cocos渲染引擎分析(四)-----渲染到纹理(RenderTexture)分析和渲染3D 错乱问题

渲染到纹理,顾名思义就是将原本需要渲染到系统屏幕上的图像渲染到纹理,cocos引擎也提供了渲染到纹理(Render Texture)的功能。当然,跟其他3D功能一样,它的渲染到纹理一样有自己的局限性,只能等比例渲染,场景为1280*720,你如果想要渲染全景,只能渲染1280*720的纹理上,如果创建的纹理是640*360,渲染出来的纹理就是原来场景的一半,下一章写出自己的自适应渲染。

渲染到纹理的使用代码如下:

      local size = CCDirector:getInstance():getWinSize()
      local renderTexture = cc.RenderTexture:create(size.width/2, 
      size.height/2,kCCTexture2DPixelFormat_RGBA8888)
      renderTexture:begin()//设置FBO,并将其作为一个command加入到渲染队列
      node:visit()//访问节点,生成command加入到渲染队列
      renderTexture:endToLua()//还原系统默认的缓存
	  renderTexture:saveToFile("test.png",cc.IMAGE_FORMAT_PNG, true );

首先,创建渲染到纹理,此时创建一个FBO,并创建颜色缓存和深度缓存,代码如下:

bool RenderTexture::initWithWidthAndHeight(int w, int h, Texture2D::PixelFormat format, GLuint depthStencilFormat)
{
        glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO);//获取默认FBO,初始为系统缓存,为O
        // textures must be power of two squared图片大小设置为2的N次方
        _texture = new (std::nothrow) Texture2D();
        // generate FBO创建FBO
        glGenFramebuffers(1, &_FBO);
        glBindFramebuffer(GL_FRAMEBUFFER, _FBO);
        // associate texture with FBO绑定FBO的颜色缓存到_texture纹理
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture->getName(), 0);
         //创建并绑定深度缓存
         glGenRenderbuffers(1, &_depthRenderBufffer);
         glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBufffer);
         glRenderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, (GLsizei)powW, (GLsizei)powH);
         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBufffer);
       
         if (depthStencilFormat == GL_DEPTH24_STENCIL8)
         {
          //创建并绑定模板缓存
         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBufffer);
          }
        glBindRenderbuffer(GL_RENDERBUFFER, oldRBO);
        glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO);
}

然后调用渲染到纹理的begin函数:

void RenderTexture::begin()
{  
    _groupCommand.init(_globalZOrder);
    Renderer *renderer =  Director::getInstance()->getRenderer();
    renderer->addCommand(&_groupCommand);//为加入_beginCommand准备
    renderer->pushGroup(_groupCommand.getRenderQueueID());
    _beginCommand.init(_globalZOrder);
    _beginCommand.func = CC_CALLBACK_0(RenderTexture::onBegin, this);
    Director::getInstance()->getRenderer()->addCommand(&_beginCommand);
    //加入_beginCommand到渲染队列
}
//此渲染队列的执行函数,设置新的FBO
void RenderTexture::onBegin()
{
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO);
    glBindFramebuffer(GL_FRAMEBUFFER, _FBO);
}

begin函数中设置新的FBO,然后vist需要渲染的模型,将这些渲染命令加入渲染队列,最后在end里加入恢复系统缓存的渲染命令,调用visit的场景将被渲染到_texture上.此外,使用上面LUA时,会导致渲染3D场景时有问题,需要使用下面的格式,这样创建的FBO才有深度缓存。

_renderTexture = RenderTexture::create(frameSize.width / 2, frameSize.height/2, Texture2D::PixelFormat::RGBA8888, GL_DEPTH24_STENCIL8);

 

你可能感兴趣的:(图形算法)