Jelajahi Sumber

Examples: More Inspector usage and revisions. (#31995)

* add overlay

* TiledLightsNode: Improve description

* Examples: add inspector

* update screenshots

* update

* improve description

* update examples

* update screenshots

* more examples

* add more examples

* fix color hex get value

* add listen()

* add more examples

* add more examples

* improve style

* Update example.css

* update

* Update example.css

* Update Parameters.js

* Update ToonOutlinePassNode.js

* add more examples

* Update Style.js

* add more examples

* add examples

* Update puppeteer.js

* add button support

* update screenshots
sunag 3 bulan lalu
induk
melakukan
72cd0f81ea
100 mengubah file dengan 1196 tambahan dan 758 penghapusan
  1. 37 13
      examples/example.css
  2. 68 33
      examples/jsm/inspector/tabs/Parameters.js
  3. 4 2
      examples/jsm/inspector/ui/Style.js
  4. 20 1
      examples/jsm/inspector/ui/Values.js
  5. 1 1
      examples/jsm/tsl/lighting/TiledLightsNode.js
  6. TEMPAT SAMPAH
      examples/screenshots/webgpu_layers.jpg
  7. TEMPAT SAMPAH
      examples/screenshots/webgpu_lights_projector.jpg
  8. TEMPAT SAMPAH
      examples/screenshots/webgpu_lines_fat_raycasting.jpg
  9. TEMPAT SAMPAH
      examples/screenshots/webgpu_materials_basic.jpg
  10. TEMPAT SAMPAH
      examples/screenshots/webgpu_mesh_batch.jpg
  11. TEMPAT SAMPAH
      examples/screenshots/webgpu_reflection_blurred.jpg
  12. TEMPAT SAMPAH
      examples/screenshots/webgpu_shadowmap_csm.jpg
  13. TEMPAT SAMPAH
      examples/screenshots/webgpu_tsl_compute_attractors_particles.jpg
  14. TEMPAT SAMPAH
      examples/screenshots/webgpu_tsl_galaxy.jpg
  15. TEMPAT SAMPAH
      examples/screenshots/webgpu_tsl_raging_sea.jpg
  16. TEMPAT SAMPAH
      examples/screenshots/webgpu_tsl_vfx_tornado.jpg
  17. TEMPAT SAMPAH
      examples/screenshots/webgpu_water.jpg
  18. 2 2
      examples/webgpu_backdrop_area.html
  19. 1 1
      examples/webgpu_backdrop_water.html
  20. 1 0
      examples/webgpu_camera.html
  21. 17 12
      examples/webgpu_camera_logarithmicdepthbuffer.html
  22. 6 2
      examples/webgpu_centroid_sampling.html
  23. 21 15
      examples/webgpu_compute_audio.html
  24. 2 3
      examples/webgpu_compute_birds.html
  25. 1 1
      examples/webgpu_compute_particles_snow.html
  26. 17 32
      examples/webgpu_compute_points.html
  27. 12 3
      examples/webgpu_compute_texture.html
  28. 16 4
      examples/webgpu_compute_texture_3d.html
  29. 12 3
      examples/webgpu_compute_texture_pingpong.html
  30. 24 23
      examples/webgpu_compute_water.html
  31. 1 1
      examples/webgpu_custom_fog_background.html
  32. 1 1
      examples/webgpu_instance_mesh.html
  33. 16 30
      examples/webgpu_layers.html
  34. 2 2
      examples/webgpu_lensflares.html
  35. 14 5
      examples/webgpu_lightprobe.html
  36. 15 3
      examples/webgpu_lightprobe_cubecamera.html
  37. 10 2
      examples/webgpu_lights_custom.html
  38. 13 7
      examples/webgpu_lights_ies_spotlight.html
  39. 13 10
      examples/webgpu_lights_phong.html
  40. 18 15
      examples/webgpu_lights_physical.html
  41. 12 5
      examples/webgpu_lights_pointlights.html
  42. 13 17
      examples/webgpu_lights_projector.html
  43. 13 10
      examples/webgpu_lights_rectarealight.html
  44. 22 21
      examples/webgpu_lights_selective.html
  45. 1 1
      examples/webgpu_lights_spotlight.html
  46. 15 13
      examples/webgpu_lights_tiled.html
  47. 20 16
      examples/webgpu_lines_fat_raycasting.html
  48. 16 12
      examples/webgpu_lines_fat_wireframe.html
  49. 12 5
      examples/webgpu_loader_gltf.html
  50. 14 5
      examples/webgpu_loader_gltf_anisotropy.html
  51. 10 2
      examples/webgpu_loader_gltf_compressed.html
  52. 11 3
      examples/webgpu_loader_gltf_dispersion.html
  53. 12 4
      examples/webgpu_loader_gltf_iridescence.html
  54. 14 6
      examples/webgpu_loader_gltf_sheen.html
  55. 11 4
      examples/webgpu_loader_gltf_transmission.html
  56. 15 8
      examples/webgpu_loader_materialx.html
  57. 12 12
      examples/webgpu_materials.html
  58. 8 11
      examples/webgpu_materials_alphahash.html
  59. 15 4
      examples/webgpu_materials_arrays.html
  60. 20 7
      examples/webgpu_materials_basic.html
  61. 14 5
      examples/webgpu_materials_cubemap_mipmaps.html
  62. 21 21
      examples/webgpu_materials_displacementmap.html
  63. 29 20
      examples/webgpu_materials_envmaps.html
  64. 15 6
      examples/webgpu_materials_envmaps_bpcem.html
  65. 5 4
      examples/webgpu_materials_lightmap.html
  66. 17 13
      examples/webgpu_materials_matcap.html
  67. 26 25
      examples/webgpu_materials_sss.html
  68. 12 4
      examples/webgpu_materials_texture_manualmipmap.html
  69. 16 11
      examples/webgpu_materials_toon.html
  70. 19 6
      examples/webgpu_materials_transmission.html
  71. 11 3
      examples/webgpu_materials_video.html
  72. 13 21
      examples/webgpu_materialx_noise.html
  73. 15 25
      examples/webgpu_mesh_batch.html
  74. 11 9
      examples/webgpu_modifier_curve.html
  75. 17 7
      examples/webgpu_morphtargets.html
  76. 3 13
      examples/webgpu_morphtargets_face.html
  77. 13 3
      examples/webgpu_mrt.html
  78. 10 3
      examples/webgpu_mrt_mask.html
  79. 10 2
      examples/webgpu_multiple_rendertargets.html
  80. 21 8
      examples/webgpu_multiple_rendertargets_readback.html
  81. 14 6
      examples/webgpu_multisampled_renderbuffers.html
  82. 10 3
      examples/webgpu_occlusion.html
  83. 10 1
      examples/webgpu_ocean.html
  84. 9 3
      examples/webgpu_parallax_uv.html
  85. 14 6
      examples/webgpu_particles.html
  86. 22 28
      examples/webgpu_performance.html
  87. 6 8
      examples/webgpu_pmrem_cubemap.html
  88. 6 8
      examples/webgpu_pmrem_equirectangular.html
  89. 17 7
      examples/webgpu_pmrem_scene.html
  90. 14 2
      examples/webgpu_portal.html
  91. 14 5
      examples/webgpu_procedural_texture.html
  92. 14 11
      examples/webgpu_reflection.html
  93. 13 12
      examples/webgpu_reflection_blurred.html
  94. 14 11
      examples/webgpu_reflection_roughness.html
  95. 14 3
      examples/webgpu_refraction.html
  96. 14 9
      examples/webgpu_rendertarget_2d-array_3d.html
  97. 10 3
      examples/webgpu_shadertoy.html
  98. 14 2
      examples/webgpu_shadowmap.html
  99. 18 22
      examples/webgpu_shadowmap_array.html
  100. 20 6
      examples/webgpu_shadowmap_csm.html

+ 37 - 13
examples/example.css

@@ -1,9 +1,3 @@
-* {
-	box-sizing: border-box;
-	-webkit-font-smoothing: antialiased;
-	-moz-osx-font-smoothing: grayscale;
-}
-
 body {
 	margin: 0;
 	background-color: #000;
@@ -27,7 +21,7 @@ a {
 	grid-template-columns: 50px auto;
 	grid-template-rows: auto auto;
 	column-gap: 10px;
-	align-items: center;
+	align-items: start;
 	color: #e0e0e0;
 	text-shadow: 1px 1px 5px rgba(0, 0, 0, .7);
 	font: 400 14px 'Inter', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
@@ -44,17 +38,21 @@ a {
 }
 
 .title-wrapper {
-	grid-column: 2;
-	grid-row: 1;
-	display: flex;
-	align-items: center;
+	position: absolute;
+    left: 60px;
+    top: 2px;
+    display: flex;
+    width: 300px;
 }
 
 #info > small {
-	grid-column: 2;
-	grid-row: 2;
 	font-size: 12px;
 	color: #e0e0e0;
+	position: absolute;
+	left: 60px;
+	top: 25px;
+	width: calc( 100vw - 250px );
+	line-height: 20px;
 }
 
 .title-wrapper > a {
@@ -92,3 +90,29 @@ a {
 #info.invert {
 	filter: invert(1);
 }
+
+#overlay {
+	position: absolute;
+	font-size: 16px;
+	z-index: 2;
+	top: 0;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	flex-direction: column;
+	background: rgba(0,0,0,0.7);
+}
+
+#overlay button {
+	background: transparent;
+	border: 0;
+	border: 1px solid rgb(255, 255, 255);
+	border-radius: 4px;
+	color: #ffffff;
+	padding: 12px 18px;
+	text-transform: uppercase;
+	cursor: pointer;
+}

+ 68 - 33
examples/jsm/inspector/tabs/Parameters.js

@@ -2,7 +2,7 @@ import { Tab } from '../ui/Tab.js';
 import { List } from '../ui/List.js';
 import { Item } from '../ui/Item.js';
 import { createValueSpan } from '../ui/utils.js';
-import { ValueNumber, ValueSlider, ValueSelect, ValueCheckbox, ValueColor } from '../ui/Values.js';
+import { ValueNumber, ValueSlider, ValueSelect, ValueCheckbox, ValueColor, ValueButton } from '../ui/Values.js';
 
 class ParametersGroup {
 
@@ -50,12 +50,51 @@ class ParametersGroup {
 
 			item = this.addBoolean( object, property );
 
+		} else if ( type === 'function' ) {
+
+			item = this.addButton( object, property, ...params );
+
 		}
 
 		return item;
 
 	}
 
+	_addParameter( object, property, editor, subItem ) {
+
+		editor.name = ( name ) => {
+
+			subItem.data[ 0 ].textContent = name;
+
+			return editor;
+
+		};
+
+		editor.listen = () => {
+
+			const update = () => {
+
+				const value = editor.getValue();
+				const propertyValue = object[ property ];
+
+				if ( value !== propertyValue ) {
+
+					editor.setValue( propertyValue );
+
+				}
+
+				requestAnimationFrame( update );
+
+			};
+
+			requestAnimationFrame( update );
+
+			return editor;
+
+		};
+
+	}
+
 	addFolder( name ) {
 
 		const group = new ParametersGroup( this.parameters, name );
@@ -105,13 +144,7 @@ class ParametersGroup {
 
 		// extend object property
 
-		editor.name = ( name ) => {
-
-			description.textContent = name;
-
-			return editor;
-
-		};
+		this._addParameter( object, property, editor, subItem );
 
 		return editor;
 
@@ -139,13 +172,7 @@ class ParametersGroup {
 
 		// extend object property
 
-		editor.name = ( name ) => {
-
-			description.textContent = name;
-
-			return editor;
-
-		};
+		this._addParameter( object, property, editor, subItem );
 
 		return editor;
 
@@ -173,13 +200,7 @@ class ParametersGroup {
 
 		// extend object property
 
-		editor.name = ( name ) => {
-
-			description.textContent = name;
-
-			return editor;
-
-		};
+		this._addParameter( object, property, editor, subItem );
 
 		return editor;
 
@@ -207,13 +228,7 @@ class ParametersGroup {
 
 		// extend object property
 
-		editor.name = ( name ) => {
-
-			description.textContent = name;
-
-			return editor;
-
-		};
+		this._addParameter( object, property, editor, subItem );
 
 		return editor;
 
@@ -242,13 +257,33 @@ class ParametersGroup {
 
 		// extend object property
 
-		editor.name = ( name ) => {
+		this._addParameter( object, property, editor, subItem );
 
-			description.textContent = name;
+		return editor;
 
-			return editor;
+	}
 
-		};
+	addButton( object, property ) {
+
+		const value = object[ property ];
+
+		const editor = new ValueButton( { text: property, value } );
+		editor.addEventListener( 'change', ( { value } ) => {
+
+			object[ property ] = value;
+
+		} );
+
+		const subItem = new Item( editor.domElement );
+		subItem.itemRow.childNodes[ 0 ].style.gridColumn = '1 / -1';
+		this.paramList.add( subItem );
+
+		const itemRow = subItem.domElement.firstChild;
+		itemRow.classList.add( 'actionable' );
+
+		// extend object property
+
+		this._addParameter( object, property, editor, subItem );
 
 		return editor;
 

+ 4 - 2
examples/jsm/inspector/ui/Style.js

@@ -22,9 +22,12 @@ export class Style {
 
 @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600&family=Fira+Code&display=swap');
 
-#profiler-panel * {
+#profiler-panel *, #profiler-toggle * {
 	text-transform: initial;
 	line-height: normal;
+	box-sizing: border-box;
+	-webkit-font-smoothing: antialiased;
+	-moz-osx-font-smoothing: grayscale;
 }
 
 #profiler-toggle {
@@ -353,7 +356,6 @@ export class Style {
 .list-children-container {
 	padding-left: 1.5em;
 	overflow: hidden;
-	max-height: 1000px;
 	transition: max-height 0.1s ease-out;
 	margin-top: 2px;
 }

+ 20 - 1
examples/jsm/inspector/ui/Values.js

@@ -386,6 +386,10 @@ class ValueColor extends Value {
 
 			color = `#${ color.toString( 16 ) }`;
 
+		} else if ( color[ 0 ] !== '#' ) {
+
+			color = '#' + color;
+
 		}
 
 		return color;
@@ -408,4 +412,19 @@ class ValueColor extends Value {
 
 }
 
-export { Value, ValueNumber, ValueCheckbox, ValueSlider, ValueSelect, ValueColor };
+class ValueButton extends Value {
+
+	constructor( { text = 'Button', value = () => {} } ) {
+
+		super();
+
+		const button = document.createElement( 'button' );
+		button.textContent = text;
+		button.onclick = value;
+		this.domElement.appendChild( button );
+
+	}
+
+}
+
+export { Value, ValueNumber, ValueCheckbox, ValueSlider, ValueSelect, ValueColor, ValueButton };

+ 1 - 1
examples/jsm/tsl/lighting/TiledLightsNode.js

@@ -392,7 +392,7 @@ class TiledLightsNode extends LightsNode {
 
 			} );
 
-		} )().compute( count );
+		} )().compute( count ).setName( 'Update Tiled Lights' );
 
 		// screen coordinate lighting indexes
 

TEMPAT SAMPAH
examples/screenshots/webgpu_layers.jpg


TEMPAT SAMPAH
examples/screenshots/webgpu_lights_projector.jpg


TEMPAT SAMPAH
examples/screenshots/webgpu_lines_fat_raycasting.jpg


TEMPAT SAMPAH
examples/screenshots/webgpu_materials_basic.jpg


TEMPAT SAMPAH
examples/screenshots/webgpu_mesh_batch.jpg


TEMPAT SAMPAH
examples/screenshots/webgpu_reflection_blurred.jpg


TEMPAT SAMPAH
examples/screenshots/webgpu_shadowmap_csm.jpg


TEMPAT SAMPAH
examples/screenshots/webgpu_tsl_compute_attractors_particles.jpg


TEMPAT SAMPAH
examples/screenshots/webgpu_tsl_galaxy.jpg


TEMPAT SAMPAH
examples/screenshots/webgpu_tsl_raging_sea.jpg


TEMPAT SAMPAH
examples/screenshots/webgpu_tsl_vfx_tornado.jpg


TEMPAT SAMPAH
examples/screenshots/webgpu_water.jpg


+ 2 - 2
examples/webgpu_backdrop_area.html

@@ -154,8 +154,8 @@
 				box.material = materials[ options.material ];
 
 				const gui = renderer.inspector.createParameters( 'Scene settings' );
-				gui.add( box.scale, 'x', 0.1, 2 ).step( 0.01 ).name( 'box scale x' );
-				gui.add( box.scale, 'y', 0.1, 2 ).step( 0.01 ).name( 'box scale y' );
+				gui.add( box.scale, 'x', 0.1, 2, 0.01 ).name( 'box scale x' );
+				gui.add( box.scale, 'y', 0.1, 2, 0.01 ).name( 'box scale y' );
 				gui.add( options, 'material', Object.keys( materials ) ).onChange( name => {
 
 					box.material = materials[ name ];

+ 1 - 1
examples/webgpu_backdrop_water.html

@@ -12,7 +12,7 @@
 			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
 
 			<div class="title-wrapper">
-				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>backdrop water</span>
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Backdrop Water</span>
 			</div>
 
 			<small>Water refraction with depth effect.</small>

+ 1 - 0
examples/webgpu_camera.html

@@ -7,6 +7,7 @@
 		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
+
 		<div id="info">
 			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
 

+ 17 - 12
examples/webgpu_camera_logarithmicdepthbuffer.html

@@ -1,14 +1,16 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webgpu - cameras - logarithmic depth buffer</title>
+		<title>three.js webgpu - logarithmic depth buffer</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 		<style>
+
 			body{
 				touch-action: none;
 			}
+
 			.renderer_label {
 				position: absolute;
 				bottom: 1em;
@@ -47,7 +49,9 @@
 				border: 1px inset #ccc;
 				cursor: col-resize;
 			}
+
 		</style>
+
 	</head>
 	<body>
 
@@ -58,8 +62,13 @@
 		</div>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - cameras - logarithmic depth buffer<br/>
-			mousewheel to dolly out
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Logarithmic Depth Buffer</span>
+			</div>
+
+			<small>Mousewheel to dolly out.</small>
 		</div>
 
 		<script type="importmap">
@@ -77,11 +86,11 @@
 
 			import * as THREE from 'three/webgpu';
 
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			import { FontLoader } from 'three/addons/loaders/FontLoader.js';
 			import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
 
-			import Stats from 'three/addons/libs/stats.module.js';
-
 			// 1 micrometer to 100 billion light years in one scene, with 1 unit = 1 meter?  preposterous!  and yet...
 			const NEAR = 1e-6, FAR = 1e27;
 			let SCREEN_WIDTH = window.innerWidth;
@@ -91,7 +100,7 @@
 			let zoompos = - 100, minzoomspeed = .015;
 			let zoomspeed = minzoomspeed;
 
-			let container, border, stats;
+			let container, border;
 			const objects = {};
 
 			// Generate a number of text labels, from 1µm in size up to 100,000,000 light years
@@ -130,9 +139,6 @@
 				objects.normal = await initView( scene, 'normal', false );
 				objects.logzbuf = await initView( scene, 'logzbuf', true );
 
-				stats = new Stats();
-				container.appendChild( stats.dom );
-
 				// Resize border allows the user to easily compare effects of logarithmic depth buffer over the whole scene
 				border = document.getElementById( 'renderer_border' );
 				border.addEventListener( 'pointerdown', onBorderPointerDown );
@@ -155,6 +161,7 @@
 				renderer.setSize( SCREEN_WIDTH / 2, SCREEN_HEIGHT );
 				renderer.domElement.style.position = 'relative';
 				renderer.domElement.id = 'renderer_' + name;
+				renderer.inspector = new Inspector();
 				framecontainer.appendChild( renderer.domElement );
 
 				await renderer.init();
@@ -289,8 +296,6 @@
 				objects.normal.renderer.render( objects.normal.scene, objects.normal.camera );
 				objects.logzbuf.renderer.render( objects.logzbuf.scene, objects.logzbuf.camera );
 
-				stats.update();
-
 			}
 
 			function onWindowResize() {

+ 6 - 2
examples/webgpu_centroid_sampling.html

@@ -6,6 +6,7 @@
 		<link type="text/css" rel="stylesheet" href="main.css">
 	</head>
 	<style>
+
 		body {
 			margin: 0;
 			overflow: hidden;
@@ -33,8 +34,10 @@
 			width: 100%;
 			height: 100%;
 		}
+
 	</style>
 	<body>
+
 		<div id="demo">
 			<div id="antialiasing-disabled" class="renderer-wrapper">
 				<div>antialiasing disabled</div>
@@ -60,7 +63,7 @@
 			import * as THREE from 'three/webgpu';
 			import { varying, uv, texture, Fn } from 'three/tsl';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let rendererAntialiasingEnabled;
 			let rendererAntialiasingDisabled;
@@ -222,6 +225,7 @@
 				rendererAntialiasingEnabled.setPixelRatio( window.devicePixelRatio );
 				rendererAntialiasingEnabled.setSize( window.innerWidth / 2, window.innerHeight );
 				rendererAntialiasingEnabled.setAnimationLoop( animateAliased );
+				rendererAntialiasingEnabled.inspector = new Inspector();
 
 				document.body.querySelector( '#antialiasing-disabled' ).appendChild( rendererAntialiasingDisabled.domElement );
 				document.body.querySelector( '#antialiasing-disabled' ).appendChild( rendererAntialiasingDisabled.domElement );
@@ -230,7 +234,7 @@
 
 				window.addEventListener( 'resize', onWindowResize );
 
-				gui = new GUI();
+				gui = rendererAntialiasingEnabled.inspector.createParameters( 'Settings' );
 				gui.add( effectController, 'sampling', [
 					THREE.InterpolationSamplingMode.NORMAL,
 					THREE.InterpolationSamplingMode.CENTROID,

+ 21 - 15
examples/webgpu_compute_audio.html

@@ -1,9 +1,9 @@
 <html lang="en">
 	<head>
-		<title>three.js - WebGPU - Audio Processing</title>
+		<title>three.js webgpu - audio processing</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
@@ -12,8 +12,13 @@
 		</div>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> WebGPU - Audio Processing
-			<br>Click on screen to process the audio using WebGPU.
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Audio Processing</span>
+			</div>
+
+			<small>Click on screen to process the audio using WebGPU.</small>
 		</div>
 
 		<script type="importmap">
@@ -32,7 +37,7 @@
 			import * as THREE from 'three/webgpu';
 			import { Fn, uniform, instanceIndex, instancedArray, float, texture, screenUV, color } from 'three/tsl';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let camera, scene, renderer;
 			let computeNode;
@@ -156,16 +161,6 @@
 
 				computeNode = computeShaderFn().compute( waveBuffer.length );
 
-
-				// gui
-
-				const gui = new GUI();
-
-				gui.add( pitch, 'value', .5, 2, 0.01 ).name( 'pitch' );
-				gui.add( delayVolume, 'value', 0, 1, .01 ).name( 'delayVolume' );
-				gui.add( delayOffset, 'value', .1, 1, .01 ).name( 'delayOffset' );
-
-
 				// renderer
 
 				const container = document.createElement( 'div' );
@@ -193,11 +188,22 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( render );
+				renderer.inspector = new Inspector();
 				container.appendChild( renderer.domElement );
 
 				window.addEventListener( 'resize', onWindowResize );
 				document.addEventListener( 'click', playAudioBuffer );
 
+				// gui
+
+				const gui = renderer.inspector.createParameters( 'Audio' );
+
+				gui.add( pitch, 'value', .5, 2, 0.01 ).name( 'pitch' );
+				gui.add( delayVolume, 'value', 0, 1, .01 ).name( 'delayVolume' );
+				gui.add( delayOffset, 'value', .1, 1, .01 ).name( 'delayOffset' );
+
+				//
+
 				playAudioBuffer();
 
 			}

+ 2 - 3
examples/webgpu_compute_birds.html

@@ -13,7 +13,7 @@
 
 			<div class="title-wrapper">
 				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a>
-				<span>compute birds</span>
+				<span>Compute Birds</span>
 			</div>
 
 			<small>
@@ -27,8 +27,7 @@
 					"three": "../build/three.webgpu.js",
 					"three/webgpu": "../build/three.webgpu.js",
 					"three/tsl": "../build/three.tsl.js",
-					"three/addons/": "./jsm/",
-					"stats-gl": "https://cdn.jsdelivr.net/npm/stats-gl@3.6.0/dist/main.js"
+					"three/addons/": "./jsm/"
 				}
 			}
 		</script>

+ 1 - 1
examples/webgpu_compute_particles_snow.html

@@ -13,7 +13,7 @@
 
 			<div class="title-wrapper">
 				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a>
-				<span>compute snow</span>
+				<span>Compute Snow</span>
 			</div>
 
 			<small>

+ 17 - 32
examples/webgpu_compute_points.html

@@ -1,14 +1,23 @@
 <html lang="en">
 	<head>
-		<title>three.js - WebGPU - Compute</title>
+		<title>three.js webgpu - compute</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> WebGPU - Compute - 300000 Points
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a>
+				<span>Compute</span>
+			</div>
+
+			<small>
+				300k points animated using GPU.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -27,14 +36,11 @@
 
 			import * as THREE from 'three/webgpu';
 
-			import Stats from 'stats-gl';
-
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			import { Fn, uniform, instancedArray, float, vec2, color, instanceIndex } from 'three/tsl';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
-
-			let camera, scene, renderer, stats;
+			let camera, scene, renderer;
 			let computeNode;
 
 			const pointerVector = new THREE.Vector2( - 10.0, - 10.0 ); // Out of bounds first
@@ -82,7 +88,7 @@
 
 				// compute
 
-				computeNode = computeShaderFn().compute( particlesCount );
+				computeNode = computeShaderFn().compute( particlesCount ).setName( 'Update Particles' );
 				computeNode.onInit( ( { renderer } ) => {
 
 					const precomputeShaderNode = Fn( () => {
@@ -123,27 +129,15 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
-				stats = new Stats( {
-					precision: 4,
-					horizontal: false,
-					trackGPU: true,
-					trackCPT: true,
-					logsPerSecond: 10,
-					graphsPerSecond: 60,
-					samplesGraph: 30,
-				} );
-				stats.init( renderer );
-				document.body.appendChild( stats.dom );
-				stats.dom.style.position = 'absolute';
-
 				window.addEventListener( 'resize', onWindowResize );
 				window.addEventListener( 'mousemove', onMouseMove );
 
 				// gui
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Settings' );
 
 				gui.add( scaleVector, 'x', 0, 1, 0.01 );
 				gui.add( scaleVector, 'y', 0, 1, 0.01 );
@@ -176,17 +170,8 @@
 			function animate() {
 
 				renderer.compute( computeNode );
-				renderer.resolveTimestampsAsync( THREE.TimestampQuery.COMPUTE );
-
 				renderer.render( scene, camera );
 
-
-				renderer.resolveTimestampsAsync().then( () => {
-
-					stats.update();
-
-				} );
-
 			}
 
 		</script>

+ 12 - 3
examples/webgpu_compute_texture.html

@@ -1,14 +1,23 @@
 <html lang="en">
 	<head>
-		<title>three.js - WebGPU - Compute Texture</title>
+		<title>three.js webgpu - compute texture</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> WebGPU - Compute Texture
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a>
+				<span>Compute Texture</span>
+			</div>
+
+			<small>
+				Compute texture using GPU.
+			</small>
 		</div>
 
 		<script type="importmap">

+ 16 - 4
examples/webgpu_compute_texture_3d.html

@@ -4,12 +4,22 @@
 		<title>three.js webgpu - compute texture 3D</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 
 	<body>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> WebGPU - Compute Texture 3D
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a>
+				<span>Compute Texture 3D</span>
+			</div>
+
+			<small>
+				Compute texture 3D using GPU.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -32,7 +42,8 @@
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			import WebGPU from 'three/addons/capabilities/WebGPU.js';
 
 			let renderer, scene, camera;
@@ -55,6 +66,7 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				scene = new THREE.Scene();
@@ -193,7 +205,7 @@
 				await renderer.init();
 				await renderer.computeAsync( computeNode );
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Settings' );
 				gui.add( threshold, 'value', 0, 1, 0.01 ).name( 'threshold' );
 				gui.add( opacity, 'value', 0, 1, 0.01 ).name( 'opacity' );
 				gui.add( range, 'value', 0, 1, 0.01 ).name( 'range' );

+ 12 - 3
examples/webgpu_compute_texture_pingpong.html

@@ -1,14 +1,23 @@
 <html lang="en">
 	<head>
-		<title>three.js - WebGPU - Compute Ping/Pong Texture</title>
+		<title>three.js webgpu - compute ping/pong texture</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> WebGPU - Compute Ping/Pong Texture
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a>
+				<span>Compute Ping/Pong Texture</span>
+			</div>
+
+			<small>
+				Compute ping/pong texture using GPU.
+			</small>
 		</div>
 
 		<script type="importmap">

+ 24 - 23
examples/webgpu_compute_water.html

@@ -4,13 +4,21 @@
 		<title>three.js webgpu - compute water</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - <span id="waterSize"></span> webgpu compute water<br/>
-			Click and move mouse to disturb water.
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a>
+				<span>Compute Water</span>
+			</div>
+
+			<small>
+				Click and move mouse to disturb water.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -29,14 +37,14 @@
 			import * as THREE from 'three/webgpu';
 			import { instanceIndex, struct, If, uint, int, floor, float, length, clamp, vec2, cos, vec3, vertexIndex, Fn, uniform, instancedArray, min, max, positionLocal, transformNormalToView, globalId } from 'three/tsl';
 
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			import { SimplexNoise } from 'three/addons/math/SimplexNoise.js';
 			import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
 			import { HDRLoader } from 'three/addons/loaders/HDRLoader.js';
  			import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
-			import Stats from 'three/addons/libs/stats.module.js';
 			import WebGPU from 'three/addons/capabilities/WebGPU.js';
 
 			// Dimensions of simulation grid.
@@ -49,7 +57,7 @@
 
 			const waterMaxHeight = 0.1;
 
-			let container, stats;
+			let container;
 			let camera, scene, renderer, controls;
 
 			let mouseDown = false;
@@ -245,7 +253,7 @@
 					prevHeightStorage.element( instanceIndex ).assign( height );
 					heightStorage.element( instanceIndex ).assign( newHeight );
 
-				} )().compute( WIDTH * WIDTH, [ 16, 16 ] );
+				} )().compute( WIDTH * WIDTH, [ 16, 16 ] ).setName( 'Update Height' );
 
 				// Water Geometry corresponds with buffered compute grid.
 				const waterGeometry = new THREE.PlaneGeometry( BOUNDS, BOUNDS, WIDTH - 1, WIDTH - 1 );
@@ -399,7 +407,7 @@
 					duckInstanceDataStorage.element( instanceIndex ).get( 'position' ).assign( instancePosition );
 					duckInstanceDataStorage.element( instanceIndex ).get( 'velocity' ).assign( velocity );
 
-				} )().compute( NUM_DUCKS );
+				} )().compute( NUM_DUCKS ).setName( 'Update Ducks' );
 
 				// Models / Textures
 
@@ -433,17 +441,17 @@
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.toneMapping = THREE.ACESFilmicToneMapping;
 				renderer.toneMappingExposure = 0.5;
-				renderer.setAnimationLoop( animate );
+				renderer.setAnimationLoop( render );
 				container.appendChild( renderer.domElement );
 
+				renderer.inspector = new Inspector();
+				document.body.appendChild( renderer.inspector.domElement );
+
 				controls = new OrbitControls( camera, container );
 
 				container.style.touchAction = 'none';
 
-				// Stats
-
-				stats = new Stats();
-				container.appendChild( stats.dom );
+				//
 
 				container.style.touchAction = 'none';
 				container.addEventListener( 'pointermove', onPointerMove );
@@ -454,7 +462,7 @@
 
 				// GUI
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Settings' );
 				gui.add( effectController.mouseSize, 'value', 0.1, .3 ).name( 'Mouse Size' );
 				gui.add( effectController.mouseDeep, 'value', 0.1, 1 ).name( 'Mouse Deep' );
 				gui.add( effectController.viscosity, 'value', 0.9, 0.96, 0.001 ).name( 'viscosity' );
@@ -517,13 +525,6 @@
 
 			}
 
-			function animate() {
-
-				render();
-				stats.update();
-
-			}
-
 			function raycast() {
 
 				if ( mouseDown && ( firstClick || ! controls.enabled ) ) {
@@ -585,11 +586,11 @@
 
 				if ( frame >= 7 - effectController.speed ) {
 
-					renderer.computeAsync( computeHeight, [ 8, 8, 1 ] );
+					renderer.compute( computeHeight, [ 8, 8, 1 ] );
 
 					if ( effectController.ducksEnabled ) {
 
-						renderer.computeAsync( computeDucks );
+						renderer.compute( computeDucks );
 
 					}
 

+ 1 - 1
examples/webgpu_custom_fog_background.html

@@ -17,7 +17,7 @@
 
 			<small>
 				Custom Fog Background via Post-Processing.<br/>
-				Battle Damaged Sci-fi Helmet by <a href="https://sketchfab.com/theblueturtle_" target="_blank" rel="noopener">theblueturtle_</a>.<br/>
+				Battle Damaged Sci-fi Helmet by <a href="https://sketchfab.com/theblueturtle_" target="_blank" rel="noopener">theblueturtle_</a>.
 				<a href="https://hdrihaven.com/hdri/?h=royal_esplanade" target="_blank" rel="noopener">Royal Esplanade</a> by <a href="https://hdrihaven.com/" target="_blank" rel="noopener">HDRI Haven</a>.
 			</small>
 		</div>

+ 1 - 1
examples/webgpu_instance_mesh.html

@@ -76,7 +76,7 @@
 					//
 
 					const gui = renderer.inspector.createParameters( 'Settings' );
-					gui.add( mesh, 'count', 1, count ).step( 1 ).name( 'instance count' );
+					gui.add( mesh, 'count', 1, count, 1 ).name( 'instance count' );
 
 				} );
 

+ 16 - 30
examples/webgpu_layers.html

@@ -35,7 +35,7 @@
 
 			import * as THREE from 'three/webgpu';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			import { positionLocal, time, mod, instancedBufferAttribute, rotate, screenUV, color, vec2 } from 'three/tsl';
 
@@ -82,50 +82,36 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				// GUI
 
 				const layers = {
+					'Red': true,
+					'Yellow': true,
+					'Green': true
+				};
 
-					'toggle red': function () {
-
-						camera.layers.toggle( 0 );
-
-					},
-
-					'toggle yellow': function () {
-
-						camera.layers.toggle( 1 );
-
-					},
-
-					'toggle green': function () {
-
-						camera.layers.toggle( 2 );
+				const gui = renderer.inspector.createParameters( 'Layers' );
 
-					},
+				gui.add( layers, 'Red' ).onChange( () => {
 
-					'enable all': function () {
+					camera.layers.toggle( 0 );
 
-						camera.layers.enableAll();
+				} );
 
-					},
+				gui.add( layers, 'Yellow' ).onChange( () => {
 
-					'disable all': function () {
+					camera.layers.toggle( 1 );
 
-						camera.layers.disableAll();
+				} );
 
-					}
+				gui.add( layers, 'Green' ).onChange( () => {
 
-				};
+					camera.layers.toggle( 2 );
 
-				const gui = new GUI();
-				gui.add( layers, 'toggle red' );
-				gui.add( layers, 'toggle yellow' );
-				gui.add( layers, 'toggle green' );
-				gui.add( layers, 'enable all' );
-				gui.add( layers, 'disable all' );
+				} );
 
 				//
 

+ 2 - 2
examples/webgpu_lensflares.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webgpu - lensflares</title>
+		<title>three.js webgpu - lens flares</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="example.css">
@@ -13,7 +13,7 @@
 			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
 
 			<div class="title-wrapper">
-				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Lensflares</span>
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Lens Flares</span>
 			</div>
 
 			<small>

+ 14 - 5
examples/webgpu_lightprobe.html

@@ -4,12 +4,21 @@
 		<title>three.js webgpu - light probe</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 
 	<body>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - light probe
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Light Probe</span>
+			</div>
+
+			<small>
+				Light probes and environment lighting.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -27,7 +36,7 @@
 
 			import * as THREE from 'three/webgpu';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
@@ -58,12 +67,12 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				// tone mapping
 				renderer.toneMapping = THREE.NoToneMapping;
 
-
 				// scene
 				scene = new THREE.Scene();
 
@@ -130,7 +139,7 @@
 
 
 				// gui
-				gui = new GUI( { title: 'Intensity' } );
+				gui = renderer.inspector.createParameters( 'Intensity' );
 
 				gui.add( API, 'lightProbeIntensity', 0, 1, 0.02 )
 					.name( 'light probe' )

+ 15 - 3
examples/webgpu_lightprobe_cubecamera.html

@@ -1,15 +1,24 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webgpu - light probe from cubeCamera</title>
+		<title>three.js webgpu - light probe from cube camera</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 
 	<body>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - light probe from cubeCamera
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Light Probe from Cube Camera</span>
+			</div>
+
+			<small>
+				Light probes and environment lighting from cube camera.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -27,6 +36,8 @@
 
 			import * as THREE from 'three/webgpu';
 
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { LightProbeHelper } from 'three/addons/helpers/LightProbeHelperGPU.js';
 			import { LightProbeGenerator } from 'three/addons/lights/LightProbeGenerator.js';
@@ -43,6 +54,7 @@
 				renderer = new THREE.WebGPURenderer( { antialias: true } );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				// scene

+ 10 - 2
examples/webgpu_lights_custom.html

@@ -3,12 +3,20 @@
 		<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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - custom lighting model
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Custom Lighting Model</span>
+			</div>
+
+			<small>
+				Custom lighting model with selective lights.
+			</small>
 		</div>
 
 		<script type="importmap">

+ 13 - 7
examples/webgpu_lights_ies_spotlight.html

@@ -4,12 +4,20 @@
 		<title>three.js webgpu - ies spotlight</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - ies spotlight<br />
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>IES Spot Light</span>
+			</div>
+
+			<small>
+				IES Spot Light with IES texture files.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -31,7 +39,7 @@
 
 			import { IESLoader } from 'three/addons/loaders/IESLoader.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let renderer, scene, camera;
 			let lights;
@@ -138,6 +146,7 @@
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( render );
 				renderer.shadowMap.enabled = true;
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, .1, 100 );
@@ -164,12 +173,9 @@
 
 				//
 
-				const gui = new GUI();
-
+				const gui = renderer.inspector.createParameters( 'Settings' );
 				gui.add( { helper: false }, 'helper' ).onChange( ( v ) => setHelperVisible( v ) );
 
-				gui.open();
-
 				//
 
 				window.addEventListener( 'resize', onWindowResize );

+ 13 - 10
examples/webgpu_lights_phong.html

@@ -4,13 +4,20 @@
 		<title>three.js webgpu - phong 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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - phong lighting model<br />
-			<b style="color:red">Left: Red lights</b> - <b>Center: All lights</b> - <b style="color:blue">Right: blue light</b>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Phong</span>
+			</div>
+
+			<small>
+				<b style="color:red">Left: Red lights</b> - <b>Center: All lights</b> - <b style="color:blue">Right: blue light</b>
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -29,7 +36,7 @@
 			import * as THREE from 'three/webgpu';
 			import { color, fog, rangeFogFactor, checker, uv, mix, texture, lights, normalMap } from 'three/tsl';
 
-			import Stats from 'three/addons/libs/stats.module.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { TeapotGeometry } from 'three/addons/geometries/TeapotGeometry.js';
@@ -124,6 +131,7 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				// controls
@@ -132,10 +140,7 @@
 				controls.minDistance = 3;
 				controls.maxDistance = 25;
 
-				// stats
-
-				stats = new Stats();
-				document.body.appendChild( stats.dom );
+				//
 
 				window.addEventListener( 'resize', onWindowResize );
 
@@ -173,8 +178,6 @@
 
 				renderer.render( scene, camera );
 
-				stats.update();
-
 			}
 
 		</script>

+ 18 - 15
examples/webgpu_lights_physical.html

@@ -4,21 +4,31 @@
 		<title>three.js webgpu - physical 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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="container"></div>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - Physically accurate incandescent bulb by <a href="http://clara.io" target="_blank" rel="noopener">Ben Houston</a><br />
-			Real world scale: Brick cube is 50 cm in size. Globe is 50 cm in diameter.<br/>
-			Reinhard tonemapping with real-world light falloff (decay = 2).
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Physical Lighting Model</span>
+			</div>
+
+			<small>
+				Physically accurate incandescent bulb by <a href="http://clara.io" target="_blank" rel="noopener">Ben Houston</a><br />
+				Real world scale: Brick cube is 50 cm in size. Globe is 50 cm in diameter.<br/>
+				Reinhard tonemapping with real-world light falloff (decay = 2).
+			</small>
 		</div>
 
 		<script type="importmap">
 			{
 				"imports": {
 					"three": "../build/three.webgpu.js",
+					"three/tsl": "../build/three.tsl.js",
 					"three/webgpu": "../build/three.webgpu.js",
 					"three/addons/": "./jsm/"
 				}
@@ -29,12 +39,11 @@
 
 			import * as THREE from 'three/webgpu';
 
-			import Stats from 'three/addons/libs/stats.module.js';
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
-			let camera, scene, renderer, bulbLight, bulbMat, hemiLight, stats;
+			let camera, scene, renderer, bulbLight, bulbMat, hemiLight;
 			let ballMat, cubeMat, floorMat;
 
 			let previousShadowMap = false;
@@ -79,9 +88,6 @@
 
 				const container = document.getElementById( 'container' );
 
-				stats = new Stats();
-				container.appendChild( stats.dom );
-
 				//
 
 				camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.1, 100 );
@@ -233,6 +239,7 @@
 				renderer.setAnimationLoop( animate );
 				renderer.shadowMap.enabled = true;
 				renderer.toneMapping = THREE.ReinhardToneMapping;
+				renderer.inspector = new Inspector();
 				container.appendChild( renderer.domElement );
 
 				const controls = new OrbitControls( camera, renderer.domElement );
@@ -243,13 +250,11 @@
 
 				//
 
-				const gui = new GUI();
-
+				const gui = renderer.inspector.createParameters( 'Settings' );
 				gui.add( params, 'hemiIrradiance', Object.keys( hemiLuminousIrradiances ) );
 				gui.add( params, 'bulbPower', Object.keys( bulbLuminousPowers ) );
 				gui.add( params, 'exposure', 0, 1 );
 				gui.add( params, 'shadows' );
-				gui.open();
 
 			}
 
@@ -289,8 +294,6 @@
 
 				renderer.render( scene, camera );
 
-				stats.update();
-
 			}
 
 		</script>

+ 12 - 5
examples/webgpu_lights_pointlights.html

@@ -1,17 +1,24 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js - lights - point lights</title>
+		<title>three.js webgpu - 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">
+		<link type="text/css" rel="stylesheet" href="example.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://oosmoxiecode.com/archive/js_webgl/stanford_bunny/" target="_blank" rel="noopener">oosmoxiecode</a>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Point Lights</span>
+			</div>
+
+			<small>
+				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://oosmoxiecode.com/archive/js_webgl/stanford_bunny/" target="_blank" rel="noopener">oosmoxiecode</a>
+			</small>
 		</div>
 
 		<script type="importmap">

+ 13 - 17
examples/webgpu_lights_projector.html

@@ -4,12 +4,20 @@
 		<title>three.js webgpu - projector light</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - projector light<br />
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Projector Light</span>
+			</div>
+
+			<small>
+				Projector light with procedural caustics, video and texture projection.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -33,9 +41,7 @@
 			import * as THREE from 'three/webgpu';
 			import { Fn, color, mx_worley_noise_float, time } from 'three/tsl';
 
-			import Stats from 'three/addons/libs/stats.module.js';
-
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			import { PLYLoader } from 'three/addons/loaders/PLYLoader.js';
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
@@ -44,23 +50,17 @@
 
 			let projectorLight, lightHelper;
 
-			let stats;
-
 			init();
 
 			function init() {
 
-				// Stats
-
-				stats = new Stats();
-				document.body.appendChild( stats.dom );
-
 				// Renderer
 
 				renderer = new THREE.WebGPURenderer( { antialias: true } );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				renderer.shadowMap.enabled = true;
@@ -156,7 +156,7 @@
 
 				// GUI
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Projector Light' );
 
 				const params = {
 					type: 'procedural',
@@ -274,8 +274,6 @@
 
 				} );
 
-				gui.open();
-
 			}
 
 			function onWindowResize() {
@@ -291,8 +289,6 @@
 
 				const time = performance.now() / 3000;
 
-				stats.update();
-
 				projectorLight.position.x = Math.cos( time ) * 2.5;
 				projectorLight.position.z = Math.sin( time ) * 2.5;
 

+ 13 - 10
examples/webgpu_lights_rectarealight.html

@@ -1,16 +1,23 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webGPU - rect area light</title>
+		<title>three.js webgpu - rect area light</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - rect area light<br/>
-			by <a href="http://github.com/abelnation" target="_blank" rel="noopener">abelnation</a>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Rect Area Light</span>
+			</div>
+
+			<small>
+				Rect area light by <a href="http://github.com/abelnation" target="_blank" rel="noopener">abelnation</a>.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -28,7 +35,7 @@
 
 			import * as THREE from 'three/webgpu';
 
-			import Stats from 'three/addons/libs/stats.module.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { RectAreaLightHelper } from 'three/addons/helpers/RectAreaLightHelper.js';
@@ -47,6 +54,7 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animation );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
@@ -89,9 +97,6 @@
 
 				window.addEventListener( 'resize', onWindowResize );
 
-				stats = new Stats();
-				document.body.appendChild( stats.dom );
-
 			}
 
 			function onWindowResize() {
@@ -108,8 +113,6 @@
 
 				renderer.render( scene, camera );
 
-				stats.update();
-
 			}
 
 		</script>

+ 22 - 21
examples/webgpu_lights_selective.html

@@ -4,13 +4,20 @@
 		<title>three.js webgpu - selective 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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - selective lights<br />
-			<b style="color:red">Left: Red lights</b> - <b>Center: All lights</b> - <b style="color:blue">Right: blue light</b>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Selective Lights</span>
+			</div>
+
+			<small>
+				<b style="color:red">Left: Red lights</b> - <b>Center: All lights</b> - <b style="color:blue">Right: blue light</b>
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -29,16 +36,14 @@
 			import * as THREE from 'three/webgpu';
 			import { fog, rangeFogFactor, color, lights, texture, normalMap } from 'three/tsl';
 
-			import Stats from 'three/addons/libs/stats.module.js';
-
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { TeapotGeometry } from 'three/addons/geometries/TeapotGeometry.js';
 
 			let camera, scene, renderer,
 				light1, light2, light3, light4,
-				stats, controls;
+				controls;
 
 			init();
 
