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