调用glDrawElements

时间:2017-01-04 06:30:17

标签: c++ macos opengl segmentation-fault

我有一个我在macOS上开发的OpenGL应用程序。我在代码中调用了glDrawElements段错误。我链接OpenGL.framework文件并添加<OpenGL/gl.h>。但是,如果我包含<OpenGL/gl3.h>,程序不会出现段错误,并且它或多或少会按预期工作(我仍然会收到无效的操作调用,但网格会绘制到屏幕上)。这是扩展加载问题吗?我没有使用GLEW或任何扩展加载库。我正在创建一个2.1版本的上下文。

Here是我设置OpenGL数据的地方,here是我实际绘图的地方。我还要注意,这在Linux机器上运行并没有问题。它似乎只是macOS我遇到了段错误。

这是堆栈跟踪:

(lldb) bt
* thread #1: tid = 0x206bb7, 0x00007fff92a330d0 libsystem_platform.dylib`_platform_memmove$VARIANT$Nehalem + 112, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
  * frame #0: 0x00007fff92a330d0 libsystem_platform.dylib`_platform_memmove$VARIANT$Nehalem + 112
    frame #1: 0x00007fff78853c86 GeForceGLDriver`___lldb_unnamed_symbol5651$$GeForceGLDriver + 187
    frame #2: 0x00007fff78855102 GeForceGLDriver`___lldb_unnamed_symbol5659$$GeForceGLDriver + 771
    frame #3: 0x00007fff789710fe GeForceGLDriver`___lldb_unnamed_symbol10497$$GeForceGLDriver + 393
    frame #4: 0x00007fff8227a15f GLEngine`glDrawElements_Exec + 271
    frame #5: 0x0000000100030fb4 mcomp`GLRender::DrawModel(this=0x00007fff5fbff7f8, model=0x0000000100770e20) + 5956 at glrender.cc:202
    frame #6: 0x0000000100003fa7 mcomp`Mcomp::Update(this=0x00007fff5fbff7b8) + 423 at mcomp.cc:27
    frame #7: 0x0000000100007941 mcomp`Engine::Run(this=0x00007fff5fbff798) + 65 at engine.cc:22
    frame #8: 0x00000001000026ea mcomp`main(argc=1, argv=0x00007fff5fbffa00) + 378 at main.cc:21
    frame #9: 0x00007fff92826255 libdyld.dylib`start + 1
(lldb) 

1 个答案:

答案 0 :(得分:2)

我在这里看到了一些错误。

  • 当你拥有一个顶点属性应该从中提取数据的缓冲区对象时,必须调用glVertexAttribPointer()。我建议首先设置和配置顶点缓冲区(包括顶点属性),然后单独继续执行索引缓冲区。您目前正在混合和匹配它们。
  • 您可能需要在调用glVertexAttribPointer()之后调用glEnableVertexAttribArray(),但我不完全记得标准是否需要这个。
  • “顶点数组对象”会跟踪您设置的顶点属性。反过来,顶点属性会记住它们从哪个缓冲区对象中提取数据。因此,在绘制时不需要显式绑定缓冲区对象。
  • 当你设置的缓冲区对象太小,你试图绘制比你的索引缓冲区更多的索引,或者你的步幅关闭时,你通常会在调用glDrawElements()时遇到分段错误。因此,可以确保所有长度,尺寸等对您有意义。当你的索引缓冲区引用越界值时也可能发生这种情况,但如果我没记错的话,这可能取决于如何处理这个问题的实现。

作为参考,以下是我通常设置VAO的顺序:

  1. 创建VAO
  2. 绑定VAO
  3. 创建缓冲区(顶点)
  4. 绑定缓冲区
  5. 使用几何数据填充缓冲区
  6. 设置相关的顶点属性指针
  7. 启用顶点属性指针
  8. 创建缓冲区(索引)
  9. 绑定缓冲区
  10. 使用索引填充缓冲区
  11. 这应该设置一切。要绘制,使用相关的着色器程序,绑定VAO并调用glDrawElements()

    编辑:您能概述为什么要创建2.x上下文,而不是3.x或4.x上下文?使用缓冲区绘制和VAO是现代OpenGL渲染方式。为什么不将上下文版本与该级别匹配?