Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Billboard understainding

Discussion in 'Shaders' started by vbyhgn, Oct 28, 2020.

  1. vbyhgn

    vbyhgn

    Joined:
    Oct 18, 2018
    Posts:
    1
    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, v.vertex.z); // 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. }
    I found this shader in the internet and I want to understand how does Billboard function works, so I can modify it. Now, it only rotates sprite around y axis, but I want it to always look directly at the player
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    The basic of any billboard shader is you need to calculate the rotation matrix that rotates a mesh to face the direction you want. The up, right, and forward vectors in the above code are the 3 parts of a 3x3 rotation matrix. In this example, you know two vectors, “up” (which is the local mesh’s up vector, (0,1,0)), and the camera forward vector. A cross product of two vectors gets you a vector that is perpendicular to both of the inputs, which gets you the “right” vector. The result is a rotation matrix that rotates the mesh only around its y axis, as the “up” vector is hard coded. If you want it to face the camera, add this line after the line that calculates the
    rightVector
    :
    Code (csharp):
    1. upVector = normalize(cross(forwardVector, rightVector));
    That’ll recalculate the up vector to be one that is perpendicular to the forward and just calculated right vector. The original up vector was not necessarily perpendicular to the forward vector, so that line makes sure it is. And now you have a rotation matrix that rotates the mesh to face the camera, and not just around one axis.