Category Archives: Unity

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.

Unity Custom Fog Shader on Windows Phone 8

 

Unity doesn’t support Standard fog on  all Windows Phone 8 devices.
So if you switch on fog in render settings fog is shown in the editor but not on the actual device.

Fog Render Settings

Fog Render Settings

Fog in the Editor

Fog in the Editor

You can however create a custom shader with fog.

To do so start right click in the project area and choose ‘Create/Shader’. You can name the shader e.g. ‘Fog’.  You can then apply this ‘Custom/Fog’ shader to your materials.

But still nothing has changed in your scene. Therefore the first change one should make to the shader is to switch off the standard fog, because otherwise you will still see the ‘Unity Fog’.

To do so, double click the newly created shader and add ‘Fog {Mode Off}’. After saving the ‘Unity Fog’ should disappear.

Switch Fog Mode Off

Switch Fog Mode Off

We want to use the parameters of the Render Settings pane, so we add some Unity standard parameters to the shader code.

Unity Fog Parameter

Unity Fog Parameter

Next step is to add a vertex and finalcolor function.

In the vertex function we compute the distance between the vertex and camera and calculate based on the parameters a factor (fogFactor) that describes how much fog color to apply.

Fog Vertex- and Finalcolor Function

Fog Vertex- and Finalcolor Function

At this state we still don’t see any fog in the editor or game view of Unity, because we have to tell the system about our vertex and finalcolor function. So we will extend the #pragma statement accordingly.

Extend #pragma

Extend #pragma

Now when the shader is saved and automatically compiled by Unity we can now see our fog. This kind of fog is also visible on the Windows Phone 8 device.

In case you want to use exponential fog you can replace the linear fog computation by:

float f = cameraVertDist * unity_FogDensity;
data.fogFactor = saturate(1 / pow(2.71828,  f));

or for the exp2 case with

float f = cameraVertDist * unity_FogDensity;
data.fogFactor = saturate(1 / pow(2.71828,  f * f));

Here the whole shader:

Shader "Custom/Fog" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		Fog {Mode  Off}
		LOD 200

		CGPROGRAM
		#pragma surface surf Lambert vertex:fogVertex finalcolor:fogColor

		sampler2D _MainTex;

		uniform half4 unity_FogColor;
		uniform half4 unity_FogStart;
		uniform half4 unity_FogEnd;
		uniform half4 unity_FogDensity;

		struct Input {
			float2 uv_MainTex;
			half fogFactor;
		};

		void fogVertex(inout appdata_full v, out Input data) 
		{
			UNITY_INITIALIZE_OUTPUT(Input, data);
			float cameraVertDist = length(mul(UNITY_MATRIX_MV, v.vertex).xyz);
			data.fogFactor = saturate((unity_FogEnd.x - cameraVertDist) / (unity_FogEnd.x - unity_FogStart.x));			
		}

		void fogColor(Input IN, SurfaceOutput o, inout fixed4 color)
		{
			color.rgb = lerp(unity_FogColor.rgb, color.rgb, IN.fogFactor);
		}

		void surf (Input IN, inout SurfaceOutput o) {
			half4 c = tex2D (_MainTex, IN.uv_MainTex);
			o.Albedo = c.rgb;
			o.Alpha = c.a;
		}
		ENDCG
	} 
	FallBack "Diffuse"
}

[Update 1/20/2014] On user request you can download the project from here.

The test project is only a static scene. Nothing fancy.

Instructions:

  • download and extract the zip file
  • choose <File/Build settings…>
  • choose ‘Windows Phone 8’ from Platform
  • click on ‘Switch Platform’
  • click on ‘Build and Run’
  • enjoy 🙂 

Deploy your Unity app on your WinRT tablet

 

Testing on real devices is very important. Especially for games.

Deploying your Unity app on your WinRT tablet is relatively comfortable with VS 2012.

– download Remote Tools for Visual Studio 2012 (ARM)
– install it on WinRT
– start the Remote Debugger on the tablet

– create a simple test project in Unity
– choose ‘Windows Store Apps’ in Unity’s build dialog
– build
– open the project in Visual Studio 2012
– choose ‘Remote Machine’
– deploy
– get a developer license for Windows RT on the tablet
– enjoy

Here is the screencast with instructions on how to deploy your app to WinRT: