ShadowGun : Optimising for Mobile

Hi everyone, we wanted to help you with optimizing your mobile game, so we recently published a blog post with some tips and tricks from the game ShadowGun, courtesy of MadFinger Games. We provide a sample level with some awesome shaders from the game that you are free to use in your games - the rest of the sample (meshes, textures) are copyright of MadFinger.

Please use this forum to discuss the tips therein, and related optimization issues.

Check out the blog post below -

http://blogs.unity3d.com/2012/03/23/shadowgun-optimizing-for-mobile-sample-level/

nb. Please note that dynamic fluid surfaces should be discussed in separate threads.

1 Like

As suggested i rewrite my question here:

The project with my Mac 10.7.3 and Unity Pro 3.5 have lost all references.
I have tried to download it again, but it doesn’t works.
Could you provide an .unitypackage or how i can rebuilt library references?

Thank you.

Thanks for moving this to the forums Will.

Copy of my reply on the Blog Post:

Thanks for the replies.
My problem is if I target armv7, my framerate is crippled on iPad 1. It’s easily a 50% performance hit. Targeting Universal armv6 and armv7, both cripples performance and results in a build size that makes it impossible using Unity to hit the 20meg limit for mobile downloads.

My game is based on breaking glass so I use very simple glass shaders to make very low poly objects look like glass with a heavy reliance on the physics system for breakage. Since the whole world is made of glass, I’m using shaders with Tags to designate the render Queue allowing for transparent overlapping objects that I can control. (Background, Background+1, playerQueue, OverLay for in front of player) The shaders are shockingly simple with a simple color property for different colored glass and blending (Blend One One) for additive or Blend ScrAlpha OneMinusAlpha for real alpha blending. Oddly enough (armv6 ES1.1) handles this setup admirably. (armv7 ES2.0) on the other hand seems to immediately hit me with a 50% penalty.

I would love to move to armv7 so I can use some of the effects demonstrated by MadFinger. I’ll keep researching.

Allan

Thanks

This is no less than releasing Doom Source Code many years ago :slight_smile:
But the last thing i would imagine is that the waving flag is an animated shader!!!
Kudos, You have an amazing Shaders Team, I must say that Shaders are one of the Heroes on this project, and for this only i find the sample level EPIC, even without any gameplay features revealed.
Perfect Again, thank you, will bug you again in the comments.

It’s a milestone in unity blog postings. I’ve asked many a time for unity to put some exciting blogs out and also asked many times for insights into the techniques in shadowgun, mostly the tricks used for character shading, and both madfinger and unity have delivered.

I honestly didn’t expect much and had already shut up about it when this came along…! Props to all involved, this is important for not just mobile, but for any developer wishing to optimise.

For an indie with very serious time constraints, can you imagine how important it is?

Once again - thank you.

Jason Amstrad will have to wait longer for his wet dream.

You are 100% totally wasting your time supporting Arm 6. I’ll go on record saying you’ll make a grand total of zero sales for arm 6 (the iphone 3G original).

The problem with iPad is that the opengl ES 2.0 shaders appear to be much slower, I’m not sure why, they just are. I can only assume black magic.

I love that unity decided to share this information with us. But the think I want to know most is how they did their cover system. I am more of an artist that a programmer and I just can’t seem to figure out where to even start.

Hippocoder,

I’m not so much “targeting” avrmv6 as I am just using what works. I fully intend to release for iPhone 3GS and up devices. I test on all of them.

Armv6:
My game runs at 60fps with no hiccups on iPad2. It runs great on iPhone 4 and 4S. I’ve been using the iPad 1 as the baseline since it is the slowest due to the higher resolution. (I do have performance problems on the 3GS but I think that is due to the physics/slower cpu). Given the much lower resolution on the 3GS, the 3GS likely renders equal or faster than the iPad1.

I agree with you however. I am going to try to get things running on armv7.

So the question is why would this simple shader crush armv7? Granted I’m using it on multiple materials with different color values and different render Queue Tags so I can control the Draw order of my transparent/glass objects. But ES1.1 handles it fine but ES2.0 is sees 40-50% drop in FPS.
This is the code for the BackgroundQueueAdditive.

hader "Mobile/BackgroundQueueAdditive" 
{ 
	Properties 
	{
		_Color ("Main Color", Color) = (.5,.5,.5,0)
	   _EnvMap ("EnvMap", 2D) = "black" { TexGen SphereMap }
	}
	
	Category 
	{
		Tags { "Queue"="Background" "IgnoreProjector" = "True" "RenderType"="Background"} 
		//SeparateSpecular On
   		Lighting Off
        Zwrite off
        Fog { Mode Off }
        //Ztest Always
   		//Cull off //Will Show back thorugh front
   		
        Blend One One                       // additive
        //Blend One OneMinusSrcColor          // soft additive
        //Blend SrcAlpha OneMinusSrcAlpha     // real alpha blending

		SubShader 
		{ 
	      Pass 
	      { 
	      	SetTexture [_EnvMap] 
	      	{ 
	         	combine texture
	      	} 
	      	SetTexture [_EnvMap] 
	        {
	            constantColor [_Color]
	            Combine previous * constant DOUBLE, previous * constant
	        }  
	      }
	  }
   } 
}

This is something you’ll see happen quite a lot using shaderlab stuff, it just is a lot slower on ES 2.0, but a lot faster on 1.1. I do not know why this is, but if I had to hazard a guess it is because that shader is written with fixed function in mind. 2.0 hasn’t got any fixed function, so what happens is the shader is automatically converted from fixed function to GLSL, but something is being added (probably lighting stuff and so on) which will slow it right down.

I don’t know the specifics, but it means the only way to match 1.1 speeds is to write the shader in either cg, or glsl (both which I suck at and can’t really help you with).

Could someone please assist in getting this to open properly in unity?

I am using Unity version 3.5.0f5, yet when I open the _Level unity scene file, all I get are a bunch of lights and nothing else. It also reads “The referenced script on this Behaviour is missing!”

Don’t know how to get this to work!

I’ve tried re-downloading it multiple times, all yielding the same results.

@Chaneya: Have you tried writing actual pixel vertex shaders as opposed to using the fixed function pipeline which is emulated?

From looking at the shader you posted, i would imaging that _EnvMap (“EnvMap”, 2D) = “black” { TexGen SphereMap } is not great for performance on the GLES 1.1. emulated shader path.

As you can see in Shadowgun, you can get the iPad1 to perform well on pretty high-end scenes.
But you have to actually dig into your shaders and make sure they are well optimized. Especially on surfaces that cover a lot of pixels.

Maybe you should start with the shadowgun shaders as a basis and tweak them for your specific needs?

Joachim,

I am working with the Shadowgun shaders but many of them are way over my head. Many of them are very very complex.

Although it may be _EnvMap (“EnvMap”, 2D) = “black” { TexGen SphereMap } that is causing the crush in ES2.0, if I comment out my use the following lines that apply the color, I get great framerate in ES2.0.

_Color (“Main Color”, Color) = (.5,.5,.5,0)

SetTexture [_EnvMap]
{
constantColor [_Color]
Combine previous * constant DOUBLE, previous * constant
}

Thanks for the tip though.

Allan

I cleared the lighmapping, changed some light and baked again: bug on 3.5:

Something went wrong in the Beast lightmapper: Job Execution Failure This is a bug - please report it with a scene reproducing the issue.

File : /Applications/buildAgent/work//Editor/Src/Lightmapping.cpp at line 42

I have similar problem.

Unity 3.50f5, Lion 10.7.3 and when i open the level, in the project panel i can see only “Shaders” Folder that is in this path:

ShadowgunSampleLevel/ShadowGunSample/Assets/Assets/Shaders

EDIT: i have tried to rename the second folder Assets/Shaders to Assets2/Shaders, so i am able to open the level but (obviously ) all shaders references are lost.

In any case could you provide an .unitypackage?

Assets are broken. Only a Shader folder and no meshes. They all show as red in the hierarchy.

Gary

I agree, i have tried with Snow Leopard too, and i have the same problems.
The project works with Mac or only with Windows?

It works but after some tricks!

In fact the Assets/Assets folder brokes the references library.

1- Copy Assets/Shaders

2-Delete Assets/Shaders

3-Open project

4-Paste Assets/Shaders with Finder

5-Rename Assets/Shaders to Assets2/Shaders

6-Save all

7-Play!

@chaneya

I tried to port your shader to cgsl but I can’t currently test it on a mobile device.
Can you test it and report back if it’s also crushing your performance?

Shader "Mobile/BackgroundQueueAdditive2"
{
Properties {
		_Color ("Main Color", Color) = (0.5, 0.5, 0.5, 0)
		_EnvTex ("EnvMap", 2D) = "black" {}						 							 
	}
	SubShader {
//		Tags { "Queue"="Background" "IgnoreProjector" = "True" "RenderType"="Background"}
		Tags { "Queue"="Transparent" "IgnoreProjector" = "True" "RenderType"="Transparent"}
		
		Pass{
//			Alphatest Greater 0
//			Cull Off
			ZWrite Off

//			Blend SrcAlpha OneMinusSrcAlpha     // Alpha blending
			Blend One One                       // Additive
//			Blend One OneMinusDstColor          // Soft Additive
//			Blend DstColor Zero                 // Multiplicative
//			Blend DstColor SrcColor             // 2x Multiplicative
			
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			
			//Declare Properties
			sampler2D _EnvTex;
			fixed4 _Color;
			//------------------
			
			//Declare structures
			struct v2f{
				float4 pos : SV_POSITION;
				//half4 color : COLOR0;
				//half2 uv : TEXCOORD1;
				half2 uvSphere : TEXCOORD0;
			};
			struct appdata_custom {
				float4 vertex : POSITION;
				//float4 tangent : TANGENT;
				half3 normal : NORMAL;
				//half4 texcoord : TEXCOORD0;
				//half4 color : COLOR;
			};
			//--------------------
			
			half4 _EnvTex_ST;;
			
			//vertex shader
			v2f vert (appdata_custom v)
			{
				v2f o;
				o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
				
				//Sphere mapping ported from http://www.ozone3d.net/tutorials/glsl_texturing_p04.php
				half3 u = normalize( mul(UNITY_MATRIX_MV, v.vertex));
				half3 n = mul(UNITY_MATRIX_IT_MV, float4(v.normal.xyz,0));
				half3 r = reflect( u, n);
				
				half m = 2.0 * sqrt( r.x*r.x + r.y*r.y + (r.z+1.0)*(r.z+1.0) );
				o.uvSphere = half2(r.x/m+0.5, r.y/m+0.5);
				//---------------
								
				//o.uv = TRANSFORM_TEX (v.texcoord, _EnvTex);;
				//o.color = v.color;
				return o;
			}
			
			//fragment shader
			fixed4 frag (v2f i) : COLOR {
				fixed4 tex = tex2D(_EnvTex, i.uvSphere) * _Color;
				tex.rgb *= 2; 	//double the color values, but leave alpha untouched
				return tex;
		    }
			ENDCG
			
		}
	} 
}

Hope it works on iPad. Also, if it looks slightly different on mobile, it’s because I changed lots of variables from floats to halfs, so it’s faster but less precise. It’s just a quick test and I didn’t clean it up. : )

vwekker,

Wow you just made my week!

Your shader translation appears to work great and as far as I can tell it fixes the crushing performance problems when deploying to an iPad1 targeting platform armv7(OpenGL ES 2.0) (in Player Settings).

I still find it odd that emulating such a simple ES1.1 shader would have such profound performance destruction in ES 2.0. It really is a 50% overall hit in framerate. Thanks so much for doing this.

For anyone interested, this relatively simple shader gives you:

  • glass that looks like glass on mobile with very little performance hit. (Doesn’t break batching as other glass shaders seemed to do in the past)
  • alter color using the color picker on your material
  • control the rendering layer, rendering Queue or Draw Order (however you want to refer to it) by changing the Tag Queue in the SubShader. This gives you complete control over how your overlapping glass objects are displayed.
  • You can compress a spheremapped texture down to 64 X 64 RGBA PVRTC 4bits (2.0kb) and the glass will still look great. (I’ve attached the spheremap texture I’ve been using)
  • change the blending option by commenting and uncommenting the lines for additive, alphablending, Soft Additive etc. Using alphablending will make your glass look dark and bold where additive makes it appear more pastel in color.

1 Like