LearnOpenGL环境搭建
2020年2月春节期间我刷完过一遍LearnOpenGL,这是一个很好的入门openGL良心教程,一直没时间记录。最近打游戏荒废了好久,刚好换了电脑,重新装下环境顺便记录下LearnOpenGL的环境搭建。
教程中使用的环境是Visual Studios + CMake + MSVC,我没用过也没安装过Visual Studio。所以我选择的环境是vscode + CMake + MinGW-w64,在linux直接gcc就行了,mac用gcc、clang都可以。这样的好处是在win、linux、mac上都能搭建这套环境。
工具安装
我的系统是win,因为要打游戏(
- vscode 就不多说了,用其他编辑器/IDE也行
mingw-w64
编译器肯定是必须的,我没用过msvc,只用过gcc,mingw-w64就是win上的gcc。
-
双击打开,选择native windows,x86_64,如果是32位系统则选i686。设置好安装目录
-
直接点process安装
-
完成后,安装目录的bin文件夹里就有gcc了
-
最后吧bin目录添加到系统环境变量PATH里:此电脑-属性-高级系统设置-环境变量-PATH-添加
D:\app\mingw-w64\bin
cmake
c++在编译的时候,需要引用各种头文件,链接这个那个的各种动态库、静态库。项目复杂的时候编译会很麻烦,cmake相当于一个构建系统,用不怎么简洁的语法,描述如何编译目标,帮我们生成makefile文件,自动编译项目。
- 下载地址:https://cmake.org/download/,选择
.msi
安装 - 一路点next,安装路径无所谓,记得加入PATH就行
- 完事检查下安装成功
依赖库安装
需要用到以下库:
- GLFW - 负责创建OpenGL上下文并显示窗口
- GLAD - 查找openGL函数指针
GLFW
在画出出色的效果之前,首先要做的就是创建一个OpenGL上下文(Context)和一个用于显示的窗口。然而,这些操作在每个系统上都是不一样的,OpenGL有目的地从这些操作抽象(Abstract)出去。这意味着我们不得不自己处理创建窗口,定义OpenGL上下文以及处理用户输入。
GLFW就是帮我们在不同平台做这个事情
- 获取源代码:www.glfw.org/download.html,下载source package
- 记得看看官方编译指南https://www.glfw.org/docs/latest/compile.html
- 解压后进入目录
- 在此目录执行
cmake -S . -B build -G "MinGW Makefiles" -DBUILD_SHARED_LIBS=ON
,其中-S
指定源码所在目录,-B
指定构建/输出目录,-G
指定我们是给MinGW生产makefile,最后一个参数是告诉CMake,我们要动态库 - 最后,进入
build/
目录,执行mingw32-make.exe -j4
,-j4
指定我们用4个cpu核心,注意由于我们装的mingw,所以make
命令变成了mingw32-make.exe
- 完事后我们就得到了lib文件
- GLFW就编译完了,关键目录只有两个
- 头文件
path\to\glfw-3.3.6\include
- lib文件
path\to\glfw-3.3.6\build\src
- 头文件
- 在
path\to\glfw-3.3.6\build
目录执行mingw32-make.exe install
(需要管理员权限),文件会被安装到C:/Program Files (x86)/GLFW/
下 - 最后手动复制
glfw3.dll
到C:\Windows\System32
下,不然运行程序会报找不到dll,其他库类似
GLAD
OpenGL只是一个标准/规范,具体的实现是由驱动开发商针对特定显卡实现的。由于OpenGL驱动版本众多,它大多数函数的位置都无法在编译时确定下来,需要在运行时查询。
GLAD会帮我们找到函数位置
- 使用在线服务定制我们需要的源代码:https://glad.dav1d.de/
- 下载解压后,
include
目录里是俩头文件,src
目录里面就一个glad.c
- 这个
glad.c
后面会直接和程序一起参与编译
到这里就可以创建项目了
创建项目
建立一个名为LearnOpenGL
的文件夹作为项目根目录。整个项目结构是这样的:
- root(LearnOpenGL)
CMakeLists.txt
- cmake构建文件- cmake/modules/ - 存放cmake自动查找库的find文件
- include/ - 存放头文件
- src/ - 存放源代码
可以参考:https://github.com/kirito41dd/LearnOpenGL
创建窗口
先给出目录细节再详细说,所有参与文件如下:
CMakeLists.txt
- cmake构建文件- cmake/modules/ - 存放cmake自动查找库的find文件
FindGLFW3.cmake
- 负责自动查找glfw的头文件路径和lib路径
- include/ - 存放头文件
glad.c
- 把安装GLAD时的文件复制过来- glad/ - 安装GLAD时的头文件目录,复制过来
glad.h
- KHR/ - 安装GLAD时的头文件目录,复制过来
khrplatform.h
- src/ - 存放源代码
- start/ - 存放LearnOpenGL教程第一部分源码
CMakeLists.txt
- 子目录构建文件HelloWindow.cpp
- 创建窗口示例程序
- start/ - 存放LearnOpenGL教程第一部分源码
1.主CMakeLists.txt
根目录下的CMakeLists.txt
文件是引导cmake的入口,主要做一些项目设置,和头文件,lib等查找工作,详细如下:
cmake_minimum_required(VERSION 2.9) # 指定cmake最小版本
project(learnopengl) # 设置项目名
# 依赖环境
# ------------------------------------------------------------------------------
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/")
find_package(GLFW3 REQUIRED)
include_directories(${GLFW3_INCLUDE_DIR})
add_library(glad include/glad.c)
# ------------------------------------------------------------------------------
include_directories(./include) # 添加头文件搜索目录
# 子目录
add_subdirectory(src/start) # 子目录也会有CMakeLists.txt文件,环境是相通的
主要来看依赖环境部分:
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/")
这句是往CMAKE_MODULE_PATH
里追加一个目录,
这些目录里存放着各种find文件,命名为Find${LIB}.cmake
find_package(GLFW3 REQUIRED)
表示调用FindGLFW3.cmake
查找GLFW3的头文件和lib,而且是必须找到,否则构建终止。
如果找到了,会设置GLFW3_XXX
等一系列变量
include_directories(${GLFW3_INCLUDE_DIR})
,find执行成功才会执行这句,变量GLFW3_INCLUDE_DIR
里存放着GLFW头文件的路径,然后添加头文件搜索目录
add_library(glad include/glad.c)
声明一个名为glad
的lib,后面可以指定链接它,glad.c
就会参与编译
2.FindGLFW.cmake
看下项目里GLFW的搜索文件cmake/modules/FindGLFW3.cmake
,这个文件可以在网上找到很多例子,cmake本身也会预装很多find文件。
set( _glfw3_HEADER_SEARCH_DIRS
"/usr/include"
"/usr/local/include"
"${CMAKE_SOURCE_DIR}/includes"
"C:/Program Files (x86)/glfw/include"
"C:/Program Files (x86)/GLFW/include") # 注意这里,就是我们安装的目录
set( _glfw3_LIB_SEARCH_DIRS
"/usr/lib"
"/usr/local/lib"
"${CMAKE_SOURCE_DIR}/lib"
"C:/Program Files (x86)/glfw/lib-msvc110"
"C:/Program Files (x86)/GLFW/lib") # 注意这里
# Check environment for root search directory
set( _glfw3_ENV_ROOT $ENV{GLFW3_ROOT} )
if( NOT GLFW3_ROOT AND _glfw3_ENV_ROOT )
set(GLFW3_ROOT ${_glfw3_ENV_ROOT} )
endif()
# Put user specified location at beginning of search
if( GLFW3_ROOT )
list( INSERT _glfw3_HEADER_SEARCH_DIRS 0 "${GLFW3_ROOT}/include" )
list( INSERT _glfw3_LIB_SEARCH_DIRS 0 "${GLFW3_ROOT}/lib" )
endif()
# Search for the header
FIND_PATH(GLFW3_INCLUDE_DIR "GLFW/glfw3.h" # 头文件目录的变量
PATHS ${_glfw3_HEADER_SEARCH_DIRS} )
# Search for the library
FIND_LIBRARY(GLFW3_LIBRARY NAMES glfw3 glfw glfw3dll
PATHS ${_glfw3_LIB_SEARCH_DIRS} )
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLFW3 DEFAULT_MSG
GLFW3_LIBRARY GLFW3_INCLUDE_DIR) # 注意这里
IF(GLFW3_FOUND)
IF(NOT GLFW3_FIND_QUIETLY)
MESSAGE(STATUS "Found ASSIMP: ${GLFW3_LIBRARY}")
ENDIF(NOT GLFW3_FIND_QUIETLY)
ELSE(GLFW3_FOUND)
IF(GLFW3_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find GLFW3")
ENDIF(GLFW3_FIND_REQUIRED)
ENDIF(GLFW3_FOUND)
3.创建窗口
这里和LearnOpenGL里教的一样了就,src/start/HelloWindow.cpp
// 你好,窗口
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stdlib.h>
using namespace std;
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
int main()
{
cout << "hellow" << endl;
glfwInit(); // 初始化库
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // 配置主版本号
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // 配置次版本号
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 使用核心模式
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Mac OS X 使用
// 创建一个窗口
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window); // 设置为当前上下文
// glad
// GLAD是用来管理OpenGL的函数指针的,所以在调用任何OpenGL的函数之前我们需要初始化GLAD。
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// 设置窗口的维度
// glViewport函数前两个参数控制窗口左下角的位置。第三个和第四个参数控制渲染窗口的宽度和高度(像素)。
glViewport(0, 0, 800, 600);
// 设置一个回调,当用户改变窗口的大小的时候,视口也应该被调整。
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// 渲染循环 render loop
while(!glfwWindowShouldClose(window))
{
processInput(window); // 处理输入
glClearColor(0.2f, 0.3f, 0.3f, 1.0f); // 设置清空屏幕所用的颜色
glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲之后,整个颜色缓冲都会被填充为glClearColor里所设置的颜色
glfwSwapBuffers(window); // 交换颜色缓冲(它是一个储存着GLFW窗口每一个像素颜色值的大缓冲)
glfwPollEvents(); // 函数检查有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状态,并调用对应的回调函数(可以通过回调方法手动设置)。
}
// 释放之前分配的资源
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow *window)
{
// 如果按下 esc , 窗口在下次循环将会退出
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
4.子CMakeLists.txt
最后来写下src/start
目录里的CMakeLists.txt
,来告诉cmake如何编译上面的cpp文件:
# 你好,窗口
add_executable(HelloWindow HelloWindow.cpp) # 添加可执行程序
target_link_libraries(HelloWindow ${GLFW3_LIBRARY} glad) # 链接lib glfw glad.c
5.编译
回到项目根目录执行:cmake -S . -B build/ -G"MinGW Makefiles"
进入build目录执行:mingw32-make.exe
编译结束后,在build/src/start/
目录里能看到名为HelloWindow.exe
的可执行程序,恭喜
三角形也可以画出来了,具体跟着教程走吧
终
- LearnOpenGL
- 我的通关记录github
希望你也能通关,终点等你。
(依赖库安装还没写完,待续。。。