Skip to content

Commit 28b0bf1

Browse files
authored
Examples: Small changes to Procedural Wood Example (#31786)
* Replaced grainPosition and grainRotation with transformation matrix. Added GUI to modify custom wood * Improved contrast of white text
1 parent c08ca65 commit 28b0bf1

File tree

2 files changed

+81
-57
lines changed

2 files changed

+81
-57
lines changed

examples/jsm/materials/WoodNodeMaterial.js

Lines changed: 32 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,9 @@ const spaceWarp = TSL.Fn( ( [ p, warpStrength, xyScale, zScale ] ) => {
227227

228228
} );
229229

230-
const woodRings = TSL.Fn( ( [ w, ringCount, ringBias, ringSizeVariance, ringVarianceScale, barkThickness ] ) => {
230+
const woodRings = TSL.Fn( ( [ w, ringThickness, ringBias, ringSizeVariance, ringVarianceScale, barkThickness ] ) => {
231231

232-
const rings = noiseFbm( w.mul( ringVarianceScale ), TSL.float( 1 ), TSL.float( 0.5 ), TSL.float( 1 ), TSL.int( 1 ) ).mul( ringSizeVariance ).add( w ).mul( ringCount ).fract().mul( barkThickness );
232+
const rings = noiseFbm( w.mul( ringVarianceScale ), TSL.float( 1 ), TSL.float( 0.5 ), TSL.float( 1 ), TSL.int( 1 ) ).mul( ringSizeVariance ).add( w ).mul( ringThickness ).fract().mul( barkThickness );
233233

234234
const sharpRings = TSL.min( mapRange( rings, 0, ringBias, 0, 1, TSL.bool( true ) ), mapRange( rings, ringBias, 1, 1, 0, TSL.bool( true ) ) );
235235

@@ -268,7 +268,7 @@ const wood = TSL.Fn( ( [
268268
smallWarpScale,
269269
fineWarpStrength,
270270
fineWarpScale,
271-
ringCount,
271+
ringThickness,
272272
ringBias,
273273
ringSizeVariance,
274274
ringVarianceScale,
@@ -284,7 +284,7 @@ const wood = TSL.Fn( ( [
284284
const center = woodCenter( p, centerSize );
285285
const mainWarp = spaceWarp( spaceWarp( p, center, largeWarpScale, largeGrainStretch ), smallWarpStrength, smallWarpScale, 0.17 );
286286
const detailWarp = spaceWarp( mainWarp, fineWarpStrength, fineWarpScale, 0.17 );
287-
const rings = woodRings( detailWarp.length(), ringCount, ringBias, ringSizeVariance, ringVarianceScale, barkThickness );
287+
const rings = woodRings( detailWarp.length(), TSL.float( 1 ).div( ringThickness ), ringBias, ringSizeVariance, ringVarianceScale, barkThickness );
288288
const detail = woodDetail( detailWarp, p, detailWarp.length(), splotchScale );
289289
const cells = cellStructure( mainWarp, cellScale, cellSize.div( TSL.max( TSL.positionView.length().mul( 10 ), 1 ) ) );
290290
const baseColor = TSL.mix( darkGrainColor, lightGrainColor, rings );
@@ -295,91 +295,81 @@ const wood = TSL.Fn( ( [
295295

296296
const woodParams = {
297297
teak: {
298-
grainPosition: { x: - 0.4, y: 0, z: 0 },
299-
grainRotation: { x: 0, y: 0, z: 0 },
298+
transformationMatrix: new THREE.Matrix4().identity(),
300299
centerSize: 1.11, largeWarpScale: 0.32, largeGrainStretch: 0.24, smallWarpStrength: 0.059,
301-
smallWarpScale: 2, fineWarpStrength: 0.006, fineWarpScale: 32.8, ringCount: 34,
300+
smallWarpScale: 2, fineWarpStrength: 0.006, fineWarpScale: 32.8, ringThickness: 1/34,
302301
ringBias: 0.03, ringSizeVariance: 0.03, ringVarianceScale: 4.4, barkThickness: 0.3,
303302
splotchScale: 0.2, splotchIntensity: 0.541, cellScale: 910, cellSize: 0.1,
304303
darkGrainColor: '#0c0504', lightGrainColor: '#926c50'
305304
},
306305
walnut: {
307-
grainPosition: { x: - 0.4, y: 0, z: 0 },
308-
grainRotation: { x: 0, y: 0, z: 0 },
306+
transformationMatrix: new THREE.Matrix4().identity(),
309307
centerSize: 1.07, largeWarpScale: 0.42, largeGrainStretch: 0.34, smallWarpStrength: 0.016,
310-
smallWarpScale: 10.3, fineWarpStrength: 0.028, fineWarpScale: 12.7, ringCount: 32,
308+
smallWarpScale: 10.3, fineWarpStrength: 0.028, fineWarpScale: 12.7, ringThickness: 1/32,
311309
ringBias: 0.08, ringSizeVariance: 0.03, ringVarianceScale: 5.5, barkThickness: 0.98,
312310
splotchScale: 1.84, splotchIntensity: 0.97, cellScale: 710, cellSize: 0.31,
313311
darkGrainColor: '#311e13', lightGrainColor: '#523424'
314312
},
315313
white_oak: {
316-
grainPosition: { x: - 0.4, y: 0, z: 0 },
317-
grainRotation: { x: 0, y: 0, z: 0 },
314+
transformationMatrix: new THREE.Matrix4().identity(),
318315
centerSize: 1.23, largeWarpScale: 0.21, largeGrainStretch: 0.21, smallWarpStrength: 0.034,
319-
smallWarpScale: 2.44, fineWarpStrength: 0.01, fineWarpScale: 14.3, ringCount: 34,
316+
smallWarpScale: 2.44, fineWarpStrength: 0.01, fineWarpScale: 14.3, ringThickness: 1/34,
320317
ringBias: 0.82, ringSizeVariance: 0.16, ringVarianceScale: 1.4, barkThickness: 0.7,
321318
splotchScale: 0.2, splotchIntensity: 0.541, cellScale: 800, cellSize: 0.28,
322319
darkGrainColor: '#8b4c21', lightGrainColor: '#c57e43'
323320
},
324321
pine: {
325-
grainPosition: { x: - 0.4, y: 0, z: - 0.2 },
326-
grainRotation: { x: 0, y: 0, z: 0 },
322+
transformationMatrix: new THREE.Matrix4().identity(),
327323
centerSize: 1.23, largeWarpScale: 0.21, largeGrainStretch: 0.18, smallWarpStrength: 0.041,
328-
smallWarpScale: 2.44, fineWarpStrength: 0.006, fineWarpScale: 23.2, ringCount: 24,
324+
smallWarpScale: 2.44, fineWarpStrength: 0.006, fineWarpScale: 23.2, ringThickness: 1/24,
329325
ringBias: 0.1, ringSizeVariance: 0.07, ringVarianceScale: 5, barkThickness: 0.35,
330326
splotchScale: 0.51, splotchIntensity: 3.32, cellScale: 1480, cellSize: 0.07,
331327
darkGrainColor: '#c58355', lightGrainColor: '#d19d61'
332328
},
333329
poplar: {
334-
grainPosition: { x: - 0.4, y: 0, z: 0.2 },
335-
grainRotation: { x: 0, y: 0, z: 0 },
330+
transformationMatrix: new THREE.Matrix4().identity(),
336331
centerSize: 1.43, largeWarpScale: 0.33, largeGrainStretch: 0.18, smallWarpStrength: 0.04,
337-
smallWarpScale: 4.3, fineWarpStrength: 0.004, fineWarpScale: 33.6, ringCount: 37,
332+
smallWarpScale: 4.3, fineWarpStrength: 0.004, fineWarpScale: 33.6, ringThickness: 1/37,
338333
ringBias: 0.07, ringSizeVariance: 0.03, ringVarianceScale: 3.8, barkThickness: 0.3,
339334
splotchScale: 1.92, splotchIntensity: 0.71, cellScale: 830, cellSize: 0.04,
340335
darkGrainColor: '#716347', lightGrainColor: '#998966'
341336
},
342337
maple: {
343-
grainPosition: { x: - 0.4, y: 0.3, z: - 0.2 },
344-
grainRotation: { x: 0, y: 0, z: 0 },
338+
transformationMatrix: new THREE.Matrix4().identity(),
345339
centerSize: 1.4, largeWarpScale: 0.38, largeGrainStretch: 0.25, smallWarpStrength: 0.067,
346-
smallWarpScale: 2.5, fineWarpStrength: 0.005, fineWarpScale: 33.6, ringCount: 35,
340+
smallWarpScale: 2.5, fineWarpStrength: 0.005, fineWarpScale: 33.6, ringThickness: 1/35,
347341
ringBias: 0.1, ringSizeVariance: 0.07, ringVarianceScale: 4.6, barkThickness: 0.61,
348342
splotchScale: 0.46, splotchIntensity: 1.49, cellScale: 800, cellSize: 0.03,
349343
darkGrainColor: '#b08969', lightGrainColor: '#bc9d7d'
350344
},
351345
red_oak: {
352-
grainPosition: { x: - 0.4, y: 0, z: 0.4 },
353-
grainRotation: { x: 0, y: 0, z: 0 },
346+
transformationMatrix: new THREE.Matrix4().identity(),
354347
centerSize: 1.21, largeWarpScale: 0.24, largeGrainStretch: 0.25, smallWarpStrength: 0.044,
355-
smallWarpScale: 2.54, fineWarpStrength: 0.01, fineWarpScale: 14.5, ringCount: 34,
348+
smallWarpScale: 2.54, fineWarpStrength: 0.01, fineWarpScale: 14.5, ringThickness: 1/34,
356349
ringBias: 0.92, ringSizeVariance: 0.03, ringVarianceScale: 5.6, barkThickness: 1.01,
357350
splotchScale: 0.28, splotchIntensity: 3.48, cellScale: 800, cellSize: 0.25,
358351
darkGrainColor: '#af613b', lightGrainColor: '#e0a27a'
359352
},
360353
cherry: {
361-
grainPosition: { x: - 0.4, y: 0.3, z: 0 },
362-
grainRotation: { x: 0, y: 0, z: 0 },
354+
transformationMatrix: new THREE.Matrix4().identity(),
363355
centerSize: 1.33, largeWarpScale: 0.11, largeGrainStretch: 0.33, smallWarpStrength: 0.024,
364-
smallWarpScale: 2.48, fineWarpStrength: 0.01, fineWarpScale: 15.3, ringCount: 36,
356+
smallWarpScale: 2.48, fineWarpStrength: 0.01, fineWarpScale: 15.3, ringThickness: 1/36,
365357
ringBias: 0.02, ringSizeVariance: 0.04, ringVarianceScale: 6.5, barkThickness: 0.09,
366358
splotchScale: 1.27, splotchIntensity: 1.24, cellScale: 1530, cellSize: 0.15,
367359
darkGrainColor: '#913f27', lightGrainColor: '#b45837'
368360
},
369361
cedar: {
370-
grainPosition: { x: - 0.4, y: 0.1, z: 0.1 },
371-
grainRotation: { x: 0, y: 0, z: 0 },
362+
transformationMatrix: new THREE.Matrix4().identity(),
372363
centerSize: 1.11, largeWarpScale: 0.39, largeGrainStretch: 0.12, smallWarpStrength: 0.061,
373-
smallWarpScale: 1.9, fineWarpStrength: 0.006, fineWarpScale: 4.8, ringCount: 25,
364+
smallWarpScale: 1.9, fineWarpStrength: 0.006, fineWarpScale: 4.8, ringThickness: 1/25,
374365
ringBias: 0.01, ringSizeVariance: 0.07, ringVarianceScale: 6.7, barkThickness: 0.1,
375366
splotchScale: 0.61, splotchIntensity: 2.54, cellScale: 630, cellSize: 0.19,
376367
darkGrainColor: '#9a5b49', lightGrainColor: '#ae745e'
377368
},
378369
mahogany: {
379-
grainPosition: { x: - 0.4, y: 0.2, z: 0 },
380-
grainRotation: { x: 0, y: 0, z: 0 },
370+
transformationMatrix: new THREE.Matrix4().identity(),
381371
centerSize: 1.25, largeWarpScale: 0.26, largeGrainStretch: 0.29, smallWarpStrength: 0.044,
382-
smallWarpScale: 2.54, fineWarpStrength: 0.01, fineWarpScale: 15.3, ringCount: 38,
372+
smallWarpScale: 2.54, fineWarpStrength: 0.01, fineWarpScale: 15.3, ringThickness: 1/38,
383373
ringBias: 0.01, ringSizeVariance: 0.33, ringVarianceScale: 1.2, barkThickness: 0.07,
384374
splotchScale: 0.77, splotchIntensity: 1.39, cellScale: 1400, cellSize: 0.23,
385375
darkGrainColor: '#501d12', lightGrainColor: '#6d3722'
@@ -415,7 +405,7 @@ export function GetWoodPreset( genus, finish ) {
415405

416406
}
417407

418-
return { ...params, grainPosition: new THREE.Vector3().copy( params.grainPosition ), grainRotation: new THREE.Vector3().copy( params.grainRotation ), genus, finish, clearcoat, clearcoatRoughness, clearcoatDarken };
408+
return { ...params, transformationMatrix: new THREE.Matrix4().copy( params.transformationMatrix ), genus, finish, clearcoat, clearcoatRoughness, clearcoatDarken };
419409

420410
}
421411

@@ -429,7 +419,7 @@ uniforms.smallWarpStrength = TSL.uniform( params.smallWarpStrength ).onObjectUpd
429419
uniforms.smallWarpScale = TSL.uniform( params.smallWarpScale ).onObjectUpdate( ( { material } ) => material.smallWarpScale );
430420
uniforms.fineWarpStrength = TSL.uniform( params.fineWarpStrength ).onObjectUpdate( ( { material } ) => material.fineWarpStrength );
431421
uniforms.fineWarpScale = TSL.uniform( params.fineWarpScale ).onObjectUpdate( ( { material } ) => material.fineWarpScale );
432-
uniforms.ringCount = TSL.uniform( params.ringCount ).onObjectUpdate( ( { material } ) => material.ringCount );
422+
uniforms.ringThickness = TSL.uniform( params.ringThickness ).onObjectUpdate( ( { material } ) => material.ringThickness );
433423
uniforms.ringBias = TSL.uniform( params.ringBias ).onObjectUpdate( ( { material } ) => material.ringBias );
434424
uniforms.ringSizeVariance = TSL.uniform( params.ringSizeVariance ).onObjectUpdate( ( { material } ) => material.ringSizeVariance );
435425
uniforms.ringVarianceScale = TSL.uniform( params.ringVarianceScale ).onObjectUpdate( ( { material } ) => material.ringVarianceScale );
@@ -440,19 +430,18 @@ uniforms.cellScale = TSL.uniform( params.cellScale ).onObjectUpdate( ( { materia
440430
uniforms.cellSize = TSL.uniform( params.cellSize ).onObjectUpdate( ( { material } ) => material.cellSize );
441431
uniforms.darkGrainColor = TSL.uniform( new THREE.Color( params.darkGrainColor ) ).onObjectUpdate( ( { material }, self ) => self.value.set( material.darkGrainColor ) );
442432
uniforms.lightGrainColor = TSL.uniform( new THREE.Color( params.lightGrainColor ) ).onObjectUpdate( ( { material }, self ) => self.value.set( material.lightGrainColor ) );
443-
uniforms.grainPosition = TSL.uniform( new THREE.Vector3().copy( params.grainPosition ) ).onObjectUpdate( ( { material } ) => material.grainPosition );
444-
uniforms.grainRotation = TSL.uniform( new THREE.Vector3().copy( params.grainRotation ) ).onObjectUpdate( ( { material } ) => material.grainRotation );
433+
uniforms.transformationMatrix = TSL.uniform( new THREE.Matrix4().copy( params.transformationMatrix ) ).onObjectUpdate( ( { material } ) => material.transformationMatrix );
445434

446435
const colorNode = wood(
447-
TSL.rotate( TSL.positionLocal.add( uniforms.grainPosition ), uniforms.grainRotation ),
436+
uniforms.transformationMatrix.mul( TSL.vec4(TSL.positionLocal, 1) ).xyz,
448437
uniforms.centerSize,
449438
uniforms.largeWarpScale,
450439
uniforms.largeGrainStretch,
451440
uniforms.smallWarpStrength,
452441
uniforms.smallWarpScale,
453442
uniforms.fineWarpStrength,
454443
uniforms.fineWarpScale,
455-
uniforms.ringCount,
444+
uniforms.ringThickness,
456445
uniforms.ringBias,
457446
uniforms.ringSizeVariance,
458447
uniforms.ringVarianceScale,
@@ -476,7 +465,7 @@ const colorNode = wood(
476465
* // Using custom parameters (for advanced customization)
477466
* const material = new WoodNodeMaterial({
478467
* centerSize: 1.2,
479-
* ringCount: 40,
468+
* ringThickness: 1/40,
480469
* darkGrainColor: new THREE.Color('#2a1a0a'),
481470
* lightGrainColor: new THREE.Color('#8b4513'),
482471
* clearcoat: 1,
@@ -487,11 +476,11 @@ const colorNode = wood(
487476
* const walnutParams = GetWoodPreset('walnut', 'raw');
488477
* const material = new WoodNodeMaterial({
489478
* ...walnutParams,
490-
* ringCount: 50, // Override specific parameter
479+
* ringThickness: 1/50, // Override specific parameter
491480
* clearcoat: 1 // Add finish
492481
* });
493482
*/
494-
export class WoodNodeMaterial extends THREE.MeshPhysicalNodeMaterial {
483+
export class WoodNodeMaterial extends THREE.MeshPhysicalMaterial {
495484

496485
static get type() {
497486

examples/webgpu_tsl_wood.html

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<style>
1010

1111
body {
12-
color:white;
12+
color:rgb(55, 55, 55);
1313
}
1414

1515
#info a {
@@ -45,10 +45,11 @@
4545
import { HDRLoader } from 'three/addons/loaders/HDRLoader.js';
4646
import { FontLoader } from 'three/addons/loaders/FontLoader.js';
4747
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
48+
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
4849
import { RoundedBoxGeometry } from 'three/addons/geometries/RoundedBoxGeometry.js';
4950
import { WoodNodeMaterial, WoodGenuses, Finishes } from 'three/addons/materials/WoodNodeMaterial.js';
5051

51-
let scene, base, camera, renderer, controls, stats, font, blockGeometry;
52+
let scene, base, camera, renderer, controls, stats, font, blockGeometry, gui;
5253

5354
// Helper function to get grid position
5455
function getGridPosition( woodIndex, finishIndex ) {
@@ -163,6 +164,8 @@
163164

164165
stats = new Stats();
165166
document.body.appendChild( stats.dom );
167+
168+
gui = new GUI();
166169

167170
font = await new FontLoader().loadAsync( './fonts/helvetiker_regular.typeface.json' );
168171

@@ -213,7 +216,9 @@
213216

214217
const material = WoodNodeMaterial.fromPreset( WoodGenuses[ x ], Finishes[ y ] );
215218
const cube = new THREE.Mesh( blockGeometry, material );
219+
216220
cube.position.copy( getGridPosition( x, y ) );
221+
material.transformationMatrix = new THREE.Matrix4().setPosition( new THREE.Vector3( -0.1, 0, Math.random() ) );
217222
base.add( cube );
218223

219224
await new Promise( resolve => setTimeout( resolve, 0 ) );
@@ -222,7 +227,7 @@
222227

223228
}
224229

225-
add_custom_wood( text_mat );
230+
add_custom_wood( text_mat );
226231

227232
}
228233

@@ -262,22 +267,52 @@
262267

263268
// Create custom wood material with unique parameters
264269
const customMaterial = new WoodNodeMaterial( {
265-
centerSize: 1.8,
266-
largeWarpScale: 0.5,
267-
ringCount: 45,
268-
ringBias: 0.15,
269-
barkThickness: 0.8,
270-
splotchScale: 2.5,
271-
splotchIntensity: 1.8,
272-
cellScale: 1200,
273-
cellSize: 0.05,
274-
darkGrainColor: new THREE.Color( '#0a0a0a' ),
275-
lightGrainColor: new THREE.Color( '#8b4513' ),
270+
centerSize: 1.11,
271+
largeWarpScale: 0.32,
272+
largeGrainStretch: 0.24,
273+
smallWarpStrength: 0.059,
274+
smallWarpScale: 2,
275+
fineWarpStrength: 0.006,
276+
fineWarpScale: 32.8,
277+
ringThickness: 1/34,
278+
ringBias: 0.03,
279+
ringSizeVariance: 0.03,
280+
ringVarianceScale: 4.4,
281+
barkThickness: 0.3,
282+
splotchScale: 0.2,
283+
splotchIntensity: 0.541,
284+
cellScale: 910,
285+
cellSize: 0.1,
286+
darkGrainColor: new THREE.Color( '#0c0504') ,
287+
lightGrainColor: new THREE.Color( '#926c50' ),
276288
clearcoat: 1,
277289
clearcoatRoughness: 0.2
278290
} );
279291

292+
gui.add( customMaterial, 'centerSize', 0.0, 2.0, 0.01 ).name( 'centerSize' );
293+
gui.add( customMaterial, 'largeWarpScale', 0.0, 1.0, 0.001 ).name( 'largeWarpScale' );
294+
gui.add( customMaterial, 'largeGrainStretch', 0.0, 1.0, 0.001 ).name( 'largeGrainStretch' );
295+
gui.add( customMaterial, 'smallWarpStrength', 0.0, 0.2, 0.001 ).name( 'smallWarpStrength' );
296+
gui.add( customMaterial, 'smallWarpScale', 0.0, 5.0, 0.01 ).name( 'smallWarpScale' );
297+
gui.add( customMaterial, 'fineWarpStrength', 0.0, 0.05, 0.001 ).name( 'fineWarpStrength' );
298+
gui.add( customMaterial, 'fineWarpScale', 0.0, 50.0, 0.1 ).name( 'fineWarpScale' );
299+
gui.add( customMaterial, 'ringThickness', 0.0, 0.1, 0.001 ).name( 'ringThickness' );
300+
gui.add( customMaterial, 'ringBias', -0.2, 0.2, 0.001 ).name( 'ringBias' );
301+
gui.add( customMaterial, 'ringSizeVariance', 0.0, 0.2, 0.001 ).name( 'ringSizeVariance' );
302+
gui.add( customMaterial, 'ringVarianceScale', 0.0, 10.0, 0.1 ).name( 'ringVarianceScale' );
303+
gui.add( customMaterial, 'barkThickness', 0.0, 1.0, 0.01 ).name( 'barkThickness' );
304+
gui.add( customMaterial, 'splotchScale', 0.0, 1.0, 0.01 ).name( 'splotchScale' );
305+
gui.add( customMaterial, 'splotchIntensity', 0.0, 1.0, 0.01 ).name( 'splotchIntensity' );
306+
gui.add( customMaterial, 'cellScale', 100, 2000, 1 ).name( 'cellScale' );
307+
gui.add( customMaterial, 'cellSize', 0.01, 0.5, 0.001 ).name( 'cellSize' );
308+
gui.addColor( { darkGrainColor: '#0c0504' }, 'darkGrainColor' ).onChange( v => customMaterial.darkGrainColor.set( v ) );
309+
gui.addColor( { lightGrainColor: '#926c50' }, 'lightGrainColor' ).onChange( v => customMaterial.lightGrainColor.set( v ) );
310+
gui.add( customMaterial, 'clearcoat', 0.0, 1.0, 0.01 ).name( 'clearcoat' );
311+
gui.add( customMaterial, 'clearcoatRoughness', 0.0, 1.0, 0.01 ).name( 'clearcoatRoughness' );
312+
280313
const cube = new THREE.Mesh( blockGeometry, customMaterial );
314+
315+
customMaterial.transformationMatrix = new THREE.Matrix4().setPosition( new THREE.Vector3( -0.1, 0, Math.random() ) );
281316
cube.position.copy( getGridPosition( Math.round( WoodGenuses.length / 2 ), 5 ) );
282317

283318
base.add( cube );

0 commit comments

Comments
 (0)