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
Shader "Custom/InstancedIndirectGrass" {
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader {
Tags { "RenderType" = "Opaque" }
LOD 100
Pass {
ZTest On
Cull Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata_t {
float4 vertex : POSITION;
float4 color : COLOR;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
};
struct v2f {
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
};
struct MeshProperties {
float4x4 mat;
float3 normal;
};
StructuredBuffer<MeshProperties> _Properties;
Texture2D _MainTex;
SamplerState sampler_MainTex;
float4 _MainTex_ST;
v2f vert(appdata_t i, uint instanceID: SV_InstanceID) {
v2f o;
// data
float4 pos = mul(_Properties[instanceID].mat, i.vertex);
float4 worldOrigin = mul(unity_ObjectToWorld, float4(0, 0, 0, 1));
float4 viewOrigin = float4(UnityObjectToViewPos(float3(0, 0, 0)), 1);
// Billboard effect
float4 worldPosition = mul(unity_ObjectToWorld, pos);
// Removed rotation
float4 viewPosition = worldPosition - worldOrigin + viewOrigin;
float4 clipPosition = mul(UNITY_MATRIX_P, viewPosition);
o.vertex = clipPosition;
o.normal = _Properties[instanceID].normal;
o.uv = TRANSFORM_TEX(i.uv, _MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target {
fixed4 col = _MainTex.Sample(sampler_MainTex, i.uv);
clip(col.a - 0.5);
return col;
}
ENDCG
}
}
}