在不同的 VBO 中存储不同的顶点属性

2021-12-19 00:00:00 opengl c++ vbo

是否可以在不同的顶点缓冲区中存储不同的顶点属性?

Is it possible to store different vertex attributes in different vertex buffers?

到目前为止我看到的所有例子都是这样的

All the examples I've seen so far do something like this

float data[] = 
{
//position
   v1x, v1y, v1z,
   v2x, v2y, v2z,
   ...
   vnx, vny, vnz,

//color
   c1r, c1g, c1b,
   c2r, c2g, c2b,
   ...
   cnr, cng, cnb,   
};
GLuint buffname;
glGenBuffers(1, &buffname);
glBindBuffer(GL_ARRAY_BUFFER, buffname);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);

绘图是这样完成的:

glBindBuffer(GL_ARRAY_BUFFER, buffname);
glEnableVertexAttrib(position_location);
glEnableVertexAttrib(color_location);
glVertexAttribPointer(position_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(color_location, 3, GL_FLOAT, GL_FALSE, 0, (void*)(3*n));

glDrawArrays(GL_TRIANGLES, 0, n/3);

glDisableVertexAttrib(position_location);
glDisableVertexAttrib(color_location);
glBindBuffer(GL_ARRAY_BUFFER, 0);

不能在不同的 VBO 中存储位置数据和颜色数据吗?问题是我不明白这是怎么回事,因为你不能同时绑定两个缓冲区,对吗?

Isn't it possible to store position data and color data in different VBOs? The problem is I don't understand how this would work out because you can't bind two buffers at once, can you?

如果有一个简单但效率低下的解决方案,我更喜欢它而不是一个更复杂但更有效的解决方案,因为我处于初级学习状态,我不想把事情复杂化.

If there is a simple but inefficient solution, I would prefer it over a more complicated but efficient solution because I am in primary learning state and I don't want to complicate things too much.

另外,如果我问的是可能的,这是否是一个好主意?

Also, if what I'm asking is possible, is it a good idea or not?

澄清:我确实了解如何在不同的 VBO 中存储不同的属性.我不明白我以后会怎么画它们.

To clarify: I do understand how I could store different attributes in different VBO's. I don't understand how I would later draw them.

推荐答案

属性位置 X 和提供该属性的缓冲区对象之间的关联是使用 glVertexAttribPointer 命令建立的.它的工作方式很简单,但不直观.

The association between attribute location X and the buffer object that provides that attribute is made with the glVertexAttribPointer command. The way it works is simple, but unintuitive.

在调用 glVertexAttribPointer 时(这是很多人没有得到的部分),当前绑定到 GL_ARRAY_BUFFER 的任何缓冲区对象code> 与属性 X 相关联,其中 X 是 glVertexAttribPointer 的第一个参数.

At the time glVertexAttribPointer is called (that's the part a lot of people don't get), whatever buffer object is currently bound to GL_ARRAY_BUFFER becomes associated with the attribute X, where X is the first parameter of glVertexAttribPointer.

因此,如果您想要一个来自一个缓冲区的属性和一个来自另一个缓冲区的属性,您可以这样做:

So if you want to have an attribute that comes from one buffer and an attribute that comes from another, you do this:

glEnableVertexAttrib(position_location);
glEnableVertexAttrib(color_location);
glBindBuffer(GL_ARRAY_BUFFER, buffPosition);
glVertexAttribPointer(position_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, buffColor);
glVertexAttribPointer(color_location, 3, GL_FLOAT, GL_FALSE, 0, 0);

<小时>

至于是否应该将属性拆分到不同的缓冲区...我会说只有在您有可证明的需求时才应该这样做.

例如,假设您正在制作动态高度图,可能是为了某种水效果.每个元素的 Z 位置发生变化,但这也意味着法线发生变化.但是,XY 位置和纹理坐标不会改变.

For example, let's say you're doing a dynamic height-map, perhaps for some kind of water effect. The Z position of each element changes, but this also means that the normals change. However, the XY positions and the texture coordinates do not change.

高效的流媒体通常需要双缓冲缓冲区对象或使它们无效(使用 glBufferData(NULL) 或 glMapBufferRange(GL_INVALIDATE_BIT) 重新分配它们).任何一种方法都只有在流数据位于非流数据的另一个缓冲区对象中时才有效.

Efficient streaming often requires either double-buffering buffer objects or invalidating them (reallocating them with a glBufferData(NULL) or glMapBufferRange(GL_INVALIDATE_BIT)). Either way only works if the streamed data is in another buffer object from the non-streamed data.

另一个可证明需求的例子是,如果内存是一个问题并且多个对象共享某些属性列表.也许对象具有不同的位置和法线数组,但具有相同的颜色和纹理坐标数组.或者类似的东西.

Another example of a demonstrable need is if memory is a concern and several objects share certain attribute lists. Perhaps objects have different position and normal arrays but the same color and texture coordinate arrays. Or something like that.

但除此之外,最好将对象的所有内容都放入一个缓冲区中.即使你不交错数组.

But otherwise, it's best to just put everything for an object into one buffer. Even if you don't interleave the arrays.

相关文章