本章节,我们实现window的resize的效果,更改窗口大小时,设置viewport。
windowResize
事件传递的路径:
- Application::OnWindowResize
- Renderer::OnWindowResize
- RenderCommand::SetViewport
- OpenGLRendererAPI::SetViewport
Application增加OnWindowResize,增加m_Minimized字段,当窗口缩小到0时,不做渲染处理。
c++
private:
bool OnWindowClose(WindowCloseEvent& e);
bool OnWindowResize(WindowResizeEvent& e);
private:
Scope<Window> m_Window;
ImGuiLayer* m_ImGuiLayer;
bool m_Running = true;
// 最小化标记,此时不做渲染
bool m_Minimized = false;
LayerStack m_LayerStack;
float m_LastFrameTime = 0;
Sandbox/Hazel/src/Hazel/Application.cpp
c++
void Application::OnEvent(Event &e) {
EventDispatcher dispatcher(e);
dispatcher.Dispatch<WindowCloseEvent>(BIND_EVENT_FN(OnWindowClose));
// 增加windowResize事件分发
dispatcher.Dispatch<WindowResizeEvent>(BIND_EVENT_FN(OnWindowResize));
...
}
bool Application::OnWindowResize(Hazel::WindowResizeEvent &e) {
if (e.GetWidth() == 0 || e.GetHeight() == 0) {
m_Minimized = true;
return false;
}
m_Minimized = false;
uint32_t pixelWidth = e.GetWidth(), pixelHeight = e.GetHeight();
m_Window->GetPixelSize(pixelWidth, pixelHeight);
HZ_INFO("width = {0}, height = {1}, pixelWidth = {2}, pixelHeight = {3}", e.GetWidth(), e.GetHeight(), pixelWidth, pixelHeight);
Renderer::OnWindowResize(pixelWidth, pixelHeight);
return false;
}
void Application::Run() {
while (m_Running) {
float time = glfwGetTime();
Timestep timestep = time - m_LastFrameTime;
m_LastFrameTime = time;
if (!m_Minimized) {
for (Layer *layer: m_LayerStack) {
layer->OnUpdate(timestep);
}
}
...
}
}
...
注意!!OpenGL的setViewport方法宽高设置的是像素,glfw的size改变回调中传回来的是坐标,mac的retina屏幕像素是坐标的两倍,参考下图中日志。
通过glfwGetFramebufferSize方法将坐标转换成像素值。参考stackoverflow帖子:
Why retina screen coordinate value is twice the value of pixel value
Window中增加获取真实像素值的接口,WindowsWindow中增加实现
Sandbox/Hazel/src/Hazel/Core/Window.h
c++
virtual void GetPixelSize(uint32_t& width, uint32_t& height) const {
width = GetWidth();
height = GetHeight();
};
Sandbox/Hazel/src/Hazel/Platform/Windows/WindowsWindow.h
c++
namespace Hazel{
class WindowsWindow : public Window{
public:
void GetPixelSize(uint32_t& width, uint32_t& height) const override;
WindowsWindow(const WindowProps& props);
virtual ~WindowsWindow();
...
}
}
Sandbox/Hazel/src/Hazel/Platform/Windows/WindowsWindow.cpp
c++
void WindowsWindow::GetPixelSize(uint32_t& width, uint32_t& height) const {
glfwGetFramebufferSize(m_Window, reinterpret_cast<int *>(&width), reinterpret_cast<int *>(&height));
}
按顺序,整个调用链条上的类,都需要增加OnWindowResize接口
Sandbox/Hazel/src/Hazel/Renderer/Renderer.h
c++
static void OnWindowResize(uint32_t width, uint32_t height);
Sandbox/Hazel/src/Hazel/Renderer/Renderer.cpp
c++
void Renderer::OnWindowResize(uint32_t width, uint32_t height) {
RenderCommand::SetViewport(0, 0, width, height);
}
Sandbox/Hazel/src/Hazel/Renderer/RenderCommand.h
c++
inline static void SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
s_RendererAPI->SetViewport(x, y, width, height);
}
Sandbox/Hazel/src/Hazel/Renderer/RendererAPI.h
c++
virtual void SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) = 0;
Sandbox/Hazel/src/Hazel/Platform/OpenGL/OpenGLRendererAPI.h
c++
#include "Renderer/RendererAPI.h"
namespace Hazel {
class OpenGLRendererAPI : public RendererAPI{
public:
...
void Init() override;
void SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override;
};
}
Sandbox/Hazel/src/Hazel/Platform/OpenGL/OpenGLRendererAPI.cpp
c++
void OpenGLRendererAPI::SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
// mac 屏幕上有问题,不知道为啥
glViewport(x, y, width, height);
}
完整代码参考:
github.com/summer-go/H...
代码维护
最后花一点时间,整理下整个工程的代码,将src/Hazel中的大部分文件挪到src/Hazel/Core下
完整代码参考:
github.com/summer-go/H...