Navigation


RSS : Articles / Comments


Casting Shadows in Papervision 3d

7:39 PM, Posted by Jim Foley, 9 Comments

Want to add that extra dimension to your 3D scene? Use shadows! They're pretty easy to implement really. See the sample code below and follow the code hightlighted in red to see the steps needed to create shadows.

Note: You will need to download the ShadowCaster class. See this post on Andy Zupko's blog for the source files.

Example Code (don't freak, there's just a lot of comments)
package {
//import the ShadowCaster classes
import com.everydayflash.pv3d.ShadowCaster;
import flash.display.BlendMode;
import flash.display.Sprite;
import flash.events.Event;
import flash.filters.BlurFilter;
import org.papervision3d.cameras.CameraType;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.MovieMaterial;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.materials.special.CompositeMaterial;
import org.papervision3d.objects.primitives.Cylinder;
import org.papervision3d.objects.primitives.Plane;
import org.papervision3d.view.BasicView;
[SWF(width="600", height="400", framerate="31", backgroundColor="0xFFFFFF")]
public class Shadows extends Sprite
{
private var view:BasicView;
//to cast shadows we will need dummy sprite object
//that we can draw our shadows into using the ShadowCaster object
private var spr:Sprite;
//That dummy sprite will then be passed into a moviematerial
//where we can project our shadows into our 3D scene
private var sprMaterial:MovieMaterial;
private var shadowPlane:Plane;
private var wire:WireframeMaterial;
private var color:ColorMaterial;
private var composite:CompositeMaterial;
private var cylinder:Cylinder;
//To cast shadows we will need a light
//Declare a PointLight3D object
private var light:PointLight3D;
//The shadows are drawn using the ShadowCaster object
//Declare a ShadowCaster object
private var shadowCaster:ShadowCaster;
public function Shadows()
{
view = new BasicView(600, 400, false, true, CameraType.FREE);
view.camera.y = 300; view.camera.rotationX = 30;
//Instantiate your dummy sprite
spr = new Sprite();
//draw a rectangle into your dummy sprite
//note that if you don't want your plane to show in the scene
//but you do want shadows, you can set the alpha of the
//beginFill method to 0 (shadows will be drawn but the plane color fill will not)
spr.graphics.beginFill(0xFFFFFF);
//the larger the "drawRect" shape the better the quality of your shadows
spr.graphics.drawRect(0, 0, 256, 256);
//Add the dummy sprite to a MovieMaterial object
sprMaterial = new MovieMaterial(spr, true, true, true);
//create a plane and apply your dummy sprite MovieMaterial to it
shadowPlane = new Plane(sprMaterial, 2000, 2000, 1, 1);
//rotate and orient your plane so that it is aligned as the floor/ground
shadowPlane.rotationX = 90;
shadowPlane.y = -200;
wire = new WireframeMaterial(0x0000AA);
color = new ColorMaterial(0x0066CC);
composite = new CompositeMaterial();
composite.addMaterial(color);
composite.addMaterial(wire);
//we'll use a cylinder as the object that is going to cast the shadow
cylinder = new Cylinder(composite, 80, 250, 8, 3);
//Instantiate your light object and set the z, y axis up and to the back
light = new PointLight3D(); light.z = 600; light.y = 500;
//Instantiate your shadowCaster object
//The parameters are as follows
//ShadowCaster("name", shadow color, blend mode, shadow alpha, [filters]);
shadowCaster = new ShadowCaster("shadow", 0x000000, BlendMode.MULTIPLY, .3, [new BlurFilter(10, 10, 1)]);
//Set the light type (options are SPOTLIGHT and DIRECTIONAL)
shadowCaster.setType(ShadowCaster.SPOTLIGHT);
//Add your shadowPlane and Cylinder to the scene
view.scene.addChild(shadowPlane);
view.scene.addChild(cylinder);
addChild(view);
addEventListener(Event.ENTER_FRAME, onRenderViewport);
}
private function onRenderViewport(e:Event):void
{
//the invalidate() method basically clears the previously drawn shadow
shadowCaster.invalidate();
//the castModel method casts the shadow of an object in your scene
//castModel parameters are as follows
//castModel(object to cast shadow from, light, plane to cast the shadow onto
shadowCaster.castModel(cylinder, light, shadowPlane);
cylinder.yaw(2);
cylinder.pitch(1);
view.singleRender();
}
}
}


Another thing to note, if you want to cast shadows of multiple objects you can do so by grouping your objects together into a single DisplayObject3D object and then use the DisplayObject3D as your model to cast a shadow in the castModel method of your ShadowCaster instance.

Example : click here
Flash Source : click here
Flex Source : click here

9 Comments

Chrome-fusion @ November 23, 2008 5:12 AM

Very nice thanks for the source code!!!

Dustin @ November 23, 2008 5:15 PM

Cool man, it's nice to see a simple example of it in action. It took a while to get my first shadow projects working. I'll use this post as a reference when i forget to do it in the future.

zu @ November 23, 2008 7:31 PM

Very nice and handy, thanks!

Anonymous @ December 27, 2008 8:35 AM

Great demo. Thanks!

Has anyone seen this class casting shadows on something other than planes? Like boxes or other Colladas?

Look at:
http://blog.papervision3d.org/2008/05/14/den-ivanovs-pv3d-garden/

The tree is casting a shadow that looks something like a shadow Caster shadow. Any thoughts?

Anonymous @ December 27, 2008 8:37 AM

Link from above comment.

Jim Foley @ December 28, 2008 11:30 PM

I would think that those shadows are actually a baked texture. Check out this post for Texture Baking info: http://www.everydayflash.com/blog/index.php/2008/11/20/texture-baking-is-your-friend/

Anonymous @ August 7, 2009 7:57 PM

Great work!But when I used dae model with shader, the faces seen to be pieces,u can see it through.

Anis @ August 17, 2009 11:19 AM

guys the flash source is inaccessible, if anyone can help i'll be grateful

Anonymous @ August 21, 2009 9:26 AM

All of your links are broken to videos and source files. hmmm