Cocos2dx-OpenGL ES2.0教程:你的第一个立方体(5)

转载 2015年11月18日 16:30:17

上篇文章中,我们介绍了VBO索引的使用,使用VBO索引可以有效地减少顶点个数,优化内存,提高程序效率。

本教程将带领大家一起走进3D–绘制一个立方体。其实画立方体本质上和画三角形没什么区别,所有的模型最终都要转换为三角形。

同时,本文还会介绍如何通过修改MVP矩阵来让此立方体不停地旋转。另外,大家还可以动手去修改本教程的示例代码,借此我们可以更加深入地理解OpenGL的normalized device space。

准备立方体数据

在开始真正的绘制代码之前,我们先要准备好数据。首先,我们需要改进的是代表顶点属性的结构体:

1
2
3
4
 typedef struct {
        float Position[3];
        float Color[4];
} Vertex;

这里,我们把Position从一个长度为2的数组变成了一个长度为3的数组,用于存储顶点的xyz的值。

接下来是顶点数据,因为一共有6个面。每个面由二个三角形组成,因此需要4个顶点,那么整个立方体就需要4*6=24个顶点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Vertex data[] =
   {
       // Front
       { {1, -1, 0}, {1, 0, 0, 1}},
       { {1, 1, 0}, {0, 1, 0, 1}},
       { {-1, 1, 0}, {0, 0, 1, 1}},
       { {-1, -1, 0}, {0, 0, 0, 1}},
       // Back
       { {1, 1, -2}, {1, 0, 0, 1}},
       { {-1, -1, -2}, {0, 1, 0, 1}},
       { {1, -1, -2}, {0, 0, 1, 1}},
       { {-1, 1, -2}, {0, 0, 0, 1}},
       // Left
       { {-1, -1, 0}, {1, 0, 0, 1}},
       { {-1, 1, 0}, {0, 1, 0, 1}},
       { {-1, 1, -2}, {0, 0, 1, 1}},
       { {-1, -1, -2}, {0, 0, 0, 1}},
       // Right
       { {1, -1, -2}, {1, 0, 0, 1}},
       { {1, 1, -2}, {0, 1, 0, 1}},
       { {1, 1, 0}, {0, 0, 1, 1}},
       { {1, -1, 0}, {0, 0, 0, 1}},
       // Top
       { {1, 1, 0}, {1, 0, 0, 1}},
       { {1, 1, -2}, {0, 1, 0, 1}},
       { {-1, 1, -2}, {0, 0, 1, 1}},
       { {-1, 1, 0}, {0, 0, 0, 1}},
       // Bottom
       { {1, -1, -2}, {1, 0, 0, 1}},
       { {1, -1, 0}, {0, 1, 0, 1}},
       { {-1, -1, 0}, {0, 0, 1, 1}},
       { {-1, -1, -2}, {0, 0, 0, 1}}
   };

接下来,当然是最重要的VBO索引啦:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
GLubyte indices[] = {
       // Front
       0, 1, 2,
       2, 3, 0,
       // Back
       4, 5, 6,
       4, 5, 7,
       // Left
       8, 9, 10,
       10, 11, 8,
       // Right
       12, 13, 14,
       14, 15, 12,
       // Top
       16, 17, 18,
       18, 19, 16,
       // Bottom
       20, 21, 22,
       22, 23, 20
   };

最后,由于我们修改了顶点属性,所以我们要相应地修改vertex shader和glVertexAttribPointer的调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    glVertexAttribPointer(positionLocation,
                          3,
                          GL_FLOAT,
                          GL_FALSE,
                          sizeof(Vertex),
                          (GLvoid*)offsetof(Vertex,Position));

//下面是vertex shader

attribute vec3 a_position;  //注意之前我们使用的是vec2
attribute vec4 a_color;

varying vec4 v_fragmentColor;

void main()
{
    gl_Position = CC_MVPMatrix * vec4(a_position.xyz,1);  //这里用swizzle的时候是xyz
    v_fragmentColor = a_color;
}

此时,编译运行,你会得到如下结果 :

cube01cube01

别诧异,这就是一个立方体,只不过现在它离我们的“眼睛”(Cemera)很近,所以我们只能看到一个面。接下来,让我们修改一个modelView矩阵,让它离我们的camera远一点。

让立方体动起来

我们有很多方法可以让立方体转起来。比如直接修改modelView矩阵,也可以使用modelView配合projection矩阵。

首先,是最简单的方法,我们把整个立方体数据先缩小一半,然后再往-z轴方向移动0.5个单位,最后让它围绕着x轴不停地旋转。

1
2
3
4
5
6
7
8
9
10
11
modelViewMatrix.scale(0.5);
modelViewMatrix.translate(0.0,0, -0.5);

static float rotation = 0;
modelViewMatrix.rotate(Vec3(1,0,0),CC_DEGREES_TO_RADIANS(rotation));
rotation++;
if (rotation < 360) {
    rotation = 0;
}

Director::getInstance()->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, modelViewMatrix);

