文档章节

Android OpenGl ES 初级学习笔记

蜀山下的鱼
 蜀山下的鱼
发布于 2015/04/29 00:38
字数 4237
阅读 85
收藏 0

****************Android OpenGl ES 学习笔记*******************

 原文地址:http://zhan.renren.com/programfans?gid=3602888498000602783&checked=true

 

  ———— By xbw

零:【为何学OpenGl ES】

作为一个图形库,OpenGl被很多游戏大作使用。移动端的OpenGl ES则是从节省性能考虑,精简了OpenGl,使之更适合移动平台。OpenGl当然是为了绘制3D图形的,对于开发3D游戏或一些涉及到3D图形显示的软件都要用这个,如iReader的模拟出的书本翻页效果。其实我觉得即使对于2D图形,很多地方用opengl比系统自带的绘图函数好用的多,比如贴图旋转平移什么的~

 

 

一:【构造OpenGL ES View】

 

1.关于GLSurfaceView

 

Android平台提供的OpenGL ES API主要定义在包android.opengl ,javax.microedition.khronos.egl ,javax.microedition.khronos.opengles,java.nio等几个包中,其中类GLSurfaceView为这些包中的核心类:

 

* 起到连接OpenGL ES与Android 的View层次结构之间的桥梁作用。

* 使得Open GL ES库适应于Anndroid系统的Activity生命周期。

* 使得选择合适的Frame buffer像素格式变得容易。

* 创建和管理单独绘图线程以达到平滑动画效果。

* 提供了方便使用的调试工具来跟踪OpenGL ES函数调用以帮助检查错误。

 

——因此编写OpenGL ES应用的起始是从类GLSurfaceView开始,设置GLSurfaceView只需调用一个方法来设置OpenGLView用到的Renderer。一般的android程序主Activity中用setContentView来设置程序用到的layout布局,即程序的界面效果,opengl只需要构造好Renderer,将其添加入GlSurfaceView,再setContentView将activity设置为用这个gl的view作为显示就行了。

 

2.关于GLSurfaceView.Renderer

 

定义了一个统一图形绘制的接口,它定义了如下三个接口函数:

* onSurfaceCreated:在这个方法中主要用来设置一些绘制时不常变化的参数,比如:背景色,是否打开z-buffer等。

*   onDrawFrame:定义实际的绘图操作。

*   onSurfaceChanged:如果设备支持屏幕横向和纵向切换,这个方法将发生在横向<->纵向互换时.此时可以重新设置绘制的纵横比率。

 

~~~~~~~则得到一个OpenGl应用的基本框架模板~~~~~~~~~~

* TutorialPartI.java (主Activity)

 

public class TutorialPartI extends Activity {

 // Called when the activity is first created.

 @Override

 public void onCreate(Bundle savedInstanceState) {

 super.onCreate(savedInstanceState);

 this.requestWindowFeature(Window.FEATURE_NO_TITLE); // 设置无标题

 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

 WindowManager.LayoutParams.FLAG_FULLSCREEN); // 设置全屏

 

 GLSurfaceView view = new GLSurfaceView(this);//构造view

 view.setRenderer(new OpenGLRenderer());

 setContentView(view);

 }

 

 

* OpenGLRenderer.java(关键)

 

public class OpenGLRenderer implements Renderer {

 public void onSurfaceCreated(GL10 gl, EGLConfig config) {

 // Set the background color to black ( rgba ).

 gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);  // OpenGL docs.

 // Enable Smooth Shading, default not really needed.

 gl.glShadeModel(GL10.GL_SMOOTH);// OpenGL docs.

 // Depth buffer setup.

 gl.glClearDepthf(1.0f);// OpenGL docs.

 // Enables depth testing.

 gl.glEnable(GL10.GL_DEPTH_TEST);// OpenGL docs.

 // The type of depth testing to do.

 gl.glDepthFunc(GL10.GL_LEQUAL);// OpenGL docs.

 // Really nice perspective calculations.

 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, // OpenGL docs.

