330 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			330 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include <ecs/registry.hpp>
 | 
						|
#include <input/events/window.hpp>
 | 
						|
#include <lt_debug/assertions.hpp>
 | 
						|
#include <renderer/blender.hpp>
 | 
						|
#include <renderer/buffers.hpp>
 | 
						|
#include <renderer/framebuffer.hpp>
 | 
						|
#include <renderer/programs/quad.hpp>
 | 
						|
#include <renderer/programs/texture.hpp>
 | 
						|
#include <renderer/programs/tinted_texture.hpp>
 | 
						|
#include <renderer/render_command.hpp>
 | 
						|
#include <renderer/renderer.hpp>
 | 
						|
#include <renderer/shader.hpp>
 | 
						|
#include <renderer/texture.hpp>
 | 
						|
 | 
						|
namespace lt {
 | 
						|
 | 
						|
Renderer *Renderer::s_context = nullptr;
 | 
						|
 | 
						|
Renderer::Renderer(const Ref<SharedContext> &shared_context, CreateInfo create_info)
 | 
						|
    : m_quad_renderer(
 | 
						|
          create_scope<QuadRendererProgram>(
 | 
						|
              LT_MAX_QUAD_RENDERER_VERTICES,
 | 
						|
              shared_context,
 | 
						|
              std::move(create_info.quad_renderer_shader)
 | 
						|
          )
 | 
						|
      )
 | 
						|
    , m_texture_renderer(
 | 
						|
          create_scope<TextureRendererProgram>(
 | 
						|
              LT_MAX_TEXTURE_RENDERER_VERTICES,
 | 
						|
              shared_context,
 | 
						|
              std::move(create_info.texture_renderer_shader)
 | 
						|
          )
 | 
						|
      )
 | 
						|
    , m_tinted_texture_renderer(
 | 
						|
          create_scope<TintedTextureRendererProgram>(
 | 
						|
              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)
 | 
						|
 | 
						|
{
 | 
						|
	ensure(!s_context, "An instance of 'renderer' already exists, do not construct this class!");
 | 
						|
	s_context = this;
 | 
						|
 | 
						|
	m_view_projection_buffer = ConstantBuffer::create(
 | 
						|
	    ConstantBufferIndex::ViewProjection,
 | 
						|
	    sizeof(math::mat4),
 | 
						|
	    shared_context
 | 
						|
	);
 | 
						|
 | 
						|
	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);
 | 
						|
}
 | 
						|
 | 
						|
Renderer::~Renderer() // NOLINT
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
auto Renderer::create(Ref<SharedContext> sharedContext, CreateInfo create_info) -> Scope<Renderer>
 | 
						|
{
 | 
						|
	return make_scope<Renderer>(new Renderer(std::move(sharedContext), std::move(create_info)));
 | 
						|
}
 | 
						|
 | 
						|
void Renderer::on_window_resize(const WindowResizedEvent &event)
 | 
						|
{
 | 
						|
	m_render_command->set_viewport(0u, 0u, event.get_size().x, event.get_size().y);
 | 
						|
}
 | 
						|
 | 
						|
//======================================== DRAW_QUAD ========================================//
 | 
						|
/* tinted textures */
 | 
						|
void Renderer::draw_quad_impl(
 | 
						|
    const math::vec3 &position,
 | 
						|
    const math::vec2 &size,
 | 
						|
    const math::vec4 &tint,
 | 
						|
    Ref<Texture> texture
 | 
						|
)
 | 
						|
{
 | 
						|
	draw_quad(
 | 
						|
	    math::translate(position) * math::scale(math::vec3 { size.x, size.y, 1.0f }),
 | 
						|
	    tint,
 | 
						|
	    texture
 | 
						|
	);
 | 
						|
}
 | 
						|
 | 
						|
/* tint */
 | 
						|
void Renderer::draw_quad_impl(
 | 
						|
    const math::vec3 &position,
 | 
						|
    const math::vec2 &size,
 | 
						|
    const math::vec4 &tint
 | 
						|
)
 | 
						|
{
 | 
						|
	draw_quad(math::translate(position) * math::scale(math::vec3 { size.x, size.y, 1.0f }), tint);
 | 
						|
}
 | 
						|
 | 
						|
/* texture */
 | 
						|
void Renderer::draw_quad_impl(
 | 
						|
    const math::vec3 &position,
 | 
						|
    const math::vec2 &size,
 | 
						|
    Ref<Texture> texture
 | 
						|
)
 | 
						|
{
 | 
						|
	draw_quad(
 | 
						|
	    math::translate(position) * math::scale(math::vec3 { size.x, size.y, 1.0f }),
 | 
						|
	    texture
 | 
						|
	);
 | 
						|
}
 | 
						|
//======================================== DRAW_QUAD ========================================//
 | 
						|
 | 
						|
//==================== DRAW_QUAD_TINT ====================//
 | 
						|
void Renderer::draw_quad_impl(const math::mat4 &transform, const math::vec4 &tint)
 | 
						|
{
 | 
						|
	auto map = std::span<QuadRendererProgram::QuadVertexData> { m_quad_renderer->get_map_current(),
 | 
						|
		                                                        4 };
 | 
						|
 | 
						|
	// top left
 | 
						|
	map[0].position = transform * math::vec4(-0.5f, -0.5f, 0.0f, 1.0f);
 | 
						|
	map[0].tint = tint;
 | 
						|
 | 
						|
	// top right
 | 
						|
	map[1].position = transform * math::vec4(0.5f, -0.5f, 0.0f, 1.0f);
 | 
						|
	map[1].tint = tint;
 | 
						|
 | 
						|
	// bottom right
 | 
						|
	map[2].position = transform * math::vec4(0.5f, 0.5f, 0.0f, 1.0f);
 | 
						|
	map[2].tint = tint;
 | 
						|
 | 
						|
	// bottom left
 | 
						|
	map[3].position = transform * math::vec4(-0.5f, 0.5f, 0.0f, 1.0f);
 | 
						|
	map[3].tint = tint;
 | 
						|
 | 
						|
	// advance
 | 
						|
	if (!m_quad_renderer->advance())
 | 
						|
	{
 | 
						|
		log_wrn("Exceeded LT_MAX_QUAD_RENDERER_VERTICES: {}", LT_MAX_QUAD_RENDERER_VERTICES);
 | 
						|
		flush_scene();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Renderer::draw_quad_impl(const math::mat4 &transform, const Ref<Texture> &texture)
 | 
						|
{
 | 
						|
	ensure(texture, "Texture passed to renderer::draw_quad_impl");
 | 
						|
 | 
						|
	texture->bind();
 | 
						|
	auto map = std::span<TextureRendererProgram::TextureVertexData> {
 | 
						|
		m_texture_renderer->get_map_current(),
 | 
						|
		4
 | 
						|
	};
 | 
						|
 | 
						|
	// top left
 | 
						|
	map[0].position = transform * math::vec4(-0.5f, -0.5f, 0.0f, 1.0f);
 | 
						|
	map[0].texcoord = { 0.0f, 0.0f };
 | 
						|
 | 
						|
	// top right
 | 
						|
	map[1].position = transform * math::vec4(0.5f, -0.5f, 0.0f, 1.0f);
 | 
						|
	map[1].texcoord = { 1.0f, 0.0f };
 | 
						|
 | 
						|
	// bottom right
 | 
						|
	map[2].position = transform * math::vec4(0.5f, 0.5f, 0.0f, 1.0f);
 | 
						|
	map[2].texcoord = { 1.0f, 1.0f };
 | 
						|
 | 
						|
	// bottom left
 | 
						|
	map[3].position = transform * math::vec4(-0.5f, 0.5f, 0.0f, 1.0f);
 | 
						|
	map[3].texcoord = { 0.0f, 1.0f };
 | 
						|
 | 
						|
	// advance
 | 
						|
	if (!m_texture_renderer->advance())
 | 
						|
	{
 | 
						|
		log_wrn("Exceeded LT_MAX_TEXTURE_RENDERER_VERTICES: {}", LT_MAX_TEXTURE_RENDERER_VERTICES);
 | 
						|
		flush_scene();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Renderer::draw_quad_impl(
 | 
						|
    const math::mat4 &transform,
 | 
						|
    const math::vec4 &tint,
 | 
						|
    const Ref<Texture> &texture
 | 
						|
)
 | 
						|
{
 | 
						|
	ensure(texture, "Texture passed to renderer::draw_quad_impl");
 | 
						|
 | 
						|
	texture->bind();
 | 
						|
	auto map = std::span<TintedTextureRendererProgram::TintedTextureVertexData> {
 | 
						|
		m_tinted_texture_renderer->get_map_current(),
 | 
						|
		4
 | 
						|
	};
 | 
						|
 | 
						|
	// top left
 | 
						|
	map[0].position = transform * math::vec4(-0.5f, -0.5f, 0.0f, 1.0f);
 | 
						|
	map[0].tint = tint;
 | 
						|
	map[0].texcoord = { 0.0f, 0.0f };
 | 
						|
 | 
						|
	// top right
 | 
						|
	map[1].position = transform * math::vec4(0.5f, -0.5f, 0.0f, 1.0f);
 | 
						|
	map[1].tint = tint;
 | 
						|
	map[1].texcoord = { 1.0f, 0.0f };
 | 
						|
 | 
						|
	// bottom right
 | 
						|
	map[2].position = transform * math::vec4(0.5f, 0.5f, 0.0f, 1.0f);
 | 
						|
	map[2].tint = tint;
 | 
						|
	map[2].texcoord = { 1.0f, 1.0f };
 | 
						|
 | 
						|
	// bottom left
 | 
						|
	map[3].position = transform * math::vec4(-0.5f, 0.5f, 0.0f, 1.0f);
 | 
						|
	map[3].tint = tint;
 | 
						|
	map[3].texcoord = { 0.0f, 1.0f };
 | 
						|
 | 
						|
	if (!m_tinted_texture_renderer->advance())
 | 
						|
	{
 | 
						|
		log_wrn("Exceeded LT_MAX_TEXTURE_RENDERER_VERTICES: {}", LT_MAX_TEXTURE_RENDERER_VERTICES);
 | 
						|
		flush_scene();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void Renderer::begin_frame()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void Renderer::end_frame()
 | 
						|
{
 | 
						|
	m_render_command->swap_buffers();
 | 
						|
	m_render_command->clear_back_buffer(
 | 
						|
	    m_default_framebuffer_camera ? m_default_framebuffer_camera->get_background_color() :
 | 
						|
	                                   math::vec4(0.0f)
 | 
						|
	);
 | 
						|
 | 
						|
	m_default_framebuffer_camera = nullptr;
 | 
						|
}
 | 
						|
 | 
						|
void Renderer::begin_scene_impl(
 | 
						|
    Camera *camera,
 | 
						|
    const math::mat4 &cameraTransform,
 | 
						|
    const Ref<Framebuffer> &targetFrameBuffer /* = nullptr */
 | 
						|
)
 | 
						|
{
 | 
						|
	// determine the target frame buffer
 | 
						|
	m_target_framebuffer = targetFrameBuffer;
 | 
						|
 | 
						|
	if (targetFrameBuffer)
 | 
						|
	{
 | 
						|
		targetFrameBuffer->bind_as_target(camera->get_background_color());
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		m_default_framebuffer_camera = camera;
 | 
						|
		m_render_command->default_target_framebuffer();
 | 
						|
	}
 | 
						|
 | 
						|
	// 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();
 | 
						|
 | 
						|
	// map renderers
 | 
						|
	m_quad_renderer->map();
 | 
						|
	m_texture_renderer->map();
 | 
						|
	m_tinted_texture_renderer->map();
 | 
						|
}
 | 
						|
 | 
						|
void Renderer::flush_scene()
 | 
						|
{
 | 
						|
	/* 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);
 | 
						|
	}
 | 
						|
 | 
						|
	/* 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);
 | 
						|
	}
 | 
						|
 | 
						|
	/* 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();
 | 
						|
}
 | 
						|
 | 
						|
void Renderer::end_scene_impl()
 | 
						|
{
 | 
						|
	/* 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);
 | 
						|
	}
 | 
						|
 | 
						|
	/* 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);
 | 
						|
	}
 | 
						|
 | 
						|
	/* 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);
 | 
						|
	}
 | 
						|
 | 
						|
	// reset frame buffer
 | 
						|
	if (m_target_framebuffer)
 | 
						|
	{
 | 
						|
		m_target_framebuffer = nullptr;
 | 
						|
		m_render_command->default_target_framebuffer();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
} // namespace lt
 |