1
0
Эх сурвалжийг харах

TSL: Introduce `time` (#29557)

* introduce time

* testing possible relation

* Update webgpu_backdrop_water.jpg

* Revert "testing possible relation"

This reverts commit db4a5b26e0d455615492237f04f13e78e99d8868.
sunag 1 жил өмнө
parent
commit
25e6fd33e3
35 өөрчлөгдсөн 117 нэмэгдсэн , 283 устгасан
  1. 7 7
      examples/jsm/objects/WaterMesh.js
  2. 1 1
      examples/jsm/transpiler/ShaderToyDecoder.js
  3. BIN
      examples/screenshots/webgpu_backdrop_water.jpg
  4. 2 3
      examples/webgpu_animation_retargeting.html
  5. 2 2
      examples/webgpu_backdrop.html
  6. 2 2
      examples/webgpu_backdrop_water.html
  7. 4 6
      examples/webgpu_compute_particles_rain.html
  8. 3 5
      examples/webgpu_compute_particles_snow.html
  9. 2 2
      examples/webgpu_cubemap_mix.html
  10. 2 2
      examples/webgpu_instance_mesh.html
  11. 3 3
      examples/webgpu_instance_points.html
  12. 2 4
      examples/webgpu_instance_sprites.html
  13. 2 3
      examples/webgpu_materialx_noise.html
  14. 6 5
      examples/webgpu_particles.html
  15. 3 3
      examples/webgpu_portal.html
  16. 2 2
      examples/webgpu_postprocessing_dof.html
  17. 2 2
      examples/webgpu_sandbox.html
  18. 1 1
      examples/webgpu_shadertoy.html
  19. 2 2
      examples/webgpu_skinning_instancing.html
  20. 2 3
      examples/webgpu_texturegrad.html
  21. 2 2
      examples/webgpu_textures_2d-array.html
  22. 1 2
      examples/webgpu_tsl_coffee_smoke.html
  23. 3 3
      examples/webgpu_tsl_editor.html
  24. 1 3
      examples/webgpu_tsl_galaxy.html
  25. 4 4
      examples/webgpu_tsl_interoperability.html
  26. 1 3
      examples/webgpu_tsl_raging_sea.html
  27. 1 5
      examples/webgpu_tsl_vfx_flames.html
  28. 3 3
      examples/webgpu_tsl_vfx_linkedparticles.html
  29. 14 14
      examples/webgpu_tsl_vfx_tornado.html
  30. 0 2
      src/nodes/Nodes.js
  31. 2 2
      src/nodes/TSL.js
  32. 0 85
      src/nodes/utils/OscNode.js
  33. 6 0
      src/nodes/utils/Oscillators.js
  34. 29 0
      src/nodes/utils/Timer.js
  35. 0 97
      src/nodes/utils/TimerNode.js

+ 7 - 7
examples/jsm/objects/WaterMesh.js

@@ -3,7 +3,7 @@ import {
 	Mesh,
 	Vector3
 } from 'three';
-import { Fn, NodeMaterial, add, cameraPosition, div, normalize, positionWorld, sub, timerLocal, texture, vec2, vec3, vec4, max, dot, reflect, pow, length, float, uniform, reflector, mul, mix } from 'three/tsl';
+import { Fn, NodeMaterial, add, cameraPosition, div, normalize, positionWorld, sub, time, texture, vec2, vec3, vec4, max, dot, reflect, pow, length, float, uniform, reflector, mul, mix } from 'three/tsl';
 
 /**
  * Work based on :
@@ -36,14 +36,14 @@ class WaterMesh extends Mesh {
 
 		// TSL
 
-		const timeNode = timerLocal();
-
 		const getNoise = Fn( ( [ uv ] ) => {
 
-			const uv0 = add( div( uv, 103 ), vec2( div( timeNode, 17 ), div( timeNode, 29 ) ) ).toVar();
-			const uv1 = div( uv, 107 ).sub( vec2( div( timeNode, - 19 ), div( timeNode, 31 ) ) ).toVar();
-			const uv2 = add( div( uv, vec2( 8907.0, 9803.0 ) ), vec2( div( timeNode, 101 ), div( timeNode, 97 ) ) ).toVar();
-			const uv3 = sub( div( uv, vec2( 1091.0, 1027.0 ) ), vec2( div( timeNode, 109 ), div( timeNode, - 113 ) ) ).toVar();
+			const offset = time;
+
+			const uv0 = add( div( uv, 103 ), vec2( div( offset, 17 ), div( offset, 29 ) ) ).toVar();
+			const uv1 = div( uv, 107 ).sub( vec2( div( offset, - 19 ), div( offset, 31 ) ) ).toVar();
+			const uv2 = add( div( uv, vec2( 8907.0, 9803.0 ) ), vec2( div( offset, 101 ), div( offset, 97 ) ) ).toVar();
+			const uv3 = sub( div( uv, vec2( 1091.0, 1027.0 ) ), vec2( div( offset, 109 ), div( offset, - 113 ) ) ).toVar();
 
 			const sample0 = this.waterNormals.uv( uv0 );
 			const sample1 = this.waterNormals.uv( uv1 );

+ 1 - 1
examples/jsm/transpiler/ShaderToyDecoder.js

@@ -7,7 +7,7 @@ class ShaderToyDecoder extends GLSLDecoder {
 
 		super();
 
-		this.addPolyfill( 'iTime', 'float iTime = timerGlobal();' );
+		this.addPolyfill( 'iTime', 'float iTime = time;' );
 		this.addPolyfill( 'iResolution', 'vec2 iResolution = screenSize;' );
 		this.addPolyfill( 'fragCoord', 'vec3 fragCoord = vec3( screenCoordinate.x, screenSize.y - screenCoordinate.y, screenCoordinate.z );' );
 

BIN
examples/screenshots/webgpu_backdrop_water.jpg


+ 2 - 3
examples/webgpu_animation_retargeting.html

@@ -24,7 +24,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { color, screenUV, hue, timerLocal, reflector, Fn, vec2, length, atan2, float, sin, cos, vec3, sub, mul, pow, dodge, normalWorld } from 'three/tsl';
+			import { color, screenUV, hue, reflector, time, Fn, vec2, length, atan2, float, sin, cos, vec3, sub, mul, pow, dodge, normalWorld } from 'three/tsl';
 
 			import Stats from 'three/addons/libs/stats.module.js';
 
@@ -61,7 +61,6 @@
 
 				// forked from https://www.shadertoy.com/view/7ly3D1
 
-				const time = timerLocal( 1 );
 				const suv = vec2( suv_immutable );
 				const uv = vec2( length( suv ), atan2( suv.y, suv.x ) );
 				const offset = float( float( .1 ).mul( sin( uv.y.mul( 10. ).sub( time.mul( .6 ) ) ) ).mul( cos( uv.y.mul( 48. ).add( time.mul( .3 ) ) ) ).mul( cos( uv.y.mul( 3.7 ).add( time ) ) ) );
@@ -83,7 +82,7 @@
 
 			// background
 
-			const coloredVignette = screenUV.distance( .5 ).mix( hue( color( 0x0175ad ), timerLocal( .1 ) ), hue( color( 0x02274f ), timerLocal( .5 ) ) );
+			const coloredVignette = screenUV.distance( .5 ).mix( hue( color( 0x0175ad ), time.mul( .1 ) ), hue( color( 0x02274f ), time.mul( .5 ) ) );
 			const lightSpeedEffect = lightSpeed( normalWorld ).clamp();
 			const lightSpeedSky = normalWorld.y.remapClamp( -.1, 1 ).mix( 0, lightSpeedEffect );
 			const composedBackground = dodge( coloredVignette, lightSpeedSky );

+ 2 - 2
examples/webgpu_backdrop.html

@@ -25,7 +25,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { float, vec3, color, viewportSharedTexture, hue, overlay, posterize, grayscale, saturation, viewportSafeUV, screenUV, checker, uv, timerLocal, oscSine, output } from 'three/tsl';
+			import { float, vec3, color, viewportSharedTexture, hue, overlay, posterize, grayscale, saturation, viewportSafeUV, screenUV, checker, uv, time, oscSine, output } from 'three/tsl';
 
 			import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
 
@@ -62,7 +62,7 @@
 					mixer = new THREE.AnimationMixer( object );
 
 					const material = object.children[ 0 ].children[ 0 ].material;
-					material.outputNode = oscSine( timerLocal( .1 ) ).mix( output, posterize( output.add( .1 ), 4 ).mul( 2 ) );
+					material.outputNode = oscSine( time.mul( .1 ) ).mix( output, posterize( output.add( .1 ), 4 ).mul( 2 ) );
 
 					const action = mixer.clipAction( gltf.animations[ 0 ] );
 					action.play();

+ 2 - 2
examples/webgpu_backdrop_water.html

@@ -25,7 +25,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { color, vec2, pass, linearDepth, normalWorld, triplanarTexture, texture, objectPosition, screenUV, viewportLinearDepth, viewportDepthTexture, viewportSharedTexture, mx_worley_noise_float, positionWorld, timerLocal } from 'three/tsl';
+			import { color, vec2, pass, linearDepth, normalWorld, triplanarTexture, texture, objectPosition, screenUV, viewportLinearDepth, viewportDepthTexture, viewportSharedTexture, mx_worley_noise_float, positionWorld, time } from 'three/tsl';
 			import { gaussianBlur } from 'three/addons/tsl/display/GaussianBlurNode.js';
 
 			import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
@@ -135,7 +135,7 @@
 
 				// water
 
-				const timer = timerLocal( .8 );
+				const timer = time.mul( .8 );
 				const floorUV = positionWorld.xzy;
 
 				const waterLayer0 = mx_worley_noise_float( floorUV.mul( 4 ).add( timer ) );

+ 4 - 6
examples/webgpu_compute_particles_rain.html

@@ -24,7 +24,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { Fn, texture, uv, uint, positionWorld, billboarding, timerLocal, hash, timerDelta, vec2, instanceIndex, positionGeometry, storage, If } from 'three/tsl';
+			import { Fn, texture, uv, uint, positionWorld, billboarding, time, hash, deltaTime, vec2, instanceIndex, positionGeometry, storage, If } from 'three/tsl';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
@@ -102,8 +102,6 @@
 
 				// compute
 
-				const timer = timerLocal();
-
 				const randUint = () => uint( Math.random() * 0xFFFFFF );
 
 				const computeInit = Fn( () => {
@@ -139,7 +137,7 @@
 
 					position.addAssign( velocity );
 
-					rippleTime.x = rippleTime.x.add( timerDelta().mul( 4 ) );
+					rippleTime.x = rippleTime.x.add( deltaTime.mul( 4 ) );
 
 					//
 
@@ -166,8 +164,8 @@
 
 						// next drops will not fall in the same place
 
-						position.x = hash( instanceIndex.add( timer ) ).mul( 100 ).add( - 50 );
-						position.z = hash( instanceIndex.add( timer.add( randUint() ) ) ).mul( 100 ).add( - 50 );
+						position.x = hash( instanceIndex.add( time ) ).mul( 100 ).add( - 50 );
+						position.z = hash( instanceIndex.add( time.add( randUint() ) ) ).mul( 100 ).add( - 50 );
 
 					} );
 

+ 3 - 5
examples/webgpu_compute_particles_snow.html

@@ -25,7 +25,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { Fn, texture, vec3, pass, color, uint, screenUV, positionWorld, positionLocal, timerLocal, vec2, hash, instanceIndex, storage, If } from 'three/tsl';
+			import { Fn, texture, vec3, pass, color, uint, screenUV, positionWorld, positionLocal, time, vec2, hash, instanceIndex, storage, If } from 'three/tsl';
 			import { gaussianBlur } from 'three/addons/tsl/display/GaussianBlurNode.js';
 
 			import { TeapotGeometry } from 'three/addons/geometries/TeapotGeometry.js';
@@ -102,8 +102,6 @@
 
 				// compute
 
-				const timer = timerLocal();
-
 				const randUint = () => uint( Math.random() * 0xFFFFFF );
 
 				const computeInit = Fn( () => {
@@ -153,8 +151,8 @@
 
 					If( position.y.greaterThan( rippleFloorArea ), () => {
 
-						position.x = particleData.x.add( timer.mul( random.mul( random ) ).mul( speed ).sin().mul( 3 ) );
-						position.z = particleData.z.add( timer.mul( random ).mul( speed ).cos().mul( random.mul( 10 ) ) );
+						position.x = particleData.x.add( time.mul( random.mul( random ) ).mul( speed ).sin().mul( 3 ) );
+						position.z = particleData.z.add( time.mul( random ).mul( speed ).cos().mul( random.mul( 10 ) ) );
 
 						position.y = position.y.add( velocity );
 

+ 2 - 2
examples/webgpu_cubemap_mix.html

@@ -27,7 +27,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { mix, oscSine, timerLocal, pmremTexture, float } from 'three/tsl';
+			import { mix, oscSine, time, pmremTexture, float } from 'three/tsl';
 
 			import { RGBMLoader } from 'three/addons/loaders/RGBMLoader.js';
 
@@ -65,7 +65,7 @@
 				cube2Texture.generateMipmaps = true;
 				cube2Texture.minFilter = THREE.LinearMipmapLinearFilter;
 
-				scene.environmentNode = mix( pmremTexture( cube2Texture ), pmremTexture( cube1Texture ), oscSine( timerLocal( .1 ) ) );
+				scene.environmentNode = mix( pmremTexture( cube2Texture ), pmremTexture( cube1Texture ), oscSine( time.mul( .1 ) ) );
 
 				scene.backgroundNode = scene.environmentNode.context( {
 					getTextureLevel: () => float( .5 )

+ 2 - 2
examples/webgpu_instance_mesh.html

@@ -25,7 +25,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { mix, range, normalWorld, oscSine, timerLocal } from 'three/tsl';
+			import { mix, range, normalWorld, oscSine, time } from 'three/tsl';
 
 			import Stats from 'three/addons/libs/stats.module.js';
 
@@ -53,7 +53,7 @@
 				// random colors between instances from 0x000000 to 0xFFFFFF
 				const randomColors = range( new THREE.Color( 0x000000 ), new THREE.Color( 0xFFFFFF ) );
 
-				material.colorNode = mix( normalWorld, randomColors, oscSine( timerLocal( .1 ) ) );
+				material.colorNode = mix( normalWorld, randomColors, oscSine( time.mul( .1 ) ) );
 
 				const loader = new THREE.BufferGeometryLoader();
 				loader.load( 'models/json/suzanne_buffergeometry.json', function ( geometry ) {

+ 3 - 3
examples/webgpu_instance_points.html

@@ -26,7 +26,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { color, storage, Fn, instanceIndex, sin, timerLocal, float, uniform, attribute, mix, vec3 } from 'three/tsl';
+			import { color, storage, Fn, instanceIndex, sin, time, float, uniform, attribute, mix, vec3 } from 'three/tsl';
 
 			import Stats from 'three/addons/libs/stats.module.js';
 
@@ -126,9 +126,9 @@
 
 					const { pulseSpeed, minWidth, maxWidth } = effectController;
 
-					const time = timerLocal().add( float( instanceIndex ) );
+					const relativeTime = time.add( float( instanceIndex ) );
 
-					const sizeFactor = sin( time.mul( pulseSpeed ) ).add( 1 ).div( 2 );
+					const sizeFactor = sin( relativeTime.mul( pulseSpeed ) ).add( 1 ).div( 2 );
 
 					instanceSizeStorage.element( instanceIndex ).assign( sizeFactor.mul( maxWidth.sub( minWidth ) ).add( minWidth ) );
 

+ 2 - 4
examples/webgpu_instance_sprites.html

@@ -29,7 +29,7 @@
 			import Stats from 'three/addons/libs/stats.module.js';
 			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 
-			import { uniform, timerGlobal, instanceIndex, instancedBufferAttribute } from 'three/tsl';
+			import { uniform, time, instanceIndex, instancedBufferAttribute } from 'three/tsl';
 
 
 			let camera, scene, renderer, stats, material;
@@ -69,12 +69,10 @@
 
 				// material
 
-				const timer = timerGlobal();
-
 				material = new THREE.SpriteNodeMaterial( { sizeAttenuation: true, map, alphaMap: map, alphaTest: 0.1, transparent: true } );
 				material.color.setHSL( 1.0, 0.3, 0.7, THREE.SRGBColorSpace );
 				material.positionNode = instancedBufferAttribute( positionAttribute );
-				material.rotationNode = timer.add( instanceIndex ).sin();
+				material.rotationNode = time.add( instanceIndex ).sin();
 				material.scaleNode = uniform( 15 );
 
 				// sprites

+ 2 - 3
examples/webgpu_materialx_noise.html

@@ -24,7 +24,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { normalWorld, timerLocal, mx_noise_vec3, mx_worley_noise_vec3, mx_cell_noise_float, mx_fractal_noise_vec3 } from 'three/tsl';
+			import { normalWorld, time, mx_noise_vec3, mx_worley_noise_vec3, mx_cell_noise_float, mx_fractal_noise_vec3 } from 'three/tsl';
 
 			import Stats from 'three/addons/libs/stats.module.js';
 
@@ -60,8 +60,7 @@
 
 							const geometry = new THREE.SphereGeometry( 8, 64, 32 );
 
-							const offsetNode = timerLocal();
-							const customUV = normalWorld.mul( 10 ).add( offsetNode );
+							const customUV = normalWorld.mul( 10 ).add( time );
 
 							// left top
 

+ 6 - 5
examples/webgpu_particles.html

@@ -24,7 +24,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { range, texture, mix, uv, color, rotateUV, positionLocal, timerLocal } from 'three/tsl';
+			import { range, texture, mix, uv, color, rotateUV, positionLocal, time, uniform } from 'three/tsl';
 
 			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 
@@ -55,9 +55,10 @@
 				const lifeRange = range( .1, 1 );
 				const offsetRange = range( new THREE.Vector3( - 2, 3, - 2 ), new THREE.Vector3( 2, 5, 2 ) );
 
-				const timer = timerLocal( .2, 1/*100000*/ ); // @TODO: need to work with 64-bit precision
+				const speed = uniform( .2 );
+				const scaledTime = time.add( 5 ).mul( speed );
 
