@sangwonl/pocato-core 0.1.0 → 0.2.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 CHANGED
@@ -15,6 +15,7 @@ interface PocaCardOptions {
15
15
  backImage?: string;
16
16
  flippable?: boolean;
17
17
  initialFlipped?: boolean;
18
+ flipSpeed?: number;
18
19
  customShader?: string;
19
20
  }
20
21
  declare class PocaCard extends EventEmitter {
package/dist/index.js CHANGED
@@ -853,6 +853,104 @@ void main() {
853
853
  }
854
854
  `;
855
855
 
856
+ // src/shaders/holo.frag.ts
857
+ var holo_frag_default = glsl`
858
+ #ifdef GL_ES
859
+ precision mediump float;
860
+ #endif
861
+
862
+ uniform vec2 uResolution;
863
+ uniform vec2 uMouse;
864
+ uniform vec2 uMove;
865
+ uniform vec2 uRotate;
866
+ uniform float uTime;
867
+ uniform sampler2D uImgBase;
868
+ uniform sampler2D uImgPopup;
869
+
870
+ varying vec2 vUv;
871
+
872
+ #include <utils/defaultLighting>
873
+
874
+ // HSV to RGB conversion
875
+ vec3 hsv2rgb(vec3 c) {
876
+ vec4 K = vec4(1.0, 2.0/3.0, 1.0/3.0, 3.0);
877
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
878
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
879
+ }
880
+
881
+ void main() {
882
+ vec4 baseColor = texture2D(uImgBase, vUv);
883
+ vec4 popupColor = texture2D(uImgPopup, vUv);
884
+
885
+ // Iridescence on base only
886
+ float angle = uRotate.x * 2.0 + uRotate.y * 1.5;
887
+ float hue = fract(vUv.y * 0.8 + vUv.x * 0.3 + angle * 0.5 + uTime * 0.05);
888
+ vec3 rainbow = hsv2rgb(vec3(hue, 0.6, 1.0));
889
+
890
+ float tiltAmount = length(uRotate) * 3.0;
891
+ float holoIntensity = smoothstep(0.0, 1.0, tiltAmount) * 0.35;
892
+
893
+ vec3 holoBase = baseColor.rgb + rainbow * holoIntensity;
894
+
895
+ // Composite popup on top without holo
896
+ float aSoft = smoothstep(0.4, 1.0, popupColor.a);
897
+ vec3 finalColor = mix(holoBase, popupColor.rgb, aSoft);
898
+
899
+ gl_FragColor = defaultLighting(vec4(finalColor, 1.0), uResolution, uRotate, 1.0);
900
+ }
901
+ `;
902
+
903
+ // src/shaders/holo-3d.frag.ts
904
+ var holo_3d_frag_default = glsl`
905
+ #ifdef GL_ES
906
+ precision mediump float;
907
+ #endif
908
+
909
+ uniform vec2 uResolution;
910
+ uniform vec2 uMouse;
911
+ uniform vec2 uMove;
912
+ uniform vec2 uRotate;
913
+ uniform float uTime;
914
+ uniform sampler2D uImgBase;
915
+ uniform sampler2D uImgPopup;
916
+
917
+ varying vec2 vUv;
918
+
919
+ #include <utils/defaultLighting>
920
+
921
+ // HSV to RGB conversion
922
+ vec3 hsv2rgb(vec3 c) {
923
+ vec4 K = vec4(1.0, 2.0/3.0, 1.0/3.0, 3.0);
924
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
925
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
926
+ }
927
+
928
+ void main() {
929
+ vec4 baseColor = texture2D(uImgBase, vUv);
930
+
931
+ // 3D parallax offset for popup layer
932
+ vec2 popupOffset = vec2(-uRotate.x * 0.08, -uRotate.y * 0.06);
933
+ vec2 popupUv = vUv + popupOffset;
934
+ vec4 popupColor = texture2D(uImgPopup, popupUv);
935
+
936
+ // Iridescence on base only
937
+ float angle = uRotate.x * 2.0 + uRotate.y * 1.5;
938
+ float hue = fract(vUv.y * 0.8 + vUv.x * 0.3 + angle * 0.5 + uTime * 0.05);
939
+ vec3 rainbow = hsv2rgb(vec3(hue, 0.6, 1.0));
940
+
941
+ float tiltAmount = length(uRotate) * 3.0;
942
+ float holoIntensity = smoothstep(0.0, 1.0, tiltAmount) * 0.35;
943
+
944
+ vec3 holoBase = baseColor.rgb + rainbow * holoIntensity;
945
+
946
+ // Composite popup on top without holo
947
+ float aSoft = smoothstep(0.4, 1.0, popupColor.a);
948
+ vec3 finalColor = mix(holoBase, popupColor.rgb, aSoft);
949
+
950
+ gl_FragColor = defaultLighting(vec4(finalColor, 1.0), uResolution, uRotate, 1.0);
951
+ }
952
+ `;
953
+
856
954
  // src/renderer/index.ts
857
955
  var FRAG_SHADERS = {
858
956
  "glare": glare_frag_default,
@@ -862,7 +960,9 @@ var FRAG_SHADERS = {
862
960
  "brush": brush_frag_default,
863
961
  "brush-3d": brush_3d_frag_default,
864
962
  "blur": blur_frag_default,
865
- "blur-3d": blur_3d_frag_default
963
+ "blur-3d": blur_3d_frag_default,
964
+ "holo": holo_frag_default,
965
+ "holo-3d": holo_3d_frag_default
866
966
  };
867
967
  var Renderer = class {
868
968
  constructor(container, options, onError, onReady) {
@@ -1148,11 +1248,6 @@ var Renderer = class {
1148
1248
  }
1149
1249
  };
1150
1250
 
1151
- // src/utils/math.ts
1152
- var round = (value, precision = 3) => parseFloat(value.toFixed(precision));
1153
- var clamp = (value, min = 0, max = 100) => Math.min(Math.max(value, min), max);
1154
- var distance = (x1, y1, x2, y2) => Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
1155
-
1156
1251
  // src/animation/spring.ts
1157
1252
  var tasks = /* @__PURE__ */ new Set();
1158
1253
  var rafId = null;
@@ -1258,9 +1353,27 @@ function springVec2(initial, onChange, opts = {}) {
1258
1353
  queueMicrotask(flush);
1259
1354
  }, opts);
1260
1355
  return {
1261
- stiffness: opts.stiffness ?? 0.15,
1262
- damping: opts.damping ?? 0.8,
1263
- precision: opts.precision ?? 0.01,
1356
+ get stiffness() {
1357
+ return sx.stiffness;
1358
+ },
1359
+ set stiffness(v) {
1360
+ sx.stiffness = v;
1361
+ sy.stiffness = v;
1362
+ },
1363
+ get damping() {
1364
+ return sx.damping;
1365
+ },
1366
+ set damping(v) {
1367
+ sx.damping = v;
1368
+ sy.damping = v;
1369
+ },
1370
+ get precision() {
1371
+ return sx.precision;
1372
+ },
1373
+ set precision(v) {
1374
+ sx.precision = v;
1375
+ sy.precision = v;
1376
+ },
1264
1377
  get() {
1265
1378
  return { x: sx.get(), y: sy.get() };
1266
1379
  },
@@ -1297,9 +1410,30 @@ function springVec3(initial, onChange, opts = {}) {
1297
1410
  queueMicrotask(flush);
1298
1411
  }, opts);
1299
1412
  return {
1300
- stiffness: opts.stiffness ?? 0.15,
1301
- damping: opts.damping ?? 0.8,
1302
- precision: opts.precision ?? 0.01,
1413
+ get stiffness() {
1414
+ return sx.stiffness;
1415
+ },
1416
+ set stiffness(v) {
1417
+ sx.stiffness = v;
1418
+ sy.stiffness = v;
1419
+ so.stiffness = v;
1420
+ },
1421
+ get damping() {
1422
+ return sx.damping;
1423
+ },
1424
+ set damping(v) {
1425
+ sx.damping = v;
1426
+ sy.damping = v;
1427
+ so.damping = v;
1428
+ },
1429
+ get precision() {
1430
+ return sx.precision;
1431
+ },
1432
+ set precision(v) {
1433
+ sx.precision = v;
1434
+ sy.precision = v;
1435
+ so.precision = v;
1436
+ },
1303
1437
  get() {
1304
1438
  return { x: sx.get(), y: sy.get(), o: so.get() };
1305
1439
  },
@@ -1313,6 +1447,11 @@ function springVec3(initial, onChange, opts = {}) {
1313
1447
  };
1314
1448
  }
1315
1449
 
1450
+ // src/utils/math.ts
1451
+ var round = (value, precision = 3) => parseFloat(value.toFixed(precision));
1452
+ var clamp = (value, min = 0, max = 100) => Math.min(Math.max(value, min), max);
1453
+ var distance = (x1, y1, x2, y2) => Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
1454
+
1316
1455
  // src/interaction/index.ts
1317
1456
  var SPRING_INTERACT = { stiffness: 0.095, damping: 0.5 };
1318
1457
  var SPRING_FLIP = { stiffness: 0.03, damping: 0.25 };
@@ -1331,6 +1470,7 @@ var InteractionHandler = class {
1331
1470
  this.clickCount = 0;
1332
1471
  this.dblClickTimer = null;
1333
1472
  this.activePointerId = null;
1473
+ this._flipSpeed = 1;
1334
1474
  this.flipped = initialFlipped;
1335
1475
  this.springRotate = springVec2({ x: 0, y: 0 }, (v) => {
1336
1476
  callbacks.onRotate(v);
@@ -1469,11 +1609,15 @@ var InteractionHandler = class {
1469
1609
  y: rect.height / 2 * dpr
1470
1610
  });
1471
1611
  }
1612
+ set flipSpeed(speed) {
1613
+ this._flipSpeed = speed;
1614
+ }
1472
1615
  flip(flipped) {
1473
1616
  this.flipped = flipped ?? !this.flipped;
1474
- this.springRotate.stiffness = SPRING_FLIP.stiffness;
1617
+ const targetX = this.flipped ? 180 : 0;
1618
+ this.springRotate.stiffness = SPRING_FLIP.stiffness * this._flipSpeed;
1475
1619
  this.springRotate.damping = SPRING_FLIP.damping;
1476
- this.springRotate.set({ x: this.flipped ? 180 : 0, y: 0 }).then(() => {
1620
+ this.springRotate.set({ x: targetX, y: 0 }).then(() => {
1477
1621
  this.springRotate.stiffness = SPRING_INTERACT.stiffness;
1478
1622
  this.springRotate.damping = SPRING_INTERACT.damping;
1479
1623
  });
@@ -1521,7 +1665,7 @@ var InteractionHandler = class {
1521
1665
  }
1522
1666
  };
1523
1667
 
1524
- // src/animation/wiggle.ts
1668
+ // src/animation/tween.ts
1525
1669
  var easeOut = (t) => 1 - (1 - t) ** 3;
1526
1670
  var easeInOut = (t) => t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2;
1527
1671
  var easeIn = (t) => t * t * t;
@@ -1548,14 +1692,15 @@ function tween(opts) {
1548
1692
  }
1549
1693
  rafId2 = requestAnimationFrame(tick);
1550
1694
  });
1551
- const controller = Object.assign(promise, {
1695
+ return Object.assign(promise, {
1552
1696
  cancel() {
1553
1697
  cancelled = true;
1554
1698
  if (rafId2 !== null) cancelAnimationFrame(rafId2);
1555
1699
  }
1556
1700
  });
1557
- return controller;
1558
1701
  }
1702
+
1703
+ // src/animation/wiggle.ts
1559
1704
  function wiggle(cx, cy, radius, onUpdate) {
1560
1705
  let stopped = false;
1561
1706
  const cancellers = [];
@@ -1652,6 +1797,9 @@ var PocaCard = class extends EventEmitter {
1652
1797
  options.flippable ?? false,
1653
1798
  options.initialFlipped ?? false
1654
1799
  );
1800
+ if (options.flipSpeed != null) {
1801
+ this.interaction.flipSpeed = options.flipSpeed;
1802
+ }
1655
1803
  }
1656
1804
  getFrontContentEl() {
1657
1805
  return this.renderer.getFrontContentEl();
@@ -1680,6 +1828,9 @@ var PocaCard = class extends EventEmitter {
1680
1828
  this.interaction.simulateEndInteract();
1681
1829
  }
1682
1830
  updateOptions(options) {
1831
+ if (options.flipSpeed != null) {
1832
+ this.interaction.flipSpeed = options.flipSpeed;
1833
+ }
1683
1834
  if (options.customShader) {
1684
1835
  this.renderer.updateShader(options.customShader);
1685
1836
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/event-emitter.ts","../src/renderer/index.ts","../src/renderer/shader-bootstrap.ts","../src/shaders/lygia/math/permute.glsl","../src/shaders/lygia/math/mod289.glsl","../src/shaders/lygia/math/taylorInvSqrt.glsl","../src/shaders/lygia/math/grad4.glsl","../src/shaders/lygia/math/rotate4d.glsl","../src/shaders/lygia/math/cubic.glsl","../src/shaders/lygia/math/quintic.glsl","../src/shaders/lygia/math/sum.glsl","../src/shaders/lygia/math/saturate.glsl","../src/shaders/lygia/math/gaussian.glsl","../src/shaders/lygia/space/ratio.glsl","../src/shaders/lygia/generative/random.glsl","../src/shaders/lygia/generative/srandom.glsl","../src/shaders/lygia/generative/gnoise.glsl","../src/shaders/lygia/generative/snoise.glsl","../src/shaders/lygia/generative/fbm.glsl","../src/shaders/lygia/morphological/dilation.glsl","../src/shaders/lygia/sampler.glsl","../src/shaders/lygia/sample/clamp2edge.glsl","../src/shaders/lygia/draw/digits.glsl","../src/shaders/lygia/filter/gaussianBlur.glsl","../src/shaders/lygia/filter/gaussianBlur/2D.glsl","../src/shaders/lygia/filter/gaussianBlur/1D.glsl","../src/shaders/lygia/filter/gaussianBlur/1D_fast13.glsl","../src/shaders/lygia/filter/gaussianBlur/1D_fast9.glsl","../src/shaders/lygia/filter/gaussianBlur/1D_fast5.glsl","../src/shaders/lygia/filter/kuwahara.glsl","../src/shaders/utils/glsl.ts","../src/shaders/utils/default-lighting.glsl.ts","../src/shaders/common.vert.ts","../src/shaders/glare.frag.ts","../src/shaders/glare-3d.frag.ts","../src/shaders/snowfall.frag.ts","../src/shaders/snowfall-3d.frag.ts","../src/shaders/brush.frag.ts","../src/shaders/brush-3d.frag.ts","../src/shaders/blur.frag.ts","../src/shaders/blur-3d.frag.ts","../src/utils/math.ts","../src/animation/spring.ts","../src/interaction/index.ts","../src/animation/wiggle.ts","../src/poca-card.ts"],"sourcesContent":["type Handler = (...args: any[]) => void\n\nexport class EventEmitter {\n private listeners = new Map<string, Set<Handler>>()\n\n on(event: string, handler: Handler): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set())\n }\n this.listeners.get(event)!.add(handler)\n }\n\n off(event: string, handler: Handler): void {\n this.listeners.get(event)?.delete(handler)\n }\n\n protected emit(event: string, ...args: any[]): void {\n this.listeners.get(event)?.forEach((handler) => {\n try {\n handler(...args)\n } catch (e) {\n console.error(`[pocato] Error in ${event} handler:`, e)\n }\n })\n }\n\n protected removeAllListeners(): void {\n this.listeners.clear()\n }\n}\n","import * as THREE from 'three'\nimport { bootstrapShaders, resolveIncludes } from './shader-bootstrap'\nimport vertexShader from '../shaders/common.vert'\nimport fragShaderGlare from '../shaders/glare.frag'\nimport fragShaderGlare3d from '../shaders/glare-3d.frag'\nimport fragShaderSnowfall from '../shaders/snowfall.frag'\nimport fragShaderSnowfall3d from '../shaders/snowfall-3d.frag'\nimport fragShaderBrush from '../shaders/brush.frag'\nimport fragShaderBrush3d from '../shaders/brush-3d.frag'\nimport fragShaderBlur from '../shaders/blur.frag'\nimport fragShaderBlur3d from '../shaders/blur-3d.frag'\n\nconst FRAG_SHADERS: Record<string, string> = {\n 'glare': fragShaderGlare,\n 'glare-3d': fragShaderGlare3d,\n 'snowfall': fragShaderSnowfall,\n 'snowfall-3d': fragShaderSnowfall3d,\n 'brush': fragShaderBrush,\n 'brush-3d': fragShaderBrush3d,\n 'blur': fragShaderBlur,\n 'blur-3d': fragShaderBlur3d,\n}\n\nexport interface RendererOptions {\n type: string\n baseImage: string\n popupImage?: string\n maskImage?: string\n backImage?: string\n customShader?: string\n}\n\nexport class Renderer {\n private scene: THREE.Scene | null = null\n private camera: THREE.Camera | null = null\n private webglRenderer: THREE.WebGLRenderer | null = null\n private material: THREE.ShaderMaterial | null = null\n private mesh: THREE.Mesh | null = null\n private clock = new THREE.Clock()\n private rafId: number | null = null\n private textures: THREE.Texture[] = []\n private canvas: HTMLCanvasElement\n private cardEl: HTMLDivElement\n private rotatorEl: HTMLDivElement\n private frontEl: HTMLDivElement\n private backEl: HTMLDivElement\n private frontContentEl: HTMLDivElement\n private backContentEl: HTMLDivElement\n private resizeObserver: ResizeObserver | null = null\n\n constructor(\n private container: HTMLElement,\n private options: RendererOptions,\n private onError?: (error: Error) => void,\n private onReady?: () => void,\n ) {\n this.injectStyles()\n\n // Build DOM:\n // .pocato-card > .pocato-rotator > .pocato-back\n // > .pocato-front > canvas\n this.cardEl = document.createElement('div')\n this.cardEl.className = 'pocato-card pocato-loading'\n\n this.rotatorEl = document.createElement('div')\n this.rotatorEl.className = 'pocato-rotator'\n\n // Back face\n this.backEl = document.createElement('div')\n this.backEl.className = 'pocato-back'\n if (options.backImage) {\n const backImg = document.createElement('img')\n backImg.src = options.backImage\n backImg.className = 'pocato-back-img'\n this.backEl.appendChild(backImg)\n }\n\n // Front face\n this.frontEl = document.createElement('div')\n this.frontEl.className = 'pocato-front'\n\n this.canvas = document.createElement('canvas')\n this.canvas.className = 'pocato-canvas'\n\n // Content containers for user-provided children (via React portal etc.)\n this.frontContentEl = document.createElement('div')\n this.frontContentEl.className = 'pocato-content pocato-front-content'\n\n this.backContentEl = document.createElement('div')\n this.backContentEl.className = 'pocato-content pocato-back-content'\n\n this.frontEl.appendChild(this.canvas)\n this.frontEl.appendChild(this.frontContentEl)\n this.backEl.appendChild(this.backContentEl)\n\n this.rotatorEl.appendChild(this.backEl)\n this.rotatorEl.appendChild(this.frontEl)\n this.cardEl.appendChild(this.rotatorEl)\n this.container.appendChild(this.cardEl)\n\n bootstrapShaders()\n this.init()\n }\n\n private injectStyles(): void {\n const id = 'pocato-styles'\n if (document.getElementById(id)) return\n\n const style = document.createElement('style')\n style.id = id\n style.textContent = `\n .pocato-card {\n width: 100%;\n height: 100%;\n perspective: 1000px;\n touch-action: none;\n user-select: none;\n transform: translate3d(0,0,0);\n opacity: 0;\n transition: opacity 0.5s ease;\n }\n .pocato-card.pocato-ready {\n opacity: 1;\n }\n .pocato-rotator {\n width: 100%;\n height: 100%;\n position: relative;\n transform-style: preserve-3d;\n transform-origin: center;\n transform: rotateY(var(--pocato-rotate-x, 0deg)) rotateX(var(--pocato-rotate-y, 0deg));\n border-radius: 2%;\n will-change: transform, box-shadow;\n transition: box-shadow 0.4s ease;\n box-shadow:\n 0px 10px 20px -5px rgba(0,0,0,0.4),\n 0 2px 15px -5px rgba(0,0,0,0.3);\n pointer-events: auto;\n }\n .pocato-front {\n position: absolute;\n top: 0; left: 0;\n width: 100%;\n height: 100%;\n backface-visibility: hidden;\n -webkit-backface-visibility: hidden;\n transform: translate3d(0,0,0);\n border-radius: 2%;\n overflow: hidden;\n }\n .pocato-back {\n position: absolute;\n top: 0; left: 0;\n width: 100%;\n height: 100%;\n backface-visibility: hidden;\n -webkit-backface-visibility: hidden;\n transform: rotateY(180deg) translateZ(0);\n border-radius: 2%;\n overflow: hidden;\n background-color: #1a1a2e;\n }\n .pocato-back-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n pointer-events: none;\n }\n .pocato-canvas {\n width: 100%;\n height: 100%;\n display: block;\n }\n .pocato-content {\n position: absolute;\n top: 0; left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 1;\n }\n .pocato-content > * {\n pointer-events: auto;\n }\n `\n document.head.appendChild(style)\n }\n\n private init(): void {\n const { width, height } = this.container.getBoundingClientRect()\n\n this.scene = new THREE.Scene()\n this.camera = new THREE.Camera()\n\n this.webglRenderer = new THREE.WebGLRenderer({\n canvas: this.canvas,\n alpha: true,\n })\n this.webglRenderer.setPixelRatio(window.devicePixelRatio)\n this.webglRenderer.setSize(width, height)\n\n // Use actual pixel dimensions (CSS size × DPR) for uResolution,\n // matching Angular which uses renderer.domElement.width/height\n const pixelWidth = this.canvas.width\n const pixelHeight = this.canvas.height\n const uniforms = this.createUniforms(pixelWidth, pixelHeight)\n\n const rawFragmentShader = this.options.customShader\n ?? FRAG_SHADERS[this.options.type]\n\n const fragmentShader = resolveIncludes(rawFragmentShader)\n\n this.material = new THREE.ShaderMaterial({\n vertexShader: resolveIncludes(vertexShader),\n fragmentShader,\n uniforms,\n transparent: true,\n })\n\n const geometry = new THREE.PlaneGeometry(2, 2)\n this.mesh = new THREE.Mesh(geometry, this.material)\n this.scene.add(this.mesh)\n\n this.loadTextures()\n this.setupResizeObserver()\n this.startRenderLoop()\n\n // Fade in after a short delay (matching Angular loading behavior)\n requestAnimationFrame(() => {\n this.cardEl.classList.remove('pocato-loading')\n this.cardEl.classList.add('pocato-ready')\n })\n }\n\n private createUniforms(width: number, height: number): Record<string, THREE.IUniform> {\n return {\n uTime: { value: 0 },\n uResolution: { value: new THREE.Vector2(width, height) },\n uMouse: { value: new THREE.Vector2(0, 0) },\n uMove: { value: new THREE.Vector2(0, 0) },\n uRotate: { value: new THREE.Vector2(0, 0) },\n uCardOpacity: { value: 1.0 },\n uImgBase: { value: null },\n uImgPopup: { value: null },\n uImgMask: { value: null },\n }\n }\n\n private loadTextures(): void {\n const loader = new THREE.TextureLoader()\n const load = (url: string | undefined, uniform: string) => {\n if (!url) return\n loader.load(\n url,\n (texture) => {\n this.textures.push(texture)\n if (this.material) {\n this.material.uniforms[uniform].value = texture\n }\n },\n undefined,\n () => {\n this.onError?.(new Error(`Failed to load texture: ${url}`))\n },\n )\n }\n\n load(this.options.baseImage, 'uImgBase')\n load(this.options.popupImage, 'uImgPopup')\n load(this.options.maskImage, 'uImgMask')\n\n this.onReady?.()\n }\n\n private setupResizeObserver(): void {\n this.resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (!entry) return\n const { width, height } = entry.contentRect\n if (width === 0 || height === 0) return\n\n this.webglRenderer?.setSize(width, height)\n // Use pixel dimensions after setSize (accounts for DPR)\n if (this.material) {\n this.material.uniforms.uResolution.value.set(this.canvas.width, this.canvas.height)\n }\n })\n this.resizeObserver.observe(this.container)\n }\n\n private startRenderLoop(): void {\n const animate = () => {\n this.rafId = requestAnimationFrame(animate)\n if (!this.material || !this.scene || !this.camera || !this.webglRenderer) return\n\n const delta = this.clock.getDelta()\n this.material.uniforms.uTime.value += delta\n this.webglRenderer.render(this.scene, this.camera)\n }\n this.rafId = requestAnimationFrame(animate)\n }\n\n updateUniforms(updates: {\n rotate?: { x: number; y: number }\n mouse?: { x: number; y: number }\n move?: { x: number; y: number }\n opacity?: number\n }): void {\n if (!this.material) return\n const u = this.material.uniforms\n if (updates.rotate) {\n // CSS transform for 3D card tilt (degrees)\n this.rotatorEl.style.setProperty('--pocato-rotate-x', `${updates.rotate.x}deg`)\n this.rotatorEl.style.setProperty('--pocato-rotate-y', `${updates.rotate.y}deg`)\n // Shader uniform (radians)\n u.uRotate.value.set(\n updates.rotate.x * (Math.PI / 180),\n updates.rotate.y * (Math.PI / 180),\n )\n }\n if (updates.mouse) u.uMouse.value.set(updates.mouse.x, updates.mouse.y)\n if (updates.move) u.uMove.value.set(updates.move.x, updates.move.y)\n if (updates.opacity !== undefined) u.uCardOpacity.value = updates.opacity\n }\n\n updateShader(fragmentShader: string): void {\n if (!this.material) return\n this.material.fragmentShader = resolveIncludes(fragmentShader)\n this.material.needsUpdate = true\n }\n\n updateTextures(options: Partial<RendererOptions>): void {\n const loader = new THREE.TextureLoader()\n const load = (url: string | undefined, uniform: string) => {\n if (!url) return\n loader.load(url, (texture) => {\n this.textures.push(texture)\n if (this.material) {\n this.material.uniforms[uniform].value = texture\n }\n })\n }\n if (options.baseImage) load(options.baseImage, 'uImgBase')\n if (options.popupImage) load(options.popupImage, 'uImgPopup')\n if (options.maskImage) load(options.maskImage, 'uImgMask')\n }\n\n getContainerRect(): DOMRect {\n return this.container.getBoundingClientRect()\n }\n\n getRotatorEl(): HTMLDivElement {\n return this.rotatorEl\n }\n\n getFrontContentEl(): HTMLDivElement {\n return this.frontContentEl\n }\n\n getBackContentEl(): HTMLDivElement {\n return this.backContentEl\n }\n\n destroy(): void {\n if (this.rafId !== null) cancelAnimationFrame(this.rafId)\n this.resizeObserver?.disconnect()\n this.textures.forEach((t) => t.dispose())\n this.mesh?.geometry.dispose()\n this.material?.dispose()\n this.webglRenderer?.dispose()\n if (this.cardEl.parentNode) {\n this.cardEl.parentNode.removeChild(this.cardEl)\n }\n this.scene = null\n this.camera = null\n this.webglRenderer = null\n this.material = null\n this.mesh = null\n }\n}\n","import * as THREE from 'three'\n\nimport permute from '../shaders/lygia/math/permute.glsl'\nimport mod289 from '../shaders/lygia/math/mod289.glsl'\nimport taylorInvSqrt from '../shaders/lygia/math/taylorInvSqrt.glsl'\nimport grad4 from '../shaders/lygia/math/grad4.glsl'\nimport rotate4d from '../shaders/lygia/math/rotate4d.glsl'\nimport cubic from '../shaders/lygia/math/cubic.glsl'\nimport quintic from '../shaders/lygia/math/quintic.glsl'\nimport sum from '../shaders/lygia/math/sum.glsl'\nimport saturate from '../shaders/lygia/math/saturate.glsl'\nimport gaussian from '../shaders/lygia/math/gaussian.glsl'\nimport ratio from '../shaders/lygia/space/ratio.glsl'\nimport random from '../shaders/lygia/generative/random.glsl'\nimport srandom from '../shaders/lygia/generative/srandom.glsl'\nimport gnoise from '../shaders/lygia/generative/gnoise.glsl'\nimport snoise from '../shaders/lygia/generative/snoise.glsl'\nimport fbm from '../shaders/lygia/generative/fbm.glsl'\nimport dilation from '../shaders/lygia/morphological/dilation.glsl'\nimport sampler from '../shaders/lygia/sampler.glsl'\nimport clamp2edge from '../shaders/lygia/sample/clamp2edge.glsl'\nimport digits from '../shaders/lygia/draw/digits.glsl'\nimport gaussianBlur from '../shaders/lygia/filter/gaussianBlur.glsl'\nimport gaussianBlur2D from '../shaders/lygia/filter/gaussianBlur/2D.glsl'\nimport gaussianBlur1D from '../shaders/lygia/filter/gaussianBlur/1D.glsl'\nimport gaussianBlur1DFast13 from '../shaders/lygia/filter/gaussianBlur/1D_fast13.glsl'\nimport gaussianBlur1DFast9 from '../shaders/lygia/filter/gaussianBlur/1D_fast9.glsl'\nimport gaussianBlur1DFast5 from '../shaders/lygia/filter/gaussianBlur/1D_fast5.glsl'\nimport kuwahara from '../shaders/lygia/filter/kuwahara.glsl'\n\nimport defaultLighting from '../shaders/utils/default-lighting.glsl'\n\nlet bootstrapped = false\n\n// Build a reverse lookup: short name (e.g. \"mod289\") → full chunk key (e.g. \"lygia/math/mod289\")\nconst shortNameMap = new Map<string, string>()\n\nfunction buildShortNameMap(): void {\n const chunks = THREE.ShaderChunk as any\n for (const key of Object.keys(chunks)) {\n // Extract short name from full path\n const parts = key.split('/')\n const shortName = parts[parts.length - 1]\n if (!shortNameMap.has(shortName)) {\n shortNameMap.set(shortName, key)\n }\n }\n}\n\n/**\n * Recursively resolve #include directives using THREE.ShaderChunk.\n * Handles:\n * - #include <lygia/math/mod289> (angle bracket, full path)\n * - #include <utils/defaultLighting> (angle bracket, registered key)\n * - #include \"mod289.glsl\" (quote, short name from LYGIA internals)\n * - #include \"../math/cubic.glsl\" (quote, relative path from LYGIA internals)\n */\nexport function resolveIncludes(source: string): string {\n if (shortNameMap.size === 0) buildShortNameMap()\n\n const pattern = /^[ \\t]*#include\\s+[<\"]([^>\"]+)[>\"]/gm\n const resolved = new Set<string>() // prevent infinite recursion via guard set\n\n function resolve(src: string, depth = 0): string {\n if (depth > 15) return src\n return src.replace(pattern, (_match, rawName: string) => {\n // Normalize: strip .glsl extension\n const name = rawName.replace(/\\.glsl$/, '')\n\n // Prevent re-including the same chunk\n if (resolved.has(name)) return ''\n\n const chunks = THREE.ShaderChunk as any\n\n // 1. Try exact key match\n let chunk = chunks[name]\n\n // 2. Try short name lookup (e.g. \"mod289\" → \"lygia/math/mod289\")\n if (chunk === undefined) {\n const shortName = name.split('/').pop()!\n const fullKey = shortNameMap.get(shortName)\n if (fullKey) chunk = chunks[fullKey]\n }\n\n // 3. Try normalizing relative paths (e.g. \"../math/cubic\" → \"lygia/math/cubic\")\n if (chunk === undefined && (name.startsWith('../') || name.startsWith('./'))) {\n // Try stripping relative prefix and prepending lygia/\n const cleaned = name.replace(/^\\.\\.\\//, '').replace(/^\\.\\//, '')\n chunk = chunks['lygia/' + cleaned]\n if (chunk === undefined) {\n // Try just the short name\n const shortName = cleaned.split('/').pop()!\n const fullKey = shortNameMap.get(shortName)\n if (fullKey) chunk = chunks[fullKey]\n }\n }\n\n if (chunk !== undefined) {\n resolved.add(name)\n return resolve(chunk, depth + 1)\n }\n\n // Chunk not found — leave a comment so shader doesn't break silently\n console.warn(`[pocato] Shader chunk not found: ${rawName}`)\n return `/* chunk not found: ${rawName} */`\n })\n }\n return resolve(source)\n}\n\nexport function bootstrapShaders(): void {\n if (bootstrapped) return\n bootstrapped = true\n\n const ThreeShaderChunk = THREE.ShaderChunk as any\n ThreeShaderChunk['lygia/math/permute'] = permute\n ThreeShaderChunk['lygia/math/mod289'] = mod289\n ThreeShaderChunk['lygia/math/taylorInvSqrt'] = taylorInvSqrt\n ThreeShaderChunk['lygia/math/grad4'] = grad4\n ThreeShaderChunk['lygia/math/rotate4d'] = rotate4d\n ThreeShaderChunk['lygia/math/cubic'] = cubic\n ThreeShaderChunk['lygia/math/quintic'] = quintic\n ThreeShaderChunk['lygia/math/sum'] = sum\n ThreeShaderChunk['lygia/math/saturate'] = saturate\n ThreeShaderChunk['lygia/math/gaussian'] = gaussian\n ThreeShaderChunk['lygia/space/ratio'] = ratio\n ThreeShaderChunk['lygia/generative/random'] = random\n ThreeShaderChunk['lygia/generative/srandom'] = srandom\n ThreeShaderChunk['lygia/generative/gnoise'] = gnoise\n ThreeShaderChunk['lygia/generative/snoise'] = snoise\n ThreeShaderChunk['lygia/generative/fbm'] = fbm\n ThreeShaderChunk['lygia/morphological/dilation'] = dilation\n ThreeShaderChunk['lygia/sampler'] = sampler\n ThreeShaderChunk['lygia/sample/clamp2edge'] = clamp2edge\n ThreeShaderChunk['lygia/draw/digits'] = digits\n ThreeShaderChunk['lygia/filter/gaussianBlur'] = gaussianBlur\n ThreeShaderChunk['lygia/filter/gaussianBlur/2D'] = gaussianBlur2D\n ThreeShaderChunk['lygia/filter/gaussianBlur/1D'] = gaussianBlur1D\n ThreeShaderChunk['lygia/filter/gaussianBlur/1D_fast13'] = gaussianBlur1DFast13\n ThreeShaderChunk['lygia/filter/gaussianBlur/1D_fast9'] = gaussianBlur1DFast9\n ThreeShaderChunk['lygia/filter/gaussianBlur/1D_fast5'] = gaussianBlur1DFast5\n ThreeShaderChunk['lygia/filter/kuwahara'] = kuwahara\n ThreeShaderChunk['utils/defaultLighting'] = defaultLighting\n}\n","#include \"mod289.glsl\"\n\n/*\ncontributors: [Stefan Gustavson, Ian McEwan]\ndescription: permute\nuse: <float|vec2|vec3|vec4> permute(<float|vec2|vec3|vec4> x)\nexamples:\n - https://raw.githubusercontent.com/patriciogonzalezvivo/lygia_examples/main/math_functions.frag\n*/\n\n#ifndef FNC_PERMUTE\n#define FNC_PERMUTE\n\nfloat permute(const in float v) { return mod289(((v * 34.0) + 1.0) * v); }\nvec2 permute(const in vec2 v) { return mod289(((v * 34.0) + 1.0) * v); }\nvec3 permute(const in vec3 v) { return mod289(((v * 34.0) + 1.0) * v); }\nvec4 permute(const in vec4 v) { return mod289(((v * 34.0) + 1.0) * v); }\n\n#endif\n","/*\ncontributors: [Stefan Gustavson, Ian McEwan]\ndescription: modulus of 289\nuse: <float|vec2|vec3|vec4> mod289(<float|vec2|vec3|vec4> x)\n*/\n\n#ifndef FNC_MOD289\n#define FNC_MOD289\n\nfloat mod289(const in float x) { return x - floor(x * (1. / 289.)) * 289.; }\nvec2 mod289(const in vec2 x) { return x - floor(x * (1. / 289.)) * 289.; }\nvec3 mod289(const in vec3 x) { return x - floor(x * (1. / 289.)) * 289.; }\nvec4 mod289(const in vec4 x) { return x - floor(x * (1. / 289.)) * 289.; }\n\n#endif\n","/*\ncontributors: [Stefan Gustavson, Ian McEwan]\ndescription: Fast, accurate inverse square root. \nuse: <float|vec2|vec3|vec4> taylorInvSqrt(<float|vec2|vec3|vec4> x)\n*/\n\n#ifndef FNC_TAYLORINVSQRT\n#define FNC_TAYLORINVSQRT\nfloat taylorInvSqrt(in float r) { return 1.79284291400159 - 0.85373472095314 * r; }\nvec2 taylorInvSqrt(in vec2 r) { return 1.79284291400159 - 0.85373472095314 * r; }\nvec3 taylorInvSqrt(in vec3 r) { return 1.79284291400159 - 0.85373472095314 * r; }\nvec4 taylorInvSqrt(in vec4 r) { return 1.79284291400159 - 0.85373472095314 * r; }\n#endif","/*\ncontributors: [Stefan Gustavson, Ian McEwan]\ndescription: grad4, used for snoise(vec4 v)\nuse: grad4(<float> j, <vec4> ip)\n*/\n\n#ifndef FNC_GRAD4\n#define FNC_GRAD4\nvec4 grad4(float j, vec4 ip) {\n const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);\n vec4 p,s;\n p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;\n p.w = 1.5 - dot(abs(p.xyz), ones.xyz);\n s = vec4(lessThan(p, vec4(0.0)));\n p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www;\n return p;\n}\n#endif\n","/*\ncontributors: Patricio Gonzalez Vivo\ndescription: returns a 4x4 rotation matrix\nuse: <mat4> rotate4d(<vec3> axis, <float> radians)\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef FNC_ROTATE4D\n#define FNC_ROTATE4D\nmat4 rotate4d(in vec3 a, const in float r) {\n a = normalize(a);\n float s = sin(r);\n float c = cos(r);\n float oc = 1.0 - c;\n vec4 col1 = vec4(oc * a.x * a.x + c, oc * a.x * a.y + a.z * s, oc * a.z * a.x - a.y * s, 0.0);\n vec4 col2 = vec4(oc * a.x * a.y - a.z * s, oc * a.y * a.y + c, oc * a.y * a.z + a.x * s, 0.0);\n vec4 col3 = vec4(oc * a.z * a.x + a.y * s, oc * a.y * a.z - a.x * s, oc * a.z * a.z + c, 0.0);\n vec4 col4 = vec4(0.0, 0.0, 0.0, 1.0);\n return mat4(col1, col2, col3, col4);\n}\n#endif\n","/*\ncontributors: Inigo Quiles\ndescription: cubic polynomial https://iquilezles.org/articles/smoothsteps/\nuse: <float|vec2|vec3|vec4> cubic(<float|vec2|vec3|vec4> value[, <float> in, <float> out]);\nexamples:\n - https://raw.githubusercontent.com/patriciogonzalezvivo/lygia_examples/main/math_functions.frag\n*/\n\n#ifndef FNC_CUBIC\n#define FNC_CUBIC \nfloat cubic(const in float v) { return v*v*(3.0-2.0*v); }\nvec2 cubic(const in vec2 v) { return v*v*(3.0-2.0*v); }\nvec3 cubic(const in vec3 v) { return v*v*(3.0-2.0*v); }\nvec4 cubic(const in vec4 v) { return v*v*(3.0-2.0*v); }\n\nfloat cubic(const in float v, in float slope0, in float slope1) {\n float a = slope0 + slope1 - 2.;\n float b = -2. * slope0 - slope1 + 3.;\n float c = slope0;\n float v2 = v * v;\n float v3 = v * v2;\n return a * v3 + b * v2 + c * v;\n}\n\nvec2 cubic(const in vec2 v, in float slope0, in float slope1) {\n float a = slope0 + slope1 - 2.;\n float b = -2. * slope0 - slope1 + 3.;\n float c = slope0;\n vec2 v2 = v * v;\n vec2 v3 = v * v2;\n return a * v3 + b * v2 + c * v;\n}\n\nvec3 cubic(const in vec3 v, in float slope0, in float slope1) {\n float a = slope0 + slope1 - 2.;\n float b = -2. * slope0 - slope1 + 3.;\n float c = slope0;\n vec3 v2 = v * v;\n vec3 v3 = v * v2;\n return a * v3 + b * v2 + c * v;\n}\n\nvec4 cubic(const in vec4 v, in float slope0, in float slope1) {\n float a = slope0 + slope1 - 2.;\n float b = -2. * slope0 - slope1 + 3.;\n float c = slope0;\n vec4 v2 = v * v;\n vec4 v3 = v * v2;\n return a * v3 + b * v2 + c * v;\n}\n#endif","/*\ncontributors: Inigo Quiles\ndescription: quintic polynomial https://iquilezles.org/articles/smoothsteps/\nuse: <float|vec2|vec3|vec4> quintic(<float|vec2|vec3|vec4> value);\nexamples:\n - https://raw.githubusercontent.com/patriciogonzalezvivo/lygia_examples/main/math_functions.frag\n*/\n\n#ifndef FNC_QUINTIC\n#define FNC_QUINTIC \n\nfloat quintic(const in float v) { return v*v*v*(v*(v*6.0-15.0)+10.0); }\nvec2 quintic(const in vec2 v) { return v*v*v*(v*(v*6.0-15.0)+10.0); }\nvec3 quintic(const in vec3 v) { return v*v*v*(v*(v*6.0-15.0)+10.0); }\nvec4 quintic(const in vec4 v) { return v*v*v*(v*(v*6.0-15.0)+10.0); }\n\n#endif","/*\ncontributors: Patricio Gonzalez Vivo\ndescription: Sum elements of a vector\nuse: <float> sum(<vec2|vec3|vec4> value)\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef FNC_SUM\n#define FNC_SUM\nfloat sum( float v ) { return v; }\nfloat sum( vec2 v ) { return v.x+v.y; }\nfloat sum( vec3 v ) { return v.x+v.y+v.z; }\nfloat sum( vec4 v ) { return v.x+v.y+v.z+v.w; }\n#endif\n","/*\ncontributors: Patricio Gonzalez Vivo\ndescription: clamp a value between 0 and 1\nuse: <float|vec2|vec3|vec4> saturation(<float|vec2|vec3|vec4> value)\nexamples:\n - https://raw.githubusercontent.com/patriciogonzalezvivo/lygia_examples/main/math_functions.frag\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#if !defined(FNC_SATURATE) && !defined(saturate)\n#define FNC_SATURATE\n#define saturate(V) clamp(V, 0.0, 1.0)\n#endif","/*\ncontributors: Patricio Gonzalez Vivo\ndescription: gaussian coefficient\nuse: <vec4|vec3|vec2|float> gaussian(<float> sigma, <vec4|vec3|vec2|float> d)\nexamples:\n - https://raw.githubusercontent.com/patriciogonzalezvivo/lygia_examples/main/math_gaussian.frag\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef FNC_GAUSSIAN\n#define FNC_GAUSSIAN\nfloat gaussian(float d, float s) { return exp(-(d*d) / (2.0 * s*s)); }\nfloat gaussian( vec2 d, float s) { return exp(-( d.x*d.x + d.y*d.y) / (2.0 * s*s)); }\nfloat gaussian( vec3 d, float s) { return exp(-( d.x*d.x + d.y*d.y + d.z*d.z ) / (2.0 * s*s)); }\nfloat gaussian( vec4 d, float s) { return exp(-( d.x*d.x + d.y*d.y + d.z*d.z + d.w*d.w ) / (2.0 * s*s)); }\n#endif","/*\ncontributors: Patricio Gonzalez Vivo\ndescription: \"Fix the aspect ratio of a space keeping things squared for you, \\nin\\\n \\ a similar way that aspect.glsl does, but while scaling the \\nspace to keep the\\\n \\ entire 0.0,0.0 ~ 1.0,1.0 range visible\\n\"\nuse: <vec2> ratio(<vec2> st, <vec2> st_size)\nexamples:\n - https://raw.githubusercontent.com/patriciogonzalezvivo/lygia_examples/main/draw_shapes.frag\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef FNC_RATIO\n#define FNC_RATIO\nvec2 ratio(in vec2 v, in vec2 s) {\n return mix( vec2((v.x*s.x/s.y)-(s.x*.5-s.y*.5)/s.y,v.y),\n vec2(v.x,v.y*(s.y/s.x)-(s.y*.5-s.x*.5)/s.x),\n step(s.x,s.y));\n}\n#endif\n","/*\ncontributors: [\"Patricio Gonzalez Vivo\", \"David Hoskins\", \"Inigo Quilez\"]\ndescription: Pass a value and get some random normalize value between 0 and 1\nuse: float random[2|3](<float|vec2|vec3> value)\noptions:\n - RANDOM_HIGHER_RANGE: for working with a range over 0 and 1\n - RANDOM_SINLESS: Use sin-less random, which tolerates bigger values before producing pattern. From https://www.shadertoy.com/view/4djSRW\n - RANDOM_SCALE: by default this scale if for number with a big range. For producing good random between 0 and 1 use bigger range\nexamples:\n - /shaders/generative_random.frag\nlicense:\n - MIT License (MIT) Copyright 2014, David Hoskins\n*/\n\n#ifndef RANDOM_SCALE\n#ifdef RANDOM_HIGHER_RANGE\n#define RANDOM_SCALE vec4(.1031, .1030, .0973, .1099)\n#else\n#define RANDOM_SCALE vec4(443.897, 441.423, .0973, .1099)\n#endif\n#endif\n\n#ifndef FNC_RANDOM\n#define FNC_RANDOM\nfloat random(in float x) {\n#ifdef RANDOM_SINLESS\n x = fract(x * RANDOM_SCALE.x);\n x *= x + 33.33;\n x *= x + x;\n return fract(x);\n#else\n return fract(sin(x) * 43758.5453);\n#endif\n}\n\nfloat random(in vec2 st) {\n#ifdef RANDOM_SINLESS\n vec3 p3 = fract(vec3(st.xyx) * RANDOM_SCALE.xyz);\n p3 += dot(p3, p3.yzx + 33.33);\n return fract((p3.x + p3.y) * p3.z);\n#else\n return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453);\n#endif\n}\n\nfloat random(in vec3 pos) {\n#ifdef RANDOM_SINLESS\n pos = fract(pos * RANDOM_SCALE.xyz);\n pos += dot(pos, pos.zyx + 31.32);\n return fract((pos.x + pos.y) * pos.z);\n#else\n return fract(sin(dot(pos.xyz, vec3(70.9898, 78.233, 32.4355))) * 43758.5453123);\n#endif\n}\n\nfloat random(in vec4 pos) {\n#ifdef RANDOM_SINLESS\n pos = fract(pos * RANDOM_SCALE);\n pos += dot(pos, pos.wzxy + 33.33);\n return fract((pos.x + pos.y) * (pos.z + pos.w));\n#else\n float dot_product = dot(pos, vec4(12.9898,78.233,45.164,94.673));\n return fract(sin(dot_product) * 43758.5453);\n#endif\n}\n\nvec2 random2(float p) {\n vec3 p3 = fract(vec3(p) * RANDOM_SCALE.xyz);\n p3 += dot(p3, p3.yzx + 19.19);\n return fract((p3.xx + p3.yz) * p3.zy);\n}\n\nvec2 random2(vec2 p) {\n vec3 p3 = fract(p.xyx * RANDOM_SCALE.xyz);\n p3 += dot(p3, p3.yzx + 19.19);\n return fract((p3.xx + p3.yz) * p3.zy);\n}\n\nvec2 random2(vec3 p3) {\n p3 = fract(p3 * RANDOM_SCALE.xyz);\n p3 += dot(p3, p3.yzx + 19.19);\n return fract((p3.xx + p3.yz) * p3.zy);\n}\n\nvec3 random3(float p) {\n vec3 p3 = fract(vec3(p) * RANDOM_SCALE.xyz);\n p3 += dot(p3, p3.yzx + 19.19);\n return fract((p3.xxy + p3.yzz) * p3.zyx); \n}\n\nvec3 random3(vec2 p) {\n vec3 p3 = fract(vec3(p.xyx) * RANDOM_SCALE.xyz);\n p3 += dot(p3, p3.yxz + 19.19);\n return fract((p3.xxy + p3.yzz) * p3.zyx);\n}\n\nvec3 random3(vec3 p) {\n p = fract(p * RANDOM_SCALE.xyz);\n p += dot(p, p.yxz + 19.19);\n return fract((p.xxy + p.yzz) * p.zyx);\n}\n\nvec4 random4(float p) {\n vec4 p4 = fract(p * RANDOM_SCALE);\n p4 += dot(p4, p4.wzxy + 19.19);\n return fract((p4.xxyz + p4.yzzw) * p4.zywx); \n}\n\nvec4 random4(vec2 p) {\n vec4 p4 = fract(p.xyxy * RANDOM_SCALE);\n p4 += dot(p4, p4.wzxy + 19.19);\n return fract((p4.xxyz + p4.yzzw) * p4.zywx);\n}\n\nvec4 random4(vec3 p) {\n vec4 p4 = fract(p.xyzx * RANDOM_SCALE);\n p4 += dot(p4, p4.wzxy + 19.19);\n return fract((p4.xxyz + p4.yzzw) * p4.zywx);\n}\n\nvec4 random4(vec4 p4) {\n p4 = fract(p4 * RANDOM_SCALE);\n p4 += dot(p4, p4.wzxy + 19.19);\n return fract((p4.xxyz + p4.yzzw) * p4.zywx);\n}\n#endif","/*\ncontributors: Patricio Gonzalez Vivo\ndescription: Signed Random\nuse: srandomX(<vec2|vec3> x)\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef FNC_SRANDOM\n#define FNC_SRANDOM\n\nfloat srandom(in float x) {\n return -1. + 2. * fract(sin(x) * 43758.5453);\n}\n\nfloat srandom(in vec2 st) {\n return -1. + 2. * fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453);\n}\n\nfloat srandom(in vec3 pos) {\n return -1. + 2. * fract(sin(dot(pos.xyz, vec3(70.9898, 78.233, 32.4355))) * 43758.5453123);\n}\n\nfloat srandom(in vec4 pos) {\n float dot_product = dot(pos, vec4(12.9898,78.233,45.164,94.673));\n return -1. + 2. * fract(sin(dot_product) * 43758.5453);\n}\n\nvec2 srandom2(in vec2 st) {\n const vec2 k = vec2(.3183099, .3678794);\n st = st * k + k.yx;\n return -1. + 2. * fract(16. * k * fract(st.x * st.y * (st.x + st.y)));\n}\n\nvec3 srandom3(in vec3 p) {\n p = vec3( dot(p, vec3(127.1, 311.7, 74.7)),\n dot(p, vec3(269.5, 183.3, 246.1)),\n dot(p, vec3(113.5, 271.9, 124.6)));\n return -1. + 2. * fract(sin(p) * 43758.5453123);\n}\n\nvec2 srandom2(in vec2 p, const in float tileLength) {\n p = mod(p, vec2(tileLength));\n return srandom2(p);\n}\n\nvec3 srandom3(in vec3 p, const in float tileLength) {\n p = mod(p, vec3(tileLength));\n return srandom3(p);\n}\n\n#endif","#include \"random.glsl\"\n#include \"srandom.glsl\"\n#include \"../math/cubic.glsl\"\n#include \"../math/quintic.glsl\"\n\n/*\ncontributors: Patricio Gonzalez Vivo\ndescription: Gradient Noise\nuse: gnoise(<float> x)\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef FNC_GNOISE\n#define FNC_GNOISE\n\nfloat gnoise(float x) {\n float i = floor(x); // integer\n float f = fract(x); // fraction\n return mix(random(i), random(i + 1.0), smoothstep(0.,1.,f)); \n}\n\nfloat gnoise(vec2 st) {\n vec2 i = floor(st);\n vec2 f = fract(st);\n float a = random(i);\n float b = random(i + vec2(1.0, 0.0));\n float c = random(i + vec2(0.0, 1.0));\n float d = random(i + vec2(1.0, 1.0));\n vec2 u = cubic(f);\n return mix( a, b, u.x) +\n (c - a)* u.y * (1.0 - u.x) +\n (d - b) * u.x * u.y;\n}\n\nfloat gnoise(vec3 p) {\n vec3 i = floor(p);\n vec3 f = fract(p);\n vec3 u = quintic(f);\n return -1.0 + 2.0 * mix( mix( mix( random(i + vec3(0.0,0.0,0.0)), \n random(i + vec3(1.0,0.0,0.0)), u.x),\n mix( random(i + vec3(0.0,1.0,0.0)), \n random(i + vec3(1.0,1.0,0.0)), u.x), u.y),\n mix( mix( random(i + vec3(0.0,0.0,1.0)), \n random(i + vec3(1.0,0.0,1.0)), u.x),\n mix( random(i + vec3(0.0,1.0,1.0)), \n random(i + vec3(1.0,1.0,1.0)), u.x), u.y), u.z );\n}\n\nfloat gnoise(vec3 p, float tileLength) {\n vec3 i = floor(p);\n vec3 f = fract(p);\n \n vec3 u = quintic(f);\n \n return mix( mix( mix( dot( srandom3(i + vec3(0.0,0.0,0.0), tileLength), f - vec3(0.0,0.0,0.0)), \n dot( srandom3(i + vec3(1.0,0.0,0.0), tileLength), f - vec3(1.0,0.0,0.0)), u.x),\n mix( dot( srandom3(i + vec3(0.0,1.0,0.0), tileLength), f - vec3(0.0,1.0,0.0)), \n dot( srandom3(i + vec3(1.0,1.0,0.0), tileLength), f - vec3(1.0,1.0,0.0)), u.x), u.y),\n mix( mix( dot( srandom3(i + vec3(0.0,0.0,1.0), tileLength), f - vec3(0.0,0.0,1.0)), \n dot( srandom3(i + vec3(1.0,0.0,1.0), tileLength), f - vec3(1.0,0.0,1.0)), u.x),\n mix( dot( srandom3(i + vec3(0.0,1.0,1.0), tileLength), f - vec3(0.0,1.0,1.0)), \n dot( srandom3(i + vec3(1.0,1.0,1.0), tileLength), f - vec3(1.0,1.0,1.0)), u.x), u.y), u.z );\n}\n\nvec3 gnoise3(vec3 x) {\n return vec3(gnoise(x+vec3(123.456, 0.567, 0.37)),\n gnoise(x+vec3(0.11, 47.43, 19.17)),\n gnoise(x) );\n}\n\n#endif","#include \"../math/mod289.glsl\"\n#include \"../math/permute.glsl\"\n#include \"../math/taylorInvSqrt.glsl\"\n#include \"../math/grad4.glsl\"\n\n/*\ncontributors: [Stefan Gustavson, Ian McEwan]\ndescription: Simplex Noise https://github.com/stegu/webgl-noise\nuse: snoise(<vec2|vec3|vec4> pos)\nlicense: |\n Copyright 2021-2023 by Stefan Gustavson and Ian McEwan.\n Published under the terms of the MIT license:\n https://opensource.org/license/mit/\nexamples:\n - /shaders/generative_snoise.frag\n*/\n\n#ifndef FNC_SNOISE\n#define FNC_SNOISE\nfloat snoise(in vec2 v) {\n const vec4 C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0\n 0.366025403784439, // 0.5*(sqrt(3.0)-1.0)\n -0.577350269189626, // -1.0 + 2.0 * C.x\n 0.024390243902439); // 1.0 / 41.0\n // First corner\n vec2 i = floor(v + dot(v, C.yy) );\n vec2 x0 = v - i + dot(i, C.xx);\n\n // Other corners\n vec2 i1;\n //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0\n //i1.y = 1.0 - i1.x;\n i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);\n // x0 = x0 - 0.0 + 0.0 * C.xx ;\n // x1 = x0 - i1 + 1.0 * C.xx ;\n // x2 = x0 - 1.0 + 2.0 * C.xx ;\n vec4 x12 = x0.xyxy + C.xxzz;\n x12.xy -= i1;\n\n // Permutations\n i = mod289(i); // Avoid truncation effects in permutation\n vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))\n + i.x + vec3(0.0, i1.x, 1.0 ));\n\n vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);\n m = m*m ;\n m = m*m ;\n\n // Gradients: 41 points uniformly over a line, mapped onto a diamond.\n // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)\n\n vec3 x = 2.0 * fract(p * C.www) - 1.0;\n vec3 h = abs(x) - 0.5;\n vec3 ox = floor(x + 0.5);\n vec3 a0 = x - ox;\n\n // Normalise gradients implicitly by scaling m\n // Approximation of: m *= inversesqrt( a0*a0 + h*h );\n m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );\n\n // Compute final noise value at P\n vec3 g;\n g.x = a0.x * x0.x + h.x * x0.y;\n g.yz = a0.yz * x12.xz + h.yz * x12.yw;\n return 130.0 * dot(m, g);\n}\n\n\nfloat snoise(in vec3 v) {\n const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;\n const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n // First corner\n vec3 i = floor(v + dot(v, C.yyy) );\n vec3 x0 = v - i + dot(i, C.xxx) ;\n\n // Other corners\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n vec3 i1 = min( g.xyz, l.zxy );\n vec3 i2 = max( g.xyz, l.zxy );\n\n // x0 = x0 - 0.0 + 0.0 * C.xxx;\n // x1 = x0 - i1 + 1.0 * C.xxx;\n // x2 = x0 - i2 + 2.0 * C.xxx;\n // x3 = x0 - 1.0 + 3.0 * C.xxx;\n vec3 x1 = x0 - i1 + C.xxx;\n vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y\n vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y\n\n // Permutations\n i = mod289(i);\n vec4 p = permute( permute( permute(\n i.z + vec4(0.0, i1.z, i2.z, 1.0 ))\n + i.y + vec4(0.0, i1.y, i2.y, 1.0 ))\n + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));\n\n // Gradients: 7x7 points over a square, mapped onto an octahedron.\n // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)\n float n_ = 0.142857142857; // 1.0/7.0\n vec3 ns = n_ * D.wyz - D.xzx;\n\n vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)\n\n vec4 x_ = floor(j * ns.z);\n vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)\n\n vec4 x = x_ *ns.x + ns.yyyy;\n vec4 y = y_ *ns.x + ns.yyyy;\n vec4 h = 1.0 - abs(x) - abs(y);\n\n vec4 b0 = vec4( x.xy, y.xy );\n vec4 b1 = vec4( x.zw, y.zw );\n\n //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;\n //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;\n vec4 s0 = floor(b0)*2.0 + 1.0;\n vec4 s1 = floor(b1)*2.0 + 1.0;\n vec4 sh = -step(h, vec4(0.0));\n\n vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;\n vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;\n\n vec3 p0 = vec3(a0.xy,h.x);\n vec3 p1 = vec3(a0.zw,h.y);\n vec3 p2 = vec3(a1.xy,h.z);\n vec3 p3 = vec3(a1.zw,h.w);\n\n //Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n\n // Mix final noise value\n vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\n m = m * m;\n return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),\n dot(p2,x2), dot(p3,x3) ) );\n}\n\nfloat snoise(in vec4 v) {\n const vec4 C = vec4( 0.138196601125011, // (5 - sqrt(5))/20 G4\n 0.276393202250021, // 2 * G4\n 0.414589803375032, // 3 * G4\n -0.447213595499958); // -1 + 4 * G4\n\n // First corner\n vec4 i = floor(v + dot(v, vec4(.309016994374947451)) ); // (sqrt(5) - 1)/4\n vec4 x0 = v - i + dot(i, C.xxxx);\n\n // Other corners\n\n // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)\n vec4 i0;\n vec3 isX = step( x0.yzw, x0.xxx );\n vec3 isYZ = step( x0.zww, x0.yyz );\n // i0.x = dot( isX, vec3( 1.0 ) );\n i0.x = isX.x + isX.y + isX.z;\n i0.yzw = 1.0 - isX;\n // i0.y += dot( isYZ.xy, vec2( 1.0 ) );\n i0.y += isYZ.x + isYZ.y;\n i0.zw += 1.0 - isYZ.xy;\n i0.z += isYZ.z;\n i0.w += 1.0 - isYZ.z;\n\n // i0 now contains the unique values 0,1,2,3 in each channel\n vec4 i3 = clamp( i0, 0.0, 1.0 );\n vec4 i2 = clamp( i0-1.0, 0.0, 1.0 );\n vec4 i1 = clamp( i0-2.0, 0.0, 1.0 );\n\n // x0 = x0 - 0.0 + 0.0 * C.xxxx\n // x1 = x0 - i1 + 1.0 * C.xxxx\n // x2 = x0 - i2 + 2.0 * C.xxxx\n // x3 = x0 - i3 + 3.0 * C.xxxx\n // x4 = x0 - 1.0 + 4.0 * C.xxxx\n vec4 x1 = x0 - i1 + C.xxxx;\n vec4 x2 = x0 - i2 + C.yyyy;\n vec4 x3 = x0 - i3 + C.zzzz;\n vec4 x4 = x0 + C.wwww;\n\n // Permutations\n i = mod289(i);\n float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x);\n vec4 j1 = permute( permute( permute( permute (\n i.w + vec4(i1.w, i2.w, i3.w, 1.0 ))\n + i.z + vec4(i1.z, i2.z, i3.z, 1.0 ))\n + i.y + vec4(i1.y, i2.y, i3.y, 1.0 ))\n + i.x + vec4(i1.x, i2.x, i3.x, 1.0 ));\n\n // Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope\n // 7*7*6 = 294, which is close to the ring size 17*17 = 289.\n vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ;\n\n vec4 p0 = grad4(j0, ip);\n vec4 p1 = grad4(j1.x, ip);\n vec4 p2 = grad4(j1.y, ip);\n vec4 p3 = grad4(j1.z, ip);\n vec4 p4 = grad4(j1.w, ip);\n\n // Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n p4 *= taylorInvSqrt(dot(p4,p4));\n\n // Mix contributions from the five corners\n vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0);\n vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0);\n m0 = m0 * m0;\n m1 = m1 * m1;\n return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 )))\n + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ;\n}\n\nvec2 snoise2( vec2 x ){\n float s = snoise(vec2( x ));\n float s1 = snoise(vec2( x.y - 19.1, x.x + 47.2 ));\n return vec2( s , s1 );\n}\n\nvec3 snoise3( vec3 x ){\n float s = snoise(vec3( x ));\n float s1 = snoise(vec3( x.y - 19.1 , x.z + 33.4 , x.x + 47.2 ));\n float s2 = snoise(vec3( x.z + 74.2 , x.x - 124.5 , x.y + 99.4 ));\n return vec3( s , s1 , s2 );\n}\n\nvec3 snoise3( vec4 x ){\n float s = snoise(vec4( x ));\n float s1 = snoise(vec4( x.y - 19.1 , x.z + 33.4 , x.x + 47.2, x.w ));\n float s2 = snoise(vec4( x.z + 74.2 , x.x - 124.5 , x.y + 99.4, x.w ));\n return vec3( s , s1 , s2 );\n}\n\n#endif\n","#include \"snoise.glsl\"\n#include \"gnoise.glsl\"\n\n\n/*\ncontributors: Patricio Gonzalez Vivo\ndescription: Fractal Brownian Motion\nuse: fbm(<vec2> pos)\noptions:\n FBM_OCTAVES: numbers of octaves. Default is 4.\n FBM_NOISE_FNC(UV): noise function to use Default 'snoise(UV)' (simplex noise)\n FBM_VALUE_INITIAL: initial value. Default is 0.\n FBM_SCALE_SCALAR: scalar. Default is 2.\n FBM_AMPLITUDE_INITIAL: initial amplitude value. Default is 0.5\n FBM_AMPLITUDE_SCALAR: amplitude scalar. Default is 0.5\nexamples:\n - /shaders/generative_fbm.frag\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef FBM_OCTAVES\n#define FBM_OCTAVES 4\n#endif\n\n#ifndef FBM_NOISE_FNC\n#define FBM_NOISE_FNC(UV) snoise(UV)\n#endif\n\n#ifndef FBM_NOISE2_FNC\n#define FBM_NOISE2_FNC(UV) FBM_NOISE_FNC(UV)\n#endif\n\n#ifndef FBM_NOISE3_FNC\n#define FBM_NOISE3_FNC(UV) FBM_NOISE_FNC(UV)\n#endif\n\n#ifndef FBM_NOISE_TILABLE_FNC\n#define FBM_NOISE_TILABLE_FNC(UV, TILE) gnoise(UV, TILE)\n#endif\n\n#ifndef FBM_NOISE3_TILABLE_FNC\n#define FBM_NOISE3_TILABLE_FNC(UV, TILE) FBM_NOISE_TILABLE_FNC(UV, TILE)\n#endif\n\n#ifndef FBM_NOISE_TYPE\n#define FBM_NOISE_TYPE float\n#endif\n\n#ifndef FBM_VALUE_INITIAL\n#define FBM_VALUE_INITIAL 0.0\n#endif\n\n#ifndef FBM_SCALE_SCALAR\n#define FBM_SCALE_SCALAR 2.0\n#endif\n\n#ifndef FBM_AMPLITUDE_INITIAL\n#define FBM_AMPLITUDE_INITIAL 0.5\n#endif\n\n#ifndef FBM_AMPLITUDE_SCALAR\n#define FBM_AMPLITUDE_SCALAR 0.5\n#endif\n\n#ifndef FNC_FBM\n#define FNC_FBM\nFBM_NOISE_TYPE fbm(in vec2 st) {\n // Initial values\n FBM_NOISE_TYPE value = FBM_NOISE_TYPE(FBM_VALUE_INITIAL);\n float amplitude = FBM_AMPLITUDE_INITIAL;\n\n // Loop of octaves\n for (int i = 0; i < FBM_OCTAVES; i++) {\n value += amplitude * FBM_NOISE2_FNC(st);\n st *= FBM_SCALE_SCALAR;\n amplitude *= FBM_AMPLITUDE_SCALAR;\n }\n return value;\n}\n\nFBM_NOISE_TYPE fbm(in vec3 pos) {\n // Initial values\n FBM_NOISE_TYPE value = FBM_NOISE_TYPE(FBM_VALUE_INITIAL);\n float amplitude = FBM_AMPLITUDE_INITIAL;\n\n // Loop of octaves\n for (int i = 0; i < FBM_OCTAVES; i++) {\n value += amplitude * FBM_NOISE3_FNC(pos);\n pos *= FBM_SCALE_SCALAR;\n amplitude *= FBM_AMPLITUDE_SCALAR;\n }\n return value;\n}\n\nFBM_NOISE_TYPE fbm(vec3 p, float tileLength) {\n const float persistence = 0.5;\n const float lacunarity = 2.0;\n\n float amplitude = 0.5;\n FBM_NOISE_TYPE total = FBM_NOISE_TYPE(0.0);\n float normalization = 0.0;\n\n for (int i = 0; i < FBM_OCTAVES; ++i) {\n float noiseValue = FBM_NOISE3_TILABLE_FNC(p, tileLength * lacunarity * 0.5) * 0.5 + 0.5;\n total += noiseValue * amplitude;\n normalization += amplitude;\n amplitude *= persistence;\n p = p * lacunarity;\n }\n\n return total / normalization;\n}\n#endif\n","#include \"../sampler.glsl\"\n#include \"../math/saturate.glsl\"\n#include \"../math/sum.glsl\"\n\n/*\ncontributors: Patricio Gonzalez Vivo\ndescription: \"morphological dilation operation. Based on: \\n https://lettier.github.io/3d-game-shaders-for-beginners/dilation.html\\n\\\n \\ https://www.shadertoy.com/view/WsyXWc\\n\"\nuse: dilation(<SAMPLER_TYPE> texture, <float2> st, <float2> pixels_scale, <int> passes)\noptions:\n - SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))\n - DILATION_TYPE\n - DILATION_SAMPLE_FNC(TEX, UV)\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef DILATION_TYPE\n#define DILATION_TYPE float\n#endif\n\n#ifndef DILATION_MAX_RADIUS\n#define DILATION_MAX_RADIUS 16\n#endif\n\n#ifndef DILATION_SAMPLE_FNC\n#define DILATION_SAMPLE_FNC(TEX, UV) SAMPLER_FNC(TEX, UV).r\n#endif\n\n#ifndef FNC_DILATE\n#define FNC_DILATE\n\nDILATION_TYPE dilation(SAMPLER_TYPE tex, vec2 st, vec2 pixel, int radius) {\n float invKR = 1.0 / float(radius);\n DILATION_TYPE acc = DILATION_TYPE(0.0);\n float w = 0.0;\n\n #ifdef PLATFORM_WEBGL\n for(int i = -DILATION_MAX_RADIUS; i <= DILATION_MAX_RADIUS; ++i) {\n if (i >= radius) break;\n for(int j = -DILATION_MAX_RADIUS; j <= DILATION_MAX_RADIUS; ++j) {\n if (j >= radius) break;\n #else\n for(int i = -radius; i <= radius; ++i) {\n for(int j = -radius; j <= radius; ++j) {\n #endif\n vec2 rxy = vec2(ivec2(i, j));\n vec2 kst = rxy * invKR * 2.0;\n vec2 texOffset = st + rxy * pixel;\n float kernel = saturate(1.0 - dot(kst, kst));\n DILATION_TYPE t = DILATION_SAMPLE_FNC(tex, texOffset);\n DILATION_TYPE v = t + kernel;\n if (sum(v) > sum(acc)) {\n acc = v;\n w = kernel;\n }\n }\n }\n \n return acc - w;\n}\n\n#endif","/*\ncontributors: Patricio Gonzalez Vivo\ndescription: It defines the default sampler type and function for the shader based on the version of GLSL.\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n#ifndef SAMPLER_FNC\n#if __VERSION__ >= 300\n#define SAMPLER_FNC(TEX, UV) texture(TEX, UV)\n#else\n#define SAMPLER_FNC(TEX, UV) texture2D(TEX, UV)\n#endif\n#endif\n\n#ifndef SAMPLER_TYPE\n#define SAMPLER_TYPE sampler2D\n#endif","#include \"../sampler.glsl\"\n\n/*\ncontributors: Patricio Gonzalez Vivo\ndescription: fakes a clamp to edge texture\nuse: <vec4> sampleClamp2edge(<SAMPLER_TYPE> tex, <vec2> st [, <vec2> texResolution]);\noptions:\n - SAMPLER_FNC(TEX, UV)\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef FNC_SAMPLECLAMP2EDGE\n#define FNC_SAMPLECLAMP2EDGE\nvec4 sampleClamp2edge(SAMPLER_TYPE tex, vec2 st, vec2 texResolution) {\n vec2 pixel = 1.0/texResolution;\n return SAMPLER_FNC( tex, clamp(st, pixel, 1.0-pixel) );\n}\n\nvec4 sampleClamp2edge(SAMPLER_TYPE tex, vec2 st) { \n return SAMPLER_FNC( tex, clamp(st, vec2(0.01), vec2(0.99) ) ); \n}\n\nvec4 sampleClamp2edge(SAMPLER_TYPE tex, vec2 st, float edge) { \n return SAMPLER_FNC( tex, clamp(st, vec2(edge), vec2(1.0 - edge) ) ); \n}\n#endif","/*\ncontributors: Patricio Gonzalez Vivo\ndescription: |\n Draws all the digits of a floating point number, useful for debugging.\n Requires high precision to work properly.\nuse: digits(<vec2> st, <float> value [, <float> nDecDigit])\noptions:\n DIGITS_DECIMALS: number of decimals after the point, defaults to 2\n DIGITS_SIZE: size of the font, defaults to vec2(.025)\nexamples:\n - /shaders/draw_digits.frag\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef DIGITS_SIZE\n#define DIGITS_SIZE vec2(.02)\n#endif\n\n#ifndef DIGITS_DECIMALS\n#define DIGITS_DECIMALS 2.0\n#endif\n\n#ifndef DIGITS_VALUE_OFFSET\n#define DIGITS_VALUE_OFFSET vec2(-6.0, 3.0) \n#endif\n\n#ifndef FNC_DIGITS\n#define FNC_DIGITS\nfloat digits(in vec2 st, in float value, in float nDecDigit) {\n st /= DIGITS_SIZE;\n\n float absValue = abs(value);\n float biggestDigitIndex = max(floor(log2(absValue) / log2(10.)), 0.);\n float counter = floor(absValue);\n float nIntDigits = 1.;\n for (int i = 0; i < 9; i++) {\n counter = floor(counter*.1);\n nIntDigits++;\n if (counter == 0.)\n break;\n }\n\n float digit = 12.;\n float digitIndex = (nIntDigits-1.) - floor(st.x);\n if (digitIndex > (-nDecDigit - 1.5)) {\n if (digitIndex > biggestDigitIndex) {\n if (value < 0.) {\n if (digitIndex < (biggestDigitIndex+1.5)) {\n digit = 11.;\n }\n }\n } \n else {\n if (digitIndex == -1.) {\n if (nDecDigit > 0.) {\n digit = 10.;\n }\n } \n else {\n if (digitIndex < 0.) {\n digitIndex += 1.;\n }\n float digitValue = (absValue / (pow(10., digitIndex)));\n digit = mod(floor(0.0001+digitValue), 10.);\n }\n }\n }\n vec2 pos = vec2(fract(st.x), st.y);\n\n if (pos.x < 0.) return 0.;\n if (pos.y < 0.) return 0.;\n if (pos.x >= 1.) return 0.;\n if (pos.y >= 1.) return 0.;\n\n // make a 4x5 array of bits\n float bin = 0.;\n if (digit < 0.5) // 0\n bin = 7. + 5. * 16. + 5. * 256. + 5. * 4096. + 7. * 65536.; \n else if (digit < 1.5) // 1\n bin = 2. + 2. * 16. + 2. * 256. + 2. * 4096. + 2. * 65536.;\n else if (digit < 2.5) // 2\n bin = 7. + 1. * 16. + 7. * 256. + 4. * 4096. + 7. * 65536.;\n else if (digit < 3.5) // 3\n bin = 7. + 4. * 16. + 7. * 256. + 4. * 4096. + 7. * 65536.;\n else if (digit < 4.5) // 4\n bin = 4. + 7. * 16. + 5. * 256. + 1. * 4096. + 1. * 65536.;\n else if (digit < 5.5) // 5\n bin = 7. + 4. * 16. + 7. * 256. + 1. * 4096. + 7. * 65536.;\n else if (digit < 6.5) // 6\n bin = 7. + 5. * 16. + 7. * 256. + 1. * 4096. + 7. * 65536.;\n else if (digit < 7.5) // 7\n bin = 4. + 4. * 16. + 4. * 256. + 4. * 4096. + 7. * 65536.;\n else if (digit < 8.5) // 8\n bin = 7. + 5. * 16. + 7. * 256. + 5. * 4096. + 7. * 65536.;\n else if (digit < 9.5) // 9\n bin = 7. + 4. * 16. + 7. * 256. + 5. * 4096. + 7. * 65536.;\n else if (digit < 10.5) // '.'\n bin = 2. + 0. * 16. + 0. * 256. + 0. * 4096. + 0. * 65536.;\n else if (digit < 11.5) // '-'\n bin = 0. + 0. * 16. + 7. * 256. + 0. * 4096. + 0. * 65536.;\n\n vec2 pixel = floor(pos * vec2(4., 5.));\n return mod(floor(bin / pow(2., (pixel.x + (pixel.y * 4.)))), 2.);\n}\n\nfloat digits(in vec2 st, in float value, in float nDecDigit, in float nIntDigits) {\n vec2 st2 = st;\n float result = 0.0;\n float dig = nDecDigit;\n\n #ifndef DIGITS_LEADING_INT\n #if defined(PLATFORM_WEBGL)\n #define DIGITS_LEADING_INT 1.0\n #else\n #define DIGITS_LEADING_INT nIntDigits\n #endif\n #endif\n\n for (float i = DIGITS_LEADING_INT - 1.0; i > 0.0 ; i--) {\n if (i * 10.0 > value) {\n result += digits(st2, 0.0, 0.0);\n st2.x -= DIGITS_SIZE.x;\n }\n }\n result += digits(st2, value, nDecDigit);\n return result; \n}\n\nfloat digits(in vec2 st, in int value) {\n return digits(st, float(value), 0.0);\n}\n\nfloat digits(in vec2 st, in float value) {\n return digits(st, value, (DIGITS_DECIMALS));\n}\n\nfloat digits(in vec2 st, in vec2 v) {\n float rta = 0.0;\n for (int i = 0; i < 2; i++) {\n vec2 pos = st + vec2(float(i), 0.0) * DIGITS_SIZE * DIGITS_VALUE_OFFSET;\n float value = i == 0 ? v.x : v.y;\n rta += digits( pos, value );\n }\n return rta;\n}\n\nfloat digits(in vec2 st, in vec3 v) {\n float rta = 0.0;\n for (int i = 0; i < 3; i++) {\n vec2 pos = st + vec2(float(i), 0.0) * DIGITS_SIZE * DIGITS_VALUE_OFFSET;\n float value = i == 0 ? v.x : i == 1 ? v.y : v.z;\n rta += digits( pos, value );\n }\n return rta;\n}\n\nfloat digits(in vec2 st, in vec4 v) {\n float rta = 0.0;\n for (int i = 0; i < 4; i++) {\n vec2 pos = st + vec2(float(i), 0.0) * DIGITS_SIZE * DIGITS_VALUE_OFFSET;\n float value = i == 0 ? v.x : i == 1 ? v.y : i == 2 ? v.z : v.w;\n rta += digits( pos, value );\n }\n return rta;\n}\n\nfloat digits(in vec2 st, in mat2 _matrix) {\n float rta = 0.0;\n for (int i = 0; i < 2; i++) {\n for (int j = 0; j < 2; j++) {\n vec2 pos = st + vec2(float(i), float(j)) * DIGITS_SIZE * DIGITS_VALUE_OFFSET - DIGITS_SIZE * vec2(0.0, 3.0);\n float value = _matrix[j][i];\n rta += digits( pos, value );\n }\n }\n return rta;\n}\n\nfloat digits(in vec2 st, in mat3 _matrix) {\n float rta = 0.0;\n for (int i = 0; i < 3; i++) {\n for (int j = 0; j < 3; j++) {\n vec2 pos = st + vec2(float(i), float(j)) * DIGITS_SIZE * DIGITS_VALUE_OFFSET - DIGITS_SIZE * vec2(0.0, 6.0);\n float value = _matrix[j][i];\n rta += digits( pos, value );\n }\n }\n return rta;\n}\n\nfloat digits(in vec2 st, in mat4 _matrix) {\n float rta = 0.0;\n for (int i = 0; i < 4; i++) {\n for (int j = 0; j < 4; j++) {\n vec2 pos = st + vec2(float(i), float(j)) * DIGITS_SIZE * DIGITS_VALUE_OFFSET - DIGITS_SIZE * vec2(0.0, 9.0);\n float value = _matrix[j][i];\n rta += digits( pos, value );\n }\n }\n return rta;\n}\n#endif\n","#include \"../sampler.glsl\"\n\n/*\ncontributors:\n - Matt DesLauriers\n - Patricio Gonzalez Vivo\ndescription: Adapted versions from 5, 9 and 13 gaussian fast blur from https://github.com/Jam3/glsl-fast-gaussian-blur\nuse: gaussianBlur(<SAMPLER_TYPE> texture, <vec2> st, <vec2> pixel_direction [, const int kernelSize])\noptions:\n - GAUSSIANBLUR_AMOUNT: gaussianBlur5 gaussianBlur9 gaussianBlur13\n - GAUSSIANBLUR_2D: default to 1D\n - SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))\nexamples:\n - /shaders/filter_gaussianBlur2D.frag\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef GAUSSIANBLUR_AMOUNT\n#define GAUSSIANBLUR_AMOUNT gaussianBlur13\n#endif\n\n#ifndef GAUSSIANBLUR_TYPE\n#define GAUSSIANBLUR_TYPE vec4\n#endif\n\n#ifndef GAUSSIANBLUR_SAMPLER_FNC\n#define GAUSSIANBLUR_SAMPLER_FNC(TEX, UV) SAMPLER_FNC(TEX, UV)\n#endif\n\n#include \"gaussianBlur/2D.glsl\"\n#include \"gaussianBlur/1D.glsl\"\n#include \"gaussianBlur/1D_fast13.glsl\"\n#include \"gaussianBlur/1D_fast9.glsl\"\n#include \"gaussianBlur/1D_fast5.glsl\"\n\n#ifndef FNC_GAUSSIANBLUR\n#define FNC_GAUSSIANBLUR\nGAUSSIANBLUR_TYPE gaussianBlur13(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset) {\n#ifdef GAUSSIANBLUR_2D\n return gaussianBlur2D(tex, st, offset, 7);\n#else\n return gaussianBlur1D_fast13(tex, st, offset);\n#endif\n}\n\nGAUSSIANBLUR_TYPE gaussianBlur9(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset) {\n#ifdef GAUSSIANBLUR_2D\n return gaussianBlur2D(tex, st, offset, 5);\n#else\n return gaussianBlur1D_fast9(tex, st, offset);\n#endif\n}\n\nGAUSSIANBLUR_TYPE gaussianBlur5(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset) {\n#ifdef GAUSSIANBLUR_2D\n return gaussianBlur2D(tex, st, offset, 3);\n#else\n return gaussianBlur1D_fast5(tex, st, offset);\n#endif\n}\n\nGAUSSIANBLUR_TYPE gaussianBlur(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset, const int kernelSize) {\n#ifdef GAUSSIANBLUR_2D\n return gaussianBlur2D(tex, st, offset, kernelSize);\n#else\n return gaussianBlur1D(tex, st, offset, kernelSize);\n#endif\n}\n\nGAUSSIANBLUR_TYPE gaussianBlur(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset) {\n return GAUSSIANBLUR_AMOUNT(tex, st, offset);\n}\n#endif\n","#include \"../../math/gaussian.glsl\"\n#include \"../../sample/clamp2edge.glsl\"\n\n/*\ncontributors: Patricio Gonzalez Vivo\ndescription: Two dimension Gaussian Blur to be applied in only one passes\nuse: gaussianBlur2D(<SAMPLER_TYPE> texture, <vec2> st, <vec2> pixel_direction, const int kernelSize)\noptions:\n - SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))\n - GAUSSIANBLUR2D_TYPE: Default `vec4`\n - GAUSSIANBLUR2D_SAMPLER_FNC(TEX, UV): Default `texture2D(tex, TEX, UV)`\n - GAUSSIANBLUR2D_KERNELSIZE: Use only for WebGL 1.0 and OpenGL ES 2.0 . For example RaspberryPis is not happy with dynamic loops. Default is 'kernelSize'\nexamples:\n - /shaders/filter_gaussianBlur2D.frag\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef GAUSSIANBLUR2D_TYPE\n#ifdef GAUSSIANBLUR_TYPE\n#define GAUSSIANBLUR2D_TYPE GAUSSIANBLUR_TYPE\n#else\n#define GAUSSIANBLUR2D_TYPE vec4\n#endif\n#endif\n\n#ifndef GAUSSIANBLUR2D_SAMPLER_FNC\n#ifdef GAUSSIANBLUR_SAMPLER_FNC\n#define GAUSSIANBLUR2D_SAMPLER_FNC(TEX, UV) GAUSSIANBLUR_SAMPLER_FNC(TEX, UV)\n#else\n#define GAUSSIANBLUR2D_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#endif\n#endif\n\n#ifndef FNC_GAUSSIANBLUR2D\n#define FNC_GAUSSIANBLUR2D\nGAUSSIANBLUR2D_TYPE gaussianBlur2D(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset, const int kernelSize) {\n GAUSSIANBLUR2D_TYPE accumColor = GAUSSIANBLUR2D_TYPE(0.);\n \n #ifndef GAUSSIANBLUR2D_KERNELSIZE\n \n #if defined(PLATFORM_WEBGL)\n #define GAUSSIANBLUR2D_KERNELSIZE 20\n float kernelSizef = float(kernelSize);\n #else\n #define GAUSSIANBLUR2D_KERNELSIZE kernelSize\n float kernelSizef = float(GAUSSIANBLUR2D_KERNELSIZE);\n #endif\n\n #else\n float kernelSizef = float(GAUSSIANBLUR2D_KERNELSIZE);\n #endif\n\n float accumWeight = 0.;\n const float k = 0.15915494; // 1 / (2*PI)\n vec2 xy = vec2(0.0);\n for (int j = 0; j < GAUSSIANBLUR2D_KERNELSIZE; j++) {\n #if defined(PLATFORM_WEBGL)\n if (j >= kernelSize)\n break;\n #endif\n xy.y = -.5 * (kernelSizef - 1.) + float(j);\n for (int i = 0; i < GAUSSIANBLUR2D_KERNELSIZE; i++) {\n #if defined(PLATFORM_WEBGL)\n if (i >= kernelSize)\n break;\n #endif\n xy.x = -0.5 * (kernelSizef - 1.) + float(i);\n float weight = (k / kernelSizef) * gaussian(xy, kernelSizef);\n accumColor += weight * GAUSSIANBLUR2D_SAMPLER_FNC(tex, st + xy * offset);\n accumWeight += weight;\n }\n }\n return accumColor / accumWeight;\n}\n#endif\n","#include \"../../math/gaussian.glsl\"\n#include \"../../sample/clamp2edge.glsl\"\n\n/*\ncontributors: Patricio Gonzalez Vivo\ndescription: One dimension Gaussian Blur to be applied in two passes\nuse: gaussianBlur1D(<SAMPLER_TYPE> texture, <vec2> st, <vec2> pixel_direction , const int kernelSize)\noptions:\n - SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))\n - GAUSSIANBLUR1D_TYPE: null\n - GAUSSIANBLUR1D_SAMPLER_FNC(TEX, UV): null\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef GAUSSIANBLUR1D_TYPE\n#ifdef GAUSSIANBLUR_TYPE\n#define GAUSSIANBLUR1D_TYPE GAUSSIANBLUR_TYPE\n#else\n#define GAUSSIANBLUR1D_TYPE vec4\n#endif\n#endif\n\n#ifndef GAUSSIANBLUR1D_SAMPLER_FNC\n#ifdef GAUSSIANBLUR_SAMPLER_FNC\n#define GAUSSIANBLUR1D_SAMPLER_FNC(TEX, UV) GAUSSIANBLUR_SAMPLER_FNC(TEX, UV)\n#else\n#define GAUSSIANBLUR1D_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#endif\n#endif\n\n#ifndef FNC_GAUSSIANBLUR1D\n#define FNC_GAUSSIANBLUR1D\n\n#ifdef PLATFORM_WEBGL\n\nGAUSSIANBLUR1D_TYPE gaussianBlur1D(in SAMPLER_TYPE tex,in vec2 st,in vec2 offset,const int kernelSize){\n GAUSSIANBLUR1D_TYPE accumColor = GAUSSIANBLUR1D_TYPE(0.0);\n\n float kernelSizef = float(kernelSize);\n float accumWeight = 0.0;\n const float k = 0.39894228;// 1 / sqrt(2*PI)\n for (int i = 0; i < 16; i++) {\n if( i >= kernelSize)\n break;\n float x = -0.5 * (float(kernelSize) - 1.0)+float(i);\n float weight = (k/float(kernelSize)) * gaussian(x, kernelSizef);\n GAUSSIANBLUR1D_TYPE tex = GAUSSIANBLUR1D_SAMPLER_FNC(tex, st + x * offset);\n accumColor += weight * tex;\n accumWeight += weight;\n }\n return accumColor/accumWeight;\n}\n\n#else\n\nGAUSSIANBLUR1D_TYPE gaussianBlur1D(in SAMPLER_TYPE tex,in vec2 st,in vec2 offset,const int kernelSize){\n GAUSSIANBLUR1D_TYPE accumColor=GAUSSIANBLUR1D_TYPE(0.);\n\n float kernelSizef = float(kernelSize);\n \n float accumWeight = 0.0;\n const float k = 0.39894228;// 1 / sqrt(2*PI)\n for (int i = 0; i < kernelSize; i++) {\n float x = -0.5 * ( kernelSizef -1.0) + float(i);\n float weight = (k / kernelSizef) * gaussian(x, kernelSizef);\n GAUSSIANBLUR1D_TYPE tex = GAUSSIANBLUR1D_SAMPLER_FNC(tex, st + x * offset);\n accumColor += weight * tex;\n accumWeight += weight;\n }\n return accumColor/accumWeight;\n}\n#endif\n\n#endif\n","#include \"../../sample/clamp2edge.glsl\"\n\n/*\nfunction: gaussianBlur1D_fast13\ncontributors: Matt DesLauriers\ndescription: Adapted versions of gaussian fast blur 13 from https://github.com/Jam3/glsl-fast-gaussian-blur\nuse: gaussianBlur1D_fast13(<SAMPLER_TYPE> texture, <vec2> st, <vec2> pixel_direction)\noptions:\n - SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))\n - GAUSSIANBLUR1D_FAST13_TYPE\n - GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(TEX, UV)\n*/\n\n#ifndef GAUSSIANBLUR1D_FAST13_TYPE\n#ifdef GAUSSIANBLUR_TYPE\n#define GAUSSIANBLUR1D_FAST13_TYPE GAUSSIANBLUR_TYPE\n#else\n#define GAUSSIANBLUR1D_FAST13_TYPE vec4\n#endif\n#endif\n\n#ifndef GAUSSIANBLUR1D_FAST13_SAMPLER_FNC\n#ifdef GAUSSIANBLUR_SAMPLER_FNC\n#define GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(TEX, UV) GAUSSIANBLUR_SAMPLER_FNC(TEX, UV)\n#else\n#define GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#endif\n#endif\n\n#ifndef FNC_GAUSSIANBLUR1D_FAST13\n#define FNC_GAUSSIANBLUR1D_FAST13\nGAUSSIANBLUR1D_FAST13_TYPE gaussianBlur1D_fast13(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset) {\n GAUSSIANBLUR1D_FAST13_TYPE color = GAUSSIANBLUR1D_FAST13_TYPE(0.);\n vec2 off1 = vec2(1.411764705882353) * offset;\n vec2 off2 = vec2(3.2941176470588234) * offset;\n vec2 off3 = vec2(5.176470588235294) * offset;\n color += GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(tex, st) * .1964825501511404;\n color += GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(tex, st + (off1)) * .2969069646728344;\n color += GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(tex, st - (off1)) * .2969069646728344;\n color += GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(tex, st + (off2)) * .09447039785044732;\n color += GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(tex, st - (off2)) * .09447039785044732;\n color += GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(tex, st + (off3)) * .010381362401148057;\n color += GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(tex, st - (off3)) * .010381362401148057;\n return color;\n}\n#endif\n","#include \"../../sample/clamp2edge.glsl\"\n\n/*\ncontributors: Matt DesLauriers\ndescription: Adapted versions of gaussian fast blur 13 from https://github.com/Jam3/glsl-fast-gaussian-blur\nuse: gaussianBlur1D_fast9(<SAMPLER_TYPE> texture, <vec2> st, <vec2> pixel_direction)\noptions:\n - SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))\n - GAUSSIANBLUR1D_FAST9_TYPE\n - GAUSSIANBLUR1D_FAST9_SAMPLER_FNC(TEX, UV)\n*/\n\n#ifndef GAUSSIANBLUR1D_FAST9_TYPE\n#ifdef GAUSSIANBLUR_TYPE\n#define GAUSSIANBLUR1D_FAST9_TYPE GAUSSIANBLUR_TYPE\n#else\n#define GAUSSIANBLUR1D_FAST9_TYPE vec4\n#endif\n#endif\n\n#ifndef GAUSSIANBLUR1D_FAST9_SAMPLER_FNC\n#ifdef GAUSSIANBLUR_SAMPLER_FNC\n#define GAUSSIANBLUR1D_FAST9_SAMPLER_FNC(TEX, UV) GAUSSIANBLUR_SAMPLER_FNC(TEX, UV)\n#else\n#define GAUSSIANBLUR1D_FAST9_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#endif\n#endif\n\n#ifndef FNC_GAUSSIANBLUR1D_FAST9\n#define FNC_GAUSSIANBLUR1D_FAST9\nGAUSSIANBLUR1D_FAST9_TYPE gaussianBlur1D_fast9(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset) {\n GAUSSIANBLUR1D_FAST9_TYPE color = GAUSSIANBLUR1D_FAST9_TYPE(0.);\n vec2 off1 = vec2(1.3846153846) * offset;\n vec2 off2 = vec2(3.2307692308) * offset;\n color += GAUSSIANBLUR1D_FAST9_SAMPLER_FNC(tex, st) * .2270270270;\n color += GAUSSIANBLUR1D_FAST9_SAMPLER_FNC(tex, st + (off1)) * .3162162162;\n color += GAUSSIANBLUR1D_FAST9_SAMPLER_FNC(tex, st - (off1)) * .3162162162;\n color += GAUSSIANBLUR1D_FAST9_SAMPLER_FNC(tex, st + (off2)) * .0702702703;\n color += GAUSSIANBLUR1D_FAST9_SAMPLER_FNC(tex, st - (off2)) * .0702702703;\n return color;\n}\n#endif\n","#include \"../../sample/clamp2edge.glsl\"\n\n/*\ncontributors: Matt DesLauriers\ndescription: Adapted versions of gaussian fast blur 13 from https://github.com/Jam3/glsl-fast-gaussian-blur\nuse: gaussianBlur1D_fast5(<SAMPLER_TYPE> texture, <vec2> st, <vec2> pixel_direction)\noptions:\n - SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))\n - GAUSSIANBLUR1D_FAST5_TYPE\n - GAUSSIANBLUR1D_FAST5_SAMPLER_FNC(TEX, UV)\n*/\n\n#ifndef GAUSSIANBLUR1D_FAST5_TYPE\n#ifdef GAUSSIANBLUR_TYPE\n#define GAUSSIANBLUR1D_FAST5_TYPE GAUSSIANBLUR_TYPE\n#else\n#define GAUSSIANBLUR1D_FAST5_TYPE vec4\n#endif\n#endif\n\n#ifndef GAUSSIANBLUR1D_FAST5_SAMPLER_FNC\n#ifdef GAUSSIANBLUR_SAMPLER_FNC\n#define GAUSSIANBLUR1D_FAST5_SAMPLER_FNC(TEX, UV) GAUSSIANBLUR_SAMPLER_FNC(TEX, UV)\n#else\n#define GAUSSIANBLUR1D_FAST5_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#endif\n#endif\n\n#ifndef FNC_GAUSSIANBLUR1D_FAST5\n#define FNC_GAUSSIANBLUR1D_FAST5\nGAUSSIANBLUR1D_FAST5_TYPE gaussianBlur1D_fast5(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset) {\n GAUSSIANBLUR1D_FAST5_TYPE color = GAUSSIANBLUR1D_FAST5_TYPE(0.);\n vec2 off1 = vec2(1.3333333333333333) * offset;\n color += GAUSSIANBLUR1D_FAST5_SAMPLER_FNC(tex, st) * .29411764705882354;\n color += GAUSSIANBLUR1D_FAST5_SAMPLER_FNC(tex, st + (off1)) * .35294117647058826;\n color += GAUSSIANBLUR1D_FAST5_SAMPLER_FNC(tex, st - (off1)) * .35294117647058826;\n return color;\n}\n#endif\n","#include \"../sampler.glsl\"\n\n/*\ncontributors: [Brad Larson, Ben Cochran, Hugues Lismonde, Keitaroh Kobayashi, Alaric Cole, Matthew Clark, Jacob Gundersen, Chris Williams.]\ndescription: Kuwahara image abstraction, drawn from the work of Kyprianidis, et. al. in their publication \"Anisotropic Kuwahara Filtering on the GPU\" within the GPU Pro collection. This produces an oil-painting-like image, but it is extremely computationally expensive, so it can take seconds to render a frame on an iPad 2. This might be best used for still images.\nuse: kuwahara(<SAMPLER_TYPE> texture, <vec2> st, <vec2> pixel, <float> radius)\noptions:\n - KUWAHARA_TYPE: defaults to vec3\n - KUWAHARA_SAMPLER_FNC(TEX, UV): defaults to texture2D(tex, TEX, UV).rgb\n - KUWAHARA_RADIUS radius\n - SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))\n*/\n\n#ifndef KUWAHARA_TYPE\n#define KUWAHARA_TYPE vec4\n#endif\n\n#ifndef KUWAHARA_SAMPLER_FNC\n#define KUWAHARA_SAMPLER_FNC(TEX, UV) SAMPLER_FNC(TEX, UV)\n#endif\n\n#ifndef FNC_KUWAHARA\n#define FNC_KUWAHARA\n\n#ifdef TARGET_MOBILE\nKUWAHARA_TYPE kuwahara(in SAMPLER_TYPE tex, in vec2 st, in vec2 pixel, in float radius) {\n\n #ifndef KUWAHARA_RADIUS\n #define KUWAHARA_RADIUS radius\n #endif\n\n float n = (KUWAHARA_RADIUS + 1.0) * (KUWAHARA_RADIUS + 1.0);\n KUWAHARA_TYPE m0 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE m1 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE m2 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE m3 = KUWAHARA_TYPE(0.0);\n KUWAHARA_TYPE s0 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE s1 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE s2 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE s3 = KUWAHARA_TYPE(0.0);\n KUWAHARA_TYPE rta = KUWAHARA_TYPE(0.0);\n KUWAHARA_TYPE c = KUWAHARA_TYPE(0.0);\n\n for (float j = -KUWAHARA_RADIUS; j <= 0.0; ++j) {\n for (float i = -KUWAHARA_RADIUS; i <= 0.0; ++i) {\n c = KUWAHARA_SAMPLER_FNC(tex, st + vec2(i,j) * pixel);\n m0 += c;\n s0 += c * c;\n }\n }\n\n for (float j = -KUWAHARA_RADIUS; j <= 0.0; ++j) {\n for (float i = 0.0; i <= KUWAHARA_RADIUS; ++i) {\n c = KUWAHARA_SAMPLER_FNC(tex, st + vec2(i,j) * pixel);\n m1 += c;\n s1 += c * c;\n }\n }\n\n for (float j = 0.0; j <= KUWAHARA_RADIUS; ++j) {\n for (float i = 0.0; i <= KUWAHARA_RADIUS; ++i) {\n c = KUWAHARA_SAMPLER_FNC(tex, st + vec2(i,j) * pixel);\n m2 += c;\n s2 += c * c;\n }\n }\n\n for (float j = 0.0; j <= KUWAHARA_RADIUS; ++j) {\n for (float i = -KUWAHARA_RADIUS; i <= 0.0; ++i) {\n c = KUWAHARA_SAMPLER_FNC(tex, st + vec2(i,j) * pixel);\n m3 += c;\n s3 += c * c;\n }\n }\n\n float min_sigma2 = 1e+2;\n m0 /= n;\n s0 = abs(s0 / n - m0 * m0);\n\n float sigma2 = s0.r + s0.g + s0.b;\n if (sigma2 < min_sigma2) {\n min_sigma2 = sigma2;\n rta = m0;\n }\n\n m1 /= n;\n s1 = abs(s1 / n - m1 * m1);\n\n sigma2 = s1.r + s1.g + s1.b;\n if (sigma2 < min_sigma2) {\n min_sigma2 = sigma2;\n rta = m1;\n }\n\n m2 /= n;\n s2 = abs(s2 / n - m2 * m2);\n\n sigma2 = s2.r + s2.g + s2.b;\n if (sigma2 < min_sigma2) {\n min_sigma2 = sigma2;\n rta = m2;\n }\n\n m3 /= n;\n s3 = abs(s3 / n - m3 * m3);\n\n sigma2 = s3.r + s3.g + s3.b;\n if (sigma2 < min_sigma2) {\n min_sigma2 = sigma2;\n rta = m3;\n }\n\n return rta;\n}\n\n#else\n\nKUWAHARA_TYPE kuwahara(in SAMPLER_TYPE tex, in vec2 st, in vec2 pixel, in float radius) {\n\n #ifndef KUWAHARA_RADIUS\n\n #if defined(PLATFORM_WEBGL)\n #define KUWAHARA_RADIUS 20.0\n float n = (radius + 1.0) * (radius + 1.0);\n #else\n #define KUWAHARA_RADIUS radius\n float n = (KUWAHARA_RADIUS + 1.0) * (KUWAHARA_RADIUS + 1.0);\n #endif\n\n #else\n float n = (KUWAHARA_RADIUS + 1.0) * (KUWAHARA_RADIUS + 1.0);\n #endif\n\n KUWAHARA_TYPE m0 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE m1 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE m2 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE m3 = KUWAHARA_TYPE(0.0);\n KUWAHARA_TYPE s0 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE s1 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE s2 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE s3 = KUWAHARA_TYPE(0.0);\n KUWAHARA_TYPE rta = KUWAHARA_TYPE(0.0);\n KUWAHARA_TYPE c = KUWAHARA_TYPE(0.0);\n \n for (float j = -KUWAHARA_RADIUS; j <= 0.0; ++j) { \n for (float i = -KUWAHARA_RADIUS; i <= 0.0; ++i) {\n c = KUWAHARA_SAMPLER_FNC(tex, st + vec2(i,j) * pixel);\n m0 += c;\n s0 += c * c;\n }\n }\n \n for (float j = -KUWAHARA_RADIUS; j <= 0.0; ++j) {\n for (float i = 0.0; i <= KUWAHARA_RADIUS; ++i) {\n #if defined(PLATFORM_WEBGL)\n if (i > radius)\n break;\n #endif\n c = KUWAHARA_SAMPLER_FNC(tex, st + vec2(i,j) * pixel);\n m1 += c;\n s1 += c * c;\n }\n }\n \n for (float j = 0.0; j <= KUWAHARA_RADIUS; ++j) {\n #if defined(PLATFORM_WEBGL)\n if (j > radius)\n break;\n #endif\n for (float i = 0.0; i <= KUWAHARA_RADIUS; ++i) {\n #if defined(PLATFORM_WEBGL)\n if (i > radius)\n break;\n #endif\n c = KUWAHARA_SAMPLER_FNC(tex, st + vec2(i,j) * pixel);\n m2 += c;\n s2 += c * c;\n }\n }\n \n for (float j = 0.0; j <= KUWAHARA_RADIUS; ++j) {\n for (float i = -KUWAHARA_RADIUS; i <= 0.0; ++i) {\n c = KUWAHARA_SAMPLER_FNC(tex, st + vec2(i,j) * pixel);\n m3 += c;\n s3 += c * c;\n }\n }\n \n \n float min_sigma2 = 1e+2;\n m0 /= n;\n s0 = abs(s0 / n - m0 * m0);\n \n float sigma2 = s0.r + s0.g + s0.b;\n if (sigma2 < min_sigma2) {\n min_sigma2 = sigma2;\n rta = m0;\n }\n \n m1 /= n;\n s1 = abs(s1 / n - m1 * m1);\n \n sigma2 = s1.r + s1.g + s1.b;\n if (sigma2 < min_sigma2) {\n min_sigma2 = sigma2;\n rta = m1;\n }\n \n m2 /= n;\n s2 = abs(s2 / n - m2 * m2);\n \n sigma2 = s2.r + s2.g + s2.b;\n if (sigma2 < min_sigma2) {\n min_sigma2 = sigma2;\n rta = m2;\n }\n \n m3 /= n;\n s3 = abs(s3 / n - m3 * m3);\n \n sigma2 = s3.r + s3.g + s3.b;\n if (sigma2 < min_sigma2) {\n min_sigma2 = sigma2;\n rta = m3;\n }\n\n return rta;\n}\n\n#endif\n\n#endif","export const glsl = (x: TemplateStringsArray): string => String.raw(x)\n","import { glsl } from './glsl'\n\nexport default glsl`\nmat3 rotationX(float angle) {\n float s = sin(angle);\n float c = cos(angle);\n return mat3(\n 1.0, 0.0, 0.0,\n 0.0, c, -s,\n 0.0, s, c\n );\n}\n\nmat3 rotationY(float angle) {\n float s = sin(angle);\n float c = cos(angle);\n return mat3(\n c, 0.0, s,\n 0.0, 1.0, 0.0,\n -s, 0.0, c\n );\n}\n\nvec4 defaultLighting(vec4 color, vec2 res, vec2 rot, float diff) {\n float aspectRatio = res.y / res.x;\n vec2 uv = (gl_FragCoord.xy / res.xy) * 2.0 - 1.0;\n vec2 specPos = vec2(rot.x * 3.8, rot.y * 2.2);\n\n vec3 baseNormal = vec3(0.0, 0.0, 1.0);\n mat3 rotMatrix = rotationX(rot.y) * rotationY(rot.x);\n vec3 normal = normalize(rotMatrix * baseNormal);\n\n vec3 lightDir = normalize(vec3(0.1, 0.5, 1.0));\n vec3 viewDir = normalize(vec3(0.0, 0.0, 1.0));\n\n vec3 halfDir = normalize(lightDir + viewDir);\n float spec = pow(max(dot(normal, halfDir), 0.0), 64.0);\n\n vec2 diffPos = uv - specPos;\n diffPos.y *= aspectRatio;\n float dist = length(diffPos);\n float mask = exp(-dist * 0.6);\n float lightFalloff = 1.0 / (dist + 1.3);\n spec *= mask * lightFalloff;\n\n return vec4(color.rgb * diff + vec3(1.0) * spec, 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n// three.js built-in attributes\n// attribute vec3 position;\n// attribute vec3 normal;\n// attribute vec2 uv;\n\n// three.js built-in uniforms\n// uniform mat4 modelMatrix; // a.k.a worldMatrix\n// uniform mat4 viewMatrix;\n// uniform mat4 modelViewMatrix;\n// uniform mat3 normalMatrix;\n// uniform mat4 projectionMatrix;\n// uniform vec3 cameraPosition;\n\n// world transformed attributes for the fragment shader\nvarying vec3 vNormal;\nvarying vec3 vPosition;\nvarying vec2 vUv;\nvarying vec3 vView;\n\nvoid main() {\n // vec4 pos = viewMatrix * modelMatrix * vec4(position, 1.0);\n vec4 pos = modelViewMatrix * vec4(position, 1.0);\n\n // normalMatrix = transpose(inverse(mat3(modelMatrix)));\n // because transform matrix for normal vector is L^-1T\n vUv = uv;\n vPosition = pos.xyz;\n vView = normalize(cameraPosition - vPosition);\n vNormal = normalize(normalMatrix * normal);\n\n // transform the position to clip space\n gl_Position = projectionMatrix * pos;\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n#include <utils/defaultLighting>\n\nvoid main() {\n // 기본 카드 텍스처 샘플링\n vec4 baseColor = texture2D(uImgBase, vUv);\n\n // 팝업 텍스처 샘플링 (움직임 반영)\n float popupOffset = 0.0;\n vec2 popupUv = vUv + (uMove / uResolution) * popupOffset; // 팝업 이동 효과\n vec4 popupColor = texture2D(uImgPopup, popupUv);\n\n float aSoft = smoothstep(0.4, 1.0, popupColor.a);\n vec4 pocaColor = mix(baseColor, popupColor, aSoft);\n\n gl_FragColor = defaultLighting(pocaColor, uResolution, uRotate, 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n#include <utils/defaultLighting>\n\nvoid main() {\n // 기본 카드 텍스처 샘플링\n vec4 baseColor = texture2D(uImgBase, vUv);\n\n // 팝업 텍스처 샘플링 (움직임 반영)\n vec2 popupOffset = vec2(-uRotate.x * 0.08, -uRotate.y * 0.06);\n vec2 popupUv = vUv + popupOffset; // 팝업 이동 효과\n vec4 popupColor = texture2D(uImgPopup, popupUv);\n\n float aSoft = smoothstep(0.4, 1.0, popupColor.a);\n vec4 pocaColor = mix(baseColor, popupColor, aSoft);\n\n gl_FragColor = defaultLighting(pocaColor, uResolution, uRotate, 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n#define mod289(x) mod(x, 289.)\n\nvec3 permute(vec3 x) { return mod289(((x * 34.0) + 1.0) * x); }\n\nfloat snoise(vec2 coord) {\n const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439);\n vec2 intPart = floor(coord + dot(coord, C.yy));\n vec2 fracPart = coord - intPart + dot(intPart, C.xx);\n\n vec2 offset;\n offset = (fracPart.x > fracPart.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);\n vec4 combined = fracPart.xyxy + C.xxzz;\n combined.xy -= offset;\n\n intPart = mod289(intPart);\n vec3 perm = permute(permute(intPart.y + vec3(0.0, offset.y, 1.0))\n + intPart.x + vec3(0.0, offset.x, 1.0));\n\n vec3 gradient = max(0.5 - vec3(dot(fracPart, fracPart), dot(combined.xy, combined.xy), dot(combined.zw, combined.zw)), 0.0);\n gradient *= gradient;\n gradient *= gradient;\n\n vec3 noiseVec = 2.0 * fract(perm * C.www) - 1.0;\n vec3 absDiff = abs(noiseVec) - 0.5;\n vec3 offsetVec = floor(noiseVec + 0.5);\n vec3 gradientVec = noiseVec - offsetVec;\n\n gradient *= 1.79284291400159 - 0.85373472095314 * (gradientVec * gradientVec + absDiff * absDiff);\n\n vec3 finalGrad;\n finalGrad.x = gradientVec.x * fracPart.x + absDiff.x * fracPart.y;\n finalGrad.yz = gradientVec.yz * combined.xz + absDiff.yz * combined.yw;\n\n return 130.0 * dot(gradient, finalGrad);\n}\n\nfloat fbm(vec2 position) {\n float result = 0.0;\n float weight = 0.5;\n for (int i = 0; i < 5; i++) {\n result += weight * snoise(position);\n position *= 2.0;\n weight *= 0.5;\n }\n return result;\n}\n\n// snowfall\nconst int LAYERS = 66;\nconst float DEPTH_NEAR = 0.3;\nconst float WIDTH_NEAR = 0.4;\nconst float SPEED_NEAR = 0.6;\nconst float DEPTH_FAR = 0.1;\nconst float WIDTH_FAR = 0.3;\nconst float SPEED_FAR = 0.1;\n\nfloat computeSnow(in vec2 uv, int layerStart, int layerEnd) {\n const mat3 permutationMatrix = mat3(13.323122, 23.5112, 21.71123, 21.1212, 28.7312, 11.9312, 21.8112, 14.7212, 61.3934);\n vec2 moveNormalized = uMove.xy / uResolution.xy;\n moveNormalized.x = max(0.15, smoothstep(0.15, 0.8, moveNormalized.x));\n uv.x += moveNormalized.x * 0.2;\n float totalLayers = float(LAYERS);\n float accumulation = 0.0;\n float depthOfField = 5.0 * sin(uTime * 0.1);\n for (int i = max(layerStart, 0); i < min(layerEnd, LAYERS); i++) {\n float layer = float(i);\n float depthFactor = smoothstep(DEPTH_NEAR, DEPTH_FAR, layer / totalLayers);\n float widthFactor = smoothstep(WIDTH_NEAR, WIDTH_FAR, layer / totalLayers);\n float speedFactor = smoothstep(SPEED_NEAR, SPEED_FAR, layer / totalLayers);\n vec2 offsetUv = uv * (1.0 + layer * depthFactor);\n float windEffect = widthFactor * mod(layer * 7.238917, 1.0) - widthFactor * 0.1 * sin(uTime * 2.0 + layer);\n offsetUv += vec2(offsetUv.y * windEffect, speedFactor * uTime / (1.0 + layer * depthFactor * 0.03));\n vec3 noiseInput = vec3(floor(offsetUv), 31.189 + layer);\n vec3 permuted = floor(noiseInput) * 0.00001 + fract(noiseInput);\n vec3 noise = fract((31415.9 + permuted) / fract(permutationMatrix * permuted));\n vec2 particleShape = abs(mod(offsetUv, 1.0) - 0.5 + 0.9 * noise.xy - 0.45);\n particleShape += 0.01 * abs(2.0 * fract(10.0 * offsetUv.yx) - 1.0);\n float distance = 0.6 * max(particleShape.x - particleShape.y, particleShape.x + particleShape.y) + max(particleShape.x, particleShape.y) - 0.01;\n float edgeThreshold = 0.05 + 0.05 * min(0.5 * abs(layer - 5.0 - depthOfField), 1.0);\n accumulation += smoothstep(edgeThreshold, -edgeThreshold, distance) * (noise.x / (1.0 + 0.02 * layer * depthFactor));\n }\n return accumulation;\n}\n\nvoid main() {\n vec4 baseTexture = texture2D(uImgBase, vUv);\n gl_FragColor = mix(gl_FragColor, baseTexture, baseTexture.a);\n\n float snowEffect = computeSnow(vUv, 5, 15);\n gl_FragColor += vec4(vec3(snowEffect), 1.0);\n\n float popupMoveOffset = 0.0;\n vec2 popupOffsetUv = vUv + (uMove.xy / uResolution.xy) * popupMoveOffset;\n vec4 popupTexture = texture2D(uImgPopup, popupOffsetUv);\n gl_FragColor = mix(gl_FragColor, popupTexture, popupTexture.a);\n\n snowEffect = computeSnow(vUv, 16, 20);\n gl_FragColor += vec4(vec3(snowEffect), 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n#define mod289(x) mod(x, 289.)\n\nvec3 permute(vec3 x) { return mod289(((x * 34.0) + 1.0) * x); }\n\nfloat snoise(vec2 coord) {\n const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439);\n vec2 intPart = floor(coord + dot(coord, C.yy));\n vec2 fracPart = coord - intPart + dot(intPart, C.xx);\n\n vec2 offset;\n offset = (fracPart.x > fracPart.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);\n vec4 combined = fracPart.xyxy + C.xxzz;\n combined.xy -= offset;\n\n intPart = mod289(intPart);\n vec3 perm = permute(permute(intPart.y + vec3(0.0, offset.y, 1.0))\n + intPart.x + vec3(0.0, offset.x, 1.0));\n\n vec3 gradient = max(0.5 - vec3(dot(fracPart, fracPart), dot(combined.xy, combined.xy), dot(combined.zw, combined.zw)), 0.0);\n gradient *= gradient;\n gradient *= gradient;\n\n vec3 noiseVec = 2.0 * fract(perm * C.www) - 1.0;\n vec3 absDiff = abs(noiseVec) - 0.5;\n vec3 offsetVec = floor(noiseVec + 0.5);\n vec3 gradientVec = noiseVec - offsetVec;\n\n gradient *= 1.79284291400159 - 0.85373472095314 * (gradientVec * gradientVec + absDiff * absDiff);\n\n vec3 finalGrad;\n finalGrad.x = gradientVec.x * fracPart.x + absDiff.x * fracPart.y;\n finalGrad.yz = gradientVec.yz * combined.xz + absDiff.yz * combined.yw;\n\n return 130.0 * dot(gradient, finalGrad);\n}\n\nfloat fbm(vec2 position) {\n float result = 0.0;\n float weight = 0.5;\n for (int i = 0; i < 5; i++) {\n result += weight * snoise(position);\n position *= 2.0;\n weight *= 0.5;\n }\n return result;\n}\n\n// snowfall\nconst int LAYERS = 66;\nconst float DEPTH_NEAR = 0.3;\nconst float WIDTH_NEAR = 0.4;\nconst float SPEED_NEAR = 0.6;\nconst float DEPTH_FAR = 0.1;\nconst float WIDTH_FAR = 0.3;\nconst float SPEED_FAR = 0.1;\n\nfloat computeSnow(in vec2 uv, int layerStart, int layerEnd) {\n const mat3 permutationMatrix = mat3(13.323122, 23.5112, 21.71123, 21.1212, 28.7312, 11.9312, 21.8112, 14.7212, 61.3934);\n vec2 moveNormalized = uMove.xy / uResolution.xy;\n moveNormalized.x = max(0.15, smoothstep(0.15, 0.8, moveNormalized.x));\n uv.x += moveNormalized.x * 0.2;\n float totalLayers = float(LAYERS);\n float accumulation = 0.0;\n float depthOfField = 5.0 * sin(uTime * 0.1);\n for (int i = max(layerStart, 0); i < min(layerEnd, LAYERS); i++) {\n float layer = float(i);\n float depthFactor = smoothstep(DEPTH_NEAR, DEPTH_FAR, layer / totalLayers);\n float widthFactor = smoothstep(WIDTH_NEAR, WIDTH_FAR, layer / totalLayers);\n float speedFactor = smoothstep(SPEED_NEAR, SPEED_FAR, layer / totalLayers);\n vec2 offsetUv = uv * (1.0 + layer * depthFactor);\n float windEffect = widthFactor * mod(layer * 7.238917, 1.0) - widthFactor * 0.1 * sin(uTime * 2.0 + layer);\n offsetUv += vec2(offsetUv.y * windEffect, speedFactor * uTime / (1.0 + layer * depthFactor * 0.03));\n vec3 noiseInput = vec3(floor(offsetUv), 31.189 + layer);\n vec3 permuted = floor(noiseInput) * 0.00001 + fract(noiseInput);\n vec3 noise = fract((31415.9 + permuted) / fract(permutationMatrix * permuted));\n vec2 particleShape = abs(mod(offsetUv, 1.0) - 0.5 + 0.9 * noise.xy - 0.45);\n particleShape += 0.01 * abs(2.0 * fract(10.0 * offsetUv.yx) - 1.0);\n float distance = 0.6 * max(particleShape.x - particleShape.y, particleShape.x + particleShape.y) + max(particleShape.x, particleShape.y) - 0.01;\n float edgeThreshold = 0.05 + 0.05 * min(0.5 * abs(layer - 5.0 - depthOfField), 1.0);\n accumulation += smoothstep(edgeThreshold, -edgeThreshold, distance) * (noise.x / (1.0 + 0.02 * layer * depthFactor));\n }\n return accumulation;\n}\n\nvoid main() {\n vec4 baseTexture = texture2D(uImgBase, vUv);\n gl_FragColor = mix(gl_FragColor, baseTexture, baseTexture.a);\n\n float snowEffect = computeSnow(vUv, 5, 15);\n gl_FragColor += vec4(vec3(snowEffect), 1.0);\n\n // 3D parallax offset for popup layer\n vec2 popupOffset = vec2(-uRotate.x * 0.08, -uRotate.y * 0.06);\n vec2 popupOffsetUv = vUv + popupOffset;\n vec4 popupTexture = texture2D(uImgPopup, popupOffsetUv);\n gl_FragColor = mix(gl_FragColor, popupTexture, popupTexture.a);\n\n snowEffect = computeSnow(vUv, 16, 20);\n gl_FragColor += vec4(vec3(snowEffect), 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n#include <lygia/sample/clamp2edge>\n#define KUWAHARA_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#include <lygia/filter/kuwahara>\n#include <lygia/draw/digits>\n#include <utils/defaultLighting>\n\nvoid main() {\n vec2 pixel = 1.0 / uResolution.xy;\n vec2 popUpUv = vUv + (uMove.xy / uResolution.xy) * 0.008;\n\n vec4 baseColor = kuwahara(uImgBase, vUv, pixel, 4.0);\n vec4 popupColor = kuwahara(uImgPopup, popUpUv, pixel, 4.0);\n\n float aSoft = smoothstep(0.4, 1.0, popupColor.a);\n vec4 pocaColor = mix(baseColor, popupColor, aSoft);\n\n gl_FragColor = defaultLighting(pocaColor, uResolution, uRotate, 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n#include <lygia/sample/clamp2edge>\n#define KUWAHARA_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#include <lygia/filter/kuwahara>\n#include <lygia/draw/digits>\n#include <utils/defaultLighting>\n\nvoid main() {\n vec2 pixel = 1.0 / uResolution.xy;\n\n // 3D parallax offset for popup layer\n vec2 popupOffset = vec2(-uRotate.x * 0.08, -uRotate.y * 0.06);\n vec2 popUpUv = vUv + popupOffset;\n\n vec4 baseColor = kuwahara(uImgBase, vUv, pixel, 4.0);\n vec4 popupColor = kuwahara(uImgPopup, popUpUv, pixel, 4.0);\n\n float aSoft = smoothstep(0.4, 1.0, popupColor.a);\n vec4 pocaColor = mix(baseColor, popupColor, aSoft);\n\n gl_FragColor = defaultLighting(pocaColor, uResolution, uRotate, 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n// #define GAUSSIANBLUR_2D\n#include <lygia/sample/clamp2edge>\n#define GAUSSIANBLUR_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#include <lygia/filter/gaussianBlur>\n#include <lygia/draw/digits>\n#include <utils/defaultLighting>\n\nvoid main() {\n vec2 pixel = 1.0 / uResolution.xy;\n vec2 popUpUv = vUv + (uMove.xy / uResolution.xy) * 0.008;\n\n vec4 baseColor = gaussianBlur(uImgBase, vUv, pixel, 12);\n vec4 popupColor = texture2D(uImgPopup, popUpUv);\n\n float aSoft = smoothstep(0.4, 1.0, popupColor.a);\n vec4 pocaColor = mix(baseColor, popupColor, aSoft);\n\n gl_FragColor = defaultLighting(pocaColor, uResolution, uRotate, 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n// #define GAUSSIANBLUR_2D\n#include <lygia/sample/clamp2edge>\n#define GAUSSIANBLUR_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#include <lygia/filter/gaussianBlur>\n#include <lygia/draw/digits>\n#include <utils/defaultLighting>\n\nvoid main() {\n vec2 pixel = 1.0 / uResolution.xy;\n\n // 3D parallax offset for popup layer\n vec2 popupOffset = vec2(-uRotate.x * 0.08, -uRotate.y * 0.06);\n vec2 popUpUv = vUv + popupOffset;\n\n vec4 baseColor = gaussianBlur(uImgBase, vUv, pixel, 12);\n vec4 popupColor = texture2D(uImgPopup, popUpUv);\n\n float aSoft = smoothstep(0.4, 1.0, popupColor.a);\n vec4 pocaColor = mix(baseColor, popupColor, aSoft);\n\n gl_FragColor = defaultLighting(pocaColor, uResolution, uRotate, 1.0);\n}\n`\n","export const round = (value: number, precision = 3): number =>\n parseFloat(value.toFixed(precision))\n\nexport const clamp = (value: number, min = 0, max = 100): number =>\n Math.min(Math.max(value, min), max)\n\nexport const adjust = (\n value: number,\n fromMin: number,\n fromMax: number,\n toMin: number,\n toMax: number,\n): number =>\n round(toMin + ((toMax - toMin) * (value - fromMin)) / (fromMax - fromMin))\n\nexport const distance = (x1: number, y1: number, x2: number, y2: number): number =>\n Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)\n","export interface SpringOpts {\n stiffness?: number\n damping?: number\n precision?: number\n}\n\nexport interface SpringUpdateOpts {\n hard?: boolean\n soft?: number | boolean\n}\n\nexport interface Spring<T> {\n set(value: T, opts?: SpringUpdateOpts): Promise<void>\n get(): T\n stiffness: number\n damping: number\n precision: number\n}\n\n// Global animation loop shared across all springs\nconst tasks: Set<() => boolean> = new Set()\nlet rafId: number | null = null\n\nfunction runLoop() {\n if (tasks.size === 0) {\n rafId = null\n return\n }\n for (const task of tasks) {\n if (!task()) {\n tasks.delete(task)\n }\n }\n rafId = requestAnimationFrame(runLoop)\n}\n\nfunction scheduleTask(task: () => boolean) {\n tasks.add(task)\n if (rafId === null) {\n rafId = requestAnimationFrame(runLoop)\n }\n}\n\nfunction tickSpring(\n ctx: { val: number; lastVal: number; target: number; invMass: number },\n stiffness: number,\n damping: number,\n precision: number,\n): boolean {\n const delta = ctx.target - ctx.val\n const velocity = ctx.val - ctx.lastVal\n const springForce = stiffness * delta\n const damperForce = damping * velocity\n const acceleration = (springForce - damperForce) * ctx.invMass\n const d = velocity + acceleration\n\n if (Math.abs(d) < precision && Math.abs(delta) < precision) {\n ctx.val = ctx.target\n ctx.lastVal = ctx.target\n return false // settled\n }\n\n ctx.lastVal = ctx.val\n ctx.val += d\n return true // still moving\n}\n\nexport function spring(\n initialValue: number,\n onChange: (value: number) => void,\n opts: SpringOpts = {},\n): Spring<number> {\n const stiffness = opts.stiffness ?? 0.15\n const damping = opts.damping ?? 0.8\n const precision = opts.precision ?? 0.01\n\n const ctx = {\n val: initialValue,\n lastVal: initialValue,\n target: initialValue,\n invMass: 1,\n }\n let currentResolve: (() => void) | null = null\n\n const s: Spring<number> = {\n stiffness,\n damping,\n precision,\n get() {\n return ctx.val\n },\n set(value: number, updateOpts?: SpringUpdateOpts) {\n ctx.target = value\n\n if (updateOpts?.hard) {\n ctx.val = value\n ctx.lastVal = value\n onChange(value)\n return Promise.resolve()\n }\n\n if (updateOpts?.soft) {\n const rate = typeof updateOpts.soft === 'number' ? updateOpts.soft : 0.5\n ctx.invMass = Math.min(ctx.invMass, rate)\n }\n\n return new Promise<void>((resolve) => {\n currentResolve = resolve\n scheduleTask(() => {\n const invMassTarget = 1\n ctx.invMass = Math.min(ctx.invMass + 0.02, invMassTarget)\n\n const moving = tickSpring(ctx, s.stiffness, s.damping, s.precision)\n onChange(ctx.val)\n\n if (!moving) {\n currentResolve?.()\n currentResolve = null\n }\n return moving\n })\n })\n },\n }\n\n return s\n}\n\n// Convenience: spring for {x, y} objects\n// Uses batched onChange — ticks all components per frame, calls onChange once\nexport function springVec2(\n initial: { x: number; y: number },\n onChange: (value: { x: number; y: number }) => void,\n opts: SpringOpts = {},\n): Spring<{ x: number; y: number }> {\n const state = { x: initial.x, y: initial.y }\n let dirty = false\n\n const flush = () => {\n if (dirty) {\n dirty = false\n onChange({ ...state })\n }\n }\n\n const sx = spring(initial.x, (v) => {\n state.x = v\n dirty = true\n // Use microtask to batch x+y updates within the same frame\n queueMicrotask(flush)\n }, opts)\n\n const sy = spring(initial.y, (v) => {\n state.y = v\n dirty = true\n queueMicrotask(flush)\n }, opts)\n\n return {\n stiffness: opts.stiffness ?? 0.15,\n damping: opts.damping ?? 0.8,\n precision: opts.precision ?? 0.01,\n get() {\n return { x: sx.get(), y: sy.get() }\n },\n async set(value, updateOpts) {\n await Promise.all([\n sx.set(value.x, updateOpts),\n sy.set(value.y, updateOpts),\n ])\n },\n }\n}\n\n// Convenience: spring for {x, y, o} (glare)\nexport function springVec3(\n initial: { x: number; y: number; o: number },\n onChange: (value: { x: number; y: number; o: number }) => void,\n opts: SpringOpts = {},\n): Spring<{ x: number; y: number; o: number }> {\n const state = { x: initial.x, y: initial.y, o: initial.o }\n let dirty = false\n\n const flush = () => {\n if (dirty) {\n dirty = false\n onChange({ ...state })\n }\n }\n\n const sx = spring(initial.x, (v) => {\n state.x = v\n dirty = true\n queueMicrotask(flush)\n }, opts)\n\n const sy = spring(initial.y, (v) => {\n state.y = v\n dirty = true\n queueMicrotask(flush)\n }, opts)\n\n const so = spring(initial.o, (v) => {\n state.o = v\n dirty = true\n queueMicrotask(flush)\n }, opts)\n\n return {\n stiffness: opts.stiffness ?? 0.15,\n damping: opts.damping ?? 0.8,\n precision: opts.precision ?? 0.01,\n get() {\n return { x: sx.get(), y: sy.get(), o: so.get() }\n },\n async set(value, updateOpts) {\n await Promise.all([\n sx.set(value.x, updateOpts),\n sy.set(value.y, updateOpts),\n so.set(value.o, updateOpts),\n ])\n },\n }\n}\n","import { round, clamp, adjust, distance } from '../utils/math'\nimport { springVec2, springVec3, type Spring } from '../animation/spring'\n\nexport interface InteractionCallbacks {\n onRotate: (rotate: { x: number; y: number }) => void\n onGlare: (glare: { x: number; y: number; o: number }) => void\n onMousePos: (pos: { x: number; y: number }) => void\n onMoveDelta: (delta: { x: number; y: number }) => void\n onDistFromCenter: (dist: number) => void\n onFlip: (flipped: boolean) => void\n}\n\ninterface Rect {\n left: number\n top: number\n width: number\n height: number\n}\n\nconst SPRING_INTERACT = { stiffness: 0.095, damping: 0.5 }\nconst SPRING_FLIP = { stiffness: 0.03, damping: 0.25 }\nconst THROTTLE_MS = 1000 / 60\nconst DBLCLICK_MS = 200\n\nexport class InteractionHandler {\n private flipped = false\n private interacting = false\n private boundingRect: Rect = { left: 0, top: 0, width: 0, height: 0 }\n private interactionOrigin = { x: 0, y: 0 }\n\n private springRotate: Spring<{ x: number; y: number }>\n private springGlare: Spring<{ x: number; y: number; o: number }>\n\n private lastThrottleTime = 0\n private clickCount = 0\n private dblClickTimer: ReturnType<typeof setTimeout> | null = null\n private activePointerId: number | null = null\n\n private boundPointerDown: (e: PointerEvent) => void\n private boundPointerMove: (e: PointerEvent) => void\n private boundPointerUp: (e: PointerEvent) => void\n private boundClick: (e: MouseEvent) => void\n private boundTouchHandler: (e: TouchEvent) => void\n\n constructor(\n private container: HTMLElement,\n private callbacks: InteractionCallbacks,\n private flippable: boolean,\n initialFlipped: boolean,\n ) {\n this.flipped = initialFlipped\n\n // Spring rotate onChange: apply flip-aware sign to CSS rotation\n // Angular: { x: flipped ? 180 - v.x : -v.x, y: flipped ? -v.y : v.y }\n this.springRotate = springVec2({ x: 0, y: 0 }, (v) => {\n callbacks.onRotate(v)\n callbacks.onDistFromCenter(clamp(distance(v.x, v.y, 0, 0) / 50, 0, 1))\n }, SPRING_INTERACT)\n\n this.springGlare = springVec3({ x: 50, y: 50, o: 0 }, (v) => {\n callbacks.onGlare(v)\n }, SPRING_INTERACT)\n\n this.boundPointerDown = this.onPointerDown.bind(this)\n this.boundPointerMove = this.onPointerMove.bind(this)\n this.boundPointerUp = this.onPointerUp.bind(this)\n this.boundClick = this.onClick.bind(this)\n this.boundTouchHandler = (e: TouchEvent) => { e.stopPropagation() }\n\n this.container.addEventListener('pointerdown', this.boundPointerDown)\n this.container.addEventListener('pointermove', this.boundPointerMove)\n this.container.addEventListener('pointerup', this.boundPointerUp)\n this.container.addEventListener('pointercancel', this.boundPointerUp)\n this.container.addEventListener('click', this.boundClick)\n this.container.addEventListener('touchstart', this.boundTouchHandler, { passive: true })\n this.container.addEventListener('touchmove', this.boundTouchHandler, { passive: true })\n }\n\n updateRect(rect: Rect): void {\n this.boundingRect = rect\n }\n\n private onPointerDown(e: PointerEvent): void {\n e.preventDefault()\n e.stopPropagation()\n this.interacting = true\n this.activePointerId = e.pointerId\n this.container.setPointerCapture(e.pointerId)\n\n const rect = this.container.getBoundingClientRect()\n this.boundingRect = { left: rect.left, top: rect.top, width: rect.width, height: rect.height }\n this.interactionOrigin = { x: e.clientX, y: e.clientY }\n this.doInteract(e.clientX, e.clientY)\n }\n\n private onPointerMove(e: PointerEvent): void {\n if (!this.interacting) return\n const now = performance.now()\n if (now - this.lastThrottleTime < THROTTLE_MS) return\n this.lastThrottleTime = now\n this.doInteract(e.clientX, e.clientY)\n }\n\n private onPointerUp(_e: PointerEvent): void {\n if (!this.interacting) return\n this.interacting = false\n if (this.activePointerId !== null) {\n try { this.container.releasePointerCapture(this.activePointerId) } catch {}\n this.activePointerId = null\n }\n this.endInteract()\n }\n\n private onClick(_e: MouseEvent): void {\n if (!this.flippable) return\n this.clickCount++\n if (this.dblClickTimer) clearTimeout(this.dblClickTimer)\n this.dblClickTimer = setTimeout(() => {\n if (this.clickCount >= 2) {\n this.flip()\n }\n this.clickCount = 0\n }, DBLCLICK_MS)\n }\n\n /**\n * Core interaction math — faithfully ported from Angular move.service.ts doInteract()\n */\n private doInteract(clientX: number, clientY: number): void {\n const rect = this.boundingRect\n if (rect.width === 0 || rect.height === 0) return\n\n const deltaX = clientX - this.interactionOrigin.x\n const deltaY = clientY - this.interactionOrigin.y\n\n // touchPosFromLT: absolute position within card (for glare)\n const touchPosFromLT = {\n x: clientX - rect.left,\n y: clientY - rect.top,\n }\n const touchPercentFromLT = {\n x: clamp(round((100 / rect.width) * touchPosFromLT.x)),\n y: clamp(round((100 / rect.height) * touchPosFromLT.y)),\n }\n\n // touchPosFromCenter: delta-based center offset (for rotation)\n const touchPosFromCenter = {\n x: rect.width / 2 + deltaX,\n y: rect.height / 2 + deltaY,\n }\n const touchPercentFromCenter = {\n x: clamp(round((100 / rect.width) * touchPosFromCenter.x)),\n y: clamp(round((100 / rect.height) * touchPosFromCenter.y)),\n }\n const touchPercentBasedCenter = {\n x: touchPercentFromCenter.x - 50,\n y: touchPercentFromCenter.y - 50,\n }\n\n // moveDelta: raw pixel delta (no DPR)\n this.callbacks.onMoveDelta({ x: deltaX, y: deltaY })\n\n // mousePos: absolute position in card, DPR-scaled, Y-flipped for WebGL\n const dpr = window.devicePixelRatio || 1\n this.callbacks.onMousePos({\n x: (clientX - rect.left) * dpr,\n y: (rect.height - (clientY - rect.top)) * dpr,\n })\n\n // Rotation: basedCenter / divisor\n const rotate = {\n x: round(touchPercentBasedCenter.x / 3.5),\n y: round(touchPercentBasedCenter.y / 2),\n }\n\n // Glare: absolute percentage from left-top\n const glare = {\n x: round(touchPercentFromLT.x),\n y: round(touchPercentFromLT.y),\n o: 1 as number,\n }\n\n this.updateSprings(glare, rotate)\n }\n\n /**\n * Apply spring targets with flip-aware rotation sign.\n * Angular: { x: flipped ? 180 - rotate.x : -rotate.x, y: flipped ? -rotate.y : rotate.y }\n */\n private updateSprings(\n glare: { x: number; y: number; o: number },\n rotate: { x: number; y: number },\n ): void {\n this.springGlare.stiffness = SPRING_INTERACT.stiffness\n this.springGlare.damping = SPRING_INTERACT.damping\n this.springGlare.set(glare)\n\n this.springRotate.stiffness = SPRING_INTERACT.stiffness\n this.springRotate.damping = SPRING_INTERACT.damping\n this.springRotate.set({\n x: this.flipped ? 180 - rotate.x : -rotate.x,\n y: this.flipped ? -rotate.y : rotate.y,\n })\n }\n\n private endInteract(): void {\n this.springRotate.set({ x: this.flipped ? 180 : 0, y: 0 })\n this.springGlare.set({ x: 50, y: 50, o: 0 })\n this.callbacks.onMoveDelta({ x: 0, y: 0 })\n\n const rect = this.boundingRect\n const dpr = window.devicePixelRatio || 1\n this.callbacks.onMousePos({\n x: (rect.width / 2) * dpr,\n y: (rect.height / 2) * dpr,\n })\n }\n\n flip(flipped?: boolean): boolean {\n this.flipped = flipped ?? !this.flipped\n this.springRotate.stiffness = SPRING_FLIP.stiffness\n this.springRotate.damping = SPRING_FLIP.damping\n this.springRotate.set({ x: this.flipped ? 180 : 0, y: 0 }).then(() => {\n // Restore interaction spring params after flip animation settles\n this.springRotate.stiffness = SPRING_INTERACT.stiffness\n this.springRotate.damping = SPRING_INTERACT.damping\n })\n this.callbacks.onFlip(this.flipped)\n return this.flipped\n }\n\n /**\n * Wiggle support: start a synthetic interaction.\n * Matches Angular: startInteraction(0, 0, false)\n * Sets origin at (0,0) so wiggle coordinates become deltas directly.\n */\n startSyntheticInteraction(): void {\n const rect = this.container.getBoundingClientRect()\n this.boundingRect = { left: rect.left, top: rect.top, width: rect.width, height: rect.height }\n this.interactionOrigin = { x: 0, y: 0 }\n }\n\n /**\n * Feed raw clientX/Y directly to doInteract.\n * Used by wiggle where coordinates come from DefaultWiggler(0,0,100).\n */\n simulateInteractRaw(clientX: number, clientY: number): void {\n this.doInteract(clientX, clientY)\n }\n\n simulateEndInteract(): void {\n this.endInteract()\n }\n\n isFlipped(): boolean {\n return this.flipped\n }\n\n destroy(): void {\n if (this.activePointerId !== null) {\n try { this.container.releasePointerCapture(this.activePointerId) } catch {}\n }\n this.container.removeEventListener('pointerdown', this.boundPointerDown)\n this.container.removeEventListener('pointermove', this.boundPointerMove)\n this.container.removeEventListener('pointerup', this.boundPointerUp)\n this.container.removeEventListener('pointercancel', this.boundPointerUp)\n this.container.removeEventListener('click', this.boundClick)\n this.container.removeEventListener('touchstart', this.boundTouchHandler)\n this.container.removeEventListener('touchmove', this.boundTouchHandler)\n if (this.dblClickTimer) clearTimeout(this.dblClickTimer)\n }\n}\n","export interface WiggleController {\n stop(): void\n}\n\ntype EasingFn = (t: number) => number\n\nconst easeOut: EasingFn = (t) => 1 - (1 - t) ** 3\nconst easeInOut: EasingFn = (t) =>\n t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2\nconst easeIn: EasingFn = (t) => t * t * t\n\ninterface TweenOpts {\n from: number\n to: number\n duration: number\n easing: EasingFn\n onUpdate: (value: number) => void\n}\n\nfunction tween(opts: TweenOpts): Promise<void> & { cancel: () => void } {\n let cancelled = false\n let rafId: number | null = null\n\n const promise = new Promise<void>((resolve) => {\n const start = performance.now()\n const range = opts.to - opts.from\n\n function tick(now: number) {\n if (cancelled) { resolve(); return }\n const elapsed = now - start\n const t = Math.min(elapsed / opts.duration, 1)\n const value = opts.from + range * opts.easing(t)\n opts.onUpdate(value)\n\n if (t < 1) {\n rafId = requestAnimationFrame(tick)\n } else {\n resolve()\n }\n }\n rafId = requestAnimationFrame(tick)\n })\n\n const controller = Object.assign(promise, {\n cancel() {\n cancelled = true\n if (rafId !== null) cancelAnimationFrame(rafId)\n },\n })\n\n return controller\n}\n\nexport function wiggle(\n cx: number,\n cy: number,\n radius: number,\n onUpdate: (pos: { x: number; y: number }, done: boolean) => void,\n): WiggleController {\n let stopped = false\n const cancellers: (() => void)[] = []\n\n async function run() {\n let currentRadius = 0\n let theta = 0\n\n // Phase 1: Expand (0.5s)\n const expand = tween({\n from: 0, to: radius,\n duration: 500, easing: easeOut,\n onUpdate: (r) => {\n if (stopped) return\n currentRadius = r\n onUpdate({ x: cx + r, y: cy }, false)\n },\n })\n cancellers.push(expand.cancel)\n await expand\n if (stopped) return\n\n // Phase 2: Rotate (0.5s, 0 → π)\n const rotate = tween({\n from: 0, to: Math.PI,\n duration: 500, easing: easeInOut,\n onUpdate: (t) => {\n if (stopped) return\n theta = t\n onUpdate({\n x: cx + currentRadius * Math.cos(theta),\n y: cy + currentRadius * Math.sin(theta),\n }, false)\n },\n })\n cancellers.push(rotate.cancel)\n await rotate\n if (stopped) return\n\n // Phase 3: Shrink (0.3s)\n const shrink = tween({\n from: currentRadius, to: 0,\n duration: 300, easing: easeIn,\n onUpdate: (r) => {\n if (stopped) return\n currentRadius = r\n onUpdate({ x: cx + r * Math.cos(theta), y: cy }, false)\n },\n })\n cancellers.push(shrink.cancel)\n await shrink\n\n if (!stopped) {\n onUpdate({ x: cx, y: cy }, true)\n }\n }\n\n run()\n\n return {\n stop() {\n stopped = true\n cancellers.forEach((c) => c())\n },\n }\n}\n","import { EventEmitter } from './event-emitter'\nimport { Renderer, type RendererOptions } from './renderer'\nimport { InteractionHandler } from './interaction'\nimport { wiggle, type WiggleController } from './animation/wiggle'\nexport interface PocaCardOptions {\n type: string\n baseImage: string\n popupImage?: string\n maskImage?: string\n backImage?: string\n flippable?: boolean\n initialFlipped?: boolean\n customShader?: string\n}\n\nexport class PocaCard extends EventEmitter {\n private renderer: Renderer\n private interaction: InteractionHandler\n private wiggleController: WiggleController | null = null\n\n constructor(container: HTMLElement, options: PocaCardOptions) {\n super()\n\n this.renderer = new Renderer(\n container,\n {\n type: options.type,\n baseImage: options.baseImage,\n popupImage: options.popupImage,\n maskImage: options.maskImage,\n backImage: options.backImage,\n customShader: options.customShader,\n },\n (error) => this.emit('error', error),\n () => this.emit('ready'),\n )\n\n // Bind pointer events on the rotator element (inside the perspective container)\n this.interaction = new InteractionHandler(\n this.renderer.getRotatorEl(),\n {\n onRotate: (rotate) => this.renderer.updateUniforms({ rotate }),\n onGlare: () => {},\n onMousePos: (pos) => this.renderer.updateUniforms({ mouse: pos }),\n onMoveDelta: (delta) => this.renderer.updateUniforms({ move: delta }),\n onDistFromCenter: (_dist) => {\n // Could be used for opacity or other effects in the future\n },\n onFlip: (flipped) => this.emit('flip', flipped),\n },\n options.flippable ?? false,\n options.initialFlipped ?? false,\n )\n }\n\n getFrontContentEl(): HTMLDivElement {\n return this.renderer.getFrontContentEl()\n }\n\n getBackContentEl(): HTMLDivElement {\n return this.renderer.getBackContentEl()\n }\n\n flip(): void {\n this.interaction.flip()\n }\n\n wiggle(): void {\n this.wiggleController?.stop()\n\n // Match Angular: startInteraction(0,0,false) then feed raw pixel coords\n // DefaultWiggler(0, 0, 100) — center at origin, radius 100px\n this.interaction.startSyntheticInteraction()\n\n this.wiggleController = wiggle(0, 0, 100, (pos, done) => {\n if (done) {\n this.interaction.simulateEndInteract()\n this.wiggleController = null\n } else {\n // Feed wiggle position directly as clientX/Y (origin is 0,0)\n this.interaction.simulateInteractRaw(pos.x, pos.y)\n }\n })\n }\n\n reset(): void {\n this.wiggleController?.stop()\n this.wiggleController = null\n this.interaction.simulateEndInteract()\n }\n\n updateOptions(options: Partial<PocaCardOptions>): void {\n if (options.customShader) {\n this.renderer.updateShader(options.customShader)\n }\n if (options.baseImage || options.popupImage || options.maskImage) {\n this.renderer.updateTextures(options)\n }\n }\n\n destroy(): void {\n this.wiggleController?.stop()\n this.interaction.destroy()\n this.renderer.destroy()\n this.removeAllListeners()\n }\n}\n"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAf,IAAO,qBAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAf,IAAO,wBAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAf,IAAO,oBAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAf,IAAO,uBAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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","names":["THREE","D_default","D_default","rafId"]}
1
+ {"version":3,"sources":["../src/event-emitter.ts","../src/renderer/index.ts","../src/renderer/shader-bootstrap.ts","../src/shaders/lygia/math/permute.glsl","../src/shaders/lygia/math/mod289.glsl","../src/shaders/lygia/math/taylorInvSqrt.glsl","../src/shaders/lygia/math/grad4.glsl","../src/shaders/lygia/math/rotate4d.glsl","../src/shaders/lygia/math/cubic.glsl","../src/shaders/lygia/math/quintic.glsl","../src/shaders/lygia/math/sum.glsl","../src/shaders/lygia/math/saturate.glsl","../src/shaders/lygia/math/gaussian.glsl","../src/shaders/lygia/space/ratio.glsl","../src/shaders/lygia/generative/random.glsl","../src/shaders/lygia/generative/srandom.glsl","../src/shaders/lygia/generative/gnoise.glsl","../src/shaders/lygia/generative/snoise.glsl","../src/shaders/lygia/generative/fbm.glsl","../src/shaders/lygia/morphological/dilation.glsl","../src/shaders/lygia/sampler.glsl","../src/shaders/lygia/sample/clamp2edge.glsl","../src/shaders/lygia/draw/digits.glsl","../src/shaders/lygia/filter/gaussianBlur.glsl","../src/shaders/lygia/filter/gaussianBlur/2D.glsl","../src/shaders/lygia/filter/gaussianBlur/1D.glsl","../src/shaders/lygia/filter/gaussianBlur/1D_fast13.glsl","../src/shaders/lygia/filter/gaussianBlur/1D_fast9.glsl","../src/shaders/lygia/filter/gaussianBlur/1D_fast5.glsl","../src/shaders/lygia/filter/kuwahara.glsl","../src/shaders/utils/glsl.ts","../src/shaders/utils/default-lighting.glsl.ts","../src/shaders/common.vert.ts","../src/shaders/glare.frag.ts","../src/shaders/glare-3d.frag.ts","../src/shaders/snowfall.frag.ts","../src/shaders/snowfall-3d.frag.ts","../src/shaders/brush.frag.ts","../src/shaders/brush-3d.frag.ts","../src/shaders/blur.frag.ts","../src/shaders/blur-3d.frag.ts","../src/shaders/holo.frag.ts","../src/shaders/holo-3d.frag.ts","../src/animation/spring.ts","../src/utils/math.ts","../src/interaction/index.ts","../src/animation/tween.ts","../src/animation/wiggle.ts","../src/poca-card.ts"],"sourcesContent":["type Handler = (...args: any[]) => void\n\nexport class EventEmitter {\n private listeners = new Map<string, Set<Handler>>()\n\n on(event: string, handler: Handler): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set())\n }\n this.listeners.get(event)!.add(handler)\n }\n\n off(event: string, handler: Handler): void {\n this.listeners.get(event)?.delete(handler)\n }\n\n protected emit(event: string, ...args: any[]): void {\n this.listeners.get(event)?.forEach((handler) => {\n try {\n handler(...args)\n } catch (e) {\n console.error(`[pocato] Error in ${event} handler:`, e)\n }\n })\n }\n\n protected removeAllListeners(): void {\n this.listeners.clear()\n }\n}\n","import * as THREE from 'three'\nimport { bootstrapShaders, resolveIncludes } from './shader-bootstrap'\nimport vertexShader from '../shaders/common.vert'\nimport fragShaderGlare from '../shaders/glare.frag'\nimport fragShaderGlare3d from '../shaders/glare-3d.frag'\nimport fragShaderSnowfall from '../shaders/snowfall.frag'\nimport fragShaderSnowfall3d from '../shaders/snowfall-3d.frag'\nimport fragShaderBrush from '../shaders/brush.frag'\nimport fragShaderBrush3d from '../shaders/brush-3d.frag'\nimport fragShaderBlur from '../shaders/blur.frag'\nimport fragShaderBlur3d from '../shaders/blur-3d.frag'\nimport fragShaderHolo from '../shaders/holo.frag'\nimport fragShaderHolo3d from '../shaders/holo-3d.frag'\n\nconst FRAG_SHADERS: Record<string, string> = {\n 'glare': fragShaderGlare,\n 'glare-3d': fragShaderGlare3d,\n 'snowfall': fragShaderSnowfall,\n 'snowfall-3d': fragShaderSnowfall3d,\n 'brush': fragShaderBrush,\n 'brush-3d': fragShaderBrush3d,\n 'blur': fragShaderBlur,\n 'blur-3d': fragShaderBlur3d,\n 'holo': fragShaderHolo,\n 'holo-3d': fragShaderHolo3d,\n}\n\nexport interface RendererOptions {\n type: string\n baseImage: string\n popupImage?: string\n maskImage?: string\n backImage?: string\n customShader?: string\n}\n\nexport class Renderer {\n private scene: THREE.Scene | null = null\n private camera: THREE.Camera | null = null\n private webglRenderer: THREE.WebGLRenderer | null = null\n private material: THREE.ShaderMaterial | null = null\n private mesh: THREE.Mesh | null = null\n private clock = new THREE.Clock()\n private rafId: number | null = null\n private textures: THREE.Texture[] = []\n private canvas: HTMLCanvasElement\n private cardEl: HTMLDivElement\n private rotatorEl: HTMLDivElement\n private frontEl: HTMLDivElement\n private backEl: HTMLDivElement\n private frontContentEl: HTMLDivElement\n private backContentEl: HTMLDivElement\n private resizeObserver: ResizeObserver | null = null\n\n constructor(\n private container: HTMLElement,\n private options: RendererOptions,\n private onError?: (error: Error) => void,\n private onReady?: () => void,\n ) {\n this.injectStyles()\n\n // Build DOM:\n // .pocato-card > .pocato-rotator > .pocato-back\n // > .pocato-front > canvas\n this.cardEl = document.createElement('div')\n this.cardEl.className = 'pocato-card pocato-loading'\n\n this.rotatorEl = document.createElement('div')\n this.rotatorEl.className = 'pocato-rotator'\n\n // Back face\n this.backEl = document.createElement('div')\n this.backEl.className = 'pocato-back'\n if (options.backImage) {\n const backImg = document.createElement('img')\n backImg.src = options.backImage\n backImg.className = 'pocato-back-img'\n this.backEl.appendChild(backImg)\n }\n\n // Front face\n this.frontEl = document.createElement('div')\n this.frontEl.className = 'pocato-front'\n\n this.canvas = document.createElement('canvas')\n this.canvas.className = 'pocato-canvas'\n\n // Content containers for user-provided children (via React portal etc.)\n this.frontContentEl = document.createElement('div')\n this.frontContentEl.className = 'pocato-content pocato-front-content'\n\n this.backContentEl = document.createElement('div')\n this.backContentEl.className = 'pocato-content pocato-back-content'\n\n this.frontEl.appendChild(this.canvas)\n this.frontEl.appendChild(this.frontContentEl)\n this.backEl.appendChild(this.backContentEl)\n\n this.rotatorEl.appendChild(this.backEl)\n this.rotatorEl.appendChild(this.frontEl)\n this.cardEl.appendChild(this.rotatorEl)\n this.container.appendChild(this.cardEl)\n\n bootstrapShaders()\n this.init()\n }\n\n private injectStyles(): void {\n const id = 'pocato-styles'\n if (document.getElementById(id)) return\n\n const style = document.createElement('style')\n style.id = id\n style.textContent = `\n .pocato-card {\n width: 100%;\n height: 100%;\n perspective: 1000px;\n touch-action: none;\n user-select: none;\n transform: translate3d(0,0,0);\n opacity: 0;\n transition: opacity 0.5s ease;\n }\n .pocato-card.pocato-ready {\n opacity: 1;\n }\n .pocato-rotator {\n width: 100%;\n height: 100%;\n position: relative;\n transform-style: preserve-3d;\n transform-origin: center;\n transform: rotateY(var(--pocato-rotate-x, 0deg)) rotateX(var(--pocato-rotate-y, 0deg));\n border-radius: 2%;\n will-change: transform, box-shadow;\n transition: box-shadow 0.4s ease;\n box-shadow:\n 0px 10px 20px -5px rgba(0,0,0,0.4),\n 0 2px 15px -5px rgba(0,0,0,0.3);\n pointer-events: auto;\n }\n .pocato-front {\n position: absolute;\n top: 0; left: 0;\n width: 100%;\n height: 100%;\n backface-visibility: hidden;\n -webkit-backface-visibility: hidden;\n transform: translate3d(0,0,0);\n border-radius: 2%;\n overflow: hidden;\n }\n .pocato-back {\n position: absolute;\n top: 0; left: 0;\n width: 100%;\n height: 100%;\n backface-visibility: hidden;\n -webkit-backface-visibility: hidden;\n transform: rotateY(180deg) translateZ(0);\n border-radius: 2%;\n overflow: hidden;\n background-color: #1a1a2e;\n }\n .pocato-back-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n pointer-events: none;\n }\n .pocato-canvas {\n width: 100%;\n height: 100%;\n display: block;\n }\n .pocato-content {\n position: absolute;\n top: 0; left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 1;\n }\n .pocato-content > * {\n pointer-events: auto;\n }\n `\n document.head.appendChild(style)\n }\n\n private init(): void {\n const { width, height } = this.container.getBoundingClientRect()\n\n this.scene = new THREE.Scene()\n this.camera = new THREE.Camera()\n\n this.webglRenderer = new THREE.WebGLRenderer({\n canvas: this.canvas,\n alpha: true,\n })\n this.webglRenderer.setPixelRatio(window.devicePixelRatio)\n this.webglRenderer.setSize(width, height)\n\n // Use actual pixel dimensions (CSS size × DPR) for uResolution,\n // matching Angular which uses renderer.domElement.width/height\n const pixelWidth = this.canvas.width\n const pixelHeight = this.canvas.height\n const uniforms = this.createUniforms(pixelWidth, pixelHeight)\n\n const rawFragmentShader = this.options.customShader\n ?? FRAG_SHADERS[this.options.type]\n\n const fragmentShader = resolveIncludes(rawFragmentShader)\n\n this.material = new THREE.ShaderMaterial({\n vertexShader: resolveIncludes(vertexShader),\n fragmentShader,\n uniforms,\n transparent: true,\n })\n\n const geometry = new THREE.PlaneGeometry(2, 2)\n this.mesh = new THREE.Mesh(geometry, this.material)\n this.scene.add(this.mesh)\n\n this.loadTextures()\n this.setupResizeObserver()\n this.startRenderLoop()\n\n // Fade in after a short delay (matching Angular loading behavior)\n requestAnimationFrame(() => {\n this.cardEl.classList.remove('pocato-loading')\n this.cardEl.classList.add('pocato-ready')\n })\n }\n\n private createUniforms(width: number, height: number): Record<string, THREE.IUniform> {\n return {\n uTime: { value: 0 },\n uResolution: { value: new THREE.Vector2(width, height) },\n uMouse: { value: new THREE.Vector2(0, 0) },\n uMove: { value: new THREE.Vector2(0, 0) },\n uRotate: { value: new THREE.Vector2(0, 0) },\n uCardOpacity: { value: 1.0 },\n uImgBase: { value: null },\n uImgPopup: { value: null },\n uImgMask: { value: null },\n }\n }\n\n private loadTextures(): void {\n const loader = new THREE.TextureLoader()\n const load = (url: string | undefined, uniform: string) => {\n if (!url) return\n loader.load(\n url,\n (texture) => {\n this.textures.push(texture)\n if (this.material) {\n this.material.uniforms[uniform].value = texture\n }\n },\n undefined,\n () => {\n this.onError?.(new Error(`Failed to load texture: ${url}`))\n },\n )\n }\n\n load(this.options.baseImage, 'uImgBase')\n load(this.options.popupImage, 'uImgPopup')\n load(this.options.maskImage, 'uImgMask')\n\n this.onReady?.()\n }\n\n private setupResizeObserver(): void {\n this.resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (!entry) return\n const { width, height } = entry.contentRect\n if (width === 0 || height === 0) return\n\n this.webglRenderer?.setSize(width, height)\n // Use pixel dimensions after setSize (accounts for DPR)\n if (this.material) {\n this.material.uniforms.uResolution.value.set(this.canvas.width, this.canvas.height)\n }\n })\n this.resizeObserver.observe(this.container)\n }\n\n private startRenderLoop(): void {\n const animate = () => {\n this.rafId = requestAnimationFrame(animate)\n if (!this.material || !this.scene || !this.camera || !this.webglRenderer) return\n\n const delta = this.clock.getDelta()\n this.material.uniforms.uTime.value += delta\n this.webglRenderer.render(this.scene, this.camera)\n }\n this.rafId = requestAnimationFrame(animate)\n }\n\n updateUniforms(updates: {\n rotate?: { x: number; y: number }\n mouse?: { x: number; y: number }\n move?: { x: number; y: number }\n opacity?: number\n }): void {\n if (!this.material) return\n const u = this.material.uniforms\n if (updates.rotate) {\n // CSS transform for 3D card tilt (degrees)\n this.rotatorEl.style.setProperty('--pocato-rotate-x', `${updates.rotate.x}deg`)\n this.rotatorEl.style.setProperty('--pocato-rotate-y', `${updates.rotate.y}deg`)\n // Shader uniform (radians)\n u.uRotate.value.set(\n updates.rotate.x * (Math.PI / 180),\n updates.rotate.y * (Math.PI / 180),\n )\n }\n if (updates.mouse) u.uMouse.value.set(updates.mouse.x, updates.mouse.y)\n if (updates.move) u.uMove.value.set(updates.move.x, updates.move.y)\n if (updates.opacity !== undefined) u.uCardOpacity.value = updates.opacity\n }\n\n updateShader(fragmentShader: string): void {\n if (!this.material) return\n this.material.fragmentShader = resolveIncludes(fragmentShader)\n this.material.needsUpdate = true\n }\n\n updateTextures(options: Partial<RendererOptions>): void {\n const loader = new THREE.TextureLoader()\n const load = (url: string | undefined, uniform: string) => {\n if (!url) return\n loader.load(url, (texture) => {\n this.textures.push(texture)\n if (this.material) {\n this.material.uniforms[uniform].value = texture\n }\n })\n }\n if (options.baseImage) load(options.baseImage, 'uImgBase')\n if (options.popupImage) load(options.popupImage, 'uImgPopup')\n if (options.maskImage) load(options.maskImage, 'uImgMask')\n }\n\n getContainerRect(): DOMRect {\n return this.container.getBoundingClientRect()\n }\n\n getRotatorEl(): HTMLDivElement {\n return this.rotatorEl\n }\n\n getFrontContentEl(): HTMLDivElement {\n return this.frontContentEl\n }\n\n getBackContentEl(): HTMLDivElement {\n return this.backContentEl\n }\n\n destroy(): void {\n if (this.rafId !== null) cancelAnimationFrame(this.rafId)\n this.resizeObserver?.disconnect()\n this.textures.forEach((t) => t.dispose())\n this.mesh?.geometry.dispose()\n this.material?.dispose()\n this.webglRenderer?.dispose()\n if (this.cardEl.parentNode) {\n this.cardEl.parentNode.removeChild(this.cardEl)\n }\n this.scene = null\n this.camera = null\n this.webglRenderer = null\n this.material = null\n this.mesh = null\n }\n}\n","import * as THREE from 'three'\n\nimport permute from '../shaders/lygia/math/permute.glsl'\nimport mod289 from '../shaders/lygia/math/mod289.glsl'\nimport taylorInvSqrt from '../shaders/lygia/math/taylorInvSqrt.glsl'\nimport grad4 from '../shaders/lygia/math/grad4.glsl'\nimport rotate4d from '../shaders/lygia/math/rotate4d.glsl'\nimport cubic from '../shaders/lygia/math/cubic.glsl'\nimport quintic from '../shaders/lygia/math/quintic.glsl'\nimport sum from '../shaders/lygia/math/sum.glsl'\nimport saturate from '../shaders/lygia/math/saturate.glsl'\nimport gaussian from '../shaders/lygia/math/gaussian.glsl'\nimport ratio from '../shaders/lygia/space/ratio.glsl'\nimport random from '../shaders/lygia/generative/random.glsl'\nimport srandom from '../shaders/lygia/generative/srandom.glsl'\nimport gnoise from '../shaders/lygia/generative/gnoise.glsl'\nimport snoise from '../shaders/lygia/generative/snoise.glsl'\nimport fbm from '../shaders/lygia/generative/fbm.glsl'\nimport dilation from '../shaders/lygia/morphological/dilation.glsl'\nimport sampler from '../shaders/lygia/sampler.glsl'\nimport clamp2edge from '../shaders/lygia/sample/clamp2edge.glsl'\nimport digits from '../shaders/lygia/draw/digits.glsl'\nimport gaussianBlur from '../shaders/lygia/filter/gaussianBlur.glsl'\nimport gaussianBlur2D from '../shaders/lygia/filter/gaussianBlur/2D.glsl'\nimport gaussianBlur1D from '../shaders/lygia/filter/gaussianBlur/1D.glsl'\nimport gaussianBlur1DFast13 from '../shaders/lygia/filter/gaussianBlur/1D_fast13.glsl'\nimport gaussianBlur1DFast9 from '../shaders/lygia/filter/gaussianBlur/1D_fast9.glsl'\nimport gaussianBlur1DFast5 from '../shaders/lygia/filter/gaussianBlur/1D_fast5.glsl'\nimport kuwahara from '../shaders/lygia/filter/kuwahara.glsl'\n\nimport defaultLighting from '../shaders/utils/default-lighting.glsl'\n\nlet bootstrapped = false\n\n// Build a reverse lookup: short name (e.g. \"mod289\") → full chunk key (e.g. \"lygia/math/mod289\")\nconst shortNameMap = new Map<string, string>()\n\nfunction buildShortNameMap(): void {\n const chunks = THREE.ShaderChunk as any\n for (const key of Object.keys(chunks)) {\n // Extract short name from full path\n const parts = key.split('/')\n const shortName = parts[parts.length - 1]\n if (!shortNameMap.has(shortName)) {\n shortNameMap.set(shortName, key)\n }\n }\n}\n\n/**\n * Recursively resolve #include directives using THREE.ShaderChunk.\n * Handles:\n * - #include <lygia/math/mod289> (angle bracket, full path)\n * - #include <utils/defaultLighting> (angle bracket, registered key)\n * - #include \"mod289.glsl\" (quote, short name from LYGIA internals)\n * - #include \"../math/cubic.glsl\" (quote, relative path from LYGIA internals)\n */\nexport function resolveIncludes(source: string): string {\n if (shortNameMap.size === 0) buildShortNameMap()\n\n const pattern = /^[ \\t]*#include\\s+[<\"]([^>\"]+)[>\"]/gm\n const resolved = new Set<string>() // prevent infinite recursion via guard set\n\n function resolve(src: string, depth = 0): string {\n if (depth > 15) return src\n return src.replace(pattern, (_match, rawName: string) => {\n // Normalize: strip .glsl extension\n const name = rawName.replace(/\\.glsl$/, '')\n\n // Prevent re-including the same chunk\n if (resolved.has(name)) return ''\n\n const chunks = THREE.ShaderChunk as any\n\n // 1. Try exact key match\n let chunk = chunks[name]\n\n // 2. Try short name lookup (e.g. \"mod289\" → \"lygia/math/mod289\")\n if (chunk === undefined) {\n const shortName = name.split('/').pop()!\n const fullKey = shortNameMap.get(shortName)\n if (fullKey) chunk = chunks[fullKey]\n }\n\n // 3. Try normalizing relative paths (e.g. \"../math/cubic\" → \"lygia/math/cubic\")\n if (chunk === undefined && (name.startsWith('../') || name.startsWith('./'))) {\n // Try stripping relative prefix and prepending lygia/\n const cleaned = name.replace(/^\\.\\.\\//, '').replace(/^\\.\\//, '')\n chunk = chunks['lygia/' + cleaned]\n if (chunk === undefined) {\n // Try just the short name\n const shortName = cleaned.split('/').pop()!\n const fullKey = shortNameMap.get(shortName)\n if (fullKey) chunk = chunks[fullKey]\n }\n }\n\n if (chunk !== undefined) {\n resolved.add(name)\n return resolve(chunk, depth + 1)\n }\n\n // Chunk not found — leave a comment so shader doesn't break silently\n console.warn(`[pocato] Shader chunk not found: ${rawName}`)\n return `/* chunk not found: ${rawName} */`\n })\n }\n return resolve(source)\n}\n\nexport function bootstrapShaders(): void {\n if (bootstrapped) return\n bootstrapped = true\n\n const ThreeShaderChunk = THREE.ShaderChunk as any\n ThreeShaderChunk['lygia/math/permute'] = permute\n ThreeShaderChunk['lygia/math/mod289'] = mod289\n ThreeShaderChunk['lygia/math/taylorInvSqrt'] = taylorInvSqrt\n ThreeShaderChunk['lygia/math/grad4'] = grad4\n ThreeShaderChunk['lygia/math/rotate4d'] = rotate4d\n ThreeShaderChunk['lygia/math/cubic'] = cubic\n ThreeShaderChunk['lygia/math/quintic'] = quintic\n ThreeShaderChunk['lygia/math/sum'] = sum\n ThreeShaderChunk['lygia/math/saturate'] = saturate\n ThreeShaderChunk['lygia/math/gaussian'] = gaussian\n ThreeShaderChunk['lygia/space/ratio'] = ratio\n ThreeShaderChunk['lygia/generative/random'] = random\n ThreeShaderChunk['lygia/generative/srandom'] = srandom\n ThreeShaderChunk['lygia/generative/gnoise'] = gnoise\n ThreeShaderChunk['lygia/generative/snoise'] = snoise\n ThreeShaderChunk['lygia/generative/fbm'] = fbm\n ThreeShaderChunk['lygia/morphological/dilation'] = dilation\n ThreeShaderChunk['lygia/sampler'] = sampler\n ThreeShaderChunk['lygia/sample/clamp2edge'] = clamp2edge\n ThreeShaderChunk['lygia/draw/digits'] = digits\n ThreeShaderChunk['lygia/filter/gaussianBlur'] = gaussianBlur\n ThreeShaderChunk['lygia/filter/gaussianBlur/2D'] = gaussianBlur2D\n ThreeShaderChunk['lygia/filter/gaussianBlur/1D'] = gaussianBlur1D\n ThreeShaderChunk['lygia/filter/gaussianBlur/1D_fast13'] = gaussianBlur1DFast13\n ThreeShaderChunk['lygia/filter/gaussianBlur/1D_fast9'] = gaussianBlur1DFast9\n ThreeShaderChunk['lygia/filter/gaussianBlur/1D_fast5'] = gaussianBlur1DFast5\n ThreeShaderChunk['lygia/filter/kuwahara'] = kuwahara\n ThreeShaderChunk['utils/defaultLighting'] = defaultLighting\n}\n","#include \"mod289.glsl\"\n\n/*\ncontributors: [Stefan Gustavson, Ian McEwan]\ndescription: permute\nuse: <float|vec2|vec3|vec4> permute(<float|vec2|vec3|vec4> x)\nexamples:\n - https://raw.githubusercontent.com/patriciogonzalezvivo/lygia_examples/main/math_functions.frag\n*/\n\n#ifndef FNC_PERMUTE\n#define FNC_PERMUTE\n\nfloat permute(const in float v) { return mod289(((v * 34.0) + 1.0) * v); }\nvec2 permute(const in vec2 v) { return mod289(((v * 34.0) + 1.0) * v); }\nvec3 permute(const in vec3 v) { return mod289(((v * 34.0) + 1.0) * v); }\nvec4 permute(const in vec4 v) { return mod289(((v * 34.0) + 1.0) * v); }\n\n#endif\n","/*\ncontributors: [Stefan Gustavson, Ian McEwan]\ndescription: modulus of 289\nuse: <float|vec2|vec3|vec4> mod289(<float|vec2|vec3|vec4> x)\n*/\n\n#ifndef FNC_MOD289\n#define FNC_MOD289\n\nfloat mod289(const in float x) { return x - floor(x * (1. / 289.)) * 289.; }\nvec2 mod289(const in vec2 x) { return x - floor(x * (1. / 289.)) * 289.; }\nvec3 mod289(const in vec3 x) { return x - floor(x * (1. / 289.)) * 289.; }\nvec4 mod289(const in vec4 x) { return x - floor(x * (1. / 289.)) * 289.; }\n\n#endif\n","/*\ncontributors: [Stefan Gustavson, Ian McEwan]\ndescription: Fast, accurate inverse square root. \nuse: <float|vec2|vec3|vec4> taylorInvSqrt(<float|vec2|vec3|vec4> x)\n*/\n\n#ifndef FNC_TAYLORINVSQRT\n#define FNC_TAYLORINVSQRT\nfloat taylorInvSqrt(in float r) { return 1.79284291400159 - 0.85373472095314 * r; }\nvec2 taylorInvSqrt(in vec2 r) { return 1.79284291400159 - 0.85373472095314 * r; }\nvec3 taylorInvSqrt(in vec3 r) { return 1.79284291400159 - 0.85373472095314 * r; }\nvec4 taylorInvSqrt(in vec4 r) { return 1.79284291400159 - 0.85373472095314 * r; }\n#endif","/*\ncontributors: [Stefan Gustavson, Ian McEwan]\ndescription: grad4, used for snoise(vec4 v)\nuse: grad4(<float> j, <vec4> ip)\n*/\n\n#ifndef FNC_GRAD4\n#define FNC_GRAD4\nvec4 grad4(float j, vec4 ip) {\n const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);\n vec4 p,s;\n p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;\n p.w = 1.5 - dot(abs(p.xyz), ones.xyz);\n s = vec4(lessThan(p, vec4(0.0)));\n p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www;\n return p;\n}\n#endif\n","/*\ncontributors: Patricio Gonzalez Vivo\ndescription: returns a 4x4 rotation matrix\nuse: <mat4> rotate4d(<vec3> axis, <float> radians)\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef FNC_ROTATE4D\n#define FNC_ROTATE4D\nmat4 rotate4d(in vec3 a, const in float r) {\n a = normalize(a);\n float s = sin(r);\n float c = cos(r);\n float oc = 1.0 - c;\n vec4 col1 = vec4(oc * a.x * a.x + c, oc * a.x * a.y + a.z * s, oc * a.z * a.x - a.y * s, 0.0);\n vec4 col2 = vec4(oc * a.x * a.y - a.z * s, oc * a.y * a.y + c, oc * a.y * a.z + a.x * s, 0.0);\n vec4 col3 = vec4(oc * a.z * a.x + a.y * s, oc * a.y * a.z - a.x * s, oc * a.z * a.z + c, 0.0);\n vec4 col4 = vec4(0.0, 0.0, 0.0, 1.0);\n return mat4(col1, col2, col3, col4);\n}\n#endif\n","/*\ncontributors: Inigo Quiles\ndescription: cubic polynomial https://iquilezles.org/articles/smoothsteps/\nuse: <float|vec2|vec3|vec4> cubic(<float|vec2|vec3|vec4> value[, <float> in, <float> out]);\nexamples:\n - https://raw.githubusercontent.com/patriciogonzalezvivo/lygia_examples/main/math_functions.frag\n*/\n\n#ifndef FNC_CUBIC\n#define FNC_CUBIC \nfloat cubic(const in float v) { return v*v*(3.0-2.0*v); }\nvec2 cubic(const in vec2 v) { return v*v*(3.0-2.0*v); }\nvec3 cubic(const in vec3 v) { return v*v*(3.0-2.0*v); }\nvec4 cubic(const in vec4 v) { return v*v*(3.0-2.0*v); }\n\nfloat cubic(const in float v, in float slope0, in float slope1) {\n float a = slope0 + slope1 - 2.;\n float b = -2. * slope0 - slope1 + 3.;\n float c = slope0;\n float v2 = v * v;\n float v3 = v * v2;\n return a * v3 + b * v2 + c * v;\n}\n\nvec2 cubic(const in vec2 v, in float slope0, in float slope1) {\n float a = slope0 + slope1 - 2.;\n float b = -2. * slope0 - slope1 + 3.;\n float c = slope0;\n vec2 v2 = v * v;\n vec2 v3 = v * v2;\n return a * v3 + b * v2 + c * v;\n}\n\nvec3 cubic(const in vec3 v, in float slope0, in float slope1) {\n float a = slope0 + slope1 - 2.;\n float b = -2. * slope0 - slope1 + 3.;\n float c = slope0;\n vec3 v2 = v * v;\n vec3 v3 = v * v2;\n return a * v3 + b * v2 + c * v;\n}\n\nvec4 cubic(const in vec4 v, in float slope0, in float slope1) {\n float a = slope0 + slope1 - 2.;\n float b = -2. * slope0 - slope1 + 3.;\n float c = slope0;\n vec4 v2 = v * v;\n vec4 v3 = v * v2;\n return a * v3 + b * v2 + c * v;\n}\n#endif","/*\ncontributors: Inigo Quiles\ndescription: quintic polynomial https://iquilezles.org/articles/smoothsteps/\nuse: <float|vec2|vec3|vec4> quintic(<float|vec2|vec3|vec4> value);\nexamples:\n - https://raw.githubusercontent.com/patriciogonzalezvivo/lygia_examples/main/math_functions.frag\n*/\n\n#ifndef FNC_QUINTIC\n#define FNC_QUINTIC \n\nfloat quintic(const in float v) { return v*v*v*(v*(v*6.0-15.0)+10.0); }\nvec2 quintic(const in vec2 v) { return v*v*v*(v*(v*6.0-15.0)+10.0); }\nvec3 quintic(const in vec3 v) { return v*v*v*(v*(v*6.0-15.0)+10.0); }\nvec4 quintic(const in vec4 v) { return v*v*v*(v*(v*6.0-15.0)+10.0); }\n\n#endif","/*\ncontributors: Patricio Gonzalez Vivo\ndescription: Sum elements of a vector\nuse: <float> sum(<vec2|vec3|vec4> value)\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef FNC_SUM\n#define FNC_SUM\nfloat sum( float v ) { return v; }\nfloat sum( vec2 v ) { return v.x+v.y; }\nfloat sum( vec3 v ) { return v.x+v.y+v.z; }\nfloat sum( vec4 v ) { return v.x+v.y+v.z+v.w; }\n#endif\n","/*\ncontributors: Patricio Gonzalez Vivo\ndescription: clamp a value between 0 and 1\nuse: <float|vec2|vec3|vec4> saturation(<float|vec2|vec3|vec4> value)\nexamples:\n - https://raw.githubusercontent.com/patriciogonzalezvivo/lygia_examples/main/math_functions.frag\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#if !defined(FNC_SATURATE) && !defined(saturate)\n#define FNC_SATURATE\n#define saturate(V) clamp(V, 0.0, 1.0)\n#endif","/*\ncontributors: Patricio Gonzalez Vivo\ndescription: gaussian coefficient\nuse: <vec4|vec3|vec2|float> gaussian(<float> sigma, <vec4|vec3|vec2|float> d)\nexamples:\n - https://raw.githubusercontent.com/patriciogonzalezvivo/lygia_examples/main/math_gaussian.frag\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef FNC_GAUSSIAN\n#define FNC_GAUSSIAN\nfloat gaussian(float d, float s) { return exp(-(d*d) / (2.0 * s*s)); }\nfloat gaussian( vec2 d, float s) { return exp(-( d.x*d.x + d.y*d.y) / (2.0 * s*s)); }\nfloat gaussian( vec3 d, float s) { return exp(-( d.x*d.x + d.y*d.y + d.z*d.z ) / (2.0 * s*s)); }\nfloat gaussian( vec4 d, float s) { return exp(-( d.x*d.x + d.y*d.y + d.z*d.z + d.w*d.w ) / (2.0 * s*s)); }\n#endif","/*\ncontributors: Patricio Gonzalez Vivo\ndescription: \"Fix the aspect ratio of a space keeping things squared for you, \\nin\\\n \\ a similar way that aspect.glsl does, but while scaling the \\nspace to keep the\\\n \\ entire 0.0,0.0 ~ 1.0,1.0 range visible\\n\"\nuse: <vec2> ratio(<vec2> st, <vec2> st_size)\nexamples:\n - https://raw.githubusercontent.com/patriciogonzalezvivo/lygia_examples/main/draw_shapes.frag\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef FNC_RATIO\n#define FNC_RATIO\nvec2 ratio(in vec2 v, in vec2 s) {\n return mix( vec2((v.x*s.x/s.y)-(s.x*.5-s.y*.5)/s.y,v.y),\n vec2(v.x,v.y*(s.y/s.x)-(s.y*.5-s.x*.5)/s.x),\n step(s.x,s.y));\n}\n#endif\n","/*\ncontributors: [\"Patricio Gonzalez Vivo\", \"David Hoskins\", \"Inigo Quilez\"]\ndescription: Pass a value and get some random normalize value between 0 and 1\nuse: float random[2|3](<float|vec2|vec3> value)\noptions:\n - RANDOM_HIGHER_RANGE: for working with a range over 0 and 1\n - RANDOM_SINLESS: Use sin-less random, which tolerates bigger values before producing pattern. From https://www.shadertoy.com/view/4djSRW\n - RANDOM_SCALE: by default this scale if for number with a big range. For producing good random between 0 and 1 use bigger range\nexamples:\n - /shaders/generative_random.frag\nlicense:\n - MIT License (MIT) Copyright 2014, David Hoskins\n*/\n\n#ifndef RANDOM_SCALE\n#ifdef RANDOM_HIGHER_RANGE\n#define RANDOM_SCALE vec4(.1031, .1030, .0973, .1099)\n#else\n#define RANDOM_SCALE vec4(443.897, 441.423, .0973, .1099)\n#endif\n#endif\n\n#ifndef FNC_RANDOM\n#define FNC_RANDOM\nfloat random(in float x) {\n#ifdef RANDOM_SINLESS\n x = fract(x * RANDOM_SCALE.x);\n x *= x + 33.33;\n x *= x + x;\n return fract(x);\n#else\n return fract(sin(x) * 43758.5453);\n#endif\n}\n\nfloat random(in vec2 st) {\n#ifdef RANDOM_SINLESS\n vec3 p3 = fract(vec3(st.xyx) * RANDOM_SCALE.xyz);\n p3 += dot(p3, p3.yzx + 33.33);\n return fract((p3.x + p3.y) * p3.z);\n#else\n return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453);\n#endif\n}\n\nfloat random(in vec3 pos) {\n#ifdef RANDOM_SINLESS\n pos = fract(pos * RANDOM_SCALE.xyz);\n pos += dot(pos, pos.zyx + 31.32);\n return fract((pos.x + pos.y) * pos.z);\n#else\n return fract(sin(dot(pos.xyz, vec3(70.9898, 78.233, 32.4355))) * 43758.5453123);\n#endif\n}\n\nfloat random(in vec4 pos) {\n#ifdef RANDOM_SINLESS\n pos = fract(pos * RANDOM_SCALE);\n pos += dot(pos, pos.wzxy + 33.33);\n return fract((pos.x + pos.y) * (pos.z + pos.w));\n#else\n float dot_product = dot(pos, vec4(12.9898,78.233,45.164,94.673));\n return fract(sin(dot_product) * 43758.5453);\n#endif\n}\n\nvec2 random2(float p) {\n vec3 p3 = fract(vec3(p) * RANDOM_SCALE.xyz);\n p3 += dot(p3, p3.yzx + 19.19);\n return fract((p3.xx + p3.yz) * p3.zy);\n}\n\nvec2 random2(vec2 p) {\n vec3 p3 = fract(p.xyx * RANDOM_SCALE.xyz);\n p3 += dot(p3, p3.yzx + 19.19);\n return fract((p3.xx + p3.yz) * p3.zy);\n}\n\nvec2 random2(vec3 p3) {\n p3 = fract(p3 * RANDOM_SCALE.xyz);\n p3 += dot(p3, p3.yzx + 19.19);\n return fract((p3.xx + p3.yz) * p3.zy);\n}\n\nvec3 random3(float p) {\n vec3 p3 = fract(vec3(p) * RANDOM_SCALE.xyz);\n p3 += dot(p3, p3.yzx + 19.19);\n return fract((p3.xxy + p3.yzz) * p3.zyx); \n}\n\nvec3 random3(vec2 p) {\n vec3 p3 = fract(vec3(p.xyx) * RANDOM_SCALE.xyz);\n p3 += dot(p3, p3.yxz + 19.19);\n return fract((p3.xxy + p3.yzz) * p3.zyx);\n}\n\nvec3 random3(vec3 p) {\n p = fract(p * RANDOM_SCALE.xyz);\n p += dot(p, p.yxz + 19.19);\n return fract((p.xxy + p.yzz) * p.zyx);\n}\n\nvec4 random4(float p) {\n vec4 p4 = fract(p * RANDOM_SCALE);\n p4 += dot(p4, p4.wzxy + 19.19);\n return fract((p4.xxyz + p4.yzzw) * p4.zywx); \n}\n\nvec4 random4(vec2 p) {\n vec4 p4 = fract(p.xyxy * RANDOM_SCALE);\n p4 += dot(p4, p4.wzxy + 19.19);\n return fract((p4.xxyz + p4.yzzw) * p4.zywx);\n}\n\nvec4 random4(vec3 p) {\n vec4 p4 = fract(p.xyzx * RANDOM_SCALE);\n p4 += dot(p4, p4.wzxy + 19.19);\n return fract((p4.xxyz + p4.yzzw) * p4.zywx);\n}\n\nvec4 random4(vec4 p4) {\n p4 = fract(p4 * RANDOM_SCALE);\n p4 += dot(p4, p4.wzxy + 19.19);\n return fract((p4.xxyz + p4.yzzw) * p4.zywx);\n}\n#endif","/*\ncontributors: Patricio Gonzalez Vivo\ndescription: Signed Random\nuse: srandomX(<vec2|vec3> x)\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef FNC_SRANDOM\n#define FNC_SRANDOM\n\nfloat srandom(in float x) {\n return -1. + 2. * fract(sin(x) * 43758.5453);\n}\n\nfloat srandom(in vec2 st) {\n return -1. + 2. * fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453);\n}\n\nfloat srandom(in vec3 pos) {\n return -1. + 2. * fract(sin(dot(pos.xyz, vec3(70.9898, 78.233, 32.4355))) * 43758.5453123);\n}\n\nfloat srandom(in vec4 pos) {\n float dot_product = dot(pos, vec4(12.9898,78.233,45.164,94.673));\n return -1. + 2. * fract(sin(dot_product) * 43758.5453);\n}\n\nvec2 srandom2(in vec2 st) {\n const vec2 k = vec2(.3183099, .3678794);\n st = st * k + k.yx;\n return -1. + 2. * fract(16. * k * fract(st.x * st.y * (st.x + st.y)));\n}\n\nvec3 srandom3(in vec3 p) {\n p = vec3( dot(p, vec3(127.1, 311.7, 74.7)),\n dot(p, vec3(269.5, 183.3, 246.1)),\n dot(p, vec3(113.5, 271.9, 124.6)));\n return -1. + 2. * fract(sin(p) * 43758.5453123);\n}\n\nvec2 srandom2(in vec2 p, const in float tileLength) {\n p = mod(p, vec2(tileLength));\n return srandom2(p);\n}\n\nvec3 srandom3(in vec3 p, const in float tileLength) {\n p = mod(p, vec3(tileLength));\n return srandom3(p);\n}\n\n#endif","#include \"random.glsl\"\n#include \"srandom.glsl\"\n#include \"../math/cubic.glsl\"\n#include \"../math/quintic.glsl\"\n\n/*\ncontributors: Patricio Gonzalez Vivo\ndescription: Gradient Noise\nuse: gnoise(<float> x)\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef FNC_GNOISE\n#define FNC_GNOISE\n\nfloat gnoise(float x) {\n float i = floor(x); // integer\n float f = fract(x); // fraction\n return mix(random(i), random(i + 1.0), smoothstep(0.,1.,f)); \n}\n\nfloat gnoise(vec2 st) {\n vec2 i = floor(st);\n vec2 f = fract(st);\n float a = random(i);\n float b = random(i + vec2(1.0, 0.0));\n float c = random(i + vec2(0.0, 1.0));\n float d = random(i + vec2(1.0, 1.0));\n vec2 u = cubic(f);\n return mix( a, b, u.x) +\n (c - a)* u.y * (1.0 - u.x) +\n (d - b) * u.x * u.y;\n}\n\nfloat gnoise(vec3 p) {\n vec3 i = floor(p);\n vec3 f = fract(p);\n vec3 u = quintic(f);\n return -1.0 + 2.0 * mix( mix( mix( random(i + vec3(0.0,0.0,0.0)), \n random(i + vec3(1.0,0.0,0.0)), u.x),\n mix( random(i + vec3(0.0,1.0,0.0)), \n random(i + vec3(1.0,1.0,0.0)), u.x), u.y),\n mix( mix( random(i + vec3(0.0,0.0,1.0)), \n random(i + vec3(1.0,0.0,1.0)), u.x),\n mix( random(i + vec3(0.0,1.0,1.0)), \n random(i + vec3(1.0,1.0,1.0)), u.x), u.y), u.z );\n}\n\nfloat gnoise(vec3 p, float tileLength) {\n vec3 i = floor(p);\n vec3 f = fract(p);\n \n vec3 u = quintic(f);\n \n return mix( mix( mix( dot( srandom3(i + vec3(0.0,0.0,0.0), tileLength), f - vec3(0.0,0.0,0.0)), \n dot( srandom3(i + vec3(1.0,0.0,0.0), tileLength), f - vec3(1.0,0.0,0.0)), u.x),\n mix( dot( srandom3(i + vec3(0.0,1.0,0.0), tileLength), f - vec3(0.0,1.0,0.0)), \n dot( srandom3(i + vec3(1.0,1.0,0.0), tileLength), f - vec3(1.0,1.0,0.0)), u.x), u.y),\n mix( mix( dot( srandom3(i + vec3(0.0,0.0,1.0), tileLength), f - vec3(0.0,0.0,1.0)), \n dot( srandom3(i + vec3(1.0,0.0,1.0), tileLength), f - vec3(1.0,0.0,1.0)), u.x),\n mix( dot( srandom3(i + vec3(0.0,1.0,1.0), tileLength), f - vec3(0.0,1.0,1.0)), \n dot( srandom3(i + vec3(1.0,1.0,1.0), tileLength), f - vec3(1.0,1.0,1.0)), u.x), u.y), u.z );\n}\n\nvec3 gnoise3(vec3 x) {\n return vec3(gnoise(x+vec3(123.456, 0.567, 0.37)),\n gnoise(x+vec3(0.11, 47.43, 19.17)),\n gnoise(x) );\n}\n\n#endif","#include \"../math/mod289.glsl\"\n#include \"../math/permute.glsl\"\n#include \"../math/taylorInvSqrt.glsl\"\n#include \"../math/grad4.glsl\"\n\n/*\ncontributors: [Stefan Gustavson, Ian McEwan]\ndescription: Simplex Noise https://github.com/stegu/webgl-noise\nuse: snoise(<vec2|vec3|vec4> pos)\nlicense: |\n Copyright 2021-2023 by Stefan Gustavson and Ian McEwan.\n Published under the terms of the MIT license:\n https://opensource.org/license/mit/\nexamples:\n - /shaders/generative_snoise.frag\n*/\n\n#ifndef FNC_SNOISE\n#define FNC_SNOISE\nfloat snoise(in vec2 v) {\n const vec4 C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0\n 0.366025403784439, // 0.5*(sqrt(3.0)-1.0)\n -0.577350269189626, // -1.0 + 2.0 * C.x\n 0.024390243902439); // 1.0 / 41.0\n // First corner\n vec2 i = floor(v + dot(v, C.yy) );\n vec2 x0 = v - i + dot(i, C.xx);\n\n // Other corners\n vec2 i1;\n //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0\n //i1.y = 1.0 - i1.x;\n i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);\n // x0 = x0 - 0.0 + 0.0 * C.xx ;\n // x1 = x0 - i1 + 1.0 * C.xx ;\n // x2 = x0 - 1.0 + 2.0 * C.xx ;\n vec4 x12 = x0.xyxy + C.xxzz;\n x12.xy -= i1;\n\n // Permutations\n i = mod289(i); // Avoid truncation effects in permutation\n vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))\n + i.x + vec3(0.0, i1.x, 1.0 ));\n\n vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);\n m = m*m ;\n m = m*m ;\n\n // Gradients: 41 points uniformly over a line, mapped onto a diamond.\n // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)\n\n vec3 x = 2.0 * fract(p * C.www) - 1.0;\n vec3 h = abs(x) - 0.5;\n vec3 ox = floor(x + 0.5);\n vec3 a0 = x - ox;\n\n // Normalise gradients implicitly by scaling m\n // Approximation of: m *= inversesqrt( a0*a0 + h*h );\n m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );\n\n // Compute final noise value at P\n vec3 g;\n g.x = a0.x * x0.x + h.x * x0.y;\n g.yz = a0.yz * x12.xz + h.yz * x12.yw;\n return 130.0 * dot(m, g);\n}\n\n\nfloat snoise(in vec3 v) {\n const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;\n const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);\n\n // First corner\n vec3 i = floor(v + dot(v, C.yyy) );\n vec3 x0 = v - i + dot(i, C.xxx) ;\n\n // Other corners\n vec3 g = step(x0.yzx, x0.xyz);\n vec3 l = 1.0 - g;\n vec3 i1 = min( g.xyz, l.zxy );\n vec3 i2 = max( g.xyz, l.zxy );\n\n // x0 = x0 - 0.0 + 0.0 * C.xxx;\n // x1 = x0 - i1 + 1.0 * C.xxx;\n // x2 = x0 - i2 + 2.0 * C.xxx;\n // x3 = x0 - 1.0 + 3.0 * C.xxx;\n vec3 x1 = x0 - i1 + C.xxx;\n vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y\n vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y\n\n // Permutations\n i = mod289(i);\n vec4 p = permute( permute( permute(\n i.z + vec4(0.0, i1.z, i2.z, 1.0 ))\n + i.y + vec4(0.0, i1.y, i2.y, 1.0 ))\n + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));\n\n // Gradients: 7x7 points over a square, mapped onto an octahedron.\n // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)\n float n_ = 0.142857142857; // 1.0/7.0\n vec3 ns = n_ * D.wyz - D.xzx;\n\n vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)\n\n vec4 x_ = floor(j * ns.z);\n vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)\n\n vec4 x = x_ *ns.x + ns.yyyy;\n vec4 y = y_ *ns.x + ns.yyyy;\n vec4 h = 1.0 - abs(x) - abs(y);\n\n vec4 b0 = vec4( x.xy, y.xy );\n vec4 b1 = vec4( x.zw, y.zw );\n\n //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;\n //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;\n vec4 s0 = floor(b0)*2.0 + 1.0;\n vec4 s1 = floor(b1)*2.0 + 1.0;\n vec4 sh = -step(h, vec4(0.0));\n\n vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;\n vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;\n\n vec3 p0 = vec3(a0.xy,h.x);\n vec3 p1 = vec3(a0.zw,h.y);\n vec3 p2 = vec3(a1.xy,h.z);\n vec3 p3 = vec3(a1.zw,h.w);\n\n //Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n\n // Mix final noise value\n vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);\n m = m * m;\n return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),\n dot(p2,x2), dot(p3,x3) ) );\n}\n\nfloat snoise(in vec4 v) {\n const vec4 C = vec4( 0.138196601125011, // (5 - sqrt(5))/20 G4\n 0.276393202250021, // 2 * G4\n 0.414589803375032, // 3 * G4\n -0.447213595499958); // -1 + 4 * G4\n\n // First corner\n vec4 i = floor(v + dot(v, vec4(.309016994374947451)) ); // (sqrt(5) - 1)/4\n vec4 x0 = v - i + dot(i, C.xxxx);\n\n // Other corners\n\n // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)\n vec4 i0;\n vec3 isX = step( x0.yzw, x0.xxx );\n vec3 isYZ = step( x0.zww, x0.yyz );\n // i0.x = dot( isX, vec3( 1.0 ) );\n i0.x = isX.x + isX.y + isX.z;\n i0.yzw = 1.0 - isX;\n // i0.y += dot( isYZ.xy, vec2( 1.0 ) );\n i0.y += isYZ.x + isYZ.y;\n i0.zw += 1.0 - isYZ.xy;\n i0.z += isYZ.z;\n i0.w += 1.0 - isYZ.z;\n\n // i0 now contains the unique values 0,1,2,3 in each channel\n vec4 i3 = clamp( i0, 0.0, 1.0 );\n vec4 i2 = clamp( i0-1.0, 0.0, 1.0 );\n vec4 i1 = clamp( i0-2.0, 0.0, 1.0 );\n\n // x0 = x0 - 0.0 + 0.0 * C.xxxx\n // x1 = x0 - i1 + 1.0 * C.xxxx\n // x2 = x0 - i2 + 2.0 * C.xxxx\n // x3 = x0 - i3 + 3.0 * C.xxxx\n // x4 = x0 - 1.0 + 4.0 * C.xxxx\n vec4 x1 = x0 - i1 + C.xxxx;\n vec4 x2 = x0 - i2 + C.yyyy;\n vec4 x3 = x0 - i3 + C.zzzz;\n vec4 x4 = x0 + C.wwww;\n\n // Permutations\n i = mod289(i);\n float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x);\n vec4 j1 = permute( permute( permute( permute (\n i.w + vec4(i1.w, i2.w, i3.w, 1.0 ))\n + i.z + vec4(i1.z, i2.z, i3.z, 1.0 ))\n + i.y + vec4(i1.y, i2.y, i3.y, 1.0 ))\n + i.x + vec4(i1.x, i2.x, i3.x, 1.0 ));\n\n // Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope\n // 7*7*6 = 294, which is close to the ring size 17*17 = 289.\n vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ;\n\n vec4 p0 = grad4(j0, ip);\n vec4 p1 = grad4(j1.x, ip);\n vec4 p2 = grad4(j1.y, ip);\n vec4 p3 = grad4(j1.z, ip);\n vec4 p4 = grad4(j1.w, ip);\n\n // Normalise gradients\n vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));\n p0 *= norm.x;\n p1 *= norm.y;\n p2 *= norm.z;\n p3 *= norm.w;\n p4 *= taylorInvSqrt(dot(p4,p4));\n\n // Mix contributions from the five corners\n vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0);\n vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0);\n m0 = m0 * m0;\n m1 = m1 * m1;\n return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 )))\n + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ;\n}\n\nvec2 snoise2( vec2 x ){\n float s = snoise(vec2( x ));\n float s1 = snoise(vec2( x.y - 19.1, x.x + 47.2 ));\n return vec2( s , s1 );\n}\n\nvec3 snoise3( vec3 x ){\n float s = snoise(vec3( x ));\n float s1 = snoise(vec3( x.y - 19.1 , x.z + 33.4 , x.x + 47.2 ));\n float s2 = snoise(vec3( x.z + 74.2 , x.x - 124.5 , x.y + 99.4 ));\n return vec3( s , s1 , s2 );\n}\n\nvec3 snoise3( vec4 x ){\n float s = snoise(vec4( x ));\n float s1 = snoise(vec4( x.y - 19.1 , x.z + 33.4 , x.x + 47.2, x.w ));\n float s2 = snoise(vec4( x.z + 74.2 , x.x - 124.5 , x.y + 99.4, x.w ));\n return vec3( s , s1 , s2 );\n}\n\n#endif\n","#include \"snoise.glsl\"\n#include \"gnoise.glsl\"\n\n\n/*\ncontributors: Patricio Gonzalez Vivo\ndescription: Fractal Brownian Motion\nuse: fbm(<vec2> pos)\noptions:\n FBM_OCTAVES: numbers of octaves. Default is 4.\n FBM_NOISE_FNC(UV): noise function to use Default 'snoise(UV)' (simplex noise)\n FBM_VALUE_INITIAL: initial value. Default is 0.\n FBM_SCALE_SCALAR: scalar. Default is 2.\n FBM_AMPLITUDE_INITIAL: initial amplitude value. Default is 0.5\n FBM_AMPLITUDE_SCALAR: amplitude scalar. Default is 0.5\nexamples:\n - /shaders/generative_fbm.frag\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef FBM_OCTAVES\n#define FBM_OCTAVES 4\n#endif\n\n#ifndef FBM_NOISE_FNC\n#define FBM_NOISE_FNC(UV) snoise(UV)\n#endif\n\n#ifndef FBM_NOISE2_FNC\n#define FBM_NOISE2_FNC(UV) FBM_NOISE_FNC(UV)\n#endif\n\n#ifndef FBM_NOISE3_FNC\n#define FBM_NOISE3_FNC(UV) FBM_NOISE_FNC(UV)\n#endif\n\n#ifndef FBM_NOISE_TILABLE_FNC\n#define FBM_NOISE_TILABLE_FNC(UV, TILE) gnoise(UV, TILE)\n#endif\n\n#ifndef FBM_NOISE3_TILABLE_FNC\n#define FBM_NOISE3_TILABLE_FNC(UV, TILE) FBM_NOISE_TILABLE_FNC(UV, TILE)\n#endif\n\n#ifndef FBM_NOISE_TYPE\n#define FBM_NOISE_TYPE float\n#endif\n\n#ifndef FBM_VALUE_INITIAL\n#define FBM_VALUE_INITIAL 0.0\n#endif\n\n#ifndef FBM_SCALE_SCALAR\n#define FBM_SCALE_SCALAR 2.0\n#endif\n\n#ifndef FBM_AMPLITUDE_INITIAL\n#define FBM_AMPLITUDE_INITIAL 0.5\n#endif\n\n#ifndef FBM_AMPLITUDE_SCALAR\n#define FBM_AMPLITUDE_SCALAR 0.5\n#endif\n\n#ifndef FNC_FBM\n#define FNC_FBM\nFBM_NOISE_TYPE fbm(in vec2 st) {\n // Initial values\n FBM_NOISE_TYPE value = FBM_NOISE_TYPE(FBM_VALUE_INITIAL);\n float amplitude = FBM_AMPLITUDE_INITIAL;\n\n // Loop of octaves\n for (int i = 0; i < FBM_OCTAVES; i++) {\n value += amplitude * FBM_NOISE2_FNC(st);\n st *= FBM_SCALE_SCALAR;\n amplitude *= FBM_AMPLITUDE_SCALAR;\n }\n return value;\n}\n\nFBM_NOISE_TYPE fbm(in vec3 pos) {\n // Initial values\n FBM_NOISE_TYPE value = FBM_NOISE_TYPE(FBM_VALUE_INITIAL);\n float amplitude = FBM_AMPLITUDE_INITIAL;\n\n // Loop of octaves\n for (int i = 0; i < FBM_OCTAVES; i++) {\n value += amplitude * FBM_NOISE3_FNC(pos);\n pos *= FBM_SCALE_SCALAR;\n amplitude *= FBM_AMPLITUDE_SCALAR;\n }\n return value;\n}\n\nFBM_NOISE_TYPE fbm(vec3 p, float tileLength) {\n const float persistence = 0.5;\n const float lacunarity = 2.0;\n\n float amplitude = 0.5;\n FBM_NOISE_TYPE total = FBM_NOISE_TYPE(0.0);\n float normalization = 0.0;\n\n for (int i = 0; i < FBM_OCTAVES; ++i) {\n float noiseValue = FBM_NOISE3_TILABLE_FNC(p, tileLength * lacunarity * 0.5) * 0.5 + 0.5;\n total += noiseValue * amplitude;\n normalization += amplitude;\n amplitude *= persistence;\n p = p * lacunarity;\n }\n\n return total / normalization;\n}\n#endif\n","#include \"../sampler.glsl\"\n#include \"../math/saturate.glsl\"\n#include \"../math/sum.glsl\"\n\n/*\ncontributors: Patricio Gonzalez Vivo\ndescription: \"morphological dilation operation. Based on: \\n https://lettier.github.io/3d-game-shaders-for-beginners/dilation.html\\n\\\n \\ https://www.shadertoy.com/view/WsyXWc\\n\"\nuse: dilation(<SAMPLER_TYPE> texture, <float2> st, <float2> pixels_scale, <int> passes)\noptions:\n - SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))\n - DILATION_TYPE\n - DILATION_SAMPLE_FNC(TEX, UV)\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef DILATION_TYPE\n#define DILATION_TYPE float\n#endif\n\n#ifndef DILATION_MAX_RADIUS\n#define DILATION_MAX_RADIUS 16\n#endif\n\n#ifndef DILATION_SAMPLE_FNC\n#define DILATION_SAMPLE_FNC(TEX, UV) SAMPLER_FNC(TEX, UV).r\n#endif\n\n#ifndef FNC_DILATE\n#define FNC_DILATE\n\nDILATION_TYPE dilation(SAMPLER_TYPE tex, vec2 st, vec2 pixel, int radius) {\n float invKR = 1.0 / float(radius);\n DILATION_TYPE acc = DILATION_TYPE(0.0);\n float w = 0.0;\n\n #ifdef PLATFORM_WEBGL\n for(int i = -DILATION_MAX_RADIUS; i <= DILATION_MAX_RADIUS; ++i) {\n if (i >= radius) break;\n for(int j = -DILATION_MAX_RADIUS; j <= DILATION_MAX_RADIUS; ++j) {\n if (j >= radius) break;\n #else\n for(int i = -radius; i <= radius; ++i) {\n for(int j = -radius; j <= radius; ++j) {\n #endif\n vec2 rxy = vec2(ivec2(i, j));\n vec2 kst = rxy * invKR * 2.0;\n vec2 texOffset = st + rxy * pixel;\n float kernel = saturate(1.0 - dot(kst, kst));\n DILATION_TYPE t = DILATION_SAMPLE_FNC(tex, texOffset);\n DILATION_TYPE v = t + kernel;\n if (sum(v) > sum(acc)) {\n acc = v;\n w = kernel;\n }\n }\n }\n \n return acc - w;\n}\n\n#endif","/*\ncontributors: Patricio Gonzalez Vivo\ndescription: It defines the default sampler type and function for the shader based on the version of GLSL.\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n#ifndef SAMPLER_FNC\n#if __VERSION__ >= 300\n#define SAMPLER_FNC(TEX, UV) texture(TEX, UV)\n#else\n#define SAMPLER_FNC(TEX, UV) texture2D(TEX, UV)\n#endif\n#endif\n\n#ifndef SAMPLER_TYPE\n#define SAMPLER_TYPE sampler2D\n#endif","#include \"../sampler.glsl\"\n\n/*\ncontributors: Patricio Gonzalez Vivo\ndescription: fakes a clamp to edge texture\nuse: <vec4> sampleClamp2edge(<SAMPLER_TYPE> tex, <vec2> st [, <vec2> texResolution]);\noptions:\n - SAMPLER_FNC(TEX, UV)\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef FNC_SAMPLECLAMP2EDGE\n#define FNC_SAMPLECLAMP2EDGE\nvec4 sampleClamp2edge(SAMPLER_TYPE tex, vec2 st, vec2 texResolution) {\n vec2 pixel = 1.0/texResolution;\n return SAMPLER_FNC( tex, clamp(st, pixel, 1.0-pixel) );\n}\n\nvec4 sampleClamp2edge(SAMPLER_TYPE tex, vec2 st) { \n return SAMPLER_FNC( tex, clamp(st, vec2(0.01), vec2(0.99) ) ); \n}\n\nvec4 sampleClamp2edge(SAMPLER_TYPE tex, vec2 st, float edge) { \n return SAMPLER_FNC( tex, clamp(st, vec2(edge), vec2(1.0 - edge) ) ); \n}\n#endif","/*\ncontributors: Patricio Gonzalez Vivo\ndescription: |\n Draws all the digits of a floating point number, useful for debugging.\n Requires high precision to work properly.\nuse: digits(<vec2> st, <float> value [, <float> nDecDigit])\noptions:\n DIGITS_DECIMALS: number of decimals after the point, defaults to 2\n DIGITS_SIZE: size of the font, defaults to vec2(.025)\nexamples:\n - /shaders/draw_digits.frag\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef DIGITS_SIZE\n#define DIGITS_SIZE vec2(.02)\n#endif\n\n#ifndef DIGITS_DECIMALS\n#define DIGITS_DECIMALS 2.0\n#endif\n\n#ifndef DIGITS_VALUE_OFFSET\n#define DIGITS_VALUE_OFFSET vec2(-6.0, 3.0) \n#endif\n\n#ifndef FNC_DIGITS\n#define FNC_DIGITS\nfloat digits(in vec2 st, in float value, in float nDecDigit) {\n st /= DIGITS_SIZE;\n\n float absValue = abs(value);\n float biggestDigitIndex = max(floor(log2(absValue) / log2(10.)), 0.);\n float counter = floor(absValue);\n float nIntDigits = 1.;\n for (int i = 0; i < 9; i++) {\n counter = floor(counter*.1);\n nIntDigits++;\n if (counter == 0.)\n break;\n }\n\n float digit = 12.;\n float digitIndex = (nIntDigits-1.) - floor(st.x);\n if (digitIndex > (-nDecDigit - 1.5)) {\n if (digitIndex > biggestDigitIndex) {\n if (value < 0.) {\n if (digitIndex < (biggestDigitIndex+1.5)) {\n digit = 11.;\n }\n }\n } \n else {\n if (digitIndex == -1.) {\n if (nDecDigit > 0.) {\n digit = 10.;\n }\n } \n else {\n if (digitIndex < 0.) {\n digitIndex += 1.;\n }\n float digitValue = (absValue / (pow(10., digitIndex)));\n digit = mod(floor(0.0001+digitValue), 10.);\n }\n }\n }\n vec2 pos = vec2(fract(st.x), st.y);\n\n if (pos.x < 0.) return 0.;\n if (pos.y < 0.) return 0.;\n if (pos.x >= 1.) return 0.;\n if (pos.y >= 1.) return 0.;\n\n // make a 4x5 array of bits\n float bin = 0.;\n if (digit < 0.5) // 0\n bin = 7. + 5. * 16. + 5. * 256. + 5. * 4096. + 7. * 65536.; \n else if (digit < 1.5) // 1\n bin = 2. + 2. * 16. + 2. * 256. + 2. * 4096. + 2. * 65536.;\n else if (digit < 2.5) // 2\n bin = 7. + 1. * 16. + 7. * 256. + 4. * 4096. + 7. * 65536.;\n else if (digit < 3.5) // 3\n bin = 7. + 4. * 16. + 7. * 256. + 4. * 4096. + 7. * 65536.;\n else if (digit < 4.5) // 4\n bin = 4. + 7. * 16. + 5. * 256. + 1. * 4096. + 1. * 65536.;\n else if (digit < 5.5) // 5\n bin = 7. + 4. * 16. + 7. * 256. + 1. * 4096. + 7. * 65536.;\n else if (digit < 6.5) // 6\n bin = 7. + 5. * 16. + 7. * 256. + 1. * 4096. + 7. * 65536.;\n else if (digit < 7.5) // 7\n bin = 4. + 4. * 16. + 4. * 256. + 4. * 4096. + 7. * 65536.;\n else if (digit < 8.5) // 8\n bin = 7. + 5. * 16. + 7. * 256. + 5. * 4096. + 7. * 65536.;\n else if (digit < 9.5) // 9\n bin = 7. + 4. * 16. + 7. * 256. + 5. * 4096. + 7. * 65536.;\n else if (digit < 10.5) // '.'\n bin = 2. + 0. * 16. + 0. * 256. + 0. * 4096. + 0. * 65536.;\n else if (digit < 11.5) // '-'\n bin = 0. + 0. * 16. + 7. * 256. + 0. * 4096. + 0. * 65536.;\n\n vec2 pixel = floor(pos * vec2(4., 5.));\n return mod(floor(bin / pow(2., (pixel.x + (pixel.y * 4.)))), 2.);\n}\n\nfloat digits(in vec2 st, in float value, in float nDecDigit, in float nIntDigits) {\n vec2 st2 = st;\n float result = 0.0;\n float dig = nDecDigit;\n\n #ifndef DIGITS_LEADING_INT\n #if defined(PLATFORM_WEBGL)\n #define DIGITS_LEADING_INT 1.0\n #else\n #define DIGITS_LEADING_INT nIntDigits\n #endif\n #endif\n\n for (float i = DIGITS_LEADING_INT - 1.0; i > 0.0 ; i--) {\n if (i * 10.0 > value) {\n result += digits(st2, 0.0, 0.0);\n st2.x -= DIGITS_SIZE.x;\n }\n }\n result += digits(st2, value, nDecDigit);\n return result; \n}\n\nfloat digits(in vec2 st, in int value) {\n return digits(st, float(value), 0.0);\n}\n\nfloat digits(in vec2 st, in float value) {\n return digits(st, value, (DIGITS_DECIMALS));\n}\n\nfloat digits(in vec2 st, in vec2 v) {\n float rta = 0.0;\n for (int i = 0; i < 2; i++) {\n vec2 pos = st + vec2(float(i), 0.0) * DIGITS_SIZE * DIGITS_VALUE_OFFSET;\n float value = i == 0 ? v.x : v.y;\n rta += digits( pos, value );\n }\n return rta;\n}\n\nfloat digits(in vec2 st, in vec3 v) {\n float rta = 0.0;\n for (int i = 0; i < 3; i++) {\n vec2 pos = st + vec2(float(i), 0.0) * DIGITS_SIZE * DIGITS_VALUE_OFFSET;\n float value = i == 0 ? v.x : i == 1 ? v.y : v.z;\n rta += digits( pos, value );\n }\n return rta;\n}\n\nfloat digits(in vec2 st, in vec4 v) {\n float rta = 0.0;\n for (int i = 0; i < 4; i++) {\n vec2 pos = st + vec2(float(i), 0.0) * DIGITS_SIZE * DIGITS_VALUE_OFFSET;\n float value = i == 0 ? v.x : i == 1 ? v.y : i == 2 ? v.z : v.w;\n rta += digits( pos, value );\n }\n return rta;\n}\n\nfloat digits(in vec2 st, in mat2 _matrix) {\n float rta = 0.0;\n for (int i = 0; i < 2; i++) {\n for (int j = 0; j < 2; j++) {\n vec2 pos = st + vec2(float(i), float(j)) * DIGITS_SIZE * DIGITS_VALUE_OFFSET - DIGITS_SIZE * vec2(0.0, 3.0);\n float value = _matrix[j][i];\n rta += digits( pos, value );\n }\n }\n return rta;\n}\n\nfloat digits(in vec2 st, in mat3 _matrix) {\n float rta = 0.0;\n for (int i = 0; i < 3; i++) {\n for (int j = 0; j < 3; j++) {\n vec2 pos = st + vec2(float(i), float(j)) * DIGITS_SIZE * DIGITS_VALUE_OFFSET - DIGITS_SIZE * vec2(0.0, 6.0);\n float value = _matrix[j][i];\n rta += digits( pos, value );\n }\n }\n return rta;\n}\n\nfloat digits(in vec2 st, in mat4 _matrix) {\n float rta = 0.0;\n for (int i = 0; i < 4; i++) {\n for (int j = 0; j < 4; j++) {\n vec2 pos = st + vec2(float(i), float(j)) * DIGITS_SIZE * DIGITS_VALUE_OFFSET - DIGITS_SIZE * vec2(0.0, 9.0);\n float value = _matrix[j][i];\n rta += digits( pos, value );\n }\n }\n return rta;\n}\n#endif\n","#include \"../sampler.glsl\"\n\n/*\ncontributors:\n - Matt DesLauriers\n - Patricio Gonzalez Vivo\ndescription: Adapted versions from 5, 9 and 13 gaussian fast blur from https://github.com/Jam3/glsl-fast-gaussian-blur\nuse: gaussianBlur(<SAMPLER_TYPE> texture, <vec2> st, <vec2> pixel_direction [, const int kernelSize])\noptions:\n - GAUSSIANBLUR_AMOUNT: gaussianBlur5 gaussianBlur9 gaussianBlur13\n - GAUSSIANBLUR_2D: default to 1D\n - SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))\nexamples:\n - /shaders/filter_gaussianBlur2D.frag\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef GAUSSIANBLUR_AMOUNT\n#define GAUSSIANBLUR_AMOUNT gaussianBlur13\n#endif\n\n#ifndef GAUSSIANBLUR_TYPE\n#define GAUSSIANBLUR_TYPE vec4\n#endif\n\n#ifndef GAUSSIANBLUR_SAMPLER_FNC\n#define GAUSSIANBLUR_SAMPLER_FNC(TEX, UV) SAMPLER_FNC(TEX, UV)\n#endif\n\n#include \"gaussianBlur/2D.glsl\"\n#include \"gaussianBlur/1D.glsl\"\n#include \"gaussianBlur/1D_fast13.glsl\"\n#include \"gaussianBlur/1D_fast9.glsl\"\n#include \"gaussianBlur/1D_fast5.glsl\"\n\n#ifndef FNC_GAUSSIANBLUR\n#define FNC_GAUSSIANBLUR\nGAUSSIANBLUR_TYPE gaussianBlur13(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset) {\n#ifdef GAUSSIANBLUR_2D\n return gaussianBlur2D(tex, st, offset, 7);\n#else\n return gaussianBlur1D_fast13(tex, st, offset);\n#endif\n}\n\nGAUSSIANBLUR_TYPE gaussianBlur9(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset) {\n#ifdef GAUSSIANBLUR_2D\n return gaussianBlur2D(tex, st, offset, 5);\n#else\n return gaussianBlur1D_fast9(tex, st, offset);\n#endif\n}\n\nGAUSSIANBLUR_TYPE gaussianBlur5(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset) {\n#ifdef GAUSSIANBLUR_2D\n return gaussianBlur2D(tex, st, offset, 3);\n#else\n return gaussianBlur1D_fast5(tex, st, offset);\n#endif\n}\n\nGAUSSIANBLUR_TYPE gaussianBlur(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset, const int kernelSize) {\n#ifdef GAUSSIANBLUR_2D\n return gaussianBlur2D(tex, st, offset, kernelSize);\n#else\n return gaussianBlur1D(tex, st, offset, kernelSize);\n#endif\n}\n\nGAUSSIANBLUR_TYPE gaussianBlur(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset) {\n return GAUSSIANBLUR_AMOUNT(tex, st, offset);\n}\n#endif\n","#include \"../../math/gaussian.glsl\"\n#include \"../../sample/clamp2edge.glsl\"\n\n/*\ncontributors: Patricio Gonzalez Vivo\ndescription: Two dimension Gaussian Blur to be applied in only one passes\nuse: gaussianBlur2D(<SAMPLER_TYPE> texture, <vec2> st, <vec2> pixel_direction, const int kernelSize)\noptions:\n - SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))\n - GAUSSIANBLUR2D_TYPE: Default `vec4`\n - GAUSSIANBLUR2D_SAMPLER_FNC(TEX, UV): Default `texture2D(tex, TEX, UV)`\n - GAUSSIANBLUR2D_KERNELSIZE: Use only for WebGL 1.0 and OpenGL ES 2.0 . For example RaspberryPis is not happy with dynamic loops. Default is 'kernelSize'\nexamples:\n - /shaders/filter_gaussianBlur2D.frag\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef GAUSSIANBLUR2D_TYPE\n#ifdef GAUSSIANBLUR_TYPE\n#define GAUSSIANBLUR2D_TYPE GAUSSIANBLUR_TYPE\n#else\n#define GAUSSIANBLUR2D_TYPE vec4\n#endif\n#endif\n\n#ifndef GAUSSIANBLUR2D_SAMPLER_FNC\n#ifdef GAUSSIANBLUR_SAMPLER_FNC\n#define GAUSSIANBLUR2D_SAMPLER_FNC(TEX, UV) GAUSSIANBLUR_SAMPLER_FNC(TEX, UV)\n#else\n#define GAUSSIANBLUR2D_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#endif\n#endif\n\n#ifndef FNC_GAUSSIANBLUR2D\n#define FNC_GAUSSIANBLUR2D\nGAUSSIANBLUR2D_TYPE gaussianBlur2D(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset, const int kernelSize) {\n GAUSSIANBLUR2D_TYPE accumColor = GAUSSIANBLUR2D_TYPE(0.);\n \n #ifndef GAUSSIANBLUR2D_KERNELSIZE\n \n #if defined(PLATFORM_WEBGL)\n #define GAUSSIANBLUR2D_KERNELSIZE 20\n float kernelSizef = float(kernelSize);\n #else\n #define GAUSSIANBLUR2D_KERNELSIZE kernelSize\n float kernelSizef = float(GAUSSIANBLUR2D_KERNELSIZE);\n #endif\n\n #else\n float kernelSizef = float(GAUSSIANBLUR2D_KERNELSIZE);\n #endif\n\n float accumWeight = 0.;\n const float k = 0.15915494; // 1 / (2*PI)\n vec2 xy = vec2(0.0);\n for (int j = 0; j < GAUSSIANBLUR2D_KERNELSIZE; j++) {\n #if defined(PLATFORM_WEBGL)\n if (j >= kernelSize)\n break;\n #endif\n xy.y = -.5 * (kernelSizef - 1.) + float(j);\n for (int i = 0; i < GAUSSIANBLUR2D_KERNELSIZE; i++) {\n #if defined(PLATFORM_WEBGL)\n if (i >= kernelSize)\n break;\n #endif\n xy.x = -0.5 * (kernelSizef - 1.) + float(i);\n float weight = (k / kernelSizef) * gaussian(xy, kernelSizef);\n accumColor += weight * GAUSSIANBLUR2D_SAMPLER_FNC(tex, st + xy * offset);\n accumWeight += weight;\n }\n }\n return accumColor / accumWeight;\n}\n#endif\n","#include \"../../math/gaussian.glsl\"\n#include \"../../sample/clamp2edge.glsl\"\n\n/*\ncontributors: Patricio Gonzalez Vivo\ndescription: One dimension Gaussian Blur to be applied in two passes\nuse: gaussianBlur1D(<SAMPLER_TYPE> texture, <vec2> st, <vec2> pixel_direction , const int kernelSize)\noptions:\n - SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))\n - GAUSSIANBLUR1D_TYPE: null\n - GAUSSIANBLUR1D_SAMPLER_FNC(TEX, UV): null\nlicense:\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0\n - Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license\n*/\n\n#ifndef GAUSSIANBLUR1D_TYPE\n#ifdef GAUSSIANBLUR_TYPE\n#define GAUSSIANBLUR1D_TYPE GAUSSIANBLUR_TYPE\n#else\n#define GAUSSIANBLUR1D_TYPE vec4\n#endif\n#endif\n\n#ifndef GAUSSIANBLUR1D_SAMPLER_FNC\n#ifdef GAUSSIANBLUR_SAMPLER_FNC\n#define GAUSSIANBLUR1D_SAMPLER_FNC(TEX, UV) GAUSSIANBLUR_SAMPLER_FNC(TEX, UV)\n#else\n#define GAUSSIANBLUR1D_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#endif\n#endif\n\n#ifndef FNC_GAUSSIANBLUR1D\n#define FNC_GAUSSIANBLUR1D\n\n#ifdef PLATFORM_WEBGL\n\nGAUSSIANBLUR1D_TYPE gaussianBlur1D(in SAMPLER_TYPE tex,in vec2 st,in vec2 offset,const int kernelSize){\n GAUSSIANBLUR1D_TYPE accumColor = GAUSSIANBLUR1D_TYPE(0.0);\n\n float kernelSizef = float(kernelSize);\n float accumWeight = 0.0;\n const float k = 0.39894228;// 1 / sqrt(2*PI)\n for (int i = 0; i < 16; i++) {\n if( i >= kernelSize)\n break;\n float x = -0.5 * (float(kernelSize) - 1.0)+float(i);\n float weight = (k/float(kernelSize)) * gaussian(x, kernelSizef);\n GAUSSIANBLUR1D_TYPE tex = GAUSSIANBLUR1D_SAMPLER_FNC(tex, st + x * offset);\n accumColor += weight * tex;\n accumWeight += weight;\n }\n return accumColor/accumWeight;\n}\n\n#else\n\nGAUSSIANBLUR1D_TYPE gaussianBlur1D(in SAMPLER_TYPE tex,in vec2 st,in vec2 offset,const int kernelSize){\n GAUSSIANBLUR1D_TYPE accumColor=GAUSSIANBLUR1D_TYPE(0.);\n\n float kernelSizef = float(kernelSize);\n \n float accumWeight = 0.0;\n const float k = 0.39894228;// 1 / sqrt(2*PI)\n for (int i = 0; i < kernelSize; i++) {\n float x = -0.5 * ( kernelSizef -1.0) + float(i);\n float weight = (k / kernelSizef) * gaussian(x, kernelSizef);\n GAUSSIANBLUR1D_TYPE tex = GAUSSIANBLUR1D_SAMPLER_FNC(tex, st + x * offset);\n accumColor += weight * tex;\n accumWeight += weight;\n }\n return accumColor/accumWeight;\n}\n#endif\n\n#endif\n","#include \"../../sample/clamp2edge.glsl\"\n\n/*\nfunction: gaussianBlur1D_fast13\ncontributors: Matt DesLauriers\ndescription: Adapted versions of gaussian fast blur 13 from https://github.com/Jam3/glsl-fast-gaussian-blur\nuse: gaussianBlur1D_fast13(<SAMPLER_TYPE> texture, <vec2> st, <vec2> pixel_direction)\noptions:\n - SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))\n - GAUSSIANBLUR1D_FAST13_TYPE\n - GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(TEX, UV)\n*/\n\n#ifndef GAUSSIANBLUR1D_FAST13_TYPE\n#ifdef GAUSSIANBLUR_TYPE\n#define GAUSSIANBLUR1D_FAST13_TYPE GAUSSIANBLUR_TYPE\n#else\n#define GAUSSIANBLUR1D_FAST13_TYPE vec4\n#endif\n#endif\n\n#ifndef GAUSSIANBLUR1D_FAST13_SAMPLER_FNC\n#ifdef GAUSSIANBLUR_SAMPLER_FNC\n#define GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(TEX, UV) GAUSSIANBLUR_SAMPLER_FNC(TEX, UV)\n#else\n#define GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#endif\n#endif\n\n#ifndef FNC_GAUSSIANBLUR1D_FAST13\n#define FNC_GAUSSIANBLUR1D_FAST13\nGAUSSIANBLUR1D_FAST13_TYPE gaussianBlur1D_fast13(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset) {\n GAUSSIANBLUR1D_FAST13_TYPE color = GAUSSIANBLUR1D_FAST13_TYPE(0.);\n vec2 off1 = vec2(1.411764705882353) * offset;\n vec2 off2 = vec2(3.2941176470588234) * offset;\n vec2 off3 = vec2(5.176470588235294) * offset;\n color += GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(tex, st) * .1964825501511404;\n color += GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(tex, st + (off1)) * .2969069646728344;\n color += GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(tex, st - (off1)) * .2969069646728344;\n color += GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(tex, st + (off2)) * .09447039785044732;\n color += GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(tex, st - (off2)) * .09447039785044732;\n color += GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(tex, st + (off3)) * .010381362401148057;\n color += GAUSSIANBLUR1D_FAST13_SAMPLER_FNC(tex, st - (off3)) * .010381362401148057;\n return color;\n}\n#endif\n","#include \"../../sample/clamp2edge.glsl\"\n\n/*\ncontributors: Matt DesLauriers\ndescription: Adapted versions of gaussian fast blur 13 from https://github.com/Jam3/glsl-fast-gaussian-blur\nuse: gaussianBlur1D_fast9(<SAMPLER_TYPE> texture, <vec2> st, <vec2> pixel_direction)\noptions:\n - SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))\n - GAUSSIANBLUR1D_FAST9_TYPE\n - GAUSSIANBLUR1D_FAST9_SAMPLER_FNC(TEX, UV)\n*/\n\n#ifndef GAUSSIANBLUR1D_FAST9_TYPE\n#ifdef GAUSSIANBLUR_TYPE\n#define GAUSSIANBLUR1D_FAST9_TYPE GAUSSIANBLUR_TYPE\n#else\n#define GAUSSIANBLUR1D_FAST9_TYPE vec4\n#endif\n#endif\n\n#ifndef GAUSSIANBLUR1D_FAST9_SAMPLER_FNC\n#ifdef GAUSSIANBLUR_SAMPLER_FNC\n#define GAUSSIANBLUR1D_FAST9_SAMPLER_FNC(TEX, UV) GAUSSIANBLUR_SAMPLER_FNC(TEX, UV)\n#else\n#define GAUSSIANBLUR1D_FAST9_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#endif\n#endif\n\n#ifndef FNC_GAUSSIANBLUR1D_FAST9\n#define FNC_GAUSSIANBLUR1D_FAST9\nGAUSSIANBLUR1D_FAST9_TYPE gaussianBlur1D_fast9(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset) {\n GAUSSIANBLUR1D_FAST9_TYPE color = GAUSSIANBLUR1D_FAST9_TYPE(0.);\n vec2 off1 = vec2(1.3846153846) * offset;\n vec2 off2 = vec2(3.2307692308) * offset;\n color += GAUSSIANBLUR1D_FAST9_SAMPLER_FNC(tex, st) * .2270270270;\n color += GAUSSIANBLUR1D_FAST9_SAMPLER_FNC(tex, st + (off1)) * .3162162162;\n color += GAUSSIANBLUR1D_FAST9_SAMPLER_FNC(tex, st - (off1)) * .3162162162;\n color += GAUSSIANBLUR1D_FAST9_SAMPLER_FNC(tex, st + (off2)) * .0702702703;\n color += GAUSSIANBLUR1D_FAST9_SAMPLER_FNC(tex, st - (off2)) * .0702702703;\n return color;\n}\n#endif\n","#include \"../../sample/clamp2edge.glsl\"\n\n/*\ncontributors: Matt DesLauriers\ndescription: Adapted versions of gaussian fast blur 13 from https://github.com/Jam3/glsl-fast-gaussian-blur\nuse: gaussianBlur1D_fast5(<SAMPLER_TYPE> texture, <vec2> st, <vec2> pixel_direction)\noptions:\n - SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))\n - GAUSSIANBLUR1D_FAST5_TYPE\n - GAUSSIANBLUR1D_FAST5_SAMPLER_FNC(TEX, UV)\n*/\n\n#ifndef GAUSSIANBLUR1D_FAST5_TYPE\n#ifdef GAUSSIANBLUR_TYPE\n#define GAUSSIANBLUR1D_FAST5_TYPE GAUSSIANBLUR_TYPE\n#else\n#define GAUSSIANBLUR1D_FAST5_TYPE vec4\n#endif\n#endif\n\n#ifndef GAUSSIANBLUR1D_FAST5_SAMPLER_FNC\n#ifdef GAUSSIANBLUR_SAMPLER_FNC\n#define GAUSSIANBLUR1D_FAST5_SAMPLER_FNC(TEX, UV) GAUSSIANBLUR_SAMPLER_FNC(TEX, UV)\n#else\n#define GAUSSIANBLUR1D_FAST5_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#endif\n#endif\n\n#ifndef FNC_GAUSSIANBLUR1D_FAST5\n#define FNC_GAUSSIANBLUR1D_FAST5\nGAUSSIANBLUR1D_FAST5_TYPE gaussianBlur1D_fast5(in SAMPLER_TYPE tex, in vec2 st, in vec2 offset) {\n GAUSSIANBLUR1D_FAST5_TYPE color = GAUSSIANBLUR1D_FAST5_TYPE(0.);\n vec2 off1 = vec2(1.3333333333333333) * offset;\n color += GAUSSIANBLUR1D_FAST5_SAMPLER_FNC(tex, st) * .29411764705882354;\n color += GAUSSIANBLUR1D_FAST5_SAMPLER_FNC(tex, st + (off1)) * .35294117647058826;\n color += GAUSSIANBLUR1D_FAST5_SAMPLER_FNC(tex, st - (off1)) * .35294117647058826;\n return color;\n}\n#endif\n","#include \"../sampler.glsl\"\n\n/*\ncontributors: [Brad Larson, Ben Cochran, Hugues Lismonde, Keitaroh Kobayashi, Alaric Cole, Matthew Clark, Jacob Gundersen, Chris Williams.]\ndescription: Kuwahara image abstraction, drawn from the work of Kyprianidis, et. al. in their publication \"Anisotropic Kuwahara Filtering on the GPU\" within the GPU Pro collection. This produces an oil-painting-like image, but it is extremely computationally expensive, so it can take seconds to render a frame on an iPad 2. This might be best used for still images.\nuse: kuwahara(<SAMPLER_TYPE> texture, <vec2> st, <vec2> pixel, <float> radius)\noptions:\n - KUWAHARA_TYPE: defaults to vec3\n - KUWAHARA_SAMPLER_FNC(TEX, UV): defaults to texture2D(tex, TEX, UV).rgb\n - KUWAHARA_RADIUS radius\n - SAMPLER_FNC(TEX, UV): optional depending the target version of GLSL (texture2D(...) or texture(...))\n*/\n\n#ifndef KUWAHARA_TYPE\n#define KUWAHARA_TYPE vec4\n#endif\n\n#ifndef KUWAHARA_SAMPLER_FNC\n#define KUWAHARA_SAMPLER_FNC(TEX, UV) SAMPLER_FNC(TEX, UV)\n#endif\n\n#ifndef FNC_KUWAHARA\n#define FNC_KUWAHARA\n\n#ifdef TARGET_MOBILE\nKUWAHARA_TYPE kuwahara(in SAMPLER_TYPE tex, in vec2 st, in vec2 pixel, in float radius) {\n\n #ifndef KUWAHARA_RADIUS\n #define KUWAHARA_RADIUS radius\n #endif\n\n float n = (KUWAHARA_RADIUS + 1.0) * (KUWAHARA_RADIUS + 1.0);\n KUWAHARA_TYPE m0 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE m1 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE m2 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE m3 = KUWAHARA_TYPE(0.0);\n KUWAHARA_TYPE s0 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE s1 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE s2 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE s3 = KUWAHARA_TYPE(0.0);\n KUWAHARA_TYPE rta = KUWAHARA_TYPE(0.0);\n KUWAHARA_TYPE c = KUWAHARA_TYPE(0.0);\n\n for (float j = -KUWAHARA_RADIUS; j <= 0.0; ++j) {\n for (float i = -KUWAHARA_RADIUS; i <= 0.0; ++i) {\n c = KUWAHARA_SAMPLER_FNC(tex, st + vec2(i,j) * pixel);\n m0 += c;\n s0 += c * c;\n }\n }\n\n for (float j = -KUWAHARA_RADIUS; j <= 0.0; ++j) {\n for (float i = 0.0; i <= KUWAHARA_RADIUS; ++i) {\n c = KUWAHARA_SAMPLER_FNC(tex, st + vec2(i,j) * pixel);\n m1 += c;\n s1 += c * c;\n }\n }\n\n for (float j = 0.0; j <= KUWAHARA_RADIUS; ++j) {\n for (float i = 0.0; i <= KUWAHARA_RADIUS; ++i) {\n c = KUWAHARA_SAMPLER_FNC(tex, st + vec2(i,j) * pixel);\n m2 += c;\n s2 += c * c;\n }\n }\n\n for (float j = 0.0; j <= KUWAHARA_RADIUS; ++j) {\n for (float i = -KUWAHARA_RADIUS; i <= 0.0; ++i) {\n c = KUWAHARA_SAMPLER_FNC(tex, st + vec2(i,j) * pixel);\n m3 += c;\n s3 += c * c;\n }\n }\n\n float min_sigma2 = 1e+2;\n m0 /= n;\n s0 = abs(s0 / n - m0 * m0);\n\n float sigma2 = s0.r + s0.g + s0.b;\n if (sigma2 < min_sigma2) {\n min_sigma2 = sigma2;\n rta = m0;\n }\n\n m1 /= n;\n s1 = abs(s1 / n - m1 * m1);\n\n sigma2 = s1.r + s1.g + s1.b;\n if (sigma2 < min_sigma2) {\n min_sigma2 = sigma2;\n rta = m1;\n }\n\n m2 /= n;\n s2 = abs(s2 / n - m2 * m2);\n\n sigma2 = s2.r + s2.g + s2.b;\n if (sigma2 < min_sigma2) {\n min_sigma2 = sigma2;\n rta = m2;\n }\n\n m3 /= n;\n s3 = abs(s3 / n - m3 * m3);\n\n sigma2 = s3.r + s3.g + s3.b;\n if (sigma2 < min_sigma2) {\n min_sigma2 = sigma2;\n rta = m3;\n }\n\n return rta;\n}\n\n#else\n\nKUWAHARA_TYPE kuwahara(in SAMPLER_TYPE tex, in vec2 st, in vec2 pixel, in float radius) {\n\n #ifndef KUWAHARA_RADIUS\n\n #if defined(PLATFORM_WEBGL)\n #define KUWAHARA_RADIUS 20.0\n float n = (radius + 1.0) * (radius + 1.0);\n #else\n #define KUWAHARA_RADIUS radius\n float n = (KUWAHARA_RADIUS + 1.0) * (KUWAHARA_RADIUS + 1.0);\n #endif\n\n #else\n float n = (KUWAHARA_RADIUS + 1.0) * (KUWAHARA_RADIUS + 1.0);\n #endif\n\n KUWAHARA_TYPE m0 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE m1 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE m2 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE m3 = KUWAHARA_TYPE(0.0);\n KUWAHARA_TYPE s0 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE s1 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE s2 = KUWAHARA_TYPE(0.0); KUWAHARA_TYPE s3 = KUWAHARA_TYPE(0.0);\n KUWAHARA_TYPE rta = KUWAHARA_TYPE(0.0);\n KUWAHARA_TYPE c = KUWAHARA_TYPE(0.0);\n \n for (float j = -KUWAHARA_RADIUS; j <= 0.0; ++j) { \n for (float i = -KUWAHARA_RADIUS; i <= 0.0; ++i) {\n c = KUWAHARA_SAMPLER_FNC(tex, st + vec2(i,j) * pixel);\n m0 += c;\n s0 += c * c;\n }\n }\n \n for (float j = -KUWAHARA_RADIUS; j <= 0.0; ++j) {\n for (float i = 0.0; i <= KUWAHARA_RADIUS; ++i) {\n #if defined(PLATFORM_WEBGL)\n if (i > radius)\n break;\n #endif\n c = KUWAHARA_SAMPLER_FNC(tex, st + vec2(i,j) * pixel);\n m1 += c;\n s1 += c * c;\n }\n }\n \n for (float j = 0.0; j <= KUWAHARA_RADIUS; ++j) {\n #if defined(PLATFORM_WEBGL)\n if (j > radius)\n break;\n #endif\n for (float i = 0.0; i <= KUWAHARA_RADIUS; ++i) {\n #if defined(PLATFORM_WEBGL)\n if (i > radius)\n break;\n #endif\n c = KUWAHARA_SAMPLER_FNC(tex, st + vec2(i,j) * pixel);\n m2 += c;\n s2 += c * c;\n }\n }\n \n for (float j = 0.0; j <= KUWAHARA_RADIUS; ++j) {\n for (float i = -KUWAHARA_RADIUS; i <= 0.0; ++i) {\n c = KUWAHARA_SAMPLER_FNC(tex, st + vec2(i,j) * pixel);\n m3 += c;\n s3 += c * c;\n }\n }\n \n \n float min_sigma2 = 1e+2;\n m0 /= n;\n s0 = abs(s0 / n - m0 * m0);\n \n float sigma2 = s0.r + s0.g + s0.b;\n if (sigma2 < min_sigma2) {\n min_sigma2 = sigma2;\n rta = m0;\n }\n \n m1 /= n;\n s1 = abs(s1 / n - m1 * m1);\n \n sigma2 = s1.r + s1.g + s1.b;\n if (sigma2 < min_sigma2) {\n min_sigma2 = sigma2;\n rta = m1;\n }\n \n m2 /= n;\n s2 = abs(s2 / n - m2 * m2);\n \n sigma2 = s2.r + s2.g + s2.b;\n if (sigma2 < min_sigma2) {\n min_sigma2 = sigma2;\n rta = m2;\n }\n \n m3 /= n;\n s3 = abs(s3 / n - m3 * m3);\n \n sigma2 = s3.r + s3.g + s3.b;\n if (sigma2 < min_sigma2) {\n min_sigma2 = sigma2;\n rta = m3;\n }\n\n return rta;\n}\n\n#endif\n\n#endif","export const glsl = (x: TemplateStringsArray): string => String.raw(x)\n","import { glsl } from './glsl'\n\nexport default glsl`\nmat3 rotationX(float angle) {\n float s = sin(angle);\n float c = cos(angle);\n return mat3(\n 1.0, 0.0, 0.0,\n 0.0, c, -s,\n 0.0, s, c\n );\n}\n\nmat3 rotationY(float angle) {\n float s = sin(angle);\n float c = cos(angle);\n return mat3(\n c, 0.0, s,\n 0.0, 1.0, 0.0,\n -s, 0.0, c\n );\n}\n\nvec4 defaultLighting(vec4 color, vec2 res, vec2 rot, float diff) {\n float aspectRatio = res.y / res.x;\n vec2 uv = (gl_FragCoord.xy / res.xy) * 2.0 - 1.0;\n vec2 specPos = vec2(rot.x * 3.8, rot.y * 2.2);\n\n vec3 baseNormal = vec3(0.0, 0.0, 1.0);\n mat3 rotMatrix = rotationX(rot.y) * rotationY(rot.x);\n vec3 normal = normalize(rotMatrix * baseNormal);\n\n vec3 lightDir = normalize(vec3(0.1, 0.5, 1.0));\n vec3 viewDir = normalize(vec3(0.0, 0.0, 1.0));\n\n vec3 halfDir = normalize(lightDir + viewDir);\n float spec = pow(max(dot(normal, halfDir), 0.0), 64.0);\n\n vec2 diffPos = uv - specPos;\n diffPos.y *= aspectRatio;\n float dist = length(diffPos);\n float mask = exp(-dist * 0.6);\n float lightFalloff = 1.0 / (dist + 1.3);\n spec *= mask * lightFalloff;\n\n return vec4(color.rgb * diff + vec3(1.0) * spec, 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n// three.js built-in attributes\n// attribute vec3 position;\n// attribute vec3 normal;\n// attribute vec2 uv;\n\n// three.js built-in uniforms\n// uniform mat4 modelMatrix; // a.k.a worldMatrix\n// uniform mat4 viewMatrix;\n// uniform mat4 modelViewMatrix;\n// uniform mat3 normalMatrix;\n// uniform mat4 projectionMatrix;\n// uniform vec3 cameraPosition;\n\n// world transformed attributes for the fragment shader\nvarying vec3 vNormal;\nvarying vec3 vPosition;\nvarying vec2 vUv;\nvarying vec3 vView;\n\nvoid main() {\n // vec4 pos = viewMatrix * modelMatrix * vec4(position, 1.0);\n vec4 pos = modelViewMatrix * vec4(position, 1.0);\n\n // normalMatrix = transpose(inverse(mat3(modelMatrix)));\n // because transform matrix for normal vector is L^-1T\n vUv = uv;\n vPosition = pos.xyz;\n vView = normalize(cameraPosition - vPosition);\n vNormal = normalize(normalMatrix * normal);\n\n // transform the position to clip space\n gl_Position = projectionMatrix * pos;\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n#include <utils/defaultLighting>\n\nvoid main() {\n // 기본 카드 텍스처 샘플링\n vec4 baseColor = texture2D(uImgBase, vUv);\n\n // 팝업 텍스처 샘플링 (움직임 반영)\n float popupOffset = 0.0;\n vec2 popupUv = vUv + (uMove / uResolution) * popupOffset; // 팝업 이동 효과\n vec4 popupColor = texture2D(uImgPopup, popupUv);\n\n float aSoft = smoothstep(0.4, 1.0, popupColor.a);\n vec4 pocaColor = mix(baseColor, popupColor, aSoft);\n\n gl_FragColor = defaultLighting(pocaColor, uResolution, uRotate, 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n#include <utils/defaultLighting>\n\nvoid main() {\n // 기본 카드 텍스처 샘플링\n vec4 baseColor = texture2D(uImgBase, vUv);\n\n // 팝업 텍스처 샘플링 (움직임 반영)\n vec2 popupOffset = vec2(-uRotate.x * 0.08, -uRotate.y * 0.06);\n vec2 popupUv = vUv + popupOffset; // 팝업 이동 효과\n vec4 popupColor = texture2D(uImgPopup, popupUv);\n\n float aSoft = smoothstep(0.4, 1.0, popupColor.a);\n vec4 pocaColor = mix(baseColor, popupColor, aSoft);\n\n gl_FragColor = defaultLighting(pocaColor, uResolution, uRotate, 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n#define mod289(x) mod(x, 289.)\n\nvec3 permute(vec3 x) { return mod289(((x * 34.0) + 1.0) * x); }\n\nfloat snoise(vec2 coord) {\n const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439);\n vec2 intPart = floor(coord + dot(coord, C.yy));\n vec2 fracPart = coord - intPart + dot(intPart, C.xx);\n\n vec2 offset;\n offset = (fracPart.x > fracPart.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);\n vec4 combined = fracPart.xyxy + C.xxzz;\n combined.xy -= offset;\n\n intPart = mod289(intPart);\n vec3 perm = permute(permute(intPart.y + vec3(0.0, offset.y, 1.0))\n + intPart.x + vec3(0.0, offset.x, 1.0));\n\n vec3 gradient = max(0.5 - vec3(dot(fracPart, fracPart), dot(combined.xy, combined.xy), dot(combined.zw, combined.zw)), 0.0);\n gradient *= gradient;\n gradient *= gradient;\n\n vec3 noiseVec = 2.0 * fract(perm * C.www) - 1.0;\n vec3 absDiff = abs(noiseVec) - 0.5;\n vec3 offsetVec = floor(noiseVec + 0.5);\n vec3 gradientVec = noiseVec - offsetVec;\n\n gradient *= 1.79284291400159 - 0.85373472095314 * (gradientVec * gradientVec + absDiff * absDiff);\n\n vec3 finalGrad;\n finalGrad.x = gradientVec.x * fracPart.x + absDiff.x * fracPart.y;\n finalGrad.yz = gradientVec.yz * combined.xz + absDiff.yz * combined.yw;\n\n return 130.0 * dot(gradient, finalGrad);\n}\n\nfloat fbm(vec2 position) {\n float result = 0.0;\n float weight = 0.5;\n for (int i = 0; i < 5; i++) {\n result += weight * snoise(position);\n position *= 2.0;\n weight *= 0.5;\n }\n return result;\n}\n\n// snowfall\nconst int LAYERS = 66;\nconst float DEPTH_NEAR = 0.3;\nconst float WIDTH_NEAR = 0.4;\nconst float SPEED_NEAR = 0.6;\nconst float DEPTH_FAR = 0.1;\nconst float WIDTH_FAR = 0.3;\nconst float SPEED_FAR = 0.1;\n\nfloat computeSnow(in vec2 uv, int layerStart, int layerEnd) {\n const mat3 permutationMatrix = mat3(13.323122, 23.5112, 21.71123, 21.1212, 28.7312, 11.9312, 21.8112, 14.7212, 61.3934);\n vec2 moveNormalized = uMove.xy / uResolution.xy;\n moveNormalized.x = max(0.15, smoothstep(0.15, 0.8, moveNormalized.x));\n uv.x += moveNormalized.x * 0.2;\n float totalLayers = float(LAYERS);\n float accumulation = 0.0;\n float depthOfField = 5.0 * sin(uTime * 0.1);\n for (int i = max(layerStart, 0); i < min(layerEnd, LAYERS); i++) {\n float layer = float(i);\n float depthFactor = smoothstep(DEPTH_NEAR, DEPTH_FAR, layer / totalLayers);\n float widthFactor = smoothstep(WIDTH_NEAR, WIDTH_FAR, layer / totalLayers);\n float speedFactor = smoothstep(SPEED_NEAR, SPEED_FAR, layer / totalLayers);\n vec2 offsetUv = uv * (1.0 + layer * depthFactor);\n float windEffect = widthFactor * mod(layer * 7.238917, 1.0) - widthFactor * 0.1 * sin(uTime * 2.0 + layer);\n offsetUv += vec2(offsetUv.y * windEffect, speedFactor * uTime / (1.0 + layer * depthFactor * 0.03));\n vec3 noiseInput = vec3(floor(offsetUv), 31.189 + layer);\n vec3 permuted = floor(noiseInput) * 0.00001 + fract(noiseInput);\n vec3 noise = fract((31415.9 + permuted) / fract(permutationMatrix * permuted));\n vec2 particleShape = abs(mod(offsetUv, 1.0) - 0.5 + 0.9 * noise.xy - 0.45);\n particleShape += 0.01 * abs(2.0 * fract(10.0 * offsetUv.yx) - 1.0);\n float distance = 0.6 * max(particleShape.x - particleShape.y, particleShape.x + particleShape.y) + max(particleShape.x, particleShape.y) - 0.01;\n float edgeThreshold = 0.05 + 0.05 * min(0.5 * abs(layer - 5.0 - depthOfField), 1.0);\n accumulation += smoothstep(edgeThreshold, -edgeThreshold, distance) * (noise.x / (1.0 + 0.02 * layer * depthFactor));\n }\n return accumulation;\n}\n\nvoid main() {\n vec4 baseTexture = texture2D(uImgBase, vUv);\n gl_FragColor = mix(gl_FragColor, baseTexture, baseTexture.a);\n\n float snowEffect = computeSnow(vUv, 5, 15);\n gl_FragColor += vec4(vec3(snowEffect), 1.0);\n\n float popupMoveOffset = 0.0;\n vec2 popupOffsetUv = vUv + (uMove.xy / uResolution.xy) * popupMoveOffset;\n vec4 popupTexture = texture2D(uImgPopup, popupOffsetUv);\n gl_FragColor = mix(gl_FragColor, popupTexture, popupTexture.a);\n\n snowEffect = computeSnow(vUv, 16, 20);\n gl_FragColor += vec4(vec3(snowEffect), 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n#define mod289(x) mod(x, 289.)\n\nvec3 permute(vec3 x) { return mod289(((x * 34.0) + 1.0) * x); }\n\nfloat snoise(vec2 coord) {\n const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439);\n vec2 intPart = floor(coord + dot(coord, C.yy));\n vec2 fracPart = coord - intPart + dot(intPart, C.xx);\n\n vec2 offset;\n offset = (fracPart.x > fracPart.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);\n vec4 combined = fracPart.xyxy + C.xxzz;\n combined.xy -= offset;\n\n intPart = mod289(intPart);\n vec3 perm = permute(permute(intPart.y + vec3(0.0, offset.y, 1.0))\n + intPart.x + vec3(0.0, offset.x, 1.0));\n\n vec3 gradient = max(0.5 - vec3(dot(fracPart, fracPart), dot(combined.xy, combined.xy), dot(combined.zw, combined.zw)), 0.0);\n gradient *= gradient;\n gradient *= gradient;\n\n vec3 noiseVec = 2.0 * fract(perm * C.www) - 1.0;\n vec3 absDiff = abs(noiseVec) - 0.5;\n vec3 offsetVec = floor(noiseVec + 0.5);\n vec3 gradientVec = noiseVec - offsetVec;\n\n gradient *= 1.79284291400159 - 0.85373472095314 * (gradientVec * gradientVec + absDiff * absDiff);\n\n vec3 finalGrad;\n finalGrad.x = gradientVec.x * fracPart.x + absDiff.x * fracPart.y;\n finalGrad.yz = gradientVec.yz * combined.xz + absDiff.yz * combined.yw;\n\n return 130.0 * dot(gradient, finalGrad);\n}\n\nfloat fbm(vec2 position) {\n float result = 0.0;\n float weight = 0.5;\n for (int i = 0; i < 5; i++) {\n result += weight * snoise(position);\n position *= 2.0;\n weight *= 0.5;\n }\n return result;\n}\n\n// snowfall\nconst int LAYERS = 66;\nconst float DEPTH_NEAR = 0.3;\nconst float WIDTH_NEAR = 0.4;\nconst float SPEED_NEAR = 0.6;\nconst float DEPTH_FAR = 0.1;\nconst float WIDTH_FAR = 0.3;\nconst float SPEED_FAR = 0.1;\n\nfloat computeSnow(in vec2 uv, int layerStart, int layerEnd) {\n const mat3 permutationMatrix = mat3(13.323122, 23.5112, 21.71123, 21.1212, 28.7312, 11.9312, 21.8112, 14.7212, 61.3934);\n vec2 moveNormalized = uMove.xy / uResolution.xy;\n moveNormalized.x = max(0.15, smoothstep(0.15, 0.8, moveNormalized.x));\n uv.x += moveNormalized.x * 0.2;\n float totalLayers = float(LAYERS);\n float accumulation = 0.0;\n float depthOfField = 5.0 * sin(uTime * 0.1);\n for (int i = max(layerStart, 0); i < min(layerEnd, LAYERS); i++) {\n float layer = float(i);\n float depthFactor = smoothstep(DEPTH_NEAR, DEPTH_FAR, layer / totalLayers);\n float widthFactor = smoothstep(WIDTH_NEAR, WIDTH_FAR, layer / totalLayers);\n float speedFactor = smoothstep(SPEED_NEAR, SPEED_FAR, layer / totalLayers);\n vec2 offsetUv = uv * (1.0 + layer * depthFactor);\n float windEffect = widthFactor * mod(layer * 7.238917, 1.0) - widthFactor * 0.1 * sin(uTime * 2.0 + layer);\n offsetUv += vec2(offsetUv.y * windEffect, speedFactor * uTime / (1.0 + layer * depthFactor * 0.03));\n vec3 noiseInput = vec3(floor(offsetUv), 31.189 + layer);\n vec3 permuted = floor(noiseInput) * 0.00001 + fract(noiseInput);\n vec3 noise = fract((31415.9 + permuted) / fract(permutationMatrix * permuted));\n vec2 particleShape = abs(mod(offsetUv, 1.0) - 0.5 + 0.9 * noise.xy - 0.45);\n particleShape += 0.01 * abs(2.0 * fract(10.0 * offsetUv.yx) - 1.0);\n float distance = 0.6 * max(particleShape.x - particleShape.y, particleShape.x + particleShape.y) + max(particleShape.x, particleShape.y) - 0.01;\n float edgeThreshold = 0.05 + 0.05 * min(0.5 * abs(layer - 5.0 - depthOfField), 1.0);\n accumulation += smoothstep(edgeThreshold, -edgeThreshold, distance) * (noise.x / (1.0 + 0.02 * layer * depthFactor));\n }\n return accumulation;\n}\n\nvoid main() {\n vec4 baseTexture = texture2D(uImgBase, vUv);\n gl_FragColor = mix(gl_FragColor, baseTexture, baseTexture.a);\n\n float snowEffect = computeSnow(vUv, 5, 15);\n gl_FragColor += vec4(vec3(snowEffect), 1.0);\n\n // 3D parallax offset for popup layer\n vec2 popupOffset = vec2(-uRotate.x * 0.08, -uRotate.y * 0.06);\n vec2 popupOffsetUv = vUv + popupOffset;\n vec4 popupTexture = texture2D(uImgPopup, popupOffsetUv);\n gl_FragColor = mix(gl_FragColor, popupTexture, popupTexture.a);\n\n snowEffect = computeSnow(vUv, 16, 20);\n gl_FragColor += vec4(vec3(snowEffect), 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n#include <lygia/sample/clamp2edge>\n#define KUWAHARA_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#include <lygia/filter/kuwahara>\n#include <lygia/draw/digits>\n#include <utils/defaultLighting>\n\nvoid main() {\n vec2 pixel = 1.0 / uResolution.xy;\n vec2 popUpUv = vUv + (uMove.xy / uResolution.xy) * 0.008;\n\n vec4 baseColor = kuwahara(uImgBase, vUv, pixel, 4.0);\n vec4 popupColor = kuwahara(uImgPopup, popUpUv, pixel, 4.0);\n\n float aSoft = smoothstep(0.4, 1.0, popupColor.a);\n vec4 pocaColor = mix(baseColor, popupColor, aSoft);\n\n gl_FragColor = defaultLighting(pocaColor, uResolution, uRotate, 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n#include <lygia/sample/clamp2edge>\n#define KUWAHARA_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#include <lygia/filter/kuwahara>\n#include <lygia/draw/digits>\n#include <utils/defaultLighting>\n\nvoid main() {\n vec2 pixel = 1.0 / uResolution.xy;\n\n // 3D parallax offset for popup layer\n vec2 popupOffset = vec2(-uRotate.x * 0.08, -uRotate.y * 0.06);\n vec2 popUpUv = vUv + popupOffset;\n\n vec4 baseColor = kuwahara(uImgBase, vUv, pixel, 4.0);\n vec4 popupColor = kuwahara(uImgPopup, popUpUv, pixel, 4.0);\n\n float aSoft = smoothstep(0.4, 1.0, popupColor.a);\n vec4 pocaColor = mix(baseColor, popupColor, aSoft);\n\n gl_FragColor = defaultLighting(pocaColor, uResolution, uRotate, 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n// #define GAUSSIANBLUR_2D\n#include <lygia/sample/clamp2edge>\n#define GAUSSIANBLUR_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#include <lygia/filter/gaussianBlur>\n#include <lygia/draw/digits>\n#include <utils/defaultLighting>\n\nvoid main() {\n vec2 pixel = 1.0 / uResolution.xy;\n vec2 popUpUv = vUv + (uMove.xy / uResolution.xy) * 0.008;\n\n vec4 baseColor = gaussianBlur(uImgBase, vUv, pixel, 12);\n vec4 popupColor = texture2D(uImgPopup, popUpUv);\n\n float aSoft = smoothstep(0.4, 1.0, popupColor.a);\n vec4 pocaColor = mix(baseColor, popupColor, aSoft);\n\n gl_FragColor = defaultLighting(pocaColor, uResolution, uRotate, 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n// #define GAUSSIANBLUR_2D\n#include <lygia/sample/clamp2edge>\n#define GAUSSIANBLUR_SAMPLER_FNC(TEX, UV) sampleClamp2edge(TEX, UV)\n#include <lygia/filter/gaussianBlur>\n#include <lygia/draw/digits>\n#include <utils/defaultLighting>\n\nvoid main() {\n vec2 pixel = 1.0 / uResolution.xy;\n\n // 3D parallax offset for popup layer\n vec2 popupOffset = vec2(-uRotate.x * 0.08, -uRotate.y * 0.06);\n vec2 popUpUv = vUv + popupOffset;\n\n vec4 baseColor = gaussianBlur(uImgBase, vUv, pixel, 12);\n vec4 popupColor = texture2D(uImgPopup, popUpUv);\n\n float aSoft = smoothstep(0.4, 1.0, popupColor.a);\n vec4 pocaColor = mix(baseColor, popupColor, aSoft);\n\n gl_FragColor = defaultLighting(pocaColor, uResolution, uRotate, 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n#include <utils/defaultLighting>\n\n// HSV to RGB conversion\nvec3 hsv2rgb(vec3 c) {\n vec4 K = vec4(1.0, 2.0/3.0, 1.0/3.0, 3.0);\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\nvoid main() {\n vec4 baseColor = texture2D(uImgBase, vUv);\n vec4 popupColor = texture2D(uImgPopup, vUv);\n\n // Iridescence on base only\n float angle = uRotate.x * 2.0 + uRotate.y * 1.5;\n float hue = fract(vUv.y * 0.8 + vUv.x * 0.3 + angle * 0.5 + uTime * 0.05);\n vec3 rainbow = hsv2rgb(vec3(hue, 0.6, 1.0));\n\n float tiltAmount = length(uRotate) * 3.0;\n float holoIntensity = smoothstep(0.0, 1.0, tiltAmount) * 0.35;\n\n vec3 holoBase = baseColor.rgb + rainbow * holoIntensity;\n\n // Composite popup on top without holo\n float aSoft = smoothstep(0.4, 1.0, popupColor.a);\n vec3 finalColor = mix(holoBase, popupColor.rgb, aSoft);\n\n gl_FragColor = defaultLighting(vec4(finalColor, 1.0), uResolution, uRotate, 1.0);\n}\n`\n","import { glsl } from './utils/glsl'\n\nexport default glsl`\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nuniform vec2 uResolution;\nuniform vec2 uMouse;\nuniform vec2 uMove;\nuniform vec2 uRotate;\nuniform float uTime;\nuniform sampler2D uImgBase;\nuniform sampler2D uImgPopup;\n\nvarying vec2 vUv;\n\n#include <utils/defaultLighting>\n\n// HSV to RGB conversion\nvec3 hsv2rgb(vec3 c) {\n vec4 K = vec4(1.0, 2.0/3.0, 1.0/3.0, 3.0);\n vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\nvoid main() {\n vec4 baseColor = texture2D(uImgBase, vUv);\n\n // 3D parallax offset for popup layer\n vec2 popupOffset = vec2(-uRotate.x * 0.08, -uRotate.y * 0.06);\n vec2 popupUv = vUv + popupOffset;\n vec4 popupColor = texture2D(uImgPopup, popupUv);\n\n // Iridescence on base only\n float angle = uRotate.x * 2.0 + uRotate.y * 1.5;\n float hue = fract(vUv.y * 0.8 + vUv.x * 0.3 + angle * 0.5 + uTime * 0.05);\n vec3 rainbow = hsv2rgb(vec3(hue, 0.6, 1.0));\n\n float tiltAmount = length(uRotate) * 3.0;\n float holoIntensity = smoothstep(0.0, 1.0, tiltAmount) * 0.35;\n\n vec3 holoBase = baseColor.rgb + rainbow * holoIntensity;\n\n // Composite popup on top without holo\n float aSoft = smoothstep(0.4, 1.0, popupColor.a);\n vec3 finalColor = mix(holoBase, popupColor.rgb, aSoft);\n\n gl_FragColor = defaultLighting(vec4(finalColor, 1.0), uResolution, uRotate, 1.0);\n}\n`\n","export interface SpringOpts {\n stiffness?: number\n damping?: number\n precision?: number\n}\n\nexport interface SpringUpdateOpts {\n hard?: boolean\n soft?: number | boolean\n}\n\nexport interface Spring<T> {\n set(value: T, opts?: SpringUpdateOpts): Promise<void>\n get(): T\n stiffness: number\n damping: number\n precision: number\n}\n\n// Global animation loop shared across all springs\nconst tasks: Set<() => boolean> = new Set()\nlet rafId: number | null = null\n\nfunction runLoop() {\n if (tasks.size === 0) {\n rafId = null\n return\n }\n for (const task of tasks) {\n if (!task()) {\n tasks.delete(task)\n }\n }\n rafId = requestAnimationFrame(runLoop)\n}\n\nfunction scheduleTask(task: () => boolean) {\n tasks.add(task)\n if (rafId === null) {\n rafId = requestAnimationFrame(runLoop)\n }\n}\n\nfunction tickSpring(\n ctx: { val: number; lastVal: number; target: number; invMass: number },\n stiffness: number,\n damping: number,\n precision: number,\n): boolean {\n const delta = ctx.target - ctx.val\n const velocity = ctx.val - ctx.lastVal\n const springForce = stiffness * delta\n const damperForce = damping * velocity\n const acceleration = (springForce - damperForce) * ctx.invMass\n const d = velocity + acceleration\n\n if (Math.abs(d) < precision && Math.abs(delta) < precision) {\n ctx.val = ctx.target\n ctx.lastVal = ctx.target\n return false // settled\n }\n\n ctx.lastVal = ctx.val\n ctx.val += d\n return true // still moving\n}\n\nexport function spring(\n initialValue: number,\n onChange: (value: number) => void,\n opts: SpringOpts = {},\n): Spring<number> {\n const stiffness = opts.stiffness ?? 0.15\n const damping = opts.damping ?? 0.8\n const precision = opts.precision ?? 0.01\n\n const ctx = {\n val: initialValue,\n lastVal: initialValue,\n target: initialValue,\n invMass: 1,\n }\n let currentResolve: (() => void) | null = null\n\n const s: Spring<number> = {\n stiffness,\n damping,\n precision,\n get() {\n return ctx.val\n },\n set(value: number, updateOpts?: SpringUpdateOpts) {\n ctx.target = value\n\n if (updateOpts?.hard) {\n ctx.val = value\n ctx.lastVal = value\n onChange(value)\n return Promise.resolve()\n }\n\n if (updateOpts?.soft) {\n const rate = typeof updateOpts.soft === 'number' ? updateOpts.soft : 0.5\n ctx.invMass = Math.min(ctx.invMass, rate)\n }\n\n return new Promise<void>((resolve) => {\n currentResolve = resolve\n scheduleTask(() => {\n const invMassTarget = 1\n ctx.invMass = Math.min(ctx.invMass + 0.02, invMassTarget)\n\n const moving = tickSpring(ctx, s.stiffness, s.damping, s.precision)\n onChange(ctx.val)\n\n if (!moving) {\n currentResolve?.()\n currentResolve = null\n }\n return moving\n })\n })\n },\n }\n\n return s\n}\n\n// Convenience: spring for {x, y} objects\n// Uses batched onChange — ticks all components per frame, calls onChange once\nexport function springVec2(\n initial: { x: number; y: number },\n onChange: (value: { x: number; y: number }) => void,\n opts: SpringOpts = {},\n): Spring<{ x: number; y: number }> {\n const state = { x: initial.x, y: initial.y }\n let dirty = false\n\n const flush = () => {\n if (dirty) {\n dirty = false\n onChange({ ...state })\n }\n }\n\n const sx = spring(initial.x, (v) => {\n state.x = v\n dirty = true\n // Use microtask to batch x+y updates within the same frame\n queueMicrotask(flush)\n }, opts)\n\n const sy = spring(initial.y, (v) => {\n state.y = v\n dirty = true\n queueMicrotask(flush)\n }, opts)\n\n return {\n get stiffness() { return sx.stiffness },\n set stiffness(v) { sx.stiffness = v; sy.stiffness = v },\n get damping() { return sx.damping },\n set damping(v) { sx.damping = v; sy.damping = v },\n get precision() { return sx.precision },\n set precision(v) { sx.precision = v; sy.precision = v },\n get() {\n return { x: sx.get(), y: sy.get() }\n },\n async set(value, updateOpts) {\n await Promise.all([\n sx.set(value.x, updateOpts),\n sy.set(value.y, updateOpts),\n ])\n },\n }\n}\n\n// Convenience: spring for {x, y, o} (glare)\nexport function springVec3(\n initial: { x: number; y: number; o: number },\n onChange: (value: { x: number; y: number; o: number }) => void,\n opts: SpringOpts = {},\n): Spring<{ x: number; y: number; o: number }> {\n const state = { x: initial.x, y: initial.y, o: initial.o }\n let dirty = false\n\n const flush = () => {\n if (dirty) {\n dirty = false\n onChange({ ...state })\n }\n }\n\n const sx = spring(initial.x, (v) => {\n state.x = v\n dirty = true\n queueMicrotask(flush)\n }, opts)\n\n const sy = spring(initial.y, (v) => {\n state.y = v\n dirty = true\n queueMicrotask(flush)\n }, opts)\n\n const so = spring(initial.o, (v) => {\n state.o = v\n dirty = true\n queueMicrotask(flush)\n }, opts)\n\n return {\n get stiffness() { return sx.stiffness },\n set stiffness(v) { sx.stiffness = v; sy.stiffness = v; so.stiffness = v },\n get damping() { return sx.damping },\n set damping(v) { sx.damping = v; sy.damping = v; so.damping = v },\n get precision() { return sx.precision },\n set precision(v) { sx.precision = v; sy.precision = v; so.precision = v },\n get() {\n return { x: sx.get(), y: sy.get(), o: so.get() }\n },\n async set(value, updateOpts) {\n await Promise.all([\n sx.set(value.x, updateOpts),\n sy.set(value.y, updateOpts),\n so.set(value.o, updateOpts),\n ])\n },\n }\n}\n","export const round = (value: number, precision = 3): number =>\n parseFloat(value.toFixed(precision))\n\nexport const clamp = (value: number, min = 0, max = 100): number =>\n Math.min(Math.max(value, min), max)\n\nexport const adjust = (\n value: number,\n fromMin: number,\n fromMax: number,\n toMin: number,\n toMax: number,\n): number =>\n round(toMin + ((toMax - toMin) * (value - fromMin)) / (fromMax - fromMin))\n\nexport const distance = (x1: number, y1: number, x2: number, y2: number): number =>\n Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)\n","import { springVec2, springVec3, type Spring } from '../animation/spring';\nimport { clamp, distance, round } from '../utils/math';\n\nexport interface InteractionCallbacks {\n onRotate: (rotate: { x: number; y: number }) => void\n onGlare: (glare: { x: number; y: number; o: number }) => void\n onMousePos: (pos: { x: number; y: number }) => void\n onMoveDelta: (delta: { x: number; y: number }) => void\n onDistFromCenter: (dist: number) => void\n onFlip: (flipped: boolean) => void\n}\n\ninterface Rect {\n left: number\n top: number\n width: number\n height: number\n}\n\nconst SPRING_INTERACT = { stiffness: 0.095, damping: 0.5 }\nconst SPRING_FLIP = { stiffness: 0.03, damping: 0.25 }\nconst THROTTLE_MS = 1000 / 60\nconst DBLCLICK_MS = 200\n\nexport class InteractionHandler {\n private flipped = false\n private interacting = false\n private boundingRect: Rect = { left: 0, top: 0, width: 0, height: 0 }\n private interactionOrigin = { x: 0, y: 0 }\n\n private springRotate: Spring<{ x: number; y: number }>\n private springGlare: Spring<{ x: number; y: number; o: number }>\n\n private lastThrottleTime = 0\n private clickCount = 0\n private dblClickTimer: ReturnType<typeof setTimeout> | null = null\n private activePointerId: number | null = null\n\n private boundPointerDown: (e: PointerEvent) => void\n private boundPointerMove: (e: PointerEvent) => void\n private boundPointerUp: (e: PointerEvent) => void\n private boundClick: (e: MouseEvent) => void\n private boundTouchHandler: (e: TouchEvent) => void\n\n private _flipSpeed = 1\n\n constructor(\n private container: HTMLElement,\n private callbacks: InteractionCallbacks,\n private flippable: boolean,\n initialFlipped: boolean,\n ) {\n this.flipped = initialFlipped\n\n // Spring rotate onChange: apply flip-aware sign to CSS rotation\n // Angular: { x: flipped ? 180 - v.x : -v.x, y: flipped ? -v.y : v.y }\n this.springRotate = springVec2({ x: 0, y: 0 }, (v) => {\n callbacks.onRotate(v)\n callbacks.onDistFromCenter(clamp(distance(v.x, v.y, 0, 0) / 50, 0, 1))\n }, SPRING_INTERACT)\n\n this.springGlare = springVec3({ x: 50, y: 50, o: 0 }, (v) => {\n callbacks.onGlare(v)\n }, SPRING_INTERACT)\n\n this.boundPointerDown = this.onPointerDown.bind(this)\n this.boundPointerMove = this.onPointerMove.bind(this)\n this.boundPointerUp = this.onPointerUp.bind(this)\n this.boundClick = this.onClick.bind(this)\n this.boundTouchHandler = (e: TouchEvent) => { e.stopPropagation() }\n\n this.container.addEventListener('pointerdown', this.boundPointerDown)\n this.container.addEventListener('pointermove', this.boundPointerMove)\n this.container.addEventListener('pointerup', this.boundPointerUp)\n this.container.addEventListener('pointercancel', this.boundPointerUp)\n this.container.addEventListener('click', this.boundClick)\n this.container.addEventListener('touchstart', this.boundTouchHandler, { passive: true })\n this.container.addEventListener('touchmove', this.boundTouchHandler, { passive: true })\n }\n\n updateRect(rect: Rect): void {\n this.boundingRect = rect\n }\n\n private onPointerDown(e: PointerEvent): void {\n e.preventDefault()\n e.stopPropagation()\n this.interacting = true\n this.activePointerId = e.pointerId\n this.container.setPointerCapture(e.pointerId)\n\n const rect = this.container.getBoundingClientRect()\n this.boundingRect = { left: rect.left, top: rect.top, width: rect.width, height: rect.height }\n this.interactionOrigin = { x: e.clientX, y: e.clientY }\n this.doInteract(e.clientX, e.clientY)\n }\n\n private onPointerMove(e: PointerEvent): void {\n if (!this.interacting) return\n const now = performance.now()\n if (now - this.lastThrottleTime < THROTTLE_MS) return\n this.lastThrottleTime = now\n this.doInteract(e.clientX, e.clientY)\n }\n\n private onPointerUp(_e: PointerEvent): void {\n if (!this.interacting) return\n this.interacting = false\n if (this.activePointerId !== null) {\n try { this.container.releasePointerCapture(this.activePointerId) } catch {}\n this.activePointerId = null\n }\n this.endInteract()\n }\n\n private onClick(_e: MouseEvent): void {\n if (!this.flippable) return\n this.clickCount++\n if (this.dblClickTimer) clearTimeout(this.dblClickTimer)\n this.dblClickTimer = setTimeout(() => {\n if (this.clickCount >= 2) {\n this.flip()\n }\n this.clickCount = 0\n }, DBLCLICK_MS)\n }\n\n /**\n * Core interaction math — faithfully ported from Angular move.service.ts doInteract()\n */\n private doInteract(clientX: number, clientY: number): void {\n const rect = this.boundingRect\n if (rect.width === 0 || rect.height === 0) return\n\n const deltaX = clientX - this.interactionOrigin.x\n const deltaY = clientY - this.interactionOrigin.y\n\n // touchPosFromLT: absolute position within card (for glare)\n const touchPosFromLT = {\n x: clientX - rect.left,\n y: clientY - rect.top,\n }\n const touchPercentFromLT = {\n x: clamp(round((100 / rect.width) * touchPosFromLT.x)),\n y: clamp(round((100 / rect.height) * touchPosFromLT.y)),\n }\n\n // touchPosFromCenter: delta-based center offset (for rotation)\n const touchPosFromCenter = {\n x: rect.width / 2 + deltaX,\n y: rect.height / 2 + deltaY,\n }\n const touchPercentFromCenter = {\n x: clamp(round((100 / rect.width) * touchPosFromCenter.x)),\n y: clamp(round((100 / rect.height) * touchPosFromCenter.y)),\n }\n const touchPercentBasedCenter = {\n x: touchPercentFromCenter.x - 50,\n y: touchPercentFromCenter.y - 50,\n }\n\n // moveDelta: raw pixel delta (no DPR)\n this.callbacks.onMoveDelta({ x: deltaX, y: deltaY })\n\n // mousePos: absolute position in card, DPR-scaled, Y-flipped for WebGL\n const dpr = window.devicePixelRatio || 1\n this.callbacks.onMousePos({\n x: (clientX - rect.left) * dpr,\n y: (rect.height - (clientY - rect.top)) * dpr,\n })\n\n // Rotation: basedCenter / divisor\n const rotate = {\n x: round(touchPercentBasedCenter.x / 3.5),\n y: round(touchPercentBasedCenter.y / 2),\n }\n\n // Glare: absolute percentage from left-top\n const glare = {\n x: round(touchPercentFromLT.x),\n y: round(touchPercentFromLT.y),\n o: 1 as number,\n }\n\n this.updateSprings(glare, rotate)\n }\n\n /**\n * Apply spring targets with flip-aware rotation sign.\n * Angular: { x: flipped ? 180 - rotate.x : -rotate.x, y: flipped ? -rotate.y : rotate.y }\n */\n private updateSprings(\n glare: { x: number; y: number; o: number },\n rotate: { x: number; y: number },\n ): void {\n this.springGlare.stiffness = SPRING_INTERACT.stiffness\n this.springGlare.damping = SPRING_INTERACT.damping\n this.springGlare.set(glare)\n\n this.springRotate.stiffness = SPRING_INTERACT.stiffness\n this.springRotate.damping = SPRING_INTERACT.damping\n this.springRotate.set({\n x: this.flipped ? 180 - rotate.x : -rotate.x,\n y: this.flipped ? -rotate.y : rotate.y,\n })\n }\n\n private endInteract(): void {\n this.springRotate.set({ x: this.flipped ? 180 : 0, y: 0 })\n this.springGlare.set({ x: 50, y: 50, o: 0 })\n this.callbacks.onMoveDelta({ x: 0, y: 0 })\n\n const rect = this.boundingRect\n const dpr = window.devicePixelRatio || 1\n this.callbacks.onMousePos({\n x: (rect.width / 2) * dpr,\n y: (rect.height / 2) * dpr,\n })\n }\n\n set flipSpeed(speed: number) {\n this._flipSpeed = speed\n }\n\n flip(flipped?: boolean): boolean {\n this.flipped = flipped ?? !this.flipped\n const targetX = this.flipped ? 180 : 0\n\n this.springRotate.stiffness = SPRING_FLIP.stiffness * this._flipSpeed\n this.springRotate.damping = SPRING_FLIP.damping\n this.springRotate.set({ x: targetX, y: 0 }).then(() => {\n this.springRotate.stiffness = SPRING_INTERACT.stiffness\n this.springRotate.damping = SPRING_INTERACT.damping\n })\n\n this.callbacks.onFlip(this.flipped)\n return this.flipped\n }\n\n /**\n * Wiggle support: start a synthetic interaction.\n * Matches Angular: startInteraction(0, 0, false)\n * Sets origin at (0,0) so wiggle coordinates become deltas directly.\n */\n startSyntheticInteraction(): void {\n const rect = this.container.getBoundingClientRect()\n this.boundingRect = { left: rect.left, top: rect.top, width: rect.width, height: rect.height }\n this.interactionOrigin = { x: 0, y: 0 }\n }\n\n /**\n * Feed raw clientX/Y directly to doInteract.\n * Used by wiggle where coordinates come from DefaultWiggler(0,0,100).\n */\n simulateInteractRaw(clientX: number, clientY: number): void {\n this.doInteract(clientX, clientY)\n }\n\n simulateEndInteract(): void {\n this.endInteract()\n }\n\n isFlipped(): boolean {\n return this.flipped\n }\n\n destroy(): void {\n if (this.activePointerId !== null) {\n try { this.container.releasePointerCapture(this.activePointerId) } catch {}\n }\n this.container.removeEventListener('pointerdown', this.boundPointerDown)\n this.container.removeEventListener('pointermove', this.boundPointerMove)\n this.container.removeEventListener('pointerup', this.boundPointerUp)\n this.container.removeEventListener('pointercancel', this.boundPointerUp)\n this.container.removeEventListener('click', this.boundClick)\n this.container.removeEventListener('touchstart', this.boundTouchHandler)\n this.container.removeEventListener('touchmove', this.boundTouchHandler)\n if (this.dblClickTimer) clearTimeout(this.dblClickTimer)\n }\n}\n","export type EasingFn = (t: number) => number\n\nexport const easeOut: EasingFn = (t) => 1 - (1 - t) ** 3\nexport const easeInOut: EasingFn = (t) =>\n t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2\nexport const easeIn: EasingFn = (t) => t * t * t\n\nexport interface TweenOpts {\n from: number\n to: number\n duration: number\n easing: EasingFn\n onUpdate: (value: number) => void\n}\n\nexport function tween(opts: TweenOpts): Promise<void> & { cancel: () => void } {\n let cancelled = false\n let rafId: number | null = null\n\n const promise = new Promise<void>((resolve) => {\n const start = performance.now()\n const range = opts.to - opts.from\n\n function tick(now: number) {\n if (cancelled) { resolve(); return }\n const elapsed = now - start\n const t = Math.min(elapsed / opts.duration, 1)\n const value = opts.from + range * opts.easing(t)\n opts.onUpdate(value)\n\n if (t < 1) {\n rafId = requestAnimationFrame(tick)\n } else {\n resolve()\n }\n }\n rafId = requestAnimationFrame(tick)\n })\n\n return Object.assign(promise, {\n cancel() {\n cancelled = true\n if (rafId !== null) cancelAnimationFrame(rafId)\n },\n })\n}\n","import { tween, easeOut, easeInOut, easeIn } from './tween'\n\nexport interface WiggleController {\n stop(): void\n}\n\nexport function wiggle(\n cx: number,\n cy: number,\n radius: number,\n onUpdate: (pos: { x: number; y: number }, done: boolean) => void,\n): WiggleController {\n let stopped = false\n const cancellers: (() => void)[] = []\n\n async function run() {\n let currentRadius = 0\n let theta = 0\n\n // Phase 1: Expand (0.5s)\n const expand = tween({\n from: 0, to: radius,\n duration: 500, easing: easeOut,\n onUpdate: (r) => {\n if (stopped) return\n currentRadius = r\n onUpdate({ x: cx + r, y: cy }, false)\n },\n })\n cancellers.push(expand.cancel)\n await expand\n if (stopped) return\n\n // Phase 2: Rotate (0.5s, 0 → π)\n const rotate = tween({\n from: 0, to: Math.PI,\n duration: 500, easing: easeInOut,\n onUpdate: (t) => {\n if (stopped) return\n theta = t\n onUpdate({\n x: cx + currentRadius * Math.cos(theta),\n y: cy + currentRadius * Math.sin(theta),\n }, false)\n },\n })\n cancellers.push(rotate.cancel)\n await rotate\n if (stopped) return\n\n // Phase 3: Shrink (0.3s)\n const shrink = tween({\n from: currentRadius, to: 0,\n duration: 300, easing: easeIn,\n onUpdate: (r) => {\n if (stopped) return\n currentRadius = r\n onUpdate({ x: cx + r * Math.cos(theta), y: cy }, false)\n },\n })\n cancellers.push(shrink.cancel)\n await shrink\n\n if (!stopped) {\n onUpdate({ x: cx, y: cy }, true)\n }\n }\n\n run()\n\n return {\n stop() {\n stopped = true\n cancellers.forEach((c) => c())\n },\n }\n}\n","import { EventEmitter } from './event-emitter'\nimport { Renderer, type RendererOptions } from './renderer'\nimport { InteractionHandler } from './interaction'\nimport { wiggle, type WiggleController } from './animation/wiggle'\nexport interface PocaCardOptions {\n type: string\n baseImage: string\n popupImage?: string\n maskImage?: string\n backImage?: string\n flippable?: boolean\n initialFlipped?: boolean\n flipSpeed?: number\n customShader?: string\n}\n\nexport class PocaCard extends EventEmitter {\n private renderer: Renderer\n private interaction: InteractionHandler\n private wiggleController: WiggleController | null = null\n\n constructor(container: HTMLElement, options: PocaCardOptions) {\n super()\n\n this.renderer = new Renderer(\n container,\n {\n type: options.type,\n baseImage: options.baseImage,\n popupImage: options.popupImage,\n maskImage: options.maskImage,\n backImage: options.backImage,\n customShader: options.customShader,\n },\n (error) => this.emit('error', error),\n () => this.emit('ready'),\n )\n\n // Bind pointer events on the rotator element (inside the perspective container)\n this.interaction = new InteractionHandler(\n this.renderer.getRotatorEl(),\n {\n onRotate: (rotate) => this.renderer.updateUniforms({ rotate }),\n onGlare: () => {},\n onMousePos: (pos) => this.renderer.updateUniforms({ mouse: pos }),\n onMoveDelta: (delta) => this.renderer.updateUniforms({ move: delta }),\n onDistFromCenter: (_dist) => {\n // Could be used for opacity or other effects in the future\n },\n onFlip: (flipped) => this.emit('flip', flipped),\n },\n options.flippable ?? false,\n options.initialFlipped ?? false,\n )\n\n if (options.flipSpeed != null) {\n this.interaction.flipSpeed = options.flipSpeed\n }\n }\n\n getFrontContentEl(): HTMLDivElement {\n return this.renderer.getFrontContentEl()\n }\n\n getBackContentEl(): HTMLDivElement {\n return this.renderer.getBackContentEl()\n }\n\n flip(): void {\n this.interaction.flip()\n }\n\n wiggle(): void {\n this.wiggleController?.stop()\n\n // Match Angular: startInteraction(0,0,false) then feed raw pixel coords\n // DefaultWiggler(0, 0, 100) — center at origin, radius 100px\n this.interaction.startSyntheticInteraction()\n\n this.wiggleController = wiggle(0, 0, 100, (pos, done) => {\n if (done) {\n this.interaction.simulateEndInteract()\n this.wiggleController = null\n } else {\n // Feed wiggle position directly as clientX/Y (origin is 0,0)\n this.interaction.simulateInteractRaw(pos.x, pos.y)\n }\n })\n }\n\n reset(): void {\n this.wiggleController?.stop()\n this.wiggleController = null\n this.interaction.simulateEndInteract()\n }\n\n updateOptions(options: Partial<PocaCardOptions>): void {\n if (options.flipSpeed != null) {\n this.interaction.flipSpeed = options.flipSpeed\n }\n if (options.customShader) {\n this.renderer.updateShader(options.customShader)\n }\n if (options.baseImage || options.popupImage || options.maskImage) {\n this.renderer.updateTextures(options)\n }\n }\n\n destroy(): void {\n this.wiggleController?.stop()\n this.interaction.destroy()\n this.renderer.destroy()\n this.removeAllListeners()\n }\n}\n"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAf,IAAO,qBAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAf,IAAO,wBAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAf,IAAO,oBAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAf,IAAO,uBAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAf,IAAO,oBAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAf,IAAO,uBAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AzCYf,IAAM,eAAuC;AAAA,EAC3C,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,WAAW;AACb;AAWO,IAAM,WAAN,MAAe;AAAA,EAkBpB,YACU,WACA,SACA,SACA,SACR;AAJQ;AACA;AACA;AACA;AArBV,SAAQ,QAA4B;AACpC,SAAQ,SAA8B;AACtC,SAAQ,gBAA4C;AACpD,SAAQ,WAAwC;AAChD,SAAQ,OAA0B;AAClC,SAAQ,QAAQ,IAAU,aAAM;AAChC,SAAQ,QAAuB;AAC/B,SAAQ,WAA4B,CAAC;AAQrC,SAAQ,iBAAwC;AAQ9C,SAAK,aAAa;AAKlB,SAAK,SAAS,SAAS,cAAc,KAAK;AAC1C,SAAK,OAAO,YAAY;AAExB,SAAK,YAAY,SAAS,cAAc,KAAK;AAC7C,SAAK,UAAU,YAAY;AAG3B,SAAK,SAAS,SAAS,cAAc,KAAK;AAC1C,SAAK,OAAO,YAAY;AACxB,QAAI,QAAQ,WAAW;AACrB,YAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,cAAQ,MAAM,QAAQ;AACtB,cAAQ,YAAY;AACpB,WAAK,OAAO,YAAY,OAAO;AAAA,IACjC;AAGA,SAAK,UAAU,SAAS,cAAc,KAAK;AAC3C,SAAK,QAAQ,YAAY;AAEzB,SAAK,SAAS,SAAS,cAAc,QAAQ;AAC7C,SAAK,OAAO,YAAY;AAGxB,SAAK,iBAAiB,SAAS,cAAc,KAAK;AAClD,SAAK,eAAe,YAAY;AAEhC,SAAK,gBAAgB,SAAS,cAAc,KAAK;AACjD,SAAK,cAAc,YAAY;AAE/B,SAAK,QAAQ,YAAY,KAAK,MAAM;AACpC,SAAK,QAAQ,YAAY,KAAK,cAAc;AAC5C,SAAK,OAAO,YAAY,KAAK,aAAa;AAE1C,SAAK,UAAU,YAAY,KAAK,MAAM;AACtC,SAAK,UAAU,YAAY,KAAK,OAAO;AACvC,SAAK,OAAO,YAAY,KAAK,SAAS;AACtC,SAAK,UAAU,YAAY,KAAK,MAAM;AAEtC,qBAAiB;AACjB,SAAK,KAAK;AAAA,EACZ;AAAA,EAEQ,eAAqB;AAC3B,UAAM,KAAK;AACX,QAAI,SAAS,eAAe,EAAE,EAAG;AAEjC,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,KAAK;AACX,UAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2EpB,aAAS,KAAK,YAAY,KAAK;AAAA,EACjC;AAAA,EAEQ,OAAa;AACnB,UAAM,EAAE,OAAO,OAAO,IAAI,KAAK,UAAU,sBAAsB;AAE/D,SAAK,QAAQ,IAAU,aAAM;AAC7B,SAAK,SAAS,IAAU,cAAO;AAE/B,SAAK,gBAAgB,IAAU,qBAAc;AAAA,MAC3C,QAAQ,KAAK;AAAA,MACb,OAAO;AAAA,IACT,CAAC;AACD,SAAK,cAAc,cAAc,OAAO,gBAAgB;AACxD,SAAK,cAAc,QAAQ,OAAO,MAAM;AAIxC,UAAM,aAAa,KAAK,OAAO;AAC/B,UAAM,cAAc,KAAK,OAAO;AAChC,UAAM,WAAW,KAAK,eAAe,YAAY,WAAW;AAE5D,UAAM,oBAAoB,KAAK,QAAQ,gBAClC,aAAa,KAAK,QAAQ,IAAI;AAEnC,UAAM,iBAAiB,gBAAgB,iBAAiB;AAExD,SAAK,WAAW,IAAU,sBAAe;AAAA,MACvC,cAAc,gBAAgB,mBAAY;AAAA,MAC1C;AAAA,MACA;AAAA,MACA,aAAa;AAAA,IACf,CAAC;AAED,UAAM,WAAW,IAAU,qBAAc,GAAG,CAAC;AAC7C,SAAK,OAAO,IAAU,YAAK,UAAU,KAAK,QAAQ;AAClD,SAAK,MAAM,IAAI,KAAK,IAAI;AAExB,SAAK,aAAa;AAClB,SAAK,oBAAoB;AACzB,SAAK,gBAAgB;AAGrB,0BAAsB,MAAM;AAC1B,WAAK,OAAO,UAAU,OAAO,gBAAgB;AAC7C,WAAK,OAAO,UAAU,IAAI,cAAc;AAAA,IAC1C,CAAC;AAAA,EACH;AAAA,EAEQ,eAAe,OAAe,QAAgD;AACpF,WAAO;AAAA,MACL,OAAO,EAAE,OAAO,EAAE;AAAA,MAClB,aAAa,EAAE,OAAO,IAAU,eAAQ,OAAO,MAAM,EAAE;AAAA,MACvD,QAAQ,EAAE,OAAO,IAAU,eAAQ,GAAG,CAAC,EAAE;AAAA,MACzC,OAAO,EAAE,OAAO,IAAU,eAAQ,GAAG,CAAC,EAAE;AAAA,MACxC,SAAS,EAAE,OAAO,IAAU,eAAQ,GAAG,CAAC,EAAE;AAAA,MAC1C,cAAc,EAAE,OAAO,EAAI;AAAA,MAC3B,UAAU,EAAE,OAAO,KAAK;AAAA,MACxB,WAAW,EAAE,OAAO,KAAK;AAAA,MACzB,UAAU,EAAE,OAAO,KAAK;AAAA,IAC1B;AAAA,EACF;AAAA,EAEQ,eAAqB;AAC3B,UAAM,SAAS,IAAU,qBAAc;AACvC,UAAM,OAAO,CAAC,KAAyB,YAAoB;AACzD,UAAI,CAAC,IAAK;AACV,aAAO;AAAA,QACL;AAAA,QACA,CAAC,YAAY;AACX,eAAK,SAAS,KAAK,OAAO;AAC1B,cAAI,KAAK,UAAU;AACjB,iBAAK,SAAS,SAAS,OAAO,EAAE,QAAQ;AAAA,UAC1C;AAAA,QACF;AAAA,QACA;AAAA,QACA,MAAM;AACJ,eAAK,UAAU,IAAI,MAAM,2BAA2B,GAAG,EAAE,CAAC;AAAA,QAC5D;AAAA,MACF;AAAA,IACF;AAEA,SAAK,KAAK,QAAQ,WAAW,UAAU;AACvC,SAAK,KAAK,QAAQ,YAAY,WAAW;AACzC,SAAK,KAAK,QAAQ,WAAW,UAAU;AAEvC,SAAK,UAAU;AAAA,EACjB;AAAA,EAEQ,sBAA4B;AAClC,SAAK,iBAAiB,IAAI,eAAe,CAAC,YAAY;AACpD,YAAM,QAAQ,QAAQ,CAAC;AACvB,UAAI,CAAC,MAAO;AACZ,YAAM,EAAE,OAAO,OAAO,IAAI,MAAM;AAChC,UAAI,UAAU,KAAK,WAAW,EAAG;AAEjC,WAAK,eAAe,QAAQ,OAAO,MAAM;AAEzC,UAAI,KAAK,UAAU;AACjB,aAAK,SAAS,SAAS,YAAY,MAAM,IAAI,KAAK,OAAO,OAAO,KAAK,OAAO,MAAM;AAAA,MACpF;AAAA,IACF,CAAC;AACD,SAAK,eAAe,QAAQ,KAAK,SAAS;AAAA,EAC5C;AAAA,EAEQ,kBAAwB;AAC9B,UAAM,UAAU,MAAM;AACpB,WAAK,QAAQ,sBAAsB,OAAO;AAC1C,UAAI,CAAC,KAAK,YAAY,CAAC,KAAK,SAAS,CAAC,KAAK,UAAU,CAAC,KAAK,cAAe;AAE1E,YAAM,QAAQ,KAAK,MAAM,SAAS;AAClC,WAAK,SAAS,SAAS,MAAM,SAAS;AACtC,WAAK,cAAc,OAAO,KAAK,OAAO,KAAK,MAAM;AAAA,IACnD;AACA,SAAK,QAAQ,sBAAsB,OAAO;AAAA,EAC5C;AAAA,EAEA,eAAe,SAKN;AACP,QAAI,CAAC,KAAK,SAAU;AACpB,UAAM,IAAI,KAAK,SAAS;AACxB,QAAI,QAAQ,QAAQ;AAElB,WAAK,UAAU,MAAM,YAAY,qBAAqB,GAAG,QAAQ,OAAO,CAAC,KAAK;AAC9E,WAAK,UAAU,MAAM,YAAY,qBAAqB,GAAG,QAAQ,OAAO,CAAC,KAAK;AAE9E,QAAE,QAAQ,MAAM;AAAA,QACd,QAAQ,OAAO,KAAK,KAAK,KAAK;AAAA,QAC9B,QAAQ,OAAO,KAAK,KAAK,KAAK;AAAA,MAChC;AAAA,IACF;AACA,QAAI,QAAQ,MAAO,GAAE,OAAO,MAAM,IAAI,QAAQ,MAAM,GAAG,QAAQ,MAAM,CAAC;AACtE,QAAI,QAAQ,KAAM,GAAE,MAAM,MAAM,IAAI,QAAQ,KAAK,GAAG,QAAQ,KAAK,CAAC;AAClE,QAAI,QAAQ,YAAY,OAAW,GAAE,aAAa,QAAQ,QAAQ;AAAA,EACpE;AAAA,EAEA,aAAa,gBAA8B;AACzC,QAAI,CAAC,KAAK,SAAU;AACpB,SAAK,SAAS,iBAAiB,gBAAgB,cAAc;AAC7D,SAAK,SAAS,cAAc;AAAA,EAC9B;AAAA,EAEA,eAAe,SAAyC;AACtD,UAAM,SAAS,IAAU,qBAAc;AACvC,UAAM,OAAO,CAAC,KAAyB,YAAoB;AACzD,UAAI,CAAC,IAAK;AACV,aAAO,KAAK,KAAK,CAAC,YAAY;AAC5B,aAAK,SAAS,KAAK,OAAO;AAC1B,YAAI,KAAK,UAAU;AACjB,eAAK,SAAS,SAAS,OAAO,EAAE,QAAQ;AAAA,QAC1C;AAAA,MACF,CAAC;AAAA,IACH;AACA,QAAI,QAAQ,UAAW,MAAK,QAAQ,WAAW,UAAU;AACzD,QAAI,QAAQ,WAAY,MAAK,QAAQ,YAAY,WAAW;AAC5D,QAAI,QAAQ,UAAW,MAAK,QAAQ,WAAW,UAAU;AAAA,EAC3D;AAAA,EAEA,mBAA4B;AAC1B,WAAO,KAAK,UAAU,sBAAsB;AAAA,EAC9C;AAAA,EAEA,eAA+B;AAC7B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,oBAAoC;AAClC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,mBAAmC;AACjC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,UAAU,KAAM,sBAAqB,KAAK,KAAK;AACxD,SAAK,gBAAgB,WAAW;AAChC,SAAK,SAAS,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;AACxC,SAAK,MAAM,SAAS,QAAQ;AAC5B,SAAK,UAAU,QAAQ;AACvB,SAAK,eAAe,QAAQ;AAC5B,QAAI,KAAK,OAAO,YAAY;AAC1B,WAAK,OAAO,WAAW,YAAY,KAAK,MAAM;AAAA,IAChD;AACA,SAAK,QAAQ;AACb,SAAK,SAAS;AACd,SAAK,gBAAgB;AACrB,SAAK,WAAW;AAChB,SAAK,OAAO;AAAA,EACd;AACF;;;A0C3WA,IAAM,QAA4B,oBAAI,IAAI;AAC1C,IAAI,QAAuB;AAE3B,SAAS,UAAU;AACjB,MAAI,MAAM,SAAS,GAAG;AACpB,YAAQ;AACR;AAAA,EACF;AACA,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,KAAK,GAAG;AACX,YAAM,OAAO,IAAI;AAAA,IACnB;AAAA,EACF;AACA,UAAQ,sBAAsB,OAAO;AACvC;AAEA,SAAS,aAAa,MAAqB;AACzC,QAAM,IAAI,IAAI;AACd,MAAI,UAAU,MAAM;AAClB,YAAQ,sBAAsB,OAAO;AAAA,EACvC;AACF;AAEA,SAAS,WACP,KACA,WACA,SACA,WACS;AACT,QAAM,QAAQ,IAAI,SAAS,IAAI;AAC/B,QAAM,WAAW,IAAI,MAAM,IAAI;AAC/B,QAAM,cAAc,YAAY;AAChC,QAAM,cAAc,UAAU;AAC9B,QAAM,gBAAgB,cAAc,eAAe,IAAI;AACvD,QAAM,IAAI,WAAW;AAErB,MAAI,KAAK,IAAI,CAAC,IAAI,aAAa,KAAK,IAAI,KAAK,IAAI,WAAW;AAC1D,QAAI,MAAM,IAAI;AACd,QAAI,UAAU,IAAI;AAClB,WAAO;AAAA,EACT;AAEA,MAAI,UAAU,IAAI;AAClB,MAAI,OAAO;AACX,SAAO;AACT;AAEO,SAAS,OACd,cACA,UACA,OAAmB,CAAC,GACJ;AAChB,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,UAAU,KAAK,WAAW;AAChC,QAAM,YAAY,KAAK,aAAa;AAEpC,QAAM,MAAM;AAAA,IACV,KAAK;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS;AAAA,EACX;AACA,MAAI,iBAAsC;AAE1C,QAAM,IAAoB;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM;AACJ,aAAO,IAAI;AAAA,IACb;AAAA,IACA,IAAI,OAAe,YAA+B;AAChD,UAAI,SAAS;AAEb,UAAI,YAAY,MAAM;AACpB,YAAI,MAAM;AACV,YAAI,UAAU;AACd,iBAAS,KAAK;AACd,eAAO,QAAQ,QAAQ;AAAA,MACzB;AAEA,UAAI,YAAY,MAAM;AACpB,cAAM,OAAO,OAAO,WAAW,SAAS,WAAW,WAAW,OAAO;AACrE,YAAI,UAAU,KAAK,IAAI,IAAI,SAAS,IAAI;AAAA,MAC1C;AAEA,aAAO,IAAI,QAAc,CAAC,YAAY;AACpC,yBAAiB;AACjB,qBAAa,MAAM;AACjB,gBAAM,gBAAgB;AACtB,cAAI,UAAU,KAAK,IAAI,IAAI,UAAU,MAAM,aAAa;AAExD,gBAAM,SAAS,WAAW,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS;AAClE,mBAAS,IAAI,GAAG;AAEhB,cAAI,CAAC,QAAQ;AACX,6BAAiB;AACjB,6BAAiB;AAAA,UACnB;AACA,iBAAO;AAAA,QACT,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAIO,SAAS,WACd,SACA,UACA,OAAmB,CAAC,GACc;AAClC,QAAM,QAAQ,EAAE,GAAG,QAAQ,GAAG,GAAG,QAAQ,EAAE;AAC3C,MAAI,QAAQ;AAEZ,QAAM,QAAQ,MAAM;AAClB,QAAI,OAAO;AACT,cAAQ;AACR,eAAS,EAAE,GAAG,MAAM,CAAC;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,KAAK,OAAO,QAAQ,GAAG,CAAC,MAAM;AAClC,UAAM,IAAI;AACV,YAAQ;AAER,mBAAe,KAAK;AAAA,EACtB,GAAG,IAAI;AAEP,QAAM,KAAK,OAAO,QAAQ,GAAG,CAAC,MAAM;AAClC,UAAM,IAAI;AACV,YAAQ;AACR,mBAAe,KAAK;AAAA,EACtB,GAAG,IAAI;AAEP,SAAO;AAAA,IACL,IAAI,YAAY;AAAE,aAAO,GAAG;AAAA,IAAU;AAAA,IACtC,IAAI,UAAU,GAAG;AAAE,SAAG,YAAY;AAAG,SAAG,YAAY;AAAA,IAAE;AAAA,IACtD,IAAI,UAAU;AAAE,aAAO,GAAG;AAAA,IAAQ;AAAA,IAClC,IAAI,QAAQ,GAAG;AAAE,SAAG,UAAU;AAAG,SAAG,UAAU;AAAA,IAAE;AAAA,IAChD,IAAI,YAAY;AAAE,aAAO,GAAG;AAAA,IAAU;AAAA,IACtC,IAAI,UAAU,GAAG;AAAE,SAAG,YAAY;AAAG,SAAG,YAAY;AAAA,IAAE;AAAA,IACtD,MAAM;AACJ,aAAO,EAAE,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,EAAE;AAAA,IACpC;AAAA,IACA,MAAM,IAAI,OAAO,YAAY;AAC3B,YAAM,QAAQ,IAAI;AAAA,QAChB,GAAG,IAAI,MAAM,GAAG,UAAU;AAAA,QAC1B,GAAG,IAAI,MAAM,GAAG,UAAU;AAAA,MAC5B,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAGO,SAAS,WACd,SACA,UACA,OAAmB,CAAC,GACyB;AAC7C,QAAM,QAAQ,EAAE,GAAG,QAAQ,GAAG,GAAG,QAAQ,GAAG,GAAG,QAAQ,EAAE;AACzD,MAAI,QAAQ;AAEZ,QAAM,QAAQ,MAAM;AAClB,QAAI,OAAO;AACT,cAAQ;AACR,eAAS,EAAE,GAAG,MAAM,CAAC;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,KAAK,OAAO,QAAQ,GAAG,CAAC,MAAM;AAClC,UAAM,IAAI;AACV,YAAQ;AACR,mBAAe,KAAK;AAAA,EACtB,GAAG,IAAI;AAEP,QAAM,KAAK,OAAO,QAAQ,GAAG,CAAC,MAAM;AAClC,UAAM,IAAI;AACV,YAAQ;AACR,mBAAe,KAAK;AAAA,EACtB,GAAG,IAAI;AAEP,QAAM,KAAK,OAAO,QAAQ,GAAG,CAAC,MAAM;AAClC,UAAM,IAAI;AACV,YAAQ;AACR,mBAAe,KAAK;AAAA,EACtB,GAAG,IAAI;AAEP,SAAO;AAAA,IACL,IAAI,YAAY;AAAE,aAAO,GAAG;AAAA,IAAU;AAAA,IACtC,IAAI,UAAU,GAAG;AAAE,SAAG,YAAY;AAAG,SAAG,YAAY;AAAG,SAAG,YAAY;AAAA,IAAE;AAAA,IACxE,IAAI,UAAU;AAAE,aAAO,GAAG;AAAA,IAAQ;AAAA,IAClC,IAAI,QAAQ,GAAG;AAAE,SAAG,UAAU;AAAG,SAAG,UAAU;AAAG,SAAG,UAAU;AAAA,IAAE;AAAA,IAChE,IAAI,YAAY;AAAE,aAAO,GAAG;AAAA,IAAU;AAAA,IACtC,IAAI,UAAU,GAAG;AAAE,SAAG,YAAY;AAAG,SAAG,YAAY;AAAG,SAAG,YAAY;AAAA,IAAE;AAAA,IACxE,MAAM;AACJ,aAAO,EAAE,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,EAAE;AAAA,IACjD;AAAA,IACA,MAAM,IAAI,OAAO,YAAY;AAC3B,YAAM,QAAQ,IAAI;AAAA,QAChB,GAAG,IAAI,MAAM,GAAG,UAAU;AAAA,QAC1B,GAAG,IAAI,MAAM,GAAG,UAAU;AAAA,QAC1B,GAAG,IAAI,MAAM,GAAG,UAAU;AAAA,MAC5B,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ACrOO,IAAM,QAAQ,CAAC,OAAe,YAAY,MAC/C,WAAW,MAAM,QAAQ,SAAS,CAAC;AAE9B,IAAM,QAAQ,CAAC,OAAe,MAAM,GAAG,MAAM,QAClD,KAAK,IAAI,KAAK,IAAI,OAAO,GAAG,GAAG,GAAG;AAW7B,IAAM,WAAW,CAAC,IAAY,IAAY,IAAY,OAC3D,KAAK,MAAM,KAAK,OAAO,KAAK,KAAK,OAAO,CAAC;;;ACG3C,IAAM,kBAAkB,EAAE,WAAW,OAAO,SAAS,IAAI;AACzD,IAAM,cAAc,EAAE,WAAW,MAAM,SAAS,KAAK;AACrD,IAAM,cAAc,MAAO;AAC3B,IAAM,cAAc;AAEb,IAAM,qBAAN,MAAyB;AAAA,EAsB9B,YACU,WACA,WACA,WACR,gBACA;AAJQ;AACA;AACA;AAxBV,SAAQ,UAAU;AAClB,SAAQ,cAAc;AACtB,SAAQ,eAAqB,EAAE,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,EAAE;AACpE,SAAQ,oBAAoB,EAAE,GAAG,GAAG,GAAG,EAAE;AAKzC,SAAQ,mBAAmB;AAC3B,SAAQ,aAAa;AACrB,SAAQ,gBAAsD;AAC9D,SAAQ,kBAAiC;AAQzC,SAAQ,aAAa;AAQnB,SAAK,UAAU;AAIf,SAAK,eAAe,WAAW,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,CAAC,MAAM;AACpD,gBAAU,SAAS,CAAC;AACpB,gBAAU,iBAAiB,MAAM,SAAS,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC;AAAA,IACvE,GAAG,eAAe;AAElB,SAAK,cAAc,WAAW,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,EAAE,GAAG,CAAC,MAAM;AAC3D,gBAAU,QAAQ,CAAC;AAAA,IACrB,GAAG,eAAe;AAElB,SAAK,mBAAmB,KAAK,cAAc,KAAK,IAAI;AACpD,SAAK,mBAAmB,KAAK,cAAc,KAAK,IAAI;AACpD,SAAK,iBAAiB,KAAK,YAAY,KAAK,IAAI;AAChD,SAAK,aAAa,KAAK,QAAQ,KAAK,IAAI;AACxC,SAAK,oBAAoB,CAAC,MAAkB;AAAE,QAAE,gBAAgB;AAAA,IAAE;AAElE,SAAK,UAAU,iBAAiB,eAAe,KAAK,gBAAgB;AACpE,SAAK,UAAU,iBAAiB,eAAe,KAAK,gBAAgB;AACpE,SAAK,UAAU,iBAAiB,aAAa,KAAK,cAAc;AAChE,SAAK,UAAU,iBAAiB,iBAAiB,KAAK,cAAc;AACpE,SAAK,UAAU,iBAAiB,SAAS,KAAK,UAAU;AACxD,SAAK,UAAU,iBAAiB,cAAc,KAAK,mBAAmB,EAAE,SAAS,KAAK,CAAC;AACvF,SAAK,UAAU,iBAAiB,aAAa,KAAK,mBAAmB,EAAE,SAAS,KAAK,CAAC;AAAA,EACxF;AAAA,EAEA,WAAW,MAAkB;AAC3B,SAAK,eAAe;AAAA,EACtB;AAAA,EAEQ,cAAc,GAAuB;AAC3C,MAAE,eAAe;AACjB,MAAE,gBAAgB;AAClB,SAAK,cAAc;AACnB,SAAK,kBAAkB,EAAE;AACzB,SAAK,UAAU,kBAAkB,EAAE,SAAS;AAE5C,UAAM,OAAO,KAAK,UAAU,sBAAsB;AAClD,SAAK,eAAe,EAAE,MAAM,KAAK,MAAM,KAAK,KAAK,KAAK,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO;AAC7F,SAAK,oBAAoB,EAAE,GAAG,EAAE,SAAS,GAAG,EAAE,QAAQ;AACtD,SAAK,WAAW,EAAE,SAAS,EAAE,OAAO;AAAA,EACtC;AAAA,EAEQ,cAAc,GAAuB;AAC3C,QAAI,CAAC,KAAK,YAAa;AACvB,UAAM,MAAM,YAAY,IAAI;AAC5B,QAAI,MAAM,KAAK,mBAAmB,YAAa;AAC/C,SAAK,mBAAmB;AACxB,SAAK,WAAW,EAAE,SAAS,EAAE,OAAO;AAAA,EACtC;AAAA,EAEQ,YAAY,IAAwB;AAC1C,QAAI,CAAC,KAAK,YAAa;AACvB,SAAK,cAAc;AACnB,QAAI,KAAK,oBAAoB,MAAM;AACjC,UAAI;AAAE,aAAK,UAAU,sBAAsB,KAAK,eAAe;AAAA,MAAE,QAAQ;AAAA,MAAC;AAC1E,WAAK,kBAAkB;AAAA,IACzB;AACA,SAAK,YAAY;AAAA,EACnB;AAAA,EAEQ,QAAQ,IAAsB;AACpC,QAAI,CAAC,KAAK,UAAW;AACrB,SAAK;AACL,QAAI,KAAK,cAAe,cAAa,KAAK,aAAa;AACvD,SAAK,gBAAgB,WAAW,MAAM;AACpC,UAAI,KAAK,cAAc,GAAG;AACxB,aAAK,KAAK;AAAA,MACZ;AACA,WAAK,aAAa;AAAA,IACpB,GAAG,WAAW;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKQ,WAAW,SAAiB,SAAuB;AACzD,UAAM,OAAO,KAAK;AAClB,QAAI,KAAK,UAAU,KAAK,KAAK,WAAW,EAAG;AAE3C,UAAM,SAAS,UAAU,KAAK,kBAAkB;AAChD,UAAM,SAAS,UAAU,KAAK,kBAAkB;AAGhD,UAAM,iBAAiB;AAAA,MACrB,GAAG,UAAU,KAAK;AAAA,MAClB,GAAG,UAAU,KAAK;AAAA,IACpB;AACA,UAAM,qBAAqB;AAAA,MACzB,GAAG,MAAM,MAAO,MAAM,KAAK,QAAS,eAAe,CAAC,CAAC;AAAA,MACrD,GAAG,MAAM,MAAO,MAAM,KAAK,SAAU,eAAe,CAAC,CAAC;AAAA,IACxD;AAGA,UAAM,qBAAqB;AAAA,MACzB,GAAG,KAAK,QAAQ,IAAI;AAAA,MACpB,GAAG,KAAK,SAAS,IAAI;AAAA,IACvB;AACA,UAAM,yBAAyB;AAAA,MAC7B,GAAG,MAAM,MAAO,MAAM,KAAK,QAAS,mBAAmB,CAAC,CAAC;AAAA,MACzD,GAAG,MAAM,MAAO,MAAM,KAAK,SAAU,mBAAmB,CAAC,CAAC;AAAA,IAC5D;AACA,UAAM,0BAA0B;AAAA,MAC9B,GAAG,uBAAuB,IAAI;AAAA,MAC9B,GAAG,uBAAuB,IAAI;AAAA,IAChC;AAGA,SAAK,UAAU,YAAY,EAAE,GAAG,QAAQ,GAAG,OAAO,CAAC;AAGnD,UAAM,MAAM,OAAO,oBAAoB;AACvC,SAAK,UAAU,WAAW;AAAA,MACxB,IAAI,UAAU,KAAK,QAAQ;AAAA,MAC3B,IAAI,KAAK,UAAU,UAAU,KAAK,QAAQ;AAAA,IAC5C,CAAC;AAGD,UAAM,SAAS;AAAA,MACb,GAAG,MAAM,wBAAwB,IAAI,GAAG;AAAA,MACxC,GAAG,MAAM,wBAAwB,IAAI,CAAC;AAAA,IACxC;AAGA,UAAM,QAAQ;AAAA,MACZ,GAAG,MAAM,mBAAmB,CAAC;AAAA,MAC7B,GAAG,MAAM,mBAAmB,CAAC;AAAA,MAC7B,GAAG;AAAA,IACL;AAEA,SAAK,cAAc,OAAO,MAAM;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,cACN,OACA,QACM;AACN,SAAK,YAAY,YAAY,gBAAgB;AAC7C,SAAK,YAAY,UAAU,gBAAgB;AAC3C,SAAK,YAAY,IAAI,KAAK;AAE1B,SAAK,aAAa,YAAY,gBAAgB;AAC9C,SAAK,aAAa,UAAU,gBAAgB;AAC5C,SAAK,aAAa,IAAI;AAAA,MACpB,GAAG,KAAK,UAAU,MAAM,OAAO,IAAI,CAAC,OAAO;AAAA,MAC3C,GAAG,KAAK,UAAU,CAAC,OAAO,IAAI,OAAO;AAAA,IACvC,CAAC;AAAA,EACH;AAAA,EAEQ,cAAoB;AAC1B,SAAK,aAAa,IAAI,EAAE,GAAG,KAAK,UAAU,MAAM,GAAG,GAAG,EAAE,CAAC;AACzD,SAAK,YAAY,IAAI,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;AAC3C,SAAK,UAAU,YAAY,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;AAEzC,UAAM,OAAO,KAAK;AAClB,UAAM,MAAM,OAAO,oBAAoB;AACvC,SAAK,UAAU,WAAW;AAAA,MACxB,GAAI,KAAK,QAAQ,IAAK;AAAA,MACtB,GAAI,KAAK,SAAS,IAAK;AAAA,IACzB,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,UAAU,OAAe;AAC3B,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,KAAK,SAA4B;AAC/B,SAAK,UAAU,WAAW,CAAC,KAAK;AAChC,UAAM,UAAU,KAAK,UAAU,MAAM;AAErC,SAAK,aAAa,YAAY,YAAY,YAAY,KAAK;AAC3D,SAAK,aAAa,UAAU,YAAY;AACxC,SAAK,aAAa,IAAI,EAAE,GAAG,SAAS,GAAG,EAAE,CAAC,EAAE,KAAK,MAAM;AACrD,WAAK,aAAa,YAAY,gBAAgB;AAC9C,WAAK,aAAa,UAAU,gBAAgB;AAAA,IAC9C,CAAC;AAED,SAAK,UAAU,OAAO,KAAK,OAAO;AAClC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,4BAAkC;AAChC,UAAM,OAAO,KAAK,UAAU,sBAAsB;AAClD,SAAK,eAAe,EAAE,MAAM,KAAK,MAAM,KAAK,KAAK,KAAK,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO;AAC7F,SAAK,oBAAoB,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB,SAAiB,SAAuB;AAC1D,SAAK,WAAW,SAAS,OAAO;AAAA,EAClC;AAAA,EAEA,sBAA4B;AAC1B,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,YAAqB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,oBAAoB,MAAM;AACjC,UAAI;AAAE,aAAK,UAAU,sBAAsB,KAAK,eAAe;AAAA,MAAE,QAAQ;AAAA,MAAC;AAAA,IAC5E;AACA,SAAK,UAAU,oBAAoB,eAAe,KAAK,gBAAgB;AACvE,SAAK,UAAU,oBAAoB,eAAe,KAAK,gBAAgB;AACvE,SAAK,UAAU,oBAAoB,aAAa,KAAK,cAAc;AACnE,SAAK,UAAU,oBAAoB,iBAAiB,KAAK,cAAc;AACvE,SAAK,UAAU,oBAAoB,SAAS,KAAK,UAAU;AAC3D,SAAK,UAAU,oBAAoB,cAAc,KAAK,iBAAiB;AACvE,SAAK,UAAU,oBAAoB,aAAa,KAAK,iBAAiB;AACtE,QAAI,KAAK,cAAe,cAAa,KAAK,aAAa;AAAA,EACzD;AACF;;;ACrRO,IAAM,UAAoB,CAAC,MAAM,KAAK,IAAI,MAAM;AAChD,IAAM,YAAsB,CAAC,MAClC,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,KAAK,KAAK,IAAI,MAAM,IAAI;AAC7C,IAAM,SAAmB,CAAC,MAAM,IAAI,IAAI;AAUxC,SAAS,MAAM,MAAyD;AAC7E,MAAI,YAAY;AAChB,MAAIC,SAAuB;AAE3B,QAAM,UAAU,IAAI,QAAc,CAAC,YAAY;AAC7C,UAAM,QAAQ,YAAY,IAAI;AAC9B,UAAM,QAAQ,KAAK,KAAK,KAAK;AAE7B,aAAS,KAAK,KAAa;AACzB,UAAI,WAAW;AAAE,gBAAQ;AAAG;AAAA,MAAO;AACnC,YAAM,UAAU,MAAM;AACtB,YAAM,IAAI,KAAK,IAAI,UAAU,KAAK,UAAU,CAAC;AAC7C,YAAM,QAAQ,KAAK,OAAO,QAAQ,KAAK,OAAO,CAAC;AAC/C,WAAK,SAAS,KAAK;AAEnB,UAAI,IAAI,GAAG;AACT,QAAAA,SAAQ,sBAAsB,IAAI;AAAA,MACpC,OAAO;AACL,gBAAQ;AAAA,MACV;AAAA,IACF;AACA,IAAAA,SAAQ,sBAAsB,IAAI;AAAA,EACpC,CAAC;AAED,SAAO,OAAO,OAAO,SAAS;AAAA,IAC5B,SAAS;AACP,kBAAY;AACZ,UAAIA,WAAU,KAAM,sBAAqBA,MAAK;AAAA,IAChD;AAAA,EACF,CAAC;AACH;;;ACvCO,SAAS,OACd,IACA,IACA,QACA,UACkB;AAClB,MAAI,UAAU;AACd,QAAM,aAA6B,CAAC;AAEpC,iBAAe,MAAM;AACnB,QAAI,gBAAgB;AACpB,QAAI,QAAQ;AAGZ,UAAM,SAAS,MAAM;AAAA,MACnB,MAAM;AAAA,MAAG,IAAI;AAAA,MACb,UAAU;AAAA,MAAK,QAAQ;AAAA,MACvB,UAAU,CAAC,MAAM;AACf,YAAI,QAAS;AACb,wBAAgB;AAChB,iBAAS,EAAE,GAAG,KAAK,GAAG,GAAG,GAAG,GAAG,KAAK;AAAA,MACtC;AAAA,IACF,CAAC;AACD,eAAW,KAAK,OAAO,MAAM;AAC7B,UAAM;AACN,QAAI,QAAS;AAGb,UAAM,SAAS,MAAM;AAAA,MACnB,MAAM;AAAA,MAAG,IAAI,KAAK;AAAA,MAClB,UAAU;AAAA,MAAK,QAAQ;AAAA,MACvB,UAAU,CAAC,MAAM;AACf,YAAI,QAAS;AACb,gBAAQ;AACR,iBAAS;AAAA,UACP,GAAG,KAAK,gBAAgB,KAAK,IAAI,KAAK;AAAA,UACtC,GAAG,KAAK,gBAAgB,KAAK,IAAI,KAAK;AAAA,QACxC,GAAG,KAAK;AAAA,MACV;AAAA,IACF,CAAC;AACD,eAAW,KAAK,OAAO,MAAM;AAC7B,UAAM;AACN,QAAI,QAAS;AAGb,UAAM,SAAS,MAAM;AAAA,MACnB,MAAM;AAAA,MAAe,IAAI;AAAA,MACzB,UAAU;AAAA,MAAK,QAAQ;AAAA,MACvB,UAAU,CAAC,MAAM;AACf,YAAI,QAAS;AACb,wBAAgB;AAChB,iBAAS,EAAE,GAAG,KAAK,IAAI,KAAK,IAAI,KAAK,GAAG,GAAG,GAAG,GAAG,KAAK;AAAA,MACxD;AAAA,IACF,CAAC;AACD,eAAW,KAAK,OAAO,MAAM;AAC7B,UAAM;AAEN,QAAI,CAAC,SAAS;AACZ,eAAS,EAAE,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI;AAAA,IACjC;AAAA,EACF;AAEA,MAAI;AAEJ,SAAO;AAAA,IACL,OAAO;AACL,gBAAU;AACV,iBAAW,QAAQ,CAAC,MAAM,EAAE,CAAC;AAAA,IAC/B;AAAA,EACF;AACF;;;AC5DO,IAAM,WAAN,cAAuB,aAAa;AAAA,EAKzC,YAAY,WAAwB,SAA0B;AAC5D,UAAM;AAHR,SAAQ,mBAA4C;AAKlD,SAAK,WAAW,IAAI;AAAA,MAClB;AAAA,MACA;AAAA,QACE,MAAM,QAAQ;AAAA,QACd,WAAW,QAAQ;AAAA,QACnB,YAAY,QAAQ;AAAA,QACpB,WAAW,QAAQ;AAAA,QACnB,WAAW,QAAQ;AAAA,QACnB,cAAc,QAAQ;AAAA,MACxB;AAAA,MACA,CAAC,UAAU,KAAK,KAAK,SAAS,KAAK;AAAA,MACnC,MAAM,KAAK,KAAK,OAAO;AAAA,IACzB;AAGA,SAAK,cAAc,IAAI;AAAA,MACrB,KAAK,SAAS,aAAa;AAAA,MAC3B;AAAA,QACE,UAAU,CAAC,WAAW,KAAK,SAAS,eAAe,EAAE,OAAO,CAAC;AAAA,QAC7D,SAAS,MAAM;AAAA,QAAC;AAAA,QAChB,YAAY,CAAC,QAAQ,KAAK,SAAS,eAAe,EAAE,OAAO,IAAI,CAAC;AAAA,QAChE,aAAa,CAAC,UAAU,KAAK,SAAS,eAAe,EAAE,MAAM,MAAM,CAAC;AAAA,QACpE,kBAAkB,CAAC,UAAU;AAAA,QAE7B;AAAA,QACA,QAAQ,CAAC,YAAY,KAAK,KAAK,QAAQ,OAAO;AAAA,MAChD;AAAA,MACA,QAAQ,aAAa;AAAA,MACrB,QAAQ,kBAAkB;AAAA,IAC5B;AAEA,QAAI,QAAQ,aAAa,MAAM;AAC7B,WAAK,YAAY,YAAY,QAAQ;AAAA,IACvC;AAAA,EACF;AAAA,EAEA,oBAAoC;AAClC,WAAO,KAAK,SAAS,kBAAkB;AAAA,EACzC;AAAA,EAEA,mBAAmC;AACjC,WAAO,KAAK,SAAS,iBAAiB;AAAA,EACxC;AAAA,EAEA,OAAa;AACX,SAAK,YAAY,KAAK;AAAA,EACxB;AAAA,EAEA,SAAe;AACb,SAAK,kBAAkB,KAAK;AAI5B,SAAK,YAAY,0BAA0B;AAE3C,SAAK,mBAAmB,OAAO,GAAG,GAAG,KAAK,CAAC,KAAK,SAAS;AACvD,UAAI,MAAM;AACR,aAAK,YAAY,oBAAoB;AACrC,aAAK,mBAAmB;AAAA,MAC1B,OAAO;AAEL,aAAK,YAAY,oBAAoB,IAAI,GAAG,IAAI,CAAC;AAAA,MACnD;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,QAAc;AACZ,SAAK,kBAAkB,KAAK;AAC5B,SAAK,mBAAmB;AACxB,SAAK,YAAY,oBAAoB;AAAA,EACvC;AAAA,EAEA,cAAc,SAAyC;AACrD,QAAI,QAAQ,aAAa,MAAM;AAC7B,WAAK,YAAY,YAAY,QAAQ;AAAA,IACvC;AACA,QAAI,QAAQ,cAAc;AACxB,WAAK,SAAS,aAAa,QAAQ,YAAY;AAAA,IACjD;AACA,QAAI,QAAQ,aAAa,QAAQ,cAAc,QAAQ,WAAW;AAChE,WAAK,SAAS,eAAe,OAAO;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,SAAK,kBAAkB,KAAK;AAC5B,SAAK,YAAY,QAAQ;AACzB,SAAK,SAAS,QAAQ;AACtB,SAAK,mBAAmB;AAAA,EAC1B;AACF;","names":["THREE","D_default","D_default","rafId"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sangwonl/pocato-core",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "author": "Sangwon Lee <gamzabaw@gmail.com>",
5
5
  "license": "MIT",
6
6
  "repository": {