Refraction seems to work. Still need to do a nice scene.

This commit is contained in:
Godzil
2020-02-21 22:50:12 +00:00
parent df52cb36db
commit 3db0aaaeac
9 changed files with 274 additions and 16 deletions

View File

@@ -49,9 +49,15 @@ target_include_directories(ch11_reflection PUBLIC ../source/include)
target_sources(ch11_reflection PRIVATE ch11_reflection.cpp)
target_link_libraries(ch11_reflection rayonnement)
add_executable(ch11_refractiontest)
target_include_directories(ch11_refractiontest PUBLIC ../source/include)
target_sources(ch11_refractiontest PRIVATE ch11_refractiontest.cpp)
target_link_libraries(ch11_refractiontest rayonnement)
add_test(NAME Chapter05_Test COMMAND $<TARGET_FILE:ch5_test>)
add_test(NAME Chapter06_Test COMMAND $<TARGET_FILE:ch6_test>)
add_test(NAME Chapter07_Test COMMAND $<TARGET_FILE:ch7_test>)
add_test(NAME Chapter09_Test COMMAND $<TARGET_FILE:ch9_test>)
add_test(NAME Chapter10_Test COMMAND $<TARGET_FILE:ch10_test>)
add_test(NAME Chapter11_Reflection COMMAND $<TARGET_FILE:ch11_reflection>)
add_test(NAME Chapter11_RefractionTest COMMAND $<TARGET_FILE:ch11_refractiontest>)

View File

@@ -0,0 +1,76 @@
/*
* DoRayMe - a quick and dirty Raytracer
* Render test for reflection in chapter 11.
*
* Created by Manoël Trapier
* Copyright (c) 2020 986-Studio.
*
*/
#include <world.h>
#include <light.h>
#include <sphere.h>
#include <plane.h>
#include <material.h>
#include <colour.h>
#include <canvas.h>
#include <camera.h>
#include <pattern.h>
#include <strippattern.h>
#include <gradientpattern.h>
#include <checkerspattern.h>
#include <ringpattern.h>
#include <transformation.h>
int main()
{
World w = World();
/* First we need to construct the world */
Plane floor = Plane();
floor.material.specular = 0;
floor.material.pattern = new CheckersPattern(Colour(1, 1, 1), Colour(0, 0, 0));
floor.material.pattern->setTransform(scaling(0.7, 0.7, 0.7));
floor.setTransform(translation(0, -3, 0));
w.addObject(&floor);
/* Add some more reflective spheres */
Sphere glassBall = Sphere();
glassBall.setTransform(scaling(1.5, 1.5, 1.5));
glassBall.material.refractiveIndex = 1.5;
glassBall.material.transparency = 1.0;
w.addObject(&glassBall);
Sphere airBubble = Sphere();
airBubble.setTransform( scaling(0.9, 0.9, 0.9));
airBubble.material.specular = 0;
airBubble.material.ambient = 0;
airBubble.material.refractiveIndex = 1.00029;
airBubble.material.transparency = 1.0;
w.addObject(&airBubble);
/* Add light */
Light light = Light(POINT_LIGHT, Point(-10, 20, -10), Colour(1, 1, 1));
w.addLight(&light);
/* Set the camera */
Camera camera = Camera(1000, 1000, M_PI / 3);
#if 0
camera.setTransform(viewTransform(Point(0, 1.5, -5),
Point(0, 1, 0),
Vector(0, 1, 0)));
#else
camera.setTransform(viewTransform(Point(0, 3.6, 0),
Point(0, 0, 0),
Vector(0, 0, 1)));
#endif
/* Now render it */
Canvas image = camera.render(w);
image.SaveAsPNG("ch11_refractiontest.png");
return 0;
}

View File

@@ -205,7 +205,6 @@ TEST(IntersectTest, Precomputing_the_reflection_vector)
TEST(IntersectTest, Finding_n1_and_n2_at_various_intersections)
{
#if 0
int i;
double n1_res[6] = { 1.0, 1.5, 2.0, 2.5, 2.5, 1.5 };
double n2_res[6] = { 1.5, 2.0, 2.5, 2.5, 1.5, 1.0 };
@@ -233,9 +232,25 @@ TEST(IntersectTest, Finding_n1_and_n2_at_various_intersections)
for(i = 0; i < xs.count(); i++)
{
Computation comps = xs[i].prepareComputation(r, &xs);
Intersection inter = xs[i];
Computation comps = inter.prepareComputation(r, &xs);
ASSERT_EQ(comps.n1, n1_res[i]);
ASSERT_EQ(comps.n2, n2_res[i]);
}
#endif
}
TEST(IntersectTest, The_under_point_is_offset_below_the_surface)
{
Ray r = Ray(Point(0, 0, -5), Vector(0, 0, 1));
GlassSphere shape = GlassSphere();
shape.setTransform(translation(0, 0, 1));
Intersection i = Intersection(5, &shape);
Intersect xs = Intersect();
xs.add(i);
Computation comps = i.prepareComputation(r, &xs);
ASSERT_TRUE(double_equal(comps.underHitPoint.z, getEpsilon() / 2));
ASSERT_LT(comps.hitPoint.z, comps.underHitPoint.z);
}

