Android OpenGL ES 绘图 -- 材质渲染

xiaoxiao2021-02-28  51

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.csdn.net/download/z896435317/9960486

转载请注明原文地址: https://www.6miu.com/read-85352.html

最新回复(0)