创建GLFW窗口,开启OpenGL之路

前言:本系列文章主要是一个学习笔记和总结,具体学习过程参考https://learnopengl-cn.github.io/这个网站的是学习OpenGL的一个很完美的新手教程。在这个部分系列中,我会以自己的理解详细描述每个函数、方法的使用,以及关键参数的解释。

注意!!!本系列属于C/C++系列的OpenGL学习,不是python。但是学习明白原理后,使用其他语言应用也是大同小异。

使用软件为Visual Studio 2022。

废话少说,开始学习!

GLFW和GLAD

OpenGL并不为我们提供一个用于绘制图像的窗口,它将这些操作抽象(Abstract)出去,交给其他组件完成。所以我们需要自己创建用于显示绘制图形的窗口,这就使用到了GLFW。当然可以使用其他的类似的库,在不同平台上你可以使用的库也不同。

OpenGL驱动版本很多,其内部的多数函数位置都无法在编译的时候确定下来,需要在运行的时候查询,过程复杂,但是使用GLAD库就可以简化这个过程。

GLFW、GLAD配置参考https://blog.csdn.net/qq_41777179/article/details/138134059

下面我们来下载GLFW和GLAD,下载网址为:

GLAD下载地址:https://glad.dav1d.de/

GLFW下载地址:https://www.glfw.org/download.html

我们先来下载GLFW和GLAD:

下载完成后可以得到两个压缩包,解压得到:

这两个先放在一边,让我来使用Visual Studio 2022创建一个C++的控制台空项目

创建完成后,打开项目路径,在如下位置创建一个Linking文件夹,并在Linking文件夹内创建lib和include文件夹:

然后找到刚才解压的GLAD和glfw-3.4.bin.WIN64文件:

1、进入glfw-3.4.bin.WIN64文件夹内,选择合适的vc版本Visual Studio 2022就选lib-vc2022,然后将其复制到Linking/lib下,并改名为GLFW;

2、进入glfw-3.4.bin.WIN64文件夹内,将include下的GLFW复制到Linking/include下

3、进入GLAD文件夹内,将include下的glad和KHR复制到Linking/include下

4、进入GLAD文件夹内,将res复制到Linking/include下

用Visual Studio 2022打开刚才生成的空项目。

有两种简单的打开方法:

1、拖动项目文件下的.xln文件到Visual Studio 2022桌面图标上

2、打开VS2022后选择项目(曾经打开过)

打开后,找到左侧资源管理器中的文件项目,右击项目文件,点击属性:

选择VC++目录,修改包含目录,编辑为Linking/include文件夹所在位置:

同样修改库目录,将其改为Linking/lib文件夹所在位置,同上述一样。

随后选择链接器 -> 输入,添加两个附加依赖项:

1、GLFW\glfw3.lib

2、opengl32.lib(windows系统自带opengl库,x64也是opengl32.lib)

设置完后,选择两个位置为x64

然后需要添加现有项到项目:

1、项目路径\Linking\include\src\glad.c

2、项目路径\Linging\include\KHR\khrplatform.h

这样就配置完成了

程↗序↘,启→动↗!

cpp 复制代码
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>

static float vertices[] = {
    -0.5f, -0.5f, 0.0f,
    0.5f, -0.5f, 0.0f,
    0.0f, 0.5f, 0.0f
};

// 当用户改变窗口的大小的时候,视口也应该被调整。
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
    glViewport(0, 0, width, height);
}

void registerFunction(GLFWwindow* window) {
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
}

// 读取用户输入,当程序运行时,按下ESC时退出进程
void processInput(GLFWwindow* window) {
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
        glfwSetWindowShouldClose(window, true);
    }
}

GLFWwindow* windowInit() {
    // 实例化窗口
    // 初始化GLFW
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // 创建一个窗口对象,参数:宽、高、名称、*、*,函数返回一个GLFWwindow对象
    GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Window", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
    }
    // 通知GLFW将创建的窗口的上下文设置为当前线程的主上下文
    glfwMakeContextCurrent(window);

    // GLAD传入了用来加载系统相关的OpenGL函数指针地址的函数
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
        std::cout << "Failed to initialize GLAD" << std::endl;
    }

    // 通知OpenGL渲染窗口的尺寸大小------视口(Viewport)
    glViewport(0, 0, 800, 600);

    return window;
}

unsigned int VAOInit() {
    unsigned int VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    return VAO;
}

unsigned int VBOInit() {
    unsigned int VBO;
    glGenBuffers(1, &VBO);
    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);

    return VBO;
}

unsigned int vertexShaderInit() {
    // 顶点着色器源文件
    const char* vertexShaderSource =
        "#version 330 core\n"
        "layout(location = 0) in vec3 aPos;\n"
        "void main(){gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f);}\n";

    // 创建顶点着色器并编译
    unsigned int vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);

    // 返回顶点着色器对象
    return vertexShader;
}

unsigned int fragmentShaderInit() {
    // 顶点着色器源文件
    const char* fragmentShaderSource =
        "#version 330 core\n"
        "out vec4 FragColor;\n"
        "void main(){FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);}\n";

    // 创建顶点着色器并编译
    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);

    // 返回顶点着色器对象
    return fragmentShader;
}

unsigned int shaderProgramInit() {
    // 初始化着色器和着色器程序
    unsigned int vertexShader = vertexShaderInit();
    unsigned int fragmentShader = fragmentShaderInit();
    unsigned int shaderProgram = glCreateProgram();
    
    // 将着色器附加到着色器程序上
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);

    // 链接到着色器程序
    glLinkProgram(shaderProgram);
    
    // 激活着色器程序
    glUseProgram(shaderProgram);

    // 链接完删除着色器对象
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    return shaderProgram;
}

void render(unsigned int shaderProgram, unsigned int VAO) {
    // 设置清空颜色(重要!)
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    // 清空颜色缓冲区和深度缓冲区
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUseProgram(shaderProgram);
    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES, 0, 3);
}

int main()
{
    GLFWwindow* window = windowInit();

    // 注册函数framebuffer_size_callback,告知GLFW当窗口调整大小时调用这个函数
    registerFunction(window);
    
    unsigned int VAO = VAOInit();
    unsigned int VBO = VBOInit();
    unsigned int shaderProgram = shaderProgramInit();


    // glfwWindowShouldClose函数在我们每次循环的开始前检查一次GLFW是否被要求退出
    while (!glfwWindowShouldClose(window)) {
        // 输入
        processInput(window);
        
        // 渲染指令
        render(shaderProgram, VAO);

        // 检查并调用事件,交换缓冲
        // glfwSwapBuffers函数会交换颜色缓冲
        glfwSwapBuffers(window);
        // glfwPollEvents函数检查有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状并调用对应的回调函数
        glfwPollEvents();
    }

    // 渲染循环结束后我们需要正确释放/删除之前的分配的所有资源。
    glfwTerminate();

    return 0;
}

后面章节会一一介绍其中的函数,及其作用,运行结果如下:

相关推荐
扶尔魔ocy4 天前
【qt openGL入门笔记】OSG实现飞机模型在网格图上飞行并进行态势标绘(四)
qt·opengl·osg
:mnong5 天前
Web 三维可视化技术对比:ParaView Web vs 本项目 wasm + Three.js
前端·webgl·opengl·opencl·科学可视化
扶尔魔ocy6 天前
【qt openGL入门笔记】OSG实现显示飞机模型飞行的点迹(二)
qt·opengl·osg
扶尔魔ocy6 天前
【qt openGL入门笔记】OSG实现飞机模型在网格图上飞行(三)
opengl·osg
扶尔魔ocy7 天前
【qt openGL入门笔记】OSG实现飞机模型在网格图上飞行
qt·opengl·osg
扶尔魔ocy11 天前
【qt openGL入门笔记】FPS相机
qt·opengl
扶尔魔ocy11 天前
qt openGL入门笔记】FPS相机和轨道相机
qt·opengl
扶尔魔ocy13 天前
【qt openGL入门笔记】基础光照
qt·opengl
扶尔魔ocy13 天前
【qt openGL入门笔记】坐标系统和摄像机
qt·opengl
茉莉玫瑰花茶16 天前
OpenGL [ 纹理 ]
开发语言·c++·opengl