目录

OpenGL和Imgui整合入门1

目录

OpenGL入门

先上效果图

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/v2-677c66b72772f5dbde0809db0f04dc66_b.jpg

环境配置

OpenGL有很多开源库,如常见的glad,glfw,glut等等,这里简述一下他们的区别:

glut是一个年代比较久远的窗口管理库,现在已经被glfw替代,不建议使用
glfw,轻量级gl库,针对OpenGL的C语言库,提供最低限度的接口,允许用户创建OpenGL上下文,定义窗口参数,处理用户输入等
glew,函数加载库,年代久远,不建议使用
glad,glew的较先进替代品

所以现在一般采用glad和glfw进行OpenGL开发,两个库的下载链接如下:

GLFW:http://www.glfw.org/download.html

glad:https://glad.dav1d.de/

具体环境配置教程网上有很多,这里采用了VS进行配置

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/v2-2702090d1e5aabfba8d77c7714b63c05_b.jpg

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/v2-0e1d0fe4b89ca378b41cb8db650c0ad5_b.jpg

记得引入glad.c文件

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/v2-0f904db83bf2a66fb4c710313af8d47c_b.jpg

配置完毕后,在网上找一段测试代码,看看配置是否有问题

 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
58
59
60
61
62
#include <glad/glad.h>
#include <gl/glfw3.h>
#include <iostream>
using namespace std;

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

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

//创建main函数,实例化glfw窗口
int main()
{
    //实例化glfw窗口,并告诉glfw使用的opengl版本:major 3,minor 3(3.3)
    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);

    //创建窗口对象
    GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGLTest", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    //初始化GLAD
    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);//输入检测

        glfwSwapBuffers(window);//双缓冲绘制
        glfwPollEvents();
    }
    glfwTerminate();//资源释放

    return 0;
}

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

这里注意,glad库必须在glfw库前包含否则会报错,编译后无法运行的同学记得查看自己的项目结构是否为32位(x86)

learn opengl官网上的注意事项

请确认是在包含GLFW的头文件之前包含了GLAD的头文件。GLAD的头文件包含了正确的OpenGL头文件(例如GL/gl.h),所以需要在其它依赖于OpenGL的头文件之前包含GLAD。

界面库采用ImGui,比较美观,使用也挺便捷

ImGui:https://github.com/ocornut/imgui

下载压缩包后直接解压到项目里然后包含就行

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/v2-033b4496b79f27a2e003f006dc7e96ec_b.jpg

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/v2-e707e3f57983bf09e2d275ff3218ffd2_b.jpg

根据learn-opengl网站的教程进行一个简单的编写

https://cdn.jsdelivr.net/gh/xinqinew/pic@main/img/v2-fd2bfcb519f1adb14a1f9f42a90525a7_b-20220217104527564.jpg

部分代码:

  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
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//ImGui部分
    {

            static int counter = 0;

            ImGui::Begin("Edit");                          // Create a window called "Hello, world!" and append into it.

            ImGui::Text("This is some useful text.");               // Display some text (you can use a format strings too)
            ImGui::Checkbox("Demo Window", &show_demo_window);      // Edit bools storing our window open/close state
            ImGui::Checkbox("Another Window", &show_another_window);

            ImGui::ColorEdit3("color", (float*)&color);            // Edit 1 float using a slider from 0.0f to 1.0f
            ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color

            if (ImGui::Button("Button"))                            // Buttons return true when clicked (most widgets return true when edited/activated)
                counter++;
            ImGui::SameLine();
            ImGui::Text("counter = %d", counter);

            ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
            ImGui::End();
        }
ImGui::Render();
......
//绘制部分
    // 更新uniform颜色
        ourShader.setVec4("newcolor", color.x, color.y, color.z, 1);
        //std::cout << color.x << " " << color.y << " " << color.z << " " << color.w << endl;
        ourShader.use();
        glDrawArrays(GL_TRIANGLES, 0, 3);


        glfwSwapBuffers(window);//双缓冲绘制
//从文件读取顶点着色器和片元着色器
Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath = nullptr)
    {
        // 1. retrieve the vertex/fragment source code from filePath
        std::string vertexCode;
        std::string fragmentCode;
        std::string geometryCode;
        std::ifstream vShaderFile;
        std::ifstream fShaderFile;
        std::ifstream gShaderFile;
        // ensure ifstream objects can throw exceptions:
        vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        gShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        try
        {
            // open files
            vShaderFile.open(vertexPath);
            fShaderFile.open(fragmentPath);
            std::stringstream vShaderStream, fShaderStream;
            // read file's buffer contents into streams
            vShaderStream << vShaderFile.rdbuf();
            fShaderStream << fShaderFile.rdbuf();
            // close file handlers
            vShaderFile.close();
            fShaderFile.close();
            // convert stream into string
            vertexCode = vShaderStream.str();
            fragmentCode = fShaderStream.str();
            // if geometry shader path is present, also load a geometry shader
            if (geometryPath != nullptr)
            {
                gShaderFile.open(geometryPath);
                std::stringstream gShaderStream;
                gShaderStream << gShaderFile.rdbuf();
                gShaderFile.close();
                geometryCode = gShaderStream.str();
            }
        }
        catch (std::ifstream::failure& e)
        {
            std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
        }
        const char* vShaderCode = vertexCode.c_str();
        const char* fShaderCode = fragmentCode.c_str();
        // 2. compile shaders
        unsigned int vertex, fragment;
        // vertex shader
        vertex = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertex, 1, &vShaderCode, NULL);
        glCompileShader(vertex);
        checkCompileErrors(vertex, "VERTEX");
        // fragment Shader
        fragment = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragment, 1, &fShaderCode, NULL);
        glCompileShader(fragment);
        checkCompileErrors(fragment, "FRAGMENT");
        // if geometry shader is given, compile geometry shader
        unsigned int geometry;
        if (geometryPath != nullptr)
        {
            const char* gShaderCode = geometryCode.c_str();
            geometry = glCreateShader(GL_GEOMETRY_SHADER);
            glShaderSource(geometry, 1, &gShaderCode, NULL);
            glCompileShader(geometry);
            checkCompileErrors(geometry, "GEOMETRY");
        }
        // shader Program
        ID = glCreateProgram();
        glAttachShader(ID, vertex);
        glAttachShader(ID, fragment);
        if (geometryPath != nullptr)
            glAttachShader(ID, geometry);
        glLinkProgram(ID);
        checkCompileErrors(ID, "PROGRAM");
        // delete the shaders as they're linked into our program now and no longer necessery
        glDeleteShader(vertex);
        glDeleteShader(fragment);
        if (geometryPath != nullptr)
            glDeleteShader(geometry);

    }
//SHADER_H头文件部分
 void setVec4(const std::string& name, float x, float y, float z, float w)
    {
        glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w);
    }

后续会具体说明ImGui的使用流程等