light/modules/engine/src/graphics/renderer.cpp

306 lines
8.5 KiB
C++
Raw Normal View History

2025-07-05 13:28:41 +03:30
#include <engine/camera/scene.hpp>
#include <engine/events/window.hpp>
#include <engine/graphics/blender.hpp>
#include <engine/graphics/buffers.hpp>
#include <engine/graphics/framebuffer.hpp>
#include <engine/graphics/render_command.hpp>
#include <engine/graphics/renderer.hpp>
#include <engine/graphics/texture.hpp>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
2022-03-04 22:40:20 +03:30
#include <glm/matrix.hpp>
2021-05-30 16:45:54 +04:30
namespace Light {
2025-07-05 13:28:41 +03:30
Renderer *Renderer::s_Context = nullptr;
Renderer::Renderer(GLFWwindow *windowHandle, Ref<SharedContext> sharedContext)
: m_quad_renderer(LT_MAX_QUAD_RENDERER_VERTICES, sharedContext)
, m_texture_renderer(LT_MAX_TEXTURE_RENDERER_VERTICES, sharedContext)
, m_tinted_texture_renderer(LT_MAX_TINTED_TEXTURE_RENDERER_VERTICES, sharedContext)
, m_view_projection_buffer(nullptr)
, m_render_command(nullptr)
, m_blender(nullptr)
, m_default_framebuffer_camera(nullptr)
, m_target_framebuffer(nullptr)
, m_should_clear_backbuffer(false)
2022-03-04 22:40:20 +03:30
{
2022-03-07 21:57:00 +03:30
ASSERT(!s_Context, "An instance of 'Renderer' already exists, do not construct this class!");
2022-03-04 22:40:20 +03:30
s_Context = this;
m_view_projection_buffer = ConstantBuffer::Create(
2025-07-05 13:28:41 +03:30
ConstantBufferIndex::ViewProjection,
sizeof(glm::mat4),
sharedContext
);
2022-03-04 22:40:20 +03:30
m_render_command = RenderCommand::Create(windowHandle, sharedContext);
m_blender = Blender::Create(sharedContext);
m_blender->Enable(BlendFactor::SRC_ALPHA, BlendFactor::INVERSE_SRC_ALPHA);
2022-03-04 22:40:20 +03:30
}
2025-07-05 13:28:41 +03:30
Scope<Renderer> Renderer::Create(GLFWwindow *windowHandle, Ref<SharedContext> sharedContext)
2022-03-04 22:40:20 +03:30
{
return MakeScope<Renderer>(new Renderer(windowHandle, sharedContext));
}
2025-07-05 13:28:41 +03:30
void Renderer::OnWindowResize(const WindowResizedEvent &event)
2022-03-04 22:40:20 +03:30
{
m_render_command->SetViewport(0u, 0u, event.GetSize().x, event.GetSize().y);
2022-03-04 22:40:20 +03:30
}
//======================================== DRAW_QUAD ========================================//
/* tinted textures */
2025-07-05 13:28:41 +03:30
void Renderer::DrawQuadImpl(
const glm::vec3 &position,
const glm::vec2 &size,
const glm::vec4 &tint,
Ref<Texture> texture
)
2022-03-04 22:40:20 +03:30
{
2025-07-05 13:28:41 +03:30
DrawQuad(
glm::translate(glm::mat4(1.0f), position)
* glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f }),
tint,
texture
);
2022-03-04 22:40:20 +03:30
}
/* tint */
2025-07-05 13:28:41 +03:30
void Renderer::DrawQuadImpl(const glm::vec3 &position, const glm::vec2 &size, const glm::vec4 &tint)
2022-03-04 22:40:20 +03:30
{
2025-07-05 13:28:41 +03:30
DrawQuad(
glm::translate(glm::mat4(1.0f), position)
* glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f }),
tint
);
2022-03-04 22:40:20 +03:30
}
/* texture */
2025-07-05 13:28:41 +03:30
void Renderer::DrawQuadImpl(const glm::vec3 &position, const glm::vec2 &size, Ref<Texture> texture)
2022-03-04 22:40:20 +03:30
{
2025-07-05 13:28:41 +03:30
DrawQuad(
glm::translate(glm::mat4(1.0f), position)
* glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f }),
texture
);
2022-03-04 22:40:20 +03:30
}
//======================================== DRAW_QUAD ========================================//
//==================== DRAW_QUAD_TINT ====================//
2025-07-05 13:28:41 +03:30
void Renderer::DrawQuadImpl(const glm::mat4 &transform, const glm::vec4 &tint)
2022-03-04 22:40:20 +03:30
{
// locals
QuadRendererProgram::QuadVertexData *bufferMap = m_quad_renderer.GetMapCurrent();
2022-03-04 22:40:20 +03:30
// top left
bufferMap[0].position = transform * glm::vec4(-0.5f, -0.5f, 0.0f, 1.0f);
2025-07-05 13:28:41 +03:30
bufferMap[0].tint = tint;
2022-03-04 22:40:20 +03:30
// top right
bufferMap[1].position = transform * glm::vec4(0.5f, -0.5f, 0.0f, 1.0f);
2025-07-05 13:28:41 +03:30
bufferMap[1].tint = tint;
2022-03-04 22:40:20 +03:30
// bottom right
bufferMap[2].position = transform * glm::vec4(0.5f, 0.5f, 0.0f, 1.0f);
2025-07-05 13:28:41 +03:30
bufferMap[2].tint = tint;
2022-03-04 22:40:20 +03:30
// bottom left
bufferMap[3].position = transform * glm::vec4(-0.5f, 0.5f, 0.0f, 1.0f);
2025-07-05 13:28:41 +03:30
bufferMap[3].tint = tint;
2022-03-04 22:40:20 +03:30
// advance
if (!m_quad_renderer.Advance())
2021-05-30 16:45:54 +04:30
{
2022-03-07 21:57:00 +03:30
LOG(warn, "Exceeded LT_MAX_QUAD_RENDERER_VERTICES: {}", LT_MAX_QUAD_RENDERER_VERTICES);
2022-03-04 22:40:20 +03:30
FlushScene();
}
}
//==================== DRAW_QUAD_TINT ====================//
2021-05-30 16:45:54 +04:30
2022-03-04 22:40:20 +03:30
//==================== DRAW_QUAD_TEXTURE ====================//
2025-07-05 13:28:41 +03:30
void Renderer::DrawQuadImpl(const glm::mat4 &transform, Ref<Texture> texture)
2022-03-04 22:40:20 +03:30
{
// #todo: implement a proper binding
2022-03-07 21:57:00 +03:30
ASSERT(texture, "Texture passed to Renderer::DrawQuadImpl");
2022-03-04 22:40:20 +03:30
texture->Bind();
2021-07-09 11:56:31 +04:30
2022-03-04 22:40:20 +03:30
// locals
TextureRendererProgram::TextureVertexData *bufferMap = m_texture_renderer.GetMapCurrent();
2021-05-30 16:45:54 +04:30
2022-03-04 22:40:20 +03:30
// top left
bufferMap[0].position = transform * glm::vec4(-0.5f, -0.5f, 0.0f, 1.0f);
bufferMap[0].texcoord = { 0.0f, 0.0f };
2021-05-30 16:45:54 +04:30
2022-03-04 22:40:20 +03:30
// top right
bufferMap[1].position = transform * glm::vec4(0.5f, -0.5f, 0.0f, 1.0f);
bufferMap[1].texcoord = { 1.0f, 0.0f };
// bottom right
bufferMap[2].position = transform * glm::vec4(0.5f, 0.5f, 0.0f, 1.0f);
bufferMap[2].texcoord = { 1.0f, 1.0f };
// bottom left
bufferMap[3].position = transform * glm::vec4(-0.5f, 0.5f, 0.0f, 1.0f);
bufferMap[3].texcoord = { 0.0f, 1.0f };
2022-03-04 22:40:20 +03:30
// advance
if (!m_texture_renderer.Advance())
{
2025-07-05 13:28:41 +03:30
LOG(warn, "Exceeded LT_MAX_TEXTURE_RENDERER_VERTICES: {}", LT_MAX_TEXTURE_RENDERER_VERTICES
);
2022-03-04 22:40:20 +03:30
FlushScene();
}
2022-03-04 22:40:20 +03:30
}
2025-07-05 13:28:41 +03:30
void Renderer::DrawQuadImpl(const glm::mat4 &transform, const glm::vec4 &tint, Ref<Texture> texture)
2022-03-04 22:40:20 +03:30
{
// #todo: implement a proper binding
2022-03-07 21:57:00 +03:30
ASSERT(texture, "Texture passed to Renderer::DrawQuadImpl");
2022-03-04 22:40:20 +03:30
texture->Bind();
// locals
TintedTextureRendererProgram::TintedTextureVertexData *bufferMap = m_tinted_texture_renderer
2025-07-05 13:28:41 +03:30
.GetMapCurrent();
2022-03-04 22:40:20 +03:30
// top left
bufferMap[0].position = transform * glm::vec4(-0.5f, -0.5f, 0.0f, 1.0f);
2025-07-05 13:28:41 +03:30
bufferMap[0].tint = tint;
2022-03-04 22:40:20 +03:30
bufferMap[0].texcoord = { 0.0f, 0.0f };
// top right
bufferMap[1].position = transform * glm::vec4(0.5f, -0.5f, 0.0f, 1.0f);
2025-07-05 13:28:41 +03:30
bufferMap[1].tint = tint;
2022-03-04 22:40:20 +03:30
bufferMap[1].texcoord = { 1.0f, 0.0f };
// bottom right
bufferMap[2].position = transform * glm::vec4(0.5f, 0.5f, 0.0f, 1.0f);
2025-07-05 13:28:41 +03:30
bufferMap[2].tint = tint;
2022-03-04 22:40:20 +03:30
bufferMap[2].texcoord = { 1.0f, 1.0f };
// bottom left
bufferMap[3].position = transform * glm::vec4(-0.5f, 0.5f, 0.0f, 1.0f);
2025-07-05 13:28:41 +03:30
bufferMap[3].tint = tint;
2022-03-04 22:40:20 +03:30
bufferMap[3].texcoord = { 0.0f, 1.0f };
// advance
if (!m_tinted_texture_renderer.Advance())
{
2025-07-05 13:28:41 +03:30
LOG(warn, "Exceeded LT_MAX_TEXTURE_RENDERER_VERTICES: {}", LT_MAX_TEXTURE_RENDERER_VERTICES
);
2022-03-04 22:40:20 +03:30
FlushScene();
}
2022-03-04 22:40:20 +03:30
}
2022-03-04 22:40:20 +03:30
//==================== DRAW_QUAD_TEXTURE ====================//
void Renderer::BeginFrame()
{
}
2022-03-04 22:40:20 +03:30
void Renderer::EndFrame()
{
m_render_command->SwapBuffers();
m_render_command->ClearBackBuffer(
m_default_framebuffer_camera ? m_default_framebuffer_camera->GetBackgroundColor() :
2025-07-05 13:28:41 +03:30
glm::vec4(0.0f)
);
2022-03-04 22:40:20 +03:30
m_default_framebuffer_camera = nullptr;
2022-03-04 22:40:20 +03:30
}
2025-07-05 13:28:41 +03:30
void Renderer::BeginSceneImpl(
Camera *camera,
const glm::mat4 &cameraTransform,
const Ref<Framebuffer> &targetFrameBuffer /* = nullptr */
)
2022-03-04 22:40:20 +03:30
{
// determine the target frame buffer
m_target_framebuffer = targetFrameBuffer;
2022-03-04 22:40:20 +03:30
if (targetFrameBuffer)
targetFrameBuffer->BindAsTarget(camera->GetBackgroundColor());
else
2021-05-30 16:45:54 +04:30
{
m_default_framebuffer_camera = camera;
m_render_command->DefaultTargetFramebuffer();
}
2022-03-04 22:40:20 +03:30
// update view projection buffer
glm::mat4 *map = (glm::mat4 *)m_view_projection_buffer->Map();
2025-07-05 13:28:41 +03:30
map[0] = camera->GetProjection() * glm::inverse(cameraTransform);
m_view_projection_buffer->UnMap();
2022-03-04 22:40:20 +03:30
// map renderers
m_quad_renderer.Map();
m_texture_renderer.Map();
m_tinted_texture_renderer.Map();
2022-03-04 22:40:20 +03:30
}
void Renderer::FlushScene()
{
/* tinted texture renderer */
m_tinted_texture_renderer.UnMap();
if (m_tinted_texture_renderer.GetQuadCount())
{
m_tinted_texture_renderer.Bind();
m_render_command->DrawIndexed(m_tinted_texture_renderer.GetQuadCount() * 6u);
}
2022-03-04 22:40:20 +03:30
/* quad renderer */
m_quad_renderer.UnMap();
if (m_quad_renderer.GetQuadCount())
{
m_quad_renderer.Bind();
m_render_command->DrawIndexed(m_quad_renderer.GetQuadCount() * 6u);
}
2022-03-04 22:40:20 +03:30
/* texture renderer */
m_texture_renderer.UnMap();
if (m_texture_renderer.GetQuadCount())
{
m_texture_renderer.Bind();
m_render_command->DrawIndexed(m_texture_renderer.GetQuadCount() * 6u);
}
m_quad_renderer.Map();
m_texture_renderer.Map();
m_tinted_texture_renderer.Map();
2022-03-04 22:40:20 +03:30
}
2022-03-04 22:40:20 +03:30
void Renderer::EndSceneImpl()
{
/* tinted texture renderer */
m_tinted_texture_renderer.UnMap();
if (m_tinted_texture_renderer.GetQuadCount())
2022-03-04 22:40:20 +03:30
{
m_tinted_texture_renderer.Bind();
m_render_command->DrawIndexed(m_tinted_texture_renderer.GetQuadCount() * 6u);
}
2022-03-04 22:40:20 +03:30
/* quad renderer */
m_quad_renderer.UnMap();
if (m_quad_renderer.GetQuadCount())
{
m_quad_renderer.Bind();
m_render_command->DrawIndexed(m_quad_renderer.GetQuadCount() * 6u);
}
2022-03-04 22:40:20 +03:30
/* texture renderer */
m_texture_renderer.UnMap();
if (m_texture_renderer.GetQuadCount())
{
m_texture_renderer.Bind();
m_render_command->DrawIndexed(m_texture_renderer.GetQuadCount() * 6u);
}
2022-03-04 22:40:20 +03:30
// reset frame buffer
if (m_target_framebuffer)
{
m_target_framebuffer = nullptr;
m_render_command->DefaultTargetFramebuffer();
}
2022-03-04 22:40:20 +03:30
}
2022-03-04 22:40:20 +03:30
} // namespace Light