Android OpenGL ES 应用(二) 纹理

上一篇讲了基础入门 OpenGL (一) ,这一次主要学习OpenGL 纹理基本学习总结

要是做复杂的OpenGL应用程序,一定会用到纹理技术。纹理说白了就是把图片或者视频图像绘制到OpenGL空间中。

因此纹理也有坐标系,称ST坐标,或者UV

上面是纹理坐标空间,但没有固定的方向

下面演示加载一张image作为纹理贴图。

public class TextureUtils {

	public static int createTexture(InputStream ins) {
		int[] textures = new int[1];
		GLES20.glGenTextures(1, textures, 0);//生成一个纹理

		int textureId = textures[0];
		GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
		GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST);
		GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
		GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_CLAMP_TO_EDGE);
		GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_CLAMP_TO_EDGE);
		//上面是纹理贴图的取样方式,包括拉伸方式,取临近值和线性值
		Bitmap bitmap = BitmapFactory.decodeStream(ins);
		GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);//让图片和纹理关联起来,加载到OpenGl空间中
		Log.d("OPENGL","bitmap:" + bitmap);
		bitmap.recycle();//不需要,可以释放
		return textureId;
	}

}
public class MyRenderer implements Renderer {

	public static float[] projMatrix = new float[16];// 投影
	public static float[] viewMatrix = new float[16];// 相机
	public static float[] mViewPjMatrix;// 总变换矩阵
	public static float[] matrixs = new float[16];
	public static int textureId = -1;
	Context context;
	MyDrawModel drawModel;

	public MyRenderer(Context context) {
		this.context = context;
	}

	@Override
	public void onDrawFrame(GL10 arg0) {
		GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
		Log.e("", "textureId:" + textureId);
		drawModel.drawFrame(textureId);
	}

	@Override
	public void onSurfaceChanged(GL10 arg0, int w, int h) {
		GLES20.glViewport(0, 0, w, h);
		float ratio = (float) w / h;
		Matrix.frustumM(projMatrix, 0, -ratio, ratio, -1, 1, 1, 10);//投影矩阵设置
		Matrix.setLookAtM(viewMatrix, 0, 0, 0, 3, 0, 0, 0, 0.0f, 1.0f, 0.0f);//摄像机坐标设置
	}

	@Override
	public void onSurfaceCreated(GL10 g, EGLConfig eglConfig) {
		GLES20.glClearColor(0.5f,0.5f,0.5f, 1.0f);
		GLES20.glEnable(GLES20.GL_DEPTH_TEST);
		InputStream ins = null;
		drawModel = new MyDrawModel();
		drawModel.init();
		try {
			ins = context.getAssets().open("house.jpg");
			textureId = TextureUtils.createTexture(ins);
			Log.e("", "textureId:" + textureId);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				ins.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		GLES20.glDisable(GLES20.GL_CULL_FACE);
	}

}
public class MyDrawModel {

	private int programId;
	private int mVPMatrixHandle; // 总变换矩阵引用id
	private int positionHandle; // 顶点位置id
	private int texCoorHandle; // 顶点纹理坐标id

	private FloatBuffer vertexBuffer;
	private FloatBuffer texCoorBuffer;

	public MyDrawModel() {
	}

	public void init() {
		initData();
		int vertexsharder = GLHelper.compileScript(GLES20.GL_VERTEX_SHADER,
				GLScript.vertex2);
		int fragmentsharder = GLHelper.compileScript(GLES20.GL_FRAGMENT_SHADER,
				GLScript.fragment2);
		programId = GLHelper.linkAttach(vertexsharder, fragmentsharder);
		boolean isOK = GLHelper.checkProgram(programId);
		positionHandle = GLES20.glGetAttribLocation(programId, "aPosition");
		texCoorHandle = GLES20.glGetAttribLocation(programId, "aTexCoor");
		mVPMatrixHandle = GLES20.glGetUniformLocation(programId, "uMVPMatrix");

		Log.d("OPENGL", "positionHandle:" + positionHandle + ";texCoorHandle:"
				+ texCoorHandle + ";mVPMatrixHandle:" + mVPMatrixHandle + ";"
				+ isOK);
	}

