From 45f4f469d082e6cfa9acdc73b5f8ad029beca701 Mon Sep 17 00:00:00 2001 From: Joey de Vries Date: Sun, 17 May 2020 18:04:36 +0200 Subject: [PATCH] Add Basic Lighting exercises to repo. --- .../basic_lighting_exercise1.cpp | 30 ++++++++ .../basic_lighting_exercise2.cpp | 59 +++++++++++++++ .../basic_lighting_exercise3.cpp | 73 +++++++++++++++++++ 3 files changed, 162 insertions(+) create mode 100644 src/2.lighting/2.3.basic_lighting_exercise1/basic_lighting_exercise1.cpp create mode 100644 src/2.lighting/2.4.basic_lighting_exercise2/basic_lighting_exercise2.cpp create mode 100644 src/2.lighting/2.5.basic_lighting_exercise3/basic_lighting_exercise3.cpp diff --git a/src/2.lighting/2.3.basic_lighting_exercise1/basic_lighting_exercise1.cpp b/src/2.lighting/2.3.basic_lighting_exercise1/basic_lighting_exercise1.cpp new file mode 100644 index 0000000..3ebe458 --- /dev/null +++ b/src/2.lighting/2.3.basic_lighting_exercise1/basic_lighting_exercise1.cpp @@ -0,0 +1,30 @@ +int main() +{ + [...] + // render loop + while(!glfwWindowShouldClose(window)) + { + // per-frame time logic + float currentFrame = glfwGetTime(); + deltaTime = currentFrame - lastFrame; + lastFrame = currentFrame; + + // input + processInput(window); + + // clear the colorbuffer + glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // change the light's position values over time (can be done anywhere in the render loop actually, but try to do it at least before using the light source positions) + lightPos.x = 1.0f + sin(glfwGetTime()) * 2.0f; + lightPos.y = sin(glfwGetTime() / 2.0f) * 1.0f; + + // set uniforms, draw objects + [...] + + // glfw: swap buffers and poll IO events + glfwSwapBuffers(window); + glfwPollEvents(); + } +} \ No newline at end of file diff --git a/src/2.lighting/2.4.basic_lighting_exercise2/basic_lighting_exercise2.cpp b/src/2.lighting/2.4.basic_lighting_exercise2/basic_lighting_exercise2.cpp new file mode 100644 index 0000000..4850de8 --- /dev/null +++ b/src/2.lighting/2.4.basic_lighting_exercise2/basic_lighting_exercise2.cpp @@ -0,0 +1,59 @@ +// Vertex shader: +// ================ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; + +out vec3 FragPos; +out vec3 Normal; +out vec3 LightPos; + +uniform vec3 lightPos; // we now define the uniform in the vertex shader and pass the 'view space' lightpos to the fragment shader. lightPos is currently in world space. + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + gl_Position = projection * view * model * vec4(aPos, 1.0); + FragPos = vec3(view * model * vec4(aPos, 1.0)); + Normal = mat3(transpose(inverse(view * model))) * aNormal; + LightPos = vec3(view * vec4(lightPos, 1.0)); // Transform world-space light position to view-space light position +} + + +// Fragment shader: +// ================ +#version 330 core +out vec4 FragColor; + +in vec3 FragPos; +in vec3 Normal; +in vec3 LightPos; // extra in variable, since we need the light position in view space we calculate this in the vertex shader + +uniform vec3 lightColor; +uniform vec3 objectColor; + +void main() +{ + // ambient + float ambientStrength = 0.1; + vec3 ambient = ambientStrength * lightColor; + + // diffuse + vec3 norm = normalize(Normal); + vec3 lightDir = normalize(LightPos - FragPos); + float diff = max(dot(norm, lightDir), 0.0); + vec3 diffuse = diff * lightColor; + + // specular + float specularStrength = 0.5; + vec3 viewDir = normalize(-FragPos); // the viewer is always at (0,0,0) in view-space, so viewDir is (0,0,0) - Position => -Position + vec3 reflectDir = reflect(-lightDir, norm); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); + vec3 specular = specularStrength * spec * lightColor; + + vec3 result = (ambient + diffuse + specular) * objectColor; + FragColor = vec4(result, 1.0); +} \ No newline at end of file diff --git a/src/2.lighting/2.5.basic_lighting_exercise3/basic_lighting_exercise3.cpp b/src/2.lighting/2.5.basic_lighting_exercise3/basic_lighting_exercise3.cpp new file mode 100644 index 0000000..340dfe9 --- /dev/null +++ b/src/2.lighting/2.5.basic_lighting_exercise3/basic_lighting_exercise3.cpp @@ -0,0 +1,73 @@ +// Vertex shader: +// ================ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; + +out vec3 LightingColor; // resulting color from lighting calculations + +uniform vec3 lightPos; +uniform vec3 viewPos; +uniform vec3 lightColor; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() +{ + gl_Position = projection * view * model * vec4(aPos, 1.0); + + // gouraud shading + // ------------------------ + vec3 Position = vec3(model * vec4(aPos, 1.0)); + vec3 Normal = mat3(transpose(inverse(model))) * aNormal; + + // ambient + float ambientStrength = 0.1; + vec3 ambient = ambientStrength * lightColor; + + // diffuse + vec3 norm = normalize(Normal); + vec3 lightDir = normalize(lightPos - Position); + float diff = max(dot(norm, lightDir), 0.0); + vec3 diffuse = diff * lightColor; + + // specular + float specularStrength = 1.0; // this is set higher to better show the effect of Gouraud shading + vec3 viewDir = normalize(viewPos - Position); + vec3 reflectDir = reflect(-lightDir, norm); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); + vec3 specular = specularStrength * spec * lightColor; + + LightingColor = ambient + diffuse + specular; +} + + +// Fragment shader: +// ================ +#version 330 core +out vec4 FragColor; + +in vec3 LightingColor; + +uniform vec3 objectColor; + +void main() +{ + FragColor = vec4(LightingColor * objectColor, 1.0); +} + + +/* +So what do we see? +You can see (for yourself or in the provided image) the clear distinction of the two triangles at the front of the +cube. This 'stripe' is visible because of fragment interpolation. From the example image we can see that the top-right +vertex of the cube's front face is lit with specular highlights. Since the top-right vertex of the bottom-right triangle is +lit and the other 2 vertices of the triangle are not, the bright values interpolates to the other 2 vertices. The same +happens for the upper-left triangle. Since the intermediate fragment colors are not directly from the light source +but are the result of interpolation, the lighting is incorrect at the intermediate fragments and the top-left and +bottom-right triangle collide in their brightness resulting in a visible stripe between both triangles. + +This effect will become more apparent when using more complicated shapes. +*/ \ No newline at end of file