Cocos2d-x 3.x RenderTexture渲染纹理源码分析

最近在学习3.x的源码,3.x的渲染机制改动比较大,改变了之前在每帧遍历所有的Node树节点时通过draw()方法中的直接渲染,而是通过生成渲染指令并将渲染指令发送到渲染队列,在每一帧结束时进行延迟渲染,这样就把游戏循环和渲染分离开来,2dx官方说要把渲染放在一个独立的线程来处理,按照3.x现在的架构可能不久就会实现。

Cocos2d-x提供了一个RenderTexture类来支持把帧缓冲中的数据渲染到一块纹理之上,通过它可以来实现游戏截图,获取纹理上的像素信息等效果,在3.x的RenderTexutrue则是使用了GroupCommand组渲染指令,将其内部一系列的渲染指令放到一个渲染队列中,这样这个组内的渲染指令将单独使用一个渲染队列,不受其他渲染指令的影响(如渲染的优先级)。

我使用的是Cocos2d-x3.2的版本,RenderTexture类在2d/misc-nodes/CCRenderTexture.h/.cpp下。

把源码都加了注释,可以通过RenderTexture整个类的构造->初始化->绘制过程->析构,来大致了解一下RenderTextrue是如何将这缓冲的数据渲染到纹理的工作流程。


CCRenderTexture.h文件

[cpp]  view plain copy
  1. #ifndef __CCRENDER_TEXTURE_H__  
  2. #define __CCRENDER_TEXTURE_H__  
  3.   
  4. #include "2d/CCNode.h"  
  5. #include "2d/CCSprite.h"  
  6. #include "platform/CCImage.h"  
  7. #include "renderer/CCGroupCommand.h"  
  8. #include "renderer/CCCustomCommand.h"  
  9.   
  10. NS_CC_BEGIN  
  11.   
  12. class EventCustom;  
  13.   
  14. class CC_DLL RenderTexture : public Node   
  15. {  
  16. protected:  
  17.       
  18.     //flags: whether generate new modelView and projection matrix or not  
  19.       
  20.     //是否保持矩阵  
  21.     bool         _keepMatrix;  
  22.     Rect         _rtTextureRect;  
  23.     Rect         _fullRect;  
  24.     Rect         _fullviewPort;  
  25.       
  26.     //帧缓冲对象  
  27.     GLuint       _FBO;  
  28.     //深度渲染缓冲对象  
  29.     GLuint       _depthRenderBufffer;  
  30.     //记录默认帧缓冲对象  
  31.     GLint        _oldFBO;  
  32.     //纹理对象  
  33.     Texture2D* _texture;  
  34.     Texture2D* _textureCopy;    // a copy of _texture  
  35.     //Image对象  
  36.     Image*     _UITextureImage;  
  37.     //客户端像素格式  
  38.     Texture2D::PixelFormat _pixelFormat;  
  39.       
  40.     // code for "auto" update  
  41.     //清屏标识位  
  42.     GLbitfield   _clearFlags;  
  43.     //颜色缓冲区清屏色  
  44.     Color4F    _clearColor;  
  45.     //深度缓冲区清屏值  
  46.     GLclampf     _clearDepth;  
  47.     //模板缓冲区清屏值  
  48.     GLint        _clearStencil;  
  49.     //是否自动绘制  
  50.     bool         _autoDraw;  
  51.   
  52.     /** The Sprite being used. 
  53.      The sprite, by default, will use the following blending function: GL_ONE, GL_ONE_MINUS_SRC_ALPHA. 
  54.      The blending function can be changed in runtime by calling: 
  55.      - renderTexture->getSprite()->setBlendFunc((BlendFunc){GL_ONE, GL_ONE_MINUS_SRC_ALPHA}); 
  56.      */  
  57.     //渲染到纹理时用到的精灵  
  58.     Sprite* _sprite;  
  59.       
  60.     //组渲染指令(将下面所有的渲染指令放到同一个渲染队列中执行)  
  61.     GroupCommand _groupCommand;  
  62.     //开始时清屏渲染指令  
  63.     CustomCommand _beginWithClearCommand;  
  64.     //清理深度缓冲区渲染指令  
  65.     CustomCommand _clearDepthCommand;  
  66.     //清屏渲染指令  
  67.     CustomCommand _clearCommand;  
  68.     //开始渲染指令  
  69.     CustomCommand _beginCommand;  
  70.     //结束渲染指令  
  71.     CustomCommand _endCommand;  
  72.     //将纹理保存到文件的渲染指令  
  73.     CustomCommand _saveToFileCommand;  
  74.       
  75.     Mat4 _oldTransMatrix, _oldProjMatrix;  
  76.     Mat4 _transformMatrix, _projectionMatrix;  
  77.   
  78. };  
  79.   
  80. // end of textures group  
  81. /// @}  
  82.   
  83. NS_CC_END  
  84.   
  85. #endif //__CCRENDER_TEXTURE_H__  

CCRenderTexture.cpp文件

