WindowResizeEvent | FlushScene

- 'Renderer' now receives 'WindowResizedEvent' and handle the
      'Framebuffer' and viewport stuff
- Added 'Renderer' now uses the new 'FlushScene' function to flush when
      the mapped vertex buffer is filled
- The viewport is now set by 'RenderCommand' via the 'Renderer' rather
      than the 'GraphicsConntext'

- 'Window' no longer sends 'WindowResizedEvent' to 'GraphicsContext'
- 'GraphicsContext' no longer receives 'OnWindowResize' events

- Note: Sending events should be done by the 'Application'
This commit is contained in:
Light 2021-07-14 00:17:30 +04:30
parent 44b135f157
commit 57616d755c
17 changed files with 86 additions and 63 deletions

View file

@ -5,14 +5,14 @@
#include "Events/Event.h" #include "Events/Event.h"
#include "Debug/Instrumentor.h"
#include "Graphics/GraphicsContext.h" #include "Graphics/GraphicsContext.h"
#include "Graphics/Renderer.h" #include "Graphics/Renderer.h"
#include "Graphics/RenderCommand.h" #include "Graphics/RenderCommand.h"
#include "UserInterface/UserInterface.h" #include "UserInterface/UserInterface.h"
#include "Debug/Instrumentor.h"
#include "Time/Timer.h" #include "Time/Timer.h"
#include <filesystem> #include <filesystem>
@ -94,8 +94,13 @@ namespace Light {
{ {
// window // window
if (event.HasCategory(WindowEventCategory)) if (event.HasCategory(WindowEventCategory))
{
m_Window->OnEvent(event); m_Window->OnEvent(event);
if(event.GetEventType() == EventType::WindowResized)
m_Window->GetGfxContext()->GetRenderer()->OnWindowResize((const WindowResizedEvent&)event);
}
// user interface // user interface
if (event.HasCategory(InputEventCategory)) if (event.HasCategory(InputEventCategory))
m_Window->GetGfxContext()->GetUserInterface()->OnInput(event); m_Window->GetGfxContext()->GetUserInterface()->OnInput(event);

View file

@ -44,8 +44,6 @@ namespace Light {
virtual ~GraphicsContext(); virtual ~GraphicsContext();
virtual void OnWindowResize(const WindowResizedEvent& event) = 0;
virtual void LogDebugData() = 0; virtual void LogDebugData() = 0;
static inline GraphicsAPI GetGraphicsAPI() { return s_Context->m_GraphicsAPI; } static inline GraphicsAPI GetGraphicsAPI() { return s_Context->m_GraphicsAPI; }

View file

@ -24,6 +24,8 @@ namespace Light {
virtual void Draw(unsigned int count) = 0; virtual void Draw(unsigned int count) = 0;
virtual void DrawIndexed(unsigned int count) = 0; virtual void DrawIndexed(unsigned int count) = 0;
virtual void SetViewport(unsigned int x, unsigned int y, unsigned int width, unsigned int height) = 0;
protected: protected:
RenderCommand() = default; RenderCommand() = default;
}; };

View file

@ -6,6 +6,8 @@
#include "Texture.h" #include "Texture.h"
#include "RenderCommand.h" #include "RenderCommand.h"
#include "Events/WindowEvents.h"
#include "Camera/Camera.h" #include "Camera/Camera.h"
#include <glm/glm.hpp> #include <glm/glm.hpp>
@ -28,6 +30,7 @@ namespace Light {
m_ViewProjectionBuffer = std::unique_ptr<ConstantBuffer>(ConstantBuffer::Create(ConstantBufferIndex::ViewProjection, sizeof(glm::mat4), sharedContext)); m_ViewProjectionBuffer = std::unique_ptr<ConstantBuffer>(ConstantBuffer::Create(ConstantBufferIndex::ViewProjection, sizeof(glm::mat4), sharedContext));
m_Blender = std::unique_ptr<Blender>(Blender::Create(sharedContext)); m_Blender = std::unique_ptr<Blender>(Blender::Create(sharedContext));
m_Blender->Enable(BlendFactor::SRC_ALPHA, BlendFactor::INVERSE_SRC_ALPHA);
} }
Renderer* Renderer::Create(GLFWwindow* windowHandle, std::shared_ptr<SharedContext> sharedContext) Renderer* Renderer::Create(GLFWwindow* windowHandle, std::shared_ptr<SharedContext> sharedContext)
@ -35,6 +38,11 @@ namespace Light {
return new Renderer(windowHandle, sharedContext); return new Renderer(windowHandle, sharedContext);
} }
void Renderer::OnWindowResize(const WindowResizedEvent& event)
{
m_RenderCommand->SetViewport(0u, 0u, event.GetSize().x, event.GetSize().y);
}
void Renderer::DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint) void Renderer::DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint)
{ {
// locals // locals
@ -64,8 +72,8 @@ namespace Light {
// advance // advance
if (!m_QuadRenderer.Advance()) if (!m_QuadRenderer.Advance())
{ {
EndFrame(); LT_ENGINE_WARN("Renderer::DrawQuadImpl: exceeded LT_MAX_QUAD_RENDERER_VERTICES: {}", LT_MAX_QUAD_RENDERER_VERTICES);
BeginFrame(); FlushScene();
} }
} }
@ -101,38 +109,42 @@ namespace Light {
// advance // advance
if (!m_TextureRenderer.Advance()) if (!m_TextureRenderer.Advance())
{ {
EndFrame(); LT_ENGINE_WARN("Renderer::DrawQuadImpl: exceeded LT_MAX_TEXTURE_RENDERER_VERTICES: {}", LT_MAX_TEXTURE_RENDERER_VERTICES);
BeginFrame(); FlushScene();
} }
} }
void Renderer::BeginFrame() void Renderer::BeginFrame()
{ {
} }
void Renderer::EndFrame() void Renderer::EndFrame()
{ {
} }
void Renderer::BeginSceneImpl(const Camera& camera) void Renderer::BeginSceneImpl(const std::shared_ptr<Camera>& camera)
{ {
glm::mat4* map = (glm::mat4*)m_ViewProjectionBuffer->Map(); glm::mat4* map = (glm::mat4*)m_ViewProjectionBuffer->Map();
map[0] = camera.GetProjection() * camera.GetView(); map[0] = camera->GetProjection() * camera->GetView();
m_ViewProjectionBuffer->UnMap(); m_ViewProjectionBuffer->UnMap();
m_QuadRenderer.Map(); m_QuadRenderer.Map();
m_TextureRenderer.Map(); m_TextureRenderer.Map();
} }
void Renderer::FlushScene()
{
EndScene();
m_QuadRenderer.Map();
m_TextureRenderer.Map();
}
void Renderer::EndSceneImpl() void Renderer::EndSceneImpl()
{ {
m_QuadRenderer.UnMap(); m_QuadRenderer.UnMap();
m_TextureRenderer.UnMap(); m_TextureRenderer.UnMap();
m_Blender->Enable(BlendFactor::SRC_ALPHA, BlendFactor::INVERSE_SRC_ALPHA);
//** QUAD_RENDERER **// //** QUAD_RENDERER **//
if (m_QuadRenderer.GetQuadCount()) if (m_QuadRenderer.GetQuadCount())
{ {

View file

@ -22,6 +22,8 @@ namespace Light {
class Texture; class Texture;
class WindowResizedEvent;
class SharedContext; class SharedContext;
class Renderer class Renderer
@ -29,12 +31,14 @@ namespace Light {
private: private:
static Renderer* s_Context; static Renderer* s_Context;
// renderer programs
QuadRendererProgram m_QuadRenderer; QuadRendererProgram m_QuadRenderer;
TextureRendererProgram m_TextureRenderer; TextureRendererProgram m_TextureRenderer;
std::unique_ptr<RenderCommand> m_RenderCommand; // constant buffers
std::unique_ptr<ConstantBuffer> m_ViewProjectionBuffer; std::unique_ptr<ConstantBuffer> m_ViewProjectionBuffer;
std::unique_ptr<RenderCommand> m_RenderCommand;
std::unique_ptr<Blender> m_Blender; std::unique_ptr<Blender> m_Blender;
public: public:
@ -43,9 +47,11 @@ namespace Light {
static inline void DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint) { s_Context->DrawQuadImpl(position, size, tint); } static inline void DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint) { s_Context->DrawQuadImpl(position, size, tint); }
static inline void DrawQuad(const glm::vec3& position, const glm::vec2& size, std::shared_ptr<Texture> texture) { s_Context->DrawQuadImpl(position, size, texture); } static inline void DrawQuad(const glm::vec3& position, const glm::vec2& size, std::shared_ptr<Texture> texture) { s_Context->DrawQuadImpl(position, size, texture); }
static inline void BeginScene(const Camera& camera) { s_Context->BeginSceneImpl(camera); } static inline void BeginScene(const std::shared_ptr<Camera>& camera) { s_Context->BeginSceneImpl(camera); }
static inline void EndScene() { s_Context->EndSceneImpl(); } static inline void EndScene() { s_Context->EndSceneImpl(); }
void OnWindowResize(const WindowResizedEvent& event);
void BeginFrame(); void BeginFrame();
void EndFrame(); void EndFrame();
@ -55,7 +61,8 @@ namespace Light {
void DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint); void DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint);
void DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, std::shared_ptr<Texture> texture); void DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, std::shared_ptr<Texture> texture);
void BeginSceneImpl(const Camera& camera); void BeginSceneImpl(const std::shared_ptr<Camera>& camera);
void FlushScene();
void EndSceneImpl(); void EndSceneImpl();
}; };

