Browse Source

Examples: Improve water demo. (#31291)

Michael Herzog 6 months ago
parent
commit
eabdf24f86

+ 1 - 3
examples/files.json

@@ -210,9 +210,7 @@
 		"webgl_tonemapping",
 		"webgl_video_kinect",
 		"webgl_video_panorama_equirectangular",
-		"webgl_watch",
-		"webgl_water",
-		"webgl_water_flowmap"
+		"webgl_watch"
 	],
 	"webgl / postprocessing": [
 		"webgl_postprocessing",

BIN
examples/models/gltf/pool.glb


BIN
examples/screenshots/webgl_water.jpg


BIN
examples/screenshots/webgl_water_flowmap.jpg


BIN
examples/screenshots/webgpu_water.jpg


+ 0 - 202
examples/webgl_water.html

@@ -1,202 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<title>three.js - 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">
-	</head>
-	<body>
-
-		<div id="container"></div>
-		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener noreferrer">three.js</a> - water
-		</div>
-
-		<script type="importmap">
-			{
-				"imports": {
-					"three": "../build/three.module.js",
-					"three/addons/": "./jsm/"
-				}
-			}
-		</script>
-
-		<script type="module">
-
-			import * as THREE from 'three';
-
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
-			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-			import { Water } from 'three/addons/objects/Water2.js';
-
-			let scene, camera, clock, renderer, water;
-
-			let torusKnot;
-
-			const params = {
-				color: '#ffffff',
-				scale: 4,
-				flowX: 1,
-				flowY: 1
-			};
-
-			init();
-
-			function init() {
-
-				// scene
-
-				scene = new THREE.Scene();
-
-				// camera
-
-				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 200 );
-				camera.position.set( - 15, 7, 15 );
-				camera.lookAt( scene.position );
-
-				// clock
-
-				clock = new THREE.Clock();
-
-				// mesh
-
-				const torusKnotGeometry = new THREE.TorusKnotGeometry( 3, 1, 256, 32 );
-				const torusKnotMaterial = new THREE.MeshNormalMaterial();
-
-				torusKnot = new THREE.Mesh( torusKnotGeometry, torusKnotMaterial );
-				torusKnot.position.y = 4;
-				torusKnot.scale.set( 0.5, 0.5, 0.5 );
-				scene.add( torusKnot );
-
-				// ground
-
-				const groundGeometry = new THREE.PlaneGeometry( 20, 20 );
-				const groundMaterial = new THREE.MeshStandardMaterial( { roughness: 0.8, metalness: 0.4 } );
-				const ground = new THREE.Mesh( groundGeometry, groundMaterial );
-				ground.rotation.x = Math.PI * - 0.5;
-				scene.add( ground );
-
-				const textureLoader = new THREE.TextureLoader();
-				textureLoader.load( 'textures/hardwood2_diffuse.jpg', function ( map ) {
-
-					map.wrapS = THREE.RepeatWrapping;
-					map.wrapT = THREE.RepeatWrapping;
-					map.anisotropy = 16;
-					map.repeat.set( 4, 4 );
-					map.colorSpace = THREE.SRGBColorSpace;
-					groundMaterial.map = map;
-					groundMaterial.needsUpdate = true;
-
-				} );
-
-				// water
-
-				const waterGeometry = new THREE.PlaneGeometry( 20, 20 );
-
-				water = new Water( waterGeometry, {
-					color: params.color,
-					scale: params.scale,
-					flowDirection: new THREE.Vector2( params.flowX, params.flowY ),
-					textureWidth: 1024,
-					textureHeight: 1024
-				} );
-
-				water.position.y = 1;
-				water.rotation.x = Math.PI * - 0.5;
-				scene.add( water );
-
-				// skybox
-
-				const cubeTextureLoader = new THREE.CubeTextureLoader();
-				cubeTextureLoader.setPath( 'textures/cube/Park2/' );
-
-				const cubeTexture = cubeTextureLoader.load( [
-					'posx.jpg', 'negx.jpg',
-					'posy.jpg', 'negy.jpg',
-					'posz.jpg', 'negz.jpg'
-				] );
-
-				scene.background = cubeTexture;
-
-				// light
-
-				const ambientLight = new THREE.AmbientLight( 0xe7e7e7, 1.2 );
-				scene.add( ambientLight );
-
-				const directionalLight = new THREE.DirectionalLight( 0xffffff, 2 );
-				directionalLight.position.set( - 1, 1, 1 );
-				scene.add( directionalLight );
-
-				// renderer
-
-				renderer = new THREE.WebGLRenderer( { antialias: true } );
-				renderer.setSize( window.innerWidth, window.innerHeight );
-				renderer.setPixelRatio( window.devicePixelRatio );
-				renderer.setAnimationLoop( animate );
-				document.body.appendChild( renderer.domElement );
-
-				// gui
-
-				const gui = new GUI();
-
-				gui.addColor( params, 'color' ).onChange( function ( value ) {
-
-					water.material.uniforms[ 'color' ].value.set( value );
-
-				} );
-				gui.add( params, 'scale', 1, 10 ).onChange( function ( value ) {
-
-					water.material.uniforms[ 'config' ].value.w = value;
-
-				} );
-				gui.add( params, 'flowX', - 1, 1 ).step( 0.01 ).onChange( function ( value ) {
-
-					water.material.uniforms[ 'flowDirection' ].value.x = value;
-					water.material.uniforms[ 'flowDirection' ].value.normalize();
-
-				} );
-				gui.add( params, 'flowY', - 1, 1 ).step( 0.01 ).onChange( function ( value ) {
-
-					water.material.uniforms[ 'flowDirection' ].value.y = value;
-					water.material.uniforms[ 'flowDirection' ].value.normalize();
-
-				} );
-
-				gui.open();
-
-				//
-
-				const controls = new OrbitControls( camera, renderer.domElement );
-				controls.minDistance = 5;
-				controls.maxDistance = 50;
-
-				//
-
-				window.addEventListener( 'resize', onWindowResize );
-
-			}
-
-			function onWindowResize() {
-
-				camera.aspect = window.innerWidth / window.innerHeight;
-				camera.updateProjectionMatrix();
-				renderer.setSize( window.innerWidth, window.innerHeight );
-
-			}
-
-			function animate() {
-
-				const delta = clock.getDelta();
-
-				torusKnot.rotation.x += delta;
-				torusKnot.rotation.y += delta * 0.5;
-
-				renderer.render( scene, camera );
-
-			}
-
-		</script>
-
-</body>
-</html>

