创建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;
}

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

相关推荐
AJi1 天前
EGL使用记录
前端·opengl
华溢澄3 天前
macOS下基于Qt/C++的OpenGL开发环境的搭建
c++·qt·macos·opengl
Kapaseker8 天前
大师级 Compose 图形编程—AGSL 入门
android·kotlin·opengl
onthewaying1 个月前
详解 Android GLSurfaceView 与 Renderer:开启你的 OpenGL ES 之旅
android·opengl
灿烂阳光g1 个月前
OpenGL Camera
opengl
用户619533334171 个月前
为ChatGPT和API集成构建MCP服务器
openai·opengl
哈市雪花1 个月前
添加捕捉吸附标识(使用QT+OpenGL开发三维CAD)
qt·教程·opengl·cad·绘制·工业软件·捕捉吸附
爱看书的小沐2 个月前
【小沐学GIS】基于Rust绘制三维数字地球Earth(Rust、OpenGL、GIS)
3d·rust·gis·opengl·cargo·earth·3d earth
爱看书的小沐2 个月前
【小沐杂货铺】基于Three.JS绘制汽车展示Car(WebGL、vue、react、autoshow、提供全部源代码)
汽车·vue3·react·webgl·three.js·opengl·autoshow