Unity的OnImageRender的实现原理解析
做过Unity里屏幕后期处理的童鞋应该都知道MonoBehaviour的OnRenderImage方法。这个方法可以很方便的实现屏幕后期处理,而不需要关心太多的其他的比如source的RenderTexture如何得到,destination的RenderTexture如何最终渲染到后备缓冲(backbuffer)。下面就对unity中OnRenderImage的实现原理进行解析,一起来看看吧。
很常见的OnRenderImage实现
void OnRenderImage(RenderTexture source,RenderTexture destination)
{
Graphics.Blit(source, destination, m_mat);
}
笔者之前一度有怀疑OnRenderImage的实现,认为source的RT的得到,需要在做后期之前,把backbuffer当前的帧拷贝到一个特殊的RT(source)中,实现这个功能,后面经过看unity 4.x的OnRenderImage的实现源码,以及用AdrenoProfiler实测发现,Unity对这个部分的优化还是做的不错的,没有冗余的部分。但其中还是有些不同要注意,比如 4.x和 5.x的不同,iOS平台和Android平台的不同,所以来总结一下这个部分的过程。
Unity在没有OnRenderImage的渲染过程:
首先是在 4.x 以及 5.x的iOS 里
主要是说,所有的非UI的部分都是按规则直接渲染到后备缓冲,最后,后备缓中呈现到屏幕中。
但在5.x以后的 Android里的 3D模式下(像用sprite实现的2D游戏就不会), 会先生成一个特殊的和屏幕等大的RenderTexture,所有的非UI的部分都先渲染到它上面,然后,再把RenderTexture一次性渲染到BackBuffer上,最后才呈现到到屏幕上。
5.x 后android下的这个设计,这就明显增加了一次全屏渲染的开销,官方给的说法是说android的设备兼容性差,为了统一的实现方法,索性加了这样一个RT,然后以后硬件会越来越好。。估计是说这个开销不算什么的意思。。
然后, OnRenderImage对整个渲染流程的影响是:
在4.x,以及5.x的iOS里
也会生成一个新的RenderTexture,来先把内容都渲染进来。然后做为OnRenderImage的source,用Grahpics.Blit,配合后期处理的Shader,把内容输出到destination里去,如果这个destination为null,那就是输出到Back Buffer。整个流程,渲染的量没有冗余,AB渲染到殊件的RenderTexture是自动完成的。
那在5.xAndroid下,过程就会变成:
也没有冗余的渲染,除了绕不开的那特殊RenderTexture的步骤。
对于 OnRenderImage来说,只要用了,就会在显存那生成 3张和后备缓冲等大的图。
二张是为了做重复交换RenderImage的color贴图,另一外是一张深度和蒙板缓冲。
这些都是必须的开销,然后,如果中途OnRenderImage暂停了没有调用,那这三张图会被销毁了,再OnRenderImage时会重建。。