LightsNode.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import Node from '../core/Node.js';
  2. import AnalyticLightNode from './AnalyticLightNode.js';
  3. import { nodeObject, nodeProxy } from '../shadernode/ShaderNode.js';
  4. const LightNodes = new WeakMap();
  5. const sortLights = ( lights ) => {
  6. return lights.sort( ( a, b ) => a.id - b.id );
  7. };
  8. class LightsNode extends Node {
  9. constructor( lightNodes = [] ) {
  10. super( 'vec3' );
  11. this.lightNodes = lightNodes;
  12. this._hash = null;
  13. }
  14. get hasLight() {
  15. return this.lightNodes.length > 0;
  16. }
  17. construct( builder ) {
  18. const lightNodes = this.lightNodes;
  19. for ( const lightNode of lightNodes ) {
  20. lightNode.build( builder );
  21. }
  22. }
  23. getHash( builder ) {
  24. if ( this._hash === null ) {
  25. let hash = '';
  26. const lightNodes = this.lightNodes;
  27. for ( const lightNode of lightNodes ) {
  28. hash += lightNode.getHash( builder ) + ' ';
  29. }
  30. this._hash = hash;
  31. }
  32. return this._hash;
  33. }
  34. getLightNodeByHash( hash ) {
  35. const lightNodes = this.lightNodes;
  36. for ( const lightNode of lightNodes ) {
  37. if ( lightNode.light.uuid === hash ) {
  38. return lightNode;
  39. }
  40. }
  41. return null;
  42. }
  43. fromLights( lights = [] ) {
  44. const lightNodes = [];
  45. lights = sortLights( lights );
  46. for ( const light of lights ) {
  47. let lightNode = this.getLightNodeByHash( light.uuid );
  48. if ( lightNode === null ) {
  49. const lightClass = light.constructor;
  50. const lightNodeClass = LightNodes.has( lightClass ) ? LightNodes.get( lightClass ) : AnalyticLightNode;
  51. lightNode = nodeObject( new lightNodeClass( light ) );
  52. }
  53. lightNodes.push( lightNode );
  54. }
  55. this.lightNodes = lightNodes;
  56. this._hash = null;
  57. return this;
  58. }
  59. }
  60. export default LightsNode;
  61. export const lights = ( lights ) => nodeObject( new LightsNode().fromLights( lights ) );
  62. export const lightsWithoutWrap = nodeProxy( LightsNode );
  63. export function addLightNode( lightClass, lightNodeClass ) {
  64. if ( LightNodes.has( lightClass ) ) throw new Error( `Redefinition of light node ${ lightNodeClass.name }` );
  65. if ( typeof lightClass !== 'function' || ! lightClass.name ) throw new Error( `Light ${ lightClass.name } is not a class` );
  66. if ( typeof lightNodeClass !== 'function' || ! lightNodeClass.name ) throw new Error( `Light node ${ lightNodeClass.name } is not a class` );
  67. LightNodes.set( lightClass, lightNodeClass );
  68. }