diff --git a/assets/shaders/lighting_dir_point_spot.frag b/assets/shaders/lighting.frag similarity index 100% rename from assets/shaders/lighting_dir_point_spot.frag rename to assets/shaders/lighting.frag diff --git a/assets/shaders/lighting_dir_point_spot.vert b/assets/shaders/lighting.vert similarity index 100% rename from assets/shaders/lighting_dir_point_spot.vert rename to assets/shaders/lighting.vert diff --git a/include/Lighting.h b/include/Lighting.h new file mode 100644 index 0000000..f343de9 --- /dev/null +++ b/include/Lighting.h @@ -0,0 +1,52 @@ +#ifndef LIGHTING_H +#define LIGHTING_H + +namespace djalim { + class ShaderProgram; +} + +#include "Camera.h" +#include + +struct DirectionalLight { + glm::vec3 direction; + glm::vec3 ambient; + glm::vec3 diffuse; + glm::vec3 specular; +}; + +struct PointLight { + glm::vec3 position; + glm::vec3 ambient; + glm::vec3 diffuse; + glm::vec3 specular; + float constant; + float linear; + float exponent; +}; + +struct SpotLight { + glm::vec3 position; + glm::vec3 direction; + glm::vec3 ambient; + glm::vec3 diffuse; + glm::vec3 specular; + float cosInnerCone; + float cosOuterCone; + float constant; + float linear; + float exponent; + bool on; +}; + +class Lighting { +public: + Lighting(); + void update(djalim::ShaderProgram& shader, FPSCamera& camera); + + DirectionalLight sunLight; + PointLight pointLights[3]; + SpotLight spotLight; +}; + +#endif // LIGHTING_H diff --git a/include/ShaderProgram.h b/include/ShaderProgram.h index 6b8f16f..06f419e 100644 --- a/include/ShaderProgram.h +++ b/include/ShaderProgram.h @@ -21,6 +21,7 @@ namespace djalim { void setUniform(const std::string& name, const glm::vec3& value); void setUniform(const std::string& name, const glm::vec4& value); void setUniform(const std::string& name, const glm::mat4& value); + void setUniformSampler(const std::string& name, int value); GLuint getProgram() const { return mHandle; } diff --git a/include/engine.h b/include/engine.h index 820aea3..363b9a5 100644 --- a/include/engine.h +++ b/include/engine.h @@ -9,6 +9,7 @@ #include #include #include "Mesh3D.h" +#include "Lighting.h" #include #include #include @@ -48,6 +49,7 @@ namespace djalim { int frameCount = 0; ShaderProgram shaderProgram; FPSCamera Camera = FPSCamera(glm::vec3(0.0f, 2.0f, 10.0f)); + Lighting lighting; Objects3D objects; diff --git a/src/core/Lighting.cpp b/src/core/Lighting.cpp new file mode 100644 index 0000000..daed1bc --- /dev/null +++ b/src/core/Lighting.cpp @@ -0,0 +1,101 @@ +#include "Lighting.h" +#include "ShaderProgram.h" +#include + +Lighting::Lighting() { + // Directional light + sunLight.direction = glm::vec3(0.0f, -0.9f, -0.17f); + sunLight.ambient = glm::vec3(0.1f, 0.1f, 0.1f); + sunLight.diffuse = glm::vec3(0.1f, 0.1f, 0.1f); + sunLight.specular = glm::vec3(0.1f, 0.1f, 0.1f); + + // Point Light 1 + pointLights[0].position = glm::vec3(-5.0f, 3.8f, 0.0f); + pointLights[0].ambient = glm::vec3(0.2f, 0.2f, 0.2f); + pointLights[0].diffuse = glm::vec3(0.0f, 1.0f, 0.1f); + pointLights[0].specular = glm::vec3(1.0f, 1.0f, 1.0f); + pointLights[0].constant = 1.0f; + pointLights[0].linear = 0.22f; + pointLights[0].exponent = 0.20f; + + // Point Light 2 + pointLights[1].position = glm::vec3(0.5f, 3.8f, 0.0f); + pointLights[1].ambient = glm::vec3(0.2f, 0.2f, 0.2f); + pointLights[1].diffuse = glm::vec3(1.0f, 0.1f, 0.0f); + pointLights[1].specular = glm::vec3(1.0f, 1.0f, 1.0f); + pointLights[1].constant = 1.0f; + pointLights[1].linear = 0.22f; + pointLights[1].exponent = 0.20f; + + // Point Light 3 + pointLights[2].position = glm::vec3(5.0f, 3.8f, 0.0f); + pointLights[2].ambient = glm::vec3(0.2f, 0.2f, 0.2f); + pointLights[2].diffuse = glm::vec3(0.0f, 0.1f, 1.0f); + pointLights[2].specular = glm::vec3(1.0f, 1.0f, 1.0f); + pointLights[2].constant = 1.0f; + pointLights[2].linear = 0.22f; + pointLights[2].exponent = 0.20f; + + // Spot light + spotLight.ambient = glm::vec3(0.1f, 0.1f, 0.1f); + spotLight.diffuse = glm::vec3(0.8f, 0.8f, 0.8f); + spotLight.specular = glm::vec3(1.0f, 1.0f, 1.0f); + spotLight.cosInnerCone = glm::cos(glm::radians(15.0f)); + spotLight.cosOuterCone = glm::cos(glm::radians(20.0f)); + spotLight.constant = 1.0f; + spotLight.linear = 0.07f; + spotLight.exponent = 0.017f; + spotLight.on = true; +} + +void Lighting::update(djalim::ShaderProgram& shader, FPSCamera& camera) { + shader.use(); + + // Directional light + shader.setUniform("sunLight.direction", sunLight.direction); + shader.setUniform("sunLight.ambient", sunLight.ambient); + shader.setUniform("sunLight.diffuse", sunLight.diffuse); + shader.setUniform("sunLight.specular", sunLight.specular); + + // Point Light 1 + shader.setUniform("pointLights[0].position", pointLights[0].position); + shader.setUniform("pointLights[0].ambient", pointLights[0].ambient); + shader.setUniform("pointLights[0].diffuse", pointLights[0].diffuse); + shader.setUniform("pointLights[0].specular", pointLights[0].specular); + shader.setUniform("pointLights[0].constant", pointLights[0].constant); + shader.setUniform("pointLights[0].linear", pointLights[0].linear); + shader.setUniform("pointLights[0].exponent", pointLights[0].exponent); + + // Point Light 2 + shader.setUniform("pointLights[1].position", pointLights[1].position); + shader.setUniform("pointLights[1].ambient", pointLights[1].ambient); + shader.setUniform("pointLights[1].diffuse", pointLights[1].diffuse); + shader.setUniform("pointLights[1].specular", pointLights[1].specular); + shader.setUniform("pointLights[1].constant", pointLights[1].constant); + shader.setUniform("pointLights[1].linear", pointLights[1].linear); + shader.setUniform("pointLights[1].exponent", pointLights[1].exponent); + + // Point Light 3 + shader.setUniform("pointLights[2].position", pointLights[2].position); + shader.setUniform("pointLights[2].ambient", pointLights[2].ambient); + shader.setUniform("pointLights[2].diffuse", pointLights[2].diffuse); + shader.setUniform("pointLights[2].specular", pointLights[2].specular); + shader.setUniform("pointLights[2].constant", pointLights[2].constant); + shader.setUniform("pointLights[2].linear", pointLights[2].linear); + shader.setUniform("pointLights[2].exponent", pointLights[2].exponent); + + // Spot light + glm::vec3 spotlightPos = camera.getPosition(); + spotlightPos.y -= 0.5f; + shader.setUniform("spotLight.position", spotlightPos); + shader.setUniform("spotLight.direction", camera.getLook()); + shader.setUniform("spotLight.ambient", spotLight.ambient); + shader.setUniform("spotLight.diffuse", spotLight.diffuse); + shader.setUniform("spotLight.specular", spotLight.specular); + shader.setUniform("spotLight.cosInnerCone", spotLight.cosInnerCone); + shader.setUniform("spotLight.cosOuterCone", spotLight.cosOuterCone); + shader.setUniform("spotLight.constant", spotLight.constant); + shader.setUniform("spotLight.linear", spotLight.linear); + shader.setUniform("spotLight.exponent", spotLight.exponent); + shader.setUniform("spotLight.on", spotLight.on); +} diff --git a/src/core/Mesh3D.cpp b/src/core/Mesh3D.cpp index 821fe95..4041bd5 100644 --- a/src/core/Mesh3D.cpp +++ b/src/core/Mesh3D.cpp @@ -105,6 +105,19 @@ void djalim::Mesh3D::loadOBJFile(const std::string& filepath) { meshVertices.push_back(v.y); meshVertices.push_back(v.z); + // Si le fichier ne contient pas de vn, on met des normales par défaut (0,0,0) + int vnIndex = face.vertices[j].vn; + if (vnIndex >= 0 && vnIndex < (int)vertexNormal.size()) { + const objVertex& vn = vertexNormal[vnIndex]; + meshVertices.push_back(vn.x); + meshVertices.push_back(vn.y); + meshVertices.push_back(vn.z); + } else { + meshVertices.push_back(0.0f); + meshVertices.push_back(0.0f); + meshVertices.push_back(0.0f); + } + // Si le fichier ne contient pas de vt, on met des coordonnées par défaut (0,0) int vtIndex = face.vertices[j].vt; if (vtIndex >= 0 && vtIndex < (int)vertexTexture.size()) { diff --git a/src/core/ShaderProgram.cpp b/src/core/ShaderProgram.cpp index a0e61dd..412bbba 100644 --- a/src/core/ShaderProgram.cpp +++ b/src/core/ShaderProgram.cpp @@ -93,3 +93,7 @@ void djalim::ShaderProgram::setUniform(const std::string& name, float value) { void djalim::ShaderProgram::setUniform(const std::string& name, const glm::vec3& value) { glUniform3f(glGetUniformLocation(mHandle, name.c_str()), value.x, value.y, value.z); } + +void djalim::ShaderProgram::setUniformSampler(const std::string& name, int value) { + glUniform1i(glGetUniformLocation(mHandle, name.c_str()), value); +} diff --git a/src/core/engine.cpp b/src/core/engine.cpp index 9425807..a29de3f 100644 --- a/src/core/engine.cpp +++ b/src/core/engine.cpp @@ -1,4 +1,5 @@ #include "engine.h" +#include "Lighting.h" #include "Mesh3D.h" #include #include @@ -44,7 +45,7 @@ djalim::OpenGlEngine::OpenGlEngine(const char* title, int width, int height) { loadCallbacks(); - bool loaded = shaderProgram.loadShaders("../assets/shaders/vertex.glsl", "../assets/shaders/fragment.glsl"); + bool loaded = shaderProgram.loadShaders("../assets/shaders/lighting.vert", "../assets/shaders/lighting.frag"); if (!loaded) { std::cerr << "Failed to load shaders correctly" << std::endl; exit(1); @@ -92,11 +93,14 @@ void djalim::OpenGlEngine::createObject(std::string name, std::string textures, glBufferData(GL_ARRAY_BUFFER, sizeof(float)*(objects[name])->meshVertices.size(), (objects[name])->meshVertices.data(), GL_STATIC_DRAW); // Attribut de position - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); - // Attribut de coordonnée de texture - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); + // Attribut de normale + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); + // Attribut de coordonnée de texture + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); + glEnableVertexAttribArray(2); } djalim::OpenGlEngine::~OpenGlEngine() { @@ -140,6 +144,12 @@ void djalim::OpenGlEngine::draw(djalim::Mesh3D* object){ shaderProgram.setUniform("model", model); + // Set material properties + shaderProgram.setUniform("material.ambient", glm::vec3(0.1f, 0.1f, 0.1f)); + shaderProgram.setUniformSampler("material.diffuseMap", 0); + shaderProgram.setUniform("material.specular", glm::vec3(0.8f, 0.8f, 0.8f)); + shaderProgram.setUniform("material.shininess", 32.0f); + glBindVertexArray(object->VAO); glDrawArrays(GL_TRIANGLES, 0, object->numFaces * 3); } diff --git a/src/onCreate.cpp b/src/onCreate.cpp index 6d6ab79..67eb567 100644 --- a/src/onCreate.cpp +++ b/src/onCreate.cpp @@ -6,12 +6,15 @@ void djalim::OpenGlEngine::onCreate(){ stbi_set_flip_vertically_on_load(true); + shaderProgram.loadShaders("../assets/shaders/lighting.vert", "../assets/shaders/lighting.frag"); + lighting = Lighting(); + createObject("mimikyu", "../assets/textures/crate.jpg", "../assets/models/destiny island.obj", glm::vec3(0.0,0.0,0.0), glm::vec3(0.0,0.0,0.0), - glm::vec3(.1,.1,.1) + glm::vec3(.01,.01,.01) ); createObject("cube", "../assets/textures/crate.jpg", diff --git a/src/onUpdate.cpp b/src/onUpdate.cpp index cb3c0e7..8890bbe 100644 --- a/src/onUpdate.cpp +++ b/src/onUpdate.cpp @@ -7,7 +7,7 @@ void djalim::OpenGlEngine::onUpdate(){ showFps(); shaderProgram.use(); - shaderProgram.setUniform("ourTexture", 0); + shaderProgram.setUniform("material.diffuseMap", 0); glm::mat4 model(1.0), view(1.0), projection(1.0); @@ -21,6 +21,8 @@ void djalim::OpenGlEngine::onUpdate(){ shaderProgram.setUniform("projection", projection); shaderProgram.setUniform("view", view); + lighting.update(shaderProgram, Camera); + draw((objects["cube"]).get()); draw((objects["mimikyu"]).get());