I am currently trying to implement a specific directional light type.

This light type has been used in the game INSIDE and is called orthogonal spotlight (aka local directional light). I assume that this is a directional light which behaves like a spot light and have a squared or rectangular attenuation but I have some difficulties to integrate it in my deferred pipeline and get the general concept of this light type.

Classical directional light : dot(worldNormal, lightDir)

enter image description here

I hope that you'll be able to give me some clues. Thanks a lot !

  • $\begingroup$ Do you by chance have a screenshot of what you are trying to achieve? (: $\endgroup$
    – Alan Wolfe
    Oct 3 '16 at 14:05
  • $\begingroup$ Unfortunately not but here is a little diagram. It's easy to do a simple directional light dot(worldNormal, lightDir) but how to limit it. $\endgroup$
    – MaT
    Oct 3 '16 at 14:11
  • 3
    $\begingroup$ This isn't a full answer but essentially you want to test if a point is in the oriented box defined by the light. You may want to soften the edges as it gets farther away from the light source but that is more challenging. $\endgroup$
    – Alan Wolfe
    Oct 3 '16 at 15:27

Alan Wolfe is pretty spot on, but I will sum up any way :)

  • render the back-faces of your "unit"-sized-box, [-1;1]
  • sample the zbuffer and transform into light-local coordinates (see our slides for a fast way to do that).
  • early-out of the pixelshader if outside of the box, i.e. if any coordinate in the local-position is outside of -1;1.
  • then do the dot-product between the normal and the lightdir, in whatever space is convenient (you can extract the worldspace-lightdir from the object-to-world matrix).
  • projecting a texture is easy, the UV-coordinates are simply the localspace xy (moved to [0;1])
  • using a falloff texture is eays, the coordinate is simply the localspace z (moved to [0;1])

In an actual game, you of course want to use some sort of acceleration to discard early; we used old-school stencil culling (and should have used depthbounds), but likely tiled culling, clustered culling or similar is better.

You could use zgreater testing to discard pixels where background is entirely behind the light, but iirc on most modern GPUs this will not actually be an advantage, as there will be no early-discard due to the hierarchical zbuffer being primed in the direction of zless.

  • 1
    $\begingroup$ That is coming from the man himself! I'm not sure if it'll be helpful, but here's a raytraced implementation in shadertoy: shadertoy.com/view/4lV3zV $\endgroup$
    – Alan Wolfe
    Oct 5 '16 at 14:07

I would start by looking into deferred decals (you can start here for example, this blogpost has a lot of useful links)

If you understand how the positions are calculated and compared with the volume then you should be able to apply the same logic in the lighting phase.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.