当遍历场景树,搜索可渲染的节点,并添加到渲染器时,渲染指令就被添加到了渲染器的渲染队列中
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);
}
一个渲染队列又分为5个组:
enum QUEUE_GROUP
{
/**Objects with globalZ smaller than 0.*/
GLOBALZ_NEG = 0,
/**Opaque 3D objects with 0 globalZ.*/
OPAQUE_3D = 1,
/**Transparent 3D objects with 0 globalZ.*/
TRANSPARENT_3D = 2,
/**2D objects with 0 globalZ.*/
GLOBALZ_ZERO = 3,
/**Objects with globalZ bigger than 0.*/
GLOBALZ_POS = 4,
QUEUE_COUNT = 5,
};
渲染顺序为GLOBALZ_NEG->OPAQUE_3D->TRANSPARENT_3D->GLOBALZ_ZERO->GLOBALZ_POS,后渲染的会盖住先渲染的,透明物体除外。当渲染指令添加到渲染队列时,会根据渲染指令的情况添加到对应的渲染组中。
void RenderQueue::push_back(RenderCommand* command)
{
float z = command->getGlobalOrder();
if(z < 0)
{
/*存入globalz<0的渲染组*/
_commands[QUEUE_GROUP::GLOBALZ_NEG].push_back(command);
}
else if(z > 0)
{
/*存入globalz>0的渲染组*/
_commands[QUEUE_GROUP::GLOBALZ_POS].push_back(command);
}
else
{
/*globalz=0又分3种情况*/
if(command->is3D())
{
/*3d透明渲染组*/
if(command->isTransparent())
{
/*3d透明渲染组*/
_commands[QUEUE_GROUP::TRANSPARENT_3D].push_back(command);
}
else
{
/*3d不透明渲染组*/
_commands[QUEUE_GROUP::OPAQUE_3D].push_back(command);
}
}
else
{
/*2d渲染组*/
_commands[QUEUE_GROUP::GLOBALZ_ZERO].push_back(command);
}
}
}
渲染前,会对渲染对象进行排序,并不会对所有的渲染组进行排序,globalzorder为0的已经排好序,但是透明3d物体需要按距视点的深度排序。
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);
}
渲染renderqueue时,需要改变一些全局设置,需要保存改变前的全局设置,渲染后再恢复全局设置
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();
}
处理renderqueue中的渲染指令,也就是进行渲染,这里可以看出渲染顺序,和渲染状态的保存恢复
void Renderer::visitRenderQueue(RenderQueue& queue)
{
/*保存全局渲染状态*/
queue.saveRenderState();
//
//Process Global-Z < 0 Objects
//
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 (auto it = zNegQueue.cbegin(); it != zNegQueue.cend(); ++it)
{
processRenderCommand(*it);
}
flush();
}
//
//Process Opaque Object
//
const auto& opaqueQueue = queue.getSubQueue(RenderQueue::QUEUE_GROUP::OPAQUE_3D);
if (opaqueQueue.size() > 0)
{
//Clear depth to achieve layered rendering
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 (auto it = opaqueQueue.cbegin(); it != opaqueQueue.cend(); ++it)
{
processRenderCommand(*it);
}
flush();
}
//
//Process 3D Transparent object
//
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 (auto it = transQueue.cbegin(); it != transQueue.cend(); ++it)
{
processRenderCommand(*it);
}
flush();
}
//
//Process Global-Z = 0 Queue
//
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 (auto it = zZeroQueue.cbegin(); it != zZeroQueue.cend(); ++it)
{
processRenderCommand(*it);
}
flush();
}
//
//Process Global-Z > 0 Queue
//
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 (auto it = zPosQueue.cbegin(); it != zPosQueue.cend(); ++it)
{
processRenderCommand(*it);
}
flush();
}
/*恢复全局渲染状态*/
queue.restoreRenderState();
}