View File

@@ -12,6 +12,7 @@
#include <material.h>
#include <transformation.h>
#include <worldbuilder.h>
#include <testpattern.h>
#include <math.h>
#include <gtest/gtest.h>
#include <plane.h>
@@ -255,6 +256,8 @@ TEST(WorldTest, Colour_at_with_mutually_reflective_surfaces)
/* It should just exit, we don't care about the actual colour */
w.colourAt(r);
SUCCEED();
}
TEST(WorldTest, The_reflected_colour_at_the_maximum_recursion_depth)
@@ -273,4 +276,120 @@ TEST(WorldTest, The_reflected_colour_at_the_maximum_recursion_depth)
/* Temporary lower the precision */
ASSERT_EQ(colour, Colour(0, 0, 0));
}
TEST(WorldTest, The_refracted_colour_with_an_opaque_surface)
{
World w = DefaultWorld();
Shape *shape = w.getObject(0);
Ray r = Ray(Point(0, 0, -5), Vector(0, 0, 1));
Intersect xs = Intersect();
xs.add(Intersection(4, shape));
xs.add(Intersection(6, shape));
Computation comps = xs[0].prepareComputation(r, &xs);
Colour c = w.refractedColour(comps, 5);
ASSERT_EQ(c, Colour(0, 0, 0));
}
TEST(WorldTest, The_refracted_colour_at_the_maximum_recursive_depth)
{
World w = DefaultWorld();
Shape *shape = w.getObject(0);
shape->material.transparency = 1.0;
shape->material.refractiveIndex = 1.5;
Ray r = Ray(Point(0, 0, -5), Vector(0, 0, 1));
Intersect xs = Intersect();
xs.add(Intersection(4, shape));
xs.add(Intersection(6, shape));
Computation comps = xs[0].prepareComputation(r, &xs);
Colour c = w.refractedColour(comps, 0);
ASSERT_EQ(c, Colour(0, 0, 0));
}
TEST(WorldTest, The_refracted_colour_under_total_internal_reflection)
{
World w = DefaultWorld();
Shape *shape = w.getObject(0);
shape->material.transparency = 1.0;
shape->material.refractiveIndex = 1.5;
Ray r = Ray(Point(0, 0, sqrt(2)/2), Vector(0, 1, 0));
Intersect xs = Intersect();
xs.add(Intersection(-sqrt(2)/2, shape));
xs.add(Intersection(sqrt(2)/2, shape));
Computation comps = xs[1].prepareComputation(r, &xs);
Colour c = w.refractedColour(comps, 5);
ASSERT_EQ(c, Colour(0, 0, 0));
}
TEST(WorldTest, The_refracted_coloud_with_a_refracted_ray)
{
World w = DefaultWorld();
Shape *A = w.getObject(0);
A->material.ambient = 1.0;
A->material.pattern = new TestPattern();
Shape *B = w.getObject(1);
B->material.transparency = 1.0;
B->material.refractiveIndex = 1.5;
Ray r = Ray(Point(0, 0, 0.1), Vector(0, 1, 0));
Intersect xs = Intersect();
xs.add(Intersection(-0.9899, A));
xs.add(Intersection(-0.4899, B));
xs.add(Intersection(0.4899, B));
xs.add(Intersection(0.9899, A));
Computation comps = xs[2].prepareComputation(r, &xs);
Colour c = w.refractedColour(comps, 5);
/* Temporary lower the precision */
set_equal_precision(0.00005);
ASSERT_EQ(c, Colour(0, 0.99888, 0.04725));
set_equal_precision(FLT_EPSILON);
}
TEST(WorldTest, Shade_hit_with_a_transparent_material)
{
World w = DefaultWorld();
Plane floor = Plane();
floor.setTransform(translation(0, -1, 0));
floor.material.transparency = 0.5;
floor.material.refractiveIndex = 1.5;
w.addObject(&floor);
Sphere ball = Sphere();
ball.material.colour = Colour(1, 0, 0);
ball.material.ambient = 0.5;
ball.setTransform(translation(0, -3.5, -0.5));
w.addObject(&ball);
Ray r = Ray(Point(0, 0, -3), Vector(0, -sqrt(2)/2, sqrt(2)/2));
Intersect xs = Intersect();
xs.add(Intersection(sqrt(2), &floor));
Computation comps = xs[0].prepareComputation(r, &xs);
Tuple c = w.shadeHit(comps, 5);
/* Temporary lower the precision */
set_equal_precision(0.00001);
ASSERT_EQ(c, Colour(0.93642, 0.68642, 0.68642));
set_equal_precision(FLT_EPSILON);
}