330 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			330 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <camera/scene.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
 |