让我们试试能不能让GLFW正常工作-Linux基础教程

让我们看看我们是否可以让 GLFW 工作。首先,创建一个新的 .cpp 文件并将以下代码粘贴到文件顶部。

#include 
#include 

确保在包含 GLFW 标头之前包含 GLAD 标头。GLAD 的头文件包含正确的 OpenGL 头文件(例如 GL/gl.h),因此需要在任何其他依赖于 OpenGL 的头文件之前包含 GLAD。接下来我们创建主函数,我们将在其中实例化 GLFW 窗口:

int main()
{
    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);
    return 0;
}

首先我们在main函数中调用glfwInit函数来初始化GLFW,然后我们可以使用glfwWindowHint函数来配置GLFW。glfwWindowHint函数的第一个参数代表选项的名称,我们可以从很多以GLFW_开头的枚举值中选择;第二个参数接受一个整数,用于设置该选项的值。这个函数的所有选项和对应的值都可以在 GLFW 的窗口处理文档中找到。如果你现在编译你的 cpp 文件,你会得到很多未定义的引用错误,这意味着你没有成功链接 GLFW 库。

由于本站的教程都是基于OpenGL3.3版本的,所以我们需要告诉GLFW我们要使用的OpenGL版本是3.3,这样GLFW会在创建的时候做出相应的动作OpenGL 上下文调整。这也确保了用户无法在没有适当的 OpenGL 版本支持的情况下运行。我们将 Major 和 Minor 都设置为 3。我们还明确告诉 GLFW 我们正在使用 Core-profile。明确告诉 GLFW 我们需要使用核心模式意味着我们只能使用 OpenGL 功能的子集(没有我们不再需要的向后兼容功能)。如果您使用的是 Mac OS X,您还需要在初始化代码中添加以下代码行以使这些配置生效(取消注释上述代码):

glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

请确保您的系统支持 OpenGL3.3 或更高版本,否则此应用程序可能会崩溃或出现不可预知的错误。如果您想检查 OpenGL 版本,请在 Linux 上运行 glxinfo游戏颜色代码怎么输入,或在 Windows 上使用其他工具(例如 OpenGL Extension Viewer)。如果你的OpenGL版本低于3.3,检查显卡是否支持OpenGL3.3+(如果不支持,你的显卡真的太老了),更新驱动,有必要如果所以,请更新显卡。

接下来我们创建一个窗口对象,该对象存储所有与窗口相关的数据,并且经常被其他 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);

glfwCreateWindow 函数将窗口的宽度和高度作为其前两个参数。第三个参数代表这个窗口的名称(标题),这里我们使用“LearnOpenGL”,当然你可以使用任何你喜欢的名称。我们暂时忽略最后两个参数。此函数将返回一个 GLFWwindow 对象,我们将在其他 GLFW 操作中使用该对象。创建窗口后,我们可以通知 GLFW 将我们窗口的上下文设置为当前线程的主上下文。

高兴的

前面教程中提到,GLAD是用来管理OpenGL函数指针的,所以我们需要在调用任何OpenGL函数之前初始化GLAD。

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

我们向 GLAD 传递一个函数来加载系统特定的 OpenGL 函数指针的地址。GLFW 给我们的是 glfwGetProcAddress,它根据我们正在编译的系统定义正确的函数。

视口

在我们开始渲染之前还有一件很重要的事情,我们必须告诉OpenGL渲染窗口的大小,也就是Viewport,这样OpenGL才能知道如何根据窗口的大小来显示数据和坐标。我们可以通过调用 glViewport 函数来设置窗口的 Dimension:

glViewport(0, 0, 800, 600);

glViewport函数的前两个参数控制窗口左下角的位置。第三个和第四个参数控制渲染窗口的宽度和高度(像素)。

我们实际上可以将视口尺寸设置为小于 GLFW 尺寸,这样所有的 OpenGL 渲染图都会显示在一个更小的窗口中,这样我们也可以在嘴外的 OpenGL 视口中显示一些其他元素。

在幕后,OpenGL 使用 glViewport 中定义的位置和宽度和高度来转换 2D 坐标,并将 OpenGL 中的位置坐标转换为您的屏幕坐标。例如,OpenGL 中的坐标 (-0.5, 0.5) 可能(最终)映射到屏幕中的坐标 (200,450)。注意处理过去OpenGL 坐标范围仅从 -1 到 1,因此我们实际上将坐标范围内的 (-1 到 1) 映射到 (0, 800) 和 (0, 600)@) >。

但是,当用户调整窗口大小时,视口也应该调整大小。我们可以向窗口注册一个回调函数(Callback Function),每次调整窗口大小时都会调用该回调函数。这个回调函数的原型如下:

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

