全部博文(38)
分类: 嵌入式
2011-12-16 15:14:22
为了方便后边的编程,我们第一篇文章主要是介绍一些关于OpenGLES基本的概念。
点
3D图像的最小单位称为点(point)或者顶点vertex。它们代表三维空间中的一个点并用来建造更复杂的物体。多边形就是由点构成,而物体是由多个多边形组成。尽管通常OpenGL支持多种多边形,但OpenGLEs只支持三边形(即三角形)所以即使我们要绘制一个正方形也要把它拆分为两个三角形绘制。先说说坐标系的问题。
默认情况下,以屏幕中心为坐标轴原点。原点左方x为负值,右边为正值。原点上方y为正,原点下方为负。垂直屏幕向外为z正,垂直屏幕向里为z负。默认情况下,从原点到屏幕边缘为1.0f,沿各轴增加或减小的数值是以任意刻度进行的–它们不代表任何真实单位,如英尺,像素或米等。你可以选择任何对你的程序有意义的刻度(全局必须保持单位一致,不能一部分使用米,一部分使用像素)。OpenGL只是将它作为一个参照单位处理,保证它们具有相同的距离。如图:
了解了坐标轴,我们来看看怎么在坐标系中表示一个点,通常用一组浮点数来表示点。例如一个正方形的4个顶点可表示为:
float vertices[] = {
-1.0f, 1.0f, 0.0f, //左上
-1.0f, -1.0f, 0.0f, //左下
1.0f, -1.0f, 0.0f, //右下
1.0f, 1.0f, 0.0f, //右上
};
为了提高性能,通常还需要将浮点数组存入一个字节缓冲中。所以有了下面的操作:
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4); //申请内存
vbb.order(ByteOrder.nativeOrder()); //设置字节顺序,其中ByteOrder.nativeOrder()是获取本机字节顺序
FloatBuffer vertexBuffer = vbb.asFloatBuffer(); //转换为float型
vertexBuffer.put(vertices); //添加数据
vertexBuffer.position(0); //设置缓冲区起始位置
OpenGLES的很多函数功能的使用状态是处于关闭的。启用和关闭这些函数可以用glEnableClientState、glDisableClientState来完成。
// 指定需要启用定点数组
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// 说明启用数组的类型和字节缓冲,类型为GL_FLOAT
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
// 不再需要时,关闭顶点数组
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
多边形
多边形是由点和边构成的单闭合环。 绘制多边形时需要特别注意顶点的绘制顺序,可以分为顺时针和逆时针。因为方向决定了多边形的朝向, 即正面和背面。避免渲染那些被遮挡的部分可以了有效提高程序性能。默认以逆时针次序绘制顶点的构成的面是正面。
可以通过glFrontFace函数来交换“正面”和“反面”的概念。
glFrontFace(GL_CCW); // 设置CCW方向为“正面”,CCW即CounterClockWise,逆时针
glFrontFace(GL_CW); // 设置CW方向为“正面”,CW即ClockWise,顺时针
渲染
有了以上的概念讲解后,现在要进行最主要的工作—渲染。渲染是把物体坐标所指定的图元转化成帧缓冲区中的图像。图像和顶点坐标有着密切的关系。这个关系通过绘制模式给出。常用到得绘制模式有GL_POINTS、GL_LINE_STRIP、GL_LINE_LOOP、GL_LINES、GL_TRIANGLES、GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN。下面分别介绍:
GL_POINTS:把每一个顶点作为一个点进行处理,顶点n即定义了点n,共绘制n个点。
GL_LINES:把每一个顶点作为一个独立的线段,顶点2n-1和2n之间共定义了n个线段,总共绘制N/2条线段。,如果N为奇数,则忽略最后一个顶点。
GL_LINE_STRIP:绘制从第一个顶点到最后一个顶点依次相连的一组线段,第n和n+1个顶点定义了线段n,总共绘制N-1条线段。
GL_LINE_LOOP:绘制从定义第一个顶点到最后一个顶点依次相连的一组线段,然后最后一个顶点与第一个顶点相连。第n和n+1个顶点定义了线段n,然后最后一个线段是由顶点N和1之间定义,总共绘制N条线段。
GL_TRIANGLES:把每三个顶点作为一个独立的三角形。顶点3n-2,3n-1和3n定义了第n个三角形,总共绘制N/3个三角形。
GL_TRIANGLE_STRIP:绘制一组相连的三角形。对于奇数点n,顶点n,n+1和n+2定义了第n个三角形;对于偶数n,顶点n+1,n和n+2定义了第n个三角形,总共绘制N-2个三角形。这是最常使用的渲染方式,第一个三角形条是由前三个顶点构成(索引0,1, 2)。第二个三角形条是由前一个三角形的两个顶点加上数组中的下一个顶点构成,继续直到整个数组结束。
GL_TRIANGLE_FAN:绘制一组相连的三角形。三角形是由第一个顶点及其后给定的顶点所确定。顶点1,n+1和n+2定义了第n个三角形,总共绘制N-2个三角形。
绘制图形步骤: 1.定义顶点并且转换存储在字节缓冲中; 2.我们使用顶点数组绘制图形,而opengles是默认关闭这个开关的,所以我们要启用它。gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 3.设置绘制的颜色。以下为设置红色 gl.glVertexPointer( 3,//每个顶点的坐标的维数,这里为3xyz GL10.GL_FIXED,//顶点坐标值的类型为GL_FIXED 0,//数组中数据的偏移值 mVertexBuffer//顶点坐标数据数组 ); 5.开始绘图 gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0, 9); 函数原型 voidglDrawArrays(int mode, int first, int count) mode为绘制式,有GL_POINTS、GL_LINES、GL_TRIANGLES、GL_TRIANGLE_STRIP等。first为数据在数组中的起始位置,读取数据的个数 视图与透视 我们生活在一个三维的世界——如果要观察一个物体,我们可以: 1、模型变换和视图变换 即设置3D模型的位移,旋转等属性。由于模型和视图的变换都通过矩阵运算来实现,在进行变换前,应先设置当前操作的矩阵为“模型视图矩阵”。设置的方法是以GL_MODELVIEW为参数调用glMatrixMode函数,像这样: 2、投影变换
1、从不同的位置去观察它。(视图变换)
2、移动或者旋转它,当然了,如果它只是计算机里面的物体,我们还可以放大或缩小它。(模型变换)
3、如果把物体画下来,我们可以选择:是否需要一种“近大远小”的透视效果。另外,我们可能只希望看到物体的一部分,而不是全部(剪裁)。(投影变换)
4、我们可能希望把整个看到的图形画下来,但它只占据纸张的一部分,而不是全部。(视口变换)
这些,都可以在OpenGL中实现。
OpenGL变换实际上是通过矩阵乘法来实现。无论是移动、旋转还是缩放大小,都是通过在当前矩阵的基础上乘以一个新的矩阵来达到目的。
glMatrixMode(GL_MODELVIEW);
通常,我们需要在进行变换前把当前矩阵设置为单位矩阵。这也只需要一行代码:
glLoadIdentity();
然后,就可以进行模型变换和视图变换了。进行模型和视图变换,主要涉及到三个函数:
glTranslate*,(*表示这个函数分为float型的glTranslatef和int型的glTranslatex)把当前矩阵和一个表示移动物体的矩阵相乘。三个参数分别表示了在三个坐标上的位移值。
glRotate*,把当前矩阵和一个表示旋转物体的矩阵相乘。物体将绕着(0,0,0)到(x,y,z)的直线以逆时针旋转,参数angle表示旋转的角度。
glScale*,把当前矩阵和一个表示缩放物体的矩阵相乘。x,y,z分别表示在该方向上的缩放比例。
投影变换就是定义一个可视空间,可视空间以外的物体不会被绘制到屏幕上。(注意,从现在起,坐标可以不再是-1.0到1.0了!)
OpenGL支持两种类型的投影变换,即透视投影和正投影。投影也是使用矩阵来实现的。如果需要操作投影矩阵,需要以GL_PROJECTION为参数调用glMatrixMode函数。
glMatrixMode(GL_PROJECTION);
通常,我们需要在进行变换前把当前矩阵设置为单位矩阵。
glLoadIdentity();