Sfoglia il codice sorgente

Add missing TSL files.

Mugen87 1 settimana fa
parent
commit
c1fa418d66

+ 61 - 0
examples/jsm/tsl/lighting/data/AmbientLightDataNode.js

@@ -0,0 +1,61 @@
+import { Color, Node } from 'three/webgpu';
+import { NodeUpdateType, renderGroup, uniform } from 'three/tsl';
+
+/**
+ * Batched data node for ambient lights in dynamic lighting mode.
+ *
+ * @augments Node
+ */
+class AmbientLightDataNode extends Node {
+
+	static get type() {
+
+		return 'AmbientLightDataNode';
+
+	}
+
+	constructor() {
+
+		super();
+
+		this._color = new Color();
+		this._lights = [];
+
+		this.colorNode = uniform( this._color ).setGroup( renderGroup );
+		this.updateType = NodeUpdateType.RENDER;
+
+	}
+
+	setLights( lights ) {
+
+		this._lights = lights;
+
+		return this;
+
+	}
+
+	update() {
+
+		this._color.setScalar( 0 );
+
+		for ( let i = 0; i < this._lights.length; i ++ ) {
+
+			const light = this._lights[ i ];
+
+			this._color.r += light.color.r * light.intensity;
+			this._color.g += light.color.g * light.intensity;
+			this._color.b += light.color.b * light.intensity;
+
+		}
+
+	}
+
+	setup( builder ) {
+
+		builder.context.irradiance.addAssign( this.colorNode );
+
+	}
+
+}
+
+export default AmbientLightDataNode;

+ 111 - 0
examples/jsm/tsl/lighting/data/DirectionalLightDataNode.js

@@ -0,0 +1,111 @@
+import { Color, Node, Vector3 } from 'three/webgpu';
+import { Loop, NodeUpdateType, renderGroup, uniform, uniformArray, vec3 } from 'three/tsl';
+
+const _lightPosition = /*@__PURE__*/ new Vector3();
+const _targetPosition = /*@__PURE__*/ new Vector3();
+
+const warn = ( message ) => {
+
+	console.warn( `THREE.DirectionalLightDataNode: ${ message }` );
+
+};
+
+/**
+ * Batched data node for directional lights in dynamic lighting mode.
+ *
+ * @augments Node
+ */
+class DirectionalLightDataNode extends Node {
+
+	static get type() {
+
+		return 'DirectionalLightDataNode';
+
+	}
+
+	constructor( maxCount = 8 ) {
+
+		super();
+
+		this.maxCount = maxCount;
+		this._lights = [];
+		this._colors = [];
+		this._directions = [];
+
+		for ( let i = 0; i < maxCount; i ++ ) {
+
+			this._colors.push( new Color() );
+			this._directions.push( new Vector3() );
+
+		}
+
+		this.colorsNode = uniformArray( this._colors, '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( { camera } ) {
+
+		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._colors[ i ].copy( light.color ).multiplyScalar( light.intensity );
+
+			_lightPosition.setFromMatrixPosition( light.matrixWorld );
+			_targetPosition.setFromMatrixPosition( light.target.matrixWorld );
+
+			this._directions[ i ].subVectors( _lightPosition, _targetPosition ).transformDirection( camera.matrixWorldInverse );
+
+		}
+
+	}
+
+	setup( builder ) {
+
+		const { lightingModel, reflectedLight } = builder.context;
+		const dynDiffuse = vec3( 0 ).toVar( 'dynDirectionalDiffuse' );
+		const dynSpecular = vec3( 0 ).toVar( 'dynDirectionalSpecular' );
+
+		Loop( this.countNode, ( { i } ) => {
+
+			const lightColor = this.colorsNode.element( i ).toVar();
+			const lightDirection = this.directionsNode.element( i ).normalize().toVar();
+
+			lightingModel.direct( {
+				lightDirection,
+				lightColor,
+				lightNode: { light: {}, shadowNode: null },
+				reflectedLight: { directDiffuse: dynDiffuse, directSpecular: dynSpecular }
+			}, builder );
+
+		} );
+
+		reflectedLight.directDiffuse.addAssign( dynDiffuse );
+		reflectedLight.directSpecular.addAssign( dynSpecular );
+
+	}
+
+}
+
+export default DirectionalLightDataNode;

+ 99 - 0
examples/jsm/tsl/lighting/data/HemisphereLightDataNode.js

@@ -0,0 +1,99 @@
+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;

+ 134 - 0
examples/jsm/tsl/lighting/data/PointLightDataNode.js