View file

@ -6,6 +6,7 @@ namespace Light {
class SharedContext; class SharedContext;
// #todo: improve textures
class Texture class Texture
{ {
public: public:

View file

@ -31,11 +31,6 @@ namespace Light {
m_SharedContext = std::make_shared<dxSharedContext>(m_Device, m_DeviceContext, m_SwapChain, m_RenderTargetView); m_SharedContext = std::make_shared<dxSharedContext>(m_Device, m_DeviceContext, m_SwapChain, m_RenderTargetView);
} }
void dxGraphicsContext::OnWindowResize(const WindowResizedEvent& event)
{
SetResolution(event.GetSize().x, event.GetSize().y);
}
void dxGraphicsContext::SetupDeviceAndSwapChain(GLFWwindow* windowHandle) void dxGraphicsContext::SetupDeviceAndSwapChain(GLFWwindow* windowHandle)
{ {
// swap chain desc // swap chain desc
@ -129,23 +124,6 @@ namespace Light {
#endif #endif
} }
void dxGraphicsContext::SetResolution(unsigned int width, unsigned int height)
{
// viewport
D3D11_VIEWPORT viewport;
viewport.Width = width;
viewport.Height = height;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
// set viewport
m_DeviceContext->RSSetViewports(1u, &viewport);
}
void dxGraphicsContext::LogDebugData() void dxGraphicsContext::LogDebugData()
{ {
// locals // locals

View file

@ -25,17 +25,12 @@ namespace Light {
public: public:
dxGraphicsContext(GLFWwindow* windowHandle); dxGraphicsContext(GLFWwindow* windowHandle);
virtual void OnWindowResize(const WindowResizedEvent& event) override;
virtual void LogDebugData() override; virtual void LogDebugData() override;
private: private:
void SetupDeviceAndSwapChain(GLFWwindow* windowHandle); void SetupDeviceAndSwapChain(GLFWwindow* windowHandle);
void SetupRenderTargets(); void SetupRenderTargets();
void SetupDebugInterface(); void SetupDebugInterface();
void SetResolution(unsigned int width, unsigned int height);
}; };
} }

View file

@ -42,4 +42,22 @@ namespace Light {
m_Context->GetDeviceContext()->DrawIndexed(count, 0u, 0u); m_Context->GetDeviceContext()->DrawIndexed(count, 0u, 0u);
} }
void dxRenderCommand::SetViewport(unsigned int x, unsigned int y, unsigned int width, unsigned int height)
{
// create viewport
D3D11_VIEWPORT viewport;
viewport.TopLeftX = x;
viewport.TopLeftY = y;
viewport.Width = width;
viewport.Height = height;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
// set viewport
m_Context->GetDeviceContext()->RSSetViewports(1u, &viewport);
}
} }

