OpenGL glDrawElements在拆分为多个绘制调用时出现问题

rbl8hiat  于 2024-01-07  发布在  其他
关注(0)|答案(1)|浏览(239)

我尝试将缓冲区分割成几个“范围”/子网格,每个子网格应用不同的材质(我的对象是一个导入的.obj文件,一组面共享一个材质)。对整个缓冲区使用glDrawElements调用绘制完整的对象,但子网格之间的纹理不会改变:

  1. glDrawElements(
  2. GL_TRIANGLES, // mode
  3. element_size, // count of indices
  4. GL_UNSIGNED_SHORT, // type
  5. NULL // element array buffer offset
  6. );

字符串
结果,左边的电脑和沙发仍然使用砖纹理:
x1c 0d1x的数据
如果我尝试对每个材质发出drawcall,如下所示:

  1. for (const auto& [id, mat]: materials_textures) {
  2. // Send material properties to the shader
  3. // Omitted a sequence of glUniformX(...)
  4. // Bind material's textures - omitted
  5. // old non-indexed drawcall that worked - glDrawArrays(GL_TRIANGLES, mat.start_idx, mat.size);
  6. glDrawElementsBaseVertex(
  7. GL_TRIANGLES, // mode
  8. mat.size,
  9. GL_UNSIGNED_SHORT, // type
  10. NULL,
  11. mat.start_idx
  12. );
  13. std::cout << element_size << " mat.start_idx: " << mat.start_idx << " mat.size: " << mat.size << std::endl;
  14. }


我只画了一部分物体(注意,眼镜也缺少了上图右上角的不透明固体透镜):

drawcall可以被替换为没有效果:

  1. glDrawElements(
  2. GL_TRIANGLES, // mode
  3. mat.size,
  4. GL_UNSIGNED_SHORT, // type
  5. (void*)(mat.start_idx)
  6. );


使用该按钮阅读:

  1. 690 mat.start_idx: 0 mat.size: 330
  2. 690 mat.start_idx: 456 mat.size: 174
  3. 690 mat.start_idx: 330 mat.size: 90
  4. 690 mat.start_idx: 630 mat.size: 60
  5. 690 mat.start_idx: 420 mat.size: 36


所以缓冲区的整个范围应该被随后的绘制调用覆盖。
我知道一个可能的解决方案是将这些子网格分割到单独的.obj文件中,但是我是否遗漏了一些简单的东西来将这些子网格保存在一个文件中,同时应用不同的材质?

s1ag04yj

s1ag04yj1#

glDrawElements的最后一个参数不是起始索引号,而是第一个索引的字节偏移量。由于您使用GL_UNSIGNED_SHORT索引,因此每个索引为2个字节。
顺便说一下,OpenGL不关心你的obj文件,甚至不知道它们的存在,所以它不关心你所有的数据是在一个文件还是几个文件中。你的程序是处理文件的那个。

相关问题