527 lines
18 KiB
C++
Executable File
527 lines
18 KiB
C++
Executable File
#include <pch.hpp>
|
|
|
|
#include "renderer/editor_camera.hpp"
|
|
#include "renderer/uniform_buffer.hpp"
|
|
#include <renderer/render_command.hpp>
|
|
#include <renderer/vertex_array.hpp>
|
|
#include <renderer/renderer2d.hpp>
|
|
#include <renderer/texture.hpp>
|
|
#include <renderer/buffer.hpp>
|
|
#include <renderer/shader.hpp>
|
|
|
|
#include <glm/ext/quaternion_common.hpp>
|
|
#include <glm/ext/matrix_transform.hpp>
|
|
#include <glm/trigonometric.hpp>
|
|
#include <glm/fwd.hpp>
|
|
#include <cstdint>
|
|
|
|
namespace OpenEngine {
|
|
struct QuadVertex
|
|
{
|
|
glm::vec3 position;
|
|
glm::vec4 color;
|
|
glm::vec2 tex_coord;
|
|
float tex_index;
|
|
float tiling_factor;
|
|
int id = -1;
|
|
};
|
|
|
|
struct Renderer2DData
|
|
{
|
|
static const uint32_t max_quads = 20000;
|
|
static const uint32_t max_vertices = max_quads * 4;
|
|
static const uint32_t max_indices = max_quads * 6;
|
|
static const uint32_t max_texture_slots = 32;
|
|
|
|
Ref<VertexArray> vertex_array;
|
|
Ref<VertexBuffer> vertex_buffer;
|
|
Ref<Shader> texture_shader;
|
|
Ref<Texture2D> white_texture;
|
|
|
|
uint32_t quad_index_count = 0;
|
|
QuadVertex* quad_vertex_base = nullptr;
|
|
QuadVertex* quad_vertex_ptr = nullptr;
|
|
|
|
std::array<Ref<Texture2D>, max_texture_slots> texture_slots;
|
|
uint32_t texture_slot_index = 1; // 0 is white texture
|
|
|
|
glm::vec4 quad_vertex_positioning[4];
|
|
|
|
Statistics stats;
|
|
|
|
struct CameraData
|
|
{
|
|
glm::mat4 view_projection;
|
|
};
|
|
CameraData camera_buffer;
|
|
Ref<UniformBuffer> camera_uniform_buffer;
|
|
};
|
|
|
|
static Renderer2DData renderer_data;
|
|
|
|
void Renderer2D::Init()
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
renderer_data.vertex_array = VertexArray::Create();
|
|
renderer_data.vertex_buffer = VertexBuffer::Create(renderer_data.max_vertices * sizeof(QuadVertex));
|
|
|
|
BufferLayout layout = {
|
|
{ ShaderDataType::Float3, "a_Position" },
|
|
{ ShaderDataType::Float4, "a_Color" },
|
|
{ ShaderDataType::Float2, "a_TexCoords" },
|
|
{ ShaderDataType::Float, "a_TexIndex" },
|
|
{ ShaderDataType::Float, "a_TilingFactor" },
|
|
{ ShaderDataType::Int, "a_EntityID"}
|
|
};
|
|
|
|
renderer_data.vertex_buffer->SetLayout(layout);
|
|
renderer_data.vertex_array->AddVertexBuffer(renderer_data.vertex_buffer);
|
|
|
|
renderer_data.quad_vertex_base = new QuadVertex[renderer_data.max_vertices];
|
|
|
|
uint32_t* quad_indices = new uint32_t[renderer_data.max_indices];
|
|
|
|
uint32_t offset = 0;
|
|
for (uint32_t i = 0; i < renderer_data.max_indices; i += 6) {
|
|
quad_indices[i + 0] = offset + 0;
|
|
quad_indices[i + 1] = offset + 1;
|
|
quad_indices[i + 2] = offset + 2;
|
|
|
|
quad_indices[i + 3] = offset + 2;
|
|
quad_indices[i + 4] = offset + 3;
|
|
quad_indices[i + 5] = offset + 0;
|
|
|
|
offset += 4;
|
|
}
|
|
|
|
Ref<IndexBuffer> index_buffer = IndexBuffer::Create(quad_indices, renderer_data.max_indices);
|
|
renderer_data.vertex_array->SetIndexBuffer(index_buffer);
|
|
delete[] quad_indices;
|
|
|
|
renderer_data.white_texture = Texture2D::Create(1, 1);
|
|
uint32_t white_texture_data = 0xffffffff;
|
|
renderer_data.white_texture->SetData(&white_texture_data, sizeof(uint32_t));
|
|
|
|
int32_t samplers[renderer_data.max_texture_slots];
|
|
for (uint32_t i = 0; i < renderer_data.max_texture_slots; i++)
|
|
samplers[i] = i;
|
|
|
|
renderer_data.texture_shader = Shader::Create("assets/shaders/texture.glsl");
|
|
|
|
renderer_data.texture_slots[0] = renderer_data.white_texture;
|
|
|
|
renderer_data.quad_vertex_positioning[0] = {-0.5, -0.5, 0.0f, 1.0f};
|
|
renderer_data.quad_vertex_positioning[1] = {0.5, -0.5, 0.0f, 1.0f};
|
|
renderer_data.quad_vertex_positioning[2] = {0.5, 0.5, 0.0f, 1.0f};
|
|
renderer_data.quad_vertex_positioning[3] = {-0.5, 0.5, 0.0f, 1.0f};
|
|
|
|
renderer_data.camera_uniform_buffer = UniformBuffer::Create(sizeof(Renderer2DData), 0);
|
|
}
|
|
|
|
void Renderer2D::Shutdown()
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
renderer_data.white_texture.reset();
|
|
renderer_data.vertex_array.reset();
|
|
renderer_data.vertex_buffer.reset();
|
|
renderer_data.texture_shader.reset();
|
|
|
|
delete[] renderer_data.quad_vertex_base;
|
|
|
|
for (uint32_t i = 0; i < renderer_data.texture_slot_index; i++)
|
|
renderer_data.texture_slots[i].reset();
|
|
}
|
|
|
|
void Renderer2D::BeginScene(const OrthographicCamera& camera)
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
renderer_data.camera_buffer.view_projection = camera.GetViewProjectionMatrix();
|
|
renderer_data.camera_uniform_buffer->SetData(&renderer_data.camera_buffer, sizeof(Renderer2DData::CameraData));
|
|
|
|
StartBatch();
|
|
}
|
|
|
|
void Renderer2D::BeginScene(const Camera& camera, const glm::mat4& transform)
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
renderer_data.camera_buffer.view_projection = camera.GetProjection() * glm::inverse(transform);
|
|
renderer_data.camera_uniform_buffer->SetData(&renderer_data.camera_buffer, sizeof(Renderer2DData::CameraData));
|
|
|
|
StartBatch();
|
|
}
|
|
|
|
void Renderer2D::BeginScene(const EditorCamera& camera)
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
renderer_data.camera_buffer.view_projection = camera.GetViewProjection();
|
|
renderer_data.camera_uniform_buffer->SetData(&renderer_data.camera_buffer, sizeof(Renderer2DData::CameraData));
|
|
|
|
StartBatch();
|
|
}
|
|
|
|
void Renderer2D::EndScene()
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
uint32_t data_size = (uint8_t*)renderer_data.quad_vertex_ptr - (uint8_t*)renderer_data.quad_vertex_base;
|
|
renderer_data.vertex_buffer->SetData(renderer_data.quad_vertex_base, data_size);
|
|
|
|
Flush();
|
|
}
|
|
|
|
void Renderer2D::Flush()
|
|
{
|
|
if (renderer_data.quad_index_count == 0)
|
|
return;
|
|
|
|
renderer_data.vertex_array->Bind();
|
|
|
|
for (int i = 0; i < renderer_data.texture_slot_index; i++)
|
|
renderer_data.texture_slots[i]->Bind(i);
|
|
|
|
renderer_data.texture_shader->Bind();
|
|
RenderCommand::DrawIndexed(renderer_data.vertex_array, renderer_data.quad_index_count);
|
|
|
|
renderer_data.stats.draw_calls++;
|
|
}
|
|
|
|
void Renderer2D::DrawQuad(const Transform& transform_data,
|
|
const Ref<Texture2D>& texture, int entity_id, float tiling_factor)
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
constexpr size_t quad_vertex_count = 4;
|
|
constexpr glm::vec2 texture_coords[] = { { 0.0f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f }};
|
|
|
|
if (renderer_data.quad_index_count >= Renderer2DData::max_indices)
|
|
FlushAndReset();
|
|
|
|
constexpr glm::vec4 color = glm::vec4(1.0f);
|
|
|
|
glm::vec3 position = transform_data.position;
|
|
glm::vec3 size = transform_data.size;
|
|
|
|
float texture_index = 0;
|
|
for (uint32_t i = 1; i < renderer_data.texture_slot_index; i++) {
|
|
if (*renderer_data.texture_slots[i].get() == *texture.get()) {
|
|
texture_index = (float)i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (texture_index == 0) {
|
|
if (renderer_data.texture_slot_index >= Renderer2DData::max_texture_slots)
|
|
FlushAndReset();
|
|
|
|
texture_index = (float)renderer_data.texture_slot_index;
|
|
renderer_data.texture_slots[renderer_data.texture_slot_index] = texture;
|
|
renderer_data.texture_slot_index++;
|
|
}
|
|
|
|
glm::mat4 transform = glm::translate(glm::mat4(1.0f), transform_data.position)
|
|
* glm::rotate(glm::mat4(1.0f), glm::radians(transform_data.rotation), { 0.0f, 0.0f, 1.0f })
|
|
* glm::scale(glm::mat4(1.0f), transform_data.size);
|
|
|
|
DrawQuad(transform, texture, entity_id);
|
|
}
|
|
|
|
void Renderer2D::DrawQuad(const Transform& transform_data,
|
|
const Ref<Texture2D>& texture, const glm::vec4& color,
|
|
int entity_id, float tiling_factor)
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
constexpr size_t quad_vertex_count = 4;
|
|
constexpr glm::vec2 texture_coords[] = { { 0.0f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f }};
|
|
|
|
if (renderer_data.quad_index_count >= Renderer2DData::max_indices)
|
|
FlushAndReset();
|
|
|
|
glm::vec3 position = transform_data.position;
|
|
glm::vec3 size = transform_data.size;
|
|
|
|
float texture_index = 0;
|
|
for (uint32_t i = 1; i < renderer_data.texture_slot_index; i++) {
|
|
if (*renderer_data.texture_slots[i].get() == *texture.get()) {
|
|
texture_index = (float)i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (texture_index == 0) {
|
|
if (renderer_data.texture_slot_index >= Renderer2DData::max_texture_slots)
|
|
FlushAndReset();
|
|
|
|
texture_index = (float)renderer_data.texture_slot_index;
|
|
renderer_data.texture_slots[renderer_data.texture_slot_index] = texture;
|
|
renderer_data.texture_slot_index++;
|
|
}
|
|
|
|
glm::mat4 transform = glm::translate(glm::mat4(1.0f), transform_data.position)
|
|
* glm::rotate(glm::mat4(1.0f), glm::radians(transform_data.rotation), { 0.0f, 0.0f, 1.0f })
|
|
* glm::scale(glm::mat4(1.0f), transform_data.size);
|
|
}
|
|
|
|
void Renderer2D::DrawQuad(const Transform& transform_data,
|
|
const Ref<Subtexture2D>& subtexture, int entity_id,
|
|
float tiling_factor)
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
constexpr size_t quad_vertex_count = 4;
|
|
const glm::vec2* texture_coords = subtexture->GetCoords();
|
|
const Ref<Texture2D>& texture = subtexture->GetTexture();
|
|
|
|
if (renderer_data.quad_index_count >= Renderer2DData::max_indices)
|
|
FlushAndReset();
|
|
|
|
constexpr glm::vec4 color = glm::vec4(1.0f);
|
|
|
|
glm::vec3 position = transform_data.position;
|
|
glm::vec3 size = transform_data.size;
|
|
|
|
float texture_index = 0;
|
|
for (uint32_t i = 1; i < renderer_data.texture_slot_index; i++) {
|
|
if (*renderer_data.texture_slots[i].get() == *texture.get()) {
|
|
texture_index = (float)i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (texture_index == 0) {
|
|
if (renderer_data.texture_slot_index >= Renderer2DData::max_texture_slots)
|
|
FlushAndReset();
|
|
|
|
texture_index = (float)renderer_data.texture_slot_index;
|
|
renderer_data.texture_slots[renderer_data.texture_slot_index] = texture;
|
|
renderer_data.texture_slot_index++;
|
|
}
|
|
|
|
glm::mat4 transform = glm::translate(glm::mat4(1.0f), transform_data.position)
|
|
* glm::rotate(glm::mat4(1.0f), glm::radians(transform_data.rotation), { 0.0f, 0.0f, 1.0f })
|
|
* glm::scale(glm::mat4(1.0f), transform_data.size);
|
|
|
|
DrawQuad(transform, subtexture, entity_id);
|
|
}
|
|
|
|
void Renderer2D::DrawQuad(const Transform& transform_data,
|
|
const glm::vec4& color, int entity_id)
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
constexpr size_t quad_vertex_count = 4;
|
|
constexpr glm::vec2 texture_coords[] = { { 0.0f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f }};
|
|
|
|
if (renderer_data.quad_index_count >= Renderer2DData::max_indices)
|
|
FlushAndReset();
|
|
|
|
glm::vec3 position = transform_data.position;
|
|
glm::vec3 size = transform_data.size;
|
|
|
|
glm::mat4 transform = glm::translate(glm::mat4(1.0f), transform_data.position)
|
|
* glm::rotate(glm::mat4(1.0f), glm::radians(transform_data.rotation), { 0.0f, 0.0f, 1.0f })
|
|
* glm::scale(glm::mat4(1.0f), transform_data.size);
|
|
|
|
|
|
DrawQuad(transform, color, entity_id);
|
|
}
|
|
|
|
void Renderer2D::DrawQuad(const glm::mat4& transform,
|
|
const Ref<Texture2D>& texture, int entity_id, float tiling_factor)
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
constexpr size_t quad_vertex_count = 4;
|
|
constexpr glm::vec2 texture_coords[] = { { 0.0f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f }};
|
|
|
|
if (renderer_data.quad_index_count >= Renderer2DData::max_indices)
|
|
FlushAndReset();
|
|
|
|
constexpr glm::vec4 color = glm::vec4(1.0f);
|
|
|
|
float texture_index = 0;
|
|
for (uint32_t i = 1; i < renderer_data.texture_slot_index; i++) {
|
|
if (*renderer_data.texture_slots[i].get() == *texture.get()) {
|
|
texture_index = (float)i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (texture_index == 0) {
|
|
if (renderer_data.texture_slot_index >= Renderer2DData::max_texture_slots)
|
|
FlushAndReset();
|
|
|
|
texture_index = (float)renderer_data.texture_slot_index;
|
|
renderer_data.texture_slots[renderer_data.texture_slot_index] = texture;
|
|
renderer_data.texture_slot_index++;
|
|
}
|
|
|
|
for (size_t i = 0; i < quad_vertex_count; i++) {
|
|
renderer_data.quad_vertex_ptr->position = transform * renderer_data.quad_vertex_positioning[i];
|
|
renderer_data.quad_vertex_ptr->color = color;
|
|
renderer_data.quad_vertex_ptr->tex_coord = texture_coords[i];
|
|
renderer_data.quad_vertex_ptr->tex_index = texture_index;
|
|
renderer_data.quad_vertex_ptr->tiling_factor = tiling_factor;
|
|
renderer_data.quad_vertex_ptr->id = entity_id;
|
|
renderer_data.quad_vertex_ptr++;
|
|
}
|
|
|
|
renderer_data.quad_index_count += 6;
|
|
renderer_data.stats.quad_count++;
|
|
}
|
|
|
|
void Renderer2D::DrawQuad(const glm::mat4& transform,
|
|
const Ref<Texture2D>& texture, const glm::vec4& color,
|
|
int entity_id, float tiling_factor)
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
constexpr size_t quad_vertex_count = 4;
|
|
constexpr glm::vec2 texture_coords[] = { { 0.0f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f }};
|
|
|
|
if (renderer_data.quad_index_count >= Renderer2DData::max_indices)
|
|
FlushAndReset();
|
|
|
|
float texture_index = 0;
|
|
for (uint32_t i = 1; i < renderer_data.texture_slot_index; i++) {
|
|
if (*renderer_data.texture_slots[i].get() == *texture.get()) {
|
|
texture_index = (float)i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (texture_index == 0) {
|
|
if (renderer_data.texture_slot_index >= Renderer2DData::max_texture_slots)
|
|
FlushAndReset();
|
|
|
|
texture_index = (float)renderer_data.texture_slot_index;
|
|
renderer_data.texture_slots[renderer_data.texture_slot_index] = texture;
|
|
renderer_data.texture_slot_index++;
|
|
}
|
|
|
|
for (size_t i = 0; i < quad_vertex_count; i++) {
|
|
renderer_data.quad_vertex_ptr->position = transform * renderer_data.quad_vertex_positioning[i];
|
|
renderer_data.quad_vertex_ptr->color = color;
|
|
renderer_data.quad_vertex_ptr->tex_coord = texture_coords[i];
|
|
renderer_data.quad_vertex_ptr->tex_index = texture_index;
|
|
renderer_data.quad_vertex_ptr->tiling_factor = tiling_factor;
|
|
renderer_data.quad_vertex_ptr->id = entity_id;
|
|
renderer_data.quad_vertex_ptr++;
|
|
}
|
|
|
|
renderer_data.quad_index_count += 6;
|
|
renderer_data.stats.quad_count++;
|
|
}
|
|
|
|
void Renderer2D::DrawQuad(const glm::mat4& transform,
|
|
const Ref<Subtexture2D>& subtexture, int entity_id,
|
|
float tiling_factor)
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
constexpr size_t quad_vertex_count = 4;
|
|
const glm::vec2* texture_coords = subtexture->GetCoords();
|
|
const Ref<Texture2D>& texture = subtexture->GetTexture();
|
|
|
|
if (renderer_data.quad_index_count >= Renderer2DData::max_indices)
|
|
FlushAndReset();
|
|
|
|
constexpr glm::vec4 color = glm::vec4(1.0f);
|
|
|
|
float texture_index = 0;
|
|
for (uint32_t i = 1; i < renderer_data.texture_slot_index; i++) {
|
|
if (*renderer_data.texture_slots[i].get() == *texture.get()) {
|
|
texture_index = (float)i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (texture_index == 0) {
|
|
if (renderer_data.texture_slot_index >= Renderer2DData::max_texture_slots)
|
|
FlushAndReset();
|
|
|
|
texture_index = (float)renderer_data.texture_slot_index;
|
|
renderer_data.texture_slots[renderer_data.texture_slot_index] = texture;
|
|
renderer_data.texture_slot_index++;
|
|
}
|
|
|
|
for (size_t i = 0; i < quad_vertex_count; i++) {
|
|
renderer_data.quad_vertex_ptr->position = transform * renderer_data.quad_vertex_positioning[i];
|
|
renderer_data.quad_vertex_ptr->color = color;
|
|
renderer_data.quad_vertex_ptr->tex_coord = texture_coords[i];
|
|
renderer_data.quad_vertex_ptr->tex_index = texture_index;
|
|
renderer_data.quad_vertex_ptr->tiling_factor = tiling_factor;
|
|
renderer_data.quad_vertex_ptr->id = entity_id;
|
|
renderer_data.quad_vertex_ptr++;
|
|
}
|
|
|
|
renderer_data.quad_index_count += 6;
|
|
renderer_data.stats.quad_count++;
|
|
}
|
|
|
|
void Renderer2D::DrawQuad(const glm::mat4& transform,
|
|
const glm::vec4& color, int entity_id)
|
|
{
|
|
OE_PROFILE_FUNCTION();
|
|
|
|
constexpr size_t quad_vertex_count = 4;
|
|
constexpr glm::vec2 texture_coords[] = { { 0.0f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f }};
|
|
|
|
if (renderer_data.quad_index_count >= Renderer2DData::max_indices)
|
|
FlushAndReset();
|
|
|
|
for (size_t i = 0; i < quad_vertex_count; i++) {
|
|
renderer_data.quad_vertex_ptr->position = transform * renderer_data.quad_vertex_positioning[i];
|
|
renderer_data.quad_vertex_ptr->color = color;
|
|
renderer_data.quad_vertex_ptr->tex_coord = texture_coords[i];
|
|
renderer_data.quad_vertex_ptr->tex_index = 0;
|
|
renderer_data.quad_vertex_ptr->tiling_factor = 1.0f;
|
|
renderer_data.quad_vertex_ptr->id = entity_id;
|
|
renderer_data.quad_vertex_ptr++;
|
|
}
|
|
|
|
renderer_data.quad_index_count += 6;
|
|
renderer_data.stats.quad_count++;
|
|
}
|
|
|
|
|
|
void Renderer2D::ResetStats()
|
|
{
|
|
memset(&renderer_data.stats, 0, sizeof(Statistics));
|
|
}
|
|
|
|
const Statistics& Renderer2D::GetStats()
|
|
{
|
|
return renderer_data.stats;
|
|
}
|
|
|
|
void Renderer2D::FlushAndReset()
|
|
{
|
|
EndScene();
|
|
|
|
renderer_data.quad_index_count = 0;
|
|
renderer_data.quad_vertex_ptr = renderer_data.quad_vertex_base;
|
|
|
|
renderer_data.texture_slot_index = 1;
|
|
}
|
|
|
|
void Renderer2D::StartBatch()
|
|
{
|
|
renderer_data.quad_index_count = 0;
|
|
renderer_data.quad_vertex_ptr = renderer_data.quad_vertex_base;
|
|
|
|
renderer_data.texture_slot_index = 1;
|
|
}
|
|
|
|
void Renderer2D::NextBatch()
|
|
{
|
|
Flush();
|
|
StartBatch();
|
|
}
|
|
}
|