应用纹理贴图

为了在OpenGL  ES中启用纹理贴图功能,可以在Renderer实现类的onSurfaceCreated(GL10  gl  ,  EGLConfig   config)方法中启动纹理贴图,例如如下代码:

//启用2D纹理贴图
gl.glEnable(GL10.GL_TEXTURE_2D);

接下来就需要准备一张图片来作为纹理贴图了,建议改图片的长宽是2的N次方,把这张准备贴图的位图放在Android项目的/res/drawable-mdpi目录下,方便应用程序加载该图片资源。

接下来程序开始加载该图片并生成对应的纹理贴图,例如如下方法:

//加载位图
bitmap = BitmapFactory.decodeResource(
context.getResources(), R.drawable.sand);
int[] textures = new int[1];
//指定生成N个纹理(第一个参数指定生成1个纹理)
//textures数组将负责存储所有纹理的代号
gl.glGenTextures(1, textures , 0);
//获取textures纹理数组中的第一个纹理
texture = textures[0];
//通知OpenGL将texture纹理绑定到GL10.GL_TEXTURE_2D目标中
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);

上面的程序中用到了GL10的如下方法:

glGenTextures(int  n , int[]  textures , int  offset):该方法指定一次性生成n个纹理,该方法所生成的纹理的代号放入其中textures数组中,offset指定从第几个数组元素开始存放纹理代号。

glBindTexture(int  target , int  texture):该方法用于将texture纹理绑定到target目标上。

glTeXParameterf(int  target  ,int  pname  , float  param):该方法用于为target纹理目标设置属性,其中第二个参数是属性名,第三个参数是属性值。程序设置了当纹理被放大时使用GL10.GL_LINEAR滤波方式;当纹理被缩小时使用GL10.GL_NEAREST滤波方式;一般来说,使用GL10.GL_LINEAR滤波方式有较好的效果,但系统开小略微大一些,具体采用哪种滤波方式则取决于目标机器本身的性能。

上面代码的最后一行调用了GLUtils工具类的方法来加载指定位图,并根据位图来生成纹理,通过上面的代码即可得到一个用于贴图的纹理了。

在3D绘制中进行纹理贴图与设置顶点颜色的步骤相似,只要三步:

1、设置启用贴图坐标数组。

2、设置贴图坐标的数组信息。

3、调用GL10的glBindTexture(int  target , int  texture)方法执行贴图。

下面的程序示范了如何为一个立方体进行贴图,而且这个程序提供了手势检测器,语允许用户通过手势来改变该立方体的角度。

import java.nio.ByteBuffer;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLUtils;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.Menu;
import android.view.MotionEvent;

