Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice
  2. Ever participated in one our Game Jams? Want pointers on your project? Our Evangelists will be available on Friday to give feedback. Come share your games with us!
    Dismiss Notice

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

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

  1. dtysky


    Jul 10, 2018
    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(;
    4.     float attenuation = getLightAttenuation(distanceVec, range);
    5.     float cotanHalfSpotAngle = 2. * lightCoord.z / lightCoord.w;
    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);
    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?

  2. bgolus


    Dec 7, 2012
    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


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