我正在尝试通过直接状态访问来加快我的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。这会显示灰色的东西,但不会显示以前的样子。我关于这些事物如何运作的思维模式显然是错误的-在哪里?
glVertexArrayVertexBuffer
的offset参数是缓冲区的第一个元素的偏移量,以字节为单位,形成缓冲区的开头,而stride是缓冲区内连续属性之间的距离。
案例A的顶点规范是错误的:
glVertexArrayVertexBuffer
每个顶点属性元组包含5个成分(x,y,r,g,b)。
glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 5 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 0, 5 * sizeof(float));
因此,颜色属性的偏移量为(x1, y1, r1, g1, b1, x2, y2, r2, g2, b2, x3, y3, r3, g3, b3)
:
2*sizeof(float)
x1的字节偏移为0,r1的字节偏移为glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 5 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 2 * sizeof(float), 5 * sizeof(float));
。从x1到x2以及从r1到r2的字节距离为2 * sizeof(float)
。
情况B的偏移量也是错误的。
5 * sizeof(float)
在情况B中,有3个顶点坐标,后跟3个颜色属性。顶点元组具有w个分量,颜色元组具有3个分量:
glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 2 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 18*sizeof(float), 3 * sizeof(float));
因此,颜色属性的起始位置为(x1, y1, x2, y2, x3, y3, r1, g1, b1, r2, g2, b2, r3, g3, b3)
(3 *(x,y)):
6*sizeof(float)
x1的字节偏移为0,r1的字节偏移为glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 2 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 6 * sizeof(float), 3 * sizeof(float));
。从x1到x2 6 * sizeof(float)
的字节距离,从r1到r2的字节距离是2 * sizeof(float)
。