Использование glVertexAttribPointer и glDrawElements для рисования из упакованного буфера вершин - PullRequest
3 голосов
/ 31 марта 2012

У меня есть упакованный буфер вершин, содержащий координаты положения, а также значения цвета для вершины в формате {X, Y, Z, R, G, B, A}.

Я могу отобразитьПрямоугольник с жестко заданным цветом, когда я изменяю фрагментный шейдер, вынимая атрибут a_Color и жестко кодируя значение vec4 для gl_FragColor, но я не могу передать цветовой атрибут vec4 в фрагментный шейдер (прямоугольник не будет отображатьсясценарий).

Как правильно использовать glVertexAttribPointer (...) и glDrawElements (...) для рисования из упакованного буфера вершин в OpenGL ES 2.0?

См. мой кодниже:

public class GameRenderer implements Renderer {
    public static final int POS_SZ = 3;
    public static final int COL_SZ = 4;
    public static final int FLOAT_SZ = 4;
    public static final int SHORT_SZ = 2;

    private FloatBuffer gridVB;
    private ShortBuffer gridIndices;
    int programCode, paPositionHandle, paColorHandle, puMVPMatrixHandle;

    private final String vertexShaderCode =
        "uniform mat4 u_MVPMatrix;  \n" +
        "attribute vec4 a_Position; \n" +
        "void main(){               \n" +
        " gl_Position = u_MVPMatrix * a_Position;   \n" +
        "} \n";

    private String fragmentShaderCode = 
        "precision mediump float;   \n" +
        "attribute vec4 a_Color; \n" +
        "void main(){               \n" +
        " gl_FragColor = a_Color;   \n" +
        "}                          \n";

    public void staticGrid() {
        float vertexArray[] = {
            -0.75f, 0.75f, 0.0f,        // position
            0.0f, 0.0f, 1.0f, 1.0f,     // colour
            0.75f, 0.75f, 0.0f,
            0.0f, 0.0f, 1.0f, 1.0f,
            0.75f, -0.75f, 0.0f,
            0.0f, 0.0f, 1.0f, 1.0f,
            -0.75f, -0.75f, 0.0f,
            0.0f, 0.0f, 1.0f, 1.0f
        };

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

        ByteBuffer vbb = ByteBuffer.allocateDirect(vertexArray.length * FLOAT_SZ);
        vbb.order(ByteOrder.nativeOrder());
        gridVB = vbb.asFloatBuffer();
        gridVB.put(vertexArray);
        gridVB.position(0);

        ByteBuffer ibb = ByteBuffer.allocateDirect(indicesArray.length * SHORT_SZ);
        ibb.order(ByteOrder.nativeOrder());
        gridIndices = ibb.asShortBuffer();
        gridIndices.put(indicesArray);
        gridIndices.position(0);
    }

    public void onSurfaceCreated(GL10 unused, EGLConfig arg1) {
        GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
        staticGrid();
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
        programCode = GLES20.glCreateProgram();
        GLES20.glAttachShader(programCode, vertexShader);
        GLES20.glAttachShader(programCode, fragmentShader);
        GLES20.glLinkProgram(programCode);

        paPositionHandle = GLES20.glGetAttribLocation(programCode, "a_Position");
        paColorHandle = GLES20.glGetAttribLocation(programCode, "a_Color");
        puMVPMatrixHandle = GLES20.glGetUniformLocation(programCode, "u_MVPMatrix");
    }

    public void onDrawFrame(GL10 unused) {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        GLES20.glUseProgram(programCode);

        int stride = (POS_SZ + COL_SZ) * FLOAT_SZ;
        int indices_cnt = 6;

        gridVB.position(0);
        GLES20.glEnableVertexAttribArray(paPositionHandle);
        GLES20.glVertexAttribPointer(paPositionHandle, POS_SZ, GLES20.GL_FLOAT, false, stride, gridVB);

        gridVB.position(POS_SZ);
        GLES20.glEnableVertexAttribArray(paColorHandle);
        GLES20.glVertexAttribPointer(paColorHandle, COL_SZ, GLES20.GL_FLOAT, false, stride, gridVB);

        // matrix manipulation ...

        GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices_cnt, GLES20.GL_UNSIGNED_SHORT, gridIndices);
    }
}

1 Ответ

6 голосов
/ 31 марта 2012

Фрагментные шейдеры не используют атрибуты. Атрибуты являются значениями для каждой вершины, о которых фрагментный шейдер ничего не знает. Что вы хотите сделать, это взять цвет как attribute для вершинного шейдера, а затем использовать varying, чтобы передать цвет фрагментному шейдеру.

Также, пожалуйста, начните использовать проверку ошибок для ваших шейдеров, она сообщит вам, когда вы сделаете такие ошибки:

http://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetProgramiv.xml (проверьте GL_LINK_STATUS)

http://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetShaderiv.xml (проверьте GL_COMPILE_STATUS)

http://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetProgramInfoLog.xml

http://www.khronos.org/opengles/sdk/docs/man/xhtml/glGetShaderInfoLog.xml

...