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