基于Cocos2d-x学习OpenGL ES 2.0系列——你的第一个立方体(5)
来源:互联网 发布:什么是高阶数据 编辑:程序博客网 时间:2024/04/20 14:44
在上篇文章中,我们介绍了VBO索引的使用,使用VBO索引可以有效地减少顶点个数,优化内存,提高程序效率。
本教程将带领大家一起走进3D--绘制一个立方体。其实画立方体本质上和画三角形没什么区别,所有的模型最终都要转换为三角形。
同时,本文还会介绍如何通过修改MVP矩阵来让此立方体不停地旋转。另外,大家还可以动手去修改本教程的示例代码,借此我们可以更加深入地理解OpenGL的normalized device space。
准备立方体数据
在开始真正的绘制代码之前,我们先要准备好数据。首先,我们需要改进的是代表顶点属性的结构体:
typedef struct { float Position[3]; float Color[4];} Vertex;
这里,我们把Position从一个长度为2的数组变成了一个长度为3的数组,用于存储顶点的xyz的值。
接下来是顶点数据,因为一共有6个面。每个面由二个三角形组成,因此需要4个顶点,那么整个立方体就需要4*6=24个顶点。
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索引啦:
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的调用:
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex,Position)); //下面是vertex shaderattribute vec3 a_position; //注意之前我们使用的是vec2attribute vec4 a_color; varying vec4 v_fragmentColor; void main(){ gl_Position = CC_MVPMatrix * vec4(a_position.xyz,1); //这里用swizzle的时候是xyz v_fragmentColor = a_color;}
此时,编译运行,你会得到如下结果 :
别诧异,这就是一个立方体,只不过现在它离我们的“眼睛”(Cemera)很近,所以我们只能看到一个面。接下来,让我们修改一个modelView矩阵,让它离我们的camera远一点。
让立方体动起来
我们有很多方法可以让立方体转起来。比如直接修改modelView矩阵,也可以使用modelView配合projection矩阵
首先,是最简单的方法,我们把整个立方体数据先缩小一半,然后再往-z轴方向移动0.5个单位,最后让它围绕着x轴不停地旋转。
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)之间。
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;}
这里面,我们可以直接拿来用,也可以自己再写一个。下面是我用的代码:
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的,强烈推荐!
最终效果:(如果你看不到,请升级你的浏览器!!!)
附上本教程源码,从下篇文章开始,我们将介绍纹理映射。
来源网址:http://4gamers.cn/archives/429
- 基于Cocos2d-x学习OpenGL ES 2.0系列——你的第一个立方体(5)
- 基于Cocos2d-x学习OpenGL ES 2.0系列——你的第一个三角形(1)
- 基于Cocos2d-x学习OpenGL ES 2.0系列——编写自己的shader(2)
- 基于Cocos2d-x学习OpenGL ES 2.0系列——OpenGL ES渲染之Shader准备(7)
- 基于Cocos2d-x学习OpenGL ES 2.0系列——OpenGL ES渲染之LayerColor(8)
- 基于Cocos2d-x学习OpenGL ES 2.0系列——初识MVP(3)
- 基于Cocos2d-x学习OpenGL ES 2.0系列——使用VBO索引(4)
- 基于Cocos2d-x学习OpenGL ES 2.0系列——纹理贴图(6)
- OpenGL ES2.0教程:你的第一个立方体(5)
- OpenGL ES 2.0教程:你的第一个三角形(1)
- OpenGL ES 2.0教程:你的第一个三角形(1)
- Cocos2dx-OpenGL ES2.0教程:你的第一个立方体(5)
- Cocos2d-x3.2 下 OpenGL ES 2.0 第一个简单的实例画三角形
- Cocos2dx-OpenGL ES 2.0教程:你的第一个三角形(1)
- 我所理解的Cocos2d-x OpenGL ES 2.0 概览
- 基于Android的OpenGL ES 2.0学习笔记(1)
- 基于Android的OpenGL ES 2.0学习笔记(2)
- Cocos2d-x学习(二) 在Cocos2d-x2.2.6搭建你第一个项目
- HDU
- minMaxLoc opencv
- Java总结篇:Java泛型
- 密码学笔记4 对称密钥算法
- Android混淆从入门到精通
- 基于Cocos2d-x学习OpenGL ES 2.0系列——你的第一个立方体(5)
- VINS(四)estimator_node 数据对齐 imu预积分 vision
- php使用memcached详解
- 数组的算法
- 程序员背单词
- Web报表系统葡萄城报表:报表工具
- 《Spark快速大数据分析》——读书笔记(3)
- RabbitMQ
- echarts之legend-改变图例的图标为自定义图片