]> gitweb.ps.run Git - subsurface_scattering/blobdiff - src/main.cpp
remove debugging renderstate
[subsurface_scattering] / src / main.cpp
index 41d5e76ea9db2cf5da6797c057d77c3c10662a45..4f18e104f3e63e803f2584b47093776bfa807201 100644 (file)
 #include <assimp/postprocess.h>\r
 #include <assimp/scene.h>\r
 \r
 #include <assimp/postprocess.h>\r
 #include <assimp/scene.h>\r
 \r
+\r
+// sample positions and weights for a Gaussian kernel from \r
+// Hable, John ; Borshukov, George ; Hejl, Jim: Fast Skin Shading. In: ShaderX7, ShaderX : Charles River Media, 2009, S. 161–173\r
+\r
+float samplePositions[] = {\r
+  0.000000f,  0.000000f,\r
+  1.633992f,  0.036795f,\r
+  0.177801f,  1.717593f,\r
+  -0.194906f,  0.091094f,\r
+  -0.239737f, -0.220217f,\r
+  -0.003530f, -0.118219f,\r
+  1.320107f, -0.181542f,\r
+  5.970690f,  0.253378f,\r
+  -1.089250f,  4.958349f,\r
+  -4.015465f,  4.156699f,\r
+  -4.063099f, -4.110150f,\r
+  -0.638605f, -6.297663f,\r
+  2.542348f, -3.245901f\r
+};\r
+\r
+float sampleWeights[] = {\r
+  0.220441f,  0.487000f, 0.635000f,\r
+  0.076356f,  0.064487f, 0.039097f,\r
+  0.116515f,  0.103222f, 0.064912f,\r
+  0.064844f,  0.086388f, 0.062272f,\r
+  0.131798f,  0.151695f, 0.103676f,\r
+  0.025690f,  0.042728f, 0.033003f,\r
+  0.048593f,  0.064740f, 0.046131f,\r
+  0.048092f,  0.003042f, 0.000400f,\r
+  0.048845f,  0.005406f, 0.001222f,\r
+  0.051322f,  0.006034f, 0.001420f,\r
+  0.061428f,  0.009152f, 0.002511f,\r
+  0.030936f,  0.002868f, 0.000652f,\r
+  0.073580f,  0.023239f, 0.009703f\r
+};\r
+\r
 struct model {\r
   std::vector<float> vertices;\r
   std::vector<GLuint> indices;\r
 struct model {\r
   std::vector<float> vertices;\r
   std::vector<GLuint> indices;\r
@@ -61,7 +97,6 @@ private:
   GLuint VAO = 0;\r
 };\r
 \r
   GLuint VAO = 0;\r
 };\r
 \r
-\r
 struct freecam {\r
   glm::vec3 pos = glm::vec3(0, 0, -1);\r
   glm::vec2 rot = glm::vec2(0, 0);\r
 struct freecam {\r
   glm::vec3 pos = glm::vec3(0, 0, -1);\r
   glm::vec2 rot = glm::vec2(0, 0);\r
@@ -115,7 +150,6 @@ private:
   float moveFactor = 20;\r
 };\r
 \r
   float moveFactor = 20;\r
 };\r
 \r
-\r
 struct arccam {\r
   glm::vec2 rot = glm::vec2(0, 0);\r
   float radius = 1;\r
 struct arccam {\r
   glm::vec2 rot = glm::vec2(0, 0);\r
   float radius = 1;\r
@@ -167,7 +201,6 @@ private:
   const float angleFactor = 200;\r
 };\r
 \r
   const float angleFactor = 200;\r
 };\r
 \r
