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