标签:
在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