From b3991a465121d66c79b6dc62a88d7e2abea0c4ca Mon Sep 17 00:00:00 2001 From: Austin Morlan Date: Tue, 18 Sep 2018 20:02:12 -0700 Subject: [PATCH] Modify lighting to use a point light --- Makefile | 2 +- include/color.h | 85 ++++++++++++++++++++++++++++++++++++------------ include/engine.h | 2 +- include/light.h | 42 +++++------------------- src/engine.cpp | 48 +++++++++++++-------------- src/geometry.cpp | 7 +++- src/light.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 183 insertions(+), 81 deletions(-) create mode 100644 src/light.cpp diff --git a/Makefile b/Makefile index b37f383..b3adeb4 100644 --- a/Makefile +++ b/Makefile @@ -44,7 +44,7 @@ _HEADERS = camera.h color.h engine.h geometry.h light.h loader.h platform.h poin transform.h util.h vec.h HEADERS = $(patsubst %,$(INCLUDE_DIR)/%,$(_HEADERS)) -_OBJS = engine.o geometry.o loader.o main.o platform.o transform.o +_OBJS = engine.o geometry.o light.o loader.o main.o platform.o transform.o OBJS = $(patsubst %,$(BUILD_DIR)/%,$(_OBJS)) $(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp $(HEADERS) diff --git a/include/color.h b/include/color.h index 5e3a958..70cf388 100644 --- a/include/color.h +++ b/include/color.h @@ -20,18 +20,6 @@ struct ColorU32 struct ColorF32 { float b, g, r, a; - - static inline ColorU32 ConvertToU32(ColorF32 c) - { - ColorU32 result; - - result.b = (uint8_t)(c.b * 255); - result.g = (uint8_t)(c.g * 255); - result.r = (uint8_t)(c.r * 255); - result.a = (uint8_t)(c.a * 255); - - return result; - } }; @@ -41,10 +29,10 @@ inline ColorF32 operator+(ColorF32 c1, ColorF32 c2) { ColorF32 result; - result.b = MIN((c1.b + c2.b), 1.0f); - result.g = MIN((c1.g + c2.g), 1.0f); - result.r = MIN((c1.r + c2.r), 1.0f); - result.a = MIN((c1.a + c2.a), 1.0f); + result.b = c1.b + c2.b; + result.g = c1.g + c2.g; + result.r = c1.r + c2.r; + result.a = c1.a + c2.a; return result; } @@ -54,7 +42,7 @@ inline ColorF32 &operator+=(ColorF32 &c1, ColorF32 c2) { c1 = c1 + c2; - return(c1); + return c1; } // c * f @@ -62,10 +50,10 @@ inline ColorF32 operator*(ColorF32 c, float f) { ColorF32 result; - result.b = MIN((f * c.b), 1.0f); - result.g = MIN((f * c.g), 1.0f); - result.r = MIN((f * c.r), 1.0f); - result.a = MIN((f * c.a), 1.0f); + result.b = f * c.b; + result.g = f * c.g; + result.r = f * c.r; + result.a = f * c.a; return result; } @@ -80,6 +68,61 @@ inline ColorF32 operator*(float f, ColorF32 c) return result; } +// c1 * c2 +inline ColorF32 operator*(ColorF32 c1, ColorF32 c2) +{ + ColorF32 result; + + result.b = c1.b * c2.b; + result.g = c1.g * c2.g; + result.r = c1.r * c2.r; + result.a = c1.a * c2.a; + + return result; +} + +// c / f +inline ColorF32 operator/(ColorF32 c, float f) +{ + ColorF32 result; + + float invF = 1.0f / f; + + result.b = c.b * invF; + result.g = c.g * invF; + result.r = c.r * invF; + result.a = c.a * invF; + + return result; +} + +// c /= f +inline ColorF32 &operator/=(ColorF32 &c, float f) +{ + c = c / f; + + return c; +} + + +inline void ScaleColor(ColorF32 &c) +{ + float blue = MAX(c.b, 0.0f); + float green = MAX(c.g, 0.0f); + float red = MAX(c.r, 0.0f); + float alpha = MAX(c.a, 0.0f); + float max = MAX(MAX(MAX(blue,green),red),1.0f); + + ColorF32 scaled = {blue, green, red, alpha}; + scaled /= max; + + c.b = scaled.b; + c.g = scaled.g; + c.r = scaled.r; + c.a = scaled.a; +} + + #define COLOR_H #endif diff --git a/include/engine.h b/include/engine.h index cd6ddae..9bea429 100644 --- a/include/engine.h +++ b/include/engine.h @@ -15,7 +15,7 @@ // GEOMETRY CONFIGURATION #define FACE_LIMIT (30000) -#define MATERIAL_LIMIT (10) +#define MATERIAL_LIMIT (5) #define TEXTURE_SIZE_LIMIT (1024) #define VERTEX_LIMIT (20000) diff --git a/include/light.h b/include/light.h index c6adea1..8879666 100644 --- a/include/light.h +++ b/include/light.h @@ -2,47 +2,23 @@ #include "color.h" -#include "vec.h" -#include +#include "geometry.h" +#include "point.h" // STRUCTURES -struct LightAmbient +struct Light { - inline ColorF32 ComputeColor(ColorF32 reflectivity) - { - ColorF32 result; - - result = reflectivity * intensity; - - return result; - } - + Point position; + ColorF32 color; float intensity; + float falloffConstant; + float falloffLinear; }; -struct LightDiffuse -{ - inline ColorF32 ComputeColor(ColorF32 reflectivity, Vector normal) - { - ColorF32 result; - float dot = Vector::Dot(normal, direction); - - result = reflectivity * intensity * dot; - - return result; - } - - float intensity; - Vector direction; -}; - -struct LightList -{ - LightAmbient ambient; - LightDiffuse diffuse; -}; +// PUBLIC FUNCTIONS +ColorF32 ComputeLight(Vertex &vert, Material &material, Light &light); #define LIGHT_H diff --git a/src/engine.cpp b/src/engine.cpp index 6420008..cb19ae6 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -15,7 +15,7 @@ // GLOBALS static Mesh mesh; static Camera camera; -static LightList lights; +static Light light; static VertexList localVerts; static VertexList transVerts; static FaceList localFaces; @@ -33,7 +33,7 @@ static void ComputeNormals(void); static void ClearDepthBuffer(Engine_Buffer &buffer); static void TransformToClipSpace(void); static void TransformToScreenSpace(void); -static void ComputeLighting(void); +static void LightMesh(void); // PUBLIC FUNCTIONS @@ -68,15 +68,17 @@ int Engine_Init(char *objFilename, char *mtlFilename) // Mesh configuration - mesh.position.z = 50; - mesh.position.y = -50; + mesh.position.z = 125; + mesh.position.y = -125; mesh.scale = 1.0f; // Light configuration - lights.ambient.intensity = 1.0f; - lights.diffuse.intensity = 1.0f; - lights.diffuse.direction = Vector(1.0f, 1.0f, 1.0f); + light.position = Point(-100.0f, 200.0f, 0.0f); + light.color = {1.0f, 1.0f, 1.0f, 1.0f}; + light.intensity = 2.0f; + light.falloffConstant = 1.0f; + light.falloffLinear = 0.001f; // Transformation matrices that do not change @@ -106,7 +108,7 @@ void Engine_Render(Engine_Buffer &buffer, uint32_t input) // Light vertices and/or faces - ComputeLighting(); + LightMesh(); // Transform vertices to screen space @@ -127,29 +129,29 @@ static void CheckInputs(uint32_t input) { if (CHECK_BIT(input, TRANSLATE_X_POS)) { - mesh.position.x += 10; + light.position.x += 10; } else if (CHECK_BIT(input, TRANSLATE_X_NEG)) { - mesh.position.x -= 10; + light.position.x -= 10; } if (CHECK_BIT(input, TRANSLATE_Z_POS)) { - mesh.position.z += 10; + light.position.z += 10; } else if (CHECK_BIT(input, TRANSLATE_Z_NEG)) { - mesh.position.z -= 10; + light.position.z -= 10; } if (CHECK_BIT(input, TRANSLATE_Y_POS)) { - mesh.position.y += 10; + light.position.y += 10; } else if (CHECK_BIT(input, TRANSLATE_Y_NEG)) { - mesh.position.y -= 10; + light.position.y -= 10; } if (CHECK_BIT(input, ROTATE_X_POS)) @@ -181,11 +183,15 @@ static void CheckInputs(uint32_t input) if (CHECK_BIT(input, SCALE_UP)) { - mesh.scale += 0.1f; + light.color.b = 0.0f; + light.color.g = 0.0f; + light.color.r = 1.0f; } else if (CHECK_BIT(input, SCALE_DOWN)) { - mesh.scale -= 0.1f; + light.color.b = 1.0f; + light.color.g = 1.0f; + light.color.r = 1.0f; } } @@ -265,25 +271,19 @@ static void TransformToScreenSpace(void) } } -static void ComputeLighting(void) +static void LightMesh(void) { for (size_t f = 0; f < transFaces.size; ++f) { Face &face = transFaces.data[f]; Material &material = materials.data[face.materialIndex]; - // TODO: Fix weird lighting - material.ambient = {1.0,1.0,1.0,1.0}; - material.diffuse = {0.5,0.5,0.5,0.5}; - // Gouraud shading for (int i = 0; i < 3; ++i) { Vertex &vert = transVerts.data[face.vertIndex[i]]; - vert.color = - lights.ambient.ComputeColor(material.ambient) - + lights.diffuse.ComputeColor(material.diffuse, vert.normal); + vert.color = ComputeLight(vert, material, light); } } } diff --git a/src/geometry.cpp b/src/geometry.cpp index a1fbc64..5bcc193 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -187,11 +187,16 @@ void RenderMesh( + (barycenter[1] * c1) + (barycenter[2] * c2); + + // Ensure no color channel exceeds 1.0 + ScaleColor(shading); + + + // Light the texture color.b *= shading.b; color.g *= shading.g; color.r *= shading.r; - // Interpolate 1/z for the z-buffer float zInv = 1.0f / diff --git a/src/light.cpp b/src/light.cpp new file mode 100644 index 0000000..a19ee1f --- /dev/null +++ b/src/light.cpp @@ -0,0 +1,78 @@ +#include "color.h" +#include "light.h" + + +// PRIVATE PROTOTYPES +static ColorF32 ComputeAmbientLight( + ColorF32 surfaceReflectivity, ColorF32 lightIntensity); + +static ColorF32 ComputeDiffuseLight( + ColorF32 surfaceReflectivity, ColorF32 lightIntensity, + Point &vertPosition, Vector &vertNormal, + Point &lightPosition); + + +// PUBLIC FUNCTIONS +ColorF32 ComputeLight(Vertex &vert, Material &material, Light &light) +{ + // Distance from light to vertex + Vector d = light.position - vert.point; + float distance = d.Length(); + + + // 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); + + + // Compute diffuse light + ColorF32 diffuseLight = ComputeDiffuseLight( + material.diffuse, intensity, + vert.point, vert.normal, + light.position); + + + // Total light is sum of all lights + ColorF32 result = ambientLight + diffuseLight; + + + return result; +} + + +// PRIVATE FUNCTIONS +static ColorF32 ComputeAmbientLight( + ColorF32 surfaceReflectivity, ColorF32 lightIntensity) +{ + ColorF32 result; + + + result = surfaceReflectivity * lightIntensity; + + + return result; +} + +static ColorF32 ComputeDiffuseLight( + ColorF32 surfaceReflectivity, ColorF32 lightIntensity, + Point &vertPosition, Vector &vertNormal, + Point &lightPosition) +{ + // Light is a function of the position of the light source and the surface + Vector direction = lightPosition - vertPosition; + direction.Normalize(); + + float dot = Vector::Dot(vertNormal, direction); + + ColorF32 result = surfaceReflectivity * lightIntensity * dot; + + + return result; +} +