#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 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* 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* 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)); } } } }