-\r
 std::string readFile(std::string filename) {\r
   std::ifstream ifs(filename, std::ios::binary);\r
   std::string result, line;\r
 std::string readFile(std::string filename) {\r
   std::ifstream ifs(filename, std::ios::binary);\r
   std::string result, line;\r
@@ -182,10 +215,13 @@ model loadModel(const std::string &filename) {
 \r
   const aiScene *scene = importer.ReadFile(\r
       filename, aiProcess_CalcTangentSpace | aiProcess_Triangulate |\r
 \r
   const aiScene *scene = importer.ReadFile(\r
       filename, aiProcess_CalcTangentSpace | aiProcess_Triangulate |\r
-                    aiProcess_SortByPType | aiProcess_GenSmoothNormals);\r
+                    aiProcess_SortByPType | aiProcess_GenSmoothNormals |\r
+                    aiProcess_GenUVCoords);\r
 \r
   model result;\r
 \r
 \r
   model result;\r
 \r
+  printf("uv channels: %d\n", scene->mMeshes[0]->GetNumUVChannels());\r
+\r
   for (int i = 0; i < scene->mMeshes[0]->mNumVertices; i++) {\r
     aiVector3D v = scene->mMeshes[0]->mVertices[i];\r
     aiVector3D n = scene->mMeshes[0]->mNormals[i];\r
   for (int i = 0; i < scene->mMeshes[0]->mNumVertices; i++) {\r
     aiVector3D v = scene->mMeshes[0]->mVertices[i];\r
     aiVector3D n = scene->mMeshes[0]->mNormals[i];\r
@@ -253,6 +289,76 @@ GLuint compileShaders(const char *vertFilename, const char *fragFilename) {
   return shaderProgram;\r
 }\r
 \r
   return shaderProgram;\r
 }\r
 \r
+struct framebuffer {\r
+  framebuffer(const char *vertFilename, const char *fragFilename, int width, int height) {\r
+    glGenFramebuffers(1, &fbo);\r
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);\r
+    \r
+    glGenTextures(1, &renderTexture);\r
+    glBindTexture(GL_TEXTURE_2D, renderTexture);\r
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);\r
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);\r
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);\r
+    //glBindTexture(GL_TEXTURE_2D, 0);\r
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture, 0);\r
+\r
+    glGenRenderbuffers(1, &rbo);\r
+    glBindRenderbuffer(GL_RENDERBUFFER, rbo);\r
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);\r
+    //glBindRenderbuffer(GL_RENDERBUFFER, 0);\r
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);\r
+\r
+    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {\r
+      printf("Successfully created framebuffer\n");\r
+    }\r
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);\r
+    \r
+    screenShaderProgram = compileShaders(vertFilename, fragFilename);\r
+    glUseProgram(screenShaderProgram);\r
+    glUniform1i(glGetUniformLocation(screenShaderProgram, "screenTexture"), 0);\r
+\r
+    // Screen VAO\r
+    \r
+    glGenBuffers(1, &screenVBO);\r
+\r
+    glGenVertexArrays(1, &screenVAO);\r
+\r
+    glBindVertexArray(screenVAO);\r
+\r
+    float screenVerts[] = {\r
+      -1.0f, +1.0f, +0.0f, +1.0f,\r
+      -1.0f, -1.0f, +0.0f, +0.0f,\r
+      +1.0f, -1.0f, +1.0f, +0.0f,\r
+  \r
+      -1.0f, +1.0f, +0.0f, +1.0f,\r
+      +1.0f, -1.0f, +1.0f, +0.0f,\r
+      +1.0f, +1.0f, +1.0f, +1.0f,\r
+    };\r
+\r
+    glBindBuffer(GL_ARRAY_BUFFER, screenVBO);\r
+    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4,\r
+                screenVerts, GL_STATIC_DRAW);\r
+\r
+    glEnableVertexAttribArray(0);\r
+    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void*)(0));\r
+    glEnableVertexAttribArray(1);\r
+    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void*)(sizeof(float) * 2));\r
+\r
+    glBindVertexArray(0);\r
+  }\r
+  ~framebuffer() {\r
+    glDeleteFramebuffers(1, &fbo);\r
+  }\r
+  \r
+  GLuint fbo;\r
+  GLuint renderTexture;\r
+  GLuint rbo;\r
+  GLuint screenShaderProgram;\r
+  GLuint screenVBO;\r
+  GLuint screenVAO;\r
+};\r
 \r
 int main() {\r
   // Window Setup\r
 \r
 int main() {\r
   // Window Setup\r
@@ -276,90 +382,42 @@ int main() {
   if (glewInit() != GLEW_OK) {\r
   }\r
 \r
   if (glewInit() != GLEW_OK) {\r
   }\r
 \r
-  GLuint shaderProgram = compileShaders("shaders/vert.glsl", "shaders/frag.glsl");\r
+  GLuint shaderProgramShadowmap = compileShaders("shaders/vert_shadowmap.glsl", "shaders/frag_shadowmap.glsl");\r
+  GLuint shaderProgramIrradiance = compileShaders("shaders/vert_irradiance.glsl", "shaders/frag_irradiance.glsl");\r
 \r
   model m = loadModel("models/Isotrop-upperjaw.ply");\r
 \r
   model m = loadModel("models/Isotrop-upperjaw.ply");\r
-\r
+  \r
   arccam arcCam;\r
   freecam freeCam;\r
   arccam arcCam;\r
   freecam freeCam;\r
-      \r
-  glm::vec3 lightPos(1.2f, 5.0f, 2.0f);\r
 \r
   // MVP\r
 \r
   glm::mat4 model = glm::scale(glm::mat4(1.0f), glm::vec3(0.01f, 0.01f, 0.01f));\r
 \r
 \r
   // MVP\r
 \r
   glm::mat4 model = glm::scale(glm::mat4(1.0f), glm::vec3(0.01f, 0.01f, 0.01f));\r
 \r
-  glm::mat4 view;\r
+  glm::mat4 view, lightView;\r
 \r
   glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)window.getSize().x / window.getSize().y, 0.001f, 1000.0f);\r
 \r
   glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)window.getSize().x / window.getSize().y, 0.001f, 1000.0f);\r