	private void initData() {

		//X,Y,Z,绘画的顶点
		float vertices[] = new float[] {
		           0,     0, 0,
			   -1.8f, -1f, 0,
			   1.8f, -1f, 0,
			   1.8f,  1f, 0,
			   -1.8f,  1f, 0,
			   -1.8f, -1f, 0
		   };

		ByteBuffer vb = ByteBuffer.allocateDirect(vertices.length * 4);
		vb.order(ByteOrder.nativeOrder());
		vertexBuffer = vb.asFloatBuffer();
		vertexBuffer.put(vertices);
		vertexBuffer.position(0);

		//纹理空间坐标 S,T
		float texCoor[] = new float[] {
				0.5f, 0.5f,
				0f,     1f,
				1f,     1f,
				1f,     0f,
				0f,     0f,
				0f,     1f
			};

		ByteBuffer cb = ByteBuffer.allocateDirect(texCoor.length * 4);
		cb.order(ByteOrder.nativeOrder());
		texCoorBuffer = cb.asFloatBuffer();
		texCoorBuffer.put(texCoor);
		texCoorBuffer.position(0);
	}

	public void drawFrame(int textureId) {

		 GLES20.glUseProgram(programId);

		 // // 初始化矩阵
		 Matrix.setRotateM(MyRenderer.matrixs, 0, 0, 1, 0, 0);
		 Matrix.translateM(MyRenderer.matrixs, 0, 0, 0, 1);

		 //矩阵转换 ,投影矩阵,摄像机矩阵,模型矩阵
		 MyRenderer.mViewPjMatrix = new float[16];
		 Matrix.multiplyMM(MyRenderer.mViewPjMatrix, 0, MyRenderer.viewMatrix,0, MyRenderer.matrixs, 0);
		 Matrix.multiplyMM(MyRenderer.mViewPjMatrix, 0, MyRenderer.projMatrix,0, MyRenderer.mViewPjMatrix, 0);
		 GLES20.glUniformMatrix4fv(mVPMatrixHandle, 1, false, MyRenderer.mViewPjMatrix, 0);

		 GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 3 * 4, vertexBuffer);
		 GLES20.glVertexAttribPointer(texCoorHandle,  2, GLES20.GL_FLOAT, false, 2 * 4, texCoorBuffer);

		 GLES20.glEnableVertexAttribArray(positionHandle);
		 GLES20.glEnableVertexAttribArray(texCoorHandle);

		 GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
		 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
		 GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 6);//六个定点,绘制三角形

	}

}

OpenGL需要把设备的坐标归一化到[-1,-1]空间中,所以这里涉及到矩阵相乘的理论,包括世界坐标,物体坐标,摄像机坐标的转换,以后会详细介绍。

public class GLScript {

	public GLScript() {
	}

	public static final String vertex1 = "attribute vec4 mPosition;\n" +
            "void main()\n" +
            "{\n" +
                "gl_Position=mPosition;\n " +
            "}\n";  

    public static final String fragment1 = "precision mediump float;\n" +
            "uniform vec4 mColor;\n" +
            "void main(){ gl_FragColor=mColor;\n}";  

    public static final String vertex2 = "uniform mat4 uMVPMatrix;\n"
    		 + "attribute vec3 aPosition;\n"
    		 + "attribute vec2 aTexCoor;\n"
    		 + "varying vec2 vTextureCoord;\n"
    		 + "void main() { \n"
    		 + "gl_Position = uMVPMatrix * vec4(aPosition,1);\n"
    		 + "vTextureCoord = aTexCoor;\n"
    		 + "}\n"
    		;

    public static final String fragment2 = "precision mediump float;\n"
    		+ "varying vec2 vTextureCoord;\n"
    		+ "uniform sampler2D sTexture;\n"
    		+ "void main() { \n"
    		+ "vec2 coord =  vTextureCoord;\n"
    		+ "coord.s =  coord.s * 0.5;\n" //其实是去图像的一半,向量缩小了
    		+ "gl_FragColor = texture2D(sTexture, coord); \n"
    		+ "}\n"
    		;

}
coord.s =  coord.s * 0.5;

这样是取纹理图像的一半,显示到界面上也就是图片的前半部分内容

其它的工具类和上一篇文章一样。

内容显示

原图:

时间: 2024-08-28 01:05:50

Android OpenGL ES 应用(二) 纹理的相关文章

初学Android OpenGL ES之使用纹理 八十三

在网上发现这些讲纹理的文章,非常不错 android 游戏导引(4. 简单纹理贴图) http://www.cnblogs.com/shengdoushi/archive/2011/01/13/1934181.html Android OpenGL es 纹理坐标设定与贴图规则 http://blog.csdn.net/cjkwin/article/details/6016224 Android OpenGL | ES给立方体进行纹理映射 http://www.ourunix.org/andro

