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.

Implementing a simple directional light is simple dot(worldNormal, lightDir) but what kind of data should I use to constraint its application into a square or a rectangle ?

enter image description here

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

  • 1
    \$\begingroup\$ Without specifying your problem, I doubt anyone could solve it. \$\endgroup\$ Oct 3 '16 at 13:09
  • \$\begingroup\$ Integrating a directional light is simple, just do a dot(worldNormal, lightDir) but what should I use to implement a local directional light ? The problem is that I don't see what kind of data should I use and how. \$\endgroup\$
    – MaT
    Oct 3 '16 at 13:42
  • \$\begingroup\$ I am not sure that I am right, but you could use an orthogonal (box) matrix and check if the world position of the pixel is inside and light it accodingly. For a falloff, use the distance from the side of the box. If you want more detail, please specify (maybe illustrate) your problem further. \$\endgroup\$ Oct 3 '16 at 14:10
  • \$\begingroup\$ Thanks for the suggestion, I've added a diagram to illustrate what I am looking for. \$\endgroup\$
    – MaT
    Oct 3 '16 at 14:30
  • 1
    \$\begingroup\$ Good picture, now it is obvious what you are asking. The solution is simple. I will write an answer if the question gets re-enabled. The short version: Transform your pixel position with the inverse of the light box matrix. If the position is inside the 0-1 range (or -1,1 if the box matrix is centered) in the XYZ components, then it is inside the light so you should wdd the light contribution. If it is outside the range, leave it as it is. \$\endgroup\$ Oct 3 '16 at 15:23

You have a box matrix, which is the orientation and the scale of your light. If you would apply that matrix to a unit box, then you would get your light box.

Now you need the inverse of that box matrix. Transform the pixel's world position with that inverse matrix, because that gives you the pixel's position in the light's local space. If that position is inside a unit box (meaning, the position's x,y,z coordinates are inside the (-1,1) range if your unit box's half extents are 1) then it is inside the light so you should apply the light contribution (multiply its color with the dot(worldNormal,lightDir)).

If you have that working, you could apply a nicer "falloff" by multiplying the light contribution according to how close the pixel's light space position is to the vector (0,0,0). That way you can get a nice gradient, not a simple cutoff.

  • \$\begingroup\$ Thanks for the answer ! I am now in the light space coordinate : float3 localPos = mul(inverseMatrix, float4(worldPos, 1)); and I am trying to detect if I am in the range of the box like Inigo Quilez do it : length(max(abs(localPos) - boxSize, 0.0)); but this results in a gradient and not sharp edges. Any idea why ? \$\endgroup\$
    – MaT
    Oct 4 '16 at 12:06
  • \$\begingroup\$ If you don't want a gradient, use a binary function like this: 'length(max(abs(localPos) - boxSize, 0.0)) < 1.0 ? 1.0 : 0.0;' \$\endgroup\$ Oct 4 '16 at 12:23
  • 1
    \$\begingroup\$ If you want a better and tuneable gradient, you should use smoothstep \$\endgroup\$
    – Alan Wolfe
    Oct 4 '16 at 21:04
  • \$\begingroup\$ Also smoothstep avoid branching which is better I think. \$\endgroup\$
    – MaT
    Oct 5 '16 at 6:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .