shaders 2.3.69 → 2.3.71

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 (80) hide show
  1. package/dist/svelte/index.js +76 -76
  2. package/dist/svelte/source/components/AngularBlur.svelte +287 -0
  3. package/dist/svelte/source/components/Ascii.svelte +288 -0
  4. package/dist/svelte/source/components/Aurora.svelte +292 -0
  5. package/dist/svelte/source/components/Beam.svelte +290 -0
  6. package/dist/svelte/source/components/Blob.svelte +289 -0
  7. package/dist/svelte/source/components/Blur.svelte +287 -0
  8. package/dist/svelte/source/components/BrightnessContrast.svelte +288 -0
  9. package/dist/svelte/source/components/Bulge.svelte +289 -0
  10. package/dist/svelte/source/components/CRTScreen.svelte +294 -0
  11. package/dist/svelte/source/components/ChannelBlur.svelte +289 -0
  12. package/dist/svelte/source/components/Checkerboard.svelte +288 -0
  13. package/dist/svelte/source/components/ChromaFlow.svelte +286 -0
  14. package/dist/svelte/source/components/ChromaticAberration.svelte +291 -0
  15. package/dist/svelte/source/components/Circle.svelte +289 -0
  16. package/dist/svelte/source/components/ConcentricSpin.svelte +290 -0
  17. package/dist/svelte/source/components/ContourLines.svelte +289 -0
  18. package/dist/svelte/source/components/CursorRipples.svelte +288 -0
  19. package/dist/svelte/source/components/CursorTrail.svelte +286 -0
  20. package/dist/svelte/source/components/DiffuseBlur.svelte +287 -0
  21. package/dist/svelte/source/components/Dither.svelte +288 -0
  22. package/dist/svelte/source/components/DotGrid.svelte +288 -0
  23. package/dist/svelte/source/components/Duotone.svelte +287 -0
  24. package/dist/svelte/source/components/FilmGrain.svelte +287 -0
  25. package/dist/svelte/source/components/FloatingParticles.svelte +290 -0
  26. package/dist/svelte/source/components/FlowField.svelte +288 -0
  27. package/dist/svelte/source/components/GlassTiles.svelte +290 -0
  28. package/dist/svelte/source/components/Glitch.svelte +292 -0
  29. package/dist/svelte/source/components/Glow.svelte +289 -0
  30. package/dist/svelte/source/components/Godrays.svelte +289 -0
  31. package/dist/svelte/source/components/Grayscale.svelte +286 -0
  32. package/dist/svelte/source/components/Grid.svelte +288 -0
  33. package/dist/svelte/source/components/GridDistortion.svelte +287 -0
  34. package/dist/svelte/source/components/Group.svelte +286 -0
  35. package/dist/svelte/source/components/Halftone.svelte +289 -0
  36. package/dist/svelte/source/components/HueShift.svelte +287 -0
  37. package/dist/svelte/source/components/ImageTexture.svelte +286 -0
  38. package/dist/svelte/source/components/Invert.svelte +286 -0
  39. package/dist/svelte/source/components/Kaleidoscope.svelte +288 -0
  40. package/dist/svelte/source/components/LensFlare.svelte +299 -0
  41. package/dist/svelte/source/components/LinearBlur.svelte +288 -0
  42. package/dist/svelte/source/components/LinearGradient.svelte +287 -0
  43. package/dist/svelte/source/components/Liquify.svelte +286 -0
  44. package/dist/svelte/source/components/Mirror.svelte +287 -0
  45. package/dist/svelte/source/components/Perspective.svelte +290 -0
  46. package/dist/svelte/source/components/Pixelate.svelte +287 -0
  47. package/dist/svelte/source/components/Plasma.svelte +290 -0
  48. package/dist/svelte/source/components/PolarCoordinates.svelte +289 -0
  49. package/dist/svelte/source/components/Posterize.svelte +287 -0
  50. package/dist/svelte/source/components/ProgressiveBlur.svelte +289 -0
  51. package/dist/svelte/source/components/RadialGradient.svelte +287 -0
  52. package/dist/svelte/source/components/RectangularCoordinates.svelte +288 -0
  53. package/dist/svelte/source/components/Ripples.svelte +290 -0
  54. package/dist/svelte/source/components/Saturation.svelte +287 -0
  55. package/dist/svelte/source/components/Sharpness.svelte +287 -0
  56. package/dist/svelte/source/components/Shatter.svelte +289 -0
  57. package/dist/svelte/source/components/SimplexNoise.svelte +288 -0
  58. package/dist/svelte/source/components/SineWave.svelte +291 -0
  59. package/dist/svelte/source/components/SolidColor.svelte +286 -0
  60. package/dist/svelte/source/components/Spherize.svelte +290 -0
  61. package/dist/svelte/source/components/Spiral.svelte +290 -0
  62. package/dist/svelte/source/components/Strands.svelte +289 -0
  63. package/dist/svelte/source/components/Stretch.svelte +289 -0
  64. package/dist/svelte/source/components/Stripes.svelte +291 -0
  65. package/dist/svelte/source/components/StudioBackground.svelte +298 -0
  66. package/dist/svelte/source/components/Swirl.svelte +288 -0
  67. package/dist/svelte/source/components/TiltShift.svelte +290 -0
  68. package/dist/svelte/source/components/Tint.svelte +287 -0
  69. package/dist/svelte/source/components/Tritone.svelte +287 -0
  70. package/dist/svelte/source/components/Twirl.svelte +287 -0
  71. package/dist/svelte/source/components/Vibrance.svelte +287 -0
  72. package/dist/svelte/source/components/VideoTexture.svelte +286 -0
  73. package/dist/svelte/source/components/WaveDistortion.svelte +289 -0
  74. package/dist/svelte/source/components/WebcamTexture.svelte +286 -0
  75. package/dist/svelte/source/components/ZoomBlur.svelte +287 -0
  76. package/dist/svelte/source/engine/Preview.svelte +320 -0
  77. package/dist/svelte/source/engine/PreviewRenderComponent.svelte +27 -0
  78. package/dist/svelte/source/engine/Shader.svelte +263 -0
  79. package/dist/svelte/source/index.js +77 -0
  80. package/package.json +2 -1
@@ -0,0 +1,320 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte'
3
+
4
+ import Shader from './Shader.svelte'
5
+ // <<< SHADERS_PREVIEW_MAP:START >>>
6
+ import AngularBlur from '../components/AngularBlur.svelte'
7
+ import Ascii from '../components/Ascii.svelte'
8
+ import Aurora from '../components/Aurora.svelte'
9
+ import Beam from '../components/Beam.svelte'
10
+ import Blob from '../components/Blob.svelte'
11
+ import Blur from '../components/Blur.svelte'
12
+ import BrightnessContrast from '../components/BrightnessContrast.svelte'
13
+ import Bulge from '../components/Bulge.svelte'
14
+ import CRTScreen from '../components/CRTScreen.svelte'
15
+ import ChannelBlur from '../components/ChannelBlur.svelte'
16
+ import Checkerboard from '../components/Checkerboard.svelte'
17
+ import ChromaFlow from '../components/ChromaFlow.svelte'
18
+ import ChromaticAberration from '../components/ChromaticAberration.svelte'
19
+ import Circle from '../components/Circle.svelte'
20
+ import ConcentricSpin from '../components/ConcentricSpin.svelte'
21
+ import ContourLines from '../components/ContourLines.svelte'
22
+ import CursorRipples from '../components/CursorRipples.svelte'
23
+ import CursorTrail from '../components/CursorTrail.svelte'
24
+ import DiffuseBlur from '../components/DiffuseBlur.svelte'
25
+ import Dither from '../components/Dither.svelte'
26
+ import DotGrid from '../components/DotGrid.svelte'
27
+ import Duotone from '../components/Duotone.svelte'
28
+ import FilmGrain from '../components/FilmGrain.svelte'
29
+ import FloatingParticles from '../components/FloatingParticles.svelte'
30
+ import FlowField from '../components/FlowField.svelte'
31
+ import GlassTiles from '../components/GlassTiles.svelte'
32
+ import Glitch from '../components/Glitch.svelte'
33
+ import Glow from '../components/Glow.svelte'
34
+ import Godrays from '../components/Godrays.svelte'
35
+ import Grayscale from '../components/Grayscale.svelte'
36
+ import Grid from '../components/Grid.svelte'
37
+ import GridDistortion from '../components/GridDistortion.svelte'
38
+ import Group from '../components/Group.svelte'
39
+ import Halftone from '../components/Halftone.svelte'
40
+ import HueShift from '../components/HueShift.svelte'
41
+ import ImageTexture from '../components/ImageTexture.svelte'
42
+ import Invert from '../components/Invert.svelte'
43
+ import Kaleidoscope from '../components/Kaleidoscope.svelte'
44
+ import LensFlare from '../components/LensFlare.svelte'
45
+ import LinearBlur from '../components/LinearBlur.svelte'
46
+ import LinearGradient from '../components/LinearGradient.svelte'
47
+ import Liquify from '../components/Liquify.svelte'
48
+ import Mirror from '../components/Mirror.svelte'
49
+ import Perspective from '../components/Perspective.svelte'
50
+ import Pixelate from '../components/Pixelate.svelte'
51
+ import Plasma from '../components/Plasma.svelte'
52
+ import PolarCoordinates from '../components/PolarCoordinates.svelte'
53
+ import Posterize from '../components/Posterize.svelte'
54
+ import ProgressiveBlur from '../components/ProgressiveBlur.svelte'
55
+ import RadialGradient from '../components/RadialGradient.svelte'
56
+ import RectangularCoordinates from '../components/RectangularCoordinates.svelte'
57
+ import Ripples from '../components/Ripples.svelte'
58
+ import Saturation from '../components/Saturation.svelte'
59
+ import Sharpness from '../components/Sharpness.svelte'
60
+ import Shatter from '../components/Shatter.svelte'
61
+ import SimplexNoise from '../components/SimplexNoise.svelte'
62
+ import SineWave from '../components/SineWave.svelte'
63
+ import SolidColor from '../components/SolidColor.svelte'
64
+ import Spherize from '../components/Spherize.svelte'
65
+ import Spiral from '../components/Spiral.svelte'
66
+ import Strands from '../components/Strands.svelte'
67
+ import Stretch from '../components/Stretch.svelte'
68
+ import Stripes from '../components/Stripes.svelte'
69
+ import StudioBackground from '../components/StudioBackground.svelte'
70
+ import Swirl from '../components/Swirl.svelte'
71
+ import TiltShift from '../components/TiltShift.svelte'
72
+ import Tint from '../components/Tint.svelte'
73
+ import Tritone from '../components/Tritone.svelte'
74
+ import Twirl from '../components/Twirl.svelte'
75
+ import Vibrance from '../components/Vibrance.svelte'
76
+ import VideoTexture from '../components/VideoTexture.svelte'
77
+ import WaveDistortion from '../components/WaveDistortion.svelte'
78
+ import WebcamTexture from '../components/WebcamTexture.svelte'
79
+ import ZoomBlur from '../components/ZoomBlur.svelte'
80
+
81
+ // --- Component Map ---
82
+
83
+ const componentMap: Record<string, any> = {
84
+ AngularBlur,
85
+ Ascii,
86
+ Aurora,
87
+ Beam,
88
+ Blob,
89
+ Blur,
90
+ BrightnessContrast,
91
+ Bulge,
92
+ CRTScreen,
93
+ ChannelBlur,
94
+ Checkerboard,
95
+ ChromaFlow,
96
+ ChromaticAberration,
97
+ Circle,
98
+ ConcentricSpin,
99
+ ContourLines,
100
+ CursorRipples,
101
+ CursorTrail,
102
+ DiffuseBlur,
103
+ Dither,
104
+ DotGrid,
105
+ Duotone,
106
+ FilmGrain,
107
+ FloatingParticles,
108
+ FlowField,
109
+ GlassTiles,
110
+ Glitch,
111
+ Glow,
112
+ Godrays,
113
+ Grayscale,
114
+ Grid,
115
+ GridDistortion,
116
+ Group,
117
+ Halftone,
118
+ HueShift,
119
+ ImageTexture,
120
+ Invert,
121
+ Kaleidoscope,
122
+ LensFlare,
123
+ LinearBlur,
124
+ LinearGradient,
125
+ Liquify,
126
+ Mirror,
127
+ Perspective,
128
+ Pixelate,
129
+ Plasma,
130
+ PolarCoordinates,
131
+ Posterize,
132
+ ProgressiveBlur,
133
+ RadialGradient,
134
+ RectangularCoordinates,
135
+ Ripples,
136
+ Saturation,
137
+ Sharpness,
138
+ Shatter,
139
+ SimplexNoise,
140
+ SineWave,
141
+ SolidColor,
142
+ Spherize,
143
+ Spiral,
144
+ Strands,
145
+ Stretch,
146
+ Stripes,
147
+ StudioBackground,
148
+ Swirl,
149
+ TiltShift,
150
+ Tint,
151
+ Tritone,
152
+ Twirl,
153
+ Vibrance,
154
+ VideoTexture,
155
+ WaveDistortion,
156
+ WebcamTexture,
157
+ ZoomBlur,
158
+ }
159
+ // <<< SHADERS_PREVIEW_MAP:END >>>
160
+
161
+ // --- Inlined Types ---
162
+
163
+ interface ShaderComponent {
164
+ type: string
165
+ id?: string
166
+ props?: Record<string, any>
167
+ children?: ShaderComponent[]
168
+ blendMode?: string
169
+ opacity?: number
170
+ renderOrder?: number
171
+ }
172
+
173
+ interface ShaderDefinition {
174
+ components: ShaderComponent[]
175
+ structureVersion?: number
176
+ colorSpace?: 'p3-linear' | 'srgb'
177
+ devicePreview?: string
178
+ }
179
+
180
+ // --- Preview Decode Logic ---
181
+ // No name mapping — preview definitions contain readable JSON.
182
+
183
+ function xorCrypt(data: Uint8Array, key: string): Uint8Array {
184
+ const keyBytes = new TextEncoder().encode(key)
185
+ const result = new Uint8Array(data.length)
186
+ for (let i = 0; i < data.length; i++) {
187
+ result[i] = data[i] ^ keyBytes[i % keyBytes.length]
188
+ }
189
+ return result
190
+ }
191
+
192
+ function decodePreviewDefinition(encoded: string, key: string): ShaderDefinition {
193
+ const binaryString = atob(encoded)
194
+ const encrypted = new Uint8Array(binaryString.length)
195
+ for (let i = 0; i < binaryString.length; i++) {
196
+ encrypted[i] = binaryString.charCodeAt(i)
197
+ }
198
+ const decrypted = xorCrypt(encrypted, key)
199
+ const json = new TextDecoder().decode(decrypted)
200
+ try {
201
+ return JSON.parse(json)
202
+ } catch {
203
+ throw new Error('Failed to decode shader definition: invalid data or incorrect key')
204
+ }
205
+ }
206
+
207
+ // Fetch from API and decode response
208
+ function fetchAndDecode(url: string, key: string): Promise<ShaderDefinition | null> {
209
+ return fetch(url)
210
+ .then(res => {
211
+ if (!res.ok) throw new Error(`Failed to fetch: ${res.status}`)
212
+ return res.json()
213
+ })
214
+ .then(data => {
215
+ const item = data.preset || data.shader
216
+ if (item?.definition && typeof item.definition === 'string') {
217
+ return decodePreviewDefinition(item.definition, key)
218
+ }
219
+ return null
220
+ })
221
+ .catch(err => {
222
+ console.error('[Shaders Preview] Failed to fetch preview:', err)
223
+ return null
224
+ })
225
+ }
226
+
227
+ // --- Props ---
228
+
229
+ export let shader: string | undefined = undefined
230
+ export let presetId: string | undefined = undefined
231
+ export let apiBaseUrl: string = 'https://shaders.com'
232
+ export let obfuscationKey: string = 'shaders-preview-key'
233
+ export let watermarkText: string = 'Unlock your Shaders Pro license'
234
+ export let watermarkLink: string = 'https://shaders.com/dashboard?pricing=true'
235
+ export let style: string | undefined = undefined
236
+
237
+ // --- Decode & Resolve ---
238
+
239
+ let resolvedDefinition: ShaderDefinition | null = null
240
+ let fetchedDefinition: ShaderDefinition | null = null
241
+ let watermarkHovered = false
242
+
243
+ // Fetch shader by token
244
+ $: if (shader) {
245
+ fetchedDefinition = null
246
+ fetchAndDecode(`${apiBaseUrl}/api/preview/shader/${shader}`, obfuscationKey)
247
+ .then(def => { fetchedDefinition = def })
248
+ } else if (!presetId) {
249
+ fetchedDefinition = null
250
+ }
251
+
252
+ // Fetch preset by ID
253
+ $: if (presetId) {
254
+ fetchedDefinition = null
255
+ fetchAndDecode(`${apiBaseUrl}/api/preview/preset/${presetId}`, obfuscationKey)
256
+ .then(def => { fetchedDefinition = def })
257
+ } else if (!shader) {
258
+ fetchedDefinition = null
259
+ }
260
+
261
+ $: resolvedDefinition = fetchedDefinition ?? null
262
+
263
+ // --- Licensing Warning ---
264
+
265
+ onMount(() => {
266
+ console.warn(
267
+ '[Shaders] Preview component is intended for use with a Shaders license. ' +
268
+ 'Visit https://shaders.com for more information.'
269
+ )
270
+ })
271
+
272
+ </script>
273
+
274
+ <script lang="ts" context="module">
275
+ // Recursive component for rendering nested shader components
276
+ import { default as RenderComponent } from './PreviewRenderComponent.svelte'
277
+ </script>
278
+
279
+ {#if resolvedDefinition}
280
+ <div class="shaders-preview" style="position: relative; width: 100%; height: 100%;{style ? ' ' + style : ''}" {...$$restProps}>
281
+ <Shader
282
+ colorSpace={resolvedDefinition.colorSpace || 'p3-linear'}
283
+ isPreview={true}
284
+ enablePerformanceTracking={true}
285
+ style="width: 100%; height: 100%;"
286
+ >
287
+ {#each resolvedDefinition.components as config, index (config.id || `root_${index}_v${resolvedDefinition.structureVersion || 0}`)}
288
+ <RenderComponent
289
+ config={{ ...config, renderOrder: config.renderOrder ?? index }}
290
+ {componentMap}
291
+ structureVersion={resolvedDefinition.structureVersion}
292
+ />
293
+ {/each}
294
+ </Shader>
295
+ {#if watermarkText}
296
+ <a
297
+ href={watermarkLink}
298
+ target="_blank"
299
+ rel="noopener noreferrer"
300
+ style="
301
+ position: absolute;
302
+ bottom: 8px;
303
+ right: 12px;
304
+ font-size: 11px;
305
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
306
+ color: {watermarkHovered ? 'rgba(255, 255, 255, 0.8)' : 'rgba(255, 255, 255, 0.5)'};
307
+ text-decoration: none;
308
+ pointer-events: auto;
309
+ z-index: 10;
310
+ text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
311
+ transition: color 0.2s ease;
312
+ "
313
+ on:mouseenter={() => watermarkHovered = true}
314
+ on:mouseleave={() => watermarkHovered = false}
315
+ >
316
+ {watermarkText}
317
+ </a>
318
+ {/if}
319
+ </div>
320
+ {/if}
@@ -0,0 +1,27 @@
1
+ <script lang="ts">
2
+ export let config: any
3
+ export let componentMap: Record<string, any>
4
+ export let structureVersion: number | undefined = undefined
5
+
6
+ $: Component = componentMap[config.type]
7
+ $: componentProps = config.props ? { ...config.props } : {}
8
+ </script>
9
+
10
+ {#if Component}
11
+ <svelte:component
12
+ this={Component}
13
+ id={config.id}
14
+ renderOrder={config.renderOrder}
15
+ {...componentProps}
16
+ >
17
+ {#if config.children}
18
+ {#each config.children as child, index (child.id || `child_${index}_v${structureVersion || 0}`)}
19
+ <svelte:self
20
+ config={{ ...child, renderOrder: child.renderOrder ?? index }}
21
+ {componentMap}
22
+ {structureVersion}
23
+ />
24
+ {/each}
25
+ {/if}
26
+ </svelte:component>
27
+ {/if}
@@ -0,0 +1,263 @@
1
+ <script lang="ts">
2
+ import { setContext, onMount, onDestroy } from 'svelte';
3
+ import { shaderRenderer } from '../../../core/index.js';
4
+ import { vec4 } from 'three/tsl';
5
+ import type { UniformsMap, BlendMode, NodeMetadata } from '../../../core/index.js';
6
+ import { shouldCollectTelemetry, isExternalUser, startTelemetry } from '../../../core/telemetry/index.js';
7
+ import { setColorSpaceMode } from '../../../core/utilities/transformations/index.js';
8
+
9
+ declare const __SHADERS_VERSION__: string;
10
+
11
+ interface Props {
12
+ disableTelemetry?: boolean;
13
+ colorSpace?: 'p3-linear' | 'srgb';
14
+ isPreview?: boolean;
15
+ children?: import('svelte').Snippet;
16
+ [key: string]: any;
17
+ }
18
+
19
+ const { disableTelemetry = false, colorSpace = 'p3-linear', isPreview = false, children, ...rest }: Props = $props();
20
+
21
+ // DOM references to the container and canvas
22
+ let containerRef: HTMLDivElement;
23
+ let canvasRef: HTMLCanvasElement;
24
+
25
+ // SSR guard — renderer and children are deferred until mount
26
+ let mounted = $state(false);
27
+
28
+ // Unique ID for this root component
29
+ const rootId = 'shader-root-' + Math.random().toString(36).substring(7);
30
+
31
+ // Renderer instance — created in onMount (deferred for SSR compatibility)
32
+ let rendererInstance: ReturnType<typeof shaderRenderer> | null = null;
33
+
34
+ // Telemetry collector reference for cleanup
35
+ let telemetryCollector: any = null;
36
+ let telemetryStartTimeout: number | null = null;
37
+ let shouldSendTelemetry: boolean | null = null;
38
+
39
+ // Set context for child components - provide parent ID
40
+ setContext('shaderParentId', rootId);
41
+
42
+ // Provide color space to child components (function getter for reactivity)
43
+ setContext('shaderColorSpace', () => colorSpace);
44
+
45
+ // Provide node registration function for child components
46
+ // Callbacks capture `rendererInstance` by reference — they see the live value after onMount sets it
47
+ setContext('shaderNodeRegister', (id: string, fragmentNodeFunc: any, parentId: string | null, metadata: any, uniforms: any = null, componentDef: any = null) => {
48
+ if (!rendererInstance) return
49
+ // If fragmentNodeFunc is null, the component is being unmounted, so remove it
50
+ if (fragmentNodeFunc === null) {
51
+ rendererInstance.removeNode(id);
52
+ } else {
53
+ rendererInstance.registerNode(id, fragmentNodeFunc, parentId, metadata, uniforms, componentDef);
54
+ }
55
+ });
56
+
57
+ // Provide optimized uniform update function
58
+ setContext('shaderUniformUpdate', (nodeId: string, uniformName: string, value: any) => {
59
+ if (!rendererInstance) return
60
+ rendererInstance.updateUniformValue(nodeId, uniformName, value);
61
+ });
62
+
63
+ // Provide optimized metadata update function
64
+ setContext('shaderMetadataUpdate', (nodeId: string, metadata: any) => {
65
+ if (!rendererInstance) return
66
+ rendererInstance.updateNodeMetadata(nodeId, metadata);
67
+ });
68
+
69
+ // Track visibility state
70
+ let wasVisible = false;
71
+ let visibilityObserver: IntersectionObserver | null = null;
72
+
73
+ // Wait for active rendering before starting telemetry collection
74
+ const startTelemetryWhenReady = () => {
75
+ const checkRendering = () => {
76
+ if (!rendererInstance) return
77
+ const stats = rendererInstance.getPerformanceStats();
78
+ if (stats.fps > 0) {
79
+ const version = typeof __SHADERS_VERSION__ !== 'undefined' ? __SHADERS_VERSION__ : 'unknown';
80
+ telemetryCollector = startTelemetry(
81
+ rendererInstance,
82
+ version,
83
+ disableTelemetry,
84
+ isPreview
85
+ );
86
+ if (telemetryCollector) {
87
+ telemetryCollector.start();
88
+ }
89
+ telemetryStartTimeout = null;
90
+ } else {
91
+ telemetryStartTimeout = window.setTimeout(checkRendering, 500);
92
+ }
93
+ };
94
+
95
+ telemetryStartTimeout = window.setTimeout(checkRendering, 500);
96
+ };
97
+
98
+ // Function to initialize renderer with visibility check
99
+ const initializeRenderer = async () => {
100
+ if (!canvasRef || !rendererInstance) return;
101
+
102
+ try {
103
+ // Check if renderer is already initialized to avoid double initialization
104
+ if (!rendererInstance.isInitialized()) {
105
+ await rendererInstance.initialize({
106
+ canvas: canvasRef,
107
+ colorSpace: colorSpace,
108
+ });
109
+ }
110
+
111
+ // Register the root node
112
+ rendererInstance.registerNode(
113
+ rootId,
114
+ ({ childNode }) => childNode || vec4(0, 0, 0, 0), // Root node that passes through children
115
+ null, // No parent (this is the root)
116
+ null, // No metadata to pass
117
+ {}
118
+ );
119
+
120
+ // Compute sampling decision once (includes random sampling roll)
121
+ if (shouldSendTelemetry === null) {
122
+ shouldSendTelemetry = isExternalUser() && shouldCollectTelemetry(disableTelemetry, isPreview);
123
+ }
124
+
125
+ if (shouldSendTelemetry && !telemetryCollector) {
126
+ startTelemetryWhenReady();
127
+ }
128
+
129
+ } catch (err) {
130
+ console.error('[Shader] Initialization failed:', err);
131
+ throw err;
132
+ }
133
+ };
134
+
135
+ // Setup visibility observer for container hide/show detection
136
+ const setupVisibilityObserver = () => {
137
+ if (!containerRef || visibilityObserver) return;
138
+
139
+ visibilityObserver = new IntersectionObserver((entries) => {
140
+ const entry = entries[0];
141
+ if (!entry) return;
142
+
143
+ const rect = containerRef?.getBoundingClientRect();
144
+ const isCurrentlyVisible = entry.isIntersecting && rect && rect.width > 0 && rect.height > 0;
145
+
146
+ if (isCurrentlyVisible && !wasVisible) {
147
+ // Canvas became visible - resume animation
148
+ if (rendererInstance?.isInitialized()) {
149
+ rendererInstance.startAnimation();
150
+ // Start telemetry if conditions are met and not already started
151
+ if (shouldSendTelemetry && !telemetryCollector && !telemetryStartTimeout) {
152
+ startTelemetryWhenReady();
153
+ }
154
+ } else {
155
+ // First time visible, need to initialize
156
+ initializeRenderer().catch(console.error);
157
+ }
158
+ wasVisible = true;
159
+ } else if (!isCurrentlyVisible && wasVisible) {
160
+ // Canvas became hidden - pause animation but keep renderer alive
161
+ rendererInstance?.stopAnimation();
162
+ wasVisible = false;
163
+ }
164
+ }, { threshold: 0 });
165
+
166
+ visibilityObserver.observe(containerRef);
167
+ };
168
+
169
+ // Initialize renderer on mount - with visibility awareness
170
+ onMount(async () => {
171
+ // Create the renderer instance (deferred from module scope for SSR compatibility)
172
+ rendererInstance = shaderRenderer();
173
+ mounted = true;
174
+
175
+ // Wait for Svelte to render the canvas + children before proceeding
176
+ await new Promise((resolve) => requestAnimationFrame(resolve));
177
+
178
+ if (!canvasRef || !containerRef) {
179
+ console.error('Canvas or container ref is null in Shader onMount');
180
+ return;
181
+ }
182
+
183
+ // Check if container is visible on mount
184
+ const rect = containerRef.getBoundingClientRect();
185
+ const isVisible = rect.width > 0 && rect.height > 0;
186
+
187
+ if (isVisible) {
188
+ // Container is visible, initialize immediately
189
+ await initializeRenderer();
190
+ wasVisible = true;
191
+ } else {
192
+ // Container is hidden, set up observer for when it becomes visible
193
+ wasVisible = false;
194
+ }
195
+
196
+ // Always set up observer to handle show/hide cycles
197
+ setupVisibilityObserver();
198
+ });
199
+
200
+ // Cleanup on component destroy
201
+ onDestroy(() => {
202
+ // Stop telemetry collection if active
203
+ if (telemetryCollector) {
204
+ telemetryCollector.stop();
205
+ telemetryCollector = null;
206
+ }
207
+
208
+ // Clear telemetry start timeout if pending
209
+ if (telemetryStartTimeout !== null) {
210
+ clearTimeout(telemetryStartTimeout);
211
+ telemetryStartTimeout = null;
212
+ }
213
+
214
+ // Clean up visibility observer
215
+ if (visibilityObserver) {
216
+ visibilityObserver.disconnect();
217
+ visibilityObserver = null;
218
+ }
219
+
220
+ // Only cleanup if renderer was initialized
221
+ if (rendererInstance?.isInitialized()) {
222
+ try {
223
+ rendererInstance.cleanup();
224
+ } catch (err) {
225
+ console.warn('[Shader] Error during cleanup:', err);
226
+ }
227
+ }
228
+ });
229
+
230
+ // Watch for colorSpace changes and update the renderer
231
+ // Skip the initial execution since colorSpace is set during initialization
232
+ let isFirstEffect = true;
233
+ $effect(() => {
234
+ // Access colorSpace to make it reactive
235
+ const currentColorSpace = colorSpace;
236
+
237
+ if (isFirstEffect) {
238
+ isFirstEffect = false;
239
+ return;
240
+ }
241
+
242
+ if (rendererInstance?.isInitialized()) {
243
+ // Update the global color space mode
244
+ setColorSpaceMode(currentColorSpace);
245
+
246
+ // Force re-initialization to apply color space changes
247
+ rendererInstance.cleanup();
248
+ initializeRenderer().catch(console.error);
249
+ }
250
+ });
251
+
252
+ </script>
253
+
254
+ <div class="shader" bind:this={containerRef} {...rest}>
255
+ {#if mounted}
256
+ <canvas
257
+ data-renderer="shaders"
258
+ bind:this={canvasRef}
259
+ style="width: 100%; height: 100%; display: block;"
260
+ ></canvas>
261
+ {@render children?.()}
262
+ {/if}
263
+ </div>
@@ -0,0 +1,77 @@
1
+ export { default as AngularBlur } from './components/AngularBlur.svelte';
2
+ export { default as Ascii } from './components/Ascii.svelte';
3
+ export { default as Aurora } from './components/Aurora.svelte';
4
+ export { default as Beam } from './components/Beam.svelte';
5
+ export { default as Blob } from './components/Blob.svelte';
6
+ export { default as Blur } from './components/Blur.svelte';
7
+ export { default as BrightnessContrast } from './components/BrightnessContrast.svelte';
8
+ export { default as Bulge } from './components/Bulge.svelte';
9
+ export { default as CRTScreen } from './components/CRTScreen.svelte';
10
+ export { default as ChannelBlur } from './components/ChannelBlur.svelte';
11
+ export { default as Checkerboard } from './components/Checkerboard.svelte';
12
+ export { default as ChromaFlow } from './components/ChromaFlow.svelte';
13
+ export { default as ChromaticAberration } from './components/ChromaticAberration.svelte';
14
+ export { default as Circle } from './components/Circle.svelte';
15
+ export { default as ConcentricSpin } from './components/ConcentricSpin.svelte';
16
+ export { default as ContourLines } from './components/ContourLines.svelte';
17
+ export { default as CursorRipples } from './components/CursorRipples.svelte';
18
+ export { default as CursorTrail } from './components/CursorTrail.svelte';
19
+ export { default as DiffuseBlur } from './components/DiffuseBlur.svelte';
20
+ export { default as Dither } from './components/Dither.svelte';
21
+ export { default as DotGrid } from './components/DotGrid.svelte';
22
+ export { default as Duotone } from './components/Duotone.svelte';
23
+ export { default as FilmGrain } from './components/FilmGrain.svelte';
24
+ export { default as FloatingParticles } from './components/FloatingParticles.svelte';
25
+ export { default as FlowField } from './components/FlowField.svelte';
26
+ export { default as GlassTiles } from './components/GlassTiles.svelte';
27
+ export { default as Glitch } from './components/Glitch.svelte';
28
+ export { default as Glow } from './components/Glow.svelte';
29
+ export { default as Godrays } from './components/Godrays.svelte';
30
+ export { default as Grayscale } from './components/Grayscale.svelte';
31
+ export { default as Grid } from './components/Grid.svelte';
32
+ export { default as GridDistortion } from './components/GridDistortion.svelte';
33
+ export { default as Group } from './components/Group.svelte';
34
+ export { default as Halftone } from './components/Halftone.svelte';
35
+ export { default as HueShift } from './components/HueShift.svelte';
36
+ export { default as ImageTexture } from './components/ImageTexture.svelte';
37
+ export { default as Invert } from './components/Invert.svelte';
38
+ export { default as Kaleidoscope } from './components/Kaleidoscope.svelte';
39
+ export { default as LensFlare } from './components/LensFlare.svelte';
40
+ export { default as LinearBlur } from './components/LinearBlur.svelte';
41
+ export { default as LinearGradient } from './components/LinearGradient.svelte';
42
+ export { default as Liquify } from './components/Liquify.svelte';
43
+ export { default as Mirror } from './components/Mirror.svelte';
44
+ export { default as Perspective } from './components/Perspective.svelte';
45
+ export { default as Pixelate } from './components/Pixelate.svelte';
46
+ export { default as Plasma } from './components/Plasma.svelte';
47
+ export { default as PolarCoordinates } from './components/PolarCoordinates.svelte';
48
+ export { default as Posterize } from './components/Posterize.svelte';
49
+ export { default as ProgressiveBlur } from './components/ProgressiveBlur.svelte';
50
+ export { default as RadialGradient } from './components/RadialGradient.svelte';
51
+ export { default as RectangularCoordinates } from './components/RectangularCoordinates.svelte';
52
+ export { default as Ripples } from './components/Ripples.svelte';
53
+ export { default as Saturation } from './components/Saturation.svelte';
54
+ export { default as Sharpness } from './components/Sharpness.svelte';
55
+ export { default as Shatter } from './components/Shatter.svelte';
56
+ export { default as SimplexNoise } from './components/SimplexNoise.svelte';
57
+ export { default as SineWave } from './components/SineWave.svelte';
58
+ export { default as SolidColor } from './components/SolidColor.svelte';
59
+ export { default as Spherize } from './components/Spherize.svelte';
60
+ export { default as Spiral } from './components/Spiral.svelte';
61
+ export { default as Strands } from './components/Strands.svelte';
62
+ export { default as Stretch } from './components/Stretch.svelte';
63
+ export { default as Stripes } from './components/Stripes.svelte';
64
+ export { default as StudioBackground } from './components/StudioBackground.svelte';
65
+ export { default as Swirl } from './components/Swirl.svelte';
66
+ export { default as TiltShift } from './components/TiltShift.svelte';
67
+ export { default as Tint } from './components/Tint.svelte';
68
+ export { default as Tritone } from './components/Tritone.svelte';
69
+ export { default as Twirl } from './components/Twirl.svelte';
70
+ export { default as Vibrance } from './components/Vibrance.svelte';
71
+ export { default as VideoTexture } from './components/VideoTexture.svelte';
72
+ export { default as WaveDistortion } from './components/WaveDistortion.svelte';
73
+ export { default as WebcamTexture } from './components/WebcamTexture.svelte';
74
+ export { default as ZoomBlur } from './components/ZoomBlur.svelte';
75
+ export { default as Shader } from './engine/Shader.svelte';
76
+ export { default as Preview } from './engine/Preview.svelte';
77
+ export { generatePresetCode } from '../utils/generatePresetCode.js';