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

前端之家收集整理的这篇文章主要介绍了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文件

  1. #ifndef__CCRENDER_TEXTURE_H__
  2. #define__CCRENDER_TEXTURE_H__
  3. #include"2d/CCNode.h"
  4. #include"2d/CCSprite.h"
  5. #include"platform/CCImage.h"
  6. #include"renderer/CCGroupCommand.h"
  7. #include"renderer/CCCustomCommand.h"
  8. NS_CC_BEGIN
  9. classEventCustom;
  10. classCC_DLLRenderTexture:publicNode
  11. {
  12. protected:
  13. //flags:whethergeneratenewmodelViewandprojectionmatrixornot
  14. //是否保持矩阵
  15. bool_keepMatrix;
  16. Rect_rtTextureRect;
  17. Rect_fullRect;
  18. Rect_fullviewPort;
  19. //帧缓冲对象
  20. GLuint_FBO;
  21. //深度渲染缓冲对象
  22. GLuint_depthRenderBufffer;
  23. //记录默认帧缓冲对象
  24. GLint_oldFBO;
  25. //纹理对象
  26. Texture2D*_texture;
  27. Texture2D*_textureCopy;//acopyof_texture
  28. //Image对象
  29. Image*_UITextureImage;
  30. //客户端像素格式
  31. Texture2D::PixelFormat_pixelFormat;
  32. //codefor"auto"update
  33. //清屏标识位
  34. GLbitfield_clearFlags;
  35. //颜色缓冲区清屏色
  36. Color4F_clearColor;
  37. //深度缓冲区清屏值
  38. GLclampf_clearDepth;
  39. //模板缓冲区清屏值
  40. GLint_clearStencil;
  41. //是否自动绘制
  42. bool_autoDraw;
  43. /**TheSpritebeingused.
  44. Thesprite,bydefault,willusethefollowingblendingfunction:GL_ONE,GL_ONE_MINUS_SRC_ALPHA.
  45. Theblendingfunctioncanbechangedinruntimebycalling:
  46. -renderTexture->getSprite()->setBlendFunc((BlendFunc){GL_ONE,GL_ONE_MINUS_SRC_ALPHA});
  47. */
  48. //渲染到纹理时用到的精灵
  49. Sprite*_sprite;
  50. //组渲染指令(将下面所有的渲染指令放到同一个渲染队列中执行)
  51. GroupCommand_groupCommand;
  52. //开始时清屏渲染指令
  53. CustomCommand_beginWithClearCommand;
  54. //清理深度缓冲区渲染指令
  55. CustomCommand_clearDepthCommand;
  56. //清屏渲染指令
  57. CustomCommand_clearCommand;
  58. //开始渲染指令
  59. CustomCommand_beginCommand;
  60. //结束渲染指令
  61. CustomCommand_endCommand;
  62. //将纹理保存到文件的渲染指令
  63. CustomCommand_saveToFileCommand;
  64. Mat4_oldTransMatrix,_oldProjMatrix;
  65. Mat4_transformMatrix,_projectionMatrix;
  66. };
  67. //endoftexturesgroup
  68. ///@}
  69. NS_CC_END
  70. #endif//__CCRENDER_TEXTURE_H__

CCRenderTexture.cpp文件

copy
    <spanstyle="font-size:12px;color:#000000;">#include"2d/CCRenderTexture.h"
  1. #include"base/ccUtils.h"
  2. #include"platform/CCFileUtils.h"
  3. #include"2d/CCGrid.h"
  4. #include"base/CCEventType.h"
  5. #include"base/CCConfiguration.h"
  6. #include"base/CCConfiguration.h"
  7. #include"base/CCDirector.h"
  8. #include"base/CCEventListenerCustom.h"
  9. #include"base/CCEventDispatcher.h"
  10. #include"renderer/CCGLProgram.h"
  11. #include"renderer/ccGLStateCache.h"
  12. #include"renderer/CCTextureCache.h"
  13. #include"renderer/CCRenderer.h"
  14. #include"CCGL.h"
  15. NS_CC_BEGIN
  16. //implementationRenderTexture
  17. RenderTexture::RenderTexture()
  18. :_FBO(0)
  19. ,_depthRenderBufffer(0)
  20. ,_oldFBO(0)
  21. false)
  22. {
  23. #ifCC_ENABLE_CACHE_TEXTURE_DATA
  24. //Listenthiseventtosaverendertexturebeforecometobackground.
  25. //ThenitcanberestoredaftercomingtoforegroundonAndroid.
  26. //使用事件机制(observer)来监听切到后台和切回前台事件,设置响应的回调方法
  27. autotoBackgroundListener=EventListenerCustom::create(EVENT_COME_TO_BACKGROUND,CC_CALLBACK_1(RenderTexture::listenToBackground,this));
  28. _eventDispatcher->addEventListenerWithSceneGraPHPriority(toBackgroundListener,153); font-weight:bold; background-color:inherit">this);
  29. autotoForegroundListener=EventListenerCustom::create(EVENT_COME_TO_FOREGROUND,CC_CALLBACK_1(RenderTexture::listenToForeground,153); font-weight:bold; background-color:inherit">this));
  30. _eventDispatcher->addEventListenerWithSceneGraPHPriority(toForegroundListener,153); font-weight:bold; background-color:inherit">this);
  31. #endif
  32. }
  33. RenderTexture::~RenderTexture()
  34. CC_SAFE_RELEASE(_sprite);
  35. CC_SAFE_RELEASE(_textureCopy);
  36. //释放帧缓冲对象
  37. glDeleteFramebuffers(1,&_FBO);
  38. if(_depthRenderBufffer)
  39. //释放深度渲染缓冲对象
  40. glDeleteRenderbuffers(1,&_depthRenderBufffer);
  41. }
  42. CC_SAFE_DELETE(_UITextureImage);
  43. /**
  44. *进入游戏后台的事件回调
  45. *
  46. *@paramevent事件对象
  47. voidRenderTexture::listenToBackground(EventCustom*event)
  48. //Wehavenotfoundawaytodispatchtheenterbackgroundmessagebeforethetexturedataaredestroyed.
  49. //Sowedisablethispairofmessagehandleratpresent.
  50. #if0
  51. //使用了纹理缓存,AndroidActiviy切到后台时会将纹理缓存释放,切回前台时重新加载
  52. //释放之前的渲染目标
  53. //togettherenderedtexturedata
  54. //创建新的渲染目标,是一个Image对象
  55. _UITextureImage=newImage(false);
  56. if(_UITextureImage)
  57. //获取纹理的大小
  58. constSize&s=_texture->getContentSizeInPixels();
  59. //在Android平台Activity切换到后台时,纹理将被释放,记录下切换到后台时的纹理信息,以便切回前台时重新创建
  60. VolatileTextureMgr::addDataTexture(_texture,_UITextureImage->getData(),s.width*s.height*4,Texture2D::PixelFormat::RGBA8888,s);
  61. if(_textureCopy)
  62. VolatileTextureMgr::addDataTexture(_textureCopy,153); font-weight:bold; background-color:inherit">else
  63. CCLOG("CacherendertextureFailed!");
  64. _FBO=0;
  65. #endif
  66. /**
  67. *游戏切回前台时间回调
  68. *
  69. *@paramevent事件对象
  70. */
  71. voidRenderTexture::listenToForeground(EventCustom*event)
  72. #if0
  73. //--regenerateframebufferobjectandattachthetexture
  74. //检查帧缓冲绑定状态,返回到_obdFBO中
  75. glGetIntegerv(GL_FRAMEBUFFER_BINDING,&_oldFBO);
  76. //生成帧缓冲对象
  77. glGenFramebuffers(1,&_FBO);
  78. //绑定帧缓冲对象
  79. glBindFramebuffer(GL_FRAMEBUFFER,_FBO);
  80. //不使用抗锯齿模糊
  81. _texture->setAliasTexParameters();
  82. if(_textureCopy)
  83. _textureCopy->setAliasTexParameters();
  84. //将帧缓冲数据输出到纹理
  85. glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,_texture->getName(),0);
  86. //还原帧缓冲绑定状态
  87. glBindFramebuffer(GL_FRAMEBUFFER,_oldFBO);
  88. *创建RenderTexture
  89. *@paramw宽度
  90. *@paramh高度
  91. *@paramformat客户端像素格式
  92. *@returnRenderTexture对象
  93. RenderTexture*RenderTexture::create(intw,inth,Texture2D::PixelFormateFormat)
  94. RenderTexture*ret=newRenderTexture();
  95. if(ret&&ret->initWithWidthAndHeight(w,h,eFormat))
  96. ret->autorelease();
  97. returnret;
  98. CC_SAFE_DELETE(ret);
  99. returnnullptr;
  100. *@paramdepthStencilFormat深度模板缓冲格式
  101. *@returnRenderTexture对象
  102. RenderTexture*RenderTexture::create( RenderTexture*ret=newRenderTexture();
  103. ret->autorelease();
  104. returnret;
  105. CC_SAFE_DELETE(ret);
  106. returnnullptr;
  107. *创建RenderTexture
  108. *@paramw宽度
  109. *@paramh高度
  110. inth)
  111. *初始化RenderTexture
  112. *@returntrue:初始化成功false:初始化失败
  113. boolRenderTexture::initWithWidthAndHeight(returninitWithWidthAndHeight(w,0);
  114. *@returntrue:初始化成功false:初始化失败
  115. //RenderTextrue只支持RGB和RGBA的客户端像素格式
  116. CCASSERT(format!=Texture2D::PixelFormat::A8,"onlyRGBandRGBAformatsarevalidforarendertexture");
  117. boolret=false;
  118. void*data=nullptr;
  119. do
  120. _fullRect=_rtTextureRect=Rect(0,w,h);
  121. //Sizesize=Director::getInstance()->getWinSizeInPixels();
  122. //_fullviewPort=Rect(0,size.width,size.height);
  123. //宽度和高度乘以缩放比
  124. w=(int)(w*CC_CONTENT_SCALE_FACTOR());
  125. h=(int)(h*CC_CONTENT_SCALE_FACTOR());
  126. _fullviewPort=Rect(0,0); background-color:inherit">//查看帧缓冲绑定的状态,返回到oldFBO中
  127. //texturesmustbepoweroftwosquared
  128. //保存纹理的宽度和高度
  129. intpowW=0;
  130. intpowH=0;
  131. //检查设备是否支持纹理为非2的幂次方
  132. if(Configuration::getInstance()->supportsNPOT())
  133. //支持就用RenderTexture的大小作为纹理的大小
  134. powW=w;
  135. powH=h;
  136. else
  137. //不支持,则转换为2的幂次方
  138. powW=ccNextPOT(w);
  139. powH=ccNextPOT(h);
  140. //根据纹理的大小申请的字节数,每个像素4字节
  141. autodataLen=powW*powH*4;
  142. //申请内存
  143. data=malloc(dataLen);
  144. //申请失败,跳出
  145. CC_BREAK_IF(!data);
  146. //使用内存
  147. memset(data,dataLen);
  148. //客户端像素格式
  149. _pixelFormat=format;
  150. //创建一个纹理对象
  151. _texture=newTexture2D();
  152. if(_texture)
  153. //初始化纹理
  154. _texture->initWithData(data,dataLen,(Texture2D::PixelFormat)_pixelFormat,powW,powH,Size((float)w,(float)h));
  155. break;
  156. GLintoldRBO;
  157. glGetIntegerv(GL_RENDERBUFFER_BINDING,&oldRBO);
  158. if(Configuration::getInstance()->checkForGLExtension("GL_QCOM"))
  159. _textureCopy=newTexture2D();
  160. _textureCopy->initWithData(data,0); background-color:inherit">//generateFBO
  161. //生成帧缓冲对象(数量为1个)
  162. //associatetexturewithFBO
  163. //设置将帧缓冲区颜色数据输出到纹理
  164. glFramebufferTexture2D(GL_FRAMEBUFFER,0);
  165. //使用了深度缓冲
  166. if(depthStencilFormat!=0)
  167. //createandattachdepthbuffer
  168. //创建1个渲染深度缓冲对象并绑定
  169. glGenRenderbuffers(1,248)"> glBindRenderbuffer(GL_RENDERBUFFER,_depthRenderBufffer);
  170. //设置渲染缓冲对象的像素格式,尺寸
  171. glRenderbufferStorage(GL_RENDERBUFFER,depthStencilFormat,(GLsizei)powW,(GLsizei)powH);
  172. //将渲染缓冲对象绑定到当前的帧缓冲中名为GL_DEPTH_ATTACHMENT的逻辑缓冲区中,帧缓冲将修改该附加点的状态
  173. glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,0); background-color:inherit">//ifdepthformatistheonewithstencilpart,bindsamerenderbufferasstencilattachment
  174. //深度缓冲格式是24位深度,8位模版缓冲,则将渲染深度缓冲对象绑定到当前帧缓冲名为GL_STENCIL_ATTACHMENT的逻辑缓冲区中,修改附加点的状态。
  175. if(depthStencilFormat==GL_DEPTH24_STENCIL8)
  176. //checkifitworked(probablyworthdoing:))
  177. //帧缓冲状态必须是完成状态
  178. CCASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER)==GL_FRAMEBUFFER_COMPLETE,"Couldnotattachtexturetoframebuffer");
  179. //设置纹理不使用抗锯齿模糊
  180. //retained
  181. //将纹理绑定到精灵,将精灵绑定到RederTexture
  182. setSprite(Sprite::createWithTexture(_texture));
  183. //释放纹理
  184. _texture->release();
  185. //设置精灵Y翻转
  186. _sprite->setFlippedY(true);
  187. //设置alpha的混合模式
  188. _sprite->setBlendFunc(BlendFunc::ALPHA_PREMULTIPLIED);
  189. //还原渲染缓冲对象和帧缓冲对象
  190. glBindRenderbuffer(GL_RENDERBUFFER,oldRBO);
  191. //Diabledbydefault.
  192. _autoDraw=//addspriteforbackwardcompatibility
  193. addChild(_sprite);
  194. ret=true;
  195. }while(0);
  196. //释放像素所占的内存
  197. CC_SAFE_FREE(data);
  198. *设置保持矩阵
  199. *@paramkeepMatrix是否保持矩阵
  200. voidRenderTexture::setKeepMatrix(boolkeepMatrix)
  201. _keepMatrix=keepMatrix;
  202. *设置虚拟视口
  203. *@paramrtBegin绘制区域左下角在屏幕上的位置(绘制区域平移)
  204. *@paramfullRectGL的绘制区域与fullViewport一致
  205. *@paramfullViewportGL的绘制区域(绘制区域缩放)
  206. voidRenderTexture::setVirtualViewport(constVec2&rtBegin,constRect&fullRect,153); font-weight:bold; background-color:inherit">constRect&fullViewport)
  207. _rtTextureRect.origin.x=rtBegin.x;
  208. _rtTextureRect.origin.y=rtBegin.y;
  209. _fullRect=fullRect;
  210. _fullviewPort=fullViewport;
  211. *清屏操作
  212. *@paramrR通道
  213. *@paramgG通道
  214. *@parambB通道
  215. *@paramaAlpha通道
  216. 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)
  217. beginWithClear(r,g,b,a,GL_COLOR_BUFFER_BIT);
  218. *清屏操作
  219. *@paramrR通道
  220. *@paramgG通道
  221. *@parambB通道
  222. *@paramaAlpha通道
  223. *@paramdepthValue深度值
  224. floata,87); font-weight:bold; background-color:inherit">floatdepthValue)
  225. *@paramstencilValue模板值
  226. floatdepthValue,87); font-weight:bold; background-color:inherit">intstencilValue)
  227. beginWithClear(r,stencilValue,GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
  228. *@paramdepthValue深度值
  229. *@paramstencilValue模板值
  230. *@paramflags清屏标志位
  231. intstencilValue,GLbitfieldflags)
  232. setClearColor(Color4F(r,a));
  233. setClearDepth(depthValue);
  234. setClearStencil(stencilValue);
  235. setClearFlags(flags);
  236. //开始绘制
  237. this->begin();
  238. //clearscreen
  239. //初始化开始清屏渲染指令
  240. _beginWithClearCommand.init(_globalZOrder);
  241. //设置回调
  242. _beginWithClearCommand.func=CC_CALLBACK_0(RenderTexture::onClear,0); background-color:inherit">//添加指令到渲染队列
  243. Director::getInstance()->getRenderer()->addCommand(&_beginWithClearCommand);
  244. //TODOfindabetterwaytoclearthescreen,thereisnoneedtorebindrenderbufferthere.
  245. voidRenderTexture::clear(this->beginWithClear(r,a);
  246. this->end();
  247. *清理深度缓冲区
  248. voidRenderTexture::clearDepth(floatdepthValue)
  249. this->begin();
  250. _clearDepthCommand.init(_globalZOrder);
  251. _clearDepthCommand.func=CC_CALLBACK_0(RenderTexture::onClearDepth,248)"> Director::getInstance()->getRenderer()->addCommand(&_clearDepthCommand);
  252. this->end();
  253. *清理模板缓冲区
  254. voidRenderTexture::clearStencil(intstencilValue)
  255. //saveoldstencilvalue
  256. intstencilClearValue;
  257. glGetIntegerv(GL_STENCIL_CLEAR_VALUE,&stencilClearValue);
  258. glClearStencil(stencilValue);
  259. glClear(GL_STENCIL_BUFFER_BIT);
  260. //restoreclearcolor
  261. glClearStencil(stencilClearValue);
  262. voidRenderTexture::visit(Renderer*renderer,153); font-weight:bold; background-color:inherit">constMat4&parentTransform,uint32_tparentFlags)
  263. //重写父类的visit方法,不再遍历所有子元素
  264. //overridevisit.
  265. //Don'tcallvisitonitschildren
  266. if(!_visible)
  267. return;
  268. //处理父节点的标识
  269. uint32_tflags=processParentFlags(parentTransform,parentFlags);
  270. //为了让开发者可以将2dx2.0的项目移植到2dx3.0的版本,扔支持矩阵堆栈
  271. //但该方法已经废弃了,不推荐使用
  272. Director*director=Director::getInstance();
  273. //IMPORTANT:
  274. //Toeasethemigrationtov3.0,westillsupporttheMat4stack,
  275. //butitisdeprecatedandyourcodeshouldnotrelyonit
  276. director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
  277. director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW,_modelViewTransform);
  278. //绘制自己
  279. _sprite->visit(renderer,_modelViewTransform,flags);
  280. draw(renderer,flags);
  281. director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
  282. _orderOfArrival=0;
  283. *将纹理保存到磁盘的文件中(只支持png和jpg两种压缩纹理格式)
  284. *@paramfileName文件
  285. *@paramisRGBA是否为RGBA
  286. *@returntrue:保存成功false:保存失败
  287. boolRenderTexture::saveToFile(conststd::string&filename,87); font-weight:bold; background-color:inherit">boolisRGBA)
  288. //将文件名转为小写
  289. std::stringbasename(filename);
  290. std::transform(basename.begin(),basename.end(),basename.begin(),::tolower);
  291. //包含.png,没有alpha通道
  292. if(basename.find(".png")!=std::string::npos)
  293. returnsaveToFile(filename,Image::Format::PNG,isRGBA);
  294. elseif(basename.find(".jpg")!=std::string::npos)
  295. //包含.jpg,有alpha通道
  296. if(isRGBA)CCLOG("RGBAisnotsupportedforJPGformat.");
  297. false);
  298. CCLOG("OnlyPNGandJPGformataresupportednow!");
  299. //默认将保存为JGP格式
  300. *将纹理保存到磁盘的文件
  301. *@paramformat图片格式
  302. *@paramisRGBA是否为RGBA
  303. *@returntrue:保存成功false:保存失败
  304. conststd::string&fileName,Image::Formatformat,87); font-weight:bold; background-color:inherit">boolisRGBA)
  305. CCASSERT(format==Image::Format::JPG||format==Image::Format::PNG,
  306. "theimagecanonlybesavedasJPGorPNGformat");
  307. if(isRGBA&&format==Image::Format::JPG)CCLOG("RGBAisnotsupportedforJPGformat");
  308. //保存图片文件的路径
  309. std::stringfullpath=FileUtils::getInstance()->getWritablePath()+fileName;
  310. //初始化将纹理保存到文件自定义渲染指令
  311. _saveToFileCommand.init(_globalZOrder);
  312. //设置自定义渲染指令的回调函数
  313. _saveToFileCommand.func=CC_CALLBACK_0(RenderTexture::onSaveToFile,153); font-weight:bold; background-color:inherit">this,fullpath,isRGBA);
  314. Director::getInstance()->getRenderer()->addCommand(&_saveToFileCommand);
  315. return*文件保存到磁盘文件的渲染回调
  316. *@paramfilename文件
  317. voidRenderTexture::onSaveToFile(//创建一个image对象
  318. Image*image=newImage(if(image)
  319. //保存到文件
  320. image->saveToFile(filename.c_str(),!isRGBA);
  321. //释放内存
  322. CC_SAFE_DELETE(image);
  323. /*getbufferasImage*/
  324. *创建一个Image对象
  325. *@paramfliimage是否将像素点数据上下倒置
  326. *@returnImage对象
  327. Image*RenderTexture::newImage(boolfliimage)
  328. //只有RGBA8888像素格式可以保存为一个Image对象
  329. CCASSERT(_pixelFormat==Texture2D::PixelFormat::RGBA8888,"onlyRGBA8888canbesavedasimage");
  330. if(nullptr==_texture)
  331. //获取纹理的大小
  332. constSize&s=_texture->getContentSizeInPixels();
  333. //togettheimagesizetosave
  334. //ifthesavingimagedomainexceedsthebuffertexturedomain,0); background-color:inherit">//itshouldbecut
  335. //保存Image对象的大小,如果image的大小比纹理的大,则会被裁剪
  336. intsavedBufferWidth=(int)s.width;
  337. intsavedBufferHeight=(int)s.height;
  338. //保存最终像素数据的数组
  339. GLubyte*buffer=nullptr;
  340. //保存临时像素数据的数组
  341. GLubyte*tempData=nullptr;
  342. Image*image=newImage();
  343. do
  344. //最终像素数据的数组申请内存
  345. CC_BREAK_IF(!(buffer=newGLubyte[savedBufferWidth*savedBufferHeight*4]));
  346. //临时像素数据的数组申请内存
  347. if(!(tempData=newGLubyte[savedBufferWidth*savedBufferHeight*4]))
  348. delete[]buffer;
  349. buffer=nullptr;
  350. //检查帧缓冲绑定状态,返回到_oldFBO帧缓冲对象中
  351. //绑定帧缓冲到_FBO帧缓冲对象中
  352. //TODOmovethistoconfigration,sowedon'tcheckiteverytime
  353. /*CertainQualcommAndrenogpu'swillretaindatainmemoryafteraframebufferswitchwhichcorruptstherendertothetexture.Thesolutionistocleartheframebufferbeforerenderingtothetexture.However,callingglClearhastheunintendedresultofclearingthecurrenttexture.Createatemporarytexturetoovercomethis.AttheendofRenderTexture::begin(),switchtheattachedtexturetothesecondone,callglClear,andthenswitchbacktotheoriginaltexture.Thissolutionisunnecessaryforotherdevicesastheydon'thavethesameissuewithswitchingframebuffers.
  354. if(Configuration::getInstance()->checkForGLExtension("GL_QCOM"))
  355. //--bindatemporarytexturesowecancleartherenderbufferwithoutlosingourtexture
  356. CHECK_GL_ERROR_DEBUG();
  357. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  358. //设置像素存储模式(读取到客户端)
  359. glPixelStorei(GL_PACK_ALIGNMENT,1);
  360. //将帧缓冲中的像素数据读到客户端中,保存在tempData数组中
  361. //像素矩形的起始位置,像素区域的大小,像素格式,数据类型,颜色数据指针
  362. //glReadPixels(GLintx,GLinty,GLsizeiwidth,GLsizeiheight,GLenumformat,GLenumtype,GLvoid*pixels)
  363. glReadPixels(0,savedBufferWidth,savedBufferHeight,GL_RGBA,GL_UNSIGNED_BYTE,tempData);
  364. //还原帧缓冲的绑定状态
  365. //是否保存到文件,保存到文件需要将像素点的数据上下颠倒
  366. if(fliimage)//--flipisonlyrequiredwhensavingimagetofile
  367. //togettheactualtexturedata
  368. //#640theimagereadfromrendertextureisdirty
  369. ///将pTempData从下往上拷到buffer数组中,initWithWidthAndHeight中精灵成员设置了Y镜像,所以图像是上下反
  370. for(inti=0;i<savedBufferHeight;++i)
  371. memcpy(&buffer[i*savedBufferWidth*4],
  372. &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);
  373. //初始化image对象
  374. image->initWithRawData(buffer,savedBufferWidth*savedBufferHeight*4,8);
  375. //初始化image对象
  376. image->initWithRawData(tempData,8);
  377. //释放保存像素数据的内存
  378. CC_SAFE_DELETE_ARRAY(buffer);
  379. CC_SAFE_DELETE_ARRAY(tempData);
  380. returnimage;
  381. *开始渲染指令的回调
  382. voidRenderTexture::onBegin()
  383. //保存变换前矩阵
  384. _oldProjMatrix=director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
  385. director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION,_projectionMatrix);
  386. _oldTransMatrix=director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
  387. //不保持矩阵,进行矩阵变换
  388. if(!_keepMatrix)
  389. director->setProjection(director->getProjection());
  390. #ifCC_TARGET_PLATFORM==CC_PLATFORM_WP8
  391. Mat4modifiedProjection=director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
  392. modifiedProjection=CCEGLView::sharedOpenGLView()->getReverSEOrientationMatrix()*modifiedProjection;
  393. director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION,modifiedProjection);
  394. constSize&texSize=_texture->getContentSizeInPixels();
  395. //Calculatetheadjustmentratiosbasedontheoldandnewprojections
  396. Sizesize=director->getWinSizeInPixels();
  397. floatwidthRatio=size.width/texSize.width;
  398. floatheightRatio=size.height/texSize.height;
  399. Mat4orthoMatrix;
  400. 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);
  401. director->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION,orthoMatrix);
  402. #ifCC_TARGET_PLATFORM==CC_PLATFORM_WP8
  403. Mat4modifiedProjection=director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
  404. modifiedProjection=CCEGLView::sharedOpenGLView()->getReverSEOrientationMatrix()*modifiedProjection;
  405. //计算视口逻辑
  406. //calculateviewport
  407. Rectviewport;
  408. viewport.size.width=_fullviewPort.size.width;
  409. viewport.size.height=_fullviewPort.size.height;
  410. floatviewPortRectWidthRatio=float(viewport.size.width)/_fullRect.size.width;
  411. floatviewPortRectHeightRatio=float(viewport.size.height)/_fullRect.size.height;
  412. viewport.origin.x=(_fullRect.origin.x-_rtTextureRect.origin.x)*viewPortRectWidthRatio;
  413. viewport.origin.y=(_fullRect.origin.y-_rtTextureRect.origin.y)*viewPortRectHeightRatio;
  414. //glViewport(_fullviewPort.origin.x,_fullviewPort.origin.y,(GLsizei)_fullviewPort.size.width,(GLsizei)_fullviewPort.size.height);
  415. glViewport(viewport.origin.x,viewport.origin.y,(GLsizei)viewport.size.width,(GLsizei)viewport.size.height);
  416. //Adjusttheorthographicprojectionandviewport
  417. //检查帧缓冲绑定状态,返回到_oldFBO中
  418. //绑定帧缓冲对象_FBO
  419. //--bindatemporarytexturesowecancleartherenderbufferwithoutlosingourtexture
  420. CHECK_GL_ERROR_DEBUG();
  421. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  422. *结束渲染指令回调
  423. voidRenderTexture::onEnd()
  424. //检查帧缓冲状态返回到_oldFBO对象
  425. //还原视口
  426. //restoreviewport
  427. director->setViewport();
  428. director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW,_oldTransMatrix);
  429. *清屏渲染指令回调
  430. voidRenderTexture::onClear()
  431. //saveclearcolor
  432. GLfloatoldClearColor[4]={0.0f};
  433. GLfloatoldDepthClearValue=0.0f;
  434. GLintoldStencilClearValue=0;
  435. //使用|运算符组合不同的缓冲标志位,表明需要清除的缓冲,例如glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)表示要清除颜色缓冲以及深度缓冲
  436. //backupandset
  437. if(_clearFlags&GL_COLOR_BUFFER_BIT)
  438. //保存颜色缓冲区的值到oldClearColor中
  439. glGetFloatv(GL_COLOR_CLEAR_VALUE,oldClearColor);
  440. //设置清屏色
  441. glClearColor(_clearColor.r,_clearColor.g,_clearColor.b,_clearColor.a);
  442. if(_clearFlags&GL_DEPTH_BUFFER_BIT)
  443. //保存深度值到oldDepthClearValue
  444. glGetFloatv(GL_DEPTH_CLEAR_VALUE,&oldDepthClearValue);
  445. //清理深度值
  446. glClearDepth(_clearDepth);
  447. if(_clearFlags&GL_STENCIL_BUFFER_BIT)
  448. //保存模板值到oldStencilClearValue
  449. //清理模板值
  450. glClearStencil(_clearStencil);
  451. //clear
  452. //清屏操作
  453. glClear(_clearFlags);
  454. //restore
  455. //还原保存的颜色值,深度值和模板值
  456. glClearColor(oldClearColor[0],oldClearColor[1],oldClearColor[2],oldClearColor[3]);
  457. glClearDepth(oldDepthClearValue);
  458. glClearStencil(oldStencilClearValue);
  459. *清理深度缓冲区渲染指令回调
  460. voidRenderTexture::onClearDepth()
  461. //!saveolddepthvalue
  462. GLfloatdepthClearValue;
  463. glClear(GL_DEPTH_BUFFER_BIT);
  464. glClearDepth(depthClearValue);
  465. *开始绘制
  466. *@paramrenderer渲染对象
  467. *@paramtransform变换矩阵
  468. *@paramflags标识
  469. voidRenderTexture::draw(Renderer*renderer,153); font-weight:bold; background-color:inherit">constMat4&transform,uint32_tflags)
  470. if(_autoDraw)
  471. //Beginwillcreatearendergroupusingnewrendertarget
  472. //开始绘制操作,创建渲染队列等
  473. begin();
  474. //初始化清屏渲染指令
  475. _clearCommand.init(_globalZOrder);
  476. _clearCommand.func=CC_CALLBACK_0(RenderTexture::onClear,0); background-color:inherit">//加入到组渲染队列中
  477. renderer->addCommand(&_clearCommand);
  478. //排序子元素,全局z优先,其次是本地z
  479. //!makesureallchildrenaredrawn
  480. sortAllChildren();
  481. //绘制子元素
  482. for(constauto&child:_children)
  483. if(child!=_sprite)
  484. child->visit(renderer,transform,0); background-color:inherit">//Endwillpopthecurrentrendergroup
  485. end();
  486. voidRenderTexture::begin()
  487. CCASSERT(nullptr!=director,"Directorisnullwhensetingmatrixstack");
  488. //在矩阵变换之前把当前矩阵保存在矩阵栈中
  489. director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
  490. _projectionMatrix=director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
  491. director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
  492. _transformMatrix=director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
  493. //不使用矩阵保持,进行矩阵变换
  494. if(!_keepMatrix)
  495. director->setProjection(director->getProjection());
  496. //纹理尺寸
  497. floatwidthRatio=size.width/texSize.width;
  498. floatheightRatio=size.height/texSize.height;
  499. Mat4orthoMatrix;
  500. Mat4::createOrthographicOffCenter(( director->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION,orthoMatrix);
  501. //初始化组渲染指令
  502. _groupCommand.init(_globalZOrder);
  503. //将组渲染指令加入当前组渲染队列之中
  504. Director::getInstance()->getRenderer()->addCommand(&_groupCommand);
  505. //将渲染队列Id加入到保存渲染队列Id的栈中
  506. Director::getInstance()->getRenderer()->pushGroup(_groupCommand.getRenderQueueID());
  507. //初始化开始渲染指令
  508. _beginCommand.init(_globalZOrder);
  509. _beginCommand.func=CC_CALLBACK_0(RenderTexture::onBegin,0); background-color:inherit">//将开始渲染指令加入到组渲染队列之中
  510. Director::getInstance()->getRenderer()->addCommand(&_beginCommand);
  511. *绘制结束
  512. voidRenderTexture::end()
  513. //初始化结束渲染指令
  514. _endCommand.init(_globalZOrder);
  515. //设置回调
  516. _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();
  517. CCASSERT(nullptr!=director,"Directorisnullwhensetingmatrixstack");
  518. Renderer*renderer=director->getRenderer();
  519. //将指令加入渲染队列
  520. renderer->addCommand(&_endCommand);
  521. //将组渲染指令生成的渲染队列弹出渲染队列
  522. renderer->popGroup();
  523. //还原矩阵
  524. director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
  525. director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
  526. NS_CC_END

本文转载自:http://www.jb51.cc/article/p-gbobhtdc-g.html

@H_170_3502@#ifndef __CCRENDER_TEXTURE_H__
@H_170_3502@#define __CCRENDER_TEXTURE_H__
@H_170_3502@#include "2d/CCNode.h"
@H_170_3502@#include "2d/CCSprite.h"
@H_170_3502@#include "platform/CCImage.h"
@H_170_3502@#include "renderer/CCGroupCommand.h"
@H_170_3502@#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,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 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 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 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 ) {
@H_301_3997@ 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 );
@H_158_4049@
/** 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) {
@H_301_4321@ _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,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,GLuint depthStencilFormat);
protected :
virtual void beginWithClear( float r, 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
@H_170_3502@#endif //__CCRENDER_TEXTURE_H__

猜你在找的Cocos2d-x相关文章