配置 OpenGL 开发环境 Vistual Studio 2017

版权声明:本文为博主原创文章,转载请标明出处,非常感谢! https://blog.csdn.net/joyous/article/details/86015199

配置 OpenGL 开发环境 Vistual Studio 2017

预备工作

先下载需要的文件,glfw、glad 和 cmake

1、glfw 下载地址 https://www.glfw.org/download.html ,这里直接下载源码 (source package),将在本地的 Vistual Studio 2017 下编译为 lib,以后在项目中使用。

2、glad 下载,https://glad.dav1d.de/ 打开页面后,选择 gl 版本,最新的是 4.6,可根据显卡情况选择,这里 gl 我选择 Version 4.5,profile 选择 core,单击 GENERATE 后得到 glad.zip 文件,解压后替换 glfw 内的 glad.
但最新的 glad 非必要,不单独下载 glad 也可以使用 glfw 目前自带的 glad,不过支持的 OpenGL 版本过低(ver 3.3),但 glfw 内的演示却可以全部编译成功,升级 glad 后,部分演示缺乏定义的常量编译不通过,也就是 glad 对新版本的 OpenGL 接口与旧版在定义上有所增减。

3、下载 cmake https://cmake.org/download/ 根据自己的喜好,下载 zip 或者 msi 都可以。

编译 OpenGL 框架 (编译 glfw)

解压 glfw-3.2.1.zip 至 d:\opengl\glfw\3.2.1
解压 glad.zip 至 d:\opengl\glad\glad_v4.5
解压或安装 cmake 后,运行 D:\cmake\3.13.2\bin\cmake-gui.exe
单击 Browse Source 选择源码目录,单击 Browse Build 选择生成编译工程目录,然后单击 Configure 时选择所支持的 IDE 版本和 32 或者 64 位的支持,单击 Generate 开始生成文件,待完成后会显示 Configuring doneGenerating done 信息

此时,在 d:\opengl\glfw\3.2.1\build_x86 目录内生产了  Vistual Studio 2017 的工程文件(这里我生成的工程是 32位,需要 64 位的工程项目的话需要用 cmake 在 configuring 时重新选择)。

双击 GLFW.sln 即可打开 Vistual Studio 2017 IDE,再点菜单上的 Build Solution 对工程进行全部编译:
这里需要注意,glad ver3.3 (glfw 内置 ) 可以将演示全部编译成功,而新版本 glad 则不能将演示全编译成功,但不影响生成 glfw3.lib 的编译。

编译通过后,一些演示和测试的 exe 文件,可以先体验一下,输出目录如下:
d:\opengl\glfw\3.2.1\build_x86\examples\Debug
d:\opengl\glfw\3.2.1\build_x86\tests\Debug
而最关键的是得到了 glfw3.lib 文件,位置在 d:\opengl\glfw\3.2.1\build_x86\src\Debug,它将是开发 OpenGL 的必备文件,如果需要 64位版本,则需要在 cmake 生成项目是选择 x64。

第一个 OpenGL 项目

新建一个空项目。

对工程进行配置:
添加 Include Directories 选项
d:\opengl\glfw\3.2.1\include
d:\opengl\glfw\3.2.1\deps
添加 Labrary Directories 选项(glfw3.lib 生成位置)
d:\opengl\glfw\3.2.1\build_x86\src\Debug

Linker 的 input 增加 lib 文件 glfw3.lib

将 glad.c 复制到项目的 Source Files

编译时注意对 lib 的 32 或者 64 位的选择,编译通过后直接运行,出现窗口如下:
不希望图形窗口背后还有个控制台窗口的可以看这篇文章 https://blog.csdn.net/joyous/article/details/86033560

测试代码如下

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);

// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";

int main()
{
  // glfw: initialize and configure
  // ------------------------------
  glfwInit();
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
  glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
#endif

    // glfw window creation
    // --------------------
  GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
  if (window == NULL)
  {
    std::cout << "Failed to create GLFW window" << std::endl;
    glfwTerminate();
    return -1;
  }
  glfwMakeContextCurrent(window);
  glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

  // glad: load all OpenGL function pointers
  // ---------------------------------------
  if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
  {
    std::cout << "Failed to initialize GLAD" << std::endl;
    return -1;
  }


  // build and compile our shader program
  // ------------------------------------
  // vertex shader
  int vertexShader = glCreateShader(GL_VERTEX_SHADER);
  glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
  glCompileShader(vertexShader);
  // check for shader compile errors
  int success;
  char infoLog[512];
  glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
  if (!success)
  {
    glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
    std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
  }
  // fragment shader
  int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
  glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
  glCompileShader(fragmentShader);
  // check for shader compile errors
  glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
  if (!success)
  {
    glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
    std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
  }
  // link shaders
  int shaderProgram = glCreateProgram();
  glAttachShader(shaderProgram, vertexShader);
  glAttachShader(shaderProgram, fragmentShader);
  glLinkProgram(shaderProgram);
  // check for linking errors
  glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
  if (!success) {
    glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
    std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
  }
  glDeleteShader(vertexShader);
  glDeleteShader(fragmentShader);

  // set up vertex data (and buffer(s)) and configure vertex attributes
  // ------------------------------------------------------------------
  float vertices[] = {
      -0.5f, -0.5f, 0.0f, // left  
       0.5f, -0.5f, 0.0f, // right 
       0.0f,  0.5f, 0.0f  // top   
  };

  unsigned int VBO, VAO;
  glGenVertexArrays(1, &VAO);
  glGenBuffers(1, &VBO);
  // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
  glBindVertexArray(VAO);

  glBindBuffer(GL_ARRAY_BUFFER, VBO);
  glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
  glEnableVertexAttribArray(0);

  // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
  glBindBuffer(GL_ARRAY_BUFFER, 0);

  // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
  // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
  glBindVertexArray(0);


  // uncomment this call to draw in wireframe polygons.
  //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

  // render loop
  // -----------
  while (!glfwWindowShouldClose(window))
  {
    // input
    // -----
    processInput(window);

    // render
    // ------
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    // draw our first triangle
    glUseProgram(shaderProgram);
    glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
    glDrawArrays(GL_TRIANGLES, 0, 3);
    // glBindVertexArray(0); // no need to unbind it every time 

    // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
    // -------------------------------------------------------------------------------
    glfwSwapBuffers(window);
    glfwPollEvents();
  }

  // optional: de-allocate all resources once they've outlived their purpose:
  // ------------------------------------------------------------------------
  glDeleteVertexArrays(1, &VAO);
  glDeleteBuffers(1, &VBO);

  // glfw: terminate, clearing all previously allocated GLFW resources.
  // ------------------------------------------------------------------
  glfwTerminate();
  return 0;
}

// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
  if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
    glfwSetWindowShouldClose(window, true);
}

// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
  // make sure the viewport matches the new window dimensions; note that width and 
  // height will be significantly larger than specified on retina displays.
  glViewport(0, 0, width, height);
}

测试代码取自 https://learnopengl.com/Getting-started/Hello-Triangle

Q群讨论:236201801

猜你喜欢

转载自blog.csdn.net/joyous/article/details/86015199
今日推荐