此帧缓冲区大小函数将 GLFWwindow 作为其第一个参数,并使用两个整数表示窗口的新尺寸。每当调整窗口大小时,GLFW 都会调用该函数并填写适当的参数供您处理。

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

我们还需要注册这个函数来告诉 GLFW 我们希望在调整窗口大小时调用这个函数:

glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

首次显示窗口时也会调用 framebuffer_size_callback。对于 Retina 显示器,宽度和高度都将显着高于原始输入值。

图片[1]-让我们试试能不能让GLFW正常工作-Linux基础教程-老王博客

我们还可以使用许多其他回调函数注册我们的函数。例如,我们可以创建一个回调函数来处理输入更改、处理错误消息等。我们在创建窗口之后、渲染循环初始化之前注册这些回调。

准备好你的引擎

我们不希望我们的应用程序在绘制图像后立即退出并关闭窗口。我们希望程序继续绘制图像并能够接受用户输入,直到我们主动关闭它。因此,我们需要在程序中添加一个while循环游戏颜色代码怎么输入,我们可以称之为Render Loop,它会一直运行直到我们让GLFW退出。以下代码行实现了一个简单的渲染循环:

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

双缓冲器

当应用程序使用单缓冲绘图时,可能会出现图像闪烁问题。这是因为生成的图像不是一次绘制的,而是从左到右、从上到下逐个像素地绘制的。最终的图像不是瞬间显示给用户的,而是一步一步生成的,导致渲染非常不真实。为了规避这些问题,我们将双缓冲应用于渲染窗口应用程序。前端缓冲区保存最终输出的图像,显​​示在屏幕上;所有渲染指令都绘制在后台缓冲区上。当所有的渲染指令都执行完后,我们交换(Swap)前缓冲区和后缓冲区,使图像立即渲染,消除了前面提到的不真实感。

最后一件事

当渲染循环结束时,我们需要正确释放/删除所有先前分配的资源。我们可以通过在主函数末尾调用 glfwTerminate 函数来做到这一点。

glfwTerminate();
return 0;

这会清理所有资源并正确退出应用程序。现在您可以尝试编译并运行您的应用程序,如果您没有做错任何事情,您将看到如下输出:

如果您看到一个非常无聊的黑色窗口,那您是对的!

进入

我们还希望能够在 GLFW 中实现一些输入控制,这可以通过使用 GLFW 的几个输入函数来完成。我们将使用 GLFW 的 glfwGetKey 函数,它接受一个窗口和一个键作为输入。该函数将返回按键是否被按下。我们将创建一个 processInput 函数来保持所有输入代码的干净。

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

这里我们检查用户是否按下了返回键(Esc)(如果没有,glfwGetKey 将返回 GLFW_RELEASE。如果用户确实按下了返回键,我们通过 glfwSetwindowShouldClose 关闭 GLFW,并将 WindowShouldClose 属性设置为 true。下一次while 循环的条件检查将失败,程序将关闭。

我们接下来在渲染循环的每次迭代中调用 processInput:

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

这为我们提供了一种非常简单的方法来检测是否按下了特定键并在每一帧都执行此操作。

使成为

我们将把所有的渲染操作放到渲染循环中,因为我们希望这些渲染指令在每次渲染循环迭代时执行。代码将是这样的:

// 渲染循环
while(!glfwWindowShouldClose(window))
{
    // 输入
    processInput(window);
    // 渲染指令
    ...
    // 检查并调用事件,交换缓冲
    glfwPollEvents();
    glfwSwapBuffers(window);
}

为了测试一切正常,我们使用自定义颜色清除屏幕。在每次新的渲染迭代开始时,我们总是希望清屏,否则我们仍然可以看到上一次迭代的渲染结果(这可能是您想要的,但通常不是)。我们可以通过调用glClear函数来清除屏幕的颜色缓冲区,该函数接受一个缓冲区位(Buffer Bit)来指定要清除的缓冲区。可能的缓冲区位是 GL_COLOR_BUFFER_BIT、GL_DEPTH_BUFFER_BIT 和 GL_STENCIL_BUFFER_BIT。由于现在我们只关心颜色值,我们只需清空颜色缓冲区。

glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

注意,除了glClear,我们还调用glClearColor来设置用来清屏的颜色。当调用 glClear 函数清除颜色缓冲区时,整个颜色缓冲区将被 glClearColor 中设置的颜色填充。在这里,我们将屏幕设置为像黑板一样的深蓝绿色。

你应该记得在我们的 OpenGL 教程中,glClearColor 函数是一个状态设置函数,而 glClear 函数是一个状态使用函数,它使用当前状态来获取应该被清除的颜色。

好的,现在我们准备开始向渲染循环添加大量渲染调用,但这是下一个教程,已经太多了。

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论