[cocos2dx]RenderTexture画布类

3.x的渲染机制改动比较大,改变了之前在每帧遍历所有的Node树节点时通过draw()方法中的直接渲染,而是通过生成渲染指令并将渲染指令发送到渲染队列,在每一帧结束时进行延迟渲染,这样就把游戏循环和渲染分离开来。
Cocos2d-x提供了一个RenderTexture类来支持把帧缓冲中的数据渲染到一块纹理之上,通过它可以来实现游戏截图,获取纹理上的像素信息等效果,在3.x的RenderTexutrue则是使用了GroupCommand组渲染指令,将其内部一系列的渲染指令放到一个渲染队列中,这样这个组内的渲染指令将单独使用一个渲染队列,不受其他渲染指令的影响(如渲染的优先级)。
我使用的是Cocos2d-x3.2的版本,RenderTexture类在2d/misc-nodes/CCRenderTexture.h/.cpp下。
把源码都加了注释,可以通过RenderTexture整个类的构造->初始化->绘制过程->析构,来大致了解一下RenderTextrue是如何将这缓冲的数据渲染到纹理的工作流程。

 

CCRenderTexture.h文件

#ifndef __CCRENDER_TEXTURE_H__
#define __CCRENDER_TEXTURE_H__

#include "2d/CCNode.h"
#include "2d/CCSprite.h"
#include "platform/CCImage.h"
#include "renderer/CCGroupCommand.h"
#include "renderer/CCCustomCommand.h"

NS_CC_BEGIN

class EventCustom;

class CC_DLL RenderTexture : public Node 
{
protected:
    
    //flags: whether generate new modelView and projection matrix or not
    
    //是否保持矩阵
    bool         _keepMatrix;
    Rect         _rtTextureRect;
    Rect         _fullRect;
    Rect         _fullviewPort;
    
    //帧缓冲对象
    GLuint       _FBO;
    //深度渲染缓冲对象
    GLuint       _depthRenderBufffer;
    //记录默认帧缓冲对象
    GLint        _oldFBO;
    //纹理对象
    Texture2D* _texture;
    Texture2D* _textureCopy;    // a copy of _texture
    //Image对象
    Image*     _UITextureImage;
    //客户端像素格式
    Texture2D::PixelFormat _pixelFormat;
    
    // code for "auto" update
    //清屏标识位
    GLbitfield   _clearFlags;
    //颜色缓冲区清屏色
    Color4F    _clearColor;
    //深度缓冲区清屏值
    GLclampf     _clearDepth;
    //模板缓冲区清屏值
    GLint        _clearStencil;
    //是否自动绘制
    bool         _autoDraw;

    /** The Sprite being used.
     The sprite, by default, will use the following blending function: 
GL_ONE, GL_ONE_MINUS_SRC_ALPHA.
     The blending function can be changed in runtime by calling:
     - renderTexture->getSprite()->setBlendFunc((BlendFunc){
GL_ONE, GL_ONE_MINUS_SRC_ALPHA});
     */
    //渲染到纹理时用到的精灵
    Sprite* _sprite;
    
    //组渲染指令(将下面所有的渲染指令放到同一个渲染队列中执行)
    GroupCommand _groupCommand;
    //开始时清屏渲染指令
    CustomCommand _beginWithClearCommand;
    //清理深度缓冲区渲染指令
    CustomCommand _clearDepthCommand;
    //清屏渲染指令
    CustomCommand _clearCommand;
    //开始渲染指令
    CustomCommand _beginCommand;
    //结束渲染指令
    CustomCommand _endCommand;
    //将纹理保存到文件的渲染指令
    CustomCommand _saveToFileCommand;
    
    Mat4 _oldTransMatrix, _oldProjMatrix;
    Mat4 _transformMatrix, _projectionMatrix;

};

// end of textures group
/// @}

NS_CC_END

#endif //__CCRENDER_TEXTURE_H__

CCRenderTexture.cpp文件

#include "2d/CCRenderTexture.h"

#include "base/ccUtils.h"
#include "platform/CCImage.h"
#include "platform/CCFileUtils.h"
#include "2d/CCGrid.h"
#include "base/CCEventType.h"
#include "base/CCConfiguration.h"
#include "base/CCConfiguration.h"
#include "base/CCDirector.h"
#include "base/CCEventListenerCustom.h"
#include "base/CCEventDispatcher.h"
#include "renderer/CCGLProgram.h"
#include "renderer/ccGLStateCache.h"
#include "renderer/CCTextureCache.h"
#include "renderer/CCRenderer.h"
#include "renderer/CCGroupCommand.h"
#include "renderer/CCCustomCommand.h"

