Android OpenGL ES 简明开发教程七 材质渲染

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

前面讨论了如何给3D图形染色,更一般的情况是使用位图来给Mesh上色(渲染材质)。主要步骤如下:

创建Bitmap对象

使用材质渲染,首先需要构造用来渲染的Bitmap对象,Bitmap对象可以从资源文件中读取或是从网络下载或是使用代码构造。为简单起见,本例从资源中读取:

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。

// Create an int array with the number of textures we want,// in this case 1.int[] textures = new int[1];// Tell OpenGL to generate textures.gl.glGenTextures(1, textures, 0);


textures中存放了创建的Texture ID,使用同样的Texture Id ,也可以来删除一个Texture:

// Delete a texture.gl.glDeleteTextures(1, textures, 0)


有了Texture Id之后,就可以通知OpenGL库使用这个Texture:

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

设置Texture参数glTexParameter

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

// 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等等。


float textureCoordinates[] = {0.0f, 1.0f1.0f, 1.0f0.0f, 0.0f1.0f, 0.0f };


 

如果使用如下坐标定义:

float textureCoordinates[] = {0.0f, 0.5f0.5f, 0.5f0.0f, 0.0f0.5f, 0.0f };

Texture匹配到Plane的左上角部分。

float textureCoordinates[] = {0.0f, 2.0f2.0f, 2.0f0.0f, 0.0f2.0f, 0.0f };

将使用一些不存在的Texture去渲染平面(UV坐标为0,0-1,1 而 (0,0)-(2,2)定义超过UV定义的大小),这时需要告诉OpenGL库如何去渲染这些不存在的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);

然后是将Bitmap资源和Texture绑定起来:


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

使用Texture

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

  1. <code class="language-java">FloatBuffer byteBuf = ByteBuffer.allocateDirect(texture.length * 4);  
  2. byteBuf.order(ByteOrder.nativeOrder());  
  3. textureBuffer = byteBuf.asFloatBuffer();  
  4. textureBuffer.put(textureCoordinates);  
  5. textureBuffer.position(0);</code>  
FloatBuffer byteBuf = ByteBuffer.allocateDirect(texture.length * 4);byteBuf.order(ByteOrder.nativeOrder());textureBuffer = byteBuf.asFloatBuffer();textureBuffer.put(textureCoordinates);textureBuffer.position(0);


 

 

 
 


渲染

// 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 坐标:


// Our UV texture buffer.private FloatBuffer mTextureBuffer; /** * Set the texture coordinates. * * @param textureCoords */protected void setTextureCoordinates(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的方法:

// Our texture id.private int mTextureId = -1// The bitmap we want to load as a texture.private Bitmap mBitmap; /** * Set the bitmap to load into a texture. * * @param bitmap */public void loadBitmap(Bitmap bitmap) this.mBitmap = bitmap; mShouldLoadTexture = true;} /** * Loads the texture. * * @param gl */private void loadGLTexture(GL10 gl) // Generate one texture pointer... int[] textures = new int[1]; gl.glGenTextures(1, textures, 0); mTextureId = textures[0];  // ...and bind it to our array gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);  // Create Nearest Filtered Texture gl.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_EDGE gl.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 the Android GLUtils to specify a two-dimensional texture image // from our bitmap GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);}

最后修改draw方法来渲染材质:


// Indicates if we need to load the texture.private boolean mShouldLoadTexture = false/** * Render the mesh. * * @param gl *            the OpenGL context to render to. */public void draw(GL10 gl) { ...  // Smooth color if (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 state gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);  // Point to our buffers gl.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定义如下:

 

 

package se.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) * */public class SimplePlane extends Mesh /** * Create a plane with a default with and height of 1 unit. */ public SimplePlane() this(1, 1); }  /** * Create a plane. * * @param width *            the width of the plane. * @param height *            the height of the plane. */ public SimplePlane(float width, float height) // Mapping coordinates for the vertices float textureCoordinates[] = { 0.0f, 2.0f, // 2.0f, 2.0f, // 0.0f, 0.0f, // 2.0f, 0.0f, // };  short[] indices = new short[] { 0, 1, 2, 1, 3, 2 };  float[] vertices = new float[] { -0.5f, -0.5f, 0.0f0.5f, -0.5f, 0.0f, -0.5f0.5f, 0.0f0.5f, 0.5f, 0.0f };  setIndices(indices); setVertices(vertices); setTextureCoordinates(textureCoordinates); }}

本例示例代码下载 ,到本篇为止介绍了OpenGL ES开发的基本方法,更详细的教程将在以后发布,后面先回到Android ApiDemos中OpenGL ES的示例。

 

           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow
这里写图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值