public class Texture3D extends Activity implements OnGestureListener{
  //定义旋转角度
  private float anglex = 0f;
  private float angley = 0f;
  static final float ROTATE_FACTOR = 60;
  //定义手势检测器实例
  GestureDetector detector;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //创建一个GLSurfaceView,用于显示OpenGL绘制的图形
    GLSurfaceView glView = new GLSurfaceView(this);
    //创建GLSurfaceView的内容绘制器
    MyRenderer myRender = new MyRenderer(this);
    //为GLSurfaceView设置绘制器
    glView.setRenderer(myRender);
    setContentView(glView);
    //创建手势检测器
    detector = new GestureDetector(getApplicationContext(), this);
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    // 将该Activity上的触碰事件交给GestureDetector
    return detector.onTouchEvent(event);
  }

  @Override
  public boolean onDown(MotionEvent e) {
    return false;
  }

  @Override
  public void onShowPress(MotionEvent e) {
  }

  @Override
  public boolean onSingleTapUp(MotionEvent e) {
    return false;
  }

  @Override
  public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
                                float distanceY) {
    return false;
  }

  @Override
  public void onLongPress(MotionEvent e) {
  }

  @Override
  public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                                          float velocityY) {
    velocityX = velocityX > 4000 ? 4000 : velocityX;
    velocityX = velocityX < -4000 ? -4000 : velocityX;
    velocityY = velocityX > 4000 ? 4000 : velocityY;
    velocityY = velocityX < -4000 ? -4000 : velocityY;
    //根据横向上的速度计算沿Y轴旋转的角度
    angley += velocityX * ROTATE_FACTOR / 4000;
    //根据纵向上的速度计算沿X轴旋转的角度
    anglex += velocityY * ROTATE_FACTOR / 4000;
    return true;
  }

  public class MyRenderer implements Renderer{
    //立方体的顶点坐标(一共是36个顶点,组成12个三角形)
    private float[] cubeVetices = {-0.6f,-0.6f,-0.6f,-0.6f,0.6f,
        -0.6f,0.6f,0.6f,-0.6f,0.6f,0.6f,-0.6f,0.6f,-0.6f,-0.6f,
        -0.6f,-0.6f,-0.6f,-0.6f,-0.6f,0.6f,0.6f,-0.6f,0.6f,0.6f,
        0.6f,0.6f,0.6f,0.6f,0.6f,-0.6f,0.6f,0.6f,-0.6f,-0.6f,
        0.6f,-0.6f,-0.6f,-0.6f,0.6f,-0.6f,-0.6f,0.6f,-0.6f,0.6f,
        0.6f,-0.6f,0.6f,-0.6f,-0.6f,0.6f,-0.6f,-0.6f,-0.6f,0.6f,
        -0.6f,-0.6f,0.6f,0.6f,-0.6f,0.6f,0.6f,0.6f,0.6f,0.6f,
        0.6f,0.6f,-0.6f,0.6f,0.6f,-0.6f,-0.6f,0.6f,0.6f,-0.6f,
        -0.6f,0.6f,-0.6f,-0.6f,0.6f,0.6f,-0.6f,0.6f,0.6f,0.6f,
        0.6f,0.6f,0.6f,0.6f,-0.6f,-0.6f,0.6f,-0.6f,-0.6f,-0.6f,
        -0.6f,-0.6f,-0.6f,0.6f,-0.6f,-0.6f,0.6f,-0.6f,0.6f,0.6f,
        0.6f,0.6f,0.6f};
    //定义立方体所需要的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};
    //定义纹理贴图的坐标数据
    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 FloatBuffer cubeVerticesBuffer;
    private ByteBuffer cubeFacetsBuffer;
    private FloatBuffer cubeTexturesBuffer;
    //定义本程序所使用的纹理
    private int texture;
    public MyRenderer(Context main){
      this.context = main;
      //将立方体的顶点位置数据数组包装成FloatBuffer
      cubeVerticesBuffer = FloatBuffer.wrap(cubeVetices);
      //将立方体的6个面(12个三角形)的数组包装成ByteBuffer
      cubeFacetsBuffer = ByteBuffer.wrap(cubeFacets);
      //将立方体的纹理贴图的坐标数据包装成FloatBuffer
      cubeTexturesBuffer = FloatBuffer.wrap(cubeTextures);
    }

    @Override
    public 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);
      //启用2D纹理贴图
      gl.glEnable(GL10.GL_TEXTURE_2D);
      //装载纹理
      loadTexture(gl);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
      // 设置3D视窗的大小及位置
      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);
    }

    @Override
    public 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);
      //----------绘制第一个图形----------
      gl.glLoadIdentity();
      //把绘图中心移入屏幕2个单位
      gl.glTranslatef(0f, 0.0f, -2.0f);
      //旋转图形
      gl.glRotatef(angley, 0, 1, 0);
      gl.glRotatef(anglex, 1, 0, 0);
      //设置顶点的位置数据
      gl.glVertexPointer(3, GL10.GL_FLOAT, 0, cubeVerticesBuffer);
      //设置贴图的坐标数据
      gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, cubeTexturesBuffer);
      //执行纹理贴图
      gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
      //按cubeFacetsBuffer指定的面绘制三角形
      gl.glDrawElements(GL10.GL_TRIANGLES,
      cubeFacetsBuffer.remaining(),
      GL10.GL_UNSIGNED_BYTE, cubeFacetsBuffer);
      //绘制结束
      gl.glFinish();
      //禁用顶点、纹理做标数组
      gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
      gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
      //递增角度值以便每次以不同角度绘制
    }
    private void loadTexture(GL10 gl){
      Bitmap bitmap = null;
      try {
        //加载位图
        bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.sand);
        int[] textures = new int[1];
        //指定生成N个纹理(第一个参数指定生成1个纹理)
        //textures数组将负责存储所有纹理的代号
        gl.glGenTextures(1, textures, 0);
        //获取textures纹理数组中的第一个纹理
        texture = textures[0];
        //通知OpenGL将texture纹理绑定到GL10.GL_TEXTURE_2D目标中
        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);
      } catch (Exception e) {
      }finally{
        //生成纹理之后,回收位图
        if(bitmap != null){
          bitmap.recycle();
        }
      }

    }

  }

}

时间: 2024-10-06 22:30:13

应用纹理贴图的相关文章

基于Cocos2d-x学习OpenGL ES 2.0系列——纹理贴图(6)

