@dopaminefx/effect-ripple 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/ripple-shader.d.ts +50 -0
- package/dist/ripple-shader.d.ts.map +1 -0
- package/dist/ripple-shader.js +253 -0
- package/dist/ripple-shader.js.map +1 -0
- package/dist/ripple.dope.json +359 -0
- package/package.json +46 -0
- package/src/index.ts +44 -0
- package/src/ripple-shader.ts +263 -0
- package/src/ripple.dope.json +359 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fmt": "dopamine-effect",
|
|
3
|
+
"v": "1.0.0",
|
|
4
|
+
"id": "dopamine.acknowledge.ripple",
|
|
5
|
+
"meta": {
|
|
6
|
+
"name": "Ripple",
|
|
7
|
+
"description": "A droplet in a still pool: concentric waves expand from the action point and refract bright caustic light that dances across the UI, then the surface settles.",
|
|
8
|
+
"tags": [
|
|
9
|
+
"acknowledge",
|
|
10
|
+
"tactile",
|
|
11
|
+
"water"
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
"controls": {
|
|
15
|
+
"mood": {
|
|
16
|
+
"type": "enum",
|
|
17
|
+
"default": "celebratory",
|
|
18
|
+
"options": [
|
|
19
|
+
"serene",
|
|
20
|
+
"celebratory",
|
|
21
|
+
"electric"
|
|
22
|
+
],
|
|
23
|
+
"ui": "segmented"
|
|
24
|
+
},
|
|
25
|
+
"intensity": {
|
|
26
|
+
"type": "scalar",
|
|
27
|
+
"default": 0.7,
|
|
28
|
+
"min": 0,
|
|
29
|
+
"max": 1,
|
|
30
|
+
"step": 0.01,
|
|
31
|
+
"ui": "slider"
|
|
32
|
+
},
|
|
33
|
+
"whimsy": {
|
|
34
|
+
"type": "scalar",
|
|
35
|
+
"default": 0.5,
|
|
36
|
+
"min": 0,
|
|
37
|
+
"max": 1,
|
|
38
|
+
"step": 0.01,
|
|
39
|
+
"ui": "slider"
|
|
40
|
+
},
|
|
41
|
+
"seed": {
|
|
42
|
+
"type": "int",
|
|
43
|
+
"default": null,
|
|
44
|
+
"nullable": true
|
|
45
|
+
},
|
|
46
|
+
"origin": {
|
|
47
|
+
"type": "point",
|
|
48
|
+
"default": "center"
|
|
49
|
+
},
|
|
50
|
+
"target": {
|
|
51
|
+
"type": "selector",
|
|
52
|
+
"default": "document.body"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"baselines": {
|
|
56
|
+
"serene": {
|
|
57
|
+
"durationMs": 2400,
|
|
58
|
+
"lightness": 0.86,
|
|
59
|
+
"chroma": 0.08,
|
|
60
|
+
"hueCenter": 220,
|
|
61
|
+
"hueRange": 110,
|
|
62
|
+
"amplitude": 0.42,
|
|
63
|
+
"rings": 3,
|
|
64
|
+
"wavelength": 0.16,
|
|
65
|
+
"speed": 0.34,
|
|
66
|
+
"caustic": 0.55
|
|
67
|
+
},
|
|
68
|
+
"celebratory": {
|
|
69
|
+
"durationMs": 1800,
|
|
70
|
+
"lightness": 0.82,
|
|
71
|
+
"chroma": 0.15,
|
|
72
|
+
"hueCenter": 190,
|
|
73
|
+
"hueRange": 280,
|
|
74
|
+
"amplitude": 0.5,
|
|
75
|
+
"rings": 4,
|
|
76
|
+
"wavelength": 0.13,
|
|
77
|
+
"speed": 0.42,
|
|
78
|
+
"caustic": 0.75
|
|
79
|
+
},
|
|
80
|
+
"electric": {
|
|
81
|
+
"durationMs": 1300,
|
|
82
|
+
"lightness": 0.8,
|
|
83
|
+
"chroma": 0.22,
|
|
84
|
+
"hueCenter": 175,
|
|
85
|
+
"hueRange": 160,
|
|
86
|
+
"amplitude": 0.58,
|
|
87
|
+
"rings": 5,
|
|
88
|
+
"wavelength": 0.11,
|
|
89
|
+
"speed": 0.52,
|
|
90
|
+
"caustic": 0.95
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"palette": {
|
|
94
|
+
"model": "oklch",
|
|
95
|
+
"space": "linear-srgb",
|
|
96
|
+
"generator": "golden-angle",
|
|
97
|
+
"goldenAngleDeg": 137.50776405003785,
|
|
98
|
+
"stops": 3,
|
|
99
|
+
"hueSpread": 0.55,
|
|
100
|
+
"lightness": {
|
|
101
|
+
"baseline": "lightness",
|
|
102
|
+
"perStop": [
|
|
103
|
+
0,
|
|
104
|
+
0.06,
|
|
105
|
+
-0.05
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
"chroma": {
|
|
109
|
+
"from": {
|
|
110
|
+
"mul": [
|
|
111
|
+
{
|
|
112
|
+
"baseline": "chroma"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"lerp": [
|
|
116
|
+
"intensity",
|
|
117
|
+
0.7,
|
|
118
|
+
1.5
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
},
|
|
123
|
+
"perStop": [
|
|
124
|
+
0,
|
|
125
|
+
0.02,
|
|
126
|
+
-0.01
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
"seed": {
|
|
130
|
+
"deterministic": true,
|
|
131
|
+
"source": "controls.seed",
|
|
132
|
+
"prng": "mulberry32"
|
|
133
|
+
},
|
|
134
|
+
"perMood": {
|
|
135
|
+
"serene": {
|
|
136
|
+
"hueCenter": 220,
|
|
137
|
+
"hueRange": 110,
|
|
138
|
+
"lightness": 0.86,
|
|
139
|
+
"chroma": 0.08
|
|
140
|
+
},
|
|
141
|
+
"celebratory": {
|
|
142
|
+
"hueCenter": 190,
|
|
143
|
+
"hueRange": 280,
|
|
144
|
+
"lightness": 0.82,
|
|
145
|
+
"chroma": 0.15
|
|
146
|
+
},
|
|
147
|
+
"electric": {
|
|
148
|
+
"hueCenter": 175,
|
|
149
|
+
"hueRange": 160,
|
|
150
|
+
"lightness": 0.8,
|
|
151
|
+
"chroma": 0.22
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"tempo": {
|
|
156
|
+
"durationMs": {
|
|
157
|
+
"from": {
|
|
158
|
+
"round": {
|
|
159
|
+
"mul": [
|
|
160
|
+
{
|
|
161
|
+
"baseline": "durationMs"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"lerp": [
|
|
165
|
+
"intensity",
|
|
166
|
+
1.1,
|
|
167
|
+
0.9
|
|
168
|
+
]
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"frame": {
|
|
175
|
+
"amp": {
|
|
176
|
+
"envelope": [
|
|
177
|
+
{
|
|
178
|
+
"input": "life"
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"param": "overshoot"
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
},
|
|
185
|
+
"extras": {}
|
|
186
|
+
},
|
|
187
|
+
"reducedMotion": {
|
|
188
|
+
"peakMs": 280,
|
|
189
|
+
"holdMs": 380
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
"render": {
|
|
193
|
+
"params": {
|
|
194
|
+
"exposure": {
|
|
195
|
+
"type": "float",
|
|
196
|
+
"from": {
|
|
197
|
+
"lerp": [
|
|
198
|
+
"intensity",
|
|
199
|
+
0.85,
|
|
200
|
+
1.5
|
|
201
|
+
]
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
"amplitude": {
|
|
205
|
+
"type": "float",
|
|
206
|
+
"from": {
|
|
207
|
+
"mul": [
|
|
208
|
+
{
|
|
209
|
+
"baseline": "amplitude"
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"lerp": [
|
|
213
|
+
"intensity",
|
|
214
|
+
0.7,
|
|
215
|
+
1.35
|
|
216
|
+
]
|
|
217
|
+
}
|
|
218
|
+
]
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
"rings": {
|
|
222
|
+
"type": "int",
|
|
223
|
+
"from": {
|
|
224
|
+
"round": {
|
|
225
|
+
"add": [
|
|
226
|
+
{
|
|
227
|
+
"baseline": "rings"
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
"lerp": [
|
|
231
|
+
"intensity",
|
|
232
|
+
0,
|
|
233
|
+
2
|
|
234
|
+
]
|
|
235
|
+
}
|
|
236
|
+
]
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
"clampMax": "MAX_RINGS",
|
|
240
|
+
"clampMin": "MIN_RINGS"
|
|
241
|
+
},
|
|
242
|
+
"wavelength": {
|
|
243
|
+
"type": "float",
|
|
244
|
+
"from": {
|
|
245
|
+
"baseline": "wavelength"
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
"speed": {
|
|
249
|
+
"type": "float",
|
|
250
|
+
"from": {
|
|
251
|
+
"mul": [
|
|
252
|
+
{
|
|
253
|
+
"baseline": "speed"
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
"lerp": [
|
|
257
|
+
"intensity",
|
|
258
|
+
0.92,
|
|
259
|
+
1.12
|
|
260
|
+
]
|
|
261
|
+
}
|
|
262
|
+
]
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
"caustic": {
|
|
266
|
+
"type": "float",
|
|
267
|
+
"from": {
|
|
268
|
+
"mul": [
|
|
269
|
+
{
|
|
270
|
+
"baseline": "caustic"
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"lerp": [
|
|
274
|
+
"intensity",
|
|
275
|
+
0.6,
|
|
276
|
+
1.3
|
|
277
|
+
]
|
|
278
|
+
}
|
|
279
|
+
]
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
"overshoot": {
|
|
283
|
+
"type": "float",
|
|
284
|
+
"from": {
|
|
285
|
+
"lerp": [
|
|
286
|
+
"intensity",
|
|
287
|
+
0.7,
|
|
288
|
+
1.4
|
|
289
|
+
]
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
"style": {
|
|
293
|
+
"type": "float",
|
|
294
|
+
"from": {
|
|
295
|
+
"control": "whimsy"
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
"shadowHeightFrac": {
|
|
300
|
+
"min": [
|
|
301
|
+
{
|
|
302
|
+
"add": [
|
|
303
|
+
{
|
|
304
|
+
"mul": [
|
|
305
|
+
{
|
|
306
|
+
"param": "wavelength"
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
"param": "rings"
|
|
310
|
+
},
|
|
311
|
+
0.6
|
|
312
|
+
]
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
"mul": [
|
|
316
|
+
{
|
|
317
|
+
"param": "amplitude"
|
|
318
|
+
},
|
|
319
|
+
0.3
|
|
320
|
+
]
|
|
321
|
+
}
|
|
322
|
+
]
|
|
323
|
+
},
|
|
324
|
+
1
|
|
325
|
+
]
|
|
326
|
+
},
|
|
327
|
+
"consts": {
|
|
328
|
+
"MAX_RINGS": 7,
|
|
329
|
+
"MIN_RINGS": 2
|
|
330
|
+
},
|
|
331
|
+
"config": {
|
|
332
|
+
"usesOrigin": true
|
|
333
|
+
},
|
|
334
|
+
"backends": {
|
|
335
|
+
"webgl2": {
|
|
336
|
+
"stage": "fullscreen-triangle",
|
|
337
|
+
"blend": "screen",
|
|
338
|
+
"shader": {
|
|
339
|
+
"program": "ripple"
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
"fallbackOrder": [
|
|
344
|
+
"webgl2"
|
|
345
|
+
]
|
|
346
|
+
},
|
|
347
|
+
"binding": {
|
|
348
|
+
"note": "CROSS-PLATFORM uniform-binding contract. Which render.params are NOT shader uniforms, the seed-keyed scatter field, the per-frame/host extras, and the texture samplers — one source of truth for the web u<Name> list, the Swift struct + packer, and the MSL struct. SHIPS in the portable .dope (the runtime derives its uniform bindings from it); the toolchain consumes it too for the Metal struct codegen. Only `x-build`, `slug` and `kind` stay toolchain-only.",
|
|
349
|
+
"excludeParams": [
|
|
350
|
+
"style",
|
|
351
|
+
"overshoot",
|
|
352
|
+
"durationMs"
|
|
353
|
+
],
|
|
354
|
+
"scatterKey": "rippleSeed",
|
|
355
|
+
"scatterWeb": "uSeed",
|
|
356
|
+
"extras": [],
|
|
357
|
+
"samplers": []
|
|
358
|
+
}
|
|
359
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dopaminefx/effect-ripple",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Ripple — concentric water-ripple success effect for Dopamine.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"dopamine-effect"
|
|
7
|
+
],
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"module": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"src"
|
|
21
|
+
],
|
|
22
|
+
"sideEffects": [
|
|
23
|
+
"./src/index.ts",
|
|
24
|
+
"./dist/index.js"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc -p tsconfig.json"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@dopaminefx/core": "^0.1.0"
|
|
31
|
+
},
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"author": "10in30",
|
|
34
|
+
"homepage": "https://github.com/10in30/dopamine#readme",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/10in30/dopamine.git",
|
|
38
|
+
"directory": "effects/ripple/web"
|
|
39
|
+
},
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/10in30/dopamine/issues"
|
|
42
|
+
},
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ripple (the tactile "droplet in a still pool" acknowledge effect) as an
|
|
3
|
+
* `EffectFactory` on the Dopamine backbone.
|
|
4
|
+
*
|
|
5
|
+
* FULLY DATA-DRIVEN (P2): everything that isn't the GLSL lives in
|
|
6
|
+
* ripple.dope.json — the mood→params mapping + OKLCH palette (the loader), AND
|
|
7
|
+
* the per-frame logic: `tempo.frame` (the held-breath envelope amp),
|
|
8
|
+
* `render.shadowHeightFrac` (the wave field's outward reach), `render.consts`
|
|
9
|
+
* (MAX_RINGS/MIN_RINGS), `render.config` and the uniform `binding` contract.
|
|
10
|
+
* `registerDopeEffect` interprets that data through the generic
|
|
11
|
+
* `createPassInstance` fullscreen-pass runner; this module is just the water
|
|
12
|
+
* SHADER + the registration call.
|
|
13
|
+
*
|
|
14
|
+
* Anchored at `uOrigin` (usesOrigin: true): concentric wavefronts expand from
|
|
15
|
+
* the action point. Distinct from Solarbloom's soft radial CORE — Ripple's light
|
|
16
|
+
* lives only on thin, moving ring crests + the caustics they refract.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { RIPPLE_FRAGMENT_SRC, RIPPLE_VERTEX_SRC } from "./ripple-shader.js";
|
|
20
|
+
import { parseDope, registerDopeEffect, type EffectFactory, type PassParams } from "@dopaminefx/core";
|
|
21
|
+
import doc from "./ripple.dope.json";
|
|
22
|
+
|
|
23
|
+
const DOPE = parseDope(doc as object);
|
|
24
|
+
|
|
25
|
+
/** The resolved render params Ripple's shader consumes. */
|
|
26
|
+
export interface RippleParams extends PassParams {
|
|
27
|
+
exposure: number;
|
|
28
|
+
amplitude: number;
|
|
29
|
+
rings: number;
|
|
30
|
+
wavelength: number;
|
|
31
|
+
speed: number;
|
|
32
|
+
caustic: number;
|
|
33
|
+
overshoot: number;
|
|
34
|
+
rippleSeed: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// The whole factory (resolve / create / reducedMotion / program registration)
|
|
38
|
+
// is data: ripple.dope.json interpreted by the core backbone.
|
|
39
|
+
export const ripple = registerDopeEffect(DOPE, {
|
|
40
|
+
vertex: RIPPLE_VERTEX_SRC,
|
|
41
|
+
fragment: RIPPLE_FRAGMENT_SRC,
|
|
42
|
+
}) as EffectFactory<PassParams> as EffectFactory<RippleParams>;
|
|
43
|
+
|
|
44
|
+
export default ripple;
|