فهرست منبع

WebGPU: Custom Lighting Model (#21706)

* WebGLNodeBuilder: Fix warns for now

* WebGPU: Custom model light example

* cleanup

* fix titles

* description

* more objective title

* improve description

* fix typo

* better var name
sunag 4 سال پیش
والد
کامیت
8eba7f642b
3فایلهای تغییر یافته به همراه184 افزوده شده و 0 حذف شده
  1. 1 0
      examples/files.json
  2. BIN
      examples/screenshots/webgpu_lights_custom.jpg
  3. 183 0
      examples/webgpu_lights_custom.html

+ 1 - 0
examples/files.json

@@ -318,6 +318,7 @@
 	"webgpu": [
 		"webgpu_compute",
 		"webgpu_instance_uniform",
+		"webgpu_lights_custom",
 		"webgpu_lights_selective",
 		"webgpu_materials",
 		"webgpu_rtt",

BIN
examples/screenshots/webgpu_lights_custom.jpg


+ 183 - 0
examples/webgpu_lights_custom.html

@@ -0,0 +1,183 @@
+<html lang="en">
+	<head>
+		<title>three.js - WebGPU - Custom Lighting Model</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> WebGPU - Custom Lighting Model<br/>(Chrome Canary with flag: --enable-unsafe-webgpu)
+		</div>
+
+		<script type="importmap">
+		{
+			"imports": {
+				"three": "../build/three.module.js"
+			}
+		}
+		</script>
+		<script type="module">
+
+			import * as THREE from 'three';
+
+			import WebGPURenderer from './jsm/renderers/webgpu/WebGPURenderer.js';
+			import WebGPU from './jsm/renderers/webgpu/WebGPU.js';
+
+			import { OrbitControls } from './jsm/controls/OrbitControls.js';
+
+			import ContextNode from './jsm/renderers/nodes/core/ContextNode.js';
+			import FunctionNode from './jsm/renderers/nodes/core/FunctionNode.js';
+
+			import LightsNode from './jsm/renderers/nodes/lights/LightsNode.js';
+
+			let camera, scene, renderer;
+
+			let light1, light2, light3;
+
+			init().then( animate ).catch( error );
+
+			async function init() {
+
+				if ( WebGPU.isAvailable() === false ) {
+
+					document.body.appendChild( WebGPU.getErrorMessage() );
+
+					throw 'No WebGPU support';
+
+				}
+
+				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 10 );
+				camera.position.z = 2;
+
+				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0x222222 );
+
+				// lights
+
+				const sphere = new THREE.SphereGeometry( 0.02, 16, 8 );
+
+				light1 = new THREE.PointLight( 0xffaa00, 2, 1 );
+				light1.add( new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: 0xffaa00 } ) ) );
+				scene.add( light1 );
+
+				light2 = new THREE.PointLight( 0x0040ff, 2, 1 );
+				light2.add( new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: 0x0040ff } ) ) );
+				scene.add( light2 );
+
+				light3 = new THREE.PointLight( 0x80ff80, 2, 1 );
+				light3.add( new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: 0x80ff80 } ) ) );
+				scene.add( light3 );
+
+				//light nodes ( selective lights )
+
+				const allLightsNode = LightsNode.fromLights( [ light1, light2, light3 ] );
+
+				// points
+
+				const points = [];
+
+				for ( let i = 0; i < 3000; i ++ ) {
+
+					const point = new THREE.Vector3().random().subScalar( 0.5 ).multiplyScalar( 2 );
+					points.push( point );
+
+				}
+
+				const geometryPoints = new THREE.BufferGeometry().setFromPoints( points );
+				const materialPoints = new THREE.PointsMaterial();
+
+				// custom lighting model
+
+				const RE_Direct = new FunctionNode( `
+					void ( vec3 lightColor ) {
+
+						// lightColor returns the light color with the intensity calculated
+
+						ReflectedLightDirectDiffuse += lightColor;
+
+					}` );
+
+
+				const RE_IndirectDiffuse = new FunctionNode( `
+					void ( ) {
+
+						//ReflectedLightIndirectDiffuse += vec3( 0.0 );
+
+					}` );
+
+				const lightingModelContext = new ContextNode( allLightsNode );
+				lightingModelContext.setParameter( 'RE_Direct', RE_Direct );
+				lightingModelContext.setParameter( 'RE_IndirectDiffuse', RE_IndirectDiffuse );
+
+				materialPoints.lightNode = lightingModelContext;
+
+				//
+
+				const pointCloud = new THREE.Points( geometryPoints, materialPoints );
+				scene.add( pointCloud );
+
+				//
+
+				renderer = new WebGPURenderer();
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				document.body.appendChild( renderer.domElement );
+
+				// controls
+
+				const controls = new OrbitControls( camera, renderer.domElement );
+				controls.minDistance = 0;
+				controls.maxDistance = 4;
+
+				// events
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+				//
+
+				return renderer.init();
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				const time = Date.now() * 0.0005;
+				const scale = .5;
+
+				light1.position.x = Math.sin( time * 0.7 ) * scale;
+				light1.position.y = Math.cos( time * 0.5 ) * scale;
+				light1.position.z = Math.cos( time * 0.3 ) * scale;
+
+				light2.position.x = Math.cos( time * 0.3 ) * scale;
+				light2.position.y = Math.sin( time * 0.5 ) * scale;
+				light2.position.z = Math.sin( time * 0.7 ) * scale;
+
+				light3.position.x = Math.sin( time * 0.7 ) * scale;
+				light3.position.y = Math.cos( time * 0.3 ) * scale;
+				light3.position.z = Math.sin( time * 0.5 ) * scale;
+
+				renderer.render( scene, camera );
+
+			}
+
+			function error( error ) {
+
+				console.error( error );
+
+			}
+
+		</script>
+	</body>
+</html>