[OpenGL]Windows上OpenGL開發環境搭建
網上資料很多都是基於Cygwin來搭建的OpenGL開發環境,這裡介紹一種非Cygwin搭建環境的方法。
1,OpenGL Loader Generator下載安裝
OpenGL Loader是一個標準規範,定義了如何在運行時期間載入OpenGL相關函數的指針。 這是windows上開發OpenGL程序才需要的lib,因為從1.1版本開始,windows不在對OpenGL 後續版本的 ABI(application binary interface)提供支持(可能是微軟的DX出來後與OGL商業競爭吧),所以開發者無法直接獲取OGL新版本的相關函數,不過有好心人寫了工具,在運行時期間獲取OGL的新版函數,這裡介紹兩個開源庫:
glad
Dav1dde/glad
glloadgen
alfonse / glLoadGen / wiki / Home
我是用的是glad,這個開源庫的開發者還提供了在線生成工具,可以不用下載安裝Load Generator,直接在線生成指定版本的OpenGL Loader: http://glad.dav1d.de/
2,編譯OpenGL Loader的靜態庫
通過glad生成的代碼,編譯一個lib, 以便後面的的示例工程調用。因為這些代碼開發者不用做修改,只是調用,所以最好編譯成lib,而不要直接加到自己的項目代碼中。
3,下載GLM(OpenGL Mathematics)
這是OpenGL的數學庫
g-truc/glm
4,下載GLFW
這是一個提供了OpenGL, OpenGL ES和Vulkan相關介面的跨平台的開源庫,有這個庫你就可以訪問他們的最新API。 glfw/glfw
5,新建一個C++工程並設置OpenGL相關的頭文件和靜態庫
指定頭文件的目錄

指定靜態庫的目錄

