OpenGL 绘图 – 材质渲染
注:参考:http://wiki.jikexueyuan.com/project/opengl-es-basics/texture-rendering.html
创建 Bitmap 对象
使用材质渲染,首先需要构造用来渲染的 Bitmap 对象,Bitmap 对象可以从资源文件中读取或是从网路下载或是使用代码构造。为简单起见,本例从资源中读取,在Renderer类中创建设置Bitmap方法(需在setRenderer前调用):
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
要注意的是,有些设备对使用的 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 texture
gl.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 坐标
UV Mapping 指将 Bitmap 的像素映射到 Mesh 上的顶点。UV 坐标定义为左上角(0,0),右下角(1,1)(因为使用的 2D Texture),下图坐标显示了 UV 坐标,右边為我们需要染色的平面的顶点順序:
为了能正确的匹配,需要把 UV 坐标中的(0,0)映射到顶点 0,(0,1)映射到顶点 2 等等。
float textureCoordinates[] = {0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.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,需要创建一 Buffer 來存储 UV 坐标:
ByteBuffer byteBuf = ByteBuffer.allocateDirect(textureCoordinates.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
FloatBuffer textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(textureCoordinates);
textureBuffer.position(0);
渲染
//开启2D材质渲染
gl.glEnable(GL10.GL_TEXTURE_2D);
//开启材质渲染UV坐标管道
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//开启点坐标管道
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//开启点颜色管道
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
//传入点坐标
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
//传入点颜色数组
gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
//传入UV坐标
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
//根据点与绘线顺序绘面
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,
GL10.GL_UNSIGNED_SHORT, indexBuffer);
//关闭点颜色管道
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
//关闭点坐标管道
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
//关闭材质渲染UV坐标管道
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//关闭2D材质渲染
gl.glDisable(GL10.GL_TEXTURE_2D);
// Delete a texture.(如果不删除,如果不断绘画,应用所占运存会不断增加)
gl.glDeleteTextures(1, textures, 0);
}
Demo
本例代码同样在上次中更改
在drawREC中
添加UV坐标
float textureCoordinates[] = {0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f};
ByteBuffer byteBuf = ByteBuffer.allocateDirect(textureCoordinates.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
FloatBuffer textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(textureCoordinates);
textureBuffer.position(0);
生成材质并绑定
int[] textures = new int[1];
// Tell OpenGL to generate textures.
gl.glGenTextures(1, textures, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
配置材质属性
// 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 texture
gl.glTexParameterf(GL10.GL_TEXTURE_2D,
GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_LINEAR);
//重复Texture去渲染不存在的Texture部分
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绑定起来
//将 Bitmap 资源和 Texture 绑定起來:
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
绘图
//开启2D材质渲染
gl.glEnable(GL10.GL_TEXTURE_2D);
//开启材质渲染UV坐标管道
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//开启点坐标管道
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//开启点颜色管道
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
//传入点坐标
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
//传入点颜色数组
gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
//传入UV坐标
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
//根据点与绘线顺序绘面
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,
GL10.GL_UNSIGNED_SHORT, indexBuffer);
//关闭点颜色管道
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
//关闭点坐标管道
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
//关闭材质渲染UV坐标管道
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
//关闭2D材质渲染
gl.glDisable(GL10.GL_TEXTURE_2D);
// Delete a texture.(如果不删除,如果不断绘画,应用所占运存会不断增加)
gl.glDeleteTextures(1, textures, 0);
效果图:
代码:http://download.youkuaiyun.com/download/z896435317/9960486