在上一篇文章中,我们介绍了如何绘制一个立方体,里面涉及的知识点有VBO(Vertex Buffer Object).IBO(Index Buffer Object)和MVP(Modile-View-Projection)变换. 本文将在教程4的基础之上,添加纹理贴图支持.最后,本文会把纹理贴图扩展至3D立方体上面. 基本方法 当我们把一张图片加载到内存里面之后,它是不能直接被GPU绘制出来的,纹理贴图过程如下: 首先,我们为之前的顶点添加纹理坐标属性并传到vertex shader里面去: 然后

windows下opengl扩展与多重纹理贴图

环境:windows8.1 参考: http://www.cnblogs.com/madfrog/archive/2010/06/25/1765243.html http://blog.csdn.net/xiangyunl/article/details/7933549 如果你在Windows平台下开发OpenGL程序,那么系统中自带的OpenGL库就是1.1的,如果想使用1.2或者更高版本的OpenGL库,那么只能使用OpenGL扩展.由于d3d的关系,windows对于opengl支持不是很

[Unity] Shader(着色器)之纹理贴图

在Shader中,我们除了可以设定各种光线处理外,还可以增加纹理贴图. 使用 settexture 命令可以为着色器指定纹理. 示例代码: Shader "Sbin/ff2" { // 贴图采样 properties { // 变量名("描述名",类型)=值 _Color("主体", color)=(1,1,1,1) _Ambient("环境光", color)=(0.3,0.3,0.3,0.3) _Specular(&quo

用OpenGL进行立方体表面纹理贴图

一.目的: 掌握OpenGL中纹理对象的创建.绑定与使用方法. 二.简单介绍: 1,连接静态库 #pragma comment(lib, "glut32.lib") #pragma comment(lib, "glaux.lib") 2,载入位图图像到内存(这是固定用法) AUX_RGBImageRec *LoadBMP(CHAR *Filename) { FILE *File = NULL; // 文件句柄 if (!Filename) // 确保文件名已提供 {

纹理贴图移动(水流、电流效果)

纹理贴图移动特效产生岩浆.瀑布效果 原理是改变动态改变纹理坐标uv的值,使之移动 首先准备好一张贴图 建立一个shader 变量一览: _MainTex 主纹理贴图 _MainTint 主要颜色   _ScrollXSpeed x轴移动速度 _ScrollYSpeed  y轴移动速度 Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _MainTint ("Diffuse Tint", C

【3.js探寻八】——法向材质与材质的纹理贴图

4.法向材质 法向材质可以将材质的颜色设置为其法向量的方向,有时候对于调试很有帮助. 法向材质的设定很简单,甚至不用设置任何参数: new THREE.MeshNormalMaterial() 材质的颜色与照相机与该物体的角度相关,下面我们只改变照相机位置,观察两个角度的颜色变化: camera.position.set(5, 25, 25);的效果: camera.position.set(25, 25, 25);的效果: 我们观察的是同样的三个面,但是由于观察的角度不同,物体的颜色就不同了.

Directx11学习笔记【十七】纹理贴图

本文由zhangbaochong原创,转载请注明出处http://www.cnblogs.com/zhangbaochong/p/5596180.html 在之前的例子中,我们实现了光照和材质使得场景大大增加了真实感,然而材质提供的细节只是在顶点级别上,要想在像素级别提供细节还得借助于纹理,这次让我们学习dx11中一些有关纹理的基础. 1.纹理坐标 1 在direct3d中,纹理坐标用一个二维向量(u,v)表示,纹理左上角为原点,u正方向沿纹理水平向右,v正方向沿纹理垂直向下,且0<=u,v<

Opengl ES 1.x NDK实例开发之六:纹理贴图

开发框架介绍请參见:Opengl ES NDK实例开发之中的一个:搭建开发框架 本章在第三章(Opengl ES 1.x NDK实例开发之三:多边形的旋转)的基础上演示怎样使用纹理贴图,分别实现了三角形纹理贴图和正方形纹理贴图. [实例解说] OpenglES要求生成纹理的图片长宽为2的n次方.支持各种格式(BMP, GIF, JPEG, PNG...) 本例中使用的图片为png格式,尺寸为128*128 本例中,在上层GLJNIView.java中生成纹理.将纹理句柄传递给Native层进行绘

unity3d 纹理贴图移动特效产生岩浆、瀑布效果

纹理贴图移动特效产生岩浆.瀑布效果 原理是改变动态改变纹理坐标uv的值,使之移动 首先准备好一张贴图 建立一个shader 变量一览: _MainTex 主纹理贴图 _MainTint 主要颜色 _ScrollXSpeed x轴移动速度 _ScrollYSpeed  y轴移动速度 Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _MainTint ("Diffuse Tint", Col