在代碼需要包含的頭文件以及lib:
#include <KHR/khrplatform.h>n#include <glad/glad.h>n#include <GLFW/glfw3.h>nn#pragma comment(lib, "opengl32.lib")n#pragma comment(lib, "glad.lib")n#pragma comment(lib, "glfw3.lib")n
新建的測試工程叫GLTest,目錄結構如下: 新加了兩個分別叫include和lib的目錄,用於存放第三方庫的頭文件和庫文件
完整的測試的代碼:
#pragma oncenn#include <iostream>n#include <windows.h>nn#include <fstream>n#include <sstream>n#include <string>nn#include <KHR/khrplatform.h>n#include <glad/glad.h>n#include <GLFW/glfw3.h>nn#pragma comment(lib, "opengl32.lib")n#pragma comment(lib, "glad.lib")n#pragma comment(lib, "glfw3.lib")nnusing std::string;nusing std::ifstream;nnGLFWwindow *window;nnstatic HMODULE libGL;nnGLuint vaoHandle;nnint width, height;nnvoid update(float t);nnvoid render();nnvoid mainLoop() {n while (!glfwWindowShouldClose(window) && !glfwGetKey(window, GLFW_KEY_ESCAPE)) {nn update(float(glfwGetTime()));n render();n glfwSwapBuffers(window);n glfwPollEvents();n }n}nnstatic void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)n{n}nnvoid dumpGLInfo(bool dumpExtensions) {n const GLubyte *renderer = glGetString(GL_RENDERER);n const GLubyte *vendor = glGetString(GL_VENDOR);n const GLubyte *version = glGetString(GL_VERSION);n const GLubyte *glslVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);nn GLint major, minor;n glGetIntegerv(GL_MAJOR_VERSION, &major);n glGetIntegerv(GL_MINOR_VERSION, &minor);nn printf("-------------------------------------------------------------n");n printf("GL Vendor : %sn", vendor);n printf("GL Renderer : %sn", renderer);n printf("GL Version : %sn", version);n printf("GL Version : %d.%dn", major, minor);n printf("GLSL Version : %sn", glslVersion);n printf("-------------------------------------------------------------n");nn if (dumpExtensions) {n GLint nExtensions;n glGetIntegerv(GL_NUM_EXTENSIONS, &nExtensions);n for (int i = 0; i < nExtensions; i++) {n printf("%sn", glGetStringi(GL_EXTENSIONS, i));n }n }n}nnvoid linkMe(GLint vertShader, GLint fragShader)n{n // Create the program objectn GLuint programHandle = glCreateProgram();n if (0 == programHandle) {n fprintf(stderr, "Error creating program object.n");n exit(1);n }nn // Bind index 0 to the shader input variable "VertexPosition"n //glBindAttribLocation(programHandle, 0, "VertexPosition");n // Bind index 1 to the shader input variable "VertexColor"n //glBindAttribLocation(programHandle, 1, "VertexColor");nn // Attach the shaders to the program objectn glAttachShader(programHandle, vertShader);n glAttachShader(programHandle, fragShader);nn // Link the programn glLinkProgram(programHandle);nn // Check for successful linkingn GLint status;n glGetProgramiv(programHandle, GL_LINK_STATUS, &status);n if (GL_FALSE == status) {nn fprintf(stderr, "Failed to link shader program!n");nn GLint logLen;n glGetProgramiv(programHandle, GL_INFO_LOG_LENGTH, &logLen);nn if (logLen > 0) {n char * log = (char *)malloc(logLen);nn GLsizei written;n glGetProgramInfoLog(programHandle, logLen, &written, log);nn fprintf(stderr, "Program log: n%s", log);nn free(log);n }n }n else {n glUseProgram(programHandle);n }n}nnvoid initScene(){n //////////////////////////////////////////////////////n /////////// Vertex shader //////////////////////////n //////////////////////////////////////////////////////nn // Load contents of filen ifstream inFile("shader/basic.vert");n if (!inFile) {n fprintf(stderr, "Error opening file: shader/basic.vertn");n exit(1);n }nn std::stringstream code;n code << inFile.rdbuf();n inFile.close();n string codeStr(code.str());nn // Create the shader objectn GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);n if (0 == vertShader) {n fprintf(stderr, "Error creating vertex shader.n");n exit(EXIT_FAILURE);n }nn // Load the source code into the shader objectn const GLchar* codeArray[] = { codeStr.c_str() };n glShaderSource(vertShader, 1, codeArray, NULL);nn // Compile the shadern glCompileShader(vertShader);nn // Check compilation statusn GLint result;n glGetShaderiv(vertShader, GL_COMPILE_STATUS, &result);n if (GL_FALSE == result) {n fprintf(stderr, "Vertex shader compilation failed!n");nn GLint logLen;n glGetShaderiv(vertShader, GL_INFO_LOG_LENGTH, &logLen);nn if (logLen > 0) {n char * log = (char *)malloc(logLen);nn GLsizei written;n glGetShaderInfoLog(vertShader, logLen, &written, log);nn fprintf(stderr, "Shader log: n%s", log);nn free(log);n }n }nn //////////////////////////////////////////////////////n /////////// Fragment shader //////////////////////////n //////////////////////////////////////////////////////nn // Load contents of file into shaderCode heren ifstream fragFile("shader/basic.frag");n if (!fragFile) {n fprintf(stderr, "Error opening file: shader/basic.fragn");n exit(1);n }nn std::stringstream fragCode;n fragCode << fragFile.rdbuf();n fragFile.close();n codeStr = fragCode.str();nn // Create the shader objectn GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);n if (0 == fragShader) {n fprintf(stderr, "Error creating fragment shader.n");n exit(1);n }nn // Load the source code into the shader objectn codeArray[0] = codeStr.c_str();n glShaderSource(fragShader, 1, codeArray, NULL);nn // Compile the shadern glCompileShader(fragShader);nn // Check compilation statusn glGetShaderiv(fragShader, GL_COMPILE_STATUS, &result);n if (GL_FALSE == result) {n fprintf(stderr, "Fragment shader compilation failed!n");nn GLint logLen;n glGetShaderiv(fragShader, GL_INFO_LOG_LENGTH, &logLen);nn if (logLen > 0) {n char * log = (char *)malloc(logLen);nn GLsizei written;n glGetShaderInfoLog(fragShader, logLen, &written, log);nn fprintf(stderr, "Shader log: n%s", log);nn free(log);n }n }nn linkMe(vertShader, fragShader);nn /////////////////// Create the VBO ////////////////////n float positionData[] = {n -0.8f, -0.8f, 0.0f,n 0.8f, -0.8f, 0.0f,n 0.0f, 0.8f, 0.0f };n float colorData[] = {n 1.0f, 0.0f, 0.0f,n 0.0f, 1.0f, 0.0f,n 0.0f, 0.0f, 1.0f };nnn // Create and populate the buffer objectsn GLuint vboHandles[2];n glGenBuffers(2, vboHandles);n GLuint positionBufferHandle = vboHandles[0];n GLuint colorBufferHandle = vboHandles[1];nn glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);n glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), positionData, GL_STATIC_DRAW);nn glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);n glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), colorData, GL_STATIC_DRAW);nn // Create and set-up the vertex array objectn glGenVertexArrays(1, &vaoHandle);n glBindVertexArray(vaoHandle);nn glEnableVertexAttribArray(0); // Vertex positionn glEnableVertexAttribArray(1); // Vertex colornn glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);n glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL);nn glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);n glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL);n glBindVertexArray(0);n}nnvoid update(float t)n{nn}nnvoid render()n{n glClear(GL_COLOR_BUFFER_BIT);nn glBindVertexArray(vaoHandle);n glDrawArrays(GL_TRIANGLES, 0, 3);n glBindVertexArray(0);n}nnvoid resize(int w, int h)n{n width = w;n height = h;n glViewport(0, 0, w, h);n}nnnvoid initializeGL() {n glClearColor(0.5f, 0.5f, 0.5f, 1.0f);n initScene();n}nnnint main(int argc, char* argv[])n{n // Initialize GLFWn if (!glfwInit()) exit(EXIT_FAILURE);nn#ifdef __APPLE__n // Select OpenGL 4.1n glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);n glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);n#elsen // Select OpenGL 4.3n glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);n glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);n#endifn glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true);n glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);n glfwWindowHint(GLFW_RESIZABLE, false);n glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true);nn // Open the windown string title = "OpenGLTest";n window = glfwCreateWindow(500, 500, title.c_str(), NULL, NULL);n if (!window) {n glfwTerminate();n exit(EXIT_FAILURE);n }n glfwMakeContextCurrent(window);n glfwSetKeyCallback(window, key_callback);nn // Get framebuffer sizen int fbw, fbh;n glfwGetFramebufferSize(window, &fbw, &fbh);nn // Load the OpenGL functions.n if (!gladLoadGL()) { exit(-1); }nn dumpGLInfo(false);nn // Initializationn initializeGL();nn // Enter the main loopn mainLoop();nn // Close window and terminate GLFWn glfwTerminate();n // Exit programn exit(EXIT_SUCCESS);nn return 0;n}n
最終效果:

測試工程下載地址:
http://pan.baidu.com/s/1nvp6kUt只保證Release模式下正常運行,Debug版本需要指定第三方庫的debug版本示例代碼參考自:
https://github.com/daw42/glslcookbook/blob/master/chapter01/scenebasic.cpp最後打個廣告,大家如果覺得有用麻煩關注下我的微博,幫我增加點粉絲數量。。
玄冬Wong推薦閱讀:
※如何判斷線段和圓弧是否相交?
※shadertoy 這個網站如何玩?
※藝術抽象科學,科學證明藝術。-- Spacetime optimization與迪斯尼的動畫12法則的聯繫
※簡述47種Shader Map的渲染原理與製作方法

