图1.16代码3
图1.17 autobatch效果3
修改代码后,芒果遮住了所有的葡萄(葡萄还发生了绘制),此时drawCall变成了3。这也正应正了前面的猜想。那么,我没修改Z-order是否会影响drawCall呢?答案是肯定的。修改代码如图1.18所示。我们可以看到,修改了Zorder,并没有使drawCall暴增,因为在绘制前,引擎会根据zOrder进行排序,所以此时drawCall为5。再对比一下帧数,我们可以发现,经过drawCall合并的渲染,效率提升了至少20个百分点。
图1.18代码4
图1.19 autobatch效果4
1.5 自定义RenderCommand
下面,我们开始进入正题,探究一下如何在2dx下写openGL代码。首先,我们依照惯例写个类,CustomRenderCommandTest:
class CustomRenderCommandTest : public cocos2d::Node { public: };
void CustomRenderCommandTest::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4& transform, uint32_t flags) { }
void CustomRenderCommandTest::onDraw(const cocos2d::Mat4& transform, uint32_t flags) { }
glClearColor(0.1f, 0.1f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_renderCommand.init(_globalZOrder);
m_renderCommand.func = CC_CALLBACK_0(CustomRenderCommandTest::onDraw, this, transform, _globalZOrder);
renderer->addCommand(&m_renderCommand); CustomRenderCommandTest(); ~CustomRenderCommandTest();
static CustomRenderCommandTest* create();
void draw(cocos2d::Renderer *renderer, const cocos2d::Mat4& transform, uint32_t void onDraw(const cocos2d::Mat4& transform, uint32_t flags); virtual bool init()override;
cocos2d::CustomCommand m_renderCommand;
flags)override; protected:
其实逻辑很简单,定义一个customRenderCommand,在draw初始化他,
使用CC_CALLBACK_0绑定一下onDraw函数(CC_CALLBACK_1,2,3,4指的是固定值参数,其宏定义的内容就是std::bind)。在onDraw里,我们简单的调用glClear函数,使屏幕变为蓝色。其效果如图1.20所示。
二. OpenGL简介
在上一章,我们已经了解了cocos2dx引擎的渲染流程,了解了如何在2dx下编写OpenGL代码。但问题又来了,到底该如何编写OpenGL代码么?且听在下分解。
2.1 OpenGL 渲染管线
OpenGL implements what’s commonly called a rendering pipeline, which is a sequence of processing stages for converting the data your application provides to OpenGL into a final rendered image.
咳咳,每天装个B,生活好甜蜜。上面那一段是OpenGL红宝书第八版上对OpenGL管线的描述。说管线就是把从程序输入的数据变为最终图像的一系列不同的程序阶段,也就是我们常说的渲染流水线。整个管线的流程,如图2.1所示。
图2.1 openGL 渲染管线
2.1.1 Vertex Shading
当我们向显卡发送渲染命令时,显卡会把显存中的顶点传入这个阶段。针对每一个顶点,程序员可以编写代码控制他的各项属性,如位置,颜色,纹理坐标,以及其他自定义属性。在可编程管线时代,把3D空间的顶点坐标转换为2D的平面的顶点坐标,也是在这一阶段实现的。在这一阶段之后,GPU会把各个顶点传入Tessellation Shading 和 Geometry Shading。这两个阶段我们现在不用关心,在以后的深入学习中,再去探讨。
2.1.2 Primitive Assembly
经过前面的一系列操作,显卡就会将前面的一系列顶点组装成图元,在ES系统下,通常是组装成三角形。传入下面一个阶段。
2.1.3 Clipping
组装好的图元将会被送进这个阶段。在这个阶段中,完全超出视图区域的将被完全丢弃,一部分超出剪裁区域的将被裁切成新的图元。
2.1.4 Rasterization
经过剪裁的图元将被送入这个阶段,进行光栅化操作。也就是把三角形进行填充,把顶点信息进行插值,这也是为什么给顶点设置不同的颜色,可以画出彩色方块的原因。如图2.2所示。
图2.2 彩色立方体