chapter 10
This commit is contained in:
parent
cbecc15fb8
commit
cdb425cb4f
1
.gitignore
vendored
1
.gitignore
vendored
@ -14,6 +14,7 @@ test/test_world
|
||||
test/test_camera
|
||||
test/test_shapes
|
||||
test/test_planes
|
||||
test/test_patterns
|
||||
raytracer
|
||||
*.ppm
|
||||
*.png
|
||||
|
48
lighting.h
Normal file
48
lighting.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include "materials.h"
|
||||
#include "shapes.h"
|
||||
#include "lights.h"
|
||||
#include "patterns.h"
|
||||
|
||||
inline static struct tuple lighting(struct material material,
|
||||
struct shape const * const object,
|
||||
struct light light,
|
||||
struct tuple point,
|
||||
struct tuple eyev,
|
||||
struct tuple normalv,
|
||||
bool in_shadow)
|
||||
{
|
||||
struct tuple color;
|
||||
if (material.has_pattern) {
|
||||
color = pattern_at_object(material.pattern, object->transform, point);
|
||||
} else {
|
||||
color = material.color;
|
||||
}
|
||||
struct tuple effective_color = hadmard_product(color, light.intensity);
|
||||
|
||||
struct tuple lightv = tuple_normalize(tuple_sub(light.position, point));
|
||||
|
||||
struct tuple ambient = tuple_mul(effective_color, material.ambient);
|
||||
|
||||
if (in_shadow) {
|
||||
return ambient;
|
||||
}
|
||||
|
||||
float light_dot_normal = tuple_dot(lightv, normalv);
|
||||
if (light_dot_normal < 0.0f) {
|
||||
return ambient;
|
||||
} else {
|
||||
struct tuple diffuse = tuple_mul(effective_color, material.diffuse * light_dot_normal);
|
||||
|
||||
struct tuple reflectv = tuple_reflect(tuple_neg(lightv), normalv);
|
||||
float reflect_dot_eye = tuple_dot(reflectv, eyev);
|
||||
if (reflect_dot_eye <= 0.0f) {
|
||||
return tuple_add(ambient, diffuse);
|
||||
} else {
|
||||
float factor = powf(reflect_dot_eye, material.shininess);
|
||||
struct tuple specular = tuple_mul(light.intensity, material.specular * factor);
|
||||
return tuple_add(tuple_add(ambient, diffuse), specular);
|
||||
}
|
||||
}
|
||||
}
|
47
materials.h
47
materials.h
@ -2,24 +2,30 @@
|
||||
|
||||
#include "tuples.h"
|
||||
#include "lights.h"
|
||||
#include "patterns.h"
|
||||
#include "math.h"
|
||||
|
||||
struct material {
|
||||
struct tuple color;
|
||||
float ambient;
|
||||
float diffuse;
|
||||
float specular;
|
||||
float shininess;
|
||||
bool has_pattern;
|
||||
union {
|
||||
struct tuple color;
|
||||
struct pattern pattern;
|
||||
};
|
||||
};
|
||||
|
||||
inline static struct material material()
|
||||
{
|
||||
return (struct material){
|
||||
color(1.0f, 1.0f, 1.0f),
|
||||
0.1f,
|
||||
0.9f,
|
||||
0.9f,
|
||||
200.0f
|
||||
200.0f,
|
||||
.has_pattern = false,
|
||||
.color = color(1.0f, 1.0f, 1.0f),
|
||||
};
|
||||
}
|
||||
|
||||
@ -32,38 +38,3 @@ inline static bool material_equal(struct material a, struct material b)
|
||||
float_equal(a.specular, b.specular) &&
|
||||
float_equal(a.shininess, b.shininess);
|
||||
}
|
||||
|
||||
inline static struct tuple lighting(struct material material,
|
||||
struct light light,
|
||||
struct tuple point,
|
||||
struct tuple eyev,
|
||||
struct tuple normalv,
|
||||
bool in_shadow)
|
||||
{
|
||||
struct tuple effective_color = hadmard_product(material.color, light.intensity);
|
||||
|
||||
struct tuple lightv = tuple_normalize(tuple_sub(light.position, point));
|
||||
|
||||
struct tuple ambient = tuple_mul(effective_color, material.ambient);
|
||||
|
||||
if (in_shadow) {
|
||||
return ambient;
|
||||
}
|
||||
|
||||
float light_dot_normal = tuple_dot(lightv, normalv);
|
||||
if (light_dot_normal < 0.0f) {
|
||||
return ambient;
|
||||
} else {
|
||||
struct tuple diffuse = tuple_mul(effective_color, material.diffuse * light_dot_normal);
|
||||
|
||||
struct tuple reflectv = tuple_reflect(tuple_neg(lightv), normalv);
|
||||
float reflect_dot_eye = tuple_dot(reflectv, eyev);
|
||||
if (reflect_dot_eye <= 0.0f) {
|
||||
return tuple_add(ambient, diffuse);
|
||||
} else {
|
||||
float factor = powf(reflect_dot_eye, material.shininess);
|
||||
struct tuple specular = tuple_mul(light.intensity, material.specular * factor);
|
||||
return tuple_add(tuple_add(ambient, diffuse), specular);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1
math.h
1
math.h
@ -7,6 +7,7 @@
|
||||
#define powf __builtin_powf
|
||||
#define tanf __builtin_tanf
|
||||
#define fabsf __builtin_fabsf
|
||||
#define floorf __builtin_floorf
|
||||
|
||||
static const float tau = 6.283185307179586f;
|
||||
static const float pi = tau / 2.0f;
|
||||
|
102
patterns.h
Normal file
102
patterns.h
Normal file
@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include "tuples.h"
|
||||
#include "matrices.h"
|
||||
|
||||
enum pattern_type {
|
||||
PATTERN_STRIPE,
|
||||
PATTERN_GRADIENT,
|
||||
PATTERN_RING,
|
||||
PATTERN_CHECKERS
|
||||
};
|
||||
|
||||
struct pattern {
|
||||
enum pattern_type type;
|
||||
struct tuple a;
|
||||
struct tuple b;
|
||||
struct mat4x4 transform;
|
||||
};
|
||||
|
||||
inline static struct pattern stripe_pattern(struct tuple a, struct tuple b)
|
||||
{
|
||||
return (struct pattern) {
|
||||
PATTERN_STRIPE,
|
||||
a,
|
||||
b,
|
||||
mat4x4_identity()
|
||||
};
|
||||
}
|
||||
|
||||
inline static struct pattern gradient_pattern(struct tuple a, struct tuple b)
|
||||
{
|
||||
return (struct pattern) {
|
||||
PATTERN_GRADIENT,
|
||||
a,
|
||||
b,
|
||||
mat4x4_identity()
|
||||
};
|
||||
}
|
||||
|
||||
inline static struct pattern ring_pattern(struct tuple a, struct tuple b)
|
||||
{
|
||||
return (struct pattern) {
|
||||
PATTERN_RING,
|
||||
a,
|
||||
b,
|
||||
mat4x4_identity()
|
||||
};
|
||||
}
|
||||
|
||||
inline static struct pattern checkers_pattern(struct tuple a, struct tuple b)
|
||||
{
|
||||
return (struct pattern) {
|
||||
PATTERN_CHECKERS,
|
||||
a,
|
||||
b,
|
||||
mat4x4_identity()
|
||||
};
|
||||
}
|
||||
|
||||
inline static struct tuple stripe_at(struct pattern pattern, struct tuple point)
|
||||
{
|
||||
return ((int)floorf(point.x)) % 2 == 0 ? pattern.a : pattern.b;
|
||||
}
|
||||
|
||||
inline static struct tuple gradient_at(struct pattern pattern, struct tuple point)
|
||||
{
|
||||
struct tuple distance = tuple_sub(pattern.b, pattern.a);
|
||||
float fraction = point.x - floorf(point.x);
|
||||
|
||||
return tuple_add(pattern.a, tuple_mul(distance, fraction));
|
||||
}
|
||||
|
||||
inline static struct tuple ring_at(struct pattern pattern, struct tuple point)
|
||||
{
|
||||
return ((int)floorf(sqrtf(point.x * point.x + point.z * point.z))) % 2 == 0 ? pattern.a : pattern.b;
|
||||
}
|
||||
|
||||
inline static struct tuple checkers_at(struct pattern pattern, struct tuple point)
|
||||
{
|
||||
return (int)(floorf(point.x) + floorf(point.y) + floorf(point.z)) % 2 == 0 ? pattern.a : pattern.b;
|
||||
}
|
||||
|
||||
inline static struct tuple pattern_at_object(struct pattern pattern, struct mat4x4 object_transform, struct tuple point)
|
||||
{
|
||||
struct tuple object_point = mat4x4_mul_t(mat4x4_inverse(object_transform), point);
|
||||
struct tuple pattern_point = mat4x4_mul_t(mat4x4_inverse(pattern.transform), object_point);
|
||||
|
||||
switch (pattern.type) {
|
||||
case PATTERN_STRIPE:
|
||||
return stripe_at(pattern, pattern_point);
|
||||
case PATTERN_GRADIENT:
|
||||
return gradient_at(pattern, pattern_point);
|
||||
case PATTERN_RING:
|
||||
return ring_at(pattern, pattern_point);
|
||||
case PATTERN_CHECKERS:
|
||||
return checkers_at(pattern, pattern_point);
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
21
raytracer.c
21
raytracer.c
@ -23,7 +23,11 @@ int main()
|
||||
float half = wall_size / 2.0f;
|
||||
|
||||
struct shape floor = plane();
|
||||
floor.material.color = color(1.0f, 0.9f, 0.9f);
|
||||
floor.material.has_pattern = true;
|
||||
floor.material.pattern.a = color(1.0f, 0.3f, 0.9f);
|
||||
floor.material.pattern.b = color(0.2f, 0.9f, 0.5f);
|
||||
floor.material.pattern.type = PATTERN_CHECKERS;
|
||||
//floor.material.pattern.transform = scaling(10.0f, 2.0f, 2.0f);
|
||||
floor.material.specular = 0.0f;
|
||||
|
||||
/*
|
||||
@ -128,17 +132,17 @@ int main()
|
||||
h6.transform = mat4x4_mul_m(h6_rr, h6_r);
|
||||
h6.transform = mat4x4_mul_m(h6_t, h6.transform);
|
||||
|
||||
h1.material = floor.material;
|
||||
h1.material.specular = 0.0f;
|
||||
h1.material.color = color(1.0f, 0.0f, 0.0f);
|
||||
h2.material = floor.material;
|
||||
h2.material.specular = 0.0f;
|
||||
h2.material.color = color(0.0f, 1.0f, 0.0f);
|
||||
h3.material = floor.material;
|
||||
h3.material.specular = 0.0f;
|
||||
h3.material.color = color(0.0f, 0.0f, 1.0f);
|
||||
h4.material = floor.material;
|
||||
h4.material.specular = 0.0f;
|
||||
h4.material.color = color(1.0f, 1.0f, 0.0f);
|
||||
h5.material = floor.material;
|
||||
h5.material.specular = 0.0f;
|
||||
h5.material.color = color(0.0f, 1.0f, 1.0f);
|
||||
h6.material = floor.material;
|
||||
h6.material.specular = 0.0f;
|
||||
h6.material.color = color(1.0f, 0.0f, 1.0f);
|
||||
|
||||
struct world world;
|
||||
@ -165,6 +169,9 @@ int main()
|
||||
|
||||
for (int i = 0; i < 360; i++) {
|
||||
|
||||
world.objects[0].material.pattern.transform =
|
||||
mat4x4_mul_m(rotation_y(-tau / 360 * (float)i * 2.0f), mat4x4_mul_m(translation((float)i / 360.0f * 10.0f, 0.0f, 0.0f), scaling(3.0f, 3.0f, 3.0f)));
|
||||
|
||||
_camera.transform = view_transform(point(2.0f * cosf(pi / 360 * (float)i * 0.5),
|
||||
8.5f,
|
||||
1.0f * sinf(pi / 360 * (float)i * 0.5)),
|
||||
|
@ -3,7 +3,7 @@
|
||||
set -eux
|
||||
|
||||
|
||||
for name in tuples canvas matrices transformations rays intersections shapes spheres planes lights materials world camera; do
|
||||
for name in tuples canvas matrices transformations rays intersections shapes spheres planes lights materials world camera patterns; do
|
||||
gcc -g -gdwarf-5 \
|
||||
-Wall -Werror -Wfatal-errors \
|
||||
-Wno-error=unused-variable \
|
||||
|
@ -2,8 +2,9 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "materials.h"
|
||||
#include "lighting.h"
|
||||
#include "runner.h"
|
||||
#include "lights.h"
|
||||
#include "shapes.h"
|
||||
|
||||
static bool materials_test_0(const char ** scenario)
|
||||
{
|
||||
@ -28,7 +29,8 @@ static bool materials_test_1(const char ** scenario)
|
||||
struct tuple eyev = vector(0.0f, 0.0f, -1.0f);
|
||||
struct tuple normalv = vector(0.0f, 0.0f, -1.0f);
|
||||
struct light light = point_light(point(0.0f, 0.0f, -10.0f), color(1.0f, 1.0f, 1.0f));
|
||||
struct tuple result = lighting(m, light, position, eyev, normalv, false);
|
||||
struct shape object = shape();
|
||||
struct tuple result = lighting(m, &object, light, position, eyev, normalv, false);
|
||||
|
||||
return tuple_equal(result, color(1.9f, 1.9f, 1.9f));
|
||||
}
|
||||
@ -43,7 +45,8 @@ static bool materials_test_2(const char ** scenario)
|
||||
struct tuple eyev = vector(0.0f, 0.7071067811865476, -0.7071067811865476);
|
||||
struct tuple normalv = vector(0.0f, 0.0f, -1.0f);
|
||||
struct light light = point_light(point(0.0f, 0.0f, -10.0f), color(1.0f, 1.0f, 1.0f));
|
||||
struct tuple result = lighting(m, light, position, eyev, normalv, false);
|
||||
struct shape object = shape();
|
||||
struct tuple result = lighting(m, &object, light, position, eyev, normalv, false);
|
||||
|
||||
return tuple_equal(result, color(1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
@ -58,7 +61,8 @@ static bool materials_test_3(const char ** scenario)
|
||||
struct tuple eyev = vector(0.0f, 0.0f, -1.0f);
|
||||
struct tuple normalv = vector(0.0f, 0.0f, -1.0f);
|
||||
struct light light = point_light(point(0.0f, 10.0f, -10.0f), color(1.0f, 1.0f, 1.0f));
|
||||
struct tuple result = lighting(m, light, position, eyev, normalv, false);
|
||||
struct shape object = shape();
|
||||
struct tuple result = lighting(m, &object, light, position, eyev, normalv, false);
|
||||
|
||||
return tuple_equal(result, color(0.7364f, 0.7364f, 0.7364f));
|
||||
}
|
||||
@ -73,7 +77,8 @@ static bool materials_test_4(const char ** scenario)
|
||||
struct tuple eyev = vector(0.0f, -0.7071067811865476, -0.7071067811865476);
|
||||
struct tuple normalv = vector(0.0f, 0.0f, -1.0f);
|
||||
struct light light = point_light(point(0.0f, 10.0f, -10.0f), color(1.0f, 1.0f, 1.0f));
|
||||
struct tuple result = lighting(m, light, position, eyev, normalv, false);
|
||||
struct shape object = shape();
|
||||
struct tuple result = lighting(m, &object, light, position, eyev, normalv, false);
|
||||
|
||||
return tuple_equal(result, color(1.63639, 1.63639, 1.63639));
|
||||
}
|
||||
@ -88,7 +93,8 @@ static bool materials_test_5(const char ** scenario)
|
||||
struct tuple eyev = vector(0.0f, 0.0f, -1.0f);
|
||||
struct tuple normalv = vector(0.0f, 0.0f, -1.0f);
|
||||
struct light light = point_light(point(0.0f, 0.0f, 10.0f), color(1.0f, 1.0f, 1.0f));
|
||||
struct tuple result = lighting(m, light, position, eyev, normalv, false);
|
||||
struct shape object = shape();
|
||||
struct tuple result = lighting(m, &object, light, position, eyev, normalv, false);
|
||||
|
||||
return tuple_equal(result, color(0.1f, 0.1f, 0.1f));
|
||||
}
|
||||
@ -105,11 +111,37 @@ static bool materials_test_6(const char ** scenario)
|
||||
struct light light = point_light(point(0.0f, 0.0f, -10.0f), color(1.0f, 1.0f, 1.0f));
|
||||
bool in_shadow = true;
|
||||
|
||||
struct tuple result = lighting(m, light, position, eyev, normalv, in_shadow);
|
||||
struct shape object = shape();
|
||||
struct tuple result = lighting(m, &object, light, position, eyev, normalv, in_shadow);
|
||||
|
||||
return tuple_equal(result, color(0.1f, 0.1f, 0.1f));
|
||||
}
|
||||
|
||||
static bool materials_test_7(const char ** scenario)
|
||||
{
|
||||
*scenario = "Lighting with a pattern applied";
|
||||
|
||||
struct material m = material();
|
||||
|
||||
struct pattern pattern = stripe_pattern(color(1.0f, 1.0f, 1.0f), color(0.0f, 0.0f, 0.0f));
|
||||
m.has_pattern = true;
|
||||
m.pattern = pattern;
|
||||
m.ambient = 1.0f;
|
||||
m.diffuse = 0.0f;
|
||||
m.specular = 0.0f;
|
||||
struct tuple eyev = vector(0.0f, 0.0f, -1.0f);
|
||||
struct tuple normalv = vector(0.0f, 0.0f, -1.0f);
|
||||
struct light light = point_light(point(0.0f, 0.0f, -10.0f), color(1.0f, 1.0f, 1.0f));
|
||||
|
||||
struct shape object = shape();
|
||||
struct tuple c1 = lighting(m, &object, light, point(0.9f, 0.0f, 0.0f), eyev, normalv, false);
|
||||
struct tuple c2 = lighting(m, &object, light, point(1.1f, 0.0f, 0.0f), eyev, normalv, false);
|
||||
|
||||
return
|
||||
tuple_equal(c1, color(1.0f, 1.0f, 1.0f)) &&
|
||||
tuple_equal(c2, color(0.0f, 0.0f, 0.0f));
|
||||
}
|
||||
|
||||
test_t materials_tests[] = {
|
||||
materials_test_0,
|
||||
materials_test_1,
|
||||
@ -118,6 +150,7 @@ test_t materials_tests[] = {
|
||||
materials_test_4,
|
||||
materials_test_5,
|
||||
materials_test_6,
|
||||
materials_test_7,
|
||||
};
|
||||
|
||||
RUNNER(materials_tests)
|
||||
|
176
test/test_patterns.c
Normal file
176
test/test_patterns.c
Normal file
@ -0,0 +1,176 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "patterns.h"
|
||||
#include "spheres.h"
|
||||
#include "transformations.h"
|
||||
#include "runner.h"
|
||||
|
||||
#define black color(0.0f, 0.0f, 0.0f)
|
||||
#define white color(1.0f, 1.0f, 1.0f)
|
||||
|
||||
static bool patterns_test_0(const char ** scenario)
|
||||
{
|
||||
*scenario = "Creating a stripe pattern";
|
||||
|
||||
struct pattern pattern = stripe_pattern(white, black);
|
||||
|
||||
return
|
||||
tuple_equal(pattern.a, white) &&
|
||||
tuple_equal(pattern.b, black);
|
||||
}
|
||||
|
||||
static bool patterns_test_1(const char ** scenario)
|
||||
{
|
||||
*scenario = "A stripe pattern is constant in y";
|
||||
|
||||
struct pattern pattern = stripe_pattern(white, black);
|
||||
|
||||
return
|
||||
tuple_equal(stripe_at(pattern, point(0.0f, 0.0f, 0.0f)), white) &&
|
||||
tuple_equal(stripe_at(pattern, point(0.0f, 1.0f, 0.0f)), white) &&
|
||||
tuple_equal(stripe_at(pattern, point(0.0f, 2.0f, 0.0f)), white);
|
||||
}
|
||||
|
||||
static bool patterns_test_2(const char ** scenario)
|
||||
{
|
||||
*scenario = "A stripe pattern is constant in z";
|
||||
|
||||
struct pattern pattern = stripe_pattern(white, black);
|
||||
|
||||
return
|
||||
tuple_equal(stripe_at(pattern, point(0.0f, 0.0f, 0.0f)), white) &&
|
||||
tuple_equal(stripe_at(pattern, point(0.0f, 0.0f, 1.0f)), white) &&
|
||||
tuple_equal(stripe_at(pattern, point(0.0f, 0.0f, 2.0f)), white);
|
||||
}
|
||||
|
||||
static bool patterns_test_3(const char ** scenario)
|
||||
{
|
||||
*scenario = "A stripe pattern alternates in x";
|
||||
|
||||
struct pattern pattern = stripe_pattern(white, black);
|
||||
|
||||
return
|
||||
tuple_equal(stripe_at(pattern, point(0.0f, 0.0f, 0.0f)), white) &&
|
||||
tuple_equal(stripe_at(pattern, point(0.9f, 0.0f, 0.0f)), white) &&
|
||||
tuple_equal(stripe_at(pattern, point(1.0f, 0.0f, 0.0f)), black) &&
|
||||
tuple_equal(stripe_at(pattern, point(-0.1f, 0.0f, 0.0f)), black) &&
|
||||
tuple_equal(stripe_at(pattern, point(-1.0f, 0.0f, 0.0f)), black) &&
|
||||
tuple_equal(stripe_at(pattern, point(-1.1f, 0.0f, 0.0f)), white);
|
||||
}
|
||||
|
||||
static bool patterns_test_4(const char ** scenario)
|
||||
{
|
||||
*scenario = "Stripes with an object transformation";
|
||||
|
||||
struct shape object = sphere();
|
||||
object.transform = scaling(2.0f, 2.0f, 2.0f);
|
||||
struct pattern pattern = stripe_pattern(white, black);
|
||||
struct tuple c = pattern_at_object(pattern, object.transform, point(1.5f, 0.0f, 0.0f));
|
||||
|
||||
return tuple_equal(c, white);
|
||||
}
|
||||
|
||||
static bool patterns_test_5(const char ** scenario)
|
||||
{
|
||||
*scenario = "Stripes with a pattern transformation";
|
||||
|
||||
struct shape object = sphere();
|
||||
struct pattern pattern = stripe_pattern(white, black);
|
||||
pattern.transform = scaling(2.0f, 2.0f, 2.0f);
|
||||
struct tuple c = pattern_at_object(pattern, object.transform, point(1.5f, 0.0f, 0.0f));
|
||||
|
||||
return tuple_equal(c, white);
|
||||
}
|
||||
|
||||
static bool patterns_test_6(const char ** scenario)
|
||||
{
|
||||
*scenario = "Stripes with both an object and a pattern transformation";
|
||||
|
||||
struct shape object = sphere();
|
||||
object.transform = scaling(2.0f, 2.0f, 2.0f);
|
||||
struct pattern pattern = stripe_pattern(white, black);
|
||||
pattern.transform = translation(0.5f, 0.0f, 0.0f);
|
||||
struct tuple c = pattern_at_object(pattern, object.transform, point(2.5f, 0.0f, 0.0f));
|
||||
|
||||
return tuple_equal(c, white);
|
||||
}
|
||||
|
||||
static bool patterns_test_7(const char ** scenario)
|
||||
{
|
||||
*scenario = "A gradient linearly interpolates between colors";
|
||||
|
||||
struct pattern pattern = gradient_pattern(white, black);
|
||||
|
||||
return
|
||||
tuple_equal(gradient_at(pattern, point(0.0f, 0.0f, 0.0f)), white) &&
|
||||
tuple_equal(gradient_at(pattern, point(0.25f, 0.0f, 0.0f)), color(0.75f, 0.75f, 0.75f)) &&
|
||||
tuple_equal(gradient_at(pattern, point(0.5f, 0.0f, 0.0f)), color(0.5f, 0.5f, 0.5f)) &&
|
||||
tuple_equal(gradient_at(pattern, point(0.75f, 0.0f, 0.0f)), color(0.25f, 0.25f, 0.25f));
|
||||
}
|
||||
|
||||
static bool patterns_test_8(const char ** scenario)
|
||||
{
|
||||
*scenario = "A ring should extend in both x and z";
|
||||
|
||||
struct pattern pattern = ring_pattern(white, black);
|
||||
|
||||
return
|
||||
tuple_equal(ring_at(pattern, point(0.0f, 0.0f, 0.0f)), white) &&
|
||||
tuple_equal(ring_at(pattern, point(1.0f, 0.0f, 0.0f)), black) &&
|
||||
tuple_equal(ring_at(pattern, point(0.0f, 0.0f, 1.0f)), black) &&
|
||||
tuple_equal(ring_at(pattern, point(0.708f, 0.0f, 0.708f)), black);
|
||||
}
|
||||
|
||||
static bool patterns_test_9(const char ** scenario)
|
||||
{
|
||||
*scenario = "Checkers should repeat in x";
|
||||
|
||||
struct pattern pattern = checkers_pattern(white, black);
|
||||
|
||||
return
|
||||
tuple_equal(checkers_at(pattern, point(0.0f, 0.0f, 0.0f)), white) &&
|
||||
tuple_equal(checkers_at(pattern, point(0.99f, 0.0f, 0.0f)), white) &&
|
||||
tuple_equal(checkers_at(pattern, point(1.01f, 0.0f, 0.0f)), black);
|
||||
}
|
||||
|
||||
static bool patterns_test_10(const char ** scenario)
|
||||
{
|
||||
*scenario = "Checkers should repeat in y";
|
||||
|
||||
struct pattern pattern = checkers_pattern(white, black);
|
||||
|
||||
return
|
||||
tuple_equal(checkers_at(pattern, point(0.0f, 0.0f, 0.0f)), white) &&
|
||||
tuple_equal(checkers_at(pattern, point(0.0f, 0.99f, 0.0f)), white) &&
|
||||
tuple_equal(checkers_at(pattern, point(0.0f, 1.01f, 0.0f)), black);
|
||||
}
|
||||
|
||||
static bool patterns_test_11(const char ** scenario)
|
||||
{
|
||||
*scenario = "Checkers should repeat in z";
|
||||
|
||||
struct pattern pattern = checkers_pattern(white, black);
|
||||
|
||||
return
|
||||
tuple_equal(checkers_at(pattern, point(0.0f, 0.0f, 0.0f)), white) &&
|
||||
tuple_equal(checkers_at(pattern, point(0.0f, 0.0f, 0.99f)), white) &&
|
||||
tuple_equal(checkers_at(pattern, point(0.0f, 0.0f, 1.01f)), black);
|
||||
}
|
||||
|
||||
test_t patterns_tests[] = {
|
||||
patterns_test_0,
|
||||
patterns_test_1,
|
||||
patterns_test_2,
|
||||
patterns_test_3,
|
||||
patterns_test_4,
|
||||
patterns_test_5,
|
||||
patterns_test_6,
|
||||
patterns_test_7,
|
||||
patterns_test_8,
|
||||
patterns_test_9,
|
||||
patterns_test_10,
|
||||
patterns_test_11
|
||||
};
|
||||
|
||||
RUNNER(patterns_tests);
|
2
world.h
2
world.h
@ -6,6 +6,7 @@
|
||||
#include "intersections_shapes.h"
|
||||
#include "rays.h"
|
||||
#include "materials.h"
|
||||
#include "lighting.h"
|
||||
|
||||
#define WORLD_MAX_OBJECTS 128
|
||||
|
||||
@ -72,6 +73,7 @@ inline static struct tuple world_shade_hit(struct world * world, struct computat
|
||||
bool is_shadowed = world_is_shadowed(world, computations->over_point);
|
||||
|
||||
struct tuple color = lighting(computations->object->material,
|
||||
computations->object,
|
||||
world->light,
|
||||
computations->point,
|
||||
computations->eyev,
|
||||
|
Loading…
x
Reference in New Issue
Block a user