Skip to content

Commit 1310e4e

Browse files
committed
Improved webgpu reflection example.
1 parent df65620 commit 1310e4e

File tree

1 file changed

+64
-74
lines changed

1 file changed

+64
-74
lines changed

examples/webgpu_reflection.html

Lines changed: 64 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929

3030
import * as THREE from 'three';
3131

32-
import { abs, color, div, float, Fn, instancedBufferAttribute, materialColor, min, normalWorldGeometry, pass, positionGeometry, positionLocal, reflector, screenUV, sin, sub, texture, time, uniform, uv, varyingProperty } from 'three/tsl';
32+
import { abs, blendOverlay, color, div, float, Fn, instancedBufferAttribute, materialColor, min, mrt, normalView, normalWorldGeometry, output, pass, positionGeometry, positionLocal, reflector, screenUV, sin, sub, texture, time, uniform, uv, varyingProperty, vec3 } from 'three/tsl';
33+
import { ao } from 'three/addons/tsl/display/GTAONode.js';
34+
import { denoise } from 'three/addons/tsl/display/DenoiseNode.js';
3335
import { gaussianBlur } from 'three/addons/tsl/display/GaussianBlurNode.js';
3436

3537
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
@@ -44,7 +46,6 @@
4446

4547
// below uniforms will be animated via TWEEN.js
4648

47-
const uniformLife = uniform( 0 );
4849
const uniformEffector1 = uniform( - 0.2 );
4950
const uniformEffector2 = uniform( - 0.2 );
5051

@@ -56,19 +57,21 @@
5657
camera.position.set( 4, 2, 4 );
5758

5859
scene = new THREE.Scene();
59-
scene.fog = new THREE.Fog( 0x0487e2, 7, 25 );
60-
scene.backgroundNode = normalWorldGeometry.y.mix( color( 0x0487e2 ), color( 0x0066ff ) );
60+
scene.fog = new THREE.Fog( 0x4195a4, 1, 25 );
61+
scene.backgroundNode = normalWorldGeometry.y.mix( color( 0x4195a4 ), color( 0x0066ff ) );
6162
camera.lookAt( 0, 1, 0 );
6263

63-
const sunLight = new THREE.DirectionalLight( 0xFFE499, 3 );
64-
sunLight.position.set( 7, 3, 7 );
64+
const sunLight = new THREE.DirectionalLight( 0xFFE499, 2 );
65+
sunLight.position.set( 7, 5, 7 );
66+
sunLight.castShadow = true;
67+
sunLight.shadow.camera.zoom = 1.5;
68+
sunLight.shadow.mapSize.set( 1024, 1024 );
69+
scene.add( sunLight );
6570

66-
const waterAmbientLight = new THREE.HemisphereLight( 0x333366, 0x74ccf4, 3 );
67-
const skyAmbientLight = new THREE.HemisphereLight( 0x74ccf4, 0, 1 );
71+
const backLight = new THREE.DirectionalLight( 0x0487e2, 0.5 );
72+
backLight.position.set( 7, - 5, 7 );
73+
scene.add( backLight );
6874

69-
scene.add( sunLight );
70-
scene.add( skyAmbientLight );
71-
scene.add( waterAmbientLight );
7275

7376
// textures
7477

@@ -86,6 +89,8 @@
8689
// tree
8790

8891
const treeMesh = createTreeMesh();
92+
treeMesh.castShadow = true;
93+
treeMesh.receiveShadow = true;
8994
scene.add( treeMesh );
9095

9196
// floor
@@ -103,6 +108,7 @@
103108

104109
const floor = new THREE.Mesh( new THREE.BoxGeometry( 50, .001, 50 ), floorMaterial );
105110
floor.position.set( 0, 0, 0 );
111+
floor.receiveShadow = true;
106112
scene.add( floor );
107113

108114
// renderer
@@ -111,6 +117,9 @@
111117
renderer.setPixelRatio( window.devicePixelRatio );
112118
renderer.setSize( window.innerWidth, window.innerHeight );
113119
renderer.setAnimationLoop( animate );
120+
renderer.shadowMap.enabled = true;
121+
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
122+
renderer.toneMapping = THREE.ACESFilmicToneMapping;
114123
document.body.appendChild( renderer.domElement );
115124