+  glm::mat4 lightProj = glm::perspective(glm::radians(90.0f), (float)window.getSize().x / window.getSize().y, 0.001f, 1000.0f);\r
 \r
   // Framebuffer\r
 \r
   // Framebuffer\r
-  GLuint fbo;\r
-  glGenFramebuffers(1, &fbo);\r
-  glBindFramebuffer(GL_FRAMEBUFFER, fbo);\r
-  \r
-  GLuint renderTexture;\r
-  glGenTextures(1, &renderTexture);\r
-  glBindTexture(GL_TEXTURE_2D, renderTexture);\r
-  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);\r
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
-  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
-  //glBindTexture(GL_TEXTURE_2D, 0);\r
-  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture, 0);\r
-\r
-  GLuint rbo;\r
-  glGenRenderbuffers(1, &rbo);\r
-  glBindRenderbuffer(GL_RENDERBUFFER, rbo);\r
-  glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);\r
-  //glBindRenderbuffer(GL_RENDERBUFFER, 0);\r
-  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);\r
-\r
-  if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {\r
-    printf("Successfully created framebuffer\n");\r
-  }\r
-  glBindFramebuffer(GL_FRAMEBUFFER, 0);\r
-  \r
-  GLuint screenShaderProgram = compileShaders("shaders/fbo_vert.glsl", "shaders/fbo_frag.glsl");\r
-  glUseProgram(screenShaderProgram);\r
-  glUniform1i(glGetUniformLocation(screenShaderProgram, "screenTexture"), 0);\r
-\r
-  // Screen VAO\r
-  \r
-  GLuint screenVBO;\r
-  glGenBuffers(1, &screenVBO);\r
-\r
-  GLuint screenVAO;\r
-  glGenVertexArrays(1, &screenVAO);\r
 \r
 \r
-  glBindVertexArray(screenVAO);\r
-\r
-  float screenVerts[] = {\r
-    -1.0f, +1.0f, +0.0f, +1.0f,\r
-    -1.0f, -1.0f, +0.0f, +0.0f,\r
-    +1.0f, -1.0f, +1.0f, +0.0f,\r
\r
-    -1.0f, +1.0f, +0.0f, +1.0f,\r
-    +1.0f, -1.0f, +1.0f, +0.0f,\r
-    +1.0f, +1.0f, +1.0f, +1.0f,\r
-  };\r
-\r
-  glBindBuffer(GL_ARRAY_BUFFER, screenVBO);\r
-  glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4,\r
-              screenVerts, GL_STATIC_DRAW);\r
-\r
-  glEnableVertexAttribArray(0);\r
-  glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void*)(0));\r
-  glEnableVertexAttribArray(1);\r
-  glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void*)(sizeof(float) * 2));\r
-\r
-  glBindVertexArray(0);\r
+  framebuffer fb_shadowmap("shaders/fbo_vert.glsl", "shaders/fbo_frag.glsl", width, height);\r
+  framebuffer fb_irradiance("shaders/fbo_vert.glsl", "shaders/fbo_frag.glsl", width, height);\r
 \r
   // Config\r
 \r
 \r
   // Config\r
 \r
-  struct {\r
+  const struct {\r
     bool wireframe = false;\r
     bool freecam = false;\r
     bool wireframe = false;\r
     bool freecam = false;\r
-  } options;\r
+    int renderState = 2;\r
+    float color[3] = { 0.7f, 0.4f, 0.4f };\r
+    glm::vec3 lightPos = glm::vec3(0.0f, 0.0f, 0.03f);\r
+    float transmittanceScale = 0.025f;\r
+    float powBase = 2;\r
+    float powFactor = 1.5;\r
+  } DefaultOptions;\r
+\r
+  auto options = DefaultOptions;\r
 \r
   sf::Clock deltaClock;\r
 \r
 \r
   sf::Clock deltaClock;\r
 \r
@@ -391,7 +449,7 @@ int main() {
       }\r
     }\r
 \r
       }\r
     }\r
 \r
-    // Update\r
+    // Update Camera\r
 \r
     if (sf::Mouse::isButtonPressed(sf::Mouse::Right)) {\r
       window.setMouseCursorVisible(false);\r
 \r
     if (sf::Mouse::isButtonPressed(sf::Mouse::Right)) {\r
       window.setMouseCursorVisible(false);\r
@@ -414,10 +472,14 @@ int main() {
 \r
     prevMouse = sf::Mouse::isButtonPressed(sf::Mouse::Right);\r
 \r
 \r
     prevMouse = sf::Mouse::isButtonPressed(sf::Mouse::Right);\r
 \r
-    // Render to fbo\r
+    // Render Shadowmap to fbo\r
 \r
 \r
-    glBindFramebuffer(GL_FRAMEBUFFER, fbo);\r
-    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);\r
+    glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE);\r
+    glClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE);\r
+    glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);\r
+\r
+    glBindFramebuffer(GL_FRAMEBUFFER, fb_shadowmap.fbo);\r
+    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);\r
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r
     glEnable(GL_DEPTH_TEST);\r
 \r
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r
     glEnable(GL_DEPTH_TEST);\r
 \r
@@ -426,39 +488,102 @@ int main() {
     else\r
       glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r
 \r
     else\r
       glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r
 \r
-    glUseProgram(shaderProgram);\r
+    glUseProgram(shaderProgramShadowmap);\r
     \r
     if (options.freecam)\r
       view = freeCam.getViewMatrix();\r
     else\r
       view = arcCam.getViewMatrix();\r
     \r
     \r
     if (options.freecam)\r
       view = freeCam.getViewMatrix();\r
     else\r
       view = arcCam.getViewMatrix();\r
     \r
+    lightView = glm::lookAt(options.lightPos, glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));\r
+    \r
     glUniformMatrix4fv(\r
     glUniformMatrix4fv(\r
-      glGetUniformLocation(shaderProgram, "model"),\r
+      glGetUniformLocation(shaderProgramShadowmap, "model"),\r
       1, GL_FALSE, glm::value_ptr(model));\r
     glUniformMatrix4fv(\r
       1, GL_FALSE, glm::value_ptr(model));\r
     glUniformMatrix4fv(\r
-      glGetUniformLocation(shaderProgram, "view"),\r
+      glGetUniformLocation(shaderProgramShadowmap, "lightView"),\r
+      1, GL_FALSE, glm::value_ptr(lightView));\r
+    glUniformMatrix4fv(\r
+      glGetUniformLocation(shaderProgramShadowmap, "projection"),\r
+      1, GL_FALSE, glm::value_ptr(lightProj));\r
+\r
+    glUniform3fv(\r
+      glGetUniformLocation(shaderProgramShadowmap, "lightPos"),\r
+      1, glm::value_ptr(options.lightPos));\r
+\r
+    m.draw();\r
+\r
+    // Render irradiance map to fbo\r
+\r
+    glBindFramebuffer(GL_FRAMEBUFFER, fb_irradiance.fbo);\r
+    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);\r
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r
+    glEnable(GL_DEPTH_TEST);\r
+\r
+    if (options.wireframe)\r
+      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);\r
+    else\r
+      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r
+\r
+    glUseProgram(shaderProgramIrradiance);\r
+    \r
+    glUniformMatrix4fv(\r
+      glGetUniformLocation(shaderProgramIrradiance, "model"),\r
+      1, GL_FALSE, glm::value_ptr(model));\r
+    glUniformMatrix4fv(\r
+      glGetUniformLocation(shaderProgramIrradiance, "view"),\r
       1, GL_FALSE, glm::value_ptr(view));\r
     glUniformMatrix4fv(\r
       1, GL_FALSE, glm::value_ptr(view));\r
     glUniformMatrix4fv(\r
-      glGetUniformLocation(shaderProgram, "projection"),\r
+      glGetUniformLocation(shaderProgramIrradiance, "lightView"),\r
+      1, GL_FALSE, glm::value_ptr(lightView));\r
+    glUniformMatrix4fv(\r
+      glGetUniformLocation(shaderProgramIrradiance, "lightViewInv"),\r
+      1, GL_FALSE, glm::value_ptr(glm::inverse(lightView)));\r
+    glUniformMatrix4fv(\r
+      glGetUniformLocation(shaderProgramIrradiance, "projection"),\r
       1, GL_FALSE, glm::value_ptr(proj));\r
       1, GL_FALSE, glm::value_ptr(proj));\r
