Windows 下OpenGL的基本安装与配置(基于Visual Studio 2019 与 MinGW)
MinGW的安裝
1.首先我們下載相應(yīng)的MinGW安裝文件, 可以通過下載相對應(yīng)的架構(gòu)和相應(yīng)的環(huán)境的壓縮文件或者在線安裝。在這里我選擇的是在線安裝的安裝程序。
如果你下載的是壓縮包的形式(.7z), 請將它解壓縮到你想安裝的位置, 然后設(shè)置相應(yīng)的環(huán)境變量。
若果你選擇在線安裝, 則直接點(diǎn)擊安裝程序(.msi), 點(diǎn)擊“Next”, 按照下圖的選項(xiàng)配置, 點(diǎn)擊“Next”, 之后選擇你的安裝路徑, 點(diǎn)擊“Next”, 等待下載相關(guān)的文件, 完成安裝。
安裝OpenGL
按下“Win + R”, 輸入“dxdiag”, 點(diǎn)擊左上角的“呈現(xiàn)”, 查看當(dāng)前顯卡的版本, 下載對應(yīng)的驅(qū)動。如果你電腦的“C:\Windows\System32\”下已經(jīng)有“opengl32.dll和glu32.dll”, 那么你可以跳過這一步。
OpenGL下載地址
CMake
在下載對應(yīng)的GLFW源代碼后,首先對其進(jìn)行解壓縮。 我們需要使用CMake工具來生成對應(yīng)的庫文件, 首先我們需要下載CMake, Cmake下載地址。下載相應(yīng)的安裝文件(.msi 大概25MB左右), 運(yùn)行它安裝CMake。
我們直接點(diǎn)擊“Next”, 接受相應(yīng)的許可協(xié)議, 點(diǎn)擊Next。
在這里推薦選擇第二項(xiàng), 以便之后的使用。
選擇安裝路徑
點(diǎn)擊“Install”開始安裝
等待安裝完成, 至此, CMake的安裝結(jié)束。
FreeGLUT
FreeGLUT是OpenGL Utility Toolkit(GLUT)庫的開源替代方案。GLUT(以及FreeGLUT)允許用戶在廣泛的平臺上創(chuàng)建和管理包含OpenGL上下文的窗口,還可以讀取鼠標(biāo),鍵盤和操縱桿功能。FreeGLUT旨在完全替代GLUT,并且僅有幾處區(qū)別。
由于GLUT陷入停滯,因此FreeGLUT正在開發(fā)中,以改進(jìn)該工具包。它根據(jù)MIT許可證發(fā)布。
執(zhí)行之后, 如果你已經(jīng)安裝了OpenGL, 那么不出錯(cuò)的話你應(yīng)當(dāng)能夠在你的FreeGLUT文件夾下看到對應(yīng)的Makefile文件。
如果最后你看到了這樣的內(nèi)容, 那么恭喜你, 你已經(jīng)把FreeGLUT安裝到你的MinGW中了, 它已經(jīng)自動把需要的include文件、lib文件以及bin文件復(fù)制到你的MinGW中了(在 freeglut 3.0.0以上的版本中, 可能不會安裝"glut.h"庫文件)。最后, 讓我們來測試一下。
編寫一個(gè)FreeGLUT的C程序example.c, 源代碼如下:
/** GL01Hello.cpp: Test OpenGL C/C++ Setup*/ #include <windows.h> // For MS Windows #include <GL/freeglut.h> // GLUT, includes glu.h and gl.h/* Handler for window-repaint event. Call back when the window first appears andwhenever the window needs to be re-painted. */ void display() {glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaqueglClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer// Draw a Red 1x1 Square centered at originglBegin(GL_QUADS); // Each set of 4 vertices form a quadglColor3f(1.0f, 0.0f, 0.0f); // RedglVertex2f(-0.5f, -0.5f); // x, yglVertex2f( 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 GLUTglutCreateWindow("OpenGL Setup Test"); // Create a window with the given titleglutInitWindowSize(320, 320); // Set the window's initial width & heightglutInitWindowPosition(50, 50); // Position the window's initial top-left cornerglutDisplayFunc(display); // Register display callback handler for window re-paintglutMainLoop(); // Enter the infinitely event-processing loopreturn 0; }執(zhí)行一下指令
gcc -c -o example.o example.c gcc -o example.exe example.o -lfreeglut -lopengl32 -Wl,--subsystem,windows運(yùn)行生成的example.exe文件, 你應(yīng)該可以看到以下界面:
如果你看到以下這種錯(cuò)誤, 那么你可能需要將“x86_64-w64-mingw32\bin”目錄下的“l(fā)ibfreeglut.dll”文件復(fù)制到MinGW安裝目錄下的"bin"目錄下。
GLEW
GLFW
GLFW是一個(gè)專門針對OpenGL的C語言庫,它提供了一些渲染物體所需的最低限度的接口。它允許用戶創(chuàng)建OpenGL上下文,定義窗口參數(shù)以及處理用戶輸入。我們需要先下載它GLFW官網(wǎng)下載,它對應(yīng)的源代碼。當(dāng)然你可以選擇直接下載對應(yīng)的已經(jīng)編譯好的庫文件, 下載源代碼來構(gòu)建庫文件是為了更好的適合每個(gè)人的電腦。
使用CMake的GUI界面可以很簡單的完成生成Makefile的任務(wù), 但是我們在這里使用命令行的方式來執(zhí)行, 一是為了更具普遍性, 二是為了之后的安裝。
不出意外的話, 你看到的應(yīng)該是以下的界面
恭喜你, 你已經(jīng)完成了GLFW的安裝, 你應(yīng)當(dāng)能在你的MinGW目錄下的“include”文件夾下看到相關(guān)的頭文件。
編寫一個(gè)簡單的OpenGL程序 HelloOpenGL.cpp
// CPP program to render a triangle using Shaders #include <GL/glew.h> #include <GL/glut.h> #include <GL/gl.h> #include <GL/glu.h> #include <GL/glext.h>#include <iostream> #include <string>using namespace std;string vertexShader = R"(#version 430in vec3 pos;void main(){gl_Position = vec4(pos, 1);} )";string fragmentShader = R"(#version 430void 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 objectcout << "Error creating shaders!";return 0;}// Attach source code to this objectglShaderSource(shaderId, 1, &shaderCode, NULL);glCompileShader(shaderId); // compile the shader objectGLint compileStatus;// check for compilation statusglGetShaderiv(shaderId, GL_COMPILE_STATUS, &compileStatus);if (!compileStatus){ // If compilation was not successfullint length;glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &length);char *cMessage = new char[length];// Get additional informationglGetShaderInfoLog(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 programif (programId == 0){cout << "Error Creating Shader Program";return 0;}// Attach both the shaders to itglAttachShader(programId, vertexShaderId);glAttachShader(programId, fragmentShaderId);// Create executable of this programglLinkProgram(programId);GLint linkStatus;// Get the link status for this programglGetProgramiv(programId, GL_LINK_STATUS, &linkStatus);if (!linkStatus){ // If the linking failedcout << "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 itglGenBuffers(1, &vboId);glBindBuffer(GL_ARRAY_BUFFER, vboId);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);// unbind the active bufferglBindBuffer(GL_ARRAY_BUFFER, 0);return vboId; }// Initialize and put everything together void init() {// clear the framebuffer each frame with black colorglClearColor(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 programGLuint posAttributePosition = glGetAttribLocation(programId, "pos");GLuint vaoId;glGenVertexArrays(1, &vaoId); // Generate VAO (Vertex Array Object)// Bind it so that rest of vao operations affect this vaoglBindVertexArray(vaoId);// buffer from which 'pos' will receive its data and the format of that dataglBindBuffer(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 drawingglClear(GL_COLOR_BUFFER_BIT);// draw triangles starting from index 0 and// using 3 indicesglDrawArrays(GL_TRIANGLES, 0, 3);// swap the buffers and hence show the buffers// content to the screenglutSwapBuffers(); }// 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運(yùn)行HelloOpenGL.exe, 你應(yīng)當(dāng)看到以下圖形
如果你看到以下這種錯(cuò)誤, 那么你可能需要將“x86_64-w64-mingw32\bin”目錄下的“glew32.dll”文件復(fù)制到MinGW安裝目錄下的"bin"目錄下。
GLAD
由于OpenGL驅(qū)動版本眾多,它大多數(shù)函數(shù)的位置都無法在編譯時(shí)確定下來,需要在運(yùn)行時(shí)查詢。所以任務(wù)就落在了開發(fā)者身上,開發(fā)者需要在運(yùn)行時(shí)獲取函數(shù)地址并將其保存在一個(gè)函數(shù)指針中供以后使用。這種方式十分麻煩, 所幸我們有GLAD來幫助我們解決這個(gè)問題。
將生成的“l(fā)ibglad.a”庫文件放入MinGW的"x86_64-w64-mingw32\lib"目錄下, 以便之后的使用。之后, 我們只需要在編譯時(shí)加入相對應(yīng)的鏈接庫即可。編譯的命令如下:
g++ ***.cpp -o ***.exe -lopengl32 -lglu32 -lglfw3 -lglew32 -lgdi32 -lglad gcc ***.cpp -o ***.exe -lopengl32 -lglu32 -lglfw3 -lglew32 -lgdi32 -lgladVisual Studio 的配置
關(guān)于Visual Studio的安裝, 相信網(wǎng)上有許多的教程, 再次就不再贅述了。
首先, 我們需要使用CMake工具生成我們的glfw3.lib庫文件, 打開CMake的GUI界面, 選擇已經(jīng)解壓縮的glfw源文件, 選擇生成項(xiàng)目的目標(biāo)目錄, 點(diǎn)擊“configure”,選擇生成的項(xiàng)目類型, 這里我們選擇“Visual Studio”類型的。.
點(diǎn)擊“finish”,等待配置完成之后, 再點(diǎn)擊“Generate”生成對應(yīng)的項(xiàng)目文件。
打開項(xiàng)目的生成路徑, 你將會看到“GLFW.sln”的文件, 雙擊打開它。點(diǎn)擊“Visual Studio”上方的“生成”——>"生成解決方案“, 最終的lib庫文件將會在“src/Debug”目錄下。
將對應(yīng)的glad.c文件轉(zhuǎn)變?yōu)閷?yīng)的lib文件, 以便使用。打開Visual Studio, 創(chuàng)建一個(gè)glad靜態(tài)庫項(xiàng)目,在該項(xiàng)目路徑下創(chuàng)建“include”, 將glad.zip內(nèi)的“include”內(nèi)的內(nèi)容復(fù)制到項(xiàng)目下的“include”目錄下, 將glad.c的內(nèi)容復(fù)制到glad.cpp文件中, 在glad.cpp的第一行添加“#include “pch.h””,將下載的glad壓縮文件內(nèi)的include目錄復(fù)制到項(xiàng)目的目錄下, 點(diǎn)擊“項(xiàng)目”——>"glad屬性“——>"C/C++“——>"常規(guī)“”, 將"附加包含目錄“設(shè)置為之前我們項(xiàng)目下的“include”目錄。
點(diǎn)擊“確定”。
點(diǎn)擊上方的“生成”——>“生成解決方案”。我們將在項(xiàng)目路徑下的“Debug”路徑下看到我們生成的glid.lib文件。
創(chuàng)建一個(gè)新的空白C++項(xiàng)目, 在項(xiàng)目目錄下創(chuàng)建目錄“include”、“l(fā)ib”,將我們之前的glfw的“include”頭文件以及我們glad.zip文件內(nèi)的“include”頭文件放入我們的創(chuàng)建的“include”目錄下,將我們之前得到的“glfw.lib”以及"glad.lib"放入我們創(chuàng)建的“l(fā)ib”目錄下, 點(diǎn)擊上方的“項(xiàng)目”——>“屬性”——>"Visual C++目錄“, 將“包含目錄”設(shè)置為我們項(xiàng)目下的“include”目錄, 將“庫目錄”設(shè)置為我們創(chuàng)建的“l(fā)ib”目錄下。
之后, 我們點(diǎn)擊“鏈接器”——>“輸入”, 在附加依賴項(xiàng)內(nèi)輸入“opengl32.lib”、以及你的glfw的庫文件, 我這里的是glfw3.lib, 生成的glad庫文件, 我這里的是glad.lib。opengl32.lib是Visual Studio SDK自帶的一個(gè)庫文件。
點(diǎn)擊“確定”, 即可完成OpenGL的配置。
點(diǎn)擊“本地Windows調(diào)試”即可運(yùn)行你的OpenGL程序。為了能夠正常運(yùn)行你的程序, 在運(yùn)行時(shí)請確保你的每個(gè)庫都是基于相同位數(shù)的, X86對應(yīng)的是32位的, 而X64對應(yīng)的是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/
總結(jié)
以上是生活随笔為你收集整理的Windows 下OpenGL的基本安装与配置(基于Visual Studio 2019 与 MinGW)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android之socket编程实例
- 下一篇: Windows常见进程大全