View file

@ -23,6 +23,8 @@ namespace Light {
virtual void Draw(unsigned int count) override; virtual void Draw(unsigned int count) override;
virtual void DrawIndexed(unsigned int count) override; virtual void DrawIndexed(unsigned int count) override;
virtual void SetViewport(unsigned int x, unsigned int y, unsigned int width, unsigned int height) override;
}; };
} }

View file

@ -29,17 +29,6 @@ namespace Light {
SetDebugMessageCallback(); SetDebugMessageCallback();
} }
void glGraphicsContext::OnWindowResize(const WindowResizedEvent& event)
{
if (event.GetSize().x < 0 || event.GetSize().y < 0)
{
LT_ENGINE_ERROR("glGraphicsContext::OnWindowResize: 'width'/'height' cannot be negative: [{}x{}]", event.GetSize().x, event.GetSize().y);
return;
}
glViewport(0, 0, event.GetSize().x, event.GetSize().y);
}
void glGraphicsContext::LogDebugData() void glGraphicsContext::LogDebugData()
{ {
// #todo: log more information // #todo: log more information

View file

@ -17,8 +17,6 @@ namespace Light {
public: public:
glGraphicsContext(GLFWwindow* windowHandle); glGraphicsContext(GLFWwindow* windowHandle);
virtual void OnWindowResize(const WindowResizedEvent& event) override;
virtual void LogDebugData() override; virtual void LogDebugData() override;
private: private:

View file

@ -31,4 +31,9 @@ namespace Light {
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr); glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr);
} }
void glRenderCommand::SetViewport(unsigned int x, unsigned int y, unsigned int width, unsigned int height)
{
glViewport(x, y, width, height);
}
} }