+    glUniformMatrix4fv(\r
+      glGetUniformLocation(shaderProgramIrradiance, "lightProjection"),\r
+      1, GL_FALSE, glm::value_ptr(lightProj));\r
+    glUniform1i(glGetUniformLocation(shaderProgramIrradiance, "screenWidth"), window.getSize().x);\r
+    glUniform1i(glGetUniformLocation(shaderProgramIrradiance, "screenHeight"), window.getSize().y);\r
+    glUniform1fv(glGetUniformLocation(shaderProgramIrradiance, "samplePositions"), 13, samplePositions);\r
+    glUniform3fv(glGetUniformLocation(shaderProgramIrradiance, "sampleWeights"), 13, sampleWeights);\r
+\r
+    glUniform1f(\r
+      glGetUniformLocation(shaderProgramIrradiance, "transmittanceScale"),\r
+      options.transmittanceScale);\r
+    glUniform1i(\r
+      glGetUniformLocation(shaderProgramIrradiance, "renderState"),\r
+      options.renderState);\r
+    glUniform1f(\r
+      glGetUniformLocation(shaderProgramIrradiance, "powBase"),\r
+      options.powBase);\r
+    glUniform1f(\r
+      glGetUniformLocation(shaderProgramIrradiance, "powFactor"),\r
+      options.powFactor);\r
 \r
 \r
+    glUniform3fv(\r
+      glGetUniformLocation(shaderProgramIrradiance, "objectColor"),\r
+      1, options.color);\r
     glUniform3f(\r
     glUniform3f(\r
-      glGetUniformLocation(shaderProgram, "objectColor"),\r
-      1.0f, 0.5f, 0.31f);\r
-    glUniform3f(\r
-      glGetUniformLocation(shaderProgram, "lightColor"),\r
+      glGetUniformLocation(shaderProgramIrradiance, "lightColor"),\r
       1.0f, 1.0f, 1.0f);\r
     glUniform3fv(\r
       1.0f, 1.0f, 1.0f);\r
     glUniform3fv(\r
-      glGetUniformLocation(shaderProgram, "lightPos"),\r
-      1, glm::value_ptr(lightPos));\r
+      glGetUniformLocation(shaderProgramIrradiance, "lightPos"),\r
+      1, glm::value_ptr(options.lightPos));\r
     glUniform3fv(\r
     glUniform3fv(\r
-      glGetUniformLocation(shaderProgram, "viewPos"),\r
+      glGetUniformLocation(shaderProgramIrradiance, "viewPos"),\r
       1, glm::value_ptr(options.freecam ? freeCam.pos : arcCam.getPos()));\r
       1, glm::value_ptr(options.freecam ? freeCam.pos : arcCam.getPos()));\r
+      \r
+      \r
+    glUniform1i(glGetUniformLocation(shaderProgramIrradiance, "shadowmapTexture"), 0);\r
+    glActiveTexture(GL_TEXTURE0 + 0);\r
+    glBindTexture(GL_TEXTURE_2D, fb_shadowmap.renderTexture);\r
 \r
     m.draw();\r
 \r
 \r
     m.draw();\r
 \r
-    // Render fbo to screen\r
+    // Render fbos to screen and calculate light spread/translucency in shader\r
     \r
     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r
 \r
     \r
     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r
 \r
@@ -466,24 +591,41 @@ int main() {
     glDisable(GL_DEPTH_TEST);\r
     glClearColor(1.0f, 1.0f, 1.0f, 1.0f);\r
     glClear(GL_COLOR_BUFFER_BIT);\r
     glDisable(GL_DEPTH_TEST);\r
     glClearColor(1.0f, 1.0f, 1.0f, 1.0f);\r
     glClear(GL_COLOR_BUFFER_BIT);\r
-    glUseProgram(screenShaderProgram);\r
-\r
-    glBindVertexArray(screenVAO);\r
-    glBindTexture(GL_TEXTURE_2D, renderTexture);\r
+    glUseProgram(fb_irradiance.screenShaderProgram);\r
+\r
+    glUniform1i(glGetUniformLocation(fb_irradiance.screenShaderProgram, "screenWidth"), window.getSize().x);\r
+    glUniform1i(glGetUniformLocation(fb_irradiance.screenShaderProgram, "screenHeight"), window.getSize().y);\r
+    glUniform1i(glGetUniformLocation(fb_irradiance.screenShaderProgram, "renderState"), options.renderState);\r
+    glUniform2fv(glGetUniformLocation(fb_irradiance.screenShaderProgram, "samplePositions"), 13, samplePositions);\r
+    glUniform3fv(glGetUniformLocation(fb_irradiance.screenShaderProgram, "sampleWeights"), 13, sampleWeights);\r
+\r
+    glBindVertexArray(fb_irradiance.screenVAO);\r
+    glUniform1i(glGetUniformLocation(fb_irradiance.screenShaderProgram, "shadowmapTexture"), 0);\r
+    glUniform1i(glGetUniformLocation(fb_irradiance.screenShaderProgram, "irradianceTexture"), 1);\r
+    glActiveTexture(GL_TEXTURE0 + 0);\r
+    glBindTexture(GL_TEXTURE_2D, fb_shadowmap.renderTexture);\r
+    glActiveTexture(GL_TEXTURE0 + 1);\r
+    glBindTexture(GL_TEXTURE_2D, fb_irradiance.renderTexture);\r
     glDrawArrays(GL_TRIANGLES, 0, 6);\r
     glBindVertexArray(0);\r
 \r
     glDrawArrays(GL_TRIANGLES, 0, 6);\r
     glBindVertexArray(0);\r
 \r
+    // menu\r
+\r
     ImGui::SFML::Update(window, deltaClock.restart());\r
 \r
     ImGui::Begin("Options");\r
     ImGui::Checkbox("Wireframe", &options.wireframe);\r
     ImGui::Checkbox("Free Cam", &options.freecam);\r
     ImGui::SFML::Update(window, deltaClock.restart());\r
 \r
     ImGui::Begin("Options");\r
     ImGui::Checkbox("Wireframe", &options.wireframe);\r
     ImGui::Checkbox("Free Cam", &options.freecam);\r
+    ImGui::DragFloat3("Color", options.color, 0.01, 0, 1);\r
+    ImGui::DragFloat("Transmittance Scale", &options.transmittanceScale, 0.0001f, 0, 0.3);\r
+    ImGui::DragFloat3("Light Pos", glm::value_ptr(options.lightPos), 0.01, -5, 5);\r
     if (options.freecam) {\r
       ImGui::LabelText("Position", "%f %f %f", freeCam.pos.x, freeCam.pos.y, freeCam.pos.z);\r
       ImGui::LabelText("Rotation", "%f %f", freeCam.rot.x, freeCam.rot.y);\r
       if (ImGui::Button("Reset")) {\r
         freeCam.pos = glm::vec3(0, 0, -1);\r
         freeCam.rot = glm::vec2(0);\r
     if (options.freecam) {\r
       ImGui::LabelText("Position", "%f %f %f", freeCam.pos.x, freeCam.pos.y, freeCam.pos.z);\r
       ImGui::LabelText("Rotation", "%f %f", freeCam.rot.x, freeCam.rot.y);\r
       if (ImGui::Button("Reset")) {\r
         freeCam.pos = glm::vec3(0, 0, -1);\r
         freeCam.rot = glm::vec2(0);\r
+        options = DefaultOptions;\r
       }\r
     } else {\r
       ImGui::LabelText("Rotation", "%f %f", arcCam.rot.x, arcCam.rot.y);\r
       }\r
     } else {\r
       ImGui::LabelText("Rotation", "%f %f", arcCam.rot.x, arcCam.rot.y);\r
@@ -491,6 +633,7 @@ int main() {
       if (ImGui::Button("Reset")) {\r
         arcCam.rot = glm::vec2(0);\r
         arcCam.radius = 1;\r
       if (ImGui::Button("Reset")) {\r
         arcCam.rot = glm::vec2(0);\r
         arcCam.radius = 1;\r
+        options = DefaultOptions;\r
       }\r
     }\r
     ImGui::End();\r
       }\r
     }\r
     ImGui::End();\r
@@ -500,7 +643,5 @@ int main() {
     window.display();\r
   }\r
 \r
     window.display();\r
   }\r
 \r
-  glDeleteFramebuffers(1, &fbo);\r
-\r
   return 0;\r
   return 0;\r
-}
\ No newline at end of file
+}\r