Android 中的 OpenGL 简单入门 (下)

上篇博客中已经介绍了如何使用openGL为android提供的api绘制出简单的三角形和四边形,,,,上篇博客地址http://blog.csdn.net/a15874647/article/details/6713503

接下来介绍对图形进行色彩渲染,以及旋转,3D效果,纹理映射,贴图

2,颜色

为图形着色有两种不同的方式,,分别是光滑着色和平面着色。。

Smooth coloring(平滑着色),先为三角形的每个顶点设置一个颜色,这个颜色和之前所说的清屏颜色一样,为我们的三角形定义颜色数组:

int one = 0x10000;//三角形的顶点颜色值(red,green,blue,alpha)private IntBuffer colorBuffer = IntBuffer.wrap(new int[]{          one,0,0,one,          0,one,0,one,          0,0,one,one});//同样需要使开启色彩渲染开关gl.glEnableClientState(GL10.GL_COLOR_ARRAY);


android中提供了glColorPointer方法来设置颜色,它的参数类型和glVertexPointer类似:

gl.glColorPointer( 4, GL10.GL_FIXED,0,colorBuffer);

最后绘制方法和之前一样,注意使用完颜色后记得关闭,在openGL中使用glEnableClientState后都需要调用glDisableClientState来关闭相对应的功能

gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

接下来是单调着色,单调着色实际上就是设置当前所使用的颜色,设置之后绘制的所有内容都是使用当前颜色,即使是在完全采用纹理贴图的时候,仍然可以用来调节纹理的色调(纹理贴图内容后面会说到)。。因为我们没有告诉openGL要改变顶点的颜色,,我们就可以直接

gl.glColor4f(0.5f,0.5f,1.0f,1.0f); 为四边形设置颜色, 这里的颜色取值范围是0-1,,建议多改变下颜色参数,,观察下效果就会慢慢适应了。。。

3,旋转

要实现旋转很简单,我们绘制的图形旋转都是围绕着X,Y,Z三个轴来旋转,,大家可以先想象一下围绕着这三根轴旋转的方向。。。接着先增加个变量来控制对象的旋转,他们是浮点类型的变量,使得能够非常精确的旋转对象。。。

float rotateTri; //三角形的角度变量float rotateQuad;//四边形的角度变量


接下来看看旋转的函数,,在android中使用glRotatef(float angle,float x,float y,float z)方法将某个物体沿指定的轴旋转,其中angle参数通常是一个变量,代表对象转过的角度,,X,Y和Z 三个参数则共同决定旋转轴的方向,,,比如 (1,0,0)所描述的是经过X坐标轴的1个单位处并且方向向右,(-1,0,0)所描述的是经过X坐标轴的1个单位处方向向左。。。

//旋转三角形gl.glRotatef(rotateTri,0.0f,1.0f,0.0f);//旋转四边形gl.glRotatef(rotateQuad,1.0f,0.0f,0.0f);


这是用于三角形和四边形的旋转的,可以看出三角形沿Y轴旋转 rotateTri角度,四边形沿X轴旋转 rotateQuad角度。。。

如果我们需要让他们不停的旋转,,很简单我们只需要在onDrawFrame方法中不断的改变角度的变量,,,rotateTri+=0.5f; rotateQuad -=0.5f;

4, 3D效果

之前我们所绘制的都3D中的2D效果,,现在来实现3D效果,,也就是给三角形增加一个左侧面,右侧面,后侧面,,来生成一个金字塔。。给正方形增加左右上下后5个面来生成一个立方体。。

绘制这样的效果其实很简单,,基本上和绘制三角形一样,重点就在于构建他们所需的顶点左边,,需要注意的是:狗仔这些顶点左边时,要让对象绕自身的轴旋转,必须让对象的中心左边总是(0.0f,0.0f,0.0f),并且三角形都是按逆时针次序绘制的。。所以在构建顶点坐标时,需要按照逆时针的顺序来绘制,,千万不能有逆时针的方向又有顺时针的方向。。下面就对照着代码来观察所构建出来的金字塔,,他的上顶点高出原点一个单位,底面中心低于原点一个单位,上顶点在底面的投影位于底面的中心。。。

        int one = 0x10000;        private IntBuffer triggerBuffer = IntBuffer.wrap(new int[]{        0,one,0,    -one,-one,0,    one,-one,-one,        0,one,0,    one,-one,one,    one,-one,-one,        0,one,0,    one,-one,-one,    -one,-one,-one,        0,one,0,    -one,-one,-one,    -one,-one,one,        });


由于所有的面都共享上顶点,所以将这个点在所有的三角形中都设置为红色,底边上的两个顶点的颜色则是互斥的。前侧面的左下顶点是绿色的,右下顶点是蓝色的,这样相邻右侧面的坐下顶点是蓝色的,右下顶点是绿色的。

private IntBuffer colorBuffer = IntBuffer.wrap(new int[]{        one,0,0,one,    0,one,0,one,    0,0,one,one,        one,0,0,one,    0,one,0,one,    0,0,one,one,        one,0,0,one,    0,one,0,one,    0,0,one,one,        one,0,0,one,    0,one,0,one,    0,0,one,one        });


创建好了顶点和颜色的相关数据,就开始绘制了,由于金字塔不在是一个三角形面,而是由4个三角形面组成,所以这里需要分别绘制出4个三角形

        //绘制金字塔    for (int i = 0; i < 4; i++) {gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,i*3,3);        }    //同理绘制四方体,只不过是6个正方形面组成的    for (int i = 0; i < 6; i++) {    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,i*4,4);    }


