@remotion/effects 4.0.541 → 4.0.543

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.
Files changed (133) hide show
  1. package/THIRD_PARTY_LICENSES.md +10 -0
  2. package/dist/esm/lightning.mjs +603 -0
  3. package/dist/esm/magnify.mjs +403 -0
  4. package/dist/esm/preview/barrel-distortion.mjs +303 -0
  5. package/dist/esm/preview/bevel-alpha.mjs +525 -0
  6. package/dist/esm/preview/blur.mjs +435 -0
  7. package/dist/esm/preview/brightness.mjs +95 -0
  8. package/dist/esm/preview/burlap.mjs +481 -0
  9. package/dist/esm/preview/checkerboard.mjs +8 -0
  10. package/dist/esm/preview/chromatic-aberration.mjs +308 -0
  11. package/dist/esm/preview/color-correction.mjs +522 -0
  12. package/dist/esm/preview/color-key.mjs +440 -0
  13. package/dist/esm/preview/contour-lines.mjs +608 -0
  14. package/dist/esm/preview/contrast.mjs +95 -0
  15. package/dist/esm/preview/corner-pin.mjs +6 -0
  16. package/dist/esm/preview/curves.mjs +357 -0
  17. package/dist/esm/preview/cylinder.mjs +273 -0
  18. package/dist/esm/preview/dot-grid.mjs +333 -0
  19. package/dist/esm/preview/drop-shadow.mjs +607 -0
  20. package/dist/esm/preview/duotone.mjs +344 -0
  21. package/dist/esm/preview/emboss.mjs +479 -0
  22. package/dist/esm/preview/evolve.mjs +485 -0
  23. package/dist/esm/preview/exposure.mjs +264 -0
  24. package/dist/esm/preview/film-burn.mjs +298 -0
  25. package/dist/esm/preview/fisheye.mjs +422 -0
  26. package/dist/esm/preview/flannel.mjs +401 -0
  27. package/dist/esm/preview/fractal-noise.mjs +642 -0
  28. package/dist/esm/preview/glow.mjs +598 -0
  29. package/dist/esm/preview/grayscale.mjs +86 -0
  30. package/dist/esm/preview/gridlines.mjs +8 -0
  31. package/dist/esm/preview/halftone-linear-gradient.mjs +523 -0
  32. package/dist/esm/preview/halftone.mjs +552 -0
  33. package/dist/esm/preview/hue.mjs +83 -0
  34. package/dist/esm/preview/index-00v3hr66.mjs +299 -0
  35. package/dist/esm/preview/index-0w4eqht8.mjs +351 -0
  36. package/dist/esm/preview/index-18y0zcy2.mjs +440 -0
  37. package/dist/esm/preview/index-1m1b1ad7.mjs +520 -0
  38. package/dist/esm/preview/index-34fxm3ax.mjs +518 -0
  39. package/dist/esm/preview/index-4fvp93ps.mjs +32 -0
  40. package/dist/esm/preview/index-4scpn12x.mjs +224 -0
  41. package/dist/esm/preview/index-4z6pt3ka.mjs +104 -0
  42. package/dist/esm/preview/index-618ky75w.mjs +51 -0
  43. package/dist/esm/preview/index-6agxdrvr.mjs +411 -0
  44. package/dist/esm/preview/index-6jkps947.mjs +120 -0
  45. package/dist/esm/preview/index-8agtsbw4.mjs +617 -0
  46. package/dist/esm/preview/index-8jx11jyn.mjs +29 -0
  47. package/dist/esm/preview/index-8p04sssx.mjs +123 -0
  48. package/dist/esm/preview/index-afdtmrh2.mjs +596 -0
  49. package/dist/esm/preview/index-b86qstcs.mjs +18 -0
  50. package/dist/esm/preview/index-cb77qg3g.mjs +587 -0
  51. package/dist/esm/preview/index-cdp7tr8x.mjs +122 -0
  52. package/dist/esm/preview/index-evy8hyah.mjs +55 -0
  53. package/dist/esm/preview/index-gnsce796.mjs +6 -0
  54. package/dist/esm/preview/index-kkvzt8b7.mjs +199 -0
  55. package/dist/esm/preview/index-r0v18b2n.mjs +425 -0
  56. package/dist/esm/preview/index-rswpzmm5.mjs +926 -0
  57. package/dist/esm/preview/index-s9mrx750.mjs +97 -0
  58. package/dist/esm/preview/index-tvfexb7s.mjs +164 -0
  59. package/dist/esm/preview/index-vp56k1gj.mjs +215 -0
  60. package/dist/esm/preview/index-wxhvgv2s.mjs +79 -0
  61. package/dist/esm/preview/index-wy95a41r.mjs +407 -0
  62. package/dist/esm/preview/index-ysnwfc4t.mjs +306 -0
  63. package/dist/esm/preview/index.mjs +51 -0
  64. package/dist/esm/preview/invert.mjs +84 -0
  65. package/dist/esm/preview/iris-wipe.mjs +315 -0
  66. package/dist/esm/preview/lens-blur.mjs +563 -0
  67. package/dist/esm/preview/levels.mjs +400 -0
  68. package/dist/esm/preview/light-leak.mjs +8 -0
  69. package/dist/esm/preview/light-trail.mjs +516 -0
  70. package/dist/esm/preview/lightning.mjs +603 -0
  71. package/dist/esm/preview/linear-gradient-tint.mjs +6 -0
  72. package/dist/esm/preview/linear-gradient.mjs +6 -0
  73. package/dist/esm/preview/linear-progressive-blur.mjs +516 -0
  74. package/dist/esm/preview/linear-progressive-pixelate.mjs +176 -0
  75. package/dist/esm/preview/lines.mjs +536 -0
  76. package/dist/esm/preview/liquid-contours.mjs +512 -0
  77. package/dist/esm/preview/long-shadows.mjs +437 -0
  78. package/dist/esm/preview/lut.mjs +601 -0
  79. package/dist/esm/preview/magnify.mjs +403 -0
  80. package/dist/esm/preview/mirror.mjs +341 -0
  81. package/dist/esm/preview/noise-displacement.mjs +584 -0
  82. package/dist/esm/preview/noise.mjs +318 -0
  83. package/dist/esm/preview/outline.mjs +725 -0
  84. package/dist/esm/preview/page-turn.mjs +302 -0
  85. package/dist/esm/preview/paper.mjs +1249 -0
  86. package/dist/esm/preview/pattern.mjs +6 -0
  87. package/dist/esm/preview/pixel-dissolve.mjs +360 -0
  88. package/dist/esm/preview/pixelate.mjs +249 -0
  89. package/dist/esm/preview/radial-progressive-blur.mjs +582 -0
  90. package/dist/esm/preview/radial-progressive-pixelate.mjs +220 -0
  91. package/dist/esm/preview/radial-wipe.mjs +224 -0
  92. package/dist/esm/preview/rain-fall.mjs +114 -0
  93. package/dist/esm/preview/region-blur.mjs +500 -0
  94. package/dist/esm/preview/rings.mjs +8 -0
  95. package/dist/esm/preview/roughen-edges.mjs +590 -0
  96. package/dist/esm/preview/saturation.mjs +86 -0
  97. package/dist/esm/preview/scale.mjs +109 -0
  98. package/dist/esm/preview/scanlines.mjs +362 -0
  99. package/dist/esm/preview/shadows-highlights.mjs +284 -0
  100. package/dist/esm/preview/shatter.mjs +868 -0
  101. package/dist/esm/preview/shine.mjs +368 -0
  102. package/dist/esm/preview/shrinkwrap.mjs +769 -0
  103. package/dist/esm/preview/skew.mjs +300 -0
  104. package/dist/esm/preview/snow-fall.mjs +170 -0
  105. package/dist/esm/preview/speckle.mjs +356 -0
  106. package/dist/esm/preview/sphere.mjs +252 -0
  107. package/dist/esm/preview/starburst.mjs +8 -0
  108. package/dist/esm/preview/tear.mjs +375 -0
  109. package/dist/esm/preview/thermal-vision.mjs +387 -0
  110. package/dist/esm/preview/tile.mjs +7 -0
  111. package/dist/esm/preview/tint.mjs +125 -0
  112. package/dist/esm/preview/translate.mjs +151 -0
  113. package/dist/esm/preview/turbulent-displace.mjs +613 -0
  114. package/dist/esm/preview/tv-signal-off.mjs +308 -0
  115. package/dist/esm/preview/venetian-blinds.mjs +341 -0
  116. package/dist/esm/preview/vibrance.mjs +254 -0
  117. package/dist/esm/preview/vignette.mjs +458 -0
  118. package/dist/esm/preview/wave.mjs +384 -0
  119. package/dist/esm/preview/waves.mjs +599 -0
  120. package/dist/esm/preview/white-balance.mjs +280 -0
  121. package/dist/esm/preview/white-noise.mjs +244 -0
  122. package/dist/esm/preview/zigzag.mjs +8 -0
  123. package/dist/esm/preview/zoom-blur.mjs +389 -0
  124. package/dist/lightning/geometry.d.ts +10 -0
  125. package/dist/lightning/index.d.ts +4 -0
  126. package/dist/lightning/mask.d.ts +2 -0
  127. package/dist/lightning/params.d.ts +259 -0
  128. package/dist/lightning/shaders.d.ts +2 -0
  129. package/dist/lightning.d.ts +2 -0
  130. package/dist/magnify/shader.d.ts +1 -0
  131. package/dist/magnify/webgpu-shader.d.ts +1 -0
  132. package/dist/magnify.d.ts +28 -0
  133. package/package.json +30 -6