@@ -0,0 +1,134 @@
+import { Color, Node, Vector3, Vector4 } from 'three/webgpu';
+import { Loop, NodeUpdateType, getDistanceAttenuation, positionView, renderGroup, uniform, uniformArray, vec3 } from 'three/tsl';
+
+const _position = /*@__PURE__*/ new Vector3();
+
+const warn = ( message ) => {
+
+	console.warn( `THREE.PointLightDataNode: ${ message }` );
+
+};
+
+/**
+ * Batched data node for point lights in dynamic lighting mode.
+ *
+ * @augments Node
+ */
+class PointLightDataNode extends Node {
+
+	static get type() {
+
+		return 'PointLightDataNode';
+
+	}
+
+	constructor( maxCount = 16 ) {
+
+		super();
+
+		this.maxCount = maxCount;
+		this._lights = [];
+		this._colors = [];
+		this._positionsAndCutoff = [];
+		this._decays = [];
+
+		for ( let i = 0; i < maxCount; i ++ ) {
+
+			this._colors.push( new Color() );
+			this._positionsAndCutoff.push( new Vector4() );
+			this._decays.push( new Vector4() );
+
+		}
+
+		this.colorsNode = uniformArray( this._colors, 'color' ).setGroup( renderGroup );
+		this.positionsAndCutoffNode = uniformArray( this._positionsAndCutoff, 'vec4' ).setGroup( renderGroup );
+		this.decaysNode = uniformArray( this._decays, 'vec4' ).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( { camera } ) {
+
+		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._colors[ i ].copy( light.color ).multiplyScalar( light.intensity );
+
+			_position.setFromMatrixPosition( light.matrixWorld );
+			_position.applyMatrix4( camera.matrixWorldInverse );
+
+			const positionAndCutoff = this._positionsAndCutoff[ i ];
+			positionAndCutoff.x = _position.x;
+			positionAndCutoff.y = _position.y;
+			positionAndCutoff.z = _position.z;
+			positionAndCutoff.w = light.distance;
+
+			this._decays[ i ].x = light.decay;
+
+		}
+
+	}
+
+	setup( builder ) {
+
+		const surfacePosition = builder.context.positionView || positionView;
+		const { lightingModel, reflectedLight } = builder.context;
+		const dynDiffuse = vec3( 0 ).toVar( 'dynPointDiffuse' );
+		const dynSpecular = vec3( 0 ).toVar( 'dynPointSpecular' );
+
+		Loop( this.countNode, ( { i } ) => {
+
+			const positionAndCutoff = this.positionsAndCutoffNode.element( i );
+			const lightViewPosition = positionAndCutoff.xyz;
+			const cutoffDistance = positionAndCutoff.w;
+			const decayExponent = this.decaysNode.element( i ).x;
+
+			const lightVector = lightViewPosition.sub( surfacePosition ).toVar();
+			const lightDirection = lightVector.normalize().toVar();
+			const lightDistance = lightVector.length();
+
+			const attenuation = getDistanceAttenuation( {
+				lightDistance,
+				cutoffDistance,
+				decayExponent
+			} );
+
+			const lightColor = this.colorsNode.element( i ).mul( attenuation ).toVar();
+
+			lightingModel.direct( {
+				lightDirection,
+				lightColor,
+				lightNode: { light: {}, shadowNode: null },
+				reflectedLight: { directDiffuse: dynDiffuse, directSpecular: dynSpecular }
+			}, builder );
+
+		} );
+
+		reflectedLight.directDiffuse.addAssign( dynDiffuse );
+		reflectedLight.directSpecular.addAssign( dynSpecular );
+
+	}
+
+}
+
+export default PointLightDataNode;

+ 161 - 0
examples/jsm/tsl/lighting/data/SpotLightDataNode.js

@@ -0,0 +1,161 @@
+import { Color, Node, Vector3, Vector4 } from 'three/webgpu';
+import { Loop, NodeUpdateType, getDistanceAttenuation, positionView, renderGroup, smoothstep, uniform, uniformArray, vec3 } from 'three/tsl';
+
+const _lightPosition = /*@__PURE__*/ new Vector3();
+const _targetPosition = /*@__PURE__*/ new Vector3();
+
+const warn = ( message ) => {
+
+	console.warn( `THREE.SpotLightDataNode: ${ message }` );
+
+};
+
+/**
+ * Batched data node for simple spot lights in dynamic lighting mode.
+ *
+ * Projected spot lights keep the default per-light path.
+ *
+ * @augments Node
+ */
+class SpotLightDataNode extends Node {
+
+	static get type() {
+
+		return 'SpotLightDataNode';
+
+	}
+
+	constructor( maxCount = 16 ) {
+
+		super();
+
+		this.maxCount = maxCount;
+		this._lights = [];
+		this._colors = [];
+		this._positionsAndCutoff = [];
+		this._directionsAndDecay = [];
+		this._cones = [];
+
+		for ( let i = 0; i < maxCount; i ++ ) {
+
+			this._colors.push( new Color() );
+			this._positionsAndCutoff.push( new Vector4() );
+			this._directionsAndDecay.push( new Vector4() );
+			this._cones.push( new Vector4() );
+
+		}
+
+		this.colorsNode = uniformArray( this._colors, 'color' ).setGroup( renderGroup );
+		this.positionsAndCutoffNode = uniformArray( this._positionsAndCutoff, 'vec4' ).setGroup( renderGroup );
+		this.directionsAndDecayNode = uniformArray( this._directionsAndDecay, 'vec4' ).setGroup( renderGroup );
+		this.conesNode = uniformArray( this._cones, 'vec4' ).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( { camera } ) {
+
+		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._colors[ i ].copy( light.color ).multiplyScalar( light.intensity );
+
+			_lightPosition.setFromMatrixPosition( light.matrixWorld );
+			_lightPosition.applyMatrix4( camera.matrixWorldInverse );
+
+			const positionAndCutoff = this._positionsAndCutoff[ i ];
+			positionAndCutoff.x = _lightPosition.x;
+			positionAndCutoff.y = _lightPosition.y;
+			positionAndCutoff.z = _lightPosition.z;
+			positionAndCutoff.w = light.distance;
+
+			_lightPosition.setFromMatrixPosition( light.matrixWorld );
+			_targetPosition.setFromMatrixPosition( light.target.matrixWorld );
+			_lightPosition.sub( _targetPosition ).transformDirection( camera.matrixWorldInverse );
+
+			const directionAndDecay = this._directionsAndDecay[ i ];
+			directionAndDecay.x = _lightPosition.x;
+			directionAndDecay.y = _lightPosition.y;
+			directionAndDecay.z = _lightPosition.z;
+			directionAndDecay.w = light.decay;
+
+			const cone = this._cones[ i ];
+			cone.x = Math.cos( light.angle );
+			cone.y = Math.cos( light.angle * ( 1 - light.penumbra ) );
+
+		}
+
+	}
+
+	setup( builder ) {
+
+		const surfacePosition = builder.context.positionView || positionView;
+		const { lightingModel, reflectedLight } = builder.context;
+		const dynDiffuse = vec3( 0 ).toVar( 'dynSpotDiffuse' );
+		const dynSpecular = vec3( 0 ).toVar( 'dynSpotSpecular' );
+
+		Loop( this.countNode, ( { i } ) => {
+
+			const positionAndCutoff = this.positionsAndCutoffNode.element( i );
+			const lightViewPosition = positionAndCutoff.xyz;
+			const cutoffDistance = positionAndCutoff.w;
+
+			const directionAndDecay = this.directionsAndDecayNode.element( i );
+			const spotDirection = directionAndDecay.xyz;
+			const decayExponent = directionAndDecay.w;
+
+			const cone = this.conesNode.element( i );
+			const coneCos = cone.x;
+			const penumbraCos = cone.y;
+
+			const lightVector = lightViewPosition.sub( surfacePosition ).toVar();
+			const lightDirection = lightVector.normalize().toVar();
+			const lightDistance = lightVector.length();
+
+			const angleCos = lightDirection.dot( spotDirection );
+			const spotAttenuation = smoothstep( coneCos, penumbraCos, angleCos );
+			const distanceAttenuation = getDistanceAttenuation( {
+				lightDistance,
+				cutoffDistance,
+				decayExponent
+			} );
+
+			const lightColor = this.colorsNode.element( i ).mul( spotAttenuation ).mul( distanceAttenuation ).toVar();
+
+			lightingModel.direct( {
+				lightDirection,
+				lightColor,
+				lightNode: { light: {}, shadowNode: null },
+				reflectedLight: { directDiffuse: dynDiffuse, directSpecular: dynSpecular }
+			}, builder );
+
+		} );
+
+		reflectedLight.directDiffuse.addAssign( dynDiffuse );
+		reflectedLight.directSpecular.addAssign( dynSpecular );
+
+	}
+
+}
+
+export default SpotLightDataNode;

粤ICP备19079148号