【问题标题】:OpenGL ES 2.0 Drawing Quad CrashesOpenGL ES 2.0 绘制四边形崩溃
【发布时间】:2015-03-20 03:30:17
【问题描述】:

我在使用 VBO 的 OpenGL ES 2.0 在 Android 中渲染四边形时遇到问题。

由于某种原因,当我运行该程序时,它会使模拟器崩溃。我正在使用 Andy 作为模拟器。我试过使用android自带的默认模拟器,在这种情况下,应用程序根本无法运行。我正在使用 eclipse 作为我的 ide。

我已设法将问题缩小到 Quad 类的渲染方法。

我想我想知道我设置 VBO 和渲染它们的方式有问题吗?

这是我的代码:

四重渲染方法:

@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public void render()
{
    mat.useMaterial();

    GLES20.glFrontFace(GLES20.GL_CW);

    //Generate VBO Buffer Handles and assign it to 'buffers'
    GLES20.glGenBuffers(4, buffers, 0);
    GLES20.glGenBuffers(1, ibo, 0);

    //Positions

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0]);
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexBuffer.capacity() * 4, vertexBuffer, GLES20.GL_STATIC_DRAW);
    GLES20.glEnableVertexAttribArray(0);
    GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
    //GLES10.glVertexPointer(3, GLES10.GL_FLOAT, 0, vertexBuffer);

    //Normals

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[1]);
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, normalBuffer.capacity() * 4, normalBuffer, GLES20.GL_STATIC_DRAW);
    GLES20.glEnableVertexAttribArray(1);
    GLES20.glVertexAttribPointer(1, 3, GLES20.GL_FLOAT, false, 0, normalBuffer);
    //GLES10.glNormalPointer(GLES10.GL_FLOAT, 0, normalBuffer);

    //Texcoords

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[2]);
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, texcoordBuffer.capacity() * 4, texcoordBuffer, GLES20.GL_STATIC_DRAW);
    GLES20.glEnableVertexAttribArray(2);
    GLES20.glVertexAttribPointer(2, 2, GLES20.GL_FLOAT, false, 0, texcoordBuffer);
    //GLES10.glTexCoordPointer(2, GLES10.GL_FLOAT, 0, texcoordBuffer);

    //Colors

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[3]);
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, colorBuffer.capacity() * 4, colorBuffer, GLES20.GL_STATIC_DRAW);
    GLES20.glEnableVertexAttribArray(3);
    GLES20.glVertexAttribPointer(3, 4, GLES20.GL_FLOAT, false, 0, colorBuffer);
    //GLES10.glColorPointer(4, GLES10.GL_FLOAT, 0, colorBuffer);

    //Indices

    GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo[0]);
    GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.capacity() * 4, indexBuffer, GLES20.GL_STATIC_DRAW);

    //Draw

    GLES20.glDrawElements(GLES20.GL_TRIANGLES, indexBuffer.capacity(), GLES20.GL_UNSIGNED_INT, indexBuffer);
    //GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertices.length / 3);

    //Unbind buffers

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

这里还有 Material 类:

package com.game.shading;

import android.opengl.GLES20;

public class Material 
{
private final String vertexShaderCode =
                "attribute vec3 vPosition;"                    +
                "attribute vec3 vNormal;"                      +
                "attribute vec2 vTexcoord"                     +
                ""                                             +
                "void main()"                                  + 
                "{"                                            +
                "    gl_Position = vec4(vPosition, 0);"        +
                "}";

private final String fragmentShaderCode =
                "precision mediump float;"                     +
                "uniform vec4 vColor;"                         +
                ""                                             +
                "void main()"                                  + 
                "{"                                            +
                "    gl_FragColor = vColor;"                   +
                "}";

private int vertShader;
private int fragShader;
private int shaderProgram;

public Material()
{
    vertShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
    fragShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

    shaderProgram = GLES20.glCreateProgram();
    GLES20.glAttachShader(shaderProgram, vertShader);
    GLES20.glAttachShader(shaderProgram, fragShader);
    GLES20.glLinkProgram(shaderProgram);
}

public void useMaterial()
{
    GLES20.glUseProgram(shaderProgram);
}

public void cleanupMaterial()
{
    GLES20.glDetachShader(shaderProgram, vertShader);
    GLES20.glDetachShader(shaderProgram, fragShader);
    GLES20.glDeleteShader(vertShader);
    GLES20.glDeleteShader(fragShader);
    GLES20.glDeleteProgram(shaderProgram);
}

private int loadShader(int type, String source)
{
    int shader = GLES20.glCreateShader(type);
    GLES20.glShaderSource(shader, source);
    GLES20.glCompileShader(shader);

    return shader;
}
}

【问题讨论】:

    标签: android opengl-es vbo


    【解决方案1】:

    您设置属性的方式有问题。以其中一个为例(同样的事情适用于所有这些,以及索引缓冲区):

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0]);
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexBuffer.capacity() * 4, vertexBuffer, GLES20.GL_STATIC_DRAW);
    GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
    

    在 ES 2.0 中,glVertexAttribPointer() 调用有两种变体。它们在 Java 绑定中有不同的签名:

    • 其中一个将Buffer 作为最后一个参数。用于指定直接从传入的缓冲区的内存中拉取顶点数据。这通常称为“客户端顶点数组”。
    • 另一个将int 作为最后一个参数。它用于存储在 VBO 中的属性值。然后,参数是相对于 VBO 开始的偏移量

    您使用的是第一个版本的调用,而实际上您有一个 VBO 绑定。在这种情况下,您需要使用第二个版本。由于您的属性数据从 VBO 的开头开始,因此偏移值为 0:

    GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, 0);
    

    然后更正其他属性和索引的相同问题。

    我也没有看到将顶点属性位置与顶点着色器中的属性相关联的代码。添加的一种选择是在链接程序之前使用glBindAttribLocation() 调用

    【讨论】:

      猜你喜欢
      • 2013-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多