转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=2473

本系列的前三篇讲的都是关于Deferred Rendering的改进,本篇会专注于流水线后端的Post Process。

Post Process链

在KlayGE的渲染流水线里,不管用不用deferred,post process链是都会执行的。完整的post process链由一系列单独的post process组成,流程如下图所示。

Post Process Chain

前三个属于HDR的,经过tone mapping转成LDR之后,又经过三次post process,得到渲染结果。如果开了stereo,就会被stereoscopic的post process处理成立体的。

不管是用CUDA里的GPU kernel launch还是用图形API里的Draw Call来启动一个GPU任务,常见的改进规则都是,如果某次GPU任务不依赖于上次任务的其他单元,就应该和上次任务合并起来。这样可以省去GPU写入和读取的带宽消耗。举例来说,比如gamma correction,PS里的每个执行单元只读取了自己位置的pixel,所以就应该和FXAA合并在一起。而FXAA需要读取周围pixel的信息,所以不能和tone mapping合并。按照这个思路,理所当然FXAA、gamma correction和color grading就应该合成一个,以节省带宽。合并后的post process叫做PostToneMapping,包含了那三个操作,可以省出来半毫秒左右的时间。

立体输出

在KlayGE 4.1之前,立体渲染是通过用不同的摄像机位置把整条流水线跑两遍来完成的,性能只有一半。4.1里,王锐实现了基于post process的立体化,通过渲染一次得到的color和depth,投影到两个摄像机位置得到左右眼的结果。虽然质量上肯定不如跑两遍,但速度几乎和单眼渲染一样。在实际中,很难看出这种方法造成的artifact。有了这样的立体化,要支持多种立体输出也就是轻而易举的事情了。原先KlayGE就支持红蓝、蓝黄、绿红、水平交错、垂直交错、水平分割、垂直分割等多种被动立体的输出,并支持NV 3DVision的主动立体输出

在新的版本里,立体输出被进一步增强。除了原先支持的那些被动和主动的方法之外,还增加了OpenGL quadbuffer、AMD HD3D和DXGI 1.2 stereo的支持。

OpenGL quadbuffer

OpenGL的API一直都是支持立体输出的,只是很少有驱动实现了而已。需要修改的是在填充PIXELFORMATDESCRIPTOR的时候,dwFlags加上PFD_STEREO。然后用glDrawBuffer(GL_BACK_LEFT)和glDrawBuffer(GL_BACK_RIGHT)就分别能指定当前输出的是左眼还是右眼。这部分已经经过孙文全在NV Quadro卡上测试。

AMD HD3D

AMD在HD5xxx以上的卡就支持称为HD3D的立体输出,但配套的立体眼镜等设备都是第三方提供的。AMD专门出了一个Quad-Buffer SDK来帮助开发人员使用HD3D。不过KlayGE里没有调用那个SDK,而是直接通过AMD驱动的DLL提供的接口来访问HD3D的功能。与NV 3DVision不同的是,AMD HD3D的back buffer是上下排列的,上为左眼,下为右眼,中间还有一定的间隔。必须通过它提供的一个API来获取右眼的起始坐标,然后把左右眼的image分别放到back buffer的指定位置就可以了。由于硬件限制,这部分还没测试过。

DXGI 1.2 stereo

Win8带的DXGI 1.2的一个重大更新就是支持立体输出。由于不需要支持D3D9,DXGI的stereo直接设计成了texture array的back buffer。array index为0的是左眼,1的是右眼。比较麻烦的是,即便硬件支持立体输入,仍有可能在系统设置里关掉了,并且有可能在程序执行的过程中打开那个选项。所以需要调用RegisterStereoStatusWindow来注册一个回调函数,负责响应stereo选项的切换。不管Desktop还是Metro,都可以通过DXGI 1.2来使用stereo。这部分也还没有测试过。

总结

本系列文章到此为止,介绍了KlayGE 4.3中渲染流水线的各个改进。希望能给做类似事情的朋友提供一些参考。同时,也希望软硬件能执行stereo的朋友跟我联系,帮忙完成那两个测试。