CocosCreator 渲染

CocosCreator 渲染,第1张

为什么我们拖一个图片到界面里就可以展示出来?

这中间发生了什么?

究竟是人性的扭曲还是……

欢迎收看本期栏目,CocosCreator究竟是怎么渲染的!

废话不多说直入主题,首先打开creator编译出的ios原生工程。

在工程在开始的AppDelegate.m文件中有这样两行代码,是启动creator游戏窗口的逻辑。

这里初始化了Application的单例,设定了屏幕的宽高,初始化了一个scheduler和一个MyTimer类的实例_timer。

game::init中首先调用了Application的init函数,然后绑定js和c++交互,最后启动js代码。

接着往下看到cc::Application::init();

 这里调用了之前初始化过的_timer的start函数。

那么MyTimer是什么呢?

他有一个Application的引用,初始化的时候把我们之前定义的Application赋值给此引用。

一个CADisplayLink的引用, CADisplayLink是ios提供的,一个能让我们以和屏幕刷新率同步的频率将特定的内容画到屏幕上的定时器类。 CADisplayLink以特定模式注册到runloop后, 每当屏幕显示内容刷新结束的时候,runloop就会向 CADisplayLink指定的target发送一次指定的selector消息, CADisplayLink类对应的selector就会被调用一次。现存的iOS设备屏幕的FPS都是60Hz,他的精度相当高。

还有一个_fps,可以自定义刷新帧率。

_timer的初始化函数把renderScene函数作为 CADisplayLink类对应的selector

MyTimer的start方法就是加入runloop开始不断调用renderScene。

renderScene里去调用了application的tick方法。

对于非ios设备,这里会让进程休眠,保持刷新频率(在上面#if #endif 代码中)。 

第一个红框里update就是我们所有定义的定时器 *** 作和事件分发,都会在这里调用。

下面就是cocos的自动回收池,简单了解一下自动回收池的概念:

cocos里有一个Ref类,是所有节点的父类。

class CC_DLL Ref {
public:
    void retain();
    void release();
    Ref *autorelease();
    unsigned int getReferenceCount() const;

protected:
    virtual ~Ref();

protected:
    unsigned int _referenceCount;
    friend class AutoreleasePool;
};

 它有一个引用计数,_referenceCount,当节点被创建出来后,就会调用Ref::retain()让_referenceCount++;准备销毁节点时就调用Ref::release(),让_referenceCount--;基本上通过create出来的节点都会调用autorelease(),自动加入到自动回收池中,在上面的时机会触发自动回收池的clear() *** 作,所有自动回收池里的节点都自动调用release,此时如果_referenceCount减为0了就销毁节点。

看到这里我忍不住确认了一下我的工程有没有打开错,因为目前来说直到这里,不能说和cocos2dx的工程一摸一样,只能说95%的相似。

不过确实有一件事让我困惑,怎么只有界面的clear,处理界面的代码去哪了?

功夫不负有心人,我在js绑定代码里找到了js代码的调用和接下去的流程。

再聊到接下去的部分就不得不提到渲染管线了。

渲染管线(rendering pipeline)到底是什么呢?

简单来说就是将场景转化为二维屏幕图像的一个过程。

从制作界面的场景里,最基础的是一个摄像机(Camera),他会模拟我们的眼睛看到视野,把看到的画面呈现在屏幕上。

摄像机有两种类型,一种是正交投影,一种是透视投影。

正交投影的效果就是图像的大小无视距离的远近,所有的东西展现在同一个平面上,我们所用的ui界面都是处于正交投影下,会有一个画布(Canvas),ui都处于画布下。

 透视投影的效果就是近大远小,物体会随着距离的远近变化大小,看板娘就是使用的此投影,只不过没有其他三维物品对比所以不明显。

渲染管线的知识非常的庞杂,不是我简短一篇文章所能讲完的,这里只是列举一些过程概念。

整个游戏场景空间里,除了摄像机,就是你所制造出来的物体,包括背景,地图,人物,各类ui,光源等等。

物体根据z值和构造顺序排序,不在摄像机视野里的就剔除,符合条件的就经过一系列变化,最终展示。

整个过程可以概括为以下:

application, geometry processing, rasterization, and pixel processing 应用阶段、几何处理阶段、光栅化阶段和像素处理阶段

应用阶段主要由应用程序驱动,包括碰撞检测、全局加速算法、动画、物理模拟以及许多其他功能,具体取决于应用程序的类型,因此通用在CPU上运行的软件中实现,其他阶段都是在GPU上实现。

几何处理阶段主要处理顶点着色、投影、裁剪和屏幕映射。

光栅化通常以三个顶点作为输入,形成一个三角形,并查找该三角形内考虑的所有像素。

像素处理阶段主要对最终形成的像素做处理,并做一些测试判断,通过判断后就把像素颜色填写到缓冲区内,等到缓冲区内的颜色都填写完成就可以准备把颜色刷新到屏幕上。

那么了解了渲染管线对我们来说有什么好处呢?

合批策略(drawcall):在整个渲染管线的流程中,别看CPU只占了一个阶段,GPU处理三个阶段,但是大多是时候都是GPU在摸鱼,等待CPU传达任务,对于GPU来说,渲染100个三角形网格和1000个三角形网格基本无差别。因为CPU需要处理GPU要用的数据,设置各种状态等,等这些都完成了才向GPU下达任务,之后进行一系列绘制,而这个过程就称为 drawcall。每个界面的drwacall数可以打开测试打印,在界面左下角就能看到。为了减少drawcall,cocos提供了合批策略,达到一定相同条件的物体会合并到同一个drawcall中去,以减少次数,提高性能。(具体代码我会在下一篇文章中给出,并辅以项目测试图。)着色器(shader):以前的渲染管线都是固定函数渲染管线,我们只能通过修改配置来 *** 控其中的一些过程,随着科技的进步,现在我们可以自己编写shader,来主导GPU的过程,在整个渲染管线中,我们能完全自主 *** 控的阶段有两个:顶点着色器和像素着色器。而shader和物体之间的联系就是材质,物体可以挂载材质,材质上着色程序会让物体展现出各种各样特殊的效果。

本篇文章先讲到这里,如果觉得我说的还不错,感谢点赞~

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/993114.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存