标签:
在Cocos2d-x 3.0的版本之前,Cocos2d-x的每个元素的绘制逻辑均分布于每个元素内部的draw()方法里,紧密依赖UI树的遍历;3.0开始,对绘制部分进行了重构,新的代码将绘制部分从UI树的遍历中分离出来,使得绘制系统设计更优雅、更灵活和易于扩展。
void Node::visit(Renderer* renderer, const Mat4 &parentTransform, uint32_t parentFlags) { // quick return if not visible. children won't be drawn. if (!_visible) { return; } uint32_t flags = processParentFlags(parentTransform, parentFlags); // IMPORTANT: // To ease the migration to v3.0, we still support the Mat4 stack, // but it is deprecated and your code should not rely on it _director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); _director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform); bool visibleByCamera = isVisitableByVisitingCamera(); int i = 0; if(!_children.empty()) { sortAllChildren(); // draw children zOrder < 0 for( ; i < _children.size(); i++ ) { auto node = _children.at(i); if (node && node->_localZOrder < 0) node->visit(renderer, _modelViewTransform, flags); else break; } // self draw if (visibleByCamera) this->draw(renderer, _modelViewTransform, flags); for(auto it=_children.cbegin()+i; it != _children.cend(); ++it) (*it)->visit(renderer, _modelViewTransform, flags); } else if (visibleByCamera) { this->draw(renderer, _modelViewTransform, flags); } _director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); // FIX ME: Why need to set _orderOfArrival to 0?? // Please refer to https://github.com/cocos2d/cocos2d-x/pull/6920 // reset for next frame // _orderOfArrival = 0; }
bool nodeComparisonLess(Node* n1, Node* n2) { return( n1->getLocalZOrder() < n2->getLocalZOrder() || ( n1->getLocalZOrder() == n2->getLocalZOrder() && n1->getOrderOfArrival() < n2->getOrderOfArrival() ) ); } void Node::sortAllChildren() { if (_reorderChildDirty) { std::sort(std::begin(_children), std::end(_children), nodeComparisonLess); _reorderChildDirty = false; } }
class CC_DLL RenderCommand { public: enum class Type { UNKNOWN_COMMAND, QUAD_COMMAND, CUSTOM_COMMAND, BATCH_COMMAND, GROUP_COMMAND, MESH_COMMAND, PRIMITIVE_COMMAND, TRIANGLES_COMMAND }; /** * init function, will be called by all the render commands */ void init(float globalZOrder, const Mat4& modelViewTransform, uint32_t flags); /** Get Render Command Id */ inline float getGlobalOrder() const { return _globalOrder; } //...其他定义省略 };
void Sprite::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) { #if CC_USE_CULLING // Don't do calculate the culling if the transform was not updated _insideBounds = (flags & FLAGS_TRANSFORM_DIRTY) ? renderer->checkVisibility(transform, _contentSize) : _insideBounds; if(_insideBounds) #endif { _quadCommand.init(_globalZOrder, _texture->getName(), getGLProgramState(), _blendFunc, &_quad, 1, transform, flags); renderer->addCommand(&_quadCommand); #if CC_SPRITE_DEBUG_DRAW _debugDrawNode->clear(); Vec2 vertices[4] = { Vec2( _quad.bl.vertices.x, _quad.bl.vertices.y ), Vec2( _quad.br.vertices.x, _quad.br.vertices.y ), Vec2( _quad.tr.vertices.x, _quad.tr.vertices.y ), Vec2( _quad.tl.vertices.x, _quad.tl.vertices.y ), }; _debugDrawNode->drawPoly(vertices, 4, true, Color4F(1.0, 1.0, 1.0, 1.0)); #endif //CC_SPRITE_DEBUG_DRAW } }
class CC_DLL RenderCommand { public: enum class Type { UNKNOWN_COMMAND, QUAD_COMMAND, CUSTOM_COMMAND, BATCH_COMMAND, GROUP_COMMAND, MESH_COMMAND, PRIMITIVE_COMMAND, TRIANGLES_COMMAND }; /** * init function, will be called by all the render commands */ void init(float globalZOrder, const Mat4& modelViewTransform, uint32_t flags); /** Get Render Command Id */ inline float getGlobalOrder() const { return _globalOrder; } };
class RenderQueue { public: enum QUEUE_GROUP { GLOBALZ_NEG = 0, OPAQUE_3D = 1, TRANSPARENT_3D = 2, GLOBALZ_ZERO = 3, GLOBALZ_POS = 4, QUEUE_COUNT = 5, }; public: RenderQueue() { clear(); } void push_back(RenderCommand* command); ssize_t size() const; void sort(); RenderCommand* operator[](ssize_t index) const; void clear(); inline std::vector<RenderCommand*>& getSubQueue(QUEUE_GROUP group) { return _commands[group]; } inline ssize_t getSubQueueSize(QUEUE_GROUP group) const { return _commands[group].size();} void saveRenderState(); void restoreRenderState(); protected: std::vector<std::vector<RenderCommand*>> _commands; //Render State related bool _isCullEnabled; bool _isDepthEnabled; GLboolean _isDepthWrite; };
static bool compareRenderCommand(RenderCommand* a, RenderCommand* b) { return a->getGlobalOrder() < b->getGlobalOrder(); } static bool compare3DCommand(RenderCommand* a, RenderCommand* b) { return a->getDepth() > b->getDepth(); } void RenderQueue::sort() { // Don't sort _queue0, it already comes sorted std::sort(std::begin(_commands[QUEUE_GROUP::TRANSPARENT_3D]), std::end(_commands[QUEUE_GROUP::TRANSPARENT_3D]), compare3DCommand); std::sort(std::begin(_commands[QUEUE_GROUP::GLOBALZ_NEG]), std::end(_commands[QUEUE_GROUP::GLOBALZ_NEG]), compareRenderCommand); std::sort(std::begin(_commands[QUEUE_GROUP::GLOBALZ_POS]), std::end(_commands[QUEUE_GROUP::GLOBALZ_POS]), compareRenderCommand); }
class CC_DLL GroupCommand : public RenderCommand { public: GroupCommand(); ~GroupCommand(); void init(float depth); inline int getRenderQueueID() const {return _renderQueueID;} protected: int _renderQueueID; };
class CC_DLL Renderer { public: static const int VBO_SIZE = 65536; static const int INDEX_VBO_SIZE = VBO_SIZE * 6 / 4; static const int BATCH_QUADCOMMAND_RESEVER_SIZE = 64; static const int MATERIAL_ID_DO_NOT_BATCH = 0; /** Adds a `RenderComamnd` into the renderer */ void addCommand(RenderCommand* command); /** Adds a `RenderComamnd` into the renderer specifying a particular render queue ID */ void addCommand(RenderCommand* command, int renderQueue); /** Pushes a group into the render queue */ void pushGroup(int renderQueueID); /** Pops a group from the render queue */ void popGroup(); /** returns whether or not a rectangle is visible or not */ bool checkVisibility(const Mat4& transform, const Size& size); protected: void processRenderCommand(RenderCommand* command); void visitRenderQueue(RenderQueue& queue); std::stack<int> _commandGroupStack; std::vector<RenderQueue> _renderGroups; MeshCommand* _lastBatchedMeshCommand; std::vector<TrianglesCommand*> _batchedCommands; std::vector<QuadCommand*> _batchQuadCommands; GroupCommandManager* _groupCommandManager; };
int GroupCommandManager::getGroupID() { //Reuse old id for(auto it = _groupMapping.begin(); it != _groupMapping.end(); ++it) { if(!it->second) { _groupMapping[it->first] = true; return it->first; } } //Create new ID // int newID = _groupMapping.size(); int newID = Director::getInstance()->getRenderer()->createRenderQueue(); _groupMapping[newID] = true; return newID; }
bool GroupCommandManager::init() { //0 is the default render group _groupMapping[0] = true; return true; }
_commandGroupStack.push(DEFAULT_RENDER_QUEUE); // DEFAULT_RENDER_QUEUE == 0
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(); }
标签:
原文地址:http://blog.csdn.net/jy_95/article/details/52296332