前言
前面已经讲了如何绘制点、线、面,现在就来绘制一个立方体,OpenGL ES中任何一个立体图形都是由很多面组成的,这个面指的就是三角形,所以绘制立方体就是绘制多个三角形而组合起来。
绘制
立方体有6个面,左、右、前、后、上、下。共有8个顶点,每个面有4个顶点,代码如下
PS:一定要注意顶点的顺序,不能随意选择
// 定义立方体的8个顶点
float[] cubeVertices = {
//左面
-0.5f,0.5f,0.5f,
-0.5f,-0.5f,0.5f,
-0.5f,0.5f,-0.5f,
-0.5f,-0.5f,-0.5f,
//右面
0.5f, 0.5f,0.5f,
0.5f,-0.5f,0.5f,
0.5f,-0.5f,-0.5f,
0.5f,0.5f,-0.5f ,
//前面
-0.5f,0.5f,0.5f,
-0.5f,-0.5f,0.5f,
0.5f,-0.5f,0.5f,
0.5f, 0.5f,0.5f,
//后面
0.5f,-0.5f,-0.5f,
0.5f,0.5f,-0.5f,
-0.5f,0.5f,-0.5f,
-0.5f,-0.5f,-0.5f,
//上面
-0.5f,0.5f,0.5f,
0.5f, 0.5f,0.5f,
0.5f,0.5f,-0.5f,
-0.5f,0.5f,-0.5f,
//下面
-0.5f,-0.5f,0.5f,
0.5f,-0.5f,0.5f,
0.5f,-0.5f,-0.5f,
-0.5f,-0.5f,-0.5f
};
然后定义一个颜色数组
// 颜色数组
float [] cubeColors = {
1f,0f,0f,1f ,
0f,1f,0f,1f,
0f,0f,1f,1f,
1f,0f,0f,1f,
1f,0f,0f,1f ,
0f,1f,0f,1f,
0f,0f,1f,1f,
1f,0f,0f,1f,
1f,0f,0f,1f ,
0f,1f,0f,1f,
0f,0f,1f,1f,
1f,0f,0f,1f,
1f,0f,0f,1f ,
0f,1f,0f,1f,
0f,0f,1f,1f,
1f,0f,0f,1f,
1f,0f,0f,1f ,
0f,1f,0f,1f,
0f,0f,1f,1f,
1f,0f,0f,1f,
1f,0f,0f,1f ,
0f,1f,0f,1f,
0f,0f,1f,1f,
1f,0f,0f,1f,
};
然后是获取浮点型缓冲数据
//获取浮点形缓冲数据
VerticesBuffer = Utils.getFloatBuffer(cubeVertices);
//获取浮点型颜色数据
Colorbuffer= Utils.getFloatBuffer(cubeColors);
为了能看到立体的效果,就让这个矩阵一直绕Y轴旋转。因为默认的是一直绘制的渲染模式,所以指定一个角度,每次都加1即可。另外指定绘制线的模式为 GL_TRIANGLE_STRIP 。即相邻三个顶点绘制一个三角形。
代码如下
@Override
public void onDrawFrame(GL10 gl) {
// 清除屏幕缓存和深度缓存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 启用顶点座标数据
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// 启用顶点颜色数据
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
// 重置当前的模型视图矩阵
gl.glLoadIdentity();
// 沿着Y轴旋转
gl.glRotatef(rotate, 0f, 1f, 0f);
// 设置顶点的位置数据
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, VerticesBuffer);
// 设置顶点的颜色数据
gl.glColorPointer(4, GL10.GL_FLOAT, 0, Colorbuffer);
//绘制三角形
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP , 0, 24);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
// 旋转角度增加1
rotate-=1;
}
效果如下:
可以看到有很多三角形,那么这并不是我们想要的效果,这时候要用到索引了。
索引绘制
索引就是让不同的顶点按照规定的顺序来绘制,这样就不会导致各种三角形的错乱。
首先定义一个索引数组,这里的0,1,2等指的是顶点顺序,比如0,1,2就是按照0,1,2的顺序绘制三角形,0,2,3就是按照02,3的顺序绘制三角形,就不会出现0,1,2 和1,2,3 以及 023都绘制的情况。
//索引数组
private short[] indices={
0,1,2,
0,2,3,
4,5,6,
4,6,7,
8,9,10,
8,10,11,
12,13,14,
12,14,15,
16,17,18,
16,18,19,
20,21,22,
20,22,23,
};
获取浮点型索引数据
//获取浮点型索引数据
indexbuffer= Utils.getShortBuffer(indices);
最后在onDrawFrame方法里,把以下去掉
//绘制三角形
//gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP , 0, 24);
换成
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indexbuffer);
这里讲一下glDrawElements方法,Android OpenGL ES学习笔记之绘制点
里讲了
OpenGL ES提供了两类方法来绘制一个空间几何图形:
-public abstract void glDrawArrays(int mode, int first, int count) 使用VetexBuffer 来绘制,顶点的顺序由vertexBuffer中的顺序指定。
- public abstract void glDrawElements(int mode, int count, int type, Buffer indices) ,可以重新定义顶点的顺序,顶点的顺序由indices Buffer 指定。
glDrawElements各个参数如下:
- mode——指明被渲染的是哪种图元,被允许的符号常量有GL_POINTS,GL_LINE_STRIP,GL_LINE_LOOP,GL_LINES,GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN 和GL_TRIANGLES
- count——指明被渲染的元素个数。
- type——指明索引指的类型,不是GL_UNSIGNED_BYTE 就是GL_UNSIGNED_SHORT。
- indices——指明存储索引的位置指针。
现在看下效果
总结
绘制正方体就这样完成了。
Demo地址:点击打开
密码:arxc