View file

@ -18,6 +18,8 @@ namespace Light {
void Draw(unsigned int count) override; void Draw(unsigned int count) override;
void DrawIndexed(unsigned int count) override; void DrawIndexed(unsigned int count) override;
virtual void SetViewport(unsigned int x, unsigned int y, unsigned int width, unsigned int height) override;
}; };
} }

View file

@ -36,7 +36,7 @@ namespace Light {
glfwSetWindowUserPointer(m_Handle, &m_EventCallback); glfwSetWindowUserPointer(m_Handle, &m_EventCallback);
BindGlfwEvents(); BindGlfwEvents();
// create graphics context // create graphics contextG
m_GraphicsContext = std::unique_ptr<GraphicsContext>(GraphicsContext::Create(GraphicsAPI::OpenGL, m_Handle)); m_GraphicsContext = std::unique_ptr<GraphicsContext>(GraphicsContext::Create(GraphicsAPI::OpenGL, m_Handle));
LT_ENGINE_ASSERT(m_GraphicsContext, "lWindow::lWindow: failed to create 'GraphicsContext'"); LT_ENGINE_ASSERT(m_GraphicsContext, "lWindow::lWindow: failed to create 'GraphicsContext'");
} }
@ -62,11 +62,16 @@ namespace Light {
// resized // resized
case EventType::WindowResized: case EventType::WindowResized:
m_GraphicsContext->OnWindowResize((const WindowResizedEvent&)event); OnWindowResize((const WindowResizedEvent&)event);
break; break;
} }
} }
void lWindow::OnWindowResize(const WindowResizedEvent& event)
{
m_Properties.size = event.GetSize();
}
void lWindow::SetProperties(const WindowProperties& properties, bool affectsVisiblity /* = false */) void lWindow::SetProperties(const WindowProperties& properties, bool affectsVisiblity /* = false */)
{ {
// save the visibility status and re-assign if 'affectVisibility' is false // save the visibility status and re-assign if 'affectVisibility' is false

View file

@ -8,6 +8,7 @@ struct GLFWwindow;
namespace Light { namespace Light {
class Event; class Event;
class WindowResizedEvent;
class lWindow : public Window class lWindow : public Window
{ {
@ -35,6 +36,8 @@ namespace Light {
private: private:
void BindGlfwEvents(); void BindGlfwEvents();
void OnWindowResize(const WindowResizedEvent& event);
}; };
} }

View file

@ -8,11 +8,12 @@ struct GLFWwindow;
namespace Light { namespace Light {
class Event; class Event;
class WindowResizedEvent;
class wWindow : public Window class wWindow : public Window
{ {
private: private:
// #todo: don't handle Windows's window with glfw, create it yourself // #todo: don't handle Windows's window with glfw, create an HWND
GLFWwindow* m_Handle = nullptr; GLFWwindow* m_Handle = nullptr;
std::function<void(Event&)> m_EventCallback; std::function<void(Event&)> m_EventCallback;
@ -37,6 +38,8 @@ namespace Light {
private: private:
void BindGlfwEvents(); void BindGlfwEvents();
void OnWindowResize(const WindowResizedEvent& event);
}; };
} }