[cpp]  view plain copy
  1. <span style="font-size:12px;color:#000000;">#include "2d/CCRenderTexture.h"  
  2.   
  3. #include "base/ccUtils.h"  
  4. #include "platform/CCImage.h"  
  5. #include "platform/CCFileUtils.h"  
  6. #include "2d/CCGrid.h"  
  7. #include "base/CCEventType.h"  
  8. #include "base/CCConfiguration.h"  
  9. #include "base/CCConfiguration.h"  
  10. #include "base/CCDirector.h"  
  11. #include "base/CCEventListenerCustom.h"  
  12. #include "base/CCEventDispatcher.h"  
  13. #include "renderer/CCGLProgram.h"  
  14. #include "renderer/ccGLStateCache.h"  
  15. #include "renderer/CCTextureCache.h"  
  16. #include "renderer/CCRenderer.h"  
  17. #include "renderer/CCGroupCommand.h"  
  18. #include "renderer/CCCustomCommand.h"  
  19.   
  20. #include "CCGL.h"  
  21.   
  22.   
  23. NS_CC_BEGIN  
  24.   
  25. // implementation RenderTexture  
  26. RenderTexture::RenderTexture()  
  27. : _FBO(0)  
  28. , _depthRenderBufffer(0)  
  29. , _oldFBO(0)  
  30. , _texture(0)  
  31. , _textureCopy(0)  
  32. , _UITextureImage(nullptr)  
  33. , _pixelFormat(Texture2D::PixelFormat::RGBA8888)  
  34. , _clearFlags(0)  
  35. , _clearColor(Color4F(0,0,0,0))  
  36. , _clearDepth(0.0f)  
  37. , _clearStencil(0)  
  38. , _autoDraw(false)  
  39. , _sprite(nullptr)  
  40. , _keepMatrix(false)  
  41. , _rtTextureRect(Rect::ZERO)  
  42. , _fullRect(Rect::ZERO)  
  43. , _fullviewPort(Rect::ZERO)  
  44. {  
  45. #if CC_ENABLE_CACHE_TEXTURE_DATA  
  46.     // Listen this event to save render texture before come to background.  
  47.     // Then it can be restored after coming to foreground on Android.  
  48.     //使用事件机制(observer)来监听切到后台和切回前台事件,设置响应的回调方法  
  49.     auto toBackgroundListener = EventListenerCustom::create(EVENT_COME_TO_BACKGROUND, CC_CALLBACK_1(RenderTexture::listenToBackground, this));  
  50.     _eventDispatcher->addEventListenerWithSceneGraphPriority(toBackgroundListener, this);  
  51.   
  52.     auto toForegroundListener = EventListenerCustom::create(EVENT_COME_TO_FOREGROUND, CC_CALLBACK_1(RenderTexture::listenToForeground, this));  
  53.     _eventDispatcher->addEventListenerWithSceneGraphPriority(toForegroundListener, this);  
  54. #endif  
  55. }  
  56.   
  57. RenderTexture::~RenderTexture()  
  58. {  
  59.     CC_SAFE_RELEASE(_sprite);  
  60.     CC_SAFE_RELEASE(_textureCopy);  
  61.       
  62.     //释放帧缓冲对象  
  63.     glDeleteFramebuffers(1, &_FBO);  
  64.     if (_depthRenderBufffer)  
  65.     {  
  66.         //释放深度渲染缓冲对象  
  67.         glDeleteRenderbuffers(1, &_depthRenderBufffer);  
  68.     }  
  69.     CC_SAFE_DELETE(_UITextureImage);  
  70. }  
  71.   
  72. /** 
  73.  *  进入游戏后台的事件回调 
  74.  * 
  75.  *  @param event 事件对象 
  76.  */  
  77. void RenderTexture::listenToBackground(EventCustom *event)  
  78. {  
  79.     // We have not found a way to dispatch the enter background message before the texture data are destroyed.  
  80.     // So we disable this pair of message handler at present.  
  81. #if 0  
  82.     //使用了纹理缓存,Android Activiy切到后台时会将纹理缓存释放,切回前台时重新加载  
  83. #if CC_ENABLE_CACHE_TEXTURE_DATA  
  84.     //释放之前的渲染目标  
  85.     CC_SAFE_DELETE(_UITextureImage);  
  86.       
  87.     // to get the rendered texture data  
  88.     //创建新的渲染目标,是一个Image对象  
  89.     _UITextureImage = newImage(false);  
  90.   
  91.     if (_UITextureImage)  
  92.     {  
  93.         //获取纹理的大小  
  94.         const Size& s = _texture->getContentSizeInPixels();  
  95.         //在Android平台Activity切换到后台时,纹理将被释放,记录下切换到后台时的纹理信息,以便切回前台时重新创建  
  96.         VolatileTextureMgr::addDataTexture(_texture, _UITextureImage->getData(), s.width * s.height * 4, Texture2D::PixelFormat::RGBA8888, s);  
  97.           
  98.         if ( _textureCopy )  
  99.         {  
  100.             VolatileTextureMgr::addDataTexture(_textureCopy, _UITextureImage->getData(), s.width * s.height * 4, Texture2D::PixelFormat::RGBA8888, s);  
  101.         }  
  102.     }  
  103.     else  
  104.     {  
  105.         CCLOG("Cache rendertexture failed!");  
  106.     }  
  107.       
  108.     //释放帧缓冲对象  
  109.     glDeleteFramebuffers(1, &_FBO);  
  110.     _FBO = 0;  
  111. #endif  
  112. #endif  
  113. }  
  114.   
  115. /** 
  116.  *  游戏切回前台时间回调 
  117.  * 
  118.  *  @param event 事件对象 
  119.  */  
  120. void RenderTexture::listenToForeground(EventCustom *event)  
  121. {  
  122. #if 0  
  123. #if CC_ENABLE_CACHE_TEXTURE_DATA  
  124.     // -- regenerate frame buffer object and attach the texture  
  125.     //检查帧缓冲绑定状态,返回到_obdFBO中  
  126.     glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO);  
  127.     //生成帧缓冲对象  
  128.     glGenFramebuffers(1, &_FBO);  
  129.     //绑定帧缓冲对象  
  130.     glBindFramebuffer(GL_FRAMEBUFFER, _FBO);  
  131.       
  132.     //不使用抗锯齿模糊  
  133.     _texture->setAliasTexParameters();  
  134.       
  135.     if ( _textureCopy )  
  136.     {  
  137.         _textureCopy->setAliasTexParameters();  
  138.     }  
  139.       
  140.     //将帧缓冲数据输出到纹理  
  141.     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture->getName(), 0);  
  142.     //还原帧缓冲绑定状态  
  143.     glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO);  
  144. #endif  
  145. #endif  
  146. }  
  147.   
  148. /** 
  149.  *  创建RenderTexture 
  150.  * 
  151.  *  @param w                    宽度 
  152.  *  @param h                    高度 
  153.  *  @param format               客户端像素格式 
  154.  * 
  155.  *  @return RenderTexture对象 
  156.  */  
  157. RenderTexture * RenderTexture::create(int w, int h, Texture2D::PixelFormat eFormat)  
  158. {  
  159.     RenderTexture *ret = new RenderTexture();  
  160.   
  161.     if(ret && ret->initWithWidthAndHeight(w, h, eFormat))  
  162.     {  
  163.         ret->autorelease();  
  164.         return ret;  
  165.     }  
  166.     CC_SAFE_DELETE(ret);  
  167.     return nullptr;  
  168. }  
  169.   
  170. /** 
  171.  *  创建RenderTexture 
  172.  * 
  173.  *  @param w                    宽度 
  174.  *  @param h                    高度 
  175.  *  @param format               客户端像素格式 
  176.  *  @param depthStencilFormat   深度模板缓冲格式 
  177.  * 
  178.  *  @return RenderTexture对象 
  179.  */  
  180. RenderTexture * RenderTexture::create(int w ,int h, Texture2D::PixelFormat eFormat, GLuint uDepthStencilFormat)  
  181. {  
  182.     RenderTexture *ret = new RenderTexture();  
  183.   
  184.     if(ret && ret->initWithWidthAndHeight(w, h, eFormat, uDepthStencilFormat))  
  185.     {  
  186.         ret->autorelease();  
  187.         return ret;  
  188.     }  
  189.     CC_SAFE_DELETE(ret);  
  190.     return nullptr;  
  191. }  
  192.   
  193. /** 
  194.  *  创建RenderTexture 
  195.  * 
  196.  *  @param w                    宽度 
  197.  *  @param h                    高度 
  198.  * 
  199.  *  @return RenderTexture对象 
  200.  */  
  201. RenderTexture * RenderTexture::create(int w, int h)  
  202. {  
  203.     RenderTexture *ret = new RenderTexture();  
  204.   
  205.     if(ret && ret->initWithWidthAndHeight(w, h, Texture2D::PixelFormat::RGBA8888, 0))  
  206.     {  
  207.         ret->autorelease();  
  208.         return ret;  
  209.     }  
  210.     CC_SAFE_DELETE(ret);  
  211.     return nullptr;  
  212. }  
  213.   
  214. /** 
  215.  *  初始化RenderTexture 
  216.  * 
  217.  *  @param w                    宽度 
  218.  *  @param h                    高度 
  219.  *  @param format               客户端像素格式 
  220.  * 
  221.  *  @return true: 初始化成功 false: 初始化失败 
  222.  */  
  223. bool RenderTexture::initWithWidthAndHeight(int w, int h, Texture2D::PixelFormat eFormat)  
  224. {  
  225.     return initWithWidthAndHeight(w, h, eFormat, 0);  
  226. }  
  227.   
  228. /** 
  229.  *  初始化RenderTexture 
  230.  * 
  231.  *  @param w                    宽度 
  232.  *  @param h                    高度 
  233.  *  @param format               客户端像素格式 
  234.  *  @param depthStencilFormat   深度模板缓冲格式 
  235.  * 
  236.  *  @return true: 初始化成功 false: 初始化失败 
  237.  */  
  238. bool RenderTexture::initWithWidthAndHeight(int w, int h, Texture2D::PixelFormat format, GLuint depthStencilFormat)  
  239. {  
  240.     //RenderTextrue只支持RGB和RGBA的客户端像素格式  
  241.     CCASSERT(format != Texture2D::PixelFormat::A8, "only RGB and RGBA formats are valid for a render texture");  
  242.   
  243.     bool ret = false;  
  244.     void *data = nullptr;  
  245.     do   
  246.     {  
  247.         _fullRect = _rtTextureRect = Rect(0,0,w,h);  
  248.         //Size size = Director::getInstance()->getWinSizeInPixels();  
  249.         //_fullviewPort = Rect(0,0,size.width,size.height);  
  250.         //宽度和高度乘以缩放比  
  251.         w = (int)(w * CC_CONTENT_SCALE_FACTOR());  
  252.         h = (int)(h * CC_CONTENT_SCALE_FACTOR());  
  253.         _fullviewPort = Rect(0,0,w,h);  
  254.           
  255.         //查看帧缓冲绑定的状态,返回到oldFBO中  
  256.         glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO);  
  257.   
  258.         // textures must be power of two squared  
  259.         //保存纹理的宽度和高度  
  260.         int powW = 0;  
  261.         int powH = 0;  
  262.           
  263.         //检查设备是否支持纹理为非2的幂次方  
  264.         if (Configuration::getInstance()->supportsNPOT())  
  265.         {  
  266.             //支持就用RenderTexture的大小作为纹理的大小  
  267.             powW = w;  
  268.             powH = h;  
  269.         }  
  270.         else  
  271.         {  
  272.             //不支持,则转换为2的幂次方  
  273.             powW = ccNextPOT(w);  
  274.             powH = ccNextPOT(h);  
  275.         }  
  276.           
  277.         //根据纹理的大小申请的字节数,每个像素4字节  
  278.         auto dataLen = powW * powH * 4;  
  279.         //申请内存  
  280.         data = malloc(dataLen);  
  281.         //申请失败,跳出  
  282.         CC_BREAK_IF(! data);  
  283.         //使用内存  
  284.         memset(data, 0, dataLen);  
  285.           
  286.         //客户端像素格式  
  287.         _pixelFormat = format;  
  288.           
  289.         //创建一个纹理对象  
  290.         _texture = new Texture2D();  
  291.         if (_texture)  
  292.         {  
  293.             //初始化纹理  
  294.             _texture->initWithData(data, dataLen, (Texture2D::PixelFormat)_pixelFormat, powW, powH, Size((float)w, (float)h));  
  295.         }  
  296.         else  
  297.         {  
  298.             break;  
  299.         }  
  300.         GLint oldRBO;  
  301.         glGetIntegerv(GL_RENDERBUFFER_BINDING, &oldRBO);  
  302.           
  303.         if (Configuration::getInstance()->checkForGLExtension("GL_QCOM"))  
  304.         {  
  305.             _textureCopy = new Texture2D();  
  306.             if (_textureCopy)  
  307.             {  
  308.                 _textureCopy->initWithData(data, dataLen, (Texture2D::PixelFormat)_pixelFormat, powW, powH, Size((float)w, (float)h));  
  309.             }  
  310.             else  
  311.             {  
  312.                 break;  
  313.             }  
  314.         }  
  315.   
  316.         // generate FBO  
  317.         //生成帧缓冲对象(数量为1个)  
  318.         glGenFramebuffers(1, &_FBO);  
  319.         //绑定帧缓冲对象  
  320.         glBindFramebuffer(GL_FRAMEBUFFER, _FBO);  
  321.   
  322.         // associate texture with FBO  
  323.         //设置将帧缓冲区颜色数据输出到纹理  
  324.         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture->getName(), 0);  
  325.   
  326.         //使用了深度缓冲  
  327.         if (depthStencilFormat != 0)  
  328.         {  
  329.             //create and attach depth buffer  
  330.             //创建1个渲染深度缓冲对象并绑定  
  331.             glGenRenderbuffers(1, &_depthRenderBufffer);  
  332.             glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBufffer);  
  333.             //设置渲染缓冲对象的像素格式,尺寸  
  334.             glRenderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, (GLsizei)powW, (GLsizei)powH);  
  335.             //将渲染缓冲对象绑定到当前的帧缓冲中名为GL_DEPTH_ATTACHMENT的逻辑缓冲区中,帧缓冲将修改该附加点的状态  
  336.             glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBufffer);  
  337.   
  338.             // if depth format is the one with stencil part, bind same render buffer as stencil attachment  
  339.             //深度缓冲格式是24位深度,8位模版缓冲,则将渲染深度缓冲对象绑定到当前帧缓冲名为GL_STENCIL_ATTACHMENT的逻辑缓冲区中,修改附加点的状态。  
  340.             if (depthStencilFormat == GL_DEPTH24_STENCIL8)  
  341.             {  
  342.                 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBufffer);  
  343.             }  
  344.         }  
  345.   
  346.         // check if it worked (probably worth doing :) )  
  347.         //帧缓冲状态必须是完成状态  
  348.         CCASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Could not attach texture to framebuffer");  
  349.           
  350.         //设置纹理不使用抗锯齿模糊  
  351.         _texture->setAliasTexParameters();  
  352.   
  353.         // retained  
  354.         //将纹理绑定到精灵,将精灵绑定到RederTexture  
  355.         setSprite(Sprite::createWithTexture(_texture));  
  356.           
  357.         //释放纹理  
  358.         _texture->release();  
  359.         //设置精灵Y翻转  
  360.         _sprite->setFlippedY(true);  
  361.         //设置alpha的混合模式  
  362.         _sprite->setBlendFunc( BlendFunc::ALPHA_PREMULTIPLIED );  
  363.           
  364.         //还原渲染缓冲对象和帧缓冲对象  
  365.         glBindRenderbuffer(GL_RENDERBUFFER, oldRBO);  
  366.         glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO);  
  367.           
  368.         // Diabled by default.  
  369.         _autoDraw = false;  
  370.           
  371.         // add sprite for backward compatibility  
  372.         addChild(_sprite);  
  373.           
  374.         ret = true;  
  375.     } while (0);  
  376.       
  377.     //释放像素所占的内存  
  378.     CC_SAFE_FREE(data);  
  379.       
  380.     return ret;  
  381. }  
  382.   
  383. /** 
  384.  *  设置保持矩阵 
  385.  * 
  386.  *  @param keepMatrix 是否保持矩阵 
  387.  */  
  388. void RenderTexture::setKeepMatrix(bool keepMatrix)  
  389. {  
  390.     _keepMatrix = keepMatrix;  
  391. }  
  392.   
  393. /** 
  394.  *  设置虚拟视口 
  395.  * 
  396.  *  @param rtBegin      绘制区域左下角在屏幕上的位置(绘制区域平移) 
  397.  *  @param fullRect     GL的绘制区域与fullViewport一致 
  398.  *  @param fullViewport GL的绘制区域(绘制区域缩放) 
  399.  */  
  400. void RenderTexture::setVirtualViewport(const Vec2& rtBegin, const Rect& fullRect, const Rect& fullViewport)  
  401. {  
  402.     _rtTextureRect.origin.x = rtBegin.x;  
  403.     _rtTextureRect.origin.y = rtBegin.y;  
  404.   
  405.     _fullRect = fullRect;  
  406.   
  407.     _fullviewPort = fullViewport;  
  408. }  
  409.   
  410. /** 
  411.  *  清屏操作 
  412.  * 
  413.  *  @param r R通道 
  414.  *  @param g G通道 
  415.  *  @param b B通道 
  416.  *  @param a Alpha通道 
  417.  */  
  418. void RenderTexture::beginWithClear(float r, float g, float b, float a)  
  419. {  
  420.     beginWithClear(r, g, b, a, 0, 0, GL_COLOR_BUFFER_BIT);  
  421. }  
  422.   
  423. /** 
  424.  *  清屏操作 
  425.  * 
  426.  *  @param r            R通道 
  427.  *  @param g            G通道 
  428.  *  @param b            B通道 
  429.  *  @param a            Alpha通道 
  430.  *  @param depthValue   深度值 
  431.  */  
  432. void RenderTexture::beginWithClear(float r, float g, float b, float a, float depthValue)  
  433. {  
  434.     beginWithClear(r, g, b, a, depthValue, 0, GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);  
  435. }  
  436.   
  437. /** 
  438.  *  清屏操作 
  439.  * 
  440.  *  @param r            R通道 
  441.  *  @param g            G通道 
  442.  *  @param b            B通道 
  443.  *  @param a            Alpha通道 
  444.  *  @param depthValue   深度值 
  445.  *  @param stencilValue 模板值 
  446.  */  
  447. void RenderTexture::beginWithClear(float r, float g, float b, float a, float depthValue, int stencilValue)  
  448. {  
  449.     beginWithClear(r, g, b, a, depthValue, stencilValue, GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);  
  450. }  
  451.   
  452. /** 
  453.  *  清屏操作 
  454.  * 
  455.  *  @param r            R通道 
  456.  *  @param g            G通道 
  457.  *  @param b            B通道 
  458.  *  @param a            Alpha通道 
  459.  *  @param depthValue   深度值 
  460.  *  @param stencilValue 模板值 
  461.  *  @param flags        清屏标志位 
  462.  */  
  463. void RenderTexture::beginWithClear(float r, float g, float b, float a, float depthValue, int stencilValue, GLbitfield flags)  
  464. {  
  465.     setClearColor(Color4F(r, g, b, a));  
  466.   
  467.     setClearDepth(depthValue);  
  468.   
  469.     setClearStencil(stencilValue);  
  470.   
  471.     setClearFlags(flags);  
  472.       
  473.     //开始绘制  
  474.     this->begin();  
  475.   
  476.     //clear screen  
  477.     //初始化开始清屏渲染指令  
  478.     _beginWithClearCommand.init(_globalZOrder);  
  479.     //设置回调  
  480.     _beginWithClearCommand.func = CC_CALLBACK_0(RenderTexture::onClear, this);  
  481.     //添加指令到渲染队列  
  482.     Director::getInstance()->getRenderer()->addCommand(&_beginWithClearCommand);  
  483. }  
  484.   
  485. //TODO find a better way to clear the screen, there is no need to rebind render buffer there.  
  486. void RenderTexture::clear(float r, float g, float b, float a)  
  487. {  
  488.     this->beginWithClear(r, g, b, a);  
  489.     this->end();  
  490. }  
  491.   
  492. /** 
  493.  *  清理深度缓冲区 
  494.  * 
  495.  *  @param depthValue 深度值 
  496.  */  
  497. void RenderTexture::clearDepth(float depthValue)  
  498. {  
  499.     setClearDepth(depthValue);  
  500.   
  501.     this->begin();  
  502.   
  503.     _clearDepthCommand.init(_globalZOrder);  
  504.     _clearDepthCommand.func = CC_CALLBACK_0(RenderTexture::onClearDepth, this);  
  505.   
  506.     Director::getInstance()->getRenderer()->addCommand(&_clearDepthCommand);  
  507.   
  508.     this->end();  
  509. }  
  510.   
  511. /** 
  512.  *  清理模板缓冲区 
  513.  * 
  514.  *  @param stencilValue 模板值 
  515.  */  
  516. void RenderTexture::clearStencil(int stencilValue)  
  517. {  
  518.     // save old stencil value  
  519.     int stencilClearValue;  
  520.     glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &stencilClearValue);  
  521.   
  522.     glClearStencil(stencilValue);  
  523.     glClear(GL_STENCIL_BUFFER_BIT);  
  524.   
  525.     // restore clear color  
  526.     glClearStencil(stencilClearValue);  
  527. }  
  528.   
  529. void RenderTexture::visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags)  
  530. {  
  531.     //重写父类的visit方法,不再遍历所有子元素  
  532.       
  533.     // override visit.  
  534.     // Don't call visit on its children  
  535.     if (!_visible)  
  536.     {  
  537.         return;  
  538.     }  
  539.       
  540.     //处理父节点的标识  
  541.     uint32_t flags = processParentFlags(parentTransform, parentFlags);  
  542.   
  543.       
  544.     //为了让开发者可以将2dx2.0的项目移植到2dx3.0的版本,扔支持矩阵堆栈  
  545.     //但该方法已经废弃了,不推荐使用  
  546.     Director* director = Director::getInstance();  
  547.     // IMPORTANT:  
  548.     // To ease the migration to v3.0, we still support the Mat4 stack,  
  549.     // but it is deprecated and your code should not rely on it  
  550.     director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);  
  551.     director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);  
  552.       
  553.     //绘制自己  
  554.     _sprite->visit(renderer, _modelViewTransform, flags);  
  555.     draw(renderer, _modelViewTransform, flags);  
  556.       
  557.     director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);  
  558.   
  559.     _orderOfArrival = 0;  
  560. }  
  561.   
  562.   
  563. /** 
  564.  *  将纹理保存到磁盘的文件中(只支持png和jpg两种压缩纹理格式) 
  565.  * 
  566.  *  @param fileName 文件名 
  567.  *  @param isRGBA   是否为RGBA 
  568.  * 
  569.  *  @return true: 保存成功 false: 保存失败 
  570.  */  
  571. bool RenderTexture::saveToFile(const std::string& filename, bool isRGBA)  
  572. {  
  573.     //将文件名转为小写  
  574.     std::string basename(filename);  
  575.     std::transform(basename.begin(), basename.end(), basename.begin(), ::tolower);  
  576.       
  577.     //包含.png,没有alpha通道  
  578.     if (basename.find(".png") != std::string::npos)  
  579.     {  
  580.         return saveToFile(filename, Image::Format::PNG, isRGBA);  
  581.     }  
  582.     else if (basename.find(".jpg") != std::string::npos)  
  583.     {  
  584.         //包含.jpg,有alpha通道  
  585.         if (isRGBA) CCLOG("RGBA is not supported for JPG format.");  
  586.         return saveToFile(filename, Image::Format::JPG, false);  
  587.     }  
  588.     else  
  589.     {  
  590.         CCLOG("Only PNG and JPG format are supported now!");  
  591.     }  
  592.       
  593.     //默认将保存为JGP格式  
  594.     return saveToFile(filename, Image::Format::JPG, false);  
  595. }  
  596.   
  597. /** 
  598.  *  将纹理保存到磁盘的文件中 
  599.  * 
  600.  *  @param fileName 文件名 
  601.  *  @param format   图片格式 
  602.  *  @param isRGBA   是否为RGBA 
  603.  * 
  604.  *  @return true: 保存成功 false: 保存失败 
  605.  */  
  606. bool RenderTexture::saveToFile(const std::string& fileName, Image::Format format, bool isRGBA)  
  607. {  
  608.     CCASSERT(format == Image::Format::JPG || format == Image::Format::PNG,  
  609.              "the image can only be saved as JPG or PNG format");  
  610.     if (isRGBA && format == Image::Format::JPG) CCLOG("RGBA is not supported for JPG format");  
  611.       
  612.     //保存图片文件的路径  
  613.     std::string fullpath = FileUtils::getInstance()->getWritablePath() + fileName;  
  614.     //初始化将纹理保存到文件的自定义渲染指令  
  615.     _saveToFileCommand.init(_globalZOrder);  
  616.     //设置自定义渲染指令的回调函数  
  617.     _saveToFileCommand.func = CC_CALLBACK_0(RenderTexture::onSaveToFile, this, fullpath, isRGBA);  
  618.       
  619.     Director::getInstance()->getRenderer()->addCommand(&_saveToFileCommand);  
  620.     return true;  
  621. }  
  622.   
  623. /** 
  624.  *  文件保存到磁盘文件的渲染回调 
  625.  * 
  626.  *  @param filename 文件名 
  627.  *  @param isRGBA   是否为RGBA 
  628.  */  
  629. void RenderTexture::onSaveToFile(const std::string& filename, bool isRGBA)  
  630. {  
  631.     //创建一个image对象  
  632.     Image *image = newImage(true);  
  633.     if (image)  
  634.     {  
  635.         //保存到文件中  
  636.         image->saveToFile(filename.c_str(), !isRGBA);  
  637.     }  
  638.       
  639.     //释放内存  
  640.     CC_SAFE_DELETE(image);  
  641. }  
  642.   
  643. /* get buffer as Image */  
  644. /** 
  645.  *  创建一个Image对象 
  646.  * 
  647.  *  @param fliimage 是否将像素点数据上下倒置 
  648.  * 
  649.  *  @return Image对象 
  650.  */  
  651. Image* RenderTexture::newImage(bool fliimage)  
  652. {  
  653.       
  654.     //只有RGBA8888像素格式可以保存为一个Image对象  
  655.     CCASSERT(_pixelFormat == Texture2D::PixelFormat::RGBA8888, "only RGBA8888 can be saved as image");  
  656.   
  657.     if (nullptr == _texture)  
  658.     {  
  659.         return nullptr;  
  660.     }  
  661.   
  662.     //获取纹理的大小  
  663.     const Size& s = _texture->getContentSizeInPixels();  
  664.   
  665.     // to get the image size to save  
  666.     //        if the saving image domain exceeds the buffer texture domain,  
  667.     //        it should be cut  
  668.     //保存Image对象的大小,如果image的大小比纹理的大,则会被裁剪  
  669.     int savedBufferWidth = (int)s.width;  
  670.     int savedBufferHeight = (int)s.height;  
  671.       
  672.     //保存最终像素数据的数组  
  673.     GLubyte *buffer = nullptr;  
  674.     //保存临时像素数据的数组  
  675.     GLubyte *tempData = nullptr;  
  676.     Image *image = new Image();  
  677.   
  678.     do  
  679.     {  
  680.         //最终像素数据的数组申请内存  
  681.         CC_BREAK_IF(! (buffer = new GLubyte[savedBufferWidth * savedBufferHeight * 4]));  
  682.           
  683.         //临时像素数据的数组申请内存  
  684.         if(! (tempData = new GLubyte[savedBufferWidth * savedBufferHeight * 4]))  
  685.         {  
  686.             delete[] buffer;  
  687.             buffer = nullptr;  
  688.             break;  
  689.         }  
  690.           
  691.         //检查帧缓冲绑定状态,返回到_oldFBO帧缓冲对象中  
  692.         glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO);  
  693.           
  694.         //绑定帧缓冲到_FBO帧缓冲对象中  
  695.         glBindFramebuffer(GL_FRAMEBUFFER, _FBO);  
  696.   
  697.         //TODO move this to configration, so we don't check it every time  
  698.         /*  Certain Qualcomm Andreno gpu's will retain data in memory after a frame buffer switch which corrupts the render to the texture. The solution is to clear the frame buffer before rendering to the texture. However, calling glClear has the unintended result of clearing the current texture. Create a temporary texture to overcome this. At the end of RenderTexture::begin(), switch the attached texture to the second one, call glClear, and then switch back to the original texture. This solution is unnecessary for other devices as they don't have the same issue with switching frame buffers. 
  699.          */  
  700.         if (Configuration::getInstance()->checkForGLExtension("GL_QCOM"))  
  701.         {  
  702.             // -- bind a temporary texture so we can clear the render buffer without losing our texture  
  703.             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _textureCopy->getName(), 0);  
  704.             CHECK_GL_ERROR_DEBUG();  
  705.             glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
  706.             glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture->getName(), 0);  
  707.         }  
  708.           
  709.         //设置像素存储模式(读取到客户端)  
  710.         glPixelStorei(GL_PACK_ALIGNMENT, 1);  
  711.           
  712.         //将帧缓冲中的像素数据读到客户端中,保存在tempData数组中  
  713.         //像素矩形的起始位置,像素区域的大小,像素格式,数据类型,颜色数据指针  
  714.         //glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)  
  715.         glReadPixels(0,0,savedBufferWidth, savedBufferHeight,GL_RGBA,GL_UNSIGNED_BYTE, tempData);  
  716.           
  717.         //还原帧缓冲的绑定状态  
  718.         glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO);  
  719.   
  720.         //是否保存到文件,保存到文件需要将像素点的数据上下颠倒  
  721.         if ( fliimage ) // -- flip is only required when saving image to file  
  722.         {  
  723.             // to get the actual texture data  
  724.             // #640 the image read from rendertexture is dirty  
  725.               
  726.             ///将pTempData从下往上拷到buffer数组中,initWithWidthAndHeight中精灵成员设置了Y镜像,所以图像是上下反  
  727.             for (int i = 0; i < savedBufferHeight; ++i)  
  728.             {  
  729.                 memcpy(&buffer[i * savedBufferWidth * 4],  
  730.                        &tempData[(savedBufferHeight - i - 1) * savedBufferWidth * 4],  
  731.                        savedBufferWidth * 4);  
  732.             }  
  733.               
  734.             //初始化image对象  
  735.             image->initWithRawData(buffer, savedBufferWidth * savedBufferHeight * 4, savedBufferWidth, savedBufferHeight, 8);  
  736.         }  
  737.         else  
  738.         {  
  739.             //初始化image对象  
  740.             image->initWithRawData(tempData, savedBufferWidth * savedBufferHeight * 4, savedBufferWidth, savedBufferHeight, 8);  
  741.         }  
  742.           
  743.     } while (0);  
  744.   
  745.     //释放保存像素数据的内存  
  746.     CC_SAFE_DELETE_ARRAY(buffer);  
  747.     CC_SAFE_DELETE_ARRAY(tempData);  
  748.   
  749.     return image;  
  750. }  
  751.   
  752. /** 
  753.  *  开始渲染指令的回调 
  754.  */  
  755. void RenderTexture::onBegin()  
  756. {  
  757.       
  758.     Director *director = Director::getInstance();  
  759.       
  760.     //保存变换前矩阵  
  761.     _oldProjMatrix = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);  
  762.     director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, _projectionMatrix);  
  763.       
  764.     _oldTransMatrix = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);  
  765.     director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _transformMatrix);  
  766.       
  767.     //不保持矩阵,进行矩阵变换  
  768.     if(!_keepMatrix)  
  769.     {  
  770.         director->setProjection(director->getProjection());  
  771.   
  772. #if CC_TARGET_PLATFORM == CC_PLATFORM_WP8  
  773.         Mat4 modifiedProjection = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);  
  774.         modifiedProjection = CCEGLView::sharedOpenGLView()->getReverseOrientationMatrix() * modifiedProjection;  
  775.         director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION,modifiedProjection);  
  776. #endif  
  777.   
  778.         const Size& texSize = _texture->getContentSizeInPixels();  
  779.           
  780.         // Calculate the adjustment ratios based on the old and new projections  
  781.         Size size = director->getWinSizeInPixels();  
  782.         float widthRatio = size.width / texSize.width;  
  783.         float heightRatio = size.height / texSize.height;  
  784.           
  785.         Mat4 orthoMatrix;  
  786.         Mat4::createOrthographicOffCenter((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1, 1, &orthoMatrix);  
  787.         director->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, orthoMatrix);  
  788.     }  
  789.     else  
  790.     {  
  791. #if CC_TARGET_PLATFORM == CC_PLATFORM_WP8  
  792.         Mat4 modifiedProjection = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);  
  793.         modifiedProjection = CCEGLView::sharedOpenGLView()->getReverseOrientationMatrix() * modifiedProjection;  
  794.         director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, modifiedProjection);  
  795. #endif  
  796.     }  
  797.       
  798.     //计算视口逻辑  
  799.     //calculate viewport  
  800.     {  
  801.         Rect viewport;  
  802.         viewport.size.width = _fullviewPort.size.width;  
  803.         viewport.size.height = _fullviewPort.size.height;  
  804.         float viewPortRectWidthRatio = float(viewport.size.width)/_fullRect.size.width;  
  805.         float viewPortRectHeightRatio = float(viewport.size.height)/_fullRect.size.height;  
  806.         viewport.origin.x = (_fullRect.origin.x - _rtTextureRect.origin.x) * viewPortRectWidthRatio;  
  807.         viewport.origin.y = (_fullRect.origin.y - _rtTextureRect.origin.y) * viewPortRectHeightRatio;  
  808.         //glViewport(_fullviewPort.origin.x, _fullviewPort.origin.y, (GLsizei)_fullviewPort.size.width, (GLsizei)_fullviewPort.size.height);  
  809.         glViewport(viewport.origin.x, viewport.origin.y, (GLsizei)viewport.size.width, (GLsizei)viewport.size.height);  
  810.     }  
  811.   
  812.     // Adjust the orthographic projection and viewport  
  813.     //检查帧缓冲绑定状态,返回到_oldFBO中  
  814.     glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO);  
  815.     //绑定帧缓冲对象_FBO  
  816.     glBindFramebuffer(GL_FRAMEBUFFER, _FBO);  
  817.   
  818.     //TODO move this to configration, so we don't check it every time  
  819.     /*  Certain Qualcomm Andreno gpu's will retain data in memory after a frame buffer switch which corrupts the render to the texture. The solution is to clear the frame buffer before rendering to the texture. However, calling glClear has the unintended result of clearing the current texture. Create a temporary texture to overcome this. At the end of RenderTexture::begin(), switch the attached texture to the second one, call glClear, and then switch back to the original texture. This solution is unnecessary for other devices as they don't have the same issue with switching frame buffers. 
  820.      */  
  821.     if (Configuration::getInstance()->checkForGLExtension("GL_QCOM"))  
  822.     {  
  823.         // -- bind a temporary texture so we can clear the render buffer without losing our texture  
  824.         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _textureCopy->getName(), 0);  
  825.         CHECK_GL_ERROR_DEBUG();  
  826.         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
  827.         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture->getName(), 0);  
  828.     }  
  829. }  
  830.   
  831. /** 
  832.  *  结束渲染指令回调 
  833.  */  
  834. void RenderTexture::onEnd()  
  835. {  
  836.     Director *director = Director::getInstance();  
  837.   
  838.     //检查帧缓冲状态返回到_oldFBO对象  
  839.     glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO);  
  840.   
  841.     //还原视口  
  842.     // restore viewport  
  843.     director->setViewport();  
  844.   
  845.     director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, _oldProjMatrix);  
  846.     director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _oldTransMatrix);  
  847.   
  848. }  
  849.   
  850. /** 
  851.  *  清屏渲染指令回调 
  852.  */  
  853. void RenderTexture::onClear()  
  854. {  
  855.     // save clear color  
  856.     GLfloat oldClearColor[4] = {0.0f};  
  857.     GLfloat oldDepthClearValue = 0.0f;  
  858.     GLint oldStencilClearValue = 0;  
  859.   
  860.     //使用 | 运算符组合不同的缓冲标志位,表明需要清除的缓冲,例如glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)表示要清除颜色缓冲以及深度缓冲  
  861.       
  862.     // backup and set  
  863.     if (_clearFlags & GL_COLOR_BUFFER_BIT)  
  864.     {  
  865.         //保存颜色缓冲区的值到oldClearColor中  
  866.         glGetFloatv(GL_COLOR_CLEAR_VALUE, oldClearColor);  
  867.         //设置清屏色  
  868.         glClearColor(_clearColor.r, _clearColor.g, _clearColor.b, _clearColor.a);  
  869.     }  
  870.   
  871.     if (_clearFlags & GL_DEPTH_BUFFER_BIT)  
  872.     {  
  873.         //保存深度值到oldDepthClearValue  
  874.         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &oldDepthClearValue);  
  875.         //清理深度值  
  876.         glClearDepth(_clearDepth);  
  877.     }  
  878.   
  879.     if (_clearFlags & GL_STENCIL_BUFFER_BIT)  
  880.     {  
  881.         //保存模板值到oldStencilClearValue  
  882.         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &oldStencilClearValue);  
  883.         //清理模板值  
  884.         glClearStencil(_clearStencil);  
  885.     }  
  886.   
  887.     // clear  
  888.     //清屏操作  
  889.     glClear(_clearFlags);  
  890.   
  891.     // restore  
  892.     //还原保存的颜色值,深度值和模板值  
  893.     if (_clearFlags & GL_COLOR_BUFFER_BIT)  
  894.     {  
  895.         glClearColor(oldClearColor[0], oldClearColor[1], oldClearColor[2], oldClearColor[3]);  
  896.     }  
  897.     if (_clearFlags & GL_DEPTH_BUFFER_BIT)  
  898.     {  
  899.         glClearDepth(oldDepthClearValue);  
  900.     }  
  901.     if (_clearFlags & GL_STENCIL_BUFFER_BIT)  
  902.     {  
  903.         glClearStencil(oldStencilClearValue);  
  904.     }  
  905. }  
  906.   
  907. /** 
  908.  *  清理深度缓冲区渲染指令回调 
  909.  */  
  910. void RenderTexture::onClearDepth()  
  911. {  
  912.     //! save old depth value  
  913.     GLfloat depthClearValue;  
  914.     glGetFloatv(GL_DEPTH_CLEAR_VALUE, &depthClearValue);  
  915.   
  916.     glClearDepth(_clearDepth);  
  917.     glClear(GL_DEPTH_BUFFER_BIT);  
  918.   
  919.     // restore clear color  
  920.     glClearDepth(depthClearValue);  
  921. }  
  922.   
  923. /** 
  924.  *  开始绘制 
  925.  * 
  926.  *  @param renderer  渲染对象 
  927.  *  @param transform 变换矩阵 
  928.  *  @param flags     标识 
  929.  */  
  930. void RenderTexture::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)  
  931. {  
  932.     if (_autoDraw)  
  933.     {  
  934.         //Begin will create a render group using new render target  
  935.         //开始绘制操作,创建渲染队列等  
  936.         begin();  
  937.   
  938.         //clear screen  
  939.         //初始化清屏渲染指令  
  940.         _clearCommand.init(_globalZOrder);  
  941.         //设置回调  
  942.         _clearCommand.func = CC_CALLBACK_0(RenderTexture::onClear, this);  
  943.         //加入到组渲染队列中  
  944.         renderer->addCommand(&_clearCommand);  
  945.           
  946.         //排序子元素,全局z优先,其次是本地z  
  947.         //! make sure all children are drawn  
  948.         sortAllChildren();  
  949.         //绘制子元素  
  950.         for(const auto &child: _children)  
  951.         {  
  952.             if (child != _sprite)  
  953.                 child->visit(renderer, transform, flags);  
  954.         }  
  955.   
  956.         //End will pop the current render group  
  957.         end();  
  958.     }  
  959. }  
  960.   
  961. /** 
  962.  *  开始绘制 
  963.  */  
  964. void RenderTexture::begin()  
  965. {  
  966.     Director* director = Director::getInstance();  
  967.     CCASSERT(nullptr != director, "Director is null when seting matrix stack");  
  968.       
  969.     //在矩阵变换之前把当前矩阵保存在矩阵栈中  
  970.     director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);  
  971.     _projectionMatrix = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);  
  972.       
  973.     director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);  
  974.     _transformMatrix = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);  
  975.       
  976.     //不使用矩阵保持,进行矩阵变换  
  977.     if(!_keepMatrix)  
  978.     {  
  979.         director->setProjection(director->getProjection());  
  980.           
  981.         //纹理尺寸  
  982.         const Size& texSize = _texture->getContentSizeInPixels();  
  983.           
  984.         // Calculate the adjustment ratios based on the old and new projections  
  985.         Size size = director->getWinSizeInPixels();  
  986.           
  987.         float widthRatio = size.width / texSize.width;  
  988.         float heightRatio = size.height / texSize.height;  
  989.           
  990.         Mat4 orthoMatrix;  
  991.         Mat4::createOrthographicOffCenter((float)-1.0 / widthRatio, (float)1.0 / widthRatio, (float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1, 1, &orthoMatrix);  
  992.         director->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, orthoMatrix);  
  993.     }  
  994.   
  995.     //初始化组渲染指令  
  996.     _groupCommand.init(_globalZOrder);  
  997.       
  998.     //将组渲染指令加入当前组渲染队列之中  
  999.     Director::getInstance()->getRenderer()->addCommand(&_groupCommand);  
  1000.     //将渲染队列Id加入到保存渲染队列Id的栈中  
  1001.     Director::getInstance()->getRenderer()->pushGroup(_groupCommand.getRenderQueueID());  
  1002.       
  1003.     //初始化开始渲染指令  
  1004.     _beginCommand.init(_globalZOrder);  
  1005.     //设置回调  
  1006.     _beginCommand.func = CC_CALLBACK_0(RenderTexture::onBegin, this);  
  1007.     //将开始渲染指令加入到组渲染队列之中  
  1008.     Director::getInstance()->getRenderer()->addCommand(&_beginCommand);  
  1009. }  
  1010.   
  1011. /** 
  1012.  *  绘制结束 
  1013.  */  
  1014. void RenderTexture::end()  
  1015. {  
  1016.     //初始化结束渲染指令  
  1017.     _endCommand.init(_globalZOrder);  
  1018.     //设置回调  
  1019.     _endCommand.func = CC_CALLBACK_0(RenderTexture::onEnd, this);  
  1020.   
  1021.     Director* director = Director::getInstance();  
  1022.     CCASSERT(nullptr != director, "Director is null when seting matrix stack");  
  1023.       
  1024.     Renderer *renderer = director->getRenderer();  
  1025.     //将指令加入渲染队列  
  1026.     renderer->addCommand(&_endCommand);  
  1027.     //将组渲染指令生成的渲染队列弹出渲染队列  
  1028.     renderer->popGroup();  
  1029.       
  1030.     //还原矩阵  
  1031.     director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);  
  1032.     director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);  
  1033.   
  1034. }  
  1035.   
  1036. NS_CC_END
  1037.   

