Skip to content

Commit e9518aa

Browse files
authored
Examples: Add webgpu_reflection_roughness (#31294)
* add `webgpu_reflection_dirty` * Update webgpu_reflection_dirty.html * rename `webgpu_reflection_dirty` -> `webgpu_reflection_roughness`
1 parent 7858b59 commit e9518aa

File tree

3 files changed

+169
-0
lines changed

3 files changed

+169
-0
lines changed

examples/files.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@
416416
"webgpu_procedural_texture",
417417
"webgpu_reflection",
418418
"webgpu_reflection_blurred",
419+
"webgpu_reflection_roughness",
419420
"webgpu_refraction",
420421
"webgpu_rendertarget_2d-array_3d",
421422
"webgpu_rtt",
81.4 KB
Loading
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>three.js webgpu - roughness reflection</title>
5+
<meta charset="utf-8">
6+
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
7+
<link type="text/css" rel="stylesheet" href="main.css">
8+
</head>
9+
<body>
10+
11+
<div id="info">
12+
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - dirty reflection
13+
</div>
14+
15+
<script type="importmap">
16+
{
17+
"imports": {
18+
"three": "../build/three.webgpu.js",
19+
"three/webgpu": "../build/three.webgpu.js",
20+
"three/tsl": "../build/three.tsl.js",
21+
"three/addons/": "./jsm/"
22+
}
23+
}
24+
</script>
25+
26+
<script type="module">
27+
28+
import * as THREE from 'three';
29+
import { Fn, vec2, vec4, texture, uv, textureBicubic, rangeFogFactor, reflector, time } from 'three/tsl';
30+
31+
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';
32+
33+
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
34+
35+
import Stats from 'three/addons/libs/stats.module.js';
36+
37+
let camera, scene, renderer;
38+
let controls;
39+
let stats;
40+
41+
init();
42+
43+
async function init() {
44+
45+
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.25, 30 );
46+
camera.position.set( - 4, 2, 4 );
47+
camera.lookAt( 0, .4, 0 );
48+
49+
scene = new THREE.Scene();
50+
51+
//
52+
53+
new RGBELoader()
54+
.setPath( 'textures/equirectangular/' )
55+
.load( 'moonless_golf_1k.hdr', function ( texture ) {
56+
57+
texture.mapping = THREE.EquirectangularReflectionMapping;
58+
59+
scene.background = texture;
60+
scene.environment = texture;
61+
62+
} );
63+
64+
// textures
65+
66+
const textureLoader = new THREE.TextureLoader();
67+
68+
const uvMap = textureLoader.load( 'textures/uv_grid_directx.jpg' );
69+
uvMap.colorSpace = THREE.SRGBColorSpace;
70+
71+
const perlinMap = textureLoader.load( './textures/noises/perlin/rgb-256x256.png' );
72+
perlinMap.wrapS = THREE.RepeatWrapping;
73+
perlinMap.wrapT = THREE.RepeatWrapping;
74+
perlinMap.colorSpace = THREE.SRGBColorSpace;
75+
76+
// uv map for debugging
77+
78+
const uvMaterial = new THREE.MeshStandardNodeMaterial( {
79+
map: uvMap,
80+
emissiveMap: uvMap,
81+
emissive: 0xffffff,
82+
side: THREE.DoubleSide
83+
} );
84+
85+
const uvMesh = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), uvMaterial );
86+
uvMesh.position.set( 0, 1, 0 );
87+
scene.add( uvMesh );
88+
89+
// reflection
90+
91+
const reflection = reflector( { resolution: .5, bounces: false, generateMipmaps: true } ); // 0.5 is half of the rendering view
92+
reflection.target.rotateX( - Math.PI / 2 );
93+
scene.add( reflection.target );
94+
95+
const animatedUV = uv().mul( 10 ).add( vec2( time.mul( .1 ), 0 ) );
96+
const roughness = texture( perlinMap, animatedUV ).r.mul( 2 ).saturate();
97+
98+
const floorMaterial = new THREE.MeshStandardNodeMaterial();
99+
floorMaterial.transparent = true;
100+
floorMaterial.metalness = 1;
101+
floorMaterial.roughnessNode = roughness.mul( .2 );
102+
floorMaterial.colorNode = Fn( () => {
103+
104+
// blur reflection using textureBicubic()
105+
const dirtyReflection = textureBicubic( reflection, roughness.mul( .9 ) ).rgb;
106+
107+
// falloff opacity by distance like an opacity-fog
108+
const opacity = rangeFogFactor( 7, 25 ).oneMinus();
109+
110+
return vec4( dirtyReflection.rgb, opacity );
111+
112+
} )();
113+
114+
const floor = new THREE.Mesh( new THREE.BoxGeometry( 50, .001, 50 ), floorMaterial );
115+
floor.position.set( 0, 0, 0 );
116+
scene.add( floor );
117+
118+
// renderer
119+
120+
renderer = new THREE.WebGPURenderer();
121+
renderer.setPixelRatio( window.devicePixelRatio );
122+
renderer.setSize( window.innerWidth, window.innerHeight );
123+
renderer.setAnimationLoop( animate );
124+
renderer.toneMapping = THREE.NeutralToneMapping;
125+
renderer.toneMappingExposure = 2;
126+
document.body.appendChild( renderer.domElement );
127+
128+
stats = new Stats();
129+
document.body.appendChild( stats.dom );
130+
131+
controls = new OrbitControls( camera, renderer.domElement );
132+
controls.minDistance = 1;
133+
controls.maxDistance = 10;
134+
controls.maxPolarAngle = Math.PI / 2;
135+
controls.autoRotate = true;
136+
controls.autoRotateSpeed = - .1;
137+
controls.target.set( 0, .5, 0 );
138+
controls.update();
139+
140+
// events
141+
142+
window.addEventListener( 'resize', onWindowResize );
143+
144+
}
145+
146+
function onWindowResize() {
147+
148+
camera.aspect = window.innerWidth / window.innerHeight;
149+
camera.updateProjectionMatrix();
150+
151+
renderer.setSize( window.innerWidth, window.innerHeight );
152+
153+
}
154+
155+
function animate() {
156+
157+
stats.update();
158+
159+
controls.update();
160+
161+
renderer.render( scene, camera );
162+
163+
}
164+
165+
</script>
166+
167+
</body>
168+
</html>

0 commit comments

Comments
 (0)