Hey there,
Recently I’ve come across a solution to creating billboard foliage game objects using a shader that you can find below that locks to the y axis, and I’m looking for some feedback. Firstly, with my game it makes use of alpha, even though it’s on mobile (it’s just the style I’m looking for), so I’m making sure to use just ‘alpha’ and not ‘alpha test’ shaders as the tile based PowerVR architecture goes four times slower if using cutout shaders.
As a solution for rendering foliage and outer objects, I was looking for a billboard shader I could use with sprite renderers that would be performant. I found and modified a simple billboard shader online and here it is…It didn’t originally write it, I just added in the necessary lines to add gpu instancing.
Basically the steps are to create an empty game object with a sprite renderer, make a material that uses this shader and drag it onto the game object, then make sure gpu instancing on the material/shader is checkmarked.
I’ve gotten so far 4-5 draw calls on 2000 trees with a perfect frame rate, this is down from my usual 800 draw calls on my forests:
Using this to create tree, bush and rock prefabs with lod 0 for the actual model and lod 1 for the foliage and rocks, and then using 360 panoramas I’m hoping to achieve the ability to target mobile platforms.
Shader "Billboards/BillboardInstanced" {
Properties{
_Color("Main Color", Color) = (1,1,1,1)
_MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
_BumpMap("Normalmap", 2D) = "bump" {}
}
SubShader{
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
"DisableBatching" = "True"
}
LOD 100
CGPROGRAM
#pragma multi_compile_instancing
#pragma vertex vert
#pragma surface surf Lambert alpha:fade
struct appdata_t
{
float4 vertex : POSITION;
float3 normal : NORMAL;
half4 color : COLOR0;
float2 texcoord : TEXCOORD0;
float2 texcoord1 : TEXCOORD1;
float2 texcoord2 : TEXCOORD2;
float4 tangent : TANGENT;
UNITY_VERTEX_INPUT_INSTANCE_ID //
};
sampler2D _MainTex;
sampler2D _BumpMap;
fixed4 _Color;
struct Input {
float2 uv_MainTex;
float2 uv_BumpMap;
};
void Billboard(inout appdata_t v)
{
UNITY_SETUP_INSTANCE_ID(v);
const float3 local = float3(v.vertex.x, v.vertex.y, 0); // this is the quad verts as generated by MakeMesh.cs in the localPos list.
const float3 offset = v.vertex.xyz - local;
const float3 upVector = half3(0, 1, 0);
const float3 forwardVector = UNITY_MATRIX_IT_MV[2].xyz; // camera forward
const float3 rightVector = normalize(cross(forwardVector, upVector));
float3 position = 0;
position += local.x * rightVector;
position += local.y * upVector;
position += local.z * forwardVector;
v.vertex = float4(offset + position, 1);
v.normal = forwardVector;
}
void vert(inout appdata_t v, out Input o)
{
UNITY_INITIALIZE_OUTPUT(Input, o);
Billboard(v);
}
void surf(Input IN, inout SurfaceOutput o) {
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = c.a;
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
}
ENDCG
}
}