HomeAbout inludoServicesGamesClientsDevelopmentsForumContact usHomeMail inludo


Shadows:


Download the source here.

Intro:
Shadows are an extremely useful visual clue of depth, size, and relationships between objects. A lot of people have expressed disatisfaction that Director 8.5 does not have support for shadows. Shadows, however, are extremely computationally slow or place a huge burden on the graphics card, which makes them impractical for current projects on current hardware.
All is not lost however! It is easy enough to mimic simple shadows, and so below is one fairly flexible (I hope!) solution.

Method:
Basically I do create another copy of the model to be shadowed, and squash it flat!.
To make it look right, there are obviously a few gotchas, but they introduce some interesting facts about Director 8.5.
Firstly, I create a shadow shader. This gets applied to the shadow object (what I call my copy of your model). It contains no texture, it's merely a colour (which you can set). It accepts no lighting from lights in the scene (after all, shadows are not actually something for light to reflect off of.
Secondly to make the shadow object look correct from the point of view of the light, I also skew my model. This involves directly manipulating the shadow object's transforms, which as well as achieving the desired effect also breaks Director's standard transform functions. Because of this I create several groups and nest them, with the shadow object at the bottom. This allows me to perform certain operations on certain groups. EG one of the groups is purely for skewing, and another for scaling. This allows me to carry on rotating and positioning the other groups happily without breaking anything.
All this can be played with if you wish, but the main aim of this code is to allow people to use shadows as simply as possible, therefore I won't be explictly detailing my shadows commands, just the two lines of code you need to make it work :)
One final point - you can move the object 'through' the shadow plane. Since this would equate to the model going through solid ground, it'll look wrong. That'll teach you.

In Practice:
To succesfully use the shadows you only need write 2 lines of code::

  • Creating the shadow object script.
    For this you create a new instance of the "[P] Shadows" script, with one of the following lines of code:

    tShadowObj = script("[P] Shadows").new(tWorld, tObj, tLight, tFloorHeight)
    tShadowObj = script("[P] Shadows").new(tWorld, tObj, tLight, tFloorHeight, tShadowColour)

    where tWorld is the name of the 3D member you wish to create the shadow object in.
    tObj is the name of the model or node you wish to create a shadow object of. It must exist in member tWorld. Why do I say node as well as model? Because you can pass the routine (for example) a group that contains a collection of models, and all models in the hierarchy will be shadowed correctly. This makes life easier - you can group a set of objects together and just use one shadow script for the lot.
    tLight can be an integer, a string or a vector. If it is an integer then the light direction vector is calculated from the direction of member(tWorld).light[tLight]. A string is almost identical, but it refers to the explicit name of the light, IE member(tWorld).light(tLight).
    tFloorHeight is the height in world units along the Y axis, of the floor plane the shadows are cast onto. This can be any value, positive or negative.
    tShadowColour specifies the colour of the shadow shader and hence the shadows. It is supplied in rgb(red, green, blue) colour object format. If this is omitted, then it defaults to rgb(0, 0, 0) - black.
  • Updating the shadow object.
    If the model changes or the lighting changes, the shadows need to be recalculated. This is done by calling the following object handler:

    tShadowObj.UpdateShadow()

    where tShadowObj is the object reference returned when you created the shadow script instance.

    It should be noted that if the light is shining upwards (IE from underneath the shadow plane) then no shadow is cast - the shadow object is removed from the world, and added back again if or when the light shines downwards.
    Note that lighting directions are only recalculated if you supplied a reference to a proper Director 8.5 light (see tLight parameter above). When you call UpdateShadow() the code looks at what the current direction of the light is and uses that for the new shadows.

 

Development
Screenshots
Demos
Tutorials