本文转载自:http://blog.youkuaiyun.com/oktears/article/details/42197417


#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;
 
/**
  * @addtogroup textures
  * @{
 
  */
 
/**
@brief RenderTexture is a generic rendering target. To render things into it,
simply construct a render target, call begin on it, call visit on any cocos
scenes or objects to render them, and call end. For convenience, render texture
adds a sprite as it's display child with the results, so you can simply add
the render texture to your scene and treat it like any other CocosNode.
There are also functions for saving the render texture to disk in PNG or JPG format.
 
@since v0.8.1
*/
class  CC_DLL RenderTexture :  public  Node
{
 
public :
     /** initializes a RenderTexture object with width and height in Points and a pixel format( only RGB and RGBA formats are valid ) and depthStencil format*/
     static  RenderTexture * create( int  w , int  h, Texture2D::PixelFormat format, GLuint depthStencilFormat);
 
     /** creates a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid */
     static  RenderTexture * create( int  w,  int  h, Texture2D::PixelFormat format);
 
     /** creates a RenderTexture object with width and height in Points, pixel format is RGBA8888 */
     static  RenderTexture * create( int  w,  int  h);
 
     /** starts grabbing */
     virtual  void  begin();
 
     /** starts rendering to the texture while clearing the texture first.
     This is more efficient then calling -clear first and then -begin */
     virtual  void  beginWithClear( float  r,  float  g,  float  b,  float  a);
 