注意,这里我们操纵顶点的取值范围只能是-1~+1,xyz每一个轴都是这样。超出这个区域(normalized device space)就会裁剪掉。但是我们实际操作一个物体的移动的时,肯定不可能局限于这么小的范围,我们可以通过modelView和projection矩阵来定义一个更好用的坐标系,然后基于这个坐标系去指定物体的坐标。
比如cocos2d-x里面,通过下列代码指定了自己的坐标系范围在(0~size.width)和(0~size.height)之间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
case Projection::_3D:
{
    float zeye = this->getZEye();
    Mat4 matrixPerspective, matrixLookup;
    loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
    // issue #1334
    Mat4::createPerspective(60, (GLfloat)size.width/size.height, 10, zeye+size.height/2, &matrixPerspective);
    multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, matrixPerspective);
    Vec3 eye(size.width/2, size.height/2, zeye), center(size.width/2, size.height/2, 0.0f), up(0.0f, 1.0f, 0.0f);
    Mat4::createLookAt(eye, center, up, &matrixLookup);
    multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, matrixLookup);
    loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
    break;
}

这里面,我们可以直接拿来用,也可以自己再写一个。下面是我用的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Mat4 projectionMatrix;
Mat4::createPerspective(60, 480/320, 1.0, 42, &projectionMatrix);
Director::getInstance()->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, projectionMatrix);

Mat4 modelViewMatrix;
Mat4::createLookAt(Vec3(0,0,1), Vec3(0,0,0), Vec3(0,1,0), &modelViewMatrix);
modelViewMatrix.translate(0, 0, -5);

static float rotation = 0;
modelViewMatrix.rotate(Vec3(1,1,1),CC_DEGREES_TO_RADIANS(rotation));
rotation++;
if (rotation < 360) {
    rotation = 0;
}
Director::getInstance()->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, modelViewMatrix);

这里我让camera的位置位于(0,0,1),然后看着(0,0,0)点,并且头朝上(0,1,0)。大家可以尝试去修改createLookAt的参数,看看每一个参数具体是什么意思。这里有一个非常不错的程序介绍View Frustum的,强烈推荐!

最终效果:(如果你看不到,请升级你的浏览器!!!)

结语

附上本教程源码,从下篇文章开始,我们将介绍纹理映射。

推荐阅读

相关文章推荐

cocos2dx之OpenGl绘图

随着OpenGL的发展,其提供的绘图函数也变得多种多样。对于同一个效果来说,常常有多种不同的实现方法,因此想要在此对OpenGL的绘图函数进行全方位的介绍是不可能的,这里我们只简单介绍Cocos2d-...

【C++ OpenGL ES 2.0编程笔记】8: 使用VBO和IBO绘制立方体

本文介绍了OpenGL ES 2.0 中的顶点缓冲对象(VBO: Vertex Buffer Object)和索引缓冲对象(IBO: Indice Buffer Object)的用法, 在之前的文章...
  • elloop
  • elloop
  • 2016年01月07日 00:54
  • 2303

OpenGL ES 使用顶点索引绘制立方体

1、新建 MyCubeRenderer.java /* * 立方体 */ public class MyCubeRenderer extends MyAbstractRenderer{ ...

cocos2D-X源码分析之从cocos2D-X学习OpenGL(12)----立方体贴图和天空盒

本篇介绍3d游戏中的天空盒概念,天空盒就是游戏中的背景,它是一个包裹整个场景的立方体,它由六个图像构成一个环绕的环境,给玩家一种所在场景比实际上大得多的感觉,如下图所示。       创建天空盒的方法...

OpenGL 核心技术之立方体贴图

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》...
  • jxw167
  • jxw167
  • 2017年02月14日 10:11
  • 2006

Cocos2dx-OpenGL ES2.0教程:编写自己的shader(2)

在上篇文章中,我给大家介绍了如何在cocos2d-x里面绘制一个三角形,当时我们使用的是cocos2d-x引擎自带的shader和一些辅助函数。在本文中,我将演示一下如何编写自己的shader,同时,...

Android OpenGL ES 2.0 的开发思路总结

背景项目一开始,自己对着一本《OpenGL ES 2.0 游戏开发(上卷)》撸了很长一段时间,里面学习到OpenGL 的挺多知识,包括着色器语言,还有大部分GL函数,纹理,光照等等。然而书中的所有De...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Android OpenGL ES 2.0画立方体

转自:点击打开链接 画过三角形后,再来画立方体。 Activity还是和画三角形的一样,只是Renderer换了。 为加强立体感,加了旋转效果。 Test2Renderer.java ...

对用OpenGL ES 2.0实现OpenGL ES 1.1的顶点着色器的研究

想要彻底研究OpenGL ES 2.0于前一代OpenGL的区别,还是要费很大一番精力的。最近在仔细研读《OpenGL ES 2.0 Programming Guide》,虽然这本书最早出版日期是20...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Cocos2dx-OpenGL ES2.0教程:你的第一个立方体(5)
举报原因:
原因补充:

(最多只允许输入30个字)