light/modules/renderer/private/renderer.cpp

330 lines
8.4 KiB
C++
Raw Normal View History

#include <camera/scene.hpp>
#include <input/events/window.hpp>
2025-07-20 04:46:15 +03:30
#include <lt_debug/assertions.hpp>
#include <renderer/blender.hpp>
#include <renderer/buffers.hpp>
#include <renderer/framebuffer.hpp>
#include <renderer/render_command.hpp>
#include <renderer/renderer.hpp>
#include <renderer/shader.hpp>
#include <renderer/texture.hpp>
#include <span>
2025-07-12 19:24:11 +03:30
#include <utility>
2025-07-11 00:05:48 +03:30
namespace lt {
2021-05-30 16:45:54 +04:30
2025-07-06 14:02:50 +03:30
Renderer *Renderer::s_context = nullptr;
2025-07-05 13:28:41 +03:30
Renderer::Renderer(
GLFWwindow *window_handle,
2025-07-15 16:31:46 +03:30
const Ref<SharedContext> &shared_context,
CreateInfo create_info
)
: m_quad_renderer(
LT_MAX_QUAD_RENDERER_VERTICES,
shared_context,
std::move(create_info.quad_renderer_shader)
)
, m_texture_renderer(
LT_MAX_TEXTURE_RENDERER_VERTICES,
shared_context,
std::move(create_info.texture_renderer_shader)
)
, m_tinted_texture_renderer(
LT_MAX_TINTED_TEXTURE_RENDERER_VERTICES,
shared_context,
std::move(create_info.tinted_texture_renderer_shader)
)
, m_view_projection_buffer(nullptr)
, m_render_command(nullptr)
, m_blender(nullptr)
, m_target_framebuffer(nullptr)
2025-07-06 16:52:50 +03:30
2022-03-04 22:40:20 +03:30
{
2025-07-11 02:12:55 +03:30
ensure(!s_context, "An instance of 'renderer' already exists, do not construct this class!");
2025-07-05 16:07:51 +03:30
s_context = this;
2022-03-04 22:40:20 +03:30
m_view_projection_buffer = ConstantBuffer::create(
2025-07-05 13:28:41 +03:30
ConstantBufferIndex::ViewProjection,
sizeof(math::mat4),
shared_context
2025-07-05 13:28:41 +03:30
);
2022-03-04 22:40:20 +03:30
m_render_command = RenderCommand::create(window_handle, shared_context);
m_blender = Blender::create(shared_context);
m_blender->enable(BlendFactor::SRC_ALPHA, BlendFactor::INVERSE_SRC_ALPHA);
2022-03-04 22:40:20 +03:30
}
auto Renderer::create(
GLFWwindow *windowHandle,
Ref<SharedContext> sharedContext,
CreateInfo create_info
) -> Scope<Renderer>
2022-03-04 22:40:20 +03:30
{
return make_scope<Renderer>(
new Renderer(windowHandle, std::move(sharedContext), std::move(create_info))
);
2022-03-04 22:40:20 +03:30
}
2025-07-06 14:02:50 +03:30
void Renderer::on_window_resize(const WindowResizedEvent &event)
2022-03-04 22:40:20 +03:30
{
m_render_command->set_viewport(0u, 0u, event.get_size().x, event.get_size().y);
2022-03-04 22:40:20 +03:30
}
//======================================== DRAW_QUAD ========================================//
/* tinted textures */
2025-07-06 14:02:50 +03:30
void Renderer::draw_quad_impl(
const math::vec3 &position,
const math::vec2 &size,
const math::vec4 &tint,
2025-07-05 13:28:41 +03:30
Ref<Texture> texture
)
2022-03-04 22:40:20 +03:30
{
draw_quad(
math::translate(position) * math::scale(math::vec3 { size.x, size.y, 1.0f }),
2025-07-05 13:28:41 +03:30
tint,
texture
2025-07-05 13:28:41 +03:30
);
2022-03-04 22:40:20 +03:30
}
/* tint */
2025-07-06 14:02:50 +03:30
void Renderer::draw_quad_impl(
const math::vec3 &position,
const math::vec2 &size,
const math::vec4 &tint
2025-07-05 16:07:51 +03:30
)
2022-03-04 22:40:20 +03:30
{
draw_quad(math::translate(position) * math::scale(math::vec3 { size.x, size.y, 1.0f }), tint);
2022-03-04 22:40:20 +03:30
}
/* texture */
2025-07-06 14:02:50 +03:30
void Renderer::draw_quad_impl(
const math::vec3 &position,
const math::vec2 &size,
2025-07-05 16:07:51 +03:30
Ref<Texture> texture
)
2022-03-04 22:40:20 +03:30
{
draw_quad(
math::translate(position) * math::scale(math::vec3 { size.x, size.y, 1.0f }),
texture
2025-07-05 13:28:41 +03:30
);
2022-03-04 22:40:20 +03:30
}
//======================================== DRAW_QUAD ========================================//
//==================== DRAW_QUAD_TINT ====================//
void Renderer::draw_quad_impl(const math::mat4 &transform, const math::vec4 &tint)
2022-03-04 22:40:20 +03:30
{
2025-07-07 15:13:05 +03:30
auto map = std::span<QuadRendererProgram::QuadVertexData> { m_quad_renderer.get_map_current(),
4 };
2022-03-04 22:40:20 +03:30
// top left
map[0].position = transform * math::vec4(-0.5f, -0.5f, 0.0f, 1.0f);
2025-07-07 15:13:05 +03:30
map[0].tint = tint;
2022-03-04 22:40:20 +03:30
// top right
map[1].position = transform * math::vec4(0.5f, -0.5f, 0.0f, 1.0f);
2025-07-07 15:13:05 +03:30
map[1].tint = tint;
2022-03-04 22:40:20 +03:30
// bottom right
map[2].position = transform * math::vec4(0.5f, 0.5f, 0.0f, 1.0f);
2025-07-07 15:13:05 +03:30
map[2].tint = tint;
2022-03-04 22:40:20 +03:30
// bottom left
map[3].position = transform * math::vec4(-0.5f, 0.5f, 0.0f, 1.0f);
2025-07-07 15:13:05 +03:30
map[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
{
2025-07-06 16:30:38 +03:30
log_wrn("Exceeded LT_MAX_QUAD_RENDERER_VERTICES: {}", LT_MAX_QUAD_RENDERER_VERTICES);
flush_scene();
2022-03-04 22:40:20 +03:30
}
}
2021-05-30 16:45:54 +04:30
void Renderer::draw_quad_impl(const math::mat4 &transform, const Ref<Texture> &texture)
2022-03-04 22:40:20 +03:30
{
2025-07-11 02:12:55 +03:30
ensure(texture, "Texture passed to renderer::draw_quad_impl");
2021-07-09 11:56:31 +04:30
2025-07-07 15:13:05 +03:30
texture->bind();
auto map = std::span<TextureRendererProgram::TextureVertexData> {
m_texture_renderer.get_map_current(),
4
};
2021-05-30 16:45:54 +04:30
2022-03-04 22:40:20 +03:30
// top left
map[0].position = transform * math::vec4(-0.5f, -0.5f, 0.0f, 1.0f);
2025-07-07 15:13:05 +03:30
map[0].texcoord = { 0.0f, 0.0f };
2021-05-30 16:45:54 +04:30
2022-03-04 22:40:20 +03:30
// top right
map[1].position = transform * math::vec4(0.5f, -0.5f, 0.0f, 1.0f);
2025-07-07 15:13:05 +03:30
map[1].texcoord = { 1.0f, 0.0f };
2022-03-04 22:40:20 +03:30
// bottom right
map[2].position = transform * math::vec4(0.5f, 0.5f, 0.0f, 1.0f);
2025-07-07 15:13:05 +03:30
map[2].texcoord = { 1.0f, 1.0f };
2022-03-04 22:40:20 +03:30
// bottom left
map[3].position = transform * math::vec4(-0.5f, 0.5f, 0.0f, 1.0f);
2025-07-07 15:13:05 +03:30
map[3].texcoord = { 0.0f, 1.0f };
2022-03-04 22:40:20 +03:30
// advance
if (!m_texture_renderer.advance())
{
2025-07-06 16:30:38 +03:30
log_wrn("Exceeded LT_MAX_TEXTURE_RENDERER_VERTICES: {}", LT_MAX_TEXTURE_RENDERER_VERTICES);
flush_scene();
}
2022-03-04 22:40:20 +03:30
}
2025-07-06 14:02:50 +03:30
void Renderer::draw_quad_impl(
const math::mat4 &transform,
const math::vec4 &tint,
2025-07-06 16:52:50 +03:30
const Ref<Texture> &texture
2025-07-05 16:07:51 +03:30
)
2022-03-04 22:40:20 +03:30
{
2025-07-11 02:12:55 +03:30
ensure(texture, "Texture passed to renderer::draw_quad_impl");
2022-03-04 22:40:20 +03:30
2025-07-07 15:13:05 +03:30
texture->bind();
auto map = std::span<TintedTextureRendererProgram::TintedTextureVertexData> {
m_tinted_texture_renderer.get_map_current(),
4
};
2022-03-04 22:40:20 +03:30
// top left
map[0].position = transform * math::vec4(-0.5f, -0.5f, 0.0f, 1.0f);
2025-07-07 15:13:05 +03:30
map[0].tint = tint;
map[0].texcoord = { 0.0f, 0.0f };
2022-03-04 22:40:20 +03:30
// top right
map[1].position = transform * math::vec4(0.5f, -0.5f, 0.0f, 1.0f);
2025-07-07 15:13:05 +03:30
map[1].tint = tint;
map[1].texcoord = { 1.0f, 0.0f };
2022-03-04 22:40:20 +03:30
// bottom right
map[2].position = transform * math::vec4(0.5f, 0.5f, 0.0f, 1.0f);
2025-07-07 15:13:05 +03:30
map[2].tint = tint;
map[2].texcoord = { 1.0f, 1.0f };
2022-03-04 22:40:20 +03:30
// bottom left
map[3].position = transform * math::vec4(-0.5f, 0.5f, 0.0f, 1.0f);
2025-07-07 15:13:05 +03:30
map[3].tint = tint;
map[3].texcoord = { 0.0f, 1.0f };
2022-03-04 22:40:20 +03:30
if (!m_tinted_texture_renderer.advance())
{
2025-07-06 16:30:38 +03:30
log_wrn("Exceeded LT_MAX_TEXTURE_RENDERER_VERTICES: {}", LT_MAX_TEXTURE_RENDERER_VERTICES);
flush_scene();
}
2022-03-04 22:40:20 +03:30
}
2025-07-06 14:02:50 +03:30
void Renderer::begin_frame()
2022-03-04 22:40:20 +03:30
{
}
2025-07-06 14:02:50 +03:30
void Renderer::end_frame()
2022-03-04 22:40:20 +03:30
{
m_render_command->swap_buffers();
m_render_command->clear_back_buffer(
2025-07-06 14:02:50 +03:30
m_default_framebuffer_camera ? m_default_framebuffer_camera->get_background_color() :
math::vec4(0.0f)
2025-07-05 13:28:41 +03:30
);
2022-03-04 22:40:20 +03:30
m_default_framebuffer_camera = nullptr;
2022-03-04 22:40:20 +03:30
}
2025-07-06 14:02:50 +03:30
void Renderer::begin_scene_impl(
2025-07-05 13:28:41 +03:30
Camera *camera,
const math::mat4 &cameraTransform,
2025-07-05 13:28:41 +03:30
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)
2025-07-06 16:52:50 +03:30
{
2025-07-06 14:02:50 +03:30
targetFrameBuffer->bind_as_target(camera->get_background_color());
2025-07-06 16:52:50 +03:30
}
2022-03-04 22:40:20 +03:30
else
2021-05-30 16:45:54 +04:30
{
m_default_framebuffer_camera = camera;
m_render_command->default_target_framebuffer();
}
2022-03-04 22:40:20 +03:30
// update view projection buffer
auto *map = (math::mat4 *)m_view_projection_buffer->map();
map[0] = camera->get_projection() * math::inverse(cameraTransform);
m_view_projection_buffer->un_map();
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
}
2025-07-06 14:02:50 +03:30
void Renderer::flush_scene()
2022-03-04 22:40:20 +03:30
{
/* tinted texture renderer */
m_tinted_texture_renderer.un_map();
if (m_tinted_texture_renderer.get_quad_count())
{
m_tinted_texture_renderer.bind();
m_render_command->draw_indexed(m_tinted_texture_renderer.get_quad_count() * 6u);
}
2022-03-04 22:40:20 +03:30
/* quad renderer */
m_quad_renderer.un_map();
if (m_quad_renderer.get_quad_count())
{
m_quad_renderer.bind();
m_render_command->draw_indexed(m_quad_renderer.get_quad_count() * 6u);
}
2022-03-04 22:40:20 +03:30
/* texture renderer */
m_texture_renderer.un_map();
if (m_texture_renderer.get_quad_count())
{
m_texture_renderer.bind();
m_render_command->draw_indexed(m_texture_renderer.get_quad_count() * 6u);
}
m_quad_renderer.map();
m_texture_renderer.map();
m_tinted_texture_renderer.map();
2022-03-04 22:40:20 +03:30
}
2025-07-06 14:02:50 +03:30
void Renderer::end_scene_impl()
2022-03-04 22:40:20 +03:30
{
/* tinted texture renderer */
m_tinted_texture_renderer.un_map();
if (m_tinted_texture_renderer.get_quad_count())
2022-03-04 22:40:20 +03:30
{
m_tinted_texture_renderer.bind();
m_render_command->draw_indexed(m_tinted_texture_renderer.get_quad_count() * 6u);
}
2022-03-04 22:40:20 +03:30
/* quad renderer */
m_quad_renderer.un_map();
if (m_quad_renderer.get_quad_count())
{
m_quad_renderer.bind();
m_render_command->draw_indexed(m_quad_renderer.get_quad_count() * 6u);
}
2022-03-04 22:40:20 +03:30
/* texture renderer */
m_texture_renderer.un_map();
if (m_texture_renderer.get_quad_count())
{
m_texture_renderer.bind();
m_render_command->draw_indexed(m_texture_renderer.get_quad_count() * 6u);
}
2022-03-04 22:40:20 +03:30
// reset frame buffer
if (m_target_framebuffer)
{
m_target_framebuffer = nullptr;
m_render_command->default_target_framebuffer();
}
2022-03-04 22:40:20 +03:30
}
2025-07-11 00:05:48 +03:30
} // namespace lt