在3D实时渲染中需要到后处理或者多pass操作的相关功能,就会涉及到屏幕空间像素着色计算。这里的计算性能是关注的一个要点。例如在移动端或者web端这些性能敏感的运行环境,则需要更加注意相关的性能问题。
这里以绘制轮廓线为例,请见下图:
如上图所示,这个描边(轮廓线)效果, 需要后处理完成。实现方式请见这篇文章:带遮挡效果的轮廓线(描边)在3D实时渲染中的一种实现_vily_lei的专栏-CSDN博客
实现这个后处理过程,最简单的方式是用整个viewport区域做像素计算,但是这样性能会差一些。减少像素计算的面积,是一个关键的办法。常用的方式是取这个区域的四分之一来做像素计算。
不过,通过观察发现,上图的描边实际只占据很小的区域,比四分之一小多了。在四分之一viewport区域的前提下,再用屏幕空间的矩形区域来限定计算范围,这样效率更高。这样做的话有两个小问题: 1.计算这个矩形有点麻烦。2.这个矩形还是有比较多的冗余,因为矩形是3D物体投影之后计算的。矩形用起来不爽,那3D空间的AABB 包围盒是否更好呢? 请看下图:
由上图可以看到,绿色的AABB包围盒比红色的矩形框包含的像素少很多。那就用包围盒吧,只要计算出世界坐标空间的包围盒就行。
uv只需要用 vec2 uv = gl_FragCoord.xy / vec2(textureWidth, textureHeight)计算出来就行。由于是后处理,必然用到FBO,那么(textureWidth, textureHeight)这个值实际就是FBO的尺寸,同时也是RTT的尺寸(不过要注意设备相关的 device pixel ratio 值可能造成的误操作)。
同样的道理,屏幕空间的像素着色计算,依据实际情况可以用模型本身渲染所占据的像素来计算,尽量减少冗余像素操作。
再上述描边效果中,其实还可以继续再过程中优化。例如有些渲染实体看不到,那就不需要计算相关的包围盒范围了,这样实际绘制的区域和可渲染实体直接相关,而不是和屏幕viewport区域简单的相关。例如下图需要描边计算的像素占据的区域就很小:
这么小的一块区域,再缩小到原来的四分之一,效能肯定比全屏操作高很多啦。