10.1.2 绘图
前面我们简单介绍了OpenGL的工作原理以及基本概念,在这一节中,我们将介绍OpenGL的几个绘图函数。随着OpenGL的发展,其提供的绘图函数也变得多种多样。对于同一个效果来说,常常有多种不同的实现方法,因此想要在此对OpenGL的绘图函数进行全方位的介绍是不可能的,这里我们只简单介绍Cocos2d-x中常用的绘图函数。
下面我们从一个简单的例子开始介绍,在这个例子中,我们需要向Cocos2d-x Hello World项目中添加一些代码。打开Hello World项目,并在"HelloWorldScene.h"中的HelloWorld类中重载void draw()方法:
- virtual void draw();
然后打开"HelloWorldScene.cpp"文件,在文件中加入以下代码:
- void HelloWorld::draw()
- {
- //顶点数据
- static GLfloat vertex[] = { //顶点坐标:x,y,z
- 0.0f, 0.0f, 0.0f, //左下
- 200.0f, 0.0f, 0.0f, //右下
- 0.0f, 200.0f, 0.0f, //左上
- 200.0f, 200.0f, 0.0f, //右上
- };
- static GLfloat coord[] = { //纹理坐标:s,t
- 0.0f, 1.0f,
- 1.0f, 1.0f,
- 0.0f, 0.0f,
- 1.0f, 0.0f,
- };
- static GLfloat color[] = { //颜色:红色、蓝色、绿色、不透明度
- 1.0f, 1.0f, 1.0f, 1.0f,
- 1.0f, 1.0f, 1.0f, 1.0f,
- 1.0f, 1.0f, 1.0f, 1.0f,
- 1.0f, 1.0f, 1.0f, 1.0f,
- };
- //初始化纹理
- static CCTexture2D* texture2d = NULL;
- if(!texture2d) {
- texture2d = CCTextureCache::sharedTextureCache()->addImage("HelloWorld.png");
- coord[2] = coord[6] = texture2d->getMaxS();
- coord[1] = coord[3] = texture2d->getMaxT();
- }
- //设置着色器
- ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex);
- texture2d->getShaderProgram()->use();
- texture2d->getShaderProgram()->setUniformForModelViewProjectionMatrix();
- //绑定纹理
- glBindTexture(GL_TEXTURE_2D, texture2d->getName());
- //设置顶点数组
- glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, 0, vertex);
- glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, coord);
- glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_FLOAT, GL_FALSE, 0, color);
- //绘图
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- }
运行Hello World项目,我们就可以看到在游戏画面的左下角出现了一个200×200大小的Cocos2d-x标志,如图10-6所示。
回顾一下刚才的代码,通过注释我们可以大概了解到draw方法中每一条语句的含义。draw大致上可以分为3个部分--数据部分、初始化纹理和绘图,它绘制了一个带纹理的矩形。事实上,我们也可以通过绘制一个"三角形带(triangle stripe)"来绘制。因为矩形实际上是两个包含公共斜边的直角三角形,所以绘制这样两个三角形,将它们的斜边相连,就可以拼成一个矩形。三角形带是计算机图形学中的一个重要概念,若要了解更多相关知识,可以参考任何一本计算机图形学方面的图书。
代码的第一部分是数据部分,在这一部分中我们声明了3个静态数组,它们分别是vertex、coord和color,对应了三角形带中共4个顶点的顶点坐标、纹理坐标和顶点颜色。每个数组均按照左下、右下、左上、右上的顺序来存储。
vertex:共4个顶点,每个顶点包含x、y和z三个分量,因此顶点坐标数组共有12个值。在本例中,矩形位于屏幕左下角,大小为200×200。
coord:包含s和t(横坐标和纵坐标)两个分量,因此共有8个值,每个分量的取值范围是0到1,需要根据纹理的属性确定取值。
color:包含r、g、b和a(红色、绿色、蓝色和不透明度)4个分量,因此共有16个值,每个分量的取值范围是0~1。把颜色值设为纯白(1, 1, 1, 1),则会显示纹理原来的颜色。
第二部分是初始化纹理。利用CCTextureCache类可以方便地从文件中载入一个纹理,获取纹理尺寸,以及获取纹理在OpenGL中的编号。在纹理没有被初始化时,我们首先使用CCTextureCache::addImage方法载入一个图片,把返回的CCTexture2D对象保存下来,并使用纹理的属性设置4个顶点的纹理坐标。对于单个纹理的图片,只需要按照上面代码中的方法设置纹理坐标即可。关于纹理坐标的细节,我们将在10.3.2节中详细介绍。
最后一部分是绘制图片。绘制图片的步骤可以简述为:绑定纹理、设置顶点数组和绘图。绑定纹理是指把一个曾经载入的纹理当做当前纹理,从此绘制出来的多边形都使用此纹理。设置顶点数组是指为OpenGL指定第一步准备好的顶点坐标数组、纹理坐标数组以及顶点颜色数组。绘图则是最终通知OpenGL如何利用刚才提供的信息进行绘图,并实际把图形绘制出来。在这个过程中,我们可以看到最重要的一个函数为glDrawArrays(GLenum mode, GLint first, GLsizei count),其中mode指定将要绘制何种图形,first表示前面数组中起始顶点的下标,count表示即将绘制的图形顶点数量。