Browse Source

Convert Renderer2D to singleton pattern

master
Riyyi 4 years ago
parent
commit
b8438ad3e7
  1. 15
      inferno/src/inferno/application.cpp
  2. 217
      inferno/src/inferno/render/renderer.cpp
  3. 99
      inferno/src/inferno/render/renderer.h

15
inferno/src/inferno/application.cpp

@ -46,7 +46,8 @@ namespace Inferno {
m_cameraO = std::make_shared<OrthographicCamera>(); m_cameraO = std::make_shared<OrthographicCamera>();
m_cameraP = std::make_shared<PerspectiveCamera>(); m_cameraP = std::make_shared<PerspectiveCamera>();
Renderer2D::initialize(); Renderer2D* renderer2D = new Renderer2D();
renderer2D->initialize();
// Load assets // Load assets
@ -56,7 +57,7 @@ namespace Inferno {
Application::~Application() Application::~Application()
{ {
Renderer2D::destroy(); Renderer2D::the().destroy();
TextureManager::the().destroy(); TextureManager::the().destroy();
ShaderManager::the().destroy(); ShaderManager::the().destroy();
// Input::destroy(); // Input::destroy();
@ -102,13 +103,13 @@ namespace Inferno {
RenderCommand::clearColor({ 0.2f, 0.3f, 0.3f, 1.0f }); RenderCommand::clearColor({ 0.2f, 0.3f, 0.3f, 1.0f });
RenderCommand::clear(); RenderCommand::clear();
Renderer2D::beginScene(m_cameraP); // camera, lights, environment Renderer2D::the().beginScene(m_cameraP); // camera, lights, environment
Renderer2D::drawQuad(std::make_shared<Transform>(cube), colors); Renderer2D::the().drawQuad(std::make_shared<Transform>(cube), colors);
Renderer2D::drawQuad(std::make_shared<Transform>(cube2), { 0.5f, 0.6f, 0.8f, 1.0f }, m_texture); Renderer2D::the().drawQuad(std::make_shared<Transform>(cube2), { 0.5f, 0.6f, 0.8f, 1.0f }, m_texture);
Renderer2D::drawQuad(std::make_shared<Transform>(cube3), { 1.0f, 1.0f, 1.0f, 1.0f }, m_texture2); Renderer2D::the().drawQuad(std::make_shared<Transform>(cube3), { 1.0f, 1.0f, 1.0f, 1.0f }, m_texture2);
Renderer2D::endScene(); Renderer2D::the().endScene();
m_window->render(); m_window->render();

217
inferno/src/inferno/render/renderer.cpp

@ -3,6 +3,7 @@
#include <glad/glad.h> #include <glad/glad.h>
#include "inferno/assertions.h"
#include "inferno/component/transform.h" #include "inferno/component/transform.h"
#include "inferno/render/buffer.h" #include "inferno/render/buffer.h"
#include "inferno/render/camera.h" #include "inferno/render/camera.h"
@ -37,68 +38,129 @@ namespace Inferno {
// ----------------------------------------- // -----------------------------------------
std::shared_ptr<Camera> Renderer2D::s_camera = nullptr; uint32_t Renderer::m_supportedTextureUnitPerBatch = 0;
QuadBatch* Renderer2D::s_quadBatch;
void Renderer::initialize()
{
// Get amount of texture units supported by the GPU
uint32_t constTextureUnitCount = textureUnitPerBatch;
uint32_t gpuTextureUnitCount = RenderCommand::textureUnitAmount();
m_supportedTextureUnitPerBatch = std::min(constTextureUnitCount, gpuTextureUnitCount);
// Create texture unit samplers
int32_t samplers[textureUnitPerBatch];
for (uint32_t i = 0; i < textureUnitPerBatch; i++) {
samplers[i] = i;
}
// Create shader
m_shader = ShaderManager::the().load("assets/glsl/batch-quad");
m_shader->bind();
m_shader->setInt("u_textures", samplers, textureUnitPerBatch);
m_shader->unbind();
}
void Renderer::destroy()
{
}
uint32_t Renderer::addTextureUnit(std::shared_ptr<Texture> texture)
{
if (texture == nullptr) {
return 0;
}
// Create a new batch if the texture unit limit has been reached
if (m_textureUnitIndex >= m_supportedTextureUnitPerBatch) {
nextBatch();
}
// If texure was already added
for (uint32_t i = 1; i < m_textureUnitIndex; i++) {
if (m_textureUnits[i] == texture) {
return i;
}
}
// Add texture
uint32_t textureUnitIndex = m_textureUnitIndex;
m_textureUnits[textureUnitIndex] = texture;
m_textureUnitIndex++;
return textureUnitIndex;
}
void Renderer::bind()
{
m_shader->bind();
for (uint32_t i = 1; i < m_textureUnitIndex; i++) {
m_textureUnits[i]->bind(i);
}
m_vertexArray->bind();
}
void Renderer::unbind()
{
m_vertexArray->unbind();
for (uint32_t i = 1; i < m_textureUnitIndex; i++) {
m_textureUnits[i]->unbind();
}
m_shader->unbind();
}
// -----------------------------------------
Renderer2D* Renderer2D::s_instance = nullptr;
void Renderer2D::initialize() void Renderer2D::initialize()
{ {
s_quadBatch = new QuadBatch(); ASSERT(!s_instance, "ShaderManager already exists!");
s_instance = this;
Renderer::initialize();
// CPU // CPU
// ----------------------------------------- // -----------------------------------------
// Create array for storing quads vertices // Create array for storing quads vertices
s_quadBatch->vertexBufferBase = std::unique_ptr<QuadVertex[]>(new QuadVertex[QuadBatch::vertexCount]); m_vertexBufferBase = std::unique_ptr<QuadVertex[]>(new QuadVertex[vertexCount]);
s_quadBatch->vertexBufferPtr = s_quadBatch->vertexBufferBase.get(); m_vertexBufferPtr = m_vertexBufferBase.get();
// Set default quad vertex positions // Set default quad vertex positions
s_quadBatch->vertexPositions[0] = { -0.5f, -0.5f, 0.0f, 1.0f }; m_vertexPositions[0] = { -0.5f, -0.5f, 0.0f, 1.0f };
s_quadBatch->vertexPositions[1] = { 0.5f, -0.5f, 0.0f, 1.0f }; m_vertexPositions[1] = { 0.5f, -0.5f, 0.0f, 1.0f };
s_quadBatch->vertexPositions[2] = { 0.5f, 0.5f, 0.0f, 1.0f }; m_vertexPositions[2] = { 0.5f, 0.5f, 0.0f, 1.0f };
s_quadBatch->vertexPositions[3] = { -0.5f, 0.5f, 0.0f, 1.0f }; m_vertexPositions[3] = { -0.5f, 0.5f, 0.0f, 1.0f };
// Create texture unit samplers
int32_t samplers[s_quadBatch->textureUnitPerBatch];
for (uint32_t i = 0; i < s_quadBatch->textureUnitPerBatch; i++) {
samplers[i] = i;
}
// Get amount of texture units supported by the GPU
uint32_t constTextureUnitCount = QuadBatch::textureUnitPerBatch;
uint32_t gpuTextureUnitCount = RenderCommand::textureUnitAmount();
s_quadBatch->supportedTextureUnitPerBatch = std::min(constTextureUnitCount, gpuTextureUnitCount);
// Texture unit 0 is reserved for no texture // Texture unit 0 is reserved for no texture
s_quadBatch->textureUnits[0] = nullptr; m_textureUnits[0] = nullptr;
// GPU // GPU
// ----------------------------------------- // -----------------------------------------
// Create shader
s_quadBatch->shader = ShaderManager::the().load("assets/glsl/batch-quad");
s_quadBatch->shader->bind();
s_quadBatch->shader->setInt("u_textures", samplers, s_quadBatch->textureUnitPerBatch);
s_quadBatch->shader->unbind();
// Create vertex array // Create vertex array
s_quadBatch->vertexArray = std::make_shared<VertexArray>(); m_vertexArray = std::make_shared<VertexArray>();
// Create vertex buffer // Create vertex buffer
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(QuadVertex) * QuadBatch::vertexCount); auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(QuadVertex) * vertexCount);
vertexBuffer->setLayout({ vertexBuffer->setLayout({
{ BufferElementType::Vec3, "a_position" }, { BufferElementType::Vec3, "a_position" },
{ BufferElementType::Vec4, "a_color" }, { BufferElementType::Vec4, "a_color" },
{ BufferElementType::Vec2, "a_textureCoordinates" }, { BufferElementType::Vec2, "a_textureCoordinates" },
{ BufferElementType::Float, "a_textureIndex" }, { BufferElementType::Float, "a_textureIndex" },
}); });
s_quadBatch->vertexArray->addVertexBuffer(std::move(vertexBuffer)); m_vertexArray->addVertexBuffer(std::move(vertexBuffer));
// Generate indices // Generate indices
uint32_t* indices = new uint32_t[QuadBatch::indexCount]; uint32_t* indices = new uint32_t[indexCount];
uint32_t offset = 0; uint32_t offset = 0;
for (uint32_t i = 0; i < QuadBatch::indexCount; i += QuadBatch::indexPerQuad) { for (uint32_t i = 0; i < indexCount; i += indexPerQuad) {
indices[i + 0] = offset + 0; indices[i + 0] = offset + 0;
indices[i + 1] = offset + 1; indices[i + 1] = offset + 1;
indices[i + 2] = offset + 2; indices[i + 2] = offset + 2;
@ -106,12 +168,12 @@ namespace Inferno {
indices[i + 4] = offset + 3; indices[i + 4] = offset + 3;
indices[i + 5] = offset + 0; indices[i + 5] = offset + 0;
offset += QuadBatch::vertexPerQuad; offset += vertexPerQuad;
} }
// Create index buffer // Create index buffer
auto indexBuffer = std::make_shared<IndexBuffer>(indices, sizeof(uint32_t) * QuadBatch::indexCount); auto indexBuffer = std::make_shared<IndexBuffer>(indices, sizeof(uint32_t) * indexCount);
s_quadBatch->vertexArray->setIndexBuffer(indexBuffer); m_vertexArray->setIndexBuffer(indexBuffer);
delete[] indices; delete[] indices;
dbg(Log::Info) << "Renderer2D initialized"; dbg(Log::Info) << "Renderer2D initialized";
@ -119,7 +181,8 @@ namespace Inferno {
void Renderer2D::destroy() void Renderer2D::destroy()
{ {
delete s_quadBatch; delete s_instance;
s_instance = nullptr;
} }
void Renderer2D::beginScene(const std::shared_ptr<Camera>& camera) void Renderer2D::beginScene(const std::shared_ptr<Camera>& camera)
@ -150,7 +213,7 @@ namespace Inferno {
void Renderer2D::drawQuad(std::shared_ptr<Transform> transform, glm::mat4 color, std::shared_ptr<Texture> texture) void Renderer2D::drawQuad(std::shared_ptr<Transform> transform, glm::mat4 color, std::shared_ptr<Texture> texture)
{ {
// Create a new batch if the quad limit has been reached // Create a new batch if the quad limit has been reached
if (s_quadBatch->quadCount >= QuadBatch::quads) { if (m_quadIndex >= quadCount) {
nextBatch(); nextBatch();
} }
@ -161,91 +224,43 @@ namespace Inferno {
uint32_t textureUnitIndex = addTextureUnit(texture); uint32_t textureUnitIndex = addTextureUnit(texture);
// Add the quads 4 vertices // Add the quads 4 vertices
for (uint32_t i = 0; i < QuadBatch::vertexPerQuad; i++) { for (uint32_t i = 0; i < vertexPerQuad; i++) {
s_quadBatch->vertexBufferPtr->position = transform->transform() * s_quadBatch->vertexPositions[i]; m_vertexBufferPtr->position = transform->transform() * m_vertexPositions[i];
s_quadBatch->vertexBufferPtr->color = color[i]; m_vertexBufferPtr->color = color[i];
s_quadBatch->vertexBufferPtr->textureCoordinates = textureCoordinates[i]; m_vertexBufferPtr->textureCoordinates = textureCoordinates[i];
s_quadBatch->vertexBufferPtr->textureIndex = (float)textureUnitIndex; m_vertexBufferPtr->textureIndex = (float)textureUnitIndex;
s_quadBatch->vertexBufferPtr++; m_vertexBufferPtr++;
}
s_quadBatch->quadCount++;
}
uint32_t Renderer2D::addTextureUnit(std::shared_ptr<Texture> texture)
{
if (texture == nullptr) {
return 0;
}
// Create a new batch if the texture unit limit has been reached
if (s_quadBatch->textureUnitIndex >= s_quadBatch->supportedTextureUnitPerBatch) {
nextBatch();
}
// If texure was already added
for (uint32_t i = 1; i < s_quadBatch->textureUnitIndex; i++) {
if (s_quadBatch->textureUnits[i] == texture) {
return i;
}
}
// Add texture
uint32_t textureUnitIndex = s_quadBatch->textureUnitIndex;
s_quadBatch->textureUnits[textureUnitIndex] = texture;
s_quadBatch->textureUnitIndex++;
return textureUnitIndex;
}
void Renderer2D::bind()
{
s_quadBatch->shader->bind();
for (uint32_t i = 1; i < s_quadBatch->textureUnitIndex; i++) {
s_quadBatch->textureUnits[i]->bind(i);
}
s_quadBatch->vertexArray->bind();
}
void Renderer2D::unbind()
{
s_quadBatch->vertexArray->unbind();
for (uint32_t i = 1; i < s_quadBatch->textureUnitIndex; i++) {
s_quadBatch->textureUnits[i]->unbind();
} }
s_quadBatch->shader->unbind(); m_quadIndex++;
} }
void Renderer2D::flush() void Renderer2D::flush()
{ {
if (s_quadBatch->quadCount == 0) { if (m_quadIndex == 0) {
return; return;
} }
// Upload vertex data to GPU // Upload vertex data to GPU
s_quadBatch->vertexArray->getVertexBuffers().at(0)->uploadData( m_vertexArray->getVertexBuffers().at(0)->uploadData(
s_quadBatch->vertexBufferBase.get(), m_vertexBufferBase.get(),
s_quadBatch->quadCount * QuadBatch::vertexPerQuad * sizeof(QuadVertex)); quadCount * vertexPerQuad * sizeof(QuadVertex));
bind(); bind();
// Render // Render
s_quadBatch->shader->setFloat("u_projectionView", s_camera->projection() * s_camera->transform()->transform()); m_shader->setFloat("u_projectionView", s_camera->projection() * s_camera->transform()->transform());
RenderCommand::drawIndexed(s_quadBatch->vertexArray, s_quadBatch->quadCount * QuadBatch::indexPerQuad); RenderCommand::drawIndexed(m_vertexArray, quadCount * indexPerQuad);
unbind(); unbind();
} }
void Renderer2D::startBatch() void Renderer2D::startBatch()
{ {
s_quadBatch->quadCount = 0; m_quadIndex = 0;
s_quadBatch->vertexBufferPtr = s_quadBatch->vertexBufferBase.get(); m_vertexBufferPtr = m_vertexBufferBase.get();
s_quadBatch->textureUnitIndex = 1; m_textureUnitIndex = 1;
} }
void Renderer2D::nextBatch() void Renderer2D::nextBatch()

99
inferno/src/inferno/render/renderer.h

@ -15,7 +15,6 @@ namespace Inferno {
class Shader; class Shader;
class Texture; class Texture;
class Transform; class Transform;
class VertexBuffer;
class VertexArray; class VertexArray;
struct QuadVertex { struct QuadVertex {
@ -25,70 +24,86 @@ namespace Inferno {
float textureIndex = 0; // @Todo get int to pass to fragment correctly float textureIndex = 0; // @Todo get int to pass to fragment correctly
}; };
struct QuadBatch { // -----------------------------------------
class RenderCommand {
public:
static void clear();
static void clearColor(const glm::vec4& color);
static void drawIndexed(const std::shared_ptr<VertexArray>& vertexArray, uint32_t indexCount = 0);
static int32_t textureUnitAmount();
};
// -----------------------------------------
class Renderer {
public:
static const uint32_t vertexPerQuad = 4; static const uint32_t vertexPerQuad = 4;
static const uint32_t indexPerQuad = 6; static const uint32_t indexPerQuad = 6;
static const uint32_t quads = 1000;
static const uint32_t vertexCount = quads * vertexPerQuad;
static const uint32_t indexCount = quads * indexPerQuad;
static const uint32_t textureUnitPerBatch = 32; static const uint32_t textureUnitPerBatch = 32;
// CPU quad vertices protected:
uint32_t quadCount = 0; virtual void initialize() = 0;
std::unique_ptr<QuadVertex[]> vertexBufferBase = nullptr; virtual void destroy() = 0;
QuadVertex* vertexBufferPtr = nullptr;
// Default quad vertex positions uint32_t addTextureUnit(std::shared_ptr<Texture> texture);
glm::vec4 vertexPositions[vertexPerQuad];
void bind();
void unbind();
virtual void flush() = 0;
virtual void startBatch() = 0;
virtual void nextBatch() = 0;
uint32_t m_quadIndex = 0;
// Texture units // Texture units
uint32_t supportedTextureUnitPerBatch = 0; static uint32_t m_supportedTextureUnitPerBatch;
uint32_t textureUnitIndex = 1; uint32_t m_textureUnitIndex = 1;
std::array<std::shared_ptr<Texture>, textureUnitPerBatch> textureUnits; std::array<std::shared_ptr<Texture>, textureUnitPerBatch> m_textureUnits;
// GPU objects // GPU objects
std::shared_ptr<Shader> shader = nullptr; std::shared_ptr<Shader> m_shader = nullptr;
std::shared_ptr<VertexArray> vertexArray = nullptr; std::shared_ptr<VertexArray> m_vertexArray = nullptr;
}; };
// ----------------------------------------- // -----------------------------------------
class RenderCommand { class Renderer2D final : public Renderer {
public: public:
static void clear(); static const uint32_t quadCount = 1000;
static void clearColor(const glm::vec4& color); static const uint32_t vertexCount = quadCount * vertexPerQuad;
static const uint32_t indexCount = quadCount * indexPerQuad;
static void drawIndexed(const std::shared_ptr<VertexArray>& vertexArray, uint32_t indexCount = 0); void initialize() override;
void destroy() override;
static int32_t textureUnitAmount(); void beginScene(const std::shared_ptr<Camera>& camera);
}; void endScene();
// ----------------------------------------- void drawQuad(std::shared_ptr<Transform> transform, glm::vec4 color);
void drawQuad(std::shared_ptr<Transform> transform, glm::mat4 color);
void drawQuad(std::shared_ptr<Transform> transform, glm::vec4 color, std::shared_ptr<Texture> texture);
void drawQuad(std::shared_ptr<Transform> transform, glm::mat4 color, std::shared_ptr<Texture> texture);
class Renderer2D { static inline Renderer2D& the() { return *s_instance; }
public:
static void initialize();
static void destroy();
static void beginScene(const std::shared_ptr<Camera>& camera); private:
static void endScene(); void flush() override;
void startBatch() override;
void nextBatch() override;
static void drawQuad(std::shared_ptr<Transform> transform, glm::vec4 color); std::shared_ptr<Camera> s_camera;
static void drawQuad(std::shared_ptr<Transform> transform, glm::mat4 color);
static void drawQuad(std::shared_ptr<Transform> transform, glm::vec4 color, std::shared_ptr<Texture> texture);
static void drawQuad(std::shared_ptr<Transform> transform, glm::mat4 color, std::shared_ptr<Texture> texture);
private: // CPU quad vertices
static uint32_t addTextureUnit(std::shared_ptr<Texture> texture); std::unique_ptr<QuadVertex[]> m_vertexBufferBase = nullptr;
QuadVertex* m_vertexBufferPtr = nullptr;
static void bind(); // Default quad vertex positions
static void unbind(); glm::vec4 m_vertexPositions[vertexPerQuad];
static void flush();
static void startBatch();
static void nextBatch();
static std::shared_ptr<Camera> s_camera; static Renderer2D* s_instance;
static QuadBatch* s_quadBatch;
}; };
} }

Loading…
Cancel
Save