1
0
Fork 0

Add flat shading with ambient and diffuse light

master
Austin Morlan 4 years ago
parent f642b0ec02
commit 63e8bd1b93
Signed by: austin
GPG Key ID: FD6B27654AF5E348
  1. 3
      Makefile
  2. 58
      include/color.h
  3. 40
      include/geometry.h
  4. 51
      include/light.h
  5. 14
      include/point.h
  6. 2
      include/util.h
  7. 82
      include/vec.h
  8. 76
      src/engine.cpp

@ -36,7 +36,8 @@ WARNINGS_OFF=-Wno-missing-braces -Wno-gnu-anonymous-struct -Wno-old-style-cast\
CFLAGS=$(D) $(O) -std=c++11 $(WARNINGS_ON) $(WARNINGS_OFF) -I$(INCLUDE_DIR)
LIBS=-lSDL2
_HEADERS = color.h engine.h geometry.h loader.h platform.h point.h transform.h util.h
_HEADERS = color.h engine.h geometry.h light.h loader.h platform.h point.h\
transform.h util.h vec.h
HEADERS = $(patsubst %,$(INCLUDE_DIR)/%,$(_HEADERS))
_OBJS = engine.o geometry.o loader.o main.o platform.o transform.o

@ -1,5 +1,6 @@
#ifndef COLOR_H
#include "util.h"
#include <cstdint>
@ -9,16 +10,65 @@ struct ColorU32
{
struct
{
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
uint8_t b, g, r, a;
};
uint32_t u32;
};
};
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;
}
};
// OPERATORS
// c1 + c2
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);
return result;
}
// c1 += c2
inline ColorF32 &operator+=(ColorF32 &c1, ColorF32 c2)
{
c1 = c1 + c2;
return(c1);
}
// c * f
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);
return result;
}
#define COLOR_H
#endif

@ -1,14 +1,22 @@
#ifndef GEOMETRY_H
#include "color.h"
#include "point.h"
#include <cstdint>
#include <vector>
// STRUCTURES
struct Material
{
ColorF32 kAmbient;
ColorF32 kDiffuse;
};
struct Face
{
unsigned int vertIndex[3];
ColorU32 color;
};
struct Mesh
@ -26,12 +34,44 @@ struct Mesh
scale = 1.0f;
}
inline void CullBackfaces(Point camPosition)
{
culledFaces.clear();
for (size_t f = 0; f < faces.size(); ++f)
{
unsigned int v0 = faces[f].vertIndex[0];
unsigned int v1 = faces[f].vertIndex[1];
unsigned int v2 = faces[f].vertIndex[2];
Vector v01 = vertsTransformed[v1] - vertsTransformed[v0];
Vector v02 = vertsTransformed[v2] - vertsTransformed[v0];
Vector normal = Vector::Cross(v01, v02);
// Invert for Blender-compatibility
normal = -normal;
// Eye vector to viewport
Vector view = camPosition - vertsTransformed[v0];
float dot = Vector::Dot(normal, view);
if (dot < EPSILON_E3)
{
culledFaces.push_back(faces[f]);
}
}
}
Point position;
float rotation[3];
float scale;
std::vector<Point> verts;
std::vector<Point> vertsTransformed;
std::vector<Face> faces;
std::vector<Face> culledFaces;
Material material;
};

@ -0,0 +1,51 @@
#ifndef LIGHT_H
#include "color.h"
#include "vec.h"
#include <cstdint>
// STRUCTURES
struct LightAmbient
{
inline ColorF32 ComputeColor(ColorF32 reflectivity)
{
ColorF32 result;
result = reflectivity * intensity;
return result;
}
float intensity;
};
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;
int diffuseCount;
};
#define LIGHT_H
#endif

@ -1,5 +1,7 @@
#ifndef POINT_H
#include "vec.h"
// STRUCTURE
struct Point
@ -34,6 +36,18 @@ inline Point operator/(Point v, float f)
return result;
}
// v1 - v2
inline Vector operator-(Point v1, Point v2)
{
Vector result;
result.x = v1.x - v2.x;
result.y = v1.y - v2.y;
result.z = v1.z - v2.z;
return result;
}
#define POINT_H
#endif

@ -13,6 +13,8 @@ const float EPSILON_E3 = 1E-3f;
#define CHECK_BIT(x, bit) (x & (1UL << bit))
#define DEG_TO_RAD(deg) ((deg * (float)M_PI) / 180.0f)
#define SWAP(a, b, temp) {temp = a; a = b; b = temp;}
#define MIN(a, b) ((a < b) ? a : b)
#define MAX(a, b) ((a > b) ? a : b)
#define FLOAT_EQUAL(a, b) ((fabsf(a - b) < EPSILON_E3) ? 1 : 0)

@ -0,0 +1,82 @@
#ifndef VEC_H
#include "util.h"
#include <cmath>
// STRUCTURE
struct Vector
{
inline Vector(void) : x(0), y(0), z(0), w(0) {}
inline Vector(float x, float y, float z) : x(x), y(y), z(z), w(0) {}
inline void Normalize(void)
{
float length = sqrtf(x*x + y*y + z*z);
// zero length
if (length < EPSILON_E3)
{
x = 0.0f;
y = 0.0f;
z = 0.0f;
}
else
{
float lengthInv = 1.0f / length;
x *= lengthInv;
y *= lengthInv;
z *= lengthInv;
}
}
inline static float Dot(Vector v1, Vector v2)
{
float result;
result = (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z);
return result;
}
inline static Vector Cross(Vector v1, Vector v2)
{
Vector result;
result.x = (v1.y * v2.z) - (v1.z * v2.y);
result.y = (v1.z * v2.x) - (v1.x * v2.z);
result.z = (v1.x * v2.y) - (v1.y * v2.x);
return result;
}
union
{
float e[4];
struct
{
float x, y, z, w;
};
};
};
// OPERATORS
// -v
inline Vector operator-(Vector v)
{
Vector result;
result.x = -v.x;
result.y = -v.y;
result.z = -v.z;
return result;
}
#define VEC_H
#endif

