diff --git a/README.md b/README.md index db89468..8acde64 100644 --- a/README.md +++ b/README.md @@ -17,101 +17,83 @@ as texture, also use [NanoJPEG](https://keyj.emphy.de/nanojpeg/) to use jpeg fil Examples outputs ---------------- -**From chapter 05 - Sphere intersections:** - +#### From chapter 05 - Sphere intersections: ![Chapter 5 rendering test](output/ch5_test.png) -**From Chapter 06 - Phong shading:** - +#### From Chapter 06 - Phong shading: ![Chapter 6 rendering test](output/ch6_test.png) -**From Chapter 07 - World / Camera / Scenes:** - +#### From Chapter 07 - World / Camera / Scenes: ![Chapter 7 rendering test](output/ch7_test.png) -**From Chapter 08 - Shadows:** - +#### From Chapter 08 - Shadows: ![Chapter 8 rendering test](output/ch8_test.png) -**From Chapter 09 - Planes:** - +#### From Chapter 09 - Planes: ![Chapter 9 rendering test](output/ch9_test.png) -**From Chapter 10 - Patterns:** - +#### From Chapter 10 - Patterns: ![Chapter 10 rendering test](output/ch10_test.png) -**From Chapter 11 - Reflections, Transparency & Refractions:** - +#### From Chapter 11 - Reflections, Transparency & Refractions: ![Chapter 11 reflections rendering test](output/ch11_reflection.png) -Bonus: Zooming on a reflective ball: +###### Bonus: Zooming on a reflective ball: ![Chapter 11 zooming on a ball](output/ch11_zooming_on_reflective_ball.png) -Zooming on a reflection on that ball: +###### Zooming on a reflection on that ball: ![Chapter 11 zooming on a reflection](output/ch11_reflection_on_ball.png) ![Chapter 11 refraction rendering test](output/ch11_refraction.png) ![Chapter 11 rendering test](output/ch11_test.png) -**From Chapter 12 - Cubes:** - +#### From Chapter 12 - Cubes: ![Chapter 12 rendering test](output/ch12_test.png) -**From Chapter 13 - Cylinders:** - +#### From Chapter 13 - Cylinders: ![Chapter 13 rendering test](output/ch13_test.png) -Bonus: +###### Bonus: ![Chapter 13 cone test](output/ch13_cone.png) -**From Chapter 14 - Groups & Bounding boxes:** +#### From Chapter 14 - Groups & Bounding boxes: ![Chapter 14 rendering test](output/ch14_test.png) -**From Chapter 15 - Triangles, Wavefrom OBJ files - Smooth trianges:** +#### From Chapter 15 - Triangles, Wavefrom OBJ files - Smooth trianges: ![Chapter 15 Triangles and teapots](output/ch15_teapot_objfile.png) -**Bonus (from the forum):** +#### From Chapter 16 - Constructive Solid Geomety: +![Chapter 16 CSG](output/ch16_test.png) +#### Bonus (from the forum): [Merry Christmas](https://forum.raytracerchallenge.com/thread/16/merry-christmas-scene-description) ![Merry Christmas](output/christmasball.png) - (about 1min render time using OpenMP on a 2.6Ghz Core i7 3720QM) -**Bonus chapter - Soft shadow / Area light** - -Without jitter: +#### Bonus chapter - Soft shadow / Area light +###### Without jitter: ![Area light without jitter](output/arealight_test_nojitter.png) - -With jitter: +###### With jitter: ![Area light witht jitter](output/arealight_test.png) -**Bonus chapter - Texture mapping** - -Spherical mapping: - +#### Bonus chapter - Texture mapping +###### Spherical mapping: ![Spherical mapping](output/uvmap_checkeredsphere.png) -Planar mapping: - +######Planar mapping: ![Planar mapping](output/uvmap_checkeredplane.png) -Cylindrical mapping: - +###### Cylindrical mapping: ![Cylindrical mapping](output/uvmap_checkeredcylinder.png) -Aligncheck plane: - +###### Aligncheck plane: ![Aligncheck plane](output/uvmap_aligncheckplane.png) -Cubical mapping: - +###### Cubical mapping: ![Cubical mapping](output/uvmap_checkeredcube.png) -Image mapping: - +###### Image mapping: ![Image mapping](output/uvmap_earth.png) -Skybox: - +###### Skybox: ![Skybox](output/uvmap_skybox.png) \ No newline at end of file diff --git a/output/ch16_test.png b/output/ch16_test.png new file mode 100644 index 0000000..c385d3b Binary files /dev/null and b/output/ch16_test.png differ diff --git a/source/canvas.cpp b/source/canvas.cpp index 208eb46..e4f03bb 100644 --- a/source/canvas.cpp +++ b/source/canvas.cpp @@ -132,12 +132,12 @@ Canvas::~Canvas() } } -void Canvas::putPixel(uint32_t x, uint32_t y, Tuple colour) +void Canvas::putPixel(uint32_t x, uint32_t y, Tuple c) { uint32_t offset = y * this->stride + x * BytePP; - this->bitmap[offset + 0] = MAX(MIN(colour.x * 255, 255), 0); - this->bitmap[offset + 1] = MAX(MIN(colour.y * 255, 255), 0); - this->bitmap[offset + 2] = MAX(MIN(colour.z * 255, 255), 0); + this->bitmap[offset + 0] = MAX(MIN(c.x * 255, 255), 0); + this->bitmap[offset + 1] = MAX(MIN(c.y * 255, 255), 0); + this->bitmap[offset + 2] = MAX(MIN(c.z * 255, 255), 0); } Colour Canvas::getPixel(uint32_t x, uint32_t y) diff --git a/source/include/csg.h b/source/include/csg.h index 51f505f..4b34400 100644 --- a/source/include/csg.h +++ b/source/include/csg.h @@ -42,6 +42,8 @@ protected: public: CSG(OperationType operation, Shape *left, Shape *right); + Intersect intersect(Ray r); + bool includes(Shape *b); void updateTransform(); diff --git a/source/intersection.cpp b/source/intersection.cpp index 20d0249..a63e1f5 100644 --- a/source/intersection.cpp +++ b/source/intersection.cpp @@ -45,7 +45,7 @@ Computation Intersection::prepareComputation(Ray r, Intersect *xs) if ((xs != nullptr) && (xs->hit().object->material.transparency > 0)) { List containers; - int j, k; + int j; for (j = 0 ; j < xs->count() ; j++) { diff --git a/source/shapes/csg.cpp b/source/shapes/csg.cpp index ce11bc7..5d193c0 100644 --- a/source/shapes/csg.cpp +++ b/source/shapes/csg.cpp @@ -40,6 +40,11 @@ Intersect CSG::localIntersect(Ray r) return ret; } +Intersect CSG::intersect(Ray r) +{ + return localIntersect(r); +} + Tuple CSG::localNormalAt(Tuple point, Intersection *hit) { return Vector(1, 0, 0); diff --git a/source/shapes/group.cpp b/source/shapes/group.cpp index d040135..2839e18 100644 --- a/source/shapes/group.cpp +++ b/source/shapes/group.cpp @@ -18,11 +18,11 @@ Group::Group() : Shape(SHAPE_GROUP) { stats.addGroup(); this->allocatedObjectCount = MIN_ALLOC; - this->objectList = (Shape **)calloc(sizeof(Shape *), MIN_ALLOC); + this->objectList = (Shape **)calloc(sizeof(Shape **), MIN_ALLOC); this->objectCount = 0; this->allocatedUnboxableObjectCount = MIN_ALLOC; - this->unboxableObjectList = (Shape **)calloc(sizeof(Shape *), MIN_ALLOC); + this->unboxableObjectList = (Shape **)calloc(sizeof(Shape **), MIN_ALLOC); this->unboxableObjectCount = 0; } diff --git a/source/shapes/light.cpp b/source/shapes/light.cpp index 5cb5ecb..ff7d5b8 100644 --- a/source/shapes/light.cpp +++ b/source/shapes/light.cpp @@ -41,7 +41,6 @@ double Light::intensityAt(World &w, Tuple point) } } return total / this->samples; - break; } } diff --git a/source/shapes/objfile.cpp b/source/shapes/objfile.cpp index 2db80ae..2b68c1a 100644 --- a/source/shapes/objfile.cpp +++ b/source/shapes/objfile.cpp @@ -299,7 +299,6 @@ static int parseFaceVertex(char *buf, uint32_t &v, uint32_t &vt, uint32_t &vn) { uint32_t bufPos = 0; uint32_t lineLength = strlen(buf); - char *tmp = buf; vt = INT32_MAX; vn = INT32_MAX; int ret = 0; diff --git a/tests/ch16_test.cpp b/tests/ch16_test.cpp index 56e2589..101249a 100644 --- a/tests/ch16_test.cpp +++ b/tests/ch16_test.cpp @@ -33,21 +33,37 @@ int main() World w = World(); /* Add lights */ - Light light1 = Light(POINT_LIGHT, Point(100, 100, -100), Colour(1, 1, 1)); + Light light1 = Light(POINT_LIGHT, Point(6, 10, 10), Colour(0.5, 0.4, 0.5)); w.addLight(&light1); + /* Add lights */ + Light light2 = Light(POINT_LIGHT, Point(6, 10, -2.5), Colour(0.5, 0.6, 0.5)); + w.addLight(&light2); + /* ----------------------------- */ - /* White background */ + /* Floor */ Plane p = Plane(); - p.setTransform(translation(0, 0, 100) * rotationX(1.5708)); - p.material.colour = Colour(1, 1, 1); - p.material.ambient = 1; - p.material.diffuse = 0; + CheckersPattern checkered = CheckersPattern(Colour(0.35, 0.35, 0.35), Colour(0.4, 0.4, 0.4)); + p.material.pattern = &checkered; + p.material.ambient = 0.2; + p.material.diffuse = 1; p.material.specular = 0; + p.material.reflective = 0.1; + p.setTransform(translation(0, 0, 0)); w.addObject(&p); + Plane p2 = Plane(); + p2.setTransform(translation(0, 0, -3) * rotationX(M_PI/2)); + p2.material.pattern = &checkered; + p2.material.ambient = 0.2; + p2.material.diffuse = 1; + p2.material.specular = 0; + w.addObject(&p2); + /* ----------------------------- */ + + /* Funky cube */ Cylinder c1 = Cylinder(); c1.minCap = -2; c1.maxCap = 2; @@ -77,22 +93,95 @@ int main() CSG leaf2 = CSG(CSG::UNION, &leaf1, &c3); Cube cb = Cube(); - //cb.materialSet = true; - //cb.material.reflective = 1; + cb.materialSet = true; + cb.material.reflective = 0.5; + cb.material.colour = Colour(0.3, 0.3, 0.3); + cb.material.ambient = 0; + cb.material.diffuse = 0.3; + cb.material.specular = 0.3; + cb.material.shininess = 20; Sphere sp = Sphere(); sp.setTransform(scaling(1.35, 1.35, 1.35)); + sp.materialSet = true; + sp.material.colour = Colour(0, 0, 0); + sp.material.ambient = 0; + sp.material.specular = 0.3; + sp.material.shininess = 20; + sp.material.reflective = 0.05; + sp.material.diffuse = 0.3; CSG leaf3 = CSG(CSG::INTERSECTION, &sp, &cb); CSG leaf4 = CSG(CSG::DIFFERENCE, &leaf3, &leaf2); - + leaf4.setTransform(translation(0, 1, 0.8) * rotationY(-0.45)); w.addObject(&leaf4); /* ----------------------------- */ + /* Tricylinder weirdy */ + Cylinder sp1 = Cylinder(); + sp1.minCap = -2; + sp1.maxCap = 2; + sp1.isClosed = true; + sp1.materialSet = true; + sp1.material.colour = Colour(1, 0, 0); + Cylinder sp2 = Cylinder(); + sp2.minCap = -2; + sp2.maxCap = 2; + sp2.isClosed = true; + sp2.materialSet = true; + sp2.setTransform(rotationX(M_PI/2)); + sp2.material.colour = Colour(0, 1, 0); + Cylinder sp3 = Cylinder(); + sp3.minCap = -2; + sp3.maxCap = 2; + sp3.isClosed = true; + sp3.materialSet = true; + sp3.setTransform(rotationZ(M_PI/2)); + sp3.material.colour = Colour(0, 0, 1); + + CSG spleaf1 = CSG(CSG::INTERSECTION, &sp1, &sp2); + CSG spleaf2 = CSG(CSG::INTERSECTION, &spleaf1, &sp3); + + spleaf2.setTransform(translation(4, 1, -0.1) * rotationY(0.35)); + w.addObject(&spleaf2); + + /* ----------------------------- */ + + Group grp = Group(); + int i; +#define SLICE_NUM (12) + for(i = 0; i < SLICE_NUM; i++) + { + Cube *c = new Cube(); + + c->setTransform(rotationY((2*M_PI / SLICE_NUM) * i) * scaling(0.1, 1.1, 0.7) * translation(0, 0, 0.9)); + c->dropShadow = false; + grp.addObject(c); + } + + grp.materialSet = true; + grp.dropShadow = false; + grp.material.ambient = 0; + grp.material.diffuse = 0.1; + grp.material.specular = 0; + grp.material.transparency = 1; + grp.material.reflective = 1; + grp.material.refractiveIndex = 1; + + Sphere ballSp = Sphere(); + ballSp.materialSet = true; + ballSp.material.colour = Colour(0.7, 0.2, 0.1); + CSG ballLeaf = CSG(CSG::INTERSECTION, &grp, &ballSp); + + ballLeaf.setTransform(translation(-4, 1, -0.1) * rotationY(-0.35) * rotationZ(0.1)); + w.addObject(&ballLeaf); + + /* ----------------------------- */ + /* Set the camera */ - Camera camera = Camera(800, 400, M_PI / 2); - camera.setTransform(viewTransform(Point(-4, 4, -9), + Camera camera = Camera(80, 40, M_PI / 2); + camera.setTransform(viewTransform(Point(0, 3, 5), Point(0, 1, 0), Vector(0, 1, 0))); diff --git a/tests/cylinder_test.cpp b/tests/cylinder_test.cpp index c99ba0b..81d85e7 100644 --- a/tests/cylinder_test.cpp +++ b/tests/cylinder_test.cpp @@ -59,7 +59,7 @@ TEST(CylinderTest, A_ray_hit_a_cylinder) double t0s[] = { 5, 4, 6.80798 }; double t1s[] = { 5, 6, 7.08872 }; - int i, j; + int i; for(i = 0; i < 3; i++) { Tuple direction = Directions[i].normalise(); diff --git a/tests/plane_test.cpp b/tests/plane_test.cpp index 36aee8a..8d943d8 100644 --- a/tests/plane_test.cpp +++ b/tests/plane_test.cpp @@ -73,7 +73,6 @@ TEST(PlaneTest, A_ray_intersecting_a_plane_from_below) TEST(PlaneTest, The_bounding_box_of_a_plane) { Plane t = Plane(); - BoundingBox b = BoundingBox(Point(-8, -5, -8), Point(8, 8, 8)); BoundingBox res = t.getBounds(); ASSERT_FALSE(res.min.isRepresentable()); diff --git a/tests/test_render.cpp b/tests/test_render.cpp index 827a66b..a3ecb42 100644 --- a/tests/test_render.cpp +++ b/tests/test_render.cpp @@ -54,7 +54,7 @@ int main() Plane p4 = Plane(); p3.setTransform(translation(6, 0, 0) * rotationZ(M_PI/2) ); p3.material.pattern = new CheckersPattern(Colour(1, 1, 1), Colour(0.1, 0.1, 0.1)); - w.addObject(&p3); + w.addObject(&p4); Plane p5 = Plane(); p5.material.pattern = new CheckersPattern(Colour(1, 1, 1), Colour(0.1, 0.1, 0.1)); diff --git a/tests/uvmap_skybox.cpp b/tests/uvmap_skybox.cpp index f463e92..bf54b12 100644 --- a/tests/uvmap_skybox.cpp +++ b/tests/uvmap_skybox.cpp @@ -31,7 +31,7 @@ int main() Light light = Light(POINT_LIGHT, Point(0, 100, 0), Colour(1, 1, 1)); w.addLight(&light); - Sphere sp = Sphere();; + Sphere sp = Sphere(); sp.setTransform(translation(0, 0, 5) * scaling(0.75, 0.75, 0.75)); sp.material.diffuse = 0.4; sp.material.specular = 0.6; diff --git a/tests/world_test.cpp b/tests/world_test.cpp index 36ee043..0564a83 100644 --- a/tests/world_test.cpp +++ b/tests/world_test.cpp @@ -44,7 +44,7 @@ TEST(WorldTest, The_default_world) ASSERT_TRUE(w.lightIsIn(l)); ASSERT_TRUE(w.objectIsIn(s1)); ASSERT_TRUE(w.objectIsIn(s2)); -}; +} TEST(WorldTest, Intersect_a_world_with_a_ray) { @@ -169,7 +169,7 @@ TEST(WorldTest, Shade_hit_is_given_an_intersection_in_shadow) Tuple c = w.shadeHit(comps); ASSERT_EQ(c, Colour(0.1, 0.1, 0.1)); -}; +} TEST(WorldTest, The_reflected_colour_for_a_non_reflective_material) {