简体   繁体   中英

Textures are stretched in android opengl es 2.0

I started from the google's android tutorial on open gl and then used this tutorial : to add textures. Since the class structures differ a bit, I had to do some code-moving-renaming. What i ended up is:

在此处输入图片说明

Here is the texture file i used. As one can see, the texture is somehow stretched along (1, 1), although the underlying object is a square. Here is my quad's code, any help is appreciated.

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);

}

}

here is the methode loading texture:

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];
}

Ok, i am now able to answer my own question. The texture was just scaled relative to its origin = left bottom point (u, v) = (0, 0), which has irritated me, since I am new to opengl, I was expecting that it would be scaled relative to at least world origin, or object's centroid.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM