light/modules/renderer/src/renderer.cpp

339 lines
8.6 KiB
C++
Raw Normal View History

#include <camera/scene.hpp>
2025-07-11 14:05:59 +03:30
#include <debug/assertions.hpp>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
2022-03-04 22:40:20 +03:30
#include <glm/matrix.hpp>
#include <input/events/window.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,
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(glm::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(
2025-07-05 13:28:41 +03:30
const glm::vec3 &position,
const glm::vec2 &size,
const glm::vec4 &tint,
Ref<Texture> texture
)
2022-03-04 22:40:20 +03:30
{
draw_quad(
2025-07-05 13:28:41 +03:30
glm::translate(glm::mat4(1.0f), position)
* glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f }),
tint,
2025-07-06 16:52:50 +03:30
std::move(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(
2025-07-05 16:07:51 +03:30
const glm::vec3 &position,
const glm::vec2 &size,
const glm::vec4 &tint
)
2022-03-04 22:40:20 +03:30
{
draw_quad(
2025-07-05 13:28:41 +03:30
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-06 14:02:50 +03:30
void Renderer::draw_quad_impl(
2025-07-05 16:07:51 +03:30
const glm::vec3 &position,
const glm::vec2 &size,
Ref<Texture> texture
)
2022-03-04 22:40:20 +03:30
{
draw_quad(
2025-07-05 13:28:41 +03:30
glm::translate(glm::mat4(1.0f), position)
* glm::scale(glm::mat4(1.0f), { size.x, size.y, 1.0f }),
2025-07-06 16:52:50 +03:30
std::move(texture)
2025-07-05 13:28:41 +03:30
);
2022-03-04 22:40:20 +03:30
}
//======================================== DRAW_QUAD ========================================//
//==================== DRAW_QUAD_TINT ====================//
2025-07-06 14:02:50 +03:30
void Renderer::draw_quad_impl(const glm::mat4 &transform, const glm::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
2025-07-07 15:13:05 +03:30
map[0].position = transform * glm::vec4(-0.5f, -0.5f, 0.0f, 1.0f);
map[0].tint = tint;
2022-03-04 22:40:20 +03:30
// top right
2025-07-07 15:13:05 +03:30
map[1].position = transform * glm::vec4(0.5f, -0.5f, 0.0f, 1.0f);
map[1].tint = tint;
2022-03-04 22:40:20 +03:30
// bottom right
2025-07-07 15:13:05 +03:30
map[2].position = transform * glm::vec4(0.5f, 0.5f, 0.0f, 1.0f);
map[2].tint = tint;
2022-03-04 22:40:20 +03:30
// bottom left
2025-07-07 15:13:05 +03:30
map[3].position = transform * glm::vec4(-0.5f, 0.5f, 0.0f, 1.0f);
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
2025-07-06 16:52:50 +03:30
void Renderer::draw_quad_impl(const glm::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
2025-07-07 15:13:05 +03:30
map[0].position = transform * glm::vec4(-0.5f, -0.5f, 0.0f, 1.0f);
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
2025-07-07 15:13:05 +03:30
map[1].position = transform * glm::vec4(0.5f, -0.5f, 0.0f, 1.0f);
map[1].texcoord = { 1.0f, 0.0f };
2022-03-04 22:40:20 +03:30
// bottom right
2025-07-07 15:13:05 +03:30
map[2].position = transform * glm::vec4(0.5f, 0.5f, 0.0f, 1.0f);
map[2].texcoord = { 1.0f, 1.0f };
2022-03-04 22:40:20 +03:30
// bottom left
2025-07-07 15:13:05 +03:30
map[3].position = transform * glm::vec4(-0.5f, 0.5f, 0.0f, 1.0f);
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(
2025-07-05 16:07:51 +03:30
const glm::mat4 &transform,
const glm::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
2025-07-07 15:13:05 +03:30
map[0].position = transform * glm::vec4(-0.5f, -0.5f, 0.0f, 1.0f);
map[0].tint = tint;
map[0].texcoord = { 0.0f, 0.0f };
2022-03-04 22:40:20 +03:30
// top right
2025-07-07 15:13:05 +03:30
map[1].position = transform * glm::vec4(0.5f, -0.5f, 0.0f, 1.0f);
map[1].tint = tint;
map[1].texcoord = { 1.0f, 0.0f };
2022-03-04 22:40:20 +03:30
// bottom right
2025-07-07 15:13:05 +03:30
map[2].position = transform * glm::vec4(0.5f, 0.5f, 0.0f, 1.0f);
map[2].tint = tint;
map[2].texcoord = { 1.0f, 1.0f };
2022-03-04 22:40:20 +03:30
// bottom left
2025-07-07 15:13:05 +03:30
map[3].position = transform * glm::vec4(-0.5f, 0.5f, 0.0f, 1.0f);
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() :
2025-07-05 16:07:51 +03:30
glm::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 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)
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
2025-07-06 16:52:50 +03:30
auto *map = (glm::mat4 *)m_view_projection_buffer->map();
2025-07-06 14:02:50 +03:30
map[0] = camera->get_projection() * glm::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