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

相关推荐
凌云行者2 天前
OpenGL入门004——使用EBO绘制矩形
c++·cmake·opengl
Thomas_YXQ3 天前
Unity3D中管理Shader效果详解
开发语言·游戏·unity·unity3d·游戏开发
闲暇部落3 天前
Android OpenGL ES详解——模板Stencil
android·kotlin·opengl·模板测试·stencil·模板缓冲·物体轮廓
凌云行者5 天前
OpenGL入门003——使用Factory设计模式简化渲染流程
c++·cmake·opengl
凌云行者6 天前
OpenGL入门002——顶点着色器和片段着色器
c++·cmake·opengl
Ljw...6 天前
C++游戏开发
c++·c·游戏开发
闲暇部落7 天前
Android OpenGL ES详解——裁剪Scissor
android·kotlin·opengl·窗口·裁剪·scissor·视口
彭祥.12 天前
点云标注工具开发记录(四)之点云根据类别展示与加速渲染
pyqt·opengl
闲暇部落15 天前
android openGL ES详解——缓冲区VBO/VAO/EBO/FBO
kotlin·opengl·缓冲区·fbo·vbo·vao·ebo
北冥没有鱼啊16 天前
ue5 扇形射线检测和鼠标拖拽物体
游戏·ue5·ue4·游戏开发·虚幻