这里说的是一些常规的人没考虑到的效果。
1、精确拾取的实现
一般普通的拾取就是AABB,再是OBB,或者是遍历一个模型的面。这三种方式都有缺陷。
现在说一种方法:就是为每个渲染物或者说是Entity附一个唯一的颜色值,然后创建一个与屏幕大小一样的RTT,把这些模型渲染到这个个RTT上,在这个渲染过程中,不需要传入模型的纹理,只需要把颜色作为输出颜色。最后通过鼠标在屏幕的XY位置就可以索引出这张纹理的颜色,根据这个颜色就知道了哪个模型被拾取。
2、勾边的实现
当一个模型被拾取时,在shader中要根据每个顶点的发线把顶点扩大一定距离,然后把勾边的颜色作为输出颜色渲染。然后还要把这次pass的cull反过来。
3、部分像素扰动。
有些特效会在场景中有扰动的效果,这种实现方法是把这个特效的范围作为一个RTT,在渲染这个RTT的过程中把像素扭曲,然后再输出。
4、LightPrePass
LightPrePass的实现与延迟渲染的实现类似延迟渲染。
首先把场景渲染到GBuffer,GBuffer由2或3张纹理组成,分别代表深度(R32F),法线(RGBA),或者材质信息。
(我的做法是:深度只用R代表,因为只能存放0,1之间的值,所以我的深度值用View空间的值再除FarPlane,到时在LightBuffer中要转回LightBuffer的计算空间)
第二步是计算点光源和太阳光的效果,生成一张纹理lightbuffer。
最后是场景渲染时要取lightbuffer纹理给模型着色。
和deferred shading的最大区别是:deferred lighting场景要渲染两次,而deferred shading只需要渲染一次
5、deferred shading和 lightprepass的区别
deferred shading和lightprepass最终的效果是差不多的,但实现起来有区别:
deferred shading整个场景至少只需要渲染一次;lightprepass要至少渲染两次。
deferred shading场景渲染一次时生成至少三张图:color,depth,normal。
最终再用这三张图来合成最后的画面。
lightprepass是第一次渲染场景只生成depth和normal。
第二次渲染场景的时候把depth和normal作为每个物件的必要纹理传进去,然后进行光照着色。
这里提出一个疑问:为什么不需要position图?因为只要有depth,在最后一步可通过viewproj矩阵的逆矩阵求出对应的世界坐标位置。