缩略渲染过程
1、
DisplayLinkDirector
::mainLoop()
{ drawScene }
2、
|
程序的主循环
|
-->DisplayLinkDirector::drawScene() { _runningScene->visit _renderer->render();
}
3、
|
在drawScene里面的一句代码_runningScene->visit
|
-->visit(_renderer,Mat4::IDENTITY,false); { if(!_children.empty()) { sortAllChildren(); this->draw } else { this->draw}
}
4、
|
递归visit |
Sprite::draw() { 产生渲染命令
}
5、
|
产生渲染命令
|
-->voidRenderer::visitRenderQueue(constRenderQueue&queue) { if(RenderCommand::Type::QUAD_COMMAND) elseif(RenderCommand::Type::GROUP_COMMAND) elseif(RenderCommand::Type::CUSTOM_COMMAND) elseif(RenderCommand::Type::BATCH_COMMAND==commandType) elseif(RenderCommand::Type::MESH_COMMAND==commandType) else
}
|
在drawScene里面的一句代码_renderer->render(); 排序渲染队列执行opengl命令 |
{
{
purgeDirector();
}
{
drawScene();
// release the objects
PoolManager
::getInstance()->getCurrentPool()->clear();
}
}
上面是主循环函数 有个drawScene 跟踪进去
// draw the scene
{
_eventDispatcher->dispatchEvent(_eventAfterVisit);//事件分发 在每一帧的绘制里面
}
_renderer->render();
上面的visit是产生渲染队列的,上面有个render跟踪进去
{
//Uncomment this once everything is rendered by new renderer
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//TODO setup camera or MVP
{
// cleanup
_drawnBatches = _drawnVertices = 0;
//Process render commands
//1. Sort render commands based on ID
{
renderqueue.sort();
}
visitRenderQueue(_renderGroups[0]);
flush();
}
clean();
}
渲染队列排序 之后到函数
{
ssize_t
size =
queue
.size();
{
{
//Batch quads
{
CCASSERT
(cmd->getQuadCount()>= 0 && cmd->getQuadCount() < VBO_SIZE,
"VBO is not big enough for quad data,please break the quad data down or use customized render command"
);
//Draw batched quads if VBO is full
drawBatchedQuads();
}
_batchedQuadCommands.push_back(cmd);
memcpy(_quads + _numQuads,cmd->getQuads(),
@H_403_448@sizeof
(
V3F_C4B_T2F_Quad
) * cmd->getQuadCount());
convertToWorldCoordinates(_quads + _numQuads,cmd->getQuadCount(),cmd->getModelView());
_numQuads += cmd->getQuadCount();
}
{
flush();
visitRenderQueue(_renderGroups[renderQueueID]);
}
{
flush();
cmd->execute();
}
{
flush();
cmd->execute();
}
{
flush();
cmd->execute();
}
{
CCLOGERROR
(
"Unknown commands in renderQueue"
);
}
}
}
3.0之前是visit后就draw,而draw是真正的OpenGL操作。也就是说,每访问一个对象,先计算节点的渲染数据,然后马上渲染。
3.0也是在visit后就draw,但是draw并不进行OpenGL操作。3.0抽象了一个RenderCommand,在draw的时候其实是生成一个渲染命令,渲染命令其实就是对渲染所需要的数据的封装。RenderCommand作为基类,只包含了两个成员,一个是命令类型_type,这个很必要,正是靠这个来获取子类对象的具体类型的,这里没有用运行时类型,应该是考虑到效率;另一个是z深度_globalOrder,这个也很必要,渲染的时候必然要对节点排序,而z序是唯一的依据。
3.0包含了以下几个RenderCommand的子类:
1,CustomCommand:
顾名思义,是客户自定义的。
使用CustomCommand还有Layer,LableAtlas,LabelBMFont
2,QuadCommand:
和CustomCommand不同,这个类包含了很多属性:纹理_textureID,Program _shader,混合函数_blendType,定点数据_quad,模型视图矩阵_mv,还有一个材质属性_materialID。。
值得一提的是3.0主要是对QuadCommand进行了优化,实际上游戏中也大多数是这种情况。在Render::render()函数中,如果当前是QuadCommand,则顶点和Command放入数组,如果是其它,则先渲染此前的QuadCommand数组,然后再渲染当前命令。
使用CustomCommand命令的类有Sprite,ParticleSystemQuad,而Sprite应该是游戏中最常用的类,所以3.0的优化还是很有意义的。
3,BatchCommand
看名字就知道,BatchCommand是CCSpriteBatchNode的改进,而事实上,也的确是CCSpriteBatchNode和CCPaticleBatchNode使用了BatchCommand。BatchCommand的属性和QuadCommand很相似,不过没有了顶点数据_quad,变成了_textureAtlas,其渲染函数也和此前的差别不大,都是材质三剑客(shader,texutre,blend)
4,GroupCommand:
这是一个Command组合,但是GroupCommand只有一个属性_renderQueueID,而GroupCommand的所有子Command其实存放在Render中。GroupCommand像其它Command一样,存放在同一个队列中,遍历的时候,如果是GroupCommand,则获取其_renderQueueID,然后根据_renderQueueID找到指定的RenderCommand队列,进而渲染这个队列。可见,在Render中,可以包含多个Command队列,一些是根节点队列(没有父Command),其它的是指定ID的GroupCommand的子命令队列。
使用GroupCommand的主要有RenderTexture,因为RenderTexture包含了两次分隔的渲染操作,一次是begin(),一次是end()。
命令从哪里来的呢????
这个是刚刚的visit函数:
@H_403_448@void
Node
::visit(
Renderer
*
renderer
,
@H_403_448@const
Mat4
&
parentTransform
,
@H_403_448@bool
parentTransformUpdated
)
{
// quick return if not visible. children won't be drawn.
{
}
// 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
* director =
Director
::getInstance();
director->pushMatrix(
MATRIX_STACK_TYPE
::
MATRIX_STACK_MODELVIEW
);
director->loadMatrix(
MATRIX_STACK_TYPE
::
MATRIX_STACK_MODELVIEW
,_modelViewTransform);
{
sortAllChildren();
// draw children zOrder < 0
{
node->visit(
renderer
,_modelViewTransform,dirty);
}
// self draw
(*it)->visit(
renderer
,dirty);
}
{
}
// reset for next frame
_orderOfArrival = 0;
director->popMatrix(
MATRIX_STACK_TYPE
::
MATRIX_STACK_MODELVIEW
);
}
看到源码如果没有儿子了 那么调用draw Node:draw是空的 因为node不画 画的是sprite这些
@H_403_448@void
Sprite
::draw(
Renderer
*
renderer
,
@H_403_448@const
Mat4
&
transform
,
@H_403_448@bool
transformUpdated
)
{
// Don't do calculate the culling if the transform was not updated
_insideBounds =
transformUpdated
?
renderer
->checkVisibility(
transform
,_contentSize) : _insideBounds;
{
_quadCommand.init(_globalZOrder,_texture->getName(),getGLProgramState(),_blendFunc,&_quad,1,
transform
);
renderer
->addCommand(&_quadCommand);
_customDebugDrawCommand.init(_globalZOrder);
renderer->addCommand(&_customDebugDrawCommand);
}
}