+ 0 - 139
examples/webgl_water_flowmap.html

@@ -1,139 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<title>three.js - water flow 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">
-	</head>
-	<body>
-
-		<div id="container"></div>
-		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener noreferrer">three.js</a> - water flow map
-		</div>
-
-		<script type="importmap">
-			{
-				"imports": {
-					"three": "../build/three.module.js",
-					"three/addons/": "./jsm/"
-				}
-			}
-		</script>
-
-		<script type="module">
-
-			import * as THREE from 'three';
-
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
-			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-			import { Water } from 'three/addons/objects/Water2.js';
-
-			let scene, camera, renderer, water;
-
-			init();
-
-			function init() {
-
-				// scene
-
-				scene = new THREE.Scene();
-
-				// camera
-
-				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 200 );
-				camera.position.set( 0, 25, 0 );
-				camera.lookAt( scene.position );
-
-				// ground
-
-				const groundGeometry = new THREE.PlaneGeometry( 20, 20, 10, 10 );
-				const groundMaterial = new THREE.MeshBasicMaterial( { color: 0xe7e7e7 } );
-				const ground = new THREE.Mesh( groundGeometry, groundMaterial );
-				ground.rotation.x = Math.PI * - 0.5;
-				scene.add( ground );
-
-				const textureLoader = new THREE.TextureLoader();
-				textureLoader.load( 'textures/floors/FloorsCheckerboard_S_Diffuse.jpg', function ( map ) {
-
-					map.wrapS = THREE.RepeatWrapping;
-					map.wrapT = THREE.RepeatWrapping;
-					map.anisotropy = 16;
-					map.repeat.set( 4, 4 );
-					map.colorSpace = THREE.SRGBColorSpace;
-					groundMaterial.map = map;
-					groundMaterial.needsUpdate = true;
-
-				} );
-
-				// water
-
-				const waterGeometry = new THREE.PlaneGeometry( 20, 20 );
-				const flowMap = textureLoader.load( 'textures/water/Water_1_M_Flow.jpg' );
-
-				water = new Water( waterGeometry, {
-					scale: 2,
-					textureWidth: 1024,
-					textureHeight: 1024,
-					flowMap: flowMap
-				} );
-
-				water.position.y = 1;
-				water.rotation.x = Math.PI * - 0.5;
-				scene.add( water );
-
-				// flow map helper
-
-				const helperGeometry = new THREE.PlaneGeometry( 20, 20 );
-				const helperMaterial = new THREE.MeshBasicMaterial( { map: flowMap } );
-				const helper = new THREE.Mesh( helperGeometry, helperMaterial );
-				helper.position.y = 1.01;
-				helper.rotation.x = Math.PI * - 0.5;
-				helper.visible = false;
-				scene.add( helper );
-
-				// renderer
-
-				renderer = new THREE.WebGLRenderer( { antialias: true } );
-				renderer.setSize( window.innerWidth, window.innerHeight );
-				renderer.setPixelRatio( window.devicePixelRatio );
-				renderer.setAnimationLoop( animate );
-				document.body.appendChild( renderer.domElement );
-
-				//
-
-				const gui = new GUI();
-				gui.add( helper, 'visible' ).name( 'Show Flow Map' );
-				gui.open();
-
-				//
-
-				const controls = new OrbitControls( camera, renderer.domElement );
-				controls.minDistance = 5;
-				controls.maxDistance = 50;
-
-				//
-
-				window.addEventListener( 'resize', onWindowResize );
-
-			}
-
-			function onWindowResize() {
-
-				camera.aspect = window.innerWidth / window.innerHeight;
-				camera.updateProjectionMatrix();
-				renderer.setSize( window.innerWidth, window.innerHeight );
-
-			}
-
-			function animate() {
-
-				renderer.render( scene, camera );
-
-			}
-
-		</script>
-
-</body>
-</html>

