【发布时间】:2020-02-22 14:27:29
【问题描述】:
我关注了this tutorial,并能够在屏幕上绘制 20 个三角形。但是,在该示例中,位置和颜色数据都存储在单个数组中,并作为单个 glBufferSubData 调用传递。我不确定我是否应该始终遵循这种方法或创建单独的数组来存储顶点属性并为每个属性调用glBufferSubData。我试图分别存储位置和颜色并遇到一个奇怪的问题。而不是在屏幕上绘制 20 个三角形,我只得到了 10 个!
[我使用 glfw 而不是 Qt 来创建窗口。]
方法一:
我定义的全局变量如下:
float dx = 0.1f;
unsigned int triangleCount = 0;
const unsigned int TRIANGLE_MAX_COUNT = 20;
const unsigned int TRIANGLE_VERTEX_COUNT = 3;
const unsigned int VERTEX_FLOAT_COUNT = 8;
const unsigned int TRIANGLE_BYTE_SIZE = TRIANGLE_VERTEX_COUNT * VERTEX_FLOAT_COUNT * sizeof(float);
我的三角形绘制函数定义为
void sendAnotherTriangle()
{
if (triangleCount == TRIANGLE_MAX_COUNT)
return;
const float x = -1 + triangleCount * dx;
glm::vec4 newTriangle[] = {
glm::vec4(x, +0.0f, +0.0f,1.0f),
glm::vec4(+1.0f, +0.0f, +0.0f,1.0f),
glm::vec4(x + dx, +1.0f, +0.0f,1.0f),
glm::vec4(+1.0f, +0.0f, +0.0f,1.0f),
glm::vec4(x, +1.0f, +0.0f,1.0f),
glm::vec4(+1.0f, +0.0f, +0.0f,1.0f)
};
glBufferSubData(GL_ARRAY_BUFFER, triangleCount * sizeof(newTriangle), sizeof(newTriangle), newTriangle);
triangleCount++;
}
顶点缓冲区布局定义如下:
unsigned int vb;
glGenBuffers(1, &vb);
glBindBuffer(GL_ARRAY_BUFFER, vb);
glBufferData(GL_ARRAY_BUFFER, TRIANGLE_MAX_COUNT*TRIANGLE_BYTE_SIZE, NULL, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, glm::vec4::length(), GL_FLOAT, GL_FALSE, 2 * sizeof(glm::vec4), (const void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, glm::vec4::length(), GL_FLOAT, GL_FALSE, 2 * sizeof(glm::vec4), (const void*)(sizeof(glm::vec4)));
根据我的理解,由于位置和颜色属性是交错的,因此这两个属性的步幅都是:2 * sizeof(glm::vec4),因为每个属性的类型都是 glm::vec4。由于位置数据从最开始开始,因此位置偏移量为 0,而颜色偏移量为 sizeof(glm::vec4),因为它从第一个顶点位置开始。
最后,绘图调用如下所示:
while (display.isRunning(window))
{
glClear(GL_DEPTH_BUFFER_BIT);
sendAnotherTriangle();
glDrawArrays(GL_TRIANGLES, 0, triangleCount * TRIANGLE_VERTEX_COUNT);
display.update();
}
这给了我想要的结果,即在屏幕上绘制了 20 个红色三角形。
方法2:
之后,我尝试使用多个 glBufferSubData 调用来做同样的事情。在这种方法中,修改后的三角形绘制函数为:
void sendAnotherTriangle()
{
if (triangleCount == TRIANGLE_MAX_COUNT)
return;
const float x = -1 + triangleCount * dx;
glm::vec4 newPositions[] = {
glm::vec4(x, +0.0f, +0.0f, +1.0f),
glm::vec4(x + dx, +1.0f, +0.0f, +1.0f),
glm::vec4(x, +1.0f, +0.0f, +1.0f)
};
glm::vec4 newColors[] = {
glm::vec4(+1.0f, +0.0f, +0.0f, +1.0f),
glm::vec4(+1.0f, +0.0f, +0.0f, +1.0f),
glm::vec4(+1.0f, +0.0f, +0.0f, +1.0f)
};
glBufferSubData(GL_ARRAY_BUFFER, triangleCount*(sizeof(newPositions) + sizeof(newColors)), sizeof(newPositions), newPositions);
glBufferSubData(GL_ARRAY_BUFFER, triangleCount*(sizeof(newPositions) + sizeof(newColors)) + sizeof(newPositions), sizeof(newColors), newColors);
triangleCount++;
}
并且顶点缓冲布局修改如下:
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, glm::vec4::length(), GL_FLOAT, GL_FALSE, 0, (const void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, glm::vec4::length(), GL_FLOAT, GL_FALSE, 0, (const void*)(TRIANGLE_VERTEX_COUNT * sizeof(glm::vec4)));
由于位置和颜色数据是分开存储的,我的理解是它们是紧密打包的,因此它们的步幅为 0,并且由于颜色数据在位置数据之后开始,所以颜色偏移量是 TRIANGLE_VERTEX_COUNT * sizeof(glm:: vec4).
使用这个新设置,我希望在屏幕上绘制 20 个三角形。但是,我只在屏幕上绘制了 10 个三角形。我猜这是由于为步幅和偏移量分配了不正确的值。但是,我想不通。
因此,我想先问一下哪种方法更好,更安全。
其次,按照第二种方法,我怎样才能得到想要的结果?
【问题讨论】: