From abf9e8fa7cce928cf18a55d59b1046b7e01d70e3 Mon Sep 17 00:00:00 2001 From: Austin Morlan Date: Wed, 19 Sep 2018 19:15:53 -0700 Subject: [PATCH] Add specular lighting --- include/light.h | 3 +- include/vec.h | 12 ++++++++ src/engine.cpp | 18 +++++------ src/light.cpp | 80 +++++++++++++++++++++++++++++++++---------------- 4 files changed, 78 insertions(+), 35 deletions(-) diff --git a/include/light.h b/include/light.h index 8879666..c13c17e 100644 --- a/include/light.h +++ b/include/light.h @@ -1,6 +1,7 @@ #ifndef LIGHT_H +#include "camera.h" #include "color.h" #include "geometry.h" #include "point.h" @@ -18,7 +19,7 @@ struct Light // PUBLIC FUNCTIONS -ColorF32 ComputeLight(Vertex &vert, Material &material, Light &light); +ColorF32 ComputeLight(Vertex &vert, Material &material, Light &light, Camera &camera); #define LIGHT_H diff --git a/include/vec.h b/include/vec.h index 6213cdd..c8603a0 100644 --- a/include/vec.h +++ b/include/vec.h @@ -32,6 +32,18 @@ inline Vector operator-(Vector const &v) return result; } +// v1 - v2 +inline Vector operator-(Vector const &v1, Vector const &v2) +{ + Vector result; + + result.x = v1.x - v2.x; + result.y = v1.y - v2.y; + result.z = v1.z - v2.z; + + return result; +} + // v1 + v2 inline Vector operator+(Vector const &v1, Vector const &v2) { diff --git a/src/engine.cpp b/src/engine.cpp index a99e76e..0cf0e7e 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -64,8 +64,8 @@ int EngineInit(char *objFilename, char *mtlFilename) // Mesh configuration - mesh.position.z = 125; - mesh.position.y = -125; + mesh.position.z = 175; + mesh.position.y = -175; mesh.scale = 1.0f; @@ -152,29 +152,29 @@ static void CheckInputs(uint32_t input) if (CHECK_BIT(input, ROTATE_X_POS)) { - mesh.rotation.x += .10; + mesh.position.x += 10; } else if (CHECK_BIT(input, ROTATE_X_NEG)) { - mesh.rotation.x -= .10; + mesh.position.x -= 10; } if (CHECK_BIT(input, ROTATE_Y_POS)) { - mesh.rotation.y += .10; + mesh.position.y += 10; } else if (CHECK_BIT(input, ROTATE_Y_NEG)) { - mesh.rotation.y -= .10; + mesh.position.y -= 10; } if (CHECK_BIT(input, ROTATE_Z_POS)) { - mesh.rotation.z += .10; + mesh.position.z += 10; } else if (CHECK_BIT(input, ROTATE_Z_NEG)) { - mesh.rotation.z -= .10; + mesh.position.z -= 10; } if (CHECK_BIT(input, SCALE_UP)) @@ -338,7 +338,7 @@ static void LightMesh(void) { Vertex &vert = verts.data[face.vertIndex[i]]; - vert.color = ComputeLight(vert, material, light); + vert.color = ComputeLight(vert, material, light, camera); } } } diff --git a/src/light.cpp b/src/light.cpp index afb7fe4..78e7367 100644 --- a/src/light.cpp +++ b/src/light.cpp @@ -1,45 +1,49 @@ +#include "camera.h" #include "color.h" #include "light.h" // PRIVATE PROTOTYPES static ColorF32 ComputeAmbientLight( - ColorF32 surfaceReflectivity, ColorF32 lightIntensity); + Material &material, ColorF32 &intensity); static ColorF32 ComputeDiffuseLight( - ColorF32 surfaceReflectivity, ColorF32 lightIntensity, - Point &vertPosition, Vector &vertNormal, - Point &lightPosition); + Material &material, ColorF32 &intensity, Vertex &vert, Light &light); + +static ColorF32 ComputeSpecularLight( + Material &material, ColorF32 &intensity, Vertex &vert, Light &light, + Camera &camera); // PUBLIC FUNCTIONS -ColorF32 ComputeLight(Vertex &vert, Material &material, Light &light) +ColorF32 ComputeLight( + Vertex &vert, Material &material, Light &light, Camera &camera) { // Distance from light to vertex Vector direction = light.position - vert.point; float distance = VectorLength(direction); - // Intensity is a function of the falloff factors and the distance + // Point light intensity is a function of the falloff factors and the distance ColorF32 intensity = (light.intensity * light.color) / (light.falloffConstant + light.falloffLinear * distance); // Compute ambient light - ColorF32 ambientLight = ComputeAmbientLight( - material.ambient, intensity); + ColorF32 ambientLight = ComputeAmbientLight(material, intensity); // Compute diffuse light - ColorF32 diffuseLight = ComputeDiffuseLight( - material.diffuse, intensity, - vert.point, vert.normal, - light.position); + ColorF32 diffuseLight = ComputeDiffuseLight(material, intensity, vert, light); + + + // Compute specular light + ColorF32 specularLight = ComputeSpecularLight(material, intensity, vert, light, camera); // Total light is sum of all lights - ColorF32 result = ambientLight + diffuseLight; + ColorF32 result = ambientLight + diffuseLight + specularLight; return result; @@ -48,29 +52,55 @@ ColorF32 ComputeLight(Vertex &vert, Material &material, Light &light) // PRIVATE FUNCTIONS static ColorF32 ComputeAmbientLight( - ColorF32 surfaceReflectivity, ColorF32 lightIntensity) + Material &material, ColorF32 &intensity) { - ColorF32 result; - - - result = surfaceReflectivity * lightIntensity; + // light = Kd * I + ColorF32 result = material.ambient * intensity; return result; } static ColorF32 ComputeDiffuseLight( - ColorF32 surfaceReflectivity, ColorF32 lightIntensity, - Point &vertPosition, Vector &vertNormal, - Point &lightPosition) + Material &material, ColorF32 &intensity, Vertex &vert, Light &light) { - // Light is a function of the position of the light source and the surface - Vector direction = lightPosition - vertPosition; + // Vector from the light to the vertex + Vector direction = light.position - vert.point; VectorNormalize(direction); + float normalDotDirection = VectorDot(vert.normal, direction); - float dot = VectorDot(vertNormal, direction); - ColorF32 result = surfaceReflectivity * lightIntensity * dot; + // light = Kr * I * n.d + ColorF32 result = material.diffuse * intensity * normalDotDirection; + + + return result; +} + +static ColorF32 ComputeSpecularLight( + Material &material, ColorF32 &intensity, Vertex &vert, Light &light, + Camera &camera) +{ + // Vector from the camera to the vertex + Vector view = camera.position - vert.point; + VectorNormalize(view); + + + // Vector from the light to the vertex + Vector direction = light.position - vert.point; + VectorNormalize(direction); + + + // Reflection vector of the light vector across the vertex normal + float normalDotDirection = VectorDot(vert.normal, direction); + Vector reflection = (2.0f * normalDotDirection * vert.normal) - direction; + float reflectDotView = MAX(VectorDot(reflection, view), 0.0f); + + + // light = Ks * I * (r.v)^sp + ColorF32 result = + material.specular * intensity * powf(reflectDotView, material.specularExp); + return result; }