2020年2月春节期间我刷完过一遍LearnOpenGL ,这是一个很好的入门openGL良心教程,一直没时间记录。最近打游戏荒废了好久,刚好换了电脑,重新装下环境顺便记录下LearnOpenGL的环境搭建。
教程中使用的环境是Visual Studios + CMake + MSVC,我没用过也没安装过Visual Studio。所以我选择的环境是vscode + CMake + MinGW-w64,在linux直接gcc就行了,mac用gcc、clang都可以。这样的好处是在win、linux、mac上都能搭建这套环境。
我的系统是win,因为要打游戏(
编译器肯定是必须的,我没用过msvc,只用过gcc,mingw-w64就是win上的gcc。
下载地址:https://www.mingw-w64.org/downloads/
双击打开,选择native windows,x86_64,如果是32位系统则选i686。设置好安装目录
直接点process安装
完成后,安装目录的bin文件夹里就有gcc了
最后吧bin目录添加到系统环境变量PATH里:此电脑-属性-高级系统设置-环境变量-PATH-添加D:\app\mingw-w64\bin
c++在编译的时候,需要引用各种头文件,链接这个那个的各种动态库、静态库。项目复杂的时候编译会很麻烦,cmake相当于一个构建系统,用不怎么简洁的语法,描述如何编译目标,帮我们生成makefile文件,自动编译项目。
需要用到以下库:
GLFW - 负责创建OpenGL上下文并显示窗口
GLAD - 查找openGL函数指针
在画出出色的效果之前,首先要做的就是创建一个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,其他库类似
OpenGL只是一个标准/规范,具体的实现是由驱动开发商针对特定显卡实现的。由于OpenGL驱动版本众多,它大多数函数的位置都无法在编译时确定下来,需要在运行时查询。
GLAD会帮我们找到函数位置
到这里就可以创建项目了
建立一个名为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时的头文件目录,复制过来
KHR/ - 安装GLAD时的头文件目录,复制过来
src/ - 存放源代码
start/ - 存放LearnOpenGL教程第一部分源码
CMakeLists.txt
- 子目录构建文件
HelloWindow.cpp
- 创建窗口示例程序
根目录下的CMakeLists.txt
文件是引导cmake的入口,主要做一些项目设置,和头文件,lib等查找工作,详细如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
就会参与编译
看下项目里GLFW的搜索文件cmake/modules/FindGLFW3.cmake
,这个文件可以在网上找到很多例子,cmake本身也会预装很多find文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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 )
这里和LearnOpenGL里教的一样了就,src/start/HelloWindow.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// 你好,窗口
#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 );
}
最后来写下src/start
目录里的CMakeLists.txt
,来告诉cmake如何编译上面的cpp文件:
1
2
3
# 你好,窗口
add_executable ( HelloWindow HelloWindow.cpp ) # 添加可执行程序
target_link_libraries ( HelloWindow ${ GLFW3_LIBRARY } glad ) # 链接lib glfw glad.c
回到项目根目录执行:cmake -S . -B build/ -G"MinGW Makefiles"
进入build目录执行:mingw32-make.exe
编译结束后,在build/src/start/
目录里能看到名为HelloWindow.exe
的可执行程序,恭喜
三角形也可以画出来了,具体跟着教程走吧
希望你也能通关,终点等你。
(依赖库安装还没写完,待续。。。