-				const lifeTime = timer.mul( lifeRange ).mod( 1 );
+				const lifeTime = scaledTime.mul( lifeRange ).mod( 1 );
 				const scaleRange = range( .3, 2 );
 				const rotateRange = range( .1, 4 );
 
@@ -65,7 +66,7 @@
 
 				const fakeLightEffect = positionLocal.y.oneMinus().max( 0.2 );
 
-				const textureNode = texture( map, rotateUV( uv(), timer.mul( rotateRange ) ) );
+				const textureNode = texture( map, rotateUV( uv(), scaledTime.mul( rotateRange ) ) );
 
 				const opacityNode = textureNode.a.mul( life.oneMinus() );
 
@@ -133,7 +134,7 @@
 
 				const gui = new GUI();
 
-				gui.add( timer, 'scale', 0, 1, 0.01 ).name( 'speed' );
+				gui.add( speed, 'value', 0, 1, 0.01 ).name( 'speed' );
 
 			}
 

+ 3 - 3
examples/webgpu_portal.html

@@ -25,7 +25,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { pass, color, mx_worley_noise_float, timerLocal, screenUV, vec2, uv, normalWorld, mx_fractal_noise_vec3 } from 'three/tsl';
+			import { pass, color, mx_worley_noise_float, time, screenUV, vec2, uv, normalWorld, mx_fractal_noise_vec3 } from 'three/tsl';
 
 			import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
 
