Add lighting system with shaders, light structs, and material support

This commit is contained in:
Djalim Simaila 2025-10-29 21:18:17 +01:00
parent 579d5ec483
commit cae53dca8b
11 changed files with 194 additions and 6 deletions

52
include/Lighting.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef LIGHTING_H
#define LIGHTING_H
namespace djalim {
class ShaderProgram;
}
#include "Camera.h"
#include <glm/glm.hpp>
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

View File

@ -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; }

View File

@ -9,6 +9,7 @@
#include <memory>
#include <string>
#include "Mesh3D.h"
#include "Lighting.h"
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
@ -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;

101
src/core/Lighting.cpp Normal file
View File

@ -0,0 +1,101 @@
#include "Lighting.h"
#include "ShaderProgram.h"
#include <glm/gtc/matrix_transform.hpp>
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);
}

View File

@ -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()) {

View File

@ -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);
}

View File

@ -1,4 +1,5 @@
#include "engine.h"
#include "Lighting.h"
#include "Mesh3D.h"
#include <GLFW/glfw3.h>
#include <cstdlib>
@ -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);
}

View File

@ -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",

View File

@ -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());