Modern OpenGL(Glad)

引言

上一节讨论图层时制作了整个图层堆栈系统,今天我们尝试引入现代 OpenGL 为之后的实时 GUI 准备。

为项目加入图形显示和 GUI 是一件令人愉悦的事情,因为我们可以看到信息、调整数值,毕竟我们不能总是为了某些数值调整而重新编译整个项目,一个小滑块就可以解决。

我们需要一种方法来实际使用现代图形 API:OpenGL(最终这个项目会支持所有的图形 API 如 DirectX11 或 Vulkan,但 OpenGL 的跨平台性和易用性让我们考虑优先实现)。所以现在我们需要添加以 C++ 代码驱动 GPU 的现代 OpenGL 功能,因此希望能够调用存储在我们图形驱动程序中的函数(事实上之前我们已经使用了 GLFW,与之前不同,我们会使用一种叫“Glad”的东西)。

Glad 配置

GLAD是继GL3W,GLEW之后,当前最新的用来访问 OpenGL 规范接口的第三方库。好的,我们首先进入 Glad 网站:

选择 4.6 OpenGL 版本,Profile 更改为 Core

生成一个网页包:https://glad.dav1d.de/generated/tmpj1wnkvqcglad/,点击 glad.zip 下载它:

接着我们在 /Infinite/Infinite/vendor 中新建 GLAD 文件夹,放入解压后的文件。

预生成文件

现在我们把新的 glad 引入预生成文件中:

workspace "Infinite"
architecture "x64"
startproject "Sandbox"

configurations
{
"Debug",
"Release",
"Dist"
}

outputdir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}"

-- Include directories relative to root folder (solution directory)
IncludeDir = {}
IncludeDir["GLFW"] = "Infinite/vendor/GLFW/include"
+IncludeDir["GLAD"] = "Infinite/vendor/GLAD/include"

include "Infinite/vendor/GLFW"
+include "Infinite/vendor/GLAD"

project "Infinite"
location "Infinite"
kind "SharedLib"
language "C++"

targetdir ("bin/" .. outputdir .. "/%{prj.name}")
objdir ("bin-int/" .. outputdir .. "/%{prj.name}")

pchheader "ifnpch.h"
pchsource "Infinite/src/ifnpch.cpp"

files
{
"%{prj.name}/src/**.h",
"%{prj.name}/src/**.cpp"
}

includedirs
{
"%{prj.name}/src",
"%{prj.name}/vendor/spdlog/include",
"%{IncludeDir.GLFW}"
+ "%{IncludeDir.GLAD}"
}

links
{
"GLFW",
+ "GLAD",
"opengl32.lib"
}

filter "system:windows"
cppdialect "C++17"
staticruntime "On"
systemversion "latest"

defines
{
"IFN_PLATFORM_WINDOWS",
"IFN_BUILD_DLL"
}

postbuildcommands
{
("{COPY} %{cfg.buildtarget.relpath} ../bin/" .. outputdir .. "/Sandbox")
}

filter "configurations:Debug"
defines "IFN_DEBUG"
buildoptions "/MDd"
symbols "On"

filter "configurations:Release"
defines "IFN_RELEASE"
buildoptions "/MD"
optimize "On"

filter "configurations:Dist"
defines "IFN_DIST"
buildoptions "/MD"
optimize "On"



project "Sandbox"
location "Sandbox"
kind "ConsoleApp"

language "C++"

targetdir ("bin/" .. outputdir .. "/%{prj.name}")
objdir ("bin-int/" .. outputdir .. "/%{prj.name}")

files
{
"%{prj.name}/src/**.h",
"%{prj.name}/src/**.cpp"
}

includedirs
{
"Infinite/vendor/spdlog/include",
"Infinite/src/Infinite",
"Infinite/src/Events"
}

links
{
"Infinite"
}

filter "system:windows"
cppdialect "C++17"
staticruntime "On"
systemversion "latest"

defines
{
"IFN_PLATFORM_WINDOWS"
}

filter "configurations:Debug"
defines "IFN_DEBUG"
buildoptions "/MDd"
symbols "On"

filter "configurations:Release"
defines "IFN_RELEASE"
buildoptions "/MD"
optimize "On"

filter "configurations:Dist"
defines "IFN_DIST"
buildoptions "/MD"
optimize "On"

复制 Infinite/vendor/GLFWpremake5GLAD 中修改:

project "GLAD"
kind "StaticLib"
language "C"

targetdir ("bin/" .. outputdir .. "/%{prj.name}")
objdir ("bin-int/" .. outputdir .. "/%{prj.name}")

files
{
"include/glad/glad.h",
"include/KHR/khrplatform.h",
"src/glad.c"
}

includedirs
{
"include"
}

filter "system:windows"
systemversion "latest"
staticruntime "On"

filter { "system.windows", "configurations:Release" }
buildoptions "/MT"

最终我们在 VisualStudio 中成功引入了 glad:

调试

最后我们对原有的 Application.cpp 进行一些修改:

#include "Events/ApplicationEvent.h"
#include "Log.h"

-#include <GLFW/glfw3.h>
+#include <glad/glad.h>

namespace Infinite {

namespace Infinite {
{
m_Window = std::unique_ptr<Window>(Window::Create());
m_Window->SetEventCallback(BIND_EVENT_FN(OnEvent));

+ int id;
+ glGenVertexArrays(1, &id);
}

Application::~Application() {}

让我们试试 gladLoadGLLoader()int gladLoadGLLoader(GLADloadproc load):任何的OpenGL接口调用都必须在初始化 GLAD 库后才可以正常访问。如果成功的话,该接口将返回 GL_TRUE,否则就会返回 GL_FALSE

其中 GLADloadproc 函数声明如下:void* (*GLADloadproc)(const char* name)

#include "Infinite/Events/MouseEvent.h"
#include "Infinite/Events/KeyEvent.h"

#include <GLAD/glad.h>

namespace Infinite {

static bool s_GLFWInitialized = false;
.....

m_Window = glfwCreateWindow((int)props.Width, (int)props.Height, m_Data.Title.c_str(), nullptr, nullptr);
glfwMakeContextCurrent(m_Window);
+ int status = gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
+ IFN_CORE_ASSERT(status, "Failed to initialize GLAD!");
glfwSetWindowUserPointer(m_Window, &m_Data);
SetVSync(true);

最后成功启动项目,代表引入 GLAD 成功。