【发布时间】:2017-01-08 19:18:46
【问题描述】:
我了解如何创建顶点和片段着色器以及如何创建顶点数组并将它们放在缓冲区中,但是如何将两者联系起来?
含义 - 当我运行我的程序时,它如何知道当前活动缓冲区上的顶点数组应该“馈入”到顶点着色器?
这只是通过使用glVertexAttribPointer 来完成的吗?
【问题讨论】:
标签: opengl
我了解如何创建顶点和片段着色器以及如何创建顶点数组并将它们放在缓冲区中,但是如何将两者联系起来?
含义 - 当我运行我的程序时,它如何知道当前活动缓冲区上的顶点数组应该“馈入”到顶点着色器?
这只是通过使用glVertexAttribPointer 来完成的吗?
【问题讨论】:
标签: opengl
没有真正意义上的“当前活动缓冲区”。 (嗯,有,但它仅在 VAO 规范时与非直接状态访问 API 相关。)
顶点数组对象 (VAO) 将指针(通过glVertexAttribPointer 设置)保存到内存缓冲区中的数据中。与这些缓冲区的绑定是 VAO 状态的一部分。当您绑定一个 VAO 时,随后的 glDraw* 命令会将顶点从绑定到当前 VAO 的缓冲区传输到管道。
为简单起见,下面是 VAO 的大致含义,以及用于设置该状态的相关 OpenGL 4.5 直接状态访问函数名称:
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[];
};
当您调用 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在缓冲区中?
glVertexAttribPointer的第一个参数中,我写了一个对着色器变量的引用,对吧?这就是程序知道将顶点发送到着色器的方式吗?
layout(location = n) 说明符指定它。
glVertexAttribPointer等......然后绑定另一个VAO,并用其他数据和一个不同的指针创建一个不同的缓冲区,然后我可以在 VAO 之间切换,随后的绘图调用将使用当前有界的 VAO?