前语
终于,到了能够看到界面的阶段了。
根据glad和GLFW来构建渲染上屏的功用。
咱们了解的OpenGL只是一套图形规范,GL版别很多,函数的地址无法在编译时确定下来,需求运行时查询,寻址的办法和渠道相关。
比如在Windows渠道上请求一段buffer的操作如下,代码显的很冗余。每个GL的API调用都如此,会有大量的重复的逻辑。
// 界说函数原型
typedef void (*GL_GENBUFFERS) (GLsizei, GLuint*);
// 找到正确的函数并赋值给函数指针
GL_GENBUFFERS glGenBuffers = (GL_GENBUFFERS)wglGetProcAddress("glGenBuffers");
// 现在函数能够被正常调用了
GLuint buffer;
glGenBuffers(1, &buffer);
这儿引进glad库处理这个问题
引进glad
glad是一个开源库,处理OpenGL API查询的繁琐问题。
进入glad官网: glad.dav1d.de/
挑选需求的版别,装备好
挑选Generate a loader,点击generate,下载glad.zip,里边有头文件和cpp源码
将头文件目录copy到工程Platform下,glad.h放到Windows下
更新引擎CMake文件,Hazel/CMakeLists.txt:
# 添加glad的头文件和源码
set(SRC_LIST
...
src/Hazel/glad.c
)
# 添加源码
target_include_directories(${PROJECT_NAME} PUBLIC
...
src/Hazel/Platform/include
)
留意!target_include_directories办法里要设置成PUBLIC,如果设置成PRIVATE,则引擎中include的头文件无法传递给业务方,即Sanbox拜访不到这儿include的头文件。
OK!glad装备好了,咱们接着装备GLFW
GLFW装备
OpenGL能够看成是一套根据GPU API的数学核算东西,可是并不能和屏幕设备打交道。
需求引进专门的处理窗口的东西-GLFW,类似的东西层还有SDL、Android渠道的EGL、苹果渠道的EAGL。
GLFW是开源的、多渠道库,支撑OpenGL、GLes、Vulkan开发,用简略的API就能创建windows、contexts和surfaces,还支撑输入事情的处理。
有多种GLFW的装备办法,这儿讲一种我运用的,相对简略、通用的。
- 下载GLFW
进入根目录执行命令,下载GLFW到vendor目录,你也能够进入glfw官网手动下载。这儿采用submodule的方式安排第三方库,将三方库从引擎工程总剥离,工程更简练清爽。
git submodule add https://github.com/TheCherno/glfw Sandbox/Hazel/vendor/GLFW
.gitmodules主动添加了一项GLFW装备
[submodule "Sandbox/Hazel/vendor/GLFW"]
path = Sandbox/Hazel/vendor/GLFW
url = https://github.com/TheCherno/glfw
2. CMake中更新GLFW装备
咱们下载的是源码,需求参与编译
# 编译子项目 GLFW
add_subdirectory(vendor/GLFW)
# 链接glfw库
target_link_libraries(${PROJECT_NAME} glfw)
# 添加glfw include地址
target_include_directories(${PROJECT_NAME} PUBLIC
...
vendor/GLFW/include
)
OK!窗口相关的环境装备好了,进入正式的编码环节了
Window笼统与完成
设计一个基类Window,笼统出窗口的基本特点和接口,再派生出Windows渠道的窗口类WindowsWindow,当然还可能有其他的渠道,咱们暂不完成。
- WindowProps:描述窗口宽高、title等特点
- OnUpdate():每次tick的时分更新
- GetWidth()、GetHeight():获取宽高
- SetEventCallback():设置事情处理的回调,需求设置进GLFW
- SetVsync():设置强制同步
- IsVSync():查询是否强制同步
声明一个静态的创建Window的函数:
static Window* Create();
由各个具体的渠道去完成,在Application层调用。
完好代码如下: Haze./src/Hazel/Core/Window.h
#ifndef SANBOX_WINDOW_H
#define SANBOX_WINDOW_H
#include "../Core.h"
#include "Event.h"
namespace Hazel {
struct WindowProps {
std::string Title;
unsigned int Width;
unsigned int Height;
// 默认参数需求手动转成(std::string&)类型
WindowProps(const std::string& title = (std::string&)("Hazel Engine"),
unsigned int width = 1280,
unsigned int height = 720)
: Title(title), Width(width), Height(height) {
}
};
class Window {
public:
using EventCallbackFn = std::function<void(Event&)>;
virtual ~Window() = default;
virtual void OnUpdate() = 0;
virtual unsigned int GetWidth() const = 0;
virtual unsigned int GetHeight() const = 0;
// Window attributes
virtual void SetEventCallback(const EventCallbackFn& callback) = 0;
virtual void SetVSync(bool enabled) = 0;
virtual bool IsVSync() const = 0;
static Window* Create(const WindowProps& props = WindowProps());
};
}
#endif //SANBOX_WINDOW_H
Windows下的Window完成
这儿根据OpenGL完成的,其实也是跨渠道的,如果后边切换成directX,则就真的是Windows渠道独有的。
在Hazel/src/Hazel/Platform/Windows目录下新建WindowsWindow.h WindowsWindow.cpp文件
这两个文件能够参考我提交的代码WindowsWindow.h、WindowsWindow.cpp
里边完成了Windows中界说的虚函数。不做过多解说,需求留意的几点:
- WindowsWindow类封装了GLFWwindow,这是实在的窗口
- glad会和GLFW冲突,需求将glad放到GLFW前面include
#include "Window.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
- glfw的运用不同的渠道上有点差异,mac上需求额外加一行代码兼容
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
- glad初始化要放到glfwMakeContextCurrent调用之后
glfwMakeContextCurrent(m_Window);
glfwSetWindowUserPointer(m_Window, &m_Data);
- 笔直同步 SetVSync(true)调用了glfwSwapInterval(1),表明只有窗口缓冲中数据更新了才swap数据上屏,否则每次都会进行swap上屏操作。
void WindowsWindow::SetVSync(bool enabled) {
if (enabled) {
glfwSwapInterval(1);
} else {
glfwSwapBuffers(0);
}
m_Data.VSync = enabled;
}
Application中添加窗口
在Application结构函数中创建窗口,在Run函数中更新窗口
别的地方不需求持有Window,咱们用unique_ptr智能指针包装Window.
在Run的While循环中,调用m_Window->OnUpdate(),这儿咱们制作一个空白的窗口,背景颜色设置为绿色
#include "Application.h"
#include "ApplicationEvent.h"
#include "Log.h"
#include <glad/glad.h>
namespace Hazel{
Application::Application() {
m_Window = std::unique_ptr<Window>(Window::Create());
}
void Application::Run() {
...
while(m_Running) {
glClearColor(0, 1, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
m_Window->OnUpdate();
}
}
}
没问题的话,你应该能看到一个纯绿色的窗口
OK!总算迈进了一大步~~
这章节完好代码参考: 窗口笼统与完成