@ -2,16 +2,19 @@
#include "color.h"
#include "engine.h"
#include "geometry.h"
#include "light.h"
#include "loader.h"
#include "matrix.h"
#include "transform.h"
#include "util.h"
#include "vec.h"
#include <cstdio>
// GLOBALS
static Mesh mesh;
static Camera camera;
static LightList lights;
// PRIVATE PROTOTYPES
@ -29,9 +32,17 @@ int Engine_Init(Engine_Buffer &buffer, char *filename)
}
mesh.position.z = 250;
mesh.material.kDiffuse = {1.0,1.0,1.0,1.0};
mesh.material.kAmbient = {1.0,1.0,1.0,1.0};
camera.SetFOV(90.0f, buffer.width, buffer.height);
lights.diffuse = (LightDiffuse*)malloc(sizeof(LightDiffuse));
lights.diffuseCount = 1;
lights.ambient.intensity = 1.0;
lights.diffuse[0].intensity = 0.5;
lights.diffuse[0].direction = Vector(1,1,1);
return 0;
}
@ -39,30 +50,69 @@ void Engine_Render(Engine_Buffer &buffer, uint32_t input)
{
CheckInputs(input);
// Local space to world space
Matrix tTranslate = Transform_Translate(
mesh.position.x, mesh.position.y, mesh.position.z);
Matrix tRotate = Transform_Rotate(
mesh.rotation[0], mesh.rotation[1], mesh.rotation[2]);
Matrix tScale = Transform_Scale(
mesh.scale);
Matrix tScale = Transform_Scale(mesh.scale);
for (size_t v = 0; v < mesh.verts.size(); ++v)
{
mesh.vertsTransformed[v] =
mesh.verts[v] * tScale * tRotate * tTranslate;
}
// Cull backfaces before computing colors
mesh.CullBackfaces(camera.position);
// Color the faces (flat shading)
for (size_t f = 0; f < mesh.culledFaces.size(); ++f)
{
unsigned int v0 = mesh.culledFaces[f].vertIndex[0];
unsigned int v1 = mesh.culledFaces[f].vertIndex[1];
unsigned int v2 = mesh.culledFaces[f].vertIndex[2];
Matrix tView = Transform_View(
camera.position, camera.rotation);
Vector v01 = mesh.vertsTransformed[v1] - mesh.vertsTransformed[v0];
Vector v02 = mesh.vertsTransformed[v2] - mesh.vertsTransformed[v0];
Vector normal = Vector::Cross(v01, v02);
normal.Normalize();
ColorF32 totalColor = lights.ambient.ComputeColor(mesh.material.kAmbient);
for (int c = 0; c < lights.diffuseCount; ++c)
{
totalColor += lights.diffuse[c].ComputeColor(
mesh.material.kDiffuse, normal);
}
mesh.faces[f].color = ColorF32::ConvertToU32(totalColor);
}
// World space to camera (view) space
Matrix tView = Transform_View(camera.position, camera.rotation);
// Camera space to perspective
Matrix tPersp = Transform_Perspective(
camera.xZoom, camera.yZoom, camera.nearClip, camera.farClip);
for (size_t v = 0; v < mesh.verts.size(); ++v)
{
mesh.vertsTransformed[v] =
mesh.verts[v] * tScale * tRotate * tTranslate * tView * tPersp;
mesh.vertsTransformed[v] = mesh.vertsTransformed[v] * tView * tPersp;
mesh.vertsTransformed[v] =
mesh.vertsTransformed[v] / mesh.vertsTransformed[v].w;
}
// Perspective to screen
Matrix tScreen = Transform_Screen(camera.xScale, camera.yScale);
for (size_t v = 0; v < mesh.verts.size(); ++v)
@ -70,16 +120,16 @@ void Engine_Render(Engine_Buffer &buffer, uint32_t input)
mesh.vertsTransformed[v] = mesh.vertsTransformed[v] * tScreen;
}
for(size_t f = 0; f < mesh.faces.size(); ++f)
{
unsigned int v0 = mesh.faces[f].vertIndex[0];
unsigned int v1 = mesh.faces[f].vertIndex[1];
unsigned int v2 = mesh.faces[f].vertIndex[2];
ColorU32 white = {0xff,0xff,0xff,0xff};
// Fill each face with its respective color
for(size_t f = 0; f < mesh.culledFaces.size(); ++f)
{
unsigned int v0 = mesh.culledFaces[f].vertIndex[0];
unsigned int v1 = mesh.culledFaces[f].vertIndex[1];
unsigned int v2 = mesh.culledFaces[f].vertIndex[2];
FillTriangle(
buffer.pixels, buffer.width, white.u32,
buffer.pixels, buffer.width, mesh.faces[f].color.u32,
mesh.vertsTransformed[v0].x, mesh.vertsTransformed[v0].y,
mesh.vertsTransformed[v1].x, mesh.vertsTransformed[v1].y,
mesh.vertsTransformed[v2].x, mesh.vertsTransformed[v2].y);

Loading…
Cancel
Save