// Persistence of Vision Ray Tracer Scene Description File // File: raytracing tests.pov // Vers: 3.5 // Desc: my second attempt at mimicking test scenes used at // http://www.cs.utah.edu/~bes/papers/scenes/paper-node3.html // Date: 2002.649 // Auth: Bob Hughes // Note: text in comments are descriptions copied from originating web pages // You would really need to see the web page examples for comparison. //cmd:+w256 +h256 +a0.0 +j0.0 +oC:\images\test-1 #version 3.5; /* 1=emission, 2=shadow, 3=large spatial extent, 4=complex illumination paths, 5=geometric accuracy */ #declare Test=2; // which? /* test 1 is much faster using +a not +a0.0 */ #declare Reflect=yes; // only used with test 4 global_settings { radiosity { count 150 error_bound 1 brightness 1.25 // increase to 3 when doing test 4 recursion_limit 2 } #if (Reflect=yes) photons { spacing 0.005 autostop 0 } #end } // TEXTURES #declare PlainBlack_T= texture { pigment { color rgb 1 } finish { ambient 0.1 diffuse 0.6 } } #declare PlainWhite_T= texture { pigment { color rgb 1 } finish { ambient 0.1 diffuse 0.6 } } #declare PlainWhiteBright_T= texture { pigment { color rgb 1 } finish { ambient 1 diffuse 1 } } #declare PlainDiffuse_T= texture { pigment { color rgb 1 } finish { ambient 0.1 diffuse 1 } } #declare NormalDiffuse_T= texture { pigment { color rgb 1 } normal { bumps 1 } finish { ambient 0.1 diffuse 1 } } #declare PlainReflect_T= texture { pigment { color rgb 0 } finish { ambient 0 diffuse 0 reflection { 1,1 } } } // TEST SCENES #switch (Test) #case (1) /* Emission: This scene is composed of two rectangular lights illuminating a ground plane. The right rectangular lights is tessellated into 10 by 10 polygons, and the left is a single polygon (Figure 1). The scene tests accurate unoccluded transfer from lights to receivers. In particular, it checks sampling algorithms and that the effect of the 100 small lights is equal to the single large light. The symmetry of the image allows a simple sanity check by flipping the image across the vertical axis and comparing it with itself. Most algorithm methods should be able to compute an arbitrarily accurate solution to this environment given enough time. Mesh-based approaches may have some trouble with the singularity at the corners, and algorithms that draw samples from the light may have trouble as the distance to the light goes to zero. */ camera { location 12.5*y right x up y sky y look_at 0 } box { -1,1 texture { PlainWhite_T } scale <10,0.5,10> translate -y/2 } // LIGHTING #declare SinglepartPoly= polygon { 5, <-1,-1>, <1,-1>, <1,1>, <-1,1>, <-1,-1> texture { PlainWhiteBright_T } interior_texture { PlainBlack_T } rotate 90*y } light_source { 0, 1 looks_like { SinglepartPoly } spotlight point_at x radius 1 falloff 90 area_light <0,1,0>, <0,0,1>, 3, 3 jitter adaptive 0 fade_distance 2 fade_power 1 translate <-5,1,0> } #declare LittlePoly= polygon { 5, <-1,-1>, <1,-1>, <1,1>, <-1,1>, <-1,-1> texture { PlainWhiteBright_T } interior_texture { PlainBlack_T } scale 0.1 rotate -90*y } #declare MultipartPoly= union { #declare i=1; #while (i>-1) #declare j=1; #while (j>-1) light_source { 0, 0.01 looks_like { LittlePoly } spotlight point_at -x radius 1 falloff 90 area_light <0,0.1,0>, <0,0,0.1>, 3, 3 jitter adaptive 0 fade_distance 2 fade_power 1 translate <0,j,i> } #declare j=j-0.2; #end #declare i=i-0.2; #end } object { MultipartPoly translate <5,1,0> } #break #case (2) /* Shadow: This scene tests accurate transfer in the presence of occluders. It contains a single light source, 8 long beams, and a ground plane (Figure 2). The light is rotated so that it is parallel to the plane formed by the tops of the lower set of beams and so that its edges are parallel with the major edges of the lower set of beams. The height between the occluding objects and the floor varies from penetrating the ground plane to high enough to eliminate the umbra. The orientation of the light causes D1 shadow discontinuities on the ground plane. */ camera { location <0,2.5,-10> right x up y sky y look_at y/2 } // LIGHTING #declare SinglepartPoly= polygon { 5, <-1,-1>, <1,-1>, <1,1>, <-1,1>, <-1,-1> texture { PlainWhiteBright_T } interior_texture { PlainBlack_T } scale 2.5 rotate -90*x } light_source { 0, 1 looks_like { SinglepartPoly } spotlight point_at -y radius 1 falloff 90 area_light <2.5,0,0>, <0,0,2.5>, 5, 5 jitter adaptive 1 orient fade_distance 15 fade_power 1 rotate <45,-45,0> translate 15*y // place ahead of rotate instead? // translate y } box // floor { -1,1 texture { PlainWhite_T } scale <10,0.5,10> translate -y/2 } #declare BoxGrid= union { #declare i=2.5; #while (i>-2.5) box { -1,1 scale <0.25,0.25,2.5> translate } #declare i=i-1.25; #end texture { PlainWhite_T } translate -0.75*x } // SHADOW OBJECTS object { BoxGrid rotate 0 translate 4*y } object { BoxGrid rotate <45,-45,0> translate y } #break #case (3) /* Large Spatial Extent: This scene has a large spatial extent, however the camera is positioned on a very small portion of the scene. The scene itself consists of a large ground plane, light, and blocker directly below and the same size as the light. Underneath the large blocker is a small light and blocker pair scaled down in width and depth by a factor of 10. The small light aims up. The camera looks under the large blocker (Figure 3). Algorithms that compute global solutions or sample lights based on the energy of each light may have trouble getting a high enough accuracy over the visible pixels, as 99% of the energy in the scene is due to the large light, but much of the visible energy is due to the small light. */ camera { location <0,5,-10> right x up y sky y look_at y/2 } plane // floor { y, 0 texture { PlainWhite_T } } // LIGHTING // overhead light #declare SinglepartPoly= polygon { 5, <-1,-1>, <1,-1>, <1,1>, <-1,1>, <-1,-1> texture { PlainWhiteBright_T } interior_texture { PlainBlack_T } scale 4 rotate 90*x } light_source { 0, 1 looks_like { SinglepartPoly } spotlight point_at -y radius 1 falloff 90 area_light // being same size as "large blocker" <4,0,0>, // this light isn't shadowing very well <0,0,4>, 12, 12 jitter adaptive 2 orient // circular fade_distance 10 fade_power 1 translate 20*y } box // large light block { -1,1 texture { PlainWhite_T } scale <4,0.1,4> translate 3*y } // underside light #declare SinglepartPoly= polygon { 5, <-1,-1>, <1,-1>, <1,1>, <-1,1>, <-1,-1> texture { PlainWhiteBright_T } interior_texture { PlainBlack_T } scale 1 rotate -90*x } light_source { 0, 3 // looks_like // { // SinglepartPoly // } spotlight // try commenting out spotlight part point_at y radius 1 falloff 90 area_light <4,0,0>/10, <0,0,4>/10, 12, 12 jitter adaptive 2 orient // circular fade_distance 2.5 fade_power 1 translate 3*y/9 } box // small light block { -1,1 texture { PlainWhite_T } scale <4,0.1,4>/10 translate 3*y/10 } #break #case (4) /* Complex Illumination Paths: This scene checks complex illumination paths. It consists of a ground plane with a light underneath. The light shines on a diffuse surface to the side of the ground plane. All illumination on the visible objects is from this secondary luminaire (Figure 4). The secondary luminaire and the block on the ground plane create a very definite shadow and the light reflected off the block creates a visible indirect effect. Light can arrive in the umbra of this shadow only after 3 or more other interactions with diffuse surfaces. A simple change to this scene can create a good test of the correct handling of specular objects. Replacing the diffuse cube with a mirrored cube creates a scene with a reflection of a caustic caused by a secondary source. It also eliminates the possibility of light reaching the umbra. */ camera { location <0,10,-10> right x up y sky y look_at y/2 } // LIGHTING #declare SinglepartPoly= polygon { 5, <-1,-1>, <1,-1>, <1,1>, <-1,1>, <-1,-1> texture { PlainWhiteBright_T } interior_texture { PlainBlack_T } scale 1 rotate <90,0,90> } light_source { 0, 3 looks_like { SinglepartPoly } spotlight point_at -x radius 1 falloff 90 area_light <1,0,0>, <0,0,1>, 5, 5 jitter // adaptive 1 // orient // circular // fade_distance 2.5 // fade_power 1 translate -2*y #if (Reflect=yes) photons { reflection on refraction off } #end } box // floor { -1,1 texture { PlainWhite_T } scale <10,0.1,10> translate -y/10 } box // "luminaire" { -1,1 texture { PlainDiffuse_T } scale <0.1,10,10> rotate -12*z translate -12*x } #if (Reflect!=yes) box // diffusing object { -1,1 texture { PlainDiffuse_T } scale <1,1,1> rotate <0,45,0> translate y } #else box // reflecting object { -1,1 texture { PlainReflect_T } scale <1,1,1> rotate <0,45,0> translate y photons // hmmmm, this isn't having noticeable affect { target reflection on refraction off collect on } } #end #break #case (5) /* Geometric Accuracy: This model consists of 3 cubes and a wedge on a ground plane (Figure 5). It contains a few of the more common geometric problems in models. The leftmost cube penetrates the ground plane by 1% of its height. The rightmost cube is raised above the ground plane by 1%. A corner of the center cube sticks through the ground plane as well. The center object is a wedge viewed from the thin side. All objects are rotated slightly from alignment with the ground plane axes. Many rendering methods that store energy on surfaces or volumes will have trouble with light or shadow leaks near the point of the wedge. Some ray tracing based approaches using tolerances may exhibit a similar problem here as well, as the shadow rays may start on the wrong side of the wedge. The cubes check the robustness of meshing algorithms. */ camera { location <0,5,-10> right x up y sky y look_at 0 } // LIGHTING #declare SinglepartPoly= polygon { 5, <-1,-1>, <1,-1>, <1,1>, <-1,1>, <-1,-1> texture { PlainWhiteBright_T } scale 1 rotate 90*x } light_source { 0, 1 looks_like { SinglepartPoly scale 25 } spotlight point_at -y radius 1 falloff 90 area_light <25,0,0>, <0,0,25>, 9, 9 jitter adaptive 1 // orient // circular fade_distance 50 fade_power 1 translate 100*y rotate <-60,-30,0> } plane // floor { y,0 texture { PlainWhite_T } } difference // wedge { box { -1,1 } plane { -x, 0 rotate 7.5*y translate 0.15*x } plane { x, 0 rotate -7.5*y translate -0.15*x } texture { PlainWhite_T } scale <1,1.5,1> rotate <0.5,-4,0> // slight offset from floor axes translate <0,1.5,1> } box // left, embedded { -1,1 texture { PlainWhite_T } rotate <0,0.5,0> // slight offset from floor axes translate <-3,0.98,1> } box // right, floating { -1,1 texture { PlainWhite_T } rotate <0,0.5,0> // slight offset from floor axes translate <3,1.02,1> // I couldn't get a artifact at gap } box // forward-center, embedded tip { -1,1 texture { PlainWhite_T } scale 0.5 rotate 45*y rotate 45*x rotate 180*z rotate <0,5,7.5> // slight offset from floor axes translate <0,0.8,-4.5> } #break #end