@@ -0,0 +1,1249 @@
1
+ import {
2
+ assertOptionalFiniteNumber,
3
+ validateUnitInterval,
4
+ validateNonNegative,
5
+ parseColorRgba
6
+ } from "./index-wxhvgv2s.mjs";
7
+ import {
8
+ WEBGPU_SINGLE_PASS_VERTEX,
9
+ setupWebGpuSinglePass,
10
+ cleanupWebGpuSinglePass,
11
+ applyWebGpuSinglePass
12
+ } from "./index-tvfexb7s.mjs";
13
+ import {
14
+ assertEffectParamsObject,
15
+ assertOptionalColor
16
+ } from "./index-4fvp93ps.mjs";
17
+
18
+ // src/paper.ts
19
+ import { Internals } from "remotion";
20
+
21
+ // src/paper-webgpu-shader.ts
22
+ var PAPER_WEBGPU_SHADER = `
23
+ diagnostic(off, derivative_uniformity);
24
+ ${WEBGPU_SINGLE_PASS_VERTEX}
25
+ @group(0) @binding(0) var source: texture_2d<f32>;
26
+ @group(0) @binding(1) var sourceSampler: sampler;
27
+ @group(0) @binding(2) var<uniform> params: Params;
28
+ struct Params { size: vec2f, aspectRatio: f32, amount: f32, colorFront: vec4f, colorBack: vec4f, contrast: f32, roughness: f32, fiber: f32, fiberSize: f32, crumples: f32, crumpleSize: f32, folds: f32, foldCount: f32, drops: f32, fade: f32, seed: f32, scale: f32, offsetY: f32, }
29
+ @group(0) @binding(3) var noiseTexture: texture_2d<f32>;
30
+ const TWO_PI=6.28318530718;
31
+ const PI=3.14159265358979323846;
32
+ fn getUvFrame(uv: vec2f) -> f32 {
33
+
34
+ var aax: f32 = 2.0 * fwidth(uv.x);
35
+ var aay: f32 = 2.0 * fwidth(uv.y);
36
+
37
+ var left: f32 = smoothstep(0.0, aax, uv.x);
38
+ var right: f32 = 1.0 - smoothstep(1.0 - aax, 1.0, uv.x);
39
+ var bottom: f32 = smoothstep(0.0, aay, uv.y);
40
+ var top: f32 = 1.0 - smoothstep(1.0 - aay, 1.0, uv.y);
41
+
42
+ return left * right * bottom * top;
43
+ }
44
+
45
+ fn rotate(uv: vec2f, th: f32) -> vec2f {
46
+
47
+ return mat2x2f(vec2f(cos(th), sin(th)),vec2f(-sin(th), cos(th))) * uv;
48
+ }
49
+
50
+ fn seedOffset(salt: f32) -> vec2f {
51
+
52
+ var seeded: f32 = params.seed + salt;
53
+ return fract(
54
+ sin(
55
+ vec2f(
56
+ seeded * 12.9898 + 78.233,
57
+ seeded * 39.3468 + 11.135
58
+ )
59
+ ) * 43758.5453
60
+ );
61
+ }
62
+
63
+ fn randomR(p: vec2f) -> f32 {
64
+
65
+ var uv: vec2f = floor(p) / 100.0 + vec2f(0.5);
66
+ return textureLoad(noiseTexture,vec2i(floor(fract(uv)*vec2f(textureDimensions(noiseTexture)))),0).r;
67
+ }
68
+
69
+ fn valueNoise(st: vec2f) -> f32 {
70
+
71
+ var i: vec2f = floor(st);
72
+ var f: vec2f = fract(st);
73
+ var a: f32 = randomR(i);
74
+ var b: f32 = randomR(i + vec2f(1.0, 0.0));
75
+ var c: f32 = randomR(i + vec2f(0.0, 1.0));
76
+ var d: f32 = randomR(i + vec2f(1.0, 1.0));
77
+ var u: vec2f = f * f * (vec2f(3.0) - 2.0 * f);
78
+ var x1: f32 = mix(a, b, u.x);
79
+ var x2: f32 = mix(c, d, u.x);
80
+ return mix(x1, x2, u.y);
81
+ }
82
+
83
+ fn fbm(nInput: vec2f) -> f32 {
84
+ var n=nInput;
85
+ var total: f32 = 0.0;
86
+ var amplitude: f32 = 0.4;
87
+ for (var i: i32 = 0; i < 3; i++) {
88
+ total += valueNoise(n) * amplitude;
89
+ n *= 1.99;
90
+ amplitude *= 0.65;
91
+ }
92
+ return total;
93
+ }
94
+
95
+ fn randomG(p: vec2f) -> f32 {
96
+
97
+ var uv: vec2f = floor(p) / 50.0 + vec2f(0.5);
98
+ return textureLoad(noiseTexture,vec2i(floor(fract(uv)*vec2f(textureDimensions(noiseTexture)))),0).g;
99
+ }
100
+
101
+ fn roughnessNoise(pInput: vec2f) -> f32 {
102
+ var p=pInput;
103
+ p *= 0.1;
104
+ var o: f32 = 0.0;
105
+ for (var i: f32 = 1.0; i < 4.0; i += 1.0) {
106
+ var w: vec4f = vec4f(floor(p), ceil(p));
107
+ var f: vec2f = fract(p);
108
+ o += mix(
109
+ mix(randomG(w.xy), randomG(w.xw), f.y),
110
+ mix(randomG(w.zy), randomG(w.zw), f.y),
111
+ f.x
112
+ );
113
+ o += 0.2 / exp(2.0 * abs(sin(0.2 * p.x + 0.5 * p.y)));
114
+ p *= 2.1;
115
+ }
116
+ return o / 3.0;
117
+ }
118
+
119
+ fn fiberRandom(p: vec2f) -> f32 {
120
+
121
+ var uv: vec2f = floor(p) / 100.0;
122
+ return textureLoad(noiseTexture,vec2i(floor(fract(uv)*vec2f(textureDimensions(noiseTexture)))),0).b;
123
+ }
124
+
125
+ fn fiberValueNoise(st: vec2f) -> f32 {
126
+
127
+ var i: vec2f = floor(st);
128
+ var f: vec2f = fract(st);
129
+ var a: f32 = fiberRandom(i);
130
+ var b: f32 = fiberRandom(i + vec2f(1.0, 0.0));
131
+ var c: f32 = fiberRandom(i + vec2f(0.0, 1.0));
132
+ var d: f32 = fiberRandom(i + vec2f(1.0, 1.0));
133
+ var u: vec2f = f * f * (vec2f(3.0) - 2.0 * f);
134
+ var x1: f32 = mix(a, b, u.x);
135
+ var x2: f32 = mix(c, d, u.x);
136
+ return mix(x1, x2, u.y);
137
+ }
138
+
139
+ fn fiberNoiseFbm(nInput: vec2f, seedOffset: vec2f) -> f32 {
140
+ var n=nInput;
141
+ var total: f32 = 0.0;
142
+ var amplitude: f32 = 1.0;
143
+ for (var i: i32 = 0; i < 4; i++) {
144
+ n = rotate(n, 0.7);
145
+ total += fiberValueNoise(n + seedOffset) * amplitude;
146
+ n *= 2.0;
147
+ amplitude *= 0.6;
148
+ }
149
+ return total;
150
+ }
151
+
152
+ fn fiberNoise(uv: vec2f, seedOffset: vec2f) -> f32 {
153
+
154
+ var epsilon: f32 = 0.001;
155
+ var n1: f32 = fiberNoiseFbm(uv + vec2f(epsilon, 0.0), seedOffset);
156
+ var n2: f32 = fiberNoiseFbm(uv - vec2f(epsilon, 0.0), seedOffset);
157
+ var n3: f32 = fiberNoiseFbm(uv + vec2f(0.0, epsilon), seedOffset);
158
+ var n4: f32 = fiberNoiseFbm(uv - vec2f(0.0, epsilon), seedOffset);
159
+ return length(vec2f(n1 - n2, n3 - n4)) / (2.0 * epsilon);
160
+ }
161
+
162
+ fn randomGB(p: vec2f) -> vec2f {
163
+
164
+ var uv: vec2f = floor(p) / 50.0 + vec2f(0.5);
165
+ return textureLoad(noiseTexture,vec2i(floor(fract(uv)*vec2f(textureDimensions(noiseTexture)))),0).gb;
166
+ }
167
+
168
+ fn crumpledNoise(t: vec2f, pw: f32) -> f32 {
169
+
170
+ var p: vec2f = floor(t);
171
+ var wsum: f32 = 0.0;
172
+ var cl: f32 = 0.0;
173
+ for (var y: i32 = -1; y < 2; y += 1) {
174
+ for (var x: i32 = -1; x < 2; x += 1) {
175
+ var b: vec2f = vec2f(f32(x), f32(y));
176
+ var q: vec2f = b + p;
177
+ var q2: vec2f = q - floor(q / 8.0) * 8.0;
178
+ var c: vec2f = q + randomGB(q2);
179
+ var r: vec2f = c - t;
180
+ var w: f32 =
181
+ pow(smoothstep(0.0, 1.0, 1.0 - abs(r.x)), pw) *
182
+ pow(smoothstep(0.0, 1.0, 1.0 - abs(r.y)), pw);
183
+ cl += (0.5 + 0.5 * sin((q2.x + q2.y * 5.0) * 8.0)) * w;
184
+ wsum += w;
185
+ }
186
+ }
187
+ return pow(select(0.0, cl / select(1.0, wsum, wsum != 0.0), wsum != 0.0), 0.5) * 2.0;
188
+ }
189
+
190
+ fn crumplesShape(uv: vec2f) -> f32 {
191
+
192
+ return crumpledNoise(uv * 0.25, 16.0) * crumpledNoise(uv * 0.5, 2.0);
193
+ }
194
+
195
+ fn folds(uv: vec2f) -> vec2f {
196
+
197
+ var pp: vec3f = vec3f(0.0);
198
+ var l: f32 = 9.0;
199
+ for (var i: f32 = 0.0; i < 15.0; i += 1.0) {
200
+ if (i >= params.foldCount) {
201
+ break;
202
+ }
203
+ var rand: vec2f = randomGB(vec2f(i, i * params.seed));
204
+ var an: f32 = rand.x * TWO_PI;
205
+ var p: vec2f = vec2f(cos(an), sin(an)) * rand.y;
206
+ var dist: f32 = distance(uv, p);
207
+ l = min(l, dist);
208
+
209
+ if (l == dist) {
210
+ pp = vec3f(uv-p,pp.z);
211
+ pp.z = dist;
212
+ }
213
+ }
214
+ return mix(pp.xy, vec2f(0.0), pow(pp.z, 0.25));
215
+ }
216
+
217
+ fn drops(uv: vec2f) -> f32 {
218
+
219
+ var iDropsUV: vec2f = floor(uv);
220
+ var fDropsUV: vec2f = fract(uv);
221
+ var dropsMinDist: f32 = 1.0;
222
+ for (var j: i32 = -1; j <= 1; j++) {
223
+ for (var i: i32 = -1; i <= 1; i++) {
224
+ var neighbor: vec2f = vec2f(f32(i), f32(j));
225
+ var offset: vec2f = randomGB(iDropsUV + neighbor);
226
+ offset = vec2f(0.5) + 0.5 * sin(vec2f(10.0 * params.seed) + TWO_PI * offset);
227
+ var pos: vec2f = neighbor + offset - fDropsUV;
228
+ var dist: f32 = length(pos);
229
+ dropsMinDist = min(dropsMinDist, dropsMinDist * dist);
230
+ }
231
+ }
232
+ return 1.0 - smoothstep(0.05, 0.09, pow(dropsMinDist, 0.5));
233
+ }
234
+
235
+ @fragment fn fragment(input: VertexOutput) -> @location(0) vec4f {
236
+ let pixel=vec2f(input.position.x,params.size.y+params.offsetY-input.position.y);
237
+ let vUv=pixel/params.size;
238
+ var color: vec4f = textureSampleLevel(source,sourceSampler,vec2f(vUv.x,1.0-vUv.y),0);
239
+ var sourceAlpha: f32 = color.a;
240
+
241
+ if (sourceAlpha <= 0.001 || params.amount <= 0.0) {
242
+ return color;
243
+ }
244
+
245
+ var sourceRgb: vec3f = color.rgb / sourceAlpha;
246
+ var imageUV: vec2f = vUv;
247
+ var patternUV: vec2f = vUv - vec2f(0.5);
248
+ patternUV /= max(params.scale, 0.001);
249
+ patternUV = 5.0 * (patternUV * vec2f(params.aspectRatio, 1.0));
250
+
251
+ var roughnessUv: vec2f =
252
+ 1.5 * (pixel - 0.5 * params.size) +
253
+ 128.0 * seedOffset(1.0);
254
+ var roughness: f32 =
255
+ roughnessNoise(roughnessUv + vec2f(1.0, 0.0)) -
256
+ roughnessNoise(roughnessUv - vec2f(1.0, 0.0));
257
+
258
+ var crumplesUV: vec2f =
259
+ fract(patternUV * 0.02 / max(params.crumpleSize, 0.001) - vec2f(params.seed)) * 32.0;
260
+ var crumples: f32 =
261
+ params.crumples *
262
+ (crumplesShape(crumplesUV + vec2f(0.05, 0.0)) -
263
+ crumplesShape(crumplesUV));
264
+
265
+ var fiberUV: vec2f = 2.0 / max(params.fiberSize, 0.001) * patternUV;
266
+ var fiber: f32 = fiberNoise(fiberUV, 64.0 * seedOffset(2.0));
267
+ fiber = 0.5 * params.fiber * (fiber - 1.0);
268
+
269
+ var normal: vec2f = vec2f(0.0);
270
+ var normalImage: vec2f = vec2f(0.0);
271
+
272
+ var foldsUV: vec2f = patternUV * 0.12;
273
+ foldsUV = rotate(foldsUV, 4.0 * params.seed);
274
+ var w: vec2f = folds(foldsUV);
275
+ foldsUV = rotate(foldsUV + vec2f(0.007 * cos(params.seed)), 0.01 * sin(params.seed));
276
+ var w2: vec2f = folds(foldsUV);
277
+
278
+ var dropPattern: f32 = params.drops * drops(patternUV * 2.0);
279
+
280
+ var fade: f32 = params.fade * fbm(0.17 * patternUV + vec2f(10.0 * params.seed));
281
+ fade = clamp(8.0 * fade * fade * fade, 0.0, 1.0);
282
+
283
+ w = mix(w, vec2f(0.0), fade);
284
+ w2 = mix(w2, vec2f(0.0), fade);
285
+ crumples = mix(crumples, 0.0, fade);
286
+ dropPattern = mix(dropPattern, 0.0, fade);
287
+ fiber *= mix(1.0, 0.5, fade);
288
+ roughness *= mix(1.0, 0.5, fade);
289
+
290
+ normal += params.folds * min(5.0 * params.contrast, 1.0) * 4.0 * max(vec2f(0.0), w + w2);
291
+ normalImage += params.folds * 2.0 * w;
292
+ normal += vec2f(crumples);
293
+ normalImage += vec2f(1.5 * crumples);
294
+ normal += vec2f(3.0 * dropPattern);
295
+ normalImage += vec2f(0.2 * dropPattern);
296
+ normal += vec2f(params.roughness * 1.5 * roughness);
297
+ normal += vec2f(fiber);
298
+ normalImage += vec2f(params.roughness * 0.75 * roughness);
299
+ normalImage += vec2f(0.2 * fiber);
300
+
301
+ var lightPos: vec3f = vec3f(1.0, 2.0, 1.0);
302
+ var res: f32 = dot(
303
+ normalize(vec3f(normal, 9.5 - 9.0 * pow(params.contrast, 0.1))),
304
+ normalize(lightPos)
305
+ );
306
+
307
+ imageUV += 0.02 * normalImage;
308
+ var frame: f32 = getUvFrame(imageUV);
309
+ var displacedSource: vec4f = textureSampleLevel(source,sourceSampler,clamp(vec2f(imageUV.x,1.0-imageUV.y),vec2f(0),vec2f(1)),0);
310
+ var displacedRgb: vec3f = select(sourceRgb,displacedSource.rgb / max(displacedSource.a,0.001),displacedSource.a > 0.001);
311
+ displacedRgb += vec3f(0.6 * pow(params.contrast, 0.4) * (res - 0.7));
312
+
313
+ var frontRgb: vec3f = mix(vec3f(1.0), params.colorFront.rgb, params.colorFront.a);
314
+ var backRgb: vec3f = mix(vec3f(1.0), params.colorBack.rgb, params.colorBack.a);
315
+ var paperTone: vec3f = mix(backRgb, frontRgb, clamp(res, 0.0, 1.0));
316
+ var texturedRgb: vec3f = displacedRgb * (0.72 + 0.42 * res);
317
+ texturedRgb = mix(texturedRgb, texturedRgb * paperTone, 0.65);
318
+ texturedRgb -= vec3f(0.007 * dropPattern);
319
+ texturedRgb = mix(sourceRgb, texturedRgb, frame);
320
+
321
+ var finalRgb: vec3f = mix(sourceRgb, clamp(texturedRgb, vec3f(0.0), vec3f(1.0)), params.amount);
322
+ return vec4f(finalRgb * sourceAlpha, sourceAlpha);
323
+ }
324
+
325
+ `;
326
+ var PAPER_CROP_WEBGPU_SHADER = `
327
+ ${WEBGPU_SINGLE_PASS_VERTEX}
328
+ @group(0) @binding(0) var source: texture_2d<f32>;
329
+ @group(0) @binding(1) var sourceSampler: sampler;
330
+ @group(0) @binding(2) var<uniform> params: vec4f;
331
+ @fragment fn fragment(input: VertexOutput) -> @location(0) vec4f {
332
+ return textureLoad(source,vec2i(input.position.xy)+vec2i(0,1),0);
333
+ }
334
+ `;
335
+
336
+ // src/paper.ts
337
+ var { createEffect, createWebGL2ContextError } = Internals;
338
+ var DEFAULT_AMOUNT = 1;
339
+ var DEFAULT_COLOR_FRONT = "#9fadbc";
340
+ var DEFAULT_COLOR_BACK = "#ffffff";
341
+ var DEFAULT_CONTRAST = 0.3;
342
+ var DEFAULT_ROUGHNESS = 0.4;
343
+ var DEFAULT_FIBER = 0.3;
344
+ var DEFAULT_FIBER_SIZE = 0.2;
345
+ var DEFAULT_CRUMPLES = 0.3;
346
+ var DEFAULT_CRUMPLE_SIZE = 0.35;
347
+ var DEFAULT_FOLDS = 0.65;
348
+ var DEFAULT_FOLD_COUNT = 5;
349
+ var DEFAULT_DROPS = 0.2;
350
+ var DEFAULT_FADE = 0;
351
+ var DEFAULT_SEED = 6;
352
+ var DEFAULT_SCALE = 0.6;
353
+ var MAX_FOLD_COUNT = 15;
354
+ var MAX_SEED = 1000;
355
+ var NOISE_TEXTURE_SIZE = 256;
356
+ var paperSchema = {
357
+ amount: {
358
+ type: "number",
359
+ min: 0,
360
+ max: 1,
361
+ step: 0.01,
362
+ default: DEFAULT_AMOUNT,
363
+ description: "Amount",
364
+ hiddenFromList: false
365
+ },
366
+ colorFront: {
367
+ type: "color",
368
+ default: DEFAULT_COLOR_FRONT,
369
+ description: "Front color"
370
+ },
371
+ colorBack: {
372
+ type: "color",
373
+ default: DEFAULT_COLOR_BACK,
374
+ description: "Back color"
375
+ },
376
+ contrast: {
377
+ type: "number",
378
+ min: 0,
379
+ max: 1,
380
+ step: 0.01,
381
+ default: DEFAULT_CONTRAST,
382
+ description: "Contrast",
383
+ hiddenFromList: false
384
+ },
385
+ roughness: {
386
+ type: "number",
387
+ min: 0,
388
+ max: 1,
389
+ step: 0.01,
390
+ default: DEFAULT_ROUGHNESS,
391
+ description: "Roughness",
392
+ hiddenFromList: false
393
+ },
394
+ fiber: {
395
+ type: "number",
396
+ min: 0,
397
+ max: 1,
398
+ step: 0.01,
399
+ default: DEFAULT_FIBER,
400
+ description: "Fiber",
401
+ hiddenFromList: false
402
+ },
403
+ fiberSize: {
404
+ type: "number",
405
+ min: 0.01,
406
+ max: 1,
407
+ step: 0.01,
408
+ default: DEFAULT_FIBER_SIZE,
409
+ description: "Fiber size",
410
+ hiddenFromList: false
411
+ },
412
+ crumples: {
413
+ type: "number",
414
+ min: 0,
415
+ max: 1,
416
+ step: 0.01,
417
+ default: DEFAULT_CRUMPLES,
418
+ description: "Crumples",
419
+ hiddenFromList: false
420
+ },
421
+ crumpleSize: {
422
+ type: "number",
423
+ min: 0.01,
424
+ max: 1,
425
+ step: 0.01,
426
+ default: DEFAULT_CRUMPLE_SIZE,
427
+ description: "Crumple size",
428
+ hiddenFromList: false
429
+ },
430
+ folds: {
431
+ type: "number",
432
+ min: 0,
433
+ max: 1,
434
+ step: 0.01,
435
+ default: DEFAULT_FOLDS,
436
+ description: "Folds",
437
+ hiddenFromList: false
438
+ },
439
+ foldCount: {
440
+ type: "number",
441
+ min: 0,
442
+ max: MAX_FOLD_COUNT,
443
+ step: 1,
444
+ default: DEFAULT_FOLD_COUNT,
445
+ description: "Fold count",
446
+ hiddenFromList: false
447
+ },
448
+ drops: {
449
+ type: "number",
450
+ min: 0,
451
+ max: 1,
452
+ step: 0.01,
453
+ default: DEFAULT_DROPS,
454
+ description: "Drops",
455
+ hiddenFromList: false
456
+ },
457
+ fade: {
458
+ type: "number",
459
+ min: 0,
460
+ max: 1,
461
+ step: 0.01,
462
+ default: DEFAULT_FADE,
463
+ description: "Fade",
464
+ hiddenFromList: false
465
+ },
466
+ seed: {
467
+ type: "number",
468
+ min: 0,
469
+ max: MAX_SEED,
470
+ step: 0.01,
471
+ default: DEFAULT_SEED,
472
+ description: "Seed",
473
+ hiddenFromList: false
474
+ },
475
+ scale: {
476
+ type: "number",
477
+ min: 0.01,
478
+ max: 4,
479
+ step: 0.01,
480
+ default: DEFAULT_SCALE,
481
+ description: "Scale",
482
+ hiddenFromList: false
483
+ }
484
+ };
485
+ var resolve = (p) => ({
486
+ amount: p.amount ?? DEFAULT_AMOUNT,
487
+ colorFront: p.colorFront ?? DEFAULT_COLOR_FRONT,
488
+ colorBack: p.colorBack ?? DEFAULT_COLOR_BACK,
489
+ contrast: p.contrast ?? DEFAULT_CONTRAST,
490
+ roughness: p.roughness ?? DEFAULT_ROUGHNESS,
491
+ fiber: p.fiber ?? DEFAULT_FIBER,
492
+ fiberSize: p.fiberSize ?? DEFAULT_FIBER_SIZE,
493
+ crumples: p.crumples ?? DEFAULT_CRUMPLES,
494
+ crumpleSize: p.crumpleSize ?? DEFAULT_CRUMPLE_SIZE,
495
+ folds: p.folds ?? DEFAULT_FOLDS,
496
+ foldCount: p.foldCount ?? DEFAULT_FOLD_COUNT,
497
+ drops: p.drops ?? DEFAULT_DROPS,
498
+ fade: p.fade ?? DEFAULT_FADE,
499
+ seed: p.seed ?? DEFAULT_SEED,
500
+ scale: p.scale ?? DEFAULT_SCALE
501
+ });
502
+ var validateAtMost = (value, max, name) => {
503
+ if (value > max) {
504
+ throw new TypeError(`"${name}" must be <= ${max}, but got ${JSON.stringify(value)}`);
505
+ }
506
+ };
507
+ var validatePositiveUnitInterval = (value, name) => {
508
+ if (value <= 0) {
509
+ throw new TypeError(`"${name}" must be greater than 0, but got ${JSON.stringify(value)}`);
510
+ }
511
+ validateAtMost(value, 1, name);
512
+ };
513
+ var validatePaperParams = (params) => {
514
+ assertEffectParamsObject(params, "Paper");
515
+ assertOptionalFiniteNumber(params.amount, "amount");
516
+ assertOptionalColor(params.colorFront, "colorFront");
517
+ assertOptionalColor(params.colorBack, "colorBack");
518
+ assertOptionalFiniteNumber(params.contrast, "contrast");
519
+ assertOptionalFiniteNumber(params.roughness, "roughness");
520
+ assertOptionalFiniteNumber(params.fiber, "fiber");
521
+ assertOptionalFiniteNumber(params.fiberSize, "fiberSize");
522
+ assertOptionalFiniteNumber(params.crumples, "crumples");
523
+ assertOptionalFiniteNumber(params.crumpleSize, "crumpleSize");
524
+ assertOptionalFiniteNumber(params.folds, "folds");
525
+ assertOptionalFiniteNumber(params.foldCount, "foldCount");
526
+ assertOptionalFiniteNumber(params.drops, "drops");
527
+ assertOptionalFiniteNumber(params.fade, "fade");
528
+ assertOptionalFiniteNumber(params.seed, "seed");
529
+ assertOptionalFiniteNumber(params.scale, "scale");
530
+ const r = resolve(params);
531
+ validateUnitInterval(r.amount, "amount");
532
+ validateUnitInterval(r.contrast, "contrast");
533
+ validateUnitInterval(r.roughness, "roughness");
534
+ validateUnitInterval(r.fiber, "fiber");
535
+ validatePositiveUnitInterval(r.fiberSize, "fiberSize");
536
+ validateUnitInterval(r.crumples, "crumples");
537
+ validatePositiveUnitInterval(r.crumpleSize, "crumpleSize");
538
+ validateUnitInterval(r.folds, "folds");
539
+ validateNonNegative(r.foldCount, "foldCount");
540
+ validateAtMost(r.foldCount, MAX_FOLD_COUNT, "foldCount");
541
+ validateUnitInterval(r.drops, "drops");
542
+ validateUnitInterval(r.fade, "fade");
543
+ validateNonNegative(r.seed, "seed");
544
+ validateAtMost(r.seed, MAX_SEED, "seed");
545
+ if (r.scale <= 0) {
546
+ throw new TypeError(`"scale" must be greater than 0, but got ${JSON.stringify(r.scale)}`);
547
+ }
548
+ validateAtMost(r.scale, 4, "scale");
549
+ };
550
+ var PAPER_VS = `#version 300 es
551
+ in vec2 aPos;
552
+ in vec2 aUv;
553
+ out vec2 vUv;
554
+
555
+ void main() {
556
+ vUv = aUv;
557
+ gl_Position = vec4(aPos, 0.0, 1.0);
558
+ }
559
+ `;
560
+ var PAPER_FS = `#version 300 es
561
+ precision highp float;
562
+
563
+ in vec2 vUv;
564
+ out vec4 fragColor;
565
+
566
+ uniform sampler2D uSource;
567
+ uniform vec2 uResolution;
568
+ uniform float uImageAspectRatio;
569
+
570
+ uniform vec4 uColorFront;
571
+ uniform vec4 uColorBack;
572
+ uniform float uAmount;
573
+ uniform float uContrast;
574
+ uniform float uRoughness;
575
+ uniform float uFiber;
576
+ uniform float uFiberSize;
577
+ uniform float uCrumples;
578
+ uniform float uCrumpleSize;
579
+ uniform float uFolds;
580
+ uniform float uFoldCount;
581
+ uniform float uDrops;
582
+ uniform float uFade;
583
+ uniform float uSeed;
584
+ uniform float uScale;
585
+ uniform sampler2D uNoiseTexture;
586
+
587
+ #define TWO_PI 6.28318530718
588
+ #define PI 3.14159265358979323846
589
+
590
+ float getUvFrame(vec2 uv) {
591
+ float aax = 2.0 * fwidth(uv.x);
592
+ float aay = 2.0 * fwidth(uv.y);
593
+
594
+ float left = smoothstep(0.0, aax, uv.x);
595
+ float right = 1.0 - smoothstep(1.0 - aax, 1.0, uv.x);
596
+ float bottom = smoothstep(0.0, aay, uv.y);
597
+ float top = 1.0 - smoothstep(1.0 - aay, 1.0, uv.y);
598
+
599
+ return left * right * bottom * top;
600
+ }
601
+
602
+ vec2 rotate(vec2 uv, float th) {
603
+ return mat2(cos(th), sin(th), -sin(th), cos(th)) * uv;
604
+ }
605
+
606
+ vec2 seedOffset(float salt) {
607
+ float seeded = uSeed + salt;
608
+ return fract(
609
+ sin(
610
+ vec2(
611
+ seeded * 12.9898 + 78.233,
612
+ seeded * 39.3468 + 11.135
613
+ )
614
+ ) * 43758.5453
615
+ );
616
+ }
617
+
618
+ float randomR(vec2 p) {
619
+ vec2 uv = floor(p) / 100.0 + 0.5;
620
+ return texture(uNoiseTexture, fract(uv)).r;
621
+ }
622
+
623
+ float valueNoise(vec2 st) {
624
+ vec2 i = floor(st);
625
+ vec2 f = fract(st);
626
+ float a = randomR(i);
627
+ float b = randomR(i + vec2(1.0, 0.0));
628
+ float c = randomR(i + vec2(0.0, 1.0));
629
+ float d = randomR(i + vec2(1.0, 1.0));
630
+ vec2 u = f * f * (3.0 - 2.0 * f);
631
+ float x1 = mix(a, b, u.x);
632
+ float x2 = mix(c, d, u.x);
633
+ return mix(x1, x2, u.y);
634
+ }
635
+
636
+ float fbm(vec2 n) {
637
+ float total = 0.0;
638
+ float amplitude = 0.4;
639
+ for (int i = 0; i < 3; i++) {
640
+ total += valueNoise(n) * amplitude;
641
+ n *= 1.99;
642
+ amplitude *= 0.65;
643
+ }
644
+ return total;
645
+ }
646
+
647
+ float randomG(vec2 p) {
648
+ vec2 uv = floor(p) / 50.0 + 0.5;
649
+ return texture(uNoiseTexture, fract(uv)).g;
650
+ }
651
+
652
+ float roughnessNoise(vec2 p) {
653
+ p *= 0.1;
654
+ float o = 0.0;
655
+ for (float i = 0.0; ++i < 4.0; p *= 2.1) {
656
+ vec4 w = vec4(floor(p), ceil(p));
657
+ vec2 f = fract(p);
658
+ o += mix(
659
+ mix(randomG(w.xy), randomG(w.xw), f.y),
660
+ mix(randomG(w.zy), randomG(w.zw), f.y),
661
+ f.x
662
+ );
663
+ o += 0.2 / exp(2.0 * abs(sin(0.2 * p.x + 0.5 * p.y)));
664
+ }
665
+ return o / 3.0;
666
+ }
667
+
668
+ float fiberRandom(vec2 p) {
669
+ vec2 uv = floor(p) / 100.0;
670
+ return texture(uNoiseTexture, fract(uv)).b;
671
+ }
672
+
673
+ float fiberValueNoise(vec2 st) {
674
+ vec2 i = floor(st);
675
+ vec2 f = fract(st);
676
+ float a = fiberRandom(i);
677
+ float b = fiberRandom(i + vec2(1.0, 0.0));
678
+ float c = fiberRandom(i + vec2(0.0, 1.0));
679
+ float d = fiberRandom(i + vec2(1.0, 1.0));
680
+ vec2 u = f * f * (3.0 - 2.0 * f);
681
+ float x1 = mix(a, b, u.x);
682
+ float x2 = mix(c, d, u.x);
683
+ return mix(x1, x2, u.y);
684
+ }
685
+
686
+ float fiberNoiseFbm(in vec2 n, vec2 seedOffset) {
687
+ float total = 0.0;
688
+ float amplitude = 1.0;
689
+ for (int i = 0; i < 4; i++) {
690
+ n = rotate(n, 0.7);
691
+ total += fiberValueNoise(n + seedOffset) * amplitude;
692
+ n *= 2.0;
693
+ amplitude *= 0.6;
694
+ }
695
+ return total;
696
+ }
697
+
698
+ float fiberNoise(vec2 uv, vec2 seedOffset) {
699
+ float epsilon = 0.001;
700
+ float n1 = fiberNoiseFbm(uv + vec2(epsilon, 0.0), seedOffset);
701
+ float n2 = fiberNoiseFbm(uv - vec2(epsilon, 0.0), seedOffset);
702
+ float n3 = fiberNoiseFbm(uv + vec2(0.0, epsilon), seedOffset);
703
+ float n4 = fiberNoiseFbm(uv - vec2(0.0, epsilon), seedOffset);
704
+ return length(vec2(n1 - n2, n3 - n4)) / (2.0 * epsilon);
705
+ }
706
+
707
+ vec2 randomGB(vec2 p) {
708
+ vec2 uv = floor(p) / 50.0 + 0.5;
709
+ return texture(uNoiseTexture, fract(uv)).gb;
710
+ }
711
+
712
+ float crumpledNoise(vec2 t, float pw) {
713
+ vec2 p = floor(t);
714
+ float wsum = 0.0;
715
+ float cl = 0.0;
716
+ for (int y = -1; y < 2; y += 1) {
717
+ for (int x = -1; x < 2; x += 1) {
718
+ vec2 b = vec2(float(x), float(y));
719
+ vec2 q = b + p;
720
+ vec2 q2 = q - floor(q / 8.0) * 8.0;
721
+ vec2 c = q + randomGB(q2);
722
+ vec2 r = c - t;
723
+ float w =
724
+ pow(smoothstep(0.0, 1.0, 1.0 - abs(r.x)), pw) *
725
+ pow(smoothstep(0.0, 1.0, 1.0 - abs(r.y)), pw);
726
+ cl += (0.5 + 0.5 * sin((q2.x + q2.y * 5.0) * 8.0)) * w;
727
+ wsum += w;
728
+ }
729
+ }
730
+ return pow(wsum != 0.0 ? cl / wsum : 0.0, 0.5) * 2.0;
731
+ }
732
+
733
+ float crumplesShape(vec2 uv) {
734
+ return crumpledNoise(uv * 0.25, 16.0) * crumpledNoise(uv * 0.5, 2.0);
735
+ }
736
+
737
+ vec2 folds(vec2 uv) {
738
+ vec3 pp = vec3(0.0);
739
+ float l = 9.0;
740
+ for (float i = 0.0; i < 15.0; i++) {
741
+ if (i >= uFoldCount) {
742
+ break;
743
+ }
744
+ vec2 rand = randomGB(vec2(i, i * uSeed));
745
+ float an = rand.x * TWO_PI;
746
+ vec2 p = vec2(cos(an), sin(an)) * rand.y;
747
+ float dist = distance(uv, p);
748
+ l = min(l, dist);
749
+
750
+ if (l == dist) {
751
+ pp.xy = uv - p.xy;
752
+ pp.z = dist;
753
+ }
754
+ }
755
+ return mix(pp.xy, vec2(0.0), pow(pp.z, 0.25));
756
+ }
757
+
758
+ float drops(vec2 uv) {
759
+ vec2 iDropsUV = floor(uv);
760
+ vec2 fDropsUV = fract(uv);
761
+ float dropsMinDist = 1.0;
762
+ for (int j = -1; j <= 1; j++) {
763
+ for (int i = -1; i <= 1; i++) {
764
+ vec2 neighbor = vec2(float(i), float(j));
765
+ vec2 offset = randomGB(iDropsUV + neighbor);
766
+ offset = 0.5 + 0.5 * sin(10.0 * uSeed + TWO_PI * offset);
767
+ vec2 pos = neighbor + offset - fDropsUV;
768
+ float dist = length(pos);
769
+ dropsMinDist = min(dropsMinDist, dropsMinDist * dist);
770
+ }
771
+ }
772
+ return 1.0 - smoothstep(0.05, 0.09, pow(dropsMinDist, 0.5));
773
+ }
774
+
775
+ void main() {
776
+ vec2 paperUv = gl_FragCoord.xy / uResolution;
777
+ vec4 source = texture(uSource, paperUv);
778
+ float sourceAlpha = source.a;
779
+
780
+ if (sourceAlpha <= 0.001 || uAmount <= 0.0) {
781
+ fragColor = source;
782
+ return;
783
+ }
784
+
785
+ vec3 sourceRgb = source.rgb / sourceAlpha;
786
+ vec2 imageUV = paperUv;
787
+ vec2 patternUV = paperUv - 0.5;
788
+ patternUV /= max(uScale, 0.001);
789
+ patternUV = 5.0 * (patternUV * vec2(uImageAspectRatio, 1.0));
790
+
791
+ vec2 roughnessUv =
792
+ 1.5 * (gl_FragCoord.xy - 0.5 * uResolution) +
793
+ 128.0 * seedOffset(1.0);
794
+ float roughness =
795
+ roughnessNoise(roughnessUv + vec2(1.0, 0.0)) -
796
+ roughnessNoise(roughnessUv - vec2(1.0, 0.0));
797
+
798
+ vec2 crumplesUV =
799
+ fract(patternUV * 0.02 / max(uCrumpleSize, 0.001) - uSeed) * 32.0;
800
+ float crumples =
801
+ uCrumples *
802
+ (crumplesShape(crumplesUV + vec2(0.05, 0.0)) -
803
+ crumplesShape(crumplesUV));
804
+
805
+ vec2 fiberUV = 2.0 / max(uFiberSize, 0.001) * patternUV;
806
+ float fiber = fiberNoise(fiberUV, 64.0 * seedOffset(2.0));
807
+ fiber = 0.5 * uFiber * (fiber - 1.0);
808
+
809
+ vec2 normal = vec2(0.0);
810
+ vec2 normalImage = vec2(0.0);
811
+
812
+ vec2 foldsUV = patternUV * 0.12;
813
+ foldsUV = rotate(foldsUV, 4.0 * uSeed);
814
+ vec2 w = folds(foldsUV);
815
+ foldsUV = rotate(foldsUV + 0.007 * cos(uSeed), 0.01 * sin(uSeed));
816
+ vec2 w2 = folds(foldsUV);
817
+
818
+ float dropPattern = uDrops * drops(patternUV * 2.0);
819
+
820
+ float fade = uFade * fbm(0.17 * patternUV + 10.0 * uSeed);
821
+ fade = clamp(8.0 * fade * fade * fade, 0.0, 1.0);
822
+
823
+ w = mix(w, vec2(0.0), fade);
824
+ w2 = mix(w2, vec2(0.0), fade);
825
+ crumples = mix(crumples, 0.0, fade);
826
+ dropPattern = mix(dropPattern, 0.0, fade);
827
+ fiber *= mix(1.0, 0.5, fade);
828
+ roughness *= mix(1.0, 0.5, fade);
829
+
830
+ normal.xy += uFolds * min(5.0 * uContrast, 1.0) * 4.0 * max(vec2(0.0), w + w2);
831
+ normalImage.xy += uFolds * 2.0 * w;
832
+ normal.xy += crumples;
833
+ normalImage.xy += 1.5 * crumples;
834
+ normal.xy += 3.0 * dropPattern;
835
+ normalImage.xy += 0.2 * dropPattern;
836
+ normal.xy += uRoughness * 1.5 * roughness;
837
+ normal.xy += fiber;
838
+ normalImage += uRoughness * 0.75 * roughness;
839
+ normalImage += 0.2 * fiber;
840
+
841
+ vec3 lightPos = vec3(1.0, 2.0, 1.0);
842
+ float res = dot(
843
+ normalize(vec3(normal, 9.5 - 9.0 * pow(uContrast, 0.1))),
844
+ normalize(lightPos)
845
+ );
846
+
847
+ imageUV += 0.02 * normalImage;
848
+ float frame = getUvFrame(imageUV);
849
+ vec4 displacedSource = texture(uSource, clamp(imageUV, vec2(0.0), vec2(1.0)));
850
+ vec3 displacedRgb = displacedSource.a > 0.001
851
+ ? displacedSource.rgb / displacedSource.a
852
+ : sourceRgb;
853
+ displacedRgb += 0.6 * pow(uContrast, 0.4) * (res - 0.7);
854
+
855
+ vec3 frontRgb = mix(vec3(1.0), uColorFront.rgb, uColorFront.a);
856
+ vec3 backRgb = mix(vec3(1.0), uColorBack.rgb, uColorBack.a);
857
+ vec3 paperTone = mix(backRgb, frontRgb, clamp(res, 0.0, 1.0));
858
+ vec3 texturedRgb = displacedRgb * (0.72 + 0.42 * res);
859
+ texturedRgb = mix(texturedRgb, texturedRgb * paperTone, 0.65);
860
+ texturedRgb -= 0.007 * dropPattern;
861
+ texturedRgb = mix(sourceRgb, texturedRgb, frame);
862
+
863
+ vec3 finalRgb = mix(sourceRgb, clamp(texturedRgb, 0.0, 1.0), uAmount);
864
+ fragColor = vec4(finalRgb * sourceAlpha, sourceAlpha);
865
+ }
866
+ `;
867
+ var compileShader = (gl, type, source) => {
868
+ const shader = gl.createShader(type);
869
+ if (!shader) {
870
+ throw new Error("Failed to create WebGL shader");
871
+ }
872
+ gl.shaderSource(shader, source);
873
+ gl.compileShader(shader);
874
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
875
+ const log = gl.getShaderInfoLog(shader);
876
+ gl.deleteShader(shader);
877
+ throw new Error(`Paper shader compile failed: ${log ?? "(no log)"}`);
878
+ }
879
+ return shader;
880
+ };
881
+ var linkProgram = (gl, vs, fs) => {
882
+ const program = gl.createProgram();
883
+ if (!program) {
884
+ throw new Error("Failed to create WebGL program");
885
+ }
886
+ gl.attachShader(program, vs);
887
+ gl.attachShader(program, fs);
888
+ gl.linkProgram(program);
889
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
890
+ const log = gl.getProgramInfoLog(program);
891
+ gl.deleteProgram(program);
892
+ throw new Error(`Paper program link failed: ${log ?? "(no log)"}`);
893
+ }
894
+ return program;
895
+ };
896
+ var createSourceTexture = (gl) => {
897
+ const texture = gl.createTexture();
898
+ if (!texture) {
899
+ throw new Error("Failed to create WebGL texture");
900
+ }
901
+ gl.bindTexture(gl.TEXTURE_2D, texture);
902
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
903
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
904
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
905
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
906
+ gl.bindTexture(gl.TEXTURE_2D, null);
907
+ return texture;
908
+ };
909
+ var initialNoiseState = (seed) => {
910
+ const scaledSeed = Math.round(seed * 1000);
911
+ const mixedState = (2654435769 ^ Math.imul(scaledSeed, 2246822507)) >>> 0;
912
+ return mixedState === 0 ? 2654435769 : mixedState;
913
+ };
914
+ var nextNoiseState = (state) => {
915
+ let next = state;
916
+ next ^= next << 13;
917
+ next ^= next >>> 17;
918
+ next ^= next << 5;
919
+ return next >>> 0;
920
+ };
921
+ var createNoiseData = (seed) => {
922
+ const data = new Uint8Array(NOISE_TEXTURE_SIZE * NOISE_TEXTURE_SIZE * 4);
923
+ let state = initialNoiseState(seed);
924
+ for (let i = 0;i < data.length; i += 4) {
925
+ state = nextNoiseState(state);
926
+ data[i] = state & 255;
927
+ state = nextNoiseState(state);
928
+ data[i + 1] = state & 255;
929
+ state = nextNoiseState(state);
930
+ data[i + 2] = state & 255;
931
+ data[i + 3] = 255;
932
+ }
933
+ return data;
934
+ };
935
+ var uploadNoiseTexture = (gl, texture, seed) => {
936
+ const data = createNoiseData(seed);
937
+ const flipY = gl.getParameter(gl.UNPACK_FLIP_Y_WEBGL);
938
+ const premultiplyAlpha = gl.getParameter(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL);
939
+ gl.bindTexture(gl.TEXTURE_2D, texture);
940
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
941
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
942
+ try {
943
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, NOISE_TEXTURE_SIZE, NOISE_TEXTURE_SIZE, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
944
+ } finally {
945
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
946
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
947
+ }
948
+ };
949
+ var createNoiseTexture = (gl) => {
950
+ const texture = gl.createTexture();
951
+ if (!texture) {
952
+ throw new Error("Failed to create WebGL noise texture");
953
+ }
954
+ uploadNoiseTexture(gl, texture, DEFAULT_SEED);
955
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
956
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
957
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
958
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
959
+ gl.bindTexture(gl.TEXTURE_2D, null);
960
+ return texture;
961
+ };
962
+ var setupPaper = (target) => {
963
+ const gl = target.getContext("webgl2", {
964
+ premultipliedAlpha: true,
965
+ alpha: true,
966
+ preserveDrawingBuffer: true
967
+ });
968
+ if (!gl) {
969
+ throw createWebGL2ContextError("paper effect");
970
+ }
971
+ const vs = compileShader(gl, gl.VERTEX_SHADER, PAPER_VS);
972
+ const fs = compileShader(gl, gl.FRAGMENT_SHADER, PAPER_FS);
973
+ const program = linkProgram(gl, vs, fs);
974
+ gl.deleteShader(vs);
975
+ gl.deleteShader(fs);
976
+ const vao = gl.createVertexArray();
977
+ if (!vao) {
978
+ throw new Error("Failed to create WebGL vertex array");
979
+ }
980
+ gl.bindVertexArray(vao);
981
+ const data = new Float32Array([
982
+ -1,
983
+ -1,
984
+ 0,
985
+ 0,
986
+ 1,
987
+ -1,
988
+ 1,
989
+ 0,
990
+ -1,
991
+ 1,
992
+ 0,
993
+ 1,
994
+ 1,
995
+ 1,
996
+ 1,
997
+ 1
998
+ ]);
999
+ const vbo = gl.createBuffer();
1000
+ if (!vbo) {
1001
+ throw new Error("Failed to create WebGL buffer");
1002
+ }
1003
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
1004
+ gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
1005
+ const aPos = gl.getAttribLocation(program, "aPos");
1006
+ const aUv = gl.getAttribLocation(program, "aUv");
1007
+ gl.enableVertexAttribArray(aPos);
1008
+ gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
1009
+ gl.enableVertexAttribArray(aUv);
1010
+ gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);
1011
+ gl.bindVertexArray(null);
1012
+ const sourceTexture = createSourceTexture(gl);
1013
+ const noiseTexture = createNoiseTexture(gl);
1014
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
1015
+ const colorCanvas = document.createElement("canvas");
1016
+ colorCanvas.width = 1;
1017
+ colorCanvas.height = 1;
1018
+ const colorCtx = colorCanvas.getContext("2d", { willReadFrequently: true });
1019
+ if (!colorCtx) {
1020
+ throw new Error("Failed to acquire 2D context for color parsing");
1021
+ }
1022
+ return {
1023
+ gl,
1024
+ program,
1025
+ vao,
1026
+ vbo,
1027
+ sourceTexture,
1028
+ noiseTexture,
1029
+ uSource: gl.getUniformLocation(program, "uSource"),
1030
+ uResolution: gl.getUniformLocation(program, "uResolution"),
1031
+ uImageAspectRatio: gl.getUniformLocation(program, "uImageAspectRatio"),
1032
+ uColorFront: gl.getUniformLocation(program, "uColorFront"),
1033
+ uColorBack: gl.getUniformLocation(program, "uColorBack"),
1034
+ uAmount: gl.getUniformLocation(program, "uAmount"),
1035
+ uContrast: gl.getUniformLocation(program, "uContrast"),
1036
+ uRoughness: gl.getUniformLocation(program, "uRoughness"),
1037
+ uFiber: gl.getUniformLocation(program, "uFiber"),
1038
+ uFiberSize: gl.getUniformLocation(program, "uFiberSize"),
1039
+ uCrumples: gl.getUniformLocation(program, "uCrumples"),
1040
+ uCrumpleSize: gl.getUniformLocation(program, "uCrumpleSize"),
1041
+ uFolds: gl.getUniformLocation(program, "uFolds"),
1042
+ uFoldCount: gl.getUniformLocation(program, "uFoldCount"),
1043
+ uDrops: gl.getUniformLocation(program, "uDrops"),
1044
+ uFade: gl.getUniformLocation(program, "uFade"),
1045
+ uSeed: gl.getUniformLocation(program, "uSeed"),
1046
+ uScale: gl.getUniformLocation(program, "uScale"),
1047
+ uNoiseTexture: gl.getUniformLocation(program, "uNoiseTexture"),
1048
+ colorCtx,
1049
+ cachedColorFront: "",
1050
+ cachedColorFrontRgba: [159, 173, 188, 255],
1051
+ cachedColorBack: "",
1052
+ cachedColorBackRgba: [255, 255, 255, 255],
1053
+ cachedNoiseSeed: DEFAULT_SEED
1054
+ };
1055
+ };
1056
+ var normalizedRgba = (color) => {
1057
+ return [color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255];
1058
+ };
1059
+ var paper = createEffect({
1060
+ type: "dev.remotion.effects.paper",
1061
+ label: "paper()",
1062
+ documentationLink: "https://www.remotion.dev/docs/effects/paper",
1063
+ calculateKey: (params) => {
1064
+ const r = resolve(params);
1065
+ return `paper-${r.amount}-${r.colorFront}-${r.colorBack}-${r.contrast}-${r.roughness}-${r.fiber}-${r.fiberSize}-${r.crumples}-${r.crumpleSize}-${r.folds}-${r.foldCount}-${r.drops}-${r.fade}-${r.seed}-${r.scale}`;
1066
+ },
1067
+ implementations: {
1068
+ webgpu: Internals.createEffectImplementation({
1069
+ setup: (target) => {
1070
+ const canvas = document.createElement("canvas");
1071
+ canvas.width = 1;
1072
+ canvas.height = 1;
1073
+ const colorCtx = canvas.getContext("2d", { willReadFrequently: true });
1074
+ if (!colorCtx)
1075
+ throw new Error("Could not create paper color parsing context");
1076
+ const paddedCanvas = document.createElement("canvas");
1077
+ return {
1078
+ ...setupWebGpuSinglePass(target, "paper"),
1079
+ colorCtx,
1080
+ noiseData: new Uint8Array(0),
1081
+ noiseSeed: null,
1082
+ paddedCanvas,
1083
+ paddedState: setupWebGpuSinglePass(paddedCanvas, "paper")
1084
+ };
1085
+ },
1086
+ apply: ({ source, width, height, params, state, gpuDevice }) => {
1087
+ if (!gpuDevice)
1088
+ throw new Error("A WebGPU device is required for the paper effect");
1089
+ const r = resolve(params);
1090
+ const offsetY = height % 2;
1091
+ if (offsetY && (state.paddedCanvas.width !== width || state.paddedCanvas.height !== height + 1)) {
1092
+ state.paddedCanvas.width = width;
1093
+ state.paddedCanvas.height = height + 1;
1094
+ }
1095
+ const uniformData = new Float32Array([
1096
+ width,
1097
+ height,
1098
+ width / height,
1099
+ r.amount,
1100
+ ...normalizedRgba(parseColorRgba(state.colorCtx, r.colorFront)),
1101
+ ...normalizedRgba(parseColorRgba(state.colorCtx, r.colorBack)),
1102
+ r.contrast,
1103
+ r.roughness,
1104
+ r.fiber,
1105
+ r.fiberSize,
1106
+ r.crumples,
1107
+ r.crumpleSize,
1108
+ r.folds,
1109
+ r.foldCount,
1110
+ r.drops,
1111
+ r.fade,
1112
+ r.seed,
1113
+ r.scale,
1114
+ offsetY,
1115
+ 0,
1116
+ 0,
1117
+ 0
1118
+ ]);
1119
+ if (state.noiseSeed !== r.seed) {
1120
+ state.noiseData = createNoiseData(r.seed);
1121
+ state.noiseSeed = r.seed;
1122
+ }
1123
+ applyWebGpuSinglePass({
1124
+ state: offsetY ? state.paddedState : state,
1125
+ source,
1126
+ width,
1127
+ height,
1128
+ device: gpuDevice,
1129
+ shader: PAPER_WEBGPU_SHADER,
1130
+ uniformData
1131
+ }, {
1132
+ sourceFilter: null,
1133
+ auxiliaryTexture: {
1134
+ data: state.noiseData,
1135
+ width: NOISE_TEXTURE_SIZE,
1136
+ height: NOISE_TEXTURE_SIZE,
1137
+ format: "rgba8unorm"
1138
+ }
1139
+ });
1140
+ if (offsetY) {
1141
+ applyWebGpuSinglePass({
1142
+ state,
1143
+ source: state.paddedCanvas,
1144
+ width,
1145
+ height,
1146
+ device: gpuDevice,
1147
+ shader: PAPER_CROP_WEBGPU_SHADER,
1148
+ uniformData: new Float32Array([width, height, 0, 0])
1149
+ });
1150
+ }
1151
+ },
1152
+ cleanup: (state) => {
1153
+ cleanupWebGpuSinglePass(state.paddedState);
1154
+ cleanupWebGpuSinglePass(state);
1155
+ }
1156
+ }),
1157
+ webgl2: Internals.createEffectImplementation({
1158
+ setup: (target) => setupPaper(target),
1159
+ apply: ({ source, width, height, params, state, flipSourceY }) => {
1160
+ const r = resolve(params);
1161
+ const { gl, program, vao, sourceTexture, noiseTexture } = state;
1162
+ if (state.cachedColorFront !== r.colorFront) {
1163
+ state.cachedColorFront = r.colorFront;
1164
+ state.cachedColorFrontRgba = parseColorRgba(state.colorCtx, r.colorFront);
1165
+ }
1166
+ if (state.cachedColorBack !== r.colorBack) {
1167
+ state.cachedColorBack = r.colorBack;
1168
+ state.cachedColorBackRgba = parseColorRgba(state.colorCtx, r.colorBack);
1169
+ }
1170
+ const [frontRed, frontGreen, frontBlue, frontAlpha] = normalizedRgba(state.cachedColorFrontRgba);
1171
+ const [backRed, backGreen, backBlue, backAlpha] = normalizedRgba(state.cachedColorBackRgba);
1172
+ gl.viewport(0, 0, width, height);
1173
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
1174
+ gl.clearColor(0, 0, 0, 0);
1175
+ gl.clear(gl.COLOR_BUFFER_BIT);
1176
+ gl.useProgram(program);
1177
+ gl.bindVertexArray(vao);
1178
+ gl.activeTexture(gl.TEXTURE0);
1179
+ gl.bindTexture(gl.TEXTURE_2D, sourceTexture);
1180
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
1181
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipSourceY);
1182
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
1183
+ gl.activeTexture(gl.TEXTURE1);
1184
+ gl.bindTexture(gl.TEXTURE_2D, noiseTexture);
1185
+ if (state.cachedNoiseSeed !== r.seed) {
1186
+ uploadNoiseTexture(gl, noiseTexture, r.seed);
1187
+ state.cachedNoiseSeed = r.seed;
1188
+ }
1189
+ if (state.uSource)
1190
+ gl.uniform1i(state.uSource, 0);
1191
+ if (state.uResolution)
1192
+ gl.uniform2f(state.uResolution, width, height);
1193
+ if (state.uImageAspectRatio)
1194
+ gl.uniform1f(state.uImageAspectRatio, width / height);
1195
+ if (state.uColorFront)
1196
+ gl.uniform4f(state.uColorFront, frontRed, frontGreen, frontBlue, frontAlpha);
1197
+ if (state.uColorBack)
1198
+ gl.uniform4f(state.uColorBack, backRed, backGreen, backBlue, backAlpha);
1199
+ if (state.uAmount)
1200
+ gl.uniform1f(state.uAmount, r.amount);
1201
+ if (state.uContrast)
1202
+ gl.uniform1f(state.uContrast, r.contrast);
1203
+ if (state.uRoughness)
1204
+ gl.uniform1f(state.uRoughness, r.roughness);
1205
+ if (state.uFiber)
1206
+ gl.uniform1f(state.uFiber, r.fiber);
1207
+ if (state.uFiberSize)
1208
+ gl.uniform1f(state.uFiberSize, r.fiberSize);
1209
+ if (state.uCrumples)
1210
+ gl.uniform1f(state.uCrumples, r.crumples);
1211
+ if (state.uCrumpleSize)
1212
+ gl.uniform1f(state.uCrumpleSize, r.crumpleSize);
1213
+ if (state.uFolds)
1214
+ gl.uniform1f(state.uFolds, r.folds);
1215
+ if (state.uFoldCount)
1216
+ gl.uniform1f(state.uFoldCount, r.foldCount);
1217
+ if (state.uDrops)
1218
+ gl.uniform1f(state.uDrops, r.drops);
1219
+ if (state.uFade)
1220
+ gl.uniform1f(state.uFade, r.fade);
1221
+ if (state.uSeed)
1222
+ gl.uniform1f(state.uSeed, r.seed);
1223
+ if (state.uScale)
1224
+ gl.uniform1f(state.uScale, r.scale);
1225
+ if (state.uNoiseTexture)
1226
+ gl.uniform1i(state.uNoiseTexture, 1);
1227
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
1228
+ gl.bindVertexArray(null);
1229
+ gl.activeTexture(gl.TEXTURE1);
1230
+ gl.bindTexture(gl.TEXTURE_2D, null);
1231
+ gl.activeTexture(gl.TEXTURE0);
1232
+ gl.bindTexture(gl.TEXTURE_2D, null);
1233
+ gl.useProgram(null);
1234
+ },
1235
+ cleanup: ({ gl, program, vao, vbo, sourceTexture, noiseTexture }) => {
1236
+ gl.deleteTexture(sourceTexture);
1237
+ gl.deleteTexture(noiseTexture);
1238
+ gl.deleteBuffer(vbo);
1239
+ gl.deleteProgram(program);
1240
+ gl.deleteVertexArray(vao);
1241
+ }
1242
+ })
1243
+ },
1244
+ schema: paperSchema,
1245
+ validateParams: validatePaperParams
1246
+ });
1247
+ export {
1248
+ paper
1249
+ };