SpotLightNode.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import AnalyticLightNode from './AnalyticLightNode.js';
  2. import { lightTargetDirection } from './LightNode.js';
  3. import { addLightNode } from './LightsNode.js';
  4. import { getDistanceAttenuation } from './LightUtils.js';
  5. import { uniform } from '../core/UniformNode.js';
  6. import { smoothstep } from '../math/MathNode.js';
  7. import { objectViewPosition } from '../accessors/Object3DNode.js';
  8. import { positionView } from '../accessors/PositionNode.js';
  9. import { addNodeClass } from '../core/Node.js';
  10. import { SpotLight } from 'three';
  11. class SpotLightNode extends AnalyticLightNode {
  12. constructor( light = null ) {
  13. super( light );
  14. this.coneCosNode = uniform( 0 );
  15. this.penumbraCosNode = uniform( 0 );
  16. this.cutoffDistanceNode = uniform( 0 );
  17. this.decayExponentNode = uniform( 0 );
  18. }
  19. update( frame ) {
  20. super.update( frame );
  21. const { light } = this;
  22. this.coneCosNode.value = Math.cos( light.angle );
  23. this.penumbraCosNode.value = Math.cos( light.angle * ( 1 - light.penumbra ) );
  24. this.cutoffDistanceNode.value = light.distance;
  25. this.decayExponentNode.value = light.decay;
  26. }
  27. getSpotAttenuation( angleCosine ) {
  28. const { coneCosNode, penumbraCosNode } = this;
  29. return smoothstep( coneCosNode, penumbraCosNode, angleCosine );
  30. }
  31. setup( builder ) {
  32. super.setup( builder );
  33. const lightingModel = builder.context.lightingModel;
  34. const { colorNode, cutoffDistanceNode, decayExponentNode, light } = this;
  35. const lVector = objectViewPosition( light ).sub( positionView ); // @TODO: Add it into LightNode
  36. const lightDirection = lVector.normalize();
  37. const angleCos = lightDirection.dot( lightTargetDirection( light ) );
  38. const spotAttenuation = this.getSpotAttenuation( angleCos );
  39. const lightDistance = lVector.length();
  40. const lightAttenuation = getDistanceAttenuation( {
  41. lightDistance,
  42. cutoffDistance: cutoffDistanceNode,
  43. decayExponent: decayExponentNode
  44. } );
  45. const lightColor = colorNode.mul( spotAttenuation ).mul( lightAttenuation );
  46. const reflectedLight = builder.context.reflectedLight;
  47. lightingModel.direct( {
  48. lightDirection,
  49. lightColor,
  50. reflectedLight
  51. }, builder.stack, builder );
  52. }
  53. }
  54. export default SpotLightNode;
  55. addNodeClass( 'SpotLightNode', SpotLightNode );
  56. addLightNode( SpotLight, SpotLightNode );