DirectionalLightDataNode.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import { Color, Node, Vector3 } from 'three/webgpu';
  2. import { Loop, NodeUpdateType, renderGroup, uniform, uniformArray, vec3 } from 'three/tsl';
  3. const _lightPosition = /*@__PURE__*/ new Vector3();
  4. const _targetPosition = /*@__PURE__*/ new Vector3();
  5. const warn = ( message ) => {
  6. console.warn( `THREE.DirectionalLightDataNode: ${ message }` );
  7. };
  8. /**
  9. * Batched data node for directional lights in dynamic lighting mode.
  10. *
  11. * @augments Node
  12. */
  13. class DirectionalLightDataNode extends Node {
  14. static get type() {
  15. return 'DirectionalLightDataNode';
  16. }
  17. constructor( maxCount = 8 ) {
  18. super();
  19. this.maxCount = maxCount;
  20. this._lights = [];
  21. this._colors = [];
  22. this._directions = [];
  23. for ( let i = 0; i < maxCount; i ++ ) {
  24. this._colors.push( new Color() );
  25. this._directions.push( new Vector3() );
  26. }
  27. this.colorsNode = uniformArray( this._colors, 'color' ).setGroup( renderGroup );
  28. this.directionsNode = uniformArray( this._directions, 'vec3' ).setGroup( renderGroup );
  29. this.countNode = uniform( 0, 'int' ).setGroup( renderGroup );
  30. this.updateType = NodeUpdateType.RENDER;
  31. }
  32. setLights( lights ) {
  33. if ( lights.length > this.maxCount ) {
  34. warn( `${ lights.length } lights exceed the configured max of ${ this.maxCount }. Excess lights are ignored.` );
  35. }
  36. this._lights = lights;
  37. return this;
  38. }
  39. update( { camera } ) {
  40. const count = Math.min( this._lights.length, this.maxCount );
  41. this.countNode.value = count;
  42. for ( let i = 0; i < count; i ++ ) {
  43. const light = this._lights[ i ];
  44. this._colors[ i ].copy( light.color ).multiplyScalar( light.intensity );
  45. _lightPosition.setFromMatrixPosition( light.matrixWorld );
  46. _targetPosition.setFromMatrixPosition( light.target.matrixWorld );
  47. this._directions[ i ].subVectors( _lightPosition, _targetPosition ).transformDirection( camera.matrixWorldInverse );
  48. }
  49. }
  50. setup( builder ) {
  51. const { lightingModel, reflectedLight } = builder.context;
  52. const dynDiffuse = vec3( 0 ).toVar( 'dynDirectionalDiffuse' );
  53. const dynSpecular = vec3( 0 ).toVar( 'dynDirectionalSpecular' );
  54. Loop( this.countNode, ( { i } ) => {
  55. const lightColor = this.colorsNode.element( i ).toVar();
  56. const lightDirection = this.directionsNode.element( i ).normalize().toVar();
  57. lightingModel.direct( {
  58. lightDirection,
  59. lightColor,
  60. lightNode: { light: {}, shadowNode: null },
  61. reflectedLight: { directDiffuse: dynDiffuse, directSpecular: dynSpecular }
  62. }, builder );
  63. } );
  64. reflectedLight.directDiffuse.addAssign( dynDiffuse );
  65. reflectedLight.directSpecular.addAssign( dynSpecular );
  66. }
  67. }
  68. export default DirectionalLightDataNode;
粤ICP备19079148号