# How can I get spot light direction in forward add pass?

Discussion in 'Shaders' started by dtysky, Jun 21, 2019.

1. ### dtysky

Joined:
Jul 10, 2018
Posts:
2
Hi everyone, I am writing my own PBR shader that uses physic lights, so it needs `range`, `direction` and `angle` of spot lights. I have get the `range` and `angle` by some trick, but has no idea that how to get `direction`:

Code (CSharp):
1. #if defined (SPOT)
2.     float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
3.     float range = length(distanceVec) / length(lightCoord.xyz);
4.     float attenuation = getLightAttenuation(distanceVec, range);
5.     float cotanHalfSpotAngle = 2. * lightCoord.z / lightCoord.w;
6.
7.     // a trial, but not working
8.     float3 lightSpaceUnitDir = float3(0., 0., 1.);
9.     float3 worldLightUnitDir = mul(lightSpaceUnitDir, inverse((float3x3)unity_WorldToLight));
10.     pbr.L = mul(UNITY_MATRIX_V, worldLightUnitDir);
11.
12.     float outerCutoff = atan(1. / cotanHalfSpotAngle);
13.     float cutoff = max(outerCutoff - .05, 0.);
14.     float theta = dot(normalize(distanceVec), pbr.L);
15.     float epsilon = cos(outerCutoff) - cos(cutoff);
16.     float intensity = clamp((theta - cos(cutoff)) / epsilon, 0.0, 1.0);
17.     attenuation *= intensity;
18. #endif
How can I get it? Why does not unity give us this information when we need to calculate attenuation ourselves?

Thanks!

2. ### bgolus

Joined:
Dec 7, 2012
Posts:
6,970
For a spotlight, the unity_WorldToLight matrix is a transform and perspective matrix, which makes things a little funny. However you're pretty close already:

float3 worldLightUnitDir = normalize(mul(float3(0,0,1), (float3x3)unity_WorldToLight));

For an orthogonal matrix, the transpose and the inverse are the same, and doing the mul in vector matrix order applies the matrix as transposed vs matrix vector order. This only works because the forward axis of the matrix isn't affected by the perspective, but it does work.

3. ### dtysky

Joined:
Jul 10, 2018
Posts:
2
Thanks! You save my time ! I finally solve this problem by `float3 worldLightUnitDir = normalize(mul(float3(0,0,-1 (float3x3)unity_WorldToLight));`