OpenGL ES --Flat coloring和Smooth coloring

来源:互联网 发布:大数据产生的背影 题 编辑:程序博客网 时间:2024/04/20 17:54

暂时还未涉及3D,但这篇文章是经验之谈。以后用的到,原文地址: http://blog.sina.com.cn/s/blog_61ef49250100r41x.html

喝了两杯茶,没睡意,于是就整理了今晚的笔记,权作理顺头绪。


1.glClear --清除先前缓存中的值
 
函数声明:
        void glClear(GLbitfield mask)
 
参数:
mask
          按位运算符 OR 来指示要清除的缓存。参数的值可以是 GL_COLOR_BUFFER_BIT/                                      GL_DEPTH_BUFFER_BIT/GL_STENCIL_BUFFER_BIT
 
描述:
          glClear是将位平面面积设置为通过调用glClearColor/glClearDepth和glClearStencil选择的 值,从而达到           忽略alpha function/blend funcion/logical operation/stenciling/ texture mapping和depth-buffering所产生的效果。
 
参数值的意义如下:
          GL_COLOR_BUFFER_BIT:颜色缓存
          GL_DEPTH_BUFFER_BIT:深度缓存
          GL_STENCIL_BUFFER_BIT:模型缓存
 
提示:
          如果一个缓存没有呈现出来,glClear将对该缓存任何影响
 
Errors:
          如果参数是上述三个已定义参数之外的,该函数将产生一个GL_INVALID_VALUE的值
 
 
2.glLoadIdentity --用指定的矩阵代替当前矩阵
 
 
函数声明:
          void glLoadIdentity(void)
描述:
          glLoadIdentity用于将当前矩阵替代为一指定矩阵,其实是将当前点移到了屏幕中心,这在语义上和调          用glLoadMatrix载入一个单位矩阵
          (1000010000100001)
是一样的,但是在某些情况下,glLoadIdentity效率会更高。
 
 
3.着色
      OpenGL Es使用的颜色模型为RGBA(Red,Green,Blue,Alpha)。前三个分别表示红绿蓝三种 颜色的值,第            四个数表示透明度,数值范围0~1,0时为全透明,1时为不透明。
 
着色有两种方式:Flat coloring和Smooth coloring
 
Flat coloring(单调着色)
图形使用Flat coloring方式着色时,只需要在OpenGL Es进行渲染时告诉它用哪种颜色即可, 这时图形只是涂上一种固定的颜色。虽然容易使用,但是必须记住一点,当选择一个颜色,告诉 OpenGL Es使用该颜色对图形进行着色时,都会用该颜色进行着色,直到你告诉OpenGL ES 要使 用其他颜色着色。也就是说,只要一次性设置好我们需要的颜色,以后所绘制的东西都会用该颜色 着色,即使是完全采用纹理贴图的时候,仍可以调节纹理的色调,除非你告诉OpenGL Es要改变颜 色。
要告诉OpenGL Es使用哪种颜色工作,你可以用下面这个函数:

public abstract void glColor4f(float red,float green,float blue,float alpha);

各参数默认值为:red=1;green=1;blue=1;alpha=1;也就是白色。这样说明为什么在不设置颜色 时,我们绘制的图形是白色的。

我们在draw 函数中这样使用glColor4f:

public void draw(GL10 gl){
 
          gl.glColor4f(0.5f,0.5f,1.0f,1.0f); //即将当前色设为0x8080FFFF
}

接着创建一个图形,比如正方形,然后就在渲染器Renderer的onDrawFrame函数中调用 draw函数,即可画出以该颜色着色的图形。


Smooth coloring(平滑着色)
Smooth coloring 要求你对图形的每个顶点设置颜色,然后OpenGL Es会将相邻点的颜色混合 在一起,创建出绚丽的颜色。