 GL10.GL_NICEST);

 }

 

 public void onDrawFrame(GL10 gl) {

 // Clears the screen and depth buffer.

 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | // OpenGL docs.

 GL10.GL_DEPTH_BUFFER_BIT);

 }

 

 public void onSurfaceChanged(GL10 gl, int width, int height) {

 // Sets the current view port to the new size.

 gl.glViewport(0, 0, width, height);// OpenGL docs.

 // Select the projection matrix

 gl.glMatrixMode(GL10.GL_PROJECTION);// OpenGL docs.

 // Reset the projection matrix

 gl.glLoadIdentity();// OpenGL docs.

 // Calculate the aspect ratio of the window

 GLU.gluPerspective(gl, 45.0f,

 (float) width / (float) height,

 0.1f, 100.0f);

 // Select the modelview matrix

 gl.glMatrixMode(GL10.GL_MODELVIEW);// OpenGL docs.

 // Reset the modelview matrix

 gl.glLoadIdentity();// OpenGL docs.

 }

}

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

 

二:【3D绘图基本概念】

 

一个3D图形通常是由一些小的基本元素(顶点,边,面,多边形)构成,每个基本元素都可以单独来操作。

 

1.Vertex(顶点):3D建模的最小单位

一个顶点也可以代表一个点光源或是Camera的位置。

* 通常的顶点定义方式,数组形式:

private float vertices[] = {

 -1.0f,  1.0f, 0.0f,  // 0, Top Left

 -1.0f, -1.0f, 0.0f,  // 1, Bottom Left

  1.0f, -1.0f, 0.0f,  // 2, Bottom Right

  1.0f,  1.0f, 0.0f,  // 3, Top Right

};//定义了4个顶点,分别是x,y,z轴坐标,相对于原点o .

定义的效果是:

  0      3

 

     o点

 

  1      2

* 与Android的View类canvas绘图不用,canvas用的屏幕坐标系,即屏幕左上角为原点(0,0),向右正x,向下正y,坐标点的值单位1为1像素。opengl用的世界坐标系,以屏幕中心为(0,0,0),单位可自行决定,绘制时是按比例的

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* 为了3D绘图的性能,通常用buffer类存放顶点颜色等等信息:

ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length* 4);   //一个float等于4个byte,因此要*4

vbb.order(ByteOrder.nativeOrder());//设置字节序

FloatBuffer vertexBuffer = vbb.asFloatBuffer();//不同buf转换

vertexBuffer.put(vertices);  //即将以上的数组放入buffer

vertexBuffer.position(0);//这个position值表示下一个可以读写的字节的缺省位置,相当于一个指针

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* 有了顶点的定义,下面一步就是如何将它们传给OpenGL ES库。OpenGl使用管道机制,来开关某些功能

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);//打开传递buf功能

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);//将定义点的数组buf传递到opengl

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);//关闭传递buf功能

 

2.Edge(边)

在OpenGL中,通常无需直接来定义一个边,而是通过顶点定义一个面,从而又面定义了这个面所拥有的边。修改两端点,从而可以修改一条边

 

3.Face(面)

在OpenGL ES中,面特指一个三角形,由三个顶点和三条边构成,对一个面所做的变化影响到连接面的所有顶点和边,面多边形

* 定义面的顶点的顺序很重要,在拼接曲面的时候,顶点的顺序定义了面的朝向(前向或是后向),为了获取绘制的高性能,一般情况不会绘制面的前面和后面,只绘制面的“前面”。虽然“前面”“后面”的定义可以应人而易,但一般为所有的“前面”定义统一的顶点顺序(顺时针或是逆时针方向)。

 

~~~~~~~~~~~~~~设置面的三种操作~~~~~~~~~~

* gl.glFrontFace(GL10.GL_CCW); //设置逆时针方法为面的"前面"。顺时针为CW

* gl.glEnable(GL10.GL_CULL_FACE);//打开忽略"后面"设置

* gl.glCullFace(GL10.GL_BACK);//明确指明“忽略“哪个面

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

4.Polygon (多边形)

多边形由多个面(三角形)拼接而成,在三维空间上,多边形不一定表示这个Polygon在同一平面上



~~~~~~实例:~~~~~

private short[] indices = {0,1,2,0,2,3};  //顶点连接顺序

ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);  //indices为short型,要*2 。(byte 8位,short 16位)

ibb.order(ByteOrder.nativeOrder());  

ShortBuffer indexBuffer = ibb.asShortBuffer(); 

indexBuffer.put(indices);  //放入数据

indexBuffer.position(0);

~~~~~~~~~~~~~~~~~~~~~~~~~~~

 


5.Render (渲染)

定义好了多边形,下面是如何使用OpenGL ES的API来绘制(渲染)这个多边形。OpenGL ES提供了两类方法来绘制一个空间几何图形:

* public abstract void glDrawArrays(int mode, int first, int count)//使用VetexBuffer来绘制,顶点的顺序由vertexBuffer中的顺序指定。若没定义indices就用这个函数

* public abstract void glDrawElements(int mode, int count, int type, Buffer indices) //可以重新定义顶点的顺序,顶点的顺序由indices指定。

* 上面两方法中的mode分类:GL_POINTS(独立的点)、GL_LINE_STRIP(按顺序不间断的一条线)、GL_LINE_LOOP(首尾封闭)、GL_LINES(两两相连的多条线段)、GL_TRIANGLES(三三组成的分离的三角形)、GL_TRIANGLE_STRIP(相连的三角形)、GL_TRIANGLE_FAN(以起点为公共顶点的相连多个三角形)

 

~~~~~~~~~~举例,下面是绘制一个正方形~~~~~~~~~~~

* Square.java

public class Square {

 private float vertices[] = {

 -1.0f,  1.0f, 0.0f,  // 0, Top Left

 -1.0f, -1.0f, 0.0f,  // 1, Bottom Left

 1.0f, -1.0f, 0.0f,  // 2, Bottom Right

 1.0f,  1.0f, 0.0f,  // 3, Top Right

 };

 private short[] indices = { 0, 1, 2, 0, 2, 3 };

 private FloatBuffer vertexBuffer;

 private ShortBuffer indexBuffer; 

 

 public Square() {

 ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);

 vbb.order(ByteOrder.nativeOrder());

 vertexBuffer = vbb.asFloatBuffer();

 vertexBuffer.put(vertices);

 vertexBuffer.position(0);

 

 ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);

 ibb.order(ByteOrder.nativeOrder());

 indexBuffer = ibb.asShortBuffer();

 indexBuffer.put(indices);

 indexBuffer.position(0);

 }

 

 public void draw(GL10 gl) {

 gl.glFrontFace(GL10.GL_CCW);

 gl.glEnable(GL10.GL_CULL_FACE);

 gl.glCullFace(GL10.GL_BACK);

 

 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

 gl.glVertexPointer(3, GL10.GL_FLOAT, 0,vertexBuffer);

 

 gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,

 GL10.GL_UNSIGNED_SHORT, indexBuffer);

 

 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

 gl.glDisable(GL10.GL_CULL_FACE);  //一般有enable必对应一个disable函数

 }

}

* 相应的在OpenGlRenderer中加入Square对象的实例化,并在其onDrawFrame函数中调用square.draw(gl);

* 这时,并不能看到画面,还需要在draw之前调用

gl.glLoadIdentity();//每次调用onDrawFrame时重置,防止每次都后移4单位

gl.glTranslatef(0, 0, -4);//由于OpenGl Es渲染时,默认坐标是(0,0,0),其中Z轴为0,这个0的基准为屏幕,即绘制时贴着屏幕画的。所以要后平移4个单位,从立体的视角“向屏幕里面去一点”

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

三:【3D坐标变换】

 

1.Coordinate System(坐标系)

OpenGl使用右手坐标系:右手拇指指x轴正向,中指y轴正向,着z轴正向为掌心向外

 

2.Translate (平移)

之前的glTranslatef(float x,float y,float z)即为平移变换函数,可以进行多次平移变换,其结果为多个平移矩阵的累计结果,矩阵的顺序不重要,可以互换

 

3.Rotate(旋转)

glRotatef(float angle,float x,float y,float z)函数,除了xyz,还有一个旋转变换角度angle,定义旋转的参照矢量方向。多次旋转次序很重要。glRotatef(angle,-x,-y,-z)和glRotatef(-angle,x,y,z)等价的。

~~~~~~~~~~~示例~~~~~~~~~~~

gl.glRotatef(90f, 1.0f, 0.0f, 0.0f);//拇指指+x,向四指方向旋转

gl.glRotatef(90f, 0.0f, 1.0f, 0.0f);//下同

gl.glRotatef(90f, 0.0f, 0.0f, 1.0f);

//***多次旋转的话坐标轴是跟随着几何体一起旋转的,下一次旋转是在前一次旋转得到的坐标轴基础上转的

~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

4.Translate & Rotate (平移和旋转组合变换)

就是上面那句话:坐标变换都是相对于变换的Mesh本身的坐标系而进行的

 

5.Scale(缩放)

方法public abstract void glScalef (float x, float y, float z)用于缩放变换。

gl.glScalef(2f, 2f, 2f)即xyz均乘以二

 

6.Translate & Scale(平移和缩放组合变换)

同样当需要平移和缩放时,变换的顺序也会影响最终结果,因为这时候单位“1”发生了变化

 

7.矩阵操作,单位矩阵

如果需要将当前矩阵回复最初的无变换的矩阵,可以使用单位矩阵(无平移,缩放,旋转),使用public abstract void glLoadIdentity()

在栈中保存当前矩阵和从栈中恢复所存矩阵,可以使用

public abstract void glPushMatrix();

public abstract void glPopMatrix();

~~~~~~~~~~~~~~~~~~~~举例~~~~~~~~~~~``~~~~~~~~

~~~绘制3个正方形A,B,C,使的B比A小50%,C比B小50%。 然后以屏幕中心逆时针旋转A,B以A为中心顺时针旋转,C以B为中心顺时针旋转同时以自己中心高速逆时针旋转

gl.glTranslatef(0, 0, -10);//得到原始矩阵

gl.glPushMatrix();//存储原始矩阵

gl.glRotatef(angle, 0, 0, 1);//变换原始矩阵,得到A

square.draw(gl);//画出A

 

gl.glPopMatrix();//回归原始矩阵

gl.glPushMatrix();//存储原始矩阵

gl.glRotatef(-angle, 0, 0, 1);//绕原始矩阵中心旋转

gl.glTranslatef(2, 0, 0);//右移

gl.glScalef(.5f, .5f, .5f);//缩小,得到B

square.draw(gl);//画出B

 

gl.glPushMatrix();//存储B

gl.glRotatef(-angle, 0, 0, 1);//绕B的中心旋转

gl.glTranslatef(2, 0, 0);//右移

gl.glScalef(.5f, .5f, .5f);//缩小

gl.glRotatef(angle*10, 0, 0, 1);//绕右移且缩小后的中心转,得到C

square.draw(gl);//画出C

 

gl.glPopMatrix();

gl.glPopMatrix();

 

angle++;//角度自增

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

四:【给图形上色】

OpenGL ES使用颜色是RGBA模式(红,绿,蓝,透明度).

不同于一般情况下的10进制的RGB,即三原色均为0~255.OpenGl中三种颜色使用0.0f~1.0f的浮点数。1相当于255。

 

1.Flat coloring(单色)

通知OpenGL使用单一的颜色来渲染,OpenGL将一直使用指定的颜色来渲染直到你指定其它的颜色,具体方法public abstract void glColor4f(float red, float green, float blue, float alpha)

缺省值均为1,即为白色不透明

 

2.Smooth coloring(平滑颜色过渡)

当给每个顶点定义一个颜色时,OpenGL自动为不同顶点颜色之间生成中间过渡颜色(渐变色)

* 颜色同顶点一样,也是用数组 + buffer的方式定义的,例如下:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

float[] colors = {

 1f, 0f, 0f, 1f, // vertex 0 red

 0f, 1f, 0f, 1f, // vertex 1 green

 0f, 0f, 1f, 1f, // vertex 2 blue

 1f, 0f, 1f, 1f, // vertex 3 magenta

};

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);

