游戏引擎从零开始(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...

相关推荐
华溢澄13 小时前
macOS下基于Qt/C++的OpenGL开发环境的搭建
c++·qt·macos·opengl
Mr_1475 天前
【独游开发必备】游戏开发资源宝藏网站(美术篇)
游戏开发
Aoife婳5 天前
【Bug】UE5中纹理和地形一直闪烁
游戏开发
Kapaseker5 天前
大师级 Compose 图形编程—AGSL 入门
android·kotlin·opengl
龚子亦6 天前
【Unity开发】丧尸围城项目实现总结
unity·游戏引擎·游戏开发
小哈里9 天前
【Game-Infra】游戏开发的流程,游戏发布的打包与构建(硬件选型,SDK与操作系统,包体管理,弹性构建,构建调优)
游戏·游戏开发·后端开发·基础设施·打包构建·游戏发布·弹性构建
小强Fnsy9 天前
一款将GIF、序列帧的指定选区转换成新的序列帧,并导出为Plist、PNG、GIF的工具
前端·游戏开发
Thomas游戏开发13 天前
Unity Android性能优化设置指南
前端框架·unity3d·游戏开发
腾讯云云开发13 天前
AI编程能做什么?9个优秀案例,手把手图文教程,部分实战作品已开源
ai编程·游戏开发·小程序·云开发
黑客影儿13 天前
在Godot中为您的游戏添加并控制游戏角色的完整技术指南
开发语言·游戏·游戏引擎·godot·gdscript·游戏开发·3d游戏