Modify lighting to use a point light
This commit is contained in:
parent
e29ad8b418
commit
b3991a4651
2
Makefile
2
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
|
transform.h util.h vec.h
|
||||||
HEADERS = $(patsubst %,$(INCLUDE_DIR)/%,$(_HEADERS))
|
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))
|
OBJS = $(patsubst %,$(BUILD_DIR)/%,$(_OBJS))
|
||||||
|
|
||||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp $(HEADERS)
|
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp $(HEADERS)
|
||||||
|
|
|
@ -20,18 +20,6 @@ struct ColorU32
|
||||||
struct ColorF32
|
struct ColorF32
|
||||||
{
|
{
|
||||||
float b, g, r, a;
|
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;
|
ColorF32 result;
|
||||||
|
|
||||||
result.b = MIN((c1.b + c2.b), 1.0f);
|
result.b = c1.b + c2.b;
|
||||||
result.g = MIN((c1.g + c2.g), 1.0f);
|
result.g = c1.g + c2.g;
|
||||||
result.r = MIN((c1.r + c2.r), 1.0f);
|
result.r = c1.r + c2.r;
|
||||||
result.a = MIN((c1.a + c2.a), 1.0f);
|
result.a = c1.a + c2.a;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +42,7 @@ inline ColorF32 &operator+=(ColorF32 &c1, ColorF32 c2)
|
||||||
{
|
{
|
||||||
c1 = c1 + c2;
|
c1 = c1 + c2;
|
||||||
|
|
||||||
return(c1);
|
return c1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// c * f
|
// c * f
|
||||||
|
@ -62,10 +50,10 @@ inline ColorF32 operator*(ColorF32 c, float f)
|
||||||
{
|
{
|
||||||
ColorF32 result;
|
ColorF32 result;
|
||||||
|
|
||||||
result.b = MIN((f * c.b), 1.0f);
|
result.b = f * c.b;
|
||||||
result.g = MIN((f * c.g), 1.0f);
|
result.g = f * c.g;
|
||||||
result.r = MIN((f * c.r), 1.0f);
|
result.r = f * c.r;
|
||||||
result.a = MIN((f * c.a), 1.0f);
|
result.a = f * c.a;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -80,6 +68,61 @@ inline ColorF32 operator*(float f, ColorF32 c)
|
||||||
return result;
|
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
|
#define COLOR_H
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
// GEOMETRY CONFIGURATION
|
// GEOMETRY CONFIGURATION
|
||||||
#define FACE_LIMIT (30000)
|
#define FACE_LIMIT (30000)
|
||||||
#define MATERIAL_LIMIT (10)
|
#define MATERIAL_LIMIT (5)
|
||||||
#define TEXTURE_SIZE_LIMIT (1024)
|
#define TEXTURE_SIZE_LIMIT (1024)
|
||||||
#define VERTEX_LIMIT (20000)
|
#define VERTEX_LIMIT (20000)
|
||||||
|
|
||||||
|
|
|
@ -2,47 +2,23 @@
|
||||||
|
|
||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "vec.h"
|
#include "geometry.h"
|
||||||
#include <cstdint>
|
#include "point.h"
|
||||||
|
|
||||||
|
|
||||||
// STRUCTURES
|
// STRUCTURES
|
||||||
struct LightAmbient
|
struct Light
|
||||||
{
|
{
|
||||||
inline ColorF32 ComputeColor(ColorF32 reflectivity)
|
Point position;
|
||||||
{
|
ColorF32 color;
|
||||||
ColorF32 result;
|
|
||||||
|
|
||||||
result = reflectivity * intensity;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
float intensity;
|
float intensity;
|
||||||
|
float falloffConstant;
|
||||||
|
float falloffLinear;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LightDiffuse
|
|
||||||
{
|
|
||||||
inline ColorF32 ComputeColor(ColorF32 reflectivity, Vector normal)
|
|
||||||
{
|
|
||||||
ColorF32 result;
|
|
||||||
|
|
||||||
float dot = Vector::Dot(normal, direction);
|
// PUBLIC FUNCTIONS
|
||||||
|
ColorF32 ComputeLight(Vertex &vert, Material &material, Light &light);
|
||||||
result = reflectivity * intensity * dot;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
float intensity;
|
|
||||||
Vector direction;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LightList
|
|
||||||
{
|
|
||||||
LightAmbient ambient;
|
|
||||||
LightDiffuse diffuse;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define LIGHT_H
|
#define LIGHT_H
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
// GLOBALS
|
// GLOBALS
|
||||||
static Mesh mesh;
|
static Mesh mesh;
|
||||||
static Camera camera;
|
static Camera camera;
|
||||||
static LightList lights;
|
static Light light;
|
||||||
static VertexList localVerts;
|
static VertexList localVerts;
|
||||||
static VertexList transVerts;
|
static VertexList transVerts;
|
||||||
static FaceList localFaces;
|
static FaceList localFaces;
|
||||||
|
@ -33,7 +33,7 @@ static void ComputeNormals(void);
|
||||||
static void ClearDepthBuffer(Engine_Buffer &buffer);
|
static void ClearDepthBuffer(Engine_Buffer &buffer);
|
||||||
static void TransformToClipSpace(void);
|
static void TransformToClipSpace(void);
|
||||||
static void TransformToScreenSpace(void);
|
static void TransformToScreenSpace(void);
|
||||||
static void ComputeLighting(void);
|
static void LightMesh(void);
|
||||||
|
|
||||||
|
|
||||||
// PUBLIC FUNCTIONS
|
// PUBLIC FUNCTIONS
|
||||||
|
@ -68,15 +68,17 @@ int Engine_Init(char *objFilename, char *mtlFilename)
|
||||||
|
|
||||||
|
|
||||||
// Mesh configuration
|
// Mesh configuration
|
||||||
mesh.position.z = 50;
|
mesh.position.z = 125;
|
||||||
mesh.position.y = -50;
|
mesh.position.y = -125;
|
||||||
mesh.scale = 1.0f;
|
mesh.scale = 1.0f;
|
||||||
|
|
||||||
|
|
||||||
// Light configuration
|
// Light configuration
|
||||||
lights.ambient.intensity = 1.0f;
|
light.position = Point(-100.0f, 200.0f, 0.0f);
|
||||||
lights.diffuse.intensity = 1.0f;
|
light.color = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
lights.diffuse.direction = Vector(1.0f, 1.0f, 1.0f);
|
light.intensity = 2.0f;
|
||||||
|
light.falloffConstant = 1.0f;
|
||||||
|
light.falloffLinear = 0.001f;
|
||||||
|
|
||||||
|
|
||||||
// Transformation matrices that do not change
|
// Transformation matrices that do not change
|
||||||
|
@ -106,7 +108,7 @@ void Engine_Render(Engine_Buffer &buffer, uint32_t input)
|
||||||
|
|
||||||
|
|
||||||
// Light vertices and/or faces
|
// Light vertices and/or faces
|
||||||
ComputeLighting();
|
LightMesh();
|
||||||
|
|
||||||
|
|
||||||
// Transform vertices to screen space
|
// Transform vertices to screen space
|
||||||
|
@ -127,29 +129,29 @@ static void CheckInputs(uint32_t input)
|
||||||
{
|
{
|
||||||
if (CHECK_BIT(input, TRANSLATE_X_POS))
|
if (CHECK_BIT(input, TRANSLATE_X_POS))
|
||||||
{
|
{
|
||||||
mesh.position.x += 10;
|
light.position.x += 10;
|
||||||
}
|
}
|
||||||
else if (CHECK_BIT(input, TRANSLATE_X_NEG))
|
else if (CHECK_BIT(input, TRANSLATE_X_NEG))
|
||||||
{
|
{
|
||||||
mesh.position.x -= 10;
|
light.position.x -= 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CHECK_BIT(input, TRANSLATE_Z_POS))
|
if (CHECK_BIT(input, TRANSLATE_Z_POS))
|
||||||
{
|
{
|
||||||
mesh.position.z += 10;
|
light.position.z += 10;
|
||||||
}
|
}
|
||||||
else if (CHECK_BIT(input, TRANSLATE_Z_NEG))
|
else if (CHECK_BIT(input, TRANSLATE_Z_NEG))
|
||||||
{
|
{
|
||||||
mesh.position.z -= 10;
|
light.position.z -= 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CHECK_BIT(input, TRANSLATE_Y_POS))
|
if (CHECK_BIT(input, TRANSLATE_Y_POS))
|
||||||
{
|
{
|
||||||
mesh.position.y += 10;
|
light.position.y += 10;
|
||||||
}
|
}
|
||||||
else if (CHECK_BIT(input, TRANSLATE_Y_NEG))
|
else if (CHECK_BIT(input, TRANSLATE_Y_NEG))
|
||||||
{
|
{
|
||||||
mesh.position.y -= 10;
|
light.position.y -= 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CHECK_BIT(input, ROTATE_X_POS))
|
if (CHECK_BIT(input, ROTATE_X_POS))
|
||||||
|
@ -181,11 +183,15 @@ static void CheckInputs(uint32_t input)
|
||||||
|
|
||||||
if (CHECK_BIT(input, SCALE_UP))
|
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))
|
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)
|
for (size_t f = 0; f < transFaces.size; ++f)
|
||||||
{
|
{
|
||||||
Face &face = transFaces.data[f];
|
Face &face = transFaces.data[f];
|
||||||
Material &material = materials.data[face.materialIndex];
|
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
|
// Gouraud shading
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
{
|
{
|
||||||
Vertex &vert = transVerts.data[face.vertIndex[i]];
|
Vertex &vert = transVerts.data[face.vertIndex[i]];
|
||||||
|
|
||||||
vert.color =
|
vert.color = ComputeLight(vert, material, light);
|
||||||
lights.ambient.ComputeColor(material.ambient)
|
|
||||||
+ lights.diffuse.ComputeColor(material.diffuse, vert.normal);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,11 +187,16 @@ void RenderMesh(
|
||||||
+ (barycenter[1] * c1)
|
+ (barycenter[1] * c1)
|
||||||
+ (barycenter[2] * c2);
|
+ (barycenter[2] * c2);
|
||||||
|
|
||||||
|
|
||||||
|
// Ensure no color channel exceeds 1.0
|
||||||
|
ScaleColor(shading);
|
||||||
|
|
||||||
|
|
||||||
|
// Light the texture
|
||||||
color.b *= shading.b;
|
color.b *= shading.b;
|
||||||
color.g *= shading.g;
|
color.g *= shading.g;
|
||||||
color.r *= shading.r;
|
color.r *= shading.r;
|
||||||
|
|
||||||
|
|
||||||
// Interpolate 1/z for the z-buffer
|
// Interpolate 1/z for the z-buffer
|
||||||
float zInv =
|
float zInv =
|
||||||
1.0f /
|
1.0f /
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue