Quellcode durchsuchen

Examples: Add coffee smoke (#28967)

* Examples > Add coffee smoke

* Examples > Update coffee smoke screenshot

* Examples: Add coffee smoke screenshot to test exceptions
Bruno Simon vor 1 Jahr
Ursprung
Commit
11a5e52b6d

+ 1 - 0
examples/files.json

@@ -401,6 +401,7 @@
 		"webgpu_textures_2d-array",
 		"webgpu_textures_anisotropy",
 		"webgpu_textures_partialupdate",
+		"webgpu_tsl_coffee_smoke",
 		"webgpu_tsl_editor",
 		"webgpu_tsl_galaxy",
 		"webgpu_tsl_transpiler",

BIN
examples/models/gltf/coffeeMug.glb


BIN
examples/screenshots/webgpu_tsl_coffee_smoke.jpg


BIN
examples/textures/noises/perlin/128x128.png


+ 177 - 0
examples/webgpu_tsl_coffee_smoke.html

@@ -0,0 +1,177 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgpu - coffee smoke</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<link type="text/css" rel="stylesheet" href="main.css">
+	</head>
+	<body>
+
+		<div id="info">
+			<a href="https://threejs.org" target="_blank" rel="noopener">three.js webgpu</a> - coffee smoke
+			<br>
+			Based on <a href="https://threejs-journey.com/lessons/coffee-smoke-shader" target="_blank" rel="noopener">Three.js Journey</a> lesson
+			<br>
+			Perlin noise texture from <a href="http://kitfox.com/projects/perlinNoiseMaker/" target="_blank" rel="noopener">Perlin Noise Maker</a>
+		</div>
+
+		<script type="importmap">
+			{
+				"imports": {
+					"three": "../build/three.webgpu.js",
+					"three/tsl": "../build/three.webgpu.js",
+					"three/addons/": "./jsm/"
+				}
+			}
+		</script>
+
+		<script type="module">
+
+			import * as THREE from 'three';
+			import { mix, mul, positionLocal, smoothstep, texture, timerLocal, tslFn, uv, vec2, vec3, vec4 } from 'three/tsl';
+
+			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
+			import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
+
+			let camera, scene, renderer, controls;
+
+			init();
+
+			function init() {
+
+				camera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 0.1, 100 );
+				camera.position.set( 8, 10, 12 );
+
+				scene = new THREE.Scene();
+
+				// Loaders
+
+				const gltfLoader = new GLTFLoader();
+				const textureLoader = new THREE.TextureLoader();
+
+				// baked model
+
+				gltfLoader.load(
+					'./models/gltf/coffeeMug.glb',
+					( gltf ) => {
+
+        				gltf.scene.getObjectByName( 'baked' ).material.map.anisotropy = 8;
+						scene.add( gltf.scene );
+
+					}
+				);
+
+				// geometry
+
+				const smokeGeometry = new THREE.PlaneGeometry( 1, 1, 16, 64 );
+				smokeGeometry.translate( 0, 0.5, 0 );
+				smokeGeometry.scale( 1.5, 6, 1.5 );
+
+				// texture
+
+				const noiseTexture = textureLoader.load( './textures/noises/perlin/128x128.png' );
+				noiseTexture.wrapS = THREE.RepeatWrapping;
+				noiseTexture.wrapT = THREE.RepeatWrapping;
+
+				// material
+
+				const smokeMaterial = new THREE.MeshBasicNodeMaterial( { transparent: true, side: THREE.DoubleSide, depthWrite: false } );
+				const time = timerLocal();
+
+				// position
+
+				smokeMaterial.positionNode = tslFn( () => {
+
+					// twist
+
+					const twistNoiseUv = vec2( 0.5, uv().y.mul( 0.2 ).sub( time.mul( 0.005 ) ).mod( 1 ) );
+					const twist = texture( noiseTexture, twistNoiseUv ).r.mul( 10 );
+					positionLocal.xz.assign( positionLocal.xz.rotateUV( twist, vec2( 0 ) ) );
+
+					// wind
+
+					const windOffset = vec2(
+						texture( noiseTexture, vec2( 0.25, time.mul( 0.01 ) ).mod( 1 ) ).r.sub( 0.5 ),
+						texture( noiseTexture, vec2( 0.75, time.mul( 0.01 ) ).mod( 1 ) ).r.sub( 0.5 ),
+					).mul( uv().y.pow( 2 ).mul( 10 ) );
+					positionLocal.addAssign( windOffset );
+
+					return positionLocal;
+
+				} )();
+
+				// color
+
+				smokeMaterial.colorNode = tslFn( () => {
+
+					// alpha
+
+					const alphaNoiseUv = uv().mul( vec2( 0.5, 0.3 ) ).add( vec2( 0, time.mul( 0.03 ).negate() ) );
+					const alpha = mul(
+
+						// pattern
+						texture( noiseTexture, alphaNoiseUv ).r.smoothstep( 0.4, 1 ),
+
+						// edges fade
+						smoothstep( 0, 0.1, uv().x ),
+						smoothstep( 1, 0.9, uv().x ),
+						smoothstep( 0, 0.1, uv().y ),
+						smoothstep( 1, 0.9, uv().y )
+
+					);
+
+					// color
+
+					const finalColor = mix( vec3( 0.6, 0.3, 0.2 ), vec3( 1, 1, 1 ), alpha.pow( 3 ) );
+
+					return vec4( finalColor, alpha );
+
+				} )();
+
+				// mesh
+
+				const smoke = new THREE.Mesh( smokeGeometry, smokeMaterial );
+				smoke.position.y = 1.83;
+				scene.add( smoke );
+
+				// renderer
+
+				renderer = new THREE.WebGPURenderer( { antialias: true } );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setAnimationLoop( animate );
+				document.body.appendChild( renderer.domElement );
+
+				// controls
+
+				controls = new OrbitControls( camera, renderer.domElement );
+				controls.enableDamping = true;
+				controls.minDistance = 0.1;
+				controls.maxDistance = 50;
+				controls.target.y = 3;
+
+				window.addEventListener( 'resize', onWindowResize );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			async function animate() {
+
+				controls.update();
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+	</body>
+</html>

+ 1 - 0
test/e2e/puppeteer.js

@@ -149,6 +149,7 @@ const exceptionList = [
 	'webgpu_texturegrad',
 	'webgpu_performance_renderbundle',
 	'webgpu_lights_rectarealight',
+	'webgpu_tsl_coffee_smoke',
 	'webgpu_tsl_vfx_flames',
 	'webgpu_tsl_galaxy',
 

粤ICP备19079148号