CCRenderer.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942
  1. /****************************************************************************
  2. Copyright (c) 2013-2016 Chukong Technologies Inc.
  3. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
  4. http://www.cocos2d-x.org
  5. Permission is hereby granted, free of charge, to any person obtaining a copy
  6. of this software and associated documentation files (the "Software"), to deal
  7. in the Software without restriction, including without limitation the rights
  8. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. copies of the Software, and to permit persons to whom the Software is
  10. furnished to do so, subject to the following conditions:
  11. The above copyright notice and this permission notice shall be included in
  12. all copies or substantial portions of the Software.
  13. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. THE SOFTWARE.
  20. ****************************************************************************/
  21. #include "renderer/CCRenderer.h"
  22. #include <algorithm>
  23. #include "renderer/CCTrianglesCommand.h"
  24. #include "renderer/CCBatchCommand.h"
  25. #include "renderer/CCCustomCommand.h"
  26. #include "renderer/CCGroupCommand.h"
  27. #include "renderer/CCPrimitiveCommand.h"
  28. #include "renderer/CCMeshCommand.h"
  29. #include "renderer/CCGLProgramCache.h"
  30. #include "renderer/CCMaterial.h"
  31. #include "renderer/CCTechnique.h"
  32. #include "renderer/CCPass.h"
  33. #include "renderer/CCRenderState.h"
  34. #include "renderer/ccGLStateCache.h"
  35. #include "base/CCConfiguration.h"
  36. #include "base/CCDirector.h"
  37. #include "base/CCEventDispatcher.h"
  38. #include "base/CCEventListenerCustom.h"
  39. #include "base/CCEventType.h"
  40. #include "2d/CCCamera.h"
  41. #include "2d/CCScene.h"
  42. NS_CC_BEGIN
  43. // helper
  44. static bool compareRenderCommand(RenderCommand* a, RenderCommand* b)
  45. {
  46. return a->getGlobalOrder() < b->getGlobalOrder();
  47. }
  48. static bool compare3DCommand(RenderCommand* a, RenderCommand* b)
  49. {
  50. return a->getDepth() > b->getDepth();
  51. }
  52. // queue
  53. RenderQueue::RenderQueue()
  54. {
  55. }
  56. void RenderQueue::push_back(RenderCommand* command)
  57. {
  58. float z = command->getGlobalOrder();
  59. if(z < 0)
  60. {
  61. _commands[QUEUE_GROUP::GLOBALZ_NEG].push_back(command);
  62. }
  63. else if(z > 0)
  64. {
  65. _commands[QUEUE_GROUP::GLOBALZ_POS].push_back(command);
  66. }
  67. else
  68. {
  69. if(command->is3D())
  70. {
  71. if(command->isTransparent())
  72. {
  73. _commands[QUEUE_GROUP::TRANSPARENT_3D].push_back(command);
  74. }
  75. else
  76. {
  77. _commands[QUEUE_GROUP::OPAQUE_3D].push_back(command);
  78. }
  79. }
  80. else
  81. {
  82. _commands[QUEUE_GROUP::GLOBALZ_ZERO].push_back(command);
  83. }
  84. }
  85. }
  86. ssize_t RenderQueue::size() const
  87. {
  88. ssize_t result(0);
  89. for(int index = 0; index < QUEUE_GROUP::QUEUE_COUNT; ++index)
  90. {
  91. result += _commands[index].size();
  92. }
  93. return result;
  94. }
  95. void RenderQueue::sort()
  96. {
  97. // Don't sort _queue0, it already comes sorted
  98. std::stable_sort(std::begin(_commands[QUEUE_GROUP::TRANSPARENT_3D]), std::end(_commands[QUEUE_GROUP::TRANSPARENT_3D]), compare3DCommand);
  99. std::stable_sort(std::begin(_commands[QUEUE_GROUP::GLOBALZ_NEG]), std::end(_commands[QUEUE_GROUP::GLOBALZ_NEG]), compareRenderCommand);
  100. std::stable_sort(std::begin(_commands[QUEUE_GROUP::GLOBALZ_POS]), std::end(_commands[QUEUE_GROUP::GLOBALZ_POS]), compareRenderCommand);
  101. }
  102. RenderCommand* RenderQueue::operator[](ssize_t index) const
  103. {
  104. for(int queIndex = 0; queIndex < QUEUE_GROUP::QUEUE_COUNT; ++queIndex)
  105. {
  106. if(index < static_cast<ssize_t>(_commands[queIndex].size()))
  107. return _commands[queIndex][index];
  108. else
  109. {
  110. index -= _commands[queIndex].size();
  111. }
  112. }
  113. CCASSERT(false, "invalid index");
  114. return nullptr;
  115. }
  116. void RenderQueue::clear()
  117. {
  118. for(int i = 0; i < QUEUE_COUNT; ++i)
  119. {
  120. _commands[i].clear();
  121. }
  122. }
  123. void RenderQueue::realloc(size_t reserveSize)
  124. {
  125. for(int i = 0; i < QUEUE_COUNT; ++i)
  126. {
  127. _commands[i] = std::vector<RenderCommand*>();
  128. _commands[i].reserve(reserveSize);
  129. }
  130. }
  131. void RenderQueue::saveRenderState()
  132. {
  133. _isDepthEnabled = glIsEnabled(GL_DEPTH_TEST) != GL_FALSE;
  134. _isCullEnabled = glIsEnabled(GL_CULL_FACE) != GL_FALSE;
  135. glGetBooleanv(GL_DEPTH_WRITEMASK, &_isDepthWrite);
  136. CHECK_GL_ERROR_DEBUG();
  137. }
  138. void RenderQueue::restoreRenderState()
  139. {
  140. if (_isCullEnabled)
  141. {
  142. glEnable(GL_CULL_FACE);
  143. RenderState::StateBlock::_defaultState->setCullFace(true);
  144. }
  145. else
  146. {
  147. glDisable(GL_CULL_FACE);
  148. RenderState::StateBlock::_defaultState->setCullFace(false);
  149. }
  150. if (_isDepthEnabled)
  151. {
  152. glEnable(GL_DEPTH_TEST);
  153. RenderState::StateBlock::_defaultState->setDepthTest(true);
  154. }
  155. else
  156. {
  157. glDisable(GL_DEPTH_TEST);
  158. RenderState::StateBlock::_defaultState->setDepthTest(false);
  159. }
  160. glDepthMask(_isDepthWrite);
  161. RenderState::StateBlock::_defaultState->setDepthWrite(_isDepthEnabled);
  162. CHECK_GL_ERROR_DEBUG();
  163. }
  164. //
  165. //
  166. //
  167. static const int DEFAULT_RENDER_QUEUE = 0;
  168. //
  169. // constructors, destructor, init
  170. //
  171. Renderer::Renderer()
  172. :_lastBatchedMeshCommand(nullptr)
  173. ,_filledVertex(0)
  174. ,_filledIndex(0)
  175. ,_glViewAssigned(false)
  176. ,_isRendering(false)
  177. ,_isDepthTestFor2D(false)
  178. ,_triBatchesToDraw(nullptr)
  179. ,_triBatchesToDrawCapacity(-1)
  180. #if CC_ENABLE_CACHE_TEXTURE_DATA
  181. ,_cacheTextureListener(nullptr)
  182. #endif
  183. {
  184. _groupCommandManager = new (std::nothrow) GroupCommandManager();
  185. _commandGroupStack.push(DEFAULT_RENDER_QUEUE);
  186. RenderQueue defaultRenderQueue;
  187. _renderGroups.push_back(defaultRenderQueue);
  188. _queuedTriangleCommands.reserve(BATCH_TRIAGCOMMAND_RESERVED_SIZE);
  189. // default clear color
  190. _clearColor = Color4F::BLACK;
  191. // for the batched TriangleCommand
  192. _triBatchesToDrawCapacity = 500;
  193. _triBatchesToDraw = (TriBatchToDraw*) malloc(sizeof(_triBatchesToDraw[0]) * _triBatchesToDrawCapacity);
  194. }
  195. Renderer::~Renderer()
  196. {
  197. _renderGroups.clear();
  198. _groupCommandManager->release();
  199. glDeleteBuffers(2, _buffersVBO);
  200. free(_triBatchesToDraw);
  201. if (Configuration::getInstance()->supportsShareableVAO())
  202. {
  203. glDeleteVertexArrays(1, &_buffersVAO);
  204. GL::bindVAO(0);
  205. }
  206. #if CC_ENABLE_CACHE_TEXTURE_DATA
  207. Director::getInstance()->getEventDispatcher()->removeEventListener(_cacheTextureListener);
  208. #endif
  209. }
  210. void Renderer::initGLView()
  211. {
  212. #if CC_ENABLE_CACHE_TEXTURE_DATA
  213. _cacheTextureListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom* event){
  214. /** listen the event that renderer was recreated on Android/WP8 */
  215. this->setupBuffer();
  216. });
  217. Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_cacheTextureListener, -1);
  218. #endif
  219. setupBuffer();
  220. _glViewAssigned = true;
  221. }
  222. void Renderer::setupBuffer()
  223. {
  224. if(Configuration::getInstance()->supportsShareableVAO())
  225. {
  226. setupVBOAndVAO();
  227. }
  228. else
  229. {
  230. setupVBO();
  231. }
  232. }
  233. void Renderer::setupVBOAndVAO()
  234. {
  235. //generate vbo and vao for trianglesCommand
  236. glGenVertexArrays(1, &_buffersVAO);
  237. GL::bindVAO(_buffersVAO);
  238. glGenBuffers(2, &_buffersVBO[0]);
  239. glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
  240. // Issue #15652
  241. // Should not initialize VBO with a large size (VBO_SIZE=65536),
  242. // it may cause low FPS on some Android devices like LG G4 & Nexus 5X.
  243. // It's probably because some implementations of OpenGLES driver will
  244. // copy the whole memory of VBO which initialized at the first time
  245. // once glBufferData/glBufferSubData is invoked.
  246. // For more discussion, please refer to https://github.com/cocos2d/cocos2d-x/issues/15652
  247. //glBufferData(GL_ARRAY_BUFFER, sizeof(_verts[0]) * VBO_SIZE, _verts, GL_DYNAMIC_DRAW);
  248. // vertices
  249. glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
  250. glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), (GLvoid*) offsetof( V3F_C4B_T2F, vertices));
  251. // colors
  252. glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_COLOR);
  253. glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B_T2F), (GLvoid*) offsetof( V3F_C4B_T2F, colors));
  254. // tex coords
  255. glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_TEX_COORD);
  256. glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), (GLvoid*) offsetof( V3F_C4B_T2F, texCoords));
  257. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
  258. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(_indices[0]) * INDEX_VBO_SIZE, _indices, GL_STATIC_DRAW);
  259. // Must unbind the VAO before changing the element buffer.
  260. GL::bindVAO(0);
  261. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  262. glBindBuffer(GL_ARRAY_BUFFER, 0);
  263. CHECK_GL_ERROR_DEBUG();
  264. }
  265. void Renderer::setupVBO()
  266. {
  267. glGenBuffers(2, &_buffersVBO[0]);
  268. // Issue #15652
  269. // Should not initialize VBO with a large size (VBO_SIZE=65536),
  270. // it may cause low FPS on some Android devices like LG G4 & Nexus 5X.
  271. // It's probably because some implementations of OpenGLES driver will
  272. // copy the whole memory of VBO which initialized at the first time
  273. // once glBufferData/glBufferSubData is invoked.
  274. // For more discussion, please refer to https://github.com/cocos2d/cocos2d-x/issues/15652
  275. // mapBuffers();
  276. }
  277. void Renderer::mapBuffers()
  278. {
  279. // Avoid changing the element buffer for whatever VAO might be bound.
  280. GL::bindVAO(0);
  281. glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
  282. glBufferData(GL_ARRAY_BUFFER, sizeof(_verts[0]) * VBO_SIZE, _verts, GL_DYNAMIC_DRAW);
  283. glBindBuffer(GL_ARRAY_BUFFER, 0);
  284. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
  285. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(_indices[0]) * INDEX_VBO_SIZE, _indices, GL_STATIC_DRAW);
  286. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  287. CHECK_GL_ERROR_DEBUG();
  288. }
  289. void Renderer::addCommand(RenderCommand* command)
  290. {
  291. int renderQueueID =_commandGroupStack.top();
  292. addCommand(command, renderQueueID);
  293. }
  294. void Renderer::addCommand(RenderCommand* command, int renderQueueID)
  295. {
  296. CCASSERT(!_isRendering, "Cannot add command while rendering");
  297. CCASSERT(renderQueueID >=0, "Invalid render queue");
  298. CCASSERT(command->getType() != RenderCommand::Type::UNKNOWN_COMMAND, "Invalid Command Type");
  299. _renderGroups[renderQueueID].push_back(command);
  300. }
  301. void Renderer::pushGroup(int renderQueueID)
  302. {
  303. CCASSERT(!_isRendering, "Cannot change render queue while rendering");
  304. _commandGroupStack.push(renderQueueID);
  305. }
  306. void Renderer::popGroup()
  307. {
  308. CCASSERT(!_isRendering, "Cannot change render queue while rendering");
  309. _commandGroupStack.pop();
  310. }
  311. int Renderer::createRenderQueue()
  312. {
  313. RenderQueue newRenderQueue;
  314. _renderGroups.push_back(newRenderQueue);
  315. return (int)_renderGroups.size() - 1;
  316. }
  317. void Renderer::processRenderCommand(RenderCommand* command)
  318. {
  319. auto commandType = command->getType();
  320. if( RenderCommand::Type::TRIANGLES_COMMAND == commandType)
  321. {
  322. // flush other queues
  323. flush3D();
  324. auto cmd = static_cast<TrianglesCommand*>(command);
  325. // flush own queue when buffer is full
  326. if(_filledVertex + cmd->getVertexCount() > VBO_SIZE || _filledIndex + cmd->getIndexCount() > INDEX_VBO_SIZE)
  327. {
  328. CCASSERT(cmd->getVertexCount()>= 0 && cmd->getVertexCount() < VBO_SIZE, "VBO for vertex is not big enough, please break the data down or use customized render command");
  329. CCASSERT(cmd->getIndexCount()>= 0 && cmd->getIndexCount() < INDEX_VBO_SIZE, "VBO for index is not big enough, please break the data down or use customized render command");
  330. drawBatchedTriangles();
  331. }
  332. // queue it
  333. _queuedTriangleCommands.push_back(cmd);
  334. _filledIndex += cmd->getIndexCount();
  335. _filledVertex += cmd->getVertexCount();
  336. }
  337. else if (RenderCommand::Type::MESH_COMMAND == commandType)
  338. {
  339. flush2D();
  340. auto cmd = static_cast<MeshCommand*>(command);
  341. if (cmd->isSkipBatching() || _lastBatchedMeshCommand == nullptr || _lastBatchedMeshCommand->getMaterialID() != cmd->getMaterialID())
  342. {
  343. flush3D();
  344. CCGL_DEBUG_INSERT_EVENT_MARKER("RENDERER_MESH_COMMAND");
  345. if(cmd->isSkipBatching())
  346. {
  347. // XXX: execute() will call bind() and unbind()
  348. // but unbind() shouldn't be call if the next command is a MESH_COMMAND with Material.
  349. // Once most of cocos2d-x moves to Pass/StateBlock, only bind() should be used.
  350. cmd->execute();
  351. }
  352. else
  353. {
  354. cmd->preBatchDraw();
  355. cmd->batchDraw();
  356. _lastBatchedMeshCommand = cmd;
  357. }
  358. }
  359. else
  360. {
  361. CCGL_DEBUG_INSERT_EVENT_MARKER("RENDERER_MESH_COMMAND");
  362. cmd->batchDraw();
  363. }
  364. }
  365. else if(RenderCommand::Type::GROUP_COMMAND == commandType)
  366. {
  367. flush();
  368. int renderQueueID = ((GroupCommand*) command)->getRenderQueueID();
  369. CCGL_DEBUG_PUSH_GROUP_MARKER("RENDERER_GROUP_COMMAND");
  370. visitRenderQueue(_renderGroups[renderQueueID]);
  371. CCGL_DEBUG_POP_GROUP_MARKER();
  372. }
  373. else if(RenderCommand::Type::CUSTOM_COMMAND == commandType)
  374. {
  375. flush();
  376. auto cmd = static_cast<CustomCommand*>(command);
  377. CCGL_DEBUG_INSERT_EVENT_MARKER("RENDERER_CUSTOM_COMMAND");
  378. cmd->execute();
  379. }
  380. else if(RenderCommand::Type::BATCH_COMMAND == commandType)
  381. {
  382. flush();
  383. auto cmd = static_cast<BatchCommand*>(command);
  384. CCGL_DEBUG_INSERT_EVENT_MARKER("RENDERER_BATCH_COMMAND");
  385. cmd->execute();
  386. }
  387. else if(RenderCommand::Type::PRIMITIVE_COMMAND == commandType)
  388. {
  389. flush();
  390. auto cmd = static_cast<PrimitiveCommand*>(command);
  391. CCGL_DEBUG_INSERT_EVENT_MARKER("RENDERER_PRIMITIVE_COMMAND");
  392. cmd->execute();
  393. }
  394. else
  395. {
  396. CCLOGERROR("Unknown commands in renderQueue");
  397. }
  398. }
  399. void Renderer::visitRenderQueue(RenderQueue& queue)
  400. {
  401. queue.saveRenderState();
  402. //
  403. //Process Global-Z < 0 Objects
  404. //
  405. const auto& zNegQueue = queue.getSubQueue(RenderQueue::QUEUE_GROUP::GLOBALZ_NEG);
  406. if (zNegQueue.size() > 0)
  407. {
  408. if(_isDepthTestFor2D)
  409. {
  410. glEnable(GL_DEPTH_TEST);
  411. glDepthMask(true);
  412. glEnable(GL_BLEND);
  413. RenderState::StateBlock::_defaultState->setDepthTest(true);
  414. RenderState::StateBlock::_defaultState->setDepthWrite(true);
  415. RenderState::StateBlock::_defaultState->setBlend(true);
  416. }
  417. else
  418. {
  419. glDisable(GL_DEPTH_TEST);
  420. glDepthMask(false);
  421. glEnable(GL_BLEND);
  422. RenderState::StateBlock::_defaultState->setDepthTest(false);
  423. RenderState::StateBlock::_defaultState->setDepthWrite(false);
  424. RenderState::StateBlock::_defaultState->setBlend(true);
  425. }
  426. glDisable(GL_CULL_FACE);
  427. RenderState::StateBlock::_defaultState->setCullFace(false);
  428. for (const auto& zNegNext : zNegQueue)
  429. {
  430. processRenderCommand(zNegNext);
  431. }
  432. flush();
  433. }
  434. //
  435. //Process Opaque Object
  436. //
  437. const auto& opaqueQueue = queue.getSubQueue(RenderQueue::QUEUE_GROUP::OPAQUE_3D);
  438. if (opaqueQueue.size() > 0)
  439. {
  440. //Clear depth to achieve layered rendering
  441. glEnable(GL_DEPTH_TEST);
  442. glDepthMask(true);
  443. glDisable(GL_BLEND);
  444. glEnable(GL_CULL_FACE);
  445. RenderState::StateBlock::_defaultState->setDepthTest(true);
  446. RenderState::StateBlock::_defaultState->setDepthWrite(true);
  447. RenderState::StateBlock::_defaultState->setBlend(false);
  448. RenderState::StateBlock::_defaultState->setCullFace(true);
  449. for (const auto& opaqueNext : opaqueQueue)
  450. {
  451. processRenderCommand(opaqueNext);
  452. }
  453. flush();
  454. }
  455. //
  456. //Process 3D Transparent object
  457. //
  458. const auto& transQueue = queue.getSubQueue(RenderQueue::QUEUE_GROUP::TRANSPARENT_3D);
  459. if (transQueue.size() > 0)
  460. {
  461. glEnable(GL_DEPTH_TEST);
  462. glDepthMask(false);
  463. glEnable(GL_BLEND);
  464. glEnable(GL_CULL_FACE);
  465. RenderState::StateBlock::_defaultState->setDepthTest(true);
  466. RenderState::StateBlock::_defaultState->setDepthWrite(false);
  467. RenderState::StateBlock::_defaultState->setBlend(true);
  468. RenderState::StateBlock::_defaultState->setCullFace(true);
  469. for (const auto& transNext : transQueue)
  470. {
  471. processRenderCommand(transNext);
  472. }
  473. flush();
  474. }
  475. //
  476. //Process Global-Z = 0 Queue
  477. //
  478. const auto& zZeroQueue = queue.getSubQueue(RenderQueue::QUEUE_GROUP::GLOBALZ_ZERO);
  479. if (zZeroQueue.size() > 0)
  480. {
  481. if(_isDepthTestFor2D)
  482. {
  483. glEnable(GL_DEPTH_TEST);
  484. glDepthMask(true);
  485. glEnable(GL_BLEND);
  486. RenderState::StateBlock::_defaultState->setDepthTest(true);
  487. RenderState::StateBlock::_defaultState->setDepthWrite(true);
  488. RenderState::StateBlock::_defaultState->setBlend(true);
  489. }
  490. else
  491. {
  492. glDisable(GL_DEPTH_TEST);
  493. glDepthMask(false);
  494. glEnable(GL_BLEND);
  495. RenderState::StateBlock::_defaultState->setDepthTest(false);
  496. RenderState::StateBlock::_defaultState->setDepthWrite(false);
  497. RenderState::StateBlock::_defaultState->setBlend(true);
  498. }
  499. glDisable(GL_CULL_FACE);
  500. RenderState::StateBlock::_defaultState->setCullFace(false);
  501. for (const auto& zZeroNext : zZeroQueue)
  502. {
  503. processRenderCommand(zZeroNext);
  504. }
  505. flush();
  506. }
  507. //
  508. //Process Global-Z > 0 Queue
  509. //
  510. const auto& zPosQueue = queue.getSubQueue(RenderQueue::QUEUE_GROUP::GLOBALZ_POS);
  511. if (zPosQueue.size() > 0)
  512. {
  513. if(_isDepthTestFor2D)
  514. {
  515. glEnable(GL_DEPTH_TEST);
  516. glDepthMask(true);
  517. glEnable(GL_BLEND);
  518. RenderState::StateBlock::_defaultState->setDepthTest(true);
  519. RenderState::StateBlock::_defaultState->setDepthWrite(true);
  520. RenderState::StateBlock::_defaultState->setBlend(true);
  521. }
  522. else
  523. {
  524. glDisable(GL_DEPTH_TEST);
  525. glDepthMask(false);
  526. glEnable(GL_BLEND);
  527. RenderState::StateBlock::_defaultState->setDepthTest(false);
  528. RenderState::StateBlock::_defaultState->setDepthWrite(false);
  529. RenderState::StateBlock::_defaultState->setBlend(true);
  530. }
  531. glDisable(GL_CULL_FACE);
  532. RenderState::StateBlock::_defaultState->setCullFace(false);
  533. for (const auto& zPosNext : zPosQueue)
  534. {
  535. processRenderCommand(zPosNext);
  536. }
  537. flush();
  538. }
  539. queue.restoreRenderState();
  540. }
  541. void Renderer::render()
  542. {
  543. //Uncomment this once everything is rendered by new renderer
  544. //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  545. //TODO: setup camera or MVP
  546. _isRendering = true;
  547. if (_glViewAssigned)
  548. {
  549. //Process render commands
  550. //1. Sort render commands based on ID
  551. for (auto &renderqueue : _renderGroups)
  552. {
  553. renderqueue.sort();
  554. }
  555. visitRenderQueue(_renderGroups[0]);
  556. }
  557. clean();
  558. _isRendering = false;
  559. }
  560. void Renderer::clean()
  561. {
  562. // Clear render group
  563. for (size_t j = 0, size = _renderGroups.size() ; j < size; j++)
  564. {
  565. //commands are owned by nodes
  566. // for (const auto &cmd : _renderGroups[j])
  567. // {
  568. // cmd->releaseToCommandPool();
  569. // }
  570. _renderGroups[j].clear();
  571. }
  572. // Clear batch commands
  573. _queuedTriangleCommands.clear();
  574. _filledVertex = 0;
  575. _filledIndex = 0;
  576. _lastBatchedMeshCommand = nullptr;
  577. }
  578. void Renderer::clear()
  579. {
  580. //Enable Depth mask to make sure glClear clear the depth buffer correctly
  581. glDepthMask(true);
  582. glClearColor(_clearColor.r, _clearColor.g, _clearColor.b, _clearColor.a);
  583. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  584. glDepthMask(false);
  585. RenderState::StateBlock::_defaultState->setDepthWrite(false);
  586. }
  587. void Renderer::setDepthTest(bool enable)
  588. {
  589. if (enable)
  590. {
  591. glClearDepth(1.0f);
  592. glEnable(GL_DEPTH_TEST);
  593. glDepthFunc(GL_LEQUAL);
  594. RenderState::StateBlock::_defaultState->setDepthTest(true);
  595. RenderState::StateBlock::_defaultState->setDepthFunction(RenderState::DEPTH_LEQUAL);
  596. // glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  597. }
  598. else
  599. {
  600. glDisable(GL_DEPTH_TEST);
  601. RenderState::StateBlock::_defaultState->setDepthTest(false);
  602. }
  603. _isDepthTestFor2D = enable;
  604. CHECK_GL_ERROR_DEBUG();
  605. }
  606. void Renderer::fillVerticesAndIndices(const TrianglesCommand* cmd)
  607. {
  608. memcpy(&_verts[_filledVertex], cmd->getVertices(), sizeof(V3F_C4B_T2F) * cmd->getVertexCount());
  609. // fill vertex, and convert them to world coordinates
  610. const Mat4& modelView = cmd->getModelView();
  611. for(ssize_t i=0; i < cmd->getVertexCount(); ++i)
  612. {
  613. modelView.transformPoint(&(_verts[i + _filledVertex].vertices));
  614. }
  615. // fill index
  616. const unsigned short* indices = cmd->getIndices();
  617. for(ssize_t i=0; i< cmd->getIndexCount(); ++i)
  618. {
  619. _indices[_filledIndex + i] = _filledVertex + indices[i];
  620. }
  621. _filledVertex += cmd->getVertexCount();
  622. _filledIndex += cmd->getIndexCount();
  623. }
  624. void Renderer::drawBatchedTriangles()
  625. {
  626. if(_queuedTriangleCommands.empty())
  627. return;
  628. CCGL_DEBUG_INSERT_EVENT_MARKER("RENDERER_BATCH_TRIANGLES");
  629. _filledVertex = 0;
  630. _filledIndex = 0;
  631. /************** 1: Setup up vertices/indices *************/
  632. _triBatchesToDraw[0].offset = 0;
  633. _triBatchesToDraw[0].indicesToDraw = 0;
  634. _triBatchesToDraw[0].cmd = nullptr;
  635. int batchesTotal = 0;
  636. uint32_t prevMaterialID = 0;
  637. bool isValidMaterialID = false;
  638. bool firstCommand = true;
  639. for(const auto& cmd : _queuedTriangleCommands)
  640. {
  641. auto currentMaterialID = cmd->getMaterialID();
  642. const bool batchable = !cmd->isSkipBatching();
  643. fillVerticesAndIndices(cmd);
  644. // in the same batch ?
  645. if (batchable && ((isValidMaterialID && prevMaterialID == currentMaterialID )|| firstCommand))
  646. {
  647. CC_ASSERT((firstCommand || _triBatchesToDraw[batchesTotal].cmd->getMaterialID() == cmd->getMaterialID()) && "argh... error in logic");
  648. _triBatchesToDraw[batchesTotal].indicesToDraw += cmd->getIndexCount();
  649. _triBatchesToDraw[batchesTotal].cmd = cmd;
  650. }
  651. else
  652. {
  653. // is this the first one?
  654. if (!firstCommand) {
  655. batchesTotal++;
  656. _triBatchesToDraw[batchesTotal].offset = _triBatchesToDraw[batchesTotal-1].offset + _triBatchesToDraw[batchesTotal-1].indicesToDraw;
  657. }
  658. _triBatchesToDraw[batchesTotal].cmd = cmd;
  659. _triBatchesToDraw[batchesTotal].indicesToDraw = (int) cmd->getIndexCount();
  660. // is this a single batch ? Prevent creating a batch group then
  661. if (!batchable)
  662. {
  663. //currentMaterialID = -1;
  664. isValidMaterialID = false;
  665. }
  666. }
  667. // capacity full ?
  668. if (batchesTotal + 1 >= _triBatchesToDrawCapacity) {
  669. _triBatchesToDrawCapacity *= 1.4;
  670. _triBatchesToDraw = (TriBatchToDraw*) realloc(_triBatchesToDraw, sizeof(_triBatchesToDraw[0]) * _triBatchesToDrawCapacity);
  671. }
  672. prevMaterialID = currentMaterialID;
  673. isValidMaterialID = true;
  674. firstCommand = false;
  675. }
  676. batchesTotal++;
  677. /************** 2: Copy vertices/indices to GL objects *************/
  678. auto conf = Configuration::getInstance();
  679. if (conf->supportsShareableVAO() && conf->supportsMapBuffer())
  680. {
  681. //Bind VAO
  682. GL::bindVAO(_buffersVAO);
  683. //Set VBO data
  684. glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
  685. // option 1: subdata
  686. // glBufferSubData(GL_ARRAY_BUFFER, sizeof(_quads[0])*start, sizeof(_quads[0]) * n , &_quads[start] );
  687. // option 2: data
  688. // glBufferData(GL_ARRAY_BUFFER, sizeof(_verts[0]) * _filledVertex, _verts, GL_STATIC_DRAW);
  689. // option 3: orphaning + glMapBuffer
  690. // FIXME: in order to work as fast as possible, it must "and the exact same size and usage hints it had before."
  691. // source: https://www.opengl.org/wiki/Buffer_Object_Streaming#Explicit_multiple_buffering
  692. // so most probably we won't have any benefit of using it
  693. glBufferData(GL_ARRAY_BUFFER, sizeof(_verts[0]) * _filledVertex, nullptr, GL_STATIC_DRAW);
  694. void *buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
  695. memcpy(buf, _verts, sizeof(_verts[0]) * _filledVertex);
  696. glUnmapBuffer(GL_ARRAY_BUFFER);
  697. glBindBuffer(GL_ARRAY_BUFFER, 0);
  698. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
  699. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(_indices[0]) * _filledIndex, _indices, GL_STATIC_DRAW);
  700. }
  701. else
  702. {
  703. // Client Side Arrays
  704. #define kQuadSize sizeof(_verts[0])
  705. glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
  706. glBufferData(GL_ARRAY_BUFFER, sizeof(_verts[0]) * _filledVertex , _verts, GL_DYNAMIC_DRAW);
  707. GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);
  708. // vertices
  709. glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof(V3F_C4B_T2F, vertices));
  710. // colors
  711. glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (GLvoid*) offsetof(V3F_C4B_T2F, colors));
  712. // tex coords
  713. glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof(V3F_C4B_T2F, texCoords));
  714. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
  715. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(_indices[0]) * _filledIndex, _indices, GL_STATIC_DRAW);
  716. }
  717. /************** 3: Draw *************/
  718. for (int i=0; i<batchesTotal; ++i)
  719. {
  720. CC_ASSERT(_triBatchesToDraw[i].cmd && "Invalid batch");
  721. _triBatchesToDraw[i].cmd->useMaterial();
  722. glDrawElements(GL_TRIANGLES, (GLsizei) _triBatchesToDraw[i].indicesToDraw, GL_UNSIGNED_SHORT, (GLvoid*) (_triBatchesToDraw[i].offset*sizeof(_indices[0])) );
  723. _drawnBatches++;
  724. _drawnVertices += _triBatchesToDraw[i].indicesToDraw;
  725. }
  726. /************** 4: Cleanup *************/
  727. if (conf->supportsShareableVAO() && conf->supportsMapBuffer())
  728. {
  729. //Unbind VAO
  730. GL::bindVAO(0);
  731. }
  732. else
  733. {
  734. glBindBuffer(GL_ARRAY_BUFFER, 0);
  735. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  736. }
  737. _queuedTriangleCommands.clear();
  738. _filledVertex = 0;
  739. _filledIndex = 0;
  740. }
  741. void Renderer::flush()
  742. {
  743. flush2D();
  744. flush3D();
  745. }
  746. void Renderer::flush2D()
  747. {
  748. flushTriangles();
  749. }
  750. void Renderer::flush3D()
  751. {
  752. if (_lastBatchedMeshCommand)
  753. {
  754. CCGL_DEBUG_INSERT_EVENT_MARKER("RENDERER_BATCH_MESH");
  755. _lastBatchedMeshCommand->postBatchDraw();
  756. _lastBatchedMeshCommand = nullptr;
  757. }
  758. }
  759. void Renderer::flushTriangles()
  760. {
  761. drawBatchedTriangles();
  762. }
  763. // helpers
  764. bool Renderer::checkVisibility(const Mat4 &transform, const Size &size)
  765. {
  766. auto director = Director::getInstance();
  767. auto scene = director->getRunningScene();
  768. //If draw to Rendertexture, return true directly.
  769. // only cull the default camera. The culling algorithm is valid for default camera.
  770. if (!scene || (scene && scene->_defaultCamera != Camera::getVisitingCamera()))
  771. return true;
  772. Rect visibleRect(director->getVisibleOrigin(), director->getVisibleSize());
  773. // transform center point to screen space
  774. float hSizeX = size.width/2;
  775. float hSizeY = size.height/2;
  776. Vec3 v3p(hSizeX, hSizeY, 0);
  777. transform.transformPoint(&v3p);
  778. Vec2 v2p = Camera::getVisitingCamera()->projectGL(v3p);
  779. // convert content size to world coordinates
  780. float wshw = std::max(fabsf(hSizeX * transform.m[0] + hSizeY * transform.m[4]), fabsf(hSizeX * transform.m[0] - hSizeY * transform.m[4]));
  781. float wshh = std::max(fabsf(hSizeX * transform.m[1] + hSizeY * transform.m[5]), fabsf(hSizeX * transform.m[1] - hSizeY * transform.m[5]));
  782. // enlarge visible rect half size in screen coord
  783. visibleRect.origin.x -= wshw;
  784. visibleRect.origin.y -= wshh;
  785. visibleRect.size.width += wshw * 2;
  786. visibleRect.size.height += wshh * 2;
  787. bool ret = visibleRect.containsPoint(v2p);
  788. return ret;
  789. }
  790. void Renderer::setClearColor(const Color4F &clearColor)
  791. {
  792. _clearColor = clearColor;
  793. }
  794. NS_CC_END