add: added lighting classes and a shader to use multiple lights

This commit is contained in:
Lukian 2025-07-15 23:26:53 +02:00
parent ee9e540b5b
commit 2610da8f8c
4 changed files with 359 additions and 64 deletions

View file

@ -0,0 +1,143 @@
#ifndef LIGHTING_HPP
#define LIGHTING_HPP
#include <glm/glm.hpp>
#include <myEngine/shader.hpp>
class Light {
private:
glm::vec3 color;
glm::vec3 ambient;
glm::vec3 diffuse;
glm::vec3 specular;
public:
Light(const glm::vec3& color, const glm::vec3& ambient, const glm::vec3& diffuse, const glm::vec3& specular)
: color(color), ambient(ambient), diffuse(diffuse), specular(specular) {}
glm::vec3 getColor() const { return color; }
glm::vec3 getAmbient() const { return ambient; }
glm::vec3 getDiffuse() const { return diffuse; }
glm::vec3 getSpecular() const { return specular; }
void setColor(const glm::vec3& newColor) { color = newColor; }
void setAmbient(const glm::vec3& newAmbient) { ambient = newAmbient; }
void setDiffuse(const glm::vec3& newDiffuse) { diffuse = newDiffuse; }
void setSpecular(const glm::vec3& newSpecular) { specular = newSpecular; }
virtual void use(Shader& shader) {}
};
class DirectLight : public Light {
private:
glm::vec3 direction;
public:
DirectLight(const glm::vec3& direction, const glm::vec3& color, const glm::vec3& ambient, const glm::vec3& diffuse, const glm::vec3& specular)
: direction(direction), Light(color, ambient, diffuse, specular) {}
glm::vec3 getDirection() const
{
return direction;
}
void setDirection(const glm::vec3& newDirection)
{
direction = newDirection;
}
void use(Shader& shader) override
{
shader.setVec3("dirLight.direction", direction);
shader.setVec3("dirLight.color", getColor());
shader.setVec3("dirLight.ambient", getAmbient());
shader.setVec3("dirLight.diffuse", getDiffuse());
shader.setVec3("dirLight.specular", getSpecular());
}
};
class SpotLight : public Light {
private:
glm::vec3 position;
glm::vec3 direction;
float cutOff;
float outerCutOff;
float constant;
float linear;
float quadratic;
public:
SpotLight(const glm::vec3& position, const glm::vec3& direction,
float cutOff, float outerCutOff,
const glm::vec3& color, const glm::vec3& ambient,
const glm::vec3& diffuse, const glm::vec3& specular,
float constant, float linear, float quadratic)
: position(position), direction(direction), cutOff(cutOff), outerCutOff(outerCutOff),
Light(color, ambient, diffuse, specular), constant(constant), linear(linear), quadratic(quadratic) {}
glm::vec3 getPosition() const { return position; }
glm::vec3 getDirection() const { return direction; }
float getCutOff() const { return cutOff; }
float getOuterCutOff() const { return outerCutOff; }
float getConstant() const { return constant; }
float getLinear() const { return linear; }
float getQuadratic() const { return quadratic; }
void setPosition(const glm::vec3& newPosition) { position = newPosition; }
void setDirection(const glm::vec3& newDirection) { direction = newDirection; }
void setCutOff(float newCutOff) { cutOff = newCutOff; }
void setOuterCutOff(float newOuterCutOff) { outerCutOff = newOuterCutOff; }
void setConstant(float newConstant) { constant = newConstant; }
void setLinear(float newLinear) { linear = newLinear; }
void setQuadratic(float newQuadratic) { quadratic = newQuadratic; }
void use(Shader& shader) override
{
shader.setVec3("spotLight.position", position);
shader.setVec3("spotLight.direction", direction);
shader.setFloat("spotLight.cutOff", glm::cos(glm::radians(cutOff)));
shader.setFloat("spotLight.outerCutOff", glm::cos(glm::radians(outerCutOff)));
shader.setVec3("spotLight.color", getColor());
shader.setVec3("spotLight.ambient", getAmbient());
shader.setVec3("spotLight.diffuse", getDiffuse());
shader.setVec3("spotLight.specular", getSpecular());
shader.setFloat("spotLight.constant", constant);
shader.setFloat("spotLight.linear", linear);
shader.setFloat("spotLight.quadratic", quadratic);
}
};
class PointLight : public Light {
private:
glm::vec3 position;
float constant;
float linear;
float quadratic;
public:
PointLight(const glm::vec3& position, const glm::vec3& color,
const glm::vec3& ambient, const glm::vec3& diffuse, const glm::vec3& specular,
float constant, float linear, float quadratic)
: position(position), Light(color, ambient, diffuse, specular),
constant(constant), linear(linear), quadratic(quadratic) {}
glm::vec3 getPosition() const { return position; }
float getConstant() const { return constant; }
float getLinear() const { return linear; }
float getQuadratic() const { return quadratic; }
void setPosition(const glm::vec3& newPosition) { position = newPosition; }
void setConstant(float newConstant) { constant = newConstant; }
void setLinear(float newLinear) { linear = newLinear; }
void setQuadratic(float newQuadratic) { quadratic = newQuadratic; }
void use(Shader& shader, int index) const
{
shader.setVec3("pointLights[" + std::to_string(index) + "].position", position);
shader.setVec3("pointLights[" + std::to_string(index) + "].color", getColor());
shader.setVec3("pointLights[" + std::to_string(index) + "].ambient", getAmbient());
shader.setVec3("pointLights[" + std::to_string(index) + "].diffuse", getDiffuse());
shader.setVec3("pointLights[" + std::to_string(index) + "].specular", getSpecular());
shader.setFloat("pointLights[" + std::to_string(index) + "].constant", constant);
shader.setFloat("pointLights[" + std::to_string(index) + "].linear", linear);
shader.setFloat("pointLights[" + std::to_string(index) + "].quadratic", quadratic);
}
};
#endif

