不同缓冲区布局中的 glVertexArrayVertexBuffer() / glVertexArrayAttribFormat() 出现问题
Trouble with glVertexArrayVertexBuffer() / glVertexArrayAttribFormat() in different buffer layouts
我正在尝试通过直接状态访问使我的 OpenGL 代码跟上速度,并且一直在密切关注 Guide to Modern OpenGL Functions 中的代码。我有一个带有一些顶点和颜色的小测试项目:
std::vector<float> vertices;
for (float y = -1.0f; y < 1.1f; y += 1.0f) {
for (float x = -1.0f; x < 1.1f; x += 1.0f) {
vertices.emplace_back(x);
vertices.emplace_back(y);
vertices.emplace_back(0.5f);
vertices.emplace_back(0.5f);
vertices.emplace_back(0.5f);
}
}
这些顶点及其索引的可视化表示:
我的主要绘制代码是这样的:
unsigned int vbo = 0;
glCreateBuffers(1, &vbo);
glNamedBufferStorage(vbo, sizeof(float) * vertices.size(), vertices.data(), GL_DYNAMIC_STORAGE_BIT);
// Indices
unsigned int indices[]{ 0,1,3,5,8,7 };
unsigned int ibo = 0;
glCreateBuffers(1, &ibo);
glNamedBufferStorage(ibo, sizeof(unsigned int) * 6, indices, GL_DYNAMIC_STORAGE_BIT);
int bindingindex_a = 1;
int bindingindex_b = 2;
int pos_location = 3;
int color_location = 4;
unsigned int vao = 0;
glCreateVertexArrays(1, &vao);
glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 5 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 0, 5 * sizeof(float));
glVertexArrayElementBuffer(vao, ibo);
glEnableVertexArrayAttrib(vao, pos_location);
glEnableVertexArrayAttrib(vao, color_location);
glVertexArrayAttribFormat(vao, pos_location, 2, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribFormat(vao, color_location, 3, GL_FLOAT, GL_FALSE, 2*sizeof(float));
glVertexArrayAttribBinding(vao, pos_location, bindingindex_a);
glVertexArrayAttribBinding(vao, color_location, bindingindex_b);
所以我绘制了两个灰色三角形,索引分别为 0、1、3 和 5、8、7。我的着色器中的属性位置在 cpp 代码中指定:
layout (location = 3) in vec2 pos;
layout (location = 4) in vec3 col;
这有效!:
甚至当我增加难度并在前面添加单个浮点值时,我可以将 glVertexArrayVertexBuffer()
函数中的偏移量调整 4 个字节。
问题是当我想从缓冲区布局 A 转到 B 时:
我调整我的数据填充循环以先写位置,然后是颜色:
for (float y = -1.0f; y < 1.1f; y += 1.0f) {
for (float x = -1.0f; x < 1.1f; x += 1.0f) {
vertices.emplace_back(x);
vertices.emplace_back(y);
}
}
for (float y = -1.0f; y < 1.1f; y += 1.0f) {
for (float x = -1.0f; x < 1.1f; x += 1.0f) {
vertices.emplace_back(0.5f);
vertices.emplace_back(0.5f);
vertices.emplace_back(0.5f);
}
}
并将调用调整为 glVertexArrayVertexBuffer()
和 glVertexArrayAttribFormat()
:
glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 2 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 18*sizeof(float), 3 * sizeof(float));
glVertexArrayAttribFormat(vao, pos_location, 2, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribFormat(vao, color_location, 3, GL_FLOAT, GL_FALSE, 0);
所以现在我的全局颜色偏移量为 18 个浮点数(9 个位置乘以两个分量),我的 relativeoffset
(khronos.org 就是这样称呼它的)两者都为 0。这显示灰色的东西,但不是他们以前做的方式。我对这些东西如何运作的心智模型显然是错误的 - 哪里?
offset 参数 glVertexArrayVertexBuffer
是缓冲区第一个元素的字节偏移量,形成缓冲区的开始和 stride 是缓冲区内连续属性之间的距离。
情况 A 的顶点规范错误:
glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 5 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 0, 5 * sizeof(float));
每个顶点属性元组由 5 个分量(x、y、r、g、b)组成。
(x1, y1, r1, g1, b1, x2, y2, r2, g2, b2, x3, y3, r3, g3, b3, ...)
因此颜色属性的偏移量是2*sizeof(float)
:
glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 5 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 2 * sizeof(float), 5 * sizeof(float));
x1的字节偏移量为0
.
r1的字节偏移量为2 * sizeof(float)
.
从 x1 到 x2 的字节距离是 5 * sizeof(float)
.
从 r1 到 r2 的字节距离是 5 * sizeof(float)
.
案例 B 的偏移量是正确的:
glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 2 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 18*sizeof(float), 3 * sizeof(float));
在情况 B 中有 9 个顶点坐标,后跟 3 个颜色属性。一个顶点元组有 w 个分量,一个颜色元组有 3 个分量:
(x1, y1, x2, y2, ... x9, y9, r1, g1, b1, r2, g2, b2, ..., r9, g9, b9)
因此颜色属性开始的偏移量是9*sizeof(float)
(3 * (x, y)):
glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 2 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 18 * sizeof(float), 3 * sizeof(float));
x1的字节偏移量为0
.
r1的字节偏移量为18 * sizeof(float)
.
从 x1 到 x2 的字节距离是 2 * sizeof(float)
.
从 r1 到 r2 的字节距离是 3 * sizeof(float)
。
我正在尝试通过直接状态访问使我的 OpenGL 代码跟上速度,并且一直在密切关注 Guide to Modern OpenGL Functions 中的代码。我有一个带有一些顶点和颜色的小测试项目:
std::vector<float> vertices;
for (float y = -1.0f; y < 1.1f; y += 1.0f) {
for (float x = -1.0f; x < 1.1f; x += 1.0f) {
vertices.emplace_back(x);
vertices.emplace_back(y);
vertices.emplace_back(0.5f);
vertices.emplace_back(0.5f);
vertices.emplace_back(0.5f);
}
}
这些顶点及其索引的可视化表示:
我的主要绘制代码是这样的:
unsigned int vbo = 0;
glCreateBuffers(1, &vbo);
glNamedBufferStorage(vbo, sizeof(float) * vertices.size(), vertices.data(), GL_DYNAMIC_STORAGE_BIT);
// Indices
unsigned int indices[]{ 0,1,3,5,8,7 };
unsigned int ibo = 0;
glCreateBuffers(1, &ibo);
glNamedBufferStorage(ibo, sizeof(unsigned int) * 6, indices, GL_DYNAMIC_STORAGE_BIT);
int bindingindex_a = 1;
int bindingindex_b = 2;
int pos_location = 3;
int color_location = 4;
unsigned int vao = 0;
glCreateVertexArrays(1, &vao);
glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 5 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 0, 5 * sizeof(float));
glVertexArrayElementBuffer(vao, ibo);
glEnableVertexArrayAttrib(vao, pos_location);
glEnableVertexArrayAttrib(vao, color_location);
glVertexArrayAttribFormat(vao, pos_location, 2, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribFormat(vao, color_location, 3, GL_FLOAT, GL_FALSE, 2*sizeof(float));
glVertexArrayAttribBinding(vao, pos_location, bindingindex_a);
glVertexArrayAttribBinding(vao, color_location, bindingindex_b);
所以我绘制了两个灰色三角形,索引分别为 0、1、3 和 5、8、7。我的着色器中的属性位置在 cpp 代码中指定:
layout (location = 3) in vec2 pos;
layout (location = 4) in vec3 col;
这有效!:
甚至当我增加难度并在前面添加单个浮点值时,我可以将 glVertexArrayVertexBuffer()
函数中的偏移量调整 4 个字节。
问题是当我想从缓冲区布局 A 转到 B 时:
我调整我的数据填充循环以先写位置,然后是颜色:
for (float y = -1.0f; y < 1.1f; y += 1.0f) {
for (float x = -1.0f; x < 1.1f; x += 1.0f) {
vertices.emplace_back(x);
vertices.emplace_back(y);
}
}
for (float y = -1.0f; y < 1.1f; y += 1.0f) {
for (float x = -1.0f; x < 1.1f; x += 1.0f) {
vertices.emplace_back(0.5f);
vertices.emplace_back(0.5f);
vertices.emplace_back(0.5f);
}
}
并将调用调整为 glVertexArrayVertexBuffer()
和 glVertexArrayAttribFormat()
:
glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 2 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 18*sizeof(float), 3 * sizeof(float));
glVertexArrayAttribFormat(vao, pos_location, 2, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribFormat(vao, color_location, 3, GL_FLOAT, GL_FALSE, 0);
所以现在我的全局颜色偏移量为 18 个浮点数(9 个位置乘以两个分量),我的 relativeoffset
(khronos.org 就是这样称呼它的)两者都为 0。这显示灰色的东西,但不是他们以前做的方式。我对这些东西如何运作的心智模型显然是错误的 - 哪里?
offset 参数 glVertexArrayVertexBuffer
是缓冲区第一个元素的字节偏移量,形成缓冲区的开始和 stride 是缓冲区内连续属性之间的距离。
情况 A 的顶点规范错误:
glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 5 * sizeof(float)); glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 0, 5 * sizeof(float));
每个顶点属性元组由 5 个分量(x、y、r、g、b)组成。
(x1, y1, r1, g1, b1, x2, y2, r2, g2, b2, x3, y3, r3, g3, b3, ...)
因此颜色属性的偏移量是2*sizeof(float)
:
glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 5 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 2 * sizeof(float), 5 * sizeof(float));
x1的字节偏移量为0
.
r1的字节偏移量为2 * sizeof(float)
.
从 x1 到 x2 的字节距离是 5 * sizeof(float)
.
从 r1 到 r2 的字节距离是 5 * sizeof(float)
.
案例 B 的偏移量是正确的:
glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 2 * sizeof(float)); glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 18*sizeof(float), 3 * sizeof(float));
在情况 B 中有 9 个顶点坐标,后跟 3 个颜色属性。一个顶点元组有 w 个分量,一个颜色元组有 3 个分量:
(x1, y1, x2, y2, ... x9, y9, r1, g1, b1, r2, g2, b2, ..., r9, g9, b9)
因此颜色属性开始的偏移量是9*sizeof(float)
(3 * (x, y)):
glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 2 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 18 * sizeof(float), 3 * sizeof(float));
x1的字节偏移量为0
.
r1的字节偏移量为18 * sizeof(float)
.
从 x1 到 x2 的字节距离是 2 * sizeof(float)
.
从 r1 到 r2 的字节距离是 3 * sizeof(float)
。