【OpenGL】窗口的创建

从今天开始我们开始学习OpenGL,从0开始,当然是有C++基础的前提

首先包含glad和GLFW的头文件

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>

初始化 GLFW

在 main 函数中,我们首先使用 glfwInit 初始化 GLFW,然后我们可以使用 glfwWindowHint 配置 GLFW,这个配置的选项和含义可以在GLFW:窗口指南里面找到非常详细的解释,这个还是当成工具查阅就行,我们真正要操作的地方不在窗口初始化这里

int main() {
    glfwInit();  // 初始化GLFW
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // 指定创建的内容必须兼容的客户端 API 版本
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // 指定创建的内容必须兼容的客户端 API 版本
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 指定要为其创建内容的 OpenGL 配置文件
    //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 指定 OpenGL 内容是否应向前兼容

    return 0;
}

创建窗口对象

接下来,我们需要创建一个窗口对象,glfwCreateWindow 函数前两个参数是窗口的宽度和高度,第三个参数是窗口的名称,后面两个参数的作用可以在GLFW:窗口指南找到

glfwMakeContextCurrent(window)告诉 GLFW 将窗口的内容作为当前线程上的主要内容

    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);

初始化 GLAD

GLAD 管理 OpenGL 的函数指针,需要在调用任何 OpenGL 函数之前初始化 GLAD,我们向 GLAD 传递函数以加载特定于操作系统的 OpenGL 函数指针的地址,GLFW 为我们提供了glfwGetProcAddress,它根据我们编译的操作系统定义了正确的函数

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

渲染窗口调整 

用glViewport设置 OpenGL 渲染窗口的大小,前两个参数设置窗口左下角的位置,第三个和第四个参数以像素为单位设置渲染窗口的宽度和高度,如果视口尺寸设置为小于 GLFW 尺寸的值;然后,所有 OpenGL 渲染都将显示在一个较小的窗口中

glViewport(0, 0, 800, 600);

当用户调整窗口大小时,视口也应该进行相应的调整,注册一个函数将 GLFWwindow 作为其第一个参数,并将两个表示新窗口尺寸的整数作为其第一个参数

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

告诉 GLFW,通过注册它来在每次调整窗口大小时调用此函数

glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);  

渲染循环

创建一个 while 循环,称之为渲染循环,它一直运行,直到我们告诉 GLFW 停止,

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

glfwWindowShouldClose 函数在每次循环迭代开始时检查是否已指示 GLFW 关闭。如果是这样,函数将返回并且渲染循环停止运行,之后我们可以关闭应用程序

glfwSwapBuffers 将交换在此渲染迭代期间用于渲染的颜色缓冲区(一个大型 2D 缓冲区,其中包含 GLFW 窗口中每个像素的颜色值),并将其显示为输出到屏幕

双缓冲区

当应用程序在单个缓冲区中绘制时,生成的图像可能会显示闪烁问题。这是因为生成的输出图像不是瞬间绘制的,而是逐像素绘制的,通常从左到右和从上到下绘制。

由于此图像在呈现时不会立即显示给用户,因此结果可能包含伪影。为了规避这些问题,窗口化应用程序应用双缓冲区进行渲染。

前端缓冲区包含屏幕上显示的最终输出图像,而所有渲染命令都绘制到后端缓冲区。

一旦所有渲染命令都完成,我们就会将后面的缓冲区交换到前面的缓冲区,这样就可以显示图像,而不必仍然渲染到其中,从而删除了所有上述伪影。

glfwPollEvents 函数检查是否触发了任何事件(如键盘输入或鼠标移动事件),更新窗口状态,并调用相应的函数(我们可以通过回调方法注册)

一旦我们退出渲染循环,我们希望正确地清理/删除所有已分配的 GLFW 资源。我们可以通过在主函数末尾调用的 glfwTerminate 函数来做到这一点

glfwTerminate();
return 0;

编译运行

如果一切顺利,那么运行程序我们会看到一个黑色窗口

如果不行,请看全部源代码分析

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include<iostream>
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    glViewport(0, 0, width, height);
}
int main() {
    glfwInit();  // 初始化窗口
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // 指定创建的内容必须兼容的客户端 API 版本
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // 指定创建的内容必须兼容的客户端 API 版本
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 指定要为其创建内容的 OpenGL 配置文件
    //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 指定 OpenGL 上下文是否应向前兼容
    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); // 注册窗口调整调用函数
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
    while(!glfwWindowShouldClose(window))
    {
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    glfwTerminate();
    return 0;
}

如果想换个颜色的话,可以使用 glClearColor 指定要清除屏幕的颜色,每当我们调用 glClear 并清除颜色缓冲区时,整个颜色缓冲区都将填充 glClearColor 配置的颜色,其中颜色的选项是rgb和透明度四个通道参数

    glClearColor(0.0f,0.5f,0.5f,1.0f);
    while(!glfwWindowShouldClose(window))
    {
        glClear(GL_COLOR_BUFFER_BIT);
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    glfwTerminate();

猜你喜欢

转载自blog.csdn.net/weixin_62264287/article/details/134795394
今日推荐