前面讨论了如何给3D图形染色,更一般的情况是使用位图来给Mesh上色(渲染材质)。主要步骤如下:
创建Bitmap对象
使用材质渲染,首先需要构造用来渲染的Bitmap对象,Bitmap对象可以从资源文件中读取或是从网络下载或是使用代码构造。为简单起见,本例从资源中读取:
|
1
2
|
Bitmap bitmap = BitmapFactory.decodeResource(contect.getResources(),R.drawable.icon); |
要注意的是,有些设备对使用的Bitmap的大小有要求,要求Bitmap的宽度和长度为2的几次幂(1,2,4,8,16,32,64.。。。),如果使用不和要求的Bitmap来渲染,可能只会显示白色。
创建材质(Generating a texture)
下一步使用OpenGL库创建一个材质(Texture),首先是获取一个Texture Id。
|
1
2
3
4
5
|
// Create an int array with the number of textures we want,// in this case 1.int[] textures =newint[1];// Tell OpenGL to generate textures.gl.glGenTextures(1, textures,0); |
textures中存放了创建的Texture ID,使用同样的Texture Id ,也可以来删除一个Texture:
|
1
2
|
// Delete a texture.gl.glDeleteTextures(1, textures,0) |
有了Texture Id之后,就可以通知OpenGL库使用这个Texture:
|
1
|
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); |
设置Texture参数glTexParameter
下一步需要给Texture填充设置参数,用来渲染的Texture可能比要渲染的区域大或者小,这是需要设置Texture需要放大或是缩小时OpenGL的模式:
|
1
2
3
4
5
6
7
8
9
|
// Scale up if the texture if smaller.gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR);// scale linearly when image smalled than texturegl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR); |
常用的两种模式为GL10.GL_LINEAR和GL10.GL_NEAREST。
需要比较清晰的图像使用GL10.GL_NEAREST:
而使用GL10.GL_LINEAR则会得到一个较模糊的图像:
UV
Mapping
下一步要告知OpenGL库如何将Bitmap的像素映射到Mesh上。这可以分为两步来完成:
定义UV坐标
UV Mapping指将Bitmap的像素映射到Mesh上的顶点。UV坐标定义为左上角(0,0),右下角(1,1)(因为使用的2D Texture),下图坐标显示了UV坐标,右边为我们需要染色的平面的顶点顺序:
为了能正确的匹配,需要把UV坐标中的(0,1)映射到顶点0,(1,1)映射到顶点2等等。
|
1
2
3
4
|
floattextureCoordinates[] = {0.0f,1.0f,1.0f,1.0f,0.0f,0.0f,1.0f,0.0f }; |
如果使用如下坐标定义:
|
1
2
3
4
|
floattextureCoordinates[] = {0.0f,0.5f,0.5f,0.5f,0.0f,0.0f,0.5f,0.0f }; |
Texture匹配到Plane的左上角部分。
而
|
1
2
3
4
|
floattextureCoordinates[] = {0.0f,2.0f,2.0f,2.0f,0.0f,0.0f,2.0f,0.0f }; |
将使用一些不存在的Texture去渲染平面(UV坐标为0,0-1,1 而 (0,0)-(2,2)定义超过UV定义的大小),这时需要告诉OpenGL库如何去渲染这些不存在的Texture部分。
有两种设置
- GL_REPEAT重复Texture。
- GL_CLAMP_TO_EDGE只靠边线绘制一次。
下面有四种不同组合:
本例使用如下配置:
|
1
2
3
4
5
6
|
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); |
然后是将Bitmap资源和Texture绑定起来:
|
1
|
GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0, bitmap,0); |
使用Texture
为了能够使用上面定义的Texture,需要创建一Buffer来存储UV坐标:
|
1
2
3
4
5
|
FloatBuffer byteBuf = ByteBuffer.allocateDirect(texture.length *4);byteBuf.order(ByteOrder.nativeOrder());textureBuffer = byteBuf.asFloatBuffer();textureBuffer.put(textureCoordinates);textureBuffer.position(0); |
渲染
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// Telling OpenGL to enable textures.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); |
本例代码是在一个平面上(SimplePlane)下使用Texture来渲染,首先是修改Mesh基类,使它能够支持定义UV 坐标:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
// Our UV texture buffer.privateFloatBuffer mTextureBuffer;/*** Set the texture coordinates.** @param textureCoords*/protectedvoidsetTextureCoordinates(float[]
textureCoords) {// float is 4 bytes, therefore we multiply the number if// vertices with 4.ByteBuffer byteBuf = ByteBuffer.allocateDirect(textureCoords.length *4);byteBuf.order(ByteOrder.nativeOrder());mTextureBuffer = byteBuf.asFloatBuffer();mTextureBuffer.put(textureCoords);mTextureBuffer.position(0);} |
并添加设置Bitmap和创建Texture的方法:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
// Our texture id.privateintmTextureId = -1;// The bitmap we want to load as a texture.privateBitmap mBitmap;/*** Set the bitmap to load into a texture.** @param bitmap*/publicvoidloadBitmap(Bitmap bitmap) {this.mBitmap = bitmap;mShouldLoadTexture =true;}/*** Loads the texture.** @param gl*/privatevoidloadGLTexture(GL10 gl) {// Generate one texture pointer...int[] textures =newint[1];gl.glGenTextures(1, textures,0);mTextureId = textures[0];// ...and bind it to our arraygl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);// Create Nearest Filtered Texturegl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR);// Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGEgl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,GL10.GL_CLAMP_TO_EDGE);gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,GL10.GL_REPEAT);// Use theAndroidGLUtils to specify a two-dimensional texture image// from our bitmapGLUtils.texImage2D(GL10.GL_TEXTURE_2D,0, mBitmap,0);} |
最后修改draw方法来渲染材质:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
// Indicates if we need to load the texture.privatebooleanmShouldLoadTexture =false;/*** Render the mesh.** @param gl* the OpenGL context to render to.*/publicvoiddraw(GL10 gl) {...// Smooth colorif(mColorBuffer !=null)
{// Enable the color array buffer to be used during rendering.gl.glEnableClientState(GL10.GL_COLOR_ARRAY);gl.glColorPointer(4, GL10.GL_FLOAT,0,
mColorBuffer);}if(mShouldLoadTexture) {loadGLTexture(gl);mShouldLoadTexture =false;}if(mTextureId != -1&&
mTextureBuffer !=null) {gl.glEnable(GL10.GL_TEXTURE_2D);// Enable the texture stategl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);// Point to our buffersgl.glTexCoordPointer(2, GL10.GL_FLOAT,0,
mTextureBuffer);gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);}gl.glTranslatef(x, y, z);...// Point out the where the color buffer is.gl.glDrawElements(GL10.GL_TRIANGLES, mNumOfIndices,GL10.GL_UNSIGNED_SHORT, mIndicesBuffer);...if(mTextureId != -1&&
mTextureBuffer !=null) {gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);}...} |
本例使用的SimplePlane定义如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
packagese.jayway.opengl.tutorial.mesh;/*** SimplePlane is a setup class for Mesh that creates a plane mesh.** @author Per-Erik Bergman (per-erik.bergman@jayway.com)**/publicclassSimplePlaneextendsMesh
{/*** Create a plane with a default with and height of 1 unit.*/publicSimplePlane() {this(1,1);}/*** Create a plane.** @param width* the width of the plane.* @param height* the height of the plane.*/publicSimplePlane(floatwidth,floatheight)
{// Mapping coordinates for the verticesfloattextureCoordinates[] = {0.0f,2.0f,//2.0f,2.0f,//0.0f,0.0f,//2.0f,0.0f,//};short[] indices =newshort[]
{0,1,2,1,3,2};float[] vertices =newfloat[]
{ -0.5f, -0.5f,0.0f,0.5f, -0.5f,0.0f,-0.5f,0.5f,0.0f,0.5f,0.5f,0.0f
};setIndices(indices);setVertices(vertices);setTextureCoordinates(textureCoordinates);}} |