#include "CCGL.h"


NS_CC_BEGIN

// implementation RenderTexture
RenderTexture::RenderTexture()
: _FBO(0)
, _depthRenderBufffer(0)
, _oldFBO(0)
, _texture(0)
, _textureCopy(0)
, _UITextureImage(nullptr)
, _pixelFormat(Texture2D::PixelFormat::RGBA8888)
, _clearFlags(0)
, _clearColor(Color4F(0,0,0,0))
, _clearDepth(0.0f)
, _clearStencil(0)
, _autoDraw(false)
, _sprite(nullptr)
, _keepMatrix(false)
, _rtTextureRect(Rect::ZERO)
, _fullRect(Rect::ZERO)
, _fullviewPort(Rect::ZERO)
{
#if CC_ENABLE_CACHE_TEXTURE_DATA
    // Listen this event to save render texture before come to background.
    // Then it can be restored after coming to foreground on Android.
    //使用事件机制(observer)来监听切到后台和切回前台事件,设置响应的回调方法
    auto toBackgroundListener = EventListenerCustom::create(EVENT_COME_TO_BACKGROUND, CC_CALLBACK_1(RenderTexture::listenToBackground, this));
    _eventDispatcher->addEventListenerWithSceneGraphPriority(toBackgroundListener, this);

    auto toForegroundListener = EventListenerCustom::create(EVENT_COME_TO_FOREGROUND, CC_CALLBACK_1(RenderTexture::listenToForeground, this));
    _eventDispatcher->addEventListenerWithSceneGraphPriority(toForegroundListener, this);
#endif
}

RenderTexture::~RenderTexture()
{
    CC_SAFE_RELEASE(_sprite);
    CC_SAFE_RELEASE(_textureCopy);
    
    //释放帧缓冲对象
    glDeleteFramebuffers(1, &_FBO);
    if (_depthRenderBufffer)
    {
        //释放深度渲染缓冲对象
        glDeleteRenderbuffers(1, &_depthRenderBufffer);
    }
    CC_SAFE_DELETE(_UITextureImage);
}

/**
 *  进入游戏后台的事件回调
 *
 *  @param event 事件对象
 */
void RenderTexture::listenToBackground(EventCustom *event)
{
    // We have not found a way to dispatch the enter background message
// before the texture data are destroyed.
    // So we disable this pair of message handler at present.
#if 0
    //使用了纹理缓存,Android Activiy切到后台时会将纹理缓存释放,切回前台时重新加载
#if CC_ENABLE_CACHE_TEXTURE_DATA
    //释放之前的渲染目标
    CC_SAFE_DELETE(_UITextureImage);
    
    // to get the rendered texture data
    //创建新的渲染目标,是一个Image对象
    _UITextureImage = newImage(false);

    if (_UITextureImage)
    {
        //获取纹理的大小
        const Size& s = _texture->getContentSizeInPixels();
        //在Android平台Activity切换到后台时,纹理将被释放,记录下切换到后台时的纹理信息,
//以便切回前台时重新创建
        VolatileTextureMgr::addDataTexture(_texture, _UITextureImage->getData(), s.width * s.height * 4, Texture2D::PixelFormat::RGBA8888, s);
        
        if ( _textureCopy )
        {
            VolatileTextureMgr::addDataTexture(_textureCopy, _UITextureImage->getData(), s.width * s.height * 4, Texture2D::PixelFormat::RGBA8888, s);
        }
    }
    else
    {
        CCLOG("Cache rendertexture failed!");
    }
    
    //释放帧缓冲对象
    glDeleteFramebuffers(1, &_FBO);
    _FBO = 0;
#endif
#endif
}

/**
 *  游戏切回前台时间回调
 *
 *  @param event 事件对象
 */
void RenderTexture::listenToForeground(EventCustom *event)
{
#if 0
#if CC_ENABLE_CACHE_TEXTURE_DATA
    // -- regenerate frame buffer object and attach the texture
    //检查帧缓冲绑定状态,返回到_obdFBO中
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO);
    //生成帧缓冲对象
    glGenFramebuffers(1, &_FBO);
    //绑定帧缓冲对象
    glBindFramebuffer(GL_FRAMEBUFFER, _FBO);
    
    //不使用抗锯齿模糊
    _texture->setAliasTexParameters();
    
    if ( _textureCopy )
    {
        _textureCopy->setAliasTexParameters();
    }
    
    //将帧缓冲数据输出到纹理
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture->getName(), 0
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值