OpenGL ES 2.0 vbo white screen



我一直在尝试让我的游戏引擎在android上工作,我被困在顶点缓冲数组。它使用FloatBuffer工作,但当我试图用vbo渲染时,我只得到一个白屏幕。所以我想知道我的代码是否有问题。

我是这样创建vbo的:

private int[] vbo = new int[1];
private int[] ibo = new int[1];
private void setUpVBO()
{
    short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
    float TextureCoords[] = 
    { 
    0.0f, 0.0f,   // bottom left
    0.0f, 1.0f,   // top left
    1.0f, 1.0f, // top right
    1.0f, 0.0f,   // bottom right
    };
    float squareCoords[] = { 
                -width / 2.f - 0.015f / 2.f,  height / 2.f + 0.015f / 2.f, 0.0f,   // top left
                -width / 2.f - 0.015f / 2.f, -height / 2.f - 0.015f / 2.f, 0.0f,   // bottom left
                 width / 2.f + 0.015f / 2.f, -height / 2.f - 0.015f / 2.f, 0.0f,   // bottom right
                 width / 2.f + 0.015f / 2.f,  height / 2.f + 0.015f / 2.f, 0.0f }; // top right
        ByteBuffer bb = ByteBuffer.allocateDirect(bb.order(ByteOrder.nativeOrder());
        bb.order(ByteOrder.nativeOrder());
        FloatBuffer vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(squareCoords);
        vertexBuffer.position(0);
        // initialize vertex byte buffer for shape coordinates
        ByteBuffer tc = ByteBuffer.allocateDirect(TextureCoords.length * 4);
        tc.order(ByteOrder.nativeOrder());
        FloatBuffer TextureCoordinateBuffer = tc.asFloatBuffer();
        TextureCoordinateBuffer.put(TextureCoords);
        TextureCoordinateBuffer.position(0);

        // initialize byte buffer for the draw list
        ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
        dlb.order(ByteOrder.nativeOrder());
        ShortBuffer drawListBuffer = dlb.asShortBuffer();
        drawListBuffer.put(drawOrder);
        drawListBuffer.position(0);

        GLES20.glGenBuffers(1, vbo, 0);
        GLES20.glGenBuffers(1, ibo, 0);
        if (vbo[0] > 0 && ibo[0] > 0) 
        {
            GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
            GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexBuffer.capacity() * 4,
                    vertexBuffer, GLES20.GL_STATIC_DRAW);
            GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
            GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, TextureCoordinateBuffer.capacity() * 4,
                    TextureCoordinateBuffer, GLES20.GL_DYNAMIC_DRAW);

            GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo[0]);
            GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, drawListBuffer.capacity()
                    * 2, drawListBuffer, GLES20.GL_STATIC_DRAW);
            GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
            GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
    }
}

我是这样渲染的:

public void render(float[] mMVPMatrix) 
{       
    if (vbo[0] > 0 && ibo[0] > 0) 
    {
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
        GLES20.glEnableVertexAttribArray(Values.mPositionHandle);
        GLES20.glVertexAttribPointer(Values.mPositionHandle, Values.COORDS_PER_VERTEX,
                GLES20.GL_FLOAT, false,
                Values.fullStride, 0);

        GLES20.glEnableVertexAttribArray(Values.mTextureCoordinateHandle);
        GLES20.glVertexAttribPointer(Values.mTextureCoordinateHandle, Values.COORDS_PER_VERTEX_TEXTURE, 
                GLES20.GL_FLOAT, false,
                Values.fullStride, 0);

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureOfBody); 
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
        GLES20.glUniform1i(Values.mTheActualTexture, 0);

    GLES20.glUniform4fv(Values.mColorHandle, 1, colorOfBody, 0);

        // Apply the projection and view transformation
        GLES20.glUniformMatrix4fv(Values.mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
        // Draw the square
        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo[0]);
        GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, 0);
        // Disable vertex array
        GLES20.glDisableVertexAttribArray(Values.mTextureCoordinateHandle);
        GLES20.glDisableVertexAttribArray(Values.mPositionHandle);

        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
    }
}

着色器被正确加载。这是我的着色器:

顶点:

    uniform mat4 uMVPMatrix;
    attribute vec4 vPosition;
    attribute vec2 TexCoordinate;
    varying vec2 TexCoordinateGLFS;
    void main()
    {
        TexCoordinateGLFS = TexCoordinate;
        gl_Position = uMVPMatrix * newPosition ;
    }

片段:

    precision mediump float;
    uniform sampler2D theActualTexture;
    uniform vec4 vColor;
    varying vec2 TexCoordinateGLFS;
    void main() 
    {
        gl_FragColor = texture2D(theActualTexture, TexCoordinateGLFS) * vColor;
    }
一些变量:

public static final int COORDS_PER_VERTEX = 3;
public static final int COORDS_PER_VERTEX_TEXTURE = 2;
public static final int vertexStride = COORDS_PER_VERTEX * 4;
public static final int textureStride = COORDS_PER_VERTEX_TEXTURE * 4;
public static final int fullStride = (COORDS_PER_VERTEX + COORDS_PER_VERTEX_TEXTURE) * 4;

编辑:这是新的VBO结构:

    ByteBuffer bb = ByteBuffer.allocateDirect((squareCoords.length + TextureCoords.length) * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(squareCoords);
        vertexBuffer.put(TextureCoords);
        vertexBuffer.position(0);

GLES20.glGenBuffers(1, vbo, 0);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexBuffer.capacity() * BYTES_PER_FLOAT,
                    vertexBuffer, GLES20.GL_DYNAMIC_DRAW);

我在这里画:

        GLES20.glVertexAttribPointer(Values.mPositionHandle, Values.COORDS_PER_VERTEX,
                GLES20.GL_FLOAT, false,
                Values.vertexStride, 0);
        GLES20.glVertexAttribPointer(Values.mTextureCoordinateHandle, Values.COORDS_PER_VERTEX_TEXTURE, 
                GLES20.GL_FLOAT, false,
                Values.textureStride, squareCoords.length);

squareCoords。长度== 12;(每个顶点3个坐标(x, y, z) -> 4 * 3 = 12)

从你发布的代码来看,你似乎用你的纹理坐标覆盖了你的位置坐标。一般来说,你需要和数组一样多的缓冲区,所以在你的情况下,你需要一个单独的纹理坐标缓冲区。更优雅的解决方案是将上述两个数组合并为一个交错数组,将其推入单个VBO,并在设置顶点和纹理坐标指针时使用stride。

这是完全不允许的:

GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexBuffer.capacity() * 4, vertexBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, TextureCoordinateBuffer.capacity() * 4, TextureCoordinateBuffer, GLES20.GL_DYNAMIC_DRAW);

当您绑定相同的缓冲区两次并将数据推送到GPU时,因此最终所有剩下的都是纹理坐标(实际上代码可能会根据您的矩阵在屏幕上的某个地方产生单个像素图像)

最新更新