前言
- OpenGL 是什么?The Industry Standard for High Performance Graphics 這是官方解釋。說白了他就是一套標(biāo)準(zhǔn)接口。對(duì),是接口,并沒有實(shí)現(xiàn)具體的代碼。
- GLFW 是什么?在我們畫出任何效果之前,首先要做的就是創(chuàng)建一個(gè)OpenGL上下文和一個(gè)用于顯示的窗口。然而,這些操作在每個(gè)系統(tǒng)上都是不一樣的,OpenGL有目的地將這些操作抽象出去。這意味著我們不得不自己處理創(chuàng)建窗口,定義OpenGL上下文以及處理用戶輸入。幸運(yùn)的是,有一些庫已經(jīng)提供了我們所需的功能,其中一部分是特別針對(duì)OpenGL的。這些庫節(jié)省了我們書寫操作系統(tǒng)相關(guān)代碼的時(shí)間,提供給我們一個(gè)窗口和上下文用來渲染。最流行的幾個(gè)庫有GLUT,SDL,SFML和GLFW。我們選擇GLFW。
- GLAD 是什么?也是由于OpenGL是由各個(gè)公司自己實(shí)現(xiàn)的方案,所以各個(gè)實(shí)現(xiàn)的細(xì)節(jié)不一致。因?yàn)镺penGL只是一個(gè)標(biāo)準(zhǔn)/規(guī)范,具體的實(shí)現(xiàn)是由驅(qū)動(dòng)開發(fā)商針對(duì)特定顯卡實(shí)現(xiàn)的。由于OpenGL驅(qū)動(dòng)版本眾多,它大多數(shù)函數(shù)的位置都無法在編譯時(shí)確定下來,需要在運(yùn)行時(shí)查詢。所以任務(wù)就落在了開發(fā)者身上,開發(fā)者需要在運(yùn)行時(shí)獲取函數(shù)地址并將其保存在一個(gè)函數(shù)指針中供以后使用。這樣的代碼非常復(fù)雜,而且很繁瑣,我們需要對(duì)每個(gè)可能使用的函數(shù)都要重復(fù)這個(gè)過程。幸運(yùn)的是,GLAD這可庫可以幫助我們做這些事情。GLAD可以屏蔽平臺(tái)之間API的差異。
安裝環(huán)境
機(jī)器:Macbook Pro
芯片:M1(arm64)
系統(tǒng):macOS Ventura 13.4.1 (c)
因?yàn)楸娝苤脑?,蘋果系統(tǒng)對(duì)OpenGL的支持不友好,mac對(duì)OpenGL的支持情況詳見蘋果官網(wǎng)
在mac上默認(rèn)開發(fā)工具是xcode,但是xcode實(shí)在是太龐大了,本文將使用CMake來管理項(xiàng)目,需要在事先配置好CMake工具,最好也配置homebrew。
下載GLAD與GLFW
一、下載GLAD
- 從GLAD的在線服務(wù)下載所需的文件,參數(shù)選擇可根據(jù)自己的需要進(jìn)行設(shè)置,本文選擇C/C++語言,gl api版本為4.1
- 解壓縮下載的壓縮包,正確的目錄結(jié)構(gòu)如下所示:
glad
├── include
│ ├── KHR
│ │ └── khrplatform.h
│ └── glad
│ └── glad.h
└── src
└── glad.c
二、下載GLFW
- GLFW官網(wǎng)處下載,可以選擇下載源碼然后自己進(jìn)行編譯,也可以選擇直接下載編譯好的庫文件。從源碼開始編譯的話更加靈活,能夠靈活適配不同的操作系統(tǒng),也能讓自己對(duì)GLFW的源碼結(jié)構(gòu)有一個(gè)基本的了解。出于方便起見本文選擇了后者
- 下載下來的壓縮包解壓縮,得到目錄結(jié)構(gòu)如下的文件:
├── LICENSE.md
├── README.md
├── docs
├── include
├── lib-arm64
├── lib-universal
└── lib-x86_64
該目錄下主要用到兩個(gè)目錄。
首先,根據(jù)自己的芯片型號(hào)選擇lib-xxx,如果你是intel(x86)的芯片,那么就選擇lib-x86-64,如果你是新版的m1或者m2芯片(arm)那么就選擇lib-arm64。除此之外,lib-universal據(jù)說是兩種芯片類型都能兼容,但由于沒有機(jī)器,作者并未進(jìn)行測(cè)試,有興趣的同學(xué)可以自行測(cè)試一下。
其次,除了lib-xxx外,還需要用到的一個(gè)目錄是include目錄中的文件,剩下的文件和目錄可以刪除,不予保留。
至此,GLAD和GLFW的下載完成。接下來可以正式開始寫我們的Demo
項(xiàng)目結(jié)構(gòu)配置
創(chuàng)建工作目錄LearnOpenGL,并創(chuàng)建include、lib和src三個(gè)文件夾,并將GLAD和GLFW目錄下的文件移動(dòng)到相應(yīng)的目錄下:
glfw-3.3.8.bin.MACOS/include/GLFW/ -> LearnOpenGL/include/GLFW/
glfw-3.3.8.bin.MACOS/lib-arm64/ -> LearnOpenGL/lib-arm64/
glad/include/glad/ -> LearnOpenGL/include/glad/
glad/include/KHR/ -> LearnOpenGL/include/KHR/
glad/src/glad.c -> LearnOpenGL/src/glad.c
移動(dòng)完成后,正確的文件目錄結(jié)構(gòu)如下所示:
LearnOpenGL
├── include
│ ├── GLFW
│ │ ├── glfw3.h
│ │ └── glfw3native.h
│ ├── KHR
│ │ └── khrplatform.h
│ └── glad
│ └── glad.h
├── lib
│ ├── libglfw.3.dylib
│ └── libglfw3.a
└── src
└── glad.c
至此,基本的項(xiàng)目結(jié)構(gòu)配置完成。
項(xiàng)目代碼及編譯
進(jìn)入項(xiàng)目的src/目錄下,創(chuàng)建文件main.cpp,并寫入以下程序代碼:
#include <glad/glad.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
void error_callback(int error, const char* description)
{
fprintf(stderr, "Error(%d): %s\n", error, description);
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow* window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetWindowShouldClose(window, true);
}
}
int main() {
glfwSetErrorCallback(error_callback);
if (!glfwInit())
{
std::cout << "Failed to init GLFW" << std::endl;
return -1;
}
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //MAC OSX needs
#endif
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
GLFWwindow* window = glfwCreateWindow(640, 480, "LearnOpenGL", NULL, NULL);
if (window == NULL) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glViewport(0, 0, 640, 480);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
while(!glfwWindowShouldClose(window)) {
processInput(window);
glClearColor(0.9f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
在項(xiàng)目的根目錄下創(chuàng)建CMakeLists.txt文件,并將下面的語句復(fù)制進(jìn)去:
cmake_minimum_required(VERSION 3.18.1)
project(HelloGL VERSION 0.0.1)
# 使用 C++ 17 標(biāo)準(zhǔn)
set(CMAKE_CXX_STANDARD 17)
# 設(shè)置代碼文件目錄
set(SRC_DIR ${PROJECT_SOURCE_DIR}/src)
# 添加頭文件
set(HEADER_DIR ${PROJECT_SOURCE_DIR}/include)
set(LIB_DIR ${PROJECT_SOURCE_DIR}/lib-arm64)
include_directories(${HEADER_DIR}/ ${LIB_DIR}/)
set(GLFW_LINK ${LIB_DIR}/libglfw.3.dylib)
set(SOURCES ${SRC_DIR}/glad.c ${SRC_DIR}/main.cpp)
add_executable(HelloGL ${SOURCES})
# 鏈接GLFW庫
target_link_libraries(HelloGL ${GLFW_LINK})
# 鏈接系統(tǒng)的 OpenGL 框架和其他必要的庫
if (APPLE)
target_link_libraries(HelloGL "-framework OpenGL")
target_link_libraries(HelloGL "-framework Cocoa")
endif()
- 項(xiàng)目根目錄下創(chuàng)建build目錄,進(jìn)入build目錄并執(zhí)行:
mkdir build
cd build
cmake ..
輸出如下:
-- The C compiler identification is AppleClang 14.0.3.14030022
-- The CXX compiler identification is AppleClang 14.0.3.14030022
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Library/Developer/CommandLineTools/usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Library/Developer/CommandLineTools/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.4s)
-- Generating done (0.0s)
-- Build files have been written to: /Users/jeff/MyFolder/MyPrograms/opengl/LearnOpenGL/build
然后,在build目錄下執(zhí)行:
make
輸出如下
[ 33%] Building C object CMakeFiles/HelloGL.dir/src/glad.c.o
[ 66%] Building CXX object CMakeFiles/HelloGL.dir/src/main.cpp.o
[100%] Linking CXX executable HelloGL
[100%] Built target HelloGL
測(cè)試可執(zhí)行文件HelloGL
在build目錄中執(zhí)行下面的命令:
./HelloGL
得到下面的結(jié)果說明一切都正確:

遇到的問題
參考網(wǎng)上的資料進(jìn)行配置,實(shí)際運(yùn)行時(shí)遇到了一些問題,主要是代碼配置問題
1、創(chuàng)建window失敗
Error(65543): NSGL: The targeted version of macOS only supports forward-compatible core profile contexts for OpenGL 3.2 and above
解決方式:
在代碼里添加下面兩行代碼
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
2、運(yùn)行crash
CMake腳本里必須鏈接Cocoa庫,程序才可以正常運(yùn)行
target_link_libraries(HelloGL "-framework Cocoa")
參考
(超級(jí)詳細(xì))如何在Mac OS上的VScode中配置OpenGL環(huán)境并編譯
GLFW+GLAD OpenGL Mac開發(fā)環(huán)境搭建
GLFW Getting started