     /** starts rendering to the texture while clearing the texture first.
      This is more efficient then calling -clear first and then -begin */
     virtual  void  beginWithClear( float  r,  float  g,  float  b,  float  a,  float  depthValue);
 
     /** starts rendering to the texture while clearing the texture first.
      This is more efficient then calling -clear first and then -begin */
     virtual  void  beginWithClear( float  r,  float  g,  float  b,  float  a,  float  depthValue,  int  stencilValue);
 
     /** end is key word of lua, use other name to export to lua. */
     inline  void  endToLua(){
  end();
};
 
     /** ends grabbing*/
     virtual  void  end();
 
     /** clears the texture with a color */
     void  clear( float  r,  float  g,  float  b,  float  a);
 
     /** clears the texture with a specified depth value */
     virtual  void  clearDepth( float  depthValue);
 
     /** clears the texture with a specified stencil value */
     virtual  void  clearStencil( int  stencilValue);
     /* creates a new Image from with the texture's data.
        Caller is responsible for releasing it by calling delete.
      */
     
     Image* newImage( bool  flipImage =  true );
     
     CC_DEPRECATED_ATTRIBUTE Image* newCCImage( bool  flipImage =  true ) {
  return  newImage(flipImage);
};
 
     /** saves the texture into a file using JPEG format. The file will be saved in the Documents folder.
         Returns true if the operation is successful.
      */
     bool  saveToFile( const  std::string& filename,  bool  isRGBA =  true );
 
