和摄像机进行交互
为了把立体和平面渲染的内容分开,我们采用了一种用到深度缓存的方式:所有超过离摄像机位预定距离的像素的立体效果,会通过清除那个距离以外的深度缓存被放弃掉。同样的,在近处的平面投射也会从那个预订距离开始,来放弃任何已经被渲染为立体的碎片。
这个方法让我们能够在立体像素和平面像素之间有一个清晰的深度顺序:我们知道所有的立体像素离摄像机位的距离都比平面像素的距离要小。这避免了在某些方式下进行最终的场景整合阶段时,需要用到深度比较而导致的昂贵性能开销,最小化了像素着色器调用的数量。
但比起基于物体的方式,这种基于像素的分裂平面的方式,最大缺陷就是绘制调用数量不那么可控。任何穿过此分裂平面上的物体,都必须同时进行立体和平面的渲染,尽管最终没有任何一个像素会被绘制两次。哪怕对很近的远平面的视椎体剔除,用普通的视椎体剔除技巧来最小化递交到立体缓存的绘制调用数量,也会比较麻烦:一个远处的物体有着很大的包围盒,比如说环境的立方体贴图永远会通过视椎体剔除绘制;就算由于远平面距离较短,它的任何像素都没有被被显示出来,但是它的包围盒和摄像机位的视椎体产生了交叉。
为了避免这种情况,我们还增加了一种方式来让你在平面渲染引擎中可以手动标记一些物体,让它们永远不会被立体缓存进行渲染。为了知道哪个物体需要标记,我们还增加两种渲染模式:一种只显示立体缓存,而不显示包含平面远景部分的整合层;而另一种显示立体缓存的同时,加上了用来进行视锥体剔除的区分平面和立体部分的远景平面,但没有深度测试。简要来说:任何被渲染到第二张图像上而没有渲染到第一张图像上的物体,都需要一个绘制调用,但由于远平面距离较短而不会显示出来。
纯立体缓存
递交到纯立体缓存的绘制调用
在这个例子里,我们可以注意到,远景的地形由于其很大的包围球,经过了视锥体剔除的测试,但由于其距离已超过了三十英尺的深度分裂平面,而不应该被渲染出来:我们需要为它加上标记来强制只进行平面的渲染,节省宝贵的绘制调用资源。这个标记在 UE4 编辑器的物体细节/渲染区域下,名字叫“Force Mono”。
避免过度渲染
远景平面渲染的主要问题在于,它最小化像素着色器开销带来的性能开销节约,可能会被立体层和平面层之间缺乏互相遮挡给浪费掉。由于我们并不会为那些离摄像机比较近的物体进行平面渲染,那些在进行最终场景整合之后并不会被看到的远景部分,依然会在平面缓存中被着色,因为没有什么东西来遮挡它。为了避免这个问题,我们选择先渲染立体部分,再读取它们的深度缓存,并计算它们的交叉。所有在左眼和右眼摄像机被同时渲染过的像素,都会被写入远景平面的深度缓存中,来避免它们在平面摄像机中进行渲染。最终结果如下图:前面立体视觉下的大柱子,在平面缓存中被遮挡掉了,确保了后面的像素不被渲染。
纯立体缓存
经过场景整合后的平面缓存