102 lines
No EOL
3.3 KiB
C++
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);
|
|
}
|
|
} |