+ 54 - 67
examples/webgpu_water.html

@@ -10,7 +10,9 @@
 
 		<div id="container"></div>
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener noreferrer">three.js</a> - water
+			<a href="https://threejs.org" target="_blank" rel="noopener noreferrer">three.js</a> - water<br />
+			<a href="https://skfb.ly/6WOOR" target="_blank" rel="noopener">The Night Pool</a> by 
+			<a href="https://sketchfab.com/syntheticplants" target="_blank" rel="noopener">syntheticplants</a> is licensed under <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank" rel="noopener">Creative Commons Attribution</a>.<br />
 		</div>
 
 		<script type="importmap">
@@ -28,81 +30,64 @@
 
 			import * as THREE from 'three';
 
+			import { pass, mrt, output, emissive, color, screenUV } from 'three/tsl';
+			import { bloom } from 'three/addons/tsl/display/BloomNode.js';
+
 			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { WaterMesh } from 'three/addons/objects/Water2Mesh.js';
+			import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
+			import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
 
-			let scene, camera, clock, renderer, water;
-
-			let torusKnot;
+			let scene, camera, renderer, water, postProcessing, controls;
 
 			const params = {
 				color: '#ffffff',
-				scale: 4,
-				flowX: 1,
-				flowY: 1
+				scale: 2,
+				flowX: 0.25,
+				flowY: 0.25
 			};
 
 			init();
 
