Cocos2dx3.0版本后渲染引入了OpenGlES3.0相关特性,使用了DrawNode类来进行绘制,那么我们就来看看DrawNode类具体是如何绘制点线面的:
我们在DrawNode.cpp中可以看到DrawNode类提供了画点drawPoint()、画线drawLine()、画矩形drawRect()、画多边形drawPoly()、画矩形面drawSolidRect()、画多边形面drawSolidPoly()等等方法。
接下来我们以drawLine()这个方法为例,看下cocos到底是如何绘制图形的:
void DrawNode::drawLine(const Vec2 &origin, const Vec2 &destination, const Color4F &color) { ensureCapacityGLLine(2); V2F_C4B_T2F *point = (V2F_C4B_T2F*)(_bufferGLLine + _bufferCountGLLine); V2F_C4B_T2F a = {origin, Color4B(color), Tex2F(0.0, 0.0)}; V2F_C4B_T2F b = {destination, Color4B(color), Tex2F(0.0, 0.0)}; *point = a; *(point+1) = b; _bufferCountGLLine += 2; _dirtyGLLine = true; }
该方法参数为终点、起点坐标、颜色值。
首先把参数传来的值赋给了V2F_C4B_T2F类型的变量,这个V2F_C4B_T2F是什么类型呢?我们看看:我们在ccTypes.h文件中可以找到对V2F_C4B_T2F的定义:
struct V2F_C4B_T2F { /// vertices (2F) Vec2 vertices; /// colors (4B) Color4B colors; /// tex coords (2F) Tex2F texCoords; };
原来V2F_C4B_T2F是一个结构体,里面点坐标、颜色值还有个Tex2F类型的成员。
回过头来,刚刚只是把绘制信息存储起来,那么drawLine具体绘制的方法在哪里呢?
我们可以在DrawNode.cpp中找到onDrawGLLine()方法,绘制线就是在这个方法里面进行的:
void DrawNode::onDrawGLLine(const Mat4 &transform, uint32_t flags) { //得到用于存储管理GL编程对象的shader着色器单例 auto glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_LENGTH_TEXTURE_COLOR); //使用shader glProgram->use(); //设置shader的一些内置uniform glProgram->setUniformsForBuiltins(transform); GL::blendFunc(_blendFunc.src, _blendFunc.dst); if (_dirtyGLLine) { //绑定一个新缓冲区 //同时把之前的一些缓冲区数据清掉 glBindBuffer(GL_ARRAY_BUFFER, _vboGLLine); //去申请存放传来数据的相关内存 glBufferData(GL_ARRAY_BUFFER, sizeof(V2F_C4B_T2F)*_bufferCapacityGLLine, _bufferGLLine, GL_STREAM_DRAW); _dirtyGLLine = false; } //根据VAO还是VBO的顶点绘制方式进行不同处理 //在OpenGL2.0时只有VBO顶点绘制方式,VAO是OpenGL3.0后的特性 //VAO比VBO即省内存又提高渲染效率 if (Configuration::getInstance()->supportsShareableVAO()) { GL::bindVAO(_vaoGLLine); } else { glBindBuffer(GL_ARRAY_BUFFER, _vboGLLine); //激活attribute GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX); // 给vertex指定数据源 glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, vertices)); // 给color指定数据源 glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, colors)); // 给texcood指定数据源 glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(V2F_C4B_T2F), (GLvoid *)offsetof(V2F_C4B_T2F, texCoords)); } //设置线的宽度 glLineWidth(_lineWidth); glDrawArrays(GL_LINES, 0, _bufferCountGLLine); if (Configuration::getInstance()->supportsShareableVAO()) { GL::bindVAO(0); } glBindBuffer(GL_ARRAY_BUFFER, 0); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,_bufferCountGLLine); CHECK_GL_ERROR_DEBUG(); }
好了,其他的图形绘制方法基本大同小异都是这个流程,如果你想深入理解,最好学习一下OpenGL的相关知识。
接下来我们就使用DrawNode类来进行一些图形绘制:
//创建DrawNode对象 auto dNode = DrawNode::create(); //将DrawNode对象添加到HelloWorld的layer上 this->addChild(dNode);
1.绘制点
//绘制点 //参数:坐标、大小、颜色 //Color4F的4个参数:R、B、G、alpha,范围0~1 dNode->drawPoint(Vec2(200,200),20,Color4F(1,0,0,1));
2.绘制线
//绘制线 //参数:起点坐标、终点坐标、颜色 dNode->drawLine(Vec2(200,200),Vec2(400,400),Color4F(0,0,1,1));
3.绘制Bezier曲线
//绘制Bezier曲线 //参数:起点坐标、控制点坐标、终点坐标、段数、颜色 //CCRANDOM_0_1()为获得0~1之间随机数的宏 //二级贝塞尔曲线 dNode->drawQuadBezier(Vec2(200, 200), Vec2(100, 300), Vec2(500, 200), 15, Color4F(0, 1, 0, 1)); //高阶贝塞尔曲线 dNode->drawCubicBezier(Vec2(200, 200), Vec2(300, 300), Vec2(450, 200), Vec2(150, 100), 10, Color4F(CCRANDOM_0_1(), CCRANDOM_0_1(), CCRANDOM_0_1(), 1));
4.绘制三角形
//绘制三角形 //参数:顶点坐标、颜色 dNode->drawTriangle(Vec2(200, 300), Vec2(400, 300), Vec2(300, 400), Color4F(1, 0, 0, 1));
5.绘制矩形
//绘制矩形 //参数:左下角顶点坐标、右上角顶点坐标、颜色 dNode->drawRect(Vec2(300, 300), Vec2(400, 400), Color4F(1, 0, 0, 1));
6.绘制圆形
//绘制圆形 //参数:圆心坐标、半径、角度(弧度)、段数、是否有线连到圆心、横、纵坐标缩放、颜色 dNode->drawCircle(Vec2(480, 320), 100, CC_DEGREES_TO_RADIANS(90), 20, true, 1, 1, Color4F(1, 0, 0, 1));
7.绘制多边形
//绘制多边形 //参数:顶点坐标数组、顶点数、是否封闭、颜色 Vec2 vertices[] = { Vec2(100, 100), Vec2(150, 150), Vec2(200, 150), Vec2(200,200), Vec2(150, 200)}; dNode->drawPoly(vertices, 5, true, Color4F(1, 0, 0, 1));
8.绘制矩形面
//绘制矩形面 //参数:左下角顶点坐标、右上角顶点坐标、颜色 dNode->drawSolidRect(Vec2(300, 300), Vec2(400, 400), Color4F(1, 0, 0, 1));
其他绘制面的方法基本也和绘制线的相同,参数基本一样,只是方法名多了“Solid”。
以上。