Monthly Archives: January 2014

Unity Shadows on Windows Phone 8

 

Due to a driver issue Unity offers currently no realtime shadows on Windows Phone 8 devices.

But you don’t have to give up shadows on WP8.

You can use a combination of

  • baked lightmaps of the static environment
  • projected shadows for dynamic things, e.g. the main character

to achieve nice shadows in your 3D world.

I’ve created a small downloadable demo using some Unity default assets. I’ve upscaled the character a bit, so that you can see what has to be considered when using larger dynamic shadows, e.g. for vehicles.

Step 1: Lightmap Baking

To achieve something similar as in my example one would use the following workflow:

  • open <Windows/Lightmapping>
  • select the directional light and switch on the shadows temporarily
  • select all static renderes in the scene and switch ‘Lightmap Static’ on
  • in the bake tab choose ‘Single Lightmaps’
  • set Ambient Occulusion to 0.4
  • set Resolution to 16 texels per world unit
  • bake Scene

Step 2: Dynamic Shadows using a Projector

The shadow projector is based on Unity’s render texture feature, which means you need Unity Pro to be able to use it.

Basically it works like this: There is a second camera that only renders the character. With the help of a Projector the shadow is then projected onto all objects that intersect its frustum.

Shadow Projection

Shadow Projection

Aras Pranckevičius (rendering dude at Unity, see his twitter profile) has created a ready-to-use Unity package for this.

Follow the instructions at http://wiki.unity3d.com/index.php/Character_Shadow.

Basically one only needs

  • to assign a specific layer for the character
  • add CharacterShadow.cs to an empty game object from where the shadows are cast

In our case the character can move around, so we do the following:

  • add an empty GameObject as Child to our character (named ‘Viking’ in the example) and name it ShadowCastPosition
  • add the CharacterShadow.cs script to it
  • since the shadow should have the direction of the directional light we add an additional simple script with the following content
public class ShadowCastPosition : MonoBehaviour
{
	public Transform lightTransform;
	public float dist = 12;
	private Vector3 back;

	void Awake()
	{
		back = lightTransform.TransformDirection(Vector3.back) * dist;
	}

	void Update ()
	{
		transform.position = transform.parent.position + back;
	}
}

The script simply positions the ShadowCastPosition GameObject towards the directional light direction with a certain distance, so the correct shadow is casted.

An important hint: if the thing that should cast a shadow is bigger (e.g. some kind of vehicle), there is an important hard-coded setting in the CharacterShadow.cs script in the method OrientToEncloseTarget.

To demonstrate this in my example, I upscaled the character a little bit. I added the public variable childCamRadius and set it 12 in my example.

To run the working demo on your WP8 device:

  • download the demo here
  • open the project in Unity
  • in the build settings switch to ‘Windows Phone 8’
  • click ‘Build And Run’
  • enjoy 🙂

Follow me on twitter, if you found this useful.