From a7d43918981d48853aedc986fcb6f9f6917ff75c Mon Sep 17 00:00:00 2001 From: Anselme Date: Sat, 12 Dec 2015 19:52:11 +0100 Subject: [PATCH] implemented most of shadowmaps code in light.cpp, added some code in posteffectmodule --- CMakeLists.txt | 1 + light.cpp | 105 ++++++++++++++++++++++++++++++++++++++++--- light.h | 21 +++++++-- phongentity.cpp | 8 ++-- phongentity.h | 2 +- posteffectmodule.cpp | 66 ++++++++++++++++++++++++++- posteffectmodule.h | 22 ++++++++- 7 files changed, 206 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 978f80b..e336c7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ set(LIB_SRC_LIST forwardmodule.cpp shadersource.cpp light.cpp + posteffectmodule.cpp ) set(LIBRARY_NAME ${PROJECT_NAME}) diff --git a/light.cpp b/light.cpp index f16ca1d..0034197 100644 --- a/light.cpp +++ b/light.cpp @@ -1,34 +1,43 @@ #include "light.h" +#include "framebuffer.h" +#include "texture.h" +#include "scene.h" +#include "shader.h" +#include "shadersource.h" +#include "phongmaterial.h" +#include "mesh.h" +#include "glassert.h" +#include Light::Light() { initPointLight(); } -void Light::initDirectionnalLight(glm::vec3 dir, glm::vec3 lightColor, bool isShadowCaster) +void Light::initDirectionnalLight(glm::vec3 dir, glm::vec3 lightColor) { direction = dir; color = lightColor; - shadowCaster = isShadowCaster; + shadowCaster = false; isDir = true; } -void Light::initPointLight(glm::vec3 pos, glm::vec3 lightColor, bool isShadowCaster) +void Light::initPointLight(glm::vec3 pos, glm::vec3 lightColor) { position = pos; angle = 360; color = lightColor; - shadowCaster = isShadowCaster; + shadowCaster = false; isDir = false; } /* -void Light::initSpotLight(glm::vec3 pos, glm::vec3 dir, float spotAngle, glm::vec3 lightColor, bool isShadowCaster) +void Light::initSpotLight(glm::vec3 pos, glm::vec3 dir, float spotAngle, glm::vec3 lightColor) { position = pos; direction = dir; angle = spotAngle; color = lightColor; - shadowCaster = isShadowCaster; + shadowCaster = false; isDir = false; } */ @@ -36,3 +45,87 @@ bool Light::isDirectionnal() { return isDir; } + +void Light::initShadowMap(int resWidth, int resHeight) +{ + shadowCaster = true; + shadowMap = new FrameBuffer(); + // Depth buffer + Texture* tex = new Texture(GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, resWidth, resHeight, GL_FLOAT); + tex->setFiltering(GL_NEAREST); + shadowMap->addTexture(tex, GL_DEPTH_ATTACHMENT); + shadowMap->initGL(); + + ShaderSource source; + source.setSource(vertSource, ShaderSource::VERTEX); + source.setSource(fragSource, ShaderSource::FRAGMENT); + std::vector defines; + shaders[0] = source.compile(defines.size(), defines.data()); + defines.push_back("ALPHA_MASK"); + shaders[1] = source.compile(defines.size(), defines.data()); +} + +void Light::generateShadowMap(Scene* scene) +{ + glm::mat4 viewMatrix = glm::lookAt(position, position+direction, glm::vec3(0, 1, 0)); + + shadowMap->bindFBO(); + glAssert(glEnable(GL_DEPTH_TEST)); + for(SceneIterator* entityIt = scene->getGeometry(); + entityIt->isValid(); entityIt->next()) + { + // compute matrix attributes + PhongEntity* entity = entityIt->getItem(); + glm::mat4 modelViewMatrix = viewMatrix * entity->modelMatrix; + glm::mat4 mvp = /*myCamera->getProjectionMatrix() * */modelViewMatrix; + // loop over material groups + for(int j=0; jgetMesh()->indiceGroups.size(); ++j) + { + Material* mat = entity->getMesh()->indiceGroups[j].material; + if(mat->getFlags() & ALPHA_MASK) + { + PhongMaterial* pmat = (PhongMaterial*)mat; + shaders[1]->bind(); + pmat->alpha_mask->bind(ALPHA_MASK); + shaders[1]->bindInteger(shaders[1]->getLocation("alphaMask"), ALPHA_MASK); + entity->drawGroup(j, false, true, false); + } + else + { + entity->drawGroup(j, false, false, false); + shaders[0]->bind(); + } + } + } +} + +Texture* Light::getShadowMap() +{ + return shadowMap->getTexture(0); +} + +const char* Light::vertSource = + "#version 330 core\n\ + layout(location = 0)in vec3 inPosition;\n\ + out vec3 varTexCoord;\n\ + uniform mat4 MVP;\n\ + void main()\n\ + {\n\ + gl_Position = MVP * vec4(inPosition, 1.0);\n\ + }\n"; + +const char* Light::fragSource = + "#version 330 core\n\ + #ifdef ALPHA_MASK\n\ + uniform sampler2D alphaMask;\n\ + #endif\n\ + in vec3 varTexCoord;\n\ + out float fragmentdepth;\n\ + void main()\n\ + {\n\ + #ifdef ALPHA_MASK\n\ + if(texture(alphaMask, varTexCoord).r < 0.5)\n\ + discard;\n\ + #endif\n\ + fragmentdepth = gl_FragCoord.z;\n\ + }\n"; diff --git a/light.h b/light.h index 5aa2efd..0d1a3de 100644 --- a/light.h +++ b/light.h @@ -2,6 +2,12 @@ #define LIGHT_H #include +#include + +class FrameBuffer; +class Shader; +class Scene; +class Texture; class Light { @@ -16,18 +22,25 @@ private: // shadowmap attributes bool shadowCaster; - // Shadowmap fbo + FrameBuffer* shadowMap; + Shader* shaders[2]; + static const char* vertSource; + static const char* fragSource; public: Light(); - void initDirectionnalLight(glm::vec3 dir = glm::vec3(1, 0, 0), glm::vec3 lightColor = glm::vec3(1), bool isShadowCaster = false); - void initPointLight(glm::vec3 pos = glm::vec3(0), glm::vec3 lightColor = glm::vec3(1), bool isShadowCaster = false); + void initDirectionnalLight(glm::vec3 dir = glm::vec3(1, 0, 0), glm::vec3 lightColor = glm::vec3(1)); + void initPointLight(glm::vec3 pos = glm::vec3(0), glm::vec3 lightColor = glm::vec3(1)); // spotlight not supported yet - //void initSpotLight(glm::vec3 pos = glm::vec3(0), glm::vec3 dir = glm::vec3(1, 0, 0), float spotAngle = 360, glm::vec3 lightColor = glm::vec3(1), bool isShadowCaster = false); + //void initSpotLight(glm::vec3 pos = glm::vec3(0), glm::vec3 dir = glm::vec3(1, 0, 0), float spotAngle = 360, glm::vec3 lightColor = glm::vec3(1)); bool isDirectionnal(); glm::vec3 getDir() {return direction;} glm::vec3 getPos() {return position;} glm::vec3 getColor() {return color;} + + void initShadowMap(int resWidth, int resHeight); + void generateShadowMap(Scene* scene); + Texture* getShadowMap(); }; #endif // LIGHT_H diff --git a/phongentity.cpp b/phongentity.cpp index ee028ba..f07e2e5 100644 --- a/phongentity.cpp +++ b/phongentity.cpp @@ -118,25 +118,25 @@ void PhongEntity::destroyGL() glAssert(glDeleteLists(displayList, 1)); } -void PhongEntity::drawGroup(int groupId) +void PhongEntity::drawGroup(int groupId, bool drawNormals, bool drawTexCoord, bool drawTangents) { glAssert(glBindVertexArray(vao)); glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[POSITION_BUFFER])); glAssert(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0))); glAssert(glEnableVertexAttribArray(0)); - if(mesh->hasNormals()) + if(mesh->hasNormals() && drawNormals) { glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[NORMAL_BUFFER])); glAssert(glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0))); glAssert(glEnableVertexAttribArray(1)); } - if(mesh->hasTexCoords()) + if(mesh->hasTexCoords() && drawTexCoord) { glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TEXCOORD_BUFFER])); glAssert(glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), BUFFER_OFFSET(0))); glAssert(glEnableVertexAttribArray(2)); } - if(mesh->hasTangents()) + if(mesh->hasTangents() && drawTangents) { glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TANGENT_BUFFER])); glAssert(glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Mesh::Tangents), BUFFER_OFFSET(0))); diff --git a/phongentity.h b/phongentity.h index 48f6b5d..5b40728 100644 --- a/phongentity.h +++ b/phongentity.h @@ -46,7 +46,7 @@ public: PhongEntity(Mesh* myMesh); void drawDisplayList(); - void drawGroup(int groupId); // temporarily public + void drawGroup(int groupId, bool drawNormals = true, bool drawTexCoord = true, bool drawTangents = true); void initGL(bool isDynamic = false); void destroyGL(); diff --git a/posteffectmodule.cpp b/posteffectmodule.cpp index 79b2c5b..03c4334 100644 --- a/posteffectmodule.cpp +++ b/posteffectmodule.cpp @@ -1,12 +1,74 @@ #include "posteffectmodule.h" +#include "framebuffer.h" +#include "glassert.h" +#include "texture.h" +#include "shader.h" -PostEffectModule::PostEffectModule() +const GLfloat PostEffectModule::vertices[] = { + 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f +}; + +PostEffectModule::PostEffectModule(int width, int height) { + inputFBO = new FrameBuffer(); + Texture* tex; + // Color buffer + tex = new Texture(GL_RGBA, GL_RGBA, width, height); + tex->setFiltering(GL_NEAREST); + inputFBO->addTexture(tex, GL_COLOR_ATTACHMENT1); + // Depth buffer + tex = new Texture(GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, width, height, GL_FLOAT); + tex->setFiltering(GL_NEAREST); + inputFBO->addTexture(tex, GL_DEPTH_ATTACHMENT); + + inputFBO->initGL(); + + outputFBO = FrameBuffer::screen; + + // set up vao + glAssert(glGenVertexArrays(1, &vao)); + glAssert(glBindVertexArray(vao)); + glAssert(glGenBuffers(1, &vbo)); + glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo)); + glAssert(glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(GLfloat), vertices, GL_STATIC_DRAW)); + glAssert(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float)*3, NULL)); + glAssert(glEnableVertexAttribArray(0)); } PostEffectModule::~PostEffectModule() { - + glAssert(glDeleteVertexArrays(1, &vao)); + glAssert(glDeleteBuffers(1, &vbo)); + delete(inputFBO); } +void PostEffectModule::renderGL(Camera* myCamera, Scene* scene) +{ + if(shader != NULL) + { + shader->bind(); + shader->bindInteger(colorLocation, COLOR_BUFFER); + shader->bindInteger(depthLocation, DEPTH_BUFFER); + + outputFBO->bindFBO(); + + inputFBO->getTexture(COLOR_BUFFER)->bind(COLOR_BUFFER); + inputFBO->getTexture(DEPTH_BUFFER)->bind(DEPTH_BUFFER); + + glAssert(glBindVertexArray(vao)); + glAssert(glDrawArrays(GL_TRIANGLES, 0, 36)); + } +} + +void PostEffectModule::setShader(Shader* myShader) +{ + shader = myShader; + colorLocation = shader->getLocation("colorSampler"); + depthLocation = shader->getLocation("depthSampler"); +} diff --git a/posteffectmodule.h b/posteffectmodule.h index ff76ac5..e5dd920 100644 --- a/posteffectmodule.h +++ b/posteffectmodule.h @@ -1,17 +1,35 @@ #ifndef POSTEFFECTMODULE_H #define POSTEFFECTMODULE_H +#include #include "module.h" +class Shader; class FrameBuffer; class PostEffectModule : public Module { + GLuint vao; + GLuint vbo; FrameBuffer* inputFBO; - FrameBuffer* outputFBO; + const FrameBuffer* outputFBO; + Shader* shader; + GLuint colorLocation; + GLuint depthLocation; + + static const GLfloat vertices[]; + + enum Buffers {COLOR_BUFFER, DEPTH_BUFFER}; public: - PostEffectModule(); + PostEffectModule(int width, int height); ~PostEffectModule(); + + virtual void renderGL(Camera* myCamera, Scene* scene); + + FrameBuffer* getInputFBO() {return inputFBO;} + void setRenderTarget(FrameBuffer* renderTarget) {outputFBO = renderTarget;} + + void setShader(Shader* myShader); }; #endif // POSTEFFECTMODULE_H