' '

Difficulty

4

Prerequisites

ray-tracers/v1

Reading material

cameras/fisheye

def scene_at(now)
{
  var y = Animations.ease(Animations.animate(5, 0, seconds(5)), Easing.quintic_out())
  var z = Animations.animate(10, -20, seconds(5))

  var camera = Cameras.fisheye( [ "eye": pos(0, y[now], z[now]),
                                  "look_at": pos(0, 0, z[now] - 1),
                                  "up": vec(0, 1, 0),
                                  "horizontal_angle": degrees(270),
                                  "vertical_angle": degrees(180) ] )

  var white = Materials.uniform( [ "ambient": Colors.white() * 0.1,
                                   "diffuse": Colors.white() * 0.8,
                                   "specular": Colors.white(),
                                   "specular_exponent": 20,
                                   "reflectivity": 0,
                                   "transparency": 0,
                                   "refractive_index": 0 ] )

  var black = Materials.uniform( [ "ambient": Colors.black(),
                                   "diffuse": Colors.white() * 0.1,
                                   "specular": Colors.white(),
                                   "specular_exponent": 20,
                                   "reflectivity": 0,
                                   "transparency": 0,
                                   "refractive_index": 0 ] )

  var pattern = Patterns.checkered(1, 1)
  var checkered = Materials.from_pattern(pattern, black, white)

  var spheres   = []

  for_each([-2..5], bind(fun (i, spheres) {
                     spheres.push_back(translate(vec(-2,0,-i*3), sphere()))
                     spheres.push_back(translate(vec(2,0,-i*3), sphere()))
                   }, _, spheres))

  var spheres_union = decorate(white, union(spheres))

  var plane     = decorate(checkered, translate(vec(0,-1,0), xz_plane()))

  var root      = union( [spheres_union, plane] )

  var lights    = [ Lights.omnidirectional( pos(0, 5, 5), Colors.white() ) ]

  return create_scene(camera, root, lights)
}


var anim = scene_animation(scene_at, seconds(5))

var raytracer   = Raytracers.v6()

var renderer    = Renderers.standard( [ "width": 500,
                                        "height": 500,
                                        "sampler": Samplers.multijittered(3),
                                        "ray_tracer": raytracer ] )


pipeline( anim,
          [ Pipeline.animation(30),
            Pipeline.renderer(renderer),
            Pipeline.studio() ] )

1. Implementation

Start with the reading material mentioned in the overview above.

The parameters for a fisheye camera are

  • Its eye.

  • Its look_at point.

  • Its up vector.

  • Its horizontal angle, type Angle.

  • Its vertical angle, type Angle.

Create the files cameras/fisheye-camera.cpp and cameras/fisheye-camera.h. We suggest you copy paste the code from perspective cameras to these files and modify them as necessary.

Following things might prove useful for implementing fisheye cameras are

  • math::Interval and math::IntervalMapper to translate \([0, 1\)] to \([\alpha, \beta\)].

  • Point3D::spherical to create a point given spherical coordinates.

2. Evaluation

Render the following scene:

def material(c)
{
  Materials.uniform( [ "ambient": c ] )
}

def scene_at(now)
{
  var t = Animations.animate(0, 1, seconds(5))[now]

  var camera = Cameras.fisheye( [ "eye": pos(0, 10-10*t, 1),
                                  "look_at": pos(0, 0, 0),
                                  "horizontal_angle": degrees(90+270*t),
                                  "vertical_angle": degrees(180) ] )

  var primitives = [ ]

  for ( var i = 0; i != 16; i += 1 ) {
    var v = Vec.cylindrical_y(5, degrees(360.0 / 16 * i), 0)
    var v2 = Vec.cylindrical_y(10, degrees(360.0 / 16 * i), 5)
    var alpha = i / 16.0 * 360.0
    var c1 = (sin(degrees(alpha)) + 1.0) / 2.0
    var c2 = (cos(degrees(alpha)) + 1.0) / 2.0
    var c3 = (sin(2*degrees(alpha)) + 1.0) / 2.0
    var m = material(RGB(c1, c2, c3))
    var m2 = material(RGB(1-c1, c2, 1-c3))
    primitives.push_back( decorate(m, translate(v, sphere())) )
    primitives.push_back( decorate(m2, translate(v2, sphere())) )
  }


  var root      = union( primitives )

  var lights    = [ ]

  return create_scene(camera, root, lights)
}


var anim = scene_animation(scene_at, seconds(5))

var raytracer   = Raytracers.v1()

var renderer    = Renderers.standard( [ "width": 500,
                                        "height": 500,
                                        "sampler": Samplers.single(),
                                        "ray_tracer": raytracer ] )


pipeline( anim,
          [ Pipeline.animation(30),
            Pipeline.renderer(renderer),
            Pipeline.studio() ] )