2015-03-20 4 views
0

У меня возникли проблемы с рендерингом Quad в Android с OpenGL ES 2.0 с использованием VBOs.OpenGL ES 2.0 Drawing Quad Crashes

По какой-то причине, когда я запускаю программу, она выдает эмулятор. Я использую Энди для эмулятора. Я попытался использовать эмулятор по умолчанию, который поставляется с Android, и в этом случае приложение просто не будет работать. Я использую eclipse как мой идеал.

Мне удалось сузить проблему до метода рендеринга класса Quad.

Я думаю, мне интересно, есть ли проблема с тем, как я настраиваю VBOs и их рендеринг?

Вот мой код:

Quad визуализации метод:

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

Также здесь есть Материал класс:

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

ответ

0

У вас есть проблемы с тем, как вы создали атрибуты , Принимая один из них в качестве примера (то же самое относится ко всем из них, а также в качестве буфера индекса):

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() звонки перед тем, как связать программу.