本例示例代码下载见http://www.linuxidc.com/Linux/2011-10/45756p8.htm,到本篇为止介绍了OpenGL ES开发的基本方法,更详细的教程将在以后发布,后面先回到AndroidApiDemos中OpenGL ES的示例。
前面简单介绍了OpenGL ES的开发:
- AndroidOpenGL ES 简明开发教程一:概述
-
AndroidOpenGL ES 简明开发教程二:构造OpenGL ES View
- AndroidOpenGL ES 简明开发教程三:3D绘图基本概念
- AndroidOpenGL ES 简明开发教程四:3D 坐标变换
- AndroidOpenGL ES 简明开发教程五:添加颜色
- AndroidOpenGL ES 简明开发教程六: 真正的3D图形
- AndroidOpenGL ES 简明开发教程七:材质渲染
和2D图形相比,3D绘图要复杂的多,Android提供了OpenGL ES 3D 图形开发包,对应熟悉OpenGL开发的不会很难,但如果一直没有从事3D开发过,一时还不容易上手,因此暂时跳过Android ApiDemos 中后OpenGL相关的例子,计划将在后面详细介绍Android OpenGL ES开发,之后补上这部分例子。
ApiDemo 中 OpenGL ES 示例解析
Graphics/OpenGL ES/Compressed Texture
Graphics/OpenGL ES/Cube Map
Graphics/OpenGL ES/Frame Buffer Object
Graphics/OpenGL ES/GLSurfaceView
Graphics/OpenGL ES/Kube
Graphics/OpenGL ES/Matrix Palette Skinning
Graphics/OpenGL ES/OpenGL ES 2.0
Graphics/OpenGL ES/Sprite Text
Graphics/OpenGL ES/Textured Triangle
Graphics/OpenGL ES/Touch Rotate
Graphics/OpenGL ES/Translucent GLSurfaceView
Graphics/SurfaceView Overlay
本文全部源码下载:
免费下载地址在http://linux.linuxidc.com/
用户名与密码都是www.linuxidc.com
具体下载目录在/pub/Android源码集锦/2011年/10月/Android OpenGL ES 简明开发教程相关源码/
1362

被折叠的 条评论
为什么被折叠?



