1- import * as THREE from 'three/webgpu ' ;
1+ import { access , fromTSL , toTSL , type TSLAccessor } from '@typegpu/three ' ;
22import * as TSL from 'three/tsl' ;
3- import { fromTSL , toTSL , type TSLAccessor } from '@typegpu/ three' ;
3+ import * as THREE from 'three/webgpu ' ;
44import * as d from 'typegpu/data' ;
55import * as std from 'typegpu/std' ;
66import { triNoise3D } from './triNoise.ts' ;
@@ -29,6 +29,11 @@ interface VerletSimulationOptions {
2929 spherePositionUniform : TSLAccessor < d . Vec3f , THREE . UniformNode < THREE . Vector3 > > ;
3030}
3131
32+ type TSLStorageAccessor < T extends d . AnyWgslData > = TSLAccessor <
33+ T ,
34+ THREE . StorageBufferNode
35+ > ;
36+
3237export class VerletSimulation {
3338 readonly vertices : Vertex [ ] ;
3439 readonly springs : Spring [ ] ;
@@ -38,42 +43,22 @@ export class VerletSimulation {
3843 readonly windUniform : TSLAccessor < d . F32 , THREE . UniformNode < number > > ;
3944 readonly dampeningUniform : TSLAccessor < d . F32 , THREE . UniformNode < number > > ;
4045
41- readonly vertexPositionBuffer : TSLAccessor <
42- d . WgslArray < d . Vec3f > ,
43- THREE . StorageBufferNode
44- > ;
45- readonly vertexForceBuffer : TSLAccessor <
46- d . WgslArray < d . Vec3f > ,
47- THREE . StorageBufferNode
48- > ;
49- readonly vertexParamsBuffer : TSLAccessor <
50- d . WgslArray < d . Vec3u > ,
51- THREE . StorageBufferNode
52- > ;
53- readonly springListBuffer : TSLAccessor <
54- d . WgslArray < d . U32 > ,
55- THREE . StorageBufferNode
56- > ;
57- readonly springVertexIdBuffer : TSLAccessor <
58- d . WgslArray < d . Vec2u > ,
59- THREE . StorageBufferNode
60- > ;
61- readonly springRestLengthBuffer : TSLAccessor <
62- d . WgslArray < d . F32 > ,
63- THREE . StorageBufferNode
64- > ;
65- readonly springForceBuffer : TSLAccessor <
66- d . WgslArray < d . Vec3f > ,
67- THREE . StorageBufferNode
68- > ;
46+ readonly vertexPositionBuffer : TSLStorageAccessor < d . WgslArray < d . Vec3f > > ;
47+ readonly vertexForceBuffer : TSLStorageAccessor < d . WgslArray < d . Vec3f > > ;
48+ readonly vertexParamsBuffer : TSLStorageAccessor < d . WgslArray < d . Vec3u > > ;
49+ readonly springListBuffer : TSLStorageAccessor < d . WgslArray < d . U32 > > ;
50+ readonly springVertexIdBuffer : TSLStorageAccessor < d . WgslArray < d . Vec2u > > ;
51+ readonly springRestLengthBuffer : TSLStorageAccessor < d . WgslArray < d . F32 > > ;
52+ readonly springForceBuffer : TSLStorageAccessor < d . WgslArray < d . Vec3f > > ;
6953
7054 readonly computeSpringForces : TSL . ShaderNodeObject < THREE . ComputeNode > ;
7155 readonly computeVertexForces : TSL . ShaderNodeObject < THREE . ComputeNode > ;
7256
73- constructor (
74- { sphereRadius, sphereUniform, spherePositionUniform } :
75- VerletSimulationOptions ,
76- ) {
57+ constructor ( {
58+ sphereRadius,
59+ sphereUniform,
60+ spherePositionUniform,
61+ } : VerletSimulationOptions ) {
7762 this . vertices = [ ] ;
7863 this . springs = [ ] ;
7964 this . vertexColumns = [ ] ;
@@ -120,7 +105,7 @@ export class VerletSimulation {
120105 for ( let y = 0 ; y <= clothNumSegmentsY ; y ++ ) {
121106 const posX = x * ( clothWidth / clothNumSegmentsX ) - clothWidth * 0.5 ;
122107 const posZ = y * ( clothHeight / clothNumSegmentsY ) ;
123- const isFixed = ( y === 0 ) && ( ( x % 5 ) === 0 ) ; // make some of the top vertices' positions fixed
108+ const isFixed = y === 0 && x % 5 === 0 ; // make some of the top vertices' positions fixed
124109 const vertex = addVerletVertex ( posX , clothHeight * 0.5 , posZ , isFixed ) ;
125110 column . push ( vertex ) ;
126111 }
@@ -229,32 +214,31 @@ export class VerletSimulation {
229214 // This sets up the compute shaders for the verlet simulation
230215 // There are two shaders that are executed for each simulation step
231216
232- const instanceIndex = fromTSL ( TSL . instanceIndex , { type : d . u32 } ) ;
233-
234217 // 1. computeSpringForces:
235218 // This shader computes a force for each spring, depending on the distance between the two vertices connected by that spring and the targeted rest length
236219
237220 this . computeSpringForces = toTSL ( ( ) => {
238221 'use gpu' ;
239222
240- if ( instanceIndex . $ >= springCount ) {
223+ const idx = access . instanceIndex . $ ;
224+ if ( idx >= springCount ) {
241225 // compute Shaders are executed in groups of 64, so instanceIndex might be bigger than the amount of springs.
242226 // in that case, return.
243227 return ;
244228 }
245229
246- const vertexId = this . springVertexIdBuffer . $ [ instanceIndex . $ ] ;
247- const restLength = this . springRestLengthBuffer . $ [ instanceIndex . $ ] ;
230+ const vertexId = this . springVertexIdBuffer . $ [ idx ] ;
231+ const restLength = this . springRestLengthBuffer . $ [ idx ] ;
248232
249233 const vertex0Position = this . vertexPositionBuffer . $ [ vertexId . x ] ;
250234 const vertex1Position = this . vertexPositionBuffer . $ [ vertexId . y ] ;
251235
252236 const delta = vertex1Position . sub ( vertex0Position ) ;
253237 const dist = std . max ( std . length ( delta ) , 0.000001 ) ;
254238 const force = delta . mul (
255- ( dist - restLength ) * this . stiffnessUniform . $ * 0.5 / dist ,
239+ ( ( dist - restLength ) * this . stiffnessUniform . $ * 0.5 ) / dist ,
256240 ) ;
257- this . springForceBuffer . $ [ instanceIndex . $ ] = d . vec3f ( force ) ;
241+ this . springForceBuffer . $ [ idx ] = d . vec3f ( force ) ;
258242 } ) . compute ( springCount ) ;
259243
260244 // 2. computeVertexForces:
@@ -267,7 +251,7 @@ export class VerletSimulation {
267251
268252 this . computeVertexForces = toTSL ( ( ) => {
269253 'use gpu' ;
270- const idx = instanceIndex . $ ;
254+ const idx = access . instanceIndex . $ ;
271255
272256 if ( idx >= vertexCount ) {
273257 // compute shaders are executed in groups of 64, so instanceIndex might be bigger than the amount of vertices.
@@ -315,7 +299,7 @@ export class VerletSimulation {
315299 const deltaSphere = position . add ( force ) . sub ( spherePositionUniform . $ ) ;
316300 const dist = std . length ( deltaSphere ) ;
317301 const sphereForce = deltaSphere . mul (
318- std . max ( 0 , sphereRadius - dist ) / dist * sphereUniform . $ ,
302+ ( std . max ( 0 , sphereRadius - dist ) / dist ) * sphereUniform . $ ,
319303 ) ;
320304 force = force . add ( sphereForce ) ;
321305
0 commit comments