【学习总结】COCOS的渲染流程

秋招了秋招了,再不写点总结就寄了,由于我最爱的Unity底层代码看不到,所以只能从COCOS底层的渲染过程大致揣测一下Unity的做法

关于COCOS渲染流程的一些总结

  1. 首先,COCOS组织整个项目资源的方式是通过资源树来进行的。据以往学习到的知识来看,使用资源树最大的好处是方便做空间划分然后剔除掉不用渲染和处理的部分,(四叉树,八叉树等空间划分法加速处理过程)。因为只要一个节点不在相机范围之内,那么这个节点之后的所有子节点全部都可以不用渲染了
  2. COCOS也有类似Unity那样渲染队列的处理。对属于不同的渲染队列的资源,则调用他们自己的排序方法进行一个正确的绘制
  3. COCOS2D-X里面也有Z分量(我之前一直以为是层级绘制的方法来做遮挡的),这个Z分量控制了精灵组件的绘制顺序
  4. 即使是2D-X,在GPU渲染管线上的处理也没有特别的地方(2D,3D同一套),底层依然是使用的OpenGL来实现的
  5. visit()方法是关键,重点分析在后面

COCOS渲染流程的启动

在这里插入图片描述

  1. 首先我们找到一个游戏场景的最开始,也就是Main.cpp文件。在Main文件中启动了Simulator的线程。
  2. 在这个类中创建了COCOS的游戏入口,AppDelegate(),同时还创建了Application并且启动了线程的run()方法。在AppDelegate()中可以看到有一个方法为applicationDidFinishLauching()。这个方法是等待Application运行完毕之后执行的,可以看到AppDelegate的初始化操作都放在了这个函数下面。因此,Application是在进入游戏之前,COCOS更早启动的流程
  3. 在CCApplication-win32.cpp中,可以找到步骤2被启动的run()方法的具体实现,最关键的一环为调用导演类的mainLoop()函数,可以认为是从这里开启了整个游戏的主循环
  4. mainLoop()中调用了drawScene()方法,而这个方法就是绘制场景的入口方法了。其中drawScence->render()则调用到了渲染部分,最后通过CCScene中的render()方法开始绘制整个资源树
    在这里插入图片描述
  5. render()方法调用了visit(),visit()是最关键的遍历算法,下面会单独讲
  6. 在visit()方法中,我们递归遍历场景的子节点,然后逐个调用draw不同子类的draw()方法。这里的draw方法是CCNode中的虚函数,每一个子类都有不同的实现方法,这里我们只讨论较为复杂的Sprite节点
  7. 在draw()方法中,基本都会调用到addCommand()方法将渲染指令推入渲染队列(下面那张图),这里的_renderGroup来自于COCOS的渲染队列分类,有点类似于Unity渲染队列的分类,这样就可以调用不同的个排序方法来排序场景元素最终得到正确的渲染结果
  8. 当将渲染命令推入渲染队列之后,就会调用CCRender的render()中的visitRenderQueue()方法,在这个方法中,根据_renderGroups的不同调用了不同的绘制方法,不过最终都调用到了processRenderCommand()方法
  9. 同样的,在processRenderCommand()方法中,也是根据类型的不同调用了不同的图元绘制方法。分别为Triangle,Quad和Mesh
    10.这些图元绘制方法最后都指向了glDrawElements方法,这个是OpenGL根据EBO绘制图像的基本方法,也就是所谓的DrawCall,之后所有的过程就在GPU,也就是渲染管线上面完成了
    关于渲染管线则可以看我这一篇文章:
    渲染管线入门
    在这里插入图片描述

Visit()方法做了什么

  1. 第一部分是一些先行的处理,例如当此节点被设置为不可见时,则直接返回不进行绘制等。在这一步中,最重要的环节是保存当前的绘图矩阵,也就是代码里面pushMatrix和loadMatrix。因为CCNode维护了模型视图的变换矩阵,会由父亲节点的模型视图变换矩阵右乘当前节点在本地坐标系中的变换矩阵得到。在遍历时,根节点的变换矩阵变为单位矩阵,依次向下传递自身的模型视图变换矩阵来计算元素的模型变换矩阵,最后这个变换矩阵连同元素相关信息一起被传入OpenGL ES渲染管线,并通过传递右乘的方式,有利于确保父节点下面的子节点都跟父亲做相同的模型视图变换,如根节点缩放并位移,其子节点也会进行相同的矩阵变换
  2. 第二部分是调用transform方法进行变换,在node->visit这个重载方法中,以便把自己以及子节点绘制到正确的位置上
  3. 经过第二部分的变换后,我们得到了一个正确的坐标系,接下来第三部分则开始绘图。visit方法中包含了一个判断:如果节点不包含子节点,则直接绘制自身。如果节点包含子节点,则需要对子节点进行遍历,具体的方式为首先对子节点按照ZOrder由小到大排序,首先对Zorder小于0的节点调用其visit方法进行绘制,然后在绘制自身,最后把ZOrder大于0的子节点绘制出来。经过这一轮的递归,以自己为根节点的整个渲染树包括其子树就都绘制完成了
  4. 最后是第四部分,进行绘制后的一些恢复工作。这一步中最重要的内容就是把之前压栈中的矩阵弹出来,把当前矩阵恢复成压栈的样子
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Cocos Creator 中,你可以使用自定义材质来实现顶点着色渲染。顶点着色渲染是一种在渲染管线中对模型的每个顶点进行颜色计算的技术,通过改变顶点的颜色来实现特定效果。下面是一个简单的示例代码: ```javascript // 在节点上添加一个脚本组件 VertexColor.js cc.Class({ extends: cc.Component, properties: { color: cc.Color.WHITE, // 自定义颜色 }, // 在渲染组件的 updateMaterial 方法中设置材质的属性 updateMaterial: function() { var material = this.getComponent(cc.RenderComponent).getMaterial(0); // 获取渲染组件的材质 material.setProperty('u_color', this.color); // 设置自定义颜色属性 }, // 在 onLoad 方法中注册 updateMaterial 方法到渲染组件的 updateMaterial 方法中 onLoad: function() { this.getComponent(cc.RenderComponent).updateMaterial = this.updateMaterial.bind(this); }, }); ``` 在上述代码中,我们假设节点上有一个渲染组件(如 Sprite、Mesh 等),我们通过自定义脚本组件 `VertexColor.js` 来实现顶点着色渲染。脚本组件中定义了一个 `color` 属性,用于设置自定义颜色。在 `updateMaterial` 方法中,我们获取渲染组件的材质,并设置自定义颜色属性。最后,在 `onLoad` 方法中将 `updateMaterial` 方法注册到渲染组件的 `updateMaterial` 方法中,以便在每帧更新时调用。 然后,你可以在 Cocos Creator 编辑器中将该脚本组件 `VertexColor.js` 添加到需要进行顶点着色渲染的节点上。在脚本组件的属性面板中,可以设置自定义的颜色值。 需要注意的是,顶点着色渲染需要使用支持顶点着色的材质和渲染组件,例如使用自定义的 Shader 或在材质中设置相应的 Uniform 属性等。具体的实现方式和效果可以根据你的需求和场景进行自定义调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值