| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- import { Color, Node, Vector3 } from 'three/webgpu';
- import { Loop, NodeUpdateType, mix, normalWorld, renderGroup, uniform, uniformArray } from 'three/tsl';
- const warn = ( message ) => {
- console.warn( `THREE.HemisphereLightDataNode: ${ message }` );
- };
- /**
- * Batched data node for hemisphere lights in dynamic lighting mode.
- *
- * @augments Node
- */
- class HemisphereLightDataNode extends Node {
- static get type() {
- return 'HemisphereLightDataNode';
- }
- constructor( maxCount = 4 ) {
- super();
- this.maxCount = maxCount;
- this._lights = [];
- this._skyColors = [];
- this._groundColors = [];
- this._directions = [];
- for ( let i = 0; i < maxCount; i ++ ) {
- this._skyColors.push( new Color() );
- this._groundColors.push( new Color() );
- this._directions.push( new Vector3() );
- }
- this.skyColorsNode = uniformArray( this._skyColors, 'color' ).setGroup( renderGroup );
- this.groundColorsNode = uniformArray( this._groundColors, 'color' ).setGroup( renderGroup );
- this.directionsNode = uniformArray( this._directions, 'vec3' ).setGroup( renderGroup );
- this.countNode = uniform( 0, 'int' ).setGroup( renderGroup );
- this.updateType = NodeUpdateType.RENDER;
- }
- setLights( lights ) {
- if ( lights.length > this.maxCount ) {
- warn( `${ lights.length } lights exceed the configured max of ${ this.maxCount }. Excess lights are ignored.` );
- }
- this._lights = lights;
- return this;
- }
- update() {
- const count = Math.min( this._lights.length, this.maxCount );
- this.countNode.value = count;
- for ( let i = 0; i < count; i ++ ) {
- const light = this._lights[ i ];
- this._skyColors[ i ].copy( light.color ).multiplyScalar( light.intensity );
- this._groundColors[ i ].copy( light.groundColor ).multiplyScalar( light.intensity );
- this._directions[ i ].setFromMatrixPosition( light.matrixWorld ).normalize();
- }
- }
- setup( builder ) {
- Loop( this.countNode, ( { i } ) => {
- const skyColor = this.skyColorsNode.element( i );
- const groundColor = this.groundColorsNode.element( i );
- const lightDirection = this.directionsNode.element( i );
- const hemiDiffuseWeight = normalWorld.dot( lightDirection ).mul( 0.5 ).add( 0.5 );
- const irradiance = mix( groundColor, skyColor, hemiDiffuseWeight );
- builder.context.irradiance.addAssign( irradiance );
- } );
- }
- }
- export default HemisphereLightDataNode;
|