最近用u3d在ios设备上做一个类似Heat distort的效果,也就是一个折射效果。
如果是一个平面(比如水平面),可以创建一个和当前摄像机同一位置和角度的摄像机,然后取到这个平面作为近剪切面,重新计算出一个视景体,然后再渲染一次场景,这样可以把平面以上的对象都拣选掉(例子可参考官方Island Demo)。
但如果不是一个平面就得把整个场景都渲染一次。
u3d可以使用两种方法来获取屏幕内容,GrabPass和RenderTexture。
GrabPass可以很方便地将BackBuffer中的内容拷贝到一张叫做_GrabTexture的贴图上。这个方法好处是使用简单,所有的工作都在shader里完成了,引擎会为你完成所有背后的工作;而且与场景复杂度无关。但也有几个问题:
1. 效率极低,因为是要从显存到内存,然后再到显存,对带宽要求很高。在配置比较高的pc上还看不到问题,但在移动设备上,这个效率是无法接受的。
2. 贴图的大小好像不能设置。反正我没找到相关资料。
3. 在安卓机上支持不了这个方法。
我用ipad mini2测试,因为其分辨率很高,所以这张贴图很大,空场景也只能跑到10多fps,此方法不可行。
剩下就只能用RenderTexture了。相比Grab方法,就是效率高,而且贴图大小可以设置,如果对折射清晰度要求不高,用一张256的就可以了,甚至更低都可以。
具体的方法:创建一个Render Texture资源,再创建一个Camera,将它的Target Texture设置为RenderTexture。当这个Camera渲染场景的时候,RenderTexture上就有整个场景图像了,然后把这张RenderTexture作为扭曲shader的一个源贴图就可以了。
这种方法虽然需要再渲染一次场景,不过因为可以使用低分辨率贴图,和屏幕渲染相比,处理的像素运算大大减少,所以效率一般都很高。如果场景渲染本身有很复杂的像素运算,可以使用Replacement Shader。
(有时想想,图像渲染其实挺粗暴的,动不动就多次渲染场景,拼的就是硬件,哈哈)