shaders-oneshot 0.0.81-shared.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +5 -0
  3. package/README.md +7 -0
  4. package/dist/empty-pixel.d.ts +1 -0
  5. package/dist/empty-pixel.js +10 -0
  6. package/dist/empty-pixel.js.map +7 -0
  7. package/dist/get-shader-color-from-string.d.ts +3 -0
  8. package/dist/get-shader-color-from-string.js +101 -0
  9. package/dist/get-shader-color-from-string.js.map +7 -0
  10. package/dist/get-shader-color-from-string.test.d.ts +1 -0
  11. package/dist/get-shader-color-from-string.test.js +69 -0
  12. package/dist/get-shader-noise-texture.d.ts +1 -0
  13. package/dist/get-shader-noise-texture.js +18 -0
  14. package/dist/get-shader-noise-texture.js.map +7 -0
  15. package/dist/index.d.ts +68 -0
  16. package/dist/index.js +194 -0
  17. package/dist/index.js.map +7 -0
  18. package/dist/shader-color-spaces.d.ts +6 -0
  19. package/dist/shader-color-spaces.js +96 -0
  20. package/dist/shader-color-spaces.js.map +7 -0
  21. package/dist/shader-mount.d.ts +199 -0
  22. package/dist/shader-mount.js +735 -0
  23. package/dist/shader-mount.js.map +7 -0
  24. package/dist/shader-sizing.d.ts +30 -0
  25. package/dist/shader-sizing.js +38 -0
  26. package/dist/shader-sizing.js.map +7 -0
  27. package/dist/shader-utils.d.ts +10 -0
  28. package/dist/shader-utils.js +131 -0
  29. package/dist/shader-utils.js.map +7 -0
  30. package/dist/shaders/color-panels.d.ts +70 -0
  31. package/dist/shaders/color-panels.js +224 -0
  32. package/dist/shaders/color-panels.js.map +7 -0
  33. package/dist/shaders/dithering.d.ts +62 -0
  34. package/dist/shaders/dithering.js +271 -0
  35. package/dist/shaders/dithering.js.map +7 -0
  36. package/dist/shaders/dot-grid.d.ts +65 -0
  37. package/dist/shaders/dot-grid.js +110 -0
  38. package/dist/shaders/dot-grid.js.map +7 -0
  39. package/dist/shaders/dot-orbit.d.ts +57 -0
  40. package/dist/shaders/dot-orbit.js +123 -0
  41. package/dist/shaders/dot-orbit.js.map +7 -0
  42. package/dist/shaders/fluted-glass.d.ts +112 -0
  43. package/dist/shaders/fluted-glass.js +361 -0
  44. package/dist/shaders/fluted-glass.js.map +7 -0
  45. package/dist/shaders/gem-smoke.d.ts +96 -0
  46. package/dist/shaders/gem-smoke.js +573 -0
  47. package/dist/shaders/gem-smoke.js.map +7 -0
  48. package/dist/shaders/god-rays.d.ts +67 -0
  49. package/dist/shaders/god-rays.js +133 -0
  50. package/dist/shaders/god-rays.js.map +7 -0
  51. package/dist/shaders/grain-gradient.d.ts +80 -0
  52. package/dist/shaders/grain-gradient.js +301 -0
  53. package/dist/shaders/grain-gradient.js.map +7 -0
  54. package/dist/shaders/halftone-cmyk.d.ts +104 -0
  55. package/dist/shaders/halftone-cmyk.js +295 -0
  56. package/dist/shaders/halftone-cmyk.js.map +7 -0
  57. package/dist/shaders/halftone-dots.d.ts +80 -0
  58. package/dist/shaders/halftone-dots.js +321 -0
  59. package/dist/shaders/halftone-dots.js.map +7 -0
  60. package/dist/shaders/heatmap.d.ts +66 -0
  61. package/dist/shaders/heatmap.js +384 -0
  62. package/dist/shaders/heatmap.js.map +7 -0
  63. package/dist/shaders/image-dithering.d.ts +64 -0
  64. package/dist/shaders/image-dithering.js +199 -0
  65. package/dist/shaders/image-dithering.js.map +7 -0
  66. package/dist/shaders/lens-distortion.d.ts +97 -0
  67. package/dist/shaders/lens-distortion.js +276 -0
  68. package/dist/shaders/lens-distortion.js.map +7 -0
  69. package/dist/shaders/liquid-metal.d.ts +89 -0
  70. package/dist/shaders/liquid-metal.js +633 -0
  71. package/dist/shaders/liquid-metal.js.map +7 -0
  72. package/dist/shaders/mesh-gradient.d.ts +52 -0
  73. package/dist/shaders/mesh-gradient.js +131 -0
  74. package/dist/shaders/mesh-gradient.js.map +7 -0
  75. package/dist/shaders/metaballs.d.ts +51 -0
  76. package/dist/shaders/metaballs.js +111 -0
  77. package/dist/shaders/metaballs.js.map +7 -0
  78. package/dist/shaders/neuro-noise.d.ts +47 -0
  79. package/dist/shaders/neuro-noise.js +77 -0
  80. package/dist/shaders/neuro-noise.js.map +7 -0
  81. package/dist/shaders/paper-texture.d.ts +109 -0
  82. package/dist/shaders/paper-texture.js +527 -0
  83. package/dist/shaders/paper-texture.js.map +7 -0
  84. package/dist/shaders/perlin-noise.d.ts +52 -0
  85. package/dist/shaders/perlin-noise.js +167 -0
  86. package/dist/shaders/perlin-noise.js.map +7 -0
  87. package/dist/shaders/pulsing-border.d.ts +98 -0
  88. package/dist/shaders/pulsing-border.js +239 -0
  89. package/dist/shaders/pulsing-border.js.map +7 -0
  90. package/dist/shaders/simplex-noise.d.ts +45 -0
  91. package/dist/shaders/simplex-noise.js +92 -0
  92. package/dist/shaders/simplex-noise.js.map +7 -0
  93. package/dist/shaders/smoke-ring.d.ts +61 -0
  94. package/dist/shaders/smoke-ring.js +133 -0
  95. package/dist/shaders/smoke-ring.js.map +7 -0
  96. package/dist/shaders/spiral.d.ts +61 -0
  97. package/dist/shaders/spiral.js +83 -0
  98. package/dist/shaders/spiral.js.map +7 -0
  99. package/dist/shaders/static-mesh-gradient.d.ts +63 -0
  100. package/dist/shaders/static-mesh-gradient.js +131 -0
  101. package/dist/shaders/static-mesh-gradient.js.map +7 -0
  102. package/dist/shaders/static-radial-gradient.d.ts +72 -0
  103. package/dist/shaders/static-radial-gradient.js +188 -0
  104. package/dist/shaders/static-radial-gradient.js.map +7 -0
  105. package/dist/shaders/swirl.d.ts +63 -0
  106. package/dist/shaders/swirl.js +104 -0
  107. package/dist/shaders/swirl.js.map +7 -0
  108. package/dist/shaders/voronoi.d.ts +65 -0
  109. package/dist/shaders/voronoi.js +139 -0
  110. package/dist/shaders/voronoi.js.map +7 -0
  111. package/dist/shaders/warp.d.ts +70 -0
  112. package/dist/shaders/warp.js +130 -0
  113. package/dist/shaders/warp.js.map +7 -0
  114. package/dist/shaders/water.d.ts +59 -0
  115. package/dist/shaders/water.js +122 -0
  116. package/dist/shaders/water.js.map +7 -0
  117. package/dist/shaders/waves.d.ts +53 -0
  118. package/dist/shaders/waves.js +66 -0
  119. package/dist/shaders/waves.js.map +7 -0
  120. package/dist/shared-webgl-renderer.d.ts +63 -0
  121. package/dist/shared-webgl-renderer.js +262 -0
  122. package/dist/shared-webgl-renderer.js.map +7 -0
  123. package/dist/types.d.ts +3 -0
  124. package/dist/types.js +6 -0
  125. package/dist/types.js.map +7 -0
  126. package/dist/vertex-shader.d.ts +2 -0
  127. package/dist/vertex-shader.js +160 -0
  128. package/dist/vertex-shader.js.map +7 -0
  129. package/package.json +29 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/shader-mount.ts"],
4
+ "sourcesContent": ["// Modified from paper-design/shaders: shared WebGL context mode, context release on dispose, lost context replacement.\nimport { vertexShaderSource } from './vertex-shader.js';\nimport { SharedWebGLRenderer, type SharedRenderTarget, type SharedTargetSize } from './shared-webgl-renderer.js';\n\nconst DEFAULT_MAX_PIXEL_COUNT: number = 1920 * 1080 * 4;\n\n/** Uniform added to shaders that read gl_FragCoord, so they see local coordinates when drawn into the shared atlas */\nconst FRAG_COORD_OFFSET_UNIFORM = 'u_paperFragCoordOffset';\n\n/** At most this many context replacements per window for a dedicated context, so a mount never fights other page elements for contexts forever */\nconst MAX_CONTEXT_RECOVERIES = 3;\nconst CONTEXT_RECOVERY_WINDOW_MS = 30_000;\n\nexport class ShaderMount implements SharedRenderTarget {\n public parentElement: PaperShaderElement;\n public canvasElement: HTMLCanvasElement;\n private gl: WebGL2RenderingContext;\n /** Set when this mount draws through the context shared by all shared mounts, null when it owns a context */\n private sharedRenderer: SharedWebGLRenderer | null = null;\n /** The visible canvas's 2D context in shared mode, where each frame is copied to */\n private context2d: CanvasRenderingContext2D | null = null;\n private webGlContextAttributes: WebGLContextAttributes | undefined;\n private program: WebGLProgram | null = null;\n private vertexArray: WebGLVertexArrayObject | null = null;\n private positionBuffer: WebGLBuffer | null = null;\n private uniformLocations: Record<string, WebGLUniformLocation | null> = {};\n /** The fragment shader that we are using */\n private fragmentShader: string;\n /** Stores the RAF for the render loop */\n private rafId: number | null = null;\n /** Time of the last rendered frame */\n private lastRenderTime = 0;\n /** Total time that we have played any animation, passed as a uniform to the shader for time-based VFX */\n private currentFrame = 0;\n /** The speed that we progress through animation time (multiplies by delta time every update). Allows negatives to play in reverse. If set to 0, rAF will stop entirely so static shaders have no recurring performance costs */\n private speed = 0;\n /** Actual speed used that accounts for visibility: we pause the shader if the tab is hidden or the element out of the viewport */\n private currentSpeed = 0;\n /** Uniforms that are provided by the user for the specific shader being mounted (not including uniforms that this Mount adds, like time and resolution) */\n private providedUniforms: ShaderMountUniforms;\n /** Names of the uniforms that should have mipmaps generated for them */\n private mipmaps: string[] = [];\n /** Just a sanity check to make sure frames don't run after we're disposed */\n private hasBeenDisposed = false;\n /** If the resolution of the canvas has changed since the last render */\n private resolutionChanged = true;\n /** Store textures that are provided by the user */\n private textures: Map<string, WebGLTexture> = new Map();\n private minPixelRatio;\n private maxPixelCount;\n private isSafari = isSafari();\n private uniformCache: Record<string, unknown> = {};\n private textureUnitMap: Map<string, number> = new Map();\n private ownerDocument: Document;\n /** Shared mode: whether time is advancing from frame to frame, as opposed to one-off redraws */\n private sharedLoopActive = false;\n /** Shared mode: the canvas size to apply right before the next draw (resizing clears the canvas) */\n private pendingCanvasWidth: number | null = null;\n private pendingCanvasHeight: number | null = null;\n private contextRecoveries: number[] = [];\n /** Dedicated mode: the context was lost and a new one goes in once the mount is visible */\n private awaitingNewContext = false;\n\n constructor(\n /** The div you'd like to mount the shader to. The shader will match its size. */\n parentElement: HTMLElement,\n fragmentShader: string,\n uniforms: ShaderMountUniforms,\n webGlContextAttributes?: WebGLContextAttributes,\n /** The speed of the animation, or 0 to stop it. Supports negative values to play in reverse. */\n speed = 0,\n /** Pass a frame to offset the starting u_time value and give deterministic results*/\n frame = 0,\n /**\n * The minimum pixel ratio to render at, defaults to 2.\n * May be reduced to improve performance or increased together with `maxPixelCount` to improve antialiasing.\n */\n minPixelRatio = 2,\n /**\n * The maximum amount of physical device pixels to render for the shader,\n * by default it's 1920 * 1080 * 2x dpi (per each side) = 8,294,400 pixels of a 4K screen.\n * Actual DOM size of the canvas can be larger, it will just lose quality after this.\n *\n * May be reduced to improve performance or increased to improve quality on high-resolution screens.\n */\n maxPixelCount: number = DEFAULT_MAX_PIXEL_COUNT,\n /** Names of the uniforms that should have mipmaps generated for them */\n mipmaps: string[] = [],\n /**\n * \"shared\" (the default) draws through one WebGL context shared by every shared mount on the page, so any number\n * of shaders can run without hitting the browser's context limit. \"dedicated\" gives this mount its own context,\n * which suits a large, always visible shader like a full screen background. Defaults to \"dedicated\" when\n * `webGlContextAttributes` are passed, since a shared context can't honor per-mount attributes.\n */\n webGlContextMode?: WebGlContextMode\n ) {\n // nodeType check instead of `instanceof` to work across document boundaries (iframes, PiP windows)\n if (parentElement?.nodeType === 1) {\n this.parentElement = parentElement as PaperShaderElement;\n } else {\n throw new Error('Paper Shaders: parent element must be an HTMLElement');\n }\n\n this.ownerDocument = parentElement.ownerDocument;\n\n if (!this.ownerDocument.querySelector('style[data-paper-shader]')) {\n const styleElement = this.ownerDocument.createElement('style');\n styleElement.innerHTML = defaultStyle;\n styleElement.setAttribute('data-paper-shader', '');\n this.ownerDocument.head.prepend(styleElement);\n }\n\n // Create the canvas element and mount it into the provided element\n let canvasElement = this.ownerDocument.createElement('canvas');\n this.parentElement.prepend(canvasElement);\n this.fragmentShader = fragmentShader;\n this.providedUniforms = uniforms;\n this.mipmaps = mipmaps;\n this.webGlContextAttributes = webGlContextAttributes;\n // Base our starting animation time on the provided frame value\n this.currentFrame = frame;\n this.minPixelRatio = minPixelRatio;\n this.maxPixelCount = maxPixelCount;\n\n const contextMode = webGlContextMode ?? (webGlContextAttributes ? 'dedicated' : 'shared');\n const sharedRenderer = contextMode === 'shared' ? SharedWebGLRenderer.get() : null;\n const context2d = sharedRenderer ? canvasElement.getContext('2d') : null;\n\n if (sharedRenderer && context2d) {\n this.sharedRenderer = sharedRenderer;\n this.context2d = context2d;\n this.gl = sharedRenderer.gl;\n sharedRenderer.register(this);\n } else {\n // Falls back to a context of its own when the browser can't share one (no WebGL2 OffscreenCanvas)\n if (sharedRenderer) {\n // A canvas that handed out a 2D context can't hand out a WebGL one\n const freshCanvas = this.ownerDocument.createElement('canvas');\n canvasElement.replaceWith(freshCanvas);\n canvasElement = freshCanvas;\n }\n const gl = canvasElement.getContext('webgl2', webGlContextAttributes);\n if (!gl) {\n throw new Error('Paper Shaders: WebGL is not supported in this browser');\n }\n this.gl = gl;\n canvasElement.addEventListener('webglcontextlost', this.handleContextLost);\n }\n this.canvasElement = canvasElement;\n\n this.initGL();\n // Set up the resize observer to handle window resizing and set u_resolution\n this.setupResizeObserver();\n // Set up the visual viewport change listener to handle zoom changes (pinch zoom and classic browser zoom)\n visualViewport?.addEventListener('resize', this.handleVisualViewportChange);\n // Set up the intersection observer to pause animation when the element is scrolled out of view\n this.setupIntersectionObserver();\n\n // Set the animation speed after everything is ready to go\n this.setSpeed(speed);\n\n // Mark parent element as paper shader mount\n this.parentElement.setAttribute('data-paper-shader', '');\n\n // Add the shaderMount instance to the div mount element to make it easily accessible\n this.parentElement.paperShaderMount = this;\n\n // Listen for document visibility changes to pause the shader when the tab is hidden\n this.ownerDocument.addEventListener('visibilitychange', this.handleDocumentVisibilityChange);\n }\n\n /** Create every GL resource this mount owns on the current context. Also rebuilds them after a context is replaced */\n private initGL = () => {\n // Anything left over belongs to a previous (lost) context and can't be used or deleted anymore\n this.program = null;\n this.vertexArray = null;\n this.positionBuffer = null;\n this.uniformLocations = {};\n this.uniformCache = {};\n this.textures.clear();\n this.textureUnitMap.clear();\n this.resolutionChanged = true;\n\n if (this.gl.isContextLost()) return;\n\n this.initProgram();\n if (!this.program) return;\n this.setupPositionAttribute();\n // Grab the locations of the uniforms in the fragment shader\n this.setupUniforms();\n // Put the user provided values into the uniforms\n this.setUniformValues(this.providedUniforms);\n };\n\n private initProgram = () => {\n const program = createProgram(this.gl, vertexShaderSource, this.fragmentShader, this.sharedRenderer !== null);\n if (!program) return;\n this.program = program;\n };\n\n private setupPositionAttribute = () => {\n const positionAttributeLocation = this.gl.getAttribLocation(this.program!, 'a_position');\n // A vertex array per mount keeps this setup intact when several mounts draw through one shared context\n this.vertexArray = this.gl.createVertexArray();\n this.gl.bindVertexArray(this.vertexArray);\n this.positionBuffer = this.gl.createBuffer();\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionBuffer);\n const positions = [-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1];\n this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(positions), this.gl.STATIC_DRAW);\n this.gl.enableVertexAttribArray(positionAttributeLocation);\n this.gl.vertexAttribPointer(positionAttributeLocation, 2, this.gl.FLOAT, false, 0, 0);\n this.gl.bindVertexArray(null);\n };\n\n private setupUniforms = () => {\n // Create a map to store all uniform locations\n const uniformLocations: Record<string, WebGLUniformLocation | null> = {\n u_time: this.gl.getUniformLocation(this.program!, 'u_time'),\n u_pixelRatio: this.gl.getUniformLocation(this.program!, 'u_pixelRatio'),\n u_resolution: this.gl.getUniformLocation(this.program!, 'u_resolution'),\n [FRAG_COORD_OFFSET_UNIFORM]: this.gl.getUniformLocation(this.program!, FRAG_COORD_OFFSET_UNIFORM),\n };\n\n // Add locations for all provided uniforms\n Object.entries(this.providedUniforms).forEach(([key, value]) => {\n uniformLocations[key] = this.gl.getUniformLocation(this.program!, key);\n\n // For texture uniforms, also look for the aspect ratio uniform\n if (value instanceof HTMLImageElement) {\n const aspectRatioUniformName = `${key}AspectRatio`;\n uniformLocations[aspectRatioUniformName] = this.gl.getUniformLocation(this.program!, aspectRatioUniformName);\n }\n });\n\n this.uniformLocations = uniformLocations;\n };\n\n /**\n * The scale that we should render at.\n * - Used to target 2x rendering even on 1x screens for better antialiasing\n * - Prevents the virtual resolution from going beyond the maximum resolution\n * - Accounts for the page zoom level so we render in physical device pixels rather than CSS pixels\n */\n private renderScale = 1;\n private parentWidth = 0;\n private parentHeight = 0;\n private parentDevicePixelWidth = 0;\n private parentDevicePixelHeight = 0;\n private devicePixelsSupported = false;\n\n private intersectionObserver: IntersectionObserver | null = null;\n private isInViewport = true;\n\n private resizeObserver: ResizeObserver | null = null;\n private setupResizeObserver = () => {\n this.resizeObserver = new ResizeObserver(([entry]) => {\n if (entry?.borderBoxSize[0]) {\n const physicalPixelSize = entry.devicePixelContentBoxSize?.[0];\n\n if (physicalPixelSize !== undefined) {\n this.devicePixelsSupported = true;\n this.parentDevicePixelWidth = physicalPixelSize.inlineSize;\n this.parentDevicePixelHeight = physicalPixelSize.blockSize;\n }\n\n this.parentWidth = entry.borderBoxSize[0].inlineSize;\n this.parentHeight = entry.borderBoxSize[0].blockSize;\n }\n\n this.handleResize();\n });\n\n this.resizeObserver.observe(this.parentElement);\n };\n\n private setupIntersectionObserver = () => {\n // we check element's own window to support shaders used within iframe/PiP elements\n const view = this.ownerDocument.defaultView;\n if (!view?.IntersectionObserver) return;\n\n this.intersectionObserver = new view.IntersectionObserver(([entry]) => {\n this.isInViewport = entry?.isIntersecting ?? true;\n this.updateCurrentSpeed();\n });\n\n this.intersectionObserver.observe(this.parentElement);\n };\n\n // Visual viewport resize handler, mainly used to react to browser zoom changes.\n // Resize observer by itself does not react to pinch zoom, and although it usually\n // reacts to classic browser zoom, it's not guaranteed in edge cases.\n // Since timing between visual viewport changes and resize observer is complex\n // and because we'd like to know the device pixel sizes of elements, we just restart\n // the observer to get a guaranteed fresh callback regardless if it would have triggered or not.\n private handleVisualViewportChange = () => {\n this.resizeObserver?.disconnect();\n this.setupResizeObserver();\n\n // In case of debugging timing, from here on:\n // - animation frame 1: a paint after the visual viewport resize\n // - animation frame 2: a paint after the resize observer has been handled, if it was ever triggered\n };\n\n /** Resize handler for when the container div changes size or the max pixel count changes and we want to resize our canvas to match */\n private handleResize = () => {\n // Aim to render at least as many pixels as physically displayed\n // This will overshoot when the user zooms out, but that's acceptable\n\n let targetPixelWidth = 0;\n let targetPixelHeight = 0;\n\n // If window.devicePixelRatio is below 1, it's safe to say the browser is just zoomed out\n // We can use 1 as the minimum value not to upscale it needlessly to meet the min pixel ratio param\n const dpr = Math.max(1, window.devicePixelRatio);\n const pinchZoom = visualViewport?.scale ?? 1;\n\n if (this.devicePixelsSupported) {\n // Use the real pixel size if we know it, plus meet the min pixel ratio requirement and add in pinch zoom\n const scaleToMeetMinPixelRatio = Math.max(1, this.minPixelRatio / dpr);\n targetPixelWidth = this.parentDevicePixelWidth * scaleToMeetMinPixelRatio * pinchZoom;\n targetPixelHeight = this.parentDevicePixelHeight * scaleToMeetMinPixelRatio * pinchZoom;\n } else {\n // Otherwise try to approximate the element size in device pixels using devicePixelRatio.\n // (devicePixelRatio is imprecise and element's width/height may be fractional CSS sizes, not real pixels).\n let targetRenderScale = Math.max(dpr, this.minPixelRatio) * pinchZoom;\n\n if (this.isSafari) {\n // As of 2025, Safari reports physical devicePixelRatio, but other browsers add the current zoom level:\n // https://bugs.webkit.org/show_bug.cgi?id=124862\n //\n // In Safari we need to factor in the zoom level manually in order to set the target resolution.\n // To avoid sidebars upscaling the target resolution, set a minimum zoom level of 1.\n // This will render at higher resolution when zoomed out, but that's fine.\n // (We mostly care about maintaining good quality when zoomed in).\n const zoomLevel = bestGuessBrowserZoom(this.ownerDocument);\n targetRenderScale *= Math.max(1, zoomLevel);\n }\n\n // Rounding the client width/height since they may be fractional in CSS layout values\n targetPixelWidth = Math.round(this.parentWidth) * targetRenderScale;\n targetPixelHeight = Math.round(this.parentHeight) * targetRenderScale;\n }\n\n // Prevent the total rendered pixel count from exceeding maxPixelCount\n const maxPixelCountHeadroom = Math.sqrt(this.maxPixelCount) / Math.sqrt(targetPixelWidth * targetPixelHeight);\n let scaleToMeetMaxPixelCount = Math.min(1, maxPixelCountHeadroom);\n if (this.sharedRenderer) {\n // The shared atlas has a maximum side, stay within it\n const maxSide = this.sharedRenderer.maxSide;\n scaleToMeetMaxPixelCount = Math.min(\n scaleToMeetMaxPixelCount,\n maxSide / targetPixelWidth,\n maxSide / targetPixelHeight\n );\n }\n const newWidth = Math.round(targetPixelWidth * scaleToMeetMaxPixelCount);\n const newHeight = Math.round(targetPixelHeight * scaleToMeetMaxPixelCount);\n const newRenderScale = newWidth / Math.round(this.parentWidth);\n\n const currentWidth = this.pendingCanvasWidth ?? this.canvasElement.width;\n const currentHeight = this.pendingCanvasHeight ?? this.canvasElement.height;\n\n if (\n currentWidth !== newWidth ||\n currentHeight !== newHeight ||\n this.renderScale !== newRenderScale // Usually, only render scale changes when the user zooms in/out\n ) {\n this.renderScale = newRenderScale;\n this.resolutionChanged = true;\n\n if (this.sharedRenderer) {\n // Resizing clears the canvas, and resize observers run after animation frames, so resizing here would show\n // an empty canvas for a frame. The shared renderer applies the size right before it redraws instead.\n this.pendingCanvasWidth = newWidth;\n this.pendingCanvasHeight = newHeight;\n this.sharedRenderer.schedule(this);\n return;\n }\n\n this.canvasElement.width = newWidth;\n this.canvasElement.height = newHeight;\n this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height);\n\n // this is necessary to avoid flashes while resizing (the next scheduled render will set uniforms)\n this.render(performance.now());\n }\n };\n\n private render = (currentTime: number) => {\n if (this.hasBeenDisposed) return;\n\n if (this.program === null) {\n console.warn('Tried to render before program or gl was initialized');\n return;\n }\n\n // Calculate the delta time\n const dt = currentTime - this.lastRenderTime;\n this.lastRenderTime = currentTime;\n // Increase the total animation time by dt * animationSpeed\n if (this.currentSpeed !== 0) {\n this.currentFrame += dt * this.currentSpeed;\n }\n\n // Clear the canvas\n this.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\n this.draw(0, 0);\n\n // Loop if we're animating\n if (this.currentSpeed !== 0) {\n this.requestRender();\n } else {\n this.rafId = null;\n }\n };\n\n /** Issue the draw call with this mount's program, geometry, textures and per-frame uniforms */\n private draw = (fragCoordOffsetX: number, fragCoordOffsetY: number) => {\n const gl = this.gl;\n\n // Update uniforms\n gl.useProgram(this.program);\n gl.bindVertexArray(this.vertexArray);\n\n // Texture units are context-wide state, rebind ours in case another mount on the shared context used them\n this.textures.forEach((texture, uniformName) => {\n gl.activeTexture(gl.TEXTURE0 + this.textureUnitMap.get(uniformName)!);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n });\n\n // Update the time uniform\n gl.uniform1f(this.uniformLocations.u_time!, this.currentFrame * 0.001);\n\n // If the resolution has changed, we need to update the uniform\n if (this.resolutionChanged) {\n gl.uniform2f(this.uniformLocations.u_resolution!, this.canvasElement.width, this.canvasElement.height);\n gl.uniform1f(this.uniformLocations.u_pixelRatio!, this.renderScale);\n this.resolutionChanged = false;\n }\n\n const fragCoordOffsetLocation = this.uniformLocations[FRAG_COORD_OFFSET_UNIFORM];\n if (fragCoordOffsetLocation) {\n gl.uniform2f(fragCoordOffsetLocation, fragCoordOffsetX, fragCoordOffsetY);\n }\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n };\n\n private requestRender = () => {\n if (this.sharedRenderer) {\n this.sharedRenderer.schedule(this);\n return;\n }\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n }\n this.rafId = requestAnimationFrame(this.render);\n };\n\n /** Draw the current state: right away with a dedicated context, on the next batched frame with the shared one */\n private redraw = () => {\n if (this.sharedRenderer) {\n this.sharedRenderer.schedule(this);\n } else {\n this.render(performance.now());\n }\n };\n\n /** @internal Shared renderer hook, see SharedRenderTarget */\n public prepareSharedFrame = (currentTime: number): SharedTargetSize | null => {\n if (this.hasBeenDisposed || this.program === null) return null;\n\n // Resizing clears the canvas, so it happens here, in the same task as the draw that refills it\n if (this.pendingCanvasWidth !== null && this.pendingCanvasHeight !== null) {\n this.canvasElement.width = this.pendingCanvasWidth;\n this.canvasElement.height = this.pendingCanvasHeight;\n this.pendingCanvasWidth = null;\n this.pendingCanvasHeight = null;\n }\n\n // One-off redraws (new uniforms, a resize) don't move time forward, only a running animation does\n const dt = this.sharedLoopActive ? Math.max(0, currentTime - this.lastRenderTime) : 0;\n this.lastRenderTime = currentTime;\n if (this.currentSpeed !== 0) {\n this.currentFrame += dt * this.currentSpeed;\n }\n\n return { width: this.canvasElement.width, height: this.canvasElement.height };\n };\n\n /** @internal Shared renderer hook, see SharedRenderTarget */\n public drawShared = (x: number, y: number): void => {\n this.draw(x, y);\n };\n\n /** @internal Shared renderer hook, see SharedRenderTarget */\n public presentShared = (frame: ImageBitmap, x: number, y: number, width: number, height: number): void => {\n if (!this.context2d) return;\n // Replace the previous frame instead of blending the new one over it\n this.context2d.globalCompositeOperation = 'copy';\n this.context2d.drawImage(frame, x, y, width, height, 0, 0, this.canvasElement.width, this.canvasElement.height);\n };\n\n /** @internal Shared renderer hook, see SharedRenderTarget */\n public finishSharedFrame = (): boolean => {\n this.sharedLoopActive = !this.hasBeenDisposed && this.program !== null && this.currentSpeed !== 0;\n return this.sharedLoopActive;\n };\n\n /** @internal Shared renderer hook, see SharedRenderTarget */\n public restoreShared = (gl: WebGL2RenderingContext): void => {\n if (this.hasBeenDisposed) return;\n this.gl = gl;\n this.initGL();\n // Don't jump the animation ahead by however long the context was gone\n this.lastRenderTime = performance.now();\n this.sharedRenderer?.schedule(this);\n };\n\n /**\n * A dedicated context was lost, usually because the page went over the browser's context limit and ours was the\n * one that rendered least recently.\n */\n private handleContextLost = () => {\n if (this.hasBeenDisposed) return;\n\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n this.awaitingNewContext = true;\n this.maybeReplaceDedicatedContext();\n };\n\n /**\n * We don't wait for 'webglcontextrestored': browsers restore an evicted context only once another context has been\n * garbage collected, which can take a long time or never happen. A new canvas with a new context goes in instead,\n * but only once the mount is on screen: every new context pushes the least recently used one out when the page is\n * at the limit, so offscreen or hidden mounts replacing theirs would just take turns evicting each other.\n */\n private maybeReplaceDedicatedContext = () => {\n if (!this.awaitingNewContext || this.hasBeenDisposed) return;\n if (this.ownerDocument.hidden || !this.isInViewport) return;\n this.awaitingNewContext = false;\n\n const now = performance.now();\n this.contextRecoveries = this.contextRecoveries.filter((time) => now - time < CONTEXT_RECOVERY_WINDOW_MS);\n if (this.contextRecoveries.length >= MAX_CONTEXT_RECOVERIES) {\n console.warn('Paper Shaders: WebGL context keeps getting lost, giving up on restoring it');\n return;\n }\n this.contextRecoveries.push(now);\n\n requestAnimationFrame(this.replaceDedicatedContext);\n };\n\n private replaceDedicatedContext = () => {\n if (this.hasBeenDisposed) return;\n\n const oldCanvas = this.canvasElement;\n const canvas = this.ownerDocument.createElement('canvas');\n canvas.width = oldCanvas.width;\n canvas.height = oldCanvas.height;\n const gl = canvas.getContext('webgl2', this.webGlContextAttributes);\n if (!gl) {\n console.warn('Paper Shaders: could not create a new WebGL context after the previous one was lost');\n return;\n }\n\n oldCanvas.removeEventListener('webglcontextlost', this.handleContextLost);\n canvas.addEventListener('webglcontextlost', this.handleContextLost);\n oldCanvas.replaceWith(canvas);\n this.canvasElement = canvas;\n this.gl = gl;\n\n this.initGL();\n gl.viewport(0, 0, canvas.width, canvas.height);\n // Don't jump the animation ahead by however long the context was gone\n this.lastRenderTime = performance.now();\n this.render(performance.now());\n };\n\n /** Creates a texture from an image and sets it into a uniform value */\n private setTextureUniform = (uniformName: string, image: HTMLImageElement): void => {\n if (!image.complete || image.naturalWidth === 0) {\n throw new Error(`Paper Shaders: image for uniform ${uniformName} must be fully loaded`);\n }\n\n // Clean up existing texture if present\n const existingTexture = this.textures.get(uniformName);\n if (existingTexture) {\n this.gl.deleteTexture(existingTexture);\n }\n\n // Get texture unit\n if (!this.textureUnitMap.has(uniformName)) {\n this.textureUnitMap.set(uniformName, this.textureUnitMap.size);\n }\n const textureUnit = this.textureUnitMap.get(uniformName)!;\n // Errors left by other work on the context would be blamed on this upload below, clear them first.\n // Bounded because a lost context reports errors forever in some browsers.\n for (let i = 0; i < 8 && this.gl.getError() !== this.gl.NO_ERROR; i++);\n\n // Activate correct texture unit before creating the texture\n this.gl.activeTexture(this.gl.TEXTURE0 + textureUnit);\n\n // Create and set up the new texture\n const texture = this.gl.createTexture();\n this.gl.bindTexture(this.gl.TEXTURE_2D, texture);\n\n // Set texture parameters\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n\n // Upload image to texture\n this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, image);\n\n // Generate mipmaps if the uniform is in the mipmaps list\n if (this.mipmaps.includes(uniformName)) {\n this.gl.generateMipmap(this.gl.TEXTURE_2D);\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR_MIPMAP_LINEAR);\n }\n\n const error = this.gl.getError();\n if (error !== this.gl.NO_ERROR || texture === null) {\n console.error('Paper Shaders: WebGL error when uploading texture:', error);\n return;\n }\n\n // Store the texture\n this.textures.set(uniformName, texture);\n\n // Set up texture unit and uniform\n const location = this.uniformLocations[uniformName];\n if (location) {\n this.gl.uniform1i(location, textureUnit);\n\n // Calculate and set the aspect ratio uniform\n const aspectRatioUniformName = `${uniformName}AspectRatio`;\n const aspectRatioLocation = this.uniformLocations[aspectRatioUniformName];\n if (aspectRatioLocation) {\n const aspectRatio = image.naturalWidth / image.naturalHeight;\n this.gl.uniform1f(aspectRatioLocation, aspectRatio);\n }\n }\n };\n\n /** Utility: recursive equality test for all the uniforms */\n private areUniformValuesEqual = (a: any, b: any): boolean => {\n if (a === b) return true;\n if (Array.isArray(a) && Array.isArray(b) && a.length === b.length) {\n return a.every((val, i) => this.areUniformValuesEqual(val, (b as any)[i]));\n }\n return false;\n };\n\n /** Sets the provided uniform values into the WebGL program, can be a partial list of uniforms that have changed */\n private setUniformValues = (updatedUniforms: ShaderMountUniforms) => {\n this.gl.useProgram(this.program);\n Object.entries(updatedUniforms).forEach(([key, value]) => {\n // Grab the value to use in the uniform cache\n let cacheValue: ShaderMountUniforms[keyof ShaderMountUniforms] | string = value;\n if (value instanceof HTMLImageElement) {\n // Images use their src for the cache value to save memory\n cacheValue = `${value.src.slice(0, 200)}|${value.naturalWidth}x${value.naturalHeight}`;\n }\n\n // Check if the uniform value has changed and, if not, bail early to avoid extra work\n if (this.areUniformValuesEqual(this.uniformCache[key], cacheValue)) return;\n // Update the uniform cache if we are still here\n this.uniformCache[key] = cacheValue;\n\n const location = this.uniformLocations[key];\n if (!location) {\n console.warn(`Uniform location for ${key} not found`);\n return;\n }\n\n if (value instanceof HTMLImageElement) {\n // Texture case, requires a good amount of code so it gets its own function:\n this.setTextureUniform(key, value);\n } else if (Array.isArray(value)) {\n // Array case\n let flatArray: number[] | null = null;\n let valueLength: number | null = null;\n\n // If it's an array of same-sized arrays, flatten it down so we can set the uniform\n if (value[0] !== undefined && Array.isArray(value[0])) {\n const firstChildLength = value[0].length;\n if (value.every((arr) => (arr as number[]).length === firstChildLength)) {\n // Array of same-sized arrays case, flattens the array sets it\n flatArray = value.flat();\n valueLength = firstChildLength;\n } else {\n console.warn(`All child arrays must be the same length for ${key}`);\n return;\n }\n } else {\n // Array of primitive values case, supports 2, 3, 4, 9, 16 length arrays\n flatArray = value as number[];\n valueLength = flatArray.length;\n }\n\n // Set the uniform based on array length... supports 2, 3, 4, 9, 16 length arrays of primitive values\n // or arbitrary length arrays of arrays\n switch (valueLength) {\n case 2:\n this.gl.uniform2fv(location, flatArray);\n break;\n case 3:\n this.gl.uniform3fv(location, flatArray);\n break;\n case 4:\n this.gl.uniform4fv(location, flatArray);\n break;\n case 9:\n this.gl.uniformMatrix3fv(location, false, flatArray);\n break;\n case 16:\n this.gl.uniformMatrix4fv(location, false, flatArray);\n break;\n default:\n console.warn(`Unsupported uniform array length: ${valueLength}`);\n }\n } else if (typeof value === 'number') {\n // Number case, supports floats and ints\n this.gl.uniform1f(location, value);\n } else if (typeof value === 'boolean') {\n // Boolean case, supports true and false\n this.gl.uniform1i(location, value ? 1 : 0);\n } else {\n // May happen on the server for SSR when undefined images are passed in\n console.warn(`Unsupported uniform type for ${key}: ${typeof value}`);\n }\n });\n };\n\n /** Gets the current total animation time from 0ms */\n public getCurrentFrame = (): number => {\n return this.currentFrame;\n };\n\n /** Set a frame to get a deterministic result, frames are literally just milliseconds from zero since the animation started */\n public setFrame = (newFrame: number): void => {\n this.currentFrame = newFrame;\n this.lastRenderTime = performance.now();\n this.redraw();\n };\n\n /** Set an animation speed (or 0 to stop animation) */\n public setSpeed = (newSpeed = 1): void => {\n // Set the new animation speed\n this.speed = newSpeed;\n this.updateCurrentSpeed();\n };\n\n /** Apply the target speed, pausing (0) while the tab is hidden or the element is out of the viewport */\n private updateCurrentSpeed = (): void => {\n this.setCurrentSpeed(this.ownerDocument.hidden || !this.isInViewport ? 0 : this.speed);\n this.maybeReplaceDedicatedContext();\n };\n\n private setCurrentSpeed = (newSpeed: number): void => {\n this.currentSpeed = newSpeed;\n\n if (this.sharedRenderer) {\n // The shared renderer keeps drawing a mount for as long as finishSharedFrame() says it's animating, so there\n // is nothing to cancel when it stops. Cancelling here could also drop a pending one-off redraw.\n if (newSpeed !== 0 && !this.sharedLoopActive) {\n this.sharedLoopActive = true;\n this.lastRenderTime = performance.now();\n this.sharedRenderer.schedule(this);\n }\n return;\n }\n\n if (this.rafId === null && newSpeed !== 0) {\n // Moving from 0 to animating, kick off a new rAF loop\n this.lastRenderTime = performance.now();\n this.rafId = requestAnimationFrame(this.render);\n }\n\n if (this.rafId !== null && newSpeed === 0) {\n // Moving from animating to not animating, cancel the rAF loop\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n };\n\n /** Set the maximum pixel count for the shader, this will limit the number of pixels that will be rendered */\n public setMaxPixelCount = (newMaxPixelCount: number = DEFAULT_MAX_PIXEL_COUNT): void => {\n this.maxPixelCount = newMaxPixelCount;\n\n this.handleResize();\n };\n\n /** Set the minimum pixel ratio for the shader */\n public setMinPixelRatio = (newMinPixelRatio: number = 2): void => {\n this.minPixelRatio = newMinPixelRatio;\n\n this.handleResize();\n };\n\n /** Update the uniforms that are provided by the outside shader, can be a partial set with only the uniforms that have changed */\n public setUniforms = (newUniforms: ShaderMountUniforms): void => {\n this.setUniformValues(newUniforms);\n this.providedUniforms = { ...this.providedUniforms, ...newUniforms };\n\n this.redraw();\n };\n\n private handleDocumentVisibilityChange = () => {\n this.updateCurrentSpeed();\n };\n\n /** Dispose of the shader mount, cleaning up all of the WebGL resources */\n public dispose = (): void => {\n // Immediately mark as disposed to prevent future renders from leaking in\n this.hasBeenDisposed = true;\n\n // Cancel the rAF loop\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n this.sharedRenderer?.unregister(this);\n\n if (this.gl && this.program) {\n // Clean up all textures\n this.textures.forEach((texture) => {\n this.gl.deleteTexture(texture);\n });\n this.textures.clear();\n\n this.gl.deleteProgram(this.program);\n this.program = null;\n this.gl.deleteVertexArray(this.vertexArray);\n this.vertexArray = null;\n this.gl.deleteBuffer(this.positionBuffer);\n this.positionBuffer = null;\n\n if (!this.sharedRenderer) {\n // Reset the WebGL context\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);\n this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, null);\n this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, null);\n this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);\n\n // Clear any errors\n this.gl.getError();\n }\n }\n\n if (!this.sharedRenderer) {\n this.canvasElement.removeEventListener('webglcontextlost', this.handleContextLost);\n // Release the context now rather than whenever the canvas gets garbage collected. Until then it would still\n // count toward the browser's context limit and push out contexts that are in use.\n this.gl.getExtension('WEBGL_lose_context')?.loseContext();\n }\n\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n\n if (this.intersectionObserver) {\n this.intersectionObserver.disconnect();\n this.intersectionObserver = null;\n }\n\n visualViewport?.removeEventListener('resize', this.handleVisualViewportChange);\n this.ownerDocument.removeEventListener('visibilitychange', this.handleDocumentVisibilityChange);\n\n this.uniformLocations = {};\n\n // Remove the shader from the div wrapper element\n this.canvasElement.remove();\n // Free up the reference to self to enable garbage collection\n delete this.parentElement.paperShaderMount;\n };\n}\n\nfunction createShader(gl: WebGL2RenderingContext, type: number, source: string): WebGLShader | null {\n const shader = gl.createShader(type);\n if (!shader) return null;\n\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n console.error('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));\n gl.deleteShader(shader);\n return null;\n }\n\n return shader;\n}\n\n/**\n * In the shared atlas a mount's viewport doesn't start at the canvas origin, so gl_FragCoord would be off by the\n * viewport's position. Route every read through a macro that subtracts that offset (set per draw), so shaders keep\n * seeing the same coordinates as on a canvas of their own.\n */\nfunction offsetFragCoord(fragmentShaderSource: string): string {\n if (!fragmentShaderSource.includes('gl_FragCoord')) return fragmentShaderSource;\n\n const source = fragmentShaderSource.replace(/\\bgl_FragCoord\\b/g, 'paperFragCoord');\n const declarations =\n `uniform highp vec2 ${FRAG_COORD_OFFSET_UNIFORM};\\n` +\n `#define paperFragCoord (gl_FragCoord - vec4(${FRAG_COORD_OFFSET_UNIFORM}, 0.0, 0.0))\\n`;\n\n // #version has to stay the first line\n const versionMatch = source.match(/^\\s*#version[^\\n]*\\n/);\n if (versionMatch) {\n const versionLength = versionMatch[0].length;\n return source.slice(0, versionLength) + declarations + source.slice(versionLength);\n }\n return declarations + source;\n}\n\nfunction createProgram(\n gl: WebGL2RenderingContext,\n vertexShaderSource: string,\n fragmentShaderSource: string,\n isShared: boolean\n): WebGLProgram | null {\n if (isShared) {\n fragmentShaderSource = offsetFragCoord(fragmentShaderSource);\n }\n\n const format = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT);\n const precision = format ? format.precision : null;\n // MEDIUM_FLOAT precision can be 10, 16 or 23 bits depending on device;\n // Shaders fail on 10 bit (and 16 bit is hard to test) => we force 23-bit by switching to highp\n if (precision && precision < 23) {\n vertexShaderSource = vertexShaderSource.replace(/precision\\s+(lowp|mediump)\\s+float;/g, 'precision highp float;');\n fragmentShaderSource = fragmentShaderSource\n .replace(/precision\\s+(lowp|mediump)\\s+float/g, 'precision highp float')\n .replace(/\\b(uniform|varying|attribute)\\s+(lowp|mediump)\\s+(\\w+)/g, '$1 highp $3');\n }\n\n const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);\n const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);\n\n if (!vertexShader || !fragmentShader) return null;\n\n const program = gl.createProgram();\n if (!program) return null;\n\n gl.attachShader(program, vertexShader);\n gl.attachShader(program, fragmentShader);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n console.error('Unable to initialize the shader program: ' + gl.getProgramInfoLog(program));\n gl.deleteProgram(program);\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n return null;\n }\n\n // Clean up shaders after successful linking\n gl.detachShader(program, vertexShader);\n gl.detachShader(program, fragmentShader);\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n\n return program;\n}\n\nconst defaultStyle = `@layer paper-shaders {\n :where([data-paper-shader]) {\n isolation: isolate;\n position: relative;\n\n & canvas {\n contain: strict;\n display: block;\n position: absolute;\n inset: 0;\n z-index: -1;\n width: 100%;\n height: 100%;\n border-radius: inherit;\n corner-shape: inherit;\n }\n }\n}`;\n\n/** The parent `<div>` element that has a ShaderMount available on it */\nexport interface PaperShaderElement extends HTMLElement {\n paperShaderMount: ShaderMount | undefined;\n}\n\n/**\n * How a ShaderMount gets its WebGL context:\n * - \"shared\": draws through one context shared by all shared mounts, so any number of shaders stays within the\n * browser's context limit. Each frame is copied into the mount's own canvas, a small cost for the typical widget.\n * - \"dedicated\": owns a context, drawn without a copy. Best for a single large shader such as a full screen background.\n */\nexport type WebGlContextMode = 'shared' | 'dedicated';\n\n/** Check if an element is a Paper shader element */\nexport function isPaperShaderElement(element: HTMLElement): element is PaperShaderElement {\n return 'paperShaderMount' in element;\n}\n\n/**\n * Uniform types that we support to be auto-mapped into the fragment shader\n *\n * We accept undefined as a convenience for server rendering, when some things may be undefined\n * We just skip setting the uniform if it's undefined. This allows the shader mount to still take up space during server rendering\n */\nexport interface ShaderMountUniforms {\n [key: string]: boolean | number | number[] | number[][] | HTMLImageElement | undefined;\n}\n\nexport interface ShaderMotionParams {\n speed?: number;\n frame?: number;\n}\n\nexport type ShaderPreset<T> = {\n name: string;\n params: Required<T>;\n};\n\nexport type ImageShaderPreset<T> = {\n name: string;\n /**\n * Params for the shader excluding the image.\n * Image is excluded as it isn't considered a preset,\n * e.g. when switching between presets it shouldn't switch the image.\n *\n * While we exclude images from presets they should still be set with a default prop value so the code-first usage of shaders remains great.\n */\n params: Required<Omit<T, 'image'>>;\n};\n\nfunction isSafari() {\n const ua = navigator.userAgent.toLowerCase();\n return ua.includes('safari') && !ua.includes('chrome') && !ua.includes('android');\n}\n\n// Zoom level can be estimated comparing the browser's outerWidth and the viewport width.\n// It's nowhere near perfect because it's affected by the presence of browser sidebars,\n// like a vertical web inspector or Arc's sidebar. Also, both outerWidth and innerWidth\n// are integers, which would almost never give us a perfect ratio at face values.\n//\n// Still, this is pretty accurate in the vast majority of cases.\n//\n// Note 1:\n// Avoid innerWidth, use visualViewport.width instead.\n// - innerWidth is affected by pinch zoom in Safari, but not other browsers.\n// visualViewport.width works consistently in all browsers.\n// - innerWidth is rounded to integer, but not visualViewport.width.\n// - visualViewport.width is affected by hard scrollbars, so they need to be added manually\n//\n// Note 2:\n// Opening a sidebar in Safari like web inspector or bookmarks will throw off the zoom\n// level detection and result in a larger target resolution. Not a concern in real-world usage\n// with Safari, but we'd rather not try to detect zoom levels with other browsers\n// (e.g. Arc always has a sidebar, which affects outerWidth vs visualViewport.width).\nfunction bestGuessBrowserZoom(doc: Document) {\n const viewportScale = visualViewport?.scale ?? 1;\n const viewportWidth = visualViewport?.width ?? window.innerWidth;\n const scrollbarWidth = window.innerWidth - doc.documentElement.clientWidth;\n const innerWidth = viewportScale * viewportWidth + scrollbarWidth;\n\n // outerWidth and innerWidth are always integers so we won't often get the original zoom ratio\n // E.g. given a 125% zoom, outerWidth = 1657, innerWidth = 1325, 1657 / 1325 = 1.2505660377\n // We check for common zoom levels and return the closest one if found.\n\n const ratio = outerWidth / innerWidth;\n const zoomPercentageRounded = Math.round(100 * ratio);\n\n // All zoom levels divisible by 5%\n if (zoomPercentageRounded % 5 === 0) {\n return zoomPercentageRounded / 100;\n }\n\n // 33% zoom\n if (zoomPercentageRounded === 33) {\n return 1 / 3;\n }\n\n // 67% zoom\n if (zoomPercentageRounded === 67) {\n return 2 / 3;\n }\n\n // 133% zoom\n if (zoomPercentageRounded === 133) {\n return 4 / 3;\n }\n\n return ratio;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["vertexShaderSource"]
7
+ }
@@ -0,0 +1,30 @@
1
+ export interface ShaderSizingUniforms {
2
+ u_fit: (typeof ShaderFitOptions)[ShaderFit];
3
+ u_scale: number;
4
+ u_rotation: number;
5
+ u_originX: number;
6
+ u_originY: number;
7
+ u_offsetX: number;
8
+ u_offsetY: number;
9
+ u_worldWidth: number;
10
+ u_worldHeight: number;
11
+ }
12
+ export interface ShaderSizingParams {
13
+ fit?: 'none' | 'contain' | 'cover';
14
+ scale?: number;
15
+ rotation?: number;
16
+ originX?: number;
17
+ originY?: number;
18
+ offsetX?: number;
19
+ offsetY?: number;
20
+ worldWidth?: number;
21
+ worldHeight?: number;
22
+ }
23
+ export declare const defaultObjectSizing: Required<ShaderSizingParams>;
24
+ export declare const defaultPatternSizing: Required<ShaderSizingParams>;
25
+ export declare const ShaderFitOptions: {
26
+ readonly none: 0;
27
+ readonly contain: 1;
28
+ readonly cover: 2;
29
+ };
30
+ export type ShaderFit = keyof typeof ShaderFitOptions;
@@ -0,0 +1,38 @@
1
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
+ * Paper Shaders *
3
+ * https://github.com/paper-design/shaders *
4
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5
+
6
+ const defaultObjectSizing = {
7
+ fit: "contain",
8
+ scale: 1,
9
+ rotation: 0,
10
+ offsetX: 0,
11
+ offsetY: 0,
12
+ originX: 0.5,
13
+ originY: 0.5,
14
+ worldWidth: 0,
15
+ worldHeight: 0
16
+ };
17
+ const defaultPatternSizing = {
18
+ fit: "none",
19
+ scale: 1,
20
+ rotation: 0,
21
+ offsetX: 0,
22
+ offsetY: 0,
23
+ originX: 0.5,
24
+ originY: 0.5,
25
+ worldWidth: 0,
26
+ worldHeight: 0
27
+ };
28
+ const ShaderFitOptions = {
29
+ none: 0,
30
+ contain: 1,
31
+ cover: 2
32
+ };
33
+ export {
34
+ ShaderFitOptions,
35
+ defaultObjectSizing,
36
+ defaultPatternSizing
37
+ };
38
+ //# sourceMappingURL=shader-sizing.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/shader-sizing.ts"],
4
+ "sourcesContent": ["export interface ShaderSizingUniforms {\r\n u_fit: (typeof ShaderFitOptions)[ShaderFit];\r\n u_scale: number;\r\n u_rotation: number;\r\n u_originX: number;\r\n u_originY: number;\r\n u_offsetX: number;\r\n u_offsetY: number;\r\n u_worldWidth: number;\r\n u_worldHeight: number;\r\n}\r\n\r\nexport interface ShaderSizingParams {\r\n fit?: 'none' | 'contain' | 'cover';\r\n scale?: number;\r\n rotation?: number;\r\n originX?: number;\r\n originY?: number;\r\n offsetX?: number;\r\n offsetY?: number;\r\n worldWidth?: number;\r\n worldHeight?: number;\r\n}\r\n\r\nexport const defaultObjectSizing: Required<ShaderSizingParams> = {\r\n fit: 'contain',\r\n scale: 1,\r\n rotation: 0,\r\n offsetX: 0,\r\n offsetY: 0,\r\n originX: 0.5,\r\n originY: 0.5,\r\n worldWidth: 0,\r\n worldHeight: 0,\r\n};\r\n\r\nexport const defaultPatternSizing: Required<ShaderSizingParams> = {\r\n fit: 'none',\r\n scale: 1,\r\n rotation: 0,\r\n offsetX: 0,\r\n offsetY: 0,\r\n originX: 0.5,\r\n originY: 0.5,\r\n worldWidth: 0,\r\n worldHeight: 0,\r\n};\r\n\r\nexport const ShaderFitOptions = {\r\n none: 0,\r\n contain: 1,\r\n cover: 2,\r\n} as const;\r\n\r\nexport type ShaderFit = keyof typeof ShaderFitOptions;\r\n"],
5
+ "mappings": ";;;;;AAwBO,MAAM,sBAAoD;AAAA,EAC/D,KAAK;AAAA,EACL,OAAO;AAAA,EACP,UAAU;AAAA,EACV,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,aAAa;AACf;AAEO,MAAM,uBAAqD;AAAA,EAChE,KAAK;AAAA,EACL,OAAO;AAAA,EACP,UAAU;AAAA,EACV,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,aAAa;AACf;AAEO,MAAM,mBAAmB;AAAA,EAC9B,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1,10 @@
1
+ export declare const declarePI = "\n#define TWO_PI 6.28318530718\n#define PI 3.14159265358979323846\n";
2
+ export declare const rotation2 = "\nvec2 rotate(vec2 uv, float th) {\n return mat2(cos(th), sin(th), -sin(th), cos(th)) * uv;\n}\n";
3
+ export declare const proceduralHash11 = "\n float hash11(float p) {\n p = fract(p * 0.3183099) + 0.1;\n p *= p + 19.19;\n return fract(p * p);\n }\n";
4
+ export declare const proceduralHash21 = "\n float hash21(vec2 p) {\n p = fract(p * vec2(0.3183099, 0.3678794)) + 0.1;\n p += dot(p, p + 19.19);\n return fract(p.x * p.y);\n }\n";
5
+ export declare const proceduralHash22 = "\n vec2 hash22(vec2 p) {\n p = fract(p * vec2(0.3183099, 0.3678794)) + 0.1;\n p += dot(p, p.yx + 19.19);\n return fract(vec2(p.x * p.y, p.x + p.y));\n }\n";
6
+ export declare const textureRandomizerR = "\n float randomR(vec2 p) {\n vec2 uv = floor(p) / 100. + .5;\n return texture(u_noiseTexture, fract(uv)).r;\n }\n";
7
+ export declare const textureRandomizerGB = "\n vec2 randomGB(vec2 p) {\n vec2 uv = floor(p) / 100. + .5;\n return texture(u_noiseTexture, fract(uv)).gb;\n }\n";
8
+ export declare const colorBandingFix = "\n color += 1. / 256. * (fract(sin(dot(.014 * gl_FragCoord.xy, vec2(12.9898, 78.233))) * 43758.5453123) - .5);\n";
9
+ export declare const simplexNoise = "\nvec3 permute(vec3 x) { return mod(((x * 34.0) + 1.0) * x, 289.0); }\nfloat snoise(vec2 v) {\n const vec4 C = vec4(0.211324865405187, 0.366025403784439,\n -0.577350269189626, 0.024390243902439);\n vec2 i = floor(v + dot(v, C.yy));\n vec2 x0 = v - i + dot(i, C.xx);\n vec2 i1;\n i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);\n vec4 x12 = x0.xyxy + C.xxzz;\n x12.xy -= i1;\n i = mod(i, 289.0);\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 vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy),\n dot(x12.zw, x12.zw)), 0.0);\n m = m * m;\n m = m * m;\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 m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h);\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";
10
+ export declare const fiberNoise = "\nfloat fiberRandom(vec2 p) {\n vec2 uv = floor(p) / 100.;\n return texture(u_noiseTexture, fract(uv)).b;\n}\n\nfloat fiberValueNoise(vec2 st) {\n vec2 i = floor(st);\n vec2 f = fract(st);\n float a = fiberRandom(i);\n float b = fiberRandom(i + vec2(1.0, 0.0));\n float c = fiberRandom(i + vec2(0.0, 1.0));\n float d = fiberRandom(i + vec2(1.0, 1.0));\n vec2 u = f * f * (3.0 - 2.0 * f);\n float x1 = mix(a, b, u.x);\n float x2 = mix(c, d, u.x);\n return mix(x1, x2, u.y);\n}\n\nfloat fiberNoiseFbm(in vec2 n, vec2 seedOffset) {\n float total = 0.0, amplitude = 1.;\n for (int i = 0; i < 4; i++) {\n n = rotate(n, .7);\n total += fiberValueNoise(n + seedOffset) * amplitude;\n n *= 2.;\n amplitude *= 0.6;\n }\n return total;\n}\n\nfloat fiberNoise(vec2 uv, vec2 seedOffset) {\n float epsilon = 0.001;\n float n1 = fiberNoiseFbm(uv + vec2(epsilon, 0.0), seedOffset);\n float n2 = fiberNoiseFbm(uv - vec2(epsilon, 0.0), seedOffset);\n float n3 = fiberNoiseFbm(uv + vec2(0.0, epsilon), seedOffset);\n float n4 = fiberNoiseFbm(uv - vec2(0.0, epsilon), seedOffset);\n return length(vec2(n1 - n2, n3 - n4)) / (2.0 * epsilon);\n}\n";
@@ -0,0 +1,131 @@
1
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
+ * Paper Shaders *
3
+ * https://github.com/paper-design/shaders *
4
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5
+
6
+ const declarePI = `
7
+ #define TWO_PI 6.28318530718
8
+ #define PI 3.14159265358979323846
9
+ `;
10
+ const rotation2 = `
11
+ vec2 rotate(vec2 uv, float th) {
12
+ return mat2(cos(th), sin(th), -sin(th), cos(th)) * uv;
13
+ }
14
+ `;
15
+ const proceduralHash11 = `
16
+ float hash11(float p) {
17
+ p = fract(p * 0.3183099) + 0.1;
18
+ p *= p + 19.19;
19
+ return fract(p * p);
20
+ }
21
+ `;
22
+ const proceduralHash21 = `
23
+ float hash21(vec2 p) {
24
+ p = fract(p * vec2(0.3183099, 0.3678794)) + 0.1;
25
+ p += dot(p, p + 19.19);
26
+ return fract(p.x * p.y);
27
+ }
28
+ `;
29
+ const proceduralHash22 = `
30
+ vec2 hash22(vec2 p) {
31
+ p = fract(p * vec2(0.3183099, 0.3678794)) + 0.1;
32
+ p += dot(p, p.yx + 19.19);
33
+ return fract(vec2(p.x * p.y, p.x + p.y));
34
+ }
35
+ `;
36
+ const textureRandomizerR = `
37
+ float randomR(vec2 p) {
38
+ vec2 uv = floor(p) / 100. + .5;
39
+ return texture(u_noiseTexture, fract(uv)).r;
40
+ }
41
+ `;
42
+ const textureRandomizerGB = `
43
+ vec2 randomGB(vec2 p) {
44
+ vec2 uv = floor(p) / 100. + .5;
45
+ return texture(u_noiseTexture, fract(uv)).gb;
46
+ }
47
+ `;
48
+ const colorBandingFix = `
49
+ color += 1. / 256. * (fract(sin(dot(.014 * gl_FragCoord.xy, vec2(12.9898, 78.233))) * 43758.5453123) - .5);
50
+ `;
51
+ const simplexNoise = `
52
+ vec3 permute(vec3 x) { return mod(((x * 34.0) + 1.0) * x, 289.0); }
53
+ float snoise(vec2 v) {
54
+ const vec4 C = vec4(0.211324865405187, 0.366025403784439,
55
+ -0.577350269189626, 0.024390243902439);
56
+ vec2 i = floor(v + dot(v, C.yy));
57
+ vec2 x0 = v - i + dot(i, C.xx);
58
+ vec2 i1;
59
+ i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
60
+ vec4 x12 = x0.xyxy + C.xxzz;
61
+ x12.xy -= i1;
62
+ i = mod(i, 289.0);
63
+ vec3 p = permute(permute(i.y + vec3(0.0, i1.y, 1.0))
64
+ + i.x + vec3(0.0, i1.x, 1.0));
65
+ vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy),
66
+ dot(x12.zw, x12.zw)), 0.0);
67
+ m = m * m;
68
+ m = m * m;
69
+ vec3 x = 2.0 * fract(p * C.www) - 1.0;
70
+ vec3 h = abs(x) - 0.5;
71
+ vec3 ox = floor(x + 0.5);
72
+ vec3 a0 = x - ox;
73
+ m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h);
74
+ vec3 g;
75
+ g.x = a0.x * x0.x + h.x * x0.y;
76
+ g.yz = a0.yz * x12.xz + h.yz * x12.yw;
77
+ return 130.0 * dot(m, g);
78
+ }
79
+ `;
80
+ const fiberNoise = `
81
+ float fiberRandom(vec2 p) {
82
+ vec2 uv = floor(p) / 100.;
83
+ return texture(u_noiseTexture, fract(uv)).b;
84
+ }
85
+
86
+ float fiberValueNoise(vec2 st) {
87
+ vec2 i = floor(st);
88
+ vec2 f = fract(st);
89
+ float a = fiberRandom(i);
90
+ float b = fiberRandom(i + vec2(1.0, 0.0));
91
+ float c = fiberRandom(i + vec2(0.0, 1.0));
92
+ float d = fiberRandom(i + vec2(1.0, 1.0));
93
+ vec2 u = f * f * (3.0 - 2.0 * f);
94
+ float x1 = mix(a, b, u.x);
95
+ float x2 = mix(c, d, u.x);
96
+ return mix(x1, x2, u.y);
97
+ }
98
+
99
+ float fiberNoiseFbm(in vec2 n, vec2 seedOffset) {
100
+ float total = 0.0, amplitude = 1.;
101
+ for (int i = 0; i < 4; i++) {
102
+ n = rotate(n, .7);
103
+ total += fiberValueNoise(n + seedOffset) * amplitude;
104
+ n *= 2.;
105
+ amplitude *= 0.6;
106
+ }
107
+ return total;
108
+ }
109
+
110
+ float fiberNoise(vec2 uv, vec2 seedOffset) {
111
+ float epsilon = 0.001;
112
+ float n1 = fiberNoiseFbm(uv + vec2(epsilon, 0.0), seedOffset);
113
+ float n2 = fiberNoiseFbm(uv - vec2(epsilon, 0.0), seedOffset);
114
+ float n3 = fiberNoiseFbm(uv + vec2(0.0, epsilon), seedOffset);
115
+ float n4 = fiberNoiseFbm(uv - vec2(0.0, epsilon), seedOffset);
116
+ return length(vec2(n1 - n2, n3 - n4)) / (2.0 * epsilon);
117
+ }
118
+ `;
119
+ export {
120
+ colorBandingFix,
121
+ declarePI,
122
+ fiberNoise,
123
+ proceduralHash11,
124
+ proceduralHash21,
125
+ proceduralHash22,
126
+ rotation2,
127
+ simplexNoise,
128
+ textureRandomizerGB,
129
+ textureRandomizerR
130
+ };
131
+ //# sourceMappingURL=shader-utils.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/shader-utils.ts"],
4
+ "sourcesContent": ["// language=GLSL\r\nexport const declarePI = `\r\n#define TWO_PI 6.28318530718\r\n#define PI 3.14159265358979323846\r\n`;\r\n\r\n// language=GLSL\r\nexport const rotation2 = `\r\nvec2 rotate(vec2 uv, float th) {\r\n return mat2(cos(th), sin(th), -sin(th), cos(th)) * uv;\r\n}\r\n`;\r\n\r\n// language=GLSL\r\nexport const proceduralHash11 = `\r\n float hash11(float p) {\r\n p = fract(p * 0.3183099) + 0.1;\r\n p *= p + 19.19;\r\n return fract(p * p);\r\n }\r\n`;\r\n\r\n// language=GLSL\r\nexport const proceduralHash21 = `\r\n float hash21(vec2 p) {\r\n p = fract(p * vec2(0.3183099, 0.3678794)) + 0.1;\r\n p += dot(p, p + 19.19);\r\n return fract(p.x * p.y);\r\n }\r\n`;\r\n\r\n// language=GLSL\r\nexport const proceduralHash22 = `\r\n vec2 hash22(vec2 p) {\r\n p = fract(p * vec2(0.3183099, 0.3678794)) + 0.1;\r\n p += dot(p, p.yx + 19.19);\r\n return fract(vec2(p.x * p.y, p.x + p.y));\r\n }\r\n`;\r\n\r\n// language=GLSL\r\nexport const textureRandomizerR = `\r\n float randomR(vec2 p) {\r\n vec2 uv = floor(p) / 100. + .5;\r\n return texture(u_noiseTexture, fract(uv)).r;\r\n }\r\n`;\r\n\r\n// language=GLSL\r\nexport const textureRandomizerGB = `\r\n vec2 randomGB(vec2 p) {\r\n vec2 uv = floor(p) / 100. + .5;\r\n return texture(u_noiseTexture, fract(uv)).gb;\r\n }\r\n`;\r\n\r\n// language=GLSL\r\nexport const colorBandingFix = `\r\n color += 1. / 256. * (fract(sin(dot(.014 * gl_FragCoord.xy, vec2(12.9898, 78.233))) * 43758.5453123) - .5);\r\n`;\r\n\r\n// language=GLSL\r\nexport const simplexNoise = `\r\nvec3 permute(vec3 x) { return mod(((x * 34.0) + 1.0) * x, 289.0); }\r\nfloat snoise(vec2 v) {\r\n const vec4 C = vec4(0.211324865405187, 0.366025403784439,\r\n -0.577350269189626, 0.024390243902439);\r\n vec2 i = floor(v + dot(v, C.yy));\r\n vec2 x0 = v - i + dot(i, C.xx);\r\n vec2 i1;\r\n i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);\r\n vec4 x12 = x0.xyxy + C.xxzz;\r\n x12.xy -= i1;\r\n i = mod(i, 289.0);\r\n vec3 p = permute(permute(i.y + vec3(0.0, i1.y, 1.0))\r\n + i.x + vec3(0.0, i1.x, 1.0));\r\n vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy),\r\n dot(x12.zw, x12.zw)), 0.0);\r\n m = m * m;\r\n m = m * m;\r\n vec3 x = 2.0 * fract(p * C.www) - 1.0;\r\n vec3 h = abs(x) - 0.5;\r\n vec3 ox = floor(x + 0.5);\r\n vec3 a0 = x - ox;\r\n m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h);\r\n vec3 g;\r\n g.x = a0.x * x0.x + h.x * x0.y;\r\n g.yz = a0.yz * x12.xz + h.yz * x12.yw;\r\n return 130.0 * dot(m, g);\r\n}\r\n`;\r\n\r\n// language=GLSL\r\nexport const fiberNoise = `\r\nfloat fiberRandom(vec2 p) {\r\n vec2 uv = floor(p) / 100.;\r\n return texture(u_noiseTexture, fract(uv)).b;\r\n}\r\n\r\nfloat fiberValueNoise(vec2 st) {\r\n vec2 i = floor(st);\r\n vec2 f = fract(st);\r\n float a = fiberRandom(i);\r\n float b = fiberRandom(i + vec2(1.0, 0.0));\r\n float c = fiberRandom(i + vec2(0.0, 1.0));\r\n float d = fiberRandom(i + vec2(1.0, 1.0));\r\n vec2 u = f * f * (3.0 - 2.0 * f);\r\n float x1 = mix(a, b, u.x);\r\n float x2 = mix(c, d, u.x);\r\n return mix(x1, x2, u.y);\r\n}\r\n\r\nfloat fiberNoiseFbm(in vec2 n, vec2 seedOffset) {\r\n float total = 0.0, amplitude = 1.;\r\n for (int i = 0; i < 4; i++) {\r\n n = rotate(n, .7);\r\n total += fiberValueNoise(n + seedOffset) * amplitude;\r\n n *= 2.;\r\n amplitude *= 0.6;\r\n }\r\n return total;\r\n}\r\n\r\nfloat fiberNoise(vec2 uv, vec2 seedOffset) {\r\n float epsilon = 0.001;\r\n float n1 = fiberNoiseFbm(uv + vec2(epsilon, 0.0), seedOffset);\r\n float n2 = fiberNoiseFbm(uv - vec2(epsilon, 0.0), seedOffset);\r\n float n3 = fiberNoiseFbm(uv + vec2(0.0, epsilon), seedOffset);\r\n float n4 = fiberNoiseFbm(uv - vec2(0.0, epsilon), seedOffset);\r\n return length(vec2(n1 - n2, n3 - n4)) / (2.0 * epsilon);\r\n}\r\n`;\r\n"],
5
+ "mappings": ";;;;;AACO,MAAM,YAAY;AAAA;AAAA;AAAA;AAMlB,MAAM,YAAY;AAAA;AAAA;AAAA;AAAA;AAOlB,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASzB,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASzB,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASzB,MAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAQ3B,MAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAQ5B,MAAM,kBAAkB;AAAA;AAAA;AAKxB,MAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA+BrB,MAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
6
+ "names": []
7
+ }
@@ -0,0 +1,70 @@
1
+ import type { vec4 } from '../types.js';
2
+ import type { ShaderMotionParams } from '../shader-mount.js';
3
+ import { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';
4
+ export declare const colorPanelsMeta: {
5
+ readonly maxColorCount: 7;
6
+ };
7
+ /**
8
+ * Pseudo-3D semi-transparent panels rotating around a central axis
9
+ *
10
+ * Fragment shader uniforms:
11
+ * - u_time (float): Animation time
12
+ * - u_scale (float): Overall zoom level, used for anti-aliasing calculations
13
+ * - u_colors (vec4[]): Up to 7 RGBA colors used to color the panels
14
+ * - u_colorsCount (float): Number of active colors
15
+ * - u_colorBack (vec4): Background color in RGBA
16
+ * - u_density (float): Angle between every 2 panels (0.25 to 7)
17
+ * - u_angle1 (float): Skew angle applied to all panes (-1 to 1)
18
+ * - u_angle2 (float): Skew angle applied to all panes (-1 to 1)
19
+ * - u_length (float): Panel length relative to total height (0 to 3)
20
+ * - u_edges (bool): Color highlight on the panels edges
21
+ * - u_blur (float): Side blur, 0 for sharp edges (0 to 0.5)
22
+ * - u_fadeIn (float): Transparency near central axis (0 to 1)
23
+ * - u_fadeOut (float): Transparency near viewer (0 to 1)
24
+ * - u_gradient (float): Color mixing within a panel, 0 = solid, 1 = gradient, needs 2+ colors (0 to 1)
25
+ *
26
+ * Vertex shader outputs (used in fragment shader):
27
+ * - v_objectUV (vec2): Object box UV coordinates with global sizing (scale, rotation, offsets, etc) applied
28
+ *
29
+ * Vertex shader uniforms:
30
+ * - u_resolution (vec2): Canvas resolution in pixels
31
+ * - u_pixelRatio (float): Device pixel ratio
32
+ * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)
33
+ * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)
34
+ * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas
35
+ * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas
36
+ * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)
37
+ * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)
38
+ * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)
39
+ * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)
40
+ * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)
41
+ *
42
+ */
43
+ export declare const colorPanelsFragmentShader: string;
44
+ export interface ColorPanelsUniforms extends ShaderSizingUniforms {
45
+ u_colors: vec4[];
46
+ u_colorsCount: number;
47
+ u_colorBack: [number, number, number, number];
48
+ u_angle1: number;
49
+ u_angle2: number;
50
+ u_length: number;
51
+ u_edges: boolean;
52
+ u_blur: number;
53
+ u_fadeIn: number;
54
+ u_fadeOut: number;
55
+ u_density: number;
56
+ u_gradient: number;
57
+ }
58
+ export interface ColorPanelsParams extends ShaderSizingParams, ShaderMotionParams {
59
+ colors?: string[];
60
+ colorBack?: string;
61
+ angle1?: number;
62
+ angle2?: number;
63
+ length?: number;
64
+ edges?: boolean;
65
+ blur?: number;
66
+ fadeIn?: number;
67
+ fadeOut?: number;
68
+ density?: number;
69
+ gradient?: number;
70
+ }