Android OpenGL ES (2) -- 纹理
来源:互联网 发布:js正则表达式\< 编辑:程序博客网 时间:2024/04/27 22:27
五颜六色的立方体并算是什么太有意思的事情,看上去太假,没什么感觉。 解决办法就是纹理贴图了。
OpenGL 中使用纹理要先用 glEnable 来启用相关功能
BitmapFactory.decodeStream 从流中加载并解码图片并生成Bitmap对象。令人不解的是更解法的 decodeResource 方法在虚拟机中工作良好,但到我的手机中就不行了。
glGenTextures 生成一组纹理并把纹理的ID存入数组参数中。这里只生成了一个。
glBindTexture 将指定ID的纹理绑定到指定的目标中去,接下来对目录所作的操作将针对该纹理进行。
glTexParameterf 设置纹理参数,这里设置了4个参数:
在 createBuffers 中添加
最终代码:
OpenGL 中使用纹理要先用 glEnable 来启用相关功能
gl.glEnable(GL10.GL_TEXTURE_2D);然后先准备一张图片作为纹理贴图,需要注意的是,有些设备对图片的尺寸有要求,我手上这个G7就只支持方形的纹理图片,其它可能的限制还有长宽必须是 2 的 n 次幂,最大尺寸不能超过256或1024等等。弄好图片之后,把它放到 res/drawable 文件夹中,然后通过资源加载到纹理 。
private void loadTexture(GL10 gl) {InputStream bitmapStream = null;Bitmap bitmap = null;try {bitmapStream = context.getResources().openRawResource(R.drawable.tree);bitmap = BitmapFactory.decodeStream(bitmapStream); int[] textures = new int[1];gl.glGenTextures(1, textures, 0);texture = textures[0]; gl.glBindTexture(GL10.GL_TEXTURE_2D, texture); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR); 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); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); } finally {if (bitmap != null)bitmap.recycle(); if (bitmapStream != null)try {bitmapStream.close();} catch (IOException e) {}}}
BitmapFactory.decodeStream 从流中加载并解码图片并生成Bitmap对象。令人不解的是更解法的 decodeResource 方法在虚拟机中工作良好,但到我的手机中就不行了。
glGenTextures 生成一组纹理并把纹理的ID存入数组参数中。这里只生成了一个。
glBindTexture 将指定ID的纹理绑定到指定的目标中去,接下来对目录所作的操作将针对该纹理进行。
glTexParameterf 设置纹理参数,这里设置了4个参数:
GL_TEXTURE_MIN_FILTER 和 GL_TEXTURE_MAG_FILTER 指定纹理在被缩小或放大时使用的过滤方式,LINEAR (线性插值?)效果要比 NEAREST(最近点?)好但也更需要更多运算。
GL_TEXTURE_WRAP_S 和 GL_TEXTURE_WRAP_T 表示当贴图坐标不在 0.0-1.0 之间时如何处理,这里使用 REPEAT 即平铺贴图。
GLUtils.texImage2D 辅助方法用于将 Bitmap 对象设置到纹理目录中,设置完后 Bitmap 对象即不再需要,可以丢弃。
最后,在 onSurfaceCreated 中调用 loadTexture 加载纹理。将在 HelloWorldRenderer 构造方法中将参数 Main Activity 存入成员变量 context 中以便在 loadTexture 中用于访问资源。
在绘制图元之前,使用 glBindTexture 将纹理绑定到目标中,在接下来的绘制中纹理将自动应用。但在此之前,还需要设置好纹理坐标
private float[] data_tvertices = { 1.0000f, 1.0000f, 1.0000f, 0.0000f,0.0000f, 0.0000f, 0.0000f, 0.0000f, 0.0000f, 1.0000f, 1.0000f,1.0000f, 0.0000f, 1.0000f, 1.0000f, 1.0000f, 1.0000f, 0.0000f,1.0000f, 0.0000f, 0.0000f, 0.0000f, 0.0000f, 1.0000f, 0.0000f,1.0000f, 1.0000f, 1.0000f, 1.0000f, 0.0000f, 1.0000f, 0.0000f,0.0000f, 0.0000f, 0.0000f, 1.0000f, 0.0000f, 1.0000f, 1.0000f,1.0000f, 1.0000f, 0.0000f, 1.0000f, 0.0000f, 0.0000f, 0.0000f,0.0000f, 1.0000f, 0.0000f, 1.0000f, 1.0000f, 1.0000f, 1.0000f,0.0000f, 1.0000f, 0.0000f, 0.0000f, 0.0000f, 0.0000f, 1.0000f,0.0000f, 1.0000f, 1.0000f, 1.0000f, 1.0000f, 0.0000f, 1.0000f,0.0000f, 0.0000f, 0.0000f, 0.0000f, 1.0000f, };以上坐标是由3ds max 场景中导出,除此之外将原有的顶点坐标及顶点索引数组的内容也一并更新,也是从同一 3ds max 场景中导出(该场景只有一个立方体)
private float[] data_vertices = { -5.0f, -5.0f, -5.0f, -5.0f, 5.0f, -5.0f,5.0f, 5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f, -5.0f, -5.0f, -5.0f,-5.0f, -5.0f, -5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, 5.0f,5.0f, 5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, -5.0f, -5.0f, 5.0f,-5.0f, -5.0f, -5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, 5.0f, 5.0f,-5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, -5.0f, -5.0f, 5.0f, -5.0f,-5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f,-5.0f, 5.0f, 5.0f, -5.0f, -5.0f, 5.0f, 5.0f, -5.0f, -5.0f, 5.0f,-5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f,5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, -5.0f, -5.0f, -5.0f, -5.0f,-5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f,-5.0f, }; private byte[] data_triangles = { 0, 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, };
在 createBuffers 中添加
tvertices = ByteBuffer.allocateDirect(data_tvertices.length * 4); tvertices.order(ByteOrder.nativeOrder()); tvertices.asFloatBuffer().put(data_tvertices); tvertices.position(0);最后在绘制代码中添加纹理及纹理坐标设置的代码
// 启用顶点数组、法向量、纹理坐标数组 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // 设置顶点数组指针为 ByteBuffer 对象 vertices // 第一个参数为每个顶点包含的数据长度(以第二个参数表示的数据类型为单位) gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertices); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, tvertices); // 绑定纹理 gl.glBindTexture(GL10.GL_TEXTURE_2D, texture); // 绘制 triangles 表示的三角形 gl.glDrawElements(GL10.GL_TRIANGLES, triangles.remaining(), GL10.GL_UNSIGNED_BYTE, triangles); // 禁用顶点、法向量、纹理坐标数组 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);修改投景变换矩阵以显示这个稍大此的立方体
GLU.gluLookAt(gl, -20f, -20f, 20f, 0f, 0f, 0f, 0, 0, 1);运行,这次立方体的六个面都贴上了同一张图片。
最终代码:
// file : HelloWorldRenderer.java package com.leftart.android.HelloWorld; import java.nio.*;import javax.microedition.khronos.egl.*;import javax.microedition.khronos.opengles.*;import android.content.Context;import android.graphics.*;import android.opengl.GLSurfaceView.Renderer;import android.opengl.*; public class HelloWorldRenderer implements Renderer {public HelloWorldRenderer(Main main) {this.context = main;createBuffers();} public void onSurfaceCreated(GL10 gl, EGLConfig config) {gl.glDisable(GL10.GL_DITHER); // 颜色抖动据说可能严重影响性能,禁用gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);// 设置清除颜色缓冲区时用的RGBA颜色值 gl.glEnable(GL10.GL_DEPTH_TEST);gl.glDepthFunc(GL10.GL_LEQUAL);gl.glClearDepthf(1f); gl.glEnable(GL10.GL_TEXTURE_2D);loadTexture(gl);} public void onSurfaceChanged(GL10 gl, int width, int height) {// 宽高比float aspect = (float) width / (float) (height == 0 ? 1 : height); // 设置视口gl.glViewport(0, 0, width, height); // 设置当前矩阵堆栈为投影矩阵,并将矩阵重置为单位矩阵gl.glMatrixMode(GL10.GL_PROJECTION);gl.glLoadIdentity(); GLU.gluPerspective(gl, 45.0f, aspect, 0.1f, 200.0f);GLU.gluLookAt(gl, -20f, -20f, 20f, 0f, 0f, 0f, 0, 0, 1);} public void onDrawFrame(GL10 gl) {// 清除颜色缓冲gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // 设置当前矩阵堆栈为模型堆栈,并重置堆栈,// 即随后的矩阵操作将应用到要绘制的模型上gl.glMatrixMode(GL10.GL_MODELVIEW);gl.glLoadIdentity(); // 将旋转矩阵应用到当前矩阵堆栈上,即旋转模型gl.glRotatef(anglez, 0, 0, 1);gl.glRotatef(angley, 0, 1, 0);gl.glRotatef(anglex, 1, 0, 0);anglex += 0.1; // 递增角度值以便每次以不同角度绘制angley += 0.2;anglez += 0.3; // 启用顶点数组、法向量、纹理坐标数组gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // 设置正面gl.glFrontFace(GL10.GL_CW);// 设置顶点数组指针为 ByteBuffer 对象 vertices// 第一个参数为每个顶点包含的数据长度(以第二个参数表示的数据类型为单位)gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertices);gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, tvertices);// 绑定纹理gl.glBindTexture(GL10.GL_TEXTURE_2D, texture); // 绘制 triangles 表示的三角形gl.glDrawElements(GL10.GL_TRIANGLES, triangles.remaining(),GL10.GL_UNSIGNED_BYTE, triangles); // 禁用顶点、法向量、纹理坐标数组gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);} private void createBuffers() {// 创建顶点缓冲,顶点数组使用 float 类型,每个 float 长4个字节vertices = ByteBuffer.allocateDirect(data_vertices.length * 4);// 设置字节顺序为本机顺序vertices.order(ByteOrder.nativeOrder());// 通过一个 FloatBuffer 适配器,将 float 数组写入 ByteBuffer 中vertices.asFloatBuffer().put(data_vertices);// 重置Buffer的当前位置vertices.position(0); // 创建索引缓冲,索引使用 byte 类型,所以无需设置字节顺序,也无需写入适配。triangles = ByteBuffer.allocateDirect(data_triangles.length * 2);triangles.put(data_triangles);triangles.position(0); normals = ByteBuffer.allocateDirect(data_normals.length * 4);normals.order(ByteOrder.nativeOrder());normals.asFloatBuffer().put(data_normals);normals.position(0); tvertices = ByteBuffer.allocateDirect(data_tvertices.length * 4);tvertices.order(ByteOrder.nativeOrder());tvertices.asFloatBuffer().put(data_tvertices);tvertices.position(0);} private void loadTexture(GL10 gl) {InputStream bitmapStream = null;Bitmap bitmap = null;try {bitmapStream = context.getResources().openRawResource(R.drawable.tree);bitmap = BitmapFactory.decodeStream(bitmapStream); int[] textures = new int[1];gl.glGenTextures(1, textures, 0);texture = textures[0]; gl.glBindTexture(GL10.GL_TEXTURE_2D, texture); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR); 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); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); } finally {if (bitmap != null)bitmap.recycle(); if (bitmapStream != null)try {bitmapStream.close();} catch (IOException e) {}}}private Context context;private ByteBuffer vertices;private ByteBuffer triangles;private ByteBuffer normals;private ByteBuffer tvertices;private int texture; private float anglex = 0f;private float angley = 0f;private float anglez = 0f; private float[] data_vertices = { -5.0f, -5.0f, -5.0f, -5.0f, 5.0f, -5.0f,5.0f, 5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f, -5.0f, -5.0f, -5.0f,-5.0f, -5.0f, -5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, 5.0f,5.0f, 5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, -5.0f, -5.0f, 5.0f,-5.0f, -5.0f, -5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, 5.0f, 5.0f,-5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, -5.0f, -5.0f, 5.0f, -5.0f,-5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f,-5.0f, 5.0f, 5.0f, -5.0f, -5.0f, 5.0f, 5.0f, -5.0f, -5.0f, 5.0f,-5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f,5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, -5.0f, -5.0f, -5.0f, -5.0f,-5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f,-5.0f, };private float[] data_normals = { -5.0f, -5.0f, -5.0f, -5.0f, 5.0f, -5.0f,5.0f, 5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f, -5.0f, -5.0f, -5.0f,-5.0f, -5.0f, -5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, 5.0f,5.0f, 5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, -5.0f, -5.0f, 5.0f,-5.0f, -5.0f, -5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, 5.0f, 5.0f,-5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, -5.0f, -5.0f, 5.0f, -5.0f,-5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f,-5.0f, 5.0f, 5.0f, -5.0f, -5.0f, 5.0f, 5.0f, -5.0f, -5.0f, 5.0f,-5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f,5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, -5.0f, -5.0f, -5.0f, -5.0f,-5.0f, 5.0f, -5.0f, -5.0f, 5.0f, -5.0f, 5.0f, 5.0f, -5.0f, 5.0f,-5.0f, }; private float[] data_tvertices = { 1.0000f, 1.0000f, 1.0000f, 0.0000f,0.0000f, 0.0000f, 0.0000f, 0.0000f, 0.0000f, 1.0000f, 1.0000f,1.0000f, 0.0000f, 1.0000f, 1.0000f, 1.0000f, 1.0000f, 0.0000f,1.0000f, 0.0000f, 0.0000f, 0.0000f, 0.0000f, 1.0000f, 0.0000f,1.0000f, 1.0000f, 1.0000f, 1.0000f, 0.0000f, 1.0000f, 0.0000f,0.0000f, 0.0000f, 0.0000f, 1.0000f, 0.0000f, 1.0000f, 1.0000f,1.0000f, 1.0000f, 0.0000f, 1.0000f, 0.0000f, 0.0000f, 0.0000f,0.0000f, 1.0000f, 0.0000f, 1.0000f, 1.0000f, 1.0000f, 1.0000f,0.0000f, 1.0000f, 0.0000f, 0.0000f, 0.0000f, 0.0000f, 1.0000f,0.0000f, 1.0000f, 1.0000f, 1.0000f, 1.0000f, 0.0000f, 1.0000f,0.0000f, 0.0000f, 0.0000f, 0.0000f, 1.0000f, }; private byte[] data_triangles = { 0, 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, };}
- Android OpenGL ES (2) -- 纹理
- android opengl es 正方体纹理效果
- android opengl es--纹理映射,光照
- Android OpenGl es 纹理坐标设定
- android opengl es 纹理贴图资料
- android opengl es绘制三角形+纹理
- android OpenGl Es实现正方体多纹理
- Android Opengl ES 2.0 纹理贴图
- Android OpenGL ES(二)纹理
- android opengl es 正方体纹理效果
- Android OpenGL ES 2.0绘图:绘制纹理
- Android OpenGL ES 应用(二) 纹理
- Android OpenGL ES(八)----纹理编程框架
- Android OpenGL ES 3.0 纹理应用
- Android OpenGL ES 2.0绘图:绘制纹理
- Android OpenGL ES(七)----理解纹理与纹理过滤
- OpenGL ES 2.0总结(2)-纹理
- OpenGL ES纹理管理
- Struts2.18 Poi-3.7 Excel 导入导出 .
- 各国模拟电视制式
- Html 常用事件列表
- 两个月了,不搞acm感觉不知点算了
- redboot下jffs2文件系统详解
- Android OpenGL ES (2) -- 纹理
- Oracle v$nls_parameters 和 nls_database_parameters 区别
- BBED的安装与使用
- ZOJ1094 POJ2246Matrix Chain Multiplication
- perror ( )
- Eclipse Helios 3.6.2 官网下载地址
- 玩的就是ROM,解锁BootLoader大势所趋!
- QT for hello world
- java加密算法