3.5beta0,RenderTexture的问题

3.5beta0的引擎

我是在一个layer上,先放一张底图A,上面放一层Sprite3D,再在最上面放一层UI
正常情况下 3D是不会显示的,会被地图和UI完全遮挡
然后通过对底图 setGlobalZOrder(-1.f),达成正确的显示层级

这时候用RenderTexture,然后layer->visit()截图,最后把RenderTexture里的图片显示出来,
发现底图没了,3D也没了

我创建了带深度缓冲区的RenderTexuture
CCRenderTexture *renderTexture = CCRenderTexture::create(DESIGN_GAMEFRAME_SIZE_X, DESIGN_GAMEFRAME_SIZE_Y, cocos2d::Texture2D::PixelFormat::RGBA8888, GL_DEPTH24_STENCIL8);
貌似也没有用

求指导。。。

在线急等,求大神指教

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,这是引擎渲染机制的设计问题。

大神出现了,多谢解答,回答的非常详细,各种机制原理都讲解清楚了,非常感谢!!!

再次感谢大神,虽然3D的问题还没试验,不过那张setGlobalZOrder(-1.f)的底图,可以正常渲染到RenderTexture了。
只要在begin和end之前手动设置RenderTexture的GlobalZOrder,就可以改变FBO打开和关闭的排序了

再次谢谢大神的详细解释

cocos引擎的renderTexture实现很杂,结构不清晰,熟悉FBO可以自己写一个!

:6: :6: :6: :6: