OpenGL 在绘制一个网格时绑定多个纹理
OpenGL binding many textures while drawing the one mesh
我想在一个网格上绑定例如 80 个纹理并将其放入我的 VBO 中。
我怎样才能做到这一点?
我读过 glActiveTexture 能够做到这一点,但它最多允许大约 32 个纹理(取决于 GPU)。
我的 VBO 代码:
//Generating VBO
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Vector3d) + textureCoords.size()*sizeof(Vector2d), 0, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size()*sizeof(Vector3d), vertices.data());
glBufferSubData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Vector3d), textureCoords.size()*sizeof(Vector2d), textureCoords.data());
glGenBuffers(1, &IND);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IND);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
//Drawing VBO:
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexPointer(3, GL_DOUBLE, 0, 0);
glTexCoordPointer(2, GL_DOUBLE, 0, (void*)(vertices.size()*sizeof(Vector3d)));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IND);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (void*)0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
绑定许多(数百个)纹理
我不确定有什么方法可以同时绑定那么多单独的纹理。如果您的许多纹理大小相同,则有 bindless textures but I don't have much experience with that extension. You could also use an array texture。但解决这个问题的标准方法是使用 纹理图集 ,将大量纹理打包到一个中,记录它们的放置位置并调整纹理坐标以匹配。
更新:您还可以使用许多纹理数组来存储纹理图集(参见评论和 )。
将多个纹理应用于网格
How will I tell the VBO, what faces will have which texture?
我认为一个更紧迫的问题是如何将不同的纹理(或 materials)应用到同一个网格。有几件事需要考虑...
应用多个纹理的最常见情况是每个存储不同的 material 属性,但它们都使用相同的纹理坐标/“UV”。例如。漫反射贴图、法线贴图、高光贴图。我想在极端情况下,当你有 100 个不同的属性时,你需要一个数组纹理。
如果每个纹理需要以不同方式映射,则每个纹理都有一个单独的每个顶点纹理坐标 VBO。然后您必须决定纹理在应用时如何相互作用或混合。
你的每张脸 materials/texture 完全分开。通常网格上只有几个 material。您呈现它的方式是在单独的批次中,按 material 分组。绑定正确的纹理,设置着色器制服,绘制三角形索引 A 到 B.
如果几乎每一张脸都有不同的material。我想如果你正在绘制一个包含许多不同方块的基于方块的游戏,可能就是这种情况。
这里的问题是绘制调用的数量成为瓶颈,
所以你必须将不同的 material 组合到同一个绘图调用中。
您可以通过在顶点属性上存储 material 来做到这一点,例如添加顶点颜色 VBO。
不仅仅是颜色,您还可以存储每个顶点的纹理 ID,如果您使用的是纹理图集,则可以在图集中找到纹理的区域。
这开始变得低效,因为您将在三角形的每个顶点上多次存储相同的 material 数据。
为了最小化开销,您可以 为每个顶点存储一个 material 索引 ,它指向在 table 某处定义的 material(或者在小的统一数组,或者如果你需要更多 materials,另一个纹理)。
然后在table.
中的material添加纹理ID和图集区域
希望最后一点能回答您的问题。
老实说,如果一个网格有超过 32 个纹理,那么您遇到的问题可能比绑定问题大得多。但是如果你坚持要有那么多纹理,你有两个选择:无绑定或纹理数组。但是,也有缺点: Bindless 会限制您的硬件支持。纹理数组确实要求纹理具有相同的大小和格式。我个人认为 Texture Array 是一个可行的解决方案。如果可能,您可以尝试调整纹理的大小,然后将具有相同大小和格式的纹理分组到一个数组中。现在,您有 32 个数组可以使用,这应该绰绰有余,例如一个数组用于所有反照率纹理,一个用于所有法线贴图等。关于调整大小,考虑将纹理缩放到您拥有的最大尺寸,或者可能分成几类,例如小号中号大号。避免任意大小。
我想在一个网格上绑定例如 80 个纹理并将其放入我的 VBO 中。 我怎样才能做到这一点?
我读过 glActiveTexture 能够做到这一点,但它最多允许大约 32 个纹理(取决于 GPU)。
我的 VBO 代码:
//Generating VBO
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Vector3d) + textureCoords.size()*sizeof(Vector2d), 0, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size()*sizeof(Vector3d), vertices.data());
glBufferSubData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Vector3d), textureCoords.size()*sizeof(Vector2d), textureCoords.data());
glGenBuffers(1, &IND);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IND);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
//Drawing VBO:
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexPointer(3, GL_DOUBLE, 0, 0);
glTexCoordPointer(2, GL_DOUBLE, 0, (void*)(vertices.size()*sizeof(Vector3d)));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IND);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (void*)0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
绑定许多(数百个)纹理
我不确定有什么方法可以同时绑定那么多单独的纹理。如果您的许多纹理大小相同,则有 bindless textures but I don't have much experience with that extension. You could also use an array texture。但解决这个问题的标准方法是使用 纹理图集 ,将大量纹理打包到一个中,记录它们的放置位置并调整纹理坐标以匹配。
更新:您还可以使用许多纹理数组来存储纹理图集(参见评论和
将多个纹理应用于网格
How will I tell the VBO, what faces will have which texture?
我认为一个更紧迫的问题是如何将不同的纹理(或 materials)应用到同一个网格。有几件事需要考虑...
应用多个纹理的最常见情况是每个存储不同的 material 属性,但它们都使用相同的纹理坐标/“UV”。例如。漫反射贴图、法线贴图、高光贴图。我想在极端情况下,当你有 100 个不同的属性时,你需要一个数组纹理。
如果每个纹理需要以不同方式映射,则每个纹理都有一个单独的每个顶点纹理坐标 VBO。然后您必须决定纹理在应用时如何相互作用或混合。
你的每张脸 materials/texture 完全分开。通常网格上只有几个 material。您呈现它的方式是在单独的批次中,按 material 分组。绑定正确的纹理,设置着色器制服,绘制三角形索引 A 到 B.
如果几乎每一张脸都有不同的material。我想如果你正在绘制一个包含许多不同方块的基于方块的游戏,可能就是这种情况。 这里的问题是绘制调用的数量成为瓶颈, 所以你必须将不同的 material 组合到同一个绘图调用中。 您可以通过在顶点属性上存储 material 来做到这一点,例如添加顶点颜色 VBO。 不仅仅是颜色,您还可以存储每个顶点的纹理 ID,如果您使用的是纹理图集,则可以在图集中找到纹理的区域。 这开始变得低效,因为您将在三角形的每个顶点上多次存储相同的 material 数据。 为了最小化开销,您可以 为每个顶点存储一个 material 索引 ,它指向在 table 某处定义的 material(或者在小的统一数组,或者如果你需要更多 materials,另一个纹理)。 然后在table.
中的material添加纹理ID和图集区域希望最后一点能回答您的问题。
老实说,如果一个网格有超过 32 个纹理,那么您遇到的问题可能比绑定问题大得多。但是如果你坚持要有那么多纹理,你有两个选择:无绑定或纹理数组。但是,也有缺点: Bindless 会限制您的硬件支持。纹理数组确实要求纹理具有相同的大小和格式。我个人认为 Texture Array 是一个可行的解决方案。如果可能,您可以尝试调整纹理的大小,然后将具有相同大小和格式的纹理分组到一个数组中。现在,您有 32 个数组可以使用,这应该绰绰有余,例如一个数组用于所有反照率纹理,一个用于所有法线贴图等。关于调整大小,考虑将纹理缩放到您拥有的最大尺寸,或者可能分成几类,例如小号中号大号。避免任意大小。