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

相关推荐
六bring个六2 天前
图形渲染+事件处理最终版
c++·qt·图形渲染·opengl
星火撩猿3 天前
OpenGl实战笔记(3)基于qt5.15.2+mingw64+opengl实现光照变化效果
笔记·qt·opengl·光照效果
星火撩猿3 天前
OpenGl实战笔记(2)基于qt5.15.2+mingw64+opengl实现纹理贴图
笔记·qt·opengl·纹理贴图
程序员爱德华4 天前
计算机图形学中的深度学习
图形学·opengl
:mnong5 天前
开放原子大赛石油软件赛道参赛经验分享
c++·qt·hdfs·开放原子·图形渲染·webgl·opengl
北冥没有鱼啊5 天前
UE 像素和线框盒子 材质
c++·ue5·游戏开发·虚幻·材质
大飞pkz6 天前
【Unity】使用XLua进行热修复
unity·c#·游戏引擎·lua·游戏开发·xlua·lua热修复
工藤新一¹7 天前
C++/SDL 进阶游戏开发 —— 双人塔防(代号:村庄保卫战 19)
开发语言·c++·游戏引擎·游戏开发·sdl
大飞pkz10 天前
【Unity】使用XML进行数据读存的简单例子
xml·unity·c#·游戏引擎·游戏开发·数据读写
大飞pkz10 天前
【Unity】如何解决UI中的Button无法绑定带参数方法的问题
ui·unity·游戏引擎·游戏开发·开发记录·button绑定