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文件
- #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
- classEventCustom;
- classCC_DLLRenderTexture:publicNode
- {
- protected:
-
- //是否保持矩阵
- bool_keepMatrix;
- Rect_rtTextureRect;
- Rect_fullRect;
- Rect_fullviewPort;
- //帧缓冲对象
- GLuint_FBO;
- //深度渲染缓冲对象
- GLuint_depthRenderBufffer;
- //记录默认帧缓冲对象
- GLint_oldFBO;
- //纹理对象
- Texture2D*_texture;
- Texture2D*_textureCopy;
-
- Image*_UITextureImage;
- //客户端像素格式
- Texture2D::PixelFormat_pixelFormat;
- //codefor"auto"update
- //清屏标识位
- GLbitfield_clearFlags;
- //颜色缓冲区清屏色
- Color4F_clearColor;
- //深度缓冲区清屏值
- GLclampf_clearDepth;
- //模板缓冲区清屏值
- GLint_clearStencil;
- //是否自动绘制
- bool_autoDraw;
- /**TheSpritebeingused.
- Thesprite,bydefault,willusethefollowingblendingfunction:GL_ONE,GL_ONE_MINUS_SRC_ALPHA.
- Theblendingfunctioncanbechangedinruntimebycalling:
- -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;
- };
- //endoftexturesgroup
- ///@}
- NS_CC_END
- #endif//__CCRENDER_TEXTURE_H__
CCRenderTexture.cpp文件
<spanstyle="font-size:12px;color:#000000;">#include"2d/CCRenderTexture.h"
- #include"base/ccUtils.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"CCGL.h"
- NS_CC_BEGIN
- //implementationRenderTexture
- RenderTexture::RenderTexture()
- :_FBO(0)
- ,_depthRenderBufffer(0)
- ,_oldFBO(0)
- false)
- {
- #ifCC_ENABLE_CACHE_TEXTURE_DATA
- //Listenthiseventtosaverendertexturebeforecometobackground.
- //ThenitcanberestoredaftercomingtoforegroundonAndroid.
- //使用事件机制(observer)来监听切到后台和切回前台事件,设置响应的回调方法
- autotoBackgroundListener=EventListenerCustom::create(EVENT_COME_TO_BACKGROUND,CC_CALLBACK_1(RenderTexture::listenToBackground,this));
- _eventDispatcher->addEventListenerWithSceneGraPHPriority(toBackgroundListener,153); font-weight:bold; background-color:inherit">this);
- autotoForegroundListener=EventListenerCustom::create(EVENT_COME_TO_FOREGROUND,CC_CALLBACK_1(RenderTexture::listenToForeground,153); font-weight:bold; background-color:inherit">this));
- _eventDispatcher->addEventListenerWithSceneGraPHPriority(toForegroundListener,153); font-weight:bold; background-color:inherit">this);
- #endif
- }
- RenderTexture::~RenderTexture()
- CC_SAFE_RELEASE(_sprite);
- CC_SAFE_RELEASE(_textureCopy);
- //释放帧缓冲对象
- glDeleteFramebuffers(1,&_FBO);
- if(_depthRenderBufffer)
- //释放深度渲染缓冲对象
- glDeleteRenderbuffers(1,&_depthRenderBufffer);
- }
- CC_SAFE_DELETE(_UITextureImage);
- /**
- *进入游戏后台的事件回调
- *
- *@paramevent事件对象
- voidRenderTexture::listenToBackground(EventCustom*event)
- //Wehavenotfoundawaytodispatchtheenterbackgroundmessagebeforethetexturedataaredestroyed.
- //Sowedisablethispairofmessagehandleratpresent.
- #if0
- //使用了纹理缓存,AndroidActiviy切到后台时会将纹理缓存释放,切回前台时重新加载
- //释放之前的渲染目标
- //togettherenderedtexturedata
- //创建新的渲染目标,是一个Image对象
- _UITextureImage=newImage(false);
- if(_UITextureImage)
- //获取纹理的大小
- constSize&s=_texture->getContentSizeInPixels();
- //在Android平台Activity切换到后台时,纹理将被释放,记录下切换到后台时的纹理信息,以便切回前台时重新创建
- VolatileTextureMgr::addDataTexture(_texture,_UITextureImage->getData(),s.width*s.height*4,Texture2D::PixelFormat::RGBA8888,s);
- if(_textureCopy)
- VolatileTextureMgr::addDataTexture(_textureCopy,153); font-weight:bold; background-color:inherit">else
- CCLOG("CacherendertextureFailed!");
- _FBO=0;
- #endif
- /**
- *游戏切回前台时间回调
- *
- *@paramevent事件对象
- */
- voidRenderTexture::listenToForeground(EventCustom*event)
- #if0
- //--regenerateframebufferobjectandattachthetexture
- //检查帧缓冲绑定状态,返回到_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);
- //还原帧缓冲绑定状态
- glBindFramebuffer(GL_FRAMEBUFFER,_oldFBO);
- *创建RenderTexture
- *@paramw宽度
- *@paramh高度
- *@paramformat客户端像素格式
- *@returnRenderTexture对象
- RenderTexture*RenderTexture::create(intw,inth,Texture2D::PixelFormateFormat)
- RenderTexture*ret=newRenderTexture();
- if(ret&&ret->initWithWidthAndHeight(w,h,eFormat))
- ret->autorelease();
- returnret;
- CC_SAFE_DELETE(ret);
- returnnullptr;
- *@paramdepthStencilFormat深度模板缓冲格式
- *@returnRenderTexture对象
- RenderTexture*RenderTexture::create( RenderTexture*ret=newRenderTexture();
- ret->autorelease();
- returnret;
- CC_SAFE_DELETE(ret);
- returnnullptr;
- *创建RenderTexture
- *@paramw宽度
- *@paramh高度
- inth)
- *初始化RenderTexture
- *@returntrue:初始化成功false:初始化失败
- boolRenderTexture::initWithWidthAndHeight(returninitWithWidthAndHeight(w,0);
- *@returntrue:初始化成功false:初始化失败
- //RenderTextrue只支持RGB和RGBA的客户端像素格式
- CCASSERT(format!=Texture2D::PixelFormat::A8,"onlyRGBandRGBAformatsarevalidforarendertexture");
- boolret=false;
- void*data=nullptr;
- do
- _fullRect=_rtTextureRect=Rect(0,w,h);
- //Sizesize=Director::getInstance()->getWinSizeInPixels();
- //_fullviewPort=Rect(0,size.width,size.height);
- //宽度和高度乘以缩放比
- w=(int)(w*CC_CONTENT_SCALE_FACTOR());
- h=(int)(h*CC_CONTENT_SCALE_FACTOR());
- _fullviewPort=Rect(0,0); background-color:inherit">//查看帧缓冲绑定的状态,返回到oldFBO中
- //texturesmustbepoweroftwosquared
- //保存纹理的宽度和高度
- intpowW=0;
- intpowH=0;
- //检查设备是否支持纹理为非2的幂次方
- if(Configuration::getInstance()->supportsNPOT())
- //支持就用RenderTexture的大小作为纹理的大小
- powW=w;
- powH=h;
- else
- //不支持,则转换为2的幂次方
- powW=ccNextPOT(w);
- powH=ccNextPOT(h);
- //根据纹理的大小申请的字节数,每个像素4字节
- autodataLen=powW*powH*4;
- //申请内存
- data=malloc(dataLen);
- //申请失败,跳出
- CC_BREAK_IF(!data);
- //使用内存
- memset(data,dataLen);
- //客户端像素格式
- _pixelFormat=format;
- //创建一个纹理对象
- _texture=newTexture2D();
- if(_texture)
- //初始化纹理
- _texture->initWithData(data,dataLen,(Texture2D::PixelFormat)_pixelFormat,powW,powH,Size((float)w,(float)h));
- break;
- GLintoldRBO;
- glGetIntegerv(GL_RENDERBUFFER_BINDING,&oldRBO);
- if(Configuration::getInstance()->checkForGLExtension("GL_QCOM"))
- _textureCopy=newTexture2D();
- _textureCopy->initWithData(data,0); background-color:inherit">//generateFBO
- //生成帧缓冲对象(数量为1个)
- //associatetexturewithFBO
- //设置将帧缓冲区颜色数据输出到纹理
- glFramebufferTexture2D(GL_FRAMEBUFFER,0);
- //使用了深度缓冲
- if(depthStencilFormat!=0)
- //createandattachdepthbuffer
- //创建1个渲染深度缓冲对象并绑定
- glGenRenderbuffers(1,248)"> glBindRenderbuffer(GL_RENDERBUFFER,_depthRenderBufffer);
- //设置渲染缓冲对象的像素格式,尺寸
- glRenderbufferStorage(GL_RENDERBUFFER,depthStencilFormat,(GLsizei)powW,(GLsizei)powH);
- //将渲染缓冲对象绑定到当前的帧缓冲中名为GL_DEPTH_ATTACHMENT的逻辑缓冲区中,帧缓冲将修改该附加点的状态
- glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,0); background-color:inherit">//ifdepthformatistheonewithstencilpart,bindsamerenderbufferasstencilattachment
- //深度缓冲格式是24位深度,8位模版缓冲,则将渲染深度缓冲对象绑定到当前帧缓冲名为GL_STENCIL_ATTACHMENT的逻辑缓冲区中,修改附加点的状态。
- if(depthStencilFormat==GL_DEPTH24_STENCIL8)
- //checkifitworked(probablyworthdoing:))
- //帧缓冲状态必须是完成状态
- CCASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER)==GL_FRAMEBUFFER_COMPLETE,"Couldnotattachtexturetoframebuffer");
- //设置纹理不使用抗锯齿模糊
- //retained
- //将纹理绑定到精灵,将精灵绑定到RederTexture
- setSprite(Sprite::createWithTexture(_texture));
- //释放纹理
- _texture->release();
- //设置精灵Y翻转
- _sprite->setFlippedY(true);
- //设置alpha的混合模式
- _sprite->setBlendFunc(BlendFunc::ALPHA_PREMULTIPLIED);
- //还原渲染缓冲对象和帧缓冲对象
- glBindRenderbuffer(GL_RENDERBUFFER,oldRBO);
- //Diabledbydefault.
- _autoDraw=//addspriteforbackwardcompatibility
- addChild(_sprite);
- ret=true;
- }while(0);
- //释放像素所占的内存
- CC_SAFE_FREE(data);
- *设置保持矩阵
- *@paramkeepMatrix是否保持矩阵
- voidRenderTexture::setKeepMatrix(boolkeepMatrix)
- _keepMatrix=keepMatrix;
- *设置虚拟视口
- *@paramrtBegin绘制区域左下角在屏幕上的位置(绘制区域平移)
- *@paramfullRectGL的绘制区域与fullViewport一致
- *@paramfullViewportGL的绘制区域(绘制区域缩放)
- voidRenderTexture::setVirtualViewport(constVec2&rtBegin,constRect&fullRect,153); font-weight:bold; background-color:inherit">constRect&fullViewport)
- _rtTextureRect.origin.x=rtBegin.x;
- _rtTextureRect.origin.y=rtBegin.y;
- _fullRect=fullRect;
- _fullviewPort=fullViewport;
- *清屏操作
- *@paramrR通道
- *@paramgG通道
- *@parambB通道
- *@paramaAlpha通道
- voidRenderTexture::beginWithClear(floatr,87); font-weight:bold; background-color:inherit">floatg,87); font-weight:bold; background-color:inherit">floatb,87); font-weight:bold; background-color:inherit">floata)
- beginWithClear(r,g,b,a,GL_COLOR_BUFFER_BIT);
- *清屏操作
- *@paramrR通道
- *@paramgG通道
- *@parambB通道
- *@paramaAlpha通道
- *@paramdepthValue深度值
- floata,87); font-weight:bold; background-color:inherit">floatdepthValue)
- *@paramstencilValue模板值
- floatdepthValue,87); font-weight:bold; background-color:inherit">intstencilValue)
- beginWithClear(r,stencilValue,GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
- *@paramdepthValue深度值
- *@paramstencilValue模板值
- *@paramflags清屏标志位
- intstencilValue,GLbitfieldflags)
- setClearColor(Color4F(r,a));
- setClearDepth(depthValue);
- setClearStencil(stencilValue);
- setClearFlags(flags);
- //开始绘制
- this->begin();
- //clearscreen
- //初始化开始清屏渲染指令
- _beginWithClearCommand.init(_globalZOrder);
- //设置回调
- _beginWithClearCommand.func=CC_CALLBACK_0(RenderTexture::onClear,0); background-color:inherit">//添加指令到渲染队列
- Director::getInstance()->getRenderer()->addCommand(&_beginWithClearCommand);
- //TODOfindabetterwaytoclearthescreen,thereisnoneedtorebindrenderbufferthere.
- voidRenderTexture::clear(this->beginWithClear(r,a);
- this->end();
- *清理深度缓冲区
- voidRenderTexture::clearDepth(floatdepthValue)
- this->begin();
- _clearDepthCommand.init(_globalZOrder);
- _clearDepthCommand.func=CC_CALLBACK_0(RenderTexture::onClearDepth,248)"> Director::getInstance()->getRenderer()->addCommand(&_clearDepthCommand);
- this->end();
- *清理模板缓冲区
- voidRenderTexture::clearStencil(intstencilValue)
- //saveoldstencilvalue
- intstencilClearValue;
- glGetIntegerv(GL_STENCIL_CLEAR_VALUE,&stencilClearValue);
- glClearStencil(stencilValue);
- glClear(GL_STENCIL_BUFFER_BIT);
- //restoreclearcolor
- glClearStencil(stencilClearValue);
- voidRenderTexture::visit(Renderer*renderer,153); font-weight:bold; background-color:inherit">constMat4&parentTransform,uint32_tparentFlags)
- //重写父类的visit方法,不再遍历所有子元素
- //overridevisit.
- //Don'tcallvisitonitschildren
- if(!_visible)
- return;
- //处理父节点的标识
- uint32_tflags=processParentFlags(parentTransform,parentFlags);
- //为了让开发者可以将2dx2.0的项目移植到2dx3.0的版本,扔支持矩阵堆栈
- //但该方法已经废弃了,不推荐使用
- Director*director=Director::getInstance();
- //IMPORTANT:
- //Toeasethemigrationtov3.0,westillsupporttheMat4stack,
- //butitisdeprecatedandyourcodeshouldnotrelyonit
- director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
- director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW,_modelViewTransform);
- //绘制自己
- _sprite->visit(renderer,_modelViewTransform,flags);
- draw(renderer,flags);
- director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
- _orderOfArrival=0;
- *将纹理保存到磁盘的文件中(只支持png和jpg两种压缩纹理格式)
- *@paramfileName文件名
- *@paramisRGBA是否为RGBA
- *@returntrue:保存成功false:保存失败
- boolRenderTexture::saveToFile(conststd::string&filename,87); font-weight:bold; background-color:inherit">boolisRGBA)
- //将文件名转为小写
- std::stringbasename(filename);
- std::transform(basename.begin(),basename.end(),basename.begin(),::tolower);
- //包含.png,没有alpha通道
- if(basename.find(".png")!=std::string::npos)
- returnsaveToFile(filename,Image::Format::PNG,isRGBA);
- elseif(basename.find(".jpg")!=std::string::npos)
- //包含.jpg,有alpha通道
- if(isRGBA)CCLOG("RGBAisnotsupportedforJPGformat.");
- false);
- CCLOG("OnlyPNGandJPGformataresupportednow!");
- //默认将保存为JGP格式
- *将纹理保存到磁盘的文件中
- *@paramformat图片格式
- *@paramisRGBA是否为RGBA
- *@returntrue:保存成功false:保存失败
- conststd::string&fileName,Image::Formatformat,87); font-weight:bold; background-color:inherit">boolisRGBA)
- CCASSERT(format==Image::Format::JPG||format==Image::Format::PNG,
- "theimagecanonlybesavedasJPGorPNGformat");
- if(isRGBA&&format==Image::Format::JPG)CCLOG("RGBAisnotsupportedforJPGformat");
- //保存图片文件的路径
- std::stringfullpath=FileUtils::getInstance()->getWritablePath()+fileName;
- //初始化将纹理保存到文件的自定义渲染指令
- _saveToFileCommand.init(_globalZOrder);
- //设置自定义渲染指令的回调函数
- _saveToFileCommand.func=CC_CALLBACK_0(RenderTexture::onSaveToFile,153); font-weight:bold; background-color:inherit">this,fullpath,isRGBA);
- Director::getInstance()->getRenderer()->addCommand(&_saveToFileCommand);
- return*文件保存到磁盘文件的渲染回调
- *@paramfilename文件名
- voidRenderTexture::onSaveToFile(//创建一个image对象
- Image*image=newImage(if(image)
- //保存到文件中
- image->saveToFile(filename.c_str(),!isRGBA);
- //释放内存
- CC_SAFE_DELETE(image);
- /*getbufferasImage*/
- *创建一个Image对象
- *@paramfliimage是否将像素点数据上下倒置
- *@returnImage对象
- Image*RenderTexture::newImage(boolfliimage)
- //只有RGBA8888像素格式可以保存为一个Image对象
- CCASSERT(_pixelFormat==Texture2D::PixelFormat::RGBA8888,"onlyRGBA8888canbesavedasimage");
- if(nullptr==_texture)
- //获取纹理的大小
- constSize&s=_texture->getContentSizeInPixels();
- //togettheimagesizetosave
- //ifthesavingimagedomainexceedsthebuffertexturedomain,0); background-color:inherit">//itshouldbecut
- //保存Image对象的大小,如果image的大小比纹理的大,则会被裁剪
- intsavedBufferWidth=(int)s.width;
- intsavedBufferHeight=(int)s.height;
- //保存最终像素数据的数组
- GLubyte*buffer=nullptr;
- //保存临时像素数据的数组
- GLubyte*tempData=nullptr;
- Image*image=newImage();
- do
- //最终像素数据的数组申请内存
- CC_BREAK_IF(!(buffer=newGLubyte[savedBufferWidth*savedBufferHeight*4]));
- //临时像素数据的数组申请内存
- if(!(tempData=newGLubyte[savedBufferWidth*savedBufferHeight*4]))
- delete[]buffer;
- buffer=nullptr;
- //检查帧缓冲绑定状态,返回到_oldFBO帧缓冲对象中
- //绑定帧缓冲到_FBO帧缓冲对象中
- //TODOmovethistoconfigration,sowedon'tcheckiteverytime
- /*CertainQualcommAndrenogpu'swillretaindatainmemoryafteraframebufferswitchwhichcorruptstherendertothetexture.Thesolutionistocleartheframebufferbeforerenderingtothetexture.However,callingglClearhastheunintendedresultofclearingthecurrenttexture.Createatemporarytexturetoovercomethis.AttheendofRenderTexture::begin(),switchtheattachedtexturetothesecondone,callglClear,andthenswitchbacktotheoriginaltexture.Thissolutionisunnecessaryforotherdevicesastheydon'thavethesameissuewithswitchingframebuffers.
- if(Configuration::getInstance()->checkForGLExtension("GL_QCOM"))
- //--bindatemporarytexturesowecancleartherenderbufferwithoutlosingourtexture
- CHECK_GL_ERROR_DEBUG();
- glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
- //设置像素存储模式(读取到客户端)
- glPixelStorei(GL_PACK_ALIGNMENT,1);
- //将帧缓冲中的像素数据读到客户端中,保存在tempData数组中
- //像素矩形的起始位置,像素区域的大小,像素格式,数据类型,颜色数据指针
- //glReadPixels(GLintx,GLinty,GLsizeiwidth,GLsizeiheight,GLenumformat,GLenumtype,GLvoid*pixels)
- glReadPixels(0,savedBufferWidth,savedBufferHeight,GL_RGBA,GL_UNSIGNED_BYTE,tempData);
- //还原帧缓冲的绑定状态
- //是否保存到文件,保存到文件需要将像素点的数据上下颠倒
- if(fliimage)
- //togettheactualtexturedata
- //#640theimagereadfromrendertextureisdirty
- ///将pTempData从下往上拷到buffer数组中,initWithWidthAndHeight中精灵成员设置了Y镜像,所以图像是上下反
- for(inti=0;i<savedBufferHeight;++i)
- memcpy(&buffer[i*savedBufferWidth*4],
- &tempData[(savedBufferHeight-i-1)*savedBufferWidth*4],108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> savedBufferWidth*4);
- //初始化image对象
- image->initWithRawData(buffer,savedBufferWidth*savedBufferHeight*4,8);
- //初始化image对象
- image->initWithRawData(tempData,8);
- //释放保存像素数据的内存
- CC_SAFE_DELETE_ARRAY(buffer);
- CC_SAFE_DELETE_ARRAY(tempData);
- returnimage;
- *开始渲染指令的回调
- voidRenderTexture::onBegin()
- //保存变换前矩阵
- _oldProjMatrix=director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
- director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION,_projectionMatrix);
- _oldTransMatrix=director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
- //不保持矩阵,进行矩阵变换
- if(!_keepMatrix)
- director->setProjection(director->getProjection());
- #ifCC_TARGET_PLATFORM==CC_PLATFORM_WP8
- Mat4modifiedProjection=director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
- modifiedProjection=CCEGLView::sharedOpenGLView()->getReverSEOrientationMatrix()*modifiedProjection;
- director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION,modifiedProjection);
- constSize&texSize=_texture->getContentSizeInPixels();
- //Calculatetheadjustmentratiosbasedontheoldandnewprojections
- Sizesize=director->getWinSizeInPixels();
- floatwidthRatio=size.width/texSize.width;
- floatheightRatio=size.height/texSize.height;
- Mat4orthoMatrix;
- Mat4::createOrthographicOffCenter((float)-1.0/widthRatio,87); font-weight:bold; background-color:inherit">float)1.0/widthRatio,87); font-weight:bold; background-color:inherit">float)-1.0/heightRatio,87); font-weight:bold; background-color:inherit">float)1.0/heightRatio,-1,1,&orthoMatrix);
- director->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION,orthoMatrix);
- #ifCC_TARGET_PLATFORM==CC_PLATFORM_WP8
- Mat4modifiedProjection=director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
- modifiedProjection=CCEGLView::sharedOpenGLView()->getReverSEOrientationMatrix()*modifiedProjection;
- //计算视口逻辑
- //calculateviewport
- Rectviewport;
- viewport.size.width=_fullviewPort.size.width;
- viewport.size.height=_fullviewPort.size.height;
- floatviewPortRectWidthRatio=float(viewport.size.width)/_fullRect.size.width;
- floatviewPortRectHeightRatio=float(viewport.size.height)/_fullRect.size.height;
- viewport.origin.x=(_fullRect.origin.x-_rtTextureRect.origin.x)*viewPortRectWidthRatio;
- viewport.origin.y=(_fullRect.origin.y-_rtTextureRect.origin.y)*viewPortRectHeightRatio;
- //glViewport(_fullviewPort.origin.x,_fullviewPort.origin.y,(GLsizei)_fullviewPort.size.width,(GLsizei)_fullviewPort.size.height);
- glViewport(viewport.origin.x,viewport.origin.y,(GLsizei)viewport.size.width,(GLsizei)viewport.size.height);
- //Adjusttheorthographicprojectionandviewport
- //检查帧缓冲绑定状态,返回到_oldFBO中
- //绑定帧缓冲对象_FBO
- //--bindatemporarytexturesowecancleartherenderbufferwithoutlosingourtexture
- CHECK_GL_ERROR_DEBUG();
- glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
- *结束渲染指令回调
- voidRenderTexture::onEnd()
- //检查帧缓冲状态返回到_oldFBO对象
- //还原视口
- //restoreviewport
- director->setViewport();
- director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW,_oldTransMatrix);
- *清屏渲染指令回调
- voidRenderTexture::onClear()
- //saveclearcolor
- GLfloatoldClearColor[4]={0.0f};
- GLfloatoldDepthClearValue=0.0f;
- GLintoldStencilClearValue=0;
- //使用|运算符组合不同的缓冲标志位,表明需要清除的缓冲,例如glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)表示要清除颜色缓冲以及深度缓冲
- //backupandset
- if(_clearFlags&GL_COLOR_BUFFER_BIT)
- //保存颜色缓冲区的值到oldClearColor中
- glGetFloatv(GL_COLOR_CLEAR_VALUE,oldClearColor);
- //设置清屏色
- glClearColor(_clearColor.r,_clearColor.g,_clearColor.b,_clearColor.a);
- if(_clearFlags&GL_DEPTH_BUFFER_BIT)
- //保存深度值到oldDepthClearValue
- glGetFloatv(GL_DEPTH_CLEAR_VALUE,&oldDepthClearValue);
- //清理深度值
- glClearDepth(_clearDepth);
- if(_clearFlags&GL_STENCIL_BUFFER_BIT)
- //保存模板值到oldStencilClearValue
- //清理模板值
- glClearStencil(_clearStencil);
- //clear
- //清屏操作
- glClear(_clearFlags);
- //restore
- //还原保存的颜色值,深度值和模板值
- glClearColor(oldClearColor[0],oldClearColor[1],oldClearColor[2],oldClearColor[3]);
- glClearDepth(oldDepthClearValue);
- glClearStencil(oldStencilClearValue);
- *清理深度缓冲区渲染指令回调
- voidRenderTexture::onClearDepth()
- //!saveolddepthvalue
- GLfloatdepthClearValue;
- glClear(GL_DEPTH_BUFFER_BIT);
- glClearDepth(depthClearValue);
- *开始绘制
- *@paramrenderer渲染对象
- *@paramtransform变换矩阵
- *@paramflags标识
- voidRenderTexture::draw(Renderer*renderer,153); font-weight:bold; background-color:inherit">constMat4&transform,uint32_tflags)
- if(_autoDraw)
- //Beginwillcreatearendergroupusingnewrendertarget
- //开始绘制操作,创建渲染队列等
- begin();
- //初始化清屏渲染指令
- _clearCommand.init(_globalZOrder);
- _clearCommand.func=CC_CALLBACK_0(RenderTexture::onClear,0); background-color:inherit">//加入到组渲染队列中
- renderer->addCommand(&_clearCommand);
- //排序子元素,全局z优先,其次是本地z
- //!makesureallchildrenaredrawn
- sortAllChildren();
- //绘制子元素
- for(constauto&child:_children)
- if(child!=_sprite)
- child->visit(renderer,transform,0); background-color:inherit">//Endwillpopthecurrentrendergroup
- end();
- voidRenderTexture::begin()
- CCASSERT(nullptr!=director,"Directorisnullwhensetingmatrixstack");
- //在矩阵变换之前把当前矩阵保存在矩阵栈中
- director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
- _projectionMatrix=director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
- director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
- _transformMatrix=director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
- //不使用矩阵保持,进行矩阵变换
- if(!_keepMatrix)
- director->setProjection(director->getProjection());
- //纹理尺寸
- floatwidthRatio=size.width/texSize.width;
- floatheightRatio=size.height/texSize.height;
- Mat4orthoMatrix;
- Mat4::createOrthographicOffCenter(( director->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION,orthoMatrix);
- //初始化组渲染指令
- _groupCommand.init(_globalZOrder);
- //将组渲染指令加入当前组渲染队列之中
- Director::getInstance()->getRenderer()->addCommand(&_groupCommand);
- //将渲染队列Id加入到保存渲染队列Id的栈中
- Director::getInstance()->getRenderer()->pushGroup(_groupCommand.getRenderQueueID());
- //初始化开始渲染指令
- _beginCommand.init(_globalZOrder);
- _beginCommand.func=CC_CALLBACK_0(RenderTexture::onBegin,0); background-color:inherit">//将开始渲染指令加入到组渲染队列之中
- Director::getInstance()->getRenderer()->addCommand(&_beginCommand);
- *绘制结束
- voidRenderTexture::end()
- //初始化结束渲染指令
- _endCommand.init(_globalZOrder);
- //设置回调
- _endCommand.func=CC_CALLBACK_0(RenderTexture::onEnd,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Director*director=Director::getInstance();
- CCASSERT(nullptr!=director,"Directorisnullwhensetingmatrixstack");
- Renderer*renderer=director->getRenderer();
- //将指令加入渲染队列
- renderer->addCommand(&_endCommand);
- //将组渲染指令生成的渲染队列弹出渲染队列
- renderer->popGroup();
- //还原矩阵
- director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
- director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
- NS_CC_END
-
本文转载自:http://www.jb51.cc/article/p-gbobhtdc-g.html
@H_170_3
502@#ifndef __CCRENDER_TEXTURE_H__
@H_170_3
502@#define __CCRENDER_TEXTURE_H__
@H_170_3
502@#include "2d/CCNode.h"
@H_170_3
502@#include "2d/CCSprite.h"
@H_170_3
502@#include "platform/CCImage.h"
@H_170_3
502@#include "renderer/CCGroupCommand.h"
@H_170_3
502@#include "renderer/CCCustomCommand.h"
NS_CC_BEGIN
class
EventCustom;
class
CC_DLL RenderTexture :
public
Node
{
public
:
static
RenderTexture * create(
int
w,
int
h,Texture2D::PixelFormat format,GLuint depthStencilFormat);
static
RenderTexture * create(
int
w,Texture2D::PixelFormat format);
static
RenderTexture * create(
int
w,
int
h);
virtual
void
begin();
virtual
void
beginWithClear(
float
r,
float
g,
float
b,
float
a);
virtual
void
beginWithClear(
float
r,
float
a,
float
depthValue);
virtual
void
beginWithClear(
float
r,
float
depthValue,
int
stencilValue);
inline
void
endToLua(){
end();
};
virtual
void
end();
void
clear(
float
r,
float
a);
virtual
void
clearDepth(
float
depthValue);
virtual
void
clearStencil(
int
stencilValue);
Image* newImage(
bool
flipImage =
true
);
CC_DEPRECATED_ATTRIBUTE Image* newCCImage(
bool
flipImage =
true
) {
@H_
301_3997@
return
newImage(flipImage);
};
bool
saveToFile(
const
std::string& filename,
bool
isRGBA =
true
);
@H_158_
4049@
bool
saveToFile(
const
std::string& filename,Image::Format format,
bool
isRGBA =
true
);
void
listenToBackground(EventCustom *event);
void
listenToForeground(EventCustom *event);
inline
unsigned
int
getClearFlags()
const
{
return
_clearFlags;
};
inline
void
setClearFlags(unsigned
int
clearFlags) {
_clearFlags = clearFlags;
};
inline
const
Color4F& getClearColor()
const
{
return
_clearColor;
};
inline
void
setClearColor(
const
Color4F &clearColor) {
_clearColor = clearColor;
};
inline
float
getClearDepth()
const
{
return
_clearDepth;
};
inline
void
setClearDepth(
float
clearDepth) {
@H_
301_4321@
_clearDepth = clearDepth;
};
inline
int
getClearStencil()
const
{
return
_clearStencil;
};
inline
void
setClearStencil(
int
clearStencil) {
_clearStencil = clearStencil;
};
inline
bool
isAutoDraw()
const
{
return
_autoDraw;
};
inline
void
setAutoDraw(
bool
isAutoDraw) {
_autoDraw = isAutoDraw;
};
inline
Sprite* getSprite()
const
{
return
_sprite;
};
inline
void
setSprite(Sprite* sprite) {
CC_SAFE_RETAIN(sprite);
CC_SAFE_RELEASE(_sprite);
_sprite = sprite;
};
virtual
void
visit(Renderer *renderer,
const
Mat4 &parentTransform,uint32_t parentFlags) override;
virtual
void
draw(Renderer *renderer,
const
Mat4 &transform,uint32_t flags) override;
void
setKeepMatrix(
bool
keepMatrix);
void
setVirtualViewport(
const
Vec2& rtBegin,
const
Rect& fullRect,
const
Rect& fullViewport);
public
:
RenderTexture();
virtual
~RenderTexture();
bool
initWithWidthAndHeight(
int
w,Texture2D::PixelFormat format);
bool
initWithWidthAndHeight(
int
w,GLuint depthStencilFormat);
protected
:
virtual
void
beginWithClear(
float
r,
int
stencilValue,GLbitfield flags);
bool
_keepMatrix;
Rect _rtTextureRect;
Rect _fullRect;
Rect _fullviewPort;
GLuint _FBO;
GLuint _depthRenderBufffer;
GLint _oldFBO;
Texture2D* _texture;
Texture2D* _textureCopy;
Image* _UITextureImage;
Texture2D::PixelFormat _pixelFormat;
GLbitfield _clearFlags;
Color4F _clearColor;
GLclampf _clearDepth;
GLint _clearStencil;
bool
_autoDraw;
Sprite* _sprite;
GroupCommand _groupCommand;
CustomCommand _beginWithClearCommand;
CustomCommand _clearDepthCommand;
CustomCommand _clearCommand;
CustomCommand _beginCommand;
CustomCommand _endCommand;
CustomCommand _saveToFileCommand;
protected
:
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);
};
}
NS_CC_END
@H_170_3
502@#endif //__CCRENDER_TEXTURE_H__