@@ -52,7 +57,7 @@
 
 				const sphereGeometry = new THREE.SphereGeometry( 0.1, 16, 8 );
 
-				//textures
+				// textures
 
 				const textureLoader = new THREE.TextureLoader();
 
@@ -64,7 +69,7 @@
 				alphaTexture.wrapS = THREE.RepeatWrapping;
 				alphaTexture.wrapT = THREE.RepeatWrapping;
 
-				//lights
+				// lights
 
 				const addLight = ( hexColor, power = 1700, distance = 100 ) => {
 
@@ -89,12 +94,12 @@
 				light3 = addLight( 0x80ff80 );
 				light4 = addLight( 0xffaa00 );
 
-				//light nodes ( selective lights )
+				// light nodes ( selective lights )
 
 				const redLightsNode = lights( [ light1 ] );
 				const blueLightsNode = lights( [ light2 ] );
 
-				//models
+				// models
 
 				const geometryTeapot = new TeapotGeometry( .8, 18 );
 
@@ -120,30 +125,28 @@
 				leftObject.rotation.y = centerObject.rotation.y = rightObject.rotation.y = Math.PI * - 0.5;
 				leftObject.position.y = centerObject.position.y = rightObject.position.y = - 1;
 
-				//renderer
+				// renderer
 
 				renderer = new THREE.WebGPURenderer( { antialias: true } );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
-				//controls
+				// controls
 
 				controls = new OrbitControls( camera, renderer.domElement );
 				controls.minDistance = 3;
 				controls.maxDistance = 25;
 
-				//stats
-
-				stats = new Stats();
-				document.body.appendChild( stats.dom );
+				// events
 
 				window.addEventListener( 'resize', onWindowResize );
 
-				//gui
+				// gui
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Material' );
 
 				gui.add( centerObject.material, 'roughness', 0, 1, 0.01 );
 				gui.add( centerObject.material, 'metalness', 0, 1, 0.01 );
@@ -189,8 +192,6 @@
 				*/
 				renderer.render( scene, camera );
 
-				stats.update();
-
 			}
 
 		</script>

+ 1 - 1
examples/webgpu_lights_spotlight.html

@@ -12,7 +12,7 @@
 			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
 
 			<div class="title-wrapper">
-				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>spot light</span>
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Spot Light</span>
 			</div>
 
 			<small>Spot light projecting texture map.</small>

+ 15 - 13
examples/webgpu_lights_tiled.html

@@ -4,12 +4,20 @@
 		<title>three.js webgpu - tiled lighting</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - Compute-based Tiled Lighting<br />
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Tiled Lighting</span>
+			</div>
+
+			<small>
+				Custom compute-based Tiled Lighting.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -31,9 +39,7 @@
 
 			import { TiledLighting } from 'three/addons/lighting/TiledLighting.js';
 
-			import Stats from 'three/addons/libs/stats.module.js';
-
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
@@ -41,7 +47,7 @@
 
 			let camera, scene, renderer,
 				lights, lightDummy,
-				stats, controls,
+				controls,
 				compose, tileInfluence,
 				lighting,
 				count,
@@ -148,6 +154,7 @@
 				renderer.lighting = lighting; // set lighting system
 				renderer.toneMapping = THREE.NeutralToneMapping;
 				renderer.toneMappingExposure = 5;
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				// controls
@@ -155,10 +162,7 @@
 				controls = new OrbitControls( camera, renderer.domElement );
 				controls.maxDistance = 400;
 
-				// stats
-
-				stats = new Stats();
-				document.body.appendChild( stats.dom );
+				// events
 
 				window.addEventListener( 'resize', onWindowResize );
 
@@ -178,7 +182,7 @@
 
 				// gui
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Settings' );
 				gui.add( tileInfluence, 'value', 0, 1 ).name( 'tile indexes debug' );
 
 			}
@@ -225,8 +229,6 @@
 
 				postProcessing.render();
 
-				stats.update();
-
 			}
 
 		</script>

+ 20 - 16
examples/webgpu_lines_fat_raycasting.html

@@ -1,25 +1,35 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webgpu - lines - fat</title>
+		<title>three.js webgpu - fat lines</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 
 	<body>
 
 		<div id="container"></div>
 
-		<div id="info"><a href="https://threejs.org" target="_blank">three.js</a> - fat lines raycasting</div>
+		<div id="info">
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Fat Lines</span>
+			</div>
+
+			<small>
+				Raycasting on fat lines. Move mouse to test raycasting.
+			</small>
+		</div>
 
 		<script type="importmap">
 			{
 				"imports": {
 					"three": "../build/three.webgpu.js",
 					"three/webgpu": "../build/three.webgpu.js",
-					"three/addons/": "./jsm/",
-					"stats-gl": "https://cdn.jsdelivr.net/npm/stats-gl@3.6.0/dist/main.js"
+					"three/tsl": "../build/three.tsl.js",
+					"three/addons/": "./jsm/"
 				}
 			}
 		</script>
@@ -28,20 +38,19 @@
 
 			import * as THREE from 'three/webgpu';
 
-			import Stats from 'stats-gl';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { LineSegments2 } from 'three/addons/lines/webgpu/LineSegments2.js';
 			import { LineSegmentsGeometry } from 'three/addons/lines/LineSegmentsGeometry.js';
 			import { Line2 } from 'three/addons/lines/webgpu/Line2.js';
 			import { LineGeometry } from 'three/addons/lines/LineGeometry.js';
 
+			//
 
 			let line, thresholdLine, segments, thresholdSegments;
 			let renderer, scene, camera, controls;
 			let sphereInter, sphereOnLine;
-			let stats;
 			let gui;
 			let clock;
 
@@ -102,6 +111,7 @@
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setClearColor( 0x000000, 0.0 );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				scene = new THREE.Scene();
@@ -195,10 +205,6 @@
 				window.addEventListener( 'resize', onWindowResize );
 				onWindowResize();
 
-				stats = new Stats( { horizontal: false, trackGPU: true } );
-				stats.init( renderer );
-				document.body.appendChild( stats.dom );
-
 				initGui();
 
 			}
@@ -267,9 +273,7 @@
 
 				}
 
-				await renderer.renderAsync( scene, camera );
-
-				stats.update();
+				renderer.render( scene, camera );
 
 			}
 
