最近看了《疯狂android讲义》的图形相关的内容,结合自己的理解,整理了一下。

下图是做出来的3D纹理贴图效果,手指在屏幕滑动时,图片可以随之转动。

要实现一个纹理贴图,很简单,大致需要五步:

1、gl.glEnable(GL10.GL_TEXTURE_2D) 启用2D纹理功能;

2、gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY) 启用纹理坐标数组;

3、gl.glBindTexture(GL10.GL_TEXTURE_2D,texture) 绑定纹理;

4、GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0) 根据位图生成纹理;

5、gl.glTexCoordPointer(2, GL10.GL_FLOAT,0, bufferUtil(cubeTextures)) 设置纹理坐标;

下面是一个完整的例子:

public class MainActivity extends AppCompatActivity implements GestureDetector.OnGestureListener{private static final String TAG = "MainActivity";GestureDetector gestureDetector;// 定义旋转角度private float anglex = 0f;private float angley = 0f;static final float ROTATE_FACTOR = 60;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);GLSurfaceView glSurfaceView = new GLSurfaceView(this);MyRenderOne myRender = new MyRenderOne(this);glSurfaceView.setRenderer(myRender);setContentView(glSurfaceView);gestureDetector = new GestureDetector(this, this);}@Overridepublic boolean onDown(MotionEvent e) {return false;}@Overridepublic void onShowPress(MotionEvent e) {  }@Overridepublic boolean onSingleTapUp(MotionEvent e) {return false;}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {return false;}@Overridepublic void onLongPress(MotionEvent e) {  }@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {velocityX = velocityX > 4000 ? 4000 : velocityX;velocityX = velocityX < -4000 ? -4000 : velocityX;velocityY = velocityY > 4000 ? 4000 : velocityY;velocityY = velocityY < -4000 ? -4000 : velocityY;// 根据横向上的速度计算沿Y轴旋转的角度angley += velocityX * ROTATE_FACTOR / 4000;// 根据纵向上的速度计算沿X轴旋转的角度anglex += velocityY * ROTATE_FACTOR / 4000;return true;}@Overridepublic boolean onTouchEvent(MotionEvent event) {// 将该Activity上的触碰事件交给GestureDetector处理return gestureDetector.onTouchEvent(event);}public class MyRenderOne implements GLSurfaceView.Renderer {// 立方体的顶点座标(一共是36个顶点,组成12个三角形)private float[] cubeVertices = { -0.4f, -0.4f, -0.4f, -0.4f, 0.4f,-0.4f, 0.4f, 0.4f, -0.4f, 0.4f, 0.4f, -0.4f, 0.4f, -0.4f, -0.4f,-0.4f, -0.4f, -0.4f, -0.4f, -0.4f, 0.4f, 0.4f, -0.4f, 0.4f, 0.4f,0.4f, 0.4f, 0.4f, 0.4f, 0.4f, -0.4f, 0.4f, 0.4f, -0.4f, -0.4f,0.4f, -0.4f, -0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, -0.4f, 0.4f,0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, -0.4f, -0.4f, -0.4f, 0.4f,-0.4f, -0.4f, 0.4f, 0.4f, -0.4f, 0.4f, 0.4f, 0.4f, 0.4f, 0.4f,0.4f, 0.4f, -0.4f, 0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, -0.4f,-0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, -0.4f, 0.4f, 0.4f, 0.4f,0.4f, 0.4f, 0.4f, 0.4f, -0.4f, -0.4f, 0.4f, -0.4f, -0.4f, -0.4f,-0.4f, -0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, -0.4f, 0.4f, 0.4f,-0.4f, 0.4f, -0.4f, };// 定义立方体所需要的6个面(一共是12个三角形所需的顶点)private byte[] cubeFacets = { 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, };// 定义纹理贴图的72个座标数据private float[] cubeTextures = { 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 Context context;private int texture;public MyRenderOne(Context con){this.context = con;}@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {gl.glDisable(GL10.GL_DITHER); //关闭抗抖动gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); //设置系统对透视进行修正gl.glClearColor(0, 0, 0, 0); //黑色背景gl.glShadeModel(GL10.GL_SMOOTH); //设置平滑模式gl.glEnable(GL10.GL_DEPTH_TEST);gl.glDepthFunc(GL10.GL_LEQUAL); //设置深度测试(opengl es会跟踪z轴的深度,以避免后面的图像挡住前面的图像)的类型gl.glEnable(GL10.GL_TEXTURE_2D); //开启2D纹理贴图loadTexture(gl);}private void loadTexture(GL10 gl) {Bitmap bitmap = null;try {bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.aa);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();}}}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {Log.i(TAG, "onSurfaceChanged enter...");gl.glViewport(0, 0, width, height); //设置视窗的大小及位置gl.glMatrixMode(GL10.GL_PROJECTION); //设置为投影矩阵gl.glLoadIdentity(); // 初始化单位矩阵float ratio = (float) width / height;gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); // 设置透视视窗的空间大小。}@Overridepublic void onDrawFrame(GL10 gl) {// 清除屏幕缓存和深度缓存gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);//开启顶点设置和纹理设置功能gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);gl.glMatrixMode(GL10.GL_MODELVIEW); //设置为模型矩阵Log.i(TAG, "onDrawFrame enter...");gl.glLoadIdentity();gl.glTranslatef(0f, 0.0f, -2.0f); // 把绘图中心移入屏幕2个单位gl.glRotatef(angley, 0, 1, 0); // 旋转图形gl.glRotatef(anglex, 1, 0, 0);gl.glVertexPointer(3, GL10.GL_FLOAT, 0, bufferUtil(cubeVertices)); //设置立方体的顶点gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, bufferUtil(cubeTextures)); //设置纹理顶点//gl.glBindTexture(GL10.GL_TEXTURE_2D, texture); //将纹理绑定到目标(执行纹理贴图)//绘制立方体gl.glDrawElements(GL10.GL_TRIANGLES, cubeFacets.length, GL10.GL_UNSIGNED_BYTE, bufferUtil2(cubeFacets));gl.glFinish(); //绘制完成// 禁用顶点和纹理设置gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);}/** OpenGL 是一个非常底层的画图接口,它所使用的缓冲区存储结构是和我们的 java 程序中不相同的。* Java 是大端字节序(BigEdian),而 OpenGL 所需要的数据是小端字节序(LittleEdian)。* 所以,我们在将 Java 的缓冲区转化为 OpenGL 可用的缓冲区时需要作一些工作。建立buff的方法如下* */public Buffer bufferUtil(float []arr){FloatBuffer mBuffer ;//先初始化buffer,数组的长度*4,因为一个float占4个字节ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 4);//数组排列用nativeOrderqbb.order(ByteOrder.nativeOrder());mBuffer = qbb.asFloatBuffer();mBuffer.put(arr);mBuffer.position(0);return mBuffer;}public Buffer bufferUtil1(int []arr){IntBuffer mBuffer ;//先初始化buffer,数组的长度*4,因为一个int占4个字节ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 4);//数组排列用nativeOrderqbb.order(ByteOrder.nativeOrder());mBuffer = qbb.asIntBuffer();mBuffer.put(arr);mBuffer.position(0);return mBuffer;}public Buffer bufferUtil2(byte []arr){//先初始化bufferByteBuffer qbb = ByteBuffer.allocateDirect(arr.length);//数组排列用nativeOrderqbb.order(ByteOrder.nativeOrder());qbb.put(arr);qbb.position(0);return qbb;}}}

其中有几点需要说明下:

1、启动2D纹理功能用的是gl.glEnable(),而不是gl.glEnableClientState();
2、gl.glDrawElements()的第一个参数指定绘制的模块,可以是:GL10.GL_TRIANGLES(绘制三角形)和GL10.GL_TRIANGLE_STRIP(用多个三角形绘制多边形),第三个参数是坐标值的类型,如果是float则为GL10.GL_FLOAT,如果是int则为GL10.GL_FIXED,如果是byte则为GL10.GL_UNSIGNED_BYTE;

3、gl.glDrawElements()最后一个参数是坐标数组,如果用不好就会报错:java.lang.IllegalArgumentException: Must use a native order direct Buffer这个错误在android1.6以上会出现,原因是Java使用的是大端字节序,而opengl使用的是小端字节序,所以需要转换一下才能使用。

OpenGL ES绘制3D纹理贴图相关推荐

