在不同的缓冲区布局中遇到glVertexArrayVertexBuffer()/ glVertexArrayAttribFormat()的问题

问题描述 投票:1回答:1

我正在尝试通过直接状态访问来加快我的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);
    }
}

这些顶点及其索引的视觉表示:

enter image description here

我的主要绘画代码是这样的:

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;

这可行!:

enter image description here

即使增加难度并在前面添加单个浮点值,我也可以将glVertexArrayVertexBuffer()函数中的偏移量调整4个字节。

问题是当我想从缓冲区布局A转到B:

enter image description here

我调整数据填充循环以首先写位置,然后写颜色:

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。这会显示灰色的东西,但不会显示以前的样子。我关于这些事物如何运作的思维模式显然是错误的-在哪里?

c++ opengl opengl-4
1个回答
1
投票

glVertexArrayVertexBufferoffset参数是缓冲区的第一个元素的偏移量,以字节为单位,形成缓冲区的开头,而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)); 。从x1x2以及从r1r2的字节距离为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)); 。从x1x2 6 * sizeof(float)的字节距离,从r1r2的字节距离是2 * sizeof(float)

© www.soinside.com 2019 - 2024. All rights reserved.