Răsfoiți Sursa

SpotLightShadow: Introduce `aspect` property (#31020)

* TSL: Fix convert `.set*()` value to node-object

* SpotLightShadow: Introduce `aspect`

* improve custom aspect example

* cleanup

* Update webgpu_lights_spotlight.html

* Update webgpu_lights_spotlight.html
sunag 8 luni în urmă
părinte
comite
8ee79cfe94

+ 21 - 7
examples/webgpu_lights_spotlight.html

@@ -26,7 +26,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { Fn, vec2, length, abs, max, min, div, mul, clamp, acos } from 'three/tsl';
+			import { Fn, vec2, length, uniform, abs, max, min, sub, div, saturate, acos } from 'three/tsl';
 
 			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 
@@ -41,6 +41,8 @@
 
 			function init() {
 
+				// Renderer
+
 				renderer = new THREE.WebGPURenderer( { antialias: true } );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
@@ -58,6 +60,8 @@
 				camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 0.1, 100 );
 				camera.position.set( 7, 4, 1 );
 
+				// Controls
+
 				const controls = new OrbitControls( camera, renderer.domElement );
 				controls.minDistance = 2;
 				controls.maxDistance = 10;
@@ -65,8 +69,7 @@
 				controls.target.set( 0, 1, 0 );
 				controls.update();
 
-				const ambient = new THREE.HemisphereLight( 0xffffff, 0x8d8d8d, 0.15 );
-				scene.add( ambient );
+				// Textures
 
 				const loader = new THREE.TextureLoader().setPath( 'textures/' );
 				const filenames = [ 'disturb.jpg', 'colors.png', 'uv_grid_opengl.jpg' ];
@@ -87,8 +90,15 @@
 
 				}
 
+				// Lights
+
+				const ambient = new THREE.HemisphereLight( 0xffffff, 0x8d8d8d, 0.15 );
+				scene.add( ambient );
+
 				const boxAttenuationFn = Fn( ( [ lightNode ], builder ) => {
 
+					const light = lightNode.light;
+
 					const sdBox = Fn( ( [ p, b ] ) => {
 
 						const d = vec2( abs( p ).sub( b ) ).toVar();
@@ -97,13 +107,13 @@
 
 					} );
 
-					const penumbraCos = lightNode.penumbraCosNode;
+					const penumbraCos = uniform( 'float' ).onRenderUpdate( () => Math.min( Math.cos( light.angle * ( 1 - light.penumbra ) ), .99999 ) );
 					const spotLightCoord = lightNode.getSpotLightCoord( builder );
 					const coord = spotLightCoord.xyz.div( spotLightCoord.w );
 
 					const boxDist = sdBox( coord.xy.sub( vec2( 0.5 ) ), vec2( 0.5 ) );
-					const angleFactor = div( 1.0, acos( penumbraCos ).sub( 1.0 ) );
-					const attenuation = clamp( mul( 2.0, boxDist ).mul( angleFactor ), 0.0, 1.0 );
+					const angleFactor = div( -1.0, sub( 1.0, acos( penumbraCos ) ).sub( 1.0 ) );
+					const attenuation = saturate( boxDist.mul( - 2.0 ).mul( angleFactor ) );
 
 					return attenuation;
 
@@ -140,7 +150,7 @@
 				mesh.receiveShadow = true;
 				scene.add( mesh );
 
-				//
+				// Models
 
 				new PLYLoader().load( 'models/ply/binary/Lucy100k.ply', function ( geometry ) {
 
@@ -246,8 +256,12 @@
 
 					spotLight.attenuationNode = val ? boxAttenuationFn : null;
 
+					aspectGUI.setValue( 1 ).enable( val );
+
 				} );
 
+				const aspectGUI = gui.add( spotLight.shadow, 'aspect', 0, 2 ).enable( false );
+
 				gui.open();
 
 			}

+ 9 - 1
src/lights/SpotLightShadow.js

@@ -34,6 +34,14 @@ class SpotLightShadow extends LightShadow {
 		 */
 		this.focus = 1;
 
+		/**
+		 * Texture aspect ratio.
+		 *
+		 * @type {number}
+		 * @default 1
+		 */
+		this.aspect = 1;
+
 	}
 
 	updateMatrices( light ) {
@@ -41,7 +49,7 @@ class SpotLightShadow extends LightShadow {
 		const camera = this.camera;
 
 		const fov = RAD2DEG * 2 * light.angle * this.focus;
-		const aspect = this.mapSize.width / this.mapSize.height;
+		const aspect = ( this.mapSize.width / this.mapSize.height ) * this.aspect;
 		const far = light.distance || camera.far;
 
 		if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {

+ 1 - 1
src/nodes/tsl/TSLCore.js

@@ -85,7 +85,7 @@ const shaderNodeHandler = {
 
 				prop = parseSwizzleAndSort( prop.slice( 3 ).toLowerCase() );
 
-				return ( value ) => nodeObject( new SetNode( node, prop, value ) );
+				return ( value ) => nodeObject( new SetNode( node, prop, nodeObject( value ) ) );
 
 			} else if ( /^flip[XYZWRGBASTPQ]{1,4}$/.test( prop ) === true ) {
 

粤ICP备19079148号