微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Cocos2d-x2.0 粒子系统深入分析三部曲(二)

Cocos2d-x2.0 粒子系统深入分析三部曲(二)

分类Cocos2d-x学习 10604人阅读 评论(6) 收藏 举报

目录(?)[+]

[Cocos2d-x相关教程来源于红孩儿的游戏编程之路CSDN博客地址:http://blog.csdn.net/honghaier]

红孩儿Cocos2d-X学习园地QQ2群:44208467加群写:Cocos2d-x
红孩儿Cocos2d-X学习园地QQ群:249941957加群写:Cocos2d-x

Cocos2d-x2.0 粒子系统深入分析三部曲(二)


上一节我们了解了粒子系统的原理,也学习了Cocos2d-x中的两个有关粒子系统的类:

(1)CCParticleSystem :粒子系统的基类,提供对粒子的创建和更新管理。

(2)CCParticleBatchNode:粒子系统的批次结点,用于将使用相同纹理的粒子系统进行同批次渲染优化处理。

在学习CCParticleSystem时,我们留下了一些疑问,什么时候调用setBatchNode?以及做为基类,CCParticleSystem提供了两个供子类重载的纯虚函数postStep()和updateQuadWithParticle,它们的具体用法是什么?我们仍然有一些迷茫。

我们今天来了解一下CCParticleSystemQuad,这个类是CCParticleSystem的子类。它将解开我们的这些疑惑。

打开CCParticleSystemQuad.h:

  1. classCC_DLLCCParticleSystemQuad:publicCCParticleSystem
  2. {
  3. protected:
  4. //如果当前粒子系统未使用批次结点,则需要为粒子系统创建单独的顶点缓冲及索引缓冲以及OPENGL进行渲染的一些相关物件。
  5. ccV3F_C4B_T2F_Quad*m_pQuads;//OPENGL渲染图形所用的四边形顶点缓冲。
  6. glushort*m_pIndices;//OPENGL渲染图形所用的索引缓冲。
  7. //这里有宏判断当前OPENGL版本是否支持使用VAO处理顶点缓冲(VAO是什么?这个问题问的好,VAO是OPENGL3.X以上引入的新特性,VBO是VertexBufferObject,VAO是VertexArrayObject。VAO是OpenGL3.0以后才引入的新东西,但是在2.0版本中做为扩展接口。VBO其实就是显卡中的显存,为了提高渲染速度,可以将要绘制的顶点数据缓存在显存中,这样就不需要将要绘制的顶点数据重复从cpu发送到GPU,浪费带宽资源。而VAO则是一个容器,可以包括多个VBO,它类似于以前的calllist,由于它进一步将VBO容于其中,所以绘制效率将在VBO的基础上更进一步。)
  8. #ifCC_TEXTURE_ATLAS_USE_VAO
  9. gluintm_uVAOname;//VAO的句柄。
  10. #endif
  11. gluintm_pBuffersVBO[2];//VBO的两个句柄,第一个句柄对应顶点缓冲,第二个句柄对应索引缓冲。
  12. public:
  13. //构造函数
  14. CCParticleSystemQuad();
  15. //析构函数
  16. virtual~CCParticleSystemQuad();
  17. //创建函数,参为为PLIST,内部调用create实现。
  18. CC_DEPRECATED_ATTRIBUTEstaticCCParticleSystemQuad*particleWithFile(constchar*plistFile);
  19. //上面函数的create实现。
  20. staticCCParticleSystemQuad*create(char*plistFile);
  21. //初始化索引缓冲。
  22. voidsetupIndices();
  23. //初始化方理坐标。
  24. voidinitTexCoordsWithRect(constCCRect&rect);
  25. //设置显示一个精灵帧。
  26. voidsetdisplayFrame(CCSpriteFrame*spriteFrame);
  27. //设置使用纹理对象上指定的矩形图像区域做为粒子系统的贴图。
  28. voidsetTextureWithRect(CCTexture2D*texture,//重载基类粒子系统的相应函数
  29. //初始化粒子数量
  30. virtualboolinitWithTotalParticles(unsignedintnumberOfParticles);
  31. //设置所用的纹理对象指针
  32. virtualvoidsetTexture(CCTexture2D*texture);
  33. //上一篇留下的疑问,虽然明显是更新粒子顶点缓冲中的位置数据。但上一篇为什么没有实现?
  34. voidupdateQuadWithParticle(tCCParticle*particle,153); font-weight:bold; background-color:inherit">constCCPoint&newPosition);
  35. //上一篇留下的疑问,不知道是做什么,咱们到CPP中看吧。
  36. voidpostStep();
  37. //渲染处理。
  38. voiddraw();
  39. //设置批次结点。
  40. voidsetBatchNode(CCParticleBatchNode*batchNode);
  41. //设置总的粒子数量
  42. voidsetTotalParticles(unsignedinttp);
  43. //监听响应当前结点的EVNET_COME_TO_FOREGROUND事件的回调函数
  44. voidlistenBackToForeground(CCObject*obj);
  45. //创建一个当前实例结点,内部调用create实现。
  46. CC_DEPRECATED_ATTRIBUTEstaticCCParticleSystemQuad*node();
  47. //上面的create实现。
  48. staticCCParticleSystemQuad*create();
  49. private:
  50. //如果使用VAO
  51. #ifCC_TEXTURE_ATLAS_USE_VAO
  52. //初始化VAO和VBO
  53. voidsetupVBOandVAO();
  54. #else
  55. //初始化VBO
  56. voidsetupVBO();
  57. #endif
  58. //申请内存。
  59. boolallocmemory();
  60. };

对应的实现:


copy
    //重载粒子系统基类的初始化函数,创建相应数量的粒子。
  1. boolCCParticleSystemQuad::initWithTotalParticles(unsignedintnumberOfParticles)
  2. {
  3. //调用基类的相应函数
  4. if(CCParticleSystem::initWithTotalParticles(numberOfParticles))
  5. //创建顶点和索引缓冲,如果失败释放并返回。
  6. if(!this->allocmemory()){
  7. this->release();
  8. returnfalse;
  9. }
  10. //填充索引缓冲。
  11. setupIndices();
  12. //如果当前OPENGL版本支持VAO,就创建VAO,如果不支持,只创建VBO。
  13. setupVBOandVAO();
  14. #else
  15. setupVBO();
  16. //设置使用顶点格式为“位置+纹理+顶点色”的顶点格式组合。
  17. setShaderProgram(CCshadercache::sharedshadercache()->programForKey(kCCShader_PositionTextureColor));
  18. //告诉通知中心,注册函数listenBackToForeground用来响应当前结点的EVNET_COME_TO_FOREGROUND事件。这个事件的意义是程序将由后面返回到前台。这个事件响应时可做资源的重新载入。
  19. CCNotificationCenter::sharednotificationCenter()->addobserver(this,
  20. callfuncO_selector(CCParticleSystemQuad::listenBackToForeground),
  21. EVNET_COME_TO_FOREGROUND,
  22. NULL);
  23. true;
  24. //构造函数
  25. CCParticleSystemQuad::CCParticleSystemQuad()
  26. :m_pQuads(NULL)
  27. ,m_pIndices(NULL)
  28. memset(m_pBuffersVBO,sizeof(m_pBuffersVBO));
  29. //析构函数
  30. CCParticleSystemQuad::~CCParticleSystemQuad()
  31. //对所创建的顶点缓冲,索引缓冲,以及VBO,VA0进行释放。
  32. if(NULL==m_pBatchNode)
  33. CC_SAFE_FREE(m_pQuads);
  34. CC_SAFE_FREE(m_pIndices);
  35. glDeleteBuffers(2,&m_pBuffersVBO[0]);
  36. glDeleteVertexArrays(1,&m_uVAOname);
  37. }
  38. //注销对通知管理器注册的相应事件的响应处理函数
  39. CCNotificationCenter::sharednotificationCenter()->removeObserver(//静态创建函数。由PLIST文件创建相应的当前实例对象,内部调用create实现。
  40. CCParticleSystemQuad*CCParticleSystemQuad::particleWithFile(char*plistFile)
  41. returnCCParticleSystemQuad::create(plistFile);
  42. CCParticleSystemQuad*CCParticleSystemQuad::create(char*plistFile)
  43. //创建一个CCParticleSystemQuad实例对象,进行初始化后交由内存管理器进行引用计数器的管理。
  44. CCParticleSystemQuad*pRet=newCCParticleSystemQuad();
  45. if(pRet&&pRet->initWithFile(plistFile))
  46. pRet->autorelease();
  47. returnpRet;
  48. //如果失败,删除并置空,返回NULL。
  49. CC_SAFE_DELETE(pRet);
  50. //初始化纹理坐标。
  51. voidCCParticleSystemQuad::initTexCoordsWithRect(constCCRect&pointRect)
  52. //创建出相应的矩形。
  53. CCRectrect=CCRectMake(
  54. pointRect.origin.x*CC_CONTENT_SCALE_FACTOR(),248)"> pointRect.origin.y*CC_CONTENT_SCALE_FACTOR(),108); list-style:decimal-leading-zero outside; color:inherit; line-height:18.9473686218262px; margin:0px!important; padding:0px 3px 0px 10px!important"> pointRect.size.width*CC_CONTENT_SCALE_FACTOR(),248)"> pointRect.size.height*CC_CONTENT_SCALE_FACTOR());
  55. //认使用的是批次结点,以批次结点的纹理对设置所用的图像区域矩形宽高。
  56. GLfloatwide=(GLfloat)pointRect.size.width;
  57. GLfloathigh=(GLfloat)pointRect.size.height;
  58. //如果使用单纹理对象,取得纹理的宽高。
  59. if(m_pTexture)
  60. wide=(GLfloat)m_pTexture->getPixelsWide();
  61. high=(GLfloat)m_pTexture->getPixelsHigh();
  62. //此宏是为了解决精灵边缘黑线而做的纹理坐标的微调。
  63. #ifCC_FIX_ARTIFACTS_BY_STRECHING_TEXEL
  64. GLfloatleft=(rect.origin.x*2+1)/(wide*2);
  65. GLfloatbottom=(rect.origin.y*2+1)/(high*2);
  66. GLfloatright=left+(rect.size.width*2-2)/(wide*2);
  67. GLfloattop=bottom+(rect.size.height*2-2)/(high*2);
  68. GLfloatleft=rect.origin.x/wide;
  69. GLfloatbottom=rect.origin.y/high;
  70. GLfloatright=left+rect.size.width/wide;
  71. GLfloattop=bottom+rect.size.height/high;
  72. //将top与bottom交换一下,因为在Cococs2d-x中坐标系Y轴是向上为正,这里处理一下后面可以做为顶点位置数据。
  73. CC_SWAP(top,bottom,float);
  74. //根据是否使用批次结点来取得相应的矩形顶点缓冲数组。
  75. ccV3F_C4B_T2F_Quad*quads=NULL;
  76. unsignedintstart=0,end=0;
  77. if(m_pBatchNode)
  78. {//如果使用批次结点,这里取得批次结点中所有粒子所对应的矩形顶点数组。
  79. quads=m_pBatchNode->getTextureAtlas()->getQuads();
  80. //取得起始和结束的粒子所对应的矩形索引。
  81. start=m_uAtlasIndex;
  82. end=m_uAtlasIndex+m_uTotalParticles;
  83. else
  84. {//如果使用单纹理对象,则起始矩形索引就是0,结束矩形索引就是最大粒子数量
  85. quads=m_pQuads;
  86. start=0;
  87. end=m_uTotalParticles;
  88. //遍历所有的矩形顶点。
  89. for(unsignedinti=start;i<end;i++)
  90. //设置四个顶点的纹理坐标。
  91. quads[i].bl.texCoords.u=left;
  92. quads[i].bl.texCoords.v=bottom;
  93. quads[i].br.texCoords.u=right;
  94. quads[i].br.texCoords.v=bottom;
  95. quads[i].tl.texCoords.u=left;
  96. quads[i].tl.texCoords.v=top;
  97. quads[i].tr.texCoords.u=right;
  98. quads[i].tr.texCoords.v=top;
  99. voidCCParticleSystemQuad::setTextureWithRect(CCTexture2D*texture,153); font-weight:bold; background-color:inherit">constCCRect&rect)
  100. //如果当前尚无纹理对或者使用的纹理与参数指定的纹理不同。则设置使用参数指定的纹理。
  101. if(!m_pTexture||texture->getName()!=m_pTexture->getName())
  102. CCParticleSystem::setTexture(texture);
  103. //设置指定的矩形图像区域做为贴图计算粒子系统的纹理坐标.
  104. this->initTexCoordsWithRect(rect);
  105. //设置使用的纹理对象。
  106. voidCCParticleSystemQuad::setTexture(CCTexture2D*texture)
  107. //取得纹理的大小。
  108. constCCSize&s=texture->getContentSize();
  109. this->setTextureWithRect(texture,CCRectMake(0,s.width,s.height));
  110. //设置使用精灵帧中的纹理。
  111. voidCCParticleSystemQuad::setdisplayFrame(CCSpriteFrame*spriteFrame)
  112. //有效性判断。
  113. CCAssert(spriteFrame->getoffsetInPixels().equals(CCPointZero),108); list-style:decimal-leading-zero outside; color:inherit; line-height:18.9473686218262px; margin:0px!important; padding:0px 3px 0px 10px!important"> "QuadParticleonlysupportsspriteFrameswithnooffsets");
  114. //如果当前尚无纹理对或者使用的纹理与参数指定的纹理不同。则设置使用参数指定的纹理。
  115. if(!m_pTexture||spriteFrame->getTexture()->getName()!=m_pTexture->getName())
  116. //设置使用精灵帧中的纹理.
  117. this->setTexture(spriteFrame->getTexture());
  118. voidCCParticleSystemQuad::setupIndices()
  119. //遍历粒子数目计算索引缓冲值。
  120. inti=0;i<m_uTotalParticles;++i)
  121. constunsignedinti6=i*6;
  122. inti4=i*4;
  123. m_pIndices[i6+0]=(glushort)i4+0;
  124. m_pIndices[i6+1]=(glushort)i4+1;
  125. m_pIndices[i6+2]=(glushort)i4+2;
  126. m_pIndices[i6+5]=(glushort)i4+1;
  127. m_pIndices[i6+4]=(glushort)i4+2;
  128. m_pIndices[i6+3]=(glushort)i4+3;
  129. //更新指定粒子的顶点缓冲中的位置数据。
  130. voidCCParticleSystemQuad::updateQuadWithParticle(tCCParticle*particle,153); font-weight:bold; background-color:inherit">constCCPoint&newPosition)
  131. //定义临时指针变量用于取得相应的粒子所对应的矩形顶点缓冲。
  132. ccV3F_C4B_T2F_Quad*quad;
  133. //如果使用了批次结点。
  134. if(m_pBatchNode)
  135. //取得批次结点中对应的矩形顶点缓冲数组指针。
  136. ccV3F_C4B_T2F_Quad*batchQuads=m_pBatchNode->getTextureAtlas()->getQuads();
  137. //通过索引取得相应的矩形顶点缓冲。
  138. quad=&(batchQuads[m_uAtlasIndex+particle->atlasIndex]);
  139. else
  140. //如果没有使用批次结点,直接取得相应的粒子的矩形顶点缓冲。
  141. quad=&(m_pQuads[m_uParticleIdx]);
  142. //根据是否由ALPHA值来设定RGB取得相应的颜色值。
  143. ccColor4Bcolor=(m_bOpacityModifyRGB)
  144. ?ccc4(particle->color.r*particle->color.a*255,particle->color.g*particle->color.a*255,particle->color.b*particle->color.a*255,particle->color.a*255)
  145. :ccc4(particle->color.r*255,particle->color.g*255,particle->color.b*255,particle->color.a*255);
  146. //填真顶点缓冲中的颜色信息。
  147. quad->bl.colors=color;
  148. quad->br.colors=color;
  149. quad->tl.colors=color;
  150. quad->tr.colors=color;
  151. //设置顶点的位置信息
  152. GLfloatsize_2=particle->size/2;
  153. //判断是否进行旋转。
  154. if(particle->rotation)
  155. //定义临时变量来存放以size_2为半径的矩形外圆上的四个顶点。
  156. GLfloatx1=-size_2;
  157. GLfloaty1=-size_2;
  158. GLfloatx2=size_2;
  159. GLfloaty2=size_2;
  160. //定义临时变量来存放圆心。
  161. GLfloatx=newPosition.x;
  162. GLfloaty=newPosition.y;
  163. //求得旋转角度。
  164. GLfloatr=(GLfloat)-CC_degrees_TO_radians(particle->rotation);
  165. //通过sin,cos来计算旋转后的矩形外圆上的四个角的顶点位置。
  166. GLfloatcr=cosf(r);
  167. GLfloatsr=sinf(r);
  168. GLfloatax=x1*cr-y1*sr+x;
  169. GLfloatay=x1*sr+y1*cr+y;
  170. GLfloatbx=x2*cr-y1*sr+x;
  171. GLfloatby=x2*sr+y1*cr+y;
  172. GLfloatcx=x2*cr-y2*sr+x;
  173. GLfloatcy=x2*sr+y2*cr+y;
  174. GLfloatdx=x1*cr-y2*sr+x;
  175. GLfloatdy=x1*sr+y2*cr+y;
  176. //填充计算旋转后的顶点位置信息。
  177. quad->bl.vertices.x=ax;
  178. quad->bl.vertices.y=ay;
  179. quad->br.vertices.x=bx;
  180. quad->br.vertices.y=by;
  181. quad->tl.vertices.x=dx;
  182. quad->tl.vertices.y=dy;
  183. quad->tr.vertices.x=cx;
  184. quad->tr.vertices.y=cy;
  185. //如果不旋转,直接填充位置信息。
  186. quad->bl.vertices.x=newPosition.x-size_2;
  187. quad->bl.vertices.y=newPosition.y-size_2;
  188. quad->br.vertices.x=newPosition.x+size_2;
  189. quad->br.vertices.y=newPosition.y-size_2;
  190. quad->tl.vertices.x=newPosition.x-size_2;
  191. quad->tl.vertices.y=newPosition.y+size_2;
  192. quad->tr.vertices.x=newPosition.x+size_2;
  193. quad->tr.vertices.y=newPosition.y+size_2;
  194. //我们一直想知道在CCParticleSystem中每次update时,如果粒子批次结点为空时为什么要调用postStep?它倒底是干什么的,看完下面的代码,就很清楚了。
  195. voidCCParticleSystemQuad::postStep()
  196. //绑定顶点缓冲区对象。
  197. glBindBuffer(GL_ARRAY_BUFFER,m_pBuffersVBO[0]);
  198. //用m_pQuads中数据更新绑定的缓冲区数据。
  199. glBufferSubData(GL_ARRAY_BUFFER,153); font-weight:bold; background-color:inherit">sizeof(m_pQuads[0])*m_uParticleCount,m_pQuads);
  200. //取消绑定缓冲区对象。
  201. CHECK_GL_ERROR_DEBUG();
  202. //清楚了,原来这个函数是针对不使用批次结点时的VBO顶点缓冲的更新。
  203. //绘制粒子系统。
  204. voidCCParticleSystemQuad::draw()
  205. //如果当前在粒子的批次结点有值,则draw()不应该被调用!为什么呢?因为有批次结点的话,渲染交给批次结点的draw()函数而不是当前粒子系统的draw()函数来处理。
  206. CCAssert(!m_pBatchNode,"drawshouldnotbecalledwhenaddedtoaparticleBatchNode");
  207. //使用相应的Shader
  208. CC_NODE_DRAW_SETUP();
  209. //绑定所用的纹理对象。
  210. ccGLBindTexture2D(m_pTexture->getName());
  211. //设定所用的ALPHA混合方案。
  212. ccGLBlendFunc(m_tBlendFunc.src,m_tBlendFunc.dst);
  213. //判断当前粒子索引是否为粒子总数,也就是判断是否已经update完成未出错。
  214. CCAssert(m_uParticleIdx==m_uParticleCount,"Abnormalerrorinparticlequad");
  215. //如果使用VAO。
  216. //使用VAO绑定的顶点数组
  217. glBindVertexArray(m_uVAOname);
  218. //绑定索引数组
  219. #ifCC_REBIND_INDICES_BUFFER
  220. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,m_pBuffersVBO[1]);
  221. //渲染调用
  222. glDrawElements(GL_TRIANGLES,(GLsizei)m_uParticleIdx*6,GL_UNSIGNED_SHORT,0);
  223. //渲染完取消绑定索引数组
  224. //取消绑定顶点数组
  225. glBindVertexArray(0);
  226. //
  227. //UsingVBOwithoutVAO
  228. //
  229. #definekQuadSizesizeof(m_pQuads[0].bl)
  230. //设置使用相应的顶点格式为:位置+颜色+纹理坐标
  231. ccGLEnabLevertexAttribs(kCCVertexAttribFlag_PosColorTex);
  232. //绑定顶点缓冲
  233. //设置顶点缓冲中位置数据的描述
  234. glVertexAttribPointer(kCCVertexAttrib_Position,3,GL_FLOAT,GL_FALSE,kQuadSize,(GLvoid*)offsetof(ccV3F_C4B_T2F,vertices));
  235. //设置顶点缓冲中颜色数据的描述
  236. glVertexAttribPointer(kCCVertexAttrib_Color,4,GL_UNSIGNED_BYTE,GL_TRUE,colors));
  237. //设置顶点缓冲中纹理坐标数据的描述
  238. glVertexAttribPointer(kCCVertexAttrib_TexCoords,2,texCoords));
  239. //绑定索引缓冲
  240. //渲染调用
  241. glDrawElements(GL_TRIANGLES,0); background-color:inherit">//取消绑定
  242. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); background-color:inherit">//渲染调用计数器加一
  243. CC_INCREMENT_GL_DRAWS(1);
  244. CHECK_GL_ERROR_DEBUG();
  245. //设置粒子数量
  246. voidCCParticleSystemQuad::setTotalParticles(unsignedinttp)
  247. //如果要申请内存的粒子数量大于之前已经申请内存的粒子数量
  248. if(tp>m_uAllocatedParticles)
  249. //计算要申请的内存大小。
  250. //粒子信息结构数组大小。
  251. size_tparticlesSize=tP*sizeof(tCCParticle);
  252. //顶点缓冲的大小
  253. size_tquadsSize=sizeof(m_pQuads[0])*tP*1;
  254. //索引缓冲的大小
  255. size_tindicesSize=sizeof(m_pIndices[0])*tP*6*1;
  256. //在m_pParticles指定的内存位置申请相应大小的内存用于存储粒子信息结构数组。
  257. tCCParticle*particlesNew=(tCCParticle*)realloc(m_pParticles,particlesSize);
  258. //在m_pQuads指定的内存位置申请相应大小的内存用于填充顶点缓冲。
  259. ccV3F_C4B_T2F_Quad*quadsNew=(ccV3F_C4B_T2F_Quad*)realloc(m_pQuads,quadsSize);
  260. //在m_pIndices指定的内存位置申请相应大小的内存用于填充索引缓冲。
  261. glushort*indicesNew=(glushort*)realloc(m_pIndices,indicesSize);
  262. //如果申请都成功。
  263. if(particlesNew&&quadsNew&&indicesNew)
  264. //将内存地址传值给成员指针。
  265. m_pParticles=particlesNew;
  266. m_pQuads=quadsNew;
  267. m_pIndices=indicesNew;
  268. //内存清零
  269. memset(m_pParticles,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18.9473686218262px; margin:0px!important; padding:0px 3px 0px 10px!important"> memset(m_pQuads,quadsSize);
  270. memset(m_pIndices,0); background-color:inherit">//记录申请内存的粒子数量
  271. m_uAllocatedParticles=tp;
  272. //如果失败,记录成功申请的内存地址打印出错LOG。
  273. if(particlesNew)m_pParticles=particlesNew;
  274. if(quadsNew)m_pQuads=quadsNew;
  275. if(indicesNew)m_pIndices=indicesNew;
  276. cclOG("Particlesystem:outofmemory");
  277. return;
  278. //更新粒子数量
  279. m_uTotalParticles=tp;
  280. //根据是否使用批次结点来设定每个粒子对应的矩形顶点块的索引。
  281. inti=0;i<m_uTotalParticles;i++)
  282. m_pParticles[i].atlasIndex=i;
  283. //填充索引缓冲。
  284. setupIndices();
  285. //初始化VAO
  286. setupVBOandVAO();
  287. //如果要申请内存的粒子数量小于原来申请的粒子数量,直接修改一下最大粒子数量就OK。
  288. m_uTotalParticles=tp;
  289. //如果当前OPENGL版本支持VAO。
  290. //初始化VBO与VAO
  291. voidCCParticleSystemQuad::setupVBOandVAO()
  292. //初始化1个顶点数组对象,产生VAO对象的句柄
  293. glGenVertexArrays(1,0); background-color:inherit">//绑定VAO。
  294. glBindVertexArray(m_uVAOname);
  295. //创建2个VBO缓冲区对象,产生两个句柄填充到句柄数组中。
  296. glGenBuffers(2,0); background-color:inherit">//绑定第一个VBO缓冲区对象。
  297. //将顶点数据拷贝到绑定的缓冲区。
  298. glBufferData(GL_ARRAY_BUFFER,153); font-weight:bold; background-color:inherit">sizeof(m_pQuads[0])*m_uTotalParticles,m_pQuads,GL_DYNAMIC_DRAW);
  299. //设置使用位置数据
  300. glEnabLevertexAttribArray(kCCVertexAttrib_Position);
  301. //设置位置数据在顶点缓冲中的描述
  302. glVertexAttribPointer(kCCVertexAttrib_Position,vertices));
  303. //设置使用颜色数据
  304. glEnabLevertexAttribArray(kCCVertexAttrib_Color);
  305. //设置颜色数据在顶点缓冲中的描述
  306. //设置使用纹理坐标数据
  307. glEnabLevertexAttribArray(kCCVertexAttrib_TexCoords);
  308. //设置纹理坐标数据在顶点缓冲中的描述
  309. glVertexAttribPointer(kCCVertexAttrib_TexCoords,texCoords));
  310. //绑定VBO的第二个缓冲区
  311. //将索引缓冲区数据拷贝到绑定的缓冲区
  312. glBufferData(GL_ELEMENT_ARRAY_BUFFER,153); font-weight:bold; background-color:inherit">sizeof(m_pIndices[0])*m_uTotalParticles*6,m_pIndices,GL_STATIC_DRAW);
  313. glBindVertexArray(0);
  314. //否则只使用VBO
  315. voidCCParticleSystemQuad::setupVBO()
  316. //创建2个VBO缓冲区对象,产生两个句柄填充到句柄数组中。
  317. glGenBuffers(2,&m_pBuffersVBO[0]);
  318. //绑定第一个VBO缓冲区对象并填充数据。
  319. glBindBuffer(GL_ARRAY_BUFFER,m_pBuffersVBO[0]);
  320. //绑定第二个VBO缓冲区对象并填充数据。
  321. //响应当前结点的EVNET_COME_TO_FOREGROUND事件。这个事件的意义是程序将由后面返回到前台。这个事件响应时可做资源的重新载入。
  322. voidCCParticleSystemQuad::listenBackToForeground(CCObject*obj)
  323. //重新初始化VBO和VAO。
  324. //创建顶点缓冲和索引缓冲区。
  325. boolCCParticleSystemQuad::allocmemory()
  326. //如果已经申请则中断。
  327. CCAssert((!m_pQuads&&!m_pIndices),"Memoryalreadyalloced");
  328. CCAssert(!m_pBatchNode,"MemoryshouldnotbeallocedwhennotusingbatchNode");
  329. //释放顶点与索引缓冲
  330. //为顶点与索引缓冲申请内存。
  331. m_pQuads=(ccV3F_C4B_T2F_Quad*)malloc(m_uTotalParticles*sizeof(ccV3F_C4B_T2F_Quad));
  332. m_pIndices=(glushort*)malloc(m_uTotalParticles*6*sizeof(glushort));
  333. //如果出现失败,则提示LOG并释放置空返回。
  334. if(!m_pQuads||!m_pIndices)
  335. cclOG("cocos2d:Particlesystem:notenoughmemory");
  336. CC_SAFE_FREE(m_pQuads);
  337. CC_SAFE_FREE(m_pIndices);
  338. //如果成功,置零操作返回true.
  339. //设置CCParticleSystemQuad使用的粒子批次结点。
  340. voidCCParticleSystemQuad::setBatchNode(CCParticleBatchNode*batchNode)
  341. //如果当前使用的粒子批次结点与参数不同,则进行更换处理。
  342. if(m_pBatchNode!=batchNode)
  343. //先记录一下当前使用的。
  344. CCParticleBatchNode*oldBatch=m_pBatchNode;
  345. //将后调用基类相应函数,设置当前使用的粒子批次结点。
  346. CCParticleSystem::setBatchNode(batchNode);
  347. //如果参数值为空,代表不使用批次结点。则进行顶点缓冲的相关初始化。
  348. if(!batchNode)
  349. //创建顶点缓冲,填充索引,并根据是否可用VAO设置顶点缓冲,设置纹理。
  350. allocmemory();
  351. setTexture(oldBatch->getTexture());
  352. setupVBO();
  353. //如果批次结点有效,且更换前没有使用粒子批次结点。
  354. elseif(!oldBatch)
  355. //取得相应粒子批次结点的矩形数组,取出相应索引位置的矩形数据,将相应的顶点缓冲数据拷到矩形数组中。
  356. ccV3F_C4B_T2F_Quad*quad=&(batchQuads[m_uAtlasIndex]);
  357. memcpy(quad,153); font-weight:bold; background-color:inherit">sizeof(m_pQuads[0]));
  358. //释放当前用的顶点缓冲
  359. //释放所用的VBO顶点对象与AVO名称
  360. glDeleteBuffers(2,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18.9473686218262px; margin:0px!important; padding:0px 3px 0px 10px!important"> glDeleteVertexArrays(1,&m_uVAOname);
  361. //创建一个CCParticleSystemQuad,内部调用create实现。
  362. CCParticleSystemQuad*CCParticleSystemQuad::node()
  363. returnCCParticleSystemQuad::create();
  364. CCParticleSystemQuad*CCParticleSystemQuad::create(){
  365. //创建一个CCParticleSystemQuad的实例对象。
  366. CCParticleSystemQuad*pParticleSystemQuad=newCCParticleSystemQuad();
  367. //如果创建成功,进行初始化。成功后交由内存管理器进行引用计数器的管理。
  368. if(pParticleSystemQuad&&pParticleSystemQuad->init())
  369. pParticleSystemQuad->autorelease();
  370. returnpParticleSystemQuad;
  371. //如果失败,释放置空并返回NULL。
  372. CC_SAFE_DELETE(pParticleSystemQuad);
  373. returnNULL;
  374. }

总结: 类CCParticleSystemQuad的源码进一步完善了粒子系统的功能,使我们可以在不需要批次结点时也能够实现粒子系统的OPENGL顶点和索引缓冲的创建和渲染,这么看来CCParticleSystem一个不完整的粒子系统的类,它只提供了使用粒子批次结点的粒子系统的渲染方案。

到这里,我们基本算领悟了Cocos2d-x中粒子系统的完整功能基类。后面我们将由此进入到多彩的粒子系统的演示中去!下课~

原文地址:https://www.jb51.cc/cocos2dx/343015.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