View file

@ -1,3 +1,6 @@
#ifndef OBJECT_HPP
#define OBJECT_HPP
#include <myEngine/model.hpp> #include <myEngine/model.hpp>
#include <glm/glm.hpp> #include <glm/glm.hpp>
@ -47,4 +50,6 @@ public:
shader.setMat4("model", modelMatrix); shader.setMat4("model", modelMatrix);
model.Draw(shader); model.Draw(shader);
} }
}; };
#endif

120
main.cpp
View file

@ -16,6 +16,7 @@
#include <myEngine/camera.hpp> #include <myEngine/camera.hpp>
#include <myEngine/model.hpp> #include <myEngine/model.hpp>
#include <myEngine/object.hpp> #include <myEngine/object.hpp>
#include <myEngine/lighting.hpp>
void framebuffer_size_callback(GLFWwindow* window, int width, int height); void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window); void processInput(GLFWwindow *window);
@ -85,10 +86,7 @@ int main()
ImGui_ImplOpenGL3_Init("#version 330 core"); ImGui_ImplOpenGL3_Init("#version 330 core");
// Shaders // Shaders
Shader ourShader("resources/shaders/vert.glsl", "resources/shaders/frag.glsl"); Shader light_shader("resources/shaders/vert.glsl", "resources/shaders/light_shader.glsl");
Shader directional_lightShader("resources/shaders/vert.glsl", "resources/shaders/directional_light.glsl");
Shader point_lightShader("resources/shaders/vert.glsl", "resources/shaders/point_light.glsl");
Shader spotlight_lightShader("resources/shaders/vert.glsl", "resources/shaders/spotlight_light.glsl");
Shader light_cubeShader("resources/shaders/vert.glsl", "resources/shaders/light_object.glsl"); Shader light_cubeShader("resources/shaders/vert.glsl", "resources/shaders/light_object.glsl");
// Models // Models
@ -101,6 +99,32 @@ int main()
Object object3(croissant, glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.1f, 0.1f, 0.1f), glm::vec3(0.0f, 0.0f, 0.0f)); Object object3(croissant, glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.1f, 0.1f, 0.1f), glm::vec3(0.0f, 0.0f, 0.0f));
Object light_cube(cube, glm::vec3(1.2f, 1.0f, 2.0f), glm::vec3(0.05f, 0.05f, 0.05f), glm::vec3(0.0f, 0.0f, 0.0f)); Object light_cube(cube, glm::vec3(1.2f, 1.0f, 2.0f), glm::vec3(0.05f, 0.05f, 0.05f), glm::vec3(0.0f, 0.0f, 0.0f));
// Lights
DirectLight directLight(glm::vec3(-0.2f, -1.0f, -0.3f),
glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.2f, 0.2f, 0.2f),
glm::vec3(0.5f, 0.5f, 0.5f),
glm::vec3(1.0f, 1.0f, 1.0f));
SpotLight spotLight(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 1.0f),
12.55f, 17.5f,
glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3(0.2f, 0.2f, 0.2f),
glm::vec3(0.5f, 0.5f, 0.5f), glm::vec3(1.0f, 1.0f, 1.0f),
1.0f, 0.09f,
0.032f);
std::vector<PointLight> pointLights;
pointLights.emplace_back(glm::vec3(1.2f, 1.0f, 2.0f),
glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.2f, 0.2f, 0.2f),
glm::vec3(0.5f, 0.5f, 0.5f),
glm::vec3(1.0f, 1.0f, 1.0f),
1.0f, 0.09f, 0.032f);
pointLights.emplace_back(glm::vec3(-1.2f, 1.0f, 2.0f),
glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(0.2f, 0.2f, 0.2f),
glm::vec3(0.5f, 0.5f, 0.5f),
glm::vec3(1.0f, 1.0f, 1.0f),
1.0f, 0.09f, 0.032f);
static float positionX = 0.0f; static float positionX = 0.0f;
static float positionY = 0.0f; static float positionY = 0.0f;
static float positionZ = 0.0f; static float positionZ = 0.0f;
@ -111,9 +135,6 @@ int main()
static float* light_color = new float[3]{1.0f, 1.0f, 1.0f}; static float* light_color = new float[3]{1.0f, 1.0f, 1.0f};
static float light_cutoff = 12.5f; static float light_cutoff = 12.5f;
static float light_outerCutoff = 17.5f; static float light_outerCutoff = 17.5f;
static float light_directionX = 0.0f;
static float light_directionY = 0.0f;
static float light_directionZ = -1.0f;
while(!glfwWindowShouldClose(window)) while(!glfwWindowShouldClose(window))
{ {
@ -139,7 +160,6 @@ int main()
ImGui::Begin("Settings"); ImGui::Begin("Settings");
ImGui::Text("FPS: %.2f", 1.0f / deltaTime); ImGui::Text("FPS: %.2f", 1.0f / deltaTime);
ImGui::Text("Camera Direction: (%.2f, %.2f, %.2f)", camera.Front.x, camera.Front.y, camera.Front.z);
ImGui::SliderFloat("Object 1 Position X", &positionX, -5.0f, 5.0f); ImGui::SliderFloat("Object 1 Position X", &positionX, -5.0f, 5.0f);
ImGui::SliderFloat("Object 1 Position Y", &positionY, -5.0f, 5.0f); ImGui::SliderFloat("Object 1 Position Y", &positionY, -5.0f, 5.0f);
ImGui::SliderFloat("Object 1 Position Z", &positionZ, -5.0f, 5.0f); ImGui::SliderFloat("Object 1 Position Z", &positionZ, -5.0f, 5.0f);
@ -149,79 +169,53 @@ int main()
ImGui::ColorEdit3("Light Cube Color", light_color); ImGui::ColorEdit3("Light Cube Color", light_color);
ImGui::SliderFloat("Light Cutoff", &light_cutoff, 0.0f, 90.0f); ImGui::SliderFloat("Light Cutoff", &light_cutoff, 0.0f, 90.0f);
ImGui::SliderFloat("Light Outer Cutoff", &light_outerCutoff, 0.0f, 90.0f); ImGui::SliderFloat("Light Outer Cutoff", &light_outerCutoff, 0.0f, 90.0f);
ImGui::SliderFloat("Light Direction X", &light_directionX, -1.0f, 1.0f);
ImGui::SliderFloat("Light Direction Y", &light_directionY, -1.0f, 1.0f);
ImGui::SliderFloat("Light Direction Z", &light_directionZ, -1.0f, 1.0f);
ImGui::End(); ImGui::End();
glm::mat4 view = camera.GetViewMatrix(); glm::mat4 view = camera.GetViewMatrix();
glm::mat4 projection = glm::perspective(glm::radians(45.0f), float(width) / float(height), 0.1f, 100.0f); glm::mat4 projection = glm::perspective(glm::radians(45.0f), float(width) / float(height), 0.1f, 100.0f);
// Bacis lighting light_shader.use();
ourShader.setVec3("viewPos", camera.Position); light_shader.setMat4("view", view);
ourShader.setVec3("light.position", 1.2f, 1.0f, 2.0f); light_shader.setVec3("viewPos", camera.Position);
ourShader.setVec3("light.color", 1.0f, 1.0f, 1.0f); light_shader.setMat4("projection", projection);
ourShader.setVec3("light.ambient", 0.2f, 0.2f, 0.2f);
ourShader.setVec3("light.diffuse", 0.5f, 0.5f, 0.5f);
ourShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
ourShader.setMat4("view", view);
ourShader.setMat4("projection", projection);
// Directional light // Directional light
directional_lightShader.setVec3("light.direction", -0.2f, -1.0f, -0.3f); directLight.use(light_shader);
directional_lightShader.setVec3("light.color", 1.0f, 1.0f, 1.0f);
directional_lightShader.setVec3("light.ambient", 0.2f, 0.2f, 0.2f); // Spotlight
directional_lightShader.setVec3("light.diffuse", 0.5f, 0.5f, 0.5f); spotLight.setPosition(camera.Position);
directional_lightShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f); spotLight.setDirection(camera.Front);
directional_lightShader.setMat4("view", view); spotLight.setCutOff(light_cutoff);
directional_lightShader.setMat4("projection", projection); spotLight.setOuterCutOff(light_outerCutoff);
spotLight.use(light_shader);
// Point light // Point light
point_lightShader.use(); light_shader.setInt("pointLightCount", static_cast<int>(pointLights.size()));
point_lightShader.setVec3("viewPos", camera.Position); pointLights[0].setPosition(glm::vec3(lightCubePositionX, lightCubePositionY, lightCubePositionZ));
point_lightShader.setVec3("light.position", lightCubePositionX, lightCubePositionY, lightCubePositionZ); pointLights[0].setColor(glm::vec3(light_color[0], light_color[1], light_color[2]));
point_lightShader.setVec3("light.color", light_color[0], light_color[1], light_color[2]); for (size_t i = 0; i < pointLights.size(); ++i)
point_lightShader.setVec3("light.ambient", 0.2f, 0.2f, 0.2f); {
point_lightShader.setVec3("light.diffuse", 0.5f, 0.5f, 0.5f); pointLights[i].use(light_shader, static_cast<int>(i));
point_lightShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f); }
point_lightShader.setFloat("light.constant", 1.0f);
point_lightShader.setFloat("light.linear", 0.09f);
point_lightShader.setFloat("light.quadratic", 0.032f);
point_lightShader.setMat4("view", view);
point_lightShader.setMat4("projection", projection);
// Spotlight light
spotlight_lightShader.use();
spotlight_lightShader.setVec3("viewPos", camera.Position);
spotlight_lightShader.setVec3("light.position", lightCubePositionX, lightCubePositionY, lightCubePositionZ);
spotlight_lightShader.setVec3("light.direction", light_directionX, light_directionY, light_directionZ);
spotlight_lightShader.setVec3("light.color", light_color[0], light_color[1], light_color[2]);
spotlight_lightShader.setVec3("light.ambient", 0.2f, 0.2f, 0.2f);
spotlight_lightShader.setVec3("light.diffuse", 0.5f, 0.5f, 0.5f);
spotlight_lightShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
spotlight_lightShader.setFloat("light.constant", 1.0f);
spotlight_lightShader.setFloat("light.linear", 0.09f);
spotlight_lightShader.setFloat("light.quadratic", 0.032f);
spotlight_lightShader.setFloat("light.cutOff", glm::cos(glm::radians(light_cutoff)));
spotlight_lightShader.setFloat("light.outerCutOff", glm::cos(glm::radians(light_outerCutoff)));
spotlight_lightShader.setMat4("view", view);
spotlight_lightShader.setMat4("projection", projection);
object1.setPosition(glm::vec3(positionX, positionY, positionZ)); object1.setPosition(glm::vec3(positionX, positionY, positionZ));
object1.Draw(spotlight_lightShader, deltaTime); object1.Draw(light_shader, deltaTime);
object2.setAcceleration(glm::vec3(0.0f, 0.001f, 0.0f)); object2.setAcceleration(glm::vec3(0.0f, 0.001f, 0.0f));
object2.Draw(spotlight_lightShader, deltaTime); object2.Draw(light_shader, deltaTime);
object3.setAcceleration(glm::vec3(0.0f, -0.001f, 0.0f)); object3.setAcceleration(glm::vec3(0.0f, -0.001f, 0.0f));
object3.Draw(spotlight_lightShader, deltaTime); object3.Draw(light_shader, deltaTime);
// Light cube shader // Light cube shader
light_cubeShader.use(); light_cubeShader.use();
light_cubeShader.setMat4("view", view); light_cubeShader.setMat4("view", view);
light_cubeShader.setMat4("projection", projection); light_cubeShader.setMat4("projection", projection);
light_cubeShader.setVec3("lightColor", light_color[0], light_color[1], light_color[2]);
light_cube.setPosition(glm::vec3(lightCubePositionX, lightCubePositionY, lightCubePositionZ)); for (size_t i = 0; i < pointLights.size(); ++i)
light_cube.Draw(light_cubeShader, deltaTime); {
light_cube.setPosition(pointLights[i].getPosition());
light_cubeShader.setVec3("lightColor", pointLights[i].getColor());
light_cube.Draw(light_cubeShader, deltaTime);
}
ImGui::Render(); ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

