From de96aa41365832f5b5c4a705c60c865ca4b68dd3 Mon Sep 17 00:00:00 2001 From: Nigel Date: Wed, 16 Feb 2022 21:06:40 +0100 Subject: [PATCH] Added multiple lights to the scene Both a directional and four points lights are used in this scene. Fixed a memory leak caused by the vertex Array buffer of the lights never being deleted --- shader.fs | 106 ++++++++++++++++++++++++++++----------------------- src/main.cpp | 91 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 136 insertions(+), 61 deletions(-) diff --git a/shader.fs b/shader.fs index 52fd39c..19e2d9b 100644 --- a/shader.fs +++ b/shader.fs @@ -11,79 +11,89 @@ struct Material { float shininess; }; -struct Light{ - vec3 position; - - vec3 direction; // neccessary when using directional lights or spotlights. - float cutoff; - float outerCutOff; +struct DirLight { + vec3 direction; vec3 ambient; vec3 diffuse; vec3 specular; - // lets create point lights +}; + +struct PointLight{ + vec3 position; + float constant; float linear; float quadratic; - + vec3 ambient; + vec3 diffuse; + vec3 specular; }; +#define NR_POINT_LIGHTS 4 -uniform Light light; +uniform PointLight PointLights[NR_POINT_LIGHTS]; +uniform DirLight dirlight; uniform Material material; uniform vec3 viewPos; +vec3 CalcDirLight(DirLight light , vec3 normal , vec3 viewDir) +{ + vec3 lightDir = normalize(-light.direction); + float diff = max(dot(normal,lightDir), 0.0); + vec3 reflectDir = reflect(-lightDir, normal); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + + vec3 ambient = light.ambient * vec3 (texture(material.diffuse, TexCoords)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); + + return (ambient + diffuse + specular); +} + +vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir) +{ + vec3 lightDir = normalize(light.position - fragPos ); + + float diff = max(dot(normal, lightDir), 0.0); + + vec3 reflectDir = reflect(-lightDir, normal); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + + float distance = length(light.position - fragPos); + float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance *distance)); + + vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); + vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); + vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); + + ambient *= attenuation; + diffuse *= attenuation; + specular *= attenuation; + + return (ambient + diffuse + specular); + +} + void main() { - - // ambient lighting calculation - vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); - - // diffuse lighting calculation vec3 norm = normalize(Normal); - vec3 lightDir = normalize(light.position - FragPos); - - float diff = max(dot(norm, lightDir), 0.0); - vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords)); - - // specular lighting vec3 viewDir = normalize(viewPos - FragPos); - vec3 reflectDir = reflect(-lightDir, norm); - - float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); - vec3 specular = light.specular * spec * vec3( texture(material.specular, TexCoords)); + // Fase 1 : Directional lighting + vec3 result = CalcDirLight(dirlight, norm, viewDir); - - float theta = dot(lightDir, normalize(-light.direction)); - float epsilon = light.cutoff - light.outerCutOff; - float intensity = clamp((theta - light.outerCutOff)/ epsilon, 0.0, 1.0); - - - diffuse *= intensity; - specular *= intensity; - - - // calculate the attenuation - float distance = length(light.position - FragPos); - float attenuation = 1.0/ (light.constant + light.linear * distance + light.quadratic * (distance*distance)); - - - - ambient *= attenuation; - diffuse *= attenuation; - specular *= attenuation; - - - - vec3 result = ambient + diffuse + specular ; - + // Fase 2 : Point lights + for( int i = 0; i < NR_POINT_LIGHTS; i++){ + result += CalcPointLight(PointLights[i], norm, FragPos, viewDir); + } + FragColor = vec4(result, 1.0); } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 1727ebd..5ba48a6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -149,6 +149,13 @@ glm::vec3 cubePositions[] = { glm::vec3(-1.3f, 1.0f, -1.5f) }; +glm::vec3 lightPositions[] = { + glm::vec3( 0.7f, 0.2f, 2.0f), + glm::vec3( 2.3f, -3.3f, -4.0f), + glm::vec3(-4.0f, 2.0f, -12.0f), + glm::vec3( 0.0f, 0.0f, -3.0f) +}; + unsigned int VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); @@ -257,21 +264,71 @@ while(!glfwWindowShouldClose(window)) shader.setFloat("material.shininess", 32.0f); +/* +Directional light + vec3 direction; - shader.setVec3("light.position", camera.Position); - shader.setVec3("light.direction", camera.Front); - shader.setFloat("light.cutoff", glm::cos(glm::radians(12.5f))); - shader.setFloat("light.outerCutOff", glm::cos(glm::radians(17.5f))); + vec3 ambient; + vec3 diffuse; + vec3 specular; +*/ - shader.setVec3("light.ambient", glm::vec3(0.2f, 0.2f, 0.2f)); - shader.setVec3("light.diffuse", glm::vec3(0.5f, 0.5f, 0.5f)); - shader.setVec3("light.specular", glm::vec3(1.0f, 1.0f, 1.0f)); + shader.setVec3("dirlight.direction", glm::vec3(1.0f,0.0f, 2.0f)); + + + shader.setVec3("dirlight.ambient", glm::vec3(0.2f, 0.2f, 0.2f)); + shader.setVec3("dirlight.diffuse", glm::vec3(0.5f, 0.5f, 0.5f)); + shader.setVec3("dirlight.specular", glm::vec3(1.0f, 1.0f, 1.0f)); + + + + +/* + Point Lights; +*/ + + + + shader.setVec3("PointLights[0].position", glm::vec3( 0.7f, 0.2f, 2.0f)); + shader.setVec3("PointLights[1].position", glm::vec3( 2.3f, -3.3f, -4.0f)); + shader.setVec3("PointLights[2].position", glm::vec3(-4.0f, 2.0f, -12.0f)); + shader.setVec3("PointLights[3].position", glm::vec3( 0.0f, 0.0f, -3.0f)); + shader.setVec3("PointLights[0].ambient", glm::vec3(0.2f, 0.2f, 0.2f)); + shader.setVec3("PointLights[0].diffuse", glm::vec3(0.5f, 0.5f, 0.5f)); + shader.setVec3("PointLights[0].specular", glm::vec3(1.0f, 1.0f, 1.0f)); - shader.setFloat("light.constant", 1.0f); - shader.setFloat("light.linear", 0.09f); - shader.setFloat("light.quadratic", 0.032f); + shader.setVec3("PointLights[1].ambient", glm::vec3(0.2f, 0.2f, 0.2f)); + shader.setVec3("PointLights[1].diffuse", glm::vec3(0.5f, 0.5f, 0.5f)); + shader.setVec3("PointLights[1].specular", glm::vec3(1.0f, 1.0f, 1.0f)); + + shader.setVec3("PointLights[2].ambient", glm::vec3(0.2f, 0.2f, 0.2f)); + shader.setVec3("PointLights[2].diffuse", glm::vec3(0.5f, 0.5f, 0.5f)); + shader.setVec3("PointLights[2].specular", glm::vec3(1.0f, 1.0f, 1.0f)); + + shader.setVec3("PointLights[3].ambient", glm::vec3(0.2f, 0.2f, 0.2f)); + shader.setVec3("PointLights[3].diffuse", glm::vec3(0.5f, 0.5f, 0.5f)); + shader.setVec3("PointLights[3].specular", glm::vec3(1.0f, 1.0f, 1.0f)); + + + + + shader.setFloat("PointLights[0].constant", 1.0f); + shader.setFloat("PointLights[1].constant", 1.0f); + shader.setFloat("PointLights[2].constant", 1.0f); + shader.setFloat("PointLights[3].constant", 1.0f); + + shader.setFloat("PointLights[0].linear", 0.09f); + shader.setFloat("PointLights[1].linear", 0.09f); + shader.setFloat("PointLights[2].linear", 0.09f); + shader.setFloat("PointLights[3].linear", 0.09f); + + + shader.setFloat("PointLights[0].quadratic", 0.032f); + shader.setFloat("PointLights[1].quadratic", 0.032f); + shader.setFloat("PointLights[2].quadratic", 0.032f); + shader.setFloat("PointLights[3].quadratic", 0.032f); shader.setVec3("viewPos", camera.Position); @@ -304,6 +361,7 @@ while(!glfwWindowShouldClose(window)) + // draw lights lightshader.use(); lightshader.setMat4("view", view); @@ -313,17 +371,24 @@ while(!glfwWindowShouldClose(window)) model = glm::translate(model, lightpos); model = glm::scale(model, glm::vec3(0.2f)); - lightshader.setMat4("model", model); - glBindVertexArray(lightVAO); - glDrawArrays(GL_TRIANGLES, 0, 36); + for ( int i = 0; i < 4 ; i ++){ + + model = glm::translate(model, lightPositions[i]); + lightshader.setMat4("model", model); + glBindVertexArray(lightVAO); + glDrawArrays(GL_TRIANGLES, 0, 36); + + } + glfwSwapBuffers(window); glfwPollEvents(); } glDeleteVertexArrays(1, &VAO); +glDeleteVertexArrays(1, &lightVAO); glDeleteBuffers(1, &VBO); glfwTerminate();