#include "graphics/renderer.h" #include "graphics/shader.h" #include "utility/resourcemanager.h" #include "utility/logger.h" #include Renderer::Renderer(const std::shared_ptr& r) : resourceManager(r) { projMat = glm::mat4(0.f); viewMat = glm::mat4(0.f); } void Renderer::setProjAndViewMatrix(const glm::mat4& proj, const glm::mat4& view) { projMat = proj; viewMat = view; } void Renderer::addDrawable(RenderLayer renderLayer, std::shared_ptr drawable) { layerPool[renderLayer].push_back(drawable); } void Renderer::removeDrawable(RenderLayer renderLayer, std::shared_ptr drawable) { auto& pool = layerPool[renderLayer]; pool.erase(std::remove(pool.begin(), pool.end(), drawable)); } void Renderer::render() { // Sort by shader id, this works to batch shaders together to avoid shader switching too much for (auto& [_,pool] : layerPool) { std::sort(pool.begin(), pool.end(), [](const std::shared_ptr& a, const std::shared_ptr& b) { return a->getShaderID() < b->getShaderID(); }); } Shader* curShader = nullptr; for (const auto& layer : renderingOrder) { unsigned curShaderID = static_cast(-1); for (const auto& item : layerPool[layer]) { if (item->getShaderID() != curShaderID) { curShaderID = item->getShaderID(); curShader = resourceManager->getShaderByID(curShaderID); if (curShader) { curShader->use(); curShader->setMatrix4f("projection", glm::value_ptr(projMat)); curShader->setMatrix4f("view", glm::value_ptr(viewMat)); } else { LOG(ERROR, "Shader with ID {} not found!", curShaderID); continue; } } if (!item->getOneShotUniforms().empty()) { uploadUniforms(curShaderID, item->getOneShotUniforms()); item->clearOneShot(); } uploadUniforms(curShaderID, item->getUniforms()); item->clearUniforms(); item->draw(); } } } void Renderer::clear() { layerPool.clear(); } void Renderer::uploadUniforms(const unsigned shaderID, const std::vector& uniforms) { Shader *shader = resourceManager->getShaderByID(shaderID); if (shader == nullptr) { LOG(ERROR, "No shader found with id {} !", shaderID); return; } for (const auto& uniform : uniforms) { std::visit([&](auto&& arg) { using T = std::decay_t; if constexpr (std::is_same_v) { shader->setBool(uniform.name, arg); } else if constexpr (std::is_same_v) { shader->setInt(uniform.name, arg); } else if constexpr (std::is_same_v) { shader->setFloat(uniform.name, arg); } else if constexpr (std::is_same_v) { shader->setVec2(uniform.name, glm::value_ptr(arg)); } else if constexpr (std::is_same_v) { shader->setMatrix4f(uniform.name, glm::value_ptr(arg)); } }, uniform.value); } }