[FEAT] until test3 of schlick implementation
This commit is contained in:
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@@ -6,6 +6,7 @@
|
|||||||
"NADAL",
|
"NADAL",
|
||||||
"noninvertible",
|
"noninvertible",
|
||||||
"Raytracer",
|
"Raytracer",
|
||||||
|
"Schlick",
|
||||||
"submatrix"
|
"submatrix"
|
||||||
],
|
],
|
||||||
"files.associations": {
|
"files.associations": {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#include "intersection-data.h"
|
#include "intersection-data.h"
|
||||||
@@ -213,3 +214,33 @@ const double IntersectionData::n2(void) const
|
|||||||
{
|
{
|
||||||
return m_n2;
|
return m_n2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
double IntersectionData::schlick(void)
|
||||||
|
{
|
||||||
|
double the_cos, the_r0;
|
||||||
|
|
||||||
|
// Find the cosine of the angle between the eye and the normal vectors
|
||||||
|
the_cos = m_eyev.dot(m_normalv);
|
||||||
|
|
||||||
|
// Total internal reflection can only occur if n1 > n2
|
||||||
|
if (m_n1 > m_n2)
|
||||||
|
{
|
||||||
|
double the_n, the_sin2_t, the_cos_t;
|
||||||
|
the_n = m_n1 / m_n2;
|
||||||
|
the_sin2_t = std::pow(the_n, 2) * (1.0 - std::pow(the_cos, 2));
|
||||||
|
if (the_sin2_t > 1.0)
|
||||||
|
{
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute cosine of the theta_t using trig identity
|
||||||
|
the_cos_t = std::sqrt(1.0 - the_sin2_t);
|
||||||
|
the_cos = the_cos_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
the_r0 = std::pow(((m_n1 - m_n2) / (m_n1 + m_n2)), 2);
|
||||||
|
|
||||||
|
return the_r0 + (1 - the_r0) * std::pow((1 - the_cos), 5);
|
||||||
|
}
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ namespace Raytracer
|
|||||||
void set_n2(double an_n2);
|
void set_n2(double an_n2);
|
||||||
const double n2(void) const;
|
const double n2(void) const;
|
||||||
|
|
||||||
|
double schlick(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_is_inside;
|
bool m_is_inside;
|
||||||
double m_distance;
|
double m_distance;
|
||||||
|
|||||||
@@ -168,7 +168,8 @@ Color World::shade_hit(const IntersectionData &an_intersection_data, uint32_t a_
|
|||||||
Color the_surface = the_object->material().lighting(the_object, m_light, an_intersection_data.over_point(),
|
Color the_surface = the_object->material().lighting(the_object, m_light, an_intersection_data.over_point(),
|
||||||
an_intersection_data.eyev(), an_intersection_data.normalv(), the_shadowed);
|
an_intersection_data.eyev(), an_intersection_data.normalv(), the_shadowed);
|
||||||
Color the_reflected = reflected_color(an_intersection_data, a_remaining);
|
Color the_reflected = reflected_color(an_intersection_data, a_remaining);
|
||||||
return the_surface + the_reflected;
|
Color the_refracted = refracted_color(an_intersection_data, a_remaining);
|
||||||
|
return the_surface + the_reflected + the_refracted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
@@ -194,7 +195,7 @@ Color World::reflected_color(const IntersectionData &a_data, uint32_t a_remainin
|
|||||||
|
|
||||||
Color World::refracted_color(const IntersectionData &an_intersection_data, uint32_t a_remaining) const
|
Color World::refracted_color(const IntersectionData &an_intersection_data, uint32_t a_remaining) const
|
||||||
{
|
{
|
||||||
double the_n_ratio, the_cos_i, the_cos_t, the_sin_t;
|
double the_n_ratio, the_cos_i, the_cos_t, the_sin2_t;
|
||||||
Tuple the_direction;
|
Tuple the_direction;
|
||||||
Color the_color;
|
Color the_color;
|
||||||
double the_transparency;
|
double the_transparency;
|
||||||
@@ -218,14 +219,14 @@ Color World::refracted_color(const IntersectionData &an_intersection_data, uint3
|
|||||||
the_cos_i = an_intersection_data.eyev().dot(an_intersection_data.normalv());
|
the_cos_i = an_intersection_data.eyev().dot(an_intersection_data.normalv());
|
||||||
|
|
||||||
// Find sin(theta_t)^2 via trigonometric identity
|
// Find sin(theta_t)^2 via trigonometric identity
|
||||||
the_sin_t = the_n_ratio * the_n_ratio * (1.0 - the_cos_i * the_cos_i);
|
the_sin2_t = the_n_ratio * the_n_ratio * (1.0 - the_cos_i * the_cos_i);
|
||||||
if (the_sin_t > 1)
|
if (the_sin2_t > 1)
|
||||||
{
|
{
|
||||||
return Color(0, 0, 0);
|
return Color(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find cos(theta_t) via trigonometric identity
|
// Find cos(theta_t) via trigonometric identity
|
||||||
the_cos_t = std::sqrt(1.0 - the_sin_t);
|
the_cos_t = std::sqrt(1.0 - the_sin2_t);
|
||||||
|
|
||||||
// Compute the direction of the refracted ray
|
// Compute the direction of the refracted ray
|
||||||
the_direction = an_intersection_data.normalv() * (the_n_ratio * the_cos_i - the_cos_t) -
|
the_direction = an_intersection_data.normalv() * (the_n_ratio * the_cos_i - the_cos_t) -
|
||||||
|
|||||||
@@ -633,3 +633,153 @@ SCENARIO("The refracted color with a refracted ray", "[features/world.feature]")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
SCENARIO("shade_hit() with a transparent material", "[features/world.feature]")
|
||||||
|
{
|
||||||
|
GIVEN("w <- default_world()")
|
||||||
|
{
|
||||||
|
World w = World::default_world();
|
||||||
|
AND_GIVEN("floor <- plane() with:")
|
||||||
|
{
|
||||||
|
// | transform | translation(0, -1, 0) |
|
||||||
|
// | material.transparency | 0.5 |
|
||||||
|
// | material.refractive_index | 1.5 |
|
||||||
|
Plane floor;
|
||||||
|
floor.set_transform(Matrix::translation(0, -1, 0));
|
||||||
|
floor.material().set_transparency(0.5);
|
||||||
|
floor.material().set_refractive_index(1.5);
|
||||||
|
AND_GIVEN("floor is added to w")
|
||||||
|
{
|
||||||
|
w.add_object(&floor);
|
||||||
|
AND_GIVEN("ball <- sphere() with:")
|
||||||
|
{
|
||||||
|
// | material.color | (1, 0, 0) |
|
||||||
|
// | material.ambient | 0.5 |
|
||||||
|
// | transform | translation(0, -3.5, -0.5) |
|
||||||
|
Sphere ball;
|
||||||
|
ball.material().set_color(Color(1, 0, 0));
|
||||||
|
ball.material().set_ambient(0.5);
|
||||||
|
ball.set_transform(Matrix::translation(0, -3.5, -0.5));
|
||||||
|
AND_GIVEN("ball is added to w")
|
||||||
|
{
|
||||||
|
w.add_object(&ball);
|
||||||
|
AND_GIVEN("r <- ray(point(0, 0, -3), vector(0, -sqrt(2) / 2, sqrt(2) / 2))")
|
||||||
|
{
|
||||||
|
Ray r(Tuple::Point(0, 0, -3), Tuple::Vector(0, -sqrt(2) / 2, sqrt(2) / 2));
|
||||||
|
AND_GIVEN("xs <- intersections(sqrt(2):floor)")
|
||||||
|
{
|
||||||
|
Intersections xs = Intersections({Intersection(sqrt(2), &floor)});
|
||||||
|
WHEN("comps <- prepare_computations(xs[0], r, xs)")
|
||||||
|
{
|
||||||
|
IntersectionData comps = xs[0].prepare_computations(r, &xs);
|
||||||
|
AND_WHEN("color <- shade_hit(w, comps, 5)")
|
||||||
|
{
|
||||||
|
Color color = w.shade_hit(comps, 5);
|
||||||
|
THEN("color = color(0.93642, 0.68642, 0.68642)")
|
||||||
|
{
|
||||||
|
REQUIRE(color == Color(0.93642, 0.68642, 0.68642));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
SCENARIO("The Schlick approximation under total internal reflection", "[features/intersections.feature]")
|
||||||
|
{
|
||||||
|
GIVEN("shape <- glass_sphere()")
|
||||||
|
{
|
||||||
|
Sphere shape = Sphere::Glass();
|
||||||
|
AND_GIVEN("r <- ray(point(0, 0, sqrt(2) / 2)), vector(0, 1, 0)")
|
||||||
|
{
|
||||||
|
Ray r(Tuple::Point(0, 0, sqrt(2) / 2), Tuple::Vector(0, 1, 0));
|
||||||
|
AND_GIVEN("xs <- intersections(-sqrt(2) / 2):shape, sqrt(2) / 2):shape)")
|
||||||
|
{
|
||||||
|
Intersections xs = Intersections({Intersection(-sqrt(2) / 2, &shape),
|
||||||
|
Intersection(sqrt(2) / 2, &shape)});
|
||||||
|
WHEN("comps <- prepare_computations(xs[1], r, xs)")
|
||||||
|
{
|
||||||
|
IntersectionData comps = xs[1].prepare_computations(r, &xs);
|
||||||
|
AND_WHEN("reflectance <- schlick(comps)")
|
||||||
|
{
|
||||||
|
double reflectance = comps.schlick();
|
||||||
|
THEN("reflectance = 1.0")
|
||||||
|
{
|
||||||
|
REQUIRE(reflectance == 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
SCENARIO("The Schlick approximation with a perpendicular viewing angle", "[features/intersections.feature]")
|
||||||
|
{
|
||||||
|
GIVEN("shape <- glass_sphere()")
|
||||||
|
{
|
||||||
|
Sphere shape = Sphere::Glass();
|
||||||
|
AND_GIVEN("r <- ray(point(0, 0, 0), vector(0, 1, 0)")
|
||||||
|
{
|
||||||
|
Ray r(Tuple::Point(0, 0, 0), Tuple::Vector(0, 1, 0));
|
||||||
|
AND_GIVEN("xs <- intersections(-1:shape, 1:shape)")
|
||||||
|
{
|
||||||
|
Intersections xs = Intersections({Intersection(-1, &shape),
|
||||||
|
Intersection(1, &shape)});
|
||||||
|
WHEN("comps <- prepare_computations(xs[1], r, xs)")
|
||||||
|
{
|
||||||
|
IntersectionData comps = xs[1].prepare_computations(r, &xs);
|
||||||
|
AND_WHEN("reflectance <- schlick(comps)")
|
||||||
|
{
|
||||||
|
double reflectance = comps.schlick();
|
||||||
|
THEN("reflectance = 0.04")
|
||||||
|
{
|
||||||
|
REQUIRE(double_equal(reflectance, 0.04));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
SCENARIO("The Schlick approximation with a small angle and n2 > n1", "[features/intersections.feature]")
|
||||||
|
{
|
||||||
|
GIVEN("shape <- glass_sphere()")
|
||||||
|
{
|
||||||
|
Sphere shape = Sphere::Glass();
|
||||||
|
AND_GIVEN("r <- ray(point(0, 0.99, -2), vector(0, 0, 1)")
|
||||||
|
{
|
||||||
|
Ray r(Tuple::Point(0, 0.99, -2), Tuple::Vector(0, 0, 1));
|
||||||
|
AND_GIVEN("xs <- intersections(1.8589:shape)")
|
||||||
|
{
|
||||||
|
Intersections xs = Intersections({Intersection(1.8589, &shape)});
|
||||||
|
WHEN("comps <- prepare_computations(xs[0], r, xs)")
|
||||||
|
{
|
||||||
|
IntersectionData comps = xs[0].prepare_computations(r, &xs);
|
||||||
|
AND_WHEN("reflectance <- schlick(comps)")
|
||||||
|
{
|
||||||
|
double reflectance = comps.schlick();
|
||||||
|
THEN("reflectance = 0.48873")
|
||||||
|
{
|
||||||
|
REQUIRE(double_equal(reflectance, 0.48873));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user