• OpenGL入门(二)


    背景

    上一篇文章我们已经初步介绍了OpenGL的基本概念,准确来说OpenGL只是一个规范,基于这个规范提供了库去实现图像编程。OpenGL的很多操作都是基于一个窗口,今天我们就来实现创建一个简单的窗口,talk is cheap,show me your code。

    环境配置

    工欲善其事, 必先利其器,在正式开发之前还需要搭建一下环境,这里仅仅以个人的环境为例,不同的平台可以去google一下,有很多相关的文章,我自己使用的是Mac,为了方便编辑器使用的是VS Code。
    step1:
    在正式开始之前需要先安装GLFW,GLFW是一个C语言写的库,符合OpenGLd的标准,使用GLFW可以创建一个OpenGL的context,创建并定义一个窗口的参数以及处理用户的输入,安装后其安装位置要记住,之后需要使用。

    brew install glfw
    • 1

    step2:

    下载glad,可以去下载页面下载,使用一下配置即可:

    glad配置
    glad配置

    然后点击下面的生成按钮并且下载。然后新建一个文件夹将解压后的include和src文件夹复制到新建的文件夹。 这个glad是一个开源库,正如之前我们所提到的OpenGL只是一个标准,具体的实现是有各个显卡厂商完成的, 所以显卡驱动的版本有很多种类,虽然都是基于OpenGL标准,实现的函数和最终的效果是一样的,但是函数的位置在编译期是无法知道的,且需要在运行时检索这些函数,然后将这些函数的位置存储在函数指针中以便之后使用,而这个检索函数的过程又是与操作系统高度相关的,而glad就是用来帮助开发者完成这些繁琐的过程。

    step3:

    新建CMakeList.txt文件,其内容如下,记得替换GLFW_H和GLFW_LINK的地址,在安装GLFW完成时会提示安装的位置。

    cmake_minimum_required(VERSION 3.0.0)
    project(HelloGL VERSION 0.1.0)

    # 使用 C++ 11 标准
    set(CMAKE_CXX_STANDARD 11)

    # 添加头文件
    set(GLAD_H ${PROJECT_SOURCE_DIR}/include)
    set(GLFW_H /usr/local/include)
    include_directories(${GLAD_H} ${GLFW_H})

    # 添加目标链接
    set(GLFW_LINK /usr/local/lib/libglfw.3.dylib)
    link_libraries(${GLFW_LINK})

    # 执行编译命令
    set(SOURCES glad.c main.cpp)
    add_executable(HelloGL ${SOURCES})

    # 链接系统的 OpenGL 框架
    if (APPLE)
        target_link_libraries(HelloGL "-framework OpenGL")
    endif()

    include(CTest)
    enable_testing()

    set(CPACK_PROJECT_NAME ${PROJECT_NAME})
    set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
    include(CPack)
    • 1

    step4:

    然后在src目录下新建一个main.cpp,内容如下:

    #include 
    #include 
    #include 
    #include 
    #include 

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

    int main(int argc, const char *argv[])
    {
        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

        GLFWwindow *window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
        if (window == NULL)
        {
            std::cout << "fail to create window" << std::endl;
            glfwTerminate();
            return -1;
        }

        glfwMakeContextCurrent(window);

        if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
        {
            std::cout << "Failed to initialize GLAD" << std::endl;
            return -1;
        }

        glViewport(0, 0, 800, 600);
        glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

        while (!glfwWindowShouldClose(window))
        {

            processInput(window);
            glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);

            glfwSwapBuffers(window);
            glfwPollEvents();
        }

        glfwTerminate();
        return 0;
    }

    void framebuffer_size_callback(GLFWwindow *window, int width, int height)
    {
        glViewport(0, 0, width, height);
    }

    void processInput(GLFWwindow *window)
    {
        if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        {
            glfwSetWindowShouldClose(window, true);
        }
    }
    • 1

    然后在主目录下新建一个build目录

    mkdir build
    • 1

    然后进入build目录

    cd build
    • 1

    使用以下命令

    cmake ..
    • 1

    然后使用make编译

    make
    • 1

    如果编译成功,会在build目录下生成HelloGL的二进制文件,使用以下命令启动程序

    ./HelloGL
    • 1

    如果此时出现一个窗口,这就是你绘制的第一个窗口。

    窗口的由来

    经过之前的配置我们已经成功创建了一个窗口了,那么这个窗口是如何被创建的呢,接下来我们通过代码仔细分析这个创建的过程。 step1:

    首先我们需要引入需要使用的库,也就是之前提到的glfw和glad

    # include 
    # include 
    • 1

    其中需要注意的是glad的引入要在GLFW之前,因为GLFW需要使用glad其中的内容

    然后需要创建一个主函数,然后在主函数中对glfw进行初始化和各种配置,以便之后使用,其代码如下, 首先需要使用glfwInit函数对glfw进行初始化,然后使用glfwWindowHint对glfw进行配置,glfwWindowHint函数主要有两个参数,第一个参数是需要配置的项,第二个参数是配置给该项的值。 下面代码通过GLFW_CONTEXT_VERSION_MAJOR配置OpenGL的主版本号,GLFW_CONTEXT_VERSION_MINOR是次版本号,GLFW_OPENGL_PROFILE是配置OpenGL的渲染模式,正如上篇文章所提到的,我嘛使用核心渲染模式,最后由于我是苹果平台,所以需要配置GLFW_OPENGL_FORWARD_COMPAT,保证程序正常执行。

    int main() {
        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);

        return 0;
    }
    • 1

    step2:

    在初始化glfw后我们则需要创建一个窗口,并将其与当前线程绑定,其代码如下:创建一个窗口需要使用glfwCreateWindow函数,其第一个参数是指定窗口的宽度,第二个参数是窗口的高度,第三个参数是窗口的名字,最后两个参数暂时可以不管设置为空即可,然后使用glfwMakeContextCurrent函数将窗口绑定在当前线程。

     GLFWwindow *window = glfwCreateWindow(800, 600, "QStackOpenGL", NULL, NULL);
        if (window == NULL) {
            std::cout<<"Fail to create a glfw window"<        glfwTerminate();
            return -1;
        }
        glfwMakeContextCurrent(window);
    • 1

    step3:

    正如之前所提到的,glad将为我们管理一些函数的指针,所以在使用OpenGL的一些函数前,我们需要初始化glad,其代码如下:

    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
            std::cout<<"fail to init glad"<        return -1;
        }
    • 1

    在正式渲染之前还需要设置一下视口(viewport),其前两个参数是窗口左上角的坐标,后两个参数是窗口的宽度和高度,设置与GLFW的窗口一致即可。

    glViewport(0, 0, 800, 600);
    • 1

    step4: 当用户改变窗口大小的时候,窗口的大小也要随之改变,需要先声明一个函数如下:

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

    其具体实现如下:

     void framebuffer_size_callback(GLFWwindow *window, int width, int height) {
            glViewport(0, 0, width, height);
        }
    • 1

    然后需要注册该函数,每次窗口大小改变时调用该函数,实现如下:

     glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    • 1

    step5: 我们不希望窗口出现一下就消失,而是只要我们不取消就一直存在,那么则需要一个循环一直去绘制窗口,其代码如下:

     while (!glfwWindowShouldClose(window))
        {
          glfwSwapBuffers(window);
          glfwPollEvents();
        }
    • 1

    glfwWindowShouldClose(window)是用来判断GLFW是否接受到关闭指令,如果没有则是true,glfwSwapBuffers(window)是交换窗口的buffer,其实在渲染过程中是有两块buffer的,一块是屏幕上展示的,另一块是在计算下一桢每一个像素的颜色等,如果使用一个buffer,就会显示出渲染的过程,体验不好,且性能也不好,glfwPollEvents()则是接受一个外界的信号如鼠标和键盘输入等。

    step6:

    当程序运行结束,我们则要关闭GLFW,代码如下:

     glfwTerminate();
    • 1

    最后

    这篇文章简要介绍了环境配置以及如何创建一个窗口,更多文章可以关注公众号QStack。

  • 相关阅读:
    10M25DCF484C8G(FPGA) AMY-6M-0002 BGA GPS模块
    windows 安装多个独立微信,设置不同快捷键
    deployment html--->JDBC--->mysql
    【C语言刷题】Leetcode268丢失的数字
    450-500未传计算机毕业设计安卓App毕设项目之ssm公园植物介绍APP
    【MMC/SD/SDIO】读写操作
    Vue.js入门教程(三)
    第7章 Redis的噩梦:阻塞
    [附源码]计算机毕业设计影评网站系统Springboot程序
    理解MySQL的日志 Redo、Undo
  • 原文地址:https://blog.csdn.net/QStack/article/details/127643648