POVRay Alpha Shadow Tutorial


 

Part 1: Hard Alpha Shadows

Suppose you have a situation where you want to render a POV object against a transparent background, but you want to create semi-transparent shadows. The sort of situation where this might arise is if you want to create objects that are to be used as moveable sprites in a computer game.

With the official version of POVRay, you can only cast shadows onto backgrounds that are visible, but there is a way to produce the effect with two passes through the POV process.

First take your scene

Original scene

Here's a very simple scene, for which we might want to make the floor disappear, but for which we want to leave the shadows visible. Here's the original POV source code:-

   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}

   plane {y, 0 pigment {rgb 1}}

The First Pass: Just the Shadows

Our first pass is to render just the shadows.
 
The Shadows
We make the following changes:
  • The scene is viewed from an orthographic camera placed vertically above the ground plane.
  • The light is made much brighter, so all points on the plane are fully white or black
  • The objects casting the shadows are no_image

So the code now looks like this:-

   camera { orthographic location y*10 look_at 0}
   light_source {<-100,200,-100> colour rgb 10}

   #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 2-colour GIF

This is the clever bit. Use an image processing package to convert the result of the first render into a two-colour GIF file. By using a paletted image format (like GIF) we can use the "transmit" keyword on the image_map. A nice thing about a two-colour GIF file is that we know that the palette numbers are zero and one, with multi-colour paletted images it might be harder to guess which palette numbers represent black and white. With PaintShop Pro zero is black and one is white, but it's just as easy if your image processing package happens to make zero be white and one black.

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 two-colour GIF
  • The white part of the image map is mapped into invisibility.
  • The black part of the image map is mapped into partial transparency.

In this image I've made the shadow 80% transparent, but you can, of course, set the transparency to whatever you like.

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 "shadow2.gif" once 
       transmit 1,1    // bright bits become 100% transparent
       transmit 0,0.3  // dark bits partially transparent
     }
     translate <-0.5, -0.5, 0>
     scale <4/3*10, 10, 1>
     rotate x*90
   }
}

Thanks to Stephen Klebs for a correction to the details of the shadow transformation.
 

Part 2: Soft Alpha Shadows
Back to Mike's Homepage