]> gitweb.ps.run Git - subsurface_scattering/blob - src/main.cpp
8b48e70a6fddb7c3c9e8abdc3fbbce64ba9d0b9b
[subsurface_scattering] / src / main.cpp
1 #include <stdio.h>\r
2 #include <fstream>\r
3 \r
4 #include <GL/glew.h>\r
5 \r
6 #define GLM_ENABLE_EXPERIMENTAL\r
7 \r
8 #include <glm/glm.hpp>\r
9 #include <glm/gtx/rotate_vector.hpp>\r
10 #include <glm/gtc/matrix_transform.hpp>\r
11 #include <glm/gtc/type_ptr.hpp>\r
12 \r
13 #include <SFML/OpenGL.hpp>\r
14 #include <SFML/Graphics.hpp>\r
15 \r
16 #include <imgui.h>\r
17 #include <imgui-SFML.h>\r
18 \r
19 #include <assimp/Importer.hpp>\r
20 #include <assimp/postprocess.h>\r
21 #include <assimp/scene.h>\r
22 \r
23 /*\r
24 \r
25 TODO:\r
26 - Save Depth to fbo\r
27 - Stencil Buffer\r
28 - LightDist > 1\r
29   - 1 - distanceToBackside in frag_irradiance\r
30 - ShadowMap Perspective (no projection?)\r
31 - (Implement Gaussian Blur)\r
32 - LightDir nicht immer zu 0 0 0\r
33 \r
34 */\r
35 \r
36 float samplePositions[] = {\r
37   0.000000f,  0.000000f,\r
38   1.633992f,  0.036795f,\r
39   0.177801f,  1.717593f,\r
40   -0.194906f,  0.091094f,\r
41   -0.239737f, -0.220217f,\r
42   -0.003530f, -0.118219f,\r
43   1.320107f, -0.181542f,\r
44   5.970690f,  0.253378f,\r
45   -1.089250f,  4.958349f,\r
46   -4.015465f,  4.156699f,\r
47   -4.063099f, -4.110150f,\r
48   -0.638605f, -6.297663f,\r
49   2.542348f, -3.245901f\r
50 };\r
51 \r
52 float sampleWeights[] = {\r
53   0.220441f,  0.487000f, 0.635000f,\r
54   0.076356f,  0.064487f, 0.039097f,\r
55   0.116515f,  0.103222f, 0.064912f,\r
56   0.064844f,  0.086388f, 0.062272f,\r
57   0.131798f,  0.151695f, 0.103676f,\r
58   0.025690f,  0.042728f, 0.033003f,\r
59   0.048593f,  0.064740f, 0.046131f,\r
60   0.048092f,  0.003042f, 0.000400f,\r
61   0.048845f,  0.005406f, 0.001222f,\r
62   0.051322f,  0.006034f, 0.001420f,\r
63   0.061428f,  0.009152f, 0.002511f,\r
64   0.030936f,  0.002868f, 0.000652f,\r
65   0.073580f,  0.023239f, 0.009703f\r
66 };\r
67 \r
68 struct model {\r
69   std::vector<float> vertices;\r
70   std::vector<GLuint> indices;\r
71 \r
72   void draw() {\r
73     if (VAO == 0) initVAO();\r
74     glBindVertexArray(VAO);\r
75     glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);\r
76     glBindVertexArray(0);\r
77   }\r
78 \r
79 private:\r
80   void initVAO() {\r
81     GLuint VBO;\r
82     glGenBuffers(1, &VBO);\r
83 \r
84     GLuint EBO;\r
85     glGenBuffers(1, &EBO);\r
86 \r
87     glGenVertexArrays(1, &VAO);\r
88 \r
89     glBindVertexArray(VAO);\r
90 \r
91     glBindBuffer(GL_ARRAY_BUFFER, VBO);\r
92     glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(),\r
93                 vertices.data(), GL_STATIC_DRAW);\r
94 \r
95     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);\r
96     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(),\r
97                 indices.data(), GL_STATIC_DRAW);\r
98 \r
99     glEnableVertexAttribArray(0);\r
100     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(0));\r
101     glEnableVertexAttribArray(1);\r
102     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(sizeof(float) * 3));\r
103 \r
104     glBindVertexArray(0);\r
105   }\r
106   GLuint VAO = 0;\r
107 };\r
108 \r
109 struct freecam {\r
110   glm::vec3 pos = glm::vec3(0, 0, -1);\r
111   glm::vec2 rot = glm::vec2(0, 0);\r
112 \r
113   void update(sf::Window &window) {\r
114     int mouseDeltaX = sf::Mouse::getPosition(window).x - window.getSize().x / 2;\r
115     int mouseDeltaY = sf::Mouse::getPosition(window).y - window.getSize().y / 2;\r
116 \r
117     rot.x += mouseDeltaX;\r
118     rot.y += mouseDeltaY;\r
119 \r
120     forward = glm::rotate(glm::vec3(0, 0, 1), rot.y / angleFactor, glm::vec3(1, 0, 0));\r
121     forward = glm::rotate(forward, -rot.x / angleFactor, glm::vec3(0, 1, 0));\r
122 \r
123     glm::vec3 left = glm::rotate(glm::vec3(0, 0, 1), -rot.x / angleFactor + glm::radians(90.0f), glm::vec3(0, 1, 0));\r
124 \r
125     if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::LShift))\r
126       moveFactor = 200;\r
127     else\r
128       moveFactor = 20;\r
129 \r
130     if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))\r
131       pos += forward / moveFactor;\r
132     if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))\r
133       pos -= forward / moveFactor;\r
134     if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))\r
135       pos += left / moveFactor;\r
136     if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))\r
137       pos -= left / moveFactor;\r
138 \r
139     limit();\r
140   }\r
141 \r
142   void limit() {\r
143     rot.x = fmod(rot.x, glm::radians(360.0f) * angleFactor);\r
144     rot.y = fmod(rot.y, glm::radians(360.0f) * angleFactor);\r
145   }\r
146 \r
147   glm::mat4 getViewMatrix() {\r
148     forward = glm::rotate(glm::vec3(0, 0, 1), rot.y / angleFactor, glm::vec3(1, 0, 0));\r
149     forward = glm::rotate(forward, -rot.x / angleFactor, glm::vec3(0, 1, 0));\r
150     glm::mat4 result = glm::lookAt(pos, pos + forward, up);\r
151     return result;\r
152   }\r
153 \r
154 private:\r
155   glm::vec3 forward = glm::vec3(0, 0, 1);\r
156   glm::vec3 up = glm::vec3(0, 1, 0);\r
157 \r
158   const float angleFactor = 200;\r
159   float moveFactor = 20;\r
160 };\r
161 \r
162 struct arccam {\r
163   glm::vec2 rot = glm::vec2(0, 0);\r
164   float radius = 1;\r
165 \r
166   void update(sf::Window &window) {\r
167     int mouseDeltaX = sf::Mouse::getPosition(window).x - window.getSize().x / 2;\r
168     int mouseDeltaY = sf::Mouse::getPosition(window).y - window.getSize().y / 2;\r
169 \r
170     rot.x += mouseDeltaX;\r
171     rot.y += mouseDeltaY;\r
172 \r
173     limit(-89, 89);\r
174   }\r
175 \r
176   void limit(float minY, float maxY) {\r
177     float angleX = rot.x / angleFactor;\r
178     float angleY = rot.y / angleFactor;\r
179 \r
180     rot.x = fmod(rot.x, glm::radians(360.0f) * angleFactor);\r
181 \r
182     if (angleY > glm::radians(maxY))\r
183       rot.y = glm::radians(maxY) * angleFactor;\r
184     if (angleY < glm::radians(minY))\r
185       rot.y = glm::radians(minY) * angleFactor;\r
186   }\r
187 \r
188   glm::vec3 getPos() {\r
189     float angle = rot.y / angleFactor;\r
190   \r
191     float camY = sin(angle) * exp(radius);\r
192     float camZ = cos(angle) * exp(radius);\r
193 \r
194     glm::vec3 result(0.0, camY, camZ);\r
195     return glm::rotate(result, -rot.x / angleFactor, glm::vec3(0, 1, 0));\r
196   }\r
197 \r
198   glm::mat4 getViewMatrix() {\r
199     float angle = rot.y / angleFactor;\r
200   \r
201     float camY = sin(angle) * exp(radius);\r
202     float camZ = cos(angle) * exp(radius);\r
203     glm::mat4 result = glm::lookAt(glm::vec3(0.0, camY, camZ), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));\r
204     result = glm::rotate(result, rot.x / angleFactor, glm::vec3(0, 1, 0));\r
205 \r
206     return result;\r
207   }\r
208 \r
209 private:\r
210   const float angleFactor = 200;\r
211 };\r
212 \r
213 std::string readFile(std::string filename) {\r
214   std::ifstream ifs(filename, std::ios::binary);\r
215   std::string result, line;\r
216   while (std::getline(ifs, line))\r
217     result += line + "\n";\r
218 \r
219   return result;\r
220 }\r
221 \r
222 model loadModel(const std::string &filename) {\r
223   Assimp::Importer importer;\r
224 \r
225   const aiScene *scene = importer.ReadFile(\r
226       filename, aiProcess_CalcTangentSpace | aiProcess_Triangulate |\r
227                     aiProcess_SortByPType | aiProcess_GenSmoothNormals |\r
228                     aiProcess_GenUVCoords);\r
229 \r
230   model result;\r
231 \r
232   printf("uv channels: %d\n", scene->mMeshes[0]->GetNumUVChannels());\r
233 \r
234   for (int i = 0; i < scene->mMeshes[0]->mNumVertices; i++) {\r
235     aiVector3D v = scene->mMeshes[0]->mVertices[i];\r
236     aiVector3D n = scene->mMeshes[0]->mNormals[i];\r
237     result.vertices.push_back(v.x);\r
238     result.vertices.push_back(v.y);\r
239     result.vertices.push_back(v.z);\r
240     result.vertices.push_back(n.x);\r
241     result.vertices.push_back(n.y);\r
242     result.vertices.push_back(n.z);\r
243   }\r
244 \r
245   for (int i = 0; i < scene->mMeshes[0]->mNumFaces; i++) {\r
246     aiFace f = scene->mMeshes[0]->mFaces[i];\r
247     for (int j = 0; j < f.mNumIndices; j++) {\r
248       result.indices.push_back(f.mIndices[j]);\r
249     }\r
250   }\r
251 \r
252   return result;\r
253 }\r
254 \r
255 GLuint compileShaders(const char *vertFilename, const char *fragFilename) {\r
256   GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);\r
257   std::string vertSource = readFile(vertFilename);\r
258   const char *vertAddr = vertSource.c_str();\r
259   glShaderSource(vertShader, 1, &vertAddr, NULL);\r
260   glCompileShader(vertShader);\r
261 \r
262   int success;\r
263   char infoLog[512];\r
264   glGetShaderiv(vertShader, GL_COMPILE_STATUS, &success);\r
265   if (!success) {\r
266     glGetShaderInfoLog(vertShader, 512, NULL, infoLog);\r
267     printf("Error compiling vertex shader(%s): %s\n", vertFilename, infoLog);\r
268   }\r
269 \r
270   GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);\r
271   std::string fragSource = readFile(fragFilename);\r
272   const char *fragAddr = fragSource.c_str();\r
273   glShaderSource(fragShader, 1, &fragAddr, NULL);\r
274   glCompileShader(fragShader);\r
275 \r
276   glGetShaderiv(fragShader, GL_COMPILE_STATUS, &success);\r
277   if (!success) {\r
278     glGetShaderInfoLog(fragShader, 512, NULL, infoLog);\r
279     printf("Error compiling fragment shader(%s): %s\n", fragFilename, infoLog);\r
280   }\r
281 \r
282   // Link Shader Program\r
283 \r
284   GLuint shaderProgram = glCreateProgram();\r
285   glAttachShader(shaderProgram, vertShader);\r
286   glAttachShader(shaderProgram, fragShader);\r
287   glLinkProgram(shaderProgram);\r
288 \r
289   glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);\r
290   if (!success) {\r
291     glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);\r
292     printf("Error linking shader program: %s\n", infoLog);\r
293   }\r
294 \r
295   glDeleteShader(vertShader);\r
296   glDeleteShader(fragShader);\r
297 \r
298   return shaderProgram;\r
299 }\r
300 \r
301 struct framebuffer {\r
302   framebuffer(const char *vertFilename, const char *fragFilename, int width, int height) {\r
303     glGenFramebuffers(1, &fbo);\r
304     glBindFramebuffer(GL_FRAMEBUFFER, fbo);\r
305     \r
306     glGenTextures(1, &renderTexture);\r
307     glBindTexture(GL_TEXTURE_2D, renderTexture);\r
308     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);\r
309     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
310     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
311     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);\r
312     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);\r
313     //glBindTexture(GL_TEXTURE_2D, 0);\r
314     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture, 0);\r
315 \r
316     glGenRenderbuffers(1, &rbo);\r
317     glBindRenderbuffer(GL_RENDERBUFFER, rbo);\r
318     glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);\r
319     //glBindRenderbuffer(GL_RENDERBUFFER, 0);\r
320     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);\r
321 \r
322     if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {\r
323       printf("Successfully created framebuffer\n");\r
324     }\r
325     glBindFramebuffer(GL_FRAMEBUFFER, 0);\r
326     \r
327     screenShaderProgram = compileShaders(vertFilename, fragFilename);\r
328     glUseProgram(screenShaderProgram);\r
329     glUniform1i(glGetUniformLocation(screenShaderProgram, "screenTexture"), 0);\r
330 \r
331     // Screen VAO\r
332     \r
333     glGenBuffers(1, &screenVBO);\r
334 \r
335     glGenVertexArrays(1, &screenVAO);\r
336 \r
337     glBindVertexArray(screenVAO);\r
338 \r
339     float screenVerts[] = {\r
340       -1.0f, +1.0f, +0.0f, +1.0f,\r
341       -1.0f, -1.0f, +0.0f, +0.0f,\r
342       +1.0f, -1.0f, +1.0f, +0.0f,\r
343   \r
344       -1.0f, +1.0f, +0.0f, +1.0f,\r
345       +1.0f, -1.0f, +1.0f, +0.0f,\r
346       +1.0f, +1.0f, +1.0f, +1.0f,\r
347     };\r
348 \r
349     glBindBuffer(GL_ARRAY_BUFFER, screenVBO);\r
350     glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4,\r
351                 screenVerts, GL_STATIC_DRAW);\r
352 \r
353     glEnableVertexAttribArray(0);\r
354     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void*)(0));\r
355     glEnableVertexAttribArray(1);\r
356     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, (void*)(sizeof(float) * 2));\r
357 \r
358     glBindVertexArray(0);\r
359   }\r
360   ~framebuffer() {\r
361     glDeleteFramebuffers(1, &fbo);\r
362   }\r
363   \r
364   GLuint fbo;\r
365   GLuint renderTexture;\r
366   GLuint rbo;\r
367   GLuint screenShaderProgram;\r
368   GLuint screenVBO;\r
369   GLuint screenVAO;\r
370 };\r
371 \r
372 int main() {\r
373   // Window Setup\r
374 \r
375   const int width = 1600, height = 900;\r
376 \r
377   sf::ContextSettings settings;\r
378   settings.depthBits = 24;\r
379   settings.antialiasingLevel = 0;\r
380   settings.majorVersion = 4;\r
381   settings.minorVersion = 6;\r
382 \r
383   sf::RenderWindow window(sf::VideoMode(1600, 900), "Subsurface Scattering",\r
384                     sf::Style::Default, settings);\r
385   window.setVerticalSyncEnabled(true);\r
386 \r
387   ImGui::SFML::Init(window);\r
388 \r
389   // Initialize GLEW\r
390 \r
391   if (glewInit() != GLEW_OK) {\r
392   }\r
393 \r
394   GLuint shaderProgramShadowmap = compileShaders("shaders/vert_shadowmap.glsl", "shaders/frag_shadowmap.glsl");\r
395   GLuint shaderProgramIrradiance = compileShaders("shaders/vert_irradiance.glsl", "shaders/frag_irradiance.glsl");\r
396 \r
397   model m = loadModel("models/Isotrop-upperjaw.ply");\r
398   \r
399   arccam arcCam;\r
400   freecam freeCam;\r
401 \r
402   // MVP\r
403 \r
404   glm::mat4 model = glm::scale(glm::mat4(1.0f), glm::vec3(0.01f, 0.01f, 0.01f));\r
405 \r
406   glm::mat4 view, lightView;\r
407 \r
408   glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)window.getSize().x / window.getSize().y, 0.001f, 1000.0f);\r
409   glm::mat4 lightProj = glm::perspective(glm::radians(90.0f), (float)window.getSize().x / window.getSize().y, 0.001f, 1000.0f);\r
410 \r
411   // Framebuffer\r
412 \r
413   framebuffer fb_shadowmap("shaders/fbo_vert.glsl", "shaders/fbo_frag.glsl", width, height);\r
414   framebuffer fb_irradiance("shaders/fbo_vert.glsl", "shaders/fbo_frag.glsl", width, height);\r
415 \r
416   // Config\r
417 \r
418   const struct {\r
419     bool wireframe = false;\r
420     bool freecam = false;\r
421     int renderState = 2;\r
422     float color[3] = { 0.7f, 0.4f, 0.4f };\r
423     glm::vec3 lightPos = glm::vec3(0.0f, 0.0f, 0.03f);\r
424     float transmittanceScale = 0.025f;\r
425     float powBase = 2;\r
426     float powFactor = 1.5;\r
427   } DefaultOptions;\r
428 \r
429   auto options = DefaultOptions;\r
430 \r
431   sf::Clock deltaClock;\r
432 \r
433   bool prevMouse = false;\r
434 \r
435   bool running = true;\r
436   while (running) {\r
437     // Events\r
438 \r
439     sf::Event event;\r
440     while (window.pollEvent(event)) {\r
441       ImGui::SFML::ProcessEvent(event);\r
442 \r
443       if (event.type == sf::Event::EventType::Closed) {\r
444         running = false;\r
445       } else if (event.type == sf::Event::EventType::Resized) {\r
446         glViewport(0, 0, event.size.width, event.size.height);\r
447       } else if (event.type == sf::Event::EventType::KeyReleased) {\r
448         using keys = sf::Keyboard;\r
449         switch (event.key.code) {\r
450         case keys::Escape:\r
451           running = false;\r
452           break;\r
453         }\r
454       } else if (event.type == sf::Event::EventType::MouseWheelScrolled) {\r
455         if (! options.freecam) {\r
456           arcCam.radius -= event.mouseWheelScroll.delta / 5.0f;\r
457         }\r
458       }\r
459     }\r
460 \r
461     // Update Camera\r
462 \r
463     if (sf::Mouse::isButtonPressed(sf::Mouse::Right)) {\r
464       window.setMouseCursorVisible(false);\r
465 \r
466       if (prevMouse) {\r
467         if (options.freecam)\r
468           freeCam.update(window);\r
469         else\r
470           arcCam.update(window);\r
471       }\r
472 \r
473 \r
474       sf::Mouse::setPosition(sf::Vector2i(\r
475           window.getSize().x / 2,\r
476           window.getSize().y / 2\r
477         ), window);  \r
478     } else {\r
479       window.setMouseCursorVisible(true);\r
480     }\r
481 \r
482     prevMouse = sf::Mouse::isButtonPressed(sf::Mouse::Right);\r
483 \r
484     // Render Shadowmap to fbo\r
485 \r
486     glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE);\r
487     glClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE);\r
488     glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);\r
489 \r
490     glBindFramebuffer(GL_FRAMEBUFFER, fb_shadowmap.fbo);\r
491     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);\r
492     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r
493     glEnable(GL_DEPTH_TEST);\r
494 \r
495     if (options.wireframe)\r
496       glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);\r
497     else\r
498       glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r
499 \r
500     glUseProgram(shaderProgramShadowmap);\r
501     \r
502     if (options.freecam)\r
503       view = freeCam.getViewMatrix();\r
504     else\r
505       view = arcCam.getViewMatrix();\r
506     \r
507     lightView = glm::lookAt(options.lightPos, glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));\r
508     \r
509     glUniformMatrix4fv(\r
510       glGetUniformLocation(shaderProgramShadowmap, "model"),\r
511       1, GL_FALSE, glm::value_ptr(model));\r
512     glUniformMatrix4fv(\r
513       glGetUniformLocation(shaderProgramShadowmap, "lightView"),\r
514       1, GL_FALSE, glm::value_ptr(lightView));\r
515     glUniformMatrix4fv(\r
516       glGetUniformLocation(shaderProgramShadowmap, "projection"),\r
517       1, GL_FALSE, glm::value_ptr(lightProj));\r
518 \r
519     glUniform3fv(\r
520       glGetUniformLocation(shaderProgramShadowmap, "lightPos"),\r
521       1, glm::value_ptr(options.lightPos));\r
522 \r
523     m.draw();\r
524 \r
525     // Render irradiance map to fbo\r
526 \r
527     glBindFramebuffer(GL_FRAMEBUFFER, fb_irradiance.fbo);\r
528     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);\r
529     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r
530     glEnable(GL_DEPTH_TEST);\r
531 \r
532     if (options.wireframe)\r
533       glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);\r
534     else\r
535       glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r
536 \r
537     glUseProgram(shaderProgramIrradiance);\r
538     \r
539     glUniformMatrix4fv(\r
540       glGetUniformLocation(shaderProgramIrradiance, "model"),\r
541       1, GL_FALSE, glm::value_ptr(model));\r
542     glUniformMatrix4fv(\r
543       glGetUniformLocation(shaderProgramIrradiance, "view"),\r
544       1, GL_FALSE, glm::value_ptr(view));\r
545     glUniformMatrix4fv(\r
546       glGetUniformLocation(shaderProgramIrradiance, "lightView"),\r
547       1, GL_FALSE, glm::value_ptr(lightView));\r
548     glUniformMatrix4fv(\r
549       glGetUniformLocation(shaderProgramIrradiance, "lightViewInv"),\r
550       1, GL_FALSE, glm::value_ptr(glm::inverse(lightView)));\r
551     glUniformMatrix4fv(\r
552       glGetUniformLocation(shaderProgramIrradiance, "projection"),\r
553       1, GL_FALSE, glm::value_ptr(proj));\r
554     glUniformMatrix4fv(\r
555       glGetUniformLocation(shaderProgramIrradiance, "lightProjection"),\r
556       1, GL_FALSE, glm::value_ptr(lightProj));\r
557     glUniform1i(glGetUniformLocation(shaderProgramIrradiance, "screenWidth"), window.getSize().x);\r
558     glUniform1i(glGetUniformLocation(shaderProgramIrradiance, "screenHeight"), window.getSize().y);\r
559     glUniform1fv(glGetUniformLocation(shaderProgramIrradiance, "samplePositions"), 13, samplePositions);\r
560     glUniform3fv(glGetUniformLocation(shaderProgramIrradiance, "sampleWeights"), 13, sampleWeights);\r
561 \r
562     glUniform1f(\r
563       glGetUniformLocation(shaderProgramIrradiance, "transmittanceScale"),\r
564       options.transmittanceScale);\r
565     glUniform1i(\r
566       glGetUniformLocation(shaderProgramIrradiance, "renderState"),\r
567       options.renderState);\r
568     glUniform1f(\r
569       glGetUniformLocation(shaderProgramIrradiance, "powBase"),\r
570       options.powBase);\r
571     glUniform1f(\r
572       glGetUniformLocation(shaderProgramIrradiance, "powFactor"),\r
573       options.powFactor);\r
574 \r
575     glUniform3fv(\r
576       glGetUniformLocation(shaderProgramIrradiance, "objectColor"),\r
577       1, options.color);\r
578     glUniform3f(\r
579       glGetUniformLocation(shaderProgramIrradiance, "lightColor"),\r
580       1.0f, 1.0f, 1.0f);\r
581     glUniform3fv(\r
582       glGetUniformLocation(shaderProgramIrradiance, "lightPos"),\r
583       1, glm::value_ptr(options.lightPos));\r
584     glUniform3fv(\r
585       glGetUniformLocation(shaderProgramIrradiance, "viewPos"),\r
586       1, glm::value_ptr(options.freecam ? freeCam.pos : arcCam.getPos()));\r
587       \r
588       \r
589     glUniform1i(glGetUniformLocation(shaderProgramIrradiance, "shadowmapTexture"), 0);\r
590     glActiveTexture(GL_TEXTURE0 + 0);\r
591     glBindTexture(GL_TEXTURE_2D, fb_shadowmap.renderTexture);\r
592 \r
593     m.draw();\r
594 \r
595     // Render fbos to screen and calculate light spread/translucency in shader\r
596     \r
597     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r
598 \r
599     glBindFramebuffer(GL_FRAMEBUFFER, 0);\r
600     glDisable(GL_DEPTH_TEST);\r
601     glClearColor(1.0f, 1.0f, 1.0f, 1.0f);\r
602     glClear(GL_COLOR_BUFFER_BIT);\r
603     glUseProgram(fb_irradiance.screenShaderProgram);\r
604 \r
605     glUniform1i(glGetUniformLocation(fb_irradiance.screenShaderProgram, "screenWidth"), window.getSize().x);\r
606     glUniform1i(glGetUniformLocation(fb_irradiance.screenShaderProgram, "screenHeight"), window.getSize().y);\r
607     glUniform1i(glGetUniformLocation(fb_irradiance.screenShaderProgram, "renderState"), options.renderState);\r
608     glUniform2fv(glGetUniformLocation(fb_irradiance.screenShaderProgram, "samplePositions"), 13, samplePositions);\r
609     glUniform3fv(glGetUniformLocation(fb_irradiance.screenShaderProgram, "sampleWeights"), 13, sampleWeights);\r
610 \r
611     glBindVertexArray(fb_irradiance.screenVAO);\r
612     glUniform1i(glGetUniformLocation(fb_irradiance.screenShaderProgram, "shadowmapTexture"), 0);\r
613     glUniform1i(glGetUniformLocation(fb_irradiance.screenShaderProgram, "irradianceTexture"), 1);\r
614     glActiveTexture(GL_TEXTURE0 + 0);\r
615     glBindTexture(GL_TEXTURE_2D, fb_shadowmap.renderTexture);\r
616     glActiveTexture(GL_TEXTURE0 + 1);\r
617     glBindTexture(GL_TEXTURE_2D, fb_irradiance.renderTexture);\r
618     glDrawArrays(GL_TRIANGLES, 0, 6);\r
619     glBindVertexArray(0);\r
620 \r
621     // menu\r
622 \r
623     ImGui::SFML::Update(window, deltaClock.restart());\r
624 \r
625     ImGui::Begin("Options");\r
626     ImGui::Checkbox("Wireframe", &options.wireframe);\r
627     ImGui::Checkbox("Free Cam", &options.freecam);\r
628     ImGui::InputInt("Render State", &options.renderState);\r
629     ImGui::DragFloat3("Color", options.color, 0.01, 0, 1);\r
630     ImGui::DragFloat("Transmittance Scale", &options.transmittanceScale, 0.0001f, 0, 0.3);\r
631     ImGui::DragFloat3("Light Pos", glm::value_ptr(options.lightPos), 0.01, -5, 5);\r
632     if (options.freecam) {\r
633       ImGui::LabelText("Position", "%f %f %f", freeCam.pos.x, freeCam.pos.y, freeCam.pos.z);\r
634       ImGui::LabelText("Rotation", "%f %f", freeCam.rot.x, freeCam.rot.y);\r
635       if (ImGui::Button("Reset")) {\r
636         freeCam.pos = glm::vec3(0, 0, -1);\r
637         freeCam.rot = glm::vec2(0);\r
638         options = DefaultOptions;\r
639       }\r
640     } else {\r
641       ImGui::LabelText("Rotation", "%f %f", arcCam.rot.x, arcCam.rot.y);\r
642       ImGui::DragFloat("Radius", &arcCam.radius, 0.01f, -1.0f, 1.0f);\r
643       if (ImGui::Button("Reset")) {\r
644         arcCam.rot = glm::vec2(0);\r
645         arcCam.radius = 1;\r
646         options = DefaultOptions;\r
647       }\r
648     }\r
649     ImGui::End();\r
650 \r
651     ImGui::SFML::Render(window);\r
652 \r
653     window.display();\r
654   }\r
655 \r
656   return 0;\r
657 }\r