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

时间:2018-12-17 04:17:09

标签: c++ opengl-es glsl shader opengl-es-3.0

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

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

        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"

Pardon C ++字符串:)

谢谢!!

1 个答案:

答案 0 :(得分:4)

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

顶点着色器

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

通过glLinkProgram链接着色器程序后,可以通过glGetAttribLocation获取属性ind3ex:

GLuint cubeShader = ....;

glLinkProgram(cubeShader);

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

这是分别在glVertexAttribPointer 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);