我从google's android tutorial on open gl开始,然后使用本教程:添加纹理。由于类结构有点不同,我不得不做一些代码移动重命名。我最终的结果是:
这是我使用的纹理文件。如您所见,纹理以某种方式沿 (1, 1) 拉伸,尽管底层对象是正方形。这是我的四边形代码,感谢您的帮助。
public class GLSquare implements IGLObject {
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" + "attribute vec2 a_TexCoordinate;"
+ "varying vec2 v_TexCoordinate;" + "attribute vec4 vPosition;"
+ "void main() {"
+
// the matrix must be included as a modifier of gl_Position
" gl_Position = uMVPMatrix * vPosition;"
+ "v_TexCoordinate = a_TexCoordinate;" + "}";
private final String fragmentShaderCode = "precision mediump float;"
+ "uniform sampler2D u_Texture;" + "varying vec2 v_TexCoordinate;"
+ "void main() {"
+ " gl_FragColor = texture2D(u_Texture, v_TexCoordinate);" + "}";
private final FloatBuffer vertexBuffer;
private final ShortBuffer drawListBuffer;
private final int mProgramHandle;
private int mPositionHandle;
private int mMVPMatrixHandle;
private int mTextureDataHandle;
/** The texture pointer */
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float squareCoords[] = { -10f, 10f, 0.0f, // top left
-10f, -10f, 0.0f, // bottom left
10f, -10f, 0.0f, // bottom right
10f, 10f, 0.0f }; // top right
private FloatBuffer textureBuffer; // buffer holding the texture coordinates
private float texture[] = {
// Mapping coordinates for the vertices
0.0f, 1.0f, // top left (V2)
0.0f, 0.0f, // bottom left (V1)
1.0f, 1.0f, // top right (V4)
1.0f, 0.0f // bottom right (V3)
};
static float[] mTranslate = new float[16];
static float[] translatedMVP = new float[16];
private final short drawOrder[] = { 0, 1, 2, 0, 2, 3 };
public GLSquare(float x, float y, float z, Context context) {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
bb = ByteBuffer.allocateDirect(texture.length * 4);
bb.order(ByteOrder.nativeOrder());
textureBuffer = bb.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(
// (# of coordinate values * 2 bytes per short)
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
Matrix.setIdentityM(mTranslate, 0);
Matrix.translateM(mTranslate, 0, x, y, z);
// prepare shaders and OpenGL program
final int vertexShaderHandle = GLTools.compileShader(
GLES20.GL_VERTEX_SHADER, vertexShaderCode);
final int fragmentShaderHandle = GLTools.compileShader(
GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgramHandle = GLTools.createAndLinkProgram(vertexShaderHandle,
fragmentShaderHandle, new String[] { "a_Position", "a_Color",
"a_TexCoordinate" });
// Load the texture
mTextureDataHandle = GLTools.loadGLTexture(context, R.raw.stars1024);
}
public void draw(float[] vpMatrix) {
// Add program to OpenGL environment
GLES20.glUseProgram(mProgramHandle);
// Pass in the position information
vertexBuffer.position(0);
GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT,
false, 0, vertexBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
int mTextureCoordinateHandle = GLES20.glGetAttribLocation(
mProgramHandle, "a_TexCoordinate");
// Pass in the texture coordinate information
textureBuffer.position(0);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, 2,
GLES20.GL_FLOAT, false, 0, textureBuffer);
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle,
"uMVPMatrix");
WideOpenRenderer.checkGlError("glGetUniformLocation");
// Apply the projection and view transformation
Matrix.multiplyMM(translatedMVP, 0, vpMatrix, 0, mTranslate, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, translatedMVP, 0);
// Draw the cube.
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
}
}
这是加载纹理的方法:
public static int loadGLTexture(Context context, final int resourceId) {
Log.d("GLTools", "Loading texture...");
final int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0)
{
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Read in the resource
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
Log.d("GLTools", "Binding texture, setting parameter" + resourceId);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
bitmap.recycle();
}
if (textureHandle[0] == 0)
{
throw new RuntimeException("Error loading texture.");
}
return textureHandle[0];
}