  1. OpenGL ES之十——纹理贴图(展示一张图片)

    概述 这是一个系列的Android平台下OpenGl ES介绍,从最基本的使用最终到VR图的展示的实现,属于基础篇.(后面针对VR视频会再有几篇文章,属于进阶篇) OpenGL ES之一--概念扫盲 ...

  2. android 使用OPENGL ES实现三角形纹理贴图效果-纹理映射基础

    效果图:...... 编写Dad.java *在Dad构造器中创建和设置场景渲染器为主动渲染,并设置重写触屏时间回调方法以记录触控笔坐标,改变三角形坐标系的位置,使三角形能够在场景中转动 *为声明场景 ...

  3. java opengl es_Java-Android-使用openGL ES绘制3D然后绘制2D

    我找到了解决方案,但我忘了发布了:)对不起 package at.bartinger.opengl; import javax.microedition.khronos.egl.EGLConfig; ...

  4. Android Studio OpenGL ES绘制三棱锥/四面体的多纹理贴图 每个面使用一张图片渲染

    本文参考了王刚的<疯狂Android讲义(第3版)>P554-P559 要求:利用OpenGL ES绘制一个三棱锥,并对每个面进行纹理贴图,每个面使用不同的图片进行渲染. 环境:Andro ...

  5. 基于VC++的3D地形绘制与纹理贴图

    前言 随着地理信息系统产业的发展,三维产品也在生活中处处吸引着我们的眼球.作为数字城市的核心内容,城市模型的构建成为了目前研究的热点.OpenGL是独立于操作系统和硬件环境的三维图形库,其为实现逼真的 ...

  6. android三个骰子摇动动画,【Android】OpenGL ES实现3D抛骰子

    实现的效果: 抛骰子 加载模型 一.OpenGL简介 OpenGL(全写Open Graphics Library)是个定义了一个跨编程语言.跨平台的编程接口的规格,它用于三维图象(二维的亦可).Op ...

  7. 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)

    0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...

  8. 【Qt for Android】OpenGL ES 绘制彩色立方体

    Qt 内置对OpenGL ES的支持.选用Qt进行OpenGL ES的开发是很方便的,很多辅助类都已经具备.从Qt 5.0開始添加了一个QWindow类,该类既能够使用OpenGL绘制3D图形,也能够 ...

  9. [OpenGL ES 03]3D变换:模型,视图,投影与Viewport

    [OpenGL ES 03]3D变换:模型,视图,投影与Viewport 罗朝辉 (http://blog.csdn.net/kesalin) 本文遵循"署名-非商业用途-保持一致" ...

最新文章

  1. Image-to-Image的论文汇总
  2. Fedora升级到4.3.4内核后virtualbox执行/sbin/rcvboxdrv setup报Bad argument setup
  3. 两直线平行交叉相乘_人教版初中数学七年级下册 平行线判定2公开课优质课课件教案视频...
  4. java 间隔分钟_java 计算两个 日期时间 相间隔多少天小时分钟 等
  5. delphi中griddata控件写入float数值_年中巨献!明道云发布多项重磅功能
  6. SpringCloud工作笔记042---SpringCloud RestFul接口中跨域问题_这个解决方式不太完美,每个接口上都要加
  7. 我整理了2019年全套资料!
  8. 寻找最小的k个数(四种方法)
  9. C11简洁之道:函数绑定
  10. DB2 数据库软件下载
  11. 解决FreeMind启动不成功,显示This application requires a Java Runtime Environment 1.5.0
  12. “程序已停止工作”问题的解决方法,停止解决方法
  13. 微信应用架构!!-----微信应用的测试管理篇
  14. WIN10开机显示被调用的对象已与其客户端断开连接解决方法之一
  15. 操作系统王道考研复习——第一章(计算机系统概述)
  16. 跟我一起写Shell脚本之十八--常用命令(head)
  17. B端设计指南——表格 究竟应该如何设计?
  18. tf_Course6循环神经网络
  19. 毕马威中国:证券基金经营机构信息技术审计项目发现洞察
  20. 卷积神经网络的应用(人脸识别)

热门文章

  1. Java中集合与数组之间的转换方法
  2. MIT四足机器人Cheetah 3控制方案理解笔记(2)——Convex Mpc身体姿态控制
  3. TensorFlow分布式全套(原理,部署,实例)
  4. 0006 手动定制原版 Win7 操作系统(五)
  5. php 文字输入输出
  6. windows下的Anaconda(三)深入了解Anaconda
  7. Java重写+malformed,java lang IllegalArgumentException MALFORMED jar解析中文报错问题
  8. foxmail 6.5 beta3 某些邮件不能直接回复的问题
  9. Field dataSource in com.security1.config.SecurityConfig required a bean of type ‘javax.sql.DataSourc
  10. 如何提高情商?这些技能很关键