这样就可以感受到逼真的3D物体了,,刚接触3D图形的时候,对于3D的空间感非常重要,不过可以靠绘制不同形状的物体来加强。。。

5 纹理映射及贴图

在创建了3D的图形时,,我们可以将openGL屏幕想象成一张很大的画纸,后面还带着许多透明的层,,就是由大量的点组成的立方体,这些点从左到右,从上到下,从前到后的不满了这个立方体。要是能够想象出屏幕的深度方向,在设计3D对象时应该是没有任何问题的。。在之前的四方体上我们只是将它铺满了颜色,在这里就要实现让他每一面都贴上一张图片,,要实现这个效果,首先要创建一个纹理,并使用图片来生成一个纹理。。。

        IntBuffer intBuffer = IntBuffer.allocate(1);        //创建纹理        gl.glGenTextures(1,intBuffer);    texture = intBuffer.get();        //设置要使用的纹理        gl.glBindTexture(GL10.GL_TEXTURE_2D,texture);


上面代码中的glGenTextures(int n,IntBuffer textures)用于通知openGL我们想生成一个纹理的名字,如果想载入多个纹理,可以在参数n处设置,参数textures描述了纹理的代号。。glBindTexture(int target,int texture)方法用于通知openGL将纹理代号texture绑定到纹理目标上。。2D的纹理只有高度,在Y轴上,,,和宽度,在X轴上。。

在android中我们使用GLUtils中的一个静态方法texImage2D(int target,int level,Bitmap bitmap,int border)来生成一个纹理,第一个参数描述了纹理的类型,第二参数描述了纹理的详细程度,一般情况下设置为0,第三个参数是用于纹理贴图的图像数据,最后一个参数描述了边框效果。。。。

           //生成纹理         GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,GLImage.mBitmap,0);

到这里成功创建了一个纹理,接下来我们还需要设置在openGL显示图像时,他放大得比原始纹理大或缩小的比原始纹理小时openGL所采用的滤波方式。通常这两种情况下都采用GL_LINEAR,这使得纹理从很远处到离屏幕很近时都平滑显示。使用GL_LINEAR需要cpu和显卡做出更多的元素按,因为效率问题,这里采用GL_NEAREST。当然也可以结合这两种滤波方式,在近处时用GL_LINEAR,在远处时使用GL_NEAREST。

         //线性滤波         gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);         gl.glTexParameterx(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR);


接下来使用glBindTexture(int target,int texture)方法来帮顶纹理,,参数target描述要帮顶的纹理的类型,参数texture描述了纹理的代号:

        //绑定纹理         gl.glBindTexture(GL10.GL_TEXTURE_2D,texture);


纹理的使用和颜色一样,需要使用glEnableClientState方法来开启纹理,,使用完后也同样要关闭。。

         gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

为了正确的映射,必须将纹理的右上角映射到四边形的右上角,纹理的左上角映射到四边形的左上角,右下角,左下角,,同理。。。如果映射错误的话,图像显示时可能上下点到,侧向一遍或者什么都没有。。

    private IntBuffer colorBuffer = IntBuffer.wrap(new int[]{        one,0,0,0,0,one,one,one,        0,0,0,one,one,one,one,0,        one,one,one,0,0,0,one,        0,one,one,one,one,0,0,0,        0,0,0,one,one,one,one,0,        one,0,0,0,0,one,one,one            });


设置好这些数据后,通过 glTexCoordPointer(2,GL10.GL_FIXED,0,texCoords); 将纹理绑定到要绘制的物体上。。其中第一个参数是纹理的坐标类型,这里使用的是2D纹理,只有X,Y两个坐标,所以是2;第二参数描述了我们所使用的是固定的纹理数据;第三个参数是步长;第四个参数是我们定义的纹理映射数据。。最后和绘制多边形一样将其绘制到屏幕上即可,这里还可以使用glDrawElements方法来绘制多边形,该方法只是多了一个数据类型的参数,用来描述所使用的数据类型,如下绘制四边形所使用的GL_UNSIGNED_BYTE。

gl.glDrawElements(GL10.GL_TRIANGLE_STRIP,24,GL10.GL_UNSIGNED_BYTE,indices);

介绍到这里,搞Android中应用程序开发中的需求基本能满足了,怎么样?OpenGL还是挺好玩的吧?不像搞应用那么无聊,,玩OpenGL还是挺过瘾的,,要画个什么东东,立竿见影!!~3D世界其实丰富多彩,还有更多的东西需要我们去学习,去研究,去发现,,目前国内在移动设备上的3D技术还处于发展状态,,大家一起加油!!

Android中的 OpenGL 简单入门 (上) http://blog.csdn.net/a15874647/article/details/6713503

更多相关文章

  1. UE4 安卓打包纹理格式选择
  2. Android(安卓)Drawable
  3. android openGL ES2 一切从绘制纹理开始
  4. Android图形显示系统(一)
  5. Android图形显示系统(一)
  6. Android动态壁纸的制作教程
  7. Android实现图表绘制和展示
  8. android中ListView点击和ListView的item里面的button或ImageView
  9. Android(安卓)自定义View——自定义View控件

随机推荐

  1. c++引用和指针的区别是什么?
  2. scanf在c语言中的作用是什么?
  3. c语言中数据结构是什么?常见数据结构有哪
  4. 虚函数和纯虚函数的区别是什么?
  5. c语言的输入输出语句有哪些?
  6. windows.h有哪些函数
  7. c语言中字符常量是什么?
  8. C语言中的指针有什么作用
  9. c语言程序中的基本功能模块为什么?
  10. C语言的三种基本程序结构是什么