116125
stats = new Stats();
@@ -137,18 +146,27 @@
137146
const scenePassColorBlurred = gaussianBlur( scenePassColor );
138147
scenePassColorBlurred.directionNode = scenePassDepth;
139148

140-
const vignette = screenUV.distance( .5 ).mul( 1.35 ).clamp().oneMinus();
149+
const vignette = screenUV.distance( .5 ).mul( 1.25 ).clamp().oneMinus().sub( 0.2);
141150

142151
postProcessing = new THREE.PostProcessing( renderer );
143-
postProcessing.outputNode = scenePassColorBlurred.mul( vignette );
152+
postProcessing.outputNode = blendOverlay( scenePassColorBlurred, vignette );
144153

145154
//
146155

147156
window.addEventListener( 'resize', onWindowResize );
148157

149-
//
158+
const effectTween = new TWEEN.Tween( uniformEffector1 )
159+
.to( { value: 1.2 }, 3000 )
160+
.delay( 800 )
161+
.repeat( Infinity )
162+
.easing( TWEEN.Easing.Sinusoidal.InOut )
163+
.start();
150164

151-
startTweens();
165+
const effect2Tween = new TWEEN.Tween( uniformEffector2 )
166+
.to( { value: 1.2 }, 3000 )
167+
.repeat( Infinity )
168+
.easing( TWEEN.Easing.Sinusoidal.InOut )
169+
.start();
152170

153171
}
154172

@@ -173,52 +191,13 @@
173191

174192
}
175193

176-
function startTweens() {
177-
178-
const lifeTween = new TWEEN.Tween( uniformLife )
179-
.to( { value: 1 }, 5000 )
180-
.easing( TWEEN.Easing.Bounce.Out );
181-
lifeTween.start();
182-
183-
const effectTween = new TWEEN.Tween( uniformEffector1 )
184-
.to( { value: 1.2 }, 2500 )
185-
.delay( 3000 )
186-
.easing( TWEEN.Easing.Sinusoidal.InOut )
187-
.onComplete( function () {
188-
189-
secondaryTweens();
190-
191-
} );
192-
effectTween.start();
193-
194-
}
195-
196-
function secondaryTweens() {
197-
198-
uniformEffector1.value = - 0.2;
199-
uniformEffector2.value = - 0.2;
200-
201-
const effect2Tween = new TWEEN.Tween( uniformEffector2 )
202-
.to( { value: 1.2 }, 3000 )
203-
.repeat( Infinity )
204-
.easing( TWEEN.Easing.Sinusoidal.InOut );
205-
effect2Tween.start();
206-
207-
const effectTween = new TWEEN.Tween( uniformEffector1 )
208-
.to( { value: 1.2 }, 3000 )
209-
.delay( 800 )
210-
.repeat( Infinity )
211-
.easing( TWEEN.Easing.Sinusoidal.InOut );
212-
effectTween.start();
213-
214-
}
194+
function random () { return ( Math.random() - 0.5 ) * 2.0 };
215195

