\r
#include <GL/glew.h>\r
\r
+#define GLM_ENABLE_EXPERIMENTAL\r
+\r
#include <glm/glm.hpp>\r
+#include <glm/gtx/rotate_vector.hpp>\r
#include <glm/gtc/matrix_transform.hpp>\r
#include <glm/gtc/type_ptr.hpp>\r
\r
#include <SFML/OpenGL.hpp>\r
-#include <SFML/Window.hpp>\r
+#include <SFML/Graphics.hpp>\r
+\r
+#include <imgui.h>\r
+#include <imgui-SFML.h>\r
\r
#include <assimp/Importer.hpp>\r
-#include <assimp/scene.h>\r
#include <assimp/postprocess.h>\r
+#include <assimp/scene.h>\r
+\r
+const char *vertexShaderSource = R"(\r
+#version 330 core\r
+\r
+layout (location = 0) in vec3 pos;\r
+layout (location = 1) in vec3 normal;\r
+\r
+out vec3 FragPos;\r
+out vec3 Normal;\r
+\r
+uniform mat4 model;\r
+uniform mat4 view;\r
+uniform mat4 projection;\r
+\r
+void main()\r
+{\r
+ gl_Position = projection * view * model * vec4(pos, 1.0);\r
+ FragPos = vec3(model * vec4(pos, 1));\r
+ Normal = normal;\r
+}\r
+)";\r
+\r
+const char *fragmentShaderSource = R"(\r
+#version 330 core\r
+\r
+in vec3 FragPos;\r
+in vec3 Normal;\r
+\r
+out vec4 FragColor;\r
+\r
+uniform vec3 objectColor;\r
+uniform vec3 lightColor;\r
+uniform vec3 lightPos;\r
\r
+void main()\r
+{\r
+ vec3 norm = normalize(Normal);\r
+ vec3 lightDir = normalize(lightPos - FragPos);\r
\r
-const char *vertexShaderSource =\r
-"#version 330 core\n"\r
-"layout (location = 0) in vec3 pos;\n"\r
-"uniform mat4 model;\n"\r
-"uniform mat4 view;\n"\r
-"uniform mat4 projection;\n"\r
-"\n"\r
-"void main()\n"\r
-"{\n"\r
-" gl_Position = projection * view * model * vec4(pos, 1.0);\n"\r
-"}\n";\r
-\r
-const char *fragmentShaderSource =\r
-"#version 330 core\n"\r
-"out vec4 FragColor;\n"\r
-"\n"\r
-"void main()\n"\r
-"{\n"\r
-" FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n"\r
-"}\n";\r
+ float diff = max(dot(norm, lightDir), 0.0);\r
+ vec3 diffuse = diff * lightColor;\r
+\r
+ float ambientStrength = 0.1;\r
+ vec3 ambient = ambientStrength * lightColor;\r
+\r
+ vec3 result = (ambient + diffuse) * objectColor;\r
+ FragColor = vec4(result, 1.0f);\r
+}\r
+)";\r
\r
std::vector<float> vertices;\r
std::vector<GLuint> indices;\r
\r
+glm::vec3 lightPos(1.2f, 5.0f, 2.0f);\r
\r
-void load(const std::string &filename, std::vector<float> &vertices, std::vector<GLuint> &indices) {\r
+void load(const std::string &filename, std::vector<float> &vertices,\r
+ std::vector<GLuint> &indices) {\r
Assimp::Importer importer;\r
\r
const aiScene *scene = importer.ReadFile(\r
- filename,\r
- aiProcess_CalcTangentSpace |\r
- aiProcess_Triangulate |\r
- aiProcess_JoinIdenticalVertices |\r
- aiProcess_SortByPType\r
- );\r
+ filename, aiProcess_CalcTangentSpace | aiProcess_Triangulate |\r
+ aiProcess_SortByPType | aiProcess_GenSmoothNormals);\r
\r
for (int i = 0; i < scene->mMeshes[0]->mNumVertices; i++) {\r
aiVector3D v = scene->mMeshes[0]->mVertices[i];\r
+ aiVector3D n = scene->mMeshes[0]->mNormals[i];\r
vertices.push_back(v.x);\r
vertices.push_back(v.y);\r
vertices.push_back(v.z);\r
+ vertices.push_back(n.x);\r
+ vertices.push_back(n.y);\r
+ vertices.push_back(n.z);\r
}\r
\r
for (int i = 0; i < scene->mMeshes[0]->mNumFaces; i++) {\r
settings.majorVersion = 4;\r
settings.minorVersion = 6;\r
\r
- sf::Window window(sf::VideoMode(800, 600), "Subsurface Scattering",\r
+ sf::RenderWindow window(sf::VideoMode(1600, 900), "Subsurface Scattering",\r
sf::Style::Default, settings);\r
window.setVerticalSyncEnabled(true);\r
+ window.setMouseCursorGrabbed(true);\r
+ window.setMouseCursorVisible(false);\r
\r
- window.setActive(true);\r
+ ImGui::SFML::Init(window);\r
\r
// Initialize GLEW\r
\r
if (glewInit() != GLEW_OK) {\r
-\r
}\r
\r
load("models/Isotrop-upperjaw.ply", vertices, indices);\r
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);\r
glCompileShader(vertexShader);\r
\r
- int success;\r
+ int success;\r
char infoLog[512];\r
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);\r
if (!success) {\r
- glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);\r
- printf("Error compiling vertex shader: %s\n", infoLog);\r
+ glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);\r
+ printf("Error compiling vertex shader: %s\n", infoLog);\r
}\r
\r
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);\r
\r
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);\r
if (!success) {\r
- glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);\r
- printf("Error compiling fragment shader: %s\n", infoLog);\r
+ glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);\r
+ printf("Error compiling fragment shader: %s\n", infoLog);\r
}\r
\r
// Link Shader Program\r
glAttachShader(shaderProgram, vertexShader);\r
glAttachShader(shaderProgram, fragmentShader);\r
glLinkProgram(shaderProgram);\r
- \r
+\r
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);\r
if (!success) {\r
- glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);\r
- printf("Error linking shader program: %s\n", infoLog);\r
+ glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);\r
+ printf("Error linking shader program: %s\n", infoLog);\r
}\r
\r
glDeleteShader(vertexShader);\r
\r
GLuint EBO;\r
glGenBuffers(1, &EBO);\r
- \r
+\r
// Create VAO\r
\r
GLuint VAO;\r
glGenVertexArrays(1, &VAO);\r
\r
glBindVertexArray(VAO);\r
- \r
+\r
glBindBuffer(GL_ARRAY_BUFFER, VBO);\r
- glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), vertices.data(), GL_STATIC_DRAW);\r
- \r
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(),\r
+ vertices.data(), GL_STATIC_DRAW);\r
+\r
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);\r
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(), indices.data(), GL_STATIC_DRAW);\r
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * indices.size(),\r
+ indices.data(), GL_STATIC_DRAW);\r
\r
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, NULL);\r
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(0));\r
glEnableVertexAttribArray(0);\r
+ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*)(sizeof(float) * 3));\r
+ glEnableVertexAttribArray(1);\r
\r
glBindVertexArray(0);\r
\r
// Perspective\r
\r
- glm::mat4 model = glm::mat4(1.0f);\r
+ glm::mat4 model = glm::scale(glm::mat4(1.0f), glm::vec3(0.01f, 0.01f, 0.01f));\r
+\r
+ struct {\r
+ float camX = 0;\r
+ float camZ = -5;\r
+ int mouseX = 0;\r
+ int mouseY = 0;\r
+ } arcball;\r
+\r
+ struct {\r
+ int mouseX = 0;\r
+ int mouseY = 0;\r
+ } freecam;\r
\r
- glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -200.0f));\r
+ glm::vec3 camPos = glm::vec3(0, 0, -3);\r
+ glm::vec3 camForward = glm::vec3(0, 0, 1);\r
+ glm::vec3 camUp = glm::vec3(0, 1, 0);\r
\r
- glm::mat4 proj = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 1000.0f);\r
+ glm::mat4 view =\r
+ glm::lookAt(glm::vec3(arcball.camX, 0.0, arcball.camZ), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));\r
\r
- bool wireframe = false;\r
+ glm::mat4 proj =\r
+ glm::perspective(glm::radians(45.0f), (float)window.getSize().x / window.getSize().y, 0.001f, 1000.0f);\r
+\r
+ struct {\r
+ bool catchMouse = false;\r
+ bool wireframe = false;\r
+ bool freecam = false;\r
+ float radius = 1.0f;\r
+ } options;\r
+\r
+ sf::Clock deltaClock;\r
\r
bool running = true;\r
while (running) {\r
sf::Event event;\r
while (window.pollEvent(event)) {\r
- if (event.type == sf::Event::Closed) {\r
+ ImGui::SFML::ProcessEvent(event);\r
+\r
+ if (event.type == sf::Event::EventType::Closed) {\r
running = false;\r
- } else if (event.type == sf::Event::Resized) {\r
+ } else if (event.type == sf::Event::EventType::Resized) {\r
glViewport(0, 0, event.size.width, event.size.height);\r
- } else if (event.type == sf::Event::KeyReleased) {\r
+ } else if (event.type == sf::Event::EventType::KeyReleased) {\r
using keys = sf::Keyboard;\r
switch (event.key.code) {\r
- case keys::W:\r
- wireframe = !wireframe;\r
- break;\r
case keys::Escape:\r
running = false;\r
break;\r
+ case keys::C:\r
+ options.catchMouse = !options.catchMouse;\r
+ break;\r
+ case keys::R:\r
+ freecam.mouseX = freecam.mouseY = 0;\r
+ break;\r
}\r
+ } else if (event.type == sf::Event::EventType::MouseWheelScrolled) {\r
+ options.radius -= event.mouseWheelScroll.delta / 5.0f;\r
}\r
}\r
\r
+ int mouseDeltaX = sf::Mouse::getPosition(window).x - window.getSize().x / 2;\r
+ int mouseDeltaY = sf::Mouse::getPosition(window).y - window.getSize().y / 2;\r
+\r
+ if (options.catchMouse) {\r
+ sf::Mouse::setPosition(sf::Vector2i(\r
+ window.getSize().x / 2,\r
+ window.getSize().y / 2\r
+ ), window);\r
+\r
+ if (options.freecam) {\r
+ freecam.mouseX += mouseDeltaX;\r
+ freecam.mouseY += mouseDeltaY;\r
+\r
+ camForward = glm::rotate(glm::vec3(0, 0, 1), freecam.mouseY / 500.0f, glm::vec3(1, 0, 0));\r
+ camForward = glm::rotate(camForward, -freecam.mouseX / 500.0f, glm::vec3(0, 1, 0));\r
+\r
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) {\r
+ camPos += camForward / 20.0f;\r
+ }\r
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) {\r
+ camPos -= camForward / 20.0f;\r
+ }\r
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) {\r
+ glm::vec3 camLeft = glm::rotate(glm::vec3(0, 0, 1), -freecam.mouseX / 500.0f + glm::radians(90.0f), glm::vec3(0, 1, 0));\r
+ camPos += camLeft / 20.0f;\r
+ }\r
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) {\r
+ glm::vec3 camRight = glm::rotate(glm::vec3(0, 0, 1), -freecam.mouseX / 500.0f - glm::radians(90.0f), glm::vec3(0, 1, 0));\r
+ camPos += camRight / 20.0f;\r
+ }\r
+ } else {\r
+ if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {\r
+ arcball.mouseX += mouseDeltaX;\r
+ arcball.mouseY += mouseDeltaY;\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+\r
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r
\r
glEnable(GL_DEPTH_TEST);\r
\r
- if (wireframe)\r
+ if (options.wireframe)\r
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);\r
else\r
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r
\r
- model = glm::rotate(model, glm::radians(0.2f), glm::vec3(0.0f, 1.0f, 0.0f));\r
+ glUseProgram(shaderProgram);\r
\r
- glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));\r
- glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE, glm::value_ptr(view));\r
- glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(proj));\r
+ //rotate\r
+ //model = glm::rotate(model, glm::radians(0.2f), glm::vec3(0.0f, 1.0f, 0.0f));\r
+\r
+ if (options.freecam) {\r
+ view = glm::lookAt(camPos, camPos + camForward, camUp);\r
+ } else {\r
+ float angle = arcball.mouseY / 200.0f;\r
+ if (angle > glm::radians(89.0f)) {\r
+ angle = glm::radians(89.0f);\r
+ arcball.mouseY = angle * 200.0f;\r
+ }\r
+ if (angle < glm::radians(-89.0f)) {\r
+ angle = glm::radians(-89.0f);\r
+ arcball.mouseY = angle * 200.0f;\r
+ }\r
+ arcball.camX = sin(angle) * exp(options.radius);\r
+ arcball.camZ = cos(angle) * exp(options.radius);\r
+ view = glm::lookAt(glm::vec3(0.0, arcball.camX, arcball.camZ), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));\r
+ view = glm::rotate(view, arcball.mouseX / 100.0f, glm::vec3(0, 1, 0));\r
+ }\r
+\r
+ glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1,\r
+ GL_FALSE, glm::value_ptr(model));\r
+ glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE,\r
+ glm::value_ptr(view));\r
+ glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1,\r
+ GL_FALSE, glm::value_ptr(proj));\r
+\r
+ glUniform3f(glGetUniformLocation(shaderProgram, "objectColor"), 1.0f, 0.5f,\r
+ 0.31f);\r
+ glUniform3f(glGetUniformLocation(shaderProgram, "lightColor"), 1.0f, 1.0f,\r
+ 1.0f);\r
+ glUniform3fv(glGetUniformLocation(shaderProgram, "lightPos"), 1, glm::value_ptr(lightPos));\r
\r
- glUseProgram(shaderProgram);\r
glBindVertexArray(VAO);\r
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);\r
glBindVertexArray(0);\r
+ \r
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);\r
+\r
+ ImGui::SFML::Update(window, deltaClock.restart());\r
+\r
+ ImGui::Begin("Options");\r
+ ImGui::LabelText("Cursor Locked", "%d", options.catchMouse);\r
+ ImGui::Checkbox("Wireframe", &options.wireframe);\r
+ ImGui::Checkbox("Free Cam", &options.freecam);\r
+ if (options.freecam) {\r
+ ImGui::LabelText("Position", "%f %f %f", camPos.x, camPos.y, camPos.z);\r
+ ImGui::LabelText("Forward", "%f %f %f", camForward.x, camForward.y, camForward.z);\r
+ ImGui::LabelText("Mouse", "%d %d", freecam.mouseX, freecam.mouseY);\r
+ } else {\r
+ ImGui::LabelText("Rotation", "%f %f", arcball.camX, arcball.camZ);\r
+ ImGui::InputFloat("Radius", &options.radius);\r
+ }\r
+ ImGui::End();\r
+\r
+ ImGui::SFML::Render(window);\r
\r
window.display();\r
}\r