     /** saves the texture into a file. The format could be JPG or PNG. The file will be saved in the Documents folder.
         Returns true if the operation is successful.
      */
     bool  saveToFile( const  std::string& filename, Image::Format format,  bool  isRGBA =  true );
     
     /** Listen "come to background" message, and save render texture.
      It only has effect on Android.
      */
     void  listenToBackground(EventCustom *event);
     
     /** Listen "come to foreground" message and restore the frame buffer object
      It only has effect on Android.
      */
     void  listenToForeground(EventCustom *event);
     
     /** Valid flags: GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT. They can be OR'ed. Valid when "autoDraw" is true. */
     inline  unsigned  int  getClearFlags()  const  {
  return  _clearFlags;
};
     inline  void  setClearFlags(unsigned  int  clearFlags) {
  _clearFlags = clearFlags;
};
     
     /** Clear color value. Valid only when "autoDraw" is true. */
     inline  const  Color4F& getClearColor()  const  {
  return  _clearColor;
};
     inline  void  setClearColor( const  Color4F &clearColor) {
  _clearColor = clearColor;
};
     
     /** Value for clearDepth. Valid only when "autoDraw" is true. */
     inline  float  getClearDepth()  const  {
  return  _clearDepth;
};
     inline  void  setClearDepth( float  clearDepth) {
  _clearDepth = clearDepth;
};
     
