yupplemayham/YuppleMayham/src/graphics/renderer.cpp

102 lines
No EOL
3.3 KiB
C++

#include "graphics/renderer.h"
#include "graphics/shader.h"
#include "utility/resourcemanager.h"
#include "utility/logger.h"
#include <algorithm>
Renderer::Renderer(const std::shared_ptr<ResourceManager>& 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> drawable)
{
layerPool[renderLayer].push_back(drawable);
}
void Renderer::removeDrawable(RenderLayer renderLayer, std::shared_ptr<Drawable> 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<Drawable>& a, const std::shared_ptr<Drawable>& b) {
return a->getShaderID() < b->getShaderID();
});
}
Shader* curShader = nullptr;
for (const auto& layer : renderingOrder) {
unsigned curShaderID = static_cast<unsigned>(-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<Uniform>& 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<decltype(arg)>;
if constexpr (std::is_same_v<T, bool>) {
shader->setBool(uniform.name, arg);
}
else if constexpr (std::is_same_v<T, int>) {
shader->setInt(uniform.name, arg);
}
else if constexpr (std::is_same_v<T, float>) {
shader->setFloat(uniform.name, arg);
}
else if constexpr (std::is_same_v<T, glm::vec2>) {
shader->setVec2(uniform.name, glm::value_ptr(arg));
}
else if constexpr (std::is_same_v<T, glm::mat4>) {
shader->setMatrix4f(uniform.name, glm::value_ptr(arg));
}
}, uniform.value);
}
}