游戏引擎从零开始(28)-windowResize

本章节,我们实现window的resize的效果,更改窗口大小时,设置viewport。

windowResize

事件传递的路径:

  1. Application::OnWindowResize
  2. Renderer::OnWindowResize
  3. RenderCommand::SetViewport
  4. 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...

相关推荐
茉莉玫瑰花茶12 小时前
OpenGL [ 纹理 ]
开发语言·c++·opengl
甲维斯1 天前
Opus5.5大考!做一个赛车游戏"秋名山车神"
人工智能·游戏开发
鑫鑫哥adam4 天前
一个 1x1 贴图,是怎么炸掉整个热更包的?
unity3d·游戏开发
Behavior4 天前
Unity 手游动态更换 App 图标 — Android 与 iOS 双端技术方案
c#·unity3d·游戏开发
SmalBox5 天前
03-03-架构篇-Runtime加载系统架构
unity3d·游戏开发
SmalBox5 天前
03-02-架构篇-Editor打包系统架构
unity3d·游戏开发
Yeah1275 天前
当 LLM 进入游戏玩法:从收权到放权
游戏开发
Behavior5 天前
Unity 手游 iOS Deep Link 唤醒全流程:从 URL Scheme / Universal Links 到 C# 层参数投递
c#·unity3d·游戏开发
SmalBox5 天前
03-01-架构篇-整体架构总览
unity3d·游戏开发
RobinDevNotes5 天前
用 godot-rust 给 Godot 写 Rust 扩展
rust·游戏开发