View file

@ -0,0 +1,153 @@
#version 330 core
out vec4 FragColor;
in vec3 Normal;
in vec2 TexCoords;
in vec3 FragPos;
struct DirLight {
vec3 direction;
vec3 color;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct PointLight {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
vec3 color;
float constant;
float linear;
float quadratic;
};
struct SpotLight {
vec3 position;
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
vec3 color;
float constant;
float linear;
float quadratic;
float cutOff;
float outerCutOff;
};
uniform sampler2D texture_diffuse1;
uniform vec3 viewPos;
uniform DirLight dirLight;
#define NR_POINT_LIGHTS 16
uniform PointLight pointLights[NR_POINT_LIGHTS];
uniform int pointLightCount;
uniform SpotLight spotLight;
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
// ambient
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * light.color;
// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(-light.direction);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * light.color;
// specular
float specularStrength = 0.5;
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * light.color;
return (ambient + diffuse + specular);
}
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
float distance = length(light.position - FragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
// ambient// ambient
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * light.color;
// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * light.color;
// specular
float specularStrength = 0.5;
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * light.color;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return (ambient + diffuse + specular);
}
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
// Calculate the direction of the light
vec3 lightDir = normalize(light.position - FragPos);
// Calculate the angle between the light direction and the spotlight direction
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cutOff - light.outerCutOff;
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
float distance = length(light.position - FragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
// ambient
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * light.color;
// diffuse
vec3 norm = normalize(Normal);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * light.color;
// specular
float specularStrength = 0.5;
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * light.color;
// Apply attenuation and intensity
ambient *= attenuation;
diffuse *= attenuation * intensity;
specular *= attenuation * intensity;
return (ambient + diffuse + specular);
}
void main()
{
// properties
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
// phase 1: Directional lighting
vec3 result = CalcDirLight(dirLight, norm, viewDir);
// phase 2: Point lights
for(int i = 0; i < pointLightCount; i++)
result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);
// phase 3: Spot light
result += CalcSpotLight(spotLight, norm, FragPos, viewDir);
FragColor = texture(texture_diffuse1, TexCoords) * vec4(result, 1.0);
}