我们以画锥形为例,首先创建一个包含锥形各顶点的数组:
publicclassTriangle {
      ......
      //锥形顶点坐标
      float[] vertex = {
            0f,1f,0f,
            -1f,-1f,0f,
            1f,-1f,1f,
 
            0f,1f,0f,
            1f,-1f,1f,
            1f,-1f,-1f,
 
            0f,1f,0f,
            1f,-1f,-1f,
            -1f,-1f,-1f,
 
            0f,1f,0f,
            -1f,-1f,-1f,
            -1f,-1f,1f
       };
       ......
 
注意:画图前要先了解OpenGL Es中的坐标系。当调用glLoadIdentity()后,我们就将原点移到 了屏幕的中心,左右方向为X轴,上下方向为Y轴,里外方向为Z轴。屏幕中心坐标为 (0.0f,0.0f,0.0f)。中心左边的坐标值为负值,右边为正值;移向屏幕顶端为正值,移向屏幕底 部为负值;移入屏幕深处为负值,移出屏幕为正值。

现在我们再创建一个包含各顶点颜色的数组:
//锥形各顶点颜色
float[] colors = {
      1f, 0f, 0f, 1f, // 0xFF0000FF vertex 0 red
      0f, 1f, 0f, 1f, // 0x00FF00FF vertex 1 green
      0f, 0f, 1f, 1f, // 0x0000FFFF vertex 2 blue
      1f, 0f, 1f, 1f, // 0xFF00FFFF vertex 3 magenta
 
      1f, 0f, 0f, 1f, // 0xFF0000FF vertex 0 red
      0f, 1f, 0f, 1f, // 0x00FF00FF vertex 1 green
      0f, 0f, 1f, 1f, // 0x0000FFFF vertex 2 blue
      1f, 0f, 1f, 1f, // 0xFF00FFFF vertex 3 magenta
 
      1f, 0f, 0f, 1f, // 0xFF0000FF vertex 0 red
      0f, 1f, 0f, 1f, // 0x00FF00FF vertex 1 green
      0f, 0f, 1f, 1f, // 0x0000FFFF vertex 2 blue
      1f, 0f, 1f, 1f, // 0xFF00FFFF vertex 3 magenta
 
      1f, 0f, 0f, 1f, // 0xFF0000FF vertex 0 red
      0f, 1f, 0f, 1f, // 0x00FF00FF vertex 1 green
      0f, 0f, 1f, 1f, // 0x0000FFFF vertex 2 blue
      1f, 0f, 1f, 1f, // 0xFF00FFFF vertex 3 magenta
};

注意:这里的颜色取值为0...1,分别对应于十进制的1到255,或者是十六进制的#00到 #FF。所以最好能在后面写下十六进制数,这样在以后的阅读中就能很快知道采用了哪种颜色。

创建后我们需要将其载入缓冲区中:
publicTriangle() {
   //顶点坐标数组
   ByteBuffer vBuffer = ByteBuffer.allocateDirect(vertex.length*4);
   vBuffer.order(ByteOrder.nativeOrder());
   triangleBuffer= vBuffer.asFloatBuffer();
   triangleBuffer.put(vertex);
   triangleBuffer.position(0);

   //缓冲区大小,字节类型,Float有4个Byte
   ByteBuffer cBuffer = ByteBuffer.allocateDirect(colors.length*4);
   //分配字节顺序与java虚拟机所在的硬件相同的缓冲区
   //本机代码库通常使用此类缓冲区时更有效
   cBuffer.order(ByteOrder.nativeOrder());
   //创建vBuffer缓冲区的视图,作为float缓冲区
   colorBuffer= cBuffer.asFloatBuffer();
   //将数组放入缓冲区中
   colorBuffer.put(colors);
   //设置缓冲区中指针的位置
   colorBuffer.position(0);
}


当然,我们需要先声明变量colorBuffer和triangleBuffer:

privateFloatBuffer triangleBuffer;
privateFloatBuffer colorBuffer;

在draw函数中,我们就可以添加绘制锥形的代码了:

publicvoiddraw(GL10 gl) {
   //告诉opengl以顺时针顺序按坐标显示该物体
   gl.glFrontFace(GL10.GL_CCW);
   //允许设置定点
   gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
   //开启颜色渲染功能
   gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
   //设置三角形颜色
   gl.glColorPointer(4, GL10.GL_FLOAT,0,colorBuffer);
   //设置三角形顶点
   gl.glVertexPointer(3, GL10.GL_FLOAT,0,triangleBuffer);
   //绘制三角形
   for(inti=0;i<4;i++){
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,i*3,3);
   }
   //关闭颜色设置
   gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
   //取消定点设置
   gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}


最后在GLRender类中实例化Triangle并在onDrawFrame方法中添加绘制代码即可。

创建Triangle对象:
publicGLRender(){
   triangle= newTriangle();
}

添加绘制代码:
@Override
publicvoidonDrawFrame(GL10 gl) {
   // TODOAuto-generated method stub
   //清除屏幕和深度缓存
   gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
   //重置当前的模型观察矩阵
   gl.glLoadIdentity();
   //移入屏幕6.0个单位
   gl.glTranslatef(0.0f, 0.0f, -6.0f);
   //绘制三角形
   triangle.draw(gl);
}
 
要运行起来还得重载Renderer的两个方法:onSurfaceChanged和onSurfaceCreated

@Override
publicvoidonSurfaceChanged(GL10 gl, intwidth, intheight) {
   // TODOAuto-generated method stub
   floatratio = (float)width/height;
   if(height==0) {
      height = 1;
   }
   //设置Open场景大小
   gl.glViewport(0, 0, width, height);
   //设置投影矩阵
   gl.glMatrixMode(GL10.GL_PROJECTION);
   //重置投影矩阵
   gl.glLoadIdentity();
   //设置视口的大小
   gl.glFrustumf(-ratio,ratio,-1, 1, 1, 10);
   //选择模型观察矩阵
   gl.glMatrixMode(GL10.GL_MODELVIEW);
   //重置模型观察矩阵
   gl.glLoadIdentity();
}

 

@Override
publicvoidonSurfaceCreated(GL10 gl, EGLConfig config) {
   // TODOAuto-generated method stub
   //黑色背景
   gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
   //启动阴影平滑
   gl.glShadeModel(GL10.GL_SMOOTH);
   //设置深度缓存
   gl.glClearDepthf(1.0f);
   //启动深度测试
   gl.glEnable(GL10.GL_DEPTH_TEST);
   //所做深度测试的类型,小于或等于预设深度值时通过测试
   gl.glDepthFunc(GL10.GL_LEQUAL);
   //告诉系统对透视进行修正
   gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
}

这样我们就绘制出一个五彩缤纷的锥形了。(*^__^*)

 

原创粉丝点击