@@ -303,7 +307,7 @@
 
 			function initGui() {
 
-				gui = new GUI();
+				gui = renderer.inspector.createParameters( 'Settings' );
 
 				gui.add( params, 'line type', { 'LineGeometry': 0, 'LineSegmentsGeometry': 1 } ).onChange( function ( val ) {
 

+ 16 - 12
examples/webgpu_lines_fat_wireframe.html

@@ -1,17 +1,27 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webgpu - lines - fat - wireframe</title>
+		<title>three.js webgpu - fat wireframe</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 
 	<body>
 
 		<div id="container"></div>
 
-		<div id="info"><a href="https://threejs.org" target="_blank">three.js</a> - fat lines</div>
+		<div id="info">
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Fat Lines</span>
+			</div>
+
+			<small>
+				Wireframe rendering of fat lines.
+			</small>
+		</div>
 
 		<script type="importmap">
 			{
@@ -29,9 +39,8 @@
 			import * as THREE from 'three/webgpu';
 			import { color } from 'three/tsl';
 
-			import Stats from 'three/addons/libs/stats.module.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { Wireframe } from 'three/addons/lines/webgpu/Wireframe.js';
 			import { WireframeGeometry2 } from 'three/addons/lines/WireframeGeometry2.js';
@@ -39,7 +48,6 @@
 			let wireframe, renderer, scene, camera, camera2, controls, backgroundNode;
 			let wireframe1;
 			let matLine, matLineBasic, matLineDashed;
-			let stats;
 			let gui;
 
 			// viewport
@@ -55,6 +63,7 @@
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setClearColor( 0x000000, 0.0 );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				scene = new THREE.Scene();
@@ -107,9 +116,6 @@
 				window.addEventListener( 'resize', onWindowResize );
 				onWindowResize();
 
-				stats = new Stats();
-				document.body.appendChild( stats.dom );
-
 				initGui();
 
 			}
@@ -164,15 +170,13 @@
 
 				renderer.setScissorTest( false );
 
-				stats.update();
-
 			}
 
 			//
 
 			function initGui() {
 
-				gui = new GUI();
+				gui = renderer.inspector.createParameters( 'Settings' );
 
 				const param = {
 					'line type': 0,

+ 12 - 5
examples/webgpu_loader_gltf.html

@@ -4,15 +4,22 @@
 		<title>three.js webgpu - gltf loader</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - gltf loader<br />
-			Battle Damaged Sci-fi Helmet by
-			<a href="https://sketchfab.com/theblueturtle_" target="_blank" rel="noopener">theblueturtle_</a><br />
-			<a href="https://hdrihaven.com/hdri/?h=royal_esplanade" target="_blank" rel="noopener">Royal Esplanade</a> by <a href="https://hdrihaven.com/" target="_blank" rel="noopener">HDRI Haven</a>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>glTF Loader</span>
+			</div>
+
+			<small>
+				Battle Damaged Sci-fi Helmet by
+				<a href="https://sketchfab.com/theblueturtle_" target="_blank" rel="noopener">theblueturtle_</a><br />
+				<a href="https://hdrihaven.com/hdri/?h=royal_esplanade" target="_blank" rel="noopener">Royal Esplanade</a> by <a href="https://hdrihaven.com/" target="_blank" rel="noopener">HDRI Haven</a>
+			</small>
 		</div>
 
 		<script type="importmap">

+ 14 - 5
examples/webgpu_loader_gltf_anisotropy.html

@@ -4,14 +4,23 @@
 		<title>three.js webgpu - glTF + anisotropy</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 
 	<body>
-		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js webgpu</a> - glTF + <a href="https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_anisotropy" target="_blank" rel="noopener">KHR_materials_anisotropy</a><br />
-			Anisotropy Barn Lamp from <a href="https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/AnisotropyBarnLamp" target="_blank" rel="noopener">glTF-Sample-Models</a><br />
-			<a href="https://hdrihaven.com/hdri/?h=royal_esplanade" target="_blank" rel="noopener">Royal Esplanade</a> from <a href="https://hdrihaven.com/" target="_blank" rel="noopener">HDRI Haven</a>
+
+		<div id="info" class="invert">
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>glTF + Anisotropy</span>
+			</div>
+
+			<small>
+				<a href="https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_anisotropy" target="_blank" rel="noopener">KHR_materials_anisotropy</a>
+				Anisotropy Barn Lamp from <a href="https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/AnisotropyBarnLamp" target="_blank" rel="noopener">glTF-Sample-Models</a><br />
+				<a href="https://hdrihaven.com/hdri/?h=royal_esplanade" target="_blank" rel="noopener">Royal Esplanade</a> from <a href="https://hdrihaven.com/" target="_blank" rel="noopener">HDRI Haven</a>
+			</small>
 		</div>
 
 		<script type="importmap">

+ 10 - 2
examples/webgpu_loader_gltf_compressed.html

@@ -4,12 +4,20 @@
 		<title>three.js webgpu - glTF + compressed</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - glTF + compression extensions
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>glTF + Compression Extensions</span>
+			</div>
+
+			<small>
+				glTF model loading with KTX2/Basis and Meshopt compression extensions.
+			</small>
 		</div>
 
 		<script type="importmap">

+ 11 - 3
examples/webgpu_loader_gltf_dispersion.html

@@ -4,13 +4,21 @@
 		<title>three.js webgpu - glTF + dispersion</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 
 	<body>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - glTF + <a href="https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_dispersion" target="_blank" rel="noopener">KHR_materials_dispersion</a><br />
-			HDR by <a href="https://polyhaven.com/a/studio_small_08" target="_blank" rel="noopener">Poly Haven</a> 
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>glTF + Dispersion</span>
+			</div>
+
+			<small>
+				<a href="https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_dispersion" target="_blank" rel="noopener">KHR_materials_dispersion</a> HDR by <a href="https://polyhaven.com/a/studio_small_08" target="_blank" rel="noopener">Poly Haven</a> 
+			</small>
 		</div>
 
 		<script type="importmap">

+ 12 - 4
examples/webgpu_loader_gltf_iridescence.html

@@ -4,14 +4,22 @@
 		<title>three.js webgpu - glTF + iridescence</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 
 	<body>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - glTF + <a href="https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_iridescence" target="_blank" rel="noopener">KHR_materials_iridescence</a><br />
-			Iridescence Lamp from <a href="https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/IridescenceLamp" target="_blank" rel="noopener">glTF-Sample-Models</a><br />
-			<a href="https://hdrihaven.com/hdri/?h=venice_sunset" target="_blank" rel="noopener">Venice Sunset</a> from <a href="https://hdrihaven.com/" target="_blank" rel="noopener">HDRI Haven</a>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>glTF + Iridescence</span>
+			</div>
+
+			<small>
+				<a href="https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_iridescence" target="_blank" rel="noopener">KHR_materials_iridescence</a> Iridescence Lamp from <a href="https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/IridescenceLamp" target="_blank" rel="noopener">glTF-Sample-Models</a><br />
+				<a href="https://hdrihaven.com/hdri/?h=venice_sunset" target="_blank" rel="noopener">Venice Sunset</a> from <a href="https://hdrihaven.com/" target="_blank" rel="noopener">HDRI Haven</a>
+			</small>
 		</div>
 
 		<script type="importmap">

+ 14 - 6
examples/webgpu_loader_gltf_sheen.html

@@ -4,7 +4,7 @@
 		<title>three.js webgpu - sheen</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 		<style>
 			body {
 				background: #bbbbbb;
@@ -13,9 +13,17 @@
 	</head>
 
 	<body>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - glTF + <a href="https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_sheen" target="_blank" rel="noopener">KHR_materials_sheen</a><br />
-			Sheen Chair from <a href="https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/SheenChair" target="_blank" rel="noopener">glTF-Sample-Models</a>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>glTF + Anisotropy</span>
+			</div>
+
+			<small>
+				<a href="https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_sheen" target="_blank" rel="noopener">KHR_materials_sheen</a> Sheen Chair from <a href="https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/SheenChair" target="_blank" rel="noopener">glTF-Sample-Models</a>
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -37,7 +45,7 @@
 			import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
 			import { HDRLoader } from 'three/addons/loaders/HDRLoader.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let camera, scene, renderer, controls;
 
@@ -64,10 +72,9 @@
 
 						const object = gltf.scene.getObjectByName( 'SheenChair_fabric' );
 
-						const gui = new GUI();
+						const gui = renderer.inspector.createParameters( 'SheenChair_fabric' );
 
 						gui.add( object.material, 'sheen', 0, 1 );
-						gui.open();
 
 					} );
 
@@ -77,6 +84,7 @@
 				renderer.setAnimationLoop( animate );
 				renderer.toneMapping = THREE.ACESFilmicToneMapping;
 				renderer.toneMappingExposure = 1;
+				renderer.inspector = new Inspector();
 				container.appendChild( renderer.domElement );
 
 				scene.background = new THREE.Color( 0xAAAAAA );

+ 11 - 4
examples/webgpu_loader_gltf_transmission.html

@@ -4,14 +4,21 @@
 		<title>three.js webgpu - glTF + transmission</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - glTF + <a href="https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission" target="_blank" rel="noopener">KHR_materials_transmission</a><br />
-			Iridescent Dish With Olives by <a href="https://github.com/echadwick-wayfair" target="_blank" rel="noopener">Eric Chadwick</a><br />
-			<a href="https://hdrihaven.com/hdri/?h=royal_esplanade" target="_blank" rel="noopener">Royal Esplanade</a> from <a href="https://hdrihaven.com/" target="_blank" rel="noopener">HDRI Haven</a>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>glTF + Transmission</span>
+			</div>
+
+			<small>
+				<a href="https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission" target="_blank" rel="noopener">KHR_materials_transmission</a> Iridescent Dish With Olives by <a href="https://github.com/echadwick-wayfair" target="_blank" rel="noopener">Eric Chadwick</a><br />
+				<a href="https://hdrihaven.com/hdri/?h=royal_esplanade" target="_blank" rel="noopener">Royal Esplanade</a> from <a href="https://hdrihaven.com/" target="_blank" rel="noopener">HDRI Haven</a>
+			</small>
 		</div>
 
 		<script type="importmap">

+ 15 - 8
examples/webgpu_loader_materialx.html

@@ -4,7 +4,7 @@
 		<title>three.js webgpu - materialx loader</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 		<style>
 			.dg .property-name {
 				width: 20% !important;
@@ -14,7 +14,15 @@
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - materialx loader<br />
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>MaterialX Loader</span>
+			</div>
+
+			<small>
+				MaterialX Standard Surface loader.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -41,7 +49,7 @@
 
 			import { MaterialXLoader } from 'three/addons/loaders/MaterialXLoader.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			const SAMPLE_PATH = 'https://raw.githubusercontent.com/materialx/MaterialX/main/resources/Materials/Examples/StandardSurface/';
 			const LOCAL_SAMPLE_PATH = 'materialx/';
@@ -108,6 +116,7 @@
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.toneMapping = THREE.LinearToneMapping;
 				renderer.toneMappingExposure = .5;
+				renderer.inspector = new Inspector();
 				renderer.setAnimationLoop( render );
 				container.appendChild( renderer.domElement );
 
@@ -259,16 +268,14 @@
 
 			function addGUI() {
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'MaterialX Loader' );
 
 				const API = {
 					showCalibrationMesh: true,
 					showPreviewMesh: true
 				};
 
-				const folder = gui.addFolder( 'SHOW' );
-
-				folder.add( API, 'showCalibrationMesh' )
+				gui.add( API, 'showCalibrationMesh' )
 					.name( 'Calibration Mesh' )
 					.onChange( function ( value ) {
 
@@ -276,7 +283,7 @@
 
 					} );
 
-				folder.add( API, 'showPreviewMesh' )
+				gui.add( API, 'showPreviewMesh' )
 					.name( 'Preview Mesh' )
 					.onChange( function ( value ) {
 

+ 12 - 12
examples/webgpu_materials.html

@@ -4,12 +4,20 @@
 		<title>three.js webgpu - materials</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - materials
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Materials</span>
+			</div>
+
+			<small>
+				Examples of built-in materials and NodeMaterials.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -33,9 +41,7 @@
 			import { TeapotGeometry } from 'three/addons/geometries/TeapotGeometry.js';
 			import WebGPU from 'three/addons/capabilities/WebGPU.js';
 
-			import Stats from 'three/addons/libs/stats.module.js';
-
-			let stats;
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let camera, scene, renderer;
 
@@ -373,15 +379,11 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				container.appendChild( renderer.domElement );
 
 				//
 
-				stats = new Stats();
-				container.appendChild( stats.dom );
-
-				//
-
 				window.addEventListener( 'resize', onWindowResize );
 
 				//
@@ -479,8 +481,6 @@
 
 				renderer.render( scene, camera );
 
-				stats.update();
-
 			}
 
 		</script>

+ 8 - 11
examples/webgpu_materials_alphahash.html

@@ -1,12 +1,13 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webgpu - materials - alpha hash</title>
+		<title>three.js webgpu - alpha hash</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
+
 		<script type="importmap">
 			{
 				"imports": {
@@ -22,14 +23,14 @@
 
 			import * as THREE from 'three/webgpu';
 
-			import Stats from 'three/addons/libs/stats.module.js';
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
 
 			import { ssaaPass } from 'three/addons/tsl/display/SSAAPassNode.js';
 
-			let camera, scene, renderer, controls, stats, mesh, material, postProcessing;
+			let camera, scene, renderer, controls, mesh, material, postProcessing;
 
 			const amount = parseInt( window.location.search.slice( 1 ) ) || 3;
 			const count = Math.pow( amount, 3 );
@@ -93,6 +94,7 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				await renderer.init();
@@ -123,7 +125,7 @@
 
 				//
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Parameters' );
 
 				gui.add( params, 'alpha', 0, 1 ).onChange( onMaterialUpdate );
 				gui.add( params, 'alphaHash' ).onChange( onMaterialUpdate );
@@ -133,9 +135,6 @@
 
 				//
 
-				stats = new Stats();
-				document.body.appendChild( stats.dom );
-
 				window.addEventListener( 'resize', onWindowResize );
 
 			}
@@ -164,8 +163,6 @@
 
 				postProcessing.render();
 
-				stats.update();
-
 			}
 
 		</script>

+ 15 - 4
examples/webgpu_materials_arrays.html

@@ -4,12 +4,21 @@
 		<title>three.js webgpu - materials arrays and geometry groups</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 
 	<body>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - WebGPU Materials Arrays and Geometry Groups<br />
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Material Array</span>
+			</div>
+
+			<small>
+				Materials Arrays and Geometry Groups.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -28,7 +37,8 @@
 			import * as THREE from 'three/webgpu';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let renderer, scene, camera, controls;
 			let planeMesh, boxMesh, boxMeshWireframe, planeMeshWireframe;
@@ -59,6 +69,7 @@
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				// scene
@@ -145,7 +156,7 @@
 
 			// gui
 
-			const gui = new GUI();
+			const gui = renderer.inspector.createParameters( 'Parameters' );
 
 			gui.add( api, 'webgpu' ).onChange( () => {
 

+ 20 - 7
examples/webgpu_materials_basic.html

@@ -1,12 +1,25 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webgpu - material - basic</title>
+		<title>three.js webgpu - basic material</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
+
+		<div id="info">
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Basic Material</span>
+			</div>
+
+			<small>
+				Basic Material example.
+			</small>
+		</div>
+
 		<script type="importmap">
 			{
 				"imports": {
@@ -22,7 +35,7 @@
 
 			import * as THREE from 'three/webgpu';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let camera, scene, renderer;
 
@@ -91,11 +104,12 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				//
 
-				const gui = new GUI( { width: 300 } );
+				const gui = renderer.inspector.createParameters( 'Parameters' );
 
 				gui.addColor( params, 'color' ).onChange( ( value ) => material.color.set( value ) );
 				gui.add( params, 'mapping', mappings ).onChange( ( value ) => {
@@ -104,15 +118,14 @@
 					material.needsUpdate = true;
 			
 				} );
-				gui.add( params, 'refractionRatio' ).min( 0.0 ).max( 1.0 ).step( 0.01 ).onChange( ( value ) => material.refractionRatio = value );
+				gui.add( params, 'refractionRatio', 0, 1, 0.01 ).onChange( ( value ) => material.refractionRatio = value );
 				gui.add( params, 'transparent' ).onChange( ( value ) => {
 			
 					material.transparent = value;
 					material.needsUpdate = true;
 
 				} );
-				gui.add( params, 'opacity' ).min( 0.0 ).max( 1.0 ).step( 0.01 ).onChange( ( value ) => material.opacity = value );
-				gui.open();
+				gui.add( params, 'opacity', 0, 1, 0.01 ).onChange( ( value ) => material.opacity = value );
 
 				//
 

+ 14 - 5
examples/webgpu_materials_cubemap_mipmaps.html

@@ -1,18 +1,27 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js WebGPU - materials - cubemap mipmaps</title>
+		<title>three.js webgpu - cubemap mipmaps</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="container"></div>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - cubemap customized mipmaps demo.<br/>
-			Left: WebGPU generated mipmaps<br/>
-			Right: manual mipmaps<br/>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Custom CubeMap Mipmaps</span>
+			</div>
+
+			<small>
+				Cubemap customized mipmaps demo.<br/>
+				Left: WebGPU generated mipmaps<br/>
+				Right: manual mipmaps<br/>
+			</small>
 		</div>
 
 		<script type="importmap">

+ 21 - 21
examples/webgpu_materials_displacementmap.html

@@ -4,14 +4,22 @@
 		<title>three.js webgpu - displacement map</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - ( normal + ao + displacement + environment ) maps<br />
-			ninja head from <a href="https://gpuopen.com/archive/gamescgi/amd-gpu-meshmapper/" target="_blank" rel="noopener">AMD GPU MeshMapper</a>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Displacement Map</span>
+			</div>
+
+			<small>
+				( normal + ao + displacement + environment ) maps.<br />
+				Ninja head from <a href="https://gpuopen.com/archive/gamescgi/amd-gpu-meshmapper/" target="_blank" rel="noopener">AMD GPU MeshMapper</a>.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -29,13 +37,11 @@
 
 			import * as THREE from 'three/webgpu';
 
-			import Stats from 'three/addons/libs/stats.module.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
 
-			let stats;
 			let camera, scene, renderer, controls;
 
 			const settings = {
@@ -62,45 +68,45 @@
 			// Init gui
 			function initGui() {
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'settings' );
 
-				gui.add( settings, 'metalness' ).min( 0 ).max( 1 ).onChange( function ( value ) {
+				gui.add( settings, 'metalness', 0, 1 ).onChange( function ( value ) {
 
 					material.metalness = value;
 
 				} );
 
-				gui.add( settings, 'roughness' ).min( 0 ).max( 1 ).onChange( function ( value ) {
+				gui.add( settings, 'roughness', 0, 1 ).onChange( function ( value ) {
 
 					material.roughness = value;
 
 				} );
 
-				gui.add( settings, 'aoMapIntensity' ).min( 0 ).max( 1 ).onChange( function ( value ) {
+				gui.add( settings, 'aoMapIntensity', 0, 1 ).onChange( function ( value ) {
 
 					material.aoMapIntensity = value;
 
 				} );
 
-				gui.add( settings, 'ambientIntensity' ).min( 0 ).max( 1 ).onChange( function ( value ) {
+				gui.add( settings, 'ambientIntensity', 0, 1 ).onChange( function ( value ) {
 
 					ambientLight.intensity = value;
 
 				} );
 
-				gui.add( settings, 'envMapIntensity' ).min( 0 ).max( 3 ).onChange( function ( value ) {
+				gui.add( settings, 'envMapIntensity', 0, 3 ).onChange( function ( value ) {
 
 					material.envMapIntensity = value;
 
 				} );
 
-				gui.add( settings, 'displacementScale' ).min( 0 ).max( 3.0 ).onChange( function ( value ) {
+				gui.add( settings, 'displacementScale', 0, 3.0 ).onChange( function ( value ) {
 
 					material.displacementScale = value;
 
 				} );
 
-				gui.add( settings, 'normalScale' ).min( - 1 ).max( 1 ).onChange( function ( value ) {
+				gui.add( settings, 'normalScale', - 1, 1 ).onChange( function ( value ) {
 
 					material.normalScale.set( 1, - 1 ).multiplyScalar( value );
 
@@ -117,6 +123,7 @@
 				renderer.setAnimationLoop( animate );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.inspector = new Inspector();
 				container.appendChild( renderer.domElement );
 
 				//
@@ -209,11 +216,6 @@
 
 				//
 
-				stats = new Stats();
-				container.appendChild( stats.dom );
-
-				//
-
 				window.addEventListener( 'resize', onWindowResize );
 
 			}
@@ -239,9 +241,7 @@
 
 				controls.update();
 
-				stats.begin();
 				render();
-				stats.end();
 
 			}
 

+ 29 - 20
examples/webgpu_materials_envmaps.html

@@ -1,16 +1,23 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webgpu - materials - environment maps</title>
+		<title>three.js webgpu - environment maps</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - webgpu environment mapping example<br/>
-			Equirectangular Map by <a href="http://www.flickr.com/photos/jonragnarsson/2294472375/" target="_blank" rel="noopener">J&oacute;n Ragnarsson</a>.
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Environment Mapping</span>
+			</div>
+
+			<small>
+				Equirectangular Map by <a href="http://www.flickr.com/photos/jonragnarsson/2294472375/" target="_blank" rel="noopener">J&oacute;n Ragnarsson</a>.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -24,12 +31,12 @@
 			}
 		</script>
 
-
 		<script type="module">
 
 			import * as THREE from 'three/webgpu';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 			let controls, camera, scene, renderer;
@@ -77,6 +84,7 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				//
@@ -88,32 +96,34 @@
 				//
 
 				params = {
-					Cube: function () {
+					Type: 'Cube',
+					Refraction: false,
+					backgroundRotationX: false,
+					backgroundRotationY: false,
+					backgroundRotationZ: false,
+					syncMaterial: false
+				};
+
+				const gui = renderer.inspector.createParameters( 'Parameters' );
+				gui.add( params, 'Type', [ 'Cube', 'Equirectangular' ] ).onChange( function ( value ) {
+
+					if ( value === 'Cube' ) {
 
 						scene.background = textureCube;
 
 						sphereMaterial.envMap = textureCube;
 						sphereMaterial.needsUpdate = true;
 
-					},
-					Equirectangular: function () {
+					} else if ( value === 'Equirectangular' ) {
 
 						scene.background = textureEquirec;
 
 						sphereMaterial.envMap = textureEquirec;
 						sphereMaterial.needsUpdate = true;
 
-					},
-					Refraction: false,
-					backgroundRotationX: false,
-					backgroundRotationY: false,
-					backgroundRotationZ: false,
-					syncMaterial: false
-				};
+					}
 
-				const gui = new GUI( { width: 300 } );
-				gui.add( params, 'Cube' );
-				gui.add( params, 'Equirectangular' );
+				} );
 				gui.add( params, 'Refraction' ).onChange( function ( value ) {
 
 					if ( value ) {
@@ -135,7 +145,6 @@
 				gui.add( params, 'backgroundRotationY' );
 				gui.add( params, 'backgroundRotationZ' );
 				gui.add( params, 'syncMaterial' );
-				gui.open();
 
 				window.addEventListener( 'resize', onWindowResize );
 

+ 15 - 6
examples/webgpu_materials_envmaps_bpcem.html

@@ -1,15 +1,23 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webgpu - materials - bpcem</title>
+		<title>three.js webgpu - bpcem</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - webgpu - box projected cube environment mapping (BPCEM)<br/>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>BPCEM</span>
+			</div>
+
+			<small>
+				Box projected cube environment mapping (BPCEM).
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -23,13 +31,13 @@
 			}
 		</script>
 
-
 		<script type="module">
 
 			import * as THREE from 'three/webgpu';
 			import { bumpMap, float, getParallaxCorrectNormal, pmremTexture, reflectVector, texture, uniform, vec3 } from 'three/tsl';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { RectAreaLightHelper } from 'three/addons/helpers/RectAreaLightHelper.js';
 			import { RectAreaLightTexturesLib } from 'three/addons/lights/RectAreaLightTexturesLib.js';
@@ -165,6 +173,7 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				window.addEventListener( 'resize', onWindowResize );
@@ -179,7 +188,7 @@
 
 				// gui
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Parameters' );
 				const params = {
 					'box projected': true
 				};

+ 5 - 4
examples/webgpu_materials_lightmap.html

@@ -4,10 +4,11 @@
 		<title>three.js webgpu - lightmap</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 
 	<body>
+
 		<script type="importmap">
 			{
 				"imports": {
@@ -24,7 +25,7 @@
 			import * as THREE from 'three/webgpu';
 			import { vec4, color, positionLocal, mix } from 'three/tsl';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
@@ -89,6 +90,7 @@
 				renderer.setAnimationLoop( animate );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( innerWidth, innerHeight );
+				renderer.inspector = new Inspector();
 				container.appendChild( renderer.domElement );
 
 				// CONTROLS
@@ -99,7 +101,7 @@
 
 				// GUI
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Parameters' );
 
 				gui.add( params, 'intensity', 0, 1 ).name( 'Light Map Intensity' ).onChange( ( value ) => {
 
@@ -110,7 +112,6 @@
 					}
 
 				} );
-				gui.open();
 
 				//
 

+ 17 - 13
examples/webgpu_materials_matcap.html

@@ -4,13 +4,21 @@
 		<title>three.js webgpu - matcap material</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 
 	<body>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - matcap material<br />
-			Drag-and-drop JPG, PNG, WebP, AVIF, or EXR MatCap image files<br/>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Matcap Material</span>
+			</div>
+
+			<small>
+				Drag-and-drop JPG, PNG, WebP, AVIF, or EXR MatCap image files.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -28,7 +36,8 @@
 
 			import * as THREE from 'three/webgpu';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
 			import { EXRLoader } from 'three/addons/loaders/EXRLoader.js';
@@ -48,6 +57,8 @@
 				renderer = new THREE.WebGPURenderer( { antialias: true } );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setAnimationLoop( render );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				// tone mapping
@@ -98,27 +109,24 @@
 				} );
 
 				// gui
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Parameters' );
 
 				gui.addColor( API, 'color' )
 					.listen()
 					.onChange( function () {
 
 						mesh.material.color.set( API.color );
-						render();
 
 					} );
 
 				gui.add( API, 'exposure', 0, 2 )
+					.listen()
 					.onChange( function () {
 
 						renderer.toneMappingExposure = API.exposure;
-						render();
 
 					} );
 
-				gui.domElement.style.webkitUserSelect = 'none';
-
 				// drag 'n drop
 				initDragAndDrop();
 
@@ -133,8 +141,6 @@
 				camera.aspect = window.innerWidth / window.innerHeight;
 				camera.updateProjectionMatrix();
 
-				render();
-
 			}
 
 			function render() {
@@ -161,8 +167,6 @@
 
 				mesh.material.needsUpdate = true; // because the color space can change
 
-				render();
-
 			}
 
 			function handleJPG( event ) { // PNG, WebP, AVIF, too

+ 26 - 25
examples/webgpu_materials_sss.html

@@ -4,14 +4,23 @@
 		<title>three.js webgpu - sss</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="container"></div>
-		<div id="info"><a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - sss
-			<br/>Fast subsurface scattering<br/>
-			[Thanks for the art support from <a href="https://github.com/shaochun" target="_blank" rel="noopener">Shaochun Lin</a>]
+
+		<div id="info">
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>SSS</span>
+			</div>
+
+			<small>
+				Fast subsurface scattering<br/>
+				[Thanks for the art support from <a href="https://github.com/shaochun" target="_blank" rel="noopener">Shaochun Lin</a>]
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -30,13 +39,12 @@
 			import * as THREE from 'three/webgpu';
 			import { texture, uniform, vec3 } from 'three/tsl';
 
-			import Stats from 'three/addons/libs/stats.module.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { FBXLoader } from 'three/addons/loaders/FBXLoader.js';
 
-			let container, stats;
+			let container;
 			let camera, scene, renderer;
 			let model;
 
@@ -77,13 +85,15 @@
 				renderer = new THREE.WebGPURenderer( { antialias: true } );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
-				renderer.setAnimationLoop( animate );
+				renderer.setAnimationLoop( render );
 				container.appendChild( renderer.domElement );
 
 				//
 
-				stats = new Stats();
-				container.appendChild( stats.dom );
+				renderer.inspector = new Inspector();
+				document.body.appendChild( renderer.inspector.domElement );
+
+				//
 
 				const controls = new OrbitControls( camera, container );
 				controls.minDistance = 500;
@@ -133,7 +143,7 @@
 
 			function initGUI( material ) {
 
-				const gui = new GUI( { title: 'Thickness Control' } );
+				const gui = renderer.inspector.createParameters( 'Parameters' );
 
 				const ThicknessControls = function () {
 
@@ -147,32 +157,31 @@
 
 				const thicknessControls = new ThicknessControls();
 
-				gui.add( thicknessControls, 'distortion' ).min( 0.01 ).max( 1 ).step( 0.01 ).onChange( function () {
+				gui.add( thicknessControls, 'distortion', 0.01, 1, 0.01 ).onChange( function () {
 
 					material.thicknessDistortionNode.value = thicknessControls.distortion;
-					console.log( 'distortion' );
 
 				} );
 
-				gui.add( thicknessControls, 'ambient' ).min( 0.01 ).max( 5.0 ).step( 0.05 ).onChange( function () {
+				gui.add( thicknessControls, 'ambient', 0.01, 5.0, 0.05 ).onChange( function () {
 
 					material.thicknessAmbientNode.value = thicknessControls.ambient;
 
 				} );
 
-				gui.add( thicknessControls, 'attenuation' ).min( 0.01 ).max( 5.0 ).step( 0.05 ).onChange( function () {
+				gui.add( thicknessControls, 'attenuation', 0.01, 5.0, 0.05 ).onChange( function () {
 
 					material.thicknessAttenuationNode.value = thicknessControls.attenuation;
 
 				} );
 
-				gui.add( thicknessControls, 'power' ).min( 0.01 ).max( 16.0 ).step( 0.1 ).onChange( function () {
+				gui.add( thicknessControls, 'power', 0.01, 16.0, 0.1 ).onChange( function () {
 
 					material.thicknessPowerNode.value = thicknessControls.power;
 
 				} );
 
-				gui.add( thicknessControls, 'scale' ).min( 0.01 ).max( 50.0 ).step( 0.1 ).onChange( function () {
+				gui.add( thicknessControls, 'scale', 0.01, 50.0, 0.1 ).onChange( function () {
 
 					material.thicknessScaleNode.value = thicknessControls.scale;
 
@@ -191,14 +200,6 @@
 
 			//
 
-			function animate() {
-
-				render();
-
-				stats.update();
-
-			}
-
 			function render() {
 
 				if ( model ) model.rotation.y = performance.now() / 5000;

+ 12 - 4
examples/webgpu_materials_texture_manualmipmap.html

@@ -1,10 +1,10 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js WebGPU - materials - manual mipmaping</title>
+		<title>three.js webgpu - manual mipmaping</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 		<style>
 
 			.lbl { color:#fff; font-size:16px; font-weight:bold; position: absolute; bottom:0px; z-index:100; text-shadow:#000 1px 1px 1px; background-color:rgba(0,0,0,0.85); padding:1em }
@@ -18,9 +18,17 @@
 	</head>
 
 	<body>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - texture manual mipmapping example<br/>
-			painting by <a href="http://en.wikipedia.org/wiki/Basket_of_Fruit_%28Caravaggio%29">Caravaggio</a>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Texture Manual Mipmapping</span>
+			</div>
+
+			<small>
+				Painting by <a href="http://en.wikipedia.org/wiki/Basket_of_Fruit_%28Caravaggio%29">Caravaggio</a>.
+			</small>
 		</div>
 
 		<div id="lbl_left" class="lbl">

+ 16 - 11
examples/webgpu_materials_toon.html

@@ -4,12 +4,23 @@
 		<title>three.js webgpu - toon material</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="container"></div>
-		<div id="info"><a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - toon material</div>
+
+		<div id="info">
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Toon Material</span>
+			</div>
+
+			<small>
+				Toon material and outline post-processing effect.
+			</small>
+		</div>
 
 		<script type="importmap">
 			{
@@ -27,13 +38,13 @@
 			import * as THREE from 'three/webgpu';
 			import { toonOutlinePass } from 'three/tsl';
 
-			import Stats from 'three/addons/libs/stats.module.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { FontLoader } from 'three/addons/loaders/FontLoader.js';
 			import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
 
-			let container, stats;
+			let container;
 
 			let camera, scene, renderer, postProcessing;
 			let particleLight;
@@ -64,6 +75,7 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( render );
+				renderer.inspector = new Inspector();
 				container.appendChild( renderer.domElement );
 
 				//
@@ -161,9 +173,6 @@
 
 				//
 
-				stats = new Stats();
-				container.appendChild( stats.dom );
-
 				const controls = new OrbitControls( camera, renderer.domElement );
 				controls.minDistance = 200;
 				controls.maxDistance = 2000;
@@ -191,12 +200,8 @@
 				particleLight.position.y = Math.cos( timer * 5 ) * 400;
 				particleLight.position.z = Math.cos( timer * 3 ) * 300;
 
-				stats.begin();
-
 				postProcessing.render();
 
-				stats.end();
-
 			}
 
 		</script>

+ 19 - 6
examples/webgpu_materials_transmission.html

@@ -4,12 +4,23 @@
 		<title>threejs webgpu - transmission</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="container"></div>
-		<div id="info"><a href="https://threejs.org" target="_blank" rel="noopener">threejs</a> webgpu - transmission</div>
+
+		<div id="info">
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Transmission</span>
+			</div>
+
+			<small>
+				Examples of built-in materials and NodeMaterials.
+			</small>
+		</div>
 
 		<script type="importmap">
 			{
@@ -26,7 +37,8 @@
 
 			import * as THREE from 'three/webgpu';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { HDRLoader } from 'three/addons/loaders/HDRLoader.js';
 
@@ -66,6 +78,7 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( render );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				renderer.toneMapping = THREE.ACESFilmicToneMapping;
@@ -120,7 +133,7 @@
 
 				//
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Settings' );
 
 				gui.addColor( params, 'color' )
 					.onChange( function () {
@@ -172,6 +185,7 @@
 					} );
 
 				gui.add( params, 'specularIntensity', 0, 1, 0.01 )
+					.name( 'specular intensity' )
 					.onChange( function () {
 
 						material.specularIntensity = params.specularIntensity;
@@ -179,6 +193,7 @@
 					} );
 
 				gui.addColor( params, 'specularColor' )
+					.name( 'specular color' )
 					.onChange( function () {
 
 						material.specularColor.set( params.specularColor );
@@ -200,8 +215,6 @@
 
 					} );
 
-				gui.open();
-
 			}
 
 			function onWindowResize() {

+ 11 - 3
examples/webgpu_materials_video.html

@@ -4,18 +4,26 @@
 		<title>three.js webgpu - video material</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="overlay">
 			<button id="startButton">Play</button>
 		</div>
+
 		<div id="container"></div>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - video material<br/>
-			playing <a href="http://durian.blender.org/" target="_blank" rel="noopener">sintel</a> trailer
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Video Material</span>
+			</div>
+
+			<small>
+				Playing <a href="http://durian.blender.org/" target="_blank" rel="noopener">sintel</a> trailer.
+			</small>
 		</div>
 
 		<video id="video" loop crossOrigin="anonymous" playsinline style="display:none">

+ 13 - 21
examples/webgpu_materialx_noise.html

@@ -4,11 +4,18 @@
 		<title>three.js webgpu - materialx noise</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - materialx noise
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>MaterialX Noise</span>
+			</div>
+
+			<small>MaterialX noise functions.</small>
 		</div>
 
 		<script type="importmap">
@@ -27,12 +34,12 @@
 			import * as THREE from 'three/webgpu';
 			import { normalWorld, time, mx_noise_vec3, mx_worley_noise_vec3, mx_cell_noise_float, mx_fractal_noise_vec3 } from 'three/tsl';
 
-			import Stats from 'three/addons/libs/stats.module.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { HDRCubeTextureLoader } from 'three/addons/loaders/HDRCubeTextureLoader.js';
 
-			let container, stats;
+			let container;
 
 			let camera, scene, renderer;
 
@@ -123,9 +130,10 @@
 				particleLight.add( new THREE.PointLight( 0xffffff, 1000 ) );
 
 				renderer = new THREE.WebGPURenderer( { antialias: true } );
-				renderer.setAnimationLoop( animate );
+				renderer.setAnimationLoop( render );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.inspector = new Inspector();
 				container.appendChild( renderer.domElement );
 
 				//
@@ -133,14 +141,6 @@
 				renderer.toneMapping = THREE.ACESFilmicToneMapping;
 				renderer.toneMappingExposure = 1.25;
 
-				//
-
-
-				//
-
-				stats = new Stats();
-				container.appendChild( stats.dom );
-
 				// EVENTS
 
 				new OrbitControls( camera, renderer.domElement );
@@ -165,14 +165,6 @@
 
 			//
 
-			function animate() {
-
-				render();
-
-				stats.update();
-
-			}
-
 			function render() {
 
 				const timer = Date.now() * 0.00025;

+ 15 - 25
examples/webgpu_mesh_batch.html

@@ -1,27 +1,28 @@
 <!DOCTYPE html>
 <html lang="en">
 <head>
-	<title>three.js webgpu - mesh - batch</title>
+	<title>three.js webgpu - batch mesh</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">
-	<style>
-		#info {
-			background-color: rgba(0,0,0,0.75);
-		}
-	</style>
+	<link type="text/css" rel="stylesheet" href="example.css">
 </head>
 <body>
 
 	<div id="info">
-		<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - mesh - batch
+		<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+		<div class="title-wrapper">
+			<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Batch Mesh</span>
+		</div>
+
+		<small>Mirror reflections using procedural effects.</small>
 	</div>
 
 	<script type="importmap">
 		{
 			"imports": {
 				"three": "../build/three.webgpu.js",
-					"three/webgpu": "../build/three.webgpu.js",
+				"three/webgpu": "../build/three.webgpu.js",
 				"three/tsl": "../build/three.tsl.js",
 				"three/addons/": "./jsm/"
 			}
@@ -32,9 +33,7 @@
 
 		import * as THREE from 'three/webgpu';
 
-		import Stats from 'three/addons/libs/stats.module.js';
-
-		import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+		import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 		import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 		import { radixSort } from 'three/addons/utils/SortUtils.js';
@@ -42,7 +41,7 @@
 		import { normalView, directionToColor, diffuseColor } from 'three/tsl';
 
 		let camera, scene, renderer;
-		let controls, stats;
+		let controls;
 		let gui;
 		let geometries, mesh, material;
 		const ids = [];
@@ -203,7 +202,6 @@
 
 				renderer.dispose();
 				controls.dispose();
-				document.body.removeChild( stats.dom );
 				document.body.removeChild( renderer.domElement );
 
 			}
@@ -220,7 +218,7 @@
 			renderer = new THREE.WebGPURenderer( { antialias: true, forceWebGL } );
 			renderer.setPixelRatio( window.devicePixelRatio );
 			renderer.setSize( window.innerWidth, window.innerHeight );
-
+			renderer.inspector = new Inspector();
 			renderer.setAnimationLoop( animate );
 
 			// scene
@@ -241,14 +239,9 @@
 			controls.autoRotate = true;
 			controls.autoRotateSpeed = 1.0;
 
-			// stats
-
-			stats = new Stats();
-			document.body.appendChild( stats.dom );
-
 			// gui
 
-			gui = new GUI();
+			gui = renderer.inspector.createParameters( 'Settings' );
 			gui.add( api, 'webgpu' ).onChange( () => {
 
 				init( ! api.webgpu );
@@ -304,7 +297,6 @@
 
 				controls.update();
 
-
 				if ( mesh.isBatchedMesh ) {
 
 					mesh.sortObjects = api.sortObjects;
@@ -313,9 +305,7 @@
 
 				}
 
-				await renderer.renderAsync( scene, camera );
-
-				stats.update();
+				renderer.render( scene, camera );
 
 			}
 

+ 11 - 9
examples/webgpu_modifier_curve.html

@@ -7,11 +7,18 @@
 			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" />
+		<link type="text/css" rel="stylesheet" href="example.css" />
 	</head>
 	<body>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - curve modifier
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Curve Modifier</span>
+			</div>
+
+			<small>Deform a mesh along a curve using GPU acceleration.</small>
 		</div>
 
 		<script type="importmap">
@@ -26,9 +33,10 @@
 		</script>
 
 		<script type="module">
+
 			import * as THREE from 'three/webgpu';
 			import { TransformControls } from 'three/addons/controls/TransformControls.js';
-			import Stats from 'three/addons/libs/stats.module.js';
+
 			import { Flow } from 'three/addons/modifiers/CurveModifierGPU.js';
 			import { FontLoader } from 'three/addons/loaders/FontLoader.js';
 			import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
@@ -37,7 +45,6 @@
 			const curveHandles = [];
 			const mouse = new THREE.Vector2();
 
-			let stats;
 			let scene,
 				camera,
 				renderer,
@@ -158,9 +165,6 @@
 
 				} );
 
-				stats = new Stats();
-				document.body.appendChild( stats.dom );
-
 				window.addEventListener( 'resize', onWindowResize );
 
 			}
@@ -213,8 +217,6 @@
 
 				renderer.render( scene, camera );
 
-				stats.update();
-
 			}
 		</script>
 	</body>

+ 17 - 7
examples/webgpu_morphtargets.html

@@ -4,14 +4,22 @@
 		<title>three.js webgpu - morph targets</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 
 	<body>
 		<div id="container"></div>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - morph targets<br/>
-			by <a href="https://discoverthreejs.com/" target="_blank" rel="noopener">Discover three.js</a>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Morph Targets</span>
+			</div>
+
+			<small>
+				Morph targets / blend shapes example with a simple geometry.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -29,7 +37,7 @@
 
 			import * as THREE from 'three/webgpu';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
@@ -63,9 +71,8 @@
 				mesh = new THREE.Mesh( geometry, material );
 				scene.add( mesh );
 
-				initGUI();
-
 				renderer = new THREE.WebGPURenderer( { antialias: true } );
+				renderer.inspector = new Inspector();
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( function () {
@@ -80,6 +87,8 @@
 
 				window.addEventListener( 'resize', onWindowResize );
 
+				initGUI();
+
 			}
 
 			function createGeometry() {
@@ -139,7 +148,8 @@
 					Spherify: 0,
 					Twist: 0,
 				};
-				const gui = new GUI( { title: 'Morph Targets' } );
+
+				const gui = renderer.inspector.createParameters( 'Morph Targets' );
 
 				gui.add( params, 'Spherify', 0, 1 ).step( 0.01 ).onChange( function ( value ) {
 

+ 3 - 13
examples/webgpu_morphtargets_face.html

@@ -33,8 +33,6 @@
 
 			import * as THREE from 'three/webgpu';
 
-			import Stats from 'three/addons/libs/stats.module.js';
-
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 			import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
@@ -42,7 +40,7 @@
 			import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js';
 			import { MeshoptDecoder } from 'three/addons/libs/meshopt_decoder.module.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			init();
 
@@ -52,7 +50,6 @@
 
 				const clock = new THREE.Clock();
 
-
 				const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 20 );
 				camera.position.set( - 1.8, 0.8, 3 );
 
@@ -63,6 +60,7 @@
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
 				renderer.toneMapping = THREE.ACESFilmicToneMapping;
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				await renderer.init();
@@ -95,8 +93,7 @@
 						const head = mesh.getObjectByName( 'mesh_2' );
 						const influences = head.morphTargetInfluences;
 
-						const gui = new GUI();
-						gui.close();
+						const gui = renderer.inspector.createParameters( 'Morph Targets' );
 
 						for ( const [ key, value ] of Object.entries( head.morphTargetDictionary ) ) {
 
@@ -119,11 +116,6 @@
 				controls.maxPolarAngle = Math.PI / 1.8;
 				controls.target.set( 0, 0.15, - 0.2 );
 
-				const stats = new Stats();
-				document.body.appendChild( stats.dom );
-
-
-
 				function animate() {
 
 					const delta = clock.getDelta();
@@ -138,8 +130,6 @@
 
 					controls.update();
 
-					stats.update();
-
 				}
 
 				window.addEventListener( 'resize', () => {

+ 13 - 3
examples/webgpu_mrt.html

@@ -4,13 +4,20 @@
 		<title>three.js webgpu - mrt</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - mrt<br />
-			Final / Beauty / Normal / Emissive / Diffuse
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Multiple Render Targets (MRT)</span>
+			</div>
+
+			<small>
+				Final / Beauty / Normal / Emissive / Diffuse
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -29,6 +36,8 @@
 			import * as THREE from 'three/webgpu';
 			import { output, normalView, pass, step, diffuseColor, emissive, directionToColor, screenUV, mix, mrt, Fn } from 'three/tsl';
 
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			import { HDRLoader } from 'three/addons/loaders/HDRLoader.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
@@ -78,6 +87,7 @@
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( render );
 				renderer.toneMapping = THREE.ACESFilmicToneMapping;
+				renderer.inspector = new Inspector();
 				container.appendChild( renderer.domElement );
 
 				// post processing

+ 10 - 3
examples/webgpu_mrt_mask.html

@@ -4,13 +4,20 @@
 		<title>three.js webgpu - mrt mask</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - mrt mask
-			<br>The mask is applied followed by a gaussian blur only on some selected materials.
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>MRT Mask</span>
+			</div>
+
+			<small>
+				The mask is applied followed by a gaussian blur only on some selected materials.
+			</small>
 		</div>
 
 		<script type="importmap">

+ 10 - 2
examples/webgpu_multiple_rendertargets.html

@@ -4,12 +4,20 @@
 		<title>three.js webgpu - multiple render targets</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank">threejs</a> webgpu - multiple rendertargets
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Multiple Render Targets</span>
+			</div>
+
+			<small>
+				Using multiple render targets to output color and normals to separate buffers.
+			</small>
 		</div>
 
 		<script type="importmap">

+ 21 - 8
examples/webgpu_multiple_rendertargets_readback.html

@@ -2,14 +2,22 @@
 	<head>
 		<title>three.js webgpu - mrt readback</title>
 		<meta charset="utf-8">
-        <link rel="shortcut icon" href="#">
+		<link rel="shortcut icon" href="#">
 		<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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - mrt readback
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Multiple Render Targets</span>
+			</div>
+
+			<small>
+				Using multiple render targets to output color and normals to separate buffers.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -30,19 +38,15 @@
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let camera, scene, renderer, torus;
 			let quadMesh, sceneMRT, renderTarget, readbackTarget, material, readbackMaterial, pixelBuffer, pixelBufferTexture;
 
-			const gui = new GUI();
-
 			const options = {
 				selection: 'mrt',
 			};
 
-			gui.add( options, 'selection', [ 'mrt', 'diffuse', 'normal' ] );
-
 			init();
 
 			function init() {
@@ -53,6 +57,15 @@
 				renderer.setAnimationLoop( render );
 				document.body.appendChild( renderer.domElement );
 
+				//
+
+				renderer.inspector = new Inspector();
+
+				//
+
+				const gui = renderer.inspector.createParameters( 'Settings' );
+				gui.add( options, 'selection', [ 'mrt', 'diffuse', 'normal' ] );
+
 				// Create a multi render target with Float buffers
 
 				renderTarget = new THREE.RenderTarget(

+ 14 - 6
examples/webgpu_multisampled_renderbuffers.html

@@ -3,12 +3,20 @@
 		<title>three.js webgpu - multisampled renderbuffers</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - multisampled renderbuffers
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Multisampled Renderbuffers</span>
+			</div>
+
+			<small>
+				Using multisampled renderbuffers for anti-aliasing.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -27,7 +35,7 @@
 			import * as THREE from 'three/webgpu';
 			import { texture } from 'three/tsl';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let camera, scene, renderer;
 			const mouse = new THREE.Vector2();
@@ -63,13 +71,12 @@
 
 			} );
 
-
-			initGUI();
 			init();
+			initGUI();
 
 			function initGUI() {
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Settings' );
 				gui.add( params, 'samples', 0, 4 ).step( 1 );
 				gui.add( params, 'animated' );
 
@@ -108,6 +115,7 @@
 				//
 
 				renderer = new THREE.WebGPURenderer( { antialias: true } );
+				renderer.inspector = new Inspector();
 				renderer.setPixelRatio( dpr );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );

+ 10 - 3
examples/webgpu_occlusion.html

@@ -4,13 +4,20 @@
 		<title>three.js webgpu - occlusion</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - occlusion<br />
-			The plane is green when the sphere is completely occluded.
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Occlusion</span>
+			</div>
+
+			<small>
+				The plane is green when the sphere is completely occluded.
+			</small>
 		</div>
 
 		<script type="importmap">

+ 10 - 1
examples/webgpu_ocean.html

@@ -9,8 +9,17 @@
 	<body>
 
 		<div id="container"></div>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - webgpu ocean
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Occlusion</span>
+			</div>
+
+			<small>
+				The plane is green when the sphere is completely occluded.
+			</small>
 		</div>
 
 		<script type="importmap">

+ 9 - 3
examples/webgpu_parallax_uv.html

@@ -4,14 +4,20 @@
 		<title>three.js webgpu - parallax uv</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - parallax uv<br />
-			Textures by <a href="https://ambientcg.com/view?id=Ice002" target="_blank" rel="noopener">ambientCG</a><br />
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
 
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Parallax UV</span>
+			</div>
+
+			<small>
+				Textures by <a href="https://ambientcg.com/view?id=Ice002" target="_blank" rel="noopener">ambientCG</a>.
+			</small>
 		</div>
 
 		<script type="importmap">

+ 14 - 6
examples/webgpu_particles.html

@@ -1,14 +1,20 @@
 <html lang="en">
 	<head>
-		<title>three.js webgpu - Particles</title>
+		<title>three.js webgpu - particles</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - particles
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Particles</span>
+			</div>
+
+			<small>Fire and smoke particles.</small>
 		</div>
 
 		<script type="importmap">
@@ -27,11 +33,12 @@
 			import * as THREE from 'three/webgpu';
 			import { range, texture, mix, uv, color, rotateUV, positionLocal, time, uniform } from 'three/tsl';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
-			import WebGPU from 'three/addons/capabilities/WebGPU.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
+			import WebGPU from 'three/addons/capabilities/WebGPU.js';
+
 			let camera, scene, renderer;
 			let controls;
 
@@ -144,6 +151,7 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( render );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				//
@@ -159,7 +167,7 @@
 
 				// gui
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Settings' );
 
 				gui.add( speed, 'value', 0, 1, 0.01 ).name( 'speed' );
 

+ 22 - 28
examples/webgpu_performance.html

@@ -1,18 +1,26 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webgpu - GLTFloader</title>
+		<title>three.js webgpu - performance</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 
 	<body>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - WebGPU Performance<br />
-			Dungeon - Low Poly Game Level Challenge by
-			<a href="https://sketchfab.com/warkarma" target="_blank" rel="noopener">Warkarma</a><br />
-			<a href="https://hdrihaven.com/hdri/?h=royal_esplanade" target="_blank" rel="noopener">Royal Esplanade</a> from <a href="https://hdrihaven.com/" target="_blank" rel="noopener">HDRI Haven</a>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Performance</span>
+			</div>
+
+			<small>
+				Dungeon - Low Poly Game Level Challenge by
+				<a href="https://sketchfab.com/warkarma" target="_blank" rel="noopener">Warkarma</a><br />
+				<a href="https://hdrihaven.com/hdri/?h=royal_esplanade" target="_blank" rel="noopener">Royal Esplanade</a> from <a href="https://hdrihaven.com/" target="_blank" rel="noopener">HDRI Haven</a>.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -20,8 +28,8 @@
 				"imports": {
 					"three": "../build/three.webgpu.js",
 					"three/webgpu": "../build/three.webgpu.js",
-					"three/addons/": "./jsm/",
-					"stats-gl": "https://cdn.jsdelivr.net/npm/stats-gl@3.6.0/dist/main.js"
+					"three/tsl": "../build/three.tsl.js",
+					"three/addons/": "./jsm/"
 
 				}
 			}
@@ -31,9 +39,7 @@
 
 			import * as THREE from 'three/webgpu';
 
-			import Stats from 'stats-gl';
-
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
@@ -41,7 +47,7 @@
 
 			import { HDRLoader } from 'three/addons/loaders/HDRLoader.js';
 
-			let camera, scene, renderer, stats;
+			let camera, scene, renderer;
 			let model;
 
 			const options = { static: true };
@@ -78,21 +84,12 @@
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.toneMapping = THREE.ACESFilmicToneMapping;
 				renderer.toneMappingExposure = 1;
-
+				renderer.inspector = new Inspector();
 				renderer.setAnimationLoop( render );
 				container.appendChild( renderer.domElement );
 
 				//
 
-				stats = new Stats( {
-					precision: 3,
-					horizontal: false,
-					trackGPU: true,
-				} );
-				stats.init( renderer );
-
-				document.body.appendChild( stats.dom );
-
 				new HDRLoader()
 					.setPath( 'textures/equirectangular/' )
 					.load( 'royal_esplanade_1k.hdr', function ( texture ) {
@@ -135,7 +132,7 @@
 
 				// gui
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Settings' );
 				gui.add( options, 'static' ).onChange( () => {
 
 					setStatic( model, options.static );
@@ -157,12 +154,9 @@
 
 			//
 
-			async function render() {
-
-				await renderer.renderAsync( scene, camera );
-				renderer.resolveTimestampsAsync( THREE.TimestampQuery.RENDER );
+			function render() {
 
-				stats.update();
+				renderer.render( scene, camera );
 
 			}
 

+ 6 - 8
examples/webgpu_pmrem_cubemap.html

@@ -4,7 +4,7 @@
 		<title>three.js webgpu - pmrem cubemap</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
@@ -28,7 +28,7 @@
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let camera, scene, renderer;
 
@@ -49,9 +49,11 @@
 				renderer = new THREE.WebGPURenderer( { antialias: true, forceWebGL } );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setAnimationLoop( render );
 				renderer.toneMapping = THREE.ACESFilmicToneMapping;
+				renderer.inspector = new Inspector();
 
-				await renderer.init();
+				//await renderer.init();
 
 				container.appendChild( renderer.domElement );
 
@@ -76,11 +78,9 @@
 
 						// gui
 
-						const gui = new GUI();
+						const gui = renderer.inspector.createParameters( 'Settings' );
 						gui.add( pmremRoughness, 'value', 0, 1, 0.001 ).name( 'roughness' ).onChange( () => render() );
 
-						render();
-
 					} );
 
 				window.addEventListener( 'resize', onWindowResize );
@@ -94,8 +94,6 @@
 
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
-				render();
-
 			}
 
 			//

+ 6 - 8
examples/webgpu_pmrem_equirectangular.html

@@ -4,7 +4,7 @@
 		<title>three.js webgpu - pmrem equirectangular</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
@@ -28,7 +28,7 @@
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let camera, scene, renderer;
 
@@ -49,9 +49,11 @@
 				renderer = new THREE.WebGPURenderer( { antialias: true, forceWebGL } );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setAnimationLoop( render );
 				renderer.toneMapping = THREE.ACESFilmicToneMapping;
+				renderer.inspector = new Inspector();
 
-				await renderer.init();
+				//await renderer.init();
 
 				container.appendChild( renderer.domElement );
 
@@ -78,11 +80,9 @@
 
 						// gui
 
-						const gui = new GUI();
+						const gui = renderer.inspector.createParameters( 'Settings' );
 						gui.add( pmremRoughness, 'value', 0, 1, 0.001 ).name( 'roughness' ).onChange( () => render() );
 
-						render();
-
 					} );
 
 				window.addEventListener( 'resize', onWindowResize );
@@ -96,8 +96,6 @@
 
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
-				render();
-
 			}
 
 			//

+ 17 - 7
examples/webgpu_pmrem_scene.html

@@ -4,10 +4,22 @@
 		<title>three.js webgpu - pmrem scene</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
+		<div id="info">
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>PMREM Scene</span>
+			</div>
+
+			<small>
+				PMREM generated from Scene.
+			</small>
+		</div>
+
 		<script type="importmap">
 			{
 				"imports": {
@@ -26,7 +38,7 @@
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let camera, scene, renderer;
 
@@ -47,6 +59,8 @@
 				renderer = new THREE.WebGPURenderer( { antialias: true, forceWebGL } );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setAnimationLoop( render );
+				renderer.inspector = new Inspector();
 				container.appendChild( renderer.domElement );
 
 				await renderer.init();
@@ -102,11 +116,9 @@
 
 				// gui
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Settings' );
 				gui.add( pmremRoughness, 'value', 0, 1, 0.001 ).name( 'roughness' ).onChange( () => render() );
 
-				render();
-
 				window.addEventListener( 'resize', onWindowResize );
 
 			}
@@ -118,8 +130,6 @@
 
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
-				render();
-
 			}
 
 			//

+ 14 - 2
examples/webgpu_portal.html

@@ -4,12 +4,20 @@
 		<title>three.js webgpu - portal</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - portal
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Portal</span>
+			</div>
+
+			<small>
+				The portal displays a different scene when viewed through it.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -32,6 +40,8 @@
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			let camera, sceneMain, scenePortal, renderer;
 			let clock;
 
@@ -49,6 +59,7 @@
 
 				scenePortal = new THREE.Scene();
 				scenePortal.backgroundNode = mx_worley_noise_float( normalWorld.mul( 20 ).add( vec2( 0, time.oneMinus() ) ) ).mul( color( 0x0066ff ) );
+				scenePortal.name = 'Portal Scene';
 
 				//
 
@@ -146,6 +157,7 @@
 				renderer.setAnimationLoop( animate );
 				renderer.toneMapping = THREE.LinearToneMapping;
 				renderer.toneMappingExposure = 0.15;
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				//

+ 14 - 5
examples/webgpu_procedural_texture.html

@@ -3,12 +3,20 @@
 		<title>three.js webgpu - procedural texture</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - procedural texture
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Procedural Texture</span>
+			</div>
+
+			<small>
+				GPU procedural texture generation.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -28,7 +36,7 @@
 			import { checker, uv, uniform, convertToTexture } from 'three/tsl';
 			import { gaussianBlur } from 'three/addons/tsl/display/GaussianBlurNode.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let camera, scene, renderer;
 
@@ -72,13 +80,14 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( render );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				window.addEventListener( 'resize', onWindowResize );
 
 				// gui
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Procedural Texture' );
 				gui.add( uvScale, 'value', 1, 10 ).name( 'uv scale ( before rtt )' );
 				gui.add( blurAmount, 'value', 0, 2 ).name( 'blur amount ( after rtt )' );
 				gui.add( proceduralToTexture, 'autoUpdate' ).name( 'auto update' );
@@ -102,7 +111,7 @@
 
 			function render() {
 
-				renderer.renderAsync( scene, camera );
+				renderer.render( scene, camera );
 
 			}
 

+ 14 - 11
examples/webgpu_reflection.html

@@ -4,14 +4,21 @@
 		<title>three.js webgpu - reflection</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - reflection<br/>
-			Based on <a href="https://oosmoxiecode.com/archive/js_webgl/recursive_tree_cubes/" target="_blank" rel="noopener">Recursive Tree Cubes</a>
-			by <a href="https://github.com/oosmoxiecode" target="_blank" rel="noopener">oosmoxiecode</a>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Reflection + Recursive Tree Cubes</span>
+			</div>
+
+			<small>
+				Based on <a href="https://oosmoxiecode.com/archive/js_webgl/recursive_tree_cubes/" target="_blank" rel="noopener">Recursive Tree Cubes</a>
+				by <a href="https://github.com/oosmoxiecode" target="_blank" rel="noopener">oosmoxiecode</a>
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -34,13 +41,13 @@
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
-			import Stats from 'three/addons/libs/stats.module.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			import TWEEN from 'three/addons/libs/tween.module.js';
 
 			let camera, scene, renderer;
 			let postProcessing;
 			let controls;
-			let stats;
 
 			// below uniforms will be animated via TWEEN.js
 
@@ -122,11 +129,9 @@
 				renderer.shadowMap.enabled = true;
 				renderer.shadowMap.type = THREE.PCFSoftShadowMap;
 				renderer.toneMapping = THREE.ACESFilmicToneMapping;
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
-				stats = new Stats();
-				document.body.appendChild( stats.dom );
-
 				// controls
 
 				controls = new OrbitControls( camera, renderer.domElement );
@@ -185,8 +190,6 @@
 
 			function animate() {
 
-				stats.update();
-
 				controls.update();
 
 				TWEEN.update();

+ 13 - 12
examples/webgpu_reflection_blurred.html

@@ -4,12 +4,20 @@
 		<title>three.js webgpu - blurred reflection</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - blurred reflection
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Blurred Reflection</span>
+			</div>
+
+			<small>
+				Reflection with a blurred effect using a hash blur algorithm.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -34,14 +42,11 @@
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
-
-			import Stats from 'three/addons/libs/stats.module.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let camera, scene, renderer;
 			let model, mixer, clock;
 			let controls;
-			let stats;
 			let gui;
 
 			init();
@@ -189,16 +194,14 @@
 				renderer.setAnimationLoop( animate );
 				renderer.toneMapping = THREE.NeutralToneMapping;
 				renderer.toneMappingExposure = 1.3;
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
-				gui = new GUI();
+				gui = renderer.inspector.createParameters( 'Settings' );
 				gui.add( roughness, 'value', 0, 1 ).name( 'roughness' );
 				gui.add( radius, 'value', 0, 1 ).name( 'radius' );
 				gui.add( reflection.reflector, 'resolutionScale', .25, 1 ).name( 'resolution scale' );
 
-				stats = new Stats();
-				document.body.appendChild( stats.dom );
-
 				controls = new OrbitControls( camera, renderer.domElement );
 				controls.minDistance = 1;
 				controls.maxDistance = 10;
@@ -225,8 +228,6 @@
 
 			function animate() {
 
-				stats.update();
-
 				controls.update();
 
 				const delta = clock.getDelta();

+ 14 - 11
examples/webgpu_reflection_roughness.html

@@ -4,12 +4,20 @@
 		<title>three.js webgpu - roughness reflection</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - roughness reflection
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Roughness Reflection</span>
+			</div>
+
+			<small>
+				Reflection with roughness.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -31,11 +39,10 @@
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { UltraHDRLoader } from 'three/addons/loaders/UltraHDRLoader.js';
 
-			import Stats from 'three/addons/libs/stats.module.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let camera, scene, renderer;
 			let controls;
-			let stats;
 
 			init();
 
@@ -87,7 +94,7 @@
 
 				// reflection
 
-				const reflection = reflector( { resolution: .5, bounces: false, generateMipmaps: true } ); // 0.5 is half of the rendering view
+				const reflection = reflector( { resolutionScale: .5, bounces: false, generateMipmaps: true } ); // 0.5 is half of the rendering view
 				reflection.target.rotateX( - Math.PI / 2 );
 				scene.add( reflection.target );
 
@@ -122,11 +129,9 @@
 				renderer.setAnimationLoop( animate );
 				renderer.toneMapping = THREE.NeutralToneMapping;
 				renderer.toneMappingExposure = 1.5;
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
-				stats = new Stats();
-				document.body.appendChild( stats.dom );
-
 				controls = new OrbitControls( camera, renderer.domElement );
 				controls.minDistance = 1;
 				controls.maxDistance = 10;
@@ -151,9 +156,7 @@
 
 			}
 
-			function animate( time ) {
-
-				stats.update();
+			function animate() {
 
 				controls.update();
 

+ 14 - 3
examples/webgpu_refraction.html

@@ -4,12 +4,20 @@
 		<title>three.js webgpu - refraction</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - refraction
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Refraction</span>
+			</div>
+
+			<small>
+				Refraction using backdrop.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -30,6 +38,8 @@
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			let camera, scene, renderer;
 
 			let cameraControls;
@@ -68,7 +78,7 @@
 				const verticalUVOffset = texture( floorNormal, uv().mul( 5 ) ).xy.mul( 2 ).sub( 1 ).mul( verticalNormalScale );
 
 				const refractorUV = screenUV.add( verticalUVOffset );
-				const verticalRefractor = viewportSharedTexture( viewportSafeUV( refractorUV ) );
+				const verticalRefractor = viewportSharedTexture( viewportSafeUV( refractorUV ) ).toInspector( 'Viewport Texture' );
 
 				const planeGeo = new THREE.PlaneGeometry( 100.1, 100.1 );
 
@@ -131,6 +141,7 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				// controls

+ 14 - 9
examples/webgpu_rendertarget_2d-array_3d.html

@@ -4,7 +4,7 @@
 		<title>three.js webgpu - RenderTargetArray and RenderTarget3D</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 		<style>
 			.viewport-label {
 				position: absolute;
@@ -21,9 +21,19 @@
 	</head>
 
 	<body>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - WebGPU - RenderTargetArray and RenderTarget3D<br />
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>RenderTarget Array/3D</span>
+			</div>
+
+			<small>
+				RenderTargetArray and RenderTarget3D examples.
+			</small>
 		</div>
+
 		<div class="viewport-label" style="bottom: 2%; left: 2%;">DataArrayTexture</div>
 		<div class="viewport-label" style="bottom: 2%; left: 52%;">Data3DTexture</div>
 		<div class="viewport-label" style="bottom: 52%; left: 52%;">RenderTarget3D</div>
@@ -44,12 +54,12 @@
 
 			import * as THREE from 'three/webgpu';
 			import { vec2, uniform, screenUV, color, texture, diffuseColor, attribute, vec3, vec4 } from 'three/tsl';
-			import Stats from 'three/addons/libs/stats.module.js';
+
 			import { TextureHelper } from 'three/addons/helpers/TextureHelperGPU.js';
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { unzipSync } from 'three/addons/libs/fflate.module.js';
 
-			let renderer, stats;
+			let renderer;
 			let views = [];
 
 			class View {
@@ -282,9 +292,6 @@
 
 					} );
 
-				stats = new Stats();
-				container.appendChild( stats.dom );
-
 				window.addEventListener( 'resize', onWindowResize );
 
 			}
@@ -329,8 +336,6 @@
 
 				} );
 
-				stats.update();
-
 			}
 
 			init();

+ 10 - 3
examples/webgpu_shadertoy.html

@@ -3,13 +3,20 @@
 		<title>three.js webgpu - shadertoy</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - shadertoy
-			<br />Shader created by <a href="https://www.shadertoy.com/view/Mt2SzR" target="_blank" rel="noopener">jackdavenport</a> and <a href="https://www.shadertoy.com/view/3tcBzH" target="_blank" rel="noopener">trinketMage</a>.
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Shadertoy</span>
+			</div>
+
+			<small>
+				Shader created by <a href="https://www.shadertoy.com/view/Mt2SzR" target="_blank" rel="noopener">jackdavenport</a> and <a href="https://www.shadertoy.com/view/3tcBzH" target="_blank" rel="noopener">trinketMage</a>.
+			</small>
 		</div>
 
 		<script type="importmap">

+ 14 - 2
examples/webgpu_shadowmap.html

@@ -4,11 +4,20 @@
 		<title>three.js webgpu - shadow map</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
+
 		<div id="info">
-		<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - webgpu shadow map
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Shadow Map</span>
+			</div>
+
+			<small>
+				Shadow map example.
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -29,6 +38,8 @@
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			let camera, scene, renderer, clock;
 			let dirLight, spotLight;
 			let torusKnot, dirGroup;
@@ -176,6 +187,7 @@
 				renderer.setAnimationLoop( animate );
 				renderer.shadowMap.enabled = true;
 				renderer.toneMapping = THREE.ACESFilmicToneMapping;
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				// Mouse control

+ 18 - 22
examples/webgpu_shadowmap_array.html

@@ -4,11 +4,20 @@
 		<title>three.js webgpu - shadow map array tile demo</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
-		<div id="info">
-		<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - tile shadow using shadow map array demonstration
+
+		<div id="info" class="invert">
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Shadow Map Array</span>
+			</div>
+
+			<small>
+				Tile shadow using shadow map array demonstration
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -17,8 +26,7 @@
 					"three": "../build/three.webgpu.js",
 					"three/webgpu": "../build/three.webgpu.js",
 					"three/tsl": "../build/three.tsl.js",
-					"three/addons/": "./jsm/",
-					"stats-gl": "https://cdn.jsdelivr.net/npm/stats-gl@3.6.0/dist/main.js"
+					"three/addons/": "./jsm/"
 				}
 			}
 		</script>
@@ -33,10 +41,10 @@
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
-			import Stats from 'stats-gl';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let camera, scene, renderer, clock;
-			let dirLight, stats;
+			let dirLight;
 			let torusKnot, dirGroup;
 			let tsmHelper;
 
@@ -50,6 +58,8 @@
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
 
+				renderer.inspector = new Inspector();
+
 				renderer.shadowMap.enabled = true;
 				renderer.shadowMap.type = THREE.BasicShadowMap;
 				// renderer.shadowMap.type = THREE.PCFSoftShadowMap;
@@ -59,6 +69,7 @@
 				document.body.appendChild( renderer.domElement );
 			
 				await renderer.init();
+
 				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
 				camera.position.set( 45, 60, 100 );
 
@@ -125,8 +136,6 @@
 				ground.receiveShadow = true;
 				scene.add( ground );
 
-
-			
 				// Spread various objects across the scene
 				createScenery();
 
@@ -138,16 +147,6 @@
 				controls.maxPolarAngle = Math.PI / 2 - 0.1; // Prevent camera from going below ground
 				controls.update();
 
-
-				stats = new Stats( {
-					precision: 3,
-					horizontal: false,
-					trackGPU: true
-				} );
-				stats.init( renderer );
-				document.body.appendChild( stats.dom );
-
-
 				clock = new THREE.Clock();
 
 				window.addEventListener( 'resize', resize );
@@ -408,9 +407,6 @@
 
 				tsmHelper.update();
 
-				await renderer.resolveTimestampsAsync();
-				stats.update();
-
 			}
 
 		</script>

+ 20 - 6
examples/webgpu_shadowmap_csm.html

@@ -4,14 +4,22 @@
 		<title>three.js webgpu - cascaded shadow maps</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">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="container"></div>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - cascaded shadow maps<br>
-			by <a href="https://github.com/strandedkitty/" target="_blank" rel="noopener">StrandedKitty</a> (<a href="https://github.com/strandedkitty/three-csm" target="_blank" rel="noopener">original repository</a>)
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Cascaded Shadow Maps</span>
+			</div>
+
+			<small>
+				By <a href="https://github.com/strandedkitty/" target="_blank" rel="noopener">StrandedKitty</a> (<a href="https://github.com/strandedkitty/three-csm" target="_blank" rel="noopener">original repository</a>).
+			</small>
 		</div>
 
 		<script type="importmap">
@@ -30,7 +38,9 @@
 			import * as THREE from 'three/webgpu';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			import { CSMShadowNode } from 'three/addons/csm/CSMShadowNode.js';
 			import { CSMHelper } from 'three/addons/csm/CSMHelper.js';
 
@@ -84,10 +94,14 @@
 				renderer = new THREE.WebGPURenderer( { antialias: true } );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
-				document.body.appendChild( renderer.domElement );
+
 				renderer.shadowMap.enabled = params.shadows;
 				renderer.shadowMap.type = THREE.PCFSoftShadowMap;
 
+				renderer.inspector = new Inspector();
+
+				document.body.appendChild( renderer.domElement );
+
 				controls = new OrbitControls( camera, renderer.domElement );
 				controls.maxPolarAngle = Math.PI / 2;
 				camera.position.set( 60, 60, 0 );
@@ -158,7 +172,7 @@
 
 				}
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Settings' );
 
 				gui.add( params, 'orthographic' ).onChange( function ( value ) {
 

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini

粤ICP备19079148号