UNPKG

three

Version:

JavaScript 3D library

263 lines (137 loc) 4.5 kB
import Node from '../core/Node.js'; import { nodeObject, vec3 } from '../tsl/TSLBase.js'; const sortLights = ( lights ) => { return lights.sort( ( a, b ) => a.id - b.id ); }; const getLightNodeById = ( id, lightNodes ) => { for ( const lightNode of lightNodes ) { if ( lightNode.isAnalyticLightNode && lightNode.light.id === id ) { return lightNode; } } return null; }; const _lightsNodeRef = /*@__PURE__*/ new WeakMap(); class LightsNode extends Node { static get type() { return 'LightsNode'; } constructor() { super( 'vec3' ); this.totalDiffuseNode = vec3().toVar( 'totalDiffuse' ); this.totalSpecularNode = vec3().toVar( 'totalSpecular' ); this.outgoingLightNode = vec3().toVar( 'outgoingLight' ); this._lights = []; this._lightNodes = null; this._lightNodesHash = null; this.global = true; } getHash( builder ) { if ( this._lightNodesHash === null ) { if ( this._lightNodes === null ) this.setupLightsNode( builder ); const hash = []; for ( const lightNode of this._lightNodes ) { hash.push( lightNode.getSelf().getHash() ); } this._lightNodesHash = 'lights-' + hash.join( ',' ); } return this._lightNodesHash; } analyze( builder ) { const properties = builder.getDataFromNode( this ); for ( const node of properties.nodes ) { node.build( builder ); } } setupLightsNode( builder ) { const lightNodes = []; const previousLightNodes = this._lightNodes; const lights = sortLights( this._lights ); const nodeLibrary = builder.renderer.library; for ( const light of lights ) { if ( light.isNode ) { lightNodes.push( nodeObject( light ) ); } else { let lightNode = null; if ( previousLightNodes !== null ) { lightNode = getLightNodeById( light.id, previousLightNodes ); // resuse existing light node } if ( lightNode === null ) { const lightNodeClass = nodeLibrary.getLightNodeClass( light.constructor ); if ( lightNodeClass === null ) { console.warn( `LightsNode.setupNodeLights: Light node not found for ${ light.constructor.name }` ); continue; } let lightNode = null; if ( ! _lightsNodeRef.has( light ) ) { lightNode = nodeObject( new lightNodeClass( light ) ); _lightsNodeRef.set( light, lightNode ); } else { lightNode = _lightsNodeRef.get( light ); } lightNodes.push( lightNode ); } } } this._lightNodes = lightNodes; } setupLights( builder, lightNodes ) { for ( const lightNode of lightNodes ) { lightNode.build( builder ); } } setup( builder ) { if ( this._lightNodes === null ) this.setupLightsNode( builder ); const context = builder.context; const lightingModel = context.lightingModel; let outgoingLightNode = this.outgoingLightNode; if ( lightingModel ) { const { _lightNodes, totalDiffuseNode, totalSpecularNode } = this; context.outgoingLight = outgoingLightNode; const stack = builder.addStack(); // const properties = builder.getDataFromNode( this ); properties.nodes = stack.nodes; // lightingModel.start( context, stack, builder ); // lights this.setupLights( builder, _lightNodes ); // lightingModel.indirect( context, stack, builder ); // const { backdrop, backdropAlpha } = context; const { directDiffuse, directSpecular, indirectDiffuse, indirectSpecular } = context.reflectedLight; let totalDiffuse = directDiffuse.add( indirectDiffuse ); if ( backdrop !== null ) { if ( backdropAlpha !== null ) { totalDiffuse = vec3( backdropAlpha.mix( totalDiffuse, backdrop ) ); } else { totalDiffuse = vec3( backdrop ); } context.material.transparent = true; } totalDiffuseNode.assign( totalDiffuse ); totalSpecularNode.assign( directSpecular.add( indirectSpecular ) ); outgoingLightNode.assign( totalDiffuseNode.add( totalSpecularNode ) ); // lightingModel.finish( context, stack, builder ); // outgoingLightNode = outgoingLightNode.bypass( builder.removeStack() ); } return outgoingLightNode; } setLights( lights ) { this._lights = lights; this._lightNodes = null; this._lightNodesHash = null; return this; } getLights() { return this._lights; } get hasLights() { return this._lights.length > 0; } } export default LightsNode; export const lights = ( lights = [] ) => nodeObject( new LightsNode() ).setLights( lights );