@@ -47,7 +47,7 @@
 				sceneMain.backgroundNode = normalWorld.y.mix( color( 0x0066ff ), color( 0xff0066 ) );
 
 				scenePortal = new THREE.Scene();
-				scenePortal.backgroundNode = mx_worley_noise_float( normalWorld.mul( 20 ).add( vec2( 0, timerLocal().oneMinus() ) ) ).mul( color( 0x0066ff ) );
+				scenePortal.backgroundNode = mx_worley_noise_float( normalWorld.mul( 20 ).add( vec2( 0, time.oneMinus() ) ) ).mul( color( 0x0066ff ) );
 
 				//
 
@@ -111,7 +111,7 @@
 
 					};
 
-					const colorNode = mx_fractal_noise_vec3( uv().mul( 20 ).add( timerLocal() ) );
+					const colorNode = mx_fractal_noise_vec3( uv().mul( 20 ).add( time ) );
 
 					const modelMain = createModel();
 					const modelPortal = createModel( colorNode );

+ 2 - 2
examples/webgpu_postprocessing_dof.html

@@ -20,7 +20,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { cubeTexture, positionWorld, oscSine, timerGlobal, pass, uniform } from 'three/tsl';
+			import { cubeTexture, positionWorld, oscSine, time, pass, uniform } from 'three/tsl';
 			import { dof } from 'three/addons/tsl/display/DepthOfFieldNode.js';
 
 			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
@@ -63,7 +63,7 @@
 
 				const textureCube = new THREE.CubeTextureLoader().load( urls );
 				const cubeTextureNode = cubeTexture( textureCube );
-				const oscPos = oscSine( positionWorld.div( 1000 /* scene distance */ ).add( timerGlobal( .2 /* speed */ ) ) );
+				const oscPos = oscSine( positionWorld.div( 1000 /* scene distance */ ).add( time.mul( .2 ) ) );
 
 				const geometry = new THREE.SphereGeometry( 60, 20, 10 );
 				const material = new THREE.MeshBasicNodeMaterial();

+ 2 - 2
examples/webgpu_sandbox.html

@@ -25,7 +25,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { timerLocal, vec2, uv, texture, mix, checker, normalLocal, positionLocal, color, oscSine, attribute } from 'three/tsl';
+			import { time, vec2, uv, texture, mix, checker, normalLocal, positionLocal, color, oscSine, attribute } from 'three/tsl';
 
 			import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js';
 
@@ -75,7 +75,7 @@
 				const materialBox = new THREE.MeshBasicNodeMaterial();
 
 				// birection speed
-				const timerScaleNode = timerLocal().mul( vec2( - 0.5, 0.1 ) );
+				const timerScaleNode = time.mul( vec2( - 0.5, 0.1 ) );
 				const animateUV = uv().add( timerScaleNode );
 
 				const textureNode = texture( uvTexture, animateUV );

+ 1 - 1
examples/webgpu_shadertoy.html

@@ -258,7 +258,7 @@
 				const geometry = new THREE.PlaneGeometry( 2, 2 );
 
 				const material = new THREE.MeshBasicNodeMaterial();
-				material.colorNode = TSL.oscSine( TSL.timerLocal( .3 ) ).mix( shaderToy1Node, shaderToy2Node );
+				material.colorNode = TSL.oscSine( TSL.time.mul( .3 ) ).mix( shaderToy1Node, shaderToy2Node );
 
 				const quad = new THREE.Mesh( geometry, material );
 				scene.add( quad );

+ 2 - 2
examples/webgpu_skinning_instancing.html

@@ -25,7 +25,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { pass, mix, range, color, oscSine, timerLocal } from 'three/tsl';
+			import { pass, mix, range, color, oscSine, time } from 'three/tsl';
 			import { gaussianBlur } from 'three/addons/tsl/display/GaussianBlurNode.js';
 
 			import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
@@ -83,7 +83,7 @@
 
 						if ( child.isMesh ) {
 
-							const oscNode = oscSine( timerLocal( .1 ) );
+							const oscNode = oscSine( time.mul( .1 ) );
 
 							// random colors between instances from 0x000000 to 0xFFFFFF
 							const randomColors = range( new THREE.Color( 0x000000 ), new THREE.Color( 0xFFFFFF ) );

+ 2 - 3
examples/webgpu_texturegrad.html

@@ -27,7 +27,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { If, vec4, float, timerLocal, cos, pow, vec2, uv, texture, Fn } from 'three/tsl';
+			import { If, vec4, float, time, cos, pow, vec2, uv, texture, Fn } from 'three/tsl';
 
 			// WebGPU Backend
 			init();
@@ -50,13 +50,12 @@
 				// load async brick_diffuse
 				const map = await new THREE.TextureLoader().loadAsync( 'textures/uv_grid_opengl.jpg' );
 
-				const elapsedTime = timerLocal();
 				material.colorNode = Fn( () => {
 
 					const color = vec4( 1. ).toVar();
 
 					const vuv = uv().toVar();
-					const blur = pow( float( 0.0625 ).sub( cos( vuv.x.mul( 20.0 ).add( elapsedTime ) ) ).mul( 0.0625 ), 2.0 );
+					const blur = pow( float( 0.0625 ).sub( cos( vuv.x.mul( 20.0 ).add( time ) ) ).mul( 0.0625 ), 2.0 );
 
 					const grad = vec2( blur ).toVar();
 

+ 2 - 2
examples/webgpu_textures_2d-array.html

@@ -28,7 +28,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { texture, uv, oscTriangle, timerLocal } from 'three/tsl';
+			import { texture, uv, time, oscTriangle } from 'three/tsl';
 
 			import Stats from 'three/addons/libs/stats.module.js';
 			import { unzipSync } from 'three/addons/libs/fflate.module.js';
@@ -66,7 +66,7 @@
 						let coord = uv();
 						coord = coord.setY( coord.y.oneMinus() ); // flip y
 
-						let oscLayers = oscTriangle( timerLocal( .5 ) ); // [ /\/ ] triangle osc animation
+						let oscLayers = oscTriangle( time.mul( .5 ) ); // [ /\/ ] triangle osc animation
 						oscLayers = oscLayers.add( 1 ).mul( .5 ); // convert osc range of [ -1, 1 ] to [ 0, 1 ]
 						oscLayers = oscLayers.mul( map.image.depth ); // scale osc range to texture depth
 

+ 1 - 2
examples/webgpu_tsl_coffee_smoke.html

@@ -29,7 +29,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { mix, mul, oneMinus, positionLocal, smoothstep, texture, timerLocal, rotateUV, Fn, uv, vec2, vec3, vec4 } from 'three/tsl';
+			import { mix, mul, oneMinus, positionLocal, smoothstep, texture, time, rotateUV, Fn, uv, vec2, vec3, vec4 } from 'three/tsl';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
@@ -77,7 +77,6 @@
 				// material
 
 				const smokeMaterial = new THREE.MeshBasicNodeMaterial( { transparent: true, side: THREE.DoubleSide, depthWrite: false } );
-				const time = timerLocal();
 
 				// position
 

+ 3 - 3
examples/webgpu_tsl_editor.html

@@ -117,7 +117,7 @@
 
 					const tslCode = `// Simple uv.x animation
 
-const { texture, uniform, vec2, vec4, uv, oscSine, timerLocal, grayscale } = THREE;
+const { texture, uniform, vec2, vec4, uv, oscSine, time, grayscale } = THREE;
 
 //const samplerTexture = new THREE.Texture();
 const samplerTexture = new THREE.TextureLoader().load( './textures/uv_grid_opengl.jpg' );
@@ -125,9 +125,9 @@ samplerTexture.wrapS = THREE.RepeatWrapping;
 //samplerTexture.wrapT = THREE.RepeatWrapping;
 //samplerTexture.colorSpace = THREE.SRGBColorSpace;
 
-const timer = timerLocal( .5 ); // .5 is speed
+const scaledTime = time.mul( .5 ); // .5 is speed
 const uv0 = uv();
-const animateUv = vec2( uv0.x.add( oscSine( timer ) ), uv0.y );
+const animateUv = vec2( uv0.x.add( oscSine( scaledTime ) ), uv0.y );
 
 // label is optional
 const myMap = texture( samplerTexture, animateUv ).rgb.label( 'myTexture' );

+ 1 - 3
examples/webgpu_tsl_galaxy.html

@@ -27,7 +27,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { color, cos, float, mix, range, sin, timerLocal, uniform, uv, vec3, vec4, PI2 } from 'three/tsl';
+			import { color, cos, float, mix, range, sin, time, uniform, uv, vec3, vec4, PI2 } from 'three/tsl';
 
 			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
@@ -55,8 +55,6 @@
 				const size = uniform( 0.08 );
 				material.scaleNode = range( 0, 1 ).mul( size );
 
-				const time = timerLocal();
-
 				const radiusRatio = range( 0, 1 );
 				const radius = radiusRatio.pow( 1.5 ).mul( 5 ).toVar();
 

+ 4 - 4
examples/webgpu_tsl_interoperability.html

@@ -28,7 +28,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { Fn, attribute, varyingProperty, timerLocal, uniform, wgslFn, texture, sampler, uv, clamp, float, vec2, vec3, fract, floor, positionGeometry, sin } from 'three/tsl';
+			import { Fn, attribute, varyingProperty, time, uniform, wgslFn, texture, sampler, uv, clamp, float, vec2, vec3, fract, floor, positionGeometry, sin } from 'three/tsl';
 
 			import WebGPU from 'three/addons/capabilities/WebGPU.js';
 
@@ -182,7 +182,7 @@
 					cellOffset: cellOffsetUniform,
 					cellSize: cellSizeUniform,
 					borderMask: borderMaskUniform,
-					time: timerLocal(),
+					time: time,
 					speed: wgslShaderSpeedUniform,
 					pulseIntensity: pulseIntensityUniform,
 					pulseWidth: pulseWidthUniform,
@@ -214,8 +214,8 @@
 
 					const maskCoord = floor( coord.add( cellOffset ) ).mul( cellSizeUniform );
 					const samplePoint = maskCoord.div( dimensions );
-					const time = timerLocal().mul( tslShaderSpeedUniform );
-					samplePoint.x = samplePoint.x.add( fract( time.div( 20 ) ) );
+					const scaledTime = time.mul( tslShaderSpeedUniform );
+					samplePoint.x = samplePoint.x.add( fract( scaledTime.div( 20 ) ) );
 					samplePoint.y = samplePoint.y.sub( 1.5 );
 
 					let color = texture( planetTexture, samplePoint );

+ 1 - 3
examples/webgpu_tsl_raging_sea.html

@@ -27,7 +27,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { float, mx_noise_float, Loop, color, positionLocal, sin, vec2, vec3, mul, timerLocal, uniform, Fn, transformNormalToView } from 'three/tsl';
+			import { float, mx_noise_float, Loop, color, positionLocal, sin, vec2, vec3, mul, time, uniform, Fn, transformNormalToView } from 'three/tsl';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
@@ -70,8 +70,6 @@
 
 				const wavesElevation = Fn( ( [ position ] ) => {
 
-					const time = timerLocal();
-
 					// large waves
 
 					const elevation = mul(

+ 1 - 5
examples/webgpu_tsl_vfx_flames.html

@@ -27,7 +27,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { PI2, oneMinus, spherizeUV, sin, step, texture, timerLocal, Fn, uv, vec2, vec3, vec4, mix, billboarding } from 'three/tsl';
+			import { PI2, oneMinus, spherizeUV, sin, step, texture, time, Fn, uv, vec2, vec3, vec4, mix, billboarding } from 'three/tsl';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
@@ -96,8 +96,6 @@
 
 				flame1Material.colorNode = Fn( () => {
 
-					const time = timerLocal();
-
 					// main UV
 					const mainUv = uv().toVar();
 					mainUv.assign( spherizeUV( mainUv, 10 ).mul( 0.6 ).add( 0.2 ) ); // spherize
@@ -134,8 +132,6 @@
 
 				flame2Material.colorNode = Fn( () => {
 
-					const time = timerLocal();
-
 					// main UV
 					const mainUv = uv().toVar();
 					mainUv.assign( spherizeUV( mainUv, 10 ).mul( 0.6 ).add( 0.2 ) ); // spherize

+ 3 - 3
examples/webgpu_tsl_vfx_linkedparticles.html

@@ -27,7 +27,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { atan2, cos, float, max, min, mix, PI, PI2, sin, vec2, vec3, color, Fn, hash, hue, If, instanceIndex, Loop, mx_fractal_noise_float, mx_fractal_noise_vec3, pass, pcurve, storage, timerDelta, timerGlobal, uv, uniform } from 'three/tsl';
+			import { atan2, cos, float, max, min, mix, PI, PI2, sin, vec2, vec3, color, Fn, hash, hue, If, instanceIndex, Loop, mx_fractal_noise_float, mx_fractal_noise_vec3, pass, pcurve, storage, deltaTime, time, uv, uniform } from 'three/tsl';
 			import { bloom } from 'three/addons/tsl/display/BloomNode.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
@@ -133,7 +133,7 @@
 					const life = particlePositions.toAttribute().w;
 					const modLife = pcurve( life.oneMinus(), 8.0, 1.0 );
 					const pulse = pcurve(
-						sin( hash( instanceIndex ).mul( PI2 ).add( timerGlobal( 0.5 ).mul( PI2 ) ) ).mul( 0.5 ).add( 0.5 ),
+						sin( hash( instanceIndex ).mul( PI2 ).add( time.mul( 0.5 ).mul( PI2 ) ) ).mul( 0.5 ).add( 0.5 ),
 						0.25,
 						0.25
 					).mul( 10.0 ).add( 1.0 );
@@ -202,7 +202,7 @@
 					const position = particlePositions.element( instanceIndex ).xyz;
 					const life = particlePositions.element( instanceIndex ).w;
 					const velocity = particleVelocities.element( instanceIndex ).xyz;
-					const dt = timerDelta( 0.1 ).mul( timeScale );
+					const dt = deltaTime.mul( 0.1 ).mul( timeScale );
 
 					If( life.greaterThan( 0.0 ), () => {
 

+ 14 - 14
examples/webgpu_tsl_vfx_tornado.html

@@ -27,7 +27,7 @@
 		<script type="module">
 
 			import * as THREE from 'three';
-			import { luminance, cos, float, min, timerLocal, atan2, uniform, pass, PI, PI2, color, positionLocal, oneMinus, sin, texture, Fn, uv, vec2, vec3, vec4 } from 'three/tsl';
+			import { luminance, cos, float, min, time, atan2, uniform, pass, PI, PI2, color, positionLocal, oneMinus, sin, texture, Fn, uv, vec2, vec3, vec4 } from 'three/tsl';
 			import { bloom } from 'three/addons/tsl/display/BloomNode.js';
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
@@ -111,14 +111,14 @@
 
 				floorMaterial.outputNode = Fn( () => {
 
-					const time = timerLocal().mul( timeScale );
+					const scaledTime = time.mul( timeScale );
 
 					// noise 1
 					const noise1Uv = toRadialUv(
 						uv(),
 						vec2( 0.5, 0.5 ),
-						time,
-						time
+						scaledTime,
+						scaledTime
 					);
 					noise1Uv.assign( toSkewedUv(
 						noise1Uv,
@@ -131,8 +131,8 @@
 					const noise2Uv = toRadialUv(
 						uv(),
 						vec2( 2, 8 ),
-						time.mul( 2 ),
-						time.mul( 8 )
+						scaledTime.mul( 2 ),
+						scaledTime.mul( 8 )
 					);
 					noise2Uv.assign( toSkewedUv(
 						noise2Uv,
@@ -172,14 +172,14 @@
 
 				const emissiveMaterial = new THREE.MeshBasicNodeMaterial( { transparent: true, side: THREE.DoubleSide, wireframe: false } );
 
-				emissiveMaterial.positionNode = twistedCylinder( positionLocal, parabolStrength, parabolOffset, parabolAmplitude.sub( 0.05 ), timerLocal().mul( timeScale ) );
+				emissiveMaterial.positionNode = twistedCylinder( positionLocal, parabolStrength, parabolOffset, parabolAmplitude.sub( 0.05 ), time.mul( timeScale ) );
 
 				emissiveMaterial.outputNode = Fn( () => {
 
-					const time = timerLocal().mul( timeScale );
+					const scaledTime = time.mul( timeScale );
 
 					// noise 1
-					const noise1Uv = uv().add( vec2( time, time.negate() ) ).toVar();
+					const noise1Uv = uv().add( vec2( scaledTime, scaledTime.negate() ) ).toVar();
 					noise1Uv.assign( toSkewedUv(
 						noise1Uv,
 						vec2( - 1, 0 )
@@ -188,7 +188,7 @@
 					const noise1 = texture( perlinTexture, noise1Uv, 1 ).r.remap( 0.45, 0.7 );
 
 					// noise 2
-					const noise2Uv = uv().add( vec2( time.mul( 0.5 ), time.negate() ) ).toVar();
+					const noise2Uv = uv().add( vec2( scaledTime.mul( 0.5 ), scaledTime.negate() ) ).toVar();
 					noise2Uv.assign( toSkewedUv(
 						noise2Uv,
 						vec2( - 1, 0 )
@@ -223,14 +223,14 @@
 
 				const darkMaterial = new THREE.MeshBasicNodeMaterial( { transparent: true, side: THREE.DoubleSide, wireframe: false } );
 
-				darkMaterial.positionNode = twistedCylinder( positionLocal, parabolStrength, parabolOffset, parabolAmplitude, timerLocal().mul( timeScale ) );
+				darkMaterial.positionNode = twistedCylinder( positionLocal, parabolStrength, parabolOffset, parabolAmplitude, time.mul( timeScale ) );
 
 				darkMaterial.outputNode = Fn( () => {
 
-					const time = timerLocal().mul( timeScale ).add( 123.4 );
+					const scaledTime = time.mul( timeScale ).add( 123.4 );
 
 					// noise 1
-					const noise1Uv = uv().add( vec2( time, time.negate() ) ).toVar();
+					const noise1Uv = uv().add( vec2( scaledTime, scaledTime.negate() ) ).toVar();
 					noise1Uv.assign( toSkewedUv(
 						noise1Uv,
 						vec2( - 1, 0 )
@@ -239,7 +239,7 @@
 					const noise1 = texture( perlinTexture, noise1Uv, 1 ).g.remap( 0.45, 0.7 );
 
 					// noise 2
-					const noise2Uv = uv().add( vec2( time.mul( 0.5 ), time.negate() ) ).toVar();
+					const noise2Uv = uv().add( vec2( scaledTime.mul( 0.5 ), scaledTime.negate() ) ).toVar();
 					noise2Uv.assign( toSkewedUv(
 						noise2Uv,
 						vec2( - 1, 0 )

+ 0 - 2
src/nodes/Nodes.js

@@ -43,14 +43,12 @@ export { default as JoinNode } from './utils/JoinNode.js';
 export { default as LoopNode } from './utils/LoopNode.js';
 export { default as MatcapUVNode } from './utils/MatcapUVNode.js';
 export { default as MaxMipLevelNode } from './utils/MaxMipLevelNode.js';
-export { default as OscNode } from './utils/OscNode.js';
 export { default as RemapNode } from './utils/RemapNode.js';
 export { default as RotateNode } from './utils/RotateNode.js';
 export { default as SetNode } from './utils/SetNode.js';
 export { default as SplitNode } from './utils/SplitNode.js';
 export { default as SpriteSheetUVNode } from './utils/SpriteSheetUVNode.js';
 export { default as StorageArrayElementNode } from './utils/StorageArrayElementNode.js';
-export { default as TimerNode } from './utils/TimerNode.js';
 export { default as TriplanarTexturesNode } from './utils/TriplanarTexturesNode.js';
 export { default as ReflectorNode } from './utils/ReflectorNode.js';
 export { default as RTTNode } from './utils/RTTNode.js';

+ 2 - 2
src/nodes/TSL.js

@@ -28,7 +28,7 @@ export * from './utils/FunctionOverloadingNode.js';
 export * from './utils/LoopNode.js';
 export * from './utils/MatcapUVNode.js';
 export * from './utils/MaxMipLevelNode.js';
-export * from './utils/OscNode.js';
+export * from './utils/Oscillators.js';
 export * from './utils/Packing.js';
 export * from './utils/RemapNode.js';
 export * from './utils/UVUtils.js';
@@ -36,7 +36,7 @@ export * from './utils/SpriteUtils.js';
 export * from './utils/ViewportUtils.js';
 export * from './utils/RotateNode.js';
 export * from './utils/SpriteSheetUVNode.js';
-export * from './utils/TimerNode.js';
+export * from './utils/Timer.js';
 export * from './utils/TriplanarTexturesNode.js';
 export * from './utils/ReflectorNode.js';
 export * from './utils/RTTNode.js';

+ 0 - 85
src/nodes/utils/OscNode.js

@@ -1,85 +0,0 @@
-import Node from '../core/Node.js';
-import { timerLocal } from './TimerNode.js';
-import { nodeObject, nodeProxy } from '../tsl/TSLBase.js';
-
-class OscNode extends Node {
-
-	static get type() {
-
-		return 'OscNode';
-
-	}
-
-	constructor( method = OscNode.SINE, timeNode = timerLocal() ) {
-
-		super();
-
-		this.method = method;
-		this.timeNode = timeNode;
-
-	}
-
-	getNodeType( builder ) {
-
-		return this.timeNode.getNodeType( builder );
-
-	}
-
-	setup() {
-
-		const method = this.method;
-		const timeNode = nodeObject( this.timeNode );
-
-		let outputNode = null;
-
-		if ( method === OscNode.SINE ) {
-
-			outputNode = timeNode.add( 0.75 ).mul( Math.PI * 2 ).sin().mul( 0.5 ).add( 0.5 );
-
-		} else if ( method === OscNode.SQUARE ) {
-
-			outputNode = timeNode.fract().round();
-
-		} else if ( method === OscNode.TRIANGLE ) {
-
-			outputNode = timeNode.add( 0.5 ).fract().mul( 2 ).sub( 1 ).abs();
-
-		} else if ( method === OscNode.SAWTOOTH ) {
-
-			outputNode = timeNode.fract();
-
-		}
-
-		return outputNode;
-
-	}
-
-	serialize( data ) {
-
-		super.serialize( data );
-
-		data.method = this.method;
-
-	}
-
-	deserialize( data ) {
-
-		super.deserialize( data );
-
-		this.method = data.method;
-
-	}
-
-}
-
-OscNode.SINE = 'sine';
-OscNode.SQUARE = 'square';
-OscNode.TRIANGLE = 'triangle';
-OscNode.SAWTOOTH = 'sawtooth';
-
-export default OscNode;
-
-export const oscSine = /*@__PURE__*/ nodeProxy( OscNode, OscNode.SINE );
-export const oscSquare = /*@__PURE__*/ nodeProxy( OscNode, OscNode.SQUARE );
-export const oscTriangle = /*@__PURE__*/ nodeProxy( OscNode, OscNode.TRIANGLE );
-export const oscSawtooth = /*@__PURE__*/ nodeProxy( OscNode, OscNode.SAWTOOTH );

+ 6 - 0
src/nodes/utils/Oscillators.js

@@ -0,0 +1,6 @@
+import { time } from './Timer.js';
+
+export const oscSine = ( t = time ) => t.add( 0.75 ).mul( Math.PI * 2 ).sin().mul( 0.5 ).add( 0.5 );
+export const oscSquare = ( t = time ) => t.fract().round();
+export const oscTriangle = ( t = time ) => t.add( 0.5 ).fract().mul( 2 ).sub( 1 ).abs();
+export const oscSawtooth = ( t = time ) => t.fract();

+ 29 - 0
src/nodes/utils/Timer.js

@@ -0,0 +1,29 @@
+import { renderGroup } from '../core/UniformGroupNode.js';
+import { uniform } from '../core/UniformNode.js';
+
+export const time = /*@__PURE__*/ uniform( 0 ).setGroup( renderGroup ).onRenderUpdate( ( frame ) => frame.time );
+export const deltaTime = /*@__PURE__*/ uniform( 0 ).setGroup( renderGroup ).onRenderUpdate( ( frame ) => frame.deltaTime );
+export const frameId = /*@__PURE__*/ uniform( 0, 'uint' ).setGroup( renderGroup ).onRenderUpdate( ( frame ) => frame.frameId );
+
+// Deprecated
+
+export const timerLocal = ( timeScale = 1 ) => { // @deprecated, r170
+
+	console.warn( 'TSL: timerLocal() is deprecated. Use "time" instead.' );
+	return time.mul( timeScale );
+
+};
+
+export const timerGlobal = ( timeScale = 1 ) => { // @deprecated, r170
+
+	console.warn( 'TSL: timerGlobal() is deprecated. Use "time" instead.' );
+	return time.mul( timeScale );
+
+};
+
+export const timerDelta = ( timeScale = 1 ) => { // @deprecated, r170
+
+	console.warn( 'TSL: timerDelta() is deprecated. Use "deltaTime" instead.' );
+	return deltaTime.mul( timeScale );
+
+};

+ 0 - 97
src/nodes/utils/TimerNode.js

@@ -1,97 +0,0 @@
-import UniformNode from '../core/UniformNode.js';
-import { NodeUpdateType } from '../core/constants.js';
-import { nodeObject, nodeImmutable } from '../tsl/TSLBase.js';
-
-class TimerNode extends UniformNode {
-
-	static get type() {
-
-		return 'TimerNode';
-
-	}
-
-	constructor( scope = TimerNode.LOCAL, scale = 1, value = 0 ) {
-
-		super( value );
-
-		this.scope = scope;
-		this.scale = scale;
-
-		this.updateType = NodeUpdateType.FRAME;
-
-	}
-	/*
-	@TODO:
-	getNodeType( builder ) {
-
-		const scope = this.scope;
-
-		if ( scope === TimerNode.FRAME ) {
-
-			return 'uint';
-
-		}
-
-		return 'float';
-
-	}
-*/
-	update( frame ) {
-
-		const scope = this.scope;
-		const scale = this.scale;
-
-		if ( scope === TimerNode.LOCAL ) {
-
-			this.value += frame.deltaTime * scale;
-
-		} else if ( scope === TimerNode.DELTA ) {
-
-			this.value = frame.deltaTime * scale;
-
-		} else if ( scope === TimerNode.FRAME ) {
-
-			this.value = frame.frameId;
-
-		} else {
-
-			// global
-
-			this.value = frame.time * scale;
-
-		}
-
-	}
-
-	serialize( data ) {
-
-		super.serialize( data );
-
-		data.scope = this.scope;
-		data.scale = this.scale;
-
-	}
-
-	deserialize( data ) {
-
-		super.deserialize( data );
-
-		this.scope = data.scope;
-		this.scale = data.scale;
-
-	}
-
-}
-
-TimerNode.LOCAL = 'local';
-TimerNode.GLOBAL = 'global';
-TimerNode.DELTA = 'delta';
-TimerNode.FRAME = 'frame';
-
-export default TimerNode;
-
-// @TODO: add support to use node in timeScale
-export const timerLocal = ( timeScale, value = 0 ) => nodeObject( new TimerNode( TimerNode.LOCAL, timeScale, value ) );
-export const timerGlobal = ( timeScale, value = 0 ) => nodeObject( new TimerNode( TimerNode.GLOBAL, timeScale, value ) );
-export const timerDelta = ( timeScale, value = 0 ) => nodeObject( new TimerNode( TimerNode.DELTA, timeScale, value ) );
-export const frameId = /*@__PURE__*/ nodeImmutable( TimerNode, TimerNode.FRAME ).toUint();

粤ICP备19079148号