Răsfoiți Sursa

Examples: Make point lights demo more interesting. (#31040)

* Examples: Make point lights demo more interesting.

* Docs: Fix links.

* E2E: Update screenshot.
Michael Herzog 11 luni în urmă
părinte
comite
1d6ae39f9d

+ 1 - 1
docs/api/ar/lights/PointLight.html

@@ -30,7 +30,7 @@
 		<h2>أمثلة (Examples)</h2>
 			
 		<p>
-		[example:webgl_lights_pointlights lights / pointlights ]<br />
+		[example:webgpu_lights_pointlights lights / pointlights ]<br />
 		[example:webgl_effects_anaglyph effects / anaglyph ]<br />
 		[example:webgl_geometry_text geometry / text ]<br />
 		[example:webgl_lensflares lensflares ]

+ 1 - 1
docs/api/en/lights/PointLight.html

@@ -31,7 +31,7 @@ scene.add( light );
 		<h2>Examples</h2>
 
 		<p>
-			[example:webgl_lights_pointlights lights / pointlights ]<br />
+			[example:webgpu_lights_pointlights lights / pointlights ]<br />
 			[example:webgl_effects_anaglyph effects / anaglyph ]<br />
 			[example:webgl_geometry_text geometry / text ]<br />
 			[example:webgl_lensflares lensflares ]

+ 1 - 1
docs/api/it/lights/PointLight.html

@@ -29,7 +29,7 @@ scene.add( light );
 		<h2>Esempi</h2>
 
 		<p>
-			[example:webgl_lights_pointlights lights / pointlights ]<br />
+			[example:webgpu_lights_pointlights lights / pointlights ]<br />
 			[example:webgl_effects_anaglyph effects / anaglyph ]<br />
 			[example:webgl_geometry_text geometry / text ]<br />
 			[example:webgl_lensflares lensflares ]

+ 1 - 1
docs/api/zh/lights/PointLight.html

@@ -28,7 +28,7 @@
 		<h2>例子</h2>
 
 		<p>
-			[example:webgl_lights_pointlights lights / pointlights ]<br />
+			[example:webgpu_lights_pointlights lights / pointlights ]<br />
 			[example:webgl_effects_anaglyph effects / anaglyph ]<br />
 			[example:webgl_geometry_text geometry / text ]<br />
 			[example:webgl_lensflares lensflares ]

+ 1 - 1
examples/files.json

@@ -60,7 +60,7 @@
 		"webgl_lightprobe_cubecamera",
 		"webgl_lights_hemisphere",
 		"webgl_lights_physical",
-		"webgl_lights_pointlights",
+		"webgpu_lights_pointlights",
 		"webgl_lights_spotlight",
 		"webgl_lights_spotlights",
 		"webgl_lights_rectarealight",

BIN
examples/screenshots/webgl_lights_pointlights.jpg


BIN
examples/screenshots/webgpu_lights_pointlights.jpg


+ 0 - 142
examples/webgl_lights_pointlights.html

@@ -1,142 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<title>three.js webgl - lights - point lights</title>
-		<meta charset="utf-8">
-		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-		<link type="text/css" rel="stylesheet" href="main.css">
-	</head>
-	<body>
-
-		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - point lights WebGL demo.<br />
-			Walt Disney head by <a href="http://web.archive.org/web/20120903131400/http://davidoreilly.com/post/18087489343/disneyhead" target="_blank" rel="noopener">David OReilly</a>
-		</div>
-
-		<script type="importmap">
-			{
-				"imports": {
-					"three": "../build/three.module.js",
-					"three/addons/": "./jsm/"
-				}
-			}
-		</script>
-
-		<script type="module">
-
-			import * as THREE from 'three';
-
-			import Stats from 'three/addons/libs/stats.module.js';
-
-			import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
-
-			let camera, scene, renderer,
-				light1, light2, light3, light4,
-				object, stats;
-
-			const clock = new THREE.Clock();
-
-			init();
-
-			function init() {
-
-				camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
-				camera.position.z = 100;
-
-				scene = new THREE.Scene();
-
-				//model
-
-				const loader = new OBJLoader();
-				loader.load( 'models/obj/walt/WaltHead.obj', function ( obj ) {
-
-					object = obj;
-					object.scale.multiplyScalar( 0.8 );
-					object.position.y = - 30;
-					scene.add( object );
-
-				} );
-
-				const sphere = new THREE.SphereGeometry( 0.5, 16, 8 );
-
-				//lights
-
-				light1 = new THREE.PointLight( 0xff0040, 400 );
-				light1.add( new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: 0xff0040 } ) ) );
-				scene.add( light1 );
-
-				light2 = new THREE.PointLight( 0x0040ff, 400 );
-				light2.add( new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: 0x0040ff } ) ) );
-				scene.add( light2 );
-
-				light3 = new THREE.PointLight( 0x80ff80, 400 );
-				light3.add( new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: 0x80ff80 } ) ) );
-				scene.add( light3 );
-
-				light4 = new THREE.PointLight( 0xffaa00, 400 );
-				light4.add( new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: 0xffaa00 } ) ) );
-				scene.add( light4 );
-
-				//renderer
-
-				renderer = new THREE.WebGLRenderer( { antialias: true } );
-				renderer.setPixelRatio( window.devicePixelRatio );
-				renderer.setSize( window.innerWidth, window.innerHeight );
-				renderer.setAnimationLoop( animate );
-				document.body.appendChild( renderer.domElement );
-
-				//stats
-
-				stats = new Stats();
-				document.body.appendChild( stats.dom );
-
-				window.addEventListener( 'resize', onWindowResize );
-
-			}
-
-			function onWindowResize() {
-
-				camera.aspect = window.innerWidth / window.innerHeight;
-				camera.updateProjectionMatrix();
-
-				renderer.setSize( window.innerWidth, window.innerHeight );
-
-			}
-
-			function animate() {
-
-				render();
-				stats.update();
-
-			}
-
-			function render() {
-
-				const time = Date.now() * 0.0005;
-				const delta = clock.getDelta();
-
-				if ( object ) object.rotation.y -= 0.5 * delta;
-
-				light1.position.x = Math.sin( time * 0.7 ) * 30;
-				light1.position.y = Math.cos( time * 0.5 ) * 40;
-				light1.position.z = Math.cos( time * 0.3 ) * 30;
-
-				light2.position.x = Math.cos( time * 0.3 ) * 30;
-				light2.position.y = Math.sin( time * 0.5 ) * 40;
-				light2.position.z = Math.sin( time * 0.7 ) * 30;
-
-				light3.position.x = Math.sin( time * 0.7 ) * 30;
-				light3.position.y = Math.cos( time * 0.3 ) * 40;
-				light3.position.z = Math.sin( time * 0.5 ) * 30;
-
-				light4.position.x = Math.sin( time * 0.3 ) * 30;
-				light4.position.y = Math.cos( time * 0.7 ) * 40;
-				light4.position.z = Math.sin( time * 0.5 ) * 30;
-
-				renderer.render( scene, camera );
-
-			}
-
-		</script>
-	</body>
-</html>

