]> gitweb.ps.run Git - subsurface_scattering/blob - src/main.cpp
fix lighting, add cam
[subsurface_scattering] / src / main.cpp
1 #include <stdio.h>\r
2 \r
3 #include <GL/glew.h>\r
4 \r
5 #define GLM_ENABLE_EXPERIMENTAL\r
6 \r
7 #include <glm/glm.hpp>\r
8 #include <glm/gtx/rotate_vector.hpp>\r
9 #include <glm/gtc/matrix_transform.hpp>\r
10 #include <glm/gtc/type_ptr.hpp>\r
11 \r
12 #include <SFML/OpenGL.hpp>\r
13 #include <SFML/Graphics.hpp>\r
14 \r
15 #include <imgui.h>\r
16 #include <imgui-SFML.h>\r
17 \r
18 #include <assimp/Importer.hpp>\r
19 #include <assimp/postprocess.h>\r
20 #include <assimp/scene.h>\r
21 \r
22 const char *vertexShaderSource = R"(\r
23 #version 330 core\r
24 \r
25 layout (location = 0) in vec3 pos;\r
26 layout (location = 1) in vec3 normal;\r
27 \r
28 out vec3 FragPos;\r
29 out vec3 Normal;\r
30 \r
31 uniform mat4 model;\r
32 uniform mat4 view;\r
33 uniform mat4 projection;\r
34 \r
35 void main()\r
36 {\r
37   gl_Position = projection * view * model * vec4(pos, 1.0);\r
38   FragPos = vec3(model * vec4(pos, 1));\r
39   Normal = normal;\r
40 }\r
41 )";\r
42 \r
43 const char *fragmentShaderSource = R"(\r
44 #version 330 core\r
45 \r
46 in vec3 FragPos;\r
47 in vec3 Normal;\r
48 \r
49 out vec4 FragColor;\r
50 \r
51 uniform vec3 objectColor;\r
52 uniform vec3 lightColor;\r
53 uniform vec3 lightPos;\r
54 \r
55 void main()\r
56 {\r
57   vec3 norm = normalize(Normal);\r
58   vec3 lightDir = normalize(lightPos - FragPos);\r
59 \r
60   float diff = max(dot(norm, lightDir), 0.0);\r
61   vec3 diffuse = diff * lightColor;\r
62 \r
63   float ambientStrength = 0.1;\r
64   vec3 ambient = ambientStrength * lightColor;\r
65 \r
66   vec3 result = (ambient + diffuse) * objectColor;\r
67   FragColor = vec4(result, 1.0f);\r
68 }\r
69 )";\r
70 \r
71 std::vector<float> vertices;\r
72 std::vector<GLuint> indices;\r
73 \r
74 glm::vec3 lightPos(1.2f, 5.0f, 2.0f);\r
75 \r
76 void load(const std::string &filename, std::vector<float> &vertices,\r
77           std::vector<GLuint> &indices) {\r
78   Assimp::Importer importer;\r
79 \r
80   const aiScene *scene = importer.ReadFile(\r
81       filename, aiProcess_CalcTangentSpace | aiProcess_Triangulate |\r
82                     aiProcess_SortByPType | aiProcess_GenSmoothNormals);\r
83 \r
84   for (int i = 0; i < scene->mMeshes[0]->mNumVertices; i++) {\r
85     aiVector3D v = scene->mMeshes[0]->mVertices[i];\r
86     aiVector3D n = scene->mMeshes[0]->mNormals[i];\r
87     vertices.push_back(v.x);\r
88     vertices.push_back(v.y);\r
89     vertices.push_back(v.z);\r
90     vertices.push_back(n.x);\r
91     vertices.push_back(n.y);\r
92     vertices.push_back(n.z);\r
93   }\r
94 \r
95   for (int i = 0; i < scene->mMeshes[0]->mNumFaces; i++) {\r
96     aiFace f = scene->mMeshes[0]->mFaces[i];\r
97     for (int j = 0; j < f.mNumIndices; j++) {\r
98       indices.push_back(f.mIndices[j]);\r
99     }\r
100   }\r
101 }\r
102 \r
103 int main() {\r
104   // Window Setup\r
105 \r
106   sf::ContextSettings settings;\r
107   settings.depthBits = 24;\r
108   settings.antialiasingLevel = 0;\r
109   settings.majorVersion = 4;\r
110   settings.minorVersion = 6;\r
111 \r
112   sf::RenderWindow window(sf::VideoMode(1600, 900), "Subsurface Scattering",\r
113                     sf::Style::Default, settings);\r
114   window.setVerticalSyncEnabled(true);\r
115   window.setMouseCursorGrabbed(true);\r
116   window.setMouseCursorVisible(false);\r
117 \r
118   ImGui::SFML::Init(window);\r
119 \r
120   // Initialize GLEW\r
121 \r
122   if (glewInit() != GLEW_OK) {\r
123   }\r
124 \r
125   load("models/Isotrop-upperjaw.ply", vertices, indices);\r
126 \r
127   // Compile Shaders\r
128 \r
129   GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);\r
130   glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);\r
131   glCompileShader(vertexShader);\r
132 \r
133   int success;\r
134   char infoLog[512];\r
135   glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);\r
136   if (!success) {\r
137     glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);\r
138     printf("Error compiling vertex shader: %s\n", infoLog);\r
139   }\r
140 \r
141   GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);\r
142   glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);\r
143   glCompileShader(fragmentShader);\r
144 \r
145   glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);\r
146   if (!success) {\r
147     glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);\r
148     printf("Error compiling fragment shader: %s\n", infoLog);\r
149   }\r
150 \r
151   // Link Shader Program\r
152 \r
153   GLuint shaderProgram = glCreateProgram();\r
154   glAttachShader(shaderProgram, vertexShader);\r
155   glAttachShader(shaderProgram, fragmentShader);\r
156   glLinkProgram(shaderProgram);\r
157 \r
158   glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);\r
159   if (!success) {\r
160     glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);\r
161     printf("Error linking shader program: %s\n", infoLog);\r
162   }\r
163 \r
164   glDeleteShader(vertexShader);\r
165   glDeleteShader(fragmentShader);\r
166 \r
167   // Create VBO\r
168 \r
169   GLuint VBO;\r
170   glGenBuffers(1, &VBO);\r
171 \r
172   // Create EBO\r
173 \r
174   GLuint EBO;\r
175   glGenBuffers(1, &EBO);\r
176 \r
177   // Create VAO\r
178 \r
179   GLuint VAO;\r
180   glGenVertexArrays(1, &VAO);\r
181 \r
182   glBindVertexArray(VAO);\r
183 \r
184   glBindBuffer(GL_ARRAY_BUFFER, VBO);\r
185   glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(),\r
186                vertices.data(), GL_STATIC_DRAW);\r
187 \r
188   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);\r
189   glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(),\r
190                indices.data(), GL_STATIC_DRAW);\r
191 \r
192   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(0));\r
193   glEnableVertexAttribArray(0);\r
194   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(sizeof(float) * 3));\r
195   glEnableVertexAttribArray(1);\r
196 \r
197   glBindVertexArray(0);\r
198 \r
199   // Perspective\r
200 \r
201   glm::mat4 model = glm::scale(glm::mat4(1.0f), glm::vec3(0.01f, 0.01f, 0.01f));\r
202 \r
203   struct {\r
204     float camX = 0;\r
205     float camZ = -5;\r
206     int mouseX = 0;\r
207     int mouseY = 0;\r
208   } arcball;\r
209 \r
210   struct {\r
211     int mouseX = 0;\r
212     int mouseY = 0;\r
213   } freecam;\r
214 \r
215   glm::vec3 camPos = glm::vec3(0, 0, -3);\r
216   glm::vec3 camForward = glm::vec3(0, 0, 1);\r
217   glm::vec3 camUp = glm::vec3(0, 1, 0);\r
218 \r
219   glm::mat4 view =\r
220       glm::lookAt(glm::vec3(arcball.camX, 0.0, arcball.camZ), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));\r
221 \r
222   glm::mat4 proj =\r
223       glm::perspective(glm::radians(45.0f), (float)window.getSize().x / window.getSize().y, 0.001f, 1000.0f);\r
224 \r
225   struct {\r
226     bool catchMouse = false;\r
227     bool wireframe = false;\r
228     bool freecam = false;\r
229     float radius = 1.0f;\r
230   } options;\r
231 \r
232   sf::Clock deltaClock;\r
233 \r
234   bool running = true;\r
235   while (running) {\r
236     sf::Event event;\r
237     while (window.pollEvent(event)) {\r
238       ImGui::SFML::ProcessEvent(event);\r
239 \r
240       if (event.type == sf::Event::EventType::Closed) {\r
241         running = false;\r
242       } else if (event.type == sf::Event::EventType::Resized) {\r
243         glViewport(0, 0, event.size.width, event.size.height);\r
244       } else if (event.type == sf::Event::EventType::KeyReleased) {\r
245         using keys = sf::Keyboard;\r
246         switch (event.key.code) {\r
247         case keys::Escape:\r
248           running = false;\r
249           break;\r
250         case keys::C:\r
251           options.catchMouse = !options.catchMouse;\r
252           break;\r
253         case keys::R:\r
254           freecam.mouseX = freecam.mouseY = 0;\r
255           break;\r
256         }\r
257       } else if (event.type == sf::Event::EventType::MouseWheelScrolled) {\r
258         options.radius -= event.mouseWheelScroll.delta / 5.0f;\r
259       }\r
260     }\r
261 \r
262     int mouseDeltaX = sf::Mouse::getPosition(window).x - window.getSize().x / 2;\r
263     int mouseDeltaY = sf::Mouse::getPosition(window).y - window.getSize().y / 2;\r
264 \r
265     if (options.catchMouse) {\r
266       sf::Mouse::setPosition(sf::Vector2i(\r
267         window.getSize().x / 2,\r
268         window.getSize().y / 2\r
269       ), window);\r
270 \r
271       if (options.freecam) {\r
272         freecam.mouseX += mouseDeltaX;\r
273         freecam.mouseY += mouseDeltaY;\r
274 \r
275         camForward = glm::rotate(glm::vec3(0, 0, 1), freecam.mouseY / 500.0f, glm::vec3(1, 0, 0));\r
276         camForward = glm::rotate(camForward, -freecam.mouseX / 500.0f, glm::vec3(0, 1, 0));\r
277 \r
278         if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {\r
279           camPos += camForward / 20.0f;\r
280         }\r
281         if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {\r
282           camPos -= camForward / 20.0f;\r
283         }\r
284         if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) {\r
285           glm::vec3 camLeft = glm::rotate(glm::vec3(0, 0, 1), -freecam.mouseX / 500.0f + glm::radians(90.0f), glm::vec3(0, 1, 0));\r
286           camPos += camLeft / 20.0f;\r
287         }\r
288         if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) {\r
289           glm::vec3 camRight = glm::rotate(glm::vec3(0, 0, 1), -freecam.mouseX / 500.0f - glm::radians(90.0f), glm::vec3(0, 1, 0));\r
290           camPos += camRight / 20.0f;\r
291         }\r
292       } else {\r
293         if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {\r
294           arcball.mouseX += mouseDeltaX;\r
295           arcball.mouseY += mouseDeltaY;\r
296         }\r
297       }\r
298     }\r
299 \r
300 \r
301 \r
302     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r
303 \r
304     glEnable(GL_DEPTH_TEST);\r
305 \r
306     if (options.wireframe)\r
307       glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);\r
308     else\r
309       glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r
310 \r
311     glUseProgram(shaderProgram);\r
312 \r
313     //rotate\r
314     //model = glm::rotate(model, glm::radians(0.2f), glm::vec3(0.0f, 1.0f, 0.0f));\r
315 \r
316     if (options.freecam) {\r
317       view = glm::lookAt(camPos, camPos + camForward, camUp);\r
318     } else {\r
319       float angle = arcball.mouseY / 200.0f;\r
320       if (angle > glm::radians(89.0f)) {\r
321         angle = glm::radians(89.0f);\r
322         arcball.mouseY = angle * 200.0f;\r
323       }\r
324       if (angle < glm::radians(-89.0f)) {\r
325         angle = glm::radians(-89.0f);\r
326         arcball.mouseY = angle * 200.0f;\r
327       }\r
328       arcball.camX = sin(angle) * exp(options.radius);\r
329       arcball.camZ = cos(angle) * exp(options.radius);\r
330       view = glm::lookAt(glm::vec3(0.0, arcball.camX, arcball.camZ), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));\r
331       view = glm::rotate(view, arcball.mouseX / 100.0f, glm::vec3(0, 1, 0));\r
332     }\r
333 \r
334     glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1,\r
335                        GL_FALSE, glm::value_ptr(model));\r
336     glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE,\r
337                        glm::value_ptr(view));\r
338     glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1,\r
339                        GL_FALSE, glm::value_ptr(proj));\r
340 \r
341     glUniform3f(glGetUniformLocation(shaderProgram, "objectColor"), 1.0f, 0.5f,\r
342                 0.31f);\r
343     glUniform3f(glGetUniformLocation(shaderProgram, "lightColor"), 1.0f, 1.0f,\r
344                 1.0f);\r
345     glUniform3fv(glGetUniformLocation(shaderProgram, "lightPos"), 1, glm::value_ptr(lightPos));\r
346 \r
347     glBindVertexArray(VAO);\r
348     glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);\r
349     glBindVertexArray(0);\r
350     \r
351     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r
352 \r
353     ImGui::SFML::Update(window, deltaClock.restart());\r
354 \r
355     ImGui::Begin("Options");\r
356     ImGui::LabelText("Cursor Locked", "%d", options.catchMouse);\r
357     ImGui::Checkbox("Wireframe", &options.wireframe);\r
358     ImGui::Checkbox("Free Cam", &options.freecam);\r
359     if (options.freecam) {\r
360       ImGui::LabelText("Position", "%f %f %f", camPos.x, camPos.y, camPos.z);\r
361       ImGui::LabelText("Forward", "%f %f %f", camForward.x, camForward.y, camForward.z);\r
362       ImGui::LabelText("Mouse", "%d %d", freecam.mouseX, freecam.mouseY);\r
363     } else {\r
364       ImGui::LabelText("Rotation", "%f %f", arcball.camX, arcball.camZ);\r
365       ImGui::InputFloat("Radius", &options.radius);\r
366     }\r
367     ImGui::End();\r
368 \r
369     ImGui::SFML::Render(window);\r
370 \r
371     window.display();\r
372   }\r
373 \r
374   return 0;\r
375 }