Mac OpenGL的坑

OpenGL使用Bug

系統:MacOS 10.13.6
openGL 版本: 4.1 ATI-1.68.21
opengl 函數管理庫:glew2.1.0
opengl 窗口庫:glfw3.3
IDE:CLion 2018.1

編譯時openGL 相關函數找不到

報錯日誌:

Undefined symbols for architecture x86_64:
  "_glClear", referenced from:
      _main in main.cpp.o
  "_glClearColor", referenced from:
      _main in main.cpp.o
  "_glGetString", referenced from:
      _main in main.cpp.o
  "_glViewport", referenced from:
      framebuffer_size_callback(GLFWwindow*, int, int) in main.cpp.o

報錯的原因是代碼中所有涉及到opengl函數調用的地方,都不被x86_64架構系統識別,這點在日誌中寫的很明白。
原因和解決方案:
學習的時候,代碼參考網絡博客,CMakeLists.txt文件如下:

cmake_minimum_required(VERSION 3.10)
project(OpenGL)

# 添加頭文件
set(CMAKE_CXX_STANDARD 11)
set(GLFW_H /usr/local/Cellar/glfw/3.3/include/GLFW)
set(GLEW_H /usr/local/Cellar/glew/2.1.0/include/GL)
include_directories(${GLFW_H} ${GLEW_H})

# 添加目標鏈接
set(GLFW_LINK /usr/local/Cellar/glfw/3.3/lib/libglfw.3.3.dylib)
set(GLEW_LINK /usr/local/Cellar/glew/2.1.0/lib/libGLEW.2.1.0.dylib)
link_libraries(${OPENGL} ${GLFW_LINK} ${GLEW_LINK})

# 執行編譯命令
set(SOURCE_FILES main.cpp)
add_executable(OpenGL ${SOURCE_FILES})

其中${OPENGL}原本應該將系統的OpenGL相關庫鏈接到項目中的,但這個寫法可能在當前環境不支持。將這種寫法換成"-framework OpenGL"即可。
替換後,完整的CMakeLists.txt文件如下:

cmake_minimum_required(VERSION 3.10)
project(OpenGL)

# 添加頭文件
set(CMAKE_CXX_STANDARD 11)
set(GLFW_H /usr/local/Cellar/glfw/3.3/include/GLFW)
set(GLEW_H /usr/local/Cellar/glew/2.1.0/include/GL)
include_directories(${GLFW_H} ${GLEW_H})

# 添加目標鏈接
set(GLFW_LINK /usr/local/Cellar/glfw/3.3/lib/libglfw.3.3.dylib)
set(GLEW_LINK /usr/local/Cellar/glew/2.1.0/lib/libGLEW.2.1.0.dylib)
link_libraries("-framework OpenGL" ${GLFW_LINK} ${GLEW_LINK})

# 執行編譯命令
set(SOURCE_FILES main.cpp)
add_executable(OpenGL ${SOURCE_FILES})

運行時EXC_BAD_ACCESS

報錯日誌:

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Segmentation fault: 11
Termination Reason:    Namespace SIGNAL, Code 0xb
Terminating Process:   exc handler [0]

VM Regions Near 0:
--> 
    __TEXT                 00000001026c2000-00000001026c5000 [   12K] r-x/rwx SM=COW  
 [/Users/**/CLionProjects/OpenGL/cmake-build-debug/OpenGL]

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   ???                           	000000000000000000 0 + 0
1   OpenGL                        	0x00000001026c3d71 main + 465 (main.cpp:55)
2   libdyld.dylib                 	0x00007fff7efbd015 start + 1

main.cpp:55 這行的代碼是:

unsigned int VBO;
glGenBuffers(1, &VBO); // main.cpp:55

原因和解決方案:

出現問題的客觀原因是:在跟隨教程你好,三角形練習時,教程中的代碼並不完成適用於當前場景,可能是系統方面的原因。直接原因:教程的代碼中,沒有執行glewInit()函數,造成隨後調用的OpenGL函數無法正確的找到對應函數,從而導致段錯誤。

來看看GLEW的官方解釋:

The OpenGL Extension Wrangler Library (GLEW) is a cross-platform open-source C/C++ extension loading library. GLEW provides efficient run-time mechanisms for determining which OpenGL extensions are supported on the target platform. OpenGL core and extension functionality is exposed in a single header file. GLEW has been tested on a variety of operating systems, including Windows, Linux, Mac OS X, FreeBSD, Irix, and Solaris.

OpenGL的使用,最基本的兩個步驟是:

  1. 初始化OpenGL上下文:上下文環境用於記錄所有OpenGL相關的狀態,位於操作系統的某一個進程中,每個進程可以擁有多個上下文,每個上下文可以描述系統中的一個窗口。簡單的說,就是在當前操作系統中創建一個窗口。
  2. 定位所有需要使用的OpenGL函數:因爲OpenGL只是一個標準,具體的實現由顯卡驅動廠商實現,但OpenGL驅動版本居多,無法在編譯時制定。這個工作就只能轉移到運行時,由開發者指定了。GLEW的作用就是在運行時,獲取顯卡驅動支持的函數,保存在對應的函數指針中供運行時調用。

所以,對應上述兩個步驟,我們應該分別執行:

  1. glfwInit:以創建上下文。
  2. glewInit:以加載系統OpenGL函數。

所以,本次未捕獲異常只需要在執行任何OpenGL函數調用之前,調用glewInit即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章