OpenGL - 需要简单的概念澄清

3
我知道如何创建顶点着色器和片段着色器,并创建顶点数组并将它们放入缓冲区,但如何将两者链接起来呢?
也就是说,当我运行程序时,它如何知道当前活动缓冲区上的顶点数组应该被"喂"到顶点着色器中?
这是否只需要使用glVertexAttribPointer来完成?
1个回答

4
“当前活动的缓冲区”即GL_ARRAY_BUFFER在绘制调用期间“不被使用”,它仅仅是告诉glVertexAttribPointer函数应该绑定哪个缓冲区到VAO上。一旦建立了这种连接,GL_ARRAY_BUFFER就可以解绑了。
“如何链接两者?”你的顶点数组和顶点着色器之间的链接是当前活动的“顶点数组对象”(VAO)。渲染管线将从绑定到VAO上的缓冲区中获取着色器所需的顶点属性。
以下伪C定义可帮助总结VAO状态:
struct VertexArrayObject
{
    // VertexArrayElementBuffer
    uint element_buffer;

    struct Binding {
        // VertexArrayVertexBuffers
        uint buffer;
        intptr offset;
        sizei stride;

        // VertexArrayBindingDivisor
        uint divisor;
    } bindings[];

    struct Attrib {
        // VertexArrayAttribBinding
        uint binding; // This is an index into bindings[]

        // EnableVertexArrayAttrib
        bool enabled;

        // VertexArrayAttrib*Format
        int size;
        enum type;
        boolean normalized;
        boolean integer;
        boolean long;
        uint relativeoffset;
    } attribs[];
};

评论中提到了对应的OpenGL 4.5 DSA函数,可以用来设置相应的状态。

当您使用glVertexAttribPointer时,它实际上在当前绑定的VAO上执行以下操作:

vao.attribs[index].binding = index;
vao.attribs[index].size = size;
vao.attribs[index].type = type;
vao.attribs[index].normalized = normalized;
vao.attribs[index].relativeoffset = 0;
vao.bindings[index].buffer = current ARRAY_BUFFER;
vao.bindings[index].offset = pointer;
vao.bindings[index].stride = stride; // if stride == 0 computes based on size and type

请注意,是通过glVertexAttribPointer函数调用将“活动”缓冲区绑定到VAO。如果您使用直接状态访问API(DSA)设置VAO,则甚至不需要激活任何缓冲区。


好的,只是为了确保我理解 - 不推荐使用VAO的替代方法是每次必须重新声明glVertexAttribPointer来告诉GPU如何处理缓冲区中的数据? - gambit20088
什么?从OpenGL 3开始,您必须使用VAO将基元传输到GPU。 - Yakov Galka
另外,在 glVertexAttribPointer 的第一个参数中,我写了一个着色器变量的引用,是吗?这就是程序知道将顶点发送到着色器的方式吗? - gambit20088
是的,这就是属性索引,你可以在着色器中使用layout(location = n)指定它。 - Yakov Galka
好的,谢谢!最后一个问题,我发誓!哈哈 我很确定答案是“是”,但我想再确认一下。所以VAO的整个概念是让我绑定一个,然后创建和绑定一个带有一些数据、glVertexAttribPointer等的缓冲区... 然后绑定另一个VAO,并使用其他数据和不同的指针创建不同的缓冲区,然后我可以在VAO之间切换,随后的绘制调用将使用当前绑定的VAO? - gambit20088
是的。尽管在更“高级”的情况下,您可能会在不同的VAO中使用相同的缓冲区。 - Yakov Galka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接