簡體   English   中英

Android OpenGL ES 2.0 VBO

[英]Android OpenGL ES 2.0 VBO

我花了幾天時間嘗試使用OpenGL ES 2.0在Android上運行VBO,但似乎無法正常工作。

這是我正在使用的代碼:

/* The Android shader code */
private static final String[] androidVertexShaderCode = new String[] {
        "attribute vec4 vertexPosition;",
        "void main() {",
        "  gl_Position = vertexPosition;",
        "}" };

private static final String[] androidFragmentShaderCode = new String[] {
        "precision mediump float;",
        "uniform vec4 colour;",
        "void main() {",
        "  gl_FragColor = colour;",
        "}" };

/* The Android shader */
public Shader androidShader;

/* The constructor with the render mode and the 
 * number of vertex values given */
public AndroidRenderer(int renderMode, int vertexValuesCount) {
    super(renderMode, vertexValuesCount);
    //Add this renderer to the list
    allRenderers.add(this);
    usage = GLES20.GL_STATIC_DRAW;
    //Setup the Android shader
    this.androidShader = new AndroidShader();
    this.androidShader.vertexShader = ShaderUtils.createShader(ArrayUtils.toStringList(androidVertexShaderCode), Shader.VERTEX_SHADER);
    this.androidShader.fragmentShader = ShaderUtils.createShader(ArrayUtils.toStringList(androidFragmentShaderCode), Shader.FRAGMENT_SHADER);
    this.androidShader.create();
}

/* The method used to setup the buffers,
 * assumes the vertices have already been set */
public void setupBuffers() {
    //Create the vertices buffer
    this.verticesBuffer = BufferUtils.createFlippedBuffer(this.verticesData);
    int[] vh = new int[1];
    GLES20.glGenBuffers(1, vh, 0);
    //Setup the vertices handle
    this.verticesHandle = vh[0];

    //Bind the vertices buffer and give OpenGL the data
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.verticesHandle);
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, Float.BYTES * verticesData.length, this.verticesBuffer, this.usage);
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);

    //Check to see whether the normals have been set
    if (this.normalsData != null) {
        //Create the normals buffer
        this.normalsBuffer = BufferUtils.createFlippedBuffer(this.normalsData);
        int[] nh = new int[1];
        GLES20.glGenBuffers(1, nh, 0);
        //Setup the normals handle
        this.normalsHandle = nh[0];

        //Bind the normals buffer and give OpenGL the data
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.normalsHandle);
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, Float.BYTES * verticesData.length, this.normalsBuffer, this.usage);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }

    //Check to see whether the colours have been set
    if (this.colourData!= null) {
        //Create the colours buffer
        this.coloursBuffer = BufferUtils.createFlippedBuffer(this.colourData);
        int[] ch = new int[1];
        GLES20.glGenBuffers(1, ch, 0);
        //Setup the colours handle
        this.coloursHandle = ch[0];

        //Bind the colours buffer and give OpenGL the data
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.coloursHandle);
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, Float.BYTES * colourData.length, this.coloursBuffer, this.usage);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }

    //Check to see whether the texture coordinates have been set
    if (this.textureData != null) {
        //Create the texture coordinates buffer
        this.texturesBuffer = BufferUtils.createFlippedBuffer(this.textureData);
        int[] th = new int[1];
        GLES20.glGenBuffers(1, th, 0);
        //Setup the texture coordinates handle
        this.texturesHandle = th[0];

        //Bind the texture coordinates buffer and give OpenGL the data
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.texturesHandle);
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, Float.BYTES * textureData.length, this.texturesBuffer, this.usage);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    }
}

