POVRay Alpha Shadow Tutorial


 

Part 2: Soft Alpha Shadows

What we saw in the previous section worked well for hard shadows. If we want soft shadows, things get a little trickier.

First take your scene

Original scene

Here's the same scene that we started with before, except now there's an area light casting soft shadows.

camera { location  <2, 4, -6> look_at <2, 1, 0>}

light_source {<-100,200,-100> colour rgb 1
    area_light <20, 0, 0>, <0, 0, 20>, 10, 10
    adaptive 1
    jitter
}

#declare Stuff = union {
  box {-1,1 translate y*3 pigment {rgb <1,1,0>}}
  sphere {<3,3,0>,1 pigment {rgb <1,0,0>}}
}

object {Stuff}

plane {y, 0 pigment {rgb 1}}

The First Pass: Just the Shadows

Our first pass is to render just the shadows.
 
The Shadows
As before, we make the following changes:
  • The scene is viewed from an orthographic camera placed vertically above the ground plane.
  • The objects casting the shadows are no_image

The light strength is carefully adjusted so that it is just bright enough to be pure white. In the previous version we were able to use a very bright light and rely on clipping, but that produces poor results for the intermediate shades. In this case the light needs to be rgb 1.9. So the code now looks like this:-

camera { orthographic location y*10 look_at 0}

light_source {<-100,200,-100> colour rgb 1.9
    area_light <20, 0, 0>, <0, 0, 20>, 10, 10
    adaptive 1
    jitter
}

#declare Stuff = union {
  box {-1,1 translate y*3 pigment {rgb <1,1,0>}}
  sphere {<3,3,0>,1 pigment {rgb <1,0,0>}}
}

object {Stuff   no_image}

plane {y, 0 pigment {rgb 1}}

Turn the render into a 256-colour GIF

Use an image processing package to convert the result of the first render into a 256-colour GIF file. By using a paletted image format (like GIF) we can use the "transmit" keyword on the image_map. We also need to use the image processing package to view the details of the palette and discover which palette entry number corresponds to pure white. In my particular case the palette entry is 230.

The Second Pass: putting it all together

The Result

We now render the whole thing. The significant features of this render are:-

  • The objects are now no_shadow. We don't want real shadows to be cast this time.
  • The camera and lighting go back to being what they were in the original scene.
  • The plane is now painted (once) with an image_map mage from our 256-colour GIF
  • The white part of the image map is mapped into invisibility.
  • The grey and black parts of the image map are mapped into partial transparency.

So the code now looks like this:-

camera { location  <2, 4, -6> look_at <2, 1, 0>}
light_source {<-100,200,-100> colour rgb 1}

#declare Stuff = union {
  box {-1,1 translate y*3 pigment {rgb <1,1,0>}}
  sphere {<3,3,0>,1 pigment {rgb <1,0,0>}}
}

object {Stuff no_shadow}


plane {y,0
   pigment {image_map {gif "shadow2b.gif" once 
       transmit all 0.3   // dark bits partially transparent 
       transmit 230,1     // bright bits become 100% transparent
     }
     translate <-0.5, -0.5, 0>
     scale <4/3*10, 10, 1>
     rotate x*90
   }
}

 
Back to Part 1: Hard Alpha Shadows
Back to Mike's Homepage