RenderTexture,即render to texture,简称RTT,使用的是FBO技术来实现实时的texture渲染,即texture是在GPU中实时生成,并渲染的。
在multi-pass的时候经常要使用RTT和MRT技术,包括后期的特效处理。
cocos2dx的渲染机制一直都是不完善的,时不时都会有bug,V3的渲染管道可以说是直接拷贝gameplay中示例的渲染管道,以下是3.4版本的渲染管道流程:
_queue3DOpaque
_queue3DTransparent
_queueNegZ
_queue0
_queuePosZ
总共有5种,按照上述的顺序来渲染的,即
原则1:3D的物体优先于2D的物体渲染,估计是为了保证2D的GUI永远处于最高层
原则2:不透明的如题优先于透明物体渲染。
原则3:根据camera的depth值来渲染,(上述没有体现,在scene的visit中)
问题症结所在:
RenderTexture使用Group command来渲染的,可以保证renderTexture的多个渲染管道命令组成一组,
可以理解为CPU编程的原子操作,把多个cmd绑定在一起变成一个不可被分割的原子操作。这一点是正确的处理方法;
问题出在group command的内部处理,即上述的渲染管道处理做了优先级排列,打乱了RenderTexture的内部管道流程。
RenderTexture渲染过程:
draw->begin->onclear->visit children->end
该流程管道命令:
onbegin->onclear->visit->onend:
在onbegin中发送启用FBO的管道cmd,
在onclear中发送清除GL状态的管道cmd,
在visit中遍历child,将需要渲染的child的管道cmd发送到render queue
在onend中发送恢复GL状态的管道cmd,
所以render texture的group cmd包括:
onbegin->onclear->child cmd->onend
其中除了child cmd以外的onbegin/onclear/onend均是_globalZOrder的common cmd,即是:
_queueNegZ
_queue0
_queuePosZ中的一种,优先级低于3D物体的管道命令,因此如果child cmd中存在3D物体那么永远不会被渲染在FBO中(因为FBO是在onbegin中打开的),
而是渲染到了visit render texture之前的frame buffer中了(该frame buffer默认是OS提供的FB,不受GL控制)
因此上述的渲染管道的原则是有问题的,不管如何修改,只要按照这种渲染的机制将永远都会有可能出现bug,这是引擎渲染机制的设计问题。