cbb.order(ByteOrder.nativeOrder());

colorBuffer = cbb.asFloatBuffer();

colorBuffer.put(colors);

colorBuffer.position(0);

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

然后在draw方法中加入

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

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

//然后要记得disable

gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

五.【从平面到立体,绘制真正的3D图形】

设计原则,创建并使用一个Mesh(网格)类来构造各种不同的3D图形。

* Mesh.java ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public class Mesh {

private FloatBuffer verticesBuffer = null;

private ShortBuffer indicesBuffer = null;

private int numOfIndices = -1;

 

private float[] rgba

= new float[] { 1.0f, 1.0f, 1.0f, 1.0f };

 

private FloatBuffer colorBuffer = null;

 

public float x = 0;

public float y = 0;

public float z = 0;

 

public float rx = 0;

public float ry = 0;

public float rz = 0;

 

public void draw(GL10 gl) {

gl.glFrontFace(GL10.GL_CCW);

gl.glEnable(GL10.GL_CULL_FACE);

gl.glCullFace(GL10.GL_BACK);

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, verticesBuffer);

gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);//渲染单色

if (colorBuffer != null) {  //若colorbuffer不为空则再渲染渐变色

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

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

}

 

gl.glTranslatef(x, y, z);

gl.glRotatef(rx, 1, 0, 0);

gl.glRotatef(ry, 0, 1, 0);

gl.glRotatef(rz, 0, 0, 1);

 

gl.glDrawElements(GL10.GL_TRIANGLES, numOfIndices,

GL10.GL_UNSIGNED_SHORT, indicesBuffer);

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisable(GL10.GL_CULL_FACE);

}

 

protected void setVertices(float[] vertices) {

ByteBuffer vbb

= ByteBuffer.allocateDirect(vertices.length * 4);

vbb.order(ByteOrder.nativeOrder());

verticesBuffer = vbb.asFloatBuffer();

verticesBuffer.put(vertices);

verticesBuffer.position(0);

}

 

protected void setIndices(short[] indices) {

ByteBuffer ibb

= ByteBuffer.allocateDirect(indices.length * 2);

ibb.order(ByteOrder.nativeOrder());

indicesBuffer = ibb.asShortBuffer();

indicesBuffer.put(indices);

indicesBuffer.position(0);

numOfIndices = indices.length;

}

 

protected void setColor(float red, float green,

float blue, float alpha) {

rgba[0] = red;

rgba[1] = green;

rgba[2] = blue;

rgba[3] = alpha;

}

 

protected void setColors(float[] colors) {

ByteBuffer cbb

= ByteBuffer.allocateDirect(colors.length * 4);

cbb.order(ByteOrder.nativeOrder());

colorBuffer = cbb.asFloatBuffer();

colorBuffer.put(colors);

colorBuffer.position(0);

}

}



//在这个Mesh类中,定义有ver(点)和ind(路径),并有相应的set方法来生成Buffer,还有颜色的set,旋转与平移的xyz值定义。在使用时,只需要定义一个图形类从Mesh派生,然后按顺序加入顶点与连接路径,或颜色,即可得到一个自定的3D图形。例如一个Cube正方体:

