I wanted to add billboard functionality to an existing spine URP shader.
However, when I add this code in the middle of an existing Spine URPShader, the following happens depending on where I add it.
- the billboard works fine, but all existing lighting effects (normalmap, rimlighting, etc.) are not applied.
- no billboard is applied, it looks exactly the same as before
- two objects are rendered on the screen, one with billboards applied but no lights, the other with billboards applied but no lights. Both are rendered on the screen at the same time, overlapping.
I want to combine the two shaders so that the billboard is applied and the existing lighting effects are maintained at the same time.
How do I put the code in to make it work the way I want it to?
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
};
sampler2D _MainTex;
float4 _MainTex_ST;
float rayPlaneIntersection(float3 rayDir, float3 rayPos, float3 planeNormal, float3 planePos)
{
float denom = dot(planeNormal, rayDir);
denom = max(denom, 0.000001); // avoid divide by zero
float3 diff = planePos - rayPos;
return dot(diff, planeNormal) / denom;
}
v2f vert(appdata_t v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
// Billboard mesh towards camera
float3 vpos = mul((float3x3)unity_ObjectToWorld, v.vertex.xyz);
float4 worldCoord = float4(unity_ObjectToWorld._m03, unity_ObjectToWorld._m13, unity_ObjectToWorld._m23, 1);
float4 viewPos = mul(UNITY_MATRIX_V, worldCoord) + float4(vpos, 0);
o.pos = mul(UNITY_MATRIX_P, viewPos);
// Calculate distance to vertical billboard plane seen at this vertex's screen position
float3 planeNormal = normalize(float3(UNITY_MATRIX_V._m20, 0.0, UNITY_MATRIX_V._m22));
float3 planePoint = unity_ObjectToWorld._m03_m13_m23;
float3 rayStart = _WorldSpaceCameraPos.xyz;
float3 rayDir = -normalize(mul(UNITY_MATRIX_I_V, float4(viewPos.xyz, 1.0)).xyz - rayStart); // Convert view to world, minus camera pos
float dist = rayPlaneIntersection(rayDir, rayStart, planeNormal, planePoint);
// Calculate the clip space z for the vertical plane
float4 planeOutPos = mul(UNITY_MATRIX_VP, float4(rayStart + rayDir * dist, 1.0));
float newPosZ = planeOutPos.z / planeOutPos.w * o.pos.w;
// Use the closest clip space z
#if defined(UNITY_REVERSED_Z)
o.pos.z = max(o.pos.z, newPosZ);
#else
o.pos.z = min(o.pos.z, newPosZ);
#endif
UNITY_TRANSFER_FOG(o, o.pos);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDHLSL