openGLeES 纹理贴图完整例子
时间: 2023-10-20 15:08:54 浏览: 34
下面是一个使用OpenGL ES 2.0进行纹理贴图的完整例子。该例子使用Android平台的Java语言进行编写,但是只要稍作修改,就可以用于其他平台的OpenGL ES 2.0开发。
在这个例子中,我们将使用一个简单的正方形作为我们的几何形状,并将一张图片作为纹理贴图。我们将使用着色器程序来将纹理映射到几何形状上。
1. 首先,我们需要定义一个顶点着色器程序,用于将顶点坐标和纹理坐标传递给渲染管线:
```
private static final String VERTEX_SHADER =
"uniform mat4 uMVPMatrix;\n" +
"attribute vec4 aPosition;\n" +
"attribute vec2 aTextureCoord;\n" +
"varying vec2 vTextureCoord;\n" +
"void main() {\n" +
" gl_Position = uMVPMatrix * aPosition;\n" +
" vTextureCoord = aTextureCoord;\n" +
"}\n";
```
2. 接下来,我们需要定义一个片段着色器程序,用于将纹理映射到几何形状上:
```
private static final String FRAGMENT_SHADER =
"precision mediump float;\n" +
"varying vec2 vTextureCoord;\n" +
"uniform sampler2D uTextureSampler;\n" +
"void main() {\n" +
" gl_FragColor = texture2D(uTextureSampler, vTextureCoord);\n" +
"}\n";
```
3. 现在,我们需要定义一个顶点数组,用于存储正方形的顶点坐标和纹理坐标:
```
private static final float[] VERTEX_ARRAY = {
// Vertex coordinates (x,y,z)
-1f, 1f, 0f, // top left
1f, 1f, 0f, // top right
-1f, -1f, 0f, // bottom left
1f, -1f, 0f, // bottom right
// Texture coordinates (u,v)
0f, 1f, // top left
1f, 1f, // top right
0f, 0f, // bottom left
1f, 0f // bottom right
};
```
4. 然后,我们需要创建一个顶点缓冲区,并将顶点数组数据传递给它:
```
private FloatBuffer vertexBuffer;
...
// initialize vertex buffer
ByteBuffer bb = ByteBuffer.allocateDirect(VERTEX_ARRAY.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(VERTEX_ARRAY);
vertexBuffer.position(0);
```
5. 接下来,我们需要加载一张图片作为纹理,并将它绑定到OpenGL ES上下文中:
```
private int[] textures = new int[1]; // stores the texture IDs
...
// load texture
Bitmap textureBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.texture);
GLES20.glGenTextures(1, textures, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, textureBitmap, 0);
textureBitmap.recycle();
```
6. 然后,我们需要定义一个着色器程序,并将顶点着色器和片段着色器绑定到它上面:
```
private int program;
...
// initialize shader program
int vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
GLES20.glShaderSource(vertexShader, VERTEX_SHADER);
GLES20.glCompileShader(vertexShader);
int fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(fragmentShader, FRAGMENT_SHADER);
GLES20.glCompileShader(fragmentShader);
program = GLES20.glCreateProgram();
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glLinkProgram(program);
```
7. 最后,我们需要在渲染循环中将顶点坐标和纹理坐标传递给着色器程序,并绘制正方形:
```
// set up MVP matrix
Matrix.setIdentityM(mvpMatrix, 0);
Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
Matrix.multiplyMM(mvpMatrix, 0, modelMatrix, 0, mvpMatrix, 0);
GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mvpMatrix, 0);
// set up vertex attributes
int positionHandle = GLES20.glGetAttribLocation(program, "aPosition");
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
int textureCoordHandle = GLES20.glGetAttribLocation(program, "aTextureCoord");
GLES20.glEnableVertexAttribArray(textureCoordHandle);
GLES20.glVertexAttribPointer(textureCoordHandle, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer);
// bind texture
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glUniform1i(textureSamplerHandle, 0);
// draw
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
// clean up
GLES20.glDisableVertexAttribArray(positionHandle);
GLES20.glDisableVertexAttribArray(textureCoordHandle);
```
完整的例子代码可以在下面找到:
```
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
public class TextureRenderer {
private static final String VERTEX_SHADER =
"uniform mat4 uMVPMatrix;\n" +
"attribute vec4 aPosition;\n" +
"attribute vec2 aTextureCoord;\n" +
"varying vec2 vTextureCoord;\n" +
"void main() {\n" +
" gl_Position = uMVPMatrix * aPosition;\n" +
" vTextureCoord = aTextureCoord;\n" +
"}\n";
private static final String FRAGMENT_SHADER =
"precision mediump float;\n" +
"varying vec2 vTextureCoord;\n" +
"uniform sampler2D uTextureSampler;\n" +
"void main() {\n" +
" gl_FragColor = texture2D(uTextureSampler, vTextureCoord);\n" +
"}\n";
private static final float[] VERTEX_ARRAY = {
// Vertex coordinates (x,y,z)
-1f, 1f, 0f, // top left
1f, 1f, 0f, // top right
-1f, -1f, 0f, // bottom left
1f, -1f, 0f, // bottom right
// Texture coordinates (u,v)
0f, 1f, // top left
1f, 1f, // top right
0f, 0f, // bottom left
1f, 0f // bottom right
};
private FloatBuffer vertexBuffer;
private int[] textures = new int[1];
private int program;
private int mvpMatrixHandle;
private int textureSamplerHandle;
private float[] modelMatrix = new float[16];
private float[] viewMatrix = new float[16];
private float[] projectionMatrix = new float[16];
private float[] mvpMatrix = new float[16];
public TextureRenderer(Context context) {
// initialize vertex buffer
ByteBuffer bb = ByteBuffer.allocateDirect(VERTEX_ARRAY.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(VERTEX_ARRAY);
vertexBuffer.position(0);
// load texture
Bitmap textureBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.texture);
GLES20.glGenTextures(1, textures, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, textureBitmap, 0);
textureBitmap.recycle();
// initialize shader program
int vertexShader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
GLES20.glShaderSource(vertexShader, VERTEX_SHADER);
GLES20.glCompileShader(vertexShader);
int fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
GLES20.glShaderSource(fragmentShader, FRAGMENT_SHADER);
GLES20.glCompileShader(fragmentShader);
program = GLES20.glCreateProgram();
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
GLES20.glLinkProgram(program);
// get attribute and uniform handles
mvpMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix");
textureSamplerHandle = GLES20.glGetUniformLocation(program, "uTextureSampler");
// set up matrices
Matrix.setIdentityM(modelMatrix, 0);
Matrix.setLookAtM(viewMatrix, 0, 0, 0, -5, 0, 0, 0, 0, 1, 0);
Matrix.orthoM(projectionMatrix, 0, -1, 1, -1, 1, 3, 7);
}
public void draw() {
// set up MVP matrix
Matrix.setIdentityM(mvpMatrix, 0);
Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
Matrix.multiplyMM(mvpMatrix, 0, modelMatrix, 0, mvpMatrix, 0);
GLES20.glUniformMatrix4fv(mvpMatrixHandle, 1, false, mvpMatrix, 0);
// set up vertex attributes
int positionHandle = GLES20.glGetAttribLocation(program, "aPosition");
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
int textureCoordHandle = GLES20.glGetAttribLocation(program, "aTextureCoord");
GLES20.glEnableVertexAttribArray(textureCoordHandle);
GLES20.glVertexAttribPointer(textureCoordHandle, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer);
// bind texture
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glUniform1i(textureSamplerHandle, 0);
// draw
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
// clean up
GLES20.glDisableVertexAttribArray(positionHandle);
GLES20.glDisableVertexAttribArray(textureCoordHandle);
}
}
```