+ 219 - 0
examples/webgpu_lights_pointlights.html

@@ -0,0 +1,219 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js - lights - point lights</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<link type="text/css" rel="stylesheet" href="main.css">
+	</head>
+	<body>
+
+		<div id="info">
+			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - point lights<br />
+			Walt Disney head by <a href="http://web.archive.org/web/20120903131400/http://davidoreilly.com/post/18087489343/disneyhead" target="_blank" rel="noopener">David OReilly</a><br />
+			Displacement effect by <a href="https://web.archive.org/web/20210101053445/http://oos.moxiecode.com/js_webgl/stanford_bunny/" target="_blank" rel="noopener">oosmoxiecode</a>
+		</div>
+
+		<script type="importmap">
+			{
+				"imports": {
+					"three": "../build/three.webgpu.js",
+					"three/webgpu": "../build/three.webgpu.js",
+					"three/tsl": "../build/three.tsl.js",
+					"three/addons/": "./jsm/"
+				}
+			}
+		</script>
+
+		<script type="module">
+
+			import * as THREE from 'three';
+
+			import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
+			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
+			import { Timer } from 'three/addons/misc/Timer.js';
+
+			import { abs, attribute, distance, float, max, modelWorldMatrixInverse, positionLocal, sin, time, uniform } from 'three/tsl';
+
+			let camera, scene, timer, renderer, controls;
+			
+			let light1, light2;
+
+			init();
+
+			function init() {
+
+				camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
+				camera.position.z = 100;
+
+				scene = new THREE.Scene();
+
+				timer = new Timer();
+				timer.connect( document );
+
+				// model
+
+				const loader = new OBJLoader();
+				loader.load( 'models/obj/walt/WaltHead.obj', function ( obj ) {
+
+					const mesh = obj.children[ 0 ];
+					mesh.geometry = createGeometry( mesh.geometry );
+					mesh.material = createMaterial();
+
+					mesh.scale.multiplyScalar( 0.8 );
+					mesh.position.y = - 30;
+					scene.add( mesh );
+
+				} );
+
+				const sphere = new THREE.SphereGeometry( 0.5, 16, 8 );
+
+				// lights
+
+				light1 = new THREE.PointLight( 0xff0040, 2000 );
+				light1.add( new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: 0xff0040 } ) ) );
+				scene.add( light1 );
+
+				light2 = new THREE.PointLight( 0x0040ff, 2000 );
+				light2.add( new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: 0x0040ff } ) ) );
+				scene.add( light2 );
+
+				scene.add( new THREE.AmbientLight( 0xaaaaaa, 0.1 ) );
+			
+				// renderer
+
+				renderer = new THREE.WebGPURenderer( { antialias: true } );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setAnimationLoop( animate );
+				document.body.appendChild( renderer.domElement );
+
+				controls = new OrbitControls( camera, renderer.domElement );
+				controls.enableDamping = true;
+
+				window.addEventListener( 'resize', onWindowResize );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function animate() {
+
+				timer.update();
+
+				const time = timer.getElapsed() * 0.5;
+
+				controls.update();
+
+				light1.position.x = Math.sin( time ) * 20;
+				light1.position.y = Math.cos( time * 0.75 ) * - 30;
+				light1.position.z = Math.cos( time * 0.5 ) * 20;
+
+				light2.position.x = Math.cos( time * 0.5 ) * 20;
+				light2.position.y = Math.sin( time * 0.75 ) * - 30;
+				light2.position.z = Math.sin( time ) * 20;
+
+				renderer.render( scene, camera );
+
+			}
+
+			// helpers
+
+			function createMaterial() {
+
+				const material = new THREE.MeshPhongNodeMaterial();
+			
+				const seedAttribute = attribute( 'seed' );
+				const displaceNormalAttribute = attribute( 'displaceNormal' );
+
+				const localTime = attribute( 'time' ).add( time );
+
+				const effector1 = uniform( light1.position ).toVar();
+				const effector2 = uniform( light2.position ).toVar();
+
+				const distance1 = distance( positionLocal, modelWorldMatrixInverse.mul( effector1 ) );
+				const distance2 = distance( positionLocal, modelWorldMatrixInverse.mul( effector2 ) );
+
+				const invDistance1 = max( 0.0, float( 20.0 ).sub( distance1 ) ).div( 2.0 );
+				const invDistance2 = max( 0.0, float( 20.0 ).sub( distance2 ) ).div( 2.0 );
+
+				const s = abs( sin( localTime.mul( 2 ).add( seedAttribute ) ).mul( 0.5 ) ).add( invDistance1 ).add( invDistance2 );
+
+				material.positionNode = positionLocal.add( displaceNormalAttribute.mul( s ) );
+
+				return material;
+
+			}
+
+			function createGeometry( geometry ) {
+			
+				const positionAttribute = geometry.getAttribute( 'position' );
+
+				const v0 = new THREE.Vector3();
+				const v1 = new THREE.Vector3();
+				const v2 = new THREE.Vector3();
+				const v3 = new THREE.Vector3();
+				const n = new THREE.Vector3();
+
+				const plane = new THREE.Plane();
+
+				const vertices = [];
+				const times = [];
+				const seeds = [];
+				const displaceNormal = [];
+
+				for ( let i = 0; i < positionAttribute.count; i += 3 ) {
+
+					v0.fromBufferAttribute( positionAttribute, i );
+					v1.fromBufferAttribute( positionAttribute, i + 1 );
+					v2.fromBufferAttribute( positionAttribute, i + 2 );
+
+					plane.setFromCoplanarPoints( v0, v1, v2 );
+
+					v3.copy( v0 ).add( v1 ).add( v2 ).divideScalar( 3 ); // compute center
+					v3.add( n.copy( plane.normal ).multiplyScalar( - 1 ) ); // displace center inwards
+
+					// generate tetraeder for each triangle
+
+					vertices.push( v0.x, v0.y, v0.z, v1.x, v1.y, v1.z, v2.x, v2.y, v2.z );
+					vertices.push( v3.x, v3.y, v3.z, v1.x, v1.y, v1.z, v0.x, v0.y, v0.z );
+					vertices.push( v3.x, v3.y, v3.z, v2.x, v2.y, v2.z, v1.x, v1.y, v1.z );
+					vertices.push( v3.x, v3.y, v3.z, v0.x, v0.y, v0.z, v2.x, v2.y, v2.z );
+
+					const t = Math.random();
+					const s = Math.random();
+					n.copy( plane.normal );
+
+					times.push( t, t, t ); times.push( t, t, t ); times.push( t, t, t ); times.push( t, t, t );
+					seeds.push( s, s, s ); seeds.push( s, s, s ); seeds.push( s, s, s ); seeds.push( s, s, s );
+
+					displaceNormal.push( n.x, n.y, n.z, n.x, n.y, n.z, n.x, n.y, n.z );
+					displaceNormal.push( n.x, n.y, n.z, n.x, n.y, n.z, n.x, n.y, n.z );
+					displaceNormal.push( n.x, n.y, n.z, n.x, n.y, n.z, n.x, n.y, n.z );
+					displaceNormal.push( n.x, n.y, n.z, n.x, n.y, n.z, n.x, n.y, n.z );
+
+				}
+
+				const newGeometry = new THREE.BufferGeometry();
+				newGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
+				newGeometry.setAttribute( 'time', new THREE.Float32BufferAttribute( times, 1 ) );
+				newGeometry.setAttribute( 'seed', new THREE.Float32BufferAttribute( seeds, 1 ) );
+				newGeometry.setAttribute( 'displaceNormal', new THREE.Float32BufferAttribute( displaceNormal, 3 ) );
+
+				newGeometry.computeVertexNormals();
+
+				return newGeometry;
+
+
+			}
+
+		</script>
+	</body>
+</html>

粤ICP备19079148号