/* The method used to draw the object */
public void render() {
    this.androidShader.use();
    short[] indices = new short[this.verticesData.length];
    for (short a = 0; a < indices.length; a++)
        indices[a] = a;
    ShortBuffer indicesBuffer = BufferUtils.createFlippedBuffer(indices);
    //Enable the arrays as needed
    int vertexPositionAttribute = GLES20.glGetAttribLocation(this.androidShader.program, "vertexPosition");
    int normalAttribute = 0;
    int colourAttribute = 0;
    int texturesAttribute = 0;
    GLES20.glEnableVertexAttribArray(vertexPositionAttribute);
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.verticesHandle);
    GLES20.glVertexAttribPointer(vertexPositionAttribute, this.vertexValuesCount, GLES20.GL_FLOAT, false, 0, 0);
    if (this.normalsData != null) {
        GLES20.glEnableVertexAttribArray(normalAttribute);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.normalsHandle);
        GLES20.glVertexAttribPointer(normalAttribute, 2, GLES20.GL_FLOAT, false, 0, 0);
    }
    if (this.colourData != null) {
        colourAttribute = GLES20.glGetAttribLocation(this.androidShader.program, "colour");
        Log.d("HELLO", "" + colourAttribute);
        GLES20.glEnableVertexAttribArray(colourAttribute);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.coloursHandle);
        GLES20.glVertexAttribPointer(colourAttribute, this.colourValuesCount, GLES20.GL_FLOAT, false, 0, 0);
    }
    if (this.textureData != null) {
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.texturesHandle);
        GLES20.glEnableVertexAttribArray(texturesAttribute);
        GLES20.glVertexAttribPointer(texturesAttribute, this.textureValuesCount, GLES20.GL_FLOAT, false, 0, 0);
    }
    //Draw the arrays
    GLES20.glDrawElements(this.renderMode, indices.length, GLES20.GL_UNSIGNED_SHORT, indicesBuffer);
    //Disable the arrays as needed
    if (this.normalsData != null)
        GLES20.glDisableVertexAttribArray(normalAttribute);
    if (this.textureData != null)
        GLES20.glDisableVertexAttribArray(texturesAttribute);
    if (this.colourData != null)
        GLES20.glDisableVertexAttribArray(colourAttribute);
    GLES20.glDisableVertexAttribArray(vertexPositionAttribute);
    this.androidShader.stopUsing();
}

目前,我還沒有實現法線或紋理的使用,因為我只是想繪制一個三角形,每個頂點的顏色不同。 我知道着色器應該可以正常工作,只要使用相同的着色器僅使用一種顏色以及頂點/顏色數據進行渲染即可。

當我查看LogCat時,消息:GL_INVALID_VALUE已被打印出來。 然后,我決定打印出使用glGetAttribLocation找到的colourAttribute的值,事實證明這是-1。 經過進一步研究,我發現了這一點: https : //www.opengl.org/sdk/docs/man/html/glGetAttribLocation.xhtml ,它指出返回值-1“如果命名屬性變量不是活動屬性在指定的程序對象中”。

搜索Google之后,我還沒有找到解決三角形不渲染問題的方法,因此不勝感激。

謝謝。

它表明vertexAttributePointer方法的跨度始終為0。這意味着您使用顏色值覆蓋了頂點緩沖區中的頂點位置。

GLES20.glVertexAttribPointer(colourAttribute, this.colourValuesCount, GLES20.GL_FLOAT, false, **0**, 0);

您必須將步幅增加之前頂點屬性大小之和的偏移量。 在您的情況4中,由於vertexPosition向量的vec4。 稍后,紋理和法線也是如此。

在這里查看glVertexAttribPointer的定義: http : //androidbook.com/akc/display? url=displaynoteimpurl&ownerUserId=android&reportId= 4229

另外,您可以嘗試向片段着色器添加固定的顏色,例如:

gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);

因此,可以避免colorHandle對渲染過程產生任何影響。

此外,嘗試避免先使用IndexBuffer而不使用

glDrawElements(.. , ..) 

方法只需將vertexBufferObject與

glDrawArrays(.., .., )

方法。

如果可行,您當然可以切換回IndexBuffer方法。

由於評論而更新

我現在看到另一個問題。 您錯過了鏈接着色器並使用glLinkProgram和glUseProgram啟用它的鏈接。 在這里看看: 適用於Android OpenGL ES的着色器

這篇文章還向您展示了如何輸出着色器程序的編譯錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM