Search Unity

Billboard Shader for you, performance and targeting mobile platform...

Discussion in 'Scripting' started by astracat111, Jan 18, 2019.

  1. astracat111

    astracat111

    Joined:
    Sep 21, 2016
    Posts:
    725
    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.

    Code (CSharp):
    1. Shader "Billboards/BillboardInstanced" {
    2. Properties{
    3. _Color("Main Color", Color) = (1,1,1,1)
    4. _MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
    5. _BumpMap("Normalmap", 2D) = "bump" {}
    6. }
    7.  
    8. SubShader{
    9. Tags
    10. {
    11. "Queue" = "Transparent"
    12. "IgnoreProjector" = "True"
    13. "RenderType" = "Transparent"
    14. "DisableBatching" = "True"
    15. }
    16. LOD 100
    17.  
    18. CGPROGRAM
    19. #pragma multi_compile_instancing
    20. #pragma vertex vert
    21. #pragma surface surf Lambert alpha:fade
    22.  
    23. struct appdata_t
    24. {
    25. float4 vertex : POSITION;
    26. float3 normal : NORMAL;
    27. half4 color : COLOR0;
    28. float2 texcoord : TEXCOORD0;
    29. float2 texcoord1 : TEXCOORD1;
    30. float2 texcoord2 : TEXCOORD2;
    31. float4 tangent : TANGENT;
    32. UNITY_VERTEX_INPUT_INSTANCE_ID //
    33. };
    34.  
    35. sampler2D _MainTex;
    36. sampler2D _BumpMap;
    37. fixed4 _Color;
    38.  
    39. struct Input {
    40. float2 uv_MainTex;
    41. float2 uv_BumpMap;
    42. };
    43.  
    44. void Billboard(inout appdata_t v)
    45. {
    46. UNITY_SETUP_INSTANCE_ID(v);
    47.  
    48. 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.
    49. const float3 offset = v.vertex.xyz - local;
    50.  
    51. const float3 upVector = half3(0, 1, 0);
    52. const float3 forwardVector = UNITY_MATRIX_IT_MV[2].xyz; // camera forward
    53. const float3 rightVector = normalize(cross(forwardVector, upVector));
    54.  
    55. float3 position = 0;
    56. position += local.x * rightVector;
    57. position += local.y * upVector;
    58. position += local.z * forwardVector;
    59.  
    60. v.vertex = float4(offset + position, 1);
    61. v.normal = forwardVector;
    62. }
    63.  
    64. void vert(inout appdata_t v, out Input o)
    65. {
    66. UNITY_INITIALIZE_OUTPUT(Input, o);
    67. Billboard(v);
    68. }
    69.  
    70. void surf(Input IN, inout SurfaceOutput o) {
    71. fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    72. o.Albedo = c.rgb;
    73. o.Alpha = c.a;
    74. o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    75. }
    76. ENDCG
    77. }
    78. }
     
  2. nat42

    nat42

    Joined:
    Jun 10, 2017
    Posts:
    353
    Seems weird to use the two orthogonal planes approach to trees, with a billboard technique to make them always face the camera. Why not just the single camera facing plane, and ditch the plane that should be invisible if facing was perfect?

    Also if the tree geometry is quads, perhaps try tight fit geometry? Perhaps even split into two models, a transparent version that draws the edges and an opaque version that draws the inner part of the foliage and the trunk. That way you let the tile based renderer eliminate a fair amount of the overdraw, especially in the worst case where you are at ground level and looking through the forest of trees, perhaps with the screen seeming to be filled with a single tree I suspect the poor mobile GPU might have to shade all of the ones behind.
     
  3. jubaerjams8548

    jubaerjams8548

    Joined:
    Jun 8, 2020
    Posts:
    41
    from where have you got the original code?