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