博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android OpenGL ES(二)纹理
阅读量:5273 次
发布时间:2019-06-14

本文共 5221 字,大约阅读时间需要 17 分钟。

五颜六色的立方体并算是什么太有意思的事情,看上去太假,没什么感觉。 解决办法就是纹理贴图了。

OpenGL 中使用纹理要先用 glEnable 来启用相关功能

1
gl.glEnable(GL10.GL_TEXTURE_2D);

然后先准备一张图片作为纹理贴图,需要注意的是,有些设备对图片的尺寸有要求,我手上这个G7就只支持方形的纹理图片,其它可能的限制还有长宽必须是 2 的 n 次幂,最大尺寸不能超过256或1024等等。弄好图片之后,把它放到 res/drawable 文件夹中,比如 leftcode.png,然后通过资源加载到纹理

private void loadTexture(GL10 gl) {    InputStream bitmapStream = null;    Bitmap bitmap = null;    try {        // 打开图片资源流        bitmapStream = context.getResources().openRawResource(                R.drawable.leftcode);        // 解码图片生成 Bitmap 实例        bitmap = BitmapFactory.decodeStream(bitmapStream);          // 生成一个纹理对象,并将其ID保存到成员变量 texture 中        int[] textures = new int[1];        gl.glGenTextures(1, textures, 0);        texture = textures[0];          // 将生成的空纹理绑定到当前2D纹理通道        gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);          // 设置2D纹理通道当前绑定的纹理的属性        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);          // 将bitmap应用到2D纹理通道当前绑定的纹理中        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);      } finally {        // 释放资源        // BTW: 期待 android 早日支持 Java 新的 try-with-resource 语法          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 对象即不再需要,可以丢弃。

最后,将在 HelloWorldRenderer 构造方法中将参数 Main Activity 存入成员变量 context 中以便在 loadTexture 中用于访问资源。并在 onSurfaceCreated 中调用 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);  // 设置正面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);
   

修改投景变换矩阵以显示这个稍大些的立方体

GLU.gluLookAt(gl, 30f, 30f, 30f, 0f, 0f, 0f, 0, 1, 0);
   

好, 运行一下,看上去还不错

最终代码:  

转载于:https://www.cnblogs.com/xieyuan/p/3787309.html

你可能感兴趣的文章
【转】移动前端手机输入法自带emoji表情字符处理
查看>>
【JS档案揭秘】第一集 内存泄漏与垃圾回收
查看>>
Python之系统交互(subprocess)
查看>>
蛋疼的wamp同一局域网内访问
查看>>
Linux文件类型与扩展名
查看>>
mybatis Mapper XML 文件
查看>>
Gerrit代码Review入门实战
查看>>
【转】5个常用Java 代码混淆器 助你保护你的代码
查看>>
二、DBMS_JOB(用于安排和管理作业队列)
查看>>
Unity3d Hololens MR开发入门
查看>>
vue-分页搜索功能
查看>>
Redis源码剖析之主从复制
查看>>
Kafka实战系列--Kafka API使用体验
查看>>
【bzoj2770】YY的Treap 权值线段树
查看>>
[development][dpdk][hugepage] 大页内存的挂载
查看>>
【二代示波器教程】第15章 FreeRTOS操作系统版本二代示波器实现
查看>>
PHP学习笔记二十三【This】
查看>>
STM32学习之大纲
查看>>
P2010回文日期
查看>>
Python开发的10个小贴士
查看>>