Cocos2d-x 渲染器Renderer

渲染队列RenderQueue
RenderQueue
遍历场景时会生成渲染命令,生成的渲染命令存储在渲染队列中。渲染队列RenderQueue会将命令分层5类存储,分别是:

class RenderQueue {
public:
    /**
    RenderCommand will be divided into Queue Groups.
	渲染队列RenderQueue把渲染命令分成五种存储
    */
    enum QUEUE_GROUP
    {
        /**Objects with globalZ smaller than 0. globalZ< 0的命令*/
        GLOBALZ_NEG = 0,
        /**Opaque 3D objects with 0 globalZ. globalZ=0的不透明3D命令*/
        OPAQUE_3D = 1,
        /**Transparent 3D objects with 0 globalZ. globalZ=0的3D透明命令*/
        TRANSPARENT_3D = 2,
        /**2D objects with 0 globalZ. globalZ=0的2D命令*/
        GLOBALZ_ZERO = 3,
        /**Objects with globalZ bigger than 0.globalZ>0的命令 */
        GLOBALZ_POS = 4,
        QUEUE_COUNT = 5,
    };
    std::vector<RenderCommand*> _commands[QUEUE_COUNT];

}


其中的globalZ对应节点的_globalZOrder。globalZ=0的命令分成了三种首先按3D、2D进行分类,然后3D还分成是否透明。这样分类的原因是:2D、3D在显示画面先后顺序时,2D一般由绘制的先后顺序决定,而3D则会使用深度缓存;3D 分成是否透明是因为透明物体显示跟绘制命令的先后顺序有关(具体参考《OpenGL编程指南(第八版)》11.4.1顺序无关透明),所以3D透明队列再绘制前需要按照绘制物体的深度进行排序。

命令排序:GLOBALZ_NEG、GLOBALZ_POS、TRANSPARENT_3D命令在绘制前会进行排序,GLOBALZ_NEG、GLOBALZ_POS会根据globalZ的值从小到大排序,TRANSPARENT_3D会根据绘制物体的深度(离摄像机的远近)进行排序。

 

Renderer类种并不是只有一个RenderQueue,而有一个RenderQueue的数组_renderGroups,之所以这样是因为渲染有时某些命令需要单独设置一些状态,例如使用模板缓存实现“镂空”绘制等,这时就需要一个单独的RenderQueue去创建一个渲染分支实现,以防止影响全局绘制。

class CC_DLL Renderer
{   
 std::vector<RenderQueue> _renderGroups;
}

渲染都是从_renderGroups[0]开始绘制,如果不使用渲染分支,也就只会用到_renderGroups[0]一个RenderQueue。如果想使用其他的RenderQueue创建渲染分支,需要使用GroupCommand渲染命令。

处理渲染命令
处理步骤如下:

对_renderGroups的每个RenderQueue中的命令进行排序
使用函数visitRenderQueue访问_renderGroups[0]中的命令,访问顺序为GLOBALZ_NEG、OPAQUE_3D、TRANSPARENT_3D、GLOBALZ_ZERO、GLOBALZ_POS。访问每个渲染命令数组访问时会先设置好OpenGL的状态,然后再用函数processRenderCommand处理渲染命令。
processRenderCommand处理渲染,按渲染命令类型对么每个命令进行渲染
 

渲染命令

一共有6种渲染命令,每种命令类型对应一个类,这些类都继承至RenderCommand类,对应关系以及作用如下:
TRIANGLES_COMMAND:TrianglesCommand,渲染三角形,可以合并命令减少OpenGL的调用提高渲染效率
MESH_COMMAND:MeshCommand,渲染3D
GROUP_COMMAND:GroupCommand,创建渲染分支,使用_renderGroups[0]之外的RenderQueue
CUSTOM_COMMAND:CustomCommand,自定义渲染命令
BATCH_COMMAND:BatchCommand,同时渲染多个使用同一纹理的图形,提高渲染效率
PRIMITIVE_COMMAND:PrimitiveCommand,渲染自定义图元。

class CC_DLL RenderCommand
{
public:
    /**Enum the type of render command. */
    enum class Type
    {
        /** Reserved type.*/
        UNKNOWN_COMMAND,
        /** Quad command, used for draw quad.*/
        QUAD_COMMAND, //可以合批渲染
        /**Custom command, used for calling callback for rendering.*/
        CUSTOM_COMMAND,
        /**Batch command, used for draw batches in texture atlas.*/
        BATCH_COMMAND,
        /**Group command, which can group command in a tree hierarchy.*/
        GROUP_COMMAND,
        /**Mesh command, used to draw 3D meshes.*/
        MESH_COMMAND,
        /**Primitive command, used to draw primitives such as lines, points and triangles.*/
        PRIMITIVE_COMMAND,
        /**Triangles command, used to draw triangles.*/
        TRIANGLES_COMMAND //可以合批渲染
    };
}

接下来由易到难对每种命令单独讲解,并用Node类实现相应的命令,因为渲染跟OpenGL紧密相关,这一块需要OpenGL的知识才能完全理解。

CustomCommand
CustomCommand是所有命令中最简单的一个,也是最灵活的一个,绘制的内容和方式完全交由我们自己决定。LayerColor、DrawNode、Skybox等待都是使用CustomCommand命令进行绘制的。

CustomCommand有一个std::function<void()> func变量,当Renderer处理CustomCommand时只是简单的调用func函数,以下是Renderer中的代码:

void Renderer::processRenderCommand(RenderCommand* command)
{

    else if(RenderCommand::Type::CUSTOM_COMMAND == commandType)
    {
        flush();
        auto cmd = static_cast<CustomCommand*>(command);
        CCGL_DEBUG_INSERT_EVENT_MARKER("RENDERER_CUSTOM_COMMAND");
        cmd->execute();
    }

}
void CustomCommand::execute()
{
    if(func)
    {
        func();
    }
}


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值