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
|
||||
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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -2,47 +2,23 @@
|
|||
|
||||
|
||||
#include "color.h"
|
||||
#include "vec.h"
|
||||
#include <cstdint>
|
||||
#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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 /
|
||||
|
|
|
@ -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