|
|
|
@ -10,151 +10,180 @@
|
|
|
|
|
#include "glad/glad.h" |
|
|
|
|
#include "ruc/format/log.h" |
|
|
|
|
|
|
|
|
|
#include "inferno/component/transformcomponent.h" |
|
|
|
|
#include "inferno/render/buffer.h" |
|
|
|
|
#include "inferno/render/render-command.h" |
|
|
|
|
#include "inferno/render/renderer.h" |
|
|
|
|
#include "inferno/render/shader.h" |
|
|
|
|
#include "inferno/render/texture.h" |
|
|
|
|
|
|
|
|
|
namespace Inferno { |
|
|
|
|
|
|
|
|
|
void RenderCommand::initialize() |
|
|
|
|
template<typename T> |
|
|
|
|
void Renderer<T>::beginScene(glm::mat4, glm::mat4) |
|
|
|
|
{ |
|
|
|
|
setDepthTest(true); |
|
|
|
|
|
|
|
|
|
// Enable transparency
|
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
|
|
|
|
glEnable(GL_BLEND); |
|
|
|
|
|
|
|
|
|
ruc::info("RenderCommand initialized"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RenderCommand::destroy() |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RenderCommand::clear() |
|
|
|
|
{ |
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RenderCommand::clearColor(const glm::vec4& color) |
|
|
|
|
{ |
|
|
|
|
glClearColor(color.r, color.g, color.b, color.a); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RenderCommand::drawIndexed(const VertexArray& vertexArray, uint32_t indexCount) |
|
|
|
|
{ |
|
|
|
|
uint32_t count = indexCount ? indexCount : vertexArray.getIndexBuffer()->getCount(); |
|
|
|
|
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RenderCommand::setViewport(int32_t x, int32_t y, uint32_t width, uint32_t height) |
|
|
|
|
{ |
|
|
|
|
glViewport(x, y, width, height); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RenderCommand::setDepthTest(bool enabled) |
|
|
|
|
{ |
|
|
|
|
// Set z-buffer / depth buffer
|
|
|
|
|
enabled ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool RenderCommand::depthTest() |
|
|
|
|
{ |
|
|
|
|
unsigned char depthTest = GL_FALSE; |
|
|
|
|
glGetBooleanv(GL_DEPTH_TEST, &depthTest); |
|
|
|
|
return depthTest == GL_TRUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int32_t RenderCommand::textureUnitAmount() |
|
|
|
|
template<typename T> |
|
|
|
|
void Renderer<T>::endScene() |
|
|
|
|
{ |
|
|
|
|
int32_t amount = 0; |
|
|
|
|
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &amount); |
|
|
|
|
return amount; |
|
|
|
|
nextBatch(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// -----------------------------------------
|
|
|
|
|
|
|
|
|
|
uint32_t Renderer::m_supportedTextureUnitPerBatch = 0; |
|
|
|
|
template<typename T> |
|
|
|
|
uint32_t Renderer<T>::m_maxSupportedTextureSlots = 0; |
|
|
|
|
|
|
|
|
|
void Renderer::initialize() |
|
|
|
|
template<typename T> |
|
|
|
|
void Renderer<T>::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); |
|
|
|
|
m_maxSupportedTextureSlots = std::min(maxTextureSlots, gpuTextureUnitCount); |
|
|
|
|
|
|
|
|
|
// Texture unit 0 is reserved for no texture
|
|
|
|
|
m_textureUnits[0] = nullptr; |
|
|
|
|
m_textureSlots[0] = nullptr; |
|
|
|
|
|
|
|
|
|
// Create texture unit samplers
|
|
|
|
|
int32_t samplers[textureUnitPerBatch]; |
|
|
|
|
for (uint32_t i = 0; i < textureUnitPerBatch; i++) { |
|
|
|
|
int32_t samplers[maxTextureSlots]; |
|
|
|
|
for (uint32_t i = 0; i < maxTextureSlots; i++) { |
|
|
|
|
samplers[i] = i; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Create shader
|
|
|
|
|
loadShader(); |
|
|
|
|
m_shader->bind(); |
|
|
|
|
m_shader->setInt("u_textures", samplers, textureUnitPerBatch); |
|
|
|
|
m_shader->setInt("u_textures", samplers, maxTextureSlots); |
|
|
|
|
m_shader->unbind(); |
|
|
|
|
|
|
|
|
|
// Create vertex array
|
|
|
|
|
m_vertexArray = std::make_shared<VertexArray>(); |
|
|
|
|
|
|
|
|
|
// CPU
|
|
|
|
|
// ---------------------------------
|
|
|
|
|
|
|
|
|
|
// Generate indices
|
|
|
|
|
|
|
|
|
|
uint32_t* indices = new uint32_t[maxIndices]; |
|
|
|
|
|
|
|
|
|
uint32_t offset = 0; |
|
|
|
|
for (uint32_t i = 0; i < maxIndices; i += indexPerQuad) { |
|
|
|
|
indices[i + 0] = offset + 0; |
|
|
|
|
indices[i + 1] = offset + 1; |
|
|
|
|
indices[i + 2] = offset + 2; |
|
|
|
|
indices[i + 3] = offset + 2; |
|
|
|
|
indices[i + 4] = offset + 3; |
|
|
|
|
indices[i + 5] = offset + 0; |
|
|
|
|
|
|
|
|
|
offset += vertexPerQuad; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// GPU
|
|
|
|
|
// ---------------------------------
|
|
|
|
|
|
|
|
|
|
// Create index buffer
|
|
|
|
|
auto indexBuffer = std::make_shared<IndexBuffer>(indices, sizeof(uint32_t) * maxIndices); |
|
|
|
|
m_vertexArray->setIndexBuffer(indexBuffer); |
|
|
|
|
delete[] indices; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Renderer::destroy() |
|
|
|
|
template<typename T> |
|
|
|
|
void Renderer<T>::destroy() |
|
|
|
|
{ |
|
|
|
|
delete[] m_vertexBufferBase; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint32_t Renderer::addTextureUnit(std::shared_ptr<Texture> texture) |
|
|
|
|
template<typename T> |
|
|
|
|
uint32_t Renderer<T>::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) { |
|
|
|
|
if (m_textureSlotIndex >= m_maxSupportedTextureSlots) { |
|
|
|
|
nextBatch(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// If texure was already added
|
|
|
|
|
for (uint32_t i = 1; i < m_textureUnitIndex; i++) { |
|
|
|
|
if (m_textureUnits[i] == texture) { |
|
|
|
|
for (uint32_t i = 1; i < m_textureSlotIndex; i++) { |
|
|
|
|
if (m_textureSlots[i] == texture) { |
|
|
|
|
return i; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Add texture
|
|
|
|
|
uint32_t textureUnitIndex = m_textureUnitIndex; |
|
|
|
|
m_textureUnits[textureUnitIndex] = texture; |
|
|
|
|
m_textureUnitIndex++; |
|
|
|
|
uint32_t textureSlotIndex = m_textureSlotIndex; |
|
|
|
|
m_textureSlots[textureSlotIndex] = texture; |
|
|
|
|
m_textureSlotIndex++; |
|
|
|
|
|
|
|
|
|
return textureUnitIndex; |
|
|
|
|
return textureSlotIndex; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Renderer::bind() |
|
|
|
|
template<typename T> |
|
|
|
|
void Renderer<T>::bind() |
|
|
|
|
{ |
|
|
|
|
m_shader->bind(); |
|
|
|
|
|
|
|
|
|
for (uint32_t i = 1; i < m_textureUnitIndex; i++) { |
|
|
|
|
m_textureUnits[i]->bind(i); |
|
|
|
|
for (uint32_t i = 1; i < m_textureSlotIndex; i++) { |
|
|
|
|
m_textureSlots[i]->bind(i); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
m_vertexArray->bind(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Renderer::unbind() |
|
|
|
|
template<typename T> |
|
|
|
|
void Renderer<T>::unbind() |
|
|
|
|
{ |
|
|
|
|
m_vertexArray->unbind(); |
|
|
|
|
|
|
|
|
|
for (uint32_t i = 1; i < m_textureUnitIndex; i++) { |
|
|
|
|
m_textureUnits[i]->unbind(); |
|
|
|
|
for (uint32_t i = 1; i < m_textureSlotIndex; i++) { |
|
|
|
|
m_textureSlots[i]->unbind(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
m_shader->unbind(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template<typename T> |
|
|
|
|
void Renderer<T>::flush() |
|
|
|
|
{ |
|
|
|
|
if (m_quadIndex == 0) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Upload vertex data to GPU
|
|
|
|
|
m_vertexArray->at(0)->uploadData( |
|
|
|
|
m_vertexBufferBase, |
|
|
|
|
m_quadIndex * vertexPerQuad * sizeof(T)); |
|
|
|
|
|
|
|
|
|
bind(); |
|
|
|
|
|
|
|
|
|
// Render
|
|
|
|
|
bool depthTest = RenderCommand::depthTest(); |
|
|
|
|
RenderCommand::setDepthTest(m_enableDepthBuffer); |
|
|
|
|
RenderCommand::drawIndexed(*m_vertexArray, m_quadIndex * indexPerQuad); |
|
|
|
|
RenderCommand::setDepthTest(depthTest); |
|
|
|
|
|
|
|
|
|
unbind(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template<typename T> |
|
|
|
|
void Renderer<T>::startBatch() |
|
|
|
|
{ |
|
|
|
|
m_quadIndex = 0; |
|
|
|
|
m_vertexBufferPtr = m_vertexBufferBase; |
|
|
|
|
|
|
|
|
|
m_textureSlotIndex = 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template<typename T> |
|
|
|
|
void Renderer<T>::nextBatch() |
|
|
|
|
{ |
|
|
|
|
flush(); |
|
|
|
|
startBatch(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// -----------------------------------------
|
|
|
|
|
|
|
|
|
|
Renderer2D::Renderer2D(s) |
|
|
|
@ -165,8 +194,8 @@ Renderer2D::Renderer2D(s)
|
|
|
|
|
// ---------------------------------
|
|
|
|
|
|
|
|
|
|
// Create array for storing quads vertices
|
|
|
|
|
m_vertexBufferBase = std::make_unique<QuadVertex[]>(vertexCount); |
|
|
|
|
m_vertexBufferPtr = m_vertexBufferBase.get(); |
|
|
|
|
m_vertexBufferBase = new QuadVertex[maxVertices]; |
|
|
|
|
m_vertexBufferPtr = m_vertexBufferBase; |
|
|
|
|
|
|
|
|
|
// Set default quad vertex positions
|
|
|
|
|
m_vertexPositions[0] = { -0.5f, -0.5f, 0.0f, 1.0f }; |
|
|
|
@ -174,27 +203,11 @@ Renderer2D::Renderer2D(s)
|
|
|
|
|
m_vertexPositions[2] = { 0.5f, 0.5f, 0.0f, 1.0f }; |
|
|
|
|
m_vertexPositions[3] = { -0.5f, 0.5f, 0.0f, 1.0f }; |
|
|
|
|
|
|
|
|
|
// Generate indices
|
|
|
|
|
|
|
|
|
|
uint32_t* indices = new uint32_t[indexCount]; |
|
|
|
|
|
|
|
|
|
uint32_t offset = 0; |
|
|
|
|
for (uint32_t i = 0; i < indexCount; i += indexPerQuad) { |
|
|
|
|
indices[i + 0] = offset + 0; |
|
|
|
|
indices[i + 1] = offset + 1; |
|
|
|
|
indices[i + 2] = offset + 2; |
|
|
|
|
indices[i + 3] = offset + 2; |
|
|
|
|
indices[i + 4] = offset + 3; |
|
|
|
|
indices[i + 5] = offset + 0; |
|
|
|
|
|
|
|
|
|
offset += vertexPerQuad; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// GPU
|
|
|
|
|
// ---------------------------------
|
|
|
|
|
|
|
|
|
|
// Create vertex buffer
|
|
|
|
|
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(QuadVertex) * vertexCount); |
|
|
|
|
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(QuadVertex) * maxVertices); |
|
|
|
|
vertexBuffer->setLayout({ |
|
|
|
|
{ BufferElementType::Vec3, "a_position" }, |
|
|
|
|
{ BufferElementType::Vec4, "a_color" }, |
|
|
|
@ -203,19 +216,9 @@ Renderer2D::Renderer2D(s)
|
|
|
|
|
}); |
|
|
|
|
m_vertexArray->addVertexBuffer(vertexBuffer); |
|
|
|
|
|
|
|
|
|
// Create index buffer
|
|
|
|
|
auto indexBuffer = std::make_shared<IndexBuffer>(indices, sizeof(uint32_t) * indexCount); |
|
|
|
|
m_vertexArray->setIndexBuffer(indexBuffer); |
|
|
|
|
delete[] indices; |
|
|
|
|
|
|
|
|
|
ruc::info("Renderer2D initialized"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Renderer2D::~Renderer2D() |
|
|
|
|
{ |
|
|
|
|
Renderer::destroy(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Renderer2D::beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView) |
|
|
|
|
{ |
|
|
|
|
m_shader->bind(); |
|
|
|
@ -223,11 +226,6 @@ void Renderer2D::beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView)
|
|
|
|
|
m_shader->unbind(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Renderer2D::endScene() |
|
|
|
|
{ |
|
|
|
|
nextBatch(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Renderer2D::drawQuad(const TransformComponent& transform, glm::vec4 color) |
|
|
|
|
{ |
|
|
|
|
drawQuad(transform, color, nullptr); |
|
|
|
@ -246,7 +244,7 @@ void Renderer2D::drawQuad(const TransformComponent& transform, glm::vec4 color,
|
|
|
|
|
void Renderer2D::drawQuad(const TransformComponent& transform, glm::mat4 color, std::shared_ptr<Texture> texture) |
|
|
|
|
{ |
|
|
|
|
// Create a new batch if the quad limit has been reached
|
|
|
|
|
if (m_quadIndex >= quadCount) { |
|
|
|
|
if (m_quadIndex >= maxQuads) { |
|
|
|
|
nextBatch(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -276,39 +274,6 @@ void Renderer2D::loadShader()
|
|
|
|
|
m_shader = ShaderManager::the().load("assets/glsl/batch-quad"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Renderer2D::flush() |
|
|
|
|
{ |
|
|
|
|
if (m_quadIndex == 0) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Upload vertex data to GPU
|
|
|
|
|
m_vertexArray->getVertexBuffers().at(0)->uploadData( |
|
|
|
|
m_vertexBufferBase.get(), |
|
|
|
|
m_quadIndex * vertexPerQuad * sizeof(QuadVertex)); |
|
|
|
|
|
|
|
|
|
bind(); |
|
|
|
|
|
|
|
|
|
// Render
|
|
|
|
|
RenderCommand::drawIndexed(*m_vertexArray, m_quadIndex * indexPerQuad); |
|
|
|
|
|
|
|
|
|
unbind(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Renderer2D::startBatch() |
|
|
|
|
{ |
|
|
|
|
m_quadIndex = 0; |
|
|
|
|
m_vertexBufferPtr = m_vertexBufferBase.get(); |
|
|
|
|
|
|
|
|
|
m_textureUnitIndex = 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Renderer2D::nextBatch() |
|
|
|
|
{ |
|
|
|
|
flush(); |
|
|
|
|
startBatch(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// -----------------------------------------
|
|
|
|
|
|
|
|
|
|
RendererCubemap::RendererCubemap(s) |
|
|
|
@ -319,8 +284,8 @@ RendererCubemap::RendererCubemap(s)
|
|
|
|
|
// ---------------------------------
|
|
|
|
|
|
|
|
|
|
// Create array for storing quads vertices
|
|
|
|
|
m_vertexBufferBase = std::make_unique<CubemapVertex[]>(vertexCount); |
|
|
|
|
m_vertexBufferPtr = m_vertexBufferBase.get(); |
|
|
|
|
m_vertexBufferBase = new CubemapVertex[maxVertices]; |
|
|
|
|
m_vertexBufferPtr = m_vertexBufferBase; |
|
|
|
|
|
|
|
|
|
// Set default cubemap vertex positions
|
|
|
|
|
|
|
|
|
@ -360,27 +325,13 @@ RendererCubemap::RendererCubemap(s)
|
|
|
|
|
m_vertexPositions[22] = { 0.5f, -0.5f, 0.5f, 1.0f }; |
|
|
|
|
m_vertexPositions[23] = { 0.5f, -0.5f, -0.5f, 1.0f }; |
|
|
|
|
|
|
|
|
|
// Generate indices
|
|
|
|
|
|
|
|
|
|
uint32_t* indices = new uint32_t[indexCount]; |
|
|
|
|
|
|
|
|
|
uint32_t offset = 0; |
|
|
|
|
for (uint32_t i = 0; i < indexCount; i += indexPerQuad) { |
|
|
|
|
indices[i + 0] = offset + 0; |
|
|
|
|
indices[i + 1] = offset + 1; |
|
|
|
|
indices[i + 2] = offset + 2; |
|
|
|
|
indices[i + 3] = offset + 2; |
|
|
|
|
indices[i + 4] = offset + 3; |
|
|
|
|
indices[i + 5] = offset + 0; |
|
|
|
|
|
|
|
|
|
offset += vertexPerQuad; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// GPU
|
|
|
|
|
// ---------------------------------
|
|
|
|
|
|
|
|
|
|
m_enableDepthBuffer = false; |
|
|
|
|
|
|
|
|
|
// Create vertex buffer
|
|
|
|
|
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(CubemapVertex) * vertexCount); |
|
|
|
|
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(CubemapVertex) * maxVertices); |
|
|
|
|
vertexBuffer->setLayout({ |
|
|
|
|
{ BufferElementType::Vec3, "a_position" }, |
|
|
|
|
{ BufferElementType::Vec4, "a_color" }, |
|
|
|
@ -388,19 +339,9 @@ RendererCubemap::RendererCubemap(s)
|
|
|
|
|
}); |
|
|
|
|
m_vertexArray->addVertexBuffer(vertexBuffer); |
|
|
|
|
|
|
|
|
|
// Create index buffer
|
|
|
|
|
auto indexBuffer = std::make_shared<IndexBuffer>(indices, sizeof(uint32_t) * indexCount); |
|
|
|
|
m_vertexArray->setIndexBuffer(indexBuffer); |
|
|
|
|
delete[] indices; |
|
|
|
|
|
|
|
|
|
ruc::info("RendererCubemap initialized"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
RendererCubemap::~RendererCubemap() |
|
|
|
|
{ |
|
|
|
|
Renderer::destroy(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RendererCubemap::beginScene(glm::mat4 cameraProjection, glm::mat4 cameraView) |
|
|
|
|
{ |
|
|
|
|
// We want the skybox fixed in position, so only retain the rotation and scale.
|
|
|
|
@ -416,11 +357,6 @@ void RendererCubemap::beginScene(glm::mat4 cameraProjection, glm::mat4 cameraVie
|
|
|
|
|
m_shader->unbind(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RendererCubemap::endScene() |
|
|
|
|
{ |
|
|
|
|
nextBatch(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RendererCubemap::drawCubemap(const TransformComponent& transform, glm::vec4 color, std::shared_ptr<Texture> texture) |
|
|
|
|
{ |
|
|
|
|
drawCubemap(transform, glm::mat4(color, color, color, color), texture); |
|
|
|
@ -429,13 +365,13 @@ void RendererCubemap::drawCubemap(const TransformComponent& transform, glm::vec4
|
|
|
|
|
void RendererCubemap::drawCubemap(const TransformComponent& transform, glm::mat4 color, std::shared_ptr<Texture> texture) |
|
|
|
|
{ |
|
|
|
|
// Create a new batch if the quad limit has been reached
|
|
|
|
|
if (m_quadIndex >= quadCount) { |
|
|
|
|
if (m_quadIndex >= maxQuads) { |
|
|
|
|
nextBatch(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint32_t textureUnitIndex = addTextureUnit(texture); |
|
|
|
|
|
|
|
|
|
// Add the quads 4 vertices
|
|
|
|
|
// Add the quads 4 vertices, 6 times, once per cube side
|
|
|
|
|
for (uint32_t i = 0; i < vertexPerQuad * quadPerCube; i++) { |
|
|
|
|
m_vertexBufferPtr->position = transform.transform * m_vertexPositions[i]; |
|
|
|
|
m_vertexBufferPtr->color = color[i % 4]; |
|
|
|
@ -451,45 +387,9 @@ void RendererCubemap::loadShader()
|
|
|
|
|
m_shader = ShaderManager::the().load("assets/glsl/batch-cubemap"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RendererCubemap::flush() |
|
|
|
|
{ |
|
|
|
|
if (m_quadIndex == 0) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Upload vertex data to GPU
|
|
|
|
|
m_vertexArray->getVertexBuffers().at(0)->uploadData( |
|
|
|
|
m_vertexBufferBase.get(), |
|
|
|
|
m_quadIndex * vertexPerQuad * sizeof(CubemapVertex)); |
|
|
|
|
|
|
|
|
|
bind(); |
|
|
|
|
|
|
|
|
|
// Render
|
|
|
|
|
bool depthTest = RenderCommand::depthTest(); |
|
|
|
|
RenderCommand::setDepthTest(false); |
|
|
|
|
RenderCommand::drawIndexed(*m_vertexArray, m_quadIndex * indexPerQuad); |
|
|
|
|
RenderCommand::setDepthTest(depthTest); |
|
|
|
|
|
|
|
|
|
unbind(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RendererCubemap::startBatch() |
|
|
|
|
{ |
|
|
|
|
m_quadIndex = 0; |
|
|
|
|
m_vertexBufferPtr = m_vertexBufferBase.get(); |
|
|
|
|
|
|
|
|
|
m_textureUnitIndex = 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RendererCubemap::nextBatch() |
|
|
|
|
{ |
|
|
|
|
flush(); |
|
|
|
|
startBatch(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// -----------------------------------------
|
|
|
|
|
|
|
|
|
|
RendererCharacter::RendererCharacter(s) |
|
|
|
|
RendererFont::RendererFont(s) |
|
|
|
|
{ |
|
|
|
|
Renderer::initialize(); |
|
|
|
|
|
|
|
|
@ -497,30 +397,16 @@ RendererCharacter::RendererCharacter(s)
|
|
|
|
|
// ---------------------------------
|
|
|
|
|
|
|
|
|
|
// Create array for storing quads vertices
|
|
|
|
|
m_vertexBufferBase = std::make_unique<CharacterVertex[]>(vertexCount); |
|
|
|
|
m_vertexBufferPtr = m_vertexBufferBase.get(); |
|
|
|
|
|
|
|
|
|
// Generate indices
|
|
|
|
|
|
|
|
|
|
uint32_t* indices = new uint32_t[indexCount]; |
|
|
|
|
|
|
|
|
|
uint32_t offset = 0; |
|
|
|
|
for (uint32_t i = 0; i < indexCount; i += indexPerQuad) { |
|
|
|
|
indices[i + 0] = offset + 0; |
|
|
|
|
indices[i + 1] = offset + 1; |
|
|
|
|
indices[i + 2] = offset + 2; |
|
|
|
|
indices[i + 3] = offset + 2; |
|
|
|
|
indices[i + 4] = offset + 3; |
|
|
|
|
indices[i + 5] = offset + 0; |
|
|
|
|
|
|
|
|
|
offset += vertexPerQuad; |
|
|
|
|
} |
|
|
|
|
m_vertexBufferBase = new SymbolVertex[maxVertices]; |
|
|
|
|
m_vertexBufferPtr = m_vertexBufferBase; |
|
|
|
|
|
|
|
|
|
// GPU
|
|
|
|
|
// ---------------------------------
|
|
|
|
|
|
|
|
|
|
m_enableDepthBuffer = false; |
|
|
|
|
|
|
|
|
|
// Create vertex buffer
|
|
|
|
|
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(CharacterVertex) * vertexCount); |
|
|
|
|
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(SymbolVertex) * maxVertices); |
|
|
|
|
vertexBuffer->setLayout({ |
|
|
|
|
{ BufferElementType::Vec3, "a_position" }, |
|
|
|
|
{ BufferElementType::Vec4, "a_color" }, |
|
|
|
@ -535,32 +421,13 @@ RendererCharacter::RendererCharacter(s)
|
|
|
|
|
}); |
|
|
|
|
m_vertexArray->addVertexBuffer(vertexBuffer); |
|
|
|
|
|
|
|
|
|
// Create index buffer
|
|
|
|
|
auto indexBuffer = std::make_shared<IndexBuffer>(indices, sizeof(uint32_t) * indexCount); |
|
|
|
|
m_vertexArray->setIndexBuffer(indexBuffer); |
|
|
|
|
delete[] indices; |
|
|
|
|
|
|
|
|
|
ruc::info("RendererCharacter initialized"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
RendererCharacter::~RendererCharacter() |
|
|
|
|
{ |
|
|
|
|
Renderer::destroy(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RendererCharacter::beginScene() |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RendererCharacter::endScene() |
|
|
|
|
{ |
|
|
|
|
nextBatch(); |
|
|
|
|
ruc::info("RendererFont initialized"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RendererCharacter::drawCharacter(std::array<CharacterVertex, vertexPerQuad>& characterQuad, std::shared_ptr<Texture> texture) |
|
|
|
|
void RendererFont::drawSymbol(std::array<SymbolVertex, vertexPerQuad>& symbolQuad, std::shared_ptr<Texture> texture) |
|
|
|
|
{ |
|
|
|
|
// Create a new batch if the quad limit has been reached
|
|
|
|
|
if (m_quadIndex >= quadCount) { |
|
|
|
|
if (m_quadIndex >= maxQuads) { |
|
|
|
|
nextBatch(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -568,17 +435,17 @@ void RendererCharacter::drawCharacter(std::array<CharacterVertex, vertexPerQuad>
|
|
|
|
|
|
|
|
|
|
// Add the quads 4 vertices
|
|
|
|
|
for (uint32_t i = 0; i < vertexPerQuad; i++) { |
|
|
|
|
m_vertexBufferPtr->quad.position = characterQuad[i].quad.position; |
|
|
|
|
m_vertexBufferPtr->quad.color = characterQuad[i].quad.color; |
|
|
|
|
m_vertexBufferPtr->quad.textureCoordinates = characterQuad[i].quad.textureCoordinates; |
|
|
|
|
m_vertexBufferPtr->quad.position = symbolQuad[i].quad.position; |
|
|
|
|
m_vertexBufferPtr->quad.color = symbolQuad[i].quad.color; |
|
|
|
|
m_vertexBufferPtr->quad.textureCoordinates = symbolQuad[i].quad.textureCoordinates; |
|
|
|
|
m_vertexBufferPtr->quad.textureIndex = (float)textureUnitIndex; |
|
|
|
|
|
|
|
|
|
m_vertexBufferPtr->width = characterQuad[i].width; |
|
|
|
|
m_vertexBufferPtr->edge = characterQuad[i].edge; |
|
|
|
|
m_vertexBufferPtr->borderWidth = characterQuad[i].borderWidth; |
|
|
|
|
m_vertexBufferPtr->borderEdge = characterQuad[i].borderEdge; |
|
|
|
|
m_vertexBufferPtr->borderColor = characterQuad[i].borderColor; |
|
|
|
|
m_vertexBufferPtr->offset = characterQuad[i].offset; |
|
|
|
|
m_vertexBufferPtr->width = symbolQuad[i].width; |
|
|
|
|
m_vertexBufferPtr->edge = symbolQuad[i].edge; |
|
|
|
|
m_vertexBufferPtr->borderWidth = symbolQuad[i].borderWidth; |
|
|
|
|
m_vertexBufferPtr->borderEdge = symbolQuad[i].borderEdge; |
|
|
|
|
m_vertexBufferPtr->borderColor = symbolQuad[i].borderColor; |
|
|
|
|
m_vertexBufferPtr->offset = symbolQuad[i].offset; |
|
|
|
|
|
|
|
|
|
m_vertexBufferPtr++; |
|
|
|
|
} |
|
|
|
@ -586,45 +453,9 @@ void RendererCharacter::drawCharacter(std::array<CharacterVertex, vertexPerQuad>
|
|
|
|
|
m_quadIndex++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RendererCharacter::loadShader() |
|
|
|
|
void RendererFont::loadShader() |
|
|
|
|
{ |
|
|
|
|
m_shader = ShaderManager::the().load("assets/glsl/batch-font"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RendererCharacter::flush() |
|
|
|
|
{ |
|
|
|
|
if (m_quadIndex == 0) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Upload vertex data to GPU
|
|
|
|
|
m_vertexArray->getVertexBuffers().at(0)->uploadData( |
|
|
|
|
m_vertexBufferBase.get(), |
|
|
|
|
m_quadIndex * vertexPerQuad * sizeof(CharacterVertex)); |
|
|
|
|
|
|
|
|
|
bind(); |
|
|
|
|
|
|
|
|
|
// Render
|
|
|
|
|
bool depthTest = RenderCommand::depthTest(); |
|
|
|
|
RenderCommand::setDepthTest(false); |
|
|
|
|
RenderCommand::drawIndexed(*m_vertexArray, m_quadIndex * indexPerQuad); |
|
|
|
|
RenderCommand::setDepthTest(depthTest); |
|
|
|
|
|
|
|
|
|
unbind(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RendererCharacter::startBatch() |
|
|
|
|
{ |
|
|
|
|
m_quadIndex = 0; |
|
|
|
|
m_vertexBufferPtr = m_vertexBufferBase.get(); |
|
|
|
|
|
|
|
|
|
m_textureUnitIndex = 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RendererCharacter::nextBatch() |
|
|
|
|
{ |
|
|
|
|
flush(); |
|
|
|
|
startBatch(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} // namespace Inferno
|
|
|
|
|