SparrowRenderer/forwardmodule.cpp

164 lines
5.5 KiB
C++

#include "forwardmodule.h"
#include "scene.h"
#include "phongentity.h"
#include "mesh.h"
#include "shader.h"
#include "light.h"
#include "glassert.h"
#include <glm/ext.hpp>
const char* const ForwardModule::flagStr[] =
{
"NORMAL_MAP",
"AMBIENT_TEXTURE",
"DIFFUSE_TEXTURE",
"SPECULAR_TEXTURE",
"ALPHA_MASK"
};
const char* const ForwardModule::lightStr[] =
{
"AMBIENT_LIGHT",
"DIRECTIONNAL_LIGHT",
"POINT_LIGHT"
};
void ForwardModule::renderGL(Camera* myCamera, Scene* scene)
{
// render ambient lighting
glAssert(glClearColor(0, 0.1f, 0.05f, 1.)); // add attribute, and setter for clear color
glAssert(glClearDepth(1.0));
glAssert(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
glAssert(glDepthFunc(GL_LESS));
glAssert(glDisable(GL_BLEND));
lightPass(myCamera, scene, NULL, AMBIENT_LIGHT);
// render directionnal lighting and point lighting
glAssert(glDepthFunc(GL_LEQUAL));
glAssert(glEnable(GL_BLEND));
glAssert(glBlendFunc(GL_ONE, GL_ONE));
glAssert(glDepthMask(GL_FALSE));
for(SceneIterator<Light*>* lightIt = scene->getLights();
lightIt->isValid(); lightIt->next())
{
Light* l = lightIt->getItem();
unsigned int type = l->isDirectionnal() ? DIRECTIONNAL_LIGHT : POINT_LIGHT;
lightPass(myCamera, scene, l, type);
}
glAssert(glDisable(GL_BLEND));
glAssert(glDepthFunc(GL_LESS));
glAssert(glDepthMask(GL_TRUE));
}
void ForwardModule::lightPass(Camera* myCamera, Scene* scene, Light* light, unsigned int type)
{
// loop over all types of geometry
for(int i=0; i<flags.size(); ++i)
{
// bind shader
Shader* shader = shaders[i*NB_LIGHT_FLAGS + type];
shader->bind();
// bind light attributes
if(type == DIRECTIONNAL_LIGHT)
shader->bindVec3(shader->getLocation("dirLight"), light->getDir());
if(type == POINT_LIGHT)
shader->bindVec3(shader->getLocation("pointLight"), light->getPos());
glm::vec3 color;
if(type == AMBIENT_LIGHT)
color = glm::vec3(0.1f); // add attribute, and setter for ambient lighting
else
color = light->getColor();
shader->bindVec3(shader->getLocation("lightColor"), color);
for(SceneIterator<PhongEntity*>* entityIt = scene->getGeometry();
entityIt->isValid(); entityIt->next())
{
// compute matrix attributes
PhongEntity* entity = entityIt->getItem();
glm::mat4 modelViewMatrix = myCamera->getViewMatrix() * entity->modelMatrix;
glm::mat4 mvp = myCamera->getProjectionMatrix() * modelViewMatrix;
glm::mat4 normalMatrix = glm::transpose(glm::inverse(modelViewMatrix));
// loop over material groups
for(int j=0; j<entity->getMesh()->indiceGroups.size(); ++j)
{
Material* mat = entity->getMesh()->indiceGroups[j].material;
if(mat->getFlags() == flags[i])
{
// bind material attributes
mat->bindAttributes(shader);
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);
// draw geometry
entity->drawGroup(j);
}
}
}
}
}
// modern opengl methods
void ForwardModule::setShaderSource(ShaderSource* source)
{
if(shaderSources != NULL)
delete(shaderSources);
shaderSources = source;
}
void ForwardModule::compileShaders(Scene* scene)
{
flags.clear();
for(Shader* s : shaders)
delete(s);
shaders.clear();
int size = 1 << NB_FLAGS;
bool geometryFlags[size];
for(int i=0; i<size; ++i)
geometryFlags[i] = false;
// get material flags
for(SceneIterator<PhongEntity*>* entityIt = scene->getGeometry();
entityIt->isValid(); entityIt->next())
{
Mesh* m = entityIt->getItem()->getMesh();
for(Mesh::Group &g : m->indiceGroups)
geometryFlags[g.material->getFlags()] = true;
}
// shader compilation
for(int i=0; i<size; ++i)
{
if(geometryFlags[i])
{
std::vector<const char*> defines;
defines.push_back(lightStr[AMBIENT_LIGHT]);
// set defines
if(i & NORMAL_MAP_FLAG)
defines.push_back(flagStr[NORMAL_MAP]);
if(i & AMBIENT_TEXTURE_FLAG)
defines.push_back(flagStr[AMBIENT_TEXTURE]);
if(i & DIFFUSE_TEXTURE_FLAG)
defines.push_back(flagStr[DIFFUSE_TEXTURE]);
if(i & SPECULAR_TEXTURE_FLAG)
defines.push_back(flagStr[SPECULAR_TEXTURE]);
// for each geometry flag, 3 shaders are compiled, one for each kind of lighting
flags.push_back(i);
// ambient
shaders.push_back(shaderSources->compile(defines.size(), defines.data()));
// directionnal
defines[0] = lightStr[DIRECTIONNAL_LIGHT];
shaders.push_back(shaderSources->compile(defines.size(), defines.data()));
// point
defines[0] = lightStr[POINT_LIGHT];
shaders.push_back(shaderSources->compile(defines.size(), defines.data()));
}
}
}