大家一定很熟悉大场景的阴影渲染容易出现的锯齿问题,我这里就不废话了。这个问题常用的解决方式是Cascaded Shadow Map(CSM),用一系列同样大小的shadow map,每个管视锥的一个范围。现在大部分引擎也都支持CSM,各种资料也很齐全,所以我这里不详细阐述原理了。想了解细节的可以看原论文,或者GPU Gems 3的文章。
CSM还是PSSM
一个常见的疑问是为什么有的叫它CSM,有的叫他PSSM(Parallel-Split Shadow Map)。实际上原论文是把它叫做PSSM,工业界实现的时候选择了个更广泛的名字CSM。从名字本身来说,只要是一系列层级关系的shadow map,就能叫CSM,而只有平行切分视锥的才叫做PSSM。换句话说,CSM是个种类,PSSM是具体方法。
PSSM
...
去年4月,Forward+刚出来的时候,我写过一篇介绍的文章。很遗憾的是,原来的paper只比较了Forward+和传统Deferred,甚至是个没怎么好好优化的Deferred。对于Tiled Deferred(TD)的比较,一直都没见到详细的。今年GDC上,终于看到了一个对Forward+和Tiled Deferred的全面性能对比,包括不同光源数,不同render target(RT)个数和是否MSAA。
别的不说,直接看结论阶段。
算法分析
首先是对Forward+和Tiled Deferred的算法分析,列出可能影响性能的地方。
RT数量对比
G-Buffer包含了多少个render target,也就是用多少带宽,对性能应系那个很大。第一轮是关闭MSAA,三角形数量较多(1.25M个),Forward+和RT数 ...
上一篇介绍了Win7的touch和手势识别状态机。在Win8中,touch API虽然还存在,但新增了一个更方便使用的Pointer API,本篇会介绍一下它的使用。
Win8桌面的Pointer
和Win7的Touch相比,Win8的Pointer成熟得多了。它分为down、up、update等多个消息,甚至还有wheel消息。也就是说,相当于鼠标消息被完全移植过来了,并加入了触点ID。所以可以和容易地把原先处理鼠标消息的经验和代码都转移到WM_POINTER的系列消息来。在功能上还胜过Touch的一点在于,Pointer不光支持触摸屏,还支持鼠标、电子笔等多种设备,并可以返回之前n帧的历史坐标。目前KlayGE并没有用那些功能,仍是把几个基本的消息转到一个经过抽象平台无关的数据结构上。
需要注 ...
上一篇提到了,KlayGE的输入系统正在大改,将要加入触摸支持。本篇将会介绍Win7的touch,以及简单的手势识别。
Win7 Touch API
实际上Win7开始就支持了多触摸,只是UI和续航没跟上,使得Win7的平板体验一般。Win7的touch分为两个层面,第一个是底层的WM_TOUCH消息,应用程序收到的是触点坐标等;第二个是高层的WM_GESTURE消息,应用程序收到的就是已经经过识别的手势了。两者只能选择一个,不能两个都收到。默认的是WM_GESTURE,如果调用了RegisterTouchWindow,系统就会不再发送WM_GESTURE,而把底层的WM_TOUCH发给应用程序。WM_GESTURE虽然简单,但缺点很明显。它受限于支持的几种手势,没有办法添加自定义的。所以这里只打算介绍WM_TOUC ...
KlayGE的输入系统从2003年完成之后,几乎就没有大的修改。谁想到在10年后的今天,输入系统几乎完全重写了。
DirectInput的缺点
原先KlayGE的输入系统只有DirectInput一个插件,基本就是简单地把DirectInput包一层,实现对键盘、鼠标和手柄的支持。在核心层,获取了设备的输入之后,经过action mapping系统,把输入转化成具体动作传给应用程序。这套系统就这么工作了很久,直到这两年触摸输入设备软硬件的发展,只支持传统输入就显得限制很大了。
即便是在键盘、鼠标上,DirectInput也不像它的名字那样direct了。根据Taking Advantage of High-Definition Mouse Movement,在系统内部,DirectInput会建立一个独立线程,读取WM_INPUT,所 ...
一年半之前,在开发KlayGE 4.0的时候,郭鹏就已经设计了一个资源载入系统,可以解决异步载入和重复载入的问题。但我只是实现了一个很粗略的异步载入。随着场景复杂度的需求越来越高,一个完善的资源载入系统也就成为必需。顺着之前的设计思路,我最近终于完成了实现。
目标
KlayGE的资源载入系统有几个设计要求:
至少支持Texture、Model、Effect、Font和Post Processor这五种资源,并能快速扩展支持新的资源。
可以选择同步或异步载入。
不重复载入资源,以减少浪费。
自动化管理,不需要手动指定资源ID,尽量不需要显式删除。
资源不需要单根继承。
异步无阻塞载入。
之前的ResLoader能支持2,4和5,部分支持1,并以很 ...
经过前两次实验,大部分C++11里有的boost组件都被替换成了C++11中相应的。剩下的还有random库和bind/function/mem_fn/ref/smart_ptr这一组。看来,到了不得不改代码的时候了。
random
在第一次实验里提到过,random虽然在boost和C++11都有,但接口不相同,所以原先我用Boost.Random实现的代码,无法直接替换成C++11的。翻了一遍boost文档,发现现在的boost其实有实现了一套名字和C++11相同的组件,于是我重写了所有用到random的地方,用和C++11兼容的代码,就解决了这个问题。好在random用得不多,改几个地方就都好了。
bind/function/mem_fn/ref/smart_ptr
这几个组件相互依赖,要么全换,要么不换。再加上牵扯面非常广,修改起来几乎都 ...
Normal map已经在实时应用中被广泛使用了,但长期以来一直有个缺陷:无法很好地做mipmap。所以在一定的视角和距离下,会出现明显的aliasing现象。在非实时渲染中,因为sampling rate很高,对于一个pixel,积分发生在计算完shading之后,也就是
[latex]spec = \sum {\left (\frac {N_{i} \cdot H}{|N_{i}|} \right )^\alpha}[/latex]
而实时渲染的sampling rate极其有限,一般只有1,积分是在建立mipmap的时候对normal做的,shading用的是积分后的normal:
[latex]spec = \left (\frac {(\sum {N_{i}}) \cdot H}{|\sum {N_{i}}|} \right )^\alpha[/latex]
很显然这两个不等价,造成了aliasing。
LEAN Mapping
I3D 2010的LEAN Mapping ...
上次实现的是Per-pixel Linked Lists方法,能做到高效地在单pass内剥离多层物体,但内存消耗不可控,而且性能和每个pixel的fragment list长度很有关系。HPG 2011上intel有个改进的方法,称为Adaptive Transparency(AT),号称能在可控的内存内做到稳定的性能和高质量的OIT。于是我打算实现一下这个方法。
方法描述
AT首先从alpha blending的方程本身下手。Alpha blending需要一个迭代的过程:
[latex]C_{n} = \alpha_{n} C_{n}+(1-\alpha_{n}) C_{n-1}[/latex]
透明渲染需要按照顺序,也就是因为这个迭代所致。AT引入了一个可见性函数
[latex]vis(z) = \prod_{0<z_{i}<z}(1-\alpha_{i})[/latex]
于是alpha blending方程就能重构 ...
2009年AMD在发布HD 5800的时候也发布了一个Order Independent Transparency(OIT)的demo,但只有介绍,没有多少可以参考的东西。GDC 2010上的OIT and GI using DX11 linked lists才给出了比较完整的算法细节。虽说这几年也有不少新的OIT算法出现,但作为具有标杆意义的OIT算法,Per-Pixel Linked Lists还是值得实现到KlayGE的开发版本中,以做对比。
算法
顾名思义,Per-Pixel Linked Lists的意思就是每个pixel上一个链表,存放属于该pixel的所有fragment。这种不均匀的数据结构对GPU来说是很要命的。
在Per-Pixel Linked Lists中,链表需要两个额外的buffer,一个称为fragments buffer,需要是屏幕尺寸的N倍,负责存放所有的fragment ...