SparrowRenderer/src/forwardmodule.cpp
2017-09-05 11:39:06 +02:00

114 lines
3.9 KiB
C++

#include "forwardmodule.h"
#include "scene.h"
#include "mesh.h"
#include "shader.h"
#include "light.h"
#include "pbrmaterial.h"
#include "texture.h"
#include "camera.h"
#include <glm/ext.hpp>
void ForwardModule::renderGL(Camera* myCamera, Scene* scene)
{
// bind target
glViewport(0, 0, width, height);
for(const Pass &p : passes)
{
for(Light *light : p.lights)
{
if(light->getFlags() & (1 << Light::AMBIENT_FLAG))
{
// render ambient lighting (opaque)
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glDisable(GL_BLEND);
}
else
{
// render directionnal lighting and point lighting (additive light)
glDepthFunc(GL_LEQUAL);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glDepthMask(GL_FALSE);
}
Shader *shader = p.shader;
shader->bind();
light->bindAttributes(shader, myCamera);
unsigned int id = 2;
for(GeometryNode *node : p.geometry)
{
shader->bindUnsignedInteger(shader->getLocation("object_identifier"), id);
if(node->mesh->m_instances_offsets.empty())
++id;
else
id += node->mesh->m_instances_offsets.size();
// compute matrix attributes
glm::mat4 modelViewMatrix = myCamera->getViewMatrix() * node->modelMatrix;
glm::mat4 mvp = myCamera->getProjectionMatrix() * modelViewMatrix;
glm::mat4 normalMatrix = glm::transpose(glm::inverse(modelViewMatrix));
shader->bindMat4(shader->getLocation("viewMatrix"), myCamera->getViewMatrix());
shader->bindMat4(shader->getLocation("modelViewMatrix"), modelViewMatrix);
shader->bindMat3(shader->getLocation("normalMatrix"), glm::mat3(normalMatrix));
shader->bindMat4(shader->getLocation("MVP"), mvp);
node->mesh->draw(shader);
}
}
}
glDisable(GL_BLEND);
glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);
}
void ForwardModule::setShaderSource(ShaderSource* source)
{
if(shaderSources != NULL)
delete(shaderSources);
shaderSources = source;
}
void ForwardModule::compileShaders(Scene* scene)
{
for(Pass &p : passes)
delete(p.shader);
passes.clear();
// list all geometry types
geometry.clear();
for(SceneIterator<GeometryNode*>* geometryIt = scene->getGeometry();
geometryIt->isValid(); geometryIt->next())
{
GeometryNode* n = geometryIt->getItem();
geometry[n->mesh->getFlags()].push_back(n);
}
// list all light types
lights.clear();
lights[ambientLight.getFlags()].push_back(&ambientLight);
for(SceneIterator<Light*>* lightIt = scene->getLights();
lightIt->isValid(); lightIt->next())
{
Light* l = lightIt->getItem();
lights[l->getFlags()].push_back(l);
}
// compile shaders and add the pass for the ambient light first
unsigned int ambientFlags = ambientLight.getFlags();
for(const auto &geomIt : geometry)
{
unsigned int geomFlags = geomIt.first;
passes.push_back(Pass(shaderSources->compile(geomFlags, ambientFlags), geomIt.second, lights[ambientFlags]));
}
// compile a shader for each combination of a geometry flag and a light flag
for(const auto &lightIt : lights)
{
unsigned int lightFlags = lightIt.first;
if(lightFlags != ambientFlags) // ambient shaders are already ready
{
for(const auto &geomIt : geometry)
{
unsigned int geomFlags = geomIt.first;
passes.push_back(Pass(shaderSources->compile(geomFlags, lightFlags), geomIt.second, lightIt.second));
}
}
}
}