138 lines
4.7 KiB
C++
138 lines
4.7 KiB
C++
#include "forwardmodule.h"
|
|
#include "scene.h"
|
|
#include "phongentity.h"
|
|
#include "mesh.h"
|
|
#include "shader.h"
|
|
#include "light.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
|
|
lightPass(NULL, myCamera, scene, AMBIENT_LIGHT);
|
|
|
|
// render directionnal lighting and point lighting
|
|
for(SceneIterator<Light*>* lightIt = scene->getLights();
|
|
lightIt->isValid(); lightIt->next())
|
|
{
|
|
Light* l = lightIt->getItem();
|
|
unsigned int type = l->isDirectionnal() ? DIRECTIONNAL_LIGHT : POINT_LIGHT;
|
|
lightPass(l, myCamera, scene, type);
|
|
}
|
|
}
|
|
|
|
void ForwardModule::lightPass(Light* light, Camera* myCamera, Scene* scene, 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[i].material;
|
|
if(mat->getFlags() == flags[i])
|
|
{
|
|
// bind material attributes
|
|
mat->bindAttributes(shader);
|
|
shader->bindMatrix(shader->getLocation("viewMatrix"), myCamera->getViewMatrix());
|
|
shader->bindMatrix(shader->getLocation("modelViewMatrix"), modelViewMatrix);
|
|
shader->bindMatrix(shader->getLocation("normalMatrix"), normalMatrix);
|
|
shader->bindMatrix(shader->getLocation("MVP"), mvp);
|
|
// draw geometry
|
|
entity->drawGroup(j);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// modern opengl methods
|
|
|
|
void ForwardModule::setShaderSource(ShaderSource* source)
|
|
{
|
|
shaderSources = source;
|
|
}
|
|
|
|
void ForwardModule::compileShaders(Scene* scene)
|
|
{
|
|
int size = 1 << NB_FLAGS;
|
|
bool geometryFlags[size];
|
|
for(int i=0; i<size; ++i)
|
|
geometryFlags[i] = false;
|
|
|
|
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;
|
|
}
|
|
|
|
for(int i=0; i<size; ++i)
|
|
{
|
|
if(geometryFlags[i])
|
|
{
|
|
std::vector<const char*> defines;
|
|
defines.push_back(lightStr[AMBIENT_LIGHT]);
|
|
|
|
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()));
|
|
}
|
|
}
|
|
}
|