• OpenGL入门(一)之认识OpenGL和创建Window


    本系列文章为Learn OpenGL个人学习总结!
    OpenGL入门(一)之认识OpenGL和创建Window
    OpenGL入门(二)之渲染管线pipeline,VAO、VBO和EBO
    OpenGL入门(三)之着色器Shader
    OpenGL入门(四)之纹理Texture
    OpenGL入门(五)之Matrix矩阵操作和坐标系统
    OpenGL进阶(一)之帧缓冲FrameBuffer
    OpenGL进阶(二)之像素缓冲PixelBuffer

    简介

    什么是OpenGL

    OpenGL是一个由Khronos组织制定并维护的规范(Specification),供我们访问GPU资源,OpenGL规范严格规定了每个函数该如何执行,以及它们的输出值,具体函数实现由各大显卡厂商提供!

    渲染模式

    • 立即渲染模式(Immediate mode),也叫固定渲染管线,该模式绘图比较简单,因为大部分实现细节都被库封装起来了!(3.2版本之前
    • 核心模式(Core-profile),可以真正理解和深入图行编程,相对来说学习也更困难一点!(3.2版本及之后

    本系列文章使用版本:OpenGL 3.3

    拓展

    OpenGL的一大特性就是对扩展(Extension)的支持,当一个显卡公司提出一个新特性或者渲染上的大优化,通常会以扩展的方式在驱动中实现。

    if(GL_ARB_extension_name)
    {
        // 使用硬件支持的全新的现代特性
    }
    else
    {
        // 不支持此扩展: 用旧的方式去做
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    状态机

    OpenGL自身是一个巨大的状态机(State Machine):一系列的变量描述OpenGL此刻应当如何运行。OpenGL的状态通常被称为OpenGL上下文(Context)。
    当使用OpenGL的时候,我们会遇到一些状态设置函数(State-changing Function),这类函数将会改变上下文。以及状态使用函数(State-using Function),这类函数会根据当前OpenGL的状态执行一些操作。

    对象

    OpenGL库是用C语言写的,同时也支持多种语言的派生,但其内核仍是一个C库。由于C的一些语言结构不易被翻译到其它的高级语言,因此OpenGL开发的时候引入了一些抽象层。
    在OpenGL中一个对象是指一些选项的集合,它代表OpenGL状态的一个子集。可以把对象看做一个C风格的结构体(Struct):

    struct object_name {
        float  option1;
        int    option2;
        char[] name;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

    创建Window

    环境

    IDE:VS Code
    OS:Mac OS

    直接去官网下载GLFW mac的预编译好的库!导入工程中!
    配置Task.json

    "tasks": [
            {
                "type": "cppbuild",
                "label": "C/C++: clang++ 生成活动文件",
                "command": "/usr/bin/clang++",
                "args": [
                    "-fcolor-diagnostics",
                    "-fansi-escape-codes",
                    "-g",
                    "${file}",
                    "-I",
                    "${workspaceFolder}/dependency/include",
                    "-L",
                    "${workspaceFolder}/dependency/lib-universal",
                    "-lglfw3",
                    "-framework",
                    "OpenGL",
                    "-framework",
                    "Cocoa",
                    "-framework",
                    "IOKit",
                    "-o",
                    "${fileDirname}/${fileBasenameNoExtension}"
                ],
                "options": {
                    "cwd": "${fileDirname}"
                },
                "problemMatcher": [
                    "$gcc"
                ],
                "group": {
                    "kind": "build",
                    "isDefault": true
                },
                "detail": "调试器生成的任务。"
            }
        ],
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    重点:主要就是上边添加头文件和库的地方:

                    "-I",
                    "${workspaceFolder}/dependency/include",
                    "-L",
                    "${workspaceFolder}/dependency/lib-universal",
                    "-lglfw3",
                    "-framework",
                    "OpenGL",
                    "-framework",
                    "Cocoa",
                    "-framework",
                    "IOKit"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    绘制

    #include 
    #include 
    
    //窗口大小改变回调函数
    void framebuffer_size_callback(GLFWwindow *window, int width, int height)
    {
        std::cout << "GLFW window change width="<<width <<",height="<<height << std::endl;
        //设置窗口的维度   前两个参数控制窗口的左下角的位置,后两个参数控制渲染窗口的宽高(像素)
        glViewport(0, 0, width, height);
    }
    
    //获取用户输入
    //如果按下了esc,则修改为true,关闭窗口
    void processInput(GLFWwindow *window)
    {
        if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
            glfwSetWindowShouldClose(window, true);
    }
    
    int main(void)
    {
        glfwInit();
        // set version 3.3
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        // set core-profile
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        // mac os need
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    
        //窗口的宽、高
        GLFWwindow *window = glfwCreateWindow(800, 600, "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);
    
        //渲染
        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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    编译运行就可以得到一个窗口了!比较简单,代码中注释也很清楚了!

    需要额外注意的一点:就是OpenGL的双缓冲

    双缓冲(Double Buffer)
    应用程序使用单缓冲绘图时可能会存在图像闪烁的问题。 这是因为生成的图像不是一下子被绘制出来的,而是按照从左到右,由上而下逐像素地绘制而成的。最终图像不是在瞬间显示给用户,而是通过一步一步生成的,这会导致渲染的结果很不真实。为了规避这些问题,我们应用双缓冲渲染窗口应用程序。前缓冲保存着最终输出的图像,它会在屏幕上显示;而所有的的渲染指令都会在后缓冲上绘制。当所有的渲染指令执行完毕后,我们交换(Swap)前缓冲和后缓冲,这样图像就立即呈显出来,之前提到的不真实感就消除了。

  • 相关阅读:
    C++交叉编译grpc
    一款构建Python命令行应用的开源库
    【校招VIP】前端专业课之七层模型
    【Linux】基本指令-入门级文件操作(二)
    Pyttsx3+Windows语音合成不同的声音
    大小端存储是什么鬼?
    微信小程序开发---页面导航
    落地护眼阅读灯哪个牌子好?落地灯品牌排行榜
    redis漏洞修复:CVE-2022-35977、CVE-2023-22458、CVE-2023-28856
    探索Redis与MySQL的双写问题
  • 原文地址:https://blog.csdn.net/aiynmimi/article/details/126525402