Mac OS上OpenGL開發(fā)環(huán)境配置并編譯(GLFW+GLAD)

前言

  1. OpenGL 是什么?The Industry Standard for High Performance Graphics 這是官方解釋。說白了他就是一套標(biāo)準(zhǔn)接口。對(duì),是接口,并沒有實(shí)現(xiàn)具體的代碼。
  2. 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。
  3. 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

  1. 從GLAD的在線服務(wù)下載所需的文件,參數(shù)選擇可根據(jù)自己的需要進(jìn)行設(shè)置,本文選擇C/C++語言,gl api版本為4.1
  1. 解壓縮下載的壓縮包,正確的目錄結(jié)構(gòu)如下所示:
  glad
  ├── include
  │   ├── KHR
  │   │   └── khrplatform.h
  │   └── glad
  │       └── glad.h
  └── src
      └── glad.c

二、下載GLFW

  1. GLFW官網(wǎng)處下載,可以選擇下載源碼然后自己進(jìn)行編譯,也可以選擇直接下載編譯好的庫文件。從源碼開始編譯的話更加靈活,能夠靈活適配不同的操作系統(tǒng),也能讓自己對(duì)GLFW的源碼結(jié)構(gòu)有一個(gè)基本的了解。出于方便起見本文選擇了后者
  1. 下載下來的壓縮包解壓縮,得到目錄結(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()

  1. 項(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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容