Search Unity

Question Using tranformation matrixes with GPU instancing

Discussion in 'Shaders' started by Nordjk, Jan 16, 2022.

  1. Nordjk

    Nordjk

    Joined:
    Aug 3, 2020
    Posts:
    3
    I'm trying to apply a billboard shader to meshes drew on top of a terrain with DrawMeshInstancedIndirect, but I can't find a way to make it work. The compute buffer contains a 4x4Matrix,with position, rotation and scale, and the normal. It looks like the built in matrixes are relative to a mesh drew at the terrain origin, even though if I replace o.vertex with UnityObjectToClipPos(pos) it works fine (without the effect). I've tried different techniques but all give the same result. I'm using urp.
    Any help is appreciated!

    Current result



    Shader
    Code (CSharp):
    1. Shader "Custom/InstancedIndirectGrass" {
    2.     Properties
    3.     {
    4.         _MainTex ("Texture", 2D) = "white" {}
    5.     }
    6.     SubShader {
    7.         Tags { "RenderType" = "Opaque" }
    8.         LOD 100
    9.  
    10.         Pass {
    11.             ZTest On
    12.             Cull Off
    13.  
    14.             CGPROGRAM
    15.             #pragma vertex vert
    16.             #pragma fragment frag
    17.  
    18.             #include "UnityCG.cginc"
    19.  
    20.             struct appdata_t {
    21.                 float4 vertex   : POSITION;
    22.                 float4 color    : COLOR;
    23.                 float3 normal   : NORMAL;
    24.                 float2 uv       : TEXCOORD0;
    25.             };
    26.  
    27.             struct v2f {
    28.                 float4 vertex   : SV_POSITION;
    29.                 fixed4 color    : COLOR;
    30.                 float3 normal   : NORMAL;
    31.                 float2 uv       : TEXCOORD0;
    32.             };
    33.  
    34.             struct MeshProperties {
    35.                 float4x4 mat;
    36.                 float3 normal;
    37.             };
    38.  
    39.             StructuredBuffer<MeshProperties> _Properties;
    40.  
    41.             Texture2D _MainTex;
    42.             SamplerState sampler_MainTex;
    43.             float4 _MainTex_ST;
    44.  
    45.             v2f vert(appdata_t i, uint instanceID: SV_InstanceID) {
    46.                 v2f o;
    47.                 // data
    48.                 float4 pos = mul(_Properties[instanceID].mat, i.vertex);
    49.                
    50.                 float4 worldOrigin = mul(unity_ObjectToWorld, float4(0, 0, 0, 1));
    51.                 float4 viewOrigin = float4(UnityObjectToViewPos(float3(0, 0, 0)), 1);
    52.                
    53.                 // Billboard effect
    54.                 float4 worldPosition = mul(unity_ObjectToWorld, pos);
    55.                 // Removed rotation
    56.                 float4 viewPosition = worldPosition - worldOrigin + viewOrigin;
    57.                 float4 clipPosition = mul(UNITY_MATRIX_P, viewPosition);
    58.  
    59.                 o.vertex = clipPosition;
    60.  
    61.                 o.normal = _Properties[instanceID].normal;
    62.                 o.uv = TRANSFORM_TEX(i.uv, _MainTex);
    63.                
    64.                 return o;
    65.             }
    66.  
    67.             fixed4 frag(v2f i) : SV_Target {
    68.                 fixed4 col = _MainTex.Sample(sampler_MainTex, i.uv);
    69.                 clip(col.a - 0.5);
    70.                 return col;
    71.             }
    72.  
    73.             ENDCG
    74.         }
    75.     }
    76. }
     
  2. Nordjk

    Nordjk

    Joined:
    Aug 3, 2020
    Posts:
    3
    I fixed it, it was my fault. I had to change worldOrigin and viewOrigin using the mesh origin position, which I added to the buffer.