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

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

#ifndef __CCRENDER_TEXTURE_H__
#define __CCRENDER_TEXTURE_H__
@H_262_3509@
#include "2d/CCNode.h"
@H_874_3515@ #include "2d/CCSprite.h"
#include "platform/CCImage.h"
#include "renderer/CCGroupCommand.h"
#include "renderer/CCCustomcatommand.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
@H_675_3593@ 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
@H_765_3607@ */
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);
@H_616_3655@
/** 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);
@H_701_3675@
/** 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.
@H_338_3801@ 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. */
@H_675_3837@ 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);
@H_616_3943@ /* creates a new Image from with the texture's data.
Caller is responsible for releasing it by calling delete.
@H_944_3955@ */
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. */
@H_397_4505@ inline void setSprite(Sprite* spritE) {
CC_SAFE_RETAIN(spritE);
CC_SAFE_RELEASE(_spritE);
_sprite = sprite;
};
// Overrides
virtual void visit(Renderer *renderer, const @H_612_3534@mat4 &parentTransform,uint32_t parentFlags) override;
virtual void draw(Renderer *renderer, const @H_612_3534@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.
@H_876_4607@ //rtBegin: the position of renderTexture on the fullRect
//fullRect: the @R_527_10586@l size of screen
//fullViewport: the @R_527_10586@l viewportSize
*/
void setVirtualViewport( const Vec2& rtBegin, const Rect& fullRect, const Rect& fullViewport);
@H_673_4653@ 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.
@H_552_4893@ The blending function can be changed in runtime by calling: @H_369_4899@ - renderTexture->getSprite()->setBlendFunc((BlendFunC){
GL_ONE,GL_ONE_MINUS_SRC_ALPHA
});
*/
Sprite* _sprite;
GroupCommand _groupCommand;
Customcatommand _beginWithClearCommand;
Customcatommand _clearDepthCommand;
Customcatommand _clearCommand;
Customcatommand _beginCommand;
Customcatommand _endCommand;
Customcatommand _saveToFileCommand;
protected :
//renderer caches and callBACks
void onBegin();
void onEnd();
void onClear();
void onClearDepth();
void onSaveToFile( const std::string& filename, bool isRGBA = true );
@H_612_3534@mat4 _oldTransmatrix,_oldProjMatrix;
@H_612_3534@mat4 _transformMatrix,_projectionMatrix;
private :
CC_DISALLOW_COPY_AND_ASSIGN(RenderTexturE);
};
// end of textures group
/// @
}
NS_CC_END
#endif //__CCRENDER_TEXTURE_H__

大佬总结

以上是大佬教程为你收集整理的Cocos2d-x 3.x RenderTexture渲染纹理源码分析全部内容,希望文章能够帮你解决Cocos2d-x 3.x RenderTexture渲染纹理源码分析所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:33.xcocoscocos2ddrendertexturex分析渲染源码纹理
猜你在找的Cocos2d-x相关文章
其他相关热搜词更多
phpJavaPython程序员load如何string使用参数jquery开发安装listlinuxiosandroid工具javascriptcap