@@ -24,7 +24,6 @@ camera.position.set(0, 0, 1);
2424
2525const scene = new THREE . Scene ( ) ;
2626
27- // top left is (0,0) - just recalling
2827const bgColor = TSL . screenUV . y . mix ( TSL . color ( 0x9f87f7 ) , TSL . color ( 0xf2cdcd ) ) ;
2928const bgVignette = TSL . screenUV . distance ( 0.5 ) . remapClamp ( 0.3 , 0.8 ) . oneMinus ( ) ;
3029const bgIntensity = 4 ;
@@ -37,86 +36,100 @@ const elasticity = TSL.uniform(0.4);
3736const damping = TSL . uniform ( 0.94 ) ;
3837const brushSize = TSL . uniform ( 0.25 ) ;
3938const brushStrength = TSL . uniform ( 0.22 ) ;
40- const pointerPositionUniform = fromTSL ( pointerPosition , { type : d . vec4f } ) ;
41- const elasticityUniform = fromTSL ( elasticity , { type : d . f32 } ) ;
42- const dampingUniform = fromTSL ( damping , { type : d . f32 } ) ;
43- const brushSizeUniform = fromTSL ( brushSize , { type : d . f32 } ) ;
44- const brushStrengthUniform = fromTSL ( brushStrength , { type : d . f32 } ) ;
39+ const pointerPositionAccessor = fromTSL ( pointerPosition , { type : d . vec4f } ) ;
40+ const elasticityAccessor = fromTSL ( elasticity , { type : d . f32 } ) ;
41+ const dampingAccessor = fromTSL ( damping , { type : d . f32 } ) ;
42+ const brushSizeAccessor = fromTSL ( brushSize , { type : d . f32 } ) ;
43+ const brushStrengthAccessor = fromTSL ( brushStrength , { type : d . f32 } ) ;
4544
4645const jelly = TSL . Fn ( ( { renderer, geometry, object } ) => {
4746 const count = geometry . attributes . position . count ;
4847
49- // Create storage buffer attribute for modified position.
50-
51- const positionBaseAttribute = geometry . attributes . position ;
5248 const positionStorageBufferAttribute = new THREE . StorageBufferAttribute (
5349 count ,
5450 3 ,
5551 ) ;
56- const speedBufferAttribute = new THREE . StorageBufferAttribute ( count , 3 ) ;
57-
5852 geometry . setAttribute ( 'storagePosition' , positionStorageBufferAttribute ) ;
5953
60- // Attributes
61-
62- const positionAttribute = TSL . storage (
63- positionBaseAttribute as THREE . BufferAttribute ,
64- 'vec3' ,
65- count ,
54+ const instanceIndexAccessor = fromTSL ( TSL . instanceIndex , { type : d . u32 } ) ;
55+ const basePositionAccessor = fromTSL (
56+ TSL . storage (
57+ geometry . attributes . position as THREE . BufferAttribute ,
58+ 'vec3' ,
59+ count ,
60+ ) ,
61+ {
62+ type : d . arrayOf ( d . vec3f ) ,
63+ } ,
6664 ) ;
67- const positionStorageAttribute = TSL . storage (
68- positionStorageBufferAttribute ,
69- 'vec3' ,
70- count ,
65+ const positionAccessor = fromTSL (
66+ TSL . storage (
67+ positionStorageBufferAttribute ,
68+ 'vec3' ,
69+ count ,
70+ ) ,
71+ {
72+ type : d . arrayOf ( d . vec3f ) ,
73+ } ,
74+ ) ;
75+ const speedAccessor = fromTSL (
76+ TSL . storage (
77+ new THREE . StorageBufferAttribute ( count , 3 ) ,
78+ 'vec3' ,
79+ count ,
80+ ) ,
81+ {
82+ type : d . arrayOf ( d . vec3f ) ,
83+ } ,
7184 ) ;
7285
73- const speedAttribute = TSL . storage ( speedBufferAttribute , 'vec3' , count ) ;
74-
75- // Vectors
76-
77- // Base vec3 position of the mesh vertices.
78- const basePosition = positionAttribute . element ( TSL . instanceIndex ) ;
79- // Mesh vertices after compute modification.
80- const currentPosition = positionStorageAttribute . element ( TSL . instanceIndex ) ;
81- // Speed of each mesh vertex.
82- const currentSpeed = speedAttribute . element ( TSL . instanceIndex ) ;
83-
84- const computeInit = TSL . Fn ( ( ) => {
85- // Modified storage position starts out the same as the base position.
86-
87- currentPosition . assign ( basePosition ) ;
88- } ) ( ) . compute ( count ) ;
89-
90- const computeUpdate = TSL . Fn ( ( ) => {
91- // pinch
92-
93- TSL . If ( pointerPosition . w . equal ( 1 ) , ( ) => {
94- const worldPosition = TSL . objectWorldMatrix ( object ) . mul ( currentPosition ) ;
95-
96- const dist = worldPosition . distance ( pointerPosition . xyz ) ;
97- const direction = pointerPosition . xyz . sub ( worldPosition ) . normalize ( ) ;
98-
99- const power = brushSize . sub ( dist ) . max ( 0 ) . mul ( brushStrength ) ;
100-
101- currentPosition . addAssign ( direction . mul ( power ) ) ;
102- } ) ;
103-
104- // compute ( jelly )
105-
106- const distance = basePosition . distance ( currentPosition ) ;
107- const force = elasticity
108- . mul ( distance )
109- . mul ( basePosition . sub ( currentPosition ) ) ;
110-
111- currentSpeed . addAssign ( force ) ;
112- currentSpeed . mulAssign ( damping ) ;
113-
114- currentPosition . addAssign ( currentSpeed ) ;
115- } ) ( )
116- . compute ( count )
117- . setName ( 'Update Jelly' ) ;
118-
119- // initialize the storage buffer with the base position
86+ const computeInit = toTSL ( ( ) => {
87+ 'use gpu' ;
88+ positionAccessor . $ [ instanceIndexAccessor . $ ] =
89+ basePositionAccessor . $ [ instanceIndexAccessor . $ ] ;
90+ } ) . compute ( count ) . setName ( 'Init Mesh' ) ;
91+
92+ const modelMatrixAccessor = fromTSL ( TSL . objectWorldMatrix ( object ) , {
93+ type : d . mat4x4f ,
94+ } ) ;
95+
96+ const computeUpdate = toTSL ( ( ) => {
97+ 'use gpu' ;
98+ const instanceIdx = instanceIndexAccessor . $ ;
99+ const basePosition = basePositionAccessor . $ [ instanceIdx ] ;
100+ let position = positionAccessor . $ [ instanceIdx ] ;
101+
102+ if ( pointerPositionAccessor . $ . w === 1 ) {
103+ const worldPosition = modelMatrixAccessor . $ . mul (
104+ d . vec4f ( position , 1 ) ,
105+ ) . xyz ;
106+ const dist = std . distance ( worldPosition , pointerPositionAccessor . $ . xyz ) ;
107+ const direction = std . normalize (
108+ pointerPositionAccessor . $ . xyz . sub ( worldPosition ) ,
109+ ) ;
110+ const power = std . max ( brushSizeAccessor . $ - dist , 0 ) *
111+ brushStrengthAccessor . $ ;
112+
113+ positionAccessor . $ [ instanceIndexAccessor . $ ] = position . add (
114+ direction . mul ( power ) ,
115+ ) ;
116+ position = positionAccessor . $ [ instanceIdx ] ;
117+ }
118+
119+ const dist = std . distance (
120+ basePosition ,
121+ position ,
122+ ) ;
123+ const force = basePosition
124+ . sub ( position )
125+ . mul ( elasticityAccessor . $ * dist ) ;
126+ const speed = speedAccessor . $ [ instanceIdx ]
127+ . add ( force )
128+ . mul ( dampingAccessor . $ ) ;
129+
130+ speedAccessor . $ [ instanceIdx ] = d . vec3f ( speed ) ;
131+ positionAccessor . $ [ instanceIdx ] = position . add ( speed ) ;
132+ } ) . compute ( count ) . setName ( 'Update Jelly' ) ;
120133
121134 computeUpdate . onInit ( ( ) => renderer . compute ( computeInit ) ) ;
122135
0 commit comments