OpenGL纹理是一种位图,可以把它粘贴到OpenGL物体的表面上。比如可以获取一张邮票的图像粘贴到正方形中,使正方形看起来像一张邮票。要使邮票保持合适的方向,以便图像井然有序地排列,则必须获得形状的每个顶点并在正方形上标记出来,以便邮票和正方形的形状保持一致。在OpenGL中引入了纹理坐标。
OpenGL 假设纹理图始终为1x1的正方形,其原点位于(0.0)处,右下角为(1,1)。如下图。
OpenGL 假设纹理图始终为1x1的正方形,其原点位于(0.0)处,右下角为(1,1)。如下图。
纹理坐标与顶点坐标之间的映射如下图:
所以我们用的浮点数组不只是要存储4个点的位置,还要存储纹理坐标值
vertices.put( new float[] { -80f, -120f, 0.0f, 1.0f ,
vertices.put( new float[] { -80f, -120f, 0.0f, 1.0f ,
80f, -120f,
1.0f, 1.0f
,
-80f, 120f,
0.0f, 0.0f
,
80f, 120f,
1.0f, 0.0f
});
处理完纹理坐标与顶点坐标之间的映射关系后,剩余工作包括将纹理位图加载到内存,为它分配纹理ID,以便重用此纹理。
来看下完整代码吧,注意我们代码中纹理坐标和顶点坐标分开存放了,这样更加清晰点,不然还要stride(跳过)内存。
注意下我们这里用到的图片"bobrgb888.png"是png格式,存放在/assets/下,长宽是128*128,好像纹理图片最好是2的n次方大小,而且是正方形。
处理完纹理坐标与顶点坐标之间的映射关系后,剩余工作包括将纹理位图加载到内存,为它分配纹理ID,以便重用此纹理。
来看下完整代码吧,注意我们代码中纹理坐标和顶点坐标分开存放了,这样更加清晰点,不然还要stride(跳过)内存。
package com.waitingfy.android.glbasics;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.opengl.GLSurfaceView.Renderer;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
public class TexturedRectangleTest extends Activity {
public GLSurfaceView glView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 去掉activity的标题,全屏显示
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
glView = new GLSurfaceView(this);
glView.setRenderer(new SimpleRenderer());
setContentView(glView);
}
@Override
public void onResume() {
super.onPause();
glView.onResume();
}
@Override
public void onPause() {
super.onPause();
glView.onPause();
}
class SimpleRenderer implements Renderer {
FloatBuffer vertices;
FloatBuffer texture;
ShortBuffer indices;
int textureId;
public SimpleRenderer() {
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4 * 2 * 4);
byteBuffer.order(ByteOrder.nativeOrder());
vertices = byteBuffer.asFloatBuffer();
// vertices.put( new float[] { -80f, -120f,0,1f,
// 80f, -120f, 1f,1f,
// -80f, 120f, 0f,0f,
// 80f,120f, 1f,0f});
vertices.put( new float[] { -80f, -120f,
80f, -120f,
-80f, 120f,
80f, 120f});
ByteBuffer indicesBuffer = ByteBuffer.allocateDirect(6 * 2);
indicesBuffer.order(ByteOrder.nativeOrder());
indices = indicesBuffer.asShortBuffer();
indices.put(new short[] { 0, 1, 2,1,2,3});
ByteBuffer textureBuffer = ByteBuffer.allocateDirect(4 * 2 * 4);
textureBuffer.order(ByteOrder.nativeOrder());
texture = textureBuffer.asFloatBuffer();
texture.put( new float[] { 0,1f,
1f,1f,
0f,0f,
1f,0f});
indices.position(0);
vertices.position(0);
texture.position(0);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Log.d("GLSurfaceViewTest", "surface created");
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
Log.d("GLSurfaceViewTest", "surface changed: " + width + "x"
+ height);
}
@Override
public void onDrawFrame(GL10 gl) {
textureId = loadTexture("bobrgb888.png",gl);
//定义显示在屏幕上的什么位置(opengl 自动转换)
gl.glViewport(0, 0, glView.getWidth(), glView.getHeight());
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrthof(-160, 160, -240, 240, 1, -1);
gl.glEnable(GL10.GL_TEXTURE_2D);
//绑定纹理ID
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertices);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texture);
// gl.glRotatef(1, 0, 1, 0);
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 6,
GL10.GL_UNSIGNED_SHORT, indices);
}
public int loadTexture(String fileName,GL10 gl) {
try {
Bitmap bitmap = BitmapFactory.decodeStream(getAssets().open(
fileName));
int textureIds[] = new int[1];
gl.glGenTextures(1, textureIds, 0);
int textureId = textureIds[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
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_NEAREST);
gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
bitmap.recycle();
return textureId;
} catch (IOException e) {
Log.d("TexturedRectangleTest",
"couldn't load asset 'bobrgb888.png'!");
throw new RuntimeException("couldn't load asset '" + fileName
+ "'");
}
}
}
}
注意下我们这里用到的图片"bobrgb888.png"是png格式,存放在/assets/下,长宽是128*128,好像纹理图片最好是2的n次方大小,而且是正方形。
原文链接: http://www.waitingfy.com/?p=66
源码下载 gl-basics