소스 검색

Examples: Add `webgpu_refraction`. (#28761)

* Node: Add `RefractorNode`.

* E2E: Add example to exception list.

* Examples: Simplify refraction demo.

* Move verticalRefractor to backdropNode

---------
Michael Herzog 1 년 전
부모
커밋
6e66343993
4개의 변경된 파일178개의 추가작업 그리고 0개의 파일을 삭제
  1. 1 0
      examples/files.json
  2. BIN
      examples/screenshots/webgpu_refraction.jpg
  3. 176 0
      examples/webgpu_refraction.html
  4. 1 0
      test/e2e/puppeteer.js

+ 1 - 0
examples/files.json

@@ -373,6 +373,7 @@
 		"webgpu_postprocessing_sobel",
 		"webgpu_postprocessing",
 		"webgpu_reflection",
+		"webgpu_refraction",
 		"webgpu_rtt",
 		"webgpu_sandbox",
 		"webgpu_shadertoy",

BIN
examples/screenshots/webgpu_refraction.jpg


+ 176 - 0
examples/webgpu_refraction.html

@@ -0,0 +1,176 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<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">
+	</head>
+	<body>
+
+		<div id="info">
+			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - refraction
+		</div>
+
+		<script type="importmap">
+			{
+				"imports": {
+					"three": "../build/three.module.js",
+					"three/addons/": "./jsm/",
+					"three/nodes": "./jsm/nodes/Nodes.js"
+				}
+			}
+		</script>
+
+		<script type="module">
+
+			import * as THREE from 'three';
+			import { MeshBasicNodeMaterial, viewportSharedTexture, texture, uv } from 'three/nodes';
+
+			import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
+
+			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
+
+			let camera, scene, renderer;
+
+			let cameraControls;
+
+			let smallSphere;
+
+			init();
+
+			function init() {
+
+				// scene
+				scene = new THREE.Scene();
+
+				// camera
+				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 500 );
+				camera.position.set( 0, 75, 160 );
+
+				//
+
+				const geometry = new THREE.IcosahedronGeometry( 5, 0 );
+				const material = new THREE.MeshPhongMaterial( { color: 0xffffff, emissive: 0x7b7b7b, flatShading: true } );
+				smallSphere = new THREE.Mesh( geometry, material );
+				scene.add( smallSphere );
+
+				// textures
+
+				const loader = new THREE.TextureLoader();
+
+				const floorNormal = loader.load( 'textures/floors/FloorsCheckerboard_S_Normal.jpg' );
+				floorNormal.wrapS = THREE.RepeatWrapping;
+				floorNormal.wrapT = THREE.RepeatWrapping;
+
+				// refractor
+
+				const verticalRefractor = viewportSharedTexture();
+
+				const verticalNormalScale = 0.1;
+				const verticalUVOffset = texture( floorNormal, uv().mul( 5 ) ).xy.mul( 2 ).sub( 1 ).mul( verticalNormalScale );
+				verticalRefractor.uvNode = verticalRefractor.uvNode.add( verticalUVOffset );
+
+				const planeGeo = new THREE.PlaneGeometry( 100.1, 100.1 );
+
+				const planeRefractor = new THREE.Mesh( planeGeo, new MeshBasicNodeMaterial( {
+					backdropNode: verticalRefractor
+				} ) );
+				planeRefractor.material.transparent = true;
+				planeRefractor.position.y = 50;
+				scene.add( planeRefractor );
+
+				// walls
+			
+				const planeTop = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0xffffff } ) );
+				planeTop.position.y = 100;
+				planeTop.rotateX( Math.PI / 2 );
+				scene.add( planeTop );
+
+				const planeBottom = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0xffffff } ) );
+				planeBottom.rotateX( - Math.PI / 2 );
+				scene.add( planeBottom );
+
+				const planeBack = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0x7f7fff } ) );
+				planeBack.position.z = - 50;
+				planeBack.position.y = 50;
+				scene.add( planeBack );
+
+				const planeRight = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0x00ff00 } ) );
+				planeRight.position.x = 50;
+				planeRight.position.y = 50;
+				planeRight.rotateY( - Math.PI / 2 );
+				scene.add( planeRight );
+
+				const planeLeft = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0xff0000 } ) );
+				planeLeft.position.x = - 50;
+				planeLeft.position.y = 50;
+				planeLeft.rotateY( Math.PI / 2 );
+				scene.add( planeLeft );
+
+				// lights
+
+				const mainLight = new THREE.PointLight( 0xe7e7e7, 2.5, 250, 0 );
+				mainLight.position.y = 60;
+				scene.add( mainLight );
+
+				const greenLight = new THREE.PointLight( 0x00ff00, 0.5, 1000, 0 );
+				greenLight.position.set( 550, 50, 0 );
+				scene.add( greenLight );
+
+				const redLight = new THREE.PointLight( 0xff0000, 0.5, 1000, 0 );
+				redLight.position.set( - 550, 50, 0 );
+				scene.add( redLight );
+
+				const blueLight = new THREE.PointLight( 0xbbbbfe, 0.5, 1000, 0 );
+				blueLight.position.set( 0, 50, 550 );
+				scene.add( blueLight );
+
+				// renderer
+
+				renderer = new WebGPURenderer( { antialias: true } );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.setAnimationLoop( animate );
+				document.body.appendChild( renderer.domElement );
+
+				// controls
+
+				cameraControls = new OrbitControls( camera, renderer.domElement );
+				cameraControls.target.set( 0, 40, 0 );
+				cameraControls.maxDistance = 400;
+				cameraControls.minDistance = 10;
+				cameraControls.update();
+
+				window.addEventListener( 'resize', onWindowResize );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function animate() {
+
+				const timer = Date.now() * 0.01;
+
+				smallSphere.position.set(
+					Math.cos( timer * 0.1 ) * 30,
+					Math.abs( Math.cos( timer * 0.2 ) ) * 20 + 5,
+					Math.sin( timer * 0.1 ) * 30
+				);
+				smallSphere.rotation.y = ( Math.PI / 2 ) - timer * 0.1;
+				smallSphere.rotation.z = timer * 0.8;
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+	</body>
+</html>

+ 1 - 0
test/e2e/puppeteer.js

@@ -135,6 +135,7 @@ const exceptionList = [
 	'webgpu_morphtargets_face',
 	'webgpu_occlusion',
 	'webgpu_particles',
+	'webgpu_refraction',
 	'webgpu_shadertoy',
 	'webgpu_shadowmap',
 	'webgpu_tsl_editor',