属性的多个缓冲区如何在 openGL (ES) 着色器和 C++ 中工作 api

How do multiple buffers for attributes work in openGL (ES) shaders and C++ api

我有众所周知的立方体示例,并且一直在编写一些代码来测试它并了解有关着色器的更多信息。我的问题是关于如何分配多个缓冲区以在着色器中访问以及如何编写着色器代码来引用它们。那里的样本似乎依赖于某种隐式引用默认值,这些默认值隐藏了真正发生的事情以及人们如何在样本中对其进行操作。

我的缓冲区设置如下(数据略)

        glGenBuffers(1, &vertexPosObject);
        glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
            sizeof(Vec3f), (void*)0);

        /* load index buffer with array of indices */
        glGenBuffers(1, &indexBufferObject);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

        /* load color buffer with array of colors */
        glGenBuffers(1, &colorBufferObject);
        glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertColors), vertColors, GL_STATIC_DRAW);

        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE,
            sizeof(Vec4f), 0);

有了这个,我得到了一个立方体绘图并可以旋转它。与.

        Matrix4d modelView;
        double rot = rc.timing().frameTime()*.3;
        rot = fmod(rot, ARTD_M_PI * 2);
        modelView.setRotation(Vec3d(0, 1, 1), rot);
        artdGlUniformMatrix4(modelViewId, modelView); // convenience call

那我就画在下面

        glUseProgram(cubeShader);

        glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject);
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject);

        const int vertexCount = 36;
        const int type = GL_UNSIGNED_INT; // unsigned short ??
        const int firstIndex = 0;

        // vertexCount is the number of verts in your vertex array object
        // firstIndex is the first index to use in an array of offsets (element index) into the vertex data.

        glDrawElements(GL_TRIANGLES, vertexCount, type, (void *)firstIndex);

        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);

我一直假设顶点数组被分配了一个“插槽”

        glEnableVertexAttribArray(0);

那个插槽“0”隐式着色器将其作为输入顶点。 (???)

所以我想我会尝试将颜色数组分配给插槽“1”,因此索引数组句柄直接传递到 glDrawElements() 并使用索引数组寻址着色器中的输入检索顶点分配给插槽“0”的缓冲区。

总的来说,我假设人们可能需要多个缓冲区来处理法线、颜色等各种内容,并且需要访问这些缓冲区的值并使用索引寻址它们。所以一般情况下的答案是可取的。

我的问题是,如何在着色器中访问颜色数组缓冲区以及在顶点着色器中将其他缓冲区作为可索引数组访问?

如何将缓冲区绑定到各种着色器可访问标识符,以及如何从着色器代码中的这些标识符访问它们。了解这些关系是关键。

目前这对着色器适用于使用计算颜色绘制立方体。

    "uniform mat4 Projection;\n"
    "uniform mat4 Model;\n"

    "attribute vec4 vPosition;\n"
    "varying vec3 color;\n"
    "void main(){\n"
        "mat4 MVP = Model * Projection;\n"
        "gl_Position = vPosition * MVP;\n"
        "color = gl_Position.xyz + vec3(0.5);\n"
    "}\n"

片段着色器

   "precision mediump float;\n"
    "varying vec3 color;\n"
    "void main()\n"
    "{\n"
        "gl_FragColor = vec4 ( color, 1.0 );\n"
    "}\n"

请原谅 C++ 字符串 :)

如果要使用颜色属性,则必须向着色器添加新属性:

顶点着色器

attribute vec4 vPosition;
attribute vec4 vColor;

varying vec4 color;

uniform mat4 Projection;
uniform mat4 Model;

void main()
{
    mat4 MVP    = Model * Projection;
    gl_Position = vPosition * MVP;
    color       = vColor;
}

shader程序链接后glLinkProgram, the attribute index can be retrieved through glGetAttribLocation:

GLuint cubeShader = ....;

glLinkProgram(cubeShader);

GLint pos_attr_i   = glGetAttribLocation(cubeShader, "vPosition");
GLint color_attr_i = glGetAttribLocation(cubeShader, "vColor");

这是必须在 glVertexAttribPointer respectively glEnableVertexAttribArray 中使用的属性索引:

glBindBuffer(GL_ARRAY_BUFFER, vertexPosObject);
glVertexAttribPointer(pos_attr_i, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3f), (void*)0);

glBindBuffer(GL_ARRAY_BUFFER, colorBufferObject);
glVertexAttribPointer(color_attr_i, 4, GL_FLOAT, GL_FALSE, sizeof(Vec4f), 0);

glEnableVertexAttribArray(pos_attr_i);
glEnableVertexAttribArray(color_attr_i);