Android OpenGL ES(七)----理解纹理与纹理过滤

1.理解纹理 OpenGL中的纹理可以用来表示图像,照片,甚至由一个数学算法生成的分形数据.每个二维的纹理都由许多小的纹理元素组成,它们是小块的数据,类似于我们前面讨论过的片段和像素.要使用纹理,最常用的方式是直接从一个图像文件加载数据. 每个二维纹理都有其自己的坐标空间,其范围是从一个拐角的(0,0)到另一个拐角的(1,1).按照惯例,一个维度叫做S,而另一个称为T.当我们想要把一个纹理应用于一个三角形或一组三角形的时候,我们要为每个顶点指定一组ST纹理坐标,以便OpenGL知道需要用那个纹理

对Android opengl ES世界坐标系和纹理坐标系的理解

初学opengl ES,每一个教你在屏幕上贴图的opengl版hello world都有这么两数组: static final float COORD[] = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, }; static final float TEXTURE_COORD[] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, }; 但是几乎都不解释,所以我学的时候都不明白这些点

Android OpenGL ES零基础系列(一):理解GLSurfaceView,GLSurfaceView.Render的基本用法

转载请注明出处 前言 OpenGL ES是OpenGL的一个子集,是针对手机.PDA和游戏主机等嵌入式设备而设计的.该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准. 因此OpenGL ES作为第三方库被应用在android中. 到目前为止,OpenGL ES已经发展有了3个版本,OpenGL ES 1.0 , OpenGL ES 2.0 , OpenGL ES 3.0.其中OpenGL ES 1.0 是以OpenGL 1.3

Android OpenGL ES(七)基本几何图形定义 .

在前面Android OpenGL ES(六):创建实例应用OpenGLDemos程序框架 我们创建了示例程序的基本框架,并提供了一个“Hello World”示例,将屏幕显示为红色. 本例介绍OpenGL ES 3D图形库支持的几种基本几何图形,通常二维图形库可以绘制点,线,多边形,圆弧,路径等等.OpenGL ES 支持绘制的基本几何图形分为三类:点,线段,三角形.也就是说OpenGL ES 只能绘制这三种基本几何图形.任何复杂的2D或是3D图形都是通过这三种几何图形构造而成的. 比如下图复

Android OpenGL ES(十二):三维坐标系及坐标变换初步 .

OpenGL ES图形库最终的结果是在二维平面上显示3D物体(常称作模型Model)这是因为目前的打部分显示器还只能显示二维图形.但我们在构造3D模型时必须要有空间现象能力,所有对模型的描述还是使用三维坐标.也就是使用3D建模,而有OpenGL ES库来完成从3D模型到二维屏幕上的显示. 这个过程可以分成三个部分: 坐标变换,坐标变换通过使用变换矩阵来描述,因此学习3D绘图需要了解一些空间几何,矩阵运算的知识.三维坐标通常使用齐次坐标来定义.变换矩阵操作可以分为视角(Viewing),模型(Mo

Android OpenGL ES 开发教程 从入门到精通

From:http://blog.csdn.net/mapdigit/article/details/7526556 Android OpenGL ES 简明开发教程 Android OpenGL ES 简明开发教程一:概述 Android OpenGL ES 简明开发教程二:构造OpenGL ES View Android OpenGL ES 简明开发教程三:3D绘图基本概念 Android OpenGL ES 简明开发教程四:3D 坐标变换 Android OpenGL ES 简明开发教程五

[工作记录] Android OpenGL ES 2.0: square texture not supported on some device

npot texture: non-power-of-two texture.rectangle texture: non-square (height != wdith) 在测试Samsumg Galaxy S4的时候, 发现rectangle texture支持不好, 虽然创建成功, 但是绘制有问题. 不同的模块出现类似的情况: 纹理采样出的颜色是(0,0,0,1). 在排除了所有可能的runtime问题以后, 尝试性改了纹理格式无果, 又尝试性的改了下尺寸, 竟然好了. 我擦... 而Ga

[转]Android OpenGL ES 开发教程 从入门到精通

本文转自:http://blog.csdn.net/mapdigit/article/details/7526556 Android OpenGL ES 简明开发教程 Android OpenGL ES 简明开发教程一:概述 Android OpenGL ES 简明开发教程二:构造OpenGL ES View Android OpenGL ES 简明开发教程三:3D绘图基本概念 Android OpenGL ES 简明开发教程四:3D 坐标变换 Android OpenGL ES 简明开发教程五