123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929 |
- #include "renderer/CCRenderer.h"
- #include <algorithm>
- #include "renderer/CCTrianglesCommand.h"
- #include "renderer/CCBatchCommand.h"
- #include "renderer/CCCustomCommand.h"
- #include "renderer/CCGroupCommand.h"
- #include "renderer/CCPrimitiveCommand.h"
- #include "renderer/CCMeshCommand.h"
- #include "renderer/CCGLProgramCache.h"
- #include "renderer/CCMaterial.h"
- #include "renderer/CCTechnique.h"
- #include "renderer/CCPass.h"
- #include "renderer/CCRenderState.h"
- #include "renderer/ccGLStateCache.h"
- #include "base/CCConfiguration.h"
- #include "base/CCDirector.h"
- #include "base/CCEventDispatcher.h"
- #include "base/CCEventListenerCustom.h"
- #include "base/CCEventType.h"
- #include "2d/CCCamera.h"
- #include "2d/CCScene.h"
- NS_CC_BEGIN
- static bool compareRenderCommand(RenderCommand* a, RenderCommand* b)
- {
- return a->getGlobalOrder() < b->getGlobalOrder();
- }
- static bool compare3DCommand(RenderCommand* a, RenderCommand* b)
- {
- return a->getDepth() > b->getDepth();
- }
- RenderQueue::RenderQueue()
- {
-
- }
- void RenderQueue::push_back(RenderCommand* command)
- {
- float z = command->getGlobalOrder();
- if(z < 0)
- {
- _commands[QUEUE_GROUP::GLOBALZ_NEG].push_back(command);
- }
- else if(z > 0)
- {
- _commands[QUEUE_GROUP::GLOBALZ_POS].push_back(command);
- }
- else
- {
- if(command->is3D())
- {
- if(command->isTransparent())
- {
- _commands[QUEUE_GROUP::TRANSPARENT_3D].push_back(command);
- }
- else
- {
- _commands[QUEUE_GROUP::OPAQUE_3D].push_back(command);
- }
- }
- else
- {
- _commands[QUEUE_GROUP::GLOBALZ_ZERO].push_back(command);
- }
- }
- }
- ssize_t RenderQueue::size() const
- {
- ssize_t result(0);
- for(int index = 0; index < QUEUE_GROUP::QUEUE_COUNT; ++index)
- {
- result += _commands[index].size();
- }
-
- return result;
- }
- void RenderQueue::sort()
- {
-
- std::stable_sort(std::begin(_commands[QUEUE_GROUP::TRANSPARENT_3D]), std::end(_commands[QUEUE_GROUP::TRANSPARENT_3D]), compare3DCommand);
- std::stable_sort(std::begin(_commands[QUEUE_GROUP::GLOBALZ_NEG]), std::end(_commands[QUEUE_GROUP::GLOBALZ_NEG]), compareRenderCommand);
- std::stable_sort(std::begin(_commands[QUEUE_GROUP::GLOBALZ_POS]), std::end(_commands[QUEUE_GROUP::GLOBALZ_POS]), compareRenderCommand);
- }
- RenderCommand* RenderQueue::operator[](ssize_t index) const
- {
- for(int queIndex = 0; queIndex < QUEUE_GROUP::QUEUE_COUNT; ++queIndex)
- {
- if(index < static_cast<ssize_t>(_commands[queIndex].size()))
- return _commands[queIndex][index];
- else
- {
- index -= _commands[queIndex].size();
- }
- }
-
- CCASSERT(false, "invalid index");
- return nullptr;
- }
- void RenderQueue::clear()
- {
- for(int i = 0; i < QUEUE_COUNT; ++i)
- {
- _commands[i].clear();
- }
- }
- void RenderQueue::realloc(size_t reserveSize)
- {
- for(int i = 0; i < QUEUE_COUNT; ++i)
- {
- _commands[i] = std::vector<RenderCommand*>();
- _commands[i].reserve(reserveSize);
- }
- }
- void RenderQueue::saveRenderState()
- {
- _isDepthEnabled = glIsEnabled(GL_DEPTH_TEST) != GL_FALSE;
- _isCullEnabled = glIsEnabled(GL_CULL_FACE) != GL_FALSE;
- glGetBooleanv(GL_DEPTH_WRITEMASK, &_isDepthWrite);
-
- CHECK_GL_ERROR_DEBUG();
- }
- void RenderQueue::restoreRenderState()
- {
- if (_isCullEnabled)
- {
- glEnable(GL_CULL_FACE);
- RenderState::StateBlock::_defaultState->setCullFace(true);
- }
- else
- {
- glDisable(GL_CULL_FACE);
- RenderState::StateBlock::_defaultState->setCullFace(false);
- }
- if (_isDepthEnabled)
- {
- glEnable(GL_DEPTH_TEST);
- RenderState::StateBlock::_defaultState->setDepthTest(true);
- }
- else
- {
- glDisable(GL_DEPTH_TEST);
- RenderState::StateBlock::_defaultState->setDepthTest(false);
- }
-
- glDepthMask(_isDepthWrite);
- RenderState::StateBlock::_defaultState->setDepthWrite(_isDepthEnabled);
- CHECK_GL_ERROR_DEBUG();
- }
- static const int DEFAULT_RENDER_QUEUE = 0;
- Renderer::Renderer()
- :_lastBatchedMeshCommand(nullptr)
- ,_filledVertex(0)
- ,_filledIndex(0)
- ,_glViewAssigned(false)
- ,_isRendering(false)
- ,_isDepthTestFor2D(false)
- ,_triBatchesToDraw(nullptr)
- ,_triBatchesToDrawCapacity(-1)
- #if CC_ENABLE_CACHE_TEXTURE_DATA
- ,_cacheTextureListener(nullptr)
- #endif
- {
- _groupCommandManager = new (std::nothrow) GroupCommandManager();
-
- _commandGroupStack.push(DEFAULT_RENDER_QUEUE);
-
- RenderQueue defaultRenderQueue;
- _renderGroups.push_back(defaultRenderQueue);
- _queuedTriangleCommands.reserve(BATCH_TRIAGCOMMAND_RESERVED_SIZE);
-
- _clearColor = Color4F::BLACK;
-
- _triBatchesToDrawCapacity = 500;
- _triBatchesToDraw = (TriBatchToDraw*) malloc(sizeof(_triBatchesToDraw[0]) * _triBatchesToDrawCapacity);
- }
- Renderer::~Renderer()
- {
- _renderGroups.clear();
- _groupCommandManager->release();
-
- glDeleteBuffers(2, _buffersVBO);
- free(_triBatchesToDraw);
- if (Configuration::getInstance()->supportsShareableVAO())
- {
- glDeleteVertexArrays(1, &_buffersVAO);
- GL::bindVAO(0);
- }
- #if CC_ENABLE_CACHE_TEXTURE_DATA
- Director::getInstance()->getEventDispatcher()->removeEventListener(_cacheTextureListener);
- #endif
- }
- void Renderer::initGLView()
- {
- #if CC_ENABLE_CACHE_TEXTURE_DATA
- _cacheTextureListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom* event){
-
- this->setupBuffer();
- });
-
- Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_cacheTextureListener, -1);
- #endif
- setupBuffer();
-
- _glViewAssigned = true;
- }
- void Renderer::setupBuffer()
- {
- if(Configuration::getInstance()->supportsShareableVAO())
- {
- setupVBOAndVAO();
- }
- else
- {
- setupVBO();
- }
- }
- void Renderer::setupVBOAndVAO()
- {
-
- glGenVertexArrays(1, &_buffersVAO);
- GL::bindVAO(_buffersVAO);
- glGenBuffers(2, &_buffersVBO[0]);
- glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
- glBufferData(GL_ARRAY_BUFFER, sizeof(_verts[0]) * VBO_SIZE, _verts, GL_DYNAMIC_DRAW);
-
- glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION);
- glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), (GLvoid*) offsetof( V3F_C4B_T2F, vertices));
-
- glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_COLOR);
- glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B_T2F), (GLvoid*) offsetof( V3F_C4B_T2F, colors));
-
- glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_TEX_COORD);
- glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B_T2F), (GLvoid*) offsetof( V3F_C4B_T2F, texCoords));
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(_indices[0]) * INDEX_VBO_SIZE, _indices, GL_STATIC_DRAW);
-
- GL::bindVAO(0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- CHECK_GL_ERROR_DEBUG();
- }
- void Renderer::setupVBO()
- {
- glGenBuffers(2, &_buffersVBO[0]);
-
-
-
-
-
-
-
- }
- void Renderer::mapBuffers()
- {
-
- GL::bindVAO(0);
- glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
- glBufferData(GL_ARRAY_BUFFER, sizeof(_verts[0]) * VBO_SIZE, _verts, GL_DYNAMIC_DRAW);
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(_indices[0]) * INDEX_VBO_SIZE, _indices, GL_STATIC_DRAW);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- CHECK_GL_ERROR_DEBUG();
- }
- void Renderer::addCommand(RenderCommand* command)
- {
- int renderQueue =_commandGroupStack.top();
- addCommand(command, renderQueue);
- }
- void Renderer::addCommand(RenderCommand* command, int renderQueue)
- {
- CCASSERT(!_isRendering, "Cannot add command while rendering");
- CCASSERT(renderQueue >=0, "Invalid render queue");
- CCASSERT(command->getType() != RenderCommand::Type::UNKNOWN_COMMAND, "Invalid Command Type");
- _renderGroups[renderQueue].push_back(command);
- }
- void Renderer::pushGroup(int renderQueueID)
- {
- CCASSERT(!_isRendering, "Cannot change render queue while rendering");
- _commandGroupStack.push(renderQueueID);
- }
- void Renderer::popGroup()
- {
- CCASSERT(!_isRendering, "Cannot change render queue while rendering");
- _commandGroupStack.pop();
- }
- int Renderer::createRenderQueue()
- {
- RenderQueue newRenderQueue;
- _renderGroups.push_back(newRenderQueue);
- return (int)_renderGroups.size() - 1;
- }
- void Renderer::processRenderCommand(RenderCommand* command)
- {
- auto commandType = command->getType();
- if( RenderCommand::Type::TRIANGLES_COMMAND == commandType)
- {
-
- flush3D();
- auto cmd = static_cast<TrianglesCommand*>(command);
-
-
- if(_filledVertex + cmd->getVertexCount() > VBO_SIZE || _filledIndex + cmd->getIndexCount() > INDEX_VBO_SIZE)
- {
- 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");
- 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");
- drawBatchedTriangles();
- }
-
-
- _queuedTriangleCommands.push_back(cmd);
- _filledIndex += cmd->getIndexCount();
- _filledVertex += cmd->getVertexCount();
- }
- else if (RenderCommand::Type::MESH_COMMAND == commandType)
- {
- flush2D();
- auto cmd = static_cast<MeshCommand*>(command);
-
- if (cmd->isSkipBatching() || _lastBatchedMeshCommand == nullptr || _lastBatchedMeshCommand->getMaterialID() != cmd->getMaterialID())
- {
- flush3D();
- CCGL_DEBUG_INSERT_EVENT_MARKER("RENDERER_MESH_COMMAND");
- if(cmd->isSkipBatching())
- {
-
-
-
- cmd->execute();
- }
- else
- {
- cmd->preBatchDraw();
- cmd->batchDraw();
- _lastBatchedMeshCommand = cmd;
- }
- }
- else
- {
- CCGL_DEBUG_INSERT_EVENT_MARKER("RENDERER_MESH_COMMAND");
- cmd->batchDraw();
- }
- }
- else if(RenderCommand::Type::GROUP_COMMAND == commandType)
- {
- flush();
- int renderQueueID = ((GroupCommand*) command)->getRenderQueueID();
- CCGL_DEBUG_PUSH_GROUP_MARKER("RENDERER_GROUP_COMMAND");
- visitRenderQueue(_renderGroups[renderQueueID]);
- CCGL_DEBUG_POP_GROUP_MARKER();
- }
- else if(RenderCommand::Type::CUSTOM_COMMAND == commandType)
- {
- flush();
- auto cmd = static_cast<CustomCommand*>(command);
- CCGL_DEBUG_INSERT_EVENT_MARKER("RENDERER_CUSTOM_COMMAND");
- cmd->execute();
- }
- else if(RenderCommand::Type::BATCH_COMMAND == commandType)
- {
- flush();
- auto cmd = static_cast<BatchCommand*>(command);
- CCGL_DEBUG_INSERT_EVENT_MARKER("RENDERER_BATCH_COMMAND");
- cmd->execute();
- }
- else if(RenderCommand::Type::PRIMITIVE_COMMAND == commandType)
- {
- flush();
- auto cmd = static_cast<PrimitiveCommand*>(command);
- CCGL_DEBUG_INSERT_EVENT_MARKER("RENDERER_PRIMITIVE_COMMAND");
- cmd->execute();
- }
- else
- {
- CCLOGERROR("Unknown commands in renderQueue");
- }
- }
- void Renderer::visitRenderQueue(RenderQueue& queue)
- {
- queue.saveRenderState();
-
-
-
-
- const auto& zNegQueue = queue.getSubQueue(RenderQueue::QUEUE_GROUP::GLOBALZ_NEG);
- if (zNegQueue.size() > 0)
- {
- if(_isDepthTestFor2D)
- {
- glEnable(GL_DEPTH_TEST);
- glDepthMask(true);
- glEnable(GL_BLEND);
- RenderState::StateBlock::_defaultState->setDepthTest(true);
- RenderState::StateBlock::_defaultState->setDepthWrite(true);
- RenderState::StateBlock::_defaultState->setBlend(true);
- }
- else
- {
- glDisable(GL_DEPTH_TEST);
- glDepthMask(false);
- glEnable(GL_BLEND);
- RenderState::StateBlock::_defaultState->setDepthTest(false);
- RenderState::StateBlock::_defaultState->setDepthWrite(false);
- RenderState::StateBlock::_defaultState->setBlend(true);
- }
- glDisable(GL_CULL_FACE);
- RenderState::StateBlock::_defaultState->setCullFace(false);
-
- for (const auto& zNegNext : zNegQueue)
- {
- processRenderCommand(zNegNext);
- }
- flush();
- }
-
-
-
-
- const auto& opaqueQueue = queue.getSubQueue(RenderQueue::QUEUE_GROUP::OPAQUE_3D);
- if (opaqueQueue.size() > 0)
- {
-
- glEnable(GL_DEPTH_TEST);
- glDepthMask(true);
- glDisable(GL_BLEND);
- glEnable(GL_CULL_FACE);
- RenderState::StateBlock::_defaultState->setDepthTest(true);
- RenderState::StateBlock::_defaultState->setDepthWrite(true);
- RenderState::StateBlock::_defaultState->setBlend(false);
- RenderState::StateBlock::_defaultState->setCullFace(true);
- for (const auto& opaqueNext : opaqueQueue)
- {
- processRenderCommand(opaqueNext);
- }
- flush();
- }
-
-
-
-
- const auto& transQueue = queue.getSubQueue(RenderQueue::QUEUE_GROUP::TRANSPARENT_3D);
- if (transQueue.size() > 0)
- {
- glEnable(GL_DEPTH_TEST);
- glDepthMask(false);
- glEnable(GL_BLEND);
- glEnable(GL_CULL_FACE);
- RenderState::StateBlock::_defaultState->setDepthTest(true);
- RenderState::StateBlock::_defaultState->setDepthWrite(false);
- RenderState::StateBlock::_defaultState->setBlend(true);
- RenderState::StateBlock::_defaultState->setCullFace(true);
- for (const auto& transNext : transQueue)
- {
- processRenderCommand(transNext);
- }
- flush();
- }
-
-
-
-
- const auto& zZeroQueue = queue.getSubQueue(RenderQueue::QUEUE_GROUP::GLOBALZ_ZERO);
- if (zZeroQueue.size() > 0)
- {
- if(_isDepthTestFor2D)
- {
- glEnable(GL_DEPTH_TEST);
- glDepthMask(true);
- glEnable(GL_BLEND);
- RenderState::StateBlock::_defaultState->setDepthTest(true);
- RenderState::StateBlock::_defaultState->setDepthWrite(true);
- RenderState::StateBlock::_defaultState->setBlend(true);
- }
- else
- {
- glDisable(GL_DEPTH_TEST);
- glDepthMask(false);
- glEnable(GL_BLEND);
- RenderState::StateBlock::_defaultState->setDepthTest(false);
- RenderState::StateBlock::_defaultState->setDepthWrite(false);
- RenderState::StateBlock::_defaultState->setBlend(true);
- }
- glDisable(GL_CULL_FACE);
- RenderState::StateBlock::_defaultState->setCullFace(false);
-
- for (const auto& zZeroNext : zZeroQueue)
- {
- processRenderCommand(zZeroNext);
- }
- flush();
- }
-
-
-
-
- const auto& zPosQueue = queue.getSubQueue(RenderQueue::QUEUE_GROUP::GLOBALZ_POS);
- if (zPosQueue.size() > 0)
- {
- if(_isDepthTestFor2D)
- {
- glEnable(GL_DEPTH_TEST);
- glDepthMask(true);
- glEnable(GL_BLEND);
-
- RenderState::StateBlock::_defaultState->setDepthTest(true);
- RenderState::StateBlock::_defaultState->setDepthWrite(true);
- RenderState::StateBlock::_defaultState->setBlend(true);
- }
- else
- {
- glDisable(GL_DEPTH_TEST);
- glDepthMask(false);
- glEnable(GL_BLEND);
-
- RenderState::StateBlock::_defaultState->setDepthTest(false);
- RenderState::StateBlock::_defaultState->setDepthWrite(false);
- RenderState::StateBlock::_defaultState->setBlend(true);
- }
- glDisable(GL_CULL_FACE);
- RenderState::StateBlock::_defaultState->setCullFace(false);
-
- for (const auto& zPosNext : zPosQueue)
- {
- processRenderCommand(zPosNext);
- }
- flush();
- }
-
- queue.restoreRenderState();
- }
- void Renderer::render()
- {
-
-
-
- _isRendering = true;
-
- if (_glViewAssigned)
- {
-
-
- for (auto &renderqueue : _renderGroups)
- {
- renderqueue.sort();
- }
- visitRenderQueue(_renderGroups[0]);
- }
- clean();
- _isRendering = false;
- }
- void Renderer::clean()
- {
-
- for (size_t j = 0, size = _renderGroups.size() ; j < size; j++)
- {
-
-
-
-
-
- _renderGroups[j].clear();
- }
-
- _queuedTriangleCommands.clear();
- _filledVertex = 0;
- _filledIndex = 0;
- _lastBatchedMeshCommand = nullptr;
- }
- void Renderer::clear()
- {
-
- glDepthMask(true);
- glClearColor(_clearColor.r, _clearColor.g, _clearColor.b, _clearColor.a);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glDepthMask(false);
- RenderState::StateBlock::_defaultState->setDepthWrite(false);
- }
- void Renderer::setDepthTest(bool enable)
- {
- if (enable)
- {
- glClearDepth(1.0f);
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LEQUAL);
- RenderState::StateBlock::_defaultState->setDepthTest(true);
- RenderState::StateBlock::_defaultState->setDepthFunction(RenderState::DEPTH_LEQUAL);
- }
- else
- {
- glDisable(GL_DEPTH_TEST);
- RenderState::StateBlock::_defaultState->setDepthTest(false);
- }
- _isDepthTestFor2D = enable;
- CHECK_GL_ERROR_DEBUG();
- }
- void Renderer::fillVerticesAndIndices(const TrianglesCommand* cmd)
- {
- memcpy(&_verts[_filledVertex], cmd->getVertices(), sizeof(V3F_C4B_T2F) * cmd->getVertexCount());
-
- const Mat4& modelView = cmd->getModelView();
- for(ssize_t i=0; i < cmd->getVertexCount(); ++i)
- {
- modelView.transformPoint(&(_verts[i + _filledVertex].vertices));
- }
-
- const unsigned short* indices = cmd->getIndices();
- for(ssize_t i=0; i< cmd->getIndexCount(); ++i)
- {
- _indices[_filledIndex + i] = _filledVertex + indices[i];
- }
- _filledVertex += cmd->getVertexCount();
- _filledIndex += cmd->getIndexCount();
- }
- void Renderer::drawBatchedTriangles()
- {
- if(_queuedTriangleCommands.empty())
- return;
- CCGL_DEBUG_INSERT_EVENT_MARKER("RENDERER_BATCH_TRIANGLES");
- _filledVertex = 0;
- _filledIndex = 0;
-
- _triBatchesToDraw[0].offset = 0;
- _triBatchesToDraw[0].indicesToDraw = 0;
- _triBatchesToDraw[0].cmd = nullptr;
- int batchesTotal = 0;
- int prevMaterialID = -1;
- bool firstCommand = true;
- for(const auto& cmd : _queuedTriangleCommands)
- {
- auto currentMaterialID = cmd->getMaterialID();
- const bool batchable = !cmd->isSkipBatching();
- fillVerticesAndIndices(cmd);
-
- if (batchable && (prevMaterialID == currentMaterialID || firstCommand))
- {
- CC_ASSERT(firstCommand || _triBatchesToDraw[batchesTotal].cmd->getMaterialID() == cmd->getMaterialID() && "argh... error in logic");
- _triBatchesToDraw[batchesTotal].indicesToDraw += cmd->getIndexCount();
- _triBatchesToDraw[batchesTotal].cmd = cmd;
- }
- else
- {
-
- if (!firstCommand) {
- batchesTotal++;
- _triBatchesToDraw[batchesTotal].offset = _triBatchesToDraw[batchesTotal-1].offset + _triBatchesToDraw[batchesTotal-1].indicesToDraw;
- }
- _triBatchesToDraw[batchesTotal].cmd = cmd;
- _triBatchesToDraw[batchesTotal].indicesToDraw = (int) cmd->getIndexCount();
-
- if (!batchable)
- currentMaterialID = -1;
- }
-
- if (batchesTotal + 1 >= _triBatchesToDrawCapacity) {
- _triBatchesToDrawCapacity *= 1.4;
- _triBatchesToDraw = (TriBatchToDraw*) realloc(_triBatchesToDraw, sizeof(_triBatchesToDraw[0]) * _triBatchesToDrawCapacity);
- }
- prevMaterialID = currentMaterialID;
- firstCommand = false;
- }
- batchesTotal++;
-
- auto conf = Configuration::getInstance();
- if (conf->supportsShareableVAO() && conf->supportsMapBuffer())
- {
-
- GL::bindVAO(_buffersVAO);
-
- glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
-
-
-
-
-
-
- glBufferData(GL_ARRAY_BUFFER, sizeof(_verts[0]) * _filledVertex, nullptr, GL_STATIC_DRAW);
- void *buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
- memcpy(buf, _verts, sizeof(_verts[0]) * _filledVertex);
- glUnmapBuffer(GL_ARRAY_BUFFER);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(_indices[0]) * _filledIndex, _indices, GL_STATIC_DRAW);
- }
- else
- {
-
- #define kQuadSize sizeof(_verts[0])
- glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
- glBufferData(GL_ARRAY_BUFFER, sizeof(_verts[0]) * _filledVertex , _verts, GL_DYNAMIC_DRAW);
- GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);
-
- glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof(V3F_C4B_T2F, vertices));
-
- glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (GLvoid*) offsetof(V3F_C4B_T2F, colors));
-
- glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof(V3F_C4B_T2F, texCoords));
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(_indices[0]) * _filledIndex, _indices, GL_STATIC_DRAW);
- }
-
- for (int i=0; i<batchesTotal; ++i)
- {
- CC_ASSERT(_triBatchesToDraw[i].cmd && "Invalid batch");
- _triBatchesToDraw[i].cmd->useMaterial();
- glDrawElements(GL_TRIANGLES, (GLsizei) _triBatchesToDraw[i].indicesToDraw, GL_UNSIGNED_SHORT, (GLvoid*) (_triBatchesToDraw[i].offset*sizeof(_indices[0])) );
- _drawnBatches++;
- _drawnVertices += _triBatchesToDraw[i].indicesToDraw;
- }
-
- if (Configuration::getInstance()->supportsShareableVAO() && conf->supportsMapBuffer())
- {
-
- GL::bindVAO(0);
- }
- else
- {
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- }
- _queuedTriangleCommands.clear();
- _filledVertex = 0;
- _filledIndex = 0;
- }
- void Renderer::flush()
- {
- flush2D();
- flush3D();
- }
- void Renderer::flush2D()
- {
- flushTriangles();
- }
- void Renderer::flush3D()
- {
- if (_lastBatchedMeshCommand)
- {
- CCGL_DEBUG_INSERT_EVENT_MARKER("RENDERER_BATCH_MESH");
- _lastBatchedMeshCommand->postBatchDraw();
- _lastBatchedMeshCommand = nullptr;
- }
- }
- void Renderer::flushTriangles()
- {
- drawBatchedTriangles();
- }
- bool Renderer::checkVisibility(const Mat4 &transform, const Size &size)
- {
- auto scene = Director::getInstance()->getRunningScene();
-
-
-
- if (!scene || (scene && scene->_defaultCamera != Camera::getVisitingCamera()))
- return true;
- auto director = Director::getInstance();
- Rect visibleRect(director->getVisibleOrigin(), director->getVisibleSize());
-
-
- float hSizeX = size.width/2;
- float hSizeY = size.height/2;
- Vec3 v3p(hSizeX, hSizeY, 0);
- transform.transformPoint(&v3p);
- Vec2 v2p = Camera::getVisitingCamera()->projectGL(v3p);
-
- float wshw = std::max(fabsf(hSizeX * transform.m[0] + hSizeY * transform.m[4]), fabsf(hSizeX * transform.m[0] - hSizeY * transform.m[4]));
- float wshh = std::max(fabsf(hSizeX * transform.m[1] + hSizeY * transform.m[5]), fabsf(hSizeX * transform.m[1] - hSizeY * transform.m[5]));
-
-
- visibleRect.origin.x -= wshw;
- visibleRect.origin.y -= wshh;
- visibleRect.size.width += wshw * 2;
- visibleRect.size.height += wshh * 2;
- bool ret = visibleRect.containsPoint(v2p);
- return ret;
- }
- void Renderer::setClearColor(const Color4F &clearColor)
- {
- _clearColor = clearColor;
- }
- NS_CC_END
|