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

相关推荐
Winston-Tao4 天前
skynet 源码阅读 -- 核心概念服务 skynet_context
lua·游戏开发·c 语言·skynet·游戏服务器框架
Winston-Tao6 天前
Skynet实践之「Lua C 模块集成—优先级队列」
c语言·lua·游戏开发·skynet·游戏服务器框架
Uncertainty!!7 天前
On to OpenGL and 3D computer graphics
c++·opengl·cg
刘好念10 天前
[OpenGL]实现屏幕空间环境光遮蔽(Screen-Space Ambient Occlusion, SSAO)
c++·计算机图形学·opengl·glsl
Thomas_YXQ10 天前
Unity3D项目开发中的资源加密详解
游戏·3d·unity·unity3d·游戏开发
小智00313 天前
Android Camera系列(八):MediaCodec视频编码下-OpenGL ES离屏渲染
android·音视频开发·opengl
Thomas_YXQ15 天前
Unity3D BEPUphysicsint定点数3D物理引擎详解
开发语言·3d·unity·unity3d·游戏开发·热更新
Starduster17 天前
Akka分布式游戏后端开发5 配置表代码设计
java·后端·游戏开发
白鹭float.19 天前
【OpenGL/Assimp】渲染模型、半透明材质与封装光源
c++·图形学·opengl·assimp
Thomas_YXQ19 天前
Unity3D 移动端CPU端性能调优详解
windows·unity·编辑器·游戏开发·热更新