     /** Value for clear Stencil. Valid only when "autoDraw" is true */
     inline  int  getClearStencil()  const  {
  return  _clearStencil;
};
     inline  void  setClearStencil( int  clearStencil) {
  _clearStencil = clearStencil;
};
     
     /** When enabled, it will render its children into the texture automatically. Disabled by default for compatiblity reasons.
      Will be enabled in the future.
      */
     inline  bool  isAutoDraw()  const  {
  return  _autoDraw;
};
     inline  void  setAutoDraw( bool  isAutoDraw) {
  _autoDraw = isAutoDraw;
};
 
     /** Gets the Sprite being used. */
     inline  Sprite* getSprite()  const  {
  return  _sprite;
};
     
     /** Sets the Sprite being used. */
     inline  void  setSprite(Sprite* sprite) {
 
         CC_SAFE_RETAIN(sprite);
         CC_SAFE_RELEASE(_sprite);
         _sprite = sprite;
     
};
     
     // Overrides
     virtual  void  visit(Renderer *renderer,  const  Mat4 &parentTransform, uint32_t parentFlags) override;
     virtual  void  draw(Renderer *renderer,  const  Mat4 &transform, uint32_t flags) override;
 
     //flag: use stack matrix computed from scene hierarchy or generate new modelView and projection matrix
     void  setKeepMatrix( bool  keepMatrix);
     /**Used for grab part of screen to a texture.
     //rtBegin: the position of renderTexture on the fullRect
     //fullRect: the total size of screen
     //fullViewport: the total viewportSize
     */
     void  setVirtualViewport( const  Vec2& rtBegin,  const  Rect& fullRect,  const  Rect& fullViewport);
 
public :
     // XXX should be procted.
     // but due to a bug in PowerVR + Android,
     // the constructor is public again
     RenderTexture();
     virtual  ~RenderTexture();
     /** initializes a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid */
     bool  initWithWidthAndHeight( int  w,  int  h, Texture2D::PixelFormat format);
     /** initializes a RenderTexture object with width and height in Points and a pixel format( only RGB and RGBA formats are valid ) and depthStencil format*/
     bool  initWithWidthAndHeight( int  w,  int  h, Texture2D::PixelFormat format, GLuint depthStencilFormat);
 
protected :
     virtual  void  beginWithClear( float  r,  float  g,  float  b,  float  a,  float  depthValue,  int  stencilValue, GLbitfield flags);
     
     //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*     _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;
protected :
     //renderer caches and callbacks
     void  onBegin();
     void  onEnd();
 
     void  onClear();
     void  onClearDepth();
 
     void  onSaveToFile( const  std::string& fileName,  bool  isRGBA =  true );
     
     Mat4 _oldTransMatrix, _oldProjMatrix;
     Mat4 _transformMatrix, _projectionMatrix;
private :
     CC_DISALLOW_COPY_AND_ASSIGN(RenderTexture);
 
 
};
 
// end of textures group
/// @
}
 
NS_CC_END
 
#endif //__CCRENDER_TEXTURE_H__

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值