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的使用,最基本的兩個步驟是:
- 初始化OpenGL上下文:上下文環境用於記錄所有OpenGL相關的狀態,位於操作系統的某一個進程中,每個進程可以擁有多個上下文,每個上下文可以描述系統中的一個窗口。簡單的說,就是在當前操作系統中創建一個窗口。
- 定位所有需要使用的OpenGL函數:因爲OpenGL只是一個標準,具體的實現由顯卡驅動廠商實現,但OpenGL驅動版本居多,無法在編譯時制定。這個工作就只能轉移到運行時,由開發者指定了。GLEW的作用就是在運行時,獲取顯卡驅動支持的函數,保存在對應的函數指針中供運行時調用。
所以,對應上述兩個步驟,我們應該分別執行:
glfwInit
:以創建上下文。glewInit
:以加載系統OpenGL函數。
所以,本次未捕獲異常只需要在執行任何OpenGL函數調用之前,調用glewInit
即可。