1.首先我们下载相应的MinGW安装文件, 可以通过下载相对应的架构和相应的环境的压缩文件或者在线安装。在这里我选择的是在线安装的安装程序。
如果你下载的是压缩包的形式(.7z), 请将它解压缩到你想安装的位置, 然后设置相应的环境变量。
若果你选择在线安装, 则直接点击安装程序(.msi), 点击“Next”, 按照下图的选项配置, 点击“Next”, 之后选择你的安装路径, 点击“Next”, 等待下载相关的文件, 完成安装。
按下“Win + R”, 输入“dxdiag”, 点击左上角的“呈现”, 查看当前显卡的版本, 下载对应的驱动。如果你电脑的“C:\Windows\System32\”下已经有“opengl32.dll和glu32.dll”, 那么你可以跳过这一步。
OpenGL下载地址
在下载对应的GLFW源代码后,首先对其进行解压缩。 我们需要使用CMake工具来生成对应的库文件, 首先我们需要下载CMake, Cmake下载地址。下载相应的安装文件(.msi 大概25MB左右), 运行它安装CMake。
我们直接点击“Next”, 接受相应的许可协议, 点击Next。
在这里推荐选择第二项, 以便之后的使用。
选择安装路径
点击“Install”开始安装
等待安装完成, 至此, CMake的安装结束。
FreeGLUT是OpenGL Utility Toolkit(GLUT)库的开源替代方案。GLUT(以及FreeGLUT)允许用户在广泛的平台上创建和管理包含OpenGL上下文的窗口,还可以读取鼠标,键盘和操纵杆功能。FreeGLUT旨在完全替代GLUT,并且仅有几处区别。
由于GLUT陷入停滞,因此FreeGLUT正在开发中,以改进该工具包。它根据MIT许可证发布。
cmake -G "MinGW Makefiles" -S . -B . -DCMAKE_INSTALL_PREFIX=安装路径\x86_64-w64-mingw32
最后的"-DCMAKE_INSTALL_PREFIX"参数的值应当与你MinGW的安装路径一致。mingw32-make install
实现安装如果最后你看到了这样的内容, 那么恭喜你, 你已经把FreeGLUT安装到你的MinGW中了, 它已经自动把需要的include文件、lib文件以及bin文件复制到你的MinGW中了(在 freeglut 3.0.0以上的版本中, 可能不会安装"glut.h"库文件)。最后, 让我们来测试一下。
编写一个FreeGLUT的C程序example.c, 源代码如下:
/*
* GL01Hello.cpp: Test OpenGL C/C++ Setup
*/
#include // For MS Windows
#include // GLUT, includes glu.h and gl.h
/* Handler for window-repaint event. Call back when the window first appears and
whenever the window needs to be re-painted. */
void display() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer
// Draw a Red 1x1 Square centered at origin
glBegin(GL_QUADS); // Each set of 4 vertices form a quad
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex2f(-0.5f, -0.5f); // x, y
glVertex2f( 0.5f, -0.5f);
glVertex2f( 0.5f, 0.5f);
glVertex2f(-0.5f, 0.5f);
glEnd();
glFlush(); // Render now
}
/* Main function: GLUT runs as a console application starting at main() */
int main(int argc, char** argv) {
glutInit(&argc, argv); // Initialize GLUT
glutCreateWindow("OpenGL Setup Test"); // Create a window with the given title
glutInitWindowSize(320, 320); // Set the window's initial width & height
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
glutDisplayFunc(display); // Register display callback handler for window re-paint
glutMainLoop(); // Enter the infinitely event-processing loop
return 0;
}
执行一下指令
gcc -c -o example.o example.c
gcc -o example.exe example.o -lfreeglut -lopengl32 -Wl,--subsystem,windows
运行生成的example.exe文件, 你应该可以看到以下界面:
如果你看到以下这种错误, 那么你可能需要将“x86_64-w64-mingw32\bin”目录下的“libfreeglut.dll”文件复制到MinGW安装目录下的"bin"目录下。
cmake -G "MinGW Makefiles“” -S . -B . -DCMAKE_INSTALL_PREFIX=MinGW安装路径\x86_64-w64-mingw32
。mingw32-make all
mingw32-make install
GLFW是一个专门针对OpenGL的C语言库,它提供了一些渲染物体所需的最低限度的接口。它允许用户创建OpenGL上下文,定义窗口参数以及处理用户输入。我们需要先下载它GLFW官网下载,它对应的源代码。当然你可以选择直接下载对应的已经编译好的库文件, 下载源代码来构建库文件是为了更好的适合每个人的电脑。
使用CMake的GUI界面可以很简单的完成生成Makefile的任务, 但是我们在这里使用命令行的方式来执行, 一是为了更具普遍性, 二是为了之后的安装。
cmake -G "MinGW Makefiles“” -S . -B . -DCMAKE_INSTALL_PREFIX=MinGW安装路径\x86_64-w64-mingw32
。mingw32-make all
mingw32-make install
不出意外的话, 你看到的应该是以下的界面
恭喜你, 你已经完成了GLFW的安装, 你应当能在你的MinGW目录下的“include”文件夹下看到相关的头文件。
// CPP program to render a triangle using Shaders
#include
#include
#include
#include
#include
#include
#include
using namespace std;
string vertexShader = R"(
#version 430
in vec3 pos;
void main()
{
gl_Position = vec4(pos, 1);
}
)";
string fragmentShader = R"(
#version 430
void main()
{
gl_FragColor = vec4(1, 1, 1, 1); // white color
}
)";
// Compile and create shader object and returns its id
GLuint compileShaders(string shader, GLenum type)
{
const char *shaderCode = shader.c_str();
GLuint shaderId = glCreateShader(type);
if (shaderId == 0)
{ // Error: Cannot create shader object
cout << "Error creating shaders!";
return 0;
}
// Attach source code to this object
glShaderSource(shaderId, 1, &shaderCode, NULL);
glCompileShader(shaderId); // compile the shader object
GLint compileStatus;
// check for compilation status
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &compileStatus);
if (!compileStatus)
{ // If compilation was not successfull
int length;
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &length);
char *cMessage = new char[length];
// Get additional information
glGetShaderInfoLog(shaderId, length, &length, cMessage);
cout << "Cannot Compile Shader: " << cMessage;
delete[] cMessage;
glDeleteShader(shaderId);
return 0;
}
return shaderId;
}
// Creates a program containing vertex and fragment shader
// links it and returns its ID
GLuint linkProgram(GLuint vertexShaderId, GLuint fragmentShaderId)
{
GLuint programId = glCreateProgram(); // crate a program
if (programId == 0)
{
cout << "Error Creating Shader Program";
return 0;
}
// Attach both the shaders to it
glAttachShader(programId, vertexShaderId);
glAttachShader(programId, fragmentShaderId);
// Create executable of this program
glLinkProgram(programId);
GLint linkStatus;
// Get the link status for this program
glGetProgramiv(programId, GL_LINK_STATUS, &linkStatus);
if (!linkStatus)
{ // If the linking failed
cout << "Error Linking program";
glDetachShader(programId, vertexShaderId);
glDetachShader(programId, fragmentShaderId);
glDeleteProgram(programId);
return 0;
}
return programId;
}
// Load data in VBO (Vertex Buffer Object) and return the vbo's id
GLuint loadDataInBuffers()
{
GLfloat vertices[] = {// triangle vertex coordinates
-0.5, -0.5, 0,
0.5, -0.5, 0,
0, 0.5, 0};
GLuint vboId;
// allocate buffer sapce and pass data to it
glGenBuffers(1, &vboId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// unbind the active buffer
glBindBuffer(GL_ARRAY_BUFFER, 0);
return vboId;
}
// Initialize and put everything together
void init()
{
// clear the framebuffer each frame with black color
glClearColor(0, 0, 0, 0);
GLuint vboId = loadDataInBuffers();
GLuint vShaderId = compileShaders(vertexShader, GL_VERTEX_SHADER);
GLuint fShaderId = compileShaders(fragmentShader, GL_FRAGMENT_SHADER);
GLuint programId = linkProgram(vShaderId, fShaderId);
// Get the 'pos' variable location inside this program
GLuint posAttributePosition = glGetAttribLocation(programId, "pos");
GLuint vaoId;
glGenVertexArrays(1, &vaoId); // Generate VAO (Vertex Array Object)
// Bind it so that rest of vao operations affect this vao
glBindVertexArray(vaoId);
// buffer from which 'pos' will receive its data and the format of that data
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glVertexAttribPointer(posAttributePosition, 3, GL_FLOAT, false, 0, 0);
// Enable this attribute array linked to 'pos'
glEnableVertexAttribArray(posAttributePosition);
// Use this program for rendering.
glUseProgram(programId);
}
// Function that does the drawing
// glut calls this function whenever it needs to redraw
void display()
{
// clear the color buffer before each drawing
glClear(GL_COLOR_BUFFER_BIT);
// draw triangles starting from index 0 and
// using 3 indices
glDrawArrays(GL_TRIANGLES, 0, 3);
// swap the buffers and hence show the buffers
// content to the screen
glutSwapBuffers();
}
// main function
// sets up window to which we'll draw
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("Triangle Using OpenGL");
glewInit();
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
将文件保存为HelloOpenGL.cpp,输入以下命令:
g++ HelloOpenGL.cpp -o HelloOpenGL.exe -lopengl32 -lglew32 -lfreeglut -lglu32
运行HelloOpenGL.exe, 你应当看到以下图形
如果你看到以下这种错误, 那么你可能需要将“x86_64-w64-mingw32\bin”目录下的“glew32.dll”文件复制到MinGW安装目录下的"bin"目录下。
由于OpenGL驱动版本众多,它大多数函数的位置都无法在编译时确定下来,需要在运行时查询。所以任务就落在了开发者身上,开发者需要在运行时获取函数地址并将其保存在一个函数指针中供以后使用。这种方式十分麻烦, 所幸我们有GLAD来帮助我们解决这个问题。
gcc -c -o glad.o glad.c
ar cr libglad.a glad.o
将生成的“libglad.a”库文件放入MinGW的"x86_64-w64-mingw32\lib"目录下, 以便之后的使用。之后, 我们只需要在编译时加入相对应的链接库即可。编译的命令如下:
g++ ***.cpp -o ***.exe -lopengl32 -lglu32 -lglfw3 -lglew32 -lgdi32 -lglad
gcc ***.cpp -o ***.exe -lopengl32 -lglu32 -lglfw3 -lglew32 -lgdi32 -lglad
关于Visual Studio的安装, 相信网上有许多的教程, 再次就不再赘述了。
首先, 我们需要使用CMake工具生成我们的glfw3.lib库文件, 打开CMake的GUI界面, 选择已经解压缩的glfw源文件, 选择生成项目的目标目录, 点击“configure”,选择生成的项目类型, 这里我们选择“Visual Studio”类型的。.
点击“finish”,等待配置完成之后, 再点击“Generate”生成对应的项目文件。
打开项目的生成路径, 你将会看到“GLFW.sln”的文件, 双击打开它。点击“Visual Studio”上方的“生成”——>"生成解决方案“, 最终的lib库文件将会在“src/Debug”目录下。
将对应的glad.c文件转变为对应的lib文件, 以便使用。打开Visual Studio, 创建一个glad静态库项目,在该项目路径下创建“include”, 将glad.zip内的“include”内的内容复制到项目下的“include”目录下, 将glad.c的内容复制到glad.cpp文件中, 在glad.cpp的第一行添加“#include “pch.h””,将下载的glad压缩文件内的include目录复制到项目的目录下, 点击“项目”——>"glad属性“——>"C/C++“——>"常规“”, 将"附加包含目录“设置为之前我们项目下的“include”目录。
点击“确定”。
点击上方的“生成”——>“生成解决方案”。我们将在项目路径下的“Debug”路径下看到我们生成的glid.lib文件。
创建一个新的空白C++项目, 在项目目录下创建目录“include”、“lib”,将我们之前的glfw的“include”头文件以及我们glad.zip文件内的“include”头文件放入我们的创建的“include”目录下,将我们之前得到的“glfw.lib”以及"glad.lib"放入我们创建的“lib”目录下, 点击上方的“项目”——>“属性”——>"Visual C++目录“, 将“包含目录”设置为我们项目下的“include”目录, 将“库目录”设置为我们创建的“lib”目录下。
之后, 我们点击“链接器”——>“输入”, 在附加依赖项内输入“opengl32.lib”、以及你的glfw的库文件, 我这里的是glfw3.lib, 生成的glad库文件, 我这里的是glad.lib。opengl32.lib是Visual Studio SDK自带的一个库文件。
点击“确定”, 即可完成OpenGL的配置。
点击“本地Windows调试”即可运行你的OpenGL程序。为了能够正常运行你的程序, 在运行时请确保你的每个库都是基于相同位数的, X86对应的是32位的, 而X64对应的是64位的。
参考
[1]: https://medium.com/@bhargav.chippada/how-to-setup-opengl-on-mingw-w64-in-windows-10-64-bits-b77f350cea7e
[2]: https://www.transmissionzero.co.uk/computing/using-glut-with-mingw/
[3]: https://learnopengl-cn.github.io/01%20Getting%20started/02%20Creating%20a%20window/