Android 上的 openGL ES 2 中纹理渲染不正确

Texture not rendering properly in openGL ES 2 on Android

我在 Android 上的 openGL ES 2 中渲染纹理时遇到问题。正在绘制图像,但从外观上看纹理未正确环绕。

我已经尝试了所有常用的方法来解决这个问题,但没有任何效果。

下面是其中一张图片的外观:

但是他们在屏幕上的样子是这样的:

忽略作为纹理一部分的黑色边框。

这是我的纹理 class:

public class HFTexture {

private int width;
private int height;

private int textureId;

private HFGame game;
private String textureFile;

public HFTexture(HFGame game, String textureFile) {
    this.game = game;
    this.textureFile = textureFile;
    //load();
}

public void load() {
    int[] texIds = new int[1];
    GLES20.glGenTextures(1, texIds, 0);
    textureId = texIds[0];

    InputStream in;
    try {
        in = game.getFileManager().getAsset(textureFile);
        Bitmap bitmap = BitmapFactory.decodeStream(in);
        width = bitmap.getWidth();
        height = bitmap.getHeight();
        bind();
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
        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_LINEAR);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
        bitmap.recycle();
    } catch(IOException ex) {

    }
}

public void bind() {
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
}

public void activate(HFShader shader, int texture) {
    GLES20.glActiveTexture(texture);
    bind();
    GLES20.glUniform1i(shader.getHandle("sampler0"), 0);
}

public void delete() {
    bind();
    int[] textureIds = {textureId};
    GLES20.glDeleteTextures(1, textureIds, 0);
}

}

这是我的顶点 class:

public class Vertices {

private FloatBuffer vertexBuffer;
private FloatBuffer normalBuffer;
private FloatBuffer texCoordBuffer;
private ShortBuffer indexBuffer;

private final int VERTEX_COUNT;
private final int VERTEX_STRIDE;
private final int VERTEX_SIZE = 3;

private final int NORMAL_STRIDE;
private final int NORMAL_SIZE = 3;

private final int TEXTURE_COORD_STRIDE;
private final int TEXTURE_COORD_SIZE = 2;

private final int INDEX_COUNT;

public Vertices(float[] vertices, float[] normals, float[] texCoords, short[] indices) {
    VERTEX_STRIDE = VERTEX_SIZE * 4;
    NORMAL_STRIDE = NORMAL_SIZE * 4;
    TEXTURE_COORD_STRIDE = TEXTURE_COORD_SIZE * 4;
    VERTEX_COUNT = vertices.length;
    INDEX_COUNT = indices.length;

    ByteBuffer bb = ByteBuffer.allocateDirect(VERTEX_COUNT * VERTEX_STRIDE);
    bb.order(ByteOrder.nativeOrder());
    vertexBuffer = bb.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

    bb = ByteBuffer.allocateDirect(normals.length * NORMAL_STRIDE);
    bb.order(ByteOrder.nativeOrder());
    normalBuffer = bb.asFloatBuffer();
    normalBuffer.put(normals);
    normalBuffer.position(0);

    bb = ByteBuffer.allocateDirect(texCoords.length * TEXTURE_COORD_STRIDE);
    bb.order(ByteOrder.nativeOrder());
    texCoordBuffer = bb.asFloatBuffer();
    texCoordBuffer.put(texCoords);
    texCoordBuffer.position(0);

    bb = ByteBuffer.allocateDirect(indices.length * 2);
    bb.order(ByteOrder.nativeOrder());
    indexBuffer = bb.asShortBuffer();
    indexBuffer.put(indices);
    indexBuffer.position(0);
}

public void bind(HFShader shader) {
    int positionHandle = shader.getHandle("position");
    int normalHandle = shader.getHandle("normal");
    int texCoordHandle = shader.getHandle("texCoord");
    GLES20.glEnableVertexAttribArray(positionHandle);
    GLES20.glVertexAttribPointer(
            positionHandle, VERTEX_SIZE,
            GLES20.GL_FLOAT, false,
            VERTEX_STRIDE, vertexBuffer);
    GLES20.glEnableVertexAttribArray(normalHandle);
    GLES20.glVertexAttribPointer(
            normalHandle, NORMAL_SIZE,
            GLES20.GL_FLOAT, false,
            NORMAL_STRIDE, normalBuffer);
    GLES20.glEnableVertexAttribArray(texCoordHandle);
    GLES20.glVertexAttribPointer(
            texCoordHandle, TEXTURE_COORD_SIZE,
            GLES20.GL_FLOAT, false,
            TEXTURE_COORD_STRIDE, vertexBuffer);
}

public void unbind(HFShader shader) {
    int positionHandle = shader.getHandle("position");
    int normalHandle = shader.getHandle("normal");
    int texCoordHandle = shader.getHandle("texCoord");
    GLES20.glDisableVertexAttribArray(positionHandle);
    GLES20.glDisableVertexAttribArray(normalHandle);
    GLES20.glDisableVertexAttribArray(texCoordHandle);
}

public void draw() {
    if(indexBuffer != null) {
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, INDEX_COUNT, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
    } else {
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, VERTEX_COUNT);
    }
}

}

这是我的顶点数据:

float[] verts = {
            -(width / 2f), (height / 2f), 0f,  // index 0
            -(width / 2f), -(height / 2f), 0f, // index 1
            (width / 2f), -(height / 2f), 0f,  // index 2
            (width / 2f), (height / 2f), 0f    // index 3
    };
    float[] norms = {
            0.0f, 0.0f, -1.0f,
            0.0f, 0.0f, -1.0f,
            0.0f, 0.0f, -1.0f,
            0.0f, 0.0f, -1.0f
    };
    float[] texCoords = {
            0f, 1f,
            0f, 0f,
            1f, 0f,
            1f, 1f
    };

    short[] indices = {
            0,1,2,2,3,0
    };

我也尝试过将钳位添加到边缘纹理参数,但这似乎没有帮助。我只是把顶点和纹理坐标放在错误的顺序还是我完全遗漏了什么?

您正在为纹理坐标设置顶点缓冲区而不是纹理坐标缓冲区:

GLES20.glEnableVertexAttribArray(texCoordHandle);
GLES20.glVertexAttribPointer(
        texCoordHandle, TEXTURE_COORD_SIZE,
        GLES20.GL_FLOAT, false,
        TEXTURE_COORD_STRIDE, vertexBuffer); // <-- here

应该是:

GLES20.glEnableVertexAttribArray(texCoordHandle);
GLES20.glVertexAttribPointer(
        texCoordHandle, TEXTURE_COORD_SIZE,
        GLES20.GL_FLOAT, false,
        TEXTURE_COORD_STRIDE, texCoordBuffer);