#include "forwardmodule.h" #include "scene.h" #include "phongentity.h" #include "mesh.h" #include "shader.h" #include "light.h" #include "glassert.h" #include 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* 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; ibind(); // 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* 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; jgetMesh()->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* 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 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())); } } }