|
1 | 1 | import SpotLightNode from './SpotLightNode.js'; |
2 | 2 |
|
3 | | -import { Fn, vec2 } from '../tsl/TSLCore.js'; |
| 3 | +import { float, Fn, If, vec2 } from '../tsl/TSLCore.js'; |
4 | 4 | import { length, min, max, saturate, acos } from '../math/MathNode.js'; |
5 | 5 | import { div, sub } from '../math/OperatorNode.js'; |
| 6 | +import { lightShadowMatrix } from '../accessors/Lights.js'; |
| 7 | +import { positionWorld } from '../accessors/Position.js'; |
6 | 8 |
|
7 | 9 | const sdBox = /*@__PURE__*/ Fn( ( [ p, b ] ) => { |
8 | 10 |
|
@@ -61,13 +63,24 @@ class ProjectorLightNode extends SpotLightNode { |
61 | 63 | */ |
62 | 64 | getSpotAttenuation( builder ) { |
63 | 65 |
|
| 66 | + const attenuation = float( 0 ).toVar(); |
64 | 67 | const penumbraCos = this.penumbraCosNode; |
65 | | - const spotLightCoord = this.getLightCoord( builder ); |
66 | | - const coord = spotLightCoord.xyz.div( spotLightCoord.w ); |
67 | 68 |
|
68 | | - const boxDist = sdBox( coord.xy.sub( vec2( 0.5 ) ), vec2( 0.5 ) ); |
69 | | - const angleFactor = div( - 1.0, sub( 1.0, acos( penumbraCos ) ).sub( 1.0 ) ); |
70 | | - const attenuation = saturate( boxDist.mul( - 2.0 ).mul( angleFactor ) ); |
| 69 | + // compute the fragment's position in the light's clip space |
| 70 | + |
| 71 | + const spotLightCoord = lightShadowMatrix( this.light ).mul( builder.context.positionWorld || positionWorld ); |
| 72 | + |
| 73 | + // the sign of w determines whether the current fragment is in front or behind the light. |
| 74 | + // to avoid a back-projection, it's important to only compute an attenuation if w is positive |
| 75 | + |
| 76 | + If( spotLightCoord.w.greaterThan( 0 ), () => { |
| 77 | + |
| 78 | + const projectionUV = spotLightCoord.xyz.div( spotLightCoord.w ); |
| 79 | + const boxDist = sdBox( projectionUV.xy.sub( vec2( 0.5 ) ), vec2( 0.5 ) ); |
| 80 | + const angleFactor = div( - 1.0, sub( 1.0, acos( penumbraCos ) ).sub( 1.0 ) ); |
| 81 | + attenuation.assign( saturate( boxDist.mul( - 2.0 ).mul( angleFactor ) ) ); |
| 82 | + |
| 83 | + } ); |
71 | 84 |
|
72 | 85 | return attenuation; |
73 | 86 |
|
|
0 commit comments