' '

Difficulty

2

Prerequisites

ray-tracers/v4

samplers/random

Reading material

lights/area

def scene_at(now)
{
  var camera = Cameras.perspective( [ "eye": pos(0,4,8),
                                      "look_at": pos(0,0,0) ] )

  var sphere_material = Materials.uniform( [ "ambient": Colors.white() * 0.1,
                                             "diffuse": Colors.white() * 0.8,
                                             "specular": Colors.white(),
                                             "specular_exponent": 100 ] )

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


  var root = union([ decorate(plane_material, translate(vec(0,-1,0), xz_plane())),
                     decorate(sphere_material, sphere()) ])

  var t = Animations.animate(degrees(0), degrees(360), seconds(1))[now]

  var light_position = Animations.circular( [ "position": pos(-3, 3, 2),
                                              "around": pos(0, 3, 0),
                                              "duration": seconds(5) ] )

  var lights = [ Lights.area( rect3d(light_position[now], vec(0.5,0,0), vec(0,0,0.5)), Samplers.multijittered(8), Colors.white() ) ]

  create_scene(camera, root, lights)
}


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

pipeline( scene_animation(scene_at, seconds(5)),
          [ Pipeline.animation(30),
            Pipeline.renderer(renderer),
            Pipeline.studio() ] )

1. Implementation

Read the explanations on area lights first.

An area light has the following properties:

  • A Rectangle3D defining its area.

  • A sampler, which will be used to determine which points from the area will be used as light sources.

  • A color.

The area light operates as follows: when asked for a list of LightRays that reach a given Point3D P, it asks the sampler to pick points \(L_i\) from its area. For each such point, it creates a LightRay starting in \(L_i\) going through \(P\). Note that it is important that the ray has to be created in such a way that \(t = 0\) coincides with \(L_i\) and \(t = 1\) with \(P\), otherwise the shadowing algorithm will not work.

Implement area lights.

Tip
wrong

If you get the result shown above, well, then you did something wrong.

Remember that we are faking an area light by creating a number of point lights. Say the area light should be 100 Watt. We are replacing it by 10 smaller light sources. Should each of these 10 light sources shine at a full 100W?

2. Evaluation

Render the following scene:

def scene_at(now)
{
    var camera = Cameras.perspective( [ "eye": pos(0,4,8),
                                    "look_at": pos(0,0,0) ] )

    var sphere_material = Materials.uniform( [ "ambient": Colors.white() * 0.1,
                                               "diffuse": Colors.white() * 0.8,
                                               "specular": Colors.white(),
                                               "specular_exponent": 100 ] )

    var plane_material = Materials.uniform( [ "ambient": Colors.white() * 0.1,
                                              "diffuse": Colors.white() * 0.8,
                                              "specular": Colors.black(),
                                              "specular_exponent": 0 ] )


    var root = union([ decorate(plane_material, translate(vec(0,0,-1), xy_plane())),
                       decorate(sphere_material, sphere()) ])

    var t = Animations.animate(0, 1, seconds(5))[now]
    var rect = rect3d(pos(-3 + 0.25 - 0.25*t, 3 + 0.25 - 0.25*t, 2),
                      vec(0.5 * t,0,0),
                      vec(0,0.5 * t,0))
    var lights = [ Lights.area( rect, Samplers.random(100), Colors.white() ) ]

    create_scene(camera, root, lights)
}


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

pipeline( scene_animation(scene_at, seconds(5)),
          [ Pipeline.animation(30),
            Pipeline.renderer(renderer),
            Pipeline.wif(),
            Pipeline.base64(),
            Pipeline.stdout() ] )

Notice the soft shadow.