Framebuffer

- Added 'Framebuffer'
- Added an optional 'FrameBuffer' parameter to'Renderer::BeginScene'
- Added 'RenderCommand::DefaultTargetFramebuffer()'
- Added static 'GraphicsContext::GetSharedContext()'

- Fixed 'dxBlender' by changing 'DestBlendAlpha' from D3D11_BLEND_ZERO
       to D3D11_BLEND_ONE
- Fixed 'glRenderCommand::ClearBackBuffer()' by calling glClear before
      glClearColor

- 'Application::GameLoop' now updates the ui ._.
This commit is contained in:
Light 2021-07-15 15:46:28 +04:30
parent 590c319d4d
commit 271f3b2075
16 changed files with 292 additions and 14 deletions

View file

@ -3,19 +3,17 @@
#include "Window.h"
#include "Events/Event.h"
#include "Debug/Instrumentor.h"
#include "Events/Event.h"
#include "Graphics/GraphicsContext.h"
#include "Graphics/Renderer.h"
#include "Graphics/RenderCommand.h"
#include "UserInterface/UserInterface.h"
#include "Time/Timer.h"
#include <filesystem>
#include "UserInterface/UserInterface.h"
namespace Light {
@ -37,7 +35,7 @@ namespace Light {
void Application::GameLoop()
{
// check
LT_ENGINE_ASSERT(!m_LayerStack.IsEmpty(), "Application::GameLoop(pre): LayerStack is empty");
// LT_ENGINE_ASSERT(!m_LayerStack.IsEmpty(), "Application::GameLoop(pre): LayerStack is empty");
// log debug data
LogDebugData();
@ -73,6 +71,7 @@ namespace Light {
// render user interface
LT_PROFILE_SCOPE("GameLoop::UserInterface");
m_Window->GetGfxContext()->GetUserInterface()->Begin();
m_LayerStack.OnUserInterfaceUpdate();
m_Window->GetGfxContext()->GetUserInterface()->End();
}

View file

@ -0,0 +1,30 @@
#include "ltpch.h"
#include "Framebuffer.h"
#include "OpenGL/glFramebuffer.h"
#ifdef LIGHT_PLATFORM_WINDOWS
#include "DirectX/dxFramebuffer.h"
#include "DirectX/dxSharedContext.h"
#endif
#include "GraphicsContext.h"
namespace Light {
Framebuffer* Framebuffer::Create(const FramebufferSpecification& specification, std::shared_ptr<SharedContext> sharedContext)
{
switch (GraphicsContext::GetGraphicsAPI())
{
case GraphicsAPI::OpenGL:
return new glFramebuffer(specification);
case GraphicsAPI::DirectX: LT_WIN(
return new dxFramebuffer(specification, std::static_pointer_cast<dxSharedContext>(sharedContext));)
default:
LT_ENGINE_ASSERT(false, "Shader::Create: invalid/unsupported 'GraphicsAPI' {}", GraphicsContext::GetGraphicsAPI());
return nullptr;
}
}
}

View file

@ -0,0 +1,35 @@
#pragma once
#include "Base.h"
#include <glm/glm.hpp>
namespace Light {
class SharedContext;
struct FramebufferSpecification
{
unsigned int width, height;
unsigned int samples = 1;
glm::uvec4 defaultColor = glm::uvec4(0u);
bool swapChainTarget = false; // render to the screen
};
class Framebuffer
{
public:
static Framebuffer* Create(const FramebufferSpecification& specification, std::shared_ptr<SharedContext> sharedContext);
virtual void* GetColorAttachment() = 0;
virtual void BindAsTarget() = 0;
virtual void BindAsResource() = 0;
protected:
Framebuffer() = default;
};
}

View file

@ -47,10 +47,12 @@ namespace Light {
virtual void LogDebugData() = 0;
static inline GraphicsAPI GetGraphicsAPI() { return s_Context->m_GraphicsAPI; }
static inline std::shared_ptr<SharedContext> GetSharedContext() { return s_Context->m_SharedContext; }
inline Renderer* GetRenderer() { return m_Renderer.get(); }
inline UserInterface* GetUserInterface() { return m_UserInterface.get(); }
protected:
GraphicsContext() = default;

View file

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

View file

@ -5,6 +5,7 @@
#include "Buffers.h"
#include "Texture.h"
#include "RenderCommand.h"
#include "Framebuffer.h"
#include "Events/WindowEvents.h"
@ -124,8 +125,16 @@ namespace Light {
m_RenderCommand->ClearBackBuffer();
}
void Renderer::BeginSceneImpl(const std::shared_ptr<Camera>& camera)
void Renderer::BeginSceneImpl(const std::shared_ptr<Camera>& camera, const std::shared_ptr<Framebuffer>& targetFrameBuffer /* = nullptr */)
{
m_TargetFramebuffer = targetFrameBuffer;
if (targetFrameBuffer)
targetFrameBuffer->BindAsTarget();
else
m_RenderCommand->DefaultTargetFramebuffer();
glm::mat4* map = (glm::mat4*)m_ViewProjectionBuffer->Map();
map[0] = camera->GetProjection() * camera->GetView();
m_ViewProjectionBuffer->UnMap();
@ -144,6 +153,8 @@ namespace Light {
void Renderer::EndSceneImpl()
{
// m_Blender->Disable();
m_Blender->Enable(BlendFactor::SRC_ALPHA, BlendFactor::INVERSE_SRC_ALPHA);
m_QuadRenderer.UnMap();
m_TextureRenderer.UnMap();
@ -160,6 +171,12 @@ namespace Light {
m_TextureRenderer.Bind();
m_RenderCommand->DrawIndexed(m_TextureRenderer.GetQuadCount() * 6u);
}
if(m_TargetFramebuffer)
{
m_TargetFramebuffer = nullptr;
m_RenderCommand->DefaultTargetFramebuffer();
}
}
}

View file

@ -4,6 +4,7 @@
#include "Buffers.h"
#include "Blender.h"
#include "Framebuffer.h"
#include "RendererPrograms/QuadRendererProgram.h"
#include "RendererPrograms/TextureRendererProgram.h"
@ -18,6 +19,8 @@ namespace Light {
class RenderCommand;
class Blender;
class Framebuffer;
class Camera;
class Texture;
@ -41,13 +44,17 @@ namespace Light {
std::unique_ptr<RenderCommand> m_RenderCommand;
std::unique_ptr<Blender> m_Blender;
std::shared_ptr<Framebuffer> m_TargetFramebuffer;
public:
static Renderer* Create(GLFWwindow* windowHandle, std::shared_ptr<SharedContext> sharedContext);
static inline void SetTargetFramebuffer(std::shared_ptr<Framebuffer> framebuffer) { s_Context->SetTargetFramebufferImpl(framebuffer); }
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 BeginScene(const std::shared_ptr<Camera>& camera) { s_Context->BeginSceneImpl(camera); }
static inline void BeginScene(const std::shared_ptr<Camera>& camera, const std::shared_ptr<Framebuffer>& targetFrameBuffer = nullptr) { s_Context->BeginSceneImpl(camera, targetFrameBuffer); }
static inline void EndScene() { s_Context->EndSceneImpl(); }
void OnWindowResize(const WindowResizedEvent& event);
@ -58,10 +65,12 @@ namespace Light {
private:
Renderer(GLFWwindow* windowHandle, std::shared_ptr<SharedContext> sharedContext);
void SetTargetFramebufferImpl(std::shared_ptr<Framebuffer> framebuffer);
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 BeginSceneImpl(const std::shared_ptr<Camera>& camera);
void BeginSceneImpl(const std::shared_ptr<Camera>& camera, const std::shared_ptr<Framebuffer>& targetFrameBuffer = nullptr);
void FlushScene();
void EndSceneImpl();
};

View file

@ -38,13 +38,13 @@ namespace Light {
// blender desc
m_Desc = { };
m_Desc.RenderTarget[0].BlendEnable = true;
m_Desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ZERO;
m_Desc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
m_Desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
m_Desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
m_Desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
m_Desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
m_Desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
m_Desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
@ -65,7 +65,7 @@ namespace Light {
DXC(m_Context->GetDevice()->CreateBlendState(&m_Desc, &m_BlendState));
// bind blend state
m_Context->GetDeviceContext()->OMSetBlendState(m_BlendState.Get(), nullptr, 0xffffffff);
m_Context->GetDeviceContext()->OMSetBlendState(m_BlendState.Get(), nullptr, 0x0000000f);
}
void dxBlender::Disable()

View file

@ -0,0 +1,57 @@
#include "ltpch.h"
#include "dxFramebuffer.h"
#include "dxSharedContext.h"
namespace Light {
dxFramebuffer::dxFramebuffer(const FramebufferSpecification& specification, std::shared_ptr<dxSharedContext> sharedContext)
: m_Specification(specification), m_Context(sharedContext)
{
HRESULT hr;
D3D11_TEXTURE2D_DESC textureDesc = { };
textureDesc.Width = specification.width;
textureDesc.Height = specification.height;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
textureDesc.SampleDesc.Count = 1u;
textureDesc.SampleDesc.Quality = 0u;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
textureDesc.CPUAccessFlags = NULL;
textureDesc.MiscFlags = NULL;
DXC(m_Context->GetDevice()->CreateTexture2D(&textureDesc, nullptr, &m_ColorAttachment));
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc = { };
shaderResourceViewDesc.Format = textureDesc.Format;
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Texture2D.MipLevels = 1;
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
DXC(m_Context->GetDevice()->CreateShaderResourceView(m_ColorAttachment.Get(), &shaderResourceViewDesc, &m_ResourceView));
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
rtvDesc.Format = textureDesc.Format;
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = 0u;
DXC(m_Context->GetDevice()->CreateRenderTargetView(m_ColorAttachment.Get(), &rtvDesc, &m_RenderTargetView));
}
void dxFramebuffer::BindAsTarget()
{
FLOAT color[] = {
m_Specification.defaultColor.r,
m_Specification.defaultColor.g,
m_Specification.defaultColor.b,
m_Specification.defaultColor.a,
};
m_Context->GetDeviceContext()->OMSetRenderTargets(1u, m_RenderTargetView.GetAddressOf(), nullptr);
m_Context->GetDeviceContext()->ClearRenderTargetView(m_RenderTargetView.Get(), color);
}
void dxFramebuffer::BindAsResource()
{
LT_ENGINE_ERROR("dxFramebuffer::BindAsResource: NO_IMPLEMENT");
}
}

View file

@ -0,0 +1,36 @@
#pragma once
#include "Base.h"
#include "Graphics/Framebuffer.h"
#include <d3d11.h>
#include <wrl.h>
namespace Light {
class dxSharedContext;
class dxFramebuffer : public Framebuffer
{
private:
std::shared_ptr<dxSharedContext> m_Context;
FramebufferSpecification m_Specification;
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> m_RenderTargetView;
Microsoft::WRL::ComPtr<ID3D11Texture2D> m_ColorAttachment;
Microsoft::WRL::ComPtr<ID3D11Texture2D> m_DepthStencilAttachment;
Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> m_ResourceView;
Microsoft::WRL::ComPtr<ID3D11DepthStencilView> m_DepthStencilView;
public:
dxFramebuffer(const FramebufferSpecification& specification, std::shared_ptr<dxSharedContext> sharedContext);
inline void* GetColorAttachment() override { return (void*)m_ResourceView.Get(); }
void BindAsTarget() override;
void BindAsResource() override;
};
}

View file

@ -28,7 +28,7 @@ namespace Light {
void dxRenderCommand::ClearBackBuffer()
{
float colors[] = { 1.2f, 0.4f, 0.9f, 1.0f }; // #todo: use a variable for this
float colors[] = { 0.1, 0.35f, 0.46f, 1.0f }; // #todo: use a local variable for this
m_Context->GetDeviceContext()->ClearRenderTargetView(m_Context->GetRenderTargetView().Get(), colors);
}
@ -42,6 +42,11 @@ namespace Light {
m_Context->GetDeviceContext()->DrawIndexed(count, 0u, 0u);
}
void dxRenderCommand::DefaultTargetFramebuffer()
{
m_Context->GetDeviceContext()->OMSetRenderTargets(1, m_Context->GetRenderTargetView().GetAddressOf(), nullptr);
}
void dxRenderCommand::SetViewport(unsigned int x, unsigned int y, unsigned int width, unsigned int height)
{
// create viewport

View file

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

View file

@ -0,0 +1,52 @@
#include "ltpch.h"
#include "glFramebuffer.h"
#include <glad/glad.h>
namespace Light {
glFramebuffer::glFramebuffer(const FramebufferSpecification& specification)
: m_Specification(specification)
{
glCreateFramebuffers(1, &m_BufferID);
glBindFramebuffer(GL_FRAMEBUFFER, m_BufferID);
// create color attachment
glCreateTextures(GL_TEXTURE_2D, 1, &m_ColorAttachment);
glBindTexture(GL_TEXTURE_2D, m_ColorAttachment);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_Specification.width, m_Specification.height, NULL, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTextureParameteri(m_ColorAttachment, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTextureParameteri(m_ColorAttachment, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_ColorAttachment, 0);
// glTextureStorage2D(m_ColorAttachment, 0, GL_RGBA8, m_Specification.width, m_Specification.height);
// glCreateTextures(GL_TEXTURE_2D, 1, &m_DepthStencilAttachment);
// glBindTexture(GL_TEXTURE_2D, m_DepthStencilAttachment);
// glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_Specification.width, m_Specification.height, NULL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
// // glTextureStorage2D(m_DepthStencilAttachment, 0, GL_DEPTH24_STENCIL8, m_Specification.width, m_Specification.height);
// glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthStencilAttachment, 0);
LT_ENGINE_ASSERT((glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE), "glFramebuffer::Validate: framebuffer is incomplete");
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
glFramebuffer::~glFramebuffer()
{
glDeleteFramebuffers(1, &m_BufferID);
}
void glFramebuffer::BindAsTarget()
{
glBindFramebuffer(GL_FRAMEBUFFER, m_BufferID);
glClearColor(m_Specification.defaultColor.r, m_Specification.defaultColor.g, m_Specification.defaultColor.b, m_Specification.defaultColor.a);
glClear(GL_COLOR_BUFFER_BIT);
}
void glFramebuffer::BindAsResource()
{
LT_ENGINE_ERROR("glFramebuffer::BindAsResource: NO_IMPLEMENT!");
}
}

View file

@ -0,0 +1,25 @@
#pragma once
#include "Base.h"
#include "Graphics/Framebuffer.h"
namespace Light {
class glFramebuffer : public Framebuffer
{
private:
FramebufferSpecification m_Specification;
unsigned int m_BufferID, m_ColorAttachment, m_DepthStencilAttachment;
public:
glFramebuffer(const FramebufferSpecification& specification);
~glFramebuffer();
inline void* GetColorAttachment() override { return (void*)m_ColorAttachment; }
void BindAsTarget() override;
void BindAsResource() override;
};
}

View file

@ -17,8 +17,8 @@ namespace Light {
void glRenderCommand::ClearBackBuffer()
{
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.25f, 0.45f, 0.91f, 1.0f); // #todo: use a variable for this
glClear(GL_COLOR_BUFFER_BIT);
}
void glRenderCommand::Draw(unsigned int count)
@ -31,6 +31,11 @@ namespace Light {
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr);
}
void glRenderCommand::DefaultTargetFramebuffer()
{
glBindFramebuffer(GL_FRAMEBUFFER, NULL);
}
void glRenderCommand::SetViewport(unsigned int x, unsigned int y, unsigned int width, unsigned int height)
{
glViewport(x, y, width, height);

View file

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