前言
- OpenGL 是什么?The Industry Standard for High Performance Graphics 这是官方解释。说白了他就是一套标准接口。对,是接口,并没有实现具体的代码。
- GLFW 是什么?在我们画出任何效果之前,首先要做的就是创建一个OpenGL上下文和一个用于显示的窗口。然而,这些操作在每个系统上都是不一样的,OpenGL有目的地将这些操作抽象出去。这意味着我们不得不自己处理创建窗口,定义OpenGL上下文以及处理用户输入。幸运的是,有一些库已经提供了我们所需的功能,其中一部分是特别针对OpenGL的。这些库节省了我们书写操作系统相关代码的时间,提供给我们一个窗口和上下文用来渲染。最流行的几个库有GLUT,SDL,SFML和GLFW。我们选择GLFW。
- GLAD 是什么?也是由于OpenGL是由各个公司自己实现的方案,所以各个实现的细节不一致。因为OpenGL只是一个标准/规范,具体的实现是由驱动开发商针对特定显卡实现的。由于OpenGL驱动版本众多,它大多数函数的位置都无法在编译时确定下来,需要在运行时查询。所以任务就落在了开发者身上,开发者需要在运行时获取函数地址并将其保存在一个函数指针中供以后使用。这样的代码非常复杂,而且很繁琐,我们需要对每个可能使用的函数都要重复这个过程。幸运的是,GLAD这可库可以帮助我们做这些事情。GLAD可以屏蔽平台之间API的差异。
安装环境
机器:Macbook Pro
芯片:M1(arm64)
系统:macOS Ventura 13.4.1 (c)
因为众所周知的原因,苹果系统对OpenGL的支持不友好,mac对OpenGL的支持情况详见苹果官网
在mac上默认开发工具是xcode,但是xcode实在是太庞大了,本文将使用CMake来管理项目,需要在事先配置好CMake工具,最好也配置homebrew。
下载GLAD与GLFW
一、下载GLAD
- 从GLAD的在线服务下载所需的文件,参数选择可根据自己的需要进行设置,本文选择C/C++语言,gl api版本为4.1
- 解压缩下载的压缩包,正确的目录结构如下所示:
glad
├── include
│ ├── KHR
│ │ └── khrplatform.h
│ └── glad
│ └── glad.h
└── src
└── glad.c
二、下载GLFW
- GLFW官网处下载,可以选择下载源码然后自己进行编译,也可以选择直接下载编译好的库文件。从源码开始编译的话更加灵活,能够灵活适配不同的操作系统,也能让自己对GLFW的源码结构有一个基本的了解。出于方便起见本文选择了后者
- 下载下来的压缩包解压缩,得到目录结构如下的文件:
├── LICENSE.md
├── README.md
├── docs
├── include
├── lib-arm64
├── lib-universal
└── lib-x86_64
该目录下主要用到两个目录。
首先,根据自己的芯片型号选择lib-xxx,如果你是intel(x86)的芯片,那么就选择lib-x86-64,如果你是新版的m1或者m2芯片(arm)那么就选择lib-arm64。除此之外,lib-universal据说是两种芯片类型都能兼容,但由于没有机器,作者并未进行测试,有兴趣的同学可以自行测试一下。
其次,除了lib-xxx外,还需要用到的一个目录是include目录中的文件,剩下的文件和目录可以删除,不予保留。
至此,GLAD和GLFW的下载完成。接下来可以正式开始写我们的Demo
项目结构配置
创建工作目录LearnOpenGL,并创建include、lib和src三个文件夹,并将GLAD和GLFW目录下的文件移动到相应的目录下:
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
移动完成后,正确的文件目录结构如下所示:
LearnOpenGL
├── include
│ ├── GLFW
│ │ ├── glfw3.h
│ │ └── glfw3native.h
│ ├── KHR
│ │ └── khrplatform.h
│ └── glad
│ └── glad.h
├── lib
│ ├── libglfw.3.dylib
│ └── libglfw3.a
└── src
└── glad.c
至此,基本的项目结构配置完成。
项目代码及编译
进入项目的src/目录下,创建文件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;
}
在项目的根目录下创建CMakeLists.txt文件,并将下面的语句复制进去:
cmake_minimum_required(VERSION 3.18.1)
project(HelloGL VERSION 0.0.1)
# 使用 C++ 17 标准
set(CMAKE_CXX_STANDARD 17)
# 设置代码文件目录
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})
# 链接系统的 OpenGL 框架和其他必要的库
if (APPLE)
target_link_libraries(HelloGL "-framework OpenGL")
target_link_libraries(HelloGL "-framework Cocoa")
endif()
- 项目根目录下创建build目录,进入build目录并执行:
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目录下执行:
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
测试可执行文件HelloGL
在build目录中执行下面的命令:
./HelloGL
得到下面的结果说明一切都正确:

遇到的问题
参考网上的资料进行配置,实际运行时遇到了一些问题,主要是代码配置问题
1、创建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、运行crash
CMake脚本里必须链接Cocoa库,程序才可以正常运行
target_link_libraries(HelloGL "-framework Cocoa")
参考
(超级详细)如何在Mac OS上的VScode中配置OpenGL环境并编译
GLFW+GLAD OpenGL Mac开发环境搭建
GLFW Getting started