216196
function createTreeMesh() {
217197

218-
const maxSteps = 6;
219-
const angleLeft = Math.PI / 180 * 30;
220-
const angleRight = Math.PI / 180 * 40;
221-
const lengthMult = 0.88;
198+
const maxSteps = 5;
199+
const angleOffset = Math.PI / 180 * 40;
200+
const lengthMult = 0.8;
222201

223202
const positions = [];
224203
const normals = [];
@@ -234,6 +213,8 @@
234213

235214
function createTreePart( angle, x, y, z, length, count ) {
236215

216+
if ( Math.random() > ( maxSteps / count ) * 0.25 ) return;
217+
237218
if ( count < maxSteps ) {
238219

239220
const newLength = length * lengthMult;
@@ -246,9 +227,9 @@
246227
if ( size > 25 ) size = 25;
247228
if ( size < 10 ) size = 10;
248229

249-
size = size / 10;
230+
size = size / 100;
250231

251-
const subSteps = 60;
232+
const subSteps = 200;
252233

253234
// below loop generates the instanced data for a tree part
254235

@@ -270,7 +251,7 @@
270251

271252
positions.push( position.x, position.y, position.z );
272253

273-
const scale = 0.25 * Math.random();
254+
const scale = Math.random();
274255

275256
// normal
276257

@@ -279,7 +260,7 @@
279260

280261
// color
281262

282-
color.setHSL( 0.55 + Math.random() * 0.05, 1.0, 0.7 + Math.random() * 0.3 );
263+
color.setHSL( ( count / maxSteps ) * 0.5 + Math.random() * 0.05, 0.75, 0.7 + Math.random() * 0.1 );
283264
colors.push( color.r, color.g, color.b );
284265

285266
// to save vertex buffers, we store the size, time and seed in a single attribute
@@ -292,8 +273,12 @@
292273

293274
}
294275

295-
createTreePart( angle - angleRight, newX, newY, newZ, newLength, count + 1 );
296-
createTreePart( angle + angleLeft, newX, newY, newZ, newLength, count + 1 );
276+
createTreePart( angle + random(), newX, newY, newZ, newLength + random(), count + 1 );
277+
createTreePart( angle + random(), newX, newY, newZ, newLength + random(), count + 1 );
278+
createTreePart( angle + random(), newX, newY, newZ, newLength + random(), count + 1 );
279+
createTreePart( angle + random(), newX, newY, newZ, newLength + random(), count + 1 );
280+
createTreePart( angle + random(), newX, newY, newZ, newLength + random(), count + 1 );
281+
createTreePart( angle + random(), newX, newY, newZ, newLength + random(), count + 1 );
297282

298283
}
299284

@@ -321,8 +306,6 @@
321306

322307
// TSL
323308

324-
const vVisbility = varyingProperty( 'float' );
325-
326309
const instancePosition = instancedBufferAttribute( attributePosition );
327310
const instanceNormal = instancedBufferAttribute( attributeNormal );
328311
const instanceColor = instancedBufferAttribute( attributeColor );
@@ -342,18 +325,13 @@
342325
const dif2 = abs( instanceTime.sub( uniformEffector2 ) ).toConst();
343326
effect = dif2.lessThanEqual( 0.15 ).select( sub( 0.15, dif2 ).mul( sub( 1.7, instanceTime ).mul( 10 ) ), effect );
344327

345-
// life (controls the visibility and initial scale of the cubes)
346-
347-
const scale = uniformLife.greaterThan( instanceTime ).select( min( 1, div( uniformLife.sub( instanceTime ), 0 ) ) ).oneMinus();
348-
vVisbility.assign( uniformLife.greaterThan( instanceTime ).select( 1, 0 ) );
349-
350328
// accumulate different vertex animations
351329

352330
let animated = positionLocal.add( instancePosition ).toVar();
353331
const direction = positionGeometry.normalize().toConst();
354332

355333
animated = animated.add( direction.mul( effect.add( instanceSize ) ) );
356-
animated = animated.sub( direction.mul( scale ) );
334+
animated = animated.sub( direction.mul( effect ) );
357335
animated = animated.add( instanceNormal.mul( effect.mul( 1 ) ) );
358336
animated = animated.add( instanceNormal.mul( abs( sin( time.add( instanceSeed.mul( 2 ) ) ).mul( 1.5 ) ) ) );
359337

@@ -363,12 +341,24 @@
363341

364342
material.colorNode = Fn( () => {
365343

366-
vVisbility.equal( 0 ).discard();
367-
368344
return materialColor.mul( instanceColor );
369345

370346
} )();
371347

348+
material.emissiveNode = Fn( () => {
349+
350+
const instanceTime = instanceData.y;
351+
352+
const dif1 = abs( instanceTime.sub( uniformEffector1 ) ).toConst();
353+
const effect1 = dif1.lessThanEqual( 0.15 ).select( sub( 0.15, dif1 ).mul( sub( 1.7, instanceTime ).mul( 10 ) ), float( 0 ) );
354+
355+
const dif2 = abs( instanceTime.sub( uniformEffector2 ) ).toConst();
356+
const effect2 = dif2.lessThanEqual( 0.15 ).select( sub( 0.15, dif2 ).mul( sub( 1.7, instanceTime ).mul( 10 ) ), effect1 );
357+
358+
return vec3( effect1, 0, effect2 ).mul( instanceColor );
359+
360+
} )();
361+
372362
return mesh;
373363

374364
}

0 commit comments

Comments
 (0)