-			function init() {
+			async function init() {
 
 				// scene
 
 				scene = new THREE.Scene();
+				scene.backgroundNode = screenUV.distance( .5 ).remap( 0, 0.5 ).mix( color( 0x666666 ), color( 0x111111 ) );
 
 				// camera
 
 				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 200 );
-				camera.position.set( - 15, 7, 15 );
+				camera.position.set( - 25, 10, - 25 );
 				camera.lookAt( scene.position );
 
-				// clock
-
-				clock = new THREE.Clock();
-
-				// mesh
-
-				const torusKnotGeometry = new THREE.TorusKnotGeometry( 3, 1, 256, 32 );
-				const torusKnotMaterial = new THREE.MeshNormalMaterial();
-
-				torusKnot = new THREE.Mesh( torusKnotGeometry, torusKnotMaterial );
-				torusKnot.position.y = 4;
-				torusKnot.scale.set( 0.5, 0.5, 0.5 );
-				scene.add( torusKnot );
+				// asset loading
 
-				// ground
-
-				const groundGeometry = new THREE.PlaneGeometry( 20, 20 );
-				const groundMaterial = new THREE.MeshStandardMaterial( { roughness: 0.8, metalness: 0.4 } );
-				const ground = new THREE.Mesh( groundGeometry, groundMaterial );
-				ground.rotation.x = Math.PI * - 0.5;
-				scene.add( ground );
+				const dracoLoader = new DRACOLoader();
+				dracoLoader.setDecoderPath( 'jsm/libs/draco/gltf/' );
 
+				const gltfLoader = new GLTFLoader();
+				gltfLoader.setDRACOLoader( dracoLoader );
+			
 				const textureLoader = new THREE.TextureLoader();
-				textureLoader.load( 'textures/hardwood2_diffuse.jpg', function ( map ) {
-
-					map.wrapS = THREE.RepeatWrapping;
-					map.wrapT = THREE.RepeatWrapping;
-					map.anisotropy = 16;
-					map.repeat.set( 4, 4 );
-					map.colorSpace = THREE.SRGBColorSpace;
-					groundMaterial.map = map;
-					groundMaterial.needsUpdate = true;
 
-				} );
+				const [ gltf, normalMap0, normalMap1 ] = await Promise.all( [
+					gltfLoader.loadAsync( 'models/gltf/pool.glb' ),
+					textureLoader.loadAsync( 'textures/water/Water_1_M_Normal.jpg' ),
+					textureLoader.loadAsync( 'textures/water/Water_2_M_Normal.jpg' )
+				] );
 
-				//
+				gltf.scene.scale.setScalar( 0.1 );
+				scene.add( gltf.scene );
 
-				const normalMap0 = textureLoader.load( 'textures/water/Water_1_M_Normal.jpg' );
-				const normalMap1 = textureLoader.load( 'textures/water/Water_2_M_Normal.jpg' );
+				// water
 
 				normalMap0.wrapS = normalMap0.wrapT = THREE.RepeatWrapping;
 				normalMap1.wrapS = normalMap1.wrapT = THREE.RepeatWrapping;
 
-				// water
-
-				const waterGeometry = new THREE.PlaneGeometry( 20, 20 );
+				const waterGeometry = new THREE.PlaneGeometry( 30, 40 );
 
 				water = new WaterMesh( waterGeometry, {
 					color: params.color,
@@ -112,29 +97,17 @@
 					normalMap1: normalMap1
 				} );
 
-				water.position.y = 1;
+				water.position.set( 0, 0.2, - 2 );
 				water.rotation.x = Math.PI * - 0.5;
+				water.renderOrder = Infinity;
 				scene.add( water );
 
-				// skybox
-
-				const cubeTextureLoader = new THREE.CubeTextureLoader();
-				cubeTextureLoader.setPath( 'textures/cube/Park2/' );
-
-				const cubeTexture = cubeTextureLoader.load( [
-					'posx.jpg', 'negx.jpg',
-					'posy.jpg', 'negy.jpg',
-					'posz.jpg', 'negz.jpg'
-				] );
-
-				scene.background = cubeTexture;
-
 				// light
 
-				const ambientLight = new THREE.AmbientLight( 0xe7e7e7, 1.2 );
+				const ambientLight = new THREE.AmbientLight( 0xccccccc, 0.4 );
 				scene.add( ambientLight );
 
-				const directionalLight = new THREE.DirectionalLight( 0xffffff, 2 );
+				const directionalLight = new THREE.DirectionalLight( 0xf435ab, 3 );
 				directionalLight.position.set( - 1, 1, 1 );
 				scene.add( directionalLight );
 
@@ -144,8 +117,24 @@
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setAnimationLoop( animate );
+				renderer.toneMapping = THREE.NeutralToneMapping;
 				document.body.appendChild( renderer.domElement );
 
+				postProcessing = new THREE.PostProcessing( renderer );
+			
+				const scenePass = pass( scene, camera );
+				scenePass.setMRT( mrt( {
+					output,
+					emissive
+				} ) );
+
+				const outputPass = scenePass.getTextureNode();
+				const emissivePass = scenePass.getTextureNode( 'emissive' );
+
+				const bloomPass = bloom( emissivePass );
+
+				postProcessing.outputNode = outputPass.add( bloomPass );
+
 				// gui
 
 				const gui = new GUI();
@@ -178,9 +167,10 @@
 
 				//
 
-				const controls = new OrbitControls( camera, renderer.domElement );
+				controls = new OrbitControls( camera, renderer.domElement );
 				controls.minDistance = 5;
 				controls.maxDistance = 50;
+				controls.enableDamping = true;
 
 				//
 
@@ -198,12 +188,9 @@
 
 			function animate() {
 
-				const delta = clock.getDelta();
-
-				torusKnot.rotation.x += delta;
-				torusKnot.rotation.y += delta * 0.5;
+				controls.update();
 
-				renderer.render( scene, camera );
+				postProcessing.render();
 
 			}
 

粤ICP备19079148号