* Cube.java~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`

public class Cube extends Mesh {

 public Cube(float width, float height, float depth) {

 width  /= 2;

 height /= 2;

 depth  /= 2;

 

 float vertices[] = { -width, -height, -depth, // 0

 width, -height, -depth, // 1

 width,  height, -depth, // 2

 -width,  height, -depth, // 3

 -width, -height,  depth, // 4

 width, -height,  depth, // 5

 width,  height,  depth, // 6

 -width,  height,  depth, // 7

 };      //8个顶点定义好后

 

 short indices[] = { 0, 4, 5,

 0, 5, 1,

 1, 5, 6,

 1, 6, 2,

 2, 6, 7,

 2, 7, 3,

 3, 7, 4,

 3, 4, 0,

 4, 7, 6,

 4, 6, 5,

 3, 0, 1,

 3, 1, 2, };   //按一定顺序把8个点连起来

 

 setIndices(indices);

 setVertices(vertices); //两个set,就得到了一个单色正方体。

 }

}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

 

六:【材质渲染】

前面是用颜色给图形上色,这里讲的是用bitmap位图来渲染

 

1.创建Bitmap对象

方法同android中的获取bitmap的方法,即:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·

Bitmap bitmap = BitmapFactory.decodeResource(contect.getResources(),R.drawable.icon);

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* 要注意的是,有些设备对使用的Bitmap的大小有要求,要求Bitmap的宽度和长度为2的几次幂(1,2,4,8,16,32,64.。。。),如果使用不和要求的Bitmap来渲染,可能只会显示白色。

 

2.创建材质(Generating a texture)

 

* 首先,获取一个texture 的id

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

int[] textures = new int[1];

// Tell OpenGL to generate textures.

gl.glGenTextures(1, textures, 0);

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·

* textures中存放了创建的Texture ID,使用同样的Texture Id ,也可以删除一个Texture,调用方法gl.glDeleteTextures(1, textures, 0);

 

* 然后调用这个函数时通知opengl使用这个textures:gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

 

*下一步需要给Texture填充设置参数,用来渲染的Texture可能比要渲染的区域大或者小,这时需要设置Texture需要放大或是缩小时OpenGL的模式

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·

gl.glTexParameterf(GL10.GL_TEXTURE_2D,

 GL10.GL_TEXTURE_MAG_FILTER,

 GL10.GL_LINEAR);//当texures小了,需要放大

gl.glTexParameterf(GL10.GL_TEXTURE_2D,

 GL10.GL_TEXTURE_MIN_FILTER,

 GL10.GL_LINEAR);//当texures需要缩小

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·

参数GL10.GL_LINEAR和GL10.GL_NEAREST,前者是模糊处理的,后者清晰

 

3.UV Mapping

告知OpenGL库如何将Bitmap的像素映射到Mesh上,分两步

 

* <1>定义UV坐标

UV Mapping指将Bitmap的像素映射到Mesh上的顶点。UV坐标定义image左上角(0,0),右下角(1,1)(因为使用的2D Texture),即映射这两个点到vertics坐标上即可。

例如~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

float textureCoordinates[] = {0.0f, 1.0f,

 1.0f, 1.0f,

 0.0f, 0.0f,

 1.0f, 0.0f };//应该也相当于一个路径,染色顺序是左下右下左上右上

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

float textureCoordinates[] = {0.0f, 0.5f,

 0.5f, 0.5f,

 0.0f, 0.0f,

 0.5f, 0.0f };//这样会得到image左上四分之一图来渲染

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

float textureCoordinates[] = {0.0f, 2.0f,

 2.0f, 2.0f,

 0.0f, 0.0f,

 2.0f, 0.0f };//这样超出Texture的边界了,这时有两种设置方法

* GL_REPEAT 重复Texture。

* GL_CLAMP_TO_EDGE 只靠边线绘制一次

例如:

gl.glTexParameterf(GL10.GL_TEXTURE_2D,

 GL10.GL_TEXTURE_WRAP_S,

 GL10.GL_REPEAT);

gl.glTexParameterf(GL10.GL_TEXTURE_2D,

 GL10.GL_TEXTURE_WRAP_T,

 GL10.GL_REPEAT);

//这样设置的结果是UV坐标系x方向一直重复,y方向也一直重复填充

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 

* <2>绑定Texture与图片

GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

 

4.使用Texture

为了能够使用上面定义的Texture,需要创建一Buffer来存储UV坐标:

FloatBuffer byteBuf = ByteBuffer.allocateDirect(texture.length * 4);

byteBuf.order(ByteOrder.nativeOrder());

textureBuffer = byteBuf.asFloatBuffer();

textureBuffer.put(textureCoordinates);

textureBuffer.position(0);

 

5.最后是渲染

gl.glEnable(GL10.GL_TEXTURE_2D);

// Tell OpenGL where our texture is located.

gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

// Tell OpenGL to enable the use of UV coordinates.

gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

// Telling OpenGL where our UV coordinates are.

gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

 

// ... here goes the rendering of the mesh ...

 

// Disable the use of UV coordinates.

gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

// Disable the use of textures.

gl.glDisable(GL10.GL_TEXTURE_2D);

 

* * 这里有非常重要的一点,我在构造一个旋转三棱锥并往上贴图时就遇到过一个问题,图形在模拟器上运行正常,但是到了手机上就贴不上图。百度才知出现这个问题原因有很多种,首先图片的大小必须得是2的幂次。还有网友是用png格式图时,要将PNG24改成PNG8-256色解决的,另外还有人是通过建立三种dpi的drawable文件夹解决的。

 

 

到此,OpenGl ES算是入门了吧。

本文转载自:http://blog.csdn.net/caiwenfeng_for_23/article/details/36200107

蜀山下的鱼
粉丝 9
博文 405
码字总数 0
作品 0
广州
高级程序员
私信 提问
Android 使用 OpenGL ES 绘制三角形

1. OpenGL ES 简介 OpenGL 是一个跨平台的图形 API,为 3D 图形处理硬件制定了一个标准软件接口。OpenGL ES 是为嵌入式设备设计的 OpenGL 规范,Android 提供了对 OpenGL ES 的支持。 OpenGL...

落英坠露
05/02
0
0
图片和图形之用OpenGL ES显示图形(9)

原文 概要 Android框架提供了大量用于创建有吸引力的功能性图形用户界面的标准工具。但是,如果您想要更多地控制应用程序在屏幕上绘制的内容,或者冒险进入三维图形,则需要使用其他工具。A...

lichong951
2018/05/26
0
0
Android图形---OpenGL(二)

本文译自:http://developer.android.com/guide/topics/graphics/opengl.html OpenGL 包 一旦使用GLSurfaceView和GLSurfaceView.Renderer类给OpenGL建立了一个View容器,那么就可以开始使用以...

长平狐
2012/10/16
121
0
Android 自定义相机开发(三) —— 了解下EGL

胡说八道 如果要使用OpenGl来自定义相机,这个还是要了解下的。可能大多数开发者使用过OpengGL但是不知道EGL是什么?EGL的作用是什么?这其实一点都不奇怪,因为Android中的GlSurfaceView已经...

aserbao
2018/05/10
0
0
Android图形---OpenGL(一)

本文译自:http://developer.android.com/guide/topics/graphics/opengl.html Android系统包含了OpenGL(Open Graphics Library),从而给2D和3D图形提供了高性能的支持,尤其是OpenGL ES A...

长平狐
2012/10/16
253
0

没有更多内容

加载失败,请刷新页面

加载更多

Redis缓存NoSQL

redis的应用场景有哪些 1、会话缓存(最常用) 2、消息队列,比如支付 3、活动排行榜或计数 4、发布、订阅消息(消息通知) 5、商品列表、评论列表等

BobwithB
14分钟前
2
0
「绘画技巧」一分钟画出动漫人物的喜怒哀乐中“喜”的各种表情

「绘画技巧」一分钟画出动漫人物的喜怒哀乐中“喜”的各种表情 表情拥有着可以凸显动漫人物情绪和主张的魔力,表情渲染整个环境。那么今天来和大家一起分享自己整理收集动漫人物喜怒哀乐中的...

知北
17分钟前
3
0
从流中的三种求和方式谈起

//使用reduce()方法int reduce = Arrays.asList(ins).stream().reduce(0, Integer::sum);//Collectors类的工厂方法,收集器int collect1 = Arrays.asList(ins).stream().collect(Colle......

我的眼里只有眼屎
18分钟前
2
0
File类的使用(文件与文件夹,获取,判断存在,删除,)

//File类的使用 public static void main(String[] args) throws IOException, ClassNotFoundException { //test3();// File f = new File("E:\\资料\\第二阶段\\d......

zhengzhixiang
22分钟前
2
0
58到家MySQL军规升级版

转载 2018-03-30 58到家DBA 架构师之路 一、基础规范 表存储引擎必须使用InnoDB 表字符集默认使用utf8,必要时候使用utf8mb4 解读: 通用,无乱码风险,汉字3字节,英文1字节 utf8...

xiaolyuh
29分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部