{"version":3,"file":"index.cjs","sources":["../src/lib/utils/base64.ts","../src/lib/utils/fmt.ts","../src/lib/utils/logger.ts","../src/lib/utils/math.ts","../src/lib/utils/quickselect.ts","../src/lib/utils/rotate-sh.ts","../src/lib/utils/text-renderer.ts","../lib/webp.mjs","../src/lib/utils/webp-codec.ts","../src/lib/data-table/data-table.ts","../src/lib/data-table/transform.ts","../src/lib/data-table/combine.ts","../src/lib/gpu/gpu-edge-cost.ts","../src/lib/spatial/kd-tree.ts","../src/lib/gpu/gpu-knn.ts","../src/lib/spatial/radix-sort.ts","../src/lib/data-table/decimate.ts","../src/lib/render/config.ts","../src/lib/data-table/gaussian-aabb.ts","../src/lib/data-table/gaussian-eval.ts","../src/lib/data-table/morton-order.ts","../src/lib/data-table/sh-bands.ts","../src/lib/data-table/summary.ts","../src/lib/io/read/file-system.ts","../src/lib/io/read/buffered-read-stream.ts","../node_modules/pathe/dist/shared/pathe.M-eThtNZ.mjs","../src/lib/io/read/memory-file-system.ts","../src/lib/io/read/url-file-system.ts","../src/lib/io/read/zip-file-system.ts","../src/lib/readers/read-ksplat.ts","../src/lib/readers/read-lcc.ts","../src/lib/readers/read-mjs.ts","../src/lib/readers/decompress-ply.ts","../src/lib/readers/read-ply.ts","../src/lib/readers/read-sog-v1.ts","../src/lib/readers/read-sog.ts","../src/lib/readers/read-splat.ts","../src/lib/spz-module.ts","../src/lib/readers/read-spz.ts","../src/lib/read.ts","../src/lib/writers/utils.ts","../src/lib/writers/compressed-chunk.ts","../src/lib/version.ts","../src/lib/writers/write-compressed-ply.ts","../src/lib/writers/write-csv.ts","../src/lib/writers/write-glb.ts","../node_modules/@playcanvas/supersplat-viewer/dist/index.js","../src/lib/io/write/write-helpers.ts","../src/lib/io/write/memory-file-system.ts","../src/lib/io/write/crc.ts","../src/lib/io/write/zip-file-system.ts","../src/lib/spatial/b-tree.ts","../src/lib/spatial/gaussian-bvh.ts","../src/lib/gpu/gpu-clustering.ts","../src/lib/gpu/shaders/dilation.ts","../src/lib/gpu/gpu-dilation.ts","../src/lib/gpu/shaders/chunks/constants.ts","../src/lib/gpu/shaders/chunks/covariance-3d.ts","../src/lib/gpu/shaders/chunks/jacobian-equirect.ts","../src/lib/gpu/shaders/chunks/jacobian-pinhole.ts","../src/lib/gpu/shaders/chunks/projection-equirect.ts","../src/lib/gpu/shaders/chunks/projection-pinhole.ts","../src/lib/gpu/shaders/chunks/quat-rotation.ts","../src/lib/gpu/shaders/chunks/sh-band-1.ts","../src/lib/gpu/shaders/chunks/sh-band-2.ts","../src/lib/gpu/shaders/chunks/sh-band-3.ts","../src/lib/gpu/shaders/chunks/tile-aabb-equirect.ts","../src/lib/gpu/shaders/chunks/tile-aabb-pinhole.ts","../src/lib/gpu/shaders/chunks/tile-walk-equirect.ts","../src/lib/gpu/shaders/chunks/tile-walk-pinhole.ts","../src/lib/gpu/shaders/finalize.ts","../src/lib/gpu/shaders/find-boundaries.ts","../src/lib/gpu/shaders/init-tile-offsets.ts","../src/lib/gpu/shaders/prefix-sum.ts","../src/lib/gpu/shaders/prepare-indirect.ts","../src/lib/gpu/shaders/project.ts","../src/lib/gpu/shaders/rasterize-binned.ts","../src/lib/gpu/shaders/tile-bin-emit-pairs.ts","../src/lib/gpu/shaders/uniforms.ts","../src/lib/gpu/gpu-splat-rasterizer.ts","../src/lib/gpu/gpu-voxelization.ts","../src/lib/spatial/k-means.ts","../src/lib/spatial/quantize-1d.ts","../src/lib/writers/write-sog.ts","../src/lib/writers/write-html.ts","../src/lib/render/camera.ts","../src/lib/render/preprocess.ts","../src/lib/render/raster-pass.ts","../src/lib/writers/write-image.ts","../src/lib/writers/write-lod.ts","../src/lib/writers/write-ply.ts","../src/lib/writers/write-spz.ts","../src/lib/voxel/morton.ts","../src/lib/voxel/block-mask-buffer.ts","../src/lib/voxel/block-mask-map.ts","../src/lib/voxel/sparse-voxel-grid.ts","../src/lib/mesh/marching-cubes.ts","../src/lib/mesh/coplanar-merge.ts","../src/lib/mesh/voxel-faces.ts","../src/lib/writers/collision-glb.ts","../src/lib/writers/sparse-octree.ts","../src/lib/voxel/block-cleanup.ts","../src/lib/voxel/voxelize.ts","../src/lib/voxel/filter-pipeline.ts","../src/lib/voxel/flood-fill.ts","../src/lib/voxel/voxel-query.ts","../src/lib/voxel/filter-cluster.ts","../src/lib/voxel/filter-floaters.ts","../src/lib/voxel/dilation.ts","../src/lib/voxel/grid-ops.ts","../src/lib/voxel/carve.ts","../src/lib/voxel/fill-exterior.ts","../src/lib/voxel/fill-floor.ts","../src/lib/writers/write-voxel.ts","../src/lib/write.ts","../src/lib/process.ts"],"sourcesContent":["const toBase64 = (bytes: Uint8Array): string => {\n    // Node.js environment\n    if (typeof Buffer !== 'undefined') {\n        return Buffer.from(bytes).toString('base64');\n    }\n\n    // Browser environment - chunk to avoid call stack limits\n    let binary = '';\n    const chunkSize = 0x8000; // 32KB chunks\n    for (let i = 0; i < bytes.length; i += chunkSize) {\n        const chunk = bytes.subarray(i, i + chunkSize);\n        binary += String.fromCharCode(...chunk);\n    }\n    return btoa(binary);\n};\n\nexport { toBase64 };\n","/**\n * Format a duration in milliseconds as a human-readable string.\n *\n * - Sub-minute durations render in seconds (e.g. `1.234s`).\n * - Sub-hour durations render as `MmS.SSSs`.\n * - Otherwise as `HhMmS.SSSs`.\n *\n * @param ms - The duration in milliseconds.\n * @returns The formatted string.\n */\nconst fmtTime = (ms: number): string => {\n    if (!Number.isFinite(ms) || ms < 0) return `${ms}ms`;\n    if (ms < 60_000) return `${(ms / 1000).toFixed(3)}s`;\n\n    const h = Math.floor(ms / 3_600_000);\n    const m = Math.floor((ms % 3_600_000) / 60_000);\n    const s = ((ms % 60_000) / 1000).toFixed(3);\n\n    return h > 0 ? `${h}h${m}m${s}s` : `${m}m${s}s`;\n};\n\n/**\n * Format a byte count using binary (1024-based) units.\n *\n * @param n - The number of bytes.\n * @returns The formatted string (e.g. `1.5MB`).\n */\nconst fmtBytes = (n: number): string => {\n    if (!Number.isFinite(n) || n < 0) return `${n}B`;\n    if (n < 1024) return `${n}B`;\n    if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)}KB`;\n    if (n < 1024 * 1024 * 1024) return `${(n / (1024 * 1024)).toFixed(1)}MB`;\n    return `${(n / (1024 * 1024 * 1024)).toFixed(2)}GB`;\n};\n\n/**\n * Format a distance in metres as a human-readable string, picking the most\n * appropriate unit (mm/cm/m/km).\n *\n * @param m - The distance in metres.\n * @returns The formatted string.\n */\nconst fmtDistance = (m: number): string => {\n    if (!Number.isFinite(m)) return `${m}m`;\n    const abs = Math.abs(m);\n    if (abs === 0) return '0m';\n    if (abs < 0.01) return `${+(m * 1000).toPrecision(3)}mm`;\n    if (abs < 1) return `${+(m * 100).toPrecision(3)}cm`;\n    if (abs < 1000) return `${+m.toPrecision(3)}m`;\n    return `${+(m / 1000).toPrecision(3)}km`;\n};\n\n/**\n * Format a count using SI suffixes (K/M/B/T) above 1000.\n *\n * @param n - The count to format.\n * @returns The formatted string.\n */\nconst fmtCount = (n: number): string => {\n    if (!Number.isFinite(n)) return `${n}`;\n    const abs = Math.abs(n);\n    if (abs < 1000) return `${n}`;\n    if (abs < 1e6) return `${+(n / 1e3).toPrecision(3)}K`;\n    if (abs < 1e9) return `${+(n / 1e6).toPrecision(3)}M`;\n    if (abs < 1e12) return `${+(n / 1e9).toPrecision(3)}B`;\n    return `${+(n / 1e12).toPrecision(3)}T`;\n};\n\nexport { fmtBytes, fmtCount, fmtDistance, fmtTime };\n","/**\n * Verbosity level controlling which messages reach the renderer.\n *\n * - `quiet`   - errors and warnings only.\n * - `normal`  - tasks, bars, info, warn, error (default).\n * - `verbose` - normal + debug messages.\n */\ntype Verbosity = 'quiet' | 'normal' | 'verbose';\n\n/** Severity tag for free-form messages (ordered descending by severity). */\ntype MessageKind = 'error' | 'warn' | 'info' | 'debug';\n\n/**\n * Semantic event delivered to a {@link Renderer}. Renderers can filter, format\n * and display these as they wish.\n *\n * `scopeStart` / `scopeEnd` represent the open/close of a {@link Group}.\n * They carry optional `index` / `total` fields when the scope is part of a\n * numbered series, which renderers can use to switch to a `[N/T] name` style.\n *\n * `barStart` / `barTick` / `barEnd` represent a determinate progress bar.\n * The bar's `name` is repeated on every event so the renderer can keep its\n * label stable across in-place updates while tracking progress via `current`\n * and `total`.\n *\n * `output` is the pipeable channel: each event represents a single logical\n * unit of output (typically one line - or a multi-line block treated as a\n * unit) that the renderer is expected to terminate with a newline. Callers\n * should not include a trailing `\\n` themselves.\n */\ntype LogEvent =\n    | { kind: 'scopeStart'; depth: number; name: string; index?: number; total?: number }\n    | { kind: 'scopeEnd'; depth: number; name: string; durationMs: number; failed?: boolean; index?: number; total?: number }\n    | { kind: 'barStart'; depth: number; name: string; total: number }\n    | { kind: 'barTick'; depth: number; name: string; current: number; total: number }\n    | { kind: 'barEnd'; depth: number; name: string; durationMs: number; current: number; total: number; failed?: boolean }\n    | { kind: 'message'; depth: number; level: MessageKind; text: string }\n    | { kind: 'output'; text: string };\n\n/**\n * Renderer interface. Receives the full stream of semantic lifecycle\n * events ({@link LogEvent}) and decides how to display them. The core\n * does not filter scope/bar events by verbosity, so renderers see a\n * faithful record of every scope open/close and bar progress update -\n * embedders consuming the event stream can rely on this for progress\n * UIs that must close themselves on completion. Visibility decisions\n * (e.g. hiding successful `scopeEnd` footers at non-`verbose`\n * verbosity) are the renderer's responsibility; {@link logger.getVerbosity}\n * is available to consult.\n *\n * `message` events for `info`, `warn` and `debug` are gated by verbosity\n * at the façade (see {@link LoggerCore.isLevelVisible}) before reaching\n * the renderer; `error` is always delivered.\n */\ninterface Renderer {\n    /**\n     * Handle a log event.\n     * @param event - The event to render.\n     */\n    handle(event: LogEvent): void;\n}\n\n/**\n * Determinate progress bar handle. Closed explicitly via `end()`, or\n * implicitly when an enclosing {@link Group}'s `end()` (or a\n * {@link Logger.unwindAll}) pops it as part of cleanup.\n *\n * Carries a `[Symbol.dispose]` slot directly (rather than extending the\n * built-in `Disposable` lib type) so the published `.d.ts` stays free of\n * any reference to the `Disposable` interface. `Symbol.dispose` itself is\n * still a TS 5.2+ / `esnext.disposable` (or `es2024.disposable`) lib\n * symbol, so consumers compiling against these declarations need that\n * lib enabled (or `skipLibCheck: true`). Callers on TS 5.2+ / Node 20+\n * can adopt `using bar = logger.bar(...)` because `using` only requires\n * the `[Symbol.dispose]` shape structurally.\n */\ninterface Bar {\n    /**\n     * Advance the bar by `n` ticks.\n     * @param n - Number of ticks to advance (default 1).\n     */\n    tick(n?: number): void;\n    /**\n     * Set the bar's absolute progress. Clamped to `[0, total]`. Suppresses\n     * a `barTick` event when the value is unchanged.\n     * @param current - Absolute progress value.\n     */\n    update(current: number): void;\n    /**\n     * Close the bar and emit final timing.\n     */\n    end(): void;\n    /** Dispose hook so `using` syntax closes the bar on scope exit. */\n    [Symbol.dispose](): void;\n}\n\n/**\n * Named, timed scope returned from {@link Logger.group}. Manages the scope's\n * lifecycle only - free-form messages, nested groups and bars are emitted via\n * the global `logger` (they auto-indent under whatever is on top of the\n * active-scope stack).\n *\n * Open scopes with `logger.group(name)` and close them with `sub.end()` after\n * the body. Embedders that catch their own exceptions (rather than letting\n * them propagate to a `logger.error()` call) should call\n * {@link Logger.unwindAll} from their catch to close any scopes/bars left\n * dangling on the stack.\n *\n * Carries a `[Symbol.dispose]` slot directly (rather than extending the\n * built-in `Disposable` lib type) so the published `.d.ts` stays free of\n * any reference to the `Disposable` interface. `Symbol.dispose` itself is\n * still a TS 5.2+ / `esnext.disposable` (or `es2024.disposable`) lib\n * symbol, so consumers compiling against these declarations need that\n * lib enabled (or `skipLibCheck: true`). Callers on TS 5.2+ / Node 20+\n * can adopt `using g = logger.group(...)` because `using` only requires\n * the `[Symbol.dispose]` shape structurally.\n */\ninterface Group {\n    /**\n     * Close the group, popping anything still open above it on the stack\n     * (defensively handles forgotten inner scopes) and emit the timing event.\n     */\n    end(): void;\n    /** Dispose hook so `using` syntax closes the group on scope exit. */\n    [Symbol.dispose](): void;\n}\n\n/**\n * Internal node tracked on the active-scope stack. Both kinds carry their own\n * depth and start time; `group` may additionally carry `index` / `total` so a\n * numbered series can re-emit the same numbering on close.\n */\ntype Scope =\n    | { kind: 'group'; name: string; depth: number; start: number; index?: number; total?: number }\n    | { kind: 'bar'; name: string; depth: number; start: number; total: number; current: number };\n\nconst now = (): number => {\n    if (typeof performance !== 'undefined' && typeof performance.now === 'function') {\n        return performance.now();\n    }\n    return Date.now();\n};\n\nconst fmtArgs = (args: any[]): string => {\n    return args.map((a) => {\n        if (a instanceof Error) return a.stack ?? a.message;\n        if (typeof a === 'string') return a;\n        if (typeof a === 'number' || typeof a === 'boolean' || a == null) return String(a);\n        try {\n            return JSON.stringify(a);\n        } catch {\n            return String(a);\n        }\n    }).join(' ');\n};\n\n/**\n * Default no-op renderer. Used when no other renderer is installed (e.g. in\n * library/embedded contexts where the host wants to consume `LogEvent`s\n * directly via {@link Logger.setRenderer} but hasn't done so yet). Drops\n * every event silently.\n */\nclass NullRenderer implements Renderer {\n    handle(_event: LogEvent): void { /* no-op */ }\n}\n\nconst verbosityRank: Record<Verbosity, number> = {\n    quiet: 0,\n    normal: 1,\n    verbose: 2\n};\n\nconst messageMinVerbosity: Record<MessageKind, Verbosity> = {\n    error: 'quiet',\n    warn: 'quiet',\n    info: 'normal',\n    debug: 'verbose'\n};\n\n/**\n * Active-scope manager and message router. The single shared instance lives\n * inside this module; the public `logger` surface is a thin façade over it.\n */\nclass LoggerCore {\n    /** Stack of currently-open scopes (innermost last). */\n    readonly stack: Scope[] = [];\n\n    private renderer: Renderer = new NullRenderer();\n\n    private verbosity: Verbosity = 'normal';\n\n    setRenderer(r: Renderer): void {\n        this.renderer = r;\n    }\n\n    setVerbosity(v: Verbosity): void {\n        this.verbosity = v;\n    }\n\n    getVerbosity(): Verbosity {\n        return this.verbosity;\n    }\n\n    /**\n     * Whether a message at `level` would be emitted at the current\n     * verbosity. Primary use: the `logger` façade calls this before\n     * formatting arguments so filtered `info`/`warn`/`debug` calls don't\n     * allocate the joined string that {@link emit} would only throw away.\n     *\n     * @param level - The message level to test.\n     * @returns `true` if a message at `level` would reach the renderer.\n     */\n    isLevelVisible(level: MessageKind): boolean {\n        return verbosityRank[this.verbosity] >= verbosityRank[messageMinVerbosity[level]];\n    }\n\n    /**\n     * Hand the event to the renderer. Lifecycle events (`scopeStart`,\n     * `scopeEnd`, `barStart`, `barTick`, `barEnd`) and `output` are always\n     * forwarded; presentation policy (e.g. hiding successful `scopeEnd`\n     * footers at non-`verbose` verbosity) lives in the renderer so\n     * embedders consuming the event stream see a complete, faithful\n     * record of scope and bar lifecycles. `message` is assumed already\n     * gated at the façade via {@link LoggerCore.isLevelVisible} (so\n     * callers can skip formatting args for filtered levels); anything\n     * that reaches here is passed through.\n     *\n     * @param event - The event to deliver.\n     */\n    emit(event: LogEvent): void {\n        this.renderer.handle(event);\n    }\n\n    /**\n     * Pop the scope at the top of the stack (no-op if empty) and emit the\n     * matching `*End` event.\n     *\n     * @param failed - When true, mark the closed scope as having failed.\n     */\n    private popScope(failed = false): void {\n        if (this.stack.length === 0) return;\n        const top = this.stack[this.stack.length - 1];\n        this.stack.pop();\n        const durationMs = now() - top.start;\n        if (top.kind === 'bar') {\n            this.emit({\n                kind: 'barEnd',\n                depth: top.depth,\n                name: top.name,\n                durationMs,\n                current: top.current,\n                total: top.total,\n                failed\n            });\n            return;\n        }\n        const numbering = top.index !== undefined && top.total !== undefined ?\n            { index: top.index, total: top.total } :\n            {};\n        this.emit({ kind: 'scopeEnd', depth: top.depth, name: top.name, durationMs, failed, ...numbering });\n    }\n\n    /**\n     * Open a named, timed group at the current depth. Pass\n     * `{ index, total }` to render the group as part of a numbered series\n     * (e.g. `[2/5] name`); both must be present together.\n     *\n     * @param name - The group name.\n     * @param options - Optional configuration.\n     * @param options.index - 1-based position in the numbered series.\n     * @param options.total - Total length of the numbered series.\n     * @returns A handle for closing the group and writing nested log entries.\n     */\n    pushGroup(name: string, options: { index?: number; total?: number } = {}): Group {\n        const { index, total } = options;\n        if ((index === undefined) !== (total === undefined)) {\n            throw new Error('logger.group: { index, total } must be passed together');\n        }\n        const depth = this.stack.length;\n        const numbering = index !== undefined && total !== undefined ? { index, total } : undefined;\n        const scope: Scope = numbering ?\n            { kind: 'group', name, depth, start: now(), index: numbering.index, total: numbering.total } :\n            { kind: 'group', name, depth, start: now() };\n        this.stack.push(scope);\n        this.emit({ kind: 'scopeStart', depth, name, ...(numbering ?? {}) });\n        return this.makeGroup(scope);\n    }\n\n    /**\n     * Open a labelled progress bar at the current stack depth (i.e. nested\n     * directly under whatever scope is currently on top of the stack). This\n     * is a pure-push operation: it does not pop or auto-close anything.\n     * Callers control nesting purely by the order in which they open and\n     * close scopes.\n     *\n     * @param name - The bar's label, displayed alongside the progress indicator.\n     * @param total - Total number of ticks the bar will report before completing.\n     * A `total` of 0 is allowed (e.g. processing an empty payload); both\n     * `LoggerCore` and `TextRenderer` already handle non-positive totals.\n     * @returns A handle for advancing and closing the bar.\n     */\n    pushBar(name: string, total: number): Bar {\n        const scope: Scope = {\n            kind: 'bar',\n            name,\n            depth: this.stack.length,\n            start: now(),\n            total: Math.max(0, total),\n            current: 0\n        };\n        this.stack.push(scope);\n        this.emit({ kind: 'barStart', depth: scope.depth, name: scope.name, total: scope.total });\n        return this.makeBar(scope);\n    }\n\n    private makeBar(scope: Scope & { kind: 'bar' }): Bar {\n        let closed = false;\n        // Bars are strictly LIFO from a renderer's perspective: a `TextRenderer`\n        // (or any other line-based renderer) only tracks one active bar line,\n        // so ticking a bar that isn't currently on top of the stack would\n        // corrupt whatever inner bar is. We still update `scope.current`\n        // internally so the recap line at `barEnd` is accurate, but we\n        // suppress `barTick` emission unless this bar is actually on top.\n        const isTopOfStack = () => this.stack[this.stack.length - 1] === scope;\n        const handle: Bar = {\n            tick: (n = 1) => {\n                if (closed) return;\n                if (this.stack.indexOf(scope) === -1) {\n                    // scope was popped from underneath us (e.g. a sibling\n                    // bar opened inside a function call). Silently retire\n                    // the handle so further ticks are no-ops.\n                    closed = true;\n                    return;\n                }\n                const next = Math.min(scope.total, scope.current + Math.max(0, n));\n                if (next === scope.current) return;\n                scope.current = next;\n                if (!isTopOfStack()) return;\n                this.emit({ kind: 'barTick', depth: scope.depth, name: scope.name, current: scope.current, total: scope.total });\n            },\n            update: (current: number) => {\n                if (closed) return;\n                if (this.stack.indexOf(scope) === -1) {\n                    closed = true;\n                    return;\n                }\n                const next = Math.min(scope.total, Math.max(0, current));\n                if (next === scope.current) return;\n                scope.current = next;\n                if (!isTopOfStack()) return;\n                this.emit({ kind: 'barTick', depth: scope.depth, name: scope.name, current: scope.current, total: scope.total });\n            },\n            end: () => {\n                if (closed) return;\n                closed = true;\n                const idx = this.stack.indexOf(scope);\n                if (idx === -1) return;\n                while (this.stack.length > idx + 1) this.popScope(true);\n                this.popScope();\n            },\n            [Symbol.dispose]: () => handle.end()\n        };\n        return handle;\n    }\n\n    private makeGroup(scope: Scope & { kind: 'group' }): Group {\n        let closed = false;\n        const handle: Group = {\n            end: () => {\n                if (closed) return;\n                closed = true;\n                const idx = this.stack.indexOf(scope);\n                if (idx === -1) return;\n                while (this.stack.length > idx + 1) this.popScope(true);\n                this.popScope();\n            },\n            [Symbol.dispose]: () => handle.end()\n        };\n        return handle;\n    }\n\n    message(level: MessageKind, text: string): void {\n        this.emit({ kind: 'message', depth: this.stack.length, level, text });\n        if (level === 'error') this.unwindAll(true);\n    }\n\n    /**\n     * Pop every open scope, emitting end-events with optional `failed` flag.\n     * Called automatically on `logger.error(...)` so that aborted work renders\n     * a clean trail of `(failed)` markers without callers needing try/finally.\n     *\n     * @param failed - When true, mark every closed scope as having failed.\n     */\n    unwindAll(failed = false): void {\n        while (this.stack.length > 0) this.popScope(failed);\n    }\n\n    output(text: string): void {\n        this.emit({ kind: 'output', text });\n    }\n}\n\nconst core = new LoggerCore();\n\n/**\n * Public logger surface.\n *\n * Open named, timed scopes with {@link Logger.group}. Pass `{ index, total }`\n * to render the group as part of a numbered series. Indeterminate progress is\n * reported with {@link Logger.bar}. Free-form messages route through `info` /\n * `warn` / `error` / `debug`, indented under whatever is on top of the\n * active-scope stack.\n *\n * Both `group` and `bar` are pure-push operations: opening a new scope simply\n * places it on top of the stack without auto-closing siblings, so call order\n * directly determines nesting. Close scopes with `handle.end()` after the\n * body. Callers that route failures through {@link Logger.error} get scope\n * cleanup for free; embedders that swallow exceptions should call\n * {@link Logger.unwindAll} from their catch to close every still-open scope.\n */\nconst logger = {\n    /**\n     * Open a named, timed scope. Returns a {@link Group} handle. Call `end()`\n     * to close it. Group children indent automatically based on call depth.\n     *\n     * Pass `{ index, total }` to render the group as part of a numbered\n     * series (e.g. `[2/5] name`). Both fields must be supplied together.\n     *\n     * @param name - The group name.\n     * @param options - Optional configuration.\n     * @param options.index - 1-based position in the numbered series.\n     * @param options.total - Total length of the numbered series.\n     * @returns A handle for closing the group and writing nested log entries.\n     */\n    group(name: string, options?: { index?: number; total?: number }): Group {\n        return core.pushGroup(name, options);\n    },\n\n    /**\n     * Open a labelled progress bar nested directly under whatever scope is\n     * currently on top of the active-scope stack. Renders as a single line\n     * at child indent.\n     *\n     * Like {@link Logger.group}, this is a pure-push operation: it does not\n     * close any sibling already on the stack. Close with `bar.end()`, or let\n     * an enclosing group's `end()` / {@link Logger.unwindAll} pop it.\n     *\n     * @param name - The bar's label.\n     * @param total - Expected number of ticks (or absolute total when using\n     * {@link Bar.update}).\n     * @returns A handle for advancing and closing the bar.\n     */\n    bar(name: string, total: number): Bar {\n        return core.pushBar(name, total);\n    },\n\n    /**\n     * Emit an info message indented under the innermost active scope.\n     * @param args - Message parts (joined with a space).\n     */\n    info(...args: any[]): void {\n        if (!core.isLevelVisible('info')) return;\n        core.message('info', fmtArgs(args));\n    },\n\n    /**\n     * Emit a warning indented under the innermost active scope.\n     * @param args - Message parts.\n     */\n    warn(...args: any[]): void {\n        if (!core.isLevelVisible('warn')) return;\n        core.message('warn', fmtArgs(args));\n    },\n\n    /**\n     * Emit an error message. Always shown, regardless of verbosity. Triggers\n     * an automatic unwind of all open scopes, marking each as failed.\n     * @param args - Message parts.\n     */\n    error(...args: any[]): void {\n        core.message('error', fmtArgs(args));\n    },\n\n    /**\n     * Emit a debug message. Shown only at `verbose` verbosity.\n     * @param args - Message parts.\n     */\n    debug(...args: any[]): void {\n        if (!core.isLevelVisible('debug')) return;\n        core.message('debug', fmtArgs(args));\n    },\n\n    /**\n     * Emit a logical unit of pipeable output (typically one line, or a\n     * multi-line block treated as a single unit). The renderer terminates\n     * each unit with a newline, so callers should not include a trailing\n     * `\\n`. Always shown, regardless of verbosity.\n     * @param text - The text to emit (without a trailing newline).\n     */\n    output(text: string): void {\n        core.output(text);\n    },\n\n    /**\n     * Replace the active renderer. Embedders install their own renderer here\n     * to consume `LogEvent`s; the default renderer is a no-op. Renderers\n     * receive every scope/bar lifecycle event regardless of verbosity, so\n     * progress UIs can rely on `scopeStart`/`scopeEnd` and `barStart`/`barEnd`\n     * to manage their state.\n     * @param r - The renderer to install.\n     */\n    setRenderer(r: Renderer): void {\n        core.setRenderer(r);\n    },\n\n    /**\n     * Set verbosity: `quiet` (errors and warnings), `normal` (default),\n     * `verbose` (includes debug).\n     * @param v - The verbosity level.\n     */\n    setVerbosity(v: Verbosity): void {\n        core.setVerbosity(v);\n    },\n\n    /**\n     * Close every open scope and bar, optionally marking them as failed.\n     * Use this from an embedder's catch when an exception is being swallowed\n     * (rather than rethrown into a `logger.error()` call), to prevent\n     * dangling scopes from corrupting subsequent output.\n     * @param failed - When true, mark every closed scope as having failed.\n     */\n    unwindAll(failed = false): void {\n        core.unwindAll(failed);\n    },\n\n    /**\n     * Get the current verbosity level.\n     * @returns The active verbosity level.\n     */\n    getVerbosity(): Verbosity {\n        return core.getVerbosity();\n    }\n};\n\n/**\n * Public type alias for the logger object. Embedders can type-hint against\n * this to inject a configured logger.\n */\ntype Logger = typeof logger;\n\nexport { logger, verbosityRank };\nexport type { Bar, Group, LogEvent, Logger, MessageKind, Renderer, Verbosity };\n","import { Mat4, Quat, Vec3 } from 'playcanvas';\n\nconst sigmoid = (v: number) => 1 / (1 + Math.exp(-v));\n\nconst _tv = new Vec3();\nconst _sv = new Vec3();\n\n/**\n * A source-to-engine coordinate transform comprising translation, rotation\n * and uniform scale. Lives alongside a DataTable to describe how raw\n * column data maps to PlayCanvas engine coordinates.\n *\n * @example\n * ```ts\n * const t = new Transform().fromEulers(0, 0, 180);\n * console.log(t.isIdentity()); // false\n *\n * const inv = t.clone().invert();\n * console.log(t.mul(inv).isIdentity()); // true\n * ```\n */\nclass Transform {\n    translation: Vec3;\n    rotation: Quat;\n    scale: number;\n\n    constructor(translation?: Vec3, rotation?: Quat, scale?: number) {\n        this.translation = translation ? translation.clone() : new Vec3();\n        this.rotation = rotation ? rotation.clone() : new Quat();\n        this.scale = scale ?? 1;\n    }\n\n    /**\n     * Sets this transform to a rotation-only transform from Euler angles in degrees.\n     *\n     * @param x - Rotation around X axis in degrees.\n     * @param y - Rotation around Y axis in degrees.\n     * @param z - Rotation around Z axis in degrees.\n     * @returns This transform (for chaining).\n     */\n    fromEulers(x: number, y: number, z: number): Transform {\n        this.translation.set(0, 0, 0);\n        this.rotation.setFromEulerAngles(x, y, z);\n        this.scale = 1;\n        return this;\n    }\n\n    /**\n     * Creates a deep copy of this transform.\n     *\n     * @returns A new Transform with the same values.\n     */\n    clone(): Transform {\n        return new Transform(this.translation, this.rotation, this.scale);\n    }\n\n    /**\n     * Tests whether this transform equals another within the given tolerance.\n     * Quaternion comparison accounts for double-cover (q and -q represent\n     * the same rotation).\n     *\n     * @param other - The transform to compare against.\n     * @param epsilon - Floating-point tolerance. Defaults to 1e-6.\n     * @returns True if the transforms are equal within the tolerance.\n     */\n    equals(other: Transform, epsilon = 1e-6): boolean {\n        const ta = this.translation;\n        const tb = other.translation;\n        if (Math.abs(ta.x - tb.x) > epsilon || Math.abs(ta.y - tb.y) > epsilon || Math.abs(ta.z - tb.z) > epsilon) {\n            return false;\n        }\n        const ra = this.rotation;\n        const rb = other.rotation;\n        const dot = ra.x * rb.x + ra.y * rb.y + ra.z * rb.z + ra.w * rb.w;\n        if (Math.abs(dot) < 1 - epsilon) {\n            return false;\n        }\n        if (Math.abs(this.scale - other.scale) > epsilon) {\n            return false;\n        }\n        return true;\n    }\n\n    /**\n     * Tests whether this transform is effectively identity within the given tolerance.\n     *\n     * @param epsilon - Floating-point tolerance. Defaults to 1e-6.\n     * @returns True if identity within the tolerance.\n     */\n    isIdentity(epsilon = 1e-6): boolean {\n        return this.equals(Transform.IDENTITY, epsilon);\n    }\n\n    /**\n     * Inverts this transform in-place.\n     *\n     * @returns This transform (for chaining).\n     */\n    invert(): Transform {\n        if (this.scale === 0) {\n            throw new Error('Cannot invert a Transform with scale 0');\n        }\n        this.scale = 1 / this.scale;\n        this.rotation.invert();\n        this.translation.mulScalar(-this.scale);\n        this.rotation.transformVector(this.translation, this.translation);\n        return this;\n    }\n\n    /**\n     * Sets this transform to the composition of a * b. Handles aliasing\n     * (either a or b may be this).\n     *\n     * @param a - The first (left) transform.\n     * @param b - The second (right) transform.\n     * @returns This transform (for chaining).\n     */\n    mul2(a: Transform, b: Transform): Transform {\n        // Translation must be computed first using original a.rotation\n        a.rotation.transformVector(b.translation, _tv);\n        _tv.mulScalar(a.scale).add(a.translation);\n\n        this.rotation.mul2(a.rotation, b.rotation);\n        this.scale = a.scale * b.scale;\n        this.translation.copy(_tv);\n        return this;\n    }\n\n    /**\n     * Sets this transform to this * other.\n     *\n     * @param other - The transform to multiply with.\n     * @returns This transform (for chaining).\n     */\n    mul(other: Transform): Transform {\n        return this.mul2(this, other);\n    }\n\n    /**\n     * Transforms a point by this TRS transform: result = translation + rotation * (scale * point).\n     *\n     * @param point - The input point.\n     * @param result - The Vec3 to write the result into (may alias point).\n     * @returns The transformed point.\n     */\n    transformPoint(point: Vec3, result: Vec3): Vec3 {\n        result.copy(point).mulScalar(this.scale);\n        this.rotation.transformVector(result, result);\n        result.add(this.translation);\n        return result;\n    }\n\n    /**\n     * Fills the provided Mat4 with the TRS matrix for this transform.\n     *\n     * @param result - The Mat4 to fill.\n     * @returns The filled Mat4.\n     */\n    getMatrix(result: Mat4): Mat4 {\n        _sv.set(this.scale, this.scale, this.scale);\n        return result.setTRS(this.translation, this.rotation, _sv);\n    }\n\n    static freeze(t: Transform): Readonly<Transform> {\n        Object.freeze(t.translation);\n        Object.freeze(t.rotation);\n        return Object.freeze(t);\n    }\n\n    static IDENTITY = Transform.freeze(new Transform());\n\n    /**\n     * PLY coordinate convention: 180-degree rotation around Z.\n     * Used by formats that store Gaussian data in PLY-style coordinates:\n     * PLY, splat, KSplat, SPZ, and SOG.\n     */\n    static PLY = Transform.freeze(new Transform().fromEulers(0, 0, 180));\n}\n\nexport { sigmoid, Transform };\n","import { TypedArray } from '../data-table';\n\n/**\n * Partition indices around the k-th smallest element using quickselect\n * (median-of-three pivot selection).\n *\n * After this call, `idx[k]` holds the index of the k-th smallest value\n * in `data`, and all indices before k map to smaller-or-equal values.\n *\n * @param data - The data array to use for comparison values.\n * @param idx - The index array to partition (mutated in place).\n * @param k - The target partition index.\n * @returns The index value at position k after partitioning.\n */\nconst quickselect = (data: TypedArray, idx: Uint32Array, k: number): number => {\n    const valAt = (p: number) => data[idx[p]];\n    const swap = (i: number, j: number) => {\n        const t = idx[i];\n        idx[i] = idx[j];\n        idx[j] = t;\n    };\n\n    const n = idx.length;\n    let l = 0;\n    let r = n - 1;\n\n    while (true) {\n        if (r <= l + 1) {\n            if (r === l + 1 && valAt(r) < valAt(l)) swap(l, r);\n            return idx[k];\n        }\n\n        const mid = (l + r) >>> 1;\n        swap(mid, l + 1);\n        if (valAt(l) > valAt(r)) swap(l, r);\n        if (valAt(l + 1) > valAt(r)) swap(l + 1, r);\n        if (valAt(l) > valAt(l + 1)) swap(l, l + 1);\n\n        let i = l + 1;\n        let j = r;\n        const pivotIdxVal = valAt(l + 1);\n        const pivotIdx = idx[l + 1];\n\n        while (true) {\n            do {\n                i++;\n            } while (i <= r && valAt(i) < pivotIdxVal);\n            do {\n                j--;\n            } while (j >= l && valAt(j) > pivotIdxVal);\n            if (j < i) break;\n            swap(i, j);\n        }\n\n        idx[l + 1] = idx[j];\n        idx[j] = pivotIdx;\n\n        if (j >= k) r = j - 1;\n        if (j <= k) l = i;\n    }\n};\n\nexport { quickselect };\n","import { Mat3 } from 'playcanvas';\n\n/* eslint-disable indent */\n\nconst kSqrt03_02  = Math.sqrt(3.0 /  2.0);\nconst kSqrt01_03  = Math.sqrt(1.0 /  3.0);\nconst kSqrt02_03  = Math.sqrt(2.0 /  3.0);\nconst kSqrt04_03  = Math.sqrt(4.0 /  3.0);\nconst kSqrt01_04  = Math.sqrt(1.0 /  4.0);\nconst kSqrt03_04  = Math.sqrt(3.0 /  4.0);\nconst kSqrt01_05  = Math.sqrt(1.0 /  5.0);\nconst kSqrt03_05  = Math.sqrt(3.0 /  5.0);\nconst kSqrt06_05  = Math.sqrt(6.0 /  5.0);\nconst kSqrt08_05  = Math.sqrt(8.0 /  5.0);\nconst kSqrt09_05  = Math.sqrt(9.0 /  5.0);\nconst kSqrt01_06  = Math.sqrt(1.0 /  6.0);\nconst kSqrt05_06  = Math.sqrt(5.0 /  6.0);\nconst kSqrt03_08  = Math.sqrt(3.0 /  8.0);\nconst kSqrt05_08  = Math.sqrt(5.0 /  8.0);\nconst kSqrt09_08  = Math.sqrt(9.0 /  8.0);\nconst kSqrt05_09  = Math.sqrt(5.0 /  9.0);\nconst kSqrt08_09  = Math.sqrt(8.0 /  9.0);\nconst kSqrt01_10  = Math.sqrt(1.0 / 10.0);\nconst kSqrt03_10  = Math.sqrt(3.0 / 10.0);\nconst kSqrt01_12  = Math.sqrt(1.0 / 12.0);\nconst kSqrt04_15  = Math.sqrt(4.0 / 15.0);\nconst kSqrt01_16  = Math.sqrt(1.0 / 16.0);\nconst kSqrt15_16  = Math.sqrt(15.0 / 16.0);\nconst kSqrt01_18  = Math.sqrt(1.0 / 18.0);\nconst kSqrt01_60  = Math.sqrt(1.0 / 60.0);\n\nconst dp = (n: number, start: number, a: number[] | Float32Array, b: number[] | Float32Array) => {\n    let sum = 0;\n    for (let i = 0; i < n; i++) {\n        sum += a[start + i] * b[i];\n    }\n    return sum;\n};\n\nconst coeffsIn = new Float32Array(15);\n\n// Build a sparse representation of the SH rotation matrices. For axis-aligned\n// rotations the matrices are highly sparse, so iterating only over non-zero\n// entries is significantly faster than the full dot-product approach.\nconst buildSparse = (sh1: number[][], sh2: number[][], sh3: number[][]) => {\n    const counts: number[] = [];\n    const indices: number[] = [];\n    const values: number[] = [];\n\n    const addBand = (matrix: number[][], size: number, base: number) => {\n        for (let i = 0; i < size; i++) {\n            let count = 0;\n            for (let j = 0; j < size; j++) {\n                if (Math.abs(matrix[i][j]) > 1e-10) {\n                    indices.push(base + j);\n                    values.push(matrix[i][j]);\n                    count++;\n                }\n            }\n            counts.push(count);\n        }\n    };\n\n    addBand(sh1, 3, 0);\n    addBand(sh2, 5, 3);\n    addBand(sh3, 7, 8);\n\n    return { counts, indices, values };\n};\n\n// Returns true if the rotation matrix is a signed permutation (every entry is 0 or ±1),\n// i.e. the rotation maps each axis to ±another axis (multiples of 90°).\nconst isAxisAligned = (rot: Float32Array) => {\n    for (let i = 0; i < 9; i++) {\n        const a = Math.abs(rot[i]);\n        if (a > 0.01 && Math.abs(a - 1) > 0.01) return false;\n    }\n    return true;\n};\n\n// Rotate spherical harmonics up to band 3 based on https://github.com/andrewwillmott/sh-lib\n//\n// This implementation calculates the rotation factors during construction which can then\n// be used to rotate multiple spherical harmonics cheaply.\nclass RotateSH {\n    apply: (result: Float32Array | number[], src?: Float32Array | number[]) => void;\n\n    constructor(mat: Mat3) {\n        const rot = mat.data;\n\n        // band 1\n        const sh1 = [\n            [rot[4], -rot[7], rot[1]],\n            [-rot[5], rot[8], -rot[2]],\n            [rot[3], -rot[6], rot[0]]\n        ];\n\n        // band 2\n        const sh2 = [[\n            kSqrt01_04 * ((sh1[2][2] * sh1[0][0] + sh1[2][0] * sh1[0][2]) + (sh1[0][2] * sh1[2][0] + sh1[0][0] * sh1[2][2])),\n                          (sh1[2][1] * sh1[0][0] + sh1[0][1] * sh1[2][0]),\n            kSqrt03_04 *  (sh1[2][1] * sh1[0][1] + sh1[0][1] * sh1[2][1]),\n                          (sh1[2][1] * sh1[0][2] + sh1[0][1] * sh1[2][2]),\n            kSqrt01_04 * ((sh1[2][2] * sh1[0][2] - sh1[2][0] * sh1[0][0]) + (sh1[0][2] * sh1[2][2] - sh1[0][0] * sh1[2][0]))\n        ], [\n            kSqrt01_04 * ((sh1[1][2] * sh1[0][0] + sh1[1][0] * sh1[0][2]) + (sh1[0][2] * sh1[1][0] + sh1[0][0] * sh1[1][2])),\n                           sh1[1][1] * sh1[0][0] + sh1[0][1] * sh1[1][0],\n            kSqrt03_04 *  (sh1[1][1] * sh1[0][1] + sh1[0][1] * sh1[1][1]),\n                           sh1[1][1] * sh1[0][2] + sh1[0][1] * sh1[1][2],\n            kSqrt01_04 * ((sh1[1][2] * sh1[0][2] - sh1[1][0] * sh1[0][0]) + (sh1[0][2] * sh1[1][2] - sh1[0][0] * sh1[1][0]))\n        ], [\n            kSqrt01_03 * (sh1[1][2] * sh1[1][0] + sh1[1][0] * sh1[1][2]) - kSqrt01_12 * ((sh1[2][2] * sh1[2][0] + sh1[2][0] * sh1[2][2]) + (sh1[0][2] * sh1[0][0] + sh1[0][0] * sh1[0][2])),\n            kSqrt04_03 *  sh1[1][1] * sh1[1][0] - kSqrt01_03 * (sh1[2][1] * sh1[2][0] + sh1[0][1] * sh1[0][0]),\n                          sh1[1][1] * sh1[1][1] - kSqrt01_04 * (sh1[2][1] * sh1[2][1] + sh1[0][1] * sh1[0][1]),\n            kSqrt04_03 *  sh1[1][1] * sh1[1][2] - kSqrt01_03 * (sh1[2][1] * sh1[2][2] + sh1[0][1] * sh1[0][2]),\n            kSqrt01_03 * (sh1[1][2] * sh1[1][2] - sh1[1][0] * sh1[1][0]) - kSqrt01_12 * ((sh1[2][2] * sh1[2][2] - sh1[2][0] * sh1[2][0]) + (sh1[0][2] * sh1[0][2] - sh1[0][0] * sh1[0][0]))\n        ], [\n            kSqrt01_04 * ((sh1[1][2] * sh1[2][0] + sh1[1][0] * sh1[2][2]) + (sh1[2][2] * sh1[1][0] + sh1[2][0] * sh1[1][2])),\n                           sh1[1][1] * sh1[2][0] + sh1[2][1] * sh1[1][0],\n            kSqrt03_04 *  (sh1[1][1] * sh1[2][1] + sh1[2][1] * sh1[1][1]),\n                           sh1[1][1] * sh1[2][2] + sh1[2][1] * sh1[1][2],\n            kSqrt01_04 * ((sh1[1][2] * sh1[2][2] - sh1[1][0] * sh1[2][0]) + (sh1[2][2] * sh1[1][2] - sh1[2][0] * sh1[1][0]))\n        ], [\n            kSqrt01_04 * ((sh1[2][2] * sh1[2][0] + sh1[2][0] * sh1[2][2]) - (sh1[0][2] * sh1[0][0] + sh1[0][0] * sh1[0][2])),\n                          (sh1[2][1] * sh1[2][0] - sh1[0][1] * sh1[0][0]),\n            kSqrt03_04 *  (sh1[2][1] * sh1[2][1] - sh1[0][1] * sh1[0][1]),\n                          (sh1[2][1] * sh1[2][2] - sh1[0][1] * sh1[0][2]),\n            kSqrt01_04 * ((sh1[2][2] * sh1[2][2] - sh1[2][0] * sh1[2][0]) - (sh1[0][2] * sh1[0][2] - sh1[0][0] * sh1[0][0]))\n        ]];\n\n        // band 3\n        const sh3 = [[\n            kSqrt01_04 * ((sh1[2][2] * sh2[0][0] + sh1[2][0] * sh2[0][4]) + (sh1[0][2] * sh2[4][0] + sh1[0][0] * sh2[4][4])),\n            kSqrt03_02 *  (sh1[2][1] * sh2[0][0] + sh1[0][1] * sh2[4][0]),\n            kSqrt15_16 *  (sh1[2][1] * sh2[0][1] + sh1[0][1] * sh2[4][1]),\n            kSqrt05_06 *  (sh1[2][1] * sh2[0][2] + sh1[0][1] * sh2[4][2]),\n            kSqrt15_16 *  (sh1[2][1] * sh2[0][3] + sh1[0][1] * sh2[4][3]),\n            kSqrt03_02 *  (sh1[2][1] * sh2[0][4] + sh1[0][1] * sh2[4][4]),\n            kSqrt01_04 * ((sh1[2][2] * sh2[0][4] - sh1[2][0] * sh2[0][0]) + (sh1[0][2] * sh2[4][4] - sh1[0][0] * sh2[4][0]))\n        ], [\n            kSqrt01_06 * (sh1[1][2] * sh2[0][0] + sh1[1][0] * sh2[0][4]) + kSqrt01_06 * ((sh1[2][2] * sh2[1][0] + sh1[2][0] * sh2[1][4]) + (sh1[0][2] * sh2[3][0] + sh1[0][0] * sh2[3][4])),\n                          sh1[1][1] * sh2[0][0]                          +               (sh1[2][1] * sh2[1][0] + sh1[0][1] * sh2[3][0]),\n            kSqrt05_08 *  sh1[1][1] * sh2[0][1]                          + kSqrt05_08 *  (sh1[2][1] * sh2[1][1] + sh1[0][1] * sh2[3][1]),\n            kSqrt05_09 *  sh1[1][1] * sh2[0][2]                          + kSqrt05_09 *  (sh1[2][1] * sh2[1][2] + sh1[0][1] * sh2[3][2]),\n            kSqrt05_08 *  sh1[1][1] * sh2[0][3]                          + kSqrt05_08 *  (sh1[2][1] * sh2[1][3] + sh1[0][1] * sh2[3][3]),\n                          sh1[1][1] * sh2[0][4]                          +               (sh1[2][1] * sh2[1][4] + sh1[0][1] * sh2[3][4]),\n            kSqrt01_06 * (sh1[1][2] * sh2[0][4] - sh1[1][0] * sh2[0][0]) + kSqrt01_06 * ((sh1[2][2] * sh2[1][4] - sh1[2][0] * sh2[1][0]) + (sh1[0][2] * sh2[3][4] - sh1[0][0] * sh2[3][0]))\n        ], [\n            kSqrt04_15 * (sh1[1][2] * sh2[1][0] + sh1[1][0] * sh2[1][4]) + kSqrt01_05 * (sh1[0][2] * sh2[2][0] + sh1[0][0] * sh2[2][4]) - kSqrt01_60 * ((sh1[2][2] * sh2[0][0] + sh1[2][0] * sh2[0][4]) - (sh1[0][2] * sh2[4][0] + sh1[0][0] * sh2[4][4])),\n            kSqrt08_05 *  sh1[1][1] * sh2[1][0]                          + kSqrt06_05 *  sh1[0][1] * sh2[2][0] - kSqrt01_10 * (sh1[2][1] * sh2[0][0] - sh1[0][1] * sh2[4][0]),\n                          sh1[1][1] * sh2[1][1]                          + kSqrt03_04 *  sh1[0][1] * sh2[2][1] - kSqrt01_16 * (sh1[2][1] * sh2[0][1] - sh1[0][1] * sh2[4][1]),\n            kSqrt08_09 *  sh1[1][1] * sh2[1][2]                          + kSqrt02_03 *  sh1[0][1] * sh2[2][2] - kSqrt01_18 * (sh1[2][1] * sh2[0][2] - sh1[0][1] * sh2[4][2]),\n                          sh1[1][1] * sh2[1][3]                          + kSqrt03_04 *  sh1[0][1] * sh2[2][3] - kSqrt01_16 * (sh1[2][1] * sh2[0][3] - sh1[0][1] * sh2[4][3]),\n            kSqrt08_05 *  sh1[1][1] * sh2[1][4]                          + kSqrt06_05 *  sh1[0][1] * sh2[2][4] - kSqrt01_10 * (sh1[2][1] * sh2[0][4] - sh1[0][1] * sh2[4][4]),\n            kSqrt04_15 * (sh1[1][2] * sh2[1][4] - sh1[1][0] * sh2[1][0]) + kSqrt01_05 * (sh1[0][2] * sh2[2][4] - sh1[0][0] * sh2[2][0]) - kSqrt01_60 * ((sh1[2][2] * sh2[0][4] - sh1[2][0] * sh2[0][0]) - (sh1[0][2] * sh2[4][4] - sh1[0][0] * sh2[4][0]))\n        ], [\n            kSqrt03_10 * (sh1[1][2] * sh2[2][0] + sh1[1][0] * sh2[2][4]) - kSqrt01_10 * ((sh1[2][2] * sh2[3][0] + sh1[2][0] * sh2[3][4]) + (sh1[0][2] * sh2[1][0] + sh1[0][0] * sh2[1][4])),\n            kSqrt09_05 *  sh1[1][1] * sh2[2][0]                          - kSqrt03_05 *  (sh1[2][1] * sh2[3][0] + sh1[0][1] * sh2[1][0]),\n            kSqrt09_08 *  sh1[1][1] * sh2[2][1]                          - kSqrt03_08 *  (sh1[2][1] * sh2[3][1] + sh1[0][1] * sh2[1][1]),\n                          sh1[1][1] * sh2[2][2]                          - kSqrt01_03 *  (sh1[2][1] * sh2[3][2] + sh1[0][1] * sh2[1][2]),\n            kSqrt09_08 *  sh1[1][1] * sh2[2][3]                          - kSqrt03_08 *  (sh1[2][1] * sh2[3][3] + sh1[0][1] * sh2[1][3]),\n            kSqrt09_05 *  sh1[1][1] * sh2[2][4]                          - kSqrt03_05 *  (sh1[2][1] * sh2[3][4] + sh1[0][1] * sh2[1][4]),\n            kSqrt03_10 * (sh1[1][2] * sh2[2][4] - sh1[1][0] * sh2[2][0]) - kSqrt01_10 * ((sh1[2][2] * sh2[3][4] - sh1[2][0] * sh2[3][0]) + (sh1[0][2] * sh2[1][4] - sh1[0][0] * sh2[1][0]))\n        ], [\n            kSqrt04_15 * (sh1[1][2] * sh2[3][0] + sh1[1][0] * sh2[3][4]) + kSqrt01_05 * (sh1[2][2] * sh2[2][0] + sh1[2][0] * sh2[2][4]) - kSqrt01_60 * ((sh1[2][2] * sh2[4][0] + sh1[2][0] * sh2[4][4]) + (sh1[0][2] * sh2[0][0] + sh1[0][0] * sh2[0][4])),\n            kSqrt08_05 *  sh1[1][1] * sh2[3][0]                          + kSqrt06_05 *  sh1[2][1] * sh2[2][0] - kSqrt01_10 * (sh1[2][1] * sh2[4][0] + sh1[0][1] * sh2[0][0]),\n                          sh1[1][1] * sh2[3][1]                          + kSqrt03_04 *  sh1[2][1] * sh2[2][1] - kSqrt01_16 * (sh1[2][1] * sh2[4][1] + sh1[0][1] * sh2[0][1]),\n            kSqrt08_09 *  sh1[1][1] * sh2[3][2]                          + kSqrt02_03 *  sh1[2][1] * sh2[2][2] - kSqrt01_18 * (sh1[2][1] * sh2[4][2] + sh1[0][1] * sh2[0][2]),\n                          sh1[1][1] * sh2[3][3]                          + kSqrt03_04 *  sh1[2][1] * sh2[2][3] - kSqrt01_16 * (sh1[2][1] * sh2[4][3] + sh1[0][1] * sh2[0][3]),\n            kSqrt08_05 *  sh1[1][1] * sh2[3][4]                          + kSqrt06_05 *  sh1[2][1] * sh2[2][4] - kSqrt01_10 * (sh1[2][1] * sh2[4][4] + sh1[0][1] * sh2[0][4]),\n            kSqrt04_15 * (sh1[1][2] * sh2[3][4] - sh1[1][0] * sh2[3][0]) + kSqrt01_05 * (sh1[2][2] * sh2[2][4] - sh1[2][0] * sh2[2][0]) - kSqrt01_60 * ((sh1[2][2] * sh2[4][4] - sh1[2][0] * sh2[4][0]) + (sh1[0][2] * sh2[0][4] - sh1[0][0] * sh2[0][0]))\n        ], [\n            kSqrt01_06 * (sh1[1][2] * sh2[4][0] + sh1[1][0] * sh2[4][4]) + kSqrt01_06 * ((sh1[2][2] * sh2[3][0] + sh1[2][0] * sh2[3][4]) - (sh1[0][2] * sh2[1][0] + sh1[0][0] * sh2[1][4])),\n                          sh1[1][1] * sh2[4][0]                          +               (sh1[2][1] * sh2[3][0] - sh1[0][1] * sh2[1][0]),\n            kSqrt05_08 *  sh1[1][1] * sh2[4][1]                          + kSqrt05_08 *  (sh1[2][1] * sh2[3][1] - sh1[0][1] * sh2[1][1]),\n            kSqrt05_09 *  sh1[1][1] * sh2[4][2]                          + kSqrt05_09 *  (sh1[2][1] * sh2[3][2] - sh1[0][1] * sh2[1][2]),\n            kSqrt05_08 *  sh1[1][1] * sh2[4][3]                          + kSqrt05_08 *  (sh1[2][1] * sh2[3][3] - sh1[0][1] * sh2[1][3]),\n                          sh1[1][1] * sh2[4][4]                          +               (sh1[2][1] * sh2[3][4] - sh1[0][1] * sh2[1][4]),\n            kSqrt01_06 * (sh1[1][2] * sh2[4][4] - sh1[1][0] * sh2[4][0]) + kSqrt01_06 * ((sh1[2][2] * sh2[3][4] - sh1[2][0] * sh2[3][0]) - (sh1[0][2] * sh2[1][4] - sh1[0][0] * sh2[1][0]))\n        ], [\n            kSqrt01_04 * ((sh1[2][2] * sh2[4][0] + sh1[2][0] * sh2[4][4]) - (sh1[0][2] * sh2[0][0] + sh1[0][0] * sh2[0][4])),\n            kSqrt03_02 *  (sh1[2][1] * sh2[4][0] - sh1[0][1] * sh2[0][0]),\n            kSqrt15_16 *  (sh1[2][1] * sh2[4][1] - sh1[0][1] * sh2[0][1]),\n            kSqrt05_06 *  (sh1[2][1] * sh2[4][2] - sh1[0][1] * sh2[0][2]),\n            kSqrt15_16 *  (sh1[2][1] * sh2[4][3] - sh1[0][1] * sh2[0][3]),\n            kSqrt03_02 *  (sh1[2][1] * sh2[4][4] - sh1[0][1] * sh2[0][4]),\n            kSqrt01_04 * ((sh1[2][2] * sh2[4][4] - sh1[2][0] * sh2[4][0]) - (sh1[0][2] * sh2[0][4] - sh1[0][0] * sh2[0][0]))\n        ]];\n\n        if (isAxisAligned(rot)) {\n            const { counts, indices, values } = buildSparse(sh1, sh2, sh3);\n\n            this.apply = (result: Float32Array | number[], src?: Float32Array | number[]) => {\n                if (!src || src === result) {\n                    coeffsIn.set(result);\n                    src = coeffsIn;\n                }\n\n                let vp = 0;\n\n                if (result.length < 3) return;\n                for (let i = 0; i < 3; i++) {\n                    let sum = 0;\n                    for (let k = 0; k < counts[i]; k++) {\n                        sum += values[vp] * src[indices[vp]];\n                        vp++;\n                    }\n                    result[i] = sum;\n                }\n\n                if (result.length < 8) return;\n                for (let i = 0; i < 5; i++) {\n                    let sum = 0;\n                    for (let k = 0; k < counts[3 + i]; k++) {\n                        sum += values[vp] * src[indices[vp]];\n                        vp++;\n                    }\n                    result[3 + i] = sum;\n                }\n\n                if (result.length < 15) return;\n                for (let i = 0; i < 7; i++) {\n                    let sum = 0;\n                    for (let k = 0; k < counts[8 + i]; k++) {\n                        sum += values[vp] * src[indices[vp]];\n                        vp++;\n                    }\n                    result[8 + i] = sum;\n                }\n            };\n        } else {\n            this.apply = (result: Float32Array | number[], src?: Float32Array | number[]) => {\n                if (!src || src === result) {\n                    coeffsIn.set(result);\n                    src = coeffsIn;\n                }\n\n                // band 1\n                if (result.length < 3) {\n                    return;\n                }\n                result[0] = dp(3, 0, src, sh1[0]);\n                result[1] = dp(3, 0, src, sh1[1]);\n                result[2] = dp(3, 0, src, sh1[2]);\n\n                // band 2\n                if (result.length < 8) {\n                    return;\n                }\n                result[3] = dp(5, 3, src, sh2[0]);\n                result[4] = dp(5, 3, src, sh2[1]);\n                result[5] = dp(5, 3, src, sh2[2]);\n                result[6] = dp(5, 3, src, sh2[3]);\n                result[7] = dp(5, 3, src, sh2[4]);\n\n                // band 3\n                if (result.length < 15) {\n                    return;\n                }\n                result[8]  = dp(7, 8, src, sh3[0]);\n                result[9]  = dp(7, 8, src, sh3[1]);\n                result[10] = dp(7, 8, src, sh3[2]);\n                result[11] = dp(7, 8, src, sh3[3]);\n                result[12] = dp(7, 8, src, sh3[4]);\n                result[13] = dp(7, 8, src, sh3[5]);\n                result[14] = dp(7, 8, src, sh3[6]);\n            };\n        }\n    }\n}\n\nexport { RotateSH };\n","import { fmtBytes, fmtTime } from './fmt';\nimport { logger, verbosityRank, type LogEvent, type Renderer } from './logger';\n\n/**\n * Output streams and optional memory-usage probe for {@link TextRenderer}.\n */\ninterface TextRendererOptions {\n    /**\n     * Receives all status chunks (scopes, bars, messages). May contain\n     * partial-line writes (e.g. progress-bar `#` ticks). For TTY output,\n     * hand this to a stream that flushes on partials\n     * (`process.stderr.write.bind(process.stderr)` in Node) so bars\n     * render in place. For non-interactive output (CI logs, file\n     * redirects), wrap in a line buffer that holds chunks until a `\\n`\n     * arrives - the bar's incremental writes then coalesce into a single\n     * complete line per bar.\n     */\n    write: (chunk: string) => void;\n    /**\n     * Receives `output` events, one logical unit per call, each already\n     * terminated with `\\n` by the renderer. Hand this to the pipeable\n     * channel (typically `process.stdout.write.bind(process.stdout)`).\n     * Defaults to the same sink as `write` when omitted.\n     */\n    output?: (chunk: string) => void;\n    /**\n     * Optional peak-memory probe in bytes. Used by the `[peak X]`\n     * overlay gated by the renderer's `mem` field. In Node this is\n     * typically derived from `process.resourceUsage().maxRSS` (which\n     * is kernel-tracked and reflects the whole process - including\n     * ArrayBuffers - rather than just the V8 heap).\n     */\n    getPeakMemory?: () => number;\n    /**\n     * Optional currently-live memory probe in bytes. When supplied\n     * alongside `getPeakMemory`, the `--mem` overlay becomes\n     * `[peak X | live Y]`, where `live` reflects memory that V8 still\n     * tracks as alive. Unlike `peak` (kernel max RSS, monotonic), this\n     * value drops when the GC reclaims unreferenced allocations, so\n     * the gap between consecutive phases reveals whether each phase\n     * actually releases its scratch buffers. In Node this is typically\n     * `heapUsed + external` from `process.memoryUsage()` so ArrayBuffer\n     * storage (typed arrays) is included.\n     */\n    getLiveMemory?: () => number;\n}\n\nconst indent = (depth: number): string => '  '.repeat(Math.max(0, depth));\n\nconst BAR_WIDTH = 20;\n\n/**\n * Default human-readable text renderer. Emits one event per line - no\n * carriage-return rewriting, no TTY detection, no buffering. Bars render\n * as `[#### ...... ] duration`, with `#` appended incrementally on each\n * `barTick` and the remainder padded with `.` on `barEnd`. `output`\n * events are treated as line-oriented: their text is written to the\n * pipeable sink with a trailing `\\n` appended (callers should not include\n * one themselves).\n *\n * Verbosity is consulted directly from the shared {@link logger} on each\n * event, so this renderer alone decides what to display - the core\n * delivers every scope/bar lifecycle event so embedders consuming the\n * event stream see a faithful record. The display rules are:\n *\n * - `quiet` - suppresses every scope/bar lifecycle line (start, tick,\n *   end - including failed ends). Errors, warnings and `output` still\n *   show.\n * - `normal` (default) - shows scope/bar headers and bar progress;\n *   shows failed `scopeEnd` / `barEnd` footers (the \"failed in ...\"\n *   cascade from `logger.error` / `unwindAll(true)`); hides successful\n *   `scopeEnd` footers.\n * - `verbose` - shows everything, including successful `scopeEnd`\n *   footers (\"done in ...\").\n *\n * Sinks are injected (no `process` reference here) so the renderer works in\n * both Node CLI and browser/bundle contexts: the CLI passes\n * `process.stderr.write` for status and `process.stdout.write` for raw\n * output; library/browser consumers can pass a `console.log` line buffer.\n */\nclass TextRenderer implements Renderer {\n    private readonly write: (chunk: string) => void;\n\n    private readonly output: (chunk: string) => void;\n\n    private readonly getPeakMemory?: () => number;\n\n    private readonly getLiveMemory?: () => number;\n\n    /**\n     * When true, scope-end and bar-end lines gain a `[peak X]` suffix\n     * (or `[peak X | live Y]` when {@link TextRendererOptions.getLiveMemory}\n     * is also supplied) sourced from\n     * {@link TextRendererOptions.getPeakMemory}. No effect when the probe\n     * is omitted. Defaults to `true` when `getPeakMemory` is provided so\n     * embedders that supply a probe see the overlay automatically. Mutable\n     * so the host can toggle the overlay without re-installing the renderer.\n     */\n    mem: boolean;\n\n    /** True while a bar header has been written without its closing `\\n`. */\n    private lineDirty = false;\n\n    /**\n     * Hash count already written for the active bar. Bars are strictly LIFO\n     * (the active-scope stack guarantees it), so a single counter suffices.\n     */\n    private barFilled = 0;\n\n    constructor(options: TextRendererOptions) {\n        this.write = options.write;\n        this.output = options.output ?? options.write;\n        this.getPeakMemory = options.getPeakMemory;\n        this.getLiveMemory = options.getLiveMemory;\n        this.mem = options.getPeakMemory !== undefined;\n    }\n\n    private rank(): number {\n        return verbosityRank[logger.getVerbosity()];\n    }\n\n    handle(event: LogEvent): void {\n        switch (event.kind) {\n            case 'scopeStart': {\n                if (this.rank() < verbosityRank.normal) return;\n                this.commitDirty();\n                const numbered = event.index !== undefined && event.total !== undefined ?\n                    `[${event.index}/${event.total}] ` : '';\n                this.write(`${indent(event.depth)}\\u25b8 ${numbered}${event.name}\\n`);\n                return;\n            }\n            case 'scopeEnd': {\n                const rank = this.rank();\n                if (event.failed) {\n                    if (rank < verbosityRank.normal) return;\n                } else if (rank < verbosityRank.verbose) {\n                    return;\n                }\n                this.commitDirty();\n                const verb = event.failed ? 'failed in' : 'done in';\n                this.write(`${indent(event.depth + 1)}${verb} ${fmtTime(event.durationMs)}${this.memSuffix()}\\n`);\n                return;\n            }\n            case 'barStart': {\n                if (this.rank() < verbosityRank.normal) return;\n                this.commitDirty();\n                this.write(`${indent(event.depth)}\\u25b8 ${event.name} [`);\n                this.lineDirty = true;\n                this.barFilled = 0;\n                return;\n            }\n            case 'barTick': {\n                if (!this.lineDirty) return;\n                if (this.rank() < verbosityRank.normal) return;\n                const target = event.total <= 0 ? 0 :\n                    Math.min(BAR_WIDTH, Math.floor((event.current / event.total) * BAR_WIDTH));\n                if (target > this.barFilled) {\n                    this.write('#'.repeat(target - this.barFilled));\n                    this.barFilled = target;\n                }\n                return;\n            }\n            case 'barEnd': {\n                if (this.rank() < verbosityRank.normal) return;\n                const suffix = event.failed ?\n                    `] (failed) ${fmtTime(event.durationMs)}` :\n                    `] ${fmtTime(event.durationMs)}`;\n                if (this.lineDirty) {\n                    const remaining = Math.max(0, BAR_WIDTH - this.barFilled);\n                    this.write(`${'.'.repeat(remaining)}${suffix}${this.memSuffix()}\\n`);\n                    this.lineDirty = false;\n                    this.barFilled = 0;\n                } else {\n                    // bar's inline line was committed early by a nested\n                    // event (e.g. a child group/message). Emit a recap\n                    // line whose fill reflects actual progress, so bars\n                    // that ended early or failed don't read as complete.\n                    const filled = event.total <= 0 ? 0 :\n                        Math.min(BAR_WIDTH, Math.floor((event.current / event.total) * BAR_WIDTH));\n                    const bar = `${'#'.repeat(filled)}${'.'.repeat(BAR_WIDTH - filled)}`;\n                    this.write(`${indent(event.depth)}\\u25b8 ${event.name} [${bar}${suffix}${this.memSuffix()}\\n`);\n                }\n                return;\n            }\n            case 'message': {\n                this.commitDirty();\n                // info/debug get a `\\u00b7` glyph only when nested under a\n                // scope - at depth 0 they're framing lines (banners,\n                // summaries) and read cleaner without decoration. warn/error\n                // always carry their severity glyph regardless of depth.\n                let prefix = '';\n                if (event.level === 'error') prefix = '\\u2717 ';\n                else if (event.level === 'warn') prefix = '! ';\n                else if (event.depth > 0) prefix = '\\u00b7 ';\n                this.write(`${indent(event.depth)}${prefix}${event.text}\\n`);\n                return;\n            }\n            case 'output': {\n                this.commitDirty();\n                this.output(`${event.text}\\n`);\n            }\n        }\n    }\n\n    /**\n     * Terminate any in-progress bar line so subsequent output starts on a\n     * fresh line. The bar's `#` count is preserved on its own line; the\n     * eventual `barEnd` will produce its own footer line if it fires later.\n     */\n    private commitDirty(): void {\n        if (this.lineDirty) {\n            this.write('\\n');\n            this.lineDirty = false;\n        }\n    }\n\n    private memSuffix(): string {\n        if (!this.mem || !this.getPeakMemory) return '';\n        const peak = fmtBytes(this.getPeakMemory());\n        if (!this.getLiveMemory) return `  [peak ${peak}]`;\n        return `  [peak ${peak} | live ${fmtBytes(this.getLiveMemory())}]`;\n    }\n}\n\nexport { TextRenderer };\nexport type { TextRendererOptions };\n","var Module = (() => {\n  \n  return (\nasync function(moduleArg = {}) {\n  var moduleRtn;\n\nvar Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var ENVIRONMENT_IS_WEB=typeof window==\"object\";var ENVIRONMENT_IS_WORKER=typeof WorkerGlobalScope!=\"undefined\";var ENVIRONMENT_IS_NODE=typeof process==\"object\"&&process.versions?.node&&process.type!=\"renderer\";if(ENVIRONMENT_IS_NODE){const{createRequire}=await import(\"module\");var require=createRequire(import.meta.url)}var arguments_=[];var thisProgram=\"./this.program\";var quit_=(status,toThrow)=>{throw toThrow};var _scriptName=import.meta.url;var scriptDirectory=\"\";function locateFile(path){if(Module[\"locateFile\"]){return Module[\"locateFile\"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require(\"fs\");var nodePath=require(\"path\");if(_scriptName.startsWith(\"file:\")){scriptDirectory=nodePath.dirname(require(\"url\").fileURLToPath(_scriptName))+\"/\"}readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:\"utf8\");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\\\/g,\"/\")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(\".\",_scriptName).href}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open(\"GET\",url,false);xhr.responseType=\"arraybuffer\";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{var response=await fetch(url,{credentials:\"same-origin\"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+\" : \"+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var wasmMemory;var ABORT=false;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAP64,HEAPU64,HEAPF64;var runtimeInitialized=false;var isFileURI=filename=>filename.startsWith(\"file://\");function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);HEAP16=new Int16Array(b);Module[\"HEAPU8\"]=HEAPU8=new Uint8Array(b);HEAPU16=new Uint16Array(b);HEAP32=new Int32Array(b);Module[\"HEAPU32\"]=HEAPU32=new Uint32Array(b);HEAPF32=new Float32Array(b);HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module[\"preRun\"]){if(typeof Module[\"preRun\"]==\"function\")Module[\"preRun\"]=[Module[\"preRun\"]];while(Module[\"preRun\"].length){addOnPreRun(Module[\"preRun\"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;wasmExports[\"c\"]()}function postRun(){if(Module[\"postRun\"]){if(typeof Module[\"postRun\"]==\"function\")Module[\"postRun\"]=[Module[\"postRun\"]];while(Module[\"postRun\"].length){addOnPostRun(Module[\"postRun\"].shift())}}callRuntimeCallbacks(onPostRuns)}var runDependencies=0;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;Module[\"monitorRunDependencies\"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module[\"monitorRunDependencies\"]?.(runDependencies);if(runDependencies==0){if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module[\"onAbort\"]?.(what);what=\"Aborted(\"+what+\")\";err(what);ABORT=true;what+=\". Build with -sASSERTIONS for more info.\";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var wasmBinaryFile;function findWasmBinary(){if(Module[\"locateFile\"]){return locateFile(\"webp.wasm\")}return new URL(\"webp.wasm\",import.meta.url).href}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw\"both async and sync fetching of the wasm failed\"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&typeof WebAssembly.instantiateStreaming==\"function\"&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:\"same-origin\"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err(\"falling back to ArrayBuffer instantiation\")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){return{a:wasmImports}}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports[\"b\"];updateMemoryViews();removeRunDependency(\"wasm-instantiate\");return wasmExports}addRunDependency(\"wasm-instantiate\");function receiveInstantiationResult(result){return receiveInstance(result[\"instance\"])}var info=getWasmImports();if(Module[\"instantiateWasm\"]){return new Promise((resolve,reject)=>{Module[\"instantiateWasm\"](info,(mod,inst)=>{resolve(receiveInstance(mod,inst))})})}wasmBinaryFile??=findWasmBinary();try{var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}catch(e){readyPromiseReject(e);return Promise.reject(e)}}class ExitStatus{name=\"ExitStatus\";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var noExitRuntime=true;var stackRestore=val=>__emscripten_stack_restore(val);var stackSave=()=>_emscripten_stack_get_current();var getHeapMax=()=>2147483648;var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var growMemory=size=>{var b=wasmMemory.buffer;var pages=(size-b.byteLength+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var getCFunc=ident=>{var func=Module[\"_\"+ident];return func};var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};var lengthBytesUTF8=str=>{var len=0;for(var i=0;i<str.length;++i){var c=str.charCodeAt(i);if(c<=127){len++}else if(c<=2047){len+=2}else if(c>=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var stackAlloc=sz=>__emscripten_stack_alloc(sz);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var UTF8Decoder=typeof TextDecoder!=\"undefined\"?new TextDecoder:undefined;var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead=NaN)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str=\"\";while(idx<endPtr){var u0=heapOrArray[idx++];if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heapOrArray[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heapOrArray[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u0=(u0&7)<<18|u1<<12|u2<<6|heapOrArray[idx++]&63}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):\"\";var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType===\"string\"){return UTF8ToString(ret)}if(returnType===\"boolean\")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func(...cArgs);function onDone(ret){if(stack!==0)stackRestore(stack);return convertReturnValue(ret)}ret=onDone(ret);return ret};var cwrap=(ident,returnType,argTypes,opts)=>{var numericArgs=!argTypes||argTypes.every(type=>type===\"number\"||type===\"boolean\");var numericRet=returnType!==\"string\";if(numericRet&&numericArgs&&!opts){return getCFunc(ident)}return(...args)=>ccall(ident,returnType,argTypes,args,opts)};{if(Module[\"noExitRuntime\"])noExitRuntime=Module[\"noExitRuntime\"];if(Module[\"print\"])out=Module[\"print\"];if(Module[\"printErr\"])err=Module[\"printErr\"];if(Module[\"wasmBinary\"])wasmBinary=Module[\"wasmBinary\"];if(Module[\"arguments\"])arguments_=Module[\"arguments\"];if(Module[\"thisProgram\"])thisProgram=Module[\"thisProgram\"]}Module[\"cwrap\"]=cwrap;var wasmImports={a:_emscripten_resize_heap};var wasmExports=await createWasm();var ___wasm_call_ctors=wasmExports[\"c\"];var _webp_encode_rgba=Module[\"_webp_encode_rgba\"]=wasmExports[\"d\"];var _webp_encode_lossless_rgba=Module[\"_webp_encode_lossless_rgba\"]=wasmExports[\"e\"];var _webp_decode_rgba=Module[\"_webp_decode_rgba\"]=wasmExports[\"f\"];var _webp_free=Module[\"_webp_free\"]=wasmExports[\"g\"];var _malloc=Module[\"_malloc\"]=wasmExports[\"h\"];var _free=Module[\"_free\"]=wasmExports[\"i\"];var __emscripten_stack_restore=wasmExports[\"j\"];var __emscripten_stack_alloc=wasmExports[\"k\"];var _emscripten_stack_get_current=wasmExports[\"l\"];function run(){if(runDependencies>0){dependenciesFulfilled=run;return}preRun();if(runDependencies>0){dependenciesFulfilled=run;return}function doRun(){Module[\"calledRun\"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);Module[\"onRuntimeInitialized\"]?.();postRun()}if(Module[\"setStatus\"]){Module[\"setStatus\"](\"Running...\");setTimeout(()=>{setTimeout(()=>Module[\"setStatus\"](\"\"),1);doRun()},1)}else{doRun()}}function preInit(){if(Module[\"preInit\"]){if(typeof Module[\"preInit\"]==\"function\")Module[\"preInit\"]=[Module[\"preInit\"]];while(Module[\"preInit\"].length>0){Module[\"preInit\"].shift()()}}}preInit();run();moduleRtn=readyPromise;\n\n\n  return moduleRtn;\n}\n);\n})();\nexport default Module;\n","import createModule from '../../../lib/webp.mjs';\n\nclass WebPCodec {\n    /**\n     * URL to the webp.wasm file. Set this before any SOG read/write operations\n     * in browser environments where the default path resolution doesn't work.\n     *\n     * @example\n     * import { WebPCodec } from '@playcanvas/splat-transform';\n     * import wasmUrl from '@playcanvas/splat-transform/lib/webp.wasm?url';\n     * WebPCodec.wasmUrl = wasmUrl;\n     */\n    static wasmUrl: string | null = null;\n\n    Module: any;\n\n    static async create() {\n        const instance = new WebPCodec();\n        instance.Module = await createModule({\n            locateFile: (path: string) => {\n                if (path.endsWith('.wasm') && WebPCodec.wasmUrl) {\n                    return WebPCodec.wasmUrl;\n                }\n                return new URL(`../lib/${path}`, import.meta.url).toString();\n            }\n        });\n        return instance;\n    }\n\n    encodeLosslessRGBA(rgba: Uint8Array, width: number, height: number, stride = width * 4) {\n        const { Module } = this;\n\n        const inPtr = Module._malloc(rgba.length);\n        const outPtrPtr = Module._malloc(4);\n        const outSizePtr = Module._malloc(4);\n\n        Module.HEAPU8.set(rgba, inPtr);\n\n        const ok = Module._webp_encode_lossless_rgba(inPtr, width, height, stride, outPtrPtr, outSizePtr);\n        if (!ok) {\n            throw new Error('WebP lossless encode failed');\n        }\n\n        const outPtr = Module.HEAPU32[outPtrPtr >> 2];\n        const outSize = Module.HEAPU32[outSizePtr >> 2];\n        const bytes = Module.HEAPU8.slice(outPtr, outPtr + outSize);\n\n        Module._webp_free(outPtr);\n        Module._free(inPtr); Module._free(outPtrPtr); Module._free(outSizePtr);\n\n        return bytes;\n    }\n\n    decodeRGBA(webp: Uint8Array): { rgba: Uint8Array, width: number, height: number } {\n        const { Module } = this;\n\n        const input = webp;\n\n        const inPtr = Module._malloc(input.length);\n        const outPtrPtr = Module._malloc(4);\n        const widthPtr = Module._malloc(4);\n        const heightPtr = Module._malloc(4);\n\n        Module.HEAPU8.set(input, inPtr);\n\n        const ok = Module._webp_decode_rgba(inPtr, input.length, outPtrPtr, widthPtr, heightPtr);\n        if (!ok) {\n            Module._free(inPtr); Module._free(outPtrPtr); Module._free(widthPtr); Module._free(heightPtr);\n            throw new Error('WebP decode failed');\n        }\n\n        const outPtr = Module.HEAPU32[outPtrPtr >> 2];\n        const width = Module.HEAPU32[widthPtr >> 2];\n        const height = Module.HEAPU32[heightPtr >> 2];\n        const size = width * height * 4;\n        const bytes = Module.HEAPU8.slice(outPtr, outPtr + size);\n\n        Module._webp_free(outPtr);\n        Module._free(inPtr); Module._free(outPtrPtr); Module._free(widthPtr); Module._free(heightPtr);\n\n        return { rgba: bytes, width, height };\n    }\n}\n\nexport { WebPCodec };\n","import { Transform } from '../utils';\n\n/**\n * Union of all typed array types supported for column data.\n */\ntype TypedArray = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array;\n\n/**\n * String identifiers for typed array element types.\n */\ntype ColumnType = 'int8' | 'uint8' | 'int16' | 'uint16' | 'int32' | 'uint32' | 'float32' | 'float64';\n\n/**\n * A named column of typed array data within a DataTable.\n *\n * Columns store homogeneous numeric data efficiently using JavaScript typed arrays.\n *\n * @example\n * ```ts\n * const positions = new Column('x', new Float32Array([1.0, 2.0, 3.0]));\n * console.log(positions.name);     // 'x'\n * console.log(positions.dataType); // 'float32'\n * ```\n */\nclass Column {\n    name: string;\n    data: TypedArray;\n\n    constructor(name: string, data: TypedArray) {\n        this.name = name;\n        this.data = data;\n    }\n\n    get dataType(): ColumnType | null {\n        switch (this.data.constructor) {\n            case Int8Array: return 'int8';\n            case Uint8Array: return 'uint8';\n            case Int16Array: return 'int16';\n            case Uint16Array: return 'uint16';\n            case Int32Array: return 'int32';\n            case Uint32Array: return 'uint32';\n            case Float32Array: return 'float32';\n            case Float64Array: return 'float64';\n        }\n        return null;\n    }\n\n    clone(): Column {\n        return new Column(this.name, this.data.slice());\n    }\n}\n\n/**\n * A row object mapping column names to numeric values.\n * @ignore\n */\ntype Row = {\n    [colName: string]: number;\n};\n\n/**\n * A table of columnar data representing Gaussian splat properties.\n *\n * DataTable is the core data structure for splat data. Each column represents\n * a property (e.g., position, rotation, color) as a typed array, and all columns\n * must have the same number of rows.\n *\n * Standard columns include:\n * - Position: `x`, `y`, `z`\n * - Rotation: `rot_0`, `rot_1`, `rot_2`, `rot_3` (quaternion)\n * - Scale: `scale_0`, `scale_1`, `scale_2` (log scale)\n * - Color: `f_dc_0`, `f_dc_1`, `f_dc_2` (spherical harmonics DC)\n * - Opacity: `opacity` (logit)\n * - Spherical Harmonics: `f_rest_0` through `f_rest_44`\n *\n * @example\n * ```ts\n * const table = new DataTable([\n *     new Column('x', new Float32Array([0, 1, 2])),\n *     new Column('y', new Float32Array([0, 0, 0])),\n *     new Column('z', new Float32Array([0, 0, 0]))\n * ]);\n * console.log(table.numRows);    // 3\n * console.log(table.numColumns); // 3\n * ```\n */\nclass DataTable {\n    columns: Column[];\n    transform: Transform;\n\n    constructor(columns: Column[], transform?: Transform) {\n        if (columns.length === 0) {\n            throw new Error('DataTable must have at least one column');\n        }\n\n        // check all columns have the same lengths\n        for (let i = 1; i < columns.length; i++) {\n            if (columns[i].data.length !== columns[0].data.length) {\n                throw new Error(`Column '${columns[i].name}' has inconsistent number of rows: expected ${columns[0].data.length}, got ${columns[i].data.length}`);\n            }\n        }\n\n        this.columns = columns;\n        this.transform = transform ? transform.clone() : new Transform();\n    }\n\n    // rows\n\n    get numRows() {\n        return this.columns[0].data.length;\n    }\n\n    getRow(index: number, row: Row = {}, columns = this.columns): Row {\n        for (const column of columns) {\n            row[column.name] = column.data[index];\n        }\n        return row;\n    }\n\n    setRow(index: number, row: Row, columns = this.columns) {\n        for (const column of columns) {\n            if (row.hasOwnProperty(column.name)) {\n                column.data[index] = row[column.name];\n            }\n        }\n    }\n\n    // columns\n\n    get numColumns() {\n        return this.columns.length;\n    }\n\n    get byteLength(): number {\n        let total = 0;\n        for (const column of this.columns) {\n            total += column.data.byteLength;\n        }\n        return total;\n    }\n\n    get columnNames() {\n        return this.columns.map(column => column.name);\n    }\n\n    get columnData() {\n        return this.columns.map(column => column.data);\n    }\n\n    get columnTypes() {\n        return this.columns.map(column => column.dataType);\n    }\n\n    getColumn(index: number): Column {\n        return this.columns[index];\n    }\n\n    getColumnIndex(name: string): number {\n        return this.columns.findIndex(column => column.name === name);\n    }\n\n    getColumnByName(name: string): Column | null {\n        return this.columns.find(column => column.name === name);\n    }\n\n    hasColumn(name: string): boolean {\n        return this.columns.some(column => column.name === name);\n    }\n\n    addColumn(column: Column) {\n        if (column.data.length !== this.numRows) {\n            throw new Error(`Column '${column.name}' has inconsistent number of rows: expected ${this.numRows}, got ${column.data.length}`);\n        }\n        this.columns.push(column);\n    }\n\n    removeColumn(name: string) {\n        const index = this.columns.findIndex(column => column.name === name);\n        if (index === -1) {\n            return false;\n        }\n        this.columns.splice(index, 1);\n        return true;\n    }\n\n    // general\n\n    /**\n     * Creates a copy of this DataTable, optionally selecting specific rows and/or columns.\n     *\n     * @param options - Optional selection criteria.\n     * @param options.rows - Row indices to include (and their order). If omitted, all rows are copied.\n     * @param options.columns - Column names to include. If omitted, all columns are copied.\n     * @returns A new DataTable with copied data.\n     *\n     * @example\n     * ```ts\n     * const full = table.clone();\n     * const subset = table.clone({ rows: [0, 2, 4], columns: ['x', 'y', 'z'] });\n     * ```\n     */\n    clone(options?: { rows?: Uint32Array | number[]; columns?: string[] }): DataTable {\n        const rows = options?.rows;\n        const columnNames = options?.columns;\n\n        let srcColumns: Column[];\n\n        if (columnNames !== undefined) {\n            if (columnNames.length === 0) {\n                throw new Error('DataTable.clone: \"columns\" must contain at least one column name.');\n            }\n\n            const uniqueNames = new Set(columnNames);\n            if (uniqueNames.size !== columnNames.length) {\n                const dupes = columnNames.filter((n, i) => columnNames.indexOf(n) !== i);\n                throw new Error(`DataTable.clone: duplicate column name(s): ${[...new Set(dupes)].join(', ')}`);\n            }\n\n            const missingColumns = columnNames.filter(name => !this.getColumnByName(name));\n            if (missingColumns.length > 0) {\n                throw new Error(`DataTable.clone: unknown column name(s): ${missingColumns.join(', ')}`);\n            }\n\n            srcColumns = columnNames.map(name => this.getColumnByName(name)!);\n        } else {\n            srcColumns = this.columns;\n        }\n\n        if (!rows) {\n            return new DataTable(srcColumns.map(c => c.clone()), this.transform);\n        }\n\n        const result = new DataTable(srcColumns.map((c) => {\n            const constructor = c.data.constructor as new (length: number) => TypedArray;\n            return new Column(c.name, new constructor(rows.length));\n        }), this.transform);\n\n        for (let i = 0; i < result.numColumns; ++i) {\n            const src = srcColumns[i].data;\n            const dst = result.getColumn(i).data;\n            for (let j = 0; j < rows.length; j++) {\n                dst[j] = src[rows[j]];\n            }\n        }\n\n        return result;\n    }\n\n    /**\n     * Permutes the rows of this DataTable in-place according to the given indices.\n     * After calling, row `i` will contain the data that was previously at row `indices[i]`.\n     *\n     * This is a memory-efficient alternative to `clone({ rows })` that modifies the table\n     * in-place rather than creating a copy. It reuses ArrayBuffers between columns to\n     * minimize memory allocations.\n     *\n     * @param indices - Array of indices defining the permutation. Must have the same\n     * length as the number of rows, and must be a valid permutation\n     * (each index 0 to n-1 appears exactly once).\n     */\n    permuteRowsInPlace(indices: Uint32Array | number[]): void {\n        // Cache for reusing ArrayBuffers by size\n        const cache = new Map<number, ArrayBuffer>();\n\n        const getBuffer = (size: number): ArrayBuffer => {\n            const cached = cache.get(size);\n            if (cached) {\n                cache.delete(size);\n                return cached;\n            }\n            return new ArrayBuffer(size);\n        };\n\n        const returnBuffer = (buffer: ArrayBuffer): void => {\n            cache.set(buffer.byteLength, buffer);\n        };\n\n        const n = this.numRows;\n\n        for (const column of this.columns) {\n            const src = column.data;\n            const constructor = src.constructor as new (buffer: ArrayBuffer) => TypedArray;\n            const dst = new constructor(getBuffer(src.byteLength));\n\n            // Sequential writes are cache-friendly\n            for (let i = 0; i < n; i++) {\n                dst[i] = src[indices[i]];\n            }\n\n            returnBuffer(src.buffer as ArrayBuffer);\n            column.data = dst;\n        }\n    }\n}\n\nexport { Column, DataTable, TypedArray, ColumnType, Row };\n","import { Mat3, Quat, Vec3 } from 'playcanvas';\n\nimport { Column, DataTable, TypedArray } from './data-table';\nimport { Transform, RotateSH } from '../utils';\n\nconst shNames = new Array(45).fill('').map((_, i) => `f_rest_${i}`);\n\nconst _v = new Vec3();\nconst _q = new Quat();\n\n// -- Helpers for on-demand column generation --\n\n/**\n * Computes the delta transform needed to convert raw data from its current\n * coordinate system into the output format's coordinate system.\n *\n * @param transform - The DataTable's current source transform.\n * @param outputFormatTransform - The output format's expected transform.\n * @returns The delta transform to apply to raw data, or null if it is identity.\n */\nconst computeWriteTransform = (transform: Transform, outputFormatTransform: Transform): Transform | null => {\n    const delta = outputFormatTransform.clone().invert().mul(transform);\n    return delta.isIdentity() ? null : delta;\n};\n\n/**\n * Detects how many SH bands (0-3) the DataTable has.\n * @ignore\n */\nconst detectSHBands = (dataTable: DataTable): number => {\n    return ({ '9': 1, '24': 2, '-1': 3 } as Record<string, number>)[String(shNames.findIndex(n => !dataTable.hasColumn(n)))] ?? 0;\n};\n\n/**\n * Generates transformed typed arrays for requested columns, applying the given\n * transform. Columns unaffected by the transform return references to the\n * original arrays (zero copy).\n *\n * @param dataTable - The source DataTable.\n * @param columnNames - Which columns to produce.\n * @param delta - The transform to apply. If identity or null, original arrays are returned.\n * @param inPlace - If true, mutate the DataTable's existing column arrays instead of allocating new ones.\n * @returns A map of column name to typed array.\n */\nconst transformColumns = (dataTable: DataTable, columnNames: string[], delta: Transform | null, inPlace = false): Map<string, TypedArray> => {\n    const result = new Map<string, TypedArray>();\n\n    if (!delta || delta.isIdentity()) {\n        for (const name of columnNames) {\n            const col = dataTable.getColumnByName(name);\n            if (col) result.set(name, col.data);\n        }\n        return result;\n    }\n\n    const numRows = dataTable.numRows;\n    const r = delta.rotation;\n    const s = delta.scale;\n\n    // Categorize requested columns\n    const posNames = ['x', 'y', 'z'];\n    const rotNames = ['rot_0', 'rot_1', 'rot_2', 'rot_3'];\n    const scaleNames = ['scale_0', 'scale_1', 'scale_2'];\n\n    const hasPos = posNames.every(n => dataTable.hasColumn(n));\n    const needPos = hasPos && posNames.some(n => columnNames.includes(n));\n    const hasRot = rotNames.every(n => dataTable.hasColumn(n));\n    const needRot = hasRot && rotNames.some(n => columnNames.includes(n));\n    const needScale = scaleNames.some(n => columnNames.includes(n) && dataTable.hasColumn(n)) && s !== 1;\n\n    const shBands = detectSHBands(dataTable);\n    const shCoeffsPerChannel = [0, 3, 8, 15][shBands];\n    const rotIsIdentity = Math.abs(Math.abs(r.w) - 1) < 1e-6;\n    const requestedSH = shBands > 0 && !rotIsIdentity && shNames.slice(0, shCoeffsPerChannel * 3).some(n => columnNames.includes(n));\n\n    // Position columns\n    if (needPos) {\n        const srcX = dataTable.getColumnByName('x')!.data;\n        const srcY = dataTable.getColumnByName('y')!.data;\n        const srcZ = dataTable.getColumnByName('z')!.data;\n        const dstX = inPlace ? srcX : new Float32Array(numRows);\n        const dstY = inPlace ? srcY : new Float32Array(numRows);\n        const dstZ = inPlace ? srcZ : new Float32Array(numRows);\n\n        for (let i = 0; i < numRows; ++i) {\n            _v.set(srcX[i], srcY[i], srcZ[i]);\n            delta.transformPoint(_v, _v);\n            dstX[i] = _v.x;\n            dstY[i] = _v.y;\n            dstZ[i] = _v.z;\n        }\n\n        if (columnNames.includes('x')) result.set('x', dstX);\n        if (columnNames.includes('y')) result.set('y', dstY);\n        if (columnNames.includes('z')) result.set('z', dstZ);\n    }\n\n    // Rotation columns\n    if (needRot) {\n        const src0 = dataTable.getColumnByName('rot_0')!.data;\n        const src1 = dataTable.getColumnByName('rot_1')!.data;\n        const src2 = dataTable.getColumnByName('rot_2')!.data;\n        const src3 = dataTable.getColumnByName('rot_3')!.data;\n        const dst0 = inPlace ? src0 : new Float32Array(numRows);\n        const dst1 = inPlace ? src1 : new Float32Array(numRows);\n        const dst2 = inPlace ? src2 : new Float32Array(numRows);\n        const dst3 = inPlace ? src3 : new Float32Array(numRows);\n\n        for (let i = 0; i < numRows; ++i) {\n            _q.set(src1[i], src2[i], src3[i], src0[i]).mul2(r, _q);\n            dst0[i] = _q.w;\n            dst1[i] = _q.x;\n            dst2[i] = _q.y;\n            dst3[i] = _q.z;\n        }\n\n        if (columnNames.includes('rot_0')) result.set('rot_0', dst0);\n        if (columnNames.includes('rot_1')) result.set('rot_1', dst1);\n        if (columnNames.includes('rot_2')) result.set('rot_2', dst2);\n        if (columnNames.includes('rot_3')) result.set('rot_3', dst3);\n    }\n\n    // Scale columns (only affected when uniform scale != 1)\n    if (needScale) {\n        const logS = Math.log(s);\n        for (const name of scaleNames) {\n            if (!columnNames.includes(name) || !dataTable.hasColumn(name)) continue;\n            const src = dataTable.getColumnByName(name)!.data;\n            const dst = inPlace ? src : new Float32Array(numRows);\n            for (let i = 0; i < numRows; ++i) {\n                dst[i] = src[i] + logS;\n            }\n            result.set(name, dst);\n        }\n    }\n\n    // SH columns\n    if (requestedSH) {\n        const mat3 = new Mat3().setFromQuat(r);\n        const rotateSH = new RotateSH(mat3);\n        const shCoeffs = new Float32Array(shCoeffsPerChannel);\n\n        const shSrc: Float32Array[][] = [];\n        const shDst: Float32Array[][] = [];\n        for (let j = 0; j < 3; ++j) {\n            const src: Float32Array[] = [];\n            const dst: Float32Array[] = [];\n            for (let k = 0; k < shCoeffsPerChannel; ++k) {\n                const name = shNames[k + j * shCoeffsPerChannel];\n                const colData = dataTable.getColumnByName(name)!.data as Float32Array;\n                src.push(colData);\n                dst.push(inPlace ? colData : new Float32Array(numRows));\n            }\n            shSrc.push(src);\n            shDst.push(dst);\n        }\n\n        for (let i = 0; i < numRows; ++i) {\n            for (let j = 0; j < 3; ++j) {\n                for (let k = 0; k < shCoeffsPerChannel; ++k) {\n                    shCoeffs[k] = shSrc[j][k][i];\n                }\n                rotateSH.apply(shCoeffs);\n                for (let k = 0; k < shCoeffsPerChannel; ++k) {\n                    shDst[j][k][i] = shCoeffs[k];\n                }\n            }\n        }\n\n        for (let j = 0; j < 3; ++j) {\n            for (let k = 0; k < shCoeffsPerChannel; ++k) {\n                const name = shNames[k + j * shCoeffsPerChannel];\n                if (columnNames.includes(name)) {\n                    result.set(name, shDst[j][k]);\n                }\n            }\n        }\n    }\n\n    // All remaining requested columns: return original array references\n    for (const name of columnNames) {\n        if (!result.has(name)) {\n            const col = dataTable.getColumnByName(name);\n            if (col) result.set(name, col.data);\n        }\n    }\n\n    return result;\n};\n\n/**\n * Returns a DataTable with column data converted to the target coordinate\n * space. If the DataTable is already in that space, returns it unchanged.\n *\n * @param dataTable - The source DataTable.\n * @param targetTransform - The desired coordinate-space transform.\n * @param inPlace - If true, mutate the DataTable's column arrays and transform\n * in place instead of allocating a new DataTable. The caller must ensure no\n * other code depends on the original column data.\n * @returns A DataTable whose raw data is in the target coordinate space.\n */\nconst convertToSpace = (dataTable: DataTable, targetTransform: Transform, inPlace = false): DataTable => {\n    const delta = computeWriteTransform(dataTable.transform, targetTransform);\n    if (!delta) return dataTable;\n\n    if (inPlace) {\n        const allNames = dataTable.columnNames;\n        transformColumns(dataTable, allNames, delta, true);\n        dataTable.transform = targetTransform.clone();\n        return dataTable;\n    }\n\n    const allNames = dataTable.columnNames;\n    const cols = transformColumns(dataTable, allNames, delta);\n    return new DataTable(allNames.map(name => new Column(name, cols.get(name)!)), targetTransform);\n};\n\nexport {\n    transformColumns,\n    computeWriteTransform,\n    convertToSpace\n};\n","import { Column, DataTable, TypedArray } from './data-table';\nimport { convertToSpace } from './transform';\nimport { logger, Transform } from '../utils';\n\n/**\n * Combines multiple DataTables into a single DataTable.\n *\n * Merges rows from all input tables. Columns are matched by name and type;\n * columns that don't exist in all tables will have undefined values for\n * rows from tables lacking that column.\n *\n * If tables have differing source transforms, all data is first converted\n * to engine coordinate space (identity transform) before combining.\n *\n * @param dataTables - Array of DataTables to combine.\n * @returns A new DataTable containing all rows from all input tables.\n *\n * @example\n * ```ts\n * const combined = combine([tableA, tableB, tableC]);\n * console.log(combined.numRows); // tableA.numRows + tableB.numRows + tableC.numRows\n * ```\n */\nconst combine = (dataTables: DataTable[]) : DataTable => {\n    if (dataTables.length === 1) {\n        return dataTables[0];\n    }\n\n    // Check if all transforms match the first table's transform\n    const refTransform = dataTables[0].transform;\n    const allMatch = dataTables.every(dt => dt.transform.equals(refTransform));\n\n    let tables = dataTables;\n    let resultTransform = refTransform;\n\n    if (!allMatch) {\n        logger.warn('Combining DataTables with different source transforms; converting to engine space.');\n        tables = dataTables.map(dt => convertToSpace(dt, Transform.IDENTITY));\n        resultTransform = Transform.IDENTITY;\n    }\n\n    const findMatchingColumn = (columns: Column[], column: Column) => {\n        for (let i = 0; i < columns.length; ++i) {\n            if (columns[i].name === column.name &&\n                columns[i].dataType === column.dataType) {\n                return columns[i];\n            }\n        }\n        return null;\n    };\n\n    // make unique list of columns where name and type must match\n    const columns = tables[0].columns.slice();\n    for (let i = 1; i < tables.length; ++i) {\n        const dataTable = tables[i];\n        for (let j = 0; j < dataTable.columns.length; ++j) {\n            if (!findMatchingColumn(columns, dataTable.columns[j])) {\n                columns.push(dataTable.columns[j]);\n            }\n        }\n    }\n\n    // count total number of rows\n    const totalRows = tables.reduce((sum, dataTable) => sum + dataTable.numRows, 0);\n\n    // construct output dataTable\n    const resultColumns = columns.map((column) => {\n        const constructor = column.data.constructor as new (length: number) => TypedArray;\n        return new Column(column.name, new constructor(totalRows));\n    });\n    const result = new DataTable(resultColumns, resultTransform);\n\n    // copy data\n    let rowOffset = 0;\n    for (let i = 0; i < tables.length; ++i) {\n        const dataTable = tables[i];\n\n        for (let j = 0; j < dataTable.columns.length; ++j) {\n            const column = dataTable.columns[j];\n            const targetColumn = findMatchingColumn(result.columns, column);\n            targetColumn.data.set(column.data, rowOffset);\n        }\n\n        rowOffset += dataTable.numRows;\n    }\n\n    return result;\n};\n\nexport { combine };\n","import {\n    BUFFERUSAGE_COPY_DST,\n    BUFFERUSAGE_COPY_SRC,\n    SHADERLANGUAGE_WGSL,\n    SHADERSTAGE_COMPUTE,\n    UNIFORMTYPE_FLOAT,\n    UNIFORMTYPE_UINT,\n    BindGroupFormat,\n    BindStorageBufferFormat,\n    BindUniformBufferFormat,\n    Compute,\n    GraphicsDevice,\n    Shader,\n    StorageBuffer,\n    UniformBufferFormat,\n    UniformFormat\n} from 'playcanvas';\n\n/**\n * Appearance columns per storage chunk. The kernel exposes three appearance\n * bindings (appA/appB/appC), so the layout holds up to 3·APP_CHUNK columns; at\n * 16 the widest chunk reaches the ~2 GB per-binding limit around ~33.5M splats.\n * The CPU-side packing in `data-table/decimate.ts` imports this same constant,\n * so the kernel strides and the host packing can't drift.\n */\nexport const APP_CHUNK = 16;\n\n/**\n * WGSL kernel: per-edge KL-style cost (matches `computeEdgeCost` in\n * `data-table/decimate.ts`).\n *\n * Each thread = one edge (i, j). Reads the per-splat cache for both\n * endpoints, computes the merged Gaussian's covariance + determinant,\n * runs a single Monte-Carlo sample through both component gaussians\n * (the same `z` for both components, matching the CPU implementation),\n * and adds an L2 distance over the appearance (SH) coefficients.\n *\n * @param strideA - Live column count of appearance chunk A (0 if unused).\n * @param strideB - Live column count of appearance chunk B (0 if unused).\n * @param strideC - Live column count of appearance chunk C (0 if unused).\n * @returns WGSL source.\n */\nconst edgeCostWgsl = (strideA: number, strideB: number, strideC: number) => /* wgsl */`\nstruct Uniforms {\n    edgeCount: u32,\n    z0: f32,\n    z1: f32,\n    z2: f32,\n}\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n// Edge list for the current dispatch batch only, split into two parallel\n// arrays (avoids a host-side (i, j) interleave). The host uploads each batch's\n// slice to offset 0, so we index edgesI/J[bid] directly — keeping these\n// buffers batch-sized instead of N·k keeps them off the per-binding limit.\n@group(0) @binding(1) var<storage, read> edgesI: array<u32>;\n@group(0) @binding(2) var<storage, read> edgesJ: array<u32>;\n// Per-splat geometry, interleaved 8-wide:\n//   posScalars[8s + 0..2] = position xyz\n//   posScalars[8s + 3]    = mass\n//   posScalars[8s + 4]    = logdet\n//   posScalars[8s + 5..7] = variances (vx, vy, vz)\n@group(0) @binding(3) var<storage, read> posScalars: array<f32>;\n// Row-major 3x3 rotation matrix per splat (9 floats per splat).\n@group(0) @binding(4) var<storage, read> rotR: array<f32>;\n// Appearance, split into up to three chunks (≤16 columns each) so no single\n// binding exceeds maxStorageBufferBindingSize (~2 GB). Each chunk's stride is\n// its live column count (STRIDE_A/B/C below); appA holds columns 0.., appB the\n// next span, appC the next. Unused chunks have stride 0, are bound to a dummy\n// buffer, and are never read.\n@group(0) @binding(5) var<storage, read> appA: array<f32>;\n@group(0) @binding(6) var<storage, read> appB: array<f32>;\n@group(0) @binding(7) var<storage, read> appC: array<f32>;\n// Output: cost per edge.\n@group(0) @binding(8) var<storage, read_write> costs: array<f32>;\n\nconst EPS_COV: f32 = 1e-8;\nconst LOG2PI: f32 = 1.8378770664093453;\n// Per-chunk appearance strides = live column count in each chunk (0 = unused,\n// dummy-bound). Baked here because the column count is fixed for the lifetime\n// of the kernel, so loop bounds and indexing resolve statically.\nconst STRIDE_A: u32 = ${strideA}u;\nconst STRIDE_B: u32 = ${strideB}u;\nconst STRIDE_C: u32 = ${strideC}u;\n\n// Symmetric 3x3 covariance helpers — we pass them around as 6 f32 (xx, xy, xz, yy, yz, zz).\n\n// Σ = R · diag(v) · R^T for row-major R (a 9-float array starting at offset r9).\n// Variances v come from posScalars[s8 + 5..7]. Result is 6 floats:\n// (xx, xy, xz, yy, yz, zz).\nfn sigmaFromRotVar(r9: u32, s8: u32) -> array<f32, 6> {\n    let r00 = rotR[r9 + 0u]; let r01 = rotR[r9 + 1u]; let r02 = rotR[r9 + 2u];\n    let r10 = rotR[r9 + 3u]; let r11 = rotR[r9 + 4u]; let r12 = rotR[r9 + 5u];\n    let r20 = rotR[r9 + 6u]; let r21 = rotR[r9 + 7u]; let r22 = rotR[r9 + 8u];\n    let vx = posScalars[s8 + 5u];\n    let vy = posScalars[s8 + 6u];\n    let vz = posScalars[s8 + 7u];\n    return array<f32, 6>(\n        r00*r00*vx + r01*r01*vy + r02*r02*vz,   // xx\n        r00*r10*vx + r01*r11*vy + r02*r12*vz,   // xy\n        r00*r20*vx + r01*r21*vy + r02*r22*vz,   // xz\n        r10*r10*vx + r11*r11*vy + r12*r12*vz,   // yy\n        r10*r20*vx + r11*r21*vy + r12*r22*vz,   // yz\n        r20*r20*vx + r21*r21*vy + r22*r22*vz    // zz\n    );\n}\n\n// log N(x | mu, R · diag(v) · R^T) for a diagonally-decomposed covariance.\n// invDiag is (1/vx, 1/vy, 1/vz); ld is logdet of the full covariance.\n// Evaluates y = R^T * (x - mu) using columns of R (= rows of Rt).\nfn gaussLogpdfDiagrot(\n    x: vec3f, mu: vec3f, r9: u32,\n    invDiag: vec3f, ld: f32\n) -> f32 {\n    let dx = x.x - mu.x;\n    let dy = x.y - mu.y;\n    let dz = x.z - mu.z;\n    // y = R^T · d. R is row-major; column k of R is (R[k], R[k+3], R[k+6]).\n    let y0 = dx * rotR[r9 + 0u] + dy * rotR[r9 + 3u] + dz * rotR[r9 + 6u];\n    let y1 = dx * rotR[r9 + 1u] + dy * rotR[r9 + 4u] + dz * rotR[r9 + 7u];\n    let y2 = dx * rotR[r9 + 2u] + dy * rotR[r9 + 5u] + dz * rotR[r9 + 8u];\n    let quad = y0*y0*invDiag.x + y1*y1*invDiag.y + y2*y2*invDiag.z;\n    return -0.5 * (3.0 * LOG2PI + ld + quad);\n}\n\nfn logAddExp(a: f32, b: f32) -> f32 {\n    let m = max(a, b);\n    return m + log(exp(a - m) + exp(b - m));\n}\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3u) {\n    let bid = gid.x;\n    if (bid >= uniforms.edgeCount) { return; }\n\n    let i = edgesI[bid];\n    let j = edgesJ[bid];\n\n    let i8 = i * 8u;\n    let j8 = j * 8u;\n    let i9 = i * 9u;\n    let j9 = j * 9u;\n\n    let mu_i = vec3f(posScalars[i8 + 0u], posScalars[i8 + 1u], posScalars[i8 + 2u]);\n    let mu_j = vec3f(posScalars[j8 + 0u], posScalars[j8 + 1u], posScalars[j8 + 2u]);\n\n    let wi = posScalars[i8 + 3u];\n    let wj = posScalars[j8 + 3u];\n    let W = wi + wj;\n    let Wsafe = select(1.0, W, W > 0.0);\n    let pi_w_raw = wi / Wsafe;\n    let pi_w = clamp(pi_w_raw, 1e-12, 1.0 - 1e-12);\n    let pj_w = 1.0 - pi_w;\n    let logPi = log(pi_w);\n    let logPj = log(pj_w);\n\n    // Merged mean.\n    let mm = pi_w * mu_i + pj_w * mu_j;\n    let di = mu_i - mm;\n    let dj = mu_j - mm;\n\n    // Σ_i and Σ_j from rotation + variances.\n    let sig_i = sigmaFromRotVar(i9, i8);\n    let sig_j = sigmaFromRotVar(j9, j8);\n\n    // Merged covariance: pi*(Σ_i + δi·δiᵀ) + pj*(Σ_j + δj·δjᵀ), + EPS on diag.\n    let s_xx = pi_w * (sig_i[0] + di.x*di.x) + pj_w * (sig_j[0] + dj.x*dj.x) + EPS_COV;\n    let s_xy = pi_w * (sig_i[1] + di.x*di.y) + pj_w * (sig_j[1] + dj.x*dj.y);\n    let s_xz = pi_w * (sig_i[2] + di.x*di.z) + pj_w * (sig_j[2] + dj.x*dj.z);\n    let s_yy = pi_w * (sig_i[3] + di.y*di.y) + pj_w * (sig_j[3] + dj.y*dj.y) + EPS_COV;\n    let s_yz = pi_w * (sig_i[4] + di.y*di.z) + pj_w * (sig_j[4] + dj.y*dj.z);\n    let s_zz = pi_w * (sig_i[5] + di.z*di.z) + pj_w * (sig_j[5] + dj.z*dj.z) + EPS_COV;\n\n    // det of symmetric 3x3.\n    let det_m = s_xx * (s_yy*s_zz - s_yz*s_yz)\n              - s_xy * (s_xy*s_zz - s_yz*s_xz)\n              + s_xz * (s_xy*s_yz - s_yy*s_xz);\n    let logdet_m = log(max(det_m, 1e-30));\n\n    // Entropy of the merged Gaussian: H = 0.5 (k log(2π) + log|Σ_m| + k), k=3.\n    let EpNegLogQ = 0.5 * (3.0 * LOG2PI + logdet_m + 3.0);\n\n    // Read per-axis std for each input (variances live at posScalars[s8+5..7]).\n    let vix = posScalars[i8 + 5u]; let viy = posScalars[i8 + 6u]; let viz = posScalars[i8 + 7u];\n    let vjx = posScalars[j8 + 5u]; let vjy = posScalars[j8 + 6u]; let vjz = posScalars[j8 + 7u];\n    let stdix = sqrt(max(vix, 0.0));\n    let stdiy = sqrt(max(viy, 0.0));\n    let stdiz = sqrt(max(viz, 0.0));\n    let stdjx = sqrt(max(vjx, 0.0));\n    let stdjy = sqrt(max(vjy, 0.0));\n    let stdjz = sqrt(max(vjz, 0.0));\n\n    // Inverse diagonals (1 / variance) for the log-pdf quadratic term.\n    let invDi = vec3f(1.0 / max(vix, 1e-30), 1.0 / max(viy, 1e-30), 1.0 / max(viz, 1e-30));\n    let invDj = vec3f(1.0 / max(vjx, 1e-30), 1.0 / max(vjy, 1e-30), 1.0 / max(vjz, 1e-30));\n    let ldi = posScalars[i8 + 4u];\n    let ldj = posScalars[j8 + 4u];\n\n    let z0 = uniforms.z0;\n    let z1 = uniforms.z1;\n    let z2 = uniforms.z2;\n\n    // Sample x = mu + R · diag(std) · z where z ~ N(0, I).\n    // Row a of R is (rotR[r9+3a], rotR[r9+3a+1], rotR[r9+3a+2]).\n    // x[a] = mu[a] + R[a][0]*std[0]*z[0] + R[a][1]*std[1]*z[1] + R[a][2]*std[2]*z[2].\n    let xix = mu_i.x + z0 * stdix * rotR[i9 + 0u] + z1 * stdiy * rotR[i9 + 1u] + z2 * stdiz * rotR[i9 + 2u];\n    let xiy = mu_i.y + z0 * stdix * rotR[i9 + 3u] + z1 * stdiy * rotR[i9 + 4u] + z2 * stdiz * rotR[i9 + 5u];\n    let xiz = mu_i.z + z0 * stdix * rotR[i9 + 6u] + z1 * stdiy * rotR[i9 + 7u] + z2 * stdiz * rotR[i9 + 8u];\n    let xi = vec3f(xix, xiy, xiz);\n\n    let xjx = mu_j.x + z0 * stdjx * rotR[j9 + 0u] + z1 * stdjy * rotR[j9 + 1u] + z2 * stdjz * rotR[j9 + 2u];\n    let xjy = mu_j.y + z0 * stdjx * rotR[j9 + 3u] + z1 * stdjy * rotR[j9 + 4u] + z2 * stdjz * rotR[j9 + 5u];\n    let xjz = mu_j.z + z0 * stdjx * rotR[j9 + 6u] + z1 * stdjy * rotR[j9 + 7u] + z2 * stdjz * rotR[j9 + 8u];\n    let xj = vec3f(xjx, xjy, xjz);\n\n    // log p_ij at samples from component i.\n    let logNiOnI = gaussLogpdfDiagrot(xi, mu_i, i9, invDi, ldi);\n    let logNjOnI = gaussLogpdfDiagrot(xi, mu_j, j9, invDj, ldj);\n    let logpOnI = logAddExp(logPi + logNiOnI, logPj + logNjOnI);\n\n    let logNiOnJ = gaussLogpdfDiagrot(xj, mu_i, i9, invDi, ldi);\n    let logNjOnJ = gaussLogpdfDiagrot(xj, mu_j, j9, invDj, ldj);\n    let logpOnJ = logAddExp(logPi + logNiOnJ, logPj + logNjOnJ);\n\n    let Ei = logpOnI;\n    let Ej = logpOnJ;\n    let EpLogp = pi_w * Ei + pj_w * Ej;\n    let geo = EpLogp + EpNegLogQ;\n\n    // Appearance L2 cost, summed across the (up to three) chunks. Each chunk's\n    // stride is its live column count, so partial chunks store/read no padding.\n    // A 0 stride yields 0 iterations, so the dummy-bound appB / appC are never\n    // touched on inputs with fewer SH bands.\n    var cSh: f32 = 0.0;\n    let iA = i * STRIDE_A; let jA = j * STRIDE_A;\n    for (var k: u32 = 0u; k < STRIDE_A; k = k + 1u) {\n        let d = appA[iA + k] - appA[jA + k];\n        cSh = cSh + d * d;\n    }\n    let iB = i * STRIDE_B; let jB = j * STRIDE_B;\n    for (var k: u32 = 0u; k < STRIDE_B; k = k + 1u) {\n        let d = appB[iB + k] - appB[jB + k];\n        cSh = cSh + d * d;\n    }\n    let iC = i * STRIDE_C; let jC = j * STRIDE_C;\n    for (var k: u32 = 0u; k < STRIDE_C; k = k + 1u) {\n        let d = appC[iC + k] - appC[jC + k];\n        cSh = cSh + d * d;\n    }\n\n    costs[bid] = geo + cSh;\n}\n`;\n\n/**\n * Per-splat cache for the edge cost kernel. Packed layouts to stay within the\n * WebGPU per-stage storage-buffer count limit (8) and the per-binding size\n * limit (~2 GB) — appearance is split into 16-column chunks for the latter.\n */\ninterface EdgeCostCache {\n    /** Per-splat geometry interleaved 8-wide: (x, y, z, mass, logdet, vx, vy, vz). */\n    posScalars: Float32Array;\n    /** Row-major 3×3 rotation per splat (length 9N). */\n    rotR: Float32Array;\n    /**\n     * Appearance in up to three chunks of ≤16 columns. Chunk c has stride\n     * width_c (= its live column count): appChunks[c][s * width_c + k].\n     */\n    appChunks: Float32Array[];\n    /** Number of appearance columns C. */\n    numAppCols: number;\n    /** Number of splats. */\n    numSplats: number;\n}\n\n/**\n * GPU edge-cost evaluator.\n *\n * Each compute thread evaluates the KL-style cost for one edge (i, j) by\n * reading the per-splat cache for both endpoints, computing the merged\n * Gaussian's covariance/determinant, running a single Monte-Carlo sample\n * through both component PDFs, and adding an L2 distance over the\n * appearance (SH) coefficients. Output is `costs[e] = cost for edge e`.\n *\n * Mirrors the CPU `computeEdgeCost` in `data-table/decimate.ts`.\n */\nclass GpuEdgeCost {\n    /**\n     * @param cache - Per-splat cache (uploaded once).\n     * @param edgeI - Edge u indices (length E).\n     * @param edgeJ - Edge v indices (length E).\n     * @param z - Single Monte-Carlo sample (3 floats from N(0,1)).\n     * @param outCosts - Destination for per-edge costs (length E).\n     */\n    execute: (\n        cache: EdgeCostCache,\n        edgeI: Uint32Array,\n        edgeJ: Uint32Array,\n        z: Float32Array,\n        outCosts: Float32Array\n    ) => Promise<void>;\n    destroy: () => void;\n\n    /**\n     * @param device - PlayCanvas GraphicsDevice (WebGPU).\n     * @param maxN - Maximum number of splats.\n     * @param maxE - Maximum number of edges in a single dispatch.\n     * @param maxAppCols - Maximum appearance column count (over all bands).\n     */\n    constructor(device: GraphicsDevice, maxN: number, maxE: number, maxAppCols: number) {\n        const workgroupSize = 64;\n        const edgesPerBatch = 1024 * workgroupSize;  // 65,536\n        // Appearance is split at fixed APP_CHUNK-column boundaries, but each\n        // chunk's *stride* is its live column count — only the last non-empty\n        // chunk is ever partial, so partial chunks neither allocate nor upload\n        // padding. The widest possible chunk reaches the ~2 GB limit at ~33.5M\n        // splats, past the ~11.2M wall the single 48-col buffer hit. The three\n        // kernel bindings (appA/appB/appC) cap the layout at three chunks.\n        // e.g. [16, 11, 0] for 27 cols, [3, 0, 0] for DC-only.\n        const appStrides = [0, 1, 2].map((ch) => {\n            return Math.min(APP_CHUNK, Math.max(0, maxAppCols - ch * APP_CHUNK));\n        });\n        // Non-empty chunk count the kernel reads. execute() validates the cache\n        // supplies exactly this many: a short count would leave a hoisted (reused\n        // across iterations) appearance buffer holding the previous iteration's\n        // data, which the kernel would then read as this iteration's appearance.\n        const numAppChunks = appStrides.filter(stride => stride > 0).length;\n\n        const bindGroupFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('edgesI', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('edgesJ', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('posScalars', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('rotR', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('appA', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('appB', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('appC', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('costs', SHADERSTAGE_COMPUTE)\n        ]);\n\n        const shader = new Shader(device, {\n            name: 'compute-edge-cost',\n            shaderLanguage: SHADERLANGUAGE_WGSL,\n            cshader: edgeCostWgsl(appStrides[0], appStrides[1], appStrides[2]),\n            // @ts-ignore\n            computeUniformBufferFormats: {\n                uniforms: new UniformBufferFormat(device, [\n                    new UniformFormat('edgeCount', UNIFORMTYPE_UINT),\n                    new UniformFormat('z0', UNIFORMTYPE_FLOAT),\n                    new UniformFormat('z1', UNIFORMTYPE_FLOAT),\n                    new UniformFormat('z2', UNIFORMTYPE_FLOAT)\n                ])\n            },\n            // @ts-ignore\n            computeBindGroupFormat: bindGroupFormat\n        });\n\n        // Pre-flight the largest per-N bindings against the device's storage\n        // limit so we fail with a clear message instead of a driver-side error.\n        // Edges are uploaded per batch (batch-sized buffers), so they can't hit\n        // the limit; the widest appearance chunk and rotR are the candidates.\n        // posScalars (8 floats/splat) is strictly smaller than rotR (9), so the\n        // rotR check already bounds it — no separate check needed.\n        const maxStorage = (device as any).limits?.maxStorageBufferBindingSize;\n        if (typeof maxStorage === 'number') {\n            const checkLimit = (label: string, bytes: number) => {\n                if (bytes > maxStorage) {\n                    throw new Error(\n                        `GpuEdgeCost: ${label} buffer (${bytes} bytes) exceeds device ` +\n                        `maxStorageBufferBindingSize (${maxStorage})`\n                    );\n                }\n            };\n            const maxChunkCols = Math.max(...appStrides);\n            checkLimit(`appearance chunk (${maxN} splats × ${maxChunkCols} cols)`, maxN * maxChunkCols * 4);\n            checkLimit(`rotR (${maxN} splats × 9)`, maxN * 9 * 4);\n        }\n\n        const posScalarsBuf = new StorageBuffer(device, maxN * 8 * 4, BUFFERUSAGE_COPY_DST);\n        const rotRBuf = new StorageBuffer(device, maxN * 9 * 4, BUFFERUSAGE_COPY_DST);\n\n        // One buffer per non-empty appearance chunk, sized to that chunk's live\n        // column count; empty slots (inputs with fewer SH bands) share a small\n        // dummy since WebGPU forbids a zero-size binding. The 3-binding layout\n        // stays fixed regardless of band count.\n        const appDummy = new StorageBuffer(device, 16, BUFFERUSAGE_COPY_DST);\n        const appBufs: StorageBuffer[] = appStrides.map((width) => {\n            return width > 0 ?\n                new StorageBuffer(device, maxN * width * 4, BUFFERUSAGE_COPY_DST) :\n                appDummy;\n        });\n\n        // Two parallel u32 buffers, sized to a single dispatch batch (not the\n        // full N·k edge list): execute uploads each batch's slice before its\n        // dispatch. Batch-sizing keeps these ~256 KB instead of N·k·4 — off the\n        // ~2 GB per-binding limit (so edges never cap scene size) and ~1.6 GB\n        // less VRAM at 13M splats. Two parallel arrays avoid a host-side pack.\n        const edgesIBuf = new StorageBuffer(device, edgesPerBatch * 4, BUFFERUSAGE_COPY_DST);\n        const edgesJBuf = new StorageBuffer(device, edgesPerBatch * 4, BUFFERUSAGE_COPY_DST);\n\n        const outBuf = new StorageBuffer(\n            device,\n            edgesPerBatch * 4,\n            BUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST\n        );\n        const outScratch = new Float32Array(edgesPerBatch);\n\n        const compute = new Compute(device, shader, 'compute-edge-cost');\n        compute.setParameter('edgesI', edgesIBuf);\n        compute.setParameter('edgesJ', edgesJBuf);\n        compute.setParameter('posScalars', posScalarsBuf);\n        compute.setParameter('rotR', rotRBuf);\n        compute.setParameter('appA', appBufs[0]);\n        compute.setParameter('appB', appBufs[1]);\n        compute.setParameter('appC', appBufs[2]);\n        compute.setParameter('costs', outBuf);\n\n        this.execute = async (\n            cache: EdgeCostCache,\n            edgeI: Uint32Array,\n            edgeJ: Uint32Array,\n            z: Float32Array,\n            outCosts: Float32Array\n        ) => {\n            const n = cache.numSplats;\n            const e = edgeI.length;\n\n            if (n > maxN) throw new Error(`GpuEdgeCost: N=${n} exceeds maxN=${maxN}`);\n            if (e > maxE) throw new Error(`GpuEdgeCost: E=${e} exceeds maxE=${maxE}`);\n            if (cache.numAppCols !== maxAppCols) {\n                throw new Error(`GpuEdgeCost: numAppCols=${cache.numAppCols} must equal maxAppCols=${maxAppCols} (baked into the kernel)`);\n            }\n            if (cache.appChunks.length !== numAppChunks) {\n                throw new Error(`GpuEdgeCost: cache supplies ${cache.appChunks.length} appearance chunks but the kernel layout expects ${numAppChunks}`);\n            }\n            if (edgeJ.length !== e || outCosts.length !== e) {\n                throw new Error('GpuEdgeCost: edgeI / edgeJ / outCosts must have same length');\n            }\n            if (z.length < 3) {\n                throw new Error('GpuEdgeCost: z must have at least 3 elements');\n            }\n\n            // Upload per-splat cache. Each appearance chunk is row-major with\n            // stride = its live column count, so we upload n*width per chunk.\n            posScalarsBuf.write(0, cache.posScalars, 0, n * 8);\n            rotRBuf.write(0, cache.rotR, 0, n * 9);\n            for (let ch = 0; ch < cache.appChunks.length; ch++) {\n                appBufs[ch].write(0, cache.appChunks[ch], 0, n * appStrides[ch]);\n            }\n\n            compute.setParameter('z0', z[0]);\n            compute.setParameter('z1', z[1]);\n            compute.setParameter('z2', z[2]);\n\n            const numBatches = Math.ceil(e / edgesPerBatch);\n            for (let batch = 0; batch < numBatches; batch++) {\n                const edgeOffset = batch * edgesPerBatch;\n                const edgeCount = Math.min(edgesPerBatch, e - edgeOffset);\n                const groups = Math.ceil(edgeCount / workgroupSize);\n\n                // Upload just this batch's edges to offset 0; the kernel indexes\n                // edgesI/J[bid] within the batch.\n                edgesIBuf.write(0, edgeI, edgeOffset, edgeCount);\n                edgesJBuf.write(0, edgeJ, edgeOffset, edgeCount);\n\n                compute.setParameter('edgeCount', edgeCount);\n\n                compute.setupDispatch(groups);\n                device.computeDispatch([compute], `edge-cost-dispatch-${batch}`);\n\n                const readBytes = edgeCount * 4;\n                await outBuf.read(0, readBytes, outScratch, true);\n                outCosts.set(outScratch.subarray(0, edgeCount), edgeOffset);\n            }\n        };\n\n        this.destroy = () => {\n            posScalarsBuf.destroy();\n            rotRBuf.destroy();\n            for (const buf of appBufs) {\n                if (buf !== appDummy) buf.destroy();\n            }\n            appDummy.destroy();\n            edgesIBuf.destroy();\n            edgesJBuf.destroy();\n            outBuf.destroy();\n            shader.destroy();\n            bindGroupFormat.destroy();\n        };\n    }\n}\n\nexport { GpuEdgeCost, type EdgeCostCache };\n","import { DataTable } from '../data-table';\n\ninterface KdTreeNode {\n    index: number;\n    count: number;          // self + children indices\n    left?: KdTreeNode;\n    right?: KdTreeNode;\n}\n\nconst nthElement = (arr: Uint32Array, lo: number, hi: number, k: number, values: any) => {\n    while (lo < hi) {\n        const mid = (lo + hi) >> 1;\n        const va = values[arr[lo]], vb = values[arr[mid]], vc = values[arr[hi]];\n        let pivotIdx: number;\n        if ((vb - va) * (vc - vb) >= 0) pivotIdx = mid;\n        else if ((va - vb) * (vc - va) >= 0) pivotIdx = lo;\n        else pivotIdx = hi;\n\n        const pivotVal = values[arr[pivotIdx]];\n        let tmp = arr[pivotIdx]; arr[pivotIdx] = arr[hi]; arr[hi] = tmp;\n        let store = lo;\n        for (let i = lo; i < hi; i++) {\n            if (values[arr[i]] < pivotVal) {\n                tmp = arr[i]; arr[i] = arr[store]; arr[store] = tmp;\n                store++;\n            }\n        }\n        tmp = arr[store]; arr[store] = arr[hi]; arr[hi] = tmp;\n\n        if (store === k) return;\n        else if (store < k) lo = store + 1;\n        else hi = store - 1;\n    }\n};\n\nclass KdTree {\n    centroids: DataTable;\n    root: KdTreeNode;\n    private colData: any[];\n\n    constructor(centroids: DataTable) {\n        const numCols = centroids.numColumns;\n        const colData = centroids.columns.map(c => c.data);\n\n        const indices = new Uint32Array(centroids.numRows);\n        for (let i = 0; i < indices.length; ++i) {\n            indices[i] = i;\n        }\n\n        const build = (lo: number, hi: number, depth: number): KdTreeNode => {\n            const count = hi - lo + 1;\n\n            if (count === 1) {\n                return { index: indices[lo], count: 1 };\n            }\n\n            const values = colData[depth % numCols];\n\n            if (count === 2) {\n                if (values[indices[lo]] > values[indices[hi]]) {\n                    const tmp = indices[lo]; indices[lo] = indices[hi]; indices[hi] = tmp;\n                }\n                return {\n                    index: indices[lo],\n                    count: 2,\n                    right: { index: indices[hi], count: 1 }\n                };\n            }\n\n            const mid = lo + (count >> 1);\n            nthElement(indices, lo, hi, mid, values);\n\n            const left = build(lo, mid - 1, depth + 1);\n            const right = build(mid + 1, hi, depth + 1);\n\n            return {\n                index: indices[mid],\n                count: 1 + left.count + right.count,\n                left,\n                right\n            };\n        };\n\n        this.centroids = centroids;\n        this.colData = colData;\n        this.root = build(0, indices.length - 1, 0);\n    }\n\n    findNearest(point: Float32Array, filterFunc?: (index: number) => boolean) {\n        const colData = this.colData;\n        const numCols = colData.length;\n\n        let mind = Infinity;\n        let mini = -1;\n        let cnt = 0;\n\n        const recurse = (node: KdTreeNode, axis: number) => {\n            const distance = point[axis] - colData[axis][node.index];\n            const next = (distance > 0) ? node.right : node.left;\n            const nextAxis = axis + 1 < numCols ? axis + 1 : 0;\n\n            cnt++;\n\n            if (next) {\n                recurse(next, nextAxis);\n            }\n\n            if (!filterFunc || filterFunc(node.index)) {\n                let thisd = 0;\n                for (let c = 0; c < numCols; c++) {\n                    const v = colData[c][node.index] - point[c];\n                    thisd += v * v;\n                }\n                if (thisd < mind) {\n                    mind = thisd;\n                    mini = node.index;\n                }\n            }\n\n            if (distance * distance < mind) {\n                const other = next === node.right ? node.left : node.right;\n                if (other) {\n                    recurse(other, nextAxis);\n                }\n            }\n        };\n\n        recurse(this.root, 0);\n\n        return { index: mini, distanceSqr: mind, cnt };\n    }\n\n    findKNearest(point: Float32Array, k: number, filterFunc?: (index: number) => boolean) {\n        if (k <= 0) {\n            return { indices: new Int32Array(0), distances: new Float32Array(0) };\n        }\n        k = Math.min(k, this.centroids.numRows);\n\n        const colData = this.colData;\n        const numCols = colData.length;\n\n        // Bounded max-heap: stores (distance, index) pairs sorted so the\n        // farthest element is at position 0, enabling O(1) pruning bound.\n        const heapDist = new Float32Array(k).fill(Infinity);\n        const heapIdx = new Int32Array(k).fill(-1);\n        let heapSize = 0;\n\n        const heapPush = (dist: number, idx: number) => {\n            if (heapSize < k) {\n                let pos = heapSize++;\n                heapDist[pos] = dist;\n                heapIdx[pos] = idx;\n                while (pos > 0) {\n                    const parent = (pos - 1) >> 1;\n                    if (heapDist[parent] < heapDist[pos]) {\n                        const td = heapDist[parent]; heapDist[parent] = heapDist[pos]; heapDist[pos] = td;\n                        const ti = heapIdx[parent]; heapIdx[parent] = heapIdx[pos]; heapIdx[pos] = ti;\n                        pos = parent;\n                    } else {\n                        break;\n                    }\n                }\n            } else if (dist < heapDist[0]) {\n                heapDist[0] = dist;\n                heapIdx[0] = idx;\n                let pos = 0;\n                for (;;) {\n                    const left = 2 * pos + 1;\n                    const right = 2 * pos + 2;\n                    let largest = pos;\n                    if (left < k && heapDist[left] > heapDist[largest]) largest = left;\n                    if (right < k && heapDist[right] > heapDist[largest]) largest = right;\n                    if (largest === pos) break;\n                    const td = heapDist[pos]; heapDist[pos] = heapDist[largest]; heapDist[largest] = td;\n                    const ti = heapIdx[pos]; heapIdx[pos] = heapIdx[largest]; heapIdx[largest] = ti;\n                    pos = largest;\n                }\n            }\n        };\n\n        const recurse = (node: KdTreeNode, axis: number) => {\n            const distance = point[axis] - colData[axis][node.index];\n            const next = (distance > 0) ? node.right : node.left;\n            const nextAxis = axis + 1 < numCols ? axis + 1 : 0;\n\n            if (next) {\n                recurse(next, nextAxis);\n            }\n\n            if (!filterFunc || filterFunc(node.index)) {\n                let thisd = 0;\n                for (let c = 0; c < numCols; c++) {\n                    const v = colData[c][node.index] - point[c];\n                    thisd += v * v;\n                }\n                heapPush(thisd, node.index);\n            }\n\n            const bound = heapSize < k ? Infinity : heapDist[0];\n            if (distance * distance < bound) {\n                const other = next === node.right ? node.left : node.right;\n                if (other) {\n                    recurse(other, nextAxis);\n                }\n            }\n        };\n\n        recurse(this.root, 0);\n\n        // Extract results sorted by distance (ascending)\n        const resultIndices = new Int32Array(heapSize);\n        const resultDist = new Float32Array(heapSize);\n        for (let i = 0; i < heapSize; i++) {\n            resultIndices[i] = heapIdx[i];\n            resultDist[i] = heapDist[i];\n        }\n\n        // Simple insertion sort by distance (k is small)\n        for (let i = 1; i < heapSize; i++) {\n            const d = resultDist[i];\n            const idx = resultIndices[i];\n            let j = i - 1;\n            while (j >= 0 && resultDist[j] > d) {\n                resultDist[j + 1] = resultDist[j];\n                resultIndices[j + 1] = resultIndices[j];\n                j--;\n            }\n            resultDist[j + 1] = d;\n            resultIndices[j + 1] = idx;\n        }\n\n        return { indices: resultIndices, distances: resultDist };\n    }\n\n    /**\n     * Flatten the tree into GPU-friendly typed arrays. Each tree node is\n     * assigned a tree-index in pre-order DFS. The arrays are parallel:\n     * for tree-index `t`, the node holds splat `nodeSplatIdx[t]` whose\n     * position is `(nodeX[t], nodeY[t], nodeZ[t])`. Children live at\n     * `nodeLeft[t]` and `nodeRight[t]` (tree indices), with the sentinel\n     * `0xFFFFFFFF` for missing children.\n     *\n     * Positions are denormalised at each tree node (rather than indirected\n     * through `nodeSplatIdx` + the source position arrays) so a tree-walk\n     * does one read per visit instead of two. Costs 12 bytes/node extra.\n     *\n     * Layout assumes the underlying `centroids` DataTable has columns\n     * `x`, `y`, `z` (the first three columns). The constructor accepts\n     * any column set, so callers must ensure these are present and first.\n     *\n     * @returns Parallel arrays of length N where N = number of points.\n     * The root is at index 0.\n     */\n    flattenForGpu(): {\n        nodeSplatIdx: Uint32Array;\n        nodeX: Float32Array;\n        nodeY: Float32Array;\n        nodeZ: Float32Array;\n        nodeLeft: Uint32Array;\n        nodeRight: Uint32Array;\n        rootIdx: number;\n        } {\n        const n = this.centroids.numRows;\n        const nodeSplatIdx = new Uint32Array(n);\n        const nodeX = new Float32Array(n);\n        const nodeY = new Float32Array(n);\n        const nodeZ = new Float32Array(n);\n        const nodeLeft = new Uint32Array(n);\n        const nodeRight = new Uint32Array(n);\n        nodeLeft.fill(0xFFFFFFFF);\n        nodeRight.fill(0xFFFFFFFF);\n\n        const x = this.colData[0], y = this.colData[1], z = this.colData[2];\n\n        // Iterative pre-order DFS: assign tree indices, then patch the parent's\n        // left/right slot when each child is visited. JS recursion blows the\n        // stack on heavily unbalanced trees, so we maintain the work stack\n        // ourselves. Encoded entries: nodeRef + (parentTreeIdx, side) where\n        // side ∈ {0 = left of parent, 1 = right of parent, 2 = root}.\n        //\n        // Max DFS depth is the tree's height. `KdTree.build` is recursive and\n        // splits at the nthElement median, so the tree is near-balanced and\n        // its height is bounded by JS's recursion limit (~10K). A fixed 64\n        // entries is enough for any tree this codebase can actually build\n        // (2^64 ≫ 10K) and avoids an `n+1`-sized scratch (~85 MB at N=17.9M).\n        const stackCap = 64;\n        const stackNode: KdTreeNode[] = [this.root];\n        const stackParent = new Int32Array(stackCap);\n        const stackSide = new Uint8Array(stackCap);\n        stackParent[0] = -1;\n        stackSide[0] = 2;\n        let sp = 1;\n\n        let cursor = 0;\n        const rootIdx = cursor;\n        while (sp > 0) {\n            sp--;\n            const node = stackNode[sp];\n            const parent = stackParent[sp];\n            const side = stackSide[sp];\n            const treeIdx = cursor++;\n            const splat = node.index;\n            nodeSplatIdx[treeIdx] = splat;\n            nodeX[treeIdx] = x[splat];\n            nodeY[treeIdx] = y[splat];\n            nodeZ[treeIdx] = z[splat];\n            if (side === 0) nodeLeft[parent] = treeIdx;\n            else if (side === 1) nodeRight[parent] = treeIdx;\n            // Push right then left so left is popped first (pre-order).\n            if (node.right) {\n                stackNode[sp] = node.right;\n                stackParent[sp] = treeIdx;\n                stackSide[sp] = 1;\n                sp++;\n            }\n            if (node.left) {\n                stackNode[sp] = node.left;\n                stackParent[sp] = treeIdx;\n                stackSide[sp] = 0;\n                sp++;\n            }\n        }\n\n        return { nodeSplatIdx, nodeX, nodeY, nodeZ, nodeLeft, nodeRight, rootIdx };\n    }\n}\n\nexport { KdTreeNode, KdTree };\n","import {\n    BUFFERUSAGE_COPY_DST,\n    BUFFERUSAGE_COPY_SRC,\n    SHADERLANGUAGE_WGSL,\n    SHADERSTAGE_COMPUTE,\n    UNIFORMTYPE_UINT,\n    BindGroupFormat,\n    BindStorageBufferFormat,\n    BindUniformBufferFormat,\n    Compute,\n    GraphicsDevice,\n    Shader,\n    StorageBuffer,\n    UniformBufferFormat,\n    UniformFormat\n} from 'playcanvas';\n\nimport { Column, DataTable } from '../data-table/data-table';\nimport { KdTree } from '../spatial/kd-tree';\n\n/**\n * WGSL kernel: iterative KD-tree K-nearest-neighbours.\n *\n * Each thread runs a depth-first traversal of the flattened KD-tree with a\n * fixed-size per-thread stack. Visits at most `O(K · log N)` nodes per\n * query thanks to the standard \"skip the far subtree if its splitting plane\n * is farther than the current K-th best\" pruning. Top-K is maintained\n * unsorted in per-thread storage with explicit worst-index tracking, so the\n * common-case \"candidate is rejected against worst\" path is a single\n * compare-and-branch (no dynamic-indexed shift).\n *\n * @param k - Compile-time K, the number of nearest neighbours per query.\n * @param stackSize - Compile-time per-thread DFS stack depth.\n * @returns WGSL source.\n */\nconst knnWgsl = (k: number, stackSize: number) => /* wgsl */`\nstruct Uniforms {\n    queryOffset: u32,\n    queryCount: u32,\n    rootIdx: u32,\n}\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n// Query positions interleaved xyz: positions[q*3 + 0/1/2].\n@group(0) @binding(1) var<storage, read> positions: array<f32>;\n// Flattened KD-tree. Positions and children are interleaved so the kernel\n// stays comfortably under the WebGPU per-stage storage-buffer minimum (8):\n// nodePositions[t*3 + 0/1/2] for tree node t, nodeChildren[t*2 + 0/1] for\n// (left, right). Kept separate from nodeSplatIdx to avoid mixing f32/u32.\n@group(0) @binding(2) var<storage, read> nodeSplatIdx: array<u32>;\n@group(0) @binding(3) var<storage, read> nodePositions: array<f32>;\n@group(0) @binding(4) var<storage, read> nodeChildren: array<u32>;\n// Output: per query, k neighbour splat indices (unsorted).\n@group(0) @binding(5) var<storage, read_write> outIndices: array<u32>;\n\nconst K: u32 = ${k}u;\nconst NULL_NODE: u32 = 0xFFFFFFFFu;\nconst F32_MAX: f32 = 3.4028234663852886e+38;\n// log2(N) + slack — safe to ~2^40 nodes which is way past our limits.\nconst STACK_SIZE: u32 = ${stackSize}u;\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3u) {\n    let bid = gid.x;\n    if (bid >= uniforms.queryCount) { return; }\n    let q = bid + uniforms.queryOffset;\n\n    let q3 = q * 3u;\n    let qx = positions[q3 + 0u];\n    let qy = positions[q3 + 1u];\n    let qz = positions[q3 + 2u];\n\n    // Top-K state, unsorted. worstIdx points to the current K-th worst slot\n    // so accepts replace it in O(1) and we recompute worst via a fixed loop.\n    var topIdx: array<u32, ${k}>;\n    var topDist: array<f32, ${k}>;\n    var worst: f32 = F32_MAX;\n    var worstIdx: u32 = 0u;\n    for (var i: u32 = 0u; i < K; i++) {\n        topDist[i] = F32_MAX;\n        topIdx[i] = 0u;\n    }\n\n    // Stack: (nodeIdx, axis) packed as u32. axis ∈ {0,1,2} in top 2 bits,\n    // nodeIdx in low 30 — supports up to ~1B nodes.\n    var stack: array<u32, ${stackSize}>;\n    var sp: u32 = 0u;\n    stack[0] = uniforms.rootIdx;   // axis=0 → no axis bits set\n    sp = 1u;\n\n    while (sp > 0u) {\n        sp = sp - 1u;\n        let packed = stack[sp];\n        let nodeIdx = packed & 0x3FFFFFFFu;\n        let axis = packed >> 30u;\n\n        // Read the node's position + splat id.\n        let np = nodeIdx * 3u;\n        let nx = nodePositions[np + 0u];\n        let ny = nodePositions[np + 1u];\n        let nz = nodePositions[np + 2u];\n        let splatId = nodeSplatIdx[nodeIdx];\n\n        // Update top-K, skipping the query itself.\n        if (splatId != q) {\n            let dx = nx - qx;\n            let dy = ny - qy;\n            let dz = nz - qz;\n            let d2 = dx * dx + dy * dy + dz * dz;\n            if (d2 < worst) {\n                topDist[worstIdx] = d2;\n                topIdx[worstIdx] = splatId;\n                // Recompute worst with a constant-bound loop (compiler can\n                // unroll → all accesses to topDist resolve statically).\n                var w: f32 = topDist[0];\n                var wi: u32 = 0u;\n                for (var i: u32 = 1u; i < K; i++) {\n                    if (topDist[i] > w) { w = topDist[i]; wi = i; }\n                }\n                worst = w;\n                worstIdx = wi;\n            }\n        }\n\n        // Choose near/far children based on which side of the splitting\n        // plane the query lies on. Walk near first (push far first so LIFO\n        // pops near first), with pruning on far.\n        var qAxisVal: f32;\n        var nAxisVal: f32;\n        if (axis == 0u) { qAxisVal = qx; nAxisVal = nx; }\n        else if (axis == 1u) { qAxisVal = qy; nAxisVal = ny; }\n        else { qAxisVal = qz; nAxisVal = nz; }\n\n        let delta = qAxisVal - nAxisVal;\n        let nextAxis = select(axis + 1u, 0u, axis + 1u >= 3u);\n        let nextAxisPacked = nextAxis << 30u;\n\n        let nc = nodeIdx * 2u;\n        let leftChild = nodeChildren[nc + 0u];\n        let rightChild = nodeChildren[nc + 1u];\n        let near = select(rightChild, leftChild, delta < 0.0);\n        let far = select(leftChild, rightChild, delta < 0.0);\n\n        // Push far first iff its subtree could still hold a closer point\n        // than the current K-th best.\n        if (far != NULL_NODE && delta * delta < worst) {\n            stack[sp] = far | nextAxisPacked;\n            sp = sp + 1u;\n        }\n        if (near != NULL_NODE) {\n            stack[sp] = near | nextAxisPacked;\n            sp = sp + 1u;\n        }\n    }\n\n    // Emit unsorted top-K (the decimator does not require sorted neighbours).\n    // Slots that never received a real candidate (n-1 < K) keep F32_MAX in\n    // topDist; emit the sentinel 0xFFFFFFFF for those so downstream\n    // edge-extraction can skip them, matching the CPU path.\n    let outBase = bid * K;\n    for (var i: u32 = 0u; i < K; i++) {\n        if (topDist[i] == F32_MAX) {\n            outIndices[outBase + i] = 0xFFFFFFFFu;\n        } else {\n            outIndices[outBase + i] = topIdx[i];\n        }\n    }\n}\n`;\n\n/**\n * GPU K-nearest-neighbours over a fixed point set using a flattened KD-tree.\n *\n * Algorithm: classic KD-tree DFS with bounded heap pruning, except the\n * recursion is unrolled into an explicit per-thread stack and the top-K is\n * maintained unsorted (with worst-index tracking) so the dominant\n * candidate-rejection path is a single compare. Same O(N log N) total work\n * as the CPU KD-tree the kernel mirrors, just parallelised across queries.\n *\n * Setup cost: O(N log N) for the CPU `KdTree` build + an O(N) DFS to\n * flatten into typed arrays.\n *\n * Memory footprint: ~24 N bytes for the flattened tree (3 floats + 3\n * u32 per node), plus query positions and the per-query output indices.\n */\nclass GpuKnn {\n    /**\n     * @param px - x coordinates of the N points (which double as queries).\n     * @param py - y coordinates.\n     * @param pz - z coordinates.\n     * @param outNeighbours - destination for per-query K neighbour indices,\n     * length `N * k`. `outNeighbours[i * k + j]` is one of the k nearest\n     * neighbours of point i (UNSORTED). Excludes i itself.\n     */\n    execute: (\n        px: Float32Array,\n        py: Float32Array,\n        pz: Float32Array,\n        outNeighbours: Uint32Array\n    ) => Promise<void>;\n    destroy: () => void;\n\n    /**\n     * @param device - PlayCanvas GraphicsDevice (WebGPU).\n     * @param maxN - Maximum number of points the index will handle.\n     * @param k - Number of nearest neighbours per query.\n     */\n    constructor(device: GraphicsDevice, maxN: number, k: number) {\n        const workgroupSize = 64;\n        const queriesPerBatch = 1024 * workgroupSize;  // 65,536\n        // Per-thread DFS stack depth: tree depth = log2(maxN) + slack. 48 is\n        // safe for any N within the 30-bit nodeIdx packing limit checked below.\n        const stackSize = 48;\n        if (maxN > 0x3FFFFFFF) {\n            throw new Error(`GpuKnn: maxN=${maxN} exceeds 30-bit nodeIdx packing limit (~1B nodes)`);\n        }\n\n        // 5 storage buffers + 1 uniform — comfortably under the WebGPU\n        // per-stage minimum (8 storage buffers). Positions and KD-tree\n        // arrays are interleaved (see WGSL above) to keep the count down.\n        const bindGroupFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('positions', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('nodeSplatIdx', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('nodePositions', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('nodeChildren', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('outIndices', SHADERSTAGE_COMPUTE)\n        ]);\n\n        const shader = new Shader(device, {\n            name: 'compute-knn-kdtree',\n            shaderLanguage: SHADERLANGUAGE_WGSL,\n            cshader: knnWgsl(k, stackSize),\n            // @ts-ignore\n            computeUniformBufferFormats: {\n                uniforms: new UniformBufferFormat(device, [\n                    new UniformFormat('queryOffset', UNIFORMTYPE_UINT),\n                    new UniformFormat('queryCount', UNIFORMTYPE_UINT),\n                    new UniformFormat('rootIdx', UNIFORMTYPE_UINT)\n                ])\n            },\n            // @ts-ignore\n            computeBindGroupFormat: bindGroupFormat\n        });\n\n        const positionsBuf = new StorageBuffer(device, maxN * 3 * 4, BUFFERUSAGE_COPY_DST);\n        const nSplatIdxBuf = new StorageBuffer(device, maxN * 4, BUFFERUSAGE_COPY_DST);\n        const nPositionsBuf = new StorageBuffer(device, maxN * 3 * 4, BUFFERUSAGE_COPY_DST);\n        const nChildrenBuf = new StorageBuffer(device, maxN * 2 * 4, BUFFERUSAGE_COPY_DST);\n\n        const outBatchBytes = queriesPerBatch * k * 4;\n        const outBuf = new StorageBuffer(\n            device,\n            outBatchBytes,\n            BUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST\n        );\n        const outScratch = new Uint32Array(queriesPerBatch * k);\n\n        const compute = new Compute(device, shader, 'compute-knn-kdtree');\n        compute.setParameter('positions', positionsBuf);\n        compute.setParameter('nodeSplatIdx', nSplatIdxBuf);\n        compute.setParameter('nodePositions', nPositionsBuf);\n        compute.setParameter('nodeChildren', nChildrenBuf);\n        compute.setParameter('outIndices', outBuf);\n\n        // Pack scratches reused across execute() calls — avoids allocating\n        // O(N) every call when simplifyGaussians runs the KNN per iteration.\n        let positionsPacked = new Float32Array(0);\n        let nodePosPacked = new Float32Array(0);\n        let nodeChildrenPacked = new Uint32Array(0);\n\n        this.execute = async (\n            px: Float32Array,\n            py: Float32Array,\n            pz: Float32Array,\n            outNeighbours: Uint32Array\n        ) => {\n            const n = px.length;\n            if (n > maxN) {\n                throw new Error(`GpuKnn: N=${n} exceeds maxN=${maxN}`);\n            }\n            if (py.length !== n || pz.length !== n) {\n                throw new Error('GpuKnn: px, py, pz must all have same length');\n            }\n            if (outNeighbours.length !== n * k) {\n                throw new Error(`GpuKnn: outNeighbours length ${outNeighbours.length} must be N*k = ${n * k}`);\n            }\n\n            // Build the KD-tree on CPU. The existing `KdTree` constructor\n            // accepts a DataTable with x/y/z columns first.\n            const posTable = new DataTable([\n                new Column('x', px),\n                new Column('y', py),\n                new Column('z', pz)\n            ]);\n            const tree = new KdTree(posTable);\n            const flat = tree.flattenForGpu();\n\n            // Pack query positions xyz-interleaved into a scratch (one buffer\n            // upload instead of three).\n            if (positionsPacked.length < n * 3) positionsPacked = new Float32Array(n * 3);\n            for (let i = 0; i < n; i++) {\n                positionsPacked[i * 3 + 0] = px[i];\n                positionsPacked[i * 3 + 1] = py[i];\n                positionsPacked[i * 3 + 2] = pz[i];\n            }\n            // Pack node positions xyz-interleaved.\n            if (nodePosPacked.length < n * 3) nodePosPacked = new Float32Array(n * 3);\n            const nodeX = flat.nodeX, nodeY = flat.nodeY, nodeZ = flat.nodeZ;\n            for (let i = 0; i < n; i++) {\n                nodePosPacked[i * 3 + 0] = nodeX[i];\n                nodePosPacked[i * 3 + 1] = nodeY[i];\n                nodePosPacked[i * 3 + 2] = nodeZ[i];\n            }\n            // Pack node children (left, right) pairs.\n            if (nodeChildrenPacked.length < n * 2) nodeChildrenPacked = new Uint32Array(n * 2);\n            const nodeLeft = flat.nodeLeft, nodeRight = flat.nodeRight;\n            for (let i = 0; i < n; i++) {\n                nodeChildrenPacked[i * 2 + 0] = nodeLeft[i];\n                nodeChildrenPacked[i * 2 + 1] = nodeRight[i];\n            }\n\n            positionsBuf.write(0, positionsPacked, 0, n * 3);\n            nSplatIdxBuf.write(0, flat.nodeSplatIdx, 0, n);\n            nPositionsBuf.write(0, nodePosPacked, 0, n * 3);\n            nChildrenBuf.write(0, nodeChildrenPacked, 0, n * 2);\n            compute.setParameter('rootIdx', flat.rootIdx);\n\n            const numBatches = Math.ceil(n / queriesPerBatch);\n            for (let batch = 0; batch < numBatches; batch++) {\n                const queryOffset = batch * queriesPerBatch;\n                const queryCount = Math.min(queriesPerBatch, n - queryOffset);\n                const groups = Math.ceil(queryCount / workgroupSize);\n\n                compute.setParameter('queryOffset', queryOffset);\n                compute.setParameter('queryCount', queryCount);\n\n                compute.setupDispatch(groups);\n                device.computeDispatch([compute], `knn-dispatch-${batch}`);\n\n                const readBytes = queryCount * k * 4;\n                await outBuf.read(0, readBytes, outScratch, true);\n                outNeighbours.set(outScratch.subarray(0, queryCount * k), queryOffset * k);\n            }\n        };\n\n        this.destroy = () => {\n            positionsBuf.destroy();\n            nSplatIdxBuf.destroy();\n            nPositionsBuf.destroy();\n            nChildrenBuf.destroy();\n            outBuf.destroy();\n            shader.destroy();\n            bindGroupFormat.destroy();\n        };\n    }\n}\n\nexport { GpuKnn };\n","/**\n * Reusable scratch buffers for `radixSortIndicesByFloat`. One instance is\n * shared across many sort calls to avoid allocating multi-MB typed arrays on\n * every call. Buffers grow on demand and never shrink.\n *\n * Only two count-sized buffers are held; the third (encoded keys) is the\n * caller's `keys` buffer reinterpreted as u32 and encoded in place. That cuts\n * scratch from ~24 N bytes to ~16 N — at 143M edges it saves ~572 MB at peak.\n */\nclass RadixSortScratch {\n    /** Ping-pong destination for u32 keys. */\n    keysAlt: Uint32Array;\n    /** Ping-pong destination for indices. */\n    indicesAlt: Uint32Array;\n    /** Per-byte histogram, reused across passes. */\n    counts: Uint32Array;\n\n    constructor() {\n        this.keysAlt = new Uint32Array(0);\n        this.indicesAlt = new Uint32Array(0);\n        this.counts = new Uint32Array(256);\n    }\n\n    ensure(count: number): void {\n        if (count > this.keysAlt.length) {\n            this.keysAlt = new Uint32Array(count);\n            this.indicesAlt = new Uint32Array(count);\n        }\n    }\n}\n\n/**\n * Encode a Float32 bit pattern as a sortable u32: positive floats get their\n * sign bit set (so they sort above negatives), negative floats get all bits\n * inverted (so larger-magnitude negatives sort lower).\n *\n * @param bits - Float32 bit pattern.\n * @returns A u32 such that radix-sorting these values yields the same order\n * as comparator-sorting the original Float32s ascending.\n */\nconst encodeFloatKey = (bits: number): number => {\n    return (bits & 0x80000000) !== 0 ? (~bits >>> 0) : ((bits ^ 0x80000000) >>> 0);\n};\n\n/**\n * 4-pass LSD radix sort of `indices[0..count)` ascending by the Float32 value\n * at the parallel position in `keys`. Mutates `indices` in place.\n *\n * `keys[i]` is the sort key for `indices[i]` — the two arrays are parallel.\n * Callers compute both before calling and the sort permutes them together so\n * the parallel relationship is preserved on output.\n *\n * **`keys` is mutated**: its underlying buffer is reinterpreted as u32 and\n * monotonic-encoded in place to save the count-sized scratch buffer that an\n * out-of-place encode would need. Callers must treat the Float32 contents of\n * `keys` as garbage after this call.\n *\n * NaN / Inf entries are sorted to one extreme based on their bit pattern.\n * Callers that need to reject them should filter before calling. (At\n * ~250K-150M elements this is ~20x faster than a JavaScript comparator\n * sort.)\n *\n * @param indices - Integer payload, mutated in place.\n * @param keys - Float32 sort keys, parallel to `indices`. Mutated — contents are u32-encoded after this call; treat as garbage.\n * @param count - Number of valid entries (length of the parallel prefix).\n * @param scratch - Reusable scratch buffers; grown on demand.\n */\nconst radixSortIndicesByFloat = (\n    indices: Uint32Array,\n    keys: Float32Array,\n    count: number,\n    scratch: RadixSortScratch\n): void => {\n    if (count < 2) return;\n    scratch.ensure(count);\n\n    const { keysAlt, indicesAlt, counts } = scratch;\n    // Reinterpret the caller's keys buffer as u32 and encode in place — saves\n    // a count-sized `keysWork` scratch (572 MB on a 143M-edge sort).\n    const keysWork = new Uint32Array(keys.buffer, keys.byteOffset, keys.length);\n    for (let i = 0; i < count; i++) {\n        keysWork[i] = encodeFloatKey(keysWork[i]);\n    }\n\n    // 4-pass LSD radix sort, 8 bits per pass. After an even number of passes\n    // (4) the sorted output is back in the originally-supplied indices buffer.\n    let kIn = keysWork, iIn = indices;\n    let kOut = keysAlt, iOut = indicesAlt;\n\n    for (let shift = 0; shift < 32; shift += 8) {\n        counts.fill(0);\n        for (let i = 0; i < count; i++) {\n            counts[(kIn[i] >>> shift) & 0xff]++;\n        }\n        // Prefix sum → starting offsets per bucket.\n        let sum = 0;\n        for (let b = 0; b < 256; b++) {\n            const c = counts[b];\n            counts[b] = sum;\n            sum += c;\n        }\n        // Scatter.\n        for (let i = 0; i < count; i++) {\n            const b = (kIn[i] >>> shift) & 0xff;\n            const pos = counts[b]++;\n            kOut[pos] = kIn[i];\n            iOut[pos] = iIn[i];\n        }\n        // Swap input/output.\n        const tk = kIn; kIn = kOut; kOut = tk;\n        const ti = iIn; iIn = iOut; iOut = ti;\n    }\n};\n\n/**\n * Test whether a Float32 bit pattern represents NaN or ±Inf.\n * Useful for callers that want to filter non-finite keys out before sorting.\n *\n * @param bits - Float32 bit pattern.\n * @returns true if the value is NaN or infinite.\n */\nconst isFloatBitsNonFinite = (bits: number): boolean => {\n    return (bits & 0x7F800000) === 0x7F800000;\n};\n\nexport { RadixSortScratch, radixSortIndicesByFloat, isFloatBitsNonFinite };\n","import { Column, DataTable } from './data-table';\nimport { APP_CHUNK, type EdgeCostCache, GpuEdgeCost } from '../gpu/gpu-edge-cost';\nimport { GpuKnn } from '../gpu/gpu-knn';\nimport { KdTree } from '../spatial/kd-tree';\nimport {\n    isFloatBitsNonFinite,\n    RadixSortScratch,\n    radixSortIndicesByFloat\n} from '../spatial/radix-sort';\nimport { type DeviceCreator } from '../types';\nimport { logger } from '../utils';\n\nconst LOG2PI = Math.log(2 * Math.PI);\nconst KNN_K = 16;\nconst MC_SAMPLES = 1;\nconst EPS_COV = 1e-8;\nconst PROGRESS_TICKS = 100;\n\n// ---------- sigmoid / logit ----------\n\nconst sigmoid = (x: number) => 1 / (1 + Math.exp(-x));\n\nconst logit = (p: number) => {\n    p = Math.max(1e-7, Math.min(1 - 1e-7, p));\n    return Math.log(p / (1 - p));\n};\n\nconst logAddExp = (a: number, b: number) => {\n    if (a === -Infinity) return b;\n    if (b === -Infinity) return a;\n    const m = Math.max(a, b);\n    return m + Math.log(Math.exp(a - m) + Math.exp(b - m));\n};\n\n// ---------- PRNG ----------\n\nconst mulberry32 = (seed: number) => {\n    return () => {\n        let t = (seed += 0x6d2b79f5);\n        t = Math.imul(t ^ (t >>> 15), t | 1);\n        t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n        return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n    };\n};\n\nconst makeGaussianSamples = (n: number, seed: number): Float64Array[] => {\n    const rand = mulberry32(seed >>> 0);\n    const out: Float64Array[] = [];\n    while (out.length < n) {\n        const u1 = Math.max(rand(), 1e-12);\n        const u2 = rand();\n        const u3 = Math.max(rand(), 1e-12);\n        const u4 = rand();\n        const r1 = Math.sqrt(-2 * Math.log(u1));\n        const t1 = 2 * Math.PI * u2;\n        const r2 = Math.sqrt(-2 * Math.log(u3));\n        const t2 = 2 * Math.PI * u4;\n        out.push(new Float64Array([r1 * Math.cos(t1), r1 * Math.sin(t1), r2 * Math.cos(t2)]));\n    }\n    return out;\n};\n\n// ---------- 3x3 matrix helpers (row-major, 9 floats) ----------\n\nconst quatToRotmat = (qw: number, qx: number, qy: number, qz: number, out: Float32Array | Float64Array, o: number) => {\n    const xx = qx * qx, yy = qy * qy, zz = qz * qz;\n    const wx = qw * qx, wy = qw * qy, wz = qw * qz;\n    const xy = qx * qy, xz = qx * qz, yz = qy * qz;\n    out[o] = 1 - 2 * (yy + zz);\n    out[o + 1] = 2 * (xy - wz);\n    out[o + 2] = 2 * (xz + wy);\n    out[o + 3] = 2 * (xy + wz);\n    out[o + 4] = 1 - 2 * (xx + zz);\n    out[o + 5] = 2 * (yz - wx);\n    out[o + 6] = 2 * (xz - wy);\n    out[o + 7] = 2 * (yz + wx);\n    out[o + 8] = 1 - 2 * (xx + yy);\n};\n\nconst sigmaFromRotVar = (R: Float32Array | Float64Array, r: number, vx: number, vy: number, vz: number, out: Float32Array | Float64Array, o: number) => {\n    const r00 = R[r], r01 = R[r + 1], r02 = R[r + 2];\n    const r10 = R[r + 3], r11 = R[r + 4], r12 = R[r + 5];\n    const r20 = R[r + 6], r21 = R[r + 7], r22 = R[r + 8];\n    out[o] = r00 * r00 * vx + r01 * r01 * vy + r02 * r02 * vz;\n    out[o + 1] = r00 * r10 * vx + r01 * r11 * vy + r02 * r12 * vz;\n    out[o + 2] = r00 * r20 * vx + r01 * r21 * vy + r02 * r22 * vz;\n    out[o + 3] = out[o + 1];\n    out[o + 4] = r10 * r10 * vx + r11 * r11 * vy + r12 * r12 * vz;\n    out[o + 5] = r10 * r20 * vx + r11 * r21 * vy + r12 * r22 * vz;\n    out[o + 6] = out[o + 2];\n    out[o + 7] = out[o + 5];\n    out[o + 8] = r20 * r20 * vx + r21 * r21 * vy + r22 * r22 * vz;\n};\n\nconst det3 = (A: Float64Array, o: number) => {\n    return (\n        A[o] * (A[o + 4] * A[o + 8] - A[o + 5] * A[o + 7]) -\n        A[o + 1] * (A[o + 3] * A[o + 8] - A[o + 5] * A[o + 6]) +\n        A[o + 2] * (A[o + 3] * A[o + 7] - A[o + 4] * A[o + 6])\n    );\n};\n\nconst gaussLogpdfDiagrot = (\n    x: number, y: number, z: number,\n    mx: number, my: number, mz: number,\n    R: Float32Array | Float64Array, ro: number,\n    invx: number, invy: number, invz: number, logdet: number\n) => {\n    const dx = x - mx, dy = y - my, dz = z - mz;\n    const y0 = dx * R[ro] + dy * R[ro + 3] + dz * R[ro + 6];\n    const y1 = dx * R[ro + 1] + dy * R[ro + 4] + dz * R[ro + 7];\n    const y2 = dx * R[ro + 2] + dy * R[ro + 5] + dz * R[ro + 8];\n    const quad = y0 * y0 * invx + y1 * y1 * invy + y2 * y2 * invz;\n    return -0.5 * (3 * LOG2PI + logdet + quad);\n};\n\n// Jacobi eigendecomposition for 3x3 symmetric matrix (full 9-element row-major).\n// `A` and `V` are caller-provided 9-element scratch buffers; `Ain` is copied\n// into `A` on entry, and on return `A`'s diagonal holds the eigenvalues and\n// `V` holds the eigenvectors as columns. Returns nothing — caller reads from\n// the buffers it passed in. This shape exists to avoid the per-call\n// allocations the merge loop would otherwise burn at ~Nlog2(N) rate.\nconst eigenSymmetric3x3 = (Ain: Float64Array, A: Float64Array, V: Float64Array) => {\n    A.set(Ain);\n    V[0] = 1; V[1] = 0; V[2] = 0;\n    V[3] = 0; V[4] = 1; V[5] = 0;\n    V[6] = 0; V[7] = 0; V[8] = 1;\n\n    for (let iter = 0; iter < 24; iter++) {\n        let p = 0, q = 1;\n        let maxAbs = Math.abs(A[1]);\n        if (Math.abs(A[2]) > maxAbs) {\n            p = 0; q = 2; maxAbs = Math.abs(A[2]);\n        }\n        if (Math.abs(A[5]) > maxAbs) {\n            p = 1; q = 2; maxAbs = Math.abs(A[5]);\n        }\n        if (maxAbs < 1e-12) break;\n\n        const pp = 3 * p + p, qq = 3 * q + q, pq = 3 * p + q;\n        const app = A[pp], aqq = A[qq], apq = A[pq];\n        const tau = (aqq - app) / (2 * apq);\n        const t = Math.sign(tau) / (Math.abs(tau) + Math.sqrt(1 + tau * tau));\n        const c = 1 / Math.sqrt(1 + t * t);\n        const s = t * c;\n\n        for (let k = 0; k < 3; k++) {\n            if (k === p || k === q) continue;\n            const kp = 3 * k + p, kq = 3 * k + q;\n            const pk = 3 * p + k, qk = 3 * q + k;\n            const akp = A[kp], akq = A[kq];\n            A[kp] = c * akp - s * akq;\n            A[pk] = A[kp];\n            A[kq] = s * akp + c * akq;\n            A[qk] = A[kq];\n        }\n        A[pp] = c * c * app - 2 * s * c * apq + s * s * aqq;\n        A[qq] = s * s * app + 2 * s * c * apq + c * c * aqq;\n        A[pq] = 0; A[3 * q + p] = 0;\n\n        for (let k = 0; k < 3; k++) {\n            const kp = 3 * k + p, kq = 3 * k + q;\n            const vkp = V[kp], vkq = V[kq];\n            V[kp] = c * vkp - s * vkq;\n            V[kq] = s * vkp + c * vkq;\n        }\n    }\n};\n\n// Writes the unit quaternion (w, x, y, z) to `out[oo..oo+3]`. The previous\n// version returned a fresh Float64Array per call — at ~9M merge calls that's\n// 280 MB of throwaway garbage per decimate.\nconst rotmatToQuat = (R: Float64Array, o: number, out: Float64Array, oo: number) => {\n    const m00 = R[o], m11 = R[o + 4], m22 = R[o + 8];\n    const tr = m00 + m11 + m22;\n    let qw: number, qx: number, qy: number, qz: number;\n\n    if (tr > 0) {\n        const S = Math.sqrt(tr + 1) * 2;\n        qw = 0.25 * S;\n        qx = (R[o + 7] - R[o + 5]) / S;\n        qy = (R[o + 2] - R[o + 6]) / S;\n        qz = (R[o + 3] - R[o + 1]) / S;\n    } else if (R[o] > R[o + 4] && R[o] > R[o + 8]) {\n        const S = Math.sqrt(1 + R[o] - R[o + 4] - R[o + 8]) * 2;\n        qw = (R[o + 7] - R[o + 5]) / S;\n        qx = 0.25 * S;\n        qy = (R[o + 1] + R[o + 3]) / S;\n        qz = (R[o + 2] + R[o + 6]) / S;\n    } else if (R[o + 4] > R[o + 8]) {\n        const S = Math.sqrt(1 + R[o + 4] - R[o] - R[o + 8]) * 2;\n        qw = (R[o + 2] - R[o + 6]) / S;\n        qx = (R[o + 1] + R[o + 3]) / S;\n        qy = 0.25 * S;\n        qz = (R[o + 5] + R[o + 7]) / S;\n    } else {\n        const S = Math.sqrt(1 + R[o + 8] - R[o] - R[o + 4]) * 2;\n        qw = (R[o + 3] - R[o + 1]) / S;\n        qx = (R[o + 2] + R[o + 6]) / S;\n        qy = (R[o + 5] + R[o + 7]) / S;\n        qz = 0.25 * S;\n    }\n\n    const n = Math.hypot(qw, qx, qy, qz);\n    const inv = 1 / Math.max(n, 1e-12);\n    out[oo] = qw * inv;\n    out[oo + 1] = qx * inv;\n    out[oo + 2] = qy * inv;\n    out[oo + 3] = qz * inv;\n};\n\n// ====================== ELLIPSOID AREA ======================\n\n// Knud Thomsen p=1.6075 approximation for ellipsoid surface area.\n// Used as the per-splat screen-projection weight in the pairwise merge.\nconst ELLIPSOID_P = 1.6075;\nconst ellipsoidArea = (sx: number, sy: number, sz: number): number => {\n    const a = Math.pow(sx * sy, ELLIPSOID_P);\n    const b = Math.pow(sx * sz, ELLIPSOID_P);\n    const c = Math.pow(sy * sz, ELLIPSOID_P);\n    return 4 * Math.PI * Math.pow((a + b + c) / 3, 1 / ELLIPSOID_P);\n};\n\n// ====================== PER-SPLAT CACHE ======================\n\n// Float32 throughout — at 17.9M splats the cache hits ~2.5GB at Float64 and the\n// downstream cost is a noisy single-MC-sample heuristic anyway, so f32\n// precision is fine. `Rt` is dropped (derivable from `R` via index swap at\n// call sites); `invdiag` is kept since it amortises ~6 divisions per edge\n// across ~k edges per splat.\ninterface SplatCache {\n    R: Float32Array;       // row-major 3×3 rotation per splat\n    v: Float32Array;       // variances (scale^2 + eps) per axis\n    invdiag: Float32Array; // 1 / v per axis, precomputed\n    logdet: Float32Array;\n    sigma: Float32Array;   // full 9-element covariance per splat\n    mass: Float32Array;\n}\n\n// `forGpu` skips the cache fields the GPU kernel recomputes on the fly —\n// `invdiag` (1/v, computed in the kernel) and `sigma` (= R·diag(v)·Rᵀ, also\n// computed in the kernel). On a 17.9M-splat run that's ~860 MB less held for\n// the entire decimate.\nconst buildPerSplatCache = (\n    n: number,\n    cop: any, cs0: any, cs1: any, cs2: any,\n    cr0: any, cr1: any, cr2: any, cr3: any,\n    forGpu: boolean\n): SplatCache => {\n    const R = new Float32Array(n * 9);\n    const v = new Float32Array(n * 3);\n    const invdiag = forGpu ? new Float32Array(0) : new Float32Array(n * 3);\n    const logdet = new Float32Array(n);\n    const sigma = forGpu ? new Float32Array(0) : new Float32Array(n * 9);\n    const mass = new Float32Array(n);\n\n    for (let i = 0; i < n; i++) {\n        const i3 = 3 * i;\n        const i9 = 9 * i;\n\n        const linAlpha = sigmoid(cop[i]);\n        const sx = Math.max(Math.exp(cs0[i] as number), 1e-12);\n        const sy = Math.max(Math.exp(cs1[i] as number), 1e-12);\n        const sz = Math.max(Math.exp(cs2[i] as number), 1e-12);\n\n        const vx = sx * sx + EPS_COV;\n        const vy = sy * sy + EPS_COV;\n        const vz = sz * sz + EPS_COV;\n\n        v[i3] = vx; v[i3 + 1] = vy; v[i3 + 2] = vz;\n        if (!forGpu) {\n            invdiag[i3] = 1 / Math.max(vx, 1e-30);\n            invdiag[i3 + 1] = 1 / Math.max(vy, 1e-30);\n            invdiag[i3 + 2] = 1 / Math.max(vz, 1e-30);\n        }\n        logdet[i] = Math.log(Math.max(vx, 1e-30)) + Math.log(Math.max(vy, 1e-30)) + Math.log(Math.max(vz, 1e-30));\n\n        // Normalize quaternion before building rotation\n        let qw = cr0[i] as number, qx = cr1[i] as number, qy = cr2[i] as number, qz = cr3[i] as number;\n        const qn = Math.hypot(qw, qx, qy, qz);\n        const invq = 1 / Math.max(qn, 1e-12);\n        qw *= invq; qx *= invq; qy *= invq; qz *= invq;\n\n        quatToRotmat(qw, qx, qy, qz, R, i9);\n        if (!forGpu) {\n            sigmaFromRotVar(R, i9, vx, vy, vz, sigma, i9);\n        }\n\n        // Area·α weighting — matches the merge formula in `momentMatch`, so\n        // the KL cost in `computeEdgeCost` (which uses `cache.mass` to derive\n        // its pi/pj mixture weights) optimises the same merge model that's\n        // actually applied. Volume·α here would mis-score pairs whose\n        // volume/area ratio differs strongly between members.\n        mass[i] = linAlpha * ellipsoidArea(sx, sy, sz) + 1e-12;\n    }\n\n    return { R, v, invdiag, logdet, sigma, mass };\n};\n\n// ====================== COST FUNCTION ======================\n\n// Reusable scratch shared by `computeEdgeCost` and `momentMatch`. Allocated\n// once per `simplifyGaussians` invocation (not per call) so concurrent\n// invocations don't share state. Per-call allocation at ~9M merges/iter\n// would burn ~5 GB of throwaway garbage; per-decimate allocation is ~600 B.\ninterface MergeScratch {\n    sigm: Float64Array;  // computeEdgeCost: merged covariance\n    sigI: Float64Array;  // momentMatch: input i covariance\n    sigJ: Float64Array;  // momentMatch: input j covariance\n    rI: Float64Array;    // momentMatch: input i rotation\n    rJ: Float64Array;    // momentMatch: input j rotation\n    sig: Float64Array;   // momentMatch: merged covariance\n    rM: Float64Array;    // momentMatch: merged rotation\n    eigA: Float64Array;  // eigenSymmetric3x3: working matrix\n    eigV: Float64Array;  // eigenSymmetric3x3: eigenvectors\n}\n\nconst createMergeScratch = (): MergeScratch => ({\n    sigm: new Float64Array(9),\n    sigI: new Float64Array(9),\n    sigJ: new Float64Array(9),\n    rI: new Float64Array(9),\n    rJ: new Float64Array(9),\n    sig: new Float64Array(9),\n    rM: new Float64Array(9),\n    eigA: new Float64Array(9),\n    eigV: new Float64Array(9)\n});\n\nconst computeEdgeCost = (\n    i: number, j: number,\n    cx: any, cy: any, cz: any,\n    cache: SplatCache,\n    Z: Float64Array[],\n    appData: any[], appColCount: number,\n    scratch: MergeScratch\n): number => {\n    const i3 = 3 * i, j3 = 3 * j;\n    const i9 = 9 * i, j9 = 9 * j;\n\n    const mux = cx[i] as number, muy = cy[i] as number, muz = cz[i] as number;\n    const mvx = cx[j] as number, mvy = cy[j] as number, mvz = cz[j] as number;\n\n    const wi = cache.mass[i], wj = cache.mass[j];\n    const W = wi + wj;\n    const Wsafe = W > 0 ? W : 1;\n\n    let pi = wi / Wsafe;\n    pi = Math.max(1e-12, Math.min(1 - 1e-12, pi));\n    const pj = 1 - pi;\n    const logPi = Math.log(pi);\n    const logPj = Math.log(pj);\n\n    // Merged mean\n    const mmx = pi * mux + pj * mvx;\n    const mmy = pi * muy + pj * mvy;\n    const mmz = pi * muz + pj * mvz;\n\n    const dix = mux - mmx, diy = muy - mmy, diz = muz - mmz;\n    const djx = mvx - mmx, djy = mvy - mmy, djz = mvz - mmz;\n\n    // Merged covariance (full 9-element, reuse preallocated buffer)\n    const sigm = scratch.sigm;\n    for (let a = 0; a < 9; a++) {\n        sigm[a] = pi * cache.sigma[i9 + a] + pj * cache.sigma[j9 + a];\n    }\n    sigm[0] += pi * dix * dix + pj * djx * djx;\n    sigm[1] += pi * dix * diy + pj * djx * djy;\n    sigm[2] += pi * dix * diz + pj * djx * djz;\n    sigm[3] += pi * diy * dix + pj * djy * djx;\n    sigm[4] += pi * diy * diy + pj * djy * djy;\n    sigm[5] += pi * diy * diz + pj * djy * djz;\n    sigm[6] += pi * diz * dix + pj * djz * djx;\n    sigm[7] += pi * diz * diy + pj * djz * djy;\n    sigm[8] += pi * diz * diz + pj * djz * djz;\n\n    // Force symmetry + regularize\n    sigm[1] = sigm[3] = 0.5 * (sigm[1] + sigm[3]);\n    sigm[2] = sigm[6] = 0.5 * (sigm[2] + sigm[6]);\n    sigm[5] = sigm[7] = 0.5 * (sigm[5] + sigm[7]);\n    sigm[0] += EPS_COV;\n    sigm[4] += EPS_COV;\n    sigm[8] += EPS_COV;\n\n    const detm = Math.max(det3(sigm, 0), 1e-30);\n    const logdetm = Math.log(detm);\n\n    // E_p[-log q_m] computed analytically as entropy of merged Gaussian\n    const EpNegLogQ = 0.5 * (3 * LOG2PI + logdetm + 3);\n\n    // Sample from each component separately with same z-vectors\n    const stdix = Math.sqrt(Math.max(cache.v[i3], 0));\n    const stdiy = Math.sqrt(Math.max(cache.v[i3 + 1], 0));\n    const stdiz = Math.sqrt(Math.max(cache.v[i3 + 2], 0));\n    const stdjx = Math.sqrt(Math.max(cache.v[j3], 0));\n    const stdjy = Math.sqrt(Math.max(cache.v[j3 + 1], 0));\n    const stdjz = Math.sqrt(Math.max(cache.v[j3 + 2], 0));\n\n    let sumLogpOnI = 0;\n    let sumLogpOnJ = 0;\n\n    for (let s = 0; s < Z.length; s++) {\n        const z0 = Z[s][0], z1 = Z[s][1], z2 = Z[s][2];\n\n        // Sample x = mu + R · diag(std) · z (same form as the GPU kernel).\n        // Each row a of R sits at R[i9 + 3a .. i9 + 3a + 2].\n        const xix = mux + z0 * stdix * cache.R[i9 + 0] + z1 * stdiy * cache.R[i9 + 1] + z2 * stdiz * cache.R[i9 + 2];\n        const xiy = muy + z0 * stdix * cache.R[i9 + 3] + z1 * stdiy * cache.R[i9 + 4] + z2 * stdiz * cache.R[i9 + 5];\n        const xiz = muz + z0 * stdix * cache.R[i9 + 6] + z1 * stdiy * cache.R[i9 + 7] + z2 * stdiz * cache.R[i9 + 8];\n\n        const xjx = mvx + z0 * stdjx * cache.R[j9 + 0] + z1 * stdjy * cache.R[j9 + 1] + z2 * stdjz * cache.R[j9 + 2];\n        const xjy = mvy + z0 * stdjx * cache.R[j9 + 3] + z1 * stdjy * cache.R[j9 + 4] + z2 * stdjz * cache.R[j9 + 5];\n        const xjz = mvz + z0 * stdjx * cache.R[j9 + 6] + z1 * stdjy * cache.R[j9 + 7] + z2 * stdjz * cache.R[j9 + 8];\n\n        // Evaluate log p_ij at samples from component i\n        const logNiOnI = gaussLogpdfDiagrot(xix, xiy, xiz, mux, muy, muz,\n            cache.R, i9, cache.invdiag[i3], cache.invdiag[i3 + 1], cache.invdiag[i3 + 2], cache.logdet[i]);\n        const logNjOnI = gaussLogpdfDiagrot(xix, xiy, xiz, mvx, mvy, mvz,\n            cache.R, j9, cache.invdiag[j3], cache.invdiag[j3 + 1], cache.invdiag[j3 + 2], cache.logdet[j]);\n        sumLogpOnI += logAddExp(logPi + logNiOnI, logPj + logNjOnI);\n\n        // Evaluate log p_ij at samples from component j\n        const logNiOnJ = gaussLogpdfDiagrot(xjx, xjy, xjz, mux, muy, muz,\n            cache.R, i9, cache.invdiag[i3], cache.invdiag[i3 + 1], cache.invdiag[i3 + 2], cache.logdet[i]);\n        const logNjOnJ = gaussLogpdfDiagrot(xjx, xjy, xjz, mvx, mvy, mvz,\n            cache.R, j9, cache.invdiag[j3], cache.invdiag[j3 + 1], cache.invdiag[j3 + 2], cache.logdet[j]);\n        sumLogpOnJ += logAddExp(logPi + logNiOnJ, logPj + logNjOnJ);\n    }\n\n    const Ei = sumLogpOnI / Z.length;\n    const Ej = sumLogpOnJ / Z.length;\n    const EpLogp = pi * Ei + pj * Ej;\n    const geo = EpLogp + EpNegLogQ;\n\n    // Appearance cost\n    let cSh = 0;\n    for (let k = 0; k < appColCount; k++) {\n        const d = (appData[k][i] as number) - (appData[k][j] as number);\n        cSh += d * d;\n    }\n\n    return geo + cSh;\n};\n\n// ====================== MERGE ======================\n\n// Pairwise merge derived from sparkjsdev/spark's `gsplat.rs::new_merged`:\n//   - weights are α · ellipsoid-area (the screen-projected \"ink\" currency),\n//     which preserves color contribution from thin/anisotropic splats that\n//     volume-weighted NanoGS would otherwise drown out\n//   - merged covariance is the area·α-weighted sum of (δδᵀ + Σ_k), giving\n//     the right merged shape via the law of total variance\n//   - merged opacity is mass-conserving: α_m = (Σ α_k · area_k) / area_merged,\n//     clamped at 1 (the `spark-no-inflate` variant — no scale inflation and\n//     no out-of-range α, so the output PLY/SOG stays standard logit-encoded)\n//   - no Spark filter floor: we're pair-wise merging, not building an LOD\n//     grid, so the inter-mean filter regularization adds blur for no benefit\nconst momentMatch = (\n    i: number, j: number,\n    cx: any, cy: any, cz: any,\n    cop: any, cs0: any, cs1: any, cs2: any,\n    cr0: any, cr1: any, cr2: any, cr3: any,\n    out: { mu: Float64Array; sc: Float64Array; q: Float64Array; op: number; sh: Float64Array },\n    appData: any[], appColCount: number,\n    scratch: MergeScratch\n) => {\n    const sxi = Math.max(Math.exp(cs0[i] as number), 1e-12);\n    const syi = Math.max(Math.exp(cs1[i] as number), 1e-12);\n    const szi = Math.max(Math.exp(cs2[i] as number), 1e-12);\n    const sxj = Math.max(Math.exp(cs0[j] as number), 1e-12);\n    const syj = Math.max(Math.exp(cs1[j] as number), 1e-12);\n    const szj = Math.max(Math.exp(cs2[j] as number), 1e-12);\n\n    const alphaI = sigmoid(cop[i] as number);\n    const alphaJ = sigmoid(cop[j] as number);\n\n    // Area·α weighting (NanoGS used (2π)^1.5·sx·sy·sz·α; we use ellipsoid area).\n    const Ai = ellipsoidArea(sxi, syi, szi);\n    const Aj = ellipsoidArea(sxj, syj, szj);\n    const wi = alphaI * Ai + 1e-30;\n    const wj = alphaJ * Aj + 1e-30;\n    const W = wi + wj;\n    const pi = wi / W;\n    const pj = wj / W;\n\n    // Merged mean (weighted)\n    const mxi = cx[i] as number, myi = cy[i] as number, mzi = cz[i] as number;\n    const mxj = cx[j] as number, myj = cy[j] as number, mzj = cz[j] as number;\n    const mux = pi * mxi + pj * mxj;\n    const muy = pi * myi + pj * myj;\n    const muz = pi * mzi + pj * mzj;\n\n    // Per-call scratch buffers — owned by `simplifyGaussians` and passed in.\n    const SigI = scratch.sigI;\n    const SigJ = scratch.sigJ;\n    const Ri = scratch.rI;\n    const Rj = scratch.rJ;\n\n    let qwi = cr0[i] as number, qxi = cr1[i] as number, qyi = cr2[i] as number, qzi = cr3[i] as number;\n    const ni = 1 / Math.max(Math.hypot(qwi, qxi, qyi, qzi), 1e-12);\n    qwi *= ni; qxi *= ni; qyi *= ni; qzi *= ni;\n    let qwj = cr0[j] as number, qxj = cr1[j] as number, qyj = cr2[j] as number, qzj = cr3[j] as number;\n    const nj = 1 / Math.max(Math.hypot(qwj, qxj, qyj, qzj), 1e-12);\n    qwj *= nj; qxj *= nj; qyj *= nj; qzj *= nj;\n\n    quatToRotmat(qwi, qxi, qyi, qzi, Ri, 0);\n    quatToRotmat(qwj, qxj, qyj, qzj, Rj, 0);\n    sigmaFromRotVar(Ri, 0, sxi * sxi, syi * syi, szi * szi, SigI, 0);\n    sigmaFromRotVar(Rj, 0, sxj * sxj, syj * syj, szj * szj, SigJ, 0);\n\n    const dix = mxi - mux, diy = myi - muy, diz = mzi - muz;\n    const djx = mxj - mux, djy = myj - muy, djz = mzj - muz;\n\n    // Merged covariance (weighted sum of δδᵀ + Σ_k) — scratch.\n    const Sig = scratch.sig;\n    Sig[0] = pi * (dix * dix + SigI[0]) + pj * (djx * djx + SigJ[0]);\n    Sig[1] = pi * (dix * diy + SigI[1]) + pj * (djx * djy + SigJ[1]);\n    Sig[2] = pi * (dix * diz + SigI[2]) + pj * (djx * djz + SigJ[2]);\n    Sig[3] = Sig[1];\n    Sig[4] = pi * (diy * diy + SigI[4]) + pj * (djy * djy + SigJ[4]);\n    Sig[5] = pi * (diy * diz + SigI[5]) + pj * (djy * djz + SigJ[5]);\n    Sig[6] = Sig[2];\n    Sig[7] = Sig[5];\n    Sig[8] = pi * (diz * diz + SigI[8]) + pj * (djz * djz + SigJ[8]);\n    Sig[0] += EPS_COV;\n    Sig[4] += EPS_COV;\n    Sig[8] += EPS_COV;\n\n    // Eigendecompose → scales (= √λ) and rotation. `eigA` ends with the\n    // eigenvalues on its diagonal (positions 0/4/8); `eigV` holds the\n    // eigenvectors as columns.\n    const eigA = scratch.eigA;\n    const eigV = scratch.eigV;\n    eigenSymmetric3x3(Sig, eigA, eigV);\n    const vecs = eigV;\n\n    // Sort eigenvalue indices descending. Hand-unrolled to avoid the\n    // `[0,1,2].sort(...)` + `.map(...)` allocations.\n    const v0 = eigA[0], v1 = eigA[4], v2 = eigA[8];\n    let o0: number, o1: number, o2: number;\n    if (v0 >= v1) {\n        if (v1 >= v2)      {\n            o0 = 0; o1 = 1; o2 = 2;\n        } else if (v0 >= v2) {\n            o0 = 0; o1 = 2; o2 = 1;\n        } else               {\n            o0 = 2; o1 = 0; o2 = 1;\n        }\n    } else {\n        if (v0 >= v2)      {\n            o0 = 1; o1 = 0; o2 = 2;\n        } else if (v1 >= v2) {\n            o0 = 1; o1 = 2; o2 = 0;\n        } else               {\n            o0 = 2; o1 = 1; o2 = 0;\n        }\n    }\n    const ev0 = Math.max(eigA[3 * o0 + o0], 1e-18);\n    const ev1 = Math.max(eigA[3 * o1 + o1], 1e-18);\n    const ev2 = Math.max(eigA[3 * o2 + o2], 1e-18);\n\n    const s0 = Math.sqrt(ev0);\n    const s1 = Math.sqrt(ev1);\n    const s2 = Math.sqrt(ev2);\n\n    // Mass-conserving opacity, capped at 1 (no scale inflation). No lower\n    // clamp here — `logit()` at the storage step already pins p ≥ 1e-7.\n    const alphaM = Math.min(1, W / Math.max(ellipsoidArea(s0, s1, s2), 1e-30));\n\n    // Build rotation matrix from sorted eigenvectors (right-handed) — scratch.\n    const Rm = scratch.rM;\n    Rm[0] = vecs[o0]; Rm[1] = vecs[o1]; Rm[2] = vecs[o2];\n    Rm[3] = vecs[3 + o0]; Rm[4] = vecs[3 + o1]; Rm[5] = vecs[3 + o2];\n    Rm[6] = vecs[6 + o0]; Rm[7] = vecs[6 + o1]; Rm[8] = vecs[6 + o2];\n    if (det3(Rm, 0) < 0) {\n        Rm[2] *= -1; Rm[5] *= -1; Rm[8] *= -1;\n    }\n    rotmatToQuat(Rm, 0, out.q, 0);\n\n    out.mu[0] = mux; out.mu[1] = muy; out.mu[2] = muz;\n    out.sc[0] = Math.log(s0);\n    out.sc[1] = Math.log(s1);\n    out.sc[2] = Math.log(s2);\n    out.op = alphaM;\n\n    // Color: weight-normalized (area·α weighted) average\n    for (let k = 0; k < appColCount; k++) {\n        out.sh[k] = pi * (appData[k][i] as number) + pj * (appData[k][j] as number);\n    }\n};\n\n// ====================== VISIBILITY PRUNING ======================\n\nconst sortByVisibility = (dataTable: DataTable, indices: Uint32Array): void => {\n    const opacityCol = dataTable.getColumnByName('opacity');\n    const scale0Col = dataTable.getColumnByName('scale_0');\n    const scale1Col = dataTable.getColumnByName('scale_1');\n    const scale2Col = dataTable.getColumnByName('scale_2');\n\n    if (!opacityCol || !scale0Col || !scale1Col || !scale2Col) {\n        logger.debug('missing required columns for visibility sorting (opacity, scale_0, scale_1, scale_2)');\n        return;\n    }\n    if (indices.length === 0) return;\n\n    const opacity = opacityCol.data;\n    const scale0 = scale0Col.data;\n    const scale1 = scale1Col.data;\n    const scale2 = scale2Col.data;\n\n    const scores = new Float32Array(indices.length);\n    for (let i = 0; i < indices.length; i++) {\n        const ri = indices[i];\n        scores[i] = (1 / (1 + Math.exp(-opacity[ri]))) * Math.exp(scale0[ri] + scale1[ri] + scale2[ri]);\n    }\n\n    const order = new Uint32Array(indices.length);\n    for (let i = 0; i < order.length; i++) order[i] = i;\n    order.sort((a, b) => scores[b] - scores[a]);\n\n    const tmp = indices.slice();\n    for (let i = 0; i < indices.length; i++) indices[i] = tmp[order[i]];\n};\n\n// ====================== MAIN: simplifyGaussians ======================\n\n/**\n * Simplifies a Gaussian splat DataTable to a target number of splats by\n * progressive pair-wise merging of nearest-neighbor gaussians.\n *\n * The merge math is derived from sparkjsdev/spark `gsplat.rs::new_merged`\n * (area·α weighted, mass-conserving opacity, no filter floor, opacity\n * clamped at 1). It preserves color fidelity through multiple iterations\n * far better than the NanoGS Porter-Duff opacity + volume-weighted formula\n * does — color drift / over-saturation is essentially gone even at\n * aggressive reductions.\n *\n * @param dataTable - The input splat DataTable.\n * @param targetCount - The desired number of output splats.\n * @param createDevice - Optional factory yielding a `GraphicsDevice`. When supplied, KNN and edge-cost run on the GPU; otherwise the CPU KD-tree path is used.\n * @returns A new DataTable with approximately `targetCount` splats.\n */\nconst simplifyGaussians = async (\n    dataTable: DataTable,\n    targetCount: number,\n    createDevice?: DeviceCreator\n): Promise<DataTable> => {\n    const N = dataTable.numRows;\n    if (N <= targetCount || targetCount <= 0) {\n        return targetCount <= 0 ? dataTable.clone({ rows: [] }) : dataTable;\n    }\n\n    // Mirrors the factory contract used by `filterFloaters` — the caller\n    // hands us a `DeviceCreator` so we can create the device lazily (and\n    // skip creation entirely on the early-return path above). We don't\n    // destroy the device; per the `DeviceCreator` contract in types.ts,\n    // the caller owns its lifecycle and is responsible for caching/reuse.\n    const device = createDevice ? await createDevice() : undefined;\n\n    const requiredCols = ['x', 'y', 'z', 'opacity', 'scale_0', 'scale_1', 'scale_2',\n        'rot_0', 'rot_1', 'rot_2', 'rot_3'];\n    for (const name of requiredCols) {\n        if (!dataTable.hasColumn(name)) {\n            logger.debug(`missing required column '${name}', falling back to visibility pruning`);\n            const indices = new Uint32Array(N);\n            for (let i = 0; i < N; i++) indices[i] = i;\n            sortByVisibility(dataTable, indices);\n            return dataTable.clone({ rows: indices.subarray(0, targetCount) });\n        }\n    }\n\n    // Identify appearance columns\n    const allAppearanceCols: string[] = [];\n    for (const name of ['f_dc_0', 'f_dc_1', 'f_dc_2']) {\n        if (dataTable.hasColumn(name)) allAppearanceCols.push(name);\n    }\n    for (let i = 0; i < 45; i++) {\n        const name = `f_rest_${i}`;\n        if (dataTable.hasColumn(name)) allAppearanceCols.push(name);\n    }\n\n    let current: DataTable = dataTable;\n\n    // Pre-generate MC samples\n    const Z = makeGaussianSamples(MC_SAMPLES, 0);\n\n    // Reusable scratch buffers for the per-iteration edge-cost sort.\n    const sortScratch = new RadixSortScratch();\n\n    // Per-call merge scratch — see `MergeScratch` above. Lives until the end\n    // of this `simplifyGaussians` invocation; not shared with concurrent calls.\n    const mergeScratch = createMergeScratch();\n\n    // Hoist GPU resources above the merging loop. Empirically this lowers peak\n    // RSS by ~1.4 GB on a 17.9M-splat run vs. per-iteration construction —\n    // the per-iteration version has a transient destroy/create overlap where\n    // GpuKnn buffers haven't been reclaimed by the WebGPU backend before\n    // GpuEdgeCost allocates fresh ones. Hoisting reuses the same backing\n    // storage across iterations. `initialMaxE` is the true upper bound on edge\n    // count, n·k (not n·k/2 — that's only the expected count; per-iteration\n    // variance lets the actual edgeCount exceed n·k/2 by a few percent). It's a\n    // validation bound, not a buffer size: GpuEdgeCost uploads edges per\n    // dispatch batch, so its edge buffers are batch-sized regardless.\n    const initialN = current.numRows;\n    const kEffMax = Math.min(Math.max(1, KNN_K), Math.max(1, initialN - 1));\n    const initialMaxE = initialN * kEffMax;\n    const numAppColsMax = allAppearanceCols.length;\n    const z = new Float32Array(3);\n    z[0] = Z[0][0]; z[1] = Z[0][1]; z[2] = Z[0][2];\n\n    // Iterative merging.\n    // Each iteration roughly halves the row count (greedy disjoint pair\n    // selection picks up to n/2 merges), so log2(n / target) is a good\n    // upper bound for the [N/T] series numbering. Iterations beyond the\n    // estimate render unnumbered, which is fine.\n    const estIterations = Math.max(1, Math.ceil(Math.log2(current.numRows / targetCount)));\n    let iterationIndex = 0;\n\n    // GPU resources live inside the try block so that if the second\n    // constructor throws (e.g. the appearance-buffer preflight in\n    // GpuEdgeCost), the partially-built first constructor's resources get\n    // cleaned up by the finally.\n    let gpuKnn: GpuKnn | undefined;\n    let gpuCost: GpuEdgeCost | undefined;\n\n    try {\n        if (device) {\n            gpuKnn = new GpuKnn(device, initialN, kEffMax);\n            gpuCost = new GpuEdgeCost(device, initialN, initialMaxE, numAppColsMax);\n        }\n\n        while (current.numRows > targetCount) {\n            const n = current.numRows;\n            // kEff fixed at kEffMax so the hoisted GPU resources (which bake k\n            // into the shader and into buffer sizing) work across every iteration.\n            // When n - 1 < kEffMax, both KNN paths fill the surplus slots with the\n            // sentinel 0xFFFFFFFF and the edge-extraction loop ignores them.\n            const kEff = kEffMax;\n\n            iterationIndex++;\n            const g = iterationIndex <= estIterations ?\n                logger.group('Decimate iteration', {\n                    index: iterationIndex,\n                    total: estIterations\n                }) :\n                logger.group('Decimate iteration');\n\n            const cx = current.getColumnByName('x')!.data;\n            const cy = current.getColumnByName('y')!.data;\n            const cz = current.getColumnByName('z')!.data;\n            const cop = current.getColumnByName('opacity')!.data;\n            const cs0 = current.getColumnByName('scale_0')!.data;\n            const cs1 = current.getColumnByName('scale_1')!.data;\n            const cs2 = current.getColumnByName('scale_2')!.data;\n            const cr0 = current.getColumnByName('rot_0')!.data;\n            const cr1 = current.getColumnByName('rot_1')!.data;\n            const cr2 = current.getColumnByName('rot_2')!.data;\n            const cr3 = current.getColumnByName('rot_3')!.data;\n\n            const cacheSub = logger.group('Building per-splat cache');\n            const cache = buildPerSplatCache(n, cop, cs0, cs1, cs2, cr0, cr1, cr2, cr3, !!device);\n            cacheSub.end();\n\n            // Flat per-query KNN output. allKnn[i*kEff + j] is one of the kEff\n            // nearest neighbours of i, excluding i itself. CPU path emits sorted\n            // ascending by distance; GPU path emits an unsorted top-K. Neither\n            // ordering matters downstream — the edge-extraction loop only filters\n            // j > i. Sentinel 0xFFFFFFFF marks unfilled slots when fewer than kEff\n            // non-self neighbours exist. `let` so we can drop the reference after\n            // edge extraction — letting it go out of scope at end of iteration\n            // doesn't help because V8 grows the heap before collecting.\n            let allKnn = new Uint32Array(n * kEff);\n\n            const pxArr = cx instanceof Float32Array ? cx : new Float32Array(cx as any);\n            const pyArr = cy instanceof Float32Array ? cy : new Float32Array(cy as any);\n            const pzArr = cz instanceof Float32Array ? cz : new Float32Array(cz as any);\n\n            if (device) {\n                const knnSub = logger.group('Finding nearest neighbors (GPU)');\n                await gpuKnn!.execute(pxArr, pyArr, pzArr, allKnn);\n                knnSub.end();\n            } else {\n                const kdSub = logger.group('Building KD-tree');\n                const posTable = new DataTable([\n                    new Column('x', pxArr),\n                    new Column('y', pyArr),\n                    new Column('z', pzArr)\n                ]);\n                const kdTree = new KdTree(posTable);\n                kdSub.end();\n\n                const queryPoint = new Float32Array(3);\n                const knnInterval = Math.max(1, Math.ceil(n / PROGRESS_TICKS));\n                const knnTicks = Math.ceil(n / knnInterval);\n                const knnBar = logger.bar('Finding nearest neighbors', knnTicks);\n                for (let i = 0; i < n; i++) {\n                    queryPoint[0] = cx[i] as number;\n                    queryPoint[1] = cy[i] as number;\n                    queryPoint[2] = cz[i] as number;\n                    // Request kEff+1 because the KD-tree returns the query itself\n                    // (distance 0) as the first match.\n                    const knn = kdTree.findKNearest(queryPoint, kEff + 1);\n                    let outPos = 0;\n                    for (let ki = 0; ki < knn.indices.length && outPos < kEff; ki++) {\n                        const j = knn.indices[ki];\n                        if (j === i) continue;\n                        allKnn[i * kEff + outPos] = j;\n                        outPos++;\n                    }\n                    while (outPos < kEff) {\n                        allKnn[i * kEff + outPos] = 0xFFFFFFFF;\n                        outPos++;\n                    }\n                    if ((i + 1) % knnInterval === 0) knnBar.tick();\n                }\n                if (n % knnInterval !== 0) knnBar.tick();\n                knnBar.end();\n            }\n\n            // Extract directed edges (i < j) from the K-NN graph.\n            let edgeCapacity = Math.ceil(n * kEff / 2);\n            let edgeU = new Uint32Array(edgeCapacity);\n            let edgeV = new Uint32Array(edgeCapacity);\n            let edgeCount = 0;\n            for (let i = 0; i < n; i++) {\n                const base = i * kEff;\n                for (let ki = 0; ki < kEff; ki++) {\n                    const j = allKnn[base + ki];\n                    if (j === 0xFFFFFFFF || j <= i) continue;\n                    if (edgeCount === edgeCapacity) {\n                        edgeCapacity *= 2;\n                        const newU = new Uint32Array(edgeCapacity);\n                        const newV = new Uint32Array(edgeCapacity);\n                        newU.set(edgeU);\n                        newV.set(edgeV);\n                        edgeU = newU;\n                        edgeV = newV;\n                    }\n                    edgeU[edgeCount] = i;\n                    edgeV[edgeCount] = j;\n                    edgeCount++;\n                }\n            }\n\n            // allKnn was only read by the edge-extraction loop above. Drop the\n            // reference so V8 can reclaim the 1.14 GB (at N=17.9M, k=16) — see\n            // the comment at the declaration.\n            allKnn = new Uint32Array(0);\n\n            // The loop only runs while n > targetCount, and a non-degenerate\n            // k-NN graph over n >= 2 splats always yields edges (splat 0's\n            // neighbours have higher indices). Zero edges here therefore means\n            // the neighbour step produced nothing usable — on the GPU path a\n            // swallowed out-of-memory leaving the k-NN buffer zeroed, on the CPU\n            // path a degenerate input — never a legitimate \"can't decimate\n            // further\". Fail rather than return an incompletely-decimated scene,\n            // regardless of how many earlier iterations succeeded.\n            if (edgeCount === 0) {\n                g.end();\n                const cause = device ?\n                    'the GPU step likely failed (e.g. out-of-memory)' :\n                    'the input is likely degenerate (e.g. non-finite positions)';\n                throw new Error(\n                    `decimation produced no edges from the k-NN graph at ${n} splats (target ${targetCount}) — ` +\n                    `${cause}. Refusing to return an incompletely-decimated scene.`\n                );\n            }\n\n            const appData: any[] = [];\n            for (let ai = 0; ai < allAppearanceCols.length; ai++) {\n                const col = current.getColumnByName(allAppearanceCols[ai]);\n                if (col) appData.push(col.data);\n            }\n\n            const mergesNeeded = n - targetCount;\n            let costs = new Float32Array(edgeCount);\n\n            if (device) {\n                // GPU path: pack the per-splat cache into the layout the kernel\n                // expects — position + scalars interleaved 8-wide in one buffer,\n                // appearance split into 16-column chunks (each chunk stays under\n                // the ~2 GB per-binding limit). `R` is already Float32, so the\n                // rotation passes through directly.\n                const costSub = logger.group('Computing edge costs (GPU)');\n\n                const C = appData.length;\n                const numChunks = Math.ceil(C / APP_CHUNK);\n\n                const posScalars = new Float32Array(n * 8);\n                for (let s = 0; s < n; s++) {\n                    const o = s * 8;\n                    posScalars[o + 0] = cx[s] as number;\n                    posScalars[o + 1] = cy[s] as number;\n                    posScalars[o + 2] = cz[s] as number;\n                    posScalars[o + 3] = cache.mass[s];\n                    posScalars[o + 4] = cache.logdet[s];\n                    posScalars[o + 5] = cache.v[s * 3 + 0];\n                    posScalars[o + 6] = cache.v[s * 3 + 1];\n                    posScalars[o + 7] = cache.v[s * 3 + 2];\n                }\n\n                // Pack appearance into chunks of ≤APP_CHUNK columns. Each\n                // chunk's stride is its live width (only the final chunk may be\n                // partial), so no padding is stored or uploaded. APP_CHUNK is\n                // the same constant the kernel bakes its strides from, so the\n                // host packing and the kernel layout stay in lockstep.\n                const appChunks: Float32Array[] = [];\n                for (let ch = 0; ch < numChunks; ch++) {\n                    const kStart = ch * APP_CHUNK;\n                    const width = Math.min(APP_CHUNK, C - kStart);\n                    const chunk = new Float32Array(n * width);\n                    for (let s = 0; s < n; s++) {\n                        const dst = s * width;\n                        for (let kk = 0; kk < width; kk++) {\n                            chunk[dst + kk] = appData[kStart + kk][s] as number;\n                        }\n                    }\n                    appChunks.push(chunk);\n                }\n\n                const cacheGpu: EdgeCostCache = {\n                    posScalars,\n                    rotR: cache.R,\n                    appChunks,\n                    numAppCols: C,\n                    numSplats: n\n                };\n\n                // Trim edge buffers to the valid prefix (edgeU/edgeV were grown).\n                const edgeITrim = edgeU.subarray(0, edgeCount);\n                const edgeJTrim = edgeV.subarray(0, edgeCount);\n\n                await gpuCost!.execute(cacheGpu, edgeITrim, edgeJTrim, z, costs);\n                costSub.end();\n            } else {\n                const costInterval = Math.max(1, Math.ceil(edgeCount / PROGRESS_TICKS));\n                const costTicks = Math.ceil(edgeCount / costInterval);\n                const costBar = logger.bar('Computing edge costs', costTicks);\n                for (let e = 0; e < edgeCount; e++) {\n                    costs[e] = computeEdgeCost(edgeU[e], edgeV[e], cx, cy, cz,\n                        cache, Z, appData, appData.length, mergeScratch);\n                    if ((e + 1) % costInterval === 0) costBar.tick();\n                }\n                if (edgeCount % costInterval !== 0) costBar.tick();\n                costBar.end();\n            }\n\n            // Release the per-splat cache fields that are no longer needed —\n            // the merge loop only reads `cache.mass` for dominant-side\n            // selection. At N=17.9M that's ~1.7 GB of buffers (R, v, invdiag,\n            // logdet, sigma) we can drop before the sort phase pushes peak.\n            cache.R = new Float32Array(0);\n            cache.v = new Float32Array(0);\n            cache.invdiag = new Float32Array(0);\n            cache.logdet = new Float32Array(0);\n            cache.sigma = new Float32Array(0);\n\n            // Sort and greedy disjoint pair selection. We pass `costs` directly as\n            // the parallel-key buffer (an edgeCount-sized Float32 scratch would\n            // otherwise add ~580 MB to peak at 17.9M splats). Non-finite costs are\n            // replaced by +Inf in place so they sort to the end; the greedy loop\n            // caps at `validCount` to ignore them. `costs` is iteration-local and\n            // not read again after this point, so mutating it is safe.\n            const pairSelectSub = logger.group('Selecting pairs');\n            let sorted = new Uint32Array(edgeCount);\n            const costBits = new Uint32Array(costs.buffer, costs.byteOffset, costs.length);\n            let validCount = edgeCount;\n            for (let i = 0; i < edgeCount; i++) {\n                sorted[i] = i;\n                if (isFloatBitsNonFinite(costBits[i])) {\n                    costs[i] = Infinity;\n                    validCount--;\n                }\n            }\n            radixSortIndicesByFloat(sorted, costs, edgeCount, sortScratch);\n\n            const used = new Uint8Array(n);\n            const pairs: [number, number][] = [];\n\n            for (let t = 0; t < validCount; t++) {\n                const e = sorted[t];\n                const u = edgeU[e], v = edgeV[e];\n                if (used[u] || used[v]) continue;\n                used[u] = 1; used[v] = 1;\n                pairs.push([u, v]);\n                if (pairs.length >= mergesNeeded) break;\n            }\n            pairSelectSub.end();\n\n            // Release the sort/edge scratch — none of it is read during the\n            // merge below. At N=17.9M this is ~2.85 GB (edgeU/V 1.14 GB,\n            // sorted 0.57 GB, costs 0.57 GB) that V8 would otherwise keep\n            // pinned through the merge.\n            edgeU = new Uint32Array(0);\n            edgeV = new Uint32Array(0);\n            costs = new Float32Array(0);\n            sorted = new Uint32Array(0);\n\n            // pairs.length === 0 only happens when every edge cost is non-finite\n            // (any finite cost yields at least one pair), i.e. a total\n            // cost-computation failure — GPU corruption on the GPU path, or\n            // non-finite inputs on either path. As above, the loop guarantees\n            // n > targetCount, so this is always a failure to reach the target,\n            // not a legitimate stop. Fatal regardless of prior progress.\n            if (pairs.length === 0) {\n                g.end();\n                const cause = device ?\n                    'the GPU step likely failed (e.g. out-of-memory) or produced non-finite costs' :\n                    'cost computation produced only non-finite values (e.g. non-finite inputs)';\n                throw new Error(\n                    `decimation found no valid merge pairs among ${edgeCount} edges at ${n} splats (target ${targetCount}) — ` +\n                    `${cause}. Refusing to return an incompletely-decimated scene.`\n                );\n            }\n\n            // Allocate output table\n            const allocSub = logger.group('Allocating output table');\n            const usedSet = new Uint8Array(n);\n            for (let p = 0; p < pairs.length; p++) {\n                usedSet[pairs[p][0]] = 1;\n                usedSet[pairs[p][1]] = 1;\n            }\n\n            const keepIndices: number[] = [];\n            for (let i = 0; i < n; i++) {\n                if (!usedSet[i]) keepIndices.push(i);\n            }\n\n            const outCount = keepIndices.length + pairs.length;\n            const cols = current.columns;\n            const newColumns: Column[] = [];\n            for (let ci = 0; ci < cols.length; ci++) {\n                const c = cols[ci];\n                newColumns.push(new Column(c.name, new (c.data.constructor as any)(outCount)));\n            }\n            const newTable = new DataTable(newColumns, dataTable.transform);\n            allocSub.end();\n\n            // Copy unmerged splats\n            const copySub = logger.group('Copying kept splats');\n            let dst = 0;\n            for (let t = 0; t < keepIndices.length; t++, dst++) {\n                const src = keepIndices[t];\n                for (let c = 0; c < cols.length; c++) {\n                    newTable.columns[c].data[dst] = cols[c].data[src] as number;\n                }\n            }\n            copySub.end();\n\n            // Merge pairs\n            const mergeOut = {\n                mu: new Float64Array(3),\n                sc: new Float64Array(3),\n                q: new Float64Array(4),\n                op: 0,\n                sh: new Float64Array(allAppearanceCols.length)\n            };\n\n            const dstXCol = newTable.getColumnByName('x')!;\n            const dstYCol = newTable.getColumnByName('y')!;\n            const dstZCol = newTable.getColumnByName('z')!;\n            const dstS0Col = newTable.getColumnByName('scale_0')!;\n            const dstS1Col = newTable.getColumnByName('scale_1')!;\n            const dstS2Col = newTable.getColumnByName('scale_2')!;\n            const dstR0Col = newTable.getColumnByName('rot_0')!;\n            const dstR1Col = newTable.getColumnByName('rot_1')!;\n            const dstR2Col = newTable.getColumnByName('rot_2')!;\n            const dstR3Col = newTable.getColumnByName('rot_3')!;\n            const dstOpCol = newTable.getColumnByName('opacity')!;\n            const dstAppCols = allAppearanceCols.map(name => newTable.getColumnByName(name));\n\n            const handledCols = new Set([\n                'x', 'y', 'z', 'opacity', 'scale_0', 'scale_1', 'scale_2',\n                'rot_0', 'rot_1', 'rot_2', 'rot_3', ...allAppearanceCols\n            ]);\n            const unhandledColPairs = cols\n            .filter(col => !handledCols.has(col.name))\n            .map(col => ({ src: col, dst: newTable.getColumnByName(col.name)! }))\n            .filter(pair => pair.dst);\n\n            const mergeInterval = Math.max(1, Math.ceil(pairs.length / PROGRESS_TICKS));\n            const mergeTicks = Math.ceil(pairs.length / mergeInterval);\n            const mergeBar = logger.bar('Merging splats', mergeTicks);\n            for (let p = 0; p < pairs.length; p++, dst++) {\n                const pi = pairs[p][0], pj = pairs[p][1];\n\n                momentMatch(pi, pj, cx, cy, cz, cop, cs0, cs1, cs2, cr0, cr1, cr2, cr3,\n                    mergeOut, appData, appData.length, mergeScratch);\n\n                dstXCol.data[dst] = mergeOut.mu[0];\n                dstYCol.data[dst] = mergeOut.mu[1];\n                dstZCol.data[dst] = mergeOut.mu[2];\n                dstS0Col.data[dst] = mergeOut.sc[0];\n                dstS1Col.data[dst] = mergeOut.sc[1];\n                dstS2Col.data[dst] = mergeOut.sc[2];\n                dstR0Col.data[dst] = mergeOut.q[0];\n                dstR1Col.data[dst] = mergeOut.q[1];\n                dstR2Col.data[dst] = mergeOut.q[2];\n                dstR3Col.data[dst] = mergeOut.q[3];\n                dstOpCol.data[dst] = logit(Math.max(0, Math.min(1, mergeOut.op)));\n\n                for (let k = 0; k < dstAppCols.length; k++) {\n                    if (dstAppCols[k]) dstAppCols[k]!.data[dst] = mergeOut.sh[k];\n                }\n\n                const dominant = cache.mass[pi] >= cache.mass[pj] ? pi : pj;\n                for (let u = 0; u < unhandledColPairs.length; u++) {\n                    unhandledColPairs[u].dst.data[dst] = unhandledColPairs[u].src.data[dominant] as number;\n                }\n\n                if ((p + 1) % mergeInterval === 0) mergeBar.tick();\n            }\n            if (pairs.length % mergeInterval !== 0) mergeBar.tick();\n            mergeBar.end();\n\n            current = newTable;\n            g.end();\n        }\n\n        return current;\n    } finally {\n        gpuKnn?.destroy();\n        gpuCost?.destroy();\n    }\n};\n\nexport { sortByVisibility, simplifyGaussians };\n","/**\n * Centralised render-time tunables. Constants that today live as magic\n * numbers in the project/rasterize WGSL shaders, in `gaussian-aabb.ts`'s\n * extent computation, and in the orchestrator's far-plane logic.\n *\n * Two goals:\n *\n *   1. Single source of truth — one place to discover every knob, so the\n *      \"reference 3DGS standard\" values are documented together rather\n *      than scattered across files.\n *\n *   2. A natural switching point for a future \"reference\" vs \"fast\"\n *      profile — for now everything is the reference-3DGS value.\n *\n * Most of these match the values used by the original INRIA 3DGS CUDA\n * rasterizer. Touching any of them is an \"exceed reference\" decision and\n * needs to be reflected in regenerated golden fixtures.\n */\n\n/**\n * Half-pixel² covariance dilation added to the 2D projected covariance's\n * diagonal before inversion. Reduces aliasing at the cost of inflating\n * every splat's screen footprint by ≤1 pixel. Matches the INRIA reference.\n */\nexport const AA_DILATION_COV = 0.3;\n\n/**\n * Maximum tan(half-FOV) factor that the EWA Jacobian's `(cx/cz, cy/cz)`\n * is clamped to before forming the projection. Splats outside this cone\n * use a distorted Jacobian. Matches the INRIA reference (`1.3 × half-FOV`).\n */\nexport const JACOBIAN_LIMIT_FACTOR = 1.3;\n\n/**\n * Per-splat alpha cap. Prevents perfectly opaque splats so the\n * transmittance chain can't collapse to exactly zero in one step. INRIA\n * reference.\n */\nexport const OPACITY_CAP = 0.99;\n\n/**\n * Per-splat alpha cutoff. Contributions below this are dropped — saves\n * work for splats whose evaluated 2D Gaussian falls below quantization\n * threshold. INRIA reference.\n */\nexport const MIN_ALPHA = 1.0 / 255.0;\n\n/**\n * Per-pixel transmittance early-out. Once `T` falls below this the pixel\n * stops accumulating; remaining ~0.01% of mass is discarded. INRIA\n * reference.\n */\nexport const MIN_TRANSMITTANCE = 1e-4;\n\n/**\n * Floor on `½·trace² − det` before sqrt when deriving the projected\n * covariance's larger eigenvalue. Bounds the radius from below by\n * `ceil(3·sqrt(½·trace + sqrt(floor)))` ≈ 1 pixel. INRIA reference.\n */\nexport const DISCRIMINANT_FLOOR = 0.1;\n\n/**\n * Number of standard deviations at which the rendered Gaussian's tail\n * is truncated. Used for both:\n *   - the AABB half-extents in `computeGaussianExtents` (BVH input)\n *   - the screen-space radius in the project shader (rasterize bbox)\n *\n * Keeping them in sync ensures a splat included by the BVH cull is\n * actually rasterized; lowering this here without also lowering it in\n * the project shader's `radius = ceil(SIGMA_CUTOFF · sqrt(λmax))` would\n * cause silently-clipped tails.\n */\nexport const SIGMA_CUTOFF = 3.0;\n\n/**\n * Value of the unit gaussian at the truncation radius. Subtracted from\n * `exp(power)` in the rasterizer so each splat's alpha reaches exactly\n * 0 at `SIGMA_CUTOFF · σ` instead of clipping at ≈ 1.1% (which would\n * leave a faint ring at the splat boundary). Matches the PlayCanvas\n * engine's edge compensation.\n */\nexport const GAUSSIAN_FLOOR = Math.exp(-0.5 * SIGMA_CUTOFF * SIGMA_CUTOFF);\n\n/**\n * Floor on the far-plane distance, expressed as a multiple of the near\n * plane. If every scene-AABB corner sits behind the camera the\n * computed far would otherwise be ≤ near; this prevents a degenerate\n * frustum. Magic number; not from any reference.\n */\nexport const FAR_PLANE_NEAR_FACTOR = 100;\n\n/**\n * Tile size in pixels for the rasterize workgroup. Must match the\n * WGSL shader's hard-coded `workgroup_size(16, 16, 1)`. Changing here\n * also requires updating the shader templates.\n */\nexport const TILE_SIZE = 16;\n\n/**\n * Equirect projection pole-exclusion factor. The equirect Jacobian's\n * latitude derivative diverges as the splat approaches the zenith /\n * nadir (rxz → 0). We clamp `rxz` from below at `POLE_EPS · r` so the\n * Jacobian (and hence the projected covariance, screen-space radius,\n * and per-tile coverage) stays bounded for splats arbitrarily close to\n * a pole. Splats *exactly* on the pole get a finite (but narrow) screen\n * footprint at a longitude determined by tiny numerical noise — in\n * practice this band is rarely visible because polar splats tend to be\n * far from the camera. Lowering the floor sharpens detail near the\n * poles at the cost of more aggressive footprint stretching for nearby\n * splats; 0.005 (~0.29°) is a reasonable balance.\n */\nexport const POLE_EPS = 0.005;\n\n\n/**\n * Total GPU memory budget for ALL pair-sized buffers combined: the\n * tile-key and splat-value buffers the rasterizer owns (2× pairsCap × 4 B)\n * plus the four internal ping-pong buffers `ComputeRadixSort` allocates\n * (`_keys0`, `_keys1`, `_values0`, `_values1` — another 4× pairsCap × 4 B).\n * That's 6 × pairsCap × 4 B = `PAIR_BUFFER_TOTAL_BYTES_PER_ELEMENT × pairsCap`.\n *\n * `chunkCap` is sized to keep this total under budget. The radix-sort\n * scratch is the dominant share; budgeting only the local buffers (as\n * earlier revisions did) under-counts actual GPU memory by ~3×.\n */\nexport const PAIR_BUFFER_BUDGET_BYTES = 768 * 1024 * 1024;\n\n/**\n * Total bytes per pair *element* across all six pair-sized buffers\n * (4 B × 6 buffers). Used by the orchestrator's chunkCap calculation\n * so the math reflects actual GPU memory consumed by the sort\n * pipeline.\n */\nexport const PAIR_BUFFER_TOTAL_BYTES_PER_ELEMENT = 4 * 6;\n\n/**\n * Screen-radius fade thresholds, expressed as fractions of image\n * height. Defends against outlier splats with large world-space scale\n * or near-camera placement that would otherwise project to a screen-\n * spanning footprint.\n *\n * A hard clamp produces a visible \"pop\" as the camera approaches a\n * splat that grows past the cap (the splat suddenly stops getting any\n * bigger). Instead we *linearly fade out* the splat's alpha between\n * `RADIUS_FADE_START_FRAC × imageHeight` (alpha × 1) and\n * `RADIUS_FADE_END_FRAC × imageHeight` (alpha × 0). Beyond the END\n * threshold the splat is discarded entirely.\n *\n * Image-height-relative so the SAME world-space splats fade at every\n * render resolution — a splat that doesn't fade at 1080p won't get\n * dropped at 8K just because its pixel radius is 4× bigger. The values\n * are calibrated so that the original 1080p thresholds (1024 px /\n * 2048 px) reproduce, while 8K renders fade only the splats that\n * would also fade at 1080p.\n *\n * Inspired by PlayCanvas engine's `min(1024.0, viewport)` axis cap\n * (see `gsplatCorner.js`), but with the cap softened into a fade.\n */\nexport const RADIUS_FADE_START_FRAC = 1024 / 1080;\nexport const RADIUS_FADE_END_FRAC = 2048 / 1080;\n","import { BoundingBox, Mat4, Quat, Vec3 } from 'playcanvas';\n\nimport { Column, DataTable } from './data-table';\nimport { SIGMA_CUTOFF } from '../render/config';\nimport { fmtCount, logger } from '../utils';\n\n/**\n * Bounds specification with min/max Vec3.\n */\ninterface Bounds {\n    min: Vec3;\n    max: Vec3;\n}\n\n/**\n * Result of computing Gaussian extents.\n */\ninterface GaussianExtentsResult {\n    /**\n     * DataTable containing extent_x, extent_y, extent_z columns.\n     * To compute AABB for Gaussian i:\n     *   minX = x[i] - extent_x[i], maxX = x[i] + extent_x[i]\n     *   minY = y[i] - extent_y[i], maxY = y[i] + extent_y[i]\n     *   minZ = z[i] - extent_z[i], maxZ = z[i] + extent_z[i]\n     */\n    extents: DataTable;\n\n    /** Scene bounds (union of all Gaussian AABBs) */\n    sceneBounds: Bounds;\n\n    /** Number of Gaussians skipped due to invalid values */\n    invalidCount: number;\n}\n\n/**\n * Compute axis-aligned bounding box half-extents for all Gaussians in a DataTable.\n *\n * Each Gaussian is an oriented ellipsoid defined by position, rotation (quaternion),\n * and scale (log scale). This function computes the AABB that encloses each\n * rotated ellipsoid and stores only the half-extents. The full AABB can be\n * reconstructed at runtime using: min = position - extent, max = position + extent.\n *\n * @param dataTable - DataTable containing Gaussian splat data\n * @returns GaussianExtentsResult with extents DataTable and scene bounds\n */\nconst computeGaussianExtents = (dataTable: DataTable): GaussianExtentsResult => {\n    const numRows = dataTable.numRows;\n\n    // Get column data\n    const x = dataTable.getColumnByName('x').data;\n    const y = dataTable.getColumnByName('y').data;\n    const z = dataTable.getColumnByName('z').data;\n    const rx = dataTable.getColumnByName('rot_1').data;\n    const ry = dataTable.getColumnByName('rot_2').data;\n    const rz = dataTable.getColumnByName('rot_3').data;\n    const rw = dataTable.getColumnByName('rot_0').data;\n    const sx = dataTable.getColumnByName('scale_0').data;\n    const sy = dataTable.getColumnByName('scale_1').data;\n    const sz = dataTable.getColumnByName('scale_2').data;\n\n    // Allocate output arrays\n    const extentX = new Float32Array(numRows);\n    const extentY = new Float32Array(numRows);\n    const extentZ = new Float32Array(numRows);\n\n    // Scene bounds\n    const sceneMin = new Vec3(Infinity, Infinity, Infinity);\n    const sceneMax = new Vec3(-Infinity, -Infinity, -Infinity);\n\n    // Reusable objects to avoid allocations in the loop\n    const position = new Vec3();\n    const rotation = new Quat();\n    const scale = new Vec3();\n    const mat4 = new Mat4();\n\n    // Local AABB centered at origin\n    const localBox = new BoundingBox();\n    localBox.center.set(0, 0, 0);\n\n    // Transformed AABB\n    const worldBox = new BoundingBox();\n\n    let invalidCount = 0;\n\n    for (let i = 0; i < numRows; i++) {\n        // Get Gaussian properties\n        position.set(x[i], y[i], z[i]);\n        rotation.set(rx[i], ry[i], rz[i], rw[i]).normalize();\n        scale.set(Math.exp(sx[i]), Math.exp(sy[i]), Math.exp(sz[i]));\n\n        // Set local box half-extents to N-sigma (Gaussians render out to N-sigma).\n        // Matches the rasterizer's projected radius (`SIGMA_CUTOFF · sqrt(λmax)`),\n        // so any splat included by the BVH cull is actually rasterized.\n        localBox.halfExtents.set(scale.x * SIGMA_CUTOFF, scale.y * SIGMA_CUTOFF, scale.z * SIGMA_CUTOFF);\n\n        // Create rotation matrix (translation is included to position the AABB correctly)\n        mat4.setTRS(position, rotation, Vec3.ONE);\n\n        // Transform local AABB to world space AABB\n        worldBox.setFromTransformedAabb(localBox, mat4);\n\n        // Get the half-extents of the world-space AABB\n        const halfExtents = worldBox.halfExtents;\n\n        // Validate\n        if (!isFinite(halfExtents.x) || !isFinite(halfExtents.y) || !isFinite(halfExtents.z)) {\n            // Store zero extents for invalid Gaussians\n            extentX[i] = 0;\n            extentY[i] = 0;\n            extentZ[i] = 0;\n            invalidCount++;\n            continue;\n        }\n\n        // Store half-extents\n        extentX[i] = halfExtents.x;\n        extentY[i] = halfExtents.y;\n        extentZ[i] = halfExtents.z;\n\n        // Update scene bounds (AABB = position +/- halfExtents)\n        const minX = position.x - halfExtents.x;\n        const minY = position.y - halfExtents.y;\n        const minZ = position.z - halfExtents.z;\n        const maxX = position.x + halfExtents.x;\n        const maxY = position.y + halfExtents.y;\n        const maxZ = position.z + halfExtents.z;\n\n        if (minX < sceneMin.x) sceneMin.x = minX;\n        if (minY < sceneMin.y) sceneMin.y = minY;\n        if (minZ < sceneMin.z) sceneMin.z = minZ;\n        if (maxX > sceneMax.x) sceneMax.x = maxX;\n        if (maxY > sceneMax.y) sceneMax.y = maxY;\n        if (maxZ > sceneMax.z) sceneMax.z = maxZ;\n    }\n\n    if (invalidCount > 0) {\n        logger.warn(`Skipped ${fmtCount(invalidCount)} Gaussians with invalid scale/rotation values`);\n    }\n\n    // Create DataTable with extent columns\n    const extentsTable = new DataTable([\n        new Column('extent_x', extentX),\n        new Column('extent_y', extentY),\n        new Column('extent_z', extentZ)\n    ]);\n\n    return {\n        extents: extentsTable,\n        sceneBounds: {\n            min: sceneMin,\n            max: sceneMax\n        },\n        invalidCount\n    };\n};\n\nexport {\n    computeGaussianExtents\n};\n\nexport type { Bounds, GaussianExtentsResult };\n","import { TypedArray } from './data-table';\nimport { sigmoid } from '../utils';\n\n/**\n * Pre-computed per-Gaussian inverse transform data for evaluating\n * Gaussian contribution at arbitrary 3D points.\n */\ninterface GaussianInverseTransform {\n    /** Inverse rotation quaternion (w, x, y, z) with xyz negated */\n    qw: number;\n    qx: number;\n    qy: number;\n    qz: number;\n    /** Inverse scale: exp(-log_scale) per axis */\n    isx: number;\n    isy: number;\n    isz: number;\n    /** Linear opacity (sigmoid of raw logit) */\n    alpha: number;\n}\n\n/**\n * Compute the inverse transform for a single Gaussian.\n *\n * @param rotW - Quaternion w component.\n * @param rotX - Quaternion x component.\n * @param rotY - Quaternion y component.\n * @param rotZ - Quaternion z component.\n * @param logScaleX - Log scale x.\n * @param logScaleY - Log scale y.\n * @param logScaleZ - Log scale z.\n * @param opacityLogit - Raw opacity logit value.\n * @returns Inverse transform parameters.\n */\nconst computeGaussianInverse = (\n    rotW: number, rotX: number, rotY: number, rotZ: number,\n    logScaleX: number, logScaleY: number, logScaleZ: number,\n    opacityLogit: number\n): GaussianInverseTransform => {\n    const qlen = Math.sqrt(rotW * rotW + rotX * rotX + rotY * rotY + rotZ * rotZ);\n    const invLen = qlen > 0 ? 1 / qlen : 0;\n    return {\n        qw: rotW * invLen,\n        qx: -rotX * invLen,\n        qy: -rotY * invLen,\n        qz: -rotZ * invLen,\n        isx: Math.exp(-logScaleX),\n        isy: Math.exp(-logScaleY),\n        isz: Math.exp(-logScaleZ),\n        alpha: sigmoid(opacityLogit)\n    };\n};\n\n/**\n * Evaluate a Gaussian's opacity contribution at a 3D point.\n *\n * Uses the Rodrigues cross-product formula for inverse rotation,\n * then computes the Mahalanobis distance in the Gaussian's local frame.\n *\n * @param g - Pre-computed inverse transform of the Gaussian.\n * @param px - Gaussian center x.\n * @param py - Gaussian center y.\n * @param pz - Gaussian center z.\n * @param vx - Evaluation point x.\n * @param vy - Evaluation point y.\n * @param vz - Evaluation point z.\n * @returns Opacity contribution at the evaluation point.\n */\nconst evaluateGaussianAt = (\n    g: GaussianInverseTransform,\n    px: number, py: number, pz: number,\n    vx: number, vy: number, vz: number\n): number => {\n    const dx = vx - px;\n    const dy = vy - py;\n    const dz = vz - pz;\n\n    const tx = 2 * (g.qy * dz - g.qz * dy);\n    const ty = 2 * (g.qz * dx - g.qx * dz);\n    const tz = 2 * (g.qx * dy - g.qy * dx);\n\n    const ldx = dx + g.qw * tx + (g.qy * tz - g.qz * ty);\n    const ldy = dy + g.qw * ty + (g.qz * tx - g.qx * tz);\n    const ldz = dz + g.qw * tz + (g.qx * ty - g.qy * tx);\n\n    const sdx = ldx * g.isx;\n    const sdy = ldy * g.isy;\n    const sdz = ldz * g.isz;\n    const d2 = sdx * sdx + sdy * sdy + sdz * sdz;\n\n    return g.alpha * Math.exp(-0.5 * d2);\n};\n\n/**\n * Column arrays needed for Gaussian contribution evaluation.\n */\ninterface GaussianColumns {\n    posX: TypedArray;\n    posY: TypedArray;\n    posZ: TypedArray;\n    rotW: TypedArray;\n    rotX: TypedArray;\n    rotY: TypedArray;\n    rotZ: TypedArray;\n    scaleX: TypedArray;\n    scaleY: TypedArray;\n    scaleZ: TypedArray;\n    opacity: TypedArray;\n    extentX: TypedArray;\n    extentY: TypedArray;\n    extentZ: TypedArray;\n}\n\nexport {\n    evaluateGaussianAt,\n    computeGaussianInverse,\n    type GaussianColumns,\n    type GaussianInverseTransform\n};\n","import { DataTable } from './data-table';\nimport { logger } from '../utils';\n\n// sort the provided indices into morton order\nconst sortMortonOrder = (dataTable: DataTable, indices: Uint32Array): void => {\n    const xCol = dataTable.getColumnByName('x');\n    const yCol = dataTable.getColumnByName('y');\n    const zCol = dataTable.getColumnByName('z');\n\n    if (!xCol || !yCol || !zCol) {\n        logger.debug('missing required position columns');\n        return;\n    }\n\n    const cx = xCol.data;\n    const cy = yCol.data;\n    const cz = zCol.data;\n\n    const generate = (indices: Uint32Array) => {\n        if (indices.length === 0) {\n            return;\n        }\n\n        // https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/\n        const encodeMorton3 = (x: number, y: number, z: number) : number => {\n            const Part1By2 = (x: number) => {\n                x &= 0x000003ff;\n                x = (x ^ (x << 16)) & 0xff0000ff;\n                x = (x ^ (x <<  8)) & 0x0300f00f;\n                x = (x ^ (x <<  4)) & 0x030c30c3;\n                x = (x ^ (x <<  2)) & 0x09249249;\n                return x;\n            };\n\n            return (Part1By2(z) << 2) + (Part1By2(y) << 1) + Part1By2(x);\n        };\n\n        let mx = Infinity;\n        let my = Infinity;\n        let mz = Infinity;\n        let Mx = -Infinity;\n        let My = -Infinity;\n        let Mz = -Infinity;\n\n        // calculate scene extents across all splats (using sort centers, because they're in world space)\n        for (let i = 0; i < indices.length; ++i) {\n            const ri = indices[i];\n            const x = cx[ri];\n            const y = cy[ri];\n            const z = cz[ri];\n\n            if (x < mx) mx = x;\n            if (x > Mx) Mx = x;\n            if (y < my) my = y;\n            if (y > My) My = y;\n            if (z < mz) mz = z;\n            if (z > Mz) Mz = z;\n        }\n\n        const xlen = Mx - mx;\n        const ylen = My - my;\n        const zlen = Mz - mz;\n\n        if (!isFinite(xlen) || !isFinite(ylen) || !isFinite(zlen)) {\n            logger.debug('invalid extents', xlen, ylen, zlen);\n            return;\n        }\n\n        // all points are identical\n        if (xlen === 0 && ylen === 0 && zlen === 0) {\n            return;\n        }\n\n        const xmul = (xlen === 0) ? 0 : 1024 / xlen;\n        const ymul = (ylen === 0) ? 0 : 1024 / ylen;\n        const zmul = (zlen === 0) ? 0 : 1024 / zlen;\n\n        const morton = new Uint32Array(indices.length);\n        for (let i = 0; i < indices.length; ++i) {\n            const ri = indices[i];\n            const x = cx[ri];\n            const y = cy[ri];\n            const z = cz[ri];\n\n            const ix = Math.min(1023, (x - mx) * xmul) >>> 0;\n            const iy = Math.min(1023, (y - my) * ymul) >>> 0;\n            const iz = Math.min(1023, (z - mz) * zmul) >>> 0;\n\n            morton[i] = encodeMorton3(ix, iy, iz);\n        }\n\n        // sort indices by morton code\n        const order = new Uint32Array(indices.length);\n        for (let i = 0; i < order.length; i++) {\n            order[i] = i;\n        }\n        order.sort((a, b) => morton[a] - morton[b]);\n\n        const tmpIndices = indices.slice();\n        for (let i = 0; i < indices.length; ++i) {\n            indices[i] = tmpIndices[order[i]];\n        }\n\n        // sort the largest buckets recursively\n        let start = 0;\n        let end = 1;\n        while (start < indices.length) {\n            while (end < indices.length && morton[order[end]] === morton[order[start]]) {\n                ++end;\n            }\n\n            if (end - start > 256) {\n                generate(indices.subarray(start, end));\n            }\n\n            start = end;\n        }\n    };\n\n    generate(indices);\n};\n\nexport { sortMortonOrder };\n","import type { DataTable } from './data-table';\n\nconst shRestNames = new Array(45).fill('').map((_, i) => `f_rest_${i}`);\n\n/**\n * Determines how many SH bands (0-3) the DataTable contains beyond the DC\n * term. Detection assumes the channel-major layout used throughout the\n * codebase: N coefficients per channel, 3 channels, stored as\n * `f_rest_0`..`f_rest_(3N-1)`.\n *\n * - 0 bands: no `f_rest_*` columns\n * - 1 band : `f_rest_0`..`f_rest_8`   (9 coeffs)\n * - 2 bands: `f_rest_0`..`f_rest_23`  (24 coeffs)\n * - 3 bands: `f_rest_0`..`f_rest_44`  (45 coeffs)\n *\n * @param dataTable - The DataTable to inspect.\n * @returns The number of SH bands (0-3).\n */\nconst getSHBands = (dataTable: DataTable): number => {\n    const idx = shRestNames.findIndex(v => !dataTable.hasColumn(v));\n    return ({ '9': 1, '24': 2, '-1': 3 } as Record<string, number>)[String(idx)] ?? 0;\n};\n\nexport { getSHBands, shRestNames };\n","import { Column, DataTable, TypedArray } from './data-table';\n\n/** Number of bins for histogram. */\nconst NUM_BINS = 16;\n\n/** Unicode block characters for histogram visualization (lowest to highest). */\nconst BARS = '▁▂▃▄▅▆▇█';\n\n/**\n * Statistical summary for a single column.\n */\ntype ColumnStats = {\n    /** Minimum value (excluding NaN/Inf). */\n    min: number;\n    /** Maximum value (excluding NaN/Inf). */\n    max: number;\n    /** Median value. */\n    median: number;\n    /** Arithmetic mean. */\n    mean: number;\n    /** Standard deviation. */\n    stdDev: number;\n    /** Count of NaN values. */\n    nanCount: number;\n    /** Count of Infinity values. */\n    infCount: number;\n    /** ASCII histogram of value distribution. */\n    histogram: string;\n};\n\n/**\n * Statistical summary for an entire DataTable.\n */\ntype SummaryData = {\n    /** Summary format version. */\n    version: number;\n    /** Total number of rows. */\n    rowCount: number;\n    /** Per-column statistics keyed by column name. */\n    columns: Record<string, ColumnStats>;\n};\n\nconst PRECISION = 6;\n\nconst round = (value: number): number => {\n    if (!Number.isFinite(value)) return value;\n    return Math.round(value * Math.pow(10, PRECISION)) / Math.pow(10, PRECISION);\n};\n\n/**\n * QuickSelect algorithm to find the k-th smallest element in O(n) average time.\n * Modifies the array in place (partial reordering).\n *\n * @param arr - The typed array to search.\n * @param k - The index of the element to find (0-based).\n * @param left - Left boundary of the search range.\n * @param right - Right boundary of the search range.\n * @returns The k-th smallest element.\n */\nconst quickSelect = (arr: TypedArray, k: number, left: number, right: number): number => {\n    while (left < right) {\n        // Use median-of-three pivot selection for better performance\n        const mid = (left + right) >>> 1;\n        if (arr[mid] < arr[left]) {\n            const t = arr[left]; arr[left] = arr[mid]; arr[mid] = t;\n        }\n        if (arr[right] < arr[left]) {\n            const t = arr[left]; arr[left] = arr[right]; arr[right] = t;\n        }\n        if (arr[right] < arr[mid]) {\n            const t = arr[mid]; arr[mid] = arr[right]; arr[right] = t;\n        }\n\n        const pivot = arr[mid];\n        let i = left;\n        let j = right;\n\n        while (i <= j) {\n            while (arr[i] < pivot) i++;\n            while (arr[j] > pivot) j--;\n            if (i <= j) {\n                const t = arr[i]; arr[i] = arr[j]; arr[j] = t;\n                i++;\n                j--;\n            }\n        }\n\n        if (k <= j) {\n            right = j;\n        } else if (k >= i) {\n            left = i;\n        } else {\n            break;\n        }\n    }\n    return arr[k];\n};\n\nconst computeColumnStats = (column: Column): ColumnStats => {\n    const data = column.data;\n    const len = data.length;\n\n    // First pass: count valid values, compute min/max/sum, count NaN/Inf\n    let nanCount = 0;\n    let infCount = 0;\n    let validCount = 0;\n    let min = Infinity;\n    let max = -Infinity;\n    let sum = 0;\n\n    for (let i = 0; i < len; i++) {\n        const v = data[i];\n        if (Number.isNaN(v)) {\n            nanCount++;\n        } else if (!Number.isFinite(v)) {\n            infCount++;\n        } else {\n            validCount++;\n            if (v < min) min = v;\n            if (v > max) max = v;\n            sum += v;\n        }\n    }\n\n    // Handle case where all values are NaN/Inf\n    if (validCount === 0) {\n        return {\n            min: NaN,\n            max: NaN,\n            median: NaN,\n            mean: NaN,\n            stdDev: NaN,\n            nanCount,\n            infCount,\n            histogram: ' '.repeat(NUM_BINS)\n        };\n    }\n\n    const mean = sum / validCount;\n\n    // Second pass: copy valid values to typed array, compute stdDev, and build histogram\n    // Use the same typed array type as the source to preserve precision and save memory\n    const TypedArrayCtor = data.constructor as new (length: number) => TypedArray;\n    const validValues = new TypedArrayCtor(validCount);\n    const bins = new Uint32Array(NUM_BINS);\n    const range = max - min;\n    let sumSquaredDiff = 0;\n    let idx = 0;\n\n    for (let i = 0; i < len; i++) {\n        const v = data[i];\n        if (Number.isFinite(v)) {\n            validValues[idx++] = v;\n            const diff = v - mean;\n            sumSquaredDiff += diff * diff;\n\n            // Bucket value into histogram bin\n            if (range > 0) {\n                const binIndex = Math.min(NUM_BINS - 1, Math.floor((v - min) / range * NUM_BINS));\n                bins[binIndex]++;\n            } else {\n                // All values are the same - put in middle bin\n                bins[NUM_BINS >>> 1]++;\n            }\n        }\n    }\n\n    const stdDev = Math.sqrt(sumSquaredDiff / validCount);\n\n    // Convert bins to ASCII histogram\n    let maxBin = 0;\n    for (let i = 0; i < NUM_BINS; i++) {\n        if (bins[i] > maxBin) maxBin = bins[i];\n    }\n    let histogram = '';\n    for (let i = 0; i < NUM_BINS; i++) {\n        if (bins[i] === 0) {\n            histogram += ' ';\n        } else {\n            const level = maxBin > 0 ? Math.floor(bins[i] / maxBin * (BARS.length - 1)) : 0;\n            histogram += BARS[level];\n        }\n    }\n\n    // Compute median using QuickSelect - O(n) instead of O(n log n)\n    const mid = validCount >>> 1;\n    let median: number;\n\n    if (validCount % 2 === 0) {\n        // For even count, need both middle values\n        const lower = quickSelect(validValues, mid - 1, 0, validCount - 1);\n        const upper = quickSelect(validValues, mid, 0, validCount - 1);\n        median = (lower + upper) / 2;\n    } else {\n        median = quickSelect(validValues, mid, 0, validCount - 1);\n    }\n\n    return {\n        min: round(min),\n        max: round(max),\n        median: round(median),\n        mean: round(mean),\n        stdDev: round(stdDev),\n        nanCount,\n        infCount,\n        histogram\n    };\n};\n\n/**\n * Computes statistical summary for all columns in a DataTable.\n *\n * For each column, calculates min, max, median, mean, standard deviation,\n * and counts of NaN/Infinity values. Useful for data validation and analysis.\n *\n * @param dataTable - The DataTable to analyze.\n * @returns Summary data with per-column statistics.\n *\n * @example\n * ```ts\n * const summary = computeSummary(dataTable);\n * console.log(summary.rowCount);\n * console.log(summary.columns['x'].mean);\n * console.log(summary.columns['opacity'].nanCount);\n * ```\n */\nconst computeSummary = (dataTable: DataTable): SummaryData => {\n    const columns: Record<string, ColumnStats> = {};\n\n    for (const column of dataTable.columns) {\n        columns[column.name] = computeColumnStats(column);\n    }\n\n    return {\n        version: 1,\n        rowCount: dataTable.numRows,\n        columns\n    };\n};\n\nexport { computeSummary, type ColumnStats, type SummaryData };\n","/**\n * Abstract base class for streaming data from a source.\n * Uses a pull-based model where the consumer provides the buffer.\n */\nabstract class ReadStream {\n    /**\n     * Size hint for buffer pre-allocation in readAll().\n     * May be undefined if size is unknown.\n     */\n    readonly expectedSize: number | undefined;\n\n    /**\n     * Total bytes read from this stream so far.\n     */\n    bytesRead: number = 0;\n\n    /**\n     * @param expectedSize - Optional size hint for buffer pre-allocation\n     */\n    constructor(expectedSize?: number) {\n        this.expectedSize = expectedSize;\n    }\n\n    /**\n     * Pull data into the provided buffer.\n     * @param target - Buffer to fill with data\n     * @returns Number of bytes read, or 0 for EOF\n     */\n    abstract pull(target: Uint8Array): Promise<number>;\n\n    /**\n     * Read entire stream into a single buffer.\n     * Uses expectedSize hint if available, grows dynamically if needed.\n     * @returns Complete data as Uint8Array\n     */\n    async readAll(): Promise<Uint8Array> {\n        const capacity = this.expectedSize ?? 65536;\n        let buffer = new Uint8Array(capacity);\n        let length = 0;\n\n        while (true) {\n            // Grow buffer if full\n            if (length >= buffer.length) {\n                const newBuffer = new Uint8Array(buffer.length * 2);\n                newBuffer.set(buffer);\n                buffer = newBuffer;\n            }\n\n            const n = await this.pull(buffer.subarray(length));\n            if (n === 0) break;\n            length += n;\n        }\n\n        // Return exact-sized view\n        return buffer.subarray(0, length);\n    }\n\n    /**\n     * Release resources and abort any pending operations.\n     */\n    close(): void {\n        // Base implementation does nothing - subclasses can override\n    }\n}\n\n/**\n * Interface representing a readable data source.\n * Provides size information and creates streams for reading.\n */\ninterface ReadSource {\n    /**\n     * The size of the source in bytes, or undefined if unknown.\n     * For compressed sources (e.g., gzipped HTTP), this may be approximate.\n     */\n    readonly size: number | undefined;\n\n    /**\n     * Whether range reads are supported.\n     * If false, read() must be called with no arguments or start=0.\n     */\n    readonly seekable: boolean;\n\n    /**\n     * Create a stream for reading data, optionally with a byte range.\n     * @param start - Starting byte offset (inclusive), defaults to 0\n     * @param end - Ending byte offset (exclusive), defaults to size/EOF\n     * @returns A ReadStream for pulling data\n     * @throws Error if range requested on non-seekable source\n     */\n    read(start?: number, end?: number): ReadStream;\n\n    /**\n     * Release any resources held by this source.\n     */\n    close(): void;\n}\n\n/**\n * Progress callback for tracking read operations.\n * @param bytesLoaded - Bytes loaded so far\n * @param totalBytes - Total bytes if known, undefined otherwise\n */\ntype ProgressCallback = (bytesLoaded: number, totalBytes: number | undefined) => void;\n\n/**\n * Interface for a file system that can create readable sources.\n * Implementations exist for various backends (URL, Node FS, Zip, Memory).\n */\ninterface ReadFileSystem {\n    /**\n     * Create a readable source for the given path/identifier.\n     * @param filename - Path or identifier for the resource\n     * @param progress - Optional callback for progress reporting\n     * @returns Promise resolving to a ReadSource\n     */\n    createSource(filename: string, progress?: ProgressCallback): Promise<ReadSource>;\n}\n\n/**\n * Read an entire file into memory.\n * Convenience helper that handles source creation, reading, and cleanup.\n * @param fs - The file system to read from\n * @param filename - Path or identifier for the resource\n * @returns Promise resolving to file contents as Uint8Array\n */\nconst readFile = async (fs: ReadFileSystem, filename: string): Promise<Uint8Array> => {\n    const source = await fs.createSource(filename);\n    try {\n        const stream = source.read();\n        return await stream.readAll();\n    } finally {\n        source.close();\n    }\n};\n\nexport { ReadStream, type ReadSource, type ReadFileSystem, type ProgressCallback, readFile };\n","import { ReadStream } from './file-system';\n\n/**\n * ReadStream wrapper that adds read-ahead buffering to reduce async overhead.\n * Reads larger chunks from the inner stream and buffers excess data for\n * subsequent small reads. Useful for sources with high per-call overhead.\n *\n * @example\n * // Wrap a stream with 4MB read-ahead buffering\n * const buffered = new BufferedReadStream(rawStream, 4 * 1024 * 1024);\n * const data = await buffered.readAll();\n */\nclass BufferedReadStream extends ReadStream {\n    private inner: ReadStream;\n    private chunkSize: number;\n\n    // Buffer state\n    private buffer: Uint8Array | null = null;\n    private bufferOffset = 0;\n\n    /**\n     * Create a caching wrapper around a stream.\n     * @param inner - The underlying stream to read from\n     * @param chunkSize - Minimum bytes to read at once from inner stream (default 64KB)\n     */\n    constructor(inner: ReadStream, chunkSize: number = 65536) {\n        super(inner.expectedSize);\n        this.inner = inner;\n        this.chunkSize = chunkSize;\n    }\n\n    async pull(target: Uint8Array): Promise<number> {\n        // Early return for zero-length requests (e.g., EOF check from readAll)\n        if (target.length === 0) {\n            return 0;\n        }\n\n        let written = 0;\n\n        // Serve from buffer first\n        if (this.buffer && this.bufferOffset < this.buffer.length) {\n            const available = this.buffer.length - this.bufferOffset;\n            const toCopy = Math.min(available, target.length);\n            target.set(this.buffer.subarray(this.bufferOffset, this.bufferOffset + toCopy));\n            this.bufferOffset += toCopy;\n            written += toCopy;\n            this.bytesRead += toCopy;\n\n            // Clear exhausted buffer\n            if (this.bufferOffset >= this.buffer.length) {\n                this.buffer = null;\n                this.bufferOffset = 0;\n            }\n\n            if (written >= target.length) {\n                return written;\n            }\n        }\n\n        // Read a chunk from inner stream\n        const remaining = target.length - written;\n        const readSize = Math.max(this.chunkSize, remaining);\n        const chunk = new Uint8Array(readSize);\n        const n = await this.inner.pull(chunk);\n\n        if (n === 0) {\n            return written;\n        }\n\n        // Copy what we need to target\n        const toCopy = Math.min(n, remaining);\n        target.set(chunk.subarray(0, toCopy), written);\n        written += toCopy;\n        this.bytesRead += toCopy;\n\n        // Cache the excess\n        if (toCopy < n) {\n            this.buffer = chunk.subarray(0, n);\n            this.bufferOffset = toCopy;\n        }\n\n        return written;\n    }\n\n    close(): void {\n        this.inner.close();\n        this.buffer = null;\n    }\n}\n\nexport { BufferedReadStream };\n","let _lazyMatch = () => { var __lib__=(()=>{var m=Object.defineProperty,V=Object.getOwnPropertyDescriptor,G=Object.getOwnPropertyNames,T=Object.prototype.hasOwnProperty,q=(r,e)=>{for(var n in e)m(r,n,{get:e[n],enumerable:true});},H=(r,e,n,a)=>{if(e&&typeof e==\"object\"||typeof e==\"function\")for(let t of G(e))!T.call(r,t)&&t!==n&&m(r,t,{get:()=>e[t],enumerable:!(a=V(e,t))||a.enumerable});return r},J=r=>H(m({},\"__esModule\",{value:true}),r),w={};q(w,{default:()=>re});var A=r=>Array.isArray(r),d=r=>typeof r==\"function\",Q=r=>r.length===0,W=r=>typeof r==\"number\",K=r=>typeof r==\"object\"&&r!==null,X=r=>r instanceof RegExp,b=r=>typeof r==\"string\",h=r=>r===void 0,Y=r=>{const e=new Map;return n=>{const a=e.get(n);if(a)return a;const t=r(n);return e.set(n,t),t}},rr=(r,e,n={})=>{const a={cache:{},input:r,index:0,indexMax:0,options:n,output:[]};if(v(e)(a)&&a.index===r.length)return a.output;throw new Error(`Failed to parse at index ${a.indexMax}`)},i=(r,e)=>A(r)?er(r,e):b(r)?ar(r,e):nr(r,e),er=(r,e)=>{const n={};for(const a of r){if(a.length!==1)throw new Error(`Invalid character: \"${a}\"`);const t=a.charCodeAt(0);n[t]=true;}return a=>{const t=a.index,o=a.input;for(;a.index<o.length&&o.charCodeAt(a.index)in n;)a.index+=1;const u=a.index;if(u>t){if(!h(e)&&!a.options.silent){const s=a.input.slice(t,u),c=d(e)?e(s,o,String(t)):e;h(c)||a.output.push(c);}a.indexMax=Math.max(a.indexMax,a.index);}return  true}},nr=(r,e)=>{const n=r.source,a=r.flags.replace(/y|$/,\"y\"),t=new RegExp(n,a);return g(o=>{t.lastIndex=o.index;const u=t.exec(o.input);if(u){if(!h(e)&&!o.options.silent){const s=d(e)?e(...u,o.input,String(o.index)):e;h(s)||o.output.push(s);}return o.index+=u[0].length,o.indexMax=Math.max(o.indexMax,o.index),true}else return  false})},ar=(r,e)=>n=>{if(n.input.startsWith(r,n.index)){if(!h(e)&&!n.options.silent){const t=d(e)?e(r,n.input,String(n.index)):e;h(t)||n.output.push(t);}return n.index+=r.length,n.indexMax=Math.max(n.indexMax,n.index),true}else return  false},C=(r,e,n,a)=>{const t=v(r);return g(_(M(o=>{let u=0;for(;u<n;){const s=o.index;if(!t(o)||(u+=1,o.index===s))break}return u>=e})))},tr=(r,e)=>C(r,0,1),f=(r,e)=>C(r,0,1/0),x=(r,e)=>{const n=r.map(v);return g(_(M(a=>{for(let t=0,o=n.length;t<o;t++)if(!n[t](a))return  false;return  true})))},l=(r,e)=>{const n=r.map(v);return g(_(a=>{for(let t=0,o=n.length;t<o;t++)if(n[t](a))return  true;return  false}))},M=(r,e=false)=>{const n=v(r);return a=>{const t=a.index,o=a.output.length,u=n(a);return (!u||e)&&(a.index=t,a.output.length!==o&&(a.output.length=o)),u}},_=(r,e)=>{const n=v(r);return n},g=(()=>{let r=0;return e=>{const n=v(e),a=r+=1;return t=>{var o;if(t.options.memoization===false)return n(t);const u=t.index,s=(o=t.cache)[a]||(o[a]=new Map),c=s.get(u);if(c===false)return  false;if(W(c))return t.index=c,true;if(c)return t.index=c.index,c.output?.length&&t.output.push(...c.output),true;{const Z=t.output.length;if(n(t)){const D=t.index,U=t.output.length;if(U>Z){const ee=t.output.slice(Z,U);s.set(u,{index:D,output:ee});}else s.set(u,D);return  true}else return s.set(u,false),false}}}})(),E=r=>{let e;return n=>(e||(e=v(r())),e(n))},v=Y(r=>{if(d(r))return Q(r)?E(r):r;if(b(r)||X(r))return i(r);if(A(r))return x(r);if(K(r))return l(Object.values(r));throw new Error(\"Invalid rule\")}),P=\"abcdefghijklmnopqrstuvwxyz\",ir=r=>{let e=\"\";for(;r>0;){const n=(r-1)%26;e=P[n]+e,r=Math.floor((r-1)/26);}return e},O=r=>{let e=0;for(let n=0,a=r.length;n<a;n++)e=e*26+P.indexOf(r[n])+1;return e},S=(r,e)=>{if(e<r)return S(e,r);const n=[];for(;r<=e;)n.push(r++);return n},or=(r,e,n)=>S(r,e).map(a=>String(a).padStart(n,\"0\")),R=(r,e)=>S(O(r),O(e)).map(ir),p=r=>r,z=r=>ur(e=>rr(e,r,{memoization:false}).join(\"\")),ur=r=>{const e={};return n=>e[n]??(e[n]=r(n))},sr=i(/^\\*\\*\\/\\*$/,\".*\"),cr=i(/^\\*\\*\\/(\\*)?([ a-zA-Z0-9._-]+)$/,(r,e,n)=>`.*${e?\"\":\"(?:^|/)\"}${n.replaceAll(\".\",\"\\\\.\")}`),lr=i(/^\\*\\*\\/(\\*)?([ a-zA-Z0-9._-]*)\\{([ a-zA-Z0-9._-]+(?:,[ a-zA-Z0-9._-]+)*)\\}$/,(r,e,n,a)=>`.*${e?\"\":\"(?:^|/)\"}${n.replaceAll(\".\",\"\\\\.\")}(?:${a.replaceAll(\",\",\"|\").replaceAll(\".\",\"\\\\.\")})`),y=i(/\\\\./,p),pr=i(/[$.*+?^(){}[\\]\\|]/,r=>`\\\\${r}`),vr=i(/./,p),hr=i(/^(?:!!)*!(.*)$/,(r,e)=>`(?!^${L(e)}$).*?`),dr=i(/^(!!)+/,\"\"),fr=l([hr,dr]),xr=i(/\\/(\\*\\*\\/)+/,\"(?:/.+/|/)\"),gr=i(/^(\\*\\*\\/)+/,\"(?:^|.*/)\"),mr=i(/\\/(\\*\\*)$/,\"(?:/.*|$)\"),_r=i(/\\*\\*/,\".*\"),j=l([xr,gr,mr,_r]),Sr=i(/\\*\\/(?!\\*\\*\\/)/,\"[^/]*/\"),yr=i(/\\*/,\"[^/]*\"),N=l([Sr,yr]),k=i(\"?\",\"[^/]\"),$r=i(\"[\",p),wr=i(\"]\",p),Ar=i(/[!^]/,\"^/\"),br=i(/[a-z]-[a-z]|[0-9]-[0-9]/i,p),Cr=i(/[$.*+?^(){}[\\|]/,r=>`\\\\${r}`),Mr=i(/[^\\]]/,p),Er=l([y,Cr,br,Mr]),B=x([$r,tr(Ar),f(Er),wr]),Pr=i(\"{\",\"(?:\"),Or=i(\"}\",\")\"),Rr=i(/(\\d+)\\.\\.(\\d+)/,(r,e,n)=>or(+e,+n,Math.min(e.length,n.length)).join(\"|\")),zr=i(/([a-z]+)\\.\\.([a-z]+)/,(r,e,n)=>R(e,n).join(\"|\")),jr=i(/([A-Z]+)\\.\\.([A-Z]+)/,(r,e,n)=>R(e.toLowerCase(),n.toLowerCase()).join(\"|\").toUpperCase()),Nr=l([Rr,zr,jr]),I=x([Pr,Nr,Or]),kr=i(\"{\",\"(?:\"),Br=i(\"}\",\")\"),Ir=i(\",\",\"|\"),Fr=i(/[$.*+?^(){[\\]\\|]/,r=>`\\\\${r}`),Lr=i(/[^}]/,p),Zr=E(()=>F),Dr=l([j,N,k,B,I,Zr,y,Fr,Ir,Lr]),F=x([kr,f(Dr),Br]),Ur=f(l([sr,cr,lr,fr,j,N,k,B,I,F,y,pr,vr])),Vr=Ur,Gr=z(Vr),L=Gr,Tr=i(/\\\\./,p),qr=i(/./,p),Hr=i(/\\*\\*\\*+/,\"*\"),Jr=i(/([^/{[(!])\\*\\*/,(r,e)=>`${e}*`),Qr=i(/(^|.)\\*\\*(?=[^*/)\\]}])/,(r,e)=>`${e}*`),Wr=f(l([Tr,Hr,Jr,Qr,qr])),Kr=Wr,Xr=z(Kr),Yr=Xr,$=(r,e)=>{const n=Array.isArray(r)?r:[r];if(!n.length)return  false;const a=n.map($.compile),t=n.every(s=>/(\\/(?:\\*\\*)?|\\[\\/\\])$/.test(s)),o=e.replace(/[\\\\\\/]+/g,\"/\").replace(/\\/$/,t?\"/\":\"\");return a.some(s=>s.test(o))};$.compile=r=>new RegExp(`^${L(Yr(r))}$`,\"s\");var re=$;return J(w)})();\n return __lib__.default || __lib__; };\nlet _match;\nconst zeptomatch = (path, pattern) => {\n  if (!_match) {\n    _match = _lazyMatch();\n    _lazyMatch = null;\n  }\n  return _match(path, pattern);\n};\n\nconst _DRIVE_LETTER_START_RE = /^[A-Za-z]:\\//;\nfunction normalizeWindowsPath(input = \"\") {\n  if (!input) {\n    return input;\n  }\n  return input.replace(/\\\\/g, \"/\").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());\n}\n\nconst _UNC_REGEX = /^[/\\\\]{2}/;\nconst _IS_ABSOLUTE_RE = /^[/\\\\](?![/\\\\])|^[/\\\\]{2}(?!\\.)|^[A-Za-z]:[/\\\\]/;\nconst _DRIVE_LETTER_RE = /^[A-Za-z]:$/;\nconst _ROOT_FOLDER_RE = /^\\/([A-Za-z]:)?$/;\nconst _EXTNAME_RE = /.(\\.[^./]+|\\.)$/;\nconst _PATH_ROOT_RE = /^[/\\\\]|^[a-zA-Z]:[/\\\\]/;\nconst sep = \"/\";\nconst normalize = function(path) {\n  if (path.length === 0) {\n    return \".\";\n  }\n  path = normalizeWindowsPath(path);\n  const isUNCPath = path.match(_UNC_REGEX);\n  const isPathAbsolute = isAbsolute(path);\n  const trailingSeparator = path[path.length - 1] === \"/\";\n  path = normalizeString(path, !isPathAbsolute);\n  if (path.length === 0) {\n    if (isPathAbsolute) {\n      return \"/\";\n    }\n    return trailingSeparator ? \"./\" : \".\";\n  }\n  if (trailingSeparator) {\n    path += \"/\";\n  }\n  if (_DRIVE_LETTER_RE.test(path)) {\n    path += \"/\";\n  }\n  if (isUNCPath) {\n    if (!isPathAbsolute) {\n      return `//./${path}`;\n    }\n    return `//${path}`;\n  }\n  return isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;\n};\nconst join = function(...segments) {\n  let path = \"\";\n  for (const seg of segments) {\n    if (!seg) {\n      continue;\n    }\n    if (path.length > 0) {\n      const pathTrailing = path[path.length - 1] === \"/\";\n      const segLeading = seg[0] === \"/\";\n      const both = pathTrailing && segLeading;\n      if (both) {\n        path += seg.slice(1);\n      } else {\n        path += pathTrailing || segLeading ? seg : `/${seg}`;\n      }\n    } else {\n      path += seg;\n    }\n  }\n  return normalize(path);\n};\nfunction cwd() {\n  if (typeof process !== \"undefined\" && typeof process.cwd === \"function\") {\n    return process.cwd().replace(/\\\\/g, \"/\");\n  }\n  return \"/\";\n}\nconst resolve = function(...arguments_) {\n  arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));\n  let resolvedPath = \"\";\n  let resolvedAbsolute = false;\n  for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {\n    const path = index >= 0 ? arguments_[index] : cwd();\n    if (!path || path.length === 0) {\n      continue;\n    }\n    resolvedPath = `${path}/${resolvedPath}`;\n    resolvedAbsolute = isAbsolute(path);\n  }\n  resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);\n  if (resolvedAbsolute && !isAbsolute(resolvedPath)) {\n    return `/${resolvedPath}`;\n  }\n  return resolvedPath.length > 0 ? resolvedPath : \".\";\n};\nfunction normalizeString(path, allowAboveRoot) {\n  let res = \"\";\n  let lastSegmentLength = 0;\n  let lastSlash = -1;\n  let dots = 0;\n  let char = null;\n  for (let index = 0; index <= path.length; ++index) {\n    if (index < path.length) {\n      char = path[index];\n    } else if (char === \"/\") {\n      break;\n    } else {\n      char = \"/\";\n    }\n    if (char === \"/\") {\n      if (lastSlash === index - 1 || dots === 1) ; else if (dots === 2) {\n        if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== \".\" || res[res.length - 2] !== \".\") {\n          if (res.length > 2) {\n            const lastSlashIndex = res.lastIndexOf(\"/\");\n            if (lastSlashIndex === -1) {\n              res = \"\";\n              lastSegmentLength = 0;\n            } else {\n              res = res.slice(0, lastSlashIndex);\n              lastSegmentLength = res.length - 1 - res.lastIndexOf(\"/\");\n            }\n            lastSlash = index;\n            dots = 0;\n            continue;\n          } else if (res.length > 0) {\n            res = \"\";\n            lastSegmentLength = 0;\n            lastSlash = index;\n            dots = 0;\n            continue;\n          }\n        }\n        if (allowAboveRoot) {\n          res += res.length > 0 ? \"/..\" : \"..\";\n          lastSegmentLength = 2;\n        }\n      } else {\n        if (res.length > 0) {\n          res += `/${path.slice(lastSlash + 1, index)}`;\n        } else {\n          res = path.slice(lastSlash + 1, index);\n        }\n        lastSegmentLength = index - lastSlash - 1;\n      }\n      lastSlash = index;\n      dots = 0;\n    } else if (char === \".\" && dots !== -1) {\n      ++dots;\n    } else {\n      dots = -1;\n    }\n  }\n  return res;\n}\nconst isAbsolute = function(p) {\n  return _IS_ABSOLUTE_RE.test(p);\n};\nconst toNamespacedPath = function(p) {\n  return normalizeWindowsPath(p);\n};\nconst extname = function(p) {\n  if (p === \"..\") return \"\";\n  const match = _EXTNAME_RE.exec(normalizeWindowsPath(p));\n  return match && match[1] || \"\";\n};\nconst relative = function(from, to) {\n  const _from = resolve(from).replace(_ROOT_FOLDER_RE, \"$1\").split(\"/\");\n  const _to = resolve(to).replace(_ROOT_FOLDER_RE, \"$1\").split(\"/\");\n  if (_to[0][1] === \":\" && _from[0][1] === \":\" && _from[0] !== _to[0]) {\n    return _to.join(\"/\");\n  }\n  const _fromCopy = [..._from];\n  for (const segment of _fromCopy) {\n    if (_to[0] !== segment) {\n      break;\n    }\n    _from.shift();\n    _to.shift();\n  }\n  return [..._from.map(() => \"..\"), ..._to].join(\"/\");\n};\nconst dirname = function(p) {\n  const segments = normalizeWindowsPath(p).replace(/\\/$/, \"\").split(\"/\").slice(0, -1);\n  if (segments.length === 1 && _DRIVE_LETTER_RE.test(segments[0])) {\n    segments[0] += \"/\";\n  }\n  return segments.join(\"/\") || (isAbsolute(p) ? \"/\" : \".\");\n};\nconst format = function(p) {\n  const ext = p.ext ? p.ext.startsWith(\".\") ? p.ext : `.${p.ext}` : \"\";\n  const segments = [p.root, p.dir, p.base ?? (p.name ?? \"\") + ext].filter(\n    Boolean\n  );\n  return normalizeWindowsPath(\n    p.root ? resolve(...segments) : segments.join(\"/\")\n  );\n};\nconst basename = function(p, extension) {\n  const segments = normalizeWindowsPath(p).split(\"/\");\n  let lastSegment = \"\";\n  for (let i = segments.length - 1; i >= 0; i--) {\n    const val = segments[i];\n    if (val) {\n      lastSegment = val;\n      break;\n    }\n  }\n  return extension && lastSegment.endsWith(extension) ? lastSegment.slice(0, -extension.length) : lastSegment;\n};\nconst parse = function(p) {\n  const root = _PATH_ROOT_RE.exec(p)?.[0]?.replace(/\\\\/g, \"/\") || \"\";\n  const base = basename(p);\n  const extension = extname(base);\n  return {\n    root,\n    dir: dirname(p),\n    base,\n    ext: extension,\n    name: base.slice(0, base.length - extension.length)\n  };\n};\nconst matchesGlob = (path, pattern) => {\n  return zeptomatch(pattern, normalize(path));\n};\n\nconst _path = {\n  __proto__: null,\n  basename: basename,\n  dirname: dirname,\n  extname: extname,\n  format: format,\n  isAbsolute: isAbsolute,\n  join: join,\n  matchesGlob: matchesGlob,\n  normalize: normalize,\n  normalizeString: normalizeString,\n  parse: parse,\n  relative: relative,\n  resolve: resolve,\n  sep: sep,\n  toNamespacedPath: toNamespacedPath\n};\n\nexport { _path as _, normalizeString as a, relative as b, basename as c, dirname as d, extname as e, format as f, normalizeWindowsPath as g, isAbsolute as i, join as j, matchesGlob as m, normalize as n, parse as p, resolve as r, sep as s, toNamespacedPath as t };\n","import { type ReadFileSystem, type ProgressCallback, type ReadSource, ReadStream } from './file-system';\n\n/**\n * ReadStream implementation for reading from memory buffers.\n */\nclass MemoryReadStream extends ReadStream {\n    private data: Uint8Array;\n    private offset: number;\n    private end: number;\n\n    constructor(data: Uint8Array, start: number, end: number) {\n        super(end - start);\n        this.data = data;\n        this.offset = start;\n        this.end = end;\n    }\n\n    pull(target: Uint8Array): Promise<number> {\n        const remaining = this.end - this.offset;\n        if (remaining <= 0) {\n            return Promise.resolve(0);\n        }\n\n        const bytesToCopy = Math.min(target.length, remaining);\n        target.set(this.data.subarray(this.offset, this.offset + bytesToCopy));\n        this.offset += bytesToCopy;\n        this.bytesRead += bytesToCopy;\n        return Promise.resolve(bytesToCopy);\n    }\n}\n\n/**\n * ReadSource implementation wrapping a Uint8Array or ArrayBuffer.\n * Size is always exact. Always seekable.\n */\nclass MemoryReadSource implements ReadSource {\n    readonly size: number;\n    readonly seekable: boolean = true;\n\n    private data: Uint8Array;\n    private closed: boolean = false;\n\n    constructor(data: Uint8Array | ArrayBuffer) {\n        this.data = data instanceof ArrayBuffer ? new Uint8Array(data) : data;\n        this.size = this.data.length;\n    }\n\n    read(start: number = 0, end: number = this.size): ReadStream {\n        if (this.closed) {\n            throw new Error('Source has been closed');\n        }\n\n        // Clamp range to valid bounds\n        const clampedStart = Math.max(0, Math.min(start, this.size));\n        const clampedEnd = Math.max(clampedStart, Math.min(end, this.size));\n\n        return new MemoryReadStream(this.data, clampedStart, clampedEnd);\n    }\n\n    close(): void {\n        this.closed = true;\n    }\n}\n\n/**\n * ReadFileSystem for reading from named memory buffers.\n * Useful for testing or when data is already in memory.\n */\nclass MemoryReadFileSystem implements ReadFileSystem {\n    private buffers: Map<string, Uint8Array> = new Map();\n\n    /**\n     * Store a named buffer.\n     * @param name - Name/path for the buffer\n     * @param data - Data to store\n     */\n    set(name: string, data: Uint8Array): void {\n        this.buffers.set(name, data);\n    }\n\n    /**\n     * Get a stored buffer by name.\n     * @param name - Name/path of the buffer\n     * @returns The stored data or undefined\n     */\n    get(name: string): Uint8Array | undefined {\n        return this.buffers.get(name);\n    }\n\n    createSource(filename: string, progress?: ProgressCallback): Promise<ReadSource> {\n        const data = this.buffers.get(filename);\n        if (!data) {\n            return Promise.reject(new Error(`Entry not found: ${filename}`));\n        }\n\n        // Report complete progress immediately since data is already in memory\n        if (progress) {\n            progress(data.length, data.length);\n        }\n\n        return Promise.resolve(new MemoryReadSource(data));\n    }\n}\n\nexport { MemoryReadFileSystem, MemoryReadSource };\n","import { type ReadFileSystem, type ProgressCallback, type ReadSource, ReadStream } from './file-system';\nimport { MemoryReadSource } from './memory-file-system';\n\n/**\n * Probe a URL to check if the server supports Range requests.\n * We can't rely on the Accept-Ranges header because CORS often blocks access to it\n * (it's not a CORS-safelisted response header).\n * Instead, we request a 1-byte range and check if we get 206 Partial Content.\n * @param url - The URL to probe\n * @returns Object with rangeSupported flag and size (from Content-Range header)\n */\nconst probeRangeSupport = async (url: string): Promise<{ rangeSupported: boolean; size?: number }> => {\n    const controller = new AbortController();\n    try {\n        const response = await fetch(url, {\n            method: 'GET',\n            headers: { 'Range': 'bytes=0-0' },\n            signal: controller.signal\n        });\n\n        // Abort immediately to prevent downloading the body.\n        // This is safe because await fetch() resolves once headers arrive,\n        // so response.status and headers are already available.\n        controller.abort();\n\n        // 206 Partial Content means Range is supported\n        if (response.status === 206) {\n            // Try to get total size from Content-Range header (format: \"bytes 0-0/12345\")\n            const contentRange = response.headers.get('Content-Range');\n            const match = contentRange?.match(/\\/(\\d+)$/);\n            const size = match ? parseInt(match[1], 10) : undefined;\n            return { rangeSupported: true, size };\n        }\n\n        // 200 OK means server ignored Range header - not supported\n        // Other status codes also mean Range isn't working as expected\n        return { rangeSupported: false };\n    } catch {\n        // Network error or other failure - assume Range not supported\n        return { rangeSupported: false };\n    }\n};\n\n/**\n * ReadStream implementation for reading from fetch responses.\n */\nclass UrlReadStream extends ReadStream {\n    private reader: ReadableStreamDefaultReader<Uint8Array> | null = null;\n    private response: Response | null = null;\n    private buffer: Uint8Array | null = null;\n    private bufferOffset: number = 0;\n    private closed: boolean = false;\n    private progress: ProgressCallback | undefined;\n    private totalSize: number | undefined;\n\n    constructor(response: Response, expectedSize?: number, progress?: ProgressCallback) {\n        super(expectedSize);\n        this.response = response;\n        this.totalSize = expectedSize;\n        this.progress = progress;\n\n        if (response.body) {\n            this.reader = response.body.getReader();\n        }\n    }\n\n    async pull(target: Uint8Array): Promise<number> {\n        if (this.closed || !this.reader) {\n            return 0;\n        }\n\n        let targetOffset = 0;\n\n        // First, consume any leftover data from previous read\n        if (this.buffer && this.bufferOffset < this.buffer.length) {\n            const remaining = this.buffer.length - this.bufferOffset;\n            const toCopy = Math.min(remaining, target.length);\n            target.set(this.buffer.subarray(this.bufferOffset, this.bufferOffset + toCopy));\n            this.bufferOffset += toCopy;\n            targetOffset += toCopy;\n            this.bytesRead += toCopy;\n\n            // Report progress\n            if (this.progress) {\n                this.progress(this.bytesRead, this.totalSize);\n            }\n\n            // If we filled the target, return\n            if (targetOffset >= target.length) {\n                return targetOffset;\n            }\n\n            // Clear exhausted buffer\n            if (this.bufferOffset >= this.buffer.length) {\n                this.buffer = null;\n                this.bufferOffset = 0;\n            }\n        }\n\n        // Read from stream\n        while (targetOffset < target.length) {\n            const { done, value } = await this.reader.read();\n\n            if (done || !value) {\n                break;\n            }\n\n            const toCopy = Math.min(value.length, target.length - targetOffset);\n            target.set(value.subarray(0, toCopy), targetOffset);\n            targetOffset += toCopy;\n            this.bytesRead += toCopy;\n\n            // Report progress\n            if (this.progress) {\n                this.progress(this.bytesRead, this.totalSize);\n            }\n\n            // Store leftover for next pull\n            if (toCopy < value.length) {\n                this.buffer = value;\n                this.bufferOffset = toCopy;\n                break;\n            }\n        }\n\n        return targetOffset;\n    }\n\n    close(): void {\n        this.closed = true;\n        if (this.reader) {\n            this.reader.cancel();\n            this.reader = null;\n        }\n        this.response = null;\n        this.buffer = null;\n    }\n}\n\n/**\n * A ReadStream that lazily initiates the fetch on first pull.\n */\nclass LazyUrlReadStream extends ReadStream {\n    private url: string;\n    private headers: Record<string, string>;\n    private innerStream: UrlReadStream | null = null;\n    private fetchPromise: Promise<UrlReadStream> | null = null;\n    private closed: boolean = false;\n    private progress: ProgressCallback | undefined;\n\n    constructor(url: string, headers: Record<string, string>, expectedSize?: number, progress?: ProgressCallback) {\n        super(expectedSize);\n        this.url = url;\n        this.headers = headers;\n        this.progress = progress;\n    }\n\n    private async ensureStream(): Promise<UrlReadStream | null> {\n        if (this.closed) {\n            return null;\n        }\n\n        if (this.innerStream) {\n            return this.innerStream;\n        }\n\n        if (!this.fetchPromise) {\n            this.fetchPromise = (async () => {\n                const response = await fetch(this.url, { headers: this.headers });\n                if (!response.ok) {\n                    throw new Error(`HTTP error ${response.status}: ${response.statusText}`);\n                }\n                return new UrlReadStream(response, this.expectedSize, this.progress);\n            })();\n        }\n\n        this.innerStream = await this.fetchPromise;\n        return this.innerStream;\n    }\n\n    async pull(target: Uint8Array): Promise<number> {\n        const stream = await this.ensureStream();\n        if (!stream) {\n            return 0;\n        }\n\n        const result = await stream.pull(target);\n        this.bytesRead = stream.bytesRead;\n        return result;\n    }\n\n    close(): void {\n        this.closed = true;\n        if (this.innerStream) {\n            this.innerStream.close();\n            this.innerStream = null;\n        }\n    }\n}\n\n/**\n * ReadSource implementation for URLs using fetch with Range headers.\n * Size is from Content-Length (may be approximate for compressed responses).\n * Seekable via Range header requests.\n */\nclass UrlReadSource implements ReadSource {\n    readonly size: number | undefined;\n    readonly seekable: boolean = true;\n\n    private url: string;\n    private closed: boolean = false;\n    private progress: ProgressCallback | undefined;\n\n    constructor(url: string, size: number | undefined, progress?: ProgressCallback) {\n        this.url = url;\n        this.size = size;\n        this.progress = progress;\n    }\n\n    read(start?: number, end?: number): ReadStream {\n        if (this.closed) {\n            throw new Error('Source has been closed');\n        }\n\n        // Calculate expected size for this range\n        let expectedSize: number | undefined;\n        if (start !== undefined || end !== undefined) {\n            const rangeStart = start ?? 0;\n            const rangeEnd = end ?? this.size;\n            if (rangeEnd !== undefined) {\n                expectedSize = rangeEnd - rangeStart;\n            }\n        } else {\n            expectedSize = this.size;\n        }\n\n        // Create fetch promise with appropriate headers\n        const headers: Record<string, string> = {};\n        if (start !== undefined || end !== undefined) {\n            const rangeStart = start ?? 0;\n            const rangeEnd = end !== undefined ? end - 1 : ''; // HTTP Range is inclusive\n            headers.Range = `bytes=${rangeStart}-${rangeEnd}`;\n        }\n\n        // We need to return a ReadStream synchronously, so we create one that\n        // will fetch on first pull\n        return new LazyUrlReadStream(this.url, headers, expectedSize, this.progress);\n    }\n\n    close(): void {\n        this.closed = true;\n    }\n}\n\n/**\n * ReadFileSystem for reading from URLs using fetch.\n * Supports optional base URL for relative paths.\n *\n * Automatically detects whether the server supports Range requests.\n * If Range requests are supported, uses streaming with Range headers for efficient seeking.\n * If not supported (e.g., Python's SimpleHTTPRequestHandler), falls back to downloading\n * the entire file into memory first.\n */\nclass UrlReadFileSystem implements ReadFileSystem {\n    private baseUrl: string;\n\n    /**\n     * @param baseUrl - Optional base URL to prepend to filenames\n     */\n    constructor(baseUrl: string = '') {\n        this.baseUrl = baseUrl;\n    }\n\n    async createSource(filename: string, progress?: ProgressCallback): Promise<ReadSource> {\n        const url = this.baseUrl ? new URL(filename, this.baseUrl).href : filename;\n\n        // Probe to check if Range requests are supported\n        const { rangeSupported, size: probeSize } = await probeRangeSupport(url);\n\n        if (!rangeSupported) {\n            // Fall back to downloading the entire file into memory\n            return await this.createMemorySource(url, progress);\n        }\n\n        // Range is supported - use streaming approach\n        // If we got size from probe, use it; otherwise try HEAD request\n        let size = probeSize;\n        if (size === undefined) {\n            const headResponse = await fetch(url, { method: 'HEAD' });\n            if (headResponse.ok) {\n                const contentLength = headResponse.headers.get('Content-Length');\n                size = contentLength ? parseInt(contentLength, 10) : undefined;\n            }\n        }\n\n        // Report initial progress\n        if (progress) {\n            progress(0, size);\n        }\n\n        return new UrlReadSource(url, size, progress);\n    }\n\n    /**\n     * Download the entire file and create a memory-based source.\n     * Used as fallback when server doesn't support Range requests.\n     * @param url - The URL to download\n     * @param progress - Optional callback for progress reporting\n     * @returns Promise resolving to a memory-based ReadSource\n     */\n    private async createMemorySource(url: string, progress?: ProgressCallback): Promise<ReadSource> {\n        const response = await fetch(url);\n        if (!response.ok) {\n            throw new Error(`HTTP error ${response.status}: ${response.statusText}`);\n        }\n\n        // Get expected size for progress reporting\n        const contentLength = response.headers.get('Content-Length');\n        const expectedSize = contentLength ? parseInt(contentLength, 10) : undefined;\n\n        // Report initial progress\n        if (progress) {\n            progress(0, expectedSize);\n        }\n\n        // Read the response body with progress updates\n        if (response.body && progress) {\n            const reader = response.body.getReader();\n            const chunks: Uint8Array[] = [];\n            let loaded = 0;\n\n            while (true) {\n                const { done, value } = await reader.read();\n                if (done) break;\n                chunks.push(value);\n                loaded += value.length;\n                progress(loaded, expectedSize);\n            }\n\n            // Combine chunks into single buffer\n            const data = new Uint8Array(loaded);\n            let offset = 0;\n            for (const chunk of chunks) {\n                data.set(chunk, offset);\n                offset += chunk.length;\n            }\n\n            return new MemoryReadSource(data);\n        }\n\n        // No progress callback or no body - simple path\n        const buffer = await response.arrayBuffer();\n        if (progress) {\n            progress(buffer.byteLength, buffer.byteLength);\n        }\n        return new MemoryReadSource(buffer);\n    }\n}\n\nexport { UrlReadFileSystem };\n","import { type ReadFileSystem, type ProgressCallback, type ReadSource, ReadStream } from './file-system';\n\n/**\n * Metadata for a zip file entry.\n */\ntype ZipEntry = {\n    name: string;\n    compressedSize: number;\n    uncompressedSize: number;\n    offset: number;        // Local header offset\n    method: number;        // 0=store, 8=deflate\n};\n\n/**\n * ReadStream for reading stored (uncompressed) zip entries.\n */\nclass StoredEntryReadStream extends ReadStream {\n    private sourceStream: ReadStream;\n\n    constructor(sourceStream: ReadStream, expectedSize: number) {\n        super(expectedSize);\n        this.sourceStream = sourceStream;\n    }\n\n    async pull(target: Uint8Array): Promise<number> {\n        const n = await this.sourceStream.pull(target);\n        this.bytesRead += n;\n        return n;\n    }\n\n    close(): void {\n        this.sourceStream.close();\n    }\n}\n\n/**\n * ReadStream for reading deflated (compressed) zip entries.\n * Uses DecompressionStream for streaming decompression.\n */\nclass DeflateEntryReadStream extends ReadStream {\n    private sourceStream: ReadStream;\n    private reader: ReadableStreamDefaultReader<Uint8Array> | null = null;\n    private buffer: Uint8Array | null = null;\n    private bufferOffset: number = 0;\n    private closed: boolean = false;\n    private initialized: boolean = false;\n\n    constructor(sourceStream: ReadStream, expectedSize: number) {\n        super(expectedSize);\n        this.sourceStream = sourceStream;\n    }\n\n    private init(): void {\n        if (this.reader || this.closed) return;\n\n        // Create a ReadableStream from our source\n        const sourceStream = this.sourceStream;\n        const inputStream = new ReadableStream<Uint8Array>({\n            async pull(controller) {\n                const chunk = new Uint8Array(32768);\n                const n = await sourceStream.pull(chunk);\n                if (n === 0) {\n                    controller.close();\n                } else {\n                    controller.enqueue(chunk.subarray(0, n));\n                }\n            }\n        });\n\n        // Pipe through decompression\n        // Type assertion needed due to TypeScript's strict typing of DecompressionStream\n        const decompressedStream = inputStream.pipeThrough(\n            new DecompressionStream('deflate-raw') as unknown as TransformStream<Uint8Array, Uint8Array>\n        );\n\n        this.reader = decompressedStream.getReader();\n    }\n\n    async pull(target: Uint8Array): Promise<number> {\n        if (this.closed) return 0;\n\n        // Initialize on first pull\n        if (!this.initialized) {\n            this.init();\n            this.initialized = true;\n        }\n\n        if (!this.reader) return 0;\n\n        let targetOffset = 0;\n\n        // First, consume any leftover data from previous read\n        if (this.buffer && this.bufferOffset < this.buffer.length) {\n            const remaining = this.buffer.length - this.bufferOffset;\n            const toCopy = Math.min(remaining, target.length);\n            target.set(this.buffer.subarray(this.bufferOffset, this.bufferOffset + toCopy));\n            this.bufferOffset += toCopy;\n            targetOffset += toCopy;\n            this.bytesRead += toCopy;\n\n            if (targetOffset >= target.length) {\n                return targetOffset;\n            }\n\n            if (this.bufferOffset >= this.buffer.length) {\n                this.buffer = null;\n                this.bufferOffset = 0;\n            }\n        }\n\n        // Read from decompressed stream\n        while (targetOffset < target.length) {\n            const { done, value } = await this.reader.read();\n\n            if (done || !value) {\n                break;\n            }\n\n            const toCopy = Math.min(value.length, target.length - targetOffset);\n            target.set(value.subarray(0, toCopy), targetOffset);\n            targetOffset += toCopy;\n            this.bytesRead += toCopy;\n\n            // Store leftover for next pull\n            if (toCopy < value.length) {\n                this.buffer = value;\n                this.bufferOffset = toCopy;\n                break;\n            }\n        }\n\n        return targetOffset;\n    }\n\n    close(): void {\n        this.closed = true;\n        if (this.reader) {\n            this.reader.cancel();\n            this.reader = null;\n        }\n        this.sourceStream.close();\n    }\n}\n\n/**\n * ReadSource for a single zip entry.\n */\nclass ZipEntrySource implements ReadSource {\n    readonly size: number;\n    readonly seekable: boolean;\n\n    private source: ReadSource;\n    private entry: ZipEntry;\n    private dataOffset: number;\n    private closed: boolean = false;\n\n    constructor(source: ReadSource, entry: ZipEntry, dataOffset: number) {\n        this.source = source;\n        this.entry = entry;\n        this.dataOffset = dataOffset;\n        this.size = entry.uncompressedSize;\n        // Only stored entries support seeking\n        this.seekable = entry.method === 0;\n    }\n\n    read(start?: number, end?: number): ReadStream {\n        if (this.closed) {\n            throw new Error('Source has been closed');\n        }\n\n        if (this.entry.method === 0) {\n            // Stored (uncompressed) - direct range read\n            const rangeStart = start ?? 0;\n            const rangeEnd = end ?? this.entry.uncompressedSize;\n            const sourceStream = this.source.read(\n                this.dataOffset + rangeStart,\n                this.dataOffset + rangeEnd\n            );\n            return new StoredEntryReadStream(sourceStream, rangeEnd - rangeStart);\n        }\n\n        if (this.entry.method === 8) {\n            // Deflate - must read from start and decompress\n            if (start !== undefined && start !== 0) {\n                throw new Error('Range reads not supported on compressed zip entries');\n            }\n\n            const sourceStream = this.source.read(\n                this.dataOffset,\n                this.dataOffset + this.entry.compressedSize\n            );\n            return new DeflateEntryReadStream(sourceStream, this.entry.uncompressedSize);\n        }\n\n        throw new Error(`Unsupported compression method: ${this.entry.method}`);\n    }\n\n    close(): void {\n        this.closed = true;\n    }\n}\n\n/**\n * Virtual filesystem for reading files from a zip archive.\n * Wraps any ReadSource and provides memory-efficient streaming access.\n */\nclass ZipReadFileSystem implements ReadFileSystem {\n    private source: ReadSource;\n    private entries: Map<string, ZipEntry> | null = null;\n    private parsePromise: Promise<Map<string, ZipEntry>> | null = null;\n    private closed: boolean = false;\n\n    constructor(source: ReadSource) {\n        this.source = source;\n    }\n\n    /**\n     * Parse the central directory from the zip file.\n     * Called lazily on first createSource() or list() call.\n     * @returns Map of entry names to ZipEntry metadata\n     */\n    private async parseDirectory(): Promise<Map<string, ZipEntry>> {\n        if (this.entries) {\n            return this.entries;\n        }\n\n        const size = this.source.size;\n        if (size === undefined) {\n            throw new Error('Cannot read zip from source with unknown size');\n        }\n\n        // Read the last 65KB to find the End of Central Directory record\n        const eocdSearchSize = Math.min(65536 + 22, size);\n        const eocdStream = this.source.read(size - eocdSearchSize, size);\n        const eocdData = await eocdStream.readAll();\n        eocdStream.close();\n\n        // Find EOCD signature (0x06054b50)\n        let eocdOffset = -1;\n        for (let i = eocdData.length - 22; i >= 0; i--) {\n            if (eocdData[i] === 0x50 &&\n                eocdData[i + 1] === 0x4b &&\n                eocdData[i + 2] === 0x05 &&\n                eocdData[i + 3] === 0x06) {\n                eocdOffset = i;\n                break;\n            }\n        }\n\n        if (eocdOffset < 0) {\n            throw new Error('End of central directory not found - invalid zip file');\n        }\n\n        const eocdView = new DataView(eocdData.buffer, eocdData.byteOffset + eocdOffset, 22);\n        const entryCount = eocdView.getUint16(10, true);\n        const cdSize = eocdView.getUint32(12, true);\n        const cdOffset = eocdView.getUint32(16, true);\n\n        // Read central directory\n        const cdStream = this.source.read(cdOffset, cdOffset + cdSize);\n        const cdData = await cdStream.readAll();\n        cdStream.close();\n\n        const entries = new Map<string, ZipEntry>();\n        let offset = 0;\n\n        for (let i = 0; i < entryCount; i++) {\n            if (offset + 46 > cdData.length) {\n                throw new Error('Truncated central directory');\n            }\n\n            const cdView = new DataView(cdData.buffer, cdData.byteOffset + offset);\n            const sig = cdView.getUint32(0, true);\n\n            if (sig !== 0x02014b50) {\n                throw new Error('Invalid central directory entry signature');\n            }\n\n            const gpFlags = cdView.getUint16(8, true);\n            const method = cdView.getUint16(10, true);\n            const compressedSize = cdView.getUint32(20, true);\n            const uncompressedSize = cdView.getUint32(24, true);\n            const nameLen = cdView.getUint16(28, true);\n            const extraLen = cdView.getUint16(30, true);\n            const commentLen = cdView.getUint16(32, true);\n            const localHeaderOffset = cdView.getUint32(42, true);\n\n            const nameBytes = cdData.subarray(offset + 46, offset + 46 + nameLen);\n            const utf8 = (gpFlags & 0x800) !== 0;\n            const name = new TextDecoder(utf8 ? 'utf-8' : 'ascii').decode(nameBytes);\n\n            entries.set(name, {\n                name,\n                compressedSize,\n                uncompressedSize,\n                offset: localHeaderOffset,\n                method\n            });\n\n            offset += 46 + nameLen + extraLen + commentLen;\n        }\n\n        this.entries = entries;\n        return entries;\n    }\n\n    /**\n     * Get the data offset for an entry by reading its local header.\n     * @param entry - Zip entry metadata\n     * @returns Byte offset where entry data begins\n     */\n    private async getDataOffset(entry: ZipEntry): Promise<number> {\n        // Read local file header to get variable-length fields\n        const headerStream = this.source.read(entry.offset, entry.offset + 30);\n        const headerData = await headerStream.readAll();\n        headerStream.close();\n\n        const headerView = new DataView(headerData.buffer, headerData.byteOffset, 30);\n        const sig = headerView.getUint32(0, true);\n\n        if (sig !== 0x04034b50) {\n            throw new Error('Invalid local file header signature');\n        }\n\n        const nameLen = headerView.getUint16(26, true);\n        const extraLen = headerView.getUint16(28, true);\n\n        return entry.offset + 30 + nameLen + extraLen;\n    }\n\n    async createSource(filename: string, _progress?: ProgressCallback): Promise<ReadSource> {\n        if (this.closed) {\n            throw new Error('Source has been closed');\n        }\n\n        if (!this.parsePromise) {\n            this.parsePromise = this.parseDirectory();\n        }\n\n        const entries = await this.parsePromise;\n        const entry = entries.get(filename);\n\n        if (!entry) {\n            throw new Error(`Entry not found: ${filename}`);\n        }\n\n        const dataOffset = await this.getDataOffset(entry);\n        return new ZipEntrySource(this.source, entry, dataOffset);\n    }\n\n    /**\n     * List all entries in the zip file.\n     * @returns Array of entry names\n     */\n    async list(): Promise<string[]> {\n        if (this.closed) {\n            throw new Error('Source has been closed');\n        }\n\n        if (!this.parsePromise) {\n            this.parsePromise = this.parseDirectory();\n        }\n\n        const entries = await this.parsePromise;\n        return Array.from(entries.keys());\n    }\n\n    /**\n     * Get entry metadata.\n     * @param filename - Entry name\n     * @returns Entry metadata or undefined if not found\n     */\n    async getEntry(filename: string): Promise<ZipEntry | undefined> {\n        if (!this.parsePromise) {\n            this.parsePromise = this.parseDirectory();\n        }\n\n        const entries = await this.parsePromise;\n        return entries.get(filename);\n    }\n\n    /**\n     * Close the zip filesystem and underlying source.\n     */\n    close(): void {\n        this.closed = true;\n        this.source.close();\n    }\n}\n\nexport { ZipReadFileSystem, type ZipEntry };\n","import { Column, DataTable } from '../data-table';\nimport { ReadSource } from '../io/read';\nimport { logger, Transform } from '../utils';\n\nconst TICK_BATCH = 1 << 16;\n\n// Format configuration for different compression modes\ninterface CompressionConfig {\n    centerBytes: number;\n    scaleBytes: number;\n    rotationBytes: number;\n    colorBytes: number;\n    harmonicsBytes: number;\n    scaleStartByte: number;\n    rotationStartByte: number;\n    colorStartByte: number;\n    harmonicsStartByte: number;\n    scaleQuantRange: number;\n}\n\n// Half-precision floating point decoder\nfunction decodeFloat16(encoded: number): number {\n    const signBit = (encoded >> 15) & 1;\n    const exponent = (encoded >> 10) & 0x1f;\n    const mantissa = encoded & 0x3ff;\n\n    if (exponent === 0) {\n        if (mantissa === 0) {\n            return signBit ? -0.0 : 0.0;\n        }\n        // Denormalized number\n        let m = mantissa;\n        let exp = -14;\n        while (!(m & 0x400)) {\n            m <<= 1;\n            exp--;\n        }\n        m &= 0x3ff;\n        const finalExp = exp + 127;\n        const finalMantissa = m << 13;\n        const bits = (signBit << 31) | (finalExp << 23) | finalMantissa;\n        return new Float32Array(new Uint32Array([bits]).buffer)[0];\n    }\n\n    if (exponent === 0x1f) {\n        return mantissa === 0 ? (signBit ? -Infinity : Infinity) : NaN;\n    }\n\n    const finalExp = exponent - 15 + 127;\n    const finalMantissa = mantissa << 13;\n    const bits = (signBit << 31) | (finalExp << 23) | finalMantissa;\n    return new Float32Array(new Uint32Array([bits]).buffer)[0];\n}\n\nconst COMPRESSION_MODES: CompressionConfig[] = [\n    {\n        centerBytes: 12,\n        scaleBytes: 12,\n        rotationBytes: 16,\n        colorBytes: 4,\n        harmonicsBytes: 4,\n        scaleStartByte: 12,\n        rotationStartByte: 24,\n        colorStartByte: 40,\n        harmonicsStartByte: 44,\n        scaleQuantRange: 1\n    },\n    {\n        centerBytes: 6,\n        scaleBytes: 6,\n        rotationBytes: 8,\n        colorBytes: 4,\n        harmonicsBytes: 2,\n        scaleStartByte: 6,\n        rotationStartByte: 12,\n        colorStartByte: 20,\n        harmonicsStartByte: 24,\n        scaleQuantRange: 32767\n    },\n    {\n        centerBytes: 6,\n        scaleBytes: 6,\n        rotationBytes: 8,\n        colorBytes: 4,\n        harmonicsBytes: 1,\n        scaleStartByte: 6,\n        rotationStartByte: 12,\n        colorStartByte: 20,\n        harmonicsStartByte: 24,\n        scaleQuantRange: 32767\n    }\n];\n\nconst HARMONICS_COMPONENT_COUNT = [0, 9, 24, 45];\n\n/**\n * Reads a .ksplat file containing compressed Gaussian splat data.\n *\n * The .ksplat format (Kevin Kwok's format) uses spatial bucketing and\n * quantization to achieve high compression ratios while preserving quality.\n * Supports multiple compression modes and spherical harmonics bands.\n *\n * @param source - The read source providing access to the .ksplat file data.\n * @returns Promise resolving to a DataTable containing the splat data.\n * @ignore\n */\nconst readKsplat = async (source: ReadSource): Promise<DataTable> => {\n    // Load complete file\n    const fileBuffer = await source.read().readAll();\n    const totalSize = fileBuffer.length;\n\n    const MAIN_HEADER_SIZE = 4096;\n    const SECTION_HEADER_SIZE = 1024;\n\n    if (totalSize < MAIN_HEADER_SIZE) {\n        throw new Error('File too small to be valid .ksplat format');\n    }\n\n    // Parse main header\n    const mainHeader = new DataView(fileBuffer.buffer, fileBuffer.byteOffset, MAIN_HEADER_SIZE);\n\n    const majorVersion = mainHeader.getUint8(0);\n    const minorVersion = mainHeader.getUint8(1);\n    if (majorVersion !== 0 || minorVersion < 1) {\n        throw new Error(`Unsupported version ${majorVersion}.${minorVersion}`);\n    }\n\n    const maxSections = mainHeader.getUint32(4, true);\n    const numSplats = mainHeader.getUint32(16, true);\n    const compressionMode = mainHeader.getUint16(20, true);\n\n    if (compressionMode > 2) {\n        throw new Error(`Invalid compression mode: ${compressionMode}`);\n    }\n\n    const minHarmonicsValue = mainHeader.getFloat32(36, true) || -1.5;\n    const maxHarmonicsValue = mainHeader.getFloat32(40, true) || 1.5;\n\n    if (numSplats === 0) {\n        throw new Error('Invalid .ksplat file: file is empty');\n    }\n\n    // First pass: scan all sections to find maximum harmonics degree\n    let maxHarmonicsDegree = 0;\n    for (let sectionIdx = 0; sectionIdx < maxSections; sectionIdx++) {\n        const sectionHeaderOffset = MAIN_HEADER_SIZE + sectionIdx * SECTION_HEADER_SIZE;\n        const sectionHeader = new DataView(fileBuffer.buffer, fileBuffer.byteOffset + sectionHeaderOffset, SECTION_HEADER_SIZE);\n\n        const sectionSplatCount = sectionHeader.getUint32(0, true);\n        if (sectionSplatCount === 0) continue; // Skip empty sections\n\n        const harmonicsDegree = sectionHeader.getUint16(40, true);\n        maxHarmonicsDegree = Math.max(maxHarmonicsDegree, harmonicsDegree);\n    }\n\n    // Initialize data storage with base columns\n    const columns: Column[] = [\n        new Column('x', new Float32Array(numSplats)),\n        new Column('y', new Float32Array(numSplats)),\n        new Column('z', new Float32Array(numSplats)),\n        new Column('scale_0', new Float32Array(numSplats)),\n        new Column('scale_1', new Float32Array(numSplats)),\n        new Column('scale_2', new Float32Array(numSplats)),\n        new Column('f_dc_0', new Float32Array(numSplats)),\n        new Column('f_dc_1', new Float32Array(numSplats)),\n        new Column('f_dc_2', new Float32Array(numSplats)),\n        new Column('opacity', new Float32Array(numSplats)),\n        new Column('rot_0', new Float32Array(numSplats)),\n        new Column('rot_1', new Float32Array(numSplats)),\n        new Column('rot_2', new Float32Array(numSplats)),\n        new Column('rot_3', new Float32Array(numSplats))\n    ];\n\n    // Add spherical harmonics columns based on maximum degree found\n    const maxHarmonicsComponentCount = HARMONICS_COMPONENT_COUNT[maxHarmonicsDegree];\n    for (let i = 0; i < maxHarmonicsComponentCount; i++) {\n        columns.push(new Column(`f_rest_${i}`, new Float32Array(numSplats)));\n    }\n\n    const {\n        centerBytes,\n        scaleBytes,\n        rotationBytes,\n        colorBytes,\n        harmonicsBytes,\n        scaleStartByte,\n        rotationStartByte,\n        colorStartByte,\n        harmonicsStartByte,\n        scaleQuantRange\n    } = COMPRESSION_MODES[compressionMode];\n\n    const bar = logger.bar('decoding', numSplats);\n\n    let currentSectionDataOffset = MAIN_HEADER_SIZE + maxSections * SECTION_HEADER_SIZE;\n    let splatIndex = 0;\n\n    // Process each section\n    for (let sectionIdx = 0; sectionIdx < maxSections; sectionIdx++) {\n        const sectionHeaderOffset = MAIN_HEADER_SIZE + sectionIdx * SECTION_HEADER_SIZE;\n        const sectionHeader = new DataView(fileBuffer.buffer, fileBuffer.byteOffset + sectionHeaderOffset, SECTION_HEADER_SIZE);\n\n        const sectionSplatCount = sectionHeader.getUint32(0, true);\n        const maxSectionSplats = sectionHeader.getUint32(4, true);\n        const bucketCapacity = sectionHeader.getUint32(8, true);\n        const bucketCount = sectionHeader.getUint32(12, true);\n        const spatialBlockSize = sectionHeader.getFloat32(16, true);\n        const bucketStorageSize = sectionHeader.getUint16(20, true);\n        const quantizationRange = sectionHeader.getUint32(24, true) || scaleQuantRange;\n        const fullBuckets = sectionHeader.getUint32(32, true);\n        const partialBuckets = sectionHeader.getUint32(36, true);\n        const harmonicsDegree = sectionHeader.getUint16(40, true);\n\n        // Calculate layout\n        const fullBucketSplats = fullBuckets * bucketCapacity;\n        const partialBucketMetaSize = partialBuckets * 4;\n        const totalBucketStorageSize = bucketStorageSize * bucketCount + partialBucketMetaSize;\n        const harmonicsComponentCount = HARMONICS_COMPONENT_COUNT[harmonicsDegree];\n        const bytesPerSplat = centerBytes + scaleBytes + rotationBytes +\n                             colorBytes + harmonicsComponentCount * harmonicsBytes;\n        const sectionDataSize = bytesPerSplat * maxSectionSplats;\n\n        // Calculate decompression parameters\n        const positionScale = spatialBlockSize / 2.0 / quantizationRange;\n\n        // Get bucket centers\n        const bucketCentersOffset = currentSectionDataOffset + partialBucketMetaSize;\n        const bucketCenters = new Float32Array(fileBuffer.buffer, fileBuffer.byteOffset + bucketCentersOffset, bucketCount * 3);\n\n        // Get partial bucket sizes\n        const partialBucketSizes = new Uint32Array(fileBuffer.buffer, fileBuffer.byteOffset + currentSectionDataOffset, partialBuckets);\n\n        // Get splat data\n        const splatDataOffset = currentSectionDataOffset + totalBucketStorageSize;\n        const splatData = new DataView(fileBuffer.buffer, fileBuffer.byteOffset + splatDataOffset, sectionDataSize);\n\n        // Harmonic value decoder\n        const decodeHarmonics = (offset: number, component: number): number => {\n            switch (compressionMode) {\n                case 0:\n                    return splatData.getFloat32(offset + harmonicsStartByte + component * 4, true);\n                case 1:\n                    return decodeFloat16(splatData.getUint16(offset + harmonicsStartByte + component * 2, true));\n                case 2: {\n                    const normalized = splatData.getUint8(offset + harmonicsStartByte + component) / 255;\n                    return minHarmonicsValue + normalized * (maxHarmonicsValue - minHarmonicsValue);\n                }\n                default:\n                    return 0;\n            }\n        };\n\n        // Track partial bucket processing\n        let currentPartialBucket = fullBuckets;\n        let currentPartialBase = fullBucketSplats;\n\n        // Process splats in this section\n        for (let splatIdx = 0; splatIdx < sectionSplatCount; splatIdx++) {\n            const splatByteOffset = splatIdx * bytesPerSplat;\n\n            // Determine which bucket this splat belongs to\n            let bucketIdx: number;\n            if (splatIdx < fullBucketSplats) {\n                bucketIdx = Math.floor(splatIdx / bucketCapacity);\n            } else {\n                const currentBucketSize = partialBucketSizes[currentPartialBucket - fullBuckets];\n                if (splatIdx >= currentPartialBase + currentBucketSize) {\n                    currentPartialBucket++;\n                    currentPartialBase += currentBucketSize;\n                }\n                bucketIdx = currentPartialBucket;\n            }\n\n            // Decode position\n            let x: number, y: number, z: number;\n            if (compressionMode === 0) {\n                x = splatData.getFloat32(splatByteOffset, true);\n                y = splatData.getFloat32(splatByteOffset + 4, true);\n                z = splatData.getFloat32(splatByteOffset + 8, true);\n            } else {\n                x = (splatData.getUint16(splatByteOffset, true) - quantizationRange) * positionScale + bucketCenters[bucketIdx * 3];\n                y = (splatData.getUint16(splatByteOffset + 2, true) - quantizationRange) * positionScale + bucketCenters[bucketIdx * 3 + 1];\n                z = (splatData.getUint16(splatByteOffset + 4, true) - quantizationRange) * positionScale + bucketCenters[bucketIdx * 3 + 2];\n            }\n\n            // Decode scales\n            let scaleX: number, scaleY: number, scaleZ: number;\n            if (compressionMode === 0) {\n                scaleX = splatData.getFloat32(splatByteOffset + scaleStartByte, true);\n                scaleY = splatData.getFloat32(splatByteOffset + scaleStartByte + 4, true);\n                scaleZ = splatData.getFloat32(splatByteOffset + scaleStartByte + 8, true);\n            } else {\n                scaleX = decodeFloat16(splatData.getUint16(splatByteOffset + scaleStartByte, true));\n                scaleY = decodeFloat16(splatData.getUint16(splatByteOffset + scaleStartByte + 2, true));\n                scaleZ = decodeFloat16(splatData.getUint16(splatByteOffset + scaleStartByte + 4, true));\n            }\n\n            // Decode rotation quaternion\n            let rot0: number, rot1: number, rot2: number, rot3: number;\n            if (compressionMode === 0) {\n                rot0 = splatData.getFloat32(splatByteOffset + rotationStartByte, true);\n                rot1 = splatData.getFloat32(splatByteOffset + rotationStartByte + 4, true);\n                rot2 = splatData.getFloat32(splatByteOffset + rotationStartByte + 8, true);\n                rot3 = splatData.getFloat32(splatByteOffset + rotationStartByte + 12, true);\n            } else {\n                rot0 = decodeFloat16(splatData.getUint16(splatByteOffset + rotationStartByte, true));\n                rot1 = decodeFloat16(splatData.getUint16(splatByteOffset + rotationStartByte + 2, true));\n                rot2 = decodeFloat16(splatData.getUint16(splatByteOffset + rotationStartByte + 4, true));\n                rot3 = decodeFloat16(splatData.getUint16(splatByteOffset + rotationStartByte + 6, true));\n            }\n\n            // Decode color and opacity\n            const red = splatData.getUint8(splatByteOffset + colorStartByte);\n            const green = splatData.getUint8(splatByteOffset + colorStartByte + 1);\n            const blue = splatData.getUint8(splatByteOffset + colorStartByte + 2);\n            const opacity = splatData.getUint8(splatByteOffset + colorStartByte + 3);\n\n            // Store position\n            (columns[0].data as Float32Array)[splatIndex] = x;\n            (columns[1].data as Float32Array)[splatIndex] = y;\n            (columns[2].data as Float32Array)[splatIndex] = z;\n\n            // Store scale (convert from linear in .ksplat to log scale for internal use)\n            (columns[3].data as Float32Array)[splatIndex] = scaleX > 0 ? Math.log(scaleX) : -10;\n            (columns[4].data as Float32Array)[splatIndex] = scaleY > 0 ? Math.log(scaleY) : -10;\n            (columns[5].data as Float32Array)[splatIndex] = scaleZ > 0 ? Math.log(scaleZ) : -10;\n\n            // Store color (convert from uint8 back to spherical harmonics)\n            const SH_C0 = 0.28209479177387814;\n            (columns[6].data as Float32Array)[splatIndex] = (red / 255.0 - 0.5) / SH_C0;\n            (columns[7].data as Float32Array)[splatIndex] = (green / 255.0 - 0.5) / SH_C0;\n            (columns[8].data as Float32Array)[splatIndex] = (blue / 255.0 - 0.5) / SH_C0;\n\n            // Store opacity (convert from uint8 to float and apply inverse sigmoid)\n            const epsilon = 1e-6;\n            const normalizedOpacity = Math.max(epsilon, Math.min(1.0 - epsilon, opacity / 255.0));\n            (columns[9].data as Float32Array)[splatIndex] = Math.log(normalizedOpacity / (1.0 - normalizedOpacity));\n\n            // Store quaternion\n            (columns[10].data as Float32Array)[splatIndex] = rot0;\n            (columns[11].data as Float32Array)[splatIndex] = rot1;\n            (columns[12].data as Float32Array)[splatIndex] = rot2;\n            (columns[13].data as Float32Array)[splatIndex] = rot3;\n\n            // Store spherical harmonics\n            for (let i = 0; i < harmonicsComponentCount; i++) {\n                let channel;\n                let coeff;\n\n                // band 0 is packed together, then band 1, then band 2.\n                if (i < 9) {\n                    channel = Math.floor(i / 3);\n                    coeff = i % 3;\n                } else if (i < 24) {\n                    channel = Math.floor((i - 9) / 5);\n                    coeff = (i - 9) % 5 + 3;\n                } else {\n                    // don't think 3 bands are supported, but here just in case\n                    channel = Math.floor((i - 24) / 7);\n                    coeff = (i - 24) % 7 + 8;\n                }\n\n                const col = channel * (harmonicsComponentCount / 3) + coeff;\n\n                (columns[14 + col].data as Float32Array)[splatIndex] = decodeHarmonics(splatByteOffset, i);\n            }\n\n            splatIndex++;\n\n            if ((splatIndex & (TICK_BATCH - 1)) === 0) {\n                bar.update(splatIndex);\n            }\n        }\n\n        currentSectionDataOffset += sectionDataSize + totalBucketStorageSize;\n    }\n\n    if (splatIndex !== numSplats) {\n        throw new Error(`Splat count mismatch: expected ${numSplats}, processed ${splatIndex}`);\n    }\n\n    bar.update(numSplats);\n    bar.end();\n\n    return new DataTable(columns, Transform.PLY);\n};\n\nexport { readKsplat };\n","import { Vec3 } from 'playcanvas';\n\nimport { Column, DataTable } from '../data-table';\nimport { dirname, join, ReadFileSystem, ReadSource, readFile } from '../io/read';\nimport { Options } from '../types';\nimport { logger, Transform } from '../utils';\n\nconst kSH_C0 = 0.28209479177387814;\nconst SQRT_2 = 1.414213562373095;\nconst SQRT_2_INV = 0.7071067811865475;\n\nconst IO_CONCURRENCY = 16;\n\n// lod data in data.bin\ntype LccLod = {\n    points: number;     // number of splats\n    offset: bigint;     // offset\n    size: number;       // data size\n}\n\n// The scene uses a quadtree for spatial partitioning,\n// with each unit having its own xy index (starting from 0) and multiple layers of lod data\ntype LccUnitInfo = {\n    x: number;          // x index\n    y: number;          // y index\n    lods: Array<LccLod>;    //  lods\n}\n\n// Used to decompress scale in data.bin and sh in shcoef.bin\ntype CompressInfo = {\n    scaleMin: Vec3;         // min scale\n    scaleMax: Vec3;         // max scale\n    shMin: Vec3;            // min sh\n    shMax: Vec3;            // max sh\n    envScaleMin: Vec3;      // min environment scale\n    envScaleMax: Vec3;      // max environment scale\n    envShMin: Vec3;         // min environment sh\n    envShMax: Vec3;         // max environment sh\n}\n\n// parse .lcc files, such as meta.lcc\nconst parseMeta = (obj: any): CompressInfo => {\n    const attributes: { [key: string]: any } = {};\n    obj.attributes.forEach((attr: any) => {\n        attributes[attr.name] = attr;\n    });\n\n    const scaleMin = new Vec3(attributes.scale.min);\n    const scaleMax = new Vec3(attributes.scale.max);\n    const shMin = new Vec3(attributes.shcoef.min);\n    const shMax = new Vec3(attributes.shcoef.max);\n    const envScaleMin = new Vec3(attributes.envscale?.min ?? attributes.scale.min);\n    const envScaleMax = new Vec3(attributes.envscale?.max ?? attributes.scale.max);\n    const envShMin = new Vec3(attributes.envshcoef?.min ?? attributes.shcoef.min);\n    const envShMax = new Vec3(attributes.envshcoef?.max ?? attributes.shcoef.max);\n\n    return { scaleMin, scaleMax, shMin, shMax, envScaleMin, envScaleMax, envShMin, envShMax };\n};\n\nconst parseIndexBin = (raw: ArrayBuffer, meta: any): Array<LccUnitInfo> => {\n    let offset = 0;\n\n    const buff = new DataView(raw);\n    const infos: Array<LccUnitInfo> = [];\n    while (true) {\n        if (offset > buff.byteLength - 1) {\n            break;\n        }\n\n        const x = buff.getInt16(offset, true);\n        offset += 2;\n        const y = buff.getInt16(offset, true);\n        offset += 2;\n\n        const lods: Array<LccLod> = [];\n        for (let i = 0; i < meta.totalLevel; i++) {\n            const ldPoints = buff.getInt32(offset, true);\n            offset += 4;\n\n            const ldOffset = buff.getBigInt64(offset, true);\n            offset += 8;\n\n            const ldSize = buff.getInt32(offset, true);\n            offset += 4;\n\n            lods.push({\n                points: ldPoints,\n                offset: ldOffset,\n                size: ldSize\n            });\n\n        }\n        const info: LccUnitInfo = {\n            x,\n            y,\n            lods\n        };\n\n        infos.push(info);\n    }\n\n    return infos;\n};\n\nconst invSigmoid = (v: number): number => {\n    return -Math.log((1.0 - v) / v);\n};\n\nconst invSH0ToColor = (v: number): number => {\n    return (v - 0.5) / kSH_C0;\n};\n\nconst invLinearScale = (v: number): number => {\n    return Math.log(v);\n};\n\nconst mix = (min: number, max: number, s: number): number => {\n    return (1.0 - s) * min + s * max;\n};\n\nconst floatProps = [\n    'x', 'y', 'z',\n    'nx', 'ny', 'nz',\n    'opacity',\n    'rot_0', 'rot_1', 'rot_2', 'rot_3',\n    'f_dc_0', 'f_dc_1', 'f_dc_2',\n    'scale_0', 'scale_1', 'scale_2'\n];\n\nconst initProperties = (length: number): Record<string, Float32Array> => {\n    const props: Record<string, Float32Array> = {};\n    for (const key of floatProps) {\n        props[`property_${key}`] = new Float32Array(length);\n    }\n    return props;\n};\n\n// Decode rotation quaternion and write directly to output arrays.\n// The encoded value packs 3 quaternion components at 10 bits each, plus a 2-bit index\n// indicating which component was omitted (the largest, which is reconstructed).\nconst decodeRotationInto = (\n    v: number,\n    rot0: Float32Array, rot1: Float32Array, rot2: Float32Array, rot3: Float32Array,\n    idx: number\n) => {\n    const d0 = (v & 1023) / 1023.0;\n    const d1 = ((v >> 10) & 1023) / 1023.0;\n    const d2 = ((v >> 20) & 1023) / 1023.0;\n    const d3 = (v >> 30) & 3;\n\n    const qx = d0 * SQRT_2 - SQRT_2_INV;\n    const qy = d1 * SQRT_2 - SQRT_2_INV;\n    const qz = d2 * SQRT_2 - SQRT_2_INV;\n    const qw = Math.sqrt(1 - Math.min(1.0, qx * qx + qy * qy + qz * qz));\n\n    // Reconstruct full quaternion with qw inserted at position d3.\n    // Output mapping matches original: rot_0 = q[3], rot_1 = q[0], rot_2 = q[1], rot_3 = q[2]\n    if (d3 === 0) {\n        rot0[idx] = qz; rot1[idx] = qw; rot2[idx] = qx; rot3[idx] = qy;\n    } else if (d3 === 1) {\n        rot0[idx] = qz; rot1[idx] = qx; rot2[idx] = qw; rot3[idx] = qy;\n    } else if (d3 === 2) {\n        rot0[idx] = qz; rot1[idx] = qx; rot2[idx] = qy; rot3[idx] = qw;\n    } else {\n        rot0[idx] = qw; rot1[idx] = qx; rot2[idx] = qy; rot3[idx] = qz;\n    }\n};\n\n// Decode a unit's splat data and write directly into the global output arrays at propertyOffset.\n// Uses typed array views instead of DataView for faster element access (assumes LE host).\nconst processUnit = async (\n    info: LccUnitInfo,\n    targetLod: number,\n    dataSource: ReadSource,\n    shSource: ReadSource | undefined,\n    compressInfo: CompressInfo,\n    propertyOffset: number,\n    properties: Record<string, Float32Array>,\n    properties_f_rest: Float32Array[] | null,\n    onUnitDone: () => void\n) => {\n    const lod = info.lods[targetLod];\n    const unitSplats = lod.points;\n    if (unitSplats === 0) {\n        onUnitDone();\n        return;\n    }\n\n    const offset = Number(lod.offset);\n    const size = lod.size;\n\n    // load data using range read\n    const dataBytes = await dataSource.read(offset, offset + size).readAll();\n    const expectedDataSize = unitSplats * 32;\n    if (dataBytes.byteLength < expectedDataSize) {\n        throw new Error(`LCC unit data too short: expected ${expectedDataSize} bytes for ${unitSplats} splats, got ${dataBytes.byteLength}`);\n    }\n\n    // Typed array views over the same buffer -- avoids DataView overhead.\n    // 32-byte record: [f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, u8 opacity,\n    //                  u16 s0, u16 s1, u16 s2, u16 rot_lo, u16 rot_hi, u16 nx, u16 ny, u16 nz]\n    const f32 = new Float32Array(dataBytes.buffer, dataBytes.byteOffset, dataBytes.byteLength >> 2);\n    const u16 = new Uint16Array(dataBytes.buffer, dataBytes.byteOffset, dataBytes.byteLength >> 1);\n    const u8 = dataBytes;\n\n    // load sh data using range read\n    let shU32: Uint32Array | null = null;\n    if (shSource) {\n        const shBytes = await shSource.read(offset * 2, offset * 2 + size * 2).readAll();\n        const expectedShSize = unitSplats * 64;\n        if (shBytes.byteLength < expectedShSize) {\n            throw new Error(`LCC unit SH data too short: expected ${expectedShSize} bytes for ${unitSplats} splats, got ${shBytes.byteLength}`);\n        }\n        shU32 = new Uint32Array(shBytes.buffer, shBytes.byteOffset, shBytes.byteLength >> 2);\n    }\n\n    // Extract array references once to avoid repeated property lookups in the hot loop\n    const px = properties.property_x;\n    const py = properties.property_y;\n    const pz = properties.property_z;\n    const pnx = properties.property_nx;\n    const pny = properties.property_ny;\n    const pnz = properties.property_nz;\n    const pop = properties.property_opacity;\n    const pr0 = properties.property_rot_0;\n    const pr1 = properties.property_rot_1;\n    const pr2 = properties.property_rot_2;\n    const pr3 = properties.property_rot_3;\n    const pdc0 = properties.property_f_dc_0;\n    const pdc1 = properties.property_f_dc_1;\n    const pdc2 = properties.property_f_dc_2;\n    const ps0 = properties.property_scale_0;\n    const ps1 = properties.property_scale_1;\n    const ps2 = properties.property_scale_2;\n\n    const sMinX = compressInfo.scaleMin.x, sMinY = compressInfo.scaleMin.y, sMinZ = compressInfo.scaleMin.z;\n    const sMaxX = compressInfo.scaleMax.x, sMaxY = compressInfo.scaleMax.y, sMaxZ = compressInfo.scaleMax.z;\n    const shMinX = compressInfo.shMin.x, shMinY = compressInfo.shMin.y, shMinZ = compressInfo.shMin.z;\n    const shMaxX = compressInfo.shMax.x, shMaxY = compressInfo.shMax.y, shMaxZ = compressInfo.shMax.z;\n\n    for (let i = 0; i < unitSplats; i++) {\n        const g = propertyOffset + i;\n\n        // position: 3 x float32 at byte offsets 0, 4, 8 → f32 indices i*8+{0,1,2}\n        const fi = i << 3;\n        px[g] = f32[fi];\n        py[g] = f32[fi + 1];\n        pz[g] = f32[fi + 2];\n\n        // color + opacity: 4 x uint8 at byte offsets 12..15\n        const bi = i << 5;\n        pdc0[g] = invSH0ToColor(u8[bi + 12] / 255.0);\n        pdc1[g] = invSH0ToColor(u8[bi + 13] / 255.0);\n        pdc2[g] = invSH0ToColor(u8[bi + 14] / 255.0);\n        pop[g] = invSigmoid(u8[bi + 15] / 255.0);\n\n        // scale + rotation + normals: uint16 at byte offsets 16..31 → u16 indices i*16+{8..15}\n        const hi = i << 4;\n        ps0[g] = invLinearScale(mix(sMinX, sMaxX, u16[hi + 8] / 65535.0));\n        ps1[g] = invLinearScale(mix(sMinY, sMaxY, u16[hi + 9] / 65535.0));\n        ps2[g] = invLinearScale(mix(sMinZ, sMaxZ, u16[hi + 10] / 65535.0));\n\n        // rotation: uint32 at byte offset 22 (not 4-byte aligned), reconstruct from two uint16s\n        decodeRotationInto(u16[hi + 11] | (u16[hi + 12] << 16), pr0, pr1, pr2, pr3, g);\n\n        pnx[g] = u16[hi + 13];\n        pny[g] = u16[hi + 14];\n        pnz[g] = u16[hi + 15];\n\n        // SH coefficients: 15 x uint32 per splat, 64-byte stride (16 uint32s)\n        if (shU32 && properties_f_rest) {\n            const si = i << 4;\n            for (let j = 0; j < 15; j++) {\n                const enc = shU32[si + j];\n                properties_f_rest[j][g] = mix(shMinX, shMaxX, (enc & 0x7FF) / 2047.0);\n                properties_f_rest[j + 15][g] = mix(shMinY, shMaxY, ((enc >> 11) & 0x3FF) / 1023.0);\n                properties_f_rest[j + 30][g] = mix(shMinZ, shMaxZ, ((enc >> 21) & 0x7FF) / 2047.0);\n            }\n        }\n    }\n\n    onUnitDone();\n};\n\n// Decode all units for a given LOD into shared global arrays with bounded concurrency.\nconst decodeUnitsForLod = async (\n    unitInfos: LccUnitInfo[],\n    targetLod: number,\n    dataSource: ReadSource,\n    shSource: ReadSource | undefined,\n    compressInfo: CompressInfo,\n    lodOffset: number,\n    properties: Record<string, Float32Array>,\n    properties_f_rest: Float32Array[] | null,\n    onUnitDone: () => void\n) => {\n    // Pre-compute write offsets so units can be processed concurrently without data races\n    const offsets = new Array<number>(unitInfos.length);\n    let unitOffset = lodOffset;\n    for (let i = 0; i < unitInfos.length; i++) {\n        offsets[i] = unitOffset;\n        unitOffset += unitInfos[i].lods[targetLod].points;\n    }\n\n    let nextUnit = 0;\n    const worker = async () => {\n        while (true) {\n            const idx = nextUnit++;\n            if (idx >= unitInfos.length) break;\n            await processUnit(\n                unitInfos[idx], targetLod, dataSource, shSource,\n                compressInfo, offsets[idx], properties, properties_f_rest,\n                onUnitDone\n            );\n        }\n    };\n    await Promise.all(\n        Array.from({ length: Math.min(IO_CONCURRENCY, unitInfos.length) }, () => worker())\n    );\n};\n\nconst deserializeEnvironment = (raw: Uint8Array, compressInfo: CompressInfo, hasSH: boolean) => {\n    const stride = hasSH ? 96 : 32;\n\n    const numGaussians = raw.length / stride;\n\n    if (!Number.isInteger(numGaussians)) {\n        throw new Error('Invalid environment data size');\n    }\n\n    const columns = [\n        'x', 'y', 'z',\n        'f_dc_0', 'f_dc_1', 'f_dc_2', 'opacity',\n        'scale_0', 'scale_1', 'scale_2',\n        'rot_0', 'rot_1', 'rot_2', 'rot_3'\n    ].concat(hasSH ? new Array(45).fill('').map((_, i) => `f_rest_${i}`) : []).map(name => new Column(name, new Float32Array(numGaussians)));\n\n    const scaleMin = compressInfo.envScaleMin;\n    const scaleMax = compressInfo.envScaleMax;\n    const shMin = compressInfo.envShMin;\n    const shMax = compressInfo.envShMax;\n\n    const rot0 = columns[10].data as Float32Array;\n    const rot1 = columns[11].data as Float32Array;\n    const rot2 = columns[12].data as Float32Array;\n    const rot3 = columns[13].data as Float32Array;\n\n    // fill data\n    const dataView = new DataView(raw.buffer, raw.byteOffset, raw.byteLength);\n    for (let i = 0; i < numGaussians; i++) {\n        const off = i * stride;\n\n        columns[0].data[i] = dataView.getFloat32(off + 0, true);   // x\n        columns[1].data[i] = dataView.getFloat32(off + 4, true);   // y\n        columns[2].data[i] = dataView.getFloat32(off + 8, true);   // z\n\n        columns[3].data[i] = invSH0ToColor(dataView.getUint8(off + 12) / 255.0);   // f_dc_0\n        columns[4].data[i] = invSH0ToColor(dataView.getUint8(off + 13) / 255.0);   // f_dc_1\n        columns[5].data[i] = invSH0ToColor(dataView.getUint8(off + 14) / 255.0);   // f_dc_2\n        columns[6].data[i] = invSigmoid(dataView.getUint8(off + 15) / 255.0);      // opacity\n\n        columns[7].data[i] = invLinearScale(mix(scaleMin.x, scaleMax.x, dataView.getUint16(off + 16, true) / 65535.0)); // scale_0\n        columns[8].data[i] = invLinearScale(mix(scaleMin.y, scaleMax.y, dataView.getUint16(off + 18, true) / 65535.0)); // scale_1\n        columns[9].data[i] = invLinearScale(mix(scaleMin.z, scaleMax.z, dataView.getUint16(off + 20, true) / 65535.0)); // scale_2\n\n        decodeRotationInto(dataView.getUint32(off + 22, true), rot0, rot1, rot2, rot3, i);\n\n        // skip normal 26-32\n\n        if (hasSH) {\n            for (let j = 0; j < 15; ++j) {\n                const enc = dataView.getUint32(off + 32 + j * 4, true);\n                const nx = (enc & 0x7FF) / 2047.0;\n                const ny = ((enc >> 11) & 0x3FF) / 1023.0;\n                const nz = ((enc >> 21) & 0x7FF) / 2047.0;\n                columns[14 + j].data[i] = mix(shMin.x, shMax.x, nx);\n                columns[14 + j + 15].data[i] = mix(shMin.y, shMax.y, ny);\n                columns[14 + j + 30].data[i] = mix(shMin.z, shMax.z, nz);\n            }\n        }\n    }\n\n    return new DataTable(columns);\n};\n\n/**\n * Reads an XGrids LCC format containing multi-LOD Gaussian splat data.\n *\n * The LCC format uses a quadtree spatial structure with multiple LOD levels.\n * Each LOD level is stored separately in data.bin with optional spherical\n * harmonics in shcoef.bin. Environment splats are stored in environment.bin.\n *\n * All selected LODs are decoded directly into a single pre-allocated DataTable\n * to avoid a costly post-read combine step.\n *\n * @param fileSystem - File system for reading the LCC files.\n * @param filename - Path to the meta.lcc file.\n * @param options - Options including LOD selection via `lodSelect`.\n * @returns Promise resolving to an array of DataTables (combined LODs + environment).\n * @ignore\n */\nconst readLcc = async (fileSystem: ReadFileSystem, filename: string, options: Options): Promise<DataTable[]> => {\n    const lccData = await readFile(fileSystem, filename);\n    const lccText = new TextDecoder().decode(lccData);\n    const lccJson = JSON.parse(lccText);\n\n    const determineSH = () => {\n        if (lccJson.fileType === 'Portable') {\n            return false;\n        }\n\n        if (lccJson.fileType === 'Quality') {\n            return true;\n        }\n\n        // before version 4 sh seems to have always been present, but we test for shcoef attribute anyway\n        return lccJson.attributes.findIndex((attr: any) => attr.name === 'shcoef') !== -1;\n    };\n\n    // FIXME: it seems some meta.lcc files at https://developer.xgrids.com/#/download?page=sampledata do not have\n    // 'fileType' field, but do appear to contain spherical harmonics data. So for now assume presence of SH when\n    // the field is missing.\n    // See https://github.com/xgrids/LCCWhitepaper/issues/3\n    const hasSH = determineSH();\n    const compressInfo = parseMeta(lccJson);\n    const splats = lccJson.splats;\n\n    const baseDir = dirname(filename);\n    const relatedFilename = (name: string) => (baseDir ? join(baseDir, name) : name);\n\n    const indexData = await readFile(fileSystem, relatedFilename('index.bin'));\n\n    const openSource = (name: string): Promise<ReadSource> => {\n        return fileSystem.createSource(relatedFilename(name));\n    };\n\n    let dataSource: ReadSource | null = null;\n    let shSource: ReadSource | null = null;\n    let mainTable: DataTable;\n\n    try {\n        // Open sequentially so a failure on the second open doesn't leak the\n        // first source. (The actual bulk reads still happen in parallel below\n        // via decodeUnitsForLod's IO_CONCURRENCY workers.)\n        dataSource = await openSource('data.bin');\n        if (hasSH) shSource = await openSource('shcoef.bin');\n\n        const unitInfos: LccUnitInfo[] = parseIndexBin(indexData.buffer.slice(indexData.byteOffset, indexData.byteOffset + indexData.byteLength) as ArrayBuffer, lccJson);\n\n        // build table of input -> output lods\n        const lods = options.lodSelect.length > 0 ?\n            options.lodSelect\n            .map(lod => (lod < 0 ? splats.length + lod : lod))    // negative indices map from the end of lod\n            .filter(lod => lod >= 0 && lod < splats.length) :\n            new Array(splats.length).fill(0).map((_, i) => i);\n\n        if (lods.length === 0) {\n            throw new Error(`No valid LODs selected for LCC input file: ${filename} lods: ${JSON.stringify(lods)}`);\n        }\n\n        // Pre-allocate a single set of arrays for all LODs combined\n        const grandTotal = lods.reduce((sum, lodIdx) => sum + splats[lodIdx], 0);\n        const properties: Record<string, Float32Array> = initProperties(grandTotal);\n        const properties_f_rest = shSource ? Array.from({ length: 45 }, () => new Float32Array(grandTotal)) : null;\n        const lodColumn = new Float32Array(grandTotal);\n\n        // One bar across all LOD passes: total = (units per LOD) * (LOD count).\n        // Bounded concurrency means ticks come in bursts; that's fine for the\n        // bar's monotonic update().\n        const totalUnits = unitInfos.length * lods.length;\n        const bar = logger.bar('decoding', totalUnits);\n        let unitsDone = 0;\n        const tick = () => {\n            bar.update(++unitsDone);\n        };\n\n        let lodOffset = 0;\n        for (let i = 0; i < lods.length; i++) {\n            const inputLod = lods[i];\n            const outputLod = i;\n            const totalSplats = splats[inputLod];\n\n            await decodeUnitsForLod(\n                unitInfos, inputLod, dataSource, shSource ?? undefined,\n                compressInfo, lodOffset, properties, properties_f_rest,\n                tick\n            );\n\n            lodColumn.fill(outputLod, lodOffset, lodOffset + totalSplats);\n            lodOffset += totalSplats;\n        }\n\n        const columns = [\n            ...floatProps.map(name => new Column(name, properties[`property_${name}`])),\n            ...(properties_f_rest ? properties_f_rest.map((storage, i) => new Column(`f_rest_${i}`, storage)) : []),\n            new Column('lod', lodColumn)\n        ];\n\n        mainTable = new DataTable(columns, new Transform().fromEulers(90, 0, 180));\n        // Close the bar only on success: leaving it open on the error path\n        // lets `logger.error() -> unwindAll(true)` mark it as failed\n        // instead of finalizing it as a successful bar first.\n        bar.end();\n    } finally {\n        dataSource?.close();\n        shSource?.close();\n    }\n\n    const result: DataTable[] = [mainTable];\n\n    // environment.bin is optional - missing file is a normal case (no skybox).\n    // Different ReadFileSystem implementations signal \"not found\" differently:\n    //   - NodeReadFileSystem throws an Error with `code === 'ENOENT'`\n    //   - Memory/Zip backends throw `Error('Entry not found: ...')`\n    //   - UrlReadFileSystem throws `Error('HTTP error 404: ...')`\n    // Suppress warnings for any of these.\n    try {\n        const envData = await readFile(fileSystem, relatedFilename('environment.bin'));\n        const envDataTable = deserializeEnvironment(envData, compressInfo, hasSH);\n        envDataTable.addColumn(new Column('lod', new Float32Array(envDataTable.numRows).fill(-1)));\n        envDataTable.transform = new Transform().fromEulers(90, 0, 180);\n        result.push(envDataTable);\n    } catch (err) {\n        const code = (err as { code?: string })?.code;\n        const message = (err as Error)?.message ?? '';\n        const isMissing = code === 'ENOENT' ||\n            message.startsWith('Entry not found') ||\n            message.startsWith('HTTP error 404');\n        if (!isMissing) {\n            logger.warn(`failed to load environment.bin: ${message || err}`);\n        }\n    }\n\n    return result;\n};\n\nexport { readLcc };\n","import { Column, DataTable } from '../data-table';\nimport { Param } from '../types';\n\ntype Generator = {\n    count: number;\n    columnNames: string[];\n    getRow: (index: number, row: any) => void;\n};\n\n/**\n * Reads splat data from a JavaScript module generator.\n *\n * The module must export a `Generator` class with a static `create(params)` method\n * that returns an object with `count`, `columnNames`, and `getRow(index, row)` properties.\n * This allows programmatic generation of splat data.\n *\n * @param moduleUrl - URL or path to the JavaScript module.\n * @param params - Parameters to pass to the generator's create method.\n * @returns Promise resolving to a DataTable containing the generated splat data.\n * @ignore\n */\nconst readMjs = async (moduleUrl: string, params: Param[]): Promise<DataTable> => {\n    const module = await import(moduleUrl);\n    if (!module) {\n        throw new Error(`Failed to load module: ${moduleUrl}`);\n    }\n\n    const generator = (await module.Generator?.create(params)) as Generator;\n\n    if (!generator) {\n        throw new Error(`Failed to create Generator instance: ${moduleUrl}`);\n    }\n\n    const columns: Column[] = generator.columnNames.map((name: string) => {\n        return new Column(name, new Float32Array(generator.count));\n    });\n\n    const row: any = {};\n    for (let i = 0; i < generator.count; ++i) {\n        generator.getRow(i, row);\n        columns.forEach((c) => {\n            c.data[i] = row[c.name];\n        });\n    }\n\n    return new DataTable(columns);\n};\n\nexport { readMjs };\n","import type { PlyData } from './read-ply';\nimport { Column, DataTable } from '../data-table';\n\n// Size of a chunk in the compressed PLY format (number of splats per chunk)\nconst CHUNK_SIZE = 256;\n\nconst isCompressedPly = (ply: PlyData): boolean => {\n    const hasShape = (dataTable: DataTable, columns: string[], type: string) => {\n        return columns.every((name) => {\n            const col = dataTable.getColumnByName(name);\n            return col && col.dataType === type;\n        });\n    };\n\n    const requiredChunkProperties = [\n        'min_x',\n        'min_y',\n        'min_z',\n        'max_x',\n        'max_y',\n        'max_z',\n        'min_scale_x',\n        'min_scale_y',\n        'min_scale_z',\n        'max_scale_x',\n        'max_scale_y',\n        'max_scale_z'\n    ];\n\n    const colorChunkProperties = [\n        'min_r',\n        'min_g',\n        'min_b',\n        'max_r',\n        'max_g',\n        'max_b'\n    ];\n\n    const vertexProperties = [\n        'packed_position',\n        'packed_rotation',\n        'packed_scale',\n        'packed_color'\n    ];\n\n    const numElements = ply.elements.length;\n    if (numElements !== 2 && numElements !== 3) return false;\n\n    const chunk = ply.elements.find(e => e.name === 'chunk');\n    if (!chunk || !hasShape(chunk.dataTable, requiredChunkProperties, 'float32')) return false;\n\n    // accept either 12 (no per-chunk color) or 18 (with per-chunk color) chunk properties\n    const numChunkCols = chunk.dataTable.numColumns;\n    if (numChunkCols === requiredChunkProperties.length + colorChunkProperties.length) {\n        if (!hasShape(chunk.dataTable, colorChunkProperties, 'float32')) return false;\n    } else if (numChunkCols !== requiredChunkProperties.length) {\n        return false;\n    }\n\n    const vertex = ply.elements.find(e => e.name === 'vertex');\n    if (!vertex || !hasShape(vertex.dataTable, vertexProperties, 'uint32')) return false;\n\n    if (Math.ceil(vertex.dataTable.numRows / CHUNK_SIZE) !== chunk.dataTable.numRows) {\n        return false;\n    }\n\n    // check optional spherical harmonics\n    if (numElements === 3) {\n        const sh = ply.elements.find(e => e.name === 'sh');\n        if (!sh) {\n            return false;\n        }\n        const shData = sh.dataTable;\n        if ([9, 24, 45].indexOf(shData.numColumns) === -1) {\n            return false;\n        }\n        for (let i = 0; i < shData.numColumns; ++i) {\n            const col = shData.getColumnByName(`f_rest_${i}`);\n            if (!col || col.dataType !== 'uint8') {\n                return false;\n            }\n        }\n\n        if (shData.numRows !== vertex.dataTable.numRows) {\n            return false;\n        }\n    }\n\n    return true;\n};\n\n// Detects the compressed PLY schema and returns a decompressed DataTable, or null if not compressed.\nconst decompressPly = (ply: PlyData): DataTable => {\n    const chunkData = ply.elements.find(e => e.name === 'chunk').dataTable;\n    const getChunk = (name: string) => chunkData.getColumnByName(name)!.data as Float32Array;\n\n    const vertexData = ply.elements.find(e => e.name === 'vertex').dataTable;\n    const packed_position = vertexData.getColumnByName('packed_position')!.data as Uint32Array;\n    const packed_rotation = vertexData.getColumnByName('packed_rotation')!.data as Uint32Array;\n    const packed_scale = vertexData.getColumnByName('packed_scale')!.data as Uint32Array;\n    const packed_color = vertexData.getColumnByName('packed_color')!.data as Uint32Array;\n\n    const min_x = getChunk('min_x');\n    const min_y = getChunk('min_y');\n    const min_z = getChunk('min_z');\n    const max_x = getChunk('max_x');\n    const max_y = getChunk('max_y');\n    const max_z = getChunk('max_z');\n    const min_scale_x = getChunk('min_scale_x');\n    const min_scale_y = getChunk('min_scale_y');\n    const min_scale_z = getChunk('min_scale_z');\n    const max_scale_x = getChunk('max_scale_x');\n    const max_scale_y = getChunk('max_scale_y');\n    const max_scale_z = getChunk('max_scale_z');\n    const hasChunkColors = chunkData.hasColumn('min_r');\n    const min_r = hasChunkColors ? getChunk('min_r') : null;\n    const min_g = hasChunkColors ? getChunk('min_g') : null;\n    const min_b = hasChunkColors ? getChunk('min_b') : null;\n    const max_r = hasChunkColors ? getChunk('max_r') : null;\n    const max_g = hasChunkColors ? getChunk('max_g') : null;\n    const max_b = hasChunkColors ? getChunk('max_b') : null;\n\n    const numSplats = vertexData.numRows;\n\n    const columns: Column[] = [\n        new Column('x', new Float32Array(numSplats)),\n        new Column('y', new Float32Array(numSplats)),\n        new Column('z', new Float32Array(numSplats)),\n        new Column('f_dc_0', new Float32Array(numSplats)),\n        new Column('f_dc_1', new Float32Array(numSplats)),\n        new Column('f_dc_2', new Float32Array(numSplats)),\n        new Column('opacity', new Float32Array(numSplats)),\n        new Column('rot_0', new Float32Array(numSplats)),\n        new Column('rot_1', new Float32Array(numSplats)),\n        new Column('rot_2', new Float32Array(numSplats)),\n        new Column('rot_3', new Float32Array(numSplats)),\n        new Column('scale_0', new Float32Array(numSplats)),\n        new Column('scale_1', new Float32Array(numSplats)),\n        new Column('scale_2', new Float32Array(numSplats))\n    ];\n\n    const result = new DataTable(columns);\n\n    const lerp = (a: number, b: number, t: number) => a * (1 - t) + b * t;\n    const unpackUnorm = (value: number, bits: number) => {\n        const t = (1 << bits) - 1;\n        return (value & t) / t;\n    };\n    const unpack111011 = (value: number) => ({\n        x: unpackUnorm(value >>> 21, 11),\n        y: unpackUnorm(value >>> 11, 10),\n        z: unpackUnorm(value, 11)\n    });\n    const unpack8888 = (value: number) => ({\n        x: unpackUnorm(value >>> 24, 8),\n        y: unpackUnorm(value >>> 16, 8),\n        z: unpackUnorm(value >>> 8, 8),\n        w: unpackUnorm(value, 8)\n    });\n    const unpackRot = (value: number) => {\n        const norm = 1.0 / (Math.sqrt(2) * 0.5);\n        const a = (unpackUnorm(value >>> 20, 10) - 0.5) * norm;\n        const b = (unpackUnorm(value >>> 10, 10) - 0.5) * norm;\n        const c = (unpackUnorm(value, 10) - 0.5) * norm;\n        const m = Math.sqrt(Math.max(0, 1.0 - (a * a + b * b + c * c)));\n        const which = value >>> 30;\n        switch (which) {\n            case 0:\n                return { x: m, y: a, z: b, w: c };\n            case 1:\n                return { x: a, y: m, z: b, w: c };\n            case 2:\n                return { x: a, y: b, z: m, w: c };\n            default:\n                return { x: a, y: b, z: c, w: m };\n        }\n    };\n\n    const SH_C0 = 0.28209479177387814;\n\n    const ox = result.getColumnByName('x')!.data as Float32Array;\n    const oy = result.getColumnByName('y')!.data as Float32Array;\n    const oz = result.getColumnByName('z')!.data as Float32Array;\n    const or0 = result.getColumnByName('rot_0')!.data as Float32Array;\n    const or1 = result.getColumnByName('rot_1')!.data as Float32Array;\n    const or2 = result.getColumnByName('rot_2')!.data as Float32Array;\n    const or3 = result.getColumnByName('rot_3')!.data as Float32Array;\n    const os0 = result.getColumnByName('scale_0')!.data as Float32Array;\n    const os1 = result.getColumnByName('scale_1')!.data as Float32Array;\n    const os2 = result.getColumnByName('scale_2')!.data as Float32Array;\n    const of0 = result.getColumnByName('f_dc_0')!.data as Float32Array;\n    const of1 = result.getColumnByName('f_dc_1')!.data as Float32Array;\n    const of2 = result.getColumnByName('f_dc_2')!.data as Float32Array;\n    const oo = result.getColumnByName('opacity')!.data as Float32Array;\n\n    for (let i = 0; i < numSplats; ++i) {\n        const ci = Math.floor(i / CHUNK_SIZE);\n\n        const p = unpack111011(packed_position[i]);\n        const r = unpackRot(packed_rotation[i]);\n        const s = unpack111011(packed_scale[i]);\n        const c = unpack8888(packed_color[i]);\n\n        ox[i] = lerp(min_x[ci], max_x[ci], p.x);\n        oy[i] = lerp(min_y[ci], max_y[ci], p.y);\n        oz[i] = lerp(min_z[ci], max_z[ci], p.z);\n\n        or0[i] = r.x;\n        or1[i] = r.y;\n        or2[i] = r.z;\n        or3[i] = r.w;\n\n        os0[i] = lerp(min_scale_x[ci], max_scale_x[ci], s.x);\n        os1[i] = lerp(min_scale_y[ci], max_scale_y[ci], s.y);\n        os2[i] = lerp(min_scale_z[ci], max_scale_z[ci], s.z);\n\n        const cr = hasChunkColors ? lerp(min_r[ci], max_r[ci], c.x) : c.x;\n        const cg = hasChunkColors ? lerp(min_g[ci], max_g[ci], c.y) : c.y;\n        const cb = hasChunkColors ? lerp(min_b[ci], max_b[ci], c.z) : c.z;\n        of0[i] = (cr - 0.5) / SH_C0;\n        of1[i] = (cg - 0.5) / SH_C0;\n        of2[i] = (cb - 0.5) / SH_C0;\n\n        oo[i] = -Math.log(1 / c.w - 1);\n    }\n\n    // extract spherical harmonics\n    const shElem = ply.elements.find(e => e.name === 'sh');\n    if (shElem) {\n        const shData = shElem.dataTable;\n        for (let k = 0; k < shData.numColumns; ++k) {\n            const col = shData.getColumn(k);\n            const src = col.data as Uint8Array;\n            const dst = new Float32Array(numSplats);\n            for (let i = 0; i < numSplats; ++i) {\n                const n = (src[i] === 0) ? 0 : (src[i] === 255) ? 1 : (src[i] + 0.5) / 256;\n                dst[i] = (n - 0.5) * 8;\n            }\n            result.addColumn(new Column(col.name, dst));\n        }\n    }\n\n    return result;\n};\n\nexport { isCompressedPly, decompressPly };\n","import { isCompressedPly, decompressPly } from './decompress-ply';\nimport { Column, DataTable } from '../data-table';\nimport { ReadSource, ReadStream } from '../io/read';\nimport { logger, Transform } from '../utils';\n\ntype PlyProperty = {\n    name: string;               // 'x', f_dc_0', etc\n    type: string;               // 'float', 'char', etc\n};\n\ntype PlyElement = {\n    name: string;               // 'vertex', etc\n    count: number;\n    properties: PlyProperty[];\n};\n\ntype PlyHeader = {\n    comments: string[];\n    elements: PlyElement[];\n};\n\ntype PlyData = {\n    comments: string[];\n    elements: {\n        name: string,\n        dataTable: DataTable\n    }[];\n};\n\nconst getDataType = (type: string) => {\n    switch (type) {\n        case 'char': return Int8Array;\n        case 'uchar': return Uint8Array;\n        case 'short': return Int16Array;\n        case 'ushort': return Uint16Array;\n        case 'int': return Int32Array;\n        case 'uint': return Uint32Array;\n        case 'float': return Float32Array;\n        case 'double': return Float64Array;\n        default: return null;\n    }\n};\n\n// Returns a function that reads a value from a DataView at the given byte offset\ntype ValueReader = (view: DataView, offset: number) => number;\n\nconst getReader = (type: string): ValueReader => {\n    switch (type) {\n        case 'char':   return (v, o) => v.getInt8(o);\n        case 'uchar':  return (v, o) => v.getUint8(o);\n        case 'short':  return (v, o) => v.getInt16(o, true);\n        case 'ushort': return (v, o) => v.getUint16(o, true);\n        case 'int':    return (v, o) => v.getInt32(o, true);\n        case 'uint':   return (v, o) => v.getUint32(o, true);\n        case 'float':  return (v, o) => v.getFloat32(o, true);\n        case 'double': return (v, o) => v.getFloat64(o, true);\n        default: throw new Error(`unsupported ply type: ${type}`);\n    }\n};\n\n// Check if all properties in an element are float type (enables fast path)\nconst isFloatElement = (element: PlyElement): boolean => {\n    return element.properties.every(p => p.type === 'float');\n};\n\n// parse the ply header text and return an array of Element structures and a\n// string containing the ply format\nconst parseHeader = (data: Uint8Array): PlyHeader => {\n    // decode header and split into lines\n    const strings = new TextDecoder('ascii')\n    .decode(data)\n    .split('\\n')\n    .filter(line => line);\n\n    const elements: PlyElement[] = [];\n    const comments: string[] = [];\n    let element;\n    for (let i = 1; i < strings.length; ++i) {\n        const words = strings[i].split(' ');\n\n        switch (words[0]) {\n            case 'ply':\n            case 'format':\n            case 'end_header':\n                // skip\n                break;\n            case 'comment':\n                comments.push(strings[i].substring(8)); // skip 'comment '\n                break;\n            case 'element': {\n                if (words.length !== 3) {\n                    throw new Error('invalid ply header');\n                }\n                element = {\n                    name: words[1],\n                    count: parseInt(words[2], 10),\n                    properties: []\n                };\n                elements.push(element);\n                break;\n            }\n            case 'property': {\n                if (!element || words.length !== 3 || !getDataType(words[1])) {\n                    throw new Error('invalid ply header');\n                }\n                element.properties.push({\n                    name: words[2],\n                    type: words[1]\n                });\n                break;\n            }\n            default: {\n                throw new Error(`unrecognized header value '${words[0]}' in ply header`);\n            }\n        }\n    }\n\n    return { comments, elements };\n};\n\nconst cmp = (a: Uint8Array, b: Uint8Array, aOffset = 0) => {\n    for (let i = 0; i < b.length; ++i) {\n        if (a[aOffset + i] !== b[i]) {\n            return false;\n        }\n    }\n    return true;\n};\n\nconst magicBytes = new Uint8Array([112, 108, 121, 10]);                                                 // ply\\n\nconst endHeaderBytes = new Uint8Array([10, 101, 110, 100, 95, 104, 101, 97, 100, 101, 114, 10]);        // \\nend_header\\n\n\n/**\n * Helper to read exactly n bytes from a stream into a buffer at an offset.\n * @param stream - The stream to read from\n * @param buffer - Target buffer\n * @param offset - Offset in buffer to write to\n * @param length - Number of bytes to read\n * @returns Number of bytes actually read\n */\nconst readExact = async (\n    stream: ReadStream,\n    buffer: Uint8Array,\n    offset: number,\n    length: number\n): Promise<number> => {\n    let totalRead = 0;\n    while (totalRead < length) {\n        const target = buffer.subarray(offset + totalRead, offset + length);\n        const n = await stream.pull(target);\n        if (n === 0) break; // EOF\n        totalRead += n;\n    }\n    return totalRead;\n};\n\n/**\n * Reads a PLY file containing Gaussian splat data.\n *\n * Supports both standard PLY files and compressed PLY format. The PLY format is\n * the standard output from 3D Gaussian Splatting training pipelines.\n *\n * @param source - The read source providing access to the PLY file data.\n * @returns Promise resolving to a DataTable containing the splat data.\n * @ignore\n */\nconst readPly = async (source: ReadSource): Promise<DataTable> => {\n    const stream = source.read();\n\n    // we don't support ply text header larger than 128k\n    const headerBuf = new Uint8Array(128 * 1024);\n\n    // smallest possible header size\n    let headerSize = magicBytes.length + endHeaderBytes.length;\n\n    if (await readExact(stream, headerBuf, 0, headerSize) !== headerSize) {\n        throw new Error('failed to read file header');\n    }\n\n    if (!cmp(headerBuf, magicBytes)) {\n        throw new Error('invalid file header');\n    }\n\n    // read the rest of the header till we find end header byte pattern\n    while (true) {\n        // read the next character\n        if (await readExact(stream, headerBuf, headerSize++, 1) !== 1) {\n            throw new Error('failed to read file header');\n        }\n\n        // check if we've reached the end of the header\n        if (cmp(headerBuf, endHeaderBytes, headerSize - endHeaderBytes.length)) {\n            break;\n        }\n    }\n\n    // parse the header\n    const header = parseHeader(headerBuf.subarray(0, headerSize));\n\n    // Single decode bar across all elements: sized by total rows so that\n    // multi-element PLYs (e.g. compressed PLY: chunk + vertex) render as one\n    // smooth progression rather than two disjoint segments.\n    const totalRows = header.elements.reduce((sum, e) => sum + e.count, 0);\n    const bar = logger.bar('decoding', totalRows);\n    let rowsDecoded = 0;\n\n    // create a data table for each ply element\n    const elements = [];\n    for (let i = 0; i < header.elements.length; ++i) {\n        const element = header.elements[i];\n\n        const columns = element.properties.map((property) => {\n            return new Column(property.name, new (getDataType(property.type)!)(element.count));\n        });\n\n        const numProperties = columns.length;\n        const numRows = element.count;\n\n        // Check if all properties are float32 (enables fast path)\n        if (isFloatElement(element)) {\n            // Fast path: all properties are float32\n            // Use Float32Array view with property-major loop order for best performance\n            const rowSize = numProperties * 4; // 4 bytes per float\n            const chunkSize = 1024;\n            const numChunks = Math.ceil(numRows / chunkSize);\n            const chunkData = new Uint8Array(chunkSize * rowSize);\n            const floatData = new Float32Array(chunkData.buffer);\n\n            // Pre-extract storage arrays for direct access\n            const storage = columns.map(c => c.data as Float32Array);\n\n            for (let c = 0; c < numChunks; ++c) {\n                const chunkRows = Math.min(chunkSize, numRows - c * chunkSize);\n                const baseRowIndex = c * chunkSize;\n\n                await readExact(stream, chunkData, 0, rowSize * chunkRows);\n\n                // Property-major loop order: better cache locality, processes batch at once\n                for (let p = 0; p < numProperties; ++p) {\n                    const s = storage[p];\n                    for (let r = 0; r < chunkRows; ++r) {\n                        s[baseRowIndex + r] = floatData[r * numProperties + p];\n                    }\n                }\n\n                rowsDecoded += chunkRows;\n                bar.update(rowsDecoded);\n            }\n        } else {\n            // General path: mixed types, use DataView with reader functions\n            let byteOffset = 0;\n            const columnInfo = element.properties.map((property, idx) => {\n                const size = columns[idx].data.BYTES_PER_ELEMENT;\n                const info = {\n                    data: columns[idx].data,\n                    size,\n                    byteOffset,\n                    reader: getReader(property.type)\n                };\n                byteOffset += size;\n                return info;\n            });\n\n            const rowSize = byteOffset;\n            const chunkSize = 1024;\n            const numChunks = Math.ceil(numRows / chunkSize);\n            const chunkData = new Uint8Array(chunkSize * rowSize);\n\n            for (let c = 0; c < numChunks; ++c) {\n                const chunkRows = Math.min(chunkSize, numRows - c * chunkSize);\n\n                await readExact(stream, chunkData, 0, rowSize * chunkRows);\n\n                // Create DataView once per chunk\n                const view = new DataView(chunkData.buffer, chunkData.byteOffset, chunkData.byteLength);\n\n                // Row-major loop with DataView readers\n                for (let r = 0; r < chunkRows; ++r) {\n                    const rowIndex = c * chunkSize + r;\n                    const rowByteOffset = r * rowSize;\n\n                    for (let p = 0; p < columnInfo.length; ++p) {\n                        const info = columnInfo[p];\n                        info.data[rowIndex] = info.reader(view, rowByteOffset + info.byteOffset);\n                    }\n                }\n\n                rowsDecoded += chunkRows;\n                bar.update(rowsDecoded);\n            }\n        }\n\n        elements.push({\n            name: element.name,\n            dataTable: new DataTable(columns)\n        });\n    }\n\n    const plyData = {\n        comments: header.comments,\n        elements\n    };\n\n    let result: DataTable;\n\n    if (isCompressedPly(plyData)) {\n        result = decompressPly(plyData);\n    } else {\n        const vertexElement = plyData.elements.find(e => e.name === 'vertex');\n        if (!vertexElement) {\n            throw new Error('PLY file does not contain vertex element');\n        }\n        result = vertexElement.dataTable;\n    }\n\n    result.transform = Transform.PLY.clone();\n\n    // Close the bar only on success: leaving it open on any earlier error\n    // path (missing `vertex` element, `decompressPly` failure, etc.) lets\n    // `logger.error() -> unwindAll(true)` mark it as failed instead of\n    // finalizing it as a successful bar first.\n    bar.end();\n\n    return result;\n};\n\nexport { PlyData, readPly };\n","import { Column, DataTable } from '../data-table';\nimport { join, type ReadFileSystem } from '../io/read';\nimport { logger, Transform, WebPCodec } from '../utils';\n\n// V1 (legacy) SOG meta layout. Quantization is a per-channel linear lerp\n// between mins/maxs, with no codebook. The engine's SOG parser still loads\n// these (with a deprecation warning), so we mirror its decoding so older\n// published assets keep working through splat-transform.\n//\n// The current (V2) format is handled in read-sog.ts; the public readSog\n// dispatcher there falls back to readSogV1 when it sees a meta without\n// `version: 2`. Keeping V1 isolated here lets both code paths stay free of\n// version branching, and makes deleting V1 support trivial when the legacy\n// data is no longer in circulation.\ntype MetaV1 = {\n    means: {\n        shape: [number, number];\n        mins: number[];\n        maxs: number[];\n        files: string[];\n    };\n    scales: { mins: number[]; maxs: number[]; files: string[] };\n    quats: { files: string[] };\n    sh0: { mins: number[]; maxs: number[]; files: string[] };\n    shN?: {\n        shape?: [number, number];\n        mins: number;\n        maxs: number;\n        quantization?: number;\n        files: string[];\n    };\n};\n\nconst decodeMeans = (lo: Uint8Array, hi: Uint8Array, count: number) => {\n    const xs = new Uint16Array(count);\n    const ys = new Uint16Array(count);\n    const zs = new Uint16Array(count);\n    for (let i = 0; i < count; i++) {\n        const o = i * 4;\n        xs[i] = lo[o + 0] | (hi[o + 0] << 8);\n        ys[i] = lo[o + 1] | (hi[o + 1] << 8);\n        zs[i] = lo[o + 2] | (hi[o + 2] << 8);\n    }\n    return { xs, ys, zs };\n};\n\n// Inverse of logTransform(x) = sign(x) * ln(|x| + 1)\nconst invLogTransform = (v: number) => {\n    const a = Math.abs(v);\n    const e = Math.exp(a) - 1; // |x|\n    return v < 0 ? -e : e;\n};\n\nconst unpackQuat = (px: number, py: number, pz: number, tag: number): [number, number, number, number] => {\n    const maxComp = tag - 252;\n    const a = px / 255 * 2 - 1;\n    const b = py / 255 * 2 - 1;\n    const c = pz / 255 * 2 - 1;\n    const sqrt2 = Math.sqrt(2);\n    const comps = [0, 0, 0, 0];\n    const idx = [\n        [1, 2, 3],\n        [0, 2, 3],\n        [0, 1, 3],\n        [0, 1, 2]\n    ][maxComp];\n    comps[idx[0]] = a / sqrt2;\n    comps[idx[1]] = b / sqrt2;\n    comps[idx[2]] = c / sqrt2;\n    // reconstruct max component to make unit length with positive sign\n    const t = 1 - (comps[0] * comps[0] + comps[1] * comps[1] + comps[2] * comps[2] + comps[3] * comps[3]);\n    comps[maxComp] = Math.sqrt(Math.max(0, t));\n    return comps as [number, number, number, number];\n};\n\n// Centroids texture width -> SH band count. The palette packs 64 entries per\n// row, each `shCoeffs` pixels wide, so width = 64 * shCoeffs. V1 has no\n// `bands` field in meta, so we infer from the texture geometry. Mapping\n// mirrors the engine's GSplatSogData.calcBands.\nconst v1ShBandsWidths: Record<number, number> = { 192: 1, 512: 2, 960: 3 };\n\n/**\n * Read a legacy V1 SOG file from a ReadFileSystem.\n *\n * Called by readSog (in read-sog.ts) after it detects a V1 meta payload.\n * Receives the already-parsed meta and the directory it was loaded from so\n * we don't re-fetch the JSON.\n *\n * @param fileSystem - The file system to read texture files from\n * @param baseDir - Directory containing the SOG textures (relative paths in\n * meta are resolved from here)\n * @param meta - The parsed V1 meta.json payload\n * @returns DataTable with Gaussian splat data\n * @ignore\n */\nconst readSogV1 = async (fileSystem: ReadFileSystem, baseDir: string, meta: MetaV1): Promise<DataTable> => {\n    const decoder = await WebPCodec.create();\n    const count = meta.means.shape[0];\n\n    const load = async (name: string): Promise<Uint8Array> => {\n        const src = await fileSystem.createSource(baseDir ? join(baseDir, name) : name);\n        try {\n            return await src.read().readAll();\n        } finally {\n            src.close();\n        }\n    };\n\n    const columns: Column[] = [\n        new Column('x', new Float32Array(count)),\n        new Column('y', new Float32Array(count)),\n        new Column('z', new Float32Array(count)),\n        new Column('scale_0', new Float32Array(count)),\n        new Column('scale_1', new Float32Array(count)),\n        new Column('scale_2', new Float32Array(count)),\n        new Column('f_dc_0', new Float32Array(count)),\n        new Column('f_dc_1', new Float32Array(count)),\n        new Column('f_dc_2', new Float32Array(count)),\n        new Column('opacity', new Float32Array(count)),\n        new Column('rot_0', new Float32Array(count)),\n        new Column('rot_1', new Float32Array(count)),\n        new Column('rot_2', new Float32Array(count)),\n        new Column('rot_3', new Float32Array(count))\n    ];\n\n    const numPasses = 4 + (meta.shN ? 1 : 0);\n    const bar = logger.bar('decoding', numPasses * count);\n    let passesDone = 0;\n    const tickPass = () => {\n        bar.update(++passesDone * count);\n    };\n\n    // means: two textures means_l (low byte) + means_u (high byte) packed as\n    // a 16-bit lerp between mins/maxs of the logTransform'd positions.\n    const meansLoWebp = await load(meta.means.files[0]);\n    const meansHiWebp = await load(meta.means.files[1]);\n    const { rgba: lo, width, height } = decoder.decodeRGBA(meansLoWebp);\n    const { rgba: hi } = decoder.decodeRGBA(meansHiWebp);\n    if (width * height < count) throw new Error('SOG means texture too small for count');\n    const { mins, maxs } = meta.means;\n    const { xs, ys, zs } = decodeMeans(lo, hi, count);\n    const xCol = columns[0].data as Float32Array;\n    const yCol = columns[1].data as Float32Array;\n    const zCol = columns[2].data as Float32Array;\n    const xMin = mins[0], xScale = (maxs[0] - mins[0]) || 1;\n    const yMin = mins[1], yScale = (maxs[1] - mins[1]) || 1;\n    const zMin = mins[2], zScale = (maxs[2] - mins[2]) || 1;\n    for (let i = 0; i < count; i++) {\n        xCol[i] = invLogTransform(xMin + xScale * (xs[i] / 65535));\n        yCol[i] = invLogTransform(yMin + yScale * (ys[i] / 65535));\n        zCol[i] = invLogTransform(zMin + zScale * (zs[i] / 65535));\n    }\n    tickPass();\n\n    // quats: 4 bytes per splat, last byte is the \"largest component\" tag\n    // (252-255 -> w/x/y/z is largest); other 3 encode the smaller components\n    // scaled by sqrt(2). Identical to V2.\n    const quatsWebp = await load(meta.quats.files[0]);\n    const { rgba: qr, width: qw, height: qh } = decoder.decodeRGBA(quatsWebp);\n    if (qw * qh < count) throw new Error('SOG quats texture too small for count');\n    const r0 = columns[10].data as Float32Array;\n    const r1 = columns[11].data as Float32Array;\n    const r2 = columns[12].data as Float32Array;\n    const r3 = columns[13].data as Float32Array;\n    for (let i = 0; i < count; i++) {\n        const o = i * 4;\n        const tag = qr[o + 3];\n        if (tag < 252 || tag > 255) { // invalid tag, default to identity (rot_0 = w)\n            r0[i] = 1; r1[i] = 0; r2[i] = 0; r3[i] = 0;\n            continue;\n        }\n        // unpackQuat returns components in (w, x, y, z) order; rot_0..rot_3 map to (w, x, y, z).\n        const [w, x, y, z] = unpackQuat(qr[o], qr[o + 1], qr[o + 2], tag);\n        r0[i] = w; r1[i] = x; r2[i] = y; r3[i] = z;\n    }\n    tickPass();\n\n    // scales: per-axis 8-bit linear lerp between mins/maxs (log-space).\n    const scalesWebp = await load(meta.scales.files[0]);\n    const { rgba: sl, width: sw, height: sh } = decoder.decodeRGBA(scalesWebp);\n    if (sw * sh < count) throw new Error('SOG scales texture too small for count');\n    const sMins = meta.scales.mins;\n    const sMaxs = meta.scales.maxs;\n    const s0 = columns[3].data as Float32Array;\n    const s1 = columns[4].data as Float32Array;\n    const s2 = columns[5].data as Float32Array;\n    for (let i = 0; i < count; i++) {\n        const o = i * 4;\n        s0[i] = sMins[0] + (sMaxs[0] - sMins[0]) * (sl[o + 0] / 255);\n        s1[i] = sMins[1] + (sMaxs[1] - sMins[1]) * (sl[o + 1] / 255);\n        s2[i] = sMins[2] + (sMaxs[2] - sMins[2]) * (sl[o + 2] / 255);\n    }\n    tickPass();\n\n    // sh0: 3 color channels lerped between mins[0..2]/maxs[0..2]; opacity is\n    // a *pre-sigmoid logit* lerped between mins[3]/maxs[3] and written\n    // straight into the opacity column (no sigmoid round-trip needed).\n    const sh0Webp = await load(meta.sh0.files[0]);\n    const { rgba: c0, width: cw, height: ch } = decoder.decodeRGBA(sh0Webp);\n    if (cw * ch < count) throw new Error('SOG sh0 texture too small for count');\n    const cMins = meta.sh0.mins;\n    const cMaxs = meta.sh0.maxs;\n    const dc0 = columns[6].data as Float32Array;\n    const dc1 = columns[7].data as Float32Array;\n    const dc2 = columns[8].data as Float32Array;\n    const opCol = columns[9].data as Float32Array;\n    for (let i = 0; i < count; i++) {\n        const o = i * 4;\n        dc0[i] = cMins[0] + (cMaxs[0] - cMins[0]) * (c0[o + 0] / 255);\n        dc1[i] = cMins[1] + (cMaxs[1] - cMins[1]) * (c0[o + 1] / 255);\n        dc2[i] = cMins[2] + (cMaxs[2] - cMins[2]) * (c0[o + 2] / 255);\n        opCol[i] = cMins[3] + (cMaxs[3] - cMins[3]) * (c0[o + 3] / 255);\n    }\n    tickPass();\n\n    // shN: indirect lookup via labels -> centroids palette, with each centroid\n    // pixel byte lerped between scalar mins/maxs that span all SH coeffs.\n    if (meta.shN) {\n        const centroidsWebp = await load(meta.shN.files[0]);\n        const labelsWebp = await load(meta.shN.files[1]);\n        const { rgba: centroidsRGBA, width: cW, height: cH } = decoder.decodeRGBA(centroidsWebp);\n        const { rgba: labelsRGBA, width: lW, height: lH } = decoder.decodeRGBA(labelsWebp);\n\n        // Validate label texture size up-front: out-of-bounds typed-array reads\n        // coerce to 0 via the bitwise ops below, which would silently map many\n        // splats to centroid 0 instead of failing.\n        if (lW * lH < count) throw new Error('SOG shN labels texture too small for count');\n\n        // Centroids width determines the band count (palette packs 64 entries\n        // per row, each shCoeffs pixels wide). An unrecognized width means the\n        // shN payload is malformed; throw rather than silently skipping.\n        const bands = v1ShBandsWidths[cW] ?? 0;\n        const shCoeffs = [0, 3, 8, 15][bands];\n        if (bands === 0) throw new Error(`SOG shN centroids texture has unrecognized width ${cW}, expected one of 192 / 512 / 960`);\n\n        if (shCoeffs > 0) {\n            const shMin = meta.shN.mins;\n            const shSpan = meta.shN.maxs - meta.shN.mins;\n            const dequant = (b: number) => shMin + shSpan * (b / 255);\n\n            // Upper-bound palette guard: V1 has no explicit count, so use the\n            // texture geometry (`floor(cW / shCoeffs) * cH` palette slots).\n            const paletteCount = Math.floor(cW / shCoeffs) * cH;\n\n            const baseIdx = columns.length;\n            for (let i = 0; i < shCoeffs * 3; i++) {\n                columns.push(new Column(`f_rest_${i}`, new Float32Array(count)));\n            }\n\n            const stride = 4;\n            const getCentroidPixel = (centroidIndex: number, coeff: number) => {\n                const cx = (centroidIndex % 64) * shCoeffs + coeff;\n                const cy = Math.floor(centroidIndex / 64);\n                if (cx >= cW || cy >= cH) return [0, 0, 0] as [number, number, number];\n                const idx = (cy * cW + cx) * stride;\n                return [centroidsRGBA[idx], centroidsRGBA[idx + 1], centroidsRGBA[idx + 2]] as [number, number, number];\n            };\n\n            for (let i = 0; i < count; i++) {\n                const o = i * 4;\n                const label = labelsRGBA[o] | (labelsRGBA[o + 1] << 8); // 16-bit palette index\n                if (label >= paletteCount) continue; // safety\n                for (let j = 0; j < shCoeffs; j++) {\n                    const [lr, lg, lb] = getCentroidPixel(label, j);\n                    (columns[baseIdx + j + shCoeffs * 0].data as Float32Array)[i] = dequant(lr);\n                    (columns[baseIdx + j + shCoeffs * 1].data as Float32Array)[i] = dequant(lg);\n                    (columns[baseIdx + j + shCoeffs * 2].data as Float32Array)[i] = dequant(lb);\n                }\n            }\n        }\n        tickPass();\n    }\n\n    // Close the bar only on success: leaving it open on the error path lets\n    // `logger.error() -> unwindAll(true)` mark it as failed instead of\n    // finalizing it as a successful bar first.\n    bar.end();\n\n    return new DataTable(columns, Transform.PLY);\n};\n\nexport { readSogV1, type MetaV1 };\n","import { Column, DataTable } from '../data-table';\nimport { basename, dirname, join, type ReadFileSystem, readFile } from '../io/read';\nimport { logger, Transform, WebPCodec } from '../utils';\nimport { readSogV1, type MetaV1 } from './read-sog-v1';\n\n// V2 (current) SOG meta layout - codebook-based quantization for scales /\n// sh0 / shN. Legacy V1 uses a different per-channel mins/maxs scheme and is\n// handled separately in read-sog-v1.ts.\ntype MetaV2 = {\n    version: 2;\n    count: number;\n    means: { mins: number[]; maxs: number[]; files: string[] };\n    scales: { codebook: number[]; files: string[] };\n    quats: { files: string[] };\n    sh0: { codebook: number[]; files: string[] };\n    shN?: { count: number; bands: number; codebook: number[]; files: string[] };\n};\n\nconst decodeMeans = (lo: Uint8Array, hi: Uint8Array, count: number) => {\n    const xs = new Uint16Array(count);\n    const ys = new Uint16Array(count);\n    const zs = new Uint16Array(count);\n    for (let i = 0; i < count; i++) {\n        const o = i * 4;\n        xs[i] = lo[o + 0] | (hi[o + 0] << 8);\n        ys[i] = lo[o + 1] | (hi[o + 1] << 8);\n        zs[i] = lo[o + 2] | (hi[o + 2] << 8);\n    }\n    return { xs, ys, zs };\n};\n\n// Inverse of logTransform(x) = sign(x) * ln(|x| + 1)\nconst invLogTransform = (v: number) => {\n    const a = Math.abs(v);\n    const e = Math.exp(a) - 1; // |x|\n    return v < 0 ? -e : e;\n};\n\nconst unpackQuat = (px: number, py: number, pz: number, tag: number): [number, number, number, number] => {\n    const maxComp = tag - 252;\n    const a = px / 255 * 2 - 1;\n    const b = py / 255 * 2 - 1;\n    const c = pz / 255 * 2 - 1;\n    const sqrt2 = Math.sqrt(2);\n    const comps = [0, 0, 0, 0];\n    const idx = [\n        [1, 2, 3],\n        [0, 2, 3],\n        [0, 1, 3],\n        [0, 1, 2]\n    ][maxComp];\n    comps[idx[0]] = a / sqrt2;\n    comps[idx[1]] = b / sqrt2;\n    comps[idx[2]] = c / sqrt2;\n    // reconstruct max component to make unit length with positive sign\n    const t = 1 - (comps[0] * comps[0] + comps[1] * comps[1] + comps[2] * comps[2] + comps[3] * comps[3]);\n    comps[maxComp] = Math.sqrt(Math.max(0, t));\n    return comps as [number, number, number, number];\n};\n\nconst sigmoidInv = (y: number) => {\n    const e = Math.min(1 - 1e-6, Math.max(1e-6, y));\n    return Math.log(e / (1 - e));\n};\n\n/**\n * Read a SOG file from a ReadFileSystem.\n *\n * The current (V2) format is decoded inline. Legacy V1 files (no `version`\n * field, per-channel mins/maxs instead of codebooks) are detected here and\n * forwarded to {@link readSogV1} in read-sog-v1.ts.\n *\n * @param fileSystem - The file system to read from\n * @param filename - Path to meta.json (relative paths resolved from its directory).\n * The basename is used verbatim for the initial meta fetch so\n * any URL querystring/fragment (e.g. presigned `?token=...`)\n * is preserved.\n * @returns DataTable with Gaussian splat data\n * @ignore\n */\nconst readSog = async (fileSystem: ReadFileSystem, filename: string): Promise<DataTable> => {\n    const baseDir = dirname(filename);\n    const metaName = basename(filename);\n    const resolve = (name: string) => (baseDir ? join(baseDir, name) : name);\n\n    const metaBytes = await readFile(fileSystem, resolve(metaName));\n    const rawMeta = JSON.parse(new TextDecoder().decode(metaBytes)) as MetaV2 | (MetaV1 & { version?: number });\n\n    // Dispatch:\n    //   - V1 (legacy) has no `version` field        -> readSogV1\n    //   - V2 (current) has `version: 2`             -> handled inline below\n    //   - any other (future/unknown) version        -> hard error rather than\n    //     silently mis-routing to V1, which would surface as confusing\n    //     downstream failures (missing `means.shape`, etc.).\n    const version = rawMeta.version;\n    if (version === undefined) {\n        return readSogV1(fileSystem, baseDir, rawMeta as MetaV1);\n    }\n    if (version !== 2) {\n        throw new Error(`Unsupported SOG meta version: ${version}`);\n    }\n    const meta = rawMeta as MetaV2;\n\n    const decoder = await WebPCodec.create();\n    const count = meta.count;\n\n    const load = async (name: string): Promise<Uint8Array> => {\n        const src = await fileSystem.createSource(resolve(name));\n        try {\n            return await src.read().readAll();\n        } finally {\n            src.close();\n        }\n    };\n\n    const columns: Column[] = [\n        new Column('x', new Float32Array(count)),\n        new Column('y', new Float32Array(count)),\n        new Column('z', new Float32Array(count)),\n        new Column('scale_0', new Float32Array(count)),\n        new Column('scale_1', new Float32Array(count)),\n        new Column('scale_2', new Float32Array(count)),\n        new Column('f_dc_0', new Float32Array(count)),\n        new Column('f_dc_1', new Float32Array(count)),\n        new Column('f_dc_2', new Float32Array(count)),\n        new Column('opacity', new Float32Array(count)),\n        new Column('rot_0', new Float32Array(count)),\n        new Column('rot_1', new Float32Array(count)),\n        new Column('rot_2', new Float32Array(count)),\n        new Column('rot_3', new Float32Array(count))\n    ];\n\n    // One bar across all per-gaussian decode passes. Total = passes * count\n    // (means, quats, scales, sh0, plus an optional shN pass). Each pass ticks\n    // with `count` once it has finished writing into the output columns.\n    const numPasses = 4 + (meta.shN ? 1 : 0);\n    const bar = logger.bar('decoding', numPasses * count);\n    let passesDone = 0;\n    const tickPass = () => {\n        bar.update(++passesDone * count);\n    };\n\n    // means: two textures means_l (low byte) + means_u (high byte) packed as\n    // a 16-bit lerp between mins/maxs of the logTransform'd positions.\n    const meansLoWebp = await load(meta.means.files[0]);\n    const meansHiWebp = await load(meta.means.files[1]);\n    const { rgba: lo, width, height } = decoder.decodeRGBA(meansLoWebp);\n    const { rgba: hi } = decoder.decodeRGBA(meansHiWebp);\n    if (width * height < count) throw new Error('SOG means texture too small for count');\n    const { mins, maxs } = meta.means;\n    const { xs, ys, zs } = decodeMeans(lo, hi, count);\n    const xCol = columns[0].data as Float32Array;\n    const yCol = columns[1].data as Float32Array;\n    const zCol = columns[2].data as Float32Array;\n    const xMin = mins[0], xScale = (maxs[0] - mins[0]) || 1;\n    const yMin = mins[1], yScale = (maxs[1] - mins[1]) || 1;\n    const zMin = mins[2], zScale = (maxs[2] - mins[2]) || 1;\n    for (let i = 0; i < count; i++) {\n        xCol[i] = invLogTransform(xMin + xScale * (xs[i] / 65535));\n        yCol[i] = invLogTransform(yMin + yScale * (ys[i] / 65535));\n        zCol[i] = invLogTransform(zMin + zScale * (zs[i] / 65535));\n    }\n    tickPass();\n\n    // quats: 4 bytes per splat, last byte is the \"largest component\" tag\n    // (252-255 -> w/x/y/z is largest); other 3 encode the smaller components\n    // scaled by sqrt(2).\n    const quatsWebp = await load(meta.quats.files[0]);\n    const { rgba: qr, width: qw, height: qh } = decoder.decodeRGBA(quatsWebp);\n    if (qw * qh < count) throw new Error('SOG quats texture too small for count');\n    const r0 = columns[10].data as Float32Array;\n    const r1 = columns[11].data as Float32Array;\n    const r2 = columns[12].data as Float32Array;\n    const r3 = columns[13].data as Float32Array;\n    for (let i = 0; i < count; i++) {\n        const o = i * 4;\n        const tag = qr[o + 3];\n        if (tag < 252 || tag > 255) { // invalid tag, default to identity (rot_0 = w)\n            r0[i] = 1; r1[i] = 0; r2[i] = 0; r3[i] = 0;\n            continue;\n        }\n        // unpackQuat returns components in (w, x, y, z) order; rot_0..rot_3 map to (w, x, y, z).\n        const [w, x, y, z] = unpackQuat(qr[o], qr[o + 1], qr[o + 2], tag);\n        r0[i] = w; r1[i] = x; r2[i] = y; r3[i] = z;\n    }\n    tickPass();\n\n    // scales: each byte indexes the shared 256-entry codebook.\n    const scalesWebp = await load(meta.scales.files[0]);\n    const { rgba: sl, width: sw, height: sh } = decoder.decodeRGBA(scalesWebp);\n    if (sw * sh < count) throw new Error('SOG scales texture too small for count');\n    const sCode = new Float32Array(meta.scales.codebook);\n    const s0 = columns[3].data as Float32Array;\n    const s1 = columns[4].data as Float32Array;\n    const s2 = columns[5].data as Float32Array;\n    for (let i = 0; i < count; i++) {\n        const o = i * 4;\n        s0[i] = sCode[sl[o]];\n        s1[i] = sCode[sl[o + 1]];\n        s2[i] = sCode[sl[o + 2]];\n    }\n    tickPass();\n\n    // sh0: 3 color bytes index the shared codebook; opacity byte is a sigmoid\n    // value, decoded back to a logit via sigmoidInv.\n    const sh0Webp = await load(meta.sh0.files[0]);\n    const { rgba: c0, width: cw, height: ch } = decoder.decodeRGBA(sh0Webp);\n    if (cw * ch < count) throw new Error('SOG sh0 texture too small for count');\n    const cCode = new Float32Array(meta.sh0.codebook);\n    const dc0 = columns[6].data as Float32Array;\n    const dc1 = columns[7].data as Float32Array;\n    const dc2 = columns[8].data as Float32Array;\n    const opCol = columns[9].data as Float32Array;\n    for (let i = 0; i < count; i++) {\n        const o = i * 4;\n        dc0[i] = cCode[c0[o + 0]];\n        dc1[i] = cCode[c0[o + 1]];\n        dc2[i] = cCode[c0[o + 2]];\n        opCol[i] = sigmoidInv(c0[o + 3] / 255);\n    }\n    tickPass();\n\n    // shN (optional): indirect lookup via labels -> centroids palette, with\n    // each centroid pixel byte indexing the shared codebook.\n    if (meta.shN) {\n        const { bands, count: paletteCount } = meta.shN;\n        const shCoeffs = [0, 3, 8, 15][bands];\n        if (shCoeffs > 0) {\n            const codebook = new Float32Array(meta.shN.codebook);\n            const centroidsWebp = await load(meta.shN.files[0]);\n            const labelsWebp = await load(meta.shN.files[1]);\n            const { rgba: centroidsRGBA, width: cW, height: cH } = decoder.decodeRGBA(centroidsWebp);\n            const { rgba: labelsRGBA, width: lW, height: lH } = decoder.decodeRGBA(labelsWebp);\n\n            // Validate texture geometry up-front: missing guards would let\n            // truncated textures silently produce zeros (out-of-bounds typed-\n            // array reads coerce to 0 via the bitwise ops below) instead of\n            // failing like the means/quats/scales/sh0 passes do.\n            if (lW * lH < count) throw new Error('SOG shN labels texture too small for count');\n            if (cW !== 64 * shCoeffs) throw new Error(`SOG shN centroids texture width ${cW} does not match expected ${64 * shCoeffs} for ${bands}-band palette`);\n\n            const baseIdx = columns.length;\n            for (let i = 0; i < shCoeffs * 3; i++) {\n                columns.push(new Column(`f_rest_${i}`, new Float32Array(count)));\n            }\n\n            const stride = 4;\n            const getCentroidPixel = (centroidIndex: number, coeff: number) => {\n                const cx = (centroidIndex % 64) * shCoeffs + coeff;\n                const cy = Math.floor(centroidIndex / 64);\n                if (cx >= cW || cy >= cH) return [0, 0, 0] as [number, number, number];\n                const idx = (cy * cW + cx) * stride;\n                return [centroidsRGBA[idx], centroidsRGBA[idx + 1], centroidsRGBA[idx + 2]] as [number, number, number];\n            };\n\n            for (let i = 0; i < count; i++) {\n                const o = i * 4;\n                const label = labelsRGBA[o] | (labelsRGBA[o + 1] << 8); // 16-bit palette index\n                if (label >= paletteCount) continue; // safety\n                for (let j = 0; j < shCoeffs; j++) {\n                    const [lr, lg, lb] = getCentroidPixel(label, j);\n                    (columns[baseIdx + j + shCoeffs * 0].data as Float32Array)[i] = codebook[lr] ?? 0;\n                    (columns[baseIdx + j + shCoeffs * 1].data as Float32Array)[i] = codebook[lg] ?? 0;\n                    (columns[baseIdx + j + shCoeffs * 2].data as Float32Array)[i] = codebook[lb] ?? 0;\n                }\n            }\n        }\n        tickPass();\n    }\n\n    // Close the bar only on success: leaving it open on the error path lets\n    // `logger.error() -> unwindAll(true)` mark it as failed instead of\n    // finalizing it as a successful bar first.\n    bar.end();\n\n    return new DataTable(columns, Transform.PLY);\n};\n\nexport { readSog };\n","import { Column, DataTable } from '../data-table';\nimport { ReadSource } from '../io/read';\nimport { logger, Transform } from '../utils';\n\nconst TICK_BATCH = 1 << 16;\n\n/**\n * Reads an Antimatter15 .splat file containing Gaussian splat data.\n *\n * The .splat format stores each splat as 32 bytes with position, scale, color,\n * opacity, and rotation data in a compact binary format.\n *\n * @param source - The read source providing access to the .splat file data.\n * @returns Promise resolving to a DataTable containing the splat data.\n * @ignore\n */\nconst readSplat = async (source: ReadSource): Promise<DataTable> => {\n    // Load complete file\n    const fileBuffer = await source.read().readAll();\n    const fileSize = fileBuffer.length;\n\n    // Each splat is 32 bytes\n    const BYTES_PER_SPLAT = 32;\n    if (fileSize % BYTES_PER_SPLAT !== 0) {\n        throw new Error('Invalid .splat file: file size is not a multiple of 32 bytes');\n    }\n\n    const numSplats = fileSize / BYTES_PER_SPLAT;\n\n    if (numSplats === 0) {\n        throw new Error('Invalid .splat file: file is empty');\n    }\n\n    // Create columns for the standard Gaussian splat data\n    const columns = [\n        // Position\n        new Column('x', new Float32Array(numSplats)),\n        new Column('y', new Float32Array(numSplats)),\n        new Column('z', new Float32Array(numSplats)),\n\n        // Scale (stored as linear in .splat, convert to log for internal use)\n        new Column('scale_0', new Float32Array(numSplats)),\n        new Column('scale_1', new Float32Array(numSplats)),\n        new Column('scale_2', new Float32Array(numSplats)),\n\n        // Color/opacity\n        new Column('f_dc_0', new Float32Array(numSplats)), // Red\n        new Column('f_dc_1', new Float32Array(numSplats)), // Green\n        new Column('f_dc_2', new Float32Array(numSplats)), // Blue\n        new Column('opacity', new Float32Array(numSplats)),\n\n        // Rotation quaternion\n        new Column('rot_0', new Float32Array(numSplats)),\n        new Column('rot_1', new Float32Array(numSplats)),\n        new Column('rot_2', new Float32Array(numSplats)),\n        new Column('rot_3', new Float32Array(numSplats))\n    ];\n\n    const bar = logger.bar('decoding', numSplats);\n\n    // Create a DataView for reading binary data\n    const dataView = new DataView(fileBuffer.buffer, fileBuffer.byteOffset, fileBuffer.byteLength);\n\n    // Parse each splat\n    for (let splatIndex = 0; splatIndex < numSplats; splatIndex++) {\n        const offset = splatIndex * BYTES_PER_SPLAT;\n\n        // Read position (3 × float32)\n        const x = dataView.getFloat32(offset + 0, true);\n        const y = dataView.getFloat32(offset + 4, true);\n        const z = dataView.getFloat32(offset + 8, true);\n\n        // Read scale (3 × float32)\n        const scaleX = dataView.getFloat32(offset + 12, true);\n        const scaleY = dataView.getFloat32(offset + 16, true);\n        const scaleZ = dataView.getFloat32(offset + 20, true);\n\n        // Read color and opacity (4 × uint8)\n        const red = fileBuffer[offset + 24];\n        const green = fileBuffer[offset + 25];\n        const blue = fileBuffer[offset + 26];\n        const opacity = fileBuffer[offset + 27];\n\n        // Read rotation quaternion (4 × uint8)\n        const rot0 = fileBuffer[offset + 28];\n        const rot1 = fileBuffer[offset + 29];\n        const rot2 = fileBuffer[offset + 30];\n        const rot3 = fileBuffer[offset + 31];\n\n        // Store position\n        (columns[0].data as Float32Array)[splatIndex] = x;\n        (columns[1].data as Float32Array)[splatIndex] = y;\n        (columns[2].data as Float32Array)[splatIndex] = z;\n\n        // Store scale (convert from linear in .splat to log scale for internal use)\n        (columns[3].data as Float32Array)[splatIndex] = Math.log(scaleX);\n        (columns[4].data as Float32Array)[splatIndex] = Math.log(scaleY);\n        (columns[5].data as Float32Array)[splatIndex] = Math.log(scaleZ);\n\n        // Store color (convert from uint8 back to spherical harmonics)\n        const SH_C0 = 0.28209479177387814;\n        (columns[6].data as Float32Array)[splatIndex] = (red / 255.0 - 0.5) / SH_C0;\n        (columns[7].data as Float32Array)[splatIndex] = (green / 255.0 - 0.5) / SH_C0;\n        (columns[8].data as Float32Array)[splatIndex] = (blue / 255.0 - 0.5) / SH_C0;\n\n        // Store opacity (convert from uint8 to float and apply inverse sigmoid)\n        const epsilon = 1e-6;\n        const normalizedOpacity = Math.max(epsilon, Math.min(1.0 - epsilon, opacity / 255.0));\n        (columns[9].data as Float32Array)[splatIndex] = Math.log(normalizedOpacity / (1.0 - normalizedOpacity));\n\n        // Store rotation quaternion (convert from uint8 [0,255] to float [-1,1] and normalize)\n        const rot0Norm = (rot0 / 255.0) * 2.0 - 1.0;\n        const rot1Norm = (rot1 / 255.0) * 2.0 - 1.0;\n        const rot2Norm = (rot2 / 255.0) * 2.0 - 1.0;\n        const rot3Norm = (rot3 / 255.0) * 2.0 - 1.0;\n\n        // Normalize quaternion\n        const length = Math.sqrt(rot0Norm * rot0Norm + rot1Norm * rot1Norm + rot2Norm * rot2Norm + rot3Norm * rot3Norm);\n        if (length > 0) {\n            (columns[10].data as Float32Array)[splatIndex] = rot0Norm / length;\n            (columns[11].data as Float32Array)[splatIndex] = rot1Norm / length;\n            (columns[12].data as Float32Array)[splatIndex] = rot2Norm / length;\n            (columns[13].data as Float32Array)[splatIndex] = rot3Norm / length;\n        } else {\n            // Default to identity quaternion if invalid (rot_0 = w)\n            (columns[10].data as Float32Array)[splatIndex] = 1.0;\n            (columns[11].data as Float32Array)[splatIndex] = 0.0;\n            (columns[12].data as Float32Array)[splatIndex] = 0.0;\n            (columns[13].data as Float32Array)[splatIndex] = 0.0;\n        }\n\n        if ((splatIndex & (TICK_BATCH - 1)) === (TICK_BATCH - 1)) {\n            bar.update(splatIndex + 1);\n        }\n    }\n\n    bar.update(numSplats);\n    bar.end();\n\n    return new DataTable(columns, Transform.PLY);\n};\n\nexport { readSplat };\n","import { Column, DataTable, convertToSpace } from './data-table';\nimport { Transform } from './utils';\n\ntype CoordinateSystem = {\n    RDF: number;\n};\n\ntype GaussianCloud = {\n    numPoints: number;\n    shDegree: number;\n    antialiased: boolean;\n    extensions: unknown[];\n    positions: Float32Array;\n    scales: Float32Array;\n    rotations: Float32Array;\n    alphas: Float32Array;\n    colors: Float32Array;\n    sh: Float32Array;\n};\n\ntype PackOptions = {\n    version: number;\n    from: number;\n    sh1Bits?: number;\n    shRestBits?: number;\n};\n\ntype UnpackOptions = {\n    to: number;\n};\n\ntype SpzModule = {\n    CoordinateSystem: CoordinateSystem;\n    LATEST_SPZ_HEADER_VERSION: number;\n    loadSpzFromBuffer(data: Uint8Array | ArrayBuffer, options?: UnpackOptions): GaussianCloud | Promise<GaussianCloud>;\n    saveSpzToBuffer(cloud: GaussianCloud, options?: PackOptions): Uint8Array;\n};\n\ntype CreateSpzModule = () => Promise<SpzModule>;\n\nconst SPZ_SH_COMPONENTS = [0, 9, 24, 45, 72] as const;\n\nlet spzModulePromise: Promise<SpzModule> | null = null;\n\n// `@adobe/spz`'s GaussianCloud uses PLY-native conventions for scales/colors/alphas:\n// scales are log-space, colors are SH DC coefficients, alphas are pre-sigmoid (logit).\n// The wasm packer applies (s+10)*16, c*0.15+0.5, sigmoid(a) internally; the unpacker inverts.\n// So we pass these fields straight through and only reorder the quaternion (xyzw <-> wxyz).\n\nconst getCreateSpzModule = async () => {\n    const { default: createModule } = await import('@adobe/spz');\n    return createModule as CreateSpzModule;\n};\n\nconst getSpzModule = (): Promise<SpzModule> => {\n    if (!spzModulePromise) {\n        spzModulePromise = getCreateSpzModule().then(createModule => createModule());\n    }\n    return spzModulePromise;\n};\n\nconst getShColumnCount = (dataTable: DataTable) => {\n    let count = 0;\n    while (dataTable.hasColumn(`f_rest_${count}`)) {\n        count += 1;\n    }\n    return count;\n};\n\nconst getShDegreeFromCount = (count: number) => {\n    const degree = SPZ_SH_COMPONENTS.indexOf(count as typeof SPZ_SH_COMPONENTS[number]);\n    if (degree === -1) {\n        throw new Error(`Unsupported SH coefficient count for SPZ: ${count}`);\n    }\n    return degree;\n};\n\nconst gaussianCloudToDataTable = (cloud: GaussianCloud) => {\n    const { numPoints, shDegree } = cloud;\n    if (shDegree < 0 || shDegree >= SPZ_SH_COMPONENTS.length) {\n        throw new Error(`Unsupported SH degree ${shDegree}`);\n    }\n\n    const shColumnCount = SPZ_SH_COMPONENTS[shDegree];\n    const shCoefficientsPerChannel = shColumnCount / 3;\n\n    const columns = [\n        new Column('x', new Float32Array(numPoints)),\n        new Column('y', new Float32Array(numPoints)),\n        new Column('z', new Float32Array(numPoints)),\n        new Column('scale_0', new Float32Array(numPoints)),\n        new Column('scale_1', new Float32Array(numPoints)),\n        new Column('scale_2', new Float32Array(numPoints)),\n        new Column('f_dc_0', new Float32Array(numPoints)),\n        new Column('f_dc_1', new Float32Array(numPoints)),\n        new Column('f_dc_2', new Float32Array(numPoints)),\n        new Column('opacity', new Float32Array(numPoints)),\n        new Column('rot_0', new Float32Array(numPoints)),\n        new Column('rot_1', new Float32Array(numPoints)),\n        new Column('rot_2', new Float32Array(numPoints)),\n        new Column('rot_3', new Float32Array(numPoints))\n    ];\n\n    for (let i = 0; i < shColumnCount; i += 1) {\n        columns.push(new Column(`f_rest_${i}`, new Float32Array(numPoints)));\n    }\n\n    const x = columns[0].data as Float32Array;\n    const y = columns[1].data as Float32Array;\n    const z = columns[2].data as Float32Array;\n    const scale0 = columns[3].data as Float32Array;\n    const scale1 = columns[4].data as Float32Array;\n    const scale2 = columns[5].data as Float32Array;\n    const color0 = columns[6].data as Float32Array;\n    const color1 = columns[7].data as Float32Array;\n    const color2 = columns[8].data as Float32Array;\n    const opacity = columns[9].data as Float32Array;\n    const rot0 = columns[10].data as Float32Array;\n    const rot1 = columns[11].data as Float32Array;\n    const rot2 = columns[12].data as Float32Array;\n    const rot3 = columns[13].data as Float32Array;\n\n    for (let i = 0; i < numPoints; i += 1) {\n        const i3 = i * 3;\n        const i4 = i * 4;\n\n        x[i] = cloud.positions[i3];\n        y[i] = cloud.positions[i3 + 1];\n        z[i] = cloud.positions[i3 + 2];\n\n        scale0[i] = cloud.scales[i3];\n        scale1[i] = cloud.scales[i3 + 1];\n        scale2[i] = cloud.scales[i3 + 2];\n\n        color0[i] = cloud.colors[i3];\n        color1[i] = cloud.colors[i3 + 1];\n        color2[i] = cloud.colors[i3 + 2];\n\n        opacity[i] = cloud.alphas[i];\n\n        rot0[i] = cloud.rotations[i4 + 3];\n        rot1[i] = cloud.rotations[i4];\n        rot2[i] = cloud.rotations[i4 + 1];\n        rot3[i] = cloud.rotations[i4 + 2];\n\n        for (let coeff = 0; coeff < shCoefficientsPerChannel; coeff += 1) {\n            const shBase = i * shColumnCount + coeff * 3;\n            (columns[14 + coeff].data as Float32Array)[i] = cloud.sh[shBase];\n            (columns[14 + shCoefficientsPerChannel + coeff].data as Float32Array)[i] = cloud.sh[shBase + 1];\n            (columns[14 + shCoefficientsPerChannel * 2 + coeff].data as Float32Array)[i] = cloud.sh[shBase + 2];\n        }\n    }\n\n    return new DataTable(columns, Transform.PLY);\n};\n\nconst dataTableToGaussianCloud = (dataTable: DataTable): GaussianCloud => {\n    const plyDataTable = convertToSpace(dataTable, Transform.PLY);\n    const shColumnCount = getShColumnCount(plyDataTable);\n    const shDegree = getShDegreeFromCount(shColumnCount);\n    const shCoefficientsPerChannel = shColumnCount / 3;\n    const numPoints = plyDataTable.numRows;\n\n    const positions = new Float32Array(numPoints * 3);\n    const scales = new Float32Array(numPoints * 3);\n    const rotations = new Float32Array(numPoints * 4);\n    const alphas = new Float32Array(numPoints);\n    const colors = new Float32Array(numPoints * 3);\n    const sh = new Float32Array(numPoints * shColumnCount);\n\n    const x = plyDataTable.getColumnByName('x').data as Float32Array;\n    const y = plyDataTable.getColumnByName('y').data as Float32Array;\n    const z = plyDataTable.getColumnByName('z').data as Float32Array;\n    const scale0 = plyDataTable.getColumnByName('scale_0').data as Float32Array;\n    const scale1 = plyDataTable.getColumnByName('scale_1').data as Float32Array;\n    const scale2 = plyDataTable.getColumnByName('scale_2').data as Float32Array;\n    const color0 = plyDataTable.getColumnByName('f_dc_0').data as Float32Array;\n    const color1 = plyDataTable.getColumnByName('f_dc_1').data as Float32Array;\n    const color2 = plyDataTable.getColumnByName('f_dc_2').data as Float32Array;\n    const opacity = plyDataTable.getColumnByName('opacity').data as Float32Array;\n    const rot0 = plyDataTable.getColumnByName('rot_0').data as Float32Array;\n    const rot1 = plyDataTable.getColumnByName('rot_1').data as Float32Array;\n    const rot2 = plyDataTable.getColumnByName('rot_2').data as Float32Array;\n    const rot3 = plyDataTable.getColumnByName('rot_3').data as Float32Array;\n\n    const shColumns = Array.from(\n        { length: shColumnCount },\n        (_, index) => plyDataTable.getColumnByName(`f_rest_${index}`).data as Float32Array\n    );\n\n    for (let i = 0; i < numPoints; i += 1) {\n        const i3 = i * 3;\n        const i4 = i * 4;\n\n        positions[i3] = x[i];\n        positions[i3 + 1] = y[i];\n        positions[i3 + 2] = z[i];\n\n        scales[i3] = scale0[i];\n        scales[i3 + 1] = scale1[i];\n        scales[i3 + 2] = scale2[i];\n\n        colors[i3] = color0[i];\n        colors[i3 + 1] = color1[i];\n        colors[i3 + 2] = color2[i];\n\n        alphas[i] = opacity[i];\n\n        rotations[i4] = rot1[i];\n        rotations[i4 + 1] = rot2[i];\n        rotations[i4 + 2] = rot3[i];\n        rotations[i4 + 3] = rot0[i];\n\n        for (let coeff = 0; coeff < shCoefficientsPerChannel; coeff += 1) {\n            const shBase = i * shColumnCount + coeff * 3;\n            sh[shBase] = shColumns[coeff][i];\n            sh[shBase + 1] = shColumns[shCoefficientsPerChannel + coeff][i];\n            sh[shBase + 2] = shColumns[shCoefficientsPerChannel * 2 + coeff][i];\n        }\n    }\n\n    return {\n        numPoints,\n        shDegree,\n        antialiased: false,\n        extensions: [],\n        positions,\n        scales,\n        rotations,\n        alphas,\n        colors,\n        sh\n    };\n};\n\n// splat-transform treats SPZ as RDF on both sides: data is converted to PLY/RDF\n// space before saving (wasm flips RDF→RUB to produce a spec-compliant on-disk file),\n// and the reader requests `to: RDF` to flip back. The SPZ format itself stores no\n// coordinate-system metadata (see NgspFileHeader in the spec), so the convention is\n// purely by agreement; this matches the Niantic spec and lets splat-transform's\n// SPZ readers/writers round-trip through PLY losslessly.\nconst makeSpzPackOptions = async (overrides: Partial<PackOptions> = {}): Promise<PackOptions> => {\n    const spz = await getSpzModule();\n    return {\n        version: spz.LATEST_SPZ_HEADER_VERSION,\n        from: spz.CoordinateSystem.RDF,\n        sh1Bits: 5,\n        shRestBits: 4,\n        ...overrides\n    };\n};\n\nexport {\n    SPZ_SH_COMPONENTS,\n    dataTableToGaussianCloud,\n    gaussianCloudToDataTable,\n    getSpzModule,\n    makeSpzPackOptions\n};\n","import { DataTable } from '../data-table';\nimport { ReadSource } from '../io/read';\nimport { gaussianCloudToDataTable, getSpzModule } from '../spz-module';\n\n/**\n * Reads a .spz file using the official SPZ WebAssembly backend.\n *\n * Decodes to RDF (PLY) space — splat-transform's SPZ pipeline writes with\n * `from: RDF` and reads with `to: RDF`, treating SPZ on-disk as the spec'd\n * RUB form.\n *\n * @param source - The read source providing access to the .spz file data.\n * @returns Promise resolving to a DataTable containing the splat data.\n * @ignore\n */\nconst readSpz = async (source: ReadSource): Promise<DataTable> => {\n    const spz = await getSpzModule();\n    const fileBuffer = await source.read().readAll();\n    const spzBuffer = fileBuffer.byteOffset === 0 && fileBuffer.byteLength === fileBuffer.buffer.byteLength ?\n        fileBuffer :\n        fileBuffer.slice();\n    const cloud = await spz.loadSpzFromBuffer(spzBuffer, {\n        to: spz.CoordinateSystem.RDF\n    });\n\n    return gaussianCloudToDataTable(cloud);\n};\n\nexport { readSpz };\n","import { DataTable } from './data-table';\nimport { ReadFileSystem, ZipReadFileSystem } from './io/read';\nimport { readKsplat, readLcc, readMjs, readPly, readSog, readSplat, readSpz } from './readers';\nimport { Options, Param } from './types';\n\n/**\n * Supported input file formats for Gaussian splat data.\n *\n * - `ply` - PLY format (standard 3DGS training output)\n * - `splat` - Antimatter15 splat format\n * - `ksplat` - Kevin Kwok's compressed splat format\n * - `spz` - Niantic Labs compressed format\n * - `sog` - PlayCanvas SOG format (WebP-compressed)\n * - `lcc` - XGrids LCC format\n * - `mjs` - JavaScript module generator\n */\ntype InputFormat = 'mjs' | 'ksplat' | 'splat' | 'sog' | 'ply' | 'spz' | 'lcc';\n\n/**\n * Determines the input format based on file extension.\n *\n * @param filename - The filename to analyze.\n * @returns The detected input format.\n * @throws Error if the file extension is not recognized.\n *\n * @example\n * ```ts\n * const format = getInputFormat('scene.ply');  // returns 'ply'\n * const format2 = getInputFormat('scene.splat');  // returns 'splat'\n * ```\n */\n// Strip a trailing `?...` querystring and/or `#...` fragment from the\n// *basename* so that extension sniffing works for URL-shaped inputs:\n//   - full URLs:   `https://host/scene.sog?token=...`\n//   - CLI splits:  `scene.sog?token=...` (resolveInput passes the bare leaf\n//                  + query down to readFile so the initial fetch carries it)\n// Only the basename (text after the last `/` or `\\`) is considered, so\n// POSIX paths containing `?` or `#` in *directory* segments are left\n// untouched. Local files literally named with `?`/`#` in the basename are\n// an unsupported edge case (the extension would be ambiguous anyway).\nconst stripQueryAndHash = (filename: string): string => {\n    const lastSep = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\\\'));\n    const basenameStart = lastSep + 1;\n    const q = filename.slice(basenameStart).search(/[?#]/);\n    return q < 0 ? filename : filename.slice(0, basenameStart + q);\n};\n\nconst getInputFormat = (filename: string): InputFormat => {\n    const lowerFilename = stripQueryAndHash(filename).toLowerCase();\n\n    if (lowerFilename.endsWith('.mjs')) {\n        return 'mjs';\n    } else if (lowerFilename.endsWith('.ksplat')) {\n        return 'ksplat';\n    } else if (lowerFilename.endsWith('.splat')) {\n        return 'splat';\n    } else if (lowerFilename.endsWith('.sog') || lowerFilename.endsWith('meta.json')) {\n        return 'sog';\n    } else if (lowerFilename.endsWith('.ply')) {\n        return 'ply';\n    } else if (lowerFilename.endsWith('.spz')) {\n        return 'spz';\n    } else if (lowerFilename.endsWith('.lcc')) {\n        return 'lcc';\n    }\n\n    throw new Error(`Unsupported input file type: ${filename}`);\n};\n\n/**\n * Options for reading a Gaussian splat file.\n */\ntype ReadFileOptions = {\n    /** Path to the input file. */\n    filename: string;\n    /** The format of the input file. */\n    inputFormat: InputFormat;\n    /** Processing options. */\n    options: Options;\n    /** Parameters for generator modules (.mjs files). */\n    params: Param[];\n    /** File system abstraction for reading files. */\n    fileSystem: ReadFileSystem;\n};\n\n/**\n * Reads a Gaussian splat file and returns its data as one or more DataTables.\n *\n * Supports multiple input formats including PLY, splat, ksplat, spz, SOG, and LCC.\n * Some formats (like LCC) may return multiple DataTables for different LOD levels.\n *\n * Per-format progress (decoding bars, multi-payload bars) is emitted directly\n * by each reader through the global {@link logger}; install a renderer via\n * `logger.setRenderer(...)` to consume those events.\n *\n * @param readFileOptions - Options specifying the file to read and how to read it.\n * @returns Promise resolving to an array of DataTables containing the splat data.\n *\n * @example\n * ```ts\n * import { readFile, getInputFormat, UrlReadFileSystem } from '@playcanvas/splat-transform';\n *\n * const filename = 'scene.ply';\n * const fileSystem = new UrlReadFileSystem('https://example.com/');\n * const tables = await readFile({\n *     filename,\n *     inputFormat: getInputFormat(filename),\n *     options: {},\n *     params: [],\n *     fileSystem\n * });\n * ```\n */\nconst readFile = async (readFileOptions: ReadFileOptions): Promise<DataTable[]> => {\n    const { filename, inputFormat, options, params, fileSystem } = readFileOptions;\n\n    let result: DataTable[];\n\n    if (inputFormat === 'mjs') {\n        result = [await readMjs(filename, params)];\n    } else if (inputFormat === 'sog') {\n        const lowerFilename = stripQueryAndHash(filename).toLowerCase();\n        if (lowerFilename.endsWith('.sog')) {\n            // Outer .sog is a ZIP container - mount it and let the inner SOG\n            // reader drive its own decode bar against the zipped payloads.\n            const source = await fileSystem.createSource(filename);\n            const zipFs = new ZipReadFileSystem(source);\n            try {\n                result = [await readSog(zipFs, 'meta.json')];\n            } finally {\n                zipFs.close();\n            }\n        } else {\n            result = [await readSog(fileSystem, filename)];\n        }\n    } else if (inputFormat === 'lcc') {\n        result = await readLcc(fileSystem, filename, options);\n    } else {\n        const source = await fileSystem.createSource(filename);\n        try {\n            if (inputFormat === 'ply') {\n                result = [await readPly(source)];\n            } else if (inputFormat === 'ksplat') {\n                result = [await readKsplat(source)];\n            } else if (inputFormat === 'splat') {\n                result = [await readSplat(source)];\n            } else if (inputFormat === 'spz') {\n                result = [await readSpz(source)];\n            }\n        } finally {\n            source.close();\n        }\n    }\n\n    return result;\n};\n\nexport { readFile, getInputFormat, type InputFormat, type ReadFileOptions };\n","import { fmtBytes, logger } from '../utils';\n\n/**\n * Emit a single `Writing`-group entry as `<filename> (<formatted size>)`.\n *\n * Lives here (rather than in `io/write/`) so the low-level I/O layer stays\n * decoupled from the logger / formatting code; only writer modules pull this\n * in alongside their renderer-aware output.\n *\n * @param filename - Display name for the written file.\n * @param bytes - Number of bytes written.\n */\nconst logWrittenFile = (filename: string, bytes: number): void => {\n    logger.info(`${filename} (${fmtBytes(bytes)})`);\n};\n\nexport { logWrittenFile };\n","import { Quat } from 'playcanvas';\n\nimport { sigmoid } from '../utils';\n\nconst q = new Quat();\n\n// process and compress a chunk of 256 splats\nclass CompressedChunk {\n    static members = [\n        'x', 'y', 'z',\n        'scale_0', 'scale_1', 'scale_2',\n        'f_dc_0', 'f_dc_1', 'f_dc_2', 'opacity',\n        'rot_0', 'rot_1', 'rot_2', 'rot_3'\n    ];\n\n    size: number;\n    data: any = {};\n\n    // compressed data\n    chunkData: Float32Array;\n    position: Uint32Array;\n    rotation: Uint32Array;\n    scale: Uint32Array;\n    color: Uint32Array;\n\n    constructor(size = 256) {\n        this.size = size;\n        CompressedChunk.members.forEach((m) => {\n            this.data[m] = new Float32Array(size);\n        });\n        this.chunkData = new Float32Array(18);\n        this.position = new Uint32Array(size);\n        this.rotation = new Uint32Array(size);\n        this.scale = new Uint32Array(size);\n        this.color = new Uint32Array(size);\n    }\n\n    set(index: number, data: any) {\n        CompressedChunk.members.forEach((m) => {\n            this.data[m][index] = data[m];\n        });\n    }\n\n    pack() {\n        const calcMinMax = (data: Float32Array) => {\n            let min;\n            let max;\n            min = max = data[0];\n            for (let i = 1; i < data.length; ++i) {\n                const v = data[i];\n                min = Math.min(min, v);\n                max = Math.max(max, v);\n            }\n            return { min, max };\n        };\n\n        const normalize = (x: number, min: number, max: number) => {\n            if (x <= min) return 0;\n            if (x >= max) return 1;\n            return (max - min < 0.00001) ? 0 : (x - min) / (max - min);\n        };\n\n        const data = this.data;\n\n        const x = data.x;\n        const y = data.y;\n        const z = data.z;\n        const scale_0 = data.scale_0;\n        const scale_1 = data.scale_1;\n        const scale_2 = data.scale_2;\n        const rot_0 = data.rot_0;\n        const rot_1 = data.rot_1;\n        const rot_2 = data.rot_2;\n        const rot_3 = data.rot_3;\n        const f_dc_0 = data.f_dc_0;\n        const f_dc_1 = data.f_dc_1;\n        const f_dc_2 = data.f_dc_2;\n        const opacity = data.opacity;\n\n        const px = calcMinMax(x);\n        const py = calcMinMax(y);\n        const pz = calcMinMax(z);\n\n        const sx = calcMinMax(scale_0);\n        const sy = calcMinMax(scale_1);\n        const sz = calcMinMax(scale_2);\n\n        // clamp scale because sometimes values are at infinity\n        const clamp = (v: number, min: number, max: number) => Math.max(min, Math.min(max, v));\n        sx.min = clamp(sx.min, -20, 20);\n        sx.max = clamp(sx.max, -20, 20);\n        sy.min = clamp(sy.min, -20, 20);\n        sy.max = clamp(sy.max, -20, 20);\n        sz.min = clamp(sz.min, -20, 20);\n        sz.max = clamp(sz.max, -20, 20);\n\n        // convert f_dc_ to colors before calculating min/max and packaging\n        const SH_C0 = 0.28209479177387814;\n        for (let i = 0; i < f_dc_0.length; ++i) {\n            f_dc_0[i] = f_dc_0[i] * SH_C0 + 0.5;\n            f_dc_1[i] = f_dc_1[i] * SH_C0 + 0.5;\n            f_dc_2[i] = f_dc_2[i] * SH_C0 + 0.5;\n        }\n\n        const cr = calcMinMax(f_dc_0);\n        const cg = calcMinMax(f_dc_1);\n        const cb = calcMinMax(f_dc_2);\n\n        const packUnorm = (value: number, bits: number) => {\n            const t = (1 << bits) - 1;\n            return Math.max(0, Math.min(t, Math.floor(value * t + 0.5)));\n        };\n\n        const pack111011 = (x: number, y: number, z: number) => {\n            return packUnorm(x, 11) << 21 |\n                   packUnorm(y, 10) << 11 |\n                   packUnorm(z, 11);\n        };\n\n        const pack8888 = (x: number, y: number, z: number, w: number) => {\n            return packUnorm(x, 8) << 24 |\n                   packUnorm(y, 8) << 16 |\n                   packUnorm(z, 8) << 8 |\n                   packUnorm(w, 8);\n        };\n\n        // pack quaternion into 2,10,10,10\n        const packRot = (x: number, y: number, z: number, w: number) => {\n            q.set(x, y, z, w).normalize();\n            const a = [q.x, q.y, q.z, q.w];\n            const largest = a.reduce((curr, v, i) => (Math.abs(v) > Math.abs(a[curr]) ? i : curr), 0);\n\n            if (a[largest] < 0) {\n                a[0] = -a[0];\n                a[1] = -a[1];\n                a[2] = -a[2];\n                a[3] = -a[3];\n            }\n\n            const norm = Math.sqrt(2) * 0.5;\n            let result = largest;\n            for (let i = 0; i < 4; ++i) {\n                if (i !== largest) {\n                    result = (result << 10) | packUnorm(a[i] * norm + 0.5, 10);\n                }\n            }\n\n            return result;\n        };\n\n        // pack\n        for (let i = 0; i < this.size; ++i) {\n            this.position[i] = pack111011(\n                normalize(x[i], px.min, px.max),\n                normalize(y[i], py.min, py.max),\n                normalize(z[i], pz.min, pz.max)\n            );\n\n            this.rotation[i] = packRot(rot_0[i], rot_1[i], rot_2[i], rot_3[i]);\n\n            this.scale[i] = pack111011(\n                normalize(scale_0[i], sx.min, sx.max),\n                normalize(scale_1[i], sy.min, sy.max),\n                normalize(scale_2[i], sz.min, sz.max)\n            );\n\n            this.color[i] = pack8888(\n                normalize(f_dc_0[i], cr.min, cr.max),\n                normalize(f_dc_1[i], cg.min, cg.max),\n                normalize(f_dc_2[i], cb.min, cb.max),\n                sigmoid(opacity[i])\n            );\n        }\n\n        this.chunkData.set([\n            px.min, py.min, pz.min, px.max, py.max, pz.max,\n            sx.min, sy.min, sz.min, sx.max, sy.max, sz.max,\n            cr.min, cg.min, cb.min, cr.max, cg.max, cb.max\n        ], 0);\n    }\n}\n\nexport { CompressedChunk };\n","/**\n * The splat-transform version (semver MAJOR.MINOR.PATCH).\n */\nexport const version: string = '$_CURRENT_VERSION';\n\n/**\n * The splat-transform revision (short Git hash of HEAD at build time).\n */\nexport const revision: string = '$_CURRENT_REVISION';\n","import { basename } from 'pathe';\n\nimport { CompressedChunk } from './compressed-chunk';\nimport { logWrittenFile } from './utils';\nimport { DataTable, sortMortonOrder, convertToSpace, getSHBands, shRestNames } from '../data-table';\nimport { type FileSystem } from '../io/write';\nimport { logger, Transform } from '../utils';\nimport { version } from '../version';\n\nconst generatedByString = `Generated by splat-transform ${version}`;\n\nconst chunkProps = [\n    'min_x', 'min_y', 'min_z',\n    'max_x', 'max_y', 'max_z',\n    'min_scale_x', 'min_scale_y', 'min_scale_z',\n    'max_scale_x', 'max_scale_y', 'max_scale_z',\n    'min_r', 'min_g', 'min_b',\n    'max_r', 'max_g', 'max_b'\n];\n\nconst vertexProps = [\n    'packed_position',\n    'packed_rotation',\n    'packed_scale',\n    'packed_color'\n];\n\n// Size of a chunk in the compressed PLY format (number of splats per chunk)\nconst CHUNK_SIZE = 256;\n\ntype WriteCompressedPlyOptions = {\n    filename: string;\n    dataTable: DataTable;\n};\n\n/**\n * Writes Gaussian splat data to compressed PLY format.\n *\n * Uses quantization and chunking to reduce file size while maintaining\n * compatibility with PLY-based viewers. Data is sorted using Morton order\n * for better compression and streaming performance.\n *\n * @param options - Options including filename and data table to write.\n * @param fs - File system for writing the output file.\n * @ignore\n */\nconst writeCompressedPly = async (options: WriteCompressedPlyOptions, fs: FileSystem) => {\n    const { filename } = options;\n    const dataTable = convertToSpace(options.dataTable, Transform.PLY);\n\n    const shBands = getSHBands(dataTable);\n    const outputSHCoeffs = [0, 3, 8, 15][shBands];\n\n    const numSplats = dataTable.numRows;\n    const numChunks = Math.ceil(numSplats / CHUNK_SIZE);\n\n    const shHeader = shBands ? [\n        `element sh ${numSplats}`,\n        new Array(outputSHCoeffs * 3).fill('').map((_, i) => `property uchar f_rest_${i}`)\n    ].flat() : [];\n\n    const headerText = [\n        'ply',\n        'format binary_little_endian 1.0',\n        `comment ${generatedByString}`,\n        `element chunk ${numChunks}`,\n        chunkProps.map(p => `property float ${p}`),\n        `element vertex ${numSplats}`,\n        vertexProps.map(p => `property uint ${p}`),\n        shHeader,\n        'end_header\\n'\n    ].flat().join('\\n');\n\n    const header = (new TextEncoder()).encode(headerText);\n    const chunkData = new Float32Array(numChunks * chunkProps.length);\n    const splatIData = new Uint32Array(numSplats * vertexProps.length);\n    const shData = new Uint8Array(numSplats * outputSHCoeffs * 3);\n\n    // sort splats into some kind of order (morton order rn)\n    const sortIndices = new Uint32Array(dataTable.numRows);\n    for (let i = 0; i < sortIndices.length; ++i) {\n        sortIndices[i] = i;\n    }\n    sortMortonOrder(dataTable, sortIndices);\n\n    const row: any = {};\n\n    const chunk = new CompressedChunk();\n\n    for (let i = 0; i < numChunks; ++i) {\n        const num = Math.min(numSplats, (i + 1) * CHUNK_SIZE) - i * CHUNK_SIZE;\n        for (let j = 0; j < num; ++j) {\n            const index = sortIndices[i * CHUNK_SIZE + j];\n\n            // read splat data\n            dataTable.getRow(index, row);\n\n            // update chunk\n            chunk.set(j, row);\n\n            // quantize and write sh data\n            let off = (i * CHUNK_SIZE + j) * outputSHCoeffs * 3;\n            for (let k = 0; k < outputSHCoeffs * 3; ++k) {\n                const nvalue = row[shRestNames[k]] / 8 + 0.5;\n                shData[off++] = Math.max(0, Math.min(255, Math.trunc(nvalue * 256)));\n            }\n        }\n\n        // repeat the last gaussian to fill the rest of the final chunk\n        for (let j = num; j < CHUNK_SIZE; ++j) {\n            chunk.set(j, row);\n        }\n\n        // pack the chunk\n        chunk.pack();\n\n        // store the float data\n        chunkData.set(chunk.chunkData, i * 18);\n\n        // write packed bits\n        const offset = i * CHUNK_SIZE * 4;\n        for (let j = 0; j < num; ++j) {\n            splatIData[offset + j * 4 + 0] = chunk.position[j];\n            splatIData[offset + j * 4 + 1] = chunk.rotation[j];\n            splatIData[offset + j * 4 + 2] = chunk.scale[j];\n            splatIData[offset + j * 4 + 3] = chunk.color[j];\n        }\n    }\n\n    const writingGroup = logger.group('Writing');\n\n    const writer = await fs.createWriter(filename);\n    await writer.write(header);\n    await writer.write(new Uint8Array(chunkData.buffer));\n    await writer.write(new Uint8Array(splatIData.buffer));\n    await writer.write(shData);\n    await writer.close();\n\n    logWrittenFile(basename(filename), writer.bytesWritten);\n    writingGroup.end();\n};\n\nexport { writeCompressedPly };\n","import { basename } from 'pathe';\n\nimport { logWrittenFile } from './utils';\nimport { DataTable } from '../data-table';\nimport { type FileSystem } from '../io/write';\nimport { logger } from '../utils';\n\ntype WriteCSVOptions = {\n    filename: string;\n    dataTable: DataTable;\n};\n\n/**\n * Writes Gaussian splat data to a CSV text file.\n *\n * Useful for debugging, analysis, or importing into spreadsheet applications.\n * Each row represents one splat with all column values separated by commas.\n *\n * @param options - Options including filename and data table to write.\n * @param fs - File system for writing the output file.\n * @ignore\n */\nconst writeCsv = async (options: WriteCSVOptions, fs: FileSystem) => {\n    const { filename, dataTable } = options;\n\n    const len = dataTable.numRows;\n\n    const textEncoder = new TextEncoder();\n\n    const writingGroup = logger.group('Writing');\n\n    const writer = await fs.createWriter(filename);\n\n    // write header\n    await writer.write(textEncoder.encode(`${dataTable.columnNames.join(',')}\\n`));\n\n    const columns = dataTable.columns.map(c => c.data);\n\n    // write rows\n    for (let i = 0; i < len; ++i) {\n        let row = '';\n        for (let c = 0; c < dataTable.columns.length; ++c) {\n            if (c) row += ',';\n            row += columns[c][i];\n        }\n        await writer.write(textEncoder.encode(`${row}\\n`));\n    }\n\n    await writer.close();\n\n    logWrittenFile(basename(filename), writer.bytesWritten);\n    writingGroup.end();\n};\n\nexport { writeCsv };\n","import { basename } from 'pathe';\n\nimport { logWrittenFile } from './utils';\nimport { DataTable, convertToSpace, getSHBands, shRestNames } from '../data-table';\nimport { type FileSystem } from '../io/write';\nimport { logger, Transform, sigmoid } from '../utils';\nimport { version } from '../version';\n\nconst SH_C0 = 0.2820947917738781;\n\ntype WriteGlbOptions = {\n    filename: string;\n    dataTable: DataTable;\n};\n\n// glTF accessor component types\nconst FLOAT = 5126;\nconst UNSIGNED_BYTE = 5121;\n\n// glTF buffer view targets\nconst ARRAY_BUFFER = 34962;\n\n// GLB chunk types\nconst GLB_MAGIC = 0x46546C67;\nconst GLB_VERSION = 2;\nconst JSON_CHUNK_TYPE = 0x4E4F534A;\nconst BIN_CHUNK_TYPE = 0x004E4942;\n\n/**\n * Computes POSITION accessor min/max bounds required by the glTF spec.\n *\n * @param x - X position data.\n * @param y - Y position data.\n * @param z - Z position data.\n * @returns Object with min and max arrays.\n */\nconst computePositionBounds = (x: Float32Array, y: Float32Array, z: Float32Array) => {\n    let minX = Infinity, minY = Infinity, minZ = Infinity;\n    let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;\n\n    for (let i = 0; i < x.length; i++) {\n        if (x[i] < minX) minX = x[i];\n        if (x[i] > maxX) maxX = x[i];\n        if (y[i] < minY) minY = y[i];\n        if (y[i] > maxY) maxY = y[i];\n        if (z[i] < minZ) minZ = z[i];\n        if (z[i] > maxZ) maxZ = z[i];\n    }\n\n    return {\n        min: [minX, minY, minZ],\n        max: [maxX, maxY, maxZ]\n    };\n};\n\n/**\n * Pads a byte length up to the next multiple of 4.\n *\n * @param n - The byte length to align.\n * @returns The aligned byte length.\n */\nconst align4 = (n: number) => (n + 3) & ~3;\n\n/**\n * Builds the binary buffer containing all attribute data, and returns the\n * list of buffer views / accessor descriptions needed for the glTF JSON.\n *\n * @param dataTable - The DataTable containing splat data.\n * @param numSplats - Number of splats in the table.\n * @param shBands - Number of SH bands beyond DC (0-3).\n * @returns Object with segments, offsets, and the assembled binary buffer.\n */\nconst buildBinaryBuffer = (dataTable: DataTable, numSplats: number, shBands: number) => {\n    const x = dataTable.getColumnByName('x')!.data as Float32Array;\n    const y = dataTable.getColumnByName('y')!.data as Float32Array;\n    const z = dataTable.getColumnByName('z')!.data as Float32Array;\n    const rot0 = dataTable.getColumnByName('rot_0')!.data as Float32Array;\n    const rot1 = dataTable.getColumnByName('rot_1')!.data as Float32Array;\n    const rot2 = dataTable.getColumnByName('rot_2')!.data as Float32Array;\n    const rot3 = dataTable.getColumnByName('rot_3')!.data as Float32Array;\n    const scale0 = dataTable.getColumnByName('scale_0')!.data as Float32Array;\n    const scale1 = dataTable.getColumnByName('scale_1')!.data as Float32Array;\n    const scale2 = dataTable.getColumnByName('scale_2')!.data as Float32Array;\n    const opacity = dataTable.getColumnByName('opacity')!.data as Float32Array;\n    const fdc0 = dataTable.getColumnByName('f_dc_0')!.data as Float32Array;\n    const fdc1 = dataTable.getColumnByName('f_dc_1')!.data as Float32Array;\n    const fdc2 = dataTable.getColumnByName('f_dc_2')!.data as Float32Array;\n\n    // Coefficients per channel for each SH band beyond DC\n    const coeffsPerChannel = [0, 3, 8, 15][shBands];\n    const shCoefCount = [0, 3, 5, 7]; // per-degree coefficient count\n    const shDegrees = shBands; // degrees 1..shDegrees have rest coefficients\n\n    // Collect all binary segments and their metadata\n    type Segment = {\n        name: string;\n        data: ArrayBuffer;\n        componentType: number;\n        type: string;\n        count: number;\n        normalized?: boolean;\n        min?: number[];\n        max?: number[];\n    };\n\n    const segments: Segment[] = [];\n\n    // POSITION (VEC3 float)\n    const posData = new Float32Array(numSplats * 3);\n    for (let i = 0; i < numSplats; i++) {\n        posData[i * 3] = x[i];\n        posData[i * 3 + 1] = y[i];\n        posData[i * 3 + 2] = z[i];\n    }\n    const bounds = computePositionBounds(x, y, z);\n    segments.push({\n        name: 'POSITION',\n        data: posData.buffer,\n        componentType: FLOAT,\n        type: 'VEC3',\n        count: numSplats,\n        min: bounds.min,\n        max: bounds.max\n    });\n\n    // COLOR_0 fallback (VEC4 unsigned byte normalized)\n    const colorData = new Uint8Array(numSplats * 4);\n    for (let i = 0; i < numSplats; i++) {\n        const r = Math.max(0, Math.min(255, Math.round((fdc0[i] * SH_C0 + 0.5) * 255)));\n        const g = Math.max(0, Math.min(255, Math.round((fdc1[i] * SH_C0 + 0.5) * 255)));\n        const b = Math.max(0, Math.min(255, Math.round((fdc2[i] * SH_C0 + 0.5) * 255)));\n        const a = Math.max(0, Math.min(255, Math.round(sigmoid(opacity[i]) * 255)));\n        colorData[i * 4] = r;\n        colorData[i * 4 + 1] = g;\n        colorData[i * 4 + 2] = b;\n        colorData[i * 4 + 3] = a;\n    }\n    segments.push({\n        name: 'COLOR_0',\n        data: colorData.buffer,\n        componentType: UNSIGNED_BYTE,\n        type: 'VEC4',\n        count: numSplats,\n        normalized: true\n    });\n\n    // KHR_gaussian_splatting:ROTATION (VEC4 float, xyzw order)\n    const rotData = new Float32Array(numSplats * 4);\n    for (let i = 0; i < numSplats; i++) {\n        rotData[i * 4] = rot1[i];     // x\n        rotData[i * 4 + 1] = rot2[i]; // y\n        rotData[i * 4 + 2] = rot3[i]; // z\n        rotData[i * 4 + 3] = rot0[i]; // w\n    }\n    segments.push({\n        name: 'KHR_gaussian_splatting:ROTATION',\n        data: rotData.buffer,\n        componentType: FLOAT,\n        type: 'VEC4',\n        count: numSplats\n    });\n\n    // KHR_gaussian_splatting:SCALE (VEC3 float, log-space)\n    const scaleData = new Float32Array(numSplats * 3);\n    for (let i = 0; i < numSplats; i++) {\n        scaleData[i * 3] = scale0[i];\n        scaleData[i * 3 + 1] = scale1[i];\n        scaleData[i * 3 + 2] = scale2[i];\n    }\n    segments.push({\n        name: 'KHR_gaussian_splatting:SCALE',\n        data: scaleData.buffer,\n        componentType: FLOAT,\n        type: 'VEC3',\n        count: numSplats\n    });\n\n    // KHR_gaussian_splatting:OPACITY (SCALAR float, sigmoid-activated)\n    const opacityData = new Float32Array(numSplats);\n    for (let i = 0; i < numSplats; i++) {\n        opacityData[i] = sigmoid(opacity[i]);\n    }\n    segments.push({\n        name: 'KHR_gaussian_splatting:OPACITY',\n        data: opacityData.buffer,\n        componentType: FLOAT,\n        type: 'SCALAR',\n        count: numSplats\n    });\n\n    // SH_DEGREE_0_COEF_0 (VEC3 float, raw DC coefficients)\n    const shDC = new Float32Array(numSplats * 3);\n    for (let i = 0; i < numSplats; i++) {\n        shDC[i * 3] = fdc0[i];\n        shDC[i * 3 + 1] = fdc1[i];\n        shDC[i * 3 + 2] = fdc2[i];\n    }\n    segments.push({\n        name: 'KHR_gaussian_splatting:SH_DEGREE_0_COEF_0',\n        data: shDC.buffer,\n        componentType: FLOAT,\n        type: 'VEC3',\n        count: numSplats\n    });\n\n    // Higher-order SH coefficients (degrees 1-3)\n    // Internal layout is channel-major: f_rest[k] for k in [0..N-1] is red,\n    // [N..2N-1] is green, [2N..3N-1] is blue, where N = coeffsPerChannel.\n    if (shDegrees > 0) {\n        const restData: Float32Array[] = [];\n        for (let k = 0; k < coeffsPerChannel; k++) {\n            restData.push(dataTable.getColumnByName(shRestNames[k])!.data as Float32Array);                     // red\n            restData.push(dataTable.getColumnByName(shRestNames[k + coeffsPerChannel])!.data as Float32Array);  // green\n            restData.push(dataTable.getColumnByName(shRestNames[k + 2 * coeffsPerChannel])!.data as Float32Array); // blue\n        }\n\n        let coefOffset = 0;\n        for (let degree = 1; degree <= shDegrees; degree++) {\n            const numCoefs = shCoefCount[degree];\n            for (let c = 0; c < numCoefs; c++) {\n                const k = coefOffset + c;\n                const rChannel = restData[k * 3];\n                const gChannel = restData[k * 3 + 1];\n                const bChannel = restData[k * 3 + 2];\n\n                const buf = new Float32Array(numSplats * 3);\n                for (let i = 0; i < numSplats; i++) {\n                    buf[i * 3] = rChannel[i];\n                    buf[i * 3 + 1] = gChannel[i];\n                    buf[i * 3 + 2] = bChannel[i];\n                }\n                segments.push({\n                    name: `KHR_gaussian_splatting:SH_DEGREE_${degree}_COEF_${c}`,\n                    data: buf.buffer,\n                    componentType: FLOAT,\n                    type: 'VEC3',\n                    count: numSplats\n                });\n            }\n            coefOffset += numCoefs;\n        }\n    }\n\n    // Compute total binary buffer size (each segment aligned to 4 bytes)\n    let totalSize = 0;\n    const offsets: number[] = [];\n    for (const seg of segments) {\n        offsets.push(totalSize);\n        totalSize += align4(seg.data.byteLength);\n    }\n\n    // Assemble the binary buffer\n    const binBuffer = new Uint8Array(totalSize);\n    for (let i = 0; i < segments.length; i++) {\n        binBuffer.set(new Uint8Array(segments[i].data), offsets[i]);\n    }\n\n    return { segments, offsets, binBuffer };\n};\n\n/**\n * Writes Gaussian splat data to a GLB file using the KHR_gaussian_splatting extension.\n *\n * @param options - Options including filename and data table to write.\n * @param fs - File system for writing the output file.\n * @ignore\n */\nconst writeGlb = async (options: WriteGlbOptions, fs: FileSystem) => {\n    const { filename } = options;\n    const dataTable = convertToSpace(options.dataTable, Transform.IDENTITY);\n    const numSplats = dataTable.numRows;\n    const shBands = getSHBands(dataTable);\n\n    const { segments, offsets, binBuffer } = buildBinaryBuffer(dataTable, numSplats, shBands);\n\n    // Build glTF JSON\n    const bufferViews: any[] = [];\n    const accessors: any[] = [];\n    const attributes: Record<string, number> = {};\n\n    for (let i = 0; i < segments.length; i++) {\n        const seg = segments[i];\n\n        bufferViews.push({\n            buffer: 0,\n            byteOffset: offsets[i],\n            byteLength: seg.data.byteLength,\n            target: ARRAY_BUFFER\n        });\n\n        const accessor: any = {\n            bufferView: i,\n            byteOffset: 0,\n            componentType: seg.componentType,\n            count: seg.count,\n            type: seg.type\n        };\n\n        if (seg.normalized) {\n            accessor.normalized = true;\n        }\n        if (seg.min) {\n            accessor.min = seg.min;\n            accessor.max = seg.max;\n        }\n\n        accessors.push(accessor);\n        attributes[seg.name] = i;\n    }\n\n    const gltf: any = {\n        asset: {\n            version: '2.0',\n            generator: `splat-transform ${version}`\n        },\n        extensionsUsed: ['KHR_gaussian_splatting'],\n        scene: 0,\n        scenes: [{ nodes: [0] }],\n        nodes: [{ mesh: 0 }],\n        buffers: [{ byteLength: binBuffer.byteLength }],\n        bufferViews,\n        accessors,\n        meshes: [{\n            primitives: [{\n                attributes,\n                mode: 0,\n                extensions: {\n                    KHR_gaussian_splatting: {\n                        kernel: 'ellipse',\n                        colorSpace: 'srgb_rec709_display',\n                        sortingMethod: 'cameraDistance',\n                        projection: 'perspective'\n                    }\n                }\n            }]\n        }]\n    };\n\n    const jsonString = JSON.stringify(gltf);\n    const jsonEncoder = new TextEncoder();\n    const jsonBytes = jsonEncoder.encode(jsonString);\n    const jsonPaddedLength = align4(jsonBytes.byteLength);\n    const binPaddedLength = align4(binBuffer.byteLength);\n\n    const totalLength = 12 + 8 + jsonPaddedLength + 8 + binPaddedLength;\n\n    const glb = new ArrayBuffer(totalLength);\n    const view = new DataView(glb);\n    const bytes = new Uint8Array(glb);\n\n    // GLB header (12 bytes)\n    view.setUint32(0, GLB_MAGIC, true);\n    view.setUint32(4, GLB_VERSION, true);\n    view.setUint32(8, totalLength, true);\n\n    // JSON chunk header (8 bytes)\n    let offset = 12;\n    view.setUint32(offset, jsonPaddedLength, true);\n    view.setUint32(offset + 4, JSON_CHUNK_TYPE, true);\n    offset += 8;\n\n    // JSON chunk data (padded with spaces per spec)\n    bytes.set(jsonBytes, offset);\n    for (let i = jsonBytes.byteLength; i < jsonPaddedLength; i++) {\n        bytes[offset + i] = 0x20; // space\n    }\n    offset += jsonPaddedLength;\n\n    // BIN chunk header (8 bytes)\n    view.setUint32(offset, binPaddedLength, true);\n    view.setUint32(offset + 4, BIN_CHUNK_TYPE, true);\n    offset += 8;\n\n    // BIN chunk data (padded with zeros per spec)\n    bytes.set(binBuffer, offset);\n\n    const writingGroup = logger.group('Writing');\n\n    // Write the GLB file\n    const writer = await fs.createWriter(filename);\n    await writer.write(new Uint8Array(glb));\n    await writer.close();\n\n    logWrittenFile(basename(filename), writer.bytesWritten);\n    writingGroup.end();\n};\n\nexport { writeGlb };\n","var index$2 = \":root {\\n  --canvas-opacity: 1;\\n}\\n\\n* {\\n  margin: 0;\\n  padding: 0;\\n  touch-action: none;\\n}\\n\\nbody {\\n  overflow: hidden;\\n  font-family: \\\"Arial\\\", sans-serif;\\n  -moz-user-select: none;\\n       user-select: none;\\n  -webkit-user-select: none;\\n  -webkit-touch-callout: none;\\n}\\n\\ncanvas {\\n  opacity: var(--canvas-opacity);\\n  position: fixed;\\n  top: 0;\\n  left: 0;\\n  width: 100%;\\n  height: 100%;\\n}\\n\\nbody::after {\\n  content: \\\"\\\";\\n  position: fixed;\\n  top: 0;\\n  left: 0;\\n  width: 1px;\\n  height: 1px;\\n  backdrop-filter: blur(1px);\\n  -webkit-backdrop-filter: blur(1px);\\n  pointer-events: none;\\n}\\n\\nbutton {\\n  -webkit-appearance: none;\\n     -moz-appearance: none;\\n          appearance: none;\\n}\\n\\n.hidden {\\n  display: none !important;\\n}\\n\\n.spacer {\\n  flex-grow: 1;\\n}\\n\\n#ui {\\n  position: fixed;\\n  top: 0;\\n  left: 0;\\n  width: 100%;\\n  height: 100%;\\n  pointer-events: none;\\n}\\n\\n#ui * {\\n  pointer-events: auto;\\n}\\n\\n.walkHint {\\n  position: absolute;\\n  top: max(60px, env(safe-area-inset-top));\\n  left: 50%;\\n  transform: translateX(-50%);\\n  background-color: rgba(0, 0, 0, 0.7);\\n  color: #fff;\\n  font-size: 14px;\\n  padding: 10px 20px;\\n  border-radius: 8px;\\n  cursor: pointer;\\n  pointer-events: auto;\\n  white-space: nowrap;\\n}\\n\\n/* branding link for third-party embeds */\\n#viewerBranding {\\n  position: absolute;\\n  top: max(16px, env(safe-area-inset-top));\\n  left: max(16px, env(safe-area-inset-left));\\n  display: flex;\\n  align-items: center;\\n  gap: 6px;\\n  text-decoration: none;\\n  white-space: nowrap;\\n  cursor: pointer;\\n  transition: color 150ms ease;\\n  color: #E0DCDD;\\n}\\n#viewerBranding:hover {\\n  color: #fff;\\n}\\n#viewerBranding > svg {\\n  height: 16px;\\n  width: auto;\\n  flex-shrink: 0;\\n  padding: 8px;\\n  border-radius: 6px;\\n  background-color: rgba(0, 0, 0, 0.3);\\n}\\n#viewerBranding > span {\\n  font-size: 14px;\\n  font-weight: bold;\\n  text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.4), 1px -1px 0 rgba(0, 0, 0, 0.4), -1px 1px 0 rgba(0, 0, 0, 0.4), 1px 1px 0 rgba(0, 0, 0, 0.4);\\n}\\n\\n/* poster */\\n#poster {\\n  display: none;\\n  position: absolute;\\n  top: 0;\\n  left: 0;\\n  width: 100%;\\n  height: 100%;\\n  background-image: var(--poster-url);\\n  background-size: cover;\\n  background-position: center;\\n  background-repeat: no-repeat;\\n}\\n\\n/* loadingWrap */\\n#loadingWrap {\\n  position: fixed;\\n  bottom: 120px;\\n  left: 50%;\\n  transform: translate(-50%, 0);\\n  width: min(380px, 100vw - 32px);\\n  display: flex;\\n  flex-direction: column;\\n  padding: 16px;\\n}\\n#loadingWrap > #loadingText {\\n  font-size: 18px;\\n  color: #fff;\\n  text-align: center;\\n  text-shadow: 0 0 4px rgba(0, 0, 0, 0.5);\\n}\\n#loadingWrap > #loadingBar {\\n  width: 100%;\\n  height: 10px;\\n  margin-top: 8px;\\n  border-radius: 4px;\\n  overflow: hidden;\\n}\\n\\n/* controlsWrap */\\n#controlsWrap {\\n  position: absolute;\\n  left: max(16px, env(safe-area-inset-left));\\n  right: max(16px, env(safe-area-inset-right));\\n  bottom: max(16px, env(safe-area-inset-bottom));\\n  display: flex;\\n  flex-direction: column;\\n}\\n#controlsWrap.faded-in {\\n  visibility: visible;\\n  opacity: 1;\\n  transition: opacity 0.5s ease-out;\\n}\\n#controlsWrap.faded-out {\\n  visibility: hidden;\\n  opacity: 0;\\n  transition: visibility 0s 0.5s, opacity 0.5s ease-out;\\n}\\n#controlsWrap > #timelineContainer {\\n  height: 30px;\\n  cursor: pointer;\\n}\\n#controlsWrap > #timelineContainer > #line {\\n  width: 100%;\\n  height: 50%;\\n  border-bottom: 4px solid #d9d9d9;\\n}\\n#controlsWrap > #timelineContainer > #handle {\\n  position: absolute;\\n  top: 16.5px;\\n  width: 12px;\\n  height: 12px;\\n  transform: translate(-50%, -50%);\\n  border: 2px solid #d9d9d9;\\n  border-radius: 50%;\\n  background-color: #FFAF50;\\n}\\n#controlsWrap > #timelineContainer > #time {\\n  position: absolute;\\n  top: 0;\\n  padding: 2px 4px;\\n  transform: translate(-50%, -100%);\\n  font-size: 12px;\\n  border-radius: 4px;\\n  color: #fff;\\n  background-color: rgba(40, 40, 40, 0.5);\\n}\\n#controlsWrap > #buttonsContainer {\\n  display: flex;\\n  gap: 8px;\\n}\\n#controlsWrap > #buttonsContainer .buttonGroup {\\n  display: flex;\\n  background-color: rgba(0, 0, 0, 0.3);\\n  border-radius: 6px;\\n}\\n#controlsWrap > #buttonsContainer .buttonGroup:not(:has(> :not(.hidden))) {\\n  display: none;\\n}\\n#controlsWrap > #buttonsContainer {\\n  /* controlButton */\\n}\\n#controlsWrap > #buttonsContainer .controlButton {\\n  width: 34px;\\n  height: 34px;\\n  padding: 0;\\n  margin: 0;\\n  border: 0;\\n  cursor: pointer;\\n  color: #E0DCDD;\\n  background-color: transparent;\\n}\\n#controlsWrap > #buttonsContainer .controlButton:hover {\\n  color: #fff;\\n}\\n#controlsWrap > #buttonsContainer .controlButton {\\n  /* icon styling */\\n}\\n#controlsWrap > #buttonsContainer .controlButton > svg {\\n  display: block;\\n  margin: auto;\\n}\\n#controlsWrap > #buttonsContainer .controlButton > svg > g.stroke {\\n  fill: none;\\n  stroke: black;\\n  stroke-width: 2;\\n  stroke-linejoin: round;\\n  opacity: 0.4;\\n}\\n#controlsWrap > #buttonsContainer .controlButton > svg > g.fill {\\n  fill: currentColor;\\n  stroke: none;\\n}\\n#controlsWrap > #buttonsContainer .controlButton {\\n  /* active highlight for simple toggle buttons (e.g. voxel overlay) */\\n}\\n#controlsWrap > #buttonsContainer .controlButton.active:not(.toggle) {\\n  color: #F60;\\n}\\n#controlsWrap > #buttonsContainer .controlButton {\\n  /* camera toggle styling */\\n}\\n#controlsWrap > #buttonsContainer .controlButton.toggle {\\n  background: linear-gradient(90deg, transparent 0%, transparent 50%, #F60 50%, #F60 100%);\\n  background-size: 200% 100%;\\n  background-position: 100% 0%;\\n  background-repeat: no-repeat;\\n  transition: background-position 0.1s ease-in-out;\\n}\\n#controlsWrap > #buttonsContainer .controlButton.toggle.left {\\n  border-radius: 4px 0px 0px 4px;\\n}\\n#controlsWrap > #buttonsContainer .controlButton.toggle.left:not(.active) {\\n  background-position: 0% 0%;\\n}\\n#controlsWrap > #buttonsContainer .controlButton.toggle.middle {\\n  border-radius: 0;\\n}\\n#controlsWrap > #buttonsContainer .controlButton.toggle.middle:not(.active) {\\n  background-position: 0% 0%;\\n}\\n#controlsWrap > #buttonsContainer .controlButton.toggle.right {\\n  border-radius: 0px 4px 4px 0px;\\n}\\n#controlsWrap > #buttonsContainer .controlButton.toggle.right:not(.active) {\\n  background-position: 200% 0%;\\n}\\n\\n/* settingsPanel */\\n#settingsPanel {\\n  position: fixed;\\n  right: max(16px, env(safe-area-inset-right));\\n  bottom: calc(max(16px, env(safe-area-inset-bottom)) + 70px);\\n  padding: 12px;\\n  border-radius: 16px;\\n  border: 1px solid rgba(255, 255, 255, 0.08);\\n  display: flex;\\n  flex-direction: column;\\n  align-items: flex-end;\\n  gap: 4px;\\n  font-size: 14px;\\n  color: #E0DCDD;\\n  background-color: rgba(51, 51, 51, 0.8);\\n  backdrop-filter: blur(20px);\\n  -webkit-backdrop-filter: blur(20px);\\n}\\n#settingsPanel > .settingsRow {\\n  display: flex;\\n  align-items: center;\\n  justify-content: space-between;\\n  gap: 4px;\\n  width: 100%;\\n}\\n#settingsPanel > .settingsRow > button {\\n  flex-grow: 1;\\n  height: 34px;\\n  padding: 0 20px;\\n  border: 1px solid rgba(255, 255, 255, 0.1);\\n  border-radius: 8px;\\n  font-size: 13px;\\n  cursor: pointer;\\n  color: #AAA;\\n  background-color: rgba(255, 255, 255, 0.04);\\n  transition: background-color 250ms ease, color 250ms ease;\\n}\\n#settingsPanel > .settingsRow > button:hover {\\n  color: #fff;\\n  background-color: rgba(255, 255, 255, 0.1);\\n}\\n#settingsPanel > .settingsRow > div {\\n  height: 34px;\\n  display: flex;\\n  align-items: center;\\n  padding: 0 8px;\\n  cursor: pointer;\\n  color: #AAA;\\n}\\n#settingsPanel > .settingsRow > div.toggleSwitch {\\n  padding: 0 4px;\\n}\\n#settingsPanel > .settingsRow > div.toggleSwitch .toggleTrack {\\n  width: 36px;\\n  height: 20px;\\n  border-radius: 10px;\\n  background-color: rgba(255, 255, 255, 0.15);\\n  position: relative;\\n  transition: background-color 200ms ease;\\n}\\n#settingsPanel > .settingsRow > div.toggleSwitch .toggleTrack .toggleThumb {\\n  width: 16px;\\n  height: 16px;\\n  border-radius: 50%;\\n  background-color: #777;\\n  position: absolute;\\n  top: 2px;\\n  left: 2px;\\n  transition: transform 200ms ease, background-color 200ms ease;\\n}\\n#settingsPanel > .settingsRow > div.toggleSwitch.active .toggleTrack {\\n  background-color: rgba(255, 102, 0, 0.35);\\n}\\n#settingsPanel > .settingsRow > div.toggleSwitch.active .toggleTrack .toggleThumb {\\n  transform: translateX(16px);\\n  background-color: #F60;\\n}\\n#settingsPanel > .settingsRow > div:hover {\\n  color: #E0DCDD;\\n}\\n#settingsPanel > .divider {\\n  width: 100%;\\n  height: 1px;\\n  margin: 8px 0;\\n  background-color: rgba(255, 255, 255, 0.08);\\n}\\n\\n/* infoPanel */\\n#infoPanel {\\n  position: fixed;\\n  top: 0;\\n  left: 0;\\n  width: 100%;\\n  height: 100%;\\n  background-color: rgba(0, 0, 0, 0.4);\\n  backdrop-filter: blur(2px);\\n}\\n#infoPanel > #infoPanelContent {\\n  position: absolute;\\n  top: 50%;\\n  left: 50%;\\n  transform: translate(-50%, -50%);\\n  width: 360px;\\n  height: min(80vh, 640px);\\n  border-radius: 16px;\\n  border: 1px solid rgba(255, 255, 255, 0.1);\\n  display: flex;\\n  flex-direction: column;\\n  overflow: hidden;\\n  color: #E0DCDD;\\n  background-color: rgba(51, 51, 51, 0.85);\\n  backdrop-filter: blur(20px);\\n  -webkit-backdrop-filter: blur(20px);\\n}\\n#infoPanel > #infoPanelContent > #viewerTitle {\\n  display: flex;\\n  align-items: center;\\n  justify-content: center;\\n  gap: 8px;\\n  padding: 14px 16px;\\n  flex-shrink: 0;\\n  background-color: rgba(0, 0, 0, 0.15);\\n  border-bottom: 1px solid rgba(255, 255, 255, 0.06);\\n  text-decoration: none;\\n  white-space: nowrap;\\n  color: #E0DCDD;\\n}\\n#infoPanel > #infoPanelContent > #viewerTitle > svg {\\n  height: 20px;\\n  width: auto;\\n  flex-shrink: 0;\\n}\\n#infoPanel > #infoPanelContent > #viewerTitle > svg > g.stroke {\\n  fill: black;\\n  stroke: black;\\n  stroke-width: 2;\\n  stroke-linejoin: round;\\n  opacity: 0.4;\\n}\\n#infoPanel > #infoPanelContent > #viewerTitle > svg > g.fill {\\n  fill: #F60;\\n  stroke: none;\\n}\\n#infoPanel > #infoPanelContent > #viewerTitle > .title-name {\\n  font-size: 14px;\\n  font-weight: bold;\\n}\\n#infoPanel > #infoPanelContent > #viewerTitle > .title-version {\\n  font-size: 12px;\\n  font-weight: normal;\\n  color: #AAA;\\n  margin-left: -2px;\\n}\\n#infoPanel > #infoPanelContent > #viewerTitle[href] {\\n  cursor: pointer;\\n  transition: color 150ms ease;\\n}\\n#infoPanel > #infoPanelContent > #viewerTitle[href]:hover {\\n  color: #fff;\\n}\\n#infoPanel > #infoPanelContent > #infoPanels {\\n  padding: 16px;\\n  flex: 1 1 auto;\\n  min-height: 0;\\n  overflow-y: auto;\\n}\\n#infoPanel > #infoPanelContent > #infoPanels::-webkit-scrollbar {\\n  width: 6px;\\n}\\n#infoPanel > #infoPanelContent > #infoPanels::-webkit-scrollbar-track {\\n  background: transparent;\\n}\\n#infoPanel > #infoPanelContent > #infoPanels::-webkit-scrollbar-thumb {\\n  background-color: rgba(255, 255, 255, 0.12);\\n  border-radius: 3px;\\n}\\n#infoPanel > #infoPanelContent > #infoPanels h1 {\\n  font-size: 11px;\\n  font-weight: bold;\\n  text-transform: uppercase;\\n  letter-spacing: 1px;\\n  padding: 4px 0 8px 0;\\n  color: #F60;\\n}\\n#infoPanel > #infoPanelContent > #infoPanels .control-item {\\n  display: flex;\\n  justify-content: space-between;\\n  align-items: center;\\n  gap: 32px;\\n  padding: 5px 8px;\\n  margin: 0 -8px;\\n  border-radius: 6px;\\n  font-size: 13px;\\n}\\n#infoPanel > #infoPanelContent > #infoPanels .control-item > .control-action {\\n  text-align: left;\\n}\\n#infoPanel > #infoPanelContent > #infoPanels .control-item > .control-key {\\n  text-align: right;\\n  color: #AAA;\\n  font-size: 12px;\\n}\\n#infoPanel > #infoPanelContent > #infoPanels .control-item:nth-child(odd) {\\n  background-color: rgba(255, 255, 255, 0.03);\\n}\\n#infoPanel > #infoPanelContent > #infoPanels .control-spacer {\\n  margin: 14px 0;\\n}\\n#infoPanel > #infoPanelContent > #tabs {\\n  display: flex;\\n  gap: 24px;\\n  padding: 8px 16px;\\n  justify-content: center;\\n  flex-shrink: 0;\\n  border-top: 1px solid rgba(255, 255, 255, 0.06);\\n}\\n#infoPanel > #infoPanelContent > #tabs > .tab {\\n  padding: 8px 4px;\\n  border-bottom: 2px solid transparent;\\n  cursor: pointer;\\n  font-weight: bold;\\n  font-size: 13px;\\n  color: #AAA;\\n  transition: color 150ms ease, border-color 150ms ease;\\n}\\n#infoPanel > #infoPanelContent > #tabs > .tab:hover {\\n  color: #fff;\\n}\\n#infoPanel > #infoPanelContent > #tabs > .tab.active {\\n  color: #fff;\\n  border-bottom-color: #F60;\\n}\\n\\n#joystickBase {\\n  position: absolute;\\n  width: 56px;\\n  height: 100px;\\n  transform: translate(-50%, -50%);\\n  border-radius: 28px;\\n  touch-action: none;\\n  background: linear-gradient(180deg, rgba(0, 0, 0, 0.2666666667) 0%, rgba(0, 0, 0, 0) 30%, rgba(0, 0, 0, 0) 70%, rgba(0, 0, 0, 0.2666666667) 100%);\\n  background-color: rgba(0, 0, 0, 0.2);\\n  border: 2px solid rgba(255, 255, 255, 0.2);\\n  transition: width 0.2s ease, height 0.2s ease, border-radius 0.2s ease;\\n}\\n#joystickBase > #joystick {\\n  position: absolute;\\n  left: 8px;\\n  width: 40px;\\n  height: 40px;\\n  border-radius: 50%;\\n  touch-action: none;\\n  background-color: rgba(255, 255, 255, 0.5333333333);\\n  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);\\n  transition: left 0.1s ease;\\n}\\n#joystickBase.mode-2d {\\n  width: 100px;\\n  height: 100px;\\n  border-radius: 50px;\\n  background: radial-gradient(circle, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0.2666666667) 100%);\\n  background-color: rgba(0, 0, 0, 0.2);\\n}\\n#joystickBase.mode-2d > #joystick {\\n  left: 30px;\\n}\\n\\n/* xr WebGL-required modal */\\n#xrModal {\\n  position: fixed;\\n  top: 0;\\n  left: 0;\\n  width: 100%;\\n  height: 100%;\\n  background-color: rgba(0, 0, 0, 0.4);\\n  backdrop-filter: blur(2px);\\n  display: flex;\\n  align-items: center;\\n  justify-content: center;\\n}\\n#xrModal > #xrModalContent {\\n  width: min(360px, 100vw - 32px);\\n  padding: 20px;\\n  border-radius: 16px;\\n  border: 1px solid rgba(255, 255, 255, 0.1);\\n  color: #E0DCDD;\\n  background-color: rgba(51, 51, 51, 0.9);\\n  backdrop-filter: blur(20px);\\n  -webkit-backdrop-filter: blur(20px);\\n}\\n#xrModal > #xrModalContent > h2 {\\n  font-size: 16px;\\n  font-weight: bold;\\n  color: #fff;\\n  margin-bottom: 12px;\\n}\\n#xrModal > #xrModalContent > p {\\n  font-size: 13px;\\n  line-height: 1.4;\\n  color: #E0DCDD;\\n  margin-bottom: 16px;\\n}\\n#xrModal > #xrModalContent > #xrModalButtons {\\n  display: flex;\\n  justify-content: flex-end;\\n  gap: 8px;\\n}\\n#xrModal > #xrModalContent > #xrModalButtons > button {\\n  height: 34px;\\n  padding: 0 20px;\\n  border: 1px solid rgba(255, 255, 255, 0.1);\\n  border-radius: 8px;\\n  font-size: 13px;\\n  cursor: pointer;\\n  color: #AAA;\\n  background-color: rgba(255, 255, 255, 0.04);\\n  transition: background-color 250ms ease, color 250ms ease;\\n}\\n#xrModal > #xrModalContent > #xrModalButtons > button:hover {\\n  color: #fff;\\n  background-color: rgba(255, 255, 255, 0.1);\\n}\\n#xrModal > #xrModalContent > #xrModalButtons > button#xrModalOk {\\n  color: #fff;\\n  background-color: rgba(255, 102, 0, 0.7);\\n  border-color: rgba(255, 102, 0, 0.8);\\n}\\n#xrModal > #xrModalContent > #xrModalButtons > button#xrModalOk:hover {\\n  background-color: #F60;\\n}\\n\\n#tooltip {\\n  display: none;\\n  position: absolute;\\n  border-radius: 4px;\\n  padding: 4px 4px;\\n  font-size: 12px;\\n  color: #E0DCDD;\\n  background-color: #282828;\\n}\\n\\n#annotations {\\n  position: fixed;\\n  top: 0;\\n  left: 0;\\n  width: 100%;\\n  height: 100%;\\n  pointer-events: none;\\n  z-index: -1;\\n}\\n\\n#annotations * {\\n  pointer-events: auto;\\n}\\n\\n/* annotationNav */\\n#annotationNav {\\n  pointer-events: none;\\n}\\n#annotationNav.faded-in {\\n  visibility: visible;\\n  opacity: 1;\\n  transition: opacity 0.5s ease-out;\\n}\\n#annotationNav.faded-out {\\n  visibility: hidden;\\n  opacity: 0;\\n  transition: visibility 0s 0.5s, opacity 0.5s ease-out;\\n}\\n#annotationNav > button {\\n  pointer-events: auto;\\n  -webkit-appearance: none;\\n     -moz-appearance: none;\\n          appearance: none;\\n  border: 0;\\n  padding: 0;\\n  margin: 0;\\n  cursor: pointer;\\n  display: flex;\\n  align-items: center;\\n  justify-content: center;\\n  color: #E0DCDD;\\n  background-color: rgba(0, 0, 0, 0.3);\\n}\\n#annotationNav > button:hover {\\n  color: #fff;\\n  background-color: rgba(0, 0, 0, 0.5);\\n}\\n#annotationNav > button > svg {\\n  display: block;\\n}\\n#annotationNav > button > svg > g.stroke {\\n  fill: none;\\n  stroke: black;\\n  stroke-width: 3;\\n  stroke-linecap: round;\\n  stroke-linejoin: round;\\n  opacity: 0.4;\\n}\\n#annotationNav > button > svg > g.fill {\\n  fill: none;\\n  stroke: currentColor;\\n  stroke-width: 2;\\n  stroke-linecap: round;\\n  stroke-linejoin: round;\\n}\\n#annotationNav.desktop {\\n  position: absolute;\\n  top: max(16px, env(safe-area-inset-top));\\n  left: 50%;\\n  transform: translateX(-50%);\\n  display: flex;\\n  align-items: center;\\n  gap: 0;\\n  border-radius: 6px;\\n  overflow: hidden;\\n  background-color: rgba(0, 0, 0, 0.6);\\n}\\n#annotationNav.desktop > button {\\n  width: 34px;\\n  height: 34px;\\n  background-color: transparent;\\n}\\n#annotationNav.desktop > button:hover {\\n  background-color: rgba(255, 255, 255, 0.1);\\n}\\n#annotationNav.desktop > #annotationInfo {\\n  pointer-events: none;\\n  display: flex;\\n  align-items: center;\\n  justify-content: center;\\n  padding: 0 12px;\\n  white-space: nowrap;\\n  width: 240px;\\n}\\n#annotationNav.desktop > #annotationInfo > #annotationNavTitle {\\n  font-size: 14px;\\n  color: #fff;\\n  overflow: hidden;\\n  text-overflow: ellipsis;\\n}\\n#annotationNav.touch {\\n  position: fixed;\\n  top: 0;\\n  left: 0;\\n  width: 100%;\\n  height: 100%;\\n}\\n#annotationNav.touch > #annotationInfo {\\n  display: none;\\n}\\n#annotationNav.touch > button {\\n  position: absolute;\\n  top: 50%;\\n  transform: translateY(-50%);\\n  width: 44px;\\n  height: 80px;\\n  background-color: rgba(0, 0, 0, 0.3);\\n}\\n#annotationNav.touch > button:active {\\n  background-color: rgba(0, 0, 0, 0.4);\\n}\\n#annotationNav.touch > #annotationPrev {\\n  left: max(0px, env(safe-area-inset-left));\\n  border-radius: 0 6px 6px 0;\\n}\\n#annotationNav.touch > #annotationNext {\\n  right: max(0px, env(safe-area-inset-right));\\n  border-radius: 6px 0 0 6px;\\n}\\n\\n/*# sourceMappingURL=index.css.map */\";\n\nvar index$1 = \"<!DOCTYPE html>\\n<html lang=\\\"en\\\">\\n    <head>\\n        <title>SuperSplat Viewer</title>\\n        <meta charset=\\\"UTF-8\\\">\\n        <meta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover\\\">\\n        <base href=\\\"\\\">\\n        <link rel=\\\"stylesheet\\\" href=\\\"./index.css\\\">\\n        <script type=\\\"module\\\">\\n            const createImage = (url) => {\\n                const img = new Image();\\n                img.src = url;\\n                return img;\\n            };\\n\\n            const url = new URL(location.href);\\n\\n            const posterUrl = url.searchParams.get('poster');\\n            const skyboxUrl = url.searchParams.get('skybox');\\n            const collisionUrl = url.searchParams.get('collision') ?? url.searchParams.get('voxel');\\n            const settingsUrl = url.searchParams.has('settings') ? url.searchParams.get('settings') : './settings.json';\\n            const contentUrl = url.searchParams.has('content') ? url.searchParams.get('content') : './scene.compressed.ply';\\n\\n            const renderer = url.searchParams.has('webgl') ? 'webgl' : 'webgpu';\\n\\n            const budgetParam = url.searchParams.get('budget');\\n            const budget = budgetParam !== null ? Number(budgetParam) : undefined;\\n\\n            const sseConfig = {\\n                poster: posterUrl && createImage(posterUrl),\\n                skyboxUrl,\\n                collisionUrl,\\n                contentUrl,\\n                contents: fetch(contentUrl),\\n                noui: url.searchParams.has('noui'),\\n                noanim: url.searchParams.has('noanim'),\\n                nofx: url.searchParams.has('nofx'),\\n                hpr: url.searchParams.has('hpr') ? ['', '1', 'true', 'enable'].includes(url.searchParams.get('hpr')) : undefined,\\n                ministats: url.searchParams.has('ministats'),\\n                colorize: url.searchParams.has('colorize'),\\n                renderer,\\n                aa: url.searchParams.has('aa'),\\n                budget,\\n                heatmap: url.searchParams.has('heatmap'),\\n                fullload: url.searchParams.has('fullload'),\\n                debug: url.searchParams.has('debug'),\\n            };\\n\\n            window.sse = {\\n                config: sseConfig,\\n                settings: fetch(settingsUrl).then(response => response.json())\\n            };\\n        </script>\\n    </head>\\n    <body>\\n        <canvas id=\\\"application-canvas\\\"></canvas>\\n\\n        <div id=\\\"ui\\\">\\n            <div id=\\\"poster\\\"></div>\\n\\n            <!-- SuperSplat Branding -->\\n            <a id=\\\"viewerBranding\\\" class=\\\"hidden\\\" target=\\\"_blank\\\" rel=\\\"noopener noreferrer\\\">\\n                <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" viewBox=\\\"64 64 384 384\\\" role=\\\"img\\\" aria-label=\\\"SuperSplat\\\">\\n                    <path\\n                        fill=\\\"#F26722\\\"\\n                        d=\\\"M129.83,217c9.75,0,17.64-7.9,17.64-17.64s-7.9-17.64-17.64-17.64-17.64,7.9-17.64,17.64,7.9,17.64,17.64,17.64Z\\\"\\n                    />\\n                    <path\\n                        fill=\\\"#F26722\\\"\\n                        d=\\\"M388.74,253.94c-12.46,0-22.57,10.11-22.57,22.57s10.11,22.57,22.57,22.57,22.57-10.11,22.57-22.57-10.11-22.57-22.57-22.57h0Z\\\"\\n                    />\\n                    <path\\n                        fill=\\\"#F26722\\\"\\n                        d=\\\"M345.26,161.1h.02c.37-.05.65-.22.97-.33,16.78-2.32,29.75-16.57,29.75-33.99,0-19.04-15.43-34.46-34.46-34.46s-34.46,15.43-34.46,34.46c0,4.29.88,8.35,2.32,12.14.04.12-.01.25.04.38,10.55,29.18-22.33,23.62-39.07,20.74-.49-.09-.88-.07-1.32-.11-4.27-.56-8.59-.97-13.03-.97-53.93,0-97.64,43.71-97.64,97.64,0,9.84,1.48,19.32,4.2,28.28.04.1,0,.17.05.27,8.97,30.15-14.83,25.49-25.52,25.69-1.04-.13-2.09-.32-3.18-.32-13.51,0-24.45,10.94-24.45,24.45s10.94,24.45,24.45,24.45c11.69,0,21.44-8.22,23.85-19.19h.02c6.31-26.57,25.9-18.02,31.15-12.67.2.2.4.26.59.42,17.44,16.25,40.75,26.26,66.47,26.26.67,0,1.34-.09,2.01-.1.66.01,1.31.04,2.04.04,9.7-.04,17.82,10.91,4.94,29.68h.13c-4.42,6.01-7.1,13.36-7.1,21.41,0,20.09,16.29,36.39,36.39,36.39s36.39-16.29,36.39-36.39c0-15.4-9.61-28.49-23.12-33.81-.32-.15-.61-.29-.98-.45-12.28-4.94-25.43-17.69-6.89-27.1l-.04-.1c31.93-16.06,53.88-49.02,53.88-87.2,0-21.15-6.8-40.68-18.23-56.66-.13-.23-.23-.47-.44-.74-23.15-31.67-2.37-36.07,10.3-38.09h-.01Z\\\"\\n                    />\\n                    <path\\n                        fill=\\\"#fff\\\"\\n                        d=\\\"M230.79,284.71c0,7.95-6.44,14.38-14.38,14.38s-14.38-6.44-14.38-14.38v-22.95c0-7.95,6.44-14.38,14.38-14.38s14.38,6.44,14.38,14.38v22.95Z\\\"\\n                    />\\n                    <path\\n                        fill=\\\"#fff\\\"\\n                        d=\\\"M309.78,284.71c0,7.95-6.44,14.38-14.38,14.38s-14.38-6.44-14.38-14.38v-22.95c0-7.95,6.44-14.38,14.38-14.38s14.38,6.44,14.38,14.38v22.95Z\\\"\\n                    />\\n                </svg>\\n                <span>SuperSplat</span>\\n            </a>\\n\\n            <!-- Loading Indicator -->\\n            <div id=\\\"loadingWrap\\\">\\n                <div id=\\\"loadingText\\\"></div>\\n                <div id=\\\"loadingBar\\\"></div>\\n            </div>\\n\\n            <div id=\\\"controlsWrap\\\" class=\\\"hidden\\\">\\n\\n                <!-- Timeline Panel -->\\n                <div id=\\\"timelineContainer\\\" class=\\\"hidden\\\">\\n                    <div id=\\\"line\\\"></div>\\n                    <div id=\\\"handle\\\"></div>\\n                    <div id=\\\"time\\\" class=\\\"hidden\\\">0:00</div>\\n                </div>\\n\\n                <!-- Buttons Panel -->\\n                <div id=\\\"buttonsContainer\\\">\\n                    <div class=\\\"buttonGroup\\\">\\n                        <button id=\\\"play\\\" class=\\\"controlButton hidden\\\">\\n                            <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\">\\n                                <g class='stroke'><use href=\\\"#playIcon\\\"/></g>\\n                                <g class='fill'><use href=\\\"#playIcon\\\"/></g>\\n                            </svg>\\n                        </button>\\n                        <button id=\\\"pause\\\" class=\\\"controlButton hidden\\\">\\n                            <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24px\\\" height=\\\"24px\\\">\\n                                <g class='stroke'><use href=\\\"#pauseIcon\\\"/></g>\\n                                <g class='fill'><use href=\\\"#pauseIcon\\\"/></g>\\n                            </svg>\\n                        </button>\\n                    </div>\\n\\n                    <div class=\\\"spacer\\\"></div>\\n\\n                    <div class=\\\"buttonGroup\\\">\\n                        <button id=\\\"orbitCamera\\\" class=\\\"controlButton toggle left\\\">\\n                            <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\">\\n                                <g class='stroke'><use href=\\\"#orbitIcon\\\"/></g>\\n                                <g class='fill'><use href=\\\"#orbitIcon\\\"/></g>\\n                            </svg>\\n                        </button>\\n                        <button id=\\\"flyCamera\\\" class=\\\"controlButton toggle right\\\">\\n                            <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\">\\n                                <g class='stroke'><use href=\\\"#flyIcon\\\"/></g>\\n                                <g class='fill'><use href=\\\"#flyIcon\\\"/></g>\\n                            </svg>\\n                        </button>\\n                        <button id=\\\"fpsCamera\\\" class=\\\"controlButton toggle right hidden\\\">\\n                            <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\">\\n                                <g class='stroke'><use href=\\\"#walkIcon\\\"/></g>\\n                                <g class='fill'><use href=\\\"#walkIcon\\\"/></g>\\n                            </svg>\\n                        </button>\\n                    </div>\\n\\n                    <div class=\\\"buttonGroup\\\">\\n                        <button id=\\\"arMode\\\" class=\\\"controlButton hidden\\\">\\n                            <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\">\\n                                <g class='stroke'><use href=\\\"#arIcon\\\"/></g>\\n                                <g class='fill'><use href=\\\"#arIcon\\\"/></g>\\n                            </svg>\\n                        </button>\\n                        <button id=\\\"vrMode\\\" class=\\\"controlButton hidden\\\">\\n                            <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\">\\n                                <g class='stroke'><use href=\\\"#vrIcon\\\"/></g>\\n                                <g class='fill'><use href=\\\"#vrIcon\\\"/></g>\\n                            </svg>\\n                        </button>\\n\\n                        <button id=\\\"showCollision\\\" class=\\\"controlButton hidden\\\">\\n                            <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\">\\n                                <g class='stroke'><use href=\\\"#voxelIcon\\\"/></g>\\n                                <g class='fill'><use href=\\\"#voxelIcon\\\"/></g>\\n                            </svg>\\n                        </button>\\n\\n                        <button id=\\\"info\\\" class=\\\"controlButton\\\">\\n                            <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\">\\n                                <g class='stroke'><use href=\\\"#infoIcon\\\"/></g>\\n                                <g class='fill'><use href=\\\"#infoIcon\\\"/></g>\\n                            </svg>\\n                        </button>\\n                        <button id=\\\"settings\\\" class=\\\"controlButton\\\">\\n                            <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\">\\n                                <g class='stroke'><use href=\\\"#settingsIcon\\\"/></g>\\n                                <g class='fill'><use href=\\\"#settingsIcon\\\"/></g>\\n                            </svg>\\n                        </button>\\n\\n                        <button id=\\\"enterFullscreen\\\" class=\\\"controlButton\\\">\\n                            <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\">\\n                                <g class='stroke'><use href=\\\"#enterFullscreenIcon\\\"/></g>\\n                                <g class='fill'><use href=\\\"#enterFullscreenIcon\\\"/></g>\\n                            </svg>\\n                        </button>\\n                        <button id=\\\"exitFullscreen\\\" class=\\\"controlButton hidden\\\">\\n                            <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"24\\\" height=\\\"24\\\">\\n                                <g class='stroke'><use href=\\\"#exitFullscreenIcon\\\"/></g>\\n                                <g class='fill'><use href=\\\"#exitFullscreenIcon\\\"/></g>\\n                            </svg>\\n                        </button>\\n                    </div>\\n                </div>\\n            </div>\\n\\n            <div id=\\\"walkHint\\\" class=\\\"walkHint hidden\\\"></div>\\n\\n            <!-- Settings Panel -->\\n            <div id=\\\"settingsPanel\\\" class=\\\"hidden\\\">\\n                <div id=\\\"performanceModeRow\\\" class=\\\"settingsRow\\\">\\n                    <div id=\\\"performanceModeOption\\\" data-i18n=\\\"settings.performance-mode\\\">Performance Mode</div>\\n                    <div id=\\\"performanceModeCheck\\\" class=\\\"toggleSwitch\\\"><div class=\\\"toggleTrack\\\"><div class=\\\"toggleThumb\\\"></div></div></div>\\n                </div>\\n                <div id=\\\"gamingControlsDivider\\\" class=\\\"divider\\\"></div>\\n                <div id=\\\"gamingControlsRow\\\" class=\\\"settingsRow\\\">\\n                    <div id=\\\"gamingControlsOption\\\" data-i18n=\\\"settings.gaming-controls\\\">Gaming Controls</div>\\n                    <div id=\\\"gamingControlsCheck\\\" class=\\\"toggleSwitch\\\"><div class=\\\"toggleTrack\\\"><div class=\\\"toggleThumb\\\"></div></div></div>\\n                </div>\\n                <div class=\\\"divider\\\"></div>\\n                <div class=\\\"settingsRow\\\">\\n                    <button id=\\\"frame\\\" data-i18n=\\\"settings.frame\\\">Frame</button>\\n                    <button id=\\\"reset\\\" data-i18n=\\\"settings.reset\\\">Reset</button>\\n                </div>\\n            </div>\\n\\n            <!-- Info Panel -->\\n            <div id=\\\"infoPanel\\\" class=\\\"hidden\\\">\\n                <div id=\\\"infoPanelContent\\\" onpointerdown=\\\"event.stopPropagation()\\\" onwheel=\\\"event.stopPropagation()\\\">\\n                    <a id=\\\"viewerTitle\\\" target=\\\"_blank\\\" rel=\\\"noopener noreferrer\\\">\\n                        <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"20\\\" height=\\\"20\\\" viewBox=\\\"0 0 32 32\\\">\\n                            <g class='stroke'><use href=\\\"#supersplatIcon\\\"/></g>\\n                            <g class='fill'><use href=\\\"#supersplatIcon\\\"/></g>\\n                        </svg>\\n                        <span class=\\\"title-name\\\">SuperSplat Viewer</span>\\n                        <span class=\\\"title-version\\\">v<span id=\\\"appVersionLabel\\\"></span></span>\\n                    </a>\\n                    <div id=\\\"infoPanels\\\">\\n                        <div id=\\\"desktopInfoPanel\\\">\\n                            <div class=\\\"control-spacer\\\"></div>\\n                            <h1 data-i18n=\\\"help.section.orbit\\\">Orbit Mode</h1>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.orbit\\\">Orbit</span>\\n                                <span class=\\\"control-key\\\" data-i18n=\\\"help.key.left-click-drag\\\">Left Click + Drag</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.pan\\\">Pan</span>\\n                                <span class=\\\"control-key\\\" data-i18n=\\\"help.key.right-click-drag\\\">Right Click + Drag</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.zoom\\\">Zoom</span>\\n                                <span class=\\\"control-key\\\" data-i18n=\\\"help.key.mouse-wheel\\\">Mouse Wheel</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.set-focus\\\">Set Focus</span>\\n                                <span class=\\\"control-key\\\" data-i18n=\\\"help.key.left-click\\\">Left Click</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.fly-to-point\\\">Fly to Point</span>\\n                                <span class=\\\"control-key\\\" data-i18n=\\\"help.key.double-click\\\">Double-click</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.frame-scene\\\">Frame Scene</span>\\n                                <span class=\\\"control-key\\\">F</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.reset-camera\\\">Reset Camera</span>\\n                                <span class=\\\"control-key\\\">R</span>\\n                            </div>\\n                            <div class=\\\"control-spacer\\\"></div>\\n                            <h1 data-i18n=\\\"help.section.fly\\\">Fly Mode</h1>\\n                            <div id=\\\"desktopFlyClickToFly\\\">\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.fly-to\\\">Fly To</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.left-click\\\">Left Click</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.look-around\\\">Look Around</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.left-click-drag\\\">Left Click + Drag</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.pan\\\">Pan</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.right-click-drag\\\">Right Click + Drag</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.move\\\">Move</span>\\n                                    <span class=\\\"control-key\\\">W,S,A,D</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.run-slow\\\">Run / Slow</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.shift-ctrl\\\">Shift / Ctrl</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.focus-point\\\">Focus Point</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.double-click\\\">Double-click</span>\\n                                </div>\\n                            </div>\\n                            <div id=\\\"desktopFlyGamingControls\\\" class=\\\"hidden\\\">\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.look-around\\\">Look Around</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.mouse\\\">Mouse</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.move\\\">Move</span>\\n                                    <span class=\\\"control-key\\\">W,S,A,D</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.vertical\\\">Vertical</span>\\n                                    <span class=\\\"control-key\\\">Q,E</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.run-slow\\\">Run / Slow</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.shift-ctrl\\\">Shift / Ctrl</span>\\n                                </div>\\n                            </div>\\n                            <div class=\\\"control-spacer\\\"></div>\\n                            <h1 data-i18n=\\\"help.section.walk\\\">Walk Mode</h1>\\n                            <div id=\\\"desktopClickToWalk\\\">\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.walk-to\\\">Walk To</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.left-click\\\">Left Click</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.look-around\\\">Look Around</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.left-click-drag\\\">Left Click + Drag</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.run-slow\\\">Run / Slow</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.shift-ctrl\\\">Shift / Ctrl</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.fly-to-point\\\">Fly to Point</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.double-click\\\">Double-click</span>\\n                                </div>\\n                            </div>\\n                            <div id=\\\"desktopGamingControls\\\">\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.look-around\\\">Look Around</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.mouse\\\">Mouse</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.move\\\">Move</span>\\n                                    <span class=\\\"control-key\\\">W,S,A,D</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.jump\\\">Jump</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.space\\\">Space</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.run-slow\\\">Run / Slow</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.shift-ctrl\\\">Shift / Ctrl</span>\\n                                </div>\\n                            </div>\\n                            <div class=\\\"control-spacer\\\"></div>\\n                            <h1 data-i18n=\\\"help.section.modes\\\">Mode Switching</h1>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.orbit-mode\\\">Orbit Mode</span>\\n                                <span class=\\\"control-key\\\">1</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.fly-mode\\\">Fly Mode</span>\\n                                <span class=\\\"control-key\\\">2</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.toggle-walk\\\">Toggle Walk</span>\\n                                <span class=\\\"control-key\\\">3</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.toggle-gaming\\\">Toggle Gaming Controls</span>\\n                                <span class=\\\"control-key\\\">G</span>\\n                            </div>\\n                            <div id=\\\"desktopShowCollisionHelp\\\" class=\\\"control-item hidden\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.show-collision\\\">Show Collision</span>\\n                                <span class=\\\"control-key\\\">V</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.play-pause\\\">Play / Pause</span>\\n                                <span class=\\\"control-key\\\" data-i18n=\\\"help.key.space\\\">Space</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.toggle-help\\\">Toggle Help</span>\\n                                <span class=\\\"control-key\\\">H</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.exit-cancel\\\">Exit / Cancel</span>\\n                                <span class=\\\"control-key\\\" data-i18n=\\\"help.key.esc\\\">Esc</span>\\n                            </div>\\n                        </div>\\n                        <div id=\\\"touchInfoPanel\\\" class=\\\"hidden\\\">\\n                            <div class=\\\"control-spacer\\\"></div>\\n                            <h1 data-i18n=\\\"help.section.orbit\\\">Orbit Mode</h1>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.orbit\\\">Orbit</span>\\n                                <span class=\\\"control-key\\\" data-i18n=\\\"help.key.one-finger-drag\\\">One Finger Drag</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.pan\\\">Pan</span>\\n                                <span class=\\\"control-key\\\" data-i18n=\\\"help.key.two-finger-drag\\\">Two Finger Drag</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.zoom\\\">Zoom</span>\\n                                <span class=\\\"control-key\\\" data-i18n=\\\"help.key.pinch\\\">Pinch</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.set-focus\\\">Set Focus</span>\\n                                <span class=\\\"control-key\\\" data-i18n=\\\"help.key.tap\\\">Tap</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\" data-i18n=\\\"help.action.fly-to-point\\\">Fly to Point</span>\\n                                <span class=\\\"control-key\\\" data-i18n=\\\"help.key.double-tap\\\">Double-tap</span>\\n                            </div>\\n                            <div class=\\\"control-spacer\\\"></div>\\n                            <h1 data-i18n=\\\"help.section.fly\\\">Fly Mode</h1>\\n                            <div id=\\\"touchFlyClickToWalk\\\">\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.fly-to\\\">Fly To</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.tap\\\">Tap</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.look-around\\\">Look Around</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.touch-drag\\\">Touch + Drag</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.move\\\">Move</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.pinch-two-finger\\\">Pinch / Two Finger Drag</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.focus-point\\\">Focus Point</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.double-tap\\\">Double-tap</span>\\n                                </div>\\n                            </div>\\n                            <div id=\\\"touchFlyGamingControls\\\" class=\\\"hidden\\\">\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.look-around\\\">Look Around</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.touch-drag\\\">Touch + Drag</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.move\\\">Move</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.joystick\\\">Joystick</span>\\n                                </div>\\n                            </div>\\n                            <div class=\\\"control-spacer\\\"></div>\\n                            <h1 data-i18n=\\\"help.section.walk\\\">Walk Mode</h1>\\n                            <div id=\\\"touchClickToWalk\\\">\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.walk-to\\\">Walk To</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.tap\\\">Tap</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.look-around\\\">Look Around</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.touch-drag\\\">Touch + Drag</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.fly-to-point\\\">Fly to Point</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.double-tap\\\">Double-tap</span>\\n                                </div>\\n                            </div>\\n                            <div id=\\\"touchGamingControls\\\" class=\\\"hidden\\\">\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.look-around\\\">Look Around</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.touch-drag\\\">Touch + Drag</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.move\\\">Move</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.joystick\\\">Joystick</span>\\n                                </div>\\n                                <div class=\\\"control-item\\\">\\n                                    <span class=\\\"control-action\\\" data-i18n=\\\"help.action.jump\\\">Jump</span>\\n                                    <span class=\\\"control-key\\\" data-i18n=\\\"help.key.tap\\\">Tap</span>\\n                                </div>\\n                            </div>\\n                        </div>\\n                    </div>\\n                    <div id=\\\"tabs\\\">\\n                        <div id=\\\"desktopTab\\\" class=\\\"tab active\\\" data-i18n=\\\"help.tab.desktop\\\">Desktop</div>\\n                        <div id=\\\"touchTab\\\" class=\\\"tab\\\" data-i18n=\\\"help.tab.touch\\\">Touch</div>\\n                    </div>\\n                </div>\\n            </div>\\n\\n            <!-- Touch Joystick -->\\n            <div id=\\\"joystickBase\\\" class=\\\"hidden\\\">\\n                <div id=\\\"joystick\\\"></div>\\n            </div>\\n\\n            <!-- Annotation Navigator -->\\n            <div id=\\\"annotationNav\\\" class=\\\"hidden\\\">\\n                <button id=\\\"annotationPrev\\\">\\n                    <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"20\\\" height=\\\"20\\\">\\n                        <g class='stroke'><use href=\\\"#chevronLeftIcon\\\"/></g>\\n                        <g class='fill'><use href=\\\"#chevronLeftIcon\\\"/></g>\\n                    </svg>\\n                </button>\\n                <div id=\\\"annotationInfo\\\">\\n                    <span id=\\\"annotationNavTitle\\\"></span>\\n                </div>\\n                <button id=\\\"annotationNext\\\">\\n                    <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"20\\\" height=\\\"20\\\">\\n                        <g class='stroke'><use href=\\\"#chevronRightIcon\\\"/></g>\\n                        <g class='fill'><use href=\\\"#chevronRightIcon\\\"/></g>\\n                    </svg>\\n                </button>\\n            </div>\\n\\n            <!-- Tooltip -->\\n            <div id=\\\"tooltip\\\"></div>\\n\\n            <!-- XR WebGL-required modal -->\\n            <div id=\\\"xrModal\\\" class=\\\"hidden\\\" onwheel=\\\"event.stopPropagation()\\\">\\n                <div id=\\\"xrModalContent\\\" onpointerdown=\\\"event.stopPropagation()\\\">\\n                    <h2 data-i18n=\\\"xr-modal.title\\\">WebGL Required</h2>\\n                    <p data-i18n=\\\"xr-modal.message\\\">AR and VR are not supported on the WebGPU renderer. Pressing OK will reload the viewer with WebGL.</p>\\n                    <div id=\\\"xrModalButtons\\\">\\n                        <button id=\\\"xrModalCancel\\\" data-i18n=\\\"xr-modal.cancel\\\">Cancel</button>\\n                        <button id=\\\"xrModalOk\\\" data-i18n=\\\"xr-modal.ok\\\">OK</button>\\n                    </div>\\n                </div>\\n            </div>\\n        </div>\\n\\n        <!-- SVG Icons -->\\n        <svg>\\n            <symbol id=\\\"playIcon\\\" viewBox=\\\"-2 0 24 24\\\">\\n                <path\\n                    d=\\\"M1 1.98725C1 1.20022 1.87789 0.730421 2.5332 1.16694L14.5605 9.18061C15.146 9.57066 15.146 10.4302 14.5605 10.8203L2.5332 18.833C1.87788 19.2695 1 18.7997 1 18.0126V1.98725Z\\\"\\n                    transform=\\\"translate(2 2)\\\"\\n                />\\n            </symbol>\\n            <symbol id=\\\"pauseIcon\\\" viewBox=\\\"0 0 20 20\\\">\\n                <path d=\\\"M5 16V4h3v12H5zm7-12h3v12h-3V4z\\\"/>\\n            </symbol>\\n            <symbol id=\\\"orbitIcon\\\" viewBox=\\\"-2 -2 20 20\\\">\\n                <path fill-rule=\\\"evenodd\\\" clip-rule=\\\"evenodd\\\" d=\\\"M4.44728 1.7561C6.14077 0.763957 8.53159 1.57857 10.4375 3.58357C12.75 3.02099 14.4585 3.40647 14.6491 4.73071C14.7831 5.66256 14.139 6.87994 12.9942 8.09008C13.7427 10.7586 13.2413 13.2551 11.5527 14.2444C9.85867 15.2369 7.46679 14.4208 5.56056 12.4143C3.34914 12.9521 1.691 12.6254 1.38412 11.4371L1.35092 11.2698C1.21678 10.3379 1.85972 9.11931 3.00457 7.90909C2.28693 5.34963 2.72037 2.94871 4.24741 1.88435L4.44728 1.7561ZM11.9889 9.03995C11.002 9.88136 9.79998 10.6808 8.47918 11.3303L8.13673 11.4937C7.70533 11.6942 7.28148 11.8681 6.8698 12.0172C7.32387 12.4287 7.79226 12.7587 8.25326 12.9983C9.39237 13.5903 10.3231 13.574 10.946 13.2092C11.5745 12.841 12.0613 12.0184 12.1263 10.7086C12.1518 10.1934 12.1065 9.62999 11.9889 9.03995ZM3.46225 9.20206C3.15128 9.5802 2.91825 9.93412 2.76238 10.2489C2.54363 10.6909 2.51958 10.967 2.53842 11.0985C2.54902 11.1721 2.56635 11.2146 2.67058 11.2763C2.81832 11.3636 3.12484 11.4626 3.6478 11.467C3.95641 11.4696 4.3074 11.4373 4.69402 11.3707C4.45655 11.0439 4.23084 10.6971 4.02215 10.3303C3.81017 9.95774 3.62416 9.58004 3.46225 9.20206ZM10.0358 4.9423C9.42018 5.13611 8.75205 5.40184 8.05014 5.74698C6.61265 6.45384 5.33887 7.34291 4.37175 8.24373C4.55213 8.73829 4.78227 9.2401 5.06511 9.73722C5.33995 10.2202 5.64271 10.6614 5.96355 11.0575C6.5793 10.8637 7.24782 10.5987 7.94988 10.2535C9.38732 9.54667 10.6605 8.65688 11.6276 7.7561C11.4473 7.26173 11.2176 6.76019 10.9349 6.26326C10.66 5.78001 10.3568 5.33855 10.0358 4.9423ZM7.74675 3.00219C6.60759 2.41015 5.67698 2.42644 5.05405 2.79126C4.42548 3.15953 3.93866 3.98199 3.87371 5.29191C3.84822 5.80668 3.89236 6.36967 4.00978 6.95922C4.91091 6.19088 5.9923 5.45862 7.17905 4.84269L7.52084 4.67016C8.07056 4.39986 8.6096 4.17089 9.12957 3.98266C8.67568 3.57138 8.20757 3.24172 7.74675 3.00219ZM12.3522 4.53344C12.0433 4.53086 11.6918 4.56177 11.3047 4.6285C11.5425 4.95566 11.7689 5.3029 11.9779 5.67016C12.1897 6.04255 12.3753 6.41999 12.5371 6.79777C12.8481 6.41965 13.0818 6.06635 13.2376 5.75154C13.4564 5.30973 13.4804 5.03352 13.4616 4.90193C13.451 4.82831 13.4337 4.7859 13.3294 4.7242C13.1817 4.63684 12.8753 4.53787 12.3522 4.53344Z\\\"/>\\n            </symbol>\\n            <symbol id=\\\"flyIcon\\\" viewBox=\\\"-2 -2 20 20\\\">\\n                <path fill-rule=\\\"evenodd\\\" clip-rule=\\\"evenodd\\\" d=\\\"M12 1.33337C13.4727 1.33337 14.6666 2.52728 14.6666 4.00004C14.6666 5.4728 13.4727 6.66671 12 6.66671C11.4931 6.66671 11.0194 6.52491 10.6159 6.27934L10.2721 6.62374C10.0345 6.86142 9.90102 7.18411 9.90102 7.52022V8.47986C9.90102 8.81597 10.0345 9.13866 10.2721 9.37634L10.6159 9.72009C11.0193 9.47463 11.4932 9.33337 12 9.33337C13.4727 9.33337 14.6666 10.5273 14.6666 12C14.6666 13.4728 13.4727 14.6667 12 14.6667C10.5272 14.6667 9.33331 13.4728 9.33331 12C9.33331 11.4932 9.47457 11.0194 9.72003 10.6159L9.37628 10.2722C9.1386 10.0345 8.81591 9.90108 8.4798 9.90108H7.52016C7.18405 9.90108 6.86136 10.0345 6.62368 10.2722L6.27928 10.6159C6.52485 11.0195 6.66665 11.4931 6.66665 12C6.66665 13.4728 5.47274 14.6667 3.99998 14.6667C2.52722 14.6667 1.33331 13.4728 1.33331 12C1.33331 10.5273 2.52722 9.33337 3.99998 9.33337C4.50658 9.33337 4.98008 9.47481 5.38344 9.72009L5.72784 9.37634C5.9655 9.13866 6.09894 8.81597 6.09894 8.47986V7.52022C6.09894 7.18411 5.9655 6.86142 5.72784 6.62374L5.38344 6.27934C4.98001 6.52473 4.5067 6.66671 3.99998 6.66671C2.52722 6.66671 1.33331 5.4728 1.33331 4.00004C1.33331 2.52728 2.52722 1.33337 3.99998 1.33337C5.47274 1.33337 6.66665 2.52728 6.66665 4.00004C6.66665 4.50676 6.52467 4.98008 6.27928 5.3835L6.62368 5.72791C6.86136 5.96556 7.18405 6.099 7.52016 6.099H8.4798C8.81591 6.099 9.1386 5.96556 9.37628 5.72791L9.72003 5.3835C9.47475 4.98014 9.33331 4.50664 9.33331 4.00004C9.33331 2.52728 10.5272 1.33337 12 1.33337ZM3.99998 10.3998C3.11632 10.3998 2.39972 11.1164 2.39972 12C2.39972 12.8837 3.11632 13.6003 3.99998 13.6003C4.88364 13.6003 5.60024 12.8837 5.60024 12C5.60024 11.7911 5.55917 11.5919 5.48631 11.4089L4.41469 12.4812C4.16723 12.7284 3.76625 12.7286 3.51886 12.4812C3.27147 12.2338 3.27158 11.8328 3.51886 11.5853L4.59047 10.5131C4.40769 10.4404 4.20862 10.3998 3.99998 10.3998ZM12 10.3998C11.7911 10.3998 11.5918 10.4403 11.4088 10.5131L12.4811 11.5853C12.7284 11.8328 12.7285 12.2338 12.4811 12.4812C12.2337 12.7286 11.8327 12.7284 11.5853 12.4812L10.513 11.4089C10.4402 11.5918 10.3997 11.7912 10.3997 12C10.3997 12.8837 11.1163 13.6003 12 13.6003C12.8836 13.6003 13.6002 12.8837 13.6002 12C13.6002 11.1164 12.8836 10.3998 12 10.3998ZM3.99998 2.39978C3.11632 2.39978 2.39972 3.11639 2.39972 4.00004C2.39972 4.8837 3.11632 5.6003 3.99998 5.6003C4.20871 5.6003 4.40763 5.55909 4.59047 5.48637L3.51886 4.41475C3.27158 4.16729 3.27147 3.76631 3.51886 3.51892C3.76625 3.27153 4.16723 3.27164 4.41469 3.51892L5.48631 4.59054C5.55903 4.40769 5.60024 4.20877 5.60024 4.00004C5.60024 3.11639 4.88364 2.39978 3.99998 2.39978ZM12 2.39978C11.1163 2.39978 10.3997 3.11639 10.3997 4.00004C10.3997 4.20868 10.4403 4.40775 10.513 4.59054L11.5853 3.51892C11.8327 3.27164 12.2337 3.27153 12.4811 3.51892C12.7285 3.76631 12.7284 4.16729 12.4811 4.41475L11.4088 5.48637C11.5918 5.55923 11.791 5.6003 12 5.6003C12.8836 5.6003 13.6002 4.8837 13.6002 4.00004C13.6002 3.11639 12.8836 2.39978 12 2.39978Z\\\"/>\\n            </symbol>\\n            <symbol id=\\\"walkIcon\\\" viewBox=\\\"-2 -2 20 20\\\">\\n                <path d=\\\"M9.75 2a1.75 1.75 0 1 1-3.5 0 1.75 1.75 0 0 1 3.5 0zM5.25 4.75h5.5v4.5h-.5v5h-2v-5h-.5v5h-2v-5h-.5z\\\"/>\\n            </symbol>\\n            <symbol id=\\\"arIcon\\\" viewBox=\\\"0 0 24 24\\\">\\n                <path fill-rule=\\\"evenodd\\\" clip-rule=\\\"evenodd\\\" d=\\\"M12 15.3994V6H16.9629C18.2109 6 19.1167 6.1089 19.6797 6.32715C20.248 6.53997 20.7021 6.92247 21.042 7.47363C21.3818 8.02476 21.5518 8.65491 21.5518 9.36426C21.5518 10.2645 21.2943 11.0093 20.7793 11.5986C20.2641 12.1825 19.4938 12.5513 18.4688 12.7041C18.9786 13.0097 19.3983 13.3453 19.7275 13.7109C20.0621 14.0766 20.5113 14.7261 21.0742 15.6592L22.5 18H19.6797L17.9746 15.3887C17.3694 14.4559 16.9555 13.8691 16.7324 13.6289C16.5095 13.3835 16.2729 13.2172 16.0234 13.1299C15.7738 13.0371 15.3777 12.9902 14.8359 12.9902H14.3584V18H10.4053L9.35742 15.2744H4.56055L3.57031 18H1L5.67383 6H8.23633L12 15.3994ZM5.30566 13.252H8.58008L6.92676 8.7998L5.30566 13.252ZM14.3584 11.0752H16.1025C17.2336 11.0752 17.9401 11.0259 18.2217 10.9277C18.5032 10.8295 18.7235 10.66 18.8828 10.4199C19.0421 10.1798 19.1221 9.87966 19.1221 9.51953C19.122 9.11597 19.016 8.79138 18.8037 8.5459C18.5966 8.29488 18.3013 8.13677 17.9189 8.07129C17.7276 8.04401 17.1541 8.03027 16.1982 8.03027H14.3584V11.0752Z\\\"/>\\n            </symbol>\\n            <symbol id=\\\"vrIcon\\\" viewBox=\\\"0 0 24 24\\\">\\n                <path fill-rule=\\\"evenodd\\\" clip-rule=\\\"evenodd\\\" d=\\\"M5.52148 10.7021L7.15918 15.1133L8.76465 10.7021L9.50195 8.7002L10.4834 6H16.9541C18.1903 6 19.0879 6.10801 19.6455 6.32422C20.2081 6.53499 20.6576 6.9134 20.9941 7.45898C21.3308 8.00484 21.499 8.62946 21.499 9.33203C21.499 10.2239 21.2446 10.9622 20.7344 11.5459C20.2241 12.1242 19.4606 12.4893 18.4453 12.6406C18.9503 12.9433 19.3662 13.2756 19.6924 13.6377C20.0238 13.9999 20.4688 14.6432 21.0264 15.5674L22.4385 17.8857H19.6455L17.9561 15.2998C17.3565 14.3758 16.9466 13.7946 16.7256 13.5566C16.5047 13.3135 16.2706 13.148 16.0234 13.0615C15.7762 12.9696 15.3841 12.9238 14.8477 12.9238H14.374V17.8857H12.0381V8.54395L8.39941 17.8857H5.86133L1.10254 6H3.71289L5.52148 10.7021ZM14.374 11.0264H16.1025C17.2228 11.0264 17.9224 10.9781 18.2012 10.8809C18.4799 10.7836 17.6986 10.6157 18.8564 10.3779C19.0141 10.1402 19.0928 9.84288 19.0928 9.48633C19.0928 9.08641 18.9877 8.7647 18.7773 8.52148C18.5722 8.27286 18.2801 8.11565 17.9014 8.05078C17.712 8.02376 17.1439 8.01075 16.1973 8.01074H14.374V11.0264Z\\\"/>\\n            </symbol>\\n            <symbol id=\\\"infoIcon\\\" viewBox=\\\"-2 -2 24 24\\\">\\n                <path d=\\\"M9.98633 7.58301C10.2598 7.58301 10.4854 7.67643 10.6631 7.86328C10.8408 8.05013 10.9297 8.3099 10.9297 8.64258V14.0361C10.9297 14.4098 10.8408 14.6924 10.6631 14.8838C10.4854 15.0752 10.2598 15.1709 9.98633 15.1709C9.71289 15.1709 9.48958 15.0729 9.31641 14.877C9.14779 14.681 9.06348 14.4007 9.06348 14.0361V8.69727C9.06348 8.32812 9.14779 8.05013 9.31641 7.86328C9.48958 7.67643 9.71289 7.58301 9.98633 7.58301Z\\\"/>\\n                <path d=\\\"M10.0068 4.88965C10.2484 4.88965 10.4626 4.96712 10.6494 5.12207C10.8363 5.27702 10.9297 5.5026 10.9297 5.79883C10.9297 6.08594 10.8385 6.31152 10.6562 6.47559C10.474 6.63509 10.2575 6.71484 10.0068 6.71484C9.74707 6.71484 9.52376 6.63509 9.33691 6.47559C9.15462 6.31608 9.06348 6.09049 9.06348 5.79883C9.06348 5.53451 9.1569 5.31803 9.34375 5.14941C9.53516 4.97624 9.75618 4.88965 10.0068 4.88965Z\\\"/>\\n                <path fill-rule=\\\"evenodd\\\" clip-rule=\\\"evenodd\\\" d=\\\"M10 0C15.5228 0 20 4.47715 20 10C20 15.5228 15.5228 20 10 20C4.47715 20 0 15.5228 0 10C0 4.47715 4.47715 0 10 0ZM10 1.7998C5.47126 1.7998 1.7998 5.47126 1.7998 10C1.7998 14.5287 5.47126 18.2002 10 18.2002C14.5287 18.2002 18.2002 14.5287 18.2002 10C18.2002 5.47126 14.5287 1.7998 10 1.7998Z\\\"/>\\n            </symbol>\\n            <symbol id=\\\"settingsIcon\\\" viewBox=\\\"0 0 24 24\\\">\\n                <path fill-rule=\\\"evenodd\\\" clip-rule=\\\"evenodd\\\" d=\\\"M12 8C14.2091 8 16 9.79086 16 12C16 14.2091 14.2091 16 12 16C9.79086 16 8 14.2091 8 12C8 9.79086 9.79086 8 12 8ZM12 9.7998C10.785 9.7998 9.7998 10.785 9.7998 12C9.7998 13.215 10.785 14.2002 12 14.2002C13.215 14.2002 14.2002 13.215 14.2002 12C14.2002 10.785 13.215 9.7998 12 9.7998Z\\\"/>\\n                <path fill-rule=\\\"evenodd\\\" clip-rule=\\\"evenodd\\\" d=\\\"M12.7119 2.2002C13.1961 2.20028 13.6296 2.49055 13.8164 2.93066L13.8506 3.02051L14.3652 4.56641C14.7875 4.70091 15.1932 4.87075 15.5801 5.07129L17.042 4.3418L17.1299 4.30176C17.5436 4.13502 18.017 4.21245 18.3564 4.50195L18.4268 4.56641L19.4336 5.57324C19.7985 5.93836 19.8889 6.49621 19.6582 6.95801L18.9268 8.41895C19.1274 8.80592 19.2971 9.21159 19.4316 9.63379L20.9795 10.1504C21.4693 10.3138 21.7997 10.7717 21.7998 11.2881V12.7119C21.7997 13.2284 21.4695 13.6873 20.9795 13.8506L19.4316 14.3652C19.2971 14.7875 19.1274 15.1932 18.9268 15.5801L19.6582 17.042C19.8889 17.5038 19.7985 18.0616 19.4336 18.4268L18.4268 19.4336C18.0616 19.7985 17.5038 19.8889 17.042 19.6582L15.5801 18.9268C15.1932 19.1274 14.7875 19.2971 14.3652 19.4316L13.8506 20.9795C13.6873 21.4695 13.2284 21.7997 12.7119 21.7998H11.2881C10.7717 21.7997 10.3138 21.4693 10.1504 20.9795L9.63379 19.4316C9.21159 19.2971 8.80592 19.1274 8.41895 18.9268L6.95801 19.6582C6.49621 19.8889 5.93836 19.7985 5.57324 19.4336L4.56641 18.4268C4.20146 18.0617 4.1112 17.5038 4.3418 17.042L5.07129 15.5801C4.87075 15.1932 4.70091 14.7875 4.56641 14.3652L3.02051 13.8506C2.53057 13.6873 2.20029 13.2283 2.2002 12.7119V11.2881C2.20024 10.7718 2.53076 10.3139 3.02051 10.1504L4.56641 9.63379C4.70094 9.21149 4.86966 8.80498 5.07031 8.41797L4.3418 6.95801C4.11113 6.49617 4.20145 5.93834 4.56641 5.57324L5.57324 4.56641C5.93834 4.20145 6.49617 4.11113 6.95801 4.3418L8.41797 5.07031C8.80498 4.86966 9.21149 4.70094 9.63379 4.56641L10.1504 3.02051L10.1836 2.92969C10.3706 2.49001 10.8042 2.20023 11.2881 2.2002H12.7119ZM11.0186 5.4707L10.8809 5.88477L10.458 5.99316C9.88479 6.13982 9.34317 6.36768 8.84473 6.66309L8.46875 6.88477L8.0791 6.69043L6.50098 5.90137L5.90137 6.50098L6.69043 8.0791L6.88477 8.46875L6.66309 8.84473C6.36768 9.34317 6.13982 9.88479 5.99316 10.458L5.88477 10.8809L5.4707 11.0186L3.7998 11.5762V12.4229L5.4707 12.9805L5.88477 13.1182L5.99316 13.541C6.13969 14.1141 6.36763 14.6556 6.66309 15.1543L6.88477 15.5303L6.69043 15.9199L5.90137 17.498L6.50098 18.0977L8.0791 17.3086L8.46875 17.1133L8.84473 17.3359C9.34314 17.6314 9.88463 17.8591 10.458 18.0059L10.8809 18.1143L11.0186 18.5283L11.5771 20.2002H12.4229L13.1182 18.1143L13.541 18.0059C14.1143 17.8593 14.6556 17.6314 15.1543 17.3359L15.5303 17.1143L15.9199 17.3086L17.498 18.0977L18.0977 17.498L17.3086 15.9199L17.1143 15.5303L17.3359 15.1543C17.6314 14.6556 17.8593 14.1143 18.0059 13.541L18.1143 13.1182L20.2002 12.4229V11.5762L18.1143 10.8809L18.0059 10.458C17.8591 9.88463 17.6314 9.34314 17.3359 8.84473L17.1133 8.46875L17.3086 8.0791L18.0977 6.50098L17.498 5.90137L15.9199 6.69043L15.5303 6.88477L15.1543 6.66309C14.6556 6.36763 14.1141 6.13969 13.541 5.99316L13.1182 5.88477L12.9805 5.4707L12.4229 3.7998H11.5762L11.0186 5.4707Z\\\"/>\\n            </symbol>\\n            <symbol id=\\\"enterFullscreenIcon\\\" viewBox=\\\"0 0 24 24\\\">\\n                <path d=\\\"M3 14.7002C3.49693 14.7002 3.90018 15.1027 3.90039 15.5996V20C3.90039 20.0552 3.94477 20.0996 4 20.0996H8.40039C8.89727 20.0998 9.2998 20.5031 9.2998 21C9.2998 21.4969 8.89727 21.9002 8.40039 21.9004H4C2.95066 21.9004 2.09961 21.0493 2.09961 20V15.5996C2.09982 15.1027 2.50307 14.7002 3 14.7002Z\\\"/>\\n                <path d=\\\"M21 14.7002C21.4969 14.7002 21.9002 15.1027 21.9004 15.5996V20C21.9004 21.0493 21.0493 21.9004 20 21.9004H15.5996C15.1027 21.9002 14.7002 21.4969 14.7002 21C14.7002 20.5031 15.1027 20.0998 15.5996 20.0996H20C20.0552 20.0996 20.0996 20.0552 20.0996 20V15.5996C20.0998 15.1027 20.5031 14.7002 21 14.7002Z\\\"/>\\n                <path d=\\\"M8.40039 2.09961C8.89727 2.09982 9.2998 2.50307 9.2998 3C9.2998 3.49693 8.89727 3.90018 8.40039 3.90039H4C3.94477 3.90039 3.90039 3.94477 3.90039 4V8.40039C3.90018 8.89727 3.49693 9.2998 3 9.2998C2.50307 9.2998 2.09982 8.89727 2.09961 8.40039V4C2.09961 2.95066 2.95066 2.09961 4 2.09961H8.40039Z\\\"/>\\n                <path d=\\\"M20 2.09961C21.0493 2.09961 21.9004 2.95066 21.9004 4V8.40039C21.9002 8.89727 21.4969 9.2998 21 9.2998C20.5031 9.2998 20.0998 8.89727 20.0996 8.40039V4C20.0996 3.94477 20.0552 3.90039 20 3.90039H15.5996C15.1027 3.90018 14.7002 3.49693 14.7002 3C14.7002 2.50307 15.1027 2.09982 15.5996 2.09961H20Z\\\"/>\\n            </symbol>\\n            <symbol id=\\\"chevronLeftIcon\\\" viewBox=\\\"0 0 24 24\\\">\\n                <path d=\\\"M15 19l-7-7 7-7\\\"/>\\n            </symbol>\\n            <symbol id=\\\"chevronRightIcon\\\" viewBox=\\\"0 0 24 24\\\">\\n                <path d=\\\"M9 5l7 7-7 7\\\"/>\\n            </symbol>\\n            <symbol id=\\\"voxelIcon\\\" viewBox=\\\"0 0 16 16\\\">\\n                <path d=\\\"M8 1L2 4.5v7L8 15l6-3.5v-7L8 1zm0 1.15L12.85 5 8 7.85 3.15 5 8 2.15zM3 5.85l4.5 2.6v5.1L3 10.95V5.85zm5.5 7.7v-5.1L13 5.85v5.1l-4.5 2.6z\\\"/>\\n            </symbol>\\n            <symbol id=\\\"exitFullscreenIcon\\\" viewBox=\\\"0 0 24 24\\\">\\n                <path d=\\\"M8 15.0996C8.49706 15.0996 8.90039 15.5029 8.90039 16V21C8.90039 21.4971 8.49706 21.9004 8 21.9004C7.50294 21.9004 7.09961 21.4971 7.09961 21V16.9004H3C2.50294 16.9004 2.09961 16.4971 2.09961 16C2.09961 15.5029 2.50294 15.0996 3 15.0996H8Z\\\" />\\n                <path d=\\\"M21 15.0996C21.4971 15.0996 21.9004 15.5029 21.9004 16C21.9004 16.4971 21.4971 16.9004 21 16.9004H16.9004V21C16.9004 21.4971 16.4971 21.9004 16 21.9004C15.5029 21.9004 15.0996 21.4971 15.0996 21V16C15.0996 15.5029 15.5029 15.0996 16 15.0996H21Z\\\" />\\n                <path d=\\\"M8 2.09961C8.49706 2.09961 8.90039 2.50294 8.90039 3V8C8.90039 8.49706 8.49706 8.90039 8 8.90039H3C2.50294 8.90039 2.09961 8.49706 2.09961 8C2.09961 7.50294 2.50294 7.09961 3 7.09961H7.09961V3C7.09961 2.50294 7.50294 2.09961 8 2.09961Z\\\" />\\n                <path d=\\\"M16 2.09961C16.4971 2.09961 16.9004 2.50294 16.9004 3V7.09961H21C21.4971 7.09961 21.9004 7.50294 21.9004 8C21.9004 8.49706 21.4971 8.90039 21 8.90039H16C15.5029 8.90039 15.0996 8.49706 15.0996 8V3C15.0996 2.50294 15.5029 2.09961 16 2.09961Z\\\" />\\n            </symbol>\\n        </svg>\\n\\n        <!-- Application Script -->\\n        <script type=\\\"module\\\">\\n            import { main } from './index.js';\\n\\n            const { config, settings } = window.sse;\\n            const { poster } = config;\\n\\n            // Show the poster image\\n            if (poster) {\\n                const element = document.getElementById('poster');\\n                element.style.setProperty('--poster-url', `url(${poster.src})`);\\n                element.style.display = 'block';\\n                element.style.filter = 'blur(40px)';\\n\\n                // hide the canvas\\n                document.documentElement.style.setProperty('--canvas-opacity', '0');\\n            }\\n\\n            document.addEventListener('DOMContentLoaded', async () => {\\n                const canvas = document.getElementById('application-canvas');\\n                const settingsJson = await settings;\\n                const viewer = await main(canvas, settingsJson, config);\\n            });\\n        </script>\\n    </body>\\n</html>\\n\";\n\nvar index = \"const TRACEID_GPU_TIMINGS = \\\"GpuTimings\\\";\\n\\nconst version$1 = \\\"2.19.2\\\";\\nconst revision = \\\"3f52bb8\\\";\\nfunction extend(target, ex) {\\n\\tfor (const prop in ex) {\\n\\t\\tconst copy = ex[prop];\\n\\t\\tif (Array.isArray(copy)) {\\n\\t\\t\\ttarget[prop] = extend([], copy);\\n\\t\\t} else if (copy && typeof copy === \\\"object\\\") {\\n\\t\\t\\ttarget[prop] = extend({}, copy);\\n\\t\\t} else {\\n\\t\\t\\ttarget[prop] = copy;\\n\\t\\t}\\n\\t}\\n\\treturn target;\\n}\\n\\nconst guid = {\\n\\tcreate() {\\n\\t\\treturn \\\"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\\\".replace(/[xy]/g, (c) => {\\n\\t\\t\\tconst r = Math.random() * 16 | 0;\\n\\t\\t\\tconst v = c === \\\"x\\\" ? r : r & 3 | 8;\\n\\t\\t\\treturn v.toString(16);\\n\\t\\t});\\n\\t}\\n};\\n\\nconst path = {\\n\\tdelimiter: \\\"/\\\",\\n\\tjoin(...sections) {\\n\\t\\tlet result = sections[0];\\n\\t\\tfor (let i = 0; i < sections.length - 1; i++) {\\n\\t\\t\\tconst one = sections[i];\\n\\t\\t\\tconst two = sections[i + 1];\\n\\t\\t\\tif (two[0] === path.delimiter) {\\n\\t\\t\\t\\tresult = two;\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tif (one && two && one[one.length - 1] !== path.delimiter && two[0] !== path.delimiter) {\\n\\t\\t\\t\\tresult += path.delimiter + two;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tresult += two;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn result;\\n\\t},\\n\\tnormalize(pathname) {\\n\\t\\tconst lead = pathname.startsWith(path.delimiter);\\n\\t\\tconst trail = pathname.endsWith(path.delimiter);\\n\\t\\tconst parts = pathname.split(\\\"/\\\");\\n\\t\\tlet result = \\\"\\\";\\n\\t\\tlet cleaned = [];\\n\\t\\tfor (let i = 0; i < parts.length; i++) {\\n\\t\\t\\tif (parts[i] === \\\"\\\") continue;\\n\\t\\t\\tif (parts[i] === \\\".\\\") continue;\\n\\t\\t\\tif (parts[i] === \\\"..\\\" && cleaned.length > 0) {\\n\\t\\t\\t\\tcleaned = cleaned.slice(0, cleaned.length - 2);\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tif (i > 0) cleaned.push(path.delimiter);\\n\\t\\t\\tcleaned.push(parts[i]);\\n\\t\\t}\\n\\t\\tresult = cleaned.join(\\\"\\\");\\n\\t\\tif (!lead && result[0] === path.delimiter) {\\n\\t\\t\\tresult = result.slice(1);\\n\\t\\t}\\n\\t\\tif (trail && result[result.length - 1] !== path.delimiter) {\\n\\t\\t\\tresult += path.delimiter;\\n\\t\\t}\\n\\t\\treturn result;\\n\\t},\\n\\tsplit(pathname) {\\n\\t\\tconst lastDelimiterIndex = pathname.lastIndexOf(path.delimiter);\\n\\t\\tif (lastDelimiterIndex !== -1) {\\n\\t\\t\\treturn [pathname.substring(0, lastDelimiterIndex), pathname.substring(lastDelimiterIndex + 1)];\\n\\t\\t}\\n\\t\\treturn [\\\"\\\", pathname];\\n\\t},\\n\\tgetBasename(pathname) {\\n\\t\\treturn path.split(pathname)[1];\\n\\t},\\n\\tgetDirectory(pathname) {\\n\\t\\treturn path.split(pathname)[0];\\n\\t},\\n\\tgetExtension(pathname) {\\n\\t\\tconst ext = pathname.split(\\\"?\\\")[0].split(\\\".\\\").pop();\\n\\t\\tif (ext !== pathname) {\\n\\t\\t\\treturn `.${ext}`;\\n\\t\\t}\\n\\t\\treturn \\\"\\\";\\n\\t},\\n\\tisRelativePath(pathname) {\\n\\t\\treturn pathname.charAt(0) !== \\\"/\\\" && pathname.match(/:\\\\/\\\\//) === null;\\n\\t},\\n\\textractPath(pathname) {\\n\\t\\tlet result = \\\"\\\";\\n\\t\\tconst parts = pathname.split(\\\"/\\\");\\n\\t\\tlet i = 0;\\n\\t\\tif (parts.length > 1) {\\n\\t\\t\\tif (path.isRelativePath(pathname)) {\\n\\t\\t\\t\\tif (parts[0] === \\\".\\\") {\\n\\t\\t\\t\\t\\tfor (i = 0; i < parts.length - 1; ++i) {\\n\\t\\t\\t\\t\\t\\tresult += i === 0 ? parts[i] : `/${parts[i]}`;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else if (parts[0] === \\\"..\\\") {\\n\\t\\t\\t\\t\\tfor (i = 0; i < parts.length - 1; ++i) {\\n\\t\\t\\t\\t\\t\\tresult += i === 0 ? parts[i] : `/${parts[i]}`;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tresult = \\\".\\\";\\n\\t\\t\\t\\t\\tfor (i = 0; i < parts.length - 1; ++i) {\\n\\t\\t\\t\\t\\t\\tresult += `/${parts[i]}`;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tfor (i = 0; i < parts.length - 1; ++i) {\\n\\t\\t\\t\\t\\tresult += i === 0 ? parts[i] : `/${parts[i]}`;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n};\\n\\nconst detectPassiveEvents = () => {\\n\\tlet result = false;\\n\\ttry {\\n\\t\\tconst opts = Object.defineProperty({}, \\\"passive\\\", {\\n\\t\\t\\tget: function() {\\n\\t\\t\\t\\tresult = true;\\n\\t\\t\\t\\treturn false;\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\twindow.addEventListener(\\\"testpassive\\\", null, opts);\\n\\t\\twindow.removeEventListener(\\\"testpassive\\\", null, opts);\\n\\t} catch (e) {\\n\\t}\\n\\treturn result;\\n};\\nconst ua = typeof navigator !== \\\"undefined\\\" ? navigator.userAgent : \\\"\\\";\\nconst environment = typeof window !== \\\"undefined\\\" ? \\\"browser\\\" : typeof global !== \\\"undefined\\\" ? \\\"node\\\" : \\\"worker\\\";\\nconst platformName = /android/i.test(ua) ? \\\"android\\\" : /ip(?:[ao]d|hone)/i.test(ua) ? \\\"ios\\\" : /windows/i.test(ua) ? \\\"windows\\\" : /mac os/i.test(ua) ? \\\"osx\\\" : /linux/i.test(ua) ? \\\"linux\\\" : /cros/i.test(ua) ? \\\"cros\\\" : null;\\nconst browserName = environment !== \\\"browser\\\" ? null : /Chrome\\\\/|Chromium\\\\/|Edg.*\\\\//.test(ua) ? \\\"chrome\\\" : (\\n\\t// chrome, chromium, edge\\n\\t/Safari\\\\//.test(ua) ? \\\"safari\\\" : (\\n\\t\\t// safari, ios chrome/firefox\\n\\t\\t/Firefox\\\\//.test(ua) ? \\\"firefox\\\" : \\\"other\\\"\\n\\t)\\n);\\nconst visionos = /Macintosh/i.test(ua) && typeof navigator !== \\\"undefined\\\" && navigator.maxTouchPoints > 0 && !/iPhone|iPad|iPod/i.test(ua);\\nconst passiveEvents = detectPassiveEvents();\\nconst platform = {\\n\\tname: platformName,\\n\\tenvironment,\\n\\tbrowser: environment === \\\"browser\\\",\\n\\tworker: environment === \\\"worker\\\",\\n\\tdesktop: [\\\"windows\\\", \\\"osx\\\", \\\"linux\\\", \\\"cros\\\"].includes(platformName),\\n\\tmobile: [\\\"android\\\", \\\"ios\\\"].includes(platformName),\\n\\tios: platformName === \\\"ios\\\",\\n\\tandroid: platformName === \\\"android\\\",\\n\\tvisionos,\\n\\tpassiveEvents,\\n\\tbrowserName\\n};\\n\\nclass EventHandle {\\n\\thandler;\\n\\tname;\\n\\tcallback;\\n\\tscope;\\n\\t_once;\\n\\t_removed = false;\\n\\tconstructor(handler, name, callback, scope, once = false) {\\n\\t\\tthis.handler = handler;\\n\\t\\tthis.name = name;\\n\\t\\tthis.callback = callback;\\n\\t\\tthis.scope = scope;\\n\\t\\tthis._once = once;\\n\\t}\\n\\toff() {\\n\\t\\tif (this._removed) return;\\n\\t\\tthis.handler.offByHandle(this);\\n\\t}\\n\\ton(name, callback, scope = this) {\\n\\t\\treturn this.handler._addCallback(name, callback, scope, false);\\n\\t}\\n\\tonce(name, callback, scope = this) {\\n\\t\\treturn this.handler._addCallback(name, callback, scope, true);\\n\\t}\\n\\tset removed(value) {\\n\\t\\tif (!value) return;\\n\\t\\tthis._removed = true;\\n\\t}\\n\\tget removed() {\\n\\t\\treturn this._removed;\\n\\t}\\n\\t// don't stringify EventHandle to JSON by JSON.stringify\\n\\ttoJSON(key) {\\n\\t\\treturn void 0;\\n\\t}\\n}\\n\\nclass EventHandler {\\n\\t_callbacks = /* @__PURE__ */ new Map();\\n\\t_callbackActive = /* @__PURE__ */ new Map();\\n\\tinitEventHandler() {\\n\\t\\tthis._callbacks = /* @__PURE__ */ new Map();\\n\\t\\tthis._callbackActive = /* @__PURE__ */ new Map();\\n\\t}\\n\\t_addCallback(name, callback, scope, once) {\\n\\t\\tif (!this._callbacks.has(name)) {\\n\\t\\t\\tthis._callbacks.set(name, []);\\n\\t\\t}\\n\\t\\tif (this._callbackActive.has(name)) {\\n\\t\\t\\tconst callbackActive = this._callbackActive.get(name);\\n\\t\\t\\tif (callbackActive && callbackActive === this._callbacks.get(name)) {\\n\\t\\t\\t\\tthis._callbackActive.set(name, callbackActive.slice());\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst evt = new EventHandle(this, name, callback, scope, once);\\n\\t\\tthis._callbacks.get(name).push(evt);\\n\\t\\treturn evt;\\n\\t}\\n\\ton(name, callback, scope = this) {\\n\\t\\treturn this._addCallback(name, callback, scope, false);\\n\\t}\\n\\tonce(name, callback, scope = this) {\\n\\t\\treturn this._addCallback(name, callback, scope, true);\\n\\t}\\n\\toff(name, callback, scope) {\\n\\t\\tif (name) {\\n\\t\\t\\tif (this._callbackActive.has(name) && this._callbackActive.get(name) === this._callbacks.get(name)) {\\n\\t\\t\\t\\tthis._callbackActive.set(name, this._callbackActive.get(name).slice());\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tfor (const [key, callbacks] of this._callbackActive) {\\n\\t\\t\\t\\tif (!this._callbacks.has(key)) {\\n\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._callbacks.get(key) !== callbacks) {\\n\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._callbackActive.set(key, callbacks.slice());\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (!name) {\\n\\t\\t\\tfor (const callbacks of this._callbacks.values()) {\\n\\t\\t\\t\\tfor (let i = 0; i < callbacks.length; i++) {\\n\\t\\t\\t\\t\\tcallbacks[i].removed = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis._callbacks.clear();\\n\\t\\t} else if (!callback) {\\n\\t\\t\\tconst callbacks = this._callbacks.get(name);\\n\\t\\t\\tif (callbacks) {\\n\\t\\t\\t\\tfor (let i = 0; i < callbacks.length; i++) {\\n\\t\\t\\t\\t\\tcallbacks[i].removed = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._callbacks.delete(name);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tconst callbacks = this._callbacks.get(name);\\n\\t\\t\\tif (!callbacks) {\\n\\t\\t\\t\\treturn this;\\n\\t\\t\\t}\\n\\t\\t\\tfor (let i = 0; i < callbacks.length; i++) {\\n\\t\\t\\t\\tif (callbacks[i].callback !== callback) {\\n\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (scope && callbacks[i].scope !== scope) {\\n\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcallbacks[i].removed = true;\\n\\t\\t\\t\\tcallbacks.splice(i, 1);\\n\\t\\t\\t\\ti--;\\n\\t\\t\\t}\\n\\t\\t\\tif (callbacks.length === 0) {\\n\\t\\t\\t\\tthis._callbacks.delete(name);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\toffByHandle(handle) {\\n\\t\\tconst name = handle.name;\\n\\t\\thandle.removed = true;\\n\\t\\tif (this._callbackActive.has(name) && this._callbackActive.get(name) === this._callbacks.get(name)) {\\n\\t\\t\\tthis._callbackActive.set(name, this._callbackActive.get(name).slice());\\n\\t\\t}\\n\\t\\tconst callbacks = this._callbacks.get(name);\\n\\t\\tif (!callbacks) {\\n\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tconst ind = callbacks.indexOf(handle);\\n\\t\\tif (ind !== -1) {\\n\\t\\t\\tcallbacks.splice(ind, 1);\\n\\t\\t\\tif (callbacks.length === 0) {\\n\\t\\t\\t\\tthis._callbacks.delete(name);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\tfire(name, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) {\\n\\t\\tif (!name) {\\n\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tconst callbacksInitial = this._callbacks.get(name);\\n\\t\\tif (!callbacksInitial) {\\n\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tlet callbacks;\\n\\t\\tif (!this._callbackActive.has(name)) {\\n\\t\\t\\tthis._callbackActive.set(name, callbacksInitial);\\n\\t\\t} else if (this._callbackActive.get(name) !== callbacksInitial) {\\n\\t\\t\\tcallbacks = callbacksInitial.slice();\\n\\t\\t}\\n\\t\\tfor (let i = 0; (callbacks || this._callbackActive.get(name)) && i < (callbacks || this._callbackActive.get(name)).length; i++) {\\n\\t\\t\\tconst evt = (callbacks || this._callbackActive.get(name))[i];\\n\\t\\t\\tif (!evt.callback) continue;\\n\\t\\t\\tevt.callback.call(evt.scope, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);\\n\\t\\t\\tif (evt._once) {\\n\\t\\t\\t\\tconst existingCallback = this._callbacks.get(name);\\n\\t\\t\\t\\tconst ind = existingCallback ? existingCallback.indexOf(evt) : -1;\\n\\t\\t\\t\\tif (ind !== -1) {\\n\\t\\t\\t\\t\\tif (this._callbackActive.get(name) === existingCallback) {\\n\\t\\t\\t\\t\\t\\tthis._callbackActive.set(name, this._callbackActive.get(name).slice());\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tconst callbacks2 = this._callbacks.get(name);\\n\\t\\t\\t\\t\\tif (!callbacks2) continue;\\n\\t\\t\\t\\t\\tcallbacks2[ind].removed = true;\\n\\t\\t\\t\\t\\tcallbacks2.splice(ind, 1);\\n\\t\\t\\t\\t\\tif (callbacks2.length === 0) {\\n\\t\\t\\t\\t\\t\\tthis._callbacks.delete(name);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (!callbacks) {\\n\\t\\t\\tthis._callbackActive.delete(name);\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\thasEvent(name) {\\n\\t\\treturn !!this._callbacks.get(name)?.length;\\n\\t}\\n}\\n\\nconst cachedResult = (func) => {\\n\\tconst uninitToken = {};\\n\\tlet result = uninitToken;\\n\\treturn () => {\\n\\t\\tif (result === uninitToken) {\\n\\t\\t\\tresult = func();\\n\\t\\t}\\n\\t\\treturn result;\\n\\t};\\n};\\nclass Impl {\\n\\tstatic modules = {};\\n\\t// returns true if the running host supports wasm modules (all browsers except IE)\\n\\tstatic wasmSupported = cachedResult(() => {\\n\\t\\ttry {\\n\\t\\t\\tif (typeof WebAssembly === \\\"object\\\" && typeof WebAssembly.instantiate === \\\"function\\\") {\\n\\t\\t\\t\\tconst module = new WebAssembly.Module(Uint8Array.of(0, 97, 115, 109, 1, 0, 0, 0));\\n\\t\\t\\t\\tif (module instanceof WebAssembly.Module) {\\n\\t\\t\\t\\t\\treturn new WebAssembly.Instance(module) instanceof WebAssembly.Instance;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t} catch (e) {\\n\\t\\t}\\n\\t\\treturn false;\\n\\t});\\n\\t// load a script\\n\\tstatic loadScript(url, callback) {\\n\\t\\tconst s = document.createElement(\\\"script\\\");\\n\\t\\ts.setAttribute(\\\"src\\\", url);\\n\\t\\ts.onload = () => {\\n\\t\\t\\tcallback(null);\\n\\t\\t};\\n\\t\\ts.onerror = () => {\\n\\t\\t\\tcallback(`Failed to load script='${url}'`);\\n\\t\\t};\\n\\t\\tdocument.body.appendChild(s);\\n\\t}\\n\\t// load a wasm module\\n\\tstatic loadWasm(moduleName, config, callback) {\\n\\t\\tconst loadUrl = Impl.wasmSupported() && config.glueUrl && config.wasmUrl ? config.glueUrl : config.fallbackUrl;\\n\\t\\tif (loadUrl) {\\n\\t\\t\\tImpl.loadScript(loadUrl, (err) => {\\n\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\tcallback(err, null);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tconst module = window[moduleName];\\n\\t\\t\\t\\t\\twindow[moduleName] = void 0;\\n\\t\\t\\t\\t\\tmodule({\\n\\t\\t\\t\\t\\t\\tlocateFile: () => config.wasmUrl,\\n\\t\\t\\t\\t\\t\\tonAbort: () => {\\n\\t\\t\\t\\t\\t\\t\\tcallback(\\\"wasm module aborted.\\\");\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}).then((instance) => {\\n\\t\\t\\t\\t\\t\\tcallback(null, instance);\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\tcallback(\\\"No supported wasm modules found.\\\", null);\\n\\t\\t}\\n\\t}\\n\\t// get state object for the named module\\n\\tstatic getModule(name) {\\n\\t\\tif (!Impl.modules.hasOwnProperty(name)) {\\n\\t\\t\\tImpl.modules[name] = {\\n\\t\\t\\t\\tconfig: null,\\n\\t\\t\\t\\tinitializing: false,\\n\\t\\t\\t\\tinstance: null,\\n\\t\\t\\t\\tcallbacks: []\\n\\t\\t\\t};\\n\\t\\t}\\n\\t\\treturn Impl.modules[name];\\n\\t}\\n\\tstatic initialize(moduleName, module) {\\n\\t\\tif (module.initializing) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst config = module.config;\\n\\t\\tif (config.glueUrl || config.wasmUrl || config.fallbackUrl) {\\n\\t\\t\\tmodule.initializing = true;\\n\\t\\t\\tImpl.loadWasm(moduleName, config, (err, instance) => {\\n\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\tif (config.errorHandler) {\\n\\t\\t\\t\\t\\t\\tconfig.errorHandler(err);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconsole.error(`failed to initialize module=${moduleName} error=${err}`);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tmodule.instance = instance;\\n\\t\\t\\t\\t\\tmodule.callbacks.forEach((callback) => {\\n\\t\\t\\t\\t\\t\\tcallback(instance);\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t}\\n\\t}\\n}\\nclass WasmModule {\\n\\tstatic setConfig(moduleName, config) {\\n\\t\\tconst module = Impl.getModule(moduleName);\\n\\t\\tmodule.config = config;\\n\\t\\tif (module.callbacks.length > 0) {\\n\\t\\t\\tImpl.initialize(moduleName, module);\\n\\t\\t}\\n\\t}\\n\\tstatic getConfig(moduleName) {\\n\\t\\treturn Impl.modules?.[moduleName]?.config;\\n\\t}\\n\\tstatic getInstance(moduleName, callback) {\\n\\t\\tconst module = Impl.getModule(moduleName);\\n\\t\\tif (module.instance) {\\n\\t\\t\\tcallback(module.instance);\\n\\t\\t} else {\\n\\t\\t\\tmodule.callbacks.push(callback);\\n\\t\\t\\tif (module.config) {\\n\\t\\t\\t\\tImpl.initialize(moduleName, module);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\n\\nclass ReadStream {\\n\\tarraybuffer;\\n\\tdataView;\\n\\toffset = 0;\\n\\tconstructor(arraybuffer) {\\n\\t\\tthis.arraybuffer = arraybuffer;\\n\\t\\tthis.dataView = new DataView(arraybuffer);\\n\\t}\\n\\tget remainingBytes() {\\n\\t\\treturn this.dataView.byteLength - this.offset;\\n\\t}\\n\\treset(offset = 0) {\\n\\t\\tthis.offset = offset;\\n\\t}\\n\\tskip(bytes) {\\n\\t\\tthis.offset += bytes;\\n\\t}\\n\\talign(bytes) {\\n\\t\\tthis.offset = this.offset + bytes - 1 & ~(bytes - 1);\\n\\t}\\n\\t_inc(amount) {\\n\\t\\tthis.offset += amount;\\n\\t\\treturn this.offset - amount;\\n\\t}\\n\\treadChar() {\\n\\t\\treturn String.fromCharCode(this.dataView.getUint8(this.offset++));\\n\\t}\\n\\treadChars(numChars) {\\n\\t\\tlet result = \\\"\\\";\\n\\t\\tfor (let i = 0; i < numChars; ++i) {\\n\\t\\t\\tresult += this.readChar();\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n\\treadU8() {\\n\\t\\treturn this.dataView.getUint8(this.offset++);\\n\\t}\\n\\treadU16() {\\n\\t\\treturn this.dataView.getUint16(this._inc(2), true);\\n\\t}\\n\\treadU32() {\\n\\t\\treturn this.dataView.getUint32(this._inc(4), true);\\n\\t}\\n\\treadU64() {\\n\\t\\treturn this.readU32() + 2 ** 32 * this.readU32();\\n\\t}\\n\\treadU32be() {\\n\\t\\treturn this.dataView.getUint32(this._inc(4), false);\\n\\t}\\n\\treadArray(result) {\\n\\t\\tfor (let i = 0; i < result.length; ++i) {\\n\\t\\t\\tresult[i] = this.readU8();\\n\\t\\t}\\n\\t}\\n\\treadLine() {\\n\\t\\tconst view = this.dataView;\\n\\t\\tlet result = \\\"\\\";\\n\\t\\twhile (true) {\\n\\t\\t\\tif (this.offset >= view.byteLength) {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\tconst c = String.fromCharCode(this.readU8());\\n\\t\\t\\tif (c === \\\"\\\\n\\\") {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\tresult += c;\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n}\\n\\nclass SortedLoopArray {\\n\\titems = [];\\n\\tlength = 0;\\n\\tloopIndex = -1;\\n\\t_sortBy;\\n\\t_sortHandler;\\n\\tconstructor(args) {\\n\\t\\tthis._sortBy = args.sortBy;\\n\\t\\tthis._sortHandler = this._doSort.bind(this);\\n\\t}\\n\\t_binarySearch(item) {\\n\\t\\tlet left = 0;\\n\\t\\tlet right = this.items.length - 1;\\n\\t\\tconst search = item[this._sortBy];\\n\\t\\tlet middle;\\n\\t\\tlet current;\\n\\t\\twhile (left <= right) {\\n\\t\\t\\tmiddle = Math.floor((left + right) / 2);\\n\\t\\t\\tcurrent = this.items[middle][this._sortBy];\\n\\t\\t\\tif (current <= search) {\\n\\t\\t\\t\\tleft = middle + 1;\\n\\t\\t\\t} else if (current > search) {\\n\\t\\t\\t\\tright = middle - 1;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn left;\\n\\t}\\n\\t_doSort(a, b) {\\n\\t\\tconst sortBy = this._sortBy;\\n\\t\\treturn a[sortBy] - b[sortBy];\\n\\t}\\n\\tinsert(item) {\\n\\t\\tconst index = this._binarySearch(item);\\n\\t\\tthis.items.splice(index, 0, item);\\n\\t\\tthis.length++;\\n\\t\\tif (this.loopIndex >= index) {\\n\\t\\t\\tthis.loopIndex++;\\n\\t\\t}\\n\\t}\\n\\tappend(item) {\\n\\t\\tthis.items.push(item);\\n\\t\\tthis.length++;\\n\\t}\\n\\tremove(item) {\\n\\t\\tconst idx = this.items.indexOf(item);\\n\\t\\tif (idx < 0) return;\\n\\t\\tthis.items.splice(idx, 1);\\n\\t\\tthis.length--;\\n\\t\\tif (this.loopIndex >= idx) {\\n\\t\\t\\tthis.loopIndex--;\\n\\t\\t}\\n\\t}\\n\\tsort() {\\n\\t\\tconst current = this.loopIndex >= 0 ? this.items[this.loopIndex] : null;\\n\\t\\tthis.items.sort(this._sortHandler);\\n\\t\\tif (current !== null) {\\n\\t\\t\\tthis.loopIndex = this.items.indexOf(current);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass Tags extends EventHandler {\\n\\tstatic EVENT_ADD = \\\"add\\\";\\n\\tstatic EVENT_REMOVE = \\\"remove\\\";\\n\\tstatic EVENT_CHANGE = \\\"change\\\";\\n\\t_index = {};\\n\\t_list = [];\\n\\t_parent;\\n\\tconstructor(parent) {\\n\\t\\tsuper();\\n\\t\\tthis._parent = parent;\\n\\t}\\n\\tadd(...args) {\\n\\t\\tlet changed = false;\\n\\t\\tconst tags = this._processArguments(args, true);\\n\\t\\tif (!tags.length) {\\n\\t\\t\\treturn changed;\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < tags.length; i++) {\\n\\t\\t\\tif (this._index[tags[i]]) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tchanged = true;\\n\\t\\t\\tthis._index[tags[i]] = true;\\n\\t\\t\\tthis._list.push(tags[i]);\\n\\t\\t\\tthis.fire(\\\"add\\\", tags[i], this._parent);\\n\\t\\t}\\n\\t\\tif (changed) {\\n\\t\\t\\tthis.fire(\\\"change\\\", this._parent);\\n\\t\\t}\\n\\t\\treturn changed;\\n\\t}\\n\\tremove(...args) {\\n\\t\\tlet changed = false;\\n\\t\\tif (!this._list.length) {\\n\\t\\t\\treturn changed;\\n\\t\\t}\\n\\t\\tconst tags = this._processArguments(args, true);\\n\\t\\tif (!tags.length) {\\n\\t\\t\\treturn changed;\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < tags.length; i++) {\\n\\t\\t\\tif (!this._index[tags[i]]) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tchanged = true;\\n\\t\\t\\tdelete this._index[tags[i]];\\n\\t\\t\\tthis._list.splice(this._list.indexOf(tags[i]), 1);\\n\\t\\t\\tthis.fire(\\\"remove\\\", tags[i], this._parent);\\n\\t\\t}\\n\\t\\tif (changed) {\\n\\t\\t\\tthis.fire(\\\"change\\\", this._parent);\\n\\t\\t}\\n\\t\\treturn changed;\\n\\t}\\n\\tclear() {\\n\\t\\tif (!this._list.length) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst tags = this._list.slice(0);\\n\\t\\tthis._list = [];\\n\\t\\tthis._index = {};\\n\\t\\tfor (let i = 0; i < tags.length; i++) {\\n\\t\\t\\tthis.fire(\\\"remove\\\", tags[i], this._parent);\\n\\t\\t}\\n\\t\\tthis.fire(\\\"change\\\", this._parent);\\n\\t}\\n\\thas(...query) {\\n\\t\\tif (!this._list.length) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\treturn this._has(this._processArguments(query));\\n\\t}\\n\\t_has(tags) {\\n\\t\\tif (!this._list.length || !tags.length) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < tags.length; i++) {\\n\\t\\t\\tif (tags[i].length === 1) {\\n\\t\\t\\t\\tif (this._index[tags[i][0]]) {\\n\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tlet multiple = true;\\n\\t\\t\\t\\tfor (let t = 0; t < tags[i].length; t++) {\\n\\t\\t\\t\\t\\tif (this._index[tags[i][t]]) {\\n\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tmultiple = false;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (multiple) {\\n\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn false;\\n\\t}\\n\\tlist() {\\n\\t\\treturn this._list.slice(0);\\n\\t}\\n\\t_processArguments(args, flat) {\\n\\t\\tconst tags = [];\\n\\t\\tlet tmp = [];\\n\\t\\tif (!args || !args.length) {\\n\\t\\t\\treturn tags;\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < args.length; i++) {\\n\\t\\t\\tif (args[i] instanceof Array) {\\n\\t\\t\\t\\tif (!flat) {\\n\\t\\t\\t\\t\\ttmp = [];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (let t = 0; t < args[i].length; t++) {\\n\\t\\t\\t\\t\\tif (typeof args[i][t] !== \\\"string\\\") {\\n\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (flat) {\\n\\t\\t\\t\\t\\t\\ttags.push(args[i][t]);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\ttmp.push(args[i][t]);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!flat && tmp.length) {\\n\\t\\t\\t\\t\\ttags.push(tmp);\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else if (typeof args[i] === \\\"string\\\") {\\n\\t\\t\\t\\tif (flat) {\\n\\t\\t\\t\\t\\ttags.push(args[i]);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\ttags.push([args[i]]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn tags;\\n\\t}\\n\\tget size() {\\n\\t\\treturn this._list.length;\\n\\t}\\n}\\n\\nconst now = typeof window !== \\\"undefined\\\" && window.performance && window.performance.now ? performance.now.bind(performance) : Date.now;\\n\\nconst re = /^(([^:/?#]+):)?(\\\\/\\\\/([^/?#]*))?([^?#]*)(\\\\?([^#]*))?(#(.*))?/;\\nclass URI {\\n\\tscheme;\\n\\tauthority;\\n\\tpath;\\n\\tquery;\\n\\tfragment;\\n\\tconstructor(uri) {\\n\\t\\tconst result = uri.match(re);\\n\\t\\tthis.scheme = result[2];\\n\\t\\tthis.authority = result[4];\\n\\t\\tthis.path = result[5];\\n\\t\\tthis.query = result[7];\\n\\t\\tthis.fragment = result[9];\\n\\t}\\n\\ttoString() {\\n\\t\\tlet s = \\\"\\\";\\n\\t\\tif (this.scheme) {\\n\\t\\t\\ts += `${this.scheme}:`;\\n\\t\\t}\\n\\t\\tif (this.authority) {\\n\\t\\t\\ts += `//${this.authority}`;\\n\\t\\t}\\n\\t\\ts += this.path;\\n\\t\\tif (this.query) {\\n\\t\\t\\ts += `?${this.query}`;\\n\\t\\t}\\n\\t\\tif (this.fragment) {\\n\\t\\t\\ts += `#${this.fragment}`;\\n\\t\\t}\\n\\t\\treturn s;\\n\\t}\\n\\tgetQuery() {\\n\\t\\tconst result = {};\\n\\t\\tif (this.query) {\\n\\t\\t\\tconst queryParams = decodeURIComponent(this.query).split(\\\"&\\\");\\n\\t\\t\\tfor (const queryParam of queryParams) {\\n\\t\\t\\t\\tconst pair = queryParam.split(\\\"=\\\");\\n\\t\\t\\t\\tresult[pair[0]] = pair[1];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n\\tsetQuery(params) {\\n\\t\\tlet q = \\\"\\\";\\n\\t\\tfor (const key in params) {\\n\\t\\t\\tif (params.hasOwnProperty(key)) {\\n\\t\\t\\t\\tif (q !== \\\"\\\") {\\n\\t\\t\\t\\t\\tq += \\\"&\\\";\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tq += `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.query = q;\\n\\t}\\n}\\n\\nclass Tracing {\\n\\tstatic _traceChannels = /* @__PURE__ */ new Set();\\n\\tstatic stack = false;\\n\\tstatic set(channel, enabled = true) {\\n\\t}\\n\\tstatic get(channel) {\\n\\t\\treturn Tracing._traceChannels.has(channel);\\n\\t}\\n}\\n\\nconst CURVE_LINEAR = 0;\\nconst CURVE_SMOOTHSTEP = 1;\\nconst CURVE_SPLINE = 4;\\nconst CURVE_STEP = 5;\\n\\nconst math = {\\n\\tDEG_TO_RAD: Math.PI / 180,\\n\\tRAD_TO_DEG: 180 / Math.PI,\\n\\tclamp(value, min, max) {\\n\\t\\tif (value >= max) return max;\\n\\t\\tif (value <= min) return min;\\n\\t\\treturn value;\\n\\t},\\n\\tintToBytes24(i) {\\n\\t\\tconst r = i >> 16 & 255;\\n\\t\\tconst g = i >> 8 & 255;\\n\\t\\tconst b = i & 255;\\n\\t\\treturn [r, g, b];\\n\\t},\\n\\tintToBytes32(i) {\\n\\t\\tconst r = i >> 24 & 255;\\n\\t\\tconst g = i >> 16 & 255;\\n\\t\\tconst b = i >> 8 & 255;\\n\\t\\tconst a = i & 255;\\n\\t\\treturn [r, g, b, a];\\n\\t},\\n\\tbytesToInt24(r, g, b) {\\n\\t\\tif (r.length) {\\n\\t\\t\\tb = r[2];\\n\\t\\t\\tg = r[1];\\n\\t\\t\\tr = r[0];\\n\\t\\t}\\n\\t\\treturn r << 16 | g << 8 | b;\\n\\t},\\n\\tbytesToInt32(r, g, b, a) {\\n\\t\\tif (r.length) {\\n\\t\\t\\ta = r[3];\\n\\t\\t\\tb = r[2];\\n\\t\\t\\tg = r[1];\\n\\t\\t\\tr = r[0];\\n\\t\\t}\\n\\t\\treturn (r << 24 | g << 16 | b << 8 | a) >>> 0;\\n\\t},\\n\\tlerp(a, b, alpha) {\\n\\t\\treturn a + (b - a) * math.clamp(alpha, 0, 1);\\n\\t},\\n\\tlerpAngle(a, b, alpha) {\\n\\t\\tif (b - a > 180) {\\n\\t\\t\\tb -= 360;\\n\\t\\t}\\n\\t\\tif (b - a < -180) {\\n\\t\\t\\tb += 360;\\n\\t\\t}\\n\\t\\treturn math.lerp(a, b, math.clamp(alpha, 0, 1));\\n\\t},\\n\\tpowerOfTwo(x) {\\n\\t\\treturn x !== 0 && !(x & x - 1);\\n\\t},\\n\\tnextPowerOfTwo(val) {\\n\\t\\tval--;\\n\\t\\tval |= val >> 1;\\n\\t\\tval |= val >> 2;\\n\\t\\tval |= val >> 4;\\n\\t\\tval |= val >> 8;\\n\\t\\tval |= val >> 16;\\n\\t\\tval++;\\n\\t\\treturn val;\\n\\t},\\n\\tnearestPowerOfTwo(val) {\\n\\t\\treturn Math.pow(2, Math.round(Math.log2(val)));\\n\\t},\\n\\trandom(min, max) {\\n\\t\\tconst diff = max - min;\\n\\t\\treturn Math.random() * diff + min;\\n\\t},\\n\\tsmoothstep(min, max, x) {\\n\\t\\tif (x <= min) return 0;\\n\\t\\tif (x >= max) return 1;\\n\\t\\tx = (x - min) / (max - min);\\n\\t\\treturn x * x * (3 - 2 * x);\\n\\t},\\n\\tsmootherstep(min, max, x) {\\n\\t\\tif (x <= min) return 0;\\n\\t\\tif (x >= max) return 1;\\n\\t\\tx = (x - min) / (max - min);\\n\\t\\treturn x * x * x * (x * (x * 6 - 15) + 10);\\n\\t},\\n\\troundUp(numToRound, multiple) {\\n\\t\\tif (multiple === 0) {\\n\\t\\t\\treturn numToRound;\\n\\t\\t}\\n\\t\\treturn Math.ceil(numToRound / multiple) * multiple;\\n\\t},\\n\\tbetween(num, a, b, inclusive) {\\n\\t\\tconst min = Math.min(a, b);\\n\\t\\tconst max = Math.max(a, b);\\n\\t\\treturn inclusive ? num >= min && num <= max : num > min && num < max;\\n\\t}\\n};\\n\\nclass Color {\\n\\tr;\\n\\tg;\\n\\tb;\\n\\ta;\\n\\tconstructor(r = 0, g = 0, b = 0, a = 1) {\\n\\t\\tconst length = r.length;\\n\\t\\tif (length === 3 || length === 4) {\\n\\t\\t\\tthis.r = r[0];\\n\\t\\t\\tthis.g = r[1];\\n\\t\\t\\tthis.b = r[2];\\n\\t\\t\\tthis.a = r[3] ?? 1;\\n\\t\\t} else {\\n\\t\\t\\tthis.r = r;\\n\\t\\t\\tthis.g = g;\\n\\t\\t\\tthis.b = b;\\n\\t\\t\\tthis.a = a;\\n\\t\\t}\\n\\t}\\n\\tclone() {\\n\\t\\tconst cstr = this.constructor;\\n\\t\\treturn new cstr(this.r, this.g, this.b, this.a);\\n\\t}\\n\\tcopy(rhs) {\\n\\t\\tthis.r = rhs.r;\\n\\t\\tthis.g = rhs.g;\\n\\t\\tthis.b = rhs.b;\\n\\t\\tthis.a = rhs.a;\\n\\t\\treturn this;\\n\\t}\\n\\tequals(rhs) {\\n\\t\\treturn this.r === rhs.r && this.g === rhs.g && this.b === rhs.b && this.a === rhs.a;\\n\\t}\\n\\tset(r, g, b, a = 1) {\\n\\t\\tthis.r = r;\\n\\t\\tthis.g = g;\\n\\t\\tthis.b = b;\\n\\t\\tthis.a = a;\\n\\t\\treturn this;\\n\\t}\\n\\tlerp(lhs, rhs, alpha) {\\n\\t\\tthis.r = lhs.r + alpha * (rhs.r - lhs.r);\\n\\t\\tthis.g = lhs.g + alpha * (rhs.g - lhs.g);\\n\\t\\tthis.b = lhs.b + alpha * (rhs.b - lhs.b);\\n\\t\\tthis.a = lhs.a + alpha * (rhs.a - lhs.a);\\n\\t\\treturn this;\\n\\t}\\n\\tlinear(src = this) {\\n\\t\\tthis.r = Math.pow(src.r, 2.2);\\n\\t\\tthis.g = Math.pow(src.g, 2.2);\\n\\t\\tthis.b = Math.pow(src.b, 2.2);\\n\\t\\tthis.a = src.a;\\n\\t\\treturn this;\\n\\t}\\n\\tgamma(src = this) {\\n\\t\\tthis.r = Math.pow(src.r, 1 / 2.2);\\n\\t\\tthis.g = Math.pow(src.g, 1 / 2.2);\\n\\t\\tthis.b = Math.pow(src.b, 1 / 2.2);\\n\\t\\tthis.a = src.a;\\n\\t\\treturn this;\\n\\t}\\n\\tmulScalar(scalar) {\\n\\t\\tthis.r *= scalar;\\n\\t\\tthis.g *= scalar;\\n\\t\\tthis.b *= scalar;\\n\\t\\treturn this;\\n\\t}\\n\\tfromString(hex) {\\n\\t\\tconst i = parseInt(hex.replace(\\\"#\\\", \\\"0x\\\"), 16);\\n\\t\\tlet bytes;\\n\\t\\tif (hex.length > 7) {\\n\\t\\t\\tbytes = math.intToBytes32(i);\\n\\t\\t} else {\\n\\t\\t\\tbytes = math.intToBytes24(i);\\n\\t\\t\\tbytes[3] = 255;\\n\\t\\t}\\n\\t\\tthis.set(bytes[0] / 255, bytes[1] / 255, bytes[2] / 255, bytes[3] / 255);\\n\\t\\treturn this;\\n\\t}\\n\\tfromArray(arr, offset = 0) {\\n\\t\\tthis.r = arr[offset] ?? this.r;\\n\\t\\tthis.g = arr[offset + 1] ?? this.g;\\n\\t\\tthis.b = arr[offset + 2] ?? this.b;\\n\\t\\tthis.a = arr[offset + 3] ?? this.a;\\n\\t\\treturn this;\\n\\t}\\n\\ttoString(alpha, asArray) {\\n\\t\\tconst { r, g, b, a } = this;\\n\\t\\tif (asArray || r > 1 || g > 1 || b > 1) {\\n\\t\\t\\treturn `${r.toFixed(3)}, ${g.toFixed(3)}, ${b.toFixed(3)}, ${a.toFixed(3)}`;\\n\\t\\t}\\n\\t\\tlet s = `#${((1 << 24) + (Math.round(r * 255) << 16) + (Math.round(g * 255) << 8) + Math.round(b * 255)).toString(16).slice(1)}`;\\n\\t\\tif (alpha === true) {\\n\\t\\t\\tconst aa = Math.round(a * 255).toString(16);\\n\\t\\t\\tif (this.a < 16 / 255) {\\n\\t\\t\\t\\ts += `0${aa}`;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\ts += aa;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn s;\\n\\t}\\n\\ttoArray(arr = [], offset = 0, alpha = true) {\\n\\t\\tarr[offset] = this.r;\\n\\t\\tarr[offset + 1] = this.g;\\n\\t\\tarr[offset + 2] = this.b;\\n\\t\\tif (alpha) {\\n\\t\\t\\tarr[offset + 3] = this.a;\\n\\t\\t}\\n\\t\\treturn arr;\\n\\t}\\n\\tstatic BLACK = Object.freeze(new Color(0, 0, 0, 1));\\n\\tstatic BLUE = Object.freeze(new Color(0, 0, 1, 1));\\n\\tstatic CYAN = Object.freeze(new Color(0, 1, 1, 1));\\n\\tstatic GRAY = Object.freeze(new Color(0.5, 0.5, 0.5, 1));\\n\\tstatic GREEN = Object.freeze(new Color(0, 1, 0, 1));\\n\\tstatic MAGENTA = Object.freeze(new Color(1, 0, 1, 1));\\n\\tstatic RED = Object.freeze(new Color(1, 0, 0, 1));\\n\\tstatic WHITE = Object.freeze(new Color(1, 1, 1, 1));\\n\\tstatic YELLOW = Object.freeze(new Color(1, 1, 0, 1));\\n}\\n\\nclass CurveEvaluator {\\n\\t_curve;\\n\\t_left = -Infinity;\\n\\t_right = Infinity;\\n\\t_recip = 0;\\n\\t_p0 = 0;\\n\\t_p1 = 0;\\n\\t_m0 = 0;\\n\\t_m1 = 0;\\n\\tconstructor(curve, time = 0) {\\n\\t\\tthis._curve = curve;\\n\\t\\tthis._reset(time);\\n\\t}\\n\\tevaluate(time, forceReset = false) {\\n\\t\\tif (forceReset || time < this._left || time >= this._right) {\\n\\t\\t\\tthis._reset(time);\\n\\t\\t}\\n\\t\\tlet result;\\n\\t\\tconst type = this._curve.type;\\n\\t\\tif (type === CURVE_STEP) {\\n\\t\\t\\tresult = this._p0;\\n\\t\\t} else {\\n\\t\\t\\tconst t = this._recip === 0 ? 0 : (time - this._left) * this._recip;\\n\\t\\t\\tif (type === CURVE_LINEAR) {\\n\\t\\t\\t\\tresult = math.lerp(this._p0, this._p1, t);\\n\\t\\t\\t} else if (type === CURVE_SMOOTHSTEP) {\\n\\t\\t\\t\\tresult = math.lerp(this._p0, this._p1, t * t * (3 - 2 * t));\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tresult = this._evaluateHermite(this._p0, this._p1, this._m0, this._m1, t);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n\\t_reset(time) {\\n\\t\\tconst keys = this._curve.keys;\\n\\t\\tconst len = keys.length;\\n\\t\\tif (!len) {\\n\\t\\t\\tthis._left = -Infinity;\\n\\t\\t\\tthis._right = Infinity;\\n\\t\\t\\tthis._recip = 0;\\n\\t\\t\\tthis._p0 = this._p1 = this._m0 = this._m1 = 0;\\n\\t\\t} else {\\n\\t\\t\\tif (time < keys[0][0]) {\\n\\t\\t\\t\\tthis._left = -Infinity;\\n\\t\\t\\t\\tthis._right = keys[0][0];\\n\\t\\t\\t\\tthis._recip = 0;\\n\\t\\t\\t\\tthis._p0 = this._p1 = keys[0][1];\\n\\t\\t\\t\\tthis._m0 = this._m1 = 0;\\n\\t\\t\\t} else if (time >= keys[len - 1][0]) {\\n\\t\\t\\t\\tthis._left = keys[len - 1][0];\\n\\t\\t\\t\\tthis._right = Infinity;\\n\\t\\t\\t\\tthis._recip = 0;\\n\\t\\t\\t\\tthis._p0 = this._p1 = keys[len - 1][1];\\n\\t\\t\\t\\tthis._m0 = this._m1 = 0;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tlet index = 0;\\n\\t\\t\\t\\twhile (time >= keys[index + 1][0]) {\\n\\t\\t\\t\\t\\tindex++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._left = keys[index][0];\\n\\t\\t\\t\\tthis._right = keys[index + 1][0];\\n\\t\\t\\t\\tconst diff = 1 / (this._right - this._left);\\n\\t\\t\\t\\tthis._recip = isFinite(diff) ? diff : 0;\\n\\t\\t\\t\\tthis._p0 = keys[index][1];\\n\\t\\t\\t\\tthis._p1 = keys[index + 1][1];\\n\\t\\t\\t\\tif (this._curve.type === CURVE_SPLINE) {\\n\\t\\t\\t\\t\\tthis._calcTangents(keys, index);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_calcTangents(keys, index) {\\n\\t\\tlet a;\\n\\t\\tconst b = keys[index];\\n\\t\\tconst c = keys[index + 1];\\n\\t\\tlet d;\\n\\t\\tif (index === 0) {\\n\\t\\t\\ta = [\\n\\t\\t\\t\\tkeys[0][0] + (keys[0][0] - keys[1][0]),\\n\\t\\t\\t\\tkeys[0][1] + (keys[0][1] - keys[1][1])\\n\\t\\t\\t];\\n\\t\\t} else {\\n\\t\\t\\ta = keys[index - 1];\\n\\t\\t}\\n\\t\\tif (index === keys.length - 2) {\\n\\t\\t\\td = [\\n\\t\\t\\t\\tkeys[index + 1][0] + (keys[index + 1][0] - keys[index][0]),\\n\\t\\t\\t\\tkeys[index + 1][1] + (keys[index + 1][1] - keys[index][1])\\n\\t\\t\\t];\\n\\t\\t} else {\\n\\t\\t\\td = keys[index + 2];\\n\\t\\t}\\n\\t\\tif (this._curve.type === CURVE_SPLINE) {\\n\\t\\t\\tconst s1_ = 2 * (c[0] - b[0]) / (c[0] - a[0]);\\n\\t\\t\\tconst s2_ = 2 * (c[0] - b[0]) / (d[0] - b[0]);\\n\\t\\t\\tthis._m0 = this._curve.tension * (isFinite(s1_) ? s1_ : 0) * (c[1] - a[1]);\\n\\t\\t\\tthis._m1 = this._curve.tension * (isFinite(s2_) ? s2_ : 0) * (d[1] - b[1]);\\n\\t\\t} else {\\n\\t\\t\\tconst s1 = (c[0] - b[0]) / (b[0] - a[0]);\\n\\t\\t\\tconst s2 = (c[0] - b[0]) / (d[0] - c[0]);\\n\\t\\t\\tconst a_ = b[1] + (a[1] - b[1]) * (isFinite(s1) ? s1 : 0);\\n\\t\\t\\tconst d_ = c[1] + (d[1] - c[1]) * (isFinite(s2) ? s2 : 0);\\n\\t\\t\\tconst tension = this._curve.tension;\\n\\t\\t\\tthis._m0 = tension * (c[1] - a_);\\n\\t\\t\\tthis._m1 = tension * (d_ - b[1]);\\n\\t\\t}\\n\\t}\\n\\t_evaluateHermite(p0, p1, m0, m1, t) {\\n\\t\\tconst t2 = t * t;\\n\\t\\tconst twot = t + t;\\n\\t\\tconst omt = 1 - t;\\n\\t\\tconst omt2 = omt * omt;\\n\\t\\treturn p0 * ((1 + twot) * omt2) + m0 * (t * omt2) + p1 * (t2 * (3 - twot)) + m1 * (t2 * (t - 1));\\n\\t}\\n}\\n\\nclass Curve {\\n\\tkeys = [];\\n\\ttype = CURVE_SMOOTHSTEP;\\n\\ttension = 0.5;\\n\\t_eval = new CurveEvaluator(this);\\n\\tconstructor(data) {\\n\\t\\tif (data) {\\n\\t\\t\\tfor (let i = 0; i < data.length - 1; i += 2) {\\n\\t\\t\\t\\tthis.keys.push([data[i], data[i + 1]]);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.sort();\\n\\t}\\n\\tget length() {\\n\\t\\treturn this.keys.length;\\n\\t}\\n\\tadd(time, value) {\\n\\t\\tconst keys = this.keys;\\n\\t\\tconst len = keys.length;\\n\\t\\tlet i = 0;\\n\\t\\tfor (; i < len; i++) {\\n\\t\\t\\tif (keys[i][0] > time) {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst key = [time, value];\\n\\t\\tthis.keys.splice(i, 0, key);\\n\\t\\treturn key;\\n\\t}\\n\\tget(index) {\\n\\t\\treturn this.keys[index];\\n\\t}\\n\\tsort() {\\n\\t\\tthis.keys.sort((a, b) => a[0] - b[0]);\\n\\t}\\n\\tvalue(time) {\\n\\t\\treturn this._eval.evaluate(time, true);\\n\\t}\\n\\tclosest(time) {\\n\\t\\tconst keys = this.keys;\\n\\t\\tconst length = keys.length;\\n\\t\\tlet min = 2;\\n\\t\\tlet result = null;\\n\\t\\tfor (let i = 0; i < length; i++) {\\n\\t\\t\\tconst diff = Math.abs(time - keys[i][0]);\\n\\t\\t\\tif (min >= diff) {\\n\\t\\t\\t\\tmin = diff;\\n\\t\\t\\t\\tresult = keys[i];\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n\\tclone() {\\n\\t\\tconst result = new this.constructor();\\n\\t\\tresult.keys = this.keys.map((key) => [...key]);\\n\\t\\tresult.type = this.type;\\n\\t\\tresult.tension = this.tension;\\n\\t\\treturn result;\\n\\t}\\n\\tquantize(precision) {\\n\\t\\tprecision = Math.max(precision, 2);\\n\\t\\tconst values = new Float32Array(precision);\\n\\t\\tconst step = 1 / (precision - 1);\\n\\t\\tvalues[0] = this._eval.evaluate(0, true);\\n\\t\\tfor (let i = 1; i < precision; i++) {\\n\\t\\t\\tvalues[i] = this._eval.evaluate(step * i);\\n\\t\\t}\\n\\t\\treturn values;\\n\\t}\\n\\tquantizeClamped(precision, min, max) {\\n\\t\\tconst result = this.quantize(precision);\\n\\t\\tfor (let i = 0; i < result.length; ++i) {\\n\\t\\t\\tresult[i] = Math.min(max, Math.max(min, result[i]));\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n}\\n\\nclass CurveSet {\\n\\tcurves = [];\\n\\t_type = CURVE_SMOOTHSTEP;\\n\\tconstructor(...args) {\\n\\t\\tif (args.length > 1) {\\n\\t\\t\\tfor (let i = 0; i < args.length; i++) {\\n\\t\\t\\t\\tthis.curves.push(new Curve(args[i]));\\n\\t\\t\\t}\\n\\t\\t} else if (args.length === 0) {\\n\\t\\t\\tthis.curves.push(new Curve());\\n\\t\\t} else {\\n\\t\\t\\tconst arg = args[0];\\n\\t\\t\\tif (typeof arg === \\\"number\\\") {\\n\\t\\t\\t\\tfor (let i = 0; i < arg; i++) {\\n\\t\\t\\t\\t\\tthis.curves.push(new Curve());\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tfor (let i = 0; i < arg.length; i++) {\\n\\t\\t\\t\\t\\tthis.curves.push(new Curve(arg[i]));\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget length() {\\n\\t\\treturn this.curves.length;\\n\\t}\\n\\tset type(value) {\\n\\t\\tthis._type = value;\\n\\t\\tfor (let i = 0; i < this.curves.length; i++) {\\n\\t\\t\\tthis.curves[i].type = value;\\n\\t\\t}\\n\\t}\\n\\tget type() {\\n\\t\\treturn this._type;\\n\\t}\\n\\tget(index) {\\n\\t\\treturn this.curves[index];\\n\\t}\\n\\tvalue(time, result = []) {\\n\\t\\tconst length = this.curves.length;\\n\\t\\tresult.length = length;\\n\\t\\tfor (let i = 0; i < length; i++) {\\n\\t\\t\\tresult[i] = this.curves[i].value(time);\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n\\tclone() {\\n\\t\\tconst result = new this.constructor();\\n\\t\\tresult.curves = [];\\n\\t\\tfor (let i = 0; i < this.curves.length; i++) {\\n\\t\\t\\tresult.curves.push(this.curves[i].clone());\\n\\t\\t}\\n\\t\\tresult._type = this._type;\\n\\t\\treturn result;\\n\\t}\\n\\tquantize(precision) {\\n\\t\\tprecision = Math.max(precision, 2);\\n\\t\\tconst numCurves = this.curves.length;\\n\\t\\tconst values = new Float32Array(precision * numCurves);\\n\\t\\tconst step = 1 / (precision - 1);\\n\\t\\tfor (let c = 0; c < numCurves; c++) {\\n\\t\\t\\tconst ev = new CurveEvaluator(this.curves[c]);\\n\\t\\t\\tfor (let i = 0; i < precision; i++) {\\n\\t\\t\\t\\tvalues[i * numCurves + c] = ev.evaluate(step * i);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn values;\\n\\t}\\n\\tquantizeClamped(precision, min, max) {\\n\\t\\tconst result = this.quantize(precision);\\n\\t\\tfor (let i = 0; i < result.length; ++i) {\\n\\t\\t\\tresult[i] = Math.min(max, Math.max(min, result[i]));\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n}\\n\\nconst floatView = new Float32Array(1);\\nconst int32View = new Int32Array(floatView.buffer);\\nclass FloatPacking {\\n\\tstatic float2Half(value) {\\n\\t\\tfloatView[0] = value;\\n\\t\\tconst x = int32View[0];\\n\\t\\tlet bits = x >> 16 & 32768;\\n\\t\\tlet m = x >> 12 & 2047;\\n\\t\\tconst e = x >> 23 & 255;\\n\\t\\tif (e < 103) {\\n\\t\\t\\treturn bits;\\n\\t\\t}\\n\\t\\tif (e > 142) {\\n\\t\\t\\tbits |= 31744;\\n\\t\\t\\tbits |= (e === 255 ? 0 : 1) && x & 8388607;\\n\\t\\t\\treturn bits;\\n\\t\\t}\\n\\t\\tif (e < 113) {\\n\\t\\t\\tm |= 2048;\\n\\t\\t\\tbits |= (m >> 114 - e) + (m >> 113 - e & 1);\\n\\t\\t\\treturn bits;\\n\\t\\t}\\n\\t\\tbits |= e - 112 << 10 | m >> 1;\\n\\t\\tbits += m & 1;\\n\\t\\treturn bits;\\n\\t}\\n\\tstatic float2RGBA8(value, data) {\\n\\t\\tfloatView[0] = value;\\n\\t\\tconst intBits = int32View[0];\\n\\t\\tdata.r = (intBits >> 24 & 255) / 255;\\n\\t\\tdata.g = (intBits >> 16 & 255) / 255;\\n\\t\\tdata.b = (intBits >> 8 & 255) / 255;\\n\\t\\tdata.a = (intBits & 255) / 255;\\n\\t}\\n}\\n\\nclass Kernel {\\n\\tstatic concentric(numRings, numPoints) {\\n\\t\\tconst kernel = [];\\n\\t\\tkernel.push(0, 0);\\n\\t\\tconst spacing = 2 * Math.PI / numRings / numPoints;\\n\\t\\tfor (let ring = 1; ring <= numRings; ring++) {\\n\\t\\t\\tconst radius = ring / numRings;\\n\\t\\t\\tconst circumference = 2 * Math.PI * radius;\\n\\t\\t\\tconst pointsPerRing = Math.max(1, Math.floor(circumference / spacing));\\n\\t\\t\\tconst angleStep = 2 * Math.PI / pointsPerRing;\\n\\t\\t\\tfor (let point = 0; point < pointsPerRing; point++) {\\n\\t\\t\\t\\tconst angle = point * angleStep;\\n\\t\\t\\t\\tconst x = radius * Math.cos(angle);\\n\\t\\t\\t\\tconst y = radius * Math.sin(angle);\\n\\t\\t\\t\\tkernel.push(x, y);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn kernel;\\n\\t}\\n}\\n\\nclass Vec3 {\\n\\tx;\\n\\ty;\\n\\tz;\\n\\tconstructor(x = 0, y = 0, z = 0) {\\n\\t\\tif (x.length === 3) {\\n\\t\\t\\tthis.x = x[0];\\n\\t\\t\\tthis.y = x[1];\\n\\t\\t\\tthis.z = x[2];\\n\\t\\t} else {\\n\\t\\t\\tthis.x = x;\\n\\t\\t\\tthis.y = y;\\n\\t\\t\\tthis.z = z;\\n\\t\\t}\\n\\t}\\n\\tadd(rhs) {\\n\\t\\tthis.x += rhs.x;\\n\\t\\tthis.y += rhs.y;\\n\\t\\tthis.z += rhs.z;\\n\\t\\treturn this;\\n\\t}\\n\\tadd2(lhs, rhs) {\\n\\t\\tthis.x = lhs.x + rhs.x;\\n\\t\\tthis.y = lhs.y + rhs.y;\\n\\t\\tthis.z = lhs.z + rhs.z;\\n\\t\\treturn this;\\n\\t}\\n\\taddScalar(scalar) {\\n\\t\\tthis.x += scalar;\\n\\t\\tthis.y += scalar;\\n\\t\\tthis.z += scalar;\\n\\t\\treturn this;\\n\\t}\\n\\taddScaled(rhs, scalar) {\\n\\t\\tthis.x += rhs.x * scalar;\\n\\t\\tthis.y += rhs.y * scalar;\\n\\t\\tthis.z += rhs.z * scalar;\\n\\t\\treturn this;\\n\\t}\\n\\tclone() {\\n\\t\\tconst cstr = this.constructor;\\n\\t\\treturn new cstr(this.x, this.y, this.z);\\n\\t}\\n\\tcopy(rhs) {\\n\\t\\tthis.x = rhs.x;\\n\\t\\tthis.y = rhs.y;\\n\\t\\tthis.z = rhs.z;\\n\\t\\treturn this;\\n\\t}\\n\\tcross(lhs, rhs) {\\n\\t\\tconst lx = lhs.x;\\n\\t\\tconst ly = lhs.y;\\n\\t\\tconst lz = lhs.z;\\n\\t\\tconst rx = rhs.x;\\n\\t\\tconst ry = rhs.y;\\n\\t\\tconst rz = rhs.z;\\n\\t\\tthis.x = ly * rz - ry * lz;\\n\\t\\tthis.y = lz * rx - rz * lx;\\n\\t\\tthis.z = lx * ry - rx * ly;\\n\\t\\treturn this;\\n\\t}\\n\\tdistance(rhs) {\\n\\t\\tconst x = this.x - rhs.x;\\n\\t\\tconst y = this.y - rhs.y;\\n\\t\\tconst z = this.z - rhs.z;\\n\\t\\treturn Math.sqrt(x * x + y * y + z * z);\\n\\t}\\n\\tdiv(rhs) {\\n\\t\\tthis.x /= rhs.x;\\n\\t\\tthis.y /= rhs.y;\\n\\t\\tthis.z /= rhs.z;\\n\\t\\treturn this;\\n\\t}\\n\\tdiv2(lhs, rhs) {\\n\\t\\tthis.x = lhs.x / rhs.x;\\n\\t\\tthis.y = lhs.y / rhs.y;\\n\\t\\tthis.z = lhs.z / rhs.z;\\n\\t\\treturn this;\\n\\t}\\n\\tdivScalar(scalar) {\\n\\t\\tthis.x /= scalar;\\n\\t\\tthis.y /= scalar;\\n\\t\\tthis.z /= scalar;\\n\\t\\treturn this;\\n\\t}\\n\\tdot(rhs) {\\n\\t\\treturn this.x * rhs.x + this.y * rhs.y + this.z * rhs.z;\\n\\t}\\n\\tequals(rhs) {\\n\\t\\treturn this.x === rhs.x && this.y === rhs.y && this.z === rhs.z;\\n\\t}\\n\\tequalsApprox(rhs, epsilon = 1e-6) {\\n\\t\\treturn Math.abs(this.x - rhs.x) < epsilon && Math.abs(this.y - rhs.y) < epsilon && Math.abs(this.z - rhs.z) < epsilon;\\n\\t}\\n\\tlength() {\\n\\t\\treturn Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);\\n\\t}\\n\\tlengthSq() {\\n\\t\\treturn this.x * this.x + this.y * this.y + this.z * this.z;\\n\\t}\\n\\tlerp(lhs, rhs, alpha) {\\n\\t\\tthis.x = lhs.x + alpha * (rhs.x - lhs.x);\\n\\t\\tthis.y = lhs.y + alpha * (rhs.y - lhs.y);\\n\\t\\tthis.z = lhs.z + alpha * (rhs.z - lhs.z);\\n\\t\\treturn this;\\n\\t}\\n\\tmul(rhs) {\\n\\t\\tthis.x *= rhs.x;\\n\\t\\tthis.y *= rhs.y;\\n\\t\\tthis.z *= rhs.z;\\n\\t\\treturn this;\\n\\t}\\n\\tmul2(lhs, rhs) {\\n\\t\\tthis.x = lhs.x * rhs.x;\\n\\t\\tthis.y = lhs.y * rhs.y;\\n\\t\\tthis.z = lhs.z * rhs.z;\\n\\t\\treturn this;\\n\\t}\\n\\tmulScalar(scalar) {\\n\\t\\tthis.x *= scalar;\\n\\t\\tthis.y *= scalar;\\n\\t\\tthis.z *= scalar;\\n\\t\\treturn this;\\n\\t}\\n\\tnormalize(src = this) {\\n\\t\\tconst lengthSq = src.x * src.x + src.y * src.y + src.z * src.z;\\n\\t\\tif (lengthSq > 0) {\\n\\t\\t\\tconst invLength = 1 / Math.sqrt(lengthSq);\\n\\t\\t\\tthis.x = src.x * invLength;\\n\\t\\t\\tthis.y = src.y * invLength;\\n\\t\\t\\tthis.z = src.z * invLength;\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\tfloor(src = this) {\\n\\t\\tthis.x = Math.floor(src.x);\\n\\t\\tthis.y = Math.floor(src.y);\\n\\t\\tthis.z = Math.floor(src.z);\\n\\t\\treturn this;\\n\\t}\\n\\tceil(src = this) {\\n\\t\\tthis.x = Math.ceil(src.x);\\n\\t\\tthis.y = Math.ceil(src.y);\\n\\t\\tthis.z = Math.ceil(src.z);\\n\\t\\treturn this;\\n\\t}\\n\\tround(src = this) {\\n\\t\\tthis.x = Math.round(src.x);\\n\\t\\tthis.y = Math.round(src.y);\\n\\t\\tthis.z = Math.round(src.z);\\n\\t\\treturn this;\\n\\t}\\n\\tmin(rhs) {\\n\\t\\tif (rhs.x < this.x) this.x = rhs.x;\\n\\t\\tif (rhs.y < this.y) this.y = rhs.y;\\n\\t\\tif (rhs.z < this.z) this.z = rhs.z;\\n\\t\\treturn this;\\n\\t}\\n\\tmax(rhs) {\\n\\t\\tif (rhs.x > this.x) this.x = rhs.x;\\n\\t\\tif (rhs.y > this.y) this.y = rhs.y;\\n\\t\\tif (rhs.z > this.z) this.z = rhs.z;\\n\\t\\treturn this;\\n\\t}\\n\\tproject(rhs) {\\n\\t\\tconst a_dot_b = this.x * rhs.x + this.y * rhs.y + this.z * rhs.z;\\n\\t\\tconst b_dot_b = rhs.x * rhs.x + rhs.y * rhs.y + rhs.z * rhs.z;\\n\\t\\tconst s = a_dot_b / b_dot_b;\\n\\t\\tthis.x = rhs.x * s;\\n\\t\\tthis.y = rhs.y * s;\\n\\t\\tthis.z = rhs.z * s;\\n\\t\\treturn this;\\n\\t}\\n\\tset(x, y, z) {\\n\\t\\tthis.x = x;\\n\\t\\tthis.y = y;\\n\\t\\tthis.z = z;\\n\\t\\treturn this;\\n\\t}\\n\\tsub(rhs) {\\n\\t\\tthis.x -= rhs.x;\\n\\t\\tthis.y -= rhs.y;\\n\\t\\tthis.z -= rhs.z;\\n\\t\\treturn this;\\n\\t}\\n\\tsub2(lhs, rhs) {\\n\\t\\tthis.x = lhs.x - rhs.x;\\n\\t\\tthis.y = lhs.y - rhs.y;\\n\\t\\tthis.z = lhs.z - rhs.z;\\n\\t\\treturn this;\\n\\t}\\n\\tsubScalar(scalar) {\\n\\t\\tthis.x -= scalar;\\n\\t\\tthis.y -= scalar;\\n\\t\\tthis.z -= scalar;\\n\\t\\treturn this;\\n\\t}\\n\\tfromArray(arr, offset = 0) {\\n\\t\\tthis.x = arr[offset] ?? this.x;\\n\\t\\tthis.y = arr[offset + 1] ?? this.y;\\n\\t\\tthis.z = arr[offset + 2] ?? this.z;\\n\\t\\treturn this;\\n\\t}\\n\\ttoString() {\\n\\t\\treturn `[${this.x}, ${this.y}, ${this.z}]`;\\n\\t}\\n\\ttoArray(arr = [], offset = 0) {\\n\\t\\tarr[offset] = this.x;\\n\\t\\tarr[offset + 1] = this.y;\\n\\t\\tarr[offset + 2] = this.z;\\n\\t\\treturn arr;\\n\\t}\\n\\tstatic ZERO = Object.freeze(new Vec3(0, 0, 0));\\n\\tstatic HALF = Object.freeze(new Vec3(0.5, 0.5, 0.5));\\n\\tstatic ONE = Object.freeze(new Vec3(1, 1, 1));\\n\\tstatic UP = Object.freeze(new Vec3(0, 1, 0));\\n\\tstatic DOWN = Object.freeze(new Vec3(0, -1, 0));\\n\\tstatic RIGHT = Object.freeze(new Vec3(1, 0, 0));\\n\\tstatic LEFT = Object.freeze(new Vec3(-1, 0, 0));\\n\\tstatic FORWARD = Object.freeze(new Vec3(0, 0, -1));\\n\\tstatic BACK = Object.freeze(new Vec3(0, 0, 1));\\n}\\n\\nclass Mat3 {\\n\\tdata = new Float32Array(9);\\n\\tconstructor() {\\n\\t\\tthis.data[0] = this.data[4] = this.data[8] = 1;\\n\\t}\\n\\tclone() {\\n\\t\\tconst cstr = this.constructor;\\n\\t\\treturn new cstr().copy(this);\\n\\t}\\n\\tcopy(rhs) {\\n\\t\\tconst src = rhs.data;\\n\\t\\tconst dst = this.data;\\n\\t\\tdst[0] = src[0];\\n\\t\\tdst[1] = src[1];\\n\\t\\tdst[2] = src[2];\\n\\t\\tdst[3] = src[3];\\n\\t\\tdst[4] = src[4];\\n\\t\\tdst[5] = src[5];\\n\\t\\tdst[6] = src[6];\\n\\t\\tdst[7] = src[7];\\n\\t\\tdst[8] = src[8];\\n\\t\\treturn this;\\n\\t}\\n\\tset(src) {\\n\\t\\tconst dst = this.data;\\n\\t\\tdst[0] = src[0];\\n\\t\\tdst[1] = src[1];\\n\\t\\tdst[2] = src[2];\\n\\t\\tdst[3] = src[3];\\n\\t\\tdst[4] = src[4];\\n\\t\\tdst[5] = src[5];\\n\\t\\tdst[6] = src[6];\\n\\t\\tdst[7] = src[7];\\n\\t\\tdst[8] = src[8];\\n\\t\\treturn this;\\n\\t}\\n\\tgetX(x = new Vec3()) {\\n\\t\\treturn x.set(this.data[0], this.data[1], this.data[2]);\\n\\t}\\n\\tgetY(y = new Vec3()) {\\n\\t\\treturn y.set(this.data[3], this.data[4], this.data[5]);\\n\\t}\\n\\tgetZ(z = new Vec3()) {\\n\\t\\treturn z.set(this.data[6], this.data[7], this.data[8]);\\n\\t}\\n\\tequals(rhs) {\\n\\t\\tconst l = this.data;\\n\\t\\tconst r = rhs.data;\\n\\t\\treturn l[0] === r[0] && l[1] === r[1] && l[2] === r[2] && l[3] === r[3] && l[4] === r[4] && l[5] === r[5] && l[6] === r[6] && l[7] === r[7] && l[8] === r[8];\\n\\t}\\n\\tisIdentity() {\\n\\t\\tconst m = this.data;\\n\\t\\treturn m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 0 && m[4] === 1 && m[5] === 0 && m[6] === 0 && m[7] === 0 && m[8] === 1;\\n\\t}\\n\\tsetIdentity() {\\n\\t\\tconst m = this.data;\\n\\t\\tm[0] = 1;\\n\\t\\tm[1] = 0;\\n\\t\\tm[2] = 0;\\n\\t\\tm[3] = 0;\\n\\t\\tm[4] = 1;\\n\\t\\tm[5] = 0;\\n\\t\\tm[6] = 0;\\n\\t\\tm[7] = 0;\\n\\t\\tm[8] = 1;\\n\\t\\treturn this;\\n\\t}\\n\\ttoString() {\\n\\t\\treturn `[${this.data.join(\\\", \\\")}]`;\\n\\t}\\n\\ttranspose(src = this) {\\n\\t\\tconst s = src.data;\\n\\t\\tconst t = this.data;\\n\\t\\tif (s === t) {\\n\\t\\t\\tlet tmp;\\n\\t\\t\\ttmp = s[1];\\n\\t\\t\\tt[1] = s[3];\\n\\t\\t\\tt[3] = tmp;\\n\\t\\t\\ttmp = s[2];\\n\\t\\t\\tt[2] = s[6];\\n\\t\\t\\tt[6] = tmp;\\n\\t\\t\\ttmp = s[5];\\n\\t\\t\\tt[5] = s[7];\\n\\t\\t\\tt[7] = tmp;\\n\\t\\t} else {\\n\\t\\t\\tt[0] = s[0];\\n\\t\\t\\tt[1] = s[3];\\n\\t\\t\\tt[2] = s[6];\\n\\t\\t\\tt[3] = s[1];\\n\\t\\t\\tt[4] = s[4];\\n\\t\\t\\tt[5] = s[7];\\n\\t\\t\\tt[6] = s[2];\\n\\t\\t\\tt[7] = s[5];\\n\\t\\t\\tt[8] = s[8];\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\tsetFromMat4(m) {\\n\\t\\tconst src = m.data;\\n\\t\\tconst dst = this.data;\\n\\t\\tdst[0] = src[0];\\n\\t\\tdst[1] = src[1];\\n\\t\\tdst[2] = src[2];\\n\\t\\tdst[3] = src[4];\\n\\t\\tdst[4] = src[5];\\n\\t\\tdst[5] = src[6];\\n\\t\\tdst[6] = src[8];\\n\\t\\tdst[7] = src[9];\\n\\t\\tdst[8] = src[10];\\n\\t\\treturn this;\\n\\t}\\n\\tsetFromQuat(r) {\\n\\t\\tconst qx = r.x;\\n\\t\\tconst qy = r.y;\\n\\t\\tconst qz = r.z;\\n\\t\\tconst qw = r.w;\\n\\t\\tconst x2 = qx + qx;\\n\\t\\tconst y2 = qy + qy;\\n\\t\\tconst z2 = qz + qz;\\n\\t\\tconst xx = qx * x2;\\n\\t\\tconst xy = qx * y2;\\n\\t\\tconst xz = qx * z2;\\n\\t\\tconst yy = qy * y2;\\n\\t\\tconst yz = qy * z2;\\n\\t\\tconst zz = qz * z2;\\n\\t\\tconst wx = qw * x2;\\n\\t\\tconst wy = qw * y2;\\n\\t\\tconst wz = qw * z2;\\n\\t\\tconst m = this.data;\\n\\t\\tm[0] = 1 - (yy + zz);\\n\\t\\tm[1] = xy + wz;\\n\\t\\tm[2] = xz - wy;\\n\\t\\tm[3] = xy - wz;\\n\\t\\tm[4] = 1 - (xx + zz);\\n\\t\\tm[5] = yz + wx;\\n\\t\\tm[6] = xz + wy;\\n\\t\\tm[7] = yz - wx;\\n\\t\\tm[8] = 1 - (xx + yy);\\n\\t\\treturn this;\\n\\t}\\n\\tinvertMat4(src) {\\n\\t\\tconst s = src.data;\\n\\t\\tconst a0 = s[0];\\n\\t\\tconst a1 = s[1];\\n\\t\\tconst a2 = s[2];\\n\\t\\tconst a4 = s[4];\\n\\t\\tconst a5 = s[5];\\n\\t\\tconst a6 = s[6];\\n\\t\\tconst a8 = s[8];\\n\\t\\tconst a9 = s[9];\\n\\t\\tconst a10 = s[10];\\n\\t\\tconst b11 = a10 * a5 - a6 * a9;\\n\\t\\tconst b21 = -a10 * a1 + a2 * a9;\\n\\t\\tconst b31 = a6 * a1 - a2 * a5;\\n\\t\\tconst b12 = -a10 * a4 + a6 * a8;\\n\\t\\tconst b22 = a10 * a0 - a2 * a8;\\n\\t\\tconst b32 = -a6 * a0 + a2 * a4;\\n\\t\\tconst b13 = a9 * a4 - a5 * a8;\\n\\t\\tconst b23 = -a9 * a0 + a1 * a8;\\n\\t\\tconst b33 = a5 * a0 - a1 * a4;\\n\\t\\tconst det = a0 * b11 + a1 * b12 + a2 * b13;\\n\\t\\tif (det === 0) {\\n\\t\\t\\tthis.setIdentity();\\n\\t\\t} else {\\n\\t\\t\\tconst invDet = 1 / det;\\n\\t\\t\\tconst t = this.data;\\n\\t\\t\\tt[0] = b11 * invDet;\\n\\t\\t\\tt[1] = b21 * invDet;\\n\\t\\t\\tt[2] = b31 * invDet;\\n\\t\\t\\tt[3] = b12 * invDet;\\n\\t\\t\\tt[4] = b22 * invDet;\\n\\t\\t\\tt[5] = b32 * invDet;\\n\\t\\t\\tt[6] = b13 * invDet;\\n\\t\\t\\tt[7] = b23 * invDet;\\n\\t\\t\\tt[8] = b33 * invDet;\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\ttransformVector(vec, res = new Vec3()) {\\n\\t\\tconst m = this.data;\\n\\t\\tconst { x, y, z } = vec;\\n\\t\\tres.x = x * m[0] + y * m[3] + z * m[6];\\n\\t\\tres.y = x * m[1] + y * m[4] + z * m[7];\\n\\t\\tres.z = x * m[2] + y * m[5] + z * m[8];\\n\\t\\treturn res;\\n\\t}\\n\\tstatic IDENTITY = Object.freeze(new Mat3());\\n\\tstatic ZERO = Object.freeze(new Mat3().set([0, 0, 0, 0, 0, 0, 0, 0, 0]));\\n}\\n\\nclass Vec2 {\\n\\tx;\\n\\ty;\\n\\tconstructor(x = 0, y = 0) {\\n\\t\\tif (x.length === 2) {\\n\\t\\t\\tthis.x = x[0];\\n\\t\\t\\tthis.y = x[1];\\n\\t\\t} else {\\n\\t\\t\\tthis.x = x;\\n\\t\\t\\tthis.y = y;\\n\\t\\t}\\n\\t}\\n\\tadd(rhs) {\\n\\t\\tthis.x += rhs.x;\\n\\t\\tthis.y += rhs.y;\\n\\t\\treturn this;\\n\\t}\\n\\tadd2(lhs, rhs) {\\n\\t\\tthis.x = lhs.x + rhs.x;\\n\\t\\tthis.y = lhs.y + rhs.y;\\n\\t\\treturn this;\\n\\t}\\n\\taddScalar(scalar) {\\n\\t\\tthis.x += scalar;\\n\\t\\tthis.y += scalar;\\n\\t\\treturn this;\\n\\t}\\n\\taddScaled(rhs, scalar) {\\n\\t\\tthis.x += rhs.x * scalar;\\n\\t\\tthis.y += rhs.y * scalar;\\n\\t\\treturn this;\\n\\t}\\n\\tclone() {\\n\\t\\tconst cstr = this.constructor;\\n\\t\\treturn new cstr(this.x, this.y);\\n\\t}\\n\\tcopy(rhs) {\\n\\t\\tthis.x = rhs.x;\\n\\t\\tthis.y = rhs.y;\\n\\t\\treturn this;\\n\\t}\\n\\tcross(rhs) {\\n\\t\\treturn this.x * rhs.y - this.y * rhs.x;\\n\\t}\\n\\tdistance(rhs) {\\n\\t\\tconst x = this.x - rhs.x;\\n\\t\\tconst y = this.y - rhs.y;\\n\\t\\treturn Math.sqrt(x * x + y * y);\\n\\t}\\n\\tdiv(rhs) {\\n\\t\\tthis.x /= rhs.x;\\n\\t\\tthis.y /= rhs.y;\\n\\t\\treturn this;\\n\\t}\\n\\tdiv2(lhs, rhs) {\\n\\t\\tthis.x = lhs.x / rhs.x;\\n\\t\\tthis.y = lhs.y / rhs.y;\\n\\t\\treturn this;\\n\\t}\\n\\tdivScalar(scalar) {\\n\\t\\tthis.x /= scalar;\\n\\t\\tthis.y /= scalar;\\n\\t\\treturn this;\\n\\t}\\n\\tdot(rhs) {\\n\\t\\treturn this.x * rhs.x + this.y * rhs.y;\\n\\t}\\n\\tequals(rhs) {\\n\\t\\treturn this.x === rhs.x && this.y === rhs.y;\\n\\t}\\n\\tequalsApprox(rhs, epsilon = 1e-6) {\\n\\t\\treturn Math.abs(this.x - rhs.x) < epsilon && Math.abs(this.y - rhs.y) < epsilon;\\n\\t}\\n\\tlength() {\\n\\t\\treturn Math.sqrt(this.x * this.x + this.y * this.y);\\n\\t}\\n\\tlengthSq() {\\n\\t\\treturn this.x * this.x + this.y * this.y;\\n\\t}\\n\\tlerp(lhs, rhs, alpha) {\\n\\t\\tthis.x = lhs.x + alpha * (rhs.x - lhs.x);\\n\\t\\tthis.y = lhs.y + alpha * (rhs.y - lhs.y);\\n\\t\\treturn this;\\n\\t}\\n\\tmul(rhs) {\\n\\t\\tthis.x *= rhs.x;\\n\\t\\tthis.y *= rhs.y;\\n\\t\\treturn this;\\n\\t}\\n\\tmul2(lhs, rhs) {\\n\\t\\tthis.x = lhs.x * rhs.x;\\n\\t\\tthis.y = lhs.y * rhs.y;\\n\\t\\treturn this;\\n\\t}\\n\\tmulScalar(scalar) {\\n\\t\\tthis.x *= scalar;\\n\\t\\tthis.y *= scalar;\\n\\t\\treturn this;\\n\\t}\\n\\tnormalize(src = this) {\\n\\t\\tconst lengthSq = src.x * src.x + src.y * src.y;\\n\\t\\tif (lengthSq > 0) {\\n\\t\\t\\tconst invLength = 1 / Math.sqrt(lengthSq);\\n\\t\\t\\tthis.x = src.x * invLength;\\n\\t\\t\\tthis.y = src.y * invLength;\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\trotate(degrees) {\\n\\t\\tconst angle = Math.atan2(this.x, this.y) + degrees * math.DEG_TO_RAD;\\n\\t\\tconst len = Math.sqrt(this.x * this.x + this.y * this.y);\\n\\t\\tthis.x = Math.sin(angle) * len;\\n\\t\\tthis.y = Math.cos(angle) * len;\\n\\t\\treturn this;\\n\\t}\\n\\tangle() {\\n\\t\\treturn Math.atan2(this.x, this.y) * math.RAD_TO_DEG;\\n\\t}\\n\\tangleTo(rhs) {\\n\\t\\treturn Math.atan2(this.x * rhs.y + this.y * rhs.x, this.x * rhs.x + this.y * rhs.y) * math.RAD_TO_DEG;\\n\\t}\\n\\tfloor(src = this) {\\n\\t\\tthis.x = Math.floor(src.x);\\n\\t\\tthis.y = Math.floor(src.y);\\n\\t\\treturn this;\\n\\t}\\n\\tceil(src = this) {\\n\\t\\tthis.x = Math.ceil(src.x);\\n\\t\\tthis.y = Math.ceil(src.y);\\n\\t\\treturn this;\\n\\t}\\n\\tround(src = this) {\\n\\t\\tthis.x = Math.round(src.x);\\n\\t\\tthis.y = Math.round(src.y);\\n\\t\\treturn this;\\n\\t}\\n\\tmin(rhs) {\\n\\t\\tif (rhs.x < this.x) this.x = rhs.x;\\n\\t\\tif (rhs.y < this.y) this.y = rhs.y;\\n\\t\\treturn this;\\n\\t}\\n\\tmax(rhs) {\\n\\t\\tif (rhs.x > this.x) this.x = rhs.x;\\n\\t\\tif (rhs.y > this.y) this.y = rhs.y;\\n\\t\\treturn this;\\n\\t}\\n\\tset(x, y) {\\n\\t\\tthis.x = x;\\n\\t\\tthis.y = y;\\n\\t\\treturn this;\\n\\t}\\n\\tsub(rhs) {\\n\\t\\tthis.x -= rhs.x;\\n\\t\\tthis.y -= rhs.y;\\n\\t\\treturn this;\\n\\t}\\n\\tsub2(lhs, rhs) {\\n\\t\\tthis.x = lhs.x - rhs.x;\\n\\t\\tthis.y = lhs.y - rhs.y;\\n\\t\\treturn this;\\n\\t}\\n\\tsubScalar(scalar) {\\n\\t\\tthis.x -= scalar;\\n\\t\\tthis.y -= scalar;\\n\\t\\treturn this;\\n\\t}\\n\\tfromArray(arr, offset = 0) {\\n\\t\\tthis.x = arr[offset] ?? this.x;\\n\\t\\tthis.y = arr[offset + 1] ?? this.y;\\n\\t\\treturn this;\\n\\t}\\n\\ttoString() {\\n\\t\\treturn `[${this.x}, ${this.y}]`;\\n\\t}\\n\\ttoArray(arr = [], offset = 0) {\\n\\t\\tarr[offset] = this.x;\\n\\t\\tarr[offset + 1] = this.y;\\n\\t\\treturn arr;\\n\\t}\\n\\tstatic angleRad(lhs, rhs) {\\n\\t\\treturn Math.atan2(lhs.x * rhs.y - lhs.y * rhs.x, lhs.x * rhs.x + lhs.y * rhs.y);\\n\\t}\\n\\tstatic ZERO = Object.freeze(new Vec2(0, 0));\\n\\tstatic HALF = Object.freeze(new Vec2(0.5, 0.5));\\n\\tstatic ONE = Object.freeze(new Vec2(1, 1));\\n\\tstatic UP = Object.freeze(new Vec2(0, 1));\\n\\tstatic DOWN = Object.freeze(new Vec2(0, -1));\\n\\tstatic RIGHT = Object.freeze(new Vec2(1, 0));\\n\\tstatic LEFT = Object.freeze(new Vec2(-1, 0));\\n}\\n\\nclass Vec4 {\\n\\tx;\\n\\ty;\\n\\tz;\\n\\tw;\\n\\tconstructor(x = 0, y = 0, z = 0, w = 0) {\\n\\t\\tif (x.length === 4) {\\n\\t\\t\\tthis.x = x[0];\\n\\t\\t\\tthis.y = x[1];\\n\\t\\t\\tthis.z = x[2];\\n\\t\\t\\tthis.w = x[3];\\n\\t\\t} else {\\n\\t\\t\\tthis.x = x;\\n\\t\\t\\tthis.y = y;\\n\\t\\t\\tthis.z = z;\\n\\t\\t\\tthis.w = w;\\n\\t\\t}\\n\\t}\\n\\tadd(rhs) {\\n\\t\\tthis.x += rhs.x;\\n\\t\\tthis.y += rhs.y;\\n\\t\\tthis.z += rhs.z;\\n\\t\\tthis.w += rhs.w;\\n\\t\\treturn this;\\n\\t}\\n\\tadd2(lhs, rhs) {\\n\\t\\tthis.x = lhs.x + rhs.x;\\n\\t\\tthis.y = lhs.y + rhs.y;\\n\\t\\tthis.z = lhs.z + rhs.z;\\n\\t\\tthis.w = lhs.w + rhs.w;\\n\\t\\treturn this;\\n\\t}\\n\\taddScalar(scalar) {\\n\\t\\tthis.x += scalar;\\n\\t\\tthis.y += scalar;\\n\\t\\tthis.z += scalar;\\n\\t\\tthis.w += scalar;\\n\\t\\treturn this;\\n\\t}\\n\\taddScaled(rhs, scalar) {\\n\\t\\tthis.x += rhs.x * scalar;\\n\\t\\tthis.y += rhs.y * scalar;\\n\\t\\tthis.z += rhs.z * scalar;\\n\\t\\tthis.w += rhs.w * scalar;\\n\\t\\treturn this;\\n\\t}\\n\\tclone() {\\n\\t\\tconst cstr = this.constructor;\\n\\t\\treturn new cstr(this.x, this.y, this.z, this.w);\\n\\t}\\n\\tcopy(rhs) {\\n\\t\\tthis.x = rhs.x;\\n\\t\\tthis.y = rhs.y;\\n\\t\\tthis.z = rhs.z;\\n\\t\\tthis.w = rhs.w;\\n\\t\\treturn this;\\n\\t}\\n\\tdiv(rhs) {\\n\\t\\tthis.x /= rhs.x;\\n\\t\\tthis.y /= rhs.y;\\n\\t\\tthis.z /= rhs.z;\\n\\t\\tthis.w /= rhs.w;\\n\\t\\treturn this;\\n\\t}\\n\\tdiv2(lhs, rhs) {\\n\\t\\tthis.x = lhs.x / rhs.x;\\n\\t\\tthis.y = lhs.y / rhs.y;\\n\\t\\tthis.z = lhs.z / rhs.z;\\n\\t\\tthis.w = lhs.w / rhs.w;\\n\\t\\treturn this;\\n\\t}\\n\\tdivScalar(scalar) {\\n\\t\\tthis.x /= scalar;\\n\\t\\tthis.y /= scalar;\\n\\t\\tthis.z /= scalar;\\n\\t\\tthis.w /= scalar;\\n\\t\\treturn this;\\n\\t}\\n\\tdot(rhs) {\\n\\t\\treturn this.x * rhs.x + this.y * rhs.y + this.z * rhs.z + this.w * rhs.w;\\n\\t}\\n\\tequals(rhs) {\\n\\t\\treturn this.x === rhs.x && this.y === rhs.y && this.z === rhs.z && this.w === rhs.w;\\n\\t}\\n\\tequalsApprox(rhs, epsilon = 1e-6) {\\n\\t\\treturn Math.abs(this.x - rhs.x) < epsilon && Math.abs(this.y - rhs.y) < epsilon && Math.abs(this.z - rhs.z) < epsilon && Math.abs(this.w - rhs.w) < epsilon;\\n\\t}\\n\\tlength() {\\n\\t\\treturn Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);\\n\\t}\\n\\tlengthSq() {\\n\\t\\treturn this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;\\n\\t}\\n\\tlerp(lhs, rhs, alpha) {\\n\\t\\tthis.x = lhs.x + alpha * (rhs.x - lhs.x);\\n\\t\\tthis.y = lhs.y + alpha * (rhs.y - lhs.y);\\n\\t\\tthis.z = lhs.z + alpha * (rhs.z - lhs.z);\\n\\t\\tthis.w = lhs.w + alpha * (rhs.w - lhs.w);\\n\\t\\treturn this;\\n\\t}\\n\\tmul(rhs) {\\n\\t\\tthis.x *= rhs.x;\\n\\t\\tthis.y *= rhs.y;\\n\\t\\tthis.z *= rhs.z;\\n\\t\\tthis.w *= rhs.w;\\n\\t\\treturn this;\\n\\t}\\n\\tmul2(lhs, rhs) {\\n\\t\\tthis.x = lhs.x * rhs.x;\\n\\t\\tthis.y = lhs.y * rhs.y;\\n\\t\\tthis.z = lhs.z * rhs.z;\\n\\t\\tthis.w = lhs.w * rhs.w;\\n\\t\\treturn this;\\n\\t}\\n\\tmulScalar(scalar) {\\n\\t\\tthis.x *= scalar;\\n\\t\\tthis.y *= scalar;\\n\\t\\tthis.z *= scalar;\\n\\t\\tthis.w *= scalar;\\n\\t\\treturn this;\\n\\t}\\n\\tnormalize(src = this) {\\n\\t\\tconst lengthSq = src.x * src.x + src.y * src.y + src.z * src.z + src.w * src.w;\\n\\t\\tif (lengthSq > 0) {\\n\\t\\t\\tconst invLength = 1 / Math.sqrt(lengthSq);\\n\\t\\t\\tthis.x = src.x * invLength;\\n\\t\\t\\tthis.y = src.y * invLength;\\n\\t\\t\\tthis.z = src.z * invLength;\\n\\t\\t\\tthis.w = src.w * invLength;\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\tfloor(src = this) {\\n\\t\\tthis.x = Math.floor(src.x);\\n\\t\\tthis.y = Math.floor(src.y);\\n\\t\\tthis.z = Math.floor(src.z);\\n\\t\\tthis.w = Math.floor(src.w);\\n\\t\\treturn this;\\n\\t}\\n\\tceil(src = this) {\\n\\t\\tthis.x = Math.ceil(src.x);\\n\\t\\tthis.y = Math.ceil(src.y);\\n\\t\\tthis.z = Math.ceil(src.z);\\n\\t\\tthis.w = Math.ceil(src.w);\\n\\t\\treturn this;\\n\\t}\\n\\tround(src = this) {\\n\\t\\tthis.x = Math.round(src.x);\\n\\t\\tthis.y = Math.round(src.y);\\n\\t\\tthis.z = Math.round(src.z);\\n\\t\\tthis.w = Math.round(src.w);\\n\\t\\treturn this;\\n\\t}\\n\\tmin(rhs) {\\n\\t\\tif (rhs.x < this.x) this.x = rhs.x;\\n\\t\\tif (rhs.y < this.y) this.y = rhs.y;\\n\\t\\tif (rhs.z < this.z) this.z = rhs.z;\\n\\t\\tif (rhs.w < this.w) this.w = rhs.w;\\n\\t\\treturn this;\\n\\t}\\n\\tmax(rhs) {\\n\\t\\tif (rhs.x > this.x) this.x = rhs.x;\\n\\t\\tif (rhs.y > this.y) this.y = rhs.y;\\n\\t\\tif (rhs.z > this.z) this.z = rhs.z;\\n\\t\\tif (rhs.w > this.w) this.w = rhs.w;\\n\\t\\treturn this;\\n\\t}\\n\\tset(x, y, z, w) {\\n\\t\\tthis.x = x;\\n\\t\\tthis.y = y;\\n\\t\\tthis.z = z;\\n\\t\\tthis.w = w;\\n\\t\\treturn this;\\n\\t}\\n\\tsub(rhs) {\\n\\t\\tthis.x -= rhs.x;\\n\\t\\tthis.y -= rhs.y;\\n\\t\\tthis.z -= rhs.z;\\n\\t\\tthis.w -= rhs.w;\\n\\t\\treturn this;\\n\\t}\\n\\tsub2(lhs, rhs) {\\n\\t\\tthis.x = lhs.x - rhs.x;\\n\\t\\tthis.y = lhs.y - rhs.y;\\n\\t\\tthis.z = lhs.z - rhs.z;\\n\\t\\tthis.w = lhs.w - rhs.w;\\n\\t\\treturn this;\\n\\t}\\n\\tsubScalar(scalar) {\\n\\t\\tthis.x -= scalar;\\n\\t\\tthis.y -= scalar;\\n\\t\\tthis.z -= scalar;\\n\\t\\tthis.w -= scalar;\\n\\t\\treturn this;\\n\\t}\\n\\tfromArray(arr, offset = 0) {\\n\\t\\tthis.x = arr[offset] ?? this.x;\\n\\t\\tthis.y = arr[offset + 1] ?? this.y;\\n\\t\\tthis.z = arr[offset + 2] ?? this.z;\\n\\t\\tthis.w = arr[offset + 3] ?? this.w;\\n\\t\\treturn this;\\n\\t}\\n\\ttoString() {\\n\\t\\treturn `[${this.x}, ${this.y}, ${this.z}, ${this.w}]`;\\n\\t}\\n\\ttoArray(arr = [], offset = 0) {\\n\\t\\tarr[offset] = this.x;\\n\\t\\tarr[offset + 1] = this.y;\\n\\t\\tarr[offset + 2] = this.z;\\n\\t\\tarr[offset + 3] = this.w;\\n\\t\\treturn arr;\\n\\t}\\n\\tstatic ZERO = Object.freeze(new Vec4(0, 0, 0, 0));\\n\\tstatic HALF = Object.freeze(new Vec4(0.5, 0.5, 0.5, 0.5));\\n\\tstatic ONE = Object.freeze(new Vec4(1, 1, 1, 1));\\n}\\n\\nconst _halfSize$1 = new Vec2();\\nconst x = new Vec3();\\nconst y = new Vec3();\\nconst z = new Vec3();\\nconst scale = new Vec3();\\nclass Mat4 {\\n\\tdata = new Float32Array(16);\\n\\tconstructor() {\\n\\t\\tthis.data[0] = this.data[5] = this.data[10] = this.data[15] = 1;\\n\\t}\\n\\t// Static function which evaluates perspective projection matrix half size at the near plane\\n\\tstatic _getPerspectiveHalfSize(halfSize, fov, aspect, znear, fovIsHorizontal) {\\n\\t\\tif (fovIsHorizontal) {\\n\\t\\t\\thalfSize.x = znear * Math.tan(fov * Math.PI / 360);\\n\\t\\t\\thalfSize.y = halfSize.x / aspect;\\n\\t\\t} else {\\n\\t\\t\\thalfSize.y = znear * Math.tan(fov * Math.PI / 360);\\n\\t\\t\\thalfSize.x = halfSize.y * aspect;\\n\\t\\t}\\n\\t}\\n\\tadd2(lhs, rhs) {\\n\\t\\tconst a = lhs.data, b = rhs.data, r = this.data;\\n\\t\\tr[0] = a[0] + b[0];\\n\\t\\tr[1] = a[1] + b[1];\\n\\t\\tr[2] = a[2] + b[2];\\n\\t\\tr[3] = a[3] + b[3];\\n\\t\\tr[4] = a[4] + b[4];\\n\\t\\tr[5] = a[5] + b[5];\\n\\t\\tr[6] = a[6] + b[6];\\n\\t\\tr[7] = a[7] + b[7];\\n\\t\\tr[8] = a[8] + b[8];\\n\\t\\tr[9] = a[9] + b[9];\\n\\t\\tr[10] = a[10] + b[10];\\n\\t\\tr[11] = a[11] + b[11];\\n\\t\\tr[12] = a[12] + b[12];\\n\\t\\tr[13] = a[13] + b[13];\\n\\t\\tr[14] = a[14] + b[14];\\n\\t\\tr[15] = a[15] + b[15];\\n\\t\\treturn this;\\n\\t}\\n\\tadd(rhs) {\\n\\t\\treturn this.add2(this, rhs);\\n\\t}\\n\\tclone() {\\n\\t\\tconst cstr = this.constructor;\\n\\t\\treturn new cstr().copy(this);\\n\\t}\\n\\tcopy(rhs) {\\n\\t\\tconst src = rhs.data, dst = this.data;\\n\\t\\tdst[0] = src[0];\\n\\t\\tdst[1] = src[1];\\n\\t\\tdst[2] = src[2];\\n\\t\\tdst[3] = src[3];\\n\\t\\tdst[4] = src[4];\\n\\t\\tdst[5] = src[5];\\n\\t\\tdst[6] = src[6];\\n\\t\\tdst[7] = src[7];\\n\\t\\tdst[8] = src[8];\\n\\t\\tdst[9] = src[9];\\n\\t\\tdst[10] = src[10];\\n\\t\\tdst[11] = src[11];\\n\\t\\tdst[12] = src[12];\\n\\t\\tdst[13] = src[13];\\n\\t\\tdst[14] = src[14];\\n\\t\\tdst[15] = src[15];\\n\\t\\treturn this;\\n\\t}\\n\\tequals(rhs) {\\n\\t\\tconst l = this.data, r = rhs.data;\\n\\t\\treturn l[0] === r[0] && l[1] === r[1] && l[2] === r[2] && l[3] === r[3] && l[4] === r[4] && l[5] === r[5] && l[6] === r[6] && l[7] === r[7] && l[8] === r[8] && l[9] === r[9] && l[10] === r[10] && l[11] === r[11] && l[12] === r[12] && l[13] === r[13] && l[14] === r[14] && l[15] === r[15];\\n\\t}\\n\\tisIdentity() {\\n\\t\\tconst m = this.data;\\n\\t\\treturn m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 0 && m[4] === 0 && m[5] === 1 && m[6] === 0 && m[7] === 0 && m[8] === 0 && m[9] === 0 && m[10] === 1 && m[11] === 0 && m[12] === 0 && m[13] === 0 && m[14] === 0 && m[15] === 1;\\n\\t}\\n\\tmul2(lhs, rhs) {\\n\\t\\tconst a = lhs.data;\\n\\t\\tconst b = rhs.data;\\n\\t\\tconst r = this.data;\\n\\t\\tconst a00 = a[0];\\n\\t\\tconst a01 = a[1];\\n\\t\\tconst a02 = a[2];\\n\\t\\tconst a03 = a[3];\\n\\t\\tconst a10 = a[4];\\n\\t\\tconst a11 = a[5];\\n\\t\\tconst a12 = a[6];\\n\\t\\tconst a13 = a[7];\\n\\t\\tconst a20 = a[8];\\n\\t\\tconst a21 = a[9];\\n\\t\\tconst a22 = a[10];\\n\\t\\tconst a23 = a[11];\\n\\t\\tconst a30 = a[12];\\n\\t\\tconst a31 = a[13];\\n\\t\\tconst a32 = a[14];\\n\\t\\tconst a33 = a[15];\\n\\t\\tlet b0, b1, b2, b3;\\n\\t\\tb0 = b[0];\\n\\t\\tb1 = b[1];\\n\\t\\tb2 = b[2];\\n\\t\\tb3 = b[3];\\n\\t\\tr[0] = a00 * b0 + a10 * b1 + a20 * b2 + a30 * b3;\\n\\t\\tr[1] = a01 * b0 + a11 * b1 + a21 * b2 + a31 * b3;\\n\\t\\tr[2] = a02 * b0 + a12 * b1 + a22 * b2 + a32 * b3;\\n\\t\\tr[3] = a03 * b0 + a13 * b1 + a23 * b2 + a33 * b3;\\n\\t\\tb0 = b[4];\\n\\t\\tb1 = b[5];\\n\\t\\tb2 = b[6];\\n\\t\\tb3 = b[7];\\n\\t\\tr[4] = a00 * b0 + a10 * b1 + a20 * b2 + a30 * b3;\\n\\t\\tr[5] = a01 * b0 + a11 * b1 + a21 * b2 + a31 * b3;\\n\\t\\tr[6] = a02 * b0 + a12 * b1 + a22 * b2 + a32 * b3;\\n\\t\\tr[7] = a03 * b0 + a13 * b1 + a23 * b2 + a33 * b3;\\n\\t\\tb0 = b[8];\\n\\t\\tb1 = b[9];\\n\\t\\tb2 = b[10];\\n\\t\\tb3 = b[11];\\n\\t\\tr[8] = a00 * b0 + a10 * b1 + a20 * b2 + a30 * b3;\\n\\t\\tr[9] = a01 * b0 + a11 * b1 + a21 * b2 + a31 * b3;\\n\\t\\tr[10] = a02 * b0 + a12 * b1 + a22 * b2 + a32 * b3;\\n\\t\\tr[11] = a03 * b0 + a13 * b1 + a23 * b2 + a33 * b3;\\n\\t\\tb0 = b[12];\\n\\t\\tb1 = b[13];\\n\\t\\tb2 = b[14];\\n\\t\\tb3 = b[15];\\n\\t\\tr[12] = a00 * b0 + a10 * b1 + a20 * b2 + a30 * b3;\\n\\t\\tr[13] = a01 * b0 + a11 * b1 + a21 * b2 + a31 * b3;\\n\\t\\tr[14] = a02 * b0 + a12 * b1 + a22 * b2 + a32 * b3;\\n\\t\\tr[15] = a03 * b0 + a13 * b1 + a23 * b2 + a33 * b3;\\n\\t\\treturn this;\\n\\t}\\n\\tmulAffine2(lhs, rhs) {\\n\\t\\tconst a = lhs.data;\\n\\t\\tconst b = rhs.data;\\n\\t\\tconst r = this.data;\\n\\t\\tconst a00 = a[0];\\n\\t\\tconst a01 = a[1];\\n\\t\\tconst a02 = a[2];\\n\\t\\tconst a10 = a[4];\\n\\t\\tconst a11 = a[5];\\n\\t\\tconst a12 = a[6];\\n\\t\\tconst a20 = a[8];\\n\\t\\tconst a21 = a[9];\\n\\t\\tconst a22 = a[10];\\n\\t\\tconst a30 = a[12];\\n\\t\\tconst a31 = a[13];\\n\\t\\tconst a32 = a[14];\\n\\t\\tlet b0, b1, b2;\\n\\t\\tb0 = b[0];\\n\\t\\tb1 = b[1];\\n\\t\\tb2 = b[2];\\n\\t\\tr[0] = a00 * b0 + a10 * b1 + a20 * b2;\\n\\t\\tr[1] = a01 * b0 + a11 * b1 + a21 * b2;\\n\\t\\tr[2] = a02 * b0 + a12 * b1 + a22 * b2;\\n\\t\\tr[3] = 0;\\n\\t\\tb0 = b[4];\\n\\t\\tb1 = b[5];\\n\\t\\tb2 = b[6];\\n\\t\\tr[4] = a00 * b0 + a10 * b1 + a20 * b2;\\n\\t\\tr[5] = a01 * b0 + a11 * b1 + a21 * b2;\\n\\t\\tr[6] = a02 * b0 + a12 * b1 + a22 * b2;\\n\\t\\tr[7] = 0;\\n\\t\\tb0 = b[8];\\n\\t\\tb1 = b[9];\\n\\t\\tb2 = b[10];\\n\\t\\tr[8] = a00 * b0 + a10 * b1 + a20 * b2;\\n\\t\\tr[9] = a01 * b0 + a11 * b1 + a21 * b2;\\n\\t\\tr[10] = a02 * b0 + a12 * b1 + a22 * b2;\\n\\t\\tr[11] = 0;\\n\\t\\tb0 = b[12];\\n\\t\\tb1 = b[13];\\n\\t\\tb2 = b[14];\\n\\t\\tr[12] = a00 * b0 + a10 * b1 + a20 * b2 + a30;\\n\\t\\tr[13] = a01 * b0 + a11 * b1 + a21 * b2 + a31;\\n\\t\\tr[14] = a02 * b0 + a12 * b1 + a22 * b2 + a32;\\n\\t\\tr[15] = 1;\\n\\t\\treturn this;\\n\\t}\\n\\tmul(rhs) {\\n\\t\\treturn this.mul2(this, rhs);\\n\\t}\\n\\ttransformPoint(vec, res = new Vec3()) {\\n\\t\\tconst m = this.data;\\n\\t\\tconst { x: x2, y: y2, z: z2 } = vec;\\n\\t\\tres.x = x2 * m[0] + y2 * m[4] + z2 * m[8] + m[12];\\n\\t\\tres.y = x2 * m[1] + y2 * m[5] + z2 * m[9] + m[13];\\n\\t\\tres.z = x2 * m[2] + y2 * m[6] + z2 * m[10] + m[14];\\n\\t\\treturn res;\\n\\t}\\n\\ttransformVector(vec, res = new Vec3()) {\\n\\t\\tconst m = this.data;\\n\\t\\tconst { x: x2, y: y2, z: z2 } = vec;\\n\\t\\tres.x = x2 * m[0] + y2 * m[4] + z2 * m[8];\\n\\t\\tres.y = x2 * m[1] + y2 * m[5] + z2 * m[9];\\n\\t\\tres.z = x2 * m[2] + y2 * m[6] + z2 * m[10];\\n\\t\\treturn res;\\n\\t}\\n\\ttransformVec4(vec, res = new Vec4()) {\\n\\t\\tconst m = this.data;\\n\\t\\tconst { x: x2, y: y2, z: z2, w } = vec;\\n\\t\\tres.x = x2 * m[0] + y2 * m[4] + z2 * m[8] + w * m[12];\\n\\t\\tres.y = x2 * m[1] + y2 * m[5] + z2 * m[9] + w * m[13];\\n\\t\\tres.z = x2 * m[2] + y2 * m[6] + z2 * m[10] + w * m[14];\\n\\t\\tres.w = x2 * m[3] + y2 * m[7] + z2 * m[11] + w * m[15];\\n\\t\\treturn res;\\n\\t}\\n\\tsetLookAt(position, target, up) {\\n\\t\\tz.sub2(position, target).normalize();\\n\\t\\ty.copy(up).normalize();\\n\\t\\tx.cross(y, z).normalize();\\n\\t\\ty.cross(z, x);\\n\\t\\tconst r = this.data;\\n\\t\\tr[0] = x.x;\\n\\t\\tr[1] = x.y;\\n\\t\\tr[2] = x.z;\\n\\t\\tr[3] = 0;\\n\\t\\tr[4] = y.x;\\n\\t\\tr[5] = y.y;\\n\\t\\tr[6] = y.z;\\n\\t\\tr[7] = 0;\\n\\t\\tr[8] = z.x;\\n\\t\\tr[9] = z.y;\\n\\t\\tr[10] = z.z;\\n\\t\\tr[11] = 0;\\n\\t\\tr[12] = position.x;\\n\\t\\tr[13] = position.y;\\n\\t\\tr[14] = position.z;\\n\\t\\tr[15] = 1;\\n\\t\\treturn this;\\n\\t}\\n\\tsetFrustum(left, right, bottom, top, znear, zfar) {\\n\\t\\tconst temp1 = 2 * znear;\\n\\t\\tconst temp2 = right - left;\\n\\t\\tconst temp3 = top - bottom;\\n\\t\\tconst temp4 = zfar - znear;\\n\\t\\tconst r = this.data;\\n\\t\\tr[0] = temp1 / temp2;\\n\\t\\tr[1] = 0;\\n\\t\\tr[2] = 0;\\n\\t\\tr[3] = 0;\\n\\t\\tr[4] = 0;\\n\\t\\tr[5] = temp1 / temp3;\\n\\t\\tr[6] = 0;\\n\\t\\tr[7] = 0;\\n\\t\\tr[8] = (right + left) / temp2;\\n\\t\\tr[9] = (top + bottom) / temp3;\\n\\t\\tr[10] = (-zfar - znear) / temp4;\\n\\t\\tr[11] = -1;\\n\\t\\tr[12] = 0;\\n\\t\\tr[13] = 0;\\n\\t\\tr[14] = -temp1 * zfar / temp4;\\n\\t\\tr[15] = 0;\\n\\t\\treturn this;\\n\\t}\\n\\tsetPerspective(fov, aspect, znear, zfar, fovIsHorizontal) {\\n\\t\\tMat4._getPerspectiveHalfSize(_halfSize$1, fov, aspect, znear, fovIsHorizontal);\\n\\t\\treturn this.setFrustum(-_halfSize$1.x, _halfSize$1.x, -_halfSize$1.y, _halfSize$1.y, znear, zfar);\\n\\t}\\n\\tsetOrtho(left, right, bottom, top, near, far) {\\n\\t\\tconst r = this.data;\\n\\t\\tr[0] = 2 / (right - left);\\n\\t\\tr[1] = 0;\\n\\t\\tr[2] = 0;\\n\\t\\tr[3] = 0;\\n\\t\\tr[4] = 0;\\n\\t\\tr[5] = 2 / (top - bottom);\\n\\t\\tr[6] = 0;\\n\\t\\tr[7] = 0;\\n\\t\\tr[8] = 0;\\n\\t\\tr[9] = 0;\\n\\t\\tr[10] = -2 / (far - near);\\n\\t\\tr[11] = 0;\\n\\t\\tr[12] = -(right + left) / (right - left);\\n\\t\\tr[13] = -(top + bottom) / (top - bottom);\\n\\t\\tr[14] = -(far + near) / (far - near);\\n\\t\\tr[15] = 1;\\n\\t\\treturn this;\\n\\t}\\n\\tsetFromAxisAngle(axis, angle) {\\n\\t\\tangle *= math.DEG_TO_RAD;\\n\\t\\tconst { x: x2, y: y2, z: z2 } = axis;\\n\\t\\tconst c = Math.cos(angle);\\n\\t\\tconst s = Math.sin(angle);\\n\\t\\tconst t = 1 - c;\\n\\t\\tconst tx = t * x2;\\n\\t\\tconst ty = t * y2;\\n\\t\\tconst m = this.data;\\n\\t\\tm[0] = tx * x2 + c;\\n\\t\\tm[1] = tx * y2 + s * z2;\\n\\t\\tm[2] = tx * z2 - s * y2;\\n\\t\\tm[3] = 0;\\n\\t\\tm[4] = tx * y2 - s * z2;\\n\\t\\tm[5] = ty * y2 + c;\\n\\t\\tm[6] = ty * z2 + s * x2;\\n\\t\\tm[7] = 0;\\n\\t\\tm[8] = tx * z2 + s * y2;\\n\\t\\tm[9] = ty * z2 - x2 * s;\\n\\t\\tm[10] = t * z2 * z2 + c;\\n\\t\\tm[11] = 0;\\n\\t\\tm[12] = 0;\\n\\t\\tm[13] = 0;\\n\\t\\tm[14] = 0;\\n\\t\\tm[15] = 1;\\n\\t\\treturn this;\\n\\t}\\n\\tsetTranslate(x2, y2, z2) {\\n\\t\\tconst m = this.data;\\n\\t\\tm[0] = 1;\\n\\t\\tm[1] = 0;\\n\\t\\tm[2] = 0;\\n\\t\\tm[3] = 0;\\n\\t\\tm[4] = 0;\\n\\t\\tm[5] = 1;\\n\\t\\tm[6] = 0;\\n\\t\\tm[7] = 0;\\n\\t\\tm[8] = 0;\\n\\t\\tm[9] = 0;\\n\\t\\tm[10] = 1;\\n\\t\\tm[11] = 0;\\n\\t\\tm[12] = x2;\\n\\t\\tm[13] = y2;\\n\\t\\tm[14] = z2;\\n\\t\\tm[15] = 1;\\n\\t\\treturn this;\\n\\t}\\n\\tsetScale(x2, y2, z2) {\\n\\t\\tconst m = this.data;\\n\\t\\tm[0] = x2;\\n\\t\\tm[1] = 0;\\n\\t\\tm[2] = 0;\\n\\t\\tm[3] = 0;\\n\\t\\tm[4] = 0;\\n\\t\\tm[5] = y2;\\n\\t\\tm[6] = 0;\\n\\t\\tm[7] = 0;\\n\\t\\tm[8] = 0;\\n\\t\\tm[9] = 0;\\n\\t\\tm[10] = z2;\\n\\t\\tm[11] = 0;\\n\\t\\tm[12] = 0;\\n\\t\\tm[13] = 0;\\n\\t\\tm[14] = 0;\\n\\t\\tm[15] = 1;\\n\\t\\treturn this;\\n\\t}\\n\\tsetViewport(x2, y2, width, height) {\\n\\t\\tconst m = this.data;\\n\\t\\tm[0] = width * 0.5;\\n\\t\\tm[1] = 0;\\n\\t\\tm[2] = 0;\\n\\t\\tm[3] = 0;\\n\\t\\tm[4] = 0;\\n\\t\\tm[5] = height * 0.5;\\n\\t\\tm[6] = 0;\\n\\t\\tm[7] = 0;\\n\\t\\tm[8] = 0;\\n\\t\\tm[9] = 0;\\n\\t\\tm[10] = 0.5;\\n\\t\\tm[11] = 0;\\n\\t\\tm[12] = x2 + width * 0.5;\\n\\t\\tm[13] = y2 + height * 0.5;\\n\\t\\tm[14] = 0.5;\\n\\t\\tm[15] = 1;\\n\\t\\treturn this;\\n\\t}\\n\\tsetReflection(normal, distance) {\\n\\t\\tconst a = normal.x;\\n\\t\\tconst b = normal.y;\\n\\t\\tconst c = normal.z;\\n\\t\\tconst data = this.data;\\n\\t\\tdata[0] = 1 - 2 * a * a;\\n\\t\\tdata[1] = -2 * a * b;\\n\\t\\tdata[2] = -2 * a * c;\\n\\t\\tdata[3] = 0;\\n\\t\\tdata[4] = -2 * a * b;\\n\\t\\tdata[5] = 1 - 2 * b * b;\\n\\t\\tdata[6] = -2 * b * c;\\n\\t\\tdata[7] = 0;\\n\\t\\tdata[8] = -2 * a * c;\\n\\t\\tdata[9] = -2 * b * c;\\n\\t\\tdata[10] = 1 - 2 * c * c;\\n\\t\\tdata[11] = 0;\\n\\t\\tdata[12] = -2 * a * distance;\\n\\t\\tdata[13] = -2 * b * distance;\\n\\t\\tdata[14] = -2 * c * distance;\\n\\t\\tdata[15] = 1;\\n\\t\\treturn this;\\n\\t}\\n\\tinvert(src = this) {\\n\\t\\tconst s = src.data;\\n\\t\\tconst a00 = s[0];\\n\\t\\tconst a01 = s[1];\\n\\t\\tconst a02 = s[2];\\n\\t\\tconst a03 = s[3];\\n\\t\\tconst a10 = s[4];\\n\\t\\tconst a11 = s[5];\\n\\t\\tconst a12 = s[6];\\n\\t\\tconst a13 = s[7];\\n\\t\\tconst a20 = s[8];\\n\\t\\tconst a21 = s[9];\\n\\t\\tconst a22 = s[10];\\n\\t\\tconst a23 = s[11];\\n\\t\\tconst a30 = s[12];\\n\\t\\tconst a31 = s[13];\\n\\t\\tconst a32 = s[14];\\n\\t\\tconst a33 = s[15];\\n\\t\\tconst b00 = a00 * a11 - a01 * a10;\\n\\t\\tconst b01 = a00 * a12 - a02 * a10;\\n\\t\\tconst b02 = a00 * a13 - a03 * a10;\\n\\t\\tconst b03 = a01 * a12 - a02 * a11;\\n\\t\\tconst b04 = a01 * a13 - a03 * a11;\\n\\t\\tconst b05 = a02 * a13 - a03 * a12;\\n\\t\\tconst b06 = a20 * a31 - a21 * a30;\\n\\t\\tconst b07 = a20 * a32 - a22 * a30;\\n\\t\\tconst b08 = a20 * a33 - a23 * a30;\\n\\t\\tconst b09 = a21 * a32 - a22 * a31;\\n\\t\\tconst b10 = a21 * a33 - a23 * a31;\\n\\t\\tconst b11 = a22 * a33 - a23 * a32;\\n\\t\\tconst det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\\n\\t\\tif (det === 0) {\\n\\t\\t\\tthis.setIdentity();\\n\\t\\t} else {\\n\\t\\t\\tconst invDet = 1 / det;\\n\\t\\t\\tconst t = this.data;\\n\\t\\t\\tt[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet;\\n\\t\\t\\tt[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet;\\n\\t\\t\\tt[2] = (a31 * b05 - a32 * b04 + a33 * b03) * invDet;\\n\\t\\t\\tt[3] = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet;\\n\\t\\t\\tt[4] = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet;\\n\\t\\t\\tt[5] = (a00 * b11 - a02 * b08 + a03 * b07) * invDet;\\n\\t\\t\\tt[6] = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet;\\n\\t\\t\\tt[7] = (a20 * b05 - a22 * b02 + a23 * b01) * invDet;\\n\\t\\t\\tt[8] = (a10 * b10 - a11 * b08 + a13 * b06) * invDet;\\n\\t\\t\\tt[9] = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet;\\n\\t\\t\\tt[10] = (a30 * b04 - a31 * b02 + a33 * b00) * invDet;\\n\\t\\t\\tt[11] = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet;\\n\\t\\t\\tt[12] = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet;\\n\\t\\t\\tt[13] = (a00 * b09 - a01 * b07 + a02 * b06) * invDet;\\n\\t\\t\\tt[14] = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet;\\n\\t\\t\\tt[15] = (a20 * b03 - a21 * b01 + a22 * b00) * invDet;\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\tset(src) {\\n\\t\\tconst dst = this.data;\\n\\t\\tdst[0] = src[0];\\n\\t\\tdst[1] = src[1];\\n\\t\\tdst[2] = src[2];\\n\\t\\tdst[3] = src[3];\\n\\t\\tdst[4] = src[4];\\n\\t\\tdst[5] = src[5];\\n\\t\\tdst[6] = src[6];\\n\\t\\tdst[7] = src[7];\\n\\t\\tdst[8] = src[8];\\n\\t\\tdst[9] = src[9];\\n\\t\\tdst[10] = src[10];\\n\\t\\tdst[11] = src[11];\\n\\t\\tdst[12] = src[12];\\n\\t\\tdst[13] = src[13];\\n\\t\\tdst[14] = src[14];\\n\\t\\tdst[15] = src[15];\\n\\t\\treturn this;\\n\\t}\\n\\tsetIdentity() {\\n\\t\\tconst m = this.data;\\n\\t\\tm[0] = 1;\\n\\t\\tm[1] = 0;\\n\\t\\tm[2] = 0;\\n\\t\\tm[3] = 0;\\n\\t\\tm[4] = 0;\\n\\t\\tm[5] = 1;\\n\\t\\tm[6] = 0;\\n\\t\\tm[7] = 0;\\n\\t\\tm[8] = 0;\\n\\t\\tm[9] = 0;\\n\\t\\tm[10] = 1;\\n\\t\\tm[11] = 0;\\n\\t\\tm[12] = 0;\\n\\t\\tm[13] = 0;\\n\\t\\tm[14] = 0;\\n\\t\\tm[15] = 1;\\n\\t\\treturn this;\\n\\t}\\n\\tsetTRS(t, r, s) {\\n\\t\\tconst qx = r.x;\\n\\t\\tconst qy = r.y;\\n\\t\\tconst qz = r.z;\\n\\t\\tconst qw = r.w;\\n\\t\\tconst sx = s.x;\\n\\t\\tconst sy = s.y;\\n\\t\\tconst sz = s.z;\\n\\t\\tconst x2 = qx + qx;\\n\\t\\tconst y2 = qy + qy;\\n\\t\\tconst z2 = qz + qz;\\n\\t\\tconst xx = qx * x2;\\n\\t\\tconst xy = qx * y2;\\n\\t\\tconst xz = qx * z2;\\n\\t\\tconst yy = qy * y2;\\n\\t\\tconst yz = qy * z2;\\n\\t\\tconst zz = qz * z2;\\n\\t\\tconst wx = qw * x2;\\n\\t\\tconst wy = qw * y2;\\n\\t\\tconst wz = qw * z2;\\n\\t\\tconst m = this.data;\\n\\t\\tm[0] = (1 - (yy + zz)) * sx;\\n\\t\\tm[1] = (xy + wz) * sx;\\n\\t\\tm[2] = (xz - wy) * sx;\\n\\t\\tm[3] = 0;\\n\\t\\tm[4] = (xy - wz) * sy;\\n\\t\\tm[5] = (1 - (xx + zz)) * sy;\\n\\t\\tm[6] = (yz + wx) * sy;\\n\\t\\tm[7] = 0;\\n\\t\\tm[8] = (xz + wy) * sz;\\n\\t\\tm[9] = (yz - wx) * sz;\\n\\t\\tm[10] = (1 - (xx + yy)) * sz;\\n\\t\\tm[11] = 0;\\n\\t\\tm[12] = t.x;\\n\\t\\tm[13] = t.y;\\n\\t\\tm[14] = t.z;\\n\\t\\tm[15] = 1;\\n\\t\\treturn this;\\n\\t}\\n\\ttranspose(src = this) {\\n\\t\\tconst s = src.data;\\n\\t\\tconst t = this.data;\\n\\t\\tif (s === t) {\\n\\t\\t\\tlet tmp;\\n\\t\\t\\ttmp = s[1];\\n\\t\\t\\tt[1] = s[4];\\n\\t\\t\\tt[4] = tmp;\\n\\t\\t\\ttmp = s[2];\\n\\t\\t\\tt[2] = s[8];\\n\\t\\t\\tt[8] = tmp;\\n\\t\\t\\ttmp = s[3];\\n\\t\\t\\tt[3] = s[12];\\n\\t\\t\\tt[12] = tmp;\\n\\t\\t\\ttmp = s[6];\\n\\t\\t\\tt[6] = s[9];\\n\\t\\t\\tt[9] = tmp;\\n\\t\\t\\ttmp = s[7];\\n\\t\\t\\tt[7] = s[13];\\n\\t\\t\\tt[13] = tmp;\\n\\t\\t\\ttmp = s[11];\\n\\t\\t\\tt[11] = s[14];\\n\\t\\t\\tt[14] = tmp;\\n\\t\\t} else {\\n\\t\\t\\tt[0] = s[0];\\n\\t\\t\\tt[1] = s[4];\\n\\t\\t\\tt[2] = s[8];\\n\\t\\t\\tt[3] = s[12];\\n\\t\\t\\tt[4] = s[1];\\n\\t\\t\\tt[5] = s[5];\\n\\t\\t\\tt[6] = s[9];\\n\\t\\t\\tt[7] = s[13];\\n\\t\\t\\tt[8] = s[2];\\n\\t\\t\\tt[9] = s[6];\\n\\t\\t\\tt[10] = s[10];\\n\\t\\t\\tt[11] = s[14];\\n\\t\\t\\tt[12] = s[3];\\n\\t\\t\\tt[13] = s[7];\\n\\t\\t\\tt[14] = s[11];\\n\\t\\t\\tt[15] = s[15];\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\tgetTranslation(t = new Vec3()) {\\n\\t\\treturn t.set(this.data[12], this.data[13], this.data[14]);\\n\\t}\\n\\tgetX(x2 = new Vec3()) {\\n\\t\\treturn x2.set(this.data[0], this.data[1], this.data[2]);\\n\\t}\\n\\tgetY(y2 = new Vec3()) {\\n\\t\\treturn y2.set(this.data[4], this.data[5], this.data[6]);\\n\\t}\\n\\tgetZ(z2 = new Vec3()) {\\n\\t\\treturn z2.set(this.data[8], this.data[9], this.data[10]);\\n\\t}\\n\\tgetScale(scale2 = new Vec3()) {\\n\\t\\tthis.getX(x);\\n\\t\\tthis.getY(y);\\n\\t\\tthis.getZ(z);\\n\\t\\tscale2.set(x.length(), y.length(), z.length());\\n\\t\\treturn scale2;\\n\\t}\\n\\tget scaleSign() {\\n\\t\\tthis.getX(x);\\n\\t\\tthis.getY(y);\\n\\t\\tthis.getZ(z);\\n\\t\\tx.cross(x, y);\\n\\t\\treturn x.dot(z) < 0 ? -1 : 1;\\n\\t}\\n\\tsetFromEulerAngles(ex, ey, ez) {\\n\\t\\tex *= math.DEG_TO_RAD;\\n\\t\\tey *= math.DEG_TO_RAD;\\n\\t\\tez *= math.DEG_TO_RAD;\\n\\t\\tconst s1 = Math.sin(-ex);\\n\\t\\tconst c1 = Math.cos(-ex);\\n\\t\\tconst s2 = Math.sin(-ey);\\n\\t\\tconst c2 = Math.cos(-ey);\\n\\t\\tconst s3 = Math.sin(-ez);\\n\\t\\tconst c3 = Math.cos(-ez);\\n\\t\\tconst m = this.data;\\n\\t\\tm[0] = c2 * c3;\\n\\t\\tm[1] = -c2 * s3;\\n\\t\\tm[2] = s2;\\n\\t\\tm[3] = 0;\\n\\t\\tm[4] = c1 * s3 + c3 * s1 * s2;\\n\\t\\tm[5] = c1 * c3 - s1 * s2 * s3;\\n\\t\\tm[6] = -c2 * s1;\\n\\t\\tm[7] = 0;\\n\\t\\tm[8] = s1 * s3 - c1 * c3 * s2;\\n\\t\\tm[9] = c3 * s1 + c1 * s2 * s3;\\n\\t\\tm[10] = c1 * c2;\\n\\t\\tm[11] = 0;\\n\\t\\tm[12] = 0;\\n\\t\\tm[13] = 0;\\n\\t\\tm[14] = 0;\\n\\t\\tm[15] = 1;\\n\\t\\treturn this;\\n\\t}\\n\\tgetEulerAngles(eulers = new Vec3()) {\\n\\t\\tthis.getScale(scale);\\n\\t\\tconst sx = scale.x;\\n\\t\\tconst sy = scale.y;\\n\\t\\tconst sz = scale.z;\\n\\t\\tif (sx === 0 || sy === 0 || sz === 0) {\\n\\t\\t\\treturn eulers.set(0, 0, 0);\\n\\t\\t}\\n\\t\\tconst m = this.data;\\n\\t\\tconst y2 = Math.asin(-m[2] / sx);\\n\\t\\tconst halfPi = Math.PI * 0.5;\\n\\t\\tlet x2, z2;\\n\\t\\tif (y2 < halfPi) {\\n\\t\\t\\tif (y2 > -halfPi) {\\n\\t\\t\\t\\tx2 = Math.atan2(m[6] / sy, m[10] / sz);\\n\\t\\t\\t\\tz2 = Math.atan2(m[1] / sx, m[0] / sx);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tz2 = 0;\\n\\t\\t\\t\\tx2 = -Math.atan2(m[4] / sy, m[5] / sy);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tz2 = 0;\\n\\t\\t\\tx2 = Math.atan2(m[4] / sy, m[5] / sy);\\n\\t\\t}\\n\\t\\treturn eulers.set(x2, y2, z2).mulScalar(math.RAD_TO_DEG);\\n\\t}\\n\\ttoString() {\\n\\t\\treturn `[${this.data.join(\\\", \\\")}]`;\\n\\t}\\n\\tstatic IDENTITY = Object.freeze(new Mat4());\\n\\tstatic ZERO = Object.freeze(new Mat4().set([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]));\\n}\\n\\nclass Quat {\\n\\tx;\\n\\ty;\\n\\tz;\\n\\tw;\\n\\tconstructor(x = 0, y = 0, z = 0, w = 1) {\\n\\t\\tif (x.length === 4) {\\n\\t\\t\\tthis.x = x[0];\\n\\t\\t\\tthis.y = x[1];\\n\\t\\t\\tthis.z = x[2];\\n\\t\\t\\tthis.w = x[3];\\n\\t\\t} else {\\n\\t\\t\\tthis.x = x;\\n\\t\\t\\tthis.y = y;\\n\\t\\t\\tthis.z = z;\\n\\t\\t\\tthis.w = w;\\n\\t\\t}\\n\\t}\\n\\tclone() {\\n\\t\\tconst cstr = this.constructor;\\n\\t\\treturn new cstr(this.x, this.y, this.z, this.w);\\n\\t}\\n\\tconjugate(src = this) {\\n\\t\\tthis.x = src.x * -1;\\n\\t\\tthis.y = src.y * -1;\\n\\t\\tthis.z = src.z * -1;\\n\\t\\tthis.w = src.w;\\n\\t\\treturn this;\\n\\t}\\n\\tcopy(rhs) {\\n\\t\\tthis.x = rhs.x;\\n\\t\\tthis.y = rhs.y;\\n\\t\\tthis.z = rhs.z;\\n\\t\\tthis.w = rhs.w;\\n\\t\\treturn this;\\n\\t}\\n\\tdot(other) {\\n\\t\\treturn this.x * other.x + this.y * other.y + this.z * other.z + this.w * other.w;\\n\\t}\\n\\tequals(rhs) {\\n\\t\\treturn this.x === rhs.x && this.y === rhs.y && this.z === rhs.z && this.w === rhs.w;\\n\\t}\\n\\tequalsApprox(rhs, epsilon = 1e-6) {\\n\\t\\treturn Math.abs(this.x - rhs.x) < epsilon && Math.abs(this.y - rhs.y) < epsilon && Math.abs(this.z - rhs.z) < epsilon && Math.abs(this.w - rhs.w) < epsilon;\\n\\t}\\n\\tgetAxisAngle(axis) {\\n\\t\\tlet rad = Math.acos(this.w) * 2;\\n\\t\\tconst s = Math.sin(rad / 2);\\n\\t\\tif (s !== 0) {\\n\\t\\t\\taxis.x = this.x / s;\\n\\t\\t\\taxis.y = this.y / s;\\n\\t\\t\\taxis.z = this.z / s;\\n\\t\\t\\tif (axis.x < 0 || axis.y < 0 || axis.z < 0) {\\n\\t\\t\\t\\taxis.x *= -1;\\n\\t\\t\\t\\taxis.y *= -1;\\n\\t\\t\\t\\taxis.z *= -1;\\n\\t\\t\\t\\trad *= -1;\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\taxis.x = 1;\\n\\t\\t\\taxis.y = 0;\\n\\t\\t\\taxis.z = 0;\\n\\t\\t}\\n\\t\\treturn rad * math.RAD_TO_DEG;\\n\\t}\\n\\tgetEulerAngles(eulers = new Vec3()) {\\n\\t\\tlet x, y, z;\\n\\t\\tconst qx = this.x;\\n\\t\\tconst qy = this.y;\\n\\t\\tconst qz = this.z;\\n\\t\\tconst qw = this.w;\\n\\t\\tconst a2 = 2 * (qw * qy - qx * qz);\\n\\t\\tif (a2 <= -0.99999) {\\n\\t\\t\\tx = 2 * Math.atan2(qx, qw);\\n\\t\\t\\ty = -Math.PI / 2;\\n\\t\\t\\tz = 0;\\n\\t\\t} else if (a2 >= 0.99999) {\\n\\t\\t\\tx = 2 * Math.atan2(qx, qw);\\n\\t\\t\\ty = Math.PI / 2;\\n\\t\\t\\tz = 0;\\n\\t\\t} else {\\n\\t\\t\\tx = Math.atan2(2 * (qw * qx + qy * qz), 1 - 2 * (qx * qx + qy * qy));\\n\\t\\t\\ty = Math.asin(a2);\\n\\t\\t\\tz = Math.atan2(2 * (qw * qz + qx * qy), 1 - 2 * (qy * qy + qz * qz));\\n\\t\\t}\\n\\t\\treturn eulers.set(x, y, z).mulScalar(math.RAD_TO_DEG);\\n\\t}\\n\\tinvert(src = this) {\\n\\t\\treturn this.conjugate(src).normalize();\\n\\t}\\n\\tlength() {\\n\\t\\treturn Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);\\n\\t}\\n\\tlengthSq() {\\n\\t\\treturn this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;\\n\\t}\\n\\tlerp(lhs, rhs, alpha) {\\n\\t\\tconst omt = (1 - alpha) * (lhs.dot(rhs) < 0 ? -1 : 1);\\n\\t\\tthis.x = lhs.x * omt + rhs.x * alpha;\\n\\t\\tthis.y = lhs.y * omt + rhs.y * alpha;\\n\\t\\tthis.z = lhs.z * omt + rhs.z * alpha;\\n\\t\\tthis.w = lhs.w * omt + rhs.w * alpha;\\n\\t\\treturn this.normalize();\\n\\t}\\n\\tmul(rhs) {\\n\\t\\tconst q1x = this.x;\\n\\t\\tconst q1y = this.y;\\n\\t\\tconst q1z = this.z;\\n\\t\\tconst q1w = this.w;\\n\\t\\tconst q2x = rhs.x;\\n\\t\\tconst q2y = rhs.y;\\n\\t\\tconst q2z = rhs.z;\\n\\t\\tconst q2w = rhs.w;\\n\\t\\tthis.x = q1w * q2x + q1x * q2w + q1y * q2z - q1z * q2y;\\n\\t\\tthis.y = q1w * q2y + q1y * q2w + q1z * q2x - q1x * q2z;\\n\\t\\tthis.z = q1w * q2z + q1z * q2w + q1x * q2y - q1y * q2x;\\n\\t\\tthis.w = q1w * q2w - q1x * q2x - q1y * q2y - q1z * q2z;\\n\\t\\treturn this;\\n\\t}\\n\\tmulScalar(scalar, src = this) {\\n\\t\\tthis.x = src.x * scalar;\\n\\t\\tthis.y = src.y * scalar;\\n\\t\\tthis.z = src.z * scalar;\\n\\t\\tthis.w = src.w * scalar;\\n\\t\\treturn this;\\n\\t}\\n\\tmul2(lhs, rhs) {\\n\\t\\tconst q1x = lhs.x;\\n\\t\\tconst q1y = lhs.y;\\n\\t\\tconst q1z = lhs.z;\\n\\t\\tconst q1w = lhs.w;\\n\\t\\tconst q2x = rhs.x;\\n\\t\\tconst q2y = rhs.y;\\n\\t\\tconst q2z = rhs.z;\\n\\t\\tconst q2w = rhs.w;\\n\\t\\tthis.x = q1w * q2x + q1x * q2w + q1y * q2z - q1z * q2y;\\n\\t\\tthis.y = q1w * q2y + q1y * q2w + q1z * q2x - q1x * q2z;\\n\\t\\tthis.z = q1w * q2z + q1z * q2w + q1x * q2y - q1y * q2x;\\n\\t\\tthis.w = q1w * q2w - q1x * q2x - q1y * q2y - q1z * q2z;\\n\\t\\treturn this;\\n\\t}\\n\\tnormalize(src = this) {\\n\\t\\tlet len = src.length();\\n\\t\\tif (len === 0) {\\n\\t\\t\\tthis.x = this.y = this.z = 0;\\n\\t\\t\\tthis.w = 1;\\n\\t\\t} else {\\n\\t\\t\\tlen = 1 / len;\\n\\t\\t\\tthis.x = src.x * len;\\n\\t\\t\\tthis.y = src.y * len;\\n\\t\\t\\tthis.z = src.z * len;\\n\\t\\t\\tthis.w = src.w * len;\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\tset(x, y, z, w) {\\n\\t\\tthis.x = x;\\n\\t\\tthis.y = y;\\n\\t\\tthis.z = z;\\n\\t\\tthis.w = w;\\n\\t\\treturn this;\\n\\t}\\n\\tsetFromAxisAngle(axis, angle) {\\n\\t\\tangle *= 0.5 * math.DEG_TO_RAD;\\n\\t\\tconst sa = Math.sin(angle);\\n\\t\\tconst ca = Math.cos(angle);\\n\\t\\tthis.x = sa * axis.x;\\n\\t\\tthis.y = sa * axis.y;\\n\\t\\tthis.z = sa * axis.z;\\n\\t\\tthis.w = ca;\\n\\t\\treturn this;\\n\\t}\\n\\tsetFromEulerAngles(ex, ey, ez) {\\n\\t\\tif (ex instanceof Vec3) {\\n\\t\\t\\tconst vec = ex;\\n\\t\\t\\tex = vec.x;\\n\\t\\t\\tey = vec.y;\\n\\t\\t\\tez = vec.z;\\n\\t\\t}\\n\\t\\tconst halfToRad = 0.5 * math.DEG_TO_RAD;\\n\\t\\tex *= halfToRad;\\n\\t\\tey *= halfToRad;\\n\\t\\tez *= halfToRad;\\n\\t\\tconst sx = Math.sin(ex);\\n\\t\\tconst cx = Math.cos(ex);\\n\\t\\tconst sy = Math.sin(ey);\\n\\t\\tconst cy = Math.cos(ey);\\n\\t\\tconst sz = Math.sin(ez);\\n\\t\\tconst cz = Math.cos(ez);\\n\\t\\tthis.x = sx * cy * cz - cx * sy * sz;\\n\\t\\tthis.y = cx * sy * cz + sx * cy * sz;\\n\\t\\tthis.z = cx * cy * sz - sx * sy * cz;\\n\\t\\tthis.w = cx * cy * cz + sx * sy * sz;\\n\\t\\treturn this;\\n\\t}\\n\\tsetFromMat4(m) {\\n\\t\\tconst d = m.data;\\n\\t\\tlet m00 = d[0];\\n\\t\\tlet m01 = d[1];\\n\\t\\tlet m02 = d[2];\\n\\t\\tlet m10 = d[4];\\n\\t\\tlet m11 = d[5];\\n\\t\\tlet m12 = d[6];\\n\\t\\tlet m20 = d[8];\\n\\t\\tlet m21 = d[9];\\n\\t\\tlet m22 = d[10];\\n\\t\\tconst det = m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m12 * m20) + m02 * (m10 * m21 - m11 * m20);\\n\\t\\tif (det < 0) {\\n\\t\\t\\tm00 = -m00;\\n\\t\\t\\tm01 = -m01;\\n\\t\\t\\tm02 = -m02;\\n\\t\\t}\\n\\t\\tlet l;\\n\\t\\tl = m00 * m00 + m01 * m01 + m02 * m02;\\n\\t\\tif (l === 0) return this.set(0, 0, 0, 1);\\n\\t\\tl = 1 / Math.sqrt(l);\\n\\t\\tm00 *= l;\\n\\t\\tm01 *= l;\\n\\t\\tm02 *= l;\\n\\t\\tl = m10 * m10 + m11 * m11 + m12 * m12;\\n\\t\\tif (l === 0) return this.set(0, 0, 0, 1);\\n\\t\\tl = 1 / Math.sqrt(l);\\n\\t\\tm10 *= l;\\n\\t\\tm11 *= l;\\n\\t\\tm12 *= l;\\n\\t\\tl = m20 * m20 + m21 * m21 + m22 * m22;\\n\\t\\tif (l === 0) return this.set(0, 0, 0, 1);\\n\\t\\tl = 1 / Math.sqrt(l);\\n\\t\\tm20 *= l;\\n\\t\\tm21 *= l;\\n\\t\\tm22 *= l;\\n\\t\\tif (m22 < 0) {\\n\\t\\t\\tif (m00 > m11) {\\n\\t\\t\\t\\tthis.set(1 + m00 - m11 - m22, m01 + m10, m20 + m02, m12 - m21);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.set(m01 + m10, 1 - m00 + m11 - m22, m12 + m21, m20 - m02);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tif (m00 < -m11) {\\n\\t\\t\\t\\tthis.set(m20 + m02, m12 + m21, 1 - m00 - m11 + m22, m01 - m10);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.set(m12 - m21, m20 - m02, m01 - m10, 1 + m00 + m11 + m22);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn this.mulScalar(1 / this.length());\\n\\t}\\n\\tsetFromDirections(from, to) {\\n\\t\\tconst dotProduct = 1 + from.dot(to);\\n\\t\\tif (dotProduct < Number.EPSILON) {\\n\\t\\t\\tif (Math.abs(from.x) > Math.abs(from.y)) {\\n\\t\\t\\t\\tthis.x = -from.z;\\n\\t\\t\\t\\tthis.y = 0;\\n\\t\\t\\t\\tthis.z = from.x;\\n\\t\\t\\t\\tthis.w = 0;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.x = 0;\\n\\t\\t\\t\\tthis.y = -from.z;\\n\\t\\t\\t\\tthis.z = from.y;\\n\\t\\t\\t\\tthis.w = 0;\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis.x = from.y * to.z - from.z * to.y;\\n\\t\\t\\tthis.y = from.z * to.x - from.x * to.z;\\n\\t\\t\\tthis.z = from.x * to.y - from.y * to.x;\\n\\t\\t\\tthis.w = dotProduct;\\n\\t\\t}\\n\\t\\treturn this.normalize();\\n\\t}\\n\\tslerp(lhs, rhs, alpha) {\\n\\t\\tconst lx = lhs.x;\\n\\t\\tconst ly = lhs.y;\\n\\t\\tconst lz = lhs.z;\\n\\t\\tconst lw = lhs.w;\\n\\t\\tlet rx = rhs.x;\\n\\t\\tlet ry = rhs.y;\\n\\t\\tlet rz = rhs.z;\\n\\t\\tlet rw = rhs.w;\\n\\t\\tlet cosHalfTheta = lw * rw + lx * rx + ly * ry + lz * rz;\\n\\t\\tif (cosHalfTheta < 0) {\\n\\t\\t\\trw = -rw;\\n\\t\\t\\trx = -rx;\\n\\t\\t\\try = -ry;\\n\\t\\t\\trz = -rz;\\n\\t\\t\\tcosHalfTheta = -cosHalfTheta;\\n\\t\\t}\\n\\t\\tif (Math.abs(cosHalfTheta) >= 1) {\\n\\t\\t\\tthis.w = lw;\\n\\t\\t\\tthis.x = lx;\\n\\t\\t\\tthis.y = ly;\\n\\t\\t\\tthis.z = lz;\\n\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tconst halfTheta = Math.acos(cosHalfTheta);\\n\\t\\tconst sinHalfTheta = Math.sqrt(1 - cosHalfTheta * cosHalfTheta);\\n\\t\\tif (Math.abs(sinHalfTheta) < 1e-3) {\\n\\t\\t\\tthis.w = lw * 0.5 + rw * 0.5;\\n\\t\\t\\tthis.x = lx * 0.5 + rx * 0.5;\\n\\t\\t\\tthis.y = ly * 0.5 + ry * 0.5;\\n\\t\\t\\tthis.z = lz * 0.5 + rz * 0.5;\\n\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tconst ratioA = Math.sin((1 - alpha) * halfTheta) / sinHalfTheta;\\n\\t\\tconst ratioB = Math.sin(alpha * halfTheta) / sinHalfTheta;\\n\\t\\tthis.w = lw * ratioA + rw * ratioB;\\n\\t\\tthis.x = lx * ratioA + rx * ratioB;\\n\\t\\tthis.y = ly * ratioA + ry * ratioB;\\n\\t\\tthis.z = lz * ratioA + rz * ratioB;\\n\\t\\treturn this;\\n\\t}\\n\\ttransformVector(vec, res = new Vec3()) {\\n\\t\\tconst x = vec.x, y = vec.y, z = vec.z;\\n\\t\\tconst qx = this.x, qy = this.y, qz = this.z, qw = this.w;\\n\\t\\tconst ix = qw * x + qy * z - qz * y;\\n\\t\\tconst iy = qw * y + qz * x - qx * z;\\n\\t\\tconst iz = qw * z + qx * y - qy * x;\\n\\t\\tconst iw = -qx * x - qy * y - qz * z;\\n\\t\\tres.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;\\n\\t\\tres.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;\\n\\t\\tres.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;\\n\\t\\treturn res;\\n\\t}\\n\\tfromArray(arr, offset = 0) {\\n\\t\\tthis.x = arr[offset] ?? this.x;\\n\\t\\tthis.y = arr[offset + 1] ?? this.y;\\n\\t\\tthis.z = arr[offset + 2] ?? this.z;\\n\\t\\tthis.w = arr[offset + 3] ?? this.w;\\n\\t\\treturn this;\\n\\t}\\n\\ttoString() {\\n\\t\\treturn `[${this.x}, ${this.y}, ${this.z}, ${this.w}]`;\\n\\t}\\n\\ttoArray(arr = [], offset = 0) {\\n\\t\\tarr[offset] = this.x;\\n\\t\\tarr[offset + 1] = this.y;\\n\\t\\tarr[offset + 2] = this.z;\\n\\t\\tarr[offset + 3] = this.w;\\n\\t\\treturn arr;\\n\\t}\\n\\tstatic IDENTITY = Object.freeze(new Quat(0, 0, 0, 1));\\n\\tstatic ZERO = Object.freeze(new Quat(0, 0, 0, 0));\\n}\\n\\nconst tmpVecA$1 = new Vec3();\\nconst tmpVecB$1 = new Vec3();\\nconst tmpVecC = new Vec3();\\nconst tmpVecD = new Vec3();\\nconst tmpVecE = new Vec3();\\nclass BoundingBox {\\n\\tcenter = new Vec3();\\n\\thalfExtents = new Vec3(0.5, 0.5, 0.5);\\n\\t_min = new Vec3();\\n\\t_max = new Vec3();\\n\\tconstructor(center, halfExtents) {\\n\\t\\tif (center) {\\n\\t\\t\\tthis.center.copy(center);\\n\\t\\t}\\n\\t\\tif (halfExtents) {\\n\\t\\t\\tthis.halfExtents.copy(halfExtents);\\n\\t\\t}\\n\\t}\\n\\tadd(other) {\\n\\t\\tconst tc = this.center;\\n\\t\\tconst tcx = tc.x;\\n\\t\\tconst tcy = tc.y;\\n\\t\\tconst tcz = tc.z;\\n\\t\\tconst th = this.halfExtents;\\n\\t\\tconst thx = th.x;\\n\\t\\tconst thy = th.y;\\n\\t\\tconst thz = th.z;\\n\\t\\tlet tminx = tcx - thx;\\n\\t\\tlet tmaxx = tcx + thx;\\n\\t\\tlet tminy = tcy - thy;\\n\\t\\tlet tmaxy = tcy + thy;\\n\\t\\tlet tminz = tcz - thz;\\n\\t\\tlet tmaxz = tcz + thz;\\n\\t\\tconst oc = other.center;\\n\\t\\tconst ocx = oc.x;\\n\\t\\tconst ocy = oc.y;\\n\\t\\tconst ocz = oc.z;\\n\\t\\tconst oh = other.halfExtents;\\n\\t\\tconst ohx = oh.x;\\n\\t\\tconst ohy = oh.y;\\n\\t\\tconst ohz = oh.z;\\n\\t\\tconst ominx = ocx - ohx;\\n\\t\\tconst omaxx = ocx + ohx;\\n\\t\\tconst ominy = ocy - ohy;\\n\\t\\tconst omaxy = ocy + ohy;\\n\\t\\tconst ominz = ocz - ohz;\\n\\t\\tconst omaxz = ocz + ohz;\\n\\t\\tif (ominx < tminx) tminx = ominx;\\n\\t\\tif (omaxx > tmaxx) tmaxx = omaxx;\\n\\t\\tif (ominy < tminy) tminy = ominy;\\n\\t\\tif (omaxy > tmaxy) tmaxy = omaxy;\\n\\t\\tif (ominz < tminz) tminz = ominz;\\n\\t\\tif (omaxz > tmaxz) tmaxz = omaxz;\\n\\t\\ttc.x = (tminx + tmaxx) * 0.5;\\n\\t\\ttc.y = (tminy + tmaxy) * 0.5;\\n\\t\\ttc.z = (tminz + tmaxz) * 0.5;\\n\\t\\tth.x = (tmaxx - tminx) * 0.5;\\n\\t\\tth.y = (tmaxy - tminy) * 0.5;\\n\\t\\tth.z = (tmaxz - tminz) * 0.5;\\n\\t}\\n\\tcopy(src) {\\n\\t\\tthis.center.copy(src.center);\\n\\t\\tthis.halfExtents.copy(src.halfExtents);\\n\\t}\\n\\tclone() {\\n\\t\\treturn new BoundingBox(this.center, this.halfExtents);\\n\\t}\\n\\tintersects(other) {\\n\\t\\tconst aMax = this.getMax();\\n\\t\\tconst aMin = this.getMin();\\n\\t\\tconst bMax = other.getMax();\\n\\t\\tconst bMin = other.getMin();\\n\\t\\treturn aMin.x <= bMax.x && aMax.x >= bMin.x && aMin.y <= bMax.y && aMax.y >= bMin.y && aMin.z <= bMax.z && aMax.z >= bMin.z;\\n\\t}\\n\\t_intersectsRay(ray, point) {\\n\\t\\tconst tMin = tmpVecA$1.copy(this.getMin()).sub(ray.origin);\\n\\t\\tconst tMax = tmpVecB$1.copy(this.getMax()).sub(ray.origin);\\n\\t\\tconst dir = ray.direction;\\n\\t\\tif (dir.x === 0) {\\n\\t\\t\\ttMin.x = tMin.x < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;\\n\\t\\t\\ttMax.x = tMax.x < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;\\n\\t\\t} else {\\n\\t\\t\\ttMin.x /= dir.x;\\n\\t\\t\\ttMax.x /= dir.x;\\n\\t\\t}\\n\\t\\tif (dir.y === 0) {\\n\\t\\t\\ttMin.y = tMin.y < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;\\n\\t\\t\\ttMax.y = tMax.y < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;\\n\\t\\t} else {\\n\\t\\t\\ttMin.y /= dir.y;\\n\\t\\t\\ttMax.y /= dir.y;\\n\\t\\t}\\n\\t\\tif (dir.z === 0) {\\n\\t\\t\\ttMin.z = tMin.z < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;\\n\\t\\t\\ttMax.z = tMax.z < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;\\n\\t\\t} else {\\n\\t\\t\\ttMin.z /= dir.z;\\n\\t\\t\\ttMax.z /= dir.z;\\n\\t\\t}\\n\\t\\tconst realMin = tmpVecC.set(Math.min(tMin.x, tMax.x), Math.min(tMin.y, tMax.y), Math.min(tMin.z, tMax.z));\\n\\t\\tconst realMax = tmpVecD.set(Math.max(tMin.x, tMax.x), Math.max(tMin.y, tMax.y), Math.max(tMin.z, tMax.z));\\n\\t\\tconst minMax = Math.min(Math.min(realMax.x, realMax.y), realMax.z);\\n\\t\\tconst maxMin = Math.max(Math.max(realMin.x, realMin.y), realMin.z);\\n\\t\\tconst intersects = minMax >= maxMin && maxMin >= 0;\\n\\t\\tif (intersects) {\\n\\t\\t\\tpoint.copy(ray.direction).mulScalar(maxMin).add(ray.origin);\\n\\t\\t}\\n\\t\\treturn intersects;\\n\\t}\\n\\t_fastIntersectsRay(ray) {\\n\\t\\tconst diff = tmpVecA$1;\\n\\t\\tconst cross = tmpVecB$1;\\n\\t\\tconst prod = tmpVecC;\\n\\t\\tconst absDiff = tmpVecD;\\n\\t\\tconst absDir = tmpVecE;\\n\\t\\tconst rayDir = ray.direction;\\n\\t\\tdiff.sub2(ray.origin, this.center);\\n\\t\\tabsDiff.set(Math.abs(diff.x), Math.abs(diff.y), Math.abs(diff.z));\\n\\t\\tprod.mul2(diff, rayDir);\\n\\t\\tif (absDiff.x > this.halfExtents.x && prod.x >= 0) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tif (absDiff.y > this.halfExtents.y && prod.y >= 0) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tif (absDiff.z > this.halfExtents.z && prod.z >= 0) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tabsDir.set(Math.abs(rayDir.x), Math.abs(rayDir.y), Math.abs(rayDir.z));\\n\\t\\tcross.cross(rayDir, diff);\\n\\t\\tcross.set(Math.abs(cross.x), Math.abs(cross.y), Math.abs(cross.z));\\n\\t\\tif (cross.x > this.halfExtents.y * absDir.z + this.halfExtents.z * absDir.y) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tif (cross.y > this.halfExtents.x * absDir.z + this.halfExtents.z * absDir.x) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tif (cross.z > this.halfExtents.x * absDir.y + this.halfExtents.y * absDir.x) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\treturn true;\\n\\t}\\n\\tintersectsRay(ray, point) {\\n\\t\\tif (point) {\\n\\t\\t\\treturn this._intersectsRay(ray, point);\\n\\t\\t}\\n\\t\\treturn this._fastIntersectsRay(ray);\\n\\t}\\n\\tsetMinMax(min, max) {\\n\\t\\tthis.center.add2(max, min).mulScalar(0.5);\\n\\t\\tthis.halfExtents.sub2(max, min).mulScalar(0.5);\\n\\t}\\n\\tgetMin() {\\n\\t\\treturn this._min.copy(this.center).sub(this.halfExtents);\\n\\t}\\n\\tgetMax() {\\n\\t\\treturn this._max.copy(this.center).add(this.halfExtents);\\n\\t}\\n\\tcontainsPoint(point) {\\n\\t\\tconst c = this.center;\\n\\t\\tconst h = this.halfExtents;\\n\\t\\tif (point.x < c.x - h.x || point.x > c.x + h.x || point.y < c.y - h.y || point.y > c.y + h.y || point.z < c.z - h.z || point.z > c.z + h.z) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\treturn true;\\n\\t}\\n\\tclosestPoint(point, result = new Vec3()) {\\n\\t\\tconst c = this.center;\\n\\t\\tconst h = this.halfExtents;\\n\\t\\treturn result.set(\\n\\t\\t\\tMath.max(c.x - h.x, Math.min(point.x, c.x + h.x)),\\n\\t\\t\\tMath.max(c.y - h.y, Math.min(point.y, c.y + h.y)),\\n\\t\\t\\tMath.max(c.z - h.z, Math.min(point.z, c.z + h.z))\\n\\t\\t);\\n\\t}\\n\\tsetFromTransformedAabb(aabb, m, ignoreScale = false) {\\n\\t\\tconst ac = aabb.center;\\n\\t\\tconst ar = aabb.halfExtents;\\n\\t\\tconst d = m.data;\\n\\t\\tlet mx0 = d[0];\\n\\t\\tlet mx1 = d[4];\\n\\t\\tlet mx2 = d[8];\\n\\t\\tlet my0 = d[1];\\n\\t\\tlet my1 = d[5];\\n\\t\\tlet my2 = d[9];\\n\\t\\tlet mz0 = d[2];\\n\\t\\tlet mz1 = d[6];\\n\\t\\tlet mz2 = d[10];\\n\\t\\tif (ignoreScale) {\\n\\t\\t\\tlet lengthSq = mx0 * mx0 + mx1 * mx1 + mx2 * mx2;\\n\\t\\t\\tif (lengthSq > 0) {\\n\\t\\t\\t\\tconst invLength = 1 / Math.sqrt(lengthSq);\\n\\t\\t\\t\\tmx0 *= invLength;\\n\\t\\t\\t\\tmx1 *= invLength;\\n\\t\\t\\t\\tmx2 *= invLength;\\n\\t\\t\\t}\\n\\t\\t\\tlengthSq = my0 * my0 + my1 * my1 + my2 * my2;\\n\\t\\t\\tif (lengthSq > 0) {\\n\\t\\t\\t\\tconst invLength = 1 / Math.sqrt(lengthSq);\\n\\t\\t\\t\\tmy0 *= invLength;\\n\\t\\t\\t\\tmy1 *= invLength;\\n\\t\\t\\t\\tmy2 *= invLength;\\n\\t\\t\\t}\\n\\t\\t\\tlengthSq = mz0 * mz0 + mz1 * mz1 + mz2 * mz2;\\n\\t\\t\\tif (lengthSq > 0) {\\n\\t\\t\\t\\tconst invLength = 1 / Math.sqrt(lengthSq);\\n\\t\\t\\t\\tmz0 *= invLength;\\n\\t\\t\\t\\tmz1 *= invLength;\\n\\t\\t\\t\\tmz2 *= invLength;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.center.set(\\n\\t\\t\\td[12] + mx0 * ac.x + mx1 * ac.y + mx2 * ac.z,\\n\\t\\t\\td[13] + my0 * ac.x + my1 * ac.y + my2 * ac.z,\\n\\t\\t\\td[14] + mz0 * ac.x + mz1 * ac.y + mz2 * ac.z\\n\\t\\t);\\n\\t\\tthis.halfExtents.set(\\n\\t\\t\\tMath.abs(mx0) * ar.x + Math.abs(mx1) * ar.y + Math.abs(mx2) * ar.z,\\n\\t\\t\\tMath.abs(my0) * ar.x + Math.abs(my1) * ar.y + Math.abs(my2) * ar.z,\\n\\t\\t\\tMath.abs(mz0) * ar.x + Math.abs(mz1) * ar.y + Math.abs(mz2) * ar.z\\n\\t\\t);\\n\\t}\\n\\tstatic computeMinMax(vertices, min, max, numVerts = vertices.length / 3) {\\n\\t\\tif (numVerts > 0) {\\n\\t\\t\\tlet minx = vertices[0];\\n\\t\\t\\tlet miny = vertices[1];\\n\\t\\t\\tlet minz = vertices[2];\\n\\t\\t\\tlet maxx = minx;\\n\\t\\t\\tlet maxy = miny;\\n\\t\\t\\tlet maxz = minz;\\n\\t\\t\\tconst n = numVerts * 3;\\n\\t\\t\\tfor (let i = 3; i < n; i += 3) {\\n\\t\\t\\t\\tconst x = vertices[i];\\n\\t\\t\\t\\tconst y = vertices[i + 1];\\n\\t\\t\\t\\tconst z = vertices[i + 2];\\n\\t\\t\\t\\tif (x < minx) minx = x;\\n\\t\\t\\t\\tif (y < miny) miny = y;\\n\\t\\t\\t\\tif (z < minz) minz = z;\\n\\t\\t\\t\\tif (x > maxx) maxx = x;\\n\\t\\t\\t\\tif (y > maxy) maxy = y;\\n\\t\\t\\t\\tif (z > maxz) maxz = z;\\n\\t\\t\\t}\\n\\t\\t\\tmin.set(minx, miny, minz);\\n\\t\\t\\tmax.set(maxx, maxy, maxz);\\n\\t\\t}\\n\\t}\\n\\tcompute(vertices, numVerts) {\\n\\t\\tBoundingBox.computeMinMax(vertices, tmpVecA$1, tmpVecB$1, numVerts);\\n\\t\\tthis.setMinMax(tmpVecA$1, tmpVecB$1);\\n\\t}\\n\\tintersectsBoundingSphere(sphere) {\\n\\t\\tconst sq = this._distanceToBoundingSphereSq(sphere);\\n\\t\\tif (sq <= sphere.radius * sphere.radius) {\\n\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\treturn false;\\n\\t}\\n\\t_distanceToBoundingSphereSq(sphere) {\\n\\t\\tconst boxMin = this.getMin();\\n\\t\\tconst boxMax = this.getMax();\\n\\t\\tlet sq = 0;\\n\\t\\tconst axis = [\\\"x\\\", \\\"y\\\", \\\"z\\\"];\\n\\t\\tfor (let i = 0; i < 3; ++i) {\\n\\t\\t\\tlet out = 0;\\n\\t\\t\\tconst pn = sphere.center[axis[i]];\\n\\t\\t\\tconst bMin = boxMin[axis[i]];\\n\\t\\t\\tconst bMax = boxMax[axis[i]];\\n\\t\\t\\tlet val = 0;\\n\\t\\t\\tif (pn < bMin) {\\n\\t\\t\\t\\tval = bMin - pn;\\n\\t\\t\\t\\tout += val * val;\\n\\t\\t\\t}\\n\\t\\t\\tif (pn > bMax) {\\n\\t\\t\\t\\tval = pn - bMax;\\n\\t\\t\\t\\tout += val * val;\\n\\t\\t\\t}\\n\\t\\t\\tsq += out;\\n\\t\\t}\\n\\t\\treturn sq;\\n\\t}\\n\\t_expand(expandMin, expandMax) {\\n\\t\\ttmpVecA$1.add2(this.getMin(), expandMin);\\n\\t\\ttmpVecB$1.add2(this.getMax(), expandMax);\\n\\t\\tthis.setMinMax(tmpVecA$1, tmpVecB$1);\\n\\t}\\n}\\n\\nconst tmpVecA = new Vec3();\\nconst tmpVecB = new Vec3();\\nclass BoundingSphere {\\n\\tcenter;\\n\\tradius;\\n\\tconstructor(center = new Vec3(), radius = 0.5) {\\n\\t\\tthis.center = center;\\n\\t\\tthis.radius = radius;\\n\\t}\\n\\tcontainsPoint(point) {\\n\\t\\tconst lenSq = tmpVecA.sub2(point, this.center).lengthSq();\\n\\t\\tconst r = this.radius;\\n\\t\\treturn lenSq < r * r;\\n\\t}\\n\\tintersectsRay(ray, point) {\\n\\t\\tconst m = tmpVecA.copy(ray.origin).sub(this.center);\\n\\t\\tconst b = m.dot(tmpVecB.copy(ray.direction).normalize());\\n\\t\\tconst c = m.dot(m) - this.radius * this.radius;\\n\\t\\tif (c > 0 && b > 0) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tconst discr = b * b - c;\\n\\t\\tif (discr < 0) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tconst t = Math.abs(-b - Math.sqrt(discr));\\n\\t\\tif (point) {\\n\\t\\t\\tpoint.copy(ray.direction).mulScalar(t).add(ray.origin);\\n\\t\\t}\\n\\t\\treturn true;\\n\\t}\\n\\tintersectsBoundingSphere(sphere) {\\n\\t\\ttmpVecA.sub2(sphere.center, this.center);\\n\\t\\tconst totalRadius = sphere.radius + this.radius;\\n\\t\\tif (tmpVecA.lengthSq() <= totalRadius * totalRadius) {\\n\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\treturn false;\\n\\t}\\n}\\n\\nclass Plane {\\n\\tnormal = new Vec3();\\n\\tdistance;\\n\\tconstructor(normal = Vec3.UP, distance = 0) {\\n\\t\\tthis.normal.copy(normal);\\n\\t\\tthis.distance = distance;\\n\\t}\\n\\tclone() {\\n\\t\\tconst cstr = this.constructor;\\n\\t\\treturn new cstr().copy(this);\\n\\t}\\n\\tcopy(src) {\\n\\t\\tthis.normal.copy(src.normal);\\n\\t\\tthis.distance = src.distance;\\n\\t\\treturn this;\\n\\t}\\n\\tintersectsLine(start, end, point) {\\n\\t\\tconst d = this.distance;\\n\\t\\tconst d0 = this.normal.dot(start) + d;\\n\\t\\tconst d1 = this.normal.dot(end) + d;\\n\\t\\tconst t = d0 / (d0 - d1);\\n\\t\\tconst intersects = t >= 0 && t <= 1;\\n\\t\\tif (intersects && point) {\\n\\t\\t\\tpoint.lerp(start, end, t);\\n\\t\\t}\\n\\t\\treturn intersects;\\n\\t}\\n\\tintersectsRay(ray, point) {\\n\\t\\tconst denominator = this.normal.dot(ray.direction);\\n\\t\\tif (denominator === 0) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tconst t = -(this.normal.dot(ray.origin) + this.distance) / denominator;\\n\\t\\tif (t >= 0 && point) {\\n\\t\\t\\tpoint.copy(ray.direction).mulScalar(t).add(ray.origin);\\n\\t\\t}\\n\\t\\treturn t >= 0;\\n\\t}\\n\\tnormalize() {\\n\\t\\tconst invLength = 1 / this.normal.length();\\n\\t\\tthis.normal.mulScalar(invLength);\\n\\t\\tthis.distance *= invLength;\\n\\t\\treturn this;\\n\\t}\\n\\tset(nx, ny, nz, d) {\\n\\t\\tthis.normal.set(nx, ny, nz);\\n\\t\\tthis.distance = d;\\n\\t\\treturn this;\\n\\t}\\n\\tsetFromPointNormal(point, normal) {\\n\\t\\tthis.normal.copy(normal);\\n\\t\\tthis.distance = -this.normal.dot(point);\\n\\t\\treturn this;\\n\\t}\\n}\\n\\nclass Frustum {\\n\\tplanes = [];\\n\\tconstructor() {\\n\\t\\tfor (let i = 0; i < 6; i++) {\\n\\t\\t\\tthis.planes[i] = new Plane();\\n\\t\\t}\\n\\t}\\n\\tclone() {\\n\\t\\tconst cstr = this.constructor;\\n\\t\\treturn new cstr().copy(this);\\n\\t}\\n\\tcopy(src) {\\n\\t\\tfor (let i = 0; i < 6; i++) {\\n\\t\\t\\tthis.planes[i].copy(src.planes[i]);\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\tsetFromMat4(matrix) {\\n\\t\\tconst d = matrix.data;\\n\\t\\tconst m00 = d[0], m01 = d[1], m02 = d[2], m03 = d[3];\\n\\t\\tconst m10 = d[4], m11 = d[5], m12 = d[6], m13 = d[7];\\n\\t\\tconst m20 = d[8], m21 = d[9], m22 = d[10], m23 = d[11];\\n\\t\\tconst m30 = d[12], m31 = d[13], m32 = d[14], m33 = d[15];\\n\\t\\tconst planes = this.planes;\\n\\t\\tplanes[0].set(m03 - m00, m13 - m10, m23 - m20, m33 - m30).normalize();\\n\\t\\tplanes[1].set(m03 + m00, m13 + m10, m23 + m20, m33 + m30).normalize();\\n\\t\\tplanes[2].set(m03 + m01, m13 + m11, m23 + m21, m33 + m31).normalize();\\n\\t\\tplanes[3].set(m03 - m01, m13 - m11, m23 - m21, m33 - m31).normalize();\\n\\t\\tplanes[4].set(m03 - m02, m13 - m12, m23 - m22, m33 - m32).normalize();\\n\\t\\tplanes[5].set(m03 + m02, m13 + m12, m23 + m22, m33 + m32).normalize();\\n\\t}\\n\\tcontainsPoint(point) {\\n\\t\\tfor (let p = 0; p < 6; p++) {\\n\\t\\t\\tconst { normal, distance } = this.planes[p];\\n\\t\\t\\tif (normal.dot(point) + distance <= 0) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn true;\\n\\t}\\n\\tadd(other) {\\n\\t\\tconst planes = this.planes;\\n\\t\\tconst otherPlanes = other.planes;\\n\\t\\tfor (let p = 0; p < 6; p++) {\\n\\t\\t\\tif (otherPlanes[p].distance > planes[p].distance) {\\n\\t\\t\\t\\tplanes[p].copy(otherPlanes[p]);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\tcontainsSphere(sphere) {\\n\\t\\tconst { center, radius } = sphere;\\n\\t\\tlet c = 0;\\n\\t\\tfor (let p = 0; p < 6; p++) {\\n\\t\\t\\tconst { normal, distance } = this.planes[p];\\n\\t\\t\\tconst d = normal.dot(center) + distance;\\n\\t\\t\\tif (d <= -radius) {\\n\\t\\t\\t\\treturn 0;\\n\\t\\t\\t}\\n\\t\\t\\tif (d > radius) {\\n\\t\\t\\t\\tc++;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn c === 6 ? 2 : 1;\\n\\t}\\n}\\n\\nclass Ray {\\n\\torigin = new Vec3();\\n\\tdirection = Vec3.FORWARD.clone();\\n\\tconstructor(origin, direction) {\\n\\t\\tif (origin) {\\n\\t\\t\\tthis.origin.copy(origin);\\n\\t\\t}\\n\\t\\tif (direction) {\\n\\t\\t\\tthis.direction.copy(direction);\\n\\t\\t}\\n\\t}\\n\\tset(origin, direction) {\\n\\t\\tthis.origin.copy(origin);\\n\\t\\tthis.direction.copy(direction);\\n\\t\\treturn this;\\n\\t}\\n\\tcopy(src) {\\n\\t\\treturn this.set(src.origin, src.direction);\\n\\t}\\n\\tclone() {\\n\\t\\treturn new this.constructor(this.origin, this.direction);\\n\\t}\\n}\\n\\nconst ADDRESS_REPEAT = 0;\\nconst ADDRESS_CLAMP_TO_EDGE = 1;\\nconst ADDRESS_MIRRORED_REPEAT = 2;\\nconst BLENDMODE_ZERO = 0;\\nconst BLENDMODE_ONE = 1;\\nconst BLENDMODE_SRC_COLOR = 2;\\nconst BLENDMODE_DST_COLOR = 4;\\nconst BLENDMODE_ONE_MINUS_DST_COLOR = 5;\\nconst BLENDMODE_SRC_ALPHA = 6;\\nconst BLENDMODE_ONE_MINUS_SRC_ALPHA = 8;\\nconst BLENDEQUATION_ADD = 0;\\nconst BLENDEQUATION_REVERSE_SUBTRACT = 2;\\nconst BLENDEQUATION_MIN = 3;\\nconst BLENDEQUATION_MAX = 4;\\nconst BUFFERUSAGE_READ = 1;\\nconst BUFFERUSAGE_COPY_SRC = 4;\\nconst BUFFERUSAGE_COPY_DST = 8;\\nconst BUFFERUSAGE_INDEX = 16;\\nconst BUFFERUSAGE_VERTEX = 32;\\nconst BUFFERUSAGE_UNIFORM = 64;\\nconst BUFFERUSAGE_STORAGE = 128;\\nconst BUFFERUSAGE_INDIRECT = 256;\\nconst BUFFER_STATIC = 0;\\nconst BUFFER_DYNAMIC = 1;\\nconst BUFFER_STREAM = 2;\\nconst BUFFER_GPUDYNAMIC = 3;\\nconst CLEARFLAG_COLOR = 1;\\nconst CLEARFLAG_DEPTH = 2;\\nconst CLEARFLAG_STENCIL = 4;\\nconst CULLFACE_NONE = 0;\\nconst CULLFACE_BACK = 1;\\nconst CULLFACE_FRONT = 2;\\nconst FRONTFACE_CCW = 0;\\nconst FRONTFACE_CW = 1;\\nconst FILTER_NEAREST = 0;\\nconst FILTER_LINEAR = 1;\\nconst FILTER_NEAREST_MIPMAP_NEAREST = 2;\\nconst FILTER_NEAREST_MIPMAP_LINEAR = 3;\\nconst FILTER_LINEAR_MIPMAP_NEAREST = 4;\\nconst FILTER_LINEAR_MIPMAP_LINEAR = 5;\\nconst FUNC_LESS = 1;\\nconst FUNC_EQUAL = 2;\\nconst FUNC_LESSEQUAL = 3;\\nconst FUNC_ALWAYS = 7;\\nconst INDEXFORMAT_UINT8 = 0;\\nconst INDEXFORMAT_UINT16 = 1;\\nconst INDEXFORMAT_UINT32 = 2;\\nconst indexFormatByteSize = [1, 2, 4];\\nconst PIXELFORMAT_A8 = 0;\\nconst PIXELFORMAT_L8 = 1;\\nconst PIXELFORMAT_LA8 = 2;\\nconst PIXELFORMAT_RGB565 = 3;\\nconst PIXELFORMAT_RGBA5551 = 4;\\nconst PIXELFORMAT_RGBA4 = 5;\\nconst PIXELFORMAT_RGB8 = 6;\\nconst PIXELFORMAT_RGBA8 = 7;\\nconst PIXELFORMAT_DXT1 = 8;\\nconst PIXELFORMAT_DXT3 = 9;\\nconst PIXELFORMAT_DXT5 = 10;\\nconst PIXELFORMAT_RGB16F = 11;\\nconst PIXELFORMAT_RGBA16F = 12;\\nconst PIXELFORMAT_RGB32F = 13;\\nconst PIXELFORMAT_RGBA32F = 14;\\nconst PIXELFORMAT_R32F = 15;\\nconst PIXELFORMAT_DEPTH = 16;\\nconst PIXELFORMAT_DEPTHSTENCIL = 17;\\nconst PIXELFORMAT_111110F = 18;\\nconst PIXELFORMAT_SRGB8 = 19;\\nconst PIXELFORMAT_SRGBA8 = 20;\\nconst PIXELFORMAT_ETC1 = 21;\\nconst PIXELFORMAT_ETC2_RGB = 22;\\nconst PIXELFORMAT_ETC2_RGBA = 23;\\nconst PIXELFORMAT_PVRTC_2BPP_RGB_1 = 24;\\nconst PIXELFORMAT_PVRTC_2BPP_RGBA_1 = 25;\\nconst PIXELFORMAT_PVRTC_4BPP_RGB_1 = 26;\\nconst PIXELFORMAT_PVRTC_4BPP_RGBA_1 = 27;\\nconst PIXELFORMAT_ASTC_4x4 = 28;\\nconst PIXELFORMAT_ATC_RGB = 29;\\nconst PIXELFORMAT_ATC_RGBA = 30;\\nconst PIXELFORMAT_BGRA8 = 31;\\nconst PIXELFORMAT_R8I = 32;\\nconst PIXELFORMAT_R8U = 33;\\nconst PIXELFORMAT_R16I = 34;\\nconst PIXELFORMAT_R16U = 35;\\nconst PIXELFORMAT_R32I = 36;\\nconst PIXELFORMAT_R32U = 37;\\nconst PIXELFORMAT_RG8I = 38;\\nconst PIXELFORMAT_RG8U = 39;\\nconst PIXELFORMAT_RG16I = 40;\\nconst PIXELFORMAT_RG16U = 41;\\nconst PIXELFORMAT_RG32I = 42;\\nconst PIXELFORMAT_RG32U = 43;\\nconst PIXELFORMAT_RGBA8I = 44;\\nconst PIXELFORMAT_RGBA8U = 45;\\nconst PIXELFORMAT_RGBA16I = 46;\\nconst PIXELFORMAT_RGBA16U = 47;\\nconst PIXELFORMAT_RGBA32I = 48;\\nconst PIXELFORMAT_RGBA32U = 49;\\nconst PIXELFORMAT_R16F = 50;\\nconst PIXELFORMAT_RG16F = 51;\\nconst PIXELFORMAT_R8 = 52;\\nconst PIXELFORMAT_RG8 = 53;\\nconst PIXELFORMAT_DXT1_SRGB = 54;\\nconst PIXELFORMAT_DXT3_SRGBA = 55;\\nconst PIXELFORMAT_DXT5_SRGBA = 56;\\nconst PIXELFORMAT_ETC2_SRGB = 61;\\nconst PIXELFORMAT_ETC2_SRGBA = 62;\\nconst PIXELFORMAT_ASTC_4x4_SRGB = 63;\\nconst PIXELFORMAT_SBGRA8 = 64;\\nconst PIXELFORMAT_BC6F = 65;\\nconst PIXELFORMAT_BC6UF = 66;\\nconst PIXELFORMAT_BC7 = 67;\\nconst PIXELFORMAT_BC7_SRGBA = 68;\\nconst PIXELFORMAT_DEPTH16 = 69;\\nconst PIXELFORMAT_RG32F = 70;\\nconst PIXELFORMAT_RGB9E5 = 71;\\nconst PIXELFORMAT_RG8S = 72;\\nconst PIXELFORMAT_RGBA8S = 73;\\nconst PIXELFORMAT_RGB10A2 = 74;\\nconst PIXELFORMAT_RGB10A2U = 75;\\nconst pixelFormatInfo = /* @__PURE__ */ new Map([\\n\\t// float formats\\n\\t[PIXELFORMAT_A8, { name: \\\"A8\\\", size: 1, ldr: true }],\\n\\t[PIXELFORMAT_R8, { name: \\\"R8\\\", size: 1, ldr: true }],\\n\\t[PIXELFORMAT_L8, { name: \\\"L8\\\", size: 1, ldr: true }],\\n\\t[PIXELFORMAT_LA8, { name: \\\"LA8\\\", size: 2, ldr: true }],\\n\\t[PIXELFORMAT_RG8, { name: \\\"RG8\\\", size: 2, ldr: true }],\\n\\t[PIXELFORMAT_RGB565, { name: \\\"RGB565\\\", size: 2, ldr: true }],\\n\\t[PIXELFORMAT_RGBA5551, { name: \\\"RGBA5551\\\", size: 2, ldr: true }],\\n\\t[PIXELFORMAT_RGBA4, { name: \\\"RGBA4\\\", size: 2, ldr: true }],\\n\\t[PIXELFORMAT_RGB8, { name: \\\"RGB8\\\", size: 4, ldr: true }],\\n\\t[PIXELFORMAT_RGBA8, { name: \\\"RGBA8\\\", size: 4, ldr: true, srgbFormat: PIXELFORMAT_SRGBA8 }],\\n\\t[PIXELFORMAT_R16F, { name: \\\"R16F\\\", size: 2 }],\\n\\t[PIXELFORMAT_RG16F, { name: \\\"RG16F\\\", size: 4 }],\\n\\t[PIXELFORMAT_RGB16F, { name: \\\"RGB16F\\\", size: 8 }],\\n\\t[PIXELFORMAT_RGBA16F, { name: \\\"RGBA16F\\\", size: 8 }],\\n\\t[PIXELFORMAT_RGB32F, { name: \\\"RGB32F\\\", size: 16 }],\\n\\t[PIXELFORMAT_RGBA32F, { name: \\\"RGBA32F\\\", size: 16 }],\\n\\t[PIXELFORMAT_R32F, { name: \\\"R32F\\\", size: 4 }],\\n\\t[PIXELFORMAT_RG32F, { name: \\\"RG32F\\\", size: 8 }],\\n\\t[PIXELFORMAT_RGB9E5, { name: \\\"RGB9E5\\\", size: 4 }],\\n\\t[PIXELFORMAT_RG8S, { name: \\\"RG8S\\\", size: 2 }],\\n\\t[PIXELFORMAT_RGBA8S, { name: \\\"RGBA8S\\\", size: 4 }],\\n\\t[PIXELFORMAT_RGB10A2, { name: \\\"RGB10A2\\\", size: 4 }],\\n\\t[PIXELFORMAT_RGB10A2U, { name: \\\"RGB10A2U\\\", size: 4, isUint: true }],\\n\\t[PIXELFORMAT_DEPTH, { name: \\\"DEPTH\\\", size: 4 }],\\n\\t[PIXELFORMAT_DEPTH16, { name: \\\"DEPTH16\\\", size: 2 }],\\n\\t[PIXELFORMAT_DEPTHSTENCIL, { name: \\\"DEPTHSTENCIL\\\", size: 4 }],\\n\\t[PIXELFORMAT_111110F, { name: \\\"111110F\\\", size: 4 }],\\n\\t[PIXELFORMAT_SRGB8, { name: \\\"SRGB8\\\", size: 4, ldr: true, srgb: true }],\\n\\t[PIXELFORMAT_SRGBA8, { name: \\\"SRGBA8\\\", size: 4, ldr: true, srgb: true }],\\n\\t[PIXELFORMAT_BGRA8, { name: \\\"BGRA8\\\", size: 4, ldr: true }],\\n\\t[PIXELFORMAT_SBGRA8, { name: \\\"SBGRA8\\\", size: 4, ldr: true, srgb: true }],\\n\\t// compressed formats\\n\\t[PIXELFORMAT_DXT1, { name: \\\"DXT1\\\", blockSize: 8, ldr: true, srgbFormat: PIXELFORMAT_DXT1_SRGB }],\\n\\t[PIXELFORMAT_DXT3, { name: \\\"DXT3\\\", blockSize: 16, ldr: true, srgbFormat: PIXELFORMAT_DXT3_SRGBA }],\\n\\t[PIXELFORMAT_DXT5, { name: \\\"DXT5\\\", blockSize: 16, ldr: true, srgbFormat: PIXELFORMAT_DXT5_SRGBA }],\\n\\t[PIXELFORMAT_ETC1, { name: \\\"ETC1\\\", blockSize: 8, ldr: true }],\\n\\t[PIXELFORMAT_ETC2_RGB, { name: \\\"ETC2_RGB\\\", blockSize: 8, ldr: true, srgbFormat: PIXELFORMAT_ETC2_SRGB }],\\n\\t[PIXELFORMAT_ETC2_RGBA, { name: \\\"ETC2_RGBA\\\", blockSize: 16, ldr: true, srgbFormat: PIXELFORMAT_ETC2_SRGBA }],\\n\\t[PIXELFORMAT_PVRTC_2BPP_RGB_1, { name: \\\"PVRTC_2BPP_RGB_1\\\", ldr: true, blockSize: 8 }],\\n\\t[PIXELFORMAT_PVRTC_2BPP_RGBA_1, { name: \\\"PVRTC_2BPP_RGBA_1\\\", ldr: true, blockSize: 8 }],\\n\\t[PIXELFORMAT_PVRTC_4BPP_RGB_1, { name: \\\"PVRTC_4BPP_RGB_1\\\", ldr: true, blockSize: 8 }],\\n\\t[PIXELFORMAT_PVRTC_4BPP_RGBA_1, { name: \\\"PVRTC_4BPP_RGBA_1\\\", ldr: true, blockSize: 8 }],\\n\\t[PIXELFORMAT_ASTC_4x4, { name: \\\"ASTC_4x4\\\", blockSize: 16, ldr: true, srgbFormat: PIXELFORMAT_ASTC_4x4_SRGB }],\\n\\t[PIXELFORMAT_ATC_RGB, { name: \\\"ATC_RGB\\\", blockSize: 8, ldr: true }],\\n\\t[PIXELFORMAT_ATC_RGBA, { name: \\\"ATC_RGBA\\\", blockSize: 16, ldr: true }],\\n\\t[PIXELFORMAT_BC6F, { name: \\\"BC6H_RGBF\\\", blockSize: 16 }],\\n\\t[PIXELFORMAT_BC6UF, { name: \\\"BC6H_RGBUF\\\", blockSize: 16 }],\\n\\t[PIXELFORMAT_BC7, { name: \\\"BC7_RGBA\\\", blockSize: 16, ldr: true, srgbFormat: PIXELFORMAT_BC7_SRGBA }],\\n\\t// compressed sRGB formats\\n\\t[PIXELFORMAT_DXT1_SRGB, { name: \\\"DXT1_SRGB\\\", blockSize: 8, ldr: true, srgb: true }],\\n\\t[PIXELFORMAT_DXT3_SRGBA, { name: \\\"DXT3_SRGBA\\\", blockSize: 16, ldr: true, srgb: true }],\\n\\t[PIXELFORMAT_DXT5_SRGBA, { name: \\\"DXT5_SRGBA\\\", blockSize: 16, ldr: true, srgb: true }],\\n\\t[PIXELFORMAT_ETC2_SRGB, { name: \\\"ETC2_SRGB\\\", blockSize: 8, ldr: true, srgb: true }],\\n\\t[PIXELFORMAT_ETC2_SRGBA, { name: \\\"ETC2_SRGBA\\\", blockSize: 16, ldr: true, srgb: true }],\\n\\t[PIXELFORMAT_ASTC_4x4_SRGB, { name: \\\"ASTC_4x4_SRGB\\\", blockSize: 16, ldr: true, srgb: true }],\\n\\t[PIXELFORMAT_BC7_SRGBA, { name: \\\"BC7_SRGBA\\\", blockSize: 16, ldr: true, srgb: true }],\\n\\t// signed integer formats\\n\\t[PIXELFORMAT_R8I, { name: \\\"R8I\\\", size: 1, isInt: true }],\\n\\t[PIXELFORMAT_R16I, { name: \\\"R16I\\\", size: 2, isInt: true }],\\n\\t[PIXELFORMAT_R32I, { name: \\\"R32I\\\", size: 4, isInt: true }],\\n\\t[PIXELFORMAT_RG8I, { name: \\\"RG8I\\\", size: 2, isInt: true }],\\n\\t[PIXELFORMAT_RG16I, { name: \\\"RG16I\\\", size: 4, isInt: true }],\\n\\t[PIXELFORMAT_RG32I, { name: \\\"RG32I\\\", size: 8, isInt: true }],\\n\\t[PIXELFORMAT_RGBA8I, { name: \\\"RGBA8I\\\", size: 4, isInt: true }],\\n\\t[PIXELFORMAT_RGBA16I, { name: \\\"RGBA16I\\\", size: 8, isInt: true }],\\n\\t[PIXELFORMAT_RGBA32I, { name: \\\"RGBA32I\\\", size: 16, isInt: true }],\\n\\t// unsigned integer formats\\n\\t[PIXELFORMAT_R8U, { name: \\\"R8U\\\", size: 1, isUint: true }],\\n\\t[PIXELFORMAT_R16U, { name: \\\"R16U\\\", size: 2, isUint: true }],\\n\\t[PIXELFORMAT_R32U, { name: \\\"R32U\\\", size: 4, isUint: true }],\\n\\t[PIXELFORMAT_RG8U, { name: \\\"RG8U\\\", size: 2, isUint: true }],\\n\\t[PIXELFORMAT_RG16U, { name: \\\"RG16U\\\", size: 4, isUint: true }],\\n\\t[PIXELFORMAT_RG32U, { name: \\\"RG32U\\\", size: 8, isUint: true }],\\n\\t[PIXELFORMAT_RGBA8U, { name: \\\"RGBA8U\\\", size: 4, isUint: true }],\\n\\t[PIXELFORMAT_RGBA16U, { name: \\\"RGBA16U\\\", size: 8, isUint: true }],\\n\\t[PIXELFORMAT_RGBA32U, { name: \\\"RGBA32U\\\", size: 16, isUint: true }]\\n]);\\nconst isCompressedPixelFormat = (format) => {\\n\\treturn pixelFormatInfo.get(format)?.blockSize !== void 0;\\n};\\nconst isSrgbPixelFormat = (format) => {\\n\\treturn pixelFormatInfo.get(format)?.srgb === true;\\n};\\nconst isIntegerPixelFormat = (format) => {\\n\\tconst info = pixelFormatInfo.get(format);\\n\\treturn info?.isInt === true || info?.isUint === true;\\n};\\nconst GLSL_FLOAT = { sampler: \\\"sampler2D\\\", returnType: \\\"vec4\\\" };\\nconst GLSL_UINT = { sampler: \\\"usampler2D\\\", returnType: \\\"uvec4\\\" };\\nconst GLSL_INT = { sampler: \\\"isampler2D\\\", returnType: \\\"ivec4\\\" };\\nconst WGSL_FLOAT = { textureType: \\\"texture_2d<f32>\\\", returnType: \\\"vec4f\\\" };\\nconst WGSL_UINT = { textureType: \\\"texture_2d<u32>\\\", returnType: \\\"vec4u\\\" };\\nconst WGSL_INT = { textureType: \\\"texture_2d<i32>\\\", returnType: \\\"vec4i\\\" };\\nconst getGlslShaderType = (format) => {\\n\\tconst info = pixelFormatInfo.get(format);\\n\\tif (info?.isUint) return GLSL_UINT;\\n\\tif (info?.isInt) return GLSL_INT;\\n\\treturn GLSL_FLOAT;\\n};\\nconst getWgslShaderType = (format) => {\\n\\tconst info = pixelFormatInfo.get(format);\\n\\tif (info?.isUint) return WGSL_UINT;\\n\\tif (info?.isInt) return WGSL_INT;\\n\\treturn WGSL_FLOAT;\\n};\\nconst pixelFormatLinearToGamma = (format) => {\\n\\treturn pixelFormatInfo.get(format)?.srgbFormat || format;\\n};\\nconst pixelFormatGammaToLinear = (format) => {\\n\\tfor (const [key, value] of pixelFormatInfo) {\\n\\t\\tif (value.srgbFormat === format) {\\n\\t\\t\\treturn key;\\n\\t\\t}\\n\\t}\\n\\treturn format;\\n};\\nconst requiresManualGamma = (format) => {\\n\\tconst info = pixelFormatInfo.get(format);\\n\\treturn !!(info?.ldr && !info?.srgb);\\n};\\nconst getPixelFormatArrayType = (format) => {\\n\\tswitch (format) {\\n\\t\\tcase PIXELFORMAT_R32F:\\n\\t\\tcase PIXELFORMAT_RG32F:\\n\\t\\tcase PIXELFORMAT_RGB32F:\\n\\t\\tcase PIXELFORMAT_RGBA32F:\\n\\t\\t\\treturn Float32Array;\\n\\t\\tcase PIXELFORMAT_R32I:\\n\\t\\tcase PIXELFORMAT_RG32I:\\n\\t\\tcase PIXELFORMAT_RGBA32I:\\n\\t\\t\\treturn Int32Array;\\n\\t\\tcase PIXELFORMAT_R32U:\\n\\t\\tcase PIXELFORMAT_RG32U:\\n\\t\\tcase PIXELFORMAT_RGBA32U:\\n\\t\\tcase PIXELFORMAT_RGB9E5:\\n\\t\\tcase PIXELFORMAT_RGB10A2:\\n\\t\\tcase PIXELFORMAT_RGB10A2U:\\n\\t\\t\\treturn Uint32Array;\\n\\t\\tcase PIXELFORMAT_R16I:\\n\\t\\tcase PIXELFORMAT_RG16I:\\n\\t\\tcase PIXELFORMAT_RGBA16I:\\n\\t\\t\\treturn Int16Array;\\n\\t\\tcase PIXELFORMAT_R16U:\\n\\t\\tcase PIXELFORMAT_RG16U:\\n\\t\\tcase PIXELFORMAT_RGBA16U:\\n\\t\\tcase PIXELFORMAT_RGB565:\\n\\t\\tcase PIXELFORMAT_RGBA5551:\\n\\t\\tcase PIXELFORMAT_RGBA4:\\n\\t\\tcase PIXELFORMAT_R16F:\\n\\t\\tcase PIXELFORMAT_RG16F:\\n\\t\\tcase PIXELFORMAT_RGB16F:\\n\\t\\tcase PIXELFORMAT_RGBA16F:\\n\\t\\t\\treturn Uint16Array;\\n\\t\\tcase PIXELFORMAT_R8I:\\n\\t\\tcase PIXELFORMAT_RG8I:\\n\\t\\tcase PIXELFORMAT_RGBA8I:\\n\\t\\tcase PIXELFORMAT_RG8S:\\n\\t\\tcase PIXELFORMAT_RGBA8S:\\n\\t\\t\\treturn Int8Array;\\n\\t\\tdefault:\\n\\t\\t\\treturn Uint8Array;\\n\\t}\\n};\\nconst PRIMITIVE_POINTS = 0;\\nconst PRIMITIVE_LINES = 1;\\nconst PRIMITIVE_LINELOOP = 2;\\nconst PRIMITIVE_LINESTRIP = 3;\\nconst PRIMITIVE_TRIANGLES = 4;\\nconst PRIMITIVE_TRISTRIP = 5;\\nconst PRIMITIVE_TRIFAN = 6;\\nconst SEMANTIC_POSITION = \\\"POSITION\\\";\\nconst SEMANTIC_NORMAL = \\\"NORMAL\\\";\\nconst SEMANTIC_TANGENT = \\\"TANGENT\\\";\\nconst SEMANTIC_BLENDWEIGHT = \\\"BLENDWEIGHT\\\";\\nconst SEMANTIC_BLENDINDICES = \\\"BLENDINDICES\\\";\\nconst SEMANTIC_COLOR = \\\"COLOR\\\";\\nconst SEMANTIC_TEXCOORD = \\\"TEXCOORD\\\";\\nconst SEMANTIC_TEXCOORD0 = \\\"TEXCOORD0\\\";\\nconst SEMANTIC_TEXCOORD1 = \\\"TEXCOORD1\\\";\\nconst SEMANTIC_TEXCOORD2 = \\\"TEXCOORD2\\\";\\nconst SEMANTIC_TEXCOORD3 = \\\"TEXCOORD3\\\";\\nconst SEMANTIC_TEXCOORD4 = \\\"TEXCOORD4\\\";\\nconst SEMANTIC_TEXCOORD5 = \\\"TEXCOORD5\\\";\\nconst SEMANTIC_TEXCOORD6 = \\\"TEXCOORD6\\\";\\nconst SEMANTIC_TEXCOORD7 = \\\"TEXCOORD7\\\";\\nconst SEMANTIC_ATTR0 = \\\"ATTR0\\\";\\nconst SEMANTIC_ATTR1 = \\\"ATTR1\\\";\\nconst SEMANTIC_ATTR2 = \\\"ATTR2\\\";\\nconst SEMANTIC_ATTR3 = \\\"ATTR3\\\";\\nconst SEMANTIC_ATTR4 = \\\"ATTR4\\\";\\nconst SEMANTIC_ATTR5 = \\\"ATTR5\\\";\\nconst SEMANTIC_ATTR6 = \\\"ATTR6\\\";\\nconst SEMANTIC_ATTR7 = \\\"ATTR7\\\";\\nconst SEMANTIC_ATTR8 = \\\"ATTR8\\\";\\nconst SEMANTIC_ATTR9 = \\\"ATTR9\\\";\\nconst SEMANTIC_ATTR10 = \\\"ATTR10\\\";\\nconst SEMANTIC_ATTR11 = \\\"ATTR11\\\";\\nconst SEMANTIC_ATTR12 = \\\"ATTR12\\\";\\nconst SEMANTIC_ATTR13 = \\\"ATTR13\\\";\\nconst SEMANTIC_ATTR14 = \\\"ATTR14\\\";\\nconst SEMANTIC_ATTR15 = \\\"ATTR15\\\";\\nconst SHADERTAG_MATERIAL = 1;\\nconst STENCILOP_KEEP = 0;\\nconst TEXTURELOCK_NONE = 0;\\nconst TEXTURELOCK_READ = 1;\\nconst TEXTURELOCK_WRITE = 2;\\nconst TEXTURETYPE_DEFAULT = \\\"default\\\";\\nconst TEXTURETYPE_RGBM = \\\"rgbm\\\";\\nconst TEXTURETYPE_RGBE = \\\"rgbe\\\";\\nconst TEXTURETYPE_RGBP = \\\"rgbp\\\";\\nconst TEXTURETYPE_SWIZZLEGGGR = \\\"swizzleGGGR\\\";\\nconst TEXTUREDIMENSION_1D = \\\"1d\\\";\\nconst TEXTUREDIMENSION_2D = \\\"2d\\\";\\nconst TEXTUREDIMENSION_2D_ARRAY = \\\"2d-array\\\";\\nconst TEXTUREDIMENSION_CUBE = \\\"cube\\\";\\nconst TEXTUREDIMENSION_CUBE_ARRAY = \\\"cube-array\\\";\\nconst TEXTUREDIMENSION_3D = \\\"3d\\\";\\nconst SAMPLETYPE_FLOAT = 0;\\nconst SAMPLETYPE_UNFILTERABLE_FLOAT = 1;\\nconst SAMPLETYPE_DEPTH = 2;\\nconst SAMPLETYPE_INT = 3;\\nconst SAMPLETYPE_UINT = 4;\\nconst TEXTUREPROJECTION_NONE = \\\"none\\\";\\nconst TEXTUREPROJECTION_CUBE = \\\"cube\\\";\\nconst TEXTUREPROJECTION_EQUIRECT = \\\"equirect\\\";\\nconst TEXTUREPROJECTION_OCTAHEDRAL = \\\"octahedral\\\";\\nconst SHADERLANGUAGE_GLSL = \\\"glsl\\\";\\nconst SHADERLANGUAGE_WGSL = \\\"wgsl\\\";\\nconst TYPE_INT8 = 0;\\nconst TYPE_UINT8 = 1;\\nconst TYPE_INT16 = 2;\\nconst TYPE_UINT16 = 3;\\nconst TYPE_INT32 = 4;\\nconst TYPE_UINT32 = 5;\\nconst TYPE_FLOAT32 = 6;\\nconst TYPE_FLOAT16 = 7;\\nconst UNIFORMTYPE_BOOL = 0;\\nconst UNIFORMTYPE_INT = 1;\\nconst UNIFORMTYPE_FLOAT = 2;\\nconst UNIFORMTYPE_VEC2 = 3;\\nconst UNIFORMTYPE_VEC3 = 4;\\nconst UNIFORMTYPE_VEC4 = 5;\\nconst UNIFORMTYPE_IVEC2 = 6;\\nconst UNIFORMTYPE_IVEC3 = 7;\\nconst UNIFORMTYPE_IVEC4 = 8;\\nconst UNIFORMTYPE_BVEC2 = 9;\\nconst UNIFORMTYPE_BVEC3 = 10;\\nconst UNIFORMTYPE_BVEC4 = 11;\\nconst UNIFORMTYPE_MAT2 = 12;\\nconst UNIFORMTYPE_MAT3 = 13;\\nconst UNIFORMTYPE_MAT4 = 14;\\nconst UNIFORMTYPE_TEXTURE2D = 15;\\nconst UNIFORMTYPE_TEXTURECUBE = 16;\\nconst UNIFORMTYPE_FLOATARRAY = 17;\\nconst UNIFORMTYPE_TEXTURE2D_SHADOW = 18;\\nconst UNIFORMTYPE_TEXTURECUBE_SHADOW = 19;\\nconst UNIFORMTYPE_TEXTURE3D = 20;\\nconst UNIFORMTYPE_VEC2ARRAY = 21;\\nconst UNIFORMTYPE_VEC3ARRAY = 22;\\nconst UNIFORMTYPE_VEC4ARRAY = 23;\\nconst UNIFORMTYPE_MAT4ARRAY = 24;\\nconst UNIFORMTYPE_TEXTURE2D_ARRAY = 25;\\nconst UNIFORMTYPE_UINT = 26;\\nconst UNIFORMTYPE_UVEC2 = 27;\\nconst UNIFORMTYPE_UVEC3 = 28;\\nconst UNIFORMTYPE_UVEC4 = 29;\\nconst UNIFORMTYPE_INTARRAY = 30;\\nconst UNIFORMTYPE_UINTARRAY = 31;\\nconst UNIFORMTYPE_BOOLARRAY = 32;\\nconst UNIFORMTYPE_IVEC2ARRAY = 33;\\nconst UNIFORMTYPE_UVEC2ARRAY = 34;\\nconst UNIFORMTYPE_BVEC2ARRAY = 35;\\nconst UNIFORMTYPE_IVEC3ARRAY = 36;\\nconst UNIFORMTYPE_UVEC3ARRAY = 37;\\nconst UNIFORMTYPE_BVEC3ARRAY = 38;\\nconst UNIFORMTYPE_IVEC4ARRAY = 39;\\nconst UNIFORMTYPE_UVEC4ARRAY = 40;\\nconst UNIFORMTYPE_BVEC4ARRAY = 41;\\nconst UNIFORMTYPE_ITEXTURE2D = 42;\\nconst UNIFORMTYPE_UTEXTURE2D = 43;\\nconst UNIFORMTYPE_ITEXTURECUBE = 44;\\nconst UNIFORMTYPE_UTEXTURECUBE = 45;\\nconst UNIFORMTYPE_ITEXTURE3D = 46;\\nconst UNIFORMTYPE_UTEXTURE3D = 47;\\nconst UNIFORMTYPE_ITEXTURE2D_ARRAY = 48;\\nconst UNIFORMTYPE_UTEXTURE2D_ARRAY = 49;\\nconst uniformTypeToName = [\\n\\t// Uniforms\\n\\t\\\"bool\\\",\\n\\t\\\"int\\\",\\n\\t\\\"float\\\",\\n\\t\\\"vec2\\\",\\n\\t\\\"vec3\\\",\\n\\t\\\"vec4\\\",\\n\\t\\\"ivec2\\\",\\n\\t\\\"ivec3\\\",\\n\\t\\\"ivec4\\\",\\n\\t\\\"bvec2\\\",\\n\\t\\\"bvec3\\\",\\n\\t\\\"bvec4\\\",\\n\\t\\\"mat2\\\",\\n\\t\\\"mat3\\\",\\n\\t\\\"mat4\\\",\\n\\t\\\"sampler2D\\\",\\n\\t\\\"samplerCube\\\",\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_FLOATARRAY\\n\\t\\\"sampler2DShadow\\\",\\n\\t\\\"samplerCubeShadow\\\",\\n\\t\\\"sampler3D\\\",\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_VEC2ARRAY\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_VEC3ARRAY\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_VEC4ARRAY\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_MAT4ARRAY\\n\\t\\\"sampler2DArray\\\",\\n\\t\\\"uint\\\",\\n\\t\\\"uvec2\\\",\\n\\t\\\"uvec3\\\",\\n\\t\\\"uvec4\\\",\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_INTARRAY\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_UINTARRAY\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_BOOLARRAY\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_IVEC2ARRAY\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_UVEC2ARRAY\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_BVEC2ARRAY\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_IVEC3ARRAY\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_UVEC3ARRAY\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_BVEC3ARRAY\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_IVEC4ARRAY\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_UVEC4ARRAY\\n\\t\\\"\\\",\\n\\t// not directly handled: UNIFORMTYPE_BVEC4ARRAY\\n\\t\\\"isampler2D\\\",\\n\\t\\\"usampler2D\\\",\\n\\t\\\"isamplerCube\\\",\\n\\t\\\"usamplerCube\\\",\\n\\t\\\"isampler3D\\\",\\n\\t\\\"usampler3D\\\",\\n\\t\\\"isampler2DArray\\\",\\n\\t\\\"usampler2DArray\\\"\\n];\\nconst uniformTypeToNameWGSL = [\\n\\t// Uniforms\\n\\t[\\\"bool\\\"],\\n\\t// UNIFORMTYPE_BOOL\\n\\t[\\\"i32\\\"],\\n\\t// UNIFORMTYPE_INT\\n\\t[\\\"f32\\\"],\\n\\t// UNIFORMTYPE_FLOAT\\n\\t[\\\"vec2f\\\", \\\"vec2<f32>\\\"],\\n\\t// UNIFORMTYPE_VEC2\\n\\t[\\\"vec3f\\\", \\\"vec3<f32>\\\"],\\n\\t// UNIFORMTYPE_VEC3\\n\\t[\\\"vec4f\\\", \\\"vec4<f32>\\\"],\\n\\t// UNIFORMTYPE_VEC4\\n\\t[\\\"vec2i\\\", \\\"vec2<i32>\\\"],\\n\\t// UNIFORMTYPE_IVEC2\\n\\t[\\\"vec3i\\\", \\\"vec3<i32>\\\"],\\n\\t// UNIFORMTYPE_IVEC3\\n\\t[\\\"vec4i\\\", \\\"vec4<i32>\\\"],\\n\\t// UNIFORMTYPE_IVEC4\\n\\t[\\\"vec2<bool>\\\"],\\n\\t// UNIFORMTYPE_BVEC2\\n\\t[\\\"vec3<bool>\\\"],\\n\\t// UNIFORMTYPE_BVEC3\\n\\t[\\\"vec4<bool>\\\"],\\n\\t// UNIFORMTYPE_BVEC4\\n\\t[\\\"mat2x2f\\\", \\\"mat2x2<f32>\\\"],\\n\\t// UNIFORMTYPE_MAT2\\n\\t[\\\"mat3x3f\\\", \\\"mat3x3<f32>\\\"],\\n\\t// UNIFORMTYPE_MAT3\\n\\t[\\\"mat4x4f\\\", \\\"mat4x4<f32>\\\"],\\n\\t// UNIFORMTYPE_MAT4\\n\\t[\\\"texture_2d<f32>\\\"],\\n\\t// UNIFORMTYPE_TEXTURE2D\\n\\t[\\\"texture_cube<f32>\\\"],\\n\\t// UNIFORMTYPE_TEXTURECUBE\\n\\t[\\\"array<f32>\\\"],\\n\\t// UNIFORMTYPE_FLOATARRAY\\n\\t[\\\"texture_depth_2d\\\"],\\n\\t// UNIFORMTYPE_TEXTURE2D_SHADOW\\n\\t[\\\"texture_depth_cube\\\"],\\n\\t// UNIFORMTYPE_TEXTURECUBE_SHADOW\\n\\t[\\\"texture_3d<f32>\\\"],\\n\\t// UNIFORMTYPE_TEXTURE3D\\n\\t[\\\"array<vec2<f32>>\\\"],\\n\\t// UNIFORMTYPE_VEC2ARRAY\\n\\t[\\\"array<vec3<f32>>\\\"],\\n\\t// UNIFORMTYPE_VEC3ARRAY\\n\\t[\\\"array<vec4<f32>>\\\"],\\n\\t// UNIFORMTYPE_VEC4ARRAY\\n\\t[\\\"array<mat4x4<f32>>\\\"],\\n\\t// UNIFORMTYPE_MAT4ARRAY\\n\\t[\\\"texture_2d_array<f32>\\\"],\\n\\t// UNIFORMTYPE_TEXTURE2D_ARRAY\\n\\t// Unsigned integer uniforms\\n\\t[\\\"u32\\\"],\\n\\t// UNIFORMTYPE_UINT\\n\\t[\\\"vec2u\\\", \\\"vec2<u32>\\\"],\\n\\t// UNIFORMTYPE_UVEC2\\n\\t[\\\"vec3u\\\", \\\"vec3<u32>\\\"],\\n\\t// UNIFORMTYPE_UVEC3\\n\\t[\\\"vec4u\\\", \\\"vec4<u32>\\\"],\\n\\t// UNIFORMTYPE_UVEC4\\n\\t// Integer array uniforms\\n\\t[\\\"array<i32>\\\"],\\n\\t// UNIFORMTYPE_INTARRAY\\n\\t[\\\"array<u32>\\\"],\\n\\t// UNIFORMTYPE_UINTARRAY\\n\\t[\\\"array<bool>\\\"],\\n\\t// UNIFORMTYPE_BOOLARRAY\\n\\t[\\\"array<vec2i>\\\", \\\"array<vec2<i32>>\\\"],\\n\\t// UNIFORMTYPE_IVEC2ARRAY\\n\\t[\\\"array<vec2u>\\\", \\\"array<vec2<u32>>\\\"],\\n\\t// UNIFORMTYPE_UVEC2ARRAY\\n\\t[\\\"array<vec2b>\\\", \\\"array<vec2<bool>>\\\"],\\n\\t// UNIFORMTYPE_BVEC2ARRAY\\n\\t[\\\"array<vec3i>\\\", \\\"array<vec3<i32>>\\\"],\\n\\t// UNIFORMTYPE_IVEC3ARRAY\\n\\t[\\\"array<vec3u>\\\", \\\"array<vec3<u32>>\\\"],\\n\\t// UNIFORMTYPE_UVEC3ARRAY\\n\\t[\\\"array<vec3b>\\\", \\\"array<vec3<bool>>\\\"],\\n\\t// UNIFORMTYPE_BVEC3ARRAY\\n\\t[\\\"array<vec4i>\\\", \\\"array<vec4<i32>>\\\"],\\n\\t// UNIFORMTYPE_IVEC4ARRAY\\n\\t[\\\"array<vec4u>\\\", \\\"array<vec4<u32>>\\\"],\\n\\t// UNIFORMTYPE_UVEC4ARRAY\\n\\t[\\\"array<vec4b>\\\", \\\"array<vec4<bool>>\\\"],\\n\\t// UNIFORMTYPE_BVEC4ARRAY\\n\\t// Integer texture types\\n\\t[\\\"texture_2d<i32>\\\"],\\n\\t// UNIFORMTYPE_ITEXTURE2D\\n\\t[\\\"texture_2d<u32>\\\"],\\n\\t// UNIFORMTYPE_UTEXTURE2D\\n\\t[\\\"texture_cube<i32>\\\"],\\n\\t// UNIFORMTYPE_ITEXTURECUBE\\n\\t[\\\"texture_cube<u32>\\\"],\\n\\t// UNIFORMTYPE_UTEXTURECUBE\\n\\t[\\\"texture_3d<i32>\\\"],\\n\\t// UNIFORMTYPE_ITEXTURE3D\\n\\t[\\\"texture_3d<u32>\\\"],\\n\\t// UNIFORMTYPE_UTEXTURE3D\\n\\t[\\\"texture_2d_array<i32>\\\"],\\n\\t// UNIFORMTYPE_ITEXTURE2D_ARRAY\\n\\t[\\\"texture_2d_array<u32>\\\"]\\n\\t// UNIFORMTYPE_UTEXTURE2D_ARRAY\\n];\\nconst uniformTypeToNameMapWGSL = /* @__PURE__ */ new Map();\\nuniformTypeToNameWGSL.forEach((names, index) => {\\n\\tnames.forEach((name) => uniformTypeToNameMapWGSL.set(name, index));\\n});\\nconst DEVICETYPE_WEBGL2 = \\\"webgl2\\\";\\nconst DEVICETYPE_WEBGPU = \\\"webgpu\\\";\\nconst DEVICETYPE_WEBGPU_BARE = \\\"webgpu:bare\\\";\\nconst DEVICETYPE_NULL = \\\"null\\\";\\nconst SHADERSTAGE_VERTEX = 1;\\nconst SHADERSTAGE_FRAGMENT = 2;\\nconst SHADERSTAGE_COMPUTE = 4;\\nconst DISPLAYFORMAT_LDR = \\\"ldr\\\";\\nconst DISPLAYFORMAT_LDR_SRGB = \\\"ldr_srgb\\\";\\nconst DISPLAYFORMAT_HDR = \\\"hdr\\\";\\nconst TEXPROPERTY_MIN_FILTER = 1;\\nconst TEXPROPERTY_MAG_FILTER = 2;\\nconst TEXPROPERTY_ADDRESS_U = 4;\\nconst TEXPROPERTY_ADDRESS_V = 8;\\nconst TEXPROPERTY_ADDRESS_W = 16;\\nconst TEXPROPERTY_COMPARE_ON_READ = 32;\\nconst TEXPROPERTY_COMPARE_FUNC = 64;\\nconst TEXPROPERTY_ANISOTROPY = 128;\\nconst TEXPROPERTY_ALL = 255;\\nconst BINDGROUP_VIEW = 0;\\nconst BINDGROUP_MESH = 1;\\nconst BINDGROUP_MESH_UB = 2;\\nconst bindGroupNames = [\\\"view\\\", \\\"mesh\\\", \\\"mesh_ub\\\"];\\nconst UNIFORM_BUFFER_DEFAULT_SLOT_NAME = \\\"default\\\";\\nconst UNUSED_UNIFORM_NAME = \\\"_unused_float_uniform\\\";\\nconst typedArrayTypes = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Uint16Array];\\nconst typedArrayTypesByteSize = [1, 1, 2, 2, 4, 4, 4, 2];\\nconst typedArrayIndexFormats = [Uint8Array, Uint16Array, Uint32Array];\\nconst typedArrayIndexFormatsByteSize = [1, 2, 4];\\nconst primitiveGlslToWgslTypeMap = /* @__PURE__ */ new Map([\\n\\t// floating-point\\n\\t[\\\"float\\\", \\\"f32\\\"],\\n\\t[\\\"vec2\\\", \\\"vec2f\\\"],\\n\\t[\\\"vec3\\\", \\\"vec3f\\\"],\\n\\t[\\\"vec4\\\", \\\"vec4f\\\"],\\n\\t// signed integer\\n\\t[\\\"int\\\", \\\"i32\\\"],\\n\\t[\\\"ivec2\\\", \\\"vec2i\\\"],\\n\\t[\\\"ivec3\\\", \\\"vec3i\\\"],\\n\\t[\\\"ivec4\\\", \\\"vec4i\\\"],\\n\\t// unsigned integer\\n\\t[\\\"uint\\\", \\\"u32\\\"],\\n\\t[\\\"uvec2\\\", \\\"vec2u\\\"],\\n\\t[\\\"uvec3\\\", \\\"vec3u\\\"],\\n\\t[\\\"uvec4\\\", \\\"vec4u\\\"]\\n]);\\nconst semanticToLocation = {};\\nsemanticToLocation[SEMANTIC_POSITION] = 0;\\nsemanticToLocation[SEMANTIC_NORMAL] = 1;\\nsemanticToLocation[SEMANTIC_BLENDWEIGHT] = 2;\\nsemanticToLocation[SEMANTIC_BLENDINDICES] = 3;\\nsemanticToLocation[SEMANTIC_COLOR] = 4;\\nsemanticToLocation[SEMANTIC_TEXCOORD0] = 5;\\nsemanticToLocation[SEMANTIC_TEXCOORD1] = 6;\\nsemanticToLocation[SEMANTIC_TEXCOORD2] = 7;\\nsemanticToLocation[SEMANTIC_TEXCOORD3] = 8;\\nsemanticToLocation[SEMANTIC_TEXCOORD4] = 9;\\nsemanticToLocation[SEMANTIC_TEXCOORD5] = 10;\\nsemanticToLocation[SEMANTIC_TEXCOORD6] = 11;\\nsemanticToLocation[SEMANTIC_TEXCOORD7] = 12;\\nsemanticToLocation[SEMANTIC_TANGENT] = 13;\\nsemanticToLocation[SEMANTIC_ATTR0] = 0;\\nsemanticToLocation[SEMANTIC_ATTR1] = 1;\\nsemanticToLocation[SEMANTIC_ATTR2] = 2;\\nsemanticToLocation[SEMANTIC_ATTR3] = 3;\\nsemanticToLocation[SEMANTIC_ATTR4] = 4;\\nsemanticToLocation[SEMANTIC_ATTR5] = 5;\\nsemanticToLocation[SEMANTIC_ATTR6] = 6;\\nsemanticToLocation[SEMANTIC_ATTR7] = 7;\\nsemanticToLocation[SEMANTIC_ATTR8] = 8;\\nsemanticToLocation[SEMANTIC_ATTR9] = 9;\\nsemanticToLocation[SEMANTIC_ATTR10] = 10;\\nsemanticToLocation[SEMANTIC_ATTR11] = 11;\\nsemanticToLocation[SEMANTIC_ATTR12] = 12;\\nsemanticToLocation[SEMANTIC_ATTR13] = 13;\\nsemanticToLocation[SEMANTIC_ATTR14] = 14;\\nsemanticToLocation[SEMANTIC_ATTR15] = 15;\\n\\nlet id$c = 0;\\nclass BindBaseFormat {\\n\\tslot = -1;\\n\\tscopeId = null;\\n\\tconstructor(name, visibility) {\\n\\t\\tthis.name = name;\\n\\t\\tthis.visibility = visibility;\\n\\t}\\n}\\nclass BindUniformBufferFormat extends BindBaseFormat {\\n}\\nclass BindStorageBufferFormat extends BindBaseFormat {\\n\\tformat = \\\"\\\";\\n\\tconstructor(name, visibility, readOnly = false) {\\n\\t\\tsuper(name, visibility);\\n\\t\\tthis.readOnly = readOnly;\\n\\t}\\n}\\nclass BindTextureFormat extends BindBaseFormat {\\n\\tconstructor(name, visibility, textureDimension = TEXTUREDIMENSION_2D, sampleType = SAMPLETYPE_FLOAT, hasSampler = true, samplerName = null) {\\n\\t\\tsuper(name, visibility);\\n\\t\\tthis.textureDimension = textureDimension;\\n\\t\\tthis.sampleType = sampleType;\\n\\t\\tthis.hasSampler = hasSampler;\\n\\t\\tthis.samplerName = samplerName ?? `${name}_sampler`;\\n\\t}\\n}\\nclass BindStorageTextureFormat extends BindBaseFormat {\\n\\tconstructor(name, format = PIXELFORMAT_RGBA8, textureDimension = TEXTUREDIMENSION_2D, write = true, read = false) {\\n\\t\\tsuper(name, SHADERSTAGE_COMPUTE);\\n\\t\\tthis.format = format;\\n\\t\\tthis.textureDimension = textureDimension;\\n\\t\\tthis.write = write;\\n\\t\\tthis.read = read;\\n\\t}\\n}\\nclass BindGroupFormat {\\n\\tuniformBufferFormats = [];\\n\\ttextureFormats = [];\\n\\tstorageTextureFormats = [];\\n\\tstorageBufferFormats = [];\\n\\tconstructor(graphicsDevice, formats) {\\n\\t\\tthis.id = id$c++;\\n\\t\\tlet slot = 0;\\n\\t\\tformats.forEach((format) => {\\n\\t\\t\\tformat.slot = slot++;\\n\\t\\t\\tif (format instanceof BindTextureFormat && format.hasSampler) {\\n\\t\\t\\t\\tslot++;\\n\\t\\t\\t}\\n\\t\\t\\tif (format instanceof BindUniformBufferFormat) {\\n\\t\\t\\t\\tthis.uniformBufferFormats.push(format);\\n\\t\\t\\t} else if (format instanceof BindTextureFormat) {\\n\\t\\t\\t\\tthis.textureFormats.push(format);\\n\\t\\t\\t} else if (format instanceof BindStorageTextureFormat) {\\n\\t\\t\\t\\tthis.storageTextureFormats.push(format);\\n\\t\\t\\t} else if (format instanceof BindStorageBufferFormat) {\\n\\t\\t\\t\\tthis.storageBufferFormats.push(format);\\n\\t\\t\\t} else ;\\n\\t\\t});\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tconst scope = graphicsDevice.scope;\\n\\t\\tthis.bufferFormatsMap = /* @__PURE__ */ new Map();\\n\\t\\tthis.uniformBufferFormats.forEach((bf, i) => this.bufferFormatsMap.set(bf.name, i));\\n\\t\\tthis.textureFormatsMap = /* @__PURE__ */ new Map();\\n\\t\\tthis.textureFormats.forEach((tf, i) => {\\n\\t\\t\\tthis.textureFormatsMap.set(tf.name, i);\\n\\t\\t\\ttf.scopeId = scope.resolve(tf.name);\\n\\t\\t});\\n\\t\\tthis.storageTextureFormatsMap = /* @__PURE__ */ new Map();\\n\\t\\tthis.storageTextureFormats.forEach((tf, i) => {\\n\\t\\t\\tthis.storageTextureFormatsMap.set(tf.name, i);\\n\\t\\t\\ttf.scopeId = scope.resolve(tf.name);\\n\\t\\t});\\n\\t\\tthis.storageBufferFormatsMap = /* @__PURE__ */ new Map();\\n\\t\\tthis.storageBufferFormats.forEach((bf, i) => {\\n\\t\\t\\tthis.storageBufferFormatsMap.set(bf.name, i);\\n\\t\\t\\tbf.scopeId = scope.resolve(bf.name);\\n\\t\\t});\\n\\t\\tthis.impl = graphicsDevice.createBindGroupFormatImpl(this);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.impl.destroy();\\n\\t}\\n\\tgetTexture(name) {\\n\\t\\tconst index = this.textureFormatsMap.get(name);\\n\\t\\tif (index !== void 0) {\\n\\t\\t\\treturn this.textureFormats[index];\\n\\t\\t}\\n\\t\\treturn null;\\n\\t}\\n\\tgetStorageTexture(name) {\\n\\t\\tconst index = this.storageTextureFormatsMap.get(name);\\n\\t\\tif (index !== void 0) {\\n\\t\\t\\treturn this.storageTextureFormats[index];\\n\\t\\t}\\n\\t\\treturn null;\\n\\t}\\n\\tloseContext() {\\n\\t}\\n}\\n\\nclass DeviceCache {\\n\\t_cache = /* @__PURE__ */ new Map();\\n\\tget(device, onCreate) {\\n\\t\\tif (!this._cache.has(device)) {\\n\\t\\t\\tthis._cache.set(device, onCreate());\\n\\t\\t\\tdevice.on(\\\"destroy\\\", () => {\\n\\t\\t\\t\\tthis.remove(device);\\n\\t\\t\\t});\\n\\t\\t\\tdevice.on(\\\"devicelost\\\", () => {\\n\\t\\t\\t\\tthis._cache.get(device)?.loseContext?.(device);\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\treturn this._cache.get(device);\\n\\t}\\n\\tremove(device) {\\n\\t\\tthis._cache.get(device)?.destroy?.(device);\\n\\t\\tthis._cache.delete(device);\\n\\t}\\n}\\n\\nclass TextureUtils {\\n\\tstatic calcLevelDimension(dimension, mipLevel) {\\n\\t\\treturn Math.max(dimension >> mipLevel, 1);\\n\\t}\\n\\tstatic calcMipLevelsCount(width, height, depth = 1) {\\n\\t\\treturn 1 + Math.floor(Math.log2(Math.max(width, height, depth)));\\n\\t}\\n\\tstatic calcLevelGpuSize(width, height, depth, format) {\\n\\t\\tconst formatInfo = pixelFormatInfo.get(format);\\n\\t\\tconst pixelSize = pixelFormatInfo.get(format)?.size ?? 0;\\n\\t\\tif (pixelSize > 0) {\\n\\t\\t\\treturn width * height * depth * pixelSize;\\n\\t\\t}\\n\\t\\tconst blockSize = formatInfo.blockSize ?? 0;\\n\\t\\tlet blockWidth = Math.floor((width + 3) / 4);\\n\\t\\tconst blockHeight = Math.floor((height + 3) / 4);\\n\\t\\tconst blockDepth = Math.floor((depth + 3) / 4);\\n\\t\\tif (format === PIXELFORMAT_PVRTC_2BPP_RGB_1 || format === PIXELFORMAT_PVRTC_2BPP_RGBA_1) {\\n\\t\\t\\tblockWidth = Math.max(Math.floor(blockWidth / 2), 1);\\n\\t\\t}\\n\\t\\treturn blockWidth * blockHeight * blockDepth * blockSize;\\n\\t}\\n\\tstatic calcGpuSize(width, height, depth, format, mipmaps, cubemap) {\\n\\t\\tlet result = 0;\\n\\t\\twhile (1) {\\n\\t\\t\\tresult += TextureUtils.calcLevelGpuSize(width, height, depth, format);\\n\\t\\t\\tif (!mipmaps || width === 1 && height === 1 && depth === 1) {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\twidth = Math.max(width >> 1, 1);\\n\\t\\t\\theight = Math.max(height >> 1, 1);\\n\\t\\t\\tdepth = Math.max(depth >> 1, 1);\\n\\t\\t}\\n\\t\\treturn result * (cubemap ? 6 : 1);\\n\\t}\\n\\tstatic calcTextureSize(count, result, widthMultiple = 1) {\\n\\t\\tlet width = Math.ceil(Math.sqrt(count));\\n\\t\\tif (widthMultiple > 1) {\\n\\t\\t\\twidth = math.roundUp(width, widthMultiple);\\n\\t\\t}\\n\\t\\treturn result.set(width, Math.ceil(count / width));\\n\\t}\\n}\\n\\nclass StringIds {\\n\\tmap = /* @__PURE__ */ new Map();\\n\\tid = 0;\\n\\tget(name) {\\n\\t\\tlet value = this.map.get(name);\\n\\t\\tif (value === void 0) {\\n\\t\\t\\tvalue = this.id++;\\n\\t\\t\\tthis.map.set(name, value);\\n\\t\\t}\\n\\t\\treturn value;\\n\\t}\\n}\\n\\nconst stringIds$5 = new StringIds();\\nclass TextureView {\\n\\ttexture;\\n\\tbaseMipLevel;\\n\\tmipLevelCount;\\n\\tbaseArrayLayer;\\n\\tarrayLayerCount;\\n\\tkey;\\n\\tconstructor(texture, baseMipLevel = 0, mipLevelCount = 1, baseArrayLayer = 0, arrayLayerCount = 1) {\\n\\t\\tthis.texture = texture;\\n\\t\\tthis.baseMipLevel = baseMipLevel;\\n\\t\\tthis.mipLevelCount = mipLevelCount;\\n\\t\\tthis.baseArrayLayer = baseArrayLayer;\\n\\t\\tthis.arrayLayerCount = arrayLayerCount;\\n\\t\\tthis.key = stringIds$5.get(`${baseMipLevel}:${mipLevelCount}:${baseArrayLayer}:${arrayLayerCount}`);\\n\\t}\\n}\\n\\nlet id$b = 0;\\nclass Texture {\\n\\tstatic createDataTexture2D(graphicsDevice, name, width, height, format, levels) {\\n\\t\\treturn new Texture(graphicsDevice, {\\n\\t\\t\\tname,\\n\\t\\t\\twidth,\\n\\t\\t\\theight,\\n\\t\\t\\tformat,\\n\\t\\t\\tmipmaps: false,\\n\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\tlevels\\n\\t\\t});\\n\\t}\\n\\tname;\\n\\t_gpuSize = 0;\\n\\treleaseSourceAfterUpload = false;\\n\\tid = id$b++;\\n\\t_invalid = false;\\n\\t_lockedLevel = -1;\\n\\t_lockedMode = TEXTURELOCK_NONE;\\n\\trenderVersionDirty = 0;\\n\\t_storage = false;\\n\\t_numLevels = 0;\\n\\t_numLevelsRequested;\\n\\tconstructor(graphicsDevice, options = {}) {\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tthis.name = options.name ?? \\\"\\\";\\n\\t\\tthis._width = Math.floor(options.width ?? 4);\\n\\t\\tthis._height = Math.floor(options.height ?? 4);\\n\\t\\tthis._format = options.format ?? PIXELFORMAT_RGBA8;\\n\\t\\tthis._compressed = isCompressedPixelFormat(this._format);\\n\\t\\tthis._integerFormat = isIntegerPixelFormat(this._format);\\n\\t\\tif (this._integerFormat) {\\n\\t\\t\\toptions.minFilter = FILTER_NEAREST;\\n\\t\\t\\toptions.magFilter = FILTER_NEAREST;\\n\\t\\t}\\n\\t\\tthis._volume = options.volume ?? false;\\n\\t\\tthis._depth = Math.floor(options.depth ?? 1);\\n\\t\\tthis._arrayLength = Math.floor(options.arrayLength ?? 0);\\n\\t\\tthis._storage = options.storage ?? false;\\n\\t\\tthis._cubemap = options.cubemap ?? false;\\n\\t\\tthis._flipY = options.flipY ?? false;\\n\\t\\tthis._premultiplyAlpha = options.premultiplyAlpha ?? false;\\n\\t\\tthis._mipmaps = options.mipmaps ?? true;\\n\\t\\tthis._numLevelsRequested = options.numLevels;\\n\\t\\tif (options.numLevels !== void 0) {\\n\\t\\t\\tthis._numLevels = options.numLevels;\\n\\t\\t}\\n\\t\\tthis._updateNumLevels();\\n\\t\\tthis._minFilter = options.minFilter ?? FILTER_LINEAR_MIPMAP_LINEAR;\\n\\t\\tthis._magFilter = options.magFilter ?? FILTER_LINEAR;\\n\\t\\tthis._anisotropy = options.anisotropy ?? 1;\\n\\t\\tthis._addressU = options.addressU ?? ADDRESS_REPEAT;\\n\\t\\tthis._addressV = options.addressV ?? ADDRESS_REPEAT;\\n\\t\\tthis._addressW = options.addressW ?? ADDRESS_REPEAT;\\n\\t\\tthis._compareOnRead = options.compareOnRead ?? false;\\n\\t\\tthis._compareFunc = options.compareFunc ?? FUNC_LESS;\\n\\t\\tthis._type = options.type ?? TEXTURETYPE_DEFAULT;\\n\\t\\tthis.projection = TEXTUREPROJECTION_NONE;\\n\\t\\tif (this._cubemap) {\\n\\t\\t\\tthis.projection = TEXTUREPROJECTION_CUBE;\\n\\t\\t} else if (options.projection && options.projection !== TEXTUREPROJECTION_CUBE) {\\n\\t\\t\\tthis.projection = options.projection;\\n\\t\\t}\\n\\t\\tthis._levels = options.levels;\\n\\t\\tconst upload = !!options.levels;\\n\\t\\tif (!this._levels) {\\n\\t\\t\\tthis._clearLevels();\\n\\t\\t}\\n\\t\\tthis.recreateImpl(upload);\\n\\t}\\n\\tdestroy() {\\n\\t\\tconst device = this.device;\\n\\t\\tif (device) {\\n\\t\\t\\tdevice.onTextureDestroyed(this);\\n\\t\\t\\tthis.impl.destroy(device);\\n\\t\\t\\tthis.adjustVramSizeTracking(device._vram, -this._gpuSize);\\n\\t\\t\\tif (this.releaseSourceAfterUpload) {\\n\\t\\t\\t\\tthis.releaseImageSources();\\n\\t\\t\\t}\\n\\t\\t\\tthis._levels = null;\\n\\t\\t\\tthis.device = null;\\n\\t\\t}\\n\\t}\\n\\treleaseImageSources() {\\n\\t\\tthis.releaseSourceAfterUpload = false;\\n\\t\\tif (typeof ImageBitmap === \\\"undefined\\\" || !this._levels) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < this._levels.length; i++) {\\n\\t\\t\\tconst level = this._levels[i];\\n\\t\\t\\tif (level instanceof ImageBitmap) {\\n\\t\\t\\t\\tlevel.close();\\n\\t\\t\\t\\tthis._levels[i] = null;\\n\\t\\t\\t} else if (Array.isArray(level)) {\\n\\t\\t\\t\\tfor (let j = 0; j < level.length; j++) {\\n\\t\\t\\t\\t\\tif (level[j] instanceof ImageBitmap) {\\n\\t\\t\\t\\t\\t\\tlevel[j].close();\\n\\t\\t\\t\\t\\t\\tlevel[j] = null;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tsetReleaseSourceAfterUpload() {\\n\\t\\tthis.releaseSourceAfterUpload = true;\\n\\t\\tif (!this._needsUpload && !this._needsMipmapsUpload) {\\n\\t\\t\\tthis.releaseImageSources();\\n\\t\\t}\\n\\t}\\n\\trecreateImpl(upload = true) {\\n\\t\\tconst { device } = this;\\n\\t\\tthis.impl?.destroy(device);\\n\\t\\tthis.impl = null;\\n\\t\\tthis.impl = device.createTextureImpl(this);\\n\\t\\tthis.dirtyAll();\\n\\t\\tif (upload) {\\n\\t\\t\\tthis.upload();\\n\\t\\t}\\n\\t}\\n\\t_clearLevels() {\\n\\t\\tthis._levels = this._cubemap ? [[null, null, null, null, null, null]] : [null];\\n\\t}\\n\\tresize(width, height, depth = 1) {\\n\\t\\tif (this.width !== width || this.height !== height || this.depth !== depth) {\\n\\t\\t\\tconst device = this.device;\\n\\t\\t\\tthis.adjustVramSizeTracking(device._vram, -this._gpuSize);\\n\\t\\t\\tthis._gpuSize = 0;\\n\\t\\t\\tthis.impl.destroy(device);\\n\\t\\t\\tthis._clearLevels();\\n\\t\\t\\tthis._width = Math.floor(width);\\n\\t\\t\\tthis._height = Math.floor(height);\\n\\t\\t\\tthis._depth = Math.floor(depth);\\n\\t\\t\\tthis._updateNumLevels();\\n\\t\\t\\tthis.impl = device.createTextureImpl(this);\\n\\t\\t\\tthis.dirtyAll();\\n\\t\\t}\\n\\t}\\n\\tloseContext() {\\n\\t\\tthis.impl.loseContext();\\n\\t\\tthis.dirtyAll();\\n\\t}\\n\\tadjustVramSizeTracking(vram, size) {\\n\\t\\tvram.tex += size;\\n\\t}\\n\\tpropertyChanged(flag) {\\n\\t\\tthis.impl.propertyChanged(flag);\\n\\t\\tthis.renderVersionDirty = this.device.renderVersion;\\n\\t}\\n\\t_updateNumLevels() {\\n\\t\\tconst maxLevels = this.mipmaps ? TextureUtils.calcMipLevelsCount(this.width, this.height) : 1;\\n\\t\\tconst requestedLevels = this._numLevelsRequested;\\n\\t\\tthis._numLevels = Math.min(requestedLevels ?? maxLevels, maxLevels);\\n\\t\\tthis._mipmaps = this._numLevels > 1;\\n\\t}\\n\\tget lockedMode() {\\n\\t\\treturn this._lockedMode;\\n\\t}\\n\\tset minFilter(v) {\\n\\t\\tif (this._minFilter !== v) {\\n\\t\\t\\tif (isIntegerPixelFormat(this._format)) ; else {\\n\\t\\t\\t\\tthis._minFilter = v;\\n\\t\\t\\t\\tthis.propertyChanged(TEXPROPERTY_MIN_FILTER);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget minFilter() {\\n\\t\\treturn this._minFilter;\\n\\t}\\n\\tset magFilter(v) {\\n\\t\\tif (this._magFilter !== v) {\\n\\t\\t\\tif (isIntegerPixelFormat(this._format)) ; else {\\n\\t\\t\\t\\tthis._magFilter = v;\\n\\t\\t\\t\\tthis.propertyChanged(TEXPROPERTY_MAG_FILTER);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget magFilter() {\\n\\t\\treturn this._magFilter;\\n\\t}\\n\\tset addressU(v) {\\n\\t\\tif (this._addressU !== v) {\\n\\t\\t\\tthis._addressU = v;\\n\\t\\t\\tthis.propertyChanged(TEXPROPERTY_ADDRESS_U);\\n\\t\\t}\\n\\t}\\n\\tget addressU() {\\n\\t\\treturn this._addressU;\\n\\t}\\n\\tset addressV(v) {\\n\\t\\tif (this._addressV !== v) {\\n\\t\\t\\tthis._addressV = v;\\n\\t\\t\\tthis.propertyChanged(TEXPROPERTY_ADDRESS_V);\\n\\t\\t}\\n\\t}\\n\\tget addressV() {\\n\\t\\treturn this._addressV;\\n\\t}\\n\\tset addressW(addressW) {\\n\\t\\tif (!this._volume) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (addressW !== this._addressW) {\\n\\t\\t\\tthis._addressW = addressW;\\n\\t\\t\\tthis.propertyChanged(TEXPROPERTY_ADDRESS_W);\\n\\t\\t}\\n\\t}\\n\\tget addressW() {\\n\\t\\treturn this._addressW;\\n\\t}\\n\\tset compareOnRead(v) {\\n\\t\\tif (this._compareOnRead !== v) {\\n\\t\\t\\tthis._compareOnRead = v;\\n\\t\\t\\tthis.propertyChanged(TEXPROPERTY_COMPARE_ON_READ);\\n\\t\\t}\\n\\t}\\n\\tget compareOnRead() {\\n\\t\\treturn this._compareOnRead;\\n\\t}\\n\\tset compareFunc(v) {\\n\\t\\tif (this._compareFunc !== v) {\\n\\t\\t\\tthis._compareFunc = v;\\n\\t\\t\\tthis.propertyChanged(TEXPROPERTY_COMPARE_FUNC);\\n\\t\\t}\\n\\t}\\n\\tget compareFunc() {\\n\\t\\treturn this._compareFunc;\\n\\t}\\n\\tset anisotropy(v) {\\n\\t\\tif (this._anisotropy !== v) {\\n\\t\\t\\tthis._anisotropy = v;\\n\\t\\t\\tthis.propertyChanged(TEXPROPERTY_ANISOTROPY);\\n\\t\\t}\\n\\t}\\n\\tget anisotropy() {\\n\\t\\treturn this._anisotropy;\\n\\t}\\n\\tset mipmaps(v) {\\n\\t\\tif (this._mipmaps !== v) {\\n\\t\\t\\tif (this.device.isWebGPU) ; else if (isIntegerPixelFormat(this._format)) ; else {\\n\\t\\t\\t\\tconst oldMipmaps = this._mipmaps;\\n\\t\\t\\t\\tconst oldNumLevels = this._numLevels;\\n\\t\\t\\t\\tthis._mipmaps = v;\\n\\t\\t\\t\\tthis._updateNumLevels();\\n\\t\\t\\t\\tif (this.array && this._numLevels !== oldNumLevels) {\\n\\t\\t\\t\\t\\tthis.recreateImpl();\\n\\t\\t\\t\\t} else if (this._mipmaps !== oldMipmaps) {\\n\\t\\t\\t\\t\\tthis.propertyChanged(TEXPROPERTY_MIN_FILTER);\\n\\t\\t\\t\\t\\tif (this._mipmaps) {\\n\\t\\t\\t\\t\\t\\tthis._needsMipmapsUpload = true;\\n\\t\\t\\t\\t\\t\\tthis.device?.texturesToUpload?.add(this);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._needsMipmapsUpload = false;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget mipmaps() {\\n\\t\\treturn this._mipmaps;\\n\\t}\\n\\tget numLevels() {\\n\\t\\treturn this._numLevels;\\n\\t}\\n\\tget storage() {\\n\\t\\treturn this._storage;\\n\\t}\\n\\tget width() {\\n\\t\\treturn this._width;\\n\\t}\\n\\tget height() {\\n\\t\\treturn this._height;\\n\\t}\\n\\tget depth() {\\n\\t\\treturn this._depth;\\n\\t}\\n\\tget format() {\\n\\t\\treturn this._format;\\n\\t}\\n\\tget cubemap() {\\n\\t\\treturn this._cubemap;\\n\\t}\\n\\tget gpuSize() {\\n\\t\\tconst mips = this.pot && this._mipmaps && !(this._compressed && this._levels.length === 1);\\n\\t\\treturn TextureUtils.calcGpuSize(this._width, this._height, this._depth, this._format, mips, this._cubemap);\\n\\t}\\n\\tget array() {\\n\\t\\treturn this._arrayLength > 0;\\n\\t}\\n\\tget arrayLength() {\\n\\t\\treturn this._arrayLength;\\n\\t}\\n\\tget volume() {\\n\\t\\treturn this._volume;\\n\\t}\\n\\tset type(value) {\\n\\t\\tif (this._type !== value) {\\n\\t\\t\\tthis._type = value;\\n\\t\\t\\tthis.device._shadersDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget type() {\\n\\t\\treturn this._type;\\n\\t}\\n\\tset srgb(value) {\\n\\t\\tconst currentSrgb = isSrgbPixelFormat(this.format);\\n\\t\\tif (value !== currentSrgb) {\\n\\t\\t\\tif (value) {\\n\\t\\t\\t\\tconst srgbFormat = pixelFormatLinearToGamma(this.format);\\n\\t\\t\\t\\tif (this._format !== srgbFormat) {\\n\\t\\t\\t\\t\\tthis._format = srgbFormat;\\n\\t\\t\\t\\t\\tthis.recreateImpl();\\n\\t\\t\\t\\t\\tthis.device._shadersDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconst linearFormat = pixelFormatGammaToLinear(this.format);\\n\\t\\t\\t\\tif (this._format !== linearFormat) {\\n\\t\\t\\t\\t\\tthis._format = linearFormat;\\n\\t\\t\\t\\t\\tthis.recreateImpl();\\n\\t\\t\\t\\t\\tthis.device._shadersDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget srgb() {\\n\\t\\treturn isSrgbPixelFormat(this.format);\\n\\t}\\n\\tset flipY(flipY) {\\n\\t\\tif (this._flipY !== flipY) {\\n\\t\\t\\tthis._flipY = flipY;\\n\\t\\t\\tthis.markForUpload();\\n\\t\\t}\\n\\t}\\n\\tget flipY() {\\n\\t\\treturn this._flipY;\\n\\t}\\n\\tset premultiplyAlpha(premultiplyAlpha) {\\n\\t\\tif (this._premultiplyAlpha !== premultiplyAlpha) {\\n\\t\\t\\tthis._premultiplyAlpha = premultiplyAlpha;\\n\\t\\t\\tthis.markForUpload();\\n\\t\\t}\\n\\t}\\n\\tget premultiplyAlpha() {\\n\\t\\treturn this._premultiplyAlpha;\\n\\t}\\n\\tget pot() {\\n\\t\\treturn math.powerOfTwo(this._width) && math.powerOfTwo(this._height);\\n\\t}\\n\\t// get the texture's encoding type\\n\\tget encoding() {\\n\\t\\tswitch (this.type) {\\n\\t\\t\\tcase TEXTURETYPE_RGBM:\\n\\t\\t\\t\\treturn \\\"rgbm\\\";\\n\\t\\t\\tcase TEXTURETYPE_RGBE:\\n\\t\\t\\t\\treturn \\\"rgbe\\\";\\n\\t\\t\\tcase TEXTURETYPE_RGBP:\\n\\t\\t\\t\\treturn \\\"rgbp\\\";\\n\\t\\t}\\n\\t\\treturn requiresManualGamma(this.format) ? \\\"srgb\\\" : \\\"linear\\\";\\n\\t}\\n\\t// Force a full resubmission of the texture to the GPU (used on a context restore event)\\n\\tdirtyAll() {\\n\\t\\tthis._levelsUpdated = this._cubemap ? [[true, true, true, true, true, true]] : [true];\\n\\t\\tthis.markForUpload();\\n\\t\\tthis._needsMipmapsUpload = this._mipmaps;\\n\\t\\tthis._mipmapsUploaded = false;\\n\\t\\tthis.propertyChanged(TEXPROPERTY_ALL);\\n\\t}\\n\\tlock(options = {}) {\\n\\t\\toptions.level ?? (options.level = 0);\\n\\t\\toptions.face ?? (options.face = 0);\\n\\t\\toptions.mode ?? (options.mode = TEXTURELOCK_WRITE);\\n\\t\\tthis._lockedMode = options.mode;\\n\\t\\tthis._lockedLevel = options.level;\\n\\t\\tconst levels = this.cubemap ? this._levels[options.face] : this._levels;\\n\\t\\tif (!levels[options.level]) {\\n\\t\\t\\tconst width = Math.max(1, this._width >> options.level);\\n\\t\\t\\tconst height = Math.max(1, this._height >> options.level);\\n\\t\\t\\tconst depth = Math.max(1, this._depth >> options.level);\\n\\t\\t\\tconst data = new ArrayBuffer(TextureUtils.calcLevelGpuSize(width, height, depth, this._format));\\n\\t\\t\\tlevels[options.level] = new (getPixelFormatArrayType(this._format))(data);\\n\\t\\t}\\n\\t\\treturn levels[options.level];\\n\\t}\\n\\tsetSource(source, mipLevel = 0) {\\n\\t\\tif (this.device._isHTMLElementInterface(source)) {\\n\\t\\t\\tif (!this.device.supportsHtmlTextures) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tif (this._cubemap || this._volume) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tlet invalid = false;\\n\\t\\tlet width, height;\\n\\t\\tif (this._cubemap) {\\n\\t\\t\\tif (source[0]) {\\n\\t\\t\\t\\twidth = source[0].width || 0;\\n\\t\\t\\t\\theight = source[0].height || 0;\\n\\t\\t\\t\\tfor (let i = 0; i < 6; i++) {\\n\\t\\t\\t\\t\\tconst face = source[i];\\n\\t\\t\\t\\t\\tif (!face || // face is missing\\n\\t\\t\\t\\t\\tface.width !== width || // face is different width\\n\\t\\t\\t\\t\\tface.height !== height || // face is different height\\n\\t\\t\\t\\t\\t!this.device._isBrowserInterface(face)) {\\n\\t\\t\\t\\t\\t\\tinvalid = true;\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tinvalid = true;\\n\\t\\t\\t}\\n\\t\\t\\tif (!invalid) {\\n\\t\\t\\t\\tfor (let i = 0; i < 6; i++) {\\n\\t\\t\\t\\t\\tif (this._levels[mipLevel][i] !== source[i]) {\\n\\t\\t\\t\\t\\t\\tthis._levelsUpdated[mipLevel][i] = true;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tif (!this.device._isBrowserInterface(source)) {\\n\\t\\t\\t\\tinvalid = true;\\n\\t\\t\\t}\\n\\t\\t\\tif (!invalid) {\\n\\t\\t\\t\\tif (source !== this._levels[mipLevel]) {\\n\\t\\t\\t\\t\\tthis._levelsUpdated[mipLevel] = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (source instanceof HTMLVideoElement) {\\n\\t\\t\\t\\t\\twidth = source.videoWidth;\\n\\t\\t\\t\\t\\theight = source.videoHeight;\\n\\t\\t\\t\\t} else if (this.device._isHTMLElementInterface(source)) {\\n\\t\\t\\t\\t\\tconst rect = source.getBoundingClientRect();\\n\\t\\t\\t\\t\\twidth = Math.floor(rect.width) || 1;\\n\\t\\t\\t\\t\\theight = Math.floor(rect.height) || 1;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\twidth = source.width;\\n\\t\\t\\t\\t\\theight = source.height;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (invalid) {\\n\\t\\t\\tthis._width = 4;\\n\\t\\t\\tthis._height = 4;\\n\\t\\t\\tif (this._cubemap) {\\n\\t\\t\\t\\tfor (let i = 0; i < 6; i++) {\\n\\t\\t\\t\\t\\tthis._levels[mipLevel][i] = null;\\n\\t\\t\\t\\t\\tthis._levelsUpdated[mipLevel][i] = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._levels[mipLevel] = null;\\n\\t\\t\\t\\tthis._levelsUpdated[mipLevel] = true;\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tif (mipLevel === 0) {\\n\\t\\t\\t\\tthis._width = width;\\n\\t\\t\\t\\tthis._height = height;\\n\\t\\t\\t}\\n\\t\\t\\tthis._levels[mipLevel] = source;\\n\\t\\t}\\n\\t\\tif (this._invalid !== invalid || !invalid) {\\n\\t\\t\\tthis._invalid = invalid;\\n\\t\\t\\tthis.upload();\\n\\t\\t}\\n\\t}\\n\\tgetSource(mipLevel = 0) {\\n\\t\\treturn this._levels[mipLevel];\\n\\t}\\n\\tunlock() {\\n\\t\\tif (this._lockedMode === TEXTURELOCK_NONE) ;\\n\\t\\tif (this._lockedMode === TEXTURELOCK_WRITE) {\\n\\t\\t\\tthis.upload();\\n\\t\\t}\\n\\t\\tthis._lockedLevel = -1;\\n\\t\\tthis._lockedMode = TEXTURELOCK_NONE;\\n\\t}\\n\\tmarkForUpload() {\\n\\t\\tthis._needsUpload = true;\\n\\t\\tthis.device?.texturesToUpload?.add(this);\\n\\t}\\n\\tupload() {\\n\\t\\tthis.markForUpload();\\n\\t\\tthis._needsMipmapsUpload = this._mipmaps;\\n\\t\\tthis.impl.uploadImmediate?.(this.device, this);\\n\\t}\\n\\tread(x, y, width, height, options = {}) {\\n\\t\\treturn this.impl.read?.(x, y, width, height, options);\\n\\t}\\n\\twrite(x, y, width, height, data) {\\n\\t\\treturn this.impl.write?.(x, y, width, height, data);\\n\\t}\\n\\tgetView(baseMipLevel = 0, mipLevelCount = 1, baseArrayLayer = 0, arrayLayerCount = 1) {\\n\\t\\treturn new TextureView(this, baseMipLevel, mipLevelCount, baseArrayLayer, arrayLayerCount);\\n\\t}\\n}\\n\\nconst textureData = {\\n\\twhite: [255, 255, 255, 255],\\n\\tgray: [128, 128, 128, 255],\\n\\tblack: [0, 0, 0, 255],\\n\\tnormal: [128, 128, 255, 255],\\n\\tpink: [255, 128, 255, 255]\\n};\\nclass BuiltInTextures {\\n\\tmap = /* @__PURE__ */ new Map();\\n\\tdestroy() {\\n\\t\\tthis.map.forEach((texture) => {\\n\\t\\t\\ttexture.destroy();\\n\\t\\t});\\n\\t}\\n}\\nconst deviceCache$3 = new DeviceCache();\\nconst getBuiltInTexture = (device, name) => {\\n\\tconst cache = deviceCache$3.get(device, () => {\\n\\t\\treturn new BuiltInTextures();\\n\\t});\\n\\tif (!cache.map.has(name)) {\\n\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\tname: `built-in-texture-${name}`,\\n\\t\\t\\twidth: 1,\\n\\t\\t\\theight: 1,\\n\\t\\t\\tformat: PIXELFORMAT_RGBA8\\n\\t\\t});\\n\\t\\tconst pixels = texture.lock();\\n\\t\\tconst data = textureData[name];\\n\\t\\tpixels.set(data);\\n\\t\\ttexture.unlock();\\n\\t\\tcache.map.set(name, texture);\\n\\t}\\n\\treturn cache.map.get(name);\\n};\\n\\nlet id$a = 0;\\nclass DynamicBindGroup {\\n\\tbindGroup;\\n\\toffsets = [];\\n}\\nclass BindGroup {\\n\\trenderVersionUpdated = -1;\\n\\tuniformBuffers;\\n\\tuniformBufferOffsets = [];\\n\\tconstructor(graphicsDevice, format, defaultUniformBuffer) {\\n\\t\\tthis.id = id$a++;\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tthis.format = format;\\n\\t\\tthis.dirty = true;\\n\\t\\tthis.impl = graphicsDevice.createBindGroupImpl(this);\\n\\t\\tthis.textures = [];\\n\\t\\tthis.storageTextures = [];\\n\\t\\tthis.storageBuffers = [];\\n\\t\\tthis.uniformBuffers = [];\\n\\t\\tthis.defaultUniformBuffer = defaultUniformBuffer;\\n\\t\\tif (defaultUniformBuffer) {\\n\\t\\t\\tthis.setUniformBuffer(UNIFORM_BUFFER_DEFAULT_SLOT_NAME, defaultUniformBuffer);\\n\\t\\t}\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.impl.destroy();\\n\\t\\tthis.impl = null;\\n\\t\\tthis.format = null;\\n\\t\\tthis.defaultUniformBuffer = null;\\n\\t}\\n\\tsetUniformBuffer(name, uniformBuffer) {\\n\\t\\tconst index = this.format.bufferFormatsMap.get(name);\\n\\t\\tif (this.uniformBuffers[index] !== uniformBuffer) {\\n\\t\\t\\tthis.uniformBuffers[index] = uniformBuffer;\\n\\t\\t\\tthis.dirty = true;\\n\\t\\t}\\n\\t}\\n\\tsetStorageBuffer(name, storageBuffer) {\\n\\t\\tconst index = this.format.storageBufferFormatsMap.get(name);\\n\\t\\tif (this.storageBuffers[index] !== storageBuffer) {\\n\\t\\t\\tthis.storageBuffers[index] = storageBuffer;\\n\\t\\t\\tthis.dirty = true;\\n\\t\\t}\\n\\t}\\n\\tsetTexture(name, value) {\\n\\t\\tconst index = this.format.textureFormatsMap.get(name);\\n\\t\\tconst texture = value instanceof TextureView ? value.texture : value;\\n\\t\\tif (this.textures[index] !== value) {\\n\\t\\t\\tthis.textures[index] = value;\\n\\t\\t\\tthis.dirty = true;\\n\\t\\t} else if (this.renderVersionUpdated < texture.renderVersionDirty) {\\n\\t\\t\\tthis.dirty = true;\\n\\t\\t}\\n\\t}\\n\\tsetStorageTexture(name, value) {\\n\\t\\tconst index = this.format.storageTextureFormatsMap.get(name);\\n\\t\\tconst texture = value instanceof TextureView ? value.texture : value;\\n\\t\\tif (this.storageTextures[index] !== value) {\\n\\t\\t\\tthis.storageTextures[index] = value;\\n\\t\\t\\tthis.dirty = true;\\n\\t\\t} else if (this.renderVersionUpdated < texture.renderVersionDirty) {\\n\\t\\t\\tthis.dirty = true;\\n\\t\\t}\\n\\t}\\n\\tupdateUniformBuffers() {\\n\\t\\tfor (let i = 0; i < this.uniformBuffers.length; i++) {\\n\\t\\t\\tthis.uniformBuffers[i].update();\\n\\t\\t}\\n\\t}\\n\\tupdate() {\\n\\t\\tconst { textureFormats, storageTextureFormats, storageBufferFormats } = this.format;\\n\\t\\tfor (let i = 0; i < textureFormats.length; i++) {\\n\\t\\t\\tconst textureFormat = textureFormats[i];\\n\\t\\t\\tlet value = textureFormat.scopeId.value;\\n\\t\\t\\tif (!value) {\\n\\t\\t\\t\\tif (textureFormat.name === \\\"uSceneDepthMap\\\") {\\n\\t\\t\\t\\t\\tvalue = getBuiltInTexture(this.device, \\\"white\\\");\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (textureFormat.name === \\\"uSceneColorMap\\\") {\\n\\t\\t\\t\\t\\tvalue = getBuiltInTexture(this.device, \\\"pink\\\");\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!value) {\\n\\t\\t\\t\\t\\tvalue = getBuiltInTexture(this.device, \\\"pink\\\");\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis.setTexture(textureFormat.name, value);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < storageTextureFormats.length; i++) {\\n\\t\\t\\tconst storageTextureFormat = storageTextureFormats[i];\\n\\t\\t\\tconst value = storageTextureFormat.scopeId.value;\\n\\t\\t\\tthis.setStorageTexture(storageTextureFormat.name, value);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < storageBufferFormats.length; i++) {\\n\\t\\t\\tconst storageBufferFormat = storageBufferFormats[i];\\n\\t\\t\\tconst value = storageBufferFormat.scopeId.value;\\n\\t\\t\\tthis.setStorageBuffer(storageBufferFormat.name, value);\\n\\t\\t}\\n\\t\\tthis.uniformBufferOffsets.length = this.uniformBuffers.length;\\n\\t\\tfor (let i = 0; i < this.uniformBuffers.length; i++) {\\n\\t\\t\\tconst uniformBuffer = this.uniformBuffers[i];\\n\\t\\t\\tthis.uniformBufferOffsets[i] = uniformBuffer.offset;\\n\\t\\t\\tif (this.renderVersionUpdated < uniformBuffer.renderVersionDirty) {\\n\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this.dirty) {\\n\\t\\t\\tthis.dirty = false;\\n\\t\\t\\tthis.renderVersionUpdated = this.device.renderVersion;\\n\\t\\t\\tthis.impl.update(this);\\n\\t\\t}\\n\\t}\\n}\\n\\nconst BitPacking = {\\n\\tset(storage, value, shift, mask = 1) {\\n\\t\\tconst data = storage & ~(mask << shift);\\n\\t\\treturn data | value << shift;\\n\\t},\\n\\tget(storage, shift, mask = 1) {\\n\\t\\treturn storage >> shift & mask;\\n\\t},\\n\\tall(storage, shift, mask = 1) {\\n\\t\\tconst shifted = mask << shift;\\n\\t\\treturn (storage & shifted) === shifted;\\n\\t},\\n\\tany(storage, shift, mask = 1) {\\n\\t\\treturn (storage & mask << shift) !== 0;\\n\\t}\\n};\\n\\nconst opMask = 7;\\nconst factorMask = 15;\\nconst colorOpShift = 0;\\nconst colorSrcFactorShift = 3;\\nconst colorDstFactorShift = 7;\\nconst alphaOpShift = 11;\\nconst alphaSrcFactorShift = 14;\\nconst alphaDstFactorShift = 18;\\nconst redWriteShift = 22;\\nconst greenWriteShift = 23;\\nconst blueWriteShift = 24;\\nconst alphaWriteShift = 25;\\nconst blendShift = 26;\\nconst allWriteMasks = 15;\\nconst allWriteShift = redWriteShift;\\nclass BlendState {\\n\\ttarget0 = 0;\\n\\tconstructor(blend = false, colorOp = BLENDEQUATION_ADD, colorSrcFactor = BLENDMODE_ONE, colorDstFactor = BLENDMODE_ZERO, alphaOp, alphaSrcFactor, alphaDstFactor, redWrite = true, greenWrite = true, blueWrite = true, alphaWrite = true) {\\n\\t\\tthis.setColorBlend(colorOp, colorSrcFactor, colorDstFactor);\\n\\t\\tthis.setAlphaBlend(alphaOp ?? colorOp, alphaSrcFactor ?? colorSrcFactor, alphaDstFactor ?? colorDstFactor);\\n\\t\\tthis.setColorWrite(redWrite, greenWrite, blueWrite, alphaWrite);\\n\\t\\tthis.blend = blend;\\n\\t}\\n\\tset blend(value) {\\n\\t\\tthis.target0 = BitPacking.set(this.target0, value ? 1 : 0, blendShift);\\n\\t}\\n\\tget blend() {\\n\\t\\treturn BitPacking.all(this.target0, blendShift);\\n\\t}\\n\\tsetColorBlend(op, srcFactor, dstFactor) {\\n\\t\\tthis.target0 = BitPacking.set(this.target0, op, colorOpShift, opMask);\\n\\t\\tthis.target0 = BitPacking.set(this.target0, srcFactor, colorSrcFactorShift, factorMask);\\n\\t\\tthis.target0 = BitPacking.set(this.target0, dstFactor, colorDstFactorShift, factorMask);\\n\\t}\\n\\tsetAlphaBlend(op, srcFactor, dstFactor) {\\n\\t\\tthis.target0 = BitPacking.set(this.target0, op, alphaOpShift, opMask);\\n\\t\\tthis.target0 = BitPacking.set(this.target0, srcFactor, alphaSrcFactorShift, factorMask);\\n\\t\\tthis.target0 = BitPacking.set(this.target0, dstFactor, alphaDstFactorShift, factorMask);\\n\\t}\\n\\tsetColorWrite(redWrite, greenWrite, blueWrite, alphaWrite) {\\n\\t\\tthis.redWrite = redWrite;\\n\\t\\tthis.greenWrite = greenWrite;\\n\\t\\tthis.blueWrite = blueWrite;\\n\\t\\tthis.alphaWrite = alphaWrite;\\n\\t}\\n\\tget colorOp() {\\n\\t\\treturn BitPacking.get(this.target0, colorOpShift, opMask);\\n\\t}\\n\\tget colorSrcFactor() {\\n\\t\\treturn BitPacking.get(this.target0, colorSrcFactorShift, factorMask);\\n\\t}\\n\\tget colorDstFactor() {\\n\\t\\treturn BitPacking.get(this.target0, colorDstFactorShift, factorMask);\\n\\t}\\n\\tget alphaOp() {\\n\\t\\treturn BitPacking.get(this.target0, alphaOpShift, opMask);\\n\\t}\\n\\tget alphaSrcFactor() {\\n\\t\\treturn BitPacking.get(this.target0, alphaSrcFactorShift, factorMask);\\n\\t}\\n\\tget alphaDstFactor() {\\n\\t\\treturn BitPacking.get(this.target0, alphaDstFactorShift, factorMask);\\n\\t}\\n\\tset redWrite(value) {\\n\\t\\tthis.target0 = BitPacking.set(this.target0, value ? 1 : 0, redWriteShift);\\n\\t}\\n\\tget redWrite() {\\n\\t\\treturn BitPacking.all(this.target0, redWriteShift);\\n\\t}\\n\\tset greenWrite(value) {\\n\\t\\tthis.target0 = BitPacking.set(this.target0, value ? 1 : 0, greenWriteShift);\\n\\t}\\n\\tget greenWrite() {\\n\\t\\treturn BitPacking.all(this.target0, greenWriteShift);\\n\\t}\\n\\tset blueWrite(value) {\\n\\t\\tthis.target0 = BitPacking.set(this.target0, value ? 1 : 0, blueWriteShift);\\n\\t}\\n\\tget blueWrite() {\\n\\t\\treturn BitPacking.all(this.target0, blueWriteShift);\\n\\t}\\n\\tset alphaWrite(value) {\\n\\t\\tthis.target0 = BitPacking.set(this.target0, value ? 1 : 0, alphaWriteShift);\\n\\t}\\n\\tget alphaWrite() {\\n\\t\\treturn BitPacking.all(this.target0, alphaWriteShift);\\n\\t}\\n\\tget allWrite() {\\n\\t\\treturn BitPacking.get(this.target0, allWriteShift, allWriteMasks);\\n\\t}\\n\\tcopy(rhs) {\\n\\t\\tthis.target0 = rhs.target0;\\n\\t\\treturn this;\\n\\t}\\n\\tclone() {\\n\\t\\tconst clone = new this.constructor();\\n\\t\\treturn clone.copy(this);\\n\\t}\\n\\tget key() {\\n\\t\\treturn this.target0;\\n\\t}\\n\\tequals(rhs) {\\n\\t\\treturn this.target0 === rhs.target0;\\n\\t}\\n\\tstatic NOBLEND = Object.freeze(new BlendState());\\n\\tstatic NOWRITE = Object.freeze(new BlendState(void 0, void 0, void 0, void 0, void 0, void 0, void 0, false, false, false, false));\\n\\tstatic ALPHABLEND = Object.freeze(new BlendState(true, BLENDEQUATION_ADD, BLENDMODE_SRC_ALPHA, BLENDMODE_ONE_MINUS_SRC_ALPHA));\\n\\tstatic ADDBLEND = Object.freeze(new BlendState(true, BLENDEQUATION_ADD, BLENDMODE_ONE, BLENDMODE_ONE));\\n}\\n\\nconst stringIds$4 = new StringIds();\\nconst funcMask = 7;\\nconst funcShift = 0;\\nconst writeShift = 3;\\nclass DepthState {\\n\\tdata = 0;\\n\\t_depthBias = 0;\\n\\t_depthBiasSlope = 0;\\n\\tkey = 0;\\n\\tconstructor(func = FUNC_LESSEQUAL, write = true) {\\n\\t\\tthis.func = func;\\n\\t\\tthis.write = write;\\n\\t}\\n\\tset test(value) {\\n\\t\\tthis.func = value ? FUNC_LESSEQUAL : FUNC_ALWAYS;\\n\\t\\tthis.updateKey();\\n\\t}\\n\\tget test() {\\n\\t\\treturn this.func !== FUNC_ALWAYS;\\n\\t}\\n\\tset write(value) {\\n\\t\\tthis.data = BitPacking.set(this.data, value ? 1 : 0, writeShift);\\n\\t\\tthis.updateKey();\\n\\t}\\n\\tget write() {\\n\\t\\treturn BitPacking.all(this.data, writeShift);\\n\\t}\\n\\tset func(value) {\\n\\t\\tthis.data = BitPacking.set(this.data, value, funcShift, funcMask);\\n\\t\\tthis.updateKey();\\n\\t}\\n\\tget func() {\\n\\t\\treturn BitPacking.get(this.data, funcShift, funcMask);\\n\\t}\\n\\tset depthBias(value) {\\n\\t\\tthis._depthBias = value;\\n\\t\\tthis.updateKey();\\n\\t}\\n\\tget depthBias() {\\n\\t\\treturn this._depthBias;\\n\\t}\\n\\tset depthBiasSlope(value) {\\n\\t\\tthis._depthBiasSlope = value;\\n\\t\\tthis.updateKey();\\n\\t}\\n\\tget depthBiasSlope() {\\n\\t\\treturn this._depthBiasSlope;\\n\\t}\\n\\tcopy(rhs) {\\n\\t\\tthis.data = rhs.data;\\n\\t\\tthis._depthBias = rhs._depthBias;\\n\\t\\tthis._depthBiasSlope = rhs._depthBiasSlope;\\n\\t\\tthis.key = rhs.key;\\n\\t\\treturn this;\\n\\t}\\n\\tclone() {\\n\\t\\tconst clone = new this.constructor();\\n\\t\\treturn clone.copy(this);\\n\\t}\\n\\tupdateKey() {\\n\\t\\tconst { data, _depthBias, _depthBiasSlope } = this;\\n\\t\\tconst key = `${data}-${_depthBias}-${_depthBiasSlope}`;\\n\\t\\tthis.key = stringIds$4.get(key);\\n\\t}\\n\\tequals(rhs) {\\n\\t\\treturn this.key === rhs.key;\\n\\t}\\n\\tstatic DEFAULT = Object.freeze(new DepthState());\\n\\tstatic NODEPTH = Object.freeze(new DepthState(FUNC_ALWAYS, false));\\n\\tstatic WRITEDEPTH = Object.freeze(new DepthState(FUNC_ALWAYS, true));\\n}\\n\\nlet id$9 = 0;\\nclass IndexBuffer {\\n\\tconstructor(graphicsDevice, format, numIndices, usage = BUFFER_STATIC, initialData, options) {\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tthis.format = format;\\n\\t\\tthis.numIndices = numIndices;\\n\\t\\tthis.usage = usage;\\n\\t\\tthis.id = id$9++;\\n\\t\\tthis.impl = graphicsDevice.createIndexBufferImpl(this, options);\\n\\t\\tconst bytesPerIndex = typedArrayIndexFormatsByteSize[format];\\n\\t\\tthis.bytesPerIndex = bytesPerIndex;\\n\\t\\tthis.numBytes = this.numIndices * bytesPerIndex;\\n\\t\\tif (initialData) {\\n\\t\\t\\tthis.setData(initialData);\\n\\t\\t} else {\\n\\t\\t\\tthis.storage = new ArrayBuffer(this.numBytes);\\n\\t\\t}\\n\\t\\tthis.adjustVramSizeTracking(graphicsDevice._vram, this.numBytes);\\n\\t\\tthis.device.buffers.add(this);\\n\\t}\\n\\tdestroy() {\\n\\t\\tconst device = this.device;\\n\\t\\tdevice.buffers.delete(this);\\n\\t\\tif (this.device.indexBuffer === this) {\\n\\t\\t\\tthis.device.indexBuffer = null;\\n\\t\\t}\\n\\t\\tif (this.impl.initialized) {\\n\\t\\t\\tthis.impl.destroy(device);\\n\\t\\t\\tthis.adjustVramSizeTracking(device._vram, -this.storage.byteLength);\\n\\t\\t}\\n\\t}\\n\\tadjustVramSizeTracking(vram, size) {\\n\\t\\tvram.ib += size;\\n\\t}\\n\\tloseContext() {\\n\\t\\tthis.impl.loseContext();\\n\\t}\\n\\trestoreContext() {\\n\\t\\tthis.unlock();\\n\\t}\\n\\tgetFormat() {\\n\\t\\treturn this.format;\\n\\t}\\n\\tgetNumIndices() {\\n\\t\\treturn this.numIndices;\\n\\t}\\n\\tlock() {\\n\\t\\treturn this.storage;\\n\\t}\\n\\tunlock() {\\n\\t\\tthis.impl.unlock(this);\\n\\t}\\n\\tsetData(data) {\\n\\t\\tif (data.byteLength !== this.numBytes) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tthis.storage = data;\\n\\t\\tthis.unlock();\\n\\t\\treturn true;\\n\\t}\\n\\t_lockTypedArray() {\\n\\t\\tconst lock = this.lock();\\n\\t\\tconst indices = this.format === INDEXFORMAT_UINT32 ? new Uint32Array(lock) : this.format === INDEXFORMAT_UINT16 ? new Uint16Array(lock) : new Uint8Array(lock);\\n\\t\\treturn indices;\\n\\t}\\n\\twriteData(data, count) {\\n\\t\\tconst indices = this._lockTypedArray();\\n\\t\\tif (data.length > count) {\\n\\t\\t\\tif (ArrayBuffer.isView(data)) {\\n\\t\\t\\t\\tdata = data.subarray(0, count);\\n\\t\\t\\t\\tindices.set(data);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\t\\t\\tindices[i] = data[i];\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tindices.set(data);\\n\\t\\t}\\n\\t\\tthis.unlock();\\n\\t}\\n\\treadData(data) {\\n\\t\\tconst indices = this._lockTypedArray();\\n\\t\\tconst count = this.numIndices;\\n\\t\\tif (ArrayBuffer.isView(data)) {\\n\\t\\t\\tdata.set(indices);\\n\\t\\t} else {\\n\\t\\t\\tdata.length = 0;\\n\\t\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\t\\tdata[i] = indices[i];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn count;\\n\\t}\\n}\\n\\nclass Version {\\n\\tglobalId = 0;\\n\\trevision = 0;\\n\\tequals(other) {\\n\\t\\treturn this.globalId === other.globalId && this.revision === other.revision;\\n\\t}\\n\\tcopy(other) {\\n\\t\\tthis.globalId = other.globalId;\\n\\t\\tthis.revision = other.revision;\\n\\t}\\n\\treset() {\\n\\t\\tthis.globalId = 0;\\n\\t\\tthis.revision = 0;\\n\\t}\\n}\\n\\nlet idCounter = 0;\\nclass VersionedObject {\\n\\tconstructor() {\\n\\t\\tidCounter++;\\n\\t\\tthis.version = new Version();\\n\\t\\tthis.version.globalId = idCounter;\\n\\t}\\n\\tincrement() {\\n\\t\\tthis.version.revision++;\\n\\t}\\n}\\n\\nclass ScopeId {\\n\\tconstructor(name) {\\n\\t\\tthis.name = name;\\n\\t\\tthis.value = null;\\n\\t\\tthis.versionObject = new VersionedObject();\\n\\t}\\n\\t// Don't stringify ScopeId to JSON by JSON.stringify, as this stores 'value'\\n\\t// which is not needed. This is used when stringifying a uniform buffer format, which\\n\\t// internally stores the scope.\\n\\ttoJSON(key) {\\n\\t\\treturn void 0;\\n\\t}\\n\\tsetValue(value) {\\n\\t\\tthis.value = value;\\n\\t\\tthis.versionObject.increment();\\n\\t}\\n\\tgetValue() {\\n\\t\\treturn this.value;\\n\\t}\\n}\\n\\nclass ScopeSpace {\\n\\tconstructor(name) {\\n\\t\\tthis.name = name;\\n\\t\\tthis.variables = /* @__PURE__ */ new Map();\\n\\t}\\n\\tresolve(name) {\\n\\t\\tif (!this.variables.has(name)) {\\n\\t\\t\\tthis.variables.set(name, new ScopeId(name));\\n\\t\\t}\\n\\t\\treturn this.variables.get(name);\\n\\t}\\n\\tremoveValue(value) {\\n\\t\\tfor (const uniform of this.variables.values()) {\\n\\t\\t\\tif (uniform.value === value) {\\n\\t\\t\\t\\tuniform.value = null;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\n\\nlet id$8 = 0;\\nclass VertexBuffer {\\n\\tusage = BUFFER_STATIC;\\n\\tconstructor(graphicsDevice, format, numVertices, options) {\\n\\t\\tthis.usage = options?.usage ?? BUFFER_STATIC;\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tthis.format = format;\\n\\t\\tthis.numVertices = numVertices;\\n\\t\\tthis.id = id$8++;\\n\\t\\tthis.impl = graphicsDevice.createVertexBufferImpl(this, format, options);\\n\\t\\tthis.numBytes = format.verticesByteSize ? format.verticesByteSize : format.size * numVertices;\\n\\t\\tthis.adjustVramSizeTracking(graphicsDevice._vram, this.numBytes);\\n\\t\\tconst initialData = options?.data;\\n\\t\\tif (initialData) {\\n\\t\\t\\tthis.setData(initialData);\\n\\t\\t} else {\\n\\t\\t\\tthis.storage = new ArrayBuffer(this.numBytes);\\n\\t\\t}\\n\\t\\tthis.device.buffers.add(this);\\n\\t}\\n\\tdestroy() {\\n\\t\\tconst device = this.device;\\n\\t\\tdevice.buffers.delete(this);\\n\\t\\tif (this.impl.initialized) {\\n\\t\\t\\tthis.impl.destroy(device);\\n\\t\\t\\tthis.adjustVramSizeTracking(device._vram, -this.storage.byteLength);\\n\\t\\t}\\n\\t}\\n\\tadjustVramSizeTracking(vram, size) {\\n\\t\\tvram.vb += size;\\n\\t}\\n\\tloseContext() {\\n\\t\\tthis.impl.loseContext();\\n\\t}\\n\\trestoreContext() {\\n\\t\\tthis.unlock();\\n\\t}\\n\\tgetFormat() {\\n\\t\\treturn this.format;\\n\\t}\\n\\tgetUsage() {\\n\\t\\treturn this.usage;\\n\\t}\\n\\tgetNumVertices() {\\n\\t\\treturn this.numVertices;\\n\\t}\\n\\tlock() {\\n\\t\\treturn this.storage;\\n\\t}\\n\\tunlock() {\\n\\t\\tthis.impl.unlock(this);\\n\\t}\\n\\tsetData(data) {\\n\\t\\tif (data.byteLength !== this.numBytes) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tthis.storage = data;\\n\\t\\tthis.unlock();\\n\\t\\treturn true;\\n\\t}\\n}\\n\\nfunction hashCode(str) {\\n\\tif (str === null || str === void 0) {\\n\\t\\treturn 0;\\n\\t}\\n\\tlet hash = 0;\\n\\tfor (let i = 0, len = str.length; i < len; i++) {\\n\\t\\thash = (hash << 5) - hash + str.charCodeAt(i);\\n\\t\\thash |= 0;\\n\\t}\\n\\treturn hash;\\n}\\nfunction hash32Fnv1a(array) {\\n\\tconst prime = 16777619;\\n\\tlet hash = 2166136261;\\n\\tfor (let i = 0; i < array.length; i++) {\\n\\t\\thash ^= array[i];\\n\\t\\thash *= prime;\\n\\t}\\n\\treturn hash >>> 0;\\n}\\n\\nconst stringIds$3 = new StringIds();\\nconst webgpuValidElementSizes = [2, 4, 8, 12, 16];\\nconst deviceCache$2 = new DeviceCache();\\nclass VertexFormat {\\n\\tconstructor(graphicsDevice, description, vertexCount) {\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tthis._elements = [];\\n\\t\\tthis.hasUv0 = false;\\n\\t\\tthis.hasUv1 = false;\\n\\t\\tthis.hasColor = false;\\n\\t\\tthis.hasTangents = false;\\n\\t\\tthis.verticesByteSize = 0;\\n\\t\\tthis.vertexCount = vertexCount;\\n\\t\\tthis.interleaved = vertexCount === void 0;\\n\\t\\tthis.instancing = false;\\n\\t\\tthis.size = description.reduce((total, desc) => {\\n\\t\\t\\treturn total + Math.ceil(desc.components * typedArrayTypesByteSize[desc.type] / 4) * 4;\\n\\t\\t}, 0);\\n\\t\\tlet offset = 0, elementSize;\\n\\t\\tfor (let i = 0, len = description.length; i < len; i++) {\\n\\t\\t\\tconst elementDesc = description[i];\\n\\t\\t\\telementSize = elementDesc.components * typedArrayTypesByteSize[elementDesc.type];\\n\\t\\t\\tif (vertexCount) {\\n\\t\\t\\t\\toffset = math.roundUp(offset, elementSize);\\n\\t\\t\\t}\\n\\t\\t\\tconst asInt = elementDesc.asInt ?? false;\\n\\t\\t\\tconst normalize = asInt ? false : elementDesc.normalize ?? false;\\n\\t\\t\\tconst element = {\\n\\t\\t\\t\\tname: elementDesc.semantic,\\n\\t\\t\\t\\toffset: vertexCount ? offset : elementDesc.hasOwnProperty(\\\"offset\\\") ? elementDesc.offset : offset,\\n\\t\\t\\t\\tstride: vertexCount ? elementSize : elementDesc.hasOwnProperty(\\\"stride\\\") ? elementDesc.stride : this.size,\\n\\t\\t\\t\\tdataType: elementDesc.type,\\n\\t\\t\\t\\tnumComponents: elementDesc.components,\\n\\t\\t\\t\\tnormalize,\\n\\t\\t\\t\\tsize: elementSize,\\n\\t\\t\\t\\tasInt\\n\\t\\t\\t};\\n\\t\\t\\tthis._elements.push(element);\\n\\t\\t\\tif (vertexCount) {\\n\\t\\t\\t\\toffset += elementSize * vertexCount;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\toffset += Math.ceil(elementSize / 4) * 4;\\n\\t\\t\\t}\\n\\t\\t\\tif (elementDesc.semantic === SEMANTIC_TEXCOORD0) {\\n\\t\\t\\t\\tthis.hasUv0 = true;\\n\\t\\t\\t} else if (elementDesc.semantic === SEMANTIC_TEXCOORD1) {\\n\\t\\t\\t\\tthis.hasUv1 = true;\\n\\t\\t\\t} else if (elementDesc.semantic === SEMANTIC_COLOR) {\\n\\t\\t\\t\\tthis.hasColor = true;\\n\\t\\t\\t} else if (elementDesc.semantic === SEMANTIC_TANGENT) {\\n\\t\\t\\t\\tthis.hasTangents = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (vertexCount) {\\n\\t\\t\\tthis.verticesByteSize = offset;\\n\\t\\t}\\n\\t\\tthis._evaluateHash();\\n\\t}\\n\\tget elements() {\\n\\t\\treturn this._elements;\\n\\t}\\n\\tstatic getDefaultInstancingFormat(graphicsDevice) {\\n\\t\\treturn deviceCache$2.get(graphicsDevice, () => {\\n\\t\\t\\treturn new VertexFormat(graphicsDevice, [\\n\\t\\t\\t\\t{ semantic: SEMANTIC_ATTR11, components: 4, type: TYPE_FLOAT32 },\\n\\t\\t\\t\\t{ semantic: SEMANTIC_ATTR12, components: 4, type: TYPE_FLOAT32 },\\n\\t\\t\\t\\t{ semantic: SEMANTIC_ATTR14, components: 4, type: TYPE_FLOAT32 },\\n\\t\\t\\t\\t{ semantic: SEMANTIC_ATTR15, components: 4, type: TYPE_FLOAT32 }\\n\\t\\t\\t]);\\n\\t\\t});\\n\\t}\\n\\tstatic isElementValid(graphicsDevice, elementDesc) {\\n\\t\\tconst elementSize = elementDesc.components * typedArrayTypesByteSize[elementDesc.type];\\n\\t\\tif (graphicsDevice.isWebGPU && !webgpuValidElementSizes.includes(elementSize)) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\treturn true;\\n\\t}\\n\\tupdate() {\\n\\t\\tthis._evaluateHash();\\n\\t}\\n\\t_evaluateHash() {\\n\\t\\tconst stringElementsBatch = [];\\n\\t\\tconst stringElementsRender = [];\\n\\t\\tconst len = this._elements.length;\\n\\t\\tfor (let i = 0; i < len; i++) {\\n\\t\\t\\tconst { name, dataType, numComponents, normalize, offset, stride, size, asInt } = this._elements[i];\\n\\t\\t\\tconst stringElementBatch = name + dataType + numComponents + normalize + asInt;\\n\\t\\t\\tstringElementsBatch.push(stringElementBatch);\\n\\t\\t\\tconst stringElementRender = stringElementBatch + offset + stride + size;\\n\\t\\t\\tstringElementsRender.push(stringElementRender);\\n\\t\\t}\\n\\t\\tstringElementsBatch.sort();\\n\\t\\tconst batchingString = stringElementsBatch.join();\\n\\t\\tthis.batchingHash = hashCode(batchingString);\\n\\t\\tthis.shaderProcessingHashString = batchingString;\\n\\t\\tthis.renderingHashString = stringElementsRender.join(\\\"_\\\");\\n\\t\\tthis.renderingHash = stringIds$3.get(this.renderingHashString);\\n\\t}\\n}\\n\\nconst stringIds$2 = new StringIds();\\nclass StencilParameters {\\n\\t_func;\\n\\t_ref;\\n\\t_fail;\\n\\t_zfail;\\n\\t_zpass;\\n\\t_readMask;\\n\\t_writeMask;\\n\\t_dirty = true;\\n\\t_key;\\n\\tset func(value) {\\n\\t\\tthis._func = value;\\n\\t\\tthis._dirty = true;\\n\\t}\\n\\tget func() {\\n\\t\\treturn this._func;\\n\\t}\\n\\tset ref(value) {\\n\\t\\tthis._ref = value;\\n\\t\\tthis._dirty = true;\\n\\t}\\n\\tget ref() {\\n\\t\\treturn this._ref;\\n\\t}\\n\\tset fail(value) {\\n\\t\\tthis._fail = value;\\n\\t\\tthis._dirty = true;\\n\\t}\\n\\tget fail() {\\n\\t\\treturn this._fail;\\n\\t}\\n\\tset zfail(value) {\\n\\t\\tthis._zfail = value;\\n\\t\\tthis._dirty = true;\\n\\t}\\n\\tget zfail() {\\n\\t\\treturn this._zfail;\\n\\t}\\n\\tset zpass(value) {\\n\\t\\tthis._zpass = value;\\n\\t\\tthis._dirty = true;\\n\\t}\\n\\tget zpass() {\\n\\t\\treturn this._zpass;\\n\\t}\\n\\tset readMask(value) {\\n\\t\\tthis._readMask = value;\\n\\t\\tthis._dirty = true;\\n\\t}\\n\\tget readMask() {\\n\\t\\treturn this._readMask;\\n\\t}\\n\\tset writeMask(value) {\\n\\t\\tthis._writeMask = value;\\n\\t\\tthis._dirty = true;\\n\\t}\\n\\tget writeMask() {\\n\\t\\treturn this._writeMask;\\n\\t}\\n\\tconstructor(options = {}) {\\n\\t\\tthis._func = options.func ?? FUNC_ALWAYS;\\n\\t\\tthis._ref = options.ref ?? 0;\\n\\t\\tthis._readMask = options.readMask ?? 255;\\n\\t\\tthis._writeMask = options.writeMask ?? 255;\\n\\t\\tthis._fail = options.fail ?? STENCILOP_KEEP;\\n\\t\\tthis._zfail = options.zfail ?? STENCILOP_KEEP;\\n\\t\\tthis._zpass = options.zpass ?? STENCILOP_KEEP;\\n\\t\\tthis._evalKey();\\n\\t}\\n\\t_evalKey() {\\n\\t\\tconst { _func, _ref, _fail, _zfail, _zpass, _readMask, _writeMask } = this;\\n\\t\\tconst key = `${_func},${_ref},${_fail},${_zfail},${_zpass},${_readMask},${_writeMask}`;\\n\\t\\tthis._key = stringIds$2.get(key);\\n\\t\\tthis._dirty = false;\\n\\t}\\n\\tget key() {\\n\\t\\tif (this._dirty) {\\n\\t\\t\\tthis._evalKey();\\n\\t\\t}\\n\\t\\treturn this._key;\\n\\t}\\n\\tcopy(rhs) {\\n\\t\\tthis._func = rhs._func;\\n\\t\\tthis._ref = rhs._ref;\\n\\t\\tthis._readMask = rhs._readMask;\\n\\t\\tthis._writeMask = rhs._writeMask;\\n\\t\\tthis._fail = rhs._fail;\\n\\t\\tthis._zfail = rhs._zfail;\\n\\t\\tthis._zpass = rhs._zpass;\\n\\t\\tthis._dirty = rhs._dirty;\\n\\t\\tthis._key = rhs._key;\\n\\t\\treturn this;\\n\\t}\\n\\tclone() {\\n\\t\\tconst clone = new this.constructor();\\n\\t\\treturn clone.copy(this);\\n\\t}\\n\\tstatic DEFAULT = Object.freeze(new StencilParameters());\\n}\\n\\nlet id$7 = 0;\\nclass StorageBuffer {\\n\\tid = id$7++;\\n\\tconstructor(graphicsDevice, byteSize, bufferUsage = 0, addStorageUsage = true) {\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tthis.byteSize = byteSize;\\n\\t\\tthis.bufferUsage = bufferUsage;\\n\\t\\tconst usage = addStorageUsage ? BUFFERUSAGE_STORAGE | bufferUsage : bufferUsage;\\n\\t\\tthis.impl = graphicsDevice.createBufferImpl(usage);\\n\\t\\tthis.impl.allocate(graphicsDevice, byteSize);\\n\\t\\tgraphicsDevice.buffers.add(this);\\n\\t\\tthis.adjustVramSizeTracking(graphicsDevice._vram, this.byteSize);\\n\\t}\\n\\tdestroy() {\\n\\t\\tconst device = this.device;\\n\\t\\tdevice.buffers.delete(this);\\n\\t\\tthis.impl.destroy(device);\\n\\t\\tthis.adjustVramSizeTracking(device._vram, -this.byteSize);\\n\\t}\\n\\tloseContext() {\\n\\t\\tthis.impl.loseContext();\\n\\t}\\n\\trestoreContext() {\\n\\t\\tthis.impl.allocate(this.device, this.byteSize);\\n\\t}\\n\\tadjustVramSizeTracking(vram, size) {\\n\\t\\tvram.sb += size;\\n\\t}\\n\\tread(offset = 0, size = this.byteSize, data = null, immediate = false) {\\n\\t\\treturn this.impl.read(this.device, offset, size, data, immediate);\\n\\t}\\n\\twrite(bufferOffset = 0, data, dataOffset = 0, size) {\\n\\t\\tthis.impl.write(this.device, bufferOffset, data, dataOffset, size);\\n\\t}\\n\\tclear(offset = 0, size = this.byteSize) {\\n\\t\\tthis.impl.clear(this.device, offset, size);\\n\\t}\\n\\tcopy(srcBuffer, srcOffset = 0, dstOffset = 0, size = srcBuffer.byteSize - srcOffset) {\\n\\t\\tconst commandEncoder = this.device.getCommandEncoder();\\n\\t\\tcommandEncoder.copyBufferToBuffer(srcBuffer.impl.buffer, srcOffset, this.impl.buffer, dstOffset, size);\\n\\t}\\n}\\n\\nclass GraphicsDevice extends EventHandler {\\n\\tcanvas;\\n\\tbackBuffer = null;\\n\\tbackBufferSize = new Vec2();\\n\\tbackBufferFormat;\\n\\tbackBufferAntialias = false;\\n\\tisWebGPU = false;\\n\\tisWebGL2 = false;\\n\\tisNull = false;\\n\\tisHdr = false;\\n\\tscope;\\n\\tmaxIndirectDrawCount = 1024;\\n\\tmaxIndirectDispatchCount = 256;\\n\\tmaxAnisotropy;\\n\\tmaxCubeMapSize;\\n\\tmaxTextureSize;\\n\\tmaxVolumeSize;\\n\\tmaxColorAttachments = 1;\\n\\tprecision;\\n\\tsamples;\\n\\tmaxSamples = 1;\\n\\tsupportsStencil;\\n\\tsupportsMultiDraw = true;\\n\\tsupportsCompute = false;\\n\\tsupportsStorageTextureRead = false;\\n\\tsupportsSubgroups = false;\\n\\tsupportsSubgroupUniformity = false;\\n\\tsupportsSubgroupId = false;\\n\\tsupportsLinearIndexing = false;\\n\\tsupportsPointerCompositeAccess = false;\\n\\tsupportsPacked4x8IntegerDotProduct = false;\\n\\tsupportsTextureAndSamplerLet = false;\\n\\tsupportsUnrestrictedPointerParameters = false;\\n\\tmaxSubgroupSize = 0;\\n\\tminSubgroupSize = 0;\\n\\trenderTarget = null;\\n\\tshaders = [];\\n\\ttextures = /* @__PURE__ */ new Set();\\n\\ttexturesToUpload = /* @__PURE__ */ new Set();\\n\\ttargets = /* @__PURE__ */ new Set();\\n\\trenderVersion = 0;\\n\\trenderPassIndex;\\n\\tinsideRenderPass = false;\\n\\tsupportsUniformBuffers = false;\\n\\tsupportsClipDistances = false;\\n\\tsupportsTextureFormatTier1 = false;\\n\\tsupportsTextureFormatTier2 = false;\\n\\tsupportsPrimitiveIndex = false;\\n\\tsupportsShaderF16 = false;\\n\\tsupportsHtmlTextures = false;\\n\\ttextureFloatRenderable;\\n\\ttextureHalfFloatRenderable;\\n\\ttextureRG11B10Renderable = false;\\n\\ttextureFloatFilterable = false;\\n\\tquadVertexBuffer;\\n\\tquadIndexBuffer;\\n\\tblendState = new BlendState();\\n\\tdepthState = new DepthState();\\n\\tstencilEnabled = false;\\n\\tstencilFront = new StencilParameters();\\n\\tstencilBack = new StencilParameters();\\n\\tdynamicBuffers;\\n\\tgpuProfiler;\\n\\t_destroyed = false;\\n\\tdefaultClearOptions = {\\n\\t\\tcolor: [0, 0, 0, 1],\\n\\t\\tdepth: 1,\\n\\t\\tstencil: 0,\\n\\t\\tflags: CLEARFLAG_COLOR | CLEARFLAG_DEPTH\\n\\t};\\n\\tclientRect = {\\n\\t\\twidth: 0,\\n\\t\\theight: 0\\n\\t};\\n\\t_shadersDirty = false;\\n\\tcapsDefines = /* @__PURE__ */ new Map();\\n\\tmapsToClear = /* @__PURE__ */ new Set();\\n\\tstatic EVENT_RESIZE = \\\"resizecanvas\\\";\\n\\tconstructor(canvas, options) {\\n\\t\\tvar _a, _b, _c, _d, _e, _f, _g;\\n\\t\\tsuper();\\n\\t\\tthis.canvas = canvas;\\n\\t\\tif (\\\"setAttribute\\\" in canvas) {\\n\\t\\t\\tcanvas.setAttribute(\\\"data-engine\\\", `PlayCanvas ${version$1}`);\\n\\t\\t}\\n\\t\\tthis.initOptions = { ...options };\\n\\t\\t(_a = this.initOptions).alpha ?? (_a.alpha = true);\\n\\t\\t(_b = this.initOptions).depth ?? (_b.depth = true);\\n\\t\\t(_c = this.initOptions).stencil ?? (_c.stencil = true);\\n\\t\\t(_d = this.initOptions).antialias ?? (_d.antialias = true);\\n\\t\\t(_e = this.initOptions).powerPreference ?? (_e.powerPreference = \\\"high-performance\\\");\\n\\t\\t(_f = this.initOptions).displayFormat ?? (_f.displayFormat = DISPLAYFORMAT_LDR);\\n\\t\\t(_g = this.initOptions).xrCompatible ?? (_g.xrCompatible = platform.browser && !!navigator.xr);\\n\\t\\tthis._maxPixelRatio = platform.browser ? Math.min(1, window.devicePixelRatio) : 1;\\n\\t\\tthis.buffers = /* @__PURE__ */ new Set();\\n\\t\\tthis._vram = {\\n\\t\\t\\ttex: 0,\\n\\t\\t\\tvb: 0,\\n\\t\\t\\tib: 0,\\n\\t\\t\\tub: 0,\\n\\t\\t\\tsb: 0\\n\\t\\t};\\n\\t\\tthis._shaderStats = {\\n\\t\\t\\tvsCompiled: 0,\\n\\t\\t\\tfsCompiled: 0,\\n\\t\\t\\tlinked: 0,\\n\\t\\t\\tmaterialShaders: 0,\\n\\t\\t\\tcompileTime: 0\\n\\t\\t};\\n\\t\\tthis.initializeContextCaches();\\n\\t\\tthis._drawCallsPerFrame = 0;\\n\\t\\tthis._shaderSwitchesPerFrame = 0;\\n\\t\\tthis._primsPerFrame = [];\\n\\t\\tfor (let i = PRIMITIVE_POINTS; i <= PRIMITIVE_TRIFAN; i++) {\\n\\t\\t\\tthis._primsPerFrame[i] = 0;\\n\\t\\t}\\n\\t\\tthis._renderTargetCreationTime = 0;\\n\\t\\tthis.scope = new ScopeSpace(\\\"Device\\\");\\n\\t\\tthis.textureBias = this.scope.resolve(\\\"textureBias\\\");\\n\\t\\tthis.textureBias.setValue(0);\\n\\t}\\n\\tpostInit() {\\n\\t\\tconst vertexFormat = new VertexFormat(this, [\\n\\t\\t\\t{ semantic: SEMANTIC_POSITION, components: 2, type: TYPE_FLOAT32 }\\n\\t\\t]);\\n\\t\\tconst positions = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]);\\n\\t\\tthis.quadVertexBuffer = new VertexBuffer(this, vertexFormat, 4, {\\n\\t\\t\\tdata: positions\\n\\t\\t});\\n\\t\\tconst indices = new Uint16Array([0, 1, 2, 2, 1, 3]);\\n\\t\\tthis.quadIndexBuffer = new IndexBuffer(this, INDEXFORMAT_UINT16, 6, BUFFER_STATIC, indices.buffer);\\n\\t}\\n\\tinitCapsDefines() {\\n\\t\\tconst { capsDefines } = this;\\n\\t\\tcapsDefines.clear();\\n\\t\\tif (this.textureFloatFilterable) capsDefines.set(\\\"CAPS_TEXTURE_FLOAT_FILTERABLE\\\", \\\"\\\");\\n\\t\\tif (this.textureFloatRenderable) capsDefines.set(\\\"CAPS_TEXTURE_FLOAT_RENDERABLE\\\", \\\"\\\");\\n\\t\\tif (this.supportsMultiDraw) capsDefines.set(\\\"CAPS_MULTI_DRAW\\\", \\\"\\\");\\n\\t\\tif (this.supportsPrimitiveIndex) capsDefines.set(\\\"CAPS_PRIMITIVE_INDEX\\\", \\\"\\\");\\n\\t\\tif (this.supportsShaderF16) capsDefines.set(\\\"CAPS_SHADER_F16\\\", \\\"\\\");\\n\\t\\tif (this.supportsSubgroups) capsDefines.set(\\\"CAPS_SUBGROUPS\\\", \\\"\\\");\\n\\t\\tif (this.supportsSubgroupId) capsDefines.set(\\\"CAPS_SUBGROUP_ID\\\", \\\"\\\");\\n\\t\\tif (this.supportsLinearIndexing) capsDefines.set(\\\"CAPS_LINEAR_INDEXING\\\", \\\"\\\");\\n\\t\\tif (this.supportsUnrestrictedPointerParameters) capsDefines.set(\\\"CAPS_UNRESTRICTED_POINTER_PARAMETERS\\\", \\\"\\\");\\n\\t\\tif (this.supportsPointerCompositeAccess) capsDefines.set(\\\"CAPS_POINTER_COMPOSITE_ACCESS\\\", \\\"\\\");\\n\\t\\tif (this.supportsPacked4x8IntegerDotProduct) capsDefines.set(\\\"CAPS_PACKED_4X8_INTEGER_DOT_PRODUCT\\\", \\\"\\\");\\n\\t\\tif (this.supportsTextureAndSamplerLet) capsDefines.set(\\\"CAPS_TEXTURE_AND_SAMPLER_LET\\\", \\\"\\\");\\n\\t\\tif (this.supportsStorageTextureRead) capsDefines.set(\\\"CAPS_STORAGE_TEXTURE_READ\\\", \\\"\\\");\\n\\t\\tif (platform.desktop) capsDefines.set(\\\"PLATFORM_DESKTOP\\\", \\\"\\\");\\n\\t\\tif (platform.mobile) capsDefines.set(\\\"PLATFORM_MOBILE\\\", \\\"\\\");\\n\\t\\tif (platform.android) capsDefines.set(\\\"PLATFORM_ANDROID\\\", \\\"\\\");\\n\\t\\tif (platform.ios) capsDefines.set(\\\"PLATFORM_IOS\\\", \\\"\\\");\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.fire(\\\"destroy\\\");\\n\\t\\tthis.quadVertexBuffer?.destroy();\\n\\t\\tthis.quadVertexBuffer = null;\\n\\t\\tthis.quadIndexBuffer?.destroy();\\n\\t\\tthis.quadIndexBuffer = null;\\n\\t\\tthis.dynamicBuffers?.destroy();\\n\\t\\tthis.dynamicBuffers = null;\\n\\t\\tthis.gpuProfiler?.destroy();\\n\\t\\tthis.gpuProfiler = null;\\n\\t\\tthis._destroyed = true;\\n\\t}\\n\\tonDestroyShader(shader) {\\n\\t\\tthis.fire(\\\"destroy:shader\\\", shader);\\n\\t\\tconst idx = this.shaders.indexOf(shader);\\n\\t\\tif (idx !== -1) {\\n\\t\\t\\tthis.shaders.splice(idx, 1);\\n\\t\\t}\\n\\t}\\n\\tonTextureDestroyed(texture) {\\n\\t\\tthis.textures.delete(texture);\\n\\t\\tthis.texturesToUpload.delete(texture);\\n\\t\\tthis.scope.removeValue(texture);\\n\\t}\\n\\t// executes after the extended classes have executed their destroy function\\n\\tpostDestroy() {\\n\\t\\tthis.scope = null;\\n\\t\\tthis.canvas = null;\\n\\t}\\n\\tloseContext() {\\n\\t\\tthis.contextLost = true;\\n\\t\\tthis.backBufferSize.set(-1, -1);\\n\\t\\tfor (const texture of this.textures) {\\n\\t\\t\\ttexture.loseContext();\\n\\t\\t}\\n\\t\\tfor (const buffer of this.buffers) {\\n\\t\\t\\tbuffer.loseContext();\\n\\t\\t}\\n\\t\\tfor (const target of this.targets) {\\n\\t\\t\\ttarget.loseContext();\\n\\t\\t}\\n\\t\\tthis.gpuProfiler?.loseContext();\\n\\t}\\n\\trestoreContext() {\\n\\t\\tthis.contextLost = false;\\n\\t\\tthis.initializeRenderState();\\n\\t\\tthis.initializeContextCaches();\\n\\t\\tfor (const buffer of this.buffers) {\\n\\t\\t\\tbuffer.restoreContext();\\n\\t\\t}\\n\\t\\tthis.gpuProfiler?.restoreContext?.();\\n\\t}\\n\\t// don't stringify GraphicsDevice to JSON by JSON.stringify\\n\\ttoJSON(key) {\\n\\t\\treturn void 0;\\n\\t}\\n\\tinitializeContextCaches() {\\n\\t\\tthis.vertexBuffers = [];\\n\\t\\tthis.shader = null;\\n\\t\\tthis.shaderValid = void 0;\\n\\t\\tthis.shaderAsyncCompile = false;\\n\\t\\tthis.renderTarget = null;\\n\\t}\\n\\tinitializeRenderState() {\\n\\t\\tthis.blendState = new BlendState();\\n\\t\\tthis.depthState = new DepthState();\\n\\t\\tthis.cullMode = CULLFACE_BACK;\\n\\t\\tthis.frontFace = FRONTFACE_CCW;\\n\\t\\tthis.vx = this.vy = this.vw = this.vh = 0;\\n\\t\\tthis.sx = this.sy = this.sw = this.sh = 0;\\n\\t\\tthis.blendColor = new Color(0, 0, 0, 0);\\n\\t}\\n\\tsetStencilState(stencilFront, stencilBack) {\\n\\t}\\n\\tsetBlendState(blendState) {\\n\\t}\\n\\tsetBlendColor(r, g, b, a) {\\n\\t}\\n\\tsetDepthState(depthState) {\\n\\t}\\n\\tsetCullMode(cullMode) {\\n\\t}\\n\\tsetFrontFace(frontFace) {\\n\\t}\\n\\tsetDrawStates(blendState = BlendState.NOBLEND, depthState = DepthState.NODEPTH, cullMode = CULLFACE_NONE, frontFace = FRONTFACE_CCW, stencilFront, stencilBack) {\\n\\t\\tthis.setBlendState(blendState);\\n\\t\\tthis.setDepthState(depthState);\\n\\t\\tthis.setCullMode(cullMode);\\n\\t\\tthis.setFrontFace(frontFace);\\n\\t\\tthis.setStencilState(stencilFront, stencilBack);\\n\\t}\\n\\tsetRenderTarget(renderTarget) {\\n\\t\\tthis.renderTarget = renderTarget;\\n\\t}\\n\\tsetVertexBuffer(vertexBuffer) {\\n\\t\\tif (vertexBuffer) {\\n\\t\\t\\tthis.vertexBuffers.push(vertexBuffer);\\n\\t\\t}\\n\\t}\\n\\tclearVertexBuffer() {\\n\\t\\tthis.vertexBuffers.length = 0;\\n\\t}\\n\\tgetIndirectDrawSlot(count = 1) {\\n\\t\\treturn 0;\\n\\t}\\n\\tget indirectDrawBuffer() {\\n\\t\\treturn null;\\n\\t}\\n\\tgetIndirectDispatchSlot(count = 1) {\\n\\t\\treturn 0;\\n\\t}\\n\\tget indirectDispatchBuffer() {\\n\\t\\treturn null;\\n\\t}\\n\\tgetRenderTarget() {\\n\\t\\treturn this.renderTarget;\\n\\t}\\n\\tinitRenderTarget(target) {\\n\\t\\tif (target.initialized) return;\\n\\t\\ttarget.init();\\n\\t\\tthis.targets.add(target);\\n\\t}\\n\\tdraw(primitive, indexBuffer, numInstances, drawCommands, first = true, last = true) {\\n\\t}\\n\\t_isBrowserInterface(texture) {\\n\\t\\treturn this._isImageBrowserInterface(texture) || this._isImageCanvasInterface(texture) || this._isImageVideoInterface(texture) || this._isHTMLElementInterface(texture);\\n\\t}\\n\\t_isImageBrowserInterface(texture) {\\n\\t\\treturn typeof ImageBitmap !== \\\"undefined\\\" && texture instanceof ImageBitmap || typeof HTMLImageElement !== \\\"undefined\\\" && texture instanceof HTMLImageElement;\\n\\t}\\n\\t_isImageCanvasInterface(texture) {\\n\\t\\treturn typeof HTMLCanvasElement !== \\\"undefined\\\" && texture instanceof HTMLCanvasElement;\\n\\t}\\n\\t_isImageVideoInterface(texture) {\\n\\t\\treturn typeof HTMLVideoElement !== \\\"undefined\\\" && texture instanceof HTMLVideoElement;\\n\\t}\\n\\t_isHTMLElementInterface(texture) {\\n\\t\\treturn typeof HTMLElement !== \\\"undefined\\\" && texture instanceof HTMLElement && !(typeof HTMLImageElement !== \\\"undefined\\\" && texture instanceof HTMLImageElement) && !(typeof HTMLCanvasElement !== \\\"undefined\\\" && texture instanceof HTMLCanvasElement) && !(typeof HTMLVideoElement !== \\\"undefined\\\" && texture instanceof HTMLVideoElement);\\n\\t}\\n\\tresizeCanvas(width, height) {\\n\\t\\tconst pixelRatio = Math.min(this._maxPixelRatio, platform.browser ? window.devicePixelRatio : 1);\\n\\t\\tconst w = Math.floor(width * pixelRatio);\\n\\t\\tconst h = Math.floor(height * pixelRatio);\\n\\t\\tif (w !== this.canvas.width || h !== this.canvas.height) {\\n\\t\\t\\tthis.setResolution(w, h);\\n\\t\\t}\\n\\t}\\n\\tsetResolution(width, height) {\\n\\t\\tthis.canvas.width = width;\\n\\t\\tthis.canvas.height = height;\\n\\t\\tthis.fire(GraphicsDevice.EVENT_RESIZE, width, height);\\n\\t}\\n\\tupdate() {\\n\\t\\tthis.updateClientRect();\\n\\t}\\n\\tupdateClientRect() {\\n\\t\\tif (platform.worker) {\\n\\t\\t\\tthis.clientRect.width = this.canvas.width;\\n\\t\\t\\tthis.clientRect.height = this.canvas.height;\\n\\t\\t} else {\\n\\t\\t\\tconst rect = this.canvas.getBoundingClientRect();\\n\\t\\t\\tthis.clientRect.width = rect.width;\\n\\t\\t\\tthis.clientRect.height = rect.height;\\n\\t\\t}\\n\\t}\\n\\tget width() {\\n\\t\\treturn this.canvas.width;\\n\\t}\\n\\tget height() {\\n\\t\\treturn this.canvas.height;\\n\\t}\\n\\tset fullscreen(fullscreen) {\\n\\t}\\n\\tget fullscreen() {\\n\\t\\treturn false;\\n\\t}\\n\\tset maxPixelRatio(ratio) {\\n\\t\\tthis._maxPixelRatio = ratio;\\n\\t}\\n\\tget maxPixelRatio() {\\n\\t\\treturn this._maxPixelRatio;\\n\\t}\\n\\tget deviceType() {\\n\\t\\treturn this._deviceType;\\n\\t}\\n\\tstartRenderPass(renderPass) {\\n\\t}\\n\\tendRenderPass(renderPass) {\\n\\t}\\n\\tstartComputePass(name) {\\n\\t}\\n\\tendComputePass() {\\n\\t}\\n\\tframeStart() {\\n\\t\\tthis.renderPassIndex = 0;\\n\\t\\tthis.renderVersion++;\\n\\t}\\n\\tframeEnd() {\\n\\t\\tthis.mapsToClear.forEach((map) => map.clear());\\n\\t\\tthis.mapsToClear.clear();\\n\\t}\\n\\tcomputeDispatch(computes, name = \\\"Unnamed\\\") {\\n\\t}\\n\\tgetRenderableHdrFormat(formats = [PIXELFORMAT_111110F, PIXELFORMAT_RGBA16F, PIXELFORMAT_RGBA32F], filterable = true, samples = 1) {\\n\\t\\tfor (let i = 0; i < formats.length; i++) {\\n\\t\\t\\tconst format = formats[i];\\n\\t\\t\\tswitch (format) {\\n\\t\\t\\t\\tcase PIXELFORMAT_111110F: {\\n\\t\\t\\t\\t\\tif (this.textureRG11B10Renderable) {\\n\\t\\t\\t\\t\\t\\treturn format;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcase PIXELFORMAT_RGBA16F:\\n\\t\\t\\t\\t\\tif (this.textureHalfFloatRenderable) {\\n\\t\\t\\t\\t\\t\\treturn format;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase PIXELFORMAT_RGBA32F:\\n\\t\\t\\t\\t\\tif (this.isWebGPU && samples > 1) {\\n\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (this.textureFloatRenderable && (!filterable || this.textureFloatFilterable)) {\\n\\t\\t\\t\\t\\t\\treturn format;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn void 0;\\n\\t}\\n\\tvalidateAttributes(shader, vb0Format, vb1Format) {\\n\\t}\\n}\\n\\nlet id$6 = 0;\\nclass RenderTarget {\\n\\tname;\\n\\t_device;\\n\\t_colorBuffer;\\n\\t_colorBuffers;\\n\\t_depthBuffer;\\n\\t_depth;\\n\\t_stencil;\\n\\t_samples;\\n\\tautoResolve;\\n\\t_face;\\n\\t_mipLevel;\\n\\t_mipmaps;\\n\\t_width;\\n\\t_height;\\n\\tflipY;\\n\\tconstructor(options = {}) {\\n\\t\\tthis.id = id$6++;\\n\\t\\tconst device = options.colorBuffer?.device ?? options.colorBuffers?.[0].device ?? options.depthBuffer?.device ?? options.graphicsDevice;\\n\\t\\tthis._device = device;\\n\\t\\tconst { maxSamples } = this._device;\\n\\t\\tthis._samples = Math.min(options.samples ?? 1, maxSamples);\\n\\t\\tif (device.isWebGPU) {\\n\\t\\t\\tthis._samples = this._samples > 1 ? maxSamples : 1;\\n\\t\\t}\\n\\t\\tthis._colorBuffer = options.colorBuffer;\\n\\t\\tif (options.colorBuffer) {\\n\\t\\t\\tthis._colorBuffers = [options.colorBuffer];\\n\\t\\t}\\n\\t\\tthis._depthBuffer = options.depthBuffer;\\n\\t\\tthis._face = options.face ?? 0;\\n\\t\\tif (this._depthBuffer) {\\n\\t\\t\\tconst format = this._depthBuffer._format;\\n\\t\\t\\tif (format === PIXELFORMAT_DEPTH || format === PIXELFORMAT_DEPTH16) {\\n\\t\\t\\t\\tthis._depth = true;\\n\\t\\t\\t\\tthis._stencil = false;\\n\\t\\t\\t} else if (format === PIXELFORMAT_DEPTHSTENCIL) {\\n\\t\\t\\t\\tthis._depth = true;\\n\\t\\t\\t\\tthis._stencil = true;\\n\\t\\t\\t} else if (format === PIXELFORMAT_R32F && this._depthBuffer.device.isWebGPU && this._samples > 1) {\\n\\t\\t\\t\\tthis._depth = true;\\n\\t\\t\\t\\tthis._stencil = false;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._depth = false;\\n\\t\\t\\t\\tthis._stencil = false;\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis._depth = options.depth ?? true;\\n\\t\\t\\tthis._stencil = options.stencil ?? false;\\n\\t\\t}\\n\\t\\tif (options.colorBuffers) {\\n\\t\\t\\tif (!this._colorBuffers) {\\n\\t\\t\\t\\tthis._colorBuffers = [...options.colorBuffers];\\n\\t\\t\\t\\tthis._colorBuffer = options.colorBuffers[0];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.autoResolve = options.autoResolve ?? true;\\n\\t\\tthis.name = options.name;\\n\\t\\tif (!this.name) {\\n\\t\\t\\tthis.name = this._colorBuffer?.name;\\n\\t\\t}\\n\\t\\tif (!this.name) {\\n\\t\\t\\tthis.name = this._depthBuffer?.name;\\n\\t\\t}\\n\\t\\tif (!this.name) {\\n\\t\\t\\tthis.name = \\\"Untitled\\\";\\n\\t\\t}\\n\\t\\tthis.flipY = options.flipY ?? false;\\n\\t\\tthis._mipLevel = options.mipLevel ?? 0;\\n\\t\\tif (this._mipLevel > 0 && this._depth) {\\n\\t\\t\\tthis._mipLevel = 0;\\n\\t\\t}\\n\\t\\tthis._mipmaps = options.mipLevel === void 0;\\n\\t\\tthis.evaluateDimensions();\\n\\t\\tthis.validateMrt();\\n\\t\\tthis.impl = device.createRenderTargetImpl(this);\\n\\t}\\n\\tdestroy() {\\n\\t\\tconst device = this._device;\\n\\t\\tif (device) {\\n\\t\\t\\tdevice.targets.delete(this);\\n\\t\\t\\tif (device.renderTarget === this) {\\n\\t\\t\\t\\tdevice.setRenderTarget(null);\\n\\t\\t\\t}\\n\\t\\t\\tthis.destroyFrameBuffers();\\n\\t\\t}\\n\\t}\\n\\tdestroyFrameBuffers() {\\n\\t\\tconst device = this._device;\\n\\t\\tif (device) {\\n\\t\\t\\tthis.impl.destroy(device);\\n\\t\\t}\\n\\t}\\n\\tdestroyTextureBuffers() {\\n\\t\\tthis._depthBuffer?.destroy();\\n\\t\\tthis._depthBuffer = null;\\n\\t\\tthis._colorBuffers?.forEach((colorBuffer) => {\\n\\t\\t\\tcolorBuffer.destroy();\\n\\t\\t});\\n\\t\\tthis._colorBuffers = null;\\n\\t\\tthis._colorBuffer = null;\\n\\t}\\n\\tresize(width, height) {\\n\\t\\tif (this.mipLevel > 0) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._depthBuffer?.resize(width, height);\\n\\t\\tthis._colorBuffers?.forEach((colorBuffer) => {\\n\\t\\t\\tcolorBuffer.resize(width, height);\\n\\t\\t});\\n\\t\\tif (this._width !== width || this._height !== height) {\\n\\t\\t\\tthis.destroyFrameBuffers();\\n\\t\\t\\tconst device = this._device;\\n\\t\\t\\tif (device.renderTarget === this) {\\n\\t\\t\\t\\tdevice.setRenderTarget(null);\\n\\t\\t\\t}\\n\\t\\t\\tthis.evaluateDimensions();\\n\\t\\t\\tthis.validateMrt();\\n\\t\\t\\tthis.impl = device.createRenderTargetImpl(this);\\n\\t\\t}\\n\\t}\\n\\tvalidateMrt() {\\n\\t}\\n\\tevaluateDimensions() {\\n\\t\\tconst buffer = this._colorBuffer ?? this._depthBuffer;\\n\\t\\tif (buffer) {\\n\\t\\t\\tthis._width = buffer.width;\\n\\t\\t\\tthis._height = buffer.height;\\n\\t\\t\\tif (this._mipLevel > 0) {\\n\\t\\t\\t\\tthis._width = TextureUtils.calcLevelDimension(this._width, this._mipLevel);\\n\\t\\t\\t\\tthis._height = TextureUtils.calcLevelDimension(this._height, this._mipLevel);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tinit() {\\n\\t\\tthis.impl.init(this._device, this);\\n\\t}\\n\\tget initialized() {\\n\\t\\treturn this.impl.initialized;\\n\\t}\\n\\tget device() {\\n\\t\\treturn this._device;\\n\\t}\\n\\tloseContext() {\\n\\t\\tthis.impl.loseContext();\\n\\t}\\n\\tresolve(color = true, depth = !!this._depthBuffer) {\\n\\t\\tif (this._device && this._samples > 1) {\\n\\t\\t\\tthis.impl.resolve(this._device, this, color, depth);\\n\\t\\t}\\n\\t}\\n\\tcopy(source, color, depth) {\\n\\t\\tif (!this._device) {\\n\\t\\t\\tif (source._device) {\\n\\t\\t\\t\\tthis._device = source._device;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\treturn false;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst success = this._device.copyRenderTarget(source, this, color, depth);\\n\\t\\treturn success;\\n\\t}\\n\\tget samples() {\\n\\t\\treturn this._samples;\\n\\t}\\n\\tget depth() {\\n\\t\\treturn this._depth;\\n\\t}\\n\\tget stencil() {\\n\\t\\treturn this._stencil;\\n\\t}\\n\\tget colorBuffer() {\\n\\t\\treturn this._colorBuffer;\\n\\t}\\n\\tgetColorBuffer(index) {\\n\\t\\treturn this._colorBuffers?.[index];\\n\\t}\\n\\tget depthBuffer() {\\n\\t\\treturn this._depthBuffer;\\n\\t}\\n\\tget face() {\\n\\t\\treturn this._face;\\n\\t}\\n\\tget mipLevel() {\\n\\t\\treturn this._mipLevel;\\n\\t}\\n\\tget mipmaps() {\\n\\t\\treturn this._mipmaps;\\n\\t}\\n\\tget width() {\\n\\t\\treturn this._width ?? this._device.width;\\n\\t}\\n\\tget height() {\\n\\t\\treturn this._height ?? this._device.height;\\n\\t}\\n\\tisColorBufferSrgb(index = 0) {\\n\\t\\tif (this.device.backBuffer === this) {\\n\\t\\t\\treturn isSrgbPixelFormat(this.device.backBufferFormat);\\n\\t\\t}\\n\\t\\tconst colorBuffer = this.getColorBuffer(index);\\n\\t\\treturn colorBuffer ? isSrgbPixelFormat(colorBuffer.format) : false;\\n\\t}\\n}\\n\\nclass WebgpuBindGroup {\\n\\tbindGroup;\\n\\tupdate(bindGroup) {\\n\\t\\tthis.destroy();\\n\\t\\tconst device = bindGroup.device;\\n\\t\\tconst desc = this.createDescriptor(device, bindGroup);\\n\\t\\tthis.bindGroup = device.wgpu.createBindGroup(desc);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.bindGroup = null;\\n\\t}\\n\\tcreateDescriptor(device, bindGroup) {\\n\\t\\tconst entries = [];\\n\\t\\tconst format = bindGroup.format;\\n\\t\\tconst uniformBufferFormats = bindGroup.format.uniformBufferFormats;\\n\\t\\tbindGroup.uniformBuffers.forEach((ub, i) => {\\n\\t\\t\\tconst slot = uniformBufferFormats[i].slot;\\n\\t\\t\\tconst buffer = ub.persistent ? ub.impl.buffer : ub.allocation.gpuBuffer.buffer;\\n\\t\\t\\tentries.push({\\n\\t\\t\\t\\tbinding: slot,\\n\\t\\t\\t\\tresource: {\\n\\t\\t\\t\\t\\tbuffer,\\n\\t\\t\\t\\t\\toffset: 0,\\n\\t\\t\\t\\t\\tsize: ub.format.byteSize\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t});\\n\\t\\tconst textureFormats = bindGroup.format.textureFormats;\\n\\t\\tbindGroup.textures.forEach((value, textureIndex) => {\\n\\t\\t\\tconst isTextureView = value instanceof TextureView;\\n\\t\\t\\tconst texture = isTextureView ? value.texture : value;\\n\\t\\t\\tconst wgpuTexture = texture.impl;\\n\\t\\t\\tconst textureFormat = format.textureFormats[textureIndex];\\n\\t\\t\\tconst slot = textureFormats[textureIndex].slot;\\n\\t\\t\\tconst view = wgpuTexture.getView(device, isTextureView ? value : void 0);\\n\\t\\t\\tentries.push({\\n\\t\\t\\t\\tbinding: slot,\\n\\t\\t\\t\\tresource: view\\n\\t\\t\\t});\\n\\t\\t\\tif (textureFormat.hasSampler) {\\n\\t\\t\\t\\tconst sampler = wgpuTexture.getSampler(device, textureFormat.sampleType);\\n\\t\\t\\t\\tentries.push({\\n\\t\\t\\t\\t\\tbinding: slot + 1,\\n\\t\\t\\t\\t\\tresource: sampler\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tconst storageTextureFormats = bindGroup.format.storageTextureFormats;\\n\\t\\tbindGroup.storageTextures.forEach((value, textureIndex) => {\\n\\t\\t\\tconst isTextureView = value instanceof TextureView;\\n\\t\\t\\tconst texture = isTextureView ? value.texture : value;\\n\\t\\t\\tconst wgpuTexture = texture.impl;\\n\\t\\t\\tconst slot = storageTextureFormats[textureIndex].slot;\\n\\t\\t\\tconst view = wgpuTexture.getView(device, isTextureView ? value : void 0);\\n\\t\\t\\tentries.push({\\n\\t\\t\\t\\tbinding: slot,\\n\\t\\t\\t\\tresource: view\\n\\t\\t\\t});\\n\\t\\t});\\n\\t\\tconst storageBufferFormats = bindGroup.format.storageBufferFormats;\\n\\t\\tbindGroup.storageBuffers.forEach((buffer, bufferIndex) => {\\n\\t\\t\\tconst wgpuBuffer = buffer.impl.buffer;\\n\\t\\t\\tconst slot = storageBufferFormats[bufferIndex].slot;\\n\\t\\t\\tentries.push({\\n\\t\\t\\t\\tbinding: slot,\\n\\t\\t\\t\\tresource: {\\n\\t\\t\\t\\t\\tbuffer: wgpuBuffer\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t});\\n\\t\\tconst desc = {\\n\\t\\t\\tlayout: bindGroup.format.impl.bindGroupLayout,\\n\\t\\t\\tentries\\n\\t\\t};\\n\\t\\treturn desc;\\n\\t}\\n}\\n\\nclass WebgpuUtils {\\n\\t// converts a combination of SHADER_STAGE_* into GPUShaderStage.*\\n\\tstatic shaderStage(stage) {\\n\\t\\tlet ret = 0;\\n\\t\\tif (stage & SHADERSTAGE_VERTEX) ret |= GPUShaderStage.VERTEX;\\n\\t\\tif (stage & SHADERSTAGE_FRAGMENT) ret |= GPUShaderStage.FRAGMENT;\\n\\t\\tif (stage & SHADERSTAGE_COMPUTE) ret |= GPUShaderStage.COMPUTE;\\n\\t\\treturn ret;\\n\\t}\\n}\\n\\nconst gpuTextureFormats = [];\\ngpuTextureFormats[PIXELFORMAT_A8] = \\\"\\\";\\ngpuTextureFormats[PIXELFORMAT_L8] = \\\"\\\";\\ngpuTextureFormats[PIXELFORMAT_LA8] = \\\"\\\";\\ngpuTextureFormats[PIXELFORMAT_R8] = \\\"r8unorm\\\";\\ngpuTextureFormats[PIXELFORMAT_RG8] = \\\"rg8unorm\\\";\\ngpuTextureFormats[PIXELFORMAT_RGB565] = \\\"\\\";\\ngpuTextureFormats[PIXELFORMAT_RGBA5551] = \\\"\\\";\\ngpuTextureFormats[PIXELFORMAT_RGBA4] = \\\"\\\";\\ngpuTextureFormats[PIXELFORMAT_RGB8] = \\\"rgba8unorm\\\";\\ngpuTextureFormats[PIXELFORMAT_RGBA8] = \\\"rgba8unorm\\\";\\ngpuTextureFormats[PIXELFORMAT_DXT1] = \\\"bc1-rgba-unorm\\\";\\ngpuTextureFormats[PIXELFORMAT_DXT3] = \\\"bc2-rgba-unorm\\\";\\ngpuTextureFormats[PIXELFORMAT_DXT5] = \\\"bc3-rgba-unorm\\\";\\ngpuTextureFormats[PIXELFORMAT_RGB16F] = \\\"\\\";\\ngpuTextureFormats[PIXELFORMAT_RGBA16F] = \\\"rgba16float\\\";\\ngpuTextureFormats[PIXELFORMAT_R16F] = \\\"r16float\\\";\\ngpuTextureFormats[PIXELFORMAT_RG16F] = \\\"rg16float\\\";\\ngpuTextureFormats[PIXELFORMAT_RGB32F] = \\\"\\\";\\ngpuTextureFormats[PIXELFORMAT_RGBA32F] = \\\"rgba32float\\\";\\ngpuTextureFormats[PIXELFORMAT_R32F] = \\\"r32float\\\";\\ngpuTextureFormats[PIXELFORMAT_RG32F] = \\\"rg32float\\\";\\ngpuTextureFormats[PIXELFORMAT_DEPTH] = \\\"depth32float\\\";\\ngpuTextureFormats[PIXELFORMAT_DEPTH16] = \\\"depth16unorm\\\";\\ngpuTextureFormats[PIXELFORMAT_DEPTHSTENCIL] = \\\"depth24plus-stencil8\\\";\\ngpuTextureFormats[PIXELFORMAT_111110F] = \\\"rg11b10ufloat\\\";\\ngpuTextureFormats[PIXELFORMAT_SRGB8] = \\\"\\\";\\ngpuTextureFormats[PIXELFORMAT_SRGBA8] = \\\"rgba8unorm-srgb\\\";\\ngpuTextureFormats[PIXELFORMAT_ETC1] = \\\"\\\";\\ngpuTextureFormats[PIXELFORMAT_ETC2_RGB] = \\\"etc2-rgb8unorm\\\";\\ngpuTextureFormats[PIXELFORMAT_ETC2_RGBA] = \\\"etc2-rgba8unorm\\\";\\ngpuTextureFormats[PIXELFORMAT_PVRTC_2BPP_RGB_1] = \\\"\\\";\\ngpuTextureFormats[PIXELFORMAT_PVRTC_2BPP_RGBA_1] = \\\"\\\";\\ngpuTextureFormats[PIXELFORMAT_PVRTC_4BPP_RGB_1] = \\\"\\\";\\ngpuTextureFormats[PIXELFORMAT_PVRTC_4BPP_RGBA_1] = \\\"\\\";\\ngpuTextureFormats[PIXELFORMAT_ASTC_4x4] = \\\"astc-4x4-unorm\\\";\\ngpuTextureFormats[PIXELFORMAT_ATC_RGB] = \\\"\\\";\\ngpuTextureFormats[PIXELFORMAT_ATC_RGBA] = \\\"\\\";\\ngpuTextureFormats[PIXELFORMAT_BGRA8] = \\\"bgra8unorm\\\";\\ngpuTextureFormats[PIXELFORMAT_SBGRA8] = \\\"bgra8unorm-srgb\\\";\\ngpuTextureFormats[PIXELFORMAT_R8I] = \\\"r8sint\\\";\\ngpuTextureFormats[PIXELFORMAT_R8U] = \\\"r8uint\\\";\\ngpuTextureFormats[PIXELFORMAT_R16I] = \\\"r16sint\\\";\\ngpuTextureFormats[PIXELFORMAT_R16U] = \\\"r16uint\\\";\\ngpuTextureFormats[PIXELFORMAT_R32I] = \\\"r32sint\\\";\\ngpuTextureFormats[PIXELFORMAT_R32U] = \\\"r32uint\\\";\\ngpuTextureFormats[PIXELFORMAT_RG8I] = \\\"rg8sint\\\";\\ngpuTextureFormats[PIXELFORMAT_RG8U] = \\\"rg8uint\\\";\\ngpuTextureFormats[PIXELFORMAT_RG16I] = \\\"rg16sint\\\";\\ngpuTextureFormats[PIXELFORMAT_RG16U] = \\\"rg16uint\\\";\\ngpuTextureFormats[PIXELFORMAT_RG32I] = \\\"rg32sint\\\";\\ngpuTextureFormats[PIXELFORMAT_RG32U] = \\\"rg32uint\\\";\\ngpuTextureFormats[PIXELFORMAT_RGBA8I] = \\\"rgba8sint\\\";\\ngpuTextureFormats[PIXELFORMAT_RGBA8U] = \\\"rgba8uint\\\";\\ngpuTextureFormats[PIXELFORMAT_RGBA16I] = \\\"rgba16sint\\\";\\ngpuTextureFormats[PIXELFORMAT_RGBA16U] = \\\"rgba16uint\\\";\\ngpuTextureFormats[PIXELFORMAT_RGBA32I] = \\\"rgba32sint\\\";\\ngpuTextureFormats[PIXELFORMAT_RGBA32U] = \\\"rgba32uint\\\";\\ngpuTextureFormats[PIXELFORMAT_BC6F] = \\\"bc6h-rgb-float\\\";\\ngpuTextureFormats[PIXELFORMAT_BC6UF] = \\\"bc6h-rgb-ufloat\\\";\\ngpuTextureFormats[PIXELFORMAT_BC7] = \\\"bc7-rgba-unorm\\\";\\ngpuTextureFormats[PIXELFORMAT_RGB9E5] = \\\"rgb9e5ufloat\\\";\\ngpuTextureFormats[PIXELFORMAT_RG8S] = \\\"rg8snorm\\\";\\ngpuTextureFormats[PIXELFORMAT_RGBA8S] = \\\"rgba8snorm\\\";\\ngpuTextureFormats[PIXELFORMAT_RGB10A2] = \\\"rgb10a2unorm\\\";\\ngpuTextureFormats[PIXELFORMAT_RGB10A2U] = \\\"rgb10a2uint\\\";\\ngpuTextureFormats[PIXELFORMAT_DXT1_SRGB] = \\\"bc1-rgba-unorm-srgb\\\";\\ngpuTextureFormats[PIXELFORMAT_DXT3_SRGBA] = \\\"bc2-rgba-unorm-srgb\\\";\\ngpuTextureFormats[PIXELFORMAT_DXT5_SRGBA] = \\\"bc3-rgba-unorm-srgb\\\";\\ngpuTextureFormats[PIXELFORMAT_ETC2_SRGB] = \\\"etc2-rgb8unorm-srgb\\\";\\ngpuTextureFormats[PIXELFORMAT_ETC2_SRGBA] = \\\"etc2-rgba8unorm-srgb\\\";\\ngpuTextureFormats[PIXELFORMAT_BC7_SRGBA] = \\\"bc7-rgba-unorm-srgb\\\";\\ngpuTextureFormats[PIXELFORMAT_ASTC_4x4_SRGB] = \\\"astc-4x4-unorm-srgb\\\";\\n\\nconst samplerTypes = [];\\nsamplerTypes[SAMPLETYPE_FLOAT] = \\\"filtering\\\";\\nsamplerTypes[SAMPLETYPE_UNFILTERABLE_FLOAT] = \\\"non-filtering\\\";\\nsamplerTypes[SAMPLETYPE_DEPTH] = \\\"comparison\\\";\\nsamplerTypes[SAMPLETYPE_INT] = \\\"comparison\\\";\\nsamplerTypes[SAMPLETYPE_UINT] = \\\"comparison\\\";\\nconst sampleTypes = [];\\nsampleTypes[SAMPLETYPE_FLOAT] = \\\"float\\\";\\nsampleTypes[SAMPLETYPE_UNFILTERABLE_FLOAT] = \\\"unfilterable-float\\\";\\nsampleTypes[SAMPLETYPE_DEPTH] = \\\"depth\\\";\\nsampleTypes[SAMPLETYPE_INT] = \\\"sint\\\";\\nsampleTypes[SAMPLETYPE_UINT] = \\\"uint\\\";\\nconst stringIds$1 = new StringIds();\\nclass WebgpuBindGroupFormat {\\n\\tconstructor(bindGroupFormat) {\\n\\t\\tconst device = bindGroupFormat.device;\\n\\t\\tconst { key, desc } = this.createDescriptor(bindGroupFormat);\\n\\t\\tthis.key = stringIds$1.get(key);\\n\\t\\tthis.bindGroupLayout = device.wgpu.createBindGroupLayout(desc);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.bindGroupLayout = null;\\n\\t}\\n\\tloseContext() {\\n\\t}\\n\\tcreateDescriptor(bindGroupFormat) {\\n\\t\\tconst entries = [];\\n\\t\\tlet key = \\\"\\\";\\n\\t\\tbindGroupFormat.uniformBufferFormats.forEach((bufferFormat) => {\\n\\t\\t\\tconst visibility = WebgpuUtils.shaderStage(bufferFormat.visibility);\\n\\t\\t\\tkey += `#${bufferFormat.slot}U:${visibility}`;\\n\\t\\t\\tentries.push({\\n\\t\\t\\t\\tbinding: bufferFormat.slot,\\n\\t\\t\\t\\tvisibility,\\n\\t\\t\\t\\tbuffer: {\\n\\t\\t\\t\\t\\ttype: \\\"uniform\\\",\\n\\t\\t\\t\\t\\t// \\\"uniform\\\", \\\"storage\\\", \\\"read-only-storage\\\"\\n\\t\\t\\t\\t\\t// whether this binding requires a dynamic offset\\n\\t\\t\\t\\t\\t// currently all UBs are dynamic and need the offset\\n\\t\\t\\t\\t\\thasDynamicOffset: true\\n\\t\\t\\t\\t\\t// defaults to 0 meaning no validation, can do early size validation using it\\n\\t\\t\\t\\t\\t// minBindingSize\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t});\\n\\t\\tbindGroupFormat.textureFormats.forEach((textureFormat) => {\\n\\t\\t\\tconst visibility = WebgpuUtils.shaderStage(textureFormat.visibility);\\n\\t\\t\\tconst sampleType = textureFormat.sampleType;\\n\\t\\t\\tconst viewDimension = textureFormat.textureDimension;\\n\\t\\t\\tconst multisampled = false;\\n\\t\\t\\tconst gpuSampleType = sampleTypes[sampleType];\\n\\t\\t\\tkey += `#${textureFormat.slot}T:${visibility}-${gpuSampleType}-${viewDimension}-${multisampled}`;\\n\\t\\t\\tentries.push({\\n\\t\\t\\t\\tbinding: textureFormat.slot,\\n\\t\\t\\t\\tvisibility,\\n\\t\\t\\t\\ttexture: {\\n\\t\\t\\t\\t\\t// Indicates the type required for texture views bound to this binding.\\n\\t\\t\\t\\t\\t// \\\"float\\\", \\\"unfilterable-float\\\", \\\"depth\\\", \\\"sint\\\", \\\"uint\\\",\\n\\t\\t\\t\\t\\tsampleType: gpuSampleType,\\n\\t\\t\\t\\t\\t// Indicates the required dimension for texture views bound to this binding.\\n\\t\\t\\t\\t\\t// \\\"1d\\\", \\\"2d\\\", \\\"2d-array\\\", \\\"cube\\\", \\\"cube-array\\\", \\\"3d\\\"\\n\\t\\t\\t\\t\\tviewDimension,\\n\\t\\t\\t\\t\\t// Indicates whether or not texture views bound to this binding must be multisampled\\n\\t\\t\\t\\t\\tmultisampled\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t\\tif (textureFormat.hasSampler) {\\n\\t\\t\\t\\tconst gpuSamplerType = samplerTypes[sampleType];\\n\\t\\t\\t\\tkey += `#${textureFormat.slot + 1}S:${visibility}-${gpuSamplerType}`;\\n\\t\\t\\t\\tentries.push({\\n\\t\\t\\t\\t\\tbinding: textureFormat.slot + 1,\\n\\t\\t\\t\\t\\tvisibility,\\n\\t\\t\\t\\t\\tsampler: {\\n\\t\\t\\t\\t\\t\\t// Indicates the required type of a sampler bound to this bindings\\n\\t\\t\\t\\t\\t\\t// 'filtering', 'non-filtering', 'comparison'\\n\\t\\t\\t\\t\\t\\ttype: gpuSamplerType\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tbindGroupFormat.storageTextureFormats.forEach((textureFormat) => {\\n\\t\\t\\tconst { format, textureDimension } = textureFormat;\\n\\t\\t\\tconst { read, write } = textureFormat;\\n\\t\\t\\tkey += `#${textureFormat.slot}ST:${format}-${textureDimension}-${read ? \\\"r1\\\" : \\\"r0\\\"}-${write ? \\\"w1\\\" : \\\"w0\\\"}`;\\n\\t\\t\\tentries.push({\\n\\t\\t\\t\\tbinding: textureFormat.slot,\\n\\t\\t\\t\\tvisibility: GPUShaderStage.COMPUTE,\\n\\t\\t\\t\\tstorageTexture: {\\n\\t\\t\\t\\t\\t// The access mode for this binding, indicating readability and writability.\\n\\t\\t\\t\\t\\t// 'write-only' is always support, 'read-write' and 'read-only' optionally\\n\\t\\t\\t\\t\\taccess: read ? write ? \\\"read-write\\\" : \\\"read-only\\\" : \\\"write-only\\\",\\n\\t\\t\\t\\t\\t// The required format of texture views bound to this binding.\\n\\t\\t\\t\\t\\tformat: gpuTextureFormats[format],\\n\\t\\t\\t\\t\\t// Indicates the required dimension for texture views bound to this binding.\\n\\t\\t\\t\\t\\t// \\\"1d\\\", \\\"2d\\\", \\\"2d-array\\\", \\\"cube\\\", \\\"cube-array\\\", \\\"3d\\\"\\n\\t\\t\\t\\t\\tviewDimension: textureDimension\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t});\\n\\t\\tbindGroupFormat.storageBufferFormats.forEach((bufferFormat) => {\\n\\t\\t\\tconst readOnly = bufferFormat.readOnly;\\n\\t\\t\\tconst visibility = WebgpuUtils.shaderStage(bufferFormat.visibility);\\n\\t\\t\\tkey += `#${bufferFormat.slot}SB:${visibility}-${readOnly ? \\\"ro\\\" : \\\"rw\\\"}`;\\n\\t\\t\\tentries.push({\\n\\t\\t\\t\\tbinding: bufferFormat.slot,\\n\\t\\t\\t\\tvisibility,\\n\\t\\t\\t\\tbuffer: {\\n\\t\\t\\t\\t\\t// \\\"storage\\\", \\\"read-only-storage\\\"\\n\\t\\t\\t\\t\\ttype: readOnly ? \\\"read-only-storage\\\" : \\\"storage\\\"\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t});\\n\\t\\tconst desc = {\\n\\t\\t\\tentries\\n\\t\\t};\\n\\t\\treturn {\\n\\t\\t\\tkey,\\n\\t\\t\\tdesc\\n\\t\\t};\\n\\t}\\n}\\n\\nclass WebgpuBuffer {\\n\\tbuffer = null;\\n\\tusageFlags = 0;\\n\\tconstructor(usageFlags = 0) {\\n\\t\\tthis.usageFlags = usageFlags;\\n\\t}\\n\\tdestroy(device) {\\n\\t\\tif (this.buffer) {\\n\\t\\t\\tdevice.deferDestroy(this.buffer);\\n\\t\\t\\tthis.buffer = null;\\n\\t\\t}\\n\\t}\\n\\tget initialized() {\\n\\t\\treturn !!this.buffer;\\n\\t}\\n\\tloseContext() {\\n\\t\\tthis.buffer = null;\\n\\t}\\n\\tallocate(device, size) {\\n\\t\\tthis.buffer = device.wgpu.createBuffer({\\n\\t\\t\\tsize,\\n\\t\\t\\tusage: this.usageFlags\\n\\t\\t});\\n\\t}\\n\\tunlock(device, storage) {\\n\\t\\tconst wgpu = device.wgpu;\\n\\t\\tif (!this.buffer) {\\n\\t\\t\\tconst size = storage.byteLength + 3 & -4;\\n\\t\\t\\tthis.usageFlags |= GPUBufferUsage.COPY_DST;\\n\\t\\t\\tthis.allocate(device, size);\\n\\t\\t}\\n\\t\\tconst srcOffset = storage.byteOffset ?? 0;\\n\\t\\tconst srcData = new Uint8Array(storage.buffer ?? storage, srcOffset, storage.byteLength);\\n\\t\\tconst data = new Uint8Array(this.buffer.size);\\n\\t\\tdata.set(srcData);\\n\\t\\twgpu.queue.writeBuffer(this.buffer, 0, data, 0, data.length);\\n\\t}\\n\\tread(device, offset, size, data, immediate) {\\n\\t\\treturn device.readStorageBuffer(this, offset, size, data, immediate);\\n\\t}\\n\\twrite(device, bufferOffset, data, dataOffset, size) {\\n\\t\\tdevice.writeStorageBuffer(this, bufferOffset, data, dataOffset, size);\\n\\t}\\n\\tclear(device, offset, size) {\\n\\t\\tdevice.clearStorageBuffer(this, offset, size);\\n\\t}\\n}\\n\\nclass WebgpuIndexBuffer extends WebgpuBuffer {\\n\\tformat = null;\\n\\tconstructor(indexBuffer, options) {\\n\\t\\tsuper(BUFFERUSAGE_INDEX | (options?.storage ? BUFFERUSAGE_STORAGE : 0));\\n\\t\\tthis.format = indexBuffer.format === INDEXFORMAT_UINT16 ? \\\"uint16\\\" : \\\"uint32\\\";\\n\\t}\\n\\tunlock(indexBuffer) {\\n\\t\\tconst device = indexBuffer.device;\\n\\t\\tsuper.unlock(device, indexBuffer.storage);\\n\\t}\\n}\\n\\nconst array$1 = {\\n\\t// helper function to compare two arrays for equality\\n\\tequals(arr1, arr2) {\\n\\t\\tif (arr1.length !== arr2.length) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < arr1.length; i++) {\\n\\t\\t\\tif (arr1[i] !== arr2[i]) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn true;\\n\\t}\\n};\\n\\nconst gpuVertexFormats = [];\\ngpuVertexFormats[TYPE_INT8] = \\\"sint8\\\";\\ngpuVertexFormats[TYPE_UINT8] = \\\"uint8\\\";\\ngpuVertexFormats[TYPE_INT16] = \\\"sint16\\\";\\ngpuVertexFormats[TYPE_UINT16] = \\\"uint16\\\";\\ngpuVertexFormats[TYPE_INT32] = \\\"sint32\\\";\\ngpuVertexFormats[TYPE_UINT32] = \\\"uint32\\\";\\ngpuVertexFormats[TYPE_FLOAT32] = \\\"float32\\\";\\ngpuVertexFormats[TYPE_FLOAT16] = \\\"float16\\\";\\nconst gpuVertexFormatsNormalized = [];\\ngpuVertexFormatsNormalized[TYPE_INT8] = \\\"snorm8\\\";\\ngpuVertexFormatsNormalized[TYPE_UINT8] = \\\"unorm8\\\";\\ngpuVertexFormatsNormalized[TYPE_INT16] = \\\"snorm16\\\";\\ngpuVertexFormatsNormalized[TYPE_UINT16] = \\\"unorm16\\\";\\ngpuVertexFormatsNormalized[TYPE_INT32] = \\\"sint32\\\";\\ngpuVertexFormatsNormalized[TYPE_UINT32] = \\\"uint32\\\";\\ngpuVertexFormatsNormalized[TYPE_FLOAT32] = \\\"float32\\\";\\ngpuVertexFormatsNormalized[TYPE_FLOAT16] = \\\"float16\\\";\\nclass WebgpuVertexBufferLayout {\\n\\tcache = /* @__PURE__ */ new Map();\\n\\tget(vertexFormat0, vertexFormat1 = null) {\\n\\t\\tconst key = this.getKey(vertexFormat0, vertexFormat1);\\n\\t\\tlet layout = this.cache.get(key);\\n\\t\\tif (!layout) {\\n\\t\\t\\tlayout = this.create(vertexFormat0, vertexFormat1);\\n\\t\\t\\tthis.cache.set(key, layout);\\n\\t\\t}\\n\\t\\treturn layout;\\n\\t}\\n\\tgetKey(vertexFormat0, vertexFormat1 = null) {\\n\\t\\treturn `${vertexFormat0?.renderingHashString}-${vertexFormat1?.renderingHashString}`;\\n\\t}\\n\\tcreate(vertexFormat0, vertexFormat1) {\\n\\t\\tconst layout = [];\\n\\t\\tconst addFormat = (format) => {\\n\\t\\t\\tconst interleaved = format.interleaved;\\n\\t\\t\\tconst stepMode = format.instancing ? \\\"instance\\\" : \\\"vertex\\\";\\n\\t\\t\\tlet attributes = [];\\n\\t\\t\\tconst elementCount = format.elements.length;\\n\\t\\t\\tfor (let i = 0; i < elementCount; i++) {\\n\\t\\t\\t\\tconst element = format.elements[i];\\n\\t\\t\\t\\tconst location = semanticToLocation[element.name];\\n\\t\\t\\t\\tconst formatTable = element.normalize ? gpuVertexFormatsNormalized : gpuVertexFormats;\\n\\t\\t\\t\\tattributes.push({\\n\\t\\t\\t\\t\\tshaderLocation: location,\\n\\t\\t\\t\\t\\toffset: interleaved ? element.offset : 0,\\n\\t\\t\\t\\t\\tformat: `${formatTable[element.dataType]}${element.numComponents > 1 ? `x${element.numComponents}` : \\\"\\\"}`\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (!interleaved || i === elementCount - 1) {\\n\\t\\t\\t\\t\\tlayout.push({\\n\\t\\t\\t\\t\\t\\tattributes,\\n\\t\\t\\t\\t\\t\\tarrayStride: element.stride,\\n\\t\\t\\t\\t\\t\\tstepMode\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\tattributes = [];\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tif (vertexFormat0) {\\n\\t\\t\\taddFormat(vertexFormat0);\\n\\t\\t}\\n\\t\\tif (vertexFormat1) {\\n\\t\\t\\taddFormat(vertexFormat1);\\n\\t\\t}\\n\\t\\treturn layout;\\n\\t}\\n}\\n\\nclass WebgpuPipeline {\\n\\tconstructor(device) {\\n\\t\\tthis.device = device;\\n\\t}\\n\\t// TODO: this could be cached using bindGroupKey\\n\\tgetPipelineLayout(bindGroupFormats) {\\n\\t\\tconst bindGroupLayouts = [];\\n\\t\\tbindGroupFormats.forEach((format) => {\\n\\t\\t\\tbindGroupLayouts.push(format.bindGroupLayout);\\n\\t\\t});\\n\\t\\tconst desc = {\\n\\t\\t\\tbindGroupLayouts\\n\\t\\t};\\n\\t\\tconst pipelineLayout = this.device.wgpu.createPipelineLayout(desc);\\n\\t\\treturn pipelineLayout;\\n\\t}\\n}\\n\\nconst _primitiveTopology = [\\n\\t\\\"point-list\\\",\\n\\t// PRIMITIVE_POINTS\\n\\t\\\"line-list\\\",\\n\\t// PRIMITIVE_LINES\\n\\tvoid 0,\\n\\t// PRIMITIVE_LINELOOP\\n\\t\\\"line-strip\\\",\\n\\t// PRIMITIVE_LINESTRIP\\n\\t\\\"triangle-list\\\",\\n\\t// PRIMITIVE_TRIANGLES\\n\\t\\\"triangle-strip\\\",\\n\\t// PRIMITIVE_TRISTRIP\\n\\tvoid 0\\n\\t// PRIMITIVE_TRIFAN\\n];\\nconst _blendOperation = [\\n\\t\\\"add\\\",\\n\\t// BLENDEQUATION_ADD\\n\\t\\\"subtract\\\",\\n\\t// BLENDEQUATION_SUBTRACT\\n\\t\\\"reverse-subtract\\\",\\n\\t// BLENDEQUATION_REVERSE_SUBTRACT\\n\\t\\\"min\\\",\\n\\t// BLENDEQUATION_MIN\\n\\t\\\"max\\\"\\n\\t// BLENDEQUATION_MAX\\n];\\nconst _blendFactor = [\\n\\t\\\"zero\\\",\\n\\t// BLENDMODE_ZERO\\n\\t\\\"one\\\",\\n\\t// BLENDMODE_ONE\\n\\t\\\"src\\\",\\n\\t// BLENDMODE_SRC_COLOR\\n\\t\\\"one-minus-src\\\",\\n\\t// BLENDMODE_ONE_MINUS_SRC_COLOR\\n\\t\\\"dst\\\",\\n\\t// BLENDMODE_DST_COLOR\\n\\t\\\"one-minus-dst\\\",\\n\\t// BLENDMODE_ONE_MINUS_DST_COLOR\\n\\t\\\"src-alpha\\\",\\n\\t// BLENDMODE_SRC_ALPHA\\n\\t\\\"src-alpha-saturated\\\",\\n\\t// BLENDMODE_SRC_ALPHA_SATURATE\\n\\t\\\"one-minus-src-alpha\\\",\\n\\t// BLENDMODE_ONE_MINUS_SRC_ALPHA\\n\\t\\\"dst-alpha\\\",\\n\\t// BLENDMODE_DST_ALPHA\\n\\t\\\"one-minus-dst-alpha\\\",\\n\\t// BLENDMODE_ONE_MINUS_DST_ALPHA\\n\\t\\\"constant\\\",\\n\\t// BLENDMODE_CONSTANT\\n\\t\\\"one-minus-constant\\\"\\n\\t// BLENDMODE_ONE_MINUS_CONSTANT\\n];\\nconst _compareFunction = [\\n\\t\\\"never\\\",\\n\\t// FUNC_NEVER\\n\\t\\\"less\\\",\\n\\t// FUNC_LESS\\n\\t\\\"equal\\\",\\n\\t// FUNC_EQUAL\\n\\t\\\"less-equal\\\",\\n\\t// FUNC_LESSEQUAL\\n\\t\\\"greater\\\",\\n\\t// FUNC_GREATER\\n\\t\\\"not-equal\\\",\\n\\t// FUNC_NOTEQUAL\\n\\t\\\"greater-equal\\\",\\n\\t// FUNC_GREATEREQUAL\\n\\t\\\"always\\\"\\n\\t// FUNC_ALWAYS\\n];\\nconst _cullModes = [\\n\\t\\\"none\\\",\\n\\t// CULLFACE_NONE\\n\\t\\\"back\\\",\\n\\t// CULLFACE_BACK\\n\\t\\\"front\\\"\\n\\t// CULLFACE_FRONT\\n];\\nconst _frontFace = [\\n\\t\\\"ccw\\\",\\n\\t// FRONTFACE_CCW\\n\\t\\\"cw\\\"\\n\\t// FRONTFACE_CW\\n];\\nconst _stencilOps = [\\n\\t\\\"keep\\\",\\n\\t// STENCILOP_KEEP\\n\\t\\\"zero\\\",\\n\\t// STENCILOP_ZERO\\n\\t\\\"replace\\\",\\n\\t// STENCILOP_REPLACE\\n\\t\\\"increment-clamp\\\",\\n\\t// STENCILOP_INCREMENT\\n\\t\\\"increment-wrap\\\",\\n\\t// STENCILOP_INCREMENTWRAP\\n\\t\\\"decrement-clamp\\\",\\n\\t// STENCILOP_DECREMENT\\n\\t\\\"decrement-wrap\\\",\\n\\t// STENCILOP_DECREMENTWRAP\\n\\t\\\"invert\\\"\\n\\t// STENCILOP_INVERT\\n];\\nconst _indexFormat = [\\n\\t\\\"\\\",\\n\\t// INDEXFORMAT_UINT8\\n\\t\\\"uint16\\\",\\n\\t// INDEXFORMAT_UINT16\\n\\t\\\"uint32\\\"\\n\\t// INDEXFORMAT_UINT32\\n];\\nlet CacheEntry$1 = class CacheEntry {\\n\\tpipeline;\\n\\thashes;\\n};\\nclass WebgpuRenderPipeline extends WebgpuPipeline {\\n\\tlookupHashes = new Uint32Array(15);\\n\\tconstructor(device) {\\n\\t\\tsuper(device);\\n\\t\\tthis.vertexBufferLayout = new WebgpuVertexBufferLayout();\\n\\t\\tthis.cache = /* @__PURE__ */ new Map();\\n\\t}\\n\\tget(primitive, vertexFormat0, vertexFormat1, ibFormat, shader, renderTarget, bindGroupFormats, blendState, depthState, cullMode, stencilEnabled, stencilFront, stencilBack, frontFace) {\\n\\t\\tconst primitiveType = primitive.type;\\n\\t\\tif (ibFormat && primitiveType !== PRIMITIVE_LINESTRIP && primitiveType !== PRIMITIVE_TRISTRIP) {\\n\\t\\t\\tibFormat = void 0;\\n\\t\\t}\\n\\t\\tconst lookupHashes = this.lookupHashes;\\n\\t\\tlookupHashes[0] = primitiveType;\\n\\t\\tlookupHashes[1] = shader.id;\\n\\t\\tlookupHashes[2] = cullMode;\\n\\t\\tlookupHashes[3] = depthState.key;\\n\\t\\tlookupHashes[4] = blendState.key;\\n\\t\\tlookupHashes[5] = vertexFormat0?.renderingHash ?? 0;\\n\\t\\tlookupHashes[6] = vertexFormat1?.renderingHash ?? 0;\\n\\t\\tlookupHashes[7] = renderTarget.impl.key;\\n\\t\\tlookupHashes[8] = bindGroupFormats[0]?.key ?? 0;\\n\\t\\tlookupHashes[9] = bindGroupFormats[1]?.key ?? 0;\\n\\t\\tlookupHashes[10] = bindGroupFormats[2]?.key ?? 0;\\n\\t\\tlookupHashes[11] = stencilEnabled ? stencilFront.key : 0;\\n\\t\\tlookupHashes[12] = stencilEnabled ? stencilBack.key : 0;\\n\\t\\tlookupHashes[13] = ibFormat ?? 0;\\n\\t\\tlookupHashes[14] = frontFace;\\n\\t\\tconst hash = hash32Fnv1a(lookupHashes);\\n\\t\\tlet cacheEntries = this.cache.get(hash);\\n\\t\\tif (cacheEntries) {\\n\\t\\t\\tfor (let i = 0; i < cacheEntries.length; i++) {\\n\\t\\t\\t\\tconst entry = cacheEntries[i];\\n\\t\\t\\t\\tif (array$1.equals(entry.hashes, lookupHashes)) {\\n\\t\\t\\t\\t\\treturn entry.pipeline;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst primitiveTopology = _primitiveTopology[primitiveType];\\n\\t\\tconst pipelineLayout = this.getPipelineLayout(bindGroupFormats);\\n\\t\\tconst vertexBufferLayout = this.vertexBufferLayout.get(vertexFormat0, vertexFormat1);\\n\\t\\tconst cacheEntry = new CacheEntry$1();\\n\\t\\tcacheEntry.hashes = new Uint32Array(lookupHashes);\\n\\t\\tcacheEntry.pipeline = this.create(\\n\\t\\t\\tprimitiveTopology,\\n\\t\\t\\tibFormat,\\n\\t\\t\\tshader,\\n\\t\\t\\trenderTarget,\\n\\t\\t\\tpipelineLayout,\\n\\t\\t\\tblendState,\\n\\t\\t\\tdepthState,\\n\\t\\t\\tvertexBufferLayout,\\n\\t\\t\\tcullMode,\\n\\t\\t\\tstencilEnabled,\\n\\t\\t\\tstencilFront,\\n\\t\\t\\tstencilBack,\\n\\t\\t\\tfrontFace\\n\\t\\t);\\n\\t\\tif (cacheEntries) {\\n\\t\\t\\tcacheEntries.push(cacheEntry);\\n\\t\\t} else {\\n\\t\\t\\tcacheEntries = [cacheEntry];\\n\\t\\t}\\n\\t\\tthis.cache.set(hash, cacheEntries);\\n\\t\\treturn cacheEntry.pipeline;\\n\\t}\\n\\tgetBlend(blendState) {\\n\\t\\tlet blend;\\n\\t\\tif (blendState.blend) {\\n\\t\\t\\tblend = {\\n\\t\\t\\t\\tcolor: {\\n\\t\\t\\t\\t\\toperation: _blendOperation[blendState.colorOp],\\n\\t\\t\\t\\t\\tsrcFactor: _blendFactor[blendState.colorSrcFactor],\\n\\t\\t\\t\\t\\tdstFactor: _blendFactor[blendState.colorDstFactor]\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\talpha: {\\n\\t\\t\\t\\t\\toperation: _blendOperation[blendState.alphaOp],\\n\\t\\t\\t\\t\\tsrcFactor: _blendFactor[blendState.alphaSrcFactor],\\n\\t\\t\\t\\t\\tdstFactor: _blendFactor[blendState.alphaDstFactor]\\n\\t\\t\\t\\t}\\n\\t\\t\\t};\\n\\t\\t}\\n\\t\\treturn blend;\\n\\t}\\n\\tgetDepthStencil(depthState, renderTarget, stencilEnabled, stencilFront, stencilBack, primitiveTopology) {\\n\\t\\tlet depthStencil;\\n\\t\\tconst { depth, stencil } = renderTarget;\\n\\t\\tif (depth || stencil) {\\n\\t\\t\\tdepthStencil = {\\n\\t\\t\\t\\tformat: renderTarget.impl.depthAttachment.format\\n\\t\\t\\t};\\n\\t\\t\\tif (depth) {\\n\\t\\t\\t\\tdepthStencil.depthWriteEnabled = depthState.write;\\n\\t\\t\\t\\tdepthStencil.depthCompare = _compareFunction[depthState.func];\\n\\t\\t\\t\\tconst biasAllowed = primitiveTopology === \\\"triangle-list\\\" || primitiveTopology === \\\"triangle-strip\\\";\\n\\t\\t\\t\\tdepthStencil.depthBias = biasAllowed ? depthState.depthBias : 0;\\n\\t\\t\\t\\tdepthStencil.depthBiasSlopeScale = biasAllowed ? depthState.depthBiasSlope : 0;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tdepthStencil.depthWriteEnabled = false;\\n\\t\\t\\t\\tdepthStencil.depthCompare = \\\"always\\\";\\n\\t\\t\\t}\\n\\t\\t\\tif (stencil && stencilEnabled) {\\n\\t\\t\\t\\tdepthStencil.stencilReadMas = stencilFront.readMask;\\n\\t\\t\\t\\tdepthStencil.stencilWriteMask = stencilFront.writeMask;\\n\\t\\t\\t\\tdepthStencil.stencilFront = {\\n\\t\\t\\t\\t\\tcompare: _compareFunction[stencilFront.func],\\n\\t\\t\\t\\t\\tfailOp: _stencilOps[stencilFront.fail],\\n\\t\\t\\t\\t\\tpassOp: _stencilOps[stencilFront.zpass],\\n\\t\\t\\t\\t\\tdepthFailOp: _stencilOps[stencilFront.zfail]\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tdepthStencil.stencilBack = {\\n\\t\\t\\t\\t\\tcompare: _compareFunction[stencilBack.func],\\n\\t\\t\\t\\t\\tfailOp: _stencilOps[stencilBack.fail],\\n\\t\\t\\t\\t\\tpassOp: _stencilOps[stencilBack.zpass],\\n\\t\\t\\t\\t\\tdepthFailOp: _stencilOps[stencilBack.zfail]\\n\\t\\t\\t\\t};\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn depthStencil;\\n\\t}\\n\\tcreate(primitiveTopology, ibFormat, shader, renderTarget, pipelineLayout, blendState, depthState, vertexBufferLayout, cullMode, stencilEnabled, stencilFront, stencilBack, frontFace) {\\n\\t\\tconst wgpu = this.device.wgpu;\\n\\t\\tconst webgpuShader = shader.impl;\\n\\t\\tconst desc = {\\n\\t\\t\\tvertex: {\\n\\t\\t\\t\\tmodule: webgpuShader.getVertexShaderModule(),\\n\\t\\t\\t\\tentryPoint: webgpuShader.vertexEntryPoint,\\n\\t\\t\\t\\tbuffers: vertexBufferLayout\\n\\t\\t\\t},\\n\\t\\t\\tprimitive: {\\n\\t\\t\\t\\ttopology: primitiveTopology,\\n\\t\\t\\t\\tfrontFace: _frontFace[frontFace],\\n\\t\\t\\t\\tcullMode: _cullModes[cullMode]\\n\\t\\t\\t},\\n\\t\\t\\tdepthStencil: this.getDepthStencil(depthState, renderTarget, stencilEnabled, stencilFront, stencilBack, primitiveTopology),\\n\\t\\t\\tmultisample: {\\n\\t\\t\\t\\tcount: renderTarget.samples\\n\\t\\t\\t},\\n\\t\\t\\t// uniform / texture binding layout\\n\\t\\t\\tlayout: pipelineLayout\\n\\t\\t};\\n\\t\\tif (ibFormat) {\\n\\t\\t\\tdesc.primitive.stripIndexFormat = _indexFormat[ibFormat];\\n\\t\\t}\\n\\t\\tdesc.fragment = {\\n\\t\\t\\tmodule: webgpuShader.getFragmentShaderModule(),\\n\\t\\t\\tentryPoint: webgpuShader.fragmentEntryPoint,\\n\\t\\t\\ttargets: []\\n\\t\\t};\\n\\t\\tconst colorAttachments = renderTarget.impl.colorAttachments;\\n\\t\\tif (colorAttachments.length > 0) {\\n\\t\\t\\tlet writeMask = 0;\\n\\t\\t\\tif (blendState.redWrite) writeMask |= GPUColorWrite.RED;\\n\\t\\t\\tif (blendState.greenWrite) writeMask |= GPUColorWrite.GREEN;\\n\\t\\t\\tif (blendState.blueWrite) writeMask |= GPUColorWrite.BLUE;\\n\\t\\t\\tif (blendState.alphaWrite) writeMask |= GPUColorWrite.ALPHA;\\n\\t\\t\\tconst blend = this.getBlend(blendState);\\n\\t\\t\\tcolorAttachments.forEach((attachment) => {\\n\\t\\t\\t\\tdesc.fragment.targets.push({\\n\\t\\t\\t\\t\\tformat: attachment.format,\\n\\t\\t\\t\\t\\twriteMask,\\n\\t\\t\\t\\t\\tblend\\n\\t\\t\\t\\t});\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tconst pipeline = wgpu.createRenderPipeline(desc);\\n\\t\\treturn pipeline;\\n\\t}\\n}\\n\\nclass CacheEntry {\\n\\tpipeline = null;\\n\\thashes = null;\\n}\\nclass WebgpuComputePipeline extends WebgpuPipeline {\\n\\tlookupHashes = new Uint32Array(2);\\n\\tcache = /* @__PURE__ */ new Map();\\n\\tget(shader, bindGroupFormat) {\\n\\t\\tconst lookupHashes = this.lookupHashes;\\n\\t\\tlookupHashes[0] = shader.impl.computeKey;\\n\\t\\tlookupHashes[1] = bindGroupFormat.impl.key;\\n\\t\\tconst hash = hash32Fnv1a(lookupHashes);\\n\\t\\tlet cacheEntries = this.cache.get(hash);\\n\\t\\tif (cacheEntries) {\\n\\t\\t\\tfor (let i = 0; i < cacheEntries.length; i++) {\\n\\t\\t\\t\\tconst entry = cacheEntries[i];\\n\\t\\t\\t\\tif (array$1.equals(entry.hashes, lookupHashes)) {\\n\\t\\t\\t\\t\\treturn entry.pipeline;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst pipelineLayout = this.getPipelineLayout([bindGroupFormat.impl]);\\n\\t\\tconst cacheEntry = new CacheEntry();\\n\\t\\tcacheEntry.hashes = new Uint32Array(lookupHashes);\\n\\t\\tcacheEntry.pipeline = this.create(shader, pipelineLayout);\\n\\t\\tif (cacheEntries) {\\n\\t\\t\\tcacheEntries.push(cacheEntry);\\n\\t\\t} else {\\n\\t\\t\\tcacheEntries = [cacheEntry];\\n\\t\\t}\\n\\t\\tthis.cache.set(hash, cacheEntries);\\n\\t\\treturn cacheEntry.pipeline;\\n\\t}\\n\\tcreate(shader, pipelineLayout) {\\n\\t\\tconst wgpu = this.device.wgpu;\\n\\t\\tconst webgpuShader = shader.impl;\\n\\t\\tconst desc = {\\n\\t\\t\\tcompute: {\\n\\t\\t\\t\\tmodule: webgpuShader.getComputeShaderModule(),\\n\\t\\t\\t\\tentryPoint: webgpuShader.computeEntryPoint\\n\\t\\t\\t},\\n\\t\\t\\t// uniform / texture binding layout\\n\\t\\t\\tlayout: pipelineLayout\\n\\t\\t};\\n\\t\\tconst pipeline = wgpu.createComputePipeline(desc);\\n\\t\\treturn pipeline;\\n\\t}\\n}\\n\\nclass RefCountedObject {\\n\\t_refCount = 0;\\n\\tincRefCount() {\\n\\t\\tthis._refCount++;\\n\\t}\\n\\tdecRefCount() {\\n\\t\\tthis._refCount--;\\n\\t}\\n\\tget refCount() {\\n\\t\\treturn this._refCount;\\n\\t}\\n}\\n\\nclass Entry extends RefCountedObject {\\n\\tobject;\\n\\tconstructor(obj) {\\n\\t\\tsuper();\\n\\t\\tthis.object = obj;\\n\\t\\tthis.incRefCount();\\n\\t}\\n}\\nclass RefCountedKeyCache {\\n\\tcache = /* @__PURE__ */ new Map();\\n\\tdestroy() {\\n\\t\\tthis.cache.forEach((entry) => {\\n\\t\\t\\tentry.object?.destroy();\\n\\t\\t});\\n\\t\\tthis.cache.clear();\\n\\t}\\n\\tclear() {\\n\\t\\tthis.cache.clear();\\n\\t}\\n\\tget(key) {\\n\\t\\tconst entry = this.cache.get(key);\\n\\t\\tif (entry) {\\n\\t\\t\\tentry.incRefCount();\\n\\t\\t\\treturn entry.object;\\n\\t\\t}\\n\\t\\treturn null;\\n\\t}\\n\\tset(key, object) {\\n\\t\\tthis.cache.set(key, new Entry(object));\\n\\t}\\n\\trelease(key) {\\n\\t\\tconst entry = this.cache.get(key);\\n\\t\\tif (entry) {\\n\\t\\t\\tentry.decRefCount();\\n\\t\\t\\tif (entry.refCount === 0) {\\n\\t\\t\\t\\tthis.cache.delete(key);\\n\\t\\t\\t\\tentry.object?.destroy();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\n\\nclass MultisampledTextureCache extends RefCountedKeyCache {\\n\\tloseContext(device) {\\n\\t\\tthis.clear();\\n\\t}\\n}\\nconst multisampledTextureCache = new DeviceCache();\\nconst getMultisampledTextureCache = (device) => {\\n\\treturn multisampledTextureCache.get(device, () => {\\n\\t\\treturn new MultisampledTextureCache();\\n\\t});\\n};\\n\\nconst stringIds = new StringIds();\\nclass ColorAttachment {\\n\\tformat;\\n\\tmultisampledBuffer;\\n\\tdestroy(device) {\\n\\t\\tdevice.deferDestroy(this.multisampledBuffer);\\n\\t\\tthis.multisampledBuffer = null;\\n\\t}\\n}\\nclass DepthAttachment {\\n\\tformat;\\n\\thasStencil;\\n\\tdepthTexture = null;\\n\\tdepthTextureInternal = false;\\n\\tmultisampledDepthBuffer = null;\\n\\tmultisampledDepthBufferKey;\\n\\tconstructor(gpuFormat) {\\n\\t\\tthis.format = gpuFormat;\\n\\t\\tthis.hasStencil = gpuFormat === \\\"depth24plus-stencil8\\\";\\n\\t}\\n\\tdestroy(device) {\\n\\t\\tif (this.depthTextureInternal) {\\n\\t\\t\\tdevice.deferDestroy(this.depthTexture);\\n\\t\\t\\tthis.depthTexture = null;\\n\\t\\t}\\n\\t\\tif (this.multisampledDepthBuffer) {\\n\\t\\t\\tthis.multisampledDepthBuffer = null;\\n\\t\\t\\tgetMultisampledTextureCache(device).release(this.multisampledDepthBufferKey);\\n\\t\\t}\\n\\t}\\n}\\nclass WebgpuRenderTarget {\\n\\tinitialized = false;\\n\\tkey;\\n\\tcolorAttachments = [];\\n\\tdepthAttachment = null;\\n\\tassignedColorTexture = null;\\n\\trenderPassDescriptor = {};\\n\\tisBackbuffer = false;\\n\\tconstructor(renderTarget) {\\n\\t\\tthis.renderTarget = renderTarget;\\n\\t}\\n\\tdestroy(device) {\\n\\t\\tthis.initialized = false;\\n\\t\\tthis.assignedColorTexture = null;\\n\\t\\tthis.colorAttachments.forEach((colorAttachment) => {\\n\\t\\t\\tcolorAttachment.destroy(device);\\n\\t\\t});\\n\\t\\tthis.colorAttachments.length = 0;\\n\\t\\tthis.depthAttachment?.destroy(device);\\n\\t\\tthis.depthAttachment = null;\\n\\t}\\n\\tupdateKey() {\\n\\t\\tconst rt = this.renderTarget;\\n\\t\\tlet key = `${rt.samples}:${this.depthAttachment ? this.depthAttachment.format : \\\"nodepth\\\"}`;\\n\\t\\tthis.colorAttachments.forEach((colorAttachment) => {\\n\\t\\t\\tkey += `:${colorAttachment.format}`;\\n\\t\\t});\\n\\t\\tthis.key = stringIds.get(key);\\n\\t}\\n\\tassignColorTexture(gpuTexture, viewFormat) {\\n\\t\\tthis.assignedColorTexture = gpuTexture;\\n\\t\\tconst wgpuDevice = this.renderTarget.device;\\n\\t\\tconst xrViewDesc = wgpuDevice?.xrColorTextureViewDescriptor;\\n\\t\\tconst xrSlice = xrViewDesc && gpuTexture === wgpuDevice.xrColorTexture;\\n\\t\\tconst view = gpuTexture.createView(\\n\\t\\t\\txrSlice ? xrViewDesc : { format: viewFormat }\\n\\t\\t);\\n\\t\\tconst colorAttachment = this.renderPassDescriptor.colorAttachments[0];\\n\\t\\tconst samples = this.renderTarget.samples;\\n\\t\\tif (samples > 1) {\\n\\t\\t\\tcolorAttachment.resolveTarget = view;\\n\\t\\t} else {\\n\\t\\t\\tcolorAttachment.view = view;\\n\\t\\t}\\n\\t\\tthis.setColorAttachment(0, void 0, viewFormat);\\n\\t\\tthis.updateKey();\\n\\t}\\n\\tsetColorAttachment(index, multisampledBuffer, format) {\\n\\t\\tif (!this.colorAttachments[index]) {\\n\\t\\t\\tthis.colorAttachments[index] = new ColorAttachment();\\n\\t\\t}\\n\\t\\tif (multisampledBuffer) {\\n\\t\\t\\tthis.colorAttachments[index].multisampledBuffer = multisampledBuffer;\\n\\t\\t}\\n\\t\\tif (format) {\\n\\t\\t\\tthis.colorAttachments[index].format = format;\\n\\t\\t}\\n\\t}\\n\\tinit(device, renderTarget) {\\n\\t\\tconst wgpu = device.wgpu;\\n\\t\\tthis.initDepthStencil(device, wgpu, renderTarget);\\n\\t\\tif (renderTarget._colorBuffers) {\\n\\t\\t\\trenderTarget._colorBuffers.forEach((colorBuffer, index) => {\\n\\t\\t\\t\\tthis.setColorAttachment(index, void 0, colorBuffer.impl.format);\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tthis.renderPassDescriptor.colorAttachments = [];\\n\\t\\tconst count = this.isBackbuffer ? 1 : renderTarget._colorBuffers?.length ?? 0;\\n\\t\\tfor (let i = 0; i < count; ++i) {\\n\\t\\t\\tconst colorAttachment = this.initColor(device, wgpu, renderTarget, i);\\n\\t\\t\\tconst isDefaultFramebuffer = i === 0 && this.colorAttachments[0]?.format;\\n\\t\\t\\tif (colorAttachment.view || isDefaultFramebuffer) {\\n\\t\\t\\t\\tthis.renderPassDescriptor.colorAttachments.push(colorAttachment);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.updateKey();\\n\\t\\tthis.initialized = true;\\n\\t}\\n\\tinitDepthStencil(device, wgpu, renderTarget) {\\n\\t\\tconst { samples, width, height, depth, depthBuffer } = renderTarget;\\n\\t\\tif (depth || depthBuffer) {\\n\\t\\t\\tlet renderingView;\\n\\t\\t\\tif (!depthBuffer) {\\n\\t\\t\\t\\tthis.depthAttachment = new DepthAttachment(\\\"depth24plus-stencil8\\\");\\n\\t\\t\\t\\tconst depthTextureDesc = {\\n\\t\\t\\t\\t\\tsize: [width, height, 1],\\n\\t\\t\\t\\t\\tdimension: \\\"2d\\\",\\n\\t\\t\\t\\t\\tsampleCount: samples,\\n\\t\\t\\t\\t\\tformat: this.depthAttachment.format,\\n\\t\\t\\t\\t\\tusage: GPUTextureUsage.RENDER_ATTACHMENT\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (samples > 1) {\\n\\t\\t\\t\\t\\tdepthTextureDesc.usage |= GPUTextureUsage.TEXTURE_BINDING;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tdepthTextureDesc.usage |= GPUTextureUsage.COPY_SRC;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst depthTexture = wgpu.createTexture(depthTextureDesc);\\n\\t\\t\\t\\tthis.depthAttachment.depthTexture = depthTexture;\\n\\t\\t\\t\\tthis.depthAttachment.depthTextureInternal = true;\\n\\t\\t\\t\\trenderingView = depthTexture.createView();\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.depthAttachment = new DepthAttachment(depthBuffer.impl.format);\\n\\t\\t\\t\\tif (samples > 1) {\\n\\t\\t\\t\\t\\tconst depthFormat = \\\"depth24plus-stencil8\\\";\\n\\t\\t\\t\\t\\tthis.depthAttachment.format = depthFormat;\\n\\t\\t\\t\\t\\tthis.depthAttachment.hasStencil = depthFormat === \\\"depth24plus-stencil8\\\";\\n\\t\\t\\t\\t\\tconst key = `${depthBuffer.id}:${width}:${height}:${samples}:${depthFormat}`;\\n\\t\\t\\t\\t\\tconst msTextures = getMultisampledTextureCache(device);\\n\\t\\t\\t\\t\\tlet msDepthTexture = msTextures.get(key);\\n\\t\\t\\t\\t\\tif (!msDepthTexture) {\\n\\t\\t\\t\\t\\t\\tconst multisampledDepthDesc = {\\n\\t\\t\\t\\t\\t\\t\\tsize: [width, height, 1],\\n\\t\\t\\t\\t\\t\\t\\tdimension: \\\"2d\\\",\\n\\t\\t\\t\\t\\t\\t\\tsampleCount: samples,\\n\\t\\t\\t\\t\\t\\t\\tformat: depthFormat,\\n\\t\\t\\t\\t\\t\\t\\tusage: GPUTextureUsage.RENDER_ATTACHMENT | // if msaa and resolve targets are different formats, we need to be able to bind the msaa target as a texture for manual shader resolve\\n\\t\\t\\t\\t\\t\\t\\t(depthFormat !== depthBuffer.impl.format ? GPUTextureUsage.TEXTURE_BINDING : 0)\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tmsDepthTexture = wgpu.createTexture(multisampledDepthDesc);\\n\\t\\t\\t\\t\\t\\tmsTextures.set(key, msDepthTexture);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tthis.depthAttachment.multisampledDepthBuffer = msDepthTexture;\\n\\t\\t\\t\\t\\tthis.depthAttachment.multisampledDepthBufferKey = key;\\n\\t\\t\\t\\t\\trenderingView = msDepthTexture.createView();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tconst depthTexture = depthBuffer.impl.gpuTexture;\\n\\t\\t\\t\\t\\tthis.depthAttachment.depthTexture = depthTexture;\\n\\t\\t\\t\\t\\trenderingView = depthTexture.createView();\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis.renderPassDescriptor.depthStencilAttachment = {\\n\\t\\t\\t\\tview: renderingView\\n\\t\\t\\t};\\n\\t\\t}\\n\\t}\\n\\tinitColor(device, wgpu, renderTarget, index) {\\n\\t\\tconst colorAttachment = {};\\n\\t\\tconst { samples, width, height, mipLevel } = renderTarget;\\n\\t\\tconst colorBuffer = renderTarget.getColorBuffer(index);\\n\\t\\tlet colorView = null;\\n\\t\\tif (colorBuffer) {\\n\\t\\t\\tconst mipLevelCount = 1;\\n\\t\\t\\tif (colorBuffer.cubemap) {\\n\\t\\t\\t\\tcolorView = colorBuffer.impl.createView({\\n\\t\\t\\t\\t\\tdimension: \\\"2d\\\",\\n\\t\\t\\t\\t\\tbaseArrayLayer: renderTarget.face,\\n\\t\\t\\t\\t\\tarrayLayerCount: 1,\\n\\t\\t\\t\\t\\tmipLevelCount,\\n\\t\\t\\t\\t\\tbaseMipLevel: mipLevel\\n\\t\\t\\t\\t});\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tcolorView = colorBuffer.impl.createView({\\n\\t\\t\\t\\t\\tmipLevelCount,\\n\\t\\t\\t\\t\\tbaseMipLevel: mipLevel\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (samples > 1) {\\n\\t\\t\\tconst format = this.isBackbuffer ? this.colorAttachments[index]?.format ?? device.backBufferViewFormat : colorBuffer.impl.format;\\n\\t\\t\\tconst multisampledTextureDesc = {\\n\\t\\t\\t\\tsize: [width, height, 1],\\n\\t\\t\\t\\tdimension: \\\"2d\\\",\\n\\t\\t\\t\\tsampleCount: samples,\\n\\t\\t\\t\\tformat,\\n\\t\\t\\t\\tusage: GPUTextureUsage.RENDER_ATTACHMENT\\n\\t\\t\\t};\\n\\t\\t\\tconst multisampledColorBuffer = wgpu.createTexture(multisampledTextureDesc);\\n\\t\\t\\tthis.setColorAttachment(index, multisampledColorBuffer, multisampledTextureDesc.format);\\n\\t\\t\\tcolorAttachment.view = multisampledColorBuffer.createView();\\n\\t\\t\\tcolorAttachment.resolveTarget = colorView;\\n\\t\\t} else {\\n\\t\\t\\tcolorAttachment.view = colorView;\\n\\t\\t}\\n\\t\\treturn colorAttachment;\\n\\t}\\n\\tsetupForRenderPass(renderPass, renderTarget) {\\n\\t\\tconst count = this.renderPassDescriptor.colorAttachments?.length ?? 0;\\n\\t\\tfor (let i = 0; i < count; ++i) {\\n\\t\\t\\tconst colorAttachment = this.renderPassDescriptor.colorAttachments[i];\\n\\t\\t\\tconst colorOps = renderPass.colorArrayOps[i];\\n\\t\\t\\tconst srgb = renderTarget.isColorBufferSrgb(i);\\n\\t\\t\\tcolorAttachment.clearValue = srgb ? colorOps.clearValueLinear : colorOps.clearValue;\\n\\t\\t\\tcolorAttachment.loadOp = colorOps.clear ? \\\"clear\\\" : \\\"load\\\";\\n\\t\\t\\tcolorAttachment.storeOp = colorOps.store ? \\\"store\\\" : \\\"discard\\\";\\n\\t\\t}\\n\\t\\tconst depthAttachment = this.renderPassDescriptor.depthStencilAttachment;\\n\\t\\tif (depthAttachment) {\\n\\t\\t\\tdepthAttachment.depthClearValue = renderPass.depthStencilOps.clearDepthValue;\\n\\t\\t\\tdepthAttachment.depthLoadOp = renderPass.depthStencilOps.clearDepth ? \\\"clear\\\" : \\\"load\\\";\\n\\t\\t\\tdepthAttachment.depthStoreOp = renderPass.depthStencilOps.storeDepth ? \\\"store\\\" : \\\"discard\\\";\\n\\t\\t\\tdepthAttachment.depthReadOnly = false;\\n\\t\\t\\tif (this.depthAttachment.hasStencil) {\\n\\t\\t\\t\\tdepthAttachment.stencilClearValue = renderPass.depthStencilOps.clearStencilValue;\\n\\t\\t\\t\\tdepthAttachment.stencilLoadOp = renderPass.depthStencilOps.clearStencil ? \\\"clear\\\" : \\\"load\\\";\\n\\t\\t\\t\\tdepthAttachment.stencilStoreOp = renderPass.depthStencilOps.storeStencil ? \\\"store\\\" : \\\"discard\\\";\\n\\t\\t\\t\\tdepthAttachment.stencilReadOnly = false;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tloseContext() {\\n\\t\\tthis.initialized = false;\\n\\t}\\n\\tresolve(device, target, color, depth) {\\n\\t}\\n}\\n\\nconst uniformTypeToNumComponents = [];\\nuniformTypeToNumComponents[UNIFORMTYPE_FLOAT] = 1;\\nuniformTypeToNumComponents[UNIFORMTYPE_VEC2] = 2;\\nuniformTypeToNumComponents[UNIFORMTYPE_VEC3] = 3;\\nuniformTypeToNumComponents[UNIFORMTYPE_VEC4] = 4;\\nuniformTypeToNumComponents[UNIFORMTYPE_INT] = 1;\\nuniformTypeToNumComponents[UNIFORMTYPE_IVEC2] = 2;\\nuniformTypeToNumComponents[UNIFORMTYPE_IVEC3] = 3;\\nuniformTypeToNumComponents[UNIFORMTYPE_IVEC4] = 4;\\nuniformTypeToNumComponents[UNIFORMTYPE_BOOL] = 1;\\nuniformTypeToNumComponents[UNIFORMTYPE_BVEC2] = 2;\\nuniformTypeToNumComponents[UNIFORMTYPE_BVEC3] = 3;\\nuniformTypeToNumComponents[UNIFORMTYPE_BVEC4] = 4;\\nuniformTypeToNumComponents[UNIFORMTYPE_MAT2] = 8;\\nuniformTypeToNumComponents[UNIFORMTYPE_MAT3] = 12;\\nuniformTypeToNumComponents[UNIFORMTYPE_MAT4] = 16;\\nuniformTypeToNumComponents[UNIFORMTYPE_UINT] = 1;\\nuniformTypeToNumComponents[UNIFORMTYPE_UVEC2] = 2;\\nuniformTypeToNumComponents[UNIFORMTYPE_UVEC3] = 3;\\nuniformTypeToNumComponents[UNIFORMTYPE_UVEC4] = 4;\\nclass UniformFormat {\\n\\tname;\\n\\t// UNIFORMTYPE_***\\n\\ttype;\\n\\tbyteSize;\\n\\toffset;\\n\\tscopeId;\\n\\tcount;\\n\\tnumComponents;\\n\\tget isArrayType() {\\n\\t\\treturn this.count > 0;\\n\\t}\\n\\tconstructor(name, type, count = 0) {\\n\\t\\tthis.shortName = name;\\n\\t\\tthis.name = count ? `${name}[0]` : name;\\n\\t\\tthis.type = type;\\n\\t\\tthis.numComponents = uniformTypeToNumComponents[type];\\n\\t\\tthis.updateType = type;\\n\\t\\tif (count > 0) {\\n\\t\\t\\tswitch (type) {\\n\\t\\t\\t\\tcase UNIFORMTYPE_FLOAT:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_FLOATARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_INT:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_INTARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_UINT:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_UINTARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_BOOL:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_BOOLARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_VEC2:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_VEC2ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_IVEC2:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_IVEC2ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_UVEC2:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_UVEC2ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_BVEC2:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_BVEC2ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_VEC3:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_VEC3ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_IVEC3:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_IVEC3ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_UVEC3:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_UVEC3ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_BVEC3:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_BVEC3ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_VEC4:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_VEC4ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_IVEC4:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_IVEC4ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_UVEC4:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_UVEC4ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_BVEC4:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_BVEC4ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_MAT4:\\n\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_MAT4ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.count = count;\\n\\t\\tlet componentSize = this.numComponents;\\n\\t\\tif (count) {\\n\\t\\t\\tcomponentSize = math.roundUp(componentSize, 4);\\n\\t\\t}\\n\\t\\tthis.byteSize = componentSize * 4;\\n\\t\\tif (count) {\\n\\t\\t\\tthis.byteSize *= count;\\n\\t\\t}\\n\\t}\\n\\t// std140 rules: https://registry.khronos.org/OpenGL/specs/gl/glspec45.core.pdf#page=159\\n\\t// TODO: this supports limited subset of functionality, arrays and arrays of structs are not supported.\\n\\tcalculateOffset(offset) {\\n\\t\\tlet alignment = this.byteSize <= 8 ? this.byteSize : 16;\\n\\t\\tif (this.count) {\\n\\t\\t\\talignment = 16;\\n\\t\\t}\\n\\t\\toffset = math.roundUp(offset, alignment);\\n\\t\\tthis.offset = offset / 4;\\n\\t}\\n}\\nclass UniformBufferFormat {\\n\\tbyteSize = 0;\\n\\tmap = /* @__PURE__ */ new Map();\\n\\tconstructor(graphicsDevice, uniforms) {\\n\\t\\tthis.scope = graphicsDevice.scope;\\n\\t\\tthis.uniforms = uniforms;\\n\\t\\tlet offset = 0;\\n\\t\\tfor (let i = 0; i < uniforms.length; i++) {\\n\\t\\t\\tconst uniform = uniforms[i];\\n\\t\\t\\tuniform.calculateOffset(offset);\\n\\t\\t\\toffset = uniform.offset * 4 + uniform.byteSize;\\n\\t\\t\\tuniform.scopeId = this.scope.resolve(uniform.name);\\n\\t\\t\\tthis.map.set(uniform.name, uniform);\\n\\t\\t}\\n\\t\\tthis.byteSize = math.roundUp(offset, 16);\\n\\t}\\n\\tget(name) {\\n\\t\\treturn this.map.get(name);\\n\\t}\\n}\\n\\nconst KEYWORD$2 = /[ \\\\t]*(\\\\battribute\\\\b|\\\\bvarying\\\\b|\\\\buniform\\\\b)/g;\\nconst KEYWORD_LINE$1 = /(\\\\battribute\\\\b|\\\\bvarying\\\\b|\\\\bout\\\\b|\\\\buniform\\\\b)[ \\\\t]*([^;]+)(;+)/g;\\nconst MARKER$1 = \\\"@@@\\\";\\nconst ARRAY_IDENTIFIER = /([\\\\w-]+)\\\\[(.*?)\\\\]/;\\nconst precisionQualifiers = /* @__PURE__ */ new Set([\\\"highp\\\", \\\"mediump\\\", \\\"lowp\\\"]);\\nconst shadowSamplers = /* @__PURE__ */ new Set([\\\"sampler2DShadow\\\", \\\"samplerCubeShadow\\\", \\\"sampler2DArrayShadow\\\"]);\\nconst textureDimensions = {\\n\\tsampler2D: TEXTUREDIMENSION_2D,\\n\\tsampler3D: TEXTUREDIMENSION_3D,\\n\\tsamplerCube: TEXTUREDIMENSION_CUBE,\\n\\tsamplerCubeShadow: TEXTUREDIMENSION_CUBE,\\n\\tsampler2DShadow: TEXTUREDIMENSION_2D,\\n\\tsampler2DArray: TEXTUREDIMENSION_2D_ARRAY,\\n\\tsampler2DArrayShadow: TEXTUREDIMENSION_2D_ARRAY,\\n\\tisampler2D: TEXTUREDIMENSION_2D,\\n\\tusampler2D: TEXTUREDIMENSION_2D,\\n\\tisampler3D: TEXTUREDIMENSION_3D,\\n\\tusampler3D: TEXTUREDIMENSION_3D,\\n\\tisamplerCube: TEXTUREDIMENSION_CUBE,\\n\\tusamplerCube: TEXTUREDIMENSION_CUBE,\\n\\tisampler2DArray: TEXTUREDIMENSION_2D_ARRAY,\\n\\tusampler2DArray: TEXTUREDIMENSION_2D_ARRAY\\n};\\nconst textureDimensionInfo = {\\n\\t[TEXTUREDIMENSION_2D]: \\\"texture2D\\\",\\n\\t[TEXTUREDIMENSION_CUBE]: \\\"textureCube\\\",\\n\\t[TEXTUREDIMENSION_3D]: \\\"texture3D\\\",\\n\\t[TEXTUREDIMENSION_2D_ARRAY]: \\\"texture2DArray\\\"\\n};\\nlet UniformLine$1 = class UniformLine {\\n\\tconstructor(line, shader) {\\n\\t\\tthis.line = line;\\n\\t\\tconst words = line.trim().split(/\\\\s+/);\\n\\t\\tif (precisionQualifiers.has(words[0])) {\\n\\t\\t\\tthis.precision = words.shift();\\n\\t\\t}\\n\\t\\tthis.type = words.shift();\\n\\t\\tif (line.includes(\\\",\\\")) ;\\n\\t\\tif (line.includes(\\\"[\\\")) {\\n\\t\\t\\tconst rest = words.join(\\\" \\\");\\n\\t\\t\\tconst match = ARRAY_IDENTIFIER.exec(rest);\\n\\t\\t\\tthis.name = match[1];\\n\\t\\t\\tthis.arraySize = Number(match[2]);\\n\\t\\t\\tif (isNaN(this.arraySize)) {\\n\\t\\t\\t\\tshader.failed = true;\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis.name = words.shift();\\n\\t\\t\\tthis.arraySize = 0;\\n\\t\\t}\\n\\t\\tthis.isSampler = this.type.indexOf(\\\"sampler\\\") !== -1;\\n\\t\\tthis.isSignedInt = this.type.indexOf(\\\"isampler\\\") !== -1;\\n\\t\\tthis.isUnsignedInt = this.type.indexOf(\\\"usampler\\\") !== -1;\\n\\t}\\n};\\nclass ShaderProcessorGLSL {\\n\\tstatic run(device, shaderDefinition, shader) {\\n\\t\\tconst varyingMap = /* @__PURE__ */ new Map();\\n\\t\\tconst vertexExtracted = ShaderProcessorGLSL.extract(shaderDefinition.vshader);\\n\\t\\tconst fragmentExtracted = ShaderProcessorGLSL.extract(shaderDefinition.fshader);\\n\\t\\tconst attributesMap = /* @__PURE__ */ new Map();\\n\\t\\tconst attributesBlock = ShaderProcessorGLSL.processAttributes(vertexExtracted.attributes, shaderDefinition.attributes, attributesMap, shaderDefinition.processingOptions);\\n\\t\\tconst vertexVaryingsBlock = ShaderProcessorGLSL.processVaryings(vertexExtracted.varyings, varyingMap, true);\\n\\t\\tconst fragmentVaryingsBlock = ShaderProcessorGLSL.processVaryings(fragmentExtracted.varyings, varyingMap, false);\\n\\t\\tconst outBlock = ShaderProcessorGLSL.processOuts(fragmentExtracted.outs);\\n\\t\\tconst concatUniforms = vertexExtracted.uniforms.concat(fragmentExtracted.uniforms);\\n\\t\\tconst uniforms = Array.from(new Set(concatUniforms));\\n\\t\\tconst parsedUniforms = uniforms.map((line) => new UniformLine$1(line, shader));\\n\\t\\tconst uniformsData = ShaderProcessorGLSL.processUniforms(device, parsedUniforms, shaderDefinition.processingOptions, shader);\\n\\t\\tconst vBlock = `${attributesBlock}\\n${vertexVaryingsBlock}\\n${uniformsData.code}`;\\n\\t\\tconst vshader = vertexExtracted.src.replace(MARKER$1, vBlock);\\n\\t\\tconst fBlock = `${fragmentVaryingsBlock}\\n${outBlock}\\n${uniformsData.code}`;\\n\\t\\tconst fshader = fragmentExtracted.src.replace(MARKER$1, fBlock);\\n\\t\\treturn {\\n\\t\\t\\tvshader,\\n\\t\\t\\tfshader,\\n\\t\\t\\tattributes: attributesMap,\\n\\t\\t\\tmeshUniformBufferFormat: uniformsData.meshUniformBufferFormat,\\n\\t\\t\\tmeshBindGroupFormat: uniformsData.meshBindGroupFormat\\n\\t\\t};\\n\\t}\\n\\t// Extract required information from the shader source code.\\n\\tstatic extract(src) {\\n\\t\\tconst attributes = [];\\n\\t\\tconst varyings = [];\\n\\t\\tconst outs = [];\\n\\t\\tconst uniforms = [];\\n\\t\\tlet replacement = `${MARKER$1}\\n`;\\n\\t\\tlet match;\\n\\t\\twhile ((match = KEYWORD$2.exec(src)) !== null) {\\n\\t\\t\\tconst keyword = match[1];\\n\\t\\t\\tswitch (keyword) {\\n\\t\\t\\t\\tcase \\\"attribute\\\":\\n\\t\\t\\t\\tcase \\\"varying\\\":\\n\\t\\t\\t\\tcase \\\"uniform\\\":\\n\\t\\t\\t\\tcase \\\"out\\\": {\\n\\t\\t\\t\\t\\tKEYWORD_LINE$1.lastIndex = match.index;\\n\\t\\t\\t\\t\\tconst lineMatch = KEYWORD_LINE$1.exec(src);\\n\\t\\t\\t\\t\\tif (keyword === \\\"attribute\\\") {\\n\\t\\t\\t\\t\\t\\tattributes.push(lineMatch[2]);\\n\\t\\t\\t\\t\\t} else if (keyword === \\\"varying\\\") {\\n\\t\\t\\t\\t\\t\\tvaryings.push(lineMatch[2]);\\n\\t\\t\\t\\t\\t} else if (keyword === \\\"out\\\") {\\n\\t\\t\\t\\t\\t\\touts.push(lineMatch[2]);\\n\\t\\t\\t\\t\\t} else if (keyword === \\\"uniform\\\") {\\n\\t\\t\\t\\t\\t\\tuniforms.push(lineMatch[2]);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tsrc = ShaderProcessorGLSL.cutOut(src, match.index, KEYWORD_LINE$1.lastIndex, replacement);\\n\\t\\t\\t\\t\\tKEYWORD$2.lastIndex = match.index + replacement.length;\\n\\t\\t\\t\\t\\treplacement = \\\"\\\";\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn {\\n\\t\\t\\tsrc,\\n\\t\\t\\tattributes,\\n\\t\\t\\tvaryings,\\n\\t\\t\\touts,\\n\\t\\t\\tuniforms\\n\\t\\t};\\n\\t}\\n\\tstatic processUniforms(device, uniforms, processingOptions, shader) {\\n\\t\\tconst uniformLinesSamplers = [];\\n\\t\\tconst uniformLinesNonSamplers = [];\\n\\t\\tuniforms.forEach((uniform) => {\\n\\t\\t\\tif (uniform.isSampler) {\\n\\t\\t\\t\\tuniformLinesSamplers.push(uniform);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tuniformLinesNonSamplers.push(uniform);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tconst meshUniforms = [];\\n\\t\\tuniformLinesNonSamplers.forEach((uniform) => {\\n\\t\\t\\tif (!processingOptions.hasUniform(uniform.name)) {\\n\\t\\t\\t\\tconst uniformType = uniformTypeToName.indexOf(uniform.type);\\n\\t\\t\\t\\tconst uniformFormat = new UniformFormat(uniform.name, uniformType, uniform.arraySize);\\n\\t\\t\\t\\tmeshUniforms.push(uniformFormat);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tif (meshUniforms.length === 0) {\\n\\t\\t\\tmeshUniforms.push(new UniformFormat(UNUSED_UNIFORM_NAME, UNIFORMTYPE_FLOAT));\\n\\t\\t}\\n\\t\\tconst meshUniformBufferFormat = meshUniforms.length ? new UniformBufferFormat(device, meshUniforms) : null;\\n\\t\\tconst textureFormats = [];\\n\\t\\tuniformLinesSamplers.forEach((uniform) => {\\n\\t\\t\\tif (!processingOptions.hasTexture(uniform.name)) {\\n\\t\\t\\t\\tlet sampleType = SAMPLETYPE_FLOAT;\\n\\t\\t\\t\\tif (uniform.isSignedInt) {\\n\\t\\t\\t\\t\\tsampleType = SAMPLETYPE_INT;\\n\\t\\t\\t\\t} else if (uniform.isUnsignedInt) {\\n\\t\\t\\t\\t\\tsampleType = SAMPLETYPE_UINT;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tif (uniform.precision === \\\"highp\\\") {\\n\\t\\t\\t\\t\\t\\tsampleType = SAMPLETYPE_UNFILTERABLE_FLOAT;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (shadowSamplers.has(uniform.type)) {\\n\\t\\t\\t\\t\\t\\tsampleType = SAMPLETYPE_DEPTH;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst dimension = textureDimensions[uniform.type];\\n\\t\\t\\t\\ttextureFormats.push(new BindTextureFormat(uniform.name, SHADERSTAGE_VERTEX | SHADERSTAGE_FRAGMENT, dimension, sampleType));\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tconst meshBindGroupFormat = new BindGroupFormat(device, textureFormats);\\n\\t\\tlet code = \\\"\\\";\\n\\t\\tprocessingOptions.uniformFormats.forEach((format, bindGroupIndex) => {\\n\\t\\t\\tif (format) {\\n\\t\\t\\t\\tcode += ShaderProcessorGLSL.getUniformShaderDeclaration(format, bindGroupIndex, 0);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tif (meshUniformBufferFormat) {\\n\\t\\t\\tcode += ShaderProcessorGLSL.getUniformShaderDeclaration(meshUniformBufferFormat, BINDGROUP_MESH_UB, 0);\\n\\t\\t}\\n\\t\\tprocessingOptions.bindGroupFormats.forEach((format, bindGroupIndex) => {\\n\\t\\t\\tif (format) {\\n\\t\\t\\t\\tcode += ShaderProcessorGLSL.getTexturesShaderDeclaration(format, bindGroupIndex);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tcode += ShaderProcessorGLSL.getTexturesShaderDeclaration(meshBindGroupFormat, BINDGROUP_MESH);\\n\\t\\treturn {\\n\\t\\t\\tcode,\\n\\t\\t\\tmeshUniformBufferFormat,\\n\\t\\t\\tmeshBindGroupFormat\\n\\t\\t};\\n\\t}\\n\\tstatic processVaryings(varyingLines, varyingMap, isVertex) {\\n\\t\\tlet block = \\\"\\\";\\n\\t\\tconst op = isVertex ? \\\"out\\\" : \\\"in\\\";\\n\\t\\tvaryingLines.forEach((line, index) => {\\n\\t\\t\\tconst words = ShaderProcessorGLSL.splitToWords(line);\\n\\t\\t\\tconst type = words.slice(0, -1).join(\\\" \\\");\\n\\t\\t\\tconst name = words[words.length - 1];\\n\\t\\t\\tif (isVertex) {\\n\\t\\t\\t\\tvaryingMap.set(name, index);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tindex = varyingMap.get(name);\\n\\t\\t\\t}\\n\\t\\t\\tblock += `layout(location = ${index}) ${op} ${type} ${name};\\n`;\\n\\t\\t});\\n\\t\\treturn block;\\n\\t}\\n\\tstatic processOuts(outsLines) {\\n\\t\\tlet block = \\\"\\\";\\n\\t\\toutsLines.forEach((line, index) => {\\n\\t\\t\\tblock += `layout(location = ${index}) out ${line};\\n`;\\n\\t\\t});\\n\\t\\treturn block;\\n\\t}\\n\\t// extract count from type ('vec3' => 3, 'float' => 1)\\n\\tstatic getTypeCount(type) {\\n\\t\\tconst lastChar = type.substring(type.length - 1);\\n\\t\\tconst num = parseInt(lastChar, 10);\\n\\t\\treturn isNaN(num) ? 1 : num;\\n\\t}\\n\\tstatic processAttributes(attributeLines, shaderDefinitionAttributes, attributesMap, processingOptions) {\\n\\t\\tlet block = \\\"\\\";\\n\\t\\tattributeLines.forEach((line) => {\\n\\t\\t\\tconst words = ShaderProcessorGLSL.splitToWords(line);\\n\\t\\t\\tlet type = words[0];\\n\\t\\t\\tlet name = words[1];\\n\\t\\t\\tif (shaderDefinitionAttributes.hasOwnProperty(name)) {\\n\\t\\t\\t\\tconst semantic = shaderDefinitionAttributes[name];\\n\\t\\t\\t\\tconst location = semanticToLocation[semantic];\\n\\t\\t\\t\\tattributesMap.set(location, name);\\n\\t\\t\\t\\tlet copyCode;\\n\\t\\t\\t\\tconst element = processingOptions.getVertexElement(semantic);\\n\\t\\t\\t\\tif (element) {\\n\\t\\t\\t\\t\\tconst dataType = element.dataType;\\n\\t\\t\\t\\t\\tif (dataType !== TYPE_FLOAT32 && dataType !== TYPE_FLOAT16 && !element.normalize && !element.asInt) {\\n\\t\\t\\t\\t\\t\\tconst attribNumElements = ShaderProcessorGLSL.getTypeCount(type);\\n\\t\\t\\t\\t\\t\\tconst newName = `_private_${name}`;\\n\\t\\t\\t\\t\\t\\tcopyCode = `vec${attribNumElements} ${name} = vec${attribNumElements}(${newName});\\n`;\\n\\t\\t\\t\\t\\t\\tname = newName;\\n\\t\\t\\t\\t\\t\\tconst isSignedType = dataType === TYPE_INT8 || dataType === TYPE_INT16 || dataType === TYPE_INT32;\\n\\t\\t\\t\\t\\t\\tif (attribNumElements === 1) {\\n\\t\\t\\t\\t\\t\\t\\ttype = isSignedType ? \\\"int\\\" : \\\"uint\\\";\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\ttype = isSignedType ? `ivec${attribNumElements}` : `uvec${attribNumElements}`;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tblock += `layout(location = ${location}) in ${type} ${name};\\n`;\\n\\t\\t\\t\\tif (copyCode) {\\n\\t\\t\\t\\t\\tblock += copyCode;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\treturn block;\\n\\t}\\n\\tstatic splitToWords(line) {\\n\\t\\tline = line.replace(/\\\\s+/g, \\\" \\\").trim();\\n\\t\\treturn line.split(\\\" \\\");\\n\\t}\\n\\tstatic cutOut(src, start, end, replacement) {\\n\\t\\treturn src.substring(0, start) + replacement + src.substring(end);\\n\\t}\\n\\tstatic getUniformShaderDeclaration(format, bindGroup, bindIndex) {\\n\\t\\tconst name = bindGroupNames[bindGroup];\\n\\t\\tlet code = `layout(set = ${bindGroup}, binding = ${bindIndex}, std140) uniform ub_${name} {\\n`;\\n\\t\\tformat.uniforms.forEach((uniform) => {\\n\\t\\t\\tconst typeString = uniformTypeToName[uniform.type];\\n\\t\\t\\tcode += `    ${typeString} ${uniform.shortName}${uniform.count ? `[${uniform.count}]` : \\\"\\\"};\\n`;\\n\\t\\t});\\n\\t\\treturn `${code}};\\n`;\\n\\t}\\n\\tstatic getTexturesShaderDeclaration(bindGroupFormat, bindGroup) {\\n\\t\\tlet code = \\\"\\\";\\n\\t\\tbindGroupFormat.textureFormats.forEach((format) => {\\n\\t\\t\\tlet textureType = textureDimensionInfo[format.textureDimension];\\n\\t\\t\\tconst isArray = textureType === \\\"texture2DArray\\\";\\n\\t\\t\\tconst sampleTypePrefix = format.sampleType === SAMPLETYPE_UINT ? \\\"u\\\" : format.sampleType === SAMPLETYPE_INT ? \\\"i\\\" : \\\"\\\";\\n\\t\\t\\ttextureType = `${sampleTypePrefix}${textureType}`;\\n\\t\\t\\tlet namePostfix = \\\"\\\";\\n\\t\\t\\tlet extraCode = \\\"\\\";\\n\\t\\t\\tif (isArray) {\\n\\t\\t\\t\\tnamePostfix = \\\"_texture\\\";\\n\\t\\t\\t\\textraCode = `#define ${format.name} ${sampleTypePrefix}sampler2DArray(${format.name}${namePostfix}, ${format.name}_sampler)\\n`;\\n\\t\\t\\t}\\n\\t\\t\\tcode += `layout(set = ${bindGroup}, binding = ${format.slot}) uniform ${textureType} ${format.name}${namePostfix};\\n`;\\n\\t\\t\\tif (format.hasSampler) {\\n\\t\\t\\t\\tcode += `layout(set = ${bindGroup}, binding = ${format.slot + 1}) uniform sampler ${format.name}_sampler;\\n`;\\n\\t\\t\\t}\\n\\t\\t\\tcode += extraCode;\\n\\t\\t});\\n\\t\\treturn code;\\n\\t}\\n}\\n\\nconst KEYWORD$1 = /^[ \\\\t]*(attribute|varying|uniform)[\\\\t ]+/gm;\\nconst KEYWORD_LINE = /^[ \\\\t]*(attribute|varying|uniform)[ \\\\t]*([^;]+)(;+)/gm;\\nconst KEYWORD_RESOURCE = /^[ \\\\t]*var\\\\s*(?:(<storage,[^>]*>)\\\\s*([\\\\w\\\\d_]+)\\\\s*:\\\\s*(.*?)\\\\s*;|(<(?!storage,)[^>]*>)?\\\\s*([\\\\w\\\\d_]+)\\\\s*:\\\\s*(texture_.*|storage_texture_.*|storage\\\\w.*|external_texture|sampler(?:_comparison)?)\\\\s*;)\\\\s*$/gm;\\nconst VARYING = /(?:@interpolate\\\\([^)]*\\\\)\\\\s*)?([\\\\w]+)\\\\s*:\\\\s*([\\\\w<>]+)/;\\nconst MARKER = \\\"@@@\\\";\\nconst ENTRY_FUNCTION = /(@vertex|@fragment)\\\\s*fn\\\\s+\\\\w+\\\\s*\\\\(\\\\s*(\\\\w+)\\\\s*:[\\\\s\\\\S]*?\\\\{/;\\nconst FRAGMENT_BUILTINS = [\\n\\t{ wgslName: \\\"position\\\", wgslType: \\\"vec4f\\\", wgslBuiltin: \\\"position\\\", pcName: \\\"pcPosition\\\", isFallback: true },\\n\\t{ wgslName: \\\"frontFacing\\\", wgslType: \\\"bool\\\", wgslBuiltin: \\\"front_facing\\\", pcName: \\\"pcFrontFacing\\\" },\\n\\t{ wgslName: \\\"sampleIndex\\\", wgslType: \\\"u32\\\", wgslBuiltin: \\\"sample_index\\\", pcName: \\\"pcSampleIndex\\\" },\\n\\t{ wgslName: \\\"primitiveIndex\\\", wgslType: \\\"u32\\\", wgslBuiltin: \\\"primitive_index\\\", pcName: \\\"pcPrimitiveIndex\\\", requiresFeature: \\\"supportsPrimitiveIndex\\\" }\\n];\\nconst VERTEX_BUILTINS = [\\n\\t{ wgslName: \\\"vertexIndex\\\", wgslType: \\\"u32\\\", wgslBuiltin: \\\"vertex_index\\\", pcName: \\\"pcVertexIndex\\\", isFallback: true },\\n\\t{ wgslName: \\\"instanceIndex\\\", wgslType: \\\"u32\\\", wgslBuiltin: \\\"instance_index\\\", pcName: \\\"pcInstanceIndex\\\" }\\n];\\nconst detectUsedBuiltins = (builtins, source, entryInputName, device) => {\\n\\treturn builtins.filter((b) => {\\n\\t\\tif (b.requiresFeature && !device[b.requiresFeature]) return false;\\n\\t\\treturn new RegExp(`\\\\\\\\b(?:${b.pcName}|${entryInputName}\\\\\\\\.${b.wgslName})\\\\\\\\b`).test(source);\\n\\t});\\n};\\nconst ensureNonEmptyStruct = (used, builtins, device, otherFieldsPresent) => {\\n\\tif (used.length === 0 && !otherFieldsPresent) {\\n\\t\\tconst fallback = builtins.find((b) => b.isFallback && (!b.requiresFeature || device[b.requiresFeature]));\\n\\t\\tif (fallback) return [fallback];\\n\\t}\\n\\treturn used;\\n};\\nconst renderBuiltinStructFields = (used) => used.map((b) => `    @builtin(${b.wgslBuiltin}) ${b.wgslName} : ${b.wgslType},\\n`).join(\\\"\\\");\\nconst renderBuiltinPrivates = (used) => used.map((b) => `    var<private> ${b.pcName}: ${b.wgslType};\\n`).join(\\\"\\\");\\nconst renderBuiltinCopies = (used) => used.map((b) => `    ${b.pcName} = input.${b.wgslName};\\n`).join(\\\"\\\");\\nconst textureBaseInfo = {\\n\\t\\\"texture_1d\\\": { viewDimension: TEXTUREDIMENSION_1D, baseSampleType: SAMPLETYPE_FLOAT },\\n\\t\\\"texture_2d\\\": { viewDimension: TEXTUREDIMENSION_2D, baseSampleType: SAMPLETYPE_FLOAT },\\n\\t\\\"texture_2d_array\\\": { viewDimension: TEXTUREDIMENSION_2D_ARRAY, baseSampleType: SAMPLETYPE_FLOAT },\\n\\t\\\"texture_3d\\\": { viewDimension: TEXTUREDIMENSION_3D, baseSampleType: SAMPLETYPE_FLOAT },\\n\\t\\\"texture_cube\\\": { viewDimension: TEXTUREDIMENSION_CUBE, baseSampleType: SAMPLETYPE_FLOAT },\\n\\t\\\"texture_cube_array\\\": { viewDimension: TEXTUREDIMENSION_CUBE_ARRAY, baseSampleType: SAMPLETYPE_FLOAT },\\n\\t\\\"texture_multisampled_2d\\\": { viewDimension: TEXTUREDIMENSION_2D, baseSampleType: SAMPLETYPE_FLOAT },\\n\\t\\\"texture_depth_2d\\\": { viewDimension: TEXTUREDIMENSION_2D, baseSampleType: SAMPLETYPE_DEPTH },\\n\\t\\\"texture_depth_2d_array\\\": { viewDimension: TEXTUREDIMENSION_2D_ARRAY, baseSampleType: SAMPLETYPE_DEPTH },\\n\\t\\\"texture_depth_cube\\\": { viewDimension: TEXTUREDIMENSION_CUBE, baseSampleType: SAMPLETYPE_DEPTH },\\n\\t\\\"texture_depth_cube_array\\\": { viewDimension: TEXTUREDIMENSION_CUBE_ARRAY, baseSampleType: SAMPLETYPE_DEPTH },\\n\\t\\\"texture_external\\\": { viewDimension: TEXTUREDIMENSION_2D, baseSampleType: SAMPLETYPE_UNFILTERABLE_FLOAT }\\n};\\nconst getTextureInfo = (baseType, componentType) => {\\n\\tconst baseInfo = textureBaseInfo[baseType];\\n\\tlet finalSampleType = baseInfo.baseSampleType;\\n\\tif (baseInfo.baseSampleType === SAMPLETYPE_FLOAT && baseType !== \\\"texture_multisampled_2d\\\") {\\n\\t\\tswitch (componentType) {\\n\\t\\t\\tcase \\\"u32\\\":\\n\\t\\t\\t\\tfinalSampleType = SAMPLETYPE_UINT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase \\\"i32\\\":\\n\\t\\t\\t\\tfinalSampleType = SAMPLETYPE_INT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase \\\"f32\\\":\\n\\t\\t\\t\\tfinalSampleType = SAMPLETYPE_FLOAT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t// custom 'uff' type for unfilterable float, allowing us to create correct bind, which is automatically generated based on the shader\\n\\t\\t\\tcase \\\"uff\\\":\\n\\t\\t\\t\\tfinalSampleType = SAMPLETYPE_UNFILTERABLE_FLOAT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t}\\n\\t}\\n\\treturn {\\n\\t\\tviewDimension: baseInfo.viewDimension,\\n\\t\\tsampleType: finalSampleType\\n\\t};\\n};\\nconst getTextureDeclarationType = (viewDimension, sampleType) => {\\n\\tif (sampleType === SAMPLETYPE_DEPTH) {\\n\\t\\tswitch (viewDimension) {\\n\\t\\t\\tcase TEXTUREDIMENSION_2D:\\n\\t\\t\\t\\treturn \\\"texture_depth_2d\\\";\\n\\t\\t\\tcase TEXTUREDIMENSION_2D_ARRAY:\\n\\t\\t\\t\\treturn \\\"texture_depth_2d_array\\\";\\n\\t\\t\\tcase TEXTUREDIMENSION_CUBE:\\n\\t\\t\\t\\treturn \\\"texture_depth_cube\\\";\\n\\t\\t\\tcase TEXTUREDIMENSION_CUBE_ARRAY:\\n\\t\\t\\t\\treturn \\\"texture_depth_cube_array\\\";\\n\\t\\t}\\n\\t}\\n\\tlet baseTypeString;\\n\\tswitch (viewDimension) {\\n\\t\\tcase TEXTUREDIMENSION_1D:\\n\\t\\t\\tbaseTypeString = \\\"texture_1d\\\";\\n\\t\\t\\tbreak;\\n\\t\\tcase TEXTUREDIMENSION_2D:\\n\\t\\t\\tbaseTypeString = \\\"texture_2d\\\";\\n\\t\\t\\tbreak;\\n\\t\\tcase TEXTUREDIMENSION_2D_ARRAY:\\n\\t\\t\\tbaseTypeString = \\\"texture_2d_array\\\";\\n\\t\\t\\tbreak;\\n\\t\\tcase TEXTUREDIMENSION_3D:\\n\\t\\t\\tbaseTypeString = \\\"texture_3d\\\";\\n\\t\\t\\tbreak;\\n\\t\\tcase TEXTUREDIMENSION_CUBE:\\n\\t\\t\\tbaseTypeString = \\\"texture_cube\\\";\\n\\t\\t\\tbreak;\\n\\t\\tcase TEXTUREDIMENSION_CUBE_ARRAY:\\n\\t\\t\\tbaseTypeString = \\\"texture_cube_array\\\";\\n\\t\\t\\tbreak;\\n\\t}\\n\\tlet coreFormatString;\\n\\tswitch (sampleType) {\\n\\t\\tcase SAMPLETYPE_FLOAT:\\n\\t\\tcase SAMPLETYPE_UNFILTERABLE_FLOAT:\\n\\t\\t\\tcoreFormatString = \\\"f32\\\";\\n\\t\\t\\tbreak;\\n\\t\\tcase SAMPLETYPE_UINT:\\n\\t\\t\\tcoreFormatString = \\\"u32\\\";\\n\\t\\t\\tbreak;\\n\\t\\tcase SAMPLETYPE_INT:\\n\\t\\t\\tcoreFormatString = \\\"i32\\\";\\n\\t\\t\\tbreak;\\n\\t}\\n\\treturn `${baseTypeString}<${coreFormatString}>`;\\n};\\nconst wrappedArrayTypes = {\\n\\t\\\"f32\\\": \\\"WrappedF32\\\",\\n\\t\\\"i32\\\": \\\"WrappedI32\\\",\\n\\t\\\"u32\\\": \\\"WrappedU32\\\",\\n\\t\\\"vec2f\\\": \\\"WrappedVec2F\\\",\\n\\t\\\"vec2i\\\": \\\"WrappedVec2I\\\",\\n\\t\\\"vec2u\\\": \\\"WrappedVec2U\\\"\\n};\\nconst splitToWords = (line) => {\\n\\tline = line.replace(/\\\\s+/g, \\\" \\\").trim();\\n\\treturn line.split(/[\\\\s:]+/);\\n};\\nconst UNIFORM_ARRAY_REGEX = /array<([^,]+),\\\\s*([^>]+)>/;\\nclass UniformLine {\\n\\tubName = null;\\n\\tarraySize = 0;\\n\\tconstructor(line, shader) {\\n\\t\\tthis.line = line;\\n\\t\\tconst parts = splitToWords(line);\\n\\t\\tif (parts.length < 2) {\\n\\t\\t\\tshader.failed = true;\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.name = parts[0];\\n\\t\\tthis.type = parts.slice(1).join(\\\" \\\");\\n\\t\\tif (this.type.includes(\\\"array<\\\")) {\\n\\t\\t\\tconst match = UNIFORM_ARRAY_REGEX.exec(this.type);\\n\\t\\t\\tthis.type = match[1].trim();\\n\\t\\t\\tthis.arraySize = Number(match[2]);\\n\\t\\t\\tif (isNaN(this.arraySize)) {\\n\\t\\t\\t\\tshader.failed = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\nconst TEXTURE_REGEX = /^\\\\s*var\\\\s+(\\\\w+)\\\\s*:\\\\s*(texture_\\\\w+)(?:<(\\\\w+)>)?;\\\\s*$/;\\nconst STORAGE_TEXTURE_REGEX = /^\\\\s*var\\\\s+([\\\\w\\\\d_]+)\\\\s*:\\\\s*(texture_storage_2d|texture_storage_2d_array)<([\\\\w\\\\d_]+),\\\\s*(\\\\w+)>\\\\s*;\\\\s*$/;\\nconst STORAGE_BUFFER_REGEX = /^\\\\s*var\\\\s*<storage,\\\\s*(read|write)?>\\\\s*([\\\\w\\\\d_]+)\\\\s*:\\\\s*(.*)\\\\s*;\\\\s*$/;\\nconst EXTERNAL_TEXTURE_REGEX = /^\\\\s*var\\\\s+([\\\\w\\\\d_]+)\\\\s*:\\\\s*texture_external;\\\\s*$/;\\nconst SAMPLER_REGEX = /^\\\\s*var\\\\s+([\\\\w\\\\d_]+)\\\\s*:\\\\s*(sampler|sampler_comparison)\\\\s*;\\\\s*$/;\\nclass ResourceLine {\\n\\tconstructor(line, shader) {\\n\\t\\tthis.originalLine = line;\\n\\t\\tthis.line = line;\\n\\t\\tthis.isTexture = false;\\n\\t\\tthis.isSampler = false;\\n\\t\\tthis.isStorageTexture = false;\\n\\t\\tthis.isStorageBuffer = false;\\n\\t\\tthis.isExternalTexture = false;\\n\\t\\tthis.type = \\\"\\\";\\n\\t\\tthis.matchedElements = [];\\n\\t\\tconst textureMatch = this.line.match(TEXTURE_REGEX);\\n\\t\\tif (textureMatch) {\\n\\t\\t\\tthis.name = textureMatch[1];\\n\\t\\t\\tthis.type = textureMatch[2];\\n\\t\\t\\tthis.textureFormat = textureMatch[3];\\n\\t\\t\\tthis.isTexture = true;\\n\\t\\t\\tthis.matchedElements.push(...textureMatch);\\n\\t\\t\\tconst info = getTextureInfo(this.type, this.textureFormat);\\n\\t\\t\\tthis.textureDimension = info.viewDimension;\\n\\t\\t\\tthis.sampleType = info.sampleType;\\n\\t\\t}\\n\\t\\tconst storageTextureMatch = this.line.match(STORAGE_TEXTURE_REGEX);\\n\\t\\tif (storageTextureMatch) {\\n\\t\\t\\tthis.isStorageTexture = true;\\n\\t\\t\\tthis.name = storageTextureMatch[1];\\n\\t\\t\\tthis.textureType = storageTextureMatch[2];\\n\\t\\t\\tthis.format = storageTextureMatch[3];\\n\\t\\t\\tthis.access = storageTextureMatch[4];\\n\\t\\t\\tthis.matchedElements.push(...storageTextureMatch);\\n\\t\\t}\\n\\t\\tconst storageBufferMatch = this.line.match(STORAGE_BUFFER_REGEX);\\n\\t\\tif (storageBufferMatch) {\\n\\t\\t\\tthis.isStorageBuffer = true;\\n\\t\\t\\tthis.accessMode = storageBufferMatch[1] || \\\"none\\\";\\n\\t\\t\\tthis.name = storageBufferMatch[2];\\n\\t\\t\\tthis.type = storageBufferMatch[3];\\n\\t\\t\\tthis.matchedElements.push(...storageBufferMatch);\\n\\t\\t}\\n\\t\\tconst externalTextureMatch = this.line.match(EXTERNAL_TEXTURE_REGEX);\\n\\t\\tif (externalTextureMatch) {\\n\\t\\t\\tthis.name = externalTextureMatch[1];\\n\\t\\t\\tthis.isExternalTexture = true;\\n\\t\\t\\tthis.matchedElements.push(...storageBufferMatch);\\n\\t\\t}\\n\\t\\tconst samplerMatch = this.line.match(SAMPLER_REGEX);\\n\\t\\tif (samplerMatch) {\\n\\t\\t\\tthis.name = samplerMatch[1];\\n\\t\\t\\tthis.samplerType = samplerMatch[2];\\n\\t\\t\\tthis.isSampler = true;\\n\\t\\t\\tthis.matchedElements.push(...samplerMatch);\\n\\t\\t}\\n\\t\\tif (this.matchedElements.length === 0) {\\n\\t\\t\\tshader.failed = true;\\n\\t\\t}\\n\\t}\\n\\tequals(other) {\\n\\t\\tif (this.name !== other.name) return false;\\n\\t\\tif (this.type !== other.type) return false;\\n\\t\\tif (this.isTexture !== other.isTexture) return false;\\n\\t\\tif (this.isSampler !== other.isSampler) return false;\\n\\t\\tif (this.isStorageTexture !== other.isStorageTexture) return false;\\n\\t\\tif (this.isStorageBuffer !== other.isStorageBuffer) return false;\\n\\t\\tif (this.isExternalTexture !== other.isExternalTexture) return false;\\n\\t\\tif (this.textureFormat !== other.textureFormat) return false;\\n\\t\\tif (this.textureDimension !== other.textureDimension) return false;\\n\\t\\tif (this.sampleType !== other.sampleType) return false;\\n\\t\\tif (this.textureType !== other.textureType) return false;\\n\\t\\tif (this.format !== other.format) return false;\\n\\t\\tif (this.access !== other.access) return false;\\n\\t\\tif (this.accessMode !== other.accessMode) return false;\\n\\t\\tif (this.samplerType !== other.samplerType) return false;\\n\\t\\treturn true;\\n\\t}\\n}\\nclass WebgpuShaderProcessorWGSL {\\n\\tstatic run(device, shaderDefinition, shader) {\\n\\t\\tconst varyingMap = /* @__PURE__ */ new Map();\\n\\t\\tconst vertexExtracted = WebgpuShaderProcessorWGSL.extract(shaderDefinition.vshader);\\n\\t\\tconst fragmentExtracted = WebgpuShaderProcessorWGSL.extract(shaderDefinition.fshader);\\n\\t\\tconst vertexInputName = vertexExtracted.src.match(ENTRY_FUNCTION)?.[2] ?? \\\"\\\";\\n\\t\\tconst fragmentInputName = fragmentExtracted.src.match(ENTRY_FUNCTION)?.[2] ?? \\\"\\\";\\n\\t\\tconst attributesMap = /* @__PURE__ */ new Map();\\n\\t\\tconst attributesBlock = WebgpuShaderProcessorWGSL.processAttributes(vertexExtracted.attributes, shaderDefinition.attributes, attributesMap, shaderDefinition.processingOptions, shader, device, vertexExtracted.src, vertexInputName);\\n\\t\\tconst vertexVaryingsBlock = WebgpuShaderProcessorWGSL.processVaryings(vertexExtracted.varyings, varyingMap, true, device);\\n\\t\\tconst fragmentVaryingsBlock = WebgpuShaderProcessorWGSL.processVaryings(fragmentExtracted.varyings, varyingMap, false, device, fragmentExtracted.src, fragmentInputName);\\n\\t\\tconst concatUniforms = vertexExtracted.uniforms.concat(fragmentExtracted.uniforms);\\n\\t\\tconst uniforms = Array.from(new Set(concatUniforms));\\n\\t\\tconst parsedUniforms = uniforms.map((line) => new UniformLine(line, shader));\\n\\t\\tconst uniformsData = WebgpuShaderProcessorWGSL.processUniforms(device, parsedUniforms, shaderDefinition.processingOptions, shader);\\n\\t\\tvertexExtracted.src = WebgpuShaderProcessorWGSL.renameUniformAccess(vertexExtracted.src, parsedUniforms);\\n\\t\\tfragmentExtracted.src = WebgpuShaderProcessorWGSL.renameUniformAccess(fragmentExtracted.src, parsedUniforms);\\n\\t\\tconst parsedResources = WebgpuShaderProcessorWGSL.mergeResources(vertexExtracted.resources, fragmentExtracted.resources, shader);\\n\\t\\tconst resourcesData = WebgpuShaderProcessorWGSL.processResources(device, parsedResources, shaderDefinition.processingOptions, shader);\\n\\t\\tconst fOutput = WebgpuShaderProcessorWGSL.generateFragmentOutputStruct(fragmentExtracted.src, device.maxColorAttachments);\\n\\t\\tvertexExtracted.src = WebgpuShaderProcessorWGSL.copyInputs(vertexExtracted.src, shader);\\n\\t\\tfragmentExtracted.src = WebgpuShaderProcessorWGSL.copyInputs(fragmentExtracted.src, shader);\\n\\t\\tconst vBlock = `${attributesBlock}\\n${vertexVaryingsBlock}\\n${uniformsData.code}\\n${resourcesData.code}\\n`;\\n\\t\\tconst vshader = vertexExtracted.src.replace(MARKER, vBlock);\\n\\t\\tconst fBlock = `${fragmentVaryingsBlock}\\n${fOutput}\\n${uniformsData.code}\\n${resourcesData.code}\\n`;\\n\\t\\tconst fshader = fragmentExtracted.src.replace(MARKER, fBlock);\\n\\t\\treturn {\\n\\t\\t\\tvshader,\\n\\t\\t\\tfshader,\\n\\t\\t\\tattributes: attributesMap,\\n\\t\\t\\tmeshUniformBufferFormat: uniformsData.meshUniformBufferFormat,\\n\\t\\t\\tmeshBindGroupFormat: resourcesData.meshBindGroupFormat\\n\\t\\t};\\n\\t}\\n\\t// Extract required information from the shader source code.\\n\\tstatic extract(src) {\\n\\t\\tconst attributes = [];\\n\\t\\tconst varyings = [];\\n\\t\\tconst uniforms = [];\\n\\t\\tconst resources = [];\\n\\t\\tlet replacement = `${MARKER}\\n`;\\n\\t\\tlet match;\\n\\t\\twhile ((match = KEYWORD$1.exec(src)) !== null) {\\n\\t\\t\\tconst keyword = match[1];\\n\\t\\t\\tKEYWORD_LINE.lastIndex = match.index;\\n\\t\\t\\tconst lineMatch = KEYWORD_LINE.exec(src);\\n\\t\\t\\tif (keyword === \\\"attribute\\\") {\\n\\t\\t\\t\\tattributes.push(lineMatch[2]);\\n\\t\\t\\t} else if (keyword === \\\"varying\\\") {\\n\\t\\t\\t\\tvaryings.push(lineMatch[2]);\\n\\t\\t\\t} else if (keyword === \\\"uniform\\\") {\\n\\t\\t\\t\\tuniforms.push(lineMatch[2]);\\n\\t\\t\\t}\\n\\t\\t\\tsrc = WebgpuShaderProcessorWGSL.cutOut(src, match.index, KEYWORD_LINE.lastIndex, replacement);\\n\\t\\t\\tKEYWORD$1.lastIndex = match.index + replacement.length;\\n\\t\\t\\treplacement = \\\"\\\";\\n\\t\\t}\\n\\t\\twhile ((match = KEYWORD_RESOURCE.exec(src)) !== null) {\\n\\t\\t\\tresources.push(match[0]);\\n\\t\\t\\tsrc = WebgpuShaderProcessorWGSL.cutOut(src, match.index, KEYWORD_RESOURCE.lastIndex, replacement);\\n\\t\\t\\tKEYWORD_RESOURCE.lastIndex = match.index + replacement.length;\\n\\t\\t\\treplacement = \\\"\\\";\\n\\t\\t}\\n\\t\\treturn {\\n\\t\\t\\tsrc,\\n\\t\\t\\tattributes,\\n\\t\\t\\tvaryings,\\n\\t\\t\\tuniforms,\\n\\t\\t\\tresources\\n\\t\\t};\\n\\t}\\n\\tstatic processUniforms(device, uniforms, processingOptions, shader) {\\n\\t\\tconst meshUniforms = [];\\n\\t\\tuniforms.forEach((uniform) => {\\n\\t\\t\\tif (!processingOptions.hasUniform(uniform.name)) {\\n\\t\\t\\t\\tuniform.ubName = \\\"ub_mesh_ub\\\";\\n\\t\\t\\t\\tconst uniformType = uniformTypeToNameMapWGSL.get(uniform.type);\\n\\t\\t\\t\\tconst uniformFormat = new UniformFormat(uniform.name, uniformType, uniform.arraySize);\\n\\t\\t\\t\\tmeshUniforms.push(uniformFormat);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tuniform.ubName = \\\"ub_view\\\";\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tif (meshUniforms.length === 0) {\\n\\t\\t\\tmeshUniforms.push(new UniformFormat(UNUSED_UNIFORM_NAME, UNIFORMTYPE_FLOAT));\\n\\t\\t}\\n\\t\\tconst meshUniformBufferFormat = new UniformBufferFormat(device, meshUniforms);\\n\\t\\tlet code = \\\"\\\";\\n\\t\\tprocessingOptions.uniformFormats.forEach((format, bindGroupIndex) => {\\n\\t\\t\\tif (format) {\\n\\t\\t\\t\\tcode += WebgpuShaderProcessorWGSL.getUniformShaderDeclaration(format, bindGroupIndex, 0);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tif (meshUniformBufferFormat) {\\n\\t\\t\\tcode += WebgpuShaderProcessorWGSL.getUniformShaderDeclaration(meshUniformBufferFormat, BINDGROUP_MESH_UB, 0);\\n\\t\\t}\\n\\t\\treturn {\\n\\t\\t\\tcode,\\n\\t\\t\\tmeshUniformBufferFormat\\n\\t\\t};\\n\\t}\\n\\tstatic renameUniformAccess(source, uniforms) {\\n\\t\\tuniforms.forEach((uniform) => {\\n\\t\\t\\tconst srcName = `uniform.${uniform.name}`;\\n\\t\\t\\tconst dstName = `${uniform.ubName}.${uniform.name}`;\\n\\t\\t\\tconst regex = new RegExp(`\\\\\\\\b${srcName}\\\\\\\\b`, \\\"g\\\");\\n\\t\\t\\tsource = source.replace(regex, dstName);\\n\\t\\t});\\n\\t\\treturn source;\\n\\t}\\n\\tstatic mergeResources(vertex, fragment, shader) {\\n\\t\\tconst resources = vertex.map((line) => new ResourceLine(line, shader));\\n\\t\\tconst fragmentResources = fragment.map((line) => new ResourceLine(line, shader));\\n\\t\\tfragmentResources.forEach((fragmentResource) => {\\n\\t\\t\\tconst existing = resources.find((resource) => resource.name === fragmentResource.name);\\n\\t\\t\\tif (existing) {\\n\\t\\t\\t\\tif (!existing.equals(fragmentResource)) {\\n\\t\\t\\t\\t\\tshader.failed = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tresources.push(fragmentResource);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\treturn resources;\\n\\t}\\n\\tstatic processResources(device, resources, processingOptions, shader) {\\n\\t\\tconst textureFormats = [];\\n\\t\\tfor (let i = 0; i < resources.length; i++) {\\n\\t\\t\\tconst resource = resources[i];\\n\\t\\t\\tif (resource.isTexture) {\\n\\t\\t\\t\\tconst sampler = resources[i + 1];\\n\\t\\t\\t\\tconst hasSampler = sampler?.isSampler;\\n\\t\\t\\t\\tconst sampleType = resource.sampleType;\\n\\t\\t\\t\\tconst dimension = resource.textureDimension;\\n\\t\\t\\t\\ttextureFormats.push(new BindTextureFormat(resource.name, SHADERSTAGE_VERTEX | SHADERSTAGE_FRAGMENT, dimension, sampleType, hasSampler, hasSampler ? sampler.name : null));\\n\\t\\t\\t\\tif (hasSampler) i++;\\n\\t\\t\\t}\\n\\t\\t\\tif (resource.isStorageBuffer) {\\n\\t\\t\\t\\tconst readOnly = resource.accessMode !== \\\"read_write\\\";\\n\\t\\t\\t\\tconst bufferFormat = new BindStorageBufferFormat(resource.name, SHADERSTAGE_VERTEX | SHADERSTAGE_FRAGMENT, readOnly);\\n\\t\\t\\t\\tbufferFormat.format = resource.type;\\n\\t\\t\\t\\ttextureFormats.push(bufferFormat);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst meshBindGroupFormat = new BindGroupFormat(device, textureFormats);\\n\\t\\tlet code = \\\"\\\";\\n\\t\\tprocessingOptions.bindGroupFormats.forEach((format, bindGroupIndex) => {\\n\\t\\t\\tif (format) {\\n\\t\\t\\t\\tcode += WebgpuShaderProcessorWGSL.getTextureShaderDeclaration(format, bindGroupIndex);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tcode += WebgpuShaderProcessorWGSL.getTextureShaderDeclaration(meshBindGroupFormat, BINDGROUP_MESH);\\n\\t\\treturn {\\n\\t\\t\\tcode,\\n\\t\\t\\tmeshBindGroupFormat\\n\\t\\t};\\n\\t}\\n\\tstatic getUniformShaderDeclaration(ubFormat, bindGroup, bindIndex) {\\n\\t\\tconst name = bindGroupNames[bindGroup];\\n\\t\\tconst structName = `struct_ub_${name}`;\\n\\t\\tlet code = `struct ${structName} {\\n`;\\n\\t\\tubFormat.uniforms.forEach((uniform) => {\\n\\t\\t\\tlet typeString = uniformTypeToNameWGSL[uniform.type][0];\\n\\t\\t\\tif (uniform.count > 0) {\\n\\t\\t\\t\\tif (wrappedArrayTypes.hasOwnProperty(typeString)) {\\n\\t\\t\\t\\t\\ttypeString = wrappedArrayTypes[typeString];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcode += `    ${uniform.shortName}: array<${typeString}, ${uniform.count}>,\\n`;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tcode += `    ${uniform.shortName}: ${typeString},\\n`;\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tcode += \\\"};\\\\n\\\";\\n\\t\\tcode += `@group(${bindGroup}) @binding(${bindIndex}) var<uniform> ub_${name} : ${structName};\\n\\n`;\\n\\t\\treturn code;\\n\\t}\\n\\tstatic getTextureShaderDeclaration(format, bindGroup) {\\n\\t\\tlet code = \\\"\\\";\\n\\t\\tformat.textureFormats.forEach((format2) => {\\n\\t\\t\\tconst textureTypeName = getTextureDeclarationType(format2.textureDimension, format2.sampleType);\\n\\t\\t\\tcode += `@group(${bindGroup}) @binding(${format2.slot}) var ${format2.name}: ${textureTypeName};\\n`;\\n\\t\\t\\tif (format2.hasSampler) {\\n\\t\\t\\t\\tconst samplerName = format2.sampleType === SAMPLETYPE_DEPTH ? \\\"sampler_comparison\\\" : \\\"sampler\\\";\\n\\t\\t\\t\\tcode += `@group(${bindGroup}) @binding(${format2.slot + 1}) var ${format2.samplerName}: ${samplerName};\\n`;\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tformat.storageBufferFormats.forEach((format2) => {\\n\\t\\t\\tconst access = format2.readOnly ? \\\"read\\\" : \\\"read_write\\\";\\n\\t\\t\\tcode += `@group(${bindGroup}) @binding(${format2.slot}) var<storage, ${access}> ${format2.name} : ${format2.format};\\n`;\\n\\t\\t});\\n\\t\\treturn code;\\n\\t}\\n\\tstatic processVaryings(varyingLines, varyingMap, isVertex, device, source = \\\"\\\", entryInputName = \\\"\\\") {\\n\\t\\tlet block = \\\"\\\";\\n\\t\\tlet blockPrivates = \\\"\\\";\\n\\t\\tlet blockCopy = \\\"\\\";\\n\\t\\tvaryingLines.forEach((line, index) => {\\n\\t\\t\\tconst match = line.match(VARYING);\\n\\t\\t\\tif (match) {\\n\\t\\t\\t\\tconst name = match[1];\\n\\t\\t\\t\\tconst type = match[2];\\n\\t\\t\\t\\tif (isVertex) {\\n\\t\\t\\t\\t\\tvaryingMap.set(name, index);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tindex = varyingMap.get(name);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tblock += `    @location(${index}) ${line},\\n`;\\n\\t\\t\\t\\tif (!isVertex) {\\n\\t\\t\\t\\t\\tblockPrivates += `    var<private> ${name}: ${type};\\n`;\\n\\t\\t\\t\\t\\tblockCopy += `    ${name} = input.${name};\\n`;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tif (isVertex) {\\n\\t\\t\\tblock += \\\"    @builtin(position) position : vec4f,\\\\n\\\";\\n\\t\\t\\treturn `\\n\\t\\t\\t\\t\\t\\t\\t\\tstruct VertexOutput {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t${block}\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t`;\\n\\t\\t}\\n\\t\\tconst usedBuiltins = ensureNonEmptyStruct(\\n\\t\\t\\tdetectUsedBuiltins(FRAGMENT_BUILTINS, source, entryInputName, device),\\n\\t\\t\\tFRAGMENT_BUILTINS,\\n\\t\\t\\tdevice,\\n\\t\\t\\tblock.length > 0\\n\\t\\t);\\n\\t\\tblock += renderBuiltinStructFields(usedBuiltins);\\n\\t\\treturn `\\n\\t\\t\\t\\t\\t\\tstruct FragmentInput {\\n\\t\\t\\t\\t\\t\\t\\t\\t${block}\\n\\t\\t\\t\\t\\t\\t};\\n\\n\\t\\t\\t\\t\\t\\t${renderBuiltinPrivates(usedBuiltins)}\\n\\t\\t\\t\\t\\t\\t${blockPrivates}\\n\\n\\t\\t\\t\\t\\t\\t// function to copy inputs (varyings) to private global variables\\n\\t\\t\\t\\t\\t\\tfn _pcCopyInputs(input: FragmentInput) {\\n\\t\\t\\t\\t\\t\\t\\t\\t${blockCopy}\\n\\t\\t\\t\\t\\t\\t\\t\\t${renderBuiltinCopies(usedBuiltins)}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t`;\\n\\t}\\n\\tstatic generateFragmentOutputStruct(src, numRenderTargets) {\\n\\t\\tlet structCode = \\\"struct FragmentOutput {\\\\n\\\";\\n\\t\\tconst colorName = (i) => `color${i > 0 ? i : \\\"\\\"}`;\\n\\t\\tfor (let i = 0; i < numRenderTargets; i++) {\\n\\t\\t\\tconst name = colorName(i);\\n\\t\\t\\tif (src.search(new RegExp(`\\\\\\\\.${name}\\\\\\\\s*=`)) !== -1) {\\n\\t\\t\\t\\tstructCode += `    @location(${i}) ${name} : pcOutType${i},\\n`;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst needsFragDepth = src.search(/\\\\.fragDepth\\\\s*=/) !== -1;\\n\\t\\tif (needsFragDepth) {\\n\\t\\t\\tstructCode += \\\"    @builtin(frag_depth) fragDepth : f32\\\\n\\\";\\n\\t\\t}\\n\\t\\treturn `${structCode}};\\n`;\\n\\t}\\n\\t// convert a float attribute type to matching signed or unsigned int type\\n\\t// for example: vec4f -> vec4u, f32 -> u32\\n\\tstatic floatAttributeToInt(type, signed) {\\n\\t\\tconst longToShortMap = {\\n\\t\\t\\t\\\"f32\\\": \\\"f32\\\",\\n\\t\\t\\t\\\"vec2<f32>\\\": \\\"vec2f\\\",\\n\\t\\t\\t\\\"vec3<f32>\\\": \\\"vec3f\\\",\\n\\t\\t\\t\\\"vec4<f32>\\\": \\\"vec4f\\\"\\n\\t\\t};\\n\\t\\tconst shortType = longToShortMap[type] || type;\\n\\t\\tconst floatToIntShort = {\\n\\t\\t\\t\\\"f32\\\": signed ? \\\"i32\\\" : \\\"u32\\\",\\n\\t\\t\\t\\\"vec2f\\\": signed ? \\\"vec2i\\\" : \\\"vec2u\\\",\\n\\t\\t\\t\\\"vec3f\\\": signed ? \\\"vec3i\\\" : \\\"vec3u\\\",\\n\\t\\t\\t\\\"vec4f\\\": signed ? \\\"vec4i\\\" : \\\"vec4u\\\"\\n\\t\\t};\\n\\t\\treturn floatToIntShort[shortType] || null;\\n\\t}\\n\\tstatic processAttributes(attributeLines, shaderDefinitionAttributes = {}, attributesMap, processingOptions, shader, device, source = \\\"\\\", entryInputName = \\\"\\\") {\\n\\t\\tlet blockAttributes = \\\"\\\";\\n\\t\\tlet blockPrivates = \\\"\\\";\\n\\t\\tlet blockCopy = \\\"\\\";\\n\\t\\tattributeLines.forEach((line) => {\\n\\t\\t\\tconst words = splitToWords(line);\\n\\t\\t\\tconst name = words[0];\\n\\t\\t\\tlet type = words[1];\\n\\t\\t\\tconst originalType = type;\\n\\t\\t\\tif (shaderDefinitionAttributes.hasOwnProperty(name)) {\\n\\t\\t\\t\\tconst semantic = shaderDefinitionAttributes[name];\\n\\t\\t\\t\\tconst location = semanticToLocation[semantic];\\n\\t\\t\\t\\tattributesMap.set(location, name);\\n\\t\\t\\t\\tconst element = processingOptions.getVertexElement(semantic);\\n\\t\\t\\t\\tif (element) {\\n\\t\\t\\t\\t\\tconst dataType = element.dataType;\\n\\t\\t\\t\\t\\tif (dataType !== TYPE_FLOAT32 && dataType !== TYPE_FLOAT16 && !element.normalize && !element.asInt) {\\n\\t\\t\\t\\t\\t\\tconst isSignedType = dataType === TYPE_INT8 || dataType === TYPE_INT16 || dataType === TYPE_INT32;\\n\\t\\t\\t\\t\\t\\ttype = WebgpuShaderProcessorWGSL.floatAttributeToInt(type, isSignedType);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tblockAttributes += `    @location(${location}) ${name}: ${type},\\n`;\\n\\t\\t\\t\\tblockPrivates += `    var<private> ${line};\\n`;\\n\\t\\t\\t\\tblockCopy += `    ${name} = ${originalType}(input.${name});\\n`;\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tconst usedBuiltins = ensureNonEmptyStruct(\\n\\t\\t\\tdetectUsedBuiltins(VERTEX_BUILTINS, source, entryInputName, device),\\n\\t\\t\\tVERTEX_BUILTINS,\\n\\t\\t\\tdevice,\\n\\t\\t\\tblockAttributes.length > 0\\n\\t\\t);\\n\\t\\treturn `\\n\\t\\t\\t\\t\\t\\tstruct VertexInput {\\n\\t\\t\\t\\t\\t\\t\\t\\t${blockAttributes}\\n\\t\\t\\t\\t\\t\\t\\t\\t${renderBuiltinStructFields(usedBuiltins)}\\n\\t\\t\\t\\t\\t\\t};\\n\\n\\t\\t\\t\\t\\t\\t${blockPrivates}\\n\\t\\t\\t\\t\\t\\t${renderBuiltinPrivates(usedBuiltins)}\\n\\n\\t\\t\\t\\t\\t\\tfn _pcCopyInputs(input: VertexInput) {\\n\\t\\t\\t\\t\\t\\t\\t\\t${blockCopy}\\n\\t\\t\\t\\t\\t\\t\\t\\t${renderBuiltinCopies(usedBuiltins)}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t`;\\n\\t}\\n\\tstatic copyInputs(src, shader) {\\n\\t\\tconst match = src.match(ENTRY_FUNCTION);\\n\\t\\tif (!match || !match[2]) {\\n\\t\\t\\treturn src;\\n\\t\\t}\\n\\t\\tconst inputName = match[2];\\n\\t\\tconst braceIndex = match.index + match[0].length - 1;\\n\\t\\tconst beginning = src.slice(0, braceIndex + 1);\\n\\t\\tconst end = src.slice(braceIndex + 1);\\n\\t\\tconst lineToInject = `\\n\\t\\t_pcCopyInputs(${inputName});`;\\n\\t\\treturn beginning + lineToInject + end;\\n\\t}\\n\\tstatic cutOut(src, start, end, replacement) {\\n\\t\\treturn src.substring(0, start) + replacement + src.substring(end);\\n\\t}\\n}\\n\\nconst computeShaderIds = new StringIds();\\nclass WebgpuShader {\\n\\t_vertexCode = null;\\n\\t_fragmentCode = null;\\n\\t_computeCode = null;\\n\\t_computeKey;\\n\\tvertexEntryPoint = \\\"main\\\";\\n\\tfragmentEntryPoint = \\\"main\\\";\\n\\tcomputeEntryPoint = \\\"main\\\";\\n\\tconstructor(shader) {\\n\\t\\tthis.shader = shader;\\n\\t\\tconst definition = shader.definition;\\n\\t\\tif (definition.shaderLanguage === SHADERLANGUAGE_WGSL) {\\n\\t\\t\\tif (definition.cshader) {\\n\\t\\t\\t\\tthis._computeCode = definition.cshader ?? null;\\n\\t\\t\\t\\tthis.computeUniformBufferFormats = definition.computeUniformBufferFormats;\\n\\t\\t\\t\\tthis.computeBindGroupFormat = definition.computeBindGroupFormat;\\n\\t\\t\\t\\tif (definition.computeEntryPoint) {\\n\\t\\t\\t\\t\\tthis.computeEntryPoint = definition.computeEntryPoint;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.vertexEntryPoint = \\\"vertexMain\\\";\\n\\t\\t\\t\\tthis.fragmentEntryPoint = \\\"fragmentMain\\\";\\n\\t\\t\\t\\tif (definition.processingOptions) {\\n\\t\\t\\t\\t\\tthis.processWGSL();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tthis._vertexCode = definition.vshader ?? null;\\n\\t\\t\\t\\t\\tthis._fragmentCode = definition.fshader ?? null;\\n\\t\\t\\t\\t\\tshader.meshUniformBufferFormat = definition.meshUniformBufferFormat;\\n\\t\\t\\t\\t\\tshader.meshBindGroupFormat = definition.meshBindGroupFormat;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tshader.ready = true;\\n\\t\\t} else {\\n\\t\\t\\tif (definition.processingOptions) {\\n\\t\\t\\t\\tthis.processGLSL();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tdestroy(shader) {\\n\\t\\tthis._vertexCode = null;\\n\\t\\tthis._fragmentCode = null;\\n\\t}\\n\\tcreateShaderModule(code, shaderType) {\\n\\t\\tconst device = this.shader.device;\\n\\t\\tconst wgpu = device.wgpu;\\n\\t\\tconst shaderModule = wgpu.createShaderModule({\\n\\t\\t\\tcode\\n\\t\\t});\\n\\t\\treturn shaderModule;\\n\\t}\\n\\tgetVertexShaderModule() {\\n\\t\\treturn this.createShaderModule(this._vertexCode, \\\"Vertex\\\");\\n\\t}\\n\\tgetFragmentShaderModule() {\\n\\t\\treturn this.createShaderModule(this._fragmentCode, \\\"Fragment\\\");\\n\\t}\\n\\tgetComputeShaderModule() {\\n\\t\\treturn this.createShaderModule(this._computeCode, \\\"Compute\\\");\\n\\t}\\n\\tprocessGLSL() {\\n\\t\\tconst shader = this.shader;\\n\\t\\tconst processed = ShaderProcessorGLSL.run(shader.device, shader.definition, shader);\\n\\t\\tthis._vertexCode = this.transpile(processed.vshader, \\\"vertex\\\", shader.definition.vshader);\\n\\t\\tthis._fragmentCode = this.transpile(processed.fshader, \\\"fragment\\\", shader.definition.fshader);\\n\\t\\tif (!(this._vertexCode && this._fragmentCode)) {\\n\\t\\t\\tshader.failed = true;\\n\\t\\t} else {\\n\\t\\t\\tshader.ready = true;\\n\\t\\t}\\n\\t\\tshader.meshUniformBufferFormat = processed.meshUniformBufferFormat;\\n\\t\\tshader.meshBindGroupFormat = processed.meshBindGroupFormat;\\n\\t\\tshader.attributes = processed.attributes;\\n\\t}\\n\\tprocessWGSL() {\\n\\t\\tconst shader = this.shader;\\n\\t\\tconst processed = WebgpuShaderProcessorWGSL.run(shader.device, shader.definition, shader);\\n\\t\\tthis._vertexCode = processed.vshader;\\n\\t\\tthis._fragmentCode = processed.fshader;\\n\\t\\tshader.meshUniformBufferFormat = processed.meshUniformBufferFormat;\\n\\t\\tshader.meshBindGroupFormat = processed.meshBindGroupFormat;\\n\\t\\tshader.attributes = processed.attributes;\\n\\t}\\n\\ttranspile(src, shaderType, originalSrc) {\\n\\t\\tconst device = this.shader.device;\\n\\t\\tif (!device.glslang || !device.twgsl) {\\n\\t\\t\\tconsole.error(`Cannot transpile shader [${this.shader.label}] - shader transpilers (glslang/twgsl) are not available. Make sure to provide glslangUrl and twgslUrl when creating the device.`, {\\n\\t\\t\\t\\tshader: this.shader\\n\\t\\t\\t});\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\ttry {\\n\\t\\t\\tconst spirv = device.glslang.compileGLSL(src, shaderType);\\n\\t\\t\\tconst wgsl = device.twgsl.convertSpirV2WGSL(spirv);\\n\\t\\t\\treturn wgsl;\\n\\t\\t} catch (err) {\\n\\t\\t\\tconsole.error(`Failed to transpile webgl ${shaderType} shader [${this.shader.label}] to WebGPU while rendering ${ void 0}, error:\\n [${err.stack}]`, {\\n\\t\\t\\t\\tprocessed: src,\\n\\t\\t\\t\\toriginal: originalSrc,\\n\\t\\t\\t\\tshader: this.shader,\\n\\t\\t\\t\\terror: err,\\n\\t\\t\\t\\tstack: err.stack\\n\\t\\t\\t});\\n\\t\\t}\\n\\t}\\n\\tget vertexCode() {\\n\\t\\treturn this._vertexCode;\\n\\t}\\n\\tget fragmentCode() {\\n\\t\\treturn this._fragmentCode;\\n\\t}\\n\\tget computeKey() {\\n\\t\\tif (this._computeKey === void 0) {\\n\\t\\t\\tconst keyString = `${this._computeCode}|${this.computeEntryPoint}`;\\n\\t\\t\\tthis._computeKey = computeShaderIds.get(keyString);\\n\\t\\t}\\n\\t\\treturn this._computeKey;\\n\\t}\\n\\tloseContext() {\\n\\t}\\n\\trestoreContext(device, shader) {\\n\\t}\\n}\\n\\nconst gpuAddressModes = [];\\ngpuAddressModes[ADDRESS_REPEAT] = \\\"repeat\\\";\\ngpuAddressModes[ADDRESS_CLAMP_TO_EDGE] = \\\"clamp-to-edge\\\";\\ngpuAddressModes[ADDRESS_MIRRORED_REPEAT] = \\\"mirror-repeat\\\";\\nconst gpuFilterModes = [];\\ngpuFilterModes[FILTER_NEAREST] = { level: \\\"nearest\\\", mip: \\\"nearest\\\" };\\ngpuFilterModes[FILTER_LINEAR] = { level: \\\"linear\\\", mip: \\\"nearest\\\" };\\ngpuFilterModes[FILTER_NEAREST_MIPMAP_NEAREST] = { level: \\\"nearest\\\", mip: \\\"nearest\\\" };\\ngpuFilterModes[FILTER_NEAREST_MIPMAP_LINEAR] = { level: \\\"nearest\\\", mip: \\\"linear\\\" };\\ngpuFilterModes[FILTER_LINEAR_MIPMAP_NEAREST] = { level: \\\"linear\\\", mip: \\\"nearest\\\" };\\ngpuFilterModes[FILTER_LINEAR_MIPMAP_LINEAR] = { level: \\\"linear\\\", mip: \\\"linear\\\" };\\nconst dummyUse = (thingOne) => {\\n};\\nclass WebgpuTexture {\\n\\tgpuTexture;\\n\\tview;\\n\\tsamplers = [];\\n\\tdesc;\\n\\tformat;\\n\\tviewCache = /* @__PURE__ */ new Map();\\n\\tconstructor(texture) {\\n\\t\\tthis.texture = texture;\\n\\t\\tthis.format = gpuTextureFormats[texture.format];\\n\\t\\tthis.create(texture.device);\\n\\t}\\n\\tcreate(device) {\\n\\t\\tconst texture = this.texture;\\n\\t\\tconst wgpu = device.wgpu;\\n\\t\\tconst numLevels = texture.numLevels;\\n\\t\\tif (isCompressedPixelFormat(texture.format) && (texture.width % 4 !== 0 || texture.height % 4 !== 0)) {\\n\\t\\t\\ttexture._width = math.roundUp(texture.width, 4);\\n\\t\\t\\ttexture._height = math.roundUp(texture.height, 4);\\n\\t\\t}\\n\\t\\tthis.desc = {\\n\\t\\t\\tsize: {\\n\\t\\t\\t\\twidth: texture.width,\\n\\t\\t\\t\\theight: texture.height,\\n\\t\\t\\t\\tdepthOrArrayLayers: texture.cubemap ? 6 : texture.array ? texture.arrayLength : 1\\n\\t\\t\\t},\\n\\t\\t\\tformat: this.format,\\n\\t\\t\\tmipLevelCount: numLevels,\\n\\t\\t\\tsampleCount: 1,\\n\\t\\t\\tdimension: texture.volume ? \\\"3d\\\" : \\\"2d\\\",\\n\\t\\t\\t// TODO: use only required usage flags\\n\\t\\t\\t// COPY_SRC - probably only needed on render target textures, to support copyRenderTarget (grab pass needs it)\\n\\t\\t\\t// RENDER_ATTACHMENT - needed for mipmap generation\\n\\t\\t\\tusage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | (isCompressedPixelFormat(texture.format) ? 0 : GPUTextureUsage.RENDER_ATTACHMENT) | (texture.storage ? GPUTextureUsage.STORAGE_BINDING : 0)\\n\\t\\t};\\n\\t\\tthis.gpuTexture = wgpu.createTexture(this.desc);\\n\\t\\tlet viewDescr;\\n\\t\\tif (this.texture.format === PIXELFORMAT_DEPTHSTENCIL) {\\n\\t\\t\\tviewDescr = {\\n\\t\\t\\t\\tformat: \\\"depth24plus\\\",\\n\\t\\t\\t\\taspect: \\\"depth-only\\\"\\n\\t\\t\\t};\\n\\t\\t}\\n\\t\\tthis.view = this.createView(viewDescr);\\n\\t\\tthis.viewCache.clear();\\n\\t}\\n\\tdestroy(device) {\\n\\t\\tdevice.deferDestroy(this.gpuTexture);\\n\\t\\tthis.gpuTexture = null;\\n\\t\\tthis.view = null;\\n\\t\\tthis.viewCache.clear();\\n\\t\\tthis.samplers.length = 0;\\n\\t}\\n\\tpropertyChanged(flag) {\\n\\t\\tthis.samplers.length = 0;\\n\\t}\\n\\tgetView(device, textureView) {\\n\\t\\tthis.uploadImmediate(device, this.texture);\\n\\t\\tif (textureView) {\\n\\t\\t\\tlet view = this.viewCache.get(textureView.key);\\n\\t\\t\\tif (!view) {\\n\\t\\t\\t\\tview = this.createView({\\n\\t\\t\\t\\t\\tbaseMipLevel: textureView.baseMipLevel,\\n\\t\\t\\t\\t\\tmipLevelCount: textureView.mipLevelCount,\\n\\t\\t\\t\\t\\tbaseArrayLayer: textureView.baseArrayLayer,\\n\\t\\t\\t\\t\\tarrayLayerCount: textureView.arrayLayerCount\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.viewCache.set(textureView.key, view);\\n\\t\\t\\t}\\n\\t\\t\\treturn view;\\n\\t\\t}\\n\\t\\treturn this.view;\\n\\t}\\n\\tcreateView(viewDescr) {\\n\\t\\tconst options = viewDescr ?? {};\\n\\t\\tconst textureDescr = this.desc;\\n\\t\\tconst texture = this.texture;\\n\\t\\tconst defaultViewDimension = () => {\\n\\t\\t\\tif (texture.cubemap) return \\\"cube\\\";\\n\\t\\t\\tif (texture.volume) return \\\"3d\\\";\\n\\t\\t\\tif (texture.array) return \\\"2d-array\\\";\\n\\t\\t\\treturn \\\"2d\\\";\\n\\t\\t};\\n\\t\\tconst desc = {\\n\\t\\t\\tformat: options.format ?? textureDescr.format,\\n\\t\\t\\tdimension: options.dimension ?? defaultViewDimension(),\\n\\t\\t\\taspect: options.aspect ?? \\\"all\\\",\\n\\t\\t\\tbaseMipLevel: options.baseMipLevel ?? 0,\\n\\t\\t\\tmipLevelCount: options.mipLevelCount ?? textureDescr.mipLevelCount,\\n\\t\\t\\tbaseArrayLayer: options.baseArrayLayer ?? 0,\\n\\t\\t\\tarrayLayerCount: options.arrayLayerCount ?? textureDescr.depthOrArrayLayers\\n\\t\\t};\\n\\t\\tconst view = this.gpuTexture.createView(desc);\\n\\t\\treturn view;\\n\\t}\\n\\t// TODO: share a global map of samplers. Possibly even use shared samplers for bind group,\\n\\t// or maybe even have some attached in view bind group and use globally\\n\\tgetSampler(device, sampleType) {\\n\\t\\tlet sampler = this.samplers[sampleType];\\n\\t\\tif (!sampler) {\\n\\t\\t\\tconst texture = this.texture;\\n\\t\\t\\tconst desc = {\\n\\t\\t\\t\\taddressModeU: gpuAddressModes[texture.addressU],\\n\\t\\t\\t\\taddressModeV: gpuAddressModes[texture.addressV],\\n\\t\\t\\t\\taddressModeW: gpuAddressModes[texture.addressW]\\n\\t\\t\\t};\\n\\t\\t\\tif (!sampleType && texture.compareOnRead) {\\n\\t\\t\\t\\tsampleType = SAMPLETYPE_DEPTH;\\n\\t\\t\\t}\\n\\t\\t\\tif (sampleType === SAMPLETYPE_DEPTH || sampleType === SAMPLETYPE_INT || sampleType === SAMPLETYPE_UINT) {\\n\\t\\t\\t\\tdesc.compare = \\\"less\\\";\\n\\t\\t\\t\\tdesc.magFilter = \\\"linear\\\";\\n\\t\\t\\t\\tdesc.minFilter = \\\"linear\\\";\\n\\t\\t\\t} else if (sampleType === SAMPLETYPE_UNFILTERABLE_FLOAT) {\\n\\t\\t\\t\\tdesc.magFilter = \\\"nearest\\\";\\n\\t\\t\\t\\tdesc.minFilter = \\\"nearest\\\";\\n\\t\\t\\t\\tdesc.mipmapFilter = \\\"nearest\\\";\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconst forceNearest = !device.textureFloatFilterable && (texture.format === PIXELFORMAT_RGBA32F || texture.format === PIXELFORMAT_RGBA16F);\\n\\t\\t\\t\\tif (forceNearest || this.texture.format === PIXELFORMAT_DEPTHSTENCIL || isIntegerPixelFormat(this.texture.format)) {\\n\\t\\t\\t\\t\\tdesc.magFilter = \\\"nearest\\\";\\n\\t\\t\\t\\t\\tdesc.minFilter = \\\"nearest\\\";\\n\\t\\t\\t\\t\\tdesc.mipmapFilter = \\\"nearest\\\";\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tdesc.magFilter = gpuFilterModes[texture.magFilter].level;\\n\\t\\t\\t\\t\\tdesc.minFilter = gpuFilterModes[texture.minFilter].level;\\n\\t\\t\\t\\t\\tdesc.mipmapFilter = gpuFilterModes[texture.minFilter].mip;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tconst allLinear = desc.minFilter === \\\"linear\\\" && desc.magFilter === \\\"linear\\\" && desc.mipmapFilter === \\\"linear\\\";\\n\\t\\t\\tdesc.maxAnisotropy = allLinear ? math.clamp(Math.round(texture._anisotropy), 1, device.maxTextureAnisotropy) : 1;\\n\\t\\t\\tsampler = device.wgpu.createSampler(desc);\\n\\t\\t\\tthis.samplers[sampleType] = sampler;\\n\\t\\t}\\n\\t\\treturn sampler;\\n\\t}\\n\\tloseContext() {\\n\\t}\\n\\tuploadImmediate(device, texture) {\\n\\t\\tif (texture._needsUpload || texture._needsMipmapsUpload) {\\n\\t\\t\\tthis.uploadData(device);\\n\\t\\t\\ttexture._needsUpload = false;\\n\\t\\t\\ttexture._needsMipmapsUpload = false;\\n\\t\\t}\\n\\t}\\n\\tuploadData(device) {\\n\\t\\tconst texture = this.texture;\\n\\t\\tif (this.desc && (this.desc.size.width !== texture.width || this.desc.size.height !== texture.height)) {\\n\\t\\t\\tdevice.deferDestroy(this.gpuTexture);\\n\\t\\t\\tthis.create(device);\\n\\t\\t\\ttexture.renderVersionDirty = device.renderVersion;\\n\\t\\t}\\n\\t\\tif (texture._levels) {\\n\\t\\t\\tlet anyUploads = false;\\n\\t\\t\\tlet anyLevelMissing = false;\\n\\t\\t\\tconst requiredMipLevels = texture.numLevels;\\n\\t\\t\\tfor (let mipLevel = 0; mipLevel < requiredMipLevels; mipLevel++) {\\n\\t\\t\\t\\tconst mipObject = texture._levels[mipLevel];\\n\\t\\t\\t\\tif (mipObject) {\\n\\t\\t\\t\\t\\tif (texture.cubemap) {\\n\\t\\t\\t\\t\\t\\tfor (let face = 0; face < 6; face++) {\\n\\t\\t\\t\\t\\t\\t\\tconst faceSource = mipObject[face];\\n\\t\\t\\t\\t\\t\\t\\tif (faceSource) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.isExternalImage(faceSource)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.uploadExternalImage(device, faceSource, mipLevel, face);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tanyUploads = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else if (ArrayBuffer.isView(faceSource)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.uploadTypedArrayData(device, faceSource, mipLevel, face);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tanyUploads = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else ;\\n\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tanyLevelMissing = true;\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t} else if (texture._volume) ; else if (texture.array) {\\n\\t\\t\\t\\t\\t\\tif (texture.arrayLength === mipObject.length) {\\n\\t\\t\\t\\t\\t\\t\\tfor (let index = 0; index < texture._arrayLength; index++) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst arraySource = mipObject[index];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.isExternalImage(arraySource)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.uploadExternalImage(device, arraySource, mipLevel, index);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tanyUploads = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else if (ArrayBuffer.isView(arraySource)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.uploadTypedArrayData(device, arraySource, mipLevel, index);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tanyUploads = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else ;\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tanyLevelMissing = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (device._isHTMLElementInterface(mipObject) && device.supportsHtmlTextures) {\\n\\t\\t\\t\\t\\t\\t\\tthis.uploadElementImage(device, mipObject, mipLevel, 0);\\n\\t\\t\\t\\t\\t\\t\\tanyUploads = true;\\n\\t\\t\\t\\t\\t\\t} else if (this.isExternalImage(mipObject)) {\\n\\t\\t\\t\\t\\t\\t\\tthis.uploadExternalImage(device, mipObject, mipLevel, 0);\\n\\t\\t\\t\\t\\t\\t\\tanyUploads = true;\\n\\t\\t\\t\\t\\t\\t} else if (ArrayBuffer.isView(mipObject)) {\\n\\t\\t\\t\\t\\t\\t\\tthis.uploadTypedArrayData(device, mipObject, mipLevel, 0);\\n\\t\\t\\t\\t\\t\\t\\tanyUploads = true;\\n\\t\\t\\t\\t\\t\\t} else ;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tanyLevelMissing = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (anyUploads && anyLevelMissing && texture.mipmaps && !isCompressedPixelFormat(texture.format) && !isIntegerPixelFormat(texture.format)) {\\n\\t\\t\\t\\tdevice.mipmapRenderer.generate(this);\\n\\t\\t\\t}\\n\\t\\t\\tif (texture._gpuSize) {\\n\\t\\t\\t\\ttexture.adjustVramSizeTracking(device._vram, -texture._gpuSize);\\n\\t\\t\\t}\\n\\t\\t\\ttexture._gpuSize = texture.gpuSize;\\n\\t\\t\\ttexture.adjustVramSizeTracking(device._vram, texture._gpuSize);\\n\\t\\t\\tif (texture.releaseSourceAfterUpload) {\\n\\t\\t\\t\\ttexture.releaseImageSources();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t// image types supported by copyExternalImageToTexture\\n\\tisExternalImage(image) {\\n\\t\\treturn typeof ImageBitmap !== \\\"undefined\\\" && image instanceof ImageBitmap || typeof HTMLVideoElement !== \\\"undefined\\\" && image instanceof HTMLVideoElement || typeof HTMLCanvasElement !== \\\"undefined\\\" && image instanceof HTMLCanvasElement || typeof OffscreenCanvas !== \\\"undefined\\\" && image instanceof OffscreenCanvas;\\n\\t}\\n\\tuploadExternalImage(device, image, mipLevel, index) {\\n\\t\\tconst src = {\\n\\t\\t\\tsource: image,\\n\\t\\t\\torigin: [0, 0],\\n\\t\\t\\tflipY: false\\n\\t\\t};\\n\\t\\tconst dst = {\\n\\t\\t\\ttexture: this.gpuTexture,\\n\\t\\t\\tmipLevel,\\n\\t\\t\\torigin: [0, 0, index],\\n\\t\\t\\taspect: \\\"all\\\",\\n\\t\\t\\t// can be: \\\"all\\\", \\\"stencil-only\\\", \\\"depth-only\\\"\\n\\t\\t\\tpremultipliedAlpha: this.texture._premultiplyAlpha\\n\\t\\t};\\n\\t\\tconst copySize = {\\n\\t\\t\\twidth: this.desc.size.width,\\n\\t\\t\\theight: this.desc.size.height,\\n\\t\\t\\tdepthOrArrayLayers: 1\\n\\t\\t\\t// single layer\\n\\t\\t};\\n\\t\\tdevice.submit();\\n\\t\\tdummyUse(image instanceof HTMLCanvasElement && image.getContext(\\\"2d\\\"));\\n\\t\\tdevice.wgpu.queue.copyExternalImageToTexture(src, dst, copySize);\\n\\t}\\n\\t// upload a generic HTML element via the HTML-in-Canvas API (copyElementImageToTexture)\\n\\tuploadElementImage(device, element, mipLevel, index) {\\n\\t\\tconst dst = {\\n\\t\\t\\ttexture: this.gpuTexture,\\n\\t\\t\\tmipLevel,\\n\\t\\t\\torigin: [0, 0, index],\\n\\t\\t\\taspect: \\\"all\\\",\\n\\t\\t\\t// can be: \\\"all\\\", \\\"stencil-only\\\", \\\"depth-only\\\"\\n\\t\\t\\tpremultipliedAlpha: this.texture._premultiplyAlpha\\n\\t\\t};\\n\\t\\tconst width = TextureUtils.calcLevelDimension(this.texture.width, mipLevel);\\n\\t\\tconst height = TextureUtils.calcLevelDimension(this.texture.height, mipLevel);\\n\\t\\tdevice.submit();\\n\\t\\tconst source = { source: element };\\n\\t\\tconst destination = { destination: dst, width, height };\\n\\t\\tdevice.wgpu.queue.copyElementImageToTexture(source, destination);\\n\\t}\\n\\tuploadTypedArrayData(device, data, mipLevel, index) {\\n\\t\\tconst texture = this.texture;\\n\\t\\tconst wgpu = device.wgpu;\\n\\t\\tconst dest = {\\n\\t\\t\\ttexture: this.gpuTexture,\\n\\t\\t\\torigin: [0, 0, index],\\n\\t\\t\\tmipLevel\\n\\t\\t};\\n\\t\\tconst width = TextureUtils.calcLevelDimension(texture.width, mipLevel);\\n\\t\\tconst height = TextureUtils.calcLevelDimension(texture.height, mipLevel);\\n\\t\\tTextureUtils.calcLevelGpuSize(width, height, 1, texture.format);\\n\\t\\tconst formatInfo = pixelFormatInfo.get(texture.format);\\n\\t\\tlet dataLayout;\\n\\t\\tlet size;\\n\\t\\tif (formatInfo.size) {\\n\\t\\t\\tdataLayout = {\\n\\t\\t\\t\\toffset: 0,\\n\\t\\t\\t\\tbytesPerRow: formatInfo.size * width,\\n\\t\\t\\t\\trowsPerImage: height\\n\\t\\t\\t};\\n\\t\\t\\tsize = {\\n\\t\\t\\t\\twidth,\\n\\t\\t\\t\\theight\\n\\t\\t\\t};\\n\\t\\t} else if (formatInfo.blockSize) {\\n\\t\\t\\tconst blockDim = (size2) => {\\n\\t\\t\\t\\treturn Math.floor((size2 + 3) / 4);\\n\\t\\t\\t};\\n\\t\\t\\tdataLayout = {\\n\\t\\t\\t\\toffset: 0,\\n\\t\\t\\t\\tbytesPerRow: formatInfo.blockSize * blockDim(width),\\n\\t\\t\\t\\trowsPerImage: blockDim(height)\\n\\t\\t\\t};\\n\\t\\t\\tsize = {\\n\\t\\t\\t\\twidth: Math.max(4, width),\\n\\t\\t\\t\\theight: Math.max(4, height)\\n\\t\\t\\t};\\n\\t\\t} else ;\\n\\t\\tdevice.submit();\\n\\t\\twgpu.queue.writeTexture(dest, data, dataLayout, size);\\n\\t}\\n\\tread(x, y, width, height, options) {\\n\\t\\tconst mipLevel = options.mipLevel ?? 0;\\n\\t\\tconst face = options.face ?? 0;\\n\\t\\tconst data = options.data ?? null;\\n\\t\\tconst immediate = options.immediate ?? false;\\n\\t\\tconst texture = this.texture;\\n\\t\\tconst formatInfo = pixelFormatInfo.get(texture.format);\\n\\t\\tconst bytesPerRow = width * formatInfo.size;\\n\\t\\tconst paddedBytesPerRow = math.roundUp(bytesPerRow, 256);\\n\\t\\tconst size = paddedBytesPerRow * height;\\n\\t\\tconst device = texture.device;\\n\\t\\tconst stagingBuffer = device.createBufferImpl(BUFFERUSAGE_READ | BUFFERUSAGE_COPY_DST);\\n\\t\\tstagingBuffer.allocate(device, size);\\n\\t\\tconst src = {\\n\\t\\t\\ttexture: this.gpuTexture,\\n\\t\\t\\tmipLevel,\\n\\t\\t\\torigin: [x, y, face]\\n\\t\\t};\\n\\t\\tconst dst = {\\n\\t\\t\\tbuffer: stagingBuffer.buffer,\\n\\t\\t\\toffset: 0,\\n\\t\\t\\tbytesPerRow: paddedBytesPerRow\\n\\t\\t};\\n\\t\\tconst copySize = {\\n\\t\\t\\twidth,\\n\\t\\t\\theight,\\n\\t\\t\\tdepthOrArrayLayers: 1\\n\\t\\t\\t// single layer\\n\\t\\t};\\n\\t\\tconst commandEncoder = device.getCommandEncoder();\\n\\t\\tcommandEncoder.copyTextureToBuffer(src, dst, copySize);\\n\\t\\treturn device.readBuffer(stagingBuffer, size, null, immediate).then((temp) => {\\n\\t\\t\\tconst ArrayType = getPixelFormatArrayType(texture.format);\\n\\t\\t\\tconst targetBuffer = data?.buffer ?? new ArrayBuffer(height * bytesPerRow);\\n\\t\\t\\tconst target = new Uint8Array(targetBuffer, data?.byteOffset ?? 0, height * bytesPerRow);\\n\\t\\t\\tfor (let i = 0; i < height; i++) {\\n\\t\\t\\t\\tconst srcOffset = i * paddedBytesPerRow;\\n\\t\\t\\t\\tconst dstOffset = i * bytesPerRow;\\n\\t\\t\\t\\ttarget.set(temp.subarray(srcOffset, srcOffset + bytesPerRow), dstOffset);\\n\\t\\t\\t}\\n\\t\\t\\treturn data ?? new ArrayType(targetBuffer);\\n\\t\\t});\\n\\t}\\n}\\n\\nclass WebgpuUniformBuffer extends WebgpuBuffer {\\n\\tconstructor(uniformBuffer) {\\n\\t\\tsuper(BUFFERUSAGE_UNIFORM);\\n\\t}\\n\\tunlock(uniformBuffer) {\\n\\t\\tconst device = uniformBuffer.device;\\n\\t\\tsuper.unlock(device, uniformBuffer.storageInt32.buffer);\\n\\t}\\n}\\n\\nclass WebgpuVertexBuffer extends WebgpuBuffer {\\n\\tconstructor(vertexBuffer, format, options) {\\n\\t\\tsuper(BUFFERUSAGE_VERTEX | (options?.storage ? BUFFERUSAGE_STORAGE : 0));\\n\\t}\\n\\tunlock(vertexBuffer) {\\n\\t\\tconst device = vertexBuffer.device;\\n\\t\\tsuper.unlock(device, vertexBuffer.storage);\\n\\t}\\n}\\n\\nconst KEYWORD = /[ \\\\t]*#(ifn?def|if|endif|else|elif|define|undef|extension|include)/g;\\nconst DEFINE = /define[ \\\\t]+([^\\\\n]+)\\\\r?(?:\\\\n|$)/g;\\nconst EXTENSION = /extension[ \\\\t]+([\\\\w-]+)[ \\\\t]*:[ \\\\t]*(enable|require)/g;\\nconst UNDEF = /undef[ \\\\t]+([^\\\\n]+)\\\\r?(?:\\\\n|$)/g;\\nconst IF = /(ifdef|ifndef|if)[ \\\\t]*([^\\\\r\\\\n]+)\\\\r?\\\\n/g;\\nconst ENDIF = /(endif|else|elif)(?:[ \\\\t]+([^\\\\r\\\\n]*))?\\\\r?\\\\n?/g;\\nconst IDENTIFIER$1 = /\\\\{?[\\\\w-]+\\\\}?/;\\nconst DEFINED = /(!|\\\\s)?defined\\\\(([\\\\w-]+)\\\\)/;\\nconst DEFINED_PARENS = /!?defined\\\\s*\\\\([^)]*\\\\)/g;\\nconst DEFINED_BEFORE_PAREN = /!?defined\\\\s*$/;\\nconst COMPARISON = /([a-z_]\\\\w*)\\\\s*(==|!=|<|<=|>|>=)\\\\s*([\\\\w\\\"']+)/i;\\nconst INVALID = /[+\\\\-]/g;\\nconst INCLUDE = /include[ \\\\t]+\\\"([\\\\w-]+)(?:\\\\s*,\\\\s*([\\\\w-]+))?\\\"/g;\\nconst LOOP_INDEX = /\\\\{i\\\\}/g;\\nconst FRAGCOLOR = /(pcFragColor[1-8])\\\\b/g;\\nconst NUMERIC_LITERAL = /^\\\\d+(?:\\\\.\\\\d+)?$/;\\nclass Preprocessor {\\n\\tstatic sourceName;\\n\\tstatic run(source, includes = /* @__PURE__ */ new Map(), options = {}) {\\n\\t\\tPreprocessor.sourceName = options.sourceName;\\n\\t\\tsource = this.stripComments(source);\\n\\t\\tsource = source.split(/\\\\r?\\\\n/).map((line) => line.trimEnd()).join(\\\"\\\\n\\\");\\n\\t\\tconst defines = /* @__PURE__ */ new Map();\\n\\t\\tconst injectDefines = /* @__PURE__ */ new Map();\\n\\t\\tsource = this._preprocess(source, defines, injectDefines, includes, options.stripDefines);\\n\\t\\tif (source === null) return null;\\n\\t\\tconst intDefines = /* @__PURE__ */ new Map();\\n\\t\\tdefines.forEach((value, key) => {\\n\\t\\t\\tif (Number.isInteger(parseFloat(value)) && !value.includes(\\\".\\\")) {\\n\\t\\t\\t\\tintDefines.set(key, value);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tsource = this.stripComments(source);\\n\\t\\tsource = this.stripUnusedColorAttachments(source, options);\\n\\t\\tsource = this.RemoveEmptyLines(source);\\n\\t\\tsource = this.processArraySize(source, intDefines);\\n\\t\\tsource = this.injectDefines(source, injectDefines);\\n\\t\\treturn source;\\n\\t}\\n\\tstatic stripUnusedColorAttachments(source, options) {\\n\\t\\tif (options.stripUnusedColorAttachments) {\\n\\t\\t\\tconst counts = /* @__PURE__ */ new Map();\\n\\t\\t\\tconst matches = source.match(FRAGCOLOR);\\n\\t\\t\\tmatches?.forEach((match) => {\\n\\t\\t\\t\\tconst index = parseInt(match.charAt(match.length - 1), 10);\\n\\t\\t\\t\\tcounts.set(index, (counts.get(index) ?? 0) + 1);\\n\\t\\t\\t});\\n\\t\\t\\tconst anySingleUse = Array.from(counts.values()).some((count) => count === 1);\\n\\t\\t\\tif (anySingleUse) {\\n\\t\\t\\t\\tconst lines = source.split(\\\"\\\\n\\\");\\n\\t\\t\\t\\tconst keepLines = [];\\n\\t\\t\\t\\tfor (let i = 0; i < lines.length; i++) {\\n\\t\\t\\t\\t\\tconst match = lines[i].match(FRAGCOLOR);\\n\\t\\t\\t\\t\\tif (match) {\\n\\t\\t\\t\\t\\t\\tconst index = parseInt(match[0].charAt(match[0].length - 1), 10);\\n\\t\\t\\t\\t\\t\\tif (index > 0 && counts.get(index) === 1) {\\n\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tkeepLines.push(lines[i]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tsource = keepLines.join(\\\"\\\\n\\\");\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn source;\\n\\t}\\n\\tstatic stripComments(source) {\\n\\t\\treturn source.replace(/\\\\/\\\\*[\\\\s\\\\S]*?\\\\*\\\\/|([^\\\\\\\\:]|^)\\\\/\\\\/.*$/gm, \\\"$1\\\");\\n\\t}\\n\\tstatic processArraySize(source, intDefines) {\\n\\t\\tif (source !== null) {\\n\\t\\t\\tintDefines.forEach((value, key) => {\\n\\t\\t\\t\\tsource = source.replace(new RegExp(`\\\\\\\\[${key}\\\\\\\\]`, \\\"g\\\"), `[${value}]`);\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\treturn source;\\n\\t}\\n\\tstatic injectDefines(source, injectDefines) {\\n\\t\\tif (source !== null && injectDefines.size > 0) {\\n\\t\\t\\tconst lines = source.split(\\\"\\\\n\\\");\\n\\t\\t\\tinjectDefines.forEach((value, key) => {\\n\\t\\t\\t\\tconst regex = new RegExp(key, \\\"g\\\");\\n\\t\\t\\t\\tfor (let i = 0; i < lines.length; i++) {\\n\\t\\t\\t\\t\\tif (!lines[i].includes(\\\"#\\\")) {\\n\\t\\t\\t\\t\\t\\tlines[i] = lines[i].replace(regex, value);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t\\tsource = lines.join(\\\"\\\\n\\\");\\n\\t\\t}\\n\\t\\treturn source;\\n\\t}\\n\\tstatic RemoveEmptyLines(source) {\\n\\t\\tif (source !== null) {\\n\\t\\t\\tsource = source.split(/\\\\r?\\\\n/).map((line) => line.trim() === \\\"\\\" ? \\\"\\\" : line).join(\\\"\\\\n\\\");\\n\\t\\t\\tsource = source.replace(/(\\\\n\\\\n){3,}/g, \\\"\\\\n\\\\n\\\");\\n\\t\\t}\\n\\t\\treturn source;\\n\\t}\\n\\tstatic _preprocess(source, defines = /* @__PURE__ */ new Map(), injectDefines, includes, stripDefines) {\\n\\t\\tconst originalSource = source;\\n\\t\\tconst stack = [];\\n\\t\\tlet error = false;\\n\\t\\tlet match;\\n\\t\\twhile ((match = KEYWORD.exec(source)) !== null && !error) {\\n\\t\\t\\tconst keyword = match[1];\\n\\t\\t\\tswitch (keyword) {\\n\\t\\t\\t\\tcase \\\"define\\\": {\\n\\t\\t\\t\\t\\tDEFINE.lastIndex = match.index;\\n\\t\\t\\t\\t\\tconst define = DEFINE.exec(source);\\n\\t\\t\\t\\t\\terror || (error = define === null);\\n\\t\\t\\t\\t\\tconst expression = define[1];\\n\\t\\t\\t\\t\\tIDENTIFIER$1.lastIndex = define.index;\\n\\t\\t\\t\\t\\tconst identifierValue = IDENTIFIER$1.exec(expression);\\n\\t\\t\\t\\t\\tconst identifier = identifierValue[0];\\n\\t\\t\\t\\t\\tlet value = expression.substring(identifier.length).trim();\\n\\t\\t\\t\\t\\tif (value === \\\"\\\") value = \\\"true\\\";\\n\\t\\t\\t\\t\\tconst keep = Preprocessor._keep(stack);\\n\\t\\t\\t\\t\\tlet stripThisDefine = stripDefines;\\n\\t\\t\\t\\t\\tif (keep) {\\n\\t\\t\\t\\t\\t\\tconst replacementDefine = identifier.startsWith(\\\"{\\\") && identifier.endsWith(\\\"}\\\");\\n\\t\\t\\t\\t\\t\\tif (replacementDefine) {\\n\\t\\t\\t\\t\\t\\t\\tstripThisDefine = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (replacementDefine) {\\n\\t\\t\\t\\t\\t\\t\\tinjectDefines.set(identifier, value);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tdefines.set(identifier, value);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (stripThisDefine) {\\n\\t\\t\\t\\t\\t\\t\\tsource = source.substring(0, define.index - 1) + source.substring(DEFINE.lastIndex);\\n\\t\\t\\t\\t\\t\\t\\tKEYWORD.lastIndex = define.index - 1;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (!stripThisDefine) {\\n\\t\\t\\t\\t\\t\\tKEYWORD.lastIndex = define.index + define[0].length;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcase \\\"undef\\\": {\\n\\t\\t\\t\\t\\tUNDEF.lastIndex = match.index;\\n\\t\\t\\t\\t\\tconst undef = UNDEF.exec(source);\\n\\t\\t\\t\\t\\tconst identifier = undef[1].trim();\\n\\t\\t\\t\\t\\tconst keep = Preprocessor._keep(stack);\\n\\t\\t\\t\\t\\tif (keep) {\\n\\t\\t\\t\\t\\t\\tdefines.delete(identifier);\\n\\t\\t\\t\\t\\t\\tif (stripDefines) {\\n\\t\\t\\t\\t\\t\\t\\tsource = source.substring(0, undef.index - 1) + source.substring(UNDEF.lastIndex);\\n\\t\\t\\t\\t\\t\\t\\tKEYWORD.lastIndex = undef.index - 1;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (!stripDefines) {\\n\\t\\t\\t\\t\\t\\tKEYWORD.lastIndex = undef.index + undef[0].length;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcase \\\"extension\\\": {\\n\\t\\t\\t\\t\\tEXTENSION.lastIndex = match.index;\\n\\t\\t\\t\\t\\tconst extension = EXTENSION.exec(source);\\n\\t\\t\\t\\t\\terror || (error = extension === null);\\n\\t\\t\\t\\t\\tif (extension) {\\n\\t\\t\\t\\t\\t\\tconst identifier = extension[1];\\n\\t\\t\\t\\t\\t\\tconst keep = Preprocessor._keep(stack);\\n\\t\\t\\t\\t\\t\\tif (keep) {\\n\\t\\t\\t\\t\\t\\t\\tdefines.set(identifier, \\\"true\\\");\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tKEYWORD.lastIndex = extension.index + extension[0].length;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcase \\\"ifdef\\\":\\n\\t\\t\\t\\tcase \\\"ifndef\\\":\\n\\t\\t\\t\\tcase \\\"if\\\": {\\n\\t\\t\\t\\t\\tIF.lastIndex = match.index;\\n\\t\\t\\t\\t\\tconst iff = IF.exec(source);\\n\\t\\t\\t\\t\\tconst expression = iff[2];\\n\\t\\t\\t\\t\\tconst evaluated = Preprocessor.evaluate(expression, defines);\\n\\t\\t\\t\\t\\terror || (error = evaluated.error);\\n\\t\\t\\t\\t\\tlet result = evaluated.result;\\n\\t\\t\\t\\t\\tif (keyword === \\\"ifndef\\\") {\\n\\t\\t\\t\\t\\t\\tresult = !result;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tstack.push({\\n\\t\\t\\t\\t\\t\\tanyKeep: result,\\n\\t\\t\\t\\t\\t\\t// true if any branch was already accepted\\n\\t\\t\\t\\t\\t\\tkeep: result,\\n\\t\\t\\t\\t\\t\\t// true if this branch is being taken\\n\\t\\t\\t\\t\\t\\tstart: match.index,\\n\\t\\t\\t\\t\\t\\t// start index if IF line\\n\\t\\t\\t\\t\\t\\tend: IF.lastIndex\\n\\t\\t\\t\\t\\t\\t// end index of IF line\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\tKEYWORD.lastIndex = iff.index + iff[0].length;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcase \\\"endif\\\":\\n\\t\\t\\t\\tcase \\\"else\\\":\\n\\t\\t\\t\\tcase \\\"elif\\\": {\\n\\t\\t\\t\\t\\tENDIF.lastIndex = match.index;\\n\\t\\t\\t\\t\\tconst endif = ENDIF.exec(source);\\n\\t\\t\\t\\t\\tconst blockInfo = stack.pop();\\n\\t\\t\\t\\t\\tif (!blockInfo) {\\n\\t\\t\\t\\t\\t\\tconsole.error(`Shader preprocessing encountered \\\"#${endif[1]}\\\" without a preceding #if #ifdef #ifndef while preprocessing ${Preprocessor.sourceName} on line:\\n ${source.substring(match.index, match.index + 100)}...`, { source: originalSource });\\n\\t\\t\\t\\t\\t\\terror = true;\\n\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tconst blockCode = blockInfo.keep ? source.substring(blockInfo.end, match.index) : \\\"\\\";\\n\\t\\t\\t\\t\\tsource = source.substring(0, blockInfo.start) + blockCode + source.substring(ENDIF.lastIndex);\\n\\t\\t\\t\\t\\tKEYWORD.lastIndex = blockInfo.start + blockCode.length;\\n\\t\\t\\t\\t\\tconst endifCommand = endif[1];\\n\\t\\t\\t\\t\\tif (endifCommand === \\\"else\\\" || endifCommand === \\\"elif\\\") {\\n\\t\\t\\t\\t\\t\\tlet result = false;\\n\\t\\t\\t\\t\\t\\tif (!blockInfo.anyKeep) {\\n\\t\\t\\t\\t\\t\\t\\tif (endifCommand === \\\"else\\\") {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult = !blockInfo.keep;\\n\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst evaluated = Preprocessor.evaluate(endif[2], defines);\\n\\t\\t\\t\\t\\t\\t\\t\\tresult = evaluated.result;\\n\\t\\t\\t\\t\\t\\t\\t\\terror || (error = evaluated.error);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tstack.push({\\n\\t\\t\\t\\t\\t\\t\\tanyKeep: blockInfo.anyKeep || result,\\n\\t\\t\\t\\t\\t\\t\\tkeep: result,\\n\\t\\t\\t\\t\\t\\t\\tstart: KEYWORD.lastIndex,\\n\\t\\t\\t\\t\\t\\t\\tend: KEYWORD.lastIndex\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcase \\\"include\\\": {\\n\\t\\t\\t\\t\\tINCLUDE.lastIndex = match.index;\\n\\t\\t\\t\\t\\tconst include = INCLUDE.exec(source);\\n\\t\\t\\t\\t\\terror || (error = include === null);\\n\\t\\t\\t\\t\\tif (!include) {\\n\\t\\t\\t\\t\\t\\terror = true;\\n\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tconst identifier = include[1].trim();\\n\\t\\t\\t\\t\\tconst countIdentifier = include[2]?.trim();\\n\\t\\t\\t\\t\\tconst keep = Preprocessor._keep(stack);\\n\\t\\t\\t\\t\\tif (keep) {\\n\\t\\t\\t\\t\\t\\tlet includeSource = includes?.get(identifier);\\n\\t\\t\\t\\t\\t\\tif (includeSource !== void 0) {\\n\\t\\t\\t\\t\\t\\t\\tincludeSource = this.stripComments(includeSource);\\n\\t\\t\\t\\t\\t\\t\\tif (countIdentifier) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst countString = defines.get(countIdentifier);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst count = parseFloat(countString);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (Number.isInteger(count)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tlet result = \\\"\\\";\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult += includeSource.replace(LOOP_INDEX, String(i));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tincludeSource = result;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tconsole.error(`Include Count identifier \\\"${countIdentifier}\\\" not resolved while preprocessing ${Preprocessor.sourceName} on line:\\n ${source.substring(match.index, match.index + 100)}...`, { originalSource, source });\\n\\t\\t\\t\\t\\t\\t\\t\\t\\terror = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\tsource = source.substring(0, include.index - 1) + includeSource + source.substring(INCLUDE.lastIndex);\\n\\t\\t\\t\\t\\t\\t\\tKEYWORD.lastIndex = include.index - 1;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tconsole.error(`Include \\\"${identifier}\\\" not resolved while preprocessing ${Preprocessor.sourceName}`, { originalSource, source });\\n\\t\\t\\t\\t\\t\\t\\terror = true;\\n\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (stack.length > 0) {\\n\\t\\t\\tconsole.error(`Shader preprocessing reached the end of the file without encountering the necessary #endif to close a preceding #if, #ifdef, or #ifndef block. ${Preprocessor.sourceName}`);\\n\\t\\t\\terror = true;\\n\\t\\t}\\n\\t\\tif (error) {\\n\\t\\t\\tconsole.error(\\\"Failed to preprocess shader: \\\", { source: originalSource });\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\treturn source;\\n\\t}\\n\\t// function returns true if the evaluation is inside keep branches\\n\\tstatic _keep(stack) {\\n\\t\\tfor (let i = 0; i < stack.length; i++) {\\n\\t\\t\\tif (!stack[i].keep) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn true;\\n\\t}\\n\\tstatic evaluateAtomicExpression(expr, defines) {\\n\\t\\tlet error = false;\\n\\t\\texpr = expr.trim();\\n\\t\\tlet invert = false;\\n\\t\\tif (expr === \\\"true\\\") {\\n\\t\\t\\treturn { result: true, error };\\n\\t\\t}\\n\\t\\tif (expr === \\\"false\\\") {\\n\\t\\t\\treturn { result: false, error };\\n\\t\\t}\\n\\t\\tif (NUMERIC_LITERAL.test(expr)) {\\n\\t\\t\\treturn { result: parseFloat(expr) !== 0, error };\\n\\t\\t}\\n\\t\\tconst definedMatch = DEFINED.exec(expr);\\n\\t\\tif (definedMatch) {\\n\\t\\t\\tinvert = definedMatch[1] === \\\"!\\\";\\n\\t\\t\\texpr = definedMatch[2].trim();\\n\\t\\t\\tconst exists = defines.has(expr);\\n\\t\\t\\treturn { result: invert ? !exists : exists, error };\\n\\t\\t}\\n\\t\\tconst comparisonMatch = COMPARISON.exec(expr);\\n\\t\\tif (comparisonMatch) {\\n\\t\\t\\tconst left = defines.get(comparisonMatch[1].trim()) ?? comparisonMatch[1].trim();\\n\\t\\t\\tconst right = defines.get(comparisonMatch[3].trim()) ?? comparisonMatch[3].trim();\\n\\t\\t\\tconst operator = comparisonMatch[2].trim();\\n\\t\\t\\tlet result2 = false;\\n\\t\\t\\tswitch (operator) {\\n\\t\\t\\t\\tcase \\\"==\\\":\\n\\t\\t\\t\\t\\tresult2 = left === right;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase \\\"!=\\\":\\n\\t\\t\\t\\t\\tresult2 = left !== right;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase \\\"<\\\":\\n\\t\\t\\t\\t\\tresult2 = left < right;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase \\\"<=\\\":\\n\\t\\t\\t\\t\\tresult2 = left <= right;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase \\\">\\\":\\n\\t\\t\\t\\t\\tresult2 = left > right;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase \\\">=\\\":\\n\\t\\t\\t\\t\\tresult2 = left >= right;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\terror = true;\\n\\t\\t\\t}\\n\\t\\t\\treturn { result: result2, error };\\n\\t\\t}\\n\\t\\tconst result = defines.has(expr);\\n\\t\\treturn { result, error };\\n\\t}\\n\\tstatic processParentheses(expression, defines) {\\n\\t\\tlet error = false;\\n\\t\\tlet processed = expression.trim();\\n\\t\\twhile (processed.startsWith(\\\"(\\\") && processed.endsWith(\\\")\\\")) {\\n\\t\\t\\tlet depth = 0;\\n\\t\\t\\tlet wrapsEntire = true;\\n\\t\\t\\tfor (let i = 0; i < processed.length - 1; i++) {\\n\\t\\t\\t\\tif (processed[i] === \\\"(\\\") depth++;\\n\\t\\t\\t\\telse if (processed[i] === \\\")\\\") {\\n\\t\\t\\t\\t\\tdepth--;\\n\\t\\t\\t\\t\\tif (depth === 0) {\\n\\t\\t\\t\\t\\t\\twrapsEntire = false;\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (wrapsEntire) {\\n\\t\\t\\t\\tprocessed = processed.slice(1, -1).trim();\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\twhile (true) {\\n\\t\\t\\tlet foundParen = false;\\n\\t\\t\\tlet depth = 0;\\n\\t\\t\\tlet maxDepth = 0;\\n\\t\\t\\tlet deepestStart = -1;\\n\\t\\t\\tlet deepestEnd = -1;\\n\\t\\t\\tlet inDefinedParen = 0;\\n\\t\\t\\tfor (let i = 0; i < processed.length; i++) {\\n\\t\\t\\t\\tif (processed[i] === \\\"(\\\") {\\n\\t\\t\\t\\t\\tconst beforeParen = processed.substring(0, i);\\n\\t\\t\\t\\t\\tif (DEFINED_BEFORE_PAREN.test(beforeParen)) {\\n\\t\\t\\t\\t\\t\\tinDefinedParen++;\\n\\t\\t\\t\\t\\t} else if (inDefinedParen === 0) {\\n\\t\\t\\t\\t\\t\\tdepth++;\\n\\t\\t\\t\\t\\t\\tif (depth > maxDepth) {\\n\\t\\t\\t\\t\\t\\t\\tmaxDepth = depth;\\n\\t\\t\\t\\t\\t\\t\\tdeepestStart = i;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfoundParen = true;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else if (processed[i] === \\\")\\\") {\\n\\t\\t\\t\\t\\tif (inDefinedParen > 0) {\\n\\t\\t\\t\\t\\t\\tinDefinedParen--;\\n\\t\\t\\t\\t\\t} else if (depth > 0) {\\n\\t\\t\\t\\t\\t\\tif (depth === maxDepth && deepestStart !== -1) {\\n\\t\\t\\t\\t\\t\\t\\tdeepestEnd = i;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tdepth--;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (!foundParen || deepestStart === -1 || deepestEnd === -1) {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\tconst subExpr = processed.substring(deepestStart + 1, deepestEnd);\\n\\t\\t\\tconst { result, error: subError } = Preprocessor.evaluate(subExpr, defines);\\n\\t\\t\\terror = error || subError;\\n\\t\\t\\tprocessed = processed.substring(0, deepestStart) + (result ? \\\"true\\\" : \\\"false\\\") + processed.substring(deepestEnd + 1);\\n\\t\\t}\\n\\t\\treturn { expression: processed, error };\\n\\t}\\n\\tstatic evaluate(expression, defines) {\\n\\t\\tconst correct = INVALID.exec(expression) === null;\\n\\t\\tlet processedExpr = expression;\\n\\t\\tlet parenError = false;\\n\\t\\tconst withoutDefined = expression.replace(DEFINED_PARENS, \\\"\\\");\\n\\t\\tif (withoutDefined.indexOf(\\\"(\\\") !== -1) {\\n\\t\\t\\tconst processed = Preprocessor.processParentheses(expression, defines);\\n\\t\\t\\tprocessedExpr = processed.expression;\\n\\t\\t\\tparenError = processed.error;\\n\\t\\t}\\n\\t\\tif (parenError) {\\n\\t\\t\\treturn { result: false, error: true };\\n\\t\\t}\\n\\t\\tconst orSegments = processedExpr.split(\\\"||\\\");\\n\\t\\tfor (const orSegment of orSegments) {\\n\\t\\t\\tconst andSegments = orSegment.split(\\\"&&\\\");\\n\\t\\t\\tlet andResult = true;\\n\\t\\t\\tfor (const andSegment of andSegments) {\\n\\t\\t\\t\\tconst { result, error } = Preprocessor.evaluateAtomicExpression(andSegment.trim(), defines);\\n\\t\\t\\t\\tif (!result || error) {\\n\\t\\t\\t\\t\\tandResult = false;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (andResult) {\\n\\t\\t\\t\\treturn { result: true, error: !correct };\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn { result: false, error: !correct };\\n\\t}\\n}\\n\\nvar gles3_default$1 = `\\n#ifndef outType_0\\n#define outType_0 vec4\\n#endif\\nlayout(location = 0) out highp outType_0 pcFragColor0;\\n#if COLOR_ATTACHMENT_1\\nlayout(location = 1) out highp outType_1 pcFragColor1;\\n#endif\\n#if COLOR_ATTACHMENT_2\\nlayout(location = 2) out highp outType_2 pcFragColor2;\\n#endif\\n#if COLOR_ATTACHMENT_3\\nlayout(location = 3) out highp outType_3 pcFragColor3;\\n#endif\\n#if COLOR_ATTACHMENT_4\\nlayout(location = 4) out highp outType_4 pcFragColor4;\\n#endif\\n#if COLOR_ATTACHMENT_5\\nlayout(location = 5) out highp outType_5 pcFragColor5;\\n#endif\\n#if COLOR_ATTACHMENT_6\\nlayout(location = 6) out highp outType_6 pcFragColor6;\\n#endif\\n#if COLOR_ATTACHMENT_7\\nlayout(location = 7) out highp outType_7 pcFragColor7;\\n#endif\\n#define gl_FragColor pcFragColor0\\n#define varying in\\n#define texture2D texture\\n#define texture2DBias texture\\n#define textureCube texture\\n#define texture2DProj textureProj\\n#define texture2DLod textureLod\\n#define texture2DProjLod textureProjLod\\n#define textureCubeLod textureLod\\n#define texture2DGrad textureGrad\\n#define texture2DProjGrad textureProjGrad\\n#define textureCubeGrad textureGrad\\n#define utexture2D texture\\n#define itexture2D texture\\n#define texture2DLodEXT texture2DLodEXT_is_no_longer_supported_use_texture2DLod_instead\\n#define texture2DProjLodEXT texture2DProjLodEXT_is_no_longer_supported_use_texture2DProjLod\\n#define textureCubeLodEXT textureCubeLodEXT_is_no_longer_supported_use_textureCubeLod_instead\\n#define texture2DGradEXT texture2DGradEXT_is_no_longer_supported_use_texture2DGrad_instead\\n#define texture2DProjGradEXT texture2DProjGradEXT_is_no_longer_supported_use_texture2DProjGrad_instead\\n#define textureCubeGradEXT textureCubeGradEXT_is_no_longer_supported_use_textureCubeGrad_instead\\n#define textureShadow(res, uv) textureGrad(res, uv, vec2(1, 1), vec2(1, 1))\\n#define SHADOWMAP_PASS(name) name\\n#define SHADOWMAP_ACCEPT(name) sampler2DShadow name\\n#define TEXTURE_PASS(name) name\\n#define TEXTURE_ACCEPT(name) sampler2D name\\n#define TEXTURE_ACCEPT_HIGHP(name) highp sampler2D name\\n#define GL2\\n`;\\n\\nvar gles3_default = `\\n#extension GL_ANGLE_multi_draw : enable\\n#define attribute in\\n#define varying out\\n#define texture2D texture\\n#define utexture2D texture\\n#define itexture2D texture\\n#define GL2\\n#define VERTEXSHADER\\n#define TEXTURE_PASS(name) name\\n#define TEXTURE_ACCEPT(name) sampler2D name\\n#define TEXTURE_ACCEPT_HIGHP(name) highp sampler2D name\\n`;\\n\\nvar webgpu_default$1 = `\\n#extension GL_EXT_samplerless_texture_functions : require\\n#ifndef outType_0\\n#define outType_0 vec4\\n#endif\\n#ifndef outType_1\\n#define outType_1 vec4\\n#endif\\n#ifndef outType_2\\n#define outType_2 vec4\\n#endif\\n#ifndef outType_3\\n#define outType_3 vec4\\n#endif\\n#ifndef outType_4\\n#define outType_4 vec4\\n#endif\\n#ifndef outType_5\\n#define outType_5 vec4\\n#endif\\n#ifndef outType_6\\n#define outType_6 vec4\\n#endif\\n#ifndef outType_7\\n#define outType_7 vec4\\n#endif\\nlayout(location = 0) out highp outType_0 pcFragColor0;\\nlayout(location = 1) out highp outType_1 pcFragColor1;\\nlayout(location = 2) out highp outType_2 pcFragColor2;\\nlayout(location = 3) out highp outType_3 pcFragColor3;\\nlayout(location = 4) out highp outType_4 pcFragColor4;\\nlayout(location = 5) out highp outType_5 pcFragColor5;\\nlayout(location = 6) out highp outType_6 pcFragColor6;\\nlayout(location = 7) out highp outType_7 pcFragColor7;\\n#define gl_FragColor pcFragColor0\\n#define texture2D(res, uv) texture(sampler2D(res, res ## _sampler), uv)\\n#define texture2DBias(res, uv, bias) texture(sampler2D(res, res ## _sampler), uv, bias)\\n#define texture2DLod(res, uv, lod) textureLod(sampler2D(res, res ## _sampler), uv, lod)\\n#define textureCube(res, uv) texture(samplerCube(res, res ## _sampler), uv)\\n#define textureCubeLod(res, uv, lod) textureLod(samplerCube(res, res ## _sampler), uv, lod)\\n#define textureShadow(res, uv) textureLod(sampler2DShadow(res, res ## _sampler), uv, 0.0)\\n#define itexture2D(res, uv) texture(isampler2D(res, res ## _sampler), uv)\\n#define utexture2D(res, uv) texture(usampler2D(res, res ## _sampler), uv)\\n#define texture2DLodEXT texture2DLodEXT_is_no_longer_supported_use_texture2DLod_instead\\n#define texture2DProjLodEXT texture2DProjLodEXT_is_no_longer_supported_use_texture2DProjLod\\n#define textureCubeLodEXT textureCubeLodEXT_is_no_longer_supported_use_textureCubeLod_instead\\n#define texture2DGradEXT texture2DGradEXT_is_no_longer_supported_use_texture2DGrad_instead\\n#define texture2DProjGradEXT texture2DProjGradEXT_is_no_longer_supported_use_texture2DProjGrad_instead\\n#define textureCubeGradEXT textureCubeGradEXT_is_no_longer_supported_use_textureCubeGrad_instead\\n#define SHADOWMAP_PASS(name) name, name ## _sampler\\n#define SHADOWMAP_ACCEPT(name) texture2D name, sampler name ## _sampler\\n#define TEXTURE_PASS(name) name, name ## _sampler\\n#define TEXTURE_ACCEPT(name) texture2D name, sampler name ## _sampler\\n#define TEXTURE_ACCEPT_HIGHP TEXTURE_ACCEPT\\n#define GL2\\n#define WEBGPU\\n`;\\n\\nvar webgpu_default = `\\n#extension GL_EXT_samplerless_texture_functions : require\\n#define texture2D(res, uv) texture(sampler2D(res, res ## _sampler), uv)\\n#define itexture2D(res, uv) texture(isampler2D(res, res ## _sampler), uv)\\n#define utexture2D(res, uv) texture(usampler2D(res, res ## _sampler), uv)\\n#define TEXTURE_PASS(name) name, name ## _sampler\\n#define TEXTURE_ACCEPT(name) texture2D name, sampler name ## _sampler\\n#define TEXTURE_ACCEPT_HIGHP TEXTURE_ACCEPT\\n#define GL2\\n#define WEBGPU\\n#define VERTEXSHADER\\n#define gl_VertexID gl_VertexIndex\\n#define gl_InstanceID gl_InstanceIndex\\n`;\\n\\nvar webgpu_wgsl_default$1 = `\\n`;\\n\\nvar webgpu_wgsl_default = `\\n#define VERTEXSHADER\\n`;\\n\\nvar shared_default = `\\nvec2 getGrabScreenPos(vec4 clipPos) {\\n\\tvec2 uv = (clipPos.xy / clipPos.w) * 0.5 + 0.5;\\n\\t#ifdef WEBGPU\\n\\t\\tuv.y = 1.0 - uv.y;\\n\\t#endif\\n\\treturn uv;\\n}\\nvec2 getImageEffectUV(vec2 uv) {\\n\\t#ifdef WEBGPU\\n\\t\\tuv.y = 1.0 - uv.y;\\n\\t#endif\\n\\treturn uv;\\n}\\n`;\\n\\nvar shared_wgsl_default = `\\n#define WEBGPU\\nfn getGrabScreenPos(clipPos: vec4<f32>) -> vec2<f32> {\\n\\tvar uv: vec2<f32> = (clipPos.xy / clipPos.w) * 0.5 + vec2<f32>(0.5);\\n\\tuv.y = 1.0 - uv.y;\\n\\treturn uv;\\n}\\nfn getImageEffectUV(uv: vec2<f32>) -> vec2<f32> {\\n\\tvar modifiedUV: vec2<f32> = uv;\\n\\tmodifiedUV.y = 1.0 - modifiedUV.y;\\n\\treturn modifiedUV;\\n}\\nstruct WrappedF32 { @size(16) element: f32 }\\nstruct WrappedI32 { @size(16) element: i32 }\\nstruct WrappedU32 { @size(16) element: u32 }\\nstruct WrappedVec2F { @size(16) element: vec2f }\\nstruct WrappedVec2I { @size(16) element: vec2i }\\nstruct WrappedVec2U { @size(16) element: vec2u }\\n`;\\n\\nvar half_types_default = `\\n#ifdef CAPS_SHADER_F16\\n\\talias half = f16;\\n\\talias half2 = vec2<f16>;\\n\\talias half3 = vec3<f16>;\\n\\talias half4 = vec4<f16>;\\n\\talias half2x2 = mat2x2<f16>;\\n\\talias half3x3 = mat3x3<f16>;\\n\\talias half4x4 = mat4x4<f16>;\\n#else\\n\\talias half = f32;\\n\\talias half2 = vec2f;\\n\\talias half3 = vec3f;\\n\\talias half4 = vec4f;\\n\\talias half2x2 = mat2x2f;\\n\\talias half3x3 = mat3x3f;\\n\\talias half4x4 = mat4x4f;\\n#endif\\n`;\\n\\nconst _attrib2Semantic = {\\n\\tvertex_position: SEMANTIC_POSITION,\\n\\tvertex_normal: SEMANTIC_NORMAL,\\n\\tvertex_tangent: SEMANTIC_TANGENT,\\n\\tvertex_texCoord0: SEMANTIC_TEXCOORD0,\\n\\tvertex_texCoord1: SEMANTIC_TEXCOORD1,\\n\\tvertex_texCoord2: SEMANTIC_TEXCOORD2,\\n\\tvertex_texCoord3: SEMANTIC_TEXCOORD3,\\n\\tvertex_texCoord4: SEMANTIC_TEXCOORD4,\\n\\tvertex_texCoord5: SEMANTIC_TEXCOORD5,\\n\\tvertex_texCoord6: SEMANTIC_TEXCOORD6,\\n\\tvertex_texCoord7: SEMANTIC_TEXCOORD7,\\n\\tvertex_color: SEMANTIC_COLOR,\\n\\tvertex_boneIndices: SEMANTIC_BLENDINDICES,\\n\\tvertex_boneWeights: SEMANTIC_BLENDWEIGHT\\n};\\nclass ShaderDefinitionUtils {\\n\\tstatic createDefinition(device, options) {\\n\\t\\tconst normalizedOutputTypes = (options2) => {\\n\\t\\t\\tlet fragmentOutputTypes = options2.fragmentOutputTypes ?? \\\"vec4\\\";\\n\\t\\t\\tif (!Array.isArray(fragmentOutputTypes)) {\\n\\t\\t\\t\\tfragmentOutputTypes = [fragmentOutputTypes];\\n\\t\\t\\t}\\n\\t\\t\\treturn fragmentOutputTypes;\\n\\t\\t};\\n\\t\\tconst getDefines = (gpu, gl2, isVertex, options2) => {\\n\\t\\t\\tconst deviceIntro = device.isWebGPU ? gpu : gl2;\\n\\t\\t\\tlet attachmentsDefine = \\\"\\\";\\n\\t\\t\\tif (!isVertex) {\\n\\t\\t\\t\\tconst fragmentOutputTypes = normalizedOutputTypes(options2);\\n\\t\\t\\t\\tfor (let i = 0; i < device.maxColorAttachments; i++) {\\n\\t\\t\\t\\t\\tattachmentsDefine += `#define COLOR_ATTACHMENT_${i}\\n`;\\n\\t\\t\\t\\t\\tconst outType = fragmentOutputTypes[i] ?? \\\"vec4\\\";\\n\\t\\t\\t\\t\\tattachmentsDefine += `#define outType_${i} ${outType}\\n`;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\treturn attachmentsDefine + deviceIntro;\\n\\t\\t};\\n\\t\\tconst getDefinesWgsl = (isVertex, options2) => {\\n\\t\\t\\tlet code = ShaderDefinitionUtils.getWGSLEnables(device, isVertex ? \\\"vertex\\\" : \\\"fragment\\\");\\n\\t\\t\\tif (!isVertex) {\\n\\t\\t\\t\\tconst fragmentOutputTypes = normalizedOutputTypes(options2);\\n\\t\\t\\t\\tfor (let i = 0; i < device.maxColorAttachments; i++) {\\n\\t\\t\\t\\t\\tconst glslOutType = fragmentOutputTypes[i] ?? \\\"vec4\\\";\\n\\t\\t\\t\\t\\tconst wgslOutType = primitiveGlslToWgslTypeMap.get(glslOutType);\\n\\t\\t\\t\\t\\tcode += `alias pcOutType${i} = ${wgslOutType};\\n`;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\treturn code;\\n\\t\\t};\\n\\t\\tconst name = options.name ?? \\\"Untitled\\\";\\n\\t\\tlet vertCode;\\n\\t\\tlet fragCode;\\n\\t\\tconst vertexDefinesCode = ShaderDefinitionUtils.getDefinesCode(device, options.vertexDefines);\\n\\t\\tconst fragmentDefinesCode = ShaderDefinitionUtils.getDefinesCode(device, options.fragmentDefines);\\n\\t\\tconst wgsl = options.shaderLanguage === SHADERLANGUAGE_WGSL;\\n\\t\\tif (wgsl) {\\n\\t\\t\\tvertCode = `\\n\\t\\t\\t\\t\\t\\t\\t\\t${getDefinesWgsl(true, options)}\\n\\t\\t\\t\\t\\t\\t\\t\\t${vertexDefinesCode}\\n\\t\\t\\t\\t\\t\\t\\t\\t${half_types_default}\\n\\t\\t\\t\\t\\t\\t\\t\\t${webgpu_wgsl_default}\\n\\t\\t\\t\\t\\t\\t\\t\\t${shared_wgsl_default}\\n\\t\\t\\t\\t\\t\\t\\t\\t${options.vertexCode}\\n\\t\\t\\t\\t\\t\\t`;\\n\\t\\t\\tfragCode = `\\n\\t\\t\\t\\t\\t\\t\\t\\t${getDefinesWgsl(false, options)}\\n\\t\\t\\t\\t\\t\\t\\t\\t${fragmentDefinesCode}\\n\\t\\t\\t\\t\\t\\t\\t\\t${half_types_default}\\n\\t\\t\\t\\t\\t\\t\\t\\t${webgpu_wgsl_default$1}\\n\\t\\t\\t\\t\\t\\t\\t\\t${shared_wgsl_default}\\n\\t\\t\\t\\t\\t\\t\\t\\t${options.fragmentCode}\\n\\t\\t\\t\\t\\t\\t`;\\n\\t\\t} else {\\n\\t\\t\\tvertCode = `${ShaderDefinitionUtils.versionCode(device) + getDefines(webgpu_default, gles3_default, true, options) + vertexDefinesCode + ShaderDefinitionUtils.precisionCode(device)}\\n\\t\\t\\t\\t\\t\\t\\t\\t${shared_default}\\n\\t\\t\\t\\t\\t\\t\\t\\t${ShaderDefinitionUtils.getShaderNameCode(name)}\\n\\t\\t\\t\\t\\t\\t\\t\\t${options.vertexCode}`;\\n\\t\\t\\tfragCode = `${(options.fragmentPreamble || \\\"\\\") + ShaderDefinitionUtils.versionCode(device) + getDefines(webgpu_default$1, gles3_default$1, false, options) + fragmentDefinesCode + ShaderDefinitionUtils.precisionCode(device)}\\n\\t\\t\\t\\t\\t\\t\\t\\t${shared_default}\\n\\t\\t\\t\\t\\t\\t\\t\\t${ShaderDefinitionUtils.getShaderNameCode(name)}\\n\\t\\t\\t\\t\\t\\t\\t\\t${options.fragmentCode}`;\\n\\t\\t}\\n\\t\\treturn {\\n\\t\\t\\tname,\\n\\t\\t\\tshaderLanguage: options.shaderLanguage ?? SHADERLANGUAGE_GLSL,\\n\\t\\t\\tattributes: options.attributes,\\n\\t\\t\\tvshader: vertCode,\\n\\t\\t\\tvincludes: options.vertexIncludes,\\n\\t\\t\\tfincludes: options.fragmentIncludes,\\n\\t\\t\\tfshader: fragCode,\\n\\t\\t\\tfeedbackVaryings: options.feedbackVaryings,\\n\\t\\t\\tuseTransformFeedback: options.useTransformFeedback,\\n\\t\\t\\tmeshUniformBufferFormat: options.meshUniformBufferFormat,\\n\\t\\t\\tmeshBindGroupFormat: options.meshBindGroupFormat\\n\\t\\t};\\n\\t}\\n\\tstatic getWGSLEnables(device, shaderType) {\\n\\t\\tlet code = \\\"\\\";\\n\\t\\tif (device.supportsShaderF16) {\\n\\t\\t\\tcode += \\\"enable f16;\\\\n\\\";\\n\\t\\t}\\n\\t\\tif (shaderType === \\\"fragment\\\" && device.supportsPrimitiveIndex) {\\n\\t\\t\\tcode += \\\"enable primitive_index;\\\\n\\\";\\n\\t\\t}\\n\\t\\tif (device.supportsSubgroups) {\\n\\t\\t\\tcode += \\\"enable subgroups;\\\\n\\\";\\n\\t\\t}\\n\\t\\tif (device.supportsSubgroupId) {\\n\\t\\t\\tcode += \\\"requires subgroup_id;\\\\n\\\";\\n\\t\\t}\\n\\t\\tif (shaderType === \\\"compute\\\" && device.supportsLinearIndexing) {\\n\\t\\t\\tcode += \\\"requires linear_indexing;\\\\n\\\";\\n\\t\\t}\\n\\t\\tif (device.supportsUnrestrictedPointerParameters) {\\n\\t\\t\\tcode += \\\"requires unrestricted_pointer_parameters;\\\\n\\\";\\n\\t\\t}\\n\\t\\tif (device.supportsPointerCompositeAccess) {\\n\\t\\t\\tcode += \\\"requires pointer_composite_access;\\\\n\\\";\\n\\t\\t}\\n\\t\\tif (device.supportsPacked4x8IntegerDotProduct) {\\n\\t\\t\\tcode += \\\"requires packed_4x8_integer_dot_product;\\\\n\\\";\\n\\t\\t}\\n\\t\\tif (device.supportsTextureAndSamplerLet) {\\n\\t\\t\\tcode += \\\"requires texture_and_sampler_let;\\\\n\\\";\\n\\t\\t}\\n\\t\\treturn code;\\n\\t}\\n\\tstatic getDefinesCode(device, defines) {\\n\\t\\tlet code = \\\"\\\";\\n\\t\\tdevice.capsDefines.forEach((value, key) => {\\n\\t\\t\\tcode += `#define ${key} ${value}\\n`;\\n\\t\\t});\\n\\t\\tcode += \\\"\\\\n\\\";\\n\\t\\tdefines?.forEach((value, key) => {\\n\\t\\t\\tcode += `#define ${key} ${value}\\n`;\\n\\t\\t});\\n\\t\\tcode += \\\"\\\\n\\\";\\n\\t\\treturn code;\\n\\t}\\n\\t// SpectorJS integration\\n\\tstatic getShaderNameCode(name) {\\n\\t\\treturn `#define SHADER_NAME ${name}\\n`;\\n\\t}\\n\\tstatic versionCode(device) {\\n\\t\\treturn device.isWebGPU ? \\\"#version 450\\\\n\\\" : \\\"#version 300 es\\\\n\\\";\\n\\t}\\n\\tstatic precisionCode(device, forcePrecision) {\\n\\t\\tif (forcePrecision && forcePrecision !== \\\"highp\\\" && forcePrecision !== \\\"mediump\\\" && forcePrecision !== \\\"lowp\\\") {\\n\\t\\t\\tforcePrecision = null;\\n\\t\\t}\\n\\t\\tif (forcePrecision) {\\n\\t\\t\\tif (forcePrecision === \\\"highp\\\" && device.maxPrecision !== \\\"highp\\\") {\\n\\t\\t\\t\\tforcePrecision = \\\"mediump\\\";\\n\\t\\t\\t}\\n\\t\\t\\tif (forcePrecision === \\\"mediump\\\" && device.maxPrecision === \\\"lowp\\\") {\\n\\t\\t\\t\\tforcePrecision = \\\"lowp\\\";\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst precision = forcePrecision ? forcePrecision : device.precision;\\n\\t\\tconst code = `\\n\\t\\t\\t\\t\\t\\tprecision ${precision} float;\\n\\t\\t\\t\\t\\t\\tprecision ${precision} int;\\n\\t\\t\\t\\t\\t\\tprecision ${precision} usampler2D;\\n\\t\\t\\t\\t\\t\\tprecision ${precision} isampler2D;\\n\\t\\t\\t\\t\\t\\tprecision ${precision} sampler2DShadow;\\n\\t\\t\\t\\t\\t\\tprecision ${precision} samplerCubeShadow;\\n\\t\\t\\t\\t\\t\\tprecision ${precision} sampler2DArray;\\n\\t\\t\\t\\t`;\\n\\t\\treturn code;\\n\\t}\\n\\tstatic collectAttributes(vsCode) {\\n\\t\\tconst attribs = {};\\n\\t\\tlet attrs = 0;\\n\\t\\tlet found = vsCode.indexOf(\\\"attribute\\\");\\n\\t\\twhile (found >= 0) {\\n\\t\\t\\tif (found > 0 && vsCode[found - 1] === \\\"/\\\") break;\\n\\t\\t\\tlet ignore = false;\\n\\t\\t\\tif (found > 0) {\\n\\t\\t\\t\\tlet startOfLine = vsCode.lastIndexOf(\\\"\\\\n\\\", found);\\n\\t\\t\\t\\tstartOfLine = startOfLine !== -1 ? startOfLine + 1 : 0;\\n\\t\\t\\t\\tconst lineStartString = vsCode.substring(startOfLine, found);\\n\\t\\t\\t\\tif (lineStartString.includes(\\\"#\\\")) {\\n\\t\\t\\t\\t\\tignore = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (!ignore) {\\n\\t\\t\\t\\tconst endOfLine = vsCode.indexOf(\\\";\\\", found);\\n\\t\\t\\t\\tconst startOfAttribName = vsCode.lastIndexOf(\\\" \\\", endOfLine);\\n\\t\\t\\t\\tconst attribName = vsCode.substring(startOfAttribName + 1, endOfLine);\\n\\t\\t\\t\\tif (attribs[attribName]) ; else {\\n\\t\\t\\t\\t\\tconst semantic = _attrib2Semantic[attribName];\\n\\t\\t\\t\\t\\tif (semantic !== void 0) {\\n\\t\\t\\t\\t\\t\\tattribs[attribName] = semantic;\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tattribs[attribName] = `ATTR${attrs}`;\\n\\t\\t\\t\\t\\t\\tattrs++;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tfound = vsCode.indexOf(\\\"attribute\\\", found + 1);\\n\\t\\t}\\n\\t\\treturn attribs;\\n\\t}\\n}\\n\\nlet id$5 = 0;\\nclass Shader {\\n\\tmeshUniformBufferFormat;\\n\\tmeshBindGroupFormat;\\n\\tattributes = /* @__PURE__ */ new Map();\\n\\tconstructor(graphicsDevice, definition) {\\n\\t\\tthis.id = id$5++;\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tthis.definition = definition;\\n\\t\\tthis.name = definition.name || \\\"Untitled\\\";\\n\\t\\tthis.init();\\n\\t\\tif (definition.cshader) {\\n\\t\\t\\tconst enablesCode = ShaderDefinitionUtils.getWGSLEnables(graphicsDevice, \\\"compute\\\");\\n\\t\\t\\tconst definesCode = ShaderDefinitionUtils.getDefinesCode(graphicsDevice, definition.cdefines);\\n\\t\\t\\tconst cshader = enablesCode + definesCode + definition.cshader;\\n\\t\\t\\tconst cincludes = definition.cincludes ?? /* @__PURE__ */ new Map();\\n\\t\\t\\tif (!cincludes.has(\\\"halfTypesCS\\\")) {\\n\\t\\t\\t\\tcincludes.set(\\\"halfTypesCS\\\", half_types_default);\\n\\t\\t\\t}\\n\\t\\t\\tdefinition.cshader = Preprocessor.run(cshader, cincludes, {\\n\\t\\t\\t\\tsourceName: `compute shader for ${this.label}`,\\n\\t\\t\\t\\tstripDefines: true\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\tconst wgsl = definition.shaderLanguage === SHADERLANGUAGE_WGSL;\\n\\t\\t\\tdefinition.vshader = Preprocessor.run(definition.vshader, definition.vincludes, {\\n\\t\\t\\t\\tsourceName: `vertex shader for ${this.label}`,\\n\\t\\t\\t\\tstripDefines: wgsl\\n\\t\\t\\t});\\n\\t\\t\\tif (definition.shaderLanguage === SHADERLANGUAGE_GLSL) {\\n\\t\\t\\t\\tdefinition.attributes ?? (definition.attributes = ShaderDefinitionUtils.collectAttributes(definition.vshader));\\n\\t\\t\\t}\\n\\t\\t\\tconst stripUnusedColorAttachments = graphicsDevice.isWebGL2 && (platform.name === \\\"osx\\\" || platform.name === \\\"ios\\\");\\n\\t\\t\\tdefinition.fshader = Preprocessor.run(definition.fshader, definition.fincludes, {\\n\\t\\t\\t\\tstripUnusedColorAttachments,\\n\\t\\t\\t\\tstripDefines: wgsl,\\n\\t\\t\\t\\tsourceName: `fragment shader for ${this.label}`\\n\\t\\t\\t});\\n\\t\\t\\tif (!definition.vshader || !definition.fshader) {\\n\\t\\t\\t\\tthis.failed = true;\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.impl = graphicsDevice.createShaderImpl(this);\\n\\t}\\n\\tinit() {\\n\\t\\tthis.ready = false;\\n\\t\\tthis.failed = false;\\n\\t}\\n\\tget label() {\\n\\t\\treturn `Shader Id ${this.id} (${this.definition.shaderLanguage === SHADERLANGUAGE_WGSL ? \\\"WGSL\\\" : \\\"GLSL\\\"}) ${this.name}`;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.device.onDestroyShader(this);\\n\\t\\tthis.impl.destroy(this);\\n\\t}\\n\\tloseContext() {\\n\\t\\tthis.init();\\n\\t\\tthis.impl.loseContext();\\n\\t}\\n\\trestoreContext() {\\n\\t\\tthis.impl.restoreContext(this.device, this);\\n\\t}\\n}\\n\\nclass UsedBuffer {\\n\\tgpuBuffer;\\n\\tstagingBuffer;\\n\\toffset;\\n\\tsize;\\n}\\nclass DynamicBufferAllocation {\\n\\tstorage;\\n\\tgpuBuffer;\\n\\toffset;\\n}\\nclass DynamicBuffers {\\n\\tbufferSize;\\n\\tgpuBuffers = [];\\n\\tstagingBuffers = [];\\n\\tusedBuffers = [];\\n\\tactiveBuffer = null;\\n\\tconstructor(device, bufferSize, bufferAlignment) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.bufferSize = bufferSize;\\n\\t\\tthis.bufferAlignment = bufferAlignment;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.gpuBuffers.forEach((gpuBuffer) => {\\n\\t\\t\\tgpuBuffer.destroy(this.device);\\n\\t\\t});\\n\\t\\tthis.gpuBuffers = null;\\n\\t\\tthis.stagingBuffers.forEach((stagingBuffer) => {\\n\\t\\t\\tstagingBuffer.destroy(this.device);\\n\\t\\t});\\n\\t\\tthis.stagingBuffers = null;\\n\\t\\tthis.usedBuffers = null;\\n\\t\\tthis.activeBuffer = null;\\n\\t}\\n\\talloc(allocation, size) {\\n\\t\\tif (this.activeBuffer) {\\n\\t\\t\\tconst alignedStart2 = math.roundUp(this.activeBuffer.size, this.bufferAlignment);\\n\\t\\t\\tconst space = this.bufferSize - alignedStart2;\\n\\t\\t\\tif (space < size) {\\n\\t\\t\\t\\tthis.scheduleSubmit();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (!this.activeBuffer) {\\n\\t\\t\\tlet gpuBuffer = this.gpuBuffers.pop();\\n\\t\\t\\tif (!gpuBuffer) {\\n\\t\\t\\t\\tgpuBuffer = this.createBuffer(this.device, this.bufferSize, false);\\n\\t\\t\\t}\\n\\t\\t\\tlet stagingBuffer = this.stagingBuffers.pop();\\n\\t\\t\\tif (!stagingBuffer) {\\n\\t\\t\\t\\tstagingBuffer = this.createBuffer(this.device, this.bufferSize, true);\\n\\t\\t\\t}\\n\\t\\t\\tthis.activeBuffer = new UsedBuffer();\\n\\t\\t\\tthis.activeBuffer.stagingBuffer = stagingBuffer;\\n\\t\\t\\tthis.activeBuffer.gpuBuffer = gpuBuffer;\\n\\t\\t\\tthis.activeBuffer.offset = 0;\\n\\t\\t\\tthis.activeBuffer.size = 0;\\n\\t\\t}\\n\\t\\tconst activeBuffer = this.activeBuffer;\\n\\t\\tconst alignedStart = math.roundUp(activeBuffer.size, this.bufferAlignment);\\n\\t\\tallocation.gpuBuffer = activeBuffer.gpuBuffer;\\n\\t\\tallocation.offset = alignedStart;\\n\\t\\tallocation.storage = activeBuffer.stagingBuffer.alloc(alignedStart, size);\\n\\t\\tactiveBuffer.size = alignedStart + size;\\n\\t}\\n\\tscheduleSubmit() {\\n\\t\\tif (this.activeBuffer) {\\n\\t\\t\\tthis.usedBuffers.push(this.activeBuffer);\\n\\t\\t\\tthis.activeBuffer = null;\\n\\t\\t}\\n\\t}\\n\\tsubmit() {\\n\\t\\tthis.scheduleSubmit();\\n\\t}\\n}\\n\\nconst _updateFunctions = [];\\n_updateFunctions[UNIFORMTYPE_FLOAT] = function(uniformBuffer, value, offset) {\\n\\tconst dst = uniformBuffer.storageFloat32;\\n\\tdst[offset] = value;\\n};\\n_updateFunctions[UNIFORMTYPE_VEC2] = (uniformBuffer, value, offset) => {\\n\\tconst dst = uniformBuffer.storageFloat32;\\n\\tdst[offset] = value[0];\\n\\tdst[offset + 1] = value[1];\\n};\\n_updateFunctions[UNIFORMTYPE_VEC3] = (uniformBuffer, value, offset) => {\\n\\tconst dst = uniformBuffer.storageFloat32;\\n\\tdst[offset] = value[0];\\n\\tdst[offset + 1] = value[1];\\n\\tdst[offset + 2] = value[2];\\n};\\n_updateFunctions[UNIFORMTYPE_VEC4] = (uniformBuffer, value, offset) => {\\n\\tconst dst = uniformBuffer.storageFloat32;\\n\\tdst[offset] = value[0];\\n\\tdst[offset + 1] = value[1];\\n\\tdst[offset + 2] = value[2];\\n\\tdst[offset + 3] = value[3];\\n};\\n_updateFunctions[UNIFORMTYPE_INT] = function(uniformBuffer, value, offset) {\\n\\tconst dst = uniformBuffer.storageInt32;\\n\\tdst[offset] = value;\\n};\\n_updateFunctions[UNIFORMTYPE_IVEC2] = function(uniformBuffer, value, offset) {\\n\\tconst dst = uniformBuffer.storageInt32;\\n\\tdst[offset] = value[0];\\n\\tdst[offset + 1] = value[1];\\n};\\n_updateFunctions[UNIFORMTYPE_IVEC3] = function(uniformBuffer, value, offset) {\\n\\tconst dst = uniformBuffer.storageInt32;\\n\\tdst[offset] = value[0];\\n\\tdst[offset + 1] = value[1];\\n\\tdst[offset + 2] = value[2];\\n};\\n_updateFunctions[UNIFORMTYPE_IVEC4] = function(uniformBuffer, value, offset) {\\n\\tconst dst = uniformBuffer.storageInt32;\\n\\tdst[offset] = value[0];\\n\\tdst[offset + 1] = value[1];\\n\\tdst[offset + 2] = value[2];\\n\\tdst[offset + 3] = value[3];\\n};\\n_updateFunctions[UNIFORMTYPE_MAT2] = (uniformBuffer, value, offset) => {\\n\\tconst dst = uniformBuffer.storageFloat32;\\n\\tdst[offset] = value[0];\\n\\tdst[offset + 1] = value[1];\\n\\tdst[offset + 4] = value[2];\\n\\tdst[offset + 5] = value[3];\\n\\tdst[offset + 8] = value[4];\\n\\tdst[offset + 9] = value[5];\\n};\\n_updateFunctions[UNIFORMTYPE_MAT3] = (uniformBuffer, value, offset) => {\\n\\tconst dst = uniformBuffer.storageFloat32;\\n\\tdst[offset] = value[0];\\n\\tdst[offset + 1] = value[1];\\n\\tdst[offset + 2] = value[2];\\n\\tdst[offset + 4] = value[3];\\n\\tdst[offset + 5] = value[4];\\n\\tdst[offset + 6] = value[5];\\n\\tdst[offset + 8] = value[6];\\n\\tdst[offset + 9] = value[7];\\n\\tdst[offset + 10] = value[8];\\n};\\n_updateFunctions[UNIFORMTYPE_FLOATARRAY] = function(uniformBuffer, value, offset, count) {\\n\\tconst dst = uniformBuffer.storageFloat32;\\n\\tfor (let i = 0; i < count; i++) {\\n\\t\\tdst[offset + i * 4] = value[i];\\n\\t}\\n};\\n_updateFunctions[UNIFORMTYPE_VEC2ARRAY] = (uniformBuffer, value, offset, count) => {\\n\\tconst dst = uniformBuffer.storageFloat32;\\n\\tfor (let i = 0; i < count; i++) {\\n\\t\\tdst[offset + i * 4] = value[i * 2];\\n\\t\\tdst[offset + i * 4 + 1] = value[i * 2 + 1];\\n\\t}\\n};\\n_updateFunctions[UNIFORMTYPE_VEC3ARRAY] = (uniformBuffer, value, offset, count) => {\\n\\tconst dst = uniformBuffer.storageFloat32;\\n\\tfor (let i = 0; i < count; i++) {\\n\\t\\tdst[offset + i * 4] = value[i * 3];\\n\\t\\tdst[offset + i * 4 + 1] = value[i * 3 + 1];\\n\\t\\tdst[offset + i * 4 + 2] = value[i * 3 + 2];\\n\\t}\\n};\\n_updateFunctions[UNIFORMTYPE_UINT] = (uniformBuffer, value, offset, count) => {\\n\\tconst dst = uniformBuffer.storageUint32;\\n\\tdst[offset] = value;\\n};\\n_updateFunctions[UNIFORMTYPE_UVEC2] = (uniformBuffer, value, offset, count) => {\\n\\tconst dst = uniformBuffer.storageUint32;\\n\\tdst[offset] = value[0];\\n\\tdst[offset + 1] = value[1];\\n};\\n_updateFunctions[UNIFORMTYPE_UVEC3] = (uniformBuffer, value, offset, count) => {\\n\\tconst dst = uniformBuffer.storageUint32;\\n\\tdst[offset] = value[0];\\n\\tdst[offset + 1] = value[1];\\n\\tdst[offset + 2] = value[2];\\n};\\n_updateFunctions[UNIFORMTYPE_UVEC4] = (uniformBuffer, value, offset, count) => {\\n\\tconst dst = uniformBuffer.storageUint32;\\n\\tdst[offset] = value[0];\\n\\tdst[offset + 1] = value[1];\\n\\tdst[offset + 2] = value[2];\\n\\tdst[offset + 3] = value[3];\\n};\\n_updateFunctions[UNIFORMTYPE_INTARRAY] = function(uniformBuffer, value, offset, count) {\\n\\tconst dst = uniformBuffer.storageInt32;\\n\\tfor (let i = 0; i < count; i++) {\\n\\t\\tdst[offset + i * 4] = value[i];\\n\\t}\\n};\\n_updateFunctions[UNIFORMTYPE_BOOLARRAY] = _updateFunctions[UNIFORMTYPE_INTARRAY];\\n_updateFunctions[UNIFORMTYPE_UINTARRAY] = function(uniformBuffer, value, offset, count) {\\n\\tconst dst = uniformBuffer.storageUint32;\\n\\tfor (let i = 0; i < count; i++) {\\n\\t\\tdst[offset + i * 4] = value[i];\\n\\t}\\n};\\n_updateFunctions[UNIFORMTYPE_IVEC2ARRAY] = (uniformBuffer, value, offset, count) => {\\n\\tconst dst = uniformBuffer.storageInt32;\\n\\tfor (let i = 0; i < count; i++) {\\n\\t\\tdst[offset + i * 4] = value[i * 2];\\n\\t\\tdst[offset + i * 4 + 1] = value[i * 2 + 1];\\n\\t}\\n};\\n_updateFunctions[UNIFORMTYPE_BVEC2ARRAY] = _updateFunctions[UNIFORMTYPE_IVEC2ARRAY];\\n_updateFunctions[UNIFORMTYPE_UVEC2ARRAY] = (uniformBuffer, value, offset, count) => {\\n\\tconst dst = uniformBuffer.storageUint32;\\n\\tfor (let i = 0; i < count; i++) {\\n\\t\\tdst[offset + i * 4] = value[i * 2];\\n\\t\\tdst[offset + i * 4 + 1] = value[i * 2 + 1];\\n\\t}\\n};\\n_updateFunctions[UNIFORMTYPE_IVEC3ARRAY] = (uniformBuffer, value, offset, count) => {\\n\\tconst dst = uniformBuffer.storageInt32;\\n\\tfor (let i = 0; i < count; i++) {\\n\\t\\tdst[offset + i * 4] = value[i * 3];\\n\\t\\tdst[offset + i * 4 + 1] = value[i * 3 + 1];\\n\\t\\tdst[offset + i * 4 + 2] = value[i * 3 + 2];\\n\\t}\\n};\\n_updateFunctions[UNIFORMTYPE_BVEC3ARRAY] = _updateFunctions[UNIFORMTYPE_IVEC3ARRAY];\\n_updateFunctions[UNIFORMTYPE_UVEC3ARRAY] = (uniformBuffer, value, offset, count) => {\\n\\tconst dst = uniformBuffer.storageUint32;\\n\\tfor (let i = 0; i < count; i++) {\\n\\t\\tdst[offset + i * 4] = value[i * 3];\\n\\t\\tdst[offset + i * 4 + 1] = value[i * 3 + 1];\\n\\t\\tdst[offset + i * 4 + 2] = value[i * 3 + 2];\\n\\t}\\n};\\nclass UniformBuffer {\\n\\tdevice;\\n\\tpersistent;\\n\\tallocation;\\n\\tstorageFloat32;\\n\\tstorageInt32;\\n\\tstorageUint32;\\n\\trenderVersionDirty = 0;\\n\\tconstructor(graphicsDevice, format, persistent = true) {\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tthis.format = format;\\n\\t\\tthis.persistent = persistent;\\n\\t\\tif (persistent) {\\n\\t\\t\\tthis.impl = graphicsDevice.createUniformBufferImpl(this);\\n\\t\\t\\tconst storage = new ArrayBuffer(format.byteSize);\\n\\t\\t\\tthis.assignStorage(new Int32Array(storage));\\n\\t\\t\\tgraphicsDevice._vram.ub += this.format.byteSize;\\n\\t\\t} else {\\n\\t\\t\\tthis.allocation = new DynamicBufferAllocation();\\n\\t\\t}\\n\\t}\\n\\tdestroy() {\\n\\t\\tif (this.persistent) {\\n\\t\\t\\tconst device = this.device;\\n\\t\\t\\tthis.impl.destroy(device);\\n\\t\\t\\tdevice._vram.ub -= this.format.byteSize;\\n\\t\\t}\\n\\t}\\n\\tget offset() {\\n\\t\\treturn this.persistent ? 0 : this.allocation.offset;\\n\\t}\\n\\tassignStorage(storage) {\\n\\t\\tthis.storageInt32 = storage;\\n\\t\\tthis.storageUint32 = new Uint32Array(storage.buffer, storage.byteOffset, storage.byteLength / 4);\\n\\t\\tthis.storageFloat32 = new Float32Array(storage.buffer, storage.byteOffset, storage.byteLength / 4);\\n\\t}\\n\\tloseContext() {\\n\\t\\tthis.impl?.loseContext();\\n\\t}\\n\\tsetUniform(uniformFormat, value) {\\n\\t\\tconst offset = uniformFormat.offset;\\n\\t\\tif (value !== null && value !== void 0) {\\n\\t\\t\\tconst updateFunction = _updateFunctions[uniformFormat.updateType];\\n\\t\\t\\tif (updateFunction) {\\n\\t\\t\\t\\tupdateFunction(this, value, offset, uniformFormat.count);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.storageFloat32.set(value, offset);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tset(name, value) {\\n\\t\\tconst uniformFormat = this.format.map.get(name);\\n\\t\\tif (uniformFormat) {\\n\\t\\t\\tthis.setUniform(uniformFormat, value);\\n\\t\\t}\\n\\t}\\n\\tstartUpdate(dynamicBindGroup) {\\n\\t\\tif (!this.persistent) {\\n\\t\\t\\tconst allocation = this.allocation;\\n\\t\\t\\tconst oldGpuBuffer = allocation.gpuBuffer;\\n\\t\\t\\tthis.device.dynamicBuffers.alloc(allocation, this.format.byteSize);\\n\\t\\t\\tthis.assignStorage(allocation.storage);\\n\\t\\t\\tif (dynamicBindGroup) {\\n\\t\\t\\t\\tdynamicBindGroup.bindGroup = allocation.gpuBuffer.getBindGroup(this);\\n\\t\\t\\t\\tdynamicBindGroup.offsets[0] = allocation.offset;\\n\\t\\t\\t}\\n\\t\\t\\tif (oldGpuBuffer !== allocation.gpuBuffer) {\\n\\t\\t\\t\\tthis.renderVersionDirty = this.device.renderVersion;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tendUpdate() {\\n\\t\\tif (this.persistent) {\\n\\t\\t\\tthis.impl.unlock(this);\\n\\t\\t} else {\\n\\t\\t\\tthis.storageFloat32 = null;\\n\\t\\t\\tthis.storageInt32 = null;\\n\\t\\t}\\n\\t}\\n\\tupdate(dynamicBindGroup) {\\n\\t\\tthis.startUpdate(dynamicBindGroup);\\n\\t\\tconst uniforms = this.format.uniforms;\\n\\t\\tfor (let i = 0; i < uniforms.length; i++) {\\n\\t\\t\\tconst value = uniforms[i].scopeId.value;\\n\\t\\t\\tthis.setUniform(uniforms[i], value);\\n\\t\\t}\\n\\t\\tthis.endUpdate();\\n\\t}\\n}\\n\\nconst primitive = {\\n\\ttype: PRIMITIVE_TRISTRIP,\\n\\tbase: 0,\\n\\tbaseVertex: 0,\\n\\tcount: 4,\\n\\tindexed: false\\n};\\nclass WebgpuClearRenderer {\\n\\tconstructor(device) {\\n\\t\\tconst code = `\\n\\n\\t\\t\\t\\t\\t\\tstruct ub_mesh {\\n\\t\\t\\t\\t\\t\\t\\t\\tcolor : vec4f,\\n\\t\\t\\t\\t\\t\\t\\t\\tdepth: f32\\n\\t\\t\\t\\t\\t\\t}\\n\\n\\t\\t\\t\\t\\t\\t@group(2) @binding(0) var<uniform> ubMesh : ub_mesh;\\n\\n\\t\\t\\t\\t\\t\\tvar<private> pos : array<vec2f, 4> = array<vec2f, 4>(\\n\\t\\t\\t\\t\\t\\t\\t\\tvec2(-1.0, 1.0), vec2(1.0, 1.0),\\n\\t\\t\\t\\t\\t\\t\\t\\tvec2(-1.0, -1.0), vec2(1.0, -1.0)\\n\\t\\t\\t\\t\\t\\t);\\n\\n\\t\\t\\t\\t\\t\\tstruct VertexOutput {\\n\\t\\t\\t\\t\\t\\t\\t\\t@builtin(position) position : vec4f\\n\\t\\t\\t\\t\\t\\t}\\n\\n\\t\\t\\t\\t\\t\\t@vertex\\n\\t\\t\\t\\t\\t\\tfn vertexMain(@builtin(vertex_index) vertexIndex : u32) -> VertexOutput {\\n\\t\\t\\t\\t\\t\\t\\t\\tvar output : VertexOutput;\\n\\t\\t\\t\\t\\t\\t\\t\\toutput.position = vec4(pos[vertexIndex], ubMesh.depth, 1.0);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn output;\\n\\t\\t\\t\\t\\t\\t}\\n\\n\\t\\t\\t\\t\\t\\t@fragment\\n\\t\\t\\t\\t\\t\\tfn fragmentMain() -> @location(0) vec4f {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn ubMesh.color;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t`;\\n\\t\\tthis.shader = new Shader(device, {\\n\\t\\t\\tname: \\\"WebGPUClearRendererShader\\\",\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tvshader: code,\\n\\t\\t\\tfshader: code\\n\\t\\t});\\n\\t\\tthis.uniformBuffer = new UniformBuffer(device, new UniformBufferFormat(device, [\\n\\t\\t\\tnew UniformFormat(\\\"color\\\", UNIFORMTYPE_VEC4),\\n\\t\\t\\tnew UniformFormat(\\\"depth\\\", UNIFORMTYPE_FLOAT)\\n\\t\\t]), false);\\n\\t\\tthis.dynamicBindGroup = new DynamicBindGroup();\\n\\t\\tthis.colorData = new Float32Array(4);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.shader.destroy();\\n\\t\\tthis.shader = null;\\n\\t\\tthis.uniformBuffer.destroy();\\n\\t\\tthis.uniformBuffer = null;\\n\\t}\\n\\tclear(device, renderTarget, options, defaultOptions) {\\n\\t\\toptions = options || defaultOptions;\\n\\t\\tconst flags = options.flags ?? defaultOptions.flags;\\n\\t\\tif (flags !== 0) {\\n\\t\\t\\tconst { uniformBuffer, dynamicBindGroup } = this;\\n\\t\\t\\tuniformBuffer.startUpdate(dynamicBindGroup);\\n\\t\\t\\tdevice.setBindGroup(BINDGROUP_MESH_UB, dynamicBindGroup.bindGroup, dynamicBindGroup.offsets);\\n\\t\\t\\tdevice.setBindGroup(BINDGROUP_MESH, device.emptyBindGroup);\\n\\t\\t\\tlet blendState;\\n\\t\\t\\tif (flags & CLEARFLAG_COLOR && (renderTarget.colorBuffer || renderTarget.impl.assignedColorTexture)) {\\n\\t\\t\\t\\tconst color = options.color ?? defaultOptions.color;\\n\\t\\t\\t\\tthis.colorData.set(color);\\n\\t\\t\\t\\tblendState = BlendState.NOBLEND;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tblendState = BlendState.NOWRITE;\\n\\t\\t\\t}\\n\\t\\t\\tuniformBuffer.set(\\\"color\\\", this.colorData);\\n\\t\\t\\tlet depthState;\\n\\t\\t\\tif (flags & CLEARFLAG_DEPTH && renderTarget.depth) {\\n\\t\\t\\t\\tconst depth = options.depth ?? defaultOptions.depth;\\n\\t\\t\\t\\tuniformBuffer.set(\\\"depth\\\", depth);\\n\\t\\t\\t\\tdepthState = DepthState.WRITEDEPTH;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tuniformBuffer.set(\\\"depth\\\", 1);\\n\\t\\t\\t\\tdepthState = DepthState.NODEPTH;\\n\\t\\t\\t}\\n\\t\\t\\tif (flags & CLEARFLAG_STENCIL && renderTarget.stencil) ;\\n\\t\\t\\tuniformBuffer.endUpdate();\\n\\t\\t\\tdevice.setDrawStates(blendState, depthState);\\n\\t\\t\\tdevice.setShader(this.shader);\\n\\t\\t\\tdevice.draw(primitive);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass WebgpuMipmapRenderer {\\n\\tdevice;\\n\\tpipelineCache = /* @__PURE__ */ new Map();\\n\\tconstructor(device) {\\n\\t\\tthis.device = device;\\n\\t\\tconst code = `\\n \\n\\t\\t\\t\\t\\t\\tvar<private> pos : array<vec2f, 4> = array<vec2f, 4>(\\n\\t\\t\\t\\t\\t\\t\\t\\tvec2(-1.0, 1.0), vec2(1.0, 1.0),\\n\\t\\t\\t\\t\\t\\t\\t\\tvec2(-1.0, -1.0), vec2(1.0, -1.0)\\n\\t\\t\\t\\t\\t\\t);\\n\\n\\t\\t\\t\\t\\t\\tstruct VertexOutput {\\n\\t\\t\\t\\t\\t\\t\\t\\t@builtin(position) position : vec4f,\\n\\t\\t\\t\\t\\t\\t\\t\\t@location(0) texCoord : vec2f\\n\\t\\t\\t\\t\\t\\t};\\n\\n\\t\\t\\t\\t\\t\\t@vertex\\n\\t\\t\\t\\t\\t\\tfn vertexMain(@builtin(vertex_index) vertexIndex : u32) -> VertexOutput {\\n\\t\\t\\t\\t\\t\\t\\tvar output : VertexOutput;\\n\\t\\t\\t\\t\\t\\t\\toutput.texCoord = pos[vertexIndex] * vec2f(0.5, -0.5) + vec2f(0.5);\\n\\t\\t\\t\\t\\t\\t\\toutput.position = vec4f(pos[vertexIndex], 0, 1);\\n\\t\\t\\t\\t\\t\\t\\treturn output;\\n\\t\\t\\t\\t\\t\\t}\\n\\n\\t\\t\\t\\t\\t\\t@group(0) @binding(0) var imgSampler : sampler;\\n\\t\\t\\t\\t\\t\\t@group(0) @binding(1) var img : texture_2d<f32>;\\n\\n\\t\\t\\t\\t\\t\\t@fragment\\n\\t\\t\\t\\t\\t\\tfn fragmentMain(@location(0) texCoord : vec2f) -> @location(0) vec4f {\\n\\t\\t\\t\\t\\t\\t\\treturn textureSample(img, imgSampler, texCoord);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t`;\\n\\t\\tthis.shader = new Shader(device, {\\n\\t\\t\\tname: \\\"WebGPUMipmapRendererShader\\\",\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tvshader: code,\\n\\t\\t\\tfshader: code\\n\\t\\t});\\n\\t\\tthis.minSampler = device.wgpu.createSampler({ minFilter: \\\"linear\\\" });\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.shader.destroy();\\n\\t\\tthis.shader = null;\\n\\t\\tthis.pipelineCache.clear();\\n\\t}\\n\\tgenerate(webgpuTexture) {\\n\\t\\tconst textureDescr = webgpuTexture.desc;\\n\\t\\tif (textureDescr.mipLevelCount <= 1) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (webgpuTexture.texture.volume) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst device = this.device;\\n\\t\\tconst wgpu = device.wgpu;\\n\\t\\tconst format = textureDescr.format;\\n\\t\\tlet pipeline = this.pipelineCache.get(format);\\n\\t\\tif (!pipeline) {\\n\\t\\t\\tconst webgpuShader = this.shader.impl;\\n\\t\\t\\tpipeline = wgpu.createRenderPipeline({\\n\\t\\t\\t\\tlayout: \\\"auto\\\",\\n\\t\\t\\t\\tvertex: {\\n\\t\\t\\t\\t\\tmodule: webgpuShader.getVertexShaderModule(),\\n\\t\\t\\t\\t\\tentryPoint: webgpuShader.vertexEntryPoint\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\tfragment: {\\n\\t\\t\\t\\t\\tmodule: webgpuShader.getFragmentShaderModule(),\\n\\t\\t\\t\\t\\tentryPoint: webgpuShader.fragmentEntryPoint,\\n\\t\\t\\t\\t\\ttargets: [{\\n\\t\\t\\t\\t\\t\\tformat\\n\\t\\t\\t\\t\\t}]\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\tprimitive: {\\n\\t\\t\\t\\t\\ttopology: \\\"triangle-strip\\\"\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t\\tthis.pipelineCache.set(format, pipeline);\\n\\t\\t}\\n\\t\\tconst texture = webgpuTexture.texture;\\n\\t\\tconst numFaces = texture.cubemap ? 6 : texture.array ? texture.arrayLength : 1;\\n\\t\\tconst srcViews = [];\\n\\t\\tfor (let face = 0; face < numFaces; face++) {\\n\\t\\t\\tsrcViews.push(webgpuTexture.createView({\\n\\t\\t\\t\\tdimension: \\\"2d\\\",\\n\\t\\t\\t\\tbaseMipLevel: 0,\\n\\t\\t\\t\\tmipLevelCount: 1,\\n\\t\\t\\t\\tbaseArrayLayer: face\\n\\t\\t\\t}));\\n\\t\\t}\\n\\t\\tconst commandEncoder = device.getCommandEncoder();\\n\\t\\tfor (let i = 1; i < textureDescr.mipLevelCount; i++) {\\n\\t\\t\\tfor (let face = 0; face < numFaces; face++) {\\n\\t\\t\\t\\tconst dstView = webgpuTexture.createView({\\n\\t\\t\\t\\t\\tdimension: \\\"2d\\\",\\n\\t\\t\\t\\t\\tbaseMipLevel: i,\\n\\t\\t\\t\\t\\tmipLevelCount: 1,\\n\\t\\t\\t\\t\\tbaseArrayLayer: face\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst passEncoder = commandEncoder.beginRenderPass({\\n\\t\\t\\t\\t\\tcolorAttachments: [{\\n\\t\\t\\t\\t\\t\\tview: dstView,\\n\\t\\t\\t\\t\\t\\tloadOp: \\\"clear\\\",\\n\\t\\t\\t\\t\\t\\tstoreOp: \\\"store\\\"\\n\\t\\t\\t\\t\\t}]\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst bindGroup = wgpu.createBindGroup({\\n\\t\\t\\t\\t\\tlayout: pipeline.getBindGroupLayout(0),\\n\\t\\t\\t\\t\\tentries: [{\\n\\t\\t\\t\\t\\t\\tbinding: 0,\\n\\t\\t\\t\\t\\t\\tresource: this.minSampler\\n\\t\\t\\t\\t\\t}, {\\n\\t\\t\\t\\t\\t\\tbinding: 1,\\n\\t\\t\\t\\t\\t\\tresource: srcViews[face]\\n\\t\\t\\t\\t\\t}]\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tpassEncoder.setPipeline(pipeline);\\n\\t\\t\\t\\tpassEncoder.setBindGroup(0, bindGroup);\\n\\t\\t\\t\\tpassEncoder.draw(4);\\n\\t\\t\\t\\tpassEncoder.end();\\n\\t\\t\\t\\tsrcViews[face] = dstView;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdevice.pipeline = null;\\n\\t}\\n}\\n\\nclass DynamicBuffer {\\n\\tdevice;\\n\\tbindGroupCache = /* @__PURE__ */ new Map();\\n\\tconstructor(device) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.bindGroupFormat = new BindGroupFormat(this.device, [\\n\\t\\t\\tnew BindUniformBufferFormat(UNIFORM_BUFFER_DEFAULT_SLOT_NAME, SHADERSTAGE_VERTEX | SHADERSTAGE_FRAGMENT)\\n\\t\\t]);\\n\\t}\\n\\tgetBindGroup(ub) {\\n\\t\\tconst ubSize = ub.format.byteSize;\\n\\t\\tlet bindGroup = this.bindGroupCache.get(ubSize);\\n\\t\\tif (!bindGroup) {\\n\\t\\t\\tbindGroup = new BindGroup(this.device, this.bindGroupFormat, ub);\\n\\t\\t\\tbindGroup.update();\\n\\t\\t\\tthis.bindGroupCache.set(ubSize, bindGroup);\\n\\t\\t}\\n\\t\\treturn bindGroup;\\n\\t}\\n}\\n\\nclass WebgpuDynamicBuffer extends DynamicBuffer {\\n\\tbuffer = null;\\n\\tmappedRange = null;\\n\\tconstructor(device, size, isStaging) {\\n\\t\\tsuper(device);\\n\\t\\tthis.buffer = device.wgpu.createBuffer({\\n\\t\\t\\tsize,\\n\\t\\t\\tusage: isStaging ? GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC : GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\\n\\t\\t\\tmappedAtCreation: isStaging\\n\\t\\t});\\n\\t\\tif (isStaging) {\\n\\t\\t\\tthis.onAvailable();\\n\\t\\t}\\n\\t\\tdevice._vram.ub += size;\\n\\t}\\n\\tdestroy(device) {\\n\\t\\tdevice._vram.ub -= this.buffer.size;\\n\\t\\tthis.buffer.destroy();\\n\\t\\tthis.buffer = null;\\n\\t}\\n\\tonAvailable() {\\n\\t\\tthis.mappedRange = this.buffer.getMappedRange();\\n\\t}\\n\\talloc(offset, size) {\\n\\t\\treturn new Int32Array(this.mappedRange, offset, size / 4);\\n\\t}\\n}\\n\\nclass WebgpuDynamicBuffers extends DynamicBuffers {\\n\\tpendingStagingBuffers = [];\\n\\tcreateBuffer(device, size, isStaging) {\\n\\t\\treturn new WebgpuDynamicBuffer(device, size, isStaging);\\n\\t}\\n\\tsubmit() {\\n\\t\\tsuper.submit();\\n\\t\\tconst count = this.usedBuffers.length;\\n\\t\\tif (count) {\\n\\t\\t\\tconst device = this.device;\\n\\t\\t\\tconst gpuBuffers = this.gpuBuffers;\\n\\t\\t\\tconst commandEncoder = device.wgpu.createCommandEncoder();\\n\\t\\t\\tfor (let i = count - 1; i >= 0; i--) {\\n\\t\\t\\t\\tconst usedBuffer = this.usedBuffers[i];\\n\\t\\t\\t\\tconst { stagingBuffer, gpuBuffer, offset, size } = usedBuffer;\\n\\t\\t\\t\\tconst src = stagingBuffer.buffer;\\n\\t\\t\\t\\tsrc.unmap();\\n\\t\\t\\t\\tcommandEncoder.copyBufferToBuffer(src, offset, gpuBuffer.buffer, offset, size);\\n\\t\\t\\t\\tgpuBuffers.push(gpuBuffer);\\n\\t\\t\\t}\\n\\t\\t\\tconst cb = commandEncoder.finish();\\n\\t\\t\\tdevice.addCommandBuffer(cb, true);\\n\\t\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\t\\tconst stagingBuffer = this.usedBuffers[i].stagingBuffer;\\n\\t\\t\\t\\tthis.pendingStagingBuffers.push(stagingBuffer);\\n\\t\\t\\t}\\n\\t\\t\\tthis.usedBuffers.length = 0;\\n\\t\\t}\\n\\t}\\n\\tonCommandBuffersSubmitted() {\\n\\t\\tconst count = this.pendingStagingBuffers.length;\\n\\t\\tif (count) {\\n\\t\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\t\\tconst stagingBuffer = this.pendingStagingBuffers[i];\\n\\t\\t\\t\\tstagingBuffer.buffer.mapAsync(GPUMapMode.WRITE).then(() => {\\n\\t\\t\\t\\t\\tif (this.stagingBuffers) {\\n\\t\\t\\t\\t\\t\\tstagingBuffer.onAvailable();\\n\\t\\t\\t\\t\\t\\tthis.stagingBuffers.push(stagingBuffer);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t\\tthis.pendingStagingBuffers.length = 0;\\n\\t\\t}\\n\\t}\\n}\\n\\nclass GpuProfiler {\\n\\tframeAllocations = [];\\n\\tpastFrameAllocations = /* @__PURE__ */ new Map();\\n\\t_enabled = false;\\n\\t_enableRequest = false;\\n\\t_frameTime = 0;\\n\\t_passTimings = /* @__PURE__ */ new Map();\\n\\t_nameCache = /* @__PURE__ */ new Map();\\n\\tmaxCount = 9999;\\n\\tloseContext() {\\n\\t\\tthis.pastFrameAllocations.clear();\\n\\t}\\n\\tset enabled(value) {\\n\\t\\tthis._enableRequest = value;\\n\\t}\\n\\tget enabled() {\\n\\t\\treturn this._enableRequest;\\n\\t}\\n\\tget passTimings() {\\n\\t\\treturn this._passTimings;\\n\\t}\\n\\tprocessEnableRequest() {\\n\\t\\tif (this._enableRequest !== this._enabled) {\\n\\t\\t\\tthis._enabled = this._enableRequest;\\n\\t\\t\\tif (!this._enabled) {\\n\\t\\t\\t\\tthis._frameTime = 0;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\trequest(renderVersion) {\\n\\t\\tthis.pastFrameAllocations.set(renderVersion, this.frameAllocations);\\n\\t\\tthis.frameAllocations = [];\\n\\t}\\n\\t_parsePassName(name) {\\n\\t\\tlet parsedName = this._nameCache.get(name);\\n\\t\\tif (parsedName === void 0) {\\n\\t\\t\\tif (name.startsWith(\\\"RenderPass\\\")) {\\n\\t\\t\\t\\tparsedName = name.substring(10);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tparsedName = name;\\n\\t\\t\\t}\\n\\t\\t\\tthis._nameCache.set(name, parsedName);\\n\\t\\t}\\n\\t\\treturn parsedName;\\n\\t}\\n\\treport(renderVersion, timings) {\\n\\t\\tif (timings) {\\n\\t\\t\\tconst allocations = this.pastFrameAllocations.get(renderVersion);\\n\\t\\t\\tif (!allocations) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tif (timings.length > 0) {\\n\\t\\t\\t\\tthis._frameTime = timings.reduce((sum, t) => sum + t, 0);\\n\\t\\t\\t}\\n\\t\\t\\tthis._passTimings.clear();\\n\\t\\t\\tfor (let i = 0; i < allocations.length; ++i) {\\n\\t\\t\\t\\tconst name = allocations[i];\\n\\t\\t\\t\\tconst timing = timings[i];\\n\\t\\t\\t\\tconst parsedName = this._parsePassName(name);\\n\\t\\t\\t\\tthis._passTimings.set(parsedName, (this._passTimings.get(parsedName) || 0) + timing);\\n\\t\\t\\t}\\n\\t\\t\\tif (Tracing.get(TRACEID_GPU_TIMINGS)) {\\n\\t\\t\\t\\tlet total = 0;\\n\\t\\t\\t\\tfor (let i = 0; i < allocations.length; ++i) {\\n\\t\\t\\t\\t\\tallocations[i];\\n\\t\\t\\t\\t\\ttotal += timings[i];\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.pastFrameAllocations.delete(renderVersion);\\n\\t}\\n\\tgetSlot(name) {\\n\\t\\tif (this.frameAllocations.length >= this.maxCount) {\\n\\t\\t\\treturn -1;\\n\\t\\t}\\n\\t\\tconst slot = this.frameAllocations.length;\\n\\t\\tthis.frameAllocations.push(name);\\n\\t\\treturn slot;\\n\\t}\\n\\tget slotCount() {\\n\\t\\treturn this.frameAllocations.length;\\n\\t}\\n}\\n\\nclass WebgpuQuerySet {\\n\\tquerySet;\\n\\tstagingBuffers = [];\\n\\tactiveStagingBuffer = null;\\n\\tbytesPerSlot;\\n\\tconstructor(device, isTimestamp, capacity) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.capacity = capacity;\\n\\t\\tthis.bytesPerSlot = isTimestamp ? 8 : 4;\\n\\t\\tconst wgpu = device.wgpu;\\n\\t\\tthis.querySet = wgpu.createQuerySet({\\n\\t\\t\\ttype: isTimestamp ? \\\"timestamp\\\" : \\\"occlusion\\\",\\n\\t\\t\\tcount: capacity\\n\\t\\t});\\n\\t\\tthis.queryBuffer = wgpu.createBuffer({\\n\\t\\t\\tsize: this.bytesPerSlot * capacity,\\n\\t\\t\\tusage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST\\n\\t\\t});\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.device.deferDestroy(this.querySet);\\n\\t\\tthis.querySet = null;\\n\\t\\tthis.device.deferDestroy(this.queryBuffer);\\n\\t\\tthis.queryBuffer = null;\\n\\t\\tthis.activeStagingBuffer = null;\\n\\t\\tthis.stagingBuffers.forEach((stagingBuffer) => {\\n\\t\\t\\tstagingBuffer.destroy();\\n\\t\\t});\\n\\t\\tthis.stagingBuffers = null;\\n\\t}\\n\\tgetStagingBuffer() {\\n\\t\\tlet stagingBuffer = this.stagingBuffers.pop();\\n\\t\\tif (!stagingBuffer) {\\n\\t\\t\\tstagingBuffer = this.device.wgpu.createBuffer({\\n\\t\\t\\t\\tsize: this.queryBuffer.size,\\n\\t\\t\\t\\tusage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\treturn stagingBuffer;\\n\\t}\\n\\tresolve(count) {\\n\\t\\tconst device = this.device;\\n\\t\\tconst commandEncoder = device.getCommandEncoder();\\n\\t\\tcommandEncoder.resolveQuerySet(this.querySet, 0, count, this.queryBuffer, 0);\\n\\t\\tconst activeStagingBuffer = this.getStagingBuffer();\\n\\t\\tthis.activeStagingBuffer = activeStagingBuffer;\\n\\t\\tcommandEncoder.copyBufferToBuffer(this.queryBuffer, 0, activeStagingBuffer, 0, this.bytesPerSlot * count);\\n\\t}\\n\\trequest(count, renderVersion) {\\n\\t\\tconst stagingBuffer = this.activeStagingBuffer;\\n\\t\\tthis.activeStagingBuffer = null;\\n\\t\\treturn stagingBuffer.mapAsync(GPUMapMode.READ).then(() => {\\n\\t\\t\\tconst srcTimings = new BigInt64Array(stagingBuffer.getMappedRange());\\n\\t\\t\\tconst timings = [];\\n\\t\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\t\\ttimings.push(Number(srcTimings[i * 2 + 1] - srcTimings[i * 2]) * 1e-6);\\n\\t\\t\\t}\\n\\t\\t\\tstagingBuffer.unmap();\\n\\t\\t\\tthis.stagingBuffers?.push(stagingBuffer);\\n\\t\\t\\treturn {\\n\\t\\t\\t\\trenderVersion,\\n\\t\\t\\t\\ttimings\\n\\t\\t\\t};\\n\\t\\t});\\n\\t}\\n}\\n\\nclass WebgpuGpuProfiler extends GpuProfiler {\\n\\tdevice;\\n\\tframeGPUMarkerSlot;\\n\\tconstructor(device) {\\n\\t\\tsuper();\\n\\t\\tthis.device = device;\\n\\t\\tthis.maxCount = 1024;\\n\\t\\tthis.timestampQueriesSet = device.supportsTimestampQuery ? new WebgpuQuerySet(device, true, 2 * this.maxCount) : null;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.timestampQueriesSet?.destroy();\\n\\t\\tthis.timestampQueriesSet = null;\\n\\t}\\n\\tframeStart() {\\n\\t\\tthis.processEnableRequest();\\n\\t}\\n\\tframeEnd() {\\n\\t\\tif (this._enabled) {\\n\\t\\t\\tthis.timestampQueriesSet?.resolve(this.slotCount * 2);\\n\\t\\t}\\n\\t}\\n\\trequest() {\\n\\t\\tif (this._enabled) {\\n\\t\\t\\tconst renderVersion = this.device.renderVersion;\\n\\t\\t\\tthis.timestampQueriesSet?.request(this.slotCount, renderVersion).then((results) => {\\n\\t\\t\\t\\tthis.report(results.renderVersion, results.timings);\\n\\t\\t\\t});\\n\\t\\t\\tsuper.request(renderVersion);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass WebgpuResolver {\\n\\tdevice;\\n\\tpipelineCache = /* @__PURE__ */ new Map();\\n\\tconstructor(device) {\\n\\t\\tthis.device = device;\\n\\t\\tconst code = `\\n \\n\\t\\t\\t\\t\\t\\tvar<private> pos : array<vec2f, 4> = array<vec2f, 4>(\\n\\t\\t\\t\\t\\t\\t\\t\\tvec2(-1.0, 1.0), vec2(1.0, 1.0), vec2(-1.0, -1.0), vec2(1.0, -1.0)\\n\\t\\t\\t\\t\\t\\t);\\n\\n\\t\\t\\t\\t\\t\\tstruct VertexOutput {\\n\\t\\t\\t\\t\\t\\t\\t\\t@builtin(position) position : vec4f,\\n\\t\\t\\t\\t\\t\\t};\\n\\n\\t\\t\\t\\t\\t\\t@vertex\\n\\t\\t\\t\\t\\t\\tfn vertexMain(@builtin(vertex_index) vertexIndex : u32) -> VertexOutput {\\n\\t\\t\\t\\t\\t\\t\\tvar output : VertexOutput;\\n\\t\\t\\t\\t\\t\\t\\toutput.position = vec4f(pos[vertexIndex], 0, 1);\\n\\t\\t\\t\\t\\t\\t\\treturn output;\\n\\t\\t\\t\\t\\t\\t}\\n\\n\\t\\t\\t\\t\\t\\t@group(0) @binding(0) var img : texture_depth_multisampled_2d;\\n\\n\\t\\t\\t\\t\\t\\t@fragment\\n\\t\\t\\t\\t\\t\\tfn fragmentMain(@builtin(position) fragColor: vec4f) -> @location(0) vec4f {\\n\\t\\t\\t\\t\\t\\t\\t\\t// load th depth value from sample index 0\\n\\t\\t\\t\\t\\t\\t\\t\\tvar depth = textureLoad(img, vec2i(fragColor.xy), 0u);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn vec4f(depth, 0.0, 0.0, 0.0);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t`;\\n\\t\\tthis.shader = new Shader(device, {\\n\\t\\t\\tname: \\\"WebGPUResolverDepthShader\\\",\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tvshader: code,\\n\\t\\t\\tfshader: code\\n\\t\\t});\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.shader.destroy();\\n\\t\\tthis.shader = null;\\n\\t\\tthis.pipelineCache = null;\\n\\t}\\n\\tgetPipeline(format) {\\n\\t\\tlet pipeline = this.pipelineCache.get(format);\\n\\t\\tif (!pipeline) {\\n\\t\\t\\tpipeline = this.createPipeline(format);\\n\\t\\t\\tthis.pipelineCache.set(format, pipeline);\\n\\t\\t}\\n\\t\\treturn pipeline;\\n\\t}\\n\\tcreatePipeline(format) {\\n\\t\\tconst webgpuShader = this.shader.impl;\\n\\t\\tconst pipeline = this.device.wgpu.createRenderPipeline({\\n\\t\\t\\tlayout: \\\"auto\\\",\\n\\t\\t\\tvertex: {\\n\\t\\t\\t\\tmodule: webgpuShader.getVertexShaderModule(),\\n\\t\\t\\t\\tentryPoint: webgpuShader.vertexEntryPoint\\n\\t\\t\\t},\\n\\t\\t\\tfragment: {\\n\\t\\t\\t\\tmodule: webgpuShader.getFragmentShaderModule(),\\n\\t\\t\\t\\tentryPoint: webgpuShader.fragmentEntryPoint,\\n\\t\\t\\t\\ttargets: [{\\n\\t\\t\\t\\t\\tformat\\n\\t\\t\\t\\t}]\\n\\t\\t\\t},\\n\\t\\t\\tprimitive: {\\n\\t\\t\\t\\ttopology: \\\"triangle-strip\\\"\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\treturn pipeline;\\n\\t}\\n\\tresolveDepth(commandEncoder, sourceTexture, destinationTexture) {\\n\\t\\tconst device = this.device;\\n\\t\\tconst wgpu = device.wgpu;\\n\\t\\tconst pipeline = this.getPipeline(destinationTexture.format);\\n\\t\\tconst numFaces = sourceTexture.depthOrArrayLayers;\\n\\t\\tfor (let face = 0; face < numFaces; face++) {\\n\\t\\t\\tconst srcView = sourceTexture.createView({\\n\\t\\t\\t\\tdimension: \\\"2d\\\",\\n\\t\\t\\t\\taspect: \\\"depth-only\\\",\\n\\t\\t\\t\\tbaseMipLevel: 0,\\n\\t\\t\\t\\tmipLevelCount: 1,\\n\\t\\t\\t\\tbaseArrayLayer: face\\n\\t\\t\\t});\\n\\t\\t\\tconst dstView = destinationTexture.createView({\\n\\t\\t\\t\\tdimension: \\\"2d\\\",\\n\\t\\t\\t\\tbaseMipLevel: 0,\\n\\t\\t\\t\\tmipLevelCount: 1,\\n\\t\\t\\t\\tbaseArrayLayer: face\\n\\t\\t\\t});\\n\\t\\t\\tconst passEncoder = commandEncoder.beginRenderPass({\\n\\t\\t\\t\\tcolorAttachments: [{\\n\\t\\t\\t\\t\\tview: dstView,\\n\\t\\t\\t\\t\\tloadOp: \\\"clear\\\",\\n\\t\\t\\t\\t\\tstoreOp: \\\"store\\\"\\n\\t\\t\\t\\t}]\\n\\t\\t\\t});\\n\\t\\t\\tconst bindGroup = wgpu.createBindGroup({\\n\\t\\t\\t\\tlayout: pipeline.getBindGroupLayout(0),\\n\\t\\t\\t\\tentries: [{\\n\\t\\t\\t\\t\\tbinding: 0,\\n\\t\\t\\t\\t\\tresource: srcView\\n\\t\\t\\t\\t}]\\n\\t\\t\\t});\\n\\t\\t\\tpassEncoder.setPipeline(pipeline);\\n\\t\\t\\tpassEncoder.setBindGroup(0, bindGroup);\\n\\t\\t\\tpassEncoder.draw(4);\\n\\t\\t\\tpassEncoder.end();\\n\\t\\t}\\n\\t\\tdevice.pipeline = null;\\n\\t}\\n}\\n\\nconst _indirectDispatchEntryByteSize$1 = 3 * 4;\\nclass WebgpuCompute {\\n\\tuniformBuffers = [];\\n\\tbindGroup = null;\\n\\tconstructor(compute) {\\n\\t\\tthis.compute = compute;\\n\\t\\tconst { device, shader } = compute;\\n\\t\\tconst { computeBindGroupFormat, computeUniformBufferFormats } = shader.impl;\\n\\t\\tthis.bindGroup = new BindGroup(device, computeBindGroupFormat);\\n\\t\\tif (computeUniformBufferFormats) {\\n\\t\\t\\tfor (const name in computeUniformBufferFormats) {\\n\\t\\t\\t\\tif (computeUniformBufferFormats.hasOwnProperty(name)) {\\n\\t\\t\\t\\t\\tconst ub = new UniformBuffer(device, computeUniformBufferFormats[name], true);\\n\\t\\t\\t\\t\\tthis.uniformBuffers.push(ub);\\n\\t\\t\\t\\t\\tthis.bindGroup.setUniformBuffer(name, ub);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.pipeline = device.computePipeline.get(shader, computeBindGroupFormat);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.uniformBuffers.forEach((ub) => ub.destroy());\\n\\t\\tthis.uniformBuffers.length = 0;\\n\\t\\tthis.bindGroup.destroy();\\n\\t\\tthis.bindGroup = null;\\n\\t}\\n\\tupdateBindGroup() {\\n\\t\\tconst { bindGroup } = this;\\n\\t\\tbindGroup.updateUniformBuffers();\\n\\t\\tbindGroup.update();\\n\\t}\\n\\tdispatch(x, y, z) {\\n\\t\\tconst device = this.compute.device;\\n\\t\\tdevice.setBindGroup(0, this.bindGroup);\\n\\t\\tconst passEncoder = device.passEncoder;\\n\\t\\tpassEncoder.setPipeline(this.pipeline);\\n\\t\\tconst { indirectSlotIndex, indirectBuffer, indirectFrameStamp } = this.compute;\\n\\t\\tif (indirectSlotIndex >= 0) {\\n\\t\\t\\tlet gpuBuffer;\\n\\t\\t\\tif (indirectBuffer) {\\n\\t\\t\\t\\tgpuBuffer = indirectBuffer.impl.buffer;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tgpuBuffer = device.indirectDispatchBuffer.impl.buffer;\\n\\t\\t\\t}\\n\\t\\t\\tconst offset = indirectSlotIndex * _indirectDispatchEntryByteSize$1;\\n\\t\\t\\tpassEncoder.dispatchWorkgroupsIndirect(gpuBuffer, offset);\\n\\t\\t} else {\\n\\t\\t\\tpassEncoder.dispatchWorkgroups(x, y, z);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass WebgpuDrawCommands {\\n\\tdevice;\\n\\tgpuIndirect = null;\\n\\tgpuIndirectSigned = null;\\n\\tstorage = null;\\n\\tconstructor(device) {\\n\\t\\tthis.device = device;\\n\\t}\\n\\tallocate(maxCount) {\\n\\t\\tif (this.gpuIndirect && this.gpuIndirect.length === 5 * maxCount) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.storage?.destroy();\\n\\t\\tthis.gpuIndirect = new Uint32Array(5 * maxCount);\\n\\t\\tthis.gpuIndirectSigned = new Int32Array(this.gpuIndirect.buffer);\\n\\t\\tthis.storage = new StorageBuffer(this.device, this.gpuIndirect.byteLength, BUFFERUSAGE_INDIRECT | BUFFERUSAGE_COPY_DST);\\n\\t}\\n\\tadd(i, indexOrVertexCount, instanceCount, firstIndexOrVertex, baseVertex = 0, firstInstance = 0) {\\n\\t\\tconst o = i * 5;\\n\\t\\tthis.gpuIndirect[o + 0] = indexOrVertexCount;\\n\\t\\tthis.gpuIndirect[o + 1] = instanceCount;\\n\\t\\tthis.gpuIndirect[o + 2] = firstIndexOrVertex;\\n\\t\\tthis.gpuIndirectSigned[o + 3] = baseVertex;\\n\\t\\tthis.gpuIndirect[o + 4] = firstInstance;\\n\\t}\\n\\tupdate(count) {\\n\\t\\tif (this.storage && count > 0) {\\n\\t\\t\\tconst used = count * 5;\\n\\t\\t\\tthis.storage.write(0, this.gpuIndirect, 0, used);\\n\\t\\t}\\n\\t\\tlet totalPrimitives = 0;\\n\\t\\treturn totalPrimitives;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.storage?.destroy();\\n\\t\\tthis.storage = null;\\n\\t}\\n}\\n\\nclass WebgpuUploadStream {\\n\\tavailableStagingBuffers = [];\\n\\tpendingStagingBuffers = [];\\n\\t_destroyed = false;\\n\\t_lastUploadSubmitVersion = -1;\\n\\tconstructor(uploadStream) {\\n\\t\\tthis.uploadStream = uploadStream;\\n\\t\\tthis.useSingleBuffer = uploadStream.useSingleBuffer;\\n\\t}\\n\\t_onDeviceLost() {\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._destroyed = true;\\n\\t\\tthis.availableStagingBuffers.forEach((buffer) => buffer.destroy());\\n\\t\\tthis.pendingStagingBuffers.forEach((buffer) => buffer.destroy());\\n\\t}\\n\\tupdate(minByteSize) {\\n\\t\\tconst pending = this.pendingStagingBuffers;\\n\\t\\tfor (let i = 0; i < pending.length; i++) {\\n\\t\\t\\tconst buffer = pending[i];\\n\\t\\t\\tbuffer.mapAsync(GPUMapMode.WRITE).then(() => {\\n\\t\\t\\t\\tif (!this._destroyed) {\\n\\t\\t\\t\\t\\tthis.availableStagingBuffers.push(buffer);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tbuffer.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tpending.length = 0;\\n\\t\\tconst available = this.availableStagingBuffers;\\n\\t\\tfor (let i = available.length - 1; i >= 0; i--) {\\n\\t\\t\\tif (available[i].size < minByteSize) {\\n\\t\\t\\t\\tavailable[i].destroy();\\n\\t\\t\\t\\tavailable.splice(i, 1);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tupload(data, target, offset, size) {\\n\\t\\tif (this.useSingleBuffer) {\\n\\t\\t\\tthis.uploadDirect(data, target, offset, size);\\n\\t\\t} else {\\n\\t\\t\\tthis.uploadStaging(data, target, offset, size);\\n\\t\\t}\\n\\t}\\n\\tuploadDirect(data, target, offset, size) {\\n\\t\\tconst byteOffset = offset * data.BYTES_PER_ELEMENT;\\n\\t\\tsize * data.BYTES_PER_ELEMENT;\\n\\t\\ttarget.write(byteOffset, data, 0, size);\\n\\t}\\n\\tuploadStaging(data, target, offset, size) {\\n\\t\\tconst device = this.uploadStream.device;\\n\\t\\tconst byteOffset = offset * data.BYTES_PER_ELEMENT;\\n\\t\\tconst byteSize = size * data.BYTES_PER_ELEMENT;\\n\\t\\tif (this.pendingStagingBuffers.length > 0) ;\\n\\t\\tthis.update(byteSize);\\n\\t\\tconst buffer = this.availableStagingBuffers.pop() ?? (() => {\\n\\t\\t\\tconst newBuffer = this.uploadStream.device.wgpu.createBuffer({\\n\\t\\t\\t\\tsize: byteSize,\\n\\t\\t\\t\\tusage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC,\\n\\t\\t\\t\\tmappedAtCreation: true\\n\\t\\t\\t});\\n\\t\\t\\treturn newBuffer;\\n\\t\\t})();\\n\\t\\tconst mappedRange = buffer.getMappedRange();\\n\\t\\tnew Uint8Array(mappedRange).set(new Uint8Array(data.buffer, data.byteOffset, byteSize));\\n\\t\\tbuffer.unmap();\\n\\t\\tdevice.getCommandEncoder().copyBufferToBuffer(\\n\\t\\t\\tbuffer,\\n\\t\\t\\t0,\\n\\t\\t\\ttarget.impl.buffer,\\n\\t\\t\\tbyteOffset,\\n\\t\\t\\tbyteSize\\n\\t\\t);\\n\\t\\tthis.pendingStagingBuffers.push(buffer);\\n\\t\\tthis._lastUploadSubmitVersion = device.submitVersion;\\n\\t}\\n}\\n\\nclass WebgpuXrBridge {\\n\\t_binding = null;\\n\\t_layer = null;\\n\\t_cachedFramebufferSize = new Vec2();\\n\\tconstructor(xrBridge) {\\n\\t\\tthis.xrBridge = xrBridge;\\n\\t}\\n\\tdestroy(device) {\\n\\t\\tthis._binding = null;\\n\\t\\tthis._layer = null;\\n\\t\\tthis._cachedFramebufferSize.set(0, 0);\\n\\t\\tdevice._clearXrState();\\n\\t}\\n\\tbeginFrame(frame, referenceSpace) {\\n\\t\\tconst device = this.xrBridge.device;\\n\\t\\tdevice._clearXrState();\\n\\t\\tif (!this._binding || !this._layer || !referenceSpace) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst pose = frame.getViewerPose(referenceSpace);\\n\\t\\tif (!pose || !pose.views?.length) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst subImages = device.xrSubImages;\\n\\t\\tfor (let i = 0; i < pose.views.length; i++) {\\n\\t\\t\\tlet sub;\\n\\t\\t\\ttry {\\n\\t\\t\\t\\tsub = this._binding.getViewSubImage(this._layer, pose.views[i]);\\n\\t\\t\\t} catch (e) {\\n\\t\\t\\t\\tthis.xrBridge._onBindingError?.(e);\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tconst colorTexture = sub?.colorTexture;\\n\\t\\t\\tif (!colorTexture) continue;\\n\\t\\t\\tlet viewDescriptor = null;\\n\\t\\t\\tif (typeof sub.getViewDescriptor === \\\"function\\\") {\\n\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\tconst desc = sub.getViewDescriptor();\\n\\t\\t\\t\\t\\tif (desc) {\\n\\t\\t\\t\\t\\t\\tviewDescriptor = { ...desc };\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} catch (e) {\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tsubImages.push({\\n\\t\\t\\t\\tcolorTexture,\\n\\t\\t\\t\\tviewDescriptor,\\n\\t\\t\\t\\tviewport: sub.viewport,\\n\\t\\t\\t\\tviewFormat: viewDescriptor?.format ?? colorTexture.format\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tconst first = subImages[0];\\n\\t\\tif (first) {\\n\\t\\t\\tdevice.xrColorTexture = first.colorTexture;\\n\\t\\t\\tdevice.xrColorTextureViewFormat = first.viewFormat;\\n\\t\\t\\tthis._cachedFramebufferSize.set(first.colorTexture.width, first.colorTexture.height);\\n\\t\\t}\\n\\t}\\n\\tendFrame() {\\n\\t\\tconst device = this.xrBridge.device;\\n\\t\\tdevice?._clearXrState();\\n\\t}\\n\\tget presentationLayer() {\\n\\t\\treturn this._layer;\\n\\t}\\n\\tget graphicsBinding() {\\n\\t\\treturn this._binding;\\n\\t}\\n\\tgetFramebufferSize(_frame, out) {\\n\\t\\tconst layer = this._layer;\\n\\t\\tif (layer) {\\n\\t\\t\\tconst lw = layer.textureWidth ?? layer.width;\\n\\t\\t\\tconst lh = layer.textureHeight ?? layer.height;\\n\\t\\t\\tif (lw > 0 && lh > 0) {\\n\\t\\t\\t\\tout.set(lw, lh);\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this._cachedFramebufferSize.x > 0 && this._cachedFramebufferSize.y > 0) {\\n\\t\\t\\tout.copy(this._cachedFramebufferSize);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tout.set(0, 0);\\n\\t}\\n\\tgetViewport(_frame, xrView) {\\n\\t\\tif (this._binding && this._layer) {\\n\\t\\t\\ttry {\\n\\t\\t\\t\\tconst sub = this._binding.getViewSubImage(this._layer, xrView);\\n\\t\\t\\t\\tif (sub?.viewport) {\\n\\t\\t\\t\\t\\treturn sub.viewport;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} catch {\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn { x: 0, y: 0, width: 0, height: 0 };\\n\\t}\\n\\tattachPresentation(session, options) {\\n\\t\\tconst XRGPUBindingCtor = globalThis.XRGPUBinding;\\n\\t\\tif (typeof XRGPUBindingCtor === \\\"undefined\\\") {\\n\\t\\t\\tthis.xrBridge._onBindingError?.(new Error(\\\"XRGPUBinding is not available in this browser.\\\"));\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst device = this.xrBridge.device;\\n\\t\\tconst wgpu = device.wgpu;\\n\\t\\ttry {\\n\\t\\t\\tthis._binding = new XRGPUBindingCtor(session, wgpu);\\n\\t\\t} catch (ex) {\\n\\t\\t\\tthis.xrBridge._onBindingError?.(ex);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst colorFormat = this._binding.getPreferredColorFormat();\\n\\t\\tconst layerOpts = {\\n\\t\\t\\tcolorFormat,\\n\\t\\t\\tscaleFactor: options.framebufferScaleFactor\\n\\t\\t};\\n\\t\\ttry {\\n\\t\\t\\tthis._layer = this._binding.createProjectionLayer({\\n\\t\\t\\t\\t...layerOpts,\\n\\t\\t\\t\\ttextureType: \\\"texture-array\\\"\\n\\t\\t\\t});\\n\\t\\t} catch {\\n\\t\\t\\tthis._layer = this._binding.createProjectionLayer({\\n\\t\\t\\t\\t...layerOpts,\\n\\t\\t\\t\\ttextureType: \\\"texture\\\"\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tsession.updateRenderState({\\n\\t\\t\\tlayers: [this._layer],\\n\\t\\t\\tdepthNear: options.depthNear,\\n\\t\\t\\tdepthFar: options.depthFar\\n\\t\\t});\\n\\t}\\n\\tsyncCameraColorTexture(xrCamera, texture) {\\n\\t\\tif (!this._binding?.getCameraImage) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst src = this._binding.getCameraImage(xrCamera);\\n\\t\\tif (!src) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst dst = texture.impl?.gpuTexture;\\n\\t\\tif (!dst) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst device = this.xrBridge.device;\\n\\t\\tconst encoder = device.getCommandEncoder();\\n\\t\\tconst width = xrCamera.width;\\n\\t\\tconst height = xrCamera.height;\\n\\t\\tencoder.copyTextureToTexture(\\n\\t\\t\\t{ texture: src },\\n\\t\\t\\t{ texture: dst },\\n\\t\\t\\t[width, height, 1]\\n\\t\\t);\\n\\t}\\n\\tsyncCameraDepthTexture(depthInfo, _texture, _depthPixelFormat) {\\n\\t\\tif (depthInfo?.texture) ;\\n\\t}\\n\\treleasePresentation() {\\n\\t\\tthis._binding = null;\\n\\t}\\n\\tonGraphicsDeviceLost() {\\n\\t\\tconst bridge = this.xrBridge;\\n\\t\\tconst session = bridge._session;\\n\\t\\tif (!session) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst rs = session.renderState;\\n\\t\\tconst device = bridge.device;\\n\\t\\tthis._binding = null;\\n\\t\\tthis._layer = null;\\n\\t\\tthis._cachedFramebufferSize.set(0, 0);\\n\\t\\tdevice._clearXrState();\\n\\t\\tsession.updateRenderState({\\n\\t\\t\\tlayers: [],\\n\\t\\t\\tdepthNear: rs.depthNear,\\n\\t\\t\\tdepthFar: rs.depthFar\\n\\t\\t});\\n\\t}\\n\\tonGraphicsDeviceRestored() {\\n\\t\\tconst bridge = this.xrBridge;\\n\\t\\tif (!bridge._session) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst eventHandler = bridge.eventHandler;\\n\\t\\tsetTimeout(() => {\\n\\t\\t\\tif (!bridge._session) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\ttry {\\n\\t\\t\\t\\tconst rs = bridge._session.renderState;\\n\\t\\t\\t\\tbridge.attachPresentation(bridge._session, {\\n\\t\\t\\t\\t\\tframebufferScaleFactor: bridge._framebufferScaleFactor,\\n\\t\\t\\t\\t\\tdepthNear: rs.depthNear,\\n\\t\\t\\t\\t\\tdepthFar: rs.depthFar,\\n\\t\\t\\t\\t\\tonBindingError: bridge._onBindingError\\n\\t\\t\\t\\t});\\n\\t\\t\\t} catch (ex) {\\n\\t\\t\\t\\teventHandler.fire(\\\"error\\\", ex);\\n\\t\\t\\t}\\n\\t\\t}, 0);\\n\\t}\\n}\\n\\nconst _uniqueLocations = /* @__PURE__ */ new Map();\\nconst _indirectEntryByteSize = 5 * 4;\\nconst _indirectDispatchEntryByteSize = 3 * 4;\\nclass WebgpuGraphicsDevice extends GraphicsDevice {\\n\\t_deferredDestroys = [];\\n\\trenderPipeline = new WebgpuRenderPipeline(this);\\n\\tcomputePipeline = new WebgpuComputePipeline(this);\\n\\t_indirectDrawBuffer = null;\\n\\t_indirectDrawBufferCount = 0;\\n\\t_indirectDrawNextIndex = 0;\\n\\t_indirectDispatchBuffer = null;\\n\\t_indirectDispatchBufferCount = 0;\\n\\t_indirectDispatchNextIndex = 0;\\n\\tclearRenderer;\\n\\tmipmapRenderer;\\n\\tpipeline = null;\\n\\tbindGroupFormats = [];\\n\\temptyBindGroup;\\n\\tsubmitVersion = 0;\\n\\txrColorTexture = null;\\n\\txrColorTextureViewFormat = null;\\n\\txrColorTextureViewDescriptor = null;\\n\\txrSubImages = [];\\n\\txrCurrentViewIndex = -1;\\n\\texternalBackbuffer = null;\\n\\tcommandEncoder = null;\\n\\tcommandBuffers = [];\\n\\tlimits;\\n\\tglslang = null;\\n\\ttwgsl = null;\\n\\tconstructor(canvas, options = {}) {\\n\\t\\tsuper(canvas, options);\\n\\t\\toptions = this.initOptions;\\n\\t\\toptions.alpha = options.alpha ?? true;\\n\\t\\tthis.backBufferAntialias = options.antialias ?? false;\\n\\t\\tthis.isWebGPU = true;\\n\\t\\tthis._deviceType = DEVICETYPE_WEBGPU;\\n\\t\\tthis.featureLevel = options.featureLevel;\\n\\t\\tthis.scope.resolve(UNUSED_UNIFORM_NAME).setValue(0);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.clearRenderer.destroy();\\n\\t\\tthis.clearRenderer = null;\\n\\t\\tthis.mipmapRenderer.destroy();\\n\\t\\tthis.mipmapRenderer = null;\\n\\t\\tthis.resolver.destroy();\\n\\t\\tthis.resolver = null;\\n\\t\\tthis._clearXrState();\\n\\t\\tthis.externalBackbuffer = null;\\n\\t\\tsuper.destroy();\\n\\t}\\n\\t_clearXrState() {\\n\\t\\tthis.xrColorTexture = null;\\n\\t\\tthis.xrColorTextureViewFormat = null;\\n\\t\\tthis.xrColorTextureViewDescriptor = null;\\n\\t\\tthis.xrSubImages.length = 0;\\n\\t\\tthis.xrCurrentViewIndex = -1;\\n\\t}\\n\\tinitDeviceCaps() {\\n\\t\\tconst limits = this.wgpu?.limits;\\n\\t\\tthis.limits = limits;\\n\\t\\tthis.precision = \\\"highp\\\";\\n\\t\\tthis.maxPrecision = \\\"highp\\\";\\n\\t\\tthis.maxSamples = 4;\\n\\t\\tthis.maxTextures = 16;\\n\\t\\tthis.maxTextureSize = limits.maxTextureDimension2D;\\n\\t\\tthis.maxCubeMapSize = limits.maxTextureDimension2D;\\n\\t\\tthis.maxVolumeSize = limits.maxTextureDimension3D;\\n\\t\\tthis.maxColorAttachments = limits.maxColorAttachments;\\n\\t\\tthis.maxPixelRatio = 1;\\n\\t\\tthis.maxAnisotropy = 16;\\n\\t\\tthis.fragmentUniformsCount = limits.maxUniformBufferBindingSize / 16;\\n\\t\\tthis.vertexUniformsCount = limits.maxUniformBufferBindingSize / 16;\\n\\t\\tthis.supportsUniformBuffers = true;\\n\\t\\tthis.supportsAreaLights = true;\\n\\t\\tthis.supportsGpuParticles = true;\\n\\t\\tthis.supportsCompute = true;\\n\\t\\tthis.textureFloatRenderable = true;\\n\\t\\tthis.textureHalfFloatRenderable = true;\\n\\t\\tthis.supportsImageBitmap = true;\\n\\t\\tthis.samples = this.backBufferAntialias ? 4 : 1;\\n\\t\\tconst wgslFeatures = window.navigator.gpu.wgslLanguageFeatures;\\n\\t\\tthis.supportsStorageTextureRead = wgslFeatures?.has(\\\"readonly_and_readwrite_storage_textures\\\");\\n\\t\\tthis.supportsSubgroupUniformity = wgslFeatures?.has(\\\"subgroup_uniformity\\\");\\n\\t\\tthis.supportsSubgroupId = wgslFeatures?.has(\\\"subgroup_id\\\");\\n\\t\\tthis.supportsLinearIndexing = wgslFeatures?.has(\\\"linear_indexing\\\");\\n\\t\\tthis.supportsUnrestrictedPointerParameters = wgslFeatures?.has(\\\"unrestricted_pointer_parameters\\\");\\n\\t\\tthis.supportsPointerCompositeAccess = wgslFeatures?.has(\\\"pointer_composite_access\\\");\\n\\t\\tthis.supportsPacked4x8IntegerDotProduct = wgslFeatures?.has(\\\"packed_4x8_integer_dot_product\\\");\\n\\t\\tthis.supportsTextureAndSamplerLet = wgslFeatures?.has(\\\"texture_and_sampler_let\\\");\\n\\t\\tthis.initCapsDefines();\\n\\t}\\n\\tasync initWebGpu(glslangUrl, twgslUrl) {\\n\\t\\tif (!window.navigator.gpu) {\\n\\t\\t\\tthrow new Error(\\\"Unable to retrieve GPU. Ensure you are using a browser that supports WebGPU rendering.\\\");\\n\\t\\t}\\n\\t\\tif (glslangUrl && twgslUrl) {\\n\\t\\t\\tconst baseUrl = window.document?.baseURI ?? window.location.href;\\n\\t\\t\\tconst buildUrl = (srcPath) => {\\n\\t\\t\\t\\treturn new URL(srcPath, baseUrl).toString();\\n\\t\\t\\t};\\n\\t\\t\\tconst twgslScriptUrl = buildUrl(twgslUrl);\\n\\t\\t\\tconst twgslWasmUrl = buildUrl(twgslUrl.replace(\\\".js\\\", \\\".wasm\\\"));\\n\\t\\t\\tconst glslangScriptUrl = buildUrl(glslangUrl);\\n\\t\\t\\tconst results = await Promise.all([\\n\\t\\t\\t\\timport(\\n\\t\\t\\t\\t\\t/* @vite-ignore */\\n\\t\\t\\t\\t\\t/* webpackIgnore: true */\\n\\t\\t\\t\\t\\t`${twgslScriptUrl}`\\n\\t\\t\\t\\t).then(() => twgsl(twgslWasmUrl)),\\n\\t\\t\\t\\timport(\\n\\t\\t\\t\\t\\t/* @vite-ignore */\\n\\t\\t\\t\\t\\t/* webpackIgnore: true */\\n\\t\\t\\t\\t\\t`${glslangScriptUrl}`\\n\\t\\t\\t\\t).then((module) => module.default())\\n\\t\\t\\t]);\\n\\t\\t\\tthis.twgsl = results[0];\\n\\t\\t\\tthis.glslang = results[1];\\n\\t\\t}\\n\\t\\treturn this.createDevice();\\n\\t}\\n\\tasync createDevice() {\\n\\t\\tconst adapterOptions = {\\n\\t\\t\\tpowerPreference: this.initOptions.powerPreference !== \\\"default\\\" ? this.initOptions.powerPreference : void 0,\\n\\t\\t\\t// Required for WebXR sessions using WebGPU\\n\\t\\t\\txrCompatible: !!this.initOptions.xrCompatible\\n\\t\\t};\\n\\t\\tthis.gpuAdapter = await window.navigator.gpu.requestAdapter(adapterOptions);\\n\\t\\tconst featureLevel = this.initOptions.featureLevel;\\n\\t\\tconst bare = featureLevel === \\\"bare\\\";\\n\\t\\tconst requiredFeatures = [];\\n\\t\\tconst requireFeature = bare ? () => false : (feature) => {\\n\\t\\t\\tconst supported = this.gpuAdapter.features.has(feature);\\n\\t\\t\\tif (supported) {\\n\\t\\t\\t\\trequiredFeatures.push(feature);\\n\\t\\t\\t}\\n\\t\\t\\treturn supported;\\n\\t\\t};\\n\\t\\tthis.textureFloatFilterable = requireFeature(\\\"float32-filterable\\\");\\n\\t\\tthis.textureFloatBlendable = requireFeature(\\\"float32-blendable\\\");\\n\\t\\tthis.extCompressedTextureS3TC = requireFeature(\\\"texture-compression-bc\\\");\\n\\t\\tthis.extCompressedTextureS3TCSliced3D = requireFeature(\\\"texture-compression-bc-sliced-3d\\\");\\n\\t\\tthis.extCompressedTextureETC = requireFeature(\\\"texture-compression-etc2\\\");\\n\\t\\tthis.extCompressedTextureASTC = requireFeature(\\\"texture-compression-astc\\\");\\n\\t\\tthis.extCompressedTextureASTCSliced3D = requireFeature(\\\"texture-compression-astc-sliced-3d\\\");\\n\\t\\tthis.supportsTimestampQuery = requireFeature(\\\"timestamp-query\\\");\\n\\t\\tthis.supportsDepthClip = requireFeature(\\\"depth-clip-control\\\");\\n\\t\\tthis.supportsDepth32Stencil = requireFeature(\\\"depth32float-stencil8\\\");\\n\\t\\tthis.supportsIndirectFirstInstance = requireFeature(\\\"indirect-first-instance\\\");\\n\\t\\tthis.supportsShaderF16 = requireFeature(\\\"shader-f16\\\");\\n\\t\\tthis.supportsStorageRGBA8 = requireFeature(\\\"bgra8unorm-storage\\\");\\n\\t\\tthis.textureRG11B10Renderable = requireFeature(\\\"rg11b10ufloat-renderable\\\");\\n\\t\\tthis.supportsClipDistances = requireFeature(\\\"clip-distances\\\");\\n\\t\\tthis.supportsTextureFormatTier1 = requireFeature(\\\"texture-format-tier1\\\");\\n\\t\\tthis.supportsTextureFormatTier2 = requireFeature(\\\"texture-format-tier2\\\");\\n\\t\\tthis.supportsTextureFormatTier1 || (this.supportsTextureFormatTier1 = this.supportsTextureFormatTier2);\\n\\t\\tthis.supportsPrimitiveIndex = requireFeature(\\\"primitive-index\\\");\\n\\t\\tthis.supportsSubgroups = requireFeature(\\\"subgroups\\\");\\n\\t\\tthis.maxSubgroupSize = this.supportsSubgroups ? this.gpuAdapter?.info?.subgroupMaxSize ?? 0 : 0;\\n\\t\\tthis.minSubgroupSize = this.supportsSubgroups ? this.gpuAdapter?.info?.subgroupMinSize ?? 0 : 0;\\n\\t\\twindow.navigator.gpu.wgslLanguageFeatures ? Array.from(window.navigator.gpu.wgslLanguageFeatures) : [];\\n\\t\\tconst requiredLimits = {};\\n\\t\\tif (!bare) {\\n\\t\\t\\tconst adapterLimits = this.gpuAdapter?.limits;\\n\\t\\t\\tif (adapterLimits) {\\n\\t\\t\\t\\tfor (const limitName in adapterLimits) {\\n\\t\\t\\t\\t\\tif (limitName === \\\"minSubgroupSize\\\" || limitName === \\\"maxSubgroupSize\\\") {\\n\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\trequiredLimits[limitName] = adapterLimits[limitName];\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst deviceDescr = {\\n\\t\\t\\trequiredFeatures,\\n\\t\\t\\trequiredLimits,\\n\\t\\t\\tdefaultQueue: {\\n\\t\\t\\t\\tlabel: \\\"Default Queue\\\"\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tthis.wgpu = await this.gpuAdapter.requestDevice(deviceDescr);\\n\\t\\tthis.supportsHtmlTextures = typeof this.wgpu.queue?.copyElementImageToTexture === \\\"function\\\";\\n\\t\\tthis.wgpu.lost?.then(this.handleDeviceLost.bind(this));\\n\\t\\tthis.wgpu.addEventListener?.(\\\"uncapturederror\\\", (ev) => {\\n\\t\\t\\tev.error;\\n\\t\\t});\\n\\t\\tthis.initDeviceCaps();\\n\\t\\tthis.gpuContext = this.canvas.getContext(\\\"webgpu\\\");\\n\\t\\tlet canvasToneMapping = \\\"standard\\\";\\n\\t\\tlet preferredCanvasFormat = window.navigator.gpu.getPreferredCanvasFormat();\\n\\t\\tconst displayFormat = this.initOptions.displayFormat;\\n\\t\\tthis.backBufferFormat = preferredCanvasFormat === \\\"rgba8unorm\\\" ? displayFormat === DISPLAYFORMAT_LDR_SRGB ? PIXELFORMAT_SRGBA8 : PIXELFORMAT_RGBA8 : (\\n\\t\\t\\t// (S)RGBA\\n\\t\\t\\tdisplayFormat === DISPLAYFORMAT_LDR_SRGB ? PIXELFORMAT_SBGRA8 : PIXELFORMAT_BGRA8\\n\\t\\t);\\n\\t\\tthis.backBufferViewFormat = displayFormat === DISPLAYFORMAT_LDR_SRGB ? `${preferredCanvasFormat}-srgb` : preferredCanvasFormat;\\n\\t\\tif (displayFormat === DISPLAYFORMAT_HDR && this.textureFloatFilterable) {\\n\\t\\t\\tconst hdrMediaQuery = window.matchMedia(\\\"(dynamic-range: high)\\\");\\n\\t\\t\\tif (hdrMediaQuery?.matches) {\\n\\t\\t\\t\\tthis.backBufferFormat = PIXELFORMAT_RGBA16F;\\n\\t\\t\\t\\tthis.backBufferViewFormat = \\\"rgba16float\\\";\\n\\t\\t\\t\\tpreferredCanvasFormat = \\\"rgba16float\\\";\\n\\t\\t\\t\\tthis.isHdr = true;\\n\\t\\t\\t\\tcanvasToneMapping = \\\"extended\\\";\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.canvasConfig = {\\n\\t\\t\\tdevice: this.wgpu,\\n\\t\\t\\tcolorSpace: \\\"srgb\\\",\\n\\t\\t\\talphaMode: this.initOptions.alpha ? \\\"premultiplied\\\" : \\\"opaque\\\",\\n\\t\\t\\t// use preferred format for optimal performance on mobile\\n\\t\\t\\tformat: preferredCanvasFormat,\\n\\t\\t\\ttoneMapping: { mode: canvasToneMapping },\\n\\t\\t\\t// RENDER_ATTACHMENT is required, COPY_SRC allows scene grab to copy out from it\\n\\t\\t\\tusage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,\\n\\t\\t\\t// formats that views created from textures returned by getCurrentTexture may use\\n\\t\\t\\t// (this allows us to view the preferred format as srgb)\\n\\t\\t\\tviewFormats: displayFormat === DISPLAYFORMAT_LDR_SRGB ? [this.backBufferViewFormat] : []\\n\\t\\t};\\n\\t\\tthis.gpuContext?.configure(this.canvasConfig);\\n\\t\\tthis.createBackbuffer();\\n\\t\\tthis.clearRenderer = new WebgpuClearRenderer(this);\\n\\t\\tthis.mipmapRenderer = new WebgpuMipmapRenderer(this);\\n\\t\\tthis.resolver = new WebgpuResolver(this);\\n\\t\\tthis.postInit();\\n\\t\\treturn this;\\n\\t}\\n\\tasync handleDeviceLost(info) {\\n\\t\\tif (info.reason !== \\\"destroyed\\\") {\\n\\t\\t\\tsuper.loseContext();\\n\\t\\t\\tthis.fire(\\\"devicelost\\\");\\n\\t\\t\\tawait this.createDevice();\\n\\t\\t\\tsuper.restoreContext();\\n\\t\\t\\tthis.fire(\\\"devicerestored\\\");\\n\\t\\t}\\n\\t}\\n\\tpostInit() {\\n\\t\\tsuper.postInit();\\n\\t\\tthis.initializeRenderState();\\n\\t\\tthis.setupPassEncoderDefaults();\\n\\t\\tthis.gpuProfiler = new WebgpuGpuProfiler(this);\\n\\t\\tthis.dynamicBuffers = new WebgpuDynamicBuffers(this, 100 * 1024, this.limits.minUniformBufferOffsetAlignment);\\n\\t\\tthis.emptyBindGroup = new BindGroup(this, new BindGroupFormat(this, []));\\n\\t\\tthis.emptyBindGroup.update();\\n\\t}\\n\\tcreateBackbuffer() {\\n\\t\\tthis.supportsStencil = this.initOptions.stencil;\\n\\t\\tthis.backBuffer = new RenderTarget({\\n\\t\\t\\tname: \\\"WebgpuFramebuffer\\\",\\n\\t\\t\\tgraphicsDevice: this,\\n\\t\\t\\tdepth: this.initOptions.depth,\\n\\t\\t\\tstencil: this.supportsStencil,\\n\\t\\t\\tsamples: this.samples\\n\\t\\t});\\n\\t\\tthis.backBuffer.impl.isBackbuffer = true;\\n\\t}\\n\\tframeStart() {\\n\\t\\tsuper.frameStart();\\n\\t\\tthis.gpuProfiler.frameStart();\\n\\t\\tthis.submit();\\n\\t\\tconst outColorBuffer = this.xrColorTexture ?? this.gpuContext?.getCurrentTexture?.() ?? this.externalBackbuffer?.impl.gpuTexture;\\n\\t\\tif (this.backBufferSize.x !== outColorBuffer.width || this.backBufferSize.y !== outColorBuffer.height) {\\n\\t\\t\\tthis.backBufferSize.set(outColorBuffer.width, outColorBuffer.height);\\n\\t\\t\\tthis.backBuffer.destroy();\\n\\t\\t\\tthis.backBuffer = null;\\n\\t\\t\\tthis.createBackbuffer();\\n\\t\\t}\\n\\t\\tconst rt = this.backBuffer;\\n\\t\\tconst wrt = rt.impl;\\n\\t\\tconst attachmentViewFormat = outColorBuffer === this.xrColorTexture && this.xrColorTextureViewFormat ? this.xrColorTextureViewFormat : this.backBufferViewFormat;\\n\\t\\twrt.setColorAttachment(0, void 0, attachmentViewFormat);\\n\\t\\trt._width = outColorBuffer.width;\\n\\t\\trt._height = outColorBuffer.height;\\n\\t\\tthis.initRenderTarget(rt);\\n\\t\\twrt.assignColorTexture(outColorBuffer, attachmentViewFormat);\\n\\t}\\n\\tframeEnd() {\\n\\t\\tsuper.frameEnd();\\n\\t\\tthis.gpuProfiler.frameEnd();\\n\\t\\tthis.submit();\\n\\t\\tif (!this.contextLost) {\\n\\t\\t\\tthis.gpuProfiler.request();\\n\\t\\t}\\n\\t\\tthis._indirectDrawNextIndex = 0;\\n\\t\\tthis._indirectDispatchNextIndex = 0;\\n\\t}\\n\\tcreateBufferImpl(usageFlags) {\\n\\t\\treturn new WebgpuBuffer(usageFlags);\\n\\t}\\n\\tcreateUniformBufferImpl(uniformBuffer) {\\n\\t\\treturn new WebgpuUniformBuffer(uniformBuffer);\\n\\t}\\n\\tcreateVertexBufferImpl(vertexBuffer, format, options) {\\n\\t\\treturn new WebgpuVertexBuffer(vertexBuffer, format, options);\\n\\t}\\n\\tcreateIndexBufferImpl(indexBuffer, options) {\\n\\t\\treturn new WebgpuIndexBuffer(indexBuffer, options);\\n\\t}\\n\\tcreateShaderImpl(shader) {\\n\\t\\treturn new WebgpuShader(shader);\\n\\t}\\n\\tcreateDrawCommandImpl(drawCommands) {\\n\\t\\treturn new WebgpuDrawCommands(this);\\n\\t}\\n\\tcreateTextureImpl(texture) {\\n\\t\\tthis.textures.add(texture);\\n\\t\\treturn new WebgpuTexture(texture);\\n\\t}\\n\\tcreateXrBridgeImpl(xrBridge) {\\n\\t\\treturn new WebgpuXrBridge(xrBridge);\\n\\t}\\n\\tcreateRenderTargetImpl(renderTarget) {\\n\\t\\treturn new WebgpuRenderTarget(renderTarget);\\n\\t}\\n\\tcreateUploadStreamImpl(uploadStream) {\\n\\t\\treturn new WebgpuUploadStream(uploadStream);\\n\\t}\\n\\tcreateBindGroupFormatImpl(bindGroupFormat) {\\n\\t\\treturn new WebgpuBindGroupFormat(bindGroupFormat);\\n\\t}\\n\\tcreateBindGroupImpl(bindGroup) {\\n\\t\\treturn new WebgpuBindGroup();\\n\\t}\\n\\tcreateComputeImpl(compute) {\\n\\t\\treturn new WebgpuCompute(compute);\\n\\t}\\n\\tget indirectDrawBuffer() {\\n\\t\\tthis.allocateIndirectDrawBuffer();\\n\\t\\treturn this._indirectDrawBuffer;\\n\\t}\\n\\tallocateIndirectDrawBuffer() {\\n\\t\\tif (this._indirectDrawNextIndex === 0 && this._indirectDrawBufferCount < this.maxIndirectDrawCount) {\\n\\t\\t\\tthis._indirectDrawBuffer?.destroy();\\n\\t\\t\\tthis._indirectDrawBuffer = null;\\n\\t\\t}\\n\\t\\tif (this._indirectDrawBuffer === null) {\\n\\t\\t\\tthis._indirectDrawBuffer = new StorageBuffer(this, this.maxIndirectDrawCount * _indirectEntryByteSize, BUFFERUSAGE_INDIRECT | BUFFERUSAGE_COPY_DST);\\n\\t\\t\\tthis._indirectDrawBufferCount = this.maxIndirectDrawCount;\\n\\t\\t}\\n\\t}\\n\\tgetIndirectDrawSlot(count = 1) {\\n\\t\\tthis.allocateIndirectDrawBuffer();\\n\\t\\tconst slot = this._indirectDrawNextIndex;\\n\\t\\tconst nextIndex = this._indirectDrawNextIndex + count;\\n\\t\\tthis._indirectDrawNextIndex = nextIndex;\\n\\t\\treturn slot;\\n\\t}\\n\\tget indirectDispatchBuffer() {\\n\\t\\tthis.allocateIndirectDispatchBuffer();\\n\\t\\treturn this._indirectDispatchBuffer;\\n\\t}\\n\\tallocateIndirectDispatchBuffer() {\\n\\t\\tif (this._indirectDispatchNextIndex === 0 && this._indirectDispatchBufferCount < this.maxIndirectDispatchCount) {\\n\\t\\t\\tthis._indirectDispatchBuffer?.destroy();\\n\\t\\t\\tthis._indirectDispatchBuffer = null;\\n\\t\\t}\\n\\t\\tif (this._indirectDispatchBuffer === null) {\\n\\t\\t\\tthis._indirectDispatchBuffer = new StorageBuffer(this, this.maxIndirectDispatchCount * _indirectDispatchEntryByteSize, BUFFERUSAGE_INDIRECT | BUFFERUSAGE_COPY_DST);\\n\\t\\t\\tthis._indirectDispatchBufferCount = this.maxIndirectDispatchCount;\\n\\t\\t}\\n\\t}\\n\\tgetIndirectDispatchSlot(count = 1) {\\n\\t\\tthis.allocateIndirectDispatchBuffer();\\n\\t\\tconst slot = this._indirectDispatchNextIndex;\\n\\t\\tconst nextIndex = this._indirectDispatchNextIndex + count;\\n\\t\\tthis._indirectDispatchNextIndex = nextIndex;\\n\\t\\treturn slot;\\n\\t}\\n\\tsetBindGroup(index, bindGroup, offsets) {\\n\\t\\tif (this.passEncoder) {\\n\\t\\t\\tthis.passEncoder.setBindGroup(index, bindGroup.impl.bindGroup, offsets ?? bindGroup.uniformBufferOffsets);\\n\\t\\t\\tthis.bindGroupFormats[index] = bindGroup.format.impl;\\n\\t\\t}\\n\\t}\\n\\tsubmitVertexBuffer(vertexBuffer, slot) {\\n\\t\\tconst format = vertexBuffer.format;\\n\\t\\tconst { interleaved, elements } = format;\\n\\t\\tconst elementCount = elements.length;\\n\\t\\tconst vbBuffer = vertexBuffer.impl.buffer;\\n\\t\\tif (interleaved) {\\n\\t\\t\\tthis.passEncoder.setVertexBuffer(slot, vbBuffer);\\n\\t\\t\\treturn 1;\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < elementCount; i++) {\\n\\t\\t\\tthis.passEncoder.setVertexBuffer(slot + i, vbBuffer, elements[i].offset);\\n\\t\\t}\\n\\t\\treturn elementCount;\\n\\t}\\n\\tvalidateVBLocations(vb0, vb1) {\\n\\t\\tconst validateVB = (vb) => {\\n\\t\\t\\tconst { elements } = vb.format;\\n\\t\\t\\tfor (let i = 0; i < elements.length; i++) {\\n\\t\\t\\t\\tconst name = elements[i].name;\\n\\t\\t\\t\\tconst location = semanticToLocation[name];\\n\\t\\t\\t\\tif (_uniqueLocations.has(location)) ;\\n\\t\\t\\t\\t_uniqueLocations.set(location, name);\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tvalidateVB(vb0);\\n\\t\\tvalidateVB(vb1);\\n\\t\\t_uniqueLocations.clear();\\n\\t}\\n\\tdraw(primitive, indexBuffer, numInstances = 1, drawCommands, first = true, last = true) {\\n\\t\\tif (this.shader.ready && !this.shader.failed) {\\n\\t\\t\\tconst passEncoder = this.passEncoder;\\n\\t\\t\\tlet pipeline = this.pipeline;\\n\\t\\t\\tconst vb0 = this.vertexBuffers[0];\\n\\t\\t\\tconst vb1 = this.vertexBuffers[1];\\n\\t\\t\\tif (first) {\\n\\t\\t\\t\\tif (vb0) {\\n\\t\\t\\t\\t\\tconst vbSlot = this.submitVertexBuffer(vb0, 0);\\n\\t\\t\\t\\t\\tif (vb1) {\\n\\t\\t\\t\\t\\t\\tthis.submitVertexBuffer(vb1, vbSlot);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tpipeline = this.renderPipeline.get(\\n\\t\\t\\t\\t\\tprimitive,\\n\\t\\t\\t\\t\\tvb0?.format,\\n\\t\\t\\t\\t\\tvb1?.format,\\n\\t\\t\\t\\t\\tindexBuffer?.format,\\n\\t\\t\\t\\t\\tthis.shader,\\n\\t\\t\\t\\t\\tthis.renderTarget,\\n\\t\\t\\t\\t\\tthis.bindGroupFormats,\\n\\t\\t\\t\\t\\tthis.blendState,\\n\\t\\t\\t\\t\\tthis.depthState,\\n\\t\\t\\t\\t\\tthis.cullMode,\\n\\t\\t\\t\\t\\tthis.stencilEnabled,\\n\\t\\t\\t\\t\\tthis.stencilFront,\\n\\t\\t\\t\\t\\tthis.stencilBack,\\n\\t\\t\\t\\t\\tthis.frontFace\\n\\t\\t\\t\\t);\\n\\t\\t\\t\\tif (this.pipeline !== pipeline) {\\n\\t\\t\\t\\t\\tthis.pipeline = pipeline;\\n\\t\\t\\t\\t\\tpassEncoder.setPipeline(pipeline);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (indexBuffer) {\\n\\t\\t\\t\\tpassEncoder.setIndexBuffer(indexBuffer.impl.buffer, indexBuffer.impl.format);\\n\\t\\t\\t}\\n\\t\\t\\tif (drawCommands) {\\n\\t\\t\\t\\tconst storage = drawCommands.impl?.storage ?? this.indirectDrawBuffer;\\n\\t\\t\\t\\tconst indirectBuffer = storage.impl.buffer;\\n\\t\\t\\t\\tconst drawsCount = drawCommands.count;\\n\\t\\t\\t\\tfor (let d = 0; d < drawsCount; d++) {\\n\\t\\t\\t\\t\\tconst indirectOffset = (drawCommands.slotIndex + d) * _indirectEntryByteSize;\\n\\t\\t\\t\\t\\tif (indexBuffer) {\\n\\t\\t\\t\\t\\t\\tpassEncoder.drawIndexedIndirect(indirectBuffer, indirectOffset);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tpassEncoder.drawIndirect(indirectBuffer, indirectOffset);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (indexBuffer) {\\n\\t\\t\\t\\t\\tpassEncoder.drawIndexed(primitive.count, numInstances, primitive.base, primitive.baseVertex ?? 0, 0);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tpassEncoder.draw(primitive.count, numInstances, primitive.base, 0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis._drawCallsPerFrame++;\\n\\t\\t}\\n\\t\\tif (last) {\\n\\t\\t\\tthis.clearVertexBuffer();\\n\\t\\t\\tthis.pipeline = null;\\n\\t\\t}\\n\\t}\\n\\tsetShader(shader, asyncCompile = false) {\\n\\t\\tif (shader !== this.shader) {\\n\\t\\t\\tthis.shader = shader;\\n\\t\\t}\\n\\t}\\n\\tsetBlendState(blendState) {\\n\\t\\tthis.blendState.copy(blendState);\\n\\t}\\n\\tsetDepthState(depthState) {\\n\\t\\tthis.depthState.copy(depthState);\\n\\t}\\n\\tsetStencilState(stencilFront, stencilBack) {\\n\\t\\tif (stencilFront || stencilBack) {\\n\\t\\t\\tthis.stencilEnabled = true;\\n\\t\\t\\tthis.stencilFront.copy(stencilFront ?? StencilParameters.DEFAULT);\\n\\t\\t\\tthis.stencilBack.copy(stencilBack ?? StencilParameters.DEFAULT);\\n\\t\\t\\tconst ref = this.stencilFront.ref;\\n\\t\\t\\tif (this.stencilRef !== ref) {\\n\\t\\t\\t\\tthis.stencilRef = ref;\\n\\t\\t\\t\\tthis.passEncoder.setStencilReference(ref);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis.stencilEnabled = false;\\n\\t\\t}\\n\\t}\\n\\tsetBlendColor(r, g, b, a) {\\n\\t\\tconst c = this.blendColor;\\n\\t\\tif (r !== c.r || g !== c.g || b !== c.b || a !== c.a) {\\n\\t\\t\\tc.set(r, g, b, a);\\n\\t\\t\\tthis.passEncoder.setBlendConstant(c);\\n\\t\\t}\\n\\t}\\n\\tsetCullMode(cullMode) {\\n\\t\\tthis.cullMode = cullMode;\\n\\t}\\n\\tsetFrontFace(frontFace) {\\n\\t\\tthis.frontFace = frontFace;\\n\\t}\\n\\tsetAlphaToCoverage(state) {\\n\\t}\\n\\tinitializeContextCaches() {\\n\\t\\tsuper.initializeContextCaches();\\n\\t}\\n\\tsetupPassEncoderDefaults() {\\n\\t\\tthis.pipeline = null;\\n\\t\\tthis.stencilRef = 0;\\n\\t\\tthis.blendColor.set(0, 0, 0, 0);\\n\\t}\\n\\t_uploadDirtyTextures() {\\n\\t\\tthis.texturesToUpload.forEach((texture) => {\\n\\t\\t\\tif (texture._needsUpload || texture._needsMipmapsUpload) {\\n\\t\\t\\t\\ttexture.upload();\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tthis.texturesToUpload.clear();\\n\\t}\\n\\tsetupTimeStampWrites(passDesc, name) {\\n\\t\\tif (this.gpuProfiler._enabled) {\\n\\t\\t\\tif (this.gpuProfiler.timestampQueriesSet) {\\n\\t\\t\\t\\tconst slot = this.gpuProfiler.getSlot(name);\\n\\t\\t\\t\\tif (slot === -1) ; else {\\n\\t\\t\\t\\t\\tpassDesc = passDesc ?? {};\\n\\t\\t\\t\\t\\tpassDesc.timestampWrites = {\\n\\t\\t\\t\\t\\t\\tquerySet: this.gpuProfiler.timestampQueriesSet.querySet,\\n\\t\\t\\t\\t\\t\\tbeginningOfPassWriteIndex: slot * 2,\\n\\t\\t\\t\\t\\t\\tendOfPassWriteIndex: slot * 2 + 1\\n\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn passDesc;\\n\\t}\\n\\tstartRenderPass(renderPass) {\\n\\t\\tthis._uploadDirtyTextures();\\n\\t\\tconst rt = renderPass.renderTarget || this.backBuffer;\\n\\t\\tthis.renderTarget = rt;\\n\\t\\tconst wrt = rt.impl;\\n\\t\\tif (rt !== this.backBuffer) {\\n\\t\\t\\tthis.initRenderTarget(rt);\\n\\t\\t}\\n\\t\\twrt.setupForRenderPass(renderPass, rt);\\n\\t\\tconst renderPassDesc = wrt.renderPassDescriptor;\\n\\t\\tthis.setupTimeStampWrites(renderPassDesc, renderPass.name);\\n\\t\\tconst commandEncoder = this.getCommandEncoder();\\n\\t\\tthis.passEncoder = commandEncoder.beginRenderPass(renderPassDesc);\\n\\t\\tthis.passEncoder.label = `${renderPass.name}-PassEncoder RT:${rt.name}`;\\n\\t\\tthis.setupPassEncoderDefaults();\\n\\t\\tconst { width, height } = rt;\\n\\t\\tthis.setViewport(0, 0, width, height);\\n\\t\\tthis.setScissor(0, 0, width, height);\\n\\t\\tthis.insideRenderPass = true;\\n\\t}\\n\\tendRenderPass(renderPass) {\\n\\t\\tthis.passEncoder.end();\\n\\t\\tthis.passEncoder = null;\\n\\t\\tthis.insideRenderPass = false;\\n\\t\\tthis.bindGroupFormats.length = 0;\\n\\t\\tconst target = this.renderTarget;\\n\\t\\tif (target) {\\n\\t\\t\\tif (target.depthBuffer && renderPass.depthStencilOps.resolveDepth) {\\n\\t\\t\\t\\tif (renderPass.samples > 1 && target.autoResolve) {\\n\\t\\t\\t\\t\\tconst depthAttachment = target.impl.depthAttachment;\\n\\t\\t\\t\\t\\tconst destTexture = target.depthBuffer.impl.gpuTexture;\\n\\t\\t\\t\\t\\tif (depthAttachment && destTexture) {\\n\\t\\t\\t\\t\\t\\tthis.resolver.resolveDepth(this.commandEncoder, depthAttachment.multisampledDepthBuffer, destTexture);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < renderPass.colorArrayOps.length; i++) {\\n\\t\\t\\tconst colorOps = renderPass.colorArrayOps[i];\\n\\t\\t\\tif (colorOps.genMipmaps) {\\n\\t\\t\\t\\tthis.mipmapRenderer.generate(renderPass.renderTarget._colorBuffers[i].impl);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tstartComputePass(name) {\\n\\t\\tthis._uploadDirtyTextures();\\n\\t\\tthis.pipeline = null;\\n\\t\\tconst computePassDesc = this.setupTimeStampWrites(void 0, name);\\n\\t\\tconst commandEncoder = this.getCommandEncoder();\\n\\t\\tthis.passEncoder = commandEncoder.beginComputePass(computePassDesc);\\n\\t\\tthis.insideRenderPass = true;\\n\\t}\\n\\tendComputePass() {\\n\\t\\tthis.passEncoder.end();\\n\\t\\tthis.passEncoder = null;\\n\\t\\tthis.insideRenderPass = false;\\n\\t\\tthis.bindGroupFormats.length = 0;\\n\\t}\\n\\tcomputeDispatch(computes, name = \\\"Unnamed\\\") {\\n\\t\\tthis.startComputePass(name);\\n\\t\\tfor (let i = 0; i < computes.length; i++) {\\n\\t\\t\\tconst compute = computes[i];\\n\\t\\t\\tcompute.applyParameters();\\n\\t\\t\\tcompute.impl.updateBindGroup();\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < computes.length; i++) {\\n\\t\\t\\tconst compute = computes[i];\\n\\t\\t\\tcompute.impl.dispatch(compute.countX, compute.countY, compute.countZ);\\n\\t\\t}\\n\\t\\tthis.endComputePass();\\n\\t}\\n\\tgetCommandEncoder() {\\n\\t\\tlet commandEncoder = this.commandEncoder;\\n\\t\\tif (!commandEncoder) {\\n\\t\\t\\tcommandEncoder = this.wgpu.createCommandEncoder();\\n\\t\\t\\tthis.commandEncoder = commandEncoder;\\n\\t\\t}\\n\\t\\treturn commandEncoder;\\n\\t}\\n\\tendCommandEncoder() {\\n\\t\\tconst { commandEncoder } = this;\\n\\t\\tif (commandEncoder) {\\n\\t\\t\\tconst cb = commandEncoder.finish();\\n\\t\\t\\tthis.addCommandBuffer(cb);\\n\\t\\t\\tthis.commandEncoder = null;\\n\\t\\t}\\n\\t}\\n\\taddCommandBuffer(commandBuffer, front = false) {\\n\\t\\tif (front) {\\n\\t\\t\\tthis.commandBuffers.unshift(commandBuffer);\\n\\t\\t} else {\\n\\t\\t\\tthis.commandBuffers.push(commandBuffer);\\n\\t\\t}\\n\\t}\\n\\tsubmit() {\\n\\t\\tthis.endCommandEncoder();\\n\\t\\tif (this.commandBuffers.length > 0) {\\n\\t\\t\\tthis.dynamicBuffers.submit();\\n\\t\\t\\tthis.wgpu.queue.submit(this.commandBuffers);\\n\\t\\t\\tthis.commandBuffers.length = 0;\\n\\t\\t\\tthis.submitVersion++;\\n\\t\\t\\tthis.dynamicBuffers.onCommandBuffersSubmitted();\\n\\t\\t}\\n\\t\\tconst deferredDestroys = this._deferredDestroys;\\n\\t\\tif (deferredDestroys.length > 0) {\\n\\t\\t\\tfor (let i = 0; i < deferredDestroys.length; i++) {\\n\\t\\t\\t\\tdeferredDestroys[i].destroy();\\n\\t\\t\\t}\\n\\t\\t\\tdeferredDestroys.length = 0;\\n\\t\\t}\\n\\t}\\n\\tdeferDestroy(gpuResource) {\\n\\t\\tif (gpuResource) {\\n\\t\\t\\tthis._deferredDestroys.push(gpuResource);\\n\\t\\t}\\n\\t}\\n\\tclear(options) {\\n\\t\\tif (options.flags) {\\n\\t\\t\\tthis.clearRenderer.clear(this, this.renderTarget, options, this.defaultClearOptions);\\n\\t\\t}\\n\\t}\\n\\tsetViewport(x, y, w, h) {\\n\\t\\tif (this.passEncoder) {\\n\\t\\t\\tif (this.xrColorTexture) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tif (!this.renderTarget.flipY) {\\n\\t\\t\\t\\ty = this.renderTarget.height - y - h;\\n\\t\\t\\t}\\n\\t\\t\\tthis.vx = x;\\n\\t\\t\\tthis.vy = y;\\n\\t\\t\\tthis.vw = w;\\n\\t\\t\\tthis.vh = h;\\n\\t\\t\\tthis.passEncoder.setViewport(x, y, w, h, 0, 1);\\n\\t\\t}\\n\\t}\\n\\tsetScissor(x, y, w, h) {\\n\\t\\tif (this.passEncoder) {\\n\\t\\t\\tif (this.xrColorTexture) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tif (!this.renderTarget.flipY) {\\n\\t\\t\\t\\ty = this.renderTarget.height - y - h;\\n\\t\\t\\t}\\n\\t\\t\\tthis.sx = x;\\n\\t\\t\\tthis.sy = y;\\n\\t\\t\\tthis.sw = w;\\n\\t\\t\\tthis.sh = h;\\n\\t\\t\\tthis.passEncoder.setScissorRect(x, y, w, h);\\n\\t\\t}\\n\\t}\\n\\tclearStorageBuffer(storageBuffer, offset = 0, size = storageBuffer.byteSize) {\\n\\t\\tconst commandEncoder = this.getCommandEncoder();\\n\\t\\tcommandEncoder.clearBuffer(storageBuffer.buffer, offset, size);\\n\\t}\\n\\treadStorageBuffer(storageBuffer, offset = 0, size = storageBuffer.byteSize - offset, data = null, immediate = false) {\\n\\t\\tconst stagingBuffer = this.createBufferImpl(BUFFERUSAGE_READ | BUFFERUSAGE_COPY_DST);\\n\\t\\tstagingBuffer.allocate(this, size);\\n\\t\\tconst destBuffer = stagingBuffer.buffer;\\n\\t\\tconst commandEncoder = this.getCommandEncoder();\\n\\t\\tcommandEncoder.copyBufferToBuffer(storageBuffer.buffer, offset, destBuffer, 0, size);\\n\\t\\treturn this.readBuffer(stagingBuffer, size, data, immediate);\\n\\t}\\n\\treadBuffer(stagingBuffer, size, data = null, immediate = false) {\\n\\t\\tconst destBuffer = stagingBuffer.buffer;\\n\\t\\treturn new Promise((resolve, reject) => {\\n\\t\\t\\tconst read = () => {\\n\\t\\t\\t\\tdestBuffer?.mapAsync(GPUMapMode.READ).then(() => {\\n\\t\\t\\t\\t\\tdata ?? (data = new Uint8Array(size));\\n\\t\\t\\t\\t\\tconst copySrc = destBuffer.getMappedRange(0, size);\\n\\t\\t\\t\\t\\tconst srcType = data.constructor;\\n\\t\\t\\t\\t\\tdata.set(new srcType(copySrc));\\n\\t\\t\\t\\t\\tdestBuffer.unmap();\\n\\t\\t\\t\\t\\tstagingBuffer.destroy(this);\\n\\t\\t\\t\\t\\tresolve(data);\\n\\t\\t\\t\\t});\\n\\t\\t\\t};\\n\\t\\t\\tif (immediate) {\\n\\t\\t\\t\\tthis.submit();\\n\\t\\t\\t\\tread();\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tsetTimeout(() => {\\n\\t\\t\\t\\t\\tread();\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n\\twriteStorageBuffer(storageBuffer, bufferOffset = 0, data, dataOffset = 0, size) {\\n\\t\\tthis.wgpu.queue.writeBuffer(storageBuffer.buffer, bufferOffset, data, dataOffset, size);\\n\\t}\\n\\tcopyRenderTarget(source, dest, color, depth) {\\n\\t\\tconst copySize = {\\n\\t\\t\\twidth: source ? source.width : dest.width,\\n\\t\\t\\theight: source ? source.height : dest.height,\\n\\t\\t\\tdepthOrArrayLayers: 1\\n\\t\\t};\\n\\t\\tconst commandEncoder = this.getCommandEncoder();\\n\\t\\tif (color) {\\n\\t\\t\\tconst copySrc = {\\n\\t\\t\\t\\ttexture: source ? source.colorBuffer.impl.gpuTexture : this.backBuffer.impl.assignedColorTexture,\\n\\t\\t\\t\\tmipLevel: source ? source.mipLevel : 0\\n\\t\\t\\t};\\n\\t\\t\\tconst copyDst = {\\n\\t\\t\\t\\ttexture: dest ? dest.colorBuffer.impl.gpuTexture : this.backBuffer.impl.assignedColorTexture,\\n\\t\\t\\t\\tmipLevel: dest ? dest.mipLevel : 0\\n\\t\\t\\t};\\n\\t\\t\\tcommandEncoder.copyTextureToTexture(copySrc, copyDst, copySize);\\n\\t\\t}\\n\\t\\tif (depth) {\\n\\t\\t\\tconst sourceRT = source ? source : this.renderTarget;\\n\\t\\t\\tconst sourceTexture = sourceRT.impl.depthAttachment.depthTexture;\\n\\t\\t\\tconst sourceMipLevel = sourceRT.mipLevel;\\n\\t\\t\\tif (source.samples > 1) {\\n\\t\\t\\t\\tconst destTexture = dest.colorBuffer.impl.gpuTexture;\\n\\t\\t\\t\\tthis.resolver.resolveDepth(commandEncoder, sourceTexture, destTexture);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconst destTexture = dest ? dest.depthBuffer.impl.gpuTexture : this.renderTarget.impl.depthAttachment.depthTexture;\\n\\t\\t\\t\\tconst destMipLevel = dest ? dest.mipLevel : this.renderTarget.mipLevel;\\n\\t\\t\\t\\tconst copySrc = {\\n\\t\\t\\t\\t\\ttexture: sourceTexture,\\n\\t\\t\\t\\t\\tmipLevel: sourceMipLevel\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst copyDst = {\\n\\t\\t\\t\\t\\ttexture: destTexture,\\n\\t\\t\\t\\t\\tmipLevel: destMipLevel\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tcommandEncoder.copyTextureToTexture(copySrc, copyDst, copySize);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn true;\\n\\t}\\n\\tget hasTranspilers() {\\n\\t\\treturn this.glslang && this.twgsl;\\n\\t}\\n}\\n\\nclass WebglBuffer {\\n\\tbufferId = null;\\n\\tdestroy(device) {\\n\\t\\tif (this.bufferId) {\\n\\t\\t\\tdevice.gl.deleteBuffer(this.bufferId);\\n\\t\\t\\tthis.bufferId = null;\\n\\t\\t}\\n\\t}\\n\\tget initialized() {\\n\\t\\treturn !!this.bufferId;\\n\\t}\\n\\tloseContext() {\\n\\t\\tthis.bufferId = null;\\n\\t}\\n\\tunlock(device, usage, target, storage) {\\n\\t\\tconst gl = device.gl;\\n\\t\\tif (!this.bufferId) {\\n\\t\\t\\tlet glUsage;\\n\\t\\t\\tswitch (usage) {\\n\\t\\t\\t\\tcase BUFFER_STATIC:\\n\\t\\t\\t\\t\\tglUsage = gl.STATIC_DRAW;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase BUFFER_DYNAMIC:\\n\\t\\t\\t\\t\\tglUsage = gl.DYNAMIC_DRAW;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase BUFFER_STREAM:\\n\\t\\t\\t\\t\\tglUsage = gl.STREAM_DRAW;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase BUFFER_GPUDYNAMIC:\\n\\t\\t\\t\\t\\tglUsage = gl.DYNAMIC_COPY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\tthis.bufferId = gl.createBuffer();\\n\\t\\t\\tgl.bindBuffer(target, this.bufferId);\\n\\t\\t\\tgl.bufferData(target, storage, glUsage);\\n\\t\\t} else {\\n\\t\\t\\tgl.bindBuffer(target, this.bufferId);\\n\\t\\t\\tgl.bufferSubData(target, 0, storage);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass WebglVertexBuffer extends WebglBuffer {\\n\\t// vertex array object\\n\\tvao = null;\\n\\tdestroy(device) {\\n\\t\\tsuper.destroy(device);\\n\\t\\tdevice.unbindVertexArray();\\n\\t}\\n\\tloseContext() {\\n\\t\\tsuper.loseContext();\\n\\t\\tthis.vao = null;\\n\\t}\\n\\tunlock(vertexBuffer) {\\n\\t\\tconst device = vertexBuffer.device;\\n\\t\\tsuper.unlock(device, vertexBuffer.usage, device.gl.ARRAY_BUFFER, vertexBuffer.storage);\\n\\t}\\n}\\n\\nclass WebglIndexBuffer extends WebglBuffer {\\n\\tconstructor(indexBuffer) {\\n\\t\\tsuper();\\n\\t\\tconst gl = indexBuffer.device.gl;\\n\\t\\tconst format = indexBuffer.format;\\n\\t\\tif (format === INDEXFORMAT_UINT8) {\\n\\t\\t\\tthis.glFormat = gl.UNSIGNED_BYTE;\\n\\t\\t} else if (format === INDEXFORMAT_UINT16) {\\n\\t\\t\\tthis.glFormat = gl.UNSIGNED_SHORT;\\n\\t\\t} else if (format === INDEXFORMAT_UINT32) {\\n\\t\\t\\tthis.glFormat = gl.UNSIGNED_INT;\\n\\t\\t}\\n\\t}\\n\\tunlock(indexBuffer) {\\n\\t\\tconst device = indexBuffer.device;\\n\\t\\tsuper.unlock(device, indexBuffer.usage, device.gl.ELEMENT_ARRAY_BUFFER, indexBuffer.storage);\\n\\t}\\n}\\n\\nclass WebglShaderInput {\\n\\tconstructor(graphicsDevice, name, type, locationId) {\\n\\t\\tthis.locationId = locationId;\\n\\t\\tthis.scopeId = graphicsDevice.scope.resolve(name);\\n\\t\\tthis.version = new Version();\\n\\t\\tif (name.substring(name.length - 3) === \\\"[0]\\\") {\\n\\t\\t\\tswitch (type) {\\n\\t\\t\\t\\tcase UNIFORMTYPE_FLOAT:\\n\\t\\t\\t\\t\\ttype = UNIFORMTYPE_FLOATARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_INT:\\n\\t\\t\\t\\t\\ttype = UNIFORMTYPE_INTARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_UINT:\\n\\t\\t\\t\\t\\ttype = UNIFORMTYPE_UINTARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_BOOL:\\n\\t\\t\\t\\t\\ttype = UNIFORMTYPE_BOOLARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_VEC2:\\n\\t\\t\\t\\t\\ttype = UNIFORMTYPE_VEC2ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_IVEC2:\\n\\t\\t\\t\\t\\ttype = UNIFORMTYPE_IVEC2ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_UVEC2:\\n\\t\\t\\t\\t\\ttype = UNIFORMTYPE_UVEC2ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_BVEC2:\\n\\t\\t\\t\\t\\ttype = UNIFORMTYPE_BVEC2ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_VEC3:\\n\\t\\t\\t\\t\\ttype = UNIFORMTYPE_VEC3ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_IVEC3:\\n\\t\\t\\t\\t\\ttype = UNIFORMTYPE_IVEC3ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_UVEC3:\\n\\t\\t\\t\\t\\ttype = UNIFORMTYPE_UVEC3ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_BVEC3:\\n\\t\\t\\t\\t\\ttype = UNIFORMTYPE_BVEC3ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_VEC4:\\n\\t\\t\\t\\t\\ttype = UNIFORMTYPE_VEC4ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_IVEC4:\\n\\t\\t\\t\\t\\ttype = UNIFORMTYPE_IVEC4ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_UVEC4:\\n\\t\\t\\t\\t\\ttype = UNIFORMTYPE_UVEC4ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase UNIFORMTYPE_BVEC4:\\n\\t\\t\\t\\t\\ttype = UNIFORMTYPE_BVEC4ARRAY;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.dataType = type;\\n\\t\\tthis.value = [null, null, null, null];\\n\\t\\tthis.array = [];\\n\\t}\\n}\\n\\nconst _vertexShaderBuiltins = /* @__PURE__ */ new Set([\\n\\t\\\"gl_VertexID\\\",\\n\\t\\\"gl_InstanceID\\\",\\n\\t\\\"gl_DrawID\\\",\\n\\t\\\"gl_BaseVertex\\\",\\n\\t\\\"gl_BaseInstance\\\"\\n]);\\nclass CompiledShaderCache {\\n\\t// maps shader source to a compiled WebGL shader\\n\\tmap = /* @__PURE__ */ new Map();\\n\\t// destroy all created shaders when the device is destroyed\\n\\tdestroy(device) {\\n\\t\\tthis.map.forEach((shader) => {\\n\\t\\t\\tdevice.gl.deleteShader(shader);\\n\\t\\t});\\n\\t}\\n\\t// just empty the cache when the context is lost\\n\\tloseContext(device) {\\n\\t\\tthis.map.clear();\\n\\t}\\n}\\nconst _vertexShaderCache = new DeviceCache();\\nconst _fragmentShaderCache = new DeviceCache();\\nclass WebglShader {\\n\\tcompileDuration = 0;\\n\\tconstructor(shader) {\\n\\t\\tthis.init();\\n\\t\\tthis.compile(shader.device, shader);\\n\\t\\tthis.link(shader.device, shader);\\n\\t\\tshader.device.shaders.push(shader);\\n\\t}\\n\\tdestroy(shader) {\\n\\t\\tif (this.glProgram) {\\n\\t\\t\\tshader.device.gl.deleteProgram(this.glProgram);\\n\\t\\t\\tthis.glProgram = null;\\n\\t\\t}\\n\\t}\\n\\tinit() {\\n\\t\\tthis.uniforms = [];\\n\\t\\tthis.samplers = [];\\n\\t\\tthis.attributes = [];\\n\\t\\tthis.glProgram = null;\\n\\t\\tthis.glVertexShader = null;\\n\\t\\tthis.glFragmentShader = null;\\n\\t}\\n\\tloseContext() {\\n\\t\\tthis.init();\\n\\t}\\n\\trestoreContext(device, shader) {\\n\\t\\tthis.compile(device, shader);\\n\\t\\tthis.link(device, shader);\\n\\t}\\n\\tcompile(device, shader) {\\n\\t\\tconst definition = shader.definition;\\n\\t\\tthis.glVertexShader = this._compileShaderSource(device, definition.vshader, true);\\n\\t\\tthis.glFragmentShader = this._compileShaderSource(device, definition.fshader, false);\\n\\t}\\n\\tlink(device, shader) {\\n\\t\\tif (this.glProgram) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst gl = device.gl;\\n\\t\\tif (gl.isContextLost()) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst glProgram = gl.createProgram();\\n\\t\\tthis.glProgram = glProgram;\\n\\t\\tgl.attachShader(glProgram, this.glVertexShader);\\n\\t\\tgl.attachShader(glProgram, this.glFragmentShader);\\n\\t\\tconst definition = shader.definition;\\n\\t\\tconst attrs = definition.attributes;\\n\\t\\tif (definition.useTransformFeedback) {\\n\\t\\t\\tlet outNames = definition.feedbackVaryings;\\n\\t\\t\\tif (!outNames) {\\n\\t\\t\\t\\toutNames = [];\\n\\t\\t\\t\\tfor (const attr in attrs) {\\n\\t\\t\\t\\t\\tif (attrs.hasOwnProperty(attr)) {\\n\\t\\t\\t\\t\\t\\toutNames.push(`out_${attr}`);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tgl.transformFeedbackVaryings(glProgram, outNames, gl.INTERLEAVED_ATTRIBS);\\n\\t\\t}\\n\\t\\tfor (const attr in attrs) {\\n\\t\\t\\tif (attrs.hasOwnProperty(attr)) {\\n\\t\\t\\t\\tconst semantic = attrs[attr];\\n\\t\\t\\t\\tconst loc = semanticToLocation[semantic];\\n\\t\\t\\t\\tgl.bindAttribLocation(glProgram, loc, attr);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgl.linkProgram(glProgram);\\n\\t}\\n\\t_compileShaderSource(device, src, isVertexShader) {\\n\\t\\tconst gl = device.gl;\\n\\t\\tif (gl.isContextLost()) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tconst shaderDeviceCache = isVertexShader ? _vertexShaderCache : _fragmentShaderCache;\\n\\t\\tconst shaderCache = shaderDeviceCache.get(device, () => {\\n\\t\\t\\treturn new CompiledShaderCache();\\n\\t\\t});\\n\\t\\tlet glShader = shaderCache.map.get(src);\\n\\t\\tif (!glShader) {\\n\\t\\t\\tglShader = gl.createShader(isVertexShader ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER);\\n\\t\\t\\tgl.shaderSource(glShader, src);\\n\\t\\t\\tgl.compileShader(glShader);\\n\\t\\t\\tshaderCache.map.set(src, glShader);\\n\\t\\t}\\n\\t\\treturn glShader;\\n\\t}\\n\\tfinalize(device, shader) {\\n\\t\\tconst gl = device.gl;\\n\\t\\tif (gl.isContextLost()) {\\n\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tconst glProgram = this.glProgram;\\n\\t\\tconst definition = shader.definition;\\n\\t\\tconst linkStatus = gl.getProgramParameter(glProgram, gl.LINK_STATUS);\\n\\t\\tif (!linkStatus) {\\n\\t\\t\\tif (!this._isCompiled(device, shader, this.glVertexShader, definition.vshader, \\\"vertex\\\")) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t\\t}\\n\\t\\t\\tif (!this._isCompiled(device, shader, this.glFragmentShader, definition.fshader, \\\"fragment\\\")) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t\\t}\\n\\t\\t\\tconst message = `Failed to link shader program. Error: ${gl.getProgramInfoLog(glProgram)}`;\\n\\t\\t\\tconsole.error(message);\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tconst numAttributes = gl.getProgramParameter(glProgram, gl.ACTIVE_ATTRIBUTES);\\n\\t\\tshader.attributes.clear();\\n\\t\\tfor (let i = 0; i < numAttributes; i++) {\\n\\t\\t\\tconst info = gl.getActiveAttrib(glProgram, i);\\n\\t\\t\\tconst location = gl.getAttribLocation(glProgram, info.name);\\n\\t\\t\\tif (_vertexShaderBuiltins.has(info.name)) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tif (definition.attributes[info.name] === void 0) {\\n\\t\\t\\t\\tconsole.error(`Vertex shader attribute \\\"${info.name}\\\" is not mapped to a semantic in shader definition, shader [${shader.label}]`, shader);\\n\\t\\t\\t\\tshader.failed = true;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tshader.attributes.set(location, info.name);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst samplerTypes = device._samplerTypes;\\n\\t\\tconst numUniforms = gl.getProgramParameter(glProgram, gl.ACTIVE_UNIFORMS);\\n\\t\\tfor (let i = 0; i < numUniforms; i++) {\\n\\t\\t\\tconst info = gl.getActiveUniform(glProgram, i);\\n\\t\\t\\tconst location = gl.getUniformLocation(glProgram, info.name);\\n\\t\\t\\tif (_vertexShaderBuiltins.has(info.name)) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tconst shaderInput = new WebglShaderInput(device, info.name, device.pcUniformType[info.type], location);\\n\\t\\t\\tif (samplerTypes.has(info.type)) {\\n\\t\\t\\t\\tthis.samplers.push(shaderInput);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.uniforms.push(shaderInput);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tshader.ready = true;\\n\\t\\treturn true;\\n\\t}\\n\\t_isCompiled(device, shader, glShader, source, shaderType) {\\n\\t\\tconst gl = device.gl;\\n\\t\\tif (!gl.getShaderParameter(glShader, gl.COMPILE_STATUS)) {\\n\\t\\t\\tconst infoLog = gl.getShaderInfoLog(glShader);\\n\\t\\t\\tconst [code, error] = this._processError(source, infoLog);\\n\\t\\t\\tconst message = `Failed to compile ${shaderType} shader:\\n\\n${infoLog}\\n${code} while rendering ${ void 0}`;\\n\\t\\t\\tconsole.error(message);\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\treturn true;\\n\\t}\\n\\tisLinked(device) {\\n\\t\\tconst { extParallelShaderCompile } = device;\\n\\t\\tif (extParallelShaderCompile) {\\n\\t\\t\\treturn device.gl.getProgramParameter(this.glProgram, extParallelShaderCompile.COMPLETION_STATUS_KHR);\\n\\t\\t}\\n\\t\\treturn true;\\n\\t}\\n\\t_processError(src, infoLog) {\\n\\t\\tconst error = {};\\n\\t\\tlet code = \\\"\\\";\\n\\t\\tif (src) {\\n\\t\\t\\tconst lines = src.split(\\\"\\\\n\\\");\\n\\t\\t\\tlet from = 0;\\n\\t\\t\\tlet to = lines.length;\\n\\t\\t\\tif (infoLog && infoLog.startsWith(\\\"ERROR:\\\")) {\\n\\t\\t\\t\\tconst match = infoLog.match(/^ERROR:\\\\s(\\\\d+):(\\\\d+):\\\\s*(.+)/);\\n\\t\\t\\t\\tif (match) {\\n\\t\\t\\t\\t\\terror.message = match[3];\\n\\t\\t\\t\\t\\terror.line = parseInt(match[2], 10);\\n\\t\\t\\t\\t\\tfrom = Math.max(0, error.line - 6);\\n\\t\\t\\t\\t\\tto = Math.min(lines.length, error.line + 5);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tfor (let i = from; i < to; i++) {\\n\\t\\t\\t\\tconst linePrefix = i + 1 === error.line ? \\\"> \\\" : \\\"  \\\";\\n\\t\\t\\t\\tcode += `${linePrefix}${i + 1}:\\t${lines[i]}\\n`;\\n\\t\\t\\t}\\n\\t\\t\\terror.source = src;\\n\\t\\t}\\n\\t\\treturn [code, error];\\n\\t}\\n}\\n\\nclass WebglDrawCommands {\\n\\tindexSizeBytes;\\n\\tglCounts = null;\\n\\tglOffsetsBytes = null;\\n\\tglInstanceCounts = null;\\n\\tconstructor(indexSizeBytes) {\\n\\t\\tthis.indexSizeBytes = indexSizeBytes;\\n\\t}\\n\\tallocate(maxCount) {\\n\\t\\tif (this.glCounts && this.glCounts.length === maxCount) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.glCounts = new Int32Array(maxCount);\\n\\t\\tthis.glOffsetsBytes = new Int32Array(maxCount);\\n\\t\\tthis.glInstanceCounts = new Int32Array(maxCount);\\n\\t}\\n\\tadd(i, indexOrVertexCount, instanceCount, firstIndexOrVertex) {\\n\\t\\tthis.glCounts[i] = indexOrVertexCount;\\n\\t\\tthis.glOffsetsBytes[i] = firstIndexOrVertex * this.indexSizeBytes;\\n\\t\\tthis.glInstanceCounts[i] = instanceCount;\\n\\t}\\n\\tupdate(count) {\\n\\t\\tlet totalPrimitives = 0;\\n\\t\\treturn totalPrimitives;\\n\\t}\\n}\\n\\nfunction downsampleImage(image, size) {\\n\\tconst srcW = image.width;\\n\\tconst srcH = image.height;\\n\\tif (srcW > size || srcH > size) {\\n\\t\\tconst scale = size / Math.max(srcW, srcH);\\n\\t\\tconst dstW = Math.floor(srcW * scale);\\n\\t\\tconst dstH = Math.floor(srcH * scale);\\n\\t\\tconst canvas = document.createElement(\\\"canvas\\\");\\n\\t\\tcanvas.width = dstW;\\n\\t\\tcanvas.height = dstH;\\n\\t\\tconst context = canvas.getContext(\\\"2d\\\");\\n\\t\\tcontext.drawImage(image, 0, 0, srcW, srcH, 0, 0, dstW, dstH);\\n\\t\\treturn canvas;\\n\\t}\\n\\treturn image;\\n}\\nclass WebglTexture {\\n\\t_glTexture = null;\\n\\t_glTarget;\\n\\t_glFormat;\\n\\t_glInternalFormat;\\n\\t_glPixelType;\\n\\t_glCreated;\\n\\tdirtyParameterFlags = 0;\\n\\tconstructor(texture) {\\n\\t\\tthis.texture = texture;\\n\\t}\\n\\tdestroy(device) {\\n\\t\\tif (this._glTexture) {\\n\\t\\t\\tfor (let i = 0; i < device.textureUnits.length; i++) {\\n\\t\\t\\t\\tconst textureUnit = device.textureUnits[i];\\n\\t\\t\\t\\tfor (let j = 0; j < textureUnit.length; j++) {\\n\\t\\t\\t\\t\\tif (textureUnit[j] === this._glTexture) {\\n\\t\\t\\t\\t\\t\\ttextureUnit[j] = null;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tdevice.gl.deleteTexture(this._glTexture);\\n\\t\\t\\tthis._glTexture = null;\\n\\t\\t}\\n\\t}\\n\\tloseContext() {\\n\\t\\tthis._glTexture = null;\\n\\t}\\n\\tpropertyChanged(flag) {\\n\\t\\tthis.dirtyParameterFlags |= flag;\\n\\t}\\n\\tinitialize(device, texture) {\\n\\t\\tconst gl = device.gl;\\n\\t\\tthis._glTexture = gl.createTexture();\\n\\t\\tthis._glTarget = texture._cubemap ? gl.TEXTURE_CUBE_MAP : texture._volume ? gl.TEXTURE_3D : texture.array ? gl.TEXTURE_2D_ARRAY : gl.TEXTURE_2D;\\n\\t\\tswitch (texture._format) {\\n\\t\\t\\tcase PIXELFORMAT_A8:\\n\\t\\t\\t\\tthis._glFormat = gl.ALPHA;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.ALPHA;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_L8:\\n\\t\\t\\t\\tthis._glFormat = gl.LUMINANCE;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.LUMINANCE;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_LA8:\\n\\t\\t\\t\\tthis._glFormat = gl.LUMINANCE_ALPHA;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.LUMINANCE_ALPHA;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_R8:\\n\\t\\t\\t\\tthis._glFormat = gl.RED;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.R8;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RG8:\\n\\t\\t\\t\\tthis._glFormat = gl.RG;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RG8;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGB565:\\n\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGB565;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_SHORT_5_6_5;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGBA5551:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGB5_A1;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_SHORT_5_5_5_1;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGBA4:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA4;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_SHORT_4_4_4_4;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGB8:\\n\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGB8;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGBA8:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA8;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_BGRA8:\\n\\t\\t\\tcase PIXELFORMAT_SBGRA8:\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RG32F:\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGB9E5:\\n\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGB9_E5;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_INT_5_9_9_9_REV;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RG8S:\\n\\t\\t\\t\\tthis._glFormat = gl.RG;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RG8_SNORM;\\n\\t\\t\\t\\tthis._glPixelType = gl.BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGBA8S:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA8_SNORM;\\n\\t\\t\\t\\tthis._glPixelType = gl.BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGB10A2:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGB10_A2;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_INT_2_10_10_10_REV;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGB10A2U:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGB10_A2UI;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_INT_2_10_10_10_REV;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t// compressed formats ----\\n\\t\\t\\tcase PIXELFORMAT_DXT1:\\n\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureS3TC.COMPRESSED_RGB_S3TC_DXT1_EXT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_DXT3:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT3_EXT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_DXT5:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT5_EXT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_ETC1:\\n\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureETC1.COMPRESSED_RGB_ETC1_WEBGL;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_PVRTC_2BPP_RGB_1:\\n\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTexturePVRTC.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_PVRTC_2BPP_RGBA_1:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTexturePVRTC.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_PVRTC_4BPP_RGB_1:\\n\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTexturePVRTC.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_PVRTC_4BPP_RGBA_1:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTexturePVRTC.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_ETC2_RGB:\\n\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureETC.COMPRESSED_RGB8_ETC2;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_ETC2_RGBA:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureETC.COMPRESSED_RGBA8_ETC2_EAC;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_ASTC_4x4:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureASTC.COMPRESSED_RGBA_ASTC_4x4_KHR;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_ATC_RGB:\\n\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureATC.COMPRESSED_RGB_ATC_WEBGL;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_ATC_RGBA:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureATC.COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_BC6F:\\n\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extTextureCompressionBPTC.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_BC6UF:\\n\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extTextureCompressionBPTC.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_BC7:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extTextureCompressionBPTC.COMPRESSED_RGBA_BPTC_UNORM_EXT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t// compressed sRGB formats ----\\n\\t\\t\\tcase PIXELFORMAT_DXT1_SRGB:\\n\\t\\t\\t\\tthis._glFormat = gl.SRGB;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureS3TC_SRGB.COMPRESSED_SRGB_S3TC_DXT1_EXT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_DXT3_SRGBA:\\n\\t\\t\\t\\tthis._glFormat = gl.SRGB_ALPHA;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureS3TC_SRGB.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_DXT5_SRGBA:\\n\\t\\t\\t\\tthis._glFormat = gl.SRGB_ALPHA;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureS3TC_SRGB.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_ETC2_SRGB:\\n\\t\\t\\t\\tthis._glFormat = gl.SRGB;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureETC.COMPRESSED_SRGB8_ETC2;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_ETC2_SRGBA:\\n\\t\\t\\t\\tthis._glFormat = gl.SRGB_ALPHA;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureETC.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_ASTC_4x4_SRGB:\\n\\t\\t\\t\\tthis._glFormat = gl.SRGB_ALPHA;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureASTC.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_BC7_SRGBA:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = device.extTextureCompressionBPTC.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t// ------------------\\n\\t\\t\\tcase PIXELFORMAT_R16F:\\n\\t\\t\\t\\tthis._glFormat = gl.RED;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.R16F;\\n\\t\\t\\t\\tthis._glPixelType = gl.HALF_FLOAT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RG16F:\\n\\t\\t\\t\\tthis._glFormat = gl.RG;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RG16F;\\n\\t\\t\\t\\tthis._glPixelType = gl.HALF_FLOAT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGB16F:\\n\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGB16F;\\n\\t\\t\\t\\tthis._glPixelType = gl.HALF_FLOAT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGBA16F:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA16F;\\n\\t\\t\\t\\tthis._glPixelType = gl.HALF_FLOAT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGB32F:\\n\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGB32F;\\n\\t\\t\\t\\tthis._glPixelType = gl.FLOAT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGBA32F:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA32F;\\n\\t\\t\\t\\tthis._glPixelType = gl.FLOAT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_R32F:\\n\\t\\t\\t\\tthis._glFormat = gl.RED;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.R32F;\\n\\t\\t\\t\\tthis._glPixelType = gl.FLOAT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_DEPTH:\\n\\t\\t\\t\\tthis._glFormat = gl.DEPTH_COMPONENT;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.DEPTH_COMPONENT32F;\\n\\t\\t\\t\\tthis._glPixelType = gl.FLOAT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_DEPTH16:\\n\\t\\t\\t\\tthis._glFormat = gl.DEPTH_COMPONENT;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.DEPTH_COMPONENT16;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_SHORT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_DEPTHSTENCIL:\\n\\t\\t\\t\\tthis._glFormat = gl.DEPTH_STENCIL;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.DEPTH24_STENCIL8;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_INT_24_8;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_111110F:\\n\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.R11F_G11F_B10F;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_INT_10F_11F_11F_REV;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_SRGB8:\\n\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.SRGB8;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_SRGBA8:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.SRGB8_ALPHA8;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t// Integer texture formats (R)\\n\\t\\t\\tcase PIXELFORMAT_R8I:\\n\\t\\t\\t\\tthis._glFormat = gl.RED_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.R8I;\\n\\t\\t\\t\\tthis._glPixelType = gl.BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_R8U:\\n\\t\\t\\t\\tthis._glFormat = gl.RED_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.R8UI;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_R16I:\\n\\t\\t\\t\\tthis._glFormat = gl.RED_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.R16I;\\n\\t\\t\\t\\tthis._glPixelType = gl.SHORT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_R16U:\\n\\t\\t\\t\\tthis._glFormat = gl.RED_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.R16UI;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_SHORT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_R32I:\\n\\t\\t\\t\\tthis._glFormat = gl.RED_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.R32I;\\n\\t\\t\\t\\tthis._glPixelType = gl.INT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_R32U:\\n\\t\\t\\t\\tthis._glFormat = gl.RED_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.R32UI;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_INT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t// Integer texture formats (RG)\\n\\t\\t\\tcase PIXELFORMAT_RG8I:\\n\\t\\t\\t\\tthis._glFormat = gl.RG_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RG8I;\\n\\t\\t\\t\\tthis._glPixelType = gl.BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RG8U:\\n\\t\\t\\t\\tthis._glFormat = gl.RG_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RG8UI;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RG16I:\\n\\t\\t\\t\\tthis._glFormat = gl.RG_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RG16I;\\n\\t\\t\\t\\tthis._glPixelType = gl.SHORT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RG16U:\\n\\t\\t\\t\\tthis._glFormat = gl.RG_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RG16UI;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_SHORT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RG32I:\\n\\t\\t\\t\\tthis._glFormat = gl.RG_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RG32I;\\n\\t\\t\\t\\tthis._glPixelType = gl.INT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RG32U:\\n\\t\\t\\t\\tthis._glFormat = gl.RG_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RG32UI;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_INT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t// Integer texture formats (RGBA)\\n\\t\\t\\tcase PIXELFORMAT_RGBA8I:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA8I;\\n\\t\\t\\t\\tthis._glPixelType = gl.BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGBA8U:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA8UI;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGBA16I:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA16I;\\n\\t\\t\\t\\tthis._glPixelType = gl.SHORT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGBA16U:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA16UI;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_SHORT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGBA32I:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA32I;\\n\\t\\t\\t\\tthis._glPixelType = gl.INT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_RGBA32U:\\n\\t\\t\\t\\tthis._glFormat = gl.RGBA_INTEGER;\\n\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA32UI;\\n\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_INT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t}\\n\\t\\tthis._glCreated = false;\\n\\t}\\n\\tupload(device, texture) {\\n\\t\\tconst gl = device.gl;\\n\\t\\tif (!texture._needsUpload && (texture._needsMipmapsUpload && texture._mipmapsUploaded || !texture.pot)) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tlet mipLevel = 0;\\n\\t\\tlet mipObject;\\n\\t\\tlet resMult;\\n\\t\\tconst requiredMipLevels = texture.numLevels;\\n\\t\\tif (texture.array && !this._glCreated) {\\n\\t\\t\\tgl.texStorage3D(\\n\\t\\t\\t\\tgl.TEXTURE_2D_ARRAY,\\n\\t\\t\\t\\trequiredMipLevels,\\n\\t\\t\\t\\tthis._glInternalFormat,\\n\\t\\t\\t\\ttexture._width,\\n\\t\\t\\t\\ttexture._height,\\n\\t\\t\\t\\ttexture._arrayLength\\n\\t\\t\\t);\\n\\t\\t}\\n\\t\\twhile (texture._levels[mipLevel] || mipLevel === 0) {\\n\\t\\t\\tif (!texture._needsUpload && mipLevel === 0) {\\n\\t\\t\\t\\tmipLevel++;\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t} else if (mipLevel && (!texture._needsMipmapsUpload || !texture._mipmaps)) {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\tmipObject = texture._levels[mipLevel];\\n\\t\\t\\tresMult = 1 / Math.pow(2, mipLevel);\\n\\t\\t\\tif (mipLevel === 1 && !texture._compressed && !texture._integerFormat && texture._levels.length < requiredMipLevels) {\\n\\t\\t\\t\\tgl.generateMipmap(this._glTarget);\\n\\t\\t\\t\\ttexture._mipmapsUploaded = true;\\n\\t\\t\\t}\\n\\t\\t\\tif (texture._cubemap) {\\n\\t\\t\\t\\tlet face;\\n\\t\\t\\t\\tif (device._isBrowserInterface(mipObject[0])) {\\n\\t\\t\\t\\t\\tfor (face = 0; face < 6; face++) {\\n\\t\\t\\t\\t\\t\\tif (!texture._levelsUpdated[0][face]) {\\n\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlet src = mipObject[face];\\n\\t\\t\\t\\t\\t\\tif (device._isImageBrowserInterface(src)) {\\n\\t\\t\\t\\t\\t\\t\\tif (src.width > device.maxCubeMapSize || src.height > device.maxCubeMapSize) {\\n\\t\\t\\t\\t\\t\\t\\t\\tsrc = downsampleImage(src, device.maxCubeMapSize);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (mipLevel === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture._width = src.width;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture._height = src.height;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tdevice.setUnpackFlipY(false);\\n\\t\\t\\t\\t\\t\\tdevice.setUnpackPremultiplyAlpha(texture._premultiplyAlpha);\\n\\t\\t\\t\\t\\t\\tif (this._glCreated) {\\n\\t\\t\\t\\t\\t\\t\\tgl.texSubImage2D(\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.TEXTURE_CUBE_MAP_POSITIVE_X + face,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipLevel,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType,\\n\\t\\t\\t\\t\\t\\t\\t\\tsrc\\n\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tgl.texImage2D(\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.TEXTURE_CUBE_MAP_POSITIVE_X + face,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipLevel,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType,\\n\\t\\t\\t\\t\\t\\t\\t\\tsrc\\n\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tresMult = 1 / Math.pow(2, mipLevel);\\n\\t\\t\\t\\t\\tfor (face = 0; face < 6; face++) {\\n\\t\\t\\t\\t\\t\\tif (!texture._levelsUpdated[0][face]) {\\n\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst texData = mipObject[face];\\n\\t\\t\\t\\t\\t\\tif (texture._compressed) {\\n\\t\\t\\t\\t\\t\\t\\tif (this._glCreated && texData) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.compressedTexSubImage2D(\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.TEXTURE_CUBE_MAP_POSITIVE_X + face,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tmipLevel,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tMath.max(texture._width * resMult, 1),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tMath.max(texture._height * resMult, 1),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ttexData\\n\\t\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.compressedTexImage2D(\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.TEXTURE_CUBE_MAP_POSITIVE_X + face,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tmipLevel,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tMath.max(texture._width * resMult, 1),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tMath.max(texture._height * resMult, 1),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ttexData\\n\\t\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackFlipY(false);\\n\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackPremultiplyAlpha(texture._premultiplyAlpha);\\n\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackAlignment(1);\\n\\t\\t\\t\\t\\t\\t\\tif (this._glCreated && texData) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.texSubImage2D(\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.TEXTURE_CUBE_MAP_POSITIVE_X + face,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tmipLevel,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tMath.max(texture._width * resMult, 1),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tMath.max(texture._height * resMult, 1),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ttexData\\n\\t\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.texImage2D(\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.TEXTURE_CUBE_MAP_POSITIVE_X + face,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tmipLevel,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tMath.max(texture._width * resMult, 1),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tMath.max(texture._height * resMult, 1),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ttexData\\n\\t\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else if (texture._volume) {\\n\\t\\t\\t\\tif (texture._compressed) {\\n\\t\\t\\t\\t\\tgl.compressedTexImage3D(\\n\\t\\t\\t\\t\\t\\tgl.TEXTURE_3D,\\n\\t\\t\\t\\t\\t\\tmipLevel,\\n\\t\\t\\t\\t\\t\\tthis._glInternalFormat,\\n\\t\\t\\t\\t\\t\\tMath.max(texture._width * resMult, 1),\\n\\t\\t\\t\\t\\t\\tMath.max(texture._height * resMult, 1),\\n\\t\\t\\t\\t\\t\\tMath.max(texture._depth * resMult, 1),\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\tmipObject\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tdevice.setUnpackFlipY(false);\\n\\t\\t\\t\\t\\tdevice.setUnpackPremultiplyAlpha(texture._premultiplyAlpha);\\n\\t\\t\\t\\t\\tdevice.setUnpackAlignment(1);\\n\\t\\t\\t\\t\\tgl.texImage3D(\\n\\t\\t\\t\\t\\t\\tgl.TEXTURE_3D,\\n\\t\\t\\t\\t\\t\\tmipLevel,\\n\\t\\t\\t\\t\\t\\tthis._glInternalFormat,\\n\\t\\t\\t\\t\\t\\tMath.max(texture._width * resMult, 1),\\n\\t\\t\\t\\t\\t\\tMath.max(texture._height * resMult, 1),\\n\\t\\t\\t\\t\\t\\tMath.max(texture._depth * resMult, 1),\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\tthis._glFormat,\\n\\t\\t\\t\\t\\t\\tthis._glPixelType,\\n\\t\\t\\t\\t\\t\\tmipObject\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else if (texture.array) {\\n\\t\\t\\t\\tif (Array.isArray(mipObject) && texture._arrayLength === mipObject.length) {\\n\\t\\t\\t\\t\\tif (texture._compressed) {\\n\\t\\t\\t\\t\\t\\tfor (let index = 0; index < texture._arrayLength; index++) {\\n\\t\\t\\t\\t\\t\\t\\tgl.compressedTexSubImage3D(\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.TEXTURE_2D_ARRAY,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipLevel,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\tindex,\\n\\t\\t\\t\\t\\t\\t\\t\\tMath.max(Math.floor(texture._width * resMult), 1),\\n\\t\\t\\t\\t\\t\\t\\t\\tMath.max(Math.floor(texture._height * resMult), 1),\\n\\t\\t\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipObject[index]\\n\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tdevice.setUnpackAlignment(1);\\n\\t\\t\\t\\t\\t\\tfor (let index = 0; index < texture._arrayLength; index++) {\\n\\t\\t\\t\\t\\t\\t\\tgl.texSubImage3D(\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.TEXTURE_2D_ARRAY,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipLevel,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\tindex,\\n\\t\\t\\t\\t\\t\\t\\t\\tMath.max(Math.floor(texture._width * resMult), 1),\\n\\t\\t\\t\\t\\t\\t\\t\\tMath.max(Math.floor(texture._height * resMult), 1),\\n\\t\\t\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipObject[index]\\n\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (device._isBrowserInterface(mipObject)) {\\n\\t\\t\\t\\t\\tif (device._isHTMLElementInterface(mipObject) && device.supportsHtmlTextures) {\\n\\t\\t\\t\\t\\t\\tdevice.setUnpackFlipY(texture._flipY);\\n\\t\\t\\t\\t\\t\\tdevice.setUnpackPremultiplyAlpha(texture._premultiplyAlpha);\\n\\t\\t\\t\\t\\t\\tconst rect = mipObject.getBoundingClientRect();\\n\\t\\t\\t\\t\\t\\tconst w = Math.floor(rect.width) || texture._width;\\n\\t\\t\\t\\t\\t\\tconst h = Math.floor(rect.height) || texture._height;\\n\\t\\t\\t\\t\\t\\tgl.texElementImage2D(\\n\\t\\t\\t\\t\\t\\t\\tgl.TEXTURE_2D,\\n\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat,\\n\\t\\t\\t\\t\\t\\t\\tmipObject\\n\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\tif (mipLevel === 0) {\\n\\t\\t\\t\\t\\t\\t\\ttexture._width = w;\\n\\t\\t\\t\\t\\t\\t\\ttexture._height = h;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (device._isImageBrowserInterface(mipObject)) {\\n\\t\\t\\t\\t\\t\\t\\tif (mipObject.width > device.maxTextureSize || mipObject.height > device.maxTextureSize) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmipObject = downsampleImage(mipObject, device.maxTextureSize);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (mipLevel === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture._width = mipObject.width;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture._height = mipObject.height;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst w = mipObject.width || mipObject.videoWidth;\\n\\t\\t\\t\\t\\t\\tconst h = mipObject.height || mipObject.videoHeight;\\n\\t\\t\\t\\t\\t\\tdevice.setUnpackFlipY(texture._flipY);\\n\\t\\t\\t\\t\\t\\tdevice.setUnpackPremultiplyAlpha(texture._premultiplyAlpha);\\n\\t\\t\\t\\t\\t\\tif (this._glCreated && texture._width === w && texture._height === h && !device._isImageVideoInterface(mipObject)) {\\n\\t\\t\\t\\t\\t\\t\\tgl.texSubImage2D(\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.TEXTURE_2D,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipLevel,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipObject\\n\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tgl.texImage2D(\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.TEXTURE_2D,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipLevel,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipObject\\n\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t\\tif (mipLevel === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\ttexture._width = w;\\n\\t\\t\\t\\t\\t\\t\\t\\ttexture._height = h;\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tresMult = 1 / Math.pow(2, mipLevel);\\n\\t\\t\\t\\t\\tif (texture._compressed) {\\n\\t\\t\\t\\t\\t\\tif (this._glCreated && mipObject) {\\n\\t\\t\\t\\t\\t\\t\\tgl.compressedTexSubImage2D(\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.TEXTURE_2D,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipLevel,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\tMath.max(Math.floor(texture._width * resMult), 1),\\n\\t\\t\\t\\t\\t\\t\\t\\tMath.max(Math.floor(texture._height * resMult), 1),\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipObject\\n\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tgl.compressedTexImage2D(\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.TEXTURE_2D,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipLevel,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tMath.max(Math.floor(texture._width * resMult), 1),\\n\\t\\t\\t\\t\\t\\t\\t\\tMath.max(Math.floor(texture._height * resMult), 1),\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipObject\\n\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tdevice.setUnpackFlipY(false);\\n\\t\\t\\t\\t\\t\\tdevice.setUnpackPremultiplyAlpha(texture._premultiplyAlpha);\\n\\t\\t\\t\\t\\t\\tdevice.setUnpackAlignment(1);\\n\\t\\t\\t\\t\\t\\tif (this._glCreated && mipObject) {\\n\\t\\t\\t\\t\\t\\t\\tgl.texSubImage2D(\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.TEXTURE_2D,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipLevel,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\tMath.max(texture._width * resMult, 1),\\n\\t\\t\\t\\t\\t\\t\\t\\tMath.max(texture._height * resMult, 1),\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipObject\\n\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tgl.texImage2D(\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.TEXTURE_2D,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipLevel,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tMath.max(texture._width * resMult, 1),\\n\\t\\t\\t\\t\\t\\t\\t\\tMath.max(texture._height * resMult, 1),\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipObject\\n\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (mipLevel === 0) {\\n\\t\\t\\t\\t\\ttexture._mipmapsUploaded = false;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\ttexture._mipmapsUploaded = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tmipLevel++;\\n\\t\\t}\\n\\t\\tif (texture._needsUpload) {\\n\\t\\t\\tif (texture._cubemap) {\\n\\t\\t\\t\\tfor (let i = 0; i < 6; i++) {\\n\\t\\t\\t\\t\\ttexture._levelsUpdated[0][i] = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\ttexture._levelsUpdated[0] = false;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (!texture._compressed && !texture._integerFormat && texture._mipmaps && texture._needsMipmapsUpload && texture._levels.length === 1) {\\n\\t\\t\\tgl.generateMipmap(this._glTarget);\\n\\t\\t\\ttexture._mipmapsUploaded = true;\\n\\t\\t}\\n\\t\\tif (texture._gpuSize) {\\n\\t\\t\\ttexture.adjustVramSizeTracking(device._vram, -texture._gpuSize);\\n\\t\\t}\\n\\t\\ttexture._gpuSize = texture.gpuSize;\\n\\t\\ttexture.adjustVramSizeTracking(device._vram, texture._gpuSize);\\n\\t\\tif (texture.releaseSourceAfterUpload) {\\n\\t\\t\\ttexture.releaseImageSources();\\n\\t\\t}\\n\\t\\tthis._glCreated = true;\\n\\t}\\n\\tuploadImmediate(device, texture) {\\n\\t\\tif (texture._needsUpload || texture._needsMipmapsUpload) {\\n\\t\\t\\tdevice.setTexture(texture, 0);\\n\\t\\t\\ttexture._needsUpload = false;\\n\\t\\t\\ttexture._needsMipmapsUpload = false;\\n\\t\\t}\\n\\t}\\n\\tread(x, y, width, height, options) {\\n\\t\\tconst texture = this.texture;\\n\\t\\tconst device = texture.device;\\n\\t\\treturn device.readTextureAsync(texture, x, y, width, height, options);\\n\\t}\\n\\twrite(x, y, width, height, data) {\\n\\t\\tconst { texture } = this;\\n\\t\\tconst { device } = texture;\\n\\t\\tdevice.setTexture(texture, 0);\\n\\t\\treturn device.writeTextureAsync(texture, x, y, width, height, data);\\n\\t}\\n}\\n\\nconst _validatedFboConfigs = new DeviceCache();\\nclass FramebufferPair {\\n\\tmsaaFB;\\n\\tresolveFB;\\n\\tconstructor(msaaFB, resolveFB) {\\n\\t\\tthis.msaaFB = msaaFB;\\n\\t\\tthis.resolveFB = resolveFB;\\n\\t}\\n\\tdestroy(gl) {\\n\\t\\tif (this.msaaFB) {\\n\\t\\t\\tgl.deleteRenderbuffer(this.msaaFB);\\n\\t\\t\\tthis.msaaFB = null;\\n\\t\\t}\\n\\t\\tif (this.resolveFB) {\\n\\t\\t\\tgl.deleteRenderbuffer(this.resolveFB);\\n\\t\\t\\tthis.resolveFB = null;\\n\\t\\t}\\n\\t}\\n}\\nclass WebglRenderTarget {\\n\\t_glFrameBuffer = null;\\n\\t_glDepthBuffer = null;\\n\\t_glResolveFrameBuffer = null;\\n\\tcolorMrtFramebuffers = null;\\n\\t_glMsaaColorBuffers = [];\\n\\t_glMsaaDepthBuffer = null;\\n\\tmsaaDepthBufferKey;\\n\\tsuppliedColorFramebuffer;\\n\\t_isInitialized = false;\\n\\tdestroy(device) {\\n\\t\\tconst gl = device.gl;\\n\\t\\tthis._isInitialized = false;\\n\\t\\tif (this._glFrameBuffer) {\\n\\t\\t\\tif (this._glFrameBuffer !== this.suppliedColorFramebuffer) {\\n\\t\\t\\t\\tgl.deleteFramebuffer(this._glFrameBuffer);\\n\\t\\t\\t}\\n\\t\\t\\tthis._glFrameBuffer = null;\\n\\t\\t}\\n\\t\\tif (this._glDepthBuffer) {\\n\\t\\t\\tgl.deleteRenderbuffer(this._glDepthBuffer);\\n\\t\\t\\tthis._glDepthBuffer = null;\\n\\t\\t}\\n\\t\\tif (this._glResolveFrameBuffer) {\\n\\t\\t\\tif (this._glResolveFrameBuffer !== this.suppliedColorFramebuffer) {\\n\\t\\t\\t\\tgl.deleteFramebuffer(this._glResolveFrameBuffer);\\n\\t\\t\\t}\\n\\t\\t\\tthis._glResolveFrameBuffer = null;\\n\\t\\t}\\n\\t\\tthis._glMsaaColorBuffers.forEach((buffer) => {\\n\\t\\t\\tgl.deleteRenderbuffer(buffer);\\n\\t\\t});\\n\\t\\tthis._glMsaaColorBuffers.length = 0;\\n\\t\\tthis.colorMrtFramebuffers?.forEach((framebuffer) => {\\n\\t\\t\\tframebuffer.destroy(gl);\\n\\t\\t});\\n\\t\\tthis.colorMrtFramebuffers = null;\\n\\t\\tif (this._glMsaaDepthBuffer) {\\n\\t\\t\\tthis._glMsaaDepthBuffer = null;\\n\\t\\t\\tif (this.msaaDepthBufferKey) {\\n\\t\\t\\t\\tgetMultisampledTextureCache(device).release(this.msaaDepthBufferKey);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.suppliedColorFramebuffer = void 0;\\n\\t}\\n\\tget initialized() {\\n\\t\\treturn this._isInitialized;\\n\\t}\\n\\tinit(device, target) {\\n\\t\\tconst gl = device.gl;\\n\\t\\tthis._isInitialized = true;\\n\\t\\tconst buffers = [];\\n\\t\\tif (this.suppliedColorFramebuffer !== void 0) {\\n\\t\\t\\tthis._glFrameBuffer = this.suppliedColorFramebuffer;\\n\\t\\t} else {\\n\\t\\t\\tthis._glFrameBuffer = gl.createFramebuffer();\\n\\t\\t\\tdevice.setFramebuffer(this._glFrameBuffer);\\n\\t\\t\\tconst colorBufferCount = target._colorBuffers?.length ?? 0;\\n\\t\\t\\tconst attachmentBaseConstant = gl.COLOR_ATTACHMENT0;\\n\\t\\t\\tfor (let i = 0; i < colorBufferCount; ++i) {\\n\\t\\t\\t\\tconst colorBuffer = target.getColorBuffer(i);\\n\\t\\t\\t\\tif (colorBuffer) {\\n\\t\\t\\t\\t\\tif (!colorBuffer.impl._glTexture) {\\n\\t\\t\\t\\t\\t\\tcolorBuffer._width = Math.min(colorBuffer.width, device.maxRenderBufferSize);\\n\\t\\t\\t\\t\\t\\tcolorBuffer._height = Math.min(colorBuffer.height, device.maxRenderBufferSize);\\n\\t\\t\\t\\t\\t\\tdevice.setTexture(colorBuffer, 0);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tgl.framebufferTexture2D(\\n\\t\\t\\t\\t\\t\\tgl.FRAMEBUFFER,\\n\\t\\t\\t\\t\\t\\tattachmentBaseConstant + i,\\n\\t\\t\\t\\t\\t\\tcolorBuffer._cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,\\n\\t\\t\\t\\t\\t\\tcolorBuffer.impl._glTexture,\\n\\t\\t\\t\\t\\t\\ttarget.mipLevel\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\tbuffers.push(attachmentBaseConstant + i);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tgl.drawBuffers(buffers);\\n\\t\\t\\tconst depthBuffer = target._depthBuffer;\\n\\t\\t\\tif (depthBuffer || target._depth) {\\n\\t\\t\\t\\tconst attachmentPoint = target._stencil ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;\\n\\t\\t\\t\\tif (depthBuffer) {\\n\\t\\t\\t\\t\\tif (!depthBuffer.impl._glTexture) {\\n\\t\\t\\t\\t\\t\\tdepthBuffer._width = Math.min(depthBuffer.width, device.maxRenderBufferSize);\\n\\t\\t\\t\\t\\t\\tdepthBuffer._height = Math.min(depthBuffer.height, device.maxRenderBufferSize);\\n\\t\\t\\t\\t\\t\\tdevice.setTexture(depthBuffer, 0);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tgl.framebufferTexture2D(\\n\\t\\t\\t\\t\\t\\tgl.FRAMEBUFFER,\\n\\t\\t\\t\\t\\t\\tattachmentPoint,\\n\\t\\t\\t\\t\\t\\tdepthBuffer._cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,\\n\\t\\t\\t\\t\\t\\ttarget._depthBuffer.impl._glTexture,\\n\\t\\t\\t\\t\\t\\ttarget.mipLevel\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tconst willRenderMsaa = target._samples > 1;\\n\\t\\t\\t\\t\\tif (!willRenderMsaa) {\\n\\t\\t\\t\\t\\t\\tif (!this._glDepthBuffer) {\\n\\t\\t\\t\\t\\t\\t\\tthis._glDepthBuffer = gl.createRenderbuffer();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst internalFormat = target._stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT32F;\\n\\t\\t\\t\\t\\t\\tgl.bindRenderbuffer(gl.RENDERBUFFER, this._glDepthBuffer);\\n\\t\\t\\t\\t\\t\\tgl.renderbufferStorage(gl.RENDERBUFFER, internalFormat, target.width, target.height);\\n\\t\\t\\t\\t\\t\\tgl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachmentPoint, gl.RENDERBUFFER, this._glDepthBuffer);\\n\\t\\t\\t\\t\\t\\tgl.bindRenderbuffer(gl.RENDERBUFFER, null);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (target._samples > 1) {\\n\\t\\t\\tthis._glResolveFrameBuffer = this._glFrameBuffer;\\n\\t\\t\\tthis._glFrameBuffer = gl.createFramebuffer();\\n\\t\\t\\tdevice.setFramebuffer(this._glFrameBuffer);\\n\\t\\t\\tconst colorBufferCount = target._colorBuffers?.length ?? 0;\\n\\t\\t\\tif (this.suppliedColorFramebuffer !== void 0) {\\n\\t\\t\\t\\tconst buffer = gl.createRenderbuffer();\\n\\t\\t\\t\\tthis._glMsaaColorBuffers.push(buffer);\\n\\t\\t\\t\\tconst internalFormat = device.backBufferFormat === PIXELFORMAT_RGBA8 ? gl.RGBA8 : gl.RGB8;\\n\\t\\t\\t\\tgl.bindRenderbuffer(gl.RENDERBUFFER, buffer);\\n\\t\\t\\t\\tgl.renderbufferStorageMultisample(gl.RENDERBUFFER, target._samples, internalFormat, target.width, target.height);\\n\\t\\t\\t\\tgl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, buffer);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tfor (let i = 0; i < colorBufferCount; ++i) {\\n\\t\\t\\t\\t\\tconst colorBuffer = target.getColorBuffer(i);\\n\\t\\t\\t\\t\\tif (colorBuffer) {\\n\\t\\t\\t\\t\\t\\tconst buffer = gl.createRenderbuffer();\\n\\t\\t\\t\\t\\t\\tthis._glMsaaColorBuffers.push(buffer);\\n\\t\\t\\t\\t\\t\\tgl.bindRenderbuffer(gl.RENDERBUFFER, buffer);\\n\\t\\t\\t\\t\\t\\tgl.renderbufferStorageMultisample(gl.RENDERBUFFER, target._samples, colorBuffer.impl._glInternalFormat, target.width, target.height);\\n\\t\\t\\t\\t\\t\\tgl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.RENDERBUFFER, buffer);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (target._depth) {\\n\\t\\t\\t\\tconst internalFormat = target._stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT32F;\\n\\t\\t\\t\\tconst attachmentPoint = target._stencil ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;\\n\\t\\t\\t\\tlet key;\\n\\t\\t\\t\\tconst depthBuffer = target._depthBuffer;\\n\\t\\t\\t\\tif (depthBuffer) {\\n\\t\\t\\t\\t\\tkey = `${depthBuffer.id}:${target.width}:${target.height}:${target._samples}:${internalFormat}:${attachmentPoint}`;\\n\\t\\t\\t\\t\\tthis._glMsaaDepthBuffer = getMultisampledTextureCache(device).get(key);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._glMsaaDepthBuffer) {\\n\\t\\t\\t\\t\\tthis._glMsaaDepthBuffer = gl.createRenderbuffer();\\n\\t\\t\\t\\t\\tgl.bindRenderbuffer(gl.RENDERBUFFER, this._glMsaaDepthBuffer);\\n\\t\\t\\t\\t\\tgl.renderbufferStorageMultisample(gl.RENDERBUFFER, target._samples, internalFormat, target.width, target.height);\\n\\t\\t\\t\\t\\tthis._glMsaaDepthBuffer.destroy = function() {\\n\\t\\t\\t\\t\\t\\tgl.deleteRenderbuffer(this);\\n\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\tif (depthBuffer) {\\n\\t\\t\\t\\t\\t\\tgetMultisampledTextureCache(device).set(key, this._glMsaaDepthBuffer);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.msaaDepthBufferKey = key;\\n\\t\\t\\t\\tgl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachmentPoint, gl.RENDERBUFFER, this._glMsaaDepthBuffer);\\n\\t\\t\\t}\\n\\t\\t\\tif (colorBufferCount > 1) {\\n\\t\\t\\t\\tthis._createMsaaMrtFramebuffers(device, target, colorBufferCount);\\n\\t\\t\\t\\tdevice.setFramebuffer(this._glFrameBuffer);\\n\\t\\t\\t\\tgl.drawBuffers(buffers);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_createMsaaMrtFramebuffers(device, target, colorBufferCount) {\\n\\t\\tconst gl = device.gl;\\n\\t\\tthis.colorMrtFramebuffers = [];\\n\\t\\tfor (let i = 0; i < colorBufferCount; ++i) {\\n\\t\\t\\tconst colorBuffer = target.getColorBuffer(i);\\n\\t\\t\\tconst srcFramebuffer = gl.createFramebuffer();\\n\\t\\t\\tdevice.setFramebuffer(srcFramebuffer);\\n\\t\\t\\tconst buffer = this._glMsaaColorBuffers[i];\\n\\t\\t\\tgl.bindRenderbuffer(gl.RENDERBUFFER, buffer);\\n\\t\\t\\tgl.renderbufferStorageMultisample(gl.RENDERBUFFER, target._samples, colorBuffer.impl._glInternalFormat, target.width, target.height);\\n\\t\\t\\tgl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, buffer);\\n\\t\\t\\tgl.drawBuffers([gl.COLOR_ATTACHMENT0]);\\n\\t\\t\\tconst dstFramebuffer = gl.createFramebuffer();\\n\\t\\t\\tdevice.setFramebuffer(dstFramebuffer);\\n\\t\\t\\tgl.framebufferTexture2D(\\n\\t\\t\\t\\tgl.FRAMEBUFFER,\\n\\t\\t\\t\\tgl.COLOR_ATTACHMENT0,\\n\\t\\t\\t\\tcolorBuffer._cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D,\\n\\t\\t\\t\\tcolorBuffer.impl._glTexture,\\n\\t\\t\\t\\t0\\n\\t\\t\\t);\\n\\t\\t\\tthis.colorMrtFramebuffers[i] = new FramebufferPair(srcFramebuffer, dstFramebuffer);\\n\\t\\t}\\n\\t}\\n\\t_checkFbo(device, target, type = \\\"\\\") {\\n\\t\\tconst colorFormats = target._colorBuffers?.map((b) => b?.format ?? -1).join(\\\",\\\") ?? \\\"\\\";\\n\\t\\tconst depthInfo = target._depth ? target._depthBuffer ? `dt${target._depthBuffer.format}` : target._stencil ? \\\"ds\\\" : \\\"d\\\" : \\\"\\\";\\n\\t\\tconst key = `${type}:${colorFormats}:${depthInfo}:${target._samples}`;\\n\\t\\tconst validated = _validatedFboConfigs.get(device, () => {\\n\\t\\t\\tconst set = /* @__PURE__ */ new Set();\\n\\t\\t\\tset.loseContext = () => set.clear();\\n\\t\\t\\treturn set;\\n\\t\\t});\\n\\t\\tif (validated.has(key)) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst gl = device.gl;\\n\\t\\tconst status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\\n\\t\\tswitch (status) {\\n\\t\\t\\tcase gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase gl.FRAMEBUFFER_UNSUPPORTED:\\n\\t\\t\\t\\tbreak;\\n\\t\\t}\\n\\t\\tif (status === gl.FRAMEBUFFER_COMPLETE) {\\n\\t\\t\\tvalidated.add(key);\\n\\t\\t}\\n\\t}\\n\\tloseContext() {\\n\\t\\tthis._glFrameBuffer = null;\\n\\t\\tthis._glDepthBuffer = null;\\n\\t\\tthis._glResolveFrameBuffer = null;\\n\\t\\tthis._glMsaaColorBuffers.length = 0;\\n\\t\\tthis._glMsaaDepthBuffer = null;\\n\\t\\tthis.msaaDepthBufferKey = void 0;\\n\\t\\tthis.colorMrtFramebuffers = null;\\n\\t\\tthis.suppliedColorFramebuffer = void 0;\\n\\t\\tthis._isInitialized = false;\\n\\t}\\n\\tinternalResolve(device, src, dst, target, mask) {\\n\\t\\tdevice.setScissor(0, 0, target.width, target.height);\\n\\t\\tconst gl = device.gl;\\n\\t\\tgl.bindFramebuffer(gl.READ_FRAMEBUFFER, src);\\n\\t\\tgl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dst);\\n\\t\\tgl.blitFramebuffer(\\n\\t\\t\\t0,\\n\\t\\t\\t0,\\n\\t\\t\\ttarget.width,\\n\\t\\t\\ttarget.height,\\n\\t\\t\\t0,\\n\\t\\t\\t0,\\n\\t\\t\\ttarget.width,\\n\\t\\t\\ttarget.height,\\n\\t\\t\\tmask,\\n\\t\\t\\tgl.NEAREST\\n\\t\\t);\\n\\t}\\n\\tresolve(device, target, color, depth) {\\n\\t\\tconst gl = device.gl;\\n\\t\\tif (this.colorMrtFramebuffers) {\\n\\t\\t\\tif (color) {\\n\\t\\t\\t\\tfor (let i = 0; i < this.colorMrtFramebuffers.length; i++) {\\n\\t\\t\\t\\t\\tconst fbPair = this.colorMrtFramebuffers[i];\\n\\t\\t\\t\\t\\tthis.internalResolve(device, fbPair.msaaFB, fbPair.resolveFB, target, gl.COLOR_BUFFER_BIT);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (depth) {\\n\\t\\t\\t\\tthis.internalResolve(device, this._glFrameBuffer, this._glResolveFrameBuffer, target, gl.DEPTH_BUFFER_BIT);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tconst isXrFramebuffer = !!device.defaultFramebuffer && this._glResolveFrameBuffer === device.defaultFramebuffer;\\n\\t\\t\\tconst xrColorQuad = color && isXrFramebuffer && platform.visionos;\\n\\t\\t\\tif (xrColorQuad) {\\n\\t\\t\\t\\tdevice.resolveMsaaColorToXrFramebufferViaQuads(\\n\\t\\t\\t\\t\\tthis._glFrameBuffer,\\n\\t\\t\\t\\t\\tthis._glResolveFrameBuffer,\\n\\t\\t\\t\\t\\ttarget.width,\\n\\t\\t\\t\\t\\ttarget.height\\n\\t\\t\\t\\t);\\n\\t\\t\\t\\tcolor = false;\\n\\t\\t\\t}\\n\\t\\t\\tif (color || depth) {\\n\\t\\t\\t\\tthis.internalResolve(\\n\\t\\t\\t\\t\\tdevice,\\n\\t\\t\\t\\t\\tthis._glFrameBuffer,\\n\\t\\t\\t\\t\\tthis._glResolveFrameBuffer,\\n\\t\\t\\t\\t\\ttarget,\\n\\t\\t\\t\\t\\t(color ? gl.COLOR_BUFFER_BIT : 0) | (depth ? gl.DEPTH_BUFFER_BIT : 0)\\n\\t\\t\\t\\t);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgl.bindFramebuffer(gl.FRAMEBUFFER, this._glFrameBuffer);\\n\\t}\\n}\\n\\nclass WebglUploadStream {\\n\\tavailablePBOs = [];\\n\\tpendingPBOs = [];\\n\\tconstructor(uploadStream) {\\n\\t\\tthis.uploadStream = uploadStream;\\n\\t\\tthis.useSingleBuffer = uploadStream.useSingleBuffer;\\n\\t}\\n\\tdestroy() {\\n\\t\\tconst gl = this.uploadStream.device.gl;\\n\\t\\tthis.availablePBOs.forEach((info) => gl.deleteBuffer(info.pbo));\\n\\t\\tthis.pendingPBOs.forEach((item) => {\\n\\t\\t\\tif (item.sync) gl.deleteSync(item.sync);\\n\\t\\t\\tgl.deleteBuffer(item.pbo);\\n\\t\\t});\\n\\t}\\n\\t_onDeviceLost() {\\n\\t\\tthis.availablePBOs.length = 0;\\n\\t\\tthis.pendingPBOs.length = 0;\\n\\t}\\n\\tupdate(minByteSize) {\\n\\t\\tconst gl = this.uploadStream.device.gl;\\n\\t\\tconst pending = this.pendingPBOs;\\n\\t\\tfor (let i = pending.length - 1; i >= 0; i--) {\\n\\t\\t\\tconst item = pending[i];\\n\\t\\t\\tconst result = gl.clientWaitSync(item.sync, 0, 0);\\n\\t\\t\\tif (result === gl.CONDITION_SATISFIED || result === gl.ALREADY_SIGNALED) {\\n\\t\\t\\t\\tgl.deleteSync(item.sync);\\n\\t\\t\\t\\tthis.availablePBOs.push({ pbo: item.pbo, size: item.size });\\n\\t\\t\\t\\tpending.splice(i, 1);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst available = this.availablePBOs;\\n\\t\\tfor (let i = available.length - 1; i >= 0; i--) {\\n\\t\\t\\tif (available[i].size < minByteSize) {\\n\\t\\t\\t\\tgl.deleteBuffer(available[i].pbo);\\n\\t\\t\\t\\tavailable.splice(i, 1);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tupload(data, target, offset, size) {\\n\\t\\tif (this.useSingleBuffer) {\\n\\t\\t\\tthis.uploadDirect(data, target, offset, size);\\n\\t\\t} else {\\n\\t\\t\\tthis.uploadPBO(data, target, offset, size);\\n\\t\\t}\\n\\t}\\n\\tuploadDirect(data, target, offset, size) {\\n\\t\\tconst device = this.uploadStream.device;\\n\\t\\tconst gl = device.gl;\\n\\t\\tconst impl = target.impl;\\n\\t\\tdevice.setTexture(target, 0);\\n\\t\\tdevice.activeTexture(0);\\n\\t\\tdevice.bindTexture(target);\\n\\t\\tdevice.setUnpackFlipY(false);\\n\\t\\tdevice.setUnpackPremultiplyAlpha(false);\\n\\t\\tdevice.setUnpackAlignment(data.BYTES_PER_ELEMENT);\\n\\t\\tlet src = data;\\n\\t\\tif (impl._glPixelType === gl.UNSIGNED_BYTE && data.BYTES_PER_ELEMENT !== 1) {\\n\\t\\t\\tconst byteSize = size * data.BYTES_PER_ELEMENT;\\n\\t\\t\\tsrc = new Uint8Array(data.buffer, data.byteOffset, byteSize);\\n\\t\\t}\\n\\t\\tgl.texImage2D(\\n\\t\\t\\tgl.TEXTURE_2D,\\n\\t\\t\\t0,\\n\\t\\t\\timpl._glInternalFormat,\\n\\t\\t\\ttarget.width,\\n\\t\\t\\ttarget.height,\\n\\t\\t\\t0,\\n\\t\\t\\timpl._glFormat,\\n\\t\\t\\timpl._glPixelType,\\n\\t\\t\\tsrc\\n\\t\\t);\\n\\t\\timpl._glCreated = true;\\n\\t}\\n\\tuploadPBO(data, target, offset, size) {\\n\\t\\tconst device = this.uploadStream.device;\\n\\t\\tconst gl = device.gl;\\n\\t\\tconst width = target.width;\\n\\t\\tconst byteSize = size * data.BYTES_PER_ELEMENT;\\n\\t\\tthis.update(byteSize);\\n\\t\\tconst startY = offset / width;\\n\\t\\tconst height = size / width;\\n\\t\\tconst pboInfo = this.availablePBOs.pop() ?? (() => {\\n\\t\\t\\tconst pbo = gl.createBuffer();\\n\\t\\t\\treturn { pbo, size: byteSize };\\n\\t\\t})();\\n\\t\\tgl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, pboInfo.pbo);\\n\\t\\tgl.bufferData(gl.PIXEL_UNPACK_BUFFER, byteSize, gl.STREAM_DRAW);\\n\\t\\tgl.bufferSubData(gl.PIXEL_UNPACK_BUFFER, 0, new Uint8Array(data.buffer, data.byteOffset, byteSize));\\n\\t\\tgl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);\\n\\t\\tdevice.setTexture(target, 0);\\n\\t\\tdevice.activeTexture(0);\\n\\t\\tdevice.bindTexture(target);\\n\\t\\tgl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, pboInfo.pbo);\\n\\t\\tdevice.setUnpackFlipY(false);\\n\\t\\tdevice.setUnpackPremultiplyAlpha(false);\\n\\t\\tdevice.setUnpackAlignment(data.BYTES_PER_ELEMENT);\\n\\t\\tgl.pixelStorei(gl.UNPACK_ROW_LENGTH, 0);\\n\\t\\tgl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);\\n\\t\\tgl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);\\n\\t\\tconst impl = target.impl;\\n\\t\\tgl.texSubImage2D(gl.TEXTURE_2D, 0, 0, startY, width, height, impl._glFormat, impl._glPixelType, 0);\\n\\t\\tgl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);\\n\\t\\tconst sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);\\n\\t\\tthis.pendingPBOs.push({ pbo: pboInfo.pbo, size: byteSize, sync });\\n\\t\\tgl.flush();\\n\\t}\\n}\\n\\nclass WebglXrBridge {\\n\\t_presentationLayer = null;\\n\\t_graphicsBinding = null;\\n\\t_cameraFbSource = null;\\n\\t_cameraFbDest = null;\\n\\tconstructor(xrBridge) {\\n\\t\\tthis.xrBridge = xrBridge;\\n\\t}\\n\\tdestroy(device) {\\n\\t\\tthis._graphicsBinding = null;\\n\\t\\tthis._presentationLayer = null;\\n\\t\\tthis._deleteCameraFramebuffers(device);\\n\\t}\\n\\t_deleteCameraFramebuffers(device) {\\n\\t\\tif (this._cameraFbSource) {\\n\\t\\t\\tconst gl = device.gl;\\n\\t\\t\\tgl.deleteFramebuffer(this._cameraFbSource);\\n\\t\\t\\tthis._cameraFbSource = null;\\n\\t\\t\\tgl.deleteFramebuffer(this._cameraFbDest);\\n\\t\\t\\tthis._cameraFbDest = null;\\n\\t\\t}\\n\\t}\\n\\tbeginFrame(frame, _referenceSpace) {\\n\\t\\tconst baseLayer = frame.session.renderState.baseLayer;\\n\\t\\tthis.xrBridge.device.defaultFramebuffer = baseLayer ? baseLayer.framebuffer : null;\\n\\t}\\n\\tendFrame() {\\n\\t\\tthis.xrBridge.device.defaultFramebuffer = null;\\n\\t}\\n\\tget presentationLayer() {\\n\\t\\treturn this._presentationLayer;\\n\\t}\\n\\tget graphicsBinding() {\\n\\t\\treturn this._graphicsBinding;\\n\\t}\\n\\tgetFramebufferSize(frame, out) {\\n\\t\\tconst baseLayer = frame.session.renderState.baseLayer;\\n\\t\\tif (!baseLayer) {\\n\\t\\t\\tout.set(0, 0);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tout.set(baseLayer.framebufferWidth, baseLayer.framebufferHeight);\\n\\t}\\n\\tgetViewport(frame, xrView) {\\n\\t\\tconst baseLayer = frame.session.renderState.baseLayer;\\n\\t\\tif (!baseLayer) {\\n\\t\\t\\treturn { x: 0, y: 0, width: 0, height: 0 };\\n\\t\\t}\\n\\t\\treturn baseLayer.getViewport(xrView);\\n\\t}\\n\\tattachPresentation(session, options) {\\n\\t\\tconst device = this.xrBridge.device;\\n\\t\\tthis._presentationLayer = new XRWebGLLayer(session, device.gl, {\\n\\t\\t\\talpha: true,\\n\\t\\t\\tdepth: true,\\n\\t\\t\\tstencil: true,\\n\\t\\t\\tframebufferScaleFactor: options.framebufferScaleFactor,\\n\\t\\t\\tantialias: false\\n\\t\\t});\\n\\t\\tif (window.XRWebGLBinding) {\\n\\t\\t\\ttry {\\n\\t\\t\\t\\tthis._graphicsBinding = new XRWebGLBinding(session, device.gl);\\n\\t\\t\\t} catch (ex) {\\n\\t\\t\\t\\tthis.xrBridge._onBindingError?.(ex);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsession.updateRenderState({\\n\\t\\t\\tbaseLayer: this._presentationLayer,\\n\\t\\t\\tdepthNear: options.depthNear,\\n\\t\\t\\tdepthFar: options.depthFar\\n\\t\\t});\\n\\t}\\n\\treleasePresentation() {\\n\\t\\tthis._graphicsBinding = null;\\n\\t}\\n\\tsyncCameraColorTexture(xrCamera, texture) {\\n\\t\\tif (!this._graphicsBinding) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst device = this.xrBridge.device;\\n\\t\\tconst gl = device.gl;\\n\\t\\tconst src = this._graphicsBinding.getCameraImage(xrCamera);\\n\\t\\tif (!src) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!this._cameraFbSource) {\\n\\t\\t\\tthis._cameraFbSource = gl.createFramebuffer();\\n\\t\\t\\tthis._cameraFbDest = gl.createFramebuffer();\\n\\t\\t}\\n\\t\\tconst width = xrCamera.width;\\n\\t\\tconst height = xrCamera.height;\\n\\t\\tdevice.setFramebuffer(this._cameraFbSource);\\n\\t\\tgl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, src, 0);\\n\\t\\tdevice.setFramebuffer(this._cameraFbDest);\\n\\t\\tgl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture.impl._glTexture, 0);\\n\\t\\tgl.bindFramebuffer(gl.READ_FRAMEBUFFER, this._cameraFbSource);\\n\\t\\tgl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, this._cameraFbDest);\\n\\t\\tgl.blitFramebuffer(0, height, width, 0, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);\\n\\t\\tdevice.setFramebuffer(device.defaultFramebuffer);\\n\\t}\\n\\tsyncCameraDepthTexture(depthInfo, texture, depthPixelFormat) {\\n\\t\\tif (!depthInfo?.texture) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst gl = this.xrBridge.device.gl;\\n\\t\\ttexture.impl._glTexture = depthInfo.texture;\\n\\t\\tif (depthInfo.textureType === \\\"texture-array\\\") {\\n\\t\\t\\ttexture.impl._glTarget = gl.TEXTURE_2D_ARRAY;\\n\\t\\t} else {\\n\\t\\t\\ttexture.impl._glTarget = gl.TEXTURE_2D;\\n\\t\\t}\\n\\t\\tswitch (depthPixelFormat) {\\n\\t\\t\\tcase PIXELFORMAT_R32F:\\n\\t\\t\\t\\ttexture.impl._glInternalFormat = gl.R32F;\\n\\t\\t\\t\\ttexture.impl._glPixelType = gl.FLOAT;\\n\\t\\t\\t\\ttexture.impl._glFormat = gl.RED;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase PIXELFORMAT_DEPTH:\\n\\t\\t\\t\\ttexture.impl._glInternalFormat = gl.DEPTH_COMPONENT16;\\n\\t\\t\\t\\ttexture.impl._glPixelType = gl.UNSIGNED_SHORT;\\n\\t\\t\\t\\ttexture.impl._glFormat = gl.DEPTH_COMPONENT;\\n\\t\\t\\t\\tbreak;\\n\\t\\t}\\n\\t\\ttexture.impl._glCreated = true;\\n\\t}\\n\\tonGraphicsDeviceLost() {\\n\\t\\tconst session = this.xrBridge._session;\\n\\t\\tif (!session) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst rs = session.renderState;\\n\\t\\tthis._graphicsBinding = null;\\n\\t\\tthis._presentationLayer = null;\\n\\t\\tthis._cameraFbSource = null;\\n\\t\\tthis._cameraFbDest = null;\\n\\t\\tsession.updateRenderState({\\n\\t\\t\\tbaseLayer: this._presentationLayer,\\n\\t\\t\\tdepthNear: rs.depthNear,\\n\\t\\t\\tdepthFar: rs.depthFar\\n\\t\\t});\\n\\t}\\n\\tonGraphicsDeviceRestored() {\\n\\t\\tconst bridge = this.xrBridge;\\n\\t\\tif (!bridge._session) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst device = bridge.device;\\n\\t\\tconst eventHandler = bridge.eventHandler;\\n\\t\\tsetTimeout(() => {\\n\\t\\t\\tif (!bridge._session) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tdevice.gl.makeXRCompatible().then(() => {\\n\\t\\t\\t\\tif (!bridge._session) {\\n\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst rs = bridge._session.renderState;\\n\\t\\t\\t\\tbridge.attachPresentation(bridge._session, {\\n\\t\\t\\t\\t\\tframebufferScaleFactor: bridge._framebufferScaleFactor,\\n\\t\\t\\t\\t\\tdepthNear: rs.depthNear,\\n\\t\\t\\t\\t\\tdepthFar: rs.depthFar,\\n\\t\\t\\t\\t\\tonBindingError: bridge._onBindingError\\n\\t\\t\\t\\t});\\n\\t\\t\\t}).catch((ex) => {\\n\\t\\t\\t\\teventHandler.fire(\\\"error\\\", ex);\\n\\t\\t\\t});\\n\\t\\t}, 0);\\n\\t}\\n}\\n\\nconst _quadPrimitive$1 = {\\n\\ttype: PRIMITIVE_TRIANGLES,\\n\\tbase: 0,\\n\\tcount: 6,\\n\\tindexed: true\\n};\\nconst vsSrc = `\\n\\tattribute vec2 vertex_position;\\n\\tvarying vec2 pcTexCoord;\\n\\tvoid main() {\\n\\t\\tgl_Position = vec4(vertex_position, 0.0, 1.0);\\n\\t\\tpcTexCoord = vertex_position * 0.5 + 0.5;\\n\\t}\\n`;\\nconst fsSrc = `\\n\\tuniform sampler2D pcSource;\\n\\tvarying vec2 pcTexCoord;\\n\\tvoid main() {\\n\\t\\tgl_FragColor = texture2D(pcSource, pcTexCoord);\\n\\t}\\n`;\\nclass WebglXrMsaaCopy {\\n\\t_device;\\n\\t_shader = null;\\n\\t_scratchTex = null;\\n\\t_scratchRt = null;\\n\\t_sourceId = null;\\n\\tconstructor(device) {\\n\\t\\tthis._device = device;\\n\\t}\\n\\t_getShader() {\\n\\t\\tif (!this._shader) {\\n\\t\\t\\tconst device = this._device;\\n\\t\\t\\tthis._shader = new Shader(device, ShaderDefinitionUtils.createDefinition(device, {\\n\\t\\t\\t\\tname: \\\"XrMsaaCopy\\\",\\n\\t\\t\\t\\tattributes: { vertex_position: SEMANTIC_POSITION },\\n\\t\\t\\t\\tvertexCode: vsSrc,\\n\\t\\t\\t\\tfragmentCode: fsSrc\\n\\t\\t\\t}));\\n\\t\\t\\tthis._sourceId = device.scope.resolve(\\\"pcSource\\\");\\n\\t\\t}\\n\\t\\treturn this._shader;\\n\\t}\\n\\t_ensureScratch(width, height) {\\n\\t\\tconst device = this._device;\\n\\t\\tif (this._scratchTex && (this._scratchTex.width !== width || this._scratchTex.height !== height)) {\\n\\t\\t\\tthis._scratchRt.destroy();\\n\\t\\t\\tthis._scratchRt = null;\\n\\t\\t\\tthis._scratchTex.destroy();\\n\\t\\t\\tthis._scratchTex = null;\\n\\t\\t}\\n\\t\\tif (!this._scratchTex) {\\n\\t\\t\\tthis._scratchTex = Texture.createDataTexture2D(device, \\\"XrMsaaScratch\\\", width, height, device.backBufferFormat);\\n\\t\\t\\tthis._scratchRt = new RenderTarget({\\n\\t\\t\\t\\tcolorBuffer: this._scratchTex,\\n\\t\\t\\t\\tdepth: false,\\n\\t\\t\\t\\tstencil: false\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tif (!this._scratchRt.impl.initialized) {\\n\\t\\t\\tthis._scratchRt.impl.init(device, this._scratchRt);\\n\\t\\t}\\n\\t}\\n\\tcopy(msaaReadFbo, xrDrawFbo, width, height) {\\n\\t\\tthis._ensureScratch(width, height);\\n\\t\\tconst device = this._device;\\n\\t\\tconst gl = device.gl;\\n\\t\\tgl.bindFramebuffer(gl.READ_FRAMEBUFFER, msaaReadFbo);\\n\\t\\tgl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, this._scratchRt.impl._glFrameBuffer);\\n\\t\\tgl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);\\n\\t\\tdevice.setDrawStates(BlendState.NOBLEND, DepthState.NODEPTH);\\n\\t\\tdevice.setFramebuffer(xrDrawFbo);\\n\\t\\tdevice.setShader(this._getShader());\\n\\t\\tdevice.clearVertexBuffer();\\n\\t\\tdevice.setVertexBuffer(device.quadVertexBuffer);\\n\\t\\tthis._sourceId.setValue(this._scratchTex);\\n\\t\\tconst { vx, vy, vw, vh, sx, sy, sw, sh } = device;\\n\\t\\tdevice.setViewport(0, 0, width, height);\\n\\t\\tdevice.setScissor(0, 0, width, height);\\n\\t\\tdevice.draw(_quadPrimitive$1, device.quadIndexBuffer);\\n\\t\\tdevice.setViewport(vx, vy, vw, vh);\\n\\t\\tdevice.setScissor(sx, sy, sw, sh);\\n\\t\\tdevice.setFramebuffer(msaaReadFbo);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._shader?.destroy();\\n\\t\\tthis._shader = null;\\n\\t\\tthis._scratchRt?.destroy();\\n\\t\\tthis._scratchRt = null;\\n\\t\\tthis._scratchTex?.destroy();\\n\\t\\tthis._scratchTex = null;\\n\\t\\tthis._sourceId = null;\\n\\t}\\n}\\n\\nclass FrameQueriesInfo {\\n\\trenderVersion;\\n\\tqueries = [];\\n\\tdestroy(gl) {\\n\\t\\tthis.queries.forEach((query) => gl.deleteQuery(query));\\n\\t\\tthis.queries = null;\\n\\t}\\n}\\nclass WebglGpuProfiler extends GpuProfiler {\\n\\tdevice;\\n\\tfreeQueries = [];\\n\\tframeQueries = [];\\n\\tpreviousFrameQueries = [];\\n\\ttimings = [];\\n\\tconstructor(device) {\\n\\t\\tsuper();\\n\\t\\tthis.device = device;\\n\\t\\tthis.ext = device.extDisjointTimerQuery;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.freeQueries.forEach((query) => this.device.gl.deleteQuery(query));\\n\\t\\tthis.frameQueries.forEach((query) => this.device.gl.deleteQuery(query));\\n\\t\\tthis.previousFrameQueries.forEach((frameQueriesInfo) => frameQueriesInfo.destroy(this.device.gl));\\n\\t\\tthis.freeQueries = null;\\n\\t\\tthis.frameQueries = null;\\n\\t\\tthis.previousFrameQueries = null;\\n\\t}\\n\\tloseContext() {\\n\\t\\tsuper.loseContext();\\n\\t\\tthis.freeQueries = [];\\n\\t\\tthis.frameQueries = [];\\n\\t\\tthis.previousFrameQueries = [];\\n\\t}\\n\\trestoreContext() {\\n\\t\\tthis.ext = this.device.extDisjointTimerQuery;\\n\\t}\\n\\tgetQuery() {\\n\\t\\treturn this.freeQueries.pop() ?? this.device.gl.createQuery();\\n\\t}\\n\\tstart(name) {\\n\\t\\tif (this.ext) {\\n\\t\\t\\tconst slot = this.getSlot(name);\\n\\t\\t\\tconst query = this.getQuery();\\n\\t\\t\\tthis.frameQueries[slot] = query;\\n\\t\\t\\tthis.device.gl.beginQuery(this.ext.TIME_ELAPSED_EXT, query);\\n\\t\\t\\treturn slot;\\n\\t\\t}\\n\\t\\treturn void 0;\\n\\t}\\n\\tend(slot) {\\n\\t\\tif (slot !== void 0) {\\n\\t\\t\\tthis.device.gl.endQuery(this.ext.TIME_ELAPSED_EXT);\\n\\t\\t}\\n\\t}\\n\\tframeStart() {\\n\\t\\tthis.processEnableRequest();\\n\\t\\tif (this._enabled) {\\n\\t\\t\\tthis.frameGPUMarkerSlot = this.start(\\\"GpuFrame\\\");\\n\\t\\t}\\n\\t}\\n\\tframeEnd() {\\n\\t\\tif (this._enabled) {\\n\\t\\t\\tthis.end(this.frameGPUMarkerSlot);\\n\\t\\t}\\n\\t}\\n\\trequest() {\\n\\t\\tif (this._enabled) {\\n\\t\\t\\tconst ext = this.ext;\\n\\t\\t\\tconst gl = this.device.gl;\\n\\t\\t\\tconst renderVersion = this.device.renderVersion;\\n\\t\\t\\tconst frameQueries = this.frameQueries;\\n\\t\\t\\tif (frameQueries.length > 0) {\\n\\t\\t\\t\\tthis.frameQueries = [];\\n\\t\\t\\t\\tconst frameQueriesInfo = new FrameQueriesInfo();\\n\\t\\t\\t\\tframeQueriesInfo.queries = frameQueries;\\n\\t\\t\\t\\tframeQueriesInfo.renderVersion = renderVersion;\\n\\t\\t\\t\\tthis.previousFrameQueries.push(frameQueriesInfo);\\n\\t\\t\\t}\\n\\t\\t\\tif (this.previousFrameQueries.length > 0) {\\n\\t\\t\\t\\tconst previousQueriesInfo = this.previousFrameQueries[0];\\n\\t\\t\\t\\tconst previousQueries = previousQueriesInfo.queries;\\n\\t\\t\\t\\tconst lastQuery = previousQueries[previousQueries.length - 1];\\n\\t\\t\\t\\tconst available = gl.getQueryParameter(lastQuery, gl.QUERY_RESULT_AVAILABLE);\\n\\t\\t\\t\\tconst disjoint = gl.getParameter(ext.GPU_DISJOINT_EXT);\\n\\t\\t\\t\\tif (available && !disjoint) {\\n\\t\\t\\t\\t\\tthis.previousFrameQueries.shift();\\n\\t\\t\\t\\t\\tconst timings = this.timings;\\n\\t\\t\\t\\t\\ttimings.length = 0;\\n\\t\\t\\t\\t\\tfor (let i = 0; i < previousQueries.length; i++) {\\n\\t\\t\\t\\t\\t\\tconst query = previousQueries[i];\\n\\t\\t\\t\\t\\t\\tconst duration = gl.getQueryParameter(query, gl.QUERY_RESULT);\\n\\t\\t\\t\\t\\t\\ttimings[i] = duration * 1e-6;\\n\\t\\t\\t\\t\\t\\tthis.freeQueries.push(query);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tthis.report(previousQueriesInfo.renderVersion, timings);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (disjoint) {\\n\\t\\t\\t\\t\\tthis.previousFrameQueries.forEach((frameQueriesInfo) => {\\n\\t\\t\\t\\t\\t\\tthis.report(frameQueriesInfo.renderVersion, null);\\n\\t\\t\\t\\t\\t\\tframeQueriesInfo.destroy(gl);\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\tthis.previousFrameQueries.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tsuper.request(renderVersion);\\n\\t\\t}\\n\\t}\\n}\\n\\nconst getPixelFormatChannelsForRgbaReadback = (format) => {\\n\\tswitch (format) {\\n\\t\\tcase PIXELFORMAT_R8:\\n\\t\\t\\treturn 1;\\n\\t\\tcase PIXELFORMAT_RG8:\\n\\t\\t\\treturn 2;\\n\\t\\tdefault:\\n\\t\\t\\treturn 0;\\n\\t}\\n};\\nconst invalidateAttachments = [];\\nclass WebglGraphicsDevice extends GraphicsDevice {\\n\\tgl;\\n\\t_defaultFramebuffer = null;\\n\\t_defaultFramebufferChanged = false;\\n\\t_xrMsaaCopy = null;\\n\\tconstructor(canvas, options = {}) {\\n\\t\\tsuper(canvas, options);\\n\\t\\toptions = this.initOptions;\\n\\t\\tthis.updateClientRect();\\n\\t\\tthis.initTextureUnits();\\n\\t\\tthis.contextLost = false;\\n\\t\\tthis._contextLostHandler = (event) => {\\n\\t\\t\\tevent.preventDefault();\\n\\t\\t\\tthis.loseContext();\\n\\t\\t};\\n\\t\\tthis._contextRestoredHandler = () => {\\n\\t\\t\\tthis.restoreContext();\\n\\t\\t};\\n\\t\\tconst ua = typeof navigator !== \\\"undefined\\\" && navigator.userAgent;\\n\\t\\tthis.forceDisableMultisampling = ua && ua.includes(\\\"AppleWebKit\\\") && (ua.includes(\\\"15.4\\\") || ua.includes(\\\"15_4\\\"));\\n\\t\\tif (this.forceDisableMultisampling) {\\n\\t\\t\\toptions.antialias = false;\\n\\t\\t}\\n\\t\\tif (platform.browserName === \\\"firefox\\\") {\\n\\t\\t\\tconst ua2 = typeof navigator !== \\\"undefined\\\" ? navigator.userAgent : \\\"\\\";\\n\\t\\t\\tconst match = ua2.match(/Firefox\\\\/(\\\\d+(\\\\.\\\\d+)*)/);\\n\\t\\t\\tconst firefoxVersion = match ? match[1] : null;\\n\\t\\t\\tif (firefoxVersion) {\\n\\t\\t\\t\\tconst version = parseFloat(firefoxVersion);\\n\\t\\t\\t\\tconst disableAntialias = platform.name === \\\"windows\\\" && (version >= 120 || version === 115) || platform.name === \\\"android\\\" && version >= 132;\\n\\t\\t\\t\\tif (disableAntialias) {\\n\\t\\t\\t\\t\\toptions.antialias = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.backBufferAntialias = options.antialias ?? false;\\n\\t\\toptions.antialias = false;\\n\\t\\tconst gl = options.gl ?? canvas.getContext(\\\"webgl2\\\", options);\\n\\t\\tif (!gl) {\\n\\t\\t\\tthrow new Error(\\\"WebGL not supported\\\");\\n\\t\\t}\\n\\t\\tthis.gl = gl;\\n\\t\\tthis.isWebGL2 = true;\\n\\t\\tthis._deviceType = DEVICETYPE_WEBGL2;\\n\\t\\tthis.updateBackbufferFormat(null);\\n\\t\\tconst isChrome = platform.browserName === \\\"chrome\\\";\\n\\t\\tconst isSafari = platform.browserName === \\\"safari\\\";\\n\\t\\tconst isMac = platform.browser && navigator.appVersion.indexOf(\\\"Mac\\\") !== -1;\\n\\t\\tthis._tempEnableSafariTextureUnitWorkaround = isSafari;\\n\\t\\tthis._tempMacChromeBlitFramebufferWorkaround = isMac && isChrome && !options.alpha;\\n\\t\\tcanvas.addEventListener(\\\"webglcontextlost\\\", this._contextLostHandler, false);\\n\\t\\tcanvas.addEventListener(\\\"webglcontextrestored\\\", this._contextRestoredHandler, false);\\n\\t\\tthis.initializeExtensions();\\n\\t\\tthis.initializeCapabilities();\\n\\t\\tthis.initializeRenderState();\\n\\t\\tthis.initializeContextCaches();\\n\\t\\tthis.createBackbuffer(null);\\n\\t\\tthis.supportsImageBitmap = !isSafari && typeof ImageBitmap !== \\\"undefined\\\";\\n\\t\\tthis._samplerTypes = /* @__PURE__ */ new Set([\\n\\t\\t\\tgl.SAMPLER_2D,\\n\\t\\t\\tgl.SAMPLER_CUBE,\\n\\t\\t\\tgl.UNSIGNED_INT_SAMPLER_2D,\\n\\t\\t\\tgl.INT_SAMPLER_2D,\\n\\t\\t\\tgl.SAMPLER_2D_SHADOW,\\n\\t\\t\\tgl.SAMPLER_CUBE_SHADOW,\\n\\t\\t\\tgl.SAMPLER_3D,\\n\\t\\t\\tgl.INT_SAMPLER_3D,\\n\\t\\t\\tgl.UNSIGNED_INT_SAMPLER_3D,\\n\\t\\t\\tgl.SAMPLER_2D_ARRAY,\\n\\t\\t\\tgl.INT_SAMPLER_2D_ARRAY,\\n\\t\\t\\tgl.UNSIGNED_INT_SAMPLER_2D_ARRAY\\n\\t\\t]);\\n\\t\\tthis.glAddress = [\\n\\t\\t\\tgl.REPEAT,\\n\\t\\t\\tgl.CLAMP_TO_EDGE,\\n\\t\\t\\tgl.MIRRORED_REPEAT\\n\\t\\t];\\n\\t\\tthis.glBlendEquation = [\\n\\t\\t\\tgl.FUNC_ADD,\\n\\t\\t\\tgl.FUNC_SUBTRACT,\\n\\t\\t\\tgl.FUNC_REVERSE_SUBTRACT,\\n\\t\\t\\tgl.MIN,\\n\\t\\t\\tgl.MAX\\n\\t\\t];\\n\\t\\tthis.glBlendFunctionColor = [\\n\\t\\t\\tgl.ZERO,\\n\\t\\t\\tgl.ONE,\\n\\t\\t\\tgl.SRC_COLOR,\\n\\t\\t\\tgl.ONE_MINUS_SRC_COLOR,\\n\\t\\t\\tgl.DST_COLOR,\\n\\t\\t\\tgl.ONE_MINUS_DST_COLOR,\\n\\t\\t\\tgl.SRC_ALPHA,\\n\\t\\t\\tgl.SRC_ALPHA_SATURATE,\\n\\t\\t\\tgl.ONE_MINUS_SRC_ALPHA,\\n\\t\\t\\tgl.DST_ALPHA,\\n\\t\\t\\tgl.ONE_MINUS_DST_ALPHA,\\n\\t\\t\\tgl.CONSTANT_COLOR,\\n\\t\\t\\tgl.ONE_MINUS_CONSTANT_COLOR\\n\\t\\t];\\n\\t\\tthis.glBlendFunctionAlpha = [\\n\\t\\t\\tgl.ZERO,\\n\\t\\t\\tgl.ONE,\\n\\t\\t\\tgl.SRC_COLOR,\\n\\t\\t\\tgl.ONE_MINUS_SRC_COLOR,\\n\\t\\t\\tgl.DST_COLOR,\\n\\t\\t\\tgl.ONE_MINUS_DST_COLOR,\\n\\t\\t\\tgl.SRC_ALPHA,\\n\\t\\t\\tgl.SRC_ALPHA_SATURATE,\\n\\t\\t\\tgl.ONE_MINUS_SRC_ALPHA,\\n\\t\\t\\tgl.DST_ALPHA,\\n\\t\\t\\tgl.ONE_MINUS_DST_ALPHA,\\n\\t\\t\\tgl.CONSTANT_ALPHA,\\n\\t\\t\\tgl.ONE_MINUS_CONSTANT_ALPHA\\n\\t\\t];\\n\\t\\tthis.glComparison = [\\n\\t\\t\\tgl.NEVER,\\n\\t\\t\\tgl.LESS,\\n\\t\\t\\tgl.EQUAL,\\n\\t\\t\\tgl.LEQUAL,\\n\\t\\t\\tgl.GREATER,\\n\\t\\t\\tgl.NOTEQUAL,\\n\\t\\t\\tgl.GEQUAL,\\n\\t\\t\\tgl.ALWAYS\\n\\t\\t];\\n\\t\\tthis.glStencilOp = [\\n\\t\\t\\tgl.KEEP,\\n\\t\\t\\tgl.ZERO,\\n\\t\\t\\tgl.REPLACE,\\n\\t\\t\\tgl.INCR,\\n\\t\\t\\tgl.INCR_WRAP,\\n\\t\\t\\tgl.DECR,\\n\\t\\t\\tgl.DECR_WRAP,\\n\\t\\t\\tgl.INVERT\\n\\t\\t];\\n\\t\\tthis.glClearFlag = [\\n\\t\\t\\t0,\\n\\t\\t\\tgl.COLOR_BUFFER_BIT,\\n\\t\\t\\tgl.DEPTH_BUFFER_BIT,\\n\\t\\t\\tgl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT,\\n\\t\\t\\tgl.STENCIL_BUFFER_BIT,\\n\\t\\t\\tgl.STENCIL_BUFFER_BIT | gl.COLOR_BUFFER_BIT,\\n\\t\\t\\tgl.STENCIL_BUFFER_BIT | gl.DEPTH_BUFFER_BIT,\\n\\t\\t\\tgl.STENCIL_BUFFER_BIT | gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT\\n\\t\\t];\\n\\t\\tthis.glCull = [\\n\\t\\t\\t0,\\n\\t\\t\\tgl.BACK,\\n\\t\\t\\tgl.FRONT,\\n\\t\\t\\tgl.FRONT_AND_BACK\\n\\t\\t];\\n\\t\\tthis.glFrontFace = [\\n\\t\\t\\tgl.CCW,\\n\\t\\t\\tgl.CW\\n\\t\\t];\\n\\t\\tthis.glFilter = [\\n\\t\\t\\tgl.NEAREST,\\n\\t\\t\\tgl.LINEAR,\\n\\t\\t\\tgl.NEAREST_MIPMAP_NEAREST,\\n\\t\\t\\tgl.NEAREST_MIPMAP_LINEAR,\\n\\t\\t\\tgl.LINEAR_MIPMAP_NEAREST,\\n\\t\\t\\tgl.LINEAR_MIPMAP_LINEAR\\n\\t\\t];\\n\\t\\tthis.glPrimitive = [\\n\\t\\t\\tgl.POINTS,\\n\\t\\t\\tgl.LINES,\\n\\t\\t\\tgl.LINE_LOOP,\\n\\t\\t\\tgl.LINE_STRIP,\\n\\t\\t\\tgl.TRIANGLES,\\n\\t\\t\\tgl.TRIANGLE_STRIP,\\n\\t\\t\\tgl.TRIANGLE_FAN\\n\\t\\t];\\n\\t\\tthis.glType = [\\n\\t\\t\\tgl.BYTE,\\n\\t\\t\\tgl.UNSIGNED_BYTE,\\n\\t\\t\\tgl.SHORT,\\n\\t\\t\\tgl.UNSIGNED_SHORT,\\n\\t\\t\\tgl.INT,\\n\\t\\t\\tgl.UNSIGNED_INT,\\n\\t\\t\\tgl.FLOAT,\\n\\t\\t\\tgl.HALF_FLOAT\\n\\t\\t];\\n\\t\\tthis.pcUniformType = {};\\n\\t\\tthis.pcUniformType[gl.BOOL] = UNIFORMTYPE_BOOL;\\n\\t\\tthis.pcUniformType[gl.INT] = UNIFORMTYPE_INT;\\n\\t\\tthis.pcUniformType[gl.FLOAT] = UNIFORMTYPE_FLOAT;\\n\\t\\tthis.pcUniformType[gl.FLOAT_VEC2] = UNIFORMTYPE_VEC2;\\n\\t\\tthis.pcUniformType[gl.FLOAT_VEC3] = UNIFORMTYPE_VEC3;\\n\\t\\tthis.pcUniformType[gl.FLOAT_VEC4] = UNIFORMTYPE_VEC4;\\n\\t\\tthis.pcUniformType[gl.INT_VEC2] = UNIFORMTYPE_IVEC2;\\n\\t\\tthis.pcUniformType[gl.INT_VEC3] = UNIFORMTYPE_IVEC3;\\n\\t\\tthis.pcUniformType[gl.INT_VEC4] = UNIFORMTYPE_IVEC4;\\n\\t\\tthis.pcUniformType[gl.BOOL_VEC2] = UNIFORMTYPE_BVEC2;\\n\\t\\tthis.pcUniformType[gl.BOOL_VEC3] = UNIFORMTYPE_BVEC3;\\n\\t\\tthis.pcUniformType[gl.BOOL_VEC4] = UNIFORMTYPE_BVEC4;\\n\\t\\tthis.pcUniformType[gl.FLOAT_MAT2] = UNIFORMTYPE_MAT2;\\n\\t\\tthis.pcUniformType[gl.FLOAT_MAT3] = UNIFORMTYPE_MAT3;\\n\\t\\tthis.pcUniformType[gl.FLOAT_MAT4] = UNIFORMTYPE_MAT4;\\n\\t\\tthis.pcUniformType[gl.SAMPLER_2D] = UNIFORMTYPE_TEXTURE2D;\\n\\t\\tthis.pcUniformType[gl.SAMPLER_CUBE] = UNIFORMTYPE_TEXTURECUBE;\\n\\t\\tthis.pcUniformType[gl.UNSIGNED_INT] = UNIFORMTYPE_UINT;\\n\\t\\tthis.pcUniformType[gl.UNSIGNED_INT_VEC2] = UNIFORMTYPE_UVEC2;\\n\\t\\tthis.pcUniformType[gl.UNSIGNED_INT_VEC3] = UNIFORMTYPE_UVEC3;\\n\\t\\tthis.pcUniformType[gl.UNSIGNED_INT_VEC4] = UNIFORMTYPE_UVEC4;\\n\\t\\tthis.pcUniformType[gl.SAMPLER_2D_SHADOW] = UNIFORMTYPE_TEXTURE2D_SHADOW;\\n\\t\\tthis.pcUniformType[gl.SAMPLER_CUBE_SHADOW] = UNIFORMTYPE_TEXTURECUBE_SHADOW;\\n\\t\\tthis.pcUniformType[gl.SAMPLER_2D_ARRAY] = UNIFORMTYPE_TEXTURE2D_ARRAY;\\n\\t\\tthis.pcUniformType[gl.SAMPLER_3D] = UNIFORMTYPE_TEXTURE3D;\\n\\t\\tthis.pcUniformType[gl.INT_SAMPLER_2D] = UNIFORMTYPE_ITEXTURE2D;\\n\\t\\tthis.pcUniformType[gl.UNSIGNED_INT_SAMPLER_2D] = UNIFORMTYPE_UTEXTURE2D;\\n\\t\\tthis.pcUniformType[gl.INT_SAMPLER_CUBE] = UNIFORMTYPE_ITEXTURECUBE;\\n\\t\\tthis.pcUniformType[gl.UNSIGNED_INT_SAMPLER_2D] = UNIFORMTYPE_UTEXTURECUBE;\\n\\t\\tthis.pcUniformType[gl.INT_SAMPLER_3D] = UNIFORMTYPE_ITEXTURE3D;\\n\\t\\tthis.pcUniformType[gl.UNSIGNED_INT_SAMPLER_3D] = UNIFORMTYPE_UTEXTURE3D;\\n\\t\\tthis.pcUniformType[gl.INT_SAMPLER_2D_ARRAY] = UNIFORMTYPE_ITEXTURE2D_ARRAY;\\n\\t\\tthis.pcUniformType[gl.UNSIGNED_INT_SAMPLER_2D_ARRAY] = UNIFORMTYPE_UTEXTURE2D_ARRAY;\\n\\t\\tthis.targetToSlot = {};\\n\\t\\tthis.targetToSlot[gl.TEXTURE_2D] = 0;\\n\\t\\tthis.targetToSlot[gl.TEXTURE_CUBE_MAP] = 1;\\n\\t\\tthis.targetToSlot[gl.TEXTURE_3D] = 2;\\n\\t\\tlet scopeX, scopeY, scopeZ, scopeW;\\n\\t\\tlet uniformValue;\\n\\t\\tthis.commitFunction = [];\\n\\t\\tthis.commitFunction[UNIFORMTYPE_BOOL] = function(uniform, value) {\\n\\t\\t\\tif (uniform.value !== value) {\\n\\t\\t\\t\\tgl.uniform1i(uniform.locationId, value);\\n\\t\\t\\t\\tuniform.value = value;\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_INT] = this.commitFunction[UNIFORMTYPE_BOOL];\\n\\t\\tthis.commitFunction[UNIFORMTYPE_FLOAT] = function(uniform, value) {\\n\\t\\t\\tif (uniform.value !== value) {\\n\\t\\t\\t\\tgl.uniform1f(uniform.locationId, value);\\n\\t\\t\\t\\tuniform.value = value;\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_VEC2] = function(uniform, value) {\\n\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\tscopeX = value[0];\\n\\t\\t\\tscopeY = value[1];\\n\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY) {\\n\\t\\t\\t\\tgl.uniform2fv(uniform.locationId, value);\\n\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_VEC3] = function(uniform, value) {\\n\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\tscopeX = value[0];\\n\\t\\t\\tscopeY = value[1];\\n\\t\\t\\tscopeZ = value[2];\\n\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY || uniformValue[2] !== scopeZ) {\\n\\t\\t\\t\\tgl.uniform3fv(uniform.locationId, value);\\n\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t\\tuniformValue[2] = scopeZ;\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_VEC4] = function(uniform, value) {\\n\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\tscopeX = value[0];\\n\\t\\t\\tscopeY = value[1];\\n\\t\\t\\tscopeZ = value[2];\\n\\t\\t\\tscopeW = value[3];\\n\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY || uniformValue[2] !== scopeZ || uniformValue[3] !== scopeW) {\\n\\t\\t\\t\\tgl.uniform4fv(uniform.locationId, value);\\n\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t\\tuniformValue[2] = scopeZ;\\n\\t\\t\\t\\tuniformValue[3] = scopeW;\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_IVEC2] = function(uniform, value) {\\n\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\tscopeX = value[0];\\n\\t\\t\\tscopeY = value[1];\\n\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY) {\\n\\t\\t\\t\\tgl.uniform2iv(uniform.locationId, value);\\n\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_BVEC2] = this.commitFunction[UNIFORMTYPE_IVEC2];\\n\\t\\tthis.commitFunction[UNIFORMTYPE_IVEC3] = function(uniform, value) {\\n\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\tscopeX = value[0];\\n\\t\\t\\tscopeY = value[1];\\n\\t\\t\\tscopeZ = value[2];\\n\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY || uniformValue[2] !== scopeZ) {\\n\\t\\t\\t\\tgl.uniform3iv(uniform.locationId, value);\\n\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t\\tuniformValue[2] = scopeZ;\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_BVEC3] = this.commitFunction[UNIFORMTYPE_IVEC3];\\n\\t\\tthis.commitFunction[UNIFORMTYPE_IVEC4] = function(uniform, value) {\\n\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\tscopeX = value[0];\\n\\t\\t\\tscopeY = value[1];\\n\\t\\t\\tscopeZ = value[2];\\n\\t\\t\\tscopeW = value[3];\\n\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY || uniformValue[2] !== scopeZ || uniformValue[3] !== scopeW) {\\n\\t\\t\\t\\tgl.uniform4iv(uniform.locationId, value);\\n\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t\\tuniformValue[2] = scopeZ;\\n\\t\\t\\t\\tuniformValue[3] = scopeW;\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_BVEC4] = this.commitFunction[UNIFORMTYPE_IVEC4];\\n\\t\\tthis.commitFunction[UNIFORMTYPE_MAT2] = function(uniform, value) {\\n\\t\\t\\tgl.uniformMatrix2fv(uniform.locationId, false, value);\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_MAT3] = function(uniform, value) {\\n\\t\\t\\tgl.uniformMatrix3fv(uniform.locationId, false, value);\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_MAT4] = function(uniform, value) {\\n\\t\\t\\tgl.uniformMatrix4fv(uniform.locationId, false, value);\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_FLOATARRAY] = function(uniform, value) {\\n\\t\\t\\tgl.uniform1fv(uniform.locationId, value);\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_VEC2ARRAY] = function(uniform, value) {\\n\\t\\t\\tgl.uniform2fv(uniform.locationId, value);\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_VEC3ARRAY] = function(uniform, value) {\\n\\t\\t\\tgl.uniform3fv(uniform.locationId, value);\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_VEC4ARRAY] = function(uniform, value) {\\n\\t\\t\\tgl.uniform4fv(uniform.locationId, value);\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_UINT] = function(uniform, value) {\\n\\t\\t\\tif (uniform.value !== value) {\\n\\t\\t\\t\\tgl.uniform1ui(uniform.locationId, value);\\n\\t\\t\\t\\tuniform.value = value;\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_UVEC2] = function(uniform, value) {\\n\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\tscopeX = value[0];\\n\\t\\t\\tscopeY = value[1];\\n\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY) {\\n\\t\\t\\t\\tgl.uniform2uiv(uniform.locationId, value);\\n\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_UVEC3] = function(uniform, value) {\\n\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\tscopeX = value[0];\\n\\t\\t\\tscopeY = value[1];\\n\\t\\t\\tscopeZ = value[2];\\n\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY || uniformValue[2] !== scopeZ) {\\n\\t\\t\\t\\tgl.uniform3uiv(uniform.locationId, value);\\n\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t\\tuniformValue[2] = scopeZ;\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_UVEC4] = function(uniform, value) {\\n\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\tscopeX = value[0];\\n\\t\\t\\tscopeY = value[1];\\n\\t\\t\\tscopeZ = value[2];\\n\\t\\t\\tscopeW = value[3];\\n\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY || uniformValue[2] !== scopeZ || uniformValue[3] !== scopeW) {\\n\\t\\t\\t\\tgl.uniform4uiv(uniform.locationId, value);\\n\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t\\tuniformValue[2] = scopeZ;\\n\\t\\t\\t\\tuniformValue[3] = scopeW;\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_INTARRAY] = function(uniform, value) {\\n\\t\\t\\tgl.uniform1iv(uniform.locationId, value);\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_UINTARRAY] = function(uniform, value) {\\n\\t\\t\\tgl.uniform1uiv(uniform.locationId, value);\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_BOOLARRAY] = this.commitFunction[UNIFORMTYPE_INTARRAY];\\n\\t\\tthis.commitFunction[UNIFORMTYPE_IVEC2ARRAY] = function(uniform, value) {\\n\\t\\t\\tgl.uniform2iv(uniform.locationId, value);\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_UVEC2ARRAY] = function(uniform, value) {\\n\\t\\t\\tgl.uniform2uiv(uniform.locationId, value);\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_BVEC2ARRAY] = this.commitFunction[UNIFORMTYPE_IVEC2ARRAY];\\n\\t\\tthis.commitFunction[UNIFORMTYPE_IVEC3ARRAY] = function(uniform, value) {\\n\\t\\t\\tgl.uniform3iv(uniform.locationId, value);\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_UVEC3ARRAY] = function(uniform, value) {\\n\\t\\t\\tgl.uniform3uiv(uniform.locationId, value);\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_BVEC3ARRAY] = this.commitFunction[UNIFORMTYPE_IVEC3ARRAY];\\n\\t\\tthis.commitFunction[UNIFORMTYPE_IVEC4ARRAY] = function(uniform, value) {\\n\\t\\t\\tgl.uniform4iv(uniform.locationId, value);\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_UVEC4ARRAY] = function(uniform, value) {\\n\\t\\t\\tgl.uniform4uiv(uniform.locationId, value);\\n\\t\\t};\\n\\t\\tthis.commitFunction[UNIFORMTYPE_BVEC4ARRAY] = this.commitFunction[UNIFORMTYPE_IVEC4ARRAY];\\n\\t\\tthis.commitFunction[UNIFORMTYPE_MAT4ARRAY] = function(uniform, value) {\\n\\t\\t\\tgl.uniformMatrix4fv(uniform.locationId, false, value);\\n\\t\\t};\\n\\t\\tthis.constantTexSource = this.scope.resolve(\\\"source\\\");\\n\\t\\tthis.postInit();\\n\\t}\\n\\tpostInit() {\\n\\t\\tsuper.postInit();\\n\\t\\tthis.gpuProfiler = new WebglGpuProfiler(this);\\n\\t}\\n\\tdestroy() {\\n\\t\\tsuper.destroy();\\n\\t\\tconst gl = this.gl;\\n\\t\\tif (this.feedback) {\\n\\t\\t\\tgl.deleteTransformFeedback(this.feedback);\\n\\t\\t}\\n\\t\\tthis.clearVertexArrayObjectCache();\\n\\t\\tthis._xrMsaaCopy?.destroy();\\n\\t\\tthis._xrMsaaCopy = null;\\n\\t\\tthis.canvas.removeEventListener(\\\"webglcontextlost\\\", this._contextLostHandler, false);\\n\\t\\tthis.canvas.removeEventListener(\\\"webglcontextrestored\\\", this._contextRestoredHandler, false);\\n\\t\\tthis._contextLostHandler = null;\\n\\t\\tthis._contextRestoredHandler = null;\\n\\t\\tthis.gl = null;\\n\\t\\tsuper.postDestroy();\\n\\t}\\n\\tcreateBackbuffer(frameBuffer) {\\n\\t\\tthis.supportsStencil = this.initOptions.stencil;\\n\\t\\tthis.backBuffer = new RenderTarget({\\n\\t\\t\\tname: \\\"WebglFramebuffer\\\",\\n\\t\\t\\tgraphicsDevice: this,\\n\\t\\t\\tdepth: this.initOptions.depth,\\n\\t\\t\\tstencil: this.supportsStencil,\\n\\t\\t\\tsamples: this.samples\\n\\t\\t});\\n\\t\\tthis.backBuffer.impl.suppliedColorFramebuffer = frameBuffer;\\n\\t}\\n\\t// Update framebuffer format based on the current framebuffer, as this is use to create matching multi-sampled framebuffer\\n\\tupdateBackbufferFormat(framebuffer) {\\n\\t\\tconst gl = this.gl;\\n\\t\\tgl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\\n\\t\\tconst alphaBits = this.gl.getParameter(this.gl.ALPHA_BITS);\\n\\t\\tthis.backBufferFormat = alphaBits ? PIXELFORMAT_RGBA8 : PIXELFORMAT_RGB8;\\n\\t}\\n\\tupdateBackbuffer() {\\n\\t\\tconst resolutionChanged = this.canvas.width !== this.backBufferSize.x || this.canvas.height !== this.backBufferSize.y;\\n\\t\\tif (this._defaultFramebufferChanged || resolutionChanged) {\\n\\t\\t\\tif (this._defaultFramebufferChanged) {\\n\\t\\t\\t\\tthis.updateBackbufferFormat(this._defaultFramebuffer);\\n\\t\\t\\t}\\n\\t\\t\\tthis._defaultFramebufferChanged = false;\\n\\t\\t\\tthis.backBufferSize.set(this.canvas.width, this.canvas.height);\\n\\t\\t\\tthis.backBuffer.destroy();\\n\\t\\t\\tthis.createBackbuffer(this._defaultFramebuffer);\\n\\t\\t}\\n\\t}\\n\\t// provide webgl implementation for the vertex buffer\\n\\tcreateVertexBufferImpl(vertexBuffer, format) {\\n\\t\\treturn new WebglVertexBuffer();\\n\\t}\\n\\t// provide webgl implementation for the index buffer\\n\\tcreateIndexBufferImpl(indexBuffer) {\\n\\t\\treturn new WebglIndexBuffer(indexBuffer);\\n\\t}\\n\\tcreateShaderImpl(shader) {\\n\\t\\treturn new WebglShader(shader);\\n\\t}\\n\\tcreateDrawCommandImpl(drawCommands) {\\n\\t\\treturn new WebglDrawCommands(drawCommands.indexSizeBytes);\\n\\t}\\n\\tcreateTextureImpl(texture) {\\n\\t\\tthis.textures.add(texture);\\n\\t\\treturn new WebglTexture(texture);\\n\\t}\\n\\tcreateXrBridgeImpl(xrBridge) {\\n\\t\\treturn new WebglXrBridge(xrBridge);\\n\\t}\\n\\tcreateRenderTargetImpl(renderTarget) {\\n\\t\\treturn new WebglRenderTarget();\\n\\t}\\n\\tcreateUploadStreamImpl(uploadStream) {\\n\\t\\treturn new WebglUploadStream(uploadStream);\\n\\t}\\n\\tgetPrecision() {\\n\\t\\tconst gl = this.gl;\\n\\t\\tlet precision = \\\"highp\\\";\\n\\t\\tif (gl.getShaderPrecisionFormat) {\\n\\t\\t\\tconst vertexShaderPrecisionHighpFloat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT);\\n\\t\\t\\tconst vertexShaderPrecisionMediumpFloat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT);\\n\\t\\t\\tconst fragmentShaderPrecisionHighpFloat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);\\n\\t\\t\\tconst fragmentShaderPrecisionMediumpFloat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT);\\n\\t\\t\\tif (vertexShaderPrecisionHighpFloat && vertexShaderPrecisionMediumpFloat && fragmentShaderPrecisionHighpFloat && fragmentShaderPrecisionMediumpFloat) {\\n\\t\\t\\t\\tconst highpAvailable = vertexShaderPrecisionHighpFloat.precision > 0 && fragmentShaderPrecisionHighpFloat.precision > 0;\\n\\t\\t\\t\\tconst mediumpAvailable = vertexShaderPrecisionMediumpFloat.precision > 0 && fragmentShaderPrecisionMediumpFloat.precision > 0;\\n\\t\\t\\t\\tif (!highpAvailable) {\\n\\t\\t\\t\\t\\tif (mediumpAvailable) {\\n\\t\\t\\t\\t\\t\\tprecision = \\\"mediump\\\";\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tprecision = \\\"lowp\\\";\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn precision;\\n\\t}\\n\\tgetExtension() {\\n\\t\\tfor (let i = 0; i < arguments.length; i++) {\\n\\t\\t\\tif (this.supportedExtensions.indexOf(arguments[i]) !== -1) {\\n\\t\\t\\t\\treturn this.gl.getExtension(arguments[i]);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn null;\\n\\t}\\n\\tget extDisjointTimerQuery() {\\n\\t\\tif (!this._extDisjointTimerQuery) {\\n\\t\\t\\tthis._extDisjointTimerQuery = this.getExtension(\\\"EXT_disjoint_timer_query_webgl2\\\", \\\"EXT_disjoint_timer_query\\\");\\n\\t\\t}\\n\\t\\treturn this._extDisjointTimerQuery;\\n\\t}\\n\\tinitializeExtensions() {\\n\\t\\tconst gl = this.gl;\\n\\t\\tthis.supportedExtensions = gl.getSupportedExtensions() ?? [];\\n\\t\\tthis._extDisjointTimerQuery = null;\\n\\t\\tthis.textureRG11B10Renderable = true;\\n\\t\\tthis.extColorBufferFloat = this.getExtension(\\\"EXT_color_buffer_float\\\");\\n\\t\\tthis.textureFloatRenderable = !!this.extColorBufferFloat;\\n\\t\\tthis.extColorBufferHalfFloat = this.getExtension(\\\"EXT_color_buffer_half_float\\\");\\n\\t\\tthis.textureHalfFloatRenderable = !!this.extColorBufferHalfFloat || !!this.extColorBufferFloat;\\n\\t\\tthis.extDebugRendererInfo = this.getExtension(\\\"WEBGL_debug_renderer_info\\\");\\n\\t\\tthis.extTextureFloatLinear = this.getExtension(\\\"OES_texture_float_linear\\\");\\n\\t\\tthis.textureFloatFilterable = !!this.extTextureFloatLinear;\\n\\t\\tthis.extFloatBlend = this.getExtension(\\\"EXT_float_blend\\\");\\n\\t\\tthis.extTextureFilterAnisotropic = this.getExtension(\\\"EXT_texture_filter_anisotropic\\\", \\\"WEBKIT_EXT_texture_filter_anisotropic\\\");\\n\\t\\tthis.extParallelShaderCompile = this.getExtension(\\\"KHR_parallel_shader_compile\\\");\\n\\t\\tthis.extMultiDraw = this.getExtension(\\\"WEBGL_multi_draw\\\");\\n\\t\\tthis.supportsMultiDraw = !!this.extMultiDraw;\\n\\t\\tthis.extCompressedTextureETC1 = this.getExtension(\\\"WEBGL_compressed_texture_etc1\\\");\\n\\t\\tthis.extCompressedTextureETC = this.getExtension(\\\"WEBGL_compressed_texture_etc\\\");\\n\\t\\tthis.extCompressedTexturePVRTC = this.getExtension(\\\"WEBGL_compressed_texture_pvrtc\\\", \\\"WEBKIT_WEBGL_compressed_texture_pvrtc\\\");\\n\\t\\tthis.extCompressedTextureS3TC = this.getExtension(\\\"WEBGL_compressed_texture_s3tc\\\", \\\"WEBKIT_WEBGL_compressed_texture_s3tc\\\");\\n\\t\\tthis.extCompressedTextureS3TC_SRGB = this.getExtension(\\\"WEBGL_compressed_texture_s3tc_srgb\\\");\\n\\t\\tthis.extCompressedTextureATC = this.getExtension(\\\"WEBGL_compressed_texture_atc\\\");\\n\\t\\tthis.extCompressedTextureASTC = this.getExtension(\\\"WEBGL_compressed_texture_astc\\\");\\n\\t\\tthis.extTextureCompressionBPTC = this.getExtension(\\\"EXT_texture_compression_bptc\\\");\\n\\t\\tthis.supportsHtmlTextures = typeof gl.texElementImage2D === \\\"function\\\";\\n\\t}\\n\\tinitializeCapabilities() {\\n\\t\\tconst gl = this.gl;\\n\\t\\tlet ext;\\n\\t\\tconst userAgent = typeof navigator !== \\\"undefined\\\" ? navigator.userAgent : \\\"\\\";\\n\\t\\tthis.maxPrecision = this.precision = this.getPrecision();\\n\\t\\tconst contextAttribs = gl.getContextAttributes();\\n\\t\\tthis.supportsMsaa = contextAttribs?.antialias ?? false;\\n\\t\\tthis.supportsStencil = contextAttribs?.stencil ?? false;\\n\\t\\tthis.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);\\n\\t\\tthis.maxCubeMapSize = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE);\\n\\t\\tthis.maxRenderBufferSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE);\\n\\t\\tthis.maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);\\n\\t\\tthis.maxCombinedTextures = gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS);\\n\\t\\tthis.maxVertexTextures = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS);\\n\\t\\tthis.vertexUniformsCount = gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS);\\n\\t\\tthis.fragmentUniformsCount = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS);\\n\\t\\tthis.maxColorAttachments = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);\\n\\t\\tthis.maxVolumeSize = gl.getParameter(gl.MAX_3D_TEXTURE_SIZE);\\n\\t\\text = this.extDebugRendererInfo;\\n\\t\\tthis.unmaskedRenderer = ext ? gl.getParameter(ext.UNMASKED_RENDERER_WEBGL) : \\\"\\\";\\n\\t\\tthis.unmaskedVendor = ext ? gl.getParameter(ext.UNMASKED_VENDOR_WEBGL) : \\\"\\\";\\n\\t\\tconst maliRendererRegex = /\\\\bMali-G52+/;\\n\\t\\tconst samsungModelRegex = /SM-[a-zA-Z0-9]+/;\\n\\t\\tthis.supportsGpuParticles = !(this.unmaskedVendor === \\\"ARM\\\" && userAgent.match(samsungModelRegex)) && !this.unmaskedRenderer.match(maliRendererRegex);\\n\\t\\text = this.extTextureFilterAnisotropic;\\n\\t\\tthis.maxAnisotropy = ext ? gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 1;\\n\\t\\tconst antialiasSupported = !this.forceDisableMultisampling;\\n\\t\\tthis.maxSamples = antialiasSupported ? gl.getParameter(gl.MAX_SAMPLES) : 1;\\n\\t\\tthis.maxSamples = Math.min(this.maxSamples, 4);\\n\\t\\tthis.samples = antialiasSupported && this.backBufferAntialias ? this.maxSamples : 1;\\n\\t\\tthis.supportsAreaLights = !platform.android;\\n\\t\\tif (this.maxTextures <= 8) {\\n\\t\\t\\tthis.supportsAreaLights = false;\\n\\t\\t}\\n\\t\\tthis.initCapsDefines();\\n\\t}\\n\\tinitializeRenderState() {\\n\\t\\tsuper.initializeRenderState();\\n\\t\\tconst gl = this.gl;\\n\\t\\tgl.disable(gl.BLEND);\\n\\t\\tgl.blendFunc(gl.ONE, gl.ZERO);\\n\\t\\tgl.blendEquation(gl.FUNC_ADD);\\n\\t\\tgl.colorMask(true, true, true, true);\\n\\t\\tgl.blendColor(0, 0, 0, 0);\\n\\t\\tgl.enable(gl.CULL_FACE);\\n\\t\\tthis.cullFace = gl.BACK;\\n\\t\\tgl.cullFace(gl.BACK);\\n\\t\\tgl.enable(gl.DEPTH_TEST);\\n\\t\\tgl.depthFunc(gl.LEQUAL);\\n\\t\\tgl.depthMask(true);\\n\\t\\tthis.stencil = false;\\n\\t\\tgl.disable(gl.STENCIL_TEST);\\n\\t\\tthis.stencilFuncFront = this.stencilFuncBack = FUNC_ALWAYS;\\n\\t\\tthis.stencilRefFront = this.stencilRefBack = 0;\\n\\t\\tthis.stencilMaskFront = this.stencilMaskBack = 255;\\n\\t\\tgl.stencilFunc(gl.ALWAYS, 0, 255);\\n\\t\\tthis.stencilFailFront = this.stencilFailBack = STENCILOP_KEEP;\\n\\t\\tthis.stencilZfailFront = this.stencilZfailBack = STENCILOP_KEEP;\\n\\t\\tthis.stencilZpassFront = this.stencilZpassBack = STENCILOP_KEEP;\\n\\t\\tthis.stencilWriteMaskFront = 255;\\n\\t\\tthis.stencilWriteMaskBack = 255;\\n\\t\\tgl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);\\n\\t\\tgl.stencilMask(255);\\n\\t\\tthis.alphaToCoverage = false;\\n\\t\\tthis.raster = true;\\n\\t\\tgl.disable(gl.SAMPLE_ALPHA_TO_COVERAGE);\\n\\t\\tgl.disable(gl.RASTERIZER_DISCARD);\\n\\t\\tthis.depthBiasEnabled = false;\\n\\t\\tgl.disable(gl.POLYGON_OFFSET_FILL);\\n\\t\\tthis.clearDepth = 1;\\n\\t\\tgl.clearDepth(1);\\n\\t\\tthis.clearColor = new Color(0, 0, 0, 0);\\n\\t\\tgl.clearColor(0, 0, 0, 0);\\n\\t\\tthis.clearStencil = 0;\\n\\t\\tgl.clearStencil(0);\\n\\t\\tgl.hint(gl.FRAGMENT_SHADER_DERIVATIVE_HINT, gl.NICEST);\\n\\t\\tgl.enable(gl.SCISSOR_TEST);\\n\\t\\tgl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);\\n\\t\\tthis.unpackFlipY = false;\\n\\t\\tgl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\\n\\t\\tthis.unpackPremultiplyAlpha = false;\\n\\t\\tgl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\\n\\t\\tthis.unpackAlignment = 1;\\n\\t\\tgl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);\\n\\t}\\n\\tinitTextureUnits(count = 16) {\\n\\t\\tthis.textureUnits = [];\\n\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\tthis.textureUnits.push([null, null, null]);\\n\\t\\t}\\n\\t}\\n\\tinitializeContextCaches() {\\n\\t\\tsuper.initializeContextCaches();\\n\\t\\tthis._vaoMap = /* @__PURE__ */ new Map();\\n\\t\\tthis.boundVao = null;\\n\\t\\tthis.activeFramebuffer = null;\\n\\t\\tthis.feedback = null;\\n\\t\\tthis.transformFeedbackBuffer = null;\\n\\t\\tthis.textureUnit = 0;\\n\\t\\tthis.initTextureUnits(this.maxCombinedTextures);\\n\\t}\\n\\tloseContext() {\\n\\t\\tsuper.loseContext();\\n\\t\\tfor (const shader of this.shaders) {\\n\\t\\t\\tshader.loseContext();\\n\\t\\t}\\n\\t\\tthis.fire(\\\"devicelost\\\");\\n\\t}\\n\\trestoreContext() {\\n\\t\\tthis.initializeExtensions();\\n\\t\\tthis.initializeCapabilities();\\n\\t\\tsuper.restoreContext();\\n\\t\\tfor (const shader of this.shaders) {\\n\\t\\t\\tshader.restoreContext();\\n\\t\\t}\\n\\t\\tthis.fire(\\\"devicerestored\\\");\\n\\t}\\n\\tsetViewport(x, y, w, h) {\\n\\t\\tif (this.vx !== x || this.vy !== y || this.vw !== w || this.vh !== h) {\\n\\t\\t\\tthis.gl.viewport(x, y, w, h);\\n\\t\\t\\tthis.vx = x;\\n\\t\\t\\tthis.vy = y;\\n\\t\\t\\tthis.vw = w;\\n\\t\\t\\tthis.vh = h;\\n\\t\\t}\\n\\t}\\n\\tsetScissor(x, y, w, h) {\\n\\t\\tif (this.sx !== x || this.sy !== y || this.sw !== w || this.sh !== h) {\\n\\t\\t\\tthis.gl.scissor(x, y, w, h);\\n\\t\\t\\tthis.sx = x;\\n\\t\\t\\tthis.sy = y;\\n\\t\\t\\tthis.sw = w;\\n\\t\\t\\tthis.sh = h;\\n\\t\\t}\\n\\t}\\n\\tsetFramebuffer(fb) {\\n\\t\\tif (this.activeFramebuffer !== fb) {\\n\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\tgl.bindFramebuffer(gl.FRAMEBUFFER, fb);\\n\\t\\t\\tthis.activeFramebuffer = fb;\\n\\t\\t}\\n\\t}\\n\\tresolveMsaaColorToXrFramebufferViaQuads(msaaReadFbo, xrDrawFbo, width, height) {\\n\\t\\tthis._xrMsaaCopy ?? (this._xrMsaaCopy = new WebglXrMsaaCopy(this));\\n\\t\\tthis._xrMsaaCopy.copy(msaaReadFbo, xrDrawFbo, width, height);\\n\\t}\\n\\tcopyRenderTarget(source, dest, color, depth) {\\n\\t\\tconst gl = this.gl;\\n\\t\\tif (source === this.backBuffer) {\\n\\t\\t\\tsource = null;\\n\\t\\t}\\n\\t\\tif (color) {\\n\\t\\t\\tif (!dest) {\\n\\t\\t\\t\\tif (!source._colorBuffer) {\\n\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else if (source) {\\n\\t\\t\\t\\tif (!source._colorBuffer || !dest._colorBuffer) {\\n\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (source._colorBuffer._format !== dest._colorBuffer._format) {\\n\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (depth && source) {\\n\\t\\t\\tif (!source._depth) {\\n\\t\\t\\t\\tif (!source._depthBuffer || !dest._depthBuffer) {\\n\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (source._depthBuffer._format !== dest._depthBuffer._format) {\\n\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst prevRt = this.renderTarget;\\n\\t\\tthis.renderTarget = dest;\\n\\t\\tthis.updateBegin();\\n\\t\\tconst src = source ? source.impl._glFrameBuffer : this.backBuffer?.impl._glFrameBuffer;\\n\\t\\tconst dst = dest ? dest.impl._glFrameBuffer : this.backBuffer?.impl._glFrameBuffer;\\n\\t\\tgl.bindFramebuffer(gl.READ_FRAMEBUFFER, src);\\n\\t\\tgl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dst);\\n\\t\\tconst w = source ? source.width : dest ? dest.width : this.width;\\n\\t\\tconst h = source ? source.height : dest ? dest.height : this.height;\\n\\t\\tgl.blitFramebuffer(\\n\\t\\t\\t0,\\n\\t\\t\\t0,\\n\\t\\t\\tw,\\n\\t\\t\\th,\\n\\t\\t\\t0,\\n\\t\\t\\t0,\\n\\t\\t\\tw,\\n\\t\\t\\th,\\n\\t\\t\\t(color ? gl.COLOR_BUFFER_BIT : 0) | (depth ? gl.DEPTH_BUFFER_BIT : 0),\\n\\t\\t\\tgl.NEAREST\\n\\t\\t);\\n\\t\\tthis.renderTarget = prevRt;\\n\\t\\tgl.bindFramebuffer(gl.FRAMEBUFFER, prevRt ? prevRt.impl._glFrameBuffer : null);\\n\\t\\treturn true;\\n\\t}\\n\\tframeStart() {\\n\\t\\tsuper.frameStart();\\n\\t\\tthis.updateBackbuffer();\\n\\t\\tthis.gpuProfiler.frameStart();\\n\\t}\\n\\tframeEnd() {\\n\\t\\tsuper.frameEnd();\\n\\t\\tthis.gpuProfiler.frameEnd();\\n\\t\\tthis.gpuProfiler.request();\\n\\t}\\n\\tstartRenderPass(renderPass) {\\n\\t\\tconst rt = renderPass.renderTarget ?? this.backBuffer;\\n\\t\\tthis.renderTarget = rt;\\n\\t\\tthis.updateBegin();\\n\\t\\tconst { width, height } = rt;\\n\\t\\tthis.setViewport(0, 0, width, height);\\n\\t\\tthis.setScissor(0, 0, width, height);\\n\\t\\tconst colorOps = renderPass.colorOps;\\n\\t\\tconst depthStencilOps = renderPass.depthStencilOps;\\n\\t\\tif (colorOps?.clear || depthStencilOps.clearDepth || depthStencilOps.clearStencil) {\\n\\t\\t\\tlet clearFlags = 0;\\n\\t\\t\\tconst clearOptions = {};\\n\\t\\t\\tif (colorOps?.clear) {\\n\\t\\t\\t\\tclearFlags |= CLEARFLAG_COLOR;\\n\\t\\t\\t\\tclearOptions.color = [colorOps.clearValue.r, colorOps.clearValue.g, colorOps.clearValue.b, colorOps.clearValue.a];\\n\\t\\t\\t}\\n\\t\\t\\tif (depthStencilOps.clearDepth) {\\n\\t\\t\\t\\tclearFlags |= CLEARFLAG_DEPTH;\\n\\t\\t\\t\\tclearOptions.depth = depthStencilOps.clearDepthValue;\\n\\t\\t\\t}\\n\\t\\t\\tif (depthStencilOps.clearStencil) {\\n\\t\\t\\t\\tclearFlags |= CLEARFLAG_STENCIL;\\n\\t\\t\\t\\tclearOptions.stencil = depthStencilOps.clearStencilValue;\\n\\t\\t\\t}\\n\\t\\t\\tclearOptions.flags = clearFlags;\\n\\t\\t\\tthis.clear(clearOptions);\\n\\t\\t}\\n\\t\\tthis.insideRenderPass = true;\\n\\t}\\n\\tendRenderPass(renderPass) {\\n\\t\\tthis.unbindVertexArray();\\n\\t\\tconst target = this.renderTarget;\\n\\t\\tconst colorBufferCount = renderPass.colorArrayOps.length;\\n\\t\\tif (target) {\\n\\t\\t\\tinvalidateAttachments.length = 0;\\n\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\tfor (let i = 0; i < colorBufferCount; i++) {\\n\\t\\t\\t\\tconst colorOps = renderPass.colorArrayOps[i];\\n\\t\\t\\t\\tif (!(colorOps.store || colorOps.resolve)) {\\n\\t\\t\\t\\t\\tinvalidateAttachments.push(gl.COLOR_ATTACHMENT0 + i);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (target !== this.backBuffer) {\\n\\t\\t\\t\\tif (!renderPass.depthStencilOps.storeDepth) {\\n\\t\\t\\t\\t\\tinvalidateAttachments.push(gl.DEPTH_ATTACHMENT);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!renderPass.depthStencilOps.storeStencil) {\\n\\t\\t\\t\\t\\tinvalidateAttachments.push(gl.STENCIL_ATTACHMENT);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (invalidateAttachments.length > 0) {\\n\\t\\t\\t\\tif (renderPass.fullSizeClearRect) {\\n\\t\\t\\t\\t\\tgl.invalidateFramebuffer(gl.DRAW_FRAMEBUFFER, invalidateAttachments);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (colorBufferCount && renderPass.colorOps?.resolve) {\\n\\t\\t\\t\\tif (renderPass.samples > 1 && target.autoResolve) {\\n\\t\\t\\t\\t\\ttarget.resolve(true, false);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (target.depthBuffer && renderPass.depthStencilOps.resolveDepth) {\\n\\t\\t\\t\\tif (renderPass.samples > 1 && target.autoResolve) {\\n\\t\\t\\t\\t\\ttarget.resolve(false, true);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tfor (let i = 0; i < colorBufferCount; i++) {\\n\\t\\t\\t\\tconst colorOps = renderPass.colorArrayOps[i];\\n\\t\\t\\t\\tif (colorOps.genMipmaps) {\\n\\t\\t\\t\\t\\tconst colorBuffer = target._colorBuffers[i];\\n\\t\\t\\t\\t\\tif (colorBuffer && colorBuffer.impl._glTexture && colorBuffer.mipmaps) {\\n\\t\\t\\t\\t\\t\\tthis.activeTexture(this.maxCombinedTextures - 1);\\n\\t\\t\\t\\t\\t\\tthis.bindTexture(colorBuffer);\\n\\t\\t\\t\\t\\t\\tthis.gl.generateMipmap(colorBuffer.impl._glTarget);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.insideRenderPass = false;\\n\\t}\\n\\tset defaultFramebuffer(value) {\\n\\t\\tif (this._defaultFramebuffer !== value) {\\n\\t\\t\\tthis._defaultFramebuffer = value;\\n\\t\\t\\tthis._defaultFramebufferChanged = true;\\n\\t\\t}\\n\\t}\\n\\tget defaultFramebuffer() {\\n\\t\\treturn this._defaultFramebuffer;\\n\\t}\\n\\tupdateBegin() {\\n\\t\\tthis.boundVao = null;\\n\\t\\tif (this._tempEnableSafariTextureUnitWorkaround) {\\n\\t\\t\\tfor (let unit = 0; unit < this.textureUnits.length; ++unit) {\\n\\t\\t\\t\\tfor (let slot = 0; slot < 3; ++slot) {\\n\\t\\t\\t\\t\\tthis.textureUnits[unit][slot] = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst target = this.renderTarget ?? this.backBuffer;\\n\\t\\tconst targetImpl = target.impl;\\n\\t\\tif (!targetImpl.initialized) {\\n\\t\\t\\tthis.initRenderTarget(target);\\n\\t\\t}\\n\\t\\tthis.setFramebuffer(targetImpl._glFrameBuffer);\\n\\t}\\n\\tupdateEnd() {\\n\\t\\tthis.unbindVertexArray();\\n\\t\\tconst target = this.renderTarget;\\n\\t\\tif (target && target !== this.backBuffer) {\\n\\t\\t\\tif (target._samples > 1 && target.autoResolve) {\\n\\t\\t\\t\\ttarget.resolve();\\n\\t\\t\\t}\\n\\t\\t\\tconst colorBuffer = target._colorBuffer;\\n\\t\\t\\tif (colorBuffer && colorBuffer.impl._glTexture && colorBuffer.mipmaps) {\\n\\t\\t\\t\\tthis.activeTexture(this.maxCombinedTextures - 1);\\n\\t\\t\\t\\tthis.bindTexture(colorBuffer);\\n\\t\\t\\t\\tthis.gl.generateMipmap(colorBuffer.impl._glTarget);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tsetUnpackFlipY(flipY) {\\n\\t\\tif (this.unpackFlipY !== flipY) {\\n\\t\\t\\tthis.unpackFlipY = flipY;\\n\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\tgl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);\\n\\t\\t}\\n\\t}\\n\\tsetUnpackPremultiplyAlpha(premultiplyAlpha) {\\n\\t\\tif (this.unpackPremultiplyAlpha !== premultiplyAlpha) {\\n\\t\\t\\tthis.unpackPremultiplyAlpha = premultiplyAlpha;\\n\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\tgl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);\\n\\t\\t}\\n\\t}\\n\\tsetUnpackAlignment(alignment) {\\n\\t\\tif (this.unpackAlignment !== alignment) {\\n\\t\\t\\tthis.unpackAlignment = alignment;\\n\\t\\t\\tthis.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT, alignment);\\n\\t\\t}\\n\\t}\\n\\tactiveTexture(textureUnit) {\\n\\t\\tif (this.textureUnit !== textureUnit) {\\n\\t\\t\\tthis.gl.activeTexture(this.gl.TEXTURE0 + textureUnit);\\n\\t\\t\\tthis.textureUnit = textureUnit;\\n\\t\\t}\\n\\t}\\n\\tbindTexture(texture) {\\n\\t\\tconst impl = texture.impl;\\n\\t\\tconst textureTarget = impl._glTarget;\\n\\t\\tconst textureObject = impl._glTexture;\\n\\t\\tconst textureUnit = this.textureUnit;\\n\\t\\tconst slot = this.targetToSlot[textureTarget];\\n\\t\\tif (this.textureUnits[textureUnit][slot] !== textureObject) {\\n\\t\\t\\tthis.gl.bindTexture(textureTarget, textureObject);\\n\\t\\t\\tthis.textureUnits[textureUnit][slot] = textureObject;\\n\\t\\t}\\n\\t}\\n\\tbindTextureOnUnit(texture, textureUnit) {\\n\\t\\tconst impl = texture.impl;\\n\\t\\tconst textureTarget = impl._glTarget;\\n\\t\\tconst textureObject = impl._glTexture;\\n\\t\\tconst slot = this.targetToSlot[textureTarget];\\n\\t\\tif (this.textureUnits[textureUnit][slot] !== textureObject) {\\n\\t\\t\\tthis.activeTexture(textureUnit);\\n\\t\\t\\tthis.gl.bindTexture(textureTarget, textureObject);\\n\\t\\t\\tthis.textureUnits[textureUnit][slot] = textureObject;\\n\\t\\t}\\n\\t}\\n\\tsetTextureParameters(texture) {\\n\\t\\tconst gl = this.gl;\\n\\t\\tconst flags = texture.impl.dirtyParameterFlags;\\n\\t\\tconst target = texture.impl._glTarget;\\n\\t\\tif (flags & TEXPROPERTY_MIN_FILTER) {\\n\\t\\t\\tlet filter = texture._minFilter;\\n\\t\\t\\tif (!texture._mipmaps || texture._compressed && texture._levels.length === 1) {\\n\\t\\t\\t\\tif (filter === FILTER_NEAREST_MIPMAP_NEAREST || filter === FILTER_NEAREST_MIPMAP_LINEAR) {\\n\\t\\t\\t\\t\\tfilter = FILTER_NEAREST;\\n\\t\\t\\t\\t} else if (filter === FILTER_LINEAR_MIPMAP_NEAREST || filter === FILTER_LINEAR_MIPMAP_LINEAR) {\\n\\t\\t\\t\\t\\tfilter = FILTER_LINEAR;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tgl.texParameteri(target, gl.TEXTURE_MIN_FILTER, this.glFilter[filter]);\\n\\t\\t}\\n\\t\\tif (flags & TEXPROPERTY_MAG_FILTER) {\\n\\t\\t\\tgl.texParameteri(target, gl.TEXTURE_MAG_FILTER, this.glFilter[texture._magFilter]);\\n\\t\\t}\\n\\t\\tif (flags & TEXPROPERTY_ADDRESS_U) {\\n\\t\\t\\tgl.texParameteri(target, gl.TEXTURE_WRAP_S, this.glAddress[texture._addressU]);\\n\\t\\t}\\n\\t\\tif (flags & TEXPROPERTY_ADDRESS_V) {\\n\\t\\t\\tgl.texParameteri(target, gl.TEXTURE_WRAP_T, this.glAddress[texture._addressV]);\\n\\t\\t}\\n\\t\\tif (flags & TEXPROPERTY_ADDRESS_W) {\\n\\t\\t\\tgl.texParameteri(target, gl.TEXTURE_WRAP_R, this.glAddress[texture._addressW]);\\n\\t\\t}\\n\\t\\tif (flags & TEXPROPERTY_COMPARE_ON_READ) {\\n\\t\\t\\tgl.texParameteri(target, gl.TEXTURE_COMPARE_MODE, texture._compareOnRead ? gl.COMPARE_REF_TO_TEXTURE : gl.NONE);\\n\\t\\t}\\n\\t\\tif (flags & TEXPROPERTY_COMPARE_FUNC) {\\n\\t\\t\\tgl.texParameteri(target, gl.TEXTURE_COMPARE_FUNC, this.glComparison[texture._compareFunc]);\\n\\t\\t}\\n\\t\\tif (flags & TEXPROPERTY_ANISOTROPY) {\\n\\t\\t\\tconst ext = this.extTextureFilterAnisotropic;\\n\\t\\t\\tif (ext) {\\n\\t\\t\\t\\tgl.texParameterf(target, ext.TEXTURE_MAX_ANISOTROPY_EXT, math.clamp(Math.round(texture._anisotropy), 1, this.maxAnisotropy));\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tsetTexture(texture, textureUnit) {\\n\\t\\tconst impl = texture.impl;\\n\\t\\tif (!impl._glTexture) {\\n\\t\\t\\timpl.initialize(this, texture);\\n\\t\\t}\\n\\t\\tif (impl.dirtyParameterFlags > 0 || texture._needsUpload || texture._needsMipmapsUpload) {\\n\\t\\t\\tthis.activeTexture(textureUnit);\\n\\t\\t\\tthis.bindTexture(texture);\\n\\t\\t\\tif (impl.dirtyParameterFlags) {\\n\\t\\t\\t\\tthis.setTextureParameters(texture);\\n\\t\\t\\t\\timpl.dirtyParameterFlags = 0;\\n\\t\\t\\t}\\n\\t\\t\\tif (texture._needsUpload || texture._needsMipmapsUpload) {\\n\\t\\t\\t\\timpl.upload(this, texture);\\n\\t\\t\\t\\ttexture._needsUpload = false;\\n\\t\\t\\t\\ttexture._needsMipmapsUpload = false;\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis.bindTextureOnUnit(texture, textureUnit);\\n\\t\\t}\\n\\t}\\n\\t// function creates VertexArrayObject from list of vertex buffers\\n\\tcreateVertexArray(vertexBuffers) {\\n\\t\\tlet key, vao;\\n\\t\\tconst useCache = vertexBuffers.length > 1;\\n\\t\\tif (useCache) {\\n\\t\\t\\tkey = \\\"\\\";\\n\\t\\t\\tfor (let i = 0; i < vertexBuffers.length; i++) {\\n\\t\\t\\t\\tconst vertexBuffer = vertexBuffers[i];\\n\\t\\t\\t\\tkey += vertexBuffer.id + vertexBuffer.format.renderingHash;\\n\\t\\t\\t}\\n\\t\\t\\tvao = this._vaoMap.get(key);\\n\\t\\t}\\n\\t\\tif (!vao) {\\n\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\tvao = gl.createVertexArray();\\n\\t\\t\\tgl.bindVertexArray(vao);\\n\\t\\t\\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\\n\\t\\t\\tfor (let i = 0; i < vertexBuffers.length; i++) {\\n\\t\\t\\t\\tconst vertexBuffer = vertexBuffers[i];\\n\\t\\t\\t\\tgl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer.impl.bufferId);\\n\\t\\t\\t\\tconst elements = vertexBuffer.format.elements;\\n\\t\\t\\t\\tfor (let j = 0; j < elements.length; j++) {\\n\\t\\t\\t\\t\\tconst e = elements[j];\\n\\t\\t\\t\\t\\tconst loc = semanticToLocation[e.name];\\n\\t\\t\\t\\t\\tif (e.asInt) {\\n\\t\\t\\t\\t\\t\\tgl.vertexAttribIPointer(loc, e.numComponents, this.glType[e.dataType], e.stride, e.offset);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tgl.vertexAttribPointer(loc, e.numComponents, this.glType[e.dataType], e.normalize, e.stride, e.offset);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tgl.enableVertexAttribArray(loc);\\n\\t\\t\\t\\t\\tif (vertexBuffer.format.instancing) {\\n\\t\\t\\t\\t\\t\\tgl.vertexAttribDivisor(loc, 1);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tgl.bindVertexArray(null);\\n\\t\\t\\tgl.bindBuffer(gl.ARRAY_BUFFER, null);\\n\\t\\t\\tif (useCache) {\\n\\t\\t\\t\\tthis._vaoMap.set(key, vao);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn vao;\\n\\t}\\n\\tunbindVertexArray() {\\n\\t\\tif (this.boundVao) {\\n\\t\\t\\tthis.boundVao = null;\\n\\t\\t\\tthis.gl.bindVertexArray(null);\\n\\t\\t}\\n\\t}\\n\\tsetBuffers(indexBuffer) {\\n\\t\\tconst gl = this.gl;\\n\\t\\tlet vao;\\n\\t\\tif (this.vertexBuffers.length === 1) {\\n\\t\\t\\tconst vertexBuffer = this.vertexBuffers[0];\\n\\t\\t\\tif (!vertexBuffer.impl.vao) {\\n\\t\\t\\t\\tvertexBuffer.impl.vao = this.createVertexArray(this.vertexBuffers);\\n\\t\\t\\t}\\n\\t\\t\\tvao = vertexBuffer.impl.vao;\\n\\t\\t} else {\\n\\t\\t\\tvao = this.createVertexArray(this.vertexBuffers);\\n\\t\\t}\\n\\t\\tif (this.boundVao !== vao) {\\n\\t\\t\\tthis.boundVao = vao;\\n\\t\\t\\tgl.bindVertexArray(vao);\\n\\t\\t}\\n\\t\\tconst bufferId = indexBuffer ? indexBuffer.impl.bufferId : null;\\n\\t\\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferId);\\n\\t}\\n\\t_multiDrawLoopFallback(mode, primitive, indexBuffer, numInstances, drawCommands) {\\n\\t\\tconst gl = this.gl;\\n\\t\\tif (primitive.indexed) {\\n\\t\\t\\tconst format = indexBuffer.impl.glFormat;\\n\\t\\t\\tconst { glCounts, glOffsetsBytes, glInstanceCounts, count } = drawCommands.impl;\\n\\t\\t\\tif (numInstances > 0) {\\n\\t\\t\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\t\\t\\tgl.drawElementsInstanced(mode, glCounts[i], format, glOffsetsBytes[i], glInstanceCounts[i]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\t\\t\\tgl.drawElements(mode, glCounts[i], format, glOffsetsBytes[i]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tconst { glCounts, glOffsetsBytes, glInstanceCounts, count } = drawCommands.impl;\\n\\t\\t\\tif (numInstances > 0) {\\n\\t\\t\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\t\\t\\tgl.drawArraysInstanced(mode, glOffsetsBytes[i], glCounts[i], glInstanceCounts[i]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\t\\t\\tgl.drawArrays(mode, glOffsetsBytes[i], glCounts[i]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tdraw(primitive, indexBuffer, numInstances, drawCommands, first = true, last = true) {\\n\\t\\tconst shader = this.shader;\\n\\t\\tif (shader) {\\n\\t\\t\\tthis.activateShader();\\n\\t\\t\\tif (this.shaderValid) {\\n\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\tif (first) {\\n\\t\\t\\t\\t\\tthis.setBuffers(indexBuffer);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet textureUnit = 0;\\n\\t\\t\\t\\tconst samplers = shader.impl.samplers;\\n\\t\\t\\t\\tfor (let i = 0, len = samplers.length; i < len; i++) {\\n\\t\\t\\t\\t\\tconst sampler = samplers[i];\\n\\t\\t\\t\\t\\tlet samplerValue = sampler.scopeId.value;\\n\\t\\t\\t\\t\\tif (!samplerValue) {\\n\\t\\t\\t\\t\\t\\tconst samplerName = sampler.scopeId.name;\\n\\t\\t\\t\\t\\t\\tif (samplerName === \\\"uSceneDepthMap\\\") {\\n\\t\\t\\t\\t\\t\\t\\tsamplerValue = getBuiltInTexture(this, \\\"white\\\");\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (samplerName === \\\"uSceneColorMap\\\") {\\n\\t\\t\\t\\t\\t\\t\\tsamplerValue = getBuiltInTexture(this, \\\"pink\\\");\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!samplerValue) {\\n\\t\\t\\t\\t\\t\\t\\tsamplerValue = getBuiltInTexture(this, \\\"pink\\\");\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (samplerValue instanceof Texture) {\\n\\t\\t\\t\\t\\t\\tconst texture = samplerValue;\\n\\t\\t\\t\\t\\t\\tthis.setTexture(texture, textureUnit);\\n\\t\\t\\t\\t\\t\\tif (sampler.slot !== textureUnit) {\\n\\t\\t\\t\\t\\t\\t\\tgl.uniform1i(sampler.locationId, textureUnit);\\n\\t\\t\\t\\t\\t\\t\\tsampler.slot = textureUnit;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\ttextureUnit++;\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tsampler.array.length = 0;\\n\\t\\t\\t\\t\\t\\tconst numTextures = samplerValue.length;\\n\\t\\t\\t\\t\\t\\tfor (let j = 0; j < numTextures; j++) {\\n\\t\\t\\t\\t\\t\\t\\tconst texture = samplerValue[j];\\n\\t\\t\\t\\t\\t\\t\\tthis.setTexture(texture, textureUnit);\\n\\t\\t\\t\\t\\t\\t\\tsampler.array[j] = textureUnit;\\n\\t\\t\\t\\t\\t\\t\\ttextureUnit++;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tgl.uniform1iv(sampler.locationId, sampler.array);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst uniforms = shader.impl.uniforms;\\n\\t\\t\\t\\tfor (let i = 0, len = uniforms.length; i < len; i++) {\\n\\t\\t\\t\\t\\tconst uniform = uniforms[i];\\n\\t\\t\\t\\t\\tconst scopeId = uniform.scopeId;\\n\\t\\t\\t\\t\\tconst uniformVersion = uniform.version;\\n\\t\\t\\t\\t\\tconst programVersion = scopeId.versionObject.version;\\n\\t\\t\\t\\t\\tif (uniformVersion.globalId !== programVersion.globalId || uniformVersion.revision !== programVersion.revision) {\\n\\t\\t\\t\\t\\t\\tuniformVersion.globalId = programVersion.globalId;\\n\\t\\t\\t\\t\\t\\tuniformVersion.revision = programVersion.revision;\\n\\t\\t\\t\\t\\t\\tconst value = scopeId.value;\\n\\t\\t\\t\\t\\t\\tif (value !== null && value !== void 0) {\\n\\t\\t\\t\\t\\t\\t\\tthis.commitFunction[uniform.dataType](uniform, value);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.transformFeedbackBuffer) {\\n\\t\\t\\t\\t\\tgl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, this.transformFeedbackBuffer.impl.bufferId);\\n\\t\\t\\t\\t\\tgl.beginTransformFeedback(gl.POINTS);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst mode = this.glPrimitive[primitive.type];\\n\\t\\t\\t\\tconst count = primitive.count;\\n\\t\\t\\t\\tif (drawCommands) {\\n\\t\\t\\t\\t\\tif (this.extMultiDraw) {\\n\\t\\t\\t\\t\\t\\tconst impl = drawCommands.impl;\\n\\t\\t\\t\\t\\t\\tif (primitive.indexed) {\\n\\t\\t\\t\\t\\t\\t\\tconst format = indexBuffer.impl.glFormat;\\n\\t\\t\\t\\t\\t\\t\\tif (numInstances > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.extMultiDraw.multiDrawElementsInstancedWEBGL(mode, impl.glCounts, 0, format, impl.glOffsetsBytes, 0, impl.glInstanceCounts, 0, drawCommands.count);\\n\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.extMultiDraw.multiDrawElementsWEBGL(mode, impl.glCounts, 0, format, impl.glOffsetsBytes, 0, drawCommands.count);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tif (numInstances > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.extMultiDraw.multiDrawArraysInstancedWEBGL(mode, impl.glOffsetsBytes, 0, impl.glCounts, 0, impl.glInstanceCounts, 0, drawCommands.count);\\n\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.extMultiDraw.multiDrawArraysWEBGL(mode, impl.glOffsetsBytes, 0, impl.glCounts, 0, drawCommands.count);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._multiDrawLoopFallback(mode, primitive, indexBuffer, numInstances, drawCommands);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tif (primitive.indexed) {\\n\\t\\t\\t\\t\\t\\tconst format = indexBuffer.impl.glFormat;\\n\\t\\t\\t\\t\\t\\tconst offset = primitive.base * indexBuffer.bytesPerIndex;\\n\\t\\t\\t\\t\\t\\tif (numInstances > 0) {\\n\\t\\t\\t\\t\\t\\t\\tgl.drawElementsInstanced(mode, count, format, offset, numInstances);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tgl.drawElements(mode, count, format, offset);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst first2 = primitive.base;\\n\\t\\t\\t\\t\\t\\tif (numInstances > 0) {\\n\\t\\t\\t\\t\\t\\t\\tgl.drawArraysInstanced(mode, first2, count, numInstances);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tgl.drawArrays(mode, first2, count);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.transformFeedbackBuffer) {\\n\\t\\t\\t\\t\\tgl.endTransformFeedback();\\n\\t\\t\\t\\t\\tgl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._drawCallsPerFrame++;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (last) {\\n\\t\\t\\tthis.clearVertexBuffer();\\n\\t\\t}\\n\\t}\\n\\tclear(options) {\\n\\t\\tconst defaultOptions = this.defaultClearOptions;\\n\\t\\toptions = options || defaultOptions;\\n\\t\\tconst flags = options.flags ?? defaultOptions.flags;\\n\\t\\tif (flags !== 0) {\\n\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\tif (flags & CLEARFLAG_COLOR) {\\n\\t\\t\\t\\tconst color = options.color ?? defaultOptions.color;\\n\\t\\t\\t\\tconst r = color[0];\\n\\t\\t\\t\\tconst g = color[1];\\n\\t\\t\\t\\tconst b = color[2];\\n\\t\\t\\t\\tconst a = color[3];\\n\\t\\t\\t\\tconst c = this.clearColor;\\n\\t\\t\\t\\tif (r !== c.r || g !== c.g || b !== c.b || a !== c.a) {\\n\\t\\t\\t\\t\\tthis.gl.clearColor(r, g, b, a);\\n\\t\\t\\t\\t\\tthis.clearColor.set(r, g, b, a);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.setBlendState(BlendState.NOBLEND);\\n\\t\\t\\t}\\n\\t\\t\\tif (flags & CLEARFLAG_DEPTH) {\\n\\t\\t\\t\\tconst depth = options.depth ?? defaultOptions.depth;\\n\\t\\t\\t\\tif (depth !== this.clearDepth) {\\n\\t\\t\\t\\t\\tthis.gl.clearDepth(depth);\\n\\t\\t\\t\\t\\tthis.clearDepth = depth;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.setDepthState(DepthState.WRITEDEPTH);\\n\\t\\t\\t}\\n\\t\\t\\tif (flags & CLEARFLAG_STENCIL) {\\n\\t\\t\\t\\tconst stencil = options.stencil ?? defaultOptions.stencil;\\n\\t\\t\\t\\tif (stencil !== this.clearStencil) {\\n\\t\\t\\t\\t\\tthis.gl.clearStencil(stencil);\\n\\t\\t\\t\\t\\tthis.clearStencil = stencil;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tgl.stencilMask(255);\\n\\t\\t\\t\\tthis.stencilWriteMaskFront = 255;\\n\\t\\t\\t\\tthis.stencilWriteMaskBack = 255;\\n\\t\\t\\t}\\n\\t\\t\\tgl.clear(this.glClearFlag[flags]);\\n\\t\\t}\\n\\t}\\n\\tsubmit() {\\n\\t\\tthis.gl.flush();\\n\\t}\\n\\treadPixels(x, y, w, h, pixels) {\\n\\t\\tconst gl = this.gl;\\n\\t\\tgl.readPixels(x, y, w, h, gl.RGBA, gl.UNSIGNED_BYTE, pixels);\\n\\t}\\n\\tclientWaitAsync(flags, interval_ms) {\\n\\t\\tconst gl = this.gl;\\n\\t\\tconst sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);\\n\\t\\tthis.submit();\\n\\t\\treturn new Promise((resolve, reject) => {\\n\\t\\t\\tfunction test() {\\n\\t\\t\\t\\tconst res = gl.clientWaitSync(sync, flags, 0);\\n\\t\\t\\t\\tif (res === gl.TIMEOUT_EXPIRED) {\\n\\t\\t\\t\\t\\tsetTimeout(test, interval_ms);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tgl.deleteSync(sync);\\n\\t\\t\\t\\t\\tif (res === gl.WAIT_FAILED) {\\n\\t\\t\\t\\t\\t\\treject(new Error(\\\"webgl clientWaitSync sync failed\\\"));\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tresolve();\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\ttest();\\n\\t\\t});\\n\\t}\\n\\tasync readPixelsAsync(x, y, w, h, pixels, forceRgba = false) {\\n\\t\\tconst gl = this.gl;\\n\\t\\tlet format, pixelType;\\n\\t\\tif (forceRgba) {\\n\\t\\t\\tformat = gl.RGBA;\\n\\t\\t\\tpixelType = gl.UNSIGNED_BYTE;\\n\\t\\t} else {\\n\\t\\t\\tconst impl = this.renderTarget.colorBuffer?.impl;\\n\\t\\t\\tformat = impl?._glFormat ?? gl.RGBA;\\n\\t\\t\\tpixelType = impl?._glPixelType ?? gl.UNSIGNED_BYTE;\\n\\t\\t}\\n\\t\\tconst buf = gl.createBuffer();\\n\\t\\tgl.bindBuffer(gl.PIXEL_PACK_BUFFER, buf);\\n\\t\\tgl.bufferData(gl.PIXEL_PACK_BUFFER, pixels.byteLength, gl.STREAM_READ);\\n\\t\\tgl.readPixels(x, y, w, h, format, pixelType, 0);\\n\\t\\tgl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);\\n\\t\\tawait this.clientWaitAsync(0, 16);\\n\\t\\tgl.bindBuffer(gl.PIXEL_PACK_BUFFER, buf);\\n\\t\\tgl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, pixels);\\n\\t\\tgl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);\\n\\t\\tgl.deleteBuffer(buf);\\n\\t\\treturn pixels;\\n\\t}\\n\\treadTextureAsync(texture, x, y, width, height, options) {\\n\\t\\tconst face = options.face ?? 0;\\n\\t\\tconst mipLevel = options.mipLevel ?? 0;\\n\\t\\tconst renderTarget = options.renderTarget ?? new RenderTarget({\\n\\t\\t\\tcolorBuffer: texture,\\n\\t\\t\\tdepth: false,\\n\\t\\t\\tface,\\n\\t\\t\\tmipLevel\\n\\t\\t});\\n\\t\\tconst rgbaChannels = getPixelFormatChannelsForRgbaReadback(texture._format);\\n\\t\\tconst needsRgbaReadback = rgbaChannels > 0;\\n\\t\\tconst ArrayType = getPixelFormatArrayType(texture._format);\\n\\t\\tconst outputData = options.data ?? new ArrayType(\\n\\t\\t\\tTextureUtils.calcLevelGpuSize(width, height, 1, texture._format) / ArrayType.BYTES_PER_ELEMENT\\n\\t\\t);\\n\\t\\tconst readBuffer = needsRgbaReadback ? new Uint8Array(width * height * 4) : outputData;\\n\\t\\tthis.setRenderTarget(renderTarget);\\n\\t\\tthis.initRenderTarget(renderTarget);\\n\\t\\tthis.setFramebuffer(renderTarget.impl._glFrameBuffer);\\n\\t\\tif (options.immediate) {\\n\\t\\t\\tthis.gl.flush();\\n\\t\\t}\\n\\t\\treturn new Promise((resolve, reject) => {\\n\\t\\t\\tconst readPromise = this.readPixelsAsync(x, y, width, height, readBuffer, needsRgbaReadback);\\n\\t\\t\\treadPromise.then((data) => {\\n\\t\\t\\t\\tif (this._destroyed) return;\\n\\t\\t\\t\\tif (!options.renderTarget) {\\n\\t\\t\\t\\t\\trenderTarget.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (needsRgbaReadback) {\\n\\t\\t\\t\\t\\tconst pixelCount = width * height;\\n\\t\\t\\t\\t\\tfor (let i = 0; i < pixelCount; i++) {\\n\\t\\t\\t\\t\\t\\tfor (let c = 0; c < rgbaChannels; c++) {\\n\\t\\t\\t\\t\\t\\t\\toutputData[i * rgbaChannels + c] = data[i * 4 + c];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tresolve(outputData);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tresolve(data);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}).catch(reject);\\n\\t\\t});\\n\\t}\\n\\tasync writeTextureAsync(texture, x, y, width, height, data) {\\n\\t\\tconst gl = this.gl;\\n\\t\\tconst impl = texture.impl;\\n\\t\\tconst format = impl?._glFormat ?? gl.RGBA;\\n\\t\\tconst pixelType = impl?._glPixelType ?? gl.UNSIGNED_BYTE;\\n\\t\\tconst buf = gl.createBuffer();\\n\\t\\tgl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buf);\\n\\t\\tgl.bufferData(gl.PIXEL_UNPACK_BUFFER, data, gl.STREAM_DRAW);\\n\\t\\tgl.bindTexture(gl.TEXTURE_2D, impl._glTexture);\\n\\t\\tgl.texSubImage2D(gl.TEXTURE_2D, 0, x, y, width, height, format, pixelType, 0);\\n\\t\\tgl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);\\n\\t\\ttexture._needsUpload = false;\\n\\t\\ttexture._mipmapsUploaded = false;\\n\\t\\tawait this.clientWaitAsync(0, 16);\\n\\t}\\n\\tsetAlphaToCoverage(state) {\\n\\t\\tif (this.alphaToCoverage !== state) {\\n\\t\\t\\tthis.alphaToCoverage = state;\\n\\t\\t\\tif (state) {\\n\\t\\t\\t\\tthis.gl.enable(this.gl.SAMPLE_ALPHA_TO_COVERAGE);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.gl.disable(this.gl.SAMPLE_ALPHA_TO_COVERAGE);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tsetTransformFeedbackBuffer(tf) {\\n\\t\\tif (this.transformFeedbackBuffer !== tf) {\\n\\t\\t\\tthis.transformFeedbackBuffer = tf;\\n\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\tif (tf) {\\n\\t\\t\\t\\tif (!this.feedback) {\\n\\t\\t\\t\\t\\tthis.feedback = gl.createTransformFeedback();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tgl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, this.feedback);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tgl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tsetRaster(on) {\\n\\t\\tif (this.raster !== on) {\\n\\t\\t\\tthis.raster = on;\\n\\t\\t\\tif (on) {\\n\\t\\t\\t\\tthis.gl.disable(this.gl.RASTERIZER_DISCARD);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.gl.enable(this.gl.RASTERIZER_DISCARD);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tsetStencilTest(enable) {\\n\\t\\tif (this.stencil !== enable) {\\n\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\tif (enable) {\\n\\t\\t\\t\\tgl.enable(gl.STENCIL_TEST);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tgl.disable(gl.STENCIL_TEST);\\n\\t\\t\\t}\\n\\t\\t\\tthis.stencil = enable;\\n\\t\\t}\\n\\t}\\n\\tsetStencilFunc(func, ref, mask) {\\n\\t\\tif (this.stencilFuncFront !== func || this.stencilRefFront !== ref || this.stencilMaskFront !== mask || this.stencilFuncBack !== func || this.stencilRefBack !== ref || this.stencilMaskBack !== mask) {\\n\\t\\t\\tthis.gl.stencilFunc(this.glComparison[func], ref, mask);\\n\\t\\t\\tthis.stencilFuncFront = this.stencilFuncBack = func;\\n\\t\\t\\tthis.stencilRefFront = this.stencilRefBack = ref;\\n\\t\\t\\tthis.stencilMaskFront = this.stencilMaskBack = mask;\\n\\t\\t}\\n\\t}\\n\\tsetStencilFuncFront(func, ref, mask) {\\n\\t\\tif (this.stencilFuncFront !== func || this.stencilRefFront !== ref || this.stencilMaskFront !== mask) {\\n\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\tgl.stencilFuncSeparate(gl.FRONT, this.glComparison[func], ref, mask);\\n\\t\\t\\tthis.stencilFuncFront = func;\\n\\t\\t\\tthis.stencilRefFront = ref;\\n\\t\\t\\tthis.stencilMaskFront = mask;\\n\\t\\t}\\n\\t}\\n\\tsetStencilFuncBack(func, ref, mask) {\\n\\t\\tif (this.stencilFuncBack !== func || this.stencilRefBack !== ref || this.stencilMaskBack !== mask) {\\n\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\tgl.stencilFuncSeparate(gl.BACK, this.glComparison[func], ref, mask);\\n\\t\\t\\tthis.stencilFuncBack = func;\\n\\t\\t\\tthis.stencilRefBack = ref;\\n\\t\\t\\tthis.stencilMaskBack = mask;\\n\\t\\t}\\n\\t}\\n\\tsetStencilOperation(fail, zfail, zpass, writeMask) {\\n\\t\\tif (this.stencilFailFront !== fail || this.stencilZfailFront !== zfail || this.stencilZpassFront !== zpass || this.stencilFailBack !== fail || this.stencilZfailBack !== zfail || this.stencilZpassBack !== zpass) {\\n\\t\\t\\tthis.gl.stencilOp(this.glStencilOp[fail], this.glStencilOp[zfail], this.glStencilOp[zpass]);\\n\\t\\t\\tthis.stencilFailFront = this.stencilFailBack = fail;\\n\\t\\t\\tthis.stencilZfailFront = this.stencilZfailBack = zfail;\\n\\t\\t\\tthis.stencilZpassFront = this.stencilZpassBack = zpass;\\n\\t\\t}\\n\\t\\tif (this.stencilWriteMaskFront !== writeMask || this.stencilWriteMaskBack !== writeMask) {\\n\\t\\t\\tthis.gl.stencilMask(writeMask);\\n\\t\\t\\tthis.stencilWriteMaskFront = writeMask;\\n\\t\\t\\tthis.stencilWriteMaskBack = writeMask;\\n\\t\\t}\\n\\t}\\n\\tsetStencilOperationFront(fail, zfail, zpass, writeMask) {\\n\\t\\tif (this.stencilFailFront !== fail || this.stencilZfailFront !== zfail || this.stencilZpassFront !== zpass) {\\n\\t\\t\\tthis.gl.stencilOpSeparate(this.gl.FRONT, this.glStencilOp[fail], this.glStencilOp[zfail], this.glStencilOp[zpass]);\\n\\t\\t\\tthis.stencilFailFront = fail;\\n\\t\\t\\tthis.stencilZfailFront = zfail;\\n\\t\\t\\tthis.stencilZpassFront = zpass;\\n\\t\\t}\\n\\t\\tif (this.stencilWriteMaskFront !== writeMask) {\\n\\t\\t\\tthis.gl.stencilMaskSeparate(this.gl.FRONT, writeMask);\\n\\t\\t\\tthis.stencilWriteMaskFront = writeMask;\\n\\t\\t}\\n\\t}\\n\\tsetStencilOperationBack(fail, zfail, zpass, writeMask) {\\n\\t\\tif (this.stencilFailBack !== fail || this.stencilZfailBack !== zfail || this.stencilZpassBack !== zpass) {\\n\\t\\t\\tthis.gl.stencilOpSeparate(this.gl.BACK, this.glStencilOp[fail], this.glStencilOp[zfail], this.glStencilOp[zpass]);\\n\\t\\t\\tthis.stencilFailBack = fail;\\n\\t\\t\\tthis.stencilZfailBack = zfail;\\n\\t\\t\\tthis.stencilZpassBack = zpass;\\n\\t\\t}\\n\\t\\tif (this.stencilWriteMaskBack !== writeMask) {\\n\\t\\t\\tthis.gl.stencilMaskSeparate(this.gl.BACK, writeMask);\\n\\t\\t\\tthis.stencilWriteMaskBack = writeMask;\\n\\t\\t}\\n\\t}\\n\\tsetBlendState(blendState) {\\n\\t\\tconst currentBlendState = this.blendState;\\n\\t\\tif (!currentBlendState.equals(blendState)) {\\n\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\tconst { blend, colorOp, alphaOp, colorSrcFactor, colorDstFactor, alphaSrcFactor, alphaDstFactor } = blendState;\\n\\t\\t\\tif (currentBlendState.blend !== blend) {\\n\\t\\t\\t\\tif (blend) {\\n\\t\\t\\t\\t\\tgl.enable(gl.BLEND);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tgl.disable(gl.BLEND);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (currentBlendState.colorOp !== colorOp || currentBlendState.alphaOp !== alphaOp) {\\n\\t\\t\\t\\tconst glBlendEquation = this.glBlendEquation;\\n\\t\\t\\t\\tgl.blendEquationSeparate(glBlendEquation[colorOp], glBlendEquation[alphaOp]);\\n\\t\\t\\t}\\n\\t\\t\\tif (currentBlendState.colorSrcFactor !== colorSrcFactor || currentBlendState.colorDstFactor !== colorDstFactor || currentBlendState.alphaSrcFactor !== alphaSrcFactor || currentBlendState.alphaDstFactor !== alphaDstFactor) {\\n\\t\\t\\t\\tgl.blendFuncSeparate(\\n\\t\\t\\t\\t\\tthis.glBlendFunctionColor[colorSrcFactor],\\n\\t\\t\\t\\t\\tthis.glBlendFunctionColor[colorDstFactor],\\n\\t\\t\\t\\t\\tthis.glBlendFunctionAlpha[alphaSrcFactor],\\n\\t\\t\\t\\t\\tthis.glBlendFunctionAlpha[alphaDstFactor]\\n\\t\\t\\t\\t);\\n\\t\\t\\t}\\n\\t\\t\\tif (currentBlendState.allWrite !== blendState.allWrite) {\\n\\t\\t\\t\\tthis.gl.colorMask(blendState.redWrite, blendState.greenWrite, blendState.blueWrite, blendState.alphaWrite);\\n\\t\\t\\t}\\n\\t\\t\\tcurrentBlendState.copy(blendState);\\n\\t\\t}\\n\\t}\\n\\tsetBlendColor(r, g, b, a) {\\n\\t\\tconst c = this.blendColor;\\n\\t\\tif (r !== c.r || g !== c.g || b !== c.b || a !== c.a) {\\n\\t\\t\\tthis.gl.blendColor(r, g, b, a);\\n\\t\\t\\tc.set(r, g, b, a);\\n\\t\\t}\\n\\t}\\n\\tsetStencilState(stencilFront, stencilBack) {\\n\\t\\tif (stencilFront || stencilBack) {\\n\\t\\t\\tthis.setStencilTest(true);\\n\\t\\t\\tif (stencilFront === stencilBack) {\\n\\t\\t\\t\\tthis.setStencilFunc(stencilFront.func, stencilFront.ref, stencilFront.readMask);\\n\\t\\t\\t\\tthis.setStencilOperation(stencilFront.fail, stencilFront.zfail, stencilFront.zpass, stencilFront.writeMask);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tstencilFront ?? (stencilFront = StencilParameters.DEFAULT);\\n\\t\\t\\t\\tthis.setStencilFuncFront(stencilFront.func, stencilFront.ref, stencilFront.readMask);\\n\\t\\t\\t\\tthis.setStencilOperationFront(stencilFront.fail, stencilFront.zfail, stencilFront.zpass, stencilFront.writeMask);\\n\\t\\t\\t\\tstencilBack ?? (stencilBack = StencilParameters.DEFAULT);\\n\\t\\t\\t\\tthis.setStencilFuncBack(stencilBack.func, stencilBack.ref, stencilBack.readMask);\\n\\t\\t\\t\\tthis.setStencilOperationBack(stencilBack.fail, stencilBack.zfail, stencilBack.zpass, stencilBack.writeMask);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis.setStencilTest(false);\\n\\t\\t}\\n\\t}\\n\\tsetDepthState(depthState) {\\n\\t\\tconst currentDepthState = this.depthState;\\n\\t\\tif (!currentDepthState.equals(depthState)) {\\n\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\tconst write = depthState.write;\\n\\t\\t\\tif (currentDepthState.write !== write) {\\n\\t\\t\\t\\tgl.depthMask(write);\\n\\t\\t\\t}\\n\\t\\t\\tlet { func, test } = depthState;\\n\\t\\t\\tif (!test && write) {\\n\\t\\t\\t\\ttest = true;\\n\\t\\t\\t\\tfunc = FUNC_ALWAYS;\\n\\t\\t\\t}\\n\\t\\t\\tif (currentDepthState.func !== func) {\\n\\t\\t\\t\\tgl.depthFunc(this.glComparison[func]);\\n\\t\\t\\t}\\n\\t\\t\\tif (currentDepthState.test !== test) {\\n\\t\\t\\t\\tif (test) {\\n\\t\\t\\t\\t\\tgl.enable(gl.DEPTH_TEST);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tgl.disable(gl.DEPTH_TEST);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tconst { depthBias, depthBiasSlope } = depthState;\\n\\t\\t\\tif (depthBias || depthBiasSlope) {\\n\\t\\t\\t\\tif (!this.depthBiasEnabled) {\\n\\t\\t\\t\\t\\tthis.depthBiasEnabled = true;\\n\\t\\t\\t\\t\\tthis.gl.enable(this.gl.POLYGON_OFFSET_FILL);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tgl.polygonOffset(depthBiasSlope, depthBias);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (this.depthBiasEnabled) {\\n\\t\\t\\t\\t\\tthis.depthBiasEnabled = false;\\n\\t\\t\\t\\t\\tthis.gl.disable(this.gl.POLYGON_OFFSET_FILL);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tcurrentDepthState.copy(depthState);\\n\\t\\t}\\n\\t}\\n\\tsetCullMode(cullMode) {\\n\\t\\tif (this.cullMode !== cullMode) {\\n\\t\\t\\tif (cullMode === CULLFACE_NONE) {\\n\\t\\t\\t\\tthis.gl.disable(this.gl.CULL_FACE);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (this.cullMode === CULLFACE_NONE) {\\n\\t\\t\\t\\t\\tthis.gl.enable(this.gl.CULL_FACE);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst mode = this.glCull[cullMode];\\n\\t\\t\\t\\tif (this.cullFace !== mode) {\\n\\t\\t\\t\\t\\tthis.gl.cullFace(mode);\\n\\t\\t\\t\\t\\tthis.cullFace = mode;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis.cullMode = cullMode;\\n\\t\\t}\\n\\t}\\n\\tsetFrontFace(frontFace) {\\n\\t\\tif (this.frontFace !== frontFace) {\\n\\t\\t\\tconst mode = this.glFrontFace[frontFace];\\n\\t\\t\\tthis.gl.frontFace(mode);\\n\\t\\t\\tthis.frontFace = frontFace;\\n\\t\\t}\\n\\t}\\n\\tsetShader(shader, asyncCompile = false) {\\n\\t\\tif (shader !== this.shader) {\\n\\t\\t\\tthis.shader = shader;\\n\\t\\t\\tthis.shaderAsyncCompile = asyncCompile;\\n\\t\\t\\tthis.shaderValid = void 0;\\n\\t\\t}\\n\\t}\\n\\tactivateShader() {\\n\\t\\tconst { shader } = this;\\n\\t\\tconst { impl } = shader;\\n\\t\\tif (this.shaderValid === void 0) {\\n\\t\\t\\tif (shader.failed) {\\n\\t\\t\\t\\tthis.shaderValid = false;\\n\\t\\t\\t} else if (!shader.ready) {\\n\\t\\t\\t\\tif (this.shaderAsyncCompile) {\\n\\t\\t\\t\\t\\tif (impl.isLinked(this)) {\\n\\t\\t\\t\\t\\t\\tif (!impl.finalize(this, shader)) {\\n\\t\\t\\t\\t\\t\\t\\tshader.failed = true;\\n\\t\\t\\t\\t\\t\\t\\tthis.shaderValid = false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.shaderValid = false;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tif (!impl.finalize(this, shader)) {\\n\\t\\t\\t\\t\\t\\tshader.failed = true;\\n\\t\\t\\t\\t\\t\\tthis.shaderValid = false;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this.shaderValid === void 0) {\\n\\t\\t\\tthis.gl.useProgram(impl.glProgram);\\n\\t\\t\\tthis.shaderValid = true;\\n\\t\\t}\\n\\t}\\n\\tclearVertexArrayObjectCache() {\\n\\t\\tconst gl = this.gl;\\n\\t\\tthis._vaoMap.forEach((item, key, mapObj) => {\\n\\t\\t\\tgl.deleteVertexArray(item);\\n\\t\\t});\\n\\t\\tthis._vaoMap.clear();\\n\\t}\\n\\tset fullscreen(fullscreen) {\\n\\t\\tif (fullscreen) {\\n\\t\\t\\tconst canvas = this.gl.canvas;\\n\\t\\t\\tcanvas.requestFullscreen();\\n\\t\\t} else {\\n\\t\\t\\tdocument.exitFullscreen();\\n\\t\\t}\\n\\t}\\n\\tget fullscreen() {\\n\\t\\treturn !!document.fullscreenElement;\\n\\t}\\n}\\n\\nclass NullIndexBuffer {\\n\\tunlock(indexBuffer) {\\n\\t}\\n}\\n\\nclass NullRenderTarget {\\n\\tdestroy(device) {\\n\\t}\\n\\tinit(device, renderTarget) {\\n\\t}\\n\\tloseContext() {\\n\\t}\\n\\tresolve(device, target, color, depth) {\\n\\t}\\n}\\n\\nclass NullShader {\\n\\tdestroy(shader) {\\n\\t}\\n\\tloseContext() {\\n\\t}\\n\\trestoreContext(device, shader) {\\n\\t}\\n}\\n\\nclass NullTexture {\\n\\tdestroy(device) {\\n\\t}\\n\\tpropertyChanged(flag) {\\n\\t}\\n\\tloseContext() {\\n\\t}\\n}\\n\\nclass NullVertexBuffer {\\n\\tdestroy(device) {\\n\\t}\\n\\tunlock(vertexBuffer) {\\n\\t}\\n}\\n\\nclass NullDrawCommands {\\n\\tadd(i, indexOrVertexCount, instanceCount, firstIndexOrVertex) {\\n\\t}\\n}\\n\\nclass NullGraphicsDevice extends GraphicsDevice {\\n\\tconstructor(canvas, options = {}) {\\n\\t\\tsuper(canvas, options);\\n\\t\\toptions = this.initOptions;\\n\\t\\tthis.isNull = true;\\n\\t\\tthis._deviceType = DEVICETYPE_NULL;\\n\\t\\tthis.samples = 1;\\n\\t\\tthis.backBuffer = new RenderTarget({\\n\\t\\t\\tname: \\\"Framebuffer\\\",\\n\\t\\t\\tgraphicsDevice: this,\\n\\t\\t\\tdepth: this.initOptions.depth,\\n\\t\\t\\tstencil: this.supportsStencil,\\n\\t\\t\\tsamples: this.samples\\n\\t\\t});\\n\\t\\tthis.initDeviceCaps();\\n\\t}\\n\\tdestroy() {\\n\\t\\tsuper.destroy();\\n\\t}\\n\\tinitDeviceCaps() {\\n\\t\\tthis.disableParticleSystem = true;\\n\\t\\tthis.precision = \\\"highp\\\";\\n\\t\\tthis.maxPrecision = \\\"highp\\\";\\n\\t\\tthis.maxSamples = 4;\\n\\t\\tthis.maxTextures = 16;\\n\\t\\tthis.maxTextureSize = 4096;\\n\\t\\tthis.maxCubeMapSize = 4096;\\n\\t\\tthis.maxVolumeSize = 4096;\\n\\t\\tthis.maxColorAttachments = 8;\\n\\t\\tthis.maxPixelRatio = 1;\\n\\t\\tthis.maxAnisotropy = 16;\\n\\t\\tthis.supportsUniformBuffers = false;\\n\\t\\tthis.supportsAreaLights = true;\\n\\t\\tthis.supportsGpuParticles = false;\\n\\t\\tthis.textureFloatRenderable = true;\\n\\t\\tthis.textureHalfFloatRenderable = true;\\n\\t\\tthis.supportsImageBitmap = false;\\n\\t}\\n\\tpostInit() {\\n\\t\\tsuper.postInit();\\n\\t}\\n\\tframeStart() {\\n\\t\\tsuper.frameStart();\\n\\t}\\n\\tframeEnd() {\\n\\t\\tsuper.frameEnd();\\n\\t}\\n\\tupdateBegin() {\\n\\t}\\n\\tupdateEnd() {\\n\\t}\\n\\treadPixels(x, y, w, h, pixels) {\\n\\t}\\n\\tcreateVertexBufferImpl(vertexBuffer, format) {\\n\\t\\treturn new NullVertexBuffer(vertexBuffer, format);\\n\\t}\\n\\tcreateIndexBufferImpl(indexBuffer) {\\n\\t\\treturn new NullIndexBuffer(indexBuffer);\\n\\t}\\n\\tcreateShaderImpl(shader) {\\n\\t\\treturn new NullShader(shader);\\n\\t}\\n\\tcreateTextureImpl(texture) {\\n\\t\\treturn new NullTexture(texture);\\n\\t}\\n\\tcreateRenderTargetImpl(renderTarget) {\\n\\t\\treturn new NullRenderTarget(renderTarget);\\n\\t}\\n\\tcreateDrawCommandImpl(drawCommands) {\\n\\t\\treturn new NullDrawCommands();\\n\\t}\\n\\tcreateUploadStreamImpl(uploadStream) {\\n\\t\\treturn null;\\n\\t}\\n\\tdraw(primitive, indexBuffer, numInstances, drawCommands, first = true, last = true) {\\n\\t}\\n\\tsetShader(shader, asyncCompile = false) {\\n\\t}\\n\\tsetBlendState(blendState) {\\n\\t}\\n\\tsetDepthState(depthState) {\\n\\t}\\n\\tsetStencilState(stencilFront, stencilBack) {\\n\\t}\\n\\tsetBlendColor(r, g, b, a) {\\n\\t}\\n\\tsetCullMode(cullMode) {\\n\\t}\\n\\tsetFrontFace(frontFace) {\\n\\t}\\n\\tsetAlphaToCoverage(state) {\\n\\t}\\n\\tinitializeContextCaches() {\\n\\t\\tsuper.initializeContextCaches();\\n\\t}\\n\\tclear(options) {\\n\\t}\\n\\tsetViewport(x, y, w, h) {\\n\\t}\\n\\tsetScissor(x, y, w, h) {\\n\\t}\\n\\tcopyRenderTarget(source, dest, color, depth) {\\n\\t\\treturn true;\\n\\t}\\n}\\n\\nfunction createGraphicsDevice(canvas, options = {}) {\\n\\tconst deviceTypes = options.deviceTypes ?? [];\\n\\tif (!deviceTypes.includes(DEVICETYPE_WEBGL2)) {\\n\\t\\tdeviceTypes.push(DEVICETYPE_WEBGL2);\\n\\t}\\n\\tif (!deviceTypes.includes(DEVICETYPE_NULL)) {\\n\\t\\tdeviceTypes.push(DEVICETYPE_NULL);\\n\\t}\\n\\tconst deviceCreateFuncs = [];\\n\\tfor (let i = 0; i < deviceTypes.length; i++) {\\n\\t\\tconst deviceType = deviceTypes[i];\\n\\t\\tif ((deviceType === DEVICETYPE_WEBGPU || deviceType === DEVICETYPE_WEBGPU_BARE) && window?.navigator?.gpu) {\\n\\t\\t\\tconst featureLevel = deviceType === DEVICETYPE_WEBGPU_BARE ? \\\"bare\\\" : void 0;\\n\\t\\t\\tdeviceCreateFuncs.push(() => {\\n\\t\\t\\t\\tconst device = new WebgpuGraphicsDevice(canvas, { ...options, featureLevel });\\n\\t\\t\\t\\treturn device.initWebGpu(options.glslangUrl, options.twgslUrl);\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tif (deviceType === DEVICETYPE_WEBGL2) {\\n\\t\\t\\tdeviceCreateFuncs.push(() => {\\n\\t\\t\\t\\treturn new WebglGraphicsDevice(canvas, options);\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tif (deviceType === DEVICETYPE_NULL) {\\n\\t\\t\\tdeviceCreateFuncs.push(() => {\\n\\t\\t\\t\\treturn new NullGraphicsDevice(canvas, options);\\n\\t\\t\\t});\\n\\t\\t}\\n\\t}\\n\\treturn new Promise((resolve, reject) => {\\n\\t\\tlet attempt = 0;\\n\\t\\tconst next = () => {\\n\\t\\t\\tif (attempt >= deviceCreateFuncs.length) {\\n\\t\\t\\t\\treject(new Error(\\\"Failed to create a graphics device\\\"));\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tPromise.resolve(deviceCreateFuncs[attempt++]()).then((device) => {\\n\\t\\t\\t\\t\\tif (device) {\\n\\t\\t\\t\\t\\t\\tresolve(device);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tnext();\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}).catch((err) => {\\n\\t\\t\\t\\t\\tconsole.log(err);\\n\\t\\t\\t\\t\\tnext();\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tnext();\\n\\t});\\n}\\n\\nclass ComputeParameter {\\n\\tvalue;\\n\\tscopeId = null;\\n}\\nclass Compute {\\n\\tshader = null;\\n\\tname;\\n\\tparameters = /* @__PURE__ */ new Map();\\n\\tcountX = 1;\\n\\tcountY;\\n\\tcountZ;\\n\\tindirectSlotIndex = -1;\\n\\tindirectBuffer = null;\\n\\tindirectFrameStamp = 0;\\n\\tconstructor(graphicsDevice, shader, name = \\\"Unnamed\\\") {\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tthis.shader = shader;\\n\\t\\tthis.name = name;\\n\\t\\tif (graphicsDevice.supportsCompute) {\\n\\t\\t\\tthis.impl = graphicsDevice.createComputeImpl(this);\\n\\t\\t}\\n\\t}\\n\\tsetParameter(name, value) {\\n\\t\\tlet param = this.parameters.get(name);\\n\\t\\tif (!param) {\\n\\t\\t\\tparam = new ComputeParameter();\\n\\t\\t\\tparam.scopeId = this.device.scope.resolve(name);\\n\\t\\t\\tthis.parameters.set(name, param);\\n\\t\\t}\\n\\t\\tparam.value = value;\\n\\t}\\n\\tgetParameter(name) {\\n\\t\\treturn this.parameters.get(name)?.value;\\n\\t}\\n\\tdeleteParameter(name) {\\n\\t\\tthis.parameters.delete(name);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.impl?.destroy();\\n\\t\\tthis.impl = null;\\n\\t}\\n\\tapplyParameters() {\\n\\t\\tfor (const [, param] of this.parameters) {\\n\\t\\t\\tparam.scopeId.setValue(param.value);\\n\\t\\t}\\n\\t}\\n\\tsetupDispatch(x, y, z) {\\n\\t\\tthis.countX = x;\\n\\t\\tthis.countY = y;\\n\\t\\tthis.countZ = z;\\n\\t\\tthis.indirectSlotIndex = -1;\\n\\t\\tthis.indirectBuffer = null;\\n\\t}\\n\\tsetupIndirectDispatch(slotIndex, buffer = null) {\\n\\t\\tthis.indirectSlotIndex = slotIndex;\\n\\t\\tthis.indirectBuffer = buffer;\\n\\t\\tthis.indirectFrameStamp = this.device.renderVersion;\\n\\t}\\n\\tstatic calcDispatchSize(count, result, maxDimension = 65535) {\\n\\t\\tif (count <= maxDimension) {\\n\\t\\t\\treturn result.set(count, 1);\\n\\t\\t}\\n\\t\\tconst y = Math.ceil(count / maxDimension);\\n\\t\\treturn result.set(Math.ceil(count / y), y);\\n\\t}\\n}\\n\\nclass DrawCommands {\\n\\tdevice;\\n\\tindexSizeBytes;\\n\\t_maxCount = 0;\\n\\tget maxCount() {\\n\\t\\treturn this._maxCount;\\n\\t}\\n\\timpl = null;\\n\\t_count = 1;\\n\\tget count() {\\n\\t\\treturn this._count;\\n\\t}\\n\\tslotIndex = 0;\\n\\tprimitiveCount = 0;\\n\\tconstructor(device, indexSizeBytes = 0) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.indexSizeBytes = indexSizeBytes;\\n\\t\\tthis.impl = device.createDrawCommandImpl(this);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.impl?.destroy?.();\\n\\t\\tthis.impl = null;\\n\\t}\\n\\tallocate(maxCount) {\\n\\t\\tthis._maxCount = maxCount;\\n\\t\\tthis.impl.allocate?.(maxCount);\\n\\t}\\n\\tadd(i, indexOrVertexCount, instanceCount, firstIndexOrVertex, baseVertex = 0, firstInstance = 0) {\\n\\t\\tthis.impl.add(i, indexOrVertexCount, instanceCount, firstIndexOrVertex, baseVertex, firstInstance);\\n\\t}\\n\\tupdate(count) {\\n\\t\\tthis._count = count;\\n\\t\\tthis.primitiveCount = this.impl.update?.(count) ?? 0;\\n\\t}\\n}\\n\\nclass FramePass {\\n\\t_name;\\n\\tdevice;\\n\\t_enabled = true;\\n\\t_skipStart = false;\\n\\t_skipEnd = false;\\n\\texecuteEnabled = true;\\n\\trequiresCubemaps = false;\\n\\tbeforePasses = [];\\n\\tafterPasses = [];\\n\\tconstructor(graphicsDevice) {\\n\\t\\tthis.device = graphicsDevice;\\n\\t}\\n\\tset name(value) {\\n\\t\\tthis._name = value;\\n\\t}\\n\\tget name() {\\n\\t\\tif (!this._name) {\\n\\t\\t\\tthis._name = this.constructor.name;\\n\\t\\t}\\n\\t\\treturn this._name;\\n\\t}\\n\\tset enabled(value) {\\n\\t\\tif (this._enabled !== value) {\\n\\t\\t\\tthis._enabled = value;\\n\\t\\t\\tif (value) {\\n\\t\\t\\t\\tthis.onEnable();\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.onDisable();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget enabled() {\\n\\t\\treturn this._enabled;\\n\\t}\\n\\tonEnable() {\\n\\t}\\n\\tonDisable() {\\n\\t}\\n\\tframeUpdate() {\\n\\t}\\n\\tbefore() {\\n\\t}\\n\\texecute() {\\n\\t}\\n\\tafter() {\\n\\t}\\n\\tdestroy() {\\n\\t}\\n\\trender() {\\n\\t\\tif (this.enabled) {\\n\\t\\t\\tthis.before();\\n\\t\\t\\tif (this.executeEnabled) {\\n\\t\\t\\t\\tthis.execute();\\n\\t\\t\\t}\\n\\t\\t\\tthis.after();\\n\\t\\t\\tthis.device.renderPassIndex++;\\n\\t\\t}\\n\\t}\\n}\\n\\nclass ColorAttachmentOps {\\n\\tclearValue = new Color(0, 0, 0, 1);\\n\\tclearValueLinear = new Color(0, 0, 0, 1);\\n\\tclear = false;\\n\\tstore = false;\\n\\tresolve = true;\\n\\tgenMipmaps = false;\\n}\\nclass DepthStencilAttachmentOps {\\n\\tclearDepthValue = 1;\\n\\tclearStencilValue = 0;\\n\\tclearDepth = false;\\n\\tclearStencil = false;\\n\\tstoreDepth = false;\\n\\tresolveDepth = false;\\n\\tstoreStencil = false;\\n}\\nclass RenderPass extends FramePass {\\n\\trenderTarget;\\n\\t_options;\\n\\tsamples = 0;\\n\\tcolorArrayOps = [];\\n\\tget colorOps() {\\n\\t\\treturn this.colorArrayOps[0];\\n\\t}\\n\\tdepthStencilOps;\\n\\trequiresCubemaps = true;\\n\\tfullSizeClearRect = true;\\n\\tset scaleX(value) {\\n\\t\\tthis._options.scaleX = value;\\n\\t}\\n\\tget scaleX() {\\n\\t\\treturn this._options.scaleX;\\n\\t}\\n\\tset scaleY(value) {\\n\\t\\tthis._options.scaleY = value;\\n\\t}\\n\\tget scaleY() {\\n\\t\\treturn this._options.scaleY;\\n\\t}\\n\\tset options(value) {\\n\\t\\tthis._options = value;\\n\\t\\tif (value) {\\n\\t\\t\\tthis.scaleX = this.scaleX ?? 1;\\n\\t\\t\\tthis.scaleY = this.scaleY ?? 1;\\n\\t\\t}\\n\\t}\\n\\tget options() {\\n\\t\\treturn this._options;\\n\\t}\\n\\tinit(renderTarget = null, options) {\\n\\t\\tthis.options = options;\\n\\t\\tthis.renderTarget = renderTarget;\\n\\t\\tthis.samples = Math.max(this.renderTarget ? this.renderTarget.samples : this.device.samples, 1);\\n\\t\\tthis.allocateAttachments();\\n\\t\\tthis.postInit();\\n\\t}\\n\\tallocateAttachments() {\\n\\t\\tconst rt = this.renderTarget;\\n\\t\\tthis.depthStencilOps = new DepthStencilAttachmentOps();\\n\\t\\tif (rt?.depthBuffer) {\\n\\t\\t\\tthis.depthStencilOps.storeDepth = true;\\n\\t\\t}\\n\\t\\tconst numColorOps = rt ? rt._colorBuffers?.length ?? 0 : 1;\\n\\t\\tthis.colorArrayOps.length = 0;\\n\\t\\tfor (let i = 0; i < numColorOps; i++) {\\n\\t\\t\\tconst colorOps = new ColorAttachmentOps();\\n\\t\\t\\tthis.colorArrayOps[i] = colorOps;\\n\\t\\t\\tif (this.samples === 1) {\\n\\t\\t\\t\\tcolorOps.store = true;\\n\\t\\t\\t\\tcolorOps.resolve = false;\\n\\t\\t\\t}\\n\\t\\t\\tconst colorBuffer = this.renderTarget?._colorBuffers?.[i];\\n\\t\\t\\tif (this.renderTarget?.mipmaps && colorBuffer?.mipmaps) {\\n\\t\\t\\t\\tconst intFormat = isIntegerPixelFormat(colorBuffer._format);\\n\\t\\t\\t\\tcolorOps.genMipmaps = !intFormat;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tpostInit() {\\n\\t}\\n\\tframeUpdate() {\\n\\t\\tif (this._options && this.renderTarget) {\\n\\t\\t\\tconst resizeSource = this._options.resizeSource ?? this.device.backBuffer;\\n\\t\\t\\tconst width = Math.floor(resizeSource.width * this.scaleX);\\n\\t\\t\\tconst height = Math.floor(resizeSource.height * this.scaleY);\\n\\t\\t\\tthis.renderTarget.resize(width, height);\\n\\t\\t}\\n\\t}\\n\\tsetClearColor(color) {\\n\\t\\tconst count = this.colorArrayOps.length;\\n\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\tconst colorOps = this.colorArrayOps[i];\\n\\t\\t\\tif (color) {\\n\\t\\t\\t\\tcolorOps.clearValue.copy(color);\\n\\t\\t\\t\\tcolorOps.clearValueLinear.linear(color);\\n\\t\\t\\t}\\n\\t\\t\\tcolorOps.clear = !!color;\\n\\t\\t}\\n\\t}\\n\\tsetClearDepth(depthValue) {\\n\\t\\tif (depthValue !== void 0) {\\n\\t\\t\\tthis.depthStencilOps.clearDepthValue = depthValue;\\n\\t\\t}\\n\\t\\tthis.depthStencilOps.clearDepth = depthValue !== void 0;\\n\\t}\\n\\tsetClearStencil(stencilValue) {\\n\\t\\tif (stencilValue !== void 0) {\\n\\t\\t\\tthis.depthStencilOps.clearStencilValue = stencilValue;\\n\\t\\t}\\n\\t\\tthis.depthStencilOps.clearStencil = stencilValue !== void 0;\\n\\t}\\n\\trender() {\\n\\t\\tif (this.enabled) {\\n\\t\\t\\tconst device = this.device;\\n\\t\\t\\tconst realPass = this.renderTarget !== void 0;\\n\\t\\t\\tthis.before();\\n\\t\\t\\tif (this.executeEnabled) {\\n\\t\\t\\t\\tif (realPass && !this._skipStart) {\\n\\t\\t\\t\\t\\tdevice.startRenderPass(this);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.execute();\\n\\t\\t\\t\\tif (realPass && !this._skipEnd) {\\n\\t\\t\\t\\t\\tdevice.endRenderPass(this);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis.after();\\n\\t\\t\\tdevice.renderPassIndex++;\\n\\t\\t}\\n\\t}\\n}\\n\\nfunction set1(a) {\\n\\tthis.array[this.index] = a;\\n}\\nfunction set2(a, b) {\\n\\tthis.array[this.index] = a;\\n\\tthis.array[this.index + 1] = b;\\n}\\nfunction set3(a, b, c) {\\n\\tthis.array[this.index] = a;\\n\\tthis.array[this.index + 1] = b;\\n\\tthis.array[this.index + 2] = c;\\n}\\nfunction set4(a, b, c, d) {\\n\\tthis.array[this.index] = a;\\n\\tthis.array[this.index + 1] = b;\\n\\tthis.array[this.index + 2] = c;\\n\\tthis.array[this.index + 3] = d;\\n}\\nfunction arraySet1(index, inputArray, inputIndex) {\\n\\tthis.array[index] = inputArray[inputIndex];\\n}\\nfunction arraySet2(index, inputArray, inputIndex) {\\n\\tthis.array[index] = inputArray[inputIndex];\\n\\tthis.array[index + 1] = inputArray[inputIndex + 1];\\n}\\nfunction arraySet3(index, inputArray, inputIndex) {\\n\\tthis.array[index] = inputArray[inputIndex];\\n\\tthis.array[index + 1] = inputArray[inputIndex + 1];\\n\\tthis.array[index + 2] = inputArray[inputIndex + 2];\\n}\\nfunction arraySet4(index, inputArray, inputIndex) {\\n\\tthis.array[index] = inputArray[inputIndex];\\n\\tthis.array[index + 1] = inputArray[inputIndex + 1];\\n\\tthis.array[index + 2] = inputArray[inputIndex + 2];\\n\\tthis.array[index + 3] = inputArray[inputIndex + 3];\\n}\\nfunction arrayGet1(offset, outputArray, outputIndex) {\\n\\toutputArray[outputIndex] = this.array[offset];\\n}\\nfunction arrayGet2(offset, outputArray, outputIndex) {\\n\\toutputArray[outputIndex] = this.array[offset];\\n\\toutputArray[outputIndex + 1] = this.array[offset + 1];\\n}\\nfunction arrayGet3(offset, outputArray, outputIndex) {\\n\\toutputArray[outputIndex] = this.array[offset];\\n\\toutputArray[outputIndex + 1] = this.array[offset + 1];\\n\\toutputArray[outputIndex + 2] = this.array[offset + 2];\\n}\\nfunction arrayGet4(offset, outputArray, outputIndex) {\\n\\toutputArray[outputIndex] = this.array[offset];\\n\\toutputArray[outputIndex + 1] = this.array[offset + 1];\\n\\toutputArray[outputIndex + 2] = this.array[offset + 2];\\n\\toutputArray[outputIndex + 3] = this.array[offset + 3];\\n}\\nclass VertexIteratorAccessor {\\n\\tconstructor(buffer, vertexElement, vertexFormat) {\\n\\t\\tthis.index = 0;\\n\\t\\tthis.numComponents = vertexElement.numComponents;\\n\\t\\tif (vertexFormat.interleaved) {\\n\\t\\t\\tthis.array = new typedArrayTypes[vertexElement.dataType](buffer, vertexElement.offset);\\n\\t\\t} else {\\n\\t\\t\\tthis.array = new typedArrayTypes[vertexElement.dataType](buffer, vertexElement.offset, vertexFormat.vertexCount * vertexElement.numComponents);\\n\\t\\t}\\n\\t\\tthis.stride = vertexElement.stride / this.array.constructor.BYTES_PER_ELEMENT;\\n\\t\\tswitch (vertexElement.numComponents) {\\n\\t\\t\\tcase 1:\\n\\t\\t\\t\\tthis.set = set1;\\n\\t\\t\\t\\tthis.getToArray = arrayGet1;\\n\\t\\t\\t\\tthis.setFromArray = arraySet1;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase 2:\\n\\t\\t\\t\\tthis.set = set2;\\n\\t\\t\\t\\tthis.getToArray = arrayGet2;\\n\\t\\t\\t\\tthis.setFromArray = arraySet2;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase 3:\\n\\t\\t\\t\\tthis.set = set3;\\n\\t\\t\\t\\tthis.getToArray = arrayGet3;\\n\\t\\t\\t\\tthis.setFromArray = arraySet3;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase 4:\\n\\t\\t\\t\\tthis.set = set4;\\n\\t\\t\\t\\tthis.getToArray = arrayGet4;\\n\\t\\t\\t\\tthis.setFromArray = arraySet4;\\n\\t\\t\\t\\tbreak;\\n\\t\\t}\\n\\t}\\n\\tget(offset) {\\n\\t\\treturn this.array[this.index + offset];\\n\\t}\\n\\tset(a, b, c, d) {\\n\\t}\\n\\tgetToArray(offset, outputArray, outputIndex) {\\n\\t}\\n\\tsetFromArray(index, inputArray, inputIndex) {\\n\\t}\\n}\\nclass VertexIterator {\\n\\tconstructor(vertexBuffer) {\\n\\t\\tthis.vertexBuffer = vertexBuffer;\\n\\t\\tthis.vertexFormatSize = vertexBuffer.getFormat().size;\\n\\t\\tthis.buffer = this.vertexBuffer.lock();\\n\\t\\tthis.accessors = [];\\n\\t\\tthis.element = {};\\n\\t\\tconst vertexFormat = this.vertexBuffer.getFormat();\\n\\t\\tfor (let i = 0; i < vertexFormat.elements.length; i++) {\\n\\t\\t\\tconst vertexElement = vertexFormat.elements[i];\\n\\t\\t\\tthis.accessors[i] = new VertexIteratorAccessor(this.buffer, vertexElement, vertexFormat);\\n\\t\\t\\tthis.element[vertexElement.name] = this.accessors[i];\\n\\t\\t}\\n\\t}\\n\\tnext(count = 1) {\\n\\t\\tlet i = 0;\\n\\t\\tconst accessors = this.accessors;\\n\\t\\tconst numAccessors = this.accessors.length;\\n\\t\\twhile (i < numAccessors) {\\n\\t\\t\\tconst accessor = accessors[i++];\\n\\t\\t\\taccessor.index += count * accessor.stride;\\n\\t\\t}\\n\\t}\\n\\tend() {\\n\\t\\tthis.vertexBuffer.unlock();\\n\\t}\\n\\twriteData(semantic, data, numVertices) {\\n\\t\\tconst element = this.element[semantic];\\n\\t\\tif (element) {\\n\\t\\t\\tif (numVertices > this.vertexBuffer.numVertices) {\\n\\t\\t\\t\\tnumVertices = this.vertexBuffer.numVertices;\\n\\t\\t\\t}\\n\\t\\t\\tconst numComponents = element.numComponents;\\n\\t\\t\\tif (this.vertexBuffer.getFormat().interleaved) {\\n\\t\\t\\t\\tlet index = 0;\\n\\t\\t\\t\\tfor (let i = 0; i < numVertices; i++) {\\n\\t\\t\\t\\t\\telement.setFromArray(index, data, i * numComponents);\\n\\t\\t\\t\\t\\tindex += element.stride;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (data.length > numVertices * numComponents) {\\n\\t\\t\\t\\t\\tconst copyCount = numVertices * numComponents;\\n\\t\\t\\t\\t\\tif (ArrayBuffer.isView(data)) {\\n\\t\\t\\t\\t\\t\\tdata = data.subarray(0, copyCount);\\n\\t\\t\\t\\t\\t\\telement.array.set(data);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tfor (let i = 0; i < copyCount; i++) {\\n\\t\\t\\t\\t\\t\\t\\telement.array[i] = data[i];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\telement.array.set(data);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\treadData(semantic, data) {\\n\\t\\tconst element = this.element[semantic];\\n\\t\\tlet count = 0;\\n\\t\\tif (element) {\\n\\t\\t\\tcount = this.vertexBuffer.numVertices;\\n\\t\\t\\tlet i;\\n\\t\\t\\tconst numComponents = element.numComponents;\\n\\t\\t\\tif (this.vertexBuffer.getFormat().interleaved) {\\n\\t\\t\\t\\tif (Array.isArray(data)) {\\n\\t\\t\\t\\t\\tdata.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\telement.index = 0;\\n\\t\\t\\t\\tlet offset = 0;\\n\\t\\t\\t\\tfor (i = 0; i < count; i++) {\\n\\t\\t\\t\\t\\telement.getToArray(offset, data, i * numComponents);\\n\\t\\t\\t\\t\\toffset += element.stride;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (ArrayBuffer.isView(data)) {\\n\\t\\t\\t\\t\\tdata.set(element.array);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tdata.length = 0;\\n\\t\\t\\t\\t\\tconst copyCount = count * numComponents;\\n\\t\\t\\t\\t\\tfor (i = 0; i < copyCount; i++) {\\n\\t\\t\\t\\t\\t\\tdata[i] = element.array[i];\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn count;\\n\\t}\\n}\\n\\nconst MOUSEBUTTON_NONE = -1;\\n\\nclass KeyboardEvent {\\n\\tkey = null;\\n\\telement = null;\\n\\tevent = null;\\n\\tconstructor(keyboard, event) {\\n\\t\\tif (event) {\\n\\t\\t\\tthis.key = event.keyCode;\\n\\t\\t\\tthis.element = event.target;\\n\\t\\t\\tthis.event = event;\\n\\t\\t}\\n\\t}\\n}\\n\\nconst _keyboardEvent = new KeyboardEvent();\\nfunction makeKeyboardEvent(event) {\\n\\t_keyboardEvent.key = event.keyCode;\\n\\t_keyboardEvent.element = event.target;\\n\\t_keyboardEvent.event = event;\\n\\treturn _keyboardEvent;\\n}\\nfunction toKeyCode(s) {\\n\\tif (typeof s === \\\"string\\\") {\\n\\t\\treturn s.toUpperCase().charCodeAt(0);\\n\\t}\\n\\treturn s;\\n}\\nconst _keyCodeToKeyIdentifier = {\\n\\t\\\"9\\\": \\\"Tab\\\",\\n\\t\\\"13\\\": \\\"Enter\\\",\\n\\t\\\"16\\\": \\\"Shift\\\",\\n\\t\\\"17\\\": \\\"Control\\\",\\n\\t\\\"18\\\": \\\"Alt\\\",\\n\\t\\\"27\\\": \\\"Escape\\\",\\n\\t\\\"37\\\": \\\"Left\\\",\\n\\t\\\"38\\\": \\\"Up\\\",\\n\\t\\\"39\\\": \\\"Right\\\",\\n\\t\\\"40\\\": \\\"Down\\\",\\n\\t\\\"46\\\": \\\"Delete\\\",\\n\\t\\\"91\\\": \\\"Win\\\"\\n};\\nclass Keyboard extends EventHandler {\\n\\tstatic EVENT_KEYDOWN = \\\"keydown\\\";\\n\\tstatic EVENT_KEYUP = \\\"keyup\\\";\\n\\t_element = null;\\n\\t_keymap = {};\\n\\t_lastmap = {};\\n\\t_keyDownHandler;\\n\\t_keyUpHandler;\\n\\t_keyPressHandler;\\n\\t_visibilityChangeHandler;\\n\\t_windowBlurHandler;\\n\\tpreventDefault;\\n\\tstopPropagation;\\n\\tconstructor(element, options = {}) {\\n\\t\\tsuper();\\n\\t\\tthis._keyDownHandler = this._handleKeyDown.bind(this);\\n\\t\\tthis._keyUpHandler = this._handleKeyUp.bind(this);\\n\\t\\tthis._keyPressHandler = this._handleKeyPress.bind(this);\\n\\t\\tthis._visibilityChangeHandler = this._handleVisibilityChange.bind(this);\\n\\t\\tthis._windowBlurHandler = this._handleWindowBlur.bind(this);\\n\\t\\tif (element) {\\n\\t\\t\\tthis.attach(element);\\n\\t\\t}\\n\\t\\tthis.preventDefault = options.preventDefault || false;\\n\\t\\tthis.stopPropagation = options.stopPropagation || false;\\n\\t}\\n\\tattach(element) {\\n\\t\\tif (this._element) {\\n\\t\\t\\tthis.detach();\\n\\t\\t}\\n\\t\\tthis._element = element;\\n\\t\\tthis._element.addEventListener(\\\"keydown\\\", this._keyDownHandler, false);\\n\\t\\tthis._element.addEventListener(\\\"keypress\\\", this._keyPressHandler, false);\\n\\t\\tthis._element.addEventListener(\\\"keyup\\\", this._keyUpHandler, false);\\n\\t\\tdocument.addEventListener(\\\"visibilitychange\\\", this._visibilityChangeHandler, false);\\n\\t\\twindow.addEventListener(\\\"blur\\\", this._windowBlurHandler, false);\\n\\t}\\n\\tdetach() {\\n\\t\\tif (!this._element) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._element.removeEventListener(\\\"keydown\\\", this._keyDownHandler);\\n\\t\\tthis._element.removeEventListener(\\\"keypress\\\", this._keyPressHandler);\\n\\t\\tthis._element.removeEventListener(\\\"keyup\\\", this._keyUpHandler);\\n\\t\\tthis._element = null;\\n\\t\\tdocument.removeEventListener(\\\"visibilitychange\\\", this._visibilityChangeHandler, false);\\n\\t\\twindow.removeEventListener(\\\"blur\\\", this._windowBlurHandler, false);\\n\\t}\\n\\ttoKeyIdentifier(keyCode) {\\n\\t\\tkeyCode = toKeyCode(keyCode);\\n\\t\\tconst id = _keyCodeToKeyIdentifier[keyCode.toString()];\\n\\t\\tif (id) {\\n\\t\\t\\treturn id;\\n\\t\\t}\\n\\t\\tlet hex = keyCode.toString(16).toUpperCase();\\n\\t\\tconst length = hex.length;\\n\\t\\tfor (let count = 0; count < 4 - length; count++) {\\n\\t\\t\\thex = `0${hex}`;\\n\\t\\t}\\n\\t\\treturn `U+${hex}`;\\n\\t}\\n\\t_handleKeyDown(event) {\\n\\t\\tconst code = event.keyCode || event.charCode;\\n\\t\\tif (code === void 0) return;\\n\\t\\tconst id = this.toKeyIdentifier(code);\\n\\t\\tthis._keymap[id] = true;\\n\\t\\tthis.fire(\\\"keydown\\\", makeKeyboardEvent(event));\\n\\t\\tif (this.preventDefault) {\\n\\t\\t\\tevent.preventDefault();\\n\\t\\t}\\n\\t\\tif (this.stopPropagation) {\\n\\t\\t\\tevent.stopPropagation();\\n\\t\\t}\\n\\t}\\n\\t_handleKeyUp(event) {\\n\\t\\tconst code = event.keyCode || event.charCode;\\n\\t\\tif (code === void 0) return;\\n\\t\\tconst id = this.toKeyIdentifier(code);\\n\\t\\tdelete this._keymap[id];\\n\\t\\tthis.fire(\\\"keyup\\\", makeKeyboardEvent(event));\\n\\t\\tif (this.preventDefault) {\\n\\t\\t\\tevent.preventDefault();\\n\\t\\t}\\n\\t\\tif (this.stopPropagation) {\\n\\t\\t\\tevent.stopPropagation();\\n\\t\\t}\\n\\t}\\n\\t_handleKeyPress(event) {\\n\\t\\tthis.fire(\\\"keypress\\\", makeKeyboardEvent(event));\\n\\t\\tif (this.preventDefault) {\\n\\t\\t\\tevent.preventDefault();\\n\\t\\t}\\n\\t\\tif (this.stopPropagation) {\\n\\t\\t\\tevent.stopPropagation();\\n\\t\\t}\\n\\t}\\n\\t_handleVisibilityChange() {\\n\\t\\tif (document.visibilityState === \\\"hidden\\\") {\\n\\t\\t\\tthis._handleWindowBlur();\\n\\t\\t}\\n\\t}\\n\\t_handleWindowBlur() {\\n\\t\\tthis._keymap = {};\\n\\t\\tthis._lastmap = {};\\n\\t}\\n\\tupdate() {\\n\\t\\tfor (const prop in this._lastmap) {\\n\\t\\t\\tdelete this._lastmap[prop];\\n\\t\\t}\\n\\t\\tfor (const prop in this._keymap) {\\n\\t\\t\\tif (this._keymap.hasOwnProperty(prop)) {\\n\\t\\t\\t\\tthis._lastmap[prop] = this._keymap[prop];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tisPressed(key) {\\n\\t\\tconst keyCode = toKeyCode(key);\\n\\t\\tconst id = this.toKeyIdentifier(keyCode);\\n\\t\\treturn !!this._keymap[id];\\n\\t}\\n\\twasPressed(key) {\\n\\t\\tconst keyCode = toKeyCode(key);\\n\\t\\tconst id = this.toKeyIdentifier(keyCode);\\n\\t\\treturn !!this._keymap[id] && !!!this._lastmap[id];\\n\\t}\\n\\twasReleased(key) {\\n\\t\\tconst keyCode = toKeyCode(key);\\n\\t\\tconst id = this.toKeyIdentifier(keyCode);\\n\\t\\treturn !!!this._keymap[id] && !!this._lastmap[id];\\n\\t}\\n}\\n\\nfunction isMousePointerLocked() {\\n\\treturn !!(document.pointerLockElement || document.mozPointerLockElement || document.webkitPointerLockElement);\\n}\\nlet MouseEvent$1 = class MouseEvent {\\n\\tx = 0;\\n\\ty = 0;\\n\\tdx = 0;\\n\\tdy = 0;\\n\\tbutton = MOUSEBUTTON_NONE;\\n\\tbuttons;\\n\\twheelDelta = 0;\\n\\telement;\\n\\tctrlKey = false;\\n\\taltKey = false;\\n\\tshiftKey = false;\\n\\tmetaKey = false;\\n\\tevent;\\n\\tconstructor(mouse, event) {\\n\\t\\tlet coords = {\\n\\t\\t\\tx: 0,\\n\\t\\t\\ty: 0\\n\\t\\t};\\n\\t\\tif (event) {\\n\\t\\t\\tif (event instanceof MouseEvent) {\\n\\t\\t\\t\\tthrow Error(\\\"Expected MouseEvent\\\");\\n\\t\\t\\t}\\n\\t\\t\\tcoords = mouse._getTargetCoords(event);\\n\\t\\t} else {\\n\\t\\t\\tevent = {};\\n\\t\\t}\\n\\t\\tif (coords) {\\n\\t\\t\\tthis.x = coords.x;\\n\\t\\t\\tthis.y = coords.y;\\n\\t\\t} else if (isMousePointerLocked()) {\\n\\t\\t\\tthis.x = 0;\\n\\t\\t\\tthis.y = 0;\\n\\t\\t} else {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (event.type === \\\"wheel\\\") {\\n\\t\\t\\tif (event.deltaY > 0) {\\n\\t\\t\\t\\tthis.wheelDelta = 1;\\n\\t\\t\\t} else if (event.deltaY < 0) {\\n\\t\\t\\t\\tthis.wheelDelta = -1;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (isMousePointerLocked()) {\\n\\t\\t\\tthis.dx = event.movementX || event.webkitMovementX || event.mozMovementX || 0;\\n\\t\\t\\tthis.dy = event.movementY || event.webkitMovementY || event.mozMovementY || 0;\\n\\t\\t} else {\\n\\t\\t\\tthis.dx = this.x - mouse._lastX;\\n\\t\\t\\tthis.dy = this.y - mouse._lastY;\\n\\t\\t}\\n\\t\\tif (event.type === \\\"mousedown\\\" || event.type === \\\"mouseup\\\") {\\n\\t\\t\\tthis.button = event.button;\\n\\t\\t}\\n\\t\\tthis.buttons = mouse._buttons.slice(0);\\n\\t\\tthis.element = event.target;\\n\\t\\tthis.ctrlKey = event.ctrlKey ?? false;\\n\\t\\tthis.altKey = event.altKey ?? false;\\n\\t\\tthis.shiftKey = event.shiftKey ?? false;\\n\\t\\tthis.metaKey = event.metaKey ?? false;\\n\\t\\tthis.event = event;\\n\\t}\\n};\\n\\nclass Mouse extends EventHandler {\\n\\tstatic EVENT_MOUSEMOVE = \\\"mousemove\\\";\\n\\tstatic EVENT_MOUSEDOWN = \\\"mousedown\\\";\\n\\tstatic EVENT_MOUSEUP = \\\"mouseup\\\";\\n\\tstatic EVENT_MOUSEWHEEL = \\\"mousewheel\\\";\\n\\t_lastX = 0;\\n\\t_lastY = 0;\\n\\t_buttons = [false, false, false];\\n\\t_lastbuttons = [false, false, false];\\n\\t_target = null;\\n\\t_attached = false;\\n\\t_upHandler;\\n\\t_downHandler;\\n\\t_moveHandler;\\n\\t_wheelHandler;\\n\\t_contextMenuHandler;\\n\\tconstructor(element) {\\n\\t\\tsuper();\\n\\t\\tthis._upHandler = this._handleUp.bind(this);\\n\\t\\tthis._downHandler = this._handleDown.bind(this);\\n\\t\\tthis._moveHandler = this._handleMove.bind(this);\\n\\t\\tthis._wheelHandler = this._handleWheel.bind(this);\\n\\t\\tthis._contextMenuHandler = (event) => {\\n\\t\\t\\tevent.preventDefault();\\n\\t\\t};\\n\\t\\tthis.attach(element);\\n\\t}\\n\\tstatic isPointerLocked() {\\n\\t\\treturn isMousePointerLocked();\\n\\t}\\n\\tattach(element) {\\n\\t\\tthis._target = element;\\n\\t\\tif (this._attached) return;\\n\\t\\tthis._attached = true;\\n\\t\\tconst passiveOptions = { passive: false };\\n\\t\\tconst options = platform.passiveEvents ? passiveOptions : false;\\n\\t\\twindow.addEventListener(\\\"mouseup\\\", this._upHandler, options);\\n\\t\\twindow.addEventListener(\\\"mousedown\\\", this._downHandler, options);\\n\\t\\twindow.addEventListener(\\\"mousemove\\\", this._moveHandler, options);\\n\\t\\twindow.addEventListener(\\\"wheel\\\", this._wheelHandler, options);\\n\\t}\\n\\tdetach() {\\n\\t\\tif (!this._attached) return;\\n\\t\\tthis._attached = false;\\n\\t\\tthis._target = null;\\n\\t\\tconst passiveOptions = { passive: false };\\n\\t\\tconst options = platform.passiveEvents ? passiveOptions : false;\\n\\t\\twindow.removeEventListener(\\\"mouseup\\\", this._upHandler, options);\\n\\t\\twindow.removeEventListener(\\\"mousedown\\\", this._downHandler, options);\\n\\t\\twindow.removeEventListener(\\\"mousemove\\\", this._moveHandler, options);\\n\\t\\twindow.removeEventListener(\\\"wheel\\\", this._wheelHandler, options);\\n\\t}\\n\\tdisableContextMenu() {\\n\\t\\tif (!this._target) return;\\n\\t\\tthis._target.addEventListener(\\\"contextmenu\\\", this._contextMenuHandler);\\n\\t}\\n\\tenableContextMenu() {\\n\\t\\tif (!this._target) return;\\n\\t\\tthis._target.removeEventListener(\\\"contextmenu\\\", this._contextMenuHandler);\\n\\t}\\n\\tenablePointerLock(success, error) {\\n\\t\\tif (!document.body.requestPointerLock) {\\n\\t\\t\\tif (error) {\\n\\t\\t\\t\\terror();\\n\\t\\t\\t}\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst s = () => {\\n\\t\\t\\tsuccess();\\n\\t\\t\\tdocument.removeEventListener(\\\"pointerlockchange\\\", s);\\n\\t\\t};\\n\\t\\tconst e = () => {\\n\\t\\t\\terror();\\n\\t\\t\\tdocument.removeEventListener(\\\"pointerlockerror\\\", e);\\n\\t\\t};\\n\\t\\tif (success) {\\n\\t\\t\\tdocument.addEventListener(\\\"pointerlockchange\\\", s, false);\\n\\t\\t}\\n\\t\\tif (error) {\\n\\t\\t\\tdocument.addEventListener(\\\"pointerlockerror\\\", e, false);\\n\\t\\t}\\n\\t\\tdocument.body.requestPointerLock();\\n\\t}\\n\\tdisablePointerLock(success) {\\n\\t\\tif (!document.exitPointerLock) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst s = () => {\\n\\t\\t\\tsuccess();\\n\\t\\t\\tdocument.removeEventListener(\\\"pointerlockchange\\\", s);\\n\\t\\t};\\n\\t\\tif (success) {\\n\\t\\t\\tdocument.addEventListener(\\\"pointerlockchange\\\", s, false);\\n\\t\\t}\\n\\t\\tdocument.exitPointerLock();\\n\\t}\\n\\tupdate() {\\n\\t\\tthis._lastbuttons[0] = this._buttons[0];\\n\\t\\tthis._lastbuttons[1] = this._buttons[1];\\n\\t\\tthis._lastbuttons[2] = this._buttons[2];\\n\\t}\\n\\tisPressed(button) {\\n\\t\\treturn this._buttons[button];\\n\\t}\\n\\twasPressed(button) {\\n\\t\\treturn this._buttons[button] && !this._lastbuttons[button];\\n\\t}\\n\\twasReleased(button) {\\n\\t\\treturn !this._buttons[button] && this._lastbuttons[button];\\n\\t}\\n\\t_handleUp(event) {\\n\\t\\tthis._buttons[event.button] = false;\\n\\t\\tconst e = new MouseEvent$1(this, event);\\n\\t\\tif (!e.event) return;\\n\\t\\tthis.fire(\\\"mouseup\\\", e);\\n\\t}\\n\\t_handleDown(event) {\\n\\t\\tthis._buttons[event.button] = true;\\n\\t\\tconst e = new MouseEvent$1(this, event);\\n\\t\\tif (!e.event) return;\\n\\t\\tthis.fire(\\\"mousedown\\\", e);\\n\\t}\\n\\t_handleMove(event) {\\n\\t\\tconst e = new MouseEvent$1(this, event);\\n\\t\\tif (!e.event) return;\\n\\t\\tthis.fire(\\\"mousemove\\\", e);\\n\\t\\tthis._lastX = e.x;\\n\\t\\tthis._lastY = e.y;\\n\\t}\\n\\t_handleWheel(event) {\\n\\t\\tconst e = new MouseEvent$1(this, event);\\n\\t\\tif (!e.event) return;\\n\\t\\tthis.fire(\\\"mousewheel\\\", e);\\n\\t}\\n\\t_getTargetCoords(event) {\\n\\t\\tconst rect = this._target.getBoundingClientRect();\\n\\t\\tconst left = Math.floor(rect.left);\\n\\t\\tconst top = Math.floor(rect.top);\\n\\t\\tif (event.clientX < left || event.clientX >= left + this._target.clientWidth || event.clientY < top || event.clientY >= top + this._target.clientHeight) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\treturn {\\n\\t\\t\\tx: event.clientX - left,\\n\\t\\t\\ty: event.clientY - top\\n\\t\\t};\\n\\t}\\n}\\n\\nfunction getTouchTargetCoords(touch) {\\n\\tlet totalOffsetX = 0;\\n\\tlet totalOffsetY = 0;\\n\\tlet target = touch.target;\\n\\twhile (!(target instanceof HTMLElement) && target) {\\n\\t\\ttarget = target.parentNode;\\n\\t}\\n\\twhile (target) {\\n\\t\\ttotalOffsetX += target.offsetLeft - target.scrollLeft;\\n\\t\\ttotalOffsetY += target.offsetTop - target.scrollTop;\\n\\t\\ttarget = target.offsetParent;\\n\\t}\\n\\treturn {\\n\\t\\tx: touch.pageX - totalOffsetX,\\n\\t\\ty: touch.pageY - totalOffsetY\\n\\t};\\n}\\nclass Touch {\\n\\tid;\\n\\tx;\\n\\ty;\\n\\ttarget;\\n\\ttouch;\\n\\tconstructor(touch) {\\n\\t\\tconst coords = getTouchTargetCoords(touch);\\n\\t\\tthis.id = touch.identifier;\\n\\t\\tthis.x = coords.x;\\n\\t\\tthis.y = coords.y;\\n\\t\\tthis.target = touch.target;\\n\\t\\tthis.touch = touch;\\n\\t}\\n}\\nclass TouchEvent {\\n\\telement;\\n\\tevent;\\n\\ttouches = [];\\n\\tchangedTouches = [];\\n\\tconstructor(device, event) {\\n\\t\\tthis.element = event.target;\\n\\t\\tthis.event = event;\\n\\t\\tthis.touches = Array.from(event.touches).map((touch) => new Touch(touch));\\n\\t\\tthis.changedTouches = Array.from(event.changedTouches).map((touch) => new Touch(touch));\\n\\t}\\n\\tgetTouchById(id, list) {\\n\\t\\treturn list.find((touch) => touch.id === id) || null;\\n\\t}\\n}\\n\\nlet TouchDevice$1 = class TouchDevice extends EventHandler {\\n\\tstatic EVENT_TOUCHSTART = \\\"touchstart\\\";\\n\\tstatic EVENT_TOUCHEND = \\\"touchend\\\";\\n\\tstatic EVENT_TOUCHMOVE = \\\"touchmove\\\";\\n\\tstatic EVENT_TOUCHCANCEL = \\\"touchcancel\\\";\\n\\t_element = null;\\n\\t_startHandler;\\n\\t_endHandler;\\n\\t_moveHandler;\\n\\t_cancelHandler;\\n\\tconstructor(element) {\\n\\t\\tsuper();\\n\\t\\tthis._startHandler = this._handleTouchStart.bind(this);\\n\\t\\tthis._endHandler = this._handleTouchEnd.bind(this);\\n\\t\\tthis._moveHandler = this._handleTouchMove.bind(this);\\n\\t\\tthis._cancelHandler = this._handleTouchCancel.bind(this);\\n\\t\\tthis.attach(element);\\n\\t}\\n\\tattach(element) {\\n\\t\\tif (this._element) {\\n\\t\\t\\tthis.detach();\\n\\t\\t}\\n\\t\\tthis._element = element;\\n\\t\\tthis._element.addEventListener(\\\"touchstart\\\", this._startHandler, false);\\n\\t\\tthis._element.addEventListener(\\\"touchend\\\", this._endHandler, false);\\n\\t\\tthis._element.addEventListener(\\\"touchmove\\\", this._moveHandler, false);\\n\\t\\tthis._element.addEventListener(\\\"touchcancel\\\", this._cancelHandler, false);\\n\\t}\\n\\tdetach() {\\n\\t\\tif (this._element) {\\n\\t\\t\\tthis._element.removeEventListener(\\\"touchstart\\\", this._startHandler, false);\\n\\t\\t\\tthis._element.removeEventListener(\\\"touchend\\\", this._endHandler, false);\\n\\t\\t\\tthis._element.removeEventListener(\\\"touchmove\\\", this._moveHandler, false);\\n\\t\\t\\tthis._element.removeEventListener(\\\"touchcancel\\\", this._cancelHandler, false);\\n\\t\\t}\\n\\t\\tthis._element = null;\\n\\t}\\n\\t_handleTouchStart(e) {\\n\\t\\tthis.fire(\\\"touchstart\\\", new TouchEvent(this, e));\\n\\t}\\n\\t_handleTouchEnd(e) {\\n\\t\\tthis.fire(\\\"touchend\\\", new TouchEvent(this, e));\\n\\t}\\n\\t_handleTouchMove(e) {\\n\\t\\te.preventDefault();\\n\\t\\tthis.fire(\\\"touchmove\\\", new TouchEvent(this, e));\\n\\t}\\n\\t_handleTouchCancel(e) {\\n\\t\\tthis.fire(\\\"touchcancel\\\", new TouchEvent(this, e));\\n\\t}\\n};\\n\\nclass Http {\\n\\tstatic ContentType = {\\n\\t\\tAAC: \\\"audio/aac\\\",\\n\\t\\tBASIS: \\\"image/basis\\\",\\n\\t\\tBIN: \\\"application/octet-stream\\\",\\n\\t\\tDDS: \\\"image/dds\\\",\\n\\t\\tFORM_URLENCODED: \\\"application/x-www-form-urlencoded\\\",\\n\\t\\tGIF: \\\"image/gif\\\",\\n\\t\\tGLB: \\\"model/gltf-binary\\\",\\n\\t\\tJPEG: \\\"image/jpeg\\\",\\n\\t\\tJSON: \\\"application/json\\\",\\n\\t\\tMP3: \\\"audio/mpeg\\\",\\n\\t\\tMP4: \\\"audio/mp4\\\",\\n\\t\\tOGG: \\\"audio/ogg\\\",\\n\\t\\tOPUS: 'audio/ogg; codecs=\\\"opus\\\"',\\n\\t\\tPNG: \\\"image/png\\\",\\n\\t\\tTEXT: \\\"text/plain\\\",\\n\\t\\tWAV: \\\"audio/x-wav\\\",\\n\\t\\tXML: \\\"application/xml\\\"\\n\\t};\\n\\tstatic ResponseType = {\\n\\t\\tTEXT: \\\"text\\\",\\n\\t\\tARRAY_BUFFER: \\\"arraybuffer\\\",\\n\\t\\tBLOB: \\\"blob\\\",\\n\\t\\tDOCUMENT: \\\"document\\\",\\n\\t\\tJSON: \\\"json\\\"\\n\\t};\\n\\tstatic binaryExtensions = [\\n\\t\\t\\\".model\\\",\\n\\t\\t\\\".wav\\\",\\n\\t\\t\\\".ogg\\\",\\n\\t\\t\\\".mp3\\\",\\n\\t\\t\\\".mp4\\\",\\n\\t\\t\\\".m4a\\\",\\n\\t\\t\\\".aac\\\",\\n\\t\\t\\\".dds\\\",\\n\\t\\t\\\".basis\\\",\\n\\t\\t\\\".glb\\\",\\n\\t\\t\\\".opus\\\"\\n\\t];\\n\\tstatic retryDelay = 100;\\n\\tget(url, options, callback) {\\n\\t\\tif (typeof options === \\\"function\\\") {\\n\\t\\t\\tcallback = options;\\n\\t\\t\\toptions = {};\\n\\t\\t}\\n\\t\\tconst result = this.request(\\\"GET\\\", url, options, callback);\\n\\t\\tconst { progress } = options;\\n\\t\\tif (progress) {\\n\\t\\t\\tconst handler = (event) => {\\n\\t\\t\\t\\tif (event.lengthComputable) {\\n\\t\\t\\t\\t\\tprogress.fire(\\\"progress\\\", event.loaded, event.total);\\n\\t\\t\\t\\t}\\n\\t\\t\\t};\\n\\t\\t\\tconst endHandler = (event) => {\\n\\t\\t\\t\\thandler(event);\\n\\t\\t\\t\\tresult.removeEventListener(\\\"loadstart\\\", handler);\\n\\t\\t\\t\\tresult.removeEventListener(\\\"progress\\\", handler);\\n\\t\\t\\t\\tresult.removeEventListener(\\\"loadend\\\", endHandler);\\n\\t\\t\\t};\\n\\t\\t\\tresult.addEventListener(\\\"loadstart\\\", handler);\\n\\t\\t\\tresult.addEventListener(\\\"progress\\\", handler);\\n\\t\\t\\tresult.addEventListener(\\\"loadend\\\", endHandler);\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n\\tpost(url, data, options, callback) {\\n\\t\\tif (typeof options === \\\"function\\\") {\\n\\t\\t\\tcallback = options;\\n\\t\\t\\toptions = {};\\n\\t\\t}\\n\\t\\toptions.postdata = data;\\n\\t\\treturn this.request(\\\"POST\\\", url, options, callback);\\n\\t}\\n\\tput(url, data, options, callback) {\\n\\t\\tif (typeof options === \\\"function\\\") {\\n\\t\\t\\tcallback = options;\\n\\t\\t\\toptions = {};\\n\\t\\t}\\n\\t\\toptions.postdata = data;\\n\\t\\treturn this.request(\\\"PUT\\\", url, options, callback);\\n\\t}\\n\\tdel(url, options, callback) {\\n\\t\\tif (typeof options === \\\"function\\\") {\\n\\t\\t\\tcallback = options;\\n\\t\\t\\toptions = {};\\n\\t\\t}\\n\\t\\treturn this.request(\\\"DELETE\\\", url, options, callback);\\n\\t}\\n\\trequest(method, url, options, callback) {\\n\\t\\tlet uri, query, postdata;\\n\\t\\tlet errored = false;\\n\\t\\tif (typeof options === \\\"function\\\") {\\n\\t\\t\\tcallback = options;\\n\\t\\t\\toptions = {};\\n\\t\\t}\\n\\t\\tif (options.retry) {\\n\\t\\t\\toptions = Object.assign({\\n\\t\\t\\t\\tretries: 0,\\n\\t\\t\\t\\tmaxRetries: 5\\n\\t\\t\\t}, options);\\n\\t\\t}\\n\\t\\toptions.callback = callback;\\n\\t\\tif (options.async == null) {\\n\\t\\t\\toptions.async = true;\\n\\t\\t}\\n\\t\\tif (options.headers == null) {\\n\\t\\t\\toptions.headers = {};\\n\\t\\t}\\n\\t\\tif (options.postdata != null) {\\n\\t\\t\\tif (options.postdata instanceof Document) {\\n\\t\\t\\t\\tpostdata = options.postdata;\\n\\t\\t\\t} else if (options.postdata instanceof FormData) {\\n\\t\\t\\t\\tpostdata = options.postdata;\\n\\t\\t\\t} else if (options.postdata instanceof Object) {\\n\\t\\t\\t\\tlet contentType = options.headers[\\\"Content-Type\\\"];\\n\\t\\t\\t\\tif (contentType === void 0) {\\n\\t\\t\\t\\t\\toptions.headers[\\\"Content-Type\\\"] = Http.ContentType.FORM_URLENCODED;\\n\\t\\t\\t\\t\\tcontentType = options.headers[\\\"Content-Type\\\"];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tswitch (contentType) {\\n\\t\\t\\t\\t\\tcase Http.ContentType.FORM_URLENCODED: {\\n\\t\\t\\t\\t\\t\\tpostdata = \\\"\\\";\\n\\t\\t\\t\\t\\t\\tlet bFirstItem = true;\\n\\t\\t\\t\\t\\t\\tfor (const key in options.postdata) {\\n\\t\\t\\t\\t\\t\\t\\tif (options.postdata.hasOwnProperty(key)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (bFirstItem) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbFirstItem = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tpostdata += \\\"&\\\";\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst encodedKey = encodeURIComponent(key);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst encodedValue = encodeURIComponent(options.postdata[key]);\\n\\t\\t\\t\\t\\t\\t\\t\\tpostdata += `${encodedKey}=${encodedValue}`;\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\tcase Http.ContentType.JSON:\\n\\t\\t\\t\\t\\t\\tif (contentType == null) {\\n\\t\\t\\t\\t\\t\\t\\toptions.headers[\\\"Content-Type\\\"] = Http.ContentType.JSON;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tpostdata = JSON.stringify(options.postdata);\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tpostdata = options.postdata;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (options.cache === false) {\\n\\t\\t\\tconst timestamp = now();\\n\\t\\t\\turi = new URI(url);\\n\\t\\t\\tif (!uri.query) {\\n\\t\\t\\t\\turi.query = `ts=${timestamp}`;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\turi.query = `${uri.query}&ts=${timestamp}`;\\n\\t\\t\\t}\\n\\t\\t\\turl = uri.toString();\\n\\t\\t}\\n\\t\\tif (options.query) {\\n\\t\\t\\turi = new URI(url);\\n\\t\\t\\tquery = extend(uri.getQuery(), options.query);\\n\\t\\t\\turi.setQuery(query);\\n\\t\\t\\turl = uri.toString();\\n\\t\\t}\\n\\t\\tconst xhr = new XMLHttpRequest();\\n\\t\\txhr.open(method, url, options.async);\\n\\t\\txhr.withCredentials = options.withCredentials !== void 0 ? options.withCredentials : false;\\n\\t\\txhr.responseType = options.responseType || this._guessResponseType(url);\\n\\t\\tfor (const header in options.headers) {\\n\\t\\t\\tif (options.headers.hasOwnProperty(header)) {\\n\\t\\t\\t\\txhr.setRequestHeader(header, options.headers[header]);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\txhr.onreadystatechange = () => {\\n\\t\\t\\tthis._onReadyStateChange(method, url, options, xhr);\\n\\t\\t};\\n\\t\\txhr.onerror = () => {\\n\\t\\t\\tthis._onError(method, url, options, xhr);\\n\\t\\t\\terrored = true;\\n\\t\\t};\\n\\t\\ttry {\\n\\t\\t\\txhr.send(postdata);\\n\\t\\t} catch (e) {\\n\\t\\t\\tif (!errored) {\\n\\t\\t\\t\\toptions.error(xhr.status, xhr, e);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn xhr;\\n\\t}\\n\\t_guessResponseType(url) {\\n\\t\\tconst uri = new URI(url);\\n\\t\\tconst ext = path.getExtension(uri.path).toLowerCase();\\n\\t\\tif (Http.binaryExtensions.indexOf(ext) >= 0) {\\n\\t\\t\\treturn Http.ResponseType.ARRAY_BUFFER;\\n\\t\\t} else if (ext === \\\".json\\\") {\\n\\t\\t\\treturn Http.ResponseType.JSON;\\n\\t\\t} else if (ext === \\\".xml\\\") {\\n\\t\\t\\treturn Http.ResponseType.DOCUMENT;\\n\\t\\t}\\n\\t\\treturn Http.ResponseType.TEXT;\\n\\t}\\n\\t_isBinaryContentType(contentType) {\\n\\t\\tconst binTypes = [\\n\\t\\t\\tHttp.ContentType.BASIS,\\n\\t\\t\\tHttp.ContentType.BIN,\\n\\t\\t\\tHttp.ContentType.DDS,\\n\\t\\t\\tHttp.ContentType.GLB,\\n\\t\\t\\tHttp.ContentType.MP3,\\n\\t\\t\\tHttp.ContentType.MP4,\\n\\t\\t\\tHttp.ContentType.OGG,\\n\\t\\t\\tHttp.ContentType.OPUS,\\n\\t\\t\\tHttp.ContentType.WAV\\n\\t\\t];\\n\\t\\tif (binTypes.indexOf(contentType) >= 0) {\\n\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\treturn false;\\n\\t}\\n\\t_isBinaryResponseType(responseType) {\\n\\t\\treturn responseType === Http.ResponseType.ARRAY_BUFFER || responseType === Http.ResponseType.BLOB || responseType === Http.ResponseType.JSON;\\n\\t}\\n\\t_onReadyStateChange(method, url, options, xhr) {\\n\\t\\tif (xhr.readyState === 4) {\\n\\t\\t\\tswitch (xhr.status) {\\n\\t\\t\\t\\tcase 0: {\\n\\t\\t\\t\\t\\tif (xhr.responseURL && xhr.responseURL.startsWith(\\\"file:///\\\")) {\\n\\t\\t\\t\\t\\t\\tthis._onSuccess(method, url, options, xhr);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._onError(method, url, options, xhr);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcase 200:\\n\\t\\t\\t\\tcase 201:\\n\\t\\t\\t\\tcase 206:\\n\\t\\t\\t\\tcase 304: {\\n\\t\\t\\t\\t\\tthis._onSuccess(method, url, options, xhr);\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdefault: {\\n\\t\\t\\t\\t\\tthis._onError(method, url, options, xhr);\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_onSuccess(method, url, options, xhr) {\\n\\t\\tlet response;\\n\\t\\tlet contentType;\\n\\t\\tconst header = xhr.getResponseHeader(\\\"Content-Type\\\");\\n\\t\\tif (header) {\\n\\t\\t\\tconst parts = header.split(\\\";\\\");\\n\\t\\t\\tcontentType = parts[0].trim();\\n\\t\\t}\\n\\t\\ttry {\\n\\t\\t\\tif (this._isBinaryContentType(contentType) || this._isBinaryResponseType(xhr.responseType)) {\\n\\t\\t\\t\\tresponse = xhr.response;\\n\\t\\t\\t} else if (contentType === Http.ContentType.JSON || url.split(\\\"?\\\")[0].endsWith(\\\".json\\\")) {\\n\\t\\t\\t\\tresponse = JSON.parse(xhr.responseText);\\n\\t\\t\\t} else if (xhr.responseType === Http.ResponseType.DOCUMENT || contentType === Http.ContentType.XML) {\\n\\t\\t\\t\\tresponse = xhr.responseXML;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tresponse = xhr.responseText;\\n\\t\\t\\t}\\n\\t\\t\\toptions.callback(null, response);\\n\\t\\t} catch (err) {\\n\\t\\t\\toptions.callback(err);\\n\\t\\t}\\n\\t}\\n\\t_onError(method, url, options, xhr) {\\n\\t\\tif (options.retrying) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (options.retry && options.retries < options.maxRetries) {\\n\\t\\t\\toptions.retries++;\\n\\t\\t\\toptions.retrying = true;\\n\\t\\t\\tconst retryDelay = math.clamp(Math.pow(2, options.retries) * Http.retryDelay, 0, options.maxRetryDelay || 5e3);\\n\\t\\t\\tconsole.log(`${method}: ${url} - Error ${xhr.status}. Retrying in ${retryDelay} ms`);\\n\\t\\t\\tsetTimeout(() => {\\n\\t\\t\\t\\toptions.retrying = false;\\n\\t\\t\\t\\tthis.request(method, url, options, options.callback);\\n\\t\\t\\t}, retryDelay);\\n\\t\\t} else {\\n\\t\\t\\toptions.callback(xhr.status === 0 ? \\\"Network error\\\" : xhr.status, null);\\n\\t\\t}\\n\\t}\\n}\\nconst http = new Http();\\n\\nconst BLEND_SUBTRACTIVE = 0;\\nconst BLEND_ADDITIVE = 1;\\nconst BLEND_NORMAL = 2;\\nconst BLEND_NONE = 3;\\nconst BLEND_PREMULTIPLIED = 4;\\nconst BLEND_MULTIPLICATIVE = 5;\\nconst BLEND_ADDITIVEALPHA = 6;\\nconst BLEND_MULTIPLICATIVE2X = 7;\\nconst BLEND_SCREEN = 8;\\nconst BLEND_MIN = 9;\\nconst BLEND_MAX = 10;\\nconst blendNames = {\\n\\t[BLEND_SUBTRACTIVE]: \\\"SUBTRACTIVE\\\",\\n\\t[BLEND_ADDITIVE]: \\\"ADDITIVE\\\",\\n\\t[BLEND_NORMAL]: \\\"NORMAL\\\",\\n\\t[BLEND_NONE]: \\\"NONE\\\",\\n\\t[BLEND_PREMULTIPLIED]: \\\"PREMULTIPLIED\\\",\\n\\t[BLEND_MULTIPLICATIVE]: \\\"MULTIPLICATIVE\\\",\\n\\t[BLEND_ADDITIVEALPHA]: \\\"ADDITIVEALPHA\\\",\\n\\t[BLEND_MULTIPLICATIVE2X]: \\\"MULTIPLICATIVE2X\\\",\\n\\t[BLEND_SCREEN]: \\\"SCREEN\\\",\\n\\t[BLEND_MIN]: \\\"MIN\\\",\\n\\t[BLEND_MAX]: \\\"MAX\\\"\\n};\\nconst FOG_NONE = \\\"none\\\";\\nconst FOG_LINEAR = \\\"linear\\\";\\nconst FRESNEL_NONE = 0;\\nconst FRESNEL_SCHLICK = 2;\\nconst fresnelNames = {\\n\\t[FRESNEL_NONE]: \\\"NONE\\\",\\n\\t[FRESNEL_SCHLICK]: \\\"SCHLICK\\\"\\n};\\nconst LAYER_WORLD = 15;\\nconst LAYERID_WORLD = 0;\\nconst LAYERID_DEPTH = 1;\\nconst LAYERID_SKYBOX = 2;\\nconst LAYERID_IMMEDIATE = 3;\\nconst LAYERID_UI = 4;\\nconst LIGHTTYPE_DIRECTIONAL = 0;\\nconst LIGHTTYPE_OMNI = 1;\\nconst LIGHTTYPE_SPOT = 2;\\nconst lightTypeNames = {\\n\\t[LIGHTTYPE_DIRECTIONAL]: \\\"DIRECTIONAL\\\",\\n\\t[LIGHTTYPE_OMNI]: \\\"OMNI\\\",\\n\\t[LIGHTTYPE_SPOT]: \\\"SPOT\\\"\\n};\\nconst LIGHT_COLOR_DIVIDER = 100;\\nconst LIGHTSHAPE_PUNCTUAL = 0;\\nconst LIGHTSHAPE_RECT = 1;\\nconst LIGHTSHAPE_DISK = 2;\\nconst LIGHTSHAPE_SPHERE = 3;\\nconst lightShapeNames = {\\n\\t[LIGHTSHAPE_PUNCTUAL]: \\\"PUNCTUAL\\\",\\n\\t[LIGHTSHAPE_RECT]: \\\"RECT\\\",\\n\\t[LIGHTSHAPE_DISK]: \\\"DISK\\\",\\n\\t[LIGHTSHAPE_SPHERE]: \\\"SPHERE\\\"\\n};\\nconst LIGHTFALLOFF_LINEAR = 0;\\nconst LIGHTFALLOFF_INVERSESQUARED = 1;\\nconst lightFalloffNames = {\\n\\t[LIGHTFALLOFF_LINEAR]: \\\"LINEAR\\\",\\n\\t[LIGHTFALLOFF_INVERSESQUARED]: \\\"INVERSESQUARED\\\"\\n};\\nconst SHADOW_PCF3_32F = 0;\\nconst SHADOW_VSM_16F = 2;\\nconst SHADOW_VSM_32F = 3;\\nconst SHADOW_PCF5_32F = 4;\\nconst SHADOW_PCF1_32F = 5;\\nconst SHADOW_PCSS_32F = 6;\\nconst SHADOW_PCF1_16F = 7;\\nconst SHADOW_PCF3_16F = 8;\\nconst SHADOW_PCF5_16F = 9;\\nconst shadowTypeInfo = /* @__PURE__ */ new Map([\\n\\t[SHADOW_PCF1_32F, { name: \\\"PCF1_32F\\\", kind: \\\"PCF1\\\", format: PIXELFORMAT_DEPTH, pcf: true }],\\n\\t[SHADOW_PCF3_32F, { name: \\\"PCF3_32F\\\", kind: \\\"PCF3\\\", format: PIXELFORMAT_DEPTH, pcf: true }],\\n\\t[SHADOW_PCF5_32F, { name: \\\"PCF5_32F\\\", kind: \\\"PCF5\\\", format: PIXELFORMAT_DEPTH, pcf: true }],\\n\\t[SHADOW_PCF1_16F, { name: \\\"PCF1_16F\\\", kind: \\\"PCF1\\\", format: PIXELFORMAT_DEPTH16, pcf: true }],\\n\\t[SHADOW_PCF3_16F, { name: \\\"PCF3_16F\\\", kind: \\\"PCF3\\\", format: PIXELFORMAT_DEPTH16, pcf: true }],\\n\\t[SHADOW_PCF5_16F, { name: \\\"PCF5_16F\\\", kind: \\\"PCF5\\\", format: PIXELFORMAT_DEPTH16, pcf: true }],\\n\\t[SHADOW_VSM_16F, { name: \\\"VSM_16F\\\", kind: \\\"VSM\\\", format: PIXELFORMAT_RGBA16F, vsm: true }],\\n\\t[SHADOW_VSM_32F, { name: \\\"VSM_32F\\\", kind: \\\"VSM\\\", format: PIXELFORMAT_RGBA32F, vsm: true }],\\n\\t[SHADOW_PCSS_32F, { name: \\\"PCSS_32F\\\", kind: \\\"PCSS\\\", format: PIXELFORMAT_R32F, pcss: true }]\\n]);\\nconst SHADOW_CASCADE_ALL = 255;\\nconst BLUR_GAUSSIAN = 1;\\nconst PROJECTION_PERSPECTIVE = 0;\\nconst PROJECTION_ORTHOGRAPHIC = 1;\\nconst RENDERSTYLE_SOLID = 0;\\nconst RENDERSTYLE_WIREFRAME = 1;\\nconst RENDERSTYLE_POINTS = 2;\\nconst CUBEPROJ_NONE = 0;\\nconst CUBEPROJ_BOX = 1;\\nconst cubemaProjectionNames = {\\n\\t[CUBEPROJ_NONE]: \\\"NONE\\\",\\n\\t[CUBEPROJ_BOX]: \\\"BOX\\\"\\n};\\nconst DETAILMODE_MUL = \\\"mul\\\";\\nconst GAMMA_NONE = 0;\\nconst GAMMA_SRGB = 1;\\nconst gammaNames = {\\n\\t[GAMMA_NONE]: \\\"NONE\\\",\\n\\t[GAMMA_SRGB]: \\\"SRGB\\\"\\n};\\nconst TONEMAP_LINEAR = 0;\\nconst TONEMAP_FILMIC = 1;\\nconst TONEMAP_HEJL = 2;\\nconst TONEMAP_ACES = 3;\\nconst TONEMAP_ACES2 = 4;\\nconst TONEMAP_NEUTRAL = 5;\\nconst TONEMAP_NONE = 6;\\nconst tonemapNames = [\\n\\t\\\"LINEAR\\\",\\n\\t\\\"FILMIC\\\",\\n\\t\\\"HEJL\\\",\\n\\t\\\"ACES\\\",\\n\\t\\\"ACES2\\\",\\n\\t\\\"NEUTRAL\\\",\\n\\t\\\"NONE\\\"\\n];\\nconst SPECOCC_NONE = 0;\\nconst SPECOCC_AO = 1;\\nconst SPECOCC_GLOSSDEPENDENT = 2;\\nconst specularOcclusionNames = {\\n\\t[SPECOCC_NONE]: \\\"NONE\\\",\\n\\t[SPECOCC_AO]: \\\"AO\\\",\\n\\t[SPECOCC_GLOSSDEPENDENT]: \\\"GLOSSDEPENDENT\\\"\\n};\\nconst REFLECTIONSRC_NONE = \\\"none\\\";\\nconst REFLECTIONSRC_ENVATLAS = \\\"envAtlas\\\";\\nconst REFLECTIONSRC_ENVATLASHQ = \\\"envAtlasHQ\\\";\\nconst REFLECTIONSRC_CUBEMAP = \\\"cubeMap\\\";\\nconst REFLECTIONSRC_SPHEREMAP = \\\"sphereMap\\\";\\nconst reflectionSrcNames = {\\n\\t[REFLECTIONSRC_NONE]: \\\"NONE\\\",\\n\\t[REFLECTIONSRC_ENVATLAS]: \\\"ENVATLAS\\\",\\n\\t[REFLECTIONSRC_ENVATLASHQ]: \\\"ENVATLASHQ\\\",\\n\\t[REFLECTIONSRC_CUBEMAP]: \\\"CUBEMAP\\\",\\n\\t[REFLECTIONSRC_SPHEREMAP]: \\\"SPHEREMAP\\\"\\n};\\nconst AMBIENTSRC_AMBIENTSH = \\\"ambientSH\\\";\\nconst AMBIENTSRC_ENVALATLAS = \\\"envAtlas\\\";\\nconst AMBIENTSRC_CONSTANT = \\\"constant\\\";\\nconst ambientSrcNames = {\\n\\t[AMBIENTSRC_AMBIENTSH]: \\\"AMBIENTSH\\\",\\n\\t[AMBIENTSRC_ENVALATLAS]: \\\"ENVALATLAS\\\",\\n\\t[AMBIENTSRC_CONSTANT]: \\\"CONSTANT\\\"\\n};\\nconst SHADERDEF_NOSHADOW = 1;\\nconst SHADERDEF_SKIN = 2;\\nconst SHADERDEF_UV0 = 4;\\nconst SHADERDEF_UV1 = 8;\\nconst SHADERDEF_VCOLOR = 16;\\nconst SHADERDEF_INSTANCING = 32;\\nconst SHADERDEF_LM = 64;\\nconst SHADERDEF_DIRLM = 128;\\nconst SHADERDEF_SCREENSPACE = 256;\\nconst SHADERDEF_TANGENTS = 512;\\nconst SHADERDEF_MORPH_POSITION = 1024;\\nconst SHADERDEF_MORPH_NORMAL = 2048;\\nconst SHADERDEF_LMAMBIENT = 4096;\\nconst SHADERDEF_MORPH_TEXTURE_BASED_INT = 8192;\\nconst SHADERDEF_BATCH = 16384;\\nconst SHADOWUPDATE_NONE = 0;\\nconst SHADOWUPDATE_THISFRAME = 1;\\nconst SHADOWUPDATE_REALTIME = 2;\\nconst MASK_AFFECT_DYNAMIC = 1;\\nconst MASK_AFFECT_LIGHTMAPPED = 2;\\nconst MASK_BAKE = 4;\\nconst SHADER_FORWARD = 0;\\nconst SHADER_PREPASS = 1;\\nconst SHADER_SHADOW = 2;\\nconst SHADER_PICK = 3;\\nconst SHADER_DEPTH_PICK = 4;\\nconst SPRITE_RENDERMODE_SIMPLE = 0;\\nconst SPRITE_RENDERMODE_SLICED = 1;\\nconst SPRITE_RENDERMODE_TILED = 2;\\nconst spriteRenderModeNames = {\\n\\t[SPRITE_RENDERMODE_SIMPLE]: \\\"SIMPLE\\\",\\n\\t[SPRITE_RENDERMODE_SLICED]: \\\"SLICED\\\",\\n\\t[SPRITE_RENDERMODE_TILED]: \\\"TILED\\\"\\n};\\nconst BAKE_COLORDIR = 1;\\nconst VIEW_CENTER = 0;\\nconst SORTMODE_NONE = 0;\\nconst SORTMODE_MANUAL = 1;\\nconst SORTMODE_MATERIALMESH = 2;\\nconst SORTMODE_BACK2FRONT = 3;\\nconst SORTMODE_FRONT2BACK = 4;\\nconst SORTMODE_CUSTOM = 5;\\nconst ASPECT_AUTO = 0;\\nconst ASPECT_MANUAL = 1;\\nconst SKYTYPE_INFINITE = \\\"infinite\\\";\\nconst SKYTYPE_BOX = \\\"box\\\";\\nconst SKYTYPE_DOME = \\\"dome\\\";\\nconst DITHER_NONE = \\\"none\\\";\\nconst DITHER_BAYER8 = \\\"bayer8\\\";\\nconst DITHER_BLUENOISE = \\\"bluenoise\\\";\\nconst DITHER_IGNNOISE = \\\"ignnoise\\\";\\nconst ditherNames = {\\n\\t[DITHER_NONE]: \\\"NONE\\\",\\n\\t[DITHER_BAYER8]: \\\"BAYER8\\\",\\n\\t[DITHER_BLUENOISE]: \\\"BLUENOISE\\\",\\n\\t[DITHER_IGNNOISE]: \\\"IGNNOISE\\\"\\n};\\nconst EVENT_PRERENDER = \\\"prerender\\\";\\nconst EVENT_POSTRENDER = \\\"postrender\\\";\\nconst EVENT_PRERENDER_LAYER = \\\"prerender:layer\\\";\\nconst EVENT_POSTRENDER_LAYER = \\\"postrender:layer\\\";\\nconst EVENT_PRECULL = \\\"precull\\\";\\nconst EVENT_POSTCULL = \\\"postcull\\\";\\nconst EVENT_CULL_END = \\\"cull:end\\\";\\nconst GSPLAT_FORWARD = 1;\\nconst GSPLAT_SHADOW = 2;\\nconst SHADOWCAMERA_NAME = \\\"pcShadowCamera\\\";\\nconst WORKBUFFER_UPDATE_AUTO = 0;\\nconst WORKBUFFER_UPDATE_ONCE = 1;\\nconst WORKBUFFER_UPDATE_ALWAYS = 2;\\nconst GSPLAT_STREAM_RESOURCE = 0;\\nconst GSPLAT_STREAM_INSTANCE = 1;\\nconst GSPLATDATA_COMPACT = \\\"compact\\\";\\nconst GSPLAT_RENDERER_AUTO = 0;\\nconst GSPLAT_RENDERER_RASTER_CPU_SORT = 1;\\nconst GSPLAT_RENDERER_RASTER_GPU_SORT = 2;\\nconst GSPLAT_RENDERER_COMPUTE = 3;\\nconst GSPLAT_DEBUG_NONE = 0;\\nconst GSPLAT_DEBUG_LOD = 1;\\nconst GSPLAT_DEBUG_SH_UPDATE = 2;\\nconst GSPLAT_DEBUG_HEATMAP = 3;\\nconst GSPLAT_DEBUG_AABBS = 4;\\nconst GSPLAT_DEBUG_NODE_AABBS = 5;\\nconst RADIX_SORT_AUTO = 0;\\nconst RADIX_SORT_PORTABLE = 1;\\nconst RADIX_SORT_ONESWEEP = 2;\\n\\nclass ShaderProcessorOptions {\\n\\tuniformFormats = [];\\n\\tbindGroupFormats = [];\\n\\tvertexFormat;\\n\\tconstructor(viewUniformFormat, viewBindGroupFormat, vertexFormat) {\\n\\t\\tthis.uniformFormats[BINDGROUP_VIEW] = viewUniformFormat;\\n\\t\\tthis.bindGroupFormats[BINDGROUP_VIEW] = viewBindGroupFormat;\\n\\t\\tthis.vertexFormat = vertexFormat;\\n\\t}\\n\\thasUniform(name) {\\n\\t\\tfor (let i = 0; i < this.uniformFormats.length; i++) {\\n\\t\\t\\tconst uniformFormat = this.uniformFormats[i];\\n\\t\\t\\tif (uniformFormat?.get(name)) {\\n\\t\\t\\t\\treturn true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn false;\\n\\t}\\n\\thasTexture(name) {\\n\\t\\tfor (let i = 0; i < this.bindGroupFormats.length; i++) {\\n\\t\\t\\tconst groupFormat = this.bindGroupFormats[i];\\n\\t\\t\\tif (groupFormat?.getTexture(name)) {\\n\\t\\t\\t\\treturn true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn false;\\n\\t}\\n\\tgetVertexElement(semantic) {\\n\\t\\treturn this.vertexFormat?.elements.find((element) => element.name === semantic);\\n\\t}\\n\\tgenerateKey(device) {\\n\\t\\tlet key = JSON.stringify(this.uniformFormats) + JSON.stringify(this.bindGroupFormats);\\n\\t\\tif (device.isWebGPU) {\\n\\t\\t\\tkey += this.vertexFormat?.shaderProcessingHashString;\\n\\t\\t}\\n\\t\\treturn key;\\n\\t}\\n}\\n\\nconst programLibraryDeviceCache = new DeviceCache();\\nfunction getProgramLibrary(device) {\\n\\tconst library = programLibraryDeviceCache.get(device);\\n\\treturn library;\\n}\\nfunction setProgramLibrary(device, library) {\\n\\tprogramLibraryDeviceCache.get(device, () => {\\n\\t\\treturn library;\\n\\t});\\n}\\n\\nclass ShaderGenerator {\\n\\tstatic definesHash(defines) {\\n\\t\\tconst sortedArray = Array.from(defines).sort((a, b) => a[0] > b[0] ? 1 : -1);\\n\\t\\treturn hashCode(JSON.stringify(sortedArray));\\n\\t}\\n}\\n\\nconst shaderPassDeviceCache = new DeviceCache();\\nclass ShaderPassInfo {\\n\\tindex;\\n\\tname;\\n\\tdefines = /* @__PURE__ */ new Map();\\n\\tconstructor(name, index, options = {}) {\\n\\t\\tthis.name = name;\\n\\t\\tthis.index = index;\\n\\t\\tObject.assign(this, options);\\n\\t\\tthis.buildShaderDefines();\\n\\t}\\n\\tbuildShaderDefines() {\\n\\t\\tlet keyword;\\n\\t\\tif (this.isShadow) {\\n\\t\\t\\tkeyword = \\\"SHADOW\\\";\\n\\t\\t} else if (this.isForward) {\\n\\t\\t\\tkeyword = \\\"FORWARD\\\";\\n\\t\\t} else if (this.index === SHADER_PICK) {\\n\\t\\t\\tkeyword = \\\"PICK\\\";\\n\\t\\t} else if (this.index === SHADER_DEPTH_PICK) {\\n\\t\\t\\tkeyword = \\\"PICK\\\";\\n\\t\\t\\tthis.defines.set(\\\"DEPTH_PICK_PASS\\\", \\\"\\\");\\n\\t\\t}\\n\\t\\tthis.defines.set(`${keyword}_PASS`, \\\"\\\");\\n\\t\\tthis.defines.set(`${this.name.toUpperCase()}_PASS`, \\\"\\\");\\n\\t}\\n}\\nclass ShaderPass {\\n\\tpassesNamed = /* @__PURE__ */ new Map();\\n\\tpassesIndexed = [];\\n\\tnextIndex = 0;\\n\\tconstructor() {\\n\\t\\tconst add = (name, index, options) => {\\n\\t\\t\\tthis.allocate(name, options);\\n\\t\\t};\\n\\t\\tadd(\\\"forward\\\", SHADER_FORWARD, { isForward: true });\\n\\t\\tadd(\\\"prepass\\\");\\n\\t\\tadd(\\\"shadow\\\");\\n\\t\\tadd(\\\"pick\\\");\\n\\t\\tadd(\\\"depth_pick\\\");\\n\\t}\\n\\tstatic get(device) {\\n\\t\\treturn shaderPassDeviceCache.get(device, () => {\\n\\t\\t\\treturn new ShaderPass();\\n\\t\\t});\\n\\t}\\n\\tallocate(name, options) {\\n\\t\\tlet info = this.passesNamed.get(name);\\n\\t\\tif (info === void 0) {\\n\\t\\t\\tinfo = new ShaderPassInfo(name, this.nextIndex, options);\\n\\t\\t\\tthis.passesNamed.set(info.name, info);\\n\\t\\t\\tthis.passesIndexed[info.index] = info;\\n\\t\\t\\tthis.nextIndex++;\\n\\t\\t}\\n\\t\\treturn info;\\n\\t}\\n\\tgetByIndex(index) {\\n\\t\\tconst info = this.passesIndexed[index];\\n\\t\\treturn info;\\n\\t}\\n\\tgetByName(name) {\\n\\t\\treturn this.passesNamed.get(name);\\n\\t}\\n}\\n\\nclass ShaderChunkMap extends Map {\\n\\t_validations;\\n\\t_keyDirty = false;\\n\\t_key = \\\"\\\";\\n\\tconstructor(validations) {\\n\\t\\tsuper();\\n\\t\\tthis._validations = validations;\\n\\t}\\n\\tset(name, code) {\\n\\t\\tif (!this.has(name) || this.get(name) !== code) {\\n\\t\\t\\tthis.markDirty();\\n\\t\\t}\\n\\t\\treturn super.set(name, code);\\n\\t}\\n\\tadd(object, override = true) {\\n\\t\\tfor (const [key, value] of Object.entries(object)) {\\n\\t\\t\\tif (override || !this.has(key)) {\\n\\t\\t\\t\\tthis.set(key, value);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\tdelete(name) {\\n\\t\\tconst existed = this.has(name);\\n\\t\\tconst result = super.delete(name);\\n\\t\\tif (existed && result) {\\n\\t\\t\\tthis.markDirty();\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n\\tclear() {\\n\\t\\tif (this.size > 0) {\\n\\t\\t\\tthis.markDirty();\\n\\t\\t}\\n\\t\\tsuper.clear();\\n\\t}\\n\\tmarkDirty() {\\n\\t\\tthis._dirty = true;\\n\\t\\tthis._keyDirty = true;\\n\\t}\\n\\tisDirty() {\\n\\t\\treturn this._dirty;\\n\\t}\\n\\tresetDirty() {\\n\\t\\tthis._dirty = false;\\n\\t}\\n\\tget key() {\\n\\t\\tif (this._keyDirty) {\\n\\t\\t\\tthis._keyDirty = false;\\n\\t\\t\\tthis._key = Array.from(this.entries()).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([k, v]) => `${k}=${hashCode(v)}`).join(\\\",\\\");\\n\\t\\t}\\n\\t\\treturn this._key;\\n\\t}\\n\\tcopy(source) {\\n\\t\\tfor (const key of this.keys()) {\\n\\t\\t\\tif (!source.has(key)) {\\n\\t\\t\\t\\tthis.delete(key);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (const [key, value] of source) {\\n\\t\\t\\tthis.set(key, value);\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n}\\n\\nconst _chunksCache = new DeviceCache();\\nclass ShaderChunks {\\n\\tstatic _validations = /* @__PURE__ */ new Map();\\n\\tglsl = new ShaderChunkMap(ShaderChunks._validations);\\n\\twgsl = new ShaderChunkMap(ShaderChunks._validations);\\n\\tstatic get(device, shaderLanguage = SHADERLANGUAGE_GLSL) {\\n\\t\\tconst cache = _chunksCache.get(device, () => {\\n\\t\\t\\treturn new ShaderChunks();\\n\\t\\t});\\n\\t\\treturn shaderLanguage === SHADERLANGUAGE_GLSL ? cache.glsl : cache.wgsl;\\n\\t}\\n\\tstatic registerValidation(name, options) {\\n\\t}\\n\\tversion = \\\"\\\";\\n\\tget useWGSL() {\\n\\t\\treturn this.glsl.size === 0 || this.wgsl.size > 0;\\n\\t}\\n\\tget key() {\\n\\t\\treturn `GLSL:${this.glsl.key}|WGSL:${this.wgsl.key}|API:${this.version}`;\\n\\t}\\n\\tisDirty() {\\n\\t\\treturn this.glsl.isDirty() || this.wgsl.isDirty();\\n\\t}\\n\\tresetDirty() {\\n\\t\\tthis.glsl.resetDirty();\\n\\t\\tthis.wgsl.resetDirty();\\n\\t}\\n\\tcopy(source) {\\n\\t\\tthis.version = source.version;\\n\\t\\tthis.glsl.copy(source.glsl);\\n\\t\\tthis.wgsl.copy(source.wgsl);\\n\\t\\treturn this;\\n\\t}\\n}\\n\\nclass MapUtils {\\n\\tstatic merge(...maps) {\\n\\t\\tconst result = new Map(maps[0] ?? []);\\n\\t\\tfor (let i = 1; i < maps.length; i++) {\\n\\t\\t\\tconst map = maps[i];\\n\\t\\t\\tif (map) {\\n\\t\\t\\t\\tfor (const [key, value] of map) {\\n\\t\\t\\t\\t\\tresult.set(key, value);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n}\\n\\nclass ShaderGeneratorPassThrough extends ShaderGenerator {\\n\\tconstructor(key, shaderDefinition) {\\n\\t\\tsuper();\\n\\t\\tthis.key = key;\\n\\t\\tthis.shaderDefinition = shaderDefinition;\\n\\t}\\n\\tgenerateKey(options) {\\n\\t\\treturn this.key;\\n\\t}\\n\\tcreateShaderDefinition(device, options) {\\n\\t\\treturn this.shaderDefinition;\\n\\t}\\n}\\nclass ShaderUtils {\\n\\tstatic createShader(device, options) {\\n\\t\\tconst programLibrary = getProgramLibrary(device);\\n\\t\\tlet shader = programLibrary.getCachedShader(options.uniqueName);\\n\\t\\tif (!shader) {\\n\\t\\t\\tconst wgsl = device.isWebGPU && (!!options.vertexWGSL || !!options.vertexChunk) && (!!options.fragmentWGSL || !!options.fragmentChunk);\\n\\t\\t\\tconst chunksMap = ShaderChunks.get(device, wgsl ? SHADERLANGUAGE_WGSL : SHADERLANGUAGE_GLSL);\\n\\t\\t\\tconst vertexCode = options.vertexChunk ? chunksMap.get(options.vertexChunk) : wgsl ? options.vertexWGSL : options.vertexGLSL;\\n\\t\\t\\tconst fragmentCode = options.fragmentChunk ? chunksMap.get(options.fragmentChunk) : wgsl ? options.fragmentWGSL : options.fragmentGLSL;\\n\\t\\t\\tconst fragmentIncludes = MapUtils.merge(chunksMap, options.fragmentIncludes);\\n\\t\\t\\tconst vertexIncludes = MapUtils.merge(chunksMap, options.vertexIncludes);\\n\\t\\t\\tshader = new Shader(device, ShaderDefinitionUtils.createDefinition(device, {\\n\\t\\t\\t\\tname: options.uniqueName,\\n\\t\\t\\t\\tshaderLanguage: wgsl ? SHADERLANGUAGE_WGSL : SHADERLANGUAGE_GLSL,\\n\\t\\t\\t\\tattributes: options.attributes,\\n\\t\\t\\t\\tvertexCode,\\n\\t\\t\\t\\tfragmentCode,\\n\\t\\t\\t\\tuseTransformFeedback: options.useTransformFeedback,\\n\\t\\t\\t\\tvertexIncludes,\\n\\t\\t\\t\\tvertexDefines: options.vertexDefines,\\n\\t\\t\\t\\tfragmentIncludes,\\n\\t\\t\\t\\tfragmentDefines: options.fragmentDefines,\\n\\t\\t\\t\\tfragmentOutputTypes: options.fragmentOutputTypes\\n\\t\\t\\t}));\\n\\t\\t\\tprogramLibrary.setCachedShader(options.uniqueName, shader);\\n\\t\\t}\\n\\t\\treturn shader;\\n\\t}\\n\\tstatic getCoreDefines(material, params) {\\n\\t\\tconst defines = new Map(material.defines);\\n\\t\\tparams.cameraShaderParams.defines.forEach((value, key) => defines.set(key, value));\\n\\t\\tconst shaderPassInfo = ShaderPass.get(params.device).getByIndex(params.pass);\\n\\t\\tshaderPassInfo.defines.forEach((value, key) => defines.set(key, value));\\n\\t\\treturn defines;\\n\\t}\\n\\tstatic processShader(shader, processingOptions) {\\n\\t\\tconst shaderDefinition = shader.definition;\\n\\t\\tconst name = shaderDefinition.name ?? \\\"shader\\\";\\n\\t\\tconst key = `${name}-id-${shader.id}`;\\n\\t\\tconst materialGenerator = new ShaderGeneratorPassThrough(key, shaderDefinition);\\n\\t\\tconst libraryModuleName = \\\"shader\\\";\\n\\t\\tconst library = getProgramLibrary(shader.device);\\n\\t\\tlibrary.register(libraryModuleName, materialGenerator);\\n\\t\\tconst variant = library.getProgram(libraryModuleName, {}, processingOptions);\\n\\t\\tlibrary.unregister(libraryModuleName);\\n\\t\\treturn variant;\\n\\t}\\n\\tstatic addScreenDepthChunkDefines(device, cameraShaderParams, defines) {\\n\\t\\tif (cameraShaderParams.sceneDepthMapLinear) {\\n\\t\\t\\tdefines.set(\\\"SCENE_DEPTHMAP_LINEAR\\\", \\\"\\\");\\n\\t\\t}\\n\\t\\tif (device.textureFloatRenderable) {\\n\\t\\t\\tdefines.set(\\\"SCENE_DEPTHMAP_FLOAT\\\", \\\"\\\");\\n\\t\\t}\\n\\t}\\n}\\n\\nconst _quadPrimitive = {\\n\\ttype: PRIMITIVE_TRIANGLES,\\n\\tbase: 0,\\n\\tcount: 6,\\n\\tindexed: true\\n};\\nconst _tempViewport = new Vec4();\\nconst _tempScissor = new Vec4();\\nconst _dynamicBindGroup$1 = new DynamicBindGroup();\\nclass QuadRender {\\n\\tuniformBuffer;\\n\\tbindGroup;\\n\\tconstructor(shader) {\\n\\t\\tconst device = shader.device;\\n\\t\\tthis.shader = shader;\\n\\t\\tif (device.supportsUniformBuffers) {\\n\\t\\t\\tconst processingOptions = new ShaderProcessorOptions();\\n\\t\\t\\tthis.shader = ShaderUtils.processShader(shader, processingOptions);\\n\\t\\t\\tconst ubFormat = this.shader.meshUniformBufferFormat;\\n\\t\\t\\tif (ubFormat) {\\n\\t\\t\\t\\tthis.uniformBuffer = new UniformBuffer(device, ubFormat, false);\\n\\t\\t\\t}\\n\\t\\t\\tconst bindGroupFormat = this.shader.meshBindGroupFormat;\\n\\t\\t\\tthis.bindGroup = new BindGroup(device, bindGroupFormat);\\n\\t\\t}\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.uniformBuffer?.destroy();\\n\\t\\tthis.uniformBuffer = null;\\n\\t\\tthis.bindGroup?.destroy();\\n\\t\\tthis.bindGroup = null;\\n\\t}\\n\\trender(viewport, scissor, numInstances) {\\n\\t\\tconst device = this.shader.device;\\n\\t\\tif (viewport) {\\n\\t\\t\\t_tempViewport.set(device.vx, device.vy, device.vw, device.vh);\\n\\t\\t\\t_tempScissor.set(device.sx, device.sy, device.sw, device.sh);\\n\\t\\t\\tscissor = scissor ?? viewport;\\n\\t\\t\\tdevice.setViewport(viewport.x, viewport.y, viewport.z, viewport.w);\\n\\t\\t\\tdevice.setScissor(scissor.x, scissor.y, scissor.z, scissor.w);\\n\\t\\t}\\n\\t\\tdevice.setVertexBuffer(device.quadVertexBuffer);\\n\\t\\tconst shader = this.shader;\\n\\t\\tdevice.setShader(shader);\\n\\t\\tif (device.supportsUniformBuffers) {\\n\\t\\t\\tdevice.setBindGroup(BINDGROUP_VIEW, device.emptyBindGroup);\\n\\t\\t\\tconst bindGroup = this.bindGroup;\\n\\t\\t\\tbindGroup.update();\\n\\t\\t\\tdevice.setBindGroup(BINDGROUP_MESH, bindGroup);\\n\\t\\t\\tconst uniformBuffer = this.uniformBuffer;\\n\\t\\t\\tif (uniformBuffer) {\\n\\t\\t\\t\\tuniformBuffer.update(_dynamicBindGroup$1);\\n\\t\\t\\t\\tdevice.setBindGroup(BINDGROUP_MESH_UB, _dynamicBindGroup$1.bindGroup, _dynamicBindGroup$1.offsets);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tdevice.setBindGroup(BINDGROUP_MESH_UB, device.emptyBindGroup);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdevice.draw(_quadPrimitive, device.quadIndexBuffer, numInstances);\\n\\t\\tif (viewport) {\\n\\t\\t\\tdevice.setViewport(_tempViewport.x, _tempViewport.y, _tempViewport.z, _tempViewport.w);\\n\\t\\t\\tdevice.setScissor(_tempScissor.x, _tempScissor.y, _tempScissor.z, _tempScissor.w);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass RenderPassQuad extends RenderPass {\\n\\tconstructor(device, quad, rect, scissorRect) {\\n\\t\\tsuper(device);\\n\\t\\tthis.quad = quad;\\n\\t\\tthis.rect = rect;\\n\\t\\tthis.scissorRect = scissorRect;\\n\\t}\\n\\texecute() {\\n\\t\\tconst { device } = this;\\n\\t\\tdevice.setDrawStates(device.blendState);\\n\\t\\tthis.quad.render(this.rect, this.scissorRect);\\n\\t}\\n}\\n\\nconst _tempRect = new Vec4();\\nfunction drawQuadWithShader(device, target, shader, rect, scissorRect) {\\n\\tconst quad = new QuadRender(shader);\\n\\tif (!rect) {\\n\\t\\trect = _tempRect;\\n\\t\\trect.x = 0;\\n\\t\\trect.y = 0;\\n\\t\\trect.z = target ? target.width : device.width;\\n\\t\\trect.w = target ? target.height : device.height;\\n\\t}\\n\\tconst renderPass = new RenderPassQuad(device, quad, rect, scissorRect);\\n\\trenderPass.init(target);\\n\\trenderPass.colorOps.clear = false;\\n\\trenderPass.depthStencilOps.clearDepth = false;\\n\\tif (device.isWebGPU && target === null && device.samples > 1) {\\n\\t\\trenderPass.colorOps.store = true;\\n\\t}\\n\\trenderPass.render();\\n\\tquad.destroy();\\n}\\n\\nclass BatchGroup {\\n\\t_ui = false;\\n\\t_sprite = false;\\n\\t_obj = {\\n\\t\\tmodel: [],\\n\\t\\telement: [],\\n\\t\\tsprite: [],\\n\\t\\trender: []\\n\\t};\\n\\tid;\\n\\tname;\\n\\tdynamic;\\n\\tmaxAabbSize;\\n\\tlayers;\\n\\tconstructor(id, name, dynamic, maxAabbSize, layers = [LAYERID_WORLD]) {\\n\\t\\tthis.id = id;\\n\\t\\tthis.name = name;\\n\\t\\tthis.dynamic = dynamic;\\n\\t\\tthis.maxAabbSize = maxAabbSize;\\n\\t\\tthis.layers = layers;\\n\\t}\\n\\tstatic MODEL = \\\"model\\\";\\n\\tstatic ELEMENT = \\\"element\\\";\\n\\tstatic SPRITE = \\\"sprite\\\";\\n\\tstatic RENDER = \\\"render\\\";\\n}\\n\\nconst _invMatrix = new Mat4();\\nclass SkinInstance {\\n\\tbones;\\n\\tconstructor(skin) {\\n\\t\\tthis._dirty = true;\\n\\t\\tthis._rootBone = null;\\n\\t\\tthis._skinUpdateIndex = -1;\\n\\t\\tthis._updateBeforeCull = true;\\n\\t\\tif (skin) {\\n\\t\\t\\tthis.initSkin(skin);\\n\\t\\t}\\n\\t}\\n\\tset rootBone(rootBone) {\\n\\t\\tthis._rootBone = rootBone;\\n\\t}\\n\\tget rootBone() {\\n\\t\\treturn this._rootBone;\\n\\t}\\n\\tinit(device, numBones) {\\n\\t\\tconst numPixels = numBones * 3;\\n\\t\\tlet width = Math.ceil(Math.sqrt(numPixels));\\n\\t\\twidth = math.roundUp(width, 3);\\n\\t\\tconst height = Math.ceil(numPixels / width);\\n\\t\\tthis.boneTexture = new Texture(device, {\\n\\t\\t\\twidth,\\n\\t\\t\\theight,\\n\\t\\t\\tformat: PIXELFORMAT_RGBA32F,\\n\\t\\t\\tmipmaps: false,\\n\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\tname: \\\"skin\\\"\\n\\t\\t});\\n\\t\\tthis.matrixPalette = this.boneTexture.lock({ mode: TEXTURELOCK_READ });\\n\\t\\tthis.boneTexture.unlock();\\n\\t}\\n\\tdestroy() {\\n\\t\\tif (this.boneTexture) {\\n\\t\\t\\tthis.boneTexture.destroy();\\n\\t\\t\\tthis.boneTexture = null;\\n\\t\\t}\\n\\t}\\n\\tresolve(rootBone, entity) {\\n\\t\\tthis.rootBone = rootBone;\\n\\t\\tconst skin = this.skin;\\n\\t\\tconst bones = [];\\n\\t\\tfor (let j = 0; j < skin.boneNames.length; j++) {\\n\\t\\t\\tconst boneName = skin.boneNames[j];\\n\\t\\t\\tlet bone = rootBone.findByName(boneName);\\n\\t\\t\\tif (!bone) {\\n\\t\\t\\t\\tbone = entity;\\n\\t\\t\\t}\\n\\t\\t\\tbones.push(bone);\\n\\t\\t}\\n\\t\\tthis.bones = bones;\\n\\t}\\n\\tinitSkin(skin) {\\n\\t\\tthis.skin = skin;\\n\\t\\tthis.bones = [];\\n\\t\\tconst numBones = skin.inverseBindPose.length;\\n\\t\\tthis.init(skin.device, numBones);\\n\\t\\tthis.matrices = [];\\n\\t\\tfor (let i = 0; i < numBones; i++) {\\n\\t\\t\\tthis.matrices[i] = new Mat4();\\n\\t\\t}\\n\\t}\\n\\tuploadBones(device) {\\n\\t\\tthis.boneTexture.upload();\\n\\t}\\n\\t_updateMatrices(rootNode, skinUpdateIndex) {\\n\\t\\tif (this._skinUpdateIndex !== skinUpdateIndex) {\\n\\t\\t\\tthis._skinUpdateIndex = skinUpdateIndex;\\n\\t\\t\\t_invMatrix.copy(rootNode.getWorldTransform()).invert();\\n\\t\\t\\tfor (let i = this.bones.length - 1; i >= 0; i--) {\\n\\t\\t\\t\\tthis.matrices[i].mulAffine2(_invMatrix, this.bones[i].getWorldTransform());\\n\\t\\t\\t\\tthis.matrices[i].mulAffine2(this.matrices[i], this.skin.inverseBindPose[i]);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tupdateMatrices(rootNode, skinUpdateIndex) {\\n\\t\\tif (this._updateBeforeCull) {\\n\\t\\t\\tthis._updateMatrices(rootNode, skinUpdateIndex);\\n\\t\\t}\\n\\t}\\n\\tupdateMatrixPalette(rootNode, skinUpdateIndex) {\\n\\t\\tthis._updateMatrices(rootNode, skinUpdateIndex);\\n\\t\\tconst mp = this.matrixPalette;\\n\\t\\tconst count = this.bones.length;\\n\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\tconst pe = this.matrices[i].data;\\n\\t\\t\\tconst base = i * 12;\\n\\t\\t\\tmp[base] = pe[0];\\n\\t\\t\\tmp[base + 1] = pe[4];\\n\\t\\t\\tmp[base + 2] = pe[8];\\n\\t\\t\\tmp[base + 3] = pe[12];\\n\\t\\t\\tmp[base + 4] = pe[1];\\n\\t\\t\\tmp[base + 5] = pe[5];\\n\\t\\t\\tmp[base + 6] = pe[9];\\n\\t\\t\\tmp[base + 7] = pe[13];\\n\\t\\t\\tmp[base + 8] = pe[2];\\n\\t\\t\\tmp[base + 9] = pe[6];\\n\\t\\t\\tmp[base + 10] = pe[10];\\n\\t\\t\\tmp[base + 11] = pe[14];\\n\\t\\t}\\n\\t\\tthis.uploadBones(this.skin.device);\\n\\t}\\n}\\n\\nlet id$4 = 0;\\nclass GeometryData {\\n\\tconstructor() {\\n\\t\\tthis.initDefaults();\\n\\t}\\n\\tinitDefaults() {\\n\\t\\tthis.recreate = false;\\n\\t\\tthis.verticesUsage = BUFFER_STATIC;\\n\\t\\tthis.indicesUsage = BUFFER_STATIC;\\n\\t\\tthis.maxVertices = 0;\\n\\t\\tthis.maxIndices = 0;\\n\\t\\tthis.vertexCount = 0;\\n\\t\\tthis.indexCount = 0;\\n\\t\\tthis.vertexStreamsUpdated = false;\\n\\t\\tthis.indexStreamUpdated = false;\\n\\t\\tthis.vertexStreamDictionary = {};\\n\\t\\tthis.indices = null;\\n\\t}\\n\\t// function called when vertex stream is requested to be updated, and validates / updates currently used vertex count\\n\\t_changeVertexCount(count, semantic) {\\n\\t\\tif (!this.vertexCount) {\\n\\t\\t\\tthis.vertexCount = count;\\n\\t\\t}\\n\\t}\\n\\t// default counts for vertex components\\n\\tstatic DEFAULT_COMPONENTS_POSITION = 3;\\n\\tstatic DEFAULT_COMPONENTS_NORMAL = 3;\\n\\tstatic DEFAULT_COMPONENTS_UV = 2;\\n\\tstatic DEFAULT_COMPONENTS_COLORS = 4;\\n}\\nclass GeometryVertexStream {\\n\\tconstructor(data, componentCount, dataType, dataTypeNormalize, asInt) {\\n\\t\\tthis.data = data;\\n\\t\\tthis.componentCount = componentCount;\\n\\t\\tthis.dataType = dataType;\\n\\t\\tthis.dataTypeNormalize = dataTypeNormalize;\\n\\t\\tthis.asInt = asInt;\\n\\t}\\n}\\nclass Mesh extends RefCountedObject {\\n\\tindexBuffer = [null];\\n\\tvertexBuffer = null;\\n\\tprimitive = [{\\n\\t\\ttype: 0,\\n\\t\\tbase: 0,\\n\\t\\tbaseVertex: 0,\\n\\t\\tcount: 0\\n\\t}];\\n\\tskin = null;\\n\\tboneAabb = null;\\n\\t_aabbVer = 0;\\n\\t_aabb = new BoundingBox();\\n\\t_geometryData = null;\\n\\t_morph = null;\\n\\t_storageIndex = false;\\n\\t_storageVertex = false;\\n\\tconstructor(graphicsDevice, options) {\\n\\t\\tsuper();\\n\\t\\tthis.id = id$4++;\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tthis._storageIndex = options?.storageIndex || false;\\n\\t\\tthis._storageVertex = options?.storageVertex || false;\\n\\t}\\n\\tstatic fromGeometry(graphicsDevice, geometry, options = {}) {\\n\\t\\tconst mesh = new Mesh(graphicsDevice, options);\\n\\t\\tconst { positions, normals, tangents, colors, uvs, uvs1, blendIndices, blendWeights, indices } = geometry;\\n\\t\\tif (positions) {\\n\\t\\t\\tmesh.setPositions(positions);\\n\\t\\t}\\n\\t\\tif (normals) {\\n\\t\\t\\tmesh.setNormals(normals);\\n\\t\\t}\\n\\t\\tif (tangents) {\\n\\t\\t\\tmesh.setVertexStream(SEMANTIC_TANGENT, tangents, 4);\\n\\t\\t}\\n\\t\\tif (colors) {\\n\\t\\t\\tmesh.setColors32(colors);\\n\\t\\t}\\n\\t\\tif (uvs) {\\n\\t\\t\\tmesh.setUvs(0, uvs);\\n\\t\\t}\\n\\t\\tif (uvs1) {\\n\\t\\t\\tmesh.setUvs(1, uvs1);\\n\\t\\t}\\n\\t\\tif (blendIndices) {\\n\\t\\t\\tmesh.setVertexStream(SEMANTIC_BLENDINDICES, blendIndices, 4, blendIndices.length / 4, TYPE_UINT8);\\n\\t\\t}\\n\\t\\tif (blendWeights) {\\n\\t\\t\\tmesh.setVertexStream(SEMANTIC_BLENDWEIGHT, blendWeights, 4);\\n\\t\\t}\\n\\t\\tif (indices) {\\n\\t\\t\\tmesh.setIndices(indices);\\n\\t\\t}\\n\\t\\tmesh.update();\\n\\t\\treturn mesh;\\n\\t}\\n\\tset morph(morph) {\\n\\t\\tif (morph !== this._morph) {\\n\\t\\t\\tif (this._morph) {\\n\\t\\t\\t\\tthis._morph.decRefCount();\\n\\t\\t\\t}\\n\\t\\t\\tthis._morph = morph;\\n\\t\\t\\tif (morph) {\\n\\t\\t\\t\\tmorph.incRefCount();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget morph() {\\n\\t\\treturn this._morph;\\n\\t}\\n\\tset aabb(aabb) {\\n\\t\\tthis._aabb = aabb;\\n\\t\\tthis._aabbVer++;\\n\\t}\\n\\tget aabb() {\\n\\t\\treturn this._aabb;\\n\\t}\\n\\tdestroy() {\\n\\t\\tconst morph = this.morph;\\n\\t\\tif (morph) {\\n\\t\\t\\tthis.morph = null;\\n\\t\\t\\tif (morph.refCount < 1) {\\n\\t\\t\\t\\tmorph.destroy();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this.vertexBuffer) {\\n\\t\\t\\tthis.vertexBuffer.destroy();\\n\\t\\t\\tthis.vertexBuffer = null;\\n\\t\\t}\\n\\t\\tfor (let j = 0; j < this.indexBuffer.length; j++) {\\n\\t\\t\\tthis._destroyIndexBuffer(j);\\n\\t\\t}\\n\\t\\tthis.indexBuffer.length = 0;\\n\\t\\tthis._geometryData = null;\\n\\t}\\n\\t_destroyIndexBuffer(index) {\\n\\t\\tif (this.indexBuffer[index]) {\\n\\t\\t\\tthis.indexBuffer[index].destroy();\\n\\t\\t\\tthis.indexBuffer[index] = null;\\n\\t\\t}\\n\\t}\\n\\t// initializes local bounding boxes for each bone based on vertices affected by the bone\\n\\t// if morph targets are provided, it also adjusts local bone bounding boxes by maximum morph displacement\\n\\t_initBoneAabbs(morphTargets) {\\n\\t\\tthis.boneAabb = [];\\n\\t\\tthis.boneUsed = [];\\n\\t\\tlet x, y, z;\\n\\t\\tlet bMax, bMin;\\n\\t\\tconst boneMin = [];\\n\\t\\tconst boneMax = [];\\n\\t\\tconst boneUsed = this.boneUsed;\\n\\t\\tconst numBones = this.skin.boneNames.length;\\n\\t\\tlet maxMorphX, maxMorphY, maxMorphZ;\\n\\t\\tfor (let i = 0; i < numBones; i++) {\\n\\t\\t\\tboneMin[i] = new Vec3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);\\n\\t\\t\\tboneMax[i] = new Vec3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);\\n\\t\\t}\\n\\t\\tconst iterator = new VertexIterator(this.vertexBuffer);\\n\\t\\tconst posElement = iterator.element[SEMANTIC_POSITION];\\n\\t\\tconst weightsElement = iterator.element[SEMANTIC_BLENDWEIGHT];\\n\\t\\tconst indicesElement = iterator.element[SEMANTIC_BLENDINDICES];\\n\\t\\tconst numVerts = this.vertexBuffer.numVertices;\\n\\t\\tfor (let j = 0; j < numVerts; j++) {\\n\\t\\t\\tfor (let k = 0; k < 4; k++) {\\n\\t\\t\\t\\tconst boneWeight = weightsElement.array[weightsElement.index + k];\\n\\t\\t\\t\\tif (boneWeight > 0) {\\n\\t\\t\\t\\t\\tconst boneIndex = indicesElement.array[indicesElement.index + k];\\n\\t\\t\\t\\t\\tboneUsed[boneIndex] = true;\\n\\t\\t\\t\\t\\tx = posElement.array[posElement.index];\\n\\t\\t\\t\\t\\ty = posElement.array[posElement.index + 1];\\n\\t\\t\\t\\t\\tz = posElement.array[posElement.index + 2];\\n\\t\\t\\t\\t\\tbMax = boneMax[boneIndex];\\n\\t\\t\\t\\t\\tbMin = boneMin[boneIndex];\\n\\t\\t\\t\\t\\tif (bMin.x > x) bMin.x = x;\\n\\t\\t\\t\\t\\tif (bMin.y > y) bMin.y = y;\\n\\t\\t\\t\\t\\tif (bMin.z > z) bMin.z = z;\\n\\t\\t\\t\\t\\tif (bMax.x < x) bMax.x = x;\\n\\t\\t\\t\\t\\tif (bMax.y < y) bMax.y = y;\\n\\t\\t\\t\\t\\tif (bMax.z < z) bMax.z = z;\\n\\t\\t\\t\\t\\tif (morphTargets) {\\n\\t\\t\\t\\t\\t\\tlet minMorphX = maxMorphX = x;\\n\\t\\t\\t\\t\\t\\tlet minMorphY = maxMorphY = y;\\n\\t\\t\\t\\t\\t\\tlet minMorphZ = maxMorphZ = z;\\n\\t\\t\\t\\t\\t\\tfor (let l = 0; l < morphTargets.length; l++) {\\n\\t\\t\\t\\t\\t\\t\\tconst target = morphTargets[l];\\n\\t\\t\\t\\t\\t\\t\\tconst dx = target.deltaPositions[j * 3];\\n\\t\\t\\t\\t\\t\\t\\tconst dy = target.deltaPositions[j * 3 + 1];\\n\\t\\t\\t\\t\\t\\t\\tconst dz = target.deltaPositions[j * 3 + 2];\\n\\t\\t\\t\\t\\t\\t\\tif (dx < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tminMorphX += dx;\\n\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tmaxMorphX += dx;\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\tif (dy < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tminMorphY += dy;\\n\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tmaxMorphY += dy;\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\tif (dz < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tminMorphZ += dz;\\n\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tmaxMorphZ += dz;\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (bMin.x > minMorphX) bMin.x = minMorphX;\\n\\t\\t\\t\\t\\t\\tif (bMin.y > minMorphY) bMin.y = minMorphY;\\n\\t\\t\\t\\t\\t\\tif (bMin.z > minMorphZ) bMin.z = minMorphZ;\\n\\t\\t\\t\\t\\t\\tif (bMax.x < maxMorphX) bMax.x = maxMorphX;\\n\\t\\t\\t\\t\\t\\tif (bMax.y < maxMorphY) bMax.y = maxMorphY;\\n\\t\\t\\t\\t\\t\\tif (bMax.z < maxMorphZ) bMax.z = maxMorphZ;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\titerator.next();\\n\\t\\t}\\n\\t\\tconst positionElement = this.vertexBuffer.getFormat().elements.find((e) => e.name === SEMANTIC_POSITION);\\n\\t\\tif (positionElement && positionElement.normalize) {\\n\\t\\t\\tconst func = (() => {\\n\\t\\t\\t\\tswitch (positionElement.dataType) {\\n\\t\\t\\t\\t\\tcase TYPE_INT8:\\n\\t\\t\\t\\t\\t\\treturn (x2) => Math.max(x2 / 127, -1);\\n\\t\\t\\t\\t\\tcase TYPE_UINT8:\\n\\t\\t\\t\\t\\t\\treturn (x2) => x2 / 255;\\n\\t\\t\\t\\t\\tcase TYPE_INT16:\\n\\t\\t\\t\\t\\t\\treturn (x2) => Math.max(x2 / 32767, -1);\\n\\t\\t\\t\\t\\tcase TYPE_UINT16:\\n\\t\\t\\t\\t\\t\\treturn (x2) => x2 / 65535;\\n\\t\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\treturn (x2) => x2;\\n\\t\\t\\t\\t}\\n\\t\\t\\t})();\\n\\t\\t\\tfor (let i = 0; i < numBones; i++) {\\n\\t\\t\\t\\tif (boneUsed[i]) {\\n\\t\\t\\t\\t\\tconst min = boneMin[i];\\n\\t\\t\\t\\t\\tconst max = boneMax[i];\\n\\t\\t\\t\\t\\tmin.set(func(min.x), func(min.y), func(min.z));\\n\\t\\t\\t\\t\\tmax.set(func(max.x), func(max.y), func(max.z));\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < numBones; i++) {\\n\\t\\t\\tconst aabb = new BoundingBox();\\n\\t\\t\\taabb.setMinMax(boneMin[i], boneMax[i]);\\n\\t\\t\\tthis.boneAabb.push(aabb);\\n\\t\\t}\\n\\t}\\n\\t// when mesh API to modify vertex / index data are used, this allocates structure to store the data\\n\\t_initGeometryData() {\\n\\t\\tif (!this._geometryData) {\\n\\t\\t\\tthis._geometryData = new GeometryData();\\n\\t\\t\\tif (this.vertexBuffer) {\\n\\t\\t\\t\\tthis._geometryData.vertexCount = this.vertexBuffer.numVertices;\\n\\t\\t\\t\\tthis._geometryData.maxVertices = this.vertexBuffer.numVertices;\\n\\t\\t\\t}\\n\\t\\t\\tif (this.indexBuffer.length > 0 && this.indexBuffer[0]) {\\n\\t\\t\\t\\tthis._geometryData.indexCount = this.indexBuffer[0].numIndices;\\n\\t\\t\\t\\tthis._geometryData.maxIndices = this.indexBuffer[0].numIndices;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tclear(verticesDynamic, indicesDynamic, maxVertices = 0, maxIndices = 0) {\\n\\t\\tthis._initGeometryData();\\n\\t\\tthis._geometryData.initDefaults();\\n\\t\\tthis._geometryData.recreate = true;\\n\\t\\tthis._geometryData.maxVertices = maxVertices;\\n\\t\\tthis._geometryData.maxIndices = maxIndices;\\n\\t\\tthis._geometryData.verticesUsage = verticesDynamic ? BUFFER_STATIC : BUFFER_DYNAMIC;\\n\\t\\tthis._geometryData.indicesUsage = indicesDynamic ? BUFFER_STATIC : BUFFER_DYNAMIC;\\n\\t}\\n\\tsetVertexStream(semantic, data, componentCount, numVertices, dataType = TYPE_FLOAT32, dataTypeNormalize = false, asInt = false) {\\n\\t\\tthis._initGeometryData();\\n\\t\\tconst vertexCount = numVertices || data.length / componentCount;\\n\\t\\tthis._geometryData._changeVertexCount(vertexCount, semantic);\\n\\t\\tthis._geometryData.vertexStreamsUpdated = true;\\n\\t\\tthis._geometryData.vertexStreamDictionary[semantic] = new GeometryVertexStream(\\n\\t\\t\\tdata,\\n\\t\\t\\tcomponentCount,\\n\\t\\t\\tdataType,\\n\\t\\t\\tdataTypeNormalize,\\n\\t\\t\\tasInt\\n\\t\\t);\\n\\t}\\n\\tgetVertexStream(semantic, data) {\\n\\t\\tlet count = 0;\\n\\t\\tlet done = false;\\n\\t\\tif (this._geometryData) {\\n\\t\\t\\tconst stream = this._geometryData.vertexStreamDictionary[semantic];\\n\\t\\t\\tif (stream) {\\n\\t\\t\\t\\tdone = true;\\n\\t\\t\\t\\tcount = this._geometryData.vertexCount;\\n\\t\\t\\t\\tif (ArrayBuffer.isView(data)) {\\n\\t\\t\\t\\t\\tdata.set(stream.data);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tdata.length = 0;\\n\\t\\t\\t\\t\\tdata.push(stream.data);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (!done) {\\n\\t\\t\\tif (this.vertexBuffer) {\\n\\t\\t\\t\\tconst iterator = new VertexIterator(this.vertexBuffer);\\n\\t\\t\\t\\tcount = iterator.readData(semantic, data);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn count;\\n\\t}\\n\\tsetPositions(positions, componentCount = GeometryData.DEFAULT_COMPONENTS_POSITION, numVertices) {\\n\\t\\tthis.setVertexStream(SEMANTIC_POSITION, positions, componentCount, numVertices, TYPE_FLOAT32, false);\\n\\t}\\n\\tsetNormals(normals, componentCount = GeometryData.DEFAULT_COMPONENTS_NORMAL, numVertices) {\\n\\t\\tthis.setVertexStream(SEMANTIC_NORMAL, normals, componentCount, numVertices, TYPE_FLOAT32, false);\\n\\t}\\n\\tsetUvs(channel, uvs, componentCount = GeometryData.DEFAULT_COMPONENTS_UV, numVertices) {\\n\\t\\tthis.setVertexStream(SEMANTIC_TEXCOORD + channel, uvs, componentCount, numVertices, TYPE_FLOAT32, false);\\n\\t}\\n\\tsetColors(colors, componentCount = GeometryData.DEFAULT_COMPONENTS_COLORS, numVertices) {\\n\\t\\tthis.setVertexStream(SEMANTIC_COLOR, colors, componentCount, numVertices, TYPE_FLOAT32, false);\\n\\t}\\n\\tsetColors32(colors, numVertices) {\\n\\t\\tthis.setVertexStream(SEMANTIC_COLOR, colors, GeometryData.DEFAULT_COMPONENTS_COLORS, numVertices, TYPE_UINT8, true);\\n\\t}\\n\\tsetIndices(indices, numIndices) {\\n\\t\\tthis._initGeometryData();\\n\\t\\tthis._geometryData.indexStreamUpdated = true;\\n\\t\\tthis._geometryData.indices = indices;\\n\\t\\tthis._geometryData.indexCount = numIndices || indices.length;\\n\\t}\\n\\tgetPositions(positions) {\\n\\t\\treturn this.getVertexStream(SEMANTIC_POSITION, positions);\\n\\t}\\n\\tgetNormals(normals) {\\n\\t\\treturn this.getVertexStream(SEMANTIC_NORMAL, normals);\\n\\t}\\n\\tgetUvs(channel, uvs) {\\n\\t\\treturn this.getVertexStream(SEMANTIC_TEXCOORD + channel, uvs);\\n\\t}\\n\\tgetColors(colors) {\\n\\t\\treturn this.getVertexStream(SEMANTIC_COLOR, colors);\\n\\t}\\n\\tgetIndices(indices) {\\n\\t\\tlet count = 0;\\n\\t\\tif (this._geometryData && this._geometryData.indices) {\\n\\t\\t\\tconst streamIndices = this._geometryData.indices;\\n\\t\\t\\tcount = this._geometryData.indexCount;\\n\\t\\t\\tif (ArrayBuffer.isView(indices)) {\\n\\t\\t\\t\\tindices.set(streamIndices);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tindices.length = 0;\\n\\t\\t\\t\\tfor (let i = 0, il = streamIndices.length; i < il; i++) {\\n\\t\\t\\t\\t\\tindices.push(streamIndices[i]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tif (this.indexBuffer.length > 0 && this.indexBuffer[0]) {\\n\\t\\t\\t\\tconst indexBuffer = this.indexBuffer[0];\\n\\t\\t\\t\\tcount = indexBuffer.readData(indices);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn count;\\n\\t}\\n\\tupdate(primitiveType = PRIMITIVE_TRIANGLES, updateBoundingBox = true) {\\n\\t\\tif (this._geometryData) {\\n\\t\\t\\tif (updateBoundingBox) {\\n\\t\\t\\t\\tconst stream = this._geometryData.vertexStreamDictionary[SEMANTIC_POSITION];\\n\\t\\t\\t\\tif (stream) {\\n\\t\\t\\t\\t\\tif (stream.componentCount === 3) {\\n\\t\\t\\t\\t\\t\\tthis._aabb.compute(stream.data, this._geometryData.vertexCount);\\n\\t\\t\\t\\t\\t\\tthis._aabbVer++;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tlet destroyVB = this._geometryData.recreate;\\n\\t\\t\\tif (this._geometryData.vertexCount > this._geometryData.maxVertices) {\\n\\t\\t\\t\\tdestroyVB = true;\\n\\t\\t\\t\\tthis._geometryData.maxVertices = this._geometryData.vertexCount;\\n\\t\\t\\t}\\n\\t\\t\\tif (destroyVB) {\\n\\t\\t\\t\\tif (this.vertexBuffer) {\\n\\t\\t\\t\\t\\tthis.vertexBuffer.destroy();\\n\\t\\t\\t\\t\\tthis.vertexBuffer = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tlet destroyIB = this._geometryData.recreate;\\n\\t\\t\\tif (this._geometryData.indexCount > this._geometryData.maxIndices) {\\n\\t\\t\\t\\tdestroyIB = true;\\n\\t\\t\\t\\tthis._geometryData.maxIndices = this._geometryData.indexCount;\\n\\t\\t\\t}\\n\\t\\t\\tif (destroyIB) {\\n\\t\\t\\t\\tif (this.indexBuffer.length > 0 && this.indexBuffer[0]) {\\n\\t\\t\\t\\t\\tthis.indexBuffer[0].destroy();\\n\\t\\t\\t\\t\\tthis.indexBuffer[0] = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (this._geometryData.vertexStreamsUpdated) {\\n\\t\\t\\t\\tthis._updateVertexBuffer();\\n\\t\\t\\t}\\n\\t\\t\\tif (this._geometryData.indexStreamUpdated) {\\n\\t\\t\\t\\tthis._updateIndexBuffer();\\n\\t\\t\\t}\\n\\t\\t\\tthis.primitive[0].type = primitiveType;\\n\\t\\t\\tif (this.indexBuffer.length > 0 && this.indexBuffer[0]) {\\n\\t\\t\\t\\tif (this._geometryData.indexStreamUpdated) {\\n\\t\\t\\t\\t\\tthis.primitive[0].count = this._geometryData.indexCount;\\n\\t\\t\\t\\t\\tthis.primitive[0].indexed = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (this._geometryData.vertexStreamsUpdated) {\\n\\t\\t\\t\\t\\tthis.primitive[0].count = this._geometryData.vertexCount;\\n\\t\\t\\t\\t\\tthis.primitive[0].indexed = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis._geometryData.vertexCount = 0;\\n\\t\\t\\tthis._geometryData.indexCount = 0;\\n\\t\\t\\tthis._geometryData.vertexStreamsUpdated = false;\\n\\t\\t\\tthis._geometryData.indexStreamUpdated = false;\\n\\t\\t\\tthis._geometryData.recreate = false;\\n\\t\\t\\tthis.updateRenderStates();\\n\\t\\t}\\n\\t}\\n\\t// builds vertex format based on attached vertex streams\\n\\t_buildVertexFormat(vertexCount) {\\n\\t\\tconst vertexDesc = [];\\n\\t\\tfor (const semantic in this._geometryData.vertexStreamDictionary) {\\n\\t\\t\\tconst stream = this._geometryData.vertexStreamDictionary[semantic];\\n\\t\\t\\tvertexDesc.push({\\n\\t\\t\\t\\tsemantic,\\n\\t\\t\\t\\tcomponents: stream.componentCount,\\n\\t\\t\\t\\ttype: stream.dataType,\\n\\t\\t\\t\\tnormalize: stream.dataTypeNormalize,\\n\\t\\t\\t\\tasInt: stream.asInt\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\treturn new VertexFormat(this.device, vertexDesc, vertexCount);\\n\\t}\\n\\t// copy attached data into vertex buffer\\n\\t_updateVertexBuffer() {\\n\\t\\tif (!this.vertexBuffer) {\\n\\t\\t\\tconst allocateVertexCount = this._geometryData.maxVertices;\\n\\t\\t\\tconst format = this._buildVertexFormat(allocateVertexCount);\\n\\t\\t\\tthis.vertexBuffer = new VertexBuffer(this.device, format, allocateVertexCount, {\\n\\t\\t\\t\\tusage: this._geometryData.verticesUsage,\\n\\t\\t\\t\\tstorage: this._storageVertex\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tconst iterator = new VertexIterator(this.vertexBuffer);\\n\\t\\tconst numVertices = this._geometryData.vertexCount;\\n\\t\\tfor (const semantic in this._geometryData.vertexStreamDictionary) {\\n\\t\\t\\tconst stream = this._geometryData.vertexStreamDictionary[semantic];\\n\\t\\t\\titerator.writeData(semantic, stream.data, numVertices);\\n\\t\\t\\tdelete this._geometryData.vertexStreamDictionary[semantic];\\n\\t\\t}\\n\\t\\titerator.end();\\n\\t}\\n\\t// copy attached data into index buffer\\n\\t_updateIndexBuffer() {\\n\\t\\tif (this.indexBuffer.length <= 0 || !this.indexBuffer[0]) {\\n\\t\\t\\tconst maxVertices = this._geometryData.maxVertices;\\n\\t\\t\\tconst createFormat = maxVertices > 65535 || maxVertices === 0 ? INDEXFORMAT_UINT32 : INDEXFORMAT_UINT16;\\n\\t\\t\\tconst options = this._storageIndex ? { storage: true } : void 0;\\n\\t\\t\\tthis.indexBuffer[0] = new IndexBuffer(this.device, createFormat, this._geometryData.maxIndices, this._geometryData.indicesUsage, void 0, options);\\n\\t\\t}\\n\\t\\tconst srcIndices = this._geometryData.indices;\\n\\t\\tif (srcIndices) {\\n\\t\\t\\tconst indexBuffer = this.indexBuffer[0];\\n\\t\\t\\tindexBuffer.writeData(srcIndices, this._geometryData.indexCount);\\n\\t\\t\\tthis._geometryData.indices = null;\\n\\t\\t}\\n\\t}\\n\\t// prepares the mesh to be rendered with specific render style\\n\\tprepareRenderState(renderStyle) {\\n\\t\\tif (renderStyle === RENDERSTYLE_WIREFRAME) {\\n\\t\\t\\tthis.generateWireframe();\\n\\t\\t} else if (renderStyle === RENDERSTYLE_POINTS) {\\n\\t\\t\\tthis.primitive[RENDERSTYLE_POINTS] = {\\n\\t\\t\\t\\ttype: PRIMITIVE_POINTS,\\n\\t\\t\\t\\tbase: 0,\\n\\t\\t\\t\\tbaseVertex: 0,\\n\\t\\t\\t\\tcount: this.vertexBuffer ? this.vertexBuffer.numVertices : 0,\\n\\t\\t\\t\\tindexed: false\\n\\t\\t\\t};\\n\\t\\t}\\n\\t}\\n\\t// updates existing render states with changes to solid render state\\n\\tupdateRenderStates() {\\n\\t\\tif (this.primitive[RENDERSTYLE_POINTS]) {\\n\\t\\t\\tthis.prepareRenderState(RENDERSTYLE_POINTS);\\n\\t\\t}\\n\\t\\tif (this.primitive[RENDERSTYLE_WIREFRAME]) {\\n\\t\\t\\tthis.prepareRenderState(RENDERSTYLE_WIREFRAME);\\n\\t\\t}\\n\\t}\\n\\tgenerateWireframe() {\\n\\t\\tthis._destroyIndexBuffer(RENDERSTYLE_WIREFRAME);\\n\\t\\tconst numVertices = this.vertexBuffer.numVertices;\\n\\t\\tlet lines;\\n\\t\\tlet format;\\n\\t\\tif (this.indexBuffer.length > 0 && this.indexBuffer[0]) {\\n\\t\\t\\tconst offsets = [[0, 1], [1, 2], [2, 0]];\\n\\t\\t\\tconst base = this.primitive[RENDERSTYLE_SOLID].base;\\n\\t\\t\\tconst count = this.primitive[RENDERSTYLE_SOLID].count;\\n\\t\\t\\tconst baseVertex = this.primitive[RENDERSTYLE_SOLID].baseVertex || 0;\\n\\t\\t\\tconst indexBuffer = this.indexBuffer[RENDERSTYLE_SOLID];\\n\\t\\t\\tconst indicesArrayType = typedArrayIndexFormats[indexBuffer.format];\\n\\t\\t\\tconst srcIndices = new indicesArrayType(indexBuffer.storage);\\n\\t\\t\\tconst tmpIndices = new indicesArrayType(count * 2);\\n\\t\\t\\tconst seen = /* @__PURE__ */ new Set();\\n\\t\\t\\tlet len = 0;\\n\\t\\t\\tfor (let j = base; j < base + count; j += 3) {\\n\\t\\t\\t\\tfor (let k = 0; k < 3; k++) {\\n\\t\\t\\t\\t\\tconst i1 = srcIndices[j + offsets[k][0]] + baseVertex;\\n\\t\\t\\t\\t\\tconst i2 = srcIndices[j + offsets[k][1]] + baseVertex;\\n\\t\\t\\t\\t\\tconst hash = i1 > i2 ? i2 * numVertices + i1 : i1 * numVertices + i2;\\n\\t\\t\\t\\t\\tif (!seen.has(hash)) {\\n\\t\\t\\t\\t\\t\\tseen.add(hash);\\n\\t\\t\\t\\t\\t\\ttmpIndices[len++] = i1;\\n\\t\\t\\t\\t\\t\\ttmpIndices[len++] = i2;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tseen.clear();\\n\\t\\t\\tformat = indexBuffer.format;\\n\\t\\t\\tlines = tmpIndices.slice(0, len);\\n\\t\\t} else {\\n\\t\\t\\tconst safeNumVertices = numVertices - numVertices % 3;\\n\\t\\t\\tconst count = safeNumVertices / 3 * 6;\\n\\t\\t\\tformat = count > 65535 ? INDEXFORMAT_UINT32 : INDEXFORMAT_UINT16;\\n\\t\\t\\tlines = count > 65535 ? new Uint32Array(count) : new Uint16Array(count);\\n\\t\\t\\tlet idx = 0;\\n\\t\\t\\tfor (let i = 0; i < safeNumVertices; i += 3) {\\n\\t\\t\\t\\tlines[idx++] = i;\\n\\t\\t\\t\\tlines[idx++] = i + 1;\\n\\t\\t\\t\\tlines[idx++] = i + 1;\\n\\t\\t\\t\\tlines[idx++] = i + 2;\\n\\t\\t\\t\\tlines[idx++] = i + 2;\\n\\t\\t\\t\\tlines[idx++] = i;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst wireBuffer = new IndexBuffer(this.vertexBuffer.device, format, lines.length, BUFFER_STATIC, lines.buffer);\\n\\t\\tthis.primitive[RENDERSTYLE_WIREFRAME] = {\\n\\t\\t\\ttype: PRIMITIVE_LINES,\\n\\t\\t\\tbase: 0,\\n\\t\\t\\tbaseVertex: 0,\\n\\t\\t\\tcount: lines.length,\\n\\t\\t\\tindexed: true\\n\\t\\t};\\n\\t\\tthis.indexBuffer[RENDERSTYLE_WIREFRAME] = wireBuffer;\\n\\t}\\n}\\n\\nconst scaleCompensatePosTransform = new Mat4();\\nconst scaleCompensatePos = new Vec3();\\nconst scaleCompensateRot = new Quat();\\nconst scaleCompensateRot2 = new Quat();\\nconst scaleCompensateScale = new Vec3();\\nconst scaleCompensateScaleForParent = new Vec3();\\nconst tmpMat4 = new Mat4();\\nconst tmpQuat = new Quat();\\nconst position = new Vec3();\\nconst invParentWtm = new Mat4();\\nconst rotation$4 = new Quat();\\nconst invParentRot = new Quat();\\nconst matrix = new Mat4();\\nconst target = new Vec3();\\nconst up$2 = new Vec3();\\nfunction createTest(attr, value) {\\n\\tif (attr instanceof Function) {\\n\\t\\treturn attr;\\n\\t}\\n\\treturn (node) => {\\n\\t\\tlet x = node[attr];\\n\\t\\tif (x instanceof Function) {\\n\\t\\t\\tx = x();\\n\\t\\t}\\n\\t\\treturn x === value;\\n\\t};\\n}\\nfunction findNode(node, test) {\\n\\tif (test(node)) {\\n\\t\\treturn node;\\n\\t}\\n\\tconst children = node._children;\\n\\tconst len = children.length;\\n\\tfor (let i = 0; i < len; ++i) {\\n\\t\\tconst result = findNode(children[i], test);\\n\\t\\tif (result) {\\n\\t\\t\\treturn result;\\n\\t\\t}\\n\\t}\\n\\treturn null;\\n}\\nclass GraphNode extends EventHandler {\\n\\tname;\\n\\ttags = new Tags(this);\\n\\t// Local space properties of transform (only first 3 are settable by the user)\\n\\tlocalPosition = new Vec3();\\n\\tlocalRotation = new Quat();\\n\\tlocalScale = new Vec3(1, 1, 1);\\n\\tlocalEulerAngles = new Vec3();\\n\\t// Only calculated on request\\n\\t// World space properties of transform\\n\\tposition = new Vec3();\\n\\trotation = new Quat();\\n\\teulerAngles = new Vec3();\\n\\t_scale = null;\\n\\tlocalTransform = new Mat4();\\n\\t_dirtyLocal = false;\\n\\t_aabbVer = 0;\\n\\t_frozen = false;\\n\\tworldTransform = new Mat4();\\n\\t_dirtyWorld = false;\\n\\t_worldScaleSign = 0;\\n\\t_normalMatrix = new Mat3();\\n\\t_dirtyNormal = true;\\n\\t_right = null;\\n\\t_up = null;\\n\\t_forward = null;\\n\\t_parent = null;\\n\\t_children = [];\\n\\t_graphDepth = 0;\\n\\t_enabled = true;\\n\\t_enabledInHierarchy = false;\\n\\tscaleCompensation = false;\\n\\tconstructor(name = \\\"Untitled\\\") {\\n\\t\\tsuper();\\n\\t\\tthis.name = name;\\n\\t}\\n\\tget right() {\\n\\t\\tif (!this._right) {\\n\\t\\t\\tthis._right = new Vec3();\\n\\t\\t}\\n\\t\\treturn this.getWorldTransform().getX(this._right).normalize();\\n\\t}\\n\\tget up() {\\n\\t\\tif (!this._up) {\\n\\t\\t\\tthis._up = new Vec3();\\n\\t\\t}\\n\\t\\treturn this.getWorldTransform().getY(this._up).normalize();\\n\\t}\\n\\tget forward() {\\n\\t\\tif (!this._forward) {\\n\\t\\t\\tthis._forward = new Vec3();\\n\\t\\t}\\n\\t\\treturn this.getWorldTransform().getZ(this._forward).normalize().mulScalar(-1);\\n\\t}\\n\\tget normalMatrix() {\\n\\t\\tconst normalMat = this._normalMatrix;\\n\\t\\tif (this._dirtyNormal) {\\n\\t\\t\\tnormalMat.invertMat4(this.getWorldTransform()).transpose();\\n\\t\\t\\tthis._dirtyNormal = false;\\n\\t\\t}\\n\\t\\treturn normalMat;\\n\\t}\\n\\tset enabled(enabled) {\\n\\t\\tif (this._enabled !== enabled) {\\n\\t\\t\\tthis._enabled = enabled;\\n\\t\\t\\tif (enabled && this._parent?.enabled || !enabled) {\\n\\t\\t\\t\\tthis._notifyHierarchyStateChanged(this, enabled);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget enabled() {\\n\\t\\treturn this._enabled && this._enabledInHierarchy;\\n\\t}\\n\\tget parent() {\\n\\t\\treturn this._parent;\\n\\t}\\n\\tget path() {\\n\\t\\tlet node = this._parent;\\n\\t\\tif (!node) {\\n\\t\\t\\treturn \\\"\\\";\\n\\t\\t}\\n\\t\\tlet result = this.name;\\n\\t\\twhile (node && node._parent) {\\n\\t\\t\\tresult = `${node.name}/${result}`;\\n\\t\\t\\tnode = node._parent;\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n\\tget root() {\\n\\t\\tlet result = this;\\n\\t\\twhile (result._parent) {\\n\\t\\t\\tresult = result._parent;\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n\\tget children() {\\n\\t\\treturn this._children;\\n\\t}\\n\\tget graphDepth() {\\n\\t\\treturn this._graphDepth;\\n\\t}\\n\\t_notifyHierarchyStateChanged(node, enabled) {\\n\\t\\tnode._onHierarchyStateChanged(enabled);\\n\\t\\tconst c = node._children;\\n\\t\\tfor (let i = 0, len = c.length; i < len; i++) {\\n\\t\\t\\tif (c[i]._enabled) {\\n\\t\\t\\t\\tthis._notifyHierarchyStateChanged(c[i], enabled);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_onHierarchyStateChanged(enabled) {\\n\\t\\tthis._enabledInHierarchy = enabled;\\n\\t\\tif (enabled && !this._frozen) {\\n\\t\\t\\tthis._unfreezeParentToRoot();\\n\\t\\t}\\n\\t}\\n\\t_cloneInternal(clone) {\\n\\t\\tclone.name = this.name;\\n\\t\\tconst tags = this.tags._list;\\n\\t\\tclone.tags.clear();\\n\\t\\tfor (let i = 0; i < tags.length; i++) {\\n\\t\\t\\tclone.tags.add(tags[i]);\\n\\t\\t}\\n\\t\\tclone.localPosition.copy(this.localPosition);\\n\\t\\tclone.localRotation.copy(this.localRotation);\\n\\t\\tclone.localScale.copy(this.localScale);\\n\\t\\tclone.localEulerAngles.copy(this.localEulerAngles);\\n\\t\\tclone.position.copy(this.position);\\n\\t\\tclone.rotation.copy(this.rotation);\\n\\t\\tclone.eulerAngles.copy(this.eulerAngles);\\n\\t\\tclone.localTransform.copy(this.localTransform);\\n\\t\\tclone._dirtyLocal = this._dirtyLocal;\\n\\t\\tclone.worldTransform.copy(this.worldTransform);\\n\\t\\tclone._dirtyWorld = this._dirtyWorld;\\n\\t\\tclone._dirtyNormal = this._dirtyNormal;\\n\\t\\tclone._aabbVer = this._aabbVer + 1;\\n\\t\\tclone._enabled = this._enabled;\\n\\t\\tclone.scaleCompensation = this.scaleCompensation;\\n\\t\\tclone._enabledInHierarchy = false;\\n\\t}\\n\\tclone() {\\n\\t\\tconst clone = new this.constructor();\\n\\t\\tthis._cloneInternal(clone);\\n\\t\\treturn clone;\\n\\t}\\n\\tcopy(source) {\\n\\t\\tsource._cloneInternal(this);\\n\\t\\treturn this;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.remove();\\n\\t\\tconst children = this._children;\\n\\t\\twhile (children.length) {\\n\\t\\t\\tconst child = children.pop();\\n\\t\\t\\tchild._parent = null;\\n\\t\\t\\tchild.destroy();\\n\\t\\t}\\n\\t\\tthis.fire(\\\"destroy\\\", this);\\n\\t\\tthis.off();\\n\\t}\\n\\tfind(attr, value) {\\n\\t\\tconst results = [];\\n\\t\\tconst test = createTest(attr, value);\\n\\t\\tthis.forEach((node) => {\\n\\t\\t\\tif (test(node)) {\\n\\t\\t\\t\\tresults.push(node);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\treturn results;\\n\\t}\\n\\tfindOne(attr, value) {\\n\\t\\tconst test = createTest(attr, value);\\n\\t\\treturn findNode(this, test);\\n\\t}\\n\\tfindByTag(...query) {\\n\\t\\tconst results = [];\\n\\t\\tconst queryNode = (node, checkNode) => {\\n\\t\\t\\tif (checkNode && node.tags.has(...query)) {\\n\\t\\t\\t\\tresults.push(node);\\n\\t\\t\\t}\\n\\t\\t\\tfor (let i = 0; i < node._children.length; i++) {\\n\\t\\t\\t\\tqueryNode(node._children[i], true);\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tqueryNode(this, false);\\n\\t\\treturn results;\\n\\t}\\n\\tfindByName(name) {\\n\\t\\treturn this.findOne(\\\"name\\\", name);\\n\\t}\\n\\tfindByPath(path) {\\n\\t\\tconst parts = Array.isArray(path) ? path : path.split(\\\"/\\\");\\n\\t\\tlet result = this;\\n\\t\\tfor (let i = 0, imax = parts.length; i < imax; ++i) {\\n\\t\\t\\tresult = result.children.find((c) => c.name === parts[i]);\\n\\t\\t\\tif (!result) {\\n\\t\\t\\t\\treturn null;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n\\tforEach(callback, thisArg) {\\n\\t\\tcallback.call(thisArg, this);\\n\\t\\tconst children = this._children;\\n\\t\\tconst len = children.length;\\n\\t\\tfor (let i = 0; i < len; ++i) {\\n\\t\\t\\tchildren[i].forEach(callback, thisArg);\\n\\t\\t}\\n\\t}\\n\\tisDescendantOf(node) {\\n\\t\\tlet parent = this._parent;\\n\\t\\twhile (parent) {\\n\\t\\t\\tif (parent === node) {\\n\\t\\t\\t\\treturn true;\\n\\t\\t\\t}\\n\\t\\t\\tparent = parent._parent;\\n\\t\\t}\\n\\t\\treturn false;\\n\\t}\\n\\tisAncestorOf(node) {\\n\\t\\treturn node.isDescendantOf(this);\\n\\t}\\n\\tgetEulerAngles() {\\n\\t\\tthis.getWorldTransform().getEulerAngles(this.eulerAngles);\\n\\t\\treturn this.eulerAngles;\\n\\t}\\n\\tgetLocalEulerAngles() {\\n\\t\\tthis.localRotation.getEulerAngles(this.localEulerAngles);\\n\\t\\treturn this.localEulerAngles;\\n\\t}\\n\\tgetLocalPosition() {\\n\\t\\treturn this.localPosition;\\n\\t}\\n\\tgetLocalRotation() {\\n\\t\\treturn this.localRotation;\\n\\t}\\n\\tgetLocalScale() {\\n\\t\\treturn this.localScale;\\n\\t}\\n\\tgetLocalTransform() {\\n\\t\\tif (this._dirtyLocal) {\\n\\t\\t\\tthis.localTransform.setTRS(this.localPosition, this.localRotation, this.localScale);\\n\\t\\t\\tthis._dirtyLocal = false;\\n\\t\\t}\\n\\t\\treturn this.localTransform;\\n\\t}\\n\\tgetPosition() {\\n\\t\\tthis.getWorldTransform().getTranslation(this.position);\\n\\t\\treturn this.position;\\n\\t}\\n\\tgetRotation() {\\n\\t\\tthis.rotation.setFromMat4(this.getWorldTransform());\\n\\t\\treturn this.rotation;\\n\\t}\\n\\tgetScale() {\\n\\t\\tif (!this._scale) {\\n\\t\\t\\tthis._scale = new Vec3();\\n\\t\\t}\\n\\t\\treturn this.getWorldTransform().getScale(this._scale);\\n\\t}\\n\\tgetWorldTransform() {\\n\\t\\tif (!this._dirtyLocal && !this._dirtyWorld) {\\n\\t\\t\\treturn this.worldTransform;\\n\\t\\t}\\n\\t\\tif (this._parent) {\\n\\t\\t\\tthis._parent.getWorldTransform();\\n\\t\\t}\\n\\t\\tthis._sync();\\n\\t\\treturn this.worldTransform;\\n\\t}\\n\\tget worldScaleSign() {\\n\\t\\tif (this._worldScaleSign === 0) {\\n\\t\\t\\tthis._worldScaleSign = this.getWorldTransform().scaleSign;\\n\\t\\t}\\n\\t\\treturn this._worldScaleSign;\\n\\t}\\n\\tremove() {\\n\\t\\tthis._parent?.removeChild(this);\\n\\t}\\n\\treparent(parent, index) {\\n\\t\\tthis.remove();\\n\\t\\tif (parent) {\\n\\t\\t\\tif (index >= 0) {\\n\\t\\t\\t\\tparent.insertChild(this, index);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tparent.addChild(this);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tsetLocalEulerAngles(x, y, z) {\\n\\t\\tthis.localRotation.setFromEulerAngles(x, y, z);\\n\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t}\\n\\t}\\n\\tsetLocalPosition(x, y, z) {\\n\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\tthis.localPosition.copy(x);\\n\\t\\t} else {\\n\\t\\t\\tthis.localPosition.set(x, y, z);\\n\\t\\t}\\n\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t}\\n\\t}\\n\\tsetLocalRotation(x, y, z, w) {\\n\\t\\tif (x instanceof Quat) {\\n\\t\\t\\tthis.localRotation.copy(x);\\n\\t\\t} else {\\n\\t\\t\\tthis.localRotation.set(x, y, z, w);\\n\\t\\t}\\n\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t}\\n\\t}\\n\\tsetLocalScale(x, y, z) {\\n\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\tthis.localScale.copy(x);\\n\\t\\t} else {\\n\\t\\t\\tthis.localScale.set(x, y, z);\\n\\t\\t}\\n\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t}\\n\\t}\\n\\t_dirtifyLocal() {\\n\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\tthis._dirtyLocal = true;\\n\\t\\t\\tif (!this._dirtyWorld) {\\n\\t\\t\\t\\tthis._dirtifyWorld();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_unfreezeParentToRoot() {\\n\\t\\tlet p = this._parent;\\n\\t\\twhile (p) {\\n\\t\\t\\tp._frozen = false;\\n\\t\\t\\tp = p._parent;\\n\\t\\t}\\n\\t}\\n\\t_dirtifyWorld() {\\n\\t\\tif (!this._dirtyWorld) {\\n\\t\\t\\tthis._unfreezeParentToRoot();\\n\\t\\t}\\n\\t\\tthis._dirtifyWorldInternal();\\n\\t}\\n\\t_dirtifyWorldInternal() {\\n\\t\\tif (!this._dirtyWorld) {\\n\\t\\t\\tthis._frozen = false;\\n\\t\\t\\tthis._dirtyWorld = true;\\n\\t\\t\\tfor (let i = 0; i < this._children.length; i++) {\\n\\t\\t\\t\\tif (!this._children[i]._dirtyWorld) {\\n\\t\\t\\t\\t\\tthis._children[i]._dirtifyWorldInternal();\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._dirtyNormal = true;\\n\\t\\tthis._worldScaleSign = 0;\\n\\t\\tthis._aabbVer++;\\n\\t}\\n\\tsetPosition(x, y, z) {\\n\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\tposition.copy(x);\\n\\t\\t} else {\\n\\t\\t\\tposition.set(x, y, z);\\n\\t\\t}\\n\\t\\tif (this._parent === null) {\\n\\t\\t\\tthis.localPosition.copy(position);\\n\\t\\t} else {\\n\\t\\t\\tinvParentWtm.copy(this._parent.getWorldTransform()).invert();\\n\\t\\t\\tinvParentWtm.transformPoint(position, this.localPosition);\\n\\t\\t}\\n\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t}\\n\\t}\\n\\tsetRotation(x, y, z, w) {\\n\\t\\tif (x instanceof Quat) {\\n\\t\\t\\trotation$4.copy(x);\\n\\t\\t} else {\\n\\t\\t\\trotation$4.set(x, y, z, w);\\n\\t\\t}\\n\\t\\tif (this._parent === null) {\\n\\t\\t\\tthis.localRotation.copy(rotation$4);\\n\\t\\t} else {\\n\\t\\t\\tconst parentRot = this._parent.getRotation();\\n\\t\\t\\tinvParentRot.copy(parentRot).invert();\\n\\t\\t\\tthis.localRotation.copy(invParentRot).mul(rotation$4);\\n\\t\\t}\\n\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t}\\n\\t}\\n\\tsetPositionAndRotation(position2, rotation2) {\\n\\t\\tif (this._parent === null) {\\n\\t\\t\\tthis.localPosition.copy(position2);\\n\\t\\t\\tthis.localRotation.copy(rotation2);\\n\\t\\t} else {\\n\\t\\t\\tconst parentWtm = this._parent.getWorldTransform();\\n\\t\\t\\tinvParentWtm.copy(parentWtm).invert();\\n\\t\\t\\tinvParentWtm.transformPoint(position2, this.localPosition);\\n\\t\\t\\tthis.localRotation.setFromMat4(invParentWtm).mul(rotation2);\\n\\t\\t}\\n\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t}\\n\\t}\\n\\tsetEulerAngles(x, y, z) {\\n\\t\\tthis.localRotation.setFromEulerAngles(x, y, z);\\n\\t\\tif (this._parent !== null) {\\n\\t\\t\\tconst parentRot = this._parent.getRotation();\\n\\t\\t\\tinvParentRot.copy(parentRot).invert();\\n\\t\\t\\tthis.localRotation.mul2(invParentRot, this.localRotation);\\n\\t\\t}\\n\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t}\\n\\t}\\n\\taddChild(node) {\\n\\t\\tthis._prepareInsertChild(node);\\n\\t\\tthis._children.push(node);\\n\\t\\tthis._onInsertChild(node);\\n\\t}\\n\\taddChildAndSaveTransform(node) {\\n\\t\\tconst wPos = node.getPosition();\\n\\t\\tconst wRot = node.getRotation();\\n\\t\\tthis._prepareInsertChild(node);\\n\\t\\tnode.setPosition(tmpMat4.copy(this.worldTransform).invert().transformPoint(wPos));\\n\\t\\tnode.setRotation(tmpQuat.copy(this.getRotation()).invert().mul(wRot));\\n\\t\\tthis._children.push(node);\\n\\t\\tthis._onInsertChild(node);\\n\\t}\\n\\tinsertChild(node, index) {\\n\\t\\tthis._prepareInsertChild(node);\\n\\t\\tthis._children.splice(index, 0, node);\\n\\t\\tthis._onInsertChild(node);\\n\\t}\\n\\t_prepareInsertChild(node) {\\n\\t\\tnode.remove();\\n\\t}\\n\\t_fireOnHierarchy(name, nameHierarchy, parent) {\\n\\t\\tthis.fire(name, parent);\\n\\t\\tfor (let i = 0; i < this._children.length; i++) {\\n\\t\\t\\tthis._children[i]._fireOnHierarchy(nameHierarchy, nameHierarchy, parent);\\n\\t\\t}\\n\\t}\\n\\t_onInsertChild(node) {\\n\\t\\tnode._parent = this;\\n\\t\\tconst enabledInHierarchy = node._enabled && this.enabled;\\n\\t\\tif (node._enabledInHierarchy !== enabledInHierarchy) {\\n\\t\\t\\tnode._enabledInHierarchy = enabledInHierarchy;\\n\\t\\t\\tnode._notifyHierarchyStateChanged(node, enabledInHierarchy);\\n\\t\\t}\\n\\t\\tnode._updateGraphDepth();\\n\\t\\tnode._dirtifyWorld();\\n\\t\\tif (this._frozen) {\\n\\t\\t\\tnode._unfreezeParentToRoot();\\n\\t\\t}\\n\\t\\tnode._fireOnHierarchy(\\\"insert\\\", \\\"inserthierarchy\\\", this);\\n\\t\\tif (this.fire) this.fire(\\\"childinsert\\\", node);\\n\\t}\\n\\t_updateGraphDepth() {\\n\\t\\tthis._graphDepth = this._parent ? this._parent._graphDepth + 1 : 0;\\n\\t\\tfor (let i = 0, len = this._children.length; i < len; i++) {\\n\\t\\t\\tthis._children[i]._updateGraphDepth();\\n\\t\\t}\\n\\t}\\n\\tremoveChild(child) {\\n\\t\\tconst index = this._children.indexOf(child);\\n\\t\\tif (index === -1) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._children.splice(index, 1);\\n\\t\\tchild._parent = null;\\n\\t\\tchild._fireOnHierarchy(\\\"remove\\\", \\\"removehierarchy\\\", this);\\n\\t\\tthis.fire(\\\"childremove\\\", child);\\n\\t}\\n\\t_sync() {\\n\\t\\tif (this._dirtyLocal) {\\n\\t\\t\\tthis.localTransform.setTRS(this.localPosition, this.localRotation, this.localScale);\\n\\t\\t\\tthis._dirtyLocal = false;\\n\\t\\t}\\n\\t\\tif (this._dirtyWorld) {\\n\\t\\t\\tif (this._parent === null) {\\n\\t\\t\\t\\tthis.worldTransform.copy(this.localTransform);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (this.scaleCompensation) {\\n\\t\\t\\t\\t\\tlet parentWorldScale;\\n\\t\\t\\t\\t\\tconst parent = this._parent;\\n\\t\\t\\t\\t\\tlet scale = this.localScale;\\n\\t\\t\\t\\t\\tlet parentToUseScaleFrom = parent;\\n\\t\\t\\t\\t\\tif (parentToUseScaleFrom) {\\n\\t\\t\\t\\t\\t\\twhile (parentToUseScaleFrom && parentToUseScaleFrom.scaleCompensation) {\\n\\t\\t\\t\\t\\t\\t\\tparentToUseScaleFrom = parentToUseScaleFrom._parent;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (parentToUseScaleFrom) {\\n\\t\\t\\t\\t\\t\\t\\tparentToUseScaleFrom = parentToUseScaleFrom._parent;\\n\\t\\t\\t\\t\\t\\t\\tif (parentToUseScaleFrom) {\\n\\t\\t\\t\\t\\t\\t\\t\\tparentWorldScale = parentToUseScaleFrom.worldTransform.getScale();\\n\\t\\t\\t\\t\\t\\t\\t\\tscaleCompensateScale.mul2(parentWorldScale, this.localScale);\\n\\t\\t\\t\\t\\t\\t\\t\\tscale = scaleCompensateScale;\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tscaleCompensateRot2.setFromMat4(parent.worldTransform);\\n\\t\\t\\t\\t\\tscaleCompensateRot.mul2(scaleCompensateRot2, this.localRotation);\\n\\t\\t\\t\\t\\tlet tmatrix = parent.worldTransform;\\n\\t\\t\\t\\t\\tif (parent.scaleCompensation) {\\n\\t\\t\\t\\t\\t\\tscaleCompensateScaleForParent.mul2(parentWorldScale, parent.getLocalScale());\\n\\t\\t\\t\\t\\t\\tscaleCompensatePosTransform.setTRS(\\n\\t\\t\\t\\t\\t\\t\\tparent.worldTransform.getTranslation(scaleCompensatePos),\\n\\t\\t\\t\\t\\t\\t\\tscaleCompensateRot2,\\n\\t\\t\\t\\t\\t\\t\\tscaleCompensateScaleForParent\\n\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\ttmatrix = scaleCompensatePosTransform;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\ttmatrix.transformPoint(this.localPosition, scaleCompensatePos);\\n\\t\\t\\t\\t\\tthis.worldTransform.setTRS(scaleCompensatePos, scaleCompensateRot, scale);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tthis.worldTransform.mulAffine2(this._parent.worldTransform, this.localTransform);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis._dirtyWorld = false;\\n\\t\\t}\\n\\t}\\n\\tsyncHierarchy() {\\n\\t\\tif (!this._enabled) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._frozen) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._frozen = true;\\n\\t\\tif (this._dirtyLocal || this._dirtyWorld) {\\n\\t\\t\\tthis._sync();\\n\\t\\t}\\n\\t\\tconst children = this._children;\\n\\t\\tfor (let i = 0, len = children.length; i < len; i++) {\\n\\t\\t\\tchildren[i].syncHierarchy();\\n\\t\\t}\\n\\t}\\n\\tlookAt(x, y, z, ux = 0, uy = 1, uz = 0) {\\n\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\ttarget.copy(x);\\n\\t\\t\\tif (y instanceof Vec3) {\\n\\t\\t\\t\\tup$2.copy(y);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tup$2.copy(Vec3.UP);\\n\\t\\t\\t}\\n\\t\\t} else if (z === void 0) {\\n\\t\\t\\treturn;\\n\\t\\t} else {\\n\\t\\t\\ttarget.set(x, y, z);\\n\\t\\t\\tup$2.set(ux, uy, uz);\\n\\t\\t}\\n\\t\\tmatrix.setLookAt(this.getPosition(), target, up$2);\\n\\t\\trotation$4.setFromMat4(matrix);\\n\\t\\tthis.setRotation(rotation$4);\\n\\t}\\n\\ttranslate(x, y, z) {\\n\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\tposition.copy(x);\\n\\t\\t} else {\\n\\t\\t\\tposition.set(x, y, z);\\n\\t\\t}\\n\\t\\tposition.add(this.getPosition());\\n\\t\\tthis.setPosition(position);\\n\\t}\\n\\ttranslateLocal(x, y, z) {\\n\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\tposition.copy(x);\\n\\t\\t} else {\\n\\t\\t\\tposition.set(x, y, z);\\n\\t\\t}\\n\\t\\tthis.localRotation.transformVector(position, position);\\n\\t\\tthis.localPosition.add(position);\\n\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t}\\n\\t}\\n\\trotate(x, y, z) {\\n\\t\\trotation$4.setFromEulerAngles(x, y, z);\\n\\t\\tif (this._parent === null) {\\n\\t\\t\\tthis.localRotation.mul2(rotation$4, this.localRotation);\\n\\t\\t} else {\\n\\t\\t\\tconst rot = this.getRotation();\\n\\t\\t\\tconst parentRot = this._parent.getRotation();\\n\\t\\t\\tinvParentRot.copy(parentRot).invert();\\n\\t\\t\\trotation$4.mul2(invParentRot, rotation$4);\\n\\t\\t\\tthis.localRotation.mul2(rotation$4, rot);\\n\\t\\t}\\n\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t}\\n\\t}\\n\\trotateLocal(x, y, z) {\\n\\t\\trotation$4.setFromEulerAngles(x, y, z);\\n\\t\\tthis.localRotation.mul(rotation$4);\\n\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t}\\n\\t}\\n}\\n\\nconst defaultMaterialDeviceCache = new DeviceCache();\\nfunction getDefaultMaterial(device) {\\n\\tconst material = defaultMaterialDeviceCache.get(device);\\n\\treturn material;\\n}\\nfunction setDefaultMaterial(device, material) {\\n\\tdefaultMaterialDeviceCache.get(device, () => {\\n\\t\\treturn material;\\n\\t});\\n}\\n\\nclass RefCountedCache {\\n\\tcache = /* @__PURE__ */ new Map();\\n\\tdestroy() {\\n\\t\\tthis.cache.forEach((refCount, object) => {\\n\\t\\t\\tobject.destroy();\\n\\t\\t});\\n\\t\\tthis.cache.clear();\\n\\t}\\n\\tincRef(object) {\\n\\t\\tconst refCount = (this.cache.get(object) || 0) + 1;\\n\\t\\tthis.cache.set(object, refCount);\\n\\t}\\n\\tdecRef(object) {\\n\\t\\tif (object) {\\n\\t\\t\\tlet refCount = this.cache.get(object);\\n\\t\\t\\tif (refCount) {\\n\\t\\t\\t\\trefCount--;\\n\\t\\t\\t\\tif (refCount === 0) {\\n\\t\\t\\t\\t\\tthis.cache.delete(object);\\n\\t\\t\\t\\t\\tobject.destroy();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tthis.cache.set(object, refCount);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\n\\nclass LightmapCache {\\n\\tstatic cache = new RefCountedCache();\\n\\t// add texture reference to lightmap cache\\n\\tstatic incRef(texture) {\\n\\t\\tthis.cache.incRef(texture);\\n\\t}\\n\\t// remove texture reference from lightmap cache\\n\\tstatic decRef(texture) {\\n\\t\\tthis.cache.decRef(texture);\\n\\t}\\n\\tstatic destroy() {\\n\\t\\tthis.cache.destroy();\\n\\t}\\n}\\n\\nclass NumericIds {\\n\\t_counter = 0;\\n\\tget() {\\n\\t\\treturn this._counter++;\\n\\t}\\n}\\n\\nconst PickerId = new NumericIds();\\n\\nconst _tmpAabb = new BoundingBox();\\nconst _tempBoneAabb = new BoundingBox();\\nconst _tempSphere = new BoundingSphere();\\nconst _meshSet = /* @__PURE__ */ new Set();\\nconst lookupHashes = new Uint32Array(4);\\nclass InstancingData {\\n\\tvertexBuffer = null;\\n\\t_destroyVertexBuffer = false;\\n\\tconstructor(numObjects) {\\n\\t\\tthis.count = numObjects;\\n\\t}\\n\\tdestroy() {\\n\\t\\tif (this._destroyVertexBuffer) {\\n\\t\\t\\tthis.vertexBuffer?.destroy();\\n\\t\\t}\\n\\t\\tthis.vertexBuffer = null;\\n\\t}\\n}\\nclass ShaderInstance {\\n\\tshader;\\n\\tbindGroup = null;\\n\\tuniformBuffer = null;\\n\\thashes;\\n\\tgetBindGroup(device) {\\n\\t\\tif (!this.bindGroup) {\\n\\t\\t\\tconst shader = this.shader;\\n\\t\\t\\tconst bindGroupFormat = shader.meshBindGroupFormat;\\n\\t\\t\\tthis.bindGroup = new BindGroup(device, bindGroupFormat);\\n\\t\\t}\\n\\t\\treturn this.bindGroup;\\n\\t}\\n\\tgetUniformBuffer(device) {\\n\\t\\tif (!this.uniformBuffer) {\\n\\t\\t\\tconst shader = this.shader;\\n\\t\\t\\tconst ubFormat = shader.meshUniformBufferFormat;\\n\\t\\t\\tthis.uniformBuffer = new UniformBuffer(device, ubFormat, false);\\n\\t\\t}\\n\\t\\treturn this.uniformBuffer;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.bindGroup?.destroy();\\n\\t\\tthis.bindGroup = null;\\n\\t\\tthis.uniformBuffer?.destroy();\\n\\t\\tthis.uniformBuffer = null;\\n\\t}\\n}\\nclass MeshInstance {\\n\\tcastShadow = false;\\n\\tshadowCascadeMask = SHADOW_CASCADE_ALL;\\n\\tcull = true;\\n\\tdrawOrder = 0;\\n\\t_drawBucket = 127;\\n\\tnode;\\n\\tvisible = true;\\n\\tvisibleThisFrame = false;\\n\\tflipFacesFactor = 1;\\n\\tgsplatInstance = null;\\n\\tid = PickerId.get();\\n\\tisVisibleFunc = null;\\n\\tinstancingData = null;\\n\\tindirectData = null;\\n\\tdrawCommands = null;\\n\\tmeshMetaData = null;\\n\\tparameters = {};\\n\\tpick = true;\\n\\tstencilFront = null;\\n\\tstencilBack = null;\\n\\ttransparent = false;\\n\\t_aabb = new BoundingBox();\\n\\t_aabbVer = -1;\\n\\t_aabbMeshVer = -1;\\n\\t_customAabb = null;\\n\\t_updateAabb = true;\\n\\t_updateAabbFunc = null;\\n\\t_sortKeyShadow = 0;\\n\\t_sortKeyForward = 0;\\n\\t_sortKeyDynamic = 0;\\n\\t_layer = LAYER_WORLD;\\n\\t_material = null;\\n\\t_skinInstance = null;\\n\\t_morphInstance = null;\\n\\t_receiveShadow = true;\\n\\t_renderStyle = RENDERSTYLE_SOLID;\\n\\t_screenSpace = false;\\n\\t_shaderCache = /* @__PURE__ */ new Map();\\n\\t_shaderDefs = MASK_AFFECT_DYNAMIC << 16;\\n\\t_calculateSortDistance = null;\\n\\tconstructor(mesh, material, node = null) {\\n\\t\\tthis.node = node;\\n\\t\\tthis._mesh = mesh;\\n\\t\\tmesh.incRefCount();\\n\\t\\tthis.material = material;\\n\\t\\tif (mesh.vertexBuffer) {\\n\\t\\t\\tconst format = mesh.vertexBuffer.format;\\n\\t\\t\\tthis._shaderDefs |= format.hasUv0 ? SHADERDEF_UV0 : 0;\\n\\t\\t\\tthis._shaderDefs |= format.hasUv1 ? SHADERDEF_UV1 : 0;\\n\\t\\t\\tthis._shaderDefs |= format.hasColor ? SHADERDEF_VCOLOR : 0;\\n\\t\\t\\tthis._shaderDefs |= format.hasTangents ? SHADERDEF_TANGENTS : 0;\\n\\t\\t}\\n\\t\\tthis.updateKey();\\n\\t}\\n\\tset drawBucket(bucket) {\\n\\t\\tthis._drawBucket = Math.floor(bucket) & 255;\\n\\t\\tthis.updateKey();\\n\\t}\\n\\tget drawBucket() {\\n\\t\\treturn this._drawBucket;\\n\\t}\\n\\tset renderStyle(renderStyle) {\\n\\t\\tthis._renderStyle = renderStyle;\\n\\t\\tthis.mesh.prepareRenderState(renderStyle);\\n\\t}\\n\\tget renderStyle() {\\n\\t\\treturn this._renderStyle;\\n\\t}\\n\\tset mesh(mesh) {\\n\\t\\tif (mesh === this._mesh) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._mesh) {\\n\\t\\t\\tthis._mesh.decRefCount();\\n\\t\\t}\\n\\t\\tthis._mesh = mesh;\\n\\t\\tif (mesh) {\\n\\t\\t\\tmesh.incRefCount();\\n\\t\\t}\\n\\t}\\n\\tget mesh() {\\n\\t\\treturn this._mesh;\\n\\t}\\n\\tset aabb(aabb) {\\n\\t\\tthis._aabb = aabb;\\n\\t}\\n\\tget aabb() {\\n\\t\\tif (!this._updateAabb) {\\n\\t\\t\\treturn this._aabb;\\n\\t\\t}\\n\\t\\tif (this._updateAabbFunc) {\\n\\t\\t\\treturn this._updateAabbFunc(this._aabb);\\n\\t\\t}\\n\\t\\tlet localAabb = this._customAabb;\\n\\t\\tlet toWorldSpace = !!localAabb;\\n\\t\\tif (!localAabb) {\\n\\t\\t\\tlocalAabb = _tmpAabb;\\n\\t\\t\\tif (this.skinInstance) {\\n\\t\\t\\t\\tif (!this.mesh.boneAabb) {\\n\\t\\t\\t\\t\\tconst morphTargets = this._morphInstance ? this._morphInstance.morph._targets : null;\\n\\t\\t\\t\\t\\tthis.mesh._initBoneAabbs(morphTargets);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst boneUsed = this.mesh.boneUsed;\\n\\t\\t\\t\\tlet first = true;\\n\\t\\t\\t\\tfor (let i = 0; i < this.mesh.boneAabb.length; i++) {\\n\\t\\t\\t\\t\\tif (boneUsed[i]) {\\n\\t\\t\\t\\t\\t\\t_tempBoneAabb.setFromTransformedAabb(this.mesh.boneAabb[i], this.skinInstance.matrices[i]);\\n\\t\\t\\t\\t\\t\\tif (first) {\\n\\t\\t\\t\\t\\t\\t\\tfirst = false;\\n\\t\\t\\t\\t\\t\\t\\tlocalAabb.center.copy(_tempBoneAabb.center);\\n\\t\\t\\t\\t\\t\\t\\tlocalAabb.halfExtents.copy(_tempBoneAabb.halfExtents);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tlocalAabb.add(_tempBoneAabb);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttoWorldSpace = true;\\n\\t\\t\\t} else if (this.node._aabbVer !== this._aabbVer || this.mesh._aabbVer !== this._aabbMeshVer) {\\n\\t\\t\\t\\tif (this.mesh) {\\n\\t\\t\\t\\t\\tlocalAabb.center.copy(this.mesh.aabb.center);\\n\\t\\t\\t\\t\\tlocalAabb.halfExtents.copy(this.mesh.aabb.halfExtents);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tlocalAabb.center.set(0, 0, 0);\\n\\t\\t\\t\\t\\tlocalAabb.halfExtents.set(0, 0, 0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.mesh && this.mesh.morph) {\\n\\t\\t\\t\\t\\tconst morphAabb = this.mesh.morph.aabb;\\n\\t\\t\\t\\t\\tlocalAabb._expand(morphAabb.getMin(), morphAabb.getMax());\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttoWorldSpace = true;\\n\\t\\t\\t\\tthis._aabbVer = this.node._aabbVer;\\n\\t\\t\\t\\tthis._aabbMeshVer = this.mesh._aabbVer;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (toWorldSpace) {\\n\\t\\t\\tthis._aabb.setFromTransformedAabb(localAabb, this.node.getWorldTransform());\\n\\t\\t}\\n\\t\\treturn this._aabb;\\n\\t}\\n\\tclearShaders() {\\n\\t\\tthis._shaderCache.forEach((shaderInstance) => {\\n\\t\\t\\tshaderInstance.destroy();\\n\\t\\t});\\n\\t\\tthis._shaderCache.clear();\\n\\t}\\n\\tgetShaderInstance(shaderPass, lightHash, scene, cameraShaderParams, viewUniformFormat, viewBindGroupFormat, sortedLights) {\\n\\t\\tconst shaderDefs = this._shaderDefs;\\n\\t\\tlookupHashes[0] = shaderPass;\\n\\t\\tlookupHashes[1] = lightHash;\\n\\t\\tlookupHashes[2] = shaderDefs;\\n\\t\\tlookupHashes[3] = cameraShaderParams.hash;\\n\\t\\tconst hash = hash32Fnv1a(lookupHashes);\\n\\t\\tlet shaderInstance = this._shaderCache.get(hash);\\n\\t\\tif (!shaderInstance) {\\n\\t\\t\\tconst mat = this._material;\\n\\t\\t\\tshaderInstance = new ShaderInstance();\\n\\t\\t\\tshaderInstance.shader = mat.variants.get(hash);\\n\\t\\t\\tshaderInstance.hashes = new Uint32Array(lookupHashes);\\n\\t\\t\\tif (!shaderInstance.shader) {\\n\\t\\t\\t\\tconst shader = mat.getShaderVariant({\\n\\t\\t\\t\\t\\tdevice: this.mesh.device,\\n\\t\\t\\t\\t\\tscene,\\n\\t\\t\\t\\t\\tobjDefs: shaderDefs,\\n\\t\\t\\t\\t\\tcameraShaderParams,\\n\\t\\t\\t\\t\\tpass: shaderPass,\\n\\t\\t\\t\\t\\tsortedLights,\\n\\t\\t\\t\\t\\tviewUniformFormat,\\n\\t\\t\\t\\t\\tviewBindGroupFormat,\\n\\t\\t\\t\\t\\tvertexFormat: this.mesh.vertexBuffer?.format\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tmat.variants.set(hash, shader);\\n\\t\\t\\t\\tshaderInstance.shader = shader;\\n\\t\\t\\t}\\n\\t\\t\\tthis._shaderCache.set(hash, shaderInstance);\\n\\t\\t}\\n\\t\\treturn shaderInstance;\\n\\t}\\n\\tset material(material) {\\n\\t\\tthis.clearShaders();\\n\\t\\tconst prevMat = this._material;\\n\\t\\tif (prevMat) {\\n\\t\\t\\tprevMat.removeMeshInstanceRef(this);\\n\\t\\t}\\n\\t\\tthis._material = material;\\n\\t\\tif (material) {\\n\\t\\t\\tmaterial.addMeshInstanceRef(this);\\n\\t\\t\\tthis.transparent = material.transparent;\\n\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t}\\n\\tget material() {\\n\\t\\treturn this._material;\\n\\t}\\n\\t_updateShaderDefs(shaderDefs) {\\n\\t\\tif (shaderDefs !== this._shaderDefs) {\\n\\t\\t\\tthis._shaderDefs = shaderDefs;\\n\\t\\t\\tthis.clearShaders();\\n\\t\\t}\\n\\t}\\n\\tset calculateSortDistance(calculateSortDistance) {\\n\\t\\tthis._calculateSortDistance = calculateSortDistance;\\n\\t}\\n\\tget calculateSortDistance() {\\n\\t\\treturn this._calculateSortDistance;\\n\\t}\\n\\tset receiveShadow(val) {\\n\\t\\tif (this._receiveShadow !== val) {\\n\\t\\t\\tthis._receiveShadow = val;\\n\\t\\t\\tthis._updateShaderDefs(val ? this._shaderDefs & ~SHADERDEF_NOSHADOW : this._shaderDefs | SHADERDEF_NOSHADOW);\\n\\t\\t}\\n\\t}\\n\\tget receiveShadow() {\\n\\t\\treturn this._receiveShadow;\\n\\t}\\n\\tset batching(val) {\\n\\t\\tthis._updateShaderDefs(val ? this._shaderDefs | SHADERDEF_BATCH : this._shaderDefs & ~SHADERDEF_BATCH);\\n\\t}\\n\\tget batching() {\\n\\t\\treturn (this._shaderDefs & SHADERDEF_BATCH) !== 0;\\n\\t}\\n\\tset skinInstance(val) {\\n\\t\\tthis._skinInstance = val;\\n\\t\\tthis._updateShaderDefs(val ? this._shaderDefs | SHADERDEF_SKIN : this._shaderDefs & ~SHADERDEF_SKIN);\\n\\t\\tthis._setupSkinUpdate();\\n\\t}\\n\\tget skinInstance() {\\n\\t\\treturn this._skinInstance;\\n\\t}\\n\\tset morphInstance(val) {\\n\\t\\tthis._morphInstance?.destroy();\\n\\t\\tthis._morphInstance = val;\\n\\t\\tlet shaderDefs = this._shaderDefs;\\n\\t\\tshaderDefs = val && val.morph.morphPositions ? shaderDefs | SHADERDEF_MORPH_POSITION : shaderDefs & ~SHADERDEF_MORPH_POSITION;\\n\\t\\tshaderDefs = val && val.morph.morphNormals ? shaderDefs | SHADERDEF_MORPH_NORMAL : shaderDefs & ~SHADERDEF_MORPH_NORMAL;\\n\\t\\tshaderDefs = val && val.morph.intRenderFormat ? shaderDefs | SHADERDEF_MORPH_TEXTURE_BASED_INT : shaderDefs & ~SHADERDEF_MORPH_TEXTURE_BASED_INT;\\n\\t\\tthis._updateShaderDefs(shaderDefs);\\n\\t}\\n\\tget morphInstance() {\\n\\t\\treturn this._morphInstance;\\n\\t}\\n\\tset screenSpace(val) {\\n\\t\\tif (this._screenSpace !== val) {\\n\\t\\t\\tthis._screenSpace = val;\\n\\t\\t\\tthis._updateShaderDefs(val ? this._shaderDefs | SHADERDEF_SCREENSPACE : this._shaderDefs & ~SHADERDEF_SCREENSPACE);\\n\\t\\t}\\n\\t}\\n\\tget screenSpace() {\\n\\t\\treturn this._screenSpace;\\n\\t}\\n\\tset key(val) {\\n\\t\\tthis._sortKeyForward = val;\\n\\t}\\n\\tget key() {\\n\\t\\treturn this._sortKeyForward;\\n\\t}\\n\\tset mask(val) {\\n\\t\\tconst toggles = this._shaderDefs & 65535;\\n\\t\\tthis._updateShaderDefs(toggles | val << 16);\\n\\t}\\n\\tget mask() {\\n\\t\\treturn this._shaderDefs >> 16;\\n\\t}\\n\\tset instancingCount(value) {\\n\\t\\tif (this.instancingData) {\\n\\t\\t\\tthis.instancingData.count = value;\\n\\t\\t}\\n\\t}\\n\\tget instancingCount() {\\n\\t\\treturn this.instancingData ? this.instancingData.count : 0;\\n\\t}\\n\\tdestroy() {\\n\\t\\tconst mesh = this.mesh;\\n\\t\\tif (mesh) {\\n\\t\\t\\tthis.mesh = null;\\n\\t\\t\\tif (mesh.refCount < 1) {\\n\\t\\t\\t\\tmesh.destroy();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.setRealtimeLightmap(MeshInstance.lightmapParamNames[0], null);\\n\\t\\tthis.setRealtimeLightmap(MeshInstance.lightmapParamNames[1], null);\\n\\t\\tthis._skinInstance?.destroy();\\n\\t\\tthis._skinInstance = null;\\n\\t\\tthis.morphInstance?.destroy();\\n\\t\\tthis.morphInstance = null;\\n\\t\\tthis.clearShaders();\\n\\t\\tthis.material = null;\\n\\t\\tthis.instancingData?.destroy();\\n\\t\\tthis.destroyDrawCommands();\\n\\t}\\n\\tdestroyDrawCommands() {\\n\\t\\tif (this.drawCommands) {\\n\\t\\t\\tfor (const cmd of this.drawCommands.values()) {\\n\\t\\t\\t\\tcmd?.destroy();\\n\\t\\t\\t}\\n\\t\\t\\tthis.drawCommands = null;\\n\\t\\t}\\n\\t}\\n\\t// shader uniform names for lightmaps\\n\\tstatic lightmapParamNames = [\\\"texture_lightMap\\\", \\\"texture_dirLightMap\\\"];\\n\\tstatic _prepareRenderStyleForArray(meshInstances, renderStyle) {\\n\\t\\tif (meshInstances) {\\n\\t\\t\\tfor (let i = 0; i < meshInstances.length; i++) {\\n\\t\\t\\t\\tmeshInstances[i]._renderStyle = renderStyle;\\n\\t\\t\\t\\tconst mesh = meshInstances[i].mesh;\\n\\t\\t\\t\\tif (!_meshSet.has(mesh)) {\\n\\t\\t\\t\\t\\t_meshSet.add(mesh);\\n\\t\\t\\t\\t\\tmesh.prepareRenderState(renderStyle);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\t_meshSet.clear();\\n\\t\\t}\\n\\t}\\n\\t_isVisible(camera) {\\n\\t\\tif (this.visible) {\\n\\t\\t\\tif (this.isVisibleFunc) {\\n\\t\\t\\t\\treturn this.isVisibleFunc(camera);\\n\\t\\t\\t}\\n\\t\\t\\t_tempSphere.center = this.aabb.center;\\n\\t\\t\\t_tempSphere.radius = this._aabb.halfExtents.length();\\n\\t\\t\\treturn camera.frustum.containsSphere(_tempSphere) > 0;\\n\\t\\t}\\n\\t\\treturn false;\\n\\t}\\n\\tupdateKey() {\\n\\t\\tconst { material } = this;\\n\\t\\tthis._sortKeyForward = this._drawBucket << 23 | (material.alphaToCoverage || material.alphaTest ? 4194304 : 0) | material.id & 4194303;\\n\\t}\\n\\tsetInstancing(vertexBuffer, cull = false) {\\n\\t\\tif (vertexBuffer) {\\n\\t\\t\\tif (vertexBuffer === true) {\\n\\t\\t\\t\\tthis.instancingData = new InstancingData(0);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.instancingData = new InstancingData(vertexBuffer.numVertices);\\n\\t\\t\\t\\tthis.instancingData.vertexBuffer = vertexBuffer;\\n\\t\\t\\t\\tvertexBuffer.format.instancing = true;\\n\\t\\t\\t}\\n\\t\\t\\tthis.cull = cull;\\n\\t\\t} else {\\n\\t\\t\\tthis.instancingData = null;\\n\\t\\t\\tthis.cull = true;\\n\\t\\t}\\n\\t\\tthis._updateShaderDefs(vertexBuffer instanceof VertexBuffer ? this._shaderDefs | SHADERDEF_INSTANCING : this._shaderDefs & ~SHADERDEF_INSTANCING);\\n\\t}\\n\\tsetIndirect(camera, slot, count = 1) {\\n\\t\\tconst key = camera?.camera ?? null;\\n\\t\\tif (slot === -1) {\\n\\t\\t\\tthis._deleteDrawCommandsKey(key);\\n\\t\\t} else {\\n\\t\\t\\tthis.drawCommands ?? (this.drawCommands = /* @__PURE__ */ new Map());\\n\\t\\t\\tconst cmd = this.drawCommands.get(key) ?? new DrawCommands(this.mesh.device);\\n\\t\\t\\tcmd.slotIndex = slot;\\n\\t\\t\\tcmd.update(count);\\n\\t\\t\\tthis.drawCommands.set(key, cmd);\\n\\t\\t\\tconst device = this.mesh.device;\\n\\t\\t\\tdevice.mapsToClear.add(this.drawCommands);\\n\\t\\t}\\n\\t}\\n\\tsetMultiDraw(camera, maxCount = 1) {\\n\\t\\tconst key = camera?.camera ?? null;\\n\\t\\tlet cmd;\\n\\t\\tif (maxCount === 0) {\\n\\t\\t\\tthis._deleteDrawCommandsKey(key);\\n\\t\\t} else {\\n\\t\\t\\tthis.drawCommands ?? (this.drawCommands = /* @__PURE__ */ new Map());\\n\\t\\t\\tcmd = this.drawCommands.get(key);\\n\\t\\t\\tif (!cmd) {\\n\\t\\t\\t\\tconst indexBuffer = this.mesh.indexBuffer?.[0];\\n\\t\\t\\t\\tconst indexFormat = indexBuffer?.format;\\n\\t\\t\\t\\tconst indexSizeBytes = indexFormat !== void 0 ? indexFormatByteSize[indexFormat] : 0;\\n\\t\\t\\t\\tcmd = new DrawCommands(this.mesh.device, indexSizeBytes);\\n\\t\\t\\t\\tthis.drawCommands.set(key, cmd);\\n\\t\\t\\t}\\n\\t\\t\\tcmd.allocate(maxCount);\\n\\t\\t}\\n\\t\\treturn cmd;\\n\\t}\\n\\t_deleteDrawCommandsKey(key) {\\n\\t\\tconst cmds = this.drawCommands;\\n\\t\\tif (cmds) {\\n\\t\\t\\tconst cmd = cmds.get(key);\\n\\t\\t\\tcmd?.destroy();\\n\\t\\t\\tcmds.delete(key);\\n\\t\\t\\tif (cmds.size === 0) {\\n\\t\\t\\t\\tthis.destroyDrawCommands();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tgetDrawCommands(camera) {\\n\\t\\tconst cmds = this.drawCommands;\\n\\t\\tif (!cmds) return void 0;\\n\\t\\treturn cmds.get(camera) ?? cmds.get(null);\\n\\t}\\n\\tgetIndirectMetaData() {\\n\\t\\tconst prim = this.mesh?.primitive[this.renderStyle];\\n\\t\\tconst data = this.meshMetaData ?? (this.meshMetaData = new Int32Array(4));\\n\\t\\tdata[0] = prim.count;\\n\\t\\tdata[1] = prim.base;\\n\\t\\tdata[2] = prim.baseVertex;\\n\\t\\treturn data;\\n\\t}\\n\\tensureMaterial(device) {\\n\\t\\tif (!this.material) {\\n\\t\\t\\tthis.material = getDefaultMaterial(device);\\n\\t\\t}\\n\\t}\\n\\t// Parameter management\\n\\tclearParameters() {\\n\\t\\tthis.parameters = {};\\n\\t}\\n\\tgetParameters() {\\n\\t\\treturn this.parameters;\\n\\t}\\n\\tgetParameter(name) {\\n\\t\\treturn this.parameters[name];\\n\\t}\\n\\tsetParameter(name, data, passFlags = 4294967295) {\\n\\t\\tconst param = this.parameters[name];\\n\\t\\tif (param) {\\n\\t\\t\\tparam.data = data;\\n\\t\\t\\tparam.passFlags = passFlags;\\n\\t\\t} else {\\n\\t\\t\\tthis.parameters[name] = {\\n\\t\\t\\t\\tscopeId: null,\\n\\t\\t\\t\\tdata,\\n\\t\\t\\t\\tpassFlags\\n\\t\\t\\t};\\n\\t\\t}\\n\\t}\\n\\tsetRealtimeLightmap(name, texture) {\\n\\t\\tconst old = this.getParameter(name);\\n\\t\\tif (old === texture) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (old) {\\n\\t\\t\\tLightmapCache.decRef(old.data);\\n\\t\\t}\\n\\t\\tif (texture) {\\n\\t\\t\\tLightmapCache.incRef(texture);\\n\\t\\t\\tthis.setParameter(name, texture);\\n\\t\\t} else {\\n\\t\\t\\tthis.deleteParameter(name);\\n\\t\\t}\\n\\t}\\n\\tdeleteParameter(name) {\\n\\t\\tif (this.parameters[name]) {\\n\\t\\t\\tdelete this.parameters[name];\\n\\t\\t}\\n\\t}\\n\\tsetParameters(device, passFlag) {\\n\\t\\tconst parameters = this.parameters;\\n\\t\\tfor (const paramName in parameters) {\\n\\t\\t\\tconst parameter = parameters[paramName];\\n\\t\\t\\tif (parameter.passFlags & passFlag) {\\n\\t\\t\\t\\tif (!parameter.scopeId) {\\n\\t\\t\\t\\t\\tparameter.scopeId = device.scope.resolve(paramName);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tparameter.scopeId.setValue(parameter.data);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tsetLightmapped(value) {\\n\\t\\tif (value) {\\n\\t\\t\\tthis.mask = (this.mask | MASK_AFFECT_LIGHTMAPPED) & -6;\\n\\t\\t} else {\\n\\t\\t\\tthis.setRealtimeLightmap(MeshInstance.lightmapParamNames[0], null);\\n\\t\\t\\tthis.setRealtimeLightmap(MeshInstance.lightmapParamNames[1], null);\\n\\t\\t\\tthis._shaderDefs &= -4289;\\n\\t\\t\\tthis.mask = (this.mask | MASK_AFFECT_DYNAMIC) & -7;\\n\\t\\t}\\n\\t}\\n\\tsetCustomAabb(aabb) {\\n\\t\\tif (aabb) {\\n\\t\\t\\tif (this._customAabb) {\\n\\t\\t\\t\\tthis._customAabb.copy(aabb);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._customAabb = aabb.clone();\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis._customAabb = null;\\n\\t\\t\\tthis._aabbVer = -1;\\n\\t\\t}\\n\\t\\tthis._setupSkinUpdate();\\n\\t}\\n\\t_setupSkinUpdate() {\\n\\t\\tif (this._skinInstance) {\\n\\t\\t\\tthis._skinInstance._updateBeforeCull = !this._customAabb;\\n\\t\\t}\\n\\t}\\n}\\n\\nconst _colorUniformName = \\\"uSceneColorMap\\\";\\nclass FramePassColorGrab extends FramePass {\\n\\tcolorRenderTarget = null;\\n\\tsource = null;\\n\\tdestroy() {\\n\\t\\tsuper.destroy();\\n\\t\\tthis.releaseRenderTarget(this.colorRenderTarget);\\n\\t}\\n\\tshouldReallocate(targetRT, sourceTexture, sourceFormat) {\\n\\t\\tconst targetFormat = targetRT?.colorBuffer.format;\\n\\t\\tif (targetFormat !== sourceFormat) {\\n\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tconst width = sourceTexture?.width || this.device.width;\\n\\t\\tconst height = sourceTexture?.height || this.device.height;\\n\\t\\treturn !targetRT || width !== targetRT.width || height !== targetRT.height;\\n\\t}\\n\\tallocateRenderTarget(renderTarget, sourceRenderTarget, device, format) {\\n\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\tname: _colorUniformName,\\n\\t\\t\\tformat,\\n\\t\\t\\twidth: sourceRenderTarget ? sourceRenderTarget.colorBuffer.width : device.width,\\n\\t\\t\\theight: sourceRenderTarget ? sourceRenderTarget.colorBuffer.height : device.height,\\n\\t\\t\\tmipmaps: true,\\n\\t\\t\\tminFilter: FILTER_LINEAR_MIPMAP_LINEAR,\\n\\t\\t\\tmagFilter: FILTER_LINEAR,\\n\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t});\\n\\t\\tif (renderTarget) {\\n\\t\\t\\trenderTarget.destroyFrameBuffers();\\n\\t\\t\\trenderTarget._colorBuffer = texture;\\n\\t\\t\\trenderTarget._colorBuffers = [texture];\\n\\t\\t\\trenderTarget.evaluateDimensions();\\n\\t\\t} else {\\n\\t\\t\\trenderTarget = new RenderTarget({\\n\\t\\t\\t\\tname: \\\"ColorGrabRT\\\",\\n\\t\\t\\t\\tcolorBuffer: texture,\\n\\t\\t\\t\\tdepth: false,\\n\\t\\t\\t\\tstencil: false,\\n\\t\\t\\t\\tautoResolve: false\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\treturn renderTarget;\\n\\t}\\n\\treleaseRenderTarget(rt) {\\n\\t\\tif (rt) {\\n\\t\\t\\trt.destroyTextureBuffers();\\n\\t\\t\\trt.destroy();\\n\\t\\t}\\n\\t}\\n\\tframeUpdate() {\\n\\t\\tconst device = this.device;\\n\\t\\tconst sourceRt = this.source;\\n\\t\\tconst sourceFormat = sourceRt?.colorBuffer.format ?? this.device.backBufferFormat;\\n\\t\\tif (this.shouldReallocate(this.colorRenderTarget, sourceRt?.colorBuffer, sourceFormat)) {\\n\\t\\t\\tthis.releaseRenderTarget(this.colorRenderTarget);\\n\\t\\t\\tthis.colorRenderTarget = this.allocateRenderTarget(this.colorRenderTarget, sourceRt, device, sourceFormat);\\n\\t\\t}\\n\\t\\tconst colorBuffer = this.colorRenderTarget.colorBuffer;\\n\\t\\tdevice.scope.resolve(_colorUniformName).setValue(colorBuffer);\\n\\t}\\n\\texecute() {\\n\\t\\tconst device = this.device;\\n\\t\\tconst sourceRt = this.source;\\n\\t\\tconst colorBuffer = this.colorRenderTarget.colorBuffer;\\n\\t\\tif (device.isWebGPU) {\\n\\t\\t\\tdevice.copyRenderTarget(sourceRt, this.colorRenderTarget, true, false);\\n\\t\\t\\tdevice.mipmapRenderer.generate(this.colorRenderTarget.colorBuffer.impl);\\n\\t\\t} else {\\n\\t\\t\\tdevice.copyRenderTarget(sourceRt, this.colorRenderTarget, true, false);\\n\\t\\t\\tdevice.activeTexture(device.maxCombinedTextures - 1);\\n\\t\\t\\tdevice.bindTexture(colorBuffer);\\n\\t\\t\\tdevice.gl.generateMipmap(colorBuffer.impl._glTarget);\\n\\t\\t}\\n\\t}\\n}\\n\\nconst _depthUniformName = \\\"uSceneDepthMap\\\";\\nclass FramePassDepthGrab extends FramePass {\\n\\tdepthRenderTarget = null;\\n\\tcamera = null;\\n\\tconstructor(device, camera) {\\n\\t\\tsuper(device);\\n\\t\\tthis.camera = camera;\\n\\t}\\n\\tdestroy() {\\n\\t\\tsuper.destroy();\\n\\t\\tthis.releaseRenderTarget(this.depthRenderTarget);\\n\\t}\\n\\tshouldReallocate(targetRT, sourceTexture) {\\n\\t\\tconst width = sourceTexture?.width || this.device.width;\\n\\t\\tconst height = sourceTexture?.height || this.device.height;\\n\\t\\treturn !targetRT || width !== targetRT.width || height !== targetRT.height;\\n\\t}\\n\\tallocateRenderTarget(renderTarget, sourceRenderTarget, device, format, isDepth) {\\n\\t\\tconst texture = Texture.createDataTexture2D(\\n\\t\\t\\tdevice,\\n\\t\\t\\t_depthUniformName,\\n\\t\\t\\tsourceRenderTarget ? sourceRenderTarget.colorBuffer.width : device.width,\\n\\t\\t\\tsourceRenderTarget ? sourceRenderTarget.colorBuffer.height : device.height,\\n\\t\\t\\tformat\\n\\t\\t);\\n\\t\\tif (renderTarget) {\\n\\t\\t\\trenderTarget.destroyFrameBuffers();\\n\\t\\t\\tif (isDepth) {\\n\\t\\t\\t\\trenderTarget._depthBuffer = texture;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\trenderTarget._colorBuffer = texture;\\n\\t\\t\\t\\trenderTarget._colorBuffers = [texture];\\n\\t\\t\\t}\\n\\t\\t\\trenderTarget.evaluateDimensions();\\n\\t\\t} else {\\n\\t\\t\\trenderTarget = new RenderTarget({\\n\\t\\t\\t\\tname: \\\"DepthGrabRT\\\",\\n\\t\\t\\t\\tcolorBuffer: isDepth ? null : texture,\\n\\t\\t\\t\\tdepthBuffer: isDepth ? texture : null,\\n\\t\\t\\t\\tdepth: !isDepth,\\n\\t\\t\\t\\tstencil: device.supportsStencil,\\n\\t\\t\\t\\tautoResolve: false\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\treturn renderTarget;\\n\\t}\\n\\treleaseRenderTarget(rt) {\\n\\t\\tif (rt) {\\n\\t\\t\\trt.destroyTextureBuffers();\\n\\t\\t\\trt.destroy();\\n\\t\\t}\\n\\t}\\n\\tbefore() {\\n\\t\\tconst camera = this.camera;\\n\\t\\tconst device = this.device;\\n\\t\\tconst destinationRt = camera?.renderTarget ?? device.backBuffer;\\n\\t\\tlet useDepthBuffer = true;\\n\\t\\tlet format = destinationRt.stencil ? PIXELFORMAT_DEPTHSTENCIL : PIXELFORMAT_DEPTH;\\n\\t\\tif (device.isWebGPU) {\\n\\t\\t\\tconst numSamples = destinationRt.samples;\\n\\t\\t\\tif (numSamples > 1) {\\n\\t\\t\\t\\tformat = PIXELFORMAT_R32F;\\n\\t\\t\\t\\tuseDepthBuffer = false;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst sourceTexture = camera.renderTarget?.depthBuffer ?? camera.renderTarget?.colorBuffer;\\n\\t\\tif (this.shouldReallocate(this.depthRenderTarget, sourceTexture)) {\\n\\t\\t\\tthis.releaseRenderTarget(this.depthRenderTarget);\\n\\t\\t\\tthis.depthRenderTarget = this.allocateRenderTarget(this.depthRenderTarget, camera.renderTarget, device, format, useDepthBuffer);\\n\\t\\t}\\n\\t\\tconst colorBuffer = useDepthBuffer ? this.depthRenderTarget.depthBuffer : this.depthRenderTarget.colorBuffer;\\n\\t\\tdevice.scope.resolve(_depthUniformName).setValue(colorBuffer);\\n\\t}\\n\\texecute() {\\n\\t\\tconst device = this.device;\\n\\t\\tif (device.isWebGL2 && device.renderTarget.samples > 1) {\\n\\t\\t\\tconst src = device.renderTarget.impl._glFrameBuffer;\\n\\t\\t\\tconst dest = this.depthRenderTarget;\\n\\t\\t\\tdevice.renderTarget = dest;\\n\\t\\t\\tdevice.updateBegin();\\n\\t\\t\\tthis.depthRenderTarget.impl.internalResolve(device, src, dest.impl._glFrameBuffer, this.depthRenderTarget, device.gl.DEPTH_BUFFER_BIT);\\n\\t\\t} else {\\n\\t\\t\\tdevice.copyRenderTarget(device.renderTarget, this.depthRenderTarget, false, true);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass CameraShaderParams {\\n\\t_gammaCorrection = GAMMA_SRGB;\\n\\t_toneMapping = TONEMAP_LINEAR;\\n\\t_srgbRenderTarget = false;\\n\\t_ssaoEnabled = false;\\n\\t_fog = FOG_NONE;\\n\\t_sceneDepthMapLinear = false;\\n\\t_hash;\\n\\t_defines = /* @__PURE__ */ new Map();\\n\\t_definesDirty = true;\\n\\tget hash() {\\n\\t\\tif (this._hash === void 0) {\\n\\t\\t\\tconst key = `${this.gammaCorrection}_${this.toneMapping}_${this.srgbRenderTarget}_${this.fog}_${this.ssaoEnabled}_${this.sceneDepthMapLinear}`;\\n\\t\\t\\tthis._hash = hashCode(key);\\n\\t\\t}\\n\\t\\treturn this._hash;\\n\\t}\\n\\tget defines() {\\n\\t\\tconst defines = this._defines;\\n\\t\\tif (this._definesDirty) {\\n\\t\\t\\tthis._definesDirty = false;\\n\\t\\t\\tdefines.clear();\\n\\t\\t\\tif (this._sceneDepthMapLinear) defines.set(\\\"SCENE_DEPTHMAP_LINEAR\\\", \\\"\\\");\\n\\t\\t\\tif (this.shaderOutputGamma === GAMMA_SRGB) defines.set(\\\"SCENE_COLORMAP_GAMMA\\\", \\\"\\\");\\n\\t\\t\\tdefines.set(\\\"FOG\\\", this._fog.toUpperCase());\\n\\t\\t\\tdefines.set(\\\"TONEMAP\\\", tonemapNames[this._toneMapping]);\\n\\t\\t\\tdefines.set(\\\"GAMMA\\\", gammaNames[this.shaderOutputGamma]);\\n\\t\\t}\\n\\t\\treturn defines;\\n\\t}\\n\\tmarkDirty() {\\n\\t\\tthis._hash = void 0;\\n\\t\\tthis._definesDirty = true;\\n\\t}\\n\\tset fog(type) {\\n\\t\\tif (this._fog !== type) {\\n\\t\\t\\tthis._fog = type;\\n\\t\\t\\tthis.markDirty();\\n\\t\\t}\\n\\t}\\n\\tget fog() {\\n\\t\\treturn this._fog;\\n\\t}\\n\\tset ssaoEnabled(value) {\\n\\t\\tif (this._ssaoEnabled !== value) {\\n\\t\\t\\tthis._ssaoEnabled = value;\\n\\t\\t\\tthis.markDirty();\\n\\t\\t}\\n\\t}\\n\\tget ssaoEnabled() {\\n\\t\\treturn this._ssaoEnabled;\\n\\t}\\n\\tset gammaCorrection(value) {\\n\\t\\tthis._gammaCorrectionAssigned = true;\\n\\t\\tif (this._gammaCorrection !== value) {\\n\\t\\t\\tthis._gammaCorrection = value;\\n\\t\\t\\tthis.markDirty();\\n\\t\\t}\\n\\t}\\n\\tget gammaCorrection() {\\n\\t\\treturn this._gammaCorrection;\\n\\t}\\n\\tset toneMapping(value) {\\n\\t\\tif (this._toneMapping !== value) {\\n\\t\\t\\tthis._toneMapping = value;\\n\\t\\t\\tthis.markDirty();\\n\\t\\t}\\n\\t}\\n\\tget toneMapping() {\\n\\t\\treturn this._toneMapping;\\n\\t}\\n\\tset srgbRenderTarget(value) {\\n\\t\\tif (this._srgbRenderTarget !== value) {\\n\\t\\t\\tthis._srgbRenderTarget = value;\\n\\t\\t\\tthis.markDirty();\\n\\t\\t}\\n\\t}\\n\\tget srgbRenderTarget() {\\n\\t\\treturn this._srgbRenderTarget;\\n\\t}\\n\\tset sceneDepthMapLinear(value) {\\n\\t\\tif (this._sceneDepthMapLinear !== value) {\\n\\t\\t\\tthis._sceneDepthMapLinear = value;\\n\\t\\t\\tthis.markDirty();\\n\\t\\t}\\n\\t}\\n\\tget sceneDepthMapLinear() {\\n\\t\\treturn this._sceneDepthMapLinear;\\n\\t}\\n\\tget shaderOutputGamma() {\\n\\t\\tconst gammaOutput = this._gammaCorrection === GAMMA_SRGB && !this._srgbRenderTarget;\\n\\t\\treturn gammaOutput ? GAMMA_SRGB : GAMMA_NONE;\\n\\t}\\n}\\n\\nconst _deviceCoord = new Vec3();\\nconst _halfSize = new Vec3();\\nconst _point = new Vec3();\\nconst _invViewProjMat = new Mat4();\\nconst _frustumPoints = [new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3()];\\nlet Camera$1 = class Camera {\\n\\tstatic _flipYProjectionMatrix = new Mat4().setScale(1, -1, 1);\\n\\tstatic _webGpuDepthRangeMatrix = new Mat4().set([\\n\\t\\t1,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t1,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0.5,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0.5,\\n\\t\\t1\\n\\t]);\\n\\tstatic _applyShaderProjectionScratch = new Mat4();\\n\\tstatic applyShaderProjectionTransform(projection, out, flipY, applyWebGpuDepthRange) {\\n\\t\\tif (!flipY && !applyWebGpuDepthRange) {\\n\\t\\t\\tout.copy(projection);\\n\\t\\t\\treturn out;\\n\\t\\t}\\n\\t\\tif (flipY && applyWebGpuDepthRange) {\\n\\t\\t\\tconst scratch = Camera._applyShaderProjectionScratch;\\n\\t\\t\\tscratch.mul2(Camera._flipYProjectionMatrix, projection);\\n\\t\\t\\tout.mul2(Camera._webGpuDepthRangeMatrix, scratch);\\n\\t\\t\\treturn out;\\n\\t\\t}\\n\\t\\tif (flipY) {\\n\\t\\t\\tout.mul2(Camera._flipYProjectionMatrix, projection);\\n\\t\\t\\treturn out;\\n\\t\\t}\\n\\t\\tout.mul2(Camera._webGpuDepthRangeMatrix, projection);\\n\\t\\treturn out;\\n\\t}\\n\\tshaderPassInfo = null;\\n\\trenderPassColorGrab = null;\\n\\trenderPassDepthGrab = null;\\n\\tfogParams = null;\\n\\tshaderParams = new CameraShaderParams();\\n\\tframePasses = [];\\n\\tbeforePasses = [];\\n\\tjitter = 0;\\n\\tdevice;\\n\\tconstructor(graphicsDevice) {\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tthis._aspectRatio = 16 / 9;\\n\\t\\tthis._aspectRatioMode = ASPECT_AUTO;\\n\\t\\tthis._calculateProjection = null;\\n\\t\\tthis._calculateTransform = null;\\n\\t\\tthis._clearColor = new Color(0.75, 0.75, 0.75, 1);\\n\\t\\tthis._clearColorBuffer = true;\\n\\t\\tthis._clearDepth = 1;\\n\\t\\tthis._clearDepthBuffer = true;\\n\\t\\tthis._clearStencil = 0;\\n\\t\\tthis._clearStencilBuffer = true;\\n\\t\\tthis._cullFaces = true;\\n\\t\\tthis._farClip = 1e3;\\n\\t\\tthis._flipFaces = false;\\n\\t\\tthis._fov = 45;\\n\\t\\tthis._frustumCulling = true;\\n\\t\\tthis._horizontalFov = false;\\n\\t\\tthis._layers = [LAYERID_WORLD, LAYERID_DEPTH, LAYERID_SKYBOX, LAYERID_UI, LAYERID_IMMEDIATE];\\n\\t\\tthis._layersSet = new Set(this._layers);\\n\\t\\tthis._nearClip = 0.1;\\n\\t\\tthis._node = null;\\n\\t\\tthis._orthoHeight = 10;\\n\\t\\tthis._projection = PROJECTION_PERSPECTIVE;\\n\\t\\tthis._rect = new Vec4(0, 0, 1, 1);\\n\\t\\tthis._renderTarget = null;\\n\\t\\tthis._scissorRect = new Vec4(0, 0, 1, 1);\\n\\t\\tthis._scissorRectClear = false;\\n\\t\\tthis._aperture = 16;\\n\\t\\tthis._shutter = 1 / 1e3;\\n\\t\\tthis._sensitivity = 1e3;\\n\\t\\tthis._projMat = new Mat4();\\n\\t\\tthis._projMatDirty = true;\\n\\t\\tthis._projMatSkybox = new Mat4();\\n\\t\\tthis._viewMat = new Mat4();\\n\\t\\tthis._viewMatDirty = true;\\n\\t\\tthis._viewProjMat = new Mat4();\\n\\t\\tthis._viewProjMatDirty = true;\\n\\t\\tthis._shaderMatricesVersion = 0;\\n\\t\\tthis._viewProjInverse = new Mat4();\\n\\t\\tthis._viewProjCurrent = null;\\n\\t\\tthis._viewProjPrevious = new Mat4();\\n\\t\\tthis._jitters = [0, 0, 0, 0];\\n\\t\\tthis.frustum = new Frustum();\\n\\t\\tthis._xr = null;\\n\\t\\tthis._xrProperties = {\\n\\t\\t\\thorizontalFov: this._horizontalFov,\\n\\t\\t\\tfov: this._fov,\\n\\t\\t\\taspectRatio: this._aspectRatio,\\n\\t\\t\\tfarClip: this._farClip,\\n\\t\\t\\tnearClip: this._nearClip\\n\\t\\t};\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.renderPassColorGrab?.destroy();\\n\\t\\tthis.renderPassColorGrab = null;\\n\\t\\tthis.renderPassDepthGrab?.destroy();\\n\\t\\tthis.renderPassDepthGrab = null;\\n\\t\\tthis.framePasses.length = 0;\\n\\t}\\n\\t_storeShaderMatrices(viewProjMat, jitterX, jitterY, renderVersion) {\\n\\t\\tif (this._shaderMatricesVersion !== renderVersion) {\\n\\t\\t\\tthis._shaderMatricesVersion = renderVersion;\\n\\t\\t\\tthis._viewProjPrevious.copy(this._viewProjCurrent ?? viewProjMat);\\n\\t\\t\\tthis._viewProjCurrent ?? (this._viewProjCurrent = new Mat4());\\n\\t\\t\\tthis._viewProjCurrent.copy(viewProjMat);\\n\\t\\t\\tthis._viewProjInverse.invert(viewProjMat);\\n\\t\\t\\tthis._jitters[2] = this._jitters[0];\\n\\t\\t\\tthis._jitters[3] = this._jitters[1];\\n\\t\\t\\tthis._jitters[0] = jitterX;\\n\\t\\t\\tthis._jitters[1] = jitterY;\\n\\t\\t}\\n\\t}\\n\\tget fullSizeClearRect() {\\n\\t\\tconst rect = this._scissorRectClear ? this.scissorRect : this._rect;\\n\\t\\treturn rect.x === 0 && rect.y === 0 && rect.z === 1 && rect.w === 1;\\n\\t}\\n\\tset aspectRatio(newValue) {\\n\\t\\tif (this._aspectRatio !== newValue) {\\n\\t\\t\\tthis._aspectRatio = newValue;\\n\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget aspectRatio() {\\n\\t\\tif (this.xr?.active) return this._xrProperties.aspectRatio;\\n\\t\\tif (this._aspectRatioMode === ASPECT_AUTO) {\\n\\t\\t\\tconst newValue = this.calculateAspectRatio();\\n\\t\\t\\tif (this._aspectRatio !== newValue) {\\n\\t\\t\\t\\tthis._aspectRatio = newValue;\\n\\t\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn this._aspectRatio;\\n\\t}\\n\\tset aspectRatioMode(newValue) {\\n\\t\\tif (this._aspectRatioMode !== newValue) {\\n\\t\\t\\tthis._aspectRatioMode = newValue;\\n\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget aspectRatioMode() {\\n\\t\\treturn this._aspectRatioMode;\\n\\t}\\n\\tset calculateProjection(newValue) {\\n\\t\\tthis._calculateProjection = newValue;\\n\\t\\tthis._projMatDirty = true;\\n\\t}\\n\\tget calculateProjection() {\\n\\t\\treturn this._calculateProjection;\\n\\t}\\n\\tset calculateTransform(newValue) {\\n\\t\\tthis._calculateTransform = newValue;\\n\\t}\\n\\tget calculateTransform() {\\n\\t\\treturn this._calculateTransform;\\n\\t}\\n\\tset clearColor(newValue) {\\n\\t\\tthis._clearColor.copy(newValue);\\n\\t}\\n\\tget clearColor() {\\n\\t\\treturn this._clearColor;\\n\\t}\\n\\tset clearColorBuffer(newValue) {\\n\\t\\tthis._clearColorBuffer = newValue;\\n\\t}\\n\\tget clearColorBuffer() {\\n\\t\\treturn this._clearColorBuffer;\\n\\t}\\n\\tset clearDepth(newValue) {\\n\\t\\tthis._clearDepth = newValue;\\n\\t}\\n\\tget clearDepth() {\\n\\t\\treturn this._clearDepth;\\n\\t}\\n\\tset clearDepthBuffer(newValue) {\\n\\t\\tthis._clearDepthBuffer = newValue;\\n\\t}\\n\\tget clearDepthBuffer() {\\n\\t\\treturn this._clearDepthBuffer;\\n\\t}\\n\\tset clearStencil(newValue) {\\n\\t\\tthis._clearStencil = newValue;\\n\\t}\\n\\tget clearStencil() {\\n\\t\\treturn this._clearStencil;\\n\\t}\\n\\tset clearStencilBuffer(newValue) {\\n\\t\\tthis._clearStencilBuffer = newValue;\\n\\t}\\n\\tget clearStencilBuffer() {\\n\\t\\treturn this._clearStencilBuffer;\\n\\t}\\n\\tset cullFaces(newValue) {\\n\\t\\tthis._cullFaces = newValue;\\n\\t}\\n\\tget cullFaces() {\\n\\t\\treturn this._cullFaces;\\n\\t}\\n\\tset farClip(newValue) {\\n\\t\\tif (this._farClip !== newValue) {\\n\\t\\t\\tthis._farClip = newValue;\\n\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget farClip() {\\n\\t\\treturn this.xr?.active ? this._xrProperties.farClip : this._farClip;\\n\\t}\\n\\tset flipFaces(newValue) {\\n\\t\\tthis._flipFaces = newValue;\\n\\t}\\n\\tget flipFaces() {\\n\\t\\treturn this._flipFaces;\\n\\t}\\n\\tset fov(newValue) {\\n\\t\\tif (this._fov !== newValue) {\\n\\t\\t\\tthis._fov = newValue;\\n\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget fov() {\\n\\t\\treturn this.xr?.active ? this._xrProperties.fov : this._fov;\\n\\t}\\n\\tset frustumCulling(newValue) {\\n\\t\\tthis._frustumCulling = newValue;\\n\\t}\\n\\tget frustumCulling() {\\n\\t\\treturn this._frustumCulling;\\n\\t}\\n\\tset horizontalFov(newValue) {\\n\\t\\tif (this._horizontalFov !== newValue) {\\n\\t\\t\\tthis._horizontalFov = newValue;\\n\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget horizontalFov() {\\n\\t\\treturn this.xr?.active ? this._xrProperties.horizontalFov : this._horizontalFov;\\n\\t}\\n\\tset layers(newValue) {\\n\\t\\tthis._layers = newValue.slice(0);\\n\\t\\tthis._layersSet = new Set(this._layers);\\n\\t}\\n\\tget layers() {\\n\\t\\treturn this._layers;\\n\\t}\\n\\tget layersSet() {\\n\\t\\treturn this._layersSet;\\n\\t}\\n\\tset nearClip(newValue) {\\n\\t\\tif (this._nearClip !== newValue) {\\n\\t\\t\\tthis._nearClip = newValue;\\n\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget nearClip() {\\n\\t\\treturn this.xr?.active ? this._xrProperties.nearClip : this._nearClip;\\n\\t}\\n\\tset node(newValue) {\\n\\t\\tthis._node = newValue;\\n\\t}\\n\\tget node() {\\n\\t\\treturn this._node;\\n\\t}\\n\\tset orthoHeight(newValue) {\\n\\t\\tif (this._orthoHeight !== newValue) {\\n\\t\\t\\tthis._orthoHeight = newValue;\\n\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget orthoHeight() {\\n\\t\\treturn this._orthoHeight;\\n\\t}\\n\\tset projection(newValue) {\\n\\t\\tif (this._projection !== newValue) {\\n\\t\\t\\tthis._projection = newValue;\\n\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget projection() {\\n\\t\\treturn this._projection;\\n\\t}\\n\\tget projectionMatrix() {\\n\\t\\tthis._evaluateProjectionMatrix();\\n\\t\\treturn this._projMat;\\n\\t}\\n\\tset rect(newValue) {\\n\\t\\tthis._rect.copy(newValue);\\n\\t\\tthis._projMatDirty = true;\\n\\t}\\n\\tget rect() {\\n\\t\\treturn this._rect;\\n\\t}\\n\\tset renderTarget(newValue) {\\n\\t\\tthis._renderTarget = newValue;\\n\\t\\tthis._projMatDirty = true;\\n\\t}\\n\\tget renderTarget() {\\n\\t\\treturn this._renderTarget;\\n\\t}\\n\\tset scissorRect(newValue) {\\n\\t\\tthis._scissorRect.copy(newValue);\\n\\t}\\n\\tget scissorRect() {\\n\\t\\treturn this._scissorRect;\\n\\t}\\n\\tget viewMatrix() {\\n\\t\\tif (this._viewMatDirty) {\\n\\t\\t\\tconst wtm = this._node.getWorldTransform();\\n\\t\\t\\tthis._viewMat.copy(wtm).invert();\\n\\t\\t\\tthis._viewMatDirty = false;\\n\\t\\t}\\n\\t\\treturn this._viewMat;\\n\\t}\\n\\tset aperture(newValue) {\\n\\t\\tthis._aperture = newValue;\\n\\t}\\n\\tget aperture() {\\n\\t\\treturn this._aperture;\\n\\t}\\n\\tset sensitivity(newValue) {\\n\\t\\tthis._sensitivity = newValue;\\n\\t}\\n\\tget sensitivity() {\\n\\t\\treturn this._sensitivity;\\n\\t}\\n\\tset shutter(newValue) {\\n\\t\\tthis._shutter = newValue;\\n\\t}\\n\\tget shutter() {\\n\\t\\treturn this._shutter;\\n\\t}\\n\\tset xr(newValue) {\\n\\t\\tif (this._xr !== newValue) {\\n\\t\\t\\tthis._xr = newValue;\\n\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget xr() {\\n\\t\\treturn this._xr;\\n\\t}\\n\\tcalculateAspectRatio(rt) {\\n\\t\\tconst target = rt ?? this._renderTarget;\\n\\t\\tconst width = target ? target.width : this.device.width;\\n\\t\\tconst height = target ? target.height : this.device.height;\\n\\t\\treturn width * this._rect.z / (height * this._rect.w);\\n\\t}\\n\\tclone() {\\n\\t\\treturn new Camera(this.device).copy(this);\\n\\t}\\n\\tcopy(other) {\\n\\t\\tthis._aspectRatio = other._aspectRatio;\\n\\t\\tthis._farClip = other._farClip;\\n\\t\\tthis._fov = other._fov;\\n\\t\\tthis._horizontalFov = other._horizontalFov;\\n\\t\\tthis._nearClip = other._nearClip;\\n\\t\\tthis._xrProperties.aspectRatio = other._xrProperties.aspectRatio;\\n\\t\\tthis._xrProperties.farClip = other._xrProperties.farClip;\\n\\t\\tthis._xrProperties.fov = other._xrProperties.fov;\\n\\t\\tthis._xrProperties.horizontalFov = other._xrProperties.horizontalFov;\\n\\t\\tthis._xrProperties.nearClip = other._xrProperties.nearClip;\\n\\t\\tthis.aspectRatioMode = other.aspectRatioMode;\\n\\t\\tthis.calculateProjection = other.calculateProjection;\\n\\t\\tthis.calculateTransform = other.calculateTransform;\\n\\t\\tthis.clearColor = other.clearColor;\\n\\t\\tthis.clearColorBuffer = other.clearColorBuffer;\\n\\t\\tthis.clearDepth = other.clearDepth;\\n\\t\\tthis.clearDepthBuffer = other.clearDepthBuffer;\\n\\t\\tthis.clearStencil = other.clearStencil;\\n\\t\\tthis.clearStencilBuffer = other.clearStencilBuffer;\\n\\t\\tthis.cullFaces = other.cullFaces;\\n\\t\\tthis.flipFaces = other.flipFaces;\\n\\t\\tthis.frustumCulling = other.frustumCulling;\\n\\t\\tthis.layers = other.layers;\\n\\t\\tthis.orthoHeight = other.orthoHeight;\\n\\t\\tthis.projection = other.projection;\\n\\t\\tthis.rect = other.rect;\\n\\t\\tthis.renderTarget = other.renderTarget;\\n\\t\\tthis.scissorRect = other.scissorRect;\\n\\t\\tthis.aperture = other.aperture;\\n\\t\\tthis.shutter = other.shutter;\\n\\t\\tthis.sensitivity = other.sensitivity;\\n\\t\\tthis.shaderPassInfo = other.shaderPassInfo;\\n\\t\\tthis.jitter = other.jitter;\\n\\t\\tthis._projMatDirty = true;\\n\\t\\treturn this;\\n\\t}\\n\\t_enableRenderPassColorGrab(device, enable) {\\n\\t\\tif (enable) {\\n\\t\\t\\tif (!this.renderPassColorGrab) {\\n\\t\\t\\t\\tthis.renderPassColorGrab = new FramePassColorGrab(device);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis.renderPassColorGrab?.destroy();\\n\\t\\t\\tthis.renderPassColorGrab = null;\\n\\t\\t}\\n\\t}\\n\\t_enableRenderPassDepthGrab(device, renderer, enable) {\\n\\t\\tif (enable) {\\n\\t\\t\\tif (!this.renderPassDepthGrab) {\\n\\t\\t\\t\\tthis.renderPassDepthGrab = new FramePassDepthGrab(device, this);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis.renderPassDepthGrab?.destroy();\\n\\t\\t\\tthis.renderPassDepthGrab = null;\\n\\t\\t}\\n\\t}\\n\\t_updateViewProjMat() {\\n\\t\\tif (this._projMatDirty || this._viewMatDirty || this._viewProjMatDirty) {\\n\\t\\t\\tthis._viewProjMat.mul2(this.projectionMatrix, this.viewMatrix);\\n\\t\\t\\tthis._viewProjMatDirty = false;\\n\\t\\t}\\n\\t}\\n\\tworldToScreen(worldCoord, cw, ch, screenCoord = new Vec3()) {\\n\\t\\tthis._updateViewProjMat();\\n\\t\\tthis._viewProjMat.transformPoint(worldCoord, screenCoord);\\n\\t\\tconst vpm = this._viewProjMat.data;\\n\\t\\tconst w = worldCoord.x * vpm[3] + worldCoord.y * vpm[7] + worldCoord.z * vpm[11] + 1 * vpm[15];\\n\\t\\tscreenCoord.x = (screenCoord.x / w + 1) * 0.5;\\n\\t\\tscreenCoord.y = (1 - screenCoord.y / w) * 0.5;\\n\\t\\tconst { x: rx, y: ry, z: rw, w: rh } = this._rect;\\n\\t\\tscreenCoord.x = screenCoord.x * rw * cw + rx * cw;\\n\\t\\tscreenCoord.y = screenCoord.y * rh * ch + (1 - ry - rh) * ch;\\n\\t\\treturn screenCoord;\\n\\t}\\n\\tscreenToWorld(x, y, z, cw, ch, worldCoord = new Vec3()) {\\n\\t\\tconst { x: rx, y: ry, z: rw, w: rh } = this._rect;\\n\\t\\tconst range = this.farClip - this.nearClip;\\n\\t\\t_deviceCoord.set(\\n\\t\\t\\t(x - rx * cw) / (rw * cw),\\n\\t\\t\\t1 - (y - (1 - ry - rh) * ch) / (rh * ch),\\n\\t\\t\\tz / range\\n\\t\\t);\\n\\t\\t_deviceCoord.mulScalar(2);\\n\\t\\t_deviceCoord.sub(Vec3.ONE);\\n\\t\\tif (this._projection === PROJECTION_PERSPECTIVE) {\\n\\t\\t\\tMat4._getPerspectiveHalfSize(_halfSize, this.fov, this.aspectRatio, this.nearClip, this.horizontalFov);\\n\\t\\t\\t_halfSize.x *= _deviceCoord.x;\\n\\t\\t\\t_halfSize.y *= _deviceCoord.y;\\n\\t\\t\\tconst invView = this._node.getWorldTransform();\\n\\t\\t\\t_halfSize.z = -this.nearClip;\\n\\t\\t\\tinvView.transformPoint(_halfSize, _point);\\n\\t\\t\\tconst cameraPos = this._node.getPosition();\\n\\t\\t\\tworldCoord.sub2(_point, cameraPos);\\n\\t\\t\\tworldCoord.normalize();\\n\\t\\t\\tworldCoord.mulScalar(z);\\n\\t\\t\\tworldCoord.add(cameraPos);\\n\\t\\t} else {\\n\\t\\t\\tthis._updateViewProjMat();\\n\\t\\t\\t_invViewProjMat.copy(this._viewProjMat).invert();\\n\\t\\t\\t_invViewProjMat.transformPoint(_deviceCoord, worldCoord);\\n\\t\\t}\\n\\t\\treturn worldCoord;\\n\\t}\\n\\t_evaluateProjectionMatrix() {\\n\\t\\tconst aspect = this.aspectRatio;\\n\\t\\tif (this._projMatDirty) {\\n\\t\\t\\tif (this._projection === PROJECTION_PERSPECTIVE) {\\n\\t\\t\\t\\tthis._projMat.setPerspective(this.fov, aspect, this.nearClip, this.farClip, this.horizontalFov);\\n\\t\\t\\t\\tthis._projMatSkybox.copy(this._projMat);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconst y = this._orthoHeight;\\n\\t\\t\\t\\tconst x = y * aspect;\\n\\t\\t\\t\\tthis._projMat.setOrtho(-x, x, -y, y, this.nearClip, this.farClip);\\n\\t\\t\\t\\tthis._projMatSkybox.setPerspective(this.fov, aspect, this.nearClip, this.farClip);\\n\\t\\t\\t}\\n\\t\\t\\tthis._projMatDirty = false;\\n\\t\\t}\\n\\t}\\n\\tgetProjectionMatrixSkybox() {\\n\\t\\tthis._evaluateProjectionMatrix();\\n\\t\\treturn this._projMatSkybox;\\n\\t}\\n\\tgetExposure() {\\n\\t\\tconst ev100 = Math.log2(this._aperture * this._aperture / this._shutter * 100 / this._sensitivity);\\n\\t\\treturn 1 / (Math.pow(2, ev100) * 1.2);\\n\\t}\\n\\t// returns estimated size of the sphere on the screen in range of [0..1]\\n\\t// 0 - infinitely small, 1 - full screen or larger\\n\\tgetScreenSize(sphere) {\\n\\t\\tif (this._projection === PROJECTION_PERSPECTIVE) {\\n\\t\\t\\tconst distance = this._node.getPosition().distance(sphere.center);\\n\\t\\t\\tif (distance < sphere.radius) {\\n\\t\\t\\t\\treturn 1;\\n\\t\\t\\t}\\n\\t\\t\\tconst viewAngle = Math.asin(sphere.radius / distance);\\n\\t\\t\\tconst sphereViewHeight = Math.tan(viewAngle);\\n\\t\\t\\tconst screenViewHeight = Math.tan(this.fov / 2 * math.DEG_TO_RAD);\\n\\t\\t\\treturn Math.min(sphereViewHeight / screenViewHeight, 1);\\n\\t\\t}\\n\\t\\treturn math.clamp(sphere.radius / this._orthoHeight, 0, 1);\\n\\t}\\n\\tgetFrustumCorners(near = this.nearClip, far = this.farClip) {\\n\\t\\tconst fov = this.fov * math.DEG_TO_RAD;\\n\\t\\tlet x, y;\\n\\t\\tif (this.projection === PROJECTION_PERSPECTIVE) {\\n\\t\\t\\tif (this.horizontalFov) {\\n\\t\\t\\t\\tx = near * Math.tan(fov / 2);\\n\\t\\t\\t\\ty = x / this.aspectRatio;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\ty = near * Math.tan(fov / 2);\\n\\t\\t\\t\\tx = y * this.aspectRatio;\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\ty = this._orthoHeight;\\n\\t\\t\\tx = y * this.aspectRatio;\\n\\t\\t}\\n\\t\\tconst points = _frustumPoints;\\n\\t\\tpoints[0].x = x;\\n\\t\\tpoints[0].y = -y;\\n\\t\\tpoints[0].z = -near;\\n\\t\\tpoints[1].x = x;\\n\\t\\tpoints[1].y = y;\\n\\t\\tpoints[1].z = -near;\\n\\t\\tpoints[2].x = -x;\\n\\t\\tpoints[2].y = y;\\n\\t\\tpoints[2].z = -near;\\n\\t\\tpoints[3].x = -x;\\n\\t\\tpoints[3].y = -y;\\n\\t\\tpoints[3].z = -near;\\n\\t\\tif (this._projection === PROJECTION_PERSPECTIVE) {\\n\\t\\t\\tif (this.horizontalFov) {\\n\\t\\t\\t\\tx = far * Math.tan(fov / 2);\\n\\t\\t\\t\\ty = x / this.aspectRatio;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\ty = far * Math.tan(fov / 2);\\n\\t\\t\\t\\tx = y * this.aspectRatio;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tpoints[4].x = x;\\n\\t\\tpoints[4].y = -y;\\n\\t\\tpoints[4].z = -far;\\n\\t\\tpoints[5].x = x;\\n\\t\\tpoints[5].y = y;\\n\\t\\tpoints[5].z = -far;\\n\\t\\tpoints[6].x = -x;\\n\\t\\tpoints[6].y = y;\\n\\t\\tpoints[6].z = -far;\\n\\t\\tpoints[7].x = -x;\\n\\t\\tpoints[7].y = -y;\\n\\t\\tpoints[7].z = -far;\\n\\t\\treturn points;\\n\\t}\\n\\tsetXrProperties(properties) {\\n\\t\\tObject.assign(this._xrProperties, properties);\\n\\t\\tthis._projMatDirty = true;\\n\\t}\\n\\tfillShaderParams(output) {\\n\\t\\tconst f = this._farClip;\\n\\t\\toutput[0] = 1 / f;\\n\\t\\toutput[1] = f;\\n\\t\\toutput[2] = this._nearClip;\\n\\t\\toutput[3] = this._projection === PROJECTION_ORTHOGRAPHIC ? 1 : 0;\\n\\t\\treturn output;\\n\\t}\\n};\\n\\nconst _viewMat$1 = new Mat4();\\nconst _viewProjMat$3 = new Mat4();\\nconst _viewportMatrix = new Mat4();\\nclass LightCamera {\\n\\t// camera rotation angles used when rendering cubemap faces\\n\\tstatic pointLightRotations = [\\n\\t\\tnew Quat().setFromEulerAngles(0, 90, 180),\\n\\t\\tnew Quat().setFromEulerAngles(0, -90, 180),\\n\\t\\tnew Quat().setFromEulerAngles(90, 0, 0),\\n\\t\\tnew Quat().setFromEulerAngles(-90, 0, 0),\\n\\t\\tnew Quat().setFromEulerAngles(0, 180, 180),\\n\\t\\tnew Quat().setFromEulerAngles(0, 0, 180)\\n\\t];\\n\\tstatic create(device, name, lightType, face) {\\n\\t\\tconst camera = new Camera$1(device);\\n\\t\\tcamera.node = new GraphNode(name);\\n\\t\\tcamera.aspectRatio = 1;\\n\\t\\tcamera.aspectRatioMode = ASPECT_MANUAL;\\n\\t\\tcamera._scissorRectClear = true;\\n\\t\\tswitch (lightType) {\\n\\t\\t\\tcase LIGHTTYPE_OMNI:\\n\\t\\t\\t\\tcamera.node.setRotation(LightCamera.pointLightRotations[face]);\\n\\t\\t\\t\\tcamera.fov = 90;\\n\\t\\t\\t\\tcamera.projection = PROJECTION_PERSPECTIVE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase LIGHTTYPE_SPOT:\\n\\t\\t\\t\\tcamera.projection = PROJECTION_PERSPECTIVE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase LIGHTTYPE_DIRECTIONAL:\\n\\t\\t\\t\\tcamera.projection = PROJECTION_ORTHOGRAPHIC;\\n\\t\\t\\t\\tbreak;\\n\\t\\t}\\n\\t\\treturn camera;\\n\\t}\\n\\tstatic _spotCookieCamera = null;\\n\\t// temporary camera to calculate spot light cookie view-projection matrix when shadow matrix is not available\\n\\t// todo - unify the code with the shadow spot camera\\n\\tstatic evalSpotCookieMatrix(light) {\\n\\t\\tlet cookieCamera = LightCamera._spotCookieCamera;\\n\\t\\tif (!cookieCamera) {\\n\\t\\t\\tcookieCamera = LightCamera.create(light.device, \\\"SpotCookieCamera\\\", LIGHTTYPE_SPOT);\\n\\t\\t\\tLightCamera._spotCookieCamera = cookieCamera;\\n\\t\\t}\\n\\t\\tcookieCamera.fov = light._outerConeAngle * 2;\\n\\t\\tconst cookieNode = cookieCamera._node;\\n\\t\\tcookieNode.setPosition(light._node.getPosition());\\n\\t\\tcookieNode.setRotation(light._node.getRotation());\\n\\t\\tcookieNode.rotateLocal(-90, 0, 0);\\n\\t\\t_viewMat$1.setTRS(cookieNode.getPosition(), cookieNode.getRotation(), Vec3.ONE).invert();\\n\\t\\t_viewProjMat$3.mul2(cookieCamera.projectionMatrix, _viewMat$1);\\n\\t\\tconst cookieMatrix = light.cookieMatrix;\\n\\t\\tconst rectViewport = light.atlasViewport;\\n\\t\\t_viewportMatrix.setViewport(rectViewport.x, rectViewport.y, rectViewport.z, rectViewport.w);\\n\\t\\tcookieMatrix.mul2(_viewportMatrix, _viewProjMat$3);\\n\\t\\treturn cookieMatrix;\\n\\t}\\n}\\n\\nconst tempVec3$1 = new Vec3();\\nconst tempAreaLightSizes = new Float32Array(6);\\nconst areaHalfAxisWidth = new Vec3(-0.5, 0, 0);\\nconst areaHalfAxisHeight = new Vec3(0, 0, 0.5);\\nconst TextureIndexFloat = {\\n\\tPOSITION_RANGE: 0,\\n\\t// positions.xyz, range\\n\\tDIRECTION_FLAGS: 1,\\n\\t// spot direction.xyz, 32bit flags\\n\\tCOLOR_ANGLES_BIAS: 2,\\n\\t// x: color.rg, y: color.b & angle flags, z: cone angles, w: biases (all packed as 16-bit values)\\n\\tPROJ_MAT_0: 3,\\n\\t// projection matrix row 0 (spot light)\\n\\tATLAS_VIEWPORT: 3,\\n\\t// atlas viewport data (omni light)\\n\\tPROJ_MAT_1: 4,\\n\\t// projection matrix row 1 (spot light)\\n\\tPROJ_MAT_2: 5,\\n\\t// projection matrix row 2 (spot light)\\n\\tPROJ_MAT_3: 6,\\n\\t// projection matrix row 3 (spot light)\\n\\tAREA_DATA_WIDTH: 7,\\n\\t// area light half-width.xyz, -\\n\\tAREA_DATA_HEIGHT: 8,\\n\\t// area light half-height.xyz, -\\n\\t// leave last\\n\\tCOUNT: 9\\n};\\nconst enums = {\\n\\t\\\"LIGHTSHAPE_PUNCTUAL\\\": `${LIGHTSHAPE_PUNCTUAL}u`,\\n\\t\\\"LIGHTSHAPE_RECT\\\": `${LIGHTSHAPE_RECT}u`,\\n\\t\\\"LIGHTSHAPE_DISK\\\": `${LIGHTSHAPE_DISK}u`,\\n\\t\\\"LIGHTSHAPE_SPHERE\\\": `${LIGHTSHAPE_SPHERE}u`,\\n\\t\\\"LIGHT_COLOR_DIVIDER\\\": `${LIGHT_COLOR_DIVIDER}.0`\\n};\\nconst buildShaderDefines = (object, prefix) => {\\n\\treturn Object.keys(object).map((key) => `#define {${prefix}${key}} ${object[key]}`).join(\\\"\\\\n\\\");\\n};\\nconst lightBufferDefines = `\\n\\n\\t\\t${buildShaderDefines(TextureIndexFloat, \\\"CLUSTER_TEXTURE_\\\")}\\n\\t\\t${buildShaderDefines(enums, \\\"\\\")}\\n`;\\nclass LightsBuffer {\\n\\tareaLightsEnabled = false;\\n\\tconstructor(device) {\\n\\t\\tthis.device = device;\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set(\\\"lightBufferDefinesPS\\\", lightBufferDefines);\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set(\\\"lightBufferDefinesPS\\\", lightBufferDefines);\\n\\t\\tthis.cookiesEnabled = false;\\n\\t\\tthis.shadowsEnabled = false;\\n\\t\\tthis.areaLightsEnabled = false;\\n\\t\\tthis.maxLights = 255;\\n\\t\\tconst pixelsPerLightFloat = TextureIndexFloat.COUNT;\\n\\t\\tthis.lightsFloat = new Float32Array(4 * pixelsPerLightFloat * this.maxLights);\\n\\t\\tthis.lightsUint = new Uint32Array(this.lightsFloat.buffer);\\n\\t\\tthis.lightsTexture = this.createTexture(this.device, pixelsPerLightFloat, this.maxLights, PIXELFORMAT_RGBA32F, \\\"LightsTexture\\\");\\n\\t\\tthis._lightsTextureId = this.device.scope.resolve(\\\"lightsTexture\\\");\\n\\t\\tthis.invMaxColorValue = 0;\\n\\t\\tthis.invMaxAttenuation = 0;\\n\\t\\tthis.boundsMin = new Vec3();\\n\\t\\tthis.boundsDelta = new Vec3();\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.lightsTexture?.destroy();\\n\\t\\tthis.lightsTexture = null;\\n\\t}\\n\\tcreateTexture(device, width, height, format, name) {\\n\\t\\tconst tex = new Texture(device, {\\n\\t\\t\\tname,\\n\\t\\t\\twidth,\\n\\t\\t\\theight,\\n\\t\\t\\tmipmaps: false,\\n\\t\\t\\tformat,\\n\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\ttype: TEXTURETYPE_DEFAULT,\\n\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\tanisotropy: 1\\n\\t\\t});\\n\\t\\treturn tex;\\n\\t}\\n\\tsetBounds(min, delta) {\\n\\t\\tthis.boundsMin.copy(min);\\n\\t\\tthis.boundsDelta.copy(delta);\\n\\t}\\n\\tuploadTextures() {\\n\\t\\tthis.lightsTexture.lock().set(this.lightsFloat);\\n\\t\\tthis.lightsTexture.unlock();\\n\\t}\\n\\tupdateUniforms() {\\n\\t\\tthis._lightsTextureId.setValue(this.lightsTexture);\\n\\t}\\n\\tgetSpotDirection(direction, spot) {\\n\\t\\tconst mat = spot._node.getWorldTransform();\\n\\t\\tmat.getY(direction).mulScalar(-1);\\n\\t\\tdirection.normalize();\\n\\t}\\n\\t// half sizes of area light in world space, returned as an array of 6 floats\\n\\tgetLightAreaSizes(light) {\\n\\t\\tconst mat = light._node.getWorldTransform();\\n\\t\\tmat.transformVector(areaHalfAxisWidth, tempVec3$1);\\n\\t\\ttempAreaLightSizes[0] = tempVec3$1.x;\\n\\t\\ttempAreaLightSizes[1] = tempVec3$1.y;\\n\\t\\ttempAreaLightSizes[2] = tempVec3$1.z;\\n\\t\\tmat.transformVector(areaHalfAxisHeight, tempVec3$1);\\n\\t\\ttempAreaLightSizes[3] = tempVec3$1.x;\\n\\t\\ttempAreaLightSizes[4] = tempVec3$1.y;\\n\\t\\ttempAreaLightSizes[5] = tempVec3$1.z;\\n\\t\\treturn tempAreaLightSizes;\\n\\t}\\n\\t// fill up both float and 8bit texture data with light properties\\n\\taddLightData(light, lightIndex) {\\n\\t\\tconst isSpot = light._type === LIGHTTYPE_SPOT;\\n\\t\\tconst hasAtlasViewport = light.atlasViewportAllocated;\\n\\t\\tconst isCookie = this.cookiesEnabled && !!light._cookie && hasAtlasViewport;\\n\\t\\tconst isArea = this.areaLightsEnabled && light.shape !== LIGHTSHAPE_PUNCTUAL;\\n\\t\\tconst castShadows = this.shadowsEnabled && light.castShadows && hasAtlasViewport;\\n\\t\\tconst pos = light._node.getPosition();\\n\\t\\tlet lightProjectionMatrix = null;\\n\\t\\tlet atlasViewport = null;\\n\\t\\tif (isSpot) {\\n\\t\\t\\tif (castShadows) {\\n\\t\\t\\t\\tconst lightRenderData = light.getRenderData(null, 0);\\n\\t\\t\\t\\tlightProjectionMatrix = lightRenderData.shadowMatrix;\\n\\t\\t\\t} else if (isCookie) {\\n\\t\\t\\t\\tlightProjectionMatrix = LightCamera.evalSpotCookieMatrix(light);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tif (castShadows || isCookie) {\\n\\t\\t\\t\\tatlasViewport = light.atlasViewport;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst dataFloat = this.lightsFloat;\\n\\t\\tconst dataUint = this.lightsUint;\\n\\t\\tconst dataFloatStart = lightIndex * this.lightsTexture.width * 4;\\n\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.POSITION_RANGE + 0] = pos.x;\\n\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.POSITION_RANGE + 1] = pos.y;\\n\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.POSITION_RANGE + 2] = pos.z;\\n\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.POSITION_RANGE + 3] = light.attenuationEnd;\\n\\t\\tconst clusteredData = light.clusteredData;\\n\\t\\tdataUint[dataFloatStart + 4 * TextureIndexFloat.COLOR_ANGLES_BIAS + 0] = clusteredData[0];\\n\\t\\tdataUint[dataFloatStart + 4 * TextureIndexFloat.COLOR_ANGLES_BIAS + 1] = clusteredData[1];\\n\\t\\tdataUint[dataFloatStart + 4 * TextureIndexFloat.COLOR_ANGLES_BIAS + 2] = clusteredData[2];\\n\\t\\tif (light.castShadows) {\\n\\t\\t\\tconst lightRenderData = light.getRenderData(null, 0);\\n\\t\\t\\tconst biases = light._getUniformBiasValues(lightRenderData);\\n\\t\\t\\tconst biasHalf = FloatPacking.float2Half(biases.bias);\\n\\t\\t\\tconst normalBiasHalf = FloatPacking.float2Half(biases.normalBias);\\n\\t\\t\\tdataUint[dataFloatStart + 4 * TextureIndexFloat.COLOR_ANGLES_BIAS + 3] = biasHalf | normalBiasHalf << 16;\\n\\t\\t}\\n\\t\\tif (isSpot) {\\n\\t\\t\\tthis.getSpotDirection(tempVec3$1, light);\\n\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.DIRECTION_FLAGS + 0] = tempVec3$1.x;\\n\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.DIRECTION_FLAGS + 1] = tempVec3$1.y;\\n\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.DIRECTION_FLAGS + 2] = tempVec3$1.z;\\n\\t\\t}\\n\\t\\tdataUint[dataFloatStart + 4 * TextureIndexFloat.DIRECTION_FLAGS + 3] = light.getClusteredFlags(castShadows, isCookie);\\n\\t\\tif (lightProjectionMatrix) {\\n\\t\\t\\tconst matData = lightProjectionMatrix.data;\\n\\t\\t\\tfor (let m = 0; m < 16; m++) {\\n\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.PROJ_MAT_0 + m] = matData[m];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (atlasViewport) {\\n\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.ATLAS_VIEWPORT + 0] = atlasViewport.x;\\n\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.ATLAS_VIEWPORT + 1] = atlasViewport.y;\\n\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.ATLAS_VIEWPORT + 2] = atlasViewport.z / 3;\\n\\t\\t}\\n\\t\\tif (isArea) {\\n\\t\\t\\tconst areaSizes = this.getLightAreaSizes(light);\\n\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.AREA_DATA_WIDTH + 0] = areaSizes[0];\\n\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.AREA_DATA_WIDTH + 1] = areaSizes[1];\\n\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.AREA_DATA_WIDTH + 2] = areaSizes[2];\\n\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.AREA_DATA_HEIGHT + 0] = areaSizes[3];\\n\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.AREA_DATA_HEIGHT + 1] = areaSizes[4];\\n\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.AREA_DATA_HEIGHT + 2] = areaSizes[5];\\n\\t\\t}\\n\\t}\\n}\\n\\nconst tmpSize$1 = new Vec2();\\nconst tempVec3 = new Vec3();\\nconst tempMin3 = new Vec3();\\nconst tempMax3 = new Vec3();\\nconst tempBox = new BoundingBox();\\nclass ClusterLight {\\n\\tconstructor() {\\n\\t\\tthis.light = null;\\n\\t\\tthis.min = new Vec3();\\n\\t\\tthis.max = new Vec3();\\n\\t}\\n}\\nclass WorldClusters {\\n\\tclusterTexture;\\n\\tconstructor(device) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.name = \\\"Untitled\\\";\\n\\t\\tthis.reportCount = 0;\\n\\t\\tthis.boundsMin = new Vec3();\\n\\t\\tthis.boundsMax = new Vec3();\\n\\t\\tthis.boundsDelta = new Vec3();\\n\\t\\tthis._cells = new Vec3(1, 1, 1);\\n\\t\\tthis._cellsLimit = new Vec3();\\n\\t\\tthis.cells = this._cells;\\n\\t\\tthis.maxCellLightCount = 4;\\n\\t\\tthis._usedLights = [];\\n\\t\\tthis._usedLights.push(new ClusterLight());\\n\\t\\tthis.lightsBuffer = new LightsBuffer(device);\\n\\t\\tthis.registerUniforms(device);\\n\\t}\\n\\tset maxCellLightCount(count) {\\n\\t\\tif (count !== this._maxCellLightCount) {\\n\\t\\t\\tthis._maxCellLightCount = count;\\n\\t\\t\\tthis._cellsDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget maxCellLightCount() {\\n\\t\\treturn this._maxCellLightCount;\\n\\t}\\n\\tset cells(value) {\\n\\t\\ttempVec3.copy(value).floor();\\n\\t\\tif (!this._cells.equals(tempVec3)) {\\n\\t\\t\\tthis._cells.copy(tempVec3);\\n\\t\\t\\tthis._cellsLimit.copy(tempVec3).sub(Vec3.ONE);\\n\\t\\t\\tthis._cellsDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget cells() {\\n\\t\\treturn this._cells;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.lightsBuffer.destroy();\\n\\t\\tthis.releaseClusterTexture();\\n\\t}\\n\\treleaseClusterTexture() {\\n\\t\\tif (this.clusterTexture) {\\n\\t\\t\\tthis.clusterTexture.destroy();\\n\\t\\t\\tthis.clusterTexture = null;\\n\\t\\t}\\n\\t}\\n\\tregisterUniforms(device) {\\n\\t\\tthis._numClusteredLightsId = device.scope.resolve(\\\"numClusteredLights\\\");\\n\\t\\tthis._clusterMaxCellsId = device.scope.resolve(\\\"clusterMaxCells\\\");\\n\\t\\tthis._clusterWorldTextureId = device.scope.resolve(\\\"clusterWorldTexture\\\");\\n\\t\\tthis._clusterBoundsMinId = device.scope.resolve(\\\"clusterBoundsMin\\\");\\n\\t\\tthis._clusterBoundsMinData = new Float32Array(3);\\n\\t\\tthis._clusterBoundsDeltaId = device.scope.resolve(\\\"clusterBoundsDelta\\\");\\n\\t\\tthis._clusterBoundsDeltaData = new Float32Array(3);\\n\\t\\tthis._clusterCellsCountByBoundsSizeId = device.scope.resolve(\\\"clusterCellsCountByBoundsSize\\\");\\n\\t\\tthis._clusterCellsCountByBoundsSizeData = new Float32Array(3);\\n\\t\\tthis._clusterCellsDotId = device.scope.resolve(\\\"clusterCellsDot\\\");\\n\\t\\tthis._clusterCellsDotData = new Int32Array(3);\\n\\t\\tthis._clusterCellsMaxId = device.scope.resolve(\\\"clusterCellsMax\\\");\\n\\t\\tthis._clusterCellsMaxData = new Int32Array(3);\\n\\t\\tthis._clusterTextureWidthId = device.scope.resolve(\\\"clusterTextureWidth\\\");\\n\\t}\\n\\t// updates itself based on parameters stored in the scene\\n\\tupdateParams(lightingParams) {\\n\\t\\tif (lightingParams) {\\n\\t\\t\\tthis.cells = lightingParams.cells;\\n\\t\\t\\tthis.maxCellLightCount = lightingParams.maxLightsPerCell;\\n\\t\\t\\tthis.lightsBuffer.cookiesEnabled = lightingParams.cookiesEnabled;\\n\\t\\t\\tthis.lightsBuffer.shadowsEnabled = lightingParams.shadowsEnabled;\\n\\t\\t\\tthis.lightsBuffer.areaLightsEnabled = lightingParams.areaLightsEnabled;\\n\\t\\t}\\n\\t}\\n\\tupdateCells() {\\n\\t\\tif (this._cellsDirty) {\\n\\t\\t\\tthis._cellsDirty = false;\\n\\t\\t\\tconst cx = this._cells.x;\\n\\t\\t\\tconst cy = this._cells.y;\\n\\t\\t\\tconst cz = this._cells.z;\\n\\t\\t\\tconst numCells = cx * cy * cz;\\n\\t\\t\\tconst totalPixels = this.maxCellLightCount * numCells;\\n\\t\\t\\tconst { x: width, y: height } = TextureUtils.calcTextureSize(totalPixels, tmpSize$1, this.maxCellLightCount);\\n\\t\\t\\tthis._clusterCellsMaxData[0] = cx;\\n\\t\\t\\tthis._clusterCellsMaxData[1] = cy;\\n\\t\\t\\tthis._clusterCellsMaxData[2] = cz;\\n\\t\\t\\tthis._clusterCellsDotData[0] = this.maxCellLightCount;\\n\\t\\t\\tthis._clusterCellsDotData[1] = cx * cz * this.maxCellLightCount;\\n\\t\\t\\tthis._clusterCellsDotData[2] = cx * this.maxCellLightCount;\\n\\t\\t\\tthis.clusters = new Uint8ClampedArray(totalPixels);\\n\\t\\t\\tthis.counts = new Int32Array(numCells);\\n\\t\\t\\tthis.releaseClusterTexture();\\n\\t\\t\\tthis.clusterTexture = this.lightsBuffer.createTexture(this.device, width, height, PIXELFORMAT_R8U, \\\"ClusterTexture\\\");\\n\\t\\t}\\n\\t}\\n\\tuploadTextures() {\\n\\t\\tthis.clusterTexture.lock().set(this.clusters);\\n\\t\\tthis.clusterTexture.unlock();\\n\\t\\tthis.lightsBuffer.uploadTextures();\\n\\t}\\n\\tupdateUniforms() {\\n\\t\\tthis._numClusteredLightsId.setValue(this._usedLights.length);\\n\\t\\tthis.lightsBuffer.updateUniforms();\\n\\t\\tthis._clusterWorldTextureId.setValue(this.clusterTexture);\\n\\t\\tthis._clusterMaxCellsId.setValue(this.maxCellLightCount);\\n\\t\\tconst boundsDelta = this.boundsDelta;\\n\\t\\tthis._clusterCellsCountByBoundsSizeData[0] = this._cells.x / boundsDelta.x;\\n\\t\\tthis._clusterCellsCountByBoundsSizeData[1] = this._cells.y / boundsDelta.y;\\n\\t\\tthis._clusterCellsCountByBoundsSizeData[2] = this._cells.z / boundsDelta.z;\\n\\t\\tthis._clusterCellsCountByBoundsSizeId.setValue(this._clusterCellsCountByBoundsSizeData);\\n\\t\\tthis._clusterBoundsMinData[0] = this.boundsMin.x;\\n\\t\\tthis._clusterBoundsMinData[1] = this.boundsMin.y;\\n\\t\\tthis._clusterBoundsMinData[2] = this.boundsMin.z;\\n\\t\\tthis._clusterBoundsDeltaData[0] = boundsDelta.x;\\n\\t\\tthis._clusterBoundsDeltaData[1] = boundsDelta.y;\\n\\t\\tthis._clusterBoundsDeltaData[2] = boundsDelta.z;\\n\\t\\tthis._clusterBoundsMinId.setValue(this._clusterBoundsMinData);\\n\\t\\tthis._clusterBoundsDeltaId.setValue(this._clusterBoundsDeltaData);\\n\\t\\tthis._clusterCellsDotId.setValue(this._clusterCellsDotData);\\n\\t\\tthis._clusterCellsMaxId.setValue(this._clusterCellsMaxData);\\n\\t\\tthis._clusterTextureWidthId.setValue(this.clusterTexture.width);\\n\\t}\\n\\t// evaluates min and max coordinates of AABB of the light in the cell space\\n\\tevalLightCellMinMax(clusteredLight, min, max) {\\n\\t\\tmin.copy(clusteredLight.min);\\n\\t\\tmin.sub(this.boundsMin);\\n\\t\\tmin.div(this.boundsDelta);\\n\\t\\tmin.mul2(min, this.cells);\\n\\t\\tmin.floor();\\n\\t\\tmax.copy(clusteredLight.max);\\n\\t\\tmax.sub(this.boundsMin);\\n\\t\\tmax.div(this.boundsDelta);\\n\\t\\tmax.mul2(max, this.cells);\\n\\t\\tmax.ceil();\\n\\t\\tmin.max(Vec3.ZERO);\\n\\t\\tmax.min(this._cellsLimit);\\n\\t}\\n\\tcollectLights(lights) {\\n\\t\\tconst maxLights = this.lightsBuffer.maxLights;\\n\\t\\tconst usedLights = this._usedLights;\\n\\t\\tlet lightIndex = 1;\\n\\t\\tlights.forEach((light) => {\\n\\t\\t\\tconst runtimeLight = !!(light.mask & (MASK_AFFECT_DYNAMIC | MASK_AFFECT_LIGHTMAPPED));\\n\\t\\t\\tconst zeroAngleSpotlight = light.type === LIGHTTYPE_SPOT && light._outerConeAngle === 0;\\n\\t\\t\\tif (light.enabled && light.type !== LIGHTTYPE_DIRECTIONAL && light.visibleThisFrame && light.intensity > 0 && runtimeLight && !zeroAngleSpotlight) {\\n\\t\\t\\t\\tif (lightIndex < maxLights) {\\n\\t\\t\\t\\t\\tlet clusteredLight;\\n\\t\\t\\t\\t\\tif (lightIndex < usedLights.length) {\\n\\t\\t\\t\\t\\t\\tclusteredLight = usedLights[lightIndex];\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tclusteredLight = new ClusterLight();\\n\\t\\t\\t\\t\\t\\tusedLights.push(clusteredLight);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tclusteredLight.light = light;\\n\\t\\t\\t\\t\\tlight.getBoundingBox(tempBox);\\n\\t\\t\\t\\t\\tclusteredLight.min.copy(tempBox.getMin());\\n\\t\\t\\t\\t\\tclusteredLight.max.copy(tempBox.getMax());\\n\\t\\t\\t\\t\\tlightIndex++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tusedLights.length = lightIndex;\\n\\t}\\n\\t// evaluate the area all lights cover\\n\\tevaluateBounds() {\\n\\t\\tconst usedLights = this._usedLights;\\n\\t\\tconst min = this.boundsMin;\\n\\t\\tconst max = this.boundsMax;\\n\\t\\tif (usedLights.length > 1) {\\n\\t\\t\\tmin.copy(usedLights[1].min);\\n\\t\\t\\tmax.copy(usedLights[1].max);\\n\\t\\t\\tfor (let i = 2; i < usedLights.length; i++) {\\n\\t\\t\\t\\tmin.min(usedLights[i].min);\\n\\t\\t\\t\\tmax.max(usedLights[i].max);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tmin.set(0, 0, 0);\\n\\t\\t\\tmax.set(1, 1, 1);\\n\\t\\t}\\n\\t\\tthis.boundsDelta.sub2(max, min);\\n\\t\\tthis.lightsBuffer.setBounds(min, this.boundsDelta);\\n\\t}\\n\\tupdateClusters(lightingParams) {\\n\\t\\tthis.counts.fill(0);\\n\\t\\tthis.clusters.fill(0);\\n\\t\\tthis.lightsBuffer.areaLightsEnabled = lightingParams ? lightingParams.areaLightsEnabled : false;\\n\\t\\tconst divX = this._cells.x;\\n\\t\\tconst divZ = this._cells.z;\\n\\t\\tconst counts = this.counts;\\n\\t\\tconst limit = this._maxCellLightCount;\\n\\t\\tconst clusters = this.clusters;\\n\\t\\tconst pixelsPerCellCount = this.maxCellLightCount;\\n\\t\\tconst usedLights = this._usedLights;\\n\\t\\tfor (let i = 1; i < usedLights.length; i++) {\\n\\t\\t\\tconst clusteredLight = usedLights[i];\\n\\t\\t\\tconst light = clusteredLight.light;\\n\\t\\t\\tthis.lightsBuffer.addLightData(light, i);\\n\\t\\t\\tthis.evalLightCellMinMax(clusteredLight, tempMin3, tempMax3);\\n\\t\\t\\tconst xStart = tempMin3.x;\\n\\t\\t\\tconst xEnd = tempMax3.x;\\n\\t\\t\\tconst yStart = tempMin3.y;\\n\\t\\t\\tconst yEnd = tempMax3.y;\\n\\t\\t\\tconst zStart = tempMin3.z;\\n\\t\\t\\tconst zEnd = tempMax3.z;\\n\\t\\t\\tfor (let x = xStart; x <= xEnd; x++) {\\n\\t\\t\\t\\tfor (let z = zStart; z <= zEnd; z++) {\\n\\t\\t\\t\\t\\tfor (let y = yStart; y <= yEnd; y++) {\\n\\t\\t\\t\\t\\t\\tconst clusterIndex = x + divX * (z + y * divZ);\\n\\t\\t\\t\\t\\t\\tconst count = counts[clusterIndex];\\n\\t\\t\\t\\t\\t\\tif (count < limit) {\\n\\t\\t\\t\\t\\t\\t\\tclusters[pixelsPerCellCount * clusterIndex + count] = i;\\n\\t\\t\\t\\t\\t\\t\\tcounts[clusterIndex] = count + 1;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t// internal update of the cluster data, executes once per frame\\n\\tupdate(lights, lightingParams = null) {\\n\\t\\tthis.updateParams(lightingParams);\\n\\t\\tthis.updateCells();\\n\\t\\tthis.collectLights(lights);\\n\\t\\tthis.evaluateBounds();\\n\\t\\tthis.updateClusters(lightingParams);\\n\\t\\tthis.uploadTextures();\\n\\t}\\n\\t// called on already updated clusters, activates for rendering by setting up uniforms / textures on the device\\n\\tactivate() {\\n\\t\\tthis.updateUniforms();\\n\\t}\\n}\\n\\nconst base64String = \\\"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\\\";\\nlet data = null;\\nconst initData = () => {\\n\\tif (!data) {\\n\\t\\tconst binaryString = atob(base64String);\\n\\t\\tdata = Uint8Array.from(binaryString, (char) => char.charCodeAt(0));\\n\\t}\\n};\\nconst blueNoiseData = () => {\\n\\tinitData();\\n\\treturn data;\\n};\\nclass BlueNoise {\\n\\tseed = 0;\\n\\tconstructor(seed = 0) {\\n\\t\\tthis.seed = seed * 4;\\n\\t\\tinitData();\\n\\t}\\n\\t_next() {\\n\\t\\tthis.seed = (this.seed + 4) % data.length;\\n\\t}\\n\\tvalue() {\\n\\t\\tthis._next();\\n\\t\\treturn data[this.seed] / 255;\\n\\t}\\n\\tvec4(dest = new Vec4()) {\\n\\t\\tthis._next();\\n\\t\\treturn dest.set(data[this.seed], data[this.seed + 1], data[this.seed + 2], data[this.seed + 3]).mulScalar(1 / 255);\\n\\t}\\n}\\n\\nconst lightCubeDir = [\\n\\tnew Vec3(-1, 0, 0),\\n\\tnew Vec3(1, 0, 0),\\n\\tnew Vec3(0, -1, 0),\\n\\tnew Vec3(0, 1, 0),\\n\\tnew Vec3(0, 0, -1),\\n\\tnew Vec3(0, 0, 1)\\n];\\nclass LightCube {\\n\\tcolors = new Float32Array(6 * 3);\\n\\tupdate(ambientLight, lights) {\\n\\t\\tconst colors = this.colors;\\n\\t\\tconst { r, g, b } = ambientLight;\\n\\t\\tfor (let j = 0; j < 6; j++) {\\n\\t\\t\\tcolors[j * 3] = r;\\n\\t\\t\\tcolors[j * 3 + 1] = g;\\n\\t\\t\\tcolors[j * 3 + 2] = b;\\n\\t\\t}\\n\\t\\tfor (let j = 0; j < lights.length; j++) {\\n\\t\\t\\tconst light = lights[j];\\n\\t\\t\\tif (light._type === LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\tfor (let c = 0; c < 6; c++) {\\n\\t\\t\\t\\t\\tconst weight = Math.max(lightCubeDir[c].dot(light._direction), 0) * light._intensity;\\n\\t\\t\\t\\t\\tconst lightColor = light._color;\\n\\t\\t\\t\\t\\tcolors[c * 3] += lightColor.r * weight;\\n\\t\\t\\t\\t\\tcolors[c * 3 + 1] += lightColor.g * weight;\\n\\t\\t\\t\\t\\tcolors[c * 3 + 2] += lightColor.b * weight;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\n\\nconst createTexture = (device, namePrefix, size, data) => {\\n\\tconst texture = new Texture(device, {\\n\\t\\tname: `${namePrefix}${size}`,\\n\\t\\twidth: size,\\n\\t\\theight: size,\\n\\t\\tformat: PIXELFORMAT_RGBA8,\\n\\t\\taddressU: ADDRESS_REPEAT,\\n\\t\\taddressV: ADDRESS_REPEAT,\\n\\t\\ttype: TEXTURETYPE_DEFAULT,\\n\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\tanisotropy: 1,\\n\\t\\tmipmaps: false\\n\\t});\\n\\ttexture.lock().set(data);\\n\\ttexture.unlock();\\n\\treturn texture;\\n};\\nconst deviceCacheBlueNoise = new DeviceCache();\\nconst getBlueNoiseTexture = (device) => {\\n\\treturn deviceCacheBlueNoise.get(device, () => {\\n\\t\\tconst data = blueNoiseData();\\n\\t\\tconst size = Math.sqrt(data.length / 4);\\n\\t\\treturn createTexture(device, \\\"BlueNoise\\\", size, data);\\n\\t});\\n};\\n\\nclass ShadowMap {\\n\\tconstructor(texture, targets) {\\n\\t\\tthis.texture = texture;\\n\\t\\tthis.cached = false;\\n\\t\\tthis.renderTargets = targets;\\n\\t}\\n\\tdestroy() {\\n\\t\\tif (this.texture) {\\n\\t\\t\\tthis.texture.destroy();\\n\\t\\t\\tthis.texture = null;\\n\\t\\t}\\n\\t\\tconst targets = this.renderTargets;\\n\\t\\tfor (let i = 0; i < targets.length; i++) {\\n\\t\\t\\ttargets[i].destroy();\\n\\t\\t}\\n\\t\\tthis.renderTargets.length = 0;\\n\\t}\\n\\tstatic create(device, light) {\\n\\t\\tlet shadowMap = null;\\n\\t\\tif (light._type === LIGHTTYPE_OMNI) {\\n\\t\\t\\tshadowMap = this.createCubemap(device, light._shadowResolution, light._shadowType);\\n\\t\\t} else {\\n\\t\\t\\tshadowMap = this.create2dMap(device, light._shadowResolution, light._shadowType);\\n\\t\\t}\\n\\t\\treturn shadowMap;\\n\\t}\\n\\t// creates a shadow map which is used by the light texture atlas for clustered lighting\\n\\tstatic createAtlas(device, resolution, shadowType) {\\n\\t\\tconst shadowMap = this.create2dMap(device, resolution, shadowType);\\n\\t\\tconst targets = shadowMap.renderTargets;\\n\\t\\tconst rt = targets[0];\\n\\t\\tfor (let i = 0; i < 5; i++) {\\n\\t\\t\\ttargets.push(rt);\\n\\t\\t}\\n\\t\\treturn shadowMap;\\n\\t}\\n\\tstatic create2dMap(device, size, shadowType) {\\n\\t\\tconst shadowInfo = shadowTypeInfo.get(shadowType);\\n\\t\\tlet format = shadowInfo.format;\\n\\t\\tif (format === PIXELFORMAT_R32F && !device.textureFloatRenderable && device.textureHalfFloatRenderable) {\\n\\t\\t\\tformat = PIXELFORMAT_R16F;\\n\\t\\t}\\n\\t\\tconst formatName = pixelFormatInfo.get(format)?.name;\\n\\t\\tlet filter = FILTER_LINEAR;\\n\\t\\tif (shadowType === SHADOW_VSM_32F) {\\n\\t\\t\\tfilter = device.extTextureFloatLinear ? FILTER_LINEAR : FILTER_NEAREST;\\n\\t\\t}\\n\\t\\tif (shadowType === SHADOW_PCSS_32F) {\\n\\t\\t\\tfilter = FILTER_NEAREST;\\n\\t\\t}\\n\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\tformat,\\n\\t\\t\\twidth: size,\\n\\t\\t\\theight: size,\\n\\t\\t\\tmipmaps: false,\\n\\t\\t\\tminFilter: filter,\\n\\t\\t\\tmagFilter: filter,\\n\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\tname: `ShadowMap2D_${formatName}`\\n\\t\\t});\\n\\t\\tlet target = null;\\n\\t\\tif (shadowInfo?.pcf) {\\n\\t\\t\\ttexture.compareOnRead = true;\\n\\t\\t\\ttexture.compareFunc = FUNC_LESS;\\n\\t\\t\\ttarget = new RenderTarget({\\n\\t\\t\\t\\tdepthBuffer: texture\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\ttarget = new RenderTarget({\\n\\t\\t\\t\\tcolorBuffer: texture,\\n\\t\\t\\t\\tdepth: true\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tif (device.isWebGPU) {\\n\\t\\t\\ttarget.flipY = true;\\n\\t\\t}\\n\\t\\treturn new ShadowMap(texture, [target]);\\n\\t}\\n\\tstatic createCubemap(device, size, shadowType) {\\n\\t\\tconst shadowInfo = shadowTypeInfo.get(shadowType);\\n\\t\\tconst formatName = pixelFormatInfo.get(shadowInfo.format)?.name;\\n\\t\\tconst isPcss = shadowType === SHADOW_PCSS_32F;\\n\\t\\tconst filter = isPcss ? FILTER_NEAREST : FILTER_LINEAR;\\n\\t\\tconst cubemap = new Texture(device, {\\n\\t\\t\\tformat: shadowInfo?.format,\\n\\t\\t\\twidth: size,\\n\\t\\t\\theight: size,\\n\\t\\t\\tcubemap: true,\\n\\t\\t\\tmipmaps: false,\\n\\t\\t\\tminFilter: filter,\\n\\t\\t\\tmagFilter: filter,\\n\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\tname: `ShadowMapCube_${formatName}`\\n\\t\\t});\\n\\t\\tif (!isPcss) {\\n\\t\\t\\tcubemap.compareOnRead = true;\\n\\t\\t\\tcubemap.compareFunc = FUNC_LESS;\\n\\t\\t}\\n\\t\\tconst targets = [];\\n\\t\\tfor (let i = 0; i < 6; i++) {\\n\\t\\t\\tif (isPcss) {\\n\\t\\t\\t\\ttargets.push(new RenderTarget({\\n\\t\\t\\t\\t\\tcolorBuffer: cubemap,\\n\\t\\t\\t\\t\\tface: i,\\n\\t\\t\\t\\t\\tdepth: true\\n\\t\\t\\t\\t}));\\n\\t\\t\\t} else {\\n\\t\\t\\t\\ttargets.push(new RenderTarget({\\n\\t\\t\\t\\t\\tdepthBuffer: cubemap,\\n\\t\\t\\t\\t\\tface: i\\n\\t\\t\\t\\t}));\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn new ShadowMap(cubemap, targets);\\n\\t}\\n}\\n\\nconst _tempArray = [];\\nconst _tempArray2 = [];\\nconst _viewport$1 = new Vec4();\\nconst _scissor = new Vec4();\\nclass Slot {\\n\\tconstructor(rect) {\\n\\t\\tthis.size = Math.floor(rect.w * 1024);\\n\\t\\tthis.used = false;\\n\\t\\tthis.lightId = -1;\\n\\t\\tthis.rect = rect;\\n\\t}\\n}\\nclass LightTextureAtlas {\\n\\tconstructor(device) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.version = 1;\\n\\t\\tthis.shadowAtlasResolution = 2048;\\n\\t\\tthis.shadowAtlas = null;\\n\\t\\tthis.shadowEdgePixels = 3;\\n\\t\\tthis.cookieAtlasResolution = 4;\\n\\t\\tthis.cookieAtlas = Texture.createDataTexture2D(this.device, \\\"CookieAtlas\\\", this.cookieAtlasResolution, this.cookieAtlasResolution, PIXELFORMAT_SRGBA8);\\n\\t\\tthis.cookieRenderTarget = new RenderTarget({\\n\\t\\t\\tcolorBuffer: this.cookieAtlas,\\n\\t\\t\\tdepth: false,\\n\\t\\t\\tflipY: true\\n\\t\\t});\\n\\t\\tthis.slots = [];\\n\\t\\tthis.atlasSplit = [];\\n\\t\\tthis.cubeSlotsOffsets = [\\n\\t\\t\\tnew Vec2(0, 0),\\n\\t\\t\\tnew Vec2(0, 1),\\n\\t\\t\\tnew Vec2(1, 0),\\n\\t\\t\\tnew Vec2(1, 1),\\n\\t\\t\\tnew Vec2(2, 0),\\n\\t\\t\\tnew Vec2(2, 1)\\n\\t\\t];\\n\\t\\tthis.scissorVec = new Vec4();\\n\\t\\tthis.allocateShadowAtlas(1);\\n\\t\\tthis.allocateCookieAtlas(1);\\n\\t\\tthis.allocateUniforms();\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.destroyShadowAtlas();\\n\\t\\tthis.destroyCookieAtlas();\\n\\t}\\n\\tdestroyShadowAtlas() {\\n\\t\\tthis.shadowAtlas?.destroy();\\n\\t\\tthis.shadowAtlas = null;\\n\\t}\\n\\tdestroyCookieAtlas() {\\n\\t\\tthis.cookieAtlas?.destroy();\\n\\t\\tthis.cookieAtlas = null;\\n\\t\\tthis.cookieRenderTarget?.destroy();\\n\\t\\tthis.cookieRenderTarget = null;\\n\\t}\\n\\tallocateShadowAtlas(resolution, shadowType = SHADOW_PCF3_32F) {\\n\\t\\tconst existingFormat = this.shadowAtlas?.texture.format;\\n\\t\\tconst requiredFormat = shadowTypeInfo.get(shadowType).format;\\n\\t\\tif (!this.shadowAtlas || this.shadowAtlas.texture.width !== resolution || existingFormat !== requiredFormat) {\\n\\t\\t\\tthis.version++;\\n\\t\\t\\tthis.destroyShadowAtlas();\\n\\t\\t\\tthis.shadowAtlas = ShadowMap.createAtlas(this.device, resolution, shadowType);\\n\\t\\t\\tthis.shadowAtlas.cached = true;\\n\\t\\t\\tconst scissorOffset = 4 / this.shadowAtlasResolution;\\n\\t\\t\\tthis.scissorVec.set(scissorOffset, scissorOffset, -2 * scissorOffset, -2 * scissorOffset);\\n\\t\\t}\\n\\t}\\n\\tallocateCookieAtlas(resolution) {\\n\\t\\tif (this.cookieAtlas.width !== resolution) {\\n\\t\\t\\tthis.cookieRenderTarget.resize(resolution, resolution);\\n\\t\\t\\tthis.version++;\\n\\t\\t}\\n\\t}\\n\\tallocateUniforms() {\\n\\t\\tthis._shadowAtlasTextureId = this.device.scope.resolve(\\\"shadowAtlasTexture\\\");\\n\\t\\tthis._shadowAtlasParamsId = this.device.scope.resolve(\\\"shadowAtlasParams\\\");\\n\\t\\tthis._shadowAtlasParams = new Float32Array(2);\\n\\t\\tthis._cookieAtlasTextureId = this.device.scope.resolve(\\\"cookieAtlasTexture\\\");\\n\\t}\\n\\tupdateUniforms() {\\n\\t\\tconst rt = this.shadowAtlas.renderTargets[0];\\n\\t\\tconst shadowBuffer = rt.depthBuffer;\\n\\t\\tthis._shadowAtlasTextureId.setValue(shadowBuffer);\\n\\t\\tthis._shadowAtlasParams[0] = this.shadowAtlasResolution;\\n\\t\\tthis._shadowAtlasParams[1] = this.shadowEdgePixels;\\n\\t\\tthis._shadowAtlasParamsId.setValue(this._shadowAtlasParams);\\n\\t\\tthis._cookieAtlasTextureId.setValue(this.cookieAtlas);\\n\\t}\\n\\tsubdivide(numLights, lightingParams) {\\n\\t\\tlet atlasSplit = lightingParams.atlasSplit;\\n\\t\\tif (!atlasSplit) {\\n\\t\\t\\tconst gridSize = Math.ceil(Math.sqrt(numLights));\\n\\t\\t\\tatlasSplit = _tempArray2;\\n\\t\\t\\tatlasSplit[0] = gridSize;\\n\\t\\t\\tatlasSplit.length = 1;\\n\\t\\t}\\n\\t\\tconst arraysEqual = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]);\\n\\t\\tif (!arraysEqual(atlasSplit, this.atlasSplit)) {\\n\\t\\t\\tthis.version++;\\n\\t\\t\\tthis.slots.length = 0;\\n\\t\\t\\tthis.atlasSplit.length = 0;\\n\\t\\t\\tthis.atlasSplit.push(...atlasSplit);\\n\\t\\t\\tconst splitCount = this.atlasSplit[0];\\n\\t\\t\\tif (splitCount > 1) {\\n\\t\\t\\t\\tconst invSize = 1 / splitCount;\\n\\t\\t\\t\\tfor (let i = 0; i < splitCount; i++) {\\n\\t\\t\\t\\t\\tfor (let j = 0; j < splitCount; j++) {\\n\\t\\t\\t\\t\\t\\tconst rect = new Vec4(i * invSize, j * invSize, invSize, invSize);\\n\\t\\t\\t\\t\\t\\tconst nextLevelSplit = this.atlasSplit[1 + i * splitCount + j];\\n\\t\\t\\t\\t\\t\\tif (nextLevelSplit > 1) {\\n\\t\\t\\t\\t\\t\\t\\tfor (let x = 0; x < nextLevelSplit; x++) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor (let y = 0; y < nextLevelSplit; y++) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tconst invSizeNext = invSize / nextLevelSplit;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tconst rectNext = new Vec4(rect.x + x * invSizeNext, rect.y + y * invSizeNext, invSizeNext, invSizeNext);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.slots.push(new Slot(rectNext));\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tthis.slots.push(new Slot(rect));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.slots.push(new Slot(new Vec4(0, 0, 1, 1)));\\n\\t\\t\\t}\\n\\t\\t\\tthis.slots.sort((a, b) => {\\n\\t\\t\\t\\treturn b.size - a.size;\\n\\t\\t\\t});\\n\\t\\t}\\n\\t}\\n\\tcollectLights(localLights, lightingParams) {\\n\\t\\tconst cookiesEnabled = lightingParams.cookiesEnabled;\\n\\t\\tconst shadowsEnabled = lightingParams.shadowsEnabled;\\n\\t\\tlet needsShadowAtlas = false;\\n\\t\\tlet needsCookieAtlas = false;\\n\\t\\tconst lights = _tempArray;\\n\\t\\tlights.length = 0;\\n\\t\\tconst processLights = (list) => {\\n\\t\\t\\tfor (let i = 0; i < list.length; i++) {\\n\\t\\t\\t\\tconst light = list[i];\\n\\t\\t\\t\\tif (light.visibleThisFrame) {\\n\\t\\t\\t\\t\\tconst lightShadow = shadowsEnabled && light.castShadows;\\n\\t\\t\\t\\t\\tconst lightCookie = cookiesEnabled && !!light.cookie;\\n\\t\\t\\t\\t\\tneedsShadowAtlas || (needsShadowAtlas = lightShadow);\\n\\t\\t\\t\\t\\tneedsCookieAtlas || (needsCookieAtlas = lightCookie);\\n\\t\\t\\t\\t\\tif (lightShadow || lightCookie) {\\n\\t\\t\\t\\t\\t\\tlights.push(light);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tif (cookiesEnabled || shadowsEnabled) {\\n\\t\\t\\tprocessLights(localLights);\\n\\t\\t}\\n\\t\\tlights.sort((a, b) => {\\n\\t\\t\\treturn b.maxScreenSize - a.maxScreenSize;\\n\\t\\t});\\n\\t\\tif (needsShadowAtlas) {\\n\\t\\t\\tthis.allocateShadowAtlas(this.shadowAtlasResolution, lightingParams.shadowType);\\n\\t\\t}\\n\\t\\tif (needsCookieAtlas) {\\n\\t\\t\\tthis.allocateCookieAtlas(this.cookieAtlasResolution);\\n\\t\\t}\\n\\t\\tif (needsShadowAtlas || needsCookieAtlas) {\\n\\t\\t\\tthis.subdivide(lights.length, lightingParams);\\n\\t\\t}\\n\\t\\treturn lights;\\n\\t}\\n\\t// configure light to use assigned slot\\n\\tsetupSlot(light, rect) {\\n\\t\\tlight.atlasViewport.copy(rect);\\n\\t\\tconst faceCount = light.numShadowFaces;\\n\\t\\tfor (let face = 0; face < faceCount; face++) {\\n\\t\\t\\tif (light.castShadows || light._cookie) {\\n\\t\\t\\t\\t_viewport$1.copy(rect);\\n\\t\\t\\t\\t_scissor.copy(rect);\\n\\t\\t\\t\\tif (light._type === LIGHTTYPE_SPOT) {\\n\\t\\t\\t\\t\\t_viewport$1.add(this.scissorVec);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (light._type === LIGHTTYPE_OMNI) {\\n\\t\\t\\t\\t\\tconst smallSize = _viewport$1.z / 3;\\n\\t\\t\\t\\t\\tconst offset = this.cubeSlotsOffsets[face];\\n\\t\\t\\t\\t\\t_viewport$1.x += smallSize * offset.x;\\n\\t\\t\\t\\t\\t_viewport$1.y += smallSize * offset.y;\\n\\t\\t\\t\\t\\t_viewport$1.z = smallSize;\\n\\t\\t\\t\\t\\t_viewport$1.w = smallSize;\\n\\t\\t\\t\\t\\t_scissor.copy(_viewport$1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (light.castShadows) {\\n\\t\\t\\t\\t\\tconst lightRenderData = light.getRenderData(null, face);\\n\\t\\t\\t\\t\\tlightRenderData.shadowViewport.copy(_viewport$1);\\n\\t\\t\\t\\t\\tlightRenderData.shadowScissor.copy(_scissor);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t// assign a slot to the light\\n\\tassignSlot(light, slotIndex, slotReassigned) {\\n\\t\\tlight.atlasViewportAllocated = true;\\n\\t\\tconst slot = this.slots[slotIndex];\\n\\t\\tslot.lightId = light.id;\\n\\t\\tslot.used = true;\\n\\t\\tif (slotReassigned) {\\n\\t\\t\\tlight.atlasSlotUpdated = true;\\n\\t\\t\\tlight.atlasVersion = this.version;\\n\\t\\t\\tlight.atlasSlotIndex = slotIndex;\\n\\t\\t}\\n\\t}\\n\\t// update texture atlas for a list of lights\\n\\tupdate(localLights, lightingParams) {\\n\\t\\tthis.shadowAtlasResolution = lightingParams.shadowAtlasResolution;\\n\\t\\tthis.cookieAtlasResolution = lightingParams.cookieAtlasResolution;\\n\\t\\tconst lights = this.collectLights(localLights, lightingParams);\\n\\t\\tif (lights.length > 0) {\\n\\t\\t\\tconst slots = this.slots;\\n\\t\\t\\tfor (let i = 0; i < slots.length; i++) {\\n\\t\\t\\t\\tslots[i].used = false;\\n\\t\\t\\t}\\n\\t\\t\\tconst assignCount = Math.min(lights.length, slots.length);\\n\\t\\t\\tfor (let i = 0; i < assignCount; i++) {\\n\\t\\t\\t\\tconst light = lights[i];\\n\\t\\t\\t\\tif (light.castShadows) {\\n\\t\\t\\t\\t\\tlight._shadowMap = this.shadowAtlas;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst previousSlot = slots[light.atlasSlotIndex];\\n\\t\\t\\t\\tif (light.atlasVersion === this.version && light.id === previousSlot?.lightId) {\\n\\t\\t\\t\\t\\tconst previousSlot2 = slots[light.atlasSlotIndex];\\n\\t\\t\\t\\t\\tif (previousSlot2.size === slots[i].size && !previousSlot2.used) {\\n\\t\\t\\t\\t\\t\\tthis.assignSlot(light, light.atlasSlotIndex, false);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tlet usedCount = 0;\\n\\t\\t\\tfor (let i = 0; i < assignCount; i++) {\\n\\t\\t\\t\\twhile (usedCount < slots.length && slots[usedCount].used) {\\n\\t\\t\\t\\t\\tusedCount++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst light = lights[i];\\n\\t\\t\\t\\tif (!light.atlasViewportAllocated) {\\n\\t\\t\\t\\t\\tthis.assignSlot(light, usedCount, true);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst slot = slots[light.atlasSlotIndex];\\n\\t\\t\\t\\tthis.setupSlot(light, slot.rect);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.updateUniforms();\\n\\t}\\n}\\n\\nconst blendModes = [];\\nblendModes[BLEND_SUBTRACTIVE] = { src: BLENDMODE_ONE, dst: BLENDMODE_ONE, op: BLENDEQUATION_REVERSE_SUBTRACT };\\nblendModes[BLEND_NONE] = { src: BLENDMODE_ONE, dst: BLENDMODE_ZERO, op: BLENDEQUATION_ADD };\\nblendModes[BLEND_NORMAL] = { src: BLENDMODE_SRC_ALPHA, dst: BLENDMODE_ONE_MINUS_SRC_ALPHA, op: BLENDEQUATION_ADD, alphaSrc: BLENDMODE_ONE };\\nblendModes[BLEND_PREMULTIPLIED] = { src: BLENDMODE_ONE, dst: BLENDMODE_ONE_MINUS_SRC_ALPHA, op: BLENDEQUATION_ADD };\\nblendModes[BLEND_ADDITIVE] = { src: BLENDMODE_ONE, dst: BLENDMODE_ONE, op: BLENDEQUATION_ADD };\\nblendModes[BLEND_ADDITIVEALPHA] = { src: BLENDMODE_SRC_ALPHA, dst: BLENDMODE_ONE, op: BLENDEQUATION_ADD };\\nblendModes[BLEND_MULTIPLICATIVE2X] = { src: BLENDMODE_DST_COLOR, dst: BLENDMODE_SRC_COLOR, op: BLENDEQUATION_ADD };\\nblendModes[BLEND_SCREEN] = { src: BLENDMODE_ONE_MINUS_DST_COLOR, dst: BLENDMODE_ONE, op: BLENDEQUATION_ADD };\\nblendModes[BLEND_MULTIPLICATIVE] = { src: BLENDMODE_DST_COLOR, dst: BLENDMODE_ZERO, op: BLENDEQUATION_ADD };\\nblendModes[BLEND_MIN] = { src: BLENDMODE_ONE, dst: BLENDMODE_ONE, op: BLENDEQUATION_MIN };\\nblendModes[BLEND_MAX] = { src: BLENDMODE_ONE, dst: BLENDMODE_ONE, op: BLENDEQUATION_MAX };\\nlet id$3 = 0;\\nclass Material {\\n\\tmeshInstances = /* @__PURE__ */ new Set();\\n\\tname = \\\"Untitled\\\";\\n\\tuserId = \\\"\\\";\\n\\tid = id$3++;\\n\\tvariants = /* @__PURE__ */ new Map();\\n\\tdefines = /* @__PURE__ */ new Map();\\n\\t_definesDirty = false;\\n\\tparameters = {};\\n\\talphaTest = 0;\\n\\talphaToCoverage = false;\\n\\t_blendState = new BlendState();\\n\\t_depthState = new DepthState();\\n\\tcull = CULLFACE_BACK;\\n\\tfrontFace = FRONTFACE_CCW;\\n\\tstencilFront = null;\\n\\tstencilBack = null;\\n\\t_shaderChunks = null;\\n\\t// this is deprecated, keeping for backwards compatibility\\n\\t_oldChunks = {};\\n\\t_dirtyShader = true;\\n\\tconstructor() {\\n\\t}\\n\\tget hasShaderChunks() {\\n\\t\\treturn this._shaderChunks != null;\\n\\t}\\n\\tget shaderChunks() {\\n\\t\\tif (!this._shaderChunks) {\\n\\t\\t\\tthis._shaderChunks = new ShaderChunks();\\n\\t\\t}\\n\\t\\treturn this._shaderChunks;\\n\\t}\\n\\tgetShaderChunks(shaderLanguage = SHADERLANGUAGE_GLSL) {\\n\\t\\tconst chunks = this.shaderChunks;\\n\\t\\treturn shaderLanguage === SHADERLANGUAGE_GLSL ? chunks.glsl : chunks.wgsl;\\n\\t}\\n\\tset shaderChunksVersion(value) {\\n\\t\\tthis.shaderChunks.version = value;\\n\\t}\\n\\tget shaderChunksVersion() {\\n\\t\\treturn this.shaderChunks.version;\\n\\t}\\n\\tset chunks(value) {\\n\\t\\tthis._oldChunks = value;\\n\\t}\\n\\tget chunks() {\\n\\t\\tObject.assign(this._oldChunks, Object.fromEntries(this.shaderChunks.glsl));\\n\\t\\treturn this._oldChunks;\\n\\t}\\n\\tset depthBias(value) {\\n\\t\\tthis._depthState.depthBias = value;\\n\\t}\\n\\tget depthBias() {\\n\\t\\treturn this._depthState.depthBias;\\n\\t}\\n\\tset slopeDepthBias(value) {\\n\\t\\tthis._depthState.depthBiasSlope = value;\\n\\t}\\n\\tget slopeDepthBias() {\\n\\t\\treturn this._depthState.depthBiasSlope;\\n\\t}\\n\\t_shaderVersion = 0;\\n\\t_scene = null;\\n\\tdirty = true;\\n\\tset redWrite(value) {\\n\\t\\tthis._blendState.redWrite = value;\\n\\t}\\n\\tget redWrite() {\\n\\t\\treturn this._blendState.redWrite;\\n\\t}\\n\\tset greenWrite(value) {\\n\\t\\tthis._blendState.greenWrite = value;\\n\\t}\\n\\tget greenWrite() {\\n\\t\\treturn this._blendState.greenWrite;\\n\\t}\\n\\tset blueWrite(value) {\\n\\t\\tthis._blendState.blueWrite = value;\\n\\t}\\n\\tget blueWrite() {\\n\\t\\treturn this._blendState.blueWrite;\\n\\t}\\n\\tset alphaWrite(value) {\\n\\t\\tthis._blendState.alphaWrite = value;\\n\\t}\\n\\tget alphaWrite() {\\n\\t\\treturn this._blendState.alphaWrite;\\n\\t}\\n\\t// returns boolean depending on material being transparent\\n\\tget transparent() {\\n\\t\\treturn this._blendState.blend;\\n\\t}\\n\\t_updateTransparency() {\\n\\t\\tfor (const meshInstance of this.meshInstances) {\\n\\t\\t\\tmeshInstance.transparent = this.transparent;\\n\\t\\t}\\n\\t}\\n\\tset blendState(value) {\\n\\t\\tthis._blendState.copy(value);\\n\\t\\tthis._updateTransparency();\\n\\t}\\n\\tget blendState() {\\n\\t\\treturn this._blendState;\\n\\t}\\n\\tset blendType(type) {\\n\\t\\tconst blendMode = blendModes[type];\\n\\t\\tthis._blendState.setColorBlend(blendMode.op, blendMode.src, blendMode.dst);\\n\\t\\tthis._blendState.setAlphaBlend(blendMode.alphaOp ?? blendMode.op, blendMode.alphaSrc ?? blendMode.src, blendMode.alphaDst ?? blendMode.dst);\\n\\t\\tconst blend = type !== BLEND_NONE;\\n\\t\\tif (this._blendState.blend !== blend) {\\n\\t\\t\\tthis._blendState.blend = blend;\\n\\t\\t\\tthis._updateTransparency();\\n\\t\\t}\\n\\t\\tthis._updateMeshInstanceKeys();\\n\\t}\\n\\tget blendType() {\\n\\t\\tif (!this.transparent) {\\n\\t\\t\\treturn BLEND_NONE;\\n\\t\\t}\\n\\t\\tconst { colorOp, colorSrcFactor, colorDstFactor, alphaOp, alphaSrcFactor, alphaDstFactor } = this._blendState;\\n\\t\\tfor (let i = 0; i < blendModes.length; i++) {\\n\\t\\t\\tconst blendMode = blendModes[i];\\n\\t\\t\\tif (blendMode.src === colorSrcFactor && blendMode.dst === colorDstFactor && blendMode.op === colorOp && blendMode.src === alphaSrcFactor && blendMode.dst === alphaDstFactor && blendMode.op === alphaOp) {\\n\\t\\t\\t\\treturn i;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn BLEND_NORMAL;\\n\\t}\\n\\tset depthState(value) {\\n\\t\\tthis._depthState.copy(value);\\n\\t}\\n\\tget depthState() {\\n\\t\\treturn this._depthState;\\n\\t}\\n\\tset depthTest(value) {\\n\\t\\tthis._depthState.test = value;\\n\\t}\\n\\tget depthTest() {\\n\\t\\treturn this._depthState.test;\\n\\t}\\n\\tset depthFunc(value) {\\n\\t\\tthis._depthState.func = value;\\n\\t}\\n\\tget depthFunc() {\\n\\t\\treturn this._depthState.func;\\n\\t}\\n\\tset depthWrite(value) {\\n\\t\\tthis._depthState.write = value;\\n\\t}\\n\\tget depthWrite() {\\n\\t\\treturn this._depthState.write;\\n\\t}\\n\\tcopy(source) {\\n\\t\\tthis.name = source.name;\\n\\t\\tthis.alphaTest = source.alphaTest;\\n\\t\\tthis.alphaToCoverage = source.alphaToCoverage;\\n\\t\\tthis._blendState.copy(source._blendState);\\n\\t\\tthis._depthState.copy(source._depthState);\\n\\t\\tthis.cull = source.cull;\\n\\t\\tthis.frontFace = source.frontFace;\\n\\t\\tthis.stencilFront = source.stencilFront?.clone();\\n\\t\\tif (source.stencilBack) {\\n\\t\\t\\tthis.stencilBack = source.stencilFront === source.stencilBack ? this.stencilFront : source.stencilBack.clone();\\n\\t\\t}\\n\\t\\tthis.clearParameters();\\n\\t\\tfor (const name in source.parameters) {\\n\\t\\t\\tif (source.parameters.hasOwnProperty(name)) {\\n\\t\\t\\t\\tthis._setParameterSimple(name, source.parameters[name].data);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.defines.clear();\\n\\t\\tsource.defines.forEach((value, key) => this.defines.set(key, value));\\n\\t\\tthis._shaderChunks = source.hasShaderChunks ? new ShaderChunks() : null;\\n\\t\\tthis._shaderChunks?.copy(source._shaderChunks);\\n\\t\\treturn this;\\n\\t}\\n\\tclone() {\\n\\t\\tconst clone = new this.constructor();\\n\\t\\treturn clone.copy(this);\\n\\t}\\n\\t_updateMeshInstanceKeys() {\\n\\t\\tfor (const meshInstance of this.meshInstances) {\\n\\t\\t\\tmeshInstance.updateKey();\\n\\t\\t}\\n\\t}\\n\\tupdateUniforms(device, scene) {\\n\\t\\tif (this._dirtyShader) {\\n\\t\\t\\tthis.clearVariants();\\n\\t\\t\\tthis._dirtyShader = false;\\n\\t\\t}\\n\\t}\\n\\tgetShaderVariant(params) {\\n\\t}\\n\\tupdate() {\\n\\t\\tif (Object.keys(this._oldChunks).length > 0) {\\n\\t\\t\\tfor (const [key, value] of Object.entries(this._oldChunks)) {\\n\\t\\t\\t\\tthis.shaderChunks.glsl.set(key, value);\\n\\t\\t\\t\\tdelete this._oldChunks[key];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this._definesDirty || this._shaderChunks?.isDirty()) {\\n\\t\\t\\tthis._definesDirty = false;\\n\\t\\t\\tthis._shaderChunks?.resetDirty();\\n\\t\\t\\tthis.clearVariants();\\n\\t\\t}\\n\\t\\tthis.dirty = true;\\n\\t}\\n\\t// Parameter management\\n\\tclearParameters() {\\n\\t\\tthis.parameters = {};\\n\\t}\\n\\tgetParameters() {\\n\\t\\treturn this.parameters;\\n\\t}\\n\\tclearVariants() {\\n\\t\\tthis.variants.clear();\\n\\t\\tfor (const meshInstance of this.meshInstances) {\\n\\t\\t\\tmeshInstance.clearShaders();\\n\\t\\t}\\n\\t}\\n\\tgetParameter(name) {\\n\\t\\treturn this.parameters[name];\\n\\t}\\n\\t_setParameterSimple(name, data) {\\n\\t\\tconst param = this.parameters[name];\\n\\t\\tif (param) {\\n\\t\\t\\tparam.data = data;\\n\\t\\t} else {\\n\\t\\t\\tthis.parameters[name] = {\\n\\t\\t\\t\\tscopeId: null,\\n\\t\\t\\t\\tdata\\n\\t\\t\\t};\\n\\t\\t}\\n\\t}\\n\\tsetParameter(name, data) {\\n\\t\\tif (data === void 0 && typeof name === \\\"object\\\") {\\n\\t\\t\\tconst uniformObject = name;\\n\\t\\t\\tif (uniformObject.length) {\\n\\t\\t\\t\\tfor (let i = 0; i < uniformObject.length; i++) {\\n\\t\\t\\t\\t\\tthis.setParameter(uniformObject[i]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tname = uniformObject.name;\\n\\t\\t\\tdata = uniformObject.value;\\n\\t\\t}\\n\\t\\tthis._setParameterSimple(name, data);\\n\\t}\\n\\tdeleteParameter(name) {\\n\\t\\tif (this.parameters[name]) {\\n\\t\\t\\tdelete this.parameters[name];\\n\\t\\t}\\n\\t}\\n\\t// used to apply parameters from this material into scope of uniforms, called internally by forward-renderer\\n\\t// optional list of parameter names to be set can be specified, otherwise all parameters are set\\n\\tsetParameters(device, names) {\\n\\t\\tconst parameters = this.parameters;\\n\\t\\tif (names === void 0) names = parameters;\\n\\t\\tfor (const paramName in names) {\\n\\t\\t\\tconst parameter = parameters[paramName];\\n\\t\\t\\tif (parameter) {\\n\\t\\t\\t\\tif (!parameter.scopeId) {\\n\\t\\t\\t\\t\\tparameter.scopeId = device.scope.resolve(paramName);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tparameter.scopeId.setValue(parameter.data);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tsetDefine(name, value) {\\n\\t\\tlet modified = false;\\n\\t\\tconst { defines } = this;\\n\\t\\tif (value !== void 0 && value !== false) {\\n\\t\\t\\tmodified = !defines.has(name) || defines.get(name) !== value;\\n\\t\\t\\tdefines.set(name, value);\\n\\t\\t} else {\\n\\t\\t\\tmodified = defines.has(name);\\n\\t\\t\\tdefines.delete(name);\\n\\t\\t}\\n\\t\\tthis._definesDirty || (this._definesDirty = modified);\\n\\t}\\n\\tgetDefine(name) {\\n\\t\\treturn this.defines.has(name);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.variants.clear();\\n\\t\\tfor (const meshInstance of this.meshInstances) {\\n\\t\\t\\tmeshInstance.clearShaders();\\n\\t\\t\\tmeshInstance._material = null;\\n\\t\\t\\tif (meshInstance.mesh) {\\n\\t\\t\\t\\tconst defaultMaterial = getDefaultMaterial(meshInstance.mesh.device);\\n\\t\\t\\t\\tif (this !== defaultMaterial) {\\n\\t\\t\\t\\t\\tmeshInstance.material = defaultMaterial;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.meshInstances.clear();\\n\\t}\\n\\taddMeshInstanceRef(meshInstance) {\\n\\t\\tthis.meshInstances.add(meshInstance);\\n\\t}\\n\\tremoveMeshInstanceRef(meshInstance) {\\n\\t\\tthis.meshInstances.delete(meshInstance);\\n\\t}\\n}\\n\\nclass ShadowMapCache {\\n\\tconstructor() {\\n\\t\\tthis.cache = /* @__PURE__ */ new Map();\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.clear();\\n\\t\\tthis.cache = null;\\n\\t}\\n\\t// remove all shadowmaps from the cache\\n\\tclear() {\\n\\t\\tthis.cache.forEach((shadowMaps) => {\\n\\t\\t\\tshadowMaps.forEach((shadowMap) => {\\n\\t\\t\\t\\tshadowMap.destroy();\\n\\t\\t\\t});\\n\\t\\t});\\n\\t\\tthis.cache.clear();\\n\\t}\\n\\t// generates a string key for the shadow map required by the light\\n\\tgetKey(light) {\\n\\t\\tconst isCubeMap = light._type === LIGHTTYPE_OMNI;\\n\\t\\tconst shadowType = light._shadowType;\\n\\t\\tconst resolution = light._shadowResolution;\\n\\t\\treturn `${isCubeMap}-${shadowType}-${resolution}`;\\n\\t}\\n\\t// returns shadow map from the cache, or creates a new one if none available\\n\\tget(device, light) {\\n\\t\\tconst key = this.getKey(light);\\n\\t\\tconst shadowMaps = this.cache.get(key);\\n\\t\\tif (shadowMaps && shadowMaps.length) {\\n\\t\\t\\treturn shadowMaps.pop();\\n\\t\\t}\\n\\t\\tconst shadowMap = ShadowMap.create(device, light);\\n\\t\\tshadowMap.cached = true;\\n\\t\\treturn shadowMap;\\n\\t}\\n\\t// returns shadow map for the light back to the cache\\n\\tadd(light, shadowMap) {\\n\\t\\tconst key = this.getKey(light);\\n\\t\\tconst shadowMaps = this.cache.get(key);\\n\\t\\tif (shadowMaps) {\\n\\t\\t\\tshadowMaps.push(shadowMap);\\n\\t\\t} else {\\n\\t\\t\\tthis.cache.set(key, [shadowMap]);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass RenderPassShadowLocalNonClustered extends RenderPass {\\n\\tconstructor(device, shadowRenderer, light, face, applyVsm) {\\n\\t\\tsuper(device);\\n\\t\\tthis.requiresCubemaps = false;\\n\\t\\tthis.shadowRenderer = shadowRenderer;\\n\\t\\tthis.light = light;\\n\\t\\tthis.face = face;\\n\\t\\tthis.applyVsm = applyVsm;\\n\\t\\tthis.shadowCamera = shadowRenderer.prepareFace(light, null, face);\\n\\t\\tshadowRenderer.setupRenderPass(this, this.shadowCamera, true);\\n\\t}\\n\\texecute() {\\n\\t\\tthis.shadowRenderer.renderFace(this.light, null, this.face, false);\\n\\t}\\n\\tafter() {\\n\\t\\tif (this.applyVsm) {\\n\\t\\t\\tthis.shadowRenderer.renderVsm(this.light, this.shadowCamera);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass ShadowRendererLocal {\\n\\t// temporary list to collect lights to render shadows for\\n\\tshadowLights = [];\\n\\trenderer;\\n\\tshadowRenderer;\\n\\tdevice;\\n\\tconstructor(renderer, shadowRenderer) {\\n\\t\\tthis.renderer = renderer;\\n\\t\\tthis.shadowRenderer = shadowRenderer;\\n\\t\\tthis.device = renderer.device;\\n\\t}\\n\\t// cull local shadow map\\n\\tcull(light, comp, casters = null) {\\n\\t\\tconst isClustered = this.renderer.scene.clusteredLightingEnabled;\\n\\t\\tlight.visibleThisFrame = true;\\n\\t\\tif (!isClustered) {\\n\\t\\t\\tif (!light._shadowMap) {\\n\\t\\t\\t\\tlight._shadowMap = ShadowMap.create(this.device, light);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst type = light._type;\\n\\t\\tconst faceCount = type === LIGHTTYPE_SPOT ? 1 : 6;\\n\\t\\tfor (let face = 0; face < faceCount; face++) {\\n\\t\\t\\tconst lightRenderData = light.getRenderData(null, face);\\n\\t\\t\\tconst shadowCam = lightRenderData.shadowCamera;\\n\\t\\t\\tshadowCam.nearClip = light.attenuationEnd / 1e3;\\n\\t\\t\\tshadowCam.farClip = light.attenuationEnd;\\n\\t\\t\\tconst shadowCamNode = shadowCam._node;\\n\\t\\t\\tconst lightNode = light._node;\\n\\t\\t\\tshadowCamNode.setPosition(lightNode.getPosition());\\n\\t\\t\\tif (type === LIGHTTYPE_SPOT) {\\n\\t\\t\\t\\tshadowCam.fov = light._outerConeAngle * 2;\\n\\t\\t\\t\\tshadowCamNode.setRotation(lightNode.getRotation());\\n\\t\\t\\t\\tshadowCamNode.rotateLocal(-90, 0, 0);\\n\\t\\t\\t} else if (type === LIGHTTYPE_OMNI) {\\n\\t\\t\\t\\tif (isClustered) {\\n\\t\\t\\t\\t\\tconst tileSize = this.shadowRenderer.lightTextureAtlas.shadowAtlasResolution * light.atlasViewport.z / 3;\\n\\t\\t\\t\\t\\tconst texelSize = 2 / tileSize;\\n\\t\\t\\t\\t\\tconst filterSize = texelSize * this.shadowRenderer.lightTextureAtlas.shadowEdgePixels;\\n\\t\\t\\t\\t\\tshadowCam.fov = Math.atan(1 + filterSize) * math.RAD_TO_DEG * 2;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tshadowCam.fov = 90;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis.renderer.updateCameraFrustum(shadowCam);\\n\\t\\t\\tthis.shadowRenderer.cullShadowCasters(comp, light, lightRenderData.visibleCasters, shadowCam, casters);\\n\\t\\t}\\n\\t}\\n\\tprepareLights(shadowLights, lights) {\\n\\t\\tlet shadowCamera;\\n\\t\\tfor (let i = 0; i < lights.length; i++) {\\n\\t\\t\\tconst light = lights[i];\\n\\t\\t\\tif (this.shadowRenderer.needsShadowRendering(light) && light.atlasViewportAllocated) {\\n\\t\\t\\t\\tshadowLights.push(light);\\n\\t\\t\\t\\tfor (let face = 0; face < light.numShadowFaces; face++) {\\n\\t\\t\\t\\t\\tshadowCamera = this.shadowRenderer.prepareFace(light, null, face);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn shadowCamera;\\n\\t}\\n\\tbuildNonClusteredRenderPasses(frameGraph, localLights) {\\n\\t\\tfor (let i = 0; i < localLights.length; i++) {\\n\\t\\t\\tconst light = localLights[i];\\n\\t\\t\\tif (this.shadowRenderer.needsShadowRendering(light)) {\\n\\t\\t\\t\\tconst applyVsm = light._type === LIGHTTYPE_SPOT;\\n\\t\\t\\t\\tconst faceCount = light.numShadowFaces;\\n\\t\\t\\t\\tfor (let face = 0; face < faceCount; face++) {\\n\\t\\t\\t\\t\\tconst renderPass = new RenderPassShadowLocalNonClustered(this.device, this.shadowRenderer, light, face, applyVsm);\\n\\t\\t\\t\\t\\tframeGraph.addRenderPass(renderPass);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\n\\nclass RenderPassShadowDirectional extends RenderPass {\\n\\tconstructor(device, shadowRenderer, light, camera, allCascadesRendering) {\\n\\t\\tsuper(device);\\n\\t\\tthis.shadowRenderer = shadowRenderer;\\n\\t\\tthis.light = light;\\n\\t\\tthis.camera = camera;\\n\\t\\tthis.allCascadesRendering = allCascadesRendering;\\n\\t}\\n\\texecute() {\\n\\t\\tconst { light, camera, shadowRenderer, allCascadesRendering } = this;\\n\\t\\tconst faceCount = light.numShadowFaces;\\n\\t\\tconst shadowUpdateOverrides = light.shadowUpdateOverrides;\\n\\t\\tfor (let face = 0; face < faceCount; face++) {\\n\\t\\t\\tif (shadowUpdateOverrides?.[face] !== SHADOWUPDATE_NONE) {\\n\\t\\t\\t\\tshadowRenderer.renderFace(light, camera, face, !allCascadesRendering);\\n\\t\\t\\t}\\n\\t\\t\\tif (shadowUpdateOverrides?.[face] === SHADOWUPDATE_THISFRAME) {\\n\\t\\t\\t\\tshadowUpdateOverrides[face] = SHADOWUPDATE_NONE;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tafter() {\\n\\t\\tthis.shadowRenderer.renderVsm(this.light, this.camera);\\n\\t}\\n}\\n\\nconst visibleSceneAabb = new BoundingBox();\\nconst center = new Vec3();\\nconst shadowCamView$1 = new Mat4();\\nconst aabbPoints = [\\n\\tnew Vec3(),\\n\\tnew Vec3(),\\n\\tnew Vec3(),\\n\\tnew Vec3(),\\n\\tnew Vec3(),\\n\\tnew Vec3(),\\n\\tnew Vec3(),\\n\\tnew Vec3()\\n];\\nconst _depthRange = { min: 0, max: 0 };\\nfunction getDepthRange(cameraViewMatrix, aabbMin, aabbMax) {\\n\\taabbPoints[0].x = aabbPoints[1].x = aabbPoints[2].x = aabbPoints[3].x = aabbMin.x;\\n\\taabbPoints[1].y = aabbPoints[3].y = aabbPoints[7].y = aabbPoints[5].y = aabbMin.y;\\n\\taabbPoints[2].z = aabbPoints[3].z = aabbPoints[6].z = aabbPoints[7].z = aabbMin.z;\\n\\taabbPoints[4].x = aabbPoints[5].x = aabbPoints[6].x = aabbPoints[7].x = aabbMax.x;\\n\\taabbPoints[0].y = aabbPoints[2].y = aabbPoints[4].y = aabbPoints[6].y = aabbMax.y;\\n\\taabbPoints[0].z = aabbPoints[1].z = aabbPoints[4].z = aabbPoints[5].z = aabbMax.z;\\n\\tlet minz = 9999999999;\\n\\tlet maxz = -9999999999;\\n\\tfor (let i = 0; i < 8; ++i) {\\n\\t\\tcameraViewMatrix.transformPoint(aabbPoints[i], aabbPoints[i]);\\n\\t\\tconst z = aabbPoints[i].z;\\n\\t\\tif (z < minz) minz = z;\\n\\t\\tif (z > maxz) maxz = z;\\n\\t}\\n\\t_depthRange.min = minz;\\n\\t_depthRange.max = maxz;\\n\\treturn _depthRange;\\n}\\nclass ShadowRendererDirectional {\\n\\trenderer;\\n\\tshadowRenderer;\\n\\tdevice;\\n\\tconstructor(renderer, shadowRenderer) {\\n\\t\\tthis.renderer = renderer;\\n\\t\\tthis.shadowRenderer = shadowRenderer;\\n\\t\\tthis.device = renderer.device;\\n\\t}\\n\\t// cull directional shadow map\\n\\tcull(light, comp, camera, casters = null) {\\n\\t\\tlight.visibleThisFrame = true;\\n\\t\\tif (!light._shadowMap) {\\n\\t\\t\\tlight._shadowMap = ShadowMap.create(this.device, light);\\n\\t\\t}\\n\\t\\tconst nearDist = camera._nearClip;\\n\\t\\tthis.generateSplitDistances(light, nearDist, Math.min(camera._farClip, light.shadowDistance));\\n\\t\\tconst shadowUpdateOverrides = light.shadowUpdateOverrides;\\n\\t\\tfor (let cascade = 0; cascade < light.numCascades; cascade++) {\\n\\t\\t\\tif (shadowUpdateOverrides?.[cascade] === SHADOWUPDATE_NONE) {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\tconst lightRenderData = light.getRenderData(camera, cascade);\\n\\t\\t\\tconst shadowCam = lightRenderData.shadowCamera;\\n\\t\\t\\tshadowCam.renderTarget = light._shadowMap.renderTargets[0];\\n\\t\\t\\tlightRenderData.shadowViewport.copy(light.cascades[cascade]);\\n\\t\\t\\tlightRenderData.shadowScissor.copy(light.cascades[cascade]);\\n\\t\\t\\tconst shadowCamNode = shadowCam._node;\\n\\t\\t\\tconst lightNode = light._node;\\n\\t\\t\\tshadowCamNode.setPosition(lightNode.getPosition());\\n\\t\\t\\tshadowCamNode.setRotation(lightNode.getRotation());\\n\\t\\t\\tshadowCamNode.rotateLocal(-90, 0, 0);\\n\\t\\t\\tconst frustumNearDist = cascade === 0 ? nearDist : light._shadowCascadeDistances[cascade - 1];\\n\\t\\t\\tconst frustumFarDist = light._shadowCascadeDistances[cascade];\\n\\t\\t\\tconst frustumPoints = camera.getFrustumCorners(frustumNearDist, frustumFarDist);\\n\\t\\t\\tcenter.set(0, 0, 0);\\n\\t\\t\\tconst cameraWorldMat = camera.node.getWorldTransform();\\n\\t\\t\\tfor (let i = 0; i < 8; i++) {\\n\\t\\t\\t\\tcameraWorldMat.transformPoint(frustumPoints[i], frustumPoints[i]);\\n\\t\\t\\t\\tcenter.add(frustumPoints[i]);\\n\\t\\t\\t}\\n\\t\\t\\tcenter.mulScalar(1 / 8);\\n\\t\\t\\tlet radius = 0;\\n\\t\\t\\tfor (let i = 0; i < 8; i++) {\\n\\t\\t\\t\\tconst dist = frustumPoints[i].sub(center).length();\\n\\t\\t\\t\\tif (dist > radius) {\\n\\t\\t\\t\\t\\tradius = dist;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tconst right = shadowCamNode.right;\\n\\t\\t\\tconst up = shadowCamNode.up;\\n\\t\\t\\tconst lightDir = shadowCamNode.forward;\\n\\t\\t\\tconst sizeRatio = 0.25 * light._shadowResolution / radius;\\n\\t\\t\\tconst x = Math.ceil(center.dot(up) * sizeRatio) / sizeRatio;\\n\\t\\t\\tconst y = Math.ceil(center.dot(right) * sizeRatio) / sizeRatio;\\n\\t\\t\\tconst scaledUp = up.mulScalar(x);\\n\\t\\t\\tconst scaledRight = right.mulScalar(y);\\n\\t\\t\\tconst dot = center.dot(lightDir);\\n\\t\\t\\tconst scaledDir = lightDir.mulScalar(dot);\\n\\t\\t\\tcenter.add2(scaledUp, scaledRight).add(scaledDir);\\n\\t\\t\\tshadowCamNode.setPosition(center);\\n\\t\\t\\tshadowCamNode.translateLocal(0, 0, 1e6);\\n\\t\\t\\tshadowCam.nearClip = 0.01;\\n\\t\\t\\tshadowCam.farClip = 2e6;\\n\\t\\t\\tshadowCam.orthoHeight = radius;\\n\\t\\t\\tthis.renderer.updateCameraFrustum(shadowCam);\\n\\t\\t\\tthis.shadowRenderer.cullShadowCasters(comp, light, lightRenderData.visibleCasters, shadowCam, casters);\\n\\t\\t\\tconst cascadeFlag = 1 << cascade;\\n\\t\\t\\tconst visibleCasters = lightRenderData.visibleCasters;\\n\\t\\t\\tconst origNumVisibleCasters = visibleCasters.length;\\n\\t\\t\\tlet numVisibleCasters = 0;\\n\\t\\t\\tfor (let i = 0; i < origNumVisibleCasters; i++) {\\n\\t\\t\\t\\tconst meshInstance = visibleCasters[i];\\n\\t\\t\\t\\tif (meshInstance.shadowCascadeMask & cascadeFlag) {\\n\\t\\t\\t\\t\\tvisibleCasters[numVisibleCasters++] = meshInstance;\\n\\t\\t\\t\\t\\tif (numVisibleCasters === 1) {\\n\\t\\t\\t\\t\\t\\tvisibleSceneAabb.copy(meshInstance.aabb);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tvisibleSceneAabb.add(meshInstance.aabb);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (origNumVisibleCasters !== numVisibleCasters) {\\n\\t\\t\\t\\tvisibleCasters.length = numVisibleCasters;\\n\\t\\t\\t}\\n\\t\\t\\tshadowCamView$1.copy(shadowCamNode.getWorldTransform()).invert();\\n\\t\\t\\tconst depthRange = getDepthRange(shadowCamView$1, visibleSceneAabb.getMin(), visibleSceneAabb.getMax());\\n\\t\\t\\tshadowCamNode.translateLocal(0, 0, depthRange.max + 0.1);\\n\\t\\t\\tshadowCam.farClip = depthRange.max - depthRange.min + 0.2;\\n\\t\\t\\tlightRenderData.projectionCompensation = radius;\\n\\t\\t}\\n\\t}\\n\\t// function to generate frustum split distances\\n\\tgenerateSplitDistances(light, nearDist, farDist) {\\n\\t\\tlight._shadowCascadeDistances.fill(farDist);\\n\\t\\tfor (let i = 1; i < light.numCascades; i++) {\\n\\t\\t\\tconst fraction = i / light.numCascades;\\n\\t\\t\\tconst linearDist = nearDist + (farDist - nearDist) * fraction;\\n\\t\\t\\tconst logDist = nearDist * (farDist / nearDist) ** fraction;\\n\\t\\t\\tconst dist = math.lerp(linearDist, logDist, light.cascadeDistribution);\\n\\t\\t\\tlight._shadowCascadeDistances[i - 1] = dist;\\n\\t\\t}\\n\\t}\\n\\tgetLightRenderPass(light, camera) {\\n\\t\\tlet renderPass = null;\\n\\t\\tif (this.shadowRenderer.needsShadowRendering(light)) {\\n\\t\\t\\tconst faceCount = light.numShadowFaces;\\n\\t\\t\\tconst shadowUpdateOverrides = light.shadowUpdateOverrides;\\n\\t\\t\\tlet allCascadesRendering = true;\\n\\t\\t\\tlet shadowCamera;\\n\\t\\t\\tfor (let face = 0; face < faceCount; face++) {\\n\\t\\t\\t\\tif (shadowUpdateOverrides?.[face] === SHADOWUPDATE_NONE) {\\n\\t\\t\\t\\t\\tallCascadesRendering = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tshadowCamera = this.shadowRenderer.prepareFace(light, camera, face);\\n\\t\\t\\t}\\n\\t\\t\\trenderPass = new RenderPassShadowDirectional(this.device, this.shadowRenderer, light, camera, allCascadesRendering);\\n\\t\\t\\tthis.shadowRenderer.setupRenderPass(renderPass, shadowCamera, allCascadesRendering);\\n\\t\\t}\\n\\t\\treturn renderPass;\\n\\t}\\n}\\n\\nconst tempSet = /* @__PURE__ */ new Set();\\nconst shadowCamView = new Mat4();\\nconst shadowCamViewProj = new Mat4();\\nconst pixelOffset = new Float32Array(2);\\nconst blurScissorRect = new Vec4(1, 1, 0, 0);\\nconst viewportMatrix = new Mat4();\\nfunction gauss(x, sigma) {\\n\\treturn Math.exp(-(x * x) / (2 * sigma * sigma));\\n}\\nfunction gaussWeights(kernelSize) {\\n\\tconst sigma = (kernelSize - 1) / (2 * 3);\\n\\tconst halfWidth = (kernelSize - 1) * 0.5;\\n\\tconst values = new Array(kernelSize);\\n\\tlet sum = 0;\\n\\tfor (let i = 0; i < kernelSize; ++i) {\\n\\t\\tvalues[i] = gauss(i - halfWidth, sigma);\\n\\t\\tsum += values[i];\\n\\t}\\n\\tfor (let i = 0; i < kernelSize; ++i) {\\n\\t\\tvalues[i] /= sum;\\n\\t}\\n\\treturn values;\\n}\\nclass ShadowRenderer {\\n\\tshadowPassCache = [];\\n\\tconstructor(renderer, lightTextureAtlas) {\\n\\t\\tthis.device = renderer.device;\\n\\t\\tthis.renderer = renderer;\\n\\t\\tthis.lightTextureAtlas = lightTextureAtlas;\\n\\t\\tconst scope = this.device.scope;\\n\\t\\tthis.sourceId = scope.resolve(\\\"source\\\");\\n\\t\\tthis.pixelOffsetId = scope.resolve(\\\"pixelOffset\\\");\\n\\t\\tthis.weightId = scope.resolve(\\\"weight[0]\\\");\\n\\t\\tthis.blurVsmShader = [{}, {}];\\n\\t\\tthis.blurVsmWeights = {};\\n\\t\\tthis.shadowMapLightRadiusId = scope.resolve(\\\"light_radius\\\");\\n\\t\\tthis.viewUniformFormat = null;\\n\\t\\tthis.viewBindGroupFormat = null;\\n\\t\\tthis.blendStateWrite = new BlendState();\\n\\t\\tthis.blendStateNoWrite = new BlendState();\\n\\t\\tthis.blendStateNoWrite.setColorWrite(false, false, false, false);\\n\\t}\\n\\t// creates shadow camera for a light and sets up its constant properties\\n\\tstatic createShadowCamera(device, shadowType, type, face) {\\n\\t\\tconst shadowCam = LightCamera.create(device, SHADOWCAMERA_NAME, type, face);\\n\\t\\tconst shadowInfo = shadowTypeInfo.get(shadowType);\\n\\t\\tconst isVsm = shadowInfo?.vsm ?? false;\\n\\t\\tconst isPcf = shadowInfo?.pcf ?? false;\\n\\t\\tif (isVsm) {\\n\\t\\t\\tshadowCam.clearColor = new Color(0, 0, 0, 0);\\n\\t\\t} else {\\n\\t\\t\\tshadowCam.clearColor = new Color(1, 1, 1, 1);\\n\\t\\t}\\n\\t\\tshadowCam.clearDepthBuffer = true;\\n\\t\\tshadowCam.clearStencilBuffer = false;\\n\\t\\tshadowCam.clearColorBuffer = !isPcf;\\n\\t\\treturn shadowCam;\\n\\t}\\n\\t_cullShadowCastersInternal(meshInstances, visible, camera) {\\n\\t\\tconst numInstances = meshInstances.length;\\n\\t\\tfor (let i = 0; i < numInstances; i++) {\\n\\t\\t\\tconst meshInstance = meshInstances[i];\\n\\t\\t\\tif (meshInstance.castShadow) {\\n\\t\\t\\t\\tif (!meshInstance.cull || meshInstance._isVisible(camera)) {\\n\\t\\t\\t\\t\\tmeshInstance.visibleThisFrame = true;\\n\\t\\t\\t\\t\\tvisible.push(meshInstance);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tcullShadowCasters(comp, light, visible, camera, casters) {\\n\\t\\tthis.renderer.scene?.fire(EVENT_PRECULL, camera);\\n\\t\\tvisible.length = 0;\\n\\t\\tif (casters) {\\n\\t\\t\\tthis._cullShadowCastersInternal(casters, visible, camera);\\n\\t\\t} else {\\n\\t\\t\\tconst layers = comp.layerList;\\n\\t\\t\\tconst len = layers.length;\\n\\t\\t\\tfor (let i = 0; i < len; i++) {\\n\\t\\t\\t\\tconst layer = layers[i];\\n\\t\\t\\t\\tif (layer._lightsSet.has(light)) {\\n\\t\\t\\t\\t\\tif (!tempSet.has(layer)) {\\n\\t\\t\\t\\t\\t\\ttempSet.add(layer);\\n\\t\\t\\t\\t\\t\\tthis._cullShadowCastersInternal(layer.shadowCasters, visible, camera);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\ttempSet.clear();\\n\\t\\t}\\n\\t\\tvisible.sort(this.sortCompareShader);\\n\\t\\tthis.renderer.scene?.fire(EVENT_POSTCULL, camera);\\n\\t}\\n\\tsortCompareShader(drawCallA, drawCallB) {\\n\\t\\tconst keyA = drawCallA._sortKeyShadow;\\n\\t\\tconst keyB = drawCallB._sortKeyShadow;\\n\\t\\tif (keyA === keyB) {\\n\\t\\t\\treturn drawCallB.mesh.id - drawCallA.mesh.id;\\n\\t\\t}\\n\\t\\treturn keyB - keyA;\\n\\t}\\n\\tsetupRenderState(device, light) {\\n\\t\\tconst isClustered = this.renderer.scene.clusteredLightingEnabled;\\n\\t\\tconst useShadowSampler = isClustered ? light._isPcf : (\\n\\t\\t\\t// both spot and omni light are using shadow sampler when clustered\\n\\t\\t\\tlight._isPcf && light._type !== LIGHTTYPE_OMNI\\n\\t\\t);\\n\\t\\tdevice.setBlendState(useShadowSampler ? this.blendStateNoWrite : this.blendStateWrite);\\n\\t\\tdevice.setDepthState(light.shadowDepthState);\\n\\t\\tdevice.setStencilState(null, null);\\n\\t}\\n\\tdispatchUniforms(light, shadowCam, lightRenderData, face) {\\n\\t\\tconst shadowCamNode = shadowCam._node;\\n\\t\\tif (light._type !== LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\tthis.renderer.dispatchViewPos(shadowCamNode.getPosition());\\n\\t\\t\\tthis.shadowMapLightRadiusId.setValue(light.attenuationEnd);\\n\\t\\t}\\n\\t\\tshadowCamView.setTRS(shadowCamNode.getPosition(), shadowCamNode.getRotation(), Vec3.ONE).invert();\\n\\t\\tshadowCamViewProj.mul2(shadowCam.projectionMatrix, shadowCamView);\\n\\t\\tconst rectViewport = lightRenderData.shadowViewport;\\n\\t\\tshadowCam.rect = rectViewport;\\n\\t\\tshadowCam.scissorRect = lightRenderData.shadowScissor;\\n\\t\\tviewportMatrix.setViewport(rectViewport.x, rectViewport.y, rectViewport.z, rectViewport.w);\\n\\t\\tlightRenderData.shadowMatrix.mul2(viewportMatrix, shadowCamViewProj);\\n\\t\\tif (light._type === LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\tlight._shadowMatrixPalette.set(lightRenderData.shadowMatrix.data, face * 16);\\n\\t\\t}\\n\\t}\\n\\tgetShadowPass(light) {\\n\\t\\tconst lightType = light._type;\\n\\t\\tconst shadowType = light._shadowType;\\n\\t\\tlet shadowPassInfo = this.shadowPassCache[lightType]?.[shadowType];\\n\\t\\tif (!shadowPassInfo) {\\n\\t\\t\\tconst shadowPassName = `ShadowPass_${lightType}_${shadowType}`;\\n\\t\\t\\tshadowPassInfo = ShaderPass.get(this.device).allocate(shadowPassName, {\\n\\t\\t\\t\\tisShadow: true,\\n\\t\\t\\t\\tlightType,\\n\\t\\t\\t\\tshadowType\\n\\t\\t\\t});\\n\\t\\t\\tif (!this.shadowPassCache[lightType]) {\\n\\t\\t\\t\\tthis.shadowPassCache[lightType] = [];\\n\\t\\t\\t}\\n\\t\\t\\tthis.shadowPassCache[lightType][shadowType] = shadowPassInfo;\\n\\t\\t}\\n\\t\\treturn shadowPassInfo.index;\\n\\t}\\n\\tsubmitCasters(visibleCasters, light, camera) {\\n\\t\\tconst device = this.device;\\n\\t\\tconst renderer = this.renderer;\\n\\t\\tconst scene = renderer.scene;\\n\\t\\tconst passFlags = 1 << SHADER_SHADOW;\\n\\t\\tconst shadowPass = this.getShadowPass(light);\\n\\t\\tconst cameraShaderParams = camera.shaderParams;\\n\\t\\tconst flipFactor = camera.renderTarget.flipY ? -1 : 1;\\n\\t\\tconst count = visibleCasters.length;\\n\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\tconst meshInstance = visibleCasters[i];\\n\\t\\t\\tconst mesh = meshInstance.mesh;\\n\\t\\t\\tconst instancingData = meshInstance.instancingData;\\n\\t\\t\\tif (instancingData && instancingData.count <= 0) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tmeshInstance.ensureMaterial(device);\\n\\t\\t\\tconst material = meshInstance.material;\\n\\t\\t\\trenderer.setBaseConstants(device, material);\\n\\t\\t\\trenderer.setSkinning(device, meshInstance);\\n\\t\\t\\tif (material.dirty) {\\n\\t\\t\\t\\tmaterial.updateUniforms(device, scene);\\n\\t\\t\\t\\tmaterial.dirty = false;\\n\\t\\t\\t}\\n\\t\\t\\trenderer.setupCullModeAndFrontFace(true, flipFactor, meshInstance);\\n\\t\\t\\tmaterial.setParameters(device);\\n\\t\\t\\tmeshInstance.setParameters(device, passFlags);\\n\\t\\t\\tconst shaderInstance = meshInstance.getShaderInstance(shadowPass, 0, scene, cameraShaderParams, this.viewUniformFormat, this.viewBindGroupFormat);\\n\\t\\t\\tconst shadowShader = shaderInstance.shader;\\n\\t\\t\\tif (shadowShader.failed) continue;\\n\\t\\t\\tmeshInstance._sortKeyShadow = shadowShader.id;\\n\\t\\t\\tdevice.setShader(shadowShader);\\n\\t\\t\\trenderer.setVertexBuffers(device, mesh);\\n\\t\\t\\trenderer.setMorphing(device, meshInstance.morphInstance);\\n\\t\\t\\tif (instancingData) {\\n\\t\\t\\t\\tdevice.setVertexBuffer(instancingData.vertexBuffer);\\n\\t\\t\\t}\\n\\t\\t\\trenderer.setMeshInstanceMatrices(meshInstance);\\n\\t\\t\\trenderer.setupMeshUniformBuffers(shaderInstance);\\n\\t\\t\\tconst style = meshInstance.renderStyle;\\n\\t\\t\\tconst indirectData = meshInstance.getDrawCommands(camera);\\n\\t\\t\\tdevice.draw(mesh.primitive[style], mesh.indexBuffer[style], instancingData?.count, indirectData);\\n\\t\\t\\trenderer._shadowDrawCalls++;\\n\\t\\t\\tif (instancingData) {\\n\\t\\t\\t\\trenderer._instancedDrawCalls++;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tneedsShadowRendering(light) {\\n\\t\\tconst needs = light.enabled && light.castShadows && light.shadowUpdateMode !== SHADOWUPDATE_NONE && light.visibleThisFrame;\\n\\t\\tif (light.shadowUpdateMode === SHADOWUPDATE_THISFRAME) {\\n\\t\\t\\tlight.shadowUpdateMode = SHADOWUPDATE_NONE;\\n\\t\\t}\\n\\t\\tif (needs) {\\n\\t\\t\\tthis.renderer._shadowMapUpdates += light.numShadowFaces;\\n\\t\\t}\\n\\t\\treturn needs;\\n\\t}\\n\\tgetLightRenderData(light, camera, face) {\\n\\t\\treturn light.getRenderData(light._type === LIGHTTYPE_DIRECTIONAL ? camera : null, face);\\n\\t}\\n\\tsetupRenderPass(renderPass, shadowCamera, clearRenderTarget) {\\n\\t\\tconst rt = shadowCamera.renderTarget;\\n\\t\\trenderPass.init(rt);\\n\\t\\trenderPass.depthStencilOps.clearDepthValue = 1;\\n\\t\\trenderPass.depthStencilOps.clearDepth = clearRenderTarget;\\n\\t\\tif (rt.depthBuffer) {\\n\\t\\t\\trenderPass.depthStencilOps.storeDepth = true;\\n\\t\\t} else {\\n\\t\\t\\trenderPass.colorOps.clearValue.copy(shadowCamera.clearColor);\\n\\t\\t\\trenderPass.colorOps.clear = clearRenderTarget;\\n\\t\\t\\trenderPass.depthStencilOps.storeDepth = false;\\n\\t\\t}\\n\\t\\trenderPass.requiresCubemaps = false;\\n\\t}\\n\\t// prepares render target / render target settings to allow render pass to be set up\\n\\tprepareFace(light, camera, face) {\\n\\t\\tconst type = light._type;\\n\\t\\tconst lightRenderData = this.getLightRenderData(light, camera, face);\\n\\t\\tconst shadowCam = lightRenderData.shadowCamera;\\n\\t\\tconst renderTargetIndex = type === LIGHTTYPE_DIRECTIONAL ? 0 : face;\\n\\t\\tshadowCam.renderTarget = light._shadowMap.renderTargets[renderTargetIndex];\\n\\t\\treturn shadowCam;\\n\\t}\\n\\trenderFace(light, camera, face, clear) {\\n\\t\\tconst device = this.device;\\n\\t\\tconst lightRenderData = this.getLightRenderData(light, camera, face);\\n\\t\\tconst shadowCam = lightRenderData.shadowCamera;\\n\\t\\tthis.dispatchUniforms(light, shadowCam, lightRenderData, face);\\n\\t\\tconst rt = shadowCam.renderTarget;\\n\\t\\tconst renderer = this.renderer;\\n\\t\\trenderer.setCameraUniforms(shadowCam, rt);\\n\\t\\tif (device.supportsUniformBuffers) {\\n\\t\\t\\trenderer.setupViewUniformBuffers(lightRenderData.viewBindGroups, this.viewUniformFormat, this.viewBindGroupFormat, null);\\n\\t\\t}\\n\\t\\trenderer.setupViewport(shadowCam, rt);\\n\\t\\tif (clear) {\\n\\t\\t\\trenderer.clear(shadowCam);\\n\\t\\t}\\n\\t\\tthis.setupRenderState(device, light);\\n\\t\\tthis.submitCasters(lightRenderData.visibleCasters, light, shadowCam);\\n\\t}\\n\\trenderVsm(light, camera) {\\n\\t\\tif (light._isVsm && light._vsmBlurSize > 1) {\\n\\t\\t\\tconst isClustered = this.renderer.scene.clusteredLightingEnabled;\\n\\t\\t\\tif (!isClustered || light._type === LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\tthis.applyVsmBlur(light, camera);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tgetVsmBlurShader(blurMode, filterSize) {\\n\\t\\tconst cache = this.blurVsmShader;\\n\\t\\tlet blurShader = cache[blurMode][filterSize];\\n\\t\\tif (!blurShader) {\\n\\t\\t\\tthis.blurVsmWeights[filterSize] = gaussWeights(filterSize);\\n\\t\\t\\tconst defines = /* @__PURE__ */ new Map();\\n\\t\\t\\tdefines.set(\\\"{SAMPLES}\\\", filterSize);\\n\\t\\t\\tif (blurMode === 1) defines.set(\\\"GAUSS\\\", \\\"\\\");\\n\\t\\t\\tblurShader = ShaderUtils.createShader(this.device, {\\n\\t\\t\\t\\tuniqueName: `blurVsm${blurMode}${filterSize}`,\\n\\t\\t\\t\\tattributes: { vertex_position: SEMANTIC_POSITION },\\n\\t\\t\\t\\tvertexChunk: \\\"fullscreenQuadVS\\\",\\n\\t\\t\\t\\tfragmentChunk: \\\"blurVSMPS\\\",\\n\\t\\t\\t\\tfragmentDefines: defines\\n\\t\\t\\t});\\n\\t\\t\\tcache[blurMode][filterSize] = blurShader;\\n\\t\\t}\\n\\t\\treturn blurShader;\\n\\t}\\n\\tapplyVsmBlur(light, camera) {\\n\\t\\tconst device = this.device;\\n\\t\\tdevice.setBlendState(BlendState.NOBLEND);\\n\\t\\tconst lightRenderData = light.getRenderData(light._type === LIGHTTYPE_DIRECTIONAL ? camera : null, 0);\\n\\t\\tconst shadowCam = lightRenderData.shadowCamera;\\n\\t\\tconst origShadowMap = shadowCam.renderTarget;\\n\\t\\tconst tempShadowMap = this.renderer.shadowMapCache.get(device, light);\\n\\t\\tconst tempRt = tempShadowMap.renderTargets[0];\\n\\t\\tconst blurMode = light.vsmBlurMode;\\n\\t\\tconst filterSize = light._vsmBlurSize;\\n\\t\\tconst blurShader = this.getVsmBlurShader(blurMode, filterSize);\\n\\t\\tblurScissorRect.z = light._shadowResolution - 2;\\n\\t\\tblurScissorRect.w = blurScissorRect.z;\\n\\t\\tthis.sourceId.setValue(origShadowMap.colorBuffer);\\n\\t\\tpixelOffset[0] = 1 / light._shadowResolution;\\n\\t\\tpixelOffset[1] = 0;\\n\\t\\tthis.pixelOffsetId.setValue(pixelOffset);\\n\\t\\tif (blurMode === BLUR_GAUSSIAN) this.weightId.setValue(this.blurVsmWeights[filterSize]);\\n\\t\\tdrawQuadWithShader(device, tempRt, blurShader, null, blurScissorRect);\\n\\t\\tthis.sourceId.setValue(tempRt.colorBuffer);\\n\\t\\tpixelOffset[1] = pixelOffset[0];\\n\\t\\tpixelOffset[0] = 0;\\n\\t\\tthis.pixelOffsetId.setValue(pixelOffset);\\n\\t\\tdrawQuadWithShader(device, origShadowMap, blurShader, null, blurScissorRect);\\n\\t\\tthis.renderer.shadowMapCache.add(light, tempShadowMap);\\n\\t}\\n\\tinitViewBindGroupFormat() {\\n\\t\\tif (this.device.supportsUniformBuffers && !this.viewUniformFormat) {\\n\\t\\t\\tthis.viewUniformFormat = new UniformBufferFormat(this.device, [\\n\\t\\t\\t\\tnew UniformFormat(\\\"matrix_viewProjection\\\", UNIFORMTYPE_MAT4)\\n\\t\\t\\t]);\\n\\t\\t\\tthis.viewBindGroupFormat = new BindGroupFormat(this.device, [\\n\\t\\t\\t\\tnew BindUniformBufferFormat(UNIFORM_BUFFER_DEFAULT_SLOT_NAME, SHADERSTAGE_VERTEX | SHADERSTAGE_FRAGMENT)\\n\\t\\t\\t]);\\n\\t\\t}\\n\\t}\\n\\tframeUpdate() {\\n\\t\\tthis.initViewBindGroupFormat();\\n\\t}\\n}\\n\\nclass FramePassMultiView extends FramePass {\\n\\tchildren = [];\\n\\tconstructor(graphicsDevice) {\\n\\t\\tsuper(graphicsDevice);\\n\\t\\tthis.name = \\\"FramePassMultiView\\\";\\n\\t}\\n\\taddChild(pass) {\\n\\t\\tthis.children.push(pass);\\n\\t}\\n\\trender() {\\n\\t\\tif (!this.enabled) return;\\n\\t\\tconst device = this.device;\\n\\t\\tconst subs = device.xrSubImages;\\n\\t\\tconst numViews = subs?.length ?? 0;\\n\\t\\tconst children = this.children;\\n\\t\\tconst childCount = children.length;\\n\\t\\tif (numViews === 0) {\\n\\t\\t\\tfor (let c = 0; c < childCount; c++) {\\n\\t\\t\\t\\tchildren[c].render();\\n\\t\\t\\t}\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst backBufferImpl = device.backBuffer?.impl;\\n\\t\\tconst savedXrColorTexture = device.xrColorTexture;\\n\\t\\tconst savedColorTexture = backBufferImpl?.assignedColorTexture ?? null;\\n\\t\\tconst savedViewFormat = backBufferImpl?.colorAttachments?.[0]?.format ?? null;\\n\\t\\tfor (let v = 0; v < numViews; v++) {\\n\\t\\t\\tconst sub = subs[v];\\n\\t\\t\\tdevice.xrCurrentViewIndex = v;\\n\\t\\t\\tdevice.xrColorTexture = sub.colorTexture;\\n\\t\\t\\tdevice.xrColorTextureViewDescriptor = sub.viewDescriptor;\\n\\t\\t\\tbackBufferImpl?.assignColorTexture?.(sub.colorTexture, sub.viewFormat);\\n\\t\\t\\tfor (let c = 0; c < childCount; c++) {\\n\\t\\t\\t\\tchildren[c].render();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdevice.xrCurrentViewIndex = -1;\\n\\t\\tdevice.xrColorTextureViewDescriptor = null;\\n\\t\\tdevice.xrColorTexture = savedXrColorTexture ?? null;\\n\\t\\tif (backBufferImpl && savedColorTexture && savedViewFormat && backBufferImpl.assignedColorTexture !== savedColorTexture) {\\n\\t\\t\\tbackBufferImpl.assignColorTexture(savedColorTexture, savedViewFormat);\\n\\t\\t}\\n\\t}\\n}\\n\\nconst tempClusterArray = [];\\nclass WorldClustersAllocator {\\n\\t_empty = null;\\n\\t_allocated = [];\\n\\t_clusters = /* @__PURE__ */ new Map();\\n\\tconstructor(graphicsDevice) {\\n\\t\\tthis.device = graphicsDevice;\\n\\t}\\n\\tdestroy() {\\n\\t\\tif (this._empty) {\\n\\t\\t\\tthis._empty.destroy();\\n\\t\\t\\tthis._empty = null;\\n\\t\\t}\\n\\t\\tthis._allocated.forEach((cluster) => {\\n\\t\\t\\tcluster.destroy();\\n\\t\\t});\\n\\t\\tthis._allocated.length = 0;\\n\\t}\\n\\tget count() {\\n\\t\\treturn this._allocated.length;\\n\\t}\\n\\t// returns an empty light cluster object to be used when no lights are used\\n\\tget empty() {\\n\\t\\tif (!this._empty) {\\n\\t\\t\\tconst empty = new WorldClusters(this.device);\\n\\t\\t\\tempty.name = \\\"ClusterEmpty\\\";\\n\\t\\t\\tempty.update([]);\\n\\t\\t\\tthis._empty = empty;\\n\\t\\t}\\n\\t\\treturn this._empty;\\n\\t}\\n\\t_assignClustersForPass(renderPass) {\\n\\t\\tconst renderActions = renderPass.renderActions;\\n\\t\\tif (!renderActions) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst count = renderActions.length;\\n\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\tconst ra = renderActions[i];\\n\\t\\t\\tra.lightClusters = null;\\n\\t\\t\\tconst layer = ra.layer;\\n\\t\\t\\tif (layer.hasClusteredLights && layer.meshInstances.length) {\\n\\t\\t\\t\\tconst hash = layer.getLightIdHash();\\n\\t\\t\\t\\tconst existingRenderAction = this._clusters.get(hash);\\n\\t\\t\\t\\tlet clusters = existingRenderAction?.lightClusters;\\n\\t\\t\\t\\tif (!clusters) {\\n\\t\\t\\t\\t\\tclusters = tempClusterArray.pop() ?? new WorldClusters(this.device);\\n\\t\\t\\t\\t\\tthis._allocated.push(clusters);\\n\\t\\t\\t\\t\\tthis._clusters.set(hash, ra);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tra.lightClusters = clusters;\\n\\t\\t\\t}\\n\\t\\t\\tif (!ra.lightClusters) {\\n\\t\\t\\t\\tra.lightClusters = this.empty;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t// assign light clusters to render actions that need it\\n\\tassign(renderPasses) {\\n\\t\\ttempClusterArray.push(...this._allocated);\\n\\t\\tthis._allocated.length = 0;\\n\\t\\tthis._clusters.clear();\\n\\t\\tconst passCount = renderPasses.length;\\n\\t\\tfor (let p = 0; p < passCount; p++) {\\n\\t\\t\\tconst pass = renderPasses[p];\\n\\t\\t\\tif (pass instanceof FramePassMultiView) {\\n\\t\\t\\t\\tconst children = pass.children;\\n\\t\\t\\t\\tfor (let c = 0; c < children.length; c++) {\\n\\t\\t\\t\\t\\tthis._assignClustersForPass(children[c]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._assignClustersForPass(pass);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\ttempClusterArray.forEach((item) => item.destroy());\\n\\t\\ttempClusterArray.length = 0;\\n\\t}\\n\\tupdate(renderPasses, lighting) {\\n\\t\\tthis.assign(renderPasses);\\n\\t\\tthis._clusters.forEach((renderAction) => {\\n\\t\\t\\tconst layer = renderAction.layer;\\n\\t\\t\\tconst cluster = renderAction.lightClusters;\\n\\t\\t\\tcluster.update(layer.clusteredLightsSet, lighting);\\n\\t\\t});\\n\\t}\\n}\\n\\nconst _viewport = new Vec4();\\nconst _invViewProjMatrices = [];\\nclass RenderPassCookieRenderer extends RenderPass {\\n\\t_quadRenderer2D = null;\\n\\t_quadRendererCube = null;\\n\\t_filteredLights = [];\\n\\t_forceCopy = false;\\n\\t_evtDeviceRestored = null;\\n\\tconstructor(device, cubeSlotsOffsets) {\\n\\t\\tsuper(device);\\n\\t\\tthis._cubeSlotsOffsets = cubeSlotsOffsets;\\n\\t\\tthis.requiresCubemaps = false;\\n\\t\\tthis.blitTextureId = device.scope.resolve(\\\"blitTexture\\\");\\n\\t\\tthis.invViewProjId = device.scope.resolve(\\\"invViewProj\\\");\\n\\t\\tthis._evtDeviceRestored = device.on(\\\"devicerestored\\\", this.onDeviceRestored, this);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._quadRenderer2D?.destroy();\\n\\t\\tthis._quadRenderer2D = null;\\n\\t\\tthis._quadRendererCube?.destroy();\\n\\t\\tthis._quadRendererCube = null;\\n\\t\\tthis._evtDeviceRestored?.off();\\n\\t\\tthis._evtDeviceRestored = null;\\n\\t}\\n\\tstatic create(renderTarget, cubeSlotsOffsets) {\\n\\t\\tconst renderPass = new RenderPassCookieRenderer(renderTarget.device, cubeSlotsOffsets);\\n\\t\\trenderPass.init(renderTarget);\\n\\t\\trenderPass.colorOps.clear = false;\\n\\t\\trenderPass.depthStencilOps.clearDepth = false;\\n\\t\\treturn renderPass;\\n\\t}\\n\\tonDeviceRestored() {\\n\\t\\tthis._forceCopy = true;\\n\\t}\\n\\tupdate(lights) {\\n\\t\\tconst filteredLights = this._filteredLights;\\n\\t\\tthis.filter(lights, filteredLights);\\n\\t\\tthis.executeEnabled = filteredLights.length > 0;\\n\\t}\\n\\tfilter(lights, filteredLights) {\\n\\t\\tfor (let i = 0; i < lights.length; i++) {\\n\\t\\t\\tconst light = lights[i];\\n\\t\\t\\tif (light._type === LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tif (!light.atlasViewportAllocated) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tif (!light.atlasSlotUpdated && !this._forceCopy) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tif (light.enabled && light.cookie && light.visibleThisFrame) {\\n\\t\\t\\t\\tfilteredLights.push(light);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._forceCopy = false;\\n\\t}\\n\\tinitInvViewProjMatrices() {\\n\\t\\tif (!_invViewProjMatrices.length) {\\n\\t\\t\\tfor (let face = 0; face < 6; face++) {\\n\\t\\t\\t\\tconst camera = LightCamera.create(this.device, null, LIGHTTYPE_OMNI, face);\\n\\t\\t\\t\\tconst projMat = camera.projectionMatrix;\\n\\t\\t\\t\\tconst viewMat = camera.node.getLocalTransform().clone().invert();\\n\\t\\t\\t\\t_invViewProjMatrices[face] = new Mat4().mul2(projMat, viewMat).invert();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget quadRenderer2D() {\\n\\t\\tif (!this._quadRenderer2D) {\\n\\t\\t\\tconst shader = ShaderUtils.createShader(this.device, {\\n\\t\\t\\t\\tuniqueName: \\\"cookieRenderer2d\\\",\\n\\t\\t\\t\\tattributes: { vertex_position: SEMANTIC_POSITION },\\n\\t\\t\\t\\tvertexChunk: \\\"cookieBlitVS\\\",\\n\\t\\t\\t\\tfragmentChunk: \\\"cookieBlit2DPS\\\"\\n\\t\\t\\t});\\n\\t\\t\\tthis._quadRenderer2D = new QuadRender(shader);\\n\\t\\t}\\n\\t\\treturn this._quadRenderer2D;\\n\\t}\\n\\tget quadRendererCube() {\\n\\t\\tif (!this._quadRendererCube) {\\n\\t\\t\\tconst shader = ShaderUtils.createShader(this.device, {\\n\\t\\t\\t\\tuniqueName: \\\"cookieRendererCube\\\",\\n\\t\\t\\t\\tattributes: { vertex_position: SEMANTIC_POSITION },\\n\\t\\t\\t\\tvertexChunk: \\\"cookieBlitVS\\\",\\n\\t\\t\\t\\tfragmentChunk: \\\"cookieBlitCubePS\\\"\\n\\t\\t\\t});\\n\\t\\t\\tthis._quadRendererCube = new QuadRender(shader);\\n\\t\\t}\\n\\t\\treturn this._quadRendererCube;\\n\\t}\\n\\texecute() {\\n\\t\\tconst device = this.device;\\n\\t\\tdevice.setDrawStates();\\n\\t\\tconst renderTargetWidth = this.renderTarget.colorBuffer.width;\\n\\t\\tconst cubeSlotsOffsets = this._cubeSlotsOffsets;\\n\\t\\tconst filteredLights = this._filteredLights;\\n\\t\\tfor (let i = 0; i < filteredLights.length; i++) {\\n\\t\\t\\tconst light = filteredLights[i];\\n\\t\\t\\tconst faceCount = light.numShadowFaces;\\n\\t\\t\\tconst quad = faceCount > 1 ? this.quadRendererCube : this.quadRenderer2D;\\n\\t\\t\\tif (faceCount > 1) {\\n\\t\\t\\t\\tthis.initInvViewProjMatrices();\\n\\t\\t\\t}\\n\\t\\t\\tthis.blitTextureId.setValue(light.cookie);\\n\\t\\t\\tfor (let face = 0; face < faceCount; face++) {\\n\\t\\t\\t\\t_viewport.copy(light.atlasViewport);\\n\\t\\t\\t\\tif (faceCount > 1) {\\n\\t\\t\\t\\t\\tconst smallSize = _viewport.z / 3;\\n\\t\\t\\t\\t\\tconst offset = cubeSlotsOffsets[face];\\n\\t\\t\\t\\t\\t_viewport.x += smallSize * offset.x;\\n\\t\\t\\t\\t\\t_viewport.y += smallSize * offset.y;\\n\\t\\t\\t\\t\\t_viewport.z = smallSize;\\n\\t\\t\\t\\t\\t_viewport.w = smallSize;\\n\\t\\t\\t\\t\\tthis.invViewProjId.setValue(_invViewProjMatrices[face].data);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\t_viewport.mulScalar(renderTargetWidth);\\n\\t\\t\\t\\tquad.render(_viewport);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfilteredLights.length = 0;\\n\\t}\\n}\\n\\nclass RenderPassShadowLocalClustered extends RenderPass {\\n\\tconstructor(device, shadowRenderer, shadowRendererLocal) {\\n\\t\\tsuper(device);\\n\\t\\tthis.requiresCubemaps = false;\\n\\t\\tthis.shadowRenderer = shadowRenderer;\\n\\t\\tthis.shadowRendererLocal = shadowRendererLocal;\\n\\t}\\n\\tupdate(localLights) {\\n\\t\\tconst shadowLights = this.shadowRendererLocal.shadowLights;\\n\\t\\tconst shadowCamera = this.shadowRendererLocal.prepareLights(shadowLights, localLights);\\n\\t\\tconst count = shadowLights.length;\\n\\t\\tthis.enabled = count > 0;\\n\\t\\tif (count) {\\n\\t\\t\\tthis.shadowRenderer.setupRenderPass(this, shadowCamera, false);\\n\\t\\t}\\n\\t}\\n\\texecute() {\\n\\t\\tconst shadowLights = this.shadowRendererLocal.shadowLights;\\n\\t\\tconst count = shadowLights.length;\\n\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\tconst light = shadowLights[i];\\n\\t\\t\\tfor (let face = 0; face < light.numShadowFaces; face++) {\\n\\t\\t\\t\\tthis.shadowRenderer.renderFace(light, null, face, true);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tshadowLights.length = 0;\\n\\t}\\n}\\n\\nclass FramePassUpdateClustered extends FramePass {\\n\\tconstructor(device, renderer, shadowRenderer, shadowRendererLocal, lightTextureAtlas) {\\n\\t\\tsuper(device);\\n\\t\\tthis.renderer = renderer;\\n\\t\\tthis.frameGraph = null;\\n\\t\\tthis.cookiesRenderPass = RenderPassCookieRenderer.create(lightTextureAtlas.cookieRenderTarget, lightTextureAtlas.cubeSlotsOffsets);\\n\\t\\tthis.beforePasses.push(this.cookiesRenderPass);\\n\\t\\tthis.shadowRenderPass = new RenderPassShadowLocalClustered(device, shadowRenderer, shadowRendererLocal);\\n\\t\\tthis.beforePasses.push(this.shadowRenderPass);\\n\\t}\\n\\tupdate(frameGraph, shadowsEnabled, cookiesEnabled, lights, localLights) {\\n\\t\\tthis.frameGraph = frameGraph;\\n\\t\\tthis.cookiesRenderPass.enabled = cookiesEnabled;\\n\\t\\tif (cookiesEnabled) {\\n\\t\\t\\tthis.cookiesRenderPass.update(lights);\\n\\t\\t}\\n\\t\\tthis.shadowRenderPass.enabled = shadowsEnabled;\\n\\t\\tif (shadowsEnabled) {\\n\\t\\t\\tthis.shadowRenderPass.update(localLights);\\n\\t\\t}\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.cookiesRenderPass.destroy();\\n\\t\\tthis.cookiesRenderPass = null;\\n\\t}\\n\\texecute() {\\n\\t\\tconst { renderer } = this;\\n\\t\\tconst { scene } = renderer;\\n\\t\\trenderer.worldClustersAllocator.update(this.frameGraph.renderPasses, scene.lighting);\\n\\t}\\n}\\n\\nlet _skinUpdateIndex = 0;\\nconst viewProjMat$1 = new Mat4();\\nconst viewInvMat = new Mat4();\\nconst viewMat = new Mat4();\\nconst viewMat3 = new Mat3();\\nconst tempSphere = new BoundingSphere();\\nconst tempFrustum = new Frustum();\\nconst _tempLightSet = /* @__PURE__ */ new Set();\\nconst _tempLayerSet = /* @__PURE__ */ new Set();\\nconst _dynamicBindGroup = new DynamicBindGroup();\\nconst _tempClearColor = [0, 0, 0, 1];\\nconst _tempClearOptions = {\\n\\tcolor: _tempClearColor,\\n\\tdepth: 1,\\n\\tstencil: 0,\\n\\tflags: 0\\n};\\nconst _haltonSequence = [\\n\\tnew Vec2(0.5, 0.333333),\\n\\tnew Vec2(0.25, 0.666667),\\n\\tnew Vec2(0.75, 0.111111),\\n\\tnew Vec2(0.125, 0.444444),\\n\\tnew Vec2(0.625, 0.777778),\\n\\tnew Vec2(0.375, 0.222222),\\n\\tnew Vec2(0.875, 0.555556),\\n\\tnew Vec2(0.0625, 0.888889),\\n\\tnew Vec2(0.5625, 0.037037),\\n\\tnew Vec2(0.3125, 0.37037),\\n\\tnew Vec2(0.8125, 0.703704),\\n\\tnew Vec2(0.1875, 0.148148),\\n\\tnew Vec2(0.6875, 0.481481),\\n\\tnew Vec2(0.4375, 0.814815),\\n\\tnew Vec2(0.9375, 0.259259),\\n\\tnew Vec2(0.03125, 0.592593)\\n];\\nconst _tempProjMat0 = new Mat4();\\nconst _tempProjMat1 = new Mat4();\\nconst _tempProjMat4 = new Mat4();\\nconst _tempProjMat5 = new Mat4();\\nconst _tempSet = /* @__PURE__ */ new Set();\\nconst _tempMeshInstances = [];\\nconst _tempMeshInstancesSkinned = [];\\nclass Renderer {\\n\\tclustersDebugRendered = false;\\n\\tscene;\\n\\tprocessingMeshInstances = /* @__PURE__ */ new Set();\\n\\tworldClustersAllocator;\\n\\tlights = [];\\n\\tlocalLights = [];\\n\\tcameraDirShadowLights = /* @__PURE__ */ new Map();\\n\\tdirLightShadows = /* @__PURE__ */ new Map();\\n\\tblueNoise = new BlueNoise(123);\\n\\tgsplatDirector = null;\\n\\tconstructor(graphicsDevice, scene) {\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tthis.scene = scene;\\n\\t\\tthis.worldClustersAllocator = new WorldClustersAllocator(graphicsDevice);\\n\\t\\tthis.lightTextureAtlas = new LightTextureAtlas(graphicsDevice);\\n\\t\\tthis.shadowMapCache = new ShadowMapCache();\\n\\t\\tthis.shadowRenderer = new ShadowRenderer(this, this.lightTextureAtlas);\\n\\t\\tthis._shadowRendererLocal = new ShadowRendererLocal(this, this.shadowRenderer);\\n\\t\\tthis._shadowRendererDirectional = new ShadowRendererDirectional(this, this.shadowRenderer);\\n\\t\\tif (this.scene.clusteredLightingEnabled) {\\n\\t\\t\\tthis._renderPassUpdateClustered = new FramePassUpdateClustered(\\n\\t\\t\\t\\tthis.device,\\n\\t\\t\\t\\tthis,\\n\\t\\t\\t\\tthis.shadowRenderer,\\n\\t\\t\\t\\tthis._shadowRendererLocal,\\n\\t\\t\\t\\tthis.lightTextureAtlas\\n\\t\\t\\t);\\n\\t\\t}\\n\\t\\tthis.viewUniformFormat = null;\\n\\t\\tthis.viewBindGroupFormat = null;\\n\\t\\tthis._skinTime = 0;\\n\\t\\tthis._morphTime = 0;\\n\\t\\tthis._cullTime = 0;\\n\\t\\tthis._shadowMapTime = 0;\\n\\t\\tthis._lightClustersTime = 0;\\n\\t\\tthis._layerCompositionUpdateTime = 0;\\n\\t\\tthis._shadowDrawCalls = 0;\\n\\t\\tthis._skinDrawCalls = 0;\\n\\t\\tthis._instancedDrawCalls = 0;\\n\\t\\tthis._shadowMapUpdates = 0;\\n\\t\\tthis._numDrawCallsCulled = 0;\\n\\t\\tthis._camerasRendered = 0;\\n\\t\\tthis._lightClusters = 0;\\n\\t\\tthis._gsplatCount = 0;\\n\\t\\tconst scope = graphicsDevice.scope;\\n\\t\\tthis.boneTextureId = scope.resolve(\\\"texture_poseMap\\\");\\n\\t\\tthis.modelMatrixId = scope.resolve(\\\"matrix_model\\\");\\n\\t\\tthis.normalMatrixId = scope.resolve(\\\"matrix_normal\\\");\\n\\t\\tthis.viewInvId = scope.resolve(\\\"matrix_viewInverse\\\");\\n\\t\\tthis.viewPos = new Float32Array(3);\\n\\t\\tthis.viewPosId = scope.resolve(\\\"view_position\\\");\\n\\t\\tthis.projId = scope.resolve(\\\"matrix_projection\\\");\\n\\t\\tthis.projSkyboxId = scope.resolve(\\\"matrix_projectionSkybox\\\");\\n\\t\\tthis.viewId = scope.resolve(\\\"matrix_view\\\");\\n\\t\\tthis.viewId3 = scope.resolve(\\\"matrix_view3\\\");\\n\\t\\tthis.viewProjId = scope.resolve(\\\"matrix_viewProjection\\\");\\n\\t\\tthis.flipYId = scope.resolve(\\\"projectionFlipY\\\");\\n\\t\\tthis.tbnBasis = scope.resolve(\\\"tbnBasis\\\");\\n\\t\\tthis.cameraParams = new Float32Array(4);\\n\\t\\tthis.cameraParamsId = scope.resolve(\\\"camera_params\\\");\\n\\t\\tthis.viewportSize = new Float32Array(4);\\n\\t\\tthis.viewportSizeId = scope.resolve(\\\"viewport_size\\\");\\n\\t\\tthis.viewIndexId = scope.resolve(\\\"view_index\\\");\\n\\t\\tthis.viewIndexId.setValue(0);\\n\\t\\tthis.blueNoiseJitterVersion = 0;\\n\\t\\tthis.blueNoiseJitterVec = new Vec4();\\n\\t\\tthis.blueNoiseJitterData = new Float32Array(4);\\n\\t\\tthis.blueNoiseJitterId = scope.resolve(\\\"blueNoiseJitter\\\");\\n\\t\\tthis.blueNoiseTextureId = scope.resolve(\\\"blueNoiseTex32\\\");\\n\\t\\tthis.alphaTestId = scope.resolve(\\\"alpha_ref\\\");\\n\\t\\tthis.opacityMapId = scope.resolve(\\\"texture_opacityMap\\\");\\n\\t\\tthis.exposureId = scope.resolve(\\\"exposure\\\");\\n\\t\\tthis.morphPositionTex = scope.resolve(\\\"morphPositionTex\\\");\\n\\t\\tthis.morphNormalTex = scope.resolve(\\\"morphNormalTex\\\");\\n\\t\\tthis.morphTexParams = scope.resolve(\\\"morph_tex_params\\\");\\n\\t\\tthis.lightCube = new LightCube();\\n\\t\\tthis.constantLightCube = scope.resolve(\\\"lightCube[0]\\\");\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.shadowRenderer = null;\\n\\t\\tthis._shadowRendererLocal = null;\\n\\t\\tthis._shadowRendererDirectional = null;\\n\\t\\tthis.shadowMapCache.destroy();\\n\\t\\tthis.shadowMapCache = null;\\n\\t\\tthis._renderPassUpdateClustered?.destroy();\\n\\t\\tthis._renderPassUpdateClustered = null;\\n\\t\\tthis.lightTextureAtlas.destroy();\\n\\t\\tthis.lightTextureAtlas = null;\\n\\t\\tthis.gsplatDirector?.destroy();\\n\\t\\tthis.gsplatDirector = null;\\n\\t}\\n\\tsetupViewport(camera, renderTarget) {\\n\\t\\tconst device = this.device;\\n\\t\\tconst pixelWidth = renderTarget ? renderTarget.width : device.width;\\n\\t\\tconst pixelHeight = renderTarget ? renderTarget.height : device.height;\\n\\t\\tconst rect = camera.rect;\\n\\t\\tlet x = Math.floor(rect.x * pixelWidth);\\n\\t\\tlet y = Math.floor(rect.y * pixelHeight);\\n\\t\\tlet w = Math.floor(rect.z * pixelWidth);\\n\\t\\tlet h = Math.floor(rect.w * pixelHeight);\\n\\t\\tdevice.setViewport(x, y, w, h);\\n\\t\\tif (camera._scissorRectClear) {\\n\\t\\t\\tconst scissorRect = camera.scissorRect;\\n\\t\\t\\tx = Math.floor(scissorRect.x * pixelWidth);\\n\\t\\t\\ty = Math.floor(scissorRect.y * pixelHeight);\\n\\t\\t\\tw = Math.floor(scissorRect.z * pixelWidth);\\n\\t\\t\\th = Math.floor(scissorRect.w * pixelHeight);\\n\\t\\t}\\n\\t\\tdevice.setScissor(x, y, w, h);\\n\\t}\\n\\tsetCameraUniforms(camera, target) {\\n\\t\\tconst flipY = target?.flipY;\\n\\t\\tlet viewList = null;\\n\\t\\tif (camera.xr && camera.xr.session) {\\n\\t\\t\\tconst transform = camera._node?.parent?.getWorldTransform() || null;\\n\\t\\t\\tconst views = camera.xr.views;\\n\\t\\t\\tviewList = views.list;\\n\\t\\t\\tfor (let v = 0; v < viewList.length; v++) {\\n\\t\\t\\t\\tconst view = viewList[v];\\n\\t\\t\\t\\tview.updateTransforms(transform);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tlet projMat = camera.projectionMatrix;\\n\\t\\t\\tif (camera.calculateProjection) {\\n\\t\\t\\t\\tcamera.calculateProjection(projMat, VIEW_CENTER);\\n\\t\\t\\t}\\n\\t\\t\\tlet projMatSkybox = camera.getProjectionMatrixSkybox();\\n\\t\\t\\tconst webgpu = this.device.isWebGPU;\\n\\t\\t\\tprojMat = Camera$1.applyShaderProjectionTransform(projMat, _tempProjMat0, flipY, webgpu);\\n\\t\\t\\tprojMatSkybox = Camera$1.applyShaderProjectionTransform(projMatSkybox, _tempProjMat1, flipY, webgpu);\\n\\t\\t\\tconst { jitter } = camera;\\n\\t\\t\\tlet jitterX = 0;\\n\\t\\t\\tlet jitterY = 0;\\n\\t\\t\\tif (jitter > 0) {\\n\\t\\t\\t\\tconst targetWidth = target ? target.width : this.device.width;\\n\\t\\t\\t\\tconst targetHeight = target ? target.height : this.device.height;\\n\\t\\t\\t\\tconst offset = _haltonSequence[this.device.renderVersion % _haltonSequence.length];\\n\\t\\t\\t\\tjitterX = jitter * (offset.x * 2 - 1) / targetWidth;\\n\\t\\t\\t\\tjitterY = jitter * (offset.y * 2 - 1) / targetHeight;\\n\\t\\t\\t\\tprojMat = _tempProjMat4.copy(projMat);\\n\\t\\t\\t\\tprojMat.data[8] = jitterX;\\n\\t\\t\\t\\tprojMat.data[9] = jitterY;\\n\\t\\t\\t\\tprojMatSkybox = _tempProjMat5.copy(projMatSkybox);\\n\\t\\t\\t\\tprojMatSkybox.data[8] = jitterX;\\n\\t\\t\\t\\tprojMatSkybox.data[9] = jitterY;\\n\\t\\t\\t\\tif (this.blueNoiseJitterVersion !== this.device.renderVersion) {\\n\\t\\t\\t\\t\\tthis.blueNoiseJitterVersion = this.device.renderVersion;\\n\\t\\t\\t\\t\\tthis.blueNoise.vec4(this.blueNoiseJitterVec);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tconst jitterVec = jitter > 0 ? this.blueNoiseJitterVec : Vec4.ZERO;\\n\\t\\t\\tthis.blueNoiseJitterData[0] = jitterVec.x;\\n\\t\\t\\tthis.blueNoiseJitterData[1] = jitterVec.y;\\n\\t\\t\\tthis.blueNoiseJitterData[2] = jitterVec.z;\\n\\t\\t\\tthis.blueNoiseJitterData[3] = jitterVec.w;\\n\\t\\t\\tthis.blueNoiseJitterId.setValue(this.blueNoiseJitterData);\\n\\t\\t\\tthis.projId.setValue(projMat.data);\\n\\t\\t\\tthis.projSkyboxId.setValue(projMatSkybox.data);\\n\\t\\t\\tif (camera.calculateTransform) {\\n\\t\\t\\t\\tcamera.calculateTransform(viewInvMat, VIEW_CENTER);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconst pos = camera._node.getPosition();\\n\\t\\t\\t\\tconst rot = camera._node.getRotation();\\n\\t\\t\\t\\tviewInvMat.setTRS(pos, rot, Vec3.ONE);\\n\\t\\t\\t}\\n\\t\\t\\tthis.viewInvId.setValue(viewInvMat.data);\\n\\t\\t\\tviewMat.copy(viewInvMat).invert();\\n\\t\\t\\tthis.viewId.setValue(viewMat.data);\\n\\t\\t\\tviewMat3.setFromMat4(viewMat);\\n\\t\\t\\tthis.viewId3.setValue(viewMat3.data);\\n\\t\\t\\tviewProjMat$1.mul2(projMat, viewMat);\\n\\t\\t\\tthis.viewProjId.setValue(viewProjMat$1.data);\\n\\t\\t\\tcamera._storeShaderMatrices(viewProjMat$1, jitterX, jitterY, this.device.renderVersion);\\n\\t\\t\\tthis.flipYId.setValue(flipY ? -1 : 1);\\n\\t\\t\\tthis.dispatchViewPos(camera._node.getPosition());\\n\\t\\t\\tcamera.frustum.setFromMat4(viewProjMat$1);\\n\\t\\t}\\n\\t\\tthis.tbnBasis.setValue(flipY ? -1 : 1);\\n\\t\\tthis.cameraParamsId.setValue(camera.fillShaderParams(this.cameraParams));\\n\\t\\tconst xrView = camera.xr?.session ? camera.xr.views.list[0] : null;\\n\\t\\tlet viewportWidth = xrView ? xrView.viewport.z : target ? target.width : this.device.width;\\n\\t\\tlet viewportHeight = xrView ? xrView.viewport.w : target ? target.height : this.device.height;\\n\\t\\tviewportWidth *= camera.rect.z;\\n\\t\\tviewportHeight *= camera.rect.w;\\n\\t\\tthis.viewportSize[0] = viewportWidth;\\n\\t\\tthis.viewportSize[1] = viewportHeight;\\n\\t\\tthis.viewportSize[2] = 1 / viewportWidth;\\n\\t\\tthis.viewportSize[3] = 1 / viewportHeight;\\n\\t\\tthis.viewportSizeId.setValue(this.viewportSize);\\n\\t\\tthis.exposureId.setValue(this.scene.physicalUnits ? camera.getExposure() : this.scene.exposure);\\n\\t\\treturn viewList;\\n\\t}\\n\\tclear(camera, clearColor, clearDepth, clearStencil) {\\n\\t\\tconst flags = (clearColor ?? camera._clearColorBuffer ? CLEARFLAG_COLOR : 0) | (clearDepth ?? camera._clearDepthBuffer ? CLEARFLAG_DEPTH : 0) | (clearStencil ?? camera._clearStencilBuffer ? CLEARFLAG_STENCIL : 0);\\n\\t\\tif (flags) {\\n\\t\\t\\tconst device = this.device;\\n\\t\\t\\tconst c = camera._clearColor;\\n\\t\\t\\t_tempClearColor[0] = c.r;\\n\\t\\t\\t_tempClearColor[1] = c.g;\\n\\t\\t\\t_tempClearColor[2] = c.b;\\n\\t\\t\\t_tempClearColor[3] = c.a;\\n\\t\\t\\t_tempClearOptions.depth = camera._clearDepth;\\n\\t\\t\\t_tempClearOptions.stencil = camera._clearStencil;\\n\\t\\t\\t_tempClearOptions.flags = flags;\\n\\t\\t\\tdevice.clear(_tempClearOptions);\\n\\t\\t}\\n\\t}\\n\\tsetupCullModeAndFrontFace(cullFaces, flipFactor, drawCall) {\\n\\t\\tconst material = drawCall.material;\\n\\t\\tconst flipFaces = flipFactor * drawCall.flipFacesFactor * drawCall.node.worldScaleSign;\\n\\t\\tlet frontFace = material.frontFace;\\n\\t\\tif (flipFaces < 0) {\\n\\t\\t\\tfrontFace = frontFace === FRONTFACE_CCW ? FRONTFACE_CW : FRONTFACE_CCW;\\n\\t\\t}\\n\\t\\tthis.device.setCullMode(cullFaces ? material.cull : CULLFACE_NONE);\\n\\t\\tthis.device.setFrontFace(frontFace);\\n\\t}\\n\\tsetupCullMode(cullFaces, flipFactor, drawCall) {\\n\\t\\tthis.setupCullModeAndFrontFace(cullFaces, flipFactor, drawCall);\\n\\t}\\n\\tupdateCameraFrustum(camera) {\\n\\t\\tif (camera.xr && camera.xr.views.list.length) {\\n\\t\\t\\tconst views = camera.xr.views.list;\\n\\t\\t\\tviewProjMat$1.mul2(views[0].projMat, views[0].viewOffMat);\\n\\t\\t\\tcamera.frustum.setFromMat4(viewProjMat$1);\\n\\t\\t\\tfor (let v = 1; v < views.length; v++) {\\n\\t\\t\\t\\tviewProjMat$1.mul2(views[v].projMat, views[v].viewOffMat);\\n\\t\\t\\t\\ttempFrustum.setFromMat4(viewProjMat$1);\\n\\t\\t\\t\\tcamera.frustum.add(tempFrustum);\\n\\t\\t\\t}\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst projMat = camera.projectionMatrix;\\n\\t\\tif (camera.calculateProjection) {\\n\\t\\t\\tcamera.calculateProjection(projMat, VIEW_CENTER);\\n\\t\\t}\\n\\t\\tif (camera.calculateTransform) {\\n\\t\\t\\tcamera.calculateTransform(viewInvMat, VIEW_CENTER);\\n\\t\\t} else {\\n\\t\\t\\tconst pos = camera._node.getPosition();\\n\\t\\t\\tconst rot = camera._node.getRotation();\\n\\t\\t\\tviewInvMat.setTRS(pos, rot, Vec3.ONE);\\n\\t\\t\\tthis.viewInvId.setValue(viewInvMat.data);\\n\\t\\t}\\n\\t\\tviewMat.copy(viewInvMat).invert();\\n\\t\\tviewProjMat$1.mul2(projMat, viewMat);\\n\\t\\tcamera.frustum.setFromMat4(viewProjMat$1);\\n\\t}\\n\\tsetBaseConstants(device, material) {\\n\\t\\tdevice.setCullMode(material.cull);\\n\\t\\tdevice.setFrontFace(material.frontFace);\\n\\t\\tif (material.opacityMap) {\\n\\t\\t\\tthis.opacityMapId.setValue(material.opacityMap);\\n\\t\\t}\\n\\t\\tif (material.opacityMap || material.alphaTest > 0) {\\n\\t\\t\\tthis.alphaTestId.setValue(material.alphaTest);\\n\\t\\t}\\n\\t}\\n\\tupdateCpuSkinMatrices(drawCalls) {\\n\\t\\t_skinUpdateIndex++;\\n\\t\\tconst drawCallsCount = drawCalls.length;\\n\\t\\tif (drawCallsCount === 0) return;\\n\\t\\tfor (let i = 0; i < drawCallsCount; i++) {\\n\\t\\t\\tconst si = drawCalls[i].skinInstance;\\n\\t\\t\\tif (si) {\\n\\t\\t\\t\\tsi.updateMatrices(drawCalls[i].node, _skinUpdateIndex);\\n\\t\\t\\t\\tsi._dirty = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tupdateGpuSkinMatrices(drawCalls) {\\n\\t\\tfor (const drawCall of drawCalls) {\\n\\t\\t\\tconst skin = drawCall.skinInstance;\\n\\t\\t\\tif (skin && skin._dirty) {\\n\\t\\t\\t\\tskin.updateMatrixPalette(drawCall.node, _skinUpdateIndex);\\n\\t\\t\\t\\tskin._dirty = false;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tupdateMorphing(drawCalls) {\\n\\t\\tfor (const drawCall of drawCalls) {\\n\\t\\t\\tconst morphInst = drawCall.morphInstance;\\n\\t\\t\\tif (morphInst && morphInst._dirty) {\\n\\t\\t\\t\\tmorphInst.update();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tupdateGSplats(drawCalls) {\\n\\t\\tfor (const drawCall of drawCalls) {\\n\\t\\t\\tdrawCall.gsplatInstance?.update();\\n\\t\\t}\\n\\t}\\n\\tgpuUpdate(drawCalls) {\\n\\t\\tthis.updateGpuSkinMatrices(drawCalls);\\n\\t\\tthis.updateMorphing(drawCalls);\\n\\t\\tthis.updateGSplats(drawCalls);\\n\\t}\\n\\tsetVertexBuffers(device, mesh) {\\n\\t\\tdevice.setVertexBuffer(mesh.vertexBuffer);\\n\\t}\\n\\tsetMorphing(device, morphInstance) {\\n\\t\\tif (morphInstance) {\\n\\t\\t\\tmorphInstance.prepareRendering(device);\\n\\t\\t\\tdevice.setVertexBuffer(morphInstance.morph.vertexBufferIds);\\n\\t\\t\\tthis.morphPositionTex.setValue(morphInstance.texturePositions);\\n\\t\\t\\tthis.morphNormalTex.setValue(morphInstance.textureNormals);\\n\\t\\t\\tthis.morphTexParams.setValue(morphInstance._textureParams);\\n\\t\\t}\\n\\t}\\n\\tsetSkinning(device, meshInstance) {\\n\\t\\tconst skinInstance = meshInstance.skinInstance;\\n\\t\\tif (skinInstance) {\\n\\t\\t\\tthis._skinDrawCalls++;\\n\\t\\t\\tconst boneTexture = skinInstance.boneTexture;\\n\\t\\t\\tthis.boneTextureId.setValue(boneTexture);\\n\\t\\t}\\n\\t}\\n\\t// sets Vec3 camera position uniform\\n\\tdispatchViewPos(position) {\\n\\t\\tconst vp = this.viewPos;\\n\\t\\tvp[0] = position.x;\\n\\t\\tvp[1] = position.y;\\n\\t\\tvp[2] = position.z;\\n\\t\\tthis.viewPosId.setValue(vp);\\n\\t}\\n\\tinitViewBindGroupFormat(isClustered) {\\n\\t\\tif (this.device.supportsUniformBuffers && !this.viewUniformFormat) {\\n\\t\\t\\tconst uniforms = [\\n\\t\\t\\t\\tnew UniformFormat(\\\"matrix_view\\\", UNIFORMTYPE_MAT4),\\n\\t\\t\\t\\tnew UniformFormat(\\\"matrix_viewInverse\\\", UNIFORMTYPE_MAT4),\\n\\t\\t\\t\\tnew UniformFormat(\\\"matrix_projection\\\", UNIFORMTYPE_MAT4),\\n\\t\\t\\t\\tnew UniformFormat(\\\"matrix_projectionSkybox\\\", UNIFORMTYPE_MAT4),\\n\\t\\t\\t\\tnew UniformFormat(\\\"matrix_viewProjection\\\", UNIFORMTYPE_MAT4),\\n\\t\\t\\t\\tnew UniformFormat(\\\"matrix_view3\\\", UNIFORMTYPE_MAT3),\\n\\t\\t\\t\\tnew UniformFormat(\\\"cubeMapRotationMatrix\\\", UNIFORMTYPE_MAT3),\\n\\t\\t\\t\\tnew UniformFormat(\\\"view_position\\\", UNIFORMTYPE_VEC3),\\n\\t\\t\\t\\tnew UniformFormat(\\\"viewport_size\\\", UNIFORMTYPE_VEC4),\\n\\t\\t\\t\\tnew UniformFormat(\\\"skyboxIntensity\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"exposure\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"textureBias\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"view_index\\\", UNIFORMTYPE_FLOAT)\\n\\t\\t\\t];\\n\\t\\t\\tif (isClustered) {\\n\\t\\t\\t\\tuniforms.push(...[\\n\\t\\t\\t\\t\\tnew UniformFormat(\\\"clusterCellsCountByBoundsSize\\\", UNIFORMTYPE_VEC3),\\n\\t\\t\\t\\t\\tnew UniformFormat(\\\"clusterBoundsMin\\\", UNIFORMTYPE_VEC3),\\n\\t\\t\\t\\t\\tnew UniformFormat(\\\"clusterBoundsDelta\\\", UNIFORMTYPE_VEC3),\\n\\t\\t\\t\\t\\tnew UniformFormat(\\\"clusterCellsDot\\\", UNIFORMTYPE_IVEC3),\\n\\t\\t\\t\\t\\tnew UniformFormat(\\\"clusterCellsMax\\\", UNIFORMTYPE_IVEC3),\\n\\t\\t\\t\\t\\tnew UniformFormat(\\\"shadowAtlasParams\\\", UNIFORMTYPE_VEC2),\\n\\t\\t\\t\\t\\tnew UniformFormat(\\\"clusterMaxCells\\\", UNIFORMTYPE_INT),\\n\\t\\t\\t\\t\\tnew UniformFormat(\\\"numClusteredLights\\\", UNIFORMTYPE_INT),\\n\\t\\t\\t\\t\\tnew UniformFormat(\\\"clusterTextureWidth\\\", UNIFORMTYPE_INT)\\n\\t\\t\\t\\t]);\\n\\t\\t\\t}\\n\\t\\t\\tthis.viewUniformFormat = new UniformBufferFormat(this.device, uniforms);\\n\\t\\t\\tconst formats = [\\n\\t\\t\\t\\t// uniform buffer needs to be first, as the shader processor assumes slot 0 for it\\n\\t\\t\\t\\tnew BindUniformBufferFormat(UNIFORM_BUFFER_DEFAULT_SLOT_NAME, SHADERSTAGE_VERTEX | SHADERSTAGE_FRAGMENT)\\n\\t\\t\\t\\t// disable view level textures, as they consume texture slots. They get automatically added to mesh bind group\\n\\t\\t\\t\\t// for the meshes that uses them\\n\\t\\t\\t\\t// new BindTextureFormat('lightsTexture', SHADERSTAGE_FRAGMENT, TEXTUREDIMENSION_2D, SAMPLETYPE_UNFILTERABLE_FLOAT),\\n\\t\\t\\t\\t// new BindTextureFormat('shadowAtlasTexture', SHADERSTAGE_FRAGMENT, TEXTUREDIMENSION_2D, SAMPLETYPE_DEPTH),\\n\\t\\t\\t\\t// new BindTextureFormat('cookieAtlasTexture', SHADERSTAGE_FRAGMENT, TEXTUREDIMENSION_2D, SAMPLETYPE_FLOAT),\\n\\t\\t\\t\\t// new BindTextureFormat('areaLightsLutTex1', SHADERSTAGE_FRAGMENT, TEXTUREDIMENSION_2D, SAMPLETYPE_FLOAT),\\n\\t\\t\\t\\t// new BindTextureFormat('areaLightsLutTex2', SHADERSTAGE_FRAGMENT, TEXTUREDIMENSION_2D, SAMPLETYPE_FLOAT)\\n\\t\\t\\t];\\n\\t\\t\\tthis.viewBindGroupFormat = new BindGroupFormat(this.device, formats);\\n\\t\\t}\\n\\t}\\n\\tsetupViewUniforms(view, index) {\\n\\t\\tthis.projId.setValue(view.projMat.data);\\n\\t\\tthis.projSkyboxId.setValue(view.projMat.data);\\n\\t\\tthis.viewId.setValue(view.viewOffMat.data);\\n\\t\\tthis.viewInvId.setValue(view.viewInvOffMat.data);\\n\\t\\tthis.viewId3.setValue(view.viewMat3.data);\\n\\t\\tthis.viewProjId.setValue(view.projViewOffMat.data);\\n\\t\\tthis.viewPosId.setValue(view.positionData);\\n\\t\\tthis.viewIndexId.setValue(index);\\n\\t}\\n\\tsetupViewUniformBuffers(viewBindGroups, viewUniformFormat, viewBindGroupFormat, viewList) {\\n\\t\\tconst { device } = this;\\n\\t\\tconst viewCount = viewList?.length ?? 1;\\n\\t\\twhile (viewBindGroups.length < viewCount) {\\n\\t\\t\\tconst ub = new UniformBuffer(device, viewUniformFormat, false);\\n\\t\\t\\tconst bg = new BindGroup(device, viewBindGroupFormat, ub);\\n\\t\\t\\tviewBindGroups.push(bg);\\n\\t\\t}\\n\\t\\tif (viewList) {\\n\\t\\t\\tfor (let i = 0; i < viewCount; i++) {\\n\\t\\t\\t\\tconst view = viewList[i];\\n\\t\\t\\t\\tthis.setupViewUniforms(view, i);\\n\\t\\t\\t\\tconst viewBindGroup = viewBindGroups[i];\\n\\t\\t\\t\\tviewBindGroup.defaultUniformBuffer.update();\\n\\t\\t\\t\\tviewBindGroup.update();\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tconst viewBindGroup = viewBindGroups[0];\\n\\t\\t\\tviewBindGroup.defaultUniformBuffer.update();\\n\\t\\t\\tviewBindGroup.update();\\n\\t\\t}\\n\\t\\tif (!viewList) {\\n\\t\\t\\tdevice.setBindGroup(BINDGROUP_VIEW, viewBindGroups[0]);\\n\\t\\t}\\n\\t}\\n\\tsetupMeshUniformBuffers(shaderInstance) {\\n\\t\\tconst device = this.device;\\n\\t\\tif (device.supportsUniformBuffers) {\\n\\t\\t\\tconst meshBindGroup = shaderInstance.getBindGroup(device);\\n\\t\\t\\tmeshBindGroup.update();\\n\\t\\t\\tdevice.setBindGroup(BINDGROUP_MESH, meshBindGroup);\\n\\t\\t\\tconst meshUniformBuffer = shaderInstance.getUniformBuffer(device);\\n\\t\\t\\tmeshUniformBuffer.update(_dynamicBindGroup);\\n\\t\\t\\tdevice.setBindGroup(BINDGROUP_MESH_UB, _dynamicBindGroup.bindGroup, _dynamicBindGroup.offsets);\\n\\t\\t}\\n\\t}\\n\\tsetMeshInstanceMatrices(meshInstance, setNormalMatrix = false) {\\n\\t\\tconst modelMatrix = meshInstance.node.worldTransform;\\n\\t\\tthis.modelMatrixId.setValue(modelMatrix.data);\\n\\t\\tif (setNormalMatrix) {\\n\\t\\t\\tthis.normalMatrixId.setValue(meshInstance.node.normalMatrix.data);\\n\\t\\t}\\n\\t}\\n\\tcull(camera, drawCalls, culledInstances) {\\n\\t\\tconst opaque = culledInstances.opaque;\\n\\t\\topaque.length = 0;\\n\\t\\tconst transparent = culledInstances.transparent;\\n\\t\\ttransparent.length = 0;\\n\\t\\tconst doCull = camera.frustumCulling;\\n\\t\\tconst count = drawCalls.length;\\n\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\tconst drawCall = drawCalls[i];\\n\\t\\t\\tif (drawCall.visible) {\\n\\t\\t\\t\\tconst visible = !doCull || !drawCall.cull || drawCall._isVisible(camera);\\n\\t\\t\\t\\tif (visible) {\\n\\t\\t\\t\\t\\tdrawCall.visibleThisFrame = true;\\n\\t\\t\\t\\t\\tconst bucket = drawCall.transparent ? transparent : opaque;\\n\\t\\t\\t\\t\\tbucket.push(drawCall);\\n\\t\\t\\t\\t\\tif (drawCall.skinInstance || drawCall.morphInstance || drawCall.gsplatInstance) {\\n\\t\\t\\t\\t\\t\\tthis.processingMeshInstances.add(drawCall);\\n\\t\\t\\t\\t\\t\\tif (drawCall.gsplatInstance) {\\n\\t\\t\\t\\t\\t\\t\\tdrawCall.gsplatInstance.cameras.push(camera);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tcollectLights(comp) {\\n\\t\\tthis.lights.length = 0;\\n\\t\\tthis.localLights.length = 0;\\n\\t\\tconst stats = this.scene._stats;\\n\\t\\tconst count = comp.layerList.length;\\n\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\tconst layer = comp.layerList[i];\\n\\t\\t\\tif (!_tempLayerSet.has(layer)) {\\n\\t\\t\\t\\t_tempLayerSet.add(layer);\\n\\t\\t\\t\\tconst lights = layer._lights;\\n\\t\\t\\t\\tfor (let j = 0; j < lights.length; j++) {\\n\\t\\t\\t\\t\\tconst light = lights[j];\\n\\t\\t\\t\\t\\tif (!_tempLightSet.has(light)) {\\n\\t\\t\\t\\t\\t\\t_tempLightSet.add(light);\\n\\t\\t\\t\\t\\t\\tthis.lights.push(light);\\n\\t\\t\\t\\t\\t\\tif (light._type !== LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\t\\t\\tthis.localLights.push(light);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tstats.lights = this.lights.length;\\n\\t\\t_tempLightSet.clear();\\n\\t\\t_tempLayerSet.clear();\\n\\t}\\n\\tcullLights(camera, lights) {\\n\\t\\tconst clusteredLightingEnabled = this.scene.clusteredLightingEnabled;\\n\\t\\tconst physicalUnits = this.scene.physicalUnits;\\n\\t\\tfor (let i = 0; i < lights.length; i++) {\\n\\t\\t\\tconst light = lights[i];\\n\\t\\t\\tif (light.enabled) {\\n\\t\\t\\t\\tif (light._type !== LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\tlight.getBoundingSphere(tempSphere);\\n\\t\\t\\t\\t\\tif (camera.frustum.containsSphere(tempSphere)) {\\n\\t\\t\\t\\t\\t\\tlight.visibleThisFrame = true;\\n\\t\\t\\t\\t\\t\\tlight.usePhysicalUnits = physicalUnits;\\n\\t\\t\\t\\t\\t\\tconst screenSize = camera.getScreenSize(tempSphere);\\n\\t\\t\\t\\t\\t\\tlight.maxScreenSize = Math.max(light.maxScreenSize, screenSize);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (!clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\t\\t\\tif (light.castShadows && !light.shadowMap) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlight.visibleThisFrame = true;\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tlight.usePhysicalUnits = this.scene.physicalUnits;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tcullShadowmaps(comp) {\\n\\t\\tconst isClustered = this.scene.clusteredLightingEnabled;\\n\\t\\tfor (let i = 0; i < this.localLights.length; i++) {\\n\\t\\t\\tconst light = this.localLights[i];\\n\\t\\t\\tif (light._type !== LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\tif (isClustered) {\\n\\t\\t\\t\\t\\tif (light.atlasSlotUpdated && light.shadowUpdateMode === SHADOWUPDATE_NONE) {\\n\\t\\t\\t\\t\\t\\tlight.shadowUpdateMode = SHADOWUPDATE_THISFRAME;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tif (light.shadowUpdateMode === SHADOWUPDATE_NONE && light.castShadows) {\\n\\t\\t\\t\\t\\t\\tif (!light.getRenderData(null, 0).shadowCamera.renderTarget) {\\n\\t\\t\\t\\t\\t\\t\\tlight.shadowUpdateMode = SHADOWUPDATE_THISFRAME;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (light.visibleThisFrame && light.castShadows && light.shadowUpdateMode !== SHADOWUPDATE_NONE) {\\n\\t\\t\\t\\t\\tthis._shadowRendererLocal.cull(light, comp);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.cameraDirShadowLights.clear();\\n\\t\\tconst cameras = comp.cameras;\\n\\t\\tfor (let i = 0; i < cameras.length; i++) {\\n\\t\\t\\tconst cameraComponent = cameras[i];\\n\\t\\t\\tif (cameraComponent.enabled) {\\n\\t\\t\\t\\tconst camera = cameraComponent.camera;\\n\\t\\t\\t\\tlet lightList;\\n\\t\\t\\t\\tconst cameraLayers = camera.layers;\\n\\t\\t\\t\\tfor (let l = 0; l < cameraLayers.length; l++) {\\n\\t\\t\\t\\t\\tconst cameraLayer = comp.getLayerById(cameraLayers[l]);\\n\\t\\t\\t\\t\\tif (cameraLayer) {\\n\\t\\t\\t\\t\\t\\tconst layerDirLights = cameraLayer.splitLights[LIGHTTYPE_DIRECTIONAL];\\n\\t\\t\\t\\t\\t\\tfor (let j = 0; j < layerDirLights.length; j++) {\\n\\t\\t\\t\\t\\t\\t\\tconst light = layerDirLights[j];\\n\\t\\t\\t\\t\\t\\t\\tif (light.castShadows && !_tempSet.has(light)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t_tempSet.add(light);\\n\\t\\t\\t\\t\\t\\t\\t\\tlightList = lightList ?? [];\\n\\t\\t\\t\\t\\t\\t\\t\\tlightList.push(light);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._shadowRendererDirectional.cull(light, comp, camera);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (lightList) {\\n\\t\\t\\t\\t\\tthis.cameraDirShadowLights.set(camera, lightList);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\t_tempSet.clear();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tcullComposition(comp) {\\n\\t\\tconst { scene } = this;\\n\\t\\tthis.processingMeshInstances.clear();\\n\\t\\tconst numCameras = comp.cameras.length;\\n\\t\\tthis._camerasRendered += numCameras;\\n\\t\\tfor (let i = 0; i < numCameras; i++) {\\n\\t\\t\\tconst camera = comp.cameras[i];\\n\\t\\t\\tconst renderTarget = camera.renderTarget;\\n\\t\\t\\tcamera.frameUpdate(renderTarget);\\n\\t\\t\\tthis.updateCameraFrustum(camera.camera);\\n\\t\\t\\tscene?.fire(EVENT_PRECULL, camera);\\n\\t\\t\\tconst layerIds = camera.layers;\\n\\t\\t\\tfor (let j = 0; j < layerIds.length; j++) {\\n\\t\\t\\t\\tconst layer = comp.getLayerById(layerIds[j]);\\n\\t\\t\\t\\tif (layer && layer.enabled) {\\n\\t\\t\\t\\t\\tthis.cullLights(camera.camera, layer._lights);\\n\\t\\t\\t\\t\\tconst culledInstances = layer.getCulledInstances(camera.camera);\\n\\t\\t\\t\\t\\tthis.cull(camera.camera, layer.meshInstances, culledInstances);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tscene?.fire(EVENT_POSTCULL, camera);\\n\\t\\t}\\n\\t\\tif (scene.clusteredLightingEnabled) {\\n\\t\\t\\tthis.updateLightTextureAtlas();\\n\\t\\t}\\n\\t\\tthis.cullShadowmaps(comp);\\n\\t\\tscene?.fire(EVENT_CULL_END);\\n\\t}\\n\\tupdateShaders(drawCalls, onlyLitShaders) {\\n\\t\\tconst count = drawCalls.length;\\n\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\tconst mat = drawCalls[i].material;\\n\\t\\t\\tif (mat) {\\n\\t\\t\\t\\tif (!_tempSet.has(mat)) {\\n\\t\\t\\t\\t\\t_tempSet.add(mat);\\n\\t\\t\\t\\t\\tif (mat.getShaderVariant !== Material.prototype.getShaderVariant) {\\n\\t\\t\\t\\t\\t\\tif (onlyLitShaders) {\\n\\t\\t\\t\\t\\t\\t\\tif (!mat.useLighting || mat.emitter && !mat.emitter.lighting) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tmat.clearVariants();\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_tempSet.clear();\\n\\t}\\n\\tupdateFrameUniforms() {\\n\\t\\tthis.blueNoiseTextureId.setValue(getBlueNoiseTexture(this.device));\\n\\t}\\n\\tbeginFrame(comp) {\\n\\t\\tconst scene = this.scene;\\n\\t\\tconst updateShaders = scene.updateShaders || this.device._shadersDirty;\\n\\t\\tconst layers = comp.layerList;\\n\\t\\tconst layerCount = layers.length;\\n\\t\\tfor (let i = 0; i < layerCount; i++) {\\n\\t\\t\\tconst layer = layers[i];\\n\\t\\t\\tconst meshInstances = layer.meshInstances;\\n\\t\\t\\tconst count = meshInstances.length;\\n\\t\\t\\tfor (let j = 0; j < count; j++) {\\n\\t\\t\\t\\tconst meshInst = meshInstances[j];\\n\\t\\t\\t\\tmeshInst.visibleThisFrame = false;\\n\\t\\t\\t\\tif (updateShaders) {\\n\\t\\t\\t\\t\\t_tempMeshInstances.push(meshInst);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (meshInst.skinInstance) {\\n\\t\\t\\t\\t\\t_tempMeshInstancesSkinned.push(meshInst);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (updateShaders) {\\n\\t\\t\\tconst onlyLitShaders = !scene.updateShaders || !this.device._shadersDirty;\\n\\t\\t\\tthis.updateShaders(_tempMeshInstances, onlyLitShaders);\\n\\t\\t\\tscene.updateShaders = false;\\n\\t\\t\\tthis.device._shadersDirty = false;\\n\\t\\t\\tscene._shaderVersion++;\\n\\t\\t}\\n\\t\\tthis.updateFrameUniforms();\\n\\t\\tthis.updateCpuSkinMatrices(_tempMeshInstancesSkinned);\\n\\t\\t_tempMeshInstances.length = 0;\\n\\t\\t_tempMeshInstancesSkinned.length = 0;\\n\\t\\tconst lights = this.lights;\\n\\t\\tconst lightCount = lights.length;\\n\\t\\tfor (let i = 0; i < lightCount; i++) {\\n\\t\\t\\tlights[i].beginFrame();\\n\\t\\t}\\n\\t}\\n\\tupdateLightTextureAtlas() {\\n\\t\\tthis.lightTextureAtlas.update(this.localLights, this.scene.lighting);\\n\\t}\\n\\tupdateLayerComposition(comp) {\\n\\t\\tconst len = comp.layerList.length;\\n\\t\\tconst scene = this.scene;\\n\\t\\tconst shaderVersion = scene._shaderVersion;\\n\\t\\tfor (let i = 0; i < len; i++) {\\n\\t\\t\\tconst layer = comp.layerList[i];\\n\\t\\t\\tlayer._shaderVersion = shaderVersion;\\n\\t\\t}\\n\\t\\tcomp._update();\\n\\t}\\n\\tframeUpdate() {\\n\\t\\tthis.clustersDebugRendered = false;\\n\\t\\tthis.initViewBindGroupFormat(this.scene.clusteredLightingEnabled);\\n\\t\\tthis.dirLightShadows.clear();\\n\\t}\\n}\\n\\nclass RenderAction {\\n\\t// {CameraComponent|null}\\n\\tcamera = null;\\n\\tconstructor() {\\n\\t\\tthis.layer = null;\\n\\t\\tthis.transparent = false;\\n\\t\\tthis.renderTarget = null;\\n\\t\\tthis.lightClusters = null;\\n\\t\\tthis.clearColor = false;\\n\\t\\tthis.clearDepth = false;\\n\\t\\tthis.clearStencil = false;\\n\\t\\tthis.triggerPostprocess = false;\\n\\t\\tthis.firstCameraUse = false;\\n\\t\\tthis.lastCameraUse = false;\\n\\t\\tthis.viewBindGroups = [];\\n\\t\\tthis.useCameraPasses = false;\\n\\t}\\n\\t// releases GPU resources\\n\\tdestroy() {\\n\\t\\tthis.viewBindGroups.forEach((bg) => {\\n\\t\\t\\tbg.defaultUniformBuffer.destroy();\\n\\t\\t\\tbg.destroy();\\n\\t\\t});\\n\\t\\tthis.viewBindGroups.length = 0;\\n\\t}\\n\\tsetupClears(camera, layer) {\\n\\t\\tthis.clearColor = camera?.clearColorBuffer || layer.clearColorBuffer;\\n\\t\\tthis.clearDepth = camera?.clearDepthBuffer || layer.clearDepthBuffer;\\n\\t\\tthis.clearStencil = camera?.clearStencilBuffer || layer.clearStencilBuffer;\\n\\t}\\n}\\n\\nclass RenderPassForward extends RenderPass {\\n\\tlayerComposition;\\n\\tscene;\\n\\trenderer;\\n\\trenderActions = [];\\n\\tgammaCorrection;\\n\\ttoneMapping;\\n\\tnoDepthClear = false;\\n\\tconstructor(device, layerComposition, scene, renderer) {\\n\\t\\tsuper(device);\\n\\t\\tthis.layerComposition = layerComposition;\\n\\t\\tthis.scene = scene;\\n\\t\\tthis.renderer = renderer;\\n\\t}\\n\\tget rendersAnything() {\\n\\t\\treturn this.renderActions.length > 0;\\n\\t}\\n\\taddRenderAction(renderAction) {\\n\\t\\tthis.renderActions.push(renderAction);\\n\\t}\\n\\taddLayer(cameraComponent, layer, transparent, autoClears = true) {\\n\\t\\tconst ra = new RenderAction();\\n\\t\\tra.renderTarget = this.renderTarget;\\n\\t\\tra.camera = cameraComponent;\\n\\t\\tra.layer = layer;\\n\\t\\tra.transparent = transparent;\\n\\t\\tif (autoClears) {\\n\\t\\t\\tconst firstRa = this.renderActions.length === 0;\\n\\t\\t\\tra.setupClears(firstRa ? cameraComponent : void 0, layer);\\n\\t\\t}\\n\\t\\tthis.addRenderAction(ra);\\n\\t}\\n\\taddLayers(composition, cameraComponent, startIndex, firstLayerClears, lastLayerId, lastLayerIsTransparent = true) {\\n\\t\\tconst { layerList, subLayerList } = composition;\\n\\t\\tlet clearRenderTarget = firstLayerClears;\\n\\t\\tlet index = startIndex;\\n\\t\\twhile (index < layerList.length) {\\n\\t\\t\\tconst layer = layerList[index];\\n\\t\\t\\tconst isTransparent = subLayerList[index];\\n\\t\\t\\tconst renderedByCamera = cameraComponent.camera.layersSet.has(layer.id);\\n\\t\\t\\tif (renderedByCamera) {\\n\\t\\t\\t\\tthis.addLayer(cameraComponent, layer, isTransparent, clearRenderTarget);\\n\\t\\t\\t\\tclearRenderTarget = false;\\n\\t\\t\\t}\\n\\t\\t\\tindex++;\\n\\t\\t\\tif (layer.id === lastLayerId && isTransparent === lastLayerIsTransparent) {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn index;\\n\\t}\\n\\t// Collect before-passes from cameras whose first render action lives in this\\n\\t// RenderPassForward. Uses the existing firstCameraUse flag (set by LayerComposition)\\n\\t// to guarantee each camera's before-passes are scheduled exactly once, even when\\n\\t// multiple RenderPassForward instances reference the same camera (e.g. CameraFrame's\\n\\t// scenePass vs afterPass).\\n\\tupdateCameraBeforePasses() {\\n\\t\\tfor (let i = 0; i < this.renderActions.length; i++) {\\n\\t\\t\\tconst ra = this.renderActions[i];\\n\\t\\t\\tif (ra.firstCameraUse) {\\n\\t\\t\\t\\tconst camera = ra.camera?.camera;\\n\\t\\t\\t\\tif (camera) {\\n\\t\\t\\t\\t\\tconst { beforePasses } = camera;\\n\\t\\t\\t\\t\\tfor (let j = 0; j < beforePasses.length; j++) {\\n\\t\\t\\t\\t\\t\\tthis.beforePasses.push(beforePasses[j]);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tupdateDirectionalShadows() {\\n\\t\\tconst { renderer, renderActions } = this;\\n\\t\\tfor (let i = 0; i < renderActions.length; i++) {\\n\\t\\t\\tconst renderAction = renderActions[i];\\n\\t\\t\\tconst cameraComp = renderAction.camera;\\n\\t\\t\\tconst camera = cameraComp.camera;\\n\\t\\t\\tconst shadowDirLights = this.renderer.cameraDirShadowLights.get(camera);\\n\\t\\t\\tif (shadowDirLights) {\\n\\t\\t\\t\\tfor (let l = 0; l < shadowDirLights.length; l++) {\\n\\t\\t\\t\\t\\tconst light = shadowDirLights[l];\\n\\t\\t\\t\\t\\tif (renderer.dirLightShadows.get(light) !== camera) {\\n\\t\\t\\t\\t\\t\\trenderer.dirLightShadows.set(light, camera);\\n\\t\\t\\t\\t\\t\\tconst shadowPass = renderer._shadowRendererDirectional.getLightRenderPass(light, camera);\\n\\t\\t\\t\\t\\t\\tif (shadowPass) {\\n\\t\\t\\t\\t\\t\\t\\tthis.beforePasses.push(shadowPass);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tupdateClears() {\\n\\t\\tconst renderAction = this.renderActions[0];\\n\\t\\tif (renderAction) {\\n\\t\\t\\tconst cameraComponent = renderAction.camera;\\n\\t\\t\\tconst camera = cameraComponent.camera;\\n\\t\\t\\tconst fullSizeClearRect = camera.fullSizeClearRect;\\n\\t\\t\\tthis.setClearColor(fullSizeClearRect && renderAction.clearColor ? camera.clearColor : void 0);\\n\\t\\t\\tthis.setClearDepth(fullSizeClearRect && renderAction.clearDepth && !this.noDepthClear ? camera.clearDepth : void 0);\\n\\t\\t\\tthis.setClearStencil(fullSizeClearRect && renderAction.clearStencil ? camera.clearStencil : void 0);\\n\\t\\t}\\n\\t}\\n\\tframeUpdate() {\\n\\t\\tsuper.frameUpdate();\\n\\t\\tthis.updateCameraBeforePasses();\\n\\t\\tthis.updateDirectionalShadows();\\n\\t\\tthis.updateClears();\\n\\t}\\n\\tbefore() {\\n\\t\\tconst { renderActions } = this;\\n\\t\\tfor (let i = 0; i < renderActions.length; i++) {\\n\\t\\t\\tconst ra = renderActions[i];\\n\\t\\t\\tif (ra.firstCameraUse) {\\n\\t\\t\\t\\tthis.scene.fire(EVENT_PRERENDER, ra.camera);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\texecute() {\\n\\t\\tconst { layerComposition, renderActions } = this;\\n\\t\\tfor (let i = 0; i < renderActions.length; i++) {\\n\\t\\t\\tconst ra = renderActions[i];\\n\\t\\t\\tconst layer = ra.layer;\\n\\t\\t\\tif (layerComposition.isEnabled(layer, ra.transparent)) {\\n\\t\\t\\t\\tthis.renderRenderAction(ra, i === 0);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tafter() {\\n\\t\\tfor (let i = 0; i < this.renderActions.length; i++) {\\n\\t\\t\\tconst ra = this.renderActions[i];\\n\\t\\t\\tif (ra.lastCameraUse) {\\n\\t\\t\\t\\tthis.scene.fire(EVENT_POSTRENDER, ra.camera);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.beforePasses.length = 0;\\n\\t}\\n\\trenderRenderAction(renderAction, firstRenderAction) {\\n\\t\\tconst { renderer, scene } = this;\\n\\t\\tconst device = renderer.device;\\n\\t\\tconst { layer, transparent, camera } = renderAction;\\n\\t\\tif (camera) {\\n\\t\\t\\tconst originalGammaCorrection = camera.gammaCorrection;\\n\\t\\t\\tconst originalToneMapping = camera.toneMapping;\\n\\t\\t\\tif (this.gammaCorrection !== void 0) camera.gammaCorrection = this.gammaCorrection;\\n\\t\\t\\tif (this.toneMapping !== void 0) camera.toneMapping = this.toneMapping;\\n\\t\\t\\tscene.fire(EVENT_PRERENDER_LAYER, camera, layer, transparent);\\n\\t\\t\\tconst options = {\\n\\t\\t\\t\\tlightClusters: renderAction.lightClusters\\n\\t\\t\\t};\\n\\t\\t\\tconst shaderPass = camera.camera.shaderPassInfo?.index ?? SHADER_FORWARD;\\n\\t\\t\\tif (!firstRenderAction || !camera.camera.fullSizeClearRect) {\\n\\t\\t\\t\\toptions.clearColor = renderAction.clearColor;\\n\\t\\t\\t\\toptions.clearDepth = renderAction.clearDepth;\\n\\t\\t\\t\\toptions.clearStencil = renderAction.clearStencil;\\n\\t\\t\\t}\\n\\t\\t\\tconst renderTarget = renderAction.renderTarget ?? device.backBuffer;\\n\\t\\t\\trenderer.renderForwardLayer(\\n\\t\\t\\t\\tcamera.camera,\\n\\t\\t\\t\\trenderTarget,\\n\\t\\t\\t\\tlayer,\\n\\t\\t\\t\\ttransparent,\\n\\t\\t\\t\\tshaderPass,\\n\\t\\t\\t\\trenderAction.viewBindGroups,\\n\\t\\t\\t\\toptions\\n\\t\\t\\t);\\n\\t\\t\\tdevice.setBlendState(BlendState.NOBLEND);\\n\\t\\t\\tdevice.setStencilState(null, null);\\n\\t\\t\\tdevice.setAlphaToCoverage(false);\\n\\t\\t\\tscene.fire(EVENT_POSTRENDER_LAYER, camera, layer, transparent);\\n\\t\\t\\tif (this.gammaCorrection !== void 0) camera.gammaCorrection = originalGammaCorrection;\\n\\t\\t\\tif (this.toneMapping !== void 0) camera.toneMapping = originalToneMapping;\\n\\t\\t}\\n\\t}\\n}\\n\\nclass FramePassPostprocessing extends FramePass {\\n\\tconstructor(device, renderer, renderAction) {\\n\\t\\tsuper(device);\\n\\t\\tthis.renderer = renderer;\\n\\t\\tthis.renderAction = renderAction;\\n\\t}\\n\\texecute() {\\n\\t\\tconst renderAction = this.renderAction;\\n\\t\\tconst camera = renderAction.camera;\\n\\t\\tcamera.onPostprocessing();\\n\\t}\\n}\\n\\nconst _noLights = [[], [], []];\\nconst tmpColor$1 = new Color();\\nconst _drawCallList = {\\n\\tdrawCalls: [],\\n\\tshaderInstances: [],\\n\\tisNewMaterial: [],\\n\\tlightMaskChanged: [],\\n\\tclear: function() {\\n\\t\\tthis.drawCalls.length = 0;\\n\\t\\tthis.shaderInstances.length = 0;\\n\\t\\tthis.isNewMaterial.length = 0;\\n\\t\\tthis.lightMaskChanged.length = 0;\\n\\t}\\n};\\nfunction vogelDiskPrecalculationSamples(numSamples) {\\n\\tconst samples = [];\\n\\tfor (let i = 0; i < numSamples; ++i) {\\n\\t\\tconst r = Math.sqrt(i + 0.5) / Math.sqrt(numSamples);\\n\\t\\tsamples.push(r);\\n\\t}\\n\\treturn samples;\\n}\\nfunction vogelSpherePrecalculationSamples(numSamples) {\\n\\tconst samples = [];\\n\\tfor (let i = 0; i < numSamples; i++) {\\n\\t\\tconst weight = i / numSamples;\\n\\t\\tconst radius = Math.sqrt(weight * weight);\\n\\t\\tsamples.push(radius);\\n\\t}\\n\\treturn samples;\\n}\\nclass ForwardRenderer extends Renderer {\\n\\tconstructor(graphicsDevice, scene) {\\n\\t\\tsuper(graphicsDevice, scene);\\n\\t\\tconst device = this.device;\\n\\t\\tthis._forwardDrawCalls = 0;\\n\\t\\tthis._materialSwitches = 0;\\n\\t\\tthis._depthMapTime = 0;\\n\\t\\tthis._forwardTime = 0;\\n\\t\\tthis._sortTime = 0;\\n\\t\\tconst scope = device.scope;\\n\\t\\tthis.fogColorId = scope.resolve(\\\"fog_color\\\");\\n\\t\\tthis.fogStartId = scope.resolve(\\\"fog_start\\\");\\n\\t\\tthis.fogEndId = scope.resolve(\\\"fog_end\\\");\\n\\t\\tthis.fogDensityId = scope.resolve(\\\"fog_density\\\");\\n\\t\\tthis.ambientId = scope.resolve(\\\"light_globalAmbient\\\");\\n\\t\\tthis.skyboxIntensityId = scope.resolve(\\\"skyboxIntensity\\\");\\n\\t\\tthis.cubeMapRotationMatrixId = scope.resolve(\\\"cubeMapRotationMatrix\\\");\\n\\t\\tthis.pcssDiskSamplesId = scope.resolve(\\\"pcssDiskSamples[0]\\\");\\n\\t\\tthis.pcssSphereSamplesId = scope.resolve(\\\"pcssSphereSamples[0]\\\");\\n\\t\\tthis.lightColorId = [];\\n\\t\\tthis.lightDir = [];\\n\\t\\tthis.lightDirId = [];\\n\\t\\tthis.lightShadowMapId = [];\\n\\t\\tthis.lightShadowMatrixId = [];\\n\\t\\tthis.lightShadowParamsId = [];\\n\\t\\tthis.lightShadowIntensity = [];\\n\\t\\tthis.lightRadiusId = [];\\n\\t\\tthis.lightPos = [];\\n\\t\\tthis.lightPosId = [];\\n\\t\\tthis.lightWidth = [];\\n\\t\\tthis.lightWidthId = [];\\n\\t\\tthis.lightHeight = [];\\n\\t\\tthis.lightHeightId = [];\\n\\t\\tthis.lightInAngleId = [];\\n\\t\\tthis.lightOutAngleId = [];\\n\\t\\tthis.lightCookieId = [];\\n\\t\\tthis.lightCookieIntId = [];\\n\\t\\tthis.lightCookieMatrixId = [];\\n\\t\\tthis.lightCookieOffsetId = [];\\n\\t\\tthis.lightShadowSearchAreaId = [];\\n\\t\\tthis.lightCameraParamsId = [];\\n\\t\\tthis.lightSoftShadowParamsId = [];\\n\\t\\tthis.shadowMatrixPaletteId = [];\\n\\t\\tthis.shadowCascadeDistancesId = [];\\n\\t\\tthis.shadowCascadeCountId = [];\\n\\t\\tthis.shadowCascadeBlendId = [];\\n\\t\\tthis.screenSizeId = scope.resolve(\\\"uScreenSize\\\");\\n\\t\\tthis._screenSize = new Float32Array(4);\\n\\t\\tthis.fogColor = new Float32Array(3);\\n\\t\\tthis.ambientColor = new Float32Array(3);\\n\\t\\tthis.pcssDiskSamples = vogelDiskPrecalculationSamples(16);\\n\\t\\tthis.pcssSphereSamples = vogelSpherePrecalculationSamples(16);\\n\\t}\\n\\tdestroy() {\\n\\t\\tsuper.destroy();\\n\\t}\\n\\tdispatchGlobalLights(scene) {\\n\\t\\tconst ambientUniform = this.ambientColor;\\n\\t\\ttmpColor$1.linear(scene.ambientLight);\\n\\t\\tambientUniform[0] = tmpColor$1.r;\\n\\t\\tambientUniform[1] = tmpColor$1.g;\\n\\t\\tambientUniform[2] = tmpColor$1.b;\\n\\t\\tif (scene.physicalUnits) {\\n\\t\\t\\tfor (let i = 0; i < 3; i++) {\\n\\t\\t\\t\\tambientUniform[i] *= scene.ambientLuminance;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.ambientId.setValue(ambientUniform);\\n\\t\\tthis.skyboxIntensityId.setValue(scene.physicalUnits ? scene.skyboxLuminance : scene.skyboxIntensity);\\n\\t\\tthis.cubeMapRotationMatrixId.setValue(scene._skyboxRotationMat3.data);\\n\\t}\\n\\t_resolveLight(scope, i) {\\n\\t\\tconst light = `light${i}`;\\n\\t\\tthis.lightColorId[i] = scope.resolve(`${light}_color`);\\n\\t\\tthis.lightDir[i] = new Float32Array(3);\\n\\t\\tthis.lightDirId[i] = scope.resolve(`${light}_direction`);\\n\\t\\tthis.lightShadowMapId[i] = scope.resolve(`${light}_shadowMap`);\\n\\t\\tthis.lightShadowMatrixId[i] = scope.resolve(`${light}_shadowMatrix`);\\n\\t\\tthis.lightShadowParamsId[i] = scope.resolve(`${light}_shadowParams`);\\n\\t\\tthis.lightShadowIntensity[i] = scope.resolve(`${light}_shadowIntensity`);\\n\\t\\tthis.lightShadowSearchAreaId[i] = scope.resolve(`${light}_shadowSearchArea`);\\n\\t\\tthis.lightRadiusId[i] = scope.resolve(`${light}_radius`);\\n\\t\\tthis.lightPos[i] = new Float32Array(3);\\n\\t\\tthis.lightPosId[i] = scope.resolve(`${light}_position`);\\n\\t\\tthis.lightWidth[i] = new Float32Array(3);\\n\\t\\tthis.lightWidthId[i] = scope.resolve(`${light}_halfWidth`);\\n\\t\\tthis.lightHeight[i] = new Float32Array(3);\\n\\t\\tthis.lightHeightId[i] = scope.resolve(`${light}_halfHeight`);\\n\\t\\tthis.lightInAngleId[i] = scope.resolve(`${light}_innerConeAngle`);\\n\\t\\tthis.lightOutAngleId[i] = scope.resolve(`${light}_outerConeAngle`);\\n\\t\\tthis.lightCookieId[i] = scope.resolve(`${light}_cookie`);\\n\\t\\tthis.lightCookieIntId[i] = scope.resolve(`${light}_cookieIntensity`);\\n\\t\\tthis.lightCookieMatrixId[i] = scope.resolve(`${light}_cookieMatrix`);\\n\\t\\tthis.lightCookieOffsetId[i] = scope.resolve(`${light}_cookieOffset`);\\n\\t\\tthis.lightCameraParamsId[i] = scope.resolve(`${light}_cameraParams`);\\n\\t\\tthis.lightSoftShadowParamsId[i] = scope.resolve(`${light}_softShadowParams`);\\n\\t\\tthis.shadowMatrixPaletteId[i] = scope.resolve(`${light}_shadowMatrixPalette[0]`);\\n\\t\\tthis.shadowCascadeDistancesId[i] = scope.resolve(`${light}_shadowCascadeDistances`);\\n\\t\\tthis.shadowCascadeCountId[i] = scope.resolve(`${light}_shadowCascadeCount`);\\n\\t\\tthis.shadowCascadeBlendId[i] = scope.resolve(`${light}_shadowCascadeBlend`);\\n\\t}\\n\\tsetLTCDirectionalLight(wtm, cnt, dir, campos, far) {\\n\\t\\tthis.lightPos[cnt][0] = campos.x - dir.x * far;\\n\\t\\tthis.lightPos[cnt][1] = campos.y - dir.y * far;\\n\\t\\tthis.lightPos[cnt][2] = campos.z - dir.z * far;\\n\\t\\tthis.lightPosId[cnt].setValue(this.lightPos[cnt]);\\n\\t\\tconst hWidth = wtm.transformVector(new Vec3(-0.5, 0, 0));\\n\\t\\tthis.lightWidth[cnt][0] = hWidth.x * far;\\n\\t\\tthis.lightWidth[cnt][1] = hWidth.y * far;\\n\\t\\tthis.lightWidth[cnt][2] = hWidth.z * far;\\n\\t\\tthis.lightWidthId[cnt].setValue(this.lightWidth[cnt]);\\n\\t\\tconst hHeight = wtm.transformVector(new Vec3(0, 0, 0.5));\\n\\t\\tthis.lightHeight[cnt][0] = hHeight.x * far;\\n\\t\\tthis.lightHeight[cnt][1] = hHeight.y * far;\\n\\t\\tthis.lightHeight[cnt][2] = hHeight.z * far;\\n\\t\\tthis.lightHeightId[cnt].setValue(this.lightHeight[cnt]);\\n\\t}\\n\\tdispatchDirectLights(dirs, mask, camera) {\\n\\t\\tlet cnt = 0;\\n\\t\\tconst scope = this.device.scope;\\n\\t\\tfor (let i = 0; i < dirs.length; i++) {\\n\\t\\t\\tif (!(dirs[i].mask & mask)) continue;\\n\\t\\t\\tconst directional = dirs[i];\\n\\t\\t\\tconst wtm = directional._node.getWorldTransform();\\n\\t\\t\\tif (!this.lightColorId[cnt]) {\\n\\t\\t\\t\\tthis._resolveLight(scope, cnt);\\n\\t\\t\\t}\\n\\t\\t\\tthis.lightColorId[cnt].setValue(directional._colorLinear);\\n\\t\\t\\twtm.getY(directional._direction).mulScalar(-1);\\n\\t\\t\\tdirectional._direction.normalize();\\n\\t\\t\\tthis.lightDir[cnt][0] = directional._direction.x;\\n\\t\\t\\tthis.lightDir[cnt][1] = directional._direction.y;\\n\\t\\t\\tthis.lightDir[cnt][2] = directional._direction.z;\\n\\t\\t\\tthis.lightDirId[cnt].setValue(this.lightDir[cnt]);\\n\\t\\t\\tif (directional.shape !== LIGHTSHAPE_PUNCTUAL) {\\n\\t\\t\\t\\tthis.setLTCDirectionalLight(wtm, cnt, directional._direction, camera._node.getPosition(), camera.farClip);\\n\\t\\t\\t}\\n\\t\\t\\tif (directional.castShadows) {\\n\\t\\t\\t\\tconst lightRenderData = directional.getRenderData(camera, 0);\\n\\t\\t\\t\\tconst biases = directional._getUniformBiasValues(lightRenderData);\\n\\t\\t\\t\\tthis.lightShadowMapId[cnt].setValue(lightRenderData.shadowBuffer);\\n\\t\\t\\t\\tthis.lightShadowMatrixId[cnt].setValue(lightRenderData.shadowMatrix.data);\\n\\t\\t\\t\\tthis.shadowMatrixPaletteId[cnt].setValue(directional._shadowMatrixPalette);\\n\\t\\t\\t\\tthis.shadowCascadeDistancesId[cnt].setValue(directional._shadowCascadeDistances);\\n\\t\\t\\t\\tthis.shadowCascadeCountId[cnt].setValue(directional.numCascades);\\n\\t\\t\\t\\tthis.shadowCascadeBlendId[cnt].setValue(1 - directional.cascadeBlend);\\n\\t\\t\\t\\tthis.lightShadowIntensity[cnt].setValue(directional.shadowIntensity);\\n\\t\\t\\t\\tthis.lightSoftShadowParamsId[cnt].setValue(directional._softShadowParams);\\n\\t\\t\\t\\tconst shadowRT = lightRenderData.shadowCamera.renderTarget;\\n\\t\\t\\t\\tif (shadowRT) {\\n\\t\\t\\t\\t\\tthis.lightShadowSearchAreaId[cnt].setValue(directional.penumbraSize / lightRenderData.shadowCamera.renderTarget.width * lightRenderData.projectionCompensation);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst cameraParams = directional._shadowCameraParams;\\n\\t\\t\\t\\tcameraParams.length = 4;\\n\\t\\t\\t\\tcameraParams[0] = 0;\\n\\t\\t\\t\\tcameraParams[1] = lightRenderData.shadowCamera._farClip;\\n\\t\\t\\t\\tcameraParams[2] = lightRenderData.shadowCamera._nearClip;\\n\\t\\t\\t\\tcameraParams[3] = 1;\\n\\t\\t\\t\\tthis.lightCameraParamsId[cnt].setValue(cameraParams);\\n\\t\\t\\t\\tconst params = directional._shadowRenderParams;\\n\\t\\t\\t\\tparams.length = 4;\\n\\t\\t\\t\\tparams[0] = directional._shadowResolution;\\n\\t\\t\\t\\tparams[1] = biases.normalBias;\\n\\t\\t\\t\\tparams[2] = biases.bias;\\n\\t\\t\\t\\tparams[3] = 0;\\n\\t\\t\\t\\tthis.lightShadowParamsId[cnt].setValue(params);\\n\\t\\t\\t}\\n\\t\\t\\tcnt++;\\n\\t\\t}\\n\\t\\treturn cnt;\\n\\t}\\n\\tsetLTCPositionalLight(wtm, cnt) {\\n\\t\\tconst hWidth = wtm.transformVector(new Vec3(-0.5, 0, 0));\\n\\t\\tthis.lightWidth[cnt][0] = hWidth.x;\\n\\t\\tthis.lightWidth[cnt][1] = hWidth.y;\\n\\t\\tthis.lightWidth[cnt][2] = hWidth.z;\\n\\t\\tthis.lightWidthId[cnt].setValue(this.lightWidth[cnt]);\\n\\t\\tconst hHeight = wtm.transformVector(new Vec3(0, 0, 0.5));\\n\\t\\tthis.lightHeight[cnt][0] = hHeight.x;\\n\\t\\tthis.lightHeight[cnt][1] = hHeight.y;\\n\\t\\tthis.lightHeight[cnt][2] = hHeight.z;\\n\\t\\tthis.lightHeightId[cnt].setValue(this.lightHeight[cnt]);\\n\\t}\\n\\tdispatchOmniLight(scope, omni, cnt) {\\n\\t\\tconst wtm = omni._node.getWorldTransform();\\n\\t\\tif (!this.lightColorId[cnt]) {\\n\\t\\t\\tthis._resolveLight(scope, cnt);\\n\\t\\t}\\n\\t\\tthis.lightRadiusId[cnt].setValue(omni.attenuationEnd);\\n\\t\\tthis.lightColorId[cnt].setValue(omni._colorLinear);\\n\\t\\twtm.getTranslation(omni._position);\\n\\t\\tthis.lightPos[cnt][0] = omni._position.x;\\n\\t\\tthis.lightPos[cnt][1] = omni._position.y;\\n\\t\\tthis.lightPos[cnt][2] = omni._position.z;\\n\\t\\tthis.lightPosId[cnt].setValue(this.lightPos[cnt]);\\n\\t\\tif (omni.shape !== LIGHTSHAPE_PUNCTUAL) {\\n\\t\\t\\tthis.setLTCPositionalLight(wtm, cnt);\\n\\t\\t}\\n\\t\\tif (omni.castShadows) {\\n\\t\\t\\tconst lightRenderData = omni.getRenderData(null, 0);\\n\\t\\t\\tthis.lightShadowMapId[cnt].setValue(lightRenderData.shadowBuffer);\\n\\t\\t\\tconst biases = omni._getUniformBiasValues(lightRenderData);\\n\\t\\t\\tconst params = omni._shadowRenderParams;\\n\\t\\t\\tparams.length = 4;\\n\\t\\t\\tparams[0] = omni._shadowResolution;\\n\\t\\t\\tparams[1] = biases.normalBias;\\n\\t\\t\\tparams[2] = biases.bias;\\n\\t\\t\\tparams[3] = 1 / omni.attenuationEnd;\\n\\t\\t\\tthis.lightShadowParamsId[cnt].setValue(params);\\n\\t\\t\\tthis.lightShadowIntensity[cnt].setValue(omni.shadowIntensity);\\n\\t\\t\\tconst pixelsPerMeter = omni.penumbraSize / lightRenderData.shadowCamera.renderTarget.width;\\n\\t\\t\\tthis.lightShadowSearchAreaId[cnt].setValue(pixelsPerMeter);\\n\\t\\t\\tconst cameraParams = omni._shadowCameraParams;\\n\\t\\t\\tcameraParams.length = 4;\\n\\t\\t\\tcameraParams[0] = 0;\\n\\t\\t\\tcameraParams[1] = lightRenderData.shadowCamera._farClip;\\n\\t\\t\\tcameraParams[2] = lightRenderData.shadowCamera._nearClip;\\n\\t\\t\\tcameraParams[3] = 0;\\n\\t\\t\\tthis.lightCameraParamsId[cnt].setValue(cameraParams);\\n\\t\\t}\\n\\t\\tif (omni._cookie) {\\n\\t\\t\\tthis.lightCookieId[cnt].setValue(omni._cookie);\\n\\t\\t\\tthis.lightShadowMatrixId[cnt].setValue(wtm.data);\\n\\t\\t\\tthis.lightCookieIntId[cnt].setValue(omni.cookieIntensity);\\n\\t\\t}\\n\\t}\\n\\tdispatchSpotLight(scope, spot, cnt) {\\n\\t\\tconst wtm = spot._node.getWorldTransform();\\n\\t\\tif (!this.lightColorId[cnt]) {\\n\\t\\t\\tthis._resolveLight(scope, cnt);\\n\\t\\t}\\n\\t\\tthis.lightInAngleId[cnt].setValue(spot._innerConeAngleCos);\\n\\t\\tthis.lightOutAngleId[cnt].setValue(spot._outerConeAngleCos);\\n\\t\\tthis.lightRadiusId[cnt].setValue(spot.attenuationEnd);\\n\\t\\tthis.lightColorId[cnt].setValue(spot._colorLinear);\\n\\t\\twtm.getTranslation(spot._position);\\n\\t\\tthis.lightPos[cnt][0] = spot._position.x;\\n\\t\\tthis.lightPos[cnt][1] = spot._position.y;\\n\\t\\tthis.lightPos[cnt][2] = spot._position.z;\\n\\t\\tthis.lightPosId[cnt].setValue(this.lightPos[cnt]);\\n\\t\\tif (spot.shape !== LIGHTSHAPE_PUNCTUAL) {\\n\\t\\t\\tthis.setLTCPositionalLight(wtm, cnt);\\n\\t\\t}\\n\\t\\twtm.getY(spot._direction).mulScalar(-1);\\n\\t\\tspot._direction.normalize();\\n\\t\\tthis.lightDir[cnt][0] = spot._direction.x;\\n\\t\\tthis.lightDir[cnt][1] = spot._direction.y;\\n\\t\\tthis.lightDir[cnt][2] = spot._direction.z;\\n\\t\\tthis.lightDirId[cnt].setValue(this.lightDir[cnt]);\\n\\t\\tif (spot.castShadows) {\\n\\t\\t\\tconst lightRenderData = spot.getRenderData(null, 0);\\n\\t\\t\\tthis.lightShadowMapId[cnt].setValue(lightRenderData.shadowBuffer);\\n\\t\\t\\tthis.lightShadowMatrixId[cnt].setValue(lightRenderData.shadowMatrix.data);\\n\\t\\t\\tconst biases = spot._getUniformBiasValues(lightRenderData);\\n\\t\\t\\tconst params = spot._shadowRenderParams;\\n\\t\\t\\tparams.length = 4;\\n\\t\\t\\tparams[0] = spot._shadowResolution;\\n\\t\\t\\tparams[1] = biases.normalBias;\\n\\t\\t\\tparams[2] = biases.bias;\\n\\t\\t\\tparams[3] = 1 / spot.attenuationEnd;\\n\\t\\t\\tthis.lightShadowParamsId[cnt].setValue(params);\\n\\t\\t\\tthis.lightShadowIntensity[cnt].setValue(spot.shadowIntensity);\\n\\t\\t\\tconst pixelsPerMeter = spot.penumbraSize / lightRenderData.shadowCamera.renderTarget.width;\\n\\t\\t\\tconst fov = lightRenderData.shadowCamera._fov * math.DEG_TO_RAD;\\n\\t\\t\\tconst fovRatio = 1 / Math.tan(fov / 2);\\n\\t\\t\\tthis.lightShadowSearchAreaId[cnt].setValue(pixelsPerMeter * fovRatio);\\n\\t\\t\\tconst cameraParams = spot._shadowCameraParams;\\n\\t\\t\\tcameraParams.length = 4;\\n\\t\\t\\tcameraParams[0] = 0;\\n\\t\\t\\tcameraParams[1] = lightRenderData.shadowCamera._farClip;\\n\\t\\t\\tcameraParams[2] = lightRenderData.shadowCamera._nearClip;\\n\\t\\t\\tcameraParams[3] = 0;\\n\\t\\t\\tthis.lightCameraParamsId[cnt].setValue(cameraParams);\\n\\t\\t}\\n\\t\\tif (spot._cookie) {\\n\\t\\t\\tif (!spot.castShadows) {\\n\\t\\t\\t\\tconst cookieMatrix = LightCamera.evalSpotCookieMatrix(spot);\\n\\t\\t\\t\\tthis.lightShadowMatrixId[cnt].setValue(cookieMatrix.data);\\n\\t\\t\\t}\\n\\t\\t\\tthis.lightCookieId[cnt].setValue(spot._cookie);\\n\\t\\t\\tthis.lightCookieIntId[cnt].setValue(spot.cookieIntensity);\\n\\t\\t\\tif (spot._cookieTransform) {\\n\\t\\t\\t\\tspot._cookieTransformUniform[0] = spot._cookieTransform.x;\\n\\t\\t\\t\\tspot._cookieTransformUniform[1] = spot._cookieTransform.y;\\n\\t\\t\\t\\tspot._cookieTransformUniform[2] = spot._cookieTransform.z;\\n\\t\\t\\t\\tspot._cookieTransformUniform[3] = spot._cookieTransform.w;\\n\\t\\t\\t\\tthis.lightCookieMatrixId[cnt].setValue(spot._cookieTransformUniform);\\n\\t\\t\\t\\tspot._cookieOffsetUniform[0] = spot._cookieOffset.x;\\n\\t\\t\\t\\tspot._cookieOffsetUniform[1] = spot._cookieOffset.y;\\n\\t\\t\\t\\tthis.lightCookieOffsetId[cnt].setValue(spot._cookieOffsetUniform);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tdispatchLocalLights(sortedLights, mask, usedDirLights) {\\n\\t\\tlet cnt = usedDirLights;\\n\\t\\tconst scope = this.device.scope;\\n\\t\\tconst omnis = sortedLights[LIGHTTYPE_OMNI];\\n\\t\\tconst numOmnis = omnis.length;\\n\\t\\tfor (let i = 0; i < numOmnis; i++) {\\n\\t\\t\\tconst omni = omnis[i];\\n\\t\\t\\tif (!(omni.mask & mask)) continue;\\n\\t\\t\\tthis.dispatchOmniLight(scope, omni, cnt);\\n\\t\\t\\tcnt++;\\n\\t\\t}\\n\\t\\tconst spts = sortedLights[LIGHTTYPE_SPOT];\\n\\t\\tconst numSpts = spts.length;\\n\\t\\tfor (let i = 0; i < numSpts; i++) {\\n\\t\\t\\tconst spot = spts[i];\\n\\t\\t\\tif (!(spot.mask & mask)) continue;\\n\\t\\t\\tthis.dispatchSpotLight(scope, spot, cnt);\\n\\t\\t\\tcnt++;\\n\\t\\t}\\n\\t}\\n\\t// execute first pass over draw calls, in order to update materials / shaders\\n\\trenderForwardPrepareMaterials(camera, renderTarget, drawCalls, sortedLights, layer, pass) {\\n\\t\\tconst fogParams = camera.fogParams ?? this.scene.fog;\\n\\t\\tconst shaderParams = camera.shaderParams;\\n\\t\\tshaderParams.fog = fogParams.type;\\n\\t\\tshaderParams.srgbRenderTarget = renderTarget?.isColorBufferSrgb(0) ?? false;\\n\\t\\tconst addCall = (drawCall, shaderInstance, isNewMaterial, lightMaskChanged) => {\\n\\t\\t\\t_drawCallList.drawCalls.push(drawCall);\\n\\t\\t\\t_drawCallList.shaderInstances.push(shaderInstance);\\n\\t\\t\\t_drawCallList.isNewMaterial.push(isNewMaterial);\\n\\t\\t\\t_drawCallList.lightMaskChanged.push(lightMaskChanged);\\n\\t\\t};\\n\\t\\t_drawCallList.clear();\\n\\t\\tconst device = this.device;\\n\\t\\tconst scene = this.scene;\\n\\t\\tconst clusteredLightingEnabled = scene.clusteredLightingEnabled;\\n\\t\\tconst lightHash = layer?.getLightHash(clusteredLightingEnabled) ?? 0;\\n\\t\\tlet prevMaterial = null, prevObjDefs, prevLightMask;\\n\\t\\tconst drawCallsCount = drawCalls.length;\\n\\t\\tfor (let i = 0; i < drawCallsCount; i++) {\\n\\t\\t\\tconst drawCall = drawCalls[i];\\n\\t\\t\\tconst instancingData = drawCall.instancingData;\\n\\t\\t\\tif (instancingData && instancingData.count <= 0) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tdrawCall.ensureMaterial(device);\\n\\t\\t\\tconst material = drawCall.material;\\n\\t\\t\\tconst objDefs = drawCall._shaderDefs;\\n\\t\\t\\tconst lightMask = drawCall.mask;\\n\\t\\t\\tif (material && material === prevMaterial && objDefs !== prevObjDefs) {\\n\\t\\t\\t\\tprevMaterial = null;\\n\\t\\t\\t}\\n\\t\\t\\tif (material !== prevMaterial) {\\n\\t\\t\\t\\tthis._materialSwitches++;\\n\\t\\t\\t\\tmaterial._scene = scene;\\n\\t\\t\\t\\tif (material.dirty) {\\n\\t\\t\\t\\t\\tmaterial.updateUniforms(device, scene);\\n\\t\\t\\t\\t\\tmaterial.dirty = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tconst shaderInstance = drawCall.getShaderInstance(pass, lightHash, scene, shaderParams, this.viewUniformFormat, this.viewBindGroupFormat, sortedLights);\\n\\t\\t\\taddCall(drawCall, shaderInstance, material !== prevMaterial, !prevMaterial || lightMask !== prevLightMask);\\n\\t\\t\\tprevMaterial = material;\\n\\t\\t\\tprevObjDefs = objDefs;\\n\\t\\t\\tprevLightMask = lightMask;\\n\\t\\t}\\n\\t\\treturn _drawCallList;\\n\\t}\\n\\trenderForwardInternal(camera, preparedCalls, sortedLights, pass, drawCallback, flipFaces, viewBindGroups) {\\n\\t\\tconst device = this.device;\\n\\t\\tconst scene = this.scene;\\n\\t\\tconst passFlag = 1 << pass;\\n\\t\\tconst flipFactor = flipFaces ? -1 : 1;\\n\\t\\tconst clusteredLightingEnabled = scene.clusteredLightingEnabled;\\n\\t\\tconst viewList = camera.xr?.session && camera.xr.views.list.length ? camera.xr.views.list : null;\\n\\t\\tconst activeView = device.xrCurrentViewIndex ?? -1;\\n\\t\\tconst viewListStart = viewList && activeView >= 0 ? activeView : 0;\\n\\t\\tconst viewListEnd = viewList && activeView >= 0 ? activeView + 1 : viewList ? viewList.length : 0;\\n\\t\\tconst preparedCallsCount = preparedCalls.drawCalls.length;\\n\\t\\tfor (let i = 0; i < preparedCallsCount; i++) {\\n\\t\\t\\tconst drawCall = preparedCalls.drawCalls[i];\\n\\t\\t\\tconst newMaterial = preparedCalls.isNewMaterial[i];\\n\\t\\t\\tconst lightMaskChanged = preparedCalls.lightMaskChanged[i];\\n\\t\\t\\tconst shaderInstance = preparedCalls.shaderInstances[i];\\n\\t\\t\\tconst material = drawCall.material;\\n\\t\\t\\tconst lightMask = drawCall.mask;\\n\\t\\t\\tif (shaderInstance.shader.failed) continue;\\n\\t\\t\\tif (newMaterial) {\\n\\t\\t\\t\\tconst asyncCompile = false;\\n\\t\\t\\t\\tdevice.setShader(shaderInstance.shader, asyncCompile);\\n\\t\\t\\t\\tmaterial.setParameters(device);\\n\\t\\t\\t\\tif (lightMaskChanged) {\\n\\t\\t\\t\\t\\tconst usedDirLights = this.dispatchDirectLights(sortedLights[LIGHTTYPE_DIRECTIONAL], lightMask, camera);\\n\\t\\t\\t\\t\\tif (!clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\t\\tthis.dispatchLocalLights(sortedLights, lightMask, usedDirLights);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.alphaTestId.setValue(material.alphaTest);\\n\\t\\t\\t\\tdevice.setBlendState(material.blendState);\\n\\t\\t\\t\\tdevice.setDepthState(material.depthState);\\n\\t\\t\\t\\tdevice.setAlphaToCoverage(material.alphaToCoverage);\\n\\t\\t\\t}\\n\\t\\t\\tthis.setupCullModeAndFrontFace(camera._cullFaces, flipFactor, drawCall);\\n\\t\\t\\tconst stencilFront = drawCall.stencilFront ?? material.stencilFront;\\n\\t\\t\\tconst stencilBack = drawCall.stencilBack ?? material.stencilBack;\\n\\t\\t\\tdevice.setStencilState(stencilFront, stencilBack);\\n\\t\\t\\tdrawCall.setParameters(device, passFlag);\\n\\t\\t\\tdevice.scope.resolve(\\\"meshInstanceId\\\").setValue(drawCall.id);\\n\\t\\t\\tconst mesh = drawCall.mesh;\\n\\t\\t\\tthis.setVertexBuffers(device, mesh);\\n\\t\\t\\tthis.setMorphing(device, drawCall.morphInstance);\\n\\t\\t\\tthis.setSkinning(device, drawCall);\\n\\t\\t\\tconst instancingData = drawCall.instancingData;\\n\\t\\t\\tif (instancingData) {\\n\\t\\t\\t\\tdevice.setVertexBuffer(instancingData.vertexBuffer);\\n\\t\\t\\t}\\n\\t\\t\\tthis.setMeshInstanceMatrices(drawCall, true);\\n\\t\\t\\tthis.setupMeshUniformBuffers(shaderInstance);\\n\\t\\t\\tconst style = drawCall.renderStyle;\\n\\t\\t\\tconst indexBuffer = mesh.indexBuffer[style];\\n\\t\\t\\tdrawCallback?.(drawCall, i);\\n\\t\\t\\tconst indirectData = drawCall.getDrawCommands(camera);\\n\\t\\t\\tif (viewList) {\\n\\t\\t\\t\\tfor (let v = viewListStart; v < viewListEnd; v++) {\\n\\t\\t\\t\\t\\tconst view = viewList[v];\\n\\t\\t\\t\\t\\tdevice.setViewport(view.viewport.x, view.viewport.y, view.viewport.z, view.viewport.w);\\n\\t\\t\\t\\t\\tif (device.supportsUniformBuffers) {\\n\\t\\t\\t\\t\\t\\tconst viewBindGroup = viewBindGroups[v];\\n\\t\\t\\t\\t\\t\\tdevice.setBindGroup(BINDGROUP_VIEW, viewBindGroup);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.setupViewUniforms(view, v);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tconst first = v === viewListStart;\\n\\t\\t\\t\\t\\tconst last = v === viewListEnd - 1;\\n\\t\\t\\t\\t\\tdevice.draw(mesh.primitive[style], indexBuffer, instancingData?.count, indirectData, first, last);\\n\\t\\t\\t\\t\\tthis._forwardDrawCalls++;\\n\\t\\t\\t\\t\\tif (drawCall.instancingData) {\\n\\t\\t\\t\\t\\t\\tthis._instancedDrawCalls++;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tdevice.draw(mesh.primitive[style], indexBuffer, instancingData?.count, indirectData);\\n\\t\\t\\t\\tthis._forwardDrawCalls++;\\n\\t\\t\\t\\tif (drawCall.instancingData) {\\n\\t\\t\\t\\t\\tthis._instancedDrawCalls++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (i < preparedCallsCount - 1 && !preparedCalls.isNewMaterial[i + 1]) {\\n\\t\\t\\t\\tmaterial.setParameters(device, drawCall.parameters);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\trenderForward(camera, renderTarget, allDrawCalls, sortedLights, pass, drawCallback, layer, flipFaces, viewBindGroups) {\\n\\t\\tconst preparedCalls = this.renderForwardPrepareMaterials(camera, renderTarget, allDrawCalls, sortedLights, layer, pass);\\n\\t\\tthis.renderForwardInternal(camera, preparedCalls, sortedLights, pass, drawCallback, flipFaces, viewBindGroups);\\n\\t\\t_drawCallList.clear();\\n\\t}\\n\\trenderForwardLayer(camera, renderTarget, layer, transparent, shaderPass, viewBindGroups, options = {}) {\\n\\t\\tconst { scene, device } = this;\\n\\t\\tconst clusteredLightingEnabled = scene.clusteredLightingEnabled;\\n\\t\\tthis.setupViewport(camera, renderTarget);\\n\\t\\tlet visible, splitLights;\\n\\t\\tif (layer) {\\n\\t\\t\\tlayer.sortVisible(camera, transparent);\\n\\t\\t\\tconst culledInstances = layer.getCulledInstances(camera);\\n\\t\\t\\tvisible = transparent ? culledInstances.transparent : culledInstances.opaque;\\n\\t\\t\\tscene.immediate.onPreRenderLayer(layer, visible, transparent);\\n\\t\\t\\tif (layer.requiresLightCube) {\\n\\t\\t\\t\\tthis.lightCube.update(scene.ambientLight, layer._lights);\\n\\t\\t\\t\\tthis.constantLightCube.setValue(this.lightCube.colors);\\n\\t\\t\\t}\\n\\t\\t\\tsplitLights = layer.splitLights;\\n\\t\\t} else {\\n\\t\\t\\tvisible = options.meshInstances;\\n\\t\\t\\tsplitLights = options.splitLights ?? _noLights;\\n\\t\\t}\\n\\t\\tif (clusteredLightingEnabled) {\\n\\t\\t\\tconst lightClusters = options.lightClusters ?? this.worldClustersAllocator.empty;\\n\\t\\t\\tlightClusters.activate();\\n\\t\\t\\tif (layer) {\\n\\t\\t\\t\\tif (!this.clustersDebugRendered && scene.lighting.debugLayer === layer.id) {\\n\\t\\t\\t\\t\\tthis.clustersDebugRendered = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tscene._activeCamera = camera;\\n\\t\\tconst fogParams = camera.fogParams ?? this.scene.fog;\\n\\t\\tthis.setFogConstants(fogParams);\\n\\t\\tconst viewList = this.setCameraUniforms(camera, renderTarget);\\n\\t\\tif (device.supportsUniformBuffers) {\\n\\t\\t\\tthis.setupViewUniformBuffers(viewBindGroups, this.viewUniformFormat, this.viewBindGroupFormat, viewList);\\n\\t\\t}\\n\\t\\tconst clearColor = options.clearColor ?? false;\\n\\t\\tconst clearDepth = options.clearDepth ?? false;\\n\\t\\tconst clearStencil = options.clearStencil ?? false;\\n\\t\\tif (clearColor || clearDepth || clearStencil) {\\n\\t\\t\\tthis.clear(camera, clearColor, clearDepth, clearStencil);\\n\\t\\t}\\n\\t\\tconst flipFaces = !!(camera._flipFaces ^ renderTarget?.flipY);\\n\\t\\tconst forwardDrawCalls = this._forwardDrawCalls;\\n\\t\\tthis.renderForward(\\n\\t\\t\\tcamera,\\n\\t\\t\\trenderTarget,\\n\\t\\t\\tvisible,\\n\\t\\t\\tsplitLights,\\n\\t\\t\\tshaderPass,\\n\\t\\t\\tnull,\\n\\t\\t\\tlayer,\\n\\t\\t\\tflipFaces,\\n\\t\\t\\tviewBindGroups\\n\\t\\t);\\n\\t\\tif (layer) {\\n\\t\\t\\tlayer._forwardDrawCalls += this._forwardDrawCalls - forwardDrawCalls;\\n\\t\\t}\\n\\t}\\n\\tsetFogConstants(fogParams) {\\n\\t\\tif (fogParams.type !== FOG_NONE) {\\n\\t\\t\\ttmpColor$1.linear(fogParams.color);\\n\\t\\t\\tconst fogUniform = this.fogColor;\\n\\t\\t\\tfogUniform[0] = tmpColor$1.r;\\n\\t\\t\\tfogUniform[1] = tmpColor$1.g;\\n\\t\\t\\tfogUniform[2] = tmpColor$1.b;\\n\\t\\t\\tthis.fogColorId.setValue(fogUniform);\\n\\t\\t\\tif (fogParams.type === FOG_LINEAR) {\\n\\t\\t\\t\\tthis.fogStartId.setValue(fogParams.start);\\n\\t\\t\\t\\tthis.fogEndId.setValue(fogParams.end);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.fogDensityId.setValue(fogParams.density);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tsetSceneConstants() {\\n\\t\\tconst scene = this.scene;\\n\\t\\tthis.dispatchGlobalLights(scene);\\n\\t\\tconst device = this.device;\\n\\t\\tthis._screenSize[0] = device.width;\\n\\t\\tthis._screenSize[1] = device.height;\\n\\t\\tthis._screenSize[2] = 1 / device.width;\\n\\t\\tthis._screenSize[3] = 1 / device.height;\\n\\t\\tthis.screenSizeId.setValue(this._screenSize);\\n\\t\\tthis.pcssDiskSamplesId.setValue(this.pcssDiskSamples);\\n\\t\\tthis.pcssSphereSamplesId.setValue(this.pcssSphereSamples);\\n\\t}\\n\\tbuildFrameGraph(frameGraph, layerComposition) {\\n\\t\\tconst scene = this.scene;\\n\\t\\tframeGraph.reset();\\n\\t\\tif (scene.clusteredLightingEnabled) {\\n\\t\\t\\tconst { shadowsEnabled, cookiesEnabled } = scene.lighting;\\n\\t\\t\\tthis._renderPassUpdateClustered.update(frameGraph, shadowsEnabled, cookiesEnabled, this.lights, this.localLights);\\n\\t\\t\\tframeGraph.addRenderPass(this._renderPassUpdateClustered);\\n\\t\\t} else {\\n\\t\\t\\tthis._shadowRendererLocal.buildNonClusteredRenderPasses(frameGraph, this.localLights);\\n\\t\\t}\\n\\t\\tlet startIndex = 0;\\n\\t\\tlet newStart = true;\\n\\t\\tlet renderTarget = null;\\n\\t\\tconst renderActions = layerComposition._renderActions;\\n\\t\\tfor (let i = startIndex; i < renderActions.length; i++) {\\n\\t\\t\\tconst renderAction = renderActions[i];\\n\\t\\t\\tconst { layer, camera } = renderAction;\\n\\t\\t\\tconst mv = this._isMultiview(camera);\\n\\t\\t\\tif (renderAction.useCameraPasses) {\\n\\t\\t\\t\\tif (mv) frameGraph.beginMultiView(this.device);\\n\\t\\t\\t\\tcamera.camera.framePasses.forEach((renderPass) => {\\n\\t\\t\\t\\t\\tframeGraph.addRenderPass(renderPass);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (mv) frameGraph.endMultiView();\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconst isDepthLayer = layer.id === LAYERID_DEPTH;\\n\\t\\t\\t\\tconst isGrabPass = isDepthLayer && (camera.renderSceneColorMap || camera.renderSceneDepthMap);\\n\\t\\t\\t\\tif (newStart) {\\n\\t\\t\\t\\t\\tnewStart = false;\\n\\t\\t\\t\\t\\tstartIndex = i;\\n\\t\\t\\t\\t\\trenderTarget = renderAction.renderTarget;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst nextRenderAction = renderActions[i + 1];\\n\\t\\t\\t\\tconst isNextLayerDepth = nextRenderAction ? !nextRenderAction.useCameraPasses && nextRenderAction.layer.id === LAYERID_DEPTH : false;\\n\\t\\t\\t\\tconst isNextLayerGrabPass = isNextLayerDepth && (camera.renderSceneColorMap || camera.renderSceneDepthMap);\\n\\t\\t\\t\\tconst nextNeedDirShadows = nextRenderAction ? nextRenderAction.firstCameraUse && this.cameraDirShadowLights.has(nextRenderAction.camera.camera) : false;\\n\\t\\t\\t\\tif (!nextRenderAction || nextRenderAction.renderTarget !== renderTarget || nextRenderAction.camera !== camera || nextNeedDirShadows || isNextLayerGrabPass || isGrabPass) {\\n\\t\\t\\t\\t\\tconst isDepthOnly = isDepthLayer && startIndex === i;\\n\\t\\t\\t\\t\\tif (mv && (camera.renderSceneColorMap || camera.renderSceneDepthMap || renderAction.triggerPostprocess && camera?.onPostprocessing)) ;\\n\\t\\t\\t\\t\\tif (mv) frameGraph.beginMultiView(this.device);\\n\\t\\t\\t\\t\\tif (!isDepthOnly) {\\n\\t\\t\\t\\t\\t\\tthis.addMainRenderPass(frameGraph, layerComposition, renderTarget, startIndex, i);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (isDepthLayer) {\\n\\t\\t\\t\\t\\t\\tif (camera.renderSceneColorMap) {\\n\\t\\t\\t\\t\\t\\t\\tconst colorGrabPass = camera.camera.renderPassColorGrab;\\n\\t\\t\\t\\t\\t\\t\\tcolorGrabPass.source = camera.renderTarget;\\n\\t\\t\\t\\t\\t\\t\\tframeGraph.addRenderPass(colorGrabPass);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (camera.renderSceneDepthMap) {\\n\\t\\t\\t\\t\\t\\t\\tframeGraph.addRenderPass(camera.camera.renderPassDepthGrab);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (renderAction.triggerPostprocess && camera?.onPostprocessing) {\\n\\t\\t\\t\\t\\t\\tconst renderPass = new FramePassPostprocessing(this.device, this, renderAction);\\n\\t\\t\\t\\t\\t\\tframeGraph.addRenderPass(renderPass);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (mv) frameGraph.endMultiView();\\n\\t\\t\\t\\t\\tnewStart = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_isMultiview(camera) {\\n\\t\\tconst xr = camera.camera?.xr;\\n\\t\\treturn this.device.isWebGPU && !!xr?.session && xr.views.list.length >= 2;\\n\\t}\\n\\taddMainRenderPass(frameGraph, layerComposition, renderTarget, startIndex, endIndex) {\\n\\t\\tconst renderPass = new RenderPassForward(this.device, layerComposition, this.scene, this);\\n\\t\\trenderPass.init(renderTarget);\\n\\t\\tconst renderActions = layerComposition._renderActions;\\n\\t\\tfor (let i = startIndex; i <= endIndex; i++) {\\n\\t\\t\\trenderPass.addRenderAction(renderActions[i]);\\n\\t\\t}\\n\\t\\tframeGraph.addRenderPass(renderPass);\\n\\t}\\n\\tupdate(comp) {\\n\\t\\tthis.frameUpdate();\\n\\t\\tthis.shadowRenderer.frameUpdate();\\n\\t\\tthis.scene._updateSkyMesh();\\n\\t\\tthis.updateLayerComposition(comp);\\n\\t\\tthis.collectLights(comp);\\n\\t\\tthis.beginFrame(comp);\\n\\t\\tthis.setSceneConstants();\\n\\t\\tthis.gsplatDirector?.update(comp);\\n\\t\\tthis.cullComposition(comp);\\n\\t\\tthis.gpuUpdate(this.processingMeshInstances);\\n\\t}\\n}\\n\\nlet layerCounter = 0;\\nconst lightKeys = [];\\nconst _tempMaterials = /* @__PURE__ */ new Set();\\nfunction sortManual(drawCallA, drawCallB) {\\n\\treturn drawCallA.drawOrder - drawCallB.drawOrder;\\n}\\nfunction sortMaterialMesh(drawCallA, drawCallB) {\\n\\tconst keyA = drawCallA._sortKeyForward;\\n\\tconst keyB = drawCallB._sortKeyForward;\\n\\tif (keyA === keyB) {\\n\\t\\treturn drawCallB.mesh.id - drawCallA.mesh.id;\\n\\t}\\n\\treturn keyB - keyA;\\n}\\nfunction sortBackToFront(drawCallA, drawCallB) {\\n\\treturn drawCallB._sortKeyDynamic - drawCallA._sortKeyDynamic;\\n}\\nfunction sortFrontToBack(drawCallA, drawCallB) {\\n\\treturn drawCallA._sortKeyDynamic - drawCallB._sortKeyDynamic;\\n}\\nconst sortCallbacks = [null, sortManual, sortMaterialMesh, sortBackToFront, sortFrontToBack];\\nclass CulledInstances {\\n\\topaque = [];\\n\\ttransparent = [];\\n}\\nclass Layer {\\n\\t// --- Identity ---\\n\\tid;\\n\\tname;\\n\\t// --- Enabled state & ref counting ---\\n\\t_enabled = true;\\n\\t_refCounter = 1;\\n\\t// --- Sorting ---\\n\\topaqueSortMode = SORTMODE_MATERIALMESH;\\n\\ttransparentSortMode = SORTMODE_BACK2FRONT;\\n\\tcustomSortCallback = null;\\n\\tcustomCalculateSortValues = null;\\n\\t// --- Clear flags ---\\n\\t_clearColorBuffer = false;\\n\\t_clearDepthBuffer = false;\\n\\t_clearStencilBuffer = false;\\n\\t// --- Enable / disable callbacks ---\\n\\tonEnable;\\n\\tonDisable;\\n\\t// --- Mesh instances & shadow casters ---\\n\\tmeshInstances = [];\\n\\tmeshInstancesSet = /* @__PURE__ */ new Set();\\n\\tshadowCasters = [];\\n\\tshadowCastersSet = /* @__PURE__ */ new Set();\\n\\t_visibleInstances = /* @__PURE__ */ new WeakMap();\\n\\t// --- Lights ---\\n\\t_lights = [];\\n\\t_lightsSet = /* @__PURE__ */ new Set();\\n\\t_clusteredLightsSet = /* @__PURE__ */ new Set();\\n\\t_splitLights = [[], [], []];\\n\\t_splitLightsDirty = true;\\n\\t_lightHash = 0;\\n\\t_lightHashDirty = false;\\n\\t_lightIdHash = 0;\\n\\t_lightIdHashDirty = false;\\n\\trequiresLightCube = false;\\n\\t// --- Cameras ---\\n\\tcameras = [];\\n\\tcamerasSet = /* @__PURE__ */ new Set();\\n\\t// --- GSplat ---\\n\\tgsplatPlacements = [];\\n\\tgsplatPlacementsSet = /* @__PURE__ */ new Set();\\n\\tgsplatShadowCasters = [];\\n\\tgsplatShadowCastersSet = /* @__PURE__ */ new Set();\\n\\tgsplatPlacementsDirty = true;\\n\\t// --- Composition / shader versioning ---\\n\\t_dirtyComposition = false;\\n\\t_shaderVersion = -1;\\n\\t// --- Profiler ---\\n\\tconstructor(options = {}) {\\n\\t\\tif (options.id !== void 0) {\\n\\t\\t\\tthis.id = options.id;\\n\\t\\t\\tlayerCounter = Math.max(this.id + 1, layerCounter);\\n\\t\\t} else {\\n\\t\\t\\tthis.id = layerCounter++;\\n\\t\\t}\\n\\t\\tthis.name = options.name;\\n\\t\\tthis._enabled = options.enabled ?? true;\\n\\t\\tthis._refCounter = this._enabled ? 1 : 0;\\n\\t\\tthis.opaqueSortMode = options.opaqueSortMode ?? SORTMODE_MATERIALMESH;\\n\\t\\tthis.transparentSortMode = options.transparentSortMode ?? SORTMODE_BACK2FRONT;\\n\\t\\tthis._clearColorBuffer = !!options.clearColorBuffer;\\n\\t\\tthis._clearDepthBuffer = !!options.clearDepthBuffer;\\n\\t\\tthis._clearStencilBuffer = !!options.clearStencilBuffer;\\n\\t\\tthis.onEnable = options.onEnable;\\n\\t\\tthis.onDisable = options.onDisable;\\n\\t\\tif (this._enabled && this.onEnable) {\\n\\t\\t\\tthis.onEnable();\\n\\t\\t}\\n\\t}\\n\\tset enabled(val) {\\n\\t\\tif (val !== this._enabled) {\\n\\t\\t\\tthis._dirtyComposition = true;\\n\\t\\t\\tthis.gsplatPlacementsDirty = true;\\n\\t\\t\\tthis._enabled = val;\\n\\t\\t\\tif (val) {\\n\\t\\t\\t\\tthis.incrementCounter();\\n\\t\\t\\t\\tif (this.onEnable) this.onEnable();\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.decrementCounter();\\n\\t\\t\\t\\tif (this.onDisable) this.onDisable();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget enabled() {\\n\\t\\treturn this._enabled;\\n\\t}\\n\\tset clearColorBuffer(val) {\\n\\t\\tthis._clearColorBuffer = val;\\n\\t\\tthis._dirtyComposition = true;\\n\\t}\\n\\tget clearColorBuffer() {\\n\\t\\treturn this._clearColorBuffer;\\n\\t}\\n\\tset clearDepthBuffer(val) {\\n\\t\\tthis._clearDepthBuffer = val;\\n\\t\\tthis._dirtyComposition = true;\\n\\t}\\n\\tget clearDepthBuffer() {\\n\\t\\treturn this._clearDepthBuffer;\\n\\t}\\n\\tset clearStencilBuffer(val) {\\n\\t\\tthis._clearStencilBuffer = val;\\n\\t\\tthis._dirtyComposition = true;\\n\\t}\\n\\tget clearStencilBuffer() {\\n\\t\\treturn this._clearStencilBuffer;\\n\\t}\\n\\tget hasClusteredLights() {\\n\\t\\treturn this._clusteredLightsSet.size > 0;\\n\\t}\\n\\tget clusteredLightsSet() {\\n\\t\\treturn this._clusteredLightsSet;\\n\\t}\\n\\tincrementCounter() {\\n\\t\\tif (this._refCounter === 0) {\\n\\t\\t\\tthis._enabled = true;\\n\\t\\t\\tif (this.onEnable) this.onEnable();\\n\\t\\t}\\n\\t\\tthis._refCounter++;\\n\\t}\\n\\tdecrementCounter() {\\n\\t\\tif (this._refCounter === 1) {\\n\\t\\t\\tthis._enabled = false;\\n\\t\\t\\tif (this.onDisable) this.onDisable();\\n\\t\\t} else if (this._refCounter === 0) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._refCounter--;\\n\\t}\\n\\taddGSplatPlacement(placement) {\\n\\t\\tif (!this.gsplatPlacementsSet.has(placement)) {\\n\\t\\t\\tthis.gsplatPlacements.push(placement);\\n\\t\\t\\tthis.gsplatPlacementsSet.add(placement);\\n\\t\\t\\tthis.gsplatPlacementsDirty = true;\\n\\t\\t}\\n\\t}\\n\\tremoveGSplatPlacement(placement) {\\n\\t\\tconst index = this.gsplatPlacements.indexOf(placement);\\n\\t\\tif (index >= 0) {\\n\\t\\t\\tthis.gsplatPlacements.splice(index, 1);\\n\\t\\t\\tthis.gsplatPlacementsSet.delete(placement);\\n\\t\\t\\tthis.gsplatPlacementsDirty = true;\\n\\t\\t}\\n\\t}\\n\\taddGSplatShadowCaster(placement) {\\n\\t\\tif (!this.gsplatShadowCastersSet.has(placement)) {\\n\\t\\t\\tthis.gsplatShadowCasters.push(placement);\\n\\t\\t\\tthis.gsplatShadowCastersSet.add(placement);\\n\\t\\t\\tthis.gsplatPlacementsDirty = true;\\n\\t\\t}\\n\\t}\\n\\tremoveGSplatShadowCaster(placement) {\\n\\t\\tconst index = this.gsplatShadowCasters.indexOf(placement);\\n\\t\\tif (index >= 0) {\\n\\t\\t\\tthis.gsplatShadowCasters.splice(index, 1);\\n\\t\\t\\tthis.gsplatShadowCastersSet.delete(placement);\\n\\t\\t\\tthis.gsplatPlacementsDirty = true;\\n\\t\\t}\\n\\t}\\n\\taddMeshInstances(meshInstances, skipShadowCasters) {\\n\\t\\tconst destMeshInstances = this.meshInstances;\\n\\t\\tconst destMeshInstancesSet = this.meshInstancesSet;\\n\\t\\tfor (let i = 0; i < meshInstances.length; i++) {\\n\\t\\t\\tconst mi = meshInstances[i];\\n\\t\\t\\tif (!destMeshInstancesSet.has(mi)) {\\n\\t\\t\\t\\tdestMeshInstances.push(mi);\\n\\t\\t\\t\\tdestMeshInstancesSet.add(mi);\\n\\t\\t\\t\\t_tempMaterials.add(mi.material);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (!skipShadowCasters) {\\n\\t\\t\\tthis.addShadowCasters(meshInstances);\\n\\t\\t}\\n\\t\\tif (_tempMaterials.size > 0) {\\n\\t\\t\\tconst sceneShaderVer = this._shaderVersion;\\n\\t\\t\\t_tempMaterials.forEach((mat) => {\\n\\t\\t\\t\\tif (sceneShaderVer >= 0 && mat._shaderVersion !== sceneShaderVer) {\\n\\t\\t\\t\\t\\tif (mat.getShaderVariant !== Material.prototype.getShaderVariant) {\\n\\t\\t\\t\\t\\t\\tmat.clearVariants();\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tmat._shaderVersion = sceneShaderVer;\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t\\t_tempMaterials.clear();\\n\\t\\t}\\n\\t}\\n\\tremoveMeshInstances(meshInstances, skipShadowCasters) {\\n\\t\\tconst destMeshInstances = this.meshInstances;\\n\\t\\tconst destMeshInstancesSet = this.meshInstancesSet;\\n\\t\\tfor (let i = 0; i < meshInstances.length; i++) {\\n\\t\\t\\tconst mi = meshInstances[i];\\n\\t\\t\\tif (destMeshInstancesSet.has(mi)) {\\n\\t\\t\\t\\tdestMeshInstancesSet.delete(mi);\\n\\t\\t\\t\\tconst j = destMeshInstances.indexOf(mi);\\n\\t\\t\\t\\tif (j >= 0) {\\n\\t\\t\\t\\t\\tdestMeshInstances.splice(j, 1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (!skipShadowCasters) {\\n\\t\\t\\tthis.removeShadowCasters(meshInstances);\\n\\t\\t}\\n\\t}\\n\\taddShadowCasters(meshInstances) {\\n\\t\\tconst shadowCasters = this.shadowCasters;\\n\\t\\tconst shadowCastersSet = this.shadowCastersSet;\\n\\t\\tfor (let i = 0; i < meshInstances.length; i++) {\\n\\t\\t\\tconst mi = meshInstances[i];\\n\\t\\t\\tif (mi.castShadow && !shadowCastersSet.has(mi)) {\\n\\t\\t\\t\\tshadowCastersSet.add(mi);\\n\\t\\t\\t\\tshadowCasters.push(mi);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tremoveShadowCasters(meshInstances) {\\n\\t\\tconst shadowCasters = this.shadowCasters;\\n\\t\\tconst shadowCastersSet = this.shadowCastersSet;\\n\\t\\tfor (let i = 0; i < meshInstances.length; i++) {\\n\\t\\t\\tconst mi = meshInstances[i];\\n\\t\\t\\tif (shadowCastersSet.has(mi)) {\\n\\t\\t\\t\\tshadowCastersSet.delete(mi);\\n\\t\\t\\t\\tconst j = shadowCasters.indexOf(mi);\\n\\t\\t\\t\\tif (j >= 0) {\\n\\t\\t\\t\\t\\tshadowCasters.splice(j, 1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tclearMeshInstances(skipShadowCasters = false) {\\n\\t\\tthis.meshInstances.length = 0;\\n\\t\\tthis.meshInstancesSet.clear();\\n\\t\\tif (!skipShadowCasters) {\\n\\t\\t\\tthis.shadowCasters.length = 0;\\n\\t\\t\\tthis.shadowCastersSet.clear();\\n\\t\\t}\\n\\t}\\n\\tmarkLightsDirty() {\\n\\t\\tthis._lightHashDirty = true;\\n\\t\\tthis._lightIdHashDirty = true;\\n\\t\\tthis._splitLightsDirty = true;\\n\\t}\\n\\thasLight(light) {\\n\\t\\treturn this._lightsSet.has(light);\\n\\t}\\n\\taddLight(light) {\\n\\t\\tconst l = light.light;\\n\\t\\tif (!this._lightsSet.has(l)) {\\n\\t\\t\\tthis._lightsSet.add(l);\\n\\t\\t\\tthis._lights.push(l);\\n\\t\\t\\tthis.markLightsDirty();\\n\\t\\t}\\n\\t\\tif (l.type !== LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\tthis._clusteredLightsSet.add(l);\\n\\t\\t}\\n\\t}\\n\\tremoveLight(light) {\\n\\t\\tconst l = light.light;\\n\\t\\tif (this._lightsSet.has(l)) {\\n\\t\\t\\tthis._lightsSet.delete(l);\\n\\t\\t\\tthis._lights.splice(this._lights.indexOf(l), 1);\\n\\t\\t\\tthis.markLightsDirty();\\n\\t\\t}\\n\\t\\tif (l.type !== LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\tthis._clusteredLightsSet.delete(l);\\n\\t\\t}\\n\\t}\\n\\tclearLights() {\\n\\t\\tthis._lightsSet.forEach((light) => light.removeLayer(this));\\n\\t\\tthis._lightsSet.clear();\\n\\t\\tthis._clusteredLightsSet.clear();\\n\\t\\tthis._lights.length = 0;\\n\\t\\tthis.markLightsDirty();\\n\\t}\\n\\tget splitLights() {\\n\\t\\tif (this._splitLightsDirty) {\\n\\t\\t\\tthis._splitLightsDirty = false;\\n\\t\\t\\tconst splitLights = this._splitLights;\\n\\t\\t\\tfor (let i = 0; i < splitLights.length; i++) {\\n\\t\\t\\t\\tsplitLights[i].length = 0;\\n\\t\\t\\t}\\n\\t\\t\\tconst lights = this._lights;\\n\\t\\t\\tfor (let i = 0; i < lights.length; i++) {\\n\\t\\t\\t\\tconst light = lights[i];\\n\\t\\t\\t\\tif (light.enabled) {\\n\\t\\t\\t\\t\\tsplitLights[light._type].push(light);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tfor (let i = 0; i < splitLights.length; i++) {\\n\\t\\t\\t\\tsplitLights[i].sort((a, b) => a.key - b.key);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn this._splitLights;\\n\\t}\\n\\tevaluateLightHash(localLights, directionalLights, useIds) {\\n\\t\\tlet hash = 0;\\n\\t\\tconst lights = this._lights;\\n\\t\\tfor (let i = 0; i < lights.length; i++) {\\n\\t\\t\\tconst isLocalLight = lights[i].type !== LIGHTTYPE_DIRECTIONAL;\\n\\t\\t\\tif (localLights && isLocalLight || directionalLights && !isLocalLight) {\\n\\t\\t\\t\\tlightKeys.push(useIds ? lights[i].id : lights[i].key);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (lightKeys.length > 0) {\\n\\t\\t\\tlightKeys.sort();\\n\\t\\t\\thash = hash32Fnv1a(lightKeys);\\n\\t\\t\\tlightKeys.length = 0;\\n\\t\\t}\\n\\t\\treturn hash;\\n\\t}\\n\\tgetLightHash(isClustered) {\\n\\t\\tif (this._lightHashDirty) {\\n\\t\\t\\tthis._lightHashDirty = false;\\n\\t\\t\\tthis._lightHash = this.evaluateLightHash(!isClustered, true, false);\\n\\t\\t}\\n\\t\\treturn this._lightHash;\\n\\t}\\n\\t// This is only used in clustered lighting mode\\n\\tgetLightIdHash() {\\n\\t\\tif (this._lightIdHashDirty) {\\n\\t\\t\\tthis._lightIdHashDirty = false;\\n\\t\\t\\tthis._lightIdHash = this.evaluateLightHash(true, false, true);\\n\\t\\t}\\n\\t\\treturn this._lightIdHash;\\n\\t}\\n\\taddCamera(camera) {\\n\\t\\tif (!this.camerasSet.has(camera.camera)) {\\n\\t\\t\\tthis.camerasSet.add(camera.camera);\\n\\t\\t\\tthis.cameras.push(camera);\\n\\t\\t\\tthis._dirtyComposition = true;\\n\\t\\t}\\n\\t}\\n\\tremoveCamera(camera) {\\n\\t\\tif (this.camerasSet.has(camera.camera)) {\\n\\t\\t\\tthis.camerasSet.delete(camera.camera);\\n\\t\\t\\tconst index = this.cameras.indexOf(camera);\\n\\t\\t\\tthis.cameras.splice(index, 1);\\n\\t\\t\\tthis._dirtyComposition = true;\\n\\t\\t}\\n\\t}\\n\\tclearCameras() {\\n\\t\\tthis.cameras.length = 0;\\n\\t\\tthis.camerasSet.clear();\\n\\t\\tthis._dirtyComposition = true;\\n\\t}\\n\\t_calculateSortDistances(drawCalls, camPos, camFwd) {\\n\\t\\tconst count = drawCalls.length;\\n\\t\\tconst { x: px, y: py, z: pz } = camPos;\\n\\t\\tconst { x: fx, y: fy, z: fz } = camFwd;\\n\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\tconst drawCall = drawCalls[i];\\n\\t\\t\\tlet zDist;\\n\\t\\t\\tif (drawCall.calculateSortDistance) {\\n\\t\\t\\t\\tzDist = drawCall.calculateSortDistance(drawCall, camPos, camFwd);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconst meshPos = drawCall.aabb.center;\\n\\t\\t\\t\\tzDist = (meshPos.x - px) * fx + (meshPos.y - py) * fy + (meshPos.z - pz) * fz;\\n\\t\\t\\t}\\n\\t\\t\\tconst bucket = drawCall._drawBucket * 1e9;\\n\\t\\t\\tdrawCall._sortKeyDynamic = bucket + zDist;\\n\\t\\t}\\n\\t}\\n\\tgetCulledInstances(camera) {\\n\\t\\tlet instances = this._visibleInstances.get(camera);\\n\\t\\tif (!instances) {\\n\\t\\t\\tinstances = new CulledInstances();\\n\\t\\t\\tthis._visibleInstances.set(camera, instances);\\n\\t\\t}\\n\\t\\treturn instances;\\n\\t}\\n\\tsortVisible(camera, transparent) {\\n\\t\\tconst sortMode = transparent ? this.transparentSortMode : this.opaqueSortMode;\\n\\t\\tif (sortMode === SORTMODE_NONE) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst culledInstances = this.getCulledInstances(camera);\\n\\t\\tconst instances = transparent ? culledInstances.transparent : culledInstances.opaque;\\n\\t\\tconst cameraNode = camera.node;\\n\\t\\tif (sortMode === SORTMODE_CUSTOM) {\\n\\t\\t\\tconst sortPos = cameraNode.getPosition();\\n\\t\\t\\tconst sortDir = cameraNode.forward;\\n\\t\\t\\tif (this.customCalculateSortValues) {\\n\\t\\t\\t\\tthis.customCalculateSortValues(instances, instances.length, sortPos, sortDir);\\n\\t\\t\\t}\\n\\t\\t\\tif (this.customSortCallback) {\\n\\t\\t\\t\\tinstances.sort(this.customSortCallback);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tif (sortMode === SORTMODE_BACK2FRONT || sortMode === SORTMODE_FRONT2BACK) {\\n\\t\\t\\t\\tconst sortPos = cameraNode.getPosition();\\n\\t\\t\\t\\tconst sortDir = cameraNode.forward;\\n\\t\\t\\t\\tthis._calculateSortDistances(instances, sortPos, sortDir);\\n\\t\\t\\t}\\n\\t\\t\\tinstances.sort(sortCallbacks[sortMode]);\\n\\t\\t}\\n\\t}\\n}\\n\\nconst cmpPriority = (a, b) => a.priority - b.priority;\\nconst sortPriority = (arr) => arr.sort(cmpPriority);\\n\\nclass LayerComposition extends EventHandler {\\n\\t// Composition can hold only 2 sublayers of each layer\\n\\tlayerList = [];\\n\\tlayerIdMap = /* @__PURE__ */ new Map();\\n\\tlayerNameMap = /* @__PURE__ */ new Map();\\n\\tlayerOpaqueIndexMap = /* @__PURE__ */ new Map();\\n\\tlayerTransparentIndexMap = /* @__PURE__ */ new Map();\\n\\tsubLayerList = [];\\n\\tsubLayerEnabled = [];\\n\\t// more granular control on top of layer.enabled (ANDed)\\n\\tcameras = [];\\n\\tcamerasSet = /* @__PURE__ */ new Set();\\n\\t_renderActions = [];\\n\\t_dirty = false;\\n\\tconstructor(name = \\\"Untitled\\\") {\\n\\t\\tsuper();\\n\\t\\tthis.name = name;\\n\\t\\tthis._opaqueOrder = {};\\n\\t\\tthis._transparentOrder = {};\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.destroyRenderActions();\\n\\t}\\n\\tdestroyRenderActions() {\\n\\t\\tthis._renderActions.forEach((ra) => ra.destroy());\\n\\t\\tthis._renderActions.length = 0;\\n\\t}\\n\\tmarkDirty() {\\n\\t\\tthis._dirty = true;\\n\\t}\\n\\t_update() {\\n\\t\\tconst len = this.layerList.length;\\n\\t\\tif (!this._dirty) {\\n\\t\\t\\tfor (let i = 0; i < len; i++) {\\n\\t\\t\\t\\tif (this.layerList[i]._dirtyComposition) {\\n\\t\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this._dirty) {\\n\\t\\t\\tthis._dirty = false;\\n\\t\\t\\tthis.cameras.length = 0;\\n\\t\\t\\tthis.camerasSet.clear();\\n\\t\\t\\tfor (let i = 0; i < len; i++) {\\n\\t\\t\\t\\tconst layer = this.layerList[i];\\n\\t\\t\\t\\tlayer._dirtyComposition = false;\\n\\t\\t\\t\\tfor (let j = 0; j < layer.cameras.length; j++) {\\n\\t\\t\\t\\t\\tconst cameraComponent = layer.cameras[j];\\n\\t\\t\\t\\t\\tif (!this.camerasSet.has(cameraComponent.camera)) {\\n\\t\\t\\t\\t\\t\\tthis.camerasSet.add(cameraComponent.camera);\\n\\t\\t\\t\\t\\t\\tthis.cameras.push(cameraComponent);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (this.cameras.length > 1) {\\n\\t\\t\\t\\tsortPriority(this.cameras);\\n\\t\\t\\t}\\n\\t\\t\\tlet renderActionCount = 0;\\n\\t\\t\\tthis.destroyRenderActions();\\n\\t\\t\\tfor (let i = 0; i < this.cameras.length; i++) {\\n\\t\\t\\t\\tconst camera = this.cameras[i];\\n\\t\\t\\t\\tif (camera.camera.framePasses.length > 0) {\\n\\t\\t\\t\\t\\tthis.addDummyRenderAction(renderActionCount, camera);\\n\\t\\t\\t\\t\\trenderActionCount++;\\n\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet cameraFirstRenderAction = true;\\n\\t\\t\\t\\tconst cameraFirstRenderActionIndex = renderActionCount;\\n\\t\\t\\t\\tlet lastRenderAction = null;\\n\\t\\t\\t\\tlet postProcessMarked = false;\\n\\t\\t\\t\\tfor (let j = 0; j < len; j++) {\\n\\t\\t\\t\\t\\tconst layer = this.layerList[j];\\n\\t\\t\\t\\t\\tconst isLayerEnabled = layer.enabled && this.subLayerEnabled[j];\\n\\t\\t\\t\\t\\tif (isLayerEnabled) {\\n\\t\\t\\t\\t\\t\\tif (layer.cameras.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\tif (camera.layers.indexOf(layer.id) >= 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!postProcessMarked && layer.id === camera.disablePostEffectsLayer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tpostProcessMarked = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tif (lastRenderAction) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlastRenderAction.triggerPostprocess = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst isTransparent = this.subLayerList[j];\\n\\t\\t\\t\\t\\t\\t\\t\\tlastRenderAction = this.addRenderAction(\\n\\t\\t\\t\\t\\t\\t\\t\\t\\trenderActionCount,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tlayer,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tisTransparent,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcamera,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tcameraFirstRenderAction,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tpostProcessMarked\\n\\t\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t\\t\\trenderActionCount++;\\n\\t\\t\\t\\t\\t\\t\\t\\tcameraFirstRenderAction = false;\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (cameraFirstRenderActionIndex < renderActionCount) {\\n\\t\\t\\t\\t\\tlastRenderAction.lastCameraUse = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!postProcessMarked && lastRenderAction) {\\n\\t\\t\\t\\t\\tlastRenderAction.triggerPostprocess = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (camera.renderTarget && camera.postEffectsEnabled) {\\n\\t\\t\\t\\t\\tthis.propagateRenderTarget(cameraFirstRenderActionIndex - 1, camera);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis._logRenderActions();\\n\\t\\t}\\n\\t}\\n\\tgetNextRenderAction(renderActionIndex) {\\n\\t\\tconst renderAction = new RenderAction();\\n\\t\\tthis._renderActions.push(renderAction);\\n\\t\\treturn renderAction;\\n\\t}\\n\\taddDummyRenderAction(renderActionIndex, camera) {\\n\\t\\tconst renderAction = this.getNextRenderAction(renderActionIndex);\\n\\t\\trenderAction.camera = camera;\\n\\t\\trenderAction.useCameraPasses = true;\\n\\t}\\n\\t// function adds new render action to a list, while trying to limit allocation and reuse already allocated objects\\n\\taddRenderAction(renderActionIndex, layer, isTransparent, camera, cameraFirstRenderAction, postProcessMarked) {\\n\\t\\tlet rt = layer.id !== LAYERID_DEPTH ? camera.renderTarget : null;\\n\\t\\tlet used = false;\\n\\t\\tconst renderActions = this._renderActions;\\n\\t\\tfor (let i = renderActionIndex - 1; i >= 0; i--) {\\n\\t\\t\\tif (renderActions[i].camera === camera && renderActions[i].renderTarget === rt) {\\n\\t\\t\\t\\tused = true;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (postProcessMarked && camera.postEffectsEnabled) {\\n\\t\\t\\trt = null;\\n\\t\\t}\\n\\t\\tconst renderAction = this.getNextRenderAction(renderActionIndex);\\n\\t\\trenderAction.triggerPostprocess = false;\\n\\t\\trenderAction.layer = layer;\\n\\t\\trenderAction.transparent = isTransparent;\\n\\t\\trenderAction.camera = camera;\\n\\t\\trenderAction.renderTarget = rt;\\n\\t\\trenderAction.firstCameraUse = cameraFirstRenderAction;\\n\\t\\trenderAction.lastCameraUse = false;\\n\\t\\tconst needsCameraClear = cameraFirstRenderAction || !used;\\n\\t\\tconst needsLayerClear = layer.clearColorBuffer || layer.clearDepthBuffer || layer.clearStencilBuffer;\\n\\t\\tif (needsCameraClear || needsLayerClear) {\\n\\t\\t\\trenderAction.setupClears(needsCameraClear ? camera : void 0, layer);\\n\\t\\t}\\n\\t\\treturn renderAction;\\n\\t}\\n\\t// executes when post-processing camera's render actions were created to propagate rendering to\\n\\t// render targets to previous camera as needed\\n\\tpropagateRenderTarget(startIndex, fromCamera) {\\n\\t\\tfor (let a = startIndex; a >= 0; a--) {\\n\\t\\t\\tconst ra = this._renderActions[a];\\n\\t\\t\\tconst layer = ra.layer;\\n\\t\\t\\tif (ra.renderTarget && layer.id !== LAYERID_DEPTH) {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\tif (layer.id === LAYERID_DEPTH) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tif (ra.useCameraPasses) {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\tconst thisCamera = ra?.camera.camera;\\n\\t\\t\\tif (thisCamera) {\\n\\t\\t\\t\\tif (!fromCamera.camera.rect.equals(thisCamera.rect) || !fromCamera.camera.scissorRect.equals(thisCamera.scissorRect)) {\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tra.renderTarget = fromCamera.renderTarget;\\n\\t\\t}\\n\\t}\\n\\t// logs render action and their properties\\n\\t_logRenderActions() {\\n\\t}\\n\\t_isLayerAdded(layer) {\\n\\t\\tconst found = this.layerIdMap.get(layer.id) === layer;\\n\\t\\treturn found;\\n\\t}\\n\\t_isSublayerAdded(layer, transparent) {\\n\\t\\tconst map = transparent ? this.layerTransparentIndexMap : this.layerOpaqueIndexMap;\\n\\t\\tif (map.get(layer) !== void 0) {\\n\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\treturn false;\\n\\t}\\n\\t// Whole layer API\\n\\tpush(layer) {\\n\\t\\tif (this._isLayerAdded(layer)) return;\\n\\t\\tthis.layerList.push(layer);\\n\\t\\tthis.layerList.push(layer);\\n\\t\\tthis._opaqueOrder[layer.id] = this.subLayerList.push(false) - 1;\\n\\t\\tthis._transparentOrder[layer.id] = this.subLayerList.push(true) - 1;\\n\\t\\tthis.subLayerEnabled.push(true);\\n\\t\\tthis.subLayerEnabled.push(true);\\n\\t\\tthis._updateLayerMaps();\\n\\t\\tthis._dirty = true;\\n\\t\\tthis.fire(\\\"add\\\", layer);\\n\\t}\\n\\tinsert(layer, index) {\\n\\t\\tif (this._isLayerAdded(layer)) return;\\n\\t\\tthis.layerList.splice(index, 0, layer, layer);\\n\\t\\tthis.subLayerList.splice(index, 0, false, true);\\n\\t\\tconst count = this.layerList.length;\\n\\t\\tthis._updateOpaqueOrder(index, count - 1);\\n\\t\\tthis._updateTransparentOrder(index, count - 1);\\n\\t\\tthis.subLayerEnabled.splice(index, 0, true, true);\\n\\t\\tthis._updateLayerMaps();\\n\\t\\tthis._dirty = true;\\n\\t\\tthis.fire(\\\"add\\\", layer);\\n\\t}\\n\\tremove(layer) {\\n\\t\\tlet id = this.layerList.indexOf(layer);\\n\\t\\tdelete this._opaqueOrder[id];\\n\\t\\tdelete this._transparentOrder[id];\\n\\t\\twhile (id >= 0) {\\n\\t\\t\\tthis.layerList.splice(id, 1);\\n\\t\\t\\tthis.subLayerList.splice(id, 1);\\n\\t\\t\\tthis.subLayerEnabled.splice(id, 1);\\n\\t\\t\\tid = this.layerList.indexOf(layer);\\n\\t\\t\\tthis._dirty = true;\\n\\t\\t\\tthis.fire(\\\"remove\\\", layer);\\n\\t\\t}\\n\\t\\tconst count = this.layerList.length;\\n\\t\\tthis._updateOpaqueOrder(0, count - 1);\\n\\t\\tthis._updateTransparentOrder(0, count - 1);\\n\\t\\tthis._updateLayerMaps();\\n\\t}\\n\\t// Sublayer API\\n\\tpushOpaque(layer) {\\n\\t\\tif (this._isSublayerAdded(layer, false)) return;\\n\\t\\tthis.layerList.push(layer);\\n\\t\\tthis._opaqueOrder[layer.id] = this.subLayerList.push(false) - 1;\\n\\t\\tthis.subLayerEnabled.push(true);\\n\\t\\tthis._updateLayerMaps();\\n\\t\\tthis._dirty = true;\\n\\t\\tthis.fire(\\\"add\\\", layer);\\n\\t}\\n\\tinsertOpaque(layer, index) {\\n\\t\\tif (this._isSublayerAdded(layer, false)) return;\\n\\t\\tthis.layerList.splice(index, 0, layer);\\n\\t\\tthis.subLayerList.splice(index, 0, false);\\n\\t\\tconst count = this.subLayerList.length;\\n\\t\\tthis._updateOpaqueOrder(index, count - 1);\\n\\t\\tthis.subLayerEnabled.splice(index, 0, true);\\n\\t\\tthis._updateLayerMaps();\\n\\t\\tthis._dirty = true;\\n\\t\\tthis.fire(\\\"add\\\", layer);\\n\\t}\\n\\tremoveOpaque(layer) {\\n\\t\\tfor (let i = 0, len = this.layerList.length; i < len; i++) {\\n\\t\\t\\tif (this.layerList[i] === layer && !this.subLayerList[i]) {\\n\\t\\t\\t\\tthis.layerList.splice(i, 1);\\n\\t\\t\\t\\tthis.subLayerList.splice(i, 1);\\n\\t\\t\\t\\tlen--;\\n\\t\\t\\t\\tthis._updateOpaqueOrder(i, len - 1);\\n\\t\\t\\t\\tthis.subLayerEnabled.splice(i, 1);\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t\\t\\tif (this.layerList.indexOf(layer) < 0) {\\n\\t\\t\\t\\t\\tthis.fire(\\\"remove\\\", layer);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._updateLayerMaps();\\n\\t}\\n\\tpushTransparent(layer) {\\n\\t\\tif (this._isSublayerAdded(layer, true)) return;\\n\\t\\tthis.layerList.push(layer);\\n\\t\\tthis._transparentOrder[layer.id] = this.subLayerList.push(true) - 1;\\n\\t\\tthis.subLayerEnabled.push(true);\\n\\t\\tthis._updateLayerMaps();\\n\\t\\tthis._dirty = true;\\n\\t\\tthis.fire(\\\"add\\\", layer);\\n\\t}\\n\\tinsertTransparent(layer, index) {\\n\\t\\tif (this._isSublayerAdded(layer, true)) return;\\n\\t\\tthis.layerList.splice(index, 0, layer);\\n\\t\\tthis.subLayerList.splice(index, 0, true);\\n\\t\\tconst count = this.subLayerList.length;\\n\\t\\tthis._updateTransparentOrder(index, count - 1);\\n\\t\\tthis.subLayerEnabled.splice(index, 0, true);\\n\\t\\tthis._updateLayerMaps();\\n\\t\\tthis._dirty = true;\\n\\t\\tthis.fire(\\\"add\\\", layer);\\n\\t}\\n\\tremoveTransparent(layer) {\\n\\t\\tfor (let i = 0, len = this.layerList.length; i < len; i++) {\\n\\t\\t\\tif (this.layerList[i] === layer && this.subLayerList[i]) {\\n\\t\\t\\t\\tthis.layerList.splice(i, 1);\\n\\t\\t\\t\\tthis.subLayerList.splice(i, 1);\\n\\t\\t\\t\\tlen--;\\n\\t\\t\\t\\tthis._updateTransparentOrder(i, len - 1);\\n\\t\\t\\t\\tthis.subLayerEnabled.splice(i, 1);\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t\\t\\tif (this.layerList.indexOf(layer) < 0) {\\n\\t\\t\\t\\t\\tthis.fire(\\\"remove\\\", layer);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._updateLayerMaps();\\n\\t}\\n\\tgetOpaqueIndex(layer) {\\n\\t\\treturn this.layerOpaqueIndexMap.get(layer) ?? -1;\\n\\t}\\n\\tgetTransparentIndex(layer) {\\n\\t\\treturn this.layerTransparentIndexMap.get(layer) ?? -1;\\n\\t}\\n\\tisEnabled(layer, transparent) {\\n\\t\\tif (layer.enabled) {\\n\\t\\t\\tconst index = transparent ? this.getTransparentIndex(layer) : this.getOpaqueIndex(layer);\\n\\t\\t\\tif (index >= 0) {\\n\\t\\t\\t\\treturn this.subLayerEnabled[index];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn false;\\n\\t}\\n\\t_updateLayerMaps() {\\n\\t\\tthis.layerIdMap.clear();\\n\\t\\tthis.layerNameMap.clear();\\n\\t\\tthis.layerOpaqueIndexMap.clear();\\n\\t\\tthis.layerTransparentIndexMap.clear();\\n\\t\\tfor (let i = 0; i < this.layerList.length; i++) {\\n\\t\\t\\tconst layer = this.layerList[i];\\n\\t\\t\\tthis.layerIdMap.set(layer.id, layer);\\n\\t\\t\\tthis.layerNameMap.set(layer.name, layer);\\n\\t\\t\\tconst subLayerIndexMap = this.subLayerList[i] ? this.layerTransparentIndexMap : this.layerOpaqueIndexMap;\\n\\t\\t\\tsubLayerIndexMap.set(layer, i);\\n\\t\\t}\\n\\t}\\n\\tgetLayerById(id) {\\n\\t\\treturn this.layerIdMap.get(id) ?? null;\\n\\t}\\n\\tgetLayerByName(name) {\\n\\t\\treturn this.layerNameMap.get(name) ?? null;\\n\\t}\\n\\t_updateOpaqueOrder(startIndex, endIndex) {\\n\\t\\tfor (let i = startIndex; i <= endIndex; i++) {\\n\\t\\t\\tif (this.subLayerList[i] === false) {\\n\\t\\t\\t\\tthis._opaqueOrder[this.layerList[i].id] = i;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_updateTransparentOrder(startIndex, endIndex) {\\n\\t\\tfor (let i = startIndex; i <= endIndex; i++) {\\n\\t\\t\\tif (this.subLayerList[i] === true) {\\n\\t\\t\\t\\tthis._transparentOrder[this.layerList[i].id] = i;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t// Used to determine which array of layers has any sublayer that is\\n\\t// on top of all the sublayers in the other array. The order is a dictionary\\n\\t// of <layerId, index>.\\n\\t_sortLayersDescending(layersA, layersB, order) {\\n\\t\\tlet topLayerA = -1;\\n\\t\\tlet topLayerB = -1;\\n\\t\\tfor (let i = 0, len = layersA.length; i < len; i++) {\\n\\t\\t\\tconst id = layersA[i];\\n\\t\\t\\tif (order.hasOwnProperty(id)) {\\n\\t\\t\\t\\ttopLayerA = Math.max(topLayerA, order[id]);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (let i = 0, len = layersB.length; i < len; i++) {\\n\\t\\t\\tconst id = layersB[i];\\n\\t\\t\\tif (order.hasOwnProperty(id)) {\\n\\t\\t\\t\\ttopLayerB = Math.max(topLayerB, order[id]);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (topLayerA === -1 && topLayerB !== -1) {\\n\\t\\t\\treturn 1;\\n\\t\\t} else if (topLayerB === -1 && topLayerA !== -1) {\\n\\t\\t\\treturn -1;\\n\\t\\t}\\n\\t\\treturn topLayerB - topLayerA;\\n\\t}\\n\\tsortTransparentLayers(layersA, layersB) {\\n\\t\\treturn this._sortLayersDescending(layersA, layersB, this._transparentOrder);\\n\\t}\\n\\tsortOpaqueLayers(layersA, layersB) {\\n\\t\\treturn this._sortLayersDescending(layersA, layersB, this._opaqueOrder);\\n\\t}\\n}\\n\\nconst tmpVec = new Vec3();\\nconst tmpBiases = {\\n\\tbias: 0,\\n\\tnormalBias: 0\\n};\\nconst tmpColor = new Color();\\nconst chanId = { r: 0, g: 1, b: 2, a: 3 };\\nconst lightTypes = {\\n\\t\\\"directional\\\": LIGHTTYPE_DIRECTIONAL,\\n\\t\\\"omni\\\": LIGHTTYPE_OMNI,\\n\\t\\\"point\\\": LIGHTTYPE_OMNI,\\n\\t\\\"spot\\\": LIGHTTYPE_SPOT\\n};\\nconst directionalCascades = [\\n\\t[new Vec4(0, 0, 1, 1)],\\n\\t[new Vec4(0, 0, 0.5, 0.5), new Vec4(0, 0.5, 0.5, 0.5)],\\n\\t[new Vec4(0, 0, 0.5, 0.5), new Vec4(0, 0.5, 0.5, 0.5), new Vec4(0.5, 0, 0.5, 0.5)],\\n\\t[new Vec4(0, 0, 0.5, 0.5), new Vec4(0, 0.5, 0.5, 0.5), new Vec4(0.5, 0, 0.5, 0.5), new Vec4(0.5, 0.5, 0.5, 0.5)]\\n];\\nconst channelMap = {\\n\\t\\\"rrr\\\": 1,\\n\\t\\\"ggg\\\": 2,\\n\\t\\\"bbb\\\": 4,\\n\\t\\\"aaa\\\": 8,\\n\\t\\\"rgb\\\": 7\\n};\\nlet id$2 = 0;\\nclass LightRenderData {\\n\\tconstructor(camera, face, light) {\\n\\t\\tthis.light = light;\\n\\t\\tthis.camera = camera;\\n\\t\\tthis.shadowCamera = ShadowRenderer.createShadowCamera(light.device, light._shadowType, light._type, face);\\n\\t\\tthis.shadowMatrix = new Mat4();\\n\\t\\tthis.shadowViewport = new Vec4(0, 0, 1, 1);\\n\\t\\tthis.shadowScissor = new Vec4(0, 0, 1, 1);\\n\\t\\tthis.projectionCompensation = 0;\\n\\t\\tthis.face = face;\\n\\t\\tthis.visibleCasters = [];\\n\\t\\tthis.viewBindGroups = [];\\n\\t}\\n\\t// releases GPU resources\\n\\tdestroy() {\\n\\t\\tthis.viewBindGroups.forEach((bg) => {\\n\\t\\t\\tbg.defaultUniformBuffer.destroy();\\n\\t\\t\\tbg.destroy();\\n\\t\\t});\\n\\t\\tthis.viewBindGroups.length = 0;\\n\\t}\\n\\t// returns shadow buffer currently attached to the shadow camera\\n\\tget shadowBuffer() {\\n\\t\\tconst rt = this.shadowCamera.renderTarget;\\n\\t\\tif (rt) {\\n\\t\\t\\treturn this.light._isPcf ? rt.depthBuffer : rt.colorBuffer;\\n\\t\\t}\\n\\t\\treturn null;\\n\\t}\\n}\\nclass Light {\\n\\tlayers = /* @__PURE__ */ new Set();\\n\\tclusteredLighting;\\n\\tshadowDepthState = DepthState.DEFAULT.clone();\\n\\tclusteredFlags = 0;\\n\\tclusteredData = new Uint32Array(3);\\n\\tclusteredData16 = new Uint16Array(this.clusteredData.buffer);\\n\\t_evtDeviceRestored = null;\\n\\tconstructor(graphicsDevice, clusteredLighting) {\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tthis.clusteredLighting = clusteredLighting;\\n\\t\\tthis.id = id$2++;\\n\\t\\tthis._evtDeviceRestored = graphicsDevice.on(\\\"devicerestored\\\", this.onDeviceRestored, this);\\n\\t\\tthis._type = LIGHTTYPE_DIRECTIONAL;\\n\\t\\tthis._color = new Color(0.8, 0.8, 0.8);\\n\\t\\tthis._intensity = 1;\\n\\t\\tthis._affectSpecularity = true;\\n\\t\\tthis._luminance = 0;\\n\\t\\tthis._castShadows = false;\\n\\t\\tthis._enabled = false;\\n\\t\\tthis._mask = MASK_AFFECT_DYNAMIC;\\n\\t\\tthis.isStatic = false;\\n\\t\\tthis.key = 0;\\n\\t\\tthis.bakeDir = true;\\n\\t\\tthis.bakeNumSamples = 1;\\n\\t\\tthis.bakeArea = 0;\\n\\t\\tthis.attenuationStart = 10;\\n\\t\\tthis.attenuationEnd = 10;\\n\\t\\tthis._falloffMode = LIGHTFALLOFF_LINEAR;\\n\\t\\tthis._shadowType = SHADOW_PCF3_32F;\\n\\t\\tthis._vsmBlurSize = 11;\\n\\t\\tthis.vsmBlurMode = BLUR_GAUSSIAN;\\n\\t\\tthis.vsmBias = 0.01 * 0.25;\\n\\t\\tthis._cookie = null;\\n\\t\\tthis.cookieIntensity = 1;\\n\\t\\tthis._cookieFalloff = true;\\n\\t\\tthis._cookieChannel = \\\"rgb\\\";\\n\\t\\tthis._cookieTransform = null;\\n\\t\\tthis._cookieTransformUniform = new Float32Array(4);\\n\\t\\tthis._cookieOffset = null;\\n\\t\\tthis._cookieOffsetUniform = new Float32Array(2);\\n\\t\\tthis._cookieTransformSet = false;\\n\\t\\tthis._cookieOffsetSet = false;\\n\\t\\tthis._innerConeAngle = 40;\\n\\t\\tthis._outerConeAngle = 45;\\n\\t\\tthis.cascades = null;\\n\\t\\tthis._shadowMatrixPalette = null;\\n\\t\\tthis._shadowCascadeDistances = null;\\n\\t\\tthis.numCascades = 1;\\n\\t\\tthis._cascadeBlend = 0;\\n\\t\\tthis.cascadeDistribution = 0.5;\\n\\t\\tthis._shape = LIGHTSHAPE_PUNCTUAL;\\n\\t\\tthis._colorLinear = new Float32Array(3);\\n\\t\\tthis._updateLinearColor();\\n\\t\\tthis._position = new Vec3(0, 0, 0);\\n\\t\\tthis._direction = new Vec3(0, 0, 0);\\n\\t\\tthis._innerConeAngleCos = Math.cos(this._innerConeAngle * math.DEG_TO_RAD);\\n\\t\\tthis._updateOuterAngle(this._outerConeAngle);\\n\\t\\tthis._usePhysicalUnits = void 0;\\n\\t\\tthis._shadowMap = null;\\n\\t\\tthis._shadowRenderParams = [];\\n\\t\\tthis._shadowCameraParams = [];\\n\\t\\tthis.shadowDistance = 40;\\n\\t\\tthis._shadowResolution = 1024;\\n\\t\\tthis._shadowBias = -5e-4;\\n\\t\\tthis._shadowIntensity = 1;\\n\\t\\tthis._normalOffsetBias = 0;\\n\\t\\tthis.shadowUpdateMode = SHADOWUPDATE_REALTIME;\\n\\t\\tthis.shadowUpdateOverrides = null;\\n\\t\\tthis._isVsm = false;\\n\\t\\tthis._isPcf = true;\\n\\t\\tthis._softShadowParams = new Float32Array(4);\\n\\t\\tthis.shadowSamples = 16;\\n\\t\\tthis.shadowBlockerSamples = 16;\\n\\t\\tthis.penumbraSize = 1;\\n\\t\\tthis.penumbraFalloff = 1;\\n\\t\\tthis._cookieMatrix = null;\\n\\t\\tthis._atlasViewport = null;\\n\\t\\tthis.atlasViewportAllocated = false;\\n\\t\\tthis.atlasVersion = 0;\\n\\t\\tthis.atlasSlotIndex = 0;\\n\\t\\tthis.atlasSlotUpdated = false;\\n\\t\\tthis._node = null;\\n\\t\\tthis._renderData = [];\\n\\t\\tthis.visibleThisFrame = false;\\n\\t\\tthis.maxScreenSize = 0;\\n\\t\\tthis._updateShadowBias();\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._evtDeviceRestored?.off();\\n\\t\\tthis._evtDeviceRestored = null;\\n\\t\\tthis._destroyShadowMap();\\n\\t\\tthis.releaseRenderData();\\n\\t\\tthis._renderData = null;\\n\\t}\\n\\tonDeviceRestored() {\\n\\t\\tif (this.shadowUpdateMode === SHADOWUPDATE_NONE) {\\n\\t\\t\\tthis.shadowUpdateMode = SHADOWUPDATE_THISFRAME;\\n\\t\\t}\\n\\t}\\n\\treleaseRenderData() {\\n\\t\\tif (this._renderData) {\\n\\t\\t\\tfor (let i = 0; i < this._renderData.length; i++) {\\n\\t\\t\\t\\tthis._renderData[i].destroy();\\n\\t\\t\\t}\\n\\t\\t\\tthis._renderData.length = 0;\\n\\t\\t}\\n\\t}\\n\\taddLayer(layer) {\\n\\t\\tthis.layers.add(layer);\\n\\t}\\n\\tremoveLayer(layer) {\\n\\t\\tthis.layers.delete(layer);\\n\\t}\\n\\tset shadowSamples(value) {\\n\\t\\tthis._softShadowParams[0] = value;\\n\\t}\\n\\tget shadowSamples() {\\n\\t\\treturn this._softShadowParams[0];\\n\\t}\\n\\tset shadowBlockerSamples(value) {\\n\\t\\tthis._softShadowParams[1] = value;\\n\\t}\\n\\tget shadowBlockerSamples() {\\n\\t\\treturn this._softShadowParams[1];\\n\\t}\\n\\tset shadowBias(value) {\\n\\t\\tif (this._shadowBias !== value) {\\n\\t\\t\\tthis._shadowBias = value;\\n\\t\\t\\tthis._updateShadowBias();\\n\\t\\t}\\n\\t}\\n\\tget shadowBias() {\\n\\t\\treturn this._shadowBias;\\n\\t}\\n\\tset numCascades(value) {\\n\\t\\tif (!this.cascades || this.numCascades !== value) {\\n\\t\\t\\tthis.cascades = directionalCascades[value - 1];\\n\\t\\t\\tthis._shadowMatrixPalette = new Float32Array(4 * 16);\\n\\t\\t\\tthis._shadowCascadeDistances = new Float32Array(4);\\n\\t\\t\\tthis._destroyShadowMap();\\n\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t}\\n\\tget numCascades() {\\n\\t\\treturn this.cascades.length;\\n\\t}\\n\\tset cascadeBlend(value) {\\n\\t\\tif (this._cascadeBlend !== value) {\\n\\t\\t\\tthis._cascadeBlend = value;\\n\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t}\\n\\tget cascadeBlend() {\\n\\t\\treturn this._cascadeBlend;\\n\\t}\\n\\tset shadowMap(shadowMap) {\\n\\t\\tif (this._shadowMap !== shadowMap) {\\n\\t\\t\\tthis._destroyShadowMap();\\n\\t\\t\\tthis._shadowMap = shadowMap;\\n\\t\\t}\\n\\t}\\n\\tget shadowMap() {\\n\\t\\treturn this._shadowMap;\\n\\t}\\n\\tset mask(value) {\\n\\t\\tif (this._mask !== value) {\\n\\t\\t\\tthis._mask = value;\\n\\t\\t\\tthis.updateKey();\\n\\t\\t\\tthis.updateClusteredFlags();\\n\\t\\t}\\n\\t}\\n\\tget mask() {\\n\\t\\treturn this._mask;\\n\\t}\\n\\t// returns number of render targets to render the shadow map\\n\\tget numShadowFaces() {\\n\\t\\tconst type = this._type;\\n\\t\\tif (type === LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\treturn this.numCascades;\\n\\t\\t} else if (type === LIGHTTYPE_OMNI) {\\n\\t\\t\\treturn 6;\\n\\t\\t}\\n\\t\\treturn 1;\\n\\t}\\n\\tset type(value) {\\n\\t\\tif (this._type === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._type = value;\\n\\t\\tthis._destroyShadowMap();\\n\\t\\tthis._updateShadowBias();\\n\\t\\tthis.updateKey();\\n\\t\\tthis.updateClusteredFlags();\\n\\t\\tconst stype = this._shadowType;\\n\\t\\tthis._shadowType = null;\\n\\t\\tthis.shadowUpdateOverrides = null;\\n\\t\\tthis.shadowType = stype;\\n\\t}\\n\\tget type() {\\n\\t\\treturn this._type;\\n\\t}\\n\\tset shape(value) {\\n\\t\\tif (this._shape === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._shape = value;\\n\\t\\tthis._destroyShadowMap();\\n\\t\\tthis.updateKey();\\n\\t\\tthis.updateClusteredFlags();\\n\\t\\tconst stype = this._shadowType;\\n\\t\\tthis._shadowType = null;\\n\\t\\tthis.shadowType = stype;\\n\\t}\\n\\tget shape() {\\n\\t\\treturn this._shape;\\n\\t}\\n\\tset usePhysicalUnits(value) {\\n\\t\\tif (this._usePhysicalUnits !== value) {\\n\\t\\t\\tthis._usePhysicalUnits = value;\\n\\t\\t\\tthis._updateLinearColor();\\n\\t\\t}\\n\\t}\\n\\tget usePhysicalUnits() {\\n\\t\\treturn this._usePhysicalUnits;\\n\\t}\\n\\tset shadowType(value) {\\n\\t\\tif (this._shadowType === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tlet shadowInfo = shadowTypeInfo.get(value);\\n\\t\\tif (!shadowInfo) {\\n\\t\\t\\tvalue = SHADOW_PCF3_32F;\\n\\t\\t}\\n\\t\\tconst device = this.device;\\n\\t\\tif (value === SHADOW_PCSS_32F && (!device.textureFloatRenderable || !device.textureFloatFilterable)) {\\n\\t\\t\\tvalue = SHADOW_PCF3_32F;\\n\\t\\t}\\n\\t\\tif (this._type === LIGHTTYPE_OMNI && value !== SHADOW_PCF1_32F && value !== SHADOW_PCF3_32F && value !== SHADOW_PCF1_16F && value !== SHADOW_PCF3_16F && value !== SHADOW_PCSS_32F) {\\n\\t\\t\\tvalue = SHADOW_PCF3_32F;\\n\\t\\t}\\n\\t\\tif (value === SHADOW_VSM_32F && (!device.textureFloatRenderable || !device.textureFloatFilterable)) {\\n\\t\\t\\tvalue = SHADOW_VSM_16F;\\n\\t\\t}\\n\\t\\tif (value === SHADOW_VSM_16F && !device.textureHalfFloatRenderable) {\\n\\t\\t\\tvalue = SHADOW_PCF3_32F;\\n\\t\\t}\\n\\t\\tshadowInfo = shadowTypeInfo.get(value);\\n\\t\\tthis._isVsm = shadowInfo?.vsm ?? false;\\n\\t\\tthis._isPcf = shadowInfo?.pcf ?? false;\\n\\t\\tthis._shadowType = value;\\n\\t\\tthis._destroyShadowMap();\\n\\t\\tthis.updateKey();\\n\\t}\\n\\tget shadowType() {\\n\\t\\treturn this._shadowType;\\n\\t}\\n\\tset enabled(value) {\\n\\t\\tif (this._enabled !== value) {\\n\\t\\t\\tthis._enabled = value;\\n\\t\\t\\tthis.layersDirty();\\n\\t\\t}\\n\\t}\\n\\tget enabled() {\\n\\t\\treturn this._enabled;\\n\\t}\\n\\tset castShadows(value) {\\n\\t\\tif (this._castShadows !== value) {\\n\\t\\t\\tthis._castShadows = value;\\n\\t\\t\\tthis._destroyShadowMap();\\n\\t\\t\\tthis.layersDirty();\\n\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t}\\n\\tget castShadows() {\\n\\t\\treturn this._castShadows && this._mask !== MASK_BAKE && this._mask !== 0;\\n\\t}\\n\\tset shadowIntensity(value) {\\n\\t\\tif (this._shadowIntensity !== value) {\\n\\t\\t\\tthis._shadowIntensity = value;\\n\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t}\\n\\tget shadowIntensity() {\\n\\t\\treturn this._shadowIntensity;\\n\\t}\\n\\tget bakeShadows() {\\n\\t\\treturn this._castShadows && this._mask === MASK_BAKE;\\n\\t}\\n\\tset shadowResolution(value) {\\n\\t\\tif (this._shadowResolution !== value) {\\n\\t\\t\\tif (this._type === LIGHTTYPE_OMNI) {\\n\\t\\t\\t\\tvalue = Math.min(value, this.device.maxCubeMapSize);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tvalue = Math.min(value, this.device.maxTextureSize);\\n\\t\\t\\t}\\n\\t\\t\\tthis._shadowResolution = value;\\n\\t\\t\\tthis._destroyShadowMap();\\n\\t\\t}\\n\\t}\\n\\tget shadowResolution() {\\n\\t\\treturn this._shadowResolution;\\n\\t}\\n\\tset vsmBlurSize(value) {\\n\\t\\tif (this._vsmBlurSize === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (value % 2 === 0) value++;\\n\\t\\tthis._vsmBlurSize = value;\\n\\t}\\n\\tget vsmBlurSize() {\\n\\t\\treturn this._vsmBlurSize;\\n\\t}\\n\\tset normalOffsetBias(value) {\\n\\t\\tif (this._normalOffsetBias !== value) {\\n\\t\\t\\tconst dirty = !this._normalOffsetBias && value || this._normalOffsetBias && !value;\\n\\t\\t\\tthis._normalOffsetBias = value;\\n\\t\\t\\tif (dirty) {\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget normalOffsetBias() {\\n\\t\\treturn this._normalOffsetBias;\\n\\t}\\n\\tset falloffMode(value) {\\n\\t\\tif (this._falloffMode === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._falloffMode = value;\\n\\t\\tthis.updateKey();\\n\\t\\tthis.updateClusteredFlags();\\n\\t}\\n\\tget falloffMode() {\\n\\t\\treturn this._falloffMode;\\n\\t}\\n\\tset innerConeAngle(value) {\\n\\t\\tif (this._innerConeAngle === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._innerConeAngle = value;\\n\\t\\tthis._innerConeAngleCos = Math.cos(value * math.DEG_TO_RAD);\\n\\t\\tthis.updateClusterData(false, true);\\n\\t\\tif (this._usePhysicalUnits) {\\n\\t\\t\\tthis._updateLinearColor();\\n\\t\\t}\\n\\t}\\n\\tget innerConeAngle() {\\n\\t\\treturn this._innerConeAngle;\\n\\t}\\n\\tset outerConeAngle(value) {\\n\\t\\tif (this._outerConeAngle === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._outerConeAngle = value;\\n\\t\\tthis._updateOuterAngle(value);\\n\\t\\tif (this._usePhysicalUnits) {\\n\\t\\t\\tthis._updateLinearColor();\\n\\t\\t}\\n\\t}\\n\\tget outerConeAngle() {\\n\\t\\treturn this._outerConeAngle;\\n\\t}\\n\\tset penumbraSize(value) {\\n\\t\\tthis._penumbraSize = value;\\n\\t\\tthis._softShadowParams[2] = value;\\n\\t}\\n\\tget penumbraSize() {\\n\\t\\treturn this._penumbraSize;\\n\\t}\\n\\tset penumbraFalloff(value) {\\n\\t\\tthis._softShadowParams[3] = value;\\n\\t}\\n\\tget penumbraFalloff() {\\n\\t\\treturn this._softShadowParams[3];\\n\\t}\\n\\t_updateOuterAngle(angle) {\\n\\t\\tconst radAngle = angle * math.DEG_TO_RAD;\\n\\t\\tthis._outerConeAngleCos = Math.cos(radAngle);\\n\\t\\tthis._outerConeAngleSin = Math.sin(radAngle);\\n\\t\\tthis.updateClusterData(false, true);\\n\\t}\\n\\tset intensity(value) {\\n\\t\\tif (this._intensity !== value) {\\n\\t\\t\\tthis._intensity = value;\\n\\t\\t\\tthis._updateLinearColor();\\n\\t\\t}\\n\\t}\\n\\tget intensity() {\\n\\t\\treturn this._intensity;\\n\\t}\\n\\tset affectSpecularity(value) {\\n\\t\\tif (this._type === LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\tthis._affectSpecularity = value;\\n\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t}\\n\\tget affectSpecularity() {\\n\\t\\treturn this._affectSpecularity;\\n\\t}\\n\\tset luminance(value) {\\n\\t\\tif (this._luminance !== value) {\\n\\t\\t\\tthis._luminance = value;\\n\\t\\t\\tthis._updateLinearColor();\\n\\t\\t}\\n\\t}\\n\\tget luminance() {\\n\\t\\treturn this._luminance;\\n\\t}\\n\\tget cookieMatrix() {\\n\\t\\tif (!this._cookieMatrix) {\\n\\t\\t\\tthis._cookieMatrix = new Mat4();\\n\\t\\t}\\n\\t\\treturn this._cookieMatrix;\\n\\t}\\n\\tget atlasViewport() {\\n\\t\\tif (!this._atlasViewport) {\\n\\t\\t\\tthis._atlasViewport = new Vec4(0, 0, 1, 1);\\n\\t\\t}\\n\\t\\treturn this._atlasViewport;\\n\\t}\\n\\tset cookie(value) {\\n\\t\\tif (this._cookie === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._cookie = value;\\n\\t\\tthis.updateKey();\\n\\t}\\n\\tget cookie() {\\n\\t\\treturn this._cookie;\\n\\t}\\n\\tset cookieFalloff(value) {\\n\\t\\tif (this._cookieFalloff === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._cookieFalloff = value;\\n\\t\\tthis.updateKey();\\n\\t}\\n\\tget cookieFalloff() {\\n\\t\\treturn this._cookieFalloff;\\n\\t}\\n\\tset cookieChannel(value) {\\n\\t\\tif (this._cookieChannel === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (value.length < 3) {\\n\\t\\t\\tconst chr = value.charAt(value.length - 1);\\n\\t\\t\\tconst addLen = 3 - value.length;\\n\\t\\t\\tfor (let i = 0; i < addLen; i++) {\\n\\t\\t\\t\\tvalue += chr;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._cookieChannel = value;\\n\\t\\tthis.updateKey();\\n\\t\\tthis.updateClusteredFlags();\\n\\t}\\n\\tget cookieChannel() {\\n\\t\\treturn this._cookieChannel;\\n\\t}\\n\\tset cookieTransform(value) {\\n\\t\\tif (this._cookieTransform === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._cookieTransform = value;\\n\\t\\tthis._cookieTransformSet = !!value;\\n\\t\\tif (value && !this._cookieOffset) {\\n\\t\\t\\tthis.cookieOffset = new Vec2();\\n\\t\\t\\tthis._cookieOffsetSet = false;\\n\\t\\t}\\n\\t\\tthis.updateKey();\\n\\t}\\n\\tget cookieTransform() {\\n\\t\\treturn this._cookieTransform;\\n\\t}\\n\\tset cookieOffset(value) {\\n\\t\\tif (this._cookieOffset === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst xformNew = !!(this._cookieTransformSet || value);\\n\\t\\tif (xformNew && !value && this._cookieOffset) {\\n\\t\\t\\tthis._cookieOffset.set(0, 0);\\n\\t\\t} else {\\n\\t\\t\\tthis._cookieOffset = value;\\n\\t\\t}\\n\\t\\tthis._cookieOffsetSet = !!value;\\n\\t\\tif (value && !this._cookieTransform) {\\n\\t\\t\\tthis.cookieTransform = new Vec4(1, 1, 0, 0);\\n\\t\\t\\tthis._cookieTransformSet = false;\\n\\t\\t}\\n\\t\\tthis.updateKey();\\n\\t}\\n\\tget cookieOffset() {\\n\\t\\treturn this._cookieOffset;\\n\\t}\\n\\t// prepares light for the frame rendering\\n\\tbeginFrame() {\\n\\t\\tthis.visibleThisFrame = this._type === LIGHTTYPE_DIRECTIONAL && this._enabled;\\n\\t\\tthis.maxScreenSize = 0;\\n\\t\\tthis.atlasViewportAllocated = false;\\n\\t\\tthis.atlasSlotUpdated = false;\\n\\t}\\n\\t// destroys shadow map related resources, called when shadow properties change and resources\\n\\t// need to be recreated\\n\\t_destroyShadowMap() {\\n\\t\\tthis.releaseRenderData();\\n\\t\\tif (this._shadowMap) {\\n\\t\\t\\tif (!this._shadowMap.cached) {\\n\\t\\t\\t\\tthis._shadowMap.destroy();\\n\\t\\t\\t}\\n\\t\\t\\tthis._shadowMap = null;\\n\\t\\t}\\n\\t\\tif (this.shadowUpdateMode === SHADOWUPDATE_NONE) {\\n\\t\\t\\tthis.shadowUpdateMode = SHADOWUPDATE_THISFRAME;\\n\\t\\t}\\n\\t\\tif (this.shadowUpdateOverrides) {\\n\\t\\t\\tfor (let i = 0; i < this.shadowUpdateOverrides.length; i++) {\\n\\t\\t\\t\\tif (this.shadowUpdateOverrides[i] === SHADOWUPDATE_NONE) {\\n\\t\\t\\t\\t\\tthis.shadowUpdateOverrides[i] = SHADOWUPDATE_THISFRAME;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t// returns LightRenderData with matching camera and face\\n\\tgetRenderData(camera, face) {\\n\\t\\tfor (let i = 0; i < this._renderData.length; i++) {\\n\\t\\t\\tconst current = this._renderData[i];\\n\\t\\t\\tif (current.camera === camera && current.face === face) {\\n\\t\\t\\t\\treturn current;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst rd = new LightRenderData(camera, face, this);\\n\\t\\tthis._renderData.push(rd);\\n\\t\\treturn rd;\\n\\t}\\n\\tclone() {\\n\\t\\tconst clone = new Light(this.device, this.clusteredLighting);\\n\\t\\tclone.type = this._type;\\n\\t\\tclone.setColor(this._color);\\n\\t\\tclone.intensity = this._intensity;\\n\\t\\tclone.affectSpecularity = this._affectSpecularity;\\n\\t\\tclone.luminance = this._luminance;\\n\\t\\tclone.castShadows = this.castShadows;\\n\\t\\tclone._enabled = this._enabled;\\n\\t\\tclone.attenuationStart = this.attenuationStart;\\n\\t\\tclone.attenuationEnd = this.attenuationEnd;\\n\\t\\tclone.falloffMode = this._falloffMode;\\n\\t\\tclone.shadowType = this._shadowType;\\n\\t\\tclone.vsmBlurSize = this._vsmBlurSize;\\n\\t\\tclone.vsmBlurMode = this.vsmBlurMode;\\n\\t\\tclone.vsmBias = this.vsmBias;\\n\\t\\tclone.shadowUpdateMode = this.shadowUpdateMode;\\n\\t\\tclone.mask = this.mask;\\n\\t\\tif (this.shadowUpdateOverrides) {\\n\\t\\t\\tclone.shadowUpdateOverrides = this.shadowUpdateOverrides.slice();\\n\\t\\t}\\n\\t\\tclone.innerConeAngle = this._innerConeAngle;\\n\\t\\tclone.outerConeAngle = this._outerConeAngle;\\n\\t\\tclone.numCascades = this.numCascades;\\n\\t\\tclone.cascadeDistribution = this.cascadeDistribution;\\n\\t\\tclone.cascadeBlend = this._cascadeBlend;\\n\\t\\tclone.shape = this._shape;\\n\\t\\tclone.shadowDepthState.copy(this.shadowDepthState);\\n\\t\\tclone.shadowBias = this.shadowBias;\\n\\t\\tclone.normalOffsetBias = this._normalOffsetBias;\\n\\t\\tclone.shadowResolution = this._shadowResolution;\\n\\t\\tclone.shadowDistance = this.shadowDistance;\\n\\t\\tclone.shadowIntensity = this.shadowIntensity;\\n\\t\\tclone.shadowSamples = this.shadowSamples;\\n\\t\\tclone.shadowBlockerSamples = this.shadowBlockerSamples;\\n\\t\\tclone.penumbraSize = this.penumbraSize;\\n\\t\\tclone.penumbraFalloff = this.penumbraFalloff;\\n\\t\\treturn clone;\\n\\t}\\n\\tstatic getLightUnitConversion(type, outerAngle = Math.PI / 4, innerAngle = 0) {\\n\\t\\tswitch (type) {\\n\\t\\t\\tcase LIGHTTYPE_SPOT: {\\n\\t\\t\\t\\tconst falloffEnd = Math.cos(outerAngle);\\n\\t\\t\\t\\tconst falloffStart = Math.cos(innerAngle);\\n\\t\\t\\t\\treturn 2 * Math.PI * (1 - falloffStart + (falloffStart - falloffEnd) / 2);\\n\\t\\t\\t}\\n\\t\\t\\tcase LIGHTTYPE_OMNI:\\n\\t\\t\\t\\treturn 4 * Math.PI;\\n\\t\\t\\tcase LIGHTTYPE_DIRECTIONAL:\\n\\t\\t\\t\\treturn 1;\\n\\t\\t}\\n\\t}\\n\\t// returns the bias (.x) and normalBias (.y) value for lights as passed to shaders by uniforms\\n\\t// Note: this needs to be revisited and simplified\\n\\t// Note: vsmBias is not used at all for omni light, even though it is editable in the Editor\\n\\t_getUniformBiasValues(lightRenderData) {\\n\\t\\tconst farClip = lightRenderData.shadowCamera._farClip;\\n\\t\\tswitch (this._type) {\\n\\t\\t\\tcase LIGHTTYPE_OMNI:\\n\\t\\t\\t\\ttmpBiases.bias = this.shadowBias;\\n\\t\\t\\t\\ttmpBiases.normalBias = this._normalOffsetBias;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase LIGHTTYPE_SPOT:\\n\\t\\t\\t\\tif (this._isVsm) {\\n\\t\\t\\t\\t\\ttmpBiases.bias = -1e-5 * 20;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\ttmpBiases.bias = this.shadowBias * 20;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttmpBiases.normalBias = this._isVsm ? this.vsmBias / (this.attenuationEnd / 7) : this._normalOffsetBias;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase LIGHTTYPE_DIRECTIONAL:\\n\\t\\t\\t\\tif (this._isVsm) {\\n\\t\\t\\t\\t\\ttmpBiases.bias = -1e-5 * 20;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\ttmpBiases.bias = this.shadowBias / farClip * 100;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttmpBiases.normalBias = this._isVsm ? this.vsmBias / (farClip / 7) : this._normalOffsetBias;\\n\\t\\t\\t\\tbreak;\\n\\t\\t}\\n\\t\\treturn tmpBiases;\\n\\t}\\n\\tgetColor() {\\n\\t\\treturn this._color;\\n\\t}\\n\\tgetBoundingSphere(sphere) {\\n\\t\\tif (this._type === LIGHTTYPE_SPOT) {\\n\\t\\t\\tconst size = this.attenuationEnd;\\n\\t\\t\\tconst angle = this._outerConeAngle;\\n\\t\\t\\tconst cosAngle = this._outerConeAngleCos;\\n\\t\\t\\tconst node = this._node;\\n\\t\\t\\ttmpVec.copy(node.up);\\n\\t\\t\\tif (angle > 45) {\\n\\t\\t\\t\\tsphere.radius = size * this._outerConeAngleSin;\\n\\t\\t\\t\\ttmpVec.mulScalar(-size * cosAngle);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tsphere.radius = size / (2 * cosAngle);\\n\\t\\t\\t\\ttmpVec.mulScalar(-sphere.radius);\\n\\t\\t\\t}\\n\\t\\t\\tsphere.center.add2(node.getPosition(), tmpVec);\\n\\t\\t} else if (this._type === LIGHTTYPE_OMNI) {\\n\\t\\t\\tsphere.center = this._node.getPosition();\\n\\t\\t\\tsphere.radius = this.attenuationEnd;\\n\\t\\t}\\n\\t}\\n\\tgetBoundingBox(box) {\\n\\t\\tif (this._type === LIGHTTYPE_SPOT) {\\n\\t\\t\\tconst range = this.attenuationEnd;\\n\\t\\t\\tconst angle = this._outerConeAngle;\\n\\t\\t\\tconst node = this._node;\\n\\t\\t\\tconst scl = Math.abs(Math.sin(angle * math.DEG_TO_RAD) * range);\\n\\t\\t\\tbox.center.set(0, -range * 0.5, 0);\\n\\t\\t\\tbox.halfExtents.set(scl, range * 0.5, scl);\\n\\t\\t\\tbox.setFromTransformedAabb(box, node.getWorldTransform(), true);\\n\\t\\t} else if (this._type === LIGHTTYPE_OMNI) {\\n\\t\\t\\tbox.center.copy(this._node.getPosition());\\n\\t\\t\\tbox.halfExtents.set(this.attenuationEnd, this.attenuationEnd, this.attenuationEnd);\\n\\t\\t}\\n\\t}\\n\\t_updateShadowBias() {\\n\\t\\tif (this._type === LIGHTTYPE_OMNI && !this.clusteredLighting) {\\n\\t\\t\\tthis.shadowDepthState.depthBias = 0;\\n\\t\\t\\tthis.shadowDepthState.depthBiasSlope = 0;\\n\\t\\t} else {\\n\\t\\t\\tconst bias = this.shadowBias * -1e3;\\n\\t\\t\\tthis.shadowDepthState.depthBias = bias;\\n\\t\\t\\tthis.shadowDepthState.depthBiasSlope = bias;\\n\\t\\t}\\n\\t}\\n\\t_updateLinearColor() {\\n\\t\\tlet intensity = this._intensity;\\n\\t\\tif (this._usePhysicalUnits) {\\n\\t\\t\\tintensity = this._luminance / Light.getLightUnitConversion(this._type, this._outerConeAngle * math.DEG_TO_RAD, this._innerConeAngle * math.DEG_TO_RAD);\\n\\t\\t}\\n\\t\\tconst color = this._color;\\n\\t\\tconst colorLinear = this._colorLinear;\\n\\t\\tif (intensity >= 1) {\\n\\t\\t\\ttmpColor.linear(color).mulScalar(intensity);\\n\\t\\t} else {\\n\\t\\t\\ttmpColor.copy(color).mulScalar(intensity).linear();\\n\\t\\t}\\n\\t\\tcolorLinear[0] = tmpColor.r;\\n\\t\\tcolorLinear[1] = tmpColor.g;\\n\\t\\tcolorLinear[2] = tmpColor.b;\\n\\t\\tthis.updateClusterData(true);\\n\\t}\\n\\tsetColor() {\\n\\t\\tif (arguments.length === 1) {\\n\\t\\t\\tthis._color.set(arguments[0].r, arguments[0].g, arguments[0].b);\\n\\t\\t} else if (arguments.length === 3) {\\n\\t\\t\\tthis._color.set(arguments[0], arguments[1], arguments[2]);\\n\\t\\t}\\n\\t\\tthis._updateLinearColor();\\n\\t}\\n\\tlayersDirty() {\\n\\t\\tthis.layers.forEach((layer) => {\\n\\t\\t\\tif (layer.hasLight(this)) {\\n\\t\\t\\t\\tlayer.markLightsDirty();\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n\\tupdateKey() {\\n\\t\\tlet key = this._type << 29 | this._shadowType << 25 | this._falloffMode << 23 | (this._normalOffsetBias !== 0 ? 1 : 0) << 22 | (this._cookie ? 1 : 0) << 21 | (this._cookieFalloff ? 1 : 0) << 20 | chanId[this._cookieChannel.charAt(0)] << 18 | (this._cookieTransform ? 1 : 0) << 12 | this._shape << 10 | (this.numCascades > 0 ? 1 : 0) << 9 | (this._cascadeBlend > 0 ? 1 : 0) << 8 | (this.affectSpecularity ? 1 : 0) << 7 | this.mask << 6 | (this._castShadows ? 1 : 0) << 3;\\n\\t\\tif (this._cookieChannel.length === 3) {\\n\\t\\t\\tkey |= chanId[this._cookieChannel.charAt(1)] << 16;\\n\\t\\t\\tkey |= chanId[this._cookieChannel.charAt(2)] << 14;\\n\\t\\t}\\n\\t\\tif (key !== this.key) {\\n\\t\\t\\tthis.layersDirty();\\n\\t\\t}\\n\\t\\tthis.key = key;\\n\\t}\\n\\tupdateClusteredFlags() {\\n\\t\\tconst isDynamic = !!(this.mask & MASK_AFFECT_DYNAMIC);\\n\\t\\tconst isLightmapped = !!(this.mask & MASK_AFFECT_LIGHTMAPPED);\\n\\t\\tthis.clusteredFlags = (this.type === LIGHTTYPE_SPOT ? 1 : 0) << 30 | // bits 30\\n\\t\\t(this._shape & 3) << 28 | // bits 29 - 28\\n\\t\\t(this._falloffMode & 1) << 27 | // bits 27\\n\\t\\t(channelMap[this._cookieChannel] ?? 0) << 23 | // bits 26 - 23\\n\\t\\t(isDynamic ? 1 : 0) << 22 | // bits 22\\n\\t\\t(isLightmapped ? 1 : 0) << 21;\\n\\t}\\n\\tgetClusteredFlags(castShadows, useCookie) {\\n\\t\\treturn this.clusteredFlags | ((castShadows ? Math.floor(this.shadowIntensity * 255) : 0) & 255) << 0 | // bits 7 - 0\\n\\t\\t((useCookie ? Math.floor(this.cookieIntensity * 255) : 0) & 255) << 8;\\n\\t}\\n\\tupdateClusterData(updateColor, updateAngles) {\\n\\t\\tconst { clusteredData16 } = this;\\n\\t\\tconst float2Half = FloatPacking.float2Half;\\n\\t\\tif (updateColor) {\\n\\t\\t\\tclusteredData16[0] = float2Half(math.clamp(this._colorLinear[0] / LIGHT_COLOR_DIVIDER, 0, 65504));\\n\\t\\t\\tclusteredData16[1] = float2Half(math.clamp(this._colorLinear[1] / LIGHT_COLOR_DIVIDER, 0, 65504));\\n\\t\\t\\tclusteredData16[2] = float2Half(math.clamp(this._colorLinear[2] / LIGHT_COLOR_DIVIDER, 0, 65504));\\n\\t\\t}\\n\\t\\tif (updateAngles) {\\n\\t\\t\\tconst cosThreshold = 0.5;\\n\\t\\t\\tlet flags = 0;\\n\\t\\t\\tconst angleShrinkFactor = 0.99;\\n\\t\\t\\tlet innerCos = Math.cos(this._innerConeAngle * angleShrinkFactor * math.DEG_TO_RAD);\\n\\t\\t\\tif (innerCos > cosThreshold) {\\n\\t\\t\\t\\tinnerCos = 1 - innerCos;\\n\\t\\t\\t\\tflags |= 1;\\n\\t\\t\\t}\\n\\t\\t\\tlet outerCos = Math.cos(this._outerConeAngle * angleShrinkFactor * math.DEG_TO_RAD);\\n\\t\\t\\tif (outerCos > cosThreshold) {\\n\\t\\t\\t\\touterCos = 1 - outerCos;\\n\\t\\t\\t\\tflags |= 2;\\n\\t\\t\\t}\\n\\t\\t\\tclusteredData16[3] = flags;\\n\\t\\t\\tclusteredData16[4] = float2Half(innerCos);\\n\\t\\t\\tclusteredData16[5] = float2Half(outerCos);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass LightingParams {\\n\\t_areaLightsEnabled = false;\\n\\t_cells = new Vec3(10, 3, 10);\\n\\t_maxLightsPerCell = 255;\\n\\t_shadowsEnabled = true;\\n\\t_shadowType = SHADOW_PCF3_32F;\\n\\t_shadowAtlasResolution = 2048;\\n\\t_cookiesEnabled = false;\\n\\t_cookieAtlasResolution = 2048;\\n\\tdebugLayer;\\n\\tatlasSplit = null;\\n\\tconstructor(supportsAreaLights, maxTextureSize, dirtyLightsFnc) {\\n\\t\\tthis._supportsAreaLights = supportsAreaLights;\\n\\t\\tthis._maxTextureSize = maxTextureSize;\\n\\t\\tthis._dirtyLightsFnc = dirtyLightsFnc;\\n\\t}\\n\\tapplySettings(render) {\\n\\t\\tthis.shadowsEnabled = render.lightingShadowsEnabled ?? this.shadowsEnabled;\\n\\t\\tthis.cookiesEnabled = render.lightingCookiesEnabled ?? this.cookiesEnabled;\\n\\t\\tthis.areaLightsEnabled = render.lightingAreaLightsEnabled ?? this.areaLightsEnabled;\\n\\t\\tthis.shadowAtlasResolution = render.lightingShadowAtlasResolution ?? this.shadowAtlasResolution;\\n\\t\\tthis.cookieAtlasResolution = render.lightingCookieAtlasResolution ?? this.cookieAtlasResolution;\\n\\t\\tthis.maxLightsPerCell = render.lightingMaxLightsPerCell ?? this.maxLightsPerCell;\\n\\t\\tthis.shadowType = render.lightingShadowType ?? this.shadowType;\\n\\t\\tif (render.lightingCells) {\\n\\t\\t\\tthis.cells = new Vec3(render.lightingCells);\\n\\t\\t}\\n\\t}\\n\\tset cells(value) {\\n\\t\\tthis._cells.copy(value);\\n\\t}\\n\\tget cells() {\\n\\t\\treturn this._cells;\\n\\t}\\n\\tset maxLightsPerCell(value) {\\n\\t\\tthis._maxLightsPerCell = math.clamp(value, 1, 255);\\n\\t}\\n\\tget maxLightsPerCell() {\\n\\t\\treturn this._maxLightsPerCell;\\n\\t}\\n\\tset cookieAtlasResolution(value) {\\n\\t\\tthis._cookieAtlasResolution = math.clamp(value, 32, this._maxTextureSize);\\n\\t}\\n\\tget cookieAtlasResolution() {\\n\\t\\treturn this._cookieAtlasResolution;\\n\\t}\\n\\tset shadowAtlasResolution(value) {\\n\\t\\tthis._shadowAtlasResolution = math.clamp(value, 32, this._maxTextureSize);\\n\\t}\\n\\tget shadowAtlasResolution() {\\n\\t\\treturn this._shadowAtlasResolution;\\n\\t}\\n\\tset shadowType(value) {\\n\\t\\tif (this._shadowType !== value) {\\n\\t\\t\\tthis._shadowType = value;\\n\\t\\t\\tthis._dirtyLightsFnc();\\n\\t\\t}\\n\\t}\\n\\tget shadowType() {\\n\\t\\treturn this._shadowType;\\n\\t}\\n\\tset cookiesEnabled(value) {\\n\\t\\tif (this._cookiesEnabled !== value) {\\n\\t\\t\\tthis._cookiesEnabled = value;\\n\\t\\t\\tthis._dirtyLightsFnc();\\n\\t\\t}\\n\\t}\\n\\tget cookiesEnabled() {\\n\\t\\treturn this._cookiesEnabled;\\n\\t}\\n\\tset areaLightsEnabled(value) {\\n\\t\\tif (this._supportsAreaLights) {\\n\\t\\t\\tif (this._areaLightsEnabled !== value) {\\n\\t\\t\\t\\tthis._areaLightsEnabled = value;\\n\\t\\t\\t\\tthis._dirtyLightsFnc();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget areaLightsEnabled() {\\n\\t\\treturn this._areaLightsEnabled;\\n\\t}\\n\\tset shadowsEnabled(value) {\\n\\t\\tif (this._shadowsEnabled !== value) {\\n\\t\\t\\tthis._shadowsEnabled = value;\\n\\t\\t\\tthis._dirtyLightsFnc();\\n\\t\\t}\\n\\t}\\n\\tget shadowsEnabled() {\\n\\t\\treturn this._shadowsEnabled;\\n\\t}\\n}\\n\\nclass MorphInstance {\\n\\tconstructor(morph) {\\n\\t\\tthis.morph = morph;\\n\\t\\tmorph.incRefCount();\\n\\t\\tthis.device = morph.device;\\n\\t\\tconst maxNumTargets = morph._targets.length;\\n\\t\\tthis.shader = this._createShader(maxNumTargets);\\n\\t\\tthis._weights = [];\\n\\t\\tthis._weightMap = /* @__PURE__ */ new Map();\\n\\t\\tfor (let v = 0; v < morph._targets.length; v++) {\\n\\t\\t\\tconst target = morph._targets[v];\\n\\t\\t\\tif (target.name) {\\n\\t\\t\\t\\tthis._weightMap.set(target.name, v);\\n\\t\\t\\t}\\n\\t\\t\\tthis.setWeight(v, target.defaultWeight);\\n\\t\\t}\\n\\t\\tthis._shaderMorphWeights = new Float32Array(maxNumTargets);\\n\\t\\tthis._shaderMorphIndex = new Uint32Array(maxNumTargets);\\n\\t\\tconst createRT = (name, textureVar) => {\\n\\t\\t\\tthis[textureVar] = morph._createTexture(name, morph._renderTextureFormat);\\n\\t\\t\\treturn new RenderTarget({\\n\\t\\t\\t\\tcolorBuffer: this[textureVar],\\n\\t\\t\\t\\tdepth: false\\n\\t\\t\\t});\\n\\t\\t};\\n\\t\\tif (morph.morphPositions) {\\n\\t\\t\\tthis.rtPositions = createRT(\\\"MorphRTPos\\\", \\\"texturePositions\\\");\\n\\t\\t}\\n\\t\\tif (morph.morphNormals) {\\n\\t\\t\\tthis.rtNormals = createRT(\\\"MorphRTNrm\\\", \\\"textureNormals\\\");\\n\\t\\t}\\n\\t\\tthis._textureParams = new Float32Array([morph.morphTextureWidth, morph.morphTextureHeight]);\\n\\t\\tconst halfSize = morph.aabb.halfExtents;\\n\\t\\tthis._aabbSize = new Float32Array([halfSize.x * 4, halfSize.y * 4, halfSize.z * 4]);\\n\\t\\tconst min = morph.aabb.getMin();\\n\\t\\tthis._aabbMin = new Float32Array([min.x * 2, min.y * 2, min.z * 2]);\\n\\t\\tthis._aabbNrmSize = new Float32Array([2, 2, 2]);\\n\\t\\tthis._aabbNrmMin = new Float32Array([-1, -1, -1]);\\n\\t\\tthis.aabbSizeId = this.device.scope.resolve(\\\"aabbSize\\\");\\n\\t\\tthis.aabbMinId = this.device.scope.resolve(\\\"aabbMin\\\");\\n\\t\\tthis.morphTextureId = this.device.scope.resolve(\\\"morphTexture\\\");\\n\\t\\tthis.morphFactor = this.device.scope.resolve(\\\"morphFactor[0]\\\");\\n\\t\\tthis.morphIndex = this.device.scope.resolve(\\\"morphIndex[0]\\\");\\n\\t\\tthis.countId = this.device.scope.resolve(\\\"count\\\");\\n\\t\\tthis.zeroTextures = false;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.shader = null;\\n\\t\\tconst morph = this.morph;\\n\\t\\tif (morph) {\\n\\t\\t\\tthis.morph = null;\\n\\t\\t\\tmorph.decRefCount();\\n\\t\\t\\tif (morph.refCount < 1) {\\n\\t\\t\\t\\tmorph.destroy();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.rtPositions?.destroy();\\n\\t\\tthis.rtPositions = null;\\n\\t\\tthis.texturePositions?.destroy();\\n\\t\\tthis.texturePositions = null;\\n\\t\\tthis.rtNormals?.destroy();\\n\\t\\tthis.rtNormals = null;\\n\\t\\tthis.textureNormals?.destroy();\\n\\t\\tthis.textureNormals = null;\\n\\t}\\n\\tclone() {\\n\\t\\treturn new MorphInstance(this.morph);\\n\\t}\\n\\t_getWeightIndex(key) {\\n\\t\\tif (typeof key === \\\"string\\\") {\\n\\t\\t\\tconst index = this._weightMap.get(key);\\n\\t\\t\\treturn index;\\n\\t\\t}\\n\\t\\treturn key;\\n\\t}\\n\\tgetWeight(key) {\\n\\t\\tconst index = this._getWeightIndex(key);\\n\\t\\treturn this._weights[index];\\n\\t}\\n\\tsetWeight(key, weight) {\\n\\t\\tconst index = this._getWeightIndex(key);\\n\\t\\tthis._weights[index] = weight;\\n\\t\\tthis._dirty = true;\\n\\t}\\n\\t_createShader(maxCount) {\\n\\t\\tconst defines = /* @__PURE__ */ new Map();\\n\\t\\tdefines.set(\\\"{MORPH_TEXTURE_MAX_COUNT}\\\", maxCount);\\n\\t\\tif (this.morph.intRenderFormat) defines.set(\\\"MORPH_INT\\\", \\\"\\\");\\n\\t\\tconst outputType = this.morph.intRenderFormat ? \\\"uvec4\\\" : \\\"vec4\\\";\\n\\t\\treturn ShaderUtils.createShader(this.device, {\\n\\t\\t\\tuniqueName: `TextureMorphShader_${maxCount}-${this.morph.intRenderFormat ? \\\"int\\\" : \\\"float\\\"}`,\\n\\t\\t\\tattributes: { vertex_position: SEMANTIC_POSITION },\\n\\t\\t\\tvertexChunk: \\\"morphVS\\\",\\n\\t\\t\\tfragmentChunk: \\\"morphPS\\\",\\n\\t\\t\\tfragmentDefines: defines,\\n\\t\\t\\tfragmentOutputTypes: [outputType]\\n\\t\\t});\\n\\t}\\n\\t_updateTextureRenderTarget(renderTarget, activeCount, isPos) {\\n\\t\\tconst { morph, device } = this;\\n\\t\\tthis.setAabbUniforms(isPos);\\n\\t\\tthis.morphTextureId.setValue(isPos ? morph.targetsTexturePositions : morph.targetsTextureNormals);\\n\\t\\tdevice.setBlendState(BlendState.NOBLEND);\\n\\t\\tthis.countId.setValue(activeCount);\\n\\t\\tthis.morphFactor.setValue(this._shaderMorphWeights);\\n\\t\\tthis.morphIndex.setValue(this._shaderMorphIndex);\\n\\t\\tdrawQuadWithShader(device, renderTarget, this.shader);\\n\\t}\\n\\t_updateTextureMorph(activeCount) {\\n\\t\\tthis.device;\\n\\t\\tif (activeCount > 0 || !this.zeroTextures) {\\n\\t\\t\\tif (this.rtPositions) {\\n\\t\\t\\t\\tthis._updateTextureRenderTarget(this.rtPositions, activeCount, true);\\n\\t\\t\\t}\\n\\t\\t\\tif (this.rtNormals) {\\n\\t\\t\\t\\tthis._updateTextureRenderTarget(this.rtNormals, activeCount, false);\\n\\t\\t\\t}\\n\\t\\t\\tthis.zeroTextures = activeCount === 0;\\n\\t\\t}\\n\\t}\\n\\tsetAabbUniforms(isPos = true) {\\n\\t\\tthis.aabbSizeId.setValue(isPos ? this._aabbSize : this._aabbNrmSize);\\n\\t\\tthis.aabbMinId.setValue(isPos ? this._aabbMin : this._aabbNrmMin);\\n\\t}\\n\\tprepareRendering(device) {\\n\\t\\tthis.setAabbUniforms();\\n\\t}\\n\\tupdate() {\\n\\t\\tthis._dirty = false;\\n\\t\\tconst targets = this.morph._targets;\\n\\t\\tconst epsilon = 1e-5;\\n\\t\\tconst weights = this._shaderMorphWeights;\\n\\t\\tconst indices = this._shaderMorphIndex;\\n\\t\\tlet activeCount = 0;\\n\\t\\tfor (let i = 0; i < targets.length; i++) {\\n\\t\\t\\tif (Math.abs(this.getWeight(i)) > epsilon) {\\n\\t\\t\\t\\tweights[activeCount] = this.getWeight(i);\\n\\t\\t\\t\\tindices[activeCount] = i;\\n\\t\\t\\t\\tactiveCount++;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._updateTextureMorph(activeCount);\\n\\t}\\n}\\n\\nclass Model {\\n\\tgraph = null;\\n\\tmeshInstances = [];\\n\\tskinInstances = [];\\n\\tmorphInstances = [];\\n\\tconstructor() {\\n\\t\\tthis.cameras = [];\\n\\t\\tthis.lights = [];\\n\\t\\tthis._shadersVersion = 0;\\n\\t\\tthis._immutable = false;\\n\\t}\\n\\tgetGraph() {\\n\\t\\treturn this.graph;\\n\\t}\\n\\tsetGraph(graph) {\\n\\t\\tthis.graph = graph;\\n\\t}\\n\\tgetCameras() {\\n\\t\\treturn this.cameras;\\n\\t}\\n\\tsetCameras(cameras) {\\n\\t\\tthis.cameras = cameras;\\n\\t}\\n\\tgetLights() {\\n\\t\\treturn this.lights;\\n\\t}\\n\\tsetLights(lights) {\\n\\t\\tthis.lights = lights;\\n\\t}\\n\\tgetMaterials() {\\n\\t\\tconst materials = [];\\n\\t\\tfor (let i = 0; i < this.meshInstances.length; i++) {\\n\\t\\t\\tconst meshInstance = this.meshInstances[i];\\n\\t\\t\\tif (materials.indexOf(meshInstance.material) === -1) {\\n\\t\\t\\t\\tmaterials.push(meshInstance.material);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn materials;\\n\\t}\\n\\tclone() {\\n\\t\\tconst srcNodes = [];\\n\\t\\tconst cloneNodes = [];\\n\\t\\tconst _duplicate = function(node) {\\n\\t\\t\\tconst newNode = node.clone();\\n\\t\\t\\tsrcNodes.push(node);\\n\\t\\t\\tcloneNodes.push(newNode);\\n\\t\\t\\tfor (let idx = 0; idx < node._children.length; idx++) {\\n\\t\\t\\t\\tnewNode.addChild(_duplicate(node._children[idx]));\\n\\t\\t\\t}\\n\\t\\t\\treturn newNode;\\n\\t\\t};\\n\\t\\tconst cloneGraph = _duplicate(this.graph);\\n\\t\\tconst cloneMeshInstances = [];\\n\\t\\tconst cloneSkinInstances = [];\\n\\t\\tconst cloneMorphInstances = [];\\n\\t\\tfor (let i = 0; i < this.skinInstances.length; i++) {\\n\\t\\t\\tconst skin = this.skinInstances[i].skin;\\n\\t\\t\\tconst cloneSkinInstance = new SkinInstance(skin);\\n\\t\\t\\tconst bones = [];\\n\\t\\t\\tfor (let j = 0; j < skin.boneNames.length; j++) {\\n\\t\\t\\t\\tconst boneName = skin.boneNames[j];\\n\\t\\t\\t\\tconst bone = cloneGraph.findByName(boneName);\\n\\t\\t\\t\\tbones.push(bone);\\n\\t\\t\\t}\\n\\t\\t\\tcloneSkinInstance.bones = bones;\\n\\t\\t\\tcloneSkinInstances.push(cloneSkinInstance);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < this.morphInstances.length; i++) {\\n\\t\\t\\tconst morph = this.morphInstances[i].morph;\\n\\t\\t\\tconst cloneMorphInstance = new MorphInstance(morph);\\n\\t\\t\\tcloneMorphInstances.push(cloneMorphInstance);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < this.meshInstances.length; i++) {\\n\\t\\t\\tconst meshInstance = this.meshInstances[i];\\n\\t\\t\\tconst nodeIndex = srcNodes.indexOf(meshInstance.node);\\n\\t\\t\\tconst cloneMeshInstance = new MeshInstance(meshInstance.mesh, meshInstance.material, cloneNodes[nodeIndex]);\\n\\t\\t\\tif (meshInstance.skinInstance) {\\n\\t\\t\\t\\tconst skinInstanceIndex = this.skinInstances.indexOf(meshInstance.skinInstance);\\n\\t\\t\\t\\tcloneMeshInstance.skinInstance = cloneSkinInstances[skinInstanceIndex];\\n\\t\\t\\t}\\n\\t\\t\\tif (meshInstance.morphInstance) {\\n\\t\\t\\t\\tconst morphInstanceIndex = this.morphInstances.indexOf(meshInstance.morphInstance);\\n\\t\\t\\t\\tcloneMeshInstance.morphInstance = cloneMorphInstances[morphInstanceIndex];\\n\\t\\t\\t}\\n\\t\\t\\tcloneMeshInstances.push(cloneMeshInstance);\\n\\t\\t}\\n\\t\\tconst clone = new Model();\\n\\t\\tclone.graph = cloneGraph;\\n\\t\\tclone.meshInstances = cloneMeshInstances;\\n\\t\\tclone.skinInstances = cloneSkinInstances;\\n\\t\\tclone.morphInstances = cloneMorphInstances;\\n\\t\\tclone.getGraph().syncHierarchy();\\n\\t\\treturn clone;\\n\\t}\\n\\tdestroy() {\\n\\t\\tconst meshInstances = this.meshInstances;\\n\\t\\tfor (let i = 0; i < meshInstances.length; i++) {\\n\\t\\t\\tmeshInstances[i].destroy();\\n\\t\\t}\\n\\t\\tthis.meshInstances.length = 0;\\n\\t}\\n\\tgenerateWireframe() {\\n\\t\\tMeshInstance._prepareRenderStyleForArray(this.meshInstances, RENDERSTYLE_WIREFRAME);\\n\\t}\\n}\\n\\nclass Morph extends RefCountedObject {\\n\\t_aabb;\\n\\tpreferHighPrecision;\\n\\tconstructor(targets, graphicsDevice, { preferHighPrecision = false } = {}) {\\n\\t\\tsuper();\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tconst device = graphicsDevice;\\n\\t\\tthis.preferHighPrecision = preferHighPrecision;\\n\\t\\tthis._targets = targets.slice();\\n\\t\\tconst renderableHalf = device.textureHalfFloatRenderable ? PIXELFORMAT_RGBA16F : void 0;\\n\\t\\tconst renderableFloat = device.textureFloatRenderable ? PIXELFORMAT_RGBA32F : void 0;\\n\\t\\tthis._renderTextureFormat = this.preferHighPrecision ? renderableFloat ?? renderableHalf : renderableHalf ?? renderableFloat;\\n\\t\\tthis._renderTextureFormat = this._renderTextureFormat ?? PIXELFORMAT_RGBA16U;\\n\\t\\tthis.intRenderFormat = isIntegerPixelFormat(this._renderTextureFormat);\\n\\t\\tthis._textureFormat = this.preferHighPrecision ? PIXELFORMAT_RGBA32F : PIXELFORMAT_RGBA16F;\\n\\t\\tthis._init();\\n\\t\\tthis._updateMorphFlags();\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.vertexBufferIds?.destroy();\\n\\t\\tthis.vertexBufferIds = null;\\n\\t\\tthis.targetsTexturePositions?.destroy();\\n\\t\\tthis.targetsTexturePositions = null;\\n\\t\\tthis.targetsTextureNormals?.destroy();\\n\\t\\tthis.targetsTextureNormals = null;\\n\\t}\\n\\tget aabb() {\\n\\t\\tif (!this._aabb) {\\n\\t\\t\\tconst min = new Vec3();\\n\\t\\t\\tconst max = new Vec3();\\n\\t\\t\\tfor (let i = 0; i < this._targets.length; i++) {\\n\\t\\t\\t\\tconst targetAabb = this._targets[i].aabb;\\n\\t\\t\\t\\tmin.min(targetAabb.getMin());\\n\\t\\t\\t\\tmax.max(targetAabb.getMax());\\n\\t\\t\\t}\\n\\t\\t\\tthis._aabb = new BoundingBox();\\n\\t\\t\\tthis._aabb.setMinMax(min, max);\\n\\t\\t}\\n\\t\\treturn this._aabb;\\n\\t}\\n\\tget morphPositions() {\\n\\t\\treturn this._morphPositions;\\n\\t}\\n\\tget morphNormals() {\\n\\t\\treturn this._morphNormals;\\n\\t}\\n\\t_init() {\\n\\t\\tthis._initTextureBased();\\n\\t\\tfor (let i = 0; i < this._targets.length; i++) {\\n\\t\\t\\tthis._targets[i]._postInit();\\n\\t\\t}\\n\\t}\\n\\t_findSparseSet(deltaArrays, ids, usedDataIndices) {\\n\\t\\tlet freeIndex = 1;\\n\\t\\tconst dataCount = deltaArrays[0].length;\\n\\t\\tfor (let v = 0; v < dataCount; v += 3) {\\n\\t\\t\\tlet vertexUsed = false;\\n\\t\\t\\tfor (let i = 0; i < deltaArrays.length; i++) {\\n\\t\\t\\t\\tconst data = deltaArrays[i];\\n\\t\\t\\t\\tif (data[v] !== 0 || data[v + 1] !== 0 || data[v + 2] !== 0) {\\n\\t\\t\\t\\t\\tvertexUsed = true;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (vertexUsed) {\\n\\t\\t\\t\\tids.push(freeIndex);\\n\\t\\t\\t\\tusedDataIndices.push(v / 3);\\n\\t\\t\\t\\tfreeIndex++;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tids.push(0);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn freeIndex;\\n\\t}\\n\\t_initTextureBased() {\\n\\t\\tconst deltaArrays = [], deltaInfos = [];\\n\\t\\tconst targets = this._targets;\\n\\t\\tfor (let i = 0; i < targets.length; i++) {\\n\\t\\t\\tconst target = targets[i];\\n\\t\\t\\tif (target.options.deltaPositions) {\\n\\t\\t\\t\\tdeltaArrays.push(target.options.deltaPositions);\\n\\t\\t\\t\\tdeltaInfos.push(true);\\n\\t\\t\\t}\\n\\t\\t\\tif (target.options.deltaNormals) {\\n\\t\\t\\t\\tdeltaArrays.push(target.options.deltaNormals);\\n\\t\\t\\t\\tdeltaInfos.push(false);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst ids = [], usedDataIndices = [];\\n\\t\\tconst freeIndex = this._findSparseSet(deltaArrays, ids, usedDataIndices);\\n\\t\\tconst maxTextureSize = this.device.maxTextureSize;\\n\\t\\tlet morphTextureWidth = Math.ceil(Math.sqrt(freeIndex));\\n\\t\\tmorphTextureWidth = Math.min(morphTextureWidth, maxTextureSize);\\n\\t\\tconst morphTextureHeight = Math.ceil(freeIndex / morphTextureWidth);\\n\\t\\tif (morphTextureHeight > maxTextureSize) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.morphTextureWidth = morphTextureWidth;\\n\\t\\tthis.morphTextureHeight = morphTextureHeight;\\n\\t\\tlet halfFloat = false;\\n\\t\\tconst float2Half = FloatPacking.float2Half;\\n\\t\\tif (this._textureFormat === PIXELFORMAT_RGBA16F) {\\n\\t\\t\\thalfFloat = true;\\n\\t\\t}\\n\\t\\tconst texturesDataPositions = [];\\n\\t\\tconst texturesDataNormals = [];\\n\\t\\tconst textureDataSize = morphTextureWidth * morphTextureHeight * 4;\\n\\t\\tfor (let i = 0; i < deltaArrays.length; i++) {\\n\\t\\t\\tconst data = deltaArrays[i];\\n\\t\\t\\tconst textureData = this._textureFormat === PIXELFORMAT_RGBA16F ? new Uint16Array(textureDataSize) : new Float32Array(textureDataSize);\\n\\t\\t\\t(deltaInfos[i] ? texturesDataPositions : texturesDataNormals).push(textureData);\\n\\t\\t\\tif (halfFloat) {\\n\\t\\t\\t\\tfor (let v = 0; v < usedDataIndices.length; v++) {\\n\\t\\t\\t\\t\\tconst index = usedDataIndices[v] * 3;\\n\\t\\t\\t\\t\\tconst dstIndex = v * 4 + 4;\\n\\t\\t\\t\\t\\ttextureData[dstIndex] = float2Half(data[index]);\\n\\t\\t\\t\\t\\ttextureData[dstIndex + 1] = float2Half(data[index + 1]);\\n\\t\\t\\t\\t\\ttextureData[dstIndex + 2] = float2Half(data[index + 2]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tfor (let v = 0; v < usedDataIndices.length; v++) {\\n\\t\\t\\t\\t\\tconst index = usedDataIndices[v] * 3;\\n\\t\\t\\t\\t\\tconst dstIndex = v * 4 + 4;\\n\\t\\t\\t\\t\\ttextureData[dstIndex] = data[index];\\n\\t\\t\\t\\t\\ttextureData[dstIndex + 1] = data[index + 1];\\n\\t\\t\\t\\t\\ttextureData[dstIndex + 2] = data[index + 2];\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (texturesDataPositions.length > 0) {\\n\\t\\t\\tthis.targetsTexturePositions = this._createTexture(\\\"MorphPositionsTexture\\\", this._textureFormat, targets.length, [texturesDataPositions]);\\n\\t\\t}\\n\\t\\tif (texturesDataNormals.length > 0) {\\n\\t\\t\\tthis.targetsTextureNormals = this._createTexture(\\\"MorphNormalsTexture\\\", this._textureFormat, targets.length, [texturesDataNormals]);\\n\\t\\t}\\n\\t\\tconst formatDesc = [{ semantic: SEMANTIC_ATTR15, components: 1, type: TYPE_UINT32, asInt: true }];\\n\\t\\tthis.vertexBufferIds = new VertexBuffer(this.device, new VertexFormat(this.device, formatDesc, ids.length), ids.length, {\\n\\t\\t\\tdata: new Uint32Array(ids)\\n\\t\\t});\\n\\t\\treturn true;\\n\\t}\\n\\tget targets() {\\n\\t\\treturn this._targets;\\n\\t}\\n\\t_updateMorphFlags() {\\n\\t\\tthis._morphPositions = false;\\n\\t\\tthis._morphNormals = false;\\n\\t\\tfor (let i = 0; i < this._targets.length; i++) {\\n\\t\\t\\tconst target = this._targets[i];\\n\\t\\t\\tif (target.morphPositions) {\\n\\t\\t\\t\\tthis._morphPositions = true;\\n\\t\\t\\t}\\n\\t\\t\\tif (target.morphNormals) {\\n\\t\\t\\t\\tthis._morphNormals = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_createTexture(name, format, arrayLength, levels) {\\n\\t\\treturn new Texture(this.device, {\\n\\t\\t\\tlevels,\\n\\t\\t\\tarrayLength,\\n\\t\\t\\twidth: this.morphTextureWidth,\\n\\t\\t\\theight: this.morphTextureHeight,\\n\\t\\t\\tformat,\\n\\t\\t\\tcubemap: false,\\n\\t\\t\\tmipmaps: false,\\n\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\tname\\n\\t\\t});\\n\\t}\\n}\\n\\nclass MorphTarget {\\n\\tused = false;\\n\\tconstructor(options) {\\n\\t\\tthis.options = options;\\n\\t\\tthis._name = options.name;\\n\\t\\tthis._defaultWeight = options.defaultWeight || 0;\\n\\t\\tthis._aabb = options.aabb;\\n\\t\\tthis.deltaPositions = options.deltaPositions;\\n\\t\\tthis.morphPositions = !!options.deltaPositions;\\n\\t\\tthis.morphNormals = !!options.deltaNormals;\\n\\t}\\n\\tget name() {\\n\\t\\treturn this._name;\\n\\t}\\n\\tget defaultWeight() {\\n\\t\\treturn this._defaultWeight;\\n\\t}\\n\\tget aabb() {\\n\\t\\tif (!this._aabb) {\\n\\t\\t\\tthis._aabb = new BoundingBox();\\n\\t\\t\\tif (this.deltaPositions) {\\n\\t\\t\\t\\tthis._aabb.compute(this.deltaPositions);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn this._aabb;\\n\\t}\\n\\tclone() {\\n\\t\\treturn new MorphTarget(this.options);\\n\\t}\\n\\t_postInit() {\\n\\t\\tif (!this.options.preserveData) {\\n\\t\\t\\tthis.options = null;\\n\\t\\t}\\n\\t\\tthis.used = true;\\n\\t}\\n}\\n\\nclass ShaderGeneratorShader extends ShaderGenerator {\\n\\tgenerateKey(options) {\\n\\t\\tconst desc = options.shaderDesc;\\n\\t\\tconst vsHashGLSL = desc.vertexGLSL ? hashCode(desc.vertexGLSL) : 0;\\n\\t\\tconst fsHashGLSL = desc.fragmentGLSL ? hashCode(desc.fragmentGLSL) : 0;\\n\\t\\tconst vsHashWGSL = desc.vertexWGSL ? hashCode(desc.vertexWGSL) : 0;\\n\\t\\tconst fsHashWGSL = desc.fragmentWGSL ? hashCode(desc.fragmentWGSL) : 0;\\n\\t\\tconst definesHash = ShaderGenerator.definesHash(options.defines);\\n\\t\\tconst chunksKey = options.shaderChunks?.key ?? \\\"\\\";\\n\\t\\tlet key = `${desc.uniqueName}_${definesHash}_${vsHashGLSL}_${fsHashGLSL}_${vsHashWGSL}_${fsHashWGSL}_${chunksKey}`;\\n\\t\\tif (options.skin) key += \\\"_skin\\\";\\n\\t\\tif (options.useInstancing) key += \\\"_inst\\\";\\n\\t\\tif (options.useMorphPosition) key += \\\"_morphp\\\";\\n\\t\\tif (options.useMorphNormal) key += \\\"_morphn\\\";\\n\\t\\tif (options.useMorphTextureBasedInt) key += \\\"_morphi\\\";\\n\\t\\treturn key;\\n\\t}\\n\\tcreateAttributesDefinition(definitionOptions, options) {\\n\\t\\tconst srcAttributes = options.shaderDesc.attributes;\\n\\t\\tconst attributes = srcAttributes ? { ...srcAttributes } : void 0;\\n\\t\\tif (options.skin) {\\n\\t\\t\\tattributes.vertex_boneWeights = SEMANTIC_BLENDWEIGHT;\\n\\t\\t\\tattributes.vertex_boneIndices = SEMANTIC_BLENDINDICES;\\n\\t\\t}\\n\\t\\tif (options.useMorphPosition || options.useMorphNormal) {\\n\\t\\t\\tattributes.morph_vertex_id = SEMANTIC_ATTR15;\\n\\t\\t}\\n\\t\\tdefinitionOptions.attributes = attributes;\\n\\t}\\n\\tcreateVertexDefinition(definitionOptions, options, sharedIncludes, wgsl) {\\n\\t\\tconst desc = options.shaderDesc;\\n\\t\\tconst includes = new Map(sharedIncludes);\\n\\t\\tincludes.set(\\\"transformInstancingVS\\\", \\\"\\\");\\n\\t\\tconst defines = new Map(options.defines);\\n\\t\\tif (options.skin) defines.set(\\\"SKIN\\\", true);\\n\\t\\tif (options.useInstancing) defines.set(\\\"INSTANCING\\\", true);\\n\\t\\tif (options.useMorphPosition || options.useMorphNormal) {\\n\\t\\t\\tdefines.set(\\\"MORPHING\\\", true);\\n\\t\\t\\tif (options.useMorphTextureBasedInt) defines.set(\\\"MORPHING_INT\\\", true);\\n\\t\\t\\tif (options.useMorphPosition) defines.set(\\\"MORPHING_POSITION\\\", true);\\n\\t\\t\\tif (options.useMorphNormal) defines.set(\\\"MORPHING_NORMAL\\\", true);\\n\\t\\t}\\n\\t\\tdefinitionOptions.vertexCode = wgsl ? desc.vertexWGSL : desc.vertexGLSL;\\n\\t\\tdefinitionOptions.vertexIncludes = includes;\\n\\t\\tdefinitionOptions.vertexDefines = defines;\\n\\t}\\n\\tcreateFragmentDefinition(definitionOptions, options, sharedIncludes, wgsl) {\\n\\t\\tconst desc = options.shaderDesc;\\n\\t\\tconst includes = new Map(sharedIncludes);\\n\\t\\tconst defines = new Map(options.defines);\\n\\t\\tdefinitionOptions.fragmentCode = wgsl ? desc.fragmentWGSL : desc.fragmentGLSL;\\n\\t\\tdefinitionOptions.fragmentIncludes = includes;\\n\\t\\tdefinitionOptions.fragmentDefines = defines;\\n\\t}\\n\\tcreateShaderDefinition(device, options) {\\n\\t\\tconst desc = options.shaderDesc;\\n\\t\\tconst wgsl = device.isWebGPU && !!desc.vertexWGSL && !!desc.fragmentWGSL && (options.shaderChunks?.useWGSL ?? true);\\n\\t\\tconst definitionOptions = {\\n\\t\\t\\tname: `ShaderMaterial-${desc.uniqueName}`,\\n\\t\\t\\tshaderLanguage: wgsl ? SHADERLANGUAGE_WGSL : SHADERLANGUAGE_GLSL,\\n\\t\\t\\tfragmentOutputTypes: desc.fragmentOutputTypes,\\n\\t\\t\\tmeshUniformBufferFormat: desc.meshUniformBufferFormat,\\n\\t\\t\\tmeshBindGroupFormat: desc.meshBindGroupFormat\\n\\t\\t};\\n\\t\\tconst shaderLanguage = wgsl ? SHADERLANGUAGE_WGSL : SHADERLANGUAGE_GLSL;\\n\\t\\tconst sharedIncludes = MapUtils.merge(\\n\\t\\t\\tShaderChunks.get(device, shaderLanguage),\\n\\t\\t\\toptions.shaderChunks[shaderLanguage]\\n\\t\\t);\\n\\t\\tthis.createAttributesDefinition(definitionOptions, options);\\n\\t\\tthis.createVertexDefinition(definitionOptions, options, sharedIncludes, wgsl);\\n\\t\\tthis.createFragmentDefinition(definitionOptions, options, sharedIncludes, wgsl);\\n\\t\\treturn ShaderDefinitionUtils.createDefinition(device, definitionOptions);\\n\\t}\\n}\\nconst shaderGeneratorShader = new ShaderGeneratorShader();\\n\\nclass ShaderMaterial extends Material {\\n\\t_shaderDesc;\\n\\tconstructor(shaderDesc) {\\n\\t\\tsuper();\\n\\t\\tthis.shaderDesc = shaderDesc;\\n\\t}\\n\\tset shaderDesc(value) {\\n\\t\\tthis._shaderDesc = void 0;\\n\\t\\tif (value) {\\n\\t\\t\\tthis._shaderDesc = {\\n\\t\\t\\t\\tuniqueName: value.uniqueName,\\n\\t\\t\\t\\tattributes: value.attributes,\\n\\t\\t\\t\\tfragmentOutputTypes: value.fragmentOutputTypes,\\n\\t\\t\\t\\tvertexGLSL: value.vertexGLSL,\\n\\t\\t\\t\\tfragmentGLSL: value.fragmentGLSL,\\n\\t\\t\\t\\tvertexWGSL: value.vertexWGSL,\\n\\t\\t\\t\\tfragmentWGSL: value.fragmentWGSL\\n\\t\\t\\t};\\n\\t\\t\\tif (value.vertexCode || value.fragmentCode || value.shaderLanguage) {\\n\\t\\t\\t\\tconst language = value.shaderLanguage ?? SHADERLANGUAGE_GLSL;\\n\\t\\t\\t\\tif (language === SHADERLANGUAGE_GLSL) {\\n\\t\\t\\t\\t\\tthis._shaderDesc.vertexGLSL = value.vertexCode;\\n\\t\\t\\t\\t\\tthis._shaderDesc.fragmentGLSL = value.fragmentCode;\\n\\t\\t\\t\\t} else if (language === SHADERLANGUAGE_WGSL) {\\n\\t\\t\\t\\t\\tthis._shaderDesc.vertexWGSL = value.vertexCode;\\n\\t\\t\\t\\t\\tthis._shaderDesc.fragmentWGSL = value.fragmentCode;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.clearVariants();\\n\\t}\\n\\tget shaderDesc() {\\n\\t\\treturn this._shaderDesc;\\n\\t}\\n\\tcopy(source) {\\n\\t\\tsuper.copy(source);\\n\\t\\tthis.shaderDesc = source.shaderDesc;\\n\\t\\treturn this;\\n\\t}\\n\\tgetShaderVariant(params) {\\n\\t\\tconst { objDefs } = params;\\n\\t\\tconst options = {\\n\\t\\t\\tdefines: ShaderUtils.getCoreDefines(this, params),\\n\\t\\t\\tskin: (objDefs & SHADERDEF_SKIN) !== 0,\\n\\t\\t\\tuseInstancing: (objDefs & SHADERDEF_INSTANCING) !== 0,\\n\\t\\t\\tuseMorphPosition: (objDefs & SHADERDEF_MORPH_POSITION) !== 0,\\n\\t\\t\\tuseMorphNormal: (objDefs & SHADERDEF_MORPH_NORMAL) !== 0,\\n\\t\\t\\tuseMorphTextureBasedInt: (objDefs & SHADERDEF_MORPH_TEXTURE_BASED_INT) !== 0,\\n\\t\\t\\tpass: params.pass,\\n\\t\\t\\tgamma: params.cameraShaderParams.shaderOutputGamma,\\n\\t\\t\\ttoneMapping: params.cameraShaderParams.toneMapping,\\n\\t\\t\\tfog: params.cameraShaderParams.fog,\\n\\t\\t\\tshaderDesc: this.shaderDesc,\\n\\t\\t\\tshaderChunks: this.shaderChunks\\n\\t\\t\\t// override chunks from the material\\n\\t\\t};\\n\\t\\tconst processingOptions = new ShaderProcessorOptions(params.viewUniformFormat, params.viewBindGroupFormat, params.vertexFormat);\\n\\t\\tconst library = getProgramLibrary(params.device);\\n\\t\\tlibrary.register(\\\"shader-material\\\", shaderGeneratorShader);\\n\\t\\treturn library.getProgram(\\\"shader-material\\\", options, processingOptions, this.userId);\\n\\t}\\n}\\n\\nvar gsplatStreamDecl_default$1 = `\\nuniform highp {sampler} {name};\\n{returnType} load{funcName}() { return texelFetch({name}, splat.uv, 0); }\\n{returnType} load{funcName}WithIndex(uint index) { return texelFetch({name}, ivec2(index % splatTextureSize, index / splatTextureSize), 0); }\\n`;\\n\\nvar gsplatStreamDecl_default = `\\nvar {name}: {textureType};\\nfn load{funcName}() -> {returnType} { return textureLoad({name}, splat.uv, 0); }\\nfn load{funcName}WithIndex(index: u32) -> {returnType} { return textureLoad({name}, vec2i(i32(index % uniform.splatTextureSize), i32(index / uniform.splatTextureSize)), 0); }\\n`;\\n\\nvar gsplatComputeStreamDecl_default = `\\n@group(0) @binding({binding}) var {name}: {textureType};\\nfn load{funcName}() -> {returnType} { return textureLoad({name}, splat.uv, 0); }\\nfn load{funcName}WithIndex(index: u32) -> {returnType} { return textureLoad({name}, vec2i(i32(index % uniforms.splatTextureSize), i32(index / uniforms.splatTextureSize)), 0); }\\n`;\\n\\nvar gsplatStreamOutput_default$1 = `\\nvoid write{funcName}({returnType} value) {\\n#if {defineGuard}\\n\\tpcFragColor{index} = value;\\n#endif\\n}\\n`;\\n\\nvar gsplatStreamOutput_default = `\\nfn write{funcName}(value: {returnType}) {\\n#if {defineGuard}\\n\\tprocessOutput.{colorSlot} = value;\\n#endif\\n}\\n`;\\n\\nvar containerFloatRead_default$1 = `\\nvec3 getCenter() { return loadDataCenter().xyz; }\\nvec4 getColor() { return loadDataColor(); }\\nvec3 getScale() { return loadDataScale().xyz; }\\nvec4 getRotation() { return loadDataRotation(); }\\n`;\\n\\nvar containerFloatRead_default = `\\nfn getCenter() -> vec3f { return loadDataCenter().xyz; }\\nfn getColor() -> vec4f { return loadDataColor(); }\\nfn getScale() -> vec3f { return loadDataScale().xyz; }\\nfn getRotation() -> vec4f { return loadDataRotation(); }\\n`;\\n\\nvar containerSimpleRead_default$1 = `\\n\\tvec3 getCenter() { return loadDataCenter().xyz; }\\n\\tvec4 getColor() { return loadDataColor(); }\\n\\tvec3 getScale() { return vec3(loadDataCenter().w); }\\n\\tvec4 getRotation() { return vec4(0.0, 0.0, 0.0, 1.0); }\\n`;\\n\\nvar containerSimpleRead_default = `\\n\\tfn getCenter() -> vec3f { return loadDataCenter().xyz; }\\n\\tfn getColor() -> vec4f { return loadDataColor(); }\\n\\tfn getScale() -> vec3f { return vec3f(loadDataCenter().w); }\\n\\tfn getRotation() -> vec4f { return vec4f(0.0, 0.0, 0.0, 1.0); }\\n`;\\n\\nconst serializeStreams = (streams) => streams.map((s) => `${s.name}:${s.format}:${s.storage}`).join(\\\",\\\");\\nconst RE_NAME = /\\\\{name\\\\}/g;\\nconst RE_SAMPLER = /\\\\{sampler\\\\}/g;\\nconst RE_TEXTURE_TYPE = /\\\\{textureType\\\\}/g;\\nconst RE_RETURN_TYPE = /\\\\{returnType\\\\}/g;\\nconst RE_FUNC_NAME = /\\\\{funcName\\\\}/g;\\nconst RE_BINDING = /\\\\{binding\\\\}/g;\\nconst RE_INDEX = /\\\\{index\\\\}/g;\\nconst RE_COLOR_SLOT = /\\\\{colorSlot\\\\}/g;\\nconst RE_DEFINE_GUARD = /\\\\{defineGuard\\\\}/g;\\nclass GSplatFormat {\\n\\t_device;\\n\\tstreams;\\n\\t_read;\\n\\tallowStreamRemoval = false;\\n\\t_extraStreams = [];\\n\\t_streamNames = /* @__PURE__ */ new Set();\\n\\t_extraStreamsVersion = 0;\\n\\t_hash;\\n\\t_resourceStreams = null;\\n\\t_instanceStreams = null;\\n\\tconstructor(device, streams, options) {\\n\\t\\tthis._device = device;\\n\\t\\tthis.streams = [...streams];\\n\\t\\tthis._streamNames = new Set(this.streams.map((s) => s.name));\\n\\t\\tconst isWebGPU = device.isWebGPU;\\n\\t\\tthis._read = isWebGPU ? options.readWGSL : options.readGLSL;\\n\\t}\\n\\tget hash() {\\n\\t\\tif (this._hash === void 0) {\\n\\t\\t\\tconst streamsStr = serializeStreams(this.streams);\\n\\t\\t\\tconst extraStr = serializeStreams(this._extraStreams);\\n\\t\\t\\tthis._hash = hashCode(\\n\\t\\t\\t\\tstreamsStr + extraStr + this._read\\n\\t\\t\\t);\\n\\t\\t}\\n\\t\\treturn this._hash;\\n\\t}\\n\\tget extraStreamsVersion() {\\n\\t\\treturn this._extraStreamsVersion;\\n\\t}\\n\\tget extraStreams() {\\n\\t\\treturn this._extraStreams;\\n\\t}\\n\\tget resourceStreams() {\\n\\t\\tif (this._resourceStreams === null) {\\n\\t\\t\\tthis._resourceStreams = [\\n\\t\\t\\t\\t...this.streams.filter((s) => s.storage !== GSPLAT_STREAM_INSTANCE),\\n\\t\\t\\t\\t...this._extraStreams.filter((s) => s.storage !== GSPLAT_STREAM_INSTANCE)\\n\\t\\t\\t];\\n\\t\\t}\\n\\t\\treturn this._resourceStreams;\\n\\t}\\n\\tget instanceStreams() {\\n\\t\\tif (this._instanceStreams === null) {\\n\\t\\t\\tthis._instanceStreams = this._extraStreams.filter((s) => s.storage === GSPLAT_STREAM_INSTANCE);\\n\\t\\t}\\n\\t\\treturn this._instanceStreams;\\n\\t}\\n\\taddExtraStreams(streams) {\\n\\t\\tif (!streams || streams.length === 0) return;\\n\\t\\tlet added = false;\\n\\t\\tfor (const s of streams) {\\n\\t\\t\\tif (this._streamNames.has(s.name)) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tthis._extraStreams.push({\\n\\t\\t\\t\\tname: s.name,\\n\\t\\t\\t\\tformat: s.format,\\n\\t\\t\\t\\tstorage: s.storage ?? GSPLAT_STREAM_RESOURCE\\n\\t\\t\\t});\\n\\t\\t\\tthis._streamNames.add(s.name);\\n\\t\\t\\tadded = true;\\n\\t\\t}\\n\\t\\tif (added) {\\n\\t\\t\\tthis._extraStreamsVersion++;\\n\\t\\t\\tthis._invalidateCaches();\\n\\t\\t}\\n\\t}\\n\\tremoveExtraStreams(names) {\\n\\t\\tif (!this.allowStreamRemoval) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tlet removed = false;\\n\\t\\tfor (const name of names) {\\n\\t\\t\\tconst idx = this._extraStreams.findIndex((s) => s.name === name);\\n\\t\\t\\tif (idx !== -1) {\\n\\t\\t\\t\\tthis._extraStreams.splice(idx, 1);\\n\\t\\t\\t\\tthis._streamNames.delete(name);\\n\\t\\t\\t\\tremoved = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (removed) {\\n\\t\\t\\tthis._extraStreamsVersion++;\\n\\t\\t\\tthis._invalidateCaches();\\n\\t\\t}\\n\\t}\\n\\tgetInputDeclarations(streamNames) {\\n\\t\\tconst isWebGPU = this._device.isWebGPU;\\n\\t\\tconst template = isWebGPU ? gsplatStreamDecl_default : gsplatStreamDecl_default$1;\\n\\t\\tconst getShaderType = isWebGPU ? getWgslShaderType : getGlslShaderType;\\n\\t\\tconst lines = [];\\n\\t\\tlet streams = [...this.streams, ...this._extraStreams];\\n\\t\\tif (streamNames) {\\n\\t\\t\\tstreams = streams.filter((s) => streamNames.includes(s.name));\\n\\t\\t}\\n\\t\\tfor (const stream of streams) {\\n\\t\\t\\tconst info = getShaderType(stream.format);\\n\\t\\t\\tconst funcName = stream.name.charAt(0).toUpperCase() + stream.name.slice(1);\\n\\t\\t\\tlet textureType = info.textureType ?? \\\"\\\";\\n\\t\\t\\tif (isWebGPU && stream.format === PIXELFORMAT_RGBA32F) {\\n\\t\\t\\t\\ttextureType = \\\"texture_2d<uff>\\\";\\n\\t\\t\\t}\\n\\t\\t\\tconst decl = template.replace(RE_NAME, stream.name).replace(RE_SAMPLER, info.sampler ?? \\\"\\\").replace(RE_TEXTURE_TYPE, textureType).replace(RE_RETURN_TYPE, info.returnType).replace(RE_FUNC_NAME, funcName);\\n\\t\\t\\tlines.push(decl);\\n\\t\\t}\\n\\t\\treturn lines.join(\\\"\\\\n\\\");\\n\\t}\\n\\tgetReadCode() {\\n\\t\\treturn this._read;\\n\\t}\\n\\tgetComputeInputDeclarations(startBinding, streamNames) {\\n\\t\\tconst lines = [];\\n\\t\\tlet streams = [...this.streams, ...this._extraStreams];\\n\\t\\tif (streamNames) {\\n\\t\\t\\tstreams = streams.filter((s) => streamNames.includes(s.name));\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < streams.length; i++) {\\n\\t\\t\\tconst stream = streams[i];\\n\\t\\t\\tconst info = getWgslShaderType(stream.format);\\n\\t\\t\\tconst funcName = stream.name.charAt(0).toUpperCase() + stream.name.slice(1);\\n\\t\\t\\tlet textureType = info.textureType ?? \\\"\\\";\\n\\t\\t\\tif (stream.format === PIXELFORMAT_RGBA32F) {\\n\\t\\t\\t\\ttextureType = \\\"texture_2d<uff>\\\";\\n\\t\\t\\t}\\n\\t\\t\\tconst decl = gsplatComputeStreamDecl_default.replace(RE_BINDING, String(startBinding + i)).replace(RE_NAME, stream.name).replace(RE_TEXTURE_TYPE, textureType).replace(RE_RETURN_TYPE, info.returnType).replace(RE_FUNC_NAME, funcName);\\n\\t\\t\\tlines.push(decl);\\n\\t\\t}\\n\\t\\treturn lines.join(\\\"\\\\n\\\");\\n\\t}\\n\\tgetComputeBindFormats(streamNames) {\\n\\t\\tlet streams = [...this.streams, ...this._extraStreams];\\n\\t\\tif (streamNames) {\\n\\t\\t\\tstreams = streams.filter((s) => streamNames.includes(s.name));\\n\\t\\t}\\n\\t\\treturn streams.map((stream) => {\\n\\t\\t\\tconst info = pixelFormatInfo.get(stream.format);\\n\\t\\t\\tlet sampleType = SAMPLETYPE_FLOAT;\\n\\t\\t\\tif (info?.isUint) sampleType = SAMPLETYPE_UINT;\\n\\t\\t\\telse if (info?.isInt) sampleType = SAMPLETYPE_INT;\\n\\t\\t\\treturn new BindTextureFormat(stream.name, SHADERSTAGE_COMPUTE, void 0, sampleType, false);\\n\\t\\t});\\n\\t}\\n\\tsetWriteCode(writeGLSL, writeWGSL) {\\n\\t\\tthis._write = this._device.isWebGPU ? writeWGSL : writeGLSL;\\n\\t}\\n\\tgetWriteCode() {\\n\\t\\treturn this._write;\\n\\t}\\n\\tgetOutputDeclarations(outputStreams) {\\n\\t\\tconst isWebGPU = this._device.isWebGPU;\\n\\t\\tconst lines = [];\\n\\t\\tconst template = isWebGPU ? gsplatStreamOutput_default : gsplatStreamOutput_default$1;\\n\\t\\tconst getShaderType = isWebGPU ? getWgslShaderType : getGlslShaderType;\\n\\t\\tfor (let i = 0; i < outputStreams.length; i++) {\\n\\t\\t\\tconst stream = outputStreams[i];\\n\\t\\t\\tconst info = getShaderType(stream.format);\\n\\t\\t\\tconst funcName = stream.name.charAt(0).toUpperCase() + stream.name.slice(1);\\n\\t\\t\\tconst colorSlot = i === 0 ? \\\"color\\\" : `color${i}`;\\n\\t\\t\\tconst decl = template.replace(RE_FUNC_NAME, funcName).replace(RE_RETURN_TYPE, info.returnType).replace(RE_INDEX, String(i)).replace(RE_COLOR_SLOT, colorSlot).replace(RE_DEFINE_GUARD, \\\"1\\\");\\n\\t\\t\\tlines.push(decl);\\n\\t\\t}\\n\\t\\treturn lines.join(\\\"\\\\n\\\");\\n\\t}\\n\\tgetOutputStubs(streams) {\\n\\t\\tconst isWebGPU = this._device.isWebGPU;\\n\\t\\tconst lines = [];\\n\\t\\tconst template = isWebGPU ? gsplatStreamOutput_default : gsplatStreamOutput_default$1;\\n\\t\\tconst getShaderType = isWebGPU ? getWgslShaderType : getGlslShaderType;\\n\\t\\tfor (const stream of streams) {\\n\\t\\t\\tconst info = getShaderType(stream.format);\\n\\t\\t\\tconst funcName = stream.name.charAt(0).toUpperCase() + stream.name.slice(1);\\n\\t\\t\\tconst stub = template.replace(RE_FUNC_NAME, funcName).replace(RE_RETURN_TYPE, info.returnType).replace(RE_DEFINE_GUARD, \\\"0\\\");\\n\\t\\t\\tlines.push(stub);\\n\\t\\t}\\n\\t\\treturn lines.join(\\\"\\\\n\\\");\\n\\t}\\n\\tgetStream(name) {\\n\\t\\tlet stream = this.streams.find((s) => s.name === name);\\n\\t\\tif (!stream) {\\n\\t\\t\\tstream = this._extraStreams.find((s) => s.name === name);\\n\\t\\t}\\n\\t\\treturn stream;\\n\\t}\\n\\t_invalidateCaches() {\\n\\t\\tthis._hash = void 0;\\n\\t\\tthis._resourceStreams = null;\\n\\t\\tthis._instanceStreams = null;\\n\\t}\\n\\tstatic createDefaultFormat(device) {\\n\\t\\treturn new GSplatFormat(device, [\\n\\t\\t\\t{ name: \\\"dataColor\\\", format: PIXELFORMAT_RGBA16F },\\n\\t\\t\\t{ name: \\\"dataCenter\\\", format: PIXELFORMAT_RGBA32F },\\n\\t\\t\\t{ name: \\\"dataScale\\\", format: PIXELFORMAT_RGBA16F },\\n\\t\\t\\t{ name: \\\"dataRotation\\\", format: PIXELFORMAT_RGBA16F }\\n\\t\\t], {\\n\\t\\t\\treadGLSL: containerFloatRead_default$1,\\n\\t\\t\\treadWGSL: containerFloatRead_default\\n\\t\\t});\\n\\t}\\n\\tstatic createSimpleFormat(device) {\\n\\t\\treturn new GSplatFormat(device, [\\n\\t\\t\\t{ name: \\\"dataCenter\\\", format: PIXELFORMAT_RGBA32F },\\n\\t\\t\\t{ name: \\\"dataColor\\\", format: PIXELFORMAT_RGBA16F }\\n\\t\\t], {\\n\\t\\t\\treadGLSL: containerSimpleRead_default$1,\\n\\t\\t\\treadWGSL: containerSimpleRead_default\\n\\t\\t});\\n\\t}\\n}\\n\\nvar containerCompactRead_default$1 = `\\nuvec4 cachedTransformA;\\nvec3 getCenter() {\\n\\tcachedTransformA = loadDataTransformA();\\n\\treturn vec3(uintBitsToFloat(cachedTransformA.r), uintBitsToFloat(cachedTransformA.g), uintBitsToFloat(cachedTransformA.b));\\n}\\nfloat getOpacity() {\\n\\treturn float(cachedTransformA.a >> 24u) / 255.0;\\n}\\nvec3 getColor() {\\n\\tuint data = loadDataColor().x;\\n\\tfloat r = float(data & 0x7FFu) * (4.0 / 2047.0);\\n\\tfloat g = float((data >> 11u) & 0x7FFu) * (4.0 / 2047.0);\\n\\tfloat b = float((data >> 22u) & 0x3FFu) * (4.0 / 1023.0);\\n\\treturn vec3(r, g, b);\\n}\\nvec4 getRotation() {\\n\\tuint data = loadDataTransformB().x;\\n\\tvec3 p = vec3(\\n\\t\\tfloat(data & 0x7FFu) / 2047.0 * 2.0 - 1.0,\\n\\t\\tfloat((data >> 11u) & 0x7FFu) / 2047.0 * 2.0 - 1.0,\\n\\t\\tfloat((data >> 22u) & 0x3FFu) / 1023.0 * 2.0 - 1.0\\n\\t);\\n\\tfloat d = dot(p, p);\\n\\treturn vec4(1.0 - d, sqrt(max(0.0, 2.0 - d)) * p);\\n}\\nvec3 getScale() {\\n\\tuint data = cachedTransformA.a;\\n\\tfloat sx = float(data & 0xFFu);\\n\\tfloat sy = float((data >> 8u) & 0xFFu);\\n\\tfloat sz = float((data >> 16u) & 0xFFu);\\n\\tconst float logRange = 21.0 / 255.0;\\n\\tconst float logMin = -12.0;\\n\\treturn vec3(\\n\\t\\tsx == 0.0 ? 0.0 : exp(sx * logRange + logMin),\\n\\t\\tsy == 0.0 ? 0.0 : exp(sy * logRange + logMin),\\n\\t\\tsz == 0.0 ? 0.0 : exp(sz * logRange + logMin)\\n\\t);\\n}\\n`;\\n\\nvar containerCompactWrite_default$1 = `\\nvoid writeSplat(vec3 center, vec4 rotation, vec3 scale, vec4 color) {\\n\\tvec3 rgb = clamp(color.rgb, 0.0, 4.0);\\n\\tuint rBits = uint(rgb.r * (2047.0 / 4.0) + 0.5);\\n\\tuint gBits = uint(rgb.g * (2047.0 / 4.0) + 0.5);\\n\\tuint bBits = uint(rgb.b * (1023.0 / 4.0) + 0.5);\\n\\twriteDataColor(uvec4(rBits | (gBits << 11u) | (bBits << 22u), 0u, 0u, 0u));\\n\\t#ifndef GSPLAT_COLOR_ONLY\\n\\t\\tvec4 q = rotation;\\n\\t\\tif (q.w < 0.0) q = -q;\\n\\t\\tvec3 p = q.xyz * inversesqrt(1.0 + q.w);\\n\\t\\tuint aBitsQ = uint(clamp((p.x * 0.5 + 0.5) * 2047.0 + 0.5, 0.0, 2047.0));\\n\\t\\tuint bBitsQ = uint(clamp((p.y * 0.5 + 0.5) * 2047.0 + 0.5, 0.0, 2047.0));\\n\\t\\tuint cBitsQ = uint(clamp((p.z * 0.5 + 0.5) * 1023.0 + 0.5, 0.0, 1023.0));\\n\\t\\tuint packedQuat = aBitsQ | (bBitsQ << 11u) | (cBitsQ << 22u);\\n\\t\\tconst float invLogRange = 255.0 / 21.0;\\n\\t\\tconst float logMin = -12.0;\\n\\t\\tuint sxBits = scale.x < 1e-10 ? 0u : uint(clamp((log(scale.x) - logMin) * invLogRange + 0.5, 1.0, 255.0));\\n\\t\\tuint syBits = scale.y < 1e-10 ? 0u : uint(clamp((log(scale.y) - logMin) * invLogRange + 0.5, 1.0, 255.0));\\n\\t\\tuint szBits = scale.z < 1e-10 ? 0u : uint(clamp((log(scale.z) - logMin) * invLogRange + 0.5, 1.0, 255.0));\\n\\t\\tuint alphaBits = uint(clamp(color.a, 0.0, 1.0) * 255.0 + 0.5);\\n\\t\\tuint packedScaleAlpha = sxBits | (syBits << 8u) | (szBits << 16u) | (alphaBits << 24u);\\n\\t\\twriteDataTransformA(uvec4(floatBitsToUint(center.x), floatBitsToUint(center.y), floatBitsToUint(center.z), packedScaleAlpha));\\n\\t\\twriteDataTransformB(uvec4(packedQuat, 0u, 0u, 0u));\\n\\t#endif\\n}\\n`;\\n\\nvar containerPackedRead_default$1 = `\\nuvec4 cachedTransformA;\\nuvec2 cachedTransformB;\\nvec4 cachedColor;\\nvec3 getCenter() {\\n\\tcachedTransformA = loadDataTransformA();\\n\\tcachedTransformB = loadDataTransformB().xy;\\n\\treturn vec3(uintBitsToFloat(cachedTransformA.r), uintBitsToFloat(cachedTransformA.g), uintBitsToFloat(cachedTransformA.b));\\n}\\nfloat getOpacity() {\\n\\t#ifdef GSPLAT_COLOR_FLOAT\\n\\t\\tcachedColor = loadDataColor();\\n\\t#else\\n\\t\\tuvec4 packedColor = loadDataColor();\\n\\t\\tuint packed_rg = packedColor.r | (packedColor.g << 16u);\\n\\t\\tuint packed_ba = packedColor.b | (packedColor.a << 16u);\\n\\t\\tcachedColor = vec4(unpackHalf2x16(packed_rg), unpackHalf2x16(packed_ba));\\n\\t#endif\\n\\treturn cachedColor.a;\\n}\\nvec3 getColor() {\\n\\treturn cachedColor.rgb;\\n}\\nvec4 getRotation() {\\n\\tvec2 rotXY = unpackHalf2x16(cachedTransformA.a);\\n\\tvec2 rotZscaleX = unpackHalf2x16(cachedTransformB.x);\\n\\tvec3 rotXYZ = vec3(rotXY, rotZscaleX.x);\\n\\treturn vec4(rotXYZ, sqrt(max(0.0, 1.0 - dot(rotXYZ, rotXYZ)))).wxyz;\\n}\\nvec3 getScale() {\\n\\tvec2 rotZscaleX = unpackHalf2x16(cachedTransformB.x);\\n\\tvec2 scaleYZ = unpackHalf2x16(cachedTransformB.y);\\n\\treturn vec3(rotZscaleX.y, scaleYZ);\\n}\\n`;\\n\\nvar containerPackedWrite_default$1 = `\\nvoid writeSplat(vec3 center, vec4 rotation, vec3 scale, vec4 color) {\\n\\t#ifdef GSPLAT_COLOR_UINT\\n\\t\\tuint packed_rg = packHalf2x16(color.rg);\\n\\t\\tuint packed_ba = packHalf2x16(color.ba);\\n\\t\\twriteDataColor(uvec4(\\n\\t\\t\\tpacked_rg & 0xFFFFu,\\n\\t\\t\\tpacked_rg >> 16u,\\n\\t\\t\\tpacked_ba & 0xFFFFu,\\n\\t\\t\\tpacked_ba >> 16u\\n\\t\\t));\\n\\t#else\\n\\t\\twriteDataColor(color);\\n\\t#endif\\n\\t#ifndef GSPLAT_COLOR_ONLY\\n\\t\\twriteDataTransformA(uvec4(floatBitsToUint(center.x), floatBitsToUint(center.y), floatBitsToUint(center.z), packHalf2x16(rotation.xy)));\\n\\t\\twriteDataTransformB(uvec4(packHalf2x16(vec2(rotation.z, scale.x)), packHalf2x16(scale.yz), 0u, 0u));\\n\\t#endif\\n}\\n`;\\n\\nvar containerCompactRead_default = `\\nvar<private> cachedTransformA: vec4u;\\nfn getCenter() -> vec3f {\\n\\tcachedTransformA = loadDataTransformA();\\n\\treturn vec3f(bitcast<f32>(cachedTransformA.r), bitcast<f32>(cachedTransformA.g), bitcast<f32>(cachedTransformA.b));\\n}\\nfn getOpacity() -> f32 {\\n\\treturn f32(cachedTransformA.a >> 24u) / 255.0;\\n}\\nfn getColor() -> vec3f {\\n\\tlet data = loadDataColor().x;\\n\\tlet r = f32(data & 0x7FFu) * (4.0 / 2047.0);\\n\\tlet g = f32((data >> 11u) & 0x7FFu) * (4.0 / 2047.0);\\n\\tlet b = f32((data >> 22u) & 0x3FFu) * (4.0 / 1023.0);\\n\\treturn vec3f(r, g, b);\\n}\\nfn getRotation() -> vec4f {\\n\\tlet data = loadDataTransformB().x;\\n\\tlet p = vec3f(\\n\\t\\tf32(data & 0x7FFu) / 2047.0 * 2.0 - 1.0,\\n\\t\\tf32((data >> 11u) & 0x7FFu) / 2047.0 * 2.0 - 1.0,\\n\\t\\tf32((data >> 22u) & 0x3FFu) / 1023.0 * 2.0 - 1.0\\n\\t);\\n\\tlet d = dot(p, p);\\n\\treturn vec4f(1.0 - d, sqrt(max(0.0, 2.0 - d)) * p);\\n}\\nfn getScale() -> vec3f {\\n\\tlet data = cachedTransformA.a;\\n\\tlet sx = f32(data & 0xFFu);\\n\\tlet sy = f32((data >> 8u) & 0xFFu);\\n\\tlet sz = f32((data >> 16u) & 0xFFu);\\n\\tlet logRange = 21.0 / 255.0;\\n\\tlet logMin = -12.0;\\n\\treturn vec3f(\\n\\t\\tselect(exp(sx * logRange + logMin), 0.0, sx == 0.0),\\n\\t\\tselect(exp(sy * logRange + logMin), 0.0, sy == 0.0),\\n\\t\\tselect(exp(sz * logRange + logMin), 0.0, sz == 0.0)\\n\\t);\\n}\\n`;\\n\\nvar containerCompactWrite_default = `\\nfn writeSplat(center: vec3f, rotation: vec4f, scale: vec3f, color: vec4f) {\\n\\tlet rgb = clamp(color.rgb, vec3f(0.0), vec3f(4.0));\\n\\tlet rBits = u32(rgb.r * (2047.0 / 4.0) + 0.5);\\n\\tlet gBits = u32(rgb.g * (2047.0 / 4.0) + 0.5);\\n\\tlet bBits = u32(rgb.b * (1023.0 / 4.0) + 0.5);\\n\\twriteDataColor(vec4u(rBits | (gBits << 11u) | (bBits << 22u), 0u, 0u, 0u));\\n\\t#ifndef GSPLAT_COLOR_ONLY\\n\\t\\tvar q = rotation;\\n\\t\\tif (q.w < 0.0) { q = -q; }\\n\\t\\tlet p = q.xyz * inverseSqrt(1.0 + q.w);\\n\\t\\tlet aBitsQ = u32(clamp(p.x * 0.5 + 0.5, 0.0, 1.0) * 2047.0 + 0.5);\\n\\t\\tlet bBitsQ = u32(clamp(p.y * 0.5 + 0.5, 0.0, 1.0) * 2047.0 + 0.5);\\n\\t\\tlet cBitsQ = u32(clamp(p.z * 0.5 + 0.5, 0.0, 1.0) * 1023.0 + 0.5);\\n\\t\\tlet packedQuat = aBitsQ | (bBitsQ << 11u) | (cBitsQ << 22u);\\n\\t\\tlet invLogRange = 255.0 / 21.0;\\n\\t\\tlet logMin = -12.0;\\n\\t\\tlet sxBits = select(u32(clamp((log(scale.x) - logMin) * invLogRange + 0.5, 1.0, 255.0)), 0u, scale.x < 1e-10);\\n\\t\\tlet syBits = select(u32(clamp((log(scale.y) - logMin) * invLogRange + 0.5, 1.0, 255.0)), 0u, scale.y < 1e-10);\\n\\t\\tlet szBits = select(u32(clamp((log(scale.z) - logMin) * invLogRange + 0.5, 1.0, 255.0)), 0u, scale.z < 1e-10);\\n\\t\\tlet alphaBits = u32(clamp(color.a, 0.0, 1.0) * 255.0 + 0.5);\\n\\t\\tlet packedScaleAlpha = sxBits | (syBits << 8u) | (szBits << 16u) | (alphaBits << 24u);\\n\\t\\twriteDataTransformA(vec4u(bitcast<u32>(center.x), bitcast<u32>(center.y), bitcast<u32>(center.z), packedScaleAlpha));\\n\\t\\twriteDataTransformB(vec4u(packedQuat, 0u, 0u, 0u));\\n\\t#endif\\n}\\n`;\\n\\nvar containerPackedRead_default = `\\nvar<private> cachedTransformA: vec4u;\\nvar<private> cachedTransformB: vec2u;\\nvar<private> cachedColor: vec4f;\\nfn getCenter() -> vec3f {\\n\\tcachedTransformA = loadDataTransformA();\\n\\tcachedTransformB = loadDataTransformB().xy;\\n\\treturn vec3f(bitcast<f32>(cachedTransformA.r), bitcast<f32>(cachedTransformA.g), bitcast<f32>(cachedTransformA.b));\\n}\\nfn getOpacity() -> f32 {\\n\\t#ifdef GSPLAT_COLOR_FLOAT\\n\\t\\tcachedColor = loadDataColor();\\n\\t#else\\n\\t\\tlet packedColor = loadDataColor();\\n\\t\\tlet packed_rg = packedColor.r | (packedColor.g << 16u);\\n\\t\\tlet packed_ba = packedColor.b | (packedColor.a << 16u);\\n\\t\\tcachedColor = vec4f(unpack2x16float(packed_rg), unpack2x16float(packed_ba));\\n\\t#endif\\n\\treturn cachedColor.a;\\n}\\nfn getColor() -> vec3f {\\n\\treturn cachedColor.rgb;\\n}\\nfn getRotation() -> vec4f {\\n\\tlet rotXY = unpack2x16float(cachedTransformA.a);\\n\\tlet rotZscaleX = unpack2x16float(cachedTransformB.x);\\n\\tlet rotXYZ = vec3f(rotXY, rotZscaleX.x);\\n\\treturn vec4f(rotXYZ, sqrt(max(0.0, 1.0 - dot(rotXYZ, rotXYZ)))).wxyz;\\n}\\nfn getScale() -> vec3f {\\n\\tlet rotZscaleX = unpack2x16float(cachedTransformB.x);\\n\\tlet scaleYZ = unpack2x16float(cachedTransformB.y);\\n\\treturn vec3f(rotZscaleX.y, scaleYZ);\\n}\\n`;\\n\\nvar containerPackedWrite_default = `\\nfn writeSplat(center: vec3f, rotation: vec4f, scale: vec3f, color: vec4f) {\\n\\twriteDataColor(color);\\n\\t#ifndef GSPLAT_COLOR_ONLY\\n\\t\\twriteDataTransformA(vec4u(bitcast<u32>(center.x), bitcast<u32>(center.y), bitcast<u32>(center.z), pack2x16float(rotation.xy)));\\n\\t\\twriteDataTransformB(vec4u(pack2x16float(vec2f(rotation.z, scale.x)), pack2x16float(scale.yz), 0u, 0u));\\n\\t#endif\\n}\\n`;\\n\\nclass GSplatParams {\\n\\t_material = new ShaderMaterial();\\n\\t_format;\\n\\t_device;\\n\\t_dataFormat = GSPLATDATA_COMPACT;\\n\\tconstructor(device) {\\n\\t\\tthis._device = device;\\n\\t\\tthis._format = this._createFormat(GSPLATDATA_COMPACT);\\n\\t\\tthis._material.setParameter(\\\"alphaClip\\\", 0.3);\\n\\t\\tthis._material.setParameter(\\\"alphaClipForward\\\", 1 / 255);\\n\\t\\tthis._material.setParameter(\\\"minPixelSize\\\", 2);\\n\\t\\tthis._material.setParameter(\\\"minContribution\\\", 3);\\n\\t}\\n\\t_createFormat(dataFormat) {\\n\\t\\tlet format;\\n\\t\\tif (dataFormat === GSPLATDATA_COMPACT) {\\n\\t\\t\\tformat = new GSplatFormat(this._device, [\\n\\t\\t\\t\\t{ name: \\\"dataColor\\\", format: PIXELFORMAT_R32U },\\n\\t\\t\\t\\t{ name: \\\"dataTransformA\\\", format: PIXELFORMAT_RGBA32U },\\n\\t\\t\\t\\t{ name: \\\"dataTransformB\\\", format: PIXELFORMAT_R32U }\\n\\t\\t\\t], {\\n\\t\\t\\t\\treadGLSL: containerCompactRead_default$1,\\n\\t\\t\\t\\treadWGSL: containerCompactRead_default\\n\\t\\t\\t});\\n\\t\\t\\tformat.setWriteCode(containerCompactWrite_default$1, containerCompactWrite_default);\\n\\t\\t} else {\\n\\t\\t\\tconst colorFormat = this._device.getRenderableHdrFormat([PIXELFORMAT_RGBA16F]) || PIXELFORMAT_RGBA16U;\\n\\t\\t\\tformat = new GSplatFormat(this._device, [\\n\\t\\t\\t\\t{ name: \\\"dataColor\\\", format: colorFormat },\\n\\t\\t\\t\\t{ name: \\\"dataTransformA\\\", format: PIXELFORMAT_RGBA32U },\\n\\t\\t\\t\\t{ name: \\\"dataTransformB\\\", format: PIXELFORMAT_RG32U }\\n\\t\\t\\t], {\\n\\t\\t\\t\\treadGLSL: containerPackedRead_default$1,\\n\\t\\t\\t\\treadWGSL: containerPackedRead_default\\n\\t\\t\\t});\\n\\t\\t\\tformat.setWriteCode(containerPackedWrite_default$1, containerPackedWrite_default);\\n\\t\\t}\\n\\t\\tformat.allowStreamRemoval = true;\\n\\t\\treturn format;\\n\\t}\\n\\tradialSorting = false;\\n\\t_renderer = GSPLAT_RENDERER_AUTO;\\n\\t_currentRenderer = GSPLAT_RENDERER_RASTER_CPU_SORT;\\n\\tset renderer(value) {\\n\\t\\tif (this._renderer !== value) {\\n\\t\\t\\tthis._renderer = value;\\n\\t\\t\\tif (value === GSPLAT_RENDERER_AUTO) {\\n\\t\\t\\t\\tthis._currentRenderer = GSPLAT_RENDERER_RASTER_CPU_SORT;\\n\\t\\t\\t} else if ((value === GSPLAT_RENDERER_COMPUTE || value === GSPLAT_RENDERER_RASTER_GPU_SORT) && !this._device.isWebGPU) {\\n\\t\\t\\t\\tthis._currentRenderer = GSPLAT_RENDERER_RASTER_CPU_SORT;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._currentRenderer = value;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget renderer() {\\n\\t\\treturn this._renderer;\\n\\t}\\n\\tget currentRenderer() {\\n\\t\\treturn this._currentRenderer;\\n\\t}\\n\\tdirty = false;\\n\\t_debug = GSPLAT_DEBUG_NONE;\\n\\tset debug(value) {\\n\\t\\tif (this._debug !== value) {\\n\\t\\t\\tconst prev = this._debug;\\n\\t\\t\\tthis._debug = value;\\n\\t\\t\\tif (value === GSPLAT_DEBUG_LOD || prev === GSPLAT_DEBUG_LOD || value === GSPLAT_DEBUG_HEATMAP || prev === GSPLAT_DEBUG_HEATMAP) {\\n\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget debug() {\\n\\t\\treturn this._debug;\\n\\t}\\n\\tset colorizeLod(value) {\\n\\t\\tthis.debug = value ? GSPLAT_DEBUG_LOD : GSPLAT_DEBUG_NONE;\\n\\t}\\n\\tget colorizeLod() {\\n\\t\\treturn this._debug === GSPLAT_DEBUG_LOD;\\n\\t}\\n\\tset debugAabbs(value) {\\n\\t\\tthis.debug = value ? GSPLAT_DEBUG_AABBS : GSPLAT_DEBUG_NONE;\\n\\t}\\n\\tget debugAabbs() {\\n\\t\\treturn this._debug === GSPLAT_DEBUG_AABBS;\\n\\t}\\n\\tset debugNodeAabbs(value) {\\n\\t\\tthis.debug = value ? GSPLAT_DEBUG_NODE_AABBS : GSPLAT_DEBUG_NONE;\\n\\t}\\n\\tget debugNodeAabbs() {\\n\\t\\treturn this._debug === GSPLAT_DEBUG_NODE_AABBS;\\n\\t}\\n\\t_enableIds = false;\\n\\tset enableIds(value) {\\n\\t\\tif (value && !this._enableIds) {\\n\\t\\t\\tthis._enableIds = true;\\n\\t\\t\\tif (!this._format.getStream(\\\"pcId\\\")) {\\n\\t\\t\\t\\tthis._format.addExtraStreams([\\n\\t\\t\\t\\t\\t{ name: \\\"pcId\\\", format: PIXELFORMAT_R32U }\\n\\t\\t\\t\\t]);\\n\\t\\t\\t}\\n\\t\\t} else if (!value && this._enableIds) {\\n\\t\\t\\tthis._enableIds = false;\\n\\t\\t\\tthis._format.removeExtraStreams([\\\"pcId\\\"]);\\n\\t\\t}\\n\\t}\\n\\tget enableIds() {\\n\\t\\treturn this._enableIds;\\n\\t}\\n\\tlodUpdateDistance = 1;\\n\\tlodUpdateAngle = 0;\\n\\t_lodBehindPenalty = 1;\\n\\tset lodBehindPenalty(value) {\\n\\t\\tif (this._lodBehindPenalty !== value) {\\n\\t\\t\\tthis._lodBehindPenalty = value;\\n\\t\\t\\tthis.dirty = true;\\n\\t\\t}\\n\\t}\\n\\tget lodBehindPenalty() {\\n\\t\\treturn this._lodBehindPenalty;\\n\\t}\\n\\t_lodRangeMin = 0;\\n\\tset lodRangeMin(value) {\\n\\t\\tif (this._lodRangeMin !== value) {\\n\\t\\t\\tthis._lodRangeMin = value;\\n\\t\\t\\tthis.dirty = true;\\n\\t\\t}\\n\\t}\\n\\tget lodRangeMin() {\\n\\t\\treturn this._lodRangeMin;\\n\\t}\\n\\t_lodRangeMax = 10;\\n\\tset lodRangeMax(value) {\\n\\t\\tif (this._lodRangeMax !== value) {\\n\\t\\t\\tthis._lodRangeMax = value;\\n\\t\\t\\tthis.dirty = true;\\n\\t\\t}\\n\\t}\\n\\tget lodRangeMax() {\\n\\t\\treturn this._lodRangeMax;\\n\\t}\\n\\t_lodUnderfillLimit = 0;\\n\\tset lodUnderfillLimit(value) {\\n\\t\\tif (this._lodUnderfillLimit !== value) {\\n\\t\\t\\tthis._lodUnderfillLimit = value;\\n\\t\\t\\tthis.dirty = true;\\n\\t\\t}\\n\\t}\\n\\tget lodUnderfillLimit() {\\n\\t\\treturn this._lodUnderfillLimit;\\n\\t}\\n\\t_splatBudget = 0;\\n\\tset splatBudget(value) {\\n\\t\\tif (this._splatBudget !== value) {\\n\\t\\t\\tthis._splatBudget = value;\\n\\t\\t\\tthis.dirty = true;\\n\\t\\t}\\n\\t}\\n\\tget splatBudget() {\\n\\t\\treturn this._splatBudget;\\n\\t}\\n\\t_colorRamp = null;\\n\\tset colorRamp(value) {\\n\\t\\tif (this._colorRamp !== value) {\\n\\t\\t\\tthis._colorRamp = value;\\n\\t\\t\\tthis.dirty = true;\\n\\t\\t}\\n\\t}\\n\\tget colorRamp() {\\n\\t\\treturn this._colorRamp;\\n\\t}\\n\\tcolorRampIntensity = 1;\\n\\tuseFog = true;\\n\\tset colorizeColorUpdate(value) {\\n\\t\\tthis.debug = value ? GSPLAT_DEBUG_SH_UPDATE : GSPLAT_DEBUG_NONE;\\n\\t}\\n\\tget colorizeColorUpdate() {\\n\\t\\treturn this._debug === GSPLAT_DEBUG_SH_UPDATE;\\n\\t}\\n\\tcolorUpdateAngle = 10;\\n\\tset colorUpdateDistance(value) {\\n\\t}\\n\\tget colorUpdateDistance() {\\n\\t\\treturn 0;\\n\\t}\\n\\tset colorUpdateDistanceLodScale(value) {\\n\\t}\\n\\tget colorUpdateDistanceLodScale() {\\n\\t\\treturn 0;\\n\\t}\\n\\tset colorUpdateAngleLodScale(value) {\\n\\t}\\n\\tget colorUpdateAngleLodScale() {\\n\\t\\treturn 0;\\n\\t}\\n\\tset alphaClip(value) {\\n\\t\\tthis._material.setParameter(\\\"alphaClip\\\", value);\\n\\t\\tthis._material.update();\\n\\t}\\n\\tget alphaClip() {\\n\\t\\treturn this._material.getParameter(\\\"alphaClip\\\")?.data ?? 0.3;\\n\\t}\\n\\tset alphaClipForward(value) {\\n\\t\\tthis._material.setParameter(\\\"alphaClipForward\\\", value);\\n\\t\\tthis._material.update();\\n\\t}\\n\\tget alphaClipForward() {\\n\\t\\treturn this._material.getParameter(\\\"alphaClipForward\\\")?.data ?? 1 / 255;\\n\\t}\\n\\tset minPixelSize(value) {\\n\\t\\tthis._material.setParameter(\\\"minPixelSize\\\", value);\\n\\t\\tthis._material.update();\\n\\t}\\n\\tget minPixelSize() {\\n\\t\\treturn this._material.getParameter(\\\"minPixelSize\\\")?.data ?? 2;\\n\\t}\\n\\tset minContribution(value) {\\n\\t\\tthis._material.setParameter(\\\"minContribution\\\", value);\\n\\t\\tthis._material.update();\\n\\t}\\n\\tget minContribution() {\\n\\t\\treturn this._material.getParameter(\\\"minContribution\\\")?.data ?? 3;\\n\\t}\\n\\tset antiAlias(value) {\\n\\t\\tthis._material.setDefine(\\\"GSPLAT_AA\\\", value);\\n\\t\\tthis._material.update();\\n\\t}\\n\\tget antiAlias() {\\n\\t\\treturn !!this._material.getDefine(\\\"GSPLAT_AA\\\");\\n\\t}\\n\\tset twoDimensional(value) {\\n\\t\\tthis._material.setDefine(\\\"GSPLAT_2DGS\\\", value);\\n\\t\\tthis._material.update();\\n\\t}\\n\\tget twoDimensional() {\\n\\t\\treturn !!this._material.getDefine(\\\"GSPLAT_2DGS\\\");\\n\\t}\\n\\t_fisheye = 0;\\n\\tset fisheye(value) {\\n\\t\\tif (this._fisheye !== value) {\\n\\t\\t\\tconst wasEnabled = this._fisheye > 0;\\n\\t\\t\\tthis._fisheye = value;\\n\\t\\t\\tconst isEnabled = value > 0;\\n\\t\\t\\tif (wasEnabled !== isEnabled) {\\n\\t\\t\\t\\tthis._material.setDefine(\\\"GSPLAT_FISHEYE\\\", isEnabled);\\n\\t\\t\\t\\tthis._material.update();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget fisheye() {\\n\\t\\treturn this._fisheye;\\n\\t}\\n\\tcooldownTicks = 100;\\n\\tset dataFormat(value) {\\n\\t\\tif (this._dataFormat !== value) {\\n\\t\\t\\tthis._dataFormat = value;\\n\\t\\t\\tconst extraStreams = this._format.extraStreams.map((s) => ({\\n\\t\\t\\t\\tname: s.name,\\n\\t\\t\\t\\tformat: s.format,\\n\\t\\t\\t\\tstorage: s.storage\\n\\t\\t\\t}));\\n\\t\\t\\tthis._format = this._createFormat(value);\\n\\t\\t\\tif (extraStreams.length > 0) {\\n\\t\\t\\t\\tthis._format.addExtraStreams(extraStreams);\\n\\t\\t\\t}\\n\\t\\t\\tthis.dirty = true;\\n\\t\\t}\\n\\t}\\n\\tget dataFormat() {\\n\\t\\treturn this._dataFormat;\\n\\t}\\n\\tget material() {\\n\\t\\treturn this._material;\\n\\t}\\n\\tget format() {\\n\\t\\treturn this._format;\\n\\t}\\n\\tframeEnd() {\\n\\t\\tthis._material.dirty = false;\\n\\t\\tthis.dirty = false;\\n\\t}\\n}\\n\\nclass FisheyeProjection {\\n\\tenabled = false;\\n\\tk = 1;\\n\\tinvK = 1;\\n\\tcornerScale = 1;\\n\\tprojMat00 = 1;\\n\\tprojMat11 = 1;\\n\\tmaxTheta = Math.PI;\\n\\t// Cached inputs for short-circuit check\\n\\t_lastT = -1;\\n\\t_lastFov = -1;\\n\\t_lastP00 = 0;\\n\\t_lastP11 = 0;\\n\\tupdate(t, fov, projMatrix) {\\n\\t\\tif (projMatrix.data[15] === 1) {\\n\\t\\t\\tt = 0;\\n\\t\\t}\\n\\t\\tconst p00 = projMatrix.data[0];\\n\\t\\tconst p11 = projMatrix.data[5];\\n\\t\\tif (t === this._lastT && fov === this._lastFov && p00 === this._lastP00 && p11 === this._lastP11) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._lastT = t;\\n\\t\\tthis._lastFov = fov;\\n\\t\\tthis._lastP00 = p00;\\n\\t\\tthis._lastP11 = p11;\\n\\t\\tif (t <= 0) {\\n\\t\\t\\tthis.enabled = false;\\n\\t\\t\\tthis.k = 1;\\n\\t\\t\\tthis.invK = 1;\\n\\t\\t\\tthis.cornerScale = 1;\\n\\t\\t\\tthis.maxTheta = Math.PI;\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.enabled = true;\\n\\t\\tconst kMin = fov / 180 + 0.15;\\n\\t\\tconst kStart = Math.max(1, fov / 180 + 0.05);\\n\\t\\tconst k = kStart * Math.pow(kMin / kStart, t);\\n\\t\\tthis.k = k;\\n\\t\\tthis.invK = 1 / k;\\n\\t\\tthis.cornerScale = 1 + (Math.SQRT2 - 1) * t;\\n\\t\\tconst maxTheta = Math.min(k * Math.PI / 2, 3.13);\\n\\t\\tconst cs = this.cornerScale;\\n\\t\\tconst halfFovX = Math.atan2(1, p00);\\n\\t\\tconst effHalfFovX = Math.min(halfFovX, maxTheta - 0.01);\\n\\t\\tthis.projMat00 = cs / (k * Math.tan(effHalfFovX / k));\\n\\t\\tconst halfFovY = Math.atan2(1, p11);\\n\\t\\tconst effHalfFovY = Math.min(halfFovY, maxTheta - 0.01);\\n\\t\\tthis.projMat11 = cs / (k * Math.tan(effHalfFovY / k));\\n\\t\\tthis.maxTheta = maxTheta;\\n\\t}\\n}\\n\\nconst decodeTable = {\\n\\t\\\"linear\\\": \\\"decodeLinear\\\",\\n\\t\\\"srgb\\\": \\\"decodeGamma\\\",\\n\\t\\\"rgbm\\\": \\\"decodeRGBM\\\",\\n\\t\\\"rgbe\\\": \\\"decodeRGBE\\\",\\n\\t\\\"rgbp\\\": \\\"decodeRGBP\\\",\\n\\t\\\"xy\\\": \\\"unpackNormalXY\\\",\\n\\t\\\"xyz\\\": \\\"unpackNormalXYZ\\\"\\n};\\nconst encodeTable = {\\n\\t\\\"linear\\\": \\\"encodeLinear\\\",\\n\\t\\\"srgb\\\": \\\"encodeGamma\\\",\\n\\t\\\"rgbm\\\": \\\"encodeRGBM\\\",\\n\\t\\\"rgbe\\\": \\\"encodeRGBE\\\",\\n\\t\\\"rgbp\\\": \\\"encodeRGBP\\\"\\n};\\nclass ChunkUtils {\\n\\t// returns the name of the decode function for the texture encoding\\n\\tstatic decodeFunc(encoding) {\\n\\t\\treturn decodeTable[encoding] ?? \\\"decodeGamma\\\";\\n\\t}\\n\\tstatic encodeFunc(encoding) {\\n\\t\\treturn encodeTable[encoding] ?? \\\"encodeGamma\\\";\\n\\t}\\n}\\n\\nconst calculateNormals = (positions, indices) => {\\n\\tconst triangleCount = indices.length / 3;\\n\\tconst vertexCount = positions.length / 3;\\n\\tconst p1 = new Vec3();\\n\\tconst p2 = new Vec3();\\n\\tconst p3 = new Vec3();\\n\\tconst p1p2 = new Vec3();\\n\\tconst p1p3 = new Vec3();\\n\\tconst faceNormal = new Vec3();\\n\\tconst normals = [];\\n\\tfor (let i = 0; i < positions.length; i++) {\\n\\t\\tnormals[i] = 0;\\n\\t}\\n\\tfor (let i = 0; i < triangleCount; i++) {\\n\\t\\tconst i1 = indices[i * 3];\\n\\t\\tconst i2 = indices[i * 3 + 1];\\n\\t\\tconst i3 = indices[i * 3 + 2];\\n\\t\\tp1.set(positions[i1 * 3], positions[i1 * 3 + 1], positions[i1 * 3 + 2]);\\n\\t\\tp2.set(positions[i2 * 3], positions[i2 * 3 + 1], positions[i2 * 3 + 2]);\\n\\t\\tp3.set(positions[i3 * 3], positions[i3 * 3 + 1], positions[i3 * 3 + 2]);\\n\\t\\tp1p2.sub2(p2, p1);\\n\\t\\tp1p3.sub2(p3, p1);\\n\\t\\tfaceNormal.cross(p1p2, p1p3).normalize();\\n\\t\\tnormals[i1 * 3] += faceNormal.x;\\n\\t\\tnormals[i1 * 3 + 1] += faceNormal.y;\\n\\t\\tnormals[i1 * 3 + 2] += faceNormal.z;\\n\\t\\tnormals[i2 * 3] += faceNormal.x;\\n\\t\\tnormals[i2 * 3 + 1] += faceNormal.y;\\n\\t\\tnormals[i2 * 3 + 2] += faceNormal.z;\\n\\t\\tnormals[i3 * 3] += faceNormal.x;\\n\\t\\tnormals[i3 * 3 + 1] += faceNormal.y;\\n\\t\\tnormals[i3 * 3 + 2] += faceNormal.z;\\n\\t}\\n\\tfor (let i = 0; i < vertexCount; i++) {\\n\\t\\tconst nx = normals[i * 3];\\n\\t\\tconst ny = normals[i * 3 + 1];\\n\\t\\tconst nz = normals[i * 3 + 2];\\n\\t\\tconst invLen = 1 / Math.sqrt(nx * nx + ny * ny + nz * nz);\\n\\t\\tnormals[i * 3] *= invLen;\\n\\t\\tnormals[i * 3 + 1] *= invLen;\\n\\t\\tnormals[i * 3 + 2] *= invLen;\\n\\t}\\n\\treturn normals;\\n};\\nconst calculateTangents = (positions, normals, uvs, indices) => {\\n\\tconst triangleCount = indices.length / 3;\\n\\tconst vertexCount = positions.length / 3;\\n\\tconst v1 = new Vec3();\\n\\tconst v2 = new Vec3();\\n\\tconst v3 = new Vec3();\\n\\tconst w1 = new Vec2();\\n\\tconst w2 = new Vec2();\\n\\tconst w3 = new Vec2();\\n\\tconst sdir = new Vec3();\\n\\tconst tdir = new Vec3();\\n\\tconst tan1 = new Float32Array(vertexCount * 3);\\n\\tconst tan2 = new Float32Array(vertexCount * 3);\\n\\tconst tangents = [];\\n\\tfor (let i = 0; i < triangleCount; i++) {\\n\\t\\tconst i1 = indices[i * 3];\\n\\t\\tconst i2 = indices[i * 3 + 1];\\n\\t\\tconst i3 = indices[i * 3 + 2];\\n\\t\\tv1.set(positions[i1 * 3], positions[i1 * 3 + 1], positions[i1 * 3 + 2]);\\n\\t\\tv2.set(positions[i2 * 3], positions[i2 * 3 + 1], positions[i2 * 3 + 2]);\\n\\t\\tv3.set(positions[i3 * 3], positions[i3 * 3 + 1], positions[i3 * 3 + 2]);\\n\\t\\tw1.set(uvs[i1 * 2], uvs[i1 * 2 + 1]);\\n\\t\\tw2.set(uvs[i2 * 2], uvs[i2 * 2 + 1]);\\n\\t\\tw3.set(uvs[i3 * 2], uvs[i3 * 2 + 1]);\\n\\t\\tconst x1 = v2.x - v1.x;\\n\\t\\tconst x2 = v3.x - v1.x;\\n\\t\\tconst y1 = v2.y - v1.y;\\n\\t\\tconst y2 = v3.y - v1.y;\\n\\t\\tconst z1 = v2.z - v1.z;\\n\\t\\tconst z2 = v3.z - v1.z;\\n\\t\\tconst s1 = w2.x - w1.x;\\n\\t\\tconst s2 = w3.x - w1.x;\\n\\t\\tconst t12 = w2.y - w1.y;\\n\\t\\tconst t22 = w3.y - w1.y;\\n\\t\\tconst area = s1 * t22 - s2 * t12;\\n\\t\\tif (area === 0) {\\n\\t\\t\\tsdir.set(0, 1, 0);\\n\\t\\t\\ttdir.set(1, 0, 0);\\n\\t\\t} else {\\n\\t\\t\\tconst r = 1 / area;\\n\\t\\t\\tsdir.set(\\n\\t\\t\\t\\t(t22 * x1 - t12 * x2) * r,\\n\\t\\t\\t\\t(t22 * y1 - t12 * y2) * r,\\n\\t\\t\\t\\t(t22 * z1 - t12 * z2) * r\\n\\t\\t\\t);\\n\\t\\t\\ttdir.set(\\n\\t\\t\\t\\t(s1 * x2 - s2 * x1) * r,\\n\\t\\t\\t\\t(s1 * y2 - s2 * y1) * r,\\n\\t\\t\\t\\t(s1 * z2 - s2 * z1) * r\\n\\t\\t\\t);\\n\\t\\t}\\n\\t\\ttan1[i1 * 3 + 0] += sdir.x;\\n\\t\\ttan1[i1 * 3 + 1] += sdir.y;\\n\\t\\ttan1[i1 * 3 + 2] += sdir.z;\\n\\t\\ttan1[i2 * 3 + 0] += sdir.x;\\n\\t\\ttan1[i2 * 3 + 1] += sdir.y;\\n\\t\\ttan1[i2 * 3 + 2] += sdir.z;\\n\\t\\ttan1[i3 * 3 + 0] += sdir.x;\\n\\t\\ttan1[i3 * 3 + 1] += sdir.y;\\n\\t\\ttan1[i3 * 3 + 2] += sdir.z;\\n\\t\\ttan2[i1 * 3 + 0] += tdir.x;\\n\\t\\ttan2[i1 * 3 + 1] += tdir.y;\\n\\t\\ttan2[i1 * 3 + 2] += tdir.z;\\n\\t\\ttan2[i2 * 3 + 0] += tdir.x;\\n\\t\\ttan2[i2 * 3 + 1] += tdir.y;\\n\\t\\ttan2[i2 * 3 + 2] += tdir.z;\\n\\t\\ttan2[i3 * 3 + 0] += tdir.x;\\n\\t\\ttan2[i3 * 3 + 1] += tdir.y;\\n\\t\\ttan2[i3 * 3 + 2] += tdir.z;\\n\\t}\\n\\tconst t1 = new Vec3();\\n\\tconst t2 = new Vec3();\\n\\tconst n = new Vec3();\\n\\tconst temp = new Vec3();\\n\\tfor (let i = 0; i < vertexCount; i++) {\\n\\t\\tn.set(normals[i * 3], normals[i * 3 + 1], normals[i * 3 + 2]);\\n\\t\\tt1.set(tan1[i * 3], tan1[i * 3 + 1], tan1[i * 3 + 2]);\\n\\t\\tt2.set(tan2[i * 3], tan2[i * 3 + 1], tan2[i * 3 + 2]);\\n\\t\\tconst ndott = n.dot(t1);\\n\\t\\ttemp.copy(n).mulScalar(ndott);\\n\\t\\ttemp.sub2(t1, temp).normalize();\\n\\t\\ttangents[i * 4] = temp.x;\\n\\t\\ttangents[i * 4 + 1] = temp.y;\\n\\t\\ttangents[i * 4 + 2] = temp.z;\\n\\t\\ttemp.cross(n, t1);\\n\\t\\ttangents[i * 4 + 3] = temp.dot(t2) < 0 ? -1 : 1;\\n\\t}\\n\\treturn tangents;\\n};\\n\\nclass Geometry {\\n\\tpositions;\\n\\tnormals;\\n\\tcolors;\\n\\tuvs;\\n\\tuvs1;\\n\\tblendIndices;\\n\\tblendWeights;\\n\\ttangents;\\n\\tindices;\\n\\tcalculateNormals() {\\n\\t\\tthis.normals = calculateNormals(this.positions, this.indices);\\n\\t}\\n\\tcalculateTangents() {\\n\\t\\tthis.tangents = calculateTangents(this.positions, this.normals, this.uvs, this.indices);\\n\\t}\\n}\\n\\nconst primitiveUv1Padding$1 = 8 / 64;\\nconst primitiveUv1PaddingScale$1 = 1 - primitiveUv1Padding$1 * 2;\\nclass BoxGeometry extends Geometry {\\n\\tconstructor(opts = {}) {\\n\\t\\tsuper();\\n\\t\\tconst he = opts.halfExtents ?? new Vec3(0.5, 0.5, 0.5);\\n\\t\\tconst ws = opts.widthSegments ?? 1;\\n\\t\\tconst ls = opts.lengthSegments ?? 1;\\n\\t\\tconst hs = opts.heightSegments ?? 1;\\n\\t\\tconst yOffset = opts.yOffset ?? 0;\\n\\t\\tconst minY = -he.y + yOffset;\\n\\t\\tconst maxY = he.y + yOffset;\\n\\t\\tconst corners = [\\n\\t\\t\\tnew Vec3(-he.x, minY, he.z),\\n\\t\\t\\tnew Vec3(he.x, minY, he.z),\\n\\t\\t\\tnew Vec3(he.x, maxY, he.z),\\n\\t\\t\\tnew Vec3(-he.x, maxY, he.z),\\n\\t\\t\\tnew Vec3(he.x, minY, -he.z),\\n\\t\\t\\tnew Vec3(-he.x, minY, -he.z),\\n\\t\\t\\tnew Vec3(-he.x, maxY, -he.z),\\n\\t\\t\\tnew Vec3(he.x, maxY, -he.z)\\n\\t\\t];\\n\\t\\tconst faceAxes = [\\n\\t\\t\\t[0, 1, 3],\\n\\t\\t\\t// FRONT\\n\\t\\t\\t[4, 5, 7],\\n\\t\\t\\t// BACK\\n\\t\\t\\t[3, 2, 6],\\n\\t\\t\\t// TOP\\n\\t\\t\\t[1, 0, 4],\\n\\t\\t\\t// BOTTOM\\n\\t\\t\\t[1, 4, 2],\\n\\t\\t\\t// RIGHT\\n\\t\\t\\t[5, 0, 6]\\n\\t\\t\\t// LEFT\\n\\t\\t];\\n\\t\\tconst faceNormals = [\\n\\t\\t\\t[0, 0, 1],\\n\\t\\t\\t// FRONT\\n\\t\\t\\t[0, 0, -1],\\n\\t\\t\\t// BACK\\n\\t\\t\\t[0, 1, 0],\\n\\t\\t\\t// TOP\\n\\t\\t\\t[0, -1, 0],\\n\\t\\t\\t// BOTTOM\\n\\t\\t\\t[1, 0, 0],\\n\\t\\t\\t// RIGHT\\n\\t\\t\\t[-1, 0, 0]\\n\\t\\t\\t// LEFT\\n\\t\\t];\\n\\t\\tconst sides = {\\n\\t\\t\\tFRONT: 0,\\n\\t\\t\\tBACK: 1,\\n\\t\\t\\tTOP: 2,\\n\\t\\t\\tBOTTOM: 3,\\n\\t\\t\\tRIGHT: 4,\\n\\t\\t\\tLEFT: 5\\n\\t\\t};\\n\\t\\tconst positions = [];\\n\\t\\tconst normals = [];\\n\\t\\tconst uvs = [];\\n\\t\\tconst uvs1 = [];\\n\\t\\tconst indices = [];\\n\\t\\tlet vcounter = 0;\\n\\t\\tconst generateFace = (side, uSegments, vSegments) => {\\n\\t\\t\\tconst temp1 = new Vec3();\\n\\t\\t\\tconst temp2 = new Vec3();\\n\\t\\t\\tconst temp3 = new Vec3();\\n\\t\\t\\tconst r = new Vec3();\\n\\t\\t\\tfor (let i = 0; i <= uSegments; i++) {\\n\\t\\t\\t\\tfor (let j = 0; j <= vSegments; j++) {\\n\\t\\t\\t\\t\\ttemp1.lerp(corners[faceAxes[side][0]], corners[faceAxes[side][1]], i / uSegments);\\n\\t\\t\\t\\t\\ttemp2.lerp(corners[faceAxes[side][0]], corners[faceAxes[side][2]], j / vSegments);\\n\\t\\t\\t\\t\\ttemp3.sub2(temp2, corners[faceAxes[side][0]]);\\n\\t\\t\\t\\t\\tr.add2(temp1, temp3);\\n\\t\\t\\t\\t\\tlet u = i / uSegments;\\n\\t\\t\\t\\t\\tlet v = j / vSegments;\\n\\t\\t\\t\\t\\tpositions.push(r.x, r.y, r.z);\\n\\t\\t\\t\\t\\tnormals.push(faceNormals[side][0], faceNormals[side][1], faceNormals[side][2]);\\n\\t\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t\\t\\tu = u * primitiveUv1PaddingScale$1 + primitiveUv1Padding$1;\\n\\t\\t\\t\\t\\tv = v * primitiveUv1PaddingScale$1 + primitiveUv1Padding$1;\\n\\t\\t\\t\\t\\tu /= 3;\\n\\t\\t\\t\\t\\tv /= 3;\\n\\t\\t\\t\\t\\tu += side % 3 / 3;\\n\\t\\t\\t\\t\\tv += Math.floor(side / 3) / 3;\\n\\t\\t\\t\\t\\tuvs1.push(u, 1 - v);\\n\\t\\t\\t\\t\\tif (i < uSegments && j < vSegments) {\\n\\t\\t\\t\\t\\t\\tindices.push(vcounter + vSegments + 1, vcounter + 1, vcounter);\\n\\t\\t\\t\\t\\t\\tindices.push(vcounter + vSegments + 1, vcounter + vSegments + 2, vcounter + 1);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tvcounter++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tgenerateFace(sides.FRONT, ws, hs);\\n\\t\\tgenerateFace(sides.BACK, ws, hs);\\n\\t\\tgenerateFace(sides.TOP, ws, ls);\\n\\t\\tgenerateFace(sides.BOTTOM, ws, ls);\\n\\t\\tgenerateFace(sides.RIGHT, ls, hs);\\n\\t\\tgenerateFace(sides.LEFT, ls, hs);\\n\\t\\tthis.positions = positions;\\n\\t\\tthis.normals = normals;\\n\\t\\tthis.uvs = uvs;\\n\\t\\tthis.uvs1 = uvs1;\\n\\t\\tthis.indices = indices;\\n\\t\\tif (opts.calculateTangents) {\\n\\t\\t\\tthis.tangents = calculateTangents(positions, normals, uvs, indices);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass SphereGeometry extends Geometry {\\n\\tconstructor(opts = {}) {\\n\\t\\tsuper();\\n\\t\\tconst radius = opts.radius ?? 0.5;\\n\\t\\tconst latitudeBands = opts.latitudeBands ?? 16;\\n\\t\\tconst longitudeBands = opts.longitudeBands ?? 16;\\n\\t\\tconst positions = [];\\n\\t\\tconst normals = [];\\n\\t\\tconst uvs = [];\\n\\t\\tconst indices = [];\\n\\t\\tfor (let lat = 0; lat <= latitudeBands; lat++) {\\n\\t\\t\\tconst theta = lat * Math.PI / latitudeBands;\\n\\t\\t\\tconst sinTheta = Math.sin(theta);\\n\\t\\t\\tconst cosTheta = Math.cos(theta);\\n\\t\\t\\tfor (let lon = 0; lon <= longitudeBands; lon++) {\\n\\t\\t\\t\\tconst phi = lon * 2 * Math.PI / longitudeBands - Math.PI / 2;\\n\\t\\t\\t\\tconst sinPhi = Math.sin(phi);\\n\\t\\t\\t\\tconst cosPhi = Math.cos(phi);\\n\\t\\t\\t\\tconst x = cosPhi * sinTheta;\\n\\t\\t\\t\\tconst y = cosTheta;\\n\\t\\t\\t\\tconst z = sinPhi * sinTheta;\\n\\t\\t\\t\\tconst u = 1 - lon / longitudeBands;\\n\\t\\t\\t\\tconst v = 1 - lat / latitudeBands;\\n\\t\\t\\t\\tpositions.push(x * radius, y * radius, z * radius);\\n\\t\\t\\t\\tnormals.push(x, y, z);\\n\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (let lat = 0; lat < latitudeBands; ++lat) {\\n\\t\\t\\tfor (let lon = 0; lon < longitudeBands; ++lon) {\\n\\t\\t\\t\\tconst first = lat * (longitudeBands + 1) + lon;\\n\\t\\t\\t\\tconst second = first + longitudeBands + 1;\\n\\t\\t\\t\\tindices.push(first + 1, second, first);\\n\\t\\t\\t\\tindices.push(first + 1, second + 1, second);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.positions = positions;\\n\\t\\tthis.normals = normals;\\n\\t\\tthis.uvs = uvs;\\n\\t\\tthis.uvs1 = uvs;\\n\\t\\tthis.indices = indices;\\n\\t\\tif (opts.calculateTangents) {\\n\\t\\t\\tthis.tangents = calculateTangents(positions, normals, uvs, indices);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass DomeGeometry extends SphereGeometry {\\n\\tconstructor(opts = {}) {\\n\\t\\tconst radius = 0.5;\\n\\t\\tconst latitudeBands = opts.latitudeBands ?? 16;\\n\\t\\tconst longitudeBands = opts.longitudeBands ?? 16;\\n\\t\\tsuper({\\n\\t\\t\\tradius,\\n\\t\\t\\tlatitudeBands,\\n\\t\\t\\tlongitudeBands\\n\\t\\t});\\n\\t\\tconst bottomLimit = 0.1;\\n\\t\\tconst curvatureRadius = 0.95;\\n\\t\\tconst curvatureRadiusSq = curvatureRadius * curvatureRadius;\\n\\t\\tconst positions = this.positions;\\n\\t\\tfor (let i = 0; i < positions.length; i += 3) {\\n\\t\\t\\tconst x = positions[i] / radius;\\n\\t\\t\\tlet y = positions[i + 1] / radius;\\n\\t\\t\\tconst z = positions[i + 2] / radius;\\n\\t\\t\\tif (y < 0) {\\n\\t\\t\\t\\ty *= 0.3;\\n\\t\\t\\t\\tif (x * x + z * z < curvatureRadiusSq) {\\n\\t\\t\\t\\t\\ty = -bottomLimit;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\ty += bottomLimit;\\n\\t\\t\\ty *= radius;\\n\\t\\t\\tpositions[i + 1] = y;\\n\\t\\t}\\n\\t}\\n}\\n\\nclass SkyGeometry {\\n\\tstatic create(device, type) {\\n\\t\\tswitch (type) {\\n\\t\\t\\tcase SKYTYPE_BOX:\\n\\t\\t\\t\\treturn SkyGeometry.box(device);\\n\\t\\t\\tcase SKYTYPE_DOME:\\n\\t\\t\\t\\treturn SkyGeometry.dome(device);\\n\\t\\t}\\n\\t\\treturn SkyGeometry.infinite(device);\\n\\t}\\n\\tstatic infinite(device) {\\n\\t\\treturn Mesh.fromGeometry(device, new BoxGeometry(device));\\n\\t}\\n\\tstatic box(device) {\\n\\t\\treturn Mesh.fromGeometry(device, new BoxGeometry({ yOffset: 0.5 }));\\n\\t}\\n\\tstatic dome(device) {\\n\\t\\tconst geom = new DomeGeometry({\\n\\t\\t\\tlatitudeBands: 50,\\n\\t\\t\\tlongitudeBands: 50\\n\\t\\t});\\n\\t\\tgeom.normals = void 0;\\n\\t\\tgeom.uvs = void 0;\\n\\t\\treturn Mesh.fromGeometry(device, geom);\\n\\t}\\n}\\n\\nclass SkyMesh {\\n\\tmeshInstance = null;\\n\\t_depthWrite = false;\\n\\tconstructor(device, scene, node, texture, type) {\\n\\t\\tconst material = new ShaderMaterial({\\n\\t\\t\\tuniqueName: \\\"SkyMaterial\\\",\\n\\t\\t\\tvertexGLSL: ShaderChunks.get(device, SHADERLANGUAGE_GLSL).get(\\\"skyboxVS\\\"),\\n\\t\\t\\tfragmentGLSL: ShaderChunks.get(device, SHADERLANGUAGE_GLSL).get(\\\"skyboxPS\\\"),\\n\\t\\t\\tvertexWGSL: ShaderChunks.get(device, SHADERLANGUAGE_WGSL).get(\\\"skyboxVS\\\"),\\n\\t\\t\\tfragmentWGSL: ShaderChunks.get(device, SHADERLANGUAGE_WGSL).get(\\\"skyboxPS\\\"),\\n\\t\\t\\tattributes: {\\n\\t\\t\\t\\taPosition: SEMANTIC_POSITION\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tmaterial.setDefine(\\\"{SKYBOX_DECODE_FNC}\\\", ChunkUtils.decodeFunc(texture.encoding));\\n\\t\\tif (type !== SKYTYPE_INFINITE) material.setDefine(\\\"SKYMESH\\\", \\\"\\\");\\n\\t\\tif (texture.cubemap) material.setDefine(\\\"SKY_CUBEMAP\\\", \\\"\\\");\\n\\t\\tmaterial.setParameter(\\\"skyboxHighlightMultiplier\\\", scene.skyboxHighlightMultiplier);\\n\\t\\tif (texture.cubemap) {\\n\\t\\t\\tmaterial.setParameter(\\\"texture_cubeMap\\\", texture);\\n\\t\\t} else {\\n\\t\\t\\tmaterial.setParameter(\\\"texture_envAtlas\\\", texture);\\n\\t\\t\\tmaterial.setParameter(\\\"mipLevel\\\", scene.skyboxMip);\\n\\t\\t}\\n\\t\\tmaterial.cull = CULLFACE_FRONT;\\n\\t\\tmaterial.depthWrite = this._depthWrite;\\n\\t\\tconst skyLayer = scene.layers.getLayerById(LAYERID_SKYBOX);\\n\\t\\tif (skyLayer) {\\n\\t\\t\\tconst mesh = SkyGeometry.create(device, type);\\n\\t\\t\\tconst meshInstance = new MeshInstance(mesh, material, node);\\n\\t\\t\\tthis.meshInstance = meshInstance;\\n\\t\\t\\tmeshInstance.cull = false;\\n\\t\\t\\tmeshInstance.pick = false;\\n\\t\\t\\tskyLayer.addMeshInstances([meshInstance]);\\n\\t\\t\\tthis.skyLayer = skyLayer;\\n\\t\\t}\\n\\t}\\n\\tdestroy() {\\n\\t\\tif (this.meshInstance) {\\n\\t\\t\\tif (this.skyLayer) {\\n\\t\\t\\t\\tthis.skyLayer.removeMeshInstances([this.meshInstance]);\\n\\t\\t\\t}\\n\\t\\t\\tthis.meshInstance.destroy();\\n\\t\\t\\tthis.meshInstance = null;\\n\\t\\t}\\n\\t}\\n\\tset depthWrite(value) {\\n\\t\\tthis._depthWrite = value;\\n\\t\\tif (this.meshInstance) {\\n\\t\\t\\tthis.meshInstance.material.depthWrite = value;\\n\\t\\t}\\n\\t}\\n\\tget depthWrite() {\\n\\t\\treturn this._depthWrite;\\n\\t}\\n}\\n\\nclass Sky {\\n\\t_type = SKYTYPE_INFINITE;\\n\\t_center = new Vec3(0, 1, 0);\\n\\tskyMesh = null;\\n\\t_depthWrite = false;\\n\\t_fisheye = 0;\\n\\t_fisheyeProj = null;\\n\\tnode = new GraphNode(\\\"SkyMeshNode\\\");\\n\\tconstructor(scene) {\\n\\t\\tthis.device = scene.device;\\n\\t\\tthis.scene = scene;\\n\\t\\tthis.center = new Vec3(0, 1, 0);\\n\\t\\tthis.centerArray = new Float32Array(3);\\n\\t\\tthis.projectedSkydomeCenterId = this.device.scope.resolve(\\\"projectedSkydomeCenter\\\");\\n\\t\\tthis._preRenderEvt = scene.on(\\\"prerender\\\", this._onPreRender, this);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._preRenderEvt.off();\\n\\t\\tthis.resetSkyMesh();\\n\\t}\\n\\tapplySettings(render) {\\n\\t\\tthis.type = render.skyType ?? SKYTYPE_INFINITE;\\n\\t\\tthis.node.setLocalPosition(new Vec3(render.skyMeshPosition ?? [0, 0, 0]));\\n\\t\\tthis.node.setLocalEulerAngles(new Vec3(render.skyMeshRotation ?? [0, 0, 0]));\\n\\t\\tthis.node.setLocalScale(new Vec3(render.skyMeshScale ?? [1, 1, 1]));\\n\\t\\tif (render.skyCenter) {\\n\\t\\t\\tthis._center = new Vec3(render.skyCenter);\\n\\t\\t}\\n\\t}\\n\\tset type(value) {\\n\\t\\tif (this._type !== value) {\\n\\t\\t\\tthis._type = value;\\n\\t\\t\\tthis.scene.updateShaders = true;\\n\\t\\t\\tthis.updateSkyMesh();\\n\\t\\t}\\n\\t}\\n\\tget type() {\\n\\t\\treturn this._type;\\n\\t}\\n\\tset center(value) {\\n\\t\\tthis._center.copy(value);\\n\\t}\\n\\tget center() {\\n\\t\\treturn this._center;\\n\\t}\\n\\tset depthWrite(value) {\\n\\t\\tif (this._depthWrite !== value) {\\n\\t\\t\\tthis._depthWrite = value;\\n\\t\\t\\tif (this.skyMesh) {\\n\\t\\t\\t\\tthis.skyMesh.depthWrite = value;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget depthWrite() {\\n\\t\\treturn this._depthWrite;\\n\\t}\\n\\tset fisheye(value) {\\n\\t\\tif (this._fisheye !== value) {\\n\\t\\t\\tconst wasEnabled = this._fisheye > 0;\\n\\t\\t\\tthis._fisheye = value;\\n\\t\\t\\tconst isEnabled = value > 0;\\n\\t\\t\\tif (wasEnabled !== isEnabled) {\\n\\t\\t\\t\\tthis._fisheyeProj ?? (this._fisheyeProj = new FisheyeProjection());\\n\\t\\t\\t\\tif (this._type === SKYTYPE_INFINITE) {\\n\\t\\t\\t\\t\\tthis._setFisheyeDefine(isEnabled);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget fisheye() {\\n\\t\\treturn this._fisheye;\\n\\t}\\n\\tupdateSkyMesh() {\\n\\t\\tconst texture = this.scene._getSkyboxTex();\\n\\t\\tif (texture) {\\n\\t\\t\\tthis.resetSkyMesh();\\n\\t\\t\\tthis.skyMesh = new SkyMesh(this.device, this.scene, this.node, texture, this.type);\\n\\t\\t\\tthis.skyMesh.depthWrite = this._depthWrite;\\n\\t\\t\\tif (this._fisheye > 0 && this.type === SKYTYPE_INFINITE) {\\n\\t\\t\\t\\tthis._setFisheyeDefine(true);\\n\\t\\t\\t}\\n\\t\\t\\tthis.scene.fire(\\\"set:skybox\\\", texture);\\n\\t\\t}\\n\\t}\\n\\tresetSkyMesh() {\\n\\t\\tthis.skyMesh?.destroy();\\n\\t\\tthis.skyMesh = null;\\n\\t}\\n\\tupdate() {\\n\\t\\tif (this.type !== SKYTYPE_INFINITE) {\\n\\t\\t\\tconst { center, centerArray } = this;\\n\\t\\t\\tconst temp = new Vec3();\\n\\t\\t\\tthis.node.getWorldTransform().transformPoint(center, temp);\\n\\t\\t\\tcenterArray[0] = temp.x;\\n\\t\\t\\tcenterArray[1] = temp.y;\\n\\t\\t\\tcenterArray[2] = temp.z;\\n\\t\\t\\tthis.projectedSkydomeCenterId.setValue(centerArray);\\n\\t\\t}\\n\\t}\\n\\t_setFisheyeDefine(enabled) {\\n\\t\\tif (this.skyMesh?.meshInstance) {\\n\\t\\t\\tconst material = this.skyMesh.meshInstance.material;\\n\\t\\t\\tmaterial.setDefine(\\\"SKY_FISHEYE\\\", enabled);\\n\\t\\t\\tmaterial.update();\\n\\t\\t}\\n\\t}\\n\\t_onPreRender(cameraComponent) {\\n\\t\\tif (this._fisheye > 0 && this._fisheyeProj && this.skyMesh?.meshInstance) {\\n\\t\\t\\tconst camera = cameraComponent.camera;\\n\\t\\t\\tconst proj = this._fisheyeProj;\\n\\t\\t\\tproj.update(this._fisheye, camera.fov, camera.projectionMatrix);\\n\\t\\t\\tconst material = this.skyMesh.meshInstance.material;\\n\\t\\t\\tmaterial.setParameter(\\\"fisheye_k\\\", proj.k);\\n\\t\\t\\tmaterial.setParameter(\\\"fisheye_invK\\\", proj.invK);\\n\\t\\t\\tmaterial.setParameter(\\\"fisheye_projMat00\\\", proj.projMat00);\\n\\t\\t\\tmaterial.setParameter(\\\"fisheye_projMat11\\\", proj.projMat11);\\n\\t\\t}\\n\\t}\\n}\\n\\nconst identityGraphNode = new GraphNode();\\nidentityGraphNode.worldTransform = Mat4.IDENTITY;\\nidentityGraphNode._dirtyWorld = identityGraphNode._dirtyNormal = false;\\nclass ImmediateBatch {\\n\\tconstructor(device, material, layer) {\\n\\t\\tthis.material = material;\\n\\t\\tthis.layer = layer;\\n\\t\\tthis.positions = [];\\n\\t\\tthis.colors = [];\\n\\t\\tthis.mesh = new Mesh(device);\\n\\t\\tthis.meshInstance = null;\\n\\t}\\n\\t// add line positions and colors to the batch\\n\\t// this function expects position in Vec3 and colors in Color format\\n\\taddLines(positions, color) {\\n\\t\\tconst destPos = this.positions;\\n\\t\\tconst count = positions.length;\\n\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\tconst pos = positions[i];\\n\\t\\t\\tdestPos.push(pos.x, pos.y, pos.z);\\n\\t\\t}\\n\\t\\tconst destCol = this.colors;\\n\\t\\tif (color.length) {\\n\\t\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\t\\tconst col = color[i];\\n\\t\\t\\t\\tdestCol.push(col.r, col.g, col.b, col.a);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\t\\tdestCol.push(color.r, color.g, color.b, color.a);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t// add line positions and colors to the batch\\n\\t// this function expects positions as arrays of numbers\\n\\t// and color as instance of Color or array of number specifying the same number of vertices as positions\\n\\taddLinesArrays(positions, color) {\\n\\t\\tconst destPos = this.positions;\\n\\t\\tfor (let i = 0; i < positions.length; i += 3) {\\n\\t\\t\\tdestPos.push(positions[i], positions[i + 1], positions[i + 2]);\\n\\t\\t}\\n\\t\\tconst destCol = this.colors;\\n\\t\\tif (color.length) {\\n\\t\\t\\tfor (let i = 0; i < color.length; i += 4) {\\n\\t\\t\\t\\tdestCol.push(color[i], color[i + 1], color[i + 2], color[i + 3]);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tconst count = positions.length / 3;\\n\\t\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\t\\tdestCol.push(color.r, color.g, color.b, color.a);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tonPreRender(visibleList, transparent) {\\n\\t\\tif (this.positions.length > 0 && this.material.transparent === transparent) {\\n\\t\\t\\tthis.mesh.setPositions(this.positions);\\n\\t\\t\\tthis.mesh.setColors(this.colors);\\n\\t\\t\\tthis.mesh.update(PRIMITIVE_LINES, false);\\n\\t\\t\\tif (!this.meshInstance) {\\n\\t\\t\\t\\tthis.meshInstance = new MeshInstance(this.mesh, this.material, identityGraphNode);\\n\\t\\t\\t}\\n\\t\\t\\tvisibleList.push(this.meshInstance);\\n\\t\\t}\\n\\t}\\n\\tclear() {\\n\\t\\tthis.positions.length = 0;\\n\\t\\tthis.colors.length = 0;\\n\\t}\\n}\\n\\nclass ImmediateBatches {\\n\\tconstructor(device) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.map = /* @__PURE__ */ new Map();\\n\\t}\\n\\tgetBatch(material, layer) {\\n\\t\\tlet batch = this.map.get(material);\\n\\t\\tif (!batch) {\\n\\t\\t\\tbatch = new ImmediateBatch(this.device, material, layer);\\n\\t\\t\\tthis.map.set(material, batch);\\n\\t\\t}\\n\\t\\treturn batch;\\n\\t}\\n\\tonPreRender(visibleList, transparent) {\\n\\t\\tthis.map.forEach((batch) => {\\n\\t\\t\\tbatch.onPreRender(visibleList, transparent);\\n\\t\\t});\\n\\t}\\n\\tclear() {\\n\\t\\tthis.map.forEach((batch) => batch.clear());\\n\\t}\\n}\\n\\nconst tempPoints = [];\\nconst vec$2 = new Vec3();\\nclass Immediate {\\n\\tshaderDescs = /* @__PURE__ */ new Map();\\n\\tconstructor(device) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.quadMesh = null;\\n\\t\\tthis.textureShader = null;\\n\\t\\tthis.depthTextureShader = null;\\n\\t\\tthis.cubeLocalPos = null;\\n\\t\\tthis.cubeWorldPos = null;\\n\\t\\tthis.batchesMap = /* @__PURE__ */ new Map();\\n\\t\\tthis.allBatches = /* @__PURE__ */ new Set();\\n\\t\\tthis.updatedLayers = /* @__PURE__ */ new Set();\\n\\t\\tthis._materialDepth = null;\\n\\t\\tthis._materialNoDepth = null;\\n\\t\\tthis.layerMeshInstances = /* @__PURE__ */ new Map();\\n\\t}\\n\\t// creates material for line rendering\\n\\tcreateMaterial(depthTest) {\\n\\t\\tconst material = new ShaderMaterial({\\n\\t\\t\\tuniqueName: \\\"ImmediateLine\\\",\\n\\t\\t\\tvertexGLSL: ShaderChunks.get(this.device, SHADERLANGUAGE_GLSL).get(\\\"immediateLineVS\\\"),\\n\\t\\t\\tfragmentGLSL: ShaderChunks.get(this.device, SHADERLANGUAGE_GLSL).get(\\\"immediateLinePS\\\"),\\n\\t\\t\\tvertexWGSL: ShaderChunks.get(this.device, SHADERLANGUAGE_WGSL).get(\\\"immediateLineVS\\\"),\\n\\t\\t\\tfragmentWGSL: ShaderChunks.get(this.device, SHADERLANGUAGE_WGSL).get(\\\"immediateLinePS\\\"),\\n\\t\\t\\tattributes: {\\n\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION,\\n\\t\\t\\t\\tvertex_color: SEMANTIC_COLOR\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tmaterial.blendType = BLEND_NORMAL;\\n\\t\\tmaterial.depthTest = depthTest;\\n\\t\\tmaterial.update();\\n\\t\\treturn material;\\n\\t}\\n\\t// material for line rendering with depth testing on\\n\\tget materialDepth() {\\n\\t\\tif (!this._materialDepth) {\\n\\t\\t\\tthis._materialDepth = this.createMaterial(true);\\n\\t\\t}\\n\\t\\treturn this._materialDepth;\\n\\t}\\n\\t// material for line rendering with depth testing off\\n\\tget materialNoDepth() {\\n\\t\\tif (!this._materialNoDepth) {\\n\\t\\t\\tthis._materialNoDepth = this.createMaterial(false);\\n\\t\\t}\\n\\t\\treturn this._materialNoDepth;\\n\\t}\\n\\t// returns a batch for rendering lines to a layer with required depth testing state\\n\\tgetBatch(layer, depthTest) {\\n\\t\\tlet batches = this.batchesMap.get(layer);\\n\\t\\tif (!batches) {\\n\\t\\t\\tbatches = new ImmediateBatches(this.device);\\n\\t\\t\\tthis.batchesMap.set(layer, batches);\\n\\t\\t}\\n\\t\\tthis.allBatches.add(batches);\\n\\t\\tconst material = depthTest ? this.materialDepth : this.materialNoDepth;\\n\\t\\treturn batches.getBatch(material, layer);\\n\\t}\\n\\tgetShaderDesc(id, fragmentGLSL, fragmentWGSL) {\\n\\t\\tif (!this.shaderDescs.has(id)) {\\n\\t\\t\\tthis.shaderDescs.set(id, {\\n\\t\\t\\t\\tuniqueName: `DebugShader:${id}`,\\n\\t\\t\\t\\t// shared vertex shader for textured quad rendering\\n\\t\\t\\t\\tvertexGLSL: `\\n\\t\\t\\t\\t\\tattribute vec2 vertex_position;\\n\\t\\t\\t\\t\\tuniform mat4 matrix_model;\\n\\t\\t\\t\\t\\tvarying vec2 uv0;\\n\\t\\t\\t\\t\\tvoid main(void) {\\n\\t\\t\\t\\t\\t\\tgl_Position = matrix_model * vec4(vertex_position, 0, 1);\\n\\t\\t\\t\\t\\t\\tuv0 = vertex_position.xy + 0.5;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t`,\\n\\t\\t\\t\\tvertexWGSL: `\\n\\t\\t\\t\\t\\tattribute vertex_position: vec2f;\\n\\t\\t\\t\\t\\tuniform matrix_model: mat4x4f;\\n\\t\\t\\t\\t\\tvarying uv0: vec2f;\\n\\t\\t\\t\\t\\t@vertex fn vertexMain(input: VertexInput) -> VertexOutput {\\n\\t\\t\\t\\t\\t\\tvar output: VertexOutput;\\n\\t\\t\\t\\t\\t\\toutput.position = uniform.matrix_model * vec4f(input.vertex_position, 0.0, 1.0);\\n\\t\\t\\t\\t\\t\\toutput.uv0 = input.vertex_position.xy + vec2f(0.5);\\n\\t\\t\\t\\t\\t\\treturn output;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t`,\\n\\t\\t\\t\\tfragmentGLSL,\\n\\t\\t\\t\\tfragmentWGSL,\\n\\t\\t\\t\\tattributes: { vertex_position: SEMANTIC_POSITION }\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\treturn this.shaderDescs.get(id);\\n\\t}\\n\\t// shader used to display texture\\n\\tgetTextureShaderDesc(encoding) {\\n\\t\\tconst decodeFunc = ChunkUtils.decodeFunc(encoding);\\n\\t\\treturn this.getShaderDesc(\\n\\t\\t\\t`textureShader-${encoding}`,\\n\\t\\t\\t`\\n\\t\\t\\t#include \\\"gammaPS\\\"\\n\\t\\t\\tvarying vec2 uv0;\\n\\t\\t\\tuniform sampler2D colorMap;\\n\\t\\t\\tvoid main (void) {\\n\\t\\t\\t\\tvec3 linearColor = ${decodeFunc}(texture2D(colorMap, uv0));\\n\\t\\t\\t\\tgl_FragColor = vec4(gammaCorrectOutput(linearColor), 1);\\n\\t\\t\\t}\\n\\t\\t`,\\n\\t\\t\\t`\\n\\t\\t\\t#include \\\"gammaPS\\\"\\n\\t\\t\\tvarying uv0: vec2f;\\n\\t\\t\\tvar colorMap: texture_2d<f32>;\\n\\t\\t\\tvar colorMapSampler: sampler;\\n\\t\\t\\t@fragment fn fragmentMain(input : FragmentInput) -> FragmentOutput {\\n\\t\\t\\t\\tvar output: FragmentOutput;\\n\\t\\t\\t\\tlet sampledTex = textureSample(colorMap, colorMapSampler, input.uv0);\\n\\t\\t\\t\\tlet linearColor: vec3f = ${decodeFunc}(sampledTex);\\n\\t\\t\\t\\toutput.color = vec4f(gammaCorrectOutput(linearColor), 1.0);\\n\\t\\t\\t\\treturn output;\\n\\t\\t\\t}\\n\\t\\t`\\n\\t\\t);\\n\\t}\\n\\t// shader used to display infilterable texture sampled using texelFetch\\n\\tgetUnfilterableTextureShaderDesc() {\\n\\t\\treturn this.getShaderDesc(\\n\\t\\t\\t\\\"textureShaderUnfilterable\\\",\\n\\t\\t\\t`\\n\\t\\t\\tvarying vec2 uv0;\\n\\t\\t\\tuniform highp sampler2D colorMap;\\n\\t\\t\\tvoid main (void) {\\n\\t\\t\\t\\tivec2 uv = ivec2(uv0 * textureSize(colorMap, 0));\\n\\t\\t\\t\\tgl_FragColor = vec4(texelFetch(colorMap, uv, 0).xyz, 1);\\n\\t\\t\\t}\\n\\t\\t`,\\n\\t\\t\\t`\\n\\t\\t\\tvarying uv0: vec2f;\\n\\t\\t\\tvar colorMap: texture_2d<uff>;\\n\\t\\t\\t@fragment fn fragmentMain(input : FragmentInput) -> FragmentOutput {\\n\\t\\t\\t\\tvar output: FragmentOutput;\\n\\t\\t\\t\\tlet uv : vec2<i32> = vec2<i32>(input.uv0 * vec2f(textureDimensions(colorMap, 0)));\\n\\t\\t\\t\\tlet fetchedColor : vec4f = textureLoad(colorMap, uv, 0);\\n\\t\\t\\t\\toutput.color = vec4f(fetchedColor.xyz, 1.0);\\n\\t\\t\\t\\treturn output;\\n\\t\\t\\t}\\n\\t\\t`\\n\\t\\t);\\n\\t}\\n\\t// shader used to display depth texture\\n\\tgetDepthTextureShaderDesc() {\\n\\t\\treturn this.getShaderDesc(\\n\\t\\t\\t\\\"depthTextureShader\\\",\\n\\t\\t\\t`\\n\\t\\t\\t#include \\\"screenDepthPS\\\"\\n\\t\\t\\t#include \\\"gammaPS\\\"\\n\\t\\t\\tvarying vec2 uv0;\\n\\t\\t\\tvoid main() {\\n\\t\\t\\t\\tfloat depth = getLinearScreenDepth(getImageEffectUV(uv0)) * camera_params.x;\\n\\t\\t\\t\\tgl_FragColor = vec4(gammaCorrectOutput(vec3(depth)), 1.0);\\n\\t\\t\\t}\\n\\t\\t`,\\n\\t\\t\\t`\\n\\t\\t\\t#include \\\"screenDepthPS\\\"\\n\\t\\t\\t#include \\\"gammaPS\\\"\\n\\t\\t\\tvarying uv0: vec2f;\\n\\t\\t\\t@fragment fn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\t\\t\\t\\tvar output: FragmentOutput;\\n\\t\\t\\t\\tlet depth: f32 = getLinearScreenDepth(getImageEffectUV(input.uv0)) * uniform.camera_params.x;\\n\\t\\t\\t\\toutput.color = vec4f(gammaCorrectOutput(vec3f(depth)), 1.0);\\n\\t\\t\\t\\treturn output;\\n\\t\\t\\t}\\n\\t\\t`\\n\\t\\t);\\n\\t}\\n\\t// creates mesh used to render a quad\\n\\tgetQuadMesh() {\\n\\t\\tif (!this.quadMesh) {\\n\\t\\t\\tthis.quadMesh = new Mesh(this.device);\\n\\t\\t\\tthis.quadMesh.setPositions([\\n\\t\\t\\t\\t-0.5,\\n\\t\\t\\t\\t-0.5,\\n\\t\\t\\t\\t0,\\n\\t\\t\\t\\t0.5,\\n\\t\\t\\t\\t-0.5,\\n\\t\\t\\t\\t0,\\n\\t\\t\\t\\t-0.5,\\n\\t\\t\\t\\t0.5,\\n\\t\\t\\t\\t0,\\n\\t\\t\\t\\t0.5,\\n\\t\\t\\t\\t0.5,\\n\\t\\t\\t\\t0\\n\\t\\t\\t]);\\n\\t\\t\\tthis.quadMesh.update(PRIMITIVE_TRISTRIP);\\n\\t\\t}\\n\\t\\treturn this.quadMesh;\\n\\t}\\n\\t// Draw mesh at this frame\\n\\tdrawMesh(material, matrix, mesh, meshInstance, layer) {\\n\\t\\tif (!meshInstance) {\\n\\t\\t\\tconst graphNode = this.getGraphNode(matrix);\\n\\t\\t\\tmeshInstance = new MeshInstance(mesh, material, graphNode);\\n\\t\\t}\\n\\t\\tlet layerMeshInstances = this.layerMeshInstances.get(layer);\\n\\t\\tif (!layerMeshInstances) {\\n\\t\\t\\tlayerMeshInstances = [];\\n\\t\\t\\tthis.layerMeshInstances.set(layer, layerMeshInstances);\\n\\t\\t}\\n\\t\\tlayerMeshInstances.push(meshInstance);\\n\\t}\\n\\tdrawWireAlignedBox(min, max, color, depthTest, layer, mat) {\\n\\t\\tif (mat) {\\n\\t\\t\\tconst mulPoint = (x, y, z) => {\\n\\t\\t\\t\\tvec$2.set(x, y, z);\\n\\t\\t\\t\\tmat.transformPoint(vec$2, vec$2);\\n\\t\\t\\t\\ttempPoints.push(vec$2.x, vec$2.y, vec$2.z);\\n\\t\\t\\t};\\n\\t\\t\\tmulPoint(min.x, min.y, min.z);\\n\\t\\t\\tmulPoint(min.x, max.y, min.z);\\n\\t\\t\\tmulPoint(min.x, max.y, min.z);\\n\\t\\t\\tmulPoint(max.x, max.y, min.z);\\n\\t\\t\\tmulPoint(max.x, max.y, min.z);\\n\\t\\t\\tmulPoint(max.x, min.y, min.z);\\n\\t\\t\\tmulPoint(max.x, min.y, min.z);\\n\\t\\t\\tmulPoint(min.x, min.y, min.z);\\n\\t\\t\\tmulPoint(min.x, min.y, max.z);\\n\\t\\t\\tmulPoint(min.x, max.y, max.z);\\n\\t\\t\\tmulPoint(min.x, max.y, max.z);\\n\\t\\t\\tmulPoint(max.x, max.y, max.z);\\n\\t\\t\\tmulPoint(max.x, max.y, max.z);\\n\\t\\t\\tmulPoint(max.x, min.y, max.z);\\n\\t\\t\\tmulPoint(max.x, min.y, max.z);\\n\\t\\t\\tmulPoint(min.x, min.y, max.z);\\n\\t\\t\\tmulPoint(min.x, min.y, min.z);\\n\\t\\t\\tmulPoint(min.x, min.y, max.z);\\n\\t\\t\\tmulPoint(min.x, max.y, min.z);\\n\\t\\t\\tmulPoint(min.x, max.y, max.z);\\n\\t\\t\\tmulPoint(max.x, max.y, min.z);\\n\\t\\t\\tmulPoint(max.x, max.y, max.z);\\n\\t\\t\\tmulPoint(max.x, min.y, min.z);\\n\\t\\t\\tmulPoint(max.x, min.y, max.z);\\n\\t\\t} else {\\n\\t\\t\\ttempPoints.push(\\n\\t\\t\\t\\tmin.x,\\n\\t\\t\\t\\tmin.y,\\n\\t\\t\\t\\tmin.z,\\n\\t\\t\\t\\tmin.x,\\n\\t\\t\\t\\tmax.y,\\n\\t\\t\\t\\tmin.z,\\n\\t\\t\\t\\tmin.x,\\n\\t\\t\\t\\tmax.y,\\n\\t\\t\\t\\tmin.z,\\n\\t\\t\\t\\tmax.x,\\n\\t\\t\\t\\tmax.y,\\n\\t\\t\\t\\tmin.z,\\n\\t\\t\\t\\tmax.x,\\n\\t\\t\\t\\tmax.y,\\n\\t\\t\\t\\tmin.z,\\n\\t\\t\\t\\tmax.x,\\n\\t\\t\\t\\tmin.y,\\n\\t\\t\\t\\tmin.z,\\n\\t\\t\\t\\tmax.x,\\n\\t\\t\\t\\tmin.y,\\n\\t\\t\\t\\tmin.z,\\n\\t\\t\\t\\tmin.x,\\n\\t\\t\\t\\tmin.y,\\n\\t\\t\\t\\tmin.z,\\n\\t\\t\\t\\tmin.x,\\n\\t\\t\\t\\tmin.y,\\n\\t\\t\\t\\tmax.z,\\n\\t\\t\\t\\tmin.x,\\n\\t\\t\\t\\tmax.y,\\n\\t\\t\\t\\tmax.z,\\n\\t\\t\\t\\tmin.x,\\n\\t\\t\\t\\tmax.y,\\n\\t\\t\\t\\tmax.z,\\n\\t\\t\\t\\tmax.x,\\n\\t\\t\\t\\tmax.y,\\n\\t\\t\\t\\tmax.z,\\n\\t\\t\\t\\tmax.x,\\n\\t\\t\\t\\tmax.y,\\n\\t\\t\\t\\tmax.z,\\n\\t\\t\\t\\tmax.x,\\n\\t\\t\\t\\tmin.y,\\n\\t\\t\\t\\tmax.z,\\n\\t\\t\\t\\tmax.x,\\n\\t\\t\\t\\tmin.y,\\n\\t\\t\\t\\tmax.z,\\n\\t\\t\\t\\tmin.x,\\n\\t\\t\\t\\tmin.y,\\n\\t\\t\\t\\tmax.z,\\n\\t\\t\\t\\tmin.x,\\n\\t\\t\\t\\tmin.y,\\n\\t\\t\\t\\tmin.z,\\n\\t\\t\\t\\tmin.x,\\n\\t\\t\\t\\tmin.y,\\n\\t\\t\\t\\tmax.z,\\n\\t\\t\\t\\tmin.x,\\n\\t\\t\\t\\tmax.y,\\n\\t\\t\\t\\tmin.z,\\n\\t\\t\\t\\tmin.x,\\n\\t\\t\\t\\tmax.y,\\n\\t\\t\\t\\tmax.z,\\n\\t\\t\\t\\tmax.x,\\n\\t\\t\\t\\tmax.y,\\n\\t\\t\\t\\tmin.z,\\n\\t\\t\\t\\tmax.x,\\n\\t\\t\\t\\tmax.y,\\n\\t\\t\\t\\tmax.z,\\n\\t\\t\\t\\tmax.x,\\n\\t\\t\\t\\tmin.y,\\n\\t\\t\\t\\tmin.z,\\n\\t\\t\\t\\tmax.x,\\n\\t\\t\\t\\tmin.y,\\n\\t\\t\\t\\tmax.z\\n\\t\\t\\t);\\n\\t\\t}\\n\\t\\tconst batch = this.getBatch(layer, depthTest);\\n\\t\\tbatch.addLinesArrays(tempPoints, color);\\n\\t\\ttempPoints.length = 0;\\n\\t}\\n\\tdrawWireSphere(center, radius, color, numSegments, depthTest, layer) {\\n\\t\\tconst step = 2 * Math.PI / numSegments;\\n\\t\\tlet angle = 0;\\n\\t\\tfor (let i = 0; i < numSegments; i++) {\\n\\t\\t\\tconst sin0 = Math.sin(angle);\\n\\t\\t\\tconst cos0 = Math.cos(angle);\\n\\t\\t\\tangle += step;\\n\\t\\t\\tconst sin1 = Math.sin(angle);\\n\\t\\t\\tconst cos1 = Math.cos(angle);\\n\\t\\t\\ttempPoints.push(center.x + radius * sin0, center.y, center.z + radius * cos0);\\n\\t\\t\\ttempPoints.push(center.x + radius * sin1, center.y, center.z + radius * cos1);\\n\\t\\t\\ttempPoints.push(center.x + radius * sin0, center.y + radius * cos0, center.z);\\n\\t\\t\\ttempPoints.push(center.x + radius * sin1, center.y + radius * cos1, center.z);\\n\\t\\t\\ttempPoints.push(center.x, center.y + radius * sin0, center.z + radius * cos0);\\n\\t\\t\\ttempPoints.push(center.x, center.y + radius * sin1, center.z + radius * cos1);\\n\\t\\t}\\n\\t\\tconst batch = this.getBatch(layer, depthTest);\\n\\t\\tbatch.addLinesArrays(tempPoints, color);\\n\\t\\ttempPoints.length = 0;\\n\\t}\\n\\tgetGraphNode(matrix) {\\n\\t\\tconst graphNode = new GraphNode(\\\"ImmediateDebug\\\");\\n\\t\\tgraphNode.worldTransform = matrix;\\n\\t\\tgraphNode._dirtyWorld = graphNode._dirtyNormal = false;\\n\\t\\treturn graphNode;\\n\\t}\\n\\t// This is called just before the layer is rendered to allow lines for the layer to be added from inside\\n\\t// the frame getting rendered\\n\\tonPreRenderLayer(layer, visibleList, transparent) {\\n\\t\\tthis.batchesMap.forEach((batches, batchLayer) => {\\n\\t\\t\\tif (batchLayer === layer) {\\n\\t\\t\\t\\tbatches.onPreRender(visibleList, transparent);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tif (!this.updatedLayers.has(layer)) {\\n\\t\\t\\tthis.updatedLayers.add(layer);\\n\\t\\t\\tconst meshInstances = this.layerMeshInstances.get(layer);\\n\\t\\t\\tif (meshInstances) {\\n\\t\\t\\t\\tfor (let i = 0; i < meshInstances.length; i++) {\\n\\t\\t\\t\\t\\tvisibleList.push(meshInstances[i]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tmeshInstances.length = 0;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t// called after the frame was rendered, clears data\\n\\tonPostRender() {\\n\\t\\tthis.allBatches.forEach((batch) => batch.clear());\\n\\t\\tthis.allBatches.clear();\\n\\t\\tthis.updatedLayers.clear();\\n\\t}\\n}\\n\\nconst _goldenAngle = 2.399963229728653;\\nconst random = {\\n\\tcirclePoint(point) {\\n\\t\\tconst r = Math.sqrt(Math.random());\\n\\t\\tconst theta = Math.random() * 2 * Math.PI;\\n\\t\\tpoint.x = r * Math.cos(theta);\\n\\t\\tpoint.y = r * Math.sin(theta);\\n\\t},\\n\\tcirclePointDeterministic(point, index, numPoints) {\\n\\t\\tconst theta = index * _goldenAngle;\\n\\t\\tconst r = Math.sqrt(index / numPoints);\\n\\t\\tpoint.x = r * Math.cos(theta);\\n\\t\\tpoint.y = r * Math.sin(theta);\\n\\t},\\n\\tspherePointDeterministic(point, index, numPoints, start = 0, end = 1) {\\n\\t\\tstart = 1 - 2 * start;\\n\\t\\tend = 1 - 2 * end;\\n\\t\\tconst y = math.lerp(start, end, index / numPoints);\\n\\t\\tconst radius = Math.sqrt(1 - y * y);\\n\\t\\tconst theta = _goldenAngle * index;\\n\\t\\tpoint.x = Math.cos(theta) * radius;\\n\\t\\tpoint.y = y;\\n\\t\\tpoint.z = Math.sin(theta) * radius;\\n\\t},\\n\\tradicalInverse(i) {\\n\\t\\tlet bits = (i << 16 | i >>> 16) >>> 0;\\n\\t\\tbits = ((bits & 1431655765) << 1 | (bits & 2863311530) >>> 1) >>> 0;\\n\\t\\tbits = ((bits & 858993459) << 2 | (bits & 3435973836) >>> 2) >>> 0;\\n\\t\\tbits = ((bits & 252645135) << 4 | (bits & 4042322160) >>> 4) >>> 0;\\n\\t\\tbits = ((bits & 16711935) << 8 | (bits & 4278255360) >>> 8) >>> 0;\\n\\t\\treturn bits * 23283064365386963e-26;\\n\\t}\\n};\\n\\nconst getProjectionName = (projection) => {\\n\\tswitch (projection) {\\n\\t\\tcase TEXTUREPROJECTION_CUBE:\\n\\t\\t\\treturn \\\"Cubemap\\\";\\n\\t\\tcase TEXTUREPROJECTION_OCTAHEDRAL:\\n\\t\\t\\treturn \\\"Octahedral\\\";\\n\\t\\tdefault:\\n\\t\\t\\treturn \\\"Equirect\\\";\\n\\t}\\n};\\nconst packFloat32ToRGBA8 = (value, array, offset) => {\\n\\tif (value <= 0) {\\n\\t\\tarray[offset + 0] = 0;\\n\\t\\tarray[offset + 1] = 0;\\n\\t\\tarray[offset + 2] = 0;\\n\\t\\tarray[offset + 3] = 0;\\n\\t} else if (value >= 1) {\\n\\t\\tarray[offset + 0] = 255;\\n\\t\\tarray[offset + 1] = 0;\\n\\t\\tarray[offset + 2] = 0;\\n\\t\\tarray[offset + 3] = 0;\\n\\t} else {\\n\\t\\tlet encX = 1 * value % 1;\\n\\t\\tlet encY = 255 * value % 1;\\n\\t\\tlet encZ = 65025 * value % 1;\\n\\t\\tconst encW = 16581375 * value % 1;\\n\\t\\tencX -= encY / 255;\\n\\t\\tencY -= encZ / 255;\\n\\t\\tencZ -= encW / 255;\\n\\t\\tarray[offset + 0] = Math.min(255, Math.floor(encX * 256));\\n\\t\\tarray[offset + 1] = Math.min(255, Math.floor(encY * 256));\\n\\t\\tarray[offset + 2] = Math.min(255, Math.floor(encZ * 256));\\n\\t\\tarray[offset + 3] = Math.min(255, Math.floor(encW * 256));\\n\\t}\\n};\\nconst packSamples = (samples) => {\\n\\tconst numSamples = samples.length;\\n\\tconst w = Math.min(numSamples, 512);\\n\\tconst h = Math.ceil(numSamples / w);\\n\\tconst data = new Uint8Array(w * h * 4);\\n\\tlet off = 0;\\n\\tfor (let i = 0; i < numSamples; i += 4) {\\n\\t\\tpackFloat32ToRGBA8(samples[i + 0] * 0.5 + 0.5, data, off + 0);\\n\\t\\tpackFloat32ToRGBA8(samples[i + 1] * 0.5 + 0.5, data, off + 4);\\n\\t\\tpackFloat32ToRGBA8(samples[i + 2] * 0.5 + 0.5, data, off + 8);\\n\\t\\tpackFloat32ToRGBA8(samples[i + 3] / 8, data, off + 12);\\n\\t\\toff += 16;\\n\\t}\\n\\treturn {\\n\\t\\twidth: w,\\n\\t\\theight: h,\\n\\t\\tdata\\n\\t};\\n};\\nconst hemisphereSamplePhong = (dstVec, x, y, specularPower) => {\\n\\tconst phi = y * 2 * Math.PI;\\n\\tconst cosTheta = Math.pow(1 - x, 1 / (specularPower + 1));\\n\\tconst sinTheta = Math.sqrt(1 - cosTheta * cosTheta);\\n\\tdstVec.set(Math.cos(phi) * sinTheta, Math.sin(phi) * sinTheta, cosTheta).normalize();\\n};\\nconst hemisphereSampleLambert = (dstVec, x, y) => {\\n\\tconst phi = y * 2 * Math.PI;\\n\\tconst cosTheta = Math.sqrt(1 - x);\\n\\tconst sinTheta = Math.sqrt(x);\\n\\tdstVec.set(Math.cos(phi) * sinTheta, Math.sin(phi) * sinTheta, cosTheta).normalize();\\n};\\nconst hemisphereSampleGGX = (dstVec, x, y, a) => {\\n\\tconst phi = y * 2 * Math.PI;\\n\\tconst cosTheta = Math.sqrt((1 - x) / (1 + (a * a - 1) * x));\\n\\tconst sinTheta = Math.sqrt(1 - cosTheta * cosTheta);\\n\\tdstVec.set(Math.cos(phi) * sinTheta, Math.sin(phi) * sinTheta, cosTheta).normalize();\\n};\\nconst D_GGX = (NoH, linearRoughness) => {\\n\\tconst a = NoH * linearRoughness;\\n\\tconst k = linearRoughness / (1 - NoH * NoH + a * a);\\n\\treturn k * k * (1 / Math.PI);\\n};\\nconst generatePhongSamples = (numSamples, specularPower) => {\\n\\tconst H = new Vec3();\\n\\tconst result = [];\\n\\tfor (let i = 0; i < numSamples; ++i) {\\n\\t\\themisphereSamplePhong(H, i / numSamples, random.radicalInverse(i), specularPower);\\n\\t\\tresult.push(H.x, H.y, H.z, 0);\\n\\t}\\n\\treturn result;\\n};\\nconst generateLambertSamples = (numSamples, sourceTotalPixels) => {\\n\\tconst pixelsPerSample = sourceTotalPixels / numSamples;\\n\\tconst H = new Vec3();\\n\\tconst result = [];\\n\\tfor (let i = 0; i < numSamples; ++i) {\\n\\t\\themisphereSampleLambert(H, i / numSamples, random.radicalInverse(i));\\n\\t\\tconst pdf = H.z / Math.PI;\\n\\t\\tconst mipLevel = 0.5 * Math.log2(pixelsPerSample / pdf);\\n\\t\\tresult.push(H.x, H.y, H.z, mipLevel);\\n\\t}\\n\\treturn result;\\n};\\nconst requiredSamplesGGX = {\\n\\t\\\"16\\\": {\\n\\t\\t\\\"2\\\": 26,\\n\\t\\t\\\"8\\\": 20,\\n\\t\\t\\\"32\\\": 17,\\n\\t\\t\\\"128\\\": 16,\\n\\t\\t\\\"512\\\": 16\\n\\t},\\n\\t\\\"32\\\": {\\n\\t\\t\\\"2\\\": 53,\\n\\t\\t\\\"8\\\": 40,\\n\\t\\t\\\"32\\\": 34,\\n\\t\\t\\\"128\\\": 32,\\n\\t\\t\\\"512\\\": 32\\n\\t},\\n\\t\\\"128\\\": {\\n\\t\\t\\\"2\\\": 214,\\n\\t\\t\\\"8\\\": 163,\\n\\t\\t\\\"32\\\": 139,\\n\\t\\t\\\"128\\\": 130,\\n\\t\\t\\\"512\\\": 128\\n\\t},\\n\\t\\\"1024\\\": {\\n\\t\\t\\\"2\\\": 1722,\\n\\t\\t\\\"8\\\": 1310,\\n\\t\\t\\\"32\\\": 1114,\\n\\t\\t\\\"128\\\": 1041,\\n\\t\\t\\\"512\\\": 1025\\n\\t}\\n};\\nconst getRequiredSamplesGGX = (numSamples, specularPower) => {\\n\\tconst table = requiredSamplesGGX[numSamples];\\n\\treturn table && table[specularPower] || numSamples;\\n};\\nconst generateGGXSamples = (numSamples, specularPower, sourceTotalPixels) => {\\n\\tconst pixelsPerSample = sourceTotalPixels / numSamples;\\n\\tconst roughness = 1 - Math.log2(specularPower) / 11;\\n\\tconst a = roughness * roughness;\\n\\tconst H = new Vec3();\\n\\tconst L = new Vec3();\\n\\tconst N = new Vec3(0, 0, 1);\\n\\tconst result = [];\\n\\tconst requiredSamples = getRequiredSamplesGGX(numSamples, specularPower);\\n\\tfor (let i = 0; i < requiredSamples; ++i) {\\n\\t\\themisphereSampleGGX(H, i / requiredSamples, random.radicalInverse(i), a);\\n\\t\\tconst NoH = H.z;\\n\\t\\tL.set(H.x, H.y, H.z).mulScalar(2 * NoH).sub(N);\\n\\t\\tif (L.z > 0) {\\n\\t\\t\\tconst pdf = D_GGX(Math.min(1, NoH), a) / 4 + 1e-3;\\n\\t\\t\\tconst mipLevel = 0.5 * Math.log2(pixelsPerSample / pdf);\\n\\t\\t\\tresult.push(L.x, L.y, L.z, mipLevel);\\n\\t\\t}\\n\\t}\\n\\twhile (result.length < numSamples * 4) {\\n\\t\\tresult.push(0, 0, 0, 0);\\n\\t}\\n\\treturn result;\\n};\\nconst createSamplesTex = (device, name, samples) => {\\n\\tconst packedSamples = packSamples(samples);\\n\\treturn new Texture(device, {\\n\\t\\tname,\\n\\t\\twidth: packedSamples.width,\\n\\t\\theight: packedSamples.height,\\n\\t\\tmipmaps: false,\\n\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\tlevels: [packedSamples.data]\\n\\t});\\n};\\nclass SimpleCache {\\n\\tconstructor(destroyContent = true) {\\n\\t\\tthis.destroyContent = destroyContent;\\n\\t}\\n\\tmap = /* @__PURE__ */ new Map();\\n\\tdestroy() {\\n\\t\\tif (this.destroyContent) {\\n\\t\\t\\tthis.map.forEach((value, key) => {\\n\\t\\t\\t\\tvalue.destroy();\\n\\t\\t\\t});\\n\\t\\t}\\n\\t}\\n\\tget(key, missFunc) {\\n\\t\\tif (!this.map.has(key)) {\\n\\t\\t\\tconst result = missFunc();\\n\\t\\t\\tthis.map.set(key, result);\\n\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\treturn this.map.get(key);\\n\\t}\\n}\\nconst samplesCache = new SimpleCache(false);\\nconst deviceCache$1 = new DeviceCache();\\nconst getCachedTexture = (device, key, getSamplesFnc) => {\\n\\tconst cache = deviceCache$1.get(device, () => {\\n\\t\\treturn new SimpleCache();\\n\\t});\\n\\treturn cache.get(key, () => {\\n\\t\\treturn createSamplesTex(device, key, samplesCache.get(key, getSamplesFnc));\\n\\t});\\n};\\nconst generateLambertSamplesTex = (device, numSamples, sourceTotalPixels) => {\\n\\tconst key = `lambert-samples-${numSamples}-${sourceTotalPixels}`;\\n\\treturn getCachedTexture(device, key, () => {\\n\\t\\treturn generateLambertSamples(numSamples, sourceTotalPixels);\\n\\t});\\n};\\nconst generatePhongSamplesTex = (device, numSamples, specularPower) => {\\n\\tconst key = `phong-samples-${numSamples}-${specularPower}`;\\n\\treturn getCachedTexture(device, key, () => {\\n\\t\\treturn generatePhongSamples(numSamples, specularPower);\\n\\t});\\n};\\nconst generateGGXSamplesTex = (device, numSamples, specularPower, sourceTotalPixels) => {\\n\\tconst key = `ggx-samples-${numSamples}-${specularPower}-${sourceTotalPixels}`;\\n\\treturn getCachedTexture(device, key, () => {\\n\\t\\treturn generateGGXSamples(numSamples, specularPower, sourceTotalPixels);\\n\\t});\\n};\\nfunction reprojectTexture(source, target, options = {}) {\\n\\tconst seamPixels = options.seamPixels ?? 0;\\n\\tconst innerWidth = (options.rect?.z ?? target.width) - seamPixels * 2;\\n\\tconst innerHeight = (options.rect?.w ?? target.height) - seamPixels * 2;\\n\\tif (innerWidth < 1 || innerHeight < 1) {\\n\\t\\treturn false;\\n\\t}\\n\\tconst funcNames = {\\n\\t\\t\\\"none\\\": \\\"reproject\\\",\\n\\t\\t\\\"lambert\\\": \\\"prefilterSamplesUnweighted\\\",\\n\\t\\t\\\"phong\\\": \\\"prefilterSamplesUnweighted\\\",\\n\\t\\t\\\"ggx\\\": \\\"prefilterSamples\\\"\\n\\t};\\n\\tconst specularPower = options.hasOwnProperty(\\\"specularPower\\\") ? options.specularPower : 1;\\n\\tconst face = options.hasOwnProperty(\\\"face\\\") ? options.face : null;\\n\\tconst distribution = options.hasOwnProperty(\\\"distribution\\\") ? options.distribution : specularPower === 1 ? \\\"none\\\" : \\\"phong\\\";\\n\\tconst processFunc = funcNames[distribution] || \\\"reproject\\\";\\n\\tconst prefilterSamples = processFunc.startsWith(\\\"prefilterSamples\\\");\\n\\tconst decodeFunc = ChunkUtils.decodeFunc(source.encoding);\\n\\tconst encodeFunc = ChunkUtils.encodeFunc(target.encoding);\\n\\tconst sourceFunc = `sample${getProjectionName(source.projection)}`;\\n\\tconst targetFunc = `getDirection${getProjectionName(target.projection)}`;\\n\\tconst numSamples = options.hasOwnProperty(\\\"numSamples\\\") ? options.numSamples : 1024;\\n\\tconst shaderKey = `ReprojectShader:${processFunc}_${decodeFunc}_${encodeFunc}_${sourceFunc}_${targetFunc}_${numSamples}`;\\n\\tconst device = source.device;\\n\\tlet shader = getProgramLibrary(device).getCachedShader(shaderKey);\\n\\tif (!shader) {\\n\\t\\tconst defines = /* @__PURE__ */ new Map();\\n\\t\\tif (prefilterSamples) defines.set(\\\"USE_SAMPLES_TEX\\\", \\\"\\\");\\n\\t\\tif (source.cubemap) defines.set(\\\"CUBEMAP_SOURCE\\\", \\\"\\\");\\n\\t\\tdefines.set(\\\"{PROCESS_FUNC}\\\", processFunc);\\n\\t\\tdefines.set(\\\"{DECODE_FUNC}\\\", decodeFunc);\\n\\t\\tdefines.set(\\\"{ENCODE_FUNC}\\\", encodeFunc);\\n\\t\\tdefines.set(\\\"{SOURCE_FUNC}\\\", sourceFunc);\\n\\t\\tdefines.set(\\\"{TARGET_FUNC}\\\", targetFunc);\\n\\t\\tdefines.set(\\\"{NUM_SAMPLES}\\\", numSamples);\\n\\t\\tdefines.set(\\\"{NUM_SAMPLES_SQRT}\\\", Math.round(Math.sqrt(numSamples)).toFixed(1));\\n\\t\\tshader = ShaderUtils.createShader(device, {\\n\\t\\t\\tuniqueName: shaderKey,\\n\\t\\t\\tattributes: { vertex_position: SEMANTIC_POSITION },\\n\\t\\t\\tvertexChunk: \\\"reprojectVS\\\",\\n\\t\\t\\tfragmentChunk: \\\"reprojectPS\\\",\\n\\t\\t\\tfragmentDefines: defines\\n\\t\\t});\\n\\t}\\n\\tdevice.setBlendState(BlendState.NOBLEND);\\n\\tconst constantSource = device.scope.resolve(source.cubemap ? \\\"sourceCube\\\" : \\\"sourceTex\\\");\\n\\tconstantSource.setValue(source);\\n\\tconst constantParams = device.scope.resolve(\\\"params\\\");\\n\\tconst uvModParam = device.scope.resolve(\\\"uvMod\\\");\\n\\tif (seamPixels > 0) {\\n\\t\\tuvModParam.setValue([\\n\\t\\t\\t(innerWidth + seamPixels * 2) / innerWidth,\\n\\t\\t\\t(innerHeight + seamPixels * 2) / innerHeight,\\n\\t\\t\\t-seamPixels / innerWidth,\\n\\t\\t\\t-seamPixels / innerHeight\\n\\t\\t]);\\n\\t} else {\\n\\t\\tuvModParam.setValue([1, 1, 0, 0]);\\n\\t}\\n\\tconst params = [\\n\\t\\t0,\\n\\t\\ttarget.width * target.height * (target.cubemap ? 6 : 1),\\n\\t\\tsource.width * source.height * (source.cubemap ? 6 : 1)\\n\\t];\\n\\tif (prefilterSamples) {\\n\\t\\tconst sourceTotalPixels = source.width * source.height * (source.cubemap ? 6 : 1);\\n\\t\\tconst samplesTex = distribution === \\\"ggx\\\" ? generateGGXSamplesTex(device, numSamples, specularPower, sourceTotalPixels) : distribution === \\\"lambert\\\" ? generateLambertSamplesTex(device, numSamples, sourceTotalPixels) : generatePhongSamplesTex(device, numSamples, specularPower);\\n\\t\\tdevice.scope.resolve(\\\"samplesTex\\\").setValue(samplesTex);\\n\\t\\tdevice.scope.resolve(\\\"samplesTexInverseSize\\\").setValue([1 / samplesTex.width, 1 / samplesTex.height]);\\n\\t}\\n\\tfor (let f = 0; f < (target.cubemap ? 6 : 1); f++) {\\n\\t\\tif (face === null || f === face) {\\n\\t\\t\\tconst renderTarget = new RenderTarget({\\n\\t\\t\\t\\tcolorBuffer: target,\\n\\t\\t\\t\\tface: f,\\n\\t\\t\\t\\tdepth: false,\\n\\t\\t\\t\\tflipY: device.isWebGPU\\n\\t\\t\\t});\\n\\t\\t\\tparams[0] = f;\\n\\t\\t\\tconstantParams.setValue(params);\\n\\t\\t\\tdrawQuadWithShader(device, renderTarget, shader, options?.rect);\\n\\t\\t\\trenderTarget.destroy();\\n\\t\\t}\\n\\t}\\n\\treturn true;\\n}\\n\\nconst calcLevels = (width, height = 0) => {\\n\\treturn 1 + Math.floor(Math.log2(Math.max(width, height)));\\n};\\nconst supportsFloat16 = (device) => {\\n\\treturn device.textureHalfFloatRenderable;\\n};\\nconst supportsFloat32 = (device) => {\\n\\treturn device.textureFloatRenderable;\\n};\\nconst lightingSourcePixelFormat = (device) => {\\n\\treturn supportsFloat16(device) ? PIXELFORMAT_RGBA16F : supportsFloat32(device) ? PIXELFORMAT_RGBA32F : PIXELFORMAT_RGBA8;\\n};\\nconst lightingPixelFormat = (device) => {\\n\\treturn PIXELFORMAT_RGBA8;\\n};\\nconst createCubemap = (device, size, format, mipmaps) => {\\n\\treturn new Texture(device, {\\n\\t\\tname: `lighting-${size}`,\\n\\t\\tcubemap: true,\\n\\t\\twidth: size,\\n\\t\\theight: size,\\n\\t\\tformat,\\n\\t\\ttype: TEXTURETYPE_RGBP ,\\n\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\tmipmaps: false\\n\\t});\\n};\\nclass EnvLighting {\\n\\tstatic generateSkyboxCubemap(source, size) {\\n\\t\\tconst device = source.device;\\n\\t\\tconst result = createCubemap(device, size || (source.cubemap ? source.width : source.width / 4), PIXELFORMAT_RGBA8);\\n\\t\\treprojectTexture(source, result, {\\n\\t\\t\\tnumSamples: 1024\\n\\t\\t});\\n\\t\\treturn result;\\n\\t}\\n\\tstatic generateLightingSource(source, options) {\\n\\t\\tconst device = source.device;\\n\\t\\tconst format = lightingSourcePixelFormat(device);\\n\\t\\tconst result = options?.target || new Texture(device, {\\n\\t\\t\\tname: \\\"lighting-source\\\",\\n\\t\\t\\tcubemap: true,\\n\\t\\t\\twidth: options?.size || 128,\\n\\t\\t\\theight: options?.size || 128,\\n\\t\\t\\tformat,\\n\\t\\t\\ttype: format === PIXELFORMAT_RGBA8 ? TEXTURETYPE_RGBP : TEXTURETYPE_DEFAULT,\\n\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\tmipmaps: true\\n\\t\\t});\\n\\t\\treprojectTexture(source, result, {\\n\\t\\t\\tnumSamples: source.mipmaps ? 1 : 1024\\n\\t\\t});\\n\\t\\treturn result;\\n\\t}\\n\\tstatic generateAtlas(source, options) {\\n\\t\\tconst device = source.device;\\n\\t\\tconst format = lightingPixelFormat();\\n\\t\\tconst result = options?.target || new Texture(device, {\\n\\t\\t\\tname: \\\"envAtlas\\\",\\n\\t\\t\\twidth: options?.size || 512,\\n\\t\\t\\theight: options?.size || 512,\\n\\t\\t\\tformat,\\n\\t\\t\\ttype: TEXTURETYPE_RGBP ,\\n\\t\\t\\tprojection: TEXTUREPROJECTION_EQUIRECT,\\n\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\tmipmaps: false\\n\\t\\t});\\n\\t\\tconst s = result.width / 512;\\n\\t\\tconst rect = new Vec4(0, 0, 512 * s, 256 * s);\\n\\t\\tconst levels = calcLevels(256) - calcLevels(4);\\n\\t\\tfor (let i = 0; i < levels; ++i) {\\n\\t\\t\\treprojectTexture(source, result, {\\n\\t\\t\\t\\tnumSamples: 1,\\n\\t\\t\\t\\trect,\\n\\t\\t\\t\\tseamPixels: s\\n\\t\\t\\t});\\n\\t\\t\\trect.x += rect.w;\\n\\t\\t\\trect.y += rect.w;\\n\\t\\t\\trect.z = Math.max(1, Math.floor(rect.z * 0.5));\\n\\t\\t\\trect.w = Math.max(1, Math.floor(rect.w * 0.5));\\n\\t\\t}\\n\\t\\trect.set(0, 256 * s, 256 * s, 128 * s);\\n\\t\\tfor (let i = 1; i < 7; ++i) {\\n\\t\\t\\treprojectTexture(source, result, {\\n\\t\\t\\t\\tnumSamples: options?.numReflectionSamples || 1024,\\n\\t\\t\\t\\tdistribution: options?.distribution || \\\"ggx\\\",\\n\\t\\t\\t\\tspecularPower: Math.max(1, 2048 >> i * 2),\\n\\t\\t\\t\\trect,\\n\\t\\t\\t\\tseamPixels: s\\n\\t\\t\\t});\\n\\t\\t\\trect.y += rect.w;\\n\\t\\t\\trect.z = Math.max(1, Math.floor(rect.z * 0.5));\\n\\t\\t\\trect.w = Math.max(1, Math.floor(rect.w * 0.5));\\n\\t\\t}\\n\\t\\trect.set(128 * s, (256 + 128) * s, 64 * s, 32 * s);\\n\\t\\treprojectTexture(source, result, {\\n\\t\\t\\tnumSamples: options?.numAmbientSamples || 2048,\\n\\t\\t\\tdistribution: \\\"lambert\\\",\\n\\t\\t\\trect,\\n\\t\\t\\tseamPixels: s\\n\\t\\t});\\n\\t\\treturn result;\\n\\t}\\n\\tstatic generatePrefilteredAtlas(sources, options) {\\n\\t\\tconst device = sources[0].device;\\n\\t\\tconst format = sources[0].format;\\n\\t\\tconst type = sources[0].type;\\n\\t\\tconst result = options?.target || new Texture(device, {\\n\\t\\t\\tname: \\\"envPrefilteredAtlas\\\",\\n\\t\\t\\twidth: options?.size || 512,\\n\\t\\t\\theight: options?.size || 512,\\n\\t\\t\\tformat,\\n\\t\\t\\ttype,\\n\\t\\t\\tprojection: TEXTUREPROJECTION_EQUIRECT,\\n\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\tmipmaps: false\\n\\t\\t});\\n\\t\\tconst s = result.width / 512;\\n\\t\\tconst rect = new Vec4(0, 0, 512 * s, 256 * s);\\n\\t\\tconst levels = calcLevels(512);\\n\\t\\tfor (let i = 0; i < levels; ++i) {\\n\\t\\t\\treprojectTexture(sources[0], result, {\\n\\t\\t\\t\\tnumSamples: 1,\\n\\t\\t\\t\\trect,\\n\\t\\t\\t\\tseamPixels: s\\n\\t\\t\\t});\\n\\t\\t\\trect.x += rect.w;\\n\\t\\t\\trect.y += rect.w;\\n\\t\\t\\trect.z = Math.max(1, Math.floor(rect.z * 0.5));\\n\\t\\t\\trect.w = Math.max(1, Math.floor(rect.w * 0.5));\\n\\t\\t}\\n\\t\\trect.set(0, 256 * s, 256 * s, 128 * s);\\n\\t\\tfor (let i = 1; i < sources.length; ++i) {\\n\\t\\t\\treprojectTexture(sources[i], result, {\\n\\t\\t\\t\\tnumSamples: 1,\\n\\t\\t\\t\\trect,\\n\\t\\t\\t\\tseamPixels: s\\n\\t\\t\\t});\\n\\t\\t\\trect.y += rect.w;\\n\\t\\t\\trect.z = Math.max(1, Math.floor(rect.z * 0.5));\\n\\t\\t\\trect.w = Math.max(1, Math.floor(rect.w * 0.5));\\n\\t\\t}\\n\\t\\trect.set(128 * s, (256 + 128) * s, 64 * s, 32 * s);\\n\\t\\tif (options?.legacyAmbient) {\\n\\t\\t\\treprojectTexture(sources[5], result, {\\n\\t\\t\\t\\tnumSamples: 1,\\n\\t\\t\\t\\trect,\\n\\t\\t\\t\\tseamPixels: s\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\treprojectTexture(sources[0], result, {\\n\\t\\t\\t\\tnumSamples: options?.numSamples || 2048,\\n\\t\\t\\t\\tdistribution: \\\"lambert\\\",\\n\\t\\t\\t\\trect,\\n\\t\\t\\t\\tseamPixels: s\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n}\\n\\nclass FogParams {\\n\\ttype = FOG_NONE;\\n\\tcolor = new Color(0, 0, 0);\\n\\tdensity = 0;\\n\\tstart = 1;\\n\\tend = 1e3;\\n}\\n\\nclass Scene extends EventHandler {\\n\\tstatic EVENT_SETLAYERS = \\\"set:layers\\\";\\n\\tstatic EVENT_SETSKYBOX = \\\"set:skybox\\\";\\n\\tstatic EVENT_PRERENDER = \\\"prerender\\\";\\n\\tstatic EVENT_POSTRENDER = \\\"postrender\\\";\\n\\tstatic EVENT_PRERENDER_LAYER = \\\"prerender:layer\\\";\\n\\tstatic EVENT_POSTRENDER_LAYER = \\\"postrender:layer\\\";\\n\\tstatic EVENT_PRECULL = \\\"precull\\\";\\n\\tstatic EVENT_POSTCULL = \\\"postcull\\\";\\n\\tambientBake = false;\\n\\tambientBakeOcclusionBrightness = 0;\\n\\tambientBakeOcclusionContrast = 0;\\n\\tambientLight = new Color(0, 0, 0);\\n\\tambientLuminance = 0;\\n\\texposure = 1;\\n\\tlightmapSizeMultiplier = 1;\\n\\tlightmapMaxResolution = 2048;\\n\\tlightmapMode = BAKE_COLORDIR;\\n\\tlightmapFilterEnabled = false;\\n\\tlightmapHDR = false;\\n\\troot = null;\\n\\tphysicalUnits = false;\\n\\t_envAtlas = null;\\n\\t_skyboxCubeMap = null;\\n\\t_fogParams = new FogParams();\\n\\tforcePassThroughSpecular = false;\\n\\tconstructor(graphicsDevice) {\\n\\t\\tsuper();\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tthis._gravity = new Vec3(0, -9.8, 0);\\n\\t\\tthis._layers = null;\\n\\t\\tthis._prefilteredCubemaps = [];\\n\\t\\tthis._internalEnvAtlas = null;\\n\\t\\tthis._skyboxIntensity = 1;\\n\\t\\tthis._skyboxLuminance = 0;\\n\\t\\tthis._skyboxMip = 0;\\n\\t\\tthis._skyboxHighlightMultiplier = 1;\\n\\t\\tthis._skyboxRotationShaderInclude = false;\\n\\t\\tthis._skyboxRotation = new Quat();\\n\\t\\tthis._skyboxRotationMat3 = new Mat3();\\n\\t\\tthis._skyboxRotationMat4 = new Mat4();\\n\\t\\tthis._ambientBakeNumSamples = 1;\\n\\t\\tthis._ambientBakeSpherePart = 0.4;\\n\\t\\tthis._lightmapFilterRange = 10;\\n\\t\\tthis._lightmapFilterSmoothness = 0.2;\\n\\t\\tthis._clusteredLightingEnabled = true;\\n\\t\\tthis._lightingParams = new LightingParams(this.device.supportsAreaLights, this.device.maxTextureSize, () => {\\n\\t\\t\\tthis.updateShaders = true;\\n\\t\\t});\\n\\t\\tthis.gsplatCentersEnabled = true;\\n\\t\\tthis._gsplatParams = new GSplatParams(this.device);\\n\\t\\tthis._sky = new Sky(this);\\n\\t\\tthis._stats = {\\n\\t\\t\\tmeshInstances: 0,\\n\\t\\t\\tlights: 0,\\n\\t\\t\\tdynamicLights: 0,\\n\\t\\t\\tbakedLights: 0,\\n\\t\\t\\tupdateShadersTime: 0\\n\\t\\t\\t// deprecated\\n\\t\\t};\\n\\t\\tthis.updateShaders = true;\\n\\t\\tthis._shaderVersion = 0;\\n\\t\\tthis.immediate = new Immediate(this.device);\\n\\t}\\n\\tget defaultDrawLayer() {\\n\\t\\treturn this.layers.getLayerById(LAYERID_IMMEDIATE);\\n\\t}\\n\\tset ambientBakeNumSamples(value) {\\n\\t\\tthis._ambientBakeNumSamples = math.clamp(Math.floor(value), 1, 255);\\n\\t}\\n\\tget ambientBakeNumSamples() {\\n\\t\\treturn this._ambientBakeNumSamples;\\n\\t}\\n\\tset ambientBakeSpherePart(value) {\\n\\t\\tthis._ambientBakeSpherePart = math.clamp(value, 1e-3, 1);\\n\\t}\\n\\tget ambientBakeSpherePart() {\\n\\t\\treturn this._ambientBakeSpherePart;\\n\\t}\\n\\tset clusteredLightingEnabled(value) {\\n\\t\\tif (this.device.isWebGPU && !value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!this._clusteredLightingEnabled && value) {\\n\\t\\t\\tconsole.error(\\\"Turning on disabled clustered lighting is not currently supported\\\");\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._clusteredLightingEnabled = value;\\n\\t}\\n\\tget clusteredLightingEnabled() {\\n\\t\\treturn this._clusteredLightingEnabled;\\n\\t}\\n\\tset envAtlas(value) {\\n\\t\\tif (value !== this._envAtlas) {\\n\\t\\t\\tthis._envAtlas = value;\\n\\t\\t\\tif (value) {\\n\\t\\t\\t\\tvalue.addressU = ADDRESS_CLAMP_TO_EDGE;\\n\\t\\t\\t\\tvalue.addressV = ADDRESS_CLAMP_TO_EDGE;\\n\\t\\t\\t\\tvalue.minFilter = FILTER_LINEAR;\\n\\t\\t\\t\\tvalue.magFilter = FILTER_LINEAR;\\n\\t\\t\\t\\tvalue.mipmaps = false;\\n\\t\\t\\t}\\n\\t\\t\\tthis._prefilteredCubemaps = [];\\n\\t\\t\\tif (this._internalEnvAtlas) {\\n\\t\\t\\t\\tthis._internalEnvAtlas.destroy();\\n\\t\\t\\t\\tthis._internalEnvAtlas = null;\\n\\t\\t\\t}\\n\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t}\\n\\t}\\n\\tget envAtlas() {\\n\\t\\treturn this._envAtlas;\\n\\t}\\n\\tset layers(layers) {\\n\\t\\tconst prev = this._layers;\\n\\t\\tthis._layers = layers;\\n\\t\\tthis.fire(\\\"set:layers\\\", prev, layers);\\n\\t}\\n\\tget layers() {\\n\\t\\treturn this._layers;\\n\\t}\\n\\tget sky() {\\n\\t\\treturn this._sky;\\n\\t}\\n\\tget lighting() {\\n\\t\\treturn this._lightingParams;\\n\\t}\\n\\tget gsplat() {\\n\\t\\treturn this._gsplatParams;\\n\\t}\\n\\tget fog() {\\n\\t\\treturn this._fogParams;\\n\\t}\\n\\tset lightmapFilterRange(value) {\\n\\t\\tthis._lightmapFilterRange = Math.max(value, 1e-3);\\n\\t}\\n\\tget lightmapFilterRange() {\\n\\t\\treturn this._lightmapFilterRange;\\n\\t}\\n\\tset lightmapFilterSmoothness(value) {\\n\\t\\tthis._lightmapFilterSmoothness = Math.max(value, 1e-3);\\n\\t}\\n\\tget lightmapFilterSmoothness() {\\n\\t\\treturn this._lightmapFilterSmoothness;\\n\\t}\\n\\tset prefilteredCubemaps(value) {\\n\\t\\tvalue = value || [];\\n\\t\\tconst cubemaps = this._prefilteredCubemaps;\\n\\t\\tconst changed = cubemaps.length !== value.length || cubemaps.some((c, i) => c !== value[i]);\\n\\t\\tif (changed) {\\n\\t\\t\\tconst complete = value.length === 6 && value.every((c) => !!c);\\n\\t\\t\\tif (complete) {\\n\\t\\t\\t\\tthis._internalEnvAtlas = EnvLighting.generatePrefilteredAtlas(value, {\\n\\t\\t\\t\\t\\ttarget: this._internalEnvAtlas\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis._envAtlas = this._internalEnvAtlas;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (this._internalEnvAtlas) {\\n\\t\\t\\t\\t\\tthis._internalEnvAtlas.destroy();\\n\\t\\t\\t\\t\\tthis._internalEnvAtlas = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._envAtlas = null;\\n\\t\\t\\t}\\n\\t\\t\\tthis._prefilteredCubemaps = value.slice();\\n\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t}\\n\\t}\\n\\tget prefilteredCubemaps() {\\n\\t\\treturn this._prefilteredCubemaps;\\n\\t}\\n\\tset skybox(value) {\\n\\t\\tif (value !== this._skyboxCubeMap) {\\n\\t\\t\\tthis._skyboxCubeMap = value;\\n\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t}\\n\\t}\\n\\tget skybox() {\\n\\t\\treturn this._skyboxCubeMap;\\n\\t}\\n\\tset skyboxIntensity(value) {\\n\\t\\tif (value !== this._skyboxIntensity) {\\n\\t\\t\\tthis._skyboxIntensity = value;\\n\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t}\\n\\t}\\n\\tget skyboxIntensity() {\\n\\t\\treturn this._skyboxIntensity;\\n\\t}\\n\\tset skyboxLuminance(value) {\\n\\t\\tif (value !== this._skyboxLuminance) {\\n\\t\\t\\tthis._skyboxLuminance = value;\\n\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t}\\n\\t}\\n\\tget skyboxLuminance() {\\n\\t\\treturn this._skyboxLuminance;\\n\\t}\\n\\tset skyboxMip(value) {\\n\\t\\tif (value !== this._skyboxMip) {\\n\\t\\t\\tthis._skyboxMip = value;\\n\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t}\\n\\t}\\n\\tget skyboxMip() {\\n\\t\\treturn this._skyboxMip;\\n\\t}\\n\\tset skyboxHighlightMultiplier(value) {\\n\\t\\tif (value !== this._skyboxHighlightMultiplier) {\\n\\t\\t\\tthis._skyboxHighlightMultiplier = value;\\n\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t}\\n\\t}\\n\\tget skyboxHighlightMultiplier() {\\n\\t\\treturn this._skyboxHighlightMultiplier;\\n\\t}\\n\\tset skyboxRotation(value) {\\n\\t\\tif (!this._skyboxRotation.equals(value)) {\\n\\t\\t\\tconst isIdentity = value.equals(Quat.IDENTITY);\\n\\t\\t\\tthis._skyboxRotation.copy(value);\\n\\t\\t\\tif (isIdentity) {\\n\\t\\t\\t\\tthis._skyboxRotationMat3.setIdentity();\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._skyboxRotationMat4.setTRS(Vec3.ZERO, value, Vec3.ONE);\\n\\t\\t\\t\\tthis._skyboxRotationMat3.invertMat4(this._skyboxRotationMat4);\\n\\t\\t\\t}\\n\\t\\t\\tif (!this._skyboxRotationShaderInclude && !isIdentity) {\\n\\t\\t\\t\\tthis._skyboxRotationShaderInclude = true;\\n\\t\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget skyboxRotation() {\\n\\t\\treturn this._skyboxRotation;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._sky.destroy();\\n\\t\\tthis.root = null;\\n\\t\\tthis.off();\\n\\t}\\n\\tdrawLine(start, end, color = Color.WHITE, depthTest = true, layer = this.defaultDrawLayer) {\\n\\t\\tconst batch = this.immediate.getBatch(layer, depthTest);\\n\\t\\tbatch.addLines([start, end], [color, color]);\\n\\t}\\n\\tdrawLines(positions, colors, depthTest = true, layer = this.defaultDrawLayer) {\\n\\t\\tconst batch = this.immediate.getBatch(layer, depthTest);\\n\\t\\tbatch.addLines(positions, colors);\\n\\t}\\n\\tdrawLineArrays(positions, colors, depthTest = true, layer = this.defaultDrawLayer) {\\n\\t\\tconst batch = this.immediate.getBatch(layer, depthTest);\\n\\t\\tbatch.addLinesArrays(positions, colors);\\n\\t}\\n\\tapplySettings(settings) {\\n\\t\\tconst physics = settings.physics;\\n\\t\\tconst render = settings.render;\\n\\t\\tthis._gravity.set(physics.gravity[0], physics.gravity[1], physics.gravity[2]);\\n\\t\\tthis.ambientLight.set(render.global_ambient[0], render.global_ambient[1], render.global_ambient[2]);\\n\\t\\tthis.ambientLuminance = render.ambientLuminance;\\n\\t\\tthis.fog.type = render.fog;\\n\\t\\tthis.fog.color.set(render.fog_color[0], render.fog_color[1], render.fog_color[2]);\\n\\t\\tthis.fog.start = render.fog_start;\\n\\t\\tthis.fog.end = render.fog_end;\\n\\t\\tthis.fog.density = render.fog_density;\\n\\t\\tthis.lightmapSizeMultiplier = render.lightmapSizeMultiplier;\\n\\t\\tthis.lightmapMaxResolution = render.lightmapMaxResolution;\\n\\t\\tthis.lightmapMode = render.lightmapMode;\\n\\t\\tthis.exposure = render.exposure;\\n\\t\\tthis._skyboxIntensity = render.skyboxIntensity ?? 1;\\n\\t\\tthis._skyboxLuminance = render.skyboxLuminance ?? 2e4;\\n\\t\\tthis._skyboxMip = render.skyboxMip ?? 0;\\n\\t\\tif (render.skyboxRotation) {\\n\\t\\t\\tthis.skyboxRotation = new Quat().setFromEulerAngles(render.skyboxRotation[0], render.skyboxRotation[1], render.skyboxRotation[2]);\\n\\t\\t}\\n\\t\\tthis.sky.applySettings(render);\\n\\t\\tthis.clusteredLightingEnabled = render.clusteredLightingEnabled ?? false;\\n\\t\\tthis.lighting.applySettings(render);\\n\\t\\t[\\n\\t\\t\\t\\\"lightmapFilterEnabled\\\",\\n\\t\\t\\t\\\"lightmapFilterRange\\\",\\n\\t\\t\\t\\\"lightmapFilterSmoothness\\\",\\n\\t\\t\\t\\\"ambientBake\\\",\\n\\t\\t\\t\\\"ambientBakeNumSamples\\\",\\n\\t\\t\\t\\\"ambientBakeSpherePart\\\",\\n\\t\\t\\t\\\"ambientBakeOcclusionBrightness\\\",\\n\\t\\t\\t\\\"ambientBakeOcclusionContrast\\\"\\n\\t\\t].forEach((setting) => {\\n\\t\\t\\tif (render.hasOwnProperty(setting)) {\\n\\t\\t\\t\\tthis[setting] = render[setting];\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tthis._resetSkyMesh();\\n\\t}\\n\\t// get the actual texture to use for skybox rendering\\n\\t_getSkyboxTex() {\\n\\t\\tconst cubemaps = this._prefilteredCubemaps;\\n\\t\\tif (this._skyboxMip) {\\n\\t\\t\\tconst skyboxMapping = [\\n\\t\\t\\t\\t0,\\n\\t\\t\\t\\t1,\\n\\t\\t\\t\\t/* 2 */\\n\\t\\t\\t\\t3,\\n\\t\\t\\t\\t4,\\n\\t\\t\\t\\t5,\\n\\t\\t\\t\\t6\\n\\t\\t\\t];\\n\\t\\t\\treturn cubemaps[skyboxMapping[this._skyboxMip]] || this._envAtlas || cubemaps[0] || this._skyboxCubeMap;\\n\\t\\t}\\n\\t\\treturn this._skyboxCubeMap || cubemaps[0] || this._envAtlas;\\n\\t}\\n\\t_updateSkyMesh() {\\n\\t\\tif (!this.sky.skyMesh) {\\n\\t\\t\\tthis.sky.updateSkyMesh();\\n\\t\\t}\\n\\t\\tthis.sky.update();\\n\\t}\\n\\t_resetSkyMesh() {\\n\\t\\tthis.sky.resetSkyMesh();\\n\\t\\tthis.updateShaders = true;\\n\\t}\\n\\tsetSkybox(cubemaps) {\\n\\t\\tif (!cubemaps) {\\n\\t\\t\\tthis.skybox = null;\\n\\t\\t\\tthis.envAtlas = null;\\n\\t\\t} else {\\n\\t\\t\\tthis.skybox = cubemaps[0] || null;\\n\\t\\t\\tif (cubemaps[1] && !cubemaps[1].cubemap) {\\n\\t\\t\\t\\tthis.envAtlas = cubemaps[1];\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.prefilteredCubemaps = cubemaps.slice(1);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget lightmapPixelFormat() {\\n\\t\\treturn this.lightmapHDR && this.device.getRenderableHdrFormat() || PIXELFORMAT_RGBA8;\\n\\t}\\n}\\n\\nclass Skin {\\n\\tconstructor(graphicsDevice, ibp, boneNames) {\\n\\t\\tthis.device = graphicsDevice;\\n\\t\\tthis.inverseBindPose = ibp;\\n\\t\\tthis.boneNames = boneNames;\\n\\t}\\n}\\n\\nconst prefixSumSource = `\\n@group(0) @binding(0) var<storage, read_write> items: array<u32>;\\n@group(0) @binding(1) var<storage, read_write> blockSums: array<u32>;\\nstruct PrefixSumUniforms {\\n\\telementCount: u32\\n};\\n@group(0) @binding(2) var<uniform> uniforms: PrefixSumUniforms;\\nconst WORKGROUP_SIZE_X: u32 = {WORKGROUP_SIZE_X}u;\\nconst WORKGROUP_SIZE_Y: u32 = {WORKGROUP_SIZE_Y}u;\\nconst THREADS_PER_WORKGROUP: u32 = {THREADS_PER_WORKGROUP}u;\\nconst ITEMS_PER_WORKGROUP: u32 = {ITEMS_PER_WORKGROUP}u;\\nvar<workgroup> temp: array<u32, ITEMS_PER_WORKGROUP * 2>;\\n@compute @workgroup_size(WORKGROUP_SIZE_X, WORKGROUP_SIZE_Y, 1)\\nfn reduce_downsweep(\\n\\t@builtin(workgroup_id) w_id: vec3<u32>,\\n\\t@builtin(num_workgroups) w_dim: vec3<u32>,\\n\\t@builtin(local_invocation_index) TID: u32,\\n) {\\n\\tlet WORKGROUP_ID = w_id.x + w_id.y * w_dim.x;\\n\\tlet WID = WORKGROUP_ID * THREADS_PER_WORKGROUP;\\n\\tlet GID = WID + TID;\\n\\t\\n\\tlet ELM_TID = TID * 2;\\n\\tlet ELM_GID = GID * 2;\\n\\t\\n\\ttemp[ELM_TID] = select(items[ELM_GID], 0u, ELM_GID >= uniforms.elementCount);\\n\\ttemp[ELM_TID + 1u] = select(items[ELM_GID + 1u], 0u, ELM_GID + 1u >= uniforms.elementCount);\\n\\tvar offset: u32 = 1u;\\n\\tfor (var d: u32 = ITEMS_PER_WORKGROUP >> 1u; d > 0u; d >>= 1u) {\\n\\t\\tworkgroupBarrier();\\n\\t\\tif (TID < d) {\\n\\t\\t\\tvar ai: u32 = offset * (ELM_TID + 1u) - 1u;\\n\\t\\t\\tvar bi: u32 = offset * (ELM_TID + 2u) - 1u;\\n\\t\\t\\ttemp[bi] += temp[ai];\\n\\t\\t}\\n\\t\\toffset *= 2u;\\n\\t}\\n\\tif (TID == 0u) {\\n\\t\\tlet last_offset = ITEMS_PER_WORKGROUP - 1u;\\n\\t\\tblockSums[WORKGROUP_ID] = temp[last_offset];\\n\\t\\ttemp[last_offset] = 0u;\\n\\t}\\n\\tfor (var d: u32 = 1u; d < ITEMS_PER_WORKGROUP; d *= 2u) {\\n\\t\\toffset >>= 1u;\\n\\t\\tworkgroupBarrier();\\n\\t\\tif (TID < d) {\\n\\t\\t\\tvar ai: u32 = offset * (ELM_TID + 1u) - 1u;\\n\\t\\t\\tvar bi: u32 = offset * (ELM_TID + 2u) - 1u;\\n\\t\\t\\tlet t: u32 = temp[ai];\\n\\t\\t\\ttemp[ai] = temp[bi];\\n\\t\\t\\ttemp[bi] += t;\\n\\t\\t}\\n\\t}\\n\\tworkgroupBarrier();\\n\\tif (ELM_GID < uniforms.elementCount) {\\n\\t\\titems[ELM_GID] = temp[ELM_TID];\\n\\t}\\n\\tif (ELM_GID + 1u < uniforms.elementCount) {\\n\\t\\titems[ELM_GID + 1u] = temp[ELM_TID + 1u];\\n\\t}\\n}\\n@compute @workgroup_size(WORKGROUP_SIZE_X, WORKGROUP_SIZE_Y, 1)\\nfn add_block_sums(\\n\\t@builtin(workgroup_id) w_id: vec3<u32>,\\n\\t@builtin(num_workgroups) w_dim: vec3<u32>,\\n\\t@builtin(local_invocation_index) TID: u32,\\n) {\\n\\tlet WORKGROUP_ID = w_id.x + w_id.y * w_dim.x;\\n\\tlet WID = WORKGROUP_ID * THREADS_PER_WORKGROUP;\\n\\tlet GID = WID + TID;\\n\\tlet ELM_ID = GID * 2u;\\n\\tif (ELM_ID >= uniforms.elementCount) {\\n\\t\\treturn;\\n\\t}\\n\\tlet blockSum = blockSums[WORKGROUP_ID];\\n\\titems[ELM_ID] += blockSum;\\n\\tif (ELM_ID + 1u >= uniforms.elementCount) {\\n\\t\\treturn;\\n\\t}\\n\\titems[ELM_ID + 1u] += blockSum;\\n}\\n`;\\n\\nconst WORKGROUP_SIZE_X$1 = 16;\\nconst WORKGROUP_SIZE_Y$1 = 16;\\nconst THREADS_PER_WORKGROUP$1 = WORKGROUP_SIZE_X$1 * WORKGROUP_SIZE_Y$1;\\nconst ITEMS_PER_WORKGROUP = 2 * THREADS_PER_WORKGROUP$1;\\nclass PrefixSumKernel {\\n\\tdevice;\\n\\tpasses = [];\\n\\t_uniformBufferFormat = null;\\n\\t_bindGroupFormat = null;\\n\\t_scanShader = null;\\n\\t_addBlockShader = null;\\n\\tconstructor(device) {\\n\\t\\tthis.device = device;\\n\\t\\tthis._createFormatsAndShaders();\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.destroyPasses();\\n\\t\\tthis._scanShader?.destroy();\\n\\t\\tthis._addBlockShader?.destroy();\\n\\t\\tthis._bindGroupFormat?.destroy();\\n\\t\\tthis._scanShader = null;\\n\\t\\tthis._addBlockShader = null;\\n\\t\\tthis._bindGroupFormat = null;\\n\\t\\tthis._uniformBufferFormat = null;\\n\\t}\\n\\t_createFormatsAndShaders() {\\n\\t\\tthis._uniformBufferFormat = new UniformBufferFormat(this.device, [\\n\\t\\t\\tnew UniformFormat(\\\"elementCount\\\", UNIFORMTYPE_UINT)\\n\\t\\t]);\\n\\t\\tthis._bindGroupFormat = new BindGroupFormat(this.device, [\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"items\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"blockSums\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE)\\n\\t\\t]);\\n\\t\\tthis._scanShader = this._createShader(\\\"PrefixSumScan\\\", \\\"reduce_downsweep\\\");\\n\\t\\tthis._addBlockShader = this._createShader(\\\"PrefixSumAddBlock\\\", \\\"add_block_sums\\\");\\n\\t}\\n\\tcreatePassesRecursive(dataBuffer, count) {\\n\\t\\tconst workgroupCount = Math.ceil(count / ITEMS_PER_WORKGROUP);\\n\\t\\tconst { x: dispatchX, y: dispatchY } = this.findOptimalDispatchSize(workgroupCount);\\n\\t\\tconst blockSumBuffer = new StorageBuffer(this.device, workgroupCount * 4);\\n\\t\\tconst scanCompute = new Compute(this.device, this._scanShader, \\\"PrefixSumScan\\\");\\n\\t\\tscanCompute.setParameter(\\\"items\\\", dataBuffer);\\n\\t\\tscanCompute.setParameter(\\\"blockSums\\\", blockSumBuffer);\\n\\t\\tconst pass = {\\n\\t\\t\\tscanCompute,\\n\\t\\t\\taddBlockCompute: null,\\n\\t\\t\\tblockSumBuffer,\\n\\t\\t\\tdispatchX,\\n\\t\\t\\tdispatchY,\\n\\t\\t\\tcount,\\n\\t\\t\\tallocatedCount: count\\n\\t\\t};\\n\\t\\tthis.passes.push(pass);\\n\\t\\tif (workgroupCount > 1) {\\n\\t\\t\\tthis.createPassesRecursive(blockSumBuffer, workgroupCount);\\n\\t\\t\\tconst addBlockCompute = new Compute(this.device, this._addBlockShader, \\\"PrefixSumAddBlock\\\");\\n\\t\\t\\taddBlockCompute.setParameter(\\\"items\\\", dataBuffer);\\n\\t\\t\\taddBlockCompute.setParameter(\\\"blockSums\\\", blockSumBuffer);\\n\\t\\t\\tpass.addBlockCompute = addBlockCompute;\\n\\t\\t}\\n\\t}\\n\\t_createShader(name, entryPoint) {\\n\\t\\tconst cdefines = /* @__PURE__ */ new Map();\\n\\t\\tcdefines.set(\\\"{WORKGROUP_SIZE_X}\\\", WORKGROUP_SIZE_X$1);\\n\\t\\tcdefines.set(\\\"{WORKGROUP_SIZE_Y}\\\", WORKGROUP_SIZE_Y$1);\\n\\t\\tcdefines.set(\\\"{THREADS_PER_WORKGROUP}\\\", THREADS_PER_WORKGROUP$1);\\n\\t\\tcdefines.set(\\\"{ITEMS_PER_WORKGROUP}\\\", ITEMS_PER_WORKGROUP);\\n\\t\\treturn new Shader(this.device, {\\n\\t\\t\\tname,\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tcshader: prefixSumSource,\\n\\t\\t\\tcdefines,\\n\\t\\t\\tcomputeEntryPoint: entryPoint,\\n\\t\\t\\tcomputeBindGroupFormat: this._bindGroupFormat,\\n\\t\\t\\tcomputeUniformBufferFormats: { uniforms: this._uniformBufferFormat }\\n\\t\\t});\\n\\t}\\n\\tfindOptimalDispatchSize(workgroupCount) {\\n\\t\\tconst maxDimension = this.device.limits.maxComputeWorkgroupsPerDimension || 65535;\\n\\t\\tif (workgroupCount <= maxDimension) {\\n\\t\\t\\treturn { x: workgroupCount, y: 1 };\\n\\t\\t}\\n\\t\\tconst x = Math.floor(Math.sqrt(workgroupCount));\\n\\t\\tconst y = Math.ceil(workgroupCount / x);\\n\\t\\treturn { x, y };\\n\\t}\\n\\tresize(dataBuffer, count) {\\n\\t\\tconst requiredPasses = this._countPassesNeeded(count);\\n\\t\\tconst currentPasses = this.passes.length;\\n\\t\\tif (requiredPasses > currentPasses) {\\n\\t\\t\\tthis.destroyPasses();\\n\\t\\t\\tthis.createPassesRecursive(dataBuffer, count);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tlet levelCount = count;\\n\\t\\tfor (let i = 0; i < this.passes.length; i++) {\\n\\t\\t\\tconst workgroupCount = Math.ceil(levelCount / ITEMS_PER_WORKGROUP);\\n\\t\\t\\tconst { x: dispatchX, y: dispatchY } = this.findOptimalDispatchSize(workgroupCount);\\n\\t\\t\\tthis.passes[i].count = levelCount;\\n\\t\\t\\tthis.passes[i].dispatchX = dispatchX;\\n\\t\\t\\tthis.passes[i].dispatchY = dispatchY;\\n\\t\\t\\tlevelCount = workgroupCount;\\n\\t\\t\\tif (workgroupCount <= 1) {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tdestroyPasses() {\\n\\t\\tfor (const pass of this.passes) {\\n\\t\\t\\tpass.blockSumBuffer?.destroy();\\n\\t\\t}\\n\\t\\tthis.passes.length = 0;\\n\\t}\\n\\t_countPassesNeeded(count) {\\n\\t\\tlet passes = 0;\\n\\t\\tlet levelCount = count;\\n\\t\\twhile (levelCount > 0) {\\n\\t\\t\\tpasses++;\\n\\t\\t\\tconst workgroupCount = Math.ceil(levelCount / ITEMS_PER_WORKGROUP);\\n\\t\\t\\tif (workgroupCount <= 1) break;\\n\\t\\t\\tlevelCount = workgroupCount;\\n\\t\\t}\\n\\t\\treturn passes;\\n\\t}\\n\\tdispatch(device) {\\n\\t\\tfor (let i = 0; i < this.passes.length; i++) {\\n\\t\\t\\tconst pass = this.passes[i];\\n\\t\\t\\tpass.scanCompute.setParameter(\\\"elementCount\\\", pass.count);\\n\\t\\t\\tpass.scanCompute.setupDispatch(pass.dispatchX, pass.dispatchY, 1);\\n\\t\\t\\tdevice.computeDispatch([pass.scanCompute], \\\"PrefixSumScan\\\");\\n\\t\\t}\\n\\t\\tfor (let i = this.passes.length - 1; i >= 0; i--) {\\n\\t\\t\\tconst pass = this.passes[i];\\n\\t\\t\\tif (pass.addBlockCompute) {\\n\\t\\t\\t\\tpass.addBlockCompute.setParameter(\\\"elementCount\\\", pass.count);\\n\\t\\t\\t\\tpass.addBlockCompute.setupDispatch(pass.dispatchX, pass.dispatchY, 1);\\n\\t\\t\\t\\tdevice.computeDispatch([pass.addBlockCompute], \\\"PrefixSumAddBlock\\\");\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\n\\nconst radixSort4bitSource = `\\n@group(0) @binding(0) var<storage, read> input: array<u32>;\\n@group(0) @binding(1) var<storage, read_write> block_sums: array<u32>;\\nstruct RadixSortUniforms {\\n\\tworkgroupCount: u32,\\n\\telementCount: u32\\n};\\n@group(0) @binding(2) var<uniform> uniforms: RadixSortUniforms;\\n#ifdef USE_INDIRECT_SORT\\n\\t@group(0) @binding(3) var<storage, read> sortElementCount: array<u32>;\\n#endif\\nconst THREADS_PER_WORKGROUP: u32 = {THREADS_PER_WORKGROUP}u;\\nconst WORKGROUP_SIZE_X: u32 = {WORKGROUP_SIZE_X}u;\\nconst WORKGROUP_SIZE_Y: u32 = {WORKGROUP_SIZE_Y}u;\\nconst CURRENT_BIT: u32 = {CURRENT_BIT}u;\\nconst ELEMENTS_PER_THREAD: u32 = {ELEMENTS_PER_THREAD}u;\\nconst ELEMENTS_PER_WORKGROUP: u32 = THREADS_PER_WORKGROUP * ELEMENTS_PER_THREAD;\\nvar<workgroup> histogram: array<atomic<u32>, 16>;\\n@compute @workgroup_size(WORKGROUP_SIZE_X, WORKGROUP_SIZE_Y, 1)\\nfn main(\\n\\t@builtin(workgroup_id) w_id: vec3<u32>,\\n\\t@builtin(num_workgroups) w_dim: vec3<u32>,\\n\\t@builtin(local_invocation_index) TID: u32,\\n) {\\n\\tlet WORKGROUP_ID = w_id.x + w_id.y * w_dim.x;\\n\\tlet WID = WORKGROUP_ID * ELEMENTS_PER_WORKGROUP;\\n\\tif (TID < 16u) {\\n\\t\\tatomicStore(&histogram[TID], 0u);\\n\\t}\\n\\tworkgroupBarrier();\\n\\t#ifdef USE_INDIRECT_SORT\\n\\t\\tlet elementCount = sortElementCount[0];\\n\\t#else\\n\\t\\tlet elementCount = uniforms.elementCount;\\n\\t#endif\\n\\tfor (var r = 0u; r < ELEMENTS_PER_THREAD; r++) {\\n\\t\\tlet GID = WID + r * THREADS_PER_WORKGROUP + TID;\\n\\t\\tlet is_valid = GID < elementCount && WORKGROUP_ID < uniforms.workgroupCount;\\n\\t\\tif (is_valid) {\\n\\t\\t\\tlet elm = input[GID];\\n\\t\\t\\tlet digit = (elm >> CURRENT_BIT) & 0xFu;\\n\\t\\t\\tatomicAdd(&histogram[digit], 1u);\\n\\t\\t}\\n\\t}\\n\\tworkgroupBarrier();\\n\\tif (TID < 16u && WORKGROUP_ID < uniforms.workgroupCount) {\\n\\t\\tblock_sums[TID * uniforms.workgroupCount + WORKGROUP_ID] = atomicLoad(&histogram[TID]);\\n\\t}\\n}\\n`;\\n\\nconst radixSortReorderSource = `\\n@group(0) @binding(0) var<storage, read> inputKeys: array<u32>;\\n@group(0) @binding(1) var<storage, read_write> outputKeys: array<u32>;\\n@group(0) @binding(2) var<storage, read> prefix_block_sum: array<u32>;\\n@group(0) @binding(3) var<storage, read> inputValues: array<u32>;\\n@group(0) @binding(4) var<storage, read_write> outputValues: array<u32>;\\nstruct RadixSortUniforms {\\n\\tworkgroupCount: u32,\\n\\telementCount: u32\\n};\\n@group(0) @binding(5) var<uniform> uniforms: RadixSortUniforms;\\n#ifdef USE_INDIRECT_SORT\\n\\t@group(0) @binding(6) var<storage, read> sortElementCount: array<u32>;\\n#endif\\nconst THREADS_PER_WORKGROUP: u32 = {THREADS_PER_WORKGROUP}u;\\nconst WORKGROUP_SIZE_X: u32 = {WORKGROUP_SIZE_X}u;\\nconst WORKGROUP_SIZE_Y: u32 = {WORKGROUP_SIZE_Y}u;\\nconst CURRENT_BIT: u32 = {CURRENT_BIT}u;\\nconst IS_FIRST_PASS: u32 = {IS_FIRST_PASS}u;\\nconst IS_LAST_PASS: u32 = {IS_LAST_PASS}u;\\nconst ELEMENTS_PER_THREAD: u32 = {ELEMENTS_PER_THREAD}u;\\nconst ELEMENTS_PER_WORKGROUP: u32 = THREADS_PER_WORKGROUP * ELEMENTS_PER_THREAD;\\nvar<workgroup> digit_masks: array<atomic<u32>, 128>;\\nvar<workgroup> digit_offsets: array<u32, 16>;\\n@compute @workgroup_size(WORKGROUP_SIZE_X, WORKGROUP_SIZE_Y, 1)\\nfn main(\\n\\t@builtin(workgroup_id) w_id: vec3<u32>,\\n\\t@builtin(num_workgroups) w_dim: vec3<u32>,\\n\\t@builtin(local_invocation_index) TID: u32,\\n) {\\n\\tlet WORKGROUP_ID = w_id.x + w_id.y * w_dim.x;\\n\\tlet WID = WORKGROUP_ID * ELEMENTS_PER_WORKGROUP;\\n\\tlet word_idx = TID >> 5u;\\n\\tlet bit_idx = TID & 31u;\\n\\tif (TID < 16u) {\\n\\t\\tdigit_offsets[TID] = 0u;\\n\\t}\\n\\tif (TID < 128u) {\\n\\t\\tatomicStore(&digit_masks[TID], 0u);\\n\\t}\\n\\tworkgroupBarrier();\\n\\t#ifdef USE_INDIRECT_SORT\\n\\t\\tlet elementCount = sortElementCount[0];\\n\\t#else\\n\\t\\tlet elementCount = uniforms.elementCount;\\n\\t#endif\\n\\tfor (var round = 0u; round < ELEMENTS_PER_THREAD; round++) {\\n\\t\\tlet GID = WID + round * THREADS_PER_WORKGROUP + TID;\\n\\t\\tlet is_valid = GID < elementCount;\\n\\t\\tlet k = select(0u, inputKeys[GID], is_valid);\\n\\t\\tlet digit = select(16u, (k >> CURRENT_BIT) & 0xFu, is_valid);\\n\\t\\tlet v = select(0u, select(inputValues[GID], GID, IS_FIRST_PASS == 1u), is_valid);\\n\\t\\tif (is_valid) {\\n\\t\\t\\tatomicOr(&digit_masks[digit * 8u + word_idx], 1u << bit_idx);\\n\\t\\t}\\n\\t\\tworkgroupBarrier();\\n\\t\\tif (is_valid) {\\n\\t\\t\\tlet base = digit * 8u;\\n\\t\\t\\tvar local_prefix = digit_offsets[digit];\\n\\t\\t\\tfor (var w = 0u; w < word_idx; w++) {\\n\\t\\t\\t\\tlocal_prefix += countOneBits(atomicLoad(&digit_masks[base + w]));\\n\\t\\t\\t}\\n\\t\\t\\tlocal_prefix += countOneBits(atomicLoad(&digit_masks[base + word_idx]) & ((1u << bit_idx) - 1u));\\n\\t\\t\\tlet pid = digit * uniforms.workgroupCount + WORKGROUP_ID;\\n\\t\\t\\tlet sorted_position = prefix_block_sum[pid] + local_prefix;\\n\\t\\t\\tif (IS_LAST_PASS == 0u) {\\n\\t\\t\\t\\toutputKeys[sorted_position] = k;\\n\\t\\t\\t}\\n\\t\\t\\toutputValues[sorted_position] = v;\\n\\t\\t}\\n\\t\\tif (round < ELEMENTS_PER_THREAD - 1u) {\\n\\t\\t\\tworkgroupBarrier();\\n\\t\\t\\tif (TID < 16u) {\\n\\t\\t\\t\\tvar count = 0u;\\n\\t\\t\\t\\tfor (var w = 0u; w < 8u; w++) {\\n\\t\\t\\t\\t\\tlet idx = TID * 8u + w;\\n\\t\\t\\t\\t\\tcount += countOneBits(atomicLoad(&digit_masks[idx]));\\n\\t\\t\\t\\t\\tatomicStore(&digit_masks[idx], 0u);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdigit_offsets[TID] += count;\\n\\t\\t\\t}\\n\\t\\t\\tworkgroupBarrier();\\n\\t\\t}\\n\\t}\\n}\\n`;\\n\\nclass ComputeRadixSortBase {\\n\\tdevice;\\n\\t_indirect = false;\\n\\tconstructor(device, indirect = false) {\\n\\t\\tthis.device = device;\\n\\t\\tthis._indirect = indirect;\\n\\t}\\n\\tcapacity = 0;\\n\\t_elementCount = 0;\\n\\t_numBits = 0;\\n\\t_hasInitialValues = false;\\n\\t_skipLastPassKeyWrite = false;\\n\\t_destructiveKeys = false;\\n\\t_keys0 = null;\\n\\t_keys1 = null;\\n\\t_values0 = null;\\n\\t_values1 = null;\\n\\t_indirectInfo = new Uint32Array(4);\\n\\tget sortedIndices() {\\n\\t\\tif (!this._values0) return null;\\n\\t\\tconst numPasses = this._numBits / this.radixBits;\\n\\t\\treturn numPasses % 2 === 1 ? this._values1 : this._values0;\\n\\t}\\n\\tget sortedKeys() {\\n\\t\\tif (!this._keys0) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tconst radix = this.radixBits;\\n\\t\\tconst numPasses = this._numBits / radix;\\n\\t\\treturn numPasses % 2 === 0 ? this._keys1 : this._keys0;\\n\\t}\\n\\tget radixBits() {\\n\\t\\treturn 0;\\n\\t}\\n\\tsort(keysBuffer, elementCount, numBits, initialValues, skipLastPassKeyWrite, destructiveKeys) {\\n\\t\\treturn null;\\n\\t}\\n\\tsortIndirect(keysBuffer, maxElementCount, numBits, sortSlotBase, sortElementCountBuffer, initialValues, skipLastPassKeyWrite, destructiveKeys) {\\n\\t\\treturn null;\\n\\t}\\n\\tprepareIndirect() {\\n\\t\\treturn this._indirectInfo;\\n\\t}\\n\\t_allocatePingPongElementBuffers(effectiveCount) {\\n\\t\\tconst elementSize = effectiveCount * 4;\\n\\t\\tconst usage = BUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST;\\n\\t\\tconst device = this.device;\\n\\t\\tthis._keys0 = new StorageBuffer(device, elementSize, usage);\\n\\t\\tif (!this._destructiveKeys) {\\n\\t\\t\\tthis._keys1 = new StorageBuffer(device, elementSize, usage);\\n\\t\\t}\\n\\t\\tthis._values0 = new StorageBuffer(device, elementSize, usage);\\n\\t\\tthis._values1 = new StorageBuffer(device, elementSize, usage);\\n\\t}\\n\\t_destroyPingPongBuffers() {\\n\\t\\tthis._keys0?.destroy();\\n\\t\\tif (!this._destructiveKeys) this._keys1?.destroy();\\n\\t\\tthis._values0?.destroy();\\n\\t\\tthis._values1?.destroy();\\n\\t\\tthis._keys0 = null;\\n\\t\\tthis._keys1 = null;\\n\\t\\tthis._values0 = null;\\n\\t\\tthis._values1 = null;\\n\\t}\\n\\tdestroy() {\\n\\t}\\n}\\n\\nconst WORKGROUP_SIZE_X = 16;\\nconst WORKGROUP_SIZE_Y = 16;\\nconst THREADS_PER_WORKGROUP = WORKGROUP_SIZE_X * WORKGROUP_SIZE_Y;\\nconst ELEMENTS_PER_THREAD = 8;\\nconst ELEMENTS_PER_WORKGROUP = THREADS_PER_WORKGROUP * ELEMENTS_PER_THREAD;\\nconst BITS_PER_PASS = 4;\\nconst BUCKET_COUNT = 16;\\nclass ComputeRadixSortMultipass extends ComputeRadixSortBase {\\n\\t_workgroupCount = 0;\\n\\t_allocatedWorkgroupCount = 0;\\n\\t_blockSums = null;\\n\\t_prefixSumKernel = null;\\n\\t_dispatchSize = new Vec2(1, 1);\\n\\t_histogramBindGroupFormat = null;\\n\\t_reorderBindGroupFormat = null;\\n\\t_uniformBufferFormat = null;\\n\\t_passes = [];\\n\\tconstructor(device, indirect = false) {\\n\\t\\tsuper(device, indirect);\\n\\t\\tconst info = this._indirectInfo;\\n\\t\\tinfo[0] = 1;\\n\\t\\tinfo[1] = ELEMENTS_PER_WORKGROUP;\\n\\t\\tthis._uniformBufferFormat = new UniformBufferFormat(device, [\\n\\t\\t\\tnew UniformFormat(\\\"workgroupCount\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"elementCount\\\", UNIFORMTYPE_UINT)\\n\\t\\t]);\\n\\t\\tconst histogramEntries = [\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"input\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"block_sums\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE)\\n\\t\\t];\\n\\t\\tconst reorderEntries = [\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"inputKeys\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"outputKeys\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"prefix_block_sum\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"inputValues\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"outputValues\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE)\\n\\t\\t];\\n\\t\\tif (indirect) {\\n\\t\\t\\thistogramEntries.push(new BindStorageBufferFormat(\\\"sortElementCount\\\", SHADERSTAGE_COMPUTE, true));\\n\\t\\t\\treorderEntries.push(new BindStorageBufferFormat(\\\"sortElementCount\\\", SHADERSTAGE_COMPUTE, true));\\n\\t\\t}\\n\\t\\tthis._histogramBindGroupFormat = new BindGroupFormat(device, histogramEntries);\\n\\t\\tthis._reorderBindGroupFormat = new BindGroupFormat(device, reorderEntries);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._destroyBuffers();\\n\\t\\tthis._destroyPasses();\\n\\t\\tthis._histogramBindGroupFormat?.destroy();\\n\\t\\tthis._reorderBindGroupFormat?.destroy();\\n\\t\\tthis._histogramBindGroupFormat = null;\\n\\t\\tthis._reorderBindGroupFormat = null;\\n\\t\\tthis._uniformBufferFormat = null;\\n\\t\\tsuper.destroy();\\n\\t}\\n\\t_destroyPasses() {\\n\\t\\tfor (const pass of this._passes) {\\n\\t\\t\\tpass.histogramCompute.shader?.destroy();\\n\\t\\t\\tpass.reorderCompute.shader?.destroy();\\n\\t\\t}\\n\\t\\tthis._passes.length = 0;\\n\\t\\tthis._numBits = 0;\\n\\t}\\n\\t_destroyBuffers() {\\n\\t\\tthis._destroyPingPongBuffers();\\n\\t\\tthis._blockSums?.destroy();\\n\\t\\tthis._prefixSumKernel?.destroy();\\n\\t\\tthis._blockSums = null;\\n\\t\\tthis._prefixSumKernel = null;\\n\\t\\tthis._workgroupCount = 0;\\n\\t\\tthis._allocatedWorkgroupCount = 0;\\n\\t}\\n\\tget radixBits() {\\n\\t\\treturn BITS_PER_PASS;\\n\\t}\\n\\t_createPasses(numBits, hasInitialValues, skipLastPassKeyWrite) {\\n\\t\\tthis._destroyPasses();\\n\\t\\tthis._numBits = numBits;\\n\\t\\tthis._hasInitialValues = hasInitialValues;\\n\\t\\tthis._skipLastPassKeyWrite = skipLastPassKeyWrite;\\n\\t\\tconst numPasses = numBits / BITS_PER_PASS;\\n\\t\\tconst suffix = this._indirect ? \\\"-Indirect\\\" : \\\"\\\";\\n\\t\\tfor (let pass = 0; pass < numPasses; pass++) {\\n\\t\\t\\tconst bitOffset = pass * BITS_PER_PASS;\\n\\t\\t\\tconst isFirstPass = pass === 0 && !hasInitialValues;\\n\\t\\t\\tconst isLastPass = skipLastPassKeyWrite && pass === numPasses - 1;\\n\\t\\t\\tconst histogramShader = this._createShader(\\n\\t\\t\\t\\t`RadixSort4bit-Histogram${suffix}-${bitOffset}`,\\n\\t\\t\\t\\tradixSort4bitSource,\\n\\t\\t\\t\\tbitOffset,\\n\\t\\t\\t\\tfalse,\\n\\t\\t\\t\\tfalse,\\n\\t\\t\\t\\tthis._histogramBindGroupFormat\\n\\t\\t\\t);\\n\\t\\t\\tconst reorderShader = this._createShader(\\n\\t\\t\\t\\t`RadixSort4bit-Reorder${suffix}-${bitOffset}`,\\n\\t\\t\\t\\tradixSortReorderSource,\\n\\t\\t\\t\\tbitOffset,\\n\\t\\t\\t\\tisFirstPass,\\n\\t\\t\\t\\tisLastPass,\\n\\t\\t\\t\\tthis._reorderBindGroupFormat\\n\\t\\t\\t);\\n\\t\\t\\tconst histogramCompute = new Compute(this.device, histogramShader, `RadixSort4bit-Histogram${suffix}-${bitOffset}`);\\n\\t\\t\\tconst reorderCompute = new Compute(this.device, reorderShader, `RadixSort4bit-Reorder${suffix}-${bitOffset}`);\\n\\t\\t\\tthis._passes.push({ histogramCompute, reorderCompute });\\n\\t\\t}\\n\\t}\\n\\t_allocateBuffers(elementCount, numBits, hasInitialValues, skipLastPassKeyWrite, forceRealloc = false) {\\n\\t\\tconst effectiveCount = Math.max(elementCount, this.capacity);\\n\\t\\tconst allocWorkgroupCount = Math.ceil(effectiveCount / ELEMENTS_PER_WORKGROUP);\\n\\t\\tconst currentWorkgroupCount = Math.max(1, Math.ceil(elementCount / ELEMENTS_PER_WORKGROUP));\\n\\t\\tconst buffersNeedRealloc = forceRealloc || allocWorkgroupCount !== this._allocatedWorkgroupCount || !this._keys0;\\n\\t\\tconst passesNeedRecreate = numBits !== this._numBits || hasInitialValues !== this._hasInitialValues || skipLastPassKeyWrite !== this._skipLastPassKeyWrite;\\n\\t\\tif (buffersNeedRealloc) {\\n\\t\\t\\tthis._destroyBuffers();\\n\\t\\t\\tthis._allocatedWorkgroupCount = allocWorkgroupCount;\\n\\t\\t\\tthis.capacity = effectiveCount;\\n\\t\\t\\tconst blockSumSize = BUCKET_COUNT * allocWorkgroupCount * 4;\\n\\t\\t\\tthis._allocatePingPongElementBuffers(effectiveCount);\\n\\t\\t\\tthis._blockSums = new StorageBuffer(this.device, blockSumSize, BUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST);\\n\\t\\t\\tthis._prefixSumKernel = new PrefixSumKernel(this.device);\\n\\t\\t}\\n\\t\\tthis._workgroupCount = currentWorkgroupCount;\\n\\t\\tCompute.calcDispatchSize(currentWorkgroupCount, this._dispatchSize, this.device.limits.maxComputeWorkgroupsPerDimension || 65535);\\n\\t\\tthis._prefixSumKernel.resize(this._blockSums, BUCKET_COUNT * currentWorkgroupCount);\\n\\t\\tif (passesNeedRecreate) {\\n\\t\\t\\tthis._createPasses(numBits, hasInitialValues, skipLastPassKeyWrite);\\n\\t\\t}\\n\\t}\\n\\t_createShader(name, source, currentBit, isFirstPass, isLastPass, bindGroupFormat) {\\n\\t\\tconst cdefines = /* @__PURE__ */ new Map();\\n\\t\\tcdefines.set(\\\"{WORKGROUP_SIZE_X}\\\", WORKGROUP_SIZE_X);\\n\\t\\tcdefines.set(\\\"{WORKGROUP_SIZE_Y}\\\", WORKGROUP_SIZE_Y);\\n\\t\\tcdefines.set(\\\"{THREADS_PER_WORKGROUP}\\\", THREADS_PER_WORKGROUP);\\n\\t\\tcdefines.set(\\\"{ELEMENTS_PER_THREAD}\\\", ELEMENTS_PER_THREAD);\\n\\t\\tcdefines.set(\\\"{CURRENT_BIT}\\\", currentBit);\\n\\t\\tcdefines.set(\\\"{IS_FIRST_PASS}\\\", isFirstPass ? 1 : 0);\\n\\t\\tcdefines.set(\\\"{IS_LAST_PASS}\\\", isLastPass ? 1 : 0);\\n\\t\\tif (this._indirect) {\\n\\t\\t\\tcdefines.set(\\\"USE_INDIRECT_SORT\\\", \\\"\\\");\\n\\t\\t}\\n\\t\\treturn new Shader(this.device, {\\n\\t\\t\\tname,\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tcshader: source,\\n\\t\\t\\tcdefines,\\n\\t\\t\\tcomputeBindGroupFormat: bindGroupFormat,\\n\\t\\t\\tcomputeUniformBufferFormats: { uniforms: this._uniformBufferFormat }\\n\\t\\t});\\n\\t}\\n\\tsort(keysBuffer, elementCount, numBits = 16, initialValues, skipLastPassKeyWrite = false, destructiveKeys = false) {\\n\\t\\treturn this._execute(keysBuffer, elementCount, numBits, -1, null, initialValues, skipLastPassKeyWrite, destructiveKeys);\\n\\t}\\n\\tsortIndirect(keysBuffer, maxElementCount, numBits, sortSlotBase, sortElementCountBuffer, initialValues, skipLastPassKeyWrite = false, destructiveKeys = false) {\\n\\t\\treturn this._execute(keysBuffer, maxElementCount, numBits, sortSlotBase, sortElementCountBuffer, initialValues, skipLastPassKeyWrite, destructiveKeys);\\n\\t}\\n\\t_execute(keysBuffer, elementCount, numBits, sortSlotBase, sortElementCountBuffer, initialValues, skipLastPassKeyWrite = false, destructiveKeys = false) {\\n\\t\\tthis._elementCount = elementCount;\\n\\t\\tconst hasInitialValues = !!initialValues;\\n\\t\\tconst prevDestructiveKeys = this._destructiveKeys;\\n\\t\\tthis._destructiveKeys = destructiveKeys;\\n\\t\\tthis._allocateBuffers(elementCount, numBits, hasInitialValues, skipLastPassKeyWrite, destructiveKeys !== prevDestructiveKeys);\\n\\t\\tif (destructiveKeys) {\\n\\t\\t\\tthis._keys1 = keysBuffer;\\n\\t\\t}\\n\\t\\tconst device = this.device;\\n\\t\\tconst numPasses = numBits / BITS_PER_PASS;\\n\\t\\tconst suffix = this._indirect ? \\\"-Indirect\\\" : \\\"\\\";\\n\\t\\tlet currentKeys = keysBuffer;\\n\\t\\tlet currentValues = initialValues ?? this._values0;\\n\\t\\tlet nextKeys = this._keys0;\\n\\t\\tlet nextValues = this._values1;\\n\\t\\tfor (let pass = 0; pass < numPasses; pass++) {\\n\\t\\t\\tconst { histogramCompute, reorderCompute } = this._passes[pass];\\n\\t\\t\\tconst isLastPass = pass === numPasses - 1;\\n\\t\\t\\tif (this._indirect) {\\n\\t\\t\\t\\tthis._blockSums.clear();\\n\\t\\t\\t}\\n\\t\\t\\thistogramCompute.setParameter(\\\"input\\\", currentKeys);\\n\\t\\t\\thistogramCompute.setParameter(\\\"block_sums\\\", this._blockSums);\\n\\t\\t\\thistogramCompute.setParameter(\\\"workgroupCount\\\", this._workgroupCount);\\n\\t\\t\\thistogramCompute.setParameter(\\\"elementCount\\\", elementCount);\\n\\t\\t\\tif (this._indirect) {\\n\\t\\t\\t\\thistogramCompute.setParameter(\\\"sortElementCount\\\", sortElementCountBuffer);\\n\\t\\t\\t\\thistogramCompute.setupIndirectDispatch(sortSlotBase);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\thistogramCompute.setupDispatch(this._dispatchSize.x, this._dispatchSize.y, 1);\\n\\t\\t\\t}\\n\\t\\t\\tdevice.computeDispatch([histogramCompute], `RadixSort4bit-Histogram${suffix}`);\\n\\t\\t\\tthis._prefixSumKernel.dispatch(device);\\n\\t\\t\\treorderCompute.setParameter(\\\"inputKeys\\\", currentKeys);\\n\\t\\t\\treorderCompute.setParameter(\\\"outputKeys\\\", nextKeys);\\n\\t\\t\\treorderCompute.setParameter(\\\"prefix_block_sum\\\", this._blockSums);\\n\\t\\t\\treorderCompute.setParameter(\\\"inputValues\\\", currentValues);\\n\\t\\t\\treorderCompute.setParameter(\\\"outputValues\\\", nextValues);\\n\\t\\t\\treorderCompute.setParameter(\\\"workgroupCount\\\", this._workgroupCount);\\n\\t\\t\\treorderCompute.setParameter(\\\"elementCount\\\", elementCount);\\n\\t\\t\\tif (this._indirect) {\\n\\t\\t\\t\\treorderCompute.setParameter(\\\"sortElementCount\\\", sortElementCountBuffer);\\n\\t\\t\\t\\treorderCompute.setupIndirectDispatch(sortSlotBase);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\treorderCompute.setupDispatch(this._dispatchSize.x, this._dispatchSize.y, 1);\\n\\t\\t\\t}\\n\\t\\t\\tdevice.computeDispatch([reorderCompute], `RadixSort4bit-Reorder${suffix}`);\\n\\t\\t\\tif (!isLastPass) {\\n\\t\\t\\t\\tcurrentKeys = nextKeys;\\n\\t\\t\\t\\tnextKeys = currentKeys === this._keys0 ? this._keys1 : this._keys0;\\n\\t\\t\\t\\tconst tempValues = currentValues;\\n\\t\\t\\t\\tcurrentValues = nextValues;\\n\\t\\t\\t\\tnextValues = tempValues;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn this.sortedIndices;\\n\\t}\\n}\\n\\nconst onesweepGlobalHistSource = `\\n@group(0) @binding(0) var<storage, read> b_sort: array<vec4<u32>>;\\n@group(0) @binding(1) var<storage, read_write> b_globalHist: array<atomic<u32>>;\\nstruct OneSweepUniforms {\\n\\tnumKeys: u32,\\n\\tthreadBlocks: u32,\\n\\tnumPasses: u32,\\n\\t_pad: u32\\n};\\n@group(0) @binding(2) var<uniform> uniforms: OneSweepUniforms;\\n#ifdef USE_INDIRECT_SORT\\n@group(0) @binding(3) var<storage, read> b_sortElementCount: array<u32>;\\n#endif\\nconst RADIX: u32 = 256u;\\nconst MAX_PASSES: u32 = 4u;\\nconst G_HIST_DIM: u32 = {G_HIST_DIM}u;\\nconst G_HIST_PART_SIZE: u32 = {G_HIST_PART_SIZE}u;\\nconst G_HIST_PART_SIZE_VEC: u32 = G_HIST_PART_SIZE / 4u;\\nconst SHARED_HIST_SIZE: u32 = 2u * MAX_PASSES * RADIX;\\nvar<workgroup> g_gHist: array<atomic<u32>, SHARED_HIST_SIZE>;\\nfn histOffset(row: u32, pass_: u32) -> u32 {\\n\\treturn row * RADIX + pass_ * 2u * RADIX;\\n}\\n@compute @workgroup_size(G_HIST_DIM, 1, 1)\\nfn main(\\n\\t@builtin(local_invocation_index) gtid: u32,\\n\\t@builtin(workgroup_id) gid: vec3<u32>,\\n\\t@builtin(num_workgroups) nwg: vec3<u32>,\\n) {\\n\\tlet flatGid = gid.x + gid.y * nwg.x;\\n\\tlet numPasses = uniforms.numPasses;\\n\\t#ifdef USE_INDIRECT_SORT\\n\\t\\tlet numKeys = b_sortElementCount[0];\\n\\t#else\\n\\t\\tlet numKeys = uniforms.numKeys;\\n\\t#endif\\n\\tlet sharedEnd = 2u * numPasses * RADIX;\\n\\tfor (var i = gtid; i < sharedEnd; i = i + G_HIST_DIM) {\\n\\t\\tatomicStore(&g_gHist[i], 0u);\\n\\t}\\n\\tworkgroupBarrier();\\n\\tlet row = gtid / 64u;\\n\\tlet numKeysVecFull = numKeys >> 2u;\\n\\tlet partitionStartVec = flatGid * G_HIST_PART_SIZE_VEC;\\n\\tlet partitionEndVec = min(partitionStartVec + G_HIST_PART_SIZE_VEC, numKeysVecFull);\\n\\tfor (var i = partitionStartVec + gtid; i < partitionEndVec; i = i + G_HIST_DIM) {\\n\\t\\tlet q = b_sort[i];\\n\\t\\tif (numPasses >= 1u) {\\n\\t\\t\\tlet off = histOffset(row, 0u);\\n\\t\\t\\tatomicAdd(&g_gHist[(q.x\\t\\t & 0xFFu) + off], 1u);\\n\\t\\t\\tatomicAdd(&g_gHist[(q.y\\t\\t & 0xFFu) + off], 1u);\\n\\t\\t\\tatomicAdd(&g_gHist[(q.z\\t\\t & 0xFFu) + off], 1u);\\n\\t\\t\\tatomicAdd(&g_gHist[(q.w\\t\\t & 0xFFu) + off], 1u);\\n\\t\\t}\\n\\t\\tif (numPasses >= 2u) {\\n\\t\\t\\tlet off = histOffset(row, 1u);\\n\\t\\t\\tatomicAdd(&g_gHist[((q.x >>  8u) & 0xFFu) + off], 1u);\\n\\t\\t\\tatomicAdd(&g_gHist[((q.y >>  8u) & 0xFFu) + off], 1u);\\n\\t\\t\\tatomicAdd(&g_gHist[((q.z >>  8u) & 0xFFu) + off], 1u);\\n\\t\\t\\tatomicAdd(&g_gHist[((q.w >>  8u) & 0xFFu) + off], 1u);\\n\\t\\t}\\n\\t\\tif (numPasses >= 3u) {\\n\\t\\t\\tlet off = histOffset(row, 2u);\\n\\t\\t\\tatomicAdd(&g_gHist[((q.x >> 16u) & 0xFFu) + off], 1u);\\n\\t\\t\\tatomicAdd(&g_gHist[((q.y >> 16u) & 0xFFu) + off], 1u);\\n\\t\\t\\tatomicAdd(&g_gHist[((q.z >> 16u) & 0xFFu) + off], 1u);\\n\\t\\t\\tatomicAdd(&g_gHist[((q.w >> 16u) & 0xFFu) + off], 1u);\\n\\t\\t}\\n\\t\\tif (numPasses >= 4u) {\\n\\t\\t\\tlet off = histOffset(row, 3u);\\n\\t\\t\\tatomicAdd(&g_gHist[((q.x >> 24u) & 0xFFu) + off], 1u);\\n\\t\\t\\tatomicAdd(&g_gHist[((q.y >> 24u) & 0xFFu) + off], 1u);\\n\\t\\t\\tatomicAdd(&g_gHist[((q.z >> 24u) & 0xFFu) + off], 1u);\\n\\t\\t\\tatomicAdd(&g_gHist[((q.w >> 24u) & 0xFFu) + off], 1u);\\n\\t\\t}\\n\\t}\\n\\tlet tailIdx = numKeysVecFull;\\n\\tif ((numKeys & 3u) != 0u &&\\n\\t\\ttailIdx >= partitionStartVec &&\\n\\t\\ttailIdx <  partitionStartVec + G_HIST_PART_SIZE_VEC &&\\n\\t\\t(tailIdx - partitionStartVec) % G_HIST_DIM == gtid) {\\n\\t\\tlet q = b_sort[tailIdx];\\n\\t\\tlet base = tailIdx << 2u;\\n\\t\\tif (numPasses >= 1u) {\\n\\t\\t\\tlet off = histOffset(row, 0u);\\n\\t\\t\\tif (base + 0u < numKeys) { atomicAdd(&g_gHist[(q.x & 0xFFu) + off], 1u); }\\n\\t\\t\\tif (base + 1u < numKeys) { atomicAdd(&g_gHist[(q.y & 0xFFu) + off], 1u); }\\n\\t\\t\\tif (base + 2u < numKeys) { atomicAdd(&g_gHist[(q.z & 0xFFu) + off], 1u); }\\n\\t\\t}\\n\\t\\tif (numPasses >= 2u) {\\n\\t\\t\\tlet off = histOffset(row, 1u);\\n\\t\\t\\tif (base + 0u < numKeys) { atomicAdd(&g_gHist[((q.x >>  8u) & 0xFFu) + off], 1u); }\\n\\t\\t\\tif (base + 1u < numKeys) { atomicAdd(&g_gHist[((q.y >>  8u) & 0xFFu) + off], 1u); }\\n\\t\\t\\tif (base + 2u < numKeys) { atomicAdd(&g_gHist[((q.z >>  8u) & 0xFFu) + off], 1u); }\\n\\t\\t}\\n\\t\\tif (numPasses >= 3u) {\\n\\t\\t\\tlet off = histOffset(row, 2u);\\n\\t\\t\\tif (base + 0u < numKeys) { atomicAdd(&g_gHist[((q.x >> 16u) & 0xFFu) + off], 1u); }\\n\\t\\t\\tif (base + 1u < numKeys) { atomicAdd(&g_gHist[((q.y >> 16u) & 0xFFu) + off], 1u); }\\n\\t\\t\\tif (base + 2u < numKeys) { atomicAdd(&g_gHist[((q.z >> 16u) & 0xFFu) + off], 1u); }\\n\\t\\t}\\n\\t\\tif (numPasses >= 4u) {\\n\\t\\t\\tlet off = histOffset(row, 3u);\\n\\t\\t\\tif (base + 0u < numKeys) { atomicAdd(&g_gHist[((q.x >> 24u) & 0xFFu) + off], 1u); }\\n\\t\\t\\tif (base + 1u < numKeys) { atomicAdd(&g_gHist[((q.y >> 24u) & 0xFFu) + off], 1u); }\\n\\t\\t\\tif (base + 2u < numKeys) { atomicAdd(&g_gHist[((q.z >> 24u) & 0xFFu) + off], 1u); }\\n\\t\\t}\\n\\t}\\n\\tworkgroupBarrier();\\n\\tfor (var i = gtid; i < RADIX; i = i + G_HIST_DIM) {\\n\\t\\tfor (var p = 0u; p < numPasses; p = p + 1u) {\\n\\t\\t\\tlet row0 = atomicLoad(&g_gHist[i + histOffset(0u, p)]);\\n\\t\\t\\tlet row1 = atomicLoad(&g_gHist[i + histOffset(1u, p)]);\\n\\t\\t\\tlet total = row0 + row1;\\n\\t\\t\\tif (total != 0u) {\\n\\t\\t\\t\\tatomicAdd(&b_globalHist[i + p * RADIX], total);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\n`;\\n\\nconst onesweepScanSource = `\\n@group(0) @binding(0) var<storage, read> b_globalHist: array<u32>;\\n@group(0) @binding(1) var<storage, read_write> b_passHist: array<atomic<u32>>;\\nstruct OneSweepScanUniforms {\\n\\tthreadBlocks: u32,\\n\\t_pad0: u32,\\n\\t_pad1: u32,\\n\\t_pad2: u32\\n};\\n@group(0) @binding(2) var<uniform> uniforms: OneSweepScanUniforms;\\n#ifdef USE_INDIRECT_SORT\\n@group(0) @binding(3) var<storage, read> b_sortElementCount: array<u32>;\\n#endif\\nconst RADIX: u32 = 256u;\\nconst FLAG_INCLUSIVE: u32 = 2u;\\nconst PART_SIZE: u32 = {PART_SIZE}u;\\nconst MAX_SUBGROUPS: u32 = {MAX_SUBGROUPS}u;\\nvar<workgroup> g_scan: array<u32, RADIX>;\\nvar<workgroup> sg_totals: array<u32, MAX_SUBGROUPS>;\\n@compute @workgroup_size(RADIX, 1, 1)\\nfn main(\\n\\t@builtin(local_invocation_index) gtid: u32,\\n\\t@builtin(workgroup_id) gid: vec3<u32>,\\n\\t@builtin(subgroup_invocation_id) sgInvId: u32,\\n\\t@builtin(subgroup_size) sgSize: u32,\\n) {\\n\\tlet pass_ = gid.x;\\n\\t#ifdef USE_INDIRECT_SORT\\n\\tlet numKeys = b_sortElementCount[0];\\n\\tlet threadBlocks = (numKeys + PART_SIZE - 1u) / PART_SIZE;\\n\\t#else\\n\\tlet threadBlocks = uniforms.threadBlocks;\\n\\t#endif\\n\\tlet waveIndex = gtid / sgSize;\\n\\tlet t = b_globalHist[gtid + pass_ * RADIX];\\n\\tlet sgExcl = subgroupExclusiveAdd(t);\\n\\tlet sgTotal = subgroupAdd(t);\\n\\tif (sgInvId == 0u) {\\n\\t\\tsg_totals[waveIndex] = sgTotal;\\n\\t}\\n\\tworkgroupBarrier();\\n\\tif (gtid == 0u) {\\n\\t\\tvar acc: u32 = 0u;\\n\\t\\tfor (var i = 0u; i < MAX_SUBGROUPS; i = i + 1u) {\\n\\t\\t\\tlet v = sg_totals[i];\\n\\t\\t\\tsg_totals[i] = acc;\\n\\t\\t\\tacc = acc + v;\\n\\t\\t}\\n\\t}\\n\\tworkgroupBarrier();\\n\\tlet excl = sgExcl + sg_totals[waveIndex];\\n\\tg_scan[gtid] = excl;\\n\\tlet dst = pass_ * threadBlocks * RADIX + gtid;\\n\\tatomicStore(&b_passHist[dst], (excl << 2u) | FLAG_INCLUSIVE);\\n}\\n`;\\n\\nconst onesweepBinningSource = `\\n@group(0) @binding(0) var<storage, read> inputKeys: array<u32>;\\n@group(0) @binding(1) var<storage, read_write> outputKeys: array<u32>;\\n@group(0) @binding(2) var<storage, read> inputValues: array<u32>;\\n@group(0) @binding(3) var<storage, read_write> outputValues: array<u32>;\\n@group(0) @binding(4) var<storage, read_write> b_passHist: array<atomic<u32>>;\\n@group(0) @binding(5) var<storage, read_write> b_index: array<atomic<u32>>;\\nstruct OneSweepBinningUniforms {\\n\\tnumKeys: u32,\\n\\tthreadBlocks: u32,\\n\\tpass_: u32,\\n\\tflags: u32\\n};\\n@group(0) @binding(6) var<uniform> uniforms: OneSweepBinningUniforms;\\n#ifdef USE_INDIRECT_SORT\\n@group(0) @binding(7) var<storage, read> b_sortElementCount: array<u32>;\\n#endif\\nconst RADIX: u32 = 256u;\\nconst RADIX_MASK: u32 = 255u;\\nconst RADIX_LOG: u32 = 8u;\\nconst D_DIM: u32 = {D_DIM}u;\\nconst KEYS_PER_THREAD: u32 = {KEYS_PER_THREAD}u;\\nconst PART_SIZE: u32 = D_DIM * KEYS_PER_THREAD;\\nconst MAX_SUBGROUPS: u32 = {MAX_SUBGROUPS}u;\\nconst WAVE_HISTS_SIZE: u32 = MAX_SUBGROUPS * RADIX;\\nconst G_D_SIZE: u32 = max(PART_SIZE, WAVE_HISTS_SIZE);\\nconst FLAG_NOT_READY: u32 = 0u;\\nconst FLAG_REDUCTION: u32 = 1u;\\nconst FLAG_INCLUSIVE: u32 = 2u;\\nconst FLAG_MASK: u32 = 3u;\\nvar<workgroup> g_d: array<atomic<u32>, G_D_SIZE>;\\nvar<workgroup> digit_base: array<u32, RADIX>;\\nvar<workgroup> sg_totals: array<u32, MAX_SUBGROUPS>;\\nvar<workgroup> wg_partIndex: u32;\\nfn passHistOffset(tb: u32, pass_: u32, partitionIdx: u32) -> u32 {\\n\\treturn pass_ * tb * RADIX + partitionIdx * RADIX;\\n}\\n@compute @workgroup_size(D_DIM, 1, 1)\\nfn main(\\n\\t@builtin(local_invocation_index) TID: u32,\\n\\t@builtin(subgroup_invocation_id) sgInvId: u32,\\n\\t@builtin(subgroup_size) sgSize: u32,\\n) {\\n\\tlet waveIndex = TID / sgSize;\\n\\tlet ltMask = (1u << sgInvId) - 1u;\\n\\tlet activeMask = select(0xFFFFFFFFu, (1u << sgSize) - 1u, sgSize < 32u);\\n\\tlet pass_ = uniforms.pass_;\\n\\tlet currentBit = pass_ << 3u;\\n\\t#ifdef USE_INDIRECT_SORT\\n\\tlet numKeys = b_sortElementCount[0];\\n\\tlet threadBlocks = (numKeys + PART_SIZE - 1u) / PART_SIZE;\\n\\t#else\\n\\tlet numKeys = uniforms.numKeys;\\n\\tlet threadBlocks = uniforms.threadBlocks;\\n\\t#endif\\n\\tlet isFirstPass = (uniforms.flags & 1u) != 0u;\\n\\tlet isLastPass = (uniforms.flags & 2u) != 0u;\\n\\tif (TID == 0u) {\\n\\t\\twg_partIndex = atomicAdd(&b_index[pass_], 1u);\\n\\t}\\n\\tlet partitionIndex = workgroupUniformLoad(&wg_partIndex);\\n\\tfor (var i = TID; i < WAVE_HISTS_SIZE; i = i + D_DIM) {\\n\\t\\tatomicStore(&g_d[i], 0u);\\n\\t}\\n\\tworkgroupBarrier();\\n\\tlet tileStart = partitionIndex * PART_SIZE;\\n\\tlet validInBlock = select(\\n\\t\\t0u,\\n\\t\\tmin(PART_SIZE, numKeys - tileStart),\\n\\t\\ttileStart < numKeys\\n\\t);\\n\\tlet subPartSize = sgSize * KEYS_PER_THREAD;\\n\\tlet waveBase = tileStart + waveIndex * subPartSize;\\n\\tvar keys: array<u32, {KEYS_PER_THREAD}>;\\n\\tvar values: array<u32, {KEYS_PER_THREAD}>;\\n\\tvar validMask: u32 = 0u;\\n\\tfor (var i = 0u; i < KEYS_PER_THREAD; i = i + 1u) {\\n\\t\\tlet gid = waveBase + sgInvId + i * sgSize;\\n\\t\\tlet is_valid = gid < numKeys;\\n\\t\\tkeys[i] = select(0xFFFFFFFFu, inputKeys[gid], is_valid);\\n\\t\\tvalues[i] = select(\\n\\t\\t\\tselect(0u, inputValues[gid], is_valid),\\n\\t\\t\\tgid,\\n\\t\\t\\tisFirstPass\\n\\t\\t);\\n\\t\\tif (is_valid) {\\n\\t\\t\\tvalidMask = validMask | (1u << i);\\n\\t\\t}\\n\\t}\\n\\tvar offsets: array<u32, {KEYS_PER_THREAD}>;\\n\\tfor (var i = 0u; i < KEYS_PER_THREAD; i = i + 1u) {\\n\\t\\tlet k = keys[i];\\n\\t\\tlet isValid = ((validMask >> i) & 1u) == 1u;\\n\\t\\tlet digit = (k >> currentBit) & RADIX_MASK;\\n\\t\\tvar waveFlag: u32 = activeMask;\\n\\t\\tfor (var b = 0u; b < 8u; b = b + 1u) {\\n\\t\\t\\tlet t = ((digit >> b) & 1u) == 1u;\\n\\t\\t\\tlet ballot = subgroupBallot(t).x;\\n\\t\\t\\twaveFlag = waveFlag & select(~ballot, ballot, t);\\n\\t\\t}\\n\\t\\tlet validBallot = subgroupBallot(isValid).x;\\n\\t\\twaveFlag = waveFlag & validBallot;\\n\\t\\tlet peerBits = countOneBits(waveFlag & ltMask);\\n\\t\\tlet totalBits = countOneBits(waveFlag);\\n\\t\\tlet lowestRankPeer = firstTrailingBit(waveFlag);\\n\\t\\tvar preIncrementVal: u32 = 0u;\\n\\t\\tif (isValid && peerBits == 0u) {\\n\\t\\t\\tpreIncrementVal = atomicAdd(&g_d[waveIndex * RADIX + digit], totalBits);\\n\\t\\t}\\n\\t\\toffsets[i] = subgroupShuffle(preIncrementVal, lowestRankPeer) + peerBits;\\n\\t\\tworkgroupBarrier();\\n\\t}\\n\\tvar myHistRed: u32 = 0u;\\n\\t{\\n\\t\\tvar histReduction = atomicLoad(&g_d[TID]);\\n\\t\\tfor (var w = 1u; w < MAX_SUBGROUPS; w = w + 1u) {\\n\\t\\t\\tlet idx = TID + w * RADIX;\\n\\t\\t\\tlet cnt = atomicLoad(&g_d[idx]);\\n\\t\\t\\thistReduction = histReduction + cnt;\\n\\t\\t\\tatomicStore(&g_d[idx], histReduction - cnt);\\n\\t\\t}\\n\\t\\tmyHistRed = histReduction;\\n\\t}\\n\\tif (partitionIndex + 1u < threadBlocks) {\\n\\t\\tlet dst = passHistOffset(threadBlocks, pass_, partitionIndex + 1u) + TID;\\n\\t\\tatomicAdd(&b_passHist[dst], FLAG_REDUCTION | (myHistRed << 2u));\\n\\t}\\n\\tlet warpExcl = subgroupExclusiveAdd(myHistRed);\\n\\tlet warpTotal = subgroupAdd(myHistRed);\\n\\tif (sgInvId == 0u) {\\n\\t\\tsg_totals[waveIndex] = warpTotal;\\n\\t}\\n\\tworkgroupBarrier();\\n\\tif (TID == 0u) {\\n\\t\\tvar acc: u32 = 0u;\\n\\t\\tfor (var w = 0u; w < MAX_SUBGROUPS; w = w + 1u) {\\n\\t\\t\\tlet t = sg_totals[w];\\n\\t\\t\\tsg_totals[w] = acc;\\n\\t\\t\\tacc = acc + t;\\n\\t\\t}\\n\\t}\\n\\tworkgroupBarrier();\\n\\tlet myDigitBase = warpExcl + sg_totals[waveIndex];\\n\\tvar scatterPos: array<u32, {KEYS_PER_THREAD}>;\\n\\tfor (var i = 0u; i < KEYS_PER_THREAD; i = i + 1u) {\\n\\t\\tlet k = keys[i];\\n\\t\\tlet digit = (k >> currentBit) & RADIX_MASK;\\n\\t\\tlet warpBase = select(0u, atomicLoad(&g_d[waveIndex * RADIX + digit]), waveIndex > 0u);\\n\\t\\tscatterPos[i] = offsets[i] + warpBase;\\n\\t}\\n\\tdigit_base[TID] = myDigitBase;\\n\\tworkgroupBarrier();\\n\\tfor (var i = 0u; i < KEYS_PER_THREAD; i = i + 1u) {\\n\\t\\tlet k = keys[i];\\n\\t\\tlet digit = (k >> currentBit) & RADIX_MASK;\\n\\t\\tscatterPos[i] = scatterPos[i] + digit_base[digit];\\n\\t}\\n\\tworkgroupBarrier();\\n\\tif (TID < RADIX) {\\n\\t\\tvar lookbackReduction: u32 = 0u;\\n\\t\\tvar k: u32 = partitionIndex;\\n\\t\\tvar done: bool = false;\\n\\t\\tloop {\\n\\t\\t\\tif (done) { break; }\\n\\t\\t\\tlet flagPayload = atomicLoad(&b_passHist[passHistOffset(threadBlocks, pass_, k) + TID]);\\n\\t\\t\\tlet flag = flagPayload & FLAG_MASK;\\n\\t\\t\\tif (flag == FLAG_INCLUSIVE) {\\n\\t\\t\\t\\tlookbackReduction = lookbackReduction + (flagPayload >> 2u);\\n\\t\\t\\t\\tif (partitionIndex + 1u < threadBlocks) {\\n\\t\\t\\t\\t\\tlet dst = passHistOffset(threadBlocks, pass_, partitionIndex + 1u) + TID;\\n\\t\\t\\t\\t\\tatomicAdd(&b_passHist[dst], 1u | (lookbackReduction << 2u));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdigit_base[TID] = lookbackReduction - myDigitBase;\\n\\t\\t\\t\\tdone = true;\\n\\t\\t\\t} else if (flag == FLAG_REDUCTION) {\\n\\t\\t\\t\\tlookbackReduction = lookbackReduction + (flagPayload >> 2u);\\n\\t\\t\\t\\tif (k == 0u) { done = true; }\\n\\t\\t\\t\\telse { k = k - 1u; }\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tfor (var i = 0u; i < KEYS_PER_THREAD; i = i + 1u) {\\n\\t\\tif (((validMask >> i) & 1u) == 1u) {\\n\\t\\t\\tatomicStore(&g_d[scatterPos[i]], keys[i]);\\n\\t\\t}\\n\\t}\\n\\tworkgroupBarrier();\\n\\tvar linearDigits: array<u32, {KEYS_PER_THREAD}>;\\n\\tfor (var r = 0u; r < KEYS_PER_THREAD; r = r + 1u) {\\n\\t\\tlet linearIdx = TID + r * D_DIM;\\n\\t\\tif (linearIdx < validInBlock) {\\n\\t\\t\\tlet k = atomicLoad(&g_d[linearIdx]);\\n\\t\\t\\tlet digit = (k >> currentBit) & RADIX_MASK;\\n\\t\\t\\tlinearDigits[r] = digit;\\n\\t\\t\\tlet globalPos = digit_base[digit] + linearIdx;\\n\\t\\t\\tif (!isLastPass) {\\n\\t\\t\\t\\toutputKeys[globalPos] = k;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tworkgroupBarrier();\\n\\tfor (var i = 0u; i < KEYS_PER_THREAD; i = i + 1u) {\\n\\t\\tif (((validMask >> i) & 1u) == 1u) {\\n\\t\\t\\tatomicStore(&g_d[scatterPos[i]], values[i]);\\n\\t\\t}\\n\\t}\\n\\tworkgroupBarrier();\\n\\tfor (var r = 0u; r < KEYS_PER_THREAD; r = r + 1u) {\\n\\t\\tlet linearIdx = TID + r * D_DIM;\\n\\t\\tif (linearIdx < validInBlock) {\\n\\t\\t\\tlet v = atomicLoad(&g_d[linearIdx]);\\n\\t\\t\\tlet digit = linearDigits[r];\\n\\t\\t\\tlet globalPos = digit_base[digit] + linearIdx;\\n\\t\\t\\toutputValues[globalPos] = v;\\n\\t\\t}\\n\\t}\\n}\\n`;\\n\\nconst D_DIM = 256;\\nconst KEYS_PER_THREAD = 15;\\nconst PART_SIZE = D_DIM * KEYS_PER_THREAD;\\nconst G_HIST_DIM = 128;\\nconst G_HIST_PART_SIZE = 32768;\\nconst RADIX = 256;\\nconst MAX_PASSES = 4;\\nclass ComputeRadixSortOneSweep extends ComputeRadixSortBase {\\n\\t_threadBlocks = 0;\\n\\t_allocatedThreadBlocks = 0;\\n\\t_globalHist = null;\\n\\t_passHist = null;\\n\\t_index = null;\\n\\t_binningDispatchSize = new Vec2(1, 1);\\n\\t_globalHistDispatchSize = new Vec2(1, 1);\\n\\t_globalHistBindGroupFormat = null;\\n\\t_scanBindGroupFormat = null;\\n\\t_binningBindGroupFormat = null;\\n\\t_globalHistUniformFormat = null;\\n\\t_scanUniformFormat = null;\\n\\t_binningUniformFormat = null;\\n\\t_globalHistShader = null;\\n\\t_scanShader = null;\\n\\t_binningShader = null;\\n\\t_globalHistCompute = null;\\n\\t_scanCompute = null;\\n\\t_binningComputes = [];\\n\\tconstructor(device, indirect = false) {\\n\\t\\tsuper(device, indirect);\\n\\t\\tconst info = this._indirectInfo;\\n\\t\\tinfo[0] = 2;\\n\\t\\tinfo[1] = PART_SIZE;\\n\\t\\tinfo[2] = G_HIST_PART_SIZE;\\n\\t\\tthis._globalHistUniformFormat = new UniformBufferFormat(device, [\\n\\t\\t\\tnew UniformFormat(\\\"numKeys\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"threadBlocks\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"numPasses\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"_pad\\\", UNIFORMTYPE_UINT)\\n\\t\\t]);\\n\\t\\tthis._scanUniformFormat = new UniformBufferFormat(device, [\\n\\t\\t\\tnew UniformFormat(\\\"threadBlocks\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"_pad0\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"_pad1\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"_pad2\\\", UNIFORMTYPE_UINT)\\n\\t\\t]);\\n\\t\\tthis._binningUniformFormat = new UniformBufferFormat(device, [\\n\\t\\t\\tnew UniformFormat(\\\"numKeys\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"threadBlocks\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"pass_\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"flags\\\", UNIFORMTYPE_UINT)\\n\\t\\t]);\\n\\t\\tconst minSubgroupSize = device.minSubgroupSize || device.maxSubgroupSize || 32;\\n\\t\\tconst maxSubgroups = Math.max(1, Math.ceil(256 / minSubgroupSize));\\n\\t\\tconst suffix = indirect ? \\\"Indirect\\\" : \\\"\\\";\\n\\t\\tconst histGroupEntries = [\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"b_sort\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"b_globalHist\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE)\\n\\t\\t];\\n\\t\\tconst scanGroupEntries = [\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"b_globalHist\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"b_passHist\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE)\\n\\t\\t];\\n\\t\\tconst binGroupEntries = [\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"inputKeys\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"outputKeys\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"inputValues\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"outputValues\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"b_passHist\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"b_index\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE)\\n\\t\\t];\\n\\t\\tif (indirect) {\\n\\t\\t\\thistGroupEntries.push(new BindStorageBufferFormat(\\\"b_sortElementCount\\\", SHADERSTAGE_COMPUTE, true));\\n\\t\\t\\tscanGroupEntries.push(new BindStorageBufferFormat(\\\"b_sortElementCount\\\", SHADERSTAGE_COMPUTE, true));\\n\\t\\t\\tbinGroupEntries.push(new BindStorageBufferFormat(\\\"b_sortElementCount\\\", SHADERSTAGE_COMPUTE, true));\\n\\t\\t}\\n\\t\\tthis._globalHistBindGroupFormat = new BindGroupFormat(device, histGroupEntries);\\n\\t\\tthis._scanBindGroupFormat = new BindGroupFormat(device, scanGroupEntries);\\n\\t\\tthis._binningBindGroupFormat = new BindGroupFormat(device, binGroupEntries);\\n\\t\\tconst histDefines = /* @__PURE__ */ new Map();\\n\\t\\thistDefines.set(\\\"{G_HIST_DIM}\\\", G_HIST_DIM);\\n\\t\\thistDefines.set(\\\"{G_HIST_PART_SIZE}\\\", G_HIST_PART_SIZE);\\n\\t\\tif (indirect) histDefines.set(\\\"USE_INDIRECT_SORT\\\", \\\"\\\");\\n\\t\\tthis._globalHistShader = new Shader(device, {\\n\\t\\t\\tname: `OneSweepGlobalHist${suffix}`,\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tcshader: onesweepGlobalHistSource,\\n\\t\\t\\tcdefines: histDefines,\\n\\t\\t\\tcomputeBindGroupFormat: this._globalHistBindGroupFormat,\\n\\t\\t\\tcomputeUniformBufferFormats: { uniforms: this._globalHistUniformFormat }\\n\\t\\t});\\n\\t\\tconst scanDefines = /* @__PURE__ */ new Map();\\n\\t\\tscanDefines.set(\\\"{MAX_SUBGROUPS}\\\", maxSubgroups);\\n\\t\\tscanDefines.set(\\\"{PART_SIZE}\\\", PART_SIZE);\\n\\t\\tif (indirect) scanDefines.set(\\\"USE_INDIRECT_SORT\\\", \\\"\\\");\\n\\t\\tthis._scanShader = new Shader(device, {\\n\\t\\t\\tname: `OneSweepScan${suffix}`,\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tcshader: onesweepScanSource,\\n\\t\\t\\tcdefines: scanDefines,\\n\\t\\t\\tcomputeBindGroupFormat: this._scanBindGroupFormat,\\n\\t\\t\\tcomputeUniformBufferFormats: { uniforms: this._scanUniformFormat }\\n\\t\\t});\\n\\t\\tconst binDefines = /* @__PURE__ */ new Map();\\n\\t\\tbinDefines.set(\\\"{D_DIM}\\\", D_DIM);\\n\\t\\tbinDefines.set(\\\"{KEYS_PER_THREAD}\\\", KEYS_PER_THREAD);\\n\\t\\tbinDefines.set(\\\"{MAX_SUBGROUPS}\\\", maxSubgroups);\\n\\t\\tif (indirect) binDefines.set(\\\"USE_INDIRECT_SORT\\\", \\\"\\\");\\n\\t\\tthis._binningShader = new Shader(device, {\\n\\t\\t\\tname: `OneSweepBinning${suffix}`,\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tcshader: onesweepBinningSource,\\n\\t\\t\\tcdefines: binDefines,\\n\\t\\t\\tcomputeBindGroupFormat: this._binningBindGroupFormat,\\n\\t\\t\\tcomputeUniformBufferFormats: { uniforms: this._binningUniformFormat }\\n\\t\\t});\\n\\t\\tthis._globalHistCompute = new Compute(device, this._globalHistShader, this._globalHistShader.name);\\n\\t\\tthis._scanCompute = new Compute(device, this._scanShader, this._scanShader.name);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._destroyBuffers();\\n\\t\\tthis._globalHistShader?.destroy();\\n\\t\\tthis._scanShader?.destroy();\\n\\t\\tthis._binningShader?.destroy();\\n\\t\\tthis._globalHistBindGroupFormat?.destroy();\\n\\t\\tthis._scanBindGroupFormat?.destroy();\\n\\t\\tthis._binningBindGroupFormat?.destroy();\\n\\t\\tthis._globalHistShader = null;\\n\\t\\tthis._scanShader = null;\\n\\t\\tthis._binningShader = null;\\n\\t\\tthis._globalHistCompute = null;\\n\\t\\tthis._scanCompute = null;\\n\\t\\tthis._binningComputes.length = 0;\\n\\t\\tthis._globalHistBindGroupFormat = null;\\n\\t\\tthis._scanBindGroupFormat = null;\\n\\t\\tthis._binningBindGroupFormat = null;\\n\\t\\tthis._globalHistUniformFormat = null;\\n\\t\\tthis._scanUniformFormat = null;\\n\\t\\tthis._binningUniformFormat = null;\\n\\t\\tsuper.destroy();\\n\\t}\\n\\t_destroyBuffers() {\\n\\t\\tthis._destroyPingPongBuffers();\\n\\t\\tthis._globalHist?.destroy();\\n\\t\\tthis._passHist?.destroy();\\n\\t\\tthis._index?.destroy();\\n\\t\\tthis._globalHist = null;\\n\\t\\tthis._passHist = null;\\n\\t\\tthis._index = null;\\n\\t\\tthis._allocatedThreadBlocks = 0;\\n\\t\\tthis._threadBlocks = 0;\\n\\t}\\n\\tget radixBits() {\\n\\t\\treturn 8;\\n\\t}\\n\\t_ensureBinningComputes(numPasses) {\\n\\t\\twhile (this._binningComputes.length < numPasses) {\\n\\t\\t\\tthis._binningComputes.push(new Compute(this.device, this._binningShader, `OneSweepBinning-${this._binningComputes.length}`));\\n\\t\\t}\\n\\t}\\n\\t_allocateBuffers(elementCount, forceRealloc = false) {\\n\\t\\tconst effectiveCount = Math.max(elementCount, this.capacity);\\n\\t\\tconst allocThreadBlocks = Math.max(1, Math.ceil(effectiveCount / PART_SIZE));\\n\\t\\tconst currentThreadBlocks = Math.max(1, Math.ceil(elementCount / PART_SIZE));\\n\\t\\tconst needRealloc = forceRealloc || allocThreadBlocks !== this._allocatedThreadBlocks || !this._keys0;\\n\\t\\tif (needRealloc) {\\n\\t\\t\\tthis._destroyBuffers();\\n\\t\\t\\tthis._allocatedThreadBlocks = allocThreadBlocks;\\n\\t\\t\\tthis.capacity = effectiveCount;\\n\\t\\t\\tconst device = this.device;\\n\\t\\t\\tthis._allocatePingPongElementBuffers(effectiveCount);\\n\\t\\t\\tthis._globalHist = new StorageBuffer(device, MAX_PASSES * RADIX * 4, BUFFERUSAGE_COPY_DST);\\n\\t\\t\\tthis._passHist = new StorageBuffer(device, MAX_PASSES * allocThreadBlocks * RADIX * 4, BUFFERUSAGE_COPY_DST);\\n\\t\\t\\tthis._index = new StorageBuffer(device, MAX_PASSES * 4, BUFFERUSAGE_COPY_DST);\\n\\t\\t}\\n\\t\\tthis._threadBlocks = currentThreadBlocks;\\n\\t\\tconst maxPerDim = this.device.limits.maxComputeWorkgroupsPerDimension || 65535;\\n\\t\\tCompute.calcDispatchSize(currentThreadBlocks, this._binningDispatchSize, maxPerDim);\\n\\t\\tconst histBlocks = Math.max(1, Math.ceil(elementCount / G_HIST_PART_SIZE));\\n\\t\\tCompute.calcDispatchSize(histBlocks, this._globalHistDispatchSize, maxPerDim);\\n\\t}\\n\\tsort(keysBuffer, elementCount, numBits = 16, initialValues, skipLastPassKeyWrite = false, destructiveKeys = false) {\\n\\t\\tconst numPasses = numBits / 8;\\n\\t\\tconst hasInitialValues = !!initialValues;\\n\\t\\tthis._elementCount = elementCount;\\n\\t\\tthis._numBits = numBits;\\n\\t\\tthis._hasInitialValues = hasInitialValues;\\n\\t\\tthis._skipLastPassKeyWrite = skipLastPassKeyWrite;\\n\\t\\tconst prevDestructiveKeys = this._destructiveKeys;\\n\\t\\tthis._destructiveKeys = destructiveKeys;\\n\\t\\tthis._allocateBuffers(elementCount, destructiveKeys !== prevDestructiveKeys);\\n\\t\\tthis._ensureBinningComputes(numPasses);\\n\\t\\tif (destructiveKeys) {\\n\\t\\t\\tthis._keys1 = keysBuffer;\\n\\t\\t}\\n\\t\\tconst device = this.device;\\n\\t\\tthis._globalHist.clear();\\n\\t\\tthis._passHist.clear(0, MAX_PASSES * this._threadBlocks * RADIX * 4);\\n\\t\\tthis._index.clear();\\n\\t\\tconst histCompute = this._globalHistCompute;\\n\\t\\thistCompute.setParameter(\\\"b_sort\\\", keysBuffer);\\n\\t\\thistCompute.setParameter(\\\"b_globalHist\\\", this._globalHist);\\n\\t\\thistCompute.setParameter(\\\"numKeys\\\", elementCount);\\n\\t\\thistCompute.setParameter(\\\"threadBlocks\\\", this._threadBlocks);\\n\\t\\thistCompute.setParameter(\\\"numPasses\\\", numPasses);\\n\\t\\thistCompute.setParameter(\\\"_pad\\\", 0);\\n\\t\\thistCompute.setupDispatch(this._globalHistDispatchSize.x, this._globalHistDispatchSize.y, 1);\\n\\t\\tdevice.computeDispatch([histCompute], \\\"OneSweep-GlobalHist\\\");\\n\\t\\tconst scanCompute = this._scanCompute;\\n\\t\\tscanCompute.setParameter(\\\"b_globalHist\\\", this._globalHist);\\n\\t\\tscanCompute.setParameter(\\\"b_passHist\\\", this._passHist);\\n\\t\\tscanCompute.setParameter(\\\"threadBlocks\\\", this._threadBlocks);\\n\\t\\tscanCompute.setParameter(\\\"_pad0\\\", 0);\\n\\t\\tscanCompute.setParameter(\\\"_pad1\\\", 0);\\n\\t\\tscanCompute.setParameter(\\\"_pad2\\\", 0);\\n\\t\\tscanCompute.setupDispatch(numPasses, 1, 1);\\n\\t\\tdevice.computeDispatch([scanCompute], \\\"OneSweep-Scan\\\");\\n\\t\\tlet currentKeys = keysBuffer;\\n\\t\\tlet currentValues = initialValues ?? this._values0;\\n\\t\\tlet nextKeys = this._keys0;\\n\\t\\tlet nextValues = this._values1;\\n\\t\\tfor (let pass = 0; pass < numPasses; pass++) {\\n\\t\\t\\tconst isFirstPass = pass === 0 && !hasInitialValues;\\n\\t\\t\\tconst isLastPass = pass === numPasses - 1;\\n\\t\\t\\tconst flags = (isFirstPass ? 1 : 0) | (isLastPass && skipLastPassKeyWrite ? 2 : 0);\\n\\t\\t\\tconst binCompute = this._binningComputes[pass];\\n\\t\\t\\tbinCompute.setParameter(\\\"inputKeys\\\", currentKeys);\\n\\t\\t\\tbinCompute.setParameter(\\\"outputKeys\\\", nextKeys);\\n\\t\\t\\tbinCompute.setParameter(\\\"inputValues\\\", currentValues);\\n\\t\\t\\tbinCompute.setParameter(\\\"outputValues\\\", nextValues);\\n\\t\\t\\tbinCompute.setParameter(\\\"b_passHist\\\", this._passHist);\\n\\t\\t\\tbinCompute.setParameter(\\\"b_index\\\", this._index);\\n\\t\\t\\tbinCompute.setParameter(\\\"numKeys\\\", elementCount);\\n\\t\\t\\tbinCompute.setParameter(\\\"threadBlocks\\\", this._threadBlocks);\\n\\t\\t\\tbinCompute.setParameter(\\\"pass_\\\", pass);\\n\\t\\t\\tbinCompute.setParameter(\\\"flags\\\", flags);\\n\\t\\t\\tbinCompute.setupDispatch(this._binningDispatchSize.x, this._binningDispatchSize.y, 1);\\n\\t\\t\\tdevice.computeDispatch([binCompute], `OneSweep-Binning-${pass}`);\\n\\t\\t\\tif (!isLastPass) {\\n\\t\\t\\t\\tcurrentKeys = nextKeys;\\n\\t\\t\\t\\tnextKeys = currentKeys === this._keys0 ? this._keys1 : this._keys0;\\n\\t\\t\\t\\tconst t = currentValues;\\n\\t\\t\\t\\tcurrentValues = nextValues;\\n\\t\\t\\t\\tnextValues = t;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn this.sortedIndices;\\n\\t}\\n\\tsortIndirect(keysBuffer, maxElementCount, numBits, sortSlotBase, sortElementCountBuffer, initialValues, skipLastPassKeyWrite = false, destructiveKeys = false) {\\n\\t\\tconst numPasses = numBits / 8;\\n\\t\\tconst hasInitialValues = !!initialValues;\\n\\t\\tthis._elementCount = maxElementCount;\\n\\t\\tthis._numBits = numBits;\\n\\t\\tthis._hasInitialValues = hasInitialValues;\\n\\t\\tthis._skipLastPassKeyWrite = skipLastPassKeyWrite;\\n\\t\\tconst prevDestructiveKeys = this._destructiveKeys;\\n\\t\\tthis._destructiveKeys = destructiveKeys;\\n\\t\\tthis._allocateBuffers(maxElementCount, destructiveKeys !== prevDestructiveKeys);\\n\\t\\tthis._ensureBinningComputes(numPasses);\\n\\t\\tif (destructiveKeys) {\\n\\t\\t\\tthis._keys1 = keysBuffer;\\n\\t\\t}\\n\\t\\tconst device = this.device;\\n\\t\\tthis._globalHist.clear();\\n\\t\\tthis._passHist.clear(0, MAX_PASSES * this._allocatedThreadBlocks * RADIX * 4);\\n\\t\\tthis._index.clear();\\n\\t\\tconst histCompute = this._globalHistCompute;\\n\\t\\thistCompute.setParameter(\\\"b_sort\\\", keysBuffer);\\n\\t\\thistCompute.setParameter(\\\"b_globalHist\\\", this._globalHist);\\n\\t\\thistCompute.setParameter(\\\"b_sortElementCount\\\", sortElementCountBuffer);\\n\\t\\thistCompute.setParameter(\\\"numKeys\\\", 0);\\n\\t\\thistCompute.setParameter(\\\"threadBlocks\\\", 0);\\n\\t\\thistCompute.setParameter(\\\"numPasses\\\", numPasses);\\n\\t\\thistCompute.setParameter(\\\"_pad\\\", 0);\\n\\t\\thistCompute.setupIndirectDispatch(sortSlotBase + 1);\\n\\t\\tdevice.computeDispatch([histCompute], \\\"OneSweep-GlobalHistIndirect\\\");\\n\\t\\tconst scanCompute = this._scanCompute;\\n\\t\\tscanCompute.setParameter(\\\"b_globalHist\\\", this._globalHist);\\n\\t\\tscanCompute.setParameter(\\\"b_passHist\\\", this._passHist);\\n\\t\\tscanCompute.setParameter(\\\"b_sortElementCount\\\", sortElementCountBuffer);\\n\\t\\tscanCompute.setParameter(\\\"threadBlocks\\\", 0);\\n\\t\\tscanCompute.setParameter(\\\"_pad0\\\", 0);\\n\\t\\tscanCompute.setParameter(\\\"_pad1\\\", 0);\\n\\t\\tscanCompute.setParameter(\\\"_pad2\\\", 0);\\n\\t\\tscanCompute.setupDispatch(numPasses, 1, 1);\\n\\t\\tdevice.computeDispatch([scanCompute], \\\"OneSweep-ScanIndirect\\\");\\n\\t\\tlet currentKeys = keysBuffer;\\n\\t\\tlet currentValues = initialValues ?? this._values0;\\n\\t\\tlet nextKeys = this._keys0;\\n\\t\\tlet nextValues = this._values1;\\n\\t\\tfor (let pass = 0; pass < numPasses; pass++) {\\n\\t\\t\\tconst isFirstPass = pass === 0 && !hasInitialValues;\\n\\t\\t\\tconst isLastPass = pass === numPasses - 1;\\n\\t\\t\\tconst flags = (isFirstPass ? 1 : 0) | (isLastPass && skipLastPassKeyWrite ? 2 : 0);\\n\\t\\t\\tconst binCompute = this._binningComputes[pass];\\n\\t\\t\\tbinCompute.setParameter(\\\"inputKeys\\\", currentKeys);\\n\\t\\t\\tbinCompute.setParameter(\\\"outputKeys\\\", nextKeys);\\n\\t\\t\\tbinCompute.setParameter(\\\"inputValues\\\", currentValues);\\n\\t\\t\\tbinCompute.setParameter(\\\"outputValues\\\", nextValues);\\n\\t\\t\\tbinCompute.setParameter(\\\"b_passHist\\\", this._passHist);\\n\\t\\t\\tbinCompute.setParameter(\\\"b_index\\\", this._index);\\n\\t\\t\\tbinCompute.setParameter(\\\"b_sortElementCount\\\", sortElementCountBuffer);\\n\\t\\t\\tbinCompute.setParameter(\\\"numKeys\\\", 0);\\n\\t\\t\\tbinCompute.setParameter(\\\"threadBlocks\\\", 0);\\n\\t\\t\\tbinCompute.setParameter(\\\"pass_\\\", pass);\\n\\t\\t\\tbinCompute.setParameter(\\\"flags\\\", flags);\\n\\t\\t\\tbinCompute.setupIndirectDispatch(sortSlotBase);\\n\\t\\t\\tdevice.computeDispatch([binCompute], `OneSweep-BinningIndirect-${pass}`);\\n\\t\\t\\tif (!isLastPass) {\\n\\t\\t\\t\\tcurrentKeys = nextKeys;\\n\\t\\t\\t\\tnextKeys = currentKeys === this._keys0 ? this._keys1 : this._keys0;\\n\\t\\t\\t\\tconst t = currentValues;\\n\\t\\t\\t\\tcurrentValues = nextValues;\\n\\t\\t\\t\\tnextValues = t;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn this.sortedIndices;\\n\\t}\\n}\\n\\nclass ComputeRadixSort {\\n\\t_impl;\\n\\tconstructor(device, options = {}) {\\n\\t\\tconst kind = options.kind ?? RADIX_SORT_AUTO;\\n\\t\\tconst indirect = options.indirect ?? false;\\n\\t\\tlet chosen = kind;\\n\\t\\tif (kind === RADIX_SORT_AUTO) {\\n\\t\\t\\tchosen = this._canUseOneSweep(device) ? RADIX_SORT_ONESWEEP : RADIX_SORT_PORTABLE;\\n\\t\\t}\\n\\t\\tif (chosen === RADIX_SORT_ONESWEEP) {\\n\\t\\t\\tif (!this._canUseOneSweep(device)) ;\\n\\t\\t\\tthis._impl = new ComputeRadixSortOneSweep(device, indirect);\\n\\t\\t} else {\\n\\t\\t\\tthis._impl = new ComputeRadixSortMultipass(device, indirect);\\n\\t\\t}\\n\\t}\\n\\t_canUseOneSweep(device) {\\n\\t\\tif (!device.supportsCompute || !device.supportsSubgroups) return false;\\n\\t\\tconst vendor = device.gpuAdapter?.info?.vendor?.toLowerCase?.();\\n\\t\\tif (vendor !== \\\"nvidia\\\") return false;\\n\\t\\tif (device.minSubgroupSize > 32) return false;\\n\\t\\treturn true;\\n\\t}\\n\\tget sortedIndices() {\\n\\t\\treturn this._impl.sortedIndices;\\n\\t}\\n\\tget sortedKeys() {\\n\\t\\treturn this._impl.sortedKeys;\\n\\t}\\n\\tget radixBits() {\\n\\t\\treturn this._impl.radixBits;\\n\\t}\\n\\tset capacity(value) {\\n\\t\\tthis._impl.capacity = value;\\n\\t}\\n\\tget capacity() {\\n\\t\\treturn this._impl.capacity;\\n\\t}\\n\\tsort(keysBuffer, elementCount, numBits = 16, initialValues, skipLastPassKeyWrite, destructiveKeys = false) {\\n\\t\\treturn this._impl.sort(keysBuffer, elementCount, numBits, initialValues, skipLastPassKeyWrite, destructiveKeys);\\n\\t}\\n\\tsortIndirect(keysBuffer, maxElementCount, numBits, sortSlotBase, sortElementCountBuffer, initialValues, skipLastPassKeyWrite, destructiveKeys = false) {\\n\\t\\treturn this._impl.sortIndirect(keysBuffer, maxElementCount, numBits, sortSlotBase, sortElementCountBuffer, initialValues, skipLastPassKeyWrite, destructiveKeys);\\n\\t}\\n\\tprepareIndirect() {\\n\\t\\treturn this._impl.prepareIndirect();\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._impl.destroy();\\n\\t}\\n}\\n\\nclass RenderPassShaderQuad extends RenderPass {\\n\\t_shader = null;\\n\\tquadRender = null;\\n\\tcullMode = CULLFACE_NONE;\\n\\tfrontFace = FRONTFACE_CCW;\\n\\tblendState = BlendState.NOBLEND;\\n\\tdepthState = DepthState.NODEPTH;\\n\\tstencilFront = null;\\n\\tstencilBack = null;\\n\\tviewport;\\n\\tscissor;\\n\\tset shader(shader) {\\n\\t\\tthis.quadRender?.destroy();\\n\\t\\tthis.quadRender = null;\\n\\t\\tthis._shader = shader;\\n\\t\\tif (shader) {\\n\\t\\t\\tthis.quadRender = new QuadRender(shader);\\n\\t\\t}\\n\\t}\\n\\tget shader() {\\n\\t\\treturn this._shader;\\n\\t}\\n\\texecute() {\\n\\t\\tthis.device.setDrawStates(this.blendState, this.depthState, this.cullMode, this.frontFace, this.stencilFront, this.stencilBack);\\n\\t\\tthis.quadRender?.render(this.viewport, this.scissor);\\n\\t}\\n}\\n\\nclass LitShaderOptions {\\n\\thasTangents = false;\\n\\tshaderChunks = null;\\n\\t// one of the SHADER_ constants\\n\\tpass = 0;\\n\\talphaTest = false;\\n\\tblendType = BLEND_NONE;\\n\\tseparateAmbient = false;\\n\\tscreenSpace = false;\\n\\tskin = false;\\n\\tbatch = false;\\n\\tuseInstancing = false;\\n\\tuseMorphPosition = false;\\n\\tuseMorphNormal = false;\\n\\tuseMorphTextureBasedInt = false;\\n\\tnineSlicedMode = 0;\\n\\tclusteredLightingEnabled = true;\\n\\tclusteredLightingCookiesEnabled = false;\\n\\tclusteredLightingShadowsEnabled = false;\\n\\tclusteredLightingShadowType = 0;\\n\\tclusteredLightingAreaLightsEnabled = false;\\n\\tvertexColors = false;\\n\\tuseVertexColorGamma = false;\\n\\tlightMapEnabled = false;\\n\\tdirLightMapEnabled = false;\\n\\tuseHeights = false;\\n\\tuseNormals = false;\\n\\tuseClearCoatNormals = false;\\n\\tuseAo = false;\\n\\tdiffuseMapEnabled = false;\\n\\tpixelSnap = false;\\n\\tambientSH = false;\\n\\tssao = false;\\n\\ttwoSidedLighting = false;\\n\\toccludeDirect = false;\\n\\toccludeSpecular = 0;\\n\\toccludeSpecularFloat = false;\\n\\tuseMsdf = false;\\n\\tmsdfTextAttribute = false;\\n\\talphaToCoverage = false;\\n\\topacityFadesSpecular = false;\\n\\topacityDither = DITHER_NONE;\\n\\topacityShadowDither = DITHER_NONE;\\n\\tcubeMapProjection = 0;\\n\\tuseSpecular = false;\\n\\tuseSpecularityFactor = false;\\n\\tenableGGXSpecular = false;\\n\\tfresnelModel = 0;\\n\\tuseRefraction = false;\\n\\tuseClearCoat = false;\\n\\tuseSheen = false;\\n\\tuseIridescence = false;\\n\\tuseMetalness = false;\\n\\tuseDynamicRefraction = false;\\n\\tdispersion = false;\\n\\tfog = FOG_NONE;\\n\\tgamma = GAMMA_NONE;\\n\\ttoneMap = -1;\\n\\treflectionSource = REFLECTIONSRC_NONE;\\n\\treflectionEncoding = null;\\n\\treflectionCubemapEncoding = null;\\n\\tambientSource = \\\"constant\\\";\\n\\tambientEncoding = null;\\n\\t// TODO: add a test for if non skybox cubemaps have rotation (when this is supported) - for now\\n\\t// assume no non-skybox cubemap rotation\\n\\tskyboxIntensity = 1;\\n\\tuseCubeMapRotation = false;\\n\\tlightMapWithoutAmbient = false;\\n\\tlights = [];\\n\\tnoShadow = false;\\n\\tlightMaskDynamic = 0;\\n\\tuserAttributes = {};\\n\\tlinearDepth = false;\\n\\tshadowCatcher = false;\\n}\\n\\nclass LitMaterialOptionsBuilder {\\n\\tstatic update(litOptions, material, scene, renderParams, objDefs, pass, sortedLights) {\\n\\t\\tLitMaterialOptionsBuilder.updateSharedOptions(litOptions, material, scene, objDefs, pass);\\n\\t\\tLitMaterialOptionsBuilder.updateMaterialOptions(litOptions, material);\\n\\t\\tLitMaterialOptionsBuilder.updateEnvOptions(litOptions, material, scene, renderParams);\\n\\t\\tLitMaterialOptionsBuilder.updateLightingOptions(litOptions, material, scene, objDefs, sortedLights);\\n\\t}\\n\\tstatic updateSharedOptions(litOptions, material, scene, objDefs, pass) {\\n\\t\\tlitOptions.shaderChunks = material.shaderChunks;\\n\\t\\tlitOptions.pass = pass;\\n\\t\\tlitOptions.alphaTest = material.alphaTest > 0;\\n\\t\\tlitOptions.blendType = material.blendType;\\n\\t\\tlitOptions.screenSpace = objDefs && (objDefs & SHADERDEF_SCREENSPACE) !== 0;\\n\\t\\tlitOptions.skin = objDefs && (objDefs & SHADERDEF_SKIN) !== 0;\\n\\t\\tlitOptions.useInstancing = objDefs && (objDefs & SHADERDEF_INSTANCING) !== 0;\\n\\t\\tlitOptions.useMorphPosition = objDefs && (objDefs & SHADERDEF_MORPH_POSITION) !== 0;\\n\\t\\tlitOptions.useMorphNormal = objDefs && (objDefs & SHADERDEF_MORPH_NORMAL) !== 0;\\n\\t\\tlitOptions.useMorphTextureBasedInt = objDefs && (objDefs & SHADERDEF_MORPH_TEXTURE_BASED_INT) !== 0;\\n\\t\\tlitOptions.hasTangents = objDefs && (objDefs & SHADERDEF_TANGENTS) !== 0;\\n\\t\\tlitOptions.nineSlicedMode = material.nineSlicedMode || SPRITE_RENDERMODE_SIMPLE;\\n\\t\\tif (material.useLighting && scene.clusteredLightingEnabled) {\\n\\t\\t\\tlitOptions.clusteredLightingEnabled = true;\\n\\t\\t\\tlitOptions.clusteredLightingCookiesEnabled = scene.lighting.cookiesEnabled;\\n\\t\\t\\tlitOptions.clusteredLightingShadowsEnabled = scene.lighting.shadowsEnabled;\\n\\t\\t\\tlitOptions.clusteredLightingShadowType = scene.lighting.shadowType;\\n\\t\\t\\tlitOptions.clusteredLightingAreaLightsEnabled = scene.lighting.areaLightsEnabled;\\n\\t\\t} else {\\n\\t\\t\\tlitOptions.clusteredLightingEnabled = false;\\n\\t\\t\\tlitOptions.clusteredLightingCookiesEnabled = false;\\n\\t\\t\\tlitOptions.clusteredLightingShadowsEnabled = false;\\n\\t\\t\\tlitOptions.clusteredLightingAreaLightsEnabled = false;\\n\\t\\t}\\n\\t}\\n\\tstatic updateMaterialOptions(litOptions, material) {\\n\\t\\tlitOptions.separateAmbient = false;\\n\\t\\tlitOptions.pixelSnap = material.pixelSnap;\\n\\t\\tlitOptions.ambientSH = material.ambientSH;\\n\\t\\tlitOptions.twoSidedLighting = material.twoSidedLighting;\\n\\t\\tlitOptions.occludeDirect = material.occludeDirect;\\n\\t\\tlitOptions.occludeSpecular = material.occludeSpecular;\\n\\t\\tlitOptions.occludeSpecularFloat = material.occludeSpecularIntensity !== 1;\\n\\t\\tlitOptions.useMsdf = false;\\n\\t\\tlitOptions.msdfTextAttribute = false;\\n\\t\\tlitOptions.alphaToCoverage = material.alphaToCoverage;\\n\\t\\tlitOptions.opacityFadesSpecular = material.opacityFadesSpecular;\\n\\t\\tlitOptions.opacityDither = material.opacityDither;\\n\\t\\tlitOptions.cubeMapProjection = CUBEPROJ_NONE;\\n\\t\\tlitOptions.useSpecular = material.hasSpecular;\\n\\t\\tlitOptions.useSpecularityFactor = material.hasSpecularityFactor;\\n\\t\\tlitOptions.enableGGXSpecular = material.ggxSpecular;\\n\\t\\tlitOptions.useAnisotropy = false;\\n\\t\\tlitOptions.fresnelModel = material.fresnelModel;\\n\\t\\tlitOptions.useRefraction = material.hasRefraction;\\n\\t\\tlitOptions.useClearCoat = material.hasClearCoat;\\n\\t\\tlitOptions.useSheen = material.hasSheen;\\n\\t\\tlitOptions.useIridescence = material.hasIrridescence;\\n\\t\\tlitOptions.useMetalness = material.hasMetalness;\\n\\t\\tlitOptions.useDynamicRefraction = material.dynamicRefraction;\\n\\t\\tlitOptions.dispersion = material.dispersion > 0;\\n\\t\\tlitOptions.vertexColors = false;\\n\\t\\tlitOptions.lightMapEnabled = material.hasLighting;\\n\\t\\tlitOptions.dirLightMapEnabled = material.dirLightMap;\\n\\t\\tlitOptions.useHeights = material.hasHeights;\\n\\t\\tlitOptions.useNormals = material.hasNormals;\\n\\t\\tlitOptions.useClearCoatNormals = material.hasClearCoatNormals;\\n\\t\\tlitOptions.useAo = material.hasAo;\\n\\t\\tlitOptions.diffuseMapEnabled = material.hasDiffuseMap;\\n\\t}\\n\\tstatic updateEnvOptions(litOptions, material, scene, renderParams) {\\n\\t\\tlitOptions.fog = material.useFog ? renderParams.fog : FOG_NONE;\\n\\t\\tlitOptions.gamma = renderParams.shaderOutputGamma;\\n\\t\\tlitOptions.toneMap = material.useTonemap ? renderParams.toneMapping : TONEMAP_NONE;\\n\\t\\tif (material.useSkybox && scene.envAtlas && scene.skybox) {\\n\\t\\t\\tlitOptions.reflectionSource = REFLECTIONSRC_ENVATLASHQ;\\n\\t\\t\\tlitOptions.reflectionEncoding = scene.envAtlas.encoding;\\n\\t\\t\\tlitOptions.reflectionCubemapEncoding = scene.skybox.encoding;\\n\\t\\t} else if (material.useSkybox && scene.envAtlas) {\\n\\t\\t\\tlitOptions.reflectionSource = REFLECTIONSRC_ENVATLAS;\\n\\t\\t\\tlitOptions.reflectionEncoding = scene.envAtlas.encoding;\\n\\t\\t} else if (material.useSkybox && scene.skybox) {\\n\\t\\t\\tlitOptions.reflectionSource = REFLECTIONSRC_CUBEMAP;\\n\\t\\t\\tlitOptions.reflectionEncoding = scene.skybox.encoding;\\n\\t\\t} else {\\n\\t\\t\\tlitOptions.reflectionSource = REFLECTIONSRC_NONE;\\n\\t\\t\\tlitOptions.reflectionEncoding = null;\\n\\t\\t}\\n\\t\\tif (material.ambientSH) {\\n\\t\\t\\tlitOptions.ambientSource = AMBIENTSRC_AMBIENTSH;\\n\\t\\t\\tlitOptions.ambientEncoding = null;\\n\\t\\t} else if (litOptions.reflectionSource !== REFLECTIONSRC_NONE && scene.envAtlas) {\\n\\t\\t\\tlitOptions.ambientSource = AMBIENTSRC_ENVALATLAS;\\n\\t\\t\\tlitOptions.ambientEncoding = scene.envAtlas.encoding;\\n\\t\\t} else {\\n\\t\\t\\tlitOptions.ambientSource = AMBIENTSRC_CONSTANT;\\n\\t\\t\\tlitOptions.ambientEncoding = null;\\n\\t\\t}\\n\\t\\tconst hasSkybox = litOptions.reflectionSource !== REFLECTIONSRC_NONE;\\n\\t\\tlitOptions.skyboxIntensity = hasSkybox;\\n\\t\\tlitOptions.useCubeMapRotation = hasSkybox && scene._skyboxRotationShaderInclude;\\n\\t}\\n\\tstatic updateLightingOptions(litOptions, material, scene, objDefs, sortedLights) {\\n\\t\\tlitOptions.lightMapWithoutAmbient = false;\\n\\t\\tif (material.useLighting) {\\n\\t\\t\\tconst lightsFiltered = [];\\n\\t\\t\\tconst mask = objDefs ? objDefs >> 16 : MASK_AFFECT_DYNAMIC;\\n\\t\\t\\tlitOptions.lightMaskDynamic = !!(mask & MASK_AFFECT_DYNAMIC);\\n\\t\\t\\tlitOptions.lightMapWithoutAmbient = false;\\n\\t\\t\\tif (sortedLights) {\\n\\t\\t\\t\\tLitMaterialOptionsBuilder.collectLights(LIGHTTYPE_DIRECTIONAL, sortedLights[LIGHTTYPE_DIRECTIONAL], lightsFiltered, mask);\\n\\t\\t\\t\\tif (!scene.clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\tLitMaterialOptionsBuilder.collectLights(LIGHTTYPE_OMNI, sortedLights[LIGHTTYPE_OMNI], lightsFiltered, mask);\\n\\t\\t\\t\\t\\tLitMaterialOptionsBuilder.collectLights(LIGHTTYPE_SPOT, sortedLights[LIGHTTYPE_SPOT], lightsFiltered, mask);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tlitOptions.lights = lightsFiltered;\\n\\t\\t} else {\\n\\t\\t\\tlitOptions.lights = [];\\n\\t\\t}\\n\\t\\tif (litOptions.lights.length === 0 && !scene.clusteredLightingEnabled || (objDefs & SHADERDEF_NOSHADOW) !== 0) {\\n\\t\\t\\tlitOptions.noShadow = true;\\n\\t\\t}\\n\\t}\\n\\tstatic collectLights(lType, lights, lightsFiltered, mask) {\\n\\t\\tfor (let i = 0; i < lights.length; i++) {\\n\\t\\t\\tconst light = lights[i];\\n\\t\\t\\tif (light.enabled) {\\n\\t\\t\\t\\tif (light.mask & mask) {\\n\\t\\t\\t\\t\\tlightsFiltered.push(light);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\n\\nconst builtinAttributes = {\\n\\tvertex_normal: SEMANTIC_NORMAL,\\n\\tvertex_tangent: SEMANTIC_TANGENT,\\n\\tvertex_texCoord0: SEMANTIC_TEXCOORD0,\\n\\tvertex_texCoord1: SEMANTIC_TEXCOORD1,\\n\\tvertex_color: SEMANTIC_COLOR,\\n\\tvertex_boneWeights: SEMANTIC_BLENDWEIGHT,\\n\\tvertex_boneIndices: SEMANTIC_BLENDINDICES\\n};\\nclass LitShader {\\n\\tvaryingsCode = \\\"\\\";\\n\\tdevice;\\n\\toptions;\\n\\tshaderLanguage;\\n\\tvDefines = /* @__PURE__ */ new Map();\\n\\tfDefines = /* @__PURE__ */ new Map();\\n\\tincludes = /* @__PURE__ */ new Map();\\n\\tchunks = null;\\n\\tconstructor(device, options, allowWGSL = true) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.options = options;\\n\\t\\tconst userChunks = options.shaderChunks;\\n\\t\\tthis.shaderLanguage = device.isWebGPU && allowWGSL && (!userChunks || userChunks.useWGSL) ? SHADERLANGUAGE_WGSL : SHADERLANGUAGE_GLSL;\\n\\t\\tif (device.isWebGPU && this.shaderLanguage === SHADERLANGUAGE_GLSL) {\\n\\t\\t\\tif (!device.hasTranspilers) ;\\n\\t\\t}\\n\\t\\tthis.attributes = {\\n\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t};\\n\\t\\tif (options.userAttributes) {\\n\\t\\t\\tfor (const [semantic, name] of Object.entries(options.userAttributes)) {\\n\\t\\t\\t\\tthis.attributes[name] = semantic;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst engineChunks = ShaderChunks.get(device, this.shaderLanguage);\\n\\t\\tthis.chunks = new Map(engineChunks);\\n\\t\\tif (userChunks) {\\n\\t\\t\\tconst userChunkMap = this.shaderLanguage === SHADERLANGUAGE_GLSL ? userChunks.glsl : userChunks.wgsl;\\n\\t\\t\\tuserChunkMap.forEach((chunk, chunkName) => {\\n\\t\\t\\t\\tfor (const a in builtinAttributes) {\\n\\t\\t\\t\\t\\tif (builtinAttributes.hasOwnProperty(a) && chunk.indexOf(a) >= 0) {\\n\\t\\t\\t\\t\\t\\tthis.attributes[a] = builtinAttributes[a];\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.chunks.set(chunkName, chunk);\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tthis.shaderPassInfo = ShaderPass.get(this.device).getByIndex(options.pass);\\n\\t\\tthis.shadowPass = this.shaderPassInfo.isShadow;\\n\\t\\tthis.lighting = options.lights.length > 0 || options.dirLightMapEnabled || options.clusteredLightingEnabled;\\n\\t\\tthis.reflections = options.reflectionSource !== REFLECTIONSRC_NONE;\\n\\t\\tthis.needsNormal = this.lighting || this.reflections || options.useSpecular || options.ambientSH || options.useHeights || options.enableGGXSpecular || options.clusteredLightingEnabled && !this.shadowPass || options.useClearCoatNormals;\\n\\t\\tthis.needsNormal = this.needsNormal && !this.shadowPass;\\n\\t\\tthis.needsSceneColor = options.useDynamicRefraction;\\n\\t\\tthis.needsScreenSize = options.useDynamicRefraction;\\n\\t\\tthis.needsTransforms = options.useDynamicRefraction;\\n\\t\\tthis.vshader = null;\\n\\t\\tthis.fshader = null;\\n\\t}\\n\\tfDefineSet(condition, name, value = \\\"\\\") {\\n\\t\\tif (condition) {\\n\\t\\t\\tthis.fDefines.set(name, value);\\n\\t\\t}\\n\\t}\\n\\tgenerateVertexShader(useUv, useUnmodifiedUv, mapTransforms) {\\n\\t\\tconst { options, vDefines, attributes } = this;\\n\\t\\tconst varyings = /* @__PURE__ */ new Map();\\n\\t\\tvaryings.set(\\\"vPositionW\\\", \\\"vec3\\\");\\n\\t\\tif (options.nineSlicedMode === SPRITE_RENDERMODE_SLICED || options.nineSlicedMode === SPRITE_RENDERMODE_TILED) {\\n\\t\\t\\tvDefines.set(\\\"NINESLICED\\\", true);\\n\\t\\t}\\n\\t\\tif (this.options.linearDepth) {\\n\\t\\t\\tvDefines.set(\\\"LINEAR_DEPTH\\\", true);\\n\\t\\t\\tvaryings.set(\\\"vLinearDepth\\\", \\\"float\\\");\\n\\t\\t}\\n\\t\\tif (this.needsNormal) vDefines.set(\\\"NORMALS\\\", true);\\n\\t\\tif (this.options.useInstancing) {\\n\\t\\t\\tconst languageChunks = ShaderChunks.get(this.device, this.shaderLanguage);\\n\\t\\t\\tif (this.chunks.get(\\\"transformInstancingVS\\\") === languageChunks.get(\\\"transformInstancingVS\\\")) {\\n\\t\\t\\t\\tattributes.instance_line1 = SEMANTIC_ATTR11;\\n\\t\\t\\t\\tattributes.instance_line2 = SEMANTIC_ATTR12;\\n\\t\\t\\t\\tattributes.instance_line3 = SEMANTIC_ATTR14;\\n\\t\\t\\t\\tattributes.instance_line4 = SEMANTIC_ATTR15;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this.needsNormal) {\\n\\t\\t\\tattributes.vertex_normal = SEMANTIC_NORMAL;\\n\\t\\t\\tvaryings.set(\\\"vNormalW\\\", \\\"vec3\\\");\\n\\t\\t\\tif (options.hasTangents && (options.useHeights || options.useNormals || options.useClearCoatNormals || options.enableGGXSpecular)) {\\n\\t\\t\\t\\tvDefines.set(\\\"TANGENTS\\\", true);\\n\\t\\t\\t\\tattributes.vertex_tangent = SEMANTIC_TANGENT;\\n\\t\\t\\t\\tvaryings.set(\\\"vTangentW\\\", \\\"vec3\\\");\\n\\t\\t\\t\\tvaryings.set(\\\"vBinormalW\\\", \\\"vec3\\\");\\n\\t\\t\\t} else if (options.enableGGXSpecular) {\\n\\t\\t\\t\\tvDefines.set(\\\"GGX_SPECULAR\\\", true);\\n\\t\\t\\t\\tvaryings.set(\\\"vObjectSpaceUpW\\\", \\\"vec3\\\");\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst maxUvSets = 2;\\n\\t\\tfor (let i = 0; i < maxUvSets; i++) {\\n\\t\\t\\tif (useUv[i]) {\\n\\t\\t\\t\\tvDefines.set(`UV${i}`, true);\\n\\t\\t\\t\\tattributes[`vertex_texCoord${i}`] = `TEXCOORD${i}`;\\n\\t\\t\\t}\\n\\t\\t\\tif (useUnmodifiedUv[i]) {\\n\\t\\t\\t\\tvDefines.set(`UV${i}_UNMODIFIED`, true);\\n\\t\\t\\t\\tvaryings.set(`vUv${i}`, \\\"vec2\\\");\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tlet numTransforms = 0;\\n\\t\\tconst transformDone = /* @__PURE__ */ new Set();\\n\\t\\tmapTransforms.forEach((mapTransform) => {\\n\\t\\t\\tconst { id, uv, name } = mapTransform;\\n\\t\\t\\tconst checkId = id + uv * 100;\\n\\t\\t\\tif (!transformDone.has(checkId)) {\\n\\t\\t\\t\\ttransformDone.add(checkId);\\n\\t\\t\\t\\tvaryings.set(`vUV${uv}_${id}`, \\\"vec2\\\");\\n\\t\\t\\t\\tconst varName = `texture_${name}MapTransform`;\\n\\t\\t\\t\\tvDefines.set(`{TRANSFORM_NAME_${numTransforms}}`, varName);\\n\\t\\t\\t\\tvDefines.set(`{TRANSFORM_UV_${numTransforms}}`, uv);\\n\\t\\t\\t\\tvDefines.set(`{TRANSFORM_ID_${numTransforms}}`, id);\\n\\t\\t\\t\\tnumTransforms++;\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tvDefines.set(\\\"UV_TRANSFORMS_COUNT\\\", numTransforms);\\n\\t\\tif (options.vertexColors) {\\n\\t\\t\\tattributes.vertex_color = SEMANTIC_COLOR;\\n\\t\\t\\tvDefines.set(\\\"VERTEX_COLOR\\\", true);\\n\\t\\t\\tvaryings.set(\\\"vVertexColor\\\", \\\"vec4\\\");\\n\\t\\t\\tif (options.useVertexColorGamma) {\\n\\t\\t\\t\\tvDefines.set(\\\"STD_VERTEX_COLOR_GAMMA\\\", \\\"\\\");\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (options.useMsdf && options.msdfTextAttribute) {\\n\\t\\t\\tattributes.vertex_outlineParameters = SEMANTIC_ATTR8;\\n\\t\\t\\tattributes.vertex_shadowParameters = SEMANTIC_ATTR9;\\n\\t\\t\\tvDefines.set(\\\"MSDF\\\", true);\\n\\t\\t}\\n\\t\\tif (options.useMorphPosition || options.useMorphNormal) {\\n\\t\\t\\tvDefines.set(\\\"MORPHING\\\", true);\\n\\t\\t\\tif (options.useMorphTextureBasedInt) vDefines.set(\\\"MORPHING_INT\\\", true);\\n\\t\\t\\tif (options.useMorphPosition) vDefines.set(\\\"MORPHING_POSITION\\\", true);\\n\\t\\t\\tif (options.useMorphNormal) vDefines.set(\\\"MORPHING_NORMAL\\\", true);\\n\\t\\t\\tattributes.morph_vertex_id = SEMANTIC_ATTR15;\\n\\t\\t}\\n\\t\\tif (options.skin) {\\n\\t\\t\\tattributes.vertex_boneIndices = SEMANTIC_BLENDINDICES;\\n\\t\\t\\tif (options.batch) {\\n\\t\\t\\t\\tvDefines.set(\\\"BATCH\\\", true);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tattributes.vertex_boneWeights = SEMANTIC_BLENDWEIGHT;\\n\\t\\t\\t\\tvDefines.set(\\\"SKIN\\\", true);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (options.useInstancing) vDefines.set(\\\"INSTANCING\\\", true);\\n\\t\\tif (options.screenSpace) vDefines.set(\\\"SCREENSPACE\\\", true);\\n\\t\\tif (options.pixelSnap) vDefines.set(\\\"PIXELSNAP\\\", true);\\n\\t\\tvaryings.forEach((type, name) => {\\n\\t\\t\\tthis.varyingsCode += `#define VARYING_${name.toUpperCase()}\\n`;\\n\\t\\t\\tthis.varyingsCode += this.shaderLanguage === SHADERLANGUAGE_WGSL ? `varying ${name}: ${primitiveGlslToWgslTypeMap.get(type)};\\n` : `varying ${type} ${name};\\n`;\\n\\t\\t});\\n\\t\\tthis.includes.set(\\\"varyingsVS\\\", this.varyingsCode);\\n\\t\\tthis.includes.set(\\\"varyingsPS\\\", this.varyingsCode);\\n\\t\\tthis.vshader = `\\n\\t\\t\\t\\t\\t\\t#include \\\"litMainVS\\\"\\n\\t\\t\\t\\t`;\\n\\t}\\n\\t_setupLightingDefines(hasAreaLights, clusteredLightingEnabled) {\\n\\t\\tconst fDefines = this.fDefines;\\n\\t\\tconst options = this.options;\\n\\t\\tthis.fDefines.set(\\\"LIGHT_COUNT\\\", options.lights.length);\\n\\t\\tif (hasAreaLights) fDefines.set(\\\"AREA_LIGHTS\\\", true);\\n\\t\\tif (clusteredLightingEnabled && this.lighting) {\\n\\t\\t\\tfDefines.set(\\\"LIT_CLUSTERED_LIGHTS\\\", true);\\n\\t\\t\\tif (options.clusteredLightingCookiesEnabled) fDefines.set(\\\"CLUSTER_COOKIES\\\", true);\\n\\t\\t\\tif (options.clusteredLightingAreaLightsEnabled) fDefines.set(\\\"CLUSTER_AREALIGHTS\\\", true);\\n\\t\\t\\tif (options.lightMaskDynamic) fDefines.set(\\\"CLUSTER_MESH_DYNAMIC_LIGHTS\\\", true);\\n\\t\\t\\tif (options.clusteredLightingShadowsEnabled && !options.noShadow) {\\n\\t\\t\\t\\tconst clusteredShadowInfo = shadowTypeInfo.get(options.clusteredLightingShadowType);\\n\\t\\t\\t\\tfDefines.set(\\\"CLUSTER_SHADOWS\\\", true);\\n\\t\\t\\t\\tfDefines.set(`SHADOW_KIND_${clusteredShadowInfo.kind}`, true);\\n\\t\\t\\t\\tfDefines.set(`CLUSTER_SHADOW_TYPE_${clusteredShadowInfo.kind}`, true);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < options.lights.length; i++) {\\n\\t\\t\\tconst light = options.lights[i];\\n\\t\\t\\tconst lightType = light._type;\\n\\t\\t\\tif (clusteredLightingEnabled && lightType !== LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tconst lightShape = hasAreaLights && light._shape ? light._shape : LIGHTSHAPE_PUNCTUAL;\\n\\t\\t\\tconst shadowType = light._shadowType;\\n\\t\\t\\tconst castShadow = light.castShadows && !options.noShadow;\\n\\t\\t\\tconst shadowInfo = shadowTypeInfo.get(shadowType);\\n\\t\\t\\tfDefines.set(`LIGHT${i}`, true);\\n\\t\\t\\tfDefines.set(`LIGHT${i}TYPE`, `${lightTypeNames[lightType]}`);\\n\\t\\t\\tfDefines.set(`LIGHT${i}SHADOWTYPE`, `${shadowInfo.name}`);\\n\\t\\t\\tfDefines.set(`LIGHT${i}SHAPE`, `${lightShapeNames[lightShape]}`);\\n\\t\\t\\tfDefines.set(`LIGHT${i}FALLOFF`, `${lightFalloffNames[light._falloffMode]}`);\\n\\t\\t\\tif (light.affectSpecularity) fDefines.set(`LIGHT${i}AFFECT_SPECULARITY`, true);\\n\\t\\t\\tif (light._cookie) {\\n\\t\\t\\t\\tif (lightType === LIGHTTYPE_SPOT && !light._cookie._cubemap || lightType === LIGHTTYPE_OMNI && light._cookie._cubemap) {\\n\\t\\t\\t\\t\\tfDefines.set(`LIGHT${i}COOKIE`, true);\\n\\t\\t\\t\\t\\tfDefines.set(`{LIGHT${i}COOKIE_CHANNEL}`, light._cookieChannel);\\n\\t\\t\\t\\t\\tif (lightType === LIGHTTYPE_SPOT) {\\n\\t\\t\\t\\t\\t\\tif (light._cookieTransform) fDefines.set(`LIGHT${i}COOKIE_TRANSFORM`, true);\\n\\t\\t\\t\\t\\t\\tif (light._cookieFalloff) fDefines.set(`LIGHT${i}COOKIE_FALLOFF`, true);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (castShadow) {\\n\\t\\t\\t\\tfDefines.set(`LIGHT${i}CASTSHADOW`, true);\\n\\t\\t\\t\\tif (shadowInfo.pcf) fDefines.set(`LIGHT${i}SHADOW_PCF`, true);\\n\\t\\t\\t\\tif (light._normalOffsetBias && !light._isVsm) fDefines.set(`LIGHT${i}_SHADOW_SAMPLE_NORMAL_OFFSET`, true);\\n\\t\\t\\t\\tif (lightType === LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\tfDefines.set(`LIGHT${i}_SHADOW_SAMPLE_ORTHO`, true);\\n\\t\\t\\t\\t\\tif (light.cascadeBlend > 0) fDefines.set(`LIGHT${i}_SHADOW_CASCADE_BLEND`, true);\\n\\t\\t\\t\\t\\tif (light.numCascades > 1) fDefines.set(`LIGHT${i}_SHADOW_CASCADES`, true);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (shadowInfo.pcf || shadowInfo.pcss || this.device.isWebGPU) fDefines.set(`LIGHT${i}_SHADOW_SAMPLE_SOURCE_ZBUFFER`, true);\\n\\t\\t\\t\\tif (lightType === LIGHTTYPE_OMNI) fDefines.set(`LIGHT${i}_SHADOW_SAMPLE_POINT`, true);\\n\\t\\t\\t}\\n\\t\\t\\tif (castShadow) {\\n\\t\\t\\t\\tfDefines.set(`SHADOW_KIND_${shadowInfo.kind}`, true);\\n\\t\\t\\t\\tif (lightType === LIGHTTYPE_DIRECTIONAL) fDefines.set(\\\"SHADOW_DIRECTIONAL\\\", true);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tprepareForwardPass(lightingUv) {\\n\\t\\tconst { options } = this;\\n\\t\\tconst clusteredAreaLights = options.clusteredLightingEnabled && options.clusteredLightingAreaLightsEnabled;\\n\\t\\tconst hasAreaLights = clusteredAreaLights || options.lights.some((light) => {\\n\\t\\t\\treturn light._shape && light._shape !== LIGHTSHAPE_PUNCTUAL;\\n\\t\\t});\\n\\t\\tconst addAmbient = !options.lightMapEnabled || options.lightMapWithoutAmbient;\\n\\t\\tconst hasTBN = this.needsNormal && (options.useNormals || options.useClearCoatNormals || options.enableGGXSpecular && !options.useHeights);\\n\\t\\tif (options.useSpecular) {\\n\\t\\t\\tthis.fDefineSet(true, \\\"LIT_SPECULAR\\\");\\n\\t\\t\\tthis.fDefineSet(this.reflections, \\\"LIT_REFLECTIONS\\\");\\n\\t\\t\\tthis.fDefineSet(options.useClearCoat, \\\"LIT_CLEARCOAT\\\");\\n\\t\\t\\tthis.fDefineSet(options.fresnelModel > 0, \\\"LIT_SPECULAR_FRESNEL\\\");\\n\\t\\t\\tthis.fDefineSet(options.useSheen, \\\"LIT_SHEEN\\\");\\n\\t\\t\\tthis.fDefineSet(options.useIridescence, \\\"LIT_IRIDESCENCE\\\");\\n\\t\\t}\\n\\t\\tthis.fDefineSet(this.lighting && options.useSpecular || this.reflections, \\\"LIT_SPECULAR_OR_REFLECTION\\\");\\n\\t\\tthis.fDefineSet(this.needsSceneColor, \\\"LIT_SCENE_COLOR\\\");\\n\\t\\tthis.fDefineSet(this.needsScreenSize, \\\"LIT_SCREEN_SIZE\\\");\\n\\t\\tthis.fDefineSet(this.needsTransforms, \\\"LIT_TRANSFORMS\\\");\\n\\t\\tthis.fDefineSet(this.needsNormal, \\\"LIT_NEEDS_NORMAL\\\");\\n\\t\\tthis.fDefineSet(this.lighting, \\\"LIT_LIGHTING\\\");\\n\\t\\tthis.fDefineSet(options.useMetalness, \\\"LIT_METALNESS\\\");\\n\\t\\tthis.fDefineSet(options.enableGGXSpecular, \\\"LIT_GGX_SPECULAR\\\");\\n\\t\\tthis.fDefineSet(options.useAnisotropy, \\\"LIT_ANISOTROPY\\\");\\n\\t\\tthis.fDefineSet(options.useSpecularityFactor, \\\"LIT_SPECULARITY_FACTOR\\\");\\n\\t\\tthis.fDefineSet(options.useCubeMapRotation, \\\"CUBEMAP_ROTATION\\\");\\n\\t\\tthis.fDefineSet(options.occludeSpecularFloat, \\\"LIT_OCCLUDE_SPECULAR_FLOAT\\\");\\n\\t\\tthis.fDefineSet(options.separateAmbient, \\\"LIT_SEPARATE_AMBIENT\\\");\\n\\t\\tthis.fDefineSet(options.twoSidedLighting, \\\"LIT_TWO_SIDED_LIGHTING\\\");\\n\\t\\tthis.fDefineSet(options.lightMapEnabled, \\\"LIT_LIGHTMAP\\\");\\n\\t\\tthis.fDefineSet(options.dirLightMapEnabled, \\\"LIT_DIR_LIGHTMAP\\\");\\n\\t\\tthis.fDefineSet(options.skyboxIntensity > 0, \\\"LIT_SKYBOX_INTENSITY\\\");\\n\\t\\tthis.fDefineSet(options.clusteredLightingShadowsEnabled, \\\"LIT_CLUSTERED_SHADOWS\\\");\\n\\t\\tthis.fDefineSet(options.clusteredLightingAreaLightsEnabled, \\\"LIT_CLUSTERED_AREA_LIGHTS\\\");\\n\\t\\tthis.fDefineSet(hasTBN, \\\"LIT_TBN\\\");\\n\\t\\tthis.fDefineSet(addAmbient, \\\"LIT_ADD_AMBIENT\\\");\\n\\t\\tthis.fDefineSet(options.hasTangents, \\\"LIT_TANGENTS\\\");\\n\\t\\tthis.fDefineSet(options.useNormals, \\\"LIT_USE_NORMALS\\\");\\n\\t\\tthis.fDefineSet(options.useClearCoatNormals, \\\"LIT_USE_CLEARCOAT_NORMALS\\\");\\n\\t\\tthis.fDefineSet(options.useRefraction, \\\"LIT_REFRACTION\\\");\\n\\t\\tthis.fDefineSet(options.useDynamicRefraction, \\\"LIT_DYNAMIC_REFRACTION\\\");\\n\\t\\tthis.fDefineSet(options.dispersion, \\\"LIT_DISPERSION\\\");\\n\\t\\tthis.fDefineSet(options.useHeights, \\\"LIT_HEIGHTS\\\");\\n\\t\\tthis.fDefineSet(options.opacityFadesSpecular, \\\"LIT_OPACITY_FADES_SPECULAR\\\");\\n\\t\\tthis.fDefineSet(options.alphaToCoverage, \\\"LIT_ALPHA_TO_COVERAGE\\\");\\n\\t\\tthis.fDefineSet(options.alphaTest, \\\"LIT_ALPHA_TEST\\\");\\n\\t\\tthis.fDefineSet(options.useMsdf, \\\"LIT_MSDF\\\");\\n\\t\\tthis.fDefineSet(options.ssao, \\\"LIT_SSAO\\\");\\n\\t\\tthis.fDefineSet(options.useAo, \\\"LIT_AO\\\");\\n\\t\\tthis.fDefineSet(options.occludeDirect, \\\"LIT_OCCLUDE_DIRECT\\\");\\n\\t\\tthis.fDefineSet(options.msdfTextAttribute, \\\"LIT_MSDF_TEXT_ATTRIBUTE\\\");\\n\\t\\tthis.fDefineSet(options.diffuseMapEnabled, \\\"LIT_DIFFUSE_MAP\\\");\\n\\t\\tthis.fDefineSet(options.shadowCatcher, \\\"LIT_SHADOW_CATCHER\\\");\\n\\t\\tthis.fDefineSet(true, \\\"LIT_FRESNEL_MODEL\\\", fresnelNames[options.fresnelModel]);\\n\\t\\tthis.fDefineSet(true, \\\"LIT_NONE_SLICE_MODE\\\", spriteRenderModeNames[options.nineSlicedMode]);\\n\\t\\tthis.fDefineSet(true, \\\"LIT_BLEND_TYPE\\\", blendNames[options.blendType]);\\n\\t\\tthis.fDefineSet(true, \\\"LIT_CUBEMAP_PROJECTION\\\", cubemaProjectionNames[options.cubeMapProjection]);\\n\\t\\tthis.fDefineSet(true, \\\"LIT_OCCLUDE_SPECULAR\\\", specularOcclusionNames[options.occludeSpecular]);\\n\\t\\tthis.fDefineSet(true, \\\"LIT_REFLECTION_SOURCE\\\", reflectionSrcNames[options.reflectionSource]);\\n\\t\\tthis.fDefineSet(true, \\\"LIT_AMBIENT_SOURCE\\\", ambientSrcNames[options.ambientSource]);\\n\\t\\tthis.fDefineSet(true, \\\"{lightingUv}\\\", lightingUv ?? \\\"\\\");\\n\\t\\tthis.fDefineSet(true, \\\"{reflectionDecode}\\\", ChunkUtils.decodeFunc(options.reflectionEncoding));\\n\\t\\tthis.fDefineSet(true, \\\"{reflectionCubemapDecode}\\\", ChunkUtils.decodeFunc(options.reflectionCubemapEncoding));\\n\\t\\tthis.fDefineSet(true, \\\"{ambientDecode}\\\", ChunkUtils.decodeFunc(options.ambientEncoding));\\n\\t\\tthis._setupLightingDefines(hasAreaLights, options.clusteredLightingEnabled);\\n\\t}\\n\\tpreparePrepassPass() {\\n\\t\\tconst { options } = this;\\n\\t\\tthis.fDefineSet(options.alphaTest, \\\"LIT_ALPHA_TEST\\\");\\n\\t\\tthis.fDefineSet(true, \\\"STD_OPACITY_DITHER\\\", ditherNames[options.opacityShadowDither]);\\n\\t}\\n\\tprepareShadowPass() {\\n\\t\\tconst { options } = this;\\n\\t\\tconst lightType = this.shaderPassInfo.lightType;\\n\\t\\tconst shadowType = this.shaderPassInfo.shadowType;\\n\\t\\tconst shadowInfo = shadowTypeInfo.get(shadowType);\\n\\t\\tconst usePerspectiveDepth = lightType === LIGHTTYPE_DIRECTIONAL || !shadowInfo.vsm && lightType === LIGHTTYPE_SPOT;\\n\\t\\tthis.fDefineSet(usePerspectiveDepth, \\\"PERSPECTIVE_DEPTH\\\");\\n\\t\\tthis.fDefineSet(true, \\\"LIGHT_TYPE\\\", `${lightTypeNames[lightType]}`);\\n\\t\\tthis.fDefineSet(true, \\\"SHADOW_TYPE\\\", `${shadowInfo.name}`);\\n\\t\\tthis.fDefineSet(options.alphaTest, \\\"LIT_ALPHA_TEST\\\");\\n\\t}\\n\\tgenerateFragmentShader(frontendDecl, frontendCode, lightingUv) {\\n\\t\\tconst options = this.options;\\n\\t\\tthis.includes.set(\\\"frontendDeclPS\\\", frontendDecl ?? \\\"\\\");\\n\\t\\tthis.includes.set(\\\"frontendCodePS\\\", frontendCode ?? \\\"\\\");\\n\\t\\tif (options.pass === SHADER_PICK) ; else if (options.pass === SHADER_PREPASS) {\\n\\t\\t\\tthis.preparePrepassPass();\\n\\t\\t} else if (this.shadowPass) {\\n\\t\\t\\tthis.prepareShadowPass();\\n\\t\\t} else {\\n\\t\\t\\tthis.prepareForwardPass(lightingUv);\\n\\t\\t}\\n\\t\\tthis.fshader = `\\n\\t\\t\\t\\t\\t\\t#include \\\"litMainPS\\\"\\n\\t\\t\\t\\t`;\\n\\t}\\n}\\n\\nconst LitOptionsUtils = {\\n\\t// generate a key for the lit options\\n\\tgenerateKey(options) {\\n\\t\\treturn `lit${Object.keys(options).sort().map((key) => {\\n\\t\\t\\tif (key === \\\"shaderChunks\\\") {\\n\\t\\t\\t\\treturn options.shaderChunks?.key ?? \\\"\\\";\\n\\t\\t\\t} else if (key === \\\"lights\\\") {\\n\\t\\t\\t\\treturn LitOptionsUtils.generateLightsKey(options);\\n\\t\\t\\t}\\n\\t\\t\\treturn key + options[key];\\n\\t\\t}).join(\\\"\\\\n\\\")}`;\\n\\t},\\n\\tgenerateLightsKey(options) {\\n\\t\\treturn `lights:${options.lights.map((light) => {\\n\\t\\t\\treturn !options.clusteredLightingEnabled || light._type === LIGHTTYPE_DIRECTIONAL ? `${light.key},` : \\\"\\\";\\n\\t\\t}).join(\\\"\\\")}`;\\n\\t}\\n};\\n\\nclass StandardMaterialOptions {\\n\\tdefines = /* @__PURE__ */ new Map();\\n\\tforceUv1 = false;\\n\\tspecularTint = false;\\n\\tmetalnessTint = false;\\n\\tglossTint = false;\\n\\temissiveEncoding = \\\"linear\\\";\\n\\tlightMapEncoding = \\\"linear\\\";\\n\\tvertexColorGamma = false;\\n\\tpackedNormal = false;\\n\\tnormalDetailPackedNormal = false;\\n\\tclearCoatPackedNormal = false;\\n\\tglossInvert = false;\\n\\tsheenGlossInvert = false;\\n\\tclearCoatGlossInvert = false;\\n\\tuseAO = false;\\n\\tlitOptions = new LitShaderOptions();\\n\\t// program-library assumes material options has a pass property\\n\\tget pass() {\\n\\t\\treturn this.litOptions.pass;\\n\\t}\\n}\\n\\nconst _matTex2D = [];\\nconst buildPropertiesList = (options) => {\\n\\treturn Object.keys(options).filter((key) => key !== \\\"litOptions\\\").sort();\\n};\\nclass ShaderGeneratorStandard extends ShaderGenerator {\\n\\t// Shared Standard Material option structures\\n\\toptionsContext = new StandardMaterialOptions();\\n\\toptionsContextMin = new StandardMaterialOptions();\\n\\tgenerateKey(options) {\\n\\t\\tlet props;\\n\\t\\tif (options === this.optionsContextMin) {\\n\\t\\t\\tif (!this.propsMin) this.propsMin = buildPropertiesList(options);\\n\\t\\t\\tprops = this.propsMin;\\n\\t\\t} else if (options === this.optionsContext) {\\n\\t\\t\\tif (!this.props) this.props = buildPropertiesList(options);\\n\\t\\t\\tprops = this.props;\\n\\t\\t} else {\\n\\t\\t\\tprops = buildPropertiesList(options);\\n\\t\\t}\\n\\t\\tconst definesHash = ShaderGenerator.definesHash(options.defines);\\n\\t\\tconst key = `standard:\\n${definesHash}\\n${props.map((prop) => prop + options[prop]).join(\\\"\\\\n\\\")}${LitOptionsUtils.generateKey(options.litOptions)}`;\\n\\t\\treturn key;\\n\\t}\\n\\t_getUvSourceExpression(transformPropName, uVPropName, options) {\\n\\t\\tconst transformId = options[transformPropName];\\n\\t\\tconst uvChannel = options[uVPropName];\\n\\t\\tconst isMainPass = options.litOptions.pass === SHADER_FORWARD;\\n\\t\\tlet expression;\\n\\t\\tif (isMainPass && options.litOptions.nineSlicedMode === SPRITE_RENDERMODE_SLICED) {\\n\\t\\t\\texpression = \\\"nineSlicedUv\\\";\\n\\t\\t} else if (isMainPass && options.litOptions.nineSlicedMode === SPRITE_RENDERMODE_TILED) {\\n\\t\\t\\texpression = \\\"nineSlicedUv\\\";\\n\\t\\t} else {\\n\\t\\t\\tif (transformId === 0) {\\n\\t\\t\\t\\texpression = `vUv${uvChannel}`;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\texpression = `vUV${uvChannel}_${transformId}`;\\n\\t\\t\\t}\\n\\t\\t\\tif (options.heightMap && transformPropName !== \\\"heightMapTransform\\\") {\\n\\t\\t\\t\\texpression += \\\" + dUvOffset\\\";\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn expression;\\n\\t}\\n\\t_validateMapChunk(code, propName, chunkName, chunks) {\\n\\t}\\n\\t_addMapDefines(fDefines, propName, chunkName, options, chunks, mapping, encoding = null) {\\n\\t\\tconst mapPropName = `${propName}Map`;\\n\\t\\tconst propNameCaps = propName.toUpperCase();\\n\\t\\tconst uVPropName = `${mapPropName}Uv`;\\n\\t\\tconst identifierPropName = `${mapPropName}Identifier`;\\n\\t\\tconst transformPropName = `${mapPropName}Transform`;\\n\\t\\tconst channelPropName = `${mapPropName}Channel`;\\n\\t\\tconst vertexColorChannelPropName = `${propName}VertexColorChannel`;\\n\\t\\tconst tintPropName = `${propName}Tint`;\\n\\t\\tconst vertexColorPropName = `${propName}VertexColor`;\\n\\t\\tconst detailModePropName = `${propName}Mode`;\\n\\t\\tconst invertName = `${propName}Invert`;\\n\\t\\tconst tintOption = options[tintPropName];\\n\\t\\tconst vertexColorOption = options[vertexColorPropName];\\n\\t\\tconst textureOption = options[mapPropName];\\n\\t\\tconst textureIdentifier = options[identifierPropName];\\n\\t\\tconst detailModeOption = options[detailModePropName];\\n\\t\\tconst chunkCode = chunks.get(chunkName);\\n\\t\\tif (textureOption) {\\n\\t\\t\\tfDefines.set(`STD_${propNameCaps}_TEXTURE`, \\\"\\\");\\n\\t\\t\\tconst uv = this._getUvSourceExpression(transformPropName, uVPropName, options);\\n\\t\\t\\tfDefines.set(`{STD_${propNameCaps}_TEXTURE_UV}`, uv);\\n\\t\\t\\tfDefines.set(`{STD_${propNameCaps}_TEXTURE_CHANNEL}`, options[channelPropName]);\\n\\t\\t\\tconst textureId = `{STD_${propNameCaps}_TEXTURE_NAME}`;\\n\\t\\t\\tif (chunkCode.includes(textureId)) {\\n\\t\\t\\t\\tlet samplerName = `texture_${mapPropName}`;\\n\\t\\t\\t\\tconst alias = mapping[textureIdentifier];\\n\\t\\t\\t\\tif (alias) {\\n\\t\\t\\t\\t\\tsamplerName = alias;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tmapping[textureIdentifier] = samplerName;\\n\\t\\t\\t\\t\\tfDefines.set(`STD_${propNameCaps}_TEXTURE_ALLOCATE`, \\\"\\\");\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfDefines.set(textureId, samplerName);\\n\\t\\t\\t}\\n\\t\\t\\tif (encoding) {\\n\\t\\t\\t\\tconst textureDecode = options[channelPropName] === \\\"aaa\\\" ? \\\"passThrough\\\" : ChunkUtils.decodeFunc(encoding);\\n\\t\\t\\t\\tfDefines.set(`{STD_${propNameCaps}_TEXTURE_DECODE}`, textureDecode);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (vertexColorOption) {\\n\\t\\t\\tfDefines.set(`STD_${propNameCaps}_VERTEX`, \\\"\\\");\\n\\t\\t\\tfDefines.set(`{STD_${propNameCaps}_VERTEX_CHANNEL}`, options[vertexColorChannelPropName]);\\n\\t\\t}\\n\\t\\tif (detailModeOption) {\\n\\t\\t\\tfDefines.set(`{STD_${propNameCaps}_DETAILMODE}`, detailModeOption);\\n\\t\\t}\\n\\t\\tif (tintOption) {\\n\\t\\t\\tfDefines.set(`STD_${propNameCaps}_CONSTANT`, \\\"\\\");\\n\\t\\t}\\n\\t\\tif (!!options[invertName]) {\\n\\t\\t\\tfDefines.set(`STD_${propNameCaps}_INVERT`, \\\"\\\");\\n\\t\\t}\\n\\t}\\n\\t_correctChannel(p, chan, _matTex2D2) {\\n\\t\\tif (_matTex2D2[p] > 0) {\\n\\t\\t\\tif (_matTex2D2[p] < chan.length) {\\n\\t\\t\\t\\treturn chan.substring(0, _matTex2D2[p]);\\n\\t\\t\\t} else if (_matTex2D2[p] > chan.length) {\\n\\t\\t\\t\\tlet str = chan;\\n\\t\\t\\t\\tconst chr = str.charAt(str.length - 1);\\n\\t\\t\\t\\tconst addLen = _matTex2D2[p] - str.length;\\n\\t\\t\\t\\tfor (let i = 0; i < addLen; i++) str += chr;\\n\\t\\t\\t\\treturn str;\\n\\t\\t\\t}\\n\\t\\t\\treturn chan;\\n\\t\\t}\\n\\t}\\n\\tcreateVertexShader(litShader, options) {\\n\\t\\tconst useUv = [];\\n\\t\\tconst useUnmodifiedUv = [];\\n\\t\\tconst mapTransforms = [];\\n\\t\\tconst maxUvSets = 2;\\n\\t\\tfor (const p in _matTex2D) {\\n\\t\\t\\tconst mapName = `${p}Map`;\\n\\t\\t\\tif (options[`${p}VertexColor`]) {\\n\\t\\t\\t\\tconst colorChannelName = `${p}VertexColorChannel`;\\n\\t\\t\\t\\toptions[colorChannelName] = this._correctChannel(p, options[colorChannelName], _matTex2D);\\n\\t\\t\\t}\\n\\t\\t\\tif (options[mapName]) {\\n\\t\\t\\t\\tconst channelName = `${mapName}Channel`;\\n\\t\\t\\t\\tconst transformName = `${mapName}Transform`;\\n\\t\\t\\t\\tconst uvName = `${mapName}Uv`;\\n\\t\\t\\t\\toptions[uvName] = Math.min(options[uvName], maxUvSets - 1);\\n\\t\\t\\t\\toptions[channelName] = this._correctChannel(p, options[channelName], _matTex2D);\\n\\t\\t\\t\\tconst uvSet = options[uvName];\\n\\t\\t\\t\\tuseUv[uvSet] = true;\\n\\t\\t\\t\\tuseUnmodifiedUv[uvSet] = useUnmodifiedUv[uvSet] || options[mapName] && !options[transformName];\\n\\t\\t\\t\\tif (options[transformName]) {\\n\\t\\t\\t\\t\\tmapTransforms.push({\\n\\t\\t\\t\\t\\t\\tname: p,\\n\\t\\t\\t\\t\\t\\tid: options[transformName],\\n\\t\\t\\t\\t\\t\\tuv: options[uvName]\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (options.forceUv1) {\\n\\t\\t\\tuseUv[1] = true;\\n\\t\\t\\tuseUnmodifiedUv[1] = useUnmodifiedUv[1] !== void 0 ? useUnmodifiedUv[1] : true;\\n\\t\\t}\\n\\t\\tlitShader.generateVertexShader(useUv, useUnmodifiedUv, mapTransforms);\\n\\t}\\n\\tprepareFragmentDefines(options, fDefines, shaderPassInfo) {\\n\\t\\tconst fDefineSet = (condition, name, value = \\\"\\\") => {\\n\\t\\t\\tif (condition) {\\n\\t\\t\\t\\tfDefines.set(name, value);\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tfDefineSet(options.lightMap, \\\"STD_LIGHTMAP\\\", \\\"\\\");\\n\\t\\tfDefineSet(options.lightVertexColor, \\\"STD_LIGHT_VERTEX_COLOR\\\", \\\"\\\");\\n\\t\\tfDefineSet(options.dirLightMap && options.litOptions.useSpecular, \\\"STD_LIGHTMAP_DIR\\\", \\\"\\\");\\n\\t\\tfDefineSet(options.heightMap, \\\"STD_HEIGHT_MAP\\\", \\\"\\\");\\n\\t\\tfDefineSet(options.useSpecularColor, \\\"STD_SPECULAR_COLOR\\\", \\\"\\\");\\n\\t\\tfDefineSet(options.aoMap || options.aoVertexColor || options.useAO, \\\"STD_AO\\\", \\\"\\\");\\n\\t\\tfDefineSet(true, \\\"STD_OPACITY_DITHER\\\", ditherNames[shaderPassInfo.isForward ? options.litOptions.opacityDither : options.litOptions.opacityShadowDither]);\\n\\t}\\n\\tcreateShaderDefinition(device, options) {\\n\\t\\tconst shaderPassInfo = ShaderPass.get(device).getByIndex(options.litOptions.pass);\\n\\t\\tconst isForwardPass = shaderPassInfo.isForward;\\n\\t\\tconst litShader = new LitShader(device, options.litOptions);\\n\\t\\tthis.createVertexShader(litShader, options);\\n\\t\\tconst textureMapping = {};\\n\\t\\toptions.litOptions.fresnelModel = options.litOptions.fresnelModel === 0 ? FRESNEL_SCHLICK : options.litOptions.fresnelModel;\\n\\t\\tconst fDefines = litShader.fDefines;\\n\\t\\tthis.prepareFragmentDefines(options, fDefines, shaderPassInfo);\\n\\t\\tlet lightingUv = \\\"\\\";\\n\\t\\tif (isForwardPass) {\\n\\t\\t\\tif (options.heightMap) {\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"height\\\", \\\"parallaxPS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t}\\n\\t\\t\\tif (options.litOptions.blendType !== BLEND_NONE || options.litOptions.alphaTest || options.litOptions.alphaToCoverage || options.litOptions.opacityDither !== DITHER_NONE) {\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"opacity\\\", \\\"opacityPS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t}\\n\\t\\t\\tif (litShader.needsNormal) {\\n\\t\\t\\t\\tif (options.normalMap || options.clearCoatNormalMap) {\\n\\t\\t\\t\\t\\tif (!options.litOptions.hasTangents) {\\n\\t\\t\\t\\t\\t\\tconst baseName = options.normalMap ? \\\"normalMap\\\" : \\\"clearCoatNormalMap\\\";\\n\\t\\t\\t\\t\\t\\tlightingUv = this._getUvSourceExpression(`${baseName}Transform`, `${baseName}Uv`, options);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"normalDetail\\\", \\\"normalMapPS\\\", options, litShader.chunks, textureMapping, options.normalDetailPackedNormal ? \\\"xy\\\" : \\\"xyz\\\");\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"normal\\\", \\\"normalMapPS\\\", options, litShader.chunks, textureMapping, options.packedNormal ? \\\"xy\\\" : \\\"xyz\\\");\\n\\t\\t\\t}\\n\\t\\t\\tif (options.diffuseDetail) {\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"diffuseDetail\\\", \\\"diffusePS\\\", options, litShader.chunks, textureMapping, options.diffuseDetailEncoding);\\n\\t\\t\\t}\\n\\t\\t\\tthis._addMapDefines(fDefines, \\\"diffuse\\\", \\\"diffusePS\\\", options, litShader.chunks, textureMapping, options.diffuseEncoding);\\n\\t\\t\\tif (options.litOptions.useRefraction) {\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"refraction\\\", \\\"transmissionPS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"thickness\\\", \\\"thicknessPS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t}\\n\\t\\t\\tif (options.litOptions.useIridescence) {\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"iridescence\\\", \\\"iridescencePS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"iridescenceThickness\\\", \\\"iridescenceThicknessPS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t}\\n\\t\\t\\tif (litShader.lighting && options.litOptions.useSpecular || litShader.reflections) {\\n\\t\\t\\t\\tif (options.litOptions.useSheen) {\\n\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"sheen\\\", \\\"sheenPS\\\", options, litShader.chunks, textureMapping, options.sheenEncoding);\\n\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"sheenGloss\\\", \\\"sheenGlossPS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.litOptions.useMetalness) {\\n\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"metalness\\\", \\\"metalnessPS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"ior\\\", \\\"iorPS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.litOptions.useSpecularityFactor) {\\n\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"specularityFactor\\\", \\\"specularityFactorPS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.useSpecularColor) {\\n\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"specular\\\", \\\"specularPS\\\", options, litShader.chunks, textureMapping, options.specularEncoding);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"gloss\\\", \\\"glossPS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t}\\n\\t\\t\\tif (options.aoDetail) {\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"aoDetail\\\", \\\"aoPS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t}\\n\\t\\t\\tif (options.aoMap || options.aoVertexColor || options.useAO) {\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"ao\\\", \\\"aoPS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t}\\n\\t\\t\\tthis._addMapDefines(fDefines, \\\"emissive\\\", \\\"emissivePS\\\", options, litShader.chunks, textureMapping, options.emissiveEncoding);\\n\\t\\t\\tif (options.litOptions.useClearCoat) {\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"clearCoat\\\", \\\"clearCoatPS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"clearCoatGloss\\\", \\\"clearCoatGlossPS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"clearCoatNormal\\\", \\\"clearCoatNormalPS\\\", options, litShader.chunks, textureMapping, options.clearCoatPackedNormal ? \\\"xy\\\" : \\\"xyz\\\");\\n\\t\\t\\t}\\n\\t\\t\\tif (options.litOptions.enableGGXSpecular) {\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"anisotropy\\\", \\\"anisotropyPS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t}\\n\\t\\t\\tif (options.lightMap || options.lightVertexColor) {\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"light\\\", \\\"lightmapPS\\\", options, litShader.chunks, textureMapping, options.lightMapEncoding);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tconst opacityShadowDither = options.litOptions.opacityShadowDither;\\n\\t\\t\\tif (options.litOptions.alphaTest || opacityShadowDither) {\\n\\t\\t\\t\\tthis._addMapDefines(fDefines, \\\"opacity\\\", \\\"opacityPS\\\", options, litShader.chunks, textureMapping);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tlitShader.generateFragmentShader(litShader.chunks.get(\\\"stdDeclarationPS\\\"), litShader.chunks.get(\\\"stdFrontEndPS\\\"), lightingUv);\\n\\t\\tconst includes = MapUtils.merge(litShader.chunks, litShader.includes);\\n\\t\\tconst vDefines = litShader.vDefines;\\n\\t\\toptions.defines.forEach((value, key) => vDefines.set(key, value));\\n\\t\\toptions.defines.forEach((value, key) => fDefines.set(key, value));\\n\\t\\tconst definition = ShaderDefinitionUtils.createDefinition(device, {\\n\\t\\t\\tname: \\\"StandardShader\\\",\\n\\t\\t\\tattributes: litShader.attributes,\\n\\t\\t\\tshaderLanguage: litShader.shaderLanguage,\\n\\t\\t\\tvertexCode: litShader.vshader,\\n\\t\\t\\tfragmentCode: litShader.fshader,\\n\\t\\t\\tvertexIncludes: includes,\\n\\t\\t\\tfragmentIncludes: includes,\\n\\t\\t\\tfragmentDefines: fDefines,\\n\\t\\t\\tvertexDefines: vDefines\\n\\t\\t});\\n\\t\\tif (litShader.shaderPassInfo.isForward) {\\n\\t\\t\\tdefinition.tag = SHADERTAG_MATERIAL;\\n\\t\\t}\\n\\t\\treturn definition;\\n\\t}\\n}\\nconst standard = new ShaderGeneratorStandard();\\n\\nconst arraysEqual = (a, b) => {\\n\\tif (a.length !== b.length) {\\n\\t\\treturn false;\\n\\t}\\n\\tfor (let i = 0; i < a.length; ++i) {\\n\\t\\tif (a[i] !== b[i]) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t}\\n\\treturn true;\\n};\\nconst notWhite = (color) => {\\n\\treturn color.r !== 1 || color.g !== 1 || color.b !== 1;\\n};\\nconst notBlack = (color) => {\\n\\treturn color.r !== 0 || color.g !== 0 || color.b !== 0;\\n};\\nclass StandardMaterialOptionsBuilder {\\n\\tconstructor() {\\n\\t\\tthis._mapXForms = null;\\n\\t}\\n\\t// Minimal options for Depth and Shadow passes\\n\\tupdateMinRef(options, scene, stdMat, objDefs, pass, sortedLights) {\\n\\t\\tthis._updateSharedOptions(options, scene, stdMat, objDefs, pass);\\n\\t\\tthis._updateMinOptions(options, stdMat, pass);\\n\\t\\tthis._updateUVOptions(options, stdMat, objDefs, true);\\n\\t}\\n\\tupdateRef(options, scene, cameraShaderParams, stdMat, objDefs, pass, sortedLights) {\\n\\t\\tthis._updateSharedOptions(options, scene, stdMat, objDefs, pass);\\n\\t\\tthis._updateEnvOptions(options, stdMat, scene, cameraShaderParams);\\n\\t\\tthis._updateMaterialOptions(options, stdMat, scene);\\n\\t\\toptions.litOptions.hasTangents = objDefs && (objDefs & SHADERDEF_TANGENTS) !== 0;\\n\\t\\tthis._updateLightOptions(options, scene, stdMat, objDefs, sortedLights);\\n\\t\\tthis._updateUVOptions(options, stdMat, objDefs, false, cameraShaderParams);\\n\\t}\\n\\t_updateSharedOptions(options, scene, stdMat, objDefs, pass) {\\n\\t\\toptions.forceUv1 = stdMat.forceUv1;\\n\\t\\tif (stdMat.userAttributes) {\\n\\t\\t\\toptions.litOptions.userAttributes = Object.fromEntries(stdMat.userAttributes.entries());\\n\\t\\t}\\n\\t\\toptions.litOptions.shaderChunks = stdMat.shaderChunks;\\n\\t\\toptions.litOptions.pass = pass;\\n\\t\\toptions.litOptions.alphaTest = stdMat.alphaTest > 0;\\n\\t\\toptions.litOptions.blendType = stdMat.blendType;\\n\\t\\toptions.litOptions.screenSpace = objDefs && (objDefs & SHADERDEF_SCREENSPACE) !== 0;\\n\\t\\toptions.litOptions.skin = objDefs && (objDefs & SHADERDEF_SKIN) !== 0;\\n\\t\\toptions.litOptions.batch = objDefs && (objDefs & SHADERDEF_BATCH) !== 0;\\n\\t\\toptions.litOptions.useInstancing = objDefs && (objDefs & SHADERDEF_INSTANCING) !== 0;\\n\\t\\toptions.litOptions.useMorphPosition = objDefs && (objDefs & SHADERDEF_MORPH_POSITION) !== 0;\\n\\t\\toptions.litOptions.useMorphNormal = objDefs && (objDefs & SHADERDEF_MORPH_NORMAL) !== 0;\\n\\t\\toptions.litOptions.useMorphTextureBasedInt = objDefs && (objDefs & SHADERDEF_MORPH_TEXTURE_BASED_INT) !== 0;\\n\\t\\toptions.litOptions.nineSlicedMode = stdMat.nineSlicedMode || 0;\\n\\t\\tif (scene.clusteredLightingEnabled && stdMat.useLighting) {\\n\\t\\t\\toptions.litOptions.clusteredLightingEnabled = true;\\n\\t\\t\\toptions.litOptions.clusteredLightingCookiesEnabled = scene.lighting.cookiesEnabled;\\n\\t\\t\\toptions.litOptions.clusteredLightingShadowsEnabled = scene.lighting.shadowsEnabled;\\n\\t\\t\\toptions.litOptions.clusteredLightingShadowType = scene.lighting.shadowType;\\n\\t\\t\\toptions.litOptions.clusteredLightingAreaLightsEnabled = scene.lighting.areaLightsEnabled;\\n\\t\\t} else {\\n\\t\\t\\toptions.litOptions.clusteredLightingEnabled = false;\\n\\t\\t\\toptions.litOptions.clusteredLightingCookiesEnabled = false;\\n\\t\\t\\toptions.litOptions.clusteredLightingShadowsEnabled = false;\\n\\t\\t\\toptions.litOptions.clusteredLightingAreaLightsEnabled = false;\\n\\t\\t}\\n\\t}\\n\\t_updateUVOptions(options, stdMat, objDefs, minimalOptions, cameraShaderParams) {\\n\\t\\tlet hasUv0 = false;\\n\\t\\tlet hasUv1 = false;\\n\\t\\tlet hasVcolor = false;\\n\\t\\tif (objDefs) {\\n\\t\\t\\thasUv0 = (objDefs & SHADERDEF_UV0) !== 0;\\n\\t\\t\\thasUv1 = (objDefs & SHADERDEF_UV1) !== 0;\\n\\t\\t\\thasVcolor = (objDefs & SHADERDEF_VCOLOR) !== 0;\\n\\t\\t}\\n\\t\\toptions.litOptions.vertexColors = false;\\n\\t\\tthis._mapXForms = [];\\n\\t\\tconst uniqueTextureMap = {};\\n\\t\\tfor (const p in _matTex2D) {\\n\\t\\t\\tthis._updateTexOptions(options, stdMat, p, hasUv0, hasUv1, hasVcolor, minimalOptions, uniqueTextureMap);\\n\\t\\t}\\n\\t\\tthis._mapXForms = null;\\n\\t\\toptions.litOptions.ssao = cameraShaderParams?.ssaoEnabled;\\n\\t\\toptions.useAO = options.litOptions.ssao;\\n\\t\\toptions.litOptions.lightMapEnabled = options.lightMap;\\n\\t\\toptions.litOptions.dirLightMapEnabled = options.dirLightMap;\\n\\t\\toptions.litOptions.useHeights = options.heightMap;\\n\\t\\toptions.litOptions.useNormals = options.normalMap;\\n\\t\\toptions.litOptions.useClearCoatNormals = options.clearCoatNormalMap;\\n\\t\\toptions.litOptions.useAo = options.aoMap || options.aoVertexColor || options.litOptions.ssao;\\n\\t\\toptions.litOptions.diffuseMapEnabled = options.diffuseMap;\\n\\t}\\n\\t_updateTexOptions(options, stdMat, p, hasUv0, hasUv1, hasVcolor, minimalOptions, uniqueTextureMap) {\\n\\t\\tconst isOpacity = p === \\\"opacity\\\";\\n\\t\\tif (!minimalOptions || isOpacity) {\\n\\t\\t\\tconst mname = `${p}Map`;\\n\\t\\t\\tconst vname = `${p}VertexColor`;\\n\\t\\t\\tconst vcname = `${p}VertexColorChannel`;\\n\\t\\t\\tconst cname = `${mname}Channel`;\\n\\t\\t\\tconst tname = `${mname}Transform`;\\n\\t\\t\\tconst uname = `${mname}Uv`;\\n\\t\\t\\tconst iname = `${mname}Identifier`;\\n\\t\\t\\tif (p !== \\\"light\\\") {\\n\\t\\t\\t\\toptions[mname] = false;\\n\\t\\t\\t\\toptions[iname] = void 0;\\n\\t\\t\\t\\toptions[cname] = \\\"\\\";\\n\\t\\t\\t\\toptions[tname] = 0;\\n\\t\\t\\t\\toptions[uname] = 0;\\n\\t\\t\\t}\\n\\t\\t\\toptions[vname] = false;\\n\\t\\t\\toptions[vcname] = \\\"\\\";\\n\\t\\t\\tif (isOpacity && stdMat.blendType === BLEND_NONE && stdMat.alphaTest === 0 && !stdMat.alphaToCoverage && stdMat.opacityDither === DITHER_NONE) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tif (p !== \\\"height\\\" && stdMat[vname]) {\\n\\t\\t\\t\\tif (hasVcolor) {\\n\\t\\t\\t\\t\\toptions[vname] = stdMat[vname];\\n\\t\\t\\t\\t\\toptions[vcname] = stdMat[vcname];\\n\\t\\t\\t\\t\\toptions.litOptions.vertexColors = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (stdMat[mname]) {\\n\\t\\t\\t\\tlet allow = true;\\n\\t\\t\\t\\tif (stdMat[uname] === 0 && !hasUv0) allow = false;\\n\\t\\t\\t\\tif (stdMat[uname] === 1 && !hasUv1) allow = false;\\n\\t\\t\\t\\tif (allow) {\\n\\t\\t\\t\\t\\tconst mapId = stdMat[mname].id;\\n\\t\\t\\t\\t\\tlet identifier = uniqueTextureMap[mapId];\\n\\t\\t\\t\\t\\tif (identifier === void 0) {\\n\\t\\t\\t\\t\\t\\tuniqueTextureMap[mapId] = p;\\n\\t\\t\\t\\t\\t\\tidentifier = p;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\toptions[mname] = !!stdMat[mname];\\n\\t\\t\\t\\t\\toptions[iname] = identifier;\\n\\t\\t\\t\\t\\toptions[tname] = this._getMapTransformID(stdMat.getUniform(tname), stdMat[uname]);\\n\\t\\t\\t\\t\\toptions[cname] = stdMat[cname];\\n\\t\\t\\t\\t\\toptions[uname] = stdMat[uname];\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_updateMinOptions(options, stdMat, pass) {\\n\\t\\tconst isPrepass = pass === SHADER_PREPASS;\\n\\t\\toptions.litOptions.opacityShadowDither = isPrepass ? stdMat.opacityDither : stdMat.opacityShadowDither;\\n\\t\\toptions.litOptions.linearDepth = isPrepass;\\n\\t\\toptions.litOptions.lights = [];\\n\\t}\\n\\t_updateMaterialOptions(options, stdMat, scene) {\\n\\t\\tconst useSpecular = !!(stdMat.useMetalness || stdMat.specularMap || stdMat.sphereMap || stdMat.cubeMap || notBlack(stdMat.specular) || stdMat.specularityFactor > 0 && stdMat.useMetalness || stdMat.enableGGXSpecular || stdMat.clearCoat > 0);\\n\\t\\tconst useSpecularColor = !stdMat.useMetalness || stdMat.useMetalnessSpecularColor;\\n\\t\\tconst specularTint = useSpecular && (stdMat.specularTint || notWhite(stdMat.specular));\\n\\t\\tconst specularityFactorTint = useSpecular && stdMat.useMetalnessSpecularColor && (stdMat.specularityFactorTint || stdMat.specularityFactor !== 1);\\n\\t\\tconst isPackedNormalMap = (texture) => texture ? texture.format === PIXELFORMAT_DXT5 || texture.type === TEXTURETYPE_SWIZZLEGGGR : false;\\n\\t\\tconst equalish = (a, b) => Math.abs(a - b) < 1e-4;\\n\\t\\toptions.specularTint = specularTint;\\n\\t\\toptions.specularityFactorTint = specularityFactorTint;\\n\\t\\toptions.metalnessTint = stdMat.useMetalness && stdMat.metalness < 1;\\n\\t\\toptions.glossTint = true;\\n\\t\\toptions.diffuseEncoding = stdMat.diffuseMap?.encoding;\\n\\t\\toptions.diffuseDetailEncoding = stdMat.diffuseDetailMap?.encoding;\\n\\t\\toptions.emissiveEncoding = stdMat.emissiveMap?.encoding;\\n\\t\\toptions.lightMapEncoding = stdMat.lightMap?.encoding;\\n\\t\\toptions.packedNormal = isPackedNormalMap(stdMat.normalMap);\\n\\t\\toptions.refractionTint = !equalish(stdMat.refraction, 1);\\n\\t\\toptions.refractionIndexTint = !equalish(stdMat.refractionIndex, 1 / 1.5);\\n\\t\\toptions.thicknessTint = stdMat.useDynamicRefraction && stdMat.thickness !== 1;\\n\\t\\toptions.specularEncoding = stdMat.specularMap?.encoding;\\n\\t\\toptions.sheenEncoding = stdMat.sheenMap?.encoding;\\n\\t\\toptions.aoMapUv = stdMat.aoUvSet;\\n\\t\\toptions.aoDetail = !!stdMat.aoDetailMap;\\n\\t\\toptions.diffuseDetail = !!stdMat.diffuseDetailMap;\\n\\t\\toptions.normalDetail = !!stdMat.normalMap;\\n\\t\\toptions.normalDetailPackedNormal = isPackedNormalMap(stdMat.normalDetailMap);\\n\\t\\toptions.diffuseDetailMode = stdMat.diffuseDetailMode;\\n\\t\\toptions.aoDetailMode = stdMat.aoDetailMode;\\n\\t\\toptions.clearCoatGloss = !!stdMat.clearCoatGloss;\\n\\t\\toptions.clearCoatPackedNormal = isPackedNormalMap(stdMat.clearCoatNormalMap);\\n\\t\\toptions.iorTint = !equalish(stdMat.refractionIndex, 1 / 1.5);\\n\\t\\tif (scene.forcePassThroughSpecular) {\\n\\t\\t\\toptions.specularEncoding = \\\"linear\\\";\\n\\t\\t\\toptions.sheenEncoding = \\\"linear\\\";\\n\\t\\t}\\n\\t\\toptions.iridescenceTint = stdMat.iridescence !== 1;\\n\\t\\toptions.glossInvert = stdMat.glossInvert;\\n\\t\\toptions.sheenGlossInvert = stdMat.sheenGlossInvert;\\n\\t\\toptions.clearCoatGlossInvert = stdMat.clearCoatGlossInvert;\\n\\t\\toptions.useSpecularColor = useSpecularColor;\\n\\t\\toptions.litOptions.separateAmbient = false;\\n\\t\\toptions.litOptions.pixelSnap = stdMat.pixelSnap;\\n\\t\\toptions.litOptions.ambientSH = !!stdMat.ambientSH;\\n\\t\\toptions.litOptions.twoSidedLighting = stdMat.twoSidedLighting;\\n\\t\\toptions.litOptions.occludeSpecular = stdMat.occludeSpecular;\\n\\t\\toptions.litOptions.occludeSpecularFloat = stdMat.occludeSpecularIntensity !== 1;\\n\\t\\toptions.litOptions.useMsdf = !!stdMat.msdfMap;\\n\\t\\toptions.litOptions.msdfTextAttribute = !!stdMat.msdfTextAttribute;\\n\\t\\toptions.litOptions.alphaToCoverage = stdMat.alphaToCoverage;\\n\\t\\toptions.litOptions.opacityFadesSpecular = stdMat.opacityFadesSpecular;\\n\\t\\toptions.litOptions.opacityDither = stdMat.opacityDither;\\n\\t\\toptions.litOptions.cubeMapProjection = stdMat.cubeMapProjection;\\n\\t\\toptions.litOptions.occludeDirect = stdMat.occludeDirect;\\n\\t\\toptions.litOptions.useSpecular = useSpecular;\\n\\t\\toptions.litOptions.useSpecularityFactor = (specularityFactorTint || !!stdMat.specularityFactorMap) && stdMat.useMetalnessSpecularColor;\\n\\t\\toptions.litOptions.enableGGXSpecular = stdMat.enableGGXSpecular;\\n\\t\\toptions.litOptions.useAnisotropy = stdMat.enableGGXSpecular && (stdMat.anisotropyIntensity > 0 || !!stdMat.anisotropyMap);\\n\\t\\toptions.litOptions.fresnelModel = stdMat.fresnelModel;\\n\\t\\toptions.litOptions.useRefraction = (stdMat.refraction || !!stdMat.refractionMap) && (stdMat.useDynamicRefraction || options.litOptions.reflectionSource !== REFLECTIONSRC_NONE);\\n\\t\\toptions.litOptions.useClearCoat = !!stdMat.clearCoat;\\n\\t\\toptions.litOptions.useSheen = stdMat.useSheen;\\n\\t\\toptions.litOptions.useIridescence = stdMat.useIridescence && stdMat.iridescence !== 0;\\n\\t\\toptions.litOptions.useMetalness = stdMat.useMetalness;\\n\\t\\toptions.litOptions.useDynamicRefraction = stdMat.useDynamicRefraction;\\n\\t\\toptions.litOptions.dispersion = stdMat.dispersion > 0;\\n\\t\\toptions.litOptions.shadowCatcher = stdMat.shadowCatcher;\\n\\t\\toptions.litOptions.useVertexColorGamma = stdMat.vertexColorGamma;\\n\\t}\\n\\t_updateEnvOptions(options, stdMat, scene, cameraShaderParams) {\\n\\t\\toptions.litOptions.fog = stdMat.useFog ? cameraShaderParams.fog : FOG_NONE;\\n\\t\\toptions.litOptions.gamma = cameraShaderParams.shaderOutputGamma;\\n\\t\\toptions.litOptions.toneMap = stdMat.useTonemap ? cameraShaderParams.toneMapping : TONEMAP_NONE;\\n\\t\\tlet usingSceneEnv = false;\\n\\t\\tif (stdMat.envAtlas && stdMat.cubeMap) {\\n\\t\\t\\toptions.litOptions.reflectionSource = REFLECTIONSRC_ENVATLASHQ;\\n\\t\\t\\toptions.litOptions.reflectionEncoding = stdMat.envAtlas.encoding;\\n\\t\\t\\toptions.litOptions.reflectionCubemapEncoding = stdMat.cubeMap.encoding;\\n\\t\\t} else if (stdMat.envAtlas) {\\n\\t\\t\\toptions.litOptions.reflectionSource = REFLECTIONSRC_ENVATLAS;\\n\\t\\t\\toptions.litOptions.reflectionEncoding = stdMat.envAtlas.encoding;\\n\\t\\t} else if (stdMat.cubeMap) {\\n\\t\\t\\toptions.litOptions.reflectionSource = REFLECTIONSRC_CUBEMAP;\\n\\t\\t\\toptions.litOptions.reflectionEncoding = stdMat.cubeMap.encoding;\\n\\t\\t} else if (stdMat.sphereMap) {\\n\\t\\t\\toptions.litOptions.reflectionSource = REFLECTIONSRC_SPHEREMAP;\\n\\t\\t\\toptions.litOptions.reflectionEncoding = stdMat.sphereMap.encoding;\\n\\t\\t} else if (stdMat.useSkybox && scene.envAtlas && scene.skybox) {\\n\\t\\t\\toptions.litOptions.reflectionSource = REFLECTIONSRC_ENVATLASHQ;\\n\\t\\t\\toptions.litOptions.reflectionEncoding = scene.envAtlas.encoding;\\n\\t\\t\\toptions.litOptions.reflectionCubemapEncoding = scene.skybox.encoding;\\n\\t\\t\\tusingSceneEnv = true;\\n\\t\\t} else if (stdMat.useSkybox && scene.envAtlas) {\\n\\t\\t\\toptions.litOptions.reflectionSource = REFLECTIONSRC_ENVATLAS;\\n\\t\\t\\toptions.litOptions.reflectionEncoding = scene.envAtlas.encoding;\\n\\t\\t\\tusingSceneEnv = true;\\n\\t\\t} else if (stdMat.useSkybox && scene.skybox) {\\n\\t\\t\\toptions.litOptions.reflectionSource = REFLECTIONSRC_CUBEMAP;\\n\\t\\t\\toptions.litOptions.reflectionEncoding = scene.skybox.encoding;\\n\\t\\t\\tusingSceneEnv = true;\\n\\t\\t} else {\\n\\t\\t\\toptions.litOptions.reflectionSource = REFLECTIONSRC_NONE;\\n\\t\\t\\toptions.litOptions.reflectionEncoding = null;\\n\\t\\t}\\n\\t\\tif (stdMat.ambientSH) {\\n\\t\\t\\toptions.litOptions.ambientSource = AMBIENTSRC_AMBIENTSH;\\n\\t\\t\\toptions.litOptions.ambientEncoding = null;\\n\\t\\t} else {\\n\\t\\t\\tconst envAtlas = stdMat.envAtlas || (stdMat.useSkybox && scene.envAtlas ? scene.envAtlas : null);\\n\\t\\t\\tif (envAtlas && !stdMat.sphereMap) {\\n\\t\\t\\t\\toptions.litOptions.ambientSource = AMBIENTSRC_ENVALATLAS;\\n\\t\\t\\t\\toptions.litOptions.ambientEncoding = envAtlas.encoding;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\toptions.litOptions.ambientSource = AMBIENTSRC_CONSTANT;\\n\\t\\t\\t\\toptions.litOptions.ambientEncoding = null;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\toptions.litOptions.skyboxIntensity = usingSceneEnv;\\n\\t\\toptions.litOptions.useCubeMapRotation = usingSceneEnv && scene._skyboxRotationShaderInclude;\\n\\t}\\n\\t_updateLightOptions(options, scene, stdMat, objDefs, sortedLights) {\\n\\t\\toptions.lightMap = false;\\n\\t\\toptions.lightMapChannel = \\\"\\\";\\n\\t\\toptions.lightMapUv = 0;\\n\\t\\toptions.lightMapTransform = 0;\\n\\t\\toptions.litOptions.lightMapWithoutAmbient = false;\\n\\t\\toptions.dirLightMap = false;\\n\\t\\tif (objDefs) {\\n\\t\\t\\toptions.litOptions.noShadow = (objDefs & SHADERDEF_NOSHADOW) !== 0;\\n\\t\\t\\tif ((objDefs & SHADERDEF_LM) !== 0) {\\n\\t\\t\\t\\toptions.lightMapEncoding = scene.lightmapPixelFormat === PIXELFORMAT_RGBA8 ? \\\"rgbm\\\" : \\\"linear\\\";\\n\\t\\t\\t\\toptions.lightMap = true;\\n\\t\\t\\t\\toptions.lightMapChannel = \\\"rgb\\\";\\n\\t\\t\\t\\toptions.lightMapUv = 1;\\n\\t\\t\\t\\toptions.lightMapTransform = 0;\\n\\t\\t\\t\\toptions.litOptions.lightMapWithoutAmbient = !stdMat.lightMap;\\n\\t\\t\\t\\tif ((objDefs & SHADERDEF_DIRLM) !== 0) {\\n\\t\\t\\t\\t\\toptions.dirLightMap = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif ((objDefs & SHADERDEF_LMAMBIENT) !== 0) {\\n\\t\\t\\t\\t\\toptions.litOptions.lightMapWithoutAmbient = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (stdMat.useLighting) {\\n\\t\\t\\tconst lightsFiltered = [];\\n\\t\\t\\tconst mask = objDefs ? objDefs >> 16 : MASK_AFFECT_DYNAMIC;\\n\\t\\t\\toptions.litOptions.lightMaskDynamic = !!(mask & MASK_AFFECT_DYNAMIC);\\n\\t\\t\\tif (sortedLights) {\\n\\t\\t\\t\\tLitMaterialOptionsBuilder.collectLights(LIGHTTYPE_DIRECTIONAL, sortedLights[LIGHTTYPE_DIRECTIONAL], lightsFiltered, mask);\\n\\t\\t\\t\\tif (!scene.clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\tLitMaterialOptionsBuilder.collectLights(LIGHTTYPE_OMNI, sortedLights[LIGHTTYPE_OMNI], lightsFiltered, mask);\\n\\t\\t\\t\\t\\tLitMaterialOptionsBuilder.collectLights(LIGHTTYPE_SPOT, sortedLights[LIGHTTYPE_SPOT], lightsFiltered, mask);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\toptions.litOptions.lights = lightsFiltered;\\n\\t\\t} else {\\n\\t\\t\\toptions.litOptions.lights = [];\\n\\t\\t}\\n\\t\\tif (options.litOptions.lights.length === 0 && !scene.clusteredLightingEnabled) {\\n\\t\\t\\toptions.litOptions.noShadow = true;\\n\\t\\t}\\n\\t}\\n\\t_getMapTransformID(xform, uv) {\\n\\t\\tif (!xform) return 0;\\n\\t\\tlet xforms = this._mapXForms[uv];\\n\\t\\tif (!xforms) {\\n\\t\\t\\txforms = [];\\n\\t\\t\\tthis._mapXForms[uv] = xforms;\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < xforms.length; i++) {\\n\\t\\t\\tif (arraysEqual(xforms[i][0].value, xform[0].value) && arraysEqual(xforms[i][1].value, xform[1].value)) {\\n\\t\\t\\t\\treturn i + 1;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn xforms.push(xform);\\n\\t}\\n}\\n\\nfunction _textureParameter(name, channel = true, vertexColor = true) {\\n\\tconst result = {};\\n\\tresult[`${name}Map`] = \\\"texture\\\";\\n\\tresult[`${name}MapTiling`] = \\\"vec2\\\";\\n\\tresult[`${name}MapOffset`] = \\\"vec2\\\";\\n\\tresult[`${name}MapRotation`] = \\\"number\\\";\\n\\tresult[`${name}MapUv`] = \\\"number\\\";\\n\\tif (channel) {\\n\\t\\tresult[`${name}MapChannel`] = \\\"string\\\";\\n\\t\\tif (vertexColor) {\\n\\t\\t\\tresult[`${name}VertexColor`] = \\\"boolean\\\";\\n\\t\\t\\tresult[`${name}VertexColorChannel`] = \\\"string\\\";\\n\\t\\t}\\n\\t}\\n\\treturn result;\\n}\\nconst standardMaterialParameterTypes = {\\n\\tname: \\\"string\\\",\\n\\tchunks: \\\"chunks\\\",\\n\\tmappingFormat: \\\"string\\\",\\n\\t_engine: \\\"boolean\\\",\\n\\t// internal param for engine-only loading\\n\\tambient: \\\"rgb\\\",\\n\\t..._textureParameter(\\\"ao\\\"),\\n\\t..._textureParameter(\\\"aoDetail\\\", true, false),\\n\\taoDetailMode: \\\"string\\\",\\n\\taoIntensity: \\\"number\\\",\\n\\tdiffuse: \\\"rgb\\\",\\n\\t..._textureParameter(\\\"diffuse\\\"),\\n\\t..._textureParameter(\\\"diffuseDetail\\\", true, false),\\n\\tdiffuseDetailMode: \\\"string\\\",\\n\\tvertexColorGamma: \\\"boolean\\\",\\n\\tspecular: \\\"rgb\\\",\\n\\tspecularTint: \\\"boolean\\\",\\n\\t..._textureParameter(\\\"specular\\\"),\\n\\toccludeSpecular: \\\"enum:occludeSpecular\\\",\\n\\tspecularityFactor: \\\"number\\\",\\n\\tspecularityFactorTint: \\\"boolean\\\",\\n\\t..._textureParameter(\\\"specularityFactor\\\"),\\n\\tuseMetalness: \\\"boolean\\\",\\n\\tmetalness: \\\"number\\\",\\n\\tenableGGXSpecular: \\\"boolean\\\",\\n\\tmetalnessTint: \\\"boolean\\\",\\n\\t..._textureParameter(\\\"metalness\\\"),\\n\\tuseMetalnessSpecularColor: \\\"boolean\\\",\\n\\tanisotropyIntensity: \\\"number\\\",\\n\\tanisotropyRotation: \\\"number\\\",\\n\\t..._textureParameter(\\\"anisotropy\\\"),\\n\\tshininess: \\\"number\\\",\\n\\tgloss: \\\"number\\\",\\n\\tglossInvert: \\\"boolean\\\",\\n\\t..._textureParameter(\\\"gloss\\\"),\\n\\tclearCoat: \\\"number\\\",\\n\\t..._textureParameter(\\\"clearCoat\\\"),\\n\\tclearCoatGloss: \\\"number\\\",\\n\\tclearCoatGlossInvert: \\\"boolean\\\",\\n\\t..._textureParameter(\\\"clearCoatGloss\\\"),\\n\\tclearCoatBumpiness: \\\"number\\\",\\n\\t..._textureParameter(\\\"clearCoatNormal\\\", false),\\n\\tuseSheen: \\\"boolean\\\",\\n\\tsheen: \\\"rgb\\\",\\n\\t..._textureParameter(\\\"sheen\\\"),\\n\\tsheenGloss: \\\"number\\\",\\n\\tsheenGlossInvert: \\\"boolean\\\",\\n\\t..._textureParameter(\\\"sheenGloss\\\"),\\n\\tfresnelModel: \\\"number\\\",\\n\\temissive: \\\"rgb\\\",\\n\\t..._textureParameter(\\\"emissive\\\"),\\n\\temissiveIntensity: \\\"number\\\",\\n\\t..._textureParameter(\\\"normal\\\", false),\\n\\tbumpiness: \\\"number\\\",\\n\\t// normalMapFactor: 'number', // TODO rename bumpiness to normalMapFactor\\n\\t..._textureParameter(\\\"normalDetail\\\", false),\\n\\tnormalDetailMapBumpiness: \\\"number\\\",\\n\\t..._textureParameter(\\\"height\\\", true, false),\\n\\theightMapFactor: \\\"number\\\",\\n\\talphaToCoverage: \\\"boolean\\\",\\n\\talphaTest: \\\"number\\\",\\n\\talphaFade: \\\"number\\\",\\n\\talphaDither: \\\"number\\\",\\n\\topacity: \\\"number\\\",\\n\\t..._textureParameter(\\\"opacity\\\"),\\n\\topacityFadesSpecular: \\\"boolean\\\",\\n\\topacityDither: \\\"string\\\",\\n\\topacityShadowDither: \\\"string\\\",\\n\\treflectivity: \\\"number\\\",\\n\\trefraction: \\\"number\\\",\\n\\trefractionTint: \\\"boolean\\\",\\n\\t..._textureParameter(\\\"refraction\\\"),\\n\\trefractionIndex: \\\"number\\\",\\n\\tdispersion: \\\"number\\\",\\n\\tthickness: \\\"number\\\",\\n\\tthicknessTint: \\\"boolean\\\",\\n\\t..._textureParameter(\\\"thickness\\\"),\\n\\tattenuation: \\\"rgb\\\",\\n\\tattenuationDistance: \\\"number\\\",\\n\\tuseDynamicRefraction: \\\"boolean\\\",\\n\\tsphereMap: \\\"texture\\\",\\n\\tcubeMap: \\\"cubemap\\\",\\n\\tcubeMapProjection: \\\"number\\\",\\n\\tcubeMapProjectionBox: \\\"boundingbox\\\",\\n\\tuseIridescence: \\\"boolean\\\",\\n\\tiridescence: \\\"number\\\",\\n\\tiridescenceTint: \\\"boolean\\\",\\n\\t..._textureParameter(\\\"iridescence\\\"),\\n\\tiridescenceThicknessTint: \\\"boolean\\\",\\n\\tiridescenceThicknessMin: \\\"number\\\",\\n\\tiridescenceThicknessMax: \\\"number\\\",\\n\\tiridescenceRefractionIndex: \\\"number\\\",\\n\\t..._textureParameter(\\\"iridescenceThickness\\\"),\\n\\t..._textureParameter(\\\"light\\\"),\\n\\tdepthTest: \\\"boolean\\\",\\n\\tdepthFunc: \\\"enum:depthFunc\\\",\\n\\tdepthWrite: \\\"boolean\\\",\\n\\tdepthBias: \\\"number\\\",\\n\\tslopeDepthBias: \\\"number\\\",\\n\\tcull: \\\"enum:cull\\\",\\n\\tblendType: \\\"enum:blendType\\\",\\n\\tuseFog: \\\"boolean\\\",\\n\\tuseLighting: \\\"boolean\\\",\\n\\tuseSkybox: \\\"boolean\\\",\\n\\tuseTonemap: \\\"boolean\\\",\\n\\tenvAtlas: \\\"texture\\\",\\n\\ttwoSidedLighting: \\\"boolean\\\",\\n\\tshadowCatcher: \\\"boolean\\\"\\n\\t// nineSlicedMode\\n\\t// pixelSnap\\n\\t// forceUv1\\n\\t// occludeDirect\\n\\t// occludeSpecularIntensity\\n\\t// msdfMap\\n\\t// msdfMapChannel\\n\\t// msdfMapUv\\n\\t// msdfMapTiling\\n\\t// msdfMapOffset\\n\\t// msdfTextAttribute\\n\\t// msdfVertexColor\\n\\t// msdfVertexColorChannel\\n};\\nconst standardMaterialTextureParameters = [];\\nfor (const key in standardMaterialParameterTypes) {\\n\\tconst type = standardMaterialParameterTypes[key];\\n\\tif (type === \\\"texture\\\") {\\n\\t\\tstandardMaterialTextureParameters.push(key);\\n\\t}\\n}\\nconst standardMaterialCubemapParameters = [];\\nfor (const key in standardMaterialParameterTypes) {\\n\\tconst type = standardMaterialParameterTypes[key];\\n\\tif (type === \\\"cubemap\\\") {\\n\\t\\tstandardMaterialCubemapParameters.push(key);\\n\\t}\\n}\\n\\nconst _props = {};\\nconst _uniforms = {};\\nlet _params = /* @__PURE__ */ new Set();\\nconst _tempColor = new Color();\\nclass StandardMaterial extends Material {\\n\\tstatic TEXTURE_PARAMETERS = standardMaterialTextureParameters;\\n\\tstatic CUBEMAP_PARAMETERS = standardMaterialCubemapParameters;\\n\\tuserAttributes = /* @__PURE__ */ new Map();\\n\\tonUpdateShader;\\n\\tconstructor() {\\n\\t\\tsuper();\\n\\t\\tthis._assetReferences = {};\\n\\t\\tthis._activeParams = /* @__PURE__ */ new Set();\\n\\t\\tthis._activeLightingParams = /* @__PURE__ */ new Set();\\n\\t\\tthis.shaderOptBuilder = new StandardMaterialOptionsBuilder();\\n\\t\\tthis.reset();\\n\\t}\\n\\treset() {\\n\\t\\tObject.keys(_props).forEach((name) => {\\n\\t\\t\\tthis[`_${name}`] = _props[name].value();\\n\\t\\t});\\n\\t\\tthis._uniformCache = {};\\n\\t}\\n\\tcopy(source) {\\n\\t\\tsuper.copy(source);\\n\\t\\tObject.keys(_props).forEach((k) => {\\n\\t\\t\\tthis[k] = source[k];\\n\\t\\t});\\n\\t\\tthis._alphaDither = source._alphaDither;\\n\\t\\tthis.userAttributes = new Map(source.userAttributes);\\n\\t\\treturn this;\\n\\t}\\n\\tsetAttribute(name, semantic) {\\n\\t\\tthis.userAttributes.set(semantic, name);\\n\\t}\\n\\t_setParameter(name, value) {\\n\\t\\t_params.add(name);\\n\\t\\tthis.setParameter(name, value);\\n\\t}\\n\\t_setParameters(parameters) {\\n\\t\\tparameters.forEach((v) => {\\n\\t\\t\\tthis._setParameter(v.name, v.value);\\n\\t\\t});\\n\\t}\\n\\t_processParameters(paramsName) {\\n\\t\\tconst prevParams = this[paramsName];\\n\\t\\tprevParams.forEach((param) => {\\n\\t\\t\\tif (!_params.has(param)) {\\n\\t\\t\\t\\tdelete this.parameters[param];\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tthis[paramsName] = _params;\\n\\t\\t_params = prevParams;\\n\\t\\t_params.clear();\\n\\t}\\n\\t_updateMap(p) {\\n\\t\\tconst mname = `${p}Map`;\\n\\t\\tconst map = this[mname];\\n\\t\\tif (map) {\\n\\t\\t\\tthis._setParameter(`texture_${mname}`, map);\\n\\t\\t\\tconst tname = `${mname}Transform`;\\n\\t\\t\\tconst uniform = this.getUniform(tname);\\n\\t\\t\\tif (uniform) {\\n\\t\\t\\t\\tthis._setParameters(uniform);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t// allocate a uniform if it doesn't already exist in the uniform cache\\n\\t_allocUniform(name, allocFunc) {\\n\\t\\tlet uniform = this._uniformCache[name];\\n\\t\\tif (!uniform) {\\n\\t\\t\\tuniform = allocFunc();\\n\\t\\t\\tthis._uniformCache[name] = uniform;\\n\\t\\t}\\n\\t\\treturn uniform;\\n\\t}\\n\\tgetUniform(name, device, scene) {\\n\\t\\treturn _uniforms[name](this, device, scene);\\n\\t}\\n\\tupdateUniforms(device, scene) {\\n\\t\\tconst getUniform = (name) => {\\n\\t\\t\\treturn this.getUniform(name, device, scene);\\n\\t\\t};\\n\\t\\tthis._setParameter(\\\"material_ambient\\\", getUniform(\\\"ambient\\\"));\\n\\t\\tthis._setParameter(\\\"material_diffuse\\\", getUniform(\\\"diffuse\\\"));\\n\\t\\tthis._setParameter(\\\"material_aoIntensity\\\", this.aoIntensity);\\n\\t\\tconst specularNotWhite = this.specular.r !== 1 || this.specular.g !== 1 || this.specular.b !== 1;\\n\\t\\tconst useSpecularConstant = !this.specularMap || this.specularTint || specularNotWhite;\\n\\t\\tif (this.useMetalness) {\\n\\t\\t\\tif (!this.metalnessMap || this.metalness < 1) {\\n\\t\\t\\t\\tthis._setParameter(\\\"material_metalness\\\", this.metalness);\\n\\t\\t\\t}\\n\\t\\t\\tif (useSpecularConstant) {\\n\\t\\t\\t\\tthis._setParameter(\\\"material_specular\\\", getUniform(\\\"specular\\\"));\\n\\t\\t\\t}\\n\\t\\t\\tif (!this.specularityFactorMap || this.specularityFactorTint || this.specularityFactor !== 1) {\\n\\t\\t\\t\\tthis._setParameter(\\\"material_specularityFactor\\\", this.specularityFactor);\\n\\t\\t\\t}\\n\\t\\t\\tthis._setParameter(\\\"material_sheen\\\", getUniform(\\\"sheen\\\"));\\n\\t\\t\\tthis._setParameter(\\\"material_sheenGloss\\\", this.sheenGloss);\\n\\t\\t\\tthis._setParameter(\\\"material_refractionIndex\\\", this.refractionIndex);\\n\\t\\t} else {\\n\\t\\t\\tif (useSpecularConstant) {\\n\\t\\t\\t\\tthis._setParameter(\\\"material_specular\\\", getUniform(\\\"specular\\\"));\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this.enableGGXSpecular) {\\n\\t\\t\\tthis._setParameter(\\\"material_anisotropyIntensity\\\", this.anisotropyIntensity);\\n\\t\\t\\tthis._setParameter(\\\"material_anisotropyRotation\\\", [Math.cos(this.anisotropyRotation * math.DEG_TO_RAD), Math.sin(this.anisotropyRotation * math.DEG_TO_RAD)]);\\n\\t\\t}\\n\\t\\tif (this.clearCoat > 0) {\\n\\t\\t\\tthis._setParameter(\\\"material_clearCoat\\\", this.clearCoat);\\n\\t\\t\\tthis._setParameter(\\\"material_clearCoatGloss\\\", this.clearCoatGloss);\\n\\t\\t\\tthis._setParameter(\\\"material_clearCoatBumpiness\\\", this.clearCoatBumpiness);\\n\\t\\t}\\n\\t\\tthis._setParameter(\\\"material_gloss\\\", this.gloss);\\n\\t\\tthis._setParameter(\\\"material_emissive\\\", getUniform(\\\"emissive\\\"));\\n\\t\\tthis._setParameter(\\\"material_emissiveIntensity\\\", this.emissiveIntensity);\\n\\t\\tif (this.refraction > 0) {\\n\\t\\t\\tthis._setParameter(\\\"material_refraction\\\", this.refraction);\\n\\t\\t}\\n\\t\\tif (this.dispersion > 0) {\\n\\t\\t\\tthis._setParameter(\\\"material_dispersion\\\", this.dispersion);\\n\\t\\t}\\n\\t\\tif (this.useDynamicRefraction) {\\n\\t\\t\\tthis._setParameter(\\\"material_thickness\\\", this.thickness);\\n\\t\\t\\tthis._setParameter(\\\"material_attenuation\\\", getUniform(\\\"attenuation\\\"));\\n\\t\\t\\tthis._setParameter(\\\"material_invAttenuationDistance\\\", this.attenuationDistance === 0 ? 0 : 1 / this.attenuationDistance);\\n\\t\\t}\\n\\t\\tif (this.useIridescence) {\\n\\t\\t\\tthis._setParameter(\\\"material_iridescence\\\", this.iridescence);\\n\\t\\t\\tthis._setParameter(\\\"material_iridescenceRefractionIndex\\\", this.iridescenceRefractionIndex);\\n\\t\\t\\tthis._setParameter(\\\"material_iridescenceThicknessMin\\\", this.iridescenceThicknessMin);\\n\\t\\t\\tthis._setParameter(\\\"material_iridescenceThicknessMax\\\", this.iridescenceThicknessMax);\\n\\t\\t}\\n\\t\\tthis._setParameter(\\\"material_opacity\\\", this.opacity);\\n\\t\\tconst ditherScale = this._opacity > 0 ? this.alphaDither / this._opacity : 1;\\n\\t\\tthis._setParameter(\\\"material_alphaDitherScale\\\", ditherScale);\\n\\t\\tif (this.opacityFadesSpecular === false) {\\n\\t\\t\\tthis._setParameter(\\\"material_alphaFade\\\", this.alphaFade);\\n\\t\\t}\\n\\t\\tif (this.occludeSpecular) {\\n\\t\\t\\tthis._setParameter(\\\"material_occludeSpecularIntensity\\\", this.occludeSpecularIntensity);\\n\\t\\t}\\n\\t\\tif (this.cubeMapProjection === CUBEPROJ_BOX) {\\n\\t\\t\\tthis._setParameter(getUniform(\\\"cubeMapProjectionBox\\\"));\\n\\t\\t}\\n\\t\\tfor (const p in _matTex2D) {\\n\\t\\t\\tthis._updateMap(p);\\n\\t\\t}\\n\\t\\tif (this.ambientSH) {\\n\\t\\t\\tthis._setParameter(\\\"ambientSH[0]\\\", this.ambientSH);\\n\\t\\t}\\n\\t\\tif (this.normalMap) {\\n\\t\\t\\tthis._setParameter(\\\"material_bumpiness\\\", this.bumpiness);\\n\\t\\t}\\n\\t\\tif (this.normalMap && this.normalDetailMap) {\\n\\t\\t\\tthis._setParameter(\\\"material_normalDetailMapBumpiness\\\", this.normalDetailMapBumpiness);\\n\\t\\t}\\n\\t\\tif (this.heightMap) {\\n\\t\\t\\tthis._setParameter(\\\"material_heightMapFactor\\\", getUniform(\\\"heightMapFactor\\\"));\\n\\t\\t}\\n\\t\\tif (this.envAtlas && this.cubeMap) {\\n\\t\\t\\tthis._setParameter(\\\"texture_envAtlas\\\", this.envAtlas);\\n\\t\\t\\tthis._setParameter(\\\"texture_cubeMap\\\", this.cubeMap);\\n\\t\\t} else if (this.envAtlas) {\\n\\t\\t\\tthis._setParameter(\\\"texture_envAtlas\\\", this.envAtlas);\\n\\t\\t} else if (this.cubeMap) {\\n\\t\\t\\tthis._setParameter(\\\"texture_cubeMap\\\", this.cubeMap);\\n\\t\\t} else if (this.sphereMap) {\\n\\t\\t\\tthis._setParameter(\\\"texture_sphereMap\\\", this.sphereMap);\\n\\t\\t}\\n\\t\\tthis._setParameter(\\\"material_reflectivity\\\", this.reflectivity);\\n\\t\\tthis._processParameters(\\\"_activeParams\\\");\\n\\t\\tsuper.updateUniforms(device, scene);\\n\\t}\\n\\tupdateEnvUniforms(device, scene) {\\n\\t\\tconst hasLocalEnvOverride = this.envAtlas || this.cubeMap || this.sphereMap;\\n\\t\\tif (!hasLocalEnvOverride && this.useSkybox) {\\n\\t\\t\\tif (scene.envAtlas && scene.skybox) {\\n\\t\\t\\t\\tthis._setParameter(\\\"texture_envAtlas\\\", scene.envAtlas);\\n\\t\\t\\t\\tthis._setParameter(\\\"texture_cubeMap\\\", scene.skybox);\\n\\t\\t\\t} else if (scene.envAtlas) {\\n\\t\\t\\t\\tthis._setParameter(\\\"texture_envAtlas\\\", scene.envAtlas);\\n\\t\\t\\t} else if (scene.skybox) {\\n\\t\\t\\t\\tthis._setParameter(\\\"texture_cubeMap\\\", scene.skybox);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._processParameters(\\\"_activeLightingParams\\\");\\n\\t}\\n\\tgetShaderVariant(params) {\\n\\t\\tconst { device, scene, pass, objDefs, sortedLights, cameraShaderParams } = params;\\n\\t\\tthis.updateEnvUniforms(device, scene);\\n\\t\\tconst shaderPassInfo = ShaderPass.get(device).getByIndex(pass);\\n\\t\\tconst minimalOptions = pass === SHADER_PICK || pass === SHADER_PREPASS || shaderPassInfo.isShadow;\\n\\t\\tlet options = minimalOptions ? standard.optionsContextMin : standard.optionsContext;\\n\\t\\toptions.defines = ShaderUtils.getCoreDefines(this, params);\\n\\t\\tif (minimalOptions) {\\n\\t\\t\\tthis.shaderOptBuilder.updateMinRef(options, scene, this, objDefs, pass, sortedLights);\\n\\t\\t} else {\\n\\t\\t\\tthis.shaderOptBuilder.updateRef(options, scene, cameraShaderParams, this, objDefs, pass, sortedLights);\\n\\t\\t}\\n\\t\\tif (!this.useFog) options.defines.set(\\\"FOG\\\", \\\"NONE\\\");\\n\\t\\toptions.defines.set(\\\"TONEMAP\\\", tonemapNames[options.litOptions.toneMap]);\\n\\t\\tif (this.onUpdateShader) {\\n\\t\\t\\toptions = this.onUpdateShader(options);\\n\\t\\t}\\n\\t\\tconst processingOptions = new ShaderProcessorOptions(params.viewUniformFormat, params.viewBindGroupFormat, params.vertexFormat);\\n\\t\\tconst library = getProgramLibrary(device);\\n\\t\\tlibrary.register(\\\"standard\\\", standard);\\n\\t\\tconst shader = library.getProgram(\\\"standard\\\", options, processingOptions, this.userId);\\n\\t\\treturn shader;\\n\\t}\\n\\tdestroy() {\\n\\t\\tfor (const asset in this._assetReferences) {\\n\\t\\t\\tthis._assetReferences[asset]._unbind();\\n\\t\\t}\\n\\t\\tthis._assetReferences = null;\\n\\t\\tsuper.destroy();\\n\\t}\\n}\\nconst defineUniform = (name, getUniformFunc) => {\\n\\t_uniforms[name] = getUniformFunc;\\n};\\nconst definePropInternal = (name, constructorFunc, setterFunc, getterFunc) => {\\n\\tObject.defineProperty(StandardMaterial.prototype, name, {\\n\\t\\tget: getterFunc || function() {\\n\\t\\t\\treturn this[`_${name}`];\\n\\t\\t},\\n\\t\\tset: setterFunc\\n\\t});\\n\\t_props[name] = {\\n\\t\\tvalue: constructorFunc\\n\\t};\\n};\\nconst defineValueProp = (prop) => {\\n\\tconst internalName = `_${prop.name}`;\\n\\tconst dirtyShaderFunc = prop.dirtyShaderFunc || (() => true);\\n\\tconst setterFunc = function(value) {\\n\\t\\tconst oldValue = this[internalName];\\n\\t\\tif (oldValue !== value) {\\n\\t\\t\\tthis._dirtyShader = this._dirtyShader || dirtyShaderFunc(oldValue, value);\\n\\t\\t\\tthis[internalName] = value;\\n\\t\\t}\\n\\t};\\n\\tdefinePropInternal(prop.name, () => prop.defaultValue, setterFunc, prop.getterFunc);\\n};\\nconst defineAggProp = (prop) => {\\n\\tconst internalName = `_${prop.name}`;\\n\\tconst dirtyShaderFunc = prop.dirtyShaderFunc || (() => true);\\n\\tconst setterFunc = function(value) {\\n\\t\\tconst oldValue = this[internalName];\\n\\t\\tif (!oldValue.equals(value)) {\\n\\t\\t\\tthis._dirtyShader = this._dirtyShader || dirtyShaderFunc(oldValue, value);\\n\\t\\t\\tthis[internalName] = oldValue.copy(value);\\n\\t\\t}\\n\\t};\\n\\tdefinePropInternal(prop.name, () => prop.defaultValue.clone(), setterFunc, prop.getterFunc);\\n};\\nconst defineProp = (prop) => {\\n\\treturn prop.defaultValue && prop.defaultValue.clone ? defineAggProp(prop) : defineValueProp(prop);\\n};\\nfunction _defineTex2D(name, channel = \\\"rgb\\\", vertexColor = true, uv = 0) {\\n\\t_matTex2D[name] = channel.length || -1;\\n\\tdefineProp({\\n\\t\\tname: `${name}Map`,\\n\\t\\tdefaultValue: null,\\n\\t\\tdirtyShaderFunc: (oldValue, newValue) => {\\n\\t\\t\\treturn !!oldValue !== !!newValue || oldValue && (oldValue.type !== newValue.type || oldValue.format !== newValue.format);\\n\\t\\t}\\n\\t});\\n\\tdefineProp({\\n\\t\\tname: `${name}MapTiling`,\\n\\t\\tdefaultValue: new Vec2(1, 1)\\n\\t});\\n\\tdefineProp({\\n\\t\\tname: `${name}MapOffset`,\\n\\t\\tdefaultValue: new Vec2(0, 0)\\n\\t});\\n\\tdefineProp({\\n\\t\\tname: `${name}MapRotation`,\\n\\t\\tdefaultValue: 0\\n\\t});\\n\\tdefineProp({\\n\\t\\tname: `${name}MapUv`,\\n\\t\\tdefaultValue: uv\\n\\t});\\n\\tif (channel) {\\n\\t\\tdefineProp({\\n\\t\\t\\tname: `${name}MapChannel`,\\n\\t\\t\\tdefaultValue: channel\\n\\t\\t});\\n\\t\\tif (vertexColor) {\\n\\t\\t\\tdefineProp({\\n\\t\\t\\t\\tname: `${name}VertexColor`,\\n\\t\\t\\t\\tdefaultValue: false\\n\\t\\t\\t});\\n\\t\\t\\tdefineProp({\\n\\t\\t\\t\\tname: `${name}VertexColorChannel`,\\n\\t\\t\\t\\tdefaultValue: channel\\n\\t\\t\\t});\\n\\t\\t}\\n\\t}\\n\\tconst mapTiling = `${name}MapTiling`;\\n\\tconst mapOffset = `${name}MapOffset`;\\n\\tconst mapRotation = `${name}MapRotation`;\\n\\tconst mapTransform = `${name}MapTransform`;\\n\\tdefineUniform(mapTransform, (material, device, scene) => {\\n\\t\\tconst tiling = material[mapTiling];\\n\\t\\tconst offset = material[mapOffset];\\n\\t\\tconst rotation = material[mapRotation];\\n\\t\\tif (tiling.x === 1 && tiling.y === 1 && offset.x === 0 && offset.y === 0 && rotation === 0) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tconst uniform = material._allocUniform(mapTransform, () => {\\n\\t\\t\\treturn [{\\n\\t\\t\\t\\tname: `texture_${mapTransform}0`,\\n\\t\\t\\t\\tvalue: new Float32Array(3)\\n\\t\\t\\t}, {\\n\\t\\t\\t\\tname: `texture_${mapTransform}1`,\\n\\t\\t\\t\\tvalue: new Float32Array(3)\\n\\t\\t\\t}];\\n\\t\\t});\\n\\t\\tconst cr = Math.cos(rotation * math.DEG_TO_RAD);\\n\\t\\tconst sr = Math.sin(rotation * math.DEG_TO_RAD);\\n\\t\\tconst uniform0 = uniform[0].value;\\n\\t\\tuniform0[0] = cr * tiling.x;\\n\\t\\tuniform0[1] = -sr * tiling.y;\\n\\t\\tuniform0[2] = offset.x;\\n\\t\\tconst uniform1 = uniform[1].value;\\n\\t\\tuniform1[0] = sr * tiling.x;\\n\\t\\tuniform1[1] = cr * tiling.y;\\n\\t\\tuniform1[2] = 1 - tiling.y - offset.y;\\n\\t\\treturn uniform;\\n\\t});\\n}\\nfunction _defineColor(name, defaultValue) {\\n\\tdefineProp({\\n\\t\\tname,\\n\\t\\tdefaultValue,\\n\\t\\tgetterFunc: function() {\\n\\t\\t\\tthis._dirtyShader = true;\\n\\t\\t\\treturn this[`_${name}`];\\n\\t\\t}\\n\\t});\\n\\tdefineUniform(name, (material, device, scene) => {\\n\\t\\tconst uniform = material._allocUniform(name, () => new Float32Array(3));\\n\\t\\tconst color = material[name];\\n\\t\\t_tempColor.linear(color);\\n\\t\\tuniform[0] = _tempColor.r;\\n\\t\\tuniform[1] = _tempColor.g;\\n\\t\\tuniform[2] = _tempColor.b;\\n\\t\\treturn uniform;\\n\\t});\\n}\\nfunction _defineFloat(name, defaultValue, getUniformFunc) {\\n\\tdefineProp({\\n\\t\\tname,\\n\\t\\tdefaultValue,\\n\\t\\tdirtyShaderFunc: (oldValue, newValue) => {\\n\\t\\t\\treturn (oldValue === 0 || oldValue === 1) !== (newValue === 0 || newValue === 1);\\n\\t\\t}\\n\\t});\\n\\tdefineUniform(name, getUniformFunc);\\n}\\nfunction _defineObject(name, getUniformFunc) {\\n\\tdefineProp({\\n\\t\\tname,\\n\\t\\tdefaultValue: null,\\n\\t\\tdirtyShaderFunc: (oldValue, newValue) => {\\n\\t\\t\\treturn !!oldValue === !!newValue;\\n\\t\\t}\\n\\t});\\n\\tdefineUniform(name, getUniformFunc);\\n}\\nfunction _defineFlag(name, defaultValue) {\\n\\tdefineProp({\\n\\t\\tname,\\n\\t\\tdefaultValue\\n\\t});\\n}\\nfunction _defineMaterialProps() {\\n\\t_defineColor(\\\"ambient\\\", new Color(1, 1, 1));\\n\\t_defineColor(\\\"diffuse\\\", new Color(1, 1, 1));\\n\\t_defineColor(\\\"specular\\\", new Color(0, 0, 0));\\n\\t_defineColor(\\\"emissive\\\", new Color(0, 0, 0));\\n\\t_defineColor(\\\"sheen\\\", new Color(1, 1, 1));\\n\\t_defineColor(\\\"attenuation\\\", new Color(1, 1, 1));\\n\\t_defineFloat(\\\"emissiveIntensity\\\", 1);\\n\\t_defineFloat(\\\"specularityFactor\\\", 1);\\n\\t_defineFloat(\\\"sheenGloss\\\", 0);\\n\\t_defineFloat(\\\"gloss\\\", 0.25);\\n\\t_defineFloat(\\\"aoIntensity\\\", 1);\\n\\t_defineFloat(\\\"heightMapFactor\\\", 1, (material, device, scene) => {\\n\\t\\treturn material.heightMapFactor * 0.025;\\n\\t});\\n\\t_defineFloat(\\\"opacity\\\", 1);\\n\\t_defineFloat(\\\"alphaFade\\\", 1);\\n\\tdefineProp({\\n\\t\\tname: \\\"alphaDither\\\",\\n\\t\\tdefaultValue: null,\\n\\t\\tdirtyShaderFunc: () => false,\\n\\t\\tgetterFunc: function() {\\n\\t\\t\\treturn this._alphaDither ?? this._opacity;\\n\\t\\t}\\n\\t});\\n\\t_defineFloat(\\\"alphaTest\\\", 0);\\n\\t_defineFloat(\\\"bumpiness\\\", 1);\\n\\t_defineFloat(\\\"normalDetailMapBumpiness\\\", 1);\\n\\t_defineFloat(\\\"reflectivity\\\", 1);\\n\\t_defineFloat(\\\"occludeSpecularIntensity\\\", 1);\\n\\t_defineFloat(\\\"refraction\\\", 0);\\n\\t_defineFloat(\\\"refractionIndex\\\", 1 / 1.5, (material, device, scene) => {\\n\\t\\treturn Math.max(1e-3, material.refractionIndex);\\n\\t});\\n\\t_defineFloat(\\\"dispersion\\\", 0);\\n\\t_defineFloat(\\\"thickness\\\", 0);\\n\\t_defineFloat(\\\"attenuationDistance\\\", 0);\\n\\t_defineFloat(\\\"metalness\\\", 1);\\n\\t_defineFloat(\\\"anisotropyIntensity\\\", 0);\\n\\t_defineFloat(\\\"anisotropyRotation\\\", 0);\\n\\t_defineFloat(\\\"clearCoat\\\", 0);\\n\\t_defineFloat(\\\"clearCoatGloss\\\", 1);\\n\\t_defineFloat(\\\"clearCoatBumpiness\\\", 1);\\n\\t_defineFloat(\\\"aoUvSet\\\", 0, null);\\n\\t_defineFloat(\\\"iridescence\\\", 0);\\n\\t_defineFloat(\\\"iridescenceRefractionIndex\\\", 1 / 1.5);\\n\\t_defineFloat(\\\"iridescenceThicknessMin\\\", 0);\\n\\t_defineFloat(\\\"iridescenceThicknessMax\\\", 0);\\n\\t_defineObject(\\\"ambientSH\\\");\\n\\t_defineObject(\\\"cubeMapProjectionBox\\\", (material, device, scene) => {\\n\\t\\tconst uniform = material._allocUniform(\\\"cubeMapProjectionBox\\\", () => {\\n\\t\\t\\treturn [{\\n\\t\\t\\t\\tname: \\\"envBoxMin\\\",\\n\\t\\t\\t\\tvalue: new Float32Array(3)\\n\\t\\t\\t}, {\\n\\t\\t\\t\\tname: \\\"envBoxMax\\\",\\n\\t\\t\\t\\tvalue: new Float32Array(3)\\n\\t\\t\\t}];\\n\\t\\t});\\n\\t\\tconst bboxMin = material.cubeMapProjectionBox.getMin();\\n\\t\\tconst minUniform = uniform[0].value;\\n\\t\\tminUniform[0] = bboxMin.x;\\n\\t\\tminUniform[1] = bboxMin.y;\\n\\t\\tminUniform[2] = bboxMin.z;\\n\\t\\tconst bboxMax = material.cubeMapProjectionBox.getMax();\\n\\t\\tconst maxUniform = uniform[1].value;\\n\\t\\tmaxUniform[0] = bboxMax.x;\\n\\t\\tmaxUniform[1] = bboxMax.y;\\n\\t\\tmaxUniform[2] = bboxMax.z;\\n\\t\\treturn uniform;\\n\\t});\\n\\t_defineFlag(\\\"specularTint\\\", false);\\n\\t_defineFlag(\\\"specularityFactorTint\\\", false);\\n\\t_defineFlag(\\\"useMetalness\\\", false);\\n\\t_defineFlag(\\\"useMetalnessSpecularColor\\\", false);\\n\\t_defineFlag(\\\"useSheen\\\", false);\\n\\t_defineFlag(\\\"enableGGXSpecular\\\", false);\\n\\t_defineFlag(\\\"occludeDirect\\\", false);\\n\\t_defineFlag(\\\"opacityFadesSpecular\\\", true);\\n\\t_defineFlag(\\\"occludeSpecular\\\", SPECOCC_AO);\\n\\t_defineFlag(\\\"fresnelModel\\\", FRESNEL_SCHLICK);\\n\\t_defineFlag(\\\"useDynamicRefraction\\\", false);\\n\\t_defineFlag(\\\"cubeMapProjection\\\", CUBEPROJ_NONE);\\n\\t_defineFlag(\\\"useFog\\\", true);\\n\\t_defineFlag(\\\"useLighting\\\", true);\\n\\t_defineFlag(\\\"useTonemap\\\", true);\\n\\t_defineFlag(\\\"useSkybox\\\", true);\\n\\t_defineFlag(\\\"forceUv1\\\", false);\\n\\t_defineFlag(\\\"pixelSnap\\\", false);\\n\\t_defineFlag(\\\"twoSidedLighting\\\", false);\\n\\t_defineFlag(\\\"nineSlicedMode\\\", void 0);\\n\\t_defineFlag(\\\"msdfTextAttribute\\\", false);\\n\\t_defineFlag(\\\"useIridescence\\\", false);\\n\\t_defineFlag(\\\"glossInvert\\\", false);\\n\\t_defineFlag(\\\"sheenGlossInvert\\\", false);\\n\\t_defineFlag(\\\"clearCoatGlossInvert\\\", false);\\n\\t_defineFlag(\\\"opacityDither\\\", DITHER_NONE);\\n\\t_defineFlag(\\\"opacityShadowDither\\\", DITHER_NONE);\\n\\t_defineFlag(\\\"shadowCatcher\\\", false);\\n\\t_defineFlag(\\\"vertexColorGamma\\\", false);\\n\\t_defineTex2D(\\\"diffuse\\\");\\n\\t_defineTex2D(\\\"specular\\\");\\n\\t_defineTex2D(\\\"emissive\\\");\\n\\t_defineTex2D(\\\"thickness\\\", \\\"g\\\");\\n\\t_defineTex2D(\\\"specularityFactor\\\", \\\"g\\\");\\n\\t_defineTex2D(\\\"normal\\\", \\\"\\\");\\n\\t_defineTex2D(\\\"metalness\\\", \\\"g\\\");\\n\\t_defineTex2D(\\\"gloss\\\", \\\"g\\\");\\n\\t_defineTex2D(\\\"opacity\\\", \\\"a\\\");\\n\\t_defineTex2D(\\\"refraction\\\", \\\"g\\\");\\n\\t_defineTex2D(\\\"height\\\", \\\"g\\\", false);\\n\\t_defineTex2D(\\\"ao\\\", \\\"g\\\");\\n\\t_defineTex2D(\\\"light\\\", \\\"rgb\\\", true, 1);\\n\\t_defineTex2D(\\\"msdf\\\", \\\"\\\");\\n\\t_defineTex2D(\\\"diffuseDetail\\\", \\\"rgb\\\", false);\\n\\t_defineTex2D(\\\"normalDetail\\\", \\\"\\\");\\n\\t_defineTex2D(\\\"aoDetail\\\", \\\"g\\\", false);\\n\\t_defineTex2D(\\\"clearCoat\\\", \\\"g\\\");\\n\\t_defineTex2D(\\\"clearCoatGloss\\\", \\\"g\\\");\\n\\t_defineTex2D(\\\"clearCoatNormal\\\", \\\"\\\");\\n\\t_defineTex2D(\\\"sheen\\\", \\\"rgb\\\");\\n\\t_defineTex2D(\\\"sheenGloss\\\", \\\"g\\\");\\n\\t_defineTex2D(\\\"iridescence\\\", \\\"g\\\");\\n\\t_defineTex2D(\\\"iridescenceThickness\\\", \\\"g\\\");\\n\\t_defineTex2D(\\\"anisotropy\\\", \\\"\\\");\\n\\t_defineFlag(\\\"diffuseDetailMode\\\", DETAILMODE_MUL);\\n\\t_defineFlag(\\\"aoDetailMode\\\", DETAILMODE_MUL);\\n\\t_defineObject(\\\"cubeMap\\\");\\n\\t_defineObject(\\\"sphereMap\\\");\\n\\t_defineObject(\\\"envAtlas\\\");\\n\\tconst getterFunc = function() {\\n\\t\\treturn this._prefilteredCubemaps;\\n\\t};\\n\\tconst setterFunc = function(value) {\\n\\t\\tconst cubemaps = this._prefilteredCubemaps;\\n\\t\\tvalue = value || [];\\n\\t\\tlet changed = false;\\n\\t\\tlet complete = true;\\n\\t\\tfor (let i = 0; i < 6; ++i) {\\n\\t\\t\\tconst v = value[i] || null;\\n\\t\\t\\tif (cubemaps[i] !== v) {\\n\\t\\t\\t\\tcubemaps[i] = v;\\n\\t\\t\\t\\tchanged = true;\\n\\t\\t\\t}\\n\\t\\t\\tcomplete = complete && !!cubemaps[i];\\n\\t\\t}\\n\\t\\tif (changed) {\\n\\t\\t\\tif (complete) {\\n\\t\\t\\t\\tthis.envAtlas = EnvLighting.generatePrefilteredAtlas(cubemaps, {\\n\\t\\t\\t\\t\\ttarget: this.envAtlas\\n\\t\\t\\t\\t});\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (this.envAtlas) {\\n\\t\\t\\t\\t\\tthis.envAtlas.destroy();\\n\\t\\t\\t\\t\\tthis.envAtlas = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis._dirtyShader = true;\\n\\t\\t}\\n\\t};\\n\\tconst empty = [null, null, null, null, null, null];\\n\\tdefinePropInternal(\\\"prefilteredCubemaps\\\", () => empty.slice(), setterFunc, getterFunc);\\n}\\n_defineMaterialProps();\\n\\nconst primitiveUv1Padding = 8 / 64;\\nconst primitiveUv1PaddingScale = 1 - primitiveUv1Padding * 2;\\nclass ConeBaseGeometry extends Geometry {\\n\\tconstructor(baseRadius, peakRadius, height, heightSegments, capSegments, roundedCaps) {\\n\\t\\tsuper();\\n\\t\\tconst pos = new Vec3();\\n\\t\\tconst bottomToTop = new Vec3();\\n\\t\\tconst norm = new Vec3();\\n\\t\\tconst top = new Vec3();\\n\\t\\tconst bottom = new Vec3();\\n\\t\\tconst tangent = new Vec3();\\n\\t\\tconst positions = [];\\n\\t\\tconst normals = [];\\n\\t\\tconst uvs = [];\\n\\t\\tconst uvs1 = [];\\n\\t\\tconst indices = [];\\n\\t\\tlet offset;\\n\\t\\tif (height > 0) {\\n\\t\\t\\tfor (let i = 0; i <= heightSegments; i++) {\\n\\t\\t\\t\\tfor (let j = 0; j <= capSegments; j++) {\\n\\t\\t\\t\\t\\tconst theta = j / capSegments * 2 * Math.PI - Math.PI;\\n\\t\\t\\t\\t\\tconst sinTheta = Math.sin(theta);\\n\\t\\t\\t\\t\\tconst cosTheta = Math.cos(theta);\\n\\t\\t\\t\\t\\tbottom.set(sinTheta * baseRadius, -height / 2, cosTheta * baseRadius);\\n\\t\\t\\t\\t\\ttop.set(sinTheta * peakRadius, height / 2, cosTheta * peakRadius);\\n\\t\\t\\t\\t\\tpos.lerp(bottom, top, i / heightSegments);\\n\\t\\t\\t\\t\\tbottomToTop.sub2(top, bottom).normalize();\\n\\t\\t\\t\\t\\ttangent.set(cosTheta, 0, -sinTheta);\\n\\t\\t\\t\\t\\tnorm.cross(tangent, bottomToTop).normalize();\\n\\t\\t\\t\\t\\tpositions.push(pos.x, pos.y, pos.z);\\n\\t\\t\\t\\t\\tnormals.push(norm.x, norm.y, norm.z);\\n\\t\\t\\t\\t\\tlet u = j / capSegments;\\n\\t\\t\\t\\t\\tlet v = i / heightSegments;\\n\\t\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t\\t\\tconst _v = v;\\n\\t\\t\\t\\t\\tv = u;\\n\\t\\t\\t\\t\\tu = _v;\\n\\t\\t\\t\\t\\tu = u * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\tv = v * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\tu /= 3;\\n\\t\\t\\t\\t\\tuvs1.push(u, 1 - v);\\n\\t\\t\\t\\t\\tif (i < heightSegments && j < capSegments) {\\n\\t\\t\\t\\t\\t\\tconst first = i * (capSegments + 1) + j;\\n\\t\\t\\t\\t\\t\\tconst second = i * (capSegments + 1) + (j + 1);\\n\\t\\t\\t\\t\\t\\tconst third = (i + 1) * (capSegments + 1) + j;\\n\\t\\t\\t\\t\\t\\tconst fourth = (i + 1) * (capSegments + 1) + (j + 1);\\n\\t\\t\\t\\t\\t\\tindices.push(first, second, third);\\n\\t\\t\\t\\t\\t\\tindices.push(second, fourth, third);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (roundedCaps) {\\n\\t\\t\\tconst latitudeBands = Math.floor(capSegments / 2);\\n\\t\\t\\tconst longitudeBands = capSegments;\\n\\t\\t\\tconst capOffset = height / 2;\\n\\t\\t\\tfor (let lat = 0; lat <= latitudeBands; lat++) {\\n\\t\\t\\t\\tconst theta = lat * Math.PI * 0.5 / latitudeBands;\\n\\t\\t\\t\\tconst sinTheta = Math.sin(theta);\\n\\t\\t\\t\\tconst cosTheta = Math.cos(theta);\\n\\t\\t\\t\\tfor (let lon = 0; lon <= longitudeBands; lon++) {\\n\\t\\t\\t\\t\\tconst phi = lon * 2 * Math.PI / longitudeBands - Math.PI / 2;\\n\\t\\t\\t\\t\\tconst sinPhi = Math.sin(phi);\\n\\t\\t\\t\\t\\tconst cosPhi = Math.cos(phi);\\n\\t\\t\\t\\t\\tconst x = cosPhi * sinTheta;\\n\\t\\t\\t\\t\\tconst y = cosTheta;\\n\\t\\t\\t\\t\\tconst z = sinPhi * sinTheta;\\n\\t\\t\\t\\t\\tlet u = 1 - lon / longitudeBands;\\n\\t\\t\\t\\t\\tlet v = 1 - lat / latitudeBands;\\n\\t\\t\\t\\t\\tpositions.push(x * peakRadius, y * peakRadius + capOffset, z * peakRadius);\\n\\t\\t\\t\\t\\tnormals.push(x, y, z);\\n\\t\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t\\t\\tu = u * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\tv = v * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\tu /= 3;\\n\\t\\t\\t\\t\\tv /= 3;\\n\\t\\t\\t\\t\\tu += 1 / 3;\\n\\t\\t\\t\\t\\tuvs1.push(u, 1 - v);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\toffset = (heightSegments + 1) * (capSegments + 1);\\n\\t\\t\\tfor (let lat = 0; lat < latitudeBands; ++lat) {\\n\\t\\t\\t\\tfor (let lon = 0; lon < longitudeBands; ++lon) {\\n\\t\\t\\t\\t\\tconst first = lat * (longitudeBands + 1) + lon;\\n\\t\\t\\t\\t\\tconst second = first + longitudeBands + 1;\\n\\t\\t\\t\\t\\tindices.push(offset + first + 1, offset + second, offset + first);\\n\\t\\t\\t\\t\\tindices.push(offset + first + 1, offset + second + 1, offset + second);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tfor (let lat = 0; lat <= latitudeBands; lat++) {\\n\\t\\t\\t\\tconst theta = Math.PI * 0.5 + lat * Math.PI * 0.5 / latitudeBands;\\n\\t\\t\\t\\tconst sinTheta = Math.sin(theta);\\n\\t\\t\\t\\tconst cosTheta = Math.cos(theta);\\n\\t\\t\\t\\tfor (let lon = 0; lon <= longitudeBands; lon++) {\\n\\t\\t\\t\\t\\tconst phi = lon * 2 * Math.PI / longitudeBands - Math.PI / 2;\\n\\t\\t\\t\\t\\tconst sinPhi = Math.sin(phi);\\n\\t\\t\\t\\t\\tconst cosPhi = Math.cos(phi);\\n\\t\\t\\t\\t\\tconst x = cosPhi * sinTheta;\\n\\t\\t\\t\\t\\tconst y = cosTheta;\\n\\t\\t\\t\\t\\tconst z = sinPhi * sinTheta;\\n\\t\\t\\t\\t\\tlet u = 1 - lon / longitudeBands;\\n\\t\\t\\t\\t\\tlet v = 1 - lat / latitudeBands;\\n\\t\\t\\t\\t\\tpositions.push(x * peakRadius, y * peakRadius - capOffset, z * peakRadius);\\n\\t\\t\\t\\t\\tnormals.push(x, y, z);\\n\\t\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t\\t\\tu = u * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\tv = v * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\tu /= 3;\\n\\t\\t\\t\\t\\tv /= 3;\\n\\t\\t\\t\\t\\tu += 2 / 3;\\n\\t\\t\\t\\t\\tuvs1.push(u, 1 - v);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\toffset = (heightSegments + 1) * (capSegments + 1) + (longitudeBands + 1) * (latitudeBands + 1);\\n\\t\\t\\tfor (let lat = 0; lat < latitudeBands; ++lat) {\\n\\t\\t\\t\\tfor (let lon = 0; lon < longitudeBands; ++lon) {\\n\\t\\t\\t\\t\\tconst first = lat * (longitudeBands + 1) + lon;\\n\\t\\t\\t\\t\\tconst second = first + longitudeBands + 1;\\n\\t\\t\\t\\t\\tindices.push(offset + first + 1, offset + second, offset + first);\\n\\t\\t\\t\\t\\tindices.push(offset + first + 1, offset + second + 1, offset + second);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\toffset = (heightSegments + 1) * (capSegments + 1);\\n\\t\\t\\tif (baseRadius > 0) {\\n\\t\\t\\t\\tfor (let i = 0; i < capSegments; i++) {\\n\\t\\t\\t\\t\\tconst theta = i / capSegments * 2 * Math.PI;\\n\\t\\t\\t\\t\\tconst x = Math.sin(theta);\\n\\t\\t\\t\\t\\tconst y = -height / 2;\\n\\t\\t\\t\\t\\tconst z = Math.cos(theta);\\n\\t\\t\\t\\t\\tlet u = 1 - (x + 1) / 2;\\n\\t\\t\\t\\t\\tlet v = (z + 1) / 2;\\n\\t\\t\\t\\t\\tpositions.push(x * baseRadius, y, z * baseRadius);\\n\\t\\t\\t\\t\\tnormals.push(0, -1, 0);\\n\\t\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t\\t\\tu = u * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\tv = v * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\tu /= 3;\\n\\t\\t\\t\\t\\tv /= 3;\\n\\t\\t\\t\\t\\tu += 1 / 3;\\n\\t\\t\\t\\t\\tuvs1.push(u, 1 - v);\\n\\t\\t\\t\\t\\tif (i > 1) {\\n\\t\\t\\t\\t\\t\\tindices.push(offset, offset + i, offset + i - 1);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\toffset += capSegments;\\n\\t\\t\\tif (peakRadius > 0) {\\n\\t\\t\\t\\tfor (let i = 0; i < capSegments; i++) {\\n\\t\\t\\t\\t\\tconst theta = i / capSegments * 2 * Math.PI;\\n\\t\\t\\t\\t\\tconst x = Math.sin(theta);\\n\\t\\t\\t\\t\\tconst y = height / 2;\\n\\t\\t\\t\\t\\tconst z = Math.cos(theta);\\n\\t\\t\\t\\t\\tlet u = 1 - (x + 1) / 2;\\n\\t\\t\\t\\t\\tlet v = (z + 1) / 2;\\n\\t\\t\\t\\t\\tpositions.push(x * peakRadius, y, z * peakRadius);\\n\\t\\t\\t\\t\\tnormals.push(0, 1, 0);\\n\\t\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t\\t\\tu = u * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\tv = v * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\tu /= 3;\\n\\t\\t\\t\\t\\tv /= 3;\\n\\t\\t\\t\\t\\tu += 2 / 3;\\n\\t\\t\\t\\t\\tuvs1.push(u, 1 - v);\\n\\t\\t\\t\\t\\tif (i > 1) {\\n\\t\\t\\t\\t\\t\\tindices.push(offset, offset + i - 1, offset + i);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.positions = positions;\\n\\t\\tthis.normals = normals;\\n\\t\\tthis.uvs = uvs;\\n\\t\\tthis.uvs1 = uvs1;\\n\\t\\tthis.indices = indices;\\n\\t}\\n}\\n\\nclass CapsuleGeometry extends ConeBaseGeometry {\\n\\tconstructor(opts = {}) {\\n\\t\\tconst radius = opts.radius ?? 0.3;\\n\\t\\tconst height = opts.height ?? 1;\\n\\t\\tconst heightSegments = opts.heightSegments ?? 1;\\n\\t\\tconst sides = opts.sides ?? 20;\\n\\t\\tsuper(radius, radius, height - 2 * radius, heightSegments, sides, true);\\n\\t\\tif (opts.calculateTangents) {\\n\\t\\t\\tthis.tangents = calculateTangents(this.positions, this.normals, this.uvs, this.indices);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass ConeGeometry extends ConeBaseGeometry {\\n\\tconstructor(opts = {}) {\\n\\t\\tconst baseRadius = opts.baseRadius ?? 0.5;\\n\\t\\tconst peakRadius = opts.peakRadius ?? 0;\\n\\t\\tconst height = opts.height ?? 1;\\n\\t\\tconst heightSegments = opts.heightSegments ?? 5;\\n\\t\\tconst capSegments = opts.capSegments ?? 18;\\n\\t\\tsuper(baseRadius, peakRadius, height, heightSegments, capSegments, false);\\n\\t\\tif (opts.calculateTangents) {\\n\\t\\t\\tthis.tangents = calculateTangents(this.positions, this.normals, this.uvs, this.indices);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass CylinderGeometry extends ConeBaseGeometry {\\n\\tconstructor(opts = {}) {\\n\\t\\tconst radius = opts.radius ?? 0.5;\\n\\t\\tconst height = opts.height ?? 1;\\n\\t\\tconst heightSegments = opts.heightSegments ?? 5;\\n\\t\\tconst capSegments = opts.capSegments ?? 20;\\n\\t\\tsuper(radius, radius, height, heightSegments, capSegments, false);\\n\\t\\tif (opts.calculateTangents) {\\n\\t\\t\\tthis.tangents = calculateTangents(this.positions, this.normals, this.uvs, this.indices);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass PlaneGeometry extends Geometry {\\n\\tconstructor(opts = {}) {\\n\\t\\tsuper();\\n\\t\\tconst he = opts.halfExtents ?? new Vec2(0.5, 0.5);\\n\\t\\tconst ws = opts.widthSegments ?? 5;\\n\\t\\tconst ls = opts.lengthSegments ?? 5;\\n\\t\\tconst positions = [];\\n\\t\\tconst normals = [];\\n\\t\\tconst uvs = [];\\n\\t\\tconst indices = [];\\n\\t\\tlet vcounter = 0;\\n\\t\\tfor (let i = 0; i <= ws; i++) {\\n\\t\\t\\tfor (let j = 0; j <= ls; j++) {\\n\\t\\t\\t\\tconst x = -he.x + 2 * he.x * i / ws;\\n\\t\\t\\t\\tconst y = 0;\\n\\t\\t\\t\\tconst z = -(-he.y + 2 * he.y * j / ls);\\n\\t\\t\\t\\tconst u = i / ws;\\n\\t\\t\\t\\tconst v = j / ls;\\n\\t\\t\\t\\tpositions.push(x, y, z);\\n\\t\\t\\t\\tnormals.push(0, 1, 0);\\n\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t\\tif (i < ws && j < ls) {\\n\\t\\t\\t\\t\\tindices.push(vcounter + ls + 1, vcounter + 1, vcounter);\\n\\t\\t\\t\\t\\tindices.push(vcounter + ls + 1, vcounter + ls + 2, vcounter + 1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tvcounter++;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.positions = positions;\\n\\t\\tthis.normals = normals;\\n\\t\\tthis.uvs = uvs;\\n\\t\\tthis.uvs1 = uvs;\\n\\t\\tthis.indices = indices;\\n\\t\\tif (opts.calculateTangents) {\\n\\t\\t\\tthis.tangents = calculateTangents(positions, normals, uvs, indices);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass TorusGeometry extends Geometry {\\n\\tconstructor(opts = {}) {\\n\\t\\tsuper();\\n\\t\\tconst rc = opts.tubeRadius ?? 0.2;\\n\\t\\tconst rt = opts.ringRadius ?? 0.3;\\n\\t\\tconst sectorAngle = (opts.sectorAngle ?? 360) * math.DEG_TO_RAD;\\n\\t\\tconst segments = opts.segments ?? 30;\\n\\t\\tconst sides = opts.sides ?? 20;\\n\\t\\tconst positions = [];\\n\\t\\tconst normals = [];\\n\\t\\tconst uvs = [];\\n\\t\\tconst indices = [];\\n\\t\\tfor (let i = 0; i <= sides; i++) {\\n\\t\\t\\tfor (let j = 0; j <= segments; j++) {\\n\\t\\t\\t\\tconst x = Math.cos(sectorAngle * j / segments) * (rt + rc * Math.cos(2 * Math.PI * i / sides));\\n\\t\\t\\t\\tconst y = Math.sin(2 * Math.PI * i / sides) * rc;\\n\\t\\t\\t\\tconst z = Math.sin(sectorAngle * j / segments) * (rt + rc * Math.cos(2 * Math.PI * i / sides));\\n\\t\\t\\t\\tconst nx = Math.cos(sectorAngle * j / segments) * Math.cos(2 * Math.PI * i / sides);\\n\\t\\t\\t\\tconst ny = Math.sin(2 * Math.PI * i / sides);\\n\\t\\t\\t\\tconst nz = Math.sin(sectorAngle * j / segments) * Math.cos(2 * Math.PI * i / sides);\\n\\t\\t\\t\\tconst u = i / sides;\\n\\t\\t\\t\\tconst v = 1 - j / segments;\\n\\t\\t\\t\\tpositions.push(x, y, z);\\n\\t\\t\\t\\tnormals.push(nx, ny, nz);\\n\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t\\tif (i < sides && j < segments) {\\n\\t\\t\\t\\t\\tconst first = i * (segments + 1) + j;\\n\\t\\t\\t\\t\\tconst second = (i + 1) * (segments + 1) + j;\\n\\t\\t\\t\\t\\tconst third = i * (segments + 1) + (j + 1);\\n\\t\\t\\t\\t\\tconst fourth = (i + 1) * (segments + 1) + (j + 1);\\n\\t\\t\\t\\t\\tindices.push(first, second, third);\\n\\t\\t\\t\\t\\tindices.push(second, fourth, third);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.positions = positions;\\n\\t\\tthis.normals = normals;\\n\\t\\tthis.uvs = uvs;\\n\\t\\tthis.uvs1 = uvs;\\n\\t\\tthis.indices = indices;\\n\\t\\tif (opts.calculateTangents) {\\n\\t\\t\\tthis.tangents = calculateTangents(positions, normals, uvs, indices);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass ProgramLibrary {\\n\\tprocessedCache = /* @__PURE__ */ new Map();\\n\\tdefinitionsCache = /* @__PURE__ */ new Map();\\n\\t_generators = /* @__PURE__ */ new Map();\\n\\tconstructor(device, standardMaterial) {\\n\\t\\tthis._device = device;\\n\\t\\tthis._isClearingCache = false;\\n\\t\\tthis._precached = false;\\n\\t\\tthis._programsCollection = [];\\n\\t\\tthis._defaultStdMatOption = new StandardMaterialOptions();\\n\\t\\tthis._defaultStdMatOptionMin = new StandardMaterialOptions();\\n\\t\\tconst defaultCameraShaderParams = new CameraShaderParams();\\n\\t\\tstandardMaterial.shaderOptBuilder.updateRef(\\n\\t\\t\\tthis._defaultStdMatOption,\\n\\t\\t\\t{},\\n\\t\\t\\tdefaultCameraShaderParams,\\n\\t\\t\\tstandardMaterial,\\n\\t\\t\\tnull,\\n\\t\\t\\t[],\\n\\t\\t\\tSHADER_FORWARD,\\n\\t\\t\\tnull\\n\\t\\t);\\n\\t\\tstandardMaterial.shaderOptBuilder.updateMinRef(\\n\\t\\t\\tthis._defaultStdMatOptionMin,\\n\\t\\t\\t{},\\n\\t\\t\\tstandardMaterial,\\n\\t\\t\\tnull,\\n\\t\\t\\tSHADER_SHADOW,\\n\\t\\t\\tnull\\n\\t\\t);\\n\\t\\tdevice.on(\\\"destroy:shader\\\", (shader) => {\\n\\t\\t\\tthis.removeFromCache(shader);\\n\\t\\t});\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.clearCache();\\n\\t}\\n\\tregister(name, generator) {\\n\\t\\tif (!this._generators.has(name)) {\\n\\t\\t\\tthis._generators.set(name, generator);\\n\\t\\t}\\n\\t}\\n\\tunregister(name) {\\n\\t\\tif (this._generators.has(name)) {\\n\\t\\t\\tthis._generators.delete(name);\\n\\t\\t}\\n\\t}\\n\\tisRegistered(name) {\\n\\t\\treturn this._generators.has(name);\\n\\t}\\n\\tgenerateShaderDefinition(generator, name, key, options) {\\n\\t\\tlet def = this.definitionsCache.get(key);\\n\\t\\tif (!def) {\\n\\t\\t\\tlet lights;\\n\\t\\t\\tif (options.litOptions?.lights) {\\n\\t\\t\\t\\tlights = options.litOptions.lights;\\n\\t\\t\\t\\toptions.litOptions.lights = lights.map((l) => {\\n\\t\\t\\t\\t\\tconst lcopy = l.clone ? l.clone() : l;\\n\\t\\t\\t\\t\\tlcopy.key = l.key;\\n\\t\\t\\t\\t\\treturn lcopy;\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t\\tthis.storeNewProgram(name, options);\\n\\t\\t\\tif (options.litOptions?.lights) {\\n\\t\\t\\t\\toptions.litOptions.lights = lights;\\n\\t\\t\\t}\\n\\t\\t\\tif (this._precached) ;\\n\\t\\t\\tconst device = this._device;\\n\\t\\t\\tdef = generator.createShaderDefinition(device, options);\\n\\t\\t\\tdef.name = def.name ?? (options.pass ? `${name}-pass:${options.pass}` : name);\\n\\t\\t\\tthis.definitionsCache.set(key, def);\\n\\t\\t}\\n\\t\\treturn def;\\n\\t}\\n\\tgetCachedShader(key) {\\n\\t\\treturn this.processedCache.get(key);\\n\\t}\\n\\tsetCachedShader(key, shader) {\\n\\t\\tthis.processedCache.set(key, shader);\\n\\t}\\n\\tgetProgram(name, options, processingOptions, userMaterialId) {\\n\\t\\tconst generator = this._generators.get(name);\\n\\t\\tif (!generator) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tconst generationKeyString = generator.generateKey(options);\\n\\t\\tconst generationKey = hashCode(generationKeyString);\\n\\t\\tconst processingKeyString = processingOptions.generateKey(this._device);\\n\\t\\tconst processingKey = hashCode(processingKeyString);\\n\\t\\tconst totalKey = `${generationKey}#${processingKey}`;\\n\\t\\tlet processedShader = this.getCachedShader(totalKey);\\n\\t\\tif (!processedShader) {\\n\\t\\t\\tconst generatedShaderDef = this.generateShaderDefinition(generator, name, generationKey, options);\\n\\t\\t\\tlet passName = \\\"\\\";\\n\\t\\t\\tlet shaderPassInfo;\\n\\t\\t\\tif (options.pass !== void 0) {\\n\\t\\t\\t\\tshaderPassInfo = ShaderPass.get(this._device).getByIndex(options.pass);\\n\\t\\t\\t\\tpassName = `-${shaderPassInfo.name}`;\\n\\t\\t\\t}\\n\\t\\t\\tthis._device.fire(\\\"shader:generate\\\", {\\n\\t\\t\\t\\tuserMaterialId,\\n\\t\\t\\t\\tshaderPassInfo,\\n\\t\\t\\t\\tdefinition: generatedShaderDef\\n\\t\\t\\t});\\n\\t\\t\\tconst shaderDefinition = {\\n\\t\\t\\t\\tname: `${generatedShaderDef.name}${passName}-proc`,\\n\\t\\t\\t\\tattributes: generatedShaderDef.attributes,\\n\\t\\t\\t\\tvshader: generatedShaderDef.vshader,\\n\\t\\t\\t\\tvincludes: generatedShaderDef.vincludes,\\n\\t\\t\\t\\tfincludes: generatedShaderDef.fincludes,\\n\\t\\t\\t\\tfshader: generatedShaderDef.fshader,\\n\\t\\t\\t\\tprocessingOptions,\\n\\t\\t\\t\\tshaderLanguage: generatedShaderDef.shaderLanguage,\\n\\t\\t\\t\\tmeshUniformBufferFormat: generatedShaderDef.meshUniformBufferFormat,\\n\\t\\t\\t\\tmeshBindGroupFormat: generatedShaderDef.meshBindGroupFormat\\n\\t\\t\\t};\\n\\t\\t\\tprocessedShader = new Shader(this._device, shaderDefinition);\\n\\t\\t\\tthis.setCachedShader(totalKey, processedShader);\\n\\t\\t}\\n\\t\\treturn processedShader;\\n\\t}\\n\\tstoreNewProgram(name, options) {\\n\\t\\tlet opt = {};\\n\\t\\tif (name === \\\"standard\\\") {\\n\\t\\t\\tconst defaultMat = this._getDefaultStdMatOptions(options.pass);\\n\\t\\t\\tfor (const p in options) {\\n\\t\\t\\t\\tif (options.hasOwnProperty(p) && defaultMat[p] !== options[p] || p === \\\"pass\\\") {\\n\\t\\t\\t\\t\\topt[p] = options[p];\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tfor (const p in options.litOptions) {\\n\\t\\t\\t\\topt[p] = options.litOptions[p];\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\topt = options;\\n\\t\\t}\\n\\t\\tthis._programsCollection.push(JSON.stringify({ name, options: opt }));\\n\\t}\\n\\t// run pc.getProgramLibrary(device).dumpPrograms(); from browser console to build shader options script\\n\\tdumpPrograms() {\\n\\t\\tlet text = \\\"let device = pc.app ? pc.app.graphicsDevice : pc.Application.getApplication().graphicsDevice;\\\\n\\\";\\n\\t\\ttext += \\\"let shaders = [\\\";\\n\\t\\tif (this._programsCollection[0]) {\\n\\t\\t\\ttext += `\\n\\t${this._programsCollection[0]}`;\\n\\t\\t}\\n\\t\\tfor (let i = 1; i < this._programsCollection.length; ++i) {\\n\\t\\t\\ttext += `,\\n\\t${this._programsCollection[i]}`;\\n\\t\\t}\\n\\t\\ttext += \\\"\\\\n];\\\\n\\\";\\n\\t\\ttext += \\\"pc.getProgramLibrary(device).precompile(shaders);\\\\n\\\";\\n\\t\\ttext += `if (pc.version != \\\"${version$1}\\\" || pc.revision != \\\"${revision}\\\")\\n`;\\n\\t\\ttext += '\\tconsole.warn(\\\"precompile-shaders.js: engine version mismatch, rebuild shaders lib with current engine\\\");';\\n\\t\\tconst element = document.createElement(\\\"a\\\");\\n\\t\\telement.setAttribute(\\\"href\\\", `data:text/plain;charset=utf-8,${encodeURIComponent(text)}`);\\n\\t\\telement.setAttribute(\\\"download\\\", \\\"precompile-shaders.js\\\");\\n\\t\\telement.style.display = \\\"none\\\";\\n\\t\\tdocument.body.appendChild(element);\\n\\t\\telement.click();\\n\\t\\tdocument.body.removeChild(element);\\n\\t}\\n\\tclearCache() {\\n\\t\\tthis._isClearingCache = true;\\n\\t\\tthis.processedCache.forEach((shader) => {\\n\\t\\t\\tshader.destroy();\\n\\t\\t});\\n\\t\\tthis.processedCache.clear();\\n\\t\\tthis._isClearingCache = false;\\n\\t}\\n\\tremoveFromCache(shader) {\\n\\t\\tif (this._isClearingCache) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.processedCache.forEach((cachedShader, key) => {\\n\\t\\t\\tif (shader === cachedShader) {\\n\\t\\t\\t\\tthis.processedCache.delete(key);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n\\t_getDefaultStdMatOptions(pass) {\\n\\t\\tconst shaderPassInfo = ShaderPass.get(this._device).getByIndex(pass);\\n\\t\\treturn pass === SHADER_PICK || pass === SHADER_PREPASS || shaderPassInfo.isShadow ? this._defaultStdMatOptionMin : this._defaultStdMatOption;\\n\\t}\\n\\tprecompile(cache) {\\n\\t\\tif (cache) {\\n\\t\\t\\tconst shaders = new Array(cache.length);\\n\\t\\t\\tfor (let i = 0; i < cache.length; i++) {\\n\\t\\t\\t\\tif (cache[i].name === \\\"standard\\\") {\\n\\t\\t\\t\\t\\tconst opt = cache[i].options;\\n\\t\\t\\t\\t\\tconst defaultMat = this._getDefaultStdMatOptions(opt.pass);\\n\\t\\t\\t\\t\\tfor (const p in defaultMat) {\\n\\t\\t\\t\\t\\t\\tif (defaultMat.hasOwnProperty(p) && opt[p] === void 0) {\\n\\t\\t\\t\\t\\t\\t\\topt[p] = defaultMat[p];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tshaders[i] = this.getProgram(cache[i].name, cache[i].options);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._precached = true;\\n\\t}\\n}\\n\\nclass UploadStream {\\n\\t_deviceLostEvent = null;\\n\\tconstructor(device, useSingleBuffer = false) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.useSingleBuffer = useSingleBuffer;\\n\\t\\tthis.impl = device.createUploadStreamImpl(this);\\n\\t\\tthis._deviceLostEvent = this.device.on(\\\"devicelost\\\", this._onDeviceLost, this);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._deviceLostEvent?.off();\\n\\t\\tthis._deviceLostEvent = null;\\n\\t\\tthis.impl?.destroy();\\n\\t\\tthis.impl = null;\\n\\t}\\n\\tupload(data, target, offset = 0, size = data.length) {\\n\\t\\tthis.impl?.upload(data, target, offset, size);\\n\\t}\\n\\t_onDeviceLost() {\\n\\t\\tthis.impl?._onDeviceLost?.();\\n\\t}\\n}\\n\\nvar gsplatCopyToWorkbuffer_default$1 = `\\n#define GSPLAT_CENTER_NOPROJ\\n#include \\\"gsplatHelpersVS\\\"\\n#include \\\"gsplatFormatVS\\\"\\n#include \\\"gsplatStructsVS\\\"\\n#include \\\"gsplatDeclarationsVS\\\"\\n#include \\\"gsplatCenterVS\\\"\\n#include \\\"gsplatEvalSHVS\\\"\\n#include \\\"gsplatQuatToMat3VS\\\"\\n#include \\\"gsplatReadVS\\\"\\n#include \\\"gsplatWorkBufferOutputVS\\\"\\n#include \\\"gsplatWriteVS\\\"\\n#include \\\"gsplatModifyVS\\\"\\nflat varying ivec4 vSubDraw;\\nuniform vec3 uColorMultiply;\\nuniform vec3 model_scale;\\nuniform vec4 model_rotation;\\n#ifdef GSPLAT_ID\\n\\tuniform uint uId;\\n#endif\\nvoid main(void) {\\n\\tint localRow = int(gl_FragCoord.y) - vSubDraw.w;\\n\\tint localCol = int(gl_FragCoord.x) - vSubDraw.y;\\n\\tuint originalIndex = uint(vSubDraw.x + localRow * vSubDraw.z + localCol);\\n\\tsetSplat(originalIndex);\\n\\tvec3 modelCenter = getCenter();\\n\\tvec3 worldCenter = (matrix_model * vec4(modelCenter, 1.0)).xyz;\\n\\tSplatCenter center;\\n\\tinitCenter(modelCenter, center);\\n\\tvec4 srcRotation = getRotation().yzwx;\\n\\tvec3 srcScale = getScale();\\n\\tvec4 worldRotation = quatMul(model_rotation, srcRotation);\\n\\tif (worldRotation.w < 0.0) {\\n\\t\\tworldRotation = -worldRotation;\\n\\t}\\n\\tvec3 worldScale = model_scale * srcScale;\\n\\tvec3 originalCenter = worldCenter;\\n\\tmodifySplatCenter(worldCenter);\\n\\tmodifySplatRotationScale(originalCenter, worldCenter, worldRotation, worldScale);\\n\\tvec4 color = getColor();\\n\\t#if SH_BANDS > 0\\n\\t\\tvec3 dir = normalize(center.view * mat3(center.modelView));\\n\\t\\tvec3 sh[SH_COEFFS];\\n\\t\\tfloat scale;\\n\\t\\treadSHData(sh, scale);\\n\\t\\tcolor.xyz += evalSH(sh, dir) * scale;\\n\\t#endif\\n\\tmodifySplatColor(worldCenter, color);\\n\\tcolor.xyz *= uColorMultiply;\\n\\twriteSplat(worldCenter, worldRotation, worldScale, color);\\n\\t#ifdef GSPLAT_ID\\n\\t\\twritePcId(uvec4(uId, 0u, 0u, 0u));\\n\\t#endif\\n}\\n`;\\n\\nvar gsplatCopyToWorkbuffer_default = `\\n#define GSPLAT_CENTER_NOPROJ\\n#include \\\"gsplatHelpersVS\\\"\\n#include \\\"gsplatFormatVS\\\"\\n#include \\\"gsplatStructsVS\\\"\\n#include \\\"gsplatDeclarationsVS\\\"\\n#include \\\"gsplatCenterVS\\\"\\n#include \\\"gsplatEvalSHVS\\\"\\n#include \\\"gsplatQuatToMat3VS\\\"\\n#include \\\"gsplatReadVS\\\"\\nvar<private> processOutput: FragmentOutput;\\n#include \\\"gsplatWorkBufferOutputVS\\\"\\n#include \\\"gsplatWriteVS\\\"\\n#include \\\"gsplatModifyVS\\\"\\nvarying @interpolate(flat) vSubDraw: vec4i;\\nuniform uColorMultiply: vec3f;\\nuniform model_scale: vec3f;\\nuniform model_rotation: vec4f;\\n#ifdef GSPLAT_ID\\n\\tuniform uId: u32;\\n#endif\\n@fragment\\nfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\tlet localRow = i32(input.position.y) - input.vSubDraw.w;\\n\\tlet localCol = i32(input.position.x) - input.vSubDraw.y;\\n\\tlet originalIndex = u32(input.vSubDraw.x + localRow * input.vSubDraw.z + localCol);\\n\\tsetSplat(originalIndex);\\n\\tvar modelCenter = getCenter();\\n\\tvar worldCenter = (uniform.matrix_model * vec4f(modelCenter, 1.0)).xyz;\\n\\tvar center: SplatCenter;\\n\\tinitCenter(modelCenter, &center);\\n\\tlet srcRotation = getRotation().yzwx;\\n\\tlet srcScale = getScale();\\n\\tvar worldRotation = vec4f(quatMul(half4(uniform.model_rotation), half4(srcRotation)));\\n\\tif (worldRotation.w < 0.0) {\\n\\t\\tworldRotation = -worldRotation;\\n\\t}\\n\\tvar worldScale = uniform.model_scale * srcScale;\\n\\tlet originalCenter = worldCenter;\\n\\tmodifySplatCenter(&worldCenter);\\n\\tmodifySplatRotationScale(originalCenter, worldCenter, &worldRotation, &worldScale);\\n\\tvar color = getColor();\\n\\t#if SH_BANDS > 0\\n\\t\\tlet dir = normalize(center.view * mat3x3f(center.modelView[0].xyz, center.modelView[1].xyz, center.modelView[2].xyz));\\n\\t\\tvar sh: array<half3, SH_COEFFS>;\\n\\t\\tvar scale: f32;\\n\\t\\treadSHData(&sh, &scale);\\n\\t\\tcolor = vec4f(color.xyz + vec3f(evalSH(&sh, dir) * half(scale)), color.w);\\n\\t#endif\\n\\tmodifySplatColor(worldCenter, &color);\\n\\tcolor = vec4f(color.xyz * uniform.uColorMultiply, color.w);\\n\\twriteSplat(worldCenter, worldRotation, worldScale, color);\\n\\t#ifdef GSPLAT_ID\\n\\t\\twritePcId(vec4u(uniform.uId, 0u, 0u, 0u));\\n\\t#endif\\n\\treturn processOutput;\\n}\\n`;\\n\\nvar gsplatCopyInstancedQuad_default$1 = `\\nattribute vec2 vertex_position;\\nprecision highp usampler2D;\\nuniform usampler2D uSubDrawData;\\nuniform ivec2 uTextureSize;\\nuniform int uSubDrawBase;\\nflat varying ivec4 vSubDraw;\\nvoid main(void) {\\n\\tint subDrawWidth = textureSize(uSubDrawData, 0).x;\\n\\tint idx = gl_InstanceID + uSubDrawBase;\\n\\tuvec4 data = texelFetch(uSubDrawData, ivec2(idx % subDrawWidth, idx / subDrawWidth), 0);\\n\\tint rowStart = int(data.r & 0xFFFFu);\\n\\tint numRows = int(data.r >> 16u);\\n\\tint colStart = int(data.g);\\n\\tint colEnd = int(data.b);\\n\\tint sourceBase = int(data.a);\\n\\tfloat u = float(gl_VertexID & 1);\\n\\tfloat v = float(gl_VertexID >> 1);\\n\\tvec4 ndc = vec4(colStart, colEnd, rowStart, rowStart + numRows) / vec4(uTextureSize.x, uTextureSize.x, uTextureSize.y, uTextureSize.y) * 2.0 - 1.0;\\n\\tgl_Position = vec4(mix(ndc.x, ndc.y, u), mix(ndc.z, ndc.w, v), 0.5, 1.0);\\n\\tvSubDraw = ivec4(sourceBase, colStart, colEnd - colStart, rowStart);\\n}\\n`;\\n\\nvar gsplatCopyInstancedQuad_default = `\\nattribute vertex_position: vec2f;\\nvar uSubDrawData: texture_2d<u32>;\\nuniform uTextureSize: vec2i;\\nuniform uSubDrawBase: i32;\\nvarying @interpolate(flat) vSubDraw: vec4i;\\n@vertex\\nfn vertexMain(input: VertexInput) -> VertexOutput {\\n\\tvar output: VertexOutput;\\n\\tlet subDrawWidth = i32(textureDimensions(uSubDrawData, 0).x);\\n\\tlet instIdx = i32(input.instanceIndex) + uniform.uSubDrawBase;\\n\\tlet data = textureLoad(uSubDrawData, vec2i(instIdx % subDrawWidth, instIdx / subDrawWidth), 0);\\n\\tlet rowStart = i32(data.r & 0xFFFFu);\\n\\tlet numRows = i32(data.r >> 16u);\\n\\tlet colStart = i32(data.g);\\n\\tlet colEnd = i32(data.b);\\n\\tlet sourceBase = i32(data.a);\\n\\tlet u = f32(i32(input.vertexIndex) & 1);\\n\\tlet v = f32(i32(input.vertexIndex) >> 1u);\\n\\tlet ndc = vec4f(f32(colStart), f32(colEnd), f32(rowStart), f32(rowStart + numRows)) / vec4f(f32(uniform.uTextureSize.x), f32(uniform.uTextureSize.x), f32(uniform.uTextureSize.y), f32(uniform.uTextureSize.y)) * 2.0 - 1.0;\\n\\toutput.position = vec4f(mix(ndc.x, ndc.y, u), mix(-ndc.z, -ndc.w, v), 0.5, 1.0);\\n\\toutput.vSubDraw = vec4i(sourceBase, colStart, colEnd - colStart, rowStart);\\n\\treturn output;\\n}\\n`;\\n\\nconst _viewProjMat$2 = new Mat4();\\nconst _frustum = new Frustum();\\nconst BOUNDS_ENTRY_FLOATS = 8;\\nclass GSplatFrustumCuller {\\n\\tdevice;\\n\\tboundsBuffer = null;\\n\\ttotalBoundsEntries = 0;\\n\\t_allocatedBoundsEntries = 0;\\n\\t_boundsFloatView = null;\\n\\t_boundsUintView = null;\\n\\t_tmpSpheres = null;\\n\\ttransformsBuffer = null;\\n\\t_allocatedTransformCount = 0;\\n\\t_transformsData = null;\\n\\tfrustumPlanes = new Float32Array(24);\\n\\tfisheyeCameraPos = new Float32Array(3);\\n\\tfisheyeCameraForward = new Float32Array(3);\\n\\tfisheyeMaxTheta = Math.PI;\\n\\tconstructor(device) {\\n\\t\\tthis.device = device;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.boundsBuffer?.destroy();\\n\\t\\tthis.transformsBuffer?.destroy();\\n\\t}\\n\\tupdateBoundsData(boundsGroups) {\\n\\t\\tlet totalEntries = 0;\\n\\t\\tfor (let i = 0; i < boundsGroups.length; i++) {\\n\\t\\t\\ttotalEntries += boundsGroups[i].numBoundsEntries;\\n\\t\\t}\\n\\t\\tthis.totalBoundsEntries = totalEntries;\\n\\t\\tif (totalEntries === 0) return;\\n\\t\\tif (totalEntries > this._allocatedBoundsEntries) {\\n\\t\\t\\tthis.boundsBuffer?.destroy();\\n\\t\\t\\tthis._allocatedBoundsEntries = totalEntries;\\n\\t\\t\\tthis.boundsBuffer = new StorageBuffer(this.device, totalEntries * BOUNDS_ENTRY_FLOATS * 4, BUFFERUSAGE_COPY_DST);\\n\\t\\t\\tconst ab = new ArrayBuffer(totalEntries * BOUNDS_ENTRY_FLOATS * 4);\\n\\t\\t\\tthis._boundsFloatView = new Float32Array(ab);\\n\\t\\t\\tthis._boundsUintView = new Uint32Array(ab);\\n\\t\\t\\tthis._tmpSpheres = new Float32Array(totalEntries * 4);\\n\\t\\t}\\n\\t\\tconst floatView = this._boundsFloatView;\\n\\t\\tconst uintView = this._boundsUintView;\\n\\t\\tconst tmpSpheres = this._tmpSpheres;\\n\\t\\tfor (let i = 0; i < boundsGroups.length; i++) {\\n\\t\\t\\tconst group = boundsGroups[i];\\n\\t\\t\\tconst base = group.boundsBaseIndex;\\n\\t\\t\\tconst count = group.numBoundsEntries;\\n\\t\\t\\tgroup.splat.writeBoundsSpheres(tmpSpheres, base * 4);\\n\\t\\t\\tfor (let j = 0; j < count; j++) {\\n\\t\\t\\t\\tconst src = (base + j) * 4;\\n\\t\\t\\t\\tconst dst = (base + j) * BOUNDS_ENTRY_FLOATS;\\n\\t\\t\\t\\tfloatView[dst + 0] = tmpSpheres[src + 0];\\n\\t\\t\\t\\tfloatView[dst + 1] = tmpSpheres[src + 1];\\n\\t\\t\\t\\tfloatView[dst + 2] = tmpSpheres[src + 2];\\n\\t\\t\\t\\tfloatView[dst + 3] = tmpSpheres[src + 3];\\n\\t\\t\\t\\tuintView[dst + 4] = i;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.boundsBuffer.write(0, floatView);\\n\\t}\\n\\tupdateTransformsData(boundsGroups) {\\n\\t\\tconst numMatrices = boundsGroups.length;\\n\\t\\tif (numMatrices === 0) return;\\n\\t\\tif (numMatrices > this._allocatedTransformCount) {\\n\\t\\t\\tthis.transformsBuffer?.destroy();\\n\\t\\t\\tthis._allocatedTransformCount = numMatrices;\\n\\t\\t\\tthis.transformsBuffer = new StorageBuffer(this.device, numMatrices * 12 * 4, BUFFERUSAGE_COPY_DST);\\n\\t\\t\\tthis._transformsData = new Float32Array(numMatrices * 12);\\n\\t\\t}\\n\\t\\tconst data = this._transformsData;\\n\\t\\tlet offset = 0;\\n\\t\\tfor (let i = 0; i < boundsGroups.length; i++) {\\n\\t\\t\\tconst m = boundsGroups[i].splat.node.getWorldTransform().data;\\n\\t\\t\\tdata[offset++] = m[0];\\n\\t\\t\\tdata[offset++] = m[4];\\n\\t\\t\\tdata[offset++] = m[8];\\n\\t\\t\\tdata[offset++] = m[12];\\n\\t\\t\\tdata[offset++] = m[1];\\n\\t\\t\\tdata[offset++] = m[5];\\n\\t\\t\\tdata[offset++] = m[9];\\n\\t\\t\\tdata[offset++] = m[13];\\n\\t\\t\\tdata[offset++] = m[2];\\n\\t\\t\\tdata[offset++] = m[6];\\n\\t\\t\\tdata[offset++] = m[10];\\n\\t\\t\\tdata[offset++] = m[14];\\n\\t\\t}\\n\\t\\tthis.transformsBuffer.write(0, data);\\n\\t}\\n\\tcomputeFrustumPlanes(projectionMatrix, viewMatrix) {\\n\\t\\t_viewProjMat$2.mul2(projectionMatrix, viewMatrix);\\n\\t\\t_frustum.setFromMat4(_viewProjMat$2);\\n\\t\\tconst planes = this.frustumPlanes;\\n\\t\\tfor (let p = 0; p < 6; p++) {\\n\\t\\t\\tconst plane = _frustum.planes[p];\\n\\t\\t\\tplanes[p * 4 + 0] = plane.normal.x;\\n\\t\\t\\tplanes[p * 4 + 1] = plane.normal.y;\\n\\t\\t\\tplanes[p * 4 + 2] = plane.normal.z;\\n\\t\\t\\tplanes[p * 4 + 3] = plane.distance;\\n\\t\\t}\\n\\t}\\n\\tsetFisheyeData(cameraPos, cameraForward, maxTheta) {\\n\\t\\tthis.fisheyeCameraPos[0] = cameraPos.x;\\n\\t\\tthis.fisheyeCameraPos[1] = cameraPos.y;\\n\\t\\tthis.fisheyeCameraPos[2] = cameraPos.z;\\n\\t\\tthis.fisheyeCameraForward[0] = cameraForward.x;\\n\\t\\tthis.fisheyeCameraForward[1] = cameraForward.y;\\n\\t\\tthis.fisheyeCameraForward[2] = cameraForward.z;\\n\\t\\tthis.fisheyeMaxTheta = maxTheta;\\n\\t}\\n}\\n\\nconst _viewMat = new Mat4();\\nconst _modelScale = new Vec3();\\nconst _modelRotation = new Quat();\\nconst _tmpSize = new Vec2();\\nconst _whiteColor = [1, 1, 1];\\nclass GSplatWorkBufferRenderPass extends RenderPass {\\n\\tsplats = [];\\n\\tcolorsByLod = void 0;\\n\\tcameraNode = null;\\n\\tworkBuffer;\\n\\tcolorOnly;\\n\\t_modelScaleData = new Float32Array(3);\\n\\t_modelRotationData = new Float32Array(4);\\n\\t_textureSize = new Int32Array(2);\\n\\t_subDrawTexture;\\n\\t_partialData = [];\\n\\tconstructor(device, workBuffer, colorOnly = false) {\\n\\t\\tsuper(device);\\n\\t\\tthis.workBuffer = workBuffer;\\n\\t\\tthis.colorOnly = colorOnly;\\n\\t\\tthis._subDrawTexture = Texture.createDataTexture2D(device, \\\"GsplatSubDrawData\\\", 1, 1, PIXELFORMAT_RGBA32U);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.splats.length = 0;\\n\\t\\tthis._subDrawTexture.destroy();\\n\\t\\tsuper.destroy();\\n\\t}\\n\\tinit(renderTarget) {\\n\\t\\tsuper.init(renderTarget);\\n\\t\\tthis.colorOps.clear = false;\\n\\t\\tthis.depthStencilOps.clearDepth = false;\\n\\t}\\n\\tupdate(splats, cameraNode, colorsByLod, changedAllocIds = null) {\\n\\t\\tthis.splats.length = 0;\\n\\t\\tthis._partialData.length = 0;\\n\\t\\tthis.colorsByLod = colorsByLod;\\n\\t\\tconst textureWidth = this.workBuffer.textureSize;\\n\\t\\tif (changedAllocIds) {\\n\\t\\t\\tconst requiredCapacity = changedAllocIds.size * 3;\\n\\t\\t\\tif (this._subDrawTexture.width * this._subDrawTexture.height < requiredCapacity) {\\n\\t\\t\\t\\tTextureUtils.calcTextureSize(requiredCapacity, _tmpSize);\\n\\t\\t\\t\\tthis._subDrawTexture.resize(_tmpSize.x, _tmpSize.y);\\n\\t\\t\\t}\\n\\t\\t\\tconst texData = this._subDrawTexture.lock();\\n\\t\\t\\tlet writeOffset = 0;\\n\\t\\t\\tfor (let i = 0; i < splats.length; i++) {\\n\\t\\t\\t\\tconst splatInfo = splats[i];\\n\\t\\t\\t\\tif (splatInfo.activeSplats <= 0) continue;\\n\\t\\t\\t\\tconst intervals = splatInfo.intervals;\\n\\t\\t\\t\\tconst numIntervals = intervals.length / 2;\\n\\t\\t\\t\\tif (numIntervals === 0) {\\n\\t\\t\\t\\t\\tif (changedAllocIds.has(splatInfo.allocId)) {\\n\\t\\t\\t\\t\\t\\tthis.splats.push(splatInfo);\\n\\t\\t\\t\\t\\t\\tthis._partialData.push(0, 0);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tconst baseOffset = writeOffset;\\n\\t\\t\\t\\t\\tconst allocIds = splatInfo.intervalAllocIds;\\n\\t\\t\\t\\t\\tfor (let j = 0; j < numIntervals; j++) {\\n\\t\\t\\t\\t\\t\\tif (changedAllocIds.has(allocIds[j])) {\\n\\t\\t\\t\\t\\t\\t\\twriteOffset = splatInfo.appendSubDraws(\\n\\t\\t\\t\\t\\t\\t\\t\\ttexData,\\n\\t\\t\\t\\t\\t\\t\\t\\twriteOffset,\\n\\t\\t\\t\\t\\t\\t\\t\\tintervals[j * 2],\\n\\t\\t\\t\\t\\t\\t\\t\\tintervals[j * 2 + 1] - intervals[j * 2],\\n\\t\\t\\t\\t\\t\\t\\t\\tsplatInfo.intervalOffsets[j],\\n\\t\\t\\t\\t\\t\\t\\t\\ttextureWidth\\n\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tconst count = writeOffset - baseOffset;\\n\\t\\t\\t\\t\\tif (count > 0) {\\n\\t\\t\\t\\t\\t\\tthis.splats.push(splatInfo);\\n\\t\\t\\t\\t\\t\\tthis._partialData.push(baseOffset, count);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis._subDrawTexture.unlock();\\n\\t\\t} else {\\n\\t\\t\\tfor (let i = 0; i < splats.length; i++) {\\n\\t\\t\\t\\tconst splatInfo = splats[i];\\n\\t\\t\\t\\tif (splatInfo.activeSplats > 0) {\\n\\t\\t\\t\\t\\tthis.splats.push(splatInfo);\\n\\t\\t\\t\\t\\tthis._partialData.push(0, 0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < this.splats.length; i++) {\\n\\t\\t\\tif (this._partialData[i * 2 + 1] === 0) {\\n\\t\\t\\t\\tthis.splats[i].ensureSubDrawTexture(textureWidth);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.cameraNode = cameraNode;\\n\\t\\treturn this.splats.length > 0;\\n\\t}\\n\\texecute() {\\n\\t\\tconst { device, splats, cameraNode, _partialData } = this;\\n\\t\\tdevice.setDrawStates();\\n\\t\\tconst viewInvMat = cameraNode.getWorldTransform();\\n\\t\\tconst viewMat = _viewMat.copy(viewInvMat).invert();\\n\\t\\tdevice.scope.resolve(\\\"matrix_view\\\").setValue(viewMat.data);\\n\\t\\tfor (let i = 0; i < splats.length; i++) {\\n\\t\\t\\tconst count = _partialData[i * 2 + 1];\\n\\t\\t\\tif (count > 0) {\\n\\t\\t\\t\\tthis.renderSplat(splats[i], this._subDrawTexture, count, _partialData[i * 2]);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.renderSplat(splats[i]);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\trenderSplat(splatInfo, overrideSubDrawTexture, overrideSubDrawCount, subDrawBase = 0) {\\n\\t\\tconst { device, resource } = splatInfo;\\n\\t\\tconst scope = device.scope;\\n\\t\\tconst subDrawTexture = overrideSubDrawTexture ?? splatInfo.subDrawTexture;\\n\\t\\tconst subDrawCount = overrideSubDrawCount ?? splatInfo.subDrawCount;\\n\\t\\tconst workBufferModifier = splatInfo.getWorkBufferModifier?.() ?? null;\\n\\t\\tconst formatHash = resource.format.hash;\\n\\t\\tconst formatDeclarations = resource.format.getInputDeclarations();\\n\\t\\tconst workBufferRenderInfo = resource.getWorkBufferRenderInfo(\\n\\t\\t\\tthis.colorOnly,\\n\\t\\t\\tworkBufferModifier,\\n\\t\\t\\tformatHash,\\n\\t\\t\\tformatDeclarations,\\n\\t\\t\\tthis.workBuffer.format\\n\\t\\t);\\n\\t\\tworkBufferRenderInfo.material.setParameters(device);\\n\\t\\tconst color = this.colorsByLod?.[splatInfo.lodIndex] ?? this.colorsByLod?.[0] ?? _whiteColor;\\n\\t\\tscope.resolve(\\\"uColorMultiply\\\").setValue(color);\\n\\t\\tconst worldTransform = splatInfo.node.getWorldTransform();\\n\\t\\tworldTransform.getScale(_modelScale);\\n\\t\\t_modelRotation.setFromMat4(worldTransform);\\n\\t\\tif (_modelRotation.w < 0) {\\n\\t\\t\\t_modelRotation.mulScalar(-1);\\n\\t\\t}\\n\\t\\tthis._modelScaleData[0] = _modelScale.x;\\n\\t\\tthis._modelScaleData[1] = _modelScale.y;\\n\\t\\tthis._modelScaleData[2] = _modelScale.z;\\n\\t\\tthis._modelRotationData[0] = _modelRotation.x;\\n\\t\\tthis._modelRotationData[1] = _modelRotation.y;\\n\\t\\tthis._modelRotationData[2] = _modelRotation.z;\\n\\t\\tthis._modelRotationData[3] = _modelRotation.w;\\n\\t\\tscope.resolve(\\\"matrix_model\\\").setValue(worldTransform.data);\\n\\t\\tscope.resolve(\\\"model_scale\\\").setValue(this._modelScaleData);\\n\\t\\tscope.resolve(\\\"model_rotation\\\").setValue(this._modelRotationData);\\n\\t\\tscope.resolve(\\\"uId\\\").setValue(splatInfo.placementId);\\n\\t\\tif (splatInfo.parameters) {\\n\\t\\t\\tfor (const param of splatInfo.parameters.values()) {\\n\\t\\t\\t\\tparam.scopeId.setValue(param.data);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst instanceStreams = splatInfo.getInstanceStreams?.();\\n\\t\\tif (instanceStreams) {\\n\\t\\t\\tinstanceStreams.syncWithFormat(splatInfo.resource.format);\\n\\t\\t\\tfor (const [name, texture] of instanceStreams.textures) {\\n\\t\\t\\t\\tscope.resolve(name).setValue(texture);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tscope.resolve(\\\"uSubDrawData\\\").setValue(subDrawTexture);\\n\\t\\tscope.resolve(\\\"uSubDrawBase\\\").setValue(subDrawBase);\\n\\t\\tconst ts = this.workBuffer.textureSize;\\n\\t\\tthis._textureSize[0] = ts;\\n\\t\\tthis._textureSize[1] = ts;\\n\\t\\tscope.resolve(\\\"uTextureSize\\\").setValue(this._textureSize);\\n\\t\\tworkBufferRenderInfo.quadRender.render(void 0, void 0, subDrawCount);\\n\\t}\\n}\\n\\nclass GSplatStreams {\\n\\tdevice;\\n\\tformat = null;\\n\\ttextures = /* @__PURE__ */ new Map();\\n\\t_textureDimensions = new Vec2();\\n\\t_isInstance = false;\\n\\t_formatVersion = -1;\\n\\tget textureDimensions() {\\n\\t\\treturn this._textureDimensions;\\n\\t}\\n\\tconstructor(device, isInstance = false) {\\n\\t\\tthis.device = device;\\n\\t\\tthis._isInstance = isInstance;\\n\\t}\\n\\tdestroy() {\\n\\t\\tfor (const texture of this.textures.values()) {\\n\\t\\t\\ttexture.destroy();\\n\\t\\t}\\n\\t\\tthis.textures.clear();\\n\\t}\\n\\tinit(format, numElements) {\\n\\t\\tthis.format = format;\\n\\t\\tthis._textureDimensions = TextureUtils.calcTextureSize(numElements, new Vec2());\\n\\t\\tconst streams = this._isInstance ? format.instanceStreams : format.resourceStreams;\\n\\t\\tfor (const stream of streams) {\\n\\t\\t\\tconst texture = this.createTexture(stream.name, stream.format, this._textureDimensions);\\n\\t\\t\\tthis.textures.set(stream.name, texture);\\n\\t\\t}\\n\\t\\tthis._formatVersion = format.extraStreamsVersion;\\n\\t}\\n\\tgetTexture(name) {\\n\\t\\tthis.syncWithFormat(this.format);\\n\\t\\treturn this.textures.get(name);\\n\\t}\\n\\tgetTexturesInOrder() {\\n\\t\\tconst result = [];\\n\\t\\tif (this.format) {\\n\\t\\t\\tconst allStreams = this._isInstance ? this.format.instanceStreams : this.format.resourceStreams;\\n\\t\\t\\tfor (const stream of allStreams) {\\n\\t\\t\\t\\tconst texture = this.textures.get(stream.name);\\n\\t\\t\\t\\tif (texture) {\\n\\t\\t\\t\\t\\tresult.push(texture);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n\\tsyncWithFormat(format) {\\n\\t\\tif (format) {\\n\\t\\t\\tif (this.format === format && this._formatVersion === format.extraStreamsVersion) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tthis.format = format;\\n\\t\\t\\tconst streams = this._isInstance ? format.instanceStreams : format.resourceStreams;\\n\\t\\t\\tfor (const stream of streams) {\\n\\t\\t\\t\\tif (!this.textures.has(stream.name)) {\\n\\t\\t\\t\\t\\tconst texture = this.createTexture(stream.name, stream.format, this._textureDimensions);\\n\\t\\t\\t\\t\\tthis.textures.set(stream.name, texture);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis._formatVersion = format.extraStreamsVersion;\\n\\t\\t}\\n\\t}\\n\\tresize(width, height) {\\n\\t\\tthis._textureDimensions.set(width, height);\\n\\t\\tfor (const texture of this.textures.values()) {\\n\\t\\t\\ttexture.resize(width, height);\\n\\t\\t}\\n\\t}\\n\\tcreateTexture(name, format, size, data) {\\n\\t\\treturn Texture.createDataTexture2D(this.device, name, size.x, size.y, format, data ? [data] : void 0);\\n\\t}\\n}\\n\\nlet id$1 = 0;\\nclass WorkBufferRenderInfo {\\n\\tmaterial;\\n\\tquadRender;\\n\\tconstructor(device, key, material, colorOnly, format) {\\n\\t\\tthis.material = material;\\n\\t\\tconst clonedDefines = new Map(material.defines);\\n\\t\\tconst colorStream = format.getStream(\\\"dataColor\\\");\\n\\t\\tif (colorStream.format === PIXELFORMAT_RGBA16U) {\\n\\t\\t\\tclonedDefines.set(\\\"GSPLAT_COLOR_UINT\\\", \\\"\\\");\\n\\t\\t}\\n\\t\\tif (colorOnly) {\\n\\t\\t\\tclonedDefines.set(\\\"GSPLAT_COLOR_ONLY\\\", \\\"\\\");\\n\\t\\t}\\n\\t\\tif (format.getStream(\\\"pcId\\\")) {\\n\\t\\t\\tclonedDefines.set(\\\"GSPLAT_ID\\\", \\\"\\\");\\n\\t\\t}\\n\\t\\tconst fragmentIncludes = material.hasShaderChunks ? device.isWebGPU ? material.shaderChunks.wgsl : material.shaderChunks.glsl : void 0;\\n\\t\\tconst outputStreams = colorOnly ? [colorStream] : [...format.streams, ...format.extraStreams];\\n\\t\\tconst fragmentOutputTypes = [];\\n\\t\\tfor (const stream of outputStreams) {\\n\\t\\t\\tconst info = getGlslShaderType(stream.format);\\n\\t\\t\\tfragmentOutputTypes.push(info.returnType);\\n\\t\\t}\\n\\t\\tconst useInstanced = clonedDefines.has(\\\"GSPLAT_LOD\\\");\\n\\t\\tconst shaderOptions = {\\n\\t\\t\\tuniqueName: `SplatCopyToWorkBuffer:${key}`,\\n\\t\\t\\tattributes: { vertex_position: SEMANTIC_POSITION },\\n\\t\\t\\tvertexDefines: clonedDefines,\\n\\t\\t\\tfragmentDefines: clonedDefines,\\n\\t\\t\\tfragmentGLSL: gsplatCopyToWorkbuffer_default$1,\\n\\t\\t\\tfragmentWGSL: gsplatCopyToWorkbuffer_default,\\n\\t\\t\\tfragmentIncludes,\\n\\t\\t\\tfragmentOutputTypes\\n\\t\\t};\\n\\t\\tif (useInstanced) {\\n\\t\\t\\tshaderOptions.vertexGLSL = gsplatCopyInstancedQuad_default$1;\\n\\t\\t\\tshaderOptions.vertexWGSL = gsplatCopyInstancedQuad_default;\\n\\t\\t} else {\\n\\t\\t\\tshaderOptions.vertexChunk = \\\"fullscreenQuadVS\\\";\\n\\t\\t}\\n\\t\\tconst shader = ShaderUtils.createShader(device, shaderOptions);\\n\\t\\tthis.quadRender = new QuadRender(shader);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.material?.destroy();\\n\\t\\tthis.quadRender?.destroy();\\n\\t}\\n}\\nclass GSplatWorkBuffer {\\n\\tdevice;\\n\\tformat;\\n\\tid = id$1++;\\n\\tstreams;\\n\\trenderTarget;\\n\\tcolorRenderTarget;\\n\\torderTexture;\\n\\torderBuffer;\\n\\tuploadStream;\\n\\trenderPass;\\n\\tcolorRenderPass;\\n\\tfrustumCuller;\\n\\tconstructor(device, format) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.format = format;\\n\\t\\tthis.frustumCuller = new GSplatFrustumCuller(device);\\n\\t\\tthis.streams = new GSplatStreams(device);\\n\\t\\tthis.streams.init(format, 1);\\n\\t\\tthis._createRenderTargets();\\n\\t\\tthis.uploadStream = new UploadStream(device, !device.isWebGPU);\\n\\t\\tif (device.isWebGPU) {\\n\\t\\t\\tthis.orderBuffer = new StorageBuffer(device, 4, BUFFERUSAGE_COPY_DST);\\n\\t\\t} else {\\n\\t\\t\\tthis.orderTexture = new Texture(device, {\\n\\t\\t\\t\\tname: \\\"SplatGlobalOrder\\\",\\n\\t\\t\\t\\twidth: 1,\\n\\t\\t\\t\\theight: 1,\\n\\t\\t\\t\\tformat: PIXELFORMAT_R32U,\\n\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tthis.renderPass = new GSplatWorkBufferRenderPass(device, this);\\n\\t\\tthis.renderPass.init(this.renderTarget);\\n\\t\\tthis.colorRenderPass = new GSplatWorkBufferRenderPass(device, this, true);\\n\\t\\tthis.colorRenderPass.init(this.colorRenderTarget);\\n\\t}\\n\\t_createRenderTargets() {\\n\\t\\tthis.renderTarget?.destroy();\\n\\t\\tthis.colorRenderTarget?.destroy();\\n\\t\\tconst colorBuffers = this.streams.getTexturesInOrder();\\n\\t\\tthis.renderTarget = new RenderTarget({\\n\\t\\t\\tname: `GsplatWorkBuffer-MRT-${this.id}`,\\n\\t\\t\\tcolorBuffers,\\n\\t\\t\\tdepth: false,\\n\\t\\t\\tflipY: true\\n\\t\\t});\\n\\t\\tconst colorTexture = this.streams.getTexture(\\\"dataColor\\\");\\n\\t\\tthis.colorRenderTarget = new RenderTarget({\\n\\t\\t\\tname: `GsplatWorkBuffer-Color-${this.id}`,\\n\\t\\t\\tcolorBuffer: colorTexture,\\n\\t\\t\\tdepth: false,\\n\\t\\t\\tflipY: true\\n\\t\\t});\\n\\t\\tthis.renderPass?.init(this.renderTarget);\\n\\t\\tthis.colorRenderPass?.init(this.colorRenderTarget);\\n\\t}\\n\\tsyncWithFormat() {\\n\\t\\tconst prevVersion = this.streams._formatVersion;\\n\\t\\tthis.streams.syncWithFormat(this.format);\\n\\t\\tif (prevVersion !== this.streams._formatVersion) {\\n\\t\\t\\tthis._createRenderTargets();\\n\\t\\t}\\n\\t}\\n\\tgetTexture(name) {\\n\\t\\treturn this.streams.getTexture(name);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.renderPass?.destroy();\\n\\t\\tthis.colorRenderPass?.destroy();\\n\\t\\tthis.streams.destroy();\\n\\t\\tthis.orderTexture?.destroy();\\n\\t\\tthis.orderBuffer?.destroy();\\n\\t\\tthis.renderTarget?.destroy();\\n\\t\\tthis.colorRenderTarget?.destroy();\\n\\t\\tthis.uploadStream.destroy();\\n\\t\\tthis.frustumCuller.destroy();\\n\\t}\\n\\tget textureSize() {\\n\\t\\treturn this.streams.textureDimensions.x;\\n\\t}\\n\\tsetOrderData(data) {\\n\\t\\tthis.textureSize;\\n\\t\\tif (this.device.isWebGPU) {\\n\\t\\t\\tthis.uploadStream.upload(data, this.orderBuffer, 0, data.length);\\n\\t\\t} else {\\n\\t\\t\\tthis.uploadStream.upload(data, this.orderTexture, 0, data.length);\\n\\t\\t}\\n\\t}\\n\\tresize(textureSize) {\\n\\t\\tthis.renderTarget.resize(textureSize, textureSize);\\n\\t\\tthis.colorRenderTarget.resize(textureSize, textureSize);\\n\\t\\tthis.streams.resize(textureSize, textureSize);\\n\\t\\tif (this.device.isWebGPU) {\\n\\t\\t\\tconst newByteSize = textureSize * textureSize * 4;\\n\\t\\t\\tif (this.orderBuffer.byteSize < newByteSize) {\\n\\t\\t\\t\\tthis.orderBuffer.destroy();\\n\\t\\t\\t\\tthis.orderBuffer = new StorageBuffer(this.device, newByteSize, BUFFERUSAGE_COPY_DST);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis.orderTexture.resize(textureSize, textureSize);\\n\\t\\t}\\n\\t}\\n\\trender(splats, cameraNode, colorsByLod, changedAllocIds = null) {\\n\\t\\tif (this.renderPass.update(splats, cameraNode, colorsByLod, changedAllocIds)) {\\n\\t\\t\\tthis.renderPass.render();\\n\\t\\t}\\n\\t}\\n\\trenderColor(splats, cameraNode, colorsByLod, changedAllocIds = null) {\\n\\t\\tif (this.colorRenderPass.update(splats, cameraNode, colorsByLod, changedAllocIds)) {\\n\\t\\t\\tthis.colorRenderPass.render();\\n\\t\\t}\\n\\t}\\n}\\n\\nclass GSplatResourceCleanup {\\n\\tstatic _cache = new DeviceCache();\\n\\t_pendingDestroy = /* @__PURE__ */ new Set();\\n\\tstatic queueDestroy(device, resource) {\\n\\t\\tthis._cache.get(device, () => new GSplatResourceCleanup())._pendingDestroy.add(resource);\\n\\t}\\n\\tstatic process(device) {\\n\\t\\tconst pending = this._cache.get(device, () => new GSplatResourceCleanup())._pendingDestroy;\\n\\t\\tfor (const resource of pending) {\\n\\t\\t\\tif (resource.refCount === 0) {\\n\\t\\t\\t\\tresource._actualDestroy();\\n\\t\\t\\t\\tpending.delete(resource);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._pendingDestroy.clear();\\n\\t}\\n}\\n\\nlet id = 0;\\nconst tempMap = /* @__PURE__ */ new Map();\\nclass GSplatResourceBase {\\n\\tdevice;\\n\\tgsplatData;\\n\\tset centers(value) {\\n\\t\\tthis._centers = value;\\n\\t}\\n\\tget centers() {\\n\\t\\treturn this._centers;\\n\\t}\\n\\tget hasCenters() {\\n\\t\\treturn this._centers != null;\\n\\t}\\n\\t_centers = null;\\n\\tcentersVersion = 0;\\n\\taabb;\\n\\tmesh = null;\\n\\tid = id++;\\n\\tworkBufferRenderInfos = /* @__PURE__ */ new Map();\\n\\t_format = null;\\n\\tstreams;\\n\\tparameters = /* @__PURE__ */ new Map();\\n\\t_refCount = 0;\\n\\t_meshRefCount = 0;\\n\\tconstructor(device, gsplatData, options = {}) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.gsplatData = gsplatData;\\n\\t\\tthis.streams = new GSplatStreams(device);\\n\\t\\tif (options.prepareCenters !== false) {\\n\\t\\t\\tthis._centers = gsplatData.getCenters();\\n\\t\\t} else {\\n\\t\\t\\tthis._centers = null;\\n\\t\\t}\\n\\t\\tthis.aabb = new BoundingBox();\\n\\t\\tgsplatData.calcAabb(this.aabb);\\n\\t}\\n\\tdestroy() {\\n\\t\\tif (this.refCount > 0) {\\n\\t\\t\\tGSplatResourceCleanup.queueDestroy(this.device, this);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._actualDestroy();\\n\\t}\\n\\t_actualDestroy() {\\n\\t\\tthis.streams.destroy();\\n\\t\\tthis.mesh?.destroy();\\n\\t\\tthis.workBufferRenderInfos.forEach((info) => info.destroy());\\n\\t\\tthis.workBufferRenderInfos.clear();\\n\\t}\\n\\tincRefCount() {\\n\\t\\tthis._refCount++;\\n\\t}\\n\\tdecRefCount() {\\n\\t\\tthis._refCount--;\\n\\t}\\n\\tget refCount() {\\n\\t\\treturn this._refCount;\\n\\t}\\n\\tensureMesh() {\\n\\t\\tif (!this.mesh) {\\n\\t\\t\\tthis.mesh = GSplatResourceBase.createMesh(this.device);\\n\\t\\t\\tthis.mesh.aabb.copy(this.aabb);\\n\\t\\t}\\n\\t\\tthis._meshRefCount++;\\n\\t}\\n\\treleaseMesh() {\\n\\t\\tthis._meshRefCount--;\\n\\t\\tif (this._meshRefCount < 1) {\\n\\t\\t\\tthis.mesh = null;\\n\\t\\t}\\n\\t}\\n\\tgetWorkBufferRenderInfo(colorOnly, workBufferModifier, formatHash, formatDeclarations, workBufferFormat) {\\n\\t\\tthis.configureMaterialDefines(tempMap);\\n\\t\\ttempMap.set(\\\"GSPLAT_LOD\\\", \\\"\\\");\\n\\t\\tif (colorOnly) tempMap.set(\\\"GSPLAT_COLOR_ONLY\\\", \\\"\\\");\\n\\t\\tlet definesKey = \\\"\\\";\\n\\t\\tfor (const [k, v] of tempMap) {\\n\\t\\t\\tif (definesKey) definesKey += \\\";\\\";\\n\\t\\t\\tdefinesKey += `${k}=${v}`;\\n\\t\\t}\\n\\t\\tconst key = `${formatHash};${workBufferFormat.hash};${workBufferModifier?.hash ?? 0};${definesKey}`;\\n\\t\\tlet info = this.workBufferRenderInfos.get(key);\\n\\t\\tif (!info) {\\n\\t\\t\\tconst material = new ShaderMaterial();\\n\\t\\t\\tthis.configureMaterial(material, workBufferModifier, formatDeclarations);\\n\\t\\t\\tconst chunks = this.device.isWebGPU ? material.shaderChunks.wgsl : material.shaderChunks.glsl;\\n\\t\\t\\tconst outputStreams = colorOnly ? [workBufferFormat.getStream(\\\"dataColor\\\")] : [...workBufferFormat.streams, ...workBufferFormat.extraStreams];\\n\\t\\t\\tlet outputCode = workBufferFormat.getOutputDeclarations(outputStreams);\\n\\t\\t\\tif (colorOnly && workBufferFormat.extraStreams.length > 0) {\\n\\t\\t\\t\\toutputCode += `\\n${workBufferFormat.getOutputStubs(workBufferFormat.extraStreams)}`;\\n\\t\\t\\t}\\n\\t\\t\\tchunks.set(\\\"gsplatWorkBufferOutputVS\\\", outputCode);\\n\\t\\t\\tconst writeCode = workBufferFormat.getWriteCode();\\n\\t\\t\\tif (writeCode) {\\n\\t\\t\\t\\tchunks.set(\\\"gsplatWriteVS\\\", writeCode);\\n\\t\\t\\t}\\n\\t\\t\\ttempMap.forEach((v, k) => material.setDefine(k, v));\\n\\t\\t\\tinfo = new WorkBufferRenderInfo(this.device, key, material, colorOnly, workBufferFormat);\\n\\t\\t\\tthis.workBufferRenderInfos.set(key, info);\\n\\t\\t}\\n\\t\\ttempMap.clear();\\n\\t\\treturn info;\\n\\t}\\n\\tstatic createMesh(device) {\\n\\t\\tconst splatInstanceSize = GSplatResourceBase.instanceSize;\\n\\t\\tconst meshPositions = new Float32Array(12 * splatInstanceSize);\\n\\t\\tconst meshIndices = new Uint32Array(6 * splatInstanceSize);\\n\\t\\tfor (let i = 0; i < splatInstanceSize; ++i) {\\n\\t\\t\\tmeshPositions.set([\\n\\t\\t\\t\\t-1,\\n\\t\\t\\t\\t-1,\\n\\t\\t\\t\\ti,\\n\\t\\t\\t\\t1,\\n\\t\\t\\t\\t-1,\\n\\t\\t\\t\\ti,\\n\\t\\t\\t\\t1,\\n\\t\\t\\t\\t1,\\n\\t\\t\\t\\ti,\\n\\t\\t\\t\\t-1,\\n\\t\\t\\t\\t1,\\n\\t\\t\\t\\ti\\n\\t\\t\\t], i * 12);\\n\\t\\t\\tconst b = i * 4;\\n\\t\\t\\tmeshIndices.set([\\n\\t\\t\\t\\t0 + b,\\n\\t\\t\\t\\t1 + b,\\n\\t\\t\\t\\t2 + b,\\n\\t\\t\\t\\t0 + b,\\n\\t\\t\\t\\t2 + b,\\n\\t\\t\\t\\t3 + b\\n\\t\\t\\t], i * 6);\\n\\t\\t}\\n\\t\\tconst mesh = new Mesh(device);\\n\\t\\tmesh.setPositions(meshPositions, 3);\\n\\t\\tmesh.setIndices(meshIndices);\\n\\t\\tmesh.update();\\n\\t\\treturn mesh;\\n\\t}\\n\\tstatic get instanceSize() {\\n\\t\\treturn 128;\\n\\t}\\n\\tget numSplats() {\\n\\t\\treturn this.gsplatData.numSplats;\\n\\t}\\n\\tget format() {\\n\\t\\treturn this._format;\\n\\t}\\n\\tgetTexture(name) {\\n\\t\\treturn this.streams.getTexture(name) ?? null;\\n\\t}\\n\\tget textureDimensions() {\\n\\t\\treturn this.streams.textureDimensions;\\n\\t}\\n\\tconfigureMaterial(material, workBufferModifier, formatDeclarations) {\\n\\t\\tthis.configureMaterialDefines(material.defines);\\n\\t\\tthis.streams.syncWithFormat(this.format);\\n\\t\\tconst chunks = this.device.isWebGPU ? material.shaderChunks.wgsl : material.shaderChunks.glsl;\\n\\t\\tchunks.set(\\\"gsplatDeclarationsVS\\\", formatDeclarations);\\n\\t\\tchunks.set(\\\"gsplatReadVS\\\", this.format.getReadCode());\\n\\t\\tif (workBufferModifier?.code) {\\n\\t\\t\\tchunks.set(\\\"gsplatModifyVS\\\", workBufferModifier.code);\\n\\t\\t}\\n\\t\\tfor (const [name, texture] of this.streams.textures) {\\n\\t\\t\\tmaterial.setParameter(name, texture);\\n\\t\\t}\\n\\t\\tfor (const [name, value] of this.parameters) {\\n\\t\\t\\tmaterial.setParameter(name, value);\\n\\t\\t}\\n\\t\\tif (this.textureDimensions.x > 0) {\\n\\t\\t\\tmaterial.setParameter(\\\"splatTextureSize\\\", this.textureDimensions.x);\\n\\t\\t}\\n\\t}\\n\\tconfigureMaterialDefines(defines) {\\n\\t}\\n\\tinstantiate() {\\n\\t}\\n}\\n\\nconst mat4 = new Mat4();\\nconst quat$1 = new Quat();\\nconst aabb = new BoundingBox();\\nconst aabb2 = new BoundingBox();\\nconst debugColor = new Color(1, 1, 0, 0.4);\\nconst SH_C0$2 = 0.28209479177387814;\\nclass SplatIterator {\\n\\tconstructor(gsplatData, p, r, s, c) {\\n\\t\\tconst x = gsplatData.getProp(\\\"x\\\");\\n\\t\\tconst y = gsplatData.getProp(\\\"y\\\");\\n\\t\\tconst z = gsplatData.getProp(\\\"z\\\");\\n\\t\\tconst rx = gsplatData.getProp(\\\"rot_1\\\");\\n\\t\\tconst ry = gsplatData.getProp(\\\"rot_2\\\");\\n\\t\\tconst rz = gsplatData.getProp(\\\"rot_3\\\");\\n\\t\\tconst rw = gsplatData.getProp(\\\"rot_0\\\");\\n\\t\\tconst sx = gsplatData.getProp(\\\"scale_0\\\");\\n\\t\\tconst sy = gsplatData.getProp(\\\"scale_1\\\");\\n\\t\\tconst sz = gsplatData.getProp(\\\"scale_2\\\");\\n\\t\\tconst cr = gsplatData.getProp(\\\"f_dc_0\\\");\\n\\t\\tconst cg = gsplatData.getProp(\\\"f_dc_1\\\");\\n\\t\\tconst cb = gsplatData.getProp(\\\"f_dc_2\\\");\\n\\t\\tconst ca = gsplatData.getProp(\\\"opacity\\\");\\n\\t\\tconst sigmoid = (v) => {\\n\\t\\t\\tif (v > 0) {\\n\\t\\t\\t\\treturn 1 / (1 + Math.exp(-v));\\n\\t\\t\\t}\\n\\t\\t\\tconst t = Math.exp(v);\\n\\t\\t\\treturn t / (1 + t);\\n\\t\\t};\\n\\t\\tthis.read = (i) => {\\n\\t\\t\\tif (p) {\\n\\t\\t\\t\\tp.x = x[i];\\n\\t\\t\\t\\tp.y = y[i];\\n\\t\\t\\t\\tp.z = z[i];\\n\\t\\t\\t}\\n\\t\\t\\tif (r) {\\n\\t\\t\\t\\tr.set(rx[i], ry[i], rz[i], rw[i]);\\n\\t\\t\\t}\\n\\t\\t\\tif (s) {\\n\\t\\t\\t\\ts.set(Math.exp(sx[i]), Math.exp(sy[i]), Math.exp(sz[i]));\\n\\t\\t\\t}\\n\\t\\t\\tif (c) {\\n\\t\\t\\t\\tc.set(\\n\\t\\t\\t\\t\\t0.5 + cr[i] * SH_C0$2,\\n\\t\\t\\t\\t\\t0.5 + cg[i] * SH_C0$2,\\n\\t\\t\\t\\t\\t0.5 + cb[i] * SH_C0$2,\\n\\t\\t\\t\\t\\tsigmoid(ca[i])\\n\\t\\t\\t\\t);\\n\\t\\t\\t}\\n\\t\\t};\\n\\t}\\n}\\nconst calcSplatMat = (result, p, r) => {\\n\\tquat$1.set(r.x, r.y, r.z, r.w).normalize();\\n\\tresult.setTRS(p, quat$1, Vec3.ONE);\\n};\\nclass GSplatData {\\n\\telements;\\n\\tnumSplats;\\n\\tcomments;\\n\\tconstructor(elements, comments = []) {\\n\\t\\tthis.elements = elements;\\n\\t\\tthis.numSplats = this.getElement(\\\"vertex\\\").count;\\n\\t\\tthis.comments = comments;\\n\\t}\\n\\tstatic calcSplatAabb(result, p, r, s) {\\n\\t\\tcalcSplatMat(mat4, p, r);\\n\\t\\taabb.center.set(0, 0, 0);\\n\\t\\taabb.halfExtents.set(s.x * 2, s.y * 2, s.z * 2);\\n\\t\\tresult.setFromTransformedAabb(aabb, mat4);\\n\\t}\\n\\t// access a named property\\n\\tgetProp(name, elementName = \\\"vertex\\\") {\\n\\t\\treturn this.getElement(elementName)?.properties.find((p) => p.name === name)?.storage;\\n\\t}\\n\\t// access the named element\\n\\tgetElement(name) {\\n\\t\\treturn this.elements.find((e) => e.name === name);\\n\\t}\\n\\t// add a new property\\n\\taddProp(name, storage) {\\n\\t\\tthis.getElement(\\\"vertex\\\").properties.push({\\n\\t\\t\\ttype: \\\"float\\\",\\n\\t\\t\\tname,\\n\\t\\t\\tstorage,\\n\\t\\t\\tbyteSize: 4\\n\\t\\t});\\n\\t}\\n\\tcreateIter(p, r, s, c) {\\n\\t\\treturn new SplatIterator(this, p, r, s, c);\\n\\t}\\n\\tcalcAabb(result, pred) {\\n\\t\\tlet mx, my, mz, Mx, My, Mz;\\n\\t\\tlet first = true;\\n\\t\\tconst x = this.getProp(\\\"x\\\");\\n\\t\\tconst y = this.getProp(\\\"y\\\");\\n\\t\\tconst z = this.getProp(\\\"z\\\");\\n\\t\\tconst sx = this.getProp(\\\"scale_0\\\");\\n\\t\\tconst sy = this.getProp(\\\"scale_1\\\");\\n\\t\\tconst sz = this.getProp(\\\"scale_2\\\");\\n\\t\\tfor (let i = 0; i < this.numSplats; ++i) {\\n\\t\\t\\tif (pred && !pred(i)) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tconst px = x[i];\\n\\t\\t\\tconst py = y[i];\\n\\t\\t\\tconst pz = z[i];\\n\\t\\t\\tconst scale = Math.max(sx[i], sy[i], sz[i]);\\n\\t\\t\\tif (!isFinite(px) || !isFinite(py) || !isFinite(pz) || !isFinite(scale)) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tconst scaleVal = 2 * Math.exp(scale);\\n\\t\\t\\tif (first) {\\n\\t\\t\\t\\tfirst = false;\\n\\t\\t\\t\\tmx = px - scaleVal;\\n\\t\\t\\t\\tmy = py - scaleVal;\\n\\t\\t\\t\\tmz = pz - scaleVal;\\n\\t\\t\\t\\tMx = px + scaleVal;\\n\\t\\t\\t\\tMy = py + scaleVal;\\n\\t\\t\\t\\tMz = pz + scaleVal;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tmx = Math.min(mx, px - scaleVal);\\n\\t\\t\\t\\tmy = Math.min(my, py - scaleVal);\\n\\t\\t\\t\\tmz = Math.min(mz, pz - scaleVal);\\n\\t\\t\\t\\tMx = Math.max(Mx, px + scaleVal);\\n\\t\\t\\t\\tMy = Math.max(My, py + scaleVal);\\n\\t\\t\\t\\tMz = Math.max(Mz, pz + scaleVal);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (!first) {\\n\\t\\t\\tresult.center.set((mx + Mx) * 0.5, (my + My) * 0.5, (mz + Mz) * 0.5);\\n\\t\\t\\tresult.halfExtents.set((Mx - mx) * 0.5, (My - my) * 0.5, (Mz - mz) * 0.5);\\n\\t\\t}\\n\\t\\treturn !first;\\n\\t}\\n\\tcalcAabbExact(result, pred) {\\n\\t\\tconst p = new Vec3();\\n\\t\\tconst r = new Quat();\\n\\t\\tconst s = new Vec3();\\n\\t\\tconst iter = this.createIter(p, r, s);\\n\\t\\tlet first = true;\\n\\t\\tfor (let i = 0; i < this.numSplats; ++i) {\\n\\t\\t\\tif (pred && !pred(i)) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\titer.read(i);\\n\\t\\t\\tif (first) {\\n\\t\\t\\t\\tfirst = false;\\n\\t\\t\\t\\tGSplatData.calcSplatAabb(result, p, r, s);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tGSplatData.calcSplatAabb(aabb2, p, r, s);\\n\\t\\t\\t\\tresult.add(aabb2);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn !first;\\n\\t}\\n\\tgetCenters() {\\n\\t\\tconst x = this.getProp(\\\"x\\\");\\n\\t\\tconst y = this.getProp(\\\"y\\\");\\n\\t\\tconst z = this.getProp(\\\"z\\\");\\n\\t\\tconst result = new Float32Array(this.numSplats * 3);\\n\\t\\tfor (let i = 0; i < this.numSplats; ++i) {\\n\\t\\t\\tresult[i * 3 + 0] = x[i];\\n\\t\\t\\tresult[i * 3 + 1] = y[i];\\n\\t\\t\\tresult[i * 3 + 2] = z[i];\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n\\tcalcFocalPoint(result, pred) {\\n\\t\\tconst x = this.getProp(\\\"x\\\");\\n\\t\\tconst y = this.getProp(\\\"y\\\");\\n\\t\\tconst z = this.getProp(\\\"z\\\");\\n\\t\\tconst sx = this.getProp(\\\"scale_0\\\");\\n\\t\\tconst sy = this.getProp(\\\"scale_1\\\");\\n\\t\\tconst sz = this.getProp(\\\"scale_2\\\");\\n\\t\\tresult.x = 0;\\n\\t\\tresult.y = 0;\\n\\t\\tresult.z = 0;\\n\\t\\tlet sum = 0;\\n\\t\\tfor (let i = 0; i < this.numSplats; ++i) {\\n\\t\\t\\tif (pred && !pred(i)) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tconst px = x[i];\\n\\t\\t\\tconst py = y[i];\\n\\t\\t\\tconst pz = z[i];\\n\\t\\t\\tif (!isFinite(px) || !isFinite(py) || !isFinite(pz)) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tconst weight = 1 / (1 + Math.exp(Math.max(sx[i], sy[i], sz[i])));\\n\\t\\t\\tresult.x += px * weight;\\n\\t\\t\\tresult.y += py * weight;\\n\\t\\t\\tresult.z += pz * weight;\\n\\t\\t\\tsum += weight;\\n\\t\\t}\\n\\t\\tresult.mulScalar(1 / sum);\\n\\t}\\n\\trenderWireframeBounds(scene, worldMat) {\\n\\t\\tconst p = new Vec3();\\n\\t\\tconst r = new Quat();\\n\\t\\tconst s = new Vec3();\\n\\t\\tconst min = new Vec3();\\n\\t\\tconst max = new Vec3();\\n\\t\\tconst iter = this.createIter(p, r, s);\\n\\t\\tfor (let i = 0; i < this.numSplats; ++i) {\\n\\t\\t\\titer.read(i);\\n\\t\\t\\tcalcSplatMat(mat4, p, r);\\n\\t\\t\\tmat4.mul2(worldMat, mat4);\\n\\t\\t\\tmin.set(s.x * -2, s.y * -2, s.z * -2);\\n\\t\\t\\tmax.set(s.x * 2, s.y * 2, s.z * 2);\\n\\t\\t\\tscene.immediate.drawWireAlignedBox(min, max, debugColor, true, scene.defaultDrawLayer, mat4);\\n\\t\\t}\\n\\t}\\n\\tget isCompressed() {\\n\\t\\treturn false;\\n\\t}\\n\\t// return the number of spherical harmonic bands present. value will be between 0 and 3 inclusive.\\n\\tget shBands() {\\n\\t\\tconst numProps = () => {\\n\\t\\t\\tfor (let i = 0; i < 45; ++i) {\\n\\t\\t\\t\\tif (!this.getProp(`f_rest_${i}`)) {\\n\\t\\t\\t\\t\\treturn i;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\treturn 45;\\n\\t\\t};\\n\\t\\tconst sizes = {\\n\\t\\t\\t9: 1,\\n\\t\\t\\t24: 2,\\n\\t\\t\\t45: 3\\n\\t\\t};\\n\\t\\treturn sizes[numProps()] ?? 0;\\n\\t}\\n\\tcalcMortonOrder() {\\n\\t\\tconst calcMinMax = (arr) => {\\n\\t\\t\\tlet min = arr[0];\\n\\t\\t\\tlet max = arr[0];\\n\\t\\t\\tfor (let i = 1; i < arr.length; i++) {\\n\\t\\t\\t\\tif (arr[i] < min) min = arr[i];\\n\\t\\t\\t\\tif (arr[i] > max) max = arr[i];\\n\\t\\t\\t}\\n\\t\\t\\treturn { min, max };\\n\\t\\t};\\n\\t\\tconst encodeMorton3 = (x2, y2, z2) => {\\n\\t\\t\\tconst Part1By2 = (x3) => {\\n\\t\\t\\t\\tx3 &= 1023;\\n\\t\\t\\t\\tx3 = (x3 ^ x3 << 16) & 4278190335;\\n\\t\\t\\t\\tx3 = (x3 ^ x3 << 8) & 50393103;\\n\\t\\t\\t\\tx3 = (x3 ^ x3 << 4) & 51130563;\\n\\t\\t\\t\\tx3 = (x3 ^ x3 << 2) & 153391689;\\n\\t\\t\\t\\treturn x3;\\n\\t\\t\\t};\\n\\t\\t\\treturn (Part1By2(z2) << 2) + (Part1By2(y2) << 1) + Part1By2(x2);\\n\\t\\t};\\n\\t\\tconst x = this.getProp(\\\"x\\\");\\n\\t\\tconst y = this.getProp(\\\"y\\\");\\n\\t\\tconst z = this.getProp(\\\"z\\\");\\n\\t\\tconst { min: minX, max: maxX } = calcMinMax(x);\\n\\t\\tconst { min: minY, max: maxY } = calcMinMax(y);\\n\\t\\tconst { min: minZ, max: maxZ } = calcMinMax(z);\\n\\t\\tconst sizeX = minX === maxX ? 0 : 1024 / (maxX - minX);\\n\\t\\tconst sizeY = minY === maxY ? 0 : 1024 / (maxY - minY);\\n\\t\\tconst sizeZ = minZ === maxZ ? 0 : 1024 / (maxZ - minZ);\\n\\t\\tconst codes = /* @__PURE__ */ new Map();\\n\\t\\tfor (let i = 0; i < this.numSplats; i++) {\\n\\t\\t\\tconst ix = Math.min(1023, Math.floor((x[i] - minX) * sizeX));\\n\\t\\t\\tconst iy = Math.min(1023, Math.floor((y[i] - minY) * sizeY));\\n\\t\\t\\tconst iz = Math.min(1023, Math.floor((z[i] - minZ) * sizeZ));\\n\\t\\t\\tconst code = encodeMorton3(ix, iy, iz);\\n\\t\\t\\tconst val = codes.get(code);\\n\\t\\t\\tif (val) {\\n\\t\\t\\t\\tval.push(i);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tcodes.set(code, [i]);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst keys = Array.from(codes.keys()).sort((a, b) => a - b);\\n\\t\\tconst indices = new Uint32Array(this.numSplats);\\n\\t\\tlet idx = 0;\\n\\t\\tfor (let i = 0; i < keys.length; ++i) {\\n\\t\\t\\tconst val = codes.get(keys[i]);\\n\\t\\t\\tfor (let j = 0; j < val.length; ++j) {\\n\\t\\t\\t\\tindices[idx++] = val[j];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn indices;\\n\\t}\\n\\t// reorder the splat data to aid in better gpu memory access at render time\\n\\treorder(order) {\\n\\t\\tconst cache = /* @__PURE__ */ new Map();\\n\\t\\tconst getStorage = (size) => {\\n\\t\\t\\tif (cache.has(size)) {\\n\\t\\t\\t\\tconst buffer = cache.get(size);\\n\\t\\t\\t\\tcache.delete(size);\\n\\t\\t\\t\\treturn buffer;\\n\\t\\t\\t}\\n\\t\\t\\treturn new ArrayBuffer(size);\\n\\t\\t};\\n\\t\\tconst returnStorage = (buffer) => {\\n\\t\\t\\tcache.set(buffer.byteLength, buffer);\\n\\t\\t};\\n\\t\\tconst reorder = (data) => {\\n\\t\\t\\tconst result = new data.constructor(getStorage(data.byteLength));\\n\\t\\t\\tfor (let i = 0; i < order.length; i++) {\\n\\t\\t\\t\\tresult[i] = data[order[i]];\\n\\t\\t\\t}\\n\\t\\t\\treturnStorage(data.buffer);\\n\\t\\t\\treturn result;\\n\\t\\t};\\n\\t\\tthis.elements.forEach((element) => {\\n\\t\\t\\telement.properties.forEach((property) => {\\n\\t\\t\\t\\tif (property.storage) {\\n\\t\\t\\t\\t\\tproperty.storage = reorder(property.storage);\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t});\\n\\t}\\n\\t// reorder the splat data to aid in better gpu memory access at render time\\n\\treorderData() {\\n\\t\\tthis.reorder(this.calcMortonOrder());\\n\\t}\\n}\\n\\nconst vertexGLSL = `\\n\\tattribute vec2 vertex_position;\\n\\tvoid main(void) {\\n\\t\\tgl_Position = vec4(vertex_position, 0.0, 1.0);\\n\\t}\\n`;\\nconst fragmentGLSL = `\\n\\t#include \\\"gsplatEvalSHVS\\\"\\n\\tvec4 packRgb(vec3 v) {\\n\\t\\tuvec3 vb = uvec3(clamp(v, vec3(0.0), vec3(1.0)) * vec3(2047.0, 2047.0, 1023.0));\\n\\t\\tuint bits = (vb.x << 21) | (vb.y << 10) | vb.z;\\n\\t\\treturn vec4((uvec4(bits) >> uvec4(24, 16, 8, 0)) & uvec4(0xff)) / vec4(255.0);\\n\\t}\\n\\tuniform mediump vec3 dir;\\n\\tuniform mediump sampler2D centroids;\\n\\tuniform mediump float shN_mins;\\n\\tuniform mediump float shN_maxs;\\n\\tvoid main(void) {\\n\\t\\tivec2 uv = ivec2(gl_FragCoord.xy) * ivec2(SH_COEFFS, 1);\\n\\t\\tmediump vec3 coefficients[SH_COEFFS];\\n\\t\\tfor (int i = 0; i < SH_COEFFS; i++) {\\n\\t\\t\\tvec3 s = texelFetch(centroids, ivec2(uv.x + i, uv.y), 0).xyz;\\n\\t\\t\\tcoefficients[i] = mix(vec3(shN_mins), vec3(shN_maxs), s);\\n\\t\\t}\\n\\t\\tgl_FragColor = packRgb(evalSH(coefficients, dir) * 0.25 + 0.5);\\n\\t}\\n`;\\nconst vertexWGSL = `\\n\\tattribute vertex_position: vec2f;\\n\\t@vertex\\n\\tfn vertexMain(input: VertexInput) -> VertexOutput {\\n\\t\\tvar output: VertexOutput;\\n\\t\\toutput.position = vec4f(vertex_position, 0.0, 1.0);\\n\\t\\treturn output;\\n\\t}\\n`;\\nconst fragmentWGSL = `\\n\\t#include \\\"gsplatEvalSHVS\\\"\\n\\tfn packRgb(v: vec3f) -> vec4f {\\n\\t\\tlet vb = vec3u(clamp(v, vec3f(0.0), vec3f(1.0)) * vec3f(2047.0, 2047.0, 1023.0));\\n\\t\\tlet bits = dot(vb, vec3u(1 << 21, 1 << 10, 1));\\n\\t\\treturn vec4f((vec4u(bits) >> vec4u(24, 16, 8, 0)) & vec4u(0xff)) / vec4f(255.0);\\n\\t}\\n\\tuniform dir: vec3f;\\n\\tuniform shN_mins: f32;\\n\\tuniform shN_maxs: f32;\\n\\tvar centroids: texture_2d<f32>;\\n\\t@fragment\\n\\tfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\t\\tvar output: FragmentOutput;\\n\\t\\tvar uv = vec2i(input.position.xy) * vec2i(SH_COEFFS, 1);\\n\\t\\tvar coefficients: array<vec3f, SH_COEFFS>;\\n\\t\\tfor (var i: i32 = 0; i < SH_COEFFS; i++) {\\n\\t\\t\\tlet s: vec3f = textureLoad(centroids, vec2i(uv.x + i, uv.y), 0).xyz;\\n\\t\\t\\tcoefficients[i] = mix(vec3f(uniform.shN_mins), vec3f(uniform.shN_maxs), s);\\n\\t\\t}\\n\\t\\toutput.color = packRgb(evalSH(&coefficients, uniform.dir) * 0.25 + 0.5);\\n\\t\\treturn output;\\n\\t}\\n`;\\nconst gsplatSogColorGLSL = `\\n\\tuniform mediump sampler2D sh0;\\n\\tuniform highp sampler2D sh_labels;\\n\\tuniform mediump sampler2D sh_result;\\n\\tuniform vec4 sh0_mins;\\n\\tuniform vec4 sh0_maxs;\\n\\tfloat SH_C0 = 0.28209479177387814;\\n\\tvec3 unpackRgb(vec4 v) {\\n\\t\\tuvec4 uv = uvec4(v * 255.0);\\n\\t\\tuint bits = (uv.x << 24) | (uv.y << 16) | (uv.z << 8) | uv.w;\\n\\t\\tuvec3 vb = (uvec3(bits) >> uvec3(21, 10, 0)) & uvec3(0x7ffu, 0x7ffu, 0x3ffu);\\n\\t\\treturn vec3(vb) / vec3(2047.0, 2047.0, 1023.0);\\n\\t}\\n\\tvec4 getColor(in SplatSource source) {\\n\\t\\tvec4 baseSample = mix(sh0_mins, sh0_maxs, texelFetch(sh0, source.uv, 0));\\n\\t\\tvec4 base = vec4(vec3(0.5) + baseSample.xyz * SH_C0, 1.0 / (1.0 + exp(-baseSample.w)));\\n\\t\\tivec2 labelSample = ivec2(texelFetch(sh_labels, source.uv, 0).xy * 255.0);\\n\\t\\tint n = labelSample.x + labelSample.y * 256;\\n\\t\\tvec4 shSample = texelFetch(sh_result, ivec2(n % 64, n / 64), 0);\\n\\t\\tvec3 sh = (unpackRgb(shSample) - vec3(0.5)) * 4.0;\\n\\t\\treturn vec4(base.xyz + sh, base.w);\\n\\t}\\n`;\\nconst gsplatSogColorWGSL = `\\n\\tvar sh0: texture_2d<f32>;\\n\\tvar sh_labels: texture_2d<f32>;\\n\\tvar sh_result: texture_2d<f32>;\\n\\tuniform sh0_mins: vec4f;\\n\\tuniform sh0_maxs: vec4f;\\n\\tconst SH_C0: f32 = 0.28209479177387814;\\n\\tfn unpackRgb(v: vec4f) -> vec3f {\\n\\t\\tlet bits = dot(vec4u(v * 255.0), vec4u(1u << 24, 1u << 16, 1u << 8, 1u));\\n\\t\\tlet vb = (vec3u(bits) >> vec3u(21, 10, 0)) & vec3u(0x7ffu, 0x7ffu, 0x3ffu);\\n\\t\\treturn vec3f(vb) / vec3f(2047.0, 2047.0, 1023.0);\\n\\t}\\n\\tfn getColor(source: ptr<function, SplatSource>) -> vec4f {\\n\\t\\tlet baseSample: vec4f = mix(uniform.sh0_mins, uniform.sh0_maxs, textureLoad(sh0, source.uv, 0));\\n\\t\\tlet base = vec4f(vec3f(0.5) + baseSample.xyz * SH_C0, 1.0 / (1.0 + exp(-baseSample.w)));\\n\\t\\tlet labelSample: vec2i = vec2i(textureLoad(sh_labels, source.uv, 0).xy * 255.0);\\n\\t\\tlet n = labelSample.x + labelSample.y * 256;\\n\\t\\tlet shSample: vec4f = textureLoad(sh_result, vec2i(n % 64, n / 64), 0);\\n\\t\\tlet sh: vec3f = (unpackRgb(shSample) - vec3f(0.5)) * 4.0;\\n\\t\\treturn vec4f(base.xyz + sh, base.w);\\n\\t}\\n`;\\nconst resolve$1 = (scope, values) => {\\n\\tfor (const key in values) {\\n\\t\\tscope.resolve(key).setValue(values[key]);\\n\\t}\\n};\\nclass CustomRenderPass extends RenderPass {\\n\\texecuteCallback = null;\\n\\texecute() {\\n\\t\\tthis.executeCallback?.();\\n\\t}\\n}\\nconst invModelMat$1 = new Mat4();\\nconst dir$1 = new Vec3();\\nclass GSplatResolveSH {\\n\\tprevDir = new Vec3();\\n\\tupdateMode = \\\"enable\\\";\\n\\t// 'enable', 'disable', 'always'\\n\\tconstructor(device, gsplatInstance) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.gsplatInstance = gsplatInstance;\\n\\t\\tconst { resource } = gsplatInstance;\\n\\t\\tthis.shader = ShaderUtils.createShader(device, {\\n\\t\\t\\tuniqueName: \\\"gsplatResolveSH\\\",\\n\\t\\t\\tvertexGLSL,\\n\\t\\t\\tfragmentGLSL,\\n\\t\\t\\tvertexWGSL,\\n\\t\\t\\tfragmentWGSL,\\n\\t\\t\\tfragmentDefines: /* @__PURE__ */ new Map([\\n\\t\\t\\t\\t[\\\"SH_BANDS\\\", resource.gsplatData.shBands.toString()]\\n\\t\\t\\t]),\\n\\t\\t\\tattributes: {\\n\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tthis.texture = resource.streams.createTexture(\\\"centroids\\\", PIXELFORMAT_RGBA8, new Vec2(64, 1024));\\n\\t\\tthis.renderTarget = new RenderTarget({\\n\\t\\t\\tcolorBuffer: this.texture,\\n\\t\\t\\tdepth: false\\n\\t\\t});\\n\\t\\tthis.renderPass = new CustomRenderPass(device);\\n\\t\\tthis.renderPass.init(this.renderTarget, {});\\n\\t\\tthis.renderPass.colorOps.clear = true;\\n\\t\\tthis.quadRender = new QuadRender(this.shader);\\n\\t\\tconst { material } = gsplatInstance;\\n\\t\\tmaterial.setDefine(\\\"SH_BANDS\\\", \\\"0\\\");\\n\\t\\tconst { shaderChunks } = material;\\n\\t\\tshaderChunks.glsl.set(\\\"gsplatSogColorVS\\\", gsplatSogColorGLSL);\\n\\t\\tshaderChunks.wgsl.set(\\\"gsplatSogColorVS\\\", gsplatSogColorWGSL);\\n\\t\\tmaterial.update();\\n\\t\\tdevice.scope.resolve(\\\"sh_result\\\").setValue(this.texture);\\n\\t}\\n\\tdestroy() {\\n\\t\\tconst { gsplatInstance } = this;\\n\\t\\tconst { material } = gsplatInstance;\\n\\t\\tmaterial.setDefine(\\\"SH_BANDS\\\", gsplatInstance.resource.gsplatData.shBands.toString());\\n\\t\\tconst { shaderChunks } = material;\\n\\t\\tshaderChunks.glsl.delete(\\\"gsplatSogColorVS\\\");\\n\\t\\tshaderChunks.wgsl.delete(\\\"gsplatSogColorVS\\\");\\n\\t\\tmaterial.update();\\n\\t\\tthis.quadRender.destroy();\\n\\t\\tthis.renderPass.destroy();\\n\\t\\tthis.renderTarget.destroy();\\n\\t\\tthis.texture.destroy();\\n\\t\\tthis.shader.destroy();\\n\\t}\\n\\trender(camera, modelMat) {\\n\\t\\tconst { prevDir, updateMode } = this;\\n\\t\\tif (updateMode === \\\"disable\\\") {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tinvModelMat$1.invert(modelMat);\\n\\t\\tinvModelMat$1.transformVector(camera.forward, dir$1);\\n\\t\\tdir$1.normalize();\\n\\t\\tif (updateMode === \\\"enable\\\" && dir$1.equalsApprox(prevDir, 1e-3)) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tprevDir.copy(dir$1);\\n\\t\\tconst execute = () => {\\n\\t\\t\\tconst { device } = this;\\n\\t\\t\\tconst { sh_centroids, meta } = this.gsplatInstance.resource.gsplatData;\\n\\t\\t\\tresolve$1(device.scope, {\\n\\t\\t\\t\\tdir: dir$1.toArray(),\\n\\t\\t\\t\\tcentroids: sh_centroids,\\n\\t\\t\\t\\tshN_mins: meta.shN.mins,\\n\\t\\t\\t\\tshN_maxs: meta.shN.maxs\\n\\t\\t\\t});\\n\\t\\t\\tdevice.setDrawStates();\\n\\t\\t\\tthis.quadRender.render();\\n\\t\\t};\\n\\t\\tthis.renderPass.executeCallback = execute;\\n\\t\\tthis.renderPass.render();\\n\\t}\\n}\\n\\nfunction SortWorker() {\\n\\tconst myself = typeof self !== \\\"undefined\\\" && self || require(\\\"node:worker_threads\\\").parentPort;\\n\\tlet order;\\n\\tlet centers;\\n\\tlet chunks;\\n\\tlet mapping;\\n\\tlet cameraPosition;\\n\\tlet cameraDirection;\\n\\tlet forceUpdate = false;\\n\\tconst lastCameraPosition = { x: 0, y: 0, z: 0 };\\n\\tconst lastCameraDirection = { x: 0, y: 0, z: 0 };\\n\\tconst boundMin = { x: 0, y: 0, z: 0 };\\n\\tconst boundMax = { x: 0, y: 0, z: 0 };\\n\\tlet distances;\\n\\tlet countBuffer;\\n\\tconst numBins = 32;\\n\\tconst binCount = new Array(numBins).fill(0);\\n\\tconst binBase = new Array(numBins).fill(0);\\n\\tconst binDivider = new Array(numBins).fill(0);\\n\\tconst binarySearch = (m, n, compare_fn) => {\\n\\t\\twhile (m <= n) {\\n\\t\\t\\tconst k = n + m >> 1;\\n\\t\\t\\tconst cmp = compare_fn(k);\\n\\t\\t\\tif (cmp > 0) {\\n\\t\\t\\t\\tm = k + 1;\\n\\t\\t\\t} else if (cmp < 0) {\\n\\t\\t\\t\\tn = k - 1;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\treturn k;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn ~m;\\n\\t};\\n\\tconst update = () => {\\n\\t\\tif (!order || !centers || centers.length === 0 || !cameraPosition || !cameraDirection) return;\\n\\t\\tconst sortStartTime = performance.now();\\n\\t\\tconst px = cameraPosition.x;\\n\\t\\tconst py = cameraPosition.y;\\n\\t\\tconst pz = cameraPosition.z;\\n\\t\\tconst dx = cameraDirection.x;\\n\\t\\tconst dy = cameraDirection.y;\\n\\t\\tconst dz = cameraDirection.z;\\n\\t\\tconst epsilon = 1e-3;\\n\\t\\tif (!forceUpdate && Math.abs(px - lastCameraPosition.x) < epsilon && Math.abs(py - lastCameraPosition.y) < epsilon && Math.abs(pz - lastCameraPosition.z) < epsilon && Math.abs(dx - lastCameraDirection.x) < epsilon && Math.abs(dy - lastCameraDirection.y) < epsilon && Math.abs(dz - lastCameraDirection.z) < epsilon) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tforceUpdate = false;\\n\\t\\tlastCameraPosition.x = px;\\n\\t\\tlastCameraPosition.y = py;\\n\\t\\tlastCameraPosition.z = pz;\\n\\t\\tlastCameraDirection.x = dx;\\n\\t\\tlastCameraDirection.y = dy;\\n\\t\\tlastCameraDirection.z = dz;\\n\\t\\tlet minDist;\\n\\t\\tlet maxDist;\\n\\t\\tfor (let i = 0; i < 8; ++i) {\\n\\t\\t\\tconst x = i & 1 ? boundMin.x : boundMax.x;\\n\\t\\t\\tconst y = i & 2 ? boundMin.y : boundMax.y;\\n\\t\\t\\tconst z = i & 4 ? boundMin.z : boundMax.z;\\n\\t\\t\\tconst d = x * dx + y * dy + z * dz;\\n\\t\\t\\tif (i === 0) {\\n\\t\\t\\t\\tminDist = maxDist = d;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tminDist = Math.min(minDist, d);\\n\\t\\t\\t\\tmaxDist = Math.max(maxDist, d);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst numVertices = centers.length / 3;\\n\\t\\tconst compareBits = Math.max(10, Math.min(20, Math.round(Math.log2(numVertices / 4))));\\n\\t\\tconst bucketCount = 2 ** compareBits + 1;\\n\\t\\tif (distances?.length !== numVertices) {\\n\\t\\t\\tdistances = new Uint32Array(numVertices);\\n\\t\\t}\\n\\t\\tif (!countBuffer || countBuffer.length !== bucketCount) {\\n\\t\\t\\tcountBuffer = new Uint32Array(bucketCount);\\n\\t\\t} else {\\n\\t\\t\\tcountBuffer.fill(0);\\n\\t\\t}\\n\\t\\tconst range = maxDist - minDist;\\n\\t\\tif (range < 1e-6) {\\n\\t\\t\\tfor (let i = 0; i < numVertices; ++i) {\\n\\t\\t\\t\\tdistances[i] = 0;\\n\\t\\t\\t\\tcountBuffer[0]++;\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tconst numChunks = chunks.length / 4;\\n\\t\\t\\tbinCount.fill(0);\\n\\t\\t\\tfor (let i = 0; i < numChunks; ++i) {\\n\\t\\t\\t\\tconst x = chunks[i * 4 + 0];\\n\\t\\t\\t\\tconst y = chunks[i * 4 + 1];\\n\\t\\t\\t\\tconst z = chunks[i * 4 + 2];\\n\\t\\t\\t\\tconst r = chunks[i * 4 + 3];\\n\\t\\t\\t\\tconst d = x * dx + y * dy + z * dz - minDist;\\n\\t\\t\\t\\tconst binMin = Math.max(0, Math.floor((d - r) * numBins / range));\\n\\t\\t\\t\\tconst binMax = Math.min(numBins, Math.ceil((d + r) * numBins / range));\\n\\t\\t\\t\\tfor (let j = binMin; j < binMax; ++j) {\\n\\t\\t\\t\\t\\tbinCount[j]++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tconst binTotal = binCount.reduce((a, b) => a + b, 0);\\n\\t\\t\\tfor (let i = 0; i < numBins; ++i) {\\n\\t\\t\\t\\tbinDivider[i] = binCount[i] / binTotal * bucketCount >>> 0;\\n\\t\\t\\t}\\n\\t\\t\\tfor (let i = 0; i < numBins; ++i) {\\n\\t\\t\\t\\tbinBase[i] = i === 0 ? 0 : binBase[i - 1] + binDivider[i - 1];\\n\\t\\t\\t}\\n\\t\\t\\tconst binRange = range / numBins;\\n\\t\\t\\tlet ii = 0;\\n\\t\\t\\tfor (let i = 0; i < numVertices; ++i) {\\n\\t\\t\\t\\tconst x = centers[ii++];\\n\\t\\t\\t\\tconst y = centers[ii++];\\n\\t\\t\\t\\tconst z = centers[ii++];\\n\\t\\t\\t\\tconst d = (x * dx + y * dy + z * dz - minDist) / binRange;\\n\\t\\t\\t\\tconst bin = d >>> 0;\\n\\t\\t\\t\\tconst sortKey = binBase[bin] + binDivider[bin] * (d - bin) >>> 0;\\n\\t\\t\\t\\tdistances[i] = sortKey;\\n\\t\\t\\t\\tcountBuffer[sortKey]++;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (let i = 1; i < bucketCount; i++) {\\n\\t\\t\\tcountBuffer[i] += countBuffer[i - 1];\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < numVertices; i++) {\\n\\t\\t\\tconst distance = distances[i];\\n\\t\\t\\tconst destIndex = --countBuffer[distance];\\n\\t\\t\\torder[destIndex] = i;\\n\\t\\t}\\n\\t\\tconst cameraDist = px * dx + py * dy + pz * dz;\\n\\t\\tconst dist = (i) => {\\n\\t\\t\\tlet o = order[i] * 3;\\n\\t\\t\\treturn centers[o++] * dx + centers[o++] * dy + centers[o] * dz - cameraDist;\\n\\t\\t};\\n\\t\\tconst findZero = () => {\\n\\t\\t\\tconst result = binarySearch(0, numVertices - 1, (i) => -dist(i));\\n\\t\\t\\treturn Math.min(numVertices, Math.abs(result));\\n\\t\\t};\\n\\t\\tconst count = dist(numVertices - 1) >= 0 ? findZero() : numVertices;\\n\\t\\tif (mapping) {\\n\\t\\t\\tfor (let i = 0; i < numVertices; ++i) {\\n\\t\\t\\t\\torder[i] = mapping[order[i]];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tmyself.postMessage({\\n\\t\\t\\torder: order.buffer,\\n\\t\\t\\tcount,\\n\\t\\t\\tsortTime: performance.now() - sortStartTime\\n\\t\\t}, [order.buffer]);\\n\\t\\torder = null;\\n\\t};\\n\\tmyself.addEventListener(\\\"message\\\", (message) => {\\n\\t\\tconst msgData = message.data ?? message;\\n\\t\\tif (msgData.order) {\\n\\t\\t\\torder = new Uint32Array(msgData.order);\\n\\t\\t}\\n\\t\\tif (msgData.centers) {\\n\\t\\t\\tcenters = new Float32Array(msgData.centers);\\n\\t\\t\\tforceUpdate = true;\\n\\t\\t\\tif (msgData.chunks) {\\n\\t\\t\\t\\tconst chunksSrc = new Float32Array(msgData.chunks);\\n\\t\\t\\t\\tchunks = new Float32Array(msgData.chunks, 0, chunksSrc.length * 4 / 6);\\n\\t\\t\\t\\tboundMin.x = chunksSrc[0];\\n\\t\\t\\t\\tboundMin.y = chunksSrc[1];\\n\\t\\t\\t\\tboundMin.z = chunksSrc[2];\\n\\t\\t\\t\\tboundMax.x = chunksSrc[3];\\n\\t\\t\\t\\tboundMax.y = chunksSrc[4];\\n\\t\\t\\t\\tboundMax.z = chunksSrc[5];\\n\\t\\t\\t\\tfor (let i = 0; i < chunksSrc.length / 6; ++i) {\\n\\t\\t\\t\\t\\tconst mx = chunksSrc[i * 6 + 0];\\n\\t\\t\\t\\t\\tconst my = chunksSrc[i * 6 + 1];\\n\\t\\t\\t\\t\\tconst mz = chunksSrc[i * 6 + 2];\\n\\t\\t\\t\\t\\tconst Mx = chunksSrc[i * 6 + 3];\\n\\t\\t\\t\\t\\tconst My = chunksSrc[i * 6 + 4];\\n\\t\\t\\t\\t\\tconst Mz = chunksSrc[i * 6 + 5];\\n\\t\\t\\t\\t\\tchunks[i * 4 + 0] = (mx + Mx) * 0.5;\\n\\t\\t\\t\\t\\tchunks[i * 4 + 1] = (my + My) * 0.5;\\n\\t\\t\\t\\t\\tchunks[i * 4 + 2] = (mz + Mz) * 0.5;\\n\\t\\t\\t\\t\\tchunks[i * 4 + 3] = Math.sqrt((Mx - mx) ** 2 + (My - my) ** 2 + (Mz - mz) ** 2) * 0.5;\\n\\t\\t\\t\\t\\tif (mx < boundMin.x) boundMin.x = mx;\\n\\t\\t\\t\\t\\tif (my < boundMin.y) boundMin.y = my;\\n\\t\\t\\t\\t\\tif (mz < boundMin.z) boundMin.z = mz;\\n\\t\\t\\t\\t\\tif (Mx > boundMax.x) boundMax.x = Mx;\\n\\t\\t\\t\\t\\tif (My > boundMax.y) boundMax.y = My;\\n\\t\\t\\t\\t\\tif (Mz > boundMax.z) boundMax.z = Mz;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconst numVertices = centers.length / 3;\\n\\t\\t\\t\\tconst numChunks = Math.ceil(numVertices / 256);\\n\\t\\t\\t\\tchunks = new Float32Array(numChunks * 4);\\n\\t\\t\\t\\tboundMin.x = boundMin.y = boundMin.z = Infinity;\\n\\t\\t\\t\\tboundMax.x = boundMax.y = boundMax.z = -Infinity;\\n\\t\\t\\t\\tlet mx, my, mz, Mx, My, Mz;\\n\\t\\t\\t\\tfor (let c = 0; c < numChunks; ++c) {\\n\\t\\t\\t\\t\\tmx = my = mz = Infinity;\\n\\t\\t\\t\\t\\tMx = My = Mz = -Infinity;\\n\\t\\t\\t\\t\\tconst start = c * 256;\\n\\t\\t\\t\\t\\tconst end = Math.min(numVertices, (c + 1) * 256);\\n\\t\\t\\t\\t\\tfor (let i = start; i < end; ++i) {\\n\\t\\t\\t\\t\\t\\tconst x = centers[i * 3 + 0];\\n\\t\\t\\t\\t\\t\\tconst y = centers[i * 3 + 1];\\n\\t\\t\\t\\t\\t\\tconst z = centers[i * 3 + 2];\\n\\t\\t\\t\\t\\t\\tconst validX = Number.isFinite(x);\\n\\t\\t\\t\\t\\t\\tconst validY = Number.isFinite(y);\\n\\t\\t\\t\\t\\t\\tconst validZ = Number.isFinite(z);\\n\\t\\t\\t\\t\\t\\tif (!validX) centers[i * 3 + 0] = 0;\\n\\t\\t\\t\\t\\t\\tif (!validY) centers[i * 3 + 1] = 0;\\n\\t\\t\\t\\t\\t\\tif (!validZ) centers[i * 3 + 2] = 0;\\n\\t\\t\\t\\t\\t\\tif (!validX || !validY || !validZ) {\\n\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (x < mx) mx = x;\\n\\t\\t\\t\\t\\t\\telse if (x > Mx) Mx = x;\\n\\t\\t\\t\\t\\t\\tif (y < my) my = y;\\n\\t\\t\\t\\t\\t\\telse if (y > My) My = y;\\n\\t\\t\\t\\t\\t\\tif (z < mz) mz = z;\\n\\t\\t\\t\\t\\t\\telse if (z > Mz) Mz = z;\\n\\t\\t\\t\\t\\t\\tif (x < boundMin.x) boundMin.x = x;\\n\\t\\t\\t\\t\\t\\telse if (x > boundMax.x) boundMax.x = x;\\n\\t\\t\\t\\t\\t\\tif (y < boundMin.y) boundMin.y = y;\\n\\t\\t\\t\\t\\t\\telse if (y > boundMax.y) boundMax.y = y;\\n\\t\\t\\t\\t\\t\\tif (z < boundMin.z) boundMin.z = z;\\n\\t\\t\\t\\t\\t\\telse if (z > boundMax.z) boundMax.z = z;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tchunks[c * 4 + 0] = (mx + Mx) * 0.5;\\n\\t\\t\\t\\t\\tchunks[c * 4 + 1] = (my + My) * 0.5;\\n\\t\\t\\t\\t\\tchunks[c * 4 + 2] = (mz + Mz) * 0.5;\\n\\t\\t\\t\\t\\tchunks[c * 4 + 3] = Math.sqrt((Mx - mx) ** 2 + (My - my) ** 2 + (Mz - mz) ** 2) * 0.5;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (msgData.hasOwnProperty(\\\"mapping\\\")) {\\n\\t\\t\\tmapping = msgData.mapping ? new Uint32Array(msgData.mapping) : null;\\n\\t\\t\\tforceUpdate = true;\\n\\t\\t}\\n\\t\\tif (msgData.cameraPosition) cameraPosition = msgData.cameraPosition;\\n\\t\\tif (msgData.cameraDirection) cameraDirection = msgData.cameraDirection;\\n\\t\\tupdate();\\n\\t});\\n}\\n\\nclass GSplatSorter extends EventHandler {\\n\\tworker;\\n\\ttarget;\\n\\torderData;\\n\\tcenters;\\n\\tscene;\\n\\tuploadStream;\\n\\tpendingSorted = null;\\n\\tconstructor(device, scene) {\\n\\t\\tsuper();\\n\\t\\tthis.scene = scene ?? null;\\n\\t\\tthis.uploadStream = new UploadStream(device, !device.isWebGPU);\\n\\t\\tconst messageHandler = (message) => {\\n\\t\\t\\tconst msgData = message.data ?? message;\\n\\t\\t\\tif (this.scene && msgData.sortTime !== void 0) {\\n\\t\\t\\t\\tthis.scene.fire(\\\"gsplat:sorted\\\", msgData.sortTime);\\n\\t\\t\\t}\\n\\t\\t\\tconst newOrder = msgData.order;\\n\\t\\t\\tconst oldOrder = this.orderData;\\n\\t\\t\\tthis.worker.postMessage({\\n\\t\\t\\t\\torder: oldOrder\\n\\t\\t\\t}, [oldOrder]);\\n\\t\\t\\tthis.orderData = newOrder;\\n\\t\\t\\tthis.pendingSorted = {\\n\\t\\t\\t\\tcount: msgData.count,\\n\\t\\t\\t\\tdata: new Uint32Array(newOrder)\\n\\t\\t\\t};\\n\\t\\t\\tthis.fire(\\\"updated\\\");\\n\\t\\t};\\n\\t\\tconst workerSource = `(${SortWorker.toString()})()`;\\n\\t\\tif (platform.environment === \\\"node\\\") {\\n\\t\\t\\tthis.worker = new Worker(workerSource, {\\n\\t\\t\\t\\teval: true\\n\\t\\t\\t});\\n\\t\\t\\tthis.worker.on(\\\"message\\\", messageHandler);\\n\\t\\t} else {\\n\\t\\t\\tthis.worker = new Worker(URL.createObjectURL(new Blob([workerSource], {\\n\\t\\t\\t\\ttype: \\\"application/javascript\\\"\\n\\t\\t\\t})));\\n\\t\\t\\tthis.worker.addEventListener(\\\"message\\\", messageHandler);\\n\\t\\t}\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.worker.terminate();\\n\\t\\tthis.worker = null;\\n\\t\\tthis.uploadStream.destroy();\\n\\t\\tthis.uploadStream = null;\\n\\t}\\n\\tinit(target, numSplats, centers, chunks) {\\n\\t\\tthis.target = target;\\n\\t\\tthis.centers = centers.slice();\\n\\t\\tconst orderBuffer = new Uint32Array(numSplats);\\n\\t\\tfor (let i = 0; i < numSplats; ++i) {\\n\\t\\t\\torderBuffer[i] = i;\\n\\t\\t}\\n\\t\\tthis.orderData = new ArrayBuffer(numSplats * 4);\\n\\t\\tconst obj = {\\n\\t\\t\\torder: orderBuffer.buffer,\\n\\t\\t\\tcenters: centers.buffer,\\n\\t\\t\\tchunks: chunks?.buffer\\n\\t\\t};\\n\\t\\tconst transfer = [orderBuffer.buffer, centers.buffer].concat(chunks ? [chunks.buffer] : []);\\n\\t\\tthis.worker.postMessage(obj, transfer);\\n\\t}\\n\\tapplyPendingSorted() {\\n\\t\\tif (this.pendingSorted) {\\n\\t\\t\\tconst { count, data } = this.pendingSorted;\\n\\t\\t\\tthis.pendingSorted = null;\\n\\t\\t\\tthis.uploadStream.upload(data, this.target);\\n\\t\\t\\treturn count;\\n\\t\\t}\\n\\t\\treturn -1;\\n\\t}\\n\\tsetMapping(mapping) {\\n\\t\\tif (mapping) {\\n\\t\\t\\tconst centers = new Float32Array(mapping.length * 3);\\n\\t\\t\\tfor (let i = 0; i < mapping.length; ++i) {\\n\\t\\t\\t\\tconst src = mapping[i] * 3;\\n\\t\\t\\t\\tconst dst = i * 3;\\n\\t\\t\\t\\tcenters[dst + 0] = this.centers[src + 0];\\n\\t\\t\\t\\tcenters[dst + 1] = this.centers[src + 1];\\n\\t\\t\\t\\tcenters[dst + 2] = this.centers[src + 2];\\n\\t\\t\\t}\\n\\t\\t\\tthis.worker.postMessage({\\n\\t\\t\\t\\tcenters: centers.buffer,\\n\\t\\t\\t\\tmapping: mapping.buffer\\n\\t\\t\\t}, [centers.buffer, mapping.buffer]);\\n\\t\\t} else {\\n\\t\\t\\tconst centers = this.centers.slice();\\n\\t\\t\\tthis.worker.postMessage({\\n\\t\\t\\t\\tcenters: centers.buffer,\\n\\t\\t\\t\\tmapping: null\\n\\t\\t\\t}, [centers.buffer]);\\n\\t\\t}\\n\\t}\\n\\tsetCamera(pos, dir) {\\n\\t\\tthis.worker.postMessage({\\n\\t\\t\\tcameraPosition: { x: pos.x, y: pos.y, z: pos.z },\\n\\t\\t\\tcameraDirection: { x: dir.x, y: dir.y, z: dir.z }\\n\\t\\t});\\n\\t}\\n}\\n\\nvar gsplatSogCenters_default$1 = `\\n#include \\\"gsplatPackingPS\\\"\\nuniform highp sampler2D means_l;\\nuniform highp sampler2D means_u;\\nuniform highp uint numSplats;\\nuniform highp vec3 means_mins;\\nuniform highp vec3 means_maxs;\\nvoid main(void) {\\n\\tint w = int(textureSize(means_l, 0).x);\\n\\tivec2 uv = ivec2(gl_FragCoord.xy);\\n\\tif (uint(uv.x + uv.y * w) >= numSplats) {\\n\\t\\tdiscard;\\n\\t}\\n\\tvec3 l = texelFetch(means_l, uv, 0).xyz;\\n\\tvec3 u = texelFetch(means_u, uv, 0).xyz;\\n\\tvec3 n = (l + u * 256.0) / 257.0;\\n\\tvec3 v = mix(means_mins, means_maxs, n);\\n\\tvec3 center = sign(v) * (exp(abs(v)) - 1.0);\\n\\tpcFragColor0 = uvec4(floatBitsToUint(center), 0u);\\n}\\n`;\\n\\nvar gsplatSogCenters_default = `\\nvar means_l: texture_2d<f32>;\\nvar means_u: texture_2d<f32>;\\nuniform numSplats: u32;\\nuniform means_mins: vec3f;\\nuniform means_maxs: vec3f;\\n@fragment\\nfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\tvar output: FragmentOutput;\\n\\tlet w: u32 = textureDimensions(means_l, 0).x;\\n\\tlet uv: vec2<i32> = vec2<i32>(input.position.xy);\\n\\tif (u32(uv.x + uv.y * i32(w)) >= uniform.numSplats) {\\n\\t\\tdiscard;\\n\\t\\treturn output;\\n\\t}\\n\\tlet l: vec3f = textureLoad(means_l, uv, 0).xyz;\\n\\tlet u: vec3f = textureLoad(means_u, uv, 0).xyz;\\n\\tlet n: vec3f = (l + u * 256.0) / 257.0;\\n\\tlet v: vec3f = mix(uniform.means_mins, uniform.means_maxs, n);\\n\\tlet center: vec3f = sign(v) * (exp(abs(v)) - 1.0);\\n\\tlet packed: vec4<u32> = bitcast<vec4<u32>>(vec4f(center, 0.0));\\n\\toutput.color = packed;\\n\\treturn output;\\n}\\n`;\\n\\nconst SH_C0$1 = 0.28209479177387814;\\nconst readImageDataAsync = (texture) => {\\n\\tif (texture.device.isNull) {\\n\\t\\treturn new Promise((resolve2) => {\\n\\t\\t\\tresolve2(new Uint8Array(texture.width * texture.height * 4));\\n\\t\\t});\\n\\t}\\n\\treturn texture.read(0, 0, texture.width, texture.height, {\\n\\t\\tmipLevel: 0,\\n\\t\\tface: 0,\\n\\t\\timmediate: true\\n\\t});\\n};\\nconst resolve = (scope, values) => {\\n\\tfor (const key in values) {\\n\\t\\tscope.resolve(key).setValue(values[key]);\\n\\t}\\n};\\nclass GSplatSogIterator {\\n\\tconstructor(data, p, r, s, c, sh) {\\n\\t\\tconst lerp = (a, b, t) => a * (1 - t) + b * t;\\n\\t\\tconst { meta, shBands } = data;\\n\\t\\tconst { means, scales, sh0, shN } = meta;\\n\\t\\tconst means_l_data = p && data.means_l._levels[0];\\n\\t\\tconst means_u_data = p && data.means_u._levels[0];\\n\\t\\tconst quats_data = r && data.quats._levels[0];\\n\\t\\tconst scales_data = s && data.scales._levels[0];\\n\\t\\tconst sh0_data = c && data.sh0._levels[0];\\n\\t\\tconst sh_labels_data = sh && data.sh_labels._levels[0];\\n\\t\\tconst sh_centroids_data = sh && data.sh_centroids._levels[0];\\n\\t\\tconst norm = Math.SQRT2;\\n\\t\\tconst coeffs = { 1: 3, 2: 8, 3: 15 }[shBands] ?? 0;\\n\\t\\tthis.read = (i) => {\\n\\t\\t\\tif (p) {\\n\\t\\t\\t\\tconst nx = lerp(means.mins[0], means.maxs[0], ((means_u_data[i * 4 + 0] << 8) + means_l_data[i * 4 + 0]) / 65535);\\n\\t\\t\\t\\tconst ny = lerp(means.mins[1], means.maxs[1], ((means_u_data[i * 4 + 1] << 8) + means_l_data[i * 4 + 1]) / 65535);\\n\\t\\t\\t\\tconst nz = lerp(means.mins[2], means.maxs[2], ((means_u_data[i * 4 + 2] << 8) + means_l_data[i * 4 + 2]) / 65535);\\n\\t\\t\\t\\tp.x = Math.sign(nx) * (Math.exp(Math.abs(nx)) - 1);\\n\\t\\t\\t\\tp.y = Math.sign(ny) * (Math.exp(Math.abs(ny)) - 1);\\n\\t\\t\\t\\tp.z = Math.sign(nz) * (Math.exp(Math.abs(nz)) - 1);\\n\\t\\t\\t}\\n\\t\\t\\tif (r) {\\n\\t\\t\\t\\tconst a = (quats_data[i * 4 + 0] / 255 - 0.5) * norm;\\n\\t\\t\\t\\tconst b = (quats_data[i * 4 + 1] / 255 - 0.5) * norm;\\n\\t\\t\\t\\tconst c2 = (quats_data[i * 4 + 2] / 255 - 0.5) * norm;\\n\\t\\t\\t\\tconst d = Math.sqrt(Math.max(0, 1 - (a * a + b * b + c2 * c2)));\\n\\t\\t\\t\\tconst mode = quats_data[i * 4 + 3] - 252;\\n\\t\\t\\t\\tswitch (mode) {\\n\\t\\t\\t\\t\\tcase 0:\\n\\t\\t\\t\\t\\t\\tr.set(a, b, c2, d);\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\tcase 1:\\n\\t\\t\\t\\t\\t\\tr.set(d, b, c2, a);\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\tcase 2:\\n\\t\\t\\t\\t\\t\\tr.set(b, d, c2, a);\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\tcase 3:\\n\\t\\t\\t\\t\\t\\tr.set(b, c2, d, a);\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (s) {\\n\\t\\t\\t\\tif (meta.version === 2) {\\n\\t\\t\\t\\t\\tconst sx = scales.codebook[scales_data[i * 4 + 0]];\\n\\t\\t\\t\\t\\tconst sy = scales.codebook[scales_data[i * 4 + 1]];\\n\\t\\t\\t\\t\\tconst sz = scales.codebook[scales_data[i * 4 + 2]];\\n\\t\\t\\t\\t\\ts.set(sx, sy, sz);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tconst sx = lerp(scales.mins[0], scales.maxs[0], scales_data[i * 4 + 0] / 255);\\n\\t\\t\\t\\t\\tconst sy = lerp(scales.mins[1], scales.maxs[1], scales_data[i * 4 + 1] / 255);\\n\\t\\t\\t\\t\\tconst sz = lerp(scales.mins[2], scales.maxs[2], scales_data[i * 4 + 2] / 255);\\n\\t\\t\\t\\t\\ts.set(sx, sy, sz);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (c) {\\n\\t\\t\\t\\tif (meta.version === 2) {\\n\\t\\t\\t\\t\\tconst r2 = sh0.codebook[sh0_data[i * 4 + 0]];\\n\\t\\t\\t\\t\\tconst g = sh0.codebook[sh0_data[i * 4 + 1]];\\n\\t\\t\\t\\t\\tconst b = sh0.codebook[sh0_data[i * 4 + 2]];\\n\\t\\t\\t\\t\\tconst a = sh0_data[i * 4 + 3] / 255;\\n\\t\\t\\t\\t\\tc.set(\\n\\t\\t\\t\\t\\t\\t0.5 + r2 * SH_C0$1,\\n\\t\\t\\t\\t\\t\\t0.5 + g * SH_C0$1,\\n\\t\\t\\t\\t\\t\\t0.5 + b * SH_C0$1,\\n\\t\\t\\t\\t\\t\\ta\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tconst r2 = lerp(sh0.mins[0], sh0.maxs[0], sh0_data[i * 4 + 0] / 255);\\n\\t\\t\\t\\t\\tconst g = lerp(sh0.mins[1], sh0.maxs[1], sh0_data[i * 4 + 1] / 255);\\n\\t\\t\\t\\t\\tconst b = lerp(sh0.mins[2], sh0.maxs[2], sh0_data[i * 4 + 2] / 255);\\n\\t\\t\\t\\t\\tconst a = lerp(sh0.mins[3], sh0.maxs[3], sh0_data[i * 4 + 3] / 255);\\n\\t\\t\\t\\t\\tc.set(\\n\\t\\t\\t\\t\\t\\t0.5 + r2 * SH_C0$1,\\n\\t\\t\\t\\t\\t\\t0.5 + g * SH_C0$1,\\n\\t\\t\\t\\t\\t\\t0.5 + b * SH_C0$1,\\n\\t\\t\\t\\t\\t\\t1 / (1 + Math.exp(-a))\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (sh) {\\n\\t\\t\\t\\tconst n = sh_labels_data[i * 4 + 0] + (sh_labels_data[i * 4 + 1] << 8);\\n\\t\\t\\t\\tconst u = n % 64 * coeffs;\\n\\t\\t\\t\\tconst v = Math.floor(n / 64);\\n\\t\\t\\t\\tif (meta.version === 2) {\\n\\t\\t\\t\\t\\tfor (let j = 0; j < 3; ++j) {\\n\\t\\t\\t\\t\\t\\tfor (let k = 0; k < coeffs; ++k) {\\n\\t\\t\\t\\t\\t\\t\\tsh[j * 15 + k] = shN.codebook[sh_centroids_data[(u + k) * 4 + j + v * data.sh_centroids.width * 4]];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tfor (let j = 0; j < 3; ++j) {\\n\\t\\t\\t\\t\\t\\tfor (let k = 0; k < coeffs; ++k) {\\n\\t\\t\\t\\t\\t\\t\\tsh[j * 15 + k] = lerp(shN.mins, shN.maxs, sh_centroids_data[(u + k) * 4 + j + v * data.sh_centroids.width * 4] / 255);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t};\\n\\t}\\n}\\nclass GSplatSogData {\\n\\tmeta;\\n\\tnumSplats;\\n\\tmeans_l;\\n\\tmeans_u;\\n\\tquats;\\n\\tscales;\\n\\tsh0;\\n\\tsh_centroids;\\n\\tsh_labels;\\n\\tcodebookTexture = null;\\n\\turl = \\\"\\\";\\n\\t_centers = null;\\n\\t// Marked when resource is destroyed, to abort any in-flight async preparation\\n\\tdestroyed = false;\\n\\tshBands = 0;\\n\\t_destroyGpuResources() {\\n\\t\\tthis.means_l?.destroy();\\n\\t\\tthis.means_u?.destroy();\\n\\t\\tthis.quats?.destroy();\\n\\t\\tthis.scales?.destroy();\\n\\t\\tthis.sh0?.destroy();\\n\\t\\tthis.sh_centroids?.destroy();\\n\\t\\tthis.sh_labels?.destroy();\\n\\t\\tthis.codebookTexture?.destroy();\\n\\t\\tthis.codebookTexture = null;\\n\\t}\\n\\t// calculate the number of bands given the centroids texture width\\n\\tstatic calcBands(centroidsWidth) {\\n\\t\\tconst shBandsWidths = { 192: 1, 512: 2, 960: 3 };\\n\\t\\treturn shBandsWidths[centroidsWidth] ?? 0;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.destroyed = true;\\n\\t\\tthis._destroyGpuResources();\\n\\t}\\n\\tcreateIter(p, r, s, c, sh) {\\n\\t\\treturn new GSplatSogIterator(this, p, r, s, c, sh);\\n\\t}\\n\\tcalcAabb(result) {\\n\\t\\tconst { mins, maxs } = this.meta.means;\\n\\t\\tconst map = (v) => Math.sign(v) * (Math.exp(Math.abs(v)) - 1);\\n\\t\\tresult.center.set(\\n\\t\\t\\t(map(mins[0]) + map(maxs[0])) * 0.5,\\n\\t\\t\\t(map(mins[1]) + map(maxs[1])) * 0.5,\\n\\t\\t\\t(map(mins[2]) + map(maxs[2])) * 0.5\\n\\t\\t);\\n\\t\\tresult.halfExtents.set(\\n\\t\\t\\t(map(maxs[0]) - map(mins[0])) * 0.5,\\n\\t\\t\\t(map(maxs[1]) - map(mins[1])) * 0.5,\\n\\t\\t\\t(map(maxs[2]) - map(mins[2])) * 0.5\\n\\t\\t);\\n\\t}\\n\\tgetCenters() {\\n\\t\\tconst centers = this._centers;\\n\\t\\tthis._centers = null;\\n\\t\\treturn centers;\\n\\t}\\n\\t// use bound center for focal point\\n\\tcalcFocalPoint(result, pred) {\\n\\t\\tconst { mins, maxs } = this.meta.means;\\n\\t\\tconst map = (v) => Math.sign(v) * (Math.exp(Math.abs(v)) - 1);\\n\\t\\tresult.set(\\n\\t\\t\\t(map(mins[0]) + map(maxs[0])) * 0.5,\\n\\t\\t\\t(map(mins[1]) + map(maxs[1])) * 0.5,\\n\\t\\t\\t(map(mins[2]) + map(maxs[2])) * 0.5\\n\\t\\t);\\n\\t}\\n\\tget isSog() {\\n\\t\\treturn true;\\n\\t}\\n\\tasync decompress() {\\n\\t\\tconst members = [\\n\\t\\t\\t\\\"x\\\",\\n\\t\\t\\t\\\"y\\\",\\n\\t\\t\\t\\\"z\\\",\\n\\t\\t\\t\\\"f_dc_0\\\",\\n\\t\\t\\t\\\"f_dc_1\\\",\\n\\t\\t\\t\\\"f_dc_2\\\",\\n\\t\\t\\t\\\"opacity\\\",\\n\\t\\t\\t\\\"scale_0\\\",\\n\\t\\t\\t\\\"scale_1\\\",\\n\\t\\t\\t\\\"scale_2\\\",\\n\\t\\t\\t\\\"rot_0\\\",\\n\\t\\t\\t\\\"rot_1\\\",\\n\\t\\t\\t\\\"rot_2\\\",\\n\\t\\t\\t\\\"rot_3\\\"\\n\\t\\t];\\n\\t\\tthis._patchCodebooks();\\n\\t\\tconst { shBands } = this;\\n\\t\\tconst { means_l, means_u, quats, scales, sh0, sh_labels, sh_centroids } = this;\\n\\t\\tmeans_l._levels[0] = await readImageDataAsync(means_l);\\n\\t\\tmeans_u._levels[0] = await readImageDataAsync(means_u);\\n\\t\\tquats._levels[0] = await readImageDataAsync(quats);\\n\\t\\tscales._levels[0] = await readImageDataAsync(scales);\\n\\t\\tsh0._levels[0] = await readImageDataAsync(sh0);\\n\\t\\tif (shBands > 0) {\\n\\t\\t\\tsh_labels._levels[0] = await readImageDataAsync(sh_labels);\\n\\t\\t\\tsh_centroids._levels[0] = await readImageDataAsync(sh_centroids);\\n\\t\\t\\tconst shMembers = [];\\n\\t\\t\\tfor (let i = 0; i < 45; ++i) {\\n\\t\\t\\t\\tshMembers.push(`f_rest_${i}`);\\n\\t\\t\\t}\\n\\t\\t\\tmembers.splice(members.indexOf(\\\"f_dc_0\\\") + 1, 0, ...shMembers);\\n\\t\\t}\\n\\t\\tconst data = {};\\n\\t\\tmembers.forEach((name) => {\\n\\t\\t\\tdata[name] = new Float32Array(this.numSplats);\\n\\t\\t});\\n\\t\\tconst p = new Vec3();\\n\\t\\tconst r = new Quat();\\n\\t\\tconst s = new Vec3();\\n\\t\\tconst c = new Vec4();\\n\\t\\tconst sh = shBands > 0 ? new Float32Array(45) : null;\\n\\t\\tconst iter = this.createIter(p, r, s, c, sh);\\n\\t\\tfor (let i = 0; i < this.numSplats; ++i) {\\n\\t\\t\\titer.read(i);\\n\\t\\t\\tdata.x[i] = p.x;\\n\\t\\t\\tdata.y[i] = p.y;\\n\\t\\t\\tdata.z[i] = p.z;\\n\\t\\t\\tdata.rot_1[i] = r.x;\\n\\t\\t\\tdata.rot_2[i] = r.y;\\n\\t\\t\\tdata.rot_3[i] = r.z;\\n\\t\\t\\tdata.rot_0[i] = r.w;\\n\\t\\t\\tdata.scale_0[i] = s.x;\\n\\t\\t\\tdata.scale_1[i] = s.y;\\n\\t\\t\\tdata.scale_2[i] = s.z;\\n\\t\\t\\tdata.f_dc_0[i] = (c.x - 0.5) / SH_C0$1;\\n\\t\\t\\tdata.f_dc_1[i] = (c.y - 0.5) / SH_C0$1;\\n\\t\\t\\tdata.f_dc_2[i] = (c.z - 0.5) / SH_C0$1;\\n\\t\\t\\tdata.opacity[i] = c.w <= 0 ? -40 : c.w >= 1 ? 40 : -Math.log(1 / c.w - 1);\\n\\t\\t\\tif (sh) {\\n\\t\\t\\t\\tfor (let c2 = 0; c2 < 45; ++c2) {\\n\\t\\t\\t\\t\\tdata[`f_rest_${c2}`][i] = sh[c2];\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn new GSplatData([{\\n\\t\\t\\tname: \\\"vertex\\\",\\n\\t\\t\\tcount: this.numSplats,\\n\\t\\t\\tproperties: members.map((name) => {\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\tname,\\n\\t\\t\\t\\t\\ttype: \\\"float\\\",\\n\\t\\t\\t\\t\\tbyteSize: 4,\\n\\t\\t\\t\\t\\tstorage: data[name]\\n\\t\\t\\t\\t};\\n\\t\\t\\t})\\n\\t\\t}]);\\n\\t}\\n\\tasync generateCenters() {\\n\\t\\tconst { device, width, height } = this.means_l;\\n\\t\\tconst { scope } = device;\\n\\t\\tconst centersTexture = new Texture(device, {\\n\\t\\t\\tname: \\\"sogCentersTexture\\\",\\n\\t\\t\\twidth,\\n\\t\\t\\theight,\\n\\t\\t\\tformat: PIXELFORMAT_RGBA32U,\\n\\t\\t\\tmipmaps: false\\n\\t\\t});\\n\\t\\tconst shader = ShaderUtils.createShader(device, {\\n\\t\\t\\tuniqueName: \\\"GsplatSogCentersShader\\\",\\n\\t\\t\\tattributes: { vertex_position: SEMANTIC_POSITION },\\n\\t\\t\\tvertexChunk: \\\"fullscreenQuadVS\\\",\\n\\t\\t\\tfragmentGLSL: gsplatSogCenters_default$1,\\n\\t\\t\\tfragmentWGSL: gsplatSogCenters_default,\\n\\t\\t\\tfragmentOutputTypes: [\\\"uvec4\\\"]\\n\\t\\t});\\n\\t\\tconst renderTarget = new RenderTarget({\\n\\t\\t\\tcolorBuffer: centersTexture,\\n\\t\\t\\tdepth: false,\\n\\t\\t\\tmipLevel: 0\\n\\t\\t});\\n\\t\\tresolve(scope, {\\n\\t\\t\\tmeans_l: this.means_l,\\n\\t\\t\\tmeans_u: this.means_u,\\n\\t\\t\\tnumSplats: this.numSplats,\\n\\t\\t\\tmeans_mins: this.meta.means.mins,\\n\\t\\t\\tmeans_maxs: this.meta.means.maxs\\n\\t\\t});\\n\\t\\tconst quad = new QuadRender(shader);\\n\\t\\tconst renderPass = new RenderPassQuad(device, quad);\\n\\t\\trenderPass.name = \\\"SogGenerateCenters\\\";\\n\\t\\trenderPass.init(renderTarget);\\n\\t\\trenderPass.colorOps.clear = false;\\n\\t\\trenderPass.depthStencilOps.clearDepth = false;\\n\\t\\trenderPass.render();\\n\\t\\tquad.destroy();\\n\\t\\trenderTarget.destroy();\\n\\t\\tconst u32 = await readImageDataAsync(centersTexture);\\n\\t\\tif (this.destroyed || device._destroyed) {\\n\\t\\t\\tcentersTexture.destroy();\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst asFloat = new Float32Array(u32.buffer);\\n\\t\\tconst result = new Float32Array(this.numSplats * 3);\\n\\t\\tfor (let i = 0; i < this.numSplats; i++) {\\n\\t\\t\\tconst base = i * 4;\\n\\t\\t\\tresult[i * 3 + 0] = asFloat[base + 0];\\n\\t\\t\\tresult[i * 3 + 1] = asFloat[base + 1];\\n\\t\\t\\tresult[i * 3 + 2] = asFloat[base + 2];\\n\\t\\t}\\n\\t\\tthis._centers = result;\\n\\t\\tcentersTexture.destroy();\\n\\t}\\n\\t_createCodebookTexture() {\\n\\t\\tconst device = this.means_l.device;\\n\\t\\tconst { scales, sh0, shN } = this.meta;\\n\\t\\tconst scalesCb = scales.codebook;\\n\\t\\tconst sh0Cb = sh0.codebook;\\n\\t\\tconst shNCb = shN?.codebook;\\n\\t\\tconst data = new Float32Array(256 * 4);\\n\\t\\tfor (let i = 0; i < 256; i++) data[i * 4] = scalesCb[i];\\n\\t\\tfor (let i = 0; i < 256; i++) data[i * 4 + 1] = sh0Cb[i];\\n\\t\\tif (shNCb) {\\n\\t\\t\\tfor (let i = 0; i < 256; i++) data[i * 4 + 2] = shNCb[i];\\n\\t\\t}\\n\\t\\tconst urlSuffix = this.url ? `_${this.url}` : \\\"\\\";\\n\\t\\tthis.codebookTexture = new Texture(device, {\\n\\t\\t\\tname: `sogCodebook${urlSuffix}`,\\n\\t\\t\\twidth: 256,\\n\\t\\t\\theight: 1,\\n\\t\\t\\tformat: PIXELFORMAT_RGBA32F,\\n\\t\\t\\tmipmaps: false,\\n\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\tlevels: [data]\\n\\t\\t});\\n\\t}\\n\\t_patchCodebooks() {\\n\\t\\t[\\\"scales\\\", \\\"sh0\\\", \\\"shN\\\"].forEach((name) => {\\n\\t\\t\\tconst codebook = this.meta[name]?.codebook;\\n\\t\\t\\tif (codebook?.[0] === null) {\\n\\t\\t\\t\\tcodebook[0] = codebook[1] + (codebook[1] - codebook[255]) / 255;\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n\\tprepareCodebook() {\\n\\t\\tconst device = this.means_l?.device;\\n\\t\\tif (this.destroyed || !device || device._destroyed) return;\\n\\t\\tthis._patchCodebooks();\\n\\t\\tif (this.meta.version === 2) {\\n\\t\\t\\tthis._createCodebookTexture();\\n\\t\\t}\\n\\t}\\n\\tasync prepareGpuData() {\\n\\t\\tconst device = this.means_l?.device;\\n\\t\\tif (this.destroyed || !device || device._destroyed) return;\\n\\t\\tawait this.generateCenters();\\n\\t}\\n}\\n\\nconst mat = new Mat4();\\nconst cameraPosition$1 = new Vec3();\\nconst cameraDirection$1 = new Vec3();\\nclass GSplatInstance {\\n\\tresource;\\n\\torderTexture;\\n\\torderBuffer;\\n\\t_material;\\n\\tmeshInstance;\\n\\toptions = {};\\n\\tsorter = null;\\n\\tlastCameraPosition = new Vec3();\\n\\tlastCameraDirection = new Vec3();\\n\\tresolveSH = null;\\n\\tcameras = [];\\n\\tconstructor(resource, options = {}) {\\n\\t\\tthis.resource = resource;\\n\\t\\tconst device = resource.device;\\n\\t\\tconst dims = resource.streams.textureDimensions;\\n\\t\\tconst numSplats = dims.x * dims.y;\\n\\t\\tif (device.isWebGPU) {\\n\\t\\t\\tthis.orderBuffer = new StorageBuffer(device, numSplats * 4, BUFFERUSAGE_COPY_DST);\\n\\t\\t} else {\\n\\t\\t\\tthis.orderTexture = resource.streams.createTexture(\\n\\t\\t\\t\\t\\\"splatOrder\\\",\\n\\t\\t\\t\\tPIXELFORMAT_R32U,\\n\\t\\t\\t\\tdims\\n\\t\\t\\t);\\n\\t\\t}\\n\\t\\tif (options.material) {\\n\\t\\t\\tthis._material = options.material;\\n\\t\\t\\tthis._material.setDefine(\\\"{GSPLAT_INSTANCE_SIZE}\\\", String(GSplatResourceBase.instanceSize));\\n\\t\\t\\tthis.setMaterialOrderData(this._material);\\n\\t\\t\\tthis._material.setParameter(\\\"alphaClipForward\\\", 1 / 255);\\n\\t\\t} else {\\n\\t\\t\\tthis._material = new ShaderMaterial({\\n\\t\\t\\t\\tuniqueName: \\\"SplatMaterial\\\",\\n\\t\\t\\t\\tvertexGLSL: '#include \\\"gsplatVS\\\"',\\n\\t\\t\\t\\tfragmentGLSL: '#include \\\"gsplatPS\\\"',\\n\\t\\t\\t\\tvertexWGSL: '#include \\\"gsplatVS\\\"',\\n\\t\\t\\t\\tfragmentWGSL: '#include \\\"gsplatPS\\\"',\\n\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t\\tthis.configureMaterial(this._material);\\n\\t\\t\\tthis._material.update();\\n\\t\\t}\\n\\t\\tresource.ensureMesh();\\n\\t\\tthis.meshInstance = new MeshInstance(resource.mesh, this._material);\\n\\t\\tthis.meshInstance.setInstancing(true, true);\\n\\t\\tthis.meshInstance.gsplatInstance = this;\\n\\t\\tthis.meshInstance.instancingCount = 0;\\n\\t\\tif (resource.hasCenters) {\\n\\t\\t\\tconst centers = resource.centers.slice();\\n\\t\\t\\tconst chunks = resource.chunks?.slice();\\n\\t\\t\\tconst orderTarget = this.orderBuffer ?? this.orderTexture;\\n\\t\\t\\tthis.sorter = new GSplatSorter(device, options.scene);\\n\\t\\t\\tthis.sorter.init(orderTarget, numSplats, centers, chunks);\\n\\t\\t}\\n\\t\\tthis.setHighQualitySH(options.highQualitySH ?? false);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.resource?.releaseMesh();\\n\\t\\tthis.orderTexture?.destroy();\\n\\t\\tthis.orderBuffer?.destroy();\\n\\t\\tthis.resolveSH?.destroy();\\n\\t\\tthis.material?.destroy();\\n\\t\\tthis.meshInstance?.destroy();\\n\\t\\tthis.sorter?.destroy();\\n\\t}\\n\\tsetMaterialOrderData(material) {\\n\\t\\tif (this.orderBuffer) {\\n\\t\\t\\tmaterial.setParameter(\\\"splatOrder\\\", this.orderBuffer);\\n\\t\\t} else {\\n\\t\\t\\tmaterial.setParameter(\\\"splatOrder\\\", this.orderTexture);\\n\\t\\t\\tmaterial.setParameter(\\\"splatTextureSize\\\", this.orderTexture.width);\\n\\t\\t}\\n\\t}\\n\\tset material(value) {\\n\\t\\tif (this._material !== value) {\\n\\t\\t\\tthis._material = value;\\n\\t\\t\\tthis._material.setDefine(\\\"{GSPLAT_INSTANCE_SIZE}\\\", String(GSplatResourceBase.instanceSize));\\n\\t\\t\\tthis.setMaterialOrderData(this._material);\\n\\t\\t\\tthis._material.setParameter(\\\"alphaClipForward\\\", 1 / 255);\\n\\t\\t\\tif (this.meshInstance) {\\n\\t\\t\\t\\tthis.meshInstance.material = value;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget material() {\\n\\t\\treturn this._material;\\n\\t}\\n\\tconfigureMaterial(material, options = {}) {\\n\\t\\tthis.resource.configureMaterial(material, null, this.resource.format.getInputDeclarations());\\n\\t\\tmaterial.setDefine(\\\"{GSPLAT_INSTANCE_SIZE}\\\", GSplatResourceBase.instanceSize);\\n\\t\\tmaterial.setParameter(\\\"numSplats\\\", 0);\\n\\t\\tthis.setMaterialOrderData(material);\\n\\t\\tmaterial.setParameter(\\\"alphaClip\\\", 0.3);\\n\\t\\tmaterial.setParameter(\\\"alphaClipForward\\\", 1 / 255);\\n\\t\\tmaterial.setParameter(\\\"minPixelSize\\\", 2);\\n\\t\\tmaterial.setDefine(`DITHER_${options.dither ? \\\"BLUENOISE\\\" : \\\"NONE\\\"}`, \\\"\\\");\\n\\t\\tmaterial.cull = CULLFACE_NONE;\\n\\t\\tmaterial.blendType = options.dither ? BLEND_NONE : BLEND_PREMULTIPLIED;\\n\\t\\tmaterial.depthWrite = !!options.dither;\\n\\t}\\n\\tsort(cameraNode) {\\n\\t\\tif (this.sorter) {\\n\\t\\t\\tconst cameraMat = cameraNode.getWorldTransform();\\n\\t\\t\\tcameraMat.getTranslation(cameraPosition$1);\\n\\t\\t\\tcameraMat.getZ(cameraDirection$1);\\n\\t\\t\\tconst modelMat = this.meshInstance.node.getWorldTransform();\\n\\t\\t\\tconst invModelMat = mat.invert(modelMat);\\n\\t\\t\\tinvModelMat.transformPoint(cameraPosition$1, cameraPosition$1);\\n\\t\\t\\tinvModelMat.transformVector(cameraDirection$1, cameraDirection$1);\\n\\t\\t\\tif (!cameraPosition$1.equalsApprox(this.lastCameraPosition) || !cameraDirection$1.equalsApprox(this.lastCameraDirection)) {\\n\\t\\t\\t\\tthis.lastCameraPosition.copy(cameraPosition$1);\\n\\t\\t\\t\\tthis.lastCameraDirection.copy(cameraDirection$1);\\n\\t\\t\\t\\tthis.sorter.setCamera(cameraPosition$1, cameraDirection$1);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tupdate() {\\n\\t\\tconst count = this.sorter?.applyPendingSorted() ?? -1;\\n\\t\\tif (count >= 0) {\\n\\t\\t\\tthis.meshInstance.instancingCount = Math.ceil(count / GSplatResourceBase.instanceSize);\\n\\t\\t\\tthis.material.setParameter(\\\"numSplats\\\", count);\\n\\t\\t}\\n\\t\\tif (this.cameras.length > 0) {\\n\\t\\t\\tconst camera = this.cameras[0];\\n\\t\\t\\tthis.sort(camera._node);\\n\\t\\t\\tthis.resolveSH?.render(camera._node, this.meshInstance.node.getWorldTransform());\\n\\t\\t\\tthis.cameras.length = 0;\\n\\t\\t}\\n\\t}\\n\\tsetHighQualitySH(value) {\\n\\t\\tconst { resource } = this;\\n\\t\\tconst { gsplatData } = resource;\\n\\t\\tif (gsplatData instanceof GSplatSogData && gsplatData.shBands > 0 && value === !!this.resolveSH) {\\n\\t\\t\\tif (this.resolveSH) {\\n\\t\\t\\t\\tthis.resolveSH.destroy();\\n\\t\\t\\t\\tthis.resolveSH = null;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.resolveSH = new GSplatResolveSH(resource.device, this);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\n\\nconst getSHData = (gsplatData, numCoeffs) => {\\n\\tconst result = [];\\n\\tfor (let i = 0; i < numCoeffs; ++i) {\\n\\t\\tresult.push(gsplatData.getProp(`f_rest_${i}`));\\n\\t}\\n\\treturn result;\\n};\\nclass GSplatResource extends GSplatResourceBase {\\n\\tshBands;\\n\\tconstructor(device, gsplatData, options = {}) {\\n\\t\\tsuper(device, gsplatData, options);\\n\\t\\tconst numSplats = gsplatData.numSplats;\\n\\t\\tthis.shBands = gsplatData.shBands;\\n\\t\\tconst streams = [\\n\\t\\t\\t{ name: \\\"splatColor\\\", format: PIXELFORMAT_RGBA16F },\\n\\t\\t\\t{ name: \\\"transformA\\\", format: PIXELFORMAT_RGBA32U },\\n\\t\\t\\t{ name: \\\"transformB\\\", format: PIXELFORMAT_RGBA16F }\\n\\t\\t];\\n\\t\\tif (this.shBands > 0) {\\n\\t\\t\\tstreams.push({ name: \\\"splatSH_1to3\\\", format: PIXELFORMAT_RGBA32U });\\n\\t\\t\\tif (this.shBands > 1) {\\n\\t\\t\\t\\tstreams.push({ name: \\\"splatSH_4to7\\\", format: PIXELFORMAT_RGBA32U });\\n\\t\\t\\t\\tif (this.shBands > 2) {\\n\\t\\t\\t\\t\\tstreams.push({ name: \\\"splatSH_8to11\\\", format: PIXELFORMAT_RGBA32U });\\n\\t\\t\\t\\t\\tstreams.push({ name: \\\"splatSH_12to15\\\", format: PIXELFORMAT_RGBA32U });\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tstreams.push({ name: \\\"splatSH_8to11\\\", format: PIXELFORMAT_R32U });\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._format = new GSplatFormat(device, streams, {\\n\\t\\t\\treadGLSL: '#include \\\"gsplatUncompressedVS\\\"',\\n\\t\\t\\treadWGSL: '#include \\\"gsplatUncompressedVS\\\"'\\n\\t\\t});\\n\\t\\tthis.streams.init(this.format, numSplats);\\n\\t\\tthis.updateColorData(gsplatData);\\n\\t\\tthis.updateTransformData(gsplatData);\\n\\t\\tif (this.shBands > 0) {\\n\\t\\t\\tthis.updateSHData(gsplatData);\\n\\t\\t}\\n\\t}\\n\\tconfigureMaterialDefines(defines) {\\n\\t\\tdefines.set(\\\"SH_BANDS\\\", this.shBands);\\n\\t}\\n\\tupdateColorData(gsplatData) {\\n\\t\\tconst texture = this.streams.getTexture(\\\"splatColor\\\");\\n\\t\\tif (!texture) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst float2Half = FloatPacking.float2Half;\\n\\t\\tconst data = texture.lock();\\n\\t\\tconst cr = gsplatData.getProp(\\\"f_dc_0\\\");\\n\\t\\tconst cg = gsplatData.getProp(\\\"f_dc_1\\\");\\n\\t\\tconst cb = gsplatData.getProp(\\\"f_dc_2\\\");\\n\\t\\tconst ca = gsplatData.getProp(\\\"opacity\\\");\\n\\t\\tconst SH_C0 = 0.28209479177387814;\\n\\t\\tfor (let i = 0; i < this.numSplats; ++i) {\\n\\t\\t\\tconst r = cr[i] * SH_C0 + 0.5;\\n\\t\\t\\tconst g = cg[i] * SH_C0 + 0.5;\\n\\t\\t\\tconst b = cb[i] * SH_C0 + 0.5;\\n\\t\\t\\tconst a = 1 / (1 + Math.exp(-ca[i]));\\n\\t\\t\\tdata[i * 4 + 0] = float2Half(r);\\n\\t\\t\\tdata[i * 4 + 1] = float2Half(g);\\n\\t\\t\\tdata[i * 4 + 2] = float2Half(b);\\n\\t\\t\\tdata[i * 4 + 3] = float2Half(a);\\n\\t\\t}\\n\\t\\ttexture.unlock();\\n\\t}\\n\\tupdateTransformData(gsplatData) {\\n\\t\\tconst float2Half = FloatPacking.float2Half;\\n\\t\\tconst transformA = this.streams.getTexture(\\\"transformA\\\");\\n\\t\\tconst transformB = this.streams.getTexture(\\\"transformB\\\");\\n\\t\\tif (!transformA) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst dataA = transformA.lock();\\n\\t\\tconst dataAFloat32 = new Float32Array(dataA.buffer);\\n\\t\\tconst dataB = transformB.lock();\\n\\t\\tconst p = new Vec3();\\n\\t\\tconst r = new Quat();\\n\\t\\tconst s = new Vec3();\\n\\t\\tconst iter = gsplatData.createIter(p, r, s);\\n\\t\\tfor (let i = 0; i < this.numSplats; i++) {\\n\\t\\t\\titer.read(i);\\n\\t\\t\\tr.normalize();\\n\\t\\t\\tif (r.w < 0) {\\n\\t\\t\\t\\tr.mulScalar(-1);\\n\\t\\t\\t}\\n\\t\\t\\tdataAFloat32[i * 4 + 0] = p.x;\\n\\t\\t\\tdataAFloat32[i * 4 + 1] = p.y;\\n\\t\\t\\tdataAFloat32[i * 4 + 2] = p.z;\\n\\t\\t\\tdataA[i * 4 + 3] = float2Half(r.x) | float2Half(r.y) << 16;\\n\\t\\t\\tdataB[i * 4 + 0] = float2Half(s.x);\\n\\t\\t\\tdataB[i * 4 + 1] = float2Half(s.y);\\n\\t\\t\\tdataB[i * 4 + 2] = float2Half(s.z);\\n\\t\\t\\tdataB[i * 4 + 3] = float2Half(r.z);\\n\\t\\t}\\n\\t\\ttransformA.unlock();\\n\\t\\ttransformB.unlock();\\n\\t}\\n\\tupdateSHData(gsplatData) {\\n\\t\\tconst sh1to3Texture = this.streams.getTexture(\\\"splatSH_1to3\\\");\\n\\t\\tconst sh4to7Texture = this.streams.getTexture(\\\"splatSH_4to7\\\");\\n\\t\\tconst sh8to11Texture = this.streams.getTexture(\\\"splatSH_8to11\\\");\\n\\t\\tconst sh12to15Texture = this.streams.getTexture(\\\"splatSH_12to15\\\");\\n\\t\\tconst sh1to3Data = sh1to3Texture.lock();\\n\\t\\tconst sh4to7Data = sh4to7Texture?.lock();\\n\\t\\tconst sh8to11Data = sh8to11Texture?.lock();\\n\\t\\tconst sh12to15Data = sh12to15Texture?.lock();\\n\\t\\tconst numCoeffs = {\\n\\t\\t\\t1: 3,\\n\\t\\t\\t2: 8,\\n\\t\\t\\t3: 15\\n\\t\\t}[this.shBands];\\n\\t\\tconst src = getSHData(gsplatData, numCoeffs * 3);\\n\\t\\tconst t11 = (1 << 11) - 1;\\n\\t\\tconst t10 = (1 << 10) - 1;\\n\\t\\tconst float32 = new Float32Array(1);\\n\\t\\tconst uint32 = new Uint32Array(float32.buffer);\\n\\t\\tconst c = new Array(numCoeffs * 3).fill(0);\\n\\t\\tfor (let i = 0; i < gsplatData.numSplats; ++i) {\\n\\t\\t\\tfor (let j = 0; j < numCoeffs; ++j) {\\n\\t\\t\\t\\tc[j * 3] = src[j][i];\\n\\t\\t\\t\\tc[j * 3 + 1] = src[j + numCoeffs][i];\\n\\t\\t\\t\\tc[j * 3 + 2] = src[j + numCoeffs * 2][i];\\n\\t\\t\\t}\\n\\t\\t\\tlet max = c[0];\\n\\t\\t\\tfor (let j = 1; j < numCoeffs * 3; ++j) {\\n\\t\\t\\t\\tmax = Math.max(max, Math.abs(c[j]));\\n\\t\\t\\t}\\n\\t\\t\\tif (max === 0) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tfor (let j = 0; j < numCoeffs; ++j) {\\n\\t\\t\\t\\tc[j * 3 + 0] = Math.max(0, Math.min(t11, Math.floor((c[j * 3 + 0] / max * 0.5 + 0.5) * t11 + 0.5)));\\n\\t\\t\\t\\tc[j * 3 + 1] = Math.max(0, Math.min(t10, Math.floor((c[j * 3 + 1] / max * 0.5 + 0.5) * t10 + 0.5)));\\n\\t\\t\\t\\tc[j * 3 + 2] = Math.max(0, Math.min(t11, Math.floor((c[j * 3 + 2] / max * 0.5 + 0.5) * t11 + 0.5)));\\n\\t\\t\\t}\\n\\t\\t\\tfloat32[0] = max;\\n\\t\\t\\tsh1to3Data[i * 4 + 0] = uint32[0];\\n\\t\\t\\tsh1to3Data[i * 4 + 1] = c[0] << 21 | c[1] << 11 | c[2];\\n\\t\\t\\tsh1to3Data[i * 4 + 2] = c[3] << 21 | c[4] << 11 | c[5];\\n\\t\\t\\tsh1to3Data[i * 4 + 3] = c[6] << 21 | c[7] << 11 | c[8];\\n\\t\\t\\tif (this.shBands > 1) {\\n\\t\\t\\t\\tsh4to7Data[i * 4 + 0] = c[9] << 21 | c[10] << 11 | c[11];\\n\\t\\t\\t\\tsh4to7Data[i * 4 + 1] = c[12] << 21 | c[13] << 11 | c[14];\\n\\t\\t\\t\\tsh4to7Data[i * 4 + 2] = c[15] << 21 | c[16] << 11 | c[17];\\n\\t\\t\\t\\tsh4to7Data[i * 4 + 3] = c[18] << 21 | c[19] << 11 | c[20];\\n\\t\\t\\t\\tif (this.shBands > 2) {\\n\\t\\t\\t\\t\\tsh8to11Data[i * 4 + 0] = c[21] << 21 | c[22] << 11 | c[23];\\n\\t\\t\\t\\t\\tsh8to11Data[i * 4 + 1] = c[24] << 21 | c[25] << 11 | c[26];\\n\\t\\t\\t\\t\\tsh8to11Data[i * 4 + 2] = c[27] << 21 | c[28] << 11 | c[29];\\n\\t\\t\\t\\t\\tsh8to11Data[i * 4 + 3] = c[30] << 21 | c[31] << 11 | c[32];\\n\\t\\t\\t\\t\\tsh12to15Data[i * 4 + 0] = c[33] << 21 | c[34] << 11 | c[35];\\n\\t\\t\\t\\t\\tsh12to15Data[i * 4 + 1] = c[36] << 21 | c[37] << 11 | c[38];\\n\\t\\t\\t\\t\\tsh12to15Data[i * 4 + 2] = c[39] << 21 | c[40] << 11 | c[41];\\n\\t\\t\\t\\t\\tsh12to15Data[i * 4 + 3] = c[42] << 21 | c[43] << 11 | c[44];\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tsh8to11Data[i] = c[21] << 21 | c[22] << 11 | c[23];\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsh1to3Texture.unlock();\\n\\t\\tsh4to7Texture?.unlock();\\n\\t\\tsh8to11Texture?.unlock();\\n\\t\\tsh12to15Texture?.unlock();\\n\\t}\\n}\\n\\nclass GSplatSogResource extends GSplatResourceBase {\\n\\tconstructor(device, gsplatData, options = {}) {\\n\\t\\tsuper(device, gsplatData, options);\\n\\t\\tconst { meta, means_l } = gsplatData;\\n\\t\\tconst isV2 = meta.version === 2;\\n\\t\\tconst hasSH = gsplatData.shBands > 0;\\n\\t\\tif (means_l) {\\n\\t\\t\\tthis.streams.textureDimensions.set(means_l.width, means_l.height);\\n\\t\\t}\\n\\t\\tthis.streams.textures.set(\\\"means_l\\\", gsplatData.means_l);\\n\\t\\tthis.streams.textures.set(\\\"means_u\\\", gsplatData.means_u);\\n\\t\\tthis.streams.textures.set(\\\"quats\\\", gsplatData.quats);\\n\\t\\tthis.streams.textures.set(\\\"scales\\\", gsplatData.scales);\\n\\t\\tthis.streams.textures.set(\\\"sh0\\\", gsplatData.sh0);\\n\\t\\tif (hasSH) {\\n\\t\\t\\tthis.streams.textures.set(\\\"sh_labels\\\", gsplatData.sh_labels);\\n\\t\\t\\tthis.streams.textures.set(\\\"sh_centroids\\\", gsplatData.sh_centroids);\\n\\t\\t}\\n\\t\\tif (isV2) {\\n\\t\\t\\tthis.streams.textures.set(\\\"sogCodebook\\\", gsplatData.codebookTexture);\\n\\t\\t}\\n\\t\\tconst streams = [\\n\\t\\t\\t{ name: \\\"means_l\\\", format: PIXELFORMAT_RGBA8 },\\n\\t\\t\\t{ name: \\\"means_u\\\", format: PIXELFORMAT_RGBA8 },\\n\\t\\t\\t{ name: \\\"quats\\\", format: PIXELFORMAT_RGBA8 },\\n\\t\\t\\t{ name: \\\"scales\\\", format: PIXELFORMAT_RGBA8 },\\n\\t\\t\\t{ name: \\\"sh0\\\", format: PIXELFORMAT_RGBA8 }\\n\\t\\t];\\n\\t\\tif (hasSH) {\\n\\t\\t\\tstreams.push({ name: \\\"sh_labels\\\", format: PIXELFORMAT_RGBA8 });\\n\\t\\t\\tstreams.push({ name: \\\"sh_centroids\\\", format: PIXELFORMAT_RGBA8 });\\n\\t\\t}\\n\\t\\tif (isV2) {\\n\\t\\t\\tstreams.push({ name: \\\"sogCodebook\\\", format: PIXELFORMAT_RGBA32F });\\n\\t\\t}\\n\\t\\tthis._format = new GSplatFormat(device, streams, {\\n\\t\\t\\treadGLSL: '#include \\\"gsplatSogVS\\\"',\\n\\t\\t\\treadWGSL: '#include \\\"gsplatSogVS\\\"'\\n\\t\\t});\\n\\t\\tthis._populateParameters();\\n\\t}\\n\\treleaseTextureSources() {\\n\\t\\tconst d = this.gsplatData;\\n\\t\\td.means_l?.setReleaseSourceAfterUpload();\\n\\t\\td.means_u?.setReleaseSourceAfterUpload();\\n\\t\\td.quats?.setReleaseSourceAfterUpload();\\n\\t\\td.scales?.setReleaseSourceAfterUpload();\\n\\t\\td.sh0?.setReleaseSourceAfterUpload();\\n\\t\\td.sh_centroids?.setReleaseSourceAfterUpload();\\n\\t\\td.sh_labels?.setReleaseSourceAfterUpload();\\n\\t}\\n\\t_actualDestroy() {\\n\\t\\tthis.streams.textures.delete(\\\"means_l\\\");\\n\\t\\tthis.streams.textures.delete(\\\"means_u\\\");\\n\\t\\tthis.streams.textures.delete(\\\"quats\\\");\\n\\t\\tthis.streams.textures.delete(\\\"scales\\\");\\n\\t\\tthis.streams.textures.delete(\\\"sh0\\\");\\n\\t\\tthis.streams.textures.delete(\\\"sh_labels\\\");\\n\\t\\tthis.streams.textures.delete(\\\"sh_centroids\\\");\\n\\t\\tthis.streams.textures.delete(\\\"sogCodebook\\\");\\n\\t\\tthis.gsplatData.destroy();\\n\\t\\tsuper._actualDestroy();\\n\\t}\\n\\t_populateParameters() {\\n\\t\\tconst { meta } = this.gsplatData;\\n\\t\\tif (meta.means) {\\n\\t\\t\\tthis.parameters.set(\\\"means_mins\\\", meta.means.mins);\\n\\t\\t\\tthis.parameters.set(\\\"means_maxs\\\", meta.means.maxs);\\n\\t\\t}\\n\\t\\tif (meta.version !== 2) {\\n\\t\\t\\tif (meta.scales) {\\n\\t\\t\\t\\tthis.parameters.set(\\\"scales_mins\\\", meta.scales.mins);\\n\\t\\t\\t\\tthis.parameters.set(\\\"scales_maxs\\\", meta.scales.maxs);\\n\\t\\t\\t}\\n\\t\\t\\tif (meta.sh0) {\\n\\t\\t\\t\\tthis.parameters.set(\\\"sh0_mins\\\", meta.sh0.mins);\\n\\t\\t\\t\\tthis.parameters.set(\\\"sh0_maxs\\\", meta.sh0.maxs);\\n\\t\\t\\t}\\n\\t\\t\\tif (meta.shN) {\\n\\t\\t\\t\\tthis.parameters.set(\\\"shN_mins\\\", meta.shN.mins);\\n\\t\\t\\t\\tthis.parameters.set(\\\"shN_maxs\\\", meta.shN.maxs);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tconfigureMaterialDefines(defines) {\\n\\t\\tconst gsplatData = this.gsplatData;\\n\\t\\tdefines.set(\\\"SH_BANDS\\\", gsplatData.shBands);\\n\\t\\tif (gsplatData.meta.version === 2) {\\n\\t\\t\\tdefines.set(\\\"SOG_V2\\\", \\\"\\\");\\n\\t\\t}\\n\\t}\\n}\\n\\nconst FILLMODE_FILL_WINDOW = \\\"FILL_WINDOW\\\";\\nconst FILLMODE_KEEP_ASPECT = \\\"KEEP_ASPECT\\\";\\nconst RESOLUTION_AUTO = \\\"AUTO\\\";\\nconst RESOLUTION_FIXED = \\\"FIXED\\\";\\n\\nlet currentApplication;\\nfunction getApplication() {\\n\\treturn currentApplication;\\n}\\nfunction setApplication(app) {\\n\\tcurrentApplication = app;\\n}\\n\\nclass FrameGraph {\\n\\trenderPasses = [];\\n\\trenderTargetMap = /* @__PURE__ */ new Map();\\n\\tmultiview = null;\\n\\tbeginMultiView(device) {\\n\\t\\tthis.multiview = new FramePassMultiView(device);\\n\\t}\\n\\tendMultiView() {\\n\\t\\tconst wrap = this.multiview;\\n\\t\\tthis.multiview = null;\\n\\t\\tif (wrap?.children.length) {\\n\\t\\t\\tthis.renderPasses.push(wrap);\\n\\t\\t}\\n\\t}\\n\\taddRenderPass(renderPass) {\\n\\t\\trenderPass.frameUpdate();\\n\\t\\tconst beforePasses = renderPass.beforePasses;\\n\\t\\tfor (let i = 0; i < beforePasses.length; i++) {\\n\\t\\t\\tconst pass = beforePasses[i];\\n\\t\\t\\tif (pass.enabled) {\\n\\t\\t\\t\\tthis.addRenderPass(pass);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (renderPass.enabled) {\\n\\t\\t\\tif (this.multiview) {\\n\\t\\t\\t\\tthis.multiview.addChild(renderPass);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.renderPasses.push(renderPass);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst afterPasses = renderPass.afterPasses;\\n\\t\\tfor (let i = 0; i < afterPasses.length; i++) {\\n\\t\\t\\tconst pass = afterPasses[i];\\n\\t\\t\\tif (pass.enabled) {\\n\\t\\t\\t\\tthis.addRenderPass(pass);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\treset() {\\n\\t\\tthis.renderPasses.length = 0;\\n\\t}\\n\\tcompile() {\\n\\t\\tthis._compilePasses(this.renderPasses);\\n\\t\\tfor (let i = 0; i < this.renderPasses.length; i++) {\\n\\t\\t\\tconst pass = this.renderPasses[i];\\n\\t\\t\\tif (pass instanceof FramePassMultiView) {\\n\\t\\t\\t\\tthis._compilePasses(pass.children);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_compilePasses(passes) {\\n\\t\\tconst renderTargetMap = this.renderTargetMap;\\n\\t\\tfor (let i = 0; i < passes.length; i++) {\\n\\t\\t\\tconst renderPass = passes[i];\\n\\t\\t\\trenderPass._skipStart = false;\\n\\t\\t\\trenderPass._skipEnd = false;\\n\\t\\t\\tconst renderTarget = renderPass.renderTarget;\\n\\t\\t\\tif (renderTarget !== void 0) {\\n\\t\\t\\t\\tconst prevPass = renderTargetMap.get(renderTarget);\\n\\t\\t\\t\\tif (prevPass) {\\n\\t\\t\\t\\t\\tconst count = renderPass.colorArrayOps.length;\\n\\t\\t\\t\\t\\tfor (let j = 0; j < count; j++) {\\n\\t\\t\\t\\t\\t\\tconst colorOps = renderPass.colorArrayOps[j];\\n\\t\\t\\t\\t\\t\\tif (!colorOps.clear) {\\n\\t\\t\\t\\t\\t\\t\\tprevPass.colorArrayOps[j].store = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (!renderPass.depthStencilOps.clearDepth) {\\n\\t\\t\\t\\t\\t\\tprevPass.depthStencilOps.storeDepth = true;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (!renderPass.depthStencilOps.clearStencil) {\\n\\t\\t\\t\\t\\t\\tprevPass.depthStencilOps.storeStencil = true;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\trenderTargetMap.set(renderTarget, renderPass);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < passes.length - 1; i++) {\\n\\t\\t\\tconst firstPass = passes[i];\\n\\t\\t\\tconst firstRT = firstPass.renderTarget;\\n\\t\\t\\tconst secondPass = passes[i + 1];\\n\\t\\t\\tconst secondRT = secondPass.renderTarget;\\n\\t\\t\\tif (firstRT !== secondRT || firstRT === void 0) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tif (secondPass.depthStencilOps.clearDepth || secondPass.depthStencilOps.clearStencil || secondPass.colorArrayOps.some((colorOps) => colorOps.clear)) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tif (firstPass.afterPasses.length > 0) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tif (secondPass.beforePasses.length > 0) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tfirstPass._skipEnd = true;\\n\\t\\t\\tsecondPass._skipStart = true;\\n\\t\\t}\\n\\t\\tlet lastCubeTexture = null;\\n\\t\\tlet lastCubeRenderPass = null;\\n\\t\\tfor (let i = 0; i < passes.length; i++) {\\n\\t\\t\\tconst renderPass = passes[i];\\n\\t\\t\\tconst renderTarget = renderPass.renderTarget;\\n\\t\\t\\tconst thisTexture = renderTarget?.colorBuffer;\\n\\t\\t\\tif (thisTexture?.cubemap) {\\n\\t\\t\\t\\tif (lastCubeTexture === thisTexture) {\\n\\t\\t\\t\\t\\tconst count = lastCubeRenderPass.colorArrayOps.length;\\n\\t\\t\\t\\t\\tfor (let j = 0; j < count; j++) {\\n\\t\\t\\t\\t\\t\\tlastCubeRenderPass.colorArrayOps[j].mipmaps = false;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlastCubeTexture = renderTarget.colorBuffer;\\n\\t\\t\\t\\tlastCubeRenderPass = renderPass;\\n\\t\\t\\t} else if (renderPass.requiresCubemaps) {\\n\\t\\t\\t\\tlastCubeTexture = null;\\n\\t\\t\\t\\tlastCubeRenderPass = null;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\trenderTargetMap.clear();\\n\\t}\\n\\trender(device) {\\n\\t\\tthis.compile();\\n\\t\\tconst renderPasses = this.renderPasses;\\n\\t\\tfor (let i = 0; i < renderPasses.length; i++) {\\n\\t\\t\\trenderPasses[i].render();\\n\\t\\t}\\n\\t}\\n}\\n\\nclass AreaLightCacheEntry {\\n\\tconstructor(texture0, texture1) {\\n\\t\\tthis.texture0 = texture0;\\n\\t\\tthis.texture1 = texture1;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.texture0?.destroy();\\n\\t\\tthis.texture1?.destroy();\\n\\t}\\n}\\nconst deviceCache = new DeviceCache();\\nclass AreaLightLuts {\\n\\tstatic createTexture(device, format, size, postfix = \\\"\\\") {\\n\\t\\tconst tex = new Texture(device, {\\n\\t\\t\\tname: `AreaLightLUT${postfix}`,\\n\\t\\t\\twidth: size,\\n\\t\\t\\theight: size,\\n\\t\\t\\tformat,\\n\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\ttype: TEXTURETYPE_DEFAULT,\\n\\t\\t\\tmagFilter: FILTER_LINEAR,\\n\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\tanisotropy: 1,\\n\\t\\t\\tmipmaps: false\\n\\t\\t});\\n\\t\\treturn tex;\\n\\t}\\n\\tstatic applyTextures(device, texture1, texture2) {\\n\\t\\tdeviceCache.remove(device);\\n\\t\\tdeviceCache.get(device, () => {\\n\\t\\t\\treturn new AreaLightCacheEntry(texture1, texture1 === texture2 ? null : texture2);\\n\\t\\t});\\n\\t\\tdevice.scope.resolve(\\\"areaLightsLutTex1\\\").setValue(texture1);\\n\\t\\tdevice.scope.resolve(\\\"areaLightsLutTex2\\\").setValue(texture2);\\n\\t}\\n\\t// placeholder LUT textures for area light\\n\\tstatic createPlaceholder(device) {\\n\\t\\tconst texture = AreaLightLuts.createTexture(device, PIXELFORMAT_RGBA16F, 2, \\\"placeholder\\\");\\n\\t\\tconst pixels = texture.lock();\\n\\t\\tpixels.fill(0);\\n\\t\\ttexture.unlock();\\n\\t\\tAreaLightLuts.applyTextures(device, texture, texture);\\n\\t}\\n\\t// creates LUT texture used by area lights\\n\\tstatic set(device, ltcMat1, ltcMat2) {\\n\\t\\tfunction buildTexture(device2, data, format) {\\n\\t\\t\\tconst texture = AreaLightLuts.createTexture(device2, format, 64);\\n\\t\\t\\ttexture.lock().set(data);\\n\\t\\t\\ttexture.unlock();\\n\\t\\t\\treturn texture;\\n\\t\\t}\\n\\t\\tfunction convertToHalfFloat(data) {\\n\\t\\t\\tconst count = data.length;\\n\\t\\t\\tconst ret = new Uint16Array(count);\\n\\t\\t\\tconst float2Half = FloatPacking.float2Half;\\n\\t\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\t\\tret[i] = float2Half(data[i]);\\n\\t\\t\\t}\\n\\t\\t\\treturn ret;\\n\\t\\t}\\n\\t\\tconst srcData1 = ltcMat1;\\n\\t\\tconst srcData2 = ltcMat2;\\n\\t\\tconst data1 = convertToHalfFloat(srcData1);\\n\\t\\tconst data2 = convertToHalfFloat(srcData2);\\n\\t\\tconst tex1 = buildTexture(device, data1, PIXELFORMAT_RGBA16F);\\n\\t\\tconst tex2 = buildTexture(device, data2, PIXELFORMAT_RGBA16F);\\n\\t\\tAreaLightLuts.applyTextures(device, tex1, tex2);\\n\\t}\\n}\\n\\nconst DEFAULT_LOCALE = \\\"en-US\\\";\\nconst DEFAULT_LOCALE_FALLBACKS = {\\n\\t\\\"en\\\": \\\"en-US\\\",\\n\\t\\\"es\\\": \\\"en-ES\\\",\\n\\t\\\"zh\\\": \\\"zh-CN\\\",\\n\\t\\\"zh-HK\\\": \\\"zh-TW\\\",\\n\\t\\\"zh-TW\\\": \\\"zh-HK\\\",\\n\\t\\\"zh-MO\\\": \\\"zh-HK\\\",\\n\\t\\\"fr\\\": \\\"fr-FR\\\",\\n\\t\\\"de\\\": \\\"de-DE\\\",\\n\\t\\\"it\\\": \\\"it-IT\\\",\\n\\t\\\"ru\\\": \\\"ru-RU\\\",\\n\\t\\\"ja\\\": \\\"ja-JP\\\"\\n};\\n\\nconst PLURALS = {};\\nfunction definePluralFn(locales, fn) {\\n\\tfor (let i = 0, len = locales.length; i < len; i++) {\\n\\t\\tPLURALS[locales[i]] = fn;\\n\\t}\\n}\\nfunction getLang(locale) {\\n\\tconst idx = locale.indexOf(\\\"-\\\");\\n\\tif (idx !== -1) {\\n\\t\\treturn locale.substring(0, idx);\\n\\t}\\n\\treturn locale;\\n}\\nfunction replaceLang(locale, desiredLang) {\\n\\tconst idx = locale.indexOf(\\\"-\\\");\\n\\tif (idx !== -1) {\\n\\t\\treturn desiredLang + locale.substring(idx);\\n\\t}\\n\\treturn desiredLang;\\n}\\nfunction findAvailableLocale(desiredLocale, availableLocales) {\\n\\tif (availableLocales[desiredLocale]) {\\n\\t\\treturn desiredLocale;\\n\\t}\\n\\tlet fallback = DEFAULT_LOCALE_FALLBACKS[desiredLocale];\\n\\tif (fallback && availableLocales[fallback]) {\\n\\t\\treturn fallback;\\n\\t}\\n\\tconst lang = getLang(desiredLocale);\\n\\tfallback = DEFAULT_LOCALE_FALLBACKS[lang];\\n\\tif (availableLocales[fallback]) {\\n\\t\\treturn fallback;\\n\\t}\\n\\tif (availableLocales[lang]) {\\n\\t\\treturn lang;\\n\\t}\\n\\treturn DEFAULT_LOCALE;\\n}\\ndefinePluralFn([\\n\\t\\\"ja\\\",\\n\\t\\\"ko\\\",\\n\\t\\\"th\\\",\\n\\t\\\"vi\\\",\\n\\t\\\"zh\\\",\\n\\t\\\"id\\\"\\n], (n) => {\\n\\treturn 0;\\n});\\ndefinePluralFn([\\n\\t\\\"fa\\\",\\n\\t\\\"hi\\\"\\n], (n) => {\\n\\tif (n >= 0 && n <= 1) {\\n\\t\\treturn 0;\\n\\t}\\n\\treturn 1;\\n});\\ndefinePluralFn([\\n\\t\\\"fr\\\",\\n\\t\\\"pt\\\"\\n], (n) => {\\n\\tif (n >= 0 && n < 2) {\\n\\t\\treturn 0;\\n\\t}\\n\\treturn 1;\\n});\\ndefinePluralFn([\\n\\t\\\"da\\\"\\n], (n) => {\\n\\tif (n === 1 || !Number.isInteger(n) && n >= 0 && n <= 1) {\\n\\t\\treturn 0;\\n\\t}\\n\\treturn 1;\\n});\\ndefinePluralFn([\\n\\t\\\"de\\\",\\n\\t\\\"en\\\",\\n\\t\\\"it\\\",\\n\\t\\\"el\\\",\\n\\t\\\"es\\\",\\n\\t\\\"tr\\\",\\n\\t\\\"fi\\\",\\n\\t\\\"sv\\\",\\n\\t\\\"nb\\\",\\n\\t\\\"no\\\",\\n\\t\\\"ur\\\"\\n], (n) => {\\n\\tif (n === 1) {\\n\\t\\treturn 0;\\n\\t}\\n\\treturn 1;\\n});\\ndefinePluralFn([\\n\\t\\\"ru\\\",\\n\\t\\\"uk\\\"\\n], (n) => {\\n\\tif (Number.isInteger(n)) {\\n\\t\\tconst mod10 = n % 10;\\n\\t\\tconst mod100 = n % 100;\\n\\t\\tif (mod10 === 1 && mod100 !== 11) {\\n\\t\\t\\treturn 0;\\n\\t\\t} else if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) {\\n\\t\\t\\treturn 1;\\n\\t\\t} else if (mod10 === 0 || mod10 >= 5 && mod10 <= 9 || mod100 >= 11 && mod100 <= 14) {\\n\\t\\t\\treturn 2;\\n\\t\\t}\\n\\t}\\n\\treturn 3;\\n});\\ndefinePluralFn([\\n\\t\\\"pl\\\"\\n], (n) => {\\n\\tif (Number.isInteger(n)) {\\n\\t\\tif (n === 1) {\\n\\t\\t\\treturn 0;\\n\\t\\t}\\n\\t\\tconst mod10 = n % 10;\\n\\t\\tconst mod100 = n % 100;\\n\\t\\tif (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) {\\n\\t\\t\\treturn 1;\\n\\t\\t} else if (mod10 >= 0 && mod10 <= 1 || mod10 >= 5 && mod10 <= 9 || mod100 >= 12 && mod100 <= 14) {\\n\\t\\t\\treturn 2;\\n\\t\\t}\\n\\t}\\n\\treturn 3;\\n});\\ndefinePluralFn([\\n\\t\\\"ar\\\"\\n], (n) => {\\n\\tif (n === 0) {\\n\\t\\treturn 0;\\n\\t} else if (n === 1) {\\n\\t\\treturn 1;\\n\\t} else if (n === 2) {\\n\\t\\treturn 2;\\n\\t}\\n\\tif (Number.isInteger(n)) {\\n\\t\\tconst mod100 = n % 100;\\n\\t\\tif (mod100 >= 3 && mod100 <= 10) {\\n\\t\\t\\treturn 3;\\n\\t\\t} else if (mod100 >= 11 && mod100 <= 99) {\\n\\t\\t\\treturn 4;\\n\\t\\t}\\n\\t}\\n\\treturn 5;\\n});\\nconst DEFAULT_PLURAL_FN = PLURALS[getLang(DEFAULT_LOCALE)];\\nfunction getPluralFn(lang) {\\n\\treturn PLURALS[lang] || DEFAULT_PLURAL_FN;\\n}\\n\\nconst ABSOLUTE_URL = new RegExp(\\n\\t\\\"^\\\\\\\\s*(?:(?:[a-z]+[a-z0-9\\\\\\\\-+.]*:)?//|data:|blob:)\\\",\\n\\t\\\"i\\\"\\n\\t// non case-sensitive flag\\n);\\n\\nclass AssetFile {\\n\\tconstructor(url = \\\"\\\", filename = \\\"\\\", hash = null, size = null, opt = null, contents = null) {\\n\\t\\tthis.url = url;\\n\\t\\tthis.filename = filename;\\n\\t\\tthis.hash = hash;\\n\\t\\tthis.size = size;\\n\\t\\tthis.opt = opt;\\n\\t\\tthis.contents = contents;\\n\\t}\\n\\t// Compare this AssetFile with another. Returns true if they have the same data\\n\\t// and false otherwise.\\n\\tequals(other) {\\n\\t\\treturn this.url === other.url && this.filename === other.filename && this.hash === other.hash && this.size === other.size && this.opt === other.opt && this.contents === other.contents;\\n\\t}\\n}\\n\\nlet assetIdCounter = -1;\\nconst VARIANT_SUPPORT = {\\n\\tpvr: \\\"extCompressedTexturePVRTC\\\",\\n\\tdxt: \\\"extCompressedTextureS3TC\\\",\\n\\tetc2: \\\"extCompressedTextureETC\\\",\\n\\tetc1: \\\"extCompressedTextureETC1\\\",\\n\\tbasis: \\\"canvas\\\"\\n\\t// dummy, basis is always supported\\n};\\nconst VARIANT_DEFAULT_PRIORITY = [\\\"pvr\\\", \\\"dxt\\\", \\\"etc2\\\", \\\"etc1\\\", \\\"basis\\\"];\\nclass Asset extends EventHandler {\\n\\tstatic EVENT_LOAD = \\\"load\\\";\\n\\tstatic EVENT_UNLOAD = \\\"unload\\\";\\n\\tstatic EVENT_REMOVE = \\\"remove\\\";\\n\\tstatic EVENT_ERROR = \\\"error\\\";\\n\\tstatic EVENT_CHANGE = \\\"change\\\";\\n\\tstatic EVENT_PROGRESS = \\\"progress\\\";\\n\\tstatic EVENT_ADDLOCALIZED = \\\"add:localized\\\";\\n\\tstatic EVENT_REMOVELOCALIZED = \\\"remove:localized\\\";\\n\\t_file = null;\\n\\t_i18n = {};\\n\\t_preload = false;\\n\\t_resources = [];\\n\\tid = assetIdCounter--;\\n\\tloaded = false;\\n\\tloading = false;\\n\\toptions = {};\\n\\tregistry = null;\\n\\ttags = new Tags(this);\\n\\ttype;\\n\\turlObject = null;\\n\\tconstructor(name, type, file, data = {}, options = {}) {\\n\\t\\tsuper();\\n\\t\\tthis._name = name || \\\"\\\";\\n\\t\\tthis.type = type;\\n\\t\\tthis._data = data || {};\\n\\t\\tthis.options = options || {};\\n\\t\\tif (file) this.file = file;\\n\\t}\\n\\tset name(value) {\\n\\t\\tif (this._name === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst old = this._name;\\n\\t\\tthis._name = value;\\n\\t\\tthis.fire(\\\"name\\\", this, this._name, old);\\n\\t}\\n\\tget name() {\\n\\t\\treturn this._name;\\n\\t}\\n\\tset file(value) {\\n\\t\\tif (value && value.variants && [\\\"texture\\\", \\\"textureatlas\\\", \\\"bundle\\\"].indexOf(this.type) !== -1) {\\n\\t\\t\\tconst app = this.registry?._loader?._app || getApplication();\\n\\t\\t\\tconst device = app?.graphicsDevice;\\n\\t\\t\\tif (device) {\\n\\t\\t\\t\\tfor (let i = 0, len = VARIANT_DEFAULT_PRIORITY.length; i < len; i++) {\\n\\t\\t\\t\\t\\tconst variant = VARIANT_DEFAULT_PRIORITY[i];\\n\\t\\t\\t\\t\\tif (value.variants[variant] && device[VARIANT_SUPPORT[variant]]) {\\n\\t\\t\\t\\t\\t\\tvalue = value.variants[variant];\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (app.enableBundles) {\\n\\t\\t\\t\\t\\t\\tconst bundles = app.bundles.listBundlesForAsset(this);\\n\\t\\t\\t\\t\\t\\tif (bundles && bundles.find((b) => {\\n\\t\\t\\t\\t\\t\\t\\treturn b?.file?.variants[variant];\\n\\t\\t\\t\\t\\t\\t})) {\\n\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst oldFile = this._file;\\n\\t\\tconst newFile = value ? new AssetFile(value.url, value.filename, value.hash, value.size, value.opt, value.contents) : null;\\n\\t\\tif (!!newFile !== !!oldFile || newFile && !newFile.equals(oldFile)) {\\n\\t\\t\\tthis._file = newFile;\\n\\t\\t\\tthis.fire(\\\"change\\\", this, \\\"file\\\", newFile, oldFile);\\n\\t\\t\\tthis.reload();\\n\\t\\t}\\n\\t}\\n\\tget file() {\\n\\t\\treturn this._file;\\n\\t}\\n\\tset data(value) {\\n\\t\\tconst old = this._data;\\n\\t\\tthis._data = value;\\n\\t\\tif (value !== old) {\\n\\t\\t\\tthis.fire(\\\"change\\\", this, \\\"data\\\", value, old);\\n\\t\\t\\tif (this.loaded) {\\n\\t\\t\\t\\tthis.registry._loader.patch(this, this.registry);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget data() {\\n\\t\\treturn this._data;\\n\\t}\\n\\tset resource(value) {\\n\\t\\tconst _old = this._resources[0];\\n\\t\\tthis._resources[0] = value;\\n\\t\\tthis.fire(\\\"change\\\", this, \\\"resource\\\", value, _old);\\n\\t}\\n\\tget resource() {\\n\\t\\treturn this._resources[0];\\n\\t}\\n\\tset resources(value) {\\n\\t\\tconst _old = this._resources;\\n\\t\\tthis._resources = value;\\n\\t\\tthis.fire(\\\"change\\\", this, \\\"resources\\\", value, _old);\\n\\t}\\n\\tget resources() {\\n\\t\\treturn this._resources;\\n\\t}\\n\\tset preload(value) {\\n\\t\\tvalue = !!value;\\n\\t\\tif (this._preload === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._preload = value;\\n\\t\\tif (this._preload && !this.loaded && !this.loading && this.registry) {\\n\\t\\t\\tthis.registry.load(this);\\n\\t\\t}\\n\\t}\\n\\tget preload() {\\n\\t\\treturn this._preload;\\n\\t}\\n\\tset loadFaces(value) {\\n\\t\\tvalue = !!value;\\n\\t\\tif (!this.hasOwnProperty(\\\"_loadFaces\\\") || value !== this._loadFaces) {\\n\\t\\t\\tthis._loadFaces = value;\\n\\t\\t\\tif (this.loaded) {\\n\\t\\t\\t\\tthis.registry._loader.patch(this, this.registry);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget loadFaces() {\\n\\t\\treturn this._loadFaces;\\n\\t}\\n\\tgetFileUrl() {\\n\\t\\tconst file = this.file;\\n\\t\\tif (!file || !file.url) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tlet url = file.url;\\n\\t\\tif (this.registry && this.registry.prefix && !ABSOLUTE_URL.test(url)) {\\n\\t\\t\\turl = this.registry.prefix + url;\\n\\t\\t}\\n\\t\\tif (this.type !== \\\"script\\\" && file.hash) {\\n\\t\\t\\tconst separator = url.indexOf(\\\"?\\\") !== -1 ? \\\"&\\\" : \\\"?\\\";\\n\\t\\t\\turl += `${separator}t=${file.hash}`;\\n\\t\\t}\\n\\t\\treturn url;\\n\\t}\\n\\tgetAbsoluteUrl(relativePath) {\\n\\t\\tif (relativePath.startsWith(\\\"blob:\\\") || relativePath.startsWith(\\\"data:\\\")) {\\n\\t\\t\\treturn relativePath;\\n\\t\\t}\\n\\t\\tconst base = path.getDirectory(this.file.url);\\n\\t\\treturn path.join(base, relativePath);\\n\\t}\\n\\tgetLocalizedAssetId(locale) {\\n\\t\\tlocale = findAvailableLocale(locale, this._i18n);\\n\\t\\treturn this._i18n[locale] || null;\\n\\t}\\n\\taddLocalizedAssetId(locale, assetId) {\\n\\t\\tthis._i18n[locale] = assetId;\\n\\t\\tthis.fire(\\\"add:localized\\\", locale, assetId);\\n\\t}\\n\\tremoveLocalizedAssetId(locale) {\\n\\t\\tconst assetId = this._i18n[locale];\\n\\t\\tif (assetId) {\\n\\t\\t\\tdelete this._i18n[locale];\\n\\t\\t\\tthis.fire(\\\"remove:localized\\\", locale, assetId);\\n\\t\\t}\\n\\t}\\n\\tready(callback, scope) {\\n\\t\\tscope = scope || this;\\n\\t\\tif (this.loaded) {\\n\\t\\t\\tcallback.call(scope, this);\\n\\t\\t} else {\\n\\t\\t\\tthis.once(\\\"load\\\", (asset) => {\\n\\t\\t\\t\\tcallback.call(scope, asset);\\n\\t\\t\\t});\\n\\t\\t}\\n\\t}\\n\\treload() {\\n\\t\\tif (this.loaded) {\\n\\t\\t\\tthis.loaded = false;\\n\\t\\t\\tthis.registry.load(this);\\n\\t\\t}\\n\\t}\\n\\tunload() {\\n\\t\\tif (!this.loaded && this._resources.length === 0) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.fire(\\\"unload\\\", this);\\n\\t\\tthis.registry.fire(`unload:${this.id}`, this);\\n\\t\\tconst old = this._resources;\\n\\t\\tif (this.urlObject) {\\n\\t\\t\\tURL.revokeObjectURL(this.urlObject);\\n\\t\\t\\tthis.urlObject = null;\\n\\t\\t}\\n\\t\\tthis.resources = [];\\n\\t\\tthis.loaded = false;\\n\\t\\tif (this.file) {\\n\\t\\t\\tthis.registry._loader.clearCache(this.getFileUrl(), this.type);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < old.length; ++i) {\\n\\t\\t\\told[i]?.destroy?.();\\n\\t\\t}\\n\\t}\\n\\tstatic fetchArrayBuffer(loadUrl, callback, asset, maxRetries = 0) {\\n\\t\\tif (asset?.file?.contents) {\\n\\t\\t\\tsetTimeout(() => {\\n\\t\\t\\t\\tcallback(null, asset.file.contents);\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\thttp.get(loadUrl, {\\n\\t\\t\\t\\tcache: true,\\n\\t\\t\\t\\tresponseType: \\\"arraybuffer\\\",\\n\\t\\t\\t\\tretry: maxRetries > 0,\\n\\t\\t\\t\\tmaxRetries,\\n\\t\\t\\t\\tprogress: asset\\n\\t\\t\\t}, callback);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass TagsCache {\\n\\t_index = {};\\n\\t_key;\\n\\tconstructor(key = null) {\\n\\t\\tthis._key = key;\\n\\t}\\n\\taddItem(item) {\\n\\t\\tconst tags = item.tags._list;\\n\\t\\tfor (const tag of tags) {\\n\\t\\t\\tthis.add(tag, item);\\n\\t\\t}\\n\\t}\\n\\tremoveItem(item) {\\n\\t\\tconst tags = item.tags._list;\\n\\t\\tfor (const tag of tags) {\\n\\t\\t\\tthis.remove(tag, item);\\n\\t\\t}\\n\\t}\\n\\tadd(tag, item) {\\n\\t\\tif (this._index[tag] && this._index[tag].list.indexOf(item) !== -1) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!this._index[tag]) {\\n\\t\\t\\tthis._index[tag] = {\\n\\t\\t\\t\\tlist: []\\n\\t\\t\\t};\\n\\t\\t\\tif (this._key) {\\n\\t\\t\\t\\tthis._index[tag].keys = {};\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._index[tag].list.push(item);\\n\\t\\tif (this._key) {\\n\\t\\t\\tthis._index[tag].keys[item[this._key]] = item;\\n\\t\\t}\\n\\t}\\n\\tremove(tag, item) {\\n\\t\\tif (!this._index[tag]) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._key) {\\n\\t\\t\\tif (!this._index[tag].keys[item[this._key]]) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst ind = this._index[tag].list.indexOf(item);\\n\\t\\tif (ind === -1) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._index[tag].list.splice(ind, 1);\\n\\t\\tif (this._key) {\\n\\t\\t\\tdelete this._index[tag].keys[item[this._key]];\\n\\t\\t}\\n\\t\\tif (this._index[tag].list.length === 0) {\\n\\t\\t\\tdelete this._index[tag];\\n\\t\\t}\\n\\t}\\n\\tfind(args) {\\n\\t\\tconst index = {};\\n\\t\\tconst items = [];\\n\\t\\tlet item, tag, tags, tagsRest, missingIndex;\\n\\t\\tconst sort = (a, b) => {\\n\\t\\t\\treturn this._index[a].list.length - this._index[b].list.length;\\n\\t\\t};\\n\\t\\tfor (let i = 0; i < args.length; i++) {\\n\\t\\t\\ttag = args[i];\\n\\t\\t\\tif (tag instanceof Array) {\\n\\t\\t\\t\\tif (tag.length === 0) {\\n\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (tag.length === 1) {\\n\\t\\t\\t\\t\\ttag = tag[0];\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tmissingIndex = false;\\n\\t\\t\\t\\t\\tfor (let t = 0; t < tag.length; t++) {\\n\\t\\t\\t\\t\\t\\tif (!this._index[tag[t]]) {\\n\\t\\t\\t\\t\\t\\t\\tmissingIndex = true;\\n\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (missingIndex) {\\n\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\ttags = tag.slice(0).sort(sort);\\n\\t\\t\\t\\t\\ttagsRest = tags.slice(1);\\n\\t\\t\\t\\t\\tif (tagsRest.length === 1) {\\n\\t\\t\\t\\t\\t\\ttagsRest = tagsRest[0];\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tfor (let n = 0; n < this._index[tags[0]].list.length; n++) {\\n\\t\\t\\t\\t\\t\\titem = this._index[tags[0]].list[n];\\n\\t\\t\\t\\t\\t\\tif ((this._key ? !index[item[this._key]] : items.indexOf(item) === -1) && item.tags.has(tagsRest)) {\\n\\t\\t\\t\\t\\t\\t\\tif (this._key) {\\n\\t\\t\\t\\t\\t\\t\\t\\tindex[item[this._key]] = true;\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\titems.push(item);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (tag && typeof tag === \\\"string\\\" && this._index[tag]) {\\n\\t\\t\\t\\tfor (let n = 0; n < this._index[tag].list.length; n++) {\\n\\t\\t\\t\\t\\titem = this._index[tag].list[n];\\n\\t\\t\\t\\t\\tif (this._key) {\\n\\t\\t\\t\\t\\t\\tif (!index[item[this._key]]) {\\n\\t\\t\\t\\t\\t\\t\\tindex[item[this._key]] = true;\\n\\t\\t\\t\\t\\t\\t\\titems.push(item);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t} else if (items.indexOf(item) === -1) {\\n\\t\\t\\t\\t\\t\\titems.push(item);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn items;\\n\\t}\\n}\\n\\nclass AssetRegistry extends EventHandler {\\n\\tstatic EVENT_LOAD = \\\"load\\\";\\n\\tstatic EVENT_ADD = \\\"add\\\";\\n\\tstatic EVENT_REMOVE = \\\"remove\\\";\\n\\tstatic EVENT_ERROR = \\\"error\\\";\\n\\t_assets = /* @__PURE__ */ new Set();\\n\\t_loader;\\n\\t_idToAsset = /* @__PURE__ */ new Map();\\n\\t_urlToAsset = /* @__PURE__ */ new Map();\\n\\t_nameToAsset = /* @__PURE__ */ new Map();\\n\\t_tags = new TagsCache(\\\"id\\\");\\n\\tprefix = null;\\n\\tbundles = null;\\n\\tconstructor(loader) {\\n\\t\\tsuper();\\n\\t\\tthis._loader = loader;\\n\\t}\\n\\tget loader() {\\n\\t\\treturn this._loader;\\n\\t}\\n\\tlist(filters = {}) {\\n\\t\\tconst assets = Array.from(this._assets);\\n\\t\\tif (filters.preload !== void 0) {\\n\\t\\t\\treturn assets.filter((asset) => asset.preload === filters.preload);\\n\\t\\t}\\n\\t\\treturn assets;\\n\\t}\\n\\tadd(asset) {\\n\\t\\tif (this._assets.has(asset)) return;\\n\\t\\tthis._assets.add(asset);\\n\\t\\tthis._idToAsset.set(asset.id, asset);\\n\\t\\tif (asset.file?.url) {\\n\\t\\t\\tthis._urlToAsset.set(asset.file.url, asset);\\n\\t\\t}\\n\\t\\tif (!this._nameToAsset.has(asset.name)) {\\n\\t\\t\\tthis._nameToAsset.set(asset.name, /* @__PURE__ */ new Set());\\n\\t\\t}\\n\\t\\tthis._nameToAsset.get(asset.name).add(asset);\\n\\t\\tasset.on(\\\"name\\\", this._onNameChange, this);\\n\\t\\tasset.registry = this;\\n\\t\\tthis._tags.addItem(asset);\\n\\t\\tasset.tags.on(\\\"add\\\", this._onTagAdd, this);\\n\\t\\tasset.tags.on(\\\"remove\\\", this._onTagRemove, this);\\n\\t\\tthis.fire(\\\"add\\\", asset);\\n\\t\\tthis.fire(`add:${asset.id}`, asset);\\n\\t\\tif (asset.file?.url) {\\n\\t\\t\\tthis.fire(`add:url:${asset.file.url}`, asset);\\n\\t\\t}\\n\\t\\tif (asset.preload) {\\n\\t\\t\\tthis.load(asset);\\n\\t\\t}\\n\\t}\\n\\tremove(asset) {\\n\\t\\tif (!this._assets.has(asset)) return false;\\n\\t\\tthis._assets.delete(asset);\\n\\t\\tthis._idToAsset.delete(asset.id);\\n\\t\\tif (asset.file?.url) {\\n\\t\\t\\tthis._urlToAsset.delete(asset.file.url);\\n\\t\\t}\\n\\t\\tasset.off(\\\"name\\\", this._onNameChange, this);\\n\\t\\tif (this._nameToAsset.has(asset.name)) {\\n\\t\\t\\tconst items = this._nameToAsset.get(asset.name);\\n\\t\\t\\titems.delete(asset);\\n\\t\\t\\tif (items.size === 0) {\\n\\t\\t\\t\\tthis._nameToAsset.delete(asset.name);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._tags.removeItem(asset);\\n\\t\\tasset.tags.off(\\\"add\\\", this._onTagAdd, this);\\n\\t\\tasset.tags.off(\\\"remove\\\", this._onTagRemove, this);\\n\\t\\tasset.fire(\\\"remove\\\", asset);\\n\\t\\tthis.fire(\\\"remove\\\", asset);\\n\\t\\tthis.fire(`remove:${asset.id}`, asset);\\n\\t\\tif (asset.file?.url) {\\n\\t\\t\\tthis.fire(`remove:url:${asset.file.url}`, asset);\\n\\t\\t}\\n\\t\\treturn true;\\n\\t}\\n\\tget(id) {\\n\\t\\treturn this._idToAsset.get(Number(id));\\n\\t}\\n\\tgetByUrl(url) {\\n\\t\\treturn this._urlToAsset.get(url);\\n\\t}\\n\\tload(asset, options) {\\n\\t\\tif ((asset.loading || asset.loaded) && !options?.force) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst file = asset.file;\\n\\t\\tconst _fireLoad = () => {\\n\\t\\t\\tthis.fire(\\\"load\\\", asset);\\n\\t\\t\\tthis.fire(`load:${asset.id}`, asset);\\n\\t\\t\\tif (file && file.url) {\\n\\t\\t\\t\\tthis.fire(`load:url:${file.url}`, asset);\\n\\t\\t\\t}\\n\\t\\t\\tasset.fire(\\\"load\\\", asset);\\n\\t\\t};\\n\\t\\tconst _opened = (resource) => {\\n\\t\\t\\tif (resource instanceof Array) {\\n\\t\\t\\t\\tasset.resources = resource;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tasset.resource = resource;\\n\\t\\t\\t}\\n\\t\\t\\tthis._loader.patch(asset, this);\\n\\t\\t\\tif (asset.type === \\\"bundle\\\") {\\n\\t\\t\\t\\tconst assetIds = asset.data.assets;\\n\\t\\t\\t\\tfor (let i = 0; i < assetIds.length; i++) {\\n\\t\\t\\t\\t\\tconst assetInBundle = this._idToAsset.get(assetIds[i]);\\n\\t\\t\\t\\t\\tif (assetInBundle && !assetInBundle.loaded) {\\n\\t\\t\\t\\t\\t\\tthis.load(assetInBundle, { force: true });\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (asset.resource.loaded) {\\n\\t\\t\\t\\t\\t_fireLoad();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tthis.fire(\\\"load:start\\\", asset);\\n\\t\\t\\t\\t\\tthis.fire(`load:start:${asset.id}`, asset);\\n\\t\\t\\t\\t\\tif (file && file.url) {\\n\\t\\t\\t\\t\\t\\tthis.fire(`load:start:url:${file.url}`, asset);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tasset.fire(\\\"load:start\\\", asset);\\n\\t\\t\\t\\t\\tasset.resource.on(\\\"load\\\", _fireLoad);\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\t_fireLoad();\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tconst _loaded = (err, resource, extra) => {\\n\\t\\t\\tasset.loaded = true;\\n\\t\\t\\tasset.loading = false;\\n\\t\\t\\tif (err) {\\n\\t\\t\\t\\tthis.fire(\\\"error\\\", err, asset);\\n\\t\\t\\t\\tthis.fire(`error:${asset.id}`, err, asset);\\n\\t\\t\\t\\tasset.fire(\\\"error\\\", err, asset);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (asset.type === \\\"script\\\") {\\n\\t\\t\\t\\t\\tconst handler = this._loader.getHandler(\\\"script\\\");\\n\\t\\t\\t\\t\\tif (handler._cache[asset.id] && handler._cache[asset.id].parentNode === document.head) {\\n\\t\\t\\t\\t\\t\\tdocument.head.removeChild(handler._cache[asset.id]);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (extra) {\\n\\t\\t\\t\\t\\t\\thandler._cache[asset.id] = extra;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\t_opened(resource);\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tif (file || asset.type === \\\"cubemap\\\") {\\n\\t\\t\\tthis.fire(\\\"load:start\\\", asset);\\n\\t\\t\\tthis.fire(`load:${asset.id}:start`, asset);\\n\\t\\t\\tasset.loading = true;\\n\\t\\t\\tconst fileUrl = asset.getFileUrl();\\n\\t\\t\\tif (asset.type === \\\"bundle\\\") {\\n\\t\\t\\t\\tconst assetIds = asset.data.assets;\\n\\t\\t\\t\\tfor (let i = 0; i < assetIds.length; i++) {\\n\\t\\t\\t\\t\\tconst assetInBundle = this._idToAsset.get(assetIds[i]);\\n\\t\\t\\t\\t\\tif (!assetInBundle) {\\n\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (assetInBundle.loaded || assetInBundle.resource || assetInBundle.loading) {\\n\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tassetInBundle.loading = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis._loader.load(fileUrl, asset.type, _loaded, asset, options);\\n\\t\\t} else {\\n\\t\\t\\tconst resource = this._loader.open(asset.type, asset.data);\\n\\t\\t\\tasset.loaded = true;\\n\\t\\t\\t_opened(resource);\\n\\t\\t}\\n\\t}\\n\\tloadFromUrl(url, type, callback) {\\n\\t\\tthis.loadFromUrlAndFilename(url, null, type, callback);\\n\\t}\\n\\tloadFromUrlAndFilename(url, filename, type, callback) {\\n\\t\\tconst name = path.getBasename(filename || url);\\n\\t\\tconst file = {\\n\\t\\t\\tfilename: filename || name,\\n\\t\\t\\turl\\n\\t\\t};\\n\\t\\tlet asset = this.getByUrl(url);\\n\\t\\tif (!asset) {\\n\\t\\t\\tasset = new Asset(name, type, file);\\n\\t\\t\\tthis.add(asset);\\n\\t\\t} else if (asset.loaded) {\\n\\t\\t\\tcallback(asset.loadFromUrlError || null, asset);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst startLoad = (asset2) => {\\n\\t\\t\\tasset2.once(\\\"load\\\", (loadedAsset) => {\\n\\t\\t\\t\\tif (type === \\\"material\\\") {\\n\\t\\t\\t\\t\\tthis._loadTextures(loadedAsset, (err, textures) => {\\n\\t\\t\\t\\t\\t\\tcallback(err, loadedAsset);\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tcallback(null, loadedAsset);\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t\\tasset2.once(\\\"error\\\", (err) => {\\n\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\tthis.loadFromUrlError = err;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcallback(err, asset2);\\n\\t\\t\\t});\\n\\t\\t\\tthis.load(asset2);\\n\\t\\t};\\n\\t\\tif (asset.resource) {\\n\\t\\t\\tcallback(null, asset);\\n\\t\\t} else if (type === \\\"model\\\") {\\n\\t\\t\\tthis._loadModel(asset, startLoad);\\n\\t\\t} else {\\n\\t\\t\\tstartLoad(asset);\\n\\t\\t}\\n\\t}\\n\\t// private method used for engine-only loading of model data\\n\\t_loadModel(modelAsset, continuation) {\\n\\t\\tconst url = modelAsset.getFileUrl();\\n\\t\\tconst ext = path.getExtension(url);\\n\\t\\tif (ext === \\\".json\\\" || ext === \\\".glb\\\") {\\n\\t\\t\\tconst dir = path.getDirectory(url);\\n\\t\\t\\tconst basename = path.getBasename(url);\\n\\t\\t\\tconst mappingUrl = path.join(dir, basename.replace(ext, \\\".mapping.json\\\"));\\n\\t\\t\\tthis._loader.load(mappingUrl, \\\"json\\\", (err, data) => {\\n\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\tmodelAsset.data = { mapping: [] };\\n\\t\\t\\t\\t\\tcontinuation(modelAsset);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tthis._loadMaterials(modelAsset, data, (e, materials) => {\\n\\t\\t\\t\\t\\t\\tmodelAsset.data = data;\\n\\t\\t\\t\\t\\t\\tcontinuation(modelAsset);\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\tcontinuation(modelAsset);\\n\\t\\t}\\n\\t}\\n\\t// private method used for engine-only loading of model materials\\n\\t_loadMaterials(modelAsset, mapping, callback) {\\n\\t\\tconst materials = [];\\n\\t\\tlet count = 0;\\n\\t\\tconst onMaterialLoaded = (err, materialAsset) => {\\n\\t\\t\\tthis._loadTextures(materialAsset, (err2, textures) => {\\n\\t\\t\\t\\tmaterials.push(materialAsset);\\n\\t\\t\\t\\tif (materials.length === count) {\\n\\t\\t\\t\\t\\tcallback(null, materials);\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t};\\n\\t\\tfor (let i = 0; i < mapping.mapping.length; i++) {\\n\\t\\t\\tconst path2 = mapping.mapping[i].path;\\n\\t\\t\\tif (path2) {\\n\\t\\t\\t\\tcount++;\\n\\t\\t\\t\\tconst url = modelAsset.getAbsoluteUrl(path2);\\n\\t\\t\\t\\tthis.loadFromUrl(url, \\\"material\\\", onMaterialLoaded);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (count === 0) {\\n\\t\\t\\tcallback(null, materials);\\n\\t\\t}\\n\\t}\\n\\t// private method used for engine-only loading of the textures referenced by\\n\\t// the material asset\\n\\t_loadTextures(materialAsset, callback) {\\n\\t\\tconst textures = [];\\n\\t\\tlet count = 0;\\n\\t\\tconst data = materialAsset.data;\\n\\t\\tif (data.mappingFormat !== \\\"path\\\") {\\n\\t\\t\\tcallback(null, textures);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst onTextureLoaded = (err, texture) => {\\n\\t\\t\\tif (err) console.error(`Failed to load material texture for \\\"${materialAsset.name}\\\": ${err?.message ?? err}`, err);\\n\\t\\t\\ttextures.push(texture);\\n\\t\\t\\tif (textures.length === count) {\\n\\t\\t\\t\\tcallback(null, textures);\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tconst texParams = standardMaterialTextureParameters;\\n\\t\\tfor (let i = 0; i < texParams.length; i++) {\\n\\t\\t\\tconst path2 = data[texParams[i]];\\n\\t\\t\\tif (path2 && typeof path2 === \\\"string\\\") {\\n\\t\\t\\t\\tcount++;\\n\\t\\t\\t\\tconst url = materialAsset.getAbsoluteUrl(path2);\\n\\t\\t\\t\\tthis.loadFromUrl(url, \\\"texture\\\", onTextureLoaded);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (count === 0) {\\n\\t\\t\\tcallback(null, textures);\\n\\t\\t}\\n\\t}\\n\\t_onTagAdd(tag, asset) {\\n\\t\\tthis._tags.add(tag, asset);\\n\\t}\\n\\t_onTagRemove(tag, asset) {\\n\\t\\tthis._tags.remove(tag, asset);\\n\\t}\\n\\t_onNameChange(asset, name, nameOld) {\\n\\t\\tif (this._nameToAsset.has(nameOld)) {\\n\\t\\t\\tconst items = this._nameToAsset.get(nameOld);\\n\\t\\t\\titems.delete(asset);\\n\\t\\t\\tif (items.size === 0) {\\n\\t\\t\\t\\tthis._nameToAsset.delete(nameOld);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (!this._nameToAsset.has(asset.name)) {\\n\\t\\t\\tthis._nameToAsset.set(asset.name, /* @__PURE__ */ new Set());\\n\\t\\t}\\n\\t\\tthis._nameToAsset.get(asset.name).add(asset);\\n\\t}\\n\\tfindByTag(...query) {\\n\\t\\treturn this._tags.find(query);\\n\\t}\\n\\tfilter(callback) {\\n\\t\\treturn Array.from(this._assets).filter((asset) => callback(asset));\\n\\t}\\n\\tfind(name, type) {\\n\\t\\tconst items = this._nameToAsset.get(name);\\n\\t\\tif (!items) return null;\\n\\t\\tfor (const asset of items) {\\n\\t\\t\\tif (!type || asset.type === type) {\\n\\t\\t\\t\\treturn asset;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn null;\\n\\t}\\n\\tfindAll(name, type) {\\n\\t\\tconst items = this._nameToAsset.get(name);\\n\\t\\tif (!items) return [];\\n\\t\\tconst results = Array.from(items);\\n\\t\\tif (!type) return results;\\n\\t\\treturn results.filter((asset) => asset.type === type);\\n\\t}\\n\\tlog() {\\n\\t}\\n}\\n\\nclass BundleRegistry {\\n\\t_idToBundle = /* @__PURE__ */ new Map();\\n\\t_assetToBundles = /* @__PURE__ */ new Map();\\n\\t_urlsToBundles = /* @__PURE__ */ new Map();\\n\\t_fileRequests = /* @__PURE__ */ new Map();\\n\\tconstructor(assets) {\\n\\t\\tthis._assets = assets;\\n\\t\\tthis._assets.bundles = this;\\n\\t\\tthis._assets.on(\\\"add\\\", this._onAssetAdd, this);\\n\\t\\tthis._assets.on(\\\"remove\\\", this._onAssetRemove, this);\\n\\t}\\n\\t_onAssetAdd(asset) {\\n\\t\\tif (asset.type === \\\"bundle\\\") {\\n\\t\\t\\tthis._idToBundle.set(asset.id, asset);\\n\\t\\t\\tthis._assets.on(`load:start:${asset.id}`, this._onBundleLoadStart, this);\\n\\t\\t\\tthis._assets.on(`load:${asset.id}`, this._onBundleLoad, this);\\n\\t\\t\\tthis._assets.on(`error:${asset.id}`, this._onBundleError, this);\\n\\t\\t\\tconst assetIds = asset.data.assets;\\n\\t\\t\\tfor (let i = 0; i < assetIds.length; i++) {\\n\\t\\t\\t\\tthis._indexAssetInBundle(assetIds[i], asset);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tif (this._assetToBundles.has(asset.id)) {\\n\\t\\t\\t\\tthis._indexAssetFileUrls(asset);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_unbindAssetEvents(id) {\\n\\t\\tthis._assets.off(`load:start:${id}`, this._onBundleLoadStart, this);\\n\\t\\tthis._assets.off(`load:${id}`, this._onBundleLoad, this);\\n\\t\\tthis._assets.off(`error:${id}`, this._onBundleError, this);\\n\\t}\\n\\t// Index the specified asset id and its file URLs so that\\n\\t// the registry knows that the asset is in that bundle\\n\\t_indexAssetInBundle(id, bundle) {\\n\\t\\tlet bundles = this._assetToBundles.get(id);\\n\\t\\tif (!bundles) {\\n\\t\\t\\tbundles = /* @__PURE__ */ new Set();\\n\\t\\t\\tthis._assetToBundles.set(id, bundles);\\n\\t\\t}\\n\\t\\tbundles.add(bundle);\\n\\t\\tconst asset = this._assets.get(id);\\n\\t\\tif (asset) this._indexAssetFileUrls(asset);\\n\\t}\\n\\t// Index the file URLs of the specified asset\\n\\t_indexAssetFileUrls(asset) {\\n\\t\\tconst urls = this._getAssetFileUrls(asset);\\n\\t\\tif (!urls) return;\\n\\t\\tfor (let i = 0; i < urls.length; i++) {\\n\\t\\t\\tconst bundles = this._assetToBundles.get(asset.id);\\n\\t\\t\\tif (!bundles) continue;\\n\\t\\t\\tthis._urlsToBundles.set(urls[i], bundles);\\n\\t\\t}\\n\\t}\\n\\t// Get all the possible URLs of an asset\\n\\t_getAssetFileUrls(asset) {\\n\\t\\tlet url = asset.getFileUrl();\\n\\t\\tif (!url) return null;\\n\\t\\turl = url.split(\\\"?\\\")[0];\\n\\t\\tconst urls = [url];\\n\\t\\tif (asset.type === \\\"font\\\") {\\n\\t\\t\\tconst numFiles = asset.data.info.maps.length;\\n\\t\\t\\tfor (let i = 1; i < numFiles; i++) {\\n\\t\\t\\t\\turls.push(url.replace(\\\".png\\\", `${i}.png`));\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn urls;\\n\\t}\\n\\t// Remove asset from internal indexes\\n\\t_onAssetRemove(asset) {\\n\\t\\tif (asset.type === \\\"bundle\\\") {\\n\\t\\t\\tthis._idToBundle.delete(asset.id);\\n\\t\\t\\tthis._unbindAssetEvents(asset.id);\\n\\t\\t\\tconst assetIds = asset.data.assets;\\n\\t\\t\\tfor (let i = 0; i < assetIds.length; i++) {\\n\\t\\t\\t\\tconst bundles = this._assetToBundles.get(assetIds[i]);\\n\\t\\t\\t\\tif (!bundles) continue;\\n\\t\\t\\t\\tbundles.delete(asset);\\n\\t\\t\\t\\tif (bundles.size === 0) {\\n\\t\\t\\t\\t\\tthis._assetToBundles.delete(assetIds[i]);\\n\\t\\t\\t\\t\\tfor (const [url, otherBundles] of this._urlsToBundles) {\\n\\t\\t\\t\\t\\t\\tif (otherBundles !== bundles) {\\n\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._urlsToBundles.delete(url);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis._onBundleError(`Bundle ${asset.id} was removed`);\\n\\t\\t} else {\\n\\t\\t\\tconst bundles = this._assetToBundles.get(asset.id);\\n\\t\\t\\tif (!bundles) return;\\n\\t\\t\\tthis._assetToBundles.delete(asset.id);\\n\\t\\t\\tconst urls = this._getAssetFileUrls(asset);\\n\\t\\t\\tif (!urls) return;\\n\\t\\t\\tfor (let i = 0; i < urls.length; i++) {\\n\\t\\t\\t\\tthis._urlsToBundles.delete(urls[i]);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_onBundleLoadStart(asset) {\\n\\t\\tasset.resource.on(\\\"add\\\", (url, data) => {\\n\\t\\t\\tconst callbacks = this._fileRequests.get(url);\\n\\t\\t\\tif (!callbacks) return;\\n\\t\\t\\tfor (let i = 0; i < callbacks.length; i++) {\\n\\t\\t\\t\\tcallbacks[i](null, data);\\n\\t\\t\\t}\\n\\t\\t\\tthis._fileRequests.delete(url);\\n\\t\\t});\\n\\t}\\n\\t// If we have any pending file requests\\n\\t// that can be satisfied by the specified bundle\\n\\t// then resolve them\\n\\t_onBundleLoad(asset) {\\n\\t\\tif (!asset.resource) {\\n\\t\\t\\tthis._onBundleError(`Bundle ${asset.id} failed to load`);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!this._fileRequests) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tfor (const [url, requests] of this._fileRequests) {\\n\\t\\t\\tconst bundles = this._urlsToBundles.get(url);\\n\\t\\t\\tif (!bundles || !bundles.has(asset)) continue;\\n\\t\\t\\tconst decodedUrl = decodeURIComponent(url);\\n\\t\\t\\tlet err, data;\\n\\t\\t\\tif (asset.resource.has(decodedUrl)) {\\n\\t\\t\\t\\tdata = asset.resource.get(decodedUrl);\\n\\t\\t\\t} else if (asset.resource.loaded) {\\n\\t\\t\\t\\terr = `Bundle ${asset.id} does not contain URL ${url}`;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tfor (let i = 0; i < requests.length; i++) {\\n\\t\\t\\t\\trequests[i](err, err || data);\\n\\t\\t\\t}\\n\\t\\t\\tthis._fileRequests.delete(url);\\n\\t\\t}\\n\\t}\\n\\t// If we have outstanding file requests for any\\n\\t// of the URLs in the specified bundle then search for\\n\\t// other bundles that can satisfy these requests.\\n\\t// If we do not find any other bundles then fail\\n\\t// those pending file requests with the specified error.\\n\\t_onBundleError(err) {\\n\\t\\tfor (const [url, requests] of this._fileRequests) {\\n\\t\\t\\tconst bundle = this._findLoadedOrLoadingBundleForUrl(url);\\n\\t\\t\\tif (!bundle) {\\n\\t\\t\\t\\tfor (let i = 0; i < requests.length; i++) {\\n\\t\\t\\t\\t\\trequests[i](err);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._fileRequests.delete(url);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t// Finds a bundle that contains the specified URL but\\n\\t// only returns the bundle if it's either loaded or being loaded\\n\\t_findLoadedOrLoadingBundleForUrl(url) {\\n\\t\\tconst bundles = this._urlsToBundles.get(url);\\n\\t\\tif (!bundles) return null;\\n\\t\\tlet candidate = null;\\n\\t\\tfor (const bundle of bundles) {\\n\\t\\t\\tif (bundle.loaded && bundle.resource) {\\n\\t\\t\\t\\treturn bundle;\\n\\t\\t\\t} else if (bundle.loading) {\\n\\t\\t\\t\\tcandidate = bundle;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn candidate;\\n\\t}\\n\\tlistBundlesForAsset(asset) {\\n\\t\\tconst bundles = this._assetToBundles.get(asset.id);\\n\\t\\tif (bundles) return Array.from(bundles);\\n\\t\\treturn null;\\n\\t}\\n\\tlist() {\\n\\t\\treturn Array.from(this._idToBundle.values());\\n\\t}\\n\\thasUrl(url) {\\n\\t\\treturn this._urlsToBundles.has(url);\\n\\t}\\n\\turlIsLoadedOrLoading(url) {\\n\\t\\treturn !!this._findLoadedOrLoadingBundleForUrl(url);\\n\\t}\\n\\tloadUrl(url, callback) {\\n\\t\\tconst bundle = this._findLoadedOrLoadingBundleForUrl(url);\\n\\t\\tif (!bundle) {\\n\\t\\t\\tcallback(`URL ${url} not found in any bundles`);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (bundle.loaded) {\\n\\t\\t\\tconst decodedUrl = decodeURIComponent(url);\\n\\t\\t\\tif (bundle.resource.has(decodedUrl)) {\\n\\t\\t\\t\\tcallback(null, bundle.resource.get(decodedUrl));\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t} else if (bundle.resource.loaded) {\\n\\t\\t\\t\\tcallback(`Bundle ${bundle.id} does not contain URL ${url}`);\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tlet callbacks = this._fileRequests.get(url);\\n\\t\\tif (!callbacks) {\\n\\t\\t\\tcallbacks = [];\\n\\t\\t\\tthis._fileRequests.set(url, callbacks);\\n\\t\\t}\\n\\t\\tcallbacks.push(callback);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._assets.off(\\\"add\\\", this._onAssetAdd, this);\\n\\t\\tthis._assets.off(\\\"remove\\\", this._onAssetRemove, this);\\n\\t\\tfor (const id of this._idToBundle.keys()) {\\n\\t\\t\\tthis._unbindAssetEvents(id);\\n\\t\\t}\\n\\t\\tthis._assets = null;\\n\\t\\tthis._idToBundle.clear();\\n\\t\\tthis._idToBundle = null;\\n\\t\\tthis._assetToBundles.clear();\\n\\t\\tthis._assetToBundles = null;\\n\\t\\tthis._urlsToBundles.clear();\\n\\t\\tthis._urlsToBundles = null;\\n\\t\\tthis._fileRequests.clear();\\n\\t\\tthis._fileRequests = null;\\n\\t}\\n}\\n\\nclass ComponentSystemRegistry extends EventHandler {\\n\\tanim;\\n\\tanimation;\\n\\taudiolistener;\\n\\tbutton;\\n\\tcamera;\\n\\tcollision;\\n\\telement;\\n\\tgsplat;\\n\\tjoint;\\n\\tlayoutchild;\\n\\tlayoutgroup;\\n\\tlight;\\n\\tmodel;\\n\\tparticlesystem;\\n\\trender;\\n\\trigidbody;\\n\\tscreen;\\n\\tscript;\\n\\tscrollbar;\\n\\tscrollview;\\n\\tsound;\\n\\tsprite;\\n\\tzone;\\n\\tconstructor() {\\n\\t\\tsuper();\\n\\t\\tthis.list = [];\\n\\t}\\n\\tadd(system) {\\n\\t\\tconst id = system.id;\\n\\t\\tif (this[id]) {\\n\\t\\t\\tthrow new Error(`ComponentSystem name '${id}' already registered or not allowed`);\\n\\t\\t}\\n\\t\\tthis[id] = system;\\n\\t\\tthis.list.push(system);\\n\\t}\\n\\tremove(system) {\\n\\t\\tconst id = system.id;\\n\\t\\tif (!this[id]) {\\n\\t\\t\\tthrow new Error(`No ComponentSystem named '${id}' registered`);\\n\\t\\t}\\n\\t\\tdelete this[id];\\n\\t\\tconst index = this.list.indexOf(this[id]);\\n\\t\\tif (index !== -1) {\\n\\t\\t\\tthis.list.splice(index, 1);\\n\\t\\t}\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.off();\\n\\t\\tfor (let i = 0; i < this.list.length; i++) {\\n\\t\\t\\tthis.list[i].destroy();\\n\\t\\t}\\n\\t}\\n}\\n\\nclass Bundle extends EventHandler {\\n\\t_index = /* @__PURE__ */ new Map();\\n\\t_loaded = false;\\n\\tstatic EVENT_ADD = \\\"add\\\";\\n\\tstatic EVENT_LOAD = \\\"load\\\";\\n\\taddFile(url, data) {\\n\\t\\tif (this._index.has(url)) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._index.set(url, data);\\n\\t\\tthis.fire(\\\"add\\\", url, data);\\n\\t}\\n\\thas(url) {\\n\\t\\treturn this._index.has(url);\\n\\t}\\n\\tget(url) {\\n\\t\\treturn this._index.get(url) || null;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._index.clear();\\n\\t}\\n\\tset loaded(value) {\\n\\t\\tif (!value || this._loaded) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._loaded = true;\\n\\t\\tthis.fire(\\\"load\\\");\\n\\t}\\n\\tget loaded() {\\n\\t\\treturn this._loaded;\\n\\t}\\n}\\n\\nclass Untar extends EventHandler {\\n\\theaderSize = 512;\\n\\tpaddingSize = 512;\\n\\tbytesRead = 0;\\n\\tbytesReceived = 0;\\n\\theaderRead = false;\\n\\treader = null;\\n\\tdata = new Uint8Array(0);\\n\\tdecoder = null;\\n\\tprefix = \\\"\\\";\\n\\tfileName = \\\"\\\";\\n\\tfileSize = 0;\\n\\tfileType = \\\"\\\";\\n\\tustarFormat = \\\"\\\";\\n\\tconstructor(fetchPromise, assetsPrefix = \\\"\\\") {\\n\\t\\tsuper();\\n\\t\\tthis.prefix = assetsPrefix || \\\"\\\";\\n\\t\\tthis.reader = fetchPromise.body.getReader();\\n\\t\\tthis.reader.read().then((res) => {\\n\\t\\t\\tthis.pump(res.done, res.value);\\n\\t\\t}).catch((err) => {\\n\\t\\t\\tthis.fire(\\\"error\\\", err);\\n\\t\\t});\\n\\t}\\n\\tpump(done, value) {\\n\\t\\tif (done) {\\n\\t\\t\\tthis.fire(\\\"done\\\");\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tthis.bytesReceived += value.byteLength;\\n\\t\\tconst data = new Uint8Array(this.data.length + value.length);\\n\\t\\tdata.set(this.data);\\n\\t\\tdata.set(value, this.data.length);\\n\\t\\tthis.data = data;\\n\\t\\twhile (this.readFile()) ;\\n\\t\\treturn this.reader.read().then((res) => {\\n\\t\\t\\tthis.pump(res.done, res.value);\\n\\t\\t}).catch((err) => {\\n\\t\\t\\tthis.fire(\\\"error\\\", err);\\n\\t\\t});\\n\\t}\\n\\treadFile() {\\n\\t\\tif (!this.headerRead && this.bytesReceived > this.bytesRead + this.headerSize) {\\n\\t\\t\\tthis.headerRead = true;\\n\\t\\t\\tconst view = new DataView(this.data.buffer, this.bytesRead, this.headerSize);\\n\\t\\t\\tthis.decoder ?? (this.decoder = new TextDecoder(\\\"windows-1252\\\"));\\n\\t\\t\\tconst headers = this.decoder.decode(view);\\n\\t\\t\\tthis.fileName = headers.substring(0, 100).replace(/\\\\0/g, \\\"\\\");\\n\\t\\t\\tthis.fileSize = parseInt(headers.substring(124, 136), 8);\\n\\t\\t\\tthis.fileType = headers.substring(156, 157);\\n\\t\\t\\tthis.ustarFormat = headers.substring(257, 263);\\n\\t\\t\\tif (this.ustarFormat.indexOf(\\\"ustar\\\") !== -1) {\\n\\t\\t\\t\\tconst prefix = headers.substring(345, 500).replace(/\\\\0/g, \\\"\\\");\\n\\t\\t\\t\\tif (prefix.length > 0) {\\n\\t\\t\\t\\t\\tthis.fileName = prefix.trim() + this.fileName.trim();\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis.bytesRead += 512;\\n\\t\\t}\\n\\t\\tif (this.headerRead) {\\n\\t\\t\\tif (this.bytesReceived < this.bytesRead + this.fileSize) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t\\t}\\n\\t\\t\\tif (this.fileType === \\\"\\\" || this.fileType === \\\"0\\\") {\\n\\t\\t\\t\\tconst dataView = new DataView(this.data.buffer, this.bytesRead, this.fileSize);\\n\\t\\t\\t\\tconst file = {\\n\\t\\t\\t\\t\\tname: this.prefix + this.fileName,\\n\\t\\t\\t\\t\\tsize: this.fileSize,\\n\\t\\t\\t\\t\\tdata: dataView\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.fire(\\\"file\\\", file);\\n\\t\\t\\t}\\n\\t\\t\\tthis.bytesRead += this.fileSize;\\n\\t\\t\\tthis.headerRead = false;\\n\\t\\t\\tconst bytesRemained = this.bytesRead % this.paddingSize;\\n\\t\\t\\tif (bytesRemained !== 0) {\\n\\t\\t\\t\\tthis.bytesRead += this.paddingSize - bytesRemained;\\n\\t\\t\\t}\\n\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\treturn false;\\n\\t}\\n}\\n\\nclass ResourceHandler {\\n\\thandlerType = \\\"\\\";\\n\\t_app;\\n\\t_maxRetries = 0;\\n\\tconstructor(app, handlerType) {\\n\\t\\tthis._app = app;\\n\\t\\tthis.handlerType = handlerType;\\n\\t}\\n\\tset maxRetries(value) {\\n\\t\\tthis._maxRetries = value;\\n\\t}\\n\\tget maxRetries() {\\n\\t\\treturn this._maxRetries;\\n\\t}\\n\\tload(url, callback, asset) {\\n\\t}\\n\\topen(url, data, asset) {\\n\\t\\treturn data;\\n\\t}\\n\\tpatch(asset, assets) {\\n\\t}\\n}\\n\\nclass BundleHandler extends ResourceHandler {\\n\\tconstructor(app) {\\n\\t\\tsuper(app, \\\"bundle\\\");\\n\\t\\tthis._assets = app.assets;\\n\\t}\\n\\t_fetchRetries(url, options, retries = 0) {\\n\\t\\treturn new Promise((resolve, reject) => {\\n\\t\\t\\tconst tryFetch = () => {\\n\\t\\t\\t\\tfetch(url, options).then(resolve).catch((err) => {\\n\\t\\t\\t\\t\\tretries++;\\n\\t\\t\\t\\t\\tif (retries < this.maxRetries) {\\n\\t\\t\\t\\t\\t\\ttryFetch();\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\treject(err);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t};\\n\\t\\t\\ttryFetch();\\n\\t\\t});\\n\\t}\\n\\tload(url, callback) {\\n\\t\\tif (typeof url === \\\"string\\\") {\\n\\t\\t\\turl = {\\n\\t\\t\\t\\tload: url,\\n\\t\\t\\t\\toriginal: url\\n\\t\\t\\t};\\n\\t\\t}\\n\\t\\tthis._fetchRetries(url.load, {\\n\\t\\t\\tmode: \\\"cors\\\"\\n\\t\\t}, this.maxRetries).then((res) => {\\n\\t\\t\\tconst bundle = new Bundle();\\n\\t\\t\\tcallback(null, bundle);\\n\\t\\t\\tconst untar = new Untar(res, this._assets.prefix);\\n\\t\\t\\tuntar.on(\\\"file\\\", (file) => {\\n\\t\\t\\t\\tbundle.addFile(file.name, file.data);\\n\\t\\t\\t});\\n\\t\\t\\tuntar.on(\\\"done\\\", () => {\\n\\t\\t\\t\\tbundle.loaded = true;\\n\\t\\t\\t});\\n\\t\\t\\tuntar.on(\\\"error\\\", (err) => {\\n\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t});\\n\\t\\t}).catch((err) => {\\n\\t\\t\\tcallback(err);\\n\\t\\t});\\n\\t}\\n\\topen(url, bundle) {\\n\\t\\treturn bundle;\\n\\t}\\n}\\n\\nclass ResourceLoader {\\n\\tconstructor(app) {\\n\\t\\tthis._handlers = {};\\n\\t\\tthis._requests = {};\\n\\t\\tthis._cache = {};\\n\\t\\tthis._app = app;\\n\\t}\\n\\taddHandler(type, handler) {\\n\\t\\tthis._handlers[type] = handler;\\n\\t\\thandler._loader = this;\\n\\t}\\n\\tremoveHandler(type) {\\n\\t\\tdelete this._handlers[type];\\n\\t}\\n\\tgetHandler(type) {\\n\\t\\treturn this._handlers[type];\\n\\t}\\n\\tstatic makeKey(url, type) {\\n\\t\\treturn `${url}-${type}`;\\n\\t}\\n\\tload(url, type, callback, asset, options) {\\n\\t\\tconst handler = this._handlers[type];\\n\\t\\tif (!handler) {\\n\\t\\t\\tconst err = `No resource handler for asset type: '${type}' when loading [${url}]`;\\n\\t\\t\\tcallback(err);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!url) {\\n\\t\\t\\tthis._loadNull(handler, callback, asset);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst key = ResourceLoader.makeKey(url, type);\\n\\t\\tif (this._cache[key] !== void 0) {\\n\\t\\t\\tcallback(null, this._cache[key]);\\n\\t\\t} else if (this._requests[key]) {\\n\\t\\t\\tthis._requests[key].push(callback);\\n\\t\\t} else {\\n\\t\\t\\tthis._requests[key] = [callback];\\n\\t\\t\\tconst self = this;\\n\\t\\t\\tconst handleLoad = function(err, urlObj) {\\n\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\tself._onFailure(key, err);\\n\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (urlObj.load instanceof DataView) {\\n\\t\\t\\t\\t\\tif (handler.openBinary) {\\n\\t\\t\\t\\t\\t\\tif (!self._requests[key]) {\\n\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\t\\tconst data = handler.openBinary(urlObj.load);\\n\\t\\t\\t\\t\\t\\t\\tself._onSuccess(key, data);\\n\\t\\t\\t\\t\\t\\t} catch (err2) {\\n\\t\\t\\t\\t\\t\\t\\tself._onFailure(key, err2);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\turlObj.load = URL.createObjectURL(new Blob([urlObj.load]));\\n\\t\\t\\t\\t\\tif (asset) {\\n\\t\\t\\t\\t\\t\\tif (asset.urlObject) {\\n\\t\\t\\t\\t\\t\\t\\tURL.revokeObjectURL(asset.urlObject);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tasset.urlObject = urlObj.load;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\thandler.load(urlObj, (err2, data, extra) => {\\n\\t\\t\\t\\t\\tif (!self._requests[key]) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (err2) {\\n\\t\\t\\t\\t\\t\\tself._onFailure(key, err2);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\tself._onSuccess(key, handler.open(urlObj.original, data, asset), extra);\\n\\t\\t\\t\\t\\t} catch (e) {\\n\\t\\t\\t\\t\\t\\tself._onFailure(key, e);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}, asset);\\n\\t\\t\\t};\\n\\t\\t\\tconst normalizedUrl = url.split(\\\"?\\\")[0];\\n\\t\\t\\tif (this._app.enableBundles && this._app.bundles.hasUrl(normalizedUrl) && !(options && options.bundlesIgnore)) {\\n\\t\\t\\t\\tif (!this._app.bundles.urlIsLoadedOrLoading(normalizedUrl)) {\\n\\t\\t\\t\\t\\tconst bundles = this._app.bundles.listBundlesForAsset(asset);\\n\\t\\t\\t\\t\\tlet bundle;\\n\\t\\t\\t\\t\\tif (options && options.bundlesFilter) {\\n\\t\\t\\t\\t\\t\\tbundle = options.bundlesFilter(bundles);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (!bundle) {\\n\\t\\t\\t\\t\\t\\tbundles?.sort((a, b) => {\\n\\t\\t\\t\\t\\t\\t\\treturn a.file.size - b.file.size;\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tbundle = bundles?.[0];\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (bundle) this._app.assets?.load(bundle);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._app.bundles.loadUrl(normalizedUrl, (err, fileUrlFromBundle) => {\\n\\t\\t\\t\\t\\thandleLoad(err, {\\n\\t\\t\\t\\t\\t\\tload: fileUrlFromBundle,\\n\\t\\t\\t\\t\\t\\toriginal: normalizedUrl\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t} else {\\n\\t\\t\\t\\thandleLoad(null, {\\n\\t\\t\\t\\t\\tload: url,\\n\\t\\t\\t\\t\\toriginal: asset && asset.file.filename || url\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t// load an asset with no url, skipping bundles and caching\\n\\t_loadNull(handler, callback, asset) {\\n\\t\\tconst onLoad = function(err, data, extra) {\\n\\t\\t\\tif (err) {\\n\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\tcallback(null, handler.open(null, data, asset), extra);\\n\\t\\t\\t\\t} catch (e) {\\n\\t\\t\\t\\t\\tcallback(e);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\thandler.load(null, onLoad, asset);\\n\\t}\\n\\t_onSuccess(key, result, extra) {\\n\\t\\tif (result !== null) {\\n\\t\\t\\tthis._cache[key] = result;\\n\\t\\t} else {\\n\\t\\t\\tdelete this._cache[key];\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < this._requests[key].length; i++) {\\n\\t\\t\\tthis._requests[key][i](null, result, extra);\\n\\t\\t}\\n\\t\\tdelete this._requests[key];\\n\\t}\\n\\t_onFailure(key, err) {\\n\\t\\tconsole.error(`Failed to load resource [${key}]: ${err?.message ?? err}`, err);\\n\\t\\tif (this._requests[key]) {\\n\\t\\t\\tfor (let i = 0; i < this._requests[key].length; i++) {\\n\\t\\t\\t\\tthis._requests[key][i](err);\\n\\t\\t\\t}\\n\\t\\t\\tdelete this._requests[key];\\n\\t\\t}\\n\\t}\\n\\topen(type, data) {\\n\\t\\tconst handler = this._handlers[type];\\n\\t\\tif (!handler) {\\n\\t\\t\\tconsole.warn(`No resource handler found for: ${type}`);\\n\\t\\t\\treturn data;\\n\\t\\t}\\n\\t\\treturn handler.open(null, data);\\n\\t}\\n\\tpatch(asset, assets) {\\n\\t\\tconst handler = this._handlers[asset.type];\\n\\t\\tif (!handler) {\\n\\t\\t\\tconsole.warn(`No resource handler found for: ${asset.type}`);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (handler.patch) {\\n\\t\\t\\thandler.patch(asset, assets);\\n\\t\\t}\\n\\t}\\n\\tclearCache(url, type) {\\n\\t\\tconst key = ResourceLoader.makeKey(url, type);\\n\\t\\tdelete this._cache[key];\\n\\t}\\n\\tgetFromCache(url, type) {\\n\\t\\tconst key = ResourceLoader.makeKey(url, type);\\n\\t\\tif (this._cache[key]) {\\n\\t\\t\\treturn this._cache[key];\\n\\t\\t}\\n\\t\\treturn void 0;\\n\\t}\\n\\tenableRetry(maxRetries = 5) {\\n\\t\\tmaxRetries = Math.max(0, Math.floor(maxRetries)) || 0;\\n\\t\\tfor (const key in this._handlers) {\\n\\t\\t\\tthis._handlers[key].maxRetries = maxRetries;\\n\\t\\t}\\n\\t}\\n\\tdisableRetry() {\\n\\t\\tfor (const key in this._handlers) {\\n\\t\\t\\tthis._handlers[key].maxRetries = 0;\\n\\t\\t}\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._handlers = {};\\n\\t\\tthis._requests = {};\\n\\t\\tthis._cache = {};\\n\\t}\\n}\\n\\nclass I18nParser {\\n\\t_validate(data) {\\n\\t\\tif (!data.header) {\\n\\t\\t\\tthrow new Error('pc.I18n#addData: Missing \\\"header\\\" field');\\n\\t\\t}\\n\\t\\tif (!data.header.version) {\\n\\t\\t\\tthrow new Error('pc.I18n#addData: Missing \\\"header.version\\\" field');\\n\\t\\t}\\n\\t\\tif (data.header.version !== 1) {\\n\\t\\t\\tthrow new Error('pc.I18n#addData: Invalid \\\"header.version\\\" field');\\n\\t\\t}\\n\\t\\tif (!data.data) {\\n\\t\\t\\tthrow new Error('pc.I18n#addData: Missing \\\"data\\\" field');\\n\\t\\t} else if (!Array.isArray(data.data)) {\\n\\t\\t\\tthrow new Error('pc.I18n#addData: \\\"data\\\" field must be an array');\\n\\t\\t}\\n\\t\\tfor (let i = 0, len = data.data.length; i < len; i++) {\\n\\t\\t\\tconst entry = data.data[i];\\n\\t\\t\\tif (!entry.info) {\\n\\t\\t\\t\\tthrow new Error(`pc.I18n#addData: missing \\\"data[${i}].info\\\" field`);\\n\\t\\t\\t}\\n\\t\\t\\tif (!entry.info.locale) {\\n\\t\\t\\t\\tthrow new Error(`pc.I18n#addData: missing \\\"data[${i}].info.locale\\\" field`);\\n\\t\\t\\t}\\n\\t\\t\\tif (typeof entry.info.locale !== \\\"string\\\") {\\n\\t\\t\\t\\tthrow new Error(`pc.I18n#addData: \\\"data[${i}].info.locale\\\" must be a string`);\\n\\t\\t\\t}\\n\\t\\t\\tif (!entry.messages) {\\n\\t\\t\\t\\tthrow new Error(`pc.I18n#addData: missing \\\"data[${i}].messages\\\" field`);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tparse(data) {\\n\\t\\treturn data.data;\\n\\t}\\n}\\n\\nclass I18n extends EventHandler {\\n\\tstatic EVENT_CHANGE = \\\"change\\\";\\n\\tconstructor(app) {\\n\\t\\tsuper();\\n\\t\\tthis.locale = DEFAULT_LOCALE;\\n\\t\\tthis._translations = {};\\n\\t\\tthis._availableLangs = {};\\n\\t\\tthis._app = app;\\n\\t\\tthis._assets = [];\\n\\t\\tthis._parser = new I18nParser();\\n\\t}\\n\\tset assets(value) {\\n\\t\\tconst index = {};\\n\\t\\tfor (let i2 = 0, len = value.length; i2 < len; i2++) {\\n\\t\\t\\tconst id = value[i2] instanceof Asset ? value[i2].id : value[i2];\\n\\t\\t\\tindex[id] = true;\\n\\t\\t}\\n\\t\\tlet i = this._assets.length;\\n\\t\\twhile (i--) {\\n\\t\\t\\tconst id = this._assets[i];\\n\\t\\t\\tif (!index[id]) {\\n\\t\\t\\t\\tthis._app.assets.off(`add:${id}`, this._onAssetAdd, this);\\n\\t\\t\\t\\tconst asset = this._app.assets.get(id);\\n\\t\\t\\t\\tif (asset) {\\n\\t\\t\\t\\t\\tthis._onAssetRemove(asset);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._assets.splice(i, 1);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (const id in index) {\\n\\t\\t\\tconst idNum = parseInt(id, 10);\\n\\t\\t\\tif (this._assets.indexOf(idNum) !== -1) continue;\\n\\t\\t\\tthis._assets.push(idNum);\\n\\t\\t\\tconst asset = this._app.assets.get(idNum);\\n\\t\\t\\tif (!asset) {\\n\\t\\t\\t\\tthis._app.assets.once(`add:${idNum}`, this._onAssetAdd, this);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._onAssetAdd(asset);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget assets() {\\n\\t\\treturn this._assets;\\n\\t}\\n\\tset locale(value) {\\n\\t\\tif (this._locale === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tlet lang = getLang(value);\\n\\t\\tif (lang === \\\"in\\\") {\\n\\t\\t\\tlang = \\\"id\\\";\\n\\t\\t\\tvalue = replaceLang(value, lang);\\n\\t\\t\\tif (this._locale === value) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst old = this._locale;\\n\\t\\tthis._locale = value;\\n\\t\\tthis._lang = lang;\\n\\t\\tthis._pluralFn = getPluralFn(this._lang);\\n\\t\\tthis.fire(I18n.EVENT_CHANGE, value, old);\\n\\t}\\n\\tget locale() {\\n\\t\\treturn this._locale;\\n\\t}\\n\\tstatic findAvailableLocale(desiredLocale, availableLocales) {\\n\\t\\treturn findAvailableLocale(desiredLocale, availableLocales);\\n\\t}\\n\\tfindAvailableLocale(desiredLocale) {\\n\\t\\tif (this._translations[desiredLocale]) {\\n\\t\\t\\treturn desiredLocale;\\n\\t\\t}\\n\\t\\tconst lang = getLang(desiredLocale);\\n\\t\\treturn this._findFallbackLocale(desiredLocale, lang);\\n\\t}\\n\\tgetText(key, locale) {\\n\\t\\tlet result = key;\\n\\t\\tlet lang;\\n\\t\\tif (!locale) {\\n\\t\\t\\tlocale = this._locale;\\n\\t\\t\\tlang = this._lang;\\n\\t\\t}\\n\\t\\tlet translations = this._translations[locale];\\n\\t\\tif (!translations) {\\n\\t\\t\\tif (!lang) {\\n\\t\\t\\t\\tlang = getLang(locale);\\n\\t\\t\\t}\\n\\t\\t\\tlocale = this._findFallbackLocale(locale, lang);\\n\\t\\t\\ttranslations = this._translations[locale];\\n\\t\\t}\\n\\t\\tif (translations && translations.hasOwnProperty(key)) {\\n\\t\\t\\tresult = translations[key];\\n\\t\\t\\tif (Array.isArray(result)) {\\n\\t\\t\\t\\tresult = result[0];\\n\\t\\t\\t}\\n\\t\\t\\tif (result === null || result === void 0) {\\n\\t\\t\\t\\tresult = key;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n\\tgetPluralText(key, n, locale) {\\n\\t\\tlet result = key;\\n\\t\\tlet lang;\\n\\t\\tlet pluralFn;\\n\\t\\tif (!locale) {\\n\\t\\t\\tlocale = this._locale;\\n\\t\\t\\tlang = this._lang;\\n\\t\\t\\tpluralFn = this._pluralFn;\\n\\t\\t} else {\\n\\t\\t\\tlang = getLang(locale);\\n\\t\\t\\tpluralFn = getPluralFn(lang);\\n\\t\\t}\\n\\t\\tlet translations = this._translations[locale];\\n\\t\\tif (!translations) {\\n\\t\\t\\tlocale = this._findFallbackLocale(locale, lang);\\n\\t\\t\\tlang = getLang(locale);\\n\\t\\t\\tpluralFn = getPluralFn(lang);\\n\\t\\t\\ttranslations = this._translations[locale];\\n\\t\\t}\\n\\t\\tif (translations && translations[key] && pluralFn) {\\n\\t\\t\\tconst index = pluralFn(n);\\n\\t\\t\\tresult = translations[key][index];\\n\\t\\t\\tif (result === null || result === void 0) {\\n\\t\\t\\t\\tresult = key;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n\\taddData(data) {\\n\\t\\tlet parsed;\\n\\t\\ttry {\\n\\t\\t\\tparsed = this._parser.parse(data);\\n\\t\\t} catch (err) {\\n\\t\\t\\tconsole.error(`I18n.addData: failed to parse localization data: ${err?.message ?? err}`, err);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tfor (let i = 0, len = parsed.length; i < len; i++) {\\n\\t\\t\\tconst entry = parsed[i];\\n\\t\\t\\tconst locale = entry.info.locale;\\n\\t\\t\\tconst messages = entry.messages;\\n\\t\\t\\tif (!this._translations[locale]) {\\n\\t\\t\\t\\tthis._translations[locale] = {};\\n\\t\\t\\t\\tconst lang = getLang(locale);\\n\\t\\t\\t\\tif (!this._availableLangs[lang]) {\\n\\t\\t\\t\\t\\tthis._availableLangs[lang] = locale;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tObject.assign(this._translations[locale], messages);\\n\\t\\t\\tthis.fire(\\\"data:add\\\", locale, messages);\\n\\t\\t}\\n\\t}\\n\\tremoveData(data) {\\n\\t\\tlet parsed;\\n\\t\\ttry {\\n\\t\\t\\tparsed = this._parser.parse(data);\\n\\t\\t} catch (err) {\\n\\t\\t\\tconsole.error(`I18n.removeData: failed to parse localization data: ${err?.message ?? err}`, err);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tfor (let i = 0, len = parsed.length; i < len; i++) {\\n\\t\\t\\tconst entry = parsed[i];\\n\\t\\t\\tconst locale = entry.info.locale;\\n\\t\\t\\tconst translations = this._translations[locale];\\n\\t\\t\\tif (!translations) continue;\\n\\t\\t\\tconst messages = entry.messages;\\n\\t\\t\\tfor (const key in messages) {\\n\\t\\t\\t\\tdelete translations[key];\\n\\t\\t\\t}\\n\\t\\t\\tif (Object.keys(translations).length === 0) {\\n\\t\\t\\t\\tdelete this._translations[locale];\\n\\t\\t\\t\\tdelete this._availableLangs[getLang(locale)];\\n\\t\\t\\t}\\n\\t\\t\\tthis.fire(\\\"data:remove\\\", locale, messages);\\n\\t\\t}\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._translations = null;\\n\\t\\tthis._availableLangs = null;\\n\\t\\tthis._assets = null;\\n\\t\\tthis._parser = null;\\n\\t\\tthis.off();\\n\\t}\\n\\t// Finds a fallback locale for the specified locale and language.\\n\\t// 1) First tries DEFAULT_LOCALE_FALLBACKS\\n\\t// 2) If no translation exists for that locale return the first locale available for that language.\\n\\t// 3) If no translation exists for that either then return the DEFAULT_LOCALE\\n\\t_findFallbackLocale(locale, lang) {\\n\\t\\tlet result = DEFAULT_LOCALE_FALLBACKS[locale];\\n\\t\\tif (result && this._translations[result]) {\\n\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tresult = DEFAULT_LOCALE_FALLBACKS[lang];\\n\\t\\tif (result && this._translations[result]) {\\n\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tresult = this._availableLangs[lang];\\n\\t\\tif (result && this._translations[result]) {\\n\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\treturn DEFAULT_LOCALE;\\n\\t}\\n\\t_onAssetAdd(asset) {\\n\\t\\tasset.on(\\\"load\\\", this._onAssetLoad, this);\\n\\t\\tasset.on(\\\"change\\\", this._onAssetChange, this);\\n\\t\\tasset.on(\\\"remove\\\", this._onAssetRemove, this);\\n\\t\\tasset.on(\\\"unload\\\", this._onAssetUnload, this);\\n\\t\\tif (asset.resource) {\\n\\t\\t\\tthis._onAssetLoad(asset);\\n\\t\\t}\\n\\t}\\n\\t_onAssetLoad(asset) {\\n\\t\\tthis.addData(asset.resource);\\n\\t}\\n\\t_onAssetChange(asset) {\\n\\t\\tif (asset.resource) {\\n\\t\\t\\tthis.addData(asset.resource);\\n\\t\\t}\\n\\t}\\n\\t_onAssetRemove(asset) {\\n\\t\\tasset.off(\\\"load\\\", this._onAssetLoad, this);\\n\\t\\tasset.off(\\\"change\\\", this._onAssetChange, this);\\n\\t\\tasset.off(\\\"remove\\\", this._onAssetRemove, this);\\n\\t\\tasset.off(\\\"unload\\\", this._onAssetUnload, this);\\n\\t\\tif (asset.resource) {\\n\\t\\t\\tthis.removeData(asset.resource);\\n\\t\\t}\\n\\t\\tthis._app.assets.once(`add:${asset.id}`, this._onAssetAdd, this);\\n\\t}\\n\\t_onAssetUnload(asset) {\\n\\t\\tif (asset.resource) {\\n\\t\\t\\tthis.removeData(asset.resource);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass ScriptRegistry extends EventHandler {\\n\\t_scripts = {};\\n\\t_list = [];\\n\\t_scriptSchemas = /* @__PURE__ */ new Map();\\n\\tconstructor(app) {\\n\\t\\tsuper();\\n\\t\\tthis.app = app;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.app = null;\\n\\t\\tthis.off();\\n\\t}\\n\\taddSchema(id, schema) {\\n\\t\\tif (!schema) return;\\n\\t\\tthis._scriptSchemas.set(id, schema);\\n\\t}\\n\\tgetSchema(id) {\\n\\t\\treturn this._scriptSchemas.get(id);\\n\\t}\\n\\tadd(script) {\\n\\t\\tconst scriptName = script.__name;\\n\\t\\tif (this._scripts.hasOwnProperty(scriptName)) {\\n\\t\\t\\tsetTimeout(() => {\\n\\t\\t\\t\\tif (script.prototype.swap) {\\n\\t\\t\\t\\t\\tconst old = this._scripts[scriptName];\\n\\t\\t\\t\\t\\tconst ind = this._list.indexOf(old);\\n\\t\\t\\t\\t\\tthis._list[ind] = script;\\n\\t\\t\\t\\t\\tthis._scripts[scriptName] = script;\\n\\t\\t\\t\\t\\tthis.fire(\\\"swap\\\", scriptName, script);\\n\\t\\t\\t\\t\\tthis.fire(`swap:${scriptName}`, script);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tconsole.warn(`script registry already has '${scriptName}' script, define 'swap' method for new script type to enable code hot swapping`);\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tthis._scripts[scriptName] = script;\\n\\t\\tthis._list.push(script);\\n\\t\\tthis.fire(\\\"add\\\", scriptName, script);\\n\\t\\tthis.fire(`add:${scriptName}`, script);\\n\\t\\tsetTimeout(() => {\\n\\t\\t\\tif (!this._scripts.hasOwnProperty(scriptName)) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tif (!this.app || !this.app.systems || !this.app.systems.script) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tconst components = this.app.systems.script._components;\\n\\t\\t\\tlet attributes;\\n\\t\\t\\tconst scriptInstances = [];\\n\\t\\t\\tconst scriptInstancesInitialized = [];\\n\\t\\t\\tfor (components.loopIndex = 0; components.loopIndex < components.length; components.loopIndex++) {\\n\\t\\t\\t\\tconst component = components.items[components.loopIndex];\\n\\t\\t\\t\\tif (component._scriptsIndex[scriptName] && component._scriptsIndex[scriptName].awaiting) {\\n\\t\\t\\t\\t\\tif (component._scriptsData && component._scriptsData[scriptName]) {\\n\\t\\t\\t\\t\\t\\tattributes = component._scriptsData[scriptName].attributes;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tconst scriptInstance = component.create(scriptName, {\\n\\t\\t\\t\\t\\t\\tpreloading: true,\\n\\t\\t\\t\\t\\t\\tind: component._scriptsIndex[scriptName].ind,\\n\\t\\t\\t\\t\\t\\tattributes\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\tif (scriptInstance) {\\n\\t\\t\\t\\t\\t\\tscriptInstances.push(scriptInstance);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tfor (const script2 of component.scripts) {\\n\\t\\t\\t\\t\\t\\tcomponent.initializeAttributes(script2);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tfor (let i = 0; i < scriptInstances.length; i++) {\\n\\t\\t\\t\\tif (scriptInstances[i].enabled) {\\n\\t\\t\\t\\t\\tscriptInstances[i]._initialized = true;\\n\\t\\t\\t\\t\\tscriptInstancesInitialized.push(scriptInstances[i]);\\n\\t\\t\\t\\t\\tif (scriptInstances[i].initialize) {\\n\\t\\t\\t\\t\\t\\tscriptInstances[i].initialize();\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tfor (let i = 0; i < scriptInstancesInitialized.length; i++) {\\n\\t\\t\\t\\tif (!scriptInstancesInitialized[i].enabled || scriptInstancesInitialized[i]._postInitialized) {\\n\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tscriptInstancesInitialized[i]._postInitialized = true;\\n\\t\\t\\t\\tif (scriptInstancesInitialized[i].postInitialize) {\\n\\t\\t\\t\\t\\tscriptInstancesInitialized[i].postInitialize();\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\treturn true;\\n\\t}\\n\\tremove(nameOrType) {\\n\\t\\tlet scriptType = nameOrType;\\n\\t\\tlet scriptName = nameOrType;\\n\\t\\tif (typeof scriptName !== \\\"string\\\") {\\n\\t\\t\\tscriptName = scriptType.__name;\\n\\t\\t} else {\\n\\t\\t\\tscriptType = this.get(scriptName);\\n\\t\\t}\\n\\t\\tif (this.get(scriptName) !== scriptType) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tdelete this._scripts[scriptName];\\n\\t\\tconst ind = this._list.indexOf(scriptType);\\n\\t\\tthis._list.splice(ind, 1);\\n\\t\\tthis.fire(\\\"remove\\\", scriptName, scriptType);\\n\\t\\tthis.fire(`remove:${scriptName}`, scriptType);\\n\\t\\treturn true;\\n\\t}\\n\\tget(name) {\\n\\t\\treturn this._scripts[name] || null;\\n\\t}\\n\\thas(nameOrType) {\\n\\t\\tif (typeof nameOrType === \\\"string\\\") {\\n\\t\\t\\treturn this._scripts.hasOwnProperty(nameOrType);\\n\\t\\t}\\n\\t\\tif (!nameOrType) return false;\\n\\t\\tconst scriptName = nameOrType.__name;\\n\\t\\treturn this._scripts[scriptName] === nameOrType;\\n\\t}\\n\\tlist() {\\n\\t\\treturn this._list;\\n\\t}\\n}\\n\\nconst cmpStaticOrder = (a, b) => a.constructor.order - b.constructor.order;\\nconst sortStaticOrder = (arr) => arr.sort(cmpStaticOrder);\\nconst _enableList = [];\\nconst tmpPool = [];\\nconst getTempArray = () => {\\n\\treturn tmpPool.pop() ?? [];\\n};\\nconst releaseTempArray = (a) => {\\n\\ta.length = 0;\\n\\ttmpPool.push(a);\\n};\\nclass Entity extends GraphNode {\\n\\tstatic EVENT_DESTROY = \\\"destroy\\\";\\n\\tanim;\\n\\tanimation;\\n\\taudiolistener;\\n\\tbutton;\\n\\tcamera;\\n\\tcollision;\\n\\telement;\\n\\tgsplat;\\n\\tlayoutchild;\\n\\tlayoutgroup;\\n\\tlight;\\n\\tmodel;\\n\\tparticlesystem;\\n\\trender;\\n\\trigidbody;\\n\\tscreen;\\n\\tscript;\\n\\tscrollbar;\\n\\tscrollview;\\n\\tsound;\\n\\tsprite;\\n\\tc = {};\\n\\t_app;\\n\\t_destroying = false;\\n\\t_guid = null;\\n\\t_template = false;\\n\\tconstructor(name, app = getApplication()) {\\n\\t\\tsuper(name);\\n\\t\\tthis._app = app;\\n\\t}\\n\\taddComponent(type, data) {\\n\\t\\tconst system = this._app.systems[type];\\n\\t\\tif (!system) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tif (this.c[type]) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\treturn system.addComponent(this, data);\\n\\t}\\n\\tremoveComponent(type) {\\n\\t\\tconst system = this._app.systems[type];\\n\\t\\tif (!system) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!this.c[type]) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tsystem.removeComponent(this);\\n\\t}\\n\\tfindComponent(type) {\\n\\t\\tconst entity = this.findOne((entity2) => entity2.c?.[type]);\\n\\t\\treturn entity && entity.c[type];\\n\\t}\\n\\tfindComponents(type) {\\n\\t\\treturn this.find((entity) => entity.c?.[type]).map((entity) => entity.c[type]);\\n\\t}\\n\\tfindScript(nameOrType) {\\n\\t\\tconst entity = this.findOne((node) => node.c?.script?.has(nameOrType));\\n\\t\\treturn entity?.c.script.get(nameOrType);\\n\\t}\\n\\tfindScripts(nameOrType) {\\n\\t\\tconst entities = this.find((node) => node.c?.script?.has(nameOrType));\\n\\t\\treturn entities.map((entity) => entity.c.script.get(nameOrType));\\n\\t}\\n\\tset guid(value) {\\n\\t\\tconst index = this._app._entityIndex;\\n\\t\\tif (this._guid) {\\n\\t\\t\\tdelete index[this._guid];\\n\\t\\t}\\n\\t\\tthis._guid = value;\\n\\t\\tindex[this._guid] = this;\\n\\t}\\n\\tget guid() {\\n\\t\\tif (!this._guid) {\\n\\t\\t\\tthis.guid = guid.create();\\n\\t\\t}\\n\\t\\treturn this._guid;\\n\\t}\\n\\tgetGuid() {\\n\\t\\treturn this.guid;\\n\\t}\\n\\tsetGuid(guid2) {\\n\\t\\tthis.guid = guid2;\\n\\t}\\n\\t_notifyHierarchyStateChanged(node, enabled) {\\n\\t\\tlet enableFirst = false;\\n\\t\\tif (node === this && _enableList.length === 0) {\\n\\t\\t\\tenableFirst = true;\\n\\t\\t}\\n\\t\\tnode._beingEnabled = true;\\n\\t\\tnode._onHierarchyStateChanged(enabled);\\n\\t\\tif (node._onHierarchyStatePostChanged) {\\n\\t\\t\\t_enableList.push(node);\\n\\t\\t}\\n\\t\\tconst c = node._children;\\n\\t\\tfor (let i = 0, len = c.length; i < len; i++) {\\n\\t\\t\\tif (c[i]._enabled) {\\n\\t\\t\\t\\tthis._notifyHierarchyStateChanged(c[i], enabled);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tnode._beingEnabled = false;\\n\\t\\tif (enableFirst) {\\n\\t\\t\\tfor (let i = 0; i < _enableList.length; i++) {\\n\\t\\t\\t\\t_enableList[i]._onHierarchyStatePostChanged();\\n\\t\\t\\t}\\n\\t\\t\\t_enableList.length = 0;\\n\\t\\t}\\n\\t}\\n\\t_onHierarchyStateChanged(enabled) {\\n\\t\\tsuper._onHierarchyStateChanged(enabled);\\n\\t\\tconst components = this._getSortedComponents();\\n\\t\\tfor (let i = 0; i < components.length; i++) {\\n\\t\\t\\tconst component = components[i];\\n\\t\\t\\tif (component.enabled) {\\n\\t\\t\\t\\tif (enabled) {\\n\\t\\t\\t\\t\\tcomponent.onEnable();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tcomponent.onDisable();\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treleaseTempArray(components);\\n\\t}\\n\\t_onHierarchyStatePostChanged() {\\n\\t\\tconst components = this._getSortedComponents();\\n\\t\\tfor (let i = 0; i < components.length; i++) {\\n\\t\\t\\tcomponents[i].onPostStateChange();\\n\\t\\t}\\n\\t\\treleaseTempArray(components);\\n\\t}\\n\\tfindByGuid(guid2) {\\n\\t\\tif (this._guid === guid2) return this;\\n\\t\\tconst e = this._app._entityIndex[guid2];\\n\\t\\tif (e && (e === this || e.isDescendantOf(this))) {\\n\\t\\t\\treturn e;\\n\\t\\t}\\n\\t\\treturn null;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._destroying = true;\\n\\t\\tfor (const name in this.c) {\\n\\t\\t\\tthis.c[name].enabled = false;\\n\\t\\t}\\n\\t\\tfor (const name in this.c) {\\n\\t\\t\\tthis.c[name].system.removeComponent(this);\\n\\t\\t}\\n\\t\\tsuper.destroy();\\n\\t\\tif (this._guid) {\\n\\t\\t\\tdelete this._app._entityIndex[this._guid];\\n\\t\\t}\\n\\t\\tthis._destroying = false;\\n\\t}\\n\\tclone() {\\n\\t\\tconst duplicatedIdsMap = {};\\n\\t\\tconst clone = this._cloneRecursively(duplicatedIdsMap);\\n\\t\\tduplicatedIdsMap[this.guid] = clone;\\n\\t\\tresolveDuplicatedEntityReferenceProperties(this, this, clone, duplicatedIdsMap);\\n\\t\\treturn clone;\\n\\t}\\n\\t_getSortedComponents() {\\n\\t\\tconst components = this.c;\\n\\t\\tconst sortedArray = getTempArray();\\n\\t\\tlet needSort = 0;\\n\\t\\tfor (const type in components) {\\n\\t\\t\\tif (components.hasOwnProperty(type)) {\\n\\t\\t\\t\\tconst component = components[type];\\n\\t\\t\\t\\tneedSort |= component.constructor.order !== 0;\\n\\t\\t\\t\\tsortedArray.push(component);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (needSort && sortedArray.length > 1) {\\n\\t\\t\\tsortStaticOrder(sortedArray);\\n\\t\\t}\\n\\t\\treturn sortedArray;\\n\\t}\\n\\t_cloneRecursively(duplicatedIdsMap) {\\n\\t\\tconst clone = new this.constructor(void 0, this._app);\\n\\t\\tsuper._cloneInternal(clone);\\n\\t\\tfor (const type in this.c) {\\n\\t\\t\\tconst component = this.c[type];\\n\\t\\t\\tcomponent.system.cloneComponent(this, clone);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < this._children.length; i++) {\\n\\t\\t\\tconst oldChild = this._children[i];\\n\\t\\t\\tif (oldChild instanceof Entity) {\\n\\t\\t\\t\\tconst newChild = oldChild._cloneRecursively(duplicatedIdsMap);\\n\\t\\t\\t\\tclone.addChild(newChild);\\n\\t\\t\\t\\tduplicatedIdsMap[oldChild.guid] = newChild;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn clone;\\n\\t}\\n}\\nfunction resolveDuplicatedEntityReferenceProperties(oldSubtreeRoot, oldEntity, newEntity, duplicatedIdsMap) {\\n\\tif (oldEntity instanceof Entity) {\\n\\t\\tconst components = oldEntity.c;\\n\\t\\tfor (const componentName in components) {\\n\\t\\t\\tconst component = components[componentName];\\n\\t\\t\\tconst entityProperties = component.system.getPropertiesOfType(\\\"entity\\\");\\n\\t\\t\\tfor (let i = 0, len = entityProperties.length; i < len; i++) {\\n\\t\\t\\t\\tconst propertyDescriptor = entityProperties[i];\\n\\t\\t\\t\\tconst propertyName = propertyDescriptor.name;\\n\\t\\t\\t\\tconst oldEntityReferenceId = component[propertyName];\\n\\t\\t\\t\\tconst entityIsWithinOldSubtree = !!oldSubtreeRoot.findByGuid(oldEntityReferenceId);\\n\\t\\t\\t\\tif (entityIsWithinOldSubtree) {\\n\\t\\t\\t\\t\\tconst newEntityReferenceId = duplicatedIdsMap[oldEntityReferenceId].guid;\\n\\t\\t\\t\\t\\tif (newEntityReferenceId) {\\n\\t\\t\\t\\t\\t\\tnewEntity.c[componentName][propertyName] = newEntityReferenceId;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (components.script) {\\n\\t\\t\\tnewEntity.script.resolveDuplicatedEntityReferenceProperties(components.script, duplicatedIdsMap);\\n\\t\\t}\\n\\t\\tif (components.render) {\\n\\t\\t\\tnewEntity.render.resolveDuplicatedEntityReferenceProperties(components.render, duplicatedIdsMap);\\n\\t\\t}\\n\\t\\tif (components.button) {\\n\\t\\t\\tnewEntity.button.resolveDuplicatedEntityReferenceProperties(components.button, duplicatedIdsMap);\\n\\t\\t}\\n\\t\\tif (components.scrollview) {\\n\\t\\t\\tnewEntity.scrollview.resolveDuplicatedEntityReferenceProperties(components.scrollview, duplicatedIdsMap);\\n\\t\\t}\\n\\t\\tif (components.scrollbar) {\\n\\t\\t\\tnewEntity.scrollbar.resolveDuplicatedEntityReferenceProperties(components.scrollbar, duplicatedIdsMap);\\n\\t\\t}\\n\\t\\tif (components.anim) {\\n\\t\\t\\tnewEntity.anim.resolveDuplicatedEntityReferenceProperties(components.anim, duplicatedIdsMap);\\n\\t\\t}\\n\\t\\tconst _old = oldEntity.children.filter((e) => e instanceof Entity);\\n\\t\\tconst _new = newEntity.children.filter((e) => e instanceof Entity);\\n\\t\\tfor (let i = 0, len = _old.length; i < len; i++) {\\n\\t\\t\\tresolveDuplicatedEntityReferenceProperties(oldSubtreeRoot, _old[i], _new[i], duplicatedIdsMap);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass SceneRegistryItem {\\n\\tname;\\n\\turl;\\n\\tdata = null;\\n\\t_loading = false;\\n\\t_onLoadedCallbacks = [];\\n\\tconstructor(name, url) {\\n\\t\\tthis.name = name;\\n\\t\\tthis.url = url;\\n\\t}\\n\\tget loaded() {\\n\\t\\treturn !!this.data;\\n\\t}\\n\\tget loading() {\\n\\t\\treturn this._loading;\\n\\t}\\n}\\n\\nclass SceneRegistry {\\n\\t_app;\\n\\t_list = [];\\n\\t_index = {};\\n\\t_urlIndex = {};\\n\\tconstructor(app) {\\n\\t\\tthis._app = app;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._app = null;\\n\\t}\\n\\tlist() {\\n\\t\\treturn this._list;\\n\\t}\\n\\tadd(name, url) {\\n\\t\\tif (this._index.hasOwnProperty(name)) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tconst item = new SceneRegistryItem(name, url);\\n\\t\\tconst i = this._list.push(item);\\n\\t\\tthis._index[item.name] = i - 1;\\n\\t\\tthis._urlIndex[item.url] = i - 1;\\n\\t\\treturn true;\\n\\t}\\n\\tfind(name) {\\n\\t\\tif (this._index.hasOwnProperty(name)) {\\n\\t\\t\\treturn this._list[this._index[name]];\\n\\t\\t}\\n\\t\\treturn null;\\n\\t}\\n\\tfindByUrl(url) {\\n\\t\\tif (this._urlIndex.hasOwnProperty(url)) {\\n\\t\\t\\treturn this._list[this._urlIndex[url]];\\n\\t\\t}\\n\\t\\treturn null;\\n\\t}\\n\\tremove(name) {\\n\\t\\tif (this._index.hasOwnProperty(name)) {\\n\\t\\t\\tconst idx = this._index[name];\\n\\t\\t\\tlet item = this._list[idx];\\n\\t\\t\\tdelete this._urlIndex[item.url];\\n\\t\\t\\tdelete this._index[name];\\n\\t\\t\\tthis._list.splice(idx, 1);\\n\\t\\t\\tfor (let i = 0; i < this._list.length; i++) {\\n\\t\\t\\t\\titem = this._list[i];\\n\\t\\t\\t\\tthis._index[item.name] = i;\\n\\t\\t\\t\\tthis._urlIndex[item.url] = i;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_loadSceneData(sceneItem, storeInCache, callback) {\\n\\t\\tconst app = this._app;\\n\\t\\tlet url = sceneItem;\\n\\t\\tif (typeof sceneItem === \\\"string\\\") {\\n\\t\\t\\tsceneItem = this.findByUrl(url) || this.find(url) || new SceneRegistryItem(\\\"Untitled\\\", url);\\n\\t\\t}\\n\\t\\turl = sceneItem.url;\\n\\t\\tif (!url) {\\n\\t\\t\\tcallback(\\\"Cannot find scene to load\\\");\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (sceneItem.loaded) {\\n\\t\\t\\tcallback(null, sceneItem);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (app.assets && app.assets.prefix && !ABSOLUTE_URL.test(url)) {\\n\\t\\t\\turl = path.join(app.assets.prefix, url);\\n\\t\\t}\\n\\t\\tsceneItem._onLoadedCallbacks.push(callback);\\n\\t\\tif (!sceneItem._loading) {\\n\\t\\t\\tconst handler = app.loader.getHandler(\\\"hierarchy\\\");\\n\\t\\t\\thandler.load(url, (err, data) => {\\n\\t\\t\\t\\tsceneItem.data = data;\\n\\t\\t\\t\\tsceneItem._loading = false;\\n\\t\\t\\t\\tfor (let i = 0; i < sceneItem._onLoadedCallbacks.length; i++) {\\n\\t\\t\\t\\t\\tsceneItem._onLoadedCallbacks[i](err, sceneItem);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!storeInCache) {\\n\\t\\t\\t\\t\\tsceneItem.data = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tsceneItem._onLoadedCallbacks.length = 0;\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tsceneItem._loading = true;\\n\\t}\\n\\tloadSceneData(sceneItem, callback) {\\n\\t\\tthis._loadSceneData(sceneItem, true, callback);\\n\\t}\\n\\tunloadSceneData(sceneItem) {\\n\\t\\tif (typeof sceneItem === \\\"string\\\") {\\n\\t\\t\\tsceneItem = this.findByUrl(sceneItem);\\n\\t\\t}\\n\\t\\tif (sceneItem) {\\n\\t\\t\\tsceneItem.data = null;\\n\\t\\t}\\n\\t}\\n\\t_loadSceneHierarchy(sceneItem, onBeforeAddHierarchy, callback) {\\n\\t\\tthis._loadSceneData(sceneItem, false, (err, sceneItem2) => {\\n\\t\\t\\tif (err) {\\n\\t\\t\\t\\tif (callback) {\\n\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tif (onBeforeAddHierarchy) {\\n\\t\\t\\t\\tonBeforeAddHierarchy(sceneItem2);\\n\\t\\t\\t}\\n\\t\\t\\tconst app = this._app;\\n\\t\\t\\tconst _loaded = () => {\\n\\t\\t\\t\\tconst handler = app.loader.getHandler(\\\"hierarchy\\\");\\n\\t\\t\\t\\tapp.systems.script.preloading = true;\\n\\t\\t\\t\\tconst entity = handler.open(sceneItem2.url, sceneItem2.data);\\n\\t\\t\\t\\tapp.systems.script.preloading = false;\\n\\t\\t\\t\\tapp.loader.clearCache(sceneItem2.url, \\\"hierarchy\\\");\\n\\t\\t\\t\\tapp.root.addChild(entity);\\n\\t\\t\\t\\tapp.systems.fire(\\\"initialize\\\", entity);\\n\\t\\t\\t\\tapp.systems.fire(\\\"postInitialize\\\", entity);\\n\\t\\t\\t\\tapp.systems.fire(\\\"postPostInitialize\\\", entity);\\n\\t\\t\\t\\tif (callback) callback(null, entity);\\n\\t\\t\\t};\\n\\t\\t\\tapp._preloadScripts(sceneItem2.data, _loaded);\\n\\t\\t});\\n\\t}\\n\\tloadSceneHierarchy(sceneItem, callback) {\\n\\t\\tthis._loadSceneHierarchy(sceneItem, null, callback);\\n\\t}\\n\\tloadSceneSettings(sceneItem, callback) {\\n\\t\\tthis._loadSceneData(sceneItem, false, (err, sceneItem2) => {\\n\\t\\t\\tif (!err) {\\n\\t\\t\\t\\tthis._app.applySceneSettings(sceneItem2.data.settings);\\n\\t\\t\\t\\tif (callback) {\\n\\t\\t\\t\\t\\tcallback(null);\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (callback) {\\n\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n\\tchangeScene(sceneItem, callback) {\\n\\t\\tconst app = this._app;\\n\\t\\tconst onBeforeAddHierarchy = (sceneItem2) => {\\n\\t\\t\\tconst { children } = app.root;\\n\\t\\t\\twhile (children.length) {\\n\\t\\t\\t\\tchildren[0].destroy();\\n\\t\\t\\t}\\n\\t\\t\\tapp.applySceneSettings(sceneItem2.data.settings);\\n\\t\\t};\\n\\t\\tthis._loadSceneHierarchy(sceneItem, onBeforeAddHierarchy, callback);\\n\\t}\\n\\tloadScene(url, callback) {\\n\\t\\tconst app = this._app;\\n\\t\\tconst handler = app.loader.getHandler(\\\"scene\\\");\\n\\t\\tif (app.assets && app.assets.prefix && !ABSOLUTE_URL.test(url)) {\\n\\t\\t\\turl = path.join(app.assets.prefix, url);\\n\\t\\t}\\n\\t\\thandler.load(url, (err, data) => {\\n\\t\\t\\tif (!err) {\\n\\t\\t\\t\\tconst _loaded = () => {\\n\\t\\t\\t\\t\\tapp.systems.script.preloading = true;\\n\\t\\t\\t\\t\\tconst scene = handler.open(url, data);\\n\\t\\t\\t\\t\\tconst sceneItem = this.findByUrl(url);\\n\\t\\t\\t\\t\\tif (sceneItem && !sceneItem.loaded) {\\n\\t\\t\\t\\t\\t\\tsceneItem.data = data;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tapp.systems.script.preloading = false;\\n\\t\\t\\t\\t\\tapp.loader.clearCache(url, \\\"scene\\\");\\n\\t\\t\\t\\t\\tapp.loader.patch({\\n\\t\\t\\t\\t\\t\\tresource: scene,\\n\\t\\t\\t\\t\\t\\ttype: \\\"scene\\\"\\n\\t\\t\\t\\t\\t}, app.assets);\\n\\t\\t\\t\\t\\tapp.root.addChild(scene.root);\\n\\t\\t\\t\\t\\tif (app.systems.rigidbody && typeof Ammo !== \\\"undefined\\\") {\\n\\t\\t\\t\\t\\t\\tapp.systems.rigidbody.gravity.set(scene._gravity.x, scene._gravity.y, scene._gravity.z);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (callback) {\\n\\t\\t\\t\\t\\t\\tcallback(null, scene);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tapp._preloadScripts(data, _loaded);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (callback) {\\n\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n}\\n\\nclass ApplicationStats {\\n\\tconstructor(device) {\\n\\t\\tthis.frame = {\\n\\t\\t\\tfps: 0,\\n\\t\\t\\tms: 0,\\n\\t\\t\\tdt: 0,\\n\\t\\t\\tupdateStart: 0,\\n\\t\\t\\tupdateTime: 0,\\n\\t\\t\\trenderStart: 0,\\n\\t\\t\\trenderTime: 0,\\n\\t\\t\\tphysicsStart: 0,\\n\\t\\t\\tphysicsTime: 0,\\n\\t\\t\\tscriptUpdateStart: 0,\\n\\t\\t\\tscriptUpdate: 0,\\n\\t\\t\\tscriptPostUpdateStart: 0,\\n\\t\\t\\tscriptPostUpdate: 0,\\n\\t\\t\\tanimUpdateStart: 0,\\n\\t\\t\\tanimUpdate: 0,\\n\\t\\t\\tcullTime: 0,\\n\\t\\t\\tsortTime: 0,\\n\\t\\t\\tskinTime: 0,\\n\\t\\t\\tmorphTime: 0,\\n\\t\\t\\tinstancingTime: 0,\\n\\t\\t\\t// deprecated\\n\\t\\t\\ttriangles: 0,\\n\\t\\t\\tgsplats: 0,\\n\\t\\t\\tgsplatSort: 0,\\n\\t\\t\\tgsplatBufferCopy: 0,\\n\\t\\t\\totherPrimitives: 0,\\n\\t\\t\\tshaders: 0,\\n\\t\\t\\tmaterials: 0,\\n\\t\\t\\tcameras: 0,\\n\\t\\t\\tshadowMapUpdates: 0,\\n\\t\\t\\tshadowMapTime: 0,\\n\\t\\t\\tdepthMapTime: 0,\\n\\t\\t\\t// deprecated\\n\\t\\t\\tforwardTime: 0,\\n\\t\\t\\tlightClustersTime: 0,\\n\\t\\t\\tlightClusters: 0,\\n\\t\\t\\t_timeToCountFrames: 0,\\n\\t\\t\\t_fpsAccum: 0\\n\\t\\t};\\n\\t\\tthis.drawCalls = {\\n\\t\\t\\tforward: 0,\\n\\t\\t\\tdepth: 0,\\n\\t\\t\\t// deprecated\\n\\t\\t\\tshadow: 0,\\n\\t\\t\\timmediate: 0,\\n\\t\\t\\t// deprecated\\n\\t\\t\\tmisc: 0,\\n\\t\\t\\t// everything that is not forward/depth/shadow (post effect quads etc)\\n\\t\\t\\ttotal: 0,\\n\\t\\t\\t// total = forward + depth + shadow + misc\\n\\t\\t\\t// Some of forward/depth/shadow/misc draw calls:\\n\\t\\t\\tskinned: 0,\\n\\t\\t\\tinstanced: 0,\\n\\t\\t\\t// deprecated\\n\\t\\t\\tremovedByInstancing: 0\\n\\t\\t\\t// deprecated\\n\\t\\t};\\n\\t\\tthis.misc = {\\n\\t\\t\\trenderTargetCreationTime: 0\\n\\t\\t};\\n\\t\\tthis.particles = {\\n\\t\\t\\tupdatesPerFrame: 0,\\n\\t\\t\\t_updatesPerFrame: 0,\\n\\t\\t\\tframeTime: 0,\\n\\t\\t\\t_frameTime: 0\\n\\t\\t};\\n\\t\\tthis.shaders = device._shaderStats;\\n\\t\\tthis.vram = device._vram;\\n\\t\\tthis.gpu = device.gpuProfiler?.passTimings ?? /* @__PURE__ */ new Map();\\n\\t\\tObject.defineProperty(this.vram, \\\"totalUsed\\\", {\\n\\t\\t\\tget: function() {\\n\\t\\t\\t\\treturn this.tex + this.vb + this.ib + this.ub + this.sb;\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tObject.defineProperty(this.vram, \\\"geom\\\", {\\n\\t\\t\\tget: function() {\\n\\t\\t\\t\\treturn this.vb + this.ib;\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tObject.defineProperty(this.vram, \\\"buffers\\\", {\\n\\t\\t\\tget: function() {\\n\\t\\t\\t\\treturn this.ub + this.sb;\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n\\tget scene() {\\n\\t\\treturn getApplication().scene._stats;\\n\\t}\\n\\tget lightmapper() {\\n\\t\\treturn getApplication().lightmapper?.stats;\\n\\t}\\n\\tget batcher() {\\n\\t\\tconst batcher = getApplication()._batcher;\\n\\t\\treturn batcher ? batcher._stats : null;\\n\\t}\\n\\tupdateBasic(now, dt, ms, renderer, device) {\\n\\t\\tconst stats = this.frame;\\n\\t\\tstats.dt = dt;\\n\\t\\tstats.ms = ms;\\n\\t\\tif (now > stats._timeToCountFrames) {\\n\\t\\t\\tstats.fps = stats._fpsAccum;\\n\\t\\t\\tstats._fpsAccum = 0;\\n\\t\\t\\tstats._timeToCountFrames = now + 1e3;\\n\\t\\t} else {\\n\\t\\t\\tstats._fpsAccum++;\\n\\t\\t}\\n\\t\\tthis.drawCalls.total = device._drawCallsPerFrame;\\n\\t\\tdevice._drawCallsPerFrame = 0;\\n\\t\\tstats.gsplats = renderer._gsplatCount;\\n\\t\\tstats.gsplatBufferCopy = renderer._gsplatBufferCopy ?? 0;\\n\\t}\\n\\tupdateDetailed(renderer, device) {\\n\\t\\tlet stats = this.frame;\\n\\t\\tstats.cameras = renderer._camerasRendered;\\n\\t\\tstats.materials = renderer._materialSwitches;\\n\\t\\tstats.shaders = device._shaderSwitchesPerFrame;\\n\\t\\tstats.shadowMapUpdates = renderer._shadowMapUpdates;\\n\\t\\tstats.shadowMapTime = renderer._shadowMapTime;\\n\\t\\tstats.depthMapTime = renderer._depthMapTime;\\n\\t\\tstats.forwardTime = renderer._forwardTime;\\n\\t\\tconst prims = device._primsPerFrame;\\n\\t\\tstats.triangles = prims[PRIMITIVE_TRIANGLES] / 3 + Math.max(prims[PRIMITIVE_TRISTRIP] - 2, 0) + Math.max(prims[PRIMITIVE_TRIFAN] - 2, 0);\\n\\t\\tstats.cullTime = renderer._cullTime;\\n\\t\\tstats.sortTime = renderer._sortTime;\\n\\t\\tstats.skinTime = renderer._skinTime;\\n\\t\\tstats.morphTime = renderer._morphTime;\\n\\t\\tstats.lightClusters = renderer._lightClusters;\\n\\t\\tstats.lightClustersTime = renderer._lightClustersTime;\\n\\t\\tstats.otherPrimitives = 0;\\n\\t\\tfor (let i = 0; i < prims.length; i++) {\\n\\t\\t\\tif (i < PRIMITIVE_TRIANGLES) {\\n\\t\\t\\t\\tstats.otherPrimitives += prims[i];\\n\\t\\t\\t}\\n\\t\\t\\tprims[i] = 0;\\n\\t\\t}\\n\\t\\trenderer._camerasRendered = 0;\\n\\t\\trenderer._materialSwitches = 0;\\n\\t\\trenderer._shadowMapUpdates = 0;\\n\\t\\tdevice._shaderSwitchesPerFrame = 0;\\n\\t\\trenderer._cullTime = 0;\\n\\t\\trenderer._layerCompositionUpdateTime = 0;\\n\\t\\trenderer._lightClustersTime = 0;\\n\\t\\trenderer._sortTime = 0;\\n\\t\\trenderer._skinTime = 0;\\n\\t\\trenderer._morphTime = 0;\\n\\t\\trenderer._shadowMapTime = 0;\\n\\t\\trenderer._depthMapTime = 0;\\n\\t\\trenderer._forwardTime = 0;\\n\\t\\tstats = this.drawCalls;\\n\\t\\tstats.forward = renderer._forwardDrawCalls;\\n\\t\\tstats.culled = renderer._numDrawCallsCulled;\\n\\t\\tstats.depth = 0;\\n\\t\\tstats.shadow = renderer._shadowDrawCalls;\\n\\t\\tstats.skinned = renderer._skinDrawCalls;\\n\\t\\tstats.immediate = 0;\\n\\t\\tstats.instanced = 0;\\n\\t\\tstats.removedByInstancing = 0;\\n\\t\\tstats.misc = stats.total - (stats.forward + stats.shadow);\\n\\t\\trenderer._depthDrawCalls = 0;\\n\\t\\trenderer._shadowDrawCalls = 0;\\n\\t\\trenderer._forwardDrawCalls = 0;\\n\\t\\trenderer._numDrawCallsCulled = 0;\\n\\t\\trenderer._skinDrawCalls = 0;\\n\\t\\trenderer._immediateRendered = 0;\\n\\t\\trenderer._instancedDrawCalls = 0;\\n\\t\\tthis.misc.renderTargetCreationTime = device.renderTargetCreationTime;\\n\\t\\tstats = this.particles;\\n\\t\\tstats.updatesPerFrame = stats._updatesPerFrame;\\n\\t\\tstats.frameTime = stats._frameTime;\\n\\t\\tstats._updatesPerFrame = 0;\\n\\t\\tstats._frameTime = 0;\\n\\t}\\n\\tframeEnd() {\\n\\t\\tthis.frame.gsplatSort = 0;\\n\\t}\\n}\\n\\nvar alphaTest_default$1 = `\\nuniform float alpha_ref;\\nvoid alphaTest(float a) {\\n\\tif (a < alpha_ref) discard;\\n}\\n`;\\n\\nvar ambient_default$1 = `\\n#ifdef LIT_AMBIENT_SOURCE == AMBIENTSH\\n\\tuniform vec3 ambientSH[9];\\n#endif\\n#if LIT_AMBIENT_SOURCE == ENVALATLAS\\n\\t#include \\\"envAtlasPS\\\"\\n\\t#ifndef ENV_ATLAS\\n\\t#define ENV_ATLAS\\n\\t\\tuniform sampler2D texture_envAtlas;\\n\\t#endif\\n#endif\\nvoid addAmbient(vec3 worldNormal) {\\n\\t#ifdef LIT_AMBIENT_SOURCE == AMBIENTSH\\n\\t\\tvec3 n = cubeMapRotate(worldNormal);\\n\\t\\tvec3 color =\\n\\t\\t\\tambientSH[0] +\\n\\t\\t\\tambientSH[1] * n.x +\\n\\t\\t\\tambientSH[2] * n.y +\\n\\t\\t\\tambientSH[3] * n.z +\\n\\t\\t\\tambientSH[4] * n.x * n.z +\\n\\t\\t\\tambientSH[5] * n.z * n.y +\\n\\t\\t\\tambientSH[6] * n.y * n.x +\\n\\t\\t\\tambientSH[7] * (3.0 * n.z * n.z - 1.0) +\\n\\t\\t\\tambientSH[8] * (n.x * n.x - n.y * n.y);\\n\\t\\tdDiffuseLight += processEnvironment(max(color, vec3(0.0)));\\n\\t#endif\\n\\t#if LIT_AMBIENT_SOURCE == ENVALATLAS\\n\\t\\tvec3 dir = normalize(cubeMapRotate(worldNormal) * vec3(-1.0, 1.0, 1.0));\\n\\t\\tvec2 uv = mapUv(toSphericalUv(dir), vec4(128.0, 256.0 + 128.0, 64.0, 32.0) / atlasSize);\\n\\t\\tvec4 raw = texture2D(texture_envAtlas, uv);\\n\\t\\tvec3 linear = {ambientDecode}(raw);\\n\\t\\tdDiffuseLight += processEnvironment(linear);\\n\\t#endif\\n\\t#if LIT_AMBIENT_SOURCE == CONSTANT\\n\\t\\tdDiffuseLight += light_globalAmbient;\\n\\t#endif\\n}\\n`;\\n\\nvar anisotropy_default$1 = `\\n#ifdef LIT_GGX_SPECULAR\\n\\tuniform float material_anisotropyIntensity;\\n\\tuniform vec2 material_anisotropyRotation;\\n#endif\\nvoid getAnisotropy() {\\n\\tdAnisotropy = 0.0;\\n\\tdAnisotropyRotation = vec2(1.0, 0.0);\\n#ifdef LIT_GGX_SPECULAR\\n\\tdAnisotropy = material_anisotropyIntensity;\\n\\tdAnisotropyRotation = material_anisotropyRotation;\\n#endif\\n\\t#ifdef STD_ANISOTROPY_TEXTURE\\n\\tvec3 anisotropyTex = texture2DBias({STD_ANISOTROPY_TEXTURE_NAME}, {STD_ANISOTROPY_TEXTURE_UV}, textureBias).rgb;\\n\\tdAnisotropy *= anisotropyTex.b;\\n\\tvec2 anisotropyRotationFromTex = anisotropyTex.rg * 2.0 - vec2(1.0);\\n\\tmat2 rotationMatrix = mat2(dAnisotropyRotation.x, dAnisotropyRotation.y, -dAnisotropyRotation.y, dAnisotropyRotation.x);\\n\\tdAnisotropyRotation = rotationMatrix * anisotropyRotationFromTex;\\n\\t#endif\\n\\t\\n\\tdAnisotropy = clamp(dAnisotropy, 0.0, 1.0);\\n}\\n`;\\n\\nvar ao_default$1 = `\\n#if defined(STD_AO_TEXTURE) || defined(STD_AO_VERTEX)\\n\\tuniform float material_aoIntensity;\\n#endif\\n#ifdef STD_AODETAIL_TEXTURE\\n\\t#include \\\"detailModesPS\\\"\\n#endif\\nvoid getAO() {\\n\\tdAo = 1.0;\\n\\t#ifdef STD_AO_TEXTURE\\n\\t\\tfloat aoBase = texture2DBias({STD_AO_TEXTURE_NAME}, {STD_AO_TEXTURE_UV}, textureBias).{STD_AO_TEXTURE_CHANNEL};\\n\\t\\t#ifdef STD_AODETAIL_TEXTURE\\n\\t\\t\\tfloat aoDetail = texture2DBias({STD_AODETAIL_TEXTURE_NAME}, {STD_AODETAIL_TEXTURE_UV}, textureBias).{STD_AODETAIL_TEXTURE_CHANNEL};\\n\\t\\t\\taoBase = detailMode_{STD_AODETAIL_DETAILMODE}(vec3(aoBase), vec3(aoDetail)).r;\\n\\t\\t#endif\\n\\t\\tdAo *= aoBase;\\n\\t#endif\\n\\t#ifdef STD_AO_VERTEX\\n\\t\\tdAo *= saturate(vVertexColor.{STD_AO_VERTEX_CHANNEL});\\n\\t#endif\\n\\t#if defined(STD_AO_TEXTURE) || defined(STD_AO_VERTEX)\\n\\t\\tdAo = mix(1.0, dAo, material_aoIntensity);\\n\\t#endif\\n}\\n`;\\n\\nvar aoDiffuseOcc_default$1 = `\\nvoid occludeDiffuse(float ao) {\\n\\tdDiffuseLight *= ao;\\n}\\n`;\\n\\nvar aoSpecOcc_default$1 = `\\n#if LIT_OCCLUDE_SPECULAR != NONE\\n\\t#ifdef LIT_OCCLUDE_SPECULAR_FLOAT\\n\\t\\tuniform float material_occludeSpecularIntensity;\\n\\t#endif\\n#endif\\nvoid occludeSpecular(float gloss, float ao, vec3 worldNormal, vec3 viewDir) {\\n\\t#if LIT_OCCLUDE_SPECULAR == AO\\n\\t\\t#ifdef LIT_OCCLUDE_SPECULAR_FLOAT\\n\\t\\t\\tfloat specOcc = mix(1.0, ao, material_occludeSpecularIntensity);\\n\\t\\t#else\\n\\t\\t\\tfloat specOcc = ao;\\n\\t\\t#endif\\n\\t#endif\\n\\t#if LIT_OCCLUDE_SPECULAR == GLOSSDEPENDENT\\n\\t\\tfloat specPow = exp2(gloss * 11.0);\\n\\t\\tfloat specOcc = saturate(pow(dot(worldNormal, viewDir) + ao, 0.01 * specPow) - 1.0 + ao);\\n\\t\\t#ifdef LIT_OCCLUDE_SPECULAR_FLOAT\\n\\t\\t\\tspecOcc = mix(1.0, specOcc, material_occludeSpecularIntensity);\\n\\t\\t#endif\\n\\t#endif\\n\\t#if LIT_OCCLUDE_SPECULAR != NONE\\n\\t\\tdSpecularLight *= specOcc;\\n\\t\\tdReflection *= specOcc;\\n\\t\\t#ifdef LIT_SHEEN\\n\\t\\t\\tsSpecularLight *= specOcc;\\n\\t\\t\\tsReflection *= specOcc;\\n\\t\\t#endif\\n\\t#endif\\n}\\n`;\\n\\nvar bakeDirLmEnd_default$1 = `\\n\\tvec4 dirLm = texture2D(texture_dirLightMap, vUv1);\\n\\tif (bakeDir > 0.5) {\\n\\t\\tif (dAtten > 0.00001) {\\n\\t\\t\\tdirLm.xyz = dirLm.xyz * 2.0 - vec3(1.0);\\n\\t\\t\\tdAtten = saturate(dAtten);\\n\\t\\t\\tgl_FragColor.rgb = normalize(dLightDirNormW.xyz*dAtten + dirLm.xyz*dirLm.w) * 0.5 + vec3(0.5);\\n\\t\\t\\tgl_FragColor.a = dirLm.w + dAtten;\\n\\t\\t\\tgl_FragColor.a = max(gl_FragColor.a, 1.0 / 255.0);\\n\\t\\t} else {\\n\\t\\t\\tgl_FragColor = dirLm;\\n\\t\\t}\\n\\t} else {\\n\\t\\tgl_FragColor.rgb = dirLm.xyz;\\n\\t\\tgl_FragColor.a = max(dirLm.w, dAtten > 0.00001 ? (1.0/255.0) : 0.0);\\n\\t}\\n`;\\n\\nvar bakeLmEnd_default$1 = `\\n#ifdef LIT_LIGHTMAP_BAKING_ADD_AMBIENT\\n\\tdDiffuseLight = ((dDiffuseLight - 0.5) * max(ambientBakeOcclusionContrast + 1.0, 0.0)) + 0.5;\\n\\tdDiffuseLight += vec3(ambientBakeOcclusionBrightness);\\n\\tdDiffuseLight = saturate(dDiffuseLight);\\n\\tdDiffuseLight *= dAmbientLight;\\n#endif\\n#ifdef LIGHTMAP_RGBM\\n\\tgl_FragColor.rgb = dDiffuseLight;\\n\\tgl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(0.5));\\n\\tgl_FragColor.rgb /= 8.0;\\n\\tgl_FragColor.a = clamp( max( max( gl_FragColor.r, gl_FragColor.g ), max( gl_FragColor.b, 1.0 / 255.0 ) ), 0.0,1.0 );\\n\\tgl_FragColor.a = ceil(gl_FragColor.a * 255.0) / 255.0;\\n\\tgl_FragColor.rgb /= gl_FragColor.a;\\n#else\\n\\tgl_FragColor = vec4(dDiffuseLight, 1.0);\\n#endif\\n`;\\n\\nvar base_default$1 = `\\nuniform vec3 view_position;\\nuniform vec3 light_globalAmbient;\\nfloat square(float x) {\\n\\treturn x*x;\\n}\\nfloat saturate(float x) {\\n\\treturn clamp(x, 0.0, 1.0);\\n}\\nvec3 saturate(vec3 x) {\\n\\treturn clamp(x, vec3(0.0), vec3(1.0));\\n}\\n`;\\n\\nvar baseNineSliced_default$1 = `\\n#define NINESLICED\\nvarying vec2 vMask;\\nvarying vec2 vTiledUv;\\nuniform mediump vec4 innerOffset;\\nuniform mediump vec2 outerScale;\\nuniform mediump vec4 atlasRect;\\nvec2 nineSlicedUv;\\n`;\\n\\nvar baseNineSlicedTiled_default$1 = `\\n#define NINESLICED\\n#define NINESLICETILED\\nvarying vec2 vMask;\\nvarying vec2 vTiledUv;\\nuniform mediump vec4 innerOffset;\\nuniform mediump vec2 outerScale;\\nuniform mediump vec4 atlasRect;\\nvec2 nineSlicedUv;\\n`;\\n\\nvar bayer_default$1 = `\\nfloat bayer2(vec2 p) {\\n\\treturn mod(2.0 * p.y + p.x + 1.0, 4.0);\\n}\\nfloat bayer4(vec2 p) {\\n\\tvec2 p1 = mod(p, 2.0);\\n\\tvec2 p2 = floor(0.5 * mod(p, 4.0));\\n\\treturn 4.0 * bayer2(p1) + bayer2(p2);\\n}\\nfloat bayer8(vec2 p) {\\n\\tvec2 p1 = mod(p, 2.0);\\n\\tvec2 p2 = floor(0.5 * mod(p, 4.0));\\n\\tvec2 p4 = floor(0.25 * mod(p, 8.0));\\n\\treturn 4.0 * (4.0 * bayer2(p1) + bayer2(p2)) + bayer2(p4);\\n}\\n`;\\n\\nvar blurVSM_default$1 = `\\nvarying vec2 vUv0;\\nuniform sampler2D source;\\nuniform vec2 pixelOffset;\\n#ifdef GAUSS\\n\\tuniform float weight[{SAMPLES}];\\n#endif\\nvoid main(void) {\\n\\tvec3 moments = vec3(0.0);\\n\\tvec2 uv = vUv0 - pixelOffset * (float({SAMPLES}) * 0.5);\\n\\tfor (int i = 0; i < {SAMPLES}; i++) {\\n\\t\\tvec4 c = texture2D(source, uv + pixelOffset * float(i));\\n\\t\\t#ifdef GAUSS\\n\\t\\t\\tmoments += c.xyz * weight[i];\\n\\t\\t#else\\n\\t\\t\\tmoments += c.xyz;\\n\\t\\t#endif\\n\\t}\\n\\t#ifndef GAUSS\\n\\t\\tmoments *= 1.0 / float({SAMPLES});\\n\\t#endif\\n\\tgl_FragColor = vec4(moments.x, moments.y, moments.z, 1.0);\\n}\\n`;\\n\\nvar clearCoat_default$1 = `\\nuniform float material_clearCoat;\\nvoid getClearCoat() {\\n\\tccSpecularity = material_clearCoat;\\n\\t#ifdef STD_CLEARCOAT_TEXTURE\\n\\tccSpecularity *= texture2DBias({STD_CLEARCOAT_TEXTURE_NAME}, {STD_CLEARCOAT_TEXTURE_UV}, textureBias).{STD_CLEARCOAT_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_CLEARCOAT_VERTEX\\n\\tccSpecularity *= saturate(vVertexColor.{STD_CLEARCOAT_VERTEX_CHANNEL});\\n\\t#endif\\n}\\n`;\\n\\nvar clearCoatGloss_default$1 = `\\nuniform float material_clearCoatGloss;\\nvoid getClearCoatGlossiness() {\\n\\tccGlossiness = material_clearCoatGloss;\\n\\t#ifdef STD_CLEARCOATGLOSS_TEXTURE\\n\\tccGlossiness *= texture2DBias({STD_CLEARCOATGLOSS_TEXTURE_NAME}, {STD_CLEARCOATGLOSS_TEXTURE_UV}, textureBias).{STD_CLEARCOATGLOSS_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_CLEARCOATGLOSS_VERTEX\\n\\tccGlossiness *= saturate(vVertexColor.{STD_CLEARCOATGLOSS_VERTEX_CHANNEL});\\n\\t#endif\\n\\t#ifdef STD_CLEARCOATGLOSS_INVERT\\n\\tccGlossiness = 1.0 - ccGlossiness;\\n\\t#endif\\n\\tccGlossiness += 0.0000001;\\n}\\n`;\\n\\nvar clearCoatNormal_default$1 = `\\n#ifdef STD_CLEARCOATNORMAL_TEXTURE\\nuniform float material_clearCoatBumpiness;\\n#endif\\nvoid getClearCoatNormal() {\\n#ifdef STD_CLEARCOATNORMAL_TEXTURE\\n\\tvec3 normalMap = {STD_CLEARCOATNORMAL_TEXTURE_DECODE}(texture2DBias({STD_CLEARCOATNORMAL_TEXTURE_NAME}, {STD_CLEARCOATNORMAL_TEXTURE_UV}, textureBias));\\n\\tnormalMap = mix(vec3(0.0, 0.0, 1.0), normalMap, material_clearCoatBumpiness);\\n\\tccNormalW = normalize(dTBN * normalMap);\\n#else\\n\\tccNormalW = dVertexNormalW;\\n#endif\\n}\\n`;\\n\\nvar clusteredLightUtils_default$1 = `\\nvec2 getCubemapFaceCoordinates(const vec3 dir, out float faceIndex, out vec2 tileOffset)\\n{\\n\\tvec3 vAbs = abs(dir);\\n\\tfloat ma;\\n\\tvec2 uv;\\n\\tif (vAbs.z >= vAbs.x && vAbs.z >= vAbs.y) {\\n\\t\\tfaceIndex = dir.z < 0.0 ? 5.0 : 4.0;\\n\\t\\tma = 0.5 / vAbs.z;\\n\\t\\tuv = vec2(dir.z < 0.0 ? -dir.x : dir.x, -dir.y);\\n\\t\\ttileOffset.x = 2.0;\\n\\t\\ttileOffset.y = dir.z < 0.0 ? 1.0 : 0.0;\\n\\t} else if(vAbs.y >= vAbs.x) {\\n\\t\\tfaceIndex = dir.y < 0.0 ? 3.0 : 2.0;\\n\\t\\tma = 0.5 / vAbs.y;\\n\\t\\tuv = vec2(dir.x, dir.y < 0.0 ? -dir.z : dir.z);\\n\\t\\ttileOffset.x = 1.0;\\n\\t\\ttileOffset.y = dir.y < 0.0 ? 1.0 : 0.0;\\n\\t} else {\\n\\t\\tfaceIndex = dir.x < 0.0 ? 1.0 : 0.0;\\n\\t\\tma = 0.5 / vAbs.x;\\n\\t\\tuv = vec2(dir.x < 0.0 ? dir.z : -dir.z, -dir.y);\\n\\t\\ttileOffset.x = 0.0;\\n\\t\\ttileOffset.y = dir.x < 0.0 ? 1.0 : 0.0;\\n\\t}\\n\\treturn uv * ma + 0.5;\\n}\\nvec2 getCubemapAtlasCoordinates(const vec3 omniAtlasViewport, float shadowEdgePixels, float shadowTextureResolution, const vec3 dir) {\\n\\tfloat faceIndex;\\n\\tvec2 tileOffset;\\n\\tvec2 uv = getCubemapFaceCoordinates(dir, faceIndex, tileOffset);\\n\\tfloat atlasFaceSize = omniAtlasViewport.z;\\n\\tfloat tileSize = shadowTextureResolution * atlasFaceSize;\\n\\tfloat offset = shadowEdgePixels / tileSize;\\n\\tuv = uv * vec2(1.0 - offset * 2.0) + vec2(offset * 1.0);\\n\\tuv *= atlasFaceSize;\\n\\tuv += tileOffset * atlasFaceSize;\\n\\tuv += omniAtlasViewport.xy;\\n\\treturn uv;\\n}\\n`;\\n\\nvar clusteredLightCookies_default$1 = `\\nvec3 _getCookieClustered(TEXTURE_ACCEPT(tex), vec2 uv, float intensity, vec4 cookieChannel) {\\n\\tvec4 pixel = mix(vec4(1.0), texture2DLod(tex, uv, 0.0), intensity);\\n\\tbool isRgb = dot(cookieChannel.rgb, vec3(1.0)) == 3.0;\\n\\treturn isRgb ? pixel.rgb : vec3(dot(pixel, cookieChannel));\\n}\\nvec3 getCookie2DClustered(TEXTURE_ACCEPT(tex), mat4 transform, vec3 worldPosition, float intensity, vec4 cookieChannel) {\\n\\tvec4 projPos = transform * vec4(worldPosition, 1.0);\\n\\treturn _getCookieClustered(TEXTURE_PASS(tex), projPos.xy / projPos.w, intensity, cookieChannel);\\n}\\nvec3 getCookieCubeClustered(TEXTURE_ACCEPT(tex), vec3 dir, float intensity, vec4 cookieChannel, float shadowTextureResolution, float shadowEdgePixels, vec3 omniAtlasViewport) {\\n\\tvec2 uv = getCubemapAtlasCoordinates(omniAtlasViewport, shadowEdgePixels, shadowTextureResolution, dir);\\n\\treturn _getCookieClustered(TEXTURE_PASS(tex), uv, intensity, cookieChannel);\\n}\\n`;\\n\\nvar clusteredLightShadows_default$1 = `\\nvec3 _getShadowCoordPerspZbuffer(mat4 shadowMatrix, vec4 shadowParams, vec3 wPos) {\\n\\tvec4 projPos = shadowMatrix * vec4(wPos, 1.0);\\n\\tprojPos.xyz /= projPos.w;\\n\\treturn projPos.xyz;\\n}\\nvec3 getShadowCoordPerspZbufferNormalOffset(mat4 shadowMatrix, vec4 shadowParams, vec3 normal) {\\n\\tvec3 wPos = vPositionW + normal * shadowParams.y;\\n\\treturn _getShadowCoordPerspZbuffer(shadowMatrix, shadowParams, wPos);\\n}\\nvec3 normalOffsetPointShadow(vec4 shadowParams, vec3 lightPos, vec3 lightDir, vec3 lightDirNorm, vec3 normal) {\\n\\tfloat distScale = length(lightDir);\\n\\tvec3 wPos = vPositionW + normal * shadowParams.y * clamp(1.0 - dot(normal, -lightDirNorm), 0.0, 1.0) * distScale;\\n\\tvec3 dir = wPos - lightPos;\\n\\treturn dir;\\n}\\n#if defined(CLUSTER_SHADOW_TYPE_PCF1)\\nfloat getShadowOmniClusteredPCF1(SHADOWMAP_ACCEPT(shadowMap), vec4 shadowParams, vec3 omniAtlasViewport, float shadowEdgePixels, vec3 lightDir) {\\n\\tfloat shadowTextureResolution = shadowParams.x;\\n\\tvec2 uv = getCubemapAtlasCoordinates(omniAtlasViewport, shadowEdgePixels, shadowTextureResolution, lightDir);\\n\\tfloat shadowZ = length(lightDir) * shadowParams.w + shadowParams.z;\\n\\treturn textureShadow(shadowMap, vec3(uv, shadowZ));\\n}\\n#endif\\n#if defined(CLUSTER_SHADOW_TYPE_PCF3)\\nfloat getShadowOmniClusteredPCF3(SHADOWMAP_ACCEPT(shadowMap), vec4 shadowParams, vec3 omniAtlasViewport, float shadowEdgePixels, vec3 lightDir) {\\n\\tfloat shadowTextureResolution = shadowParams.x;\\n\\tvec2 uv = getCubemapAtlasCoordinates(omniAtlasViewport, shadowEdgePixels, shadowTextureResolution, lightDir);\\n\\tfloat shadowZ = length(lightDir) * shadowParams.w + shadowParams.z;\\n\\tvec3 shadowCoord = vec3(uv, shadowZ);\\n\\treturn getShadowPCF3x3(SHADOWMAP_PASS(shadowMap), shadowCoord, shadowParams);\\n}\\n#endif\\n#if defined(CLUSTER_SHADOW_TYPE_PCF5)\\nfloat getShadowOmniClusteredPCF5(SHADOWMAP_ACCEPT(shadowMap), vec4 shadowParams, vec3 omniAtlasViewport, float shadowEdgePixels, vec3 lightDir) {\\n\\tfloat shadowTextureResolution = shadowParams.x;\\n\\tvec2 uv = getCubemapAtlasCoordinates(omniAtlasViewport, shadowEdgePixels, shadowTextureResolution, lightDir);\\n\\tfloat shadowZ = length(lightDir) * shadowParams.w + shadowParams.z;\\n\\tvec3 shadowCoord = vec3(uv, shadowZ);\\n\\treturn getShadowPCF5x5(SHADOWMAP_PASS(shadowMap), shadowCoord, shadowParams);\\n}\\n#endif\\n#if defined(CLUSTER_SHADOW_TYPE_PCF1)\\nfloat getShadowSpotClusteredPCF1(SHADOWMAP_ACCEPT(shadowMap), vec3 shadowCoord, vec4 shadowParams) {\\n\\treturn textureShadow(shadowMap, shadowCoord);\\n}\\n#endif\\n#if defined(CLUSTER_SHADOW_TYPE_PCF3)\\nfloat getShadowSpotClusteredPCF3(SHADOWMAP_ACCEPT(shadowMap), vec3 shadowCoord, vec4 shadowParams) {\\n\\treturn getShadowSpotPCF3x3(SHADOWMAP_PASS(shadowMap), shadowCoord, shadowParams);\\n}\\n#endif\\n#if defined(CLUSTER_SHADOW_TYPE_PCF5)\\nfloat getShadowSpotClusteredPCF5(SHADOWMAP_ACCEPT(shadowMap), vec3 shadowCoord, vec4 shadowParams) {\\n\\treturn getShadowPCF5x5(SHADOWMAP_PASS(shadowMap), shadowCoord, shadowParams);\\n}\\n#endif\\n`;\\n\\nvar clusteredLight_default$1 = `\\n#include \\\"lightBufferDefinesPS\\\"\\n#include \\\"clusteredLightUtilsPS\\\"\\n#ifdef CLUSTER_COOKIES\\n\\t#include \\\"clusteredLightCookiesPS\\\"\\n#endif\\n#ifdef CLUSTER_SHADOWS\\n\\t#include \\\"clusteredLightShadowsPS\\\"\\n#endif\\nuniform highp usampler2D clusterWorldTexture;\\nuniform highp sampler2D lightsTexture;\\n#ifdef CLUSTER_SHADOWS\\n\\tuniform sampler2DShadow shadowAtlasTexture;\\n#endif\\n#ifdef CLUSTER_COOKIES\\n\\tuniform sampler2D cookieAtlasTexture;\\n#endif\\nuniform int clusterMaxCells;\\nuniform int numClusteredLights;\\nuniform int clusterTextureWidth;\\nuniform vec3 clusterCellsCountByBoundsSize;\\nuniform vec3 clusterBoundsMin;\\nuniform vec3 clusterBoundsDelta;\\nuniform ivec3 clusterCellsDot;\\nuniform ivec3 clusterCellsMax;\\nuniform vec2 shadowAtlasParams;\\nstruct ClusterLightData {\\n\\tvec3 position;\\n\\tint lightIndex;\\n\\tvec3 direction;\\n\\tuint shape;\\n\\tvec3 color;\\n\\tfloat shadowIntensity;\\n\\tfloat range;\\n\\tfloat biasesData;\\n\\tfloat cookieIntensity;\\n\\tbool isSpot;\\n\\tbool falloffModeLinear;\\n\\tbool isDynamic;\\n\\tbool isLightmapped;\\n};\\nstruct ClusterLightSpotData {\\n\\tfloat innerConeAngleCos;\\n\\tfloat outerConeAngleCos;\\n};\\nstruct ClusterLightAreaData {\\n\\tvec3 halfWidth;\\n\\tvec3 halfHeight;\\n};\\nstruct ClusterLightShadowData {\\n\\tfloat shadowBias;\\n\\tfloat shadowNormalBias;\\n};\\nmat4 lightProjectionMatrix;\\nuint clusterLightData_flags;\\nfloat clusterLightData_anglesData;\\nuint clusterLightData_colorBFlagsData;\\nvec4 sampleLightTextureF(int lightIndex, int index) {\\n\\treturn texelFetch(lightsTexture, ivec2(index, lightIndex), 0);\\n}\\nClusterLightData decodeClusterLightCore(int lightIndex) {\\n\\tClusterLightData clusterLightData;\\n\\tclusterLightData.lightIndex = lightIndex;\\n\\tvec4 halfData = sampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_COLOR_ANGLES_BIAS});\\n\\tclusterLightData_anglesData = halfData.z;\\n\\tclusterLightData.biasesData = halfData.w;\\n\\tclusterLightData_colorBFlagsData = floatBitsToUint(halfData.y);\\n\\tvec2 colorRG = unpackHalf2x16(floatBitsToUint(halfData.x));\\n\\tvec2 colorB_flags = unpackHalf2x16(clusterLightData_colorBFlagsData);\\n\\tclusterLightData.color = vec3(colorRG, colorB_flags.x) * {LIGHT_COLOR_DIVIDER};\\n\\tvec4 lightPosRange = sampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_POSITION_RANGE});\\n\\tclusterLightData.position = lightPosRange.xyz;\\n\\tclusterLightData.range = lightPosRange.w;\\n\\tvec4 lightDir_Flags = sampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_DIRECTION_FLAGS});\\n\\tclusterLightData.direction = lightDir_Flags.xyz;\\n\\tclusterLightData_flags = floatBitsToUint(lightDir_Flags.w);\\n\\tclusterLightData.isSpot = (clusterLightData_flags & (1u << 30u)) != 0u;\\n\\tclusterLightData.shape = (clusterLightData_flags >> 28u) & 0x3u;\\n\\tclusterLightData.falloffModeLinear = (clusterLightData_flags & (1u << 27u)) == 0u;\\n\\tclusterLightData.shadowIntensity = float((clusterLightData_flags >> 0u) & 0xFFu) / 255.0;\\n\\tclusterLightData.cookieIntensity = float((clusterLightData_flags >> 8u) & 0xFFu) / 255.0;\\n\\tclusterLightData.isDynamic = (clusterLightData_flags & (1u << 22u)) != 0u;\\n\\tclusterLightData.isLightmapped = (clusterLightData_flags & (1u << 21u)) != 0u;\\n\\treturn clusterLightData;\\n}\\nClusterLightSpotData decodeClusterLightSpot() {\\n\\tuint angleFlags = (clusterLightData_colorBFlagsData >> 16u) & 0xFFFFu;\\n\\tvec2 angleValues = unpackHalf2x16(floatBitsToUint(clusterLightData_anglesData));\\n\\tfloat innerVal = angleValues.x;\\n\\tfloat outerVal = angleValues.y;\\n\\tfloat innerIsVersine = float(angleFlags & 1u);\\n\\tfloat outerIsVersine = float((angleFlags >> 1u) & 1u);\\n\\treturn ClusterLightSpotData(\\n\\t\\tmix(innerVal, 1.0 - innerVal, innerIsVersine),\\n\\t\\tmix(outerVal, 1.0 - outerVal, outerIsVersine)\\n\\t);\\n}\\nvec3 decodeClusterLightOmniAtlasViewport(int lightIndex) {\\n\\treturn sampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_PROJ_MAT_0}).xyz;\\n}\\nClusterLightAreaData decodeClusterLightAreaData(int lightIndex) {\\n\\treturn ClusterLightAreaData(\\n\\t\\tsampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_AREA_DATA_WIDTH}).xyz,\\n\\t\\tsampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_AREA_DATA_HEIGHT}).xyz\\n\\t);\\n}\\nmat4 decodeClusterLightProjectionMatrixData(int lightIndex) {\\n\\tvec4 m0 = sampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_PROJ_MAT_0});\\n\\tvec4 m1 = sampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_PROJ_MAT_1});\\n\\tvec4 m2 = sampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_PROJ_MAT_2});\\n\\tvec4 m3 = sampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_PROJ_MAT_3});\\n\\treturn mat4(m0, m1, m2, m3);\\n}\\nClusterLightShadowData decodeClusterLightShadowData(float biasesData) {\\n\\tvec2 biases = unpackHalf2x16(floatBitsToUint(biasesData));\\n\\treturn ClusterLightShadowData(biases.x, biases.y);\\n}\\nvec4 decodeClusterLightCookieData() {\\n\\tuint cookieFlags = (clusterLightData_flags >> 23u) & 0x0Fu;\\n\\tvec4 mask = vec4(uvec4(cookieFlags) & uvec4(1u, 2u, 4u, 8u));\\n\\treturn step(1.0, mask);\\n}\\nvoid evaluateLight(\\n\\tClusterLightData light, \\n\\tvec3 worldNormal, \\n\\tvec3 viewDir, \\n\\tvec3 reflectionDir,\\n#if defined(LIT_CLEARCOAT)\\n\\tvec3 clearcoatReflectionDir,\\n#endif\\n\\tfloat gloss, \\n\\tvec3 specularity, \\n\\tvec3 geometricNormal, \\n\\tmat3 tbn, \\n#if defined(LIT_IRIDESCENCE)\\n\\tvec3 iridescenceFresnel,\\n#endif\\n\\tvec3 clearcoat_worldNormal,\\n\\tfloat clearcoat_gloss,\\n\\tfloat sheen_gloss,\\n\\tfloat iridescence_intensity\\n) {\\n\\tvec3 cookieAttenuation = vec3(1.0);\\n\\tfloat diffuseAttenuation = 1.0;\\n\\tfloat falloffAttenuation = 1.0;\\n\\tvec3 lightDirW = evalOmniLight(light.position);\\n\\tvec3 lightDirNormW = normalize(lightDirW);\\n\\t#ifdef CLUSTER_AREALIGHTS\\n\\tif (light.shape != {LIGHTSHAPE_PUNCTUAL}) {\\n\\t\\tClusterLightAreaData areaData = decodeClusterLightAreaData(light.lightIndex);\\n\\t\\tif (light.shape == {LIGHTSHAPE_RECT}) {\\n\\t\\t\\tcalcRectLightValues(light.position, areaData.halfWidth, areaData.halfHeight);\\n\\t\\t} else if (light.shape == {LIGHTSHAPE_DISK}) {\\n\\t\\t\\tcalcDiskLightValues(light.position, areaData.halfWidth, areaData.halfHeight);\\n\\t\\t} else {\\n\\t\\t\\tcalcSphereLightValues(light.position, areaData.halfWidth, areaData.halfHeight);\\n\\t\\t}\\n\\t\\tfalloffAttenuation = getFalloffWindow(light.range, lightDirW);\\n\\t} else\\n\\t#endif\\n\\t{\\n\\t\\tif (light.falloffModeLinear)\\n\\t\\t\\tfalloffAttenuation = getFalloffLinear(light.range, lightDirW);\\n\\t\\telse\\n\\t\\t\\tfalloffAttenuation = getFalloffInvSquared(light.range, lightDirW);\\n\\t}\\n\\tif (falloffAttenuation > 0.00001) {\\n\\t\\t#ifdef CLUSTER_AREALIGHTS\\n\\t\\tif (light.shape != {LIGHTSHAPE_PUNCTUAL}) {\\n\\t\\t\\tif (light.shape == {LIGHTSHAPE_RECT}) {\\n\\t\\t\\t\\tdiffuseAttenuation = getRectLightDiffuse(worldNormal, viewDir, lightDirW, lightDirNormW) * 16.0;\\n\\t\\t\\t} else if (light.shape == {LIGHTSHAPE_DISK}) {\\n\\t\\t\\t\\tdiffuseAttenuation = getDiskLightDiffuse(worldNormal, viewDir, lightDirW, lightDirNormW) * 16.0;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tdiffuseAttenuation = getSphereLightDiffuse(worldNormal, viewDir, lightDirW, lightDirNormW) * 16.0;\\n\\t\\t\\t}\\n\\t\\t} else\\n\\t\\t#endif\\n\\t\\t{\\n\\t\\t\\tfalloffAttenuation *= getLightDiffuse(worldNormal, viewDir, lightDirNormW); \\n\\t\\t}\\n\\t\\tif (light.isSpot) {\\n\\t\\t\\tClusterLightSpotData spotData = decodeClusterLightSpot();\\n\\t\\t\\tfalloffAttenuation *= getSpotEffect(light.direction, spotData.innerConeAngleCos, spotData.outerConeAngleCos, lightDirNormW);\\n\\t\\t}\\n\\t\\t#if defined(CLUSTER_COOKIES) || defined(CLUSTER_SHADOWS)\\n\\t\\tif (falloffAttenuation > 0.00001) {\\n\\t\\t\\tif (light.shadowIntensity > 0.0 || light.cookieIntensity > 0.0) {\\n\\t\\t\\t\\tvec3 omniAtlasViewport = vec3(0.0);\\n\\t\\t\\t\\tif (light.isSpot) {\\n\\t\\t\\t\\t\\tlightProjectionMatrix = decodeClusterLightProjectionMatrixData(light.lightIndex);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tomniAtlasViewport = decodeClusterLightOmniAtlasViewport(light.lightIndex);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfloat shadowTextureResolution = shadowAtlasParams.x;\\n\\t\\t\\t\\tfloat shadowEdgePixels = shadowAtlasParams.y;\\n\\t\\t\\t\\t#ifdef CLUSTER_COOKIES\\n\\t\\t\\t\\tif (light.cookieIntensity > 0.0) {\\n\\t\\t\\t\\t\\tvec4 cookieChannelMask = decodeClusterLightCookieData();\\n\\t\\t\\t\\t\\tif (light.isSpot) {\\n\\t\\t\\t\\t\\t\\tcookieAttenuation = getCookie2DClustered(TEXTURE_PASS(cookieAtlasTexture), lightProjectionMatrix, vPositionW, light.cookieIntensity, cookieChannelMask);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tcookieAttenuation = getCookieCubeClustered(TEXTURE_PASS(cookieAtlasTexture), lightDirW, light.cookieIntensity, cookieChannelMask, shadowTextureResolution, shadowEdgePixels, omniAtlasViewport);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#ifdef CLUSTER_SHADOWS\\n\\t\\t\\t\\tif (light.shadowIntensity > 0.0) {\\n\\t\\t\\t\\t\\tClusterLightShadowData shadowData = decodeClusterLightShadowData(light.biasesData);\\n\\t\\t\\t\\t\\tvec4 shadowParams = vec4(shadowTextureResolution, shadowData.shadowNormalBias, shadowData.shadowBias, 1.0 / light.range);\\n\\t\\t\\t\\t\\tif (light.isSpot) {\\n\\t\\t\\t\\t\\t\\tvec3 shadowCoord = getShadowCoordPerspZbufferNormalOffset(lightProjectionMatrix, shadowParams, geometricNormal);\\n\\t\\t\\t\\t\\t\\t\\n\\t\\t\\t\\t\\t\\t#if defined(CLUSTER_SHADOW_TYPE_PCF1)\\n\\t\\t\\t\\t\\t\\t\\tfloat shadow = getShadowSpotClusteredPCF1(SHADOWMAP_PASS(shadowAtlasTexture), shadowCoord, shadowParams);\\n\\t\\t\\t\\t\\t\\t#elif defined(CLUSTER_SHADOW_TYPE_PCF3)\\n\\t\\t\\t\\t\\t\\t\\tfloat shadow = getShadowSpotClusteredPCF3(SHADOWMAP_PASS(shadowAtlasTexture), shadowCoord, shadowParams);\\n\\t\\t\\t\\t\\t\\t#elif defined(CLUSTER_SHADOW_TYPE_PCF5)\\n\\t\\t\\t\\t\\t\\t\\tfloat shadow = getShadowSpotClusteredPCF5(SHADOWMAP_PASS(shadowAtlasTexture), shadowCoord, shadowParams);\\n\\t\\t\\t\\t\\t\\t#elif defined(CLUSTER_SHADOW_TYPE_PCSS)\\n\\t\\t\\t\\t\\t\\t\\tfloat shadow = getShadowSpotClusteredPCSS(SHADOWMAP_PASS(shadowAtlasTexture), shadowCoord, shadowParams);\\n\\t\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\t\\tfalloffAttenuation *= mix(1.0, shadow, light.shadowIntensity);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tvec3 dir = normalOffsetPointShadow(shadowParams, light.position, lightDirW, lightDirNormW, geometricNormal);\\n\\t\\t\\t\\t\\t\\t#if defined(CLUSTER_SHADOW_TYPE_PCF1)\\n\\t\\t\\t\\t\\t\\t\\tfloat shadow = getShadowOmniClusteredPCF1(SHADOWMAP_PASS(shadowAtlasTexture), shadowParams, omniAtlasViewport, shadowEdgePixels, dir);\\n\\t\\t\\t\\t\\t\\t#elif defined(CLUSTER_SHADOW_TYPE_PCF3)\\n\\t\\t\\t\\t\\t\\t\\tfloat shadow = getShadowOmniClusteredPCF3(SHADOWMAP_PASS(shadowAtlasTexture), shadowParams, omniAtlasViewport, shadowEdgePixels, dir);\\n\\t\\t\\t\\t\\t\\t#elif defined(CLUSTER_SHADOW_TYPE_PCF5)\\n\\t\\t\\t\\t\\t\\t\\tfloat shadow = getShadowOmniClusteredPCF5(SHADOWMAP_PASS(shadowAtlasTexture), shadowParams, omniAtlasViewport, shadowEdgePixels, dir);\\n\\t\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\t\\tfalloffAttenuation *= mix(1.0, shadow, light.shadowIntensity);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\t#endif\\n\\t\\t#ifdef CLUSTER_AREALIGHTS\\n\\t\\tif (light.shape != {LIGHTSHAPE_PUNCTUAL}) {\\n\\t\\t\\t{\\n\\t\\t\\t\\tvec3 areaDiffuse = (diffuseAttenuation * falloffAttenuation) * light.color * cookieAttenuation;\\n\\t\\t\\t\\t#if defined(LIT_SPECULAR)\\n\\t\\t\\t\\t\\tareaDiffuse = mix(areaDiffuse, vec3(0), dLTCSpecFres);\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\tdDiffuseLight += areaDiffuse;\\n\\t\\t\\t}\\n\\t\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\t\\tfloat areaLightSpecular;\\n\\t\\t\\t\\tif (light.shape == {LIGHTSHAPE_RECT}) {\\n\\t\\t\\t\\t\\tareaLightSpecular = getRectLightSpecular(worldNormal, viewDir);\\n\\t\\t\\t\\t} else if (light.shape == {LIGHTSHAPE_DISK}) {\\n\\t\\t\\t\\t\\tareaLightSpecular = getDiskLightSpecular(worldNormal, viewDir);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tareaLightSpecular = getSphereLightSpecular(worldNormal, viewDir);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdSpecularLight += dLTCSpecFres * areaLightSpecular * falloffAttenuation * light.color * cookieAttenuation;\\n\\t\\t\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t\\t\\tfloat areaLightSpecularCC;\\n\\t\\t\\t\\t\\tif (light.shape == {LIGHTSHAPE_RECT}) {\\n\\t\\t\\t\\t\\t\\tareaLightSpecularCC = getRectLightSpecular(clearcoat_worldNormal, viewDir);\\n\\t\\t\\t\\t\\t} else if (light.shape == {LIGHTSHAPE_DISK}) {\\n\\t\\t\\t\\t\\t\\tareaLightSpecularCC = getDiskLightSpecular(clearcoat_worldNormal, viewDir);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tareaLightSpecularCC = getSphereLightSpecular(clearcoat_worldNormal, viewDir);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tccSpecularLight += ccLTCSpecFres * areaLightSpecularCC * falloffAttenuation * light.color  * cookieAttenuation;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t} else\\n\\t\\t#endif\\n\\t\\t{\\n\\t\\t\\t{\\n\\t\\t\\t\\tvec3 punctualDiffuse = falloffAttenuation * light.color * cookieAttenuation;\\n\\t\\t\\t\\t#if defined(CLUSTER_AREALIGHTS)\\n\\t\\t\\t\\t#if defined(LIT_SPECULAR)\\n\\t\\t\\t\\t\\tpunctualDiffuse = mix(punctualDiffuse, vec3(0), specularity);\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\tdDiffuseLight += punctualDiffuse;\\n\\t\\t\\t}\\n\\t \\n\\t\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\t\\tvec3 halfDir = normalize(-lightDirNormW + viewDir);\\n\\t\\t\\t\\t\\n\\t\\t\\t\\t#ifdef LIT_SPECULAR_FRESNEL\\n\\t\\t\\t\\t\\tdSpecularLight += \\n\\t\\t\\t\\t\\t\\tgetLightSpecular(halfDir, reflectionDir, worldNormal, viewDir, lightDirNormW, gloss, tbn) * falloffAttenuation * light.color * cookieAttenuation * \\n\\t\\t\\t\\t\\t\\tgetFresnel(\\n\\t\\t\\t\\t\\t\\t\\tdot(viewDir, halfDir), \\n\\t\\t\\t\\t\\t\\t\\tgloss, \\n\\t\\t\\t\\t\\t\\t\\tspecularity\\n\\t\\t\\t\\t\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t\\t\\t\\t\\t, iridescenceFresnel,\\n\\t\\t\\t\\t\\t\\t\\tiridescence_intensity\\n\\t\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\tdSpecularLight += getLightSpecular(halfDir, reflectionDir, worldNormal, viewDir, lightDirNormW, gloss, tbn) * falloffAttenuation * light.color * cookieAttenuation * specularity;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t\\t\\t#ifdef LIT_SPECULAR_FRESNEL\\n\\t\\t\\t\\t\\t\\tccSpecularLight += getLightSpecular(halfDir, clearcoatReflectionDir, clearcoat_worldNormal, viewDir, lightDirNormW, clearcoat_gloss, tbn) * falloffAttenuation * light.color * cookieAttenuation * getFresnelCC(dot(viewDir, halfDir));\\n\\t\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\t\\tccSpecularLight += getLightSpecular(halfDir, clearcoatReflectionDir, clearcoat_worldNormal, viewDir, lightDirNormW, clearcoat_gloss, tbn) * falloffAttenuation * light.color * cookieAttenuation; \\n\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#ifdef LIT_SHEEN\\n\\t\\t\\t\\t\\tsSpecularLight += getLightSpecularSheen(halfDir, worldNormal, viewDir, lightDirNormW, sheen_gloss) * falloffAttenuation * light.color * cookieAttenuation;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t}\\n\\t}\\n\\tdAtten = falloffAttenuation;\\n\\tdLightDirNormW = lightDirNormW;\\n}\\nvoid evaluateClusterLight(\\n\\tint lightIndex, \\n\\tvec3 worldNormal, \\n\\tvec3 viewDir, \\n\\tvec3 reflectionDir, \\n#if defined(LIT_CLEARCOAT)\\n\\tvec3 clearcoatReflectionDir,\\n#endif\\n\\tfloat gloss, \\n\\tvec3 specularity, \\n\\tvec3 geometricNormal, \\n\\tmat3 tbn, \\n#if defined(LIT_IRIDESCENCE)\\n\\tvec3 iridescenceFresnel,\\n#endif\\n\\tvec3 clearcoat_worldNormal,\\n\\tfloat clearcoat_gloss,\\n\\tfloat sheen_gloss,\\n\\tfloat iridescence_intensity\\n) {\\n\\tClusterLightData clusterLightData = decodeClusterLightCore(lightIndex);\\n\\t#ifdef CLUSTER_MESH_DYNAMIC_LIGHTS\\n\\t\\tbool acceptLightMask = clusterLightData.isDynamic;\\n\\t#else\\n\\t\\tbool acceptLightMask = clusterLightData.isLightmapped;\\n\\t#endif\\n\\tif (acceptLightMask)\\n\\t\\tevaluateLight(\\n\\t\\t\\tclusterLightData, \\n\\t\\t\\tworldNormal, \\n\\t\\t\\tviewDir, \\n\\t\\t\\treflectionDir, \\n#if defined(LIT_CLEARCOAT)\\n\\t\\t\\tclearcoatReflectionDir, \\n#endif\\n\\t\\t\\tgloss, \\n\\t\\t\\tspecularity, \\n\\t\\t\\tgeometricNormal, \\n\\t\\t\\ttbn, \\n#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\tiridescenceFresnel,\\n#endif\\n\\t\\t\\tclearcoat_worldNormal,\\n\\t\\t\\tclearcoat_gloss,\\n\\t\\t\\tsheen_gloss,\\n\\t\\t\\tiridescence_intensity\\n\\t\\t);\\n}\\nvoid addClusteredLights(\\n\\tvec3 worldNormal, \\n\\tvec3 viewDir, \\n\\tvec3 reflectionDir, \\n#if defined(LIT_CLEARCOAT)\\n\\tvec3 clearcoatReflectionDir,\\n#endif\\n\\tfloat gloss, \\n\\tvec3 specularity, \\n\\tvec3 geometricNormal, \\n\\tmat3 tbn, \\n#if defined(LIT_IRIDESCENCE)\\n\\tvec3 iridescenceFresnel,\\n#endif\\n\\tvec3 clearcoat_worldNormal,\\n\\tfloat clearcoat_gloss,\\n\\tfloat sheen_gloss,\\n\\tfloat iridescence_intensity\\n) {\\n\\tif (numClusteredLights <= 1)\\n\\t\\treturn;\\n\\tivec3 cellCoords = ivec3(floor((vPositionW - clusterBoundsMin) * clusterCellsCountByBoundsSize));\\n\\tif (!(any(lessThan(cellCoords, ivec3(0))) || any(greaterThanEqual(cellCoords, clusterCellsMax)))) {\\n\\t\\tint cellIndex = cellCoords.x * clusterCellsDot.x + cellCoords.y * clusterCellsDot.y + cellCoords.z * clusterCellsDot.z;\\n\\t\\tint clusterV = cellIndex / clusterTextureWidth;\\n\\t\\tint clusterU = cellIndex - clusterV * clusterTextureWidth;\\n\\t\\tfor (int lightCellIndex = 0; lightCellIndex < clusterMaxCells; lightCellIndex++) {\\n\\t\\t\\tuint lightIndex = texelFetch(clusterWorldTexture, ivec2(clusterU + lightCellIndex, clusterV), 0).x;\\n\\t\\t\\tif (lightIndex == 0u)\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tevaluateClusterLight(\\n\\t\\t\\t\\tint(lightIndex), \\n\\t\\t\\t\\tworldNormal, \\n\\t\\t\\t\\tviewDir, \\n\\t\\t\\t\\treflectionDir,\\n#if defined(LIT_CLEARCOAT)\\n\\t\\t\\t\\tclearcoatReflectionDir,\\n#endif\\n\\t\\t\\t\\tgloss, \\n\\t\\t\\t\\tspecularity, \\n\\t\\t\\t\\tgeometricNormal, \\n\\t\\t\\t\\ttbn, \\n#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t\\tiridescenceFresnel,\\n#endif\\n\\t\\t\\t\\tclearcoat_worldNormal,\\n\\t\\t\\t\\tclearcoat_gloss,\\n\\t\\t\\t\\tsheen_gloss,\\n\\t\\t\\t\\tiridescence_intensity\\n\\t\\t\\t); \\n\\t\\t}\\n\\t}\\n}\\n`;\\n\\nvar combine_default$1 = `\\nvec3 combineColor(vec3 albedo, vec3 sheenSpecularity, float clearcoatSpecularity) {\\n\\tvec3 ret = vec3(0);\\n#ifdef LIT_OLD_AMBIENT\\n\\tret += (dDiffuseLight - light_globalAmbient) * albedo + material_ambient * light_globalAmbient;\\n#else\\n\\tret += albedo * dDiffuseLight;\\n#endif\\n#ifdef LIT_SPECULAR\\n\\tret += dSpecularLight;\\n#endif\\n#ifdef LIT_REFLECTIONS\\n\\tret += dReflection.rgb * dReflection.a;\\n#endif\\n#ifdef LIT_SHEEN\\n\\tfloat sheenScaling = 1.0 - max(max(sheenSpecularity.r, sheenSpecularity.g), sheenSpecularity.b) * 0.157;\\n\\tret = ret * sheenScaling + (sSpecularLight + sReflection.rgb) * sheenSpecularity;\\n#endif\\n#ifdef LIT_CLEARCOAT\\n\\tfloat clearCoatScaling = 1.0 - ccFresnel * clearcoatSpecularity;\\n\\tret = ret * clearCoatScaling + (ccSpecularLight + ccReflection) * clearcoatSpecularity;\\n#endif\\n\\treturn ret;\\n}\\n`;\\n\\nvar cookie_blit_2d_default$1 = `\\n\\tvarying vec2 uv0;\\n\\tuniform sampler2D blitTexture;\\n\\tvoid main(void) {\\n\\t\\tgl_FragColor = texture2D(blitTexture, uv0);\\n\\t}\\n`;\\n\\nvar cookie_blit_cube_default$1 = `\\n\\tvarying vec2 uv0;\\n\\tuniform samplerCube blitTexture;\\n\\tuniform mat4 invViewProj;\\n\\tvoid main(void) {\\n\\t\\tvec4 projPos = vec4(uv0 * 2.0 - 1.0, 0.5, 1.0);\\n\\t\\tvec4 worldPos = invViewProj * projPos;\\n\\t\\tgl_FragColor = textureCube(blitTexture, worldPos.xyz);\\n\\t}\\n`;\\n\\nvar cookie_blit_default$1 = `\\n\\tattribute vec2 vertex_position;\\n\\tvarying vec2 uv0;\\n\\tvoid main(void) {\\n\\t\\tgl_Position = vec4(vertex_position, 0.5, 1.0);\\n\\t\\tuv0 = vertex_position.xy * 0.5 + 0.5;\\n\\t\\t#ifndef WEBGPU\\n\\t\\t\\tuv0.y = 1.0 - uv0.y;\\n\\t\\t#endif\\n\\t}\\n`;\\n\\nvar cookie_default = `\\nvec4 getCookie2D(sampler2D tex, mat4 transform, float intensity) {\\n\\tvec4 projPos = transform * vec4(vPositionW, 1.0);\\n\\tprojPos.xy /= projPos.w;\\n\\treturn mix(vec4(1.0), texture2D(tex, projPos.xy), intensity);\\n}\\nvec4 getCookie2DClip(sampler2D tex, mat4 transform, float intensity) {\\n\\tvec4 projPos = transform * vec4(vPositionW, 1.0);\\n\\tprojPos.xy /= projPos.w;\\n\\tif (projPos.x < 0.0 || projPos.x > 1.0 || projPos.y < 0.0 || projPos.y > 1.0 || projPos.z < 0.0) return vec4(0.0);\\n\\treturn mix(vec4(1.0), texture2D(tex, projPos.xy), intensity);\\n}\\nvec4 getCookie2DXform(sampler2D tex, mat4 transform, float intensity, vec4 cookieMatrix, vec2 cookieOffset) {\\n\\tvec4 projPos = transform * vec4(vPositionW, 1.0);\\n\\tprojPos.xy /= projPos.w;\\n\\tprojPos.xy += cookieOffset;\\n\\tvec2 uv = mat2(cookieMatrix) * (projPos.xy-vec2(0.5)) + vec2(0.5);\\n\\treturn mix(vec4(1.0), texture2D(tex, uv), intensity);\\n}\\nvec4 getCookie2DClipXform(sampler2D tex, mat4 transform, float intensity, vec4 cookieMatrix, vec2 cookieOffset) {\\n\\tvec4 projPos = transform * vec4(vPositionW, 1.0);\\n\\tprojPos.xy /= projPos.w;\\n\\tprojPos.xy += cookieOffset;\\n\\tif (projPos.x < 0.0 || projPos.x > 1.0 || projPos.y < 0.0 || projPos.y > 1.0 || projPos.z < 0.0) return vec4(0.0);\\n\\tvec2 uv = mat2(cookieMatrix) * (projPos.xy-vec2(0.5)) + vec2(0.5);\\n\\treturn mix(vec4(1.0), texture2D(tex, uv), intensity);\\n}\\nvec4 getCookieCube(samplerCube tex, mat4 transform, float intensity) {\\n\\treturn mix(vec4(1.0), textureCube(tex, dLightDirNormW * mat3(transform)), intensity);\\n}\\n`;\\n\\nvar cubeMapProject_default$1 = `\\n#if LIT_CUBEMAP_PROJECTION == BOX\\n\\tuniform vec3 envBoxMin;\\n\\tuniform vec3 envBoxMax;\\n#endif\\nvec3 cubeMapProject(vec3 nrdir) {\\n\\t#if LIT_CUBEMAP_PROJECTION == NONE\\n\\t\\treturn cubeMapRotate(nrdir);\\n\\t#endif\\n\\t#if LIT_CUBEMAP_PROJECTION == BOX\\n\\t\\tnrdir = cubeMapRotate(nrdir);\\n\\t\\tvec3 rbmax = (envBoxMax - vPositionW) / nrdir;\\n\\t\\tvec3 rbmin = (envBoxMin - vPositionW) / nrdir;\\n\\t\\tvec3 rbminmax = mix(rbmin, rbmax, vec3(greaterThan(nrdir, vec3(0.0))));\\n\\t\\tfloat fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);\\n\\t\\tvec3 posonbox = vPositionW + nrdir * fa;\\n\\t\\tvec3 envBoxPos = (envBoxMin + envBoxMax) * 0.5;\\n\\t\\treturn normalize(posonbox - envBoxPos);\\n\\t#endif\\n}\\n`;\\n\\nvar cubeMapRotate_default$1 = `\\n#ifdef CUBEMAP_ROTATION\\nuniform mat3 cubeMapRotationMatrix;\\n#endif\\nvec3 cubeMapRotate(vec3 refDir) {\\n#ifdef CUBEMAP_ROTATION\\n\\treturn refDir * cubeMapRotationMatrix;\\n#else\\n\\treturn refDir;\\n#endif\\n}\\n`;\\n\\nvar debug_output_default$1 = `\\n#ifdef DEBUG_ALBEDO_PASS\\ngl_FragColor = vec4(gammaCorrectOutput(dAlbedo), 1.0);\\n#endif\\n#ifdef DEBUG_UV0_PASS\\ngl_FragColor = vec4(litArgs_albedo , 1.0);\\n#endif\\n#ifdef DEBUG_WORLD_NORMAL_PASS\\ngl_FragColor = vec4(litArgs_worldNormal * 0.5 + 0.5, 1.0);\\n#endif\\n#ifdef DEBUG_OPACITY_PASS\\ngl_FragColor = vec4(vec3(litArgs_opacity) , 1.0);\\n#endif\\n#ifdef DEBUG_SPECULARITY_PASS\\ngl_FragColor = vec4(litArgs_specularity, 1.0);\\n#endif\\n#ifdef DEBUG_GLOSS_PASS\\ngl_FragColor = vec4(vec3(litArgs_gloss) , 1.0);\\n#endif\\n#ifdef DEBUG_METALNESS_PASS\\ngl_FragColor = vec4(vec3(litArgs_metalness) , 1.0);\\n#endif\\n#ifdef DEBUG_AO_PASS\\ngl_FragColor = vec4(vec3(litArgs_ao) , 1.0);\\n#endif\\n#ifdef DEBUG_EMISSION_PASS\\ngl_FragColor = vec4(gammaCorrectOutput(litArgs_emission), 1.0);\\n#endif\\n`;\\n\\nvar debug_process_frontend_default$1 = `\\n#ifdef DEBUG_LIGHTING_PASS\\nlitArgs_albedo = vec3(0.5);\\n#endif\\n#ifdef DEBUG_UV0_PASS\\n#ifdef VARYING_VUV0\\nlitArgs_albedo = vec3(vUv0, 0);\\n#else\\nlitArgs_albedo = vec3(0);\\n#endif\\n#endif\\n`;\\n\\nvar decode_default$1 = `\\n#ifndef _DECODE_INCLUDED_\\n#define _DECODE_INCLUDED_\\nvec3 decodeLinear(vec4 raw) {\\n\\treturn raw.rgb;\\n}\\nfloat decodeGamma(float raw) {\\n\\treturn pow(raw, 2.2);\\n}\\nvec3 decodeGamma(vec3 raw) {\\n\\treturn pow(raw, vec3(2.2));\\n}\\nvec3 decodeGamma(vec4 raw) {\\n\\treturn pow(raw.xyz, vec3(2.2));\\n}\\nvec3 decodeRGBM(vec4 raw) {\\n\\tvec3 color = (8.0 * raw.a) * raw.rgb;\\n\\treturn color * color;\\n}\\nvec3 decodeRGBP(vec4 raw) {\\n\\tvec3 color = raw.rgb * (-raw.a * 7.0 + 8.0);\\n\\treturn color * color;\\n}\\nvec3 decodeRGBE(vec4 raw) {\\n\\tif (raw.a == 0.0) {\\n\\t\\treturn vec3(0.0, 0.0, 0.0);\\n\\t} else {\\n\\t\\treturn raw.xyz * pow(2.0, raw.w * 255.0 - 128.0);\\n\\t}\\n}\\nvec4 passThrough(vec4 raw) {\\n\\treturn raw;\\n}\\nvec3 unpackNormalXYZ(vec4 nmap) {\\n\\treturn nmap.xyz * 2.0 - 1.0;\\n}\\nvec3 unpackNormalXY(vec4 nmap) {\\n\\tvec3 normal;\\n\\tnormal.xy = nmap.wy * 2.0 - 1.0;\\n\\tnormal.z = sqrt(1.0 - clamp(dot(normal.xy, normal.xy), 0.0, 1.0));\\n\\treturn normal;\\n}\\n#endif\\n`;\\n\\nvar detailModes_default$1 = `\\n#ifndef _DETAILMODES_INCLUDED_\\n#define _DETAILMODES_INCLUDED_\\nvec3 detailMode_mul(vec3 c1, vec3 c2) {\\n\\treturn c1 * c2;\\n}\\nvec3 detailMode_add(vec3 c1, vec3 c2) {\\n\\treturn c1 + c2;\\n}\\nvec3 detailMode_screen(vec3 c1, vec3 c2) {\\n\\treturn 1.0 - (1.0 - c1)*(1.0 - c2);\\n}\\nvec3 detailMode_overlay(vec3 c1, vec3 c2) {\\n\\treturn mix(1.0 - 2.0 * (1.0 - c1)*(1.0 - c2), 2.0 * c1 * c2, step(c1, vec3(0.5)));\\n}\\nvec3 detailMode_min(vec3 c1, vec3 c2) {\\n\\treturn min(c1, c2);\\n}\\nvec3 detailMode_max(vec3 c1, vec3 c2) {\\n\\treturn max(c1, c2);\\n}\\n#endif\\n`;\\n\\nvar diffuse_default$1 = `\\nuniform vec3 material_diffuse;\\n#ifdef STD_DIFFUSEDETAIL_TEXTURE\\n\\t#include \\\"detailModesPS\\\"\\n#endif\\nvoid getAlbedo() {\\n\\tdAlbedo = material_diffuse.rgb;\\n\\t#ifdef STD_DIFFUSE_TEXTURE\\n\\t\\tvec3 albedoTexture = {STD_DIFFUSE_TEXTURE_DECODE}(texture2DBias({STD_DIFFUSE_TEXTURE_NAME}, {STD_DIFFUSE_TEXTURE_UV}, textureBias)).{STD_DIFFUSE_TEXTURE_CHANNEL};\\n\\t\\t#ifdef STD_DIFFUSEDETAIL_TEXTURE\\n\\t\\t\\tvec3 albedoDetail = {STD_DIFFUSEDETAIL_TEXTURE_DECODE}(texture2DBias({STD_DIFFUSEDETAIL_TEXTURE_NAME}, {STD_DIFFUSEDETAIL_TEXTURE_UV}, textureBias)).{STD_DIFFUSEDETAIL_TEXTURE_CHANNEL};\\n\\t\\t\\talbedoTexture = detailMode_{STD_DIFFUSEDETAIL_DETAILMODE}(albedoTexture, albedoDetail);\\n\\t\\t#endif\\n\\t\\tdAlbedo *= albedoTexture;\\n\\t#endif\\n\\t#ifdef STD_DIFFUSE_VERTEX\\n\\t\\tdAlbedo *= saturate(vVertexColor.{STD_DIFFUSE_VERTEX_CHANNEL});\\n\\t#endif\\n}\\n`;\\n\\nvar emissive_default$1 = `\\nuniform vec3 material_emissive;\\nuniform float material_emissiveIntensity;\\nvoid getEmission() {\\n\\tdEmission = material_emissive * material_emissiveIntensity;\\n\\t#ifdef STD_EMISSIVE_TEXTURE\\n\\tdEmission *= {STD_EMISSIVE_TEXTURE_DECODE}(texture2DBias({STD_EMISSIVE_TEXTURE_NAME}, {STD_EMISSIVE_TEXTURE_UV}, textureBias)).{STD_EMISSIVE_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_EMISSIVE_VERTEX\\n\\tdEmission *= saturate(vVertexColor.{STD_EMISSIVE_VERTEX_CHANNEL});\\n\\t#endif\\n}\\n`;\\n\\nvar encode_default$1 = `\\nvec4 encodeLinear(vec3 source) {\\n\\treturn vec4(source, 1.0);\\n}\\nvec4 encodeGamma(vec3 source) {\\n\\treturn vec4(pow(source + 0.0000001, vec3(1.0 / 2.2)), 1.0);\\n}\\nvec4 encodeRGBM(vec3 source) {\\n\\tvec4 result;\\n\\tresult.rgb = pow(source.rgb, vec3(0.5));\\n\\tresult.rgb *= 1.0 / 8.0;\\n\\tresult.a = saturate( max( max( result.r, result.g ), max( result.b, 1.0 / 255.0 ) ) );\\n\\tresult.a = ceil(result.a * 255.0) / 255.0;\\n\\tresult.rgb /= result.a;\\n\\treturn result;\\n}\\nvec4 encodeRGBP(vec3 source) {\\n\\tvec3 gamma = pow(source, vec3(0.5));\\n\\tfloat maxVal = min(8.0, max(1.0, max(gamma.x, max(gamma.y, gamma.z))));\\n\\tfloat v = 1.0 - ((maxVal - 1.0) / 7.0);\\n\\tv = ceil(v * 255.0) / 255.0;\\n\\treturn vec4(gamma / (-v * 7.0 + 8.0), v);\\t\\n}\\nvec4 encodeRGBE(vec3 source) {\\n\\tfloat maxVal = max(source.x, max(source.y, source.z));\\n\\tif (maxVal < 1e-32) {\\n\\t\\treturn vec4(0, 0, 0, 0);\\n\\t} else {\\n\\t\\tfloat e = ceil(log2(maxVal));\\n\\t\\treturn vec4(source / pow(2.0, e), (e + 128.0) / 255.0);\\n\\t}\\n}\\n`;\\n\\nvar end_default$1 = `\\n\\tgl_FragColor.rgb = combineColor(litArgs_albedo, litArgs_sheen_specularity, litArgs_clearcoat_specularity);\\n\\tgl_FragColor.rgb += litArgs_emission;\\n\\tgl_FragColor.rgb = addFog(gl_FragColor.rgb);\\n\\tgl_FragColor.rgb = toneMap(gl_FragColor.rgb);\\n\\tgl_FragColor.rgb = gammaCorrectOutput(gl_FragColor.rgb);\\n`;\\n\\nvar envAtlas_default$1 = `\\n#ifndef _ENVATLAS_INCLUDED_\\n#define _ENVATLAS_INCLUDED_\\nconst float atlasSize = 512.0;\\nconst float seamSize = 1.0 / atlasSize;\\nvec2 mapUv(vec2 uv, vec4 rect) {\\n\\treturn vec2(mix(rect.x + seamSize, rect.x + rect.z - seamSize, uv.x),\\n\\t\\t\\t\\tmix(rect.y + seamSize, rect.y + rect.w - seamSize, uv.y));\\n}\\nvec2 mapRoughnessUv(vec2 uv, float level) {\\n\\tfloat t = 1.0 / exp2(level);\\n\\treturn mapUv(uv, vec4(0, 1.0 - t, t, t * 0.5));\\n}\\nvec2 mapShinyUv(vec2 uv, float level) {\\n\\tfloat t = 1.0 / exp2(level);\\n\\treturn mapUv(uv, vec4(1.0 - t, 1.0 - t, t, t * 0.5));\\n}\\n#endif\\n`;\\n\\nvar envProc_default$1 = `\\n#ifdef LIT_SKYBOX_INTENSITY\\n\\tuniform float skyboxIntensity;\\n#endif\\nvec3 processEnvironment(vec3 color) {\\n\\t#ifdef LIT_SKYBOX_INTENSITY\\n\\t\\treturn color * skyboxIntensity;\\n\\t#else\\n\\t\\treturn color;\\n\\t#endif\\n}\\n`;\\n\\nvar falloffInvSquared_default$1 = `\\nfloat getFalloffWindow(float lightRadius, vec3 lightDir) {\\n\\tfloat sqrDist = dot(lightDir, lightDir);\\n\\tfloat invRadius = 1.0 / lightRadius;\\n\\treturn square(saturate(1.0 - square(sqrDist * square(invRadius))));\\n}\\nfloat getFalloffInvSquared(float lightRadius, vec3 lightDir) {\\n\\tfloat sqrDist = dot(lightDir, lightDir);\\n\\tfloat falloff = 1.0 / (sqrDist + 1.0);\\n\\tfloat invRadius = 1.0 / lightRadius;\\n\\tfalloff *= 16.0;\\n\\tfalloff *= square(saturate(1.0 - square(sqrDist * square(invRadius))));\\n\\treturn falloff;\\n}\\n`;\\n\\nvar falloffLinear_default$1 = `\\nfloat getFalloffLinear(float lightRadius, vec3 lightDir) {\\n\\tfloat d = length(lightDir);\\n\\treturn max(((lightRadius - d) / lightRadius), 0.0);\\n}\\n`;\\n\\nvar float_as_uint_default$1 = `\\n#ifndef FLOAT_AS_UINT\\n#define FLOAT_AS_UINT\\nvec4 float2uint(float value) {\\n\\tuint intBits = floatBitsToUint(value);\\n\\treturn vec4(\\n\\t\\tfloat((intBits >> 24u) & 0xFFu) / 255.0,\\n\\t\\tfloat((intBits >> 16u) & 0xFFu) / 255.0,\\n\\t\\tfloat((intBits >> 8u) & 0xFFu) / 255.0,\\n\\t\\tfloat(intBits & 0xFFu) / 255.0\\n\\t);\\n}\\nfloat uint2float(vec4 value) {\\n\\tuint intBits = \\n\\t\\t(uint(value.r * 255.0) << 24u) |\\n\\t\\t(uint(value.g * 255.0) << 16u) |\\n\\t\\t(uint(value.b * 255.0) << 8u) |\\n\\t\\tuint(value.a * 255.0);\\n\\treturn uintBitsToFloat(intBits);\\n}\\nvec4 float2vec4(float value) {\\n\\t#if defined(CAPS_TEXTURE_FLOAT_RENDERABLE)\\n\\t\\treturn vec4(value, 1.0, 1.0, 1.0);\\n\\t#else\\n\\t\\treturn float2uint(value);\\n\\t#endif\\n}\\n#endif\\n`;\\n\\nvar fog_default$1 = `\\nfloat dBlendModeFogFactor = 1.0;\\n#if (FOG != NONE)\\n\\tuniform vec3 fog_color;\\n\\t#if (FOG == LINEAR)\\n\\t\\tuniform float fog_start;\\n\\t\\tuniform float fog_end;\\n\\t#else\\n\\t\\tuniform float fog_density;\\n\\t#endif\\n#endif\\n#ifdef VERTEXSHADER\\n\\tfloat getFogFactor(float depth) {\\n#else\\n\\tfloat getFogFactor() {\\n\\t\\tfloat depth = gl_FragCoord.z / gl_FragCoord.w;\\n#endif\\n\\tfloat fogFactor = 0.0;\\n\\t#if (FOG == LINEAR)\\n\\t\\tfogFactor = (fog_end - depth) / (fog_end - fog_start);\\n\\t#elif (FOG == EXP)\\n\\t\\tfogFactor = exp(-depth * fog_density);\\n\\t#elif (FOG == EXP2)\\n\\t\\tfogFactor = exp(-depth * depth * fog_density * fog_density);\\n\\t#endif\\n\\treturn clamp(fogFactor, 0.0, 1.0);\\n}\\n#ifdef VERTEXSHADER\\n\\tvec3 addFog(vec3 color, float depth) {\\n\\t\\t#if (FOG != NONE)\\n\\t\\t\\treturn mix(fog_color * dBlendModeFogFactor, color, getFogFactor(depth));\\n\\t\\t#endif\\n\\t\\treturn color;\\n\\t}\\n#else\\n\\tvec3 addFog(vec3 color) {\\n\\t\\t#if (FOG != NONE)\\n\\t\\t\\treturn mix(fog_color * dBlendModeFogFactor, color, getFogFactor());\\n\\t\\t#endif\\n\\t\\treturn color;\\n\\t}\\n#endif\\n`;\\n\\nvar fresnelSchlick_default$1 = `\\nfloat pow5(float x) {\\n\\tfloat x2 = x * x;\\n\\treturn x2 * x2 * x;\\n}\\nvec3 getFresnel(\\n\\t\\tfloat cosTheta, \\n\\t\\tfloat gloss, \\n\\t\\tvec3 specularity\\n#if defined(LIT_IRIDESCENCE)\\n\\t\\t, vec3 iridescenceFresnel, \\n\\t\\tfloat iridescenceIntensity\\n#endif\\n\\t) {\\n\\tfloat fresnel = pow5(1.0 - saturate(cosTheta));\\n\\tfloat glossSq = gloss * gloss;\\n\\tfloat specIntensity = max(specularity.r, max(specularity.g, specularity.b));\\n\\tvec3 ret = specularity + (max(vec3(glossSq * specIntensity), specularity) - specularity) * fresnel;\\n#if defined(LIT_IRIDESCENCE)\\n\\treturn mix(ret, iridescenceFresnel, iridescenceIntensity);\\n#else\\n\\treturn ret;\\n#endif\\t\\n}\\nfloat getFresnelCC(float cosTheta) {\\n\\tfloat fresnel = pow5(1.0 - saturate(cosTheta));\\n\\treturn 0.04 + (1.0 - 0.04) * fresnel;\\n}\\n`;\\n\\nvar fullscreenQuad_default$1 = `\\nattribute vec2 vertex_position;\\nvarying vec2 vUv0;\\nvoid main(void)\\n{\\n\\tgl_Position = vec4(vertex_position, 0.5, 1.0);\\n\\tvUv0 = vertex_position.xy * 0.5 + 0.5;\\n}\\n`;\\n\\nvar gamma_default$1 = `\\n#include \\\"decodePS\\\"\\n#if (GAMMA == SRGB)\\n\\tfloat gammaCorrectInput(float color) {\\n\\t\\treturn decodeGamma(color);\\n\\t}\\n\\tvec3 gammaCorrectInput(vec3 color) {\\n\\t\\treturn decodeGamma(color);\\n\\t}\\n\\tvec4 gammaCorrectInput(vec4 color) {\\n\\t\\treturn vec4(decodeGamma(color.xyz), color.w);\\n\\t}\\n\\tvec3 gammaCorrectOutput(vec3 color) {\\n\\t\\treturn pow(color + 0.0000001, vec3(1.0 / 2.2));\\n\\t}\\n#else\\n\\tfloat gammaCorrectInput(float color) {\\n\\t\\treturn color;\\n\\t}\\n\\tvec3 gammaCorrectInput(vec3 color) {\\n\\t\\treturn color;\\n\\t}\\n\\tvec4 gammaCorrectInput(vec4 color) {\\n\\t\\treturn color;\\n\\t}\\n\\tvec3 gammaCorrectOutput(vec3 color) {\\n\\t\\treturn color;\\n\\t}\\n#endif\\n`;\\n\\nvar gloss_default$1 = `\\n#ifdef STD_GLOSS_CONSTANT\\nuniform float material_gloss;\\n#endif\\nvoid getGlossiness() {\\n\\tdGlossiness = 1.0;\\n\\t#ifdef STD_GLOSS_CONSTANT\\n\\tdGlossiness *= material_gloss;\\n\\t#endif\\n\\t#ifdef STD_GLOSS_TEXTURE\\n\\tdGlossiness *= texture2DBias({STD_GLOSS_TEXTURE_NAME}, {STD_GLOSS_TEXTURE_UV}, textureBias).{STD_GLOSS_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_GLOSS_VERTEX\\n\\tdGlossiness *= saturate(vVertexColor.{STD_GLOSS_VERTEX_CHANNEL});\\n\\t#endif\\n\\t#ifdef STD_GLOSS_INVERT\\n\\tdGlossiness = 1.0 - dGlossiness;\\n\\t#endif\\n\\tdGlossiness += 0.0000001;\\n}\\n`;\\n\\nvar quad_default$1 = `\\n\\tattribute vec2 aPosition;\\n\\tvarying vec2 uv0;\\n\\tvoid main(void)\\n\\t{\\n\\t\\tgl_Position = vec4(aPosition, 0.0, 1.0);\\n\\t\\tuv0 = getImageEffectUV((aPosition.xy + 1.0) * 0.5);\\n\\t}\\n`;\\n\\nvar immediateLine_default$3 = `\\n\\t\\t#include \\\"gammaPS\\\"\\n\\t\\tvarying vec4 color;\\n\\t\\tvoid main(void) {\\n\\t\\t\\tgl_FragColor = vec4(gammaCorrectOutput(decodeGamma(color.rgb)), color.a);\\n\\t\\t}\\n`;\\n\\nvar immediateLine_default$2 = `\\n\\tattribute vec4 vertex_position;\\n\\tattribute vec4 vertex_color;\\n\\tuniform mat4 matrix_model;\\n\\tuniform mat4 matrix_viewProjection;\\n\\tvarying vec4 color;\\n\\tvoid main(void) {\\n\\t\\tcolor = vertex_color;\\n\\t\\tgl_Position = matrix_viewProjection * matrix_model * vertex_position;\\n\\t}\\n`;\\n\\nvar iridescenceDiffraction_default$1 = `\\nuniform float material_iridescenceRefractionIndex;\\nfloat iridescence_iorToFresnel(float transmittedIor, float incidentIor) {\\n\\treturn pow((transmittedIor - incidentIor) / (transmittedIor + incidentIor), 2.0);\\n}\\nvec3 iridescence_iorToFresnel(vec3 transmittedIor, float incidentIor) {\\n\\treturn pow((transmittedIor - vec3(incidentIor)) / (transmittedIor + vec3(incidentIor)), vec3(2.0));\\n}\\nvec3 iridescence_fresnelToIor(vec3 f0) {\\n\\tvec3 sqrtF0 = sqrt(f0);\\n\\treturn (vec3(1.0) + sqrtF0) / (vec3(1.0) - sqrtF0);\\n}\\nvec3 iridescence_sensitivity(float opd, vec3 shift) {\\n\\tfloat PI = 3.141592653589793;\\n\\tfloat phase = 2.0 * PI * opd * 1.0e-9;\\n\\tconst vec3 val = vec3(5.4856e-13, 4.4201e-13, 5.2481e-13);\\n\\tconst vec3 pos = vec3(1.6810e+06, 1.7953e+06, 2.2084e+06);\\n\\tconst vec3 var = vec3(4.3278e+09, 9.3046e+09, 6.6121e+09);\\n\\tvec3 xyz = val * sqrt(2.0 * PI * var) * cos(pos * phase + shift) * exp(-pow(phase, 2.0) * var);\\n\\txyz.x += 9.7470e-14 * sqrt(2.0 * PI * 4.5282e+09) * cos(2.2399e+06 * phase + shift[0]) * exp(-4.5282e+09 * pow(phase, 2.0));\\n\\txyz /= vec3(1.0685e-07);\\n\\tconst mat3 XYZ_TO_REC709 = mat3(\\n\\t\\t3.2404542, -0.9692660,  0.0556434,\\n\\t   -1.5371385,  1.8760108, -0.2040259,\\n\\t   -0.4985314,  0.0415560,  1.0572252\\n\\t);\\n\\treturn XYZ_TO_REC709 * xyz;\\n}\\nfloat iridescence_fresnel(float cosTheta, float f0) {\\n\\tfloat x = clamp(1.0 - cosTheta, 0.0, 1.0);\\n\\tfloat x2 = x * x;\\n\\tfloat x5 = x * x2 * x2;\\n\\treturn f0 + (1.0 - f0) * x5;\\n} \\nvec3 iridescence_fresnel(float cosTheta, vec3 f0) {\\n\\tfloat x = clamp(1.0 - cosTheta, 0.0, 1.0);\\n\\tfloat x2 = x * x;\\n\\tfloat x5 = x * x2 * x2; \\n\\treturn f0 + (vec3(1.0) - f0) * x5;\\n}\\nvec3 calcIridescence(float outsideIor, float cosTheta, vec3 base_f0, float iridescenceThickness) {\\n\\tfloat PI = 3.141592653589793;\\n\\tfloat iridescenceIor = mix(outsideIor, material_iridescenceRefractionIndex, smoothstep(0.0, 0.03, iridescenceThickness));\\n\\tfloat sinTheta2Sq = pow(outsideIor / iridescenceIor, 2.0) * (1.0 - pow(cosTheta, 2.0));\\n\\tfloat cosTheta2Sq = 1.0 - sinTheta2Sq;\\n\\tif (cosTheta2Sq < 0.0) {\\n\\t\\treturn vec3(1.0);\\n\\t}\\n\\tfloat cosTheta2 = sqrt(cosTheta2Sq);\\n\\tfloat r0 = iridescence_iorToFresnel(iridescenceIor, outsideIor);\\n\\tfloat r12 = iridescence_fresnel(cosTheta, r0);\\n\\tfloat r21 = r12;\\n\\tfloat t121 = 1.0 - r12;\\n\\tfloat phi12 = iridescenceIor < outsideIor ? PI : 0.0;\\n\\tfloat phi21 = PI - phi12;\\n\\tvec3 baseIor = iridescence_fresnelToIor(base_f0 + vec3(0.0001));\\n\\tvec3 r1 = iridescence_iorToFresnel(baseIor, iridescenceIor);\\n\\tvec3 r23 = iridescence_fresnel(cosTheta2, r1);\\n\\tvec3 phi23 = vec3(0.0);\\n\\tif (baseIor[0] < iridescenceIor) phi23[0] = PI;\\n\\tif (baseIor[1] < iridescenceIor) phi23[1] = PI;\\n\\tif (baseIor[2] < iridescenceIor) phi23[2] = PI;\\n\\tfloat opd = 2.0 * iridescenceIor * iridescenceThickness * cosTheta2;\\n\\tvec3 phi = vec3(phi21) + phi23; \\n\\tvec3 r123Sq = clamp(r12 * r23, 1e-5, 0.9999);\\n\\tvec3 r123 = sqrt(r123Sq);\\n\\tvec3 rs = pow(t121, 2.0) * r23 / (1.0 - r123Sq);\\n\\tvec3 c0 = r12 + rs;\\n\\tvec3 i = c0;\\n\\tvec3 cm = rs - t121;\\n\\tfor (int m = 1; m <= 2; m++) {\\n\\t\\tcm *= r123;\\n\\t\\tvec3 sm = 2.0 * iridescence_sensitivity(float(m) * opd, float(m) * phi);\\n\\t\\ti += cm * sm;\\n\\t}\\n\\treturn max(i, vec3(0.0));\\n}\\nvec3 getIridescence(float cosTheta, vec3 specularity, float iridescenceThickness) {\\n\\treturn calcIridescence(1.0, cosTheta, specularity, iridescenceThickness);\\n}\\n`;\\n\\nvar iridescence_default$1 = `\\n#ifdef STD_IRIDESCENCE_CONSTANT\\nuniform float material_iridescence;\\n#endif\\nvoid getIridescence() {\\n\\tfloat iridescence = 1.0;\\n\\t#ifdef STD_IRIDESCENCE_CONSTANT\\n\\tiridescence *= material_iridescence;\\n\\t#endif\\n\\t#ifdef STD_IRIDESCENCE_TEXTURE\\n\\tiridescence *= texture2DBias({STD_IRIDESCENCE_TEXTURE_NAME}, {STD_IRIDESCENCE_TEXTURE_UV}, textureBias).{STD_IRIDESCENCE_TEXTURE_CHANNEL};\\n\\t#endif\\n\\tdIridescence = iridescence; \\n}\\n`;\\n\\nvar iridescenceThickness_default$1 = `\\nuniform float material_iridescenceThicknessMax;\\n#ifdef STD_IRIDESCENCETHICKNESS_TEXTURE\\nuniform float material_iridescenceThicknessMin;\\n#endif\\nvoid getIridescenceThickness() {\\n\\t#ifdef STD_IRIDESCENCETHICKNESS_TEXTURE\\n\\t\\tfloat blend = texture2DBias({STD_IRIDESCENCETHICKNESS_TEXTURE_NAME}, {STD_IRIDESCENCETHICKNESS_TEXTURE_UV}, textureBias).{STD_IRIDESCENCETHICKNESS_TEXTURE_CHANNEL};\\n\\t\\tfloat iridescenceThickness = mix(material_iridescenceThicknessMin, material_iridescenceThicknessMax, blend);\\n\\t#else\\n\\t\\tfloat iridescenceThickness = material_iridescenceThicknessMax;\\n\\t#endif\\n\\tdIridescenceThickness = iridescenceThickness; \\n}\\n`;\\n\\nvar ior_default$1 = `\\n#ifdef STD_IOR_CONSTANT\\nuniform float material_refractionIndex;\\n#endif\\nvoid getIor() {\\n#ifdef STD_IOR_CONSTANT\\n\\tdIor = material_refractionIndex;\\n#else\\n\\tdIor = 1.0 / 1.5;\\n#endif\\n}\\n`;\\n\\nvar lightDeclaration_default$1 = `\\n#if defined(LIGHT{i})\\n\\tuniform vec3 light{i}_color;\\n\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\tuniform vec3 light{i}_direction;\\n\\t#else\\n\\t\\t#define LIT_CODE_LIGHTS_POINT\\n\\t\\tuniform vec3 light{i}_position;\\n\\t\\tuniform float light{i}_radius;\\n\\t\\t#if LIGHT{i}TYPE == SPOT\\n\\t\\t\\t#define LIT_CODE_LIGHTS_SPOT\\n\\t\\t\\tuniform vec3 light{i}_direction;\\n\\t\\t\\tuniform float light{i}_innerConeAngle;\\n\\t\\t\\tuniform float light{i}_outerConeAngle;\\n\\t\\t#endif\\n\\t#endif\\n\\t#if LIGHT{i}SHAPE != PUNCTUAL\\n\\t\\t#define LIT_CODE_FALLOFF_SQUARED\\n\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\tuniform vec3 light{i}_position;\\n\\t\\t#endif\\n\\t\\tuniform vec3 light{i}_halfWidth;\\n\\t\\tuniform vec3 light{i}_halfHeight;\\n\\t#else\\n\\t\\t#if LIGHT{i}FALLOFF == LINEAR\\n\\t\\t\\t#define LIT_CODE_FALLOFF_LINEAR\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}FALLOFF == INVERSESQUARED\\n\\t\\t\\t#define LIT_CODE_FALLOFF_SQUARED\\n\\t\\t#endif\\n\\t#endif\\n\\t#if defined(LIGHT{i}CASTSHADOW)\\n\\t\\t#if LIGHT{i}TYPE != OMNI\\n\\t\\t\\tuniform mat4 light{i}_shadowMatrix;\\n\\t\\t#endif\\n\\t\\tuniform float light{i}_shadowIntensity;\\n\\t\\tuniform vec4 light{i}_shadowParams;\\n\\t\\t#if LIGHT{i}SHADOWTYPE == PCSS_32F\\n\\t\\t\\tuniform float light{i}_shadowSearchArea;\\n\\t\\t\\tuniform vec4 light{i}_cameraParams;\\n\\t\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\t\\tuniform vec4 light{i}_softShadowParams;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\tuniform mat4 light{i}_shadowMatrixPalette[4];\\n\\t\\t\\tuniform vec4 light{i}_shadowCascadeDistances;\\n\\t\\t\\tuniform int light{i}_shadowCascadeCount;\\n\\t\\t\\tuniform float light{i}_shadowCascadeBlend;\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}TYPE == OMNI\\n\\t\\t\\t#if defined(LIGHT{i}SHADOW_PCF)\\n\\t\\t\\t\\tuniform samplerCubeShadow light{i}_shadowMap;\\n\\t\\t\\t#else\\n\\t\\t\\t\\tuniform samplerCube light{i}_shadowMap;\\n\\t\\t\\t#endif\\n\\t\\t#else\\n\\t\\t\\t#if defined(LIGHT{i}SHADOW_PCF)\\n\\t\\t\\t\\tuniform sampler2DShadow light{i}_shadowMap;\\n\\t\\t\\t#else\\n\\t\\t\\t\\tuniform sampler2D light{i}_shadowMap;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t#endif\\n\\t#if defined(LIGHT{i}COOKIE)\\n\\t\\t#define LIT_CODE_COOKIE\\n\\t\\t#if LIGHT{i}TYPE == OMNI\\n\\t\\t\\tuniform samplerCube light{i}_cookie;\\n\\t\\t\\tuniform float light{i}_cookieIntensity;\\n\\t\\t\\tuniform mat4 light{i}_shadowMatrix;\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}TYPE == SPOT\\n\\t\\t\\tuniform sampler2D light{i}_cookie;\\n\\t\\t\\tuniform float light{i}_cookieIntensity;\\n\\t\\t\\t#if !defined(LIGHT{i}CASTSHADOW)\\n\\t\\t\\t\\tuniform mat4 light{i}_shadowMatrix;\\n\\t\\t\\t#endif\\n\\t\\t\\t#if defined(LIGHT{i}COOKIE_TRANSFORM)\\n\\t\\t\\t\\tuniform vec4 light{i}_cookieMatrix;\\n\\t\\t\\t\\tuniform vec2 light{i}_cookieOffset;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t#endif\\n#endif\\n`;\\n\\nvar lightDiffuseLambert_default$1 = `\\nfloat getLightDiffuse(vec3 worldNormal, vec3 viewDir, vec3 lightDirNorm) {\\n\\treturn max(dot(worldNormal, -lightDirNorm), 0.0);\\n}\\n`;\\n\\nvar lightDirPoint_default$1 = `\\nvec3 evalOmniLight(vec3 lightPosW) {\\n\\treturn vPositionW - lightPosW;\\n}\\n`;\\n\\nvar lightEvaluation_default$1 = `\\n#if defined(LIGHT{i})\\n\\tevaluateLight{i}(\\n\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\tiridescenceFresnel\\n\\t\\t#endif\\n\\t);\\n#endif\\n`;\\n\\nvar lightFunctionLight_default$1 = `\\n#if defined(LIGHT{i})\\nvoid evaluateLight{i}(\\n\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\tvec3 iridescenceFresnel\\n\\t#endif\\n) {\\n\\tvec3 lightColor = light{i}_color;\\n\\t#if LIGHT{i}TYPE == DIRECTIONAL && !defined(LIT_SHADOW_CATCHER)\\n\\t\\tif (all(equal(lightColor, vec3(0.0)))) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t#endif\\n\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\tdLightDirNormW = light{i}_direction;\\n\\t\\tdAtten = 1.0;\\n\\t#else\\n\\t\\t\\n\\t\\tvec3 lightDirW = evalOmniLight(light{i}_position);\\n\\t\\tdLightDirNormW = normalize(lightDirW);\\n\\t\\t#if defined(LIGHT{i}COOKIE)\\n\\t\\t\\t#if LIGHT{i}TYPE == SPOT\\n\\t\\t\\t\\t#ifdef LIGHT{i}COOKIE_FALLOFF\\n\\t\\t\\t\\t\\t#ifdef LIGHT{i}COOKIE_TRANSFORM\\n\\t\\t\\t\\t\\t\\tvec3 cookieAttenuation = getCookie2DXform(light{i}_cookie, light{i}_shadowMatrix, light{i}_cookieIntensity, light{i}_cookieMatrix, light{i}_cookieOffset).{LIGHT{i}COOKIE_CHANNEL};\\n\\t\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\t\\tvec3 cookieAttenuation = getCookie2D(light{i}_cookie, light{i}_shadowMatrix, light{i}_cookieIntensity).{LIGHT{i}COOKIE_CHANNEL};\\n\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\t#ifdef LIGHT{i}COOKIE_TRANSFORM\\n\\t\\t\\t\\t\\t\\tvec3 cookieAttenuation = getCookie2DClipXform(light{i}_cookie, light{i}_shadowMatrix, light{i}_cookieIntensity, light{i}_cookieMatrix, light{i}_cookieOffset).{LIGHT{i}COOKIE_CHANNEL};\\n\\t\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\t\\tvec3 cookieAttenuation = getCookie2DClip(light{i}_cookie, light{i}_shadowMatrix, light{i}_cookieIntensity).{LIGHT{i}COOKIE_CHANNEL};\\n\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}TYPE == OMNI\\n\\t\\t\\t\\tvec3 cookieAttenuation = getCookieCube(light{i}_cookie, light{i}_shadowMatrix, light{i}_cookieIntensity).{LIGHT{i}COOKIE_CHANNEL};\\n\\t\\t\\t#endif\\n\\t\\t\\tlightColor *= cookieAttenuation;\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}SHAPE == PUNCTUAL\\n\\t\\t\\t#if LIGHT{i}FALLOFF == LINEAR\\n\\t\\t\\t\\tdAtten = getFalloffLinear(light{i}_radius, lightDirW);\\n\\t\\t\\t#else\\n\\t\\t\\t\\tdAtten = getFalloffInvSquared(light{i}_radius, lightDirW);\\n\\t\\t\\t#endif\\n\\t\\t#else\\n\\t\\t\\tdAtten = getFalloffWindow(light{i}_radius, lightDirW);\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}TYPE == SPOT\\n\\t\\t\\t#if !defined(LIGHT{i}COOKIE) || defined(LIGHT{i}COOKIE_FALLOFF)\\n\\t\\t\\t\\tdAtten *= getSpotEffect(light{i}_direction, light{i}_innerConeAngle, light{i}_outerConeAngle, dLightDirNormW);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t#endif\\n\\tif (dAtten < 0.00001) {\\n\\t\\treturn;\\n\\t}\\n\\t#if LIGHT{i}SHAPE != PUNCTUAL\\n\\t\\t#if LIGHT{i}SHAPE == RECT\\n\\t\\t\\tcalcRectLightValues(light{i}_position, light{i}_halfWidth, light{i}_halfHeight);\\n\\t\\t#elif LIGHT{i}SHAPE == DISK\\n\\t\\t\\tcalcDiskLightValues(light{i}_position, light{i}_halfWidth, light{i}_halfHeight);\\n\\t\\t#elif LIGHT{i}SHAPE == SPHERE\\n\\t\\t\\tcalcSphereLightValues(light{i}_position, light{i}_halfWidth, light{i}_halfHeight);\\n\\t\\t#endif\\n\\t#endif\\n\\t#if LIGHT{i}SHAPE != PUNCTUAL\\n\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\tfloat attenDiffuse = getLightDiffuse(litArgs_worldNormal, dViewDirW, dLightDirNormW);\\n\\t\\t#else\\n\\t\\t\\t#if LIGHT{i}SHAPE == RECT\\n\\t\\t\\t\\tfloat attenDiffuse = getRectLightDiffuse(litArgs_worldNormal, dViewDirW, lightDirW, dLightDirNormW) * 16.0;\\n\\t\\t\\t#elif LIGHT{i}SHAPE == DISK\\n\\t\\t\\t\\tfloat attenDiffuse = getDiskLightDiffuse(litArgs_worldNormal, dViewDirW, lightDirW, dLightDirNormW) * 16.0;\\n\\t\\t\\t#elif LIGHT{i}SHAPE == SPHERE\\n\\t\\t\\t\\tfloat attenDiffuse = getSphereLightDiffuse(litArgs_worldNormal, dViewDirW, lightDirW, dLightDirNormW) * 16.0;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t#else\\n\\t\\tdAtten *= getLightDiffuse(litArgs_worldNormal, vec3(0.0), dLightDirNormW);\\n\\t#endif\\n\\t#ifdef LIGHT{i}CASTSHADOW\\n\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\tfloat shadow = getShadow{i}(vec3(0.0));\\n\\t\\t#else\\n\\t\\t\\tfloat shadow = getShadow{i}(lightDirW);\\n\\t\\t#endif\\n\\t\\tshadow = mix(1.0, shadow, light{i}_shadowIntensity);\\n\\t\\tdAtten *= shadow;\\n\\t\\t#if defined(LIT_SHADOW_CATCHER) && LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\tdShadowCatcher *= shadow;\\n\\t\\t#endif\\t\\t\\t\\n\\t#endif\\n\\t#if LIGHT{i}SHAPE != PUNCTUAL\\n\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\tdDiffuseLight += ((attenDiffuse * dAtten) * lightColor) * (1.0 - dLTCSpecFres);\\n\\t\\t#else\\n\\t\\t\\tdDiffuseLight += (attenDiffuse * dAtten) * lightColor;\\n\\t\\t#endif\\t\\t\\t\\t\\t\\t\\n\\t#else\\n\\t\\t#if defined(AREA_LIGHTS) && defined(LIT_SPECULAR)\\n\\t\\t\\tdDiffuseLight += (dAtten * lightColor) * (1.0 - litArgs_specularity);\\n\\t\\t#else\\n\\t\\t\\tdDiffuseLight += dAtten * lightColor;\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef LIGHT{i}AFFECT_SPECULARITY\\n\\t\\t#if LIGHT{i}SHAPE != PUNCTUAL\\n\\t\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t\\t#if LIGHT{i}SHAPE == RECT\\n\\t\\t\\t\\t\\tccSpecularLight += ccLTCSpecFres * getRectLightSpecular(litArgs_clearcoat_worldNormal, dViewDirW) * dAtten * lightColor;\\n\\t\\t\\t\\t#elif LIGHT{i}SHAPE == DISK\\n\\t\\t\\t\\t\\tccSpecularLight += ccLTCSpecFres * getDiskLightSpecular(litArgs_clearcoat_worldNormal, dViewDirW) * dAtten * lightColor;\\n\\t\\t\\t\\t#elif LIGHT{i}SHAPE == SPHERE\\n\\t\\t\\t\\t\\tccSpecularLight += ccLTCSpecFres * getSphereLightSpecular(litArgs_clearcoat_worldNormal, dViewDirW) * dAtten * lightColor;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\t\\t#if LIGHT{i}SHAPE == RECT\\n\\t\\t\\t\\t\\tdSpecularLight += dLTCSpecFres * getRectLightSpecular(litArgs_worldNormal, dViewDirW) * dAtten * lightColor;\\n\\t\\t\\t\\t#elif LIGHT{i}SHAPE == DISK\\n\\t\\t\\t\\t\\tdSpecularLight += dLTCSpecFres * getDiskLightSpecular(litArgs_worldNormal, dViewDirW) * dAtten * lightColor;\\n\\t\\t\\t\\t#elif LIGHT{i}SHAPE == SPHERE\\n\\t\\t\\t\\t\\tdSpecularLight += dLTCSpecFres * getSphereLightSpecular(litArgs_worldNormal, dViewDirW) * dAtten * lightColor;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t#else\\n\\t\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL && LIT_FRESNEL_MODEL != NONE\\n\\t\\t\\t\\t#define LIGHT{i}FRESNEL\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\t\\tvec3 halfDirW = normalize(-dLightDirNormW + dViewDirW);\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t\\tvec3 lightspecularCC = getLightSpecular(halfDirW, ccReflDirW, litArgs_clearcoat_worldNormal, dViewDirW, dLightDirNormW, litArgs_clearcoat_gloss, dTBN) * dAtten * lightColor;\\n\\t\\t\\t\\t#ifdef LIGHT{i}FRESNEL\\n\\t\\t\\t\\t\\tlightspecularCC *= getFresnelCC(dot(dViewDirW, halfDirW));\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\tccSpecularLight += lightspecularCC;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SHEEN\\n\\t\\t\\t\\tsSpecularLight += getLightSpecularSheen(halfDirW, litArgs_worldNormal, dViewDirW, dLightDirNormW, litArgs_sheen_gloss) * dAtten * lightColor;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\t\\tvec3 lightSpecular = getLightSpecular(halfDirW, dReflDirW, litArgs_worldNormal, dViewDirW, dLightDirNormW, litArgs_gloss, dTBN) * dAtten * lightColor;\\n\\t\\t\\t\\t#ifdef LIGHT{i}FRESNEL\\n\\t\\t\\t\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t\\t\\t\\tlightSpecular *= getFresnel(dot(dViewDirW, halfDirW), litArgs_gloss, litArgs_specularity, iridescenceFresnel, litArgs_iridescence_intensity);\\n\\t\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\t\\tlightSpecular *= getFresnel(dot(dViewDirW, halfDirW), litArgs_gloss, litArgs_specularity);\\n\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\tlightSpecular *= litArgs_specularity;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\n\\t\\t\\t\\tdSpecularLight += lightSpecular;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t#endif\\n}\\n#endif\\n`;\\n\\nvar lightFunctionShadow_default$1 = `\\n#ifdef LIGHT{i}CASTSHADOW\\n\\t#ifdef LIGHT{i}_SHADOW_SAMPLE_POINT\\n\\t\\tvec3 getShadowSampleCoordOmni{i}(vec4 shadowParams, vec3 worldPosition, vec3 lightPos, inout vec3 lightDir, vec3 lightDirNorm, vec3 normal) {\\n\\t\\t\\t#ifdef LIGHT{i}_SHADOW_SAMPLE_NORMAL_OFFSET\\n\\t\\t\\t\\tfloat distScale = length(lightDir);\\n\\t\\t\\t\\tvec3 surfacePosition = worldPosition + normal * shadowParams.y * clamp(1.0 - dot(normal, -lightDirNorm), 0.0, 1.0) * distScale;\\n\\t\\t\\t\\tlightDir = surfacePosition - lightPos;\\n\\t\\t\\t#endif\\n\\t\\t\\treturn lightDir;\\n\\t\\t}\\n\\t#endif\\n\\t#ifndef LIGHT{i}_SHADOW_SAMPLE_POINT\\n\\t\\tvec3 getShadowSampleCoord{i}(mat4 shadowTransform, vec4 shadowParams, vec3 worldPosition, vec3 lightPos, inout vec3 lightDir, vec3 lightDirNorm, vec3 normal) {\\n\\t\\t\\tvec3 surfacePosition = worldPosition;\\n\\t\\t\\t#ifdef LIGHT{i}_SHADOW_SAMPLE_SOURCE_ZBUFFER\\n\\t\\t\\t\\t#ifdef LIGHT{i}_SHADOW_SAMPLE_NORMAL_OFFSET\\n\\t\\t\\t\\t\\tsurfacePosition = surfacePosition + normal * shadowParams.y;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#else\\n\\t\\t\\t\\t#ifdef LIGHT{i}_SHADOW_SAMPLE_NORMAL_OFFSET\\n\\t\\t\\t\\t\\t#ifdef LIGHT{i}_SHADOW_SAMPLE_ORTHO\\n\\t\\t\\t\\t\\t\\tfloat distScale = 1.0;\\n\\t\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\t\\tfloat distScale = abs(dot(vPositionW - lightPos, lightDirNorm));\\n\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\tsurfacePosition = surfacePosition + normal * shadowParams.y * clamp(1.0 - dot(normal, -lightDirNorm), 0.0, 1.0) * distScale;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\tvec4 positionInShadowSpace = shadowTransform * vec4(surfacePosition, 1.0);\\n\\t\\t\\t#ifdef LIGHT{i}_SHADOW_SAMPLE_ORTHO\\n\\t\\t\\t\\tpositionInShadowSpace.z = saturate(positionInShadowSpace.z) - 0.0001;\\n\\t\\t\\t#else\\n\\t\\t\\t\\t#ifdef LIGHT{i}_SHADOW_SAMPLE_SOURCE_ZBUFFER\\n\\t\\t\\t\\t\\tpositionInShadowSpace.xyz /= positionInShadowSpace.w;\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\tpositionInShadowSpace.xy /= positionInShadowSpace.w;\\n\\t\\t\\t\\t\\tpositionInShadowSpace.z = length(lightDir) * shadowParams.w;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\treturn positionInShadowSpace.xyz;\\n\\t\\t}\\n\\t#endif\\n\\tfloat getShadow{i}(vec3 lightDirW) {\\n\\t\\t#if LIGHT{i}TYPE == OMNI\\n\\t\\t\\tvec3 shadowCoord = getShadowSampleCoordOmni{i}(light{i}_shadowParams, vPositionW, light{i}_position, lightDirW, dLightDirNormW, dVertexNormalW);\\n\\t\\t#else\\n\\t\\t\\t#ifdef LIGHT{i}_SHADOW_CASCADES\\n\\t\\t\\t\\tint cascadeIndex = getShadowCascadeIndex(light{i}_shadowCascadeDistances, light{i}_shadowCascadeCount);\\n\\t\\t\\t\\t#ifdef LIGHT{i}_SHADOW_CASCADE_BLEND\\n\\t\\t\\t\\t\\tcascadeIndex = ditherShadowCascadeIndex(cascadeIndex, light{i}_shadowCascadeDistances, light{i}_shadowCascadeCount, light{i}_shadowCascadeBlend);\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\tmat4 shadowMatrix = light{i}_shadowMatrixPalette[cascadeIndex];\\n\\t\\t\\t#else\\n\\t\\t\\t\\tmat4 shadowMatrix = light{i}_shadowMatrix;\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\t\\tvec3 shadowCoord = getShadowSampleCoord{i}(shadowMatrix, light{i}_shadowParams, vPositionW, vec3(0.0), lightDirW, dLightDirNormW, dVertexNormalW);\\n\\t\\t\\t#else\\n\\t\\t\\t\\tvec3 shadowCoord = getShadowSampleCoord{i}(shadowMatrix, light{i}_shadowParams, vPositionW, light{i}_position, lightDirW, dLightDirNormW, dVertexNormalW);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\tshadowCoord = fadeShadow(shadowCoord, light{i}_shadowCascadeDistances);\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == VSM_16F\\n\\t\\t\\t\\treturn getShadowVSM16(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, 5.54);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == VSM_32F\\n\\t\\t\\t\\treturn getShadowVSM32(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, 15.0);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCSS_32F\\n\\t\\t\\t\\t#if LIGHT{i}SHAPE != PUNCTUAL\\n\\t\\t\\t\\t\\tvec2 shadowSearchArea = vec2(length(light{i}_halfWidth), length(light{i}_halfHeight)) * light{i}_shadowSearchArea;\\n\\t\\t\\t\\t\\treturn getShadowPCSS(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, light{i}_cameraParams, shadowSearchArea, lightDirW);\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\treturn getShadowPCSS(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, light{i}_cameraParams, light{i}_softShadowParams, lightDirW);\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCF1_16F || LIGHT{i}SHADOWTYPE == PCF1_32F\\n\\t\\t\\t\\treturn getShadowPCF1x1(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCF3_16F || LIGHT{i}SHADOWTYPE == PCF3_32F\\n\\t\\t\\t\\treturn getShadowPCF3x3(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCF5_16F || LIGHT{i}SHADOWTYPE == PCF5_32F\\n\\t\\t\\t\\treturn getShadowPCF5x5(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}TYPE == SPOT\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == VSM_16F\\n\\t\\t\\t\\treturn getShadowSpotVSM16(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, 5.54, lightDirW);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == VSM_32F\\n\\t\\t\\t\\treturn getShadowSpotVSM32(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, 15.0, lightDirW);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCSS_32F\\n\\t\\t\\t\\t#if LIGHT{i}SHAPE != PUNCTUAL\\n\\t\\t\\t\\t\\tvec2 shadowSearchArea = vec2(length(light{i}_halfWidth), length(light{i}_halfHeight)) * light{i}_shadowSearchArea;\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\tvec2 shadowSearchArea = vec2(light{i}_shadowSearchArea);\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\treturn getShadowSpotPCSS(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, light{i}_cameraParams, shadowSearchArea, lightDirW);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCF1_16F || LIGHT{i}SHADOWTYPE == PCF1_32F\\n\\t\\t\\t\\treturn getShadowSpotPCF1x1(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCF3_16F || LIGHT{i}SHADOWTYPE == PCF3_32F\\n\\t\\t\\t\\treturn getShadowSpotPCF3x3(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCF5_16F || LIGHT{i}SHADOWTYPE == PCF5_32F\\n\\t\\t\\t\\treturn getShadowSpotPCF5x5(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}TYPE == OMNI\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCSS_32F\\n\\t\\t\\t\\t#if LIGHT{i}SHAPE != PUNCTUAL\\n\\t\\t\\t\\t\\tvec2 shadowSearchArea = vec2(length(light{i}_halfWidth), length(light{i}_halfHeight)) * light{i}_shadowSearchArea;\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\tvec2 shadowSearchArea = vec2(light{i}_shadowSearchArea);\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\treturn getShadowOmniPCSS(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, light{i}_cameraParams, shadowSearchArea, lightDirW);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCF1_16F || LIGHT{i}SHADOWTYPE == PCF1_32F\\n\\t\\t\\t\\treturn getShadowOmniPCF1x1(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, lightDirW);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCF3_16F || LIGHT{i}SHADOWTYPE == PCF3_32F\\n\\t\\t\\t\\treturn getShadowOmniPCF3x3(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, lightDirW);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t}\\n#endif\\n`;\\n\\nvar lighting_default$1 = `\\n#ifdef LIT_CLUSTERED_LIGHTS\\n\\t#define LIT_CODE_FALLOFF_LINEAR\\n\\t#define LIT_CODE_FALLOFF_SQUARED\\n\\t#define LIT_CODE_LIGHTS_POINT\\n\\t#define LIT_CODE_LIGHTS_SPOT\\n#endif\\n#ifdef AREA_LIGHTS\\n\\tuniform highp sampler2D areaLightsLutTex1;\\n\\tuniform highp sampler2D areaLightsLutTex2;\\n#endif\\n#ifdef LIT_LIGHTING\\n\\t#include \\\"lightDiffuseLambertPS\\\"\\n\\t#if defined(AREA_LIGHTS) || defined(LIT_CLUSTERED_AREA_LIGHTS)\\n\\t\\t#include \\\"ltcPS\\\"\\n\\t#endif\\n#endif\\n#ifdef SHADOW_DIRECTIONAL\\n\\t#include \\\"shadowCascadesPS\\\"\\n#endif\\n#if defined(SHADOW_KIND_PCF1)\\n\\t#include \\\"shadowPCF1PS\\\"\\n#endif\\n#if defined(SHADOW_KIND_PCF3)\\n\\t#include \\\"shadowPCF3PS\\\"\\n#endif\\n#if defined(SHADOW_KIND_PCF5)\\n\\t#include \\\"shadowPCF5PS\\\"\\n#endif\\n#if defined(SHADOW_KIND_PCSS)\\n\\t#include \\\"linearizeDepthPS\\\"\\n\\t#include \\\"shadowPCSSPS\\\"\\n\\t#include \\\"shadowSoftPS\\\"\\n#endif\\n#if defined(SHADOW_KIND_VSM)\\n\\t#include \\\"shadowEVSMPS\\\"\\n#endif\\n#ifdef LIT_CODE_FALLOFF_LINEAR\\n\\t#include \\\"falloffLinearPS\\\"\\n#endif\\n#ifdef LIT_CODE_FALLOFF_SQUARED\\n\\t#include \\\"falloffInvSquaredPS\\\"\\n#endif\\n#ifdef LIT_CODE_LIGHTS_POINT\\n\\t#include \\\"lightDirPointPS\\\"\\n#endif\\n#ifdef LIT_CODE_LIGHTS_SPOT\\n\\t#include \\\"spotPS\\\"\\n#endif\\n#ifdef LIT_CODE_COOKIE\\n\\t#include \\\"cookiePS\\\"\\n#endif\\n#ifdef LIT_CLUSTERED_LIGHTS\\n\\t#include \\\"clusteredLightPS\\\"\\n#endif\\n#ifdef LIGHT_COUNT > 0\\n\\t#include \\\"lightFunctionShadowPS, LIGHT_COUNT\\\"\\n\\t#include \\\"lightFunctionLightPS, LIGHT_COUNT\\\"\\n#endif\\n`;\\n\\nvar lightmapAdd_default$1 = `\\nvoid addLightMap(\\n\\tvec3 lightmap, \\n\\tvec3 dir, \\n\\tvec3 worldNormal, \\n\\tvec3 viewDir, \\n\\tvec3 reflectionDir, \\n\\tfloat gloss, \\n\\tvec3 specularity, \\n\\tvec3 vertexNormal, \\n\\tmat3 tbn\\n#if defined(LIT_IRIDESCENCE)\\n\\tvec3 iridescenceFresnel, \\n\\tfloat iridescenceIntensity\\n#endif\\n) {\\n\\t#if defined(LIT_SPECULAR) && defined(LIT_DIR_LIGHTMAP)\\n\\t\\tif (dot(dir, dir) < 0.0001) {\\n\\t\\t\\t\\tdDiffuseLight += lightmap;\\n\\t\\t} else {\\n\\t\\t\\tfloat vlight = saturate(dot(dir, -vertexNormal));\\n\\t\\t\\tfloat flight = saturate(dot(dir, -worldNormal));\\n\\t\\t\\tfloat nlight = (flight / max(vlight, 0.01)) * 0.5;\\n\\t\\t\\tdDiffuseLight += lightmap * nlight * 2.0;\\n\\t\\t\\tvec3 halfDir = normalize(-dir + viewDir);\\n\\t\\t\\tvec3 specularLight = lightmap * getLightSpecular(halfDir, reflectionDir, worldNormal, viewDir, dir, gloss, tbn);\\n\\t\\t\\t#ifdef LIT_SPECULAR_FRESNEL\\n\\t\\t\\t\\tspecularLight *= \\n\\t\\t\\t\\t\\tgetFresnel(dot(viewDir, halfDir), \\n\\t\\t\\t\\t\\tgloss, \\n\\t\\t\\t\\t\\tspecularity\\n\\t\\t\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t\\t\\t, iridescenceFresnel,\\n\\t\\t\\t\\t\\tiridescenceIntensity\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t#endif\\n\\t\\t\\tdSpecularLight += specularLight;\\n\\t\\t}\\n\\t#else\\n\\t\\tdDiffuseLight += lightmap;\\n\\t#endif\\n}\\n`;\\n\\nvar lightmap_default$1 = `\\n#ifdef STD_LIGHTMAP_DIR\\n\\tvec3 dLightmapDir;\\n\\tuniform sampler2D texture_dirLightMap;\\n#endif\\nvoid getLightMap() {\\n\\tdLightmap = vec3(1.0);\\n\\t#ifdef STD_LIGHT_TEXTURE\\n\\t\\tdLightmap *= {STD_LIGHT_TEXTURE_DECODE}(texture2DBias({STD_LIGHT_TEXTURE_NAME}, {STD_LIGHT_TEXTURE_UV}, textureBias)).{STD_LIGHT_TEXTURE_CHANNEL};\\n\\t\\t#ifdef STD_LIGHTMAP_DIR\\n\\t\\t\\tvec3 dir = texture2DBias(texture_dirLightMap, {STD_LIGHT_TEXTURE_UV}, textureBias).xyz * 2.0 - 1.0;\\n\\t\\t\\tfloat dirDot = dot(dir, dir);\\n\\t\\t\\tdLightmapDir = (dirDot > 0.001) ? dir / sqrt(dirDot) : vec3(0.0);\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef STD_LIGHT_VERTEX\\n\\t\\tdLightmap *= saturate(vVertexColor.{STD_LIGHT_VERTEX_CHANNEL});\\n\\t#endif\\n}\\n`;\\n\\nvar lightSpecularAnisoGGX_default$1 = `\\nfloat calcLightSpecular(float gloss, vec3 worldNormal, vec3 viewDir, vec3 h, vec3 lightDirNorm, mat3 tbn) {\\n\\tfloat PI = 3.141592653589793;\\n\\tfloat roughness = max((1.0 - gloss) * (1.0 - gloss), 0.001);\\n\\tfloat alphaRoughness = roughness * roughness;\\n\\tfloat anisotropy = dAnisotropy;\\n\\tvec2 direction = dAnisotropyRotation;\\n\\tfloat at = mix(alphaRoughness, 1.0, anisotropy * anisotropy);\\n\\tfloat ab = clamp(alphaRoughness, 0.001, 1.0);\\n\\tvec3 anisotropicT = normalize(tbn * vec3(direction, 0.0));\\n\\tvec3 anisotropicB = normalize(cross(tbn[2], anisotropicT));\\n\\tfloat NoH = dot(worldNormal, h);\\n\\tfloat ToH = dot(anisotropicT, h);\\n\\tfloat BoH = dot(anisotropicB, h);\\n\\tfloat a2 = at * ab;\\n\\tvec3 v = vec3(ab * ToH, at * BoH, a2 * NoH);\\n\\tfloat v2 = dot(v, v);\\n\\tfloat w2 = a2 / v2;\\n\\tfloat D = a2 * w2 * w2 * (1.0 / PI);\\n\\tfloat ToV = dot(anisotropicT, viewDir);\\n\\tfloat BoV = dot(anisotropicB, viewDir);\\n\\tfloat ToL = dot(anisotropicT, -lightDirNorm);\\n\\tfloat BoL = dot(anisotropicB, -lightDirNorm);\\n\\tfloat NoV = dot(worldNormal, viewDir);\\n\\tfloat NoL = dot(worldNormal, -lightDirNorm);\\n\\tfloat lambdaV = NoL * length(vec3(at * ToV, ab * BoV, NoV));\\n\\tfloat lambdaL = NoV * length(vec3(at * ToL, ab * BoL, NoL));\\n\\tfloat G = 0.5 / (lambdaV + lambdaL);\\n\\treturn D * G;\\n}\\nfloat getLightSpecular(vec3 h, vec3 reflDir, vec3 worldNormal, vec3 viewDir, vec3 lightDirNorm, float gloss, mat3 tbn) {\\n\\treturn calcLightSpecular(gloss, worldNormal, viewDir, h, lightDirNorm, tbn);\\n}\\n`;\\n\\nvar lightSpecularGGX_default$1 = `\\nfloat calcLightSpecular(float gloss, vec3 worldNormal, vec3 viewDir, vec3 h, vec3 lightDirNorm) {\\n\\tconst float PI = 3.141592653589793;\\n\\tfloat roughness = max((1.0 - gloss) * (1.0 - gloss), 0.001);\\n\\tfloat alpha = roughness * roughness;\\n\\tfloat NoH = max(dot(worldNormal, h), 0.0);\\n\\tfloat NoV = max(dot(worldNormal, viewDir), 0.0);\\n\\tfloat NoL = max(dot(worldNormal, -lightDirNorm), 0.0);\\n\\tfloat NoH2 = NoH * NoH;\\n\\tfloat denom = NoH2 * (alpha - 1.0) + 1.0;\\n\\tfloat D = alpha / (PI * denom * denom);\\n\\tfloat alpha2 = alpha * alpha;\\n\\tfloat lambdaV = NoL * sqrt(NoV * NoV * (1.0 - alpha2) + alpha2);\\n\\tfloat lambdaL = NoV * sqrt(NoL * NoL * (1.0 - alpha2) + alpha2);\\n\\tfloat G = 0.5 / max(lambdaV + lambdaL, 0.00001);\\n\\treturn D * G;\\n}\\nfloat getLightSpecular(vec3 h, vec3 reflDir, vec3 worldNormal, vec3 viewDir, vec3 lightDirNorm, float gloss, mat3 tbn) {\\n\\treturn calcLightSpecular(gloss, worldNormal, viewDir, h, lightDirNorm);\\n}\\n`;\\n\\nvar lightSpecularBlinn_default$1 = `\\nfloat calcLightSpecular(float gloss, vec3 worldNormal, vec3 h) {\\n\\tfloat nh = max( dot( h, worldNormal ), 0.0 );\\n\\tfloat specPow = exp2(gloss * 11.0);\\n\\tspecPow = max(specPow, 0.0001);\\n\\treturn pow(nh, specPow) * (specPow + 2.0) / 8.0;\\n}\\nfloat getLightSpecular(vec3 h, vec3 reflDir, vec3 worldNormal, vec3 viewDir, vec3 lightDirNorm, float gloss, mat3 tbn) {\\n\\treturn calcLightSpecular(gloss, worldNormal, h);\\n}\\n`;\\n\\nvar lightSheen_default$1 = `\\nfloat sheenD(vec3 normal, vec3 h, float roughness) {\\n\\tconst float PI = 3.141592653589793;\\n\\tfloat invR = 1.0 / (roughness * roughness);\\n\\tfloat cos2h = max(dot(normal, h), 0.0);\\n\\tcos2h *= cos2h;\\n\\tfloat sin2h = max(1.0 - cos2h, 0.0078125);\\n\\treturn (2.0 + invR) * pow(sin2h, invR * 0.5) / (2.0 * PI);\\n}\\nfloat sheenV(vec3 normal, vec3 viewDir, vec3 light) {\\n\\tfloat NoV = max(dot(normal, viewDir), 0.000001);\\n\\tfloat NoL = max(dot(normal, light), 0.000001);\\n\\treturn 1.0 / (4.0 * (NoL + NoV - NoL * NoV));\\n}\\nfloat getLightSpecularSheen(vec3 h, vec3 worldNormal, vec3 viewDir, vec3 lightDirNorm, float sheenGloss) {\\n\\tfloat D = sheenD(worldNormal, h, sheenGloss);\\n\\tfloat V = sheenV(worldNormal, viewDir, -lightDirNorm);\\n\\treturn D * V;\\n}\\n`;\\n\\nvar linearizeDepth_default$1 = `\\n#ifndef LINEARIZE_DEPTH\\n#define LINEARIZE_DEPTH\\nfloat linearizeDepthWithParams(float z, vec4 cameraParams) {\\n\\tif (cameraParams.w == 0.0)\\n\\t\\treturn (cameraParams.z * cameraParams.y) / (cameraParams.y + z * (cameraParams.z - cameraParams.y));\\n\\telse\\n\\t\\treturn cameraParams.z + z * (cameraParams.y - cameraParams.z);\\n}\\n#ifndef CAMERAPLANES\\n\\t#define CAMERAPLANES\\n\\tuniform vec4 camera_params;\\n#endif\\nfloat linearizeDepth(float z) {\\n\\treturn linearizeDepthWithParams(z, camera_params);\\n}\\n#endif\\n`;\\n\\nvar litForwardBackend_default$1 = `\\nvoid evaluateBackend() {\\n\\t#ifdef LIT_SSAO\\n\\t\\tlitArgs_ao *= texture2DLod(ssaoTexture, gl_FragCoord.xy * ssaoTextureSizeInv, 0.0).r;\\n\\t#endif\\n\\t#ifdef LIT_NEEDS_NORMAL\\n\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\tgetReflDir(litArgs_worldNormal, dViewDirW, litArgs_gloss, dTBN);\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\tccReflDirW = normalize(-reflect(dViewDirW, litArgs_clearcoat_worldNormal));\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef LIT_SPECULAR_OR_REFLECTION\\n\\t\\t#ifdef LIT_METALNESS\\n\\t\\t\\tfloat f0 = 1.0 / litArgs_ior;\\n\\t\\t\\tf0 = (f0 - 1.0) / (f0 + 1.0);\\n\\t\\t\\tf0 *= f0;\\n\\t\\t\\t#ifdef LIT_SPECULARITY_FACTOR\\n\\t\\t\\t\\tlitArgs_specularity = getSpecularModulate(litArgs_specularity, litArgs_albedo, litArgs_metalness, f0, litArgs_specularityFactor);\\n\\t\\t\\t#else\\n\\t\\t\\t\\tlitArgs_specularity = getSpecularModulate(litArgs_specularity, litArgs_albedo, litArgs_metalness, f0, 1.0);\\n\\t\\t\\t#endif\\n\\t\\t\\tlitArgs_albedo = getAlbedoModulate(litArgs_albedo, litArgs_metalness);\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_IRIDESCENCE\\n\\t\\t\\tvec3 iridescenceFresnel = getIridescence(saturate(dot(dViewDirW, litArgs_worldNormal)), litArgs_specularity, litArgs_iridescence_thickness);\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef LIT_ADD_AMBIENT\\n\\t\\taddAmbient(litArgs_worldNormal);\\n\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\tdDiffuseLight = dDiffuseLight * (1.0 - litArgs_specularity);\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_SEPARATE_AMBIENT\\n\\t\\t\\tvec3 dAmbientLight = dDiffuseLight;\\n\\t\\t\\tdDiffuseLight = vec3(0);\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifndef LIT_OLD_AMBIENT\\n\\t\\tdDiffuseLight *= material_ambient;\\n\\t#endif\\n\\t#ifdef LIT_AO\\n\\t\\t#ifndef LIT_OCCLUDE_DIRECT\\n\\t\\t\\toccludeDiffuse(litArgs_ao);\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef LIT_LIGHTMAP\\n\\t\\taddLightMap(\\n\\t\\t\\tlitArgs_lightmap, \\n\\t\\t\\tlitArgs_lightmapDir, \\n\\t\\t\\tlitArgs_worldNormal, \\n\\t\\t\\tdViewDirW, \\n\\t\\t\\tdReflDirW, \\n\\t\\t\\tlitArgs_gloss, \\n\\t\\t\\tlitArgs_specularity, \\n\\t\\t\\tdVertexNormalW,\\n\\t\\t\\tdTBN\\n\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t, iridescenceFresnel,\\n\\t\\t\\tlitArgs_iridescence_intensity\\n\\t\\t#endif\\n\\t\\t);\\n\\t#endif\\n\\t#ifdef LIT_LIGHTING || LIT_REFLECTIONS\\n\\t\\t#ifdef LIT_REFLECTIONS\\n\\t\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t\\taddReflectionCC(ccReflDirW, litArgs_clearcoat_gloss);\\n\\t\\t\\t\\n\\t\\t\\t\\t#ifdef LIT_SPECULAR_FRESNEL\\n\\t\\t\\t\\t\\tccFresnel = getFresnelCC(dot(dViewDirW, litArgs_clearcoat_worldNormal));\\n\\t\\t\\t\\t\\tccReflection *= ccFresnel;\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\tccFresnel = 0.0;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SPECULARITY_FACTOR\\n\\t\\t\\t\\tccReflection *= litArgs_specularityFactor;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SHEEN\\n\\t\\t\\t\\taddReflectionSheen(litArgs_worldNormal, dViewDirW, litArgs_sheen_gloss);\\n\\t\\t\\t#endif\\n\\t\\t\\taddReflection(dReflDirW, litArgs_gloss);\\n\\t\\t\\t#ifdef LIT_FRESNEL_MODEL\\n\\t\\t\\t\\tdReflection.rgb *= getFresnel(\\n\\t\\t\\t\\t\\tdot(dViewDirW, litArgs_worldNormal), \\n\\t\\t\\t\\t\\tlitArgs_gloss, \\n\\t\\t\\t\\t\\tlitArgs_specularity\\n\\t\\t\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t\\t\\t, iridescenceFresnel,\\n\\t\\t\\t\\t\\tlitArgs_iridescence_intensity\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t#else\\n\\t\\t\\t\\tdReflection.rgb *= litArgs_specularity;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#ifdef AREA_LIGHTS\\n\\t\\t\\tdSpecularLight *= litArgs_specularity;\\n\\t\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\t\\tcalcLTCLightValues(litArgs_gloss, litArgs_worldNormal, dViewDirW, litArgs_specularity, litArgs_clearcoat_gloss, litArgs_clearcoat_worldNormal, litArgs_clearcoat_specularity);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t\\n\\t\\t#ifdef LIGHT_COUNT > 0\\n\\t\\t\\t#include \\\"lightEvaluationPS, LIGHT_COUNT\\\"\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_CLUSTERED_LIGHTS\\n\\t\\t\\taddClusteredLights(litArgs_worldNormal, dViewDirW, dReflDirW,\\n\\t\\t\\t\\t#if defined(LIT_CLEARCOAT)\\n\\t\\t\\t\\t\\t\\tccReflDirW,\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\t\\tlitArgs_gloss, litArgs_specularity, dVertexNormalW, dTBN, \\n\\t\\t\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t\\t\\t\\tiridescenceFresnel,\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\t\\tlitArgs_clearcoat_worldNormal, litArgs_clearcoat_gloss, litArgs_sheen_gloss, litArgs_iridescence_intensity\\n\\t\\t\\t);\\n\\t\\t#endif\\n\\t\\t#ifdef AREA_LIGHTS\\n\\t\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t\\tlitArgs_clearcoat_specularity = 1.0;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\t\\tlitArgs_specularity = vec3(1);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_REFRACTION\\n\\t\\t\\taddRefraction(\\n\\t\\t\\t\\tlitArgs_worldNormal, \\n\\t\\t\\t\\tdViewDirW, \\n\\t\\t\\t\\tlitArgs_thickness, \\n\\t\\t\\t\\tlitArgs_gloss, \\n\\t\\t\\t\\tlitArgs_specularity, \\n\\t\\t\\t\\tlitArgs_albedo, \\n\\t\\t\\t\\tlitArgs_transmission,\\n\\t\\t\\t\\tlitArgs_ior,\\n\\t\\t\\t\\tlitArgs_dispersion\\n\\t\\t\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t\\t\\t, iridescenceFresnel, \\n\\t\\t\\t\\t\\tlitArgs_iridescence_intensity\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t);\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef LIT_AO\\n\\t\\t#ifdef LIT_OCCLUDE_DIRECT\\n\\t\\t\\toccludeDiffuse(litArgs_ao);\\n\\t\\t#endif\\n\\t\\t#if LIT_OCCLUDE_SPECULAR != NONE\\n\\t\\t\\toccludeSpecular(litArgs_gloss, litArgs_ao, litArgs_worldNormal, dViewDirW);\\n\\t\\t#endif\\n\\t#endif\\n\\t#if !defined(LIT_OPACITY_FADES_SPECULAR)\\n\\t\\t#if LIT_BLEND_TYPE == NORMAL || LIT_BLEND_TYPE == PREMULTIPLIED\\n\\t\\t\\tfloat specLum = dot((dSpecularLight + dReflection.rgb * dReflection.a), vec3( 0.2126, 0.7152, 0.0722 ));\\n\\t\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t\\tspecLum += dot(ccSpecularLight * litArgs_clearcoat_specularity + ccReflection * litArgs_clearcoat_specularity, vec3( 0.2126, 0.7152, 0.0722 ));\\n\\t\\t\\t#endif\\n\\t\\t\\tlitArgs_opacity = clamp(litArgs_opacity + gammaCorrectInput(specLum), 0.0, 1.0);\\n\\t\\t#endif\\n\\t\\tlitArgs_opacity *= material_alphaFade;\\n\\t#endif\\n\\t#ifdef LIT_LIGHTMAP_BAKING\\n\\t\\t#ifdef LIT_LIGHTMAP_BAKING_COLOR\\n\\t\\t\\t#include \\\"bakeLmEndPS\\\"\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_LIGHTMAP_BAKING_DIR\\n\\t\\t\\t#include \\\"bakeDirLmEndPS\\\"\\n\\t\\t#endif\\n\\t#else\\n\\t\\t#include \\\"endPS\\\"\\n\\t\\t#include \\\"outputAlphaPS\\\"\\n\\t#endif\\n\\t#ifdef LIT_MSDF\\n\\t\\tgl_FragColor = applyMsdf(gl_FragColor);\\n\\t#endif\\n\\t#include \\\"outputPS\\\"\\n\\t#include \\\"debugOutputPS\\\"\\n\\t#ifdef LIT_SHADOW_CATCHER\\n\\t\\tgl_FragColor.rgb = vec3(dShadowCatcher);\\n\\t#endif\\n}\\n`;\\n\\nvar litForwardDeclaration_default$1 = `\\nvec3 sReflection;\\nvec3 dVertexNormalW;\\nvec3 dTangentW;\\nvec3 dBinormalW;\\nvec3 dViewDirW;\\nvec3 dReflDirW;\\nvec3 ccReflDirW;\\nvec3 dLightDirNormW;\\nfloat dAtten;\\nmat3 dTBN;\\nvec4 dReflection;\\nvec3 dDiffuseLight;\\nvec3 dSpecularLight;\\nfloat ccFresnel;\\nvec3 ccReflection;\\nvec3 ccSpecularLight;\\nfloat ccSpecularityNoFres;\\nvec3 sSpecularLight;\\n#ifdef LIT_DISPERSION\\n\\tuniform float material_dispersion;\\n#endif\\n#ifndef LIT_OPACITY_FADES_SPECULAR\\n\\tuniform float material_alphaFade;\\n#endif\\n#ifdef LIT_SSAO\\n\\tuniform sampler2D ssaoTexture;\\n\\tuniform vec2 ssaoTextureSizeInv;\\n#endif\\n#ifdef LIT_SHADOW_CATCHER\\n\\tfloat dShadowCatcher = 1.0;\\n#endif\\n#if LIGHT_COUNT > 0\\n\\t#include \\\"lightDeclarationPS, LIGHT_COUNT\\\"\\n#endif\\n#ifdef LIT_SPECULAR\\n\\t#if LIT_FRESNEL_MODEL == NONE && !defined(LIT_REFLECTIONS) && !defined(LIT_DIFFUSE_MAP) \\n\\t\\t#define LIT_OLD_AMBIENT\\n\\t#endif\\n#endif\\n#ifdef STD_LIGHTMAP_DIR\\n\\tuniform float bakeDir;\\n#endif\\n#ifdef LIT_LIGHTMAP_BAKING_ADD_AMBIENT\\n\\tuniform float ambientBakeOcclusionContrast;\\n\\tuniform float ambientBakeOcclusionBrightness;\\n#endif\\n`;\\n\\nvar litForwardMain_default$1 = `\\nvoid main(void) {\\n\\t#include \\\"litUserMainStartPS\\\"\\n\\tdReflection = vec4(0);\\n\\t#ifdef LIT_CLEARCOAT\\n\\t\\tccSpecularLight = vec3(0);\\n\\t\\tccReflection = vec3(0);\\n\\t#endif\\n\\t#if LIT_NONE_SLICE_MODE == SLICED\\n\\t\\t#include \\\"startNineSlicedPS\\\"\\n\\t#elif LIT_NONE_SLICE_MODE == TILED\\n\\t\\t#include \\\"startNineSlicedTiledPS\\\"\\n\\t#endif\\n\\t#ifdef LIT_NEEDS_NORMAL\\n\\t\\tdVertexNormalW = normalize(vNormalW);\\n\\t\\t#ifdef LIT_TANGENTS\\n\\t\\t\\t#if defined(LIT_HEIGHTS) || defined(LIT_USE_NORMALS) || defined(LIT_USE_CLEARCOAT_NORMALS) || defined(LIT_GGX_SPECULAR)\\n\\t\\t\\t\\tdTangentW = vTangentW;\\n\\t\\t\\t\\tdBinormalW = vBinormalW;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\tgetViewDir();\\n\\t\\t#ifdef LIT_TBN\\n\\t\\t\\tgetTBN(dTangentW, dBinormalW, dVertexNormalW);\\n\\t\\t\\t#ifdef LIT_TWO_SIDED_LIGHTING\\n\\t\\t\\t\\thandleTwoSidedLighting();\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t#endif\\n\\tevaluateFrontend();\\n\\t#include \\\"debugProcessFrontendPS\\\"\\n\\tevaluateBackend();\\n\\t#include \\\"litUserMainEndPS\\\"\\n}\\n`;\\n\\nvar litForwardPostCode_default$1 = `\\n#ifdef LIT_NEEDS_NORMAL\\n\\t#include \\\"cubeMapRotatePS\\\"\\n\\t#include \\\"cubeMapProjectPS\\\"\\n\\t#include \\\"envProcPS\\\"\\n#endif\\n#ifdef LIT_SPECULAR_OR_REFLECTION\\n\\t#ifdef LIT_METALNESS\\n\\t\\t#include \\\"metalnessModulatePS\\\"\\n\\t#endif\\n\\t#ifdef LIT_IRIDESCENCE\\n\\t\\t#include \\\"iridescenceDiffractionPS\\\"\\n\\t#endif\\n#endif\\n#if defined(LIT_SPECULAR_OR_REFLECTION) || defined(LIT_REFRACTION)\\n\\t#if LIT_FRESNEL_MODEL == SCHLICK\\n\\t\\t#include \\\"fresnelSchlickPS\\\"\\n\\t#endif\\n#endif\\n#ifdef LIT_AO\\n\\t#include \\\"aoDiffuseOccPS\\\"\\n\\t#include \\\"aoSpecOccPS\\\"\\n#endif\\n#if LIT_REFLECTION_SOURCE == ENVATLASHQ\\n\\t#include \\\"envAtlasPS\\\"\\n\\t#include \\\"reflectionEnvHQPS\\\"\\n#elif LIT_REFLECTION_SOURCE == ENVATLAS\\n\\t#include \\\"envAtlasPS\\\"\\n\\t#include \\\"reflectionEnvPS\\\"\\n#elif LIT_REFLECTION_SOURCE == CUBEMAP\\n\\t#include \\\"reflectionCubePS\\\"\\n#elif LIT_REFLECTION_SOURCE == SPHEREMAP\\n\\t#include \\\"reflectionSpherePS\\\"\\n#endif\\n#ifdef LIT_REFLECTIONS\\n\\t#ifdef LIT_CLEARCOAT\\n\\t\\t#include \\\"reflectionCCPS\\\"\\n\\t#endif\\n\\t#ifdef LIT_SHEEN\\n\\t\\t#include \\\"reflectionSheenPS\\\"\\n\\t#endif\\n#endif\\n#ifdef LIT_REFRACTION\\n\\t#if defined(LIT_DYNAMIC_REFRACTION)\\n\\t\\t#include \\\"refractionDynamicPS\\\"\\n\\t#elif defined(LIT_REFLECTIONS)\\n\\t\\t#include \\\"refractionCubePS\\\"\\n\\t#endif\\n#endif\\n#ifdef LIT_SHEEN\\n\\t#include \\\"lightSheenPS\\\"\\n#endif\\nuniform vec3 material_ambient;\\n#ifdef LIT_SPECULAR\\n\\t#ifdef LIT_LIGHTING\\n\\t\\t#ifdef LIT_GGX_SPECULAR\\n\\t\\t\\t#ifdef LIT_ANISOTROPY\\n\\t\\t\\t\\t#include \\\"lightSpecularAnisoGGXPS\\\"\\n\\t\\t\\t#else\\n\\t\\t\\t\\t#include \\\"lightSpecularGGXPS\\\"\\n\\t\\t\\t#endif\\n\\t\\t#else\\n\\t\\t\\t#include \\\"lightSpecularBlinnPS\\\"\\n\\t\\t#endif\\n\\t#endif\\n#endif\\n#include \\\"combinePS\\\"\\n#ifdef LIT_LIGHTMAP\\n\\t#include \\\"lightmapAddPS\\\"\\n#endif\\n#ifdef LIT_ADD_AMBIENT\\n\\t#include \\\"ambientPS\\\"\\n#endif\\n#ifdef LIT_MSDF\\n\\t#include \\\"msdfPS\\\"\\n#endif\\n#ifdef LIT_NEEDS_NORMAL\\n\\t#include \\\"viewDirPS\\\"\\n\\t#ifdef LIT_SPECULAR\\n\\t\\t#ifdef LIT_ANISOTROPY\\n\\t\\t\\t#include \\\"reflDirAnisoPS\\\"\\n\\t\\t#else\\n\\t\\t\\t#include \\\"reflDirPS\\\"\\n\\t\\t#endif\\n\\t#endif\\n#endif\\n#include \\\"lightingPS\\\"\\n`;\\n\\nvar litForwardPreCode_default$1 = `\\n#include \\\"basePS\\\"\\n#include \\\"sphericalPS\\\"\\n#include \\\"decodePS\\\"\\n#include \\\"gammaPS\\\"\\n#include \\\"tonemappingPS\\\"\\n#include \\\"fogPS\\\"\\n#if LIT_NONE_SLICE_MODE == SLICED\\n\\t#include \\\"baseNineSlicedPS\\\"\\n#elif LIT_NONE_SLICE_MODE == TILED\\n\\t#include \\\"baseNineSlicedTiledPS\\\"\\n#endif\\n#ifdef LIT_TBN\\n\\t#include \\\"TBNPS\\\"\\n\\t#ifdef LIT_TWO_SIDED_LIGHTING\\n\\t\\t#include \\\"twoSidedLightingPS\\\"\\n\\t#endif\\n#endif\\n`;\\n\\nvar litMain_default$3 = `\\n#include \\\"varyingsPS\\\"\\n#include \\\"litUserDeclarationPS\\\"\\n#include \\\"frontendDeclPS\\\"\\n#if defined(PICK_PASS) || defined(PREPASS_PASS)\\n\\t#include \\\"frontendCodePS\\\"\\n\\t#include \\\"litUserCodePS\\\"\\n\\t#include \\\"litOtherMainPS\\\"\\n#elif defined(SHADOW_PASS)\\n\\t#include \\\"frontendCodePS\\\"\\n\\t#include \\\"litUserCodePS\\\"\\n\\t#include \\\"litShadowMainPS\\\"\\n#else\\n\\t#include \\\"litForwardDeclarationPS\\\"\\n\\t#include \\\"litForwardPreCodePS\\\"\\n\\t#include \\\"frontendCodePS\\\"\\n\\t#include \\\"litForwardPostCodePS\\\"\\n\\t#include \\\"litForwardBackendPS\\\"\\n\\t#include \\\"litUserCodePS\\\"\\n\\t#include \\\"litForwardMainPS\\\"\\n#endif\\n`;\\n\\nvar litMain_default$2 = `\\n#include \\\"varyingsVS\\\"\\n#include  \\\"litUserDeclarationVS\\\"\\n#ifdef VERTEX_COLOR\\n\\tattribute vec4 vertex_color;\\n#endif\\n#ifdef NINESLICED\\n\\tvarying vec2 vMask;\\n\\tvarying vec2 vTiledUv;\\n\\tuniform mediump vec4 innerOffset;\\n\\tuniform mediump vec2 outerScale;\\n\\tuniform mediump vec4 atlasRect;\\n#endif\\nvec3 dPositionW;\\nmat4 dModelMatrix;\\n#include \\\"transformCoreVS\\\"\\n#ifdef UV0\\n\\tattribute vec2 vertex_texCoord0;\\n\\t#include \\\"uv0VS\\\"\\n#endif\\n#ifdef UV1\\n\\tattribute vec2 vertex_texCoord1;\\n\\t#include \\\"uv1VS\\\"\\n#endif\\n#ifdef LINEAR_DEPTH\\n\\t#ifndef VIEWMATRIX\\n\\t#define VIEWMATRIX\\n\\t\\tuniform mat4 matrix_view;\\n\\t#endif\\n#endif\\n#include \\\"transformVS\\\"\\n#ifdef NORMALS\\n\\t#include \\\"normalCoreVS\\\"\\n\\t#include \\\"normalVS\\\"\\n#endif\\n#ifdef TANGENTS\\n\\tattribute vec4 vertex_tangent;\\n#endif\\n#include \\\"uvTransformUniformsPS, UV_TRANSFORMS_COUNT\\\"\\n#ifdef MSDF\\n\\t#include \\\"msdfVS\\\"\\n#endif\\n#include  \\\"litUserCodeVS\\\"\\n#ifdef VERTEX_COLOR\\n\\tvec3 decodeGamma(vec3 raw) {\\n\\t\\treturn pow(raw, vec3(2.2));\\n\\t}\\n\\tvec4 gammaCorrectInput(vec4 color) {\\n\\t\\treturn vec4(decodeGamma(color.xyz), color.w);\\n\\t}\\n#endif\\nvoid main(void) {\\n\\t#include \\\"litUserMainStartVS\\\"\\n\\tgl_PointSize = 1.0;\\n\\tgl_Position = getPosition();\\n\\tvPositionW = getWorldPosition();\\n\\t#ifdef NORMALS\\n\\t\\tvNormalW = getNormal();\\n\\t#endif\\n\\t#ifdef TANGENTS\\n\\t\\tvTangentW = normalize(dNormalMatrix * vertex_tangent.xyz);\\n\\t\\tvBinormalW = cross(vNormalW, vTangentW) * vertex_tangent.w;\\n\\t#elif defined(GGX_SPECULAR)\\n\\t\\tvObjectSpaceUpW = normalize(dNormalMatrix * vec3(0, 1, 0));\\n\\t#endif\\n\\t#ifdef UV0\\n\\t\\tvec2 uv0 = getUv0();\\n\\t\\t#ifdef UV0_UNMODIFIED\\n\\t\\t\\tvUv0 = uv0;\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef UV1\\n\\t\\tvec2 uv1 = getUv1();\\n\\t\\t#ifdef UV1_UNMODIFIED\\n\\t\\t\\tvUv1 = uv1;\\n\\t\\t#endif\\n\\t#endif\\n\\t#include \\\"uvTransformVS, UV_TRANSFORMS_COUNT\\\"\\n\\t#ifdef VERTEX_COLOR\\n\\t\\t#ifdef STD_VERTEX_COLOR_GAMMA\\n\\t\\t\\tvVertexColor = gammaCorrectInput(vertex_color);\\n\\t\\t#else\\n\\t\\t\\tvVertexColor = vertex_color;\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef LINEAR_DEPTH\\n\\t\\tvLinearDepth = -(matrix_view * vec4(vPositionW, 1.0)).z;\\n\\t#endif\\n\\t#ifdef MSDF\\n\\t\\tunpackMsdfParams();\\n\\t#endif\\n\\t#include \\\"litUserMainEndVS\\\"\\n}\\n`;\\n\\nvar litOtherMain_default$1 = `\\n#ifdef PICK_PASS\\n\\t#include \\\"pickPS\\\"\\n#endif\\n#ifdef PREPASS_PASS\\n\\t#include \\\"floatAsUintPS\\\"\\n#endif\\nvoid main(void) {\\n\\t#include \\\"litUserMainStartPS\\\"\\n\\tevaluateFrontend();\\n\\t#ifdef PICK_PASS\\n\\t\\tpcFragColor0 = getPickOutput();\\n\\t\\t#ifdef DEPTH_PICK_PASS\\n\\t\\t\\tpcFragColor1 = getPickDepth();\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef PREPASS_PASS\\n\\t\\tgl_FragColor = float2vec4(vLinearDepth);\\n\\t#endif\\n\\t#include \\\"litUserMainEndPS\\\"\\n}\\n`;\\n\\nvar litShaderArgs_default$1 = `\\nvec3 litArgs_albedo;\\nfloat litArgs_opacity;\\nvec3 litArgs_emission;\\nvec3 litArgs_worldNormal;\\nfloat litArgs_ao;\\nvec3 litArgs_lightmap;\\nvec3 litArgs_lightmapDir;\\nfloat litArgs_metalness;\\nvec3 litArgs_specularity;\\nfloat litArgs_specularityFactor;\\nfloat litArgs_gloss;\\nfloat litArgs_sheen_gloss;\\nvec3 litArgs_sheen_specularity;\\nfloat litArgs_transmission;\\nfloat litArgs_thickness;\\nfloat litArgs_ior;\\nfloat litArgs_dispersion;\\nfloat litArgs_iridescence_intensity;\\nfloat litArgs_iridescence_thickness;\\nvec3 litArgs_clearcoat_worldNormal;\\nfloat litArgs_clearcoat_specularity;\\nfloat litArgs_clearcoat_gloss;\\n`;\\n\\nvar litShaderCore_default$1 = `\\n\\t#if LIT_NONE_SLICE_MODE == TILED\\n\\t\\tconst float textureBias = -1000.0;\\n\\t#else\\n\\t\\tuniform float textureBias;\\n\\t#endif\\n\\t#include \\\"litShaderArgsPS\\\"\\n`;\\n\\nvar litShadowMain_default$1 = `\\n#if LIGHT_TYPE != DIRECTIONAL\\n\\tuniform vec3 view_position;\\n\\tuniform float light_radius;\\n#endif\\n#if SHADOW_TYPE == PCSS_32F\\n\\t#include \\\"linearizeDepthPS\\\"\\n#endif\\nvoid main(void) {\\n\\t#include \\\"litUserMainStartPS\\\"\\n\\tevaluateFrontend();\\n\\t#ifdef PERSPECTIVE_DEPTH\\n\\t\\tfloat depth = gl_FragCoord.z;\\n\\t\\t#if SHADOW_TYPE == PCSS_32F\\n\\t\\t\\t#if LIGHT_TYPE != DIRECTIONAL\\n\\t\\t\\t\\tdepth = linearizeDepthWithParams(depth, camera_params);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t#else\\n\\t\\tfloat depth = min(distance(view_position, vPositionW) / light_radius, 0.99999);\\n\\t\\t#define MODIFIED_DEPTH\\n\\t#endif\\n\\t#if SHADOW_TYPE == VSM_16F || SHADOW_TYPE == VSM_32F\\n\\t\\t#if SHADOW_TYPE == VSM_32F\\n\\t\\t\\tfloat exponent = 15.0;\\n\\t\\t#else\\n\\t\\t\\tfloat exponent = 5.54;\\n\\t\\t#endif\\n\\t\\tdepth = 2.0 * depth - 1.0;\\n\\t\\tdepth =  exp(exponent * depth);\\n\\t\\tgl_FragColor = vec4(depth, depth*depth, 1.0, 1.0);\\n\\t#else\\n\\t\\t#if SHADOW_TYPE == PCSS_32F\\n\\t\\t\\tgl_FragColor.r = depth;\\n\\t\\t#else\\n\\t\\t\\t#ifdef MODIFIED_DEPTH\\n\\t\\t\\t\\tgl_FragDepth = depth;\\n\\t\\t\\t#endif\\n\\t\\t\\tgl_FragColor = vec4(1.0);\\n\\t\\t#endif\\n\\t#endif\\n\\t#include \\\"litUserMainEndPS\\\"\\n}\\n`;\\n\\nvar ltc_default$1 = `\\nmat3 transposeMat3( const in mat3 m ) {\\n\\tmat3 tmp;\\n\\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\\n\\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\\n\\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\\n\\treturn tmp;\\n}\\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\\n\\tconst float LUT_SIZE = 64.0;\\n\\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\\n\\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\\n\\tfloat dotNV = saturate( dot( N, V ) );\\n\\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\\n\\tuv = uv * LUT_SCALE + LUT_BIAS;\\n\\treturn uv;\\n}\\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\\n\\tfloat l = length( f );\\n\\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\\n}\\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\\n\\tfloat x = dot( v1, v2 );\\n\\tfloat y = abs( x );\\n\\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\\n\\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\\n\\tfloat v = a / b;\\n\\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\\n\\treturn cross( v1, v2 ) * theta_sintheta;\\n}\\nstruct Coords {\\n\\tvec3 coord0;\\n\\tvec3 coord1;\\n\\tvec3 coord2;\\n\\tvec3 coord3;\\n};\\nfloat LTC_EvaluateRect( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in Coords rectCoords) {\\n\\tvec3 v1 = rectCoords.coord1 - rectCoords.coord0;\\n\\tvec3 v2 = rectCoords.coord3 - rectCoords.coord0;\\n\\t\\n\\tvec3 lightNormal = cross( v1, v2 );\\n\\tfloat factor = sign(-dot( lightNormal, P - rectCoords.coord0 ));\\n\\tvec3 T1, T2;\\n\\tT1 = normalize( V - N * dot( V, N ) );\\n\\tT2 =  factor * cross( N, T1 );\\n\\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\\n\\tvec3 coords[ 4 ];\\n\\tcoords[ 0 ] = mat * ( rectCoords.coord0 - P );\\n\\tcoords[ 1 ] = mat * ( rectCoords.coord1 - P );\\n\\tcoords[ 2 ] = mat * ( rectCoords.coord2 - P );\\n\\tcoords[ 3 ] = mat * ( rectCoords.coord3 - P );\\n\\tcoords[ 0 ] = normalize( coords[ 0 ] );\\n\\tcoords[ 1 ] = normalize( coords[ 1 ] );\\n\\tcoords[ 2 ] = normalize( coords[ 2 ] );\\n\\tcoords[ 3 ] = normalize( coords[ 3 ] );\\n\\tvec3 vectorFormFactor = vec3( 0.0 );\\n\\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\\n\\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\\n\\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\\n\\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\\n\\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\\n\\treturn result;\\n}\\nCoords dLTCCoords;\\nCoords getLTCLightCoords(vec3 lightPos, vec3 halfWidth, vec3 halfHeight){\\n\\tCoords coords;\\n\\tcoords.coord0 = lightPos + halfWidth - halfHeight;\\n\\tcoords.coord1 = lightPos - halfWidth - halfHeight;\\n\\tcoords.coord2 = lightPos - halfWidth + halfHeight;\\n\\tcoords.coord3 = lightPos + halfWidth + halfHeight;\\n\\treturn coords;\\n}\\nfloat dSphereRadius;\\nCoords getSphereLightCoords(vec3 lightPos, vec3 halfWidth, vec3 halfHeight){\\n\\tdSphereRadius = max(length(halfWidth), length(halfHeight));\\n\\tvec3 f = reflect(normalize(lightPos - view_position), vNormalW);\\n\\tvec3 w = normalize(cross(f, halfHeight));\\n\\tvec3 h = normalize(cross(f, w));\\n\\treturn getLTCLightCoords(lightPos, w * dSphereRadius, h * dSphereRadius);\\n}\\nvec2 dLTCUV;\\n#ifdef LIT_CLEARCOAT\\n\\tvec2 ccLTCUV;\\n#endif\\nvec2 getLTCLightUV(float gloss, vec3 worldNormal, vec3 viewDir)\\n{\\n\\tfloat roughness = max((1.0 - gloss) * (1.0 - gloss), 0.001);\\n\\treturn LTC_Uv( worldNormal, viewDir, roughness );\\n}\\nvec3 dLTCSpecFres;\\n#ifdef LIT_CLEARCOAT\\n\\tvec3 ccLTCSpecFres;\\n#endif\\nvec3 getLTCLightSpecFres(vec2 uv, vec3 specularity)\\n{\\n\\tvec4 t2 = texture2DLod(areaLightsLutTex2, uv, 0.0);\\n\\treturn specularity * t2.x + ( vec3( 1.0 ) - specularity) * t2.y;\\n}\\nvoid calcLTCLightValues(float gloss, vec3 worldNormal, vec3 viewDir, vec3 specularity, float clearcoatGloss, vec3 clearcoatWorldNormal, float clearcoatSpecularity)\\n{\\n\\tdLTCUV = getLTCLightUV(gloss, worldNormal, viewDir);\\n\\tdLTCSpecFres = getLTCLightSpecFres(dLTCUV, specularity); \\n#ifdef LIT_CLEARCOAT\\n\\tccLTCUV = getLTCLightUV(clearcoatGloss, clearcoatWorldNormal, viewDir);\\n\\tccLTCSpecFres = getLTCLightSpecFres(ccLTCUV, vec3(clearcoatSpecularity));\\n#endif\\n}\\nvoid calcRectLightValues(vec3 lightPos, vec3 halfWidth, vec3 halfHeight) {\\n\\tdLTCCoords = getLTCLightCoords(lightPos, halfWidth, halfHeight);\\n}\\nvoid calcDiskLightValues(vec3 lightPos, vec3 halfWidth, vec3 halfHeight) {\\n\\tcalcRectLightValues(lightPos, halfWidth, halfHeight);\\n}\\nvoid calcSphereLightValues(vec3 lightPos, vec3 halfWidth, vec3 halfHeight) {\\n\\tdLTCCoords = getSphereLightCoords(lightPos, halfWidth, halfHeight);\\n}\\nvec3 SolveCubic(vec4 Coefficient)\\n{\\n\\tfloat pi = 3.14159;\\n\\tCoefficient.xyz /= Coefficient.w;\\n\\tCoefficient.yz /= 3.0;\\n\\tfloat A = Coefficient.w;\\n\\tfloat B = Coefficient.z;\\n\\tfloat C = Coefficient.y;\\n\\tfloat D = Coefficient.x;\\n\\tvec3 Delta = vec3(\\n\\t\\t-Coefficient.z * Coefficient.z + Coefficient.y,\\n\\t\\t-Coefficient.y * Coefficient.z + Coefficient.x,\\n\\t\\tdot(vec2(Coefficient.z, -Coefficient.y), Coefficient.xy)\\n\\t);\\n\\tfloat Discriminant = dot(vec2(4.0 * Delta.x, -Delta.y), Delta.zy);\\n\\tvec2 xlc, xsc;\\n\\t{\\n\\t\\tfloat A_a = 1.0;\\n\\t\\tfloat C_a = Delta.x;\\n\\t\\tfloat D_a = -2.0 * B * Delta.x + Delta.y;\\n\\t\\tfloat Theta = atan(sqrt(Discriminant), -D_a) / 3.0;\\n\\t\\tfloat x_1a = 2.0 * sqrt(-C_a) * cos(Theta);\\n\\t\\tfloat x_3a = 2.0 * sqrt(-C_a) * cos(Theta + (2.0 / 3.0) * pi);\\n\\t\\tfloat xl;\\n\\t\\tif ((x_1a + x_3a) > 2.0 * B)\\n\\t\\t\\txl = x_1a;\\n\\t\\telse\\n\\t\\t\\txl = x_3a;\\n\\t\\txlc = vec2(xl - B, A);\\n\\t}\\n\\t{\\n\\t\\tfloat A_d = D;\\n\\t\\tfloat C_d = Delta.z;\\n\\t\\tfloat D_d = -D * Delta.y + 2.0 * C * Delta.z;\\n\\t\\tfloat Theta = atan(D * sqrt(Discriminant), -D_d) / 3.0;\\n\\t\\tfloat x_1d = 2.0 * sqrt(-C_d) * cos(Theta);\\n\\t\\tfloat x_3d = 2.0 * sqrt(-C_d) * cos(Theta + (2.0 / 3.0) * pi);\\n\\t\\tfloat xs;\\n\\t\\tif (x_1d + x_3d < 2.0 * C)\\n\\t\\t\\txs = x_1d;\\n\\t\\telse\\n\\t\\t\\txs = x_3d;\\n\\t\\txsc = vec2(-D, xs + C);\\n\\t}\\n\\tfloat E =  xlc.y * xsc.y;\\n\\tfloat F = -xlc.x * xsc.y - xlc.y * xsc.x;\\n\\tfloat G =  xlc.x * xsc.x;\\n\\tvec2 xmc = vec2(C * F - B * G, -B * F + C * E);\\n\\tvec3 Root = vec3(xsc.x / xsc.y, xmc.x / xmc.y, xlc.x / xlc.y);\\n\\tif (Root.x < Root.y && Root.x < Root.z)\\n\\t\\tRoot.xyz = Root.yxz;\\n\\telse if (Root.z < Root.x && Root.z < Root.y)\\n\\t\\tRoot.xyz = Root.xzy;\\n\\treturn Root;\\n}\\nfloat LTC_EvaluateDisk(vec3 N, vec3 V, vec3 P, mat3 Minv, Coords points)\\n{\\n\\tvec3 T1 = normalize(V - N * dot(V, N));\\n\\tvec3 T2 = cross(N, T1);\\n\\tmat3 R = transposeMat3( mat3( T1, T2, N ) );\\n\\tvec3 L_[ 3 ];\\n\\tL_[ 0 ] = R * ( points.coord0 - P );\\n\\tL_[ 1 ] = R * ( points.coord1 - P );\\n\\tL_[ 2 ] = R * ( points.coord2 - P );\\n\\tvec3 C  = 0.5 * (L_[0] + L_[2]);\\n\\tvec3 V1 = 0.5 * (L_[1] - L_[2]);\\n\\tvec3 V2 = 0.5 * (L_[1] - L_[0]);\\n\\tC  = Minv * C;\\n\\tV1 = Minv * V1;\\n\\tV2 = Minv * V2;\\n\\tfloat a, b;\\n\\tfloat d11 = dot(V1, V1);\\n\\tfloat d22 = dot(V2, V2);\\n\\tfloat d12 = dot(V1, V2);\\n\\tif (abs(d12) / sqrt(d11 * d22) > 0.0001)\\n\\t{\\n\\t\\tfloat tr = d11 + d22;\\n\\t\\tfloat det = -d12 * d12 + d11 * d22;\\n\\t\\tdet = sqrt(det);\\n\\t\\tfloat u = 0.5 * sqrt(tr - 2.0 * det);\\n\\t\\tfloat v = 0.5 * sqrt(tr + 2.0 * det);\\n\\t\\tfloat e_max = (u + v) * (u + v);\\n\\t\\tfloat e_min = (u - v) * (u - v);\\n\\t\\tvec3 V1_, V2_;\\n\\t\\tif (d11 > d22)\\n\\t\\t{\\n\\t\\t\\tV1_ = d12 * V1 + (e_max - d11) * V2;\\n\\t\\t\\tV2_ = d12 * V1 + (e_min - d11) * V2;\\n\\t\\t}\\n\\t\\telse\\n\\t\\t{\\n\\t\\t\\tV1_ = d12*V2 + (e_max - d22)*V1;\\n\\t\\t\\tV2_ = d12*V2 + (e_min - d22)*V1;\\n\\t\\t}\\n\\t\\ta = 1.0 / e_max;\\n\\t\\tb = 1.0 / e_min;\\n\\t\\tV1 = normalize(V1_);\\n\\t\\tV2 = normalize(V2_);\\n\\t}\\n\\telse\\n\\t{\\n\\t\\ta = 1.0 / dot(V1, V1);\\n\\t\\tb = 1.0 / dot(V2, V2);\\n\\t\\tV1 *= sqrt(a);\\n\\t\\tV2 *= sqrt(b);\\n\\t}\\n\\tvec3 V3 = normalize(cross(V1, V2));\\n\\tif (dot(C, V3) < 0.0)\\n\\t\\tV3 *= -1.0;\\n\\tfloat L  = dot(V3, C);\\n\\tfloat x0 = dot(V1, C) / L;\\n\\tfloat y0 = dot(V2, C) / L;\\n\\tfloat E1 = inversesqrt(a);\\n\\tfloat E2 = inversesqrt(b);\\n\\ta *= L * L;\\n\\tb *= L * L;\\n\\tfloat c0 = a * b;\\n\\tfloat c1 = a * b * (1.0 + x0 * x0 + y0 * y0) - a - b;\\n\\tfloat c2 = 1.0 - a * (1.0 + x0 * x0) - b * (1.0 + y0 * y0);\\n\\tfloat c3 = 1.0;\\n\\tvec3 roots = SolveCubic(vec4(c0, c1, c2, c3));\\n\\tfloat e1 = roots.x;\\n\\tfloat e2 = roots.y;\\n\\tfloat e3 = roots.z;\\n\\tvec3 avgDir = vec3(a * x0 / (a - e2), b * y0 / (b - e2), 1.0);\\n\\tmat3 rotate = mat3(V1, V2, V3);\\n\\tavgDir = rotate * avgDir;\\n\\tavgDir = normalize(avgDir);\\n\\tfloat L1 = sqrt(-e2 / e3);\\n\\tfloat L2 = sqrt(-e2 / e1);\\n\\tfloat formFactor = max(0.0, L1 * L2 * inversesqrt((1.0 + L1 * L1) * (1.0 + L2 * L2)));\\n\\t\\n\\tconst float LUT_SIZE = 64.0;\\n\\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\\n\\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\\n\\tvec2 uv = vec2(avgDir.z * 0.5 + 0.5, formFactor);\\n\\tuv = uv*LUT_SCALE + LUT_BIAS;\\n\\tfloat scale = texture2DLod(areaLightsLutTex2, uv, 0.0).w;\\n\\treturn formFactor*scale;\\n}\\nfloat FixNan(float value) {\\n\\t#ifdef WEBGPU\\n\\t\\treturn value != value ? 0.0 : value;\\n\\t#else\\n\\t\\treturn isnan(value) ? 0.0 : value;\\n\\t#endif\\n}\\nfloat getRectLightDiffuse(vec3 worldNormal, vec3 viewDir, vec3 lightDir, vec3 lightDirNorm) {\\n\\treturn LTC_EvaluateRect( worldNormal, viewDir, vPositionW, mat3( 1.0 ), dLTCCoords );\\n}\\nfloat getDiskLightDiffuse(vec3 worldNormal, vec3 viewDir, vec3 lightDir, vec3 lightDirNorm) {\\n\\treturn FixNan(LTC_EvaluateDisk( worldNormal, viewDir, vPositionW, mat3( 1.0 ), dLTCCoords ));\\n}\\nfloat getSphereLightDiffuse(vec3 worldNormal, vec3 viewDir, vec3 lightDir, vec3 lightDirNorm) {\\n\\tfloat falloff = dSphereRadius / (dot(lightDir, lightDir) + dSphereRadius);\\n\\treturn FixNan(getLightDiffuse(worldNormal, viewDir, lightDirNorm) * falloff);\\n}\\nmat3 getLTCLightInvMat(vec2 uv)\\n{\\n\\tvec4 t1 = texture2DLod(areaLightsLutTex1, uv, 0.0);\\n\\treturn mat3(\\n\\t\\tvec3( t1.x, 0, t1.y ),\\n\\t\\tvec3(\\t0, 1,\\t0 ),\\n\\t\\tvec3( t1.z, 0, t1.w )\\n\\t);\\n}\\nfloat calcRectLightSpecular(vec3 worldNormal, vec3 viewDir, vec2 uv) {\\n\\tmat3 mInv = getLTCLightInvMat(uv);\\n\\treturn LTC_EvaluateRect( worldNormal, viewDir, vPositionW, mInv, dLTCCoords );\\n}\\nfloat getRectLightSpecular(vec3 worldNormal, vec3 viewDir) {\\n\\treturn calcRectLightSpecular(worldNormal, viewDir, dLTCUV);\\n}\\nfloat calcDiskLightSpecular(vec3 worldNormal, vec3 viewDir, vec2 uv) {\\n\\tmat3 mInv = getLTCLightInvMat(uv);\\n\\treturn LTC_EvaluateDisk( worldNormal, viewDir, vPositionW, mInv, dLTCCoords );\\n}\\nfloat getDiskLightSpecular(vec3 worldNormal, vec3 viewDir) {\\n\\treturn calcDiskLightSpecular(worldNormal, viewDir, dLTCUV);\\n}\\nfloat getSphereLightSpecular(vec3 worldNormal, vec3 viewDir) {\\n\\treturn calcDiskLightSpecular(worldNormal, viewDir, dLTCUV);\\n}\\n`;\\n\\nvar metalness_default$1 = `\\n#ifdef STD_METALNESS_CONSTANT\\nuniform float material_metalness;\\n#endif\\nvoid getMetalness() {\\n\\tfloat metalness = 1.0;\\n\\t#ifdef STD_METALNESS_CONSTANT\\n\\tmetalness *= material_metalness;\\n\\t#endif\\n\\t#ifdef STD_METALNESS_TEXTURE\\n\\tmetalness *= texture2DBias({STD_METALNESS_TEXTURE_NAME}, {STD_METALNESS_TEXTURE_UV}, textureBias).{STD_METALNESS_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_METALNESS_VERTEX\\n\\tmetalness *= saturate(vVertexColor.{STD_METALNESS_VERTEX_CHANNEL});\\n\\t#endif\\n\\tdMetalness = metalness;\\n}\\n`;\\n\\nvar msdf_default$3 = `\\nuniform sampler2D texture_msdfMap;\\nfloat median(float r, float g, float b) {\\n\\treturn max(min(r, g), min(max(r, g), b));\\n}\\nfloat map (float min, float max, float v) {\\n\\treturn (v - min) / (max - min);\\n}\\nuniform float font_sdfIntensity;\\nuniform float font_pxrange;\\nuniform float font_textureWidth;\\n#ifndef LIT_MSDF_TEXT_ATTRIBUTE\\n\\tuniform vec4 outline_color;\\n\\tuniform float outline_thickness;\\n\\tuniform vec4 shadow_color;\\n\\tuniform vec2 shadow_offset;\\n#else\\n\\tvarying vec4 outline_color;\\n\\tvarying float outline_thickness;\\n\\tvarying vec4 shadow_color;\\n\\tvarying vec2 shadow_offset;\\n#endif\\nvec4 applyMsdf(vec4 color) {\\n\\tcolor.rgb = gammaCorrectInput(color.rgb);\\n\\tvec3 tsample = texture2D(texture_msdfMap, vUv0).rgb;\\n\\tvec2 uvShdw = vUv0 - shadow_offset;\\n\\tvec3 ssample = texture2D(texture_msdfMap, uvShdw).rgb;\\n\\tfloat sigDist = median(tsample.r, tsample.g, tsample.b);\\n\\tfloat sigDistShdw = median(ssample.r, ssample.g, ssample.b);\\n\\tfloat smoothingMax = 0.2;\\n\\tvec2 w = fwidth(vUv0);\\n\\tfloat smoothing = clamp(w.x * font_textureWidth / font_pxrange, 0.0, smoothingMax);\\n\\tfloat mapMin = 0.05;\\n\\tfloat mapMax = clamp(1.0 - font_sdfIntensity, mapMin, 1.0);\\n\\tfloat sigDistInner = map(mapMin, mapMax, sigDist);\\n\\tfloat sigDistOutline = map(mapMin, mapMax, sigDist + outline_thickness);\\n\\tsigDistShdw = map(mapMin, mapMax, sigDistShdw + outline_thickness);\\n\\tfloat center = 0.5;\\n\\tfloat inside = smoothstep(center-smoothing, center+smoothing, sigDistInner);\\n\\tfloat outline = smoothstep(center-smoothing, center+smoothing, sigDistOutline);\\n\\tfloat shadow = smoothstep(center-smoothing, center+smoothing, sigDistShdw);\\n\\tvec4 tcolor = (outline > inside) ? outline * vec4(outline_color.a * outline_color.rgb, outline_color.a) : vec4(0.0);\\n\\ttcolor = mix(tcolor, color, inside);\\n\\tvec4 scolor = (shadow > outline) ? shadow * vec4(shadow_color.a * shadow_color.rgb, shadow_color.a) : tcolor;\\n\\ttcolor = mix(scolor, tcolor, outline);\\n\\ttcolor.rgb = gammaCorrectOutput(tcolor.rgb);\\n\\t\\n\\treturn tcolor;\\n}\\n`;\\n\\nvar metalnessModulate_default$1 = `\\nvec3 getSpecularModulate(in vec3 specularity, in vec3 albedo, in float metalness, in float f0, in float specularityFactor) {\\n\\tvec3 dielectricF0 = f0 * specularity * specularityFactor;\\n\\treturn mix(dielectricF0, albedo, metalness);\\n}\\nvec3 getAlbedoModulate(in vec3 albedo, in float metalness) {\\n\\treturn albedo * (1.0 - metalness);\\n}\\n`;\\n\\nvar morph_default$3 = `\\n\\tvarying vec2 uv0;\\n\\tuniform sampler2DArray morphTexture;\\n\\tuniform highp float morphFactor[{MORPH_TEXTURE_MAX_COUNT}];\\n\\tuniform highp uint morphIndex[{MORPH_TEXTURE_MAX_COUNT}];\\n\\tuniform int count;\\n\\t#ifdef MORPH_INT\\n\\t\\tuniform vec3 aabbSize;\\n\\t\\tuniform vec3 aabbMin;\\n\\t#endif\\n\\tvoid main (void) {\\n\\t\\thighp vec3 color = vec3(0, 0, 0);\\n\\t\\tivec2 pixelCoords = ivec2(uv0 * vec2(textureSize(morphTexture, 0).xy));\\n\\t\\t\\n\\t\\tfor (int i = 0; i < count; i++) {\\n\\t\\t\\tuint textureIndex = morphIndex[i];\\n\\t\\t\\tvec3 delta = texelFetch(morphTexture, ivec3(pixelCoords, int(textureIndex)), 0).xyz;\\n\\t\\t\\tcolor += morphFactor[i] * delta;\\n\\t\\t}\\n\\t\\t#ifdef MORPH_INT\\n\\t\\t\\tcolor = (color - aabbMin) / aabbSize * 65535.0;\\n\\t\\t\\tgl_FragColor = uvec4(color, 1u);\\n\\t\\t#else\\n\\t\\t\\tgl_FragColor = vec4(color, 1.0);\\n\\t\\t#endif\\n\\t}\\n`;\\n\\nvar morph_default$2 = `\\n\\tattribute vec2 vertex_position;\\n\\tvarying vec2 uv0;\\n\\tvoid main(void) {\\n\\t\\tgl_Position = vec4(vertex_position, 0.5, 1.0);\\n\\t\\tuv0 = vertex_position.xy * 0.5 + 0.5;\\n\\t}\\n`;\\n\\nvar msdf_default$2 = `\\nattribute vec3 vertex_outlineParameters;\\nattribute vec3 vertex_shadowParameters;\\nvarying vec4 outline_color;\\nvarying float outline_thickness;\\nvarying vec4 shadow_color;\\nvarying vec2 shadow_offset;\\nvoid unpackMsdfParams() {\\n\\tvec3 little = mod(vertex_outlineParameters, 256.);\\n\\tvec3 big = (vertex_outlineParameters - little) / 256.;\\n\\toutline_color.rb = little.xy / 255.;\\n\\toutline_color.ga = big.xy / 255.;\\n\\toutline_thickness = little.z / 255. * 0.2;\\n\\tlittle = mod(vertex_shadowParameters, 256.);\\n\\tbig = (vertex_shadowParameters - little) / 256.;\\n\\tshadow_color.rb = little.xy / 255.;\\n\\tshadow_color.ga = big.xy / 255.;\\n\\tshadow_offset = (vec2(little.z, big.z) / 127. - 1.) * 0.005;\\n}\\n`;\\n\\nvar normal_default$1 = `\\nmat3 dNormalMatrix;\\nvec3 getNormal() {\\n\\tdNormalMatrix = getNormalMatrix(dModelMatrix);\\n\\tvec3 localNormal = getLocalNormal(vertex_normal);\\n\\treturn normalize(dNormalMatrix * localNormal);\\n}\\n`;\\n\\nvar normalCore_default$1 = `\\nattribute vec3 vertex_normal;\\nuniform mat3 matrix_normal;\\n#ifdef MORPHING_NORMAL\\n\\t#ifdef MORPHING_INT\\n\\t\\tuniform highp usampler2D morphNormalTex;\\n\\t#else\\n\\t\\tuniform highp sampler2D morphNormalTex;\\n\\t#endif\\n#endif\\nvec3 getLocalNormal(vec3 vertexNormal) {\\n\\tvec3 localNormal = vertex_normal;\\n\\t#ifdef MORPHING_NORMAL\\n\\t\\tivec2 morphUV = getTextureMorphCoords();\\n\\t\\t#ifdef MORPHING_INT\\n\\t\\t\\tvec3 morphNormal = vec3(texelFetch(morphNormalTex, ivec2(morphUV), 0).xyz) / 65535.0 * 2.0 - 1.0;\\n\\t\\t#else\\n\\t\\t\\tvec3 morphNormal = texelFetch(morphNormalTex, ivec2(morphUV), 0).xyz;\\n\\t\\t#endif\\n\\t\\tlocalNormal += morphNormal;\\n\\t#endif\\n\\treturn localNormal;\\n}\\n#if defined(SKIN) || defined(BATCH)\\n\\tmat3 getNormalMatrix(mat4 modelMatrix) {\\n\\t\\treturn mat3(modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz);\\n\\t}\\n#elif defined(INSTANCING)\\n\\tmat3 getNormalMatrix(mat4 modelMatrix) {\\n\\t\\treturn mat3(modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz);\\n\\t}\\n#else\\n\\tmat3 getNormalMatrix(mat4 modelMatrix) {\\n\\t\\treturn matrix_normal;\\n\\t}\\n#endif\\n`;\\n\\nvar normalMap_default$1 = `\\n#ifdef STD_NORMAL_TEXTURE\\n\\tuniform float material_bumpiness;\\n#endif\\n#ifdef STD_NORMALDETAIL_TEXTURE\\n\\tuniform float material_normalDetailMapBumpiness;\\n\\tvec3 blendNormals(vec3 n1, vec3 n2) {\\n\\t\\tn1 += vec3(0, 0, 1);\\n\\t\\tn2 *= vec3(-1, -1, 1);\\n\\t\\treturn n1 * dot(n1, n2) / n1.z - n2;\\n\\t}\\n#endif\\nvoid getNormal() {\\n#ifdef STD_NORMAL_TEXTURE\\n\\tvec3 normalMap = {STD_NORMAL_TEXTURE_DECODE}(texture2DBias({STD_NORMAL_TEXTURE_NAME}, {STD_NORMAL_TEXTURE_UV}, textureBias));\\n\\tnormalMap = mix(vec3(0.0, 0.0, 1.0), normalMap, material_bumpiness);\\n\\t#ifdef STD_NORMALDETAIL_TEXTURE\\n\\t\\tvec3 normalDetailMap = {STD_NORMALDETAIL_TEXTURE_DECODE}(texture2DBias({STD_NORMALDETAIL_TEXTURE_NAME}, {STD_NORMALDETAIL_TEXTURE_UV}, textureBias));\\n\\t\\tnormalDetailMap = mix(vec3(0.0, 0.0, 1.0), normalDetailMap, material_normalDetailMapBumpiness);\\n\\t\\tnormalMap = blendNormals(normalMap, normalDetailMap);\\n\\t#endif\\n\\tdNormalW = normalize(dTBN * normalMap);\\n#else\\n\\tdNormalW = dVertexNormalW;\\n#endif\\n}\\n`;\\n\\nvar opacity_default$1 = `\\nuniform float material_opacity;\\nuniform float material_alphaDitherScale;\\nvoid getOpacity() {\\n\\tdAlpha = material_opacity;\\n\\t#ifdef STD_OPACITY_TEXTURE\\n\\tdAlpha *= texture2DBias({STD_OPACITY_TEXTURE_NAME}, {STD_OPACITY_TEXTURE_UV}, textureBias).{STD_OPACITY_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_OPACITY_VERTEX\\n\\tdAlpha *= clamp(vVertexColor.{STD_OPACITY_VERTEX_CHANNEL}, 0.0, 1.0);\\n\\t#endif\\n}\\n`;\\n\\nvar opacity_dither_default$1 = `\\n#if STD_OPACITY_DITHER == BAYER8\\n\\t#include \\\"bayerPS\\\"\\n#endif\\nuniform vec4 blueNoiseJitter;\\n#if STD_OPACITY_DITHER == BLUENOISE\\n\\tuniform sampler2D blueNoiseTex32;\\n#endif\\nvoid opacityDither(float alpha, float id) {\\n\\tif (alpha <= 0.0)\\n\\t\\tdiscard;\\n\\tif (alpha >= 1.0)\\n\\t\\treturn;\\n\\t#if STD_OPACITY_DITHER == BAYER8\\n\\t\\tfloat noise = bayer8(floor(mod(gl_FragCoord.xy + blueNoiseJitter.xy + id, 8.0))) / 64.0;\\n\\t#else\\n\\t\\t#if STD_OPACITY_DITHER == BLUENOISE\\n\\t\\t\\tvec2 uv = fract(gl_FragCoord.xy / 32.0 + blueNoiseJitter.xy + id);\\n\\t\\t\\tfloat noise = texture2DLod(blueNoiseTex32, uv, 0.0).y;\\n\\t\\t#endif\\n\\t\\t#if STD_OPACITY_DITHER == IGNNOISE\\n\\t\\t\\tvec3 magic = vec3(0.06711056, 0.00583715, 52.9829189);\\n\\t\\t\\tfloat noise = fract(magic.z * fract(dot(gl_FragCoord.xy + blueNoiseJitter.xy + id, magic.xy)));\\n\\t\\t#endif\\n\\t#endif\\n\\tnoise = pow(noise, 2.2);\\n\\tif (alpha < noise)\\n\\t\\tdiscard;\\n}\\n`;\\n\\nvar output_default$1 = `\\n`;\\n\\nvar outputAlpha_default$1 = `\\n#if LIT_BLEND_TYPE == NORMAL || LIT_BLEND_TYPE == ADDITIVEALPHA || defined(LIT_ALPHA_TO_COVERAGE)\\n\\tgl_FragColor.a = litArgs_opacity;\\n#elif LIT_BLEND_TYPE == PREMULTIPLIED\\n\\tgl_FragColor.rgb *= litArgs_opacity;\\n\\tgl_FragColor.a = litArgs_opacity;\\n#else\\n\\tgl_FragColor.a = 1.0;\\n#endif\\n`;\\n\\nvar outputTex2D_default$1 = `\\nvarying vec2 vUv0;\\nuniform sampler2D source;\\nvoid main(void) {\\n\\tgl_FragColor = texture2D(source, vUv0);\\n}\\n`;\\n\\nvar sheen_default$1 = `\\nuniform vec3 material_sheen;\\nvoid getSheen() {\\n\\tvec3 sheenColor = material_sheen;\\n\\t#ifdef STD_SHEEN_TEXTURE\\n\\tsheenColor *= {STD_SHEEN_TEXTURE_DECODE}(texture2DBias({STD_SHEEN_TEXTURE_NAME}, {STD_SHEEN_TEXTURE_UV}, textureBias)).{STD_SHEEN_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_SHEEN_VERTEX\\n\\tsheenColor *= saturate(vVertexColor.{STD_SHEEN_VERTEX_CHANNEL});\\n\\t#endif\\n\\tsSpecularity = sheenColor;\\n}\\n`;\\n\\nvar sheenGloss_default$1 = `\\nuniform float material_sheenGloss;\\nvoid getSheenGlossiness() {\\n\\tfloat sheenGlossiness = material_sheenGloss;\\n\\t#ifdef STD_SHEENGLOSS_TEXTURE\\n\\tsheenGlossiness *= texture2DBias({STD_SHEENGLOSS_TEXTURE_NAME}, {STD_SHEENGLOSS_TEXTURE_UV}, textureBias).{STD_SHEENGLOSS_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_SHEENGLOSS_VERTEX\\n\\tsheenGlossiness *= saturate(vVertexColor.{STD_SHEENGLOSS_VERTEX_CHANNEL});\\n\\t#endif\\n\\t#ifdef STD_SHEENGLOSS_INVERT\\n\\tsheenGlossiness = 1.0 - sheenGlossiness;\\n\\t#endif\\n\\tsGlossiness = sheenGlossiness + 0.0000001;\\n}\\n`;\\n\\nvar parallax_default$1 = `\\nuniform float material_heightMapFactor;\\nvoid getParallax() {\\n\\tfloat parallaxScale = material_heightMapFactor;\\n\\tfloat height = texture2DBias({STD_HEIGHT_TEXTURE_NAME}, {STD_HEIGHT_TEXTURE_UV}, textureBias).{STD_HEIGHT_TEXTURE_CHANNEL};\\n\\theight = height * parallaxScale - parallaxScale * 0.5;\\n\\tvec3 viewDirT = dViewDirW * dTBN;\\n\\tviewDirT.z += 0.42;\\n\\tdUvOffset = height * (viewDirT.xy / viewDirT.z);\\n}\\n`;\\n\\nvar pick_default$1 = `\\nvec4 encodePickOutput(uint id) {\\n\\tconst vec4 inv = vec4(1.0 / 255.0);\\n\\tconst uvec4 shifts = uvec4(16, 8, 0, 24);\\n\\tuvec4 col = (uvec4(id) >> shifts) & uvec4(0xff);\\n\\treturn vec4(col) * inv;\\n}\\n#ifndef PICK_CUSTOM_ID\\n\\tuniform uint meshInstanceId;\\n\\tvec4 getPickOutput() {\\n\\t\\treturn encodePickOutput(meshInstanceId);\\n\\t}\\n#endif\\n#ifdef DEPTH_PICK_PASS\\n\\t#include \\\"floatAsUintPS\\\"\\n\\t#ifndef CAMERAPLANES\\n\\t\\t#define CAMERAPLANES\\n\\t\\tuniform vec4 camera_params;\\n\\t#endif\\n\\tvec4 getPickDepth() {\\n\\t\\tfloat linearDepth;\\n\\t\\tif (camera_params.w > 0.5) {\\n\\t\\t\\tlinearDepth = gl_FragCoord.z;\\n\\t\\t} else {\\n\\t\\t\\tfloat viewDist = 1.0 / gl_FragCoord.w;\\n\\t\\t\\tlinearDepth = (viewDist - camera_params.z) / (camera_params.y - camera_params.z);\\n\\t\\t}\\n\\t\\treturn float2uint(linearDepth);\\n\\t}\\n#endif\\n`;\\n\\nvar reflDir_default$1 = `\\nvoid getReflDir(vec3 worldNormal, vec3 viewDir, float gloss, mat3 tbn) {\\n\\tdReflDirW = normalize(-reflect(viewDir, worldNormal));\\n}\\n`;\\n\\nvar reflDirAniso_default$1 = `\\nvoid getReflDir(vec3 worldNormal, vec3 viewDir, float gloss, mat3 tbn) {\\n\\tfloat roughness = sqrt(1.0 - min(gloss, 1.0));\\n\\tvec2 direction = dAnisotropyRotation;\\n\\tvec3 anisotropicT = normalize(tbn * vec3(direction, 0.0));\\n\\tvec3 anisotropicB = normalize(cross(tbn[2], anisotropicT));\\n\\tfloat anisotropy = dAnisotropy;\\n\\tvec3 anisotropicDirection = anisotropicB;\\n\\tvec3 anisotropicTangent = cross(anisotropicDirection, viewDir);\\n\\tvec3 anisotropicNormal = cross(anisotropicTangent, anisotropicDirection);\\n\\tfloat bendFactor = 1.0 - anisotropy * (1.0 - roughness);\\n\\tfloat bendFactor4 = bendFactor * bendFactor * bendFactor * bendFactor;\\n\\tvec3 bentNormal = normalize(mix(normalize(anisotropicNormal), normalize(worldNormal), bendFactor4));\\n\\tdReflDirW = reflect(-viewDir, bentNormal);\\n}\\n`;\\n\\nvar reflectionCC_default$1 = `\\n#ifdef LIT_CLEARCOAT\\nvoid addReflectionCC(vec3 reflDir, float gloss) {\\n\\tccReflection += calcReflection(reflDir, gloss);\\n}\\n#endif\\n`;\\n\\nvar reflectionCube_default$1 = `\\nuniform samplerCube texture_cubeMap;\\nuniform float material_reflectivity;\\nvec3 calcReflection(vec3 reflDir, float gloss) {\\n\\tvec3 lookupVec = cubeMapProject(reflDir);\\n\\tlookupVec.x *= -1.0;\\n\\treturn {reflectionDecode}(textureCube(texture_cubeMap, lookupVec));\\n}\\nvoid addReflection(vec3 reflDir, float gloss) {   \\n\\tdReflection += vec4(calcReflection(reflDir, gloss), material_reflectivity);\\n}\\n`;\\n\\nvar reflectionEnvHQ_default$1 = `\\n#ifndef ENV_ATLAS\\n\\t#define ENV_ATLAS\\n\\tuniform sampler2D texture_envAtlas;\\n#endif\\nuniform samplerCube texture_cubeMap;\\nuniform float material_reflectivity;\\nvec3 calcReflection(vec3 reflDir, float gloss) {\\n\\tvec3 dir = cubeMapProject(reflDir) * vec3(-1.0, 1.0, 1.0);\\n\\tvec2 uv = toSphericalUv(dir);\\n\\tfloat level = saturate(1.0 - gloss) * 5.0;\\n\\tfloat ilevel = floor(level);\\n\\tfloat flevel = level - ilevel;\\n\\tvec3 sharp = {reflectionCubemapDecode}(textureCube(texture_cubeMap, dir));\\n\\tvec3 roughA = {reflectionDecode}(texture2D(texture_envAtlas, mapRoughnessUv(uv, ilevel)));\\n\\tvec3 roughB = {reflectionDecode}(texture2D(texture_envAtlas, mapRoughnessUv(uv, ilevel + 1.0)));\\n\\treturn processEnvironment(mix(sharp, mix(roughA, roughB, flevel), min(level, 1.0)));\\n}\\nvoid addReflection(vec3 reflDir, float gloss) {   \\n\\tdReflection += vec4(calcReflection(reflDir, gloss), material_reflectivity);\\n}\\n`;\\n\\nvar reflectionEnv_default$1 = `\\n#ifndef ENV_ATLAS\\n#define ENV_ATLAS\\n\\tuniform sampler2D texture_envAtlas;\\n#endif\\nuniform float material_reflectivity;\\nfloat shinyMipLevel(vec2 uv) {\\n\\tvec2 dx = dFdx(uv);\\n\\tvec2 dy = dFdy(uv);\\n\\tvec2 uv2 = vec2(fract(uv.x + 0.5), uv.y);\\n\\tvec2 dx2 = dFdx(uv2);\\n\\tvec2 dy2 = dFdy(uv2);\\n\\tfloat maxd = min(max(dot(dx, dx), dot(dy, dy)), max(dot(dx2, dx2), dot(dy2, dy2)));\\n\\treturn clamp(0.5 * log2(maxd) - 1.0 + textureBias, 0.0, 5.0);\\n}\\nvec3 calcReflection(vec3 reflDir, float gloss) {\\n\\tvec3 dir = cubeMapProject(reflDir) * vec3(-1.0, 1.0, 1.0);\\n\\tvec2 uv = toSphericalUv(dir);\\n\\tfloat level = saturate(1.0 - gloss) * 5.0;\\n\\tfloat ilevel = floor(level);\\n\\tfloat level2 = shinyMipLevel(uv * atlasSize);\\n\\tfloat ilevel2 = floor(level2);\\n\\tvec2 uv0, uv1;\\n\\tfloat weight;\\n\\tif (ilevel == 0.0) {\\n\\t\\tuv0 = mapShinyUv(uv, ilevel2);\\n\\t\\tuv1 = mapShinyUv(uv, ilevel2 + 1.0);\\n\\t\\tweight = level2 - ilevel2;\\n\\t} else {\\n\\t\\tuv0 = uv1 = mapRoughnessUv(uv, ilevel);\\n\\t\\tweight = 0.0;\\n\\t}\\n\\tvec3 linearA = {reflectionDecode}(texture2D(texture_envAtlas, uv0));\\n\\tvec3 linearB = {reflectionDecode}(texture2D(texture_envAtlas, uv1));\\n\\tvec3 linear0 = mix(linearA, linearB, weight);\\n\\tvec3 linear1 = {reflectionDecode}(texture2D(texture_envAtlas, mapRoughnessUv(uv, ilevel + 1.0)));\\n\\treturn processEnvironment(mix(linear0, linear1, level - ilevel));\\n}\\nvoid addReflection(vec3 reflDir, float gloss) {   \\n\\tdReflection += vec4(calcReflection(reflDir, gloss), material_reflectivity);\\n}\\n`;\\n\\nvar reflectionSphere_default$1 = `\\n#ifndef VIEWMATRIX\\n\\t#define VIEWMATRIX\\n\\tuniform mat4 matrix_view;\\n#endif\\nuniform sampler2D texture_sphereMap;\\nuniform float material_reflectivity;\\nvec3 calcReflection(vec3 reflDir, float gloss) {\\n\\tvec3 reflDirV = (mat3(matrix_view) * reflDir);\\n\\tfloat m = 2.0 * sqrt(dot(reflDirV.xy, reflDirV.xy) + (reflDirV.z + 1.0) * (reflDirV.z + 1.0));\\n\\tvec2 sphereMapUv = reflDirV.xy / m + 0.5;\\n\\treturn {reflectionDecode}(texture2D(texture_sphereMap, sphereMapUv));\\n}\\nvoid addReflection(vec3 reflDir, float gloss) {   \\n\\tdReflection += vec4(calcReflection(reflDir, gloss), material_reflectivity);\\n}\\n`;\\n\\nvar reflectionSheen_default$1 = `\\nvoid addReflectionSheen(vec3 worldNormal, vec3 viewDir, float gloss) {\\n\\tfloat NoV = dot(worldNormal, viewDir);\\n\\tfloat alphaG = gloss * gloss;\\n\\tfloat a = gloss < 0.25 ? -339.2 * alphaG + 161.4 * gloss - 25.9 : -8.48 * alphaG + 14.3 * gloss - 9.95;\\n\\tfloat b = gloss < 0.25 ? 44.0 * alphaG - 23.7 * gloss + 3.26 : 1.97 * alphaG - 3.27 * gloss + 0.72;\\n\\tfloat DG = exp( a * NoV + b ) + ( gloss < 0.25 ? 0.0 : 0.1 * ( gloss - 0.25 ) );\\n\\tsReflection += calcReflection(worldNormal, 0.0) * saturate(DG);\\n}\\n`;\\n\\nvar refractionCube_default$1 = `\\nvec3 refract2(vec3 viewVec, vec3 normal, float IOR) {\\n\\tfloat vn = dot(viewVec, normal);\\n\\tfloat k = 1.0 - IOR * IOR * (1.0 - vn * vn);\\n\\tvec3 refrVec = IOR * viewVec - (IOR * vn + sqrt(k)) * normal;\\n\\treturn refrVec;\\n}\\nvoid addRefraction(\\n\\tvec3 worldNormal, \\n\\tvec3 viewDir, \\n\\tfloat thickness, \\n\\tfloat gloss, \\n\\tvec3 specularity, \\n\\tvec3 albedo, \\n\\tfloat transmission,\\n\\tfloat refractionIndex,\\n\\tfloat dispersion\\n#if defined(LIT_IRIDESCENCE)\\n\\t, vec3 iridescenceFresnel,\\n\\tfloat iridescenceIntensity\\n#endif \\n) {\\n\\tvec4 tmpRefl = dReflection;\\n\\tvec3 reflectionDir = refract2(-viewDir, worldNormal, refractionIndex);\\n\\tdReflection = vec4(0);\\n\\taddReflection(reflectionDir, gloss);\\n\\tdDiffuseLight = mix(dDiffuseLight, dReflection.rgb * albedo, transmission);\\n\\tdReflection = tmpRefl;\\n}\\n`;\\n\\nvar refractionDynamic_default$1 = `\\nuniform float material_invAttenuationDistance;\\nuniform vec3 material_attenuation;\\nvec3 evalRefractionColor(vec3 refractionVector, float gloss, float refractionIndex) {\\n\\tvec4 pointOfRefraction = vec4(vPositionW + refractionVector, 1.0);\\n\\tvec4 projectionPoint = matrix_viewProjection * pointOfRefraction;\\n\\tvec2 uv = getGrabScreenPos(projectionPoint);\\n\\tfloat iorToRoughness = (1.0 - gloss) * clamp((1.0 / refractionIndex) * 2.0 - 2.0, 0.0, 1.0);\\n\\tfloat refractionLod = log2(uScreenSize.x) * iorToRoughness;\\n\\tvec3 refraction = texture2DLod(uSceneColorMap, uv, refractionLod).rgb;\\n\\t#ifdef SCENE_COLORMAP_GAMMA\\n\\t\\trefraction = decodeGamma(refraction);\\n\\t#endif\\n\\treturn refraction;\\n}\\nvoid addRefraction(\\n\\tvec3 worldNormal, \\n\\tvec3 viewDir, \\n\\tfloat thickness, \\n\\tfloat gloss, \\n\\tvec3 specularity, \\n\\tvec3 albedo, \\n\\tfloat transmission,\\n\\tfloat refractionIndex,\\n\\tfloat dispersion\\n#if defined(LIT_IRIDESCENCE)\\n\\t, vec3 iridescenceFresnel,\\n\\tfloat iridescenceIntensity\\n#endif\\n) {\\n\\tvec3 modelScale;\\n\\tmodelScale.x = length(vec3(matrix_model[0].xyz));\\n\\tmodelScale.y = length(vec3(matrix_model[1].xyz));\\n\\tmodelScale.z = length(vec3(matrix_model[2].xyz));\\n\\tvec3 scale = thickness * modelScale;\\n\\tvec3 refractionVector = normalize(refract(-viewDir, worldNormal, refractionIndex)) * scale;\\n\\tvec3 refraction = evalRefractionColor(refractionVector, gloss, refractionIndex);\\n\\t#ifdef LIT_DISPERSION\\n\\t\\tfloat halfSpread = (1.0 / refractionIndex - 1.0) * 0.025 * dispersion;\\n\\t\\tfloat refractionIndexR = refractionIndex - halfSpread;\\n\\t\\trefractionVector = normalize(refract(-viewDir, worldNormal, refractionIndexR)) * scale;\\n\\t\\trefraction.r = evalRefractionColor(refractionVector, gloss, refractionIndexR).r;\\n\\t\\tfloat refractionIndexB = refractionIndex + halfSpread;\\n\\t\\trefractionVector = normalize(refract(-viewDir, worldNormal, refractionIndexB)) * scale;\\n\\t\\trefraction.b = evalRefractionColor(refractionVector, gloss, refractionIndexB).b;\\n\\t#endif\\n\\tvec3 transmittance;\\n\\tif (material_invAttenuationDistance != 0.0)\\n\\t{\\n\\t\\tvec3 attenuation = -log(material_attenuation) * material_invAttenuationDistance;\\n\\t\\ttransmittance = exp(-attenuation * length(refractionVector));\\n\\t}\\n\\telse\\n\\t{\\n\\t\\ttransmittance = vec3(1.0);\\n\\t}\\n\\tvec3 fresnel = vec3(1.0) - \\n\\t\\tgetFresnel(\\n\\t\\t\\tdot(viewDir, worldNormal), \\n\\t\\t\\tgloss, \\n\\t\\t\\tspecularity\\n\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t, iridescenceFresnel,\\n\\t\\t\\tiridescenceIntensity\\n\\t\\t#endif\\n\\t\\t);\\n\\tdDiffuseLight = mix(dDiffuseLight, refraction * transmittance * fresnel, transmission);\\n}\\n`;\\n\\nvar reproject_default$3 = `\\nvarying vec2 vUv0;\\n#ifdef CUBEMAP_SOURCE\\n\\tuniform samplerCube sourceCube;\\n#else\\n\\tuniform sampler2D sourceTex;\\n#endif\\n#ifdef USE_SAMPLES_TEX\\n\\tuniform sampler2D samplesTex;\\n\\tuniform vec2 samplesTexInverseSize;\\n#endif\\nuniform vec3 params;\\nfloat targetFace() { return params.x; }\\nfloat targetTotalPixels() { return params.y; }\\nfloat sourceTotalPixels() { return params.z; }\\nfloat PI = 3.141592653589793;\\nfloat saturate(float x) {\\n\\treturn clamp(x, 0.0, 1.0);\\n}\\n#include \\\"decodePS\\\"\\n#include \\\"encodePS\\\"\\nvec3 modifySeams(vec3 dir, float scale) {\\n\\tvec3 adir = abs(dir);\\n\\tfloat M = max(max(adir.x, adir.y), adir.z);\\n\\treturn dir / M * vec3(\\n\\t\\tadir.x == M ? 1.0 : scale,\\n\\t\\tadir.y == M ? 1.0 : scale,\\n\\t\\tadir.z == M ? 1.0 : scale\\n\\t);\\n}\\nvec2 toSpherical(vec3 dir) {\\n\\treturn vec2(dir.xz == vec2(0.0) ? 0.0 : atan(dir.x, dir.z), asin(dir.y));\\n}\\nvec3 fromSpherical(vec2 uv) {\\n\\treturn vec3(cos(uv.y) * sin(uv.x),\\n\\t\\t\\t\\tsin(uv.y),\\n\\t\\t\\t\\tcos(uv.y) * cos(uv.x));\\n}\\nvec3 getDirectionEquirect() {\\n\\treturn fromSpherical((vec2(vUv0.x, 1.0 - vUv0.y) * 2.0 - 1.0) * vec2(PI, PI * 0.5));\\n}\\nfloat signNotZero(float k){\\n\\treturn(k >= 0.0) ? 1.0 : -1.0;\\n}\\nvec2 signNotZero(vec2 v) {\\n\\treturn vec2(signNotZero(v.x), signNotZero(v.y));\\n}\\nvec3 octDecode(vec2 o) {\\n\\tvec3 v = vec3(o.x, 1.0 - abs(o.x) - abs(o.y), o.y);\\n\\tif (v.y < 0.0) {\\n\\t\\tv.xz = (1.0 - abs(v.zx)) * signNotZero(v.xz);\\n\\t}\\n\\treturn normalize(v);\\n}\\nvec3 getDirectionOctahedral() {\\n\\treturn octDecode(vec2(vUv0.x, 1.0 - vUv0.y) * 2.0 - 1.0);\\n}\\nvec2 octEncode(in vec3 v) {\\n\\tfloat l1norm = abs(v.x) + abs(v.y) + abs(v.z);\\n\\tvec2 result = v.xz * (1.0 / l1norm);\\n\\tif (v.y < 0.0) {\\n\\t\\tresult = (1.0 - abs(result.yx)) * signNotZero(result.xy);\\n\\t}\\n\\treturn result;\\n}\\n#ifdef CUBEMAP_SOURCE\\n\\tvec4 sampleCubemap(vec3 dir) {\\n\\t\\treturn textureCube(sourceCube, modifySeams(dir, 1.0));\\n\\t}\\n\\tvec4 sampleCubemap(vec2 sph) {\\n\\t\\treturn sampleCubemap(fromSpherical(sph));\\n\\t}\\n\\tvec4 sampleCubemap(vec3 dir, float mipLevel) {\\n\\t\\treturn textureCubeLod(sourceCube, modifySeams(dir, 1.0), mipLevel);\\n\\t}\\n\\tvec4 sampleCubemap(vec2 sph, float mipLevel) {\\n\\t\\treturn sampleCubemap(fromSpherical(sph), mipLevel);\\n\\t}\\n#else\\n\\tvec4 sampleEquirect(vec2 sph) {\\n\\t\\tvec2 uv = sph / vec2(PI * 2.0, PI) + 0.5;\\n\\t\\treturn texture2D(sourceTex, vec2(uv.x, 1.0 - uv.y));\\n\\t}\\n\\tvec4 sampleEquirect(vec3 dir) {\\n\\t\\treturn sampleEquirect(toSpherical(dir));\\n\\t}\\n\\tvec4 sampleEquirect(vec2 sph, float mipLevel) {\\n\\t\\tvec2 uv = sph / vec2(PI * 2.0, PI) + 0.5;\\n\\t\\treturn texture2DLod(sourceTex, vec2(uv.x, 1.0 - uv.y), mipLevel);\\n\\t}\\n\\tvec4 sampleEquirect(vec3 dir, float mipLevel) {\\n\\t\\treturn sampleEquirect(toSpherical(dir), mipLevel);\\n\\t}\\n\\tvec4 sampleOctahedral(vec3 dir) {\\n\\t\\tvec2 uv = octEncode(dir) * 0.5 + 0.5;\\n\\t\\treturn texture2D(sourceTex, vec2(uv.x, 1.0 - uv.y));\\n\\t}\\n\\tvec4 sampleOctahedral(vec2 sph) {\\n\\t\\treturn sampleOctahedral(fromSpherical(sph));\\n\\t}\\n\\tvec4 sampleOctahedral(vec3 dir, float mipLevel) {\\n\\t\\tvec2 uv = octEncode(dir) * 0.5 + 0.5;\\n\\t\\treturn texture2DLod(sourceTex, vec2(uv.x, 1.0 - uv.y), mipLevel);\\n\\t}\\n\\tvec4 sampleOctahedral(vec2 sph, float mipLevel) {\\n\\t\\treturn sampleOctahedral(fromSpherical(sph), mipLevel);\\n\\t}\\n#endif\\nvec3 getDirectionCubemap() {\\n\\tvec2 st = vUv0 * 2.0 - 1.0;\\n\\tfloat face = targetFace();\\n\\tvec3 vec;\\n\\tif (face == 0.0) {\\n\\t\\tvec = vec3(1, -st.y, -st.x);\\n\\t} else if (face == 1.0) {\\n\\t\\tvec = vec3(-1, -st.y, st.x);\\n\\t} else if (face == 2.0) {\\n\\t\\tvec = vec3(st.x, 1, st.y);\\n\\t} else if (face == 3.0) {\\n\\t\\tvec = vec3(st.x, -1, -st.y);\\n\\t} else if (face == 4.0) {\\n\\t\\tvec = vec3(st.x, -st.y, 1);\\n\\t} else {\\n\\t\\tvec = vec3(-st.x, -st.y, -1);\\n\\t}\\n\\treturn normalize(modifySeams(vec, 1.0));\\n}\\nmat3 matrixFromVector(vec3 n) {\\n\\tfloat a = 1.0 / (1.0 + n.z);\\n\\tfloat b = -n.x * n.y * a;\\n\\tvec3 b1 = vec3(1.0 - n.x * n.x * a, b, -n.x);\\n\\tvec3 b2 = vec3(b, 1.0 - n.y * n.y * a, -n.y);\\n\\treturn mat3(b1, b2, n);\\n}\\nmat3 matrixFromVectorSlow(vec3 n) {\\n\\tvec3 up = (1.0 - abs(n.y) <= 0.0000001) ? vec3(0.0, 0.0, n.y > 0.0 ? 1.0 : -1.0) : vec3(0.0, 1.0, 0.0);\\n\\tvec3 x = normalize(cross(up, n));\\n\\tvec3 y = cross(n, x);\\n\\treturn mat3(x, y, n);\\n}\\nvec4 reproject() {\\n\\tif ({NUM_SAMPLES} <= 1) {\\n\\t\\treturn {ENCODE_FUNC}({DECODE_FUNC}({SOURCE_FUNC}({TARGET_FUNC}())));\\n\\t} else {\\n\\t\\tvec3 t = {TARGET_FUNC}();\\n\\t\\tvec3 tu = dFdx(t);\\n\\t\\tvec3 tv = dFdy(t);\\n\\t\\tvec3 result = vec3(0.0);\\n\\t\\tfor (float u = 0.0; u < {NUM_SAMPLES_SQRT}; ++u) {\\n\\t\\t\\tfor (float v = 0.0; v < {NUM_SAMPLES_SQRT}; ++v) {\\n\\t\\t\\t\\tresult += {DECODE_FUNC}({SOURCE_FUNC}(normalize(t +\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttu * (u / {NUM_SAMPLES_SQRT} - 0.5) +\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttv * (v / {NUM_SAMPLES_SQRT} - 0.5))));\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn {ENCODE_FUNC}(result / ({NUM_SAMPLES_SQRT} * {NUM_SAMPLES_SQRT}));\\n\\t}\\n}\\nvec4 unpackFloat = vec4(1.0, 1.0 / 255.0, 1.0 / 65025.0, 1.0 / 16581375.0);\\n#ifdef USE_SAMPLES_TEX\\n\\tvoid unpackSample(int i, out vec3 L, out float mipLevel) {\\n\\t\\tfloat u = (float(i * 4) + 0.5) * samplesTexInverseSize.x;\\n\\t\\tfloat v = (floor(u) + 0.5) * samplesTexInverseSize.y;\\n\\t\\tvec4 raw;\\n\\t\\traw.x = dot(texture2D(samplesTex, vec2(u, v)), unpackFloat); u += samplesTexInverseSize.x;\\n\\t\\traw.y = dot(texture2D(samplesTex, vec2(u, v)), unpackFloat); u += samplesTexInverseSize.x;\\n\\t\\traw.z = dot(texture2D(samplesTex, vec2(u, v)), unpackFloat); u += samplesTexInverseSize.x;\\n\\t\\traw.w = dot(texture2D(samplesTex, vec2(u, v)), unpackFloat);\\n\\t\\tL.xyz = raw.xyz * 2.0 - 1.0;\\n\\t\\tmipLevel = raw.w * 8.0;\\n\\t}\\n\\tvec4 prefilterSamples() {\\n\\t\\tmat3 vecSpace = matrixFromVectorSlow({TARGET_FUNC}());\\n\\t\\tvec3 L;\\n\\t\\tfloat mipLevel;\\n\\t\\tvec3 result = vec3(0.0);\\n\\t\\tfloat totalWeight = 0.0;\\n\\t\\tfor (int i = 0; i < {NUM_SAMPLES}; ++i) {\\n\\t\\t\\tunpackSample(i, L, mipLevel);\\n\\t\\t\\tresult += {DECODE_FUNC}({SOURCE_FUNC}(vecSpace * L, mipLevel)) * L.z;\\n\\t\\t\\ttotalWeight += L.z;\\n\\t\\t}\\n\\t\\treturn {ENCODE_FUNC}(result / totalWeight);\\n\\t}\\n\\tvec4 prefilterSamplesUnweighted() {\\n\\t\\tmat3 vecSpace = matrixFromVectorSlow({TARGET_FUNC}());\\n\\t\\tvec3 L;\\n\\t\\tfloat mipLevel;\\n\\t\\tvec3 result = vec3(0.0);\\n\\t\\tfloat totalWeight = 0.0;\\n\\t\\tfor (int i = 0; i < {NUM_SAMPLES}; ++i) {\\n\\t\\t\\tunpackSample(i, L, mipLevel);\\n\\t\\t\\tresult += {DECODE_FUNC}({SOURCE_FUNC}(vecSpace * L, mipLevel));\\n\\t\\t}\\n\\t\\treturn {ENCODE_FUNC}(result / float({NUM_SAMPLES}));\\n\\t}\\n#endif\\nvoid main(void) {\\n\\tgl_FragColor = {PROCESS_FUNC}();\\n}\\n`;\\n\\nvar reproject_default$2 = `\\nattribute vec2 vertex_position;\\nuniform vec4 uvMod;\\nvarying vec2 vUv0;\\nvoid main(void) {\\n\\tgl_Position = vec4(vertex_position, 0.5, 1.0);\\n\\tvUv0 = getImageEffectUV((vertex_position.xy * 0.5 + 0.5) * uvMod.xy + uvMod.zw);\\n}\\n`;\\n\\nvar screenDepth_default$1 = `\\nuniform highp sampler2D uSceneDepthMap;\\n#ifndef SCREENSIZE\\n\\t#define SCREENSIZE\\n\\tuniform vec4 uScreenSize;\\n#endif\\n#ifndef VIEWMATRIX\\n\\t#define VIEWMATRIX\\n\\tuniform mat4 matrix_view;\\n#endif\\n#ifndef LINEARIZE_DEPTH\\n\\t#define LINEARIZE_DEPTH\\n\\t\\n\\t#ifndef CAMERAPLANES\\n\\t\\t#define CAMERAPLANES\\n\\t\\tuniform vec4 camera_params;\\n\\t#endif\\n\\tfloat linearizeDepth(float z) {\\n\\t\\tif (camera_params.w == 0.0)\\n\\t\\t\\treturn (camera_params.z * camera_params.y) / (camera_params.y + z * (camera_params.z - camera_params.y));\\n\\t\\telse\\n\\t\\t\\treturn camera_params.z + z * (camera_params.y - camera_params.z);\\n\\t}\\n#endif\\nfloat delinearizeDepth(float linearDepth) {\\n\\tif (camera_params.w == 0.0) {\\n\\t\\treturn (camera_params.y * (camera_params.z - linearDepth)) / (linearDepth * (camera_params.z - camera_params.y));\\n\\t} else {\\n\\t\\treturn (linearDepth - camera_params.z) / (camera_params.y - camera_params.z);\\n\\t}\\n}\\nfloat getLinearScreenDepth(vec2 uv) {\\n\\t#ifdef SCENE_DEPTHMAP_LINEAR\\n\\t\\t#ifdef SCENE_DEPTHMAP_FLOAT\\n\\t\\t\\treturn texture2D(uSceneDepthMap, uv).r;\\n\\t\\t#else\\n\\t\\t\\tivec2 textureSize = textureSize(uSceneDepthMap, 0);\\n\\t\\t\\tivec2 texel = ivec2(uv * vec2(textureSize));\\n\\t\\t\\tvec4 data = texelFetch(uSceneDepthMap, texel, 0);\\n\\t\\t\\tuint intBits = \\n\\t\\t\\t\\t(uint(data.r * 255.0) << 24u) |\\n\\t\\t\\t\\t(uint(data.g * 255.0) << 16u) |\\n\\t\\t\\t\\t(uint(data.b * 255.0) << 8u) |\\n\\t\\t\\t\\tuint(data.a * 255.0);\\n\\t\\t\\treturn uintBitsToFloat(intBits);\\n\\t\\t#endif\\n\\t#else\\n\\t\\treturn linearizeDepth(texture2D(uSceneDepthMap, uv).r);\\n\\t#endif\\n}\\n#ifndef VERTEXSHADER\\n\\tfloat getLinearScreenDepth() {\\n\\t\\tvec2 uv = gl_FragCoord.xy * uScreenSize.zw;\\n\\t\\treturn getLinearScreenDepth(uv);\\n\\t}\\n#endif\\nfloat getLinearDepth(vec3 pos) {\\n\\treturn -(matrix_view * vec4(pos, 1.0)).z;\\n}\\n`;\\n\\nvar shadowCascades_default$1 = `\\nint getShadowCascadeIndex(vec4 shadowCascadeDistances, int shadowCascadeCount) {\\n\\tfloat depth = 1.0 / gl_FragCoord.w;\\n\\tvec4 comparisons = step(shadowCascadeDistances, vec4(depth));\\n\\tint cascadeIndex = int(dot(comparisons, vec4(1.0)));\\n\\treturn min(cascadeIndex, shadowCascadeCount - 1);\\n}\\nint ditherShadowCascadeIndex(int cascadeIndex, vec4 shadowCascadeDistances, int shadowCascadeCount, float blendFactor) {\\n \\n\\tif (cascadeIndex < shadowCascadeCount - 1) {\\n\\t\\tfloat currentRangeEnd = shadowCascadeDistances[cascadeIndex];\\n\\t\\tfloat transitionStart = blendFactor * currentRangeEnd;\\n\\t\\tfloat depth = 1.0 / gl_FragCoord.w;\\n\\t\\tif (depth > transitionStart) {\\n\\t\\t\\tfloat transitionFactor = smoothstep(transitionStart, currentRangeEnd, depth);\\n\\t\\t\\tfloat dither = fract(sin(dot(gl_FragCoord.xy, vec2(12.9898, 78.233))) * 43758.5453);\\n\\t\\t\\tif (dither < transitionFactor) {\\n\\t\\t\\t\\tcascadeIndex += 1;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\treturn cascadeIndex;\\n}\\nvec3 fadeShadow(vec3 shadowCoord, vec4 shadowCascadeDistances) {\\t\\t\\t\\t  \\n\\tfloat depth = 1.0 / gl_FragCoord.w;\\n\\tif (depth > shadowCascadeDistances.w) {\\n\\t\\tshadowCoord.z = -9999999.0;\\n\\t}\\n\\treturn shadowCoord;\\n}\\n`;\\n\\nvar shadowEVSM_default$1 = `\\nfloat linstep(float a, float b, float v) {\\n\\treturn saturate((v - a) / (b - a));\\n}\\nfloat reduceLightBleeding(float pMax, float amount) {\\n\\t return linstep(amount, 1.0, pMax);\\n}\\nfloat chebyshevUpperBound(vec2 moments, float mean, float minVariance, float lightBleedingReduction) {\\n\\tfloat variance = moments.y - (moments.x * moments.x);\\n\\tvariance = max(variance, minVariance);\\n\\tfloat d = mean - moments.x;\\n\\tfloat pMax = variance / (variance + (d * d));\\n\\tpMax = reduceLightBleeding(pMax, lightBleedingReduction);\\n\\treturn (mean <= moments.x ? 1.0 : pMax);\\n}\\nfloat calculateEVSM(vec3 moments, float Z, float vsmBias, float exponent) {\\n\\tZ = 2.0 * Z - 1.0;\\n\\tfloat warpedDepth = exp(exponent * Z);\\n\\tmoments.xy += vec2(warpedDepth, warpedDepth*warpedDepth) * (1.0 - moments.z);\\n\\tfloat VSMBias = vsmBias;\\n\\tfloat depthScale = VSMBias * exponent * warpedDepth;\\n\\tfloat minVariance1 = depthScale * depthScale;\\n\\treturn chebyshevUpperBound(moments.xy, warpedDepth, minVariance1, 0.1);\\n}\\nfloat VSM16(TEXTURE_ACCEPT(tex), vec2 texCoords, float resolution, float Z, float vsmBias, float exponent) {\\n\\tvec3 moments = texture2DLod(tex, texCoords, 0.0).xyz;\\n\\treturn calculateEVSM(moments, Z, vsmBias, exponent);\\n}\\nfloat getShadowVSM16(TEXTURE_ACCEPT(shadowMap), vec3 shadowCoord, vec4 shadowParams, float exponent) {\\n\\treturn VSM16(TEXTURE_PASS(shadowMap), shadowCoord.xy, shadowParams.x, shadowCoord.z, shadowParams.y, exponent);\\n}\\nfloat getShadowSpotVSM16(TEXTURE_ACCEPT(shadowMap), vec3 shadowCoord, vec4 shadowParams, float exponent, vec3 lightDir) {\\n\\treturn VSM16(TEXTURE_PASS(shadowMap), shadowCoord.xy, shadowParams.x, length(lightDir) * shadowParams.w + shadowParams.z, shadowParams.y, exponent);\\n}\\nfloat VSM32(TEXTURE_ACCEPT(tex), vec2 texCoords, float resolution, float Z, float vsmBias, float exponent) {\\n\\t#ifdef CAPS_TEXTURE_FLOAT_FILTERABLE\\n\\t\\tvec3 moments = texture2DLod(tex, texCoords, 0.0).xyz;\\n\\t#else\\n\\t\\tfloat pixelSize = 1.0 / resolution;\\n\\t\\ttexCoords -= vec2(pixelSize);\\n\\t\\tvec3 s00 = texture2DLod(tex, texCoords, 0.0).xyz;\\n\\t\\tvec3 s10 = texture2DLod(tex, texCoords + vec2(pixelSize, 0), 0.0).xyz;\\n\\t\\tvec3 s01 = texture2DLod(tex, texCoords + vec2(0, pixelSize), 0.0).xyz;\\n\\t\\tvec3 s11 = texture2DLod(tex, texCoords + vec2(pixelSize), 0.0).xyz;\\n\\t\\tvec2 fr = fract(texCoords * resolution);\\n\\t\\tvec3 h0 = mix(s00, s10, fr.x);\\n\\t\\tvec3 h1 = mix(s01, s11, fr.x);\\n\\t\\tvec3 moments = mix(h0, h1, fr.y);\\n\\t#endif\\n\\treturn calculateEVSM(moments, Z, vsmBias, exponent);\\n}\\nfloat getShadowVSM32(TEXTURE_ACCEPT(shadowMap), vec3 shadowCoord, vec4 shadowParams, float exponent) {\\n\\treturn VSM32(TEXTURE_PASS(shadowMap), shadowCoord.xy, shadowParams.x, shadowCoord.z, shadowParams.y, exponent);\\n}\\nfloat getShadowSpotVSM32(TEXTURE_ACCEPT(shadowMap), vec3 shadowCoord, vec4 shadowParams, float exponent, vec3 lightDir) {\\n\\tfloat Z = length(lightDir) * shadowParams.w + shadowParams.z;\\n\\treturn VSM32(TEXTURE_PASS(shadowMap), shadowCoord.xy, shadowParams.x, Z, shadowParams.y, exponent);\\n}\\n`;\\n\\nvar shadowPCF1_default$1 = `\\nfloat getShadowPCF1x1(SHADOWMAP_ACCEPT(shadowMap), vec3 shadowCoord, vec4 shadowParams) {\\n\\treturn textureShadow(shadowMap, shadowCoord);\\n}\\nfloat getShadowSpotPCF1x1(SHADOWMAP_ACCEPT(shadowMap), vec3 shadowCoord, vec4 shadowParams) {\\n\\treturn textureShadow(shadowMap, shadowCoord);\\n}\\n#ifndef WEBGPU\\nfloat getShadowOmniPCF1x1(samplerCubeShadow shadowMap, vec3 shadowCoord, vec4 shadowParams, vec3 lightDir) {\\n\\tfloat shadowZ = length(lightDir) * shadowParams.w + shadowParams.z;\\n\\treturn texture(shadowMap, vec4(lightDir, shadowZ));\\n}\\n#endif\\n`;\\n\\nvar shadowPCF3_default$1 = `\\nfloat _getShadowPCF3x3(SHADOWMAP_ACCEPT(shadowMap), vec3 shadowCoord, vec3 shadowParams) {\\n\\tfloat z = shadowCoord.z;\\n\\tvec2 uv = shadowCoord.xy * shadowParams.x;\\n\\tfloat shadowMapSizeInv = 1.0 / shadowParams.x;\\n\\tvec2 base_uv = floor(uv + 0.5);\\n\\tfloat s = (uv.x + 0.5 - base_uv.x);\\n\\tfloat t = (uv.y + 0.5 - base_uv.y); \\n\\tbase_uv -= vec2(0.5);\\n\\tbase_uv *= shadowMapSizeInv;\\n\\tfloat sum = 0.0;\\n\\tfloat uw0 = (3.0 - 2.0 * s);\\n\\tfloat uw1 = (1.0 + 2.0 * s);\\n\\tfloat u0 = (2.0 - s) / uw0 - 1.0;\\n\\tfloat u1 = s / uw1 + 1.0;\\n\\tfloat vw0 = (3.0 - 2.0 * t);\\n\\tfloat vw1 = (1.0 + 2.0 * t);\\n\\tfloat v0 = (2.0 - t) / vw0 - 1.0;\\n\\tfloat v1 = t / vw1 + 1.0;\\n\\tu0 = u0 * shadowMapSizeInv + base_uv.x;\\n\\tv0 = v0 * shadowMapSizeInv + base_uv.y;\\n\\tu1 = u1 * shadowMapSizeInv + base_uv.x;\\n\\tv1 = v1 * shadowMapSizeInv + base_uv.y;\\n\\tsum += uw0 * vw0 * textureShadow(shadowMap, vec3(u0, v0, z));\\n\\tsum += uw1 * vw0 * textureShadow(shadowMap, vec3(u1, v0, z));\\n\\tsum += uw0 * vw1 * textureShadow(shadowMap, vec3(u0, v1, z));\\n\\tsum += uw1 * vw1 * textureShadow(shadowMap, vec3(u1, v1, z));\\n\\tsum *= 1.0f / 16.0;\\n\\treturn sum;\\n}\\nfloat getShadowPCF3x3(SHADOWMAP_ACCEPT(shadowMap), vec3 shadowCoord, vec4 shadowParams) {\\n\\treturn _getShadowPCF3x3(SHADOWMAP_PASS(shadowMap), shadowCoord, shadowParams.xyz);\\n}\\nfloat getShadowSpotPCF3x3(SHADOWMAP_ACCEPT(shadowMap), vec3 shadowCoord, vec4 shadowParams) {\\n\\treturn _getShadowPCF3x3(SHADOWMAP_PASS(shadowMap), shadowCoord, shadowParams.xyz);\\n}\\n#ifndef WEBGPU\\nfloat getShadowOmniPCF3x3(samplerCubeShadow shadowMap, vec4 shadowParams, vec3 dir) {\\n\\t\\n\\tfloat shadowZ = length(dir) * shadowParams.w + shadowParams.z;\\n\\tfloat z = 1.0 / float(textureSize(shadowMap, 0));\\n\\tvec3 tc = normalize(dir);\\n\\tmediump vec4 shadows;\\n\\tshadows.x = texture(shadowMap, vec4(tc + vec3( z, z, z), shadowZ));\\n\\tshadows.y = texture(shadowMap, vec4(tc + vec3(-z,-z, z), shadowZ));\\n\\tshadows.z = texture(shadowMap, vec4(tc + vec3(-z, z,-z), shadowZ));\\n\\tshadows.w = texture(shadowMap, vec4(tc + vec3( z,-z,-z), shadowZ));\\n\\treturn dot(shadows, vec4(0.25));\\n}\\nfloat getShadowOmniPCF3x3(samplerCubeShadow shadowMap, vec3 shadowCoord, vec4 shadowParams, vec3 lightDir) {\\n\\treturn getShadowOmniPCF3x3(shadowMap, shadowParams, lightDir);\\n}\\n#endif\\n`;\\n\\nvar shadowPCF5_default$1 = `\\nfloat _getShadowPCF5x5(SHADOWMAP_ACCEPT(shadowMap), vec3 shadowCoord, vec3 shadowParams) {\\n\\tfloat z = shadowCoord.z;\\n\\tvec2 uv = shadowCoord.xy * shadowParams.x;\\n\\tfloat shadowMapSizeInv = 1.0 / shadowParams.x;\\n\\tvec2 base_uv = floor(uv + 0.5);\\n\\tfloat s = (uv.x + 0.5 - base_uv.x);\\n\\tfloat t = (uv.y + 0.5 - base_uv.y);\\n\\tbase_uv -= vec2(0.5);\\n\\tbase_uv *= shadowMapSizeInv;\\n\\tfloat uw0 = (4.0 - 3.0 * s);\\n\\tfloat uw1 = 7.0;\\n\\tfloat uw2 = (1.0 + 3.0 * s);\\n\\tfloat u0 = (3.0 - 2.0 * s) / uw0 - 2.0;\\n\\tfloat u1 = (3.0 + s) / uw1;\\n\\tfloat u2 = s / uw2 + 2.0;\\n\\tfloat vw0 = (4.0 - 3.0 * t);\\n\\tfloat vw1 = 7.0;\\n\\tfloat vw2 = (1.0 + 3.0 * t);\\n\\tfloat v0 = (3.0 - 2.0 * t) / vw0 - 2.0;\\n\\tfloat v1 = (3.0 + t) / vw1;\\n\\tfloat v2 = t / vw2 + 2.0;\\n\\tfloat sum = 0.0;\\n\\tu0 = u0 * shadowMapSizeInv + base_uv.x;\\n\\tv0 = v0 * shadowMapSizeInv + base_uv.y;\\n\\tu1 = u1 * shadowMapSizeInv + base_uv.x;\\n\\tv1 = v1 * shadowMapSizeInv + base_uv.y;\\n\\tu2 = u2 * shadowMapSizeInv + base_uv.x;\\n\\tv2 = v2 * shadowMapSizeInv + base_uv.y;\\n\\tsum += uw0 * vw0 * textureShadow(shadowMap, vec3(u0, v0, z));\\n\\tsum += uw1 * vw0 * textureShadow(shadowMap, vec3(u1, v0, z));\\n\\tsum += uw2 * vw0 * textureShadow(shadowMap, vec3(u2, v0, z));\\n\\tsum += uw0 * vw1 * textureShadow(shadowMap, vec3(u0, v1, z));\\n\\tsum += uw1 * vw1 * textureShadow(shadowMap, vec3(u1, v1, z));\\n\\tsum += uw2 * vw1 * textureShadow(shadowMap, vec3(u2, v1, z));\\n\\tsum += uw0 * vw2 * textureShadow(shadowMap, vec3(u0, v2, z));\\n\\tsum += uw1 * vw2 * textureShadow(shadowMap, vec3(u1, v2, z));\\n\\tsum += uw2 * vw2 * textureShadow(shadowMap, vec3(u2, v2, z));\\n\\tsum *= 1.0f / 144.0;\\n\\tsum = saturate(sum);\\n\\treturn sum;\\n}\\nfloat getShadowPCF5x5(SHADOWMAP_ACCEPT(shadowMap), vec3 shadowCoord, vec4 shadowParams) {\\n\\treturn _getShadowPCF5x5(SHADOWMAP_PASS(shadowMap), shadowCoord, shadowParams.xyz);\\n}\\nfloat getShadowSpotPCF5x5(SHADOWMAP_ACCEPT(shadowMap), vec3 shadowCoord, vec4 shadowParams) {\\n\\treturn _getShadowPCF5x5(SHADOWMAP_PASS(shadowMap), shadowCoord, shadowParams.xyz);\\n}\\n`;\\n\\nvar shadowPCSS_default = `\\n#define PCSS_SAMPLE_COUNT 16\\nuniform float pcssDiskSamples[PCSS_SAMPLE_COUNT];\\nuniform float pcssSphereSamples[PCSS_SAMPLE_COUNT];\\nvec2 vogelDisk(int sampleIndex, float count, float phi, float r) {\\n\\tconst float GoldenAngle = 2.4;\\n\\tfloat theta = float(sampleIndex) * GoldenAngle + phi;\\n\\tfloat sine = sin(theta);\\n\\tfloat cosine = cos(theta);\\n\\treturn vec2(r * cosine, r * sine);\\n}\\nvec3 vogelSphere(int sampleIndex, float count, float phi, float r) {\\n\\tconst float GoldenAngle = 2.4;\\n\\tfloat theta = float(sampleIndex) * GoldenAngle + phi;\\n\\tfloat weight = float(sampleIndex) / count;\\n\\treturn vec3(cos(theta) * r, weight, sin(theta) * r);\\n}\\nfloat noise(vec2 screenPos) {\\n\\tconst float PHI = 1.61803398874989484820459;\\n\\treturn fract(sin(dot(screenPos * PHI, screenPos)) * screenPos.x);\\n}\\nfloat viewSpaceDepth(float depth, mat4 invProjection) {\\n\\tfloat z = depth * 2.0 - 1.0;\\n\\tvec4 clipSpace = vec4(0.0, 0.0, z, 1.0);\\n\\tvec4 viewSpace = invProjection * clipSpace;\\n\\treturn viewSpace.z;\\n}\\nfloat PCSSBlockerDistance(TEXTURE_ACCEPT(shadowMap), vec2 sampleCoords[PCSS_SAMPLE_COUNT], vec2 shadowCoords, vec2 searchSize, float z, vec4 cameraParams) {\\n\\tfloat blockers = 0.0;\\n\\tfloat averageBlocker = 0.0;\\n\\tfor (int i = 0; i < PCSS_SAMPLE_COUNT; i++) {\\n\\t\\tvec2 offset = sampleCoords[i] * searchSize;\\n\\t\\tvec2 sampleUV = shadowCoords + offset;\\n\\t\\tfloat blocker = texture2DLod(shadowMap, sampleUV, 0.0).r;\\n\\t\\tfloat isBlocking = step(blocker, z);\\n\\t\\tblockers += isBlocking;\\n\\t\\taverageBlocker += blocker * isBlocking;\\n\\t}\\n\\tif (blockers > 0.0)\\n\\t\\treturn averageBlocker / blockers;\\n\\treturn -1.0;\\n}\\nfloat PCSS(TEXTURE_ACCEPT(shadowMap), vec3 shadowCoords, vec4 cameraParams, vec2 shadowSearchArea) {\\n\\tfloat receiverDepth = linearizeDepthWithParams(shadowCoords.z, cameraParams);\\n\\tvec2 samplePoints[PCSS_SAMPLE_COUNT];\\n\\tconst float PI = 3.141592653589793;\\n\\tfloat noise = noise( gl_FragCoord.xy ) * 2.0 * PI;\\n\\tfor (int i = 0; i < PCSS_SAMPLE_COUNT; i++) {\\n\\t\\tfloat pcssPresample = pcssDiskSamples[i];\\n\\t\\tsamplePoints[i] = vogelDisk(i, float(PCSS_SAMPLE_COUNT), noise, pcssPresample);\\n\\t}\\n\\tfloat averageBlocker = PCSSBlockerDistance(TEXTURE_PASS(shadowMap), samplePoints, shadowCoords.xy, shadowSearchArea, receiverDepth, cameraParams);\\n\\tif (averageBlocker == -1.0) {\\n\\t\\treturn 1.0;\\n\\t} else {\\n\\t\\tfloat depthDifference = (receiverDepth - averageBlocker) / 3.0;\\n\\t\\tvec2 filterRadius = depthDifference * shadowSearchArea;\\n\\t\\tfloat shadow = 0.0;\\n\\t\\tfor (int i = 0; i < PCSS_SAMPLE_COUNT; i ++)\\n\\t\\t{\\n\\t\\t\\tvec2 sampleUV = samplePoints[i] * filterRadius;\\n\\t\\t\\tsampleUV = shadowCoords.xy + sampleUV;\\n\\t\\t\\tfloat depth = texture2DLod(shadowMap, sampleUV, 0.0).r;\\n\\t\\t\\tshadow += step(receiverDepth, depth);\\n\\t\\t}\\n\\t\\treturn shadow / float(PCSS_SAMPLE_COUNT);\\n\\t} \\n}\\n#ifndef WEBGPU\\nfloat PCSSCubeBlockerDistance(samplerCube shadowMap, vec3 lightDirNorm, vec3 samplePoints[PCSS_SAMPLE_COUNT], float z, float shadowSearchArea) {\\n\\tfloat blockers = 0.0;\\n\\tfloat averageBlocker = 0.0;\\n\\tfor (int i = 0; i < PCSS_SAMPLE_COUNT; i++) {\\n\\t\\tvec3 sampleDir = lightDirNorm + samplePoints[i] * shadowSearchArea;\\n\\t\\tsampleDir = normalize(sampleDir);\\n\\t\\tfloat blocker = textureCubeLod(shadowMap, sampleDir, 0.0).r;\\n\\t\\tfloat isBlocking = step(blocker, z);\\n\\t\\tblockers += isBlocking;\\n\\t\\taverageBlocker += blocker * isBlocking;\\n\\t}\\n\\tif (blockers > 0.0)\\n\\t\\treturn averageBlocker / blockers;\\n\\treturn -1.0;\\n}\\nfloat PCSSCube(samplerCube shadowMap, vec4 shadowParams, vec3 shadowCoords, vec4 cameraParams, float shadowSearchArea, vec3 lightDir) {\\n\\t\\n\\tvec3 samplePoints[PCSS_SAMPLE_COUNT];\\n\\tconst float PI = 3.141592653589793;\\n\\tfloat noise = noise( gl_FragCoord.xy ) * 2.0 * PI;\\n\\tfor (int i = 0; i < PCSS_SAMPLE_COUNT; i++) {\\n\\t\\tfloat r = pcssSphereSamples[i];\\n\\t\\tsamplePoints[i] = vogelSphere(i, float(PCSS_SAMPLE_COUNT), noise, r);\\n\\t}\\n\\tfloat receiverDepth = length(lightDir) * shadowParams.w + shadowParams.z;\\n\\tvec3 lightDirNorm = normalize(lightDir);\\n\\t\\n\\tfloat averageBlocker = PCSSCubeBlockerDistance(shadowMap, lightDirNorm, samplePoints, receiverDepth, shadowSearchArea);\\n\\tif (averageBlocker == -1.0) {\\n\\t\\treturn 1.0;\\n\\t} else {\\n\\t\\tfloat filterRadius = ((receiverDepth - averageBlocker) / averageBlocker) * shadowSearchArea;\\n\\t\\tfloat shadow = 0.0;\\n\\t\\tfor (int i = 0; i < PCSS_SAMPLE_COUNT; i++)\\n\\t\\t{\\n\\t\\t\\tvec3 offset = samplePoints[i] * filterRadius;\\n\\t\\t\\tvec3 sampleDir = lightDirNorm + offset;\\n\\t\\t\\tsampleDir = normalize(sampleDir);\\n\\t\\t\\tfloat depth = textureCubeLod(shadowMap, sampleDir, 0.0).r;\\n\\t\\t\\tshadow += step(receiverDepth, depth);\\n\\t\\t}\\n\\t\\treturn shadow / float(PCSS_SAMPLE_COUNT);\\n\\t}\\n}\\nfloat getShadowOmniPCSS(samplerCube shadowMap, vec3 shadowCoord, vec4 shadowParams, vec4 cameraParams, vec2 shadowSearchArea, vec3 lightDir) {\\n\\treturn PCSSCube(shadowMap, shadowParams, shadowCoord, cameraParams, shadowSearchArea.x, lightDir);\\n}\\n#endif\\nfloat getShadowSpotPCSS(TEXTURE_ACCEPT(shadowMap), vec3 shadowCoord, vec4 shadowParams, vec4 cameraParams, vec2 shadowSearchArea, vec3 lightDir) {\\n\\treturn PCSS(TEXTURE_PASS(shadowMap), shadowCoord, cameraParams, shadowSearchArea);\\n}\\n`;\\n\\nvar shadowSoft_default$1 = `\\nhighp float fractSinRand(const in vec2 uv) {\\n\\tconst float PI = 3.141592653589793;\\n\\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\\n\\thighp float dt = dot(uv.xy, vec2(a, b)), sn = mod(dt, PI);\\n\\treturn fract(sin(sn) * c);\\n}\\nstruct VogelDiskData {\\n\\tfloat invNumSamples;\\n\\tfloat initialAngle;\\n\\tfloat currentPointId;\\n};\\nvoid prepareDiskConstants(out VogelDiskData data, int sampleCount, float randomSeed) {\\n\\tconst float pi2 = 6.28318530718;\\n\\tdata.invNumSamples = 1.0 / float(sampleCount);\\n\\tdata.initialAngle = randomSeed * pi2;\\n\\tdata.currentPointId = 0.0;\\n}\\nvec2 generateDiskSample(inout VogelDiskData data) {\\n\\tconst float GOLDEN_ANGLE = 2.399963;\\n\\tfloat r = sqrt((data.currentPointId + 0.5) * data.invNumSamples);\\n\\tfloat theta = data.currentPointId * GOLDEN_ANGLE + data.initialAngle;\\n\\tvec2 offset = vec2(cos(theta), sin(theta)) * pow(r, 1.33);\\n\\tdata.currentPointId += 1.0;\\n\\treturn offset;\\n}\\nvoid PCSSFindBlocker(TEXTURE_ACCEPT(shadowMap), out float avgBlockerDepth, out int numBlockers,\\n\\tvec2 shadowCoords, float z, int shadowBlockerSamples, float penumbraSize, float invShadowMapSize, float randomSeed) {\\n\\tVogelDiskData diskData;\\n\\tprepareDiskConstants(diskData, shadowBlockerSamples, randomSeed);\\n\\tfloat searchWidth = penumbraSize * invShadowMapSize;\\n\\tfloat blockerSum = 0.0;\\n\\tnumBlockers = 0;\\n\\tfor( int i = 0; i < shadowBlockerSamples; ++i ) {\\n\\t\\tvec2 diskUV = generateDiskSample(diskData);\\n\\t\\tvec2 sampleUV = shadowCoords + diskUV * searchWidth;\\n\\t\\tfloat shadowMapDepth = texture2DLod(shadowMap, sampleUV, 0.0).r;\\n\\t\\tif ( shadowMapDepth < z ) {\\n\\t\\t\\tblockerSum += shadowMapDepth;\\n\\t\\t\\tnumBlockers++;\\n\\t\\t}\\n\\t}\\n\\tavgBlockerDepth = blockerSum / float(numBlockers);\\n}\\nfloat PCSSFilter(TEXTURE_ACCEPT(shadowMap), vec2 uv, float receiverDepth, int shadowSamples, float filterRadius, float randomSeed) {\\n\\tVogelDiskData diskData;\\n\\tprepareDiskConstants(diskData, shadowSamples, randomSeed);\\n\\tfloat sum = 0.0;\\n\\tfor (int i = 0; i < shadowSamples; i++) {\\n\\t\\tvec2 offsetUV = generateDiskSample(diskData) * filterRadius;\\n\\t\\tfloat depth = texture2DLod(shadowMap, uv + offsetUV, 0.0).r;\\n\\t\\tsum += step(receiverDepth, depth);\\n\\t}\\n\\treturn sum / float(shadowSamples);\\n}\\nfloat getPenumbra(float dblocker, float dreceiver, float penumbraSize, float penumbraFalloff) {\\n\\tfloat dist = dreceiver - dblocker;\\n\\tfloat penumbra = 1.0 - pow(1.0 - dist, penumbraFalloff);\\n\\treturn penumbra * penumbraSize;\\n}\\nfloat PCSSDirectional(TEXTURE_ACCEPT(shadowMap), vec3 shadowCoords, vec4 cameraParams, vec4 softShadowParams) {\\n\\tfloat receiverDepth = shadowCoords.z;\\n\\tfloat randomSeed = fractSinRand(gl_FragCoord.xy);\\n\\tint shadowSamples = int(softShadowParams.x);\\n\\tint shadowBlockerSamples = int(softShadowParams.y);\\n\\tfloat penumbraSize = softShadowParams.z;\\n\\tfloat penumbraFalloff = softShadowParams.w;\\n\\tint shadowMapSize = textureSize(shadowMap, 0).x;\\n\\tfloat invShadowMapSize = 1.0 / float(shadowMapSize);\\n\\tinvShadowMapSize *= float(shadowMapSize) / 2048.0;\\n\\tfloat penumbra;\\n\\tif (shadowBlockerSamples > 0) {\\n\\t\\tfloat avgBlockerDepth = 0.0;\\n\\t\\tint numBlockers = 0;\\n\\t\\tPCSSFindBlocker(TEXTURE_PASS(shadowMap), avgBlockerDepth, numBlockers, shadowCoords.xy, receiverDepth, shadowBlockerSamples, penumbraSize, invShadowMapSize, randomSeed);\\n\\t\\tif (numBlockers < 1)\\n\\t\\t\\treturn 1.0f;\\n\\t\\tpenumbra = getPenumbra(avgBlockerDepth, shadowCoords.z, penumbraSize, penumbraFalloff);\\n\\t} else {\\n\\t\\tpenumbra = penumbraSize;\\n\\t}\\n\\tfloat filterRadius = penumbra * invShadowMapSize;\\n\\treturn PCSSFilter(TEXTURE_PASS(shadowMap), shadowCoords.xy, receiverDepth, shadowSamples, filterRadius, randomSeed);\\n}\\nfloat getShadowPCSS(TEXTURE_ACCEPT(shadowMap), vec3 shadowCoord, vec4 shadowParams, vec4 cameraParams, vec4 softShadowParams, vec3 lightDir) {\\n\\treturn PCSSDirectional(TEXTURE_PASS(shadowMap), shadowCoord, cameraParams, softShadowParams);\\n}\\n`;\\n\\nvar skinBatch_default$1 = `\\nattribute float vertex_boneIndices;\\nuniform highp sampler2D texture_poseMap;\\nmat4 getBoneMatrix(const in float indexFloat) {\\n\\tint width = textureSize(texture_poseMap, 0).x;\\n\\tint index = int(indexFloat + 0.5) * 3;\\n\\tint iy = index / width;\\n\\tint ix = index % width;\\n\\tvec4 v1 = texelFetch(texture_poseMap, ivec2(ix + 0, iy), 0);\\n\\tvec4 v2 = texelFetch(texture_poseMap, ivec2(ix + 1, iy), 0);\\n\\tvec4 v3 = texelFetch(texture_poseMap, ivec2(ix + 2, iy), 0);\\n\\treturn mat4(\\n\\t\\tv1.x, v2.x, v3.x, 0,\\n\\t\\tv1.y, v2.y, v3.y, 0,\\n\\t\\tv1.z, v2.z, v3.z, 0,\\n\\t\\tv1.w, v2.w, v3.w, 1\\n\\t);\\n}\\n`;\\n\\nvar skin_default$1 = `\\nattribute vec4 vertex_boneWeights;\\nattribute vec4 vertex_boneIndices;\\nuniform highp sampler2D texture_poseMap;\\nvoid getBoneMatrix(const in int width, const in int index, out vec4 v1, out vec4 v2, out vec4 v3) {\\n\\tint v = index / width;\\n\\tint u = index % width;\\n\\tv1 = texelFetch(texture_poseMap, ivec2(u + 0, v), 0);\\n\\tv2 = texelFetch(texture_poseMap, ivec2(u + 1, v), 0);\\n\\tv3 = texelFetch(texture_poseMap, ivec2(u + 2, v), 0);\\n}\\nmat4 getSkinMatrix(const in vec4 indicesFloat, const in vec4 weights) {\\n\\tint width = textureSize(texture_poseMap, 0).x;\\n\\tivec4 indices = ivec4(indicesFloat + 0.5) * 3;\\n\\tvec4 a1, a2, a3;\\n\\tgetBoneMatrix(width, indices.x, a1, a2, a3);\\n\\tvec4 b1, b2, b3;\\n\\tgetBoneMatrix(width, indices.y, b1, b2, b3);\\n\\tvec4 c1, c2, c3;\\n\\tgetBoneMatrix(width, indices.z, c1, c2, c3);\\n\\tvec4 d1, d2, d3;\\n\\tgetBoneMatrix(width, indices.w, d1, d2, d3);\\n\\tvec4 v1 = a1 * weights.x + b1 * weights.y + c1 * weights.z + d1 * weights.w;\\n\\tvec4 v2 = a2 * weights.x + b2 * weights.y + c2 * weights.z + d2 * weights.w;\\n\\tvec4 v3 = a3 * weights.x + b3 * weights.y + c3 * weights.z + d3 * weights.w;\\n\\tfloat one = dot(weights, vec4(1.0));\\n\\treturn mat4(\\n\\t\\tv1.x, v2.x, v3.x, 0,\\n\\t\\tv1.y, v2.y, v3.y, 0,\\n\\t\\tv1.z, v2.z, v3.z, 0,\\n\\t\\tv1.w, v2.w, v3.w, one\\n\\t);\\n}\\n`;\\n\\nvar skybox_default$3 = `\\n\\t#define LIT_SKYBOX_INTENSITY\\n\\t#include \\\"envProcPS\\\"\\n\\t#include \\\"gammaPS\\\"\\n\\t#include \\\"tonemappingPS\\\"\\n\\t#ifdef PREPASS_PASS\\n\\t\\tvarying float vLinearDepth;\\n\\t\\t#include \\\"floatAsUintPS\\\"\\n\\t#endif\\n\\tvarying vec3 vViewDir;\\n\\tuniform float skyboxHighlightMultiplier;\\n\\t#if defined(SKY_FISHEYE) && !defined(SKYMESH)\\n\\t\\tuniform float fisheye_k;\\n\\t\\tuniform float fisheye_invK;\\n\\t\\tuniform float fisheye_projMat00;\\n\\t\\tuniform float fisheye_projMat11;\\n\\t\\tuniform mat4 matrix_view;\\n\\t\\tuniform mat3 cubeMapRotationMatrix;\\n\\t\\tvarying vec3 vClipXYW;\\n\\t#endif\\n\\t#ifdef SKY_CUBEMAP\\n\\t\\tuniform samplerCube texture_cubeMap;\\n\\t\\t#ifdef SKYMESH\\n\\t\\t\\tvarying vec3 vWorldPos;\\n\\t\\t\\tuniform mat3 cubeMapRotationMatrix;\\n\\t\\t\\tuniform vec3 projectedSkydomeCenter;\\n\\t\\t#endif\\n\\t#else\\n\\t\\t#include \\\"sphericalPS\\\"\\n\\t\\t#include \\\"envAtlasPS\\\"\\n\\t\\tuniform sampler2D texture_envAtlas;\\n\\t\\tuniform float mipLevel;\\n\\t#endif\\n\\tvoid main(void) {\\n\\t\\t#ifdef PREPASS_PASS\\n\\t\\t\\tgl_FragColor = float2vec4(vLinearDepth);\\n\\t\\t#else\\n\\t\\t\\t#if defined(SKY_FISHEYE) && !defined(SKYMESH)\\n\\t\\t\\t\\tvec2 ndc = vClipXYW.xy / vClipXYW.z;\\n\\t\\t\\t\\tfloat px = ndc.x / fisheye_projMat00;\\n\\t\\t\\t\\tfloat py = ndc.y / fisheye_projMat11;\\n\\t\\t\\t\\tfloat r = sqrt(px * px + py * py);\\n\\t\\t\\t\\tfloat theta = fisheye_k * atan(r * fisheye_invK);\\n\\t\\t\\t\\tfloat sinT = sin(theta);\\n\\t\\t\\t\\tfloat cosT = cos(theta);\\n\\t\\t\\t\\tvec3 camDir = (r > 1e-6)\\n\\t\\t\\t\\t\\t? vec3(px / r * sinT, py / r * sinT, -cosT)\\n\\t\\t\\t\\t\\t: vec3(0.0, 0.0, -1.0);\\n\\t\\t\\t\\tvec3 dir = transpose(mat3(matrix_view)) * camDir;\\n\\t\\t\\t\\tdir = dir * cubeMapRotationMatrix;\\n\\t\\t\\t#elif defined(SKY_CUBEMAP) && defined(SKYMESH)\\n\\t\\t\\t\\tvec3 envDir = normalize(vWorldPos - projectedSkydomeCenter);\\n\\t\\t\\t\\tvec3 dir = envDir * cubeMapRotationMatrix;\\n\\t\\t\\t#else\\n\\t\\t\\t\\tvec3 dir = vViewDir;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef SKY_CUBEMAP\\n\\t\\t\\t\\tdir.x *= -1.0;\\n\\t\\t\\t\\tvec3 linear = {SKYBOX_DECODE_FNC}(textureCube(texture_cubeMap, dir));\\n\\t\\t\\t#else\\n\\t\\t\\t\\tdir *= vec3(-1.0, 1.0, 1.0);\\n\\t\\t\\t\\tvec2 uv = toSphericalUv(normalize(dir));\\n\\t\\t\\t\\tvec3 linear = {SKYBOX_DECODE_FNC}(texture2D(texture_envAtlas, mapRoughnessUv(uv, mipLevel)));\\n\\t\\t\\t#endif\\n\\t\\t\\tif (any(greaterThanEqual(linear, vec3(64.0)))) {\\n\\t\\t\\t\\tlinear *= skyboxHighlightMultiplier;\\n\\t\\t\\t}\\n\\t\\t\\tgl_FragColor = vec4(gammaCorrectOutput(toneMap(processEnvironment(linear))), 1.0);\\n\\t\\t#endif\\n\\t}\\n`;\\n\\nvar skybox_default$2 = `\\nattribute vec4 aPosition;\\nuniform mat4 matrix_view;\\nuniform mat4 matrix_projectionSkybox;\\nuniform mat3 cubeMapRotationMatrix;\\nvarying vec3 vViewDir;\\n#ifdef SKY_FISHEYE\\n\\tvarying vec3 vClipXYW;\\n#endif\\n#ifdef PREPASS_PASS\\n\\tvarying float vLinearDepth;\\n#endif\\n#ifdef SKYMESH\\n\\tuniform mat4 matrix_model;\\n\\tvarying vec3 vWorldPos;\\n#endif\\nvoid main(void) {\\n\\tmat4 view = matrix_view;\\n\\t#ifdef SKYMESH\\n\\t\\tvec4 worldPos = matrix_model * aPosition;\\n\\t\\tvWorldPos = worldPos.xyz;\\n\\t\\tgl_Position = matrix_projectionSkybox * (view * worldPos);\\n\\t\\t#ifdef PREPASS_PASS\\n\\t\\t\\tvLinearDepth = -(matrix_view * vec4(vWorldPos, 1.0)).z;\\n\\t\\t#endif\\n\\t#else\\n\\t\\tview[3][0] = view[3][1] = view[3][2] = 0.0;\\n\\t\\tvViewDir = aPosition.xyz * cubeMapRotationMatrix;\\n\\t\\t#ifdef SKY_FISHEYE\\n\\t\\t\\tvec4 viewPos = view * aPosition;\\n\\t\\t\\tgl_Position = vec4(viewPos.xy, 0.0, -viewPos.z);\\n\\t\\t\\tvClipXYW = vec3(gl_Position.xy, gl_Position.w);\\n\\t\\t#else\\n\\t\\t\\tgl_Position = matrix_projectionSkybox * (view * aPosition);\\n\\t\\t#endif\\n\\t\\t#ifdef PREPASS_PASS\\n\\t\\t\\tvLinearDepth = -gl_Position.w;\\n\\t\\t#endif\\n\\t#endif\\n\\tgl_Position.z = gl_Position.w - 1.0e-7;\\n}\\n`;\\n\\nvar specular_default$1 = `\\n#ifdef STD_SPECULAR_CONSTANT\\nuniform vec3 material_specular;\\n#endif\\nvoid getSpecularity() {\\n\\tvec3 specularColor = vec3(1,1,1);\\n\\t#ifdef STD_SPECULAR_CONSTANT\\n\\tspecularColor *= material_specular;\\n\\t#endif\\n\\t#ifdef STD_SPECULAR_TEXTURE\\n\\tspecularColor *= {STD_SPECULAR_TEXTURE_DECODE}(texture2DBias({STD_SPECULAR_TEXTURE_NAME}, {STD_SPECULAR_TEXTURE_UV}, textureBias)).{STD_SPECULAR_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_SPECULAR_VERTEX\\n\\tspecularColor *= saturate(vVertexColor.{STD_SPECULAR_VERTEX_CHANNEL});\\n\\t#endif\\n\\tdSpecularity = specularColor;\\n}\\n`;\\n\\nvar spherical_default$1 = `\\nvec2 toSpherical(vec3 dir) {\\n\\treturn vec2(dir.xz == vec2(0.0) ? 0.0 : atan(dir.x, dir.z), asin(dir.y));\\n}\\nvec2 toSphericalUv(vec3 dir) {\\n\\tconst float PI = 3.141592653589793;\\n\\tvec2 uv = toSpherical(dir) / vec2(PI * 2.0, PI) + 0.5;\\n\\treturn vec2(uv.x, 1.0 - uv.y);\\n}\\n`;\\n\\nvar specularityFactor_default$1 = `\\n#ifdef STD_SPECULARITYFACTOR_CONSTANT\\nuniform float material_specularityFactor;\\n#endif\\nvoid getSpecularityFactor() {\\n\\tfloat specularityFactor = 1.0;\\n\\t#ifdef STD_SPECULARITYFACTOR_CONSTANT\\n\\tspecularityFactor *= material_specularityFactor;\\n\\t#endif\\n\\t#ifdef STD_SPECULARITYFACTOR_TEXTURE\\n\\tspecularityFactor *= texture2DBias({STD_SPECULARITYFACTOR_TEXTURE_NAME}, {STD_SPECULARITYFACTOR_TEXTURE_UV}, textureBias).{STD_SPECULARITYFACTOR_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_SPECULARITYFACTOR_VERTEX\\n\\tspecularityFactor *= saturate(vVertexColor.{STD_SPECULARITYFACTOR_VERTEX_CHANNEL});\\n\\t#endif\\n\\tdSpecularityFactor = specularityFactor;\\n}\\n`;\\n\\nvar spot_default$1 = `\\nfloat getSpotEffect(vec3 lightSpotDir, float lightInnerConeAngle, float lightOuterConeAngle, vec3 lightDirNorm) {\\n\\tfloat cosAngle = dot(lightDirNorm, lightSpotDir);\\n\\treturn smoothstep(lightOuterConeAngle, lightInnerConeAngle, cosAngle);\\n}\\n`;\\n\\nvar startNineSliced_default$1 = `\\n\\tnineSlicedUv = vec2(vUv0.x, 1.0 - vUv0.y);\\n`;\\n\\nvar startNineSlicedTiled_default$1 = `\\n\\tvec2 tileMask = step(vMask, vec2(0.99999));\\n\\tvec2 tileSize = 0.5 * (innerOffset.xy + innerOffset.zw);\\n\\tvec2 tileScale = vec2(1.0) / (vec2(1.0) - tileSize);\\n\\tvec2 clampedUv = mix(innerOffset.xy * 0.5, vec2(1.0) - innerOffset.zw * 0.5, fract((vTiledUv - tileSize) * tileScale));\\n\\tclampedUv = clampedUv * atlasRect.zw + atlasRect.xy;\\n\\tnineSlicedUv = vUv0 * tileMask + clampedUv * (vec2(1.0) - tileMask);\\n\\tnineSlicedUv.y = 1.0 - nineSlicedUv.y;\\n\\t\\n`;\\n\\nvar stdDeclaration_default$1 = `\\n\\tfloat dAlpha = 1.0;\\n\\t#if LIT_BLEND_TYPE != NONE || defined(LIT_ALPHA_TEST) || defined(LIT_ALPHA_TO_COVERAGE) || STD_OPACITY_DITHER != NONE\\n\\t\\t#ifdef STD_OPACITY_TEXTURE_ALLOCATE\\n\\t\\t\\tuniform sampler2D texture_opacityMap;\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef FORWARD_PASS\\n\\t\\tvec3 dAlbedo;\\n\\t\\tvec3 dNormalW;\\n\\t\\tvec3 dSpecularity = vec3(0.0);\\n\\t\\tfloat dGlossiness = 0.0;\\n\\t\\t#ifdef LIT_REFRACTION\\n\\t\\t\\tfloat dTransmission;\\n\\t\\t\\tfloat dThickness;\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_SCENE_COLOR\\n\\t\\t\\tuniform sampler2D uSceneColorMap;\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_SCREEN_SIZE\\n\\t\\t\\tuniform vec4 uScreenSize;\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_TRANSFORMS\\n\\t\\t\\tuniform mat4 matrix_viewProjection;\\n\\t\\t\\tuniform mat4 matrix_model;\\n\\t\\t#endif\\n\\t\\t#ifdef STD_HEIGHT_MAP\\n\\t\\t\\tvec2 dUvOffset;\\n\\t\\t\\t#ifdef STD_HEIGHT_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tuniform sampler2D texture_heightMap;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#ifdef STD_DIFFUSE_TEXTURE_ALLOCATE\\n\\t\\t\\tuniform sampler2D texture_diffuseMap;\\n\\t\\t#endif\\n\\t\\t#ifdef STD_DIFFUSEDETAIL_TEXTURE_ALLOCATE\\n\\t\\t\\tuniform sampler2D texture_diffuseDetailMap;\\n\\t\\t#endif\\n\\t\\t#ifdef STD_NORMAL_TEXTURE_ALLOCATE\\n\\t\\t\\tuniform sampler2D texture_normalMap;\\n\\t\\t#endif\\n\\t\\t#ifdef STD_NORMALDETAIL_TEXTURE_ALLOCATE\\n\\t\\t\\tuniform sampler2D texture_normalDetailMap;\\n\\t\\t#endif\\n\\t\\t#ifdef STD_THICKNESS_TEXTURE_ALLOCATE\\n\\t\\t\\tuniform sampler2D texture_thicknessMap;\\n\\t\\t#endif\\n\\t\\t#ifdef STD_REFRACTION_TEXTURE_ALLOCATE\\n\\t\\t\\tuniform sampler2D texture_refractionMap;\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_IRIDESCENCE\\n\\t\\t\\tfloat dIridescence;\\n\\t\\t\\tfloat dIridescenceThickness;\\n\\t\\t\\t#ifdef STD_IRIDESCENCE_THICKNESS_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tuniform sampler2D texture_iridescenceThicknessMap;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef STD_IRIDESCENCE_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tuniform sampler2D texture_iridescenceMap;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\tfloat ccSpecularity;\\n\\t\\t\\tfloat ccGlossiness;\\n\\t\\t\\tvec3 ccNormalW;\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_GGX_SPECULAR\\n\\t\\t\\tfloat dAnisotropy;\\n\\t\\t\\tvec2 dAnisotropyRotation;\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_SPECULAR_OR_REFLECTION\\n\\t\\t\\t#ifdef LIT_SHEEN\\n\\t\\t\\t\\tvec3 sSpecularity;\\n\\t\\t\\t\\tfloat sGlossiness;\\n\\t\\t\\t\\t#ifdef STD_SHEEN_TEXTURE_ALLOCATE\\n\\t\\t\\t\\t\\tuniform sampler2D texture_sheenMap;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#ifdef STD_SHEENGLOSS_TEXTURE_ALLOCATE\\n\\t\\t\\t\\t\\tuniform sampler2D texture_sheenGlossMap;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_METALNESS\\n\\t\\t\\t\\tfloat dMetalness;\\n\\t\\t\\t\\tfloat dIor;\\n\\t\\t\\t\\t#ifdef STD_METALNESS_TEXTURE_ALLOCATE\\n\\t\\t\\t\\t\\tuniform sampler2D texture_metalnessMap;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SPECULARITY_FACTOR\\n\\t\\t\\t\\tfloat dSpecularityFactor;\\n\\t\\t\\t\\t#ifdef STD_SPECULARITYFACTOR_TEXTURE_ALLOCATE\\n\\t\\t\\t\\t\\tuniform sampler2D texture_specularityFactorMap;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef STD_SPECULAR_COLOR\\n\\t\\t\\t\\t#ifdef STD_SPECULAR_TEXTURE_ALLOCATE\\n\\t\\t\\t\\t\\tuniform sampler2D texture_specularMap;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef STD_GLOSS_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tuniform sampler2D texture_glossMap;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#ifdef STD_AO\\n\\t\\t\\tfloat dAo;\\n\\t\\t\\t#ifdef STD_AO_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tuniform sampler2D texture_aoMap;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef STD_AODETAIL_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tuniform sampler2D texture_aoDetailMap;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\tvec3 dEmission;\\n\\t\\t#ifdef STD_EMISSIVE_TEXTURE_ALLOCATE\\n\\t\\t\\tuniform sampler2D texture_emissiveMap;\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t#ifdef STD_CLEARCOAT_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tuniform sampler2D texture_clearCoatMap;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef STD_CLEARCOATGLOSS_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tuniform sampler2D texture_clearCoatGlossMap;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef STD_CLEARCOATNORMAL_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tuniform sampler2D texture_clearCoatNormalMap;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t\\n\\t\\t#ifdef LIT_GGX_SPECULAR\\n\\t\\t\\t#ifdef STD_ANISOTROPY_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tuniform sampler2D texture_anisotropyMap;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#if defined(STD_LIGHTMAP) || defined(STD_LIGHT_VERTEX_COLOR)\\n\\t\\t\\tvec3 dLightmap;\\n\\t\\t\\t#ifdef STD_LIGHT_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tuniform sampler2D texture_lightMap;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t#endif\\n\\t#include \\\"litShaderCorePS\\\"\\n`;\\n\\nvar stdFrontEnd_default$1 = `\\n\\t#if LIT_BLEND_TYPE != NONE || defined(LIT_ALPHA_TEST) || defined(LIT_ALPHA_TO_COVERAGE) || STD_OPACITY_DITHER != NONE\\n\\t\\t#include \\\"opacityPS\\\"\\n\\t\\t#if defined(LIT_ALPHA_TEST)\\n\\t\\t\\t#include \\\"alphaTestPS\\\"\\n\\t\\t#endif\\n\\t\\t#if STD_OPACITY_DITHER != NONE\\n\\t\\t\\t#include \\\"opacityDitherPS\\\"\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef FORWARD_PASS\\n\\t\\t#ifdef STD_HEIGHT_MAP\\n\\t\\t\\t#include \\\"parallaxPS\\\"\\n\\t\\t#endif\\n\\t\\t#include  \\\"diffusePS\\\"\\n\\t\\t#ifdef LIT_NEEDS_NORMAL\\n\\t\\t\\t#include \\\"normalMapPS\\\"\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_REFRACTION\\n\\t\\t\\t#include \\\"transmissionPS\\\"\\n\\t\\t\\t#include \\\"thicknessPS\\\"\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_IRIDESCENCE\\n\\t\\t\\t#include \\\"iridescencePS\\\"\\n\\t\\t\\t#include \\\"iridescenceThicknessPS\\\"\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_SPECULAR_OR_REFLECTION\\n\\t\\t\\t#ifdef LIT_SHEEN\\n\\t\\t\\t\\t#include \\\"sheenPS\\\"\\n\\t\\t\\t\\t#include \\\"sheenGlossPS\\\"\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_METALNESS\\n\\t\\t\\t\\t#include \\\"metalnessPS\\\"\\n\\t\\t\\t\\t#include \\\"iorPS\\\"\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SPECULARITY_FACTOR\\n\\t\\t\\t\\t#include \\\"specularityFactorPS\\\"\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef STD_SPECULAR_COLOR\\n\\t\\t\\t\\t#include \\\"specularPS\\\"\\n\\t\\t\\t#else\\n\\t\\t\\t\\tvoid getSpecularity() { \\n\\t\\t\\t\\t\\tdSpecularity = vec3(1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t#endif\\n\\t\\t\\t#include \\\"glossPS\\\"\\n\\t\\t#endif\\n\\t\\t#ifdef STD_AO\\n\\t\\t\\t#include \\\"aoPS\\\"\\n\\t\\t#endif\\n\\t\\t#include \\\"emissivePS\\\"\\n\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t#include \\\"clearCoatPS\\\"\\n\\t\\t\\t#include \\\"clearCoatGlossPS\\\"\\n\\t\\t\\t#include \\\"clearCoatNormalPS\\\"\\n\\t\\t#endif\\n\\t\\t#if defined(LIT_SPECULAR) && defined(LIT_LIGHTING) && defined(LIT_GGX_SPECULAR)\\n\\t\\t\\t#include \\\"anisotropyPS\\\"\\n\\t\\t#endif\\n\\t\\t#if defined(STD_LIGHTMAP) || defined(STD_LIGHT_VERTEX_COLOR)\\n\\t\\t\\t#include \\\"lightmapPS\\\"\\n\\t\\t#endif\\n\\t#endif\\n\\tvoid evaluateFrontend() {\\n\\t\\t#if LIT_BLEND_TYPE != NONE || defined(LIT_ALPHA_TEST) || defined(LIT_ALPHA_TO_COVERAGE) || STD_OPACITY_DITHER != NONE\\n\\t\\t\\tgetOpacity();\\n\\t\\t\\t#if defined(LIT_ALPHA_TEST)\\n\\t\\t\\t\\talphaTest(dAlpha);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if STD_OPACITY_DITHER != NONE\\n\\t\\t\\t\\topacityDither(dAlpha * material_alphaDitherScale, 0.0);\\n\\t\\t\\t#endif\\n\\t\\t\\tlitArgs_opacity = dAlpha;\\n\\t\\t#endif\\n\\t\\t#ifdef FORWARD_PASS\\n\\t\\t\\t#ifdef STD_HEIGHT_MAP\\n\\t\\t\\t\\tgetParallax();\\n\\t\\t\\t#endif\\n\\t\\t\\tgetAlbedo();\\n\\t\\t\\tlitArgs_albedo = dAlbedo;\\n\\t\\t\\t#ifdef LIT_NEEDS_NORMAL\\n\\t\\t\\t\\tgetNormal();\\n\\t\\t\\t\\tlitArgs_worldNormal = dNormalW;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_REFRACTION\\n\\t\\t\\t\\tgetRefraction();\\n\\t\\t\\t\\tlitArgs_transmission = dTransmission;\\n\\t\\t\\t\\tgetThickness();\\n\\t\\t\\t\\tlitArgs_thickness = dThickness;\\n\\t\\t\\t\\t#ifdef LIT_DISPERSION\\n\\t\\t\\t\\t\\tlitArgs_dispersion = material_dispersion;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_IRIDESCENCE\\n\\t\\t\\t\\tgetIridescence();\\n\\t\\t\\t\\tgetIridescenceThickness();\\n\\t\\t\\t\\tlitArgs_iridescence_intensity = dIridescence;\\n\\t\\t\\t\\tlitArgs_iridescence_thickness = dIridescenceThickness;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SPECULAR_OR_REFLECTION\\n\\t\\t\\t\\t#ifdef LIT_SHEEN\\n\\t\\t\\t\\t\\tgetSheen();\\n\\t\\t\\t\\t\\tlitArgs_sheen_specularity = sSpecularity;\\n\\t\\t\\t\\t\\tgetSheenGlossiness();\\n\\t\\t\\t\\t\\tlitArgs_sheen_gloss = sGlossiness;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#ifdef LIT_METALNESS\\n\\t\\t\\t\\t\\tgetMetalness();\\n\\t\\t\\t\\t\\tlitArgs_metalness = dMetalness;\\n\\t\\t\\t\\t\\tgetIor();\\n\\t\\t\\t\\t\\tlitArgs_ior = dIor;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#ifdef LIT_SPECULARITY_FACTOR\\n\\t\\t\\t\\t\\tgetSpecularityFactor();\\n\\t\\t\\t\\t\\tlitArgs_specularityFactor = dSpecularityFactor;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\tgetGlossiness();\\n\\t\\t\\t\\tgetSpecularity();\\n\\t\\t\\t\\tlitArgs_specularity = dSpecularity;\\n\\t\\t\\t\\tlitArgs_gloss = dGlossiness;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef STD_AO\\n\\t\\t\\t\\tgetAO();\\n\\t\\t\\t\\tlitArgs_ao = dAo;\\n\\t\\t\\t#endif\\n\\t\\t\\tgetEmission();\\n\\t\\t\\tlitArgs_emission = dEmission;\\n\\t\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t\\tgetClearCoat();\\n\\t\\t\\t\\tgetClearCoatGlossiness();\\n\\t\\t\\t\\tgetClearCoatNormal();\\n\\t\\t\\t\\tlitArgs_clearcoat_specularity = ccSpecularity;\\n\\t\\t\\t\\tlitArgs_clearcoat_gloss = ccGlossiness;\\n\\t\\t\\t\\tlitArgs_clearcoat_worldNormal = ccNormalW;\\n\\t\\t\\t#endif\\n\\t\\t\\t#if defined(LIT_SPECULAR) && defined(LIT_LIGHTING) && defined(LIT_GGX_SPECULAR)\\n\\t\\t\\t\\tgetAnisotropy();\\n\\t\\t\\t#endif\\n\\t\\t\\t#if defined(STD_LIGHTMAP) || defined(STD_LIGHT_VERTEX_COLOR)\\n\\t\\t\\t\\tgetLightMap();\\n\\t\\t\\t\\tlitArgs_lightmap = dLightmap;\\n\\t\\t\\t\\t#ifdef STD_LIGHTMAP_DIR\\n\\t\\t\\t\\t\\tlitArgs_lightmapDir = dLightmapDir;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t}\\n`;\\n\\nvar TBN_default$1 = `\\n#ifdef LIT_TANGENTS\\n\\t#define TBN_TANGENTS\\n#else\\n\\t#if defined(LIT_USE_NORMALS) || defined(LIT_USE_CLEARCOAT_NORMALS)\\n\\t\\t#define TBN_DERIVATIVES\\n\\t#endif\\n#endif\\n#if defined(TBN_DERIVATIVES)\\n\\tuniform float tbnBasis;\\n#endif\\nvoid getTBN(vec3 tangent, vec3 binormal, vec3 normal) {\\n\\t#ifdef TBN_TANGENTS\\n\\t\\tdTBN = mat3(normalize(tangent), normalize(binormal), normalize(normal));\\n\\t#elif defined(TBN_DERIVATIVES)\\n\\t\\tvec2 uv = {lightingUv};\\n\\t\\tvec3 dp1 = dFdx( vPositionW );\\n\\t\\tvec3 dp2 = dFdy( vPositionW );\\n\\t\\tvec2 duv1 = dFdx( uv );\\n\\t\\tvec2 duv2 = dFdy( uv );\\n\\t\\tvec3 dp2perp = cross( dp2, normal );\\n\\t\\tvec3 dp1perp = cross( normal, dp1 );\\n\\t\\tvec3 T = dp2perp * duv1.x + dp1perp * duv2.x;\\n\\t\\tvec3 B = dp2perp * duv1.y + dp1perp * duv2.y;\\n\\t\\tfloat denom = max( dot(T,T), dot(B,B) );\\n\\t\\tfloat invmax = (denom == 0.0) ? 0.0 : tbnBasis / sqrt( denom );\\n\\t\\tdTBN = mat3(T * invmax, -B * invmax, normal );\\n\\t#else\\n\\t\\tvec3 B = cross(normal, vObjectSpaceUpW);\\n\\t\\tvec3 T = cross(normal, B);\\n\\t\\tif (dot(B,B)==0.0)\\n\\t\\t{\\n\\t\\t\\tfloat major=max(max(normal.x, normal.y), normal.z);\\n\\t\\t\\tif (normal.x == major)\\n\\t\\t\\t{\\n\\t\\t\\t\\tB = cross(normal, vec3(0,1,0));\\n\\t\\t\\t\\tT = cross(normal, B);\\n\\t\\t\\t}\\n\\t\\t\\telse if (normal.y == major)\\n\\t\\t\\t{\\n\\t\\t\\t\\tB = cross(normal, vec3(0,0,1));\\n\\t\\t\\t\\tT = cross(normal, B);\\n\\t\\t\\t}\\n\\t\\t\\telse if (normal.z == major)\\n\\t\\t\\t{\\n\\t\\t\\t\\tB = cross(normal, vec3(1,0,0));\\n\\t\\t\\t\\tT = cross(normal, B);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdTBN = mat3(normalize(T), normalize(B), normalize(normal));\\n\\t#endif\\n}\\n`;\\n\\nvar thickness_default$1 = `\\n#ifdef STD_THICKNESS_CONSTANT\\nuniform float material_thickness;\\n#endif\\nvoid getThickness() {\\n\\tdThickness = 1.0;\\n\\t#ifdef STD_THICKNESS_CONSTANT\\n\\tdThickness *= material_thickness;\\n\\t#endif\\n\\t#ifdef STD_THICKNESS_TEXTURE\\n\\tdThickness *= texture2DBias({STD_THICKNESS_TEXTURE_NAME}, {STD_THICKNESS_TEXTURE_UV}, textureBias).{STD_THICKNESS_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_THICKNESS_VERTEX\\n\\tdThickness *= saturate(vVertexColor.{STD_THICKNESS_VERTEX_CHANNEL});\\n\\t#endif\\n}\\n`;\\n\\nvar tonemapping_default$1 = `\\n#ifndef TONEMAP_NO_EXPOSURE_UNIFORM\\n\\t#if TONEMAP != NONE\\n\\t\\tuniform float exposure;\\n\\t\\tfloat getExposure() { return exposure; }\\n\\t#else\\n\\t\\tfloat getExposure() { return 1.0; }\\n\\t#endif\\n#endif\\n#if (TONEMAP == NONE)\\n\\t#include \\\"tonemappingNonePS\\\"\\n#elif TONEMAP == FILMIC\\n\\t#include \\\"tonemappingFilmicPS\\\"\\n#elif TONEMAP == LINEAR\\n\\t#include \\\"tonemappingLinearPS\\\"\\n#elif TONEMAP == HEJL\\n\\t#include \\\"tonemappingHejlPS\\\"\\n#elif TONEMAP == ACES\\n\\t#include \\\"tonemappingAcesPS\\\"\\n#elif TONEMAP == ACES2\\n\\t#include \\\"tonemappingAces2PS\\\"\\n#elif TONEMAP == NEUTRAL\\n\\t#include \\\"tonemappingNeutralPS\\\"\\n#endif\\n`;\\n\\nvar tonemappingAces_default$1 = `\\nvec3 toneMap(vec3 color) {\\n\\tfloat tA = 2.51;\\n\\tfloat tB = 0.03;\\n\\tfloat tC = 2.43;\\n\\tfloat tD = 0.59;\\n\\tfloat tE = 0.14;\\n\\tvec3 x = color * getExposure();\\n\\treturn (x*(tA*x+tB))/(x*(tC*x+tD)+tE);\\n}\\n`;\\n\\nvar tonemappingAces2_default$1 = `\\nconst mat3 ACESInputMat = mat3(\\n\\t0.59719, 0.35458, 0.04823,\\n\\t0.07600, 0.90834, 0.01566,\\n\\t0.02840, 0.13383, 0.83777\\n);\\nconst mat3 ACESOutputMat = mat3(\\n\\t 1.60475, -0.53108, -0.07367,\\n\\t-0.10208,  1.10813, -0.00605,\\n\\t-0.00327, -0.07276,  1.07602\\n);\\nvec3 RRTAndODTFit(vec3 v) {\\n\\tvec3 a = v * (v + 0.0245786) - 0.000090537;\\n\\tvec3 b = v * (0.983729 * v + 0.4329510) + 0.238081;\\n\\treturn a / b;\\n}\\nvec3 toneMap(vec3 color) {\\n\\tcolor *= getExposure() / 0.6;\\n\\tcolor = color * ACESInputMat;\\n\\tcolor = RRTAndODTFit(color);\\n\\tcolor = color * ACESOutputMat;\\n\\tcolor = clamp(color, 0.0, 1.0);\\n\\treturn color;\\n}\\n`;\\n\\nvar tonemappingFilmic_default$1 = `\\nconst float A =  0.15;\\nconst float B =  0.50;\\nconst float C =  0.10;\\nconst float D =  0.20;\\nconst float E =  0.02;\\nconst float F =  0.30;\\nconst float W =  11.2;\\nvec3 uncharted2Tonemap(vec3 x) {\\n\\t return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;\\n}\\nvec3 toneMap(vec3 color) {\\n\\tcolor = uncharted2Tonemap(color * getExposure());\\n\\tvec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W,W,W));\\n\\tcolor = color * whiteScale;\\n\\treturn color;\\n}\\n`;\\n\\nvar tonemappingHejl_default$1 = `\\nvec3 toneMap(vec3 color) {\\n\\tcolor *= getExposure();\\n\\tconst float  A = 0.22, B = 0.3, C = .1, D = 0.2, E = .01, F = 0.3;\\n\\tconst float Scl = 1.25;\\n\\tvec3 h = max( vec3(0.0), color - vec3(0.004) );\\n\\treturn (h*((Scl*A)*h+Scl*vec3(C*B,C*B,C*B))+Scl*vec3(D*E,D*E,D*E)) / (h*(A*h+vec3(B,B,B))+vec3(D*F,D*F,D*F)) - Scl*vec3(E/F,E/F,E/F);\\n}\\n`;\\n\\nvar tonemappingLinear_default$1 = `\\nvec3 toneMap(vec3 color) {\\n\\treturn color * getExposure();\\n}\\n`;\\n\\nvar tonemappingNeutral_default$1 = `\\nvec3 toneMap(vec3 color) {\\n\\tcolor *= getExposure();\\n\\tfloat startCompression = 0.8 - 0.04;\\n\\tfloat desaturation = 0.15;\\n\\tfloat x = min(color.r, min(color.g, color.b));\\n\\tfloat offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\\n\\tcolor -= offset;\\n\\tfloat peak = max(color.r, max(color.g, color.b));\\n\\tif (peak < startCompression) return color;\\n\\tfloat d = 1. - startCompression;\\n\\tfloat newPeak = 1. - d * d / (peak + d - startCompression);\\n\\tcolor *= newPeak / peak;\\n\\tfloat g = 1. - 1. / (desaturation * (peak - newPeak) + 1.);\\n\\treturn mix(color, newPeak * vec3(1, 1, 1), g);\\n}\\n`;\\n\\nvar tonemappingNone_default$1 = `\\nvec3 toneMap(vec3 color) {\\n\\treturn color;\\n}\\n`;\\n\\nvar transform_default$1 = `\\n#ifdef PIXELSNAP\\nuniform vec4 uScreenSize;\\n#endif\\n#ifdef SCREENSPACE\\nuniform float projectionFlipY;\\n#endif\\nvec4 evalWorldPosition(vec3 vertexPosition, mat4 modelMatrix) {\\n\\tvec3 localPos = getLocalPosition(vertexPosition);\\n\\t#ifdef NINESLICED\\n\\t\\tlocalPos.xz *= outerScale;\\n\\t\\tvec2 positiveUnitOffset = clamp(vertexPosition.xz, vec2(0.0), vec2(1.0));\\n\\t\\tvec2 negativeUnitOffset = clamp(-vertexPosition.xz, vec2(0.0), vec2(1.0));\\n\\t\\tlocalPos.xz += (-positiveUnitOffset * innerOffset.xy + negativeUnitOffset * innerOffset.zw) * vertex_texCoord0.xy;\\n\\t\\tvTiledUv = (localPos.xz - outerScale + innerOffset.xy) * -0.5 + 1.0;\\n\\t\\tlocalPos.xz *= -0.5;\\n\\t\\tlocalPos = localPos.xzy;\\n\\t#endif\\n\\tvec4 posW = modelMatrix * vec4(localPos, 1.0);\\n\\t#ifdef SCREENSPACE\\n\\t\\tposW.zw = vec2(0.0, 1.0);\\n\\t#endif\\n\\treturn posW;\\n}\\nvec4 getPosition() {\\n\\tdModelMatrix = getModelMatrix();\\n\\tvec4 posW = evalWorldPosition(vertex_position.xyz, dModelMatrix);\\n\\tdPositionW = posW.xyz;\\n\\tvec4 screenPos;\\n\\t#ifdef UV1LAYOUT\\n\\t\\tscreenPos = vec4(vertex_texCoord1.xy * 2.0 - 1.0, 0.5, 1);\\n\\t\\t#ifdef WEBGPU\\n\\t\\t\\tscreenPos.y *= -1.0;\\n\\t\\t#endif\\n\\t#else\\n\\t\\t#ifdef SCREENSPACE\\n\\t\\t\\tscreenPos = posW;\\n\\t\\t\\tscreenPos.y *= projectionFlipY;\\n\\t\\t#else\\n\\t\\t\\tscreenPos = matrix_viewProjection * posW;\\n\\t\\t#endif\\n\\t\\t#ifdef PIXELSNAP\\n\\t\\t\\tscreenPos.xy = (screenPos.xy * 0.5) + 0.5;\\n\\t\\t\\tscreenPos.xy *= uScreenSize.xy;\\n\\t\\t\\tscreenPos.xy = floor(screenPos.xy);\\n\\t\\t\\tscreenPos.xy *= uScreenSize.zw;\\n\\t\\t\\tscreenPos.xy = (screenPos.xy * 2.0) - 1.0;\\n\\t\\t#endif\\n\\t#endif\\n\\treturn screenPos;\\n}\\nvec3 getWorldPosition() {\\n\\treturn dPositionW;\\n}\\n`;\\n\\nvar transformCore_default$1 = `\\nattribute vec4 vertex_position;\\nuniform mat4 matrix_viewProjection;\\nuniform mat4 matrix_model;\\n#ifdef MORPHING\\n\\tuniform vec2 morph_tex_params;\\n\\tattribute uint morph_vertex_id;\\n\\tivec2 getTextureMorphCoords() {\\n\\t\\tivec2 textureSize = ivec2(morph_tex_params);\\n\\t\\tint morphGridV = int(morph_vertex_id) / textureSize.x;\\n\\t\\tint morphGridU = int(morph_vertex_id) - (morphGridV * textureSize.x);\\n\\t\\t#ifdef WEBGPU\\n\\t\\t\\tmorphGridV = textureSize.y - morphGridV - 1;\\n\\t\\t#endif\\n\\t\\treturn ivec2(morphGridU, morphGridV);\\n\\t}\\n\\t#ifdef MORPHING_POSITION\\n\\t\\t#ifdef MORPHING_INT\\n\\t\\t\\tuniform vec3 aabbSize;\\n\\t\\t\\tuniform vec3 aabbMin;\\n\\t\\t\\tuniform usampler2D morphPositionTex;\\n\\t\\t#else\\n\\t\\t\\tuniform highp sampler2D morphPositionTex;\\n\\t\\t#endif\\n\\t#endif\\n#endif\\n#ifdef defined(BATCH)\\n\\t#include \\\"skinBatchVS\\\"\\n\\tmat4 getModelMatrix() {\\n\\t\\treturn getBoneMatrix(vertex_boneIndices);\\n\\t}\\n#elif defined(SKIN)\\n\\t#include \\\"skinVS\\\"\\n\\tmat4 getModelMatrix() {\\n\\t\\treturn matrix_model * getSkinMatrix(vertex_boneIndices, vertex_boneWeights);\\n\\t}\\n#elif defined(INSTANCING)\\n\\t#include \\\"transformInstancingVS\\\"\\n#else\\n\\tmat4 getModelMatrix() {\\n\\t\\treturn matrix_model;\\n\\t}\\n#endif\\nvec3 getLocalPosition(vec3 vertexPosition) {\\n\\tvec3 localPos = vertexPosition;\\n\\t#ifdef MORPHING_POSITION\\n\\t\\tivec2 morphUV = getTextureMorphCoords();\\n\\t\\t#ifdef MORPHING_INT\\n\\t\\t\\tvec3 morphPos = vec3(texelFetch(morphPositionTex, ivec2(morphUV), 0).xyz) / 65535.0 * aabbSize + aabbMin;\\n\\t\\t#else\\n\\t\\t\\tvec3 morphPos = texelFetch(morphPositionTex, ivec2(morphUV), 0).xyz;\\n\\t\\t#endif\\n\\t\\tlocalPos += morphPos;\\n\\t#endif\\n\\treturn localPos;\\n}\\n`;\\n\\nvar transformInstancing_default$1 = `\\nattribute vec4 instance_line1;\\nattribute vec4 instance_line2;\\nattribute vec4 instance_line3;\\nattribute vec4 instance_line4;\\nmat4 getModelMatrix() {\\n\\treturn matrix_model * mat4(instance_line1, instance_line2, instance_line3, instance_line4);\\n}\\n`;\\n\\nvar transmission_default$1 = `\\n#ifdef STD_REFRACTION_CONSTANT\\nuniform float material_refraction;\\n#endif\\nvoid getRefraction() {\\n\\tfloat refraction = 1.0;\\n\\t#ifdef STD_REFRACTION_CONSTANT\\n\\trefraction = material_refraction;\\n\\t#endif\\n\\t#ifdef STD_REFRACTION_TEXTURE\\n\\trefraction *= texture2DBias({STD_REFRACTION_TEXTURE_NAME}, {STD_REFRACTION_TEXTURE_UV}, textureBias).{STD_REFRACTION_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_REFRACTION_VERTEX\\n\\trefraction *= saturate(vVertexColor.{STD_REFRACTION_VERTEX_CHANNEL});\\n\\t#endif\\n\\tdTransmission = refraction;\\n}\\n`;\\n\\nvar twoSidedLighting_default$1 = `\\nvoid handleTwoSidedLighting() {\\n\\tif (!gl_FrontFacing) dTBN[2] = -dTBN[2];\\n}\\n`;\\n\\nvar uv0_default$1 = `\\n#ifdef NINESLICED\\n\\tvec2 getUv0() {\\n\\t\\tvec2 uv = vertex_position.xz;\\n\\t\\tvec2 positiveUnitOffset = clamp(vertex_position.xz, vec2(0.0), vec2(1.0));\\n\\t\\tvec2 negativeUnitOffset = clamp(-vertex_position.xz, vec2(0.0), vec2(1.0));\\n\\t\\tuv += (-positiveUnitOffset * innerOffset.xy + negativeUnitOffset * innerOffset.zw) * vertex_texCoord0.xy;\\n\\t\\tuv = uv * -0.5 + 0.5;\\n\\t\\tuv = uv * atlasRect.zw + atlasRect.xy;\\n\\t\\tvMask = vertex_texCoord0.xy;\\n\\t\\treturn uv;\\n\\t}\\n#else\\n\\tvec2 getUv0() {\\n\\t\\treturn vertex_texCoord0;\\n\\t}\\n#endif\\n`;\\n\\nvar uv1_default$1 = `\\nvec2 getUv1() {\\n\\treturn vertex_texCoord1;\\n}\\n`;\\n\\nvar uvTransform_default$1 = `\\nvUV{TRANSFORM_UV_{i}}_{TRANSFORM_ID_{i}} = vec2(\\n\\tdot(vec3(uv{TRANSFORM_UV_{i}}, 1), {TRANSFORM_NAME_{i}}0),\\n\\tdot(vec3(uv{TRANSFORM_UV_{i}}, 1), {TRANSFORM_NAME_{i}}1)\\n);\\n`;\\n\\nvar uvTransformUniforms_default$1 = `\\n\\tuniform vec3 {TRANSFORM_NAME_{i}}0;\\n\\tuniform vec3 {TRANSFORM_NAME_{i}}1;\\n`;\\n\\nvar viewDir_default$1 = `\\nvoid getViewDir() {\\n\\tdViewDirW = normalize(view_position - vPositionW);\\n}\\n`;\\n\\nconst shaderChunksGLSL = {\\n\\talphaTestPS: alphaTest_default$1,\\n\\tambientPS: ambient_default$1,\\n\\tanisotropyPS: anisotropy_default$1,\\n\\taoPS: ao_default$1,\\n\\taoDiffuseOccPS: aoDiffuseOcc_default$1,\\n\\taoSpecOccPS: aoSpecOcc_default$1,\\n\\tbakeDirLmEndPS: bakeDirLmEnd_default$1,\\n\\tbakeLmEndPS: bakeLmEnd_default$1,\\n\\tbasePS: base_default$1,\\n\\tbaseNineSlicedPS: baseNineSliced_default$1,\\n\\tbaseNineSlicedTiledPS: baseNineSlicedTiled_default$1,\\n\\tbayerPS: bayer_default$1,\\n\\tblurVSMPS: blurVSM_default$1,\\n\\tclearCoatPS: clearCoat_default$1,\\n\\tclearCoatGlossPS: clearCoatGloss_default$1,\\n\\tclearCoatNormalPS: clearCoatNormal_default$1,\\n\\tclusteredLightCookiesPS: clusteredLightCookies_default$1,\\n\\tclusteredLightShadowsPS: clusteredLightShadows_default$1,\\n\\tclusteredLightUtilsPS: clusteredLightUtils_default$1,\\n\\tclusteredLightPS: clusteredLight_default$1,\\n\\tcombinePS: combine_default$1,\\n\\tcookieBlit2DPS: cookie_blit_2d_default$1,\\n\\tcookieBlitCubePS: cookie_blit_cube_default$1,\\n\\tcookieBlitVS: cookie_blit_default$1,\\n\\tcookiePS: cookie_default,\\n\\tcubeMapProjectPS: cubeMapProject_default$1,\\n\\tcubeMapRotatePS: cubeMapRotate_default$1,\\n\\tdebugOutputPS: debug_output_default$1,\\n\\tdebugProcessFrontendPS: debug_process_frontend_default$1,\\n\\tdetailModesPS: detailModes_default$1,\\n\\tdiffusePS: diffuse_default$1,\\n\\tdecodePS: decode_default$1,\\n\\temissivePS: emissive_default$1,\\n\\tencodePS: encode_default$1,\\n\\tendPS: end_default$1,\\n\\tenvAtlasPS: envAtlas_default$1,\\n\\tenvProcPS: envProc_default$1,\\n\\tfalloffInvSquaredPS: falloffInvSquared_default$1,\\n\\tfalloffLinearPS: falloffLinear_default$1,\\n\\tfloatAsUintPS: float_as_uint_default$1,\\n\\tfogPS: fog_default$1,\\n\\tfresnelSchlickPS: fresnelSchlick_default$1,\\n\\tfrontendCodePS: \\\"\\\",\\n\\t// empty chunk, supplied by the shader generator\\n\\tfrontendDeclPS: \\\"\\\",\\n\\t// empty chunk, supplied by the shader generator\\n\\tfullscreenQuadVS: fullscreenQuad_default$1,\\n\\tgammaPS: gamma_default$1,\\n\\tgles3PS: gles3_default$1,\\n\\tgles3VS: gles3_default,\\n\\tglossPS: gloss_default$1,\\n\\tquadVS: quad_default$1,\\n\\timmediateLinePS: immediateLine_default$3,\\n\\timmediateLineVS: immediateLine_default$2,\\n\\tiridescenceDiffractionPS: iridescenceDiffraction_default$1,\\n\\tiridescencePS: iridescence_default$1,\\n\\tiridescenceThicknessPS: iridescenceThickness_default$1,\\n\\tiorPS: ior_default$1,\\n\\tlightDeclarationPS: lightDeclaration_default$1,\\n\\tlightDiffuseLambertPS: lightDiffuseLambert_default$1,\\n\\tlightDirPointPS: lightDirPoint_default$1,\\n\\tlightEvaluationPS: lightEvaluation_default$1,\\n\\tlightFunctionLightPS: lightFunctionLight_default$1,\\n\\tlightFunctionShadowPS: lightFunctionShadow_default$1,\\n\\tlightingPS: lighting_default$1,\\n\\tlightmapAddPS: lightmapAdd_default$1,\\n\\tlightmapPS: lightmap_default$1,\\n\\tlightSpecularAnisoGGXPS: lightSpecularAnisoGGX_default$1,\\n\\tlightSpecularGGXPS: lightSpecularGGX_default$1,\\n\\tlightSpecularBlinnPS: lightSpecularBlinn_default$1,\\n\\tlightSheenPS: lightSheen_default$1,\\n\\tlinearizeDepthPS: linearizeDepth_default$1,\\n\\tlitForwardBackendPS: litForwardBackend_default$1,\\n\\tlitForwardDeclarationPS: litForwardDeclaration_default$1,\\n\\tlitForwardMainPS: litForwardMain_default$1,\\n\\tlitForwardPostCodePS: litForwardPostCode_default$1,\\n\\tlitForwardPreCodePS: litForwardPreCode_default$1,\\n\\tlitMainPS: litMain_default$3,\\n\\tlitMainVS: litMain_default$2,\\n\\tlitOtherMainPS: litOtherMain_default$1,\\n\\tlitShaderArgsPS: litShaderArgs_default$1,\\n\\tlitShaderCorePS: litShaderCore_default$1,\\n\\tlitShadowMainPS: litShadowMain_default$1,\\n\\tlitUserDeclarationPS: \\\"\\\",\\n\\t// empty chunk allowing user to add custom code\\n\\tlitUserDeclarationVS: \\\"\\\",\\n\\t// empty chunk allowing user to add custom code\\n\\tlitUserCodePS: \\\"\\\",\\n\\t// empty chunk allowing user to add custom code\\n\\tlitUserCodeVS: \\\"\\\",\\n\\t// empty chunk allowing user to add custom code\\n\\tlitUserMainStartPS: \\\"\\\",\\n\\t// empty chunk allowing user to add custom code\\n\\tlitUserMainStartVS: \\\"\\\",\\n\\t// empty chunk allowing user to add custom code\\n\\tlitUserMainEndPS: \\\"\\\",\\n\\t// empty chunk allowing user to add custom code\\n\\tlitUserMainEndVS: \\\"\\\",\\n\\t// empty chunk allowing user to add custom code\\n\\tltcPS: ltc_default$1,\\n\\tmetalnessPS: metalness_default$1,\\n\\tmetalnessModulatePS: metalnessModulate_default$1,\\n\\tmorphPS: morph_default$3,\\n\\tmorphVS: morph_default$2,\\n\\tmsdfPS: msdf_default$3,\\n\\tmsdfVS: msdf_default$2,\\n\\tnormalVS: normal_default$1,\\n\\tnormalCoreVS: normalCore_default$1,\\n\\tnormalMapPS: normalMap_default$1,\\n\\topacityPS: opacity_default$1,\\n\\topacityDitherPS: opacity_dither_default$1,\\n\\toutputPS: output_default$1,\\n\\toutputAlphaPS: outputAlpha_default$1,\\n\\toutputTex2DPS: outputTex2D_default$1,\\n\\tsheenPS: sheen_default$1,\\n\\tsheenGlossPS: sheenGloss_default$1,\\n\\tparallaxPS: parallax_default$1,\\n\\tpickPS: pick_default$1,\\n\\treflDirPS: reflDir_default$1,\\n\\treflDirAnisoPS: reflDirAniso_default$1,\\n\\treflectionCCPS: reflectionCC_default$1,\\n\\treflectionCubePS: reflectionCube_default$1,\\n\\treflectionEnvHQPS: reflectionEnvHQ_default$1,\\n\\treflectionEnvPS: reflectionEnv_default$1,\\n\\treflectionSpherePS: reflectionSphere_default$1,\\n\\treflectionSheenPS: reflectionSheen_default$1,\\n\\trefractionCubePS: refractionCube_default$1,\\n\\trefractionDynamicPS: refractionDynamic_default$1,\\n\\treprojectPS: reproject_default$3,\\n\\treprojectVS: reproject_default$2,\\n\\tscreenDepthPS: screenDepth_default$1,\\n\\tshadowCascadesPS: shadowCascades_default$1,\\n\\tshadowEVSMPS: shadowEVSM_default$1,\\n\\tshadowPCF1PS: shadowPCF1_default$1,\\n\\tshadowPCF3PS: shadowPCF3_default$1,\\n\\tshadowPCF5PS: shadowPCF5_default$1,\\n\\tshadowPCSSPS: shadowPCSS_default,\\n\\tshadowSoftPS: shadowSoft_default$1,\\n\\tskinBatchVS: skinBatch_default$1,\\n\\tskinVS: skin_default$1,\\n\\tskyboxPS: skybox_default$3,\\n\\tskyboxVS: skybox_default$2,\\n\\tspecularPS: specular_default$1,\\n\\tsphericalPS: spherical_default$1,\\n\\tspecularityFactorPS: specularityFactor_default$1,\\n\\tspotPS: spot_default$1,\\n\\tstartNineSlicedPS: startNineSliced_default$1,\\n\\tstartNineSlicedTiledPS: startNineSlicedTiled_default$1,\\n\\tstdDeclarationPS: stdDeclaration_default$1,\\n\\tstdFrontEndPS: stdFrontEnd_default$1,\\n\\tTBNPS: TBN_default$1,\\n\\tthicknessPS: thickness_default$1,\\n\\ttonemappingPS: tonemapping_default$1,\\n\\ttonemappingAcesPS: tonemappingAces_default$1,\\n\\ttonemappingAces2PS: tonemappingAces2_default$1,\\n\\ttonemappingFilmicPS: tonemappingFilmic_default$1,\\n\\ttonemappingHejlPS: tonemappingHejl_default$1,\\n\\ttonemappingLinearPS: tonemappingLinear_default$1,\\n\\ttonemappingNeutralPS: tonemappingNeutral_default$1,\\n\\ttonemappingNonePS: tonemappingNone_default$1,\\n\\ttransformVS: transform_default$1,\\n\\ttransformCoreVS: transformCore_default$1,\\n\\ttransformInstancingVS: transformInstancing_default$1,\\n\\ttransmissionPS: transmission_default$1,\\n\\ttwoSidedLightingPS: twoSidedLighting_default$1,\\n\\tuv0VS: uv0_default$1,\\n\\tuv1VS: uv1_default$1,\\n\\tuvTransformVS: uvTransform_default$1,\\n\\tuvTransformUniformsPS: uvTransformUniforms_default$1,\\n\\tviewDirPS: viewDir_default$1,\\n\\twebgpuPS: webgpu_default$1,\\n\\twebgpuVS: webgpu_default\\n};\\n\\nvar alphaTest_default = `\\nuniform alpha_ref: f32;\\nfn alphaTest(a: f32) {\\n\\tif (a < uniform.alpha_ref) {\\n\\t\\tdiscard;\\n\\t}\\n}\\n`;\\n\\nvar ambient_default = `\\n#if LIT_AMBIENT_SOURCE == AMBIENTSH\\n\\tuniform ambientSH: array<vec3f, 9>;\\n#endif\\n#if LIT_AMBIENT_SOURCE == ENVALATLAS\\n\\t#include \\\"envAtlasPS\\\"\\n\\t#ifndef ENV_ATLAS\\n\\t\\t#define ENV_ATLAS\\n\\t\\tvar texture_envAtlas: texture_2d<f32>;\\n\\t\\tvar texture_envAtlasSampler: sampler;\\n\\t#endif\\n#endif\\nfn addAmbient(worldNormal: vec3f) {\\n\\t#ifdef LIT_AMBIENT_SOURCE == AMBIENTSH\\n\\t\\tlet n: vec3f = cubeMapRotate(worldNormal);\\n\\t\\tlet color: vec3f =\\n\\t\\t\\tuniform.ambientSH[0] +\\n\\t\\t\\tuniform.ambientSH[1] * n.x +\\n\\t\\t\\tuniform.ambientSH[2] * n.y +\\n\\t\\t\\tuniform.ambientSH[3] * n.z +\\n\\t\\t\\tuniform.ambientSH[4] * n.x * n.z +\\n\\t\\t\\tuniform.ambientSH[5] * n.z * n.y +\\n\\t\\t\\tuniform.ambientSH[6] * n.y * n.x +\\n\\t\\t\\tuniform.ambientSH[7] * (3.0 * n.z * n.z - 1.0) +\\n\\t\\t\\tuniform.ambientSH[8] * (n.x * n.x - n.y * n.y);\\n\\t\\tdDiffuseLight += processEnvironment(max(color, vec3f(0.0)));\\n\\t#endif\\n\\t#if LIT_AMBIENT_SOURCE == ENVALATLAS\\n\\t\\tlet dir: vec3f = normalize(cubeMapRotate(worldNormal) * vec3f(-1.0, 1.0, 1.0));\\n\\t\\tlet uv: vec2f = mapUv(toSphericalUv(dir), vec4f(128.0, 256.0 + 128.0, 64.0, 32.0) / atlasSize);\\n\\t\\tlet raw: vec4f = textureSample(texture_envAtlas, texture_envAtlasSampler, uv);\\n\\t\\tlet linear: vec3f = {ambientDecode}(raw);\\n\\t\\tdDiffuseLight += processEnvironment(linear);\\n\\t#endif\\n\\t#if LIT_AMBIENT_SOURCE == CONSTANT\\n\\t\\tdDiffuseLight += uniform.light_globalAmbient;\\n\\t#endif\\n}\\n`;\\n\\nvar anisotropy_default = `\\n#ifdef LIT_GGX_SPECULAR\\n\\tuniform material_anisotropyIntensity: f32;\\n\\tuniform material_anisotropyRotation: vec2f;\\n#endif\\nfn getAnisotropy() {\\n\\tdAnisotropy = 0.0;\\n\\tdAnisotropyRotation = vec2f(1.0, 0.0);\\n#ifdef LIT_GGX_SPECULAR\\n\\tdAnisotropy = uniform.material_anisotropyIntensity;\\n\\tdAnisotropyRotation = uniform.material_anisotropyRotation;\\n#endif\\n#ifdef STD_ANISOTROPY_TEXTURE\\n\\tlet anisotropyTex: vec3f = textureSampleBias({STD_ANISOTROPY_TEXTURE_NAME}, {STD_ANISOTROPY_TEXTURE_NAME}Sampler, {STD_ANISOTROPY_TEXTURE_UV}, uniform.textureBias).rgb;\\n\\tdAnisotropy *= anisotropyTex.b;\\n\\tlet anisotropyRotationFromTex: vec2f = anisotropyTex.rg * 2.0 - vec2f(1.0);\\n\\tlet rotationMatrix: mat2x2f = mat2x2f(dAnisotropyRotation.x, dAnisotropyRotation.y, -dAnisotropyRotation.y, dAnisotropyRotation.x);\\n\\tdAnisotropyRotation = rotationMatrix * anisotropyRotationFromTex;\\n#endif\\n\\tdAnisotropy = clamp(dAnisotropy, 0.0, 1.0);\\n}\\n`;\\n\\nvar ao_default = `\\n#if defined(STD_AO_TEXTURE) || defined(STD_AO_VERTEX)\\n\\tuniform material_aoIntensity: f32;\\n#endif\\n#ifdef STD_AODETAIL_TEXTURE\\n\\t#include \\\"detailModesPS\\\"\\n#endif\\nfn getAO() {\\n\\tdAo = 1.0;\\n\\t#ifdef STD_AO_TEXTURE\\n\\t\\tvar aoBase: f32 = textureSampleBias({STD_AO_TEXTURE_NAME}, {STD_AO_TEXTURE_NAME}Sampler, {STD_AO_TEXTURE_UV}, uniform.textureBias).{STD_AO_TEXTURE_CHANNEL};\\n\\t\\t#ifdef STD_AODETAIL_TEXTURE\\n\\t\\t\\tvar aoDetail: f32 = textureSampleBias({STD_AODETAIL_TEXTURE_NAME}, {STD_AODETAIL_TEXTURE_NAME}Sampler, {STD_AODETAIL_TEXTURE_UV}, uniform.textureBias).{STD_AODETAIL_TEXTURE_CHANNEL};\\n\\t\\t\\taoBase = detailMode_{STD_AODETAIL_DETAILMODE}(vec3f(aoBase), vec3f(aoDetail)).r;\\n\\t\\t#endif\\n\\t\\tdAo = dAo * aoBase;\\n\\t#endif\\n\\t#ifdef STD_AO_VERTEX\\n\\t\\tdAo = dAo * saturate(vVertexColor.{STD_AO_VERTEX_CHANNEL});\\n\\t#endif\\n\\t#if defined(STD_AO_TEXTURE) || defined(STD_AO_VERTEX)\\n\\t\\tdAo = mix(1.0, dAo, uniform.material_aoIntensity);\\n\\t#endif\\n}\\n`;\\n\\nvar aoDiffuseOcc_default = `\\nfn occludeDiffuse(ao: f32) {\\n\\tdDiffuseLight = dDiffuseLight * ao;\\n}\\n`;\\n\\nvar aoSpecOcc_default = `\\n#if LIT_OCCLUDE_SPECULAR != NONE\\n\\t#ifdef LIT_OCCLUDE_SPECULAR_FLOAT\\n\\t\\tuniform material_occludeSpecularIntensity: f32;\\n\\t#endif\\n#endif\\nfn occludeSpecular(gloss: f32, ao: f32, worldNormal: vec3f, viewDir: vec3f) {\\n\\t#if LIT_OCCLUDE_SPECULAR == AO\\n\\t\\t#ifdef LIT_OCCLUDE_SPECULAR_FLOAT\\n\\t\\t\\tvar specOcc: f32 = mix(1.0, ao, uniform.material_occludeSpecularIntensity);\\n\\t\\t#else\\n\\t\\t\\tvar specOcc: f32 = ao;\\n\\t\\t#endif\\n\\t#endif\\n\\t#if LIT_OCCLUDE_SPECULAR == GLOSSDEPENDENT\\n\\t\\tvar specPow: f32 = exp2(gloss * 11.0);\\n\\t\\tvar specOcc: f32 = saturate(pow(dot(worldNormal, viewDir) + ao, 0.01 * specPow) - 1.0 + ao);\\n\\t\\t#ifdef LIT_OCCLUDE_SPECULAR_FLOAT\\n\\t\\t\\tspecOcc = mix(1.0, specOcc, uniform.material_occludeSpecularIntensity);\\n\\t\\t#endif\\n\\t#endif\\n\\t#if LIT_OCCLUDE_SPECULAR != NONE\\n\\t\\tdSpecularLight = dSpecularLight * specOcc;\\n\\t\\tdReflection = dReflection * specOcc;\\n\\t\\t#ifdef LIT_SHEEN\\n\\t\\t\\tsSpecularLight = sSpecularLight * specOcc;\\n\\t\\t\\tsReflection = sReflection * specOcc;\\n\\t\\t#endif\\n\\t#endif\\n}\\n`;\\n\\nvar bakeDirLmEnd_default = `\\n\\tlet dirLm = textureSample(texture_dirLightMap, texture_dirLightMapSampler, vUv1);\\n\\tif (uniform.bakeDir > 0.5) {\\n\\t\\tif (dAtten > 0.00001) {\\n\\t\\t\\tlet unpacked_dir = dirLm.xyz * 2.0 - vec3f(1.0);\\n\\t\\t\\tdAtten = clamp(dAtten, 0.0, 1.0);\\n\\t\\t\\tlet combined_dir = dLightDirNormW.xyz * dAtten + unpacked_dir * dirLm.w;\\n\\t\\t\\tlet finalRgb = normalize(combined_dir) * 0.5 + vec3f(0.5);\\n\\t\\t\\tlet finalA = max(dirLm.w + dAtten, 1.0 / 255.0);\\n\\t\\t\\toutput.color = vec4f(finalRgb, finalA);\\n\\t\\t} else {\\n\\t\\t\\toutput.color = dirLm;\\n\\t\\t}\\n\\t} else {\\n\\t\\tlet alpha_min = select(0.0, 1.0 / 255.0, dAtten > 0.00001);\\n\\t\\tlet finalA = max(dirLm.w, alpha_min);\\n\\t\\toutput.color = vec4f(dirLm.rgb, finalA);\\n\\t}\\n`;\\n\\nvar bakeLmEnd_default = `\\n#ifdef LIT_LIGHTMAP_BAKING_ADD_AMBIENT\\n\\tdDiffuseLight = ((dDiffuseLight - 0.5) * max(uniform.ambientBakeOcclusionContrast + 1.0, 0.0)) + 0.5;\\n\\tdDiffuseLight = dDiffuseLight + vec3f(uniform.ambientBakeOcclusionBrightness);\\n\\tdDiffuseLight = saturate3(dDiffuseLight);\\n\\tdDiffuseLight = dDiffuseLight * dAmbientLight;\\n#endif\\n#ifdef LIGHTMAP_RGBM\\n\\tvar temp_color_rgbm = vec4f(dDiffuseLight, 1.0);\\n\\ttemp_color_rgbm = vec4f(pow(temp_color_rgbm.rgb, vec3f(0.5)), temp_color_rgbm.a);\\n\\ttemp_color_rgbm = vec4f(temp_color_rgbm.rgb / 8.0, temp_color_rgbm.a);\\n\\tlet max_g_b = max(temp_color_rgbm.g, max(temp_color_rgbm.b, 1.0 / 255.0));\\n\\tlet max_rgb = max(temp_color_rgbm.r, max_g_b);\\n\\ttemp_color_rgbm.a = clamp(max_rgb, 0.0, 1.0);\\n\\ttemp_color_rgbm.a = ceil(temp_color_rgbm.a * 255.0) / 255.0;\\n\\ttemp_color_rgbm = vec4f(temp_color_rgbm.rgb / temp_color_rgbm.a, temp_color_rgbm.a);\\n\\toutput.color = temp_color_rgbm;\\n#else\\n\\toutput.color = vec4f(dDiffuseLight, 1.0);\\n#endif\\n`;\\n\\nvar base_default = `\\nuniform view_position: vec3f;\\nuniform light_globalAmbient: vec3f;\\nfn square(x: f32) -> f32 {\\n\\treturn x*x;\\n}\\nfn saturate(x: f32) -> f32 {\\n\\treturn clamp(x, 0.0, 1.0);\\n}\\nfn saturate3(x: vec3f) -> vec3f {\\n\\treturn clamp(x, vec3f(0.0), vec3f(1.0));\\n}\\n`;\\n\\nvar baseNineSliced_default = `\\n#define NINESLICED\\nvarying vMask: vec2f;\\nvarying vTiledUv: vec2f;\\nuniform innerOffset: vec4f;\\nuniform outerScale: vec2f;\\nuniform atlasRect: vec4f;\\nvar<private> nineSlicedUv: vec2f;\\n`;\\n\\nvar baseNineSlicedTiled_default = `\\n#define NINESLICED\\n#define NINESLICETILED\\nvarying vMask: vec2f;\\nvarying vTiledUv: vec2f;\\nuniform innerOffset: vec4f;\\nuniform outerScale: vec2f;\\nuniform atlasRect: vec4f;\\nvar<private> nineSlicedUv: vec2f;\\n`;\\n\\nvar bayer_default = `\\nfn bayer2(p: vec2f) -> f32 {\\n\\treturn (2.0 * p.y + p.x + 1.0) % 4.0;\\n}\\nfn bayer4(p: vec2f) -> f32 {\\n\\tlet p1: vec2f = p % vec2f(2.0);\\n\\tlet p2: vec2f = floor(0.5 * (p % vec2f(4.0)));\\n\\treturn 4.0 * bayer2(p1) + bayer2(p2);\\n}\\nfn bayer8(p: vec2f) -> f32 {\\n\\tlet p1: vec2f = p % vec2f(2.0);\\n\\tlet p2: vec2f = floor(0.5 * (p % vec2f(4.0)));\\n\\tlet p4: vec2f = floor(0.25 * (p % vec2f(8.0)));\\n\\treturn 4.0 * (4.0 * bayer2(p1) + bayer2(p2)) + bayer2(p4);\\n}\\n`;\\n\\nvar blurVSM_default = `\\nvarying vUv0: vec2f;\\nvar source: texture_2d<f32>;\\nvar sourceSampler: sampler;\\n#ifdef GAUSS\\n\\tuniform weight: array<f32, {SAMPLES}>;\\n#endif\\nuniform pixelOffset: vec2f;\\n@fragment\\nfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\tvar output: FragmentOutput;\\n\\tvar moments: vec3f = vec3f(0.0);\\n\\tlet uv: vec2f = input.vUv0 - uniform.pixelOffset * (f32({SAMPLES}) * 0.5);\\n\\tfor (var i: i32 = 0; i < {SAMPLES}; i = i + 1) {\\n\\t\\tlet c: vec4f = textureSample(source, sourceSampler, uv + uniform.pixelOffset * f32(i));\\n\\t\\t#ifdef GAUSS\\n\\t\\t\\tmoments = moments + c.xyz * uniform.weight[i].element;\\n\\t\\t#else\\n\\t\\t\\tmoments = moments + c.xyz;\\n\\t\\t#endif\\n\\t}\\n\\t#ifndef GAUSS\\n\\t\\tmoments = moments * (1.0 / f32({SAMPLES}));\\n\\t#endif\\n\\toutput.color = vec4f(moments, 1.0);\\n\\treturn output;\\n}\\n`;\\n\\nvar clearCoat_default = `\\nuniform material_clearCoat: f32;\\nfn getClearCoat() {\\n\\tccSpecularity = uniform.material_clearCoat;\\n\\t#ifdef STD_CLEARCOAT_TEXTURE\\n\\tccSpecularity = ccSpecularity * textureSampleBias({STD_CLEARCOAT_TEXTURE_NAME}, {STD_CLEARCOAT_TEXTURE_NAME}Sampler, {STD_CLEARCOAT_TEXTURE_UV}, uniform.textureBias).{STD_CLEARCOAT_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_CLEARCOAT_VERTEX\\n\\tccSpecularity = ccSpecularity * saturate(vVertexColor.{STD_CLEARCOAT_VERTEX_CHANNEL});\\n\\t#endif\\n}\\n`;\\n\\nvar clearCoatGloss_default = `\\n\\tuniform material_clearCoatGloss: f32;\\nfn getClearCoatGlossiness() {\\n\\tccGlossiness = uniform.material_clearCoatGloss;\\n\\t#ifdef STD_CLEARCOATGLOSS_TEXTURE\\n\\tccGlossiness = ccGlossiness * textureSampleBias({STD_CLEARCOATGLOSS_TEXTURE_NAME}, {STD_CLEARCOATGLOSS_TEXTURE_NAME}Sampler, {STD_CLEARCOATGLOSS_TEXTURE_UV}, uniform.textureBias).{STD_CLEARCOATGLOSS_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_CLEARCOATGLOSS_VERTEX\\n\\tccGlossiness = ccGlossiness * saturate(vVertexColor.{STD_CLEARCOATGLOSS_VERTEX_CHANNEL});\\n\\t#endif\\n\\t#ifdef STD_CLEARCOATGLOSS_INVERT\\n\\tccGlossiness = 1.0 - ccGlossiness;\\n\\t#endif\\n\\tccGlossiness += 0.0000001;\\n}\\n`;\\n\\nvar clearCoatNormal_default = `\\n#ifdef STD_CLEARCOATNORMAL_TEXTURE\\n\\tuniform material_clearCoatBumpiness: f32;\\n#endif\\nfn getClearCoatNormal() {\\n#ifdef STD_CLEARCOATNORMAL_TEXTURE\\n\\tvar normalMap: vec3f = {STD_CLEARCOATNORMAL_TEXTURE_DECODE}(textureSampleBias({STD_CLEARCOATNORMAL_TEXTURE_NAME}, {STD_CLEARCOATNORMAL_TEXTURE_NAME}Sampler, {STD_CLEARCOATNORMAL_TEXTURE_UV}, uniform.textureBias));\\n\\tnormalMap = mix(vec3f(0.0, 0.0, 1.0), normalMap, uniform.material_clearCoatBumpiness);\\n\\tccNormalW = normalize(dTBN * normalMap);\\n#else\\n\\tccNormalW = dVertexNormalW;\\n#endif\\n}\\n`;\\n\\nvar clusteredLightUtils_default = `\\nstruct FaceCoords {\\n\\tuv: vec2f,\\n\\tfaceIndex: f32,\\n\\ttileOffset: vec2f,\\n}\\nfn getCubemapFaceCoordinates(dir: vec3f) -> FaceCoords {\\n\\tvar faceIndex: f32;\\n\\tvar tileOffset: vec2f;\\n\\tvar uv: vec2f;\\n\\tlet vAbs: vec3f = abs(dir);\\n\\tvar ma: f32;\\n\\tif (vAbs.z >= vAbs.x && vAbs.z >= vAbs.y) {\\n\\t\\tlet is_neg_z = dir.z < 0.0;\\n\\t\\tfaceIndex = select(4.0, 5.0, is_neg_z);\\n\\t\\tma = 0.5 / vAbs.z;\\n\\t\\tuv = vec2f(select(dir.x, -dir.x, is_neg_z), -dir.y);\\n\\t\\ttileOffset = vec2f(2.0, select(0.0, 1.0, is_neg_z));\\n\\t} else if (vAbs.y >= vAbs.x) {\\n\\t\\tlet is_neg_y = dir.y < 0.0;\\n\\t\\tfaceIndex = select(2.0, 3.0, is_neg_y);\\n\\t\\tma = 0.5 / vAbs.y;\\n\\t\\tuv = vec2f(dir.x, select(dir.z, -dir.z, is_neg_y));\\n\\t\\ttileOffset = vec2f(1.0, select(0.0, 1.0, is_neg_y));\\n\\t} else {\\n\\t\\tlet is_neg_x = dir.x < 0.0;\\n\\t\\tfaceIndex = select(0.0, 1.0, is_neg_x);\\n\\t\\tma = 0.5 / vAbs.x;\\n\\t\\tuv = vec2f(select(-dir.z, dir.z, is_neg_x), -dir.y);\\n\\t\\ttileOffset = vec2f(0.0, select(0.0, 1.0, is_neg_x));\\n\\t}\\n\\tuv = uv * ma + 0.5;\\n\\treturn FaceCoords(uv, faceIndex, tileOffset);\\n}\\nfn getCubemapAtlasCoordinates(omniAtlasViewport: vec3f, shadowEdgePixels: f32, shadowTextureResolution: f32, dir: vec3f) -> vec2f {\\n\\tlet faceData: FaceCoords = getCubemapFaceCoordinates(dir);\\n\\tvar uv: vec2f = faceData.uv;\\n\\tlet tileOffset: vec2f = faceData.tileOffset;\\n\\tlet atlasFaceSize: f32 = omniAtlasViewport.z;\\n\\tlet tileSize: f32 = shadowTextureResolution * atlasFaceSize;\\n\\tvar offset: f32 = shadowEdgePixels / tileSize;\\n\\tuv = uv * (1.0 - offset * 2.0) + offset;\\n\\tuv = uv * atlasFaceSize;\\n\\tuv = uv + tileOffset * atlasFaceSize;\\n\\tuv = uv + omniAtlasViewport.xy;\\n\\treturn uv;\\n}\\n`;\\n\\nvar clusteredLightCookies_default = `\\nfn _getCookieClustered(tex: texture_2d<f32>, texSampler: sampler, uv: vec2f, intensity: f32, cookieChannel: vec4f) -> vec3f {\\n\\tlet pixel: vec4f = mix(vec4f(1.0), textureSampleLevel(tex, texSampler, uv, 0.0), intensity);\\n\\tlet isRgb: bool = dot(cookieChannel.rgb, vec3f(1.0)) == 3.0;\\n\\treturn select(vec3f(dot(pixel, cookieChannel)), pixel.rgb, isRgb);\\n}\\nfn getCookie2DClustered(tex: texture_2d<f32>, texSampler: sampler, transform: mat4x4f, worldPosition: vec3f, intensity: f32, cookieChannel: vec4f) -> vec3f {\\n\\tlet projPos: vec4f = transform * vec4f(worldPosition, 1.0);\\n\\treturn _getCookieClustered(tex, texSampler, projPos.xy / projPos.w, intensity, cookieChannel);\\n}\\nfn getCookieCubeClustered(tex: texture_2d<f32>, texSampler: sampler, dir: vec3f, intensity: f32, cookieChannel: vec4f, shadowTextureResolution: f32, shadowEdgePixels: f32, omniAtlasViewport: vec3f) -> vec3f {\\n\\tlet uv: vec2f = getCubemapAtlasCoordinates(omniAtlasViewport, shadowEdgePixels, shadowTextureResolution, dir);\\n\\treturn _getCookieClustered(tex, texSampler, uv, intensity, cookieChannel);\\n}\\n`;\\n\\nvar clusteredLightShadows_default = `\\nfn _getShadowCoordPerspZbuffer(shadowMatrix: mat4x4f, shadowParams: vec4f, wPos: vec3f) -> vec3f {\\n\\tvar projPos = shadowMatrix * vec4f(wPos, 1.0);\\n\\treturn projPos.xyz / projPos.w;\\n}\\nfn getShadowCoordPerspZbufferNormalOffset(shadowMatrix: mat4x4f, shadowParams: vec4f, normal: vec3f) -> vec3f {\\n\\tlet wPos: vec3f = vPositionW + normal * shadowParams.y;\\n\\treturn _getShadowCoordPerspZbuffer(shadowMatrix, shadowParams, wPos);\\n}\\nfn normalOffsetPointShadow(shadowParams: vec4f, lightPos: vec3f, lightDir: vec3f, lightDirNorm: vec3f, normal: vec3f) -> vec3f {\\n\\tlet distScale: f32 = length(lightDir);\\n\\tlet wPos: vec3f = vPositionW + normal * shadowParams.y * clamp(1.0 - dot(normal, -lightDirNorm), 0.0, 1.0) * distScale;\\n\\tlet dir: vec3f = wPos - lightPos;\\n\\treturn dir;\\n}\\n#if defined(CLUSTER_SHADOW_TYPE_PCF1)\\n\\tfn getShadowOmniClusteredPCF1(shadowMap: texture_depth_2d, shadowMapSampler: sampler_comparison, shadowParams: vec4f, omniAtlasViewport: vec3f, shadowEdgePixels: f32, lightDir: vec3f) -> f32 {\\n\\t\\tlet shadowTextureResolution: f32 = shadowParams.x;\\n\\t\\tlet uv: vec2f = getCubemapAtlasCoordinates(omniAtlasViewport, shadowEdgePixels, shadowTextureResolution, lightDir);\\n\\t\\tlet shadowZ: f32 = length(lightDir) * shadowParams.w + shadowParams.z;\\n\\t\\treturn textureSampleCompareLevel(shadowMap, shadowMapSampler, uv, shadowZ);\\n\\t}\\n#endif\\n#if defined(CLUSTER_SHADOW_TYPE_PCF3)\\n\\tfn getShadowOmniClusteredPCF3(shadowMap: texture_depth_2d, shadowMapSampler: sampler_comparison, shadowParams: vec4f, omniAtlasViewport: vec3f, shadowEdgePixels: f32, lightDir: vec3f) -> f32 {\\n\\t\\tlet shadowTextureResolution: f32 = shadowParams.x;\\n\\t\\tlet uv: vec2f = getCubemapAtlasCoordinates(omniAtlasViewport, shadowEdgePixels, shadowTextureResolution, lightDir);\\n\\t\\tlet shadowZ: f32 = length(lightDir) * shadowParams.w + shadowParams.z;\\n\\t\\tlet shadowCoord: vec3f = vec3f(uv, shadowZ);\\n\\t\\treturn getShadowPCF3x3(shadowMap, shadowMapSampler, shadowCoord, shadowParams);\\n\\t}\\n#endif\\n#if defined(CLUSTER_SHADOW_TYPE_PCF5)\\n\\tfn getShadowOmniClusteredPCF5(shadowMap: texture_depth_2d, shadowMapSampler: sampler_comparison, shadowParams: vec4f, omniAtlasViewport: vec3f, shadowEdgePixels: f32, lightDir: vec3f) -> f32 {\\n\\t\\tlet shadowTextureResolution: f32 = shadowParams.x;\\n\\t\\tlet uv: vec2f = getCubemapAtlasCoordinates(omniAtlasViewport, shadowEdgePixels, shadowTextureResolution, lightDir);\\n\\t\\tlet shadowZ: f32 = length(lightDir) * shadowParams.w + shadowParams.z;\\n\\t\\tlet shadowCoord: vec3f = vec3f(uv, shadowZ);\\n\\t\\treturn getShadowPCF5x5(shadowMap, shadowMapSampler, shadowCoord, shadowParams);\\n\\t}\\n#endif\\n#if defined(CLUSTER_SHADOW_TYPE_PCF1)\\n\\tfn getShadowSpotClusteredPCF1(shadowMap: texture_depth_2d, shadowMapSampler: sampler_comparison, shadowCoord: vec3f, shadowParams: vec4f) -> f32 {\\n\\t\\treturn textureSampleCompareLevel(shadowMap, shadowMapSampler, shadowCoord.xy, shadowCoord.z);\\n\\t}\\n#endif\\n\\t#if defined(CLUSTER_SHADOW_TYPE_PCF3)\\n\\tfn getShadowSpotClusteredPCF3(shadowMap: texture_depth_2d, shadowMapSampler: sampler_comparison, shadowCoord: vec3f, shadowParams: vec4f) -> f32 {\\n\\t\\treturn getShadowSpotPCF3x3(shadowMap, shadowMapSampler, shadowCoord, shadowParams);\\n\\t}\\n#endif\\n\\t#if defined(CLUSTER_SHADOW_TYPE_PCF5)\\n\\tfn getShadowSpotClusteredPCF5(shadowMap: texture_depth_2d, shadowMapSampler: sampler_comparison, shadowCoord: vec3f, shadowParams: vec4f) -> f32 {\\n\\t\\treturn getShadowPCF5x5(shadowMap, shadowMapSampler, shadowCoord, shadowParams);\\n\\t}\\n#endif\\n`;\\n\\nvar clusteredLight_default = `\\n#include \\\"lightBufferDefinesPS\\\"\\n#include \\\"clusteredLightUtilsPS\\\"\\n#ifdef CLUSTER_COOKIES\\n\\t#include \\\"clusteredLightCookiesPS\\\"\\n#endif\\n#ifdef CLUSTER_SHADOWS\\n\\t#include \\\"clusteredLightShadowsPS\\\"\\n#endif\\nvar clusterWorldTexture: texture_2d<u32>;\\nvar lightsTexture: texture_2d<uff>;\\n#ifdef CLUSTER_SHADOWS\\n\\tvar shadowAtlasTexture: texture_depth_2d;\\n\\tvar shadowAtlasTextureSampler: sampler_comparison;\\n#endif\\n#ifdef CLUSTER_COOKIES\\n\\tvar cookieAtlasTexture: texture_2d<f32>;\\n\\tvar cookieAtlasTextureSampler: sampler;\\n#endif\\nuniform clusterMaxCells: i32;\\nuniform numClusteredLights: i32;\\nuniform clusterTextureWidth: i32;\\nuniform clusterCellsCountByBoundsSize: vec3f;\\nuniform clusterBoundsMin: vec3f;\\nuniform clusterBoundsDelta: vec3f;\\nuniform clusterCellsDot: vec3i;\\nuniform clusterCellsMax: vec3i;\\nuniform shadowAtlasParams: vec2f;\\nstruct ClusterLightData {\\n\\tposition: vec3f,\\n\\tlightIndex: i32,\\n\\tdirection: vec3f,\\n\\tshape: u32,\\n\\tcolor: vec3f,\\n\\tshadowIntensity: f32,\\n\\trange: f32,\\n\\tbiasesData: f32,\\n\\tcookieIntensity: f32,\\n\\tisSpot: bool,\\n\\tfalloffModeLinear: bool,\\n\\tisDynamic: bool,\\n\\tisLightmapped: bool\\n}\\nstruct ClusterLightSpotData {\\n\\tinnerConeAngleCos: f32,\\n\\touterConeAngleCos: f32\\n}\\nstruct ClusterLightAreaData {\\n\\thalfWidth: vec3f,\\n\\thalfHeight: vec3f\\n}\\nstruct ClusterLightShadowData {\\n\\tshadowBias: f32,\\n\\tshadowNormalBias: f32\\n}\\nvar<private> lightProjectionMatrix: mat4x4f;\\nvar<private> clusterLightData_flags: u32;\\nvar<private> clusterLightData_anglesData: f32;\\nvar<private> clusterLightData_colorBFlagsData: u32;\\nfn sampleLightTextureF(lightIndex: i32, index: i32) -> vec4f {\\n\\treturn textureLoad(lightsTexture, vec2<i32>(index, lightIndex), 0);\\n}\\nfn decodeClusterLightCore(lightIndex: i32) -> ClusterLightData {\\n\\tvar clusterLightData: ClusterLightData;\\n\\tclusterLightData.lightIndex = lightIndex;\\n\\tlet halfData: vec4f = sampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_COLOR_ANGLES_BIAS});\\n\\tclusterLightData_anglesData = halfData.z;\\n\\tclusterLightData.biasesData = halfData.w;\\n\\tclusterLightData_colorBFlagsData = bitcast<u32>(halfData.y);\\n\\tlet colorRG: vec2f = unpack2x16float(bitcast<u32>(halfData.x));\\n\\tlet colorB_flags: vec2f = unpack2x16float(clusterLightData_colorBFlagsData);\\n\\tclusterLightData.color = vec3f(colorRG, colorB_flags.x) * {LIGHT_COLOR_DIVIDER};\\n\\tlet lightPosRange: vec4f = sampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_POSITION_RANGE});\\n\\tclusterLightData.position = lightPosRange.xyz;\\n\\tclusterLightData.range = lightPosRange.w;\\n\\tlet lightDir_Flags: vec4f = sampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_DIRECTION_FLAGS});\\n\\tclusterLightData.direction = lightDir_Flags.xyz;\\n\\tclusterLightData_flags = bitcast<u32>(lightDir_Flags.w);\\n\\tclusterLightData.isSpot = (clusterLightData_flags & (1u << 30u)) != 0u;\\n\\tclusterLightData.shape = (clusterLightData_flags >> 28u) & 0x3u;\\n\\tclusterLightData.falloffModeLinear = (clusterLightData_flags & (1u << 27u)) == 0u;\\n\\tclusterLightData.shadowIntensity = f32((clusterLightData_flags >> 0u) & 0xFFu) / 255.0;\\n\\tclusterLightData.cookieIntensity = f32((clusterLightData_flags >> 8u) & 0xFFu) / 255.0;\\n\\tclusterLightData.isDynamic = (clusterLightData_flags & (1u << 22u)) != 0u;\\n\\tclusterLightData.isLightmapped = (clusterLightData_flags & (1u << 21u)) != 0u;\\n\\treturn clusterLightData;\\n}\\nfn decodeClusterLightSpot() -> ClusterLightSpotData {\\n\\tlet angleFlags: u32 = (clusterLightData_colorBFlagsData >> 16u) & 0xFFFFu;\\n\\tlet angleValues: vec2f = unpack2x16float(bitcast<u32>(clusterLightData_anglesData));\\n\\tlet innerVal: f32 = angleValues.x;\\n\\tlet outerVal: f32 = angleValues.y;\\n\\tlet innerIsVersine: bool = (angleFlags & 1u) != 0u;\\n\\tlet outerIsVersine: bool = ((angleFlags >> 1u) & 1u) != 0u;\\n\\treturn ClusterLightSpotData(\\n\\t\\tselect(innerVal, 1.0 - innerVal, innerIsVersine),\\n\\t\\tselect(outerVal, 1.0 - outerVal, outerIsVersine)\\n\\t);\\n}\\nfn decodeClusterLightOmniAtlasViewport(lightIndex: i32) -> vec3f {\\n\\treturn sampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_PROJ_MAT_0}).xyz;\\n}\\nfn decodeClusterLightAreaData(lightIndex: i32) -> ClusterLightAreaData {\\n\\treturn ClusterLightAreaData(\\n\\t\\tsampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_AREA_DATA_WIDTH}).xyz,\\n\\t\\tsampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_AREA_DATA_HEIGHT}).xyz\\n\\t);\\n}\\nfn decodeClusterLightProjectionMatrixData(lightIndex: i32) -> mat4x4f {\\n\\tlet m0: vec4f = sampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_PROJ_MAT_0});\\n\\tlet m1: vec4f = sampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_PROJ_MAT_1});\\n\\tlet m2: vec4f = sampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_PROJ_MAT_2});\\n\\tlet m3: vec4f = sampleLightTextureF(lightIndex, {CLUSTER_TEXTURE_PROJ_MAT_3});\\n\\treturn mat4x4f(m0, m1, m2, m3);\\n}\\nfn decodeClusterLightShadowData(biasesData: f32) -> ClusterLightShadowData {\\n\\tlet biases: vec2f = unpack2x16float(bitcast<u32>(biasesData));\\n\\treturn ClusterLightShadowData(biases.x, biases.y);\\n}\\nfn decodeClusterLightCookieData() -> vec4f {\\n\\tlet cookieFlags: u32 = (clusterLightData_flags >> 23u) & 0x0Fu;\\n\\tlet mask_uvec: vec4<u32> = vec4<u32>(cookieFlags) & vec4<u32>(1u, 2u, 4u, 8u);\\n\\treturn step(vec4f(1.0), vec4f(mask_uvec));\\n}\\nfn evaluateLight(\\n\\tlight: ClusterLightData,\\n\\tworldNormal: vec3f,\\n\\tviewDir: vec3f,\\n\\treflectionDir: vec3f,\\n#if defined(LIT_CLEARCOAT)\\n\\tclearcoatReflectionDir: vec3f,\\n#endif\\n\\tgloss: f32,\\n\\tspecularity: vec3f,\\n\\tgeometricNormal: vec3f,\\n\\ttbn: mat3x3f,\\n#if defined(LIT_IRIDESCENCE)\\n\\tiridescenceFresnel: vec3f,\\n#endif\\n\\tclearcoat_worldNormal: vec3f,\\n\\tclearcoat_gloss: f32,\\n\\tsheen_gloss: f32,\\n\\tiridescence_intensity: f32\\n) {\\n\\tvar cookieAttenuation: vec3f = vec3f(1.0);\\n\\tvar diffuseAttenuation: f32 = 1.0;\\n\\tvar falloffAttenuation: f32 = 1.0;\\n\\tlet lightDirW: vec3f = evalOmniLight(light.position);\\n\\tlet lightDirNormW: vec3f = normalize(lightDirW);\\n\\t#ifdef CLUSTER_AREALIGHTS\\n\\tif (light.shape != {LIGHTSHAPE_PUNCTUAL}) {\\n\\t\\tlet areaData: ClusterLightAreaData = decodeClusterLightAreaData(light.lightIndex);\\n\\t\\tif (light.shape == {LIGHTSHAPE_RECT}) {\\n\\t\\t\\tcalcRectLightValues(light.position, areaData.halfWidth, areaData.halfHeight);\\n\\t\\t} else if (light.shape == {LIGHTSHAPE_DISK}) {\\n\\t\\t\\tcalcDiskLightValues(light.position, areaData.halfWidth, areaData.halfHeight);\\n\\t\\t} else {\\n\\t\\t\\tcalcSphereLightValues(light.position, areaData.halfWidth, areaData.halfHeight);\\n\\t\\t}\\n\\t\\tfalloffAttenuation = getFalloffWindow(light.range, lightDirW);\\n\\t} else\\n\\t#endif\\n\\t{\\n\\t\\tif (light.falloffModeLinear) {\\n\\t\\t\\tfalloffAttenuation = getFalloffLinear(light.range, lightDirW);\\n\\t\\t} else {\\n\\t\\t\\tfalloffAttenuation = getFalloffInvSquared(light.range, lightDirW);\\n\\t\\t}\\n\\t}\\n\\tif (falloffAttenuation > 0.00001) {\\n\\t\\t#ifdef CLUSTER_AREALIGHTS\\n\\t\\tif (light.shape != {LIGHTSHAPE_PUNCTUAL}) {\\n\\t\\t\\tif (light.shape == {LIGHTSHAPE_RECT}) {\\n\\t\\t\\t\\tdiffuseAttenuation = getRectLightDiffuse(worldNormal, viewDir, lightDirW, lightDirNormW) * 16.0;\\n\\t\\t\\t} else if (light.shape == {LIGHTSHAPE_DISK}) {\\n\\t\\t\\t\\tdiffuseAttenuation = getDiskLightDiffuse(worldNormal, viewDir, lightDirW, lightDirNormW) * 16.0;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tdiffuseAttenuation = getSphereLightDiffuse(worldNormal, viewDir, lightDirW, lightDirNormW) * 16.0;\\n\\t\\t\\t}\\n\\t\\t} else\\n\\t\\t#endif\\n\\t\\t{\\n\\t\\t\\tfalloffAttenuation = falloffAttenuation * getLightDiffuse(worldNormal, viewDir, lightDirNormW);\\n\\t\\t}\\n\\t\\tif (light.isSpot) {\\n\\t\\t\\tlet spotData: ClusterLightSpotData = decodeClusterLightSpot();\\n\\t\\t\\tfalloffAttenuation = falloffAttenuation * getSpotEffect(light.direction, spotData.innerConeAngleCos, spotData.outerConeAngleCos, lightDirNormW);\\n\\t\\t}\\n\\t\\t#if defined(CLUSTER_COOKIES) || defined(CLUSTER_SHADOWS)\\n\\t\\tif (falloffAttenuation > 0.00001) {\\n\\t\\t\\tif (light.shadowIntensity > 0.0 || light.cookieIntensity > 0.0) {\\n\\t\\t\\t\\tvar omniAtlasViewport: vec3f = vec3f(0.0);\\n\\t\\t\\t\\tif (light.isSpot) {\\n\\t\\t\\t\\t\\tlightProjectionMatrix = decodeClusterLightProjectionMatrixData(light.lightIndex);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tomniAtlasViewport = decodeClusterLightOmniAtlasViewport(light.lightIndex);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet shadowTextureResolution: f32 = uniform.shadowAtlasParams.x;\\n\\t\\t\\t\\tlet shadowEdgePixels: f32 = uniform.shadowAtlasParams.y;\\n\\t\\t\\t\\t#ifdef CLUSTER_COOKIES\\n\\t\\t\\t\\tif (light.cookieIntensity > 0.0) {\\n\\t\\t\\t\\t\\tlet cookieChannelMask: vec4f = decodeClusterLightCookieData();\\n\\t\\t\\t\\t\\tif (light.isSpot) {\\n\\t\\t\\t\\t\\t\\tcookieAttenuation = getCookie2DClustered(cookieAtlasTexture, cookieAtlasTextureSampler, lightProjectionMatrix, vPositionW, light.cookieIntensity, cookieChannelMask);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tcookieAttenuation = getCookieCubeClustered(cookieAtlasTexture, cookieAtlasTextureSampler, lightDirW, light.cookieIntensity, cookieChannelMask, shadowTextureResolution, shadowEdgePixels, omniAtlasViewport);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#ifdef CLUSTER_SHADOWS\\n\\t\\t\\t\\tif (light.shadowIntensity > 0.0) {\\n\\t\\t\\t\\t\\tlet shadowData: ClusterLightShadowData = decodeClusterLightShadowData(light.biasesData);\\n\\t\\t\\t\\t\\tlet shadowParams: vec4f = vec4f(shadowTextureResolution, shadowData.shadowNormalBias, shadowData.shadowBias, 1.0 / light.range);\\n\\t\\t\\t\\t\\tif (light.isSpot) {\\n\\t\\t\\t\\t\\t\\tlet shadowCoord: vec3f = getShadowCoordPerspZbufferNormalOffset(lightProjectionMatrix, shadowParams, geometricNormal);\\n\\t\\t\\t\\t\\t\\t#if defined(CLUSTER_SHADOW_TYPE_PCF1)\\n\\t\\t\\t\\t\\t\\t\\tlet shadow: f32 = getShadowSpotClusteredPCF1(shadowAtlasTexture, shadowAtlasTextureSampler, shadowCoord, shadowParams);\\n\\t\\t\\t\\t\\t\\t#elif defined(CLUSTER_SHADOW_TYPE_PCF3)\\n\\t\\t\\t\\t\\t\\t\\tlet shadow: f32 = getShadowSpotClusteredPCF3(shadowAtlasTexture, shadowAtlasTextureSampler, shadowCoord, shadowParams);\\n\\t\\t\\t\\t\\t\\t#elif defined(CLUSTER_SHADOW_TYPE_PCF5)\\n\\t\\t\\t\\t\\t\\t\\tlet shadow: f32 = getShadowSpotClusteredPCF5(shadowAtlasTexture, shadowAtlasTextureSampler, shadowCoord, shadowParams);\\n\\t\\t\\t\\t\\t\\t#elif defined(CLUSTER_SHADOW_TYPE_PCSS)\\n\\t\\t\\t\\t\\t\\t\\tlet shadow: f32 = getShadowSpotClusteredPCSS(shadowAtlasTexture, shadowAtlasTextureSampler, shadowCoord, shadowParams);\\n\\t\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\t\\tfalloffAttenuation = falloffAttenuation * mix(1.0, shadow, light.shadowIntensity);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tlet dir: vec3f = normalOffsetPointShadow(shadowParams, light.position, lightDirW, lightDirNormW, geometricNormal);\\n\\t\\t\\t\\t\\t\\t#if defined(CLUSTER_SHADOW_TYPE_PCF1)\\n\\t\\t\\t\\t\\t\\t\\tlet shadow: f32 = getShadowOmniClusteredPCF1(shadowAtlasTexture, shadowAtlasTextureSampler, shadowParams, omniAtlasViewport, shadowEdgePixels, dir);\\n\\t\\t\\t\\t\\t\\t#elif defined(CLUSTER_SHADOW_TYPE_PCF3)\\n\\t\\t\\t\\t\\t\\t\\tlet shadow: f32 = getShadowOmniClusteredPCF3(shadowAtlasTexture, shadowAtlasTextureSampler, shadowParams, omniAtlasViewport, shadowEdgePixels, dir);\\n\\t\\t\\t\\t\\t\\t#elif defined(CLUSTER_SHADOW_TYPE_PCF5)\\n\\t\\t\\t\\t\\t\\t\\tlet shadow: f32 = getShadowOmniClusteredPCF5(shadowAtlasTexture, shadowAtlasTextureSampler, shadowParams, omniAtlasViewport, shadowEdgePixels, dir);\\n\\t\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\t\\tfalloffAttenuation = falloffAttenuation * mix(1.0, shadow, light.shadowIntensity);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\t#endif\\n\\t\\t#ifdef CLUSTER_AREALIGHTS\\n\\t\\tif (light.shape != {LIGHTSHAPE_PUNCTUAL}) {\\n\\t\\t\\t{\\n\\t\\t\\t\\tvar areaDiffuse: vec3f = (diffuseAttenuation * falloffAttenuation) * light.color * cookieAttenuation;\\n\\t\\t\\t\\t#if defined(LIT_SPECULAR)\\n\\t\\t\\t\\t\\tareaDiffuse = mix(areaDiffuse, vec3f(0.0), dLTCSpecFres);\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\tdDiffuseLight = dDiffuseLight + areaDiffuse;\\n\\t\\t\\t}\\n\\t\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\t\\tvar areaLightSpecular: f32;\\n\\t\\t\\t\\tif (light.shape == {LIGHTSHAPE_RECT}) {\\n\\t\\t\\t\\t\\tareaLightSpecular = getRectLightSpecular(worldNormal, viewDir);\\n\\t\\t\\t\\t} else if (light.shape == {LIGHTSHAPE_DISK}) {\\n\\t\\t\\t\\t\\tareaLightSpecular = getDiskLightSpecular(worldNormal, viewDir);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tareaLightSpecular = getSphereLightSpecular(worldNormal, viewDir);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdSpecularLight = dSpecularLight + dLTCSpecFres * areaLightSpecular * falloffAttenuation * light.color * cookieAttenuation;\\n\\t\\t\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t\\t\\tvar areaLightSpecularCC: f32;\\n\\t\\t\\t\\t\\tif (light.shape == {LIGHTSHAPE_RECT}) {\\n\\t\\t\\t\\t\\t\\tareaLightSpecularCC = getRectLightSpecular(clearcoat_worldNormal, viewDir);\\n\\t\\t\\t\\t\\t} else if (light.shape == {LIGHTSHAPE_DISK}) {\\n\\t\\t\\t\\t\\t\\tareaLightSpecularCC = getDiskLightSpecular(clearcoat_worldNormal, viewDir);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tareaLightSpecularCC = getSphereLightSpecular(clearcoat_worldNormal, viewDir);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tccSpecularLight = ccSpecularLight + ccLTCSpecFres * areaLightSpecularCC * falloffAttenuation * light.color  * cookieAttenuation;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t} else\\n\\t\\t#endif\\n\\t\\t{\\n\\t\\t\\t{\\n\\t\\t\\t\\tvar punctualDiffuse: vec3f = falloffAttenuation * light.color * cookieAttenuation;\\n\\t\\t\\t\\t#if defined(CLUSTER_AREALIGHTS)\\n\\t\\t\\t\\t#if defined(LIT_SPECULAR)\\n\\t\\t\\t\\t\\tpunctualDiffuse = mix(punctualDiffuse, vec3f(0.0), specularity);\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\tdDiffuseLight = dDiffuseLight + punctualDiffuse;\\n\\t\\t\\t}\\n\\t\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\t\\tlet halfDir: vec3f = normalize(-lightDirNormW + viewDir);\\n\\t\\t\\t\\t#ifdef LIT_SPECULAR_FRESNEL\\n\\t\\t\\t\\t\\tdSpecularLight = dSpecularLight +\\n\\t\\t\\t\\t\\t\\tgetLightSpecular(halfDir, reflectionDir, worldNormal, viewDir, lightDirNormW, gloss, tbn) * falloffAttenuation * light.color * cookieAttenuation *\\n\\t\\t\\t\\t\\t\\tgetFresnel(\\n\\t\\t\\t\\t\\t\\t\\tdot(viewDir, halfDir),\\n\\t\\t\\t\\t\\t\\t\\tgloss,\\n\\t\\t\\t\\t\\t\\t\\tspecularity\\n\\t\\t\\t\\t\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t\\t\\t\\t\\t, iridescenceFresnel,\\n\\t\\t\\t\\t\\t\\t\\tiridescence_intensity\\n\\t\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\tdSpecularLight = dSpecularLight + getLightSpecular(halfDir, reflectionDir, worldNormal, viewDir, lightDirNormW, gloss, tbn) * falloffAttenuation * light.color * cookieAttenuation * specularity;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t\\t\\t#ifdef LIT_SPECULAR_FRESNEL\\n\\t\\t\\t\\t\\t\\tccSpecularLight = ccSpecularLight + getLightSpecular(halfDir, clearcoatReflectionDir, clearcoat_worldNormal, viewDir, lightDirNormW, clearcoat_gloss, tbn) * falloffAttenuation * light.color * cookieAttenuation * getFresnelCC(dot(viewDir, halfDir));\\n\\t\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\t\\tccSpecularLight = ccSpecularLight + getLightSpecular(halfDir, clearcoatReflectionDir, clearcoat_worldNormal, viewDir, lightDirNormW, clearcoat_gloss, tbn) * falloffAttenuation * light.color * cookieAttenuation;\\n\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#ifdef LIT_SHEEN\\n\\t\\t\\t\\t\\tsSpecularLight = sSpecularLight + getLightSpecularSheen(halfDir, worldNormal, viewDir, lightDirNormW, sheen_gloss) * falloffAttenuation * light.color * cookieAttenuation;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t}\\n\\t}\\n\\tdAtten = falloffAttenuation;\\n\\tdLightDirNormW = lightDirNormW;\\n}\\nfn evaluateClusterLight(\\n\\tlightIndex: i32,\\n\\tworldNormal: vec3f,\\n\\tviewDir: vec3f,\\n\\treflectionDir: vec3f,\\n#if defined(LIT_CLEARCOAT)\\n\\tclearcoatReflectionDir: vec3f,\\n#endif\\n\\tgloss: f32,\\n\\tspecularity: vec3f,\\n\\tgeometricNormal: vec3f,\\n\\ttbn: mat3x3f,\\n#if defined(LIT_IRIDESCENCE)\\n\\tiridescenceFresnel: vec3f,\\n#endif\\n\\tclearcoat_worldNormal: vec3f,\\n\\tclearcoat_gloss: f32,\\n\\tsheen_gloss: f32,\\n\\tiridescence_intensity: f32\\n) {\\n\\tlet clusterLightData: ClusterLightData = decodeClusterLightCore(lightIndex);\\n\\t#ifdef CLUSTER_MESH_DYNAMIC_LIGHTS\\n\\t\\tlet acceptLightMask: bool = clusterLightData.isDynamic;\\n\\t#else\\n\\t\\tlet acceptLightMask: bool = clusterLightData.isLightmapped;\\n\\t#endif\\n\\tif (acceptLightMask) {\\n\\t\\tevaluateLight(\\n\\t\\t\\tclusterLightData,\\n\\t\\t\\tworldNormal,\\n\\t\\t\\tviewDir,\\n\\t\\t\\treflectionDir,\\n#if defined(LIT_CLEARCOAT)\\n\\t\\t\\tclearcoatReflectionDir,\\n#endif\\n\\t\\t\\tgloss,\\n\\t\\t\\tspecularity,\\n\\t\\t\\tgeometricNormal,\\n\\t\\t\\ttbn,\\n#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\tiridescenceFresnel,\\n#endif\\n\\t\\t\\tclearcoat_worldNormal,\\n\\t\\t\\tclearcoat_gloss,\\n\\t\\t\\tsheen_gloss,\\n\\t\\t\\tiridescence_intensity\\n\\t\\t);\\n\\t}\\n}\\nfn addClusteredLights(\\n\\tworldNormal: vec3f,\\n\\tviewDir: vec3f,\\n\\treflectionDir: vec3f,\\n#if defined(LIT_CLEARCOAT)\\n\\tclearcoatReflectionDir: vec3f,\\n#endif\\n\\tgloss: f32,\\n\\tspecularity: vec3f,\\n\\tgeometricNormal: vec3f,\\n\\ttbn: mat3x3f,\\n#if defined(LIT_IRIDESCENCE)\\n\\tiridescenceFresnel: vec3f,\\n#endif\\n\\tclearcoat_worldNormal: vec3f,\\n\\tclearcoat_gloss: f32,\\n\\tsheen_gloss: f32,\\n\\tiridescence_intensity: f32\\n) {\\n\\tif (uniform.numClusteredLights <= 1) {\\n\\t\\treturn;\\n\\t}\\n\\tlet cellCoords: vec3i = vec3i(floor((vPositionW - uniform.clusterBoundsMin) * uniform.clusterCellsCountByBoundsSize));\\n\\tif (!(any(cellCoords < vec3i(0)) || any(cellCoords >= uniform.clusterCellsMax))) {\\n\\t\\tlet cellIndex: i32 = cellCoords.x * uniform.clusterCellsDot.x + cellCoords.y * uniform.clusterCellsDot.y + cellCoords.z * uniform.clusterCellsDot.z;\\n\\t\\tlet clusterV: i32 = cellIndex / uniform.clusterTextureWidth;\\n\\t\\tlet clusterU: i32 = cellIndex - clusterV * uniform.clusterTextureWidth;\\n\\t\\tfor (var lightCellIndex: i32 = 0; lightCellIndex < uniform.clusterMaxCells; lightCellIndex = lightCellIndex + 1) {\\n\\t\\t\\tlet lightIndex: u32 = textureLoad(clusterWorldTexture, vec2<i32>(clusterU + lightCellIndex, clusterV), 0).r;\\n\\t\\t\\tif (lightIndex == 0u) {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\tevaluateClusterLight(\\n\\t\\t\\t\\ti32(lightIndex),\\n\\t\\t\\t\\tworldNormal,\\n\\t\\t\\t\\tviewDir,\\n\\t\\t\\t\\treflectionDir,\\n#if defined(LIT_CLEARCOAT)\\n\\t\\t\\t\\tclearcoatReflectionDir,\\n#endif\\n\\t\\t\\t\\tgloss,\\n\\t\\t\\t\\tspecularity,\\n\\t\\t\\t\\tgeometricNormal,\\n\\t\\t\\t\\ttbn,\\n#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t\\tiridescenceFresnel,\\n#endif\\n\\t\\t\\t\\tclearcoat_worldNormal,\\n\\t\\t\\t\\tclearcoat_gloss,\\n\\t\\t\\t\\tsheen_gloss,\\n\\t\\t\\t\\tiridescence_intensity\\n\\t\\t\\t);\\n\\t\\t}\\n\\t}\\n}`;\\n\\nvar combine_default = `\\nfn combineColor(albedo: vec3f, sheenSpecularity: vec3f, clearcoatSpecularity: f32) -> vec3f {\\n\\tvar ret: vec3f = vec3f(0.0);\\n\\t#ifdef LIT_OLD_AMBIENT\\n\\t\\tret = ret + ((dDiffuseLight - uniform.light_globalAmbient) * albedo + uniform.material_ambient * uniform.light_globalAmbient);\\n\\t#else\\n\\t\\tret = ret + (albedo * dDiffuseLight);\\n\\t#endif\\n\\t#ifdef LIT_SPECULAR\\n\\t\\tret = ret + dSpecularLight;\\n\\t#endif\\n\\t#ifdef LIT_REFLECTIONS\\n\\t\\tret = ret + (dReflection.rgb * dReflection.a);\\n\\t#endif\\n\\t#ifdef LIT_SHEEN\\n\\t\\tlet sheenScaling: f32 = 1.0 - max(max(sheenSpecularity.r, sheenSpecularity.g), sheenSpecularity.b) * 0.157;\\n\\t\\tret = ret * sheenScaling + (sSpecularLight + sReflection.rgb) * sheenSpecularity;\\n\\t#endif\\n\\t#ifdef LIT_CLEARCOAT\\n\\t\\tlet clearCoatScaling: f32 = 1.0 - ccFresnel * clearcoatSpecularity;\\n\\t\\tret = ret * clearCoatScaling + (ccSpecularLight + ccReflection) * clearcoatSpecularity;\\n\\t#endif\\n\\treturn ret;\\n}\\n`;\\n\\nvar cookie_blit_2d_default = `\\n\\tvarying uv0: vec2f;\\n\\tvar blitTexture: texture_2d<f32>;\\n\\tvar blitTextureSampler : sampler;\\n\\t@fragment\\n\\tfn fragmentMain(input : FragmentInput) -> FragmentOutput {\\n\\t\\tvar output: FragmentOutput;\\n\\t\\toutput.color = textureSample(blitTexture, blitTextureSampler, input.uv0);\\n\\t\\treturn output;\\n\\t}\\n`;\\n\\nvar cookie_blit_cube_default = `\\n\\tvarying uv0: vec2f;\\n\\tuniform invViewProj: mat4x4<f32>;\\n\\tvar blitTexture: texture_cube<f32>;\\n\\tvar blitTextureSampler : sampler;\\n\\t@fragment\\n\\tfn fragmentMain(input : FragmentInput) -> FragmentOutput {\\n\\t\\tvar output: FragmentOutput;\\n\\t\\tvar projPos = vec4f(input.uv0 * 2.0 - 1.0, 0.5, 1.0);\\n\\t\\tvar worldPos = uniform.invViewProj * projPos;\\n\\t\\toutput.color = textureSample(blitTexture, blitTextureSampler, worldPos.xyz);\\n\\t\\treturn output;\\n\\t}\\n`;\\n\\nvar cookie_blit_default = `\\n\\tattribute vertex_position: vec2f;\\n\\tvarying uv0: vec2f;\\n\\t@vertex\\n\\tfn vertexMain(input: VertexInput) -> VertexOutput {\\n\\t\\tvar output: VertexOutput;\\n\\t\\toutput.position = vec4f(input.vertex_position, 0.5, 1.0);\\n\\t\\toutput.uv0 = input.vertex_position * 0.5 + vec2f(0.5, 0.5);\\n\\t\\toutput.uv0.y = 1.0 - output.uv0.y;\\n\\t\\treturn output;\\n\\t}\\n`;\\n\\nvar cubeMapProject_default = `\\n#if LIT_CUBEMAP_PROJECTION == BOX\\n\\tuniform envBoxMin: vec3f;\\n\\tuniform envBoxMax: vec3f;\\n#endif\\nfn cubeMapProject(nrdir: vec3f) -> vec3f {\\n\\t#if LIT_CUBEMAP_PROJECTION == NONE\\n\\t\\treturn cubeMapRotate(nrdir);\\n\\t#endif\\n\\t#if LIT_CUBEMAP_PROJECTION == BOX\\n\\t\\tlet nrdir_rotated: vec3f = cubeMapRotate(nrdir);\\n\\t\\tlet rbmax: vec3f = (uniform.envBoxMax - vPositionW) / nrdir_rotated;\\n\\t\\tlet rbmin: vec3f = (uniform.envBoxMin - vPositionW) / nrdir_rotated;\\n\\t\\tlet rbminmax: vec3f = select(rbmin, rbmax, nrdir_rotated > vec3f(0.0));\\n\\t\\tlet fa: f32 = min(min(rbminmax.x, rbminmax.y), rbminmax.z);\\n\\t\\tlet posonbox: vec3f = vPositionW + nrdir_rotated * fa;\\n\\t\\tlet envBoxPos: vec3f = (uniform.envBoxMin + uniform.envBoxMax) * 0.5;\\n\\t\\treturn normalize(posonbox - envBoxPos);\\n\\t#endif\\n}\\n`;\\n\\nvar cubeMapRotate_default = `\\n#ifdef CUBEMAP_ROTATION\\nuniform cubeMapRotationMatrix: mat3x3f;\\n#endif\\nfn cubeMapRotate(refDir: vec3f) -> vec3f {\\n#ifdef CUBEMAP_ROTATION\\n\\treturn refDir * uniform.cubeMapRotationMatrix;\\n#else\\n\\treturn refDir;\\n#endif\\n}\\n`;\\n\\nvar debug_output_default = `\\n#ifdef DEBUG_ALBEDO_PASS\\noutput.color = vec4(gammaCorrectOutput(dAlbedo), 1.0);\\n#endif\\n#ifdef DEBUG_UV0_PASS\\noutput.color = vec4f(litArgs_albedo , 1.0);\\n#endif\\n#ifdef DEBUG_WORLD_NORMAL_PASS\\noutput.color = vec4f(litArgs_worldNormal * 0.5 + 0.5, 1.0);\\n#endif\\n#ifdef DEBUG_OPACITY_PASS\\noutput.color = vec4f(vec3f(litArgs_opacity) , 1.0);\\n#endif\\n#ifdef DEBUG_SPECULARITY_PASS\\noutput.color = vec4f(litArgs_specularity, 1.0);\\n#endif\\n#ifdef DEBUG_GLOSS_PASS\\noutput.color = vec4f(vec3f(litArgs_gloss) , 1.0);\\n#endif\\n#ifdef DEBUG_METALNESS_PASS\\noutput.color = vec4f(vec3f(litArgs_metalness) , 1.0);\\n#endif\\n#ifdef DEBUG_AO_PASS\\noutput.color = vec4f(vec3f(litArgs_ao) , 1.0);\\n#endif\\n#ifdef DEBUG_EMISSION_PASS\\noutput.color = vec4f(gammaCorrectOutput(litArgs_emission), 1.0);\\n#endif\\n`;\\n\\nvar debug_process_frontend_default = `\\n#ifdef DEBUG_LIGHTING_PASS\\n\\tlitArgs_albedo = vec3f(0.5);\\n#endif\\n#ifdef DEBUG_UV0_PASS\\n#ifdef VARYING_VUV0\\n\\tlitArgs_albedo = vec3f(vUv0, 0.0);\\n#else\\n\\tlitArgs_albedo = vec3f(0.0);\\n#endif\\n#endif\\n`;\\n\\nvar decode_default = `\\n#ifndef _DECODE_INCLUDED_\\n#define _DECODE_INCLUDED_\\nfn decodeLinear(raw: vec4f) -> vec3f {\\n\\treturn raw.rgb;\\n}\\nfn decodeGammaFloat(raw: f32) -> f32 {\\n\\treturn pow(raw, 2.2);\\n}\\nfn decodeGamma3(raw: vec3f) -> vec3f {\\n\\treturn pow(raw, vec3f(2.2));\\n}\\nfn decodeGamma(raw: vec4f) -> vec3f {\\n\\treturn pow(raw.xyz, vec3f(2.2));\\n}\\nfn decodeRGBM(raw: vec4f) -> vec3f {\\n\\tlet color = (8.0 * raw.a) * raw.rgb;\\n\\treturn color * color;\\n}\\nfn decodeRGBP(raw: vec4f) -> vec3f {\\n\\tlet color = raw.rgb * (-raw.a * 7.0 + 8.0);\\n\\treturn color * color;\\n}\\nfn decodeRGBE(raw: vec4f) -> vec3f {\\n\\treturn select(vec3f(0.0), raw.xyz * pow(2.0, raw.w * 255.0 - 128.0), raw.a != 0.0);\\n}\\nfn passThrough(raw: vec4f) -> vec4f {\\n\\treturn raw;\\n}\\nfn unpackNormalXYZ(nmap: vec4f) -> vec3f {\\n\\treturn nmap.xyz * 2.0 - 1.0;\\n}\\nfn unpackNormalXY(nmap: vec4f) -> vec3f {\\n\\tvar xy = nmap.wy * 2.0 - 1.0;\\n\\treturn vec3f(xy, sqrt(1.0 - clamp(dot(xy, xy), 0.0, 1.0)));\\n}\\n#endif\\n`;\\n\\nvar detailModes_default = `\\n#ifndef _DETAILMODES_INCLUDED_\\n#define _DETAILMODES_INCLUDED_\\nfn detailMode_mul(c1: vec3f, c2: vec3f) -> vec3f {\\n\\treturn c1 * c2;\\n}\\nfn detailMode_add(c1: vec3f, c2: vec3f) -> vec3f {\\n\\treturn c1 + c2;\\n}\\nfn detailMode_screen(c1: vec3f, c2: vec3f) -> vec3f {\\n\\treturn 1.0 - (1.0 - c1)*(1.0 - c2);\\n}\\nfn detailMode_overlay(c1: vec3f, c2: vec3f) -> vec3f {\\n\\treturn mix(1.0 - 2.0 * (1.0 - c1)*(1.0 - c2), 2.0 * c1 * c2, step(c1, vec3f(0.5)));\\n}\\nfn detailMode_min(c1: vec3f, c2: vec3f) -> vec3f {\\n\\treturn min(c1, c2);\\n}\\nfn detailMode_max(c1: vec3f, c2: vec3f) -> vec3f {\\n\\treturn max(c1, c2);\\n}\\n#endif\\n`;\\n\\nvar diffuse_default = `\\nuniform material_diffuse: vec3f;\\n#ifdef STD_DIFFUSEDETAIL_TEXTURE\\n\\t#include \\\"detailModesPS\\\"\\n#endif\\nfn getAlbedo() {\\n\\tdAlbedo = uniform.material_diffuse.rgb;\\n\\t#ifdef STD_DIFFUSE_TEXTURE\\n\\t\\tvar albedoTexture: vec3f = {STD_DIFFUSE_TEXTURE_DECODE}(textureSampleBias({STD_DIFFUSE_TEXTURE_NAME}, {STD_DIFFUSE_TEXTURE_NAME}Sampler, {STD_DIFFUSE_TEXTURE_UV}, uniform.textureBias)).{STD_DIFFUSE_TEXTURE_CHANNEL};\\n\\t\\t#ifdef STD_DIFFUSEDETAIL_TEXTURE\\n\\t\\t\\tvar albedoDetail: vec3f = {STD_DIFFUSEDETAIL_TEXTURE_DECODE}(textureSampleBias({STD_DIFFUSEDETAIL_TEXTURE_NAME}, {STD_DIFFUSEDETAIL_TEXTURE_NAME}Sampler, {STD_DIFFUSEDETAIL_TEXTURE_UV}, uniform.textureBias)).{STD_DIFFUSEDETAIL_TEXTURE_CHANNEL};\\n\\t\\t\\talbedoTexture = detailMode_{STD_DIFFUSEDETAIL_DETAILMODE}(albedoTexture, albedoDetail);\\n\\t\\t#endif\\n\\t\\tdAlbedo = dAlbedo * albedoTexture;\\n\\t#endif\\n\\t#ifdef STD_DIFFUSE_VERTEX\\n\\t\\tdAlbedo = dAlbedo * saturate3(vVertexColor.{STD_DIFFUSE_VERTEX_CHANNEL});\\n\\t#endif\\n}\\n`;\\n\\nvar emissive_default = `\\nuniform material_emissive: vec3f;\\nuniform material_emissiveIntensity: f32;\\nfn getEmission() {\\n\\tdEmission = uniform.material_emissive * uniform.material_emissiveIntensity;\\n\\t#ifdef STD_EMISSIVE_TEXTURE\\n\\tdEmission *= {STD_EMISSIVE_TEXTURE_DECODE}(textureSampleBias({STD_EMISSIVE_TEXTURE_NAME}, {STD_EMISSIVE_TEXTURE_NAME}Sampler, {STD_EMISSIVE_TEXTURE_UV}, uniform.textureBias)).{STD_EMISSIVE_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_EMISSIVE_VERTEX\\n\\tdEmission = dEmission * saturate3(vVertexColor.{STD_EMISSIVE_VERTEX_CHANNEL});\\n\\t#endif\\n}\\n`;\\n\\nvar encode_default = `\\nfn encodeLinear(source: vec3f) -> vec4f {\\n\\treturn vec4f(source, 1.0);\\n}\\nfn encodeGamma(source: vec3f) -> vec4f {\\n\\treturn vec4f(pow(source + vec3f(0.0000001), vec3f(1.0 / 2.2)), 1.0);\\n}\\nfn encodeRGBM(source: vec3f) -> vec4f {\\n\\tvar color: vec3f = pow(source, vec3f(0.5));\\n\\tcolor *= 1.0 / 8.0;\\n\\tvar a: f32 = saturate(max(max(color.r, color.g), max(color.b, 1.0 / 255.0)));\\n\\ta = ceil(a * 255.0) / 255.0;\\n\\tcolor /= a;\\n\\treturn vec4f(color, a);\\n}\\nfn encodeRGBP(source: vec3f) -> vec4f {\\n\\tvar gamma: vec3f = pow(source, vec3f(0.5));\\n\\tvar maxVal: f32 = min(8.0, max(1.0, max(gamma.x, max(gamma.y, gamma.z))));\\n\\tvar v: f32 = 1.0 - ((maxVal - 1.0) / 7.0);\\n\\tv = ceil(v * 255.0) / 255.0;\\n\\treturn vec4f(gamma / (-v * 7.0 + 8.0), v);\\n}\\nfn encodeRGBE(source: vec3f) -> vec4f {\\n\\tvar maxVal: f32 = max(source.x, max(source.y, source.z));\\n\\tif (maxVal < 1e-32) {\\n\\t\\treturn vec4f(0.0, 0.0, 0.0, 0.0);\\n\\t} else {\\n\\t\\tvar e: f32 = ceil(log2(maxVal));\\n\\t\\treturn vec4f(source / pow(2.0, e), (e + 128.0) / 255.0);\\n\\t}\\n}\\n`;\\n\\nvar end_default = `\\n\\tvar finalRgb: vec3f = combineColor(litArgs_albedo, litArgs_sheen_specularity, litArgs_clearcoat_specularity);\\n\\tfinalRgb = finalRgb + litArgs_emission;\\n\\tfinalRgb = addFog(finalRgb);\\n\\tfinalRgb = toneMap(finalRgb);\\n\\tfinalRgb = gammaCorrectOutput(finalRgb);\\n\\toutput.color = vec4f(finalRgb, output.color.a);\\n`;\\n\\nvar envAtlas_default = `\\n#ifndef _ENVATLAS_INCLUDED_\\n#define _ENVATLAS_INCLUDED_\\nconst atlasSize : f32 = 512.0;\\nconst seamSize : f32 = 1.0 / atlasSize;\\nfn mapUv(uv : vec2f, rect : vec4f) -> vec2f {\\n\\treturn vec2f(mix(rect.x + seamSize, rect.x + rect.z - seamSize, uv.x),\\n\\t\\t\\t\\t mix(rect.y + seamSize, rect.y + rect.w - seamSize, uv.y));\\n}\\nfn mapRoughnessUv(uv : vec2f, level : f32) -> vec2f {\\n\\tlet t : f32 = 1.0 / exp2(level);\\n\\treturn mapUv(uv, vec4f(0.0, 1.0 - t, t, t * 0.5));\\n}\\nfn mapShinyUv(uv : vec2f, level : f32) -> vec2f {\\n\\tlet t : f32 = 1.0 / exp2(level);\\n\\treturn mapUv(uv, vec4f(1.0 - t, 1.0 - t, t, t * 0.5));\\n}\\n#endif\\n`;\\n\\nvar envProc_default = `\\n#ifdef LIT_SKYBOX_INTENSITY\\n\\tuniform skyboxIntensity : f32;\\n#endif\\nfn processEnvironment(color : vec3f) -> vec3f {\\n\\t#ifdef LIT_SKYBOX_INTENSITY\\n\\t\\treturn color * uniform.skyboxIntensity;\\n\\t#else\\n\\t\\treturn color;\\n\\t#endif\\n}\\n`;\\n\\nvar falloffInvSquared_default = `\\nfn getFalloffWindow(lightRadius: f32, lightDir: vec3f) -> f32 {\\n\\tlet sqrDist: f32 = dot(lightDir, lightDir);\\n\\tlet invRadius: f32 = 1.0 / lightRadius;\\n\\treturn square(saturate(1.0 - square(sqrDist * square(invRadius))));\\n}\\nfn getFalloffInvSquared(lightRadius: f32, lightDir: vec3f) -> f32 {\\n\\tlet sqrDist: f32 = dot(lightDir, lightDir);\\n\\tvar falloff: f32 = 1.0 / (sqrDist + 1.0);\\n\\tlet invRadius: f32 = 1.0 / lightRadius;\\n\\tfalloff = falloff * 16.0;\\n\\tfalloff = falloff * square(saturate(1.0 - square(sqrDist * square(invRadius))));\\n\\treturn falloff;\\n}\\n`;\\n\\nvar falloffLinear_default = `\\nfn getFalloffLinear(lightRadius: f32, lightDir: vec3f) -> f32 {\\n\\tlet d: f32 = length(lightDir);\\n\\treturn max(((lightRadius - d) / lightRadius), 0.0);\\n}\\n`;\\n\\nvar float_as_uint_default = `\\n#ifndef FLOAT_AS_UINT\\n#define FLOAT_AS_UINT\\nfn float2uint(value: f32) -> vec4f {\\n\\tlet intBits = bitcast<u32>(value);\\n\\treturn vec4f(\\n\\t\\tf32((intBits >> 24u) & 0xffu),\\n\\t\\tf32((intBits >> 16u) & 0xffu),\\n\\t\\tf32((intBits >> 8u) & 0xffu),\\n\\t\\tf32(intBits & 0xffu)\\n\\t) / 255.0;\\n}\\nfn uint2float(value: vec4f) -> f32 {\\n\\tlet rgba_u32 = vec4<u32>(value * 255.0);\\n\\tlet intBits: u32 =\\n\\t\\t(rgba_u32.r << 24u) |\\n\\t\\t(rgba_u32.g << 16u) |\\n\\t\\t(rgba_u32.b << 8u)  |\\n\\t\\t rgba_u32.a;\\n\\treturn bitcast<f32>(intBits);\\n}\\nfn float2vec4(value: f32) -> vec4f {\\n\\t#if defined(CAPS_TEXTURE_FLOAT_RENDERABLE)\\n\\t\\treturn vec4f(value, 1.0, 1.0, 1.0);\\n\\t#else\\n\\t\\treturn float2uint(value);\\n\\t#endif\\n}\\n#endif\\n`;\\n\\nvar fog_default = `\\n#include \\\"fogMathPS\\\"\\nvar<private> dBlendModeFogFactor : f32 = 1.0;\\n#if (FOG != NONE)\\n\\tuniform fog_color : vec3f;\\n\\t\\n\\t#if (FOG == LINEAR)\\n\\t\\tuniform fog_start : f32;\\n\\t\\tuniform fog_end : f32;\\n\\t#else\\n\\t\\tuniform fog_density : f32;\\n\\t#endif\\n#endif\\n#ifdef VERTEXSHADER\\n\\tfn getFogFactor(depth: f32) -> f32 {\\n#else\\n\\tfn getFogFactor() -> f32 {\\n\\t\\tlet depth = pcPosition.z / pcPosition.w;\\n#endif\\n\\t#if (FOG == LINEAR)\\n\\t\\treturn evaluateFogFactorLinear(depth, uniform.fog_start, uniform.fog_end);\\n\\t#elif (FOG == EXP)\\n\\t\\treturn evaluateFogFactorExp(depth, uniform.fog_density);\\n\\t#elif (FOG == EXP2)\\n\\t\\treturn evaluateFogFactorExp2(depth, uniform.fog_density);\\n\\t#else\\n\\t\\treturn 1.0;\\n\\t#endif\\n}\\n#ifdef VERTEXSHADER\\n\\tfn addFog(color: vec3f, depth: f32) -> vec3f {\\n\\t\\t#if (FOG != NONE)\\n\\t\\t\\treturn mix(uniform.fog_color * dBlendModeFogFactor, color, getFogFactor(depth));\\n\\t\\t#else\\n\\t\\t\\treturn color;\\n\\t\\t#endif\\n\\t}\\n#else\\n\\tfn addFog(color: vec3f) -> vec3f {\\n\\t\\t#if (FOG != NONE)\\n\\t\\t\\treturn mix(uniform.fog_color * dBlendModeFogFactor, color, getFogFactor());\\n\\t\\t#else\\n\\t\\t\\treturn color;\\n\\t\\t#endif\\n\\t}\\n#endif\\n`;\\n\\nvar fogMath_default = `\\nfn evaluateFogFactorLinear(depth: f32, fogStart: f32, fogEnd: f32) -> f32 {\\n\\treturn clamp((fogEnd - depth) / (fogEnd - fogStart), 0.0, 1.0);\\n}\\nfn evaluateFogFactorExp(depth: f32, fogDensity: f32) -> f32 {\\n\\treturn clamp(exp(-depth * fogDensity), 0.0, 1.0);\\n}\\nfn evaluateFogFactorExp2(depth: f32, fogDensity: f32) -> f32 {\\n\\treturn clamp(exp(-depth * depth * fogDensity * fogDensity), 0.0, 1.0);\\n}\\n`;\\n\\nvar fresnelSchlick_default = `\\nfn pow5(x: f32) -> f32 {\\n\\tlet x2: f32 = x * x;\\n\\treturn x2 * x2 * x;\\n}\\nfn getFresnel(\\n\\t\\tcosTheta: f32,\\n\\t\\tgloss: f32,\\n\\t\\tspecularity: vec3f\\n\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t, iridescenceFresnel: vec3f,\\n\\t\\tiridescenceIntensity: f32\\n\\t#endif\\n) -> vec3f {\\n\\tlet fresnel: f32 = pow5(1.0 - saturate(cosTheta));\\n\\tlet glossSq: f32 = gloss * gloss;\\n\\tlet specIntensity: f32 = max(specularity.r, max(specularity.g, specularity.b));\\n\\tlet ret: vec3f = specularity + (max(vec3f(glossSq * specIntensity), specularity) - specularity) * fresnel;\\n\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\treturn mix(ret, iridescenceFresnel, iridescenceIntensity);\\n\\t#else\\n\\t\\treturn ret;\\n\\t#endif\\n}\\nfn getFresnelCC(cosTheta: f32) -> f32 {\\n\\tlet fresnel: f32 = pow5(1.0 - saturate(cosTheta));\\n\\treturn 0.04 + (1.0 - 0.04) * fresnel;\\n}`;\\n\\nvar fullscreenQuad_default = `\\nattribute vertex_position: vec2f;\\nvarying vUv0: vec2f;\\n@vertex\\nfn vertexMain(input: VertexInput) -> VertexOutput {\\n\\tvar output: VertexOutput;\\n\\toutput.position = vec4f(input.vertex_position, 0.5, 1.0);\\n\\toutput.vUv0 = input.vertex_position.xy * 0.5 + vec2f(0.5);\\n\\treturn output;\\n}\\n`;\\n\\nvar gamma_default = `\\n#include \\\"decodePS\\\"\\n#if (GAMMA == SRGB)\\n\\tfn gammaCorrectInput(color: f32) -> f32 {\\n\\t\\treturn decodeGammaFloat(color);\\n\\t}\\n\\tfn gammaCorrectInputVec3(color: vec3f) -> vec3f {\\n\\t\\treturn decodeGamma3(color);\\n\\t}\\n\\tfn gammaCorrectInputVec4(color: vec4f) -> vec4f {\\n\\t\\treturn vec4f(decodeGamma3(color.xyz), color.w);\\n\\t}\\n\\tfn gammaCorrectOutput(color: vec3f) -> vec3f {\\n\\t\\treturn pow(color + 0.0000001, vec3f(1.0 / 2.2));\\n\\t}\\n#else\\n\\tfn gammaCorrectInput(color: f32) -> f32 {\\n\\t\\treturn color;\\n\\t}\\n\\tfn gammaCorrectInputVec3(color: vec3f) -> vec3f {\\n\\t\\treturn color;\\n\\t}\\n\\tfn gammaCorrectInputVec4(color: vec4f) -> vec4f {\\n\\t\\treturn color;\\n\\t}\\n\\tfn gammaCorrectOutput(color: vec3f) -> vec3f {\\n\\t\\treturn color;\\n\\t}\\n#endif\\n`;\\n\\nvar gloss_default = `\\n#ifdef STD_GLOSS_CONSTANT\\n\\tuniform material_gloss: f32;\\n#endif\\nfn getGlossiness() {\\n\\tdGlossiness = 1.0;\\n\\t#ifdef STD_GLOSS_CONSTANT\\n\\tdGlossiness = dGlossiness * uniform.material_gloss;\\n\\t#endif\\n\\t#ifdef STD_GLOSS_TEXTURE\\n\\tdGlossiness = dGlossiness * textureSampleBias({STD_GLOSS_TEXTURE_NAME}, {STD_GLOSS_TEXTURE_NAME}Sampler, {STD_GLOSS_TEXTURE_UV}, uniform.textureBias).{STD_GLOSS_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_GLOSS_VERTEX\\n\\tdGlossiness = dGlossiness * saturate(vVertexColor.{STD_GLOSS_VERTEX_CHANNEL});\\n\\t#endif\\n\\t#ifdef STD_GLOSS_INVERT\\n\\tdGlossiness = 1.0 - dGlossiness;\\n\\t#endif\\n\\tdGlossiness = dGlossiness + 0.0000001;\\n}\\n`;\\n\\nvar quad_default = `\\n\\tattribute aPosition: vec2f;\\n\\tvarying uv0: vec2f;\\n\\t@vertex fn vertexMain(input: VertexInput) -> VertexOutput {\\n\\t\\tvar output: VertexOutput;\\n\\t\\toutput.position = vec4f(input.aPosition, 0.0, 1.0);\\n\\t\\toutput.uv0 = getImageEffectUV((input.aPosition + 1.0) * 0.5);\\n\\t\\treturn output;\\n\\t}\\n`;\\n\\nvar indirect_core_default = `\\nstruct DrawIndexedIndirectArgs {\\n\\tindexCount: u32,\\n\\tinstanceCount: u32,\\n\\tfirstIndex: u32,\\n\\tbaseVertex: i32,\\n\\tfirstInstance: u32\\n};\\nstruct DrawIndirectArgs {\\n\\tvertexCount: u32,\\n\\tinstanceCount: u32,\\n\\tfirstVertex: u32,\\n\\tfirstInstance: u32,\\n\\t_pad: u32\\n};\\n`;\\n\\nvar immediateLine_default$1 = `\\n\\t#include \\\"gammaPS\\\"\\n\\tvarying color: vec4f;\\n\\t@fragment\\n\\tfn fragmentMain(input : FragmentInput) -> FragmentOutput {\\n\\t\\tvar output: FragmentOutput;\\n\\t\\toutput.color = vec4f(gammaCorrectOutput(decodeGamma3(input.color.rgb)), input.color.a);\\n\\t\\treturn output;\\n\\t}\\n`;\\n\\nvar immediateLine_default = `\\n\\tattribute vertex_position: vec4f;\\n\\tattribute vertex_color: vec4f;\\n\\tuniform matrix_model: mat4x4f;\\n\\tuniform matrix_viewProjection: mat4x4f;\\n\\tvarying color: vec4f;\\n\\t@vertex\\n\\tfn vertexMain(input : VertexInput) -> VertexOutput {\\n\\t\\tvar output : VertexOutput;\\n\\t\\toutput.color = input.vertex_color;\\n\\t\\toutput.position = uniform.matrix_viewProjection * uniform.matrix_model * input.vertex_position;\\n\\t\\treturn output;\\n\\t}\\n`;\\n\\nvar iridescenceDiffraction_default = `\\nuniform material_iridescenceRefractionIndex: f32;\\nfn iridescence_iorToFresnelScalar(transmittedIor: f32, incidentIor: f32) -> f32 {\\n\\treturn pow((transmittedIor - incidentIor) / (transmittedIor + incidentIor), 2.0);\\n}\\nfn iridescence_iorToFresnelVec3(transmittedIor: vec3f, incidentIor: f32) -> vec3f {\\n\\treturn pow((transmittedIor - vec3f(incidentIor)) / (transmittedIor + vec3f(incidentIor)), vec3f(2.0));\\n}\\nfn iridescence_fresnelToIor(f0: vec3f) -> vec3f {\\n\\tlet sqrtF0: vec3f = sqrt(f0);\\n\\treturn (vec3f(1.0) + sqrtF0) / (vec3f(1.0) - sqrtF0);\\n}\\nconst XYZ_TO_REC709: mat3x3f = mat3x3f(\\n\\tvec3f(3.2404542, -1.5371385, -0.4985314),\\n\\tvec3f(-0.9692660,  1.8760108,  0.0415560),\\n\\tvec3f(0.0556434, -0.2040259,  1.0572252)\\n);\\nfn iridescence_sensitivity(opd: f32, shift: vec3f) -> vec3f {\\n\\tlet PI: f32 = 3.141592653589793;\\n\\tlet phase: f32 = 2.0 * PI * opd * 1.0e-9;\\n\\tconst val: vec3f = vec3f(5.4856e-13, 4.4201e-13, 5.2481e-13);\\n\\tconst pos: vec3f = vec3f(1.6810e+06, 1.7953e+06, 2.2084e+06);\\n\\tconst var_: vec3f = vec3f(4.3278e+09, 9.3046e+09, 6.6121e+09);\\n\\tvar xyz: vec3f = val * sqrt(2.0 * PI * var_) * cos(pos * phase + shift) * exp(-pow(phase, 2.0) * var_);\\n\\txyz.x = xyz.x + 9.7470e-14 * sqrt(2.0 * PI * 4.5282e+09) * cos(2.2399e+06 * phase + shift[0]) * exp(-4.5282e+09 * pow(phase, 2.0));\\n\\txyz = xyz / vec3f(1.0685e-07);\\n\\treturn XYZ_TO_REC709 * xyz;\\n}\\nfn iridescence_fresnelScalar(cosTheta: f32, f0: f32) -> f32 {\\n\\tlet x: f32 = clamp(1.0 - cosTheta, 0.0, 1.0);\\n\\tlet x2: f32 = x * x;\\n\\tlet x5: f32 = x * x2 * x2;\\n\\treturn f0 + (1.0 - f0) * x5;\\n}\\nfn iridescence_fresnelVec3(cosTheta: f32, f0: vec3f) -> vec3f {\\n\\tlet x: f32 = clamp(1.0 - cosTheta, 0.0, 1.0);\\n\\tlet x2: f32 = x * x;\\n\\tlet x5: f32 = x * x2 * x2;\\n\\treturn f0 + (vec3f(1.0) - f0) * x5;\\n}\\nfn calcIridescence(outsideIor: f32, cosTheta: f32, base_f0: vec3f, iridescenceThickness: f32) -> vec3f {\\n\\tlet PI: f32 = 3.141592653589793;\\n\\tlet iridescenceIor: f32 = mix(outsideIor, uniform.material_iridescenceRefractionIndex, smoothstep(0.0, 0.03, iridescenceThickness));\\n\\tlet sinTheta2Sq: f32 = pow(outsideIor / iridescenceIor, 2.0) * (1.0 - pow(cosTheta, 2.0));\\n\\tlet cosTheta2Sq: f32 = 1.0 - sinTheta2Sq;\\n\\tif (cosTheta2Sq < 0.0) {\\n\\t\\treturn vec3f(1.0);\\n\\t}\\n\\tlet cosTheta2: f32 = sqrt(cosTheta2Sq);\\n\\tlet r0: f32 = iridescence_iorToFresnelScalar(iridescenceIor, outsideIor);\\n\\tlet r12: f32 = iridescence_fresnelScalar(cosTheta, r0);\\n\\tlet r21: f32 = r12;\\n\\tlet t121: f32 = 1.0 - r12;\\n\\tlet phi12: f32 = select(0.0, PI, iridescenceIor < outsideIor);\\n\\tlet phi21: f32 = PI - phi12;\\n\\tlet baseIor: vec3f = iridescence_fresnelToIor(base_f0 + vec3f(0.0001));\\n\\tlet r1: vec3f = iridescence_iorToFresnelVec3(baseIor, iridescenceIor);\\n\\tlet r23: vec3f = iridescence_fresnelVec3(cosTheta2, r1);\\n\\tlet phi23: vec3f = select(vec3f(0.0), vec3f(PI), baseIor < vec3f(iridescenceIor));\\n\\tlet opd: f32 = 2.0 * iridescenceIor * iridescenceThickness * cosTheta2;\\n\\tlet phi: vec3f = vec3f(phi21) + phi23;\\n\\tlet r123Sq: vec3f = clamp(vec3f(r12) * r23, vec3f(1e-5), vec3f(0.9999));\\n\\tlet r123: vec3f = sqrt(r123Sq);\\n\\tlet rs: vec3f = pow(vec3f(t121), vec3f(2.0)) * r23 / (vec3f(1.0) - r123Sq);\\n\\tlet c0: vec3f = vec3f(r12) + rs;\\n\\tvar i_irid: vec3f = c0;\\n\\tvar cm: vec3f = rs - vec3f(t121);\\n\\tcm = cm * r123;\\n\\tlet sm1: vec3f = 2.0 * iridescence_sensitivity(1.0 * opd, 1.0 * phi);\\n\\ti_irid = i_irid + cm * sm1;\\n\\tcm = cm * r123;\\n\\tlet sm2: vec3f = 2.0 * iridescence_sensitivity(2.0 * opd, 2.0 * phi);\\n\\ti_irid = i_irid + cm * sm2;\\n\\treturn max(i_irid, vec3f(0.0));\\n}\\nfn getIridescenceDiffraction(cosTheta: f32, specularity: vec3f, iridescenceThickness: f32) -> vec3f {\\n\\treturn calcIridescence(1.0, cosTheta, specularity, iridescenceThickness);\\n}\\n`;\\n\\nvar iridescence_default = `\\n#ifdef STD_IRIDESCENCE_CONSTANT\\n\\tuniform material_iridescence: f32;\\n#endif\\nfn getIridescence() {\\n\\tvar iridescence = 1.0;\\n\\t#ifdef STD_IRIDESCENCE_CONSTANT\\n\\tiridescence = iridescence * uniform.material_iridescence;\\n\\t#endif\\n\\t#ifdef STD_IRIDESCENCE_TEXTURE\\n\\tiridescence = iridescence * textureSampleBias({STD_IRIDESCENCE_TEXTURE_NAME}, {STD_IRIDESCENCE_TEXTURE_NAME}Sampler, {STD_IRIDESCENCE_TEXTURE_UV}, uniform.textureBias).{STD_IRIDESCENCE_TEXTURE_CHANNEL};\\n\\t#endif\\n\\tdIridescence = iridescence; \\n}\\n`;\\n\\nvar iridescenceThickness_default = `\\nuniform material_iridescenceThicknessMax: f32;\\n#ifdef STD_IRIDESCENCETHICKNESS_TEXTURE\\n\\tuniform material_iridescenceThicknessMin: f32;\\n#endif\\nfn getIridescenceThickness() {\\n\\t#ifdef STD_IRIDESCENCETHICKNESS_TEXTURE\\n\\t\\tvar blend: f32 = textureSampleBias({STD_IRIDESCENCETHICKNESS_TEXTURE_NAME}, {STD_IRIDESCENCETHICKNESS_TEXTURE_NAME}Sampler, {STD_IRIDESCENCETHICKNESS_TEXTURE_UV}, uniform.textureBias).{STD_IRIDESCENCETHICKNESS_TEXTURE_CHANNEL};\\n\\t\\tvar iridescenceThickness: f32 = mix(uniform.material_iridescenceThicknessMin, uniform.material_iridescenceThicknessMax, blend);\\n\\t#else\\n\\t\\tvar iridescenceThickness: f32 = uniform.material_iridescenceThicknessMax;\\n\\t#endif\\n\\tdIridescenceThickness = iridescenceThickness; \\n}\\n`;\\n\\nvar ior_default = `\\n#ifdef STD_IOR_CONSTANT\\n\\tuniform material_refractionIndex: f32;\\n#endif\\nfn getIor() {\\n#ifdef STD_IOR_CONSTANT\\n\\tdIor = uniform.material_refractionIndex;\\n#else\\n\\tdIor = 1.0 / 1.5;\\n#endif\\n}\\n`;\\n\\nvar lightDeclaration_default = `\\n#if defined(LIGHT{i})\\n\\tuniform light{i}_color: vec3f;\\n\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\tuniform light{i}_direction: vec3f;\\n\\t#else\\n\\t\\t#define LIT_CODE_LIGHTS_POINT\\n\\t\\tuniform light{i}_position: vec3f;\\n\\t\\tuniform light{i}_radius: f32;\\n\\t\\t#if LIGHT{i}TYPE == SPOT\\n\\t\\t\\t#define LIT_CODE_LIGHTS_SPOT\\n\\t\\t\\tuniform light{i}_direction: vec3f;\\n\\t\\t\\tuniform light{i}_innerConeAngle: f32;\\n\\t\\t\\tuniform light{i}_outerConeAngle: f32;\\n\\t\\t#endif\\n\\t#endif\\n\\t#if LIGHT{i}SHAPE != PUNCTUAL\\n\\t\\t#define LIT_CODE_FALLOFF_SQUARED\\n\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\tuniform light{i}_position: vec3f;\\n\\t\\t#endif\\n\\t\\tuniform light{i}_halfWidth: vec3f;\\n\\t\\tuniform light{i}_halfHeight: vec3f;\\n\\t#else\\n\\t\\t#if LIGHT{i}FALLOFF == LINEAR\\n\\t\\t\\t#define LIT_CODE_FALLOFF_LINEAR\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}FALLOFF == INVERSESQUARED\\n\\t\\t\\t#define LIT_CODE_FALLOFF_SQUARED\\n\\t\\t#endif\\n\\t#endif\\n\\t#if defined(LIGHT{i}CASTSHADOW)\\n\\t\\t#if LIGHT{i}TYPE != OMNI\\n\\t\\t\\tuniform light{i}_shadowMatrix: mat4x4f;\\n\\t\\t#endif\\n\\t\\tuniform light{i}_shadowIntensity: f32;\\n\\t\\tuniform light{i}_shadowParams: vec4f;\\n\\t\\t#if LIGHT{i}SHADOWTYPE == PCSS_32F\\n\\t\\t\\tuniform light{i}_shadowSearchArea: f32;\\n\\t\\t\\tuniform light{i}_cameraParams: vec4f;\\n\\t\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\t\\tuniform light{i}_softShadowParams: vec4f;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\tuniform light{i}_shadowMatrixPalette: array<mat4x4f, 4>;\\n\\t\\t\\tuniform light{i}_shadowCascadeDistances: vec4f;\\n\\t\\t\\tuniform light{i}_shadowCascadeCount: i32;\\n\\t\\t\\tuniform light{i}_shadowCascadeBlend: f32;\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}TYPE == OMNI\\n\\t\\t\\tNOT SUPPORTED\\n\\t\\t#else\\n\\t\\t\\t#if defined(LIGHT{i}SHADOW_PCF)\\n\\t\\t\\t\\tvar light{i}_shadowMap: texture_depth_2d;\\n\\t\\t\\t\\tvar light{i}_shadowMapSampler: sampler_comparison;\\n\\t\\t\\t#else\\n\\t\\t\\t\\tvar light{i}_shadowMap: texture_2d<f32>;\\n\\t\\t\\t\\tvar light{i}_shadowMapSampler: sampler;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t#endif\\n\\t#if defined(LIGHT{i}COOKIE)\\n\\t\\t#define LIT_CODE_COOKIE\\n\\t\\t#if LIGHT{i}TYPE == OMNI\\n\\t\\t\\tNOT SUPPORTED\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}TYPE == SPOT\\n\\t\\t\\tNOT SUPPORTED\\n\\t\\t#endif\\n\\t#endif\\n#endif\\n`;\\n\\nvar lightDiffuseLambert_default = `\\nfn getLightDiffuse(worldNormal: vec3f, viewDir: vec3f, lightDirNorm: vec3f) -> f32 {\\n\\treturn max(dot(worldNormal, -lightDirNorm), 0.0);\\n}\\n`;\\n\\nvar lightDirPoint_default = `\\nfn evalOmniLight(lightPosW: vec3f) -> vec3f {\\n\\treturn vPositionW - lightPosW;\\n}\\n`;\\n\\nvar lightEvaluation_default = `\\n#if defined(LIGHT{i})\\n\\tevaluateLight{i}(\\n\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\tiridescenceFresnel\\n\\t\\t#endif\\n\\t);\\n#endif\\n`;\\n\\nvar lightFunctionLight_default = `\\n#if defined(LIGHT{i})\\nfn evaluateLight{i}(\\n\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\tiridescenceFresnel: vec3f\\n\\t#endif\\n) {\\n\\tvar lightColor: vec3f = uniform.light{i}_color;\\n\\t#if LIGHT{i}TYPE == DIRECTIONAL && !defined(LIT_SHADOW_CATCHER)\\n\\t\\tif (all(lightColor == vec3f(0.0, 0.0, 0.0))) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t#endif\\n\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\tdLightDirNormW = uniform.light{i}_direction;\\n\\t\\tdAtten = 1.0;\\n\\t#else\\n\\t\\tvar lightDirW: vec3f = evalOmniLight(uniform.light{i}_position);\\n\\t\\tdLightDirNormW = normalize(lightDirW);\\n\\t\\t#if defined(LIGHT{i}COOKIE)\\n\\t\\t\\t#if LIGHT{i}TYPE == SPOT\\n\\t\\t\\t\\t#ifdef LIGHT{i}COOKIE_FALLOFF\\n\\t\\t\\t\\t\\t#ifdef LIGHT{i}COOKIE_TRANSFORM\\n\\t\\t\\t\\t\\t\\tvar cookieAttenuation: vec3f = getCookie2DXform(uniform.light{i}_cookie, uniform.light{i}_shadowMatrix, uniform.light{i}_cookieIntensity, uniform.light{i}_cookieMatrix, uniform.light{i}_cookieOffset).{LIGHT{i}COOKIE_CHANNEL};\\n\\t\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\t\\tvar cookieAttenuation: vec3f = getCookie2D(uniform.light{i}_cookie, uniform.light{i}_shadowMatrix, uniform.light{i}_cookieIntensity).{LIGHT{i}COOKIE_CHANNEL};\\n\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\t#ifdef LIGHT{i}COOKIE_TRANSFORM\\n\\t\\t\\t\\t\\t\\tvar cookieAttenuation: vec3f = getCookie2DClipXform(uniform.light{i}_cookie, uniform.light{i}_shadowMatrix, uniform.light{i}_cookieIntensity, uniform.light{i}_cookieMatrix, uniform.light{i}_cookieOffset).{LIGHT{i}COOKIE_CHANNEL};\\n\\t\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\t\\tvar cookieAttenuation: vec3f = getCookie2DClip(uniform.light{i}_cookie, uniform.light{i}_shadowMatrix, uniform.light{i}_cookieIntensity).{LIGHT{i}COOKIE_CHANNEL};\\n\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}TYPE == OMNI\\n\\t\\t\\t\\tvar cookieAttenuation: vec3f = getCookieCube(uniform.light{i}_cookie, uniform.light{i}_shadowMatrix, uniform.light{i}_cookieIntensity).{LIGHT{i}COOKIE_CHANNEL};\\n\\t\\t\\t#endif\\n\\t\\t\\tlightColor = lightColor * cookieAttenuation;\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}SHAPE == PUNCTUAL\\n\\t\\t\\t#if LIGHT{i}FALLOFF == LINEAR\\n\\t\\t\\t\\tdAtten = getFalloffLinear(uniform.light{i}_radius, lightDirW);\\n\\t\\t\\t#else\\n\\t\\t\\t\\tdAtten = getFalloffInvSquared(uniform.light{i}_radius, lightDirW);\\n\\t\\t\\t#endif\\n\\t\\t#else\\n\\t\\t\\tdAtten = getFalloffWindow(uniform.light{i}_radius, lightDirW);\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}TYPE == SPOT\\n\\t\\t\\t#if !defined(LIGHT{i}COOKIE) || defined(LIGHT{i}COOKIE_FALLOFF)\\n\\t\\t\\t\\tdAtten = dAtten * getSpotEffect(uniform.light{i}_direction, uniform.light{i}_innerConeAngle, uniform.light{i}_outerConeAngle, dLightDirNormW);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t#endif\\n\\tif (dAtten < 0.00001) {\\n\\t\\treturn;\\n\\t}\\n\\t#if LIGHT{i}SHAPE != PUNCTUAL\\n\\t\\t#if LIGHT{i}SHAPE == RECT\\n\\t\\t\\tcalcRectLightValues(uniform.light{i}_position, uniform.light{i}_halfWidth, uniform.light{i}_halfHeight);\\n\\t\\t#elif LIGHT{i}SHAPE == DISK\\n\\t\\t\\tcalcDiskLightValues(uniform.light{i}_position, uniform.light{i}_halfWidth, uniform.light{i}_halfHeight);\\n\\t\\t#elif LIGHT{i}SHAPE == SPHERE\\n\\t\\t\\tcalcSphereLightValues(uniform.light{i}_position, uniform.light{i}_halfWidth, uniform.light{i}_halfHeight);\\n\\t\\t#endif\\n\\t#endif\\n\\t#if LIGHT{i}SHAPE != PUNCTUAL\\n\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\tvar attenDiffuse: f32 = getLightDiffuse(litArgs_worldNormal, dViewDirW, dLightDirNormW);\\n\\t\\t#else\\n\\t\\t\\t#if LIGHT{i}SHAPE == RECT\\n\\t\\t\\t\\tvar attenDiffuse: f32 = getRectLightDiffuse(litArgs_worldNormal, dViewDirW, lightDirW, dLightDirNormW) * 16.0;\\n\\t\\t\\t#elif LIGHT{i}SHAPE == DISK\\n\\t\\t\\t\\tvar attenDiffuse: f32 = getDiskLightDiffuse(litArgs_worldNormal, dViewDirW, lightDirW, dLightDirNormW) * 16.0;\\n\\t\\t\\t#elif LIGHT{i}SHAPE == SPHERE\\n\\t\\t\\t\\tvar attenDiffuse: f32 = getSphereLightDiffuse(litArgs_worldNormal, dViewDirW, lightDirW, dLightDirNormW) * 16.0;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t#else\\n\\t\\tdAtten = dAtten * getLightDiffuse(litArgs_worldNormal, vec3(0.0), dLightDirNormW);\\n\\t#endif\\n\\t#ifdef LIGHT{i}CASTSHADOW\\n\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\tvar shadow: f32 = getShadow{i}(vec3(0.0));\\n\\t\\t#else\\n\\t\\t\\tvar shadow: f32 = getShadow{i}(lightDirW);\\n\\t\\t#endif\\n\\t\\tshadow = mix(1.0, shadow, uniform.light{i}_shadowIntensity);\\n\\t\\tdAtten = dAtten * shadow;\\n\\t\\t#if defined(LIT_SHADOW_CATCHER) && LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\tdShadowCatcher = dShadowCatcher * shadow;\\n\\t\\t#endif\\t\\t\\t\\n\\t#endif\\n\\t#if LIGHT{i}SHAPE != PUNCTUAL\\n\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\tdDiffuseLight = dDiffuseLight + (((attenDiffuse * dAtten) * lightColor) * (1.0 - dLTCSpecFres));\\n\\t\\t#else\\n\\t\\t\\tdDiffuseLight = dDiffuseLight + ((attenDiffuse * dAtten) * lightColor);\\n\\t\\t#endif\\t\\t\\t\\t\\t\\t\\n\\t#else\\n\\t\\t#if defined(AREA_LIGHTS) && defined(LIT_SPECULAR)\\n\\t\\t\\tdDiffuseLight = dDiffuseLight + ((dAtten * lightColor) * (1.0 - litArgs_specularity));\\n\\t\\t#else\\n\\t\\t\\tdDiffuseLight = dDiffuseLight + (dAtten * lightColor);\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef LIGHT{i}AFFECT_SPECULARITY\\n\\t\\t#if LIGHT{i}SHAPE != PUNCTUAL\\n\\t\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t\\t#if LIGHT{i}SHAPE == RECT\\n\\t\\t\\t\\t\\tccSpecularLight = ccSpecularLight + (ccLTCSpecFres * getRectLightSpecular(litArgs_clearcoat_worldNormal, dViewDirW) * dAtten * lightColor);\\n\\t\\t\\t\\t#elif LIGHT{i}SHAPE == DISK\\n\\t\\t\\t\\t\\tccSpecularLight = ccSpecularLight + (ccLTCSpecFres * getDiskLightSpecular(litArgs_clearcoat_worldNormal, dViewDirW) * dAtten * lightColor);\\n\\t\\t\\t\\t#elif LIGHT{i}SHAPE == SPHERE\\n\\t\\t\\t\\t\\tccSpecularLight = ccSpecularLight + (ccLTCSpecFres * getSphereLightSpecular(litArgs_clearcoat_worldNormal, dViewDirW) * dAtten * lightColor);\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\t\\t#if LIGHT{i}SHAPE == RECT\\n\\t\\t\\t\\t\\tdSpecularLight = dSpecularLight + (dLTCSpecFres * getRectLightSpecular(litArgs_worldNormal, dViewDirW) * dAtten * lightColor);\\n\\t\\t\\t\\t#elif LIGHT{i}SHAPE == DISK\\n\\t\\t\\t\\t\\tdSpecularLight = dSpecularLight + (dLTCSpecFres * getDiskLightSpecular(litArgs_worldNormal, dViewDirW) * dAtten * lightColor);\\n\\t\\t\\t\\t#elif LIGHT{i}SHAPE == SPHERE\\n\\t\\t\\t\\t\\tdSpecularLight = dSpecularLight + (dLTCSpecFres * getSphereLightSpecular(litArgs_worldNormal, dViewDirW) * dAtten * lightColor);\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t#else\\n\\t\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL && LIT_FRESNEL_MODEL != NONE\\n\\t\\t\\t\\t#define LIGHT{i}FRESNEL\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\t\\tvar halfDirW: vec3f = normalize(-dLightDirNormW + dViewDirW);\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t\\tvar lightspecularCC: vec3f = getLightSpecular(halfDirW, ccReflDirW, litArgs_clearcoat_worldNormal, dViewDirW, dLightDirNormW, litArgs_clearcoat_gloss, dTBN) * dAtten * lightColor;\\n\\t\\t\\t\\t#ifdef LIGHT{i}FRESNEL\\n\\t\\t\\t\\t\\tlightspecularCC = lightspecularCC * getFresnelCC(dot(dViewDirW, halfDirW));\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\tccSpecularLight = ccSpecularLight + lightspecularCC;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SHEEN\\n\\t\\t\\t\\tsSpecularLight = sSpecularLight + (getLightSpecularSheen(halfDirW, litArgs_worldNormal, dViewDirW, dLightDirNormW, litArgs_sheen_gloss) * dAtten * lightColor);\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\t\\tvar lightSpecular: vec3f = getLightSpecular(halfDirW, dReflDirW, litArgs_worldNormal, dViewDirW, dLightDirNormW, litArgs_gloss, dTBN) * dAtten * lightColor;\\n\\t\\t\\t\\t#ifdef LIGHT{i}FRESNEL\\n\\t\\t\\t\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t\\t\\t\\tlightSpecular = lightSpecular * getFresnel(dot(dViewDirW, halfDirW), litArgs_gloss, litArgs_specularity, iridescenceFresnel, litArgs_iridescence_intensity);\\n\\t\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\t\\tlightSpecular = lightSpecular * getFresnel(dot(dViewDirW, halfDirW), litArgs_gloss, litArgs_specularity);\\n\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\tlightSpecular = lightSpecular * litArgs_specularity;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\n\\t\\t\\t\\tdSpecularLight = dSpecularLight + lightSpecular;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t#endif\\n}\\n#endif\\n`;\\n\\nvar lightFunctionShadow_default = `\\n#ifdef LIGHT{i}CASTSHADOW\\n\\t#ifdef LIGHT{i}_SHADOW_SAMPLE_POINT\\n\\t\\tfn getShadowSampleCoordOmni{i}(shadowParams: vec4f, worldPosition: vec3f, lightPos: vec3f, lightDir: ptr<function, vec3f>, lightDirNorm: vec3f, normal: vec3f) -> vec3f {\\n\\t\\t\\t#ifdef LIGHT{i}_SHADOW_SAMPLE_NORMAL_OFFSET\\n\\t\\t\\t\\tlet distScale: f32 = length(*lightDir);\\n\\t\\t\\t\\tvar surfacePosition = worldPosition + normal * shadowParams.y * clamp(1.0 - dot(normal, -lightDirNorm), 0.0, 1.0) * distScale;\\n\\t\\t\\t\\t*lightDir = surfacePosition - lightPos;\\n\\t\\t\\t#endif\\n\\t\\t\\treturn *lightDir;\\n\\t\\t}\\n\\t#endif\\n\\t#ifndef LIGHT{i}_SHADOW_SAMPLE_POINT\\n\\t\\tfn getShadowSampleCoord{i}(shadowTransform: mat4x4f, shadowParams: vec4f, worldPosition: vec3f, lightPos: vec3f, lightDir: ptr<function, vec3f>, lightDirNorm: vec3f, normal: vec3f) -> vec3f {\\n\\t\\t\\tvar surfacePosition = worldPosition;\\n\\t\\t\\t#ifdef LIGHT{i}_SHADOW_SAMPLE_SOURCE_ZBUFFER\\n\\t\\t\\t\\t#ifdef LIGHT{i}_SHADOW_SAMPLE_NORMAL_OFFSET\\n\\t\\t\\t\\t\\tsurfacePosition = surfacePosition + normal * shadowParams.y;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#else\\n\\t\\t\\t\\t#ifdef LIGHT{i}_SHADOW_SAMPLE_NORMAL_OFFSET\\n\\t\\t\\t\\t\\t#ifdef LIGHT{i}_SHADOW_SAMPLE_ORTHO\\n\\t\\t\\t\\t\\t\\tvar distScale: f32 = 1.0;\\n\\t\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\t\\tvar distScale: f32 = abs(dot(vPositionW - lightPos, lightDirNorm));\\n\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\tsurfacePosition = surfacePosition + normal * shadowParams.y * clamp(1.0 - dot(normal, -lightDirNorm), 0.0, 1.0) * distScale;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\tvar positionInShadowSpace: vec4f = shadowTransform * vec4f(surfacePosition, 1.0);\\n\\t\\t\\t#ifdef LIGHT{i}_SHADOW_SAMPLE_ORTHO\\n\\t\\t\\t\\tpositionInShadowSpace.z = saturate(positionInShadowSpace.z) - 0.0001;\\n\\t\\t\\t#else\\n\\t\\t\\t\\t#ifdef LIGHT{i}_SHADOW_SAMPLE_SOURCE_ZBUFFER\\n\\t\\t\\t\\t\\tpositionInShadowSpace.xyz = positionInShadowSpace.xyz / positionInShadowSpace.w;\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\tpositionInShadowSpace.xy = positionInShadowSpace.xy / positionInShadowSpace.w;\\n\\t\\t\\t\\t\\tpositionInShadowSpace.z = length(*lightDir) * shadowParams.w;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\treturn positionInShadowSpace.xyz;\\n\\t\\t}\\n\\t#endif\\n\\tfn getShadow{i}(lightDirW_in: vec3f) -> f32 {\\n\\t\\tvar lightDirArg = lightDirW_in;\\n\\t\\t#if LIGHT{i}TYPE == OMNI\\n\\t\\t\\tvar shadowCoord: vec3f = getShadowSampleCoordOmni{i}(uniform.light{i}_shadowParams, vPositionW, uniform.light{i}_position, &lightDirArg, dLightDirNormW, dVertexNormalW);\\n\\t\\t#else\\n\\t\\t\\t#ifdef LIGHT{i}_SHADOW_CASCADES\\n\\t\\t\\t\\tvar cascadeIndex: i32 = getShadowCascadeIndex(uniform.light{i}_shadowCascadeDistances, uniform.light{i}_shadowCascadeCount);\\n\\t\\t\\t\\t#ifdef LIGHT{i}_SHADOW_CASCADE_BLEND\\n\\t\\t\\t\\t\\tcascadeIndex = ditherShadowCascadeIndex(cascadeIndex, uniform.light{i}_shadowCascadeDistances, uniform.light{i}_shadowCascadeCount, uniform.light{i}_shadowCascadeBlend);\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\tvar shadowMatrix: mat4x4f = uniform.light{i}_shadowMatrixPalette[cascadeIndex];\\n\\t\\t\\t#else\\n\\t\\t\\t\\tvar shadowMatrix: mat4x4f = uniform.light{i}_shadowMatrix;\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\t\\tvar shadowCoord: vec3f = getShadowSampleCoord{i}(shadowMatrix, uniform.light{i}_shadowParams, vPositionW, vec3f(0.0), &lightDirArg, dLightDirNormW, dVertexNormalW);\\n\\t\\t\\t#else\\n\\t\\t\\t\\tvar shadowCoord: vec3f = getShadowSampleCoord{i}(shadowMatrix, uniform.light{i}_shadowParams, vPositionW, uniform.light{i}_position, &lightDirArg, dLightDirNormW, dVertexNormalW);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\tshadowCoord = fadeShadow(shadowCoord, uniform.light{i}_shadowCascadeDistances);\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}TYPE == DIRECTIONAL\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == VSM_16F\\n\\t\\t\\t\\treturn getShadowVSM16(light{i}_shadowMap, light{i}_shadowMapSampler, shadowCoord, uniform.light{i}_shadowParams, 5.54);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == VSM_32F\\n\\t\\t\\t\\treturn getShadowVSM32(light{i}_shadowMap, light{i}_shadowMapSampler, shadowCoord, uniform.light{i}_shadowParams, 15.0);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCSS_32F\\n\\t\\t\\t\\t#if LIGHT{i}SHAPE != PUNCTUAL\\n\\t\\t\\t\\t\\tlet shadowSearchArea = vec2f(length(uniform.light{i}_halfWidth), length(uniform.light{i}_halfHeight)) * uniform.light{i}_shadowSearchArea;\\n\\t\\t\\t\\t\\treturn getShadowPCSS(light{i}_shadowMap, light{i}_shadowMapSampler, shadowCoord, uniform.light{i}_shadowParams, uniform.light{i}_cameraParams, shadowSearchArea, lightDirW_in);\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\treturn getShadowPCSS(light{i}_shadowMap, light{i}_shadowMapSampler, shadowCoord, uniform.light{i}_shadowParams, uniform.light{i}_cameraParams, uniform.light{i}_softShadowParams, lightDirW_in);\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCF1_16F || LIGHT{i}SHADOWTYPE == PCF1_32F\\n\\t\\t\\t\\treturn getShadowPCF1x1(light{i}_shadowMap, light{i}_shadowMapSampler, shadowCoord, uniform.light{i}_shadowParams);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCF3_16F || LIGHT{i}SHADOWTYPE == PCF3_32F\\n\\t\\t\\t\\treturn getShadowPCF3x3(light{i}_shadowMap, light{i}_shadowMapSampler, shadowCoord, uniform.light{i}_shadowParams);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCF5_16F || LIGHT{i}SHADOWTYPE == PCF5_32F\\n\\t\\t\\t\\treturn getShadowPCF5x5(light{i}_shadowMap, light{i}_shadowMapSampler, shadowCoord, uniform.light{i}_shadowParams);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}TYPE == SPOT\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == VSM_16F\\n\\t\\t\\t\\treturn getShadowSpotVSM16(light{i}_shadowMap, light{i}_shadowMapSampler, shadowCoord, uniform.light{i}_shadowParams, 5.54, lightDirW_in);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == VSM_32F\\n\\t\\t\\t\\treturn getShadowSpotVSM32(light{i}_shadowMap, light{i}_shadowMapSampler, shadowCoord, uniform.light{i}_shadowParams, 15.0, lightDirW_in);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCSS_32F\\n\\t\\t\\t\\t#if LIGHT{i}SHAPE != PUNCTUAL\\n\\t\\t\\t\\t\\tvar shadowSearchArea: vec2f = vec2f(length(uniform.light{i}_halfWidth), length(uniform.light{i}_halfHeight)) * uniform.light{i}_shadowSearchArea;\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\tvar shadowSearchArea: vec2f = vec2f(uniform.light{i}_shadowSearchArea);\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\treturn getShadowSpotPCSS(light{i}_shadowMap, light{i}_shadowMapSampler, shadowCoord, uniform.light{i}_shadowParams, uniform.light{i}_cameraParams, shadowSearchArea, lightDirW_in);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCF1_16F || LIGHT{i}SHADOWTYPE == PCF1_32F\\n\\t\\t\\t\\treturn getShadowSpotPCF1x1(light{i}_shadowMap, light{i}_shadowMapSampler, shadowCoord, uniform.light{i}_shadowParams);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCF3_16F || LIGHT{i}SHADOWTYPE == PCF3_32F\\n\\t\\t\\t\\treturn getShadowSpotPCF3x3(light{i}_shadowMap, light{i}_shadowMapSampler, shadowCoord, uniform.light{i}_shadowParams);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCF5_16F || LIGHT{i}SHADOWTYPE == PCF5_32F\\n\\t\\t\\t\\treturn getShadowSpotPCF5x5(light{i}_shadowMap, light{i}_shadowMapSampler, shadowCoord, uniform.light{i}_shadowParams);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#if LIGHT{i}TYPE == OMNI\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCSS_32F\\n\\t\\t\\t\\t var shadowSearchArea: vec2f;\\n\\t\\t\\t\\t #if LIGHT{i}SHAPE != PUNCTUAL\\n\\t\\t\\t\\t\\tvar shadowSearchArea: vec2f = vec2f(length(uniform.light{i}_halfWidth), length(uniform.light{i}_halfHeight)) * uniform.light{i}_shadowSearchArea;\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\tvar shadowSearchArea: vec2f = vec2f(uniform.light{i}_shadowSearchArea);\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\treturn getShadowOmniPCSS(light{i}_shadowMap, light{i}_shadowMapSampler, shadowCoord, uniform.light{i}_shadowParams, uniform.light{i}_cameraParams, shadowSearchArea, lightDirW_in);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCF1_16F || LIGHT{i}SHADOWTYPE == PCF1_32F\\n\\t\\t\\t\\treturn getShadowOmniPCF1x1(light{i}_shadowMap, light{i}_shadowMapSampler, shadowCoord, uniform.light{i}_shadowParams, lightDirW_in);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if LIGHT{i}SHADOWTYPE == PCF3_16F || LIGHT{i}SHADOWTYPE == PCF3_32F\\n\\t\\t\\t\\treturn getShadowOmniPCF3x3(light{i}_shadowMap, light{i}_shadowMapSampler, shadowCoord, uniform.light{i}_shadowParams, lightDirW_in);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t}\\n#endif\\n`;\\n\\nvar lighting_default = `\\n#ifdef LIT_CLUSTERED_LIGHTS\\n\\t#define LIT_CODE_FALLOFF_LINEAR\\n\\t#define LIT_CODE_FALLOFF_SQUARED\\n\\t#define LIT_CODE_LIGHTS_POINT\\n\\t#define LIT_CODE_LIGHTS_SPOT\\n#endif\\n#ifdef AREA_LIGHTS\\n\\tvar areaLightsLutTex1: texture_2d<f32>;\\n\\tvar areaLightsLutTex1Sampler: sampler;\\n\\tvar areaLightsLutTex2: texture_2d<f32>;\\n\\tvar areaLightsLutTex2Sampler: sampler;\\n#endif\\n#ifdef LIT_LIGHTING\\n\\t#include \\\"lightDiffuseLambertPS\\\"\\n\\t#if defined(AREA_LIGHTS) || defined(LIT_CLUSTERED_AREA_LIGHTS)\\n\\t\\t#include \\\"ltcPS\\\"\\n\\t#endif\\n#endif\\n#ifdef SHADOW_DIRECTIONAL\\n\\t#include \\\"shadowCascadesPS\\\"\\n#endif\\n#if defined(SHADOW_KIND_PCF1)\\n\\t#include \\\"shadowPCF1PS\\\"\\n#endif\\n#if defined(SHADOW_KIND_PCF3)\\n\\t#include \\\"shadowPCF3PS\\\"\\n#endif\\n#if defined(SHADOW_KIND_PCF5)\\n\\t#include \\\"shadowPCF5PS\\\"\\n#endif\\n#if defined(SHADOW_KIND_PCSS)\\n\\t#include \\\"linearizeDepthPS\\\"\\n\\t#include \\\"shadowSoftPS\\\"\\n#endif\\n#if defined(SHADOW_KIND_VSM)\\n\\t#include \\\"shadowEVSMPS\\\"\\n#endif\\n#ifdef LIT_CODE_FALLOFF_LINEAR\\n\\t#include \\\"falloffLinearPS\\\"\\n#endif\\n#ifdef LIT_CODE_FALLOFF_SQUARED\\n\\t#include \\\"falloffInvSquaredPS\\\"\\n#endif\\n#ifdef LIT_CODE_LIGHTS_POINT\\n\\t#include \\\"lightDirPointPS\\\"\\n#endif\\n#ifdef LIT_CODE_LIGHTS_SPOT\\n\\t#include \\\"spotPS\\\"\\n#endif\\n#ifdef LIT_CODE_COOKIE\\n\\t#include \\\"cookiePS\\\"\\n#endif\\n#ifdef LIT_CLUSTERED_LIGHTS\\n\\t#include \\\"clusteredLightPS\\\"\\n#endif\\n#ifdef LIGHT_COUNT > 0\\n\\t#include \\\"lightFunctionShadowPS, LIGHT_COUNT\\\"\\n\\t#include \\\"lightFunctionLightPS, LIGHT_COUNT\\\"\\n#endif\\n`;\\n\\nvar lightmapAdd_default = `\\nfn addLightMap(\\n\\tlightmap: vec3f,\\n\\tdir: vec3f,\\n\\tworldNormal: vec3f,\\n\\tviewDir: vec3f,\\n\\treflectionDir: vec3f,\\n\\tgloss: f32,\\n\\tspecularity: vec3f,\\n\\tvertexNormal: vec3f,\\n\\ttbn: mat3x3f\\n#if defined(LIT_IRIDESCENCE)\\n\\t, iridescenceFresnel: vec3f,\\n\\tiridescenceIntensity: f32\\n#endif\\n) {\\n\\t#if defined(LIT_SPECULAR) && defined(LIT_DIR_LIGHTMAP)\\n\\t\\tif (dot(dir, dir) < 0.0001) {\\n\\t\\t\\t\\tdDiffuseLight = dDiffuseLight + lightmap;\\n\\t\\t} else {\\n\\t\\t\\tlet vlight: f32 = saturate(dot(dir, -vertexNormal));\\n\\t\\t\\tlet flight: f32 = saturate(dot(dir, -worldNormal));\\n\\t\\t\\tlet nlight: f32 = (flight / max(vlight, 0.01)) * 0.5;\\n\\t\\t\\tdDiffuseLight = dDiffuseLight + lightmap * nlight * 2.0;\\n\\t\\t\\tlet halfDir: vec3f = normalize(-dir + viewDir);\\n\\t\\t\\tvar specularLight: vec3f = lightmap * getLightSpecular(halfDir, reflectionDir, worldNormal, viewDir, dir, gloss, tbn);\\n\\t\\t\\t#ifdef LIT_SPECULAR_FRESNEL\\n\\t\\t\\t\\tspecularLight = specularLight *\\n\\t\\t\\t\\t\\tgetFresnel(dot(viewDir, halfDir),\\n\\t\\t\\t\\t\\tgloss,\\n\\t\\t\\t\\t\\tspecularity\\n\\t\\t\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t\\t\\t, iridescenceFresnel,\\n\\t\\t\\t\\t\\tiridescenceIntensity\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t#endif\\n\\t\\t\\tdSpecularLight = dSpecularLight + specularLight;\\n\\t\\t}\\n\\t#else\\n\\t\\tdDiffuseLight = dDiffuseLight + lightmap;\\n\\t#endif\\n}\\n`;\\n\\nvar lightmap_default = `\\n#ifdef STD_LIGHTMAP_DIR\\n\\tvar<private> dLightmapDir: vec3f;\\n\\tvar texture_dirLightMap: texture_2d<f32>;\\n\\tvar texture_dirLightMapSampler: sampler;\\n#endif\\nfn getLightMap() {\\n\\tdLightmap = vec3f(1.0);\\n\\t#ifdef STD_LIGHT_TEXTURE\\n\\t\\tdLightmap = dLightmap * {STD_LIGHT_TEXTURE_DECODE}(textureSampleBias({STD_LIGHT_TEXTURE_NAME}, {STD_LIGHT_TEXTURE_NAME}Sampler, {STD_LIGHT_TEXTURE_UV}, uniform.textureBias)).{STD_LIGHT_TEXTURE_CHANNEL};\\n\\t\\t#ifdef STD_LIGHTMAP_DIR\\n\\t\\t\\tvar dir: vec3f = textureSampleBias(texture_dirLightMap, texture_dirLightMapSampler, {STD_LIGHT_TEXTURE_UV}, uniform.textureBias).xyz * 2.0 - 1.0;\\n\\t\\t\\tvar dirDot = dot(dir, dir);\\n\\t\\t\\tdLightmapDir = select(vec3(0.0), dir / sqrt(dirDot), dirDot > 0.001);\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef STD_LIGHT_VERTEX\\n\\t\\tdLightmap = dLightmap * saturate(vVertexColor.{STD_LIGHT_VERTEX_CHANNEL});\\n\\t#endif\\n}\\n`;\\n\\nvar lightSpecularAnisoGGX_default = `\\nfn calcLightSpecular(gloss: f32, worldNormal: vec3f, viewDir: vec3f, h: vec3f, lightDirNorm: vec3f, tbn: mat3x3f) -> f32 {\\n\\tlet PI: f32 = 3.141592653589793;\\n\\tlet roughness: f32 = max((1.0 - gloss) * (1.0 - gloss), 0.001);\\n\\tlet alphaRoughness: f32 = roughness * roughness;\\n\\tlet anisotropy: f32 = dAnisotropy;\\n\\tlet direction: vec2f = dAnisotropyRotation;\\n\\tlet at: f32 = mix(alphaRoughness, 1.0, anisotropy * anisotropy);\\n\\tlet ab: f32 = clamp(alphaRoughness, 0.001, 1.0);\\n\\tlet anisotropicT: vec3f = normalize(tbn * vec3f(direction, 0.0));\\n\\tlet anisotropicB: vec3f = normalize(cross(tbn[2], anisotropicT));\\n\\tlet NoH: f32 = dot(worldNormal, h);\\n\\tlet ToH: f32 = dot(anisotropicT, h);\\n\\tlet BoH: f32 = dot(anisotropicB, h);\\n\\tlet a2: f32 = at * ab;\\n\\tlet v: vec3f = vec3f(ab * ToH, at * BoH, a2 * NoH);\\n\\tlet v2: f32 = dot(v, v);\\n\\tlet w2: f32 = a2 / v2;\\n\\tlet D: f32 = a2 * w2 * w2 * (1.0 / PI);\\n\\tlet ToV: f32 = dot(anisotropicT, viewDir);\\n\\tlet BoV: f32 = dot(anisotropicB, viewDir);\\n\\tlet ToL: f32 = dot(anisotropicT, -lightDirNorm);\\n\\tlet BoL: f32 = dot(anisotropicB, -lightDirNorm);\\n\\tlet NoV: f32 = dot(worldNormal, viewDir);\\n\\tlet NoL: f32 = dot(worldNormal, -lightDirNorm);\\n\\tlet lambdaV: f32 = NoL * length(vec3f(at * ToV, ab * BoV, NoV));\\n\\tlet lambdaL: f32 = NoV * length(vec3f(at * ToL, ab * BoL, NoL));\\n\\tlet G: f32 = 0.5 / (lambdaV + lambdaL);\\n\\treturn D * G;\\n}\\nfn getLightSpecular(h: vec3f, reflDir: vec3f, worldNormal: vec3f, viewDir: vec3f, lightDirNorm: vec3f, gloss: f32, tbn: mat3x3f) -> f32 {\\n\\treturn calcLightSpecular(gloss, worldNormal, viewDir, h, lightDirNorm, tbn);\\n}\\n`;\\n\\nvar lightSpecularGGX_default = `\\nfn calcLightSpecular(gloss: f32, worldNormal: vec3f, viewDir: vec3f, h: vec3f, lightDirNorm: vec3f) -> f32 {\\n\\tconst PI: f32 = 3.141592653589793;\\n\\tlet roughness: f32 = max((1.0 - gloss) * (1.0 - gloss), 0.001);\\n\\tlet alpha: f32 = roughness * roughness;\\n\\tlet NoH: f32 = max(dot(worldNormal, h), 0.0);\\n\\tlet NoV: f32 = max(dot(worldNormal, viewDir), 0.0);\\n\\tlet NoL: f32 = max(dot(worldNormal, -lightDirNorm), 0.0);\\n\\tlet NoH2: f32 = NoH * NoH;\\n\\tlet denom: f32 = NoH2 * (alpha - 1.0) + 1.0;\\n\\tlet D: f32 = alpha / (PI * denom * denom);\\n\\tlet alpha2: f32 = alpha * alpha;\\n\\tlet lambdaV: f32 = NoL * sqrt(NoV * NoV * (1.0 - alpha2) + alpha2);\\n\\tlet lambdaL: f32 = NoV * sqrt(NoL * NoL * (1.0 - alpha2) + alpha2);\\n\\tlet G: f32 = 0.5 / max(lambdaV + lambdaL, 0.00001);\\n\\treturn D * G;\\n}\\nfn getLightSpecular(h: vec3f, reflDir: vec3f, worldNormal: vec3f, viewDir: vec3f, lightDirNorm: vec3f, gloss: f32, tbn: mat3x3f) -> f32 {\\n\\treturn calcLightSpecular(gloss, worldNormal, viewDir, h, lightDirNorm);\\n}\\n`;\\n\\nvar lightSpecularBlinn_default = `\\nfn calcLightSpecular(gloss: f32, worldNormal: vec3f, h: vec3f) -> f32 {\\n\\tlet nh: f32 = max( dot( h, worldNormal ), 0.0 );\\n\\tvar specPow: f32 = exp2(gloss * 11.0);\\n\\tspecPow = max(specPow, 0.0001);\\n\\treturn pow(nh, specPow) * (specPow + 2.0) / 8.0;\\n}\\nfn getLightSpecular(h: vec3f, reflDir: vec3f, worldNormal: vec3f, viewDir: vec3f, lightDirNorm: vec3f, gloss: f32, tbn: mat3x3f) -> f32 {\\n\\treturn calcLightSpecular(gloss, worldNormal, h);\\n}\\n`;\\n\\nvar lightSheen_default = `\\nfn sheenD(normal: vec3f, h: vec3f, roughness: f32) -> f32 {\\n\\tlet PI: f32 = 3.141592653589793;\\n\\tlet invR: f32 = 1.0 / (roughness * roughness);\\n\\tvar cos2h: f32 = max(dot(normal, h), 0.0);\\n\\tcos2h = cos2h * cos2h;\\n\\tlet sin2h: f32 = max(1.0 - cos2h, 0.0078125);\\n\\treturn (2.0 + invR) * pow(sin2h, invR * 0.5) / (2.0 * PI);\\n}\\nfn sheenV(normal: vec3f, viewDir: vec3f, light: vec3f) -> f32 {\\n\\tlet NoV: f32 = max(dot(normal, viewDir), 0.000001);\\n\\tlet NoL: f32 = max(dot(normal, light), 0.000001);\\n\\treturn 1.0 / (4.0 * (NoL + NoV - NoL * NoV));\\n}\\nfn getLightSpecularSheen(h: vec3f, worldNormal: vec3f, viewDir: vec3f, lightDirNorm: vec3f, sheenGloss: f32) -> f32 {\\n\\tlet D: f32 = sheenD(worldNormal, h, sheenGloss);\\n\\tlet V: f32 = sheenV(worldNormal, viewDir, -lightDirNorm);\\n\\treturn D * V;\\n}`;\\n\\nvar linearizeDepth_default = `\\n#ifndef LINEARIZE_DEPTH\\n#define LINEARIZE_DEPTH\\nfn linearizeDepthWithParams(z: f32, cameraParams: vec4f) -> f32 {\\n\\tif (cameraParams.w == 0.0) {\\n\\t\\treturn (cameraParams.z * cameraParams.y) / (cameraParams.y + z * (cameraParams.z - cameraParams.y));\\n\\t} else {\\n\\t\\treturn cameraParams.z + z * (cameraParams.y - cameraParams.z);\\n\\t}\\n}\\n#ifndef CAMERAPLANES\\n\\t#define CAMERAPLANES\\n\\tuniform camera_params: vec4f;\\n#endif\\nfn linearizeDepth(z: f32) -> f32 {\\n\\treturn linearizeDepthWithParams(z, uniform.camera_params);\\n}\\n#endif\\n`;\\n\\nvar litForwardBackend_default = `\\nfn evaluateBackend() -> FragmentOutput {\\n\\tvar output: FragmentOutput;\\n\\t#ifdef LIT_SSAO\\n\\t\\tlitArgs_ao = litArgs_ao * textureSampleLevel(ssaoTexture, ssaoTextureSampler, pcPosition.xy * uniform.ssaoTextureSizeInv, 0.0).r;\\n\\t#endif\\n\\t#ifdef LIT_NEEDS_NORMAL\\n\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\tgetReflDir(litArgs_worldNormal, dViewDirW, litArgs_gloss, dTBN);\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\tccReflDirW = normalize(-reflect(dViewDirW, litArgs_clearcoat_worldNormal));\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef LIT_SPECULAR_OR_REFLECTION\\n\\t\\t#ifdef LIT_METALNESS\\n\\t\\t\\tvar f0: f32 = 1.0 / litArgs_ior;\\n\\t\\t\\tf0 = (f0 - 1.0) / (f0 + 1.0);\\n\\t\\t\\tf0 = f0 * f0;\\n\\t\\t\\t#ifdef LIT_SPECULARITY_FACTOR\\n\\t\\t\\t\\tlitArgs_specularity = getSpecularModulate(litArgs_specularity, litArgs_albedo, litArgs_metalness, f0, litArgs_specularityFactor);\\n\\t\\t\\t#else\\n\\t\\t\\t\\tlitArgs_specularity = getSpecularModulate(litArgs_specularity, litArgs_albedo, litArgs_metalness, f0, 1.0);\\n\\t\\t\\t#endif\\n\\t\\t\\tlitArgs_albedo = getAlbedoModulate(litArgs_albedo, litArgs_metalness);\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_IRIDESCENCE\\n\\t\\t\\tvar iridescenceFresnel: vec3f = getIridescenceDiffraction(saturate(dot(dViewDirW, litArgs_worldNormal)), litArgs_specularity, litArgs_iridescence_thickness);\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef LIT_ADD_AMBIENT\\n\\t\\taddAmbient(litArgs_worldNormal);\\n\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\tdDiffuseLight = dDiffuseLight * (1.0 - litArgs_specularity);\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_SEPARATE_AMBIENT\\n\\t\\t\\tvar dAmbientLight: vec3f = dDiffuseLight;\\n\\t\\t\\tdDiffuseLight = vec3(0.0);\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifndef LIT_OLD_AMBIENT\\n\\t\\tdDiffuseLight = dDiffuseLight * uniform.material_ambient;\\n\\t#endif\\n\\t#ifdef LIT_AO\\n\\t\\t#ifndef LIT_OCCLUDE_DIRECT\\n\\t\\t\\toccludeDiffuse(litArgs_ao);\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef LIT_LIGHTMAP\\n\\t\\taddLightMap(\\n\\t\\t\\tlitArgs_lightmap, \\n\\t\\t\\tlitArgs_lightmapDir, \\n\\t\\t\\tlitArgs_worldNormal, \\n\\t\\t\\tdViewDirW, \\n\\t\\t\\tdReflDirW, \\n\\t\\t\\tlitArgs_gloss, \\n\\t\\t\\tlitArgs_specularity, \\n\\t\\t\\tdVertexNormalW,\\n\\t\\t\\tdTBN\\n\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t, iridescenceFresnel,\\n\\t\\t\\tlitArgs_iridescence_intensity\\n\\t\\t#endif\\n\\t\\t);\\n\\t#endif\\n\\t#ifdef LIT_LIGHTING || LIT_REFLECTIONS\\n\\t\\t#ifdef LIT_REFLECTIONS\\n\\t\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t\\taddReflectionCC(ccReflDirW, litArgs_clearcoat_gloss);\\n\\t\\t\\t\\n\\t\\t\\t\\t#ifdef LIT_SPECULAR_FRESNEL\\n\\t\\t\\t\\t\\tccFresnel = getFresnelCC(dot(dViewDirW, litArgs_clearcoat_worldNormal));\\n\\t\\t\\t\\t\\tccReflection = ccReflection * ccFresnel;\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\tccFresnel = 0.0;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SPECULARITY_FACTOR\\n\\t\\t\\t\\tccReflection = ccReflection * litArgs_specularityFactor;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SHEEN\\n\\t\\t\\t\\taddReflectionSheen(litArgs_worldNormal, dViewDirW, litArgs_sheen_gloss);\\n\\t\\t\\t#endif\\n\\t\\t\\taddReflection(dReflDirW, litArgs_gloss);\\n\\t\\t\\t#ifdef LIT_FRESNEL_MODEL\\n\\t\\t\\t\\tdReflection = vec4f(\\n\\t\\t\\t\\t\\tdReflection.rgb * getFresnel(\\n\\t\\t\\t\\t\\t\\tdot(dViewDirW, litArgs_worldNormal),\\n\\t\\t\\t\\t\\t\\tlitArgs_gloss,\\n\\t\\t\\t\\t\\t\\tlitArgs_specularity\\n\\t\\t\\t\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t\\t\\t\\t, iridescenceFresnel,\\n\\t\\t\\t\\t\\t\\tlitArgs_iridescence_intensity\\n\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\t\\t),\\n\\t\\t\\t\\t\\tdReflection.a\\n\\t\\t\\t\\t);\\n\\t\\t\\t#else\\n\\t\\t\\t\\tdReflection = vec4f(dReflection.rgb * litArgs_specularity, dReflection.a);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#ifdef AREA_LIGHTS\\n\\t\\t\\tdSpecularLight = dSpecularLight * litArgs_specularity;\\n\\t\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\t\\tcalcLTCLightValues(litArgs_gloss, litArgs_worldNormal, dViewDirW, litArgs_specularity, litArgs_clearcoat_gloss, litArgs_clearcoat_worldNormal, litArgs_clearcoat_specularity);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t\\n\\t\\t#ifdef LIGHT_COUNT > 0\\n\\t\\t\\t#include \\\"lightEvaluationPS, LIGHT_COUNT\\\"\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_CLUSTERED_LIGHTS\\n\\t\\t\\taddClusteredLights(litArgs_worldNormal, dViewDirW, dReflDirW,\\n\\t\\t\\t\\t#if defined(LIT_CLEARCOAT)\\n\\t\\t\\t\\t\\t\\tccReflDirW,\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\t\\tlitArgs_gloss, litArgs_specularity, dVertexNormalW, dTBN, \\n\\t\\t\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t\\t\\t\\tiridescenceFresnel,\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\t\\tlitArgs_clearcoat_worldNormal, litArgs_clearcoat_gloss, litArgs_sheen_gloss, litArgs_iridescence_intensity\\n\\t\\t\\t);\\n\\t\\t#endif\\n\\t\\t#ifdef AREA_LIGHTS\\n\\t\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t\\tlitArgs_clearcoat_specularity = 1.0;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SPECULAR\\n\\t\\t\\t\\tlitArgs_specularity = vec3(1.0);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_REFRACTION\\n\\t\\t\\taddRefraction(\\n\\t\\t\\t\\tlitArgs_worldNormal, \\n\\t\\t\\t\\tdViewDirW, \\n\\t\\t\\t\\tlitArgs_thickness, \\n\\t\\t\\t\\tlitArgs_gloss, \\n\\t\\t\\t\\tlitArgs_specularity, \\n\\t\\t\\t\\tlitArgs_albedo, \\n\\t\\t\\t\\tlitArgs_transmission,\\n\\t\\t\\t\\tlitArgs_ior,\\n\\t\\t\\t\\tlitArgs_dispersion\\n\\t\\t\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t\\t\\t, iridescenceFresnel, \\n\\t\\t\\t\\t\\tlitArgs_iridescence_intensity\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t);\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef LIT_AO\\n\\t\\t#ifdef LIT_OCCLUDE_DIRECT\\n\\t\\t\\toccludeDiffuse(litArgs_ao);\\n\\t\\t#endif\\n\\t\\t#if LIT_OCCLUDE_SPECULAR != NONE\\n\\t\\t\\toccludeSpecular(litArgs_gloss, litArgs_ao, litArgs_worldNormal, dViewDirW);\\n\\t\\t#endif\\n\\t#endif\\n\\t#if !defined(LIT_OPACITY_FADES_SPECULAR)\\n\\t\\t#if LIT_BLEND_TYPE == NORMAL || LIT_BLEND_TYPE == PREMULTIPLIED\\n\\t\\t\\tvar specLum: f32 = dot((dSpecularLight + dReflection.rgb * dReflection.a), vec3f( 0.2126, 0.7152, 0.0722 ));\\n\\t\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t\\tspecLum = specLum + dot(ccSpecularLight * litArgs_clearcoat_specularity + ccReflection * litArgs_clearcoat_specularity, vec3f( 0.2126, 0.7152, 0.0722 ));\\n\\t\\t\\t#endif\\n\\t\\t\\tlitArgs_opacity = clamp(litArgs_opacity + gammaCorrectInput(specLum), 0.0, 1.0);\\n\\t\\t#endif\\n\\t\\tlitArgs_opacity = litArgs_opacity * uniform.material_alphaFade;\\n\\t#endif\\n\\t#ifdef LIT_LIGHTMAP_BAKING\\n\\t\\t#ifdef LIT_LIGHTMAP_BAKING_COLOR\\n\\t\\t\\t#include \\\"bakeLmEndPS\\\"\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_LIGHTMAP_BAKING_DIR\\n\\t\\t\\t#include \\\"bakeDirLmEndPS\\\"\\n\\t\\t#endif\\n\\t#else\\n\\t\\t#include \\\"endPS\\\"\\n\\t\\t#include \\\"outputAlphaPS\\\"\\n\\t#endif\\n\\t#ifdef LIT_MSDF\\n\\t\\toutput.color = applyMsdf(output.color);\\n\\t#endif\\n\\t#include \\\"outputPS\\\"\\n\\t#include \\\"debugOutputPS\\\"\\n\\t#ifdef LIT_SHADOW_CATCHER\\n\\t\\toutput.color = vec4f(vec3f(dShadowCatcher), output.color.a);\\n\\t#endif\\n\\treturn output;\\n}\\n`;\\n\\nvar litForwardDeclaration_default = `\\nvar<private> sReflection: vec3f;\\nvar<private> dVertexNormalW: vec3f;\\nvar<private> dTangentW: vec3f;\\nvar<private> dBinormalW: vec3f;\\nvar<private> dViewDirW: vec3f;\\nvar<private> dReflDirW: vec3f;\\nvar<private> ccReflDirW: vec3f;\\nvar<private> dLightDirNormW: vec3f;\\nvar<private> dAtten: f32;\\nvar<private> dTBN: mat3x3f;\\nvar<private> dReflection: vec4f;\\nvar<private> dDiffuseLight: vec3f;\\nvar<private> dSpecularLight: vec3f;\\nvar<private> ccFresnel: f32;\\nvar<private> ccReflection: vec3f;\\nvar<private> ccSpecularLight: vec3f;\\nvar<private> ccSpecularityNoFres: f32;\\nvar<private> sSpecularLight: vec3f;\\n#ifdef LIT_DISPERSION\\n\\tuniform material_dispersion: f32;\\n#endif\\n#ifndef LIT_OPACITY_FADES_SPECULAR\\n\\tuniform material_alphaFade: f32;\\n#endif\\n#ifdef LIT_SSAO\\n\\tvar ssaoTexture : texture_2d<f32>;\\n\\tvar ssaoTextureSampler : sampler;\\n\\tuniform ssaoTextureSizeInv: vec2f;\\n#endif\\n#ifdef LIT_SHADOW_CATCHER\\n\\tvar<private> dShadowCatcher: f32 = 1.0;\\n#endif\\n#if LIGHT_COUNT > 0\\n\\t#include \\\"lightDeclarationPS, LIGHT_COUNT\\\"\\n#endif\\n#ifdef LIT_SPECULAR\\n\\t#if LIT_FRESNEL_MODEL == NONE && !defined(LIT_REFLECTIONS) && !defined(LIT_DIFFUSE_MAP) \\n\\t\\t#define LIT_OLD_AMBIENT\\n\\t#endif\\n#endif\\n#ifdef STD_LIGHTMAP_DIR\\n\\tuniform bakeDir: f32;\\n#endif\\n#ifdef LIT_LIGHTMAP_BAKING_ADD_AMBIENT\\n\\tuniform ambientBakeOcclusionContrast: f32;\\n\\tuniform ambientBakeOcclusionBrightness: f32;\\n#endif\\n`;\\n\\nvar litForwardMain_default = `\\n@fragment\\nfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\t#include \\\"litUserMainStartPS\\\"\\n\\tdReflection = vec4f(0.0);\\n\\t#ifdef LIT_CLEARCOAT\\n\\t\\tccSpecularLight = vec3f(0.0);\\n\\t\\tccReflection = vec3f(0.0);\\n\\t#endif\\n\\t#if LIT_NONE_SLICE_MODE == SLICED\\n\\t\\t#include \\\"startNineSlicedPS\\\"\\n\\t#elif LIT_NONE_SLICE_MODE == TILED\\n\\t\\t#include \\\"startNineSlicedTiledPS\\\"\\n\\t#endif\\n\\t#ifdef LIT_NEEDS_NORMAL\\n\\t\\tdVertexNormalW = normalize(vNormalW);\\n\\t\\t#ifdef LIT_TANGENTS\\n\\t\\t\\t#if defined(LIT_HEIGHTS) || defined(LIT_USE_NORMALS) || defined(LIT_USE_CLEARCOAT_NORMALS) || defined(LIT_GGX_SPECULAR)\\n\\t\\t\\t\\tdTangentW = vTangentW;\\n\\t\\t\\t\\tdBinormalW = vBinormalW;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\tgetViewDir();\\n\\t\\t#ifdef LIT_TBN\\n\\t\\t\\tgetTBN(dTangentW, dBinormalW, dVertexNormalW);\\n\\t\\t\\t#ifdef LIT_TWO_SIDED_LIGHTING\\n\\t\\t\\t\\thandleTwoSidedLighting();\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t#endif\\n\\tevaluateFrontend();\\n\\t#include \\\"debugProcessFrontendPS\\\"\\n\\tvar output: FragmentOutput = evaluateBackend();\\n\\t#include \\\"litUserMainEndPS\\\"\\n\\treturn output;\\n}\\n`;\\n\\nvar litForwardPostCode_default = `\\n#ifdef LIT_NEEDS_NORMAL\\n\\t#include \\\"cubeMapRotatePS\\\"\\n\\t#include \\\"cubeMapProjectPS\\\"\\n\\t#include \\\"envProcPS\\\"\\n#endif\\n#ifdef LIT_SPECULAR_OR_REFLECTION\\n\\t#ifdef LIT_METALNESS\\n\\t\\t#include \\\"metalnessModulatePS\\\"\\n\\t#endif\\n\\t#ifdef LIT_IRIDESCENCE\\n\\t\\t#include \\\"iridescenceDiffractionPS\\\"\\n\\t#endif\\n#endif\\n#if defined(LIT_SPECULAR_OR_REFLECTION) || defined(LIT_REFRACTION)\\n\\t#if LIT_FRESNEL_MODEL == SCHLICK\\n\\t\\t#include \\\"fresnelSchlickPS\\\"\\n\\t#endif\\n#endif\\n#ifdef LIT_AO\\n\\t#include \\\"aoDiffuseOccPS\\\"\\n\\t#include \\\"aoSpecOccPS\\\"\\n#endif\\n#if LIT_REFLECTION_SOURCE == ENVATLASHQ\\n\\t#include \\\"envAtlasPS\\\"\\n\\t#include \\\"reflectionEnvHQPS\\\"\\n#elif LIT_REFLECTION_SOURCE == ENVATLAS\\n\\t#include \\\"envAtlasPS\\\"\\n\\t#include \\\"reflectionEnvPS\\\"\\n#elif LIT_REFLECTION_SOURCE == CUBEMAP\\n\\t#include \\\"reflectionCubePS\\\"\\n#elif LIT_REFLECTION_SOURCE == SPHEREMAP\\n\\t#include \\\"reflectionSpherePS\\\"\\n#endif\\n#ifdef LIT_REFLECTIONS\\n\\t#ifdef LIT_CLEARCOAT\\n\\t\\t#include \\\"reflectionCCPS\\\"\\n\\t#endif\\n\\t#ifdef LIT_SHEEN\\n\\t\\t#include \\\"reflectionSheenPS\\\"\\n\\t#endif\\n#endif\\n#ifdef LIT_REFRACTION\\n\\t#if defined(LIT_DYNAMIC_REFRACTION)\\n\\t\\t#include \\\"refractionDynamicPS\\\"\\n\\t#elif defined(LIT_REFLECTIONS)\\n\\t\\t#include \\\"refractionCubePS\\\"\\n\\t#endif\\n#endif\\n#ifdef LIT_SHEEN\\n\\t#include \\\"lightSheenPS\\\"\\n#endif\\nuniform material_ambient: vec3f;\\n#ifdef LIT_SPECULAR\\n\\t#ifdef LIT_LIGHTING\\n\\t\\t#ifdef LIT_GGX_SPECULAR\\n\\t\\t\\t#ifdef LIT_ANISOTROPY\\n\\t\\t\\t\\t#include \\\"lightSpecularAnisoGGXPS\\\"\\n\\t\\t\\t#else\\n\\t\\t\\t\\t#include \\\"lightSpecularGGXPS\\\"\\n\\t\\t\\t#endif\\n\\t\\t#else\\n\\t\\t\\t#include \\\"lightSpecularBlinnPS\\\"\\n\\t\\t#endif\\n\\t#endif\\n#endif\\n#include \\\"combinePS\\\"\\n#ifdef LIT_LIGHTMAP\\n\\t#include \\\"lightmapAddPS\\\"\\n#endif\\n#ifdef LIT_ADD_AMBIENT\\n\\t#include \\\"ambientPS\\\"\\n#endif\\n#ifdef LIT_MSDF\\n\\t#include \\\"msdfPS\\\"\\n#endif\\n#ifdef LIT_NEEDS_NORMAL\\n\\t#include \\\"viewDirPS\\\"\\n\\t#ifdef LIT_SPECULAR\\n\\t\\t#ifdef LIT_ANISOTROPY\\n\\t\\t\\t#include \\\"reflDirAnisoPS\\\"\\n\\t\\t#else\\n\\t\\t\\t#include \\\"reflDirPS\\\"\\n\\t\\t#endif\\n\\t#endif\\n#endif\\n#include \\\"lightingPS\\\"\\n`;\\n\\nvar litForwardPreCode_default = `\\n#include \\\"basePS\\\"\\n#include \\\"sphericalPS\\\"\\n#include \\\"decodePS\\\"\\n#include \\\"gammaPS\\\"\\n#include \\\"tonemappingPS\\\"\\n#include \\\"fogPS\\\"\\n#if LIT_NONE_SLICE_MODE == SLICED\\n\\t#include \\\"baseNineSlicedPS\\\"\\n#elif LIT_NONE_SLICE_MODE == TILED\\n\\t#include \\\"baseNineSlicedTiledPS\\\"\\n#endif\\n#ifdef LIT_TBN\\n\\t#include \\\"TBNPS\\\"\\n\\t#ifdef LIT_TWO_SIDED_LIGHTING\\n\\t\\t#include \\\"twoSidedLightingPS\\\"\\n\\t#endif\\n#endif\\n`;\\n\\nvar litMain_default$1 = `\\n#include \\\"varyingsPS\\\"\\n#include \\\"litUserDeclarationPS\\\"\\n#include \\\"frontendDeclPS\\\"\\n#if defined(PICK_PASS) || defined(PREPASS_PASS)\\n\\t#include \\\"frontendCodePS\\\"\\n\\t#include \\\"litUserCodePS\\\"\\n\\t#include \\\"litOtherMainPS\\\"\\n#elif defined(SHADOW_PASS)\\n\\t#include \\\"frontendCodePS\\\"\\n\\t#include \\\"litUserCodePS\\\"\\n\\t#include \\\"litShadowMainPS\\\"\\n#else\\n\\t#include \\\"litForwardDeclarationPS\\\"\\n\\t#include \\\"litForwardPreCodePS\\\"\\n\\t#include \\\"frontendCodePS\\\"\\n\\t#include \\\"litForwardPostCodePS\\\"\\n\\t#include \\\"litForwardBackendPS\\\"\\n\\t#include \\\"litUserCodePS\\\"\\n\\t#include \\\"litForwardMainPS\\\"\\n#endif\\n`;\\n\\nvar litMain_default = `\\n#include \\\"varyingsVS\\\"\\n#include  \\\"litUserDeclarationVS\\\"\\n#ifdef VERTEX_COLOR\\n\\tattribute vertex_color: vec4f;\\n#endif\\n#ifdef NINESLICED\\n\\tvarying vMask: vec2f;\\n\\tvarying vTiledUv: vec2f;\\n\\tvar<private> dMaskGlobal: vec2f;\\n\\tvar<private> dTiledUvGlobal: vec2f;\\n\\tuniform innerOffset: vec4f;\\n\\tuniform outerScale: vec2f;\\n\\tuniform atlasRect: vec4f;\\n#endif\\nvar<private> dPositionW: vec3f;\\nvar<private> dModelMatrix: mat4x4f;\\n#include \\\"transformCoreVS\\\"\\n#ifdef UV0\\n\\tattribute vertex_texCoord0: vec2f;\\n\\t#include \\\"uv0VS\\\"\\n#endif\\n#ifdef UV1\\n\\tattribute vertex_texCoord1: vec2f;\\n\\t#include \\\"uv1VS\\\"\\n#endif\\n#ifdef LINEAR_DEPTH\\n\\t#ifndef VIEWMATRIX\\n\\t#define VIEWMATRIX\\n\\t\\tuniform matrix_view: mat4x4f;\\n\\t#endif\\n#endif\\n#include \\\"transformVS\\\"\\n#ifdef NORMALS\\n\\t#include \\\"normalCoreVS\\\"\\n\\t#include \\\"normalVS\\\"\\n#endif\\n#ifdef TANGENTS\\n\\tattribute vertex_tangent: vec4f;\\n#endif\\n#include \\\"uvTransformUniformsPS, UV_TRANSFORMS_COUNT\\\"\\n#ifdef MSDF\\n\\t#include \\\"msdfVS\\\"\\n#endif\\n#include  \\\"litUserCodeVS\\\"\\n#ifdef VERTEX_COLOR\\n\\tfn decodeGamma3(raw: vec3f) -> vec3f {\\n\\t\\treturn pow(raw, vec3f(2.2));\\n\\t}\\n\\tfn gammaCorrectInputVec4(color: vec4f) -> vec4f {\\n\\t\\treturn vec4f(decodeGamma3(color.xyz), color.w);\\n\\t}\\n#endif\\n@vertex\\nfn vertexMain(input : VertexInput) -> VertexOutput {\\n\\t#include \\\"litUserMainStartVS\\\"\\n\\tvar output : VertexOutput;\\n\\toutput.position = getPosition();\\n\\toutput.vPositionW = getWorldPosition();\\n\\t#ifdef NORMALS\\n\\t\\toutput.vNormalW = getNormal();\\n\\t#endif\\n\\t#ifdef TANGENTS\\n\\t\\toutput.vTangentW = normalize(dNormalMatrix * vertex_tangent.xyz);\\n\\t\\toutput.vBinormalW = cross(output.vNormalW, output.vTangentW) * vertex_tangent.w;\\n\\t#elif defined(GGX_SPECULAR)\\n\\t\\toutput.vObjectSpaceUpW = normalize(dNormalMatrix * vec3f(0.0, 1.0, 0.0));\\n\\t#endif\\n\\t#ifdef UV0\\n\\t\\tvar uv0: vec2f = getUv0();\\n\\t\\t#ifdef UV0_UNMODIFIED\\n\\t\\t\\toutput.vUv0 = uv0;\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef UV1\\n\\t\\tvar uv1: vec2f = getUv1();\\n\\t\\t#ifdef UV1_UNMODIFIED\\n\\t\\t\\toutput.vUv1 = uv1;\\n\\t\\t#endif\\n\\t#endif\\n\\t#include \\\"uvTransformVS, UV_TRANSFORMS_COUNT\\\"\\n\\t#ifdef VERTEX_COLOR\\n\\t\\t#ifdef STD_VERTEX_COLOR_GAMMA\\n\\t\\t\\toutput.vVertexColor = gammaCorrectInputVec4(vertex_color);\\n\\t\\t#else\\n\\t\\t\\toutput.vVertexColor = vertex_color;\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef LINEAR_DEPTH\\n\\t\\toutput.vLinearDepth = -(uniform.matrix_view * vec4f(output.vPositionW, 1.0)).z;\\n\\t#endif\\n\\t#ifdef MSDF\\n\\t\\tunpackMsdfParams();\\n\\t\\toutput.outline_color = dOutlineColor;\\n\\t\\toutput.outline_thickness = dOutlineThickness;\\n\\t\\toutput.shadow_color = dShadowColor;\\n\\t\\toutput.shadow_offset = dShadowOffset;\\n\\t#endif\\n\\t#ifdef NINESLICED\\n\\t\\toutput.vMask = dMaskGlobal;\\n\\t\\toutput.vTiledUv = dTiledUvGlobal;\\n\\t#endif\\n\\t#include \\\"litUserMainEndVS\\\"\\n\\treturn output;\\n}\\n`;\\n\\nvar litOtherMain_default = `\\n#ifdef PICK_PASS\\n\\t#include \\\"pickPS\\\"\\n#endif\\n#ifdef PREPASS_PASS\\n\\t#include \\\"floatAsUintPS\\\"\\n#endif\\n@fragment\\nfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\t#include \\\"litUserMainStartPS\\\"\\n\\tvar output: FragmentOutput;\\n\\t\\n\\tevaluateFrontend();\\n\\t#ifdef PICK_PASS\\n\\t\\toutput.color = getPickOutput();\\n\\t\\t#ifdef DEPTH_PICK_PASS\\n\\t\\t\\toutput.color1 = getPickDepth();\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef PREPASS_PASS\\n\\t\\toutput.color = float2vec4(vLinearDepth);\\n\\t#endif\\n\\t#include \\\"litUserMainEndPS\\\"\\n\\treturn output;\\n}\\n`;\\n\\nvar litShaderArgs_default = `\\nvar<private> litArgs_albedo: vec3f;\\nvar<private> litArgs_opacity: f32;\\nvar<private> litArgs_emission: vec3f;\\nvar<private> litArgs_worldNormal: vec3f;\\nvar<private> litArgs_ao: f32;\\nvar<private> litArgs_lightmap: vec3f;\\nvar<private> litArgs_lightmapDir: vec3f;\\nvar<private> litArgs_metalness: f32;\\nvar<private> litArgs_specularity: vec3f;\\nvar<private> litArgs_specularityFactor: f32;\\nvar<private> litArgs_gloss: f32;\\nvar<private> litArgs_sheen_gloss: f32;\\nvar<private> litArgs_sheen_specularity: vec3f;\\nvar<private> litArgs_transmission: f32;\\nvar<private> litArgs_thickness: f32;\\nvar<private> litArgs_ior: f32;\\nvar<private> litArgs_dispersion: f32;\\nvar<private> litArgs_iridescence_intensity: f32;\\nvar<private> litArgs_iridescence_thickness: f32;\\nvar<private> litArgs_clearcoat_worldNormal: vec3f;\\nvar<private> litArgs_clearcoat_specularity: f32;\\nvar<private> litArgs_clearcoat_gloss: f32;\\n`;\\n\\nvar litShaderCore_default = `\\n\\t#if LIT_NONE_SLICE_MODE == TILED\\n\\t\\tvar<private> textureBias: f32 = -1000.0;\\n\\t#else\\n\\t\\tuniform textureBias: f32;\\n\\t#endif\\n\\t#include \\\"litShaderArgsPS\\\"\\n`;\\n\\nvar litShadowMain_default = `\\n#if LIGHT_TYPE != DIRECTIONAL\\n\\tuniform view_position: vec3f;\\n\\tuniform light_radius: f32;\\n#endif\\n#if SHADOW_TYPE == PCSS_32F\\n\\t#include \\\"linearizeDepthPS\\\"\\n#endif\\n@fragment\\nfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\t#include \\\"litUserMainStartPS\\\"\\n\\tvar output: FragmentOutput;\\n\\tevaluateFrontend();\\n\\t#ifdef PERSPECTIVE_DEPTH\\n\\t\\tvar depth: f32 = input.position.z;\\n\\t\\t#if SHADOW_TYPE == PCSS_32F\\n\\t\\t\\t#if LIGHT_TYPE != DIRECTIONAL\\n\\t\\t\\t\\tdepth = linearizeDepthWithParams(depth, camera_params);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t#else\\n\\t\\tvar depth: f32 = min(distance(uniform.view_position, input.vPositionW) / uniform.light_radius, 0.99999);\\n\\t\\t#define MODIFIED_DEPTH\\n\\t#endif\\n\\t#if SHADOW_TYPE == VSM_16F || SHADOW_TYPE == VSM_32F\\n\\t\\t#if SHADOW_TYPE == VSM_32F\\n\\t\\t\\tvar exponent: f32 = 15.0;\\n\\t\\t#else\\n\\t\\t\\tvar exponent: f32 = 5.54;\\n\\t\\t#endif\\n\\t\\tvar depth_vsm = 2.0 * depth - 1.0;\\n\\t\\tdepth_vsm = exp(exponent * depth_vsm);\\n\\t\\toutput.color = vec4f(depth_vsm, depth_vsm * depth_vsm, 1.0, 1.0);\\n\\t#else\\n\\t\\t#if SHADOW_TYPE == PCSS_32F\\n\\t\\t\\toutput.color = vec4f(depth, 0.0, 0.0, 1.0);\\n\\t\\t#else\\n\\t\\t\\t#ifdef MODIFIED_DEPTH\\n\\t\\t\\t\\toutput.fragDepth = depth;\\n\\t\\t\\t#endif\\n\\t\\t\\toutput.color = vec4f(1.0);\\n\\t\\t#endif\\n\\t#endif\\n\\t#include \\\"litUserMainEndPS\\\"\\n\\t\\n\\treturn output;\\n}\\n`;\\n\\nvar ltc_default = `\\nfn LTC_Uv(N: vec3f, V: vec3f, roughness: f32) -> vec2f {\\n\\tconst LUT_SIZE: f32 = 64.0;\\n\\tconst LUT_SCALE: f32 = (LUT_SIZE - 1.0) / LUT_SIZE;\\n\\tconst LUT_BIAS: f32 = 0.5 / LUT_SIZE;\\n\\tlet dotNV: f32 = saturate(dot( N, V ));\\n\\tlet uv: vec2f = vec2f( roughness, sqrt( 1.0 - dotNV ) );\\n\\treturn uv * LUT_SCALE + LUT_BIAS;\\n}\\nfn LTC_ClippedSphereFormFactor( f: vec3f ) -> f32 {\\n\\tlet l: f32 = length( f );\\n\\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\\n}\\nfn LTC_EdgeVectorFormFactor( v1: vec3f, v2: vec3f ) -> vec3f {\\n\\tlet x: f32 = dot( v1, v2 );\\n\\tlet y: f32 = abs( x );\\n\\tlet a: f32 = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\\n\\tlet b: f32 = 3.4175940 + ( 4.1616724 + y ) * y;\\n\\tlet v: f32 = a / b;\\n\\tlet inv_sqrt_term = inverseSqrt( max( 1.0 - x * x, 1e-7f ) );\\n\\tlet theta_sintheta: f32 = select( (0.5 * inv_sqrt_term - v), v, x > 0.0 );\\n\\treturn cross( v1, v2 ) * theta_sintheta;\\n}\\nstruct Coords {\\n\\tcoord0: vec3f,\\n\\tcoord1: vec3f,\\n\\tcoord2: vec3f,\\n\\tcoord3: vec3f,\\n}\\nfn LTC_EvaluateRect( N: vec3f, V: vec3f, P: vec3f, mInv: mat3x3f, rectCoords: Coords) -> f32 {\\n\\tlet v1: vec3f = rectCoords.coord1 - rectCoords.coord0;\\n\\tlet v2: vec3f = rectCoords.coord3 - rectCoords.coord0;\\n\\tlet lightNormal: vec3f = cross( v1, v2 );\\n\\tlet factor: f32 = sign(-dot( lightNormal, P - rectCoords.coord0 ));\\n\\tlet T1: vec3f = normalize( V - N * dot( V, N ) );\\n\\tlet T2: vec3f = factor * cross( N, T1 );\\n\\tlet mat: mat3x3f = mInv * transpose( mat3x3f( T1, T2, N ) );\\n\\tvar coords: array<vec3f, 4>;\\n\\tcoords[0] = mat * ( rectCoords.coord0 - P );\\n\\tcoords[1] = mat * ( rectCoords.coord1 - P );\\n\\tcoords[2] = mat * ( rectCoords.coord2 - P );\\n\\tcoords[3] = mat * ( rectCoords.coord3 - P );\\n\\tcoords[0] = normalize( coords[0] );\\n\\tcoords[1] = normalize( coords[1] );\\n\\tcoords[2] = normalize( coords[2] );\\n\\tcoords[3] = normalize( coords[3] );\\n\\tvar vectorFormFactor: vec3f = vec3f( 0.0 );\\n\\tvectorFormFactor = vectorFormFactor + LTC_EdgeVectorFormFactor( coords[0], coords[1] );\\n\\tvectorFormFactor = vectorFormFactor + LTC_EdgeVectorFormFactor( coords[1], coords[2] );\\n\\tvectorFormFactor = vectorFormFactor + LTC_EdgeVectorFormFactor( coords[2], coords[3] );\\n\\tvectorFormFactor = vectorFormFactor + LTC_EdgeVectorFormFactor( coords[3], coords[0] );\\n\\tlet result: f32 = LTC_ClippedSphereFormFactor( vectorFormFactor );\\n\\treturn result;\\n}\\nvar<private> dLTCCoords: Coords;\\nfn getLTCLightCoords(lightPos: vec3f, halfWidth: vec3f, halfHeight: vec3f) -> Coords {\\n\\tvar coords: Coords;\\n\\tcoords.coord0 = lightPos + halfWidth - halfHeight;\\n\\tcoords.coord1 = lightPos - halfWidth - halfHeight;\\n\\tcoords.coord2 = lightPos - halfWidth + halfHeight;\\n\\tcoords.coord3 = lightPos + halfWidth + halfHeight;\\n\\treturn coords;\\n}\\nvar<private> dSphereRadius: f32;\\nfn getSphereLightCoords(lightPos: vec3f, halfWidth: vec3f, halfHeight: vec3f) -> Coords {\\n\\tdSphereRadius = max(length(halfWidth), length(halfHeight));\\n\\tlet f: vec3f = reflect(normalize(lightPos - uniform.view_position), vNormalW);\\n\\tlet w: vec3f = normalize(cross(f, halfHeight));\\n\\tlet h: vec3f = normalize(cross(f, w));\\n\\treturn getLTCLightCoords(lightPos, w * dSphereRadius, h * dSphereRadius);\\n}\\nvar<private> dLTCUV: vec2f;\\n#ifdef LIT_CLEARCOAT\\n\\tvar<private> ccLTCUV: vec2f;\\n#endif\\nfn getLTCLightUV(gloss: f32, worldNormal: vec3f, viewDir: vec3f) -> vec2f {\\n\\tlet roughness: f32 = max((1.0 - gloss) * (1.0 - gloss), 0.001);\\n\\treturn LTC_Uv( worldNormal, viewDir, roughness );\\n}\\nvar<private> dLTCSpecFres: vec3f;\\n#ifdef LIT_CLEARCOAT\\n\\tvar<private> ccLTCSpecFres: vec3f;\\n#endif\\nfn getLTCLightSpecFres(uv: vec2f, specularity: vec3f) -> vec3f {\\n\\tlet t2: vec4f = textureSampleLevel(areaLightsLutTex2, areaLightsLutTex2Sampler, uv, 0.0);\\n\\treturn specularity * t2.x + ( vec3f( 1.0 ) - specularity) * t2.y;\\n}\\nfn calcLTCLightValues(gloss: f32, worldNormal: vec3f, viewDir: vec3f, specularity: vec3f, clearcoatGloss: f32, clearcoatWorldNormal: vec3f, clearcoatSpecularity: f32) {\\n\\tdLTCUV = getLTCLightUV(gloss, worldNormal, viewDir);\\n\\tdLTCSpecFres = getLTCLightSpecFres(dLTCUV, specularity);\\n\\t#ifdef LIT_CLEARCOAT\\n\\t\\tccLTCUV = getLTCLightUV(clearcoatGloss, clearcoatWorldNormal, viewDir);\\n\\t\\tccLTCSpecFres = getLTCLightSpecFres(ccLTCUV, vec3f(clearcoatSpecularity));\\n\\t#endif\\n}\\nfn calcRectLightValues(lightPos: vec3f, halfWidth: vec3f, halfHeight: vec3f) {\\n\\tdLTCCoords = getLTCLightCoords(lightPos, halfWidth, halfHeight);\\n}\\nfn calcDiskLightValues(lightPos: vec3f, halfWidth: vec3f, halfHeight: vec3f) {\\n\\tcalcRectLightValues(lightPos, halfWidth, halfHeight);\\n}\\nfn calcSphereLightValues(lightPos: vec3f, halfWidth: vec3f, halfHeight: vec3f) {\\n\\tdLTCCoords = getSphereLightCoords(lightPos, halfWidth, halfHeight);\\n}\\nfn SolveCubic(Coefficient_in: vec4f) -> vec3f {\\n\\tlet pi: f32 = 3.14159;\\n\\tvar Coefficient = Coefficient_in;\\n\\tCoefficient = vec4f(Coefficient.xyz / Coefficient.w, Coefficient.w);\\n\\tlet new_yz: vec2f = Coefficient.yz / 3.0;\\n\\tCoefficient = vec4f(Coefficient.x, new_yz.x, new_yz.y, Coefficient.w);\\n\\t\\n\\tlet A: f32 = Coefficient.w;\\n\\tlet B: f32 = Coefficient.z;\\n\\tlet C: f32 = Coefficient.y;\\n\\tlet D: f32 = Coefficient.x;\\n\\tlet Delta: vec3f = vec3f(\\n\\t\\t-Coefficient.z * Coefficient.z + Coefficient.y,\\n\\t\\t-Coefficient.y * Coefficient.z + Coefficient.x,\\n\\t\\tdot(vec2f(Coefficient.z, -Coefficient.y), Coefficient.xy)\\n\\t);\\n\\tlet Discriminant: f32 = dot(vec2f(4.0 * Delta.x, -Delta.y), Delta.zy);\\n\\tvar xlc: vec2f;\\n\\tvar xsc: vec2f;\\n\\t{\\n\\t\\tlet A_a: f32 = 1.0;\\n\\t\\tlet C_a: f32 = Delta.x;\\n\\t\\tlet D_a: f32 = -2.0 * B * Delta.x + Delta.y;\\n\\t\\tlet Theta: f32 = atan2(sqrt(Discriminant), -D_a) / 3.0;\\n\\t\\tlet sqrt_neg_Ca = sqrt(-C_a);\\n\\t\\tlet x_1a: f32 = 2.0 * sqrt_neg_Ca * cos(Theta);\\n\\t\\tlet x_3a: f32 = 2.0 * sqrt_neg_Ca * cos(Theta + (2.0 / 3.0) * pi);\\n\\t\\tlet xl: f32 = select(x_3a, x_1a, (x_1a + x_3a) > 2.0 * B);\\n\\t\\txlc = vec2f(xl - B, A);\\n\\t}\\n\\t{\\n\\t\\tlet A_d: f32 = D;\\n\\t\\tlet C_d: f32 = Delta.z;\\n\\t\\tlet D_d: f32 = -D * Delta.y + 2.0 * C * Delta.z;\\n\\t\\tlet Theta: f32 = atan2(D * sqrt(Discriminant), -D_d) / 3.0;\\n\\t\\tlet sqrt_neg_Cd = sqrt(-C_d);\\n\\t\\tlet x_1d: f32 = 2.0 * sqrt_neg_Cd * cos(Theta);\\n\\t\\tlet x_3d: f32 = 2.0 * sqrt_neg_Cd * cos(Theta + (2.0 / 3.0) * pi);\\n\\t\\tlet xs: f32 = select(x_3d, x_1d, x_1d + x_3d < 2.0 * C);\\n\\t\\txsc = vec2f(-D, xs + C);\\n\\t}\\n\\tlet E: f32 =  xlc.y * xsc.y;\\n\\tlet F: f32 = -xlc.x * xsc.y - xlc.y * xsc.x;\\n\\tlet G: f32 =  xlc.x * xsc.x;\\n\\tlet xmc: vec2f = vec2f(C * F - B * G, -B * F + C * E);\\n\\tvar Root: vec3f = vec3f(xsc.x / xsc.y, xmc.x / xmc.y, xlc.x / xlc.y);\\n\\tif (Root.x < Root.y && Root.x < Root.z) {\\n\\t\\tRoot = Root.yxz;\\n\\t} else if (Root.z < Root.x && Root.z < Root.y) {\\n\\t\\tRoot = Root.xzy;\\n\\t}\\n\\treturn Root;\\n}\\nfn LTC_EvaluateDisk(N: vec3f, V: vec3f, P: vec3f, Minv: mat3x3f, points: Coords) -> f32 {\\n\\tlet T1: vec3f = normalize(V - N * dot(V, N));\\n\\tlet T2: vec3f = cross(N, T1);\\n\\tlet R: mat3x3f = transpose( mat3x3f( T1, T2, N ) );\\n\\tvar L_: array<vec3f, 3>;\\n\\tL_[0] = R * ( points.coord0 - P );\\n\\tL_[1] = R * ( points.coord1 - P );\\n\\tL_[2] = R * ( points.coord2 - P );\\n\\tlet C: vec3f  = 0.5 * (L_[0] + L_[2]);\\n\\tvar V1: vec3f = 0.5 * (L_[1] - L_[2]);\\n\\tvar V2: vec3f = 0.5 * (L_[1] - L_[0]);\\n\\tlet C_Minv: vec3f  = Minv * C;\\n\\tlet V1_Minv: vec3f = Minv * V1;\\n\\tlet V2_Minv: vec3f = Minv * V2;\\n\\tvar a: f32;\\n\\tvar b: f32;\\n\\tlet d11: f32 = dot(V1_Minv, V1_Minv);\\n\\tlet d22: f32 = dot(V2_Minv, V2_Minv);\\n\\tlet d12: f32 = dot(V1_Minv, V2_Minv);\\n\\tif (abs(d12) / sqrt(d11 * d22) > 0.0001) {\\n\\t\\tlet tr: f32 = d11 + d22;\\n\\t\\tlet det_inner: f32 = -d12 * d12 + d11 * d22;\\n\\t\\tlet det: f32 = sqrt(det_inner);\\n\\t\\tlet u: f32 = 0.5 * sqrt(tr - 2.0 * det);\\n\\t\\tlet v: f32 = 0.5 * sqrt(tr + 2.0 * det);\\n\\t\\tlet e_max: f32 = (u + v) * (u + v);\\n\\t\\tlet e_min: f32 = (u - v) * (u - v);\\n\\t\\tvar V1_: vec3f;\\n\\t\\tvar V2_: vec3f;\\n\\t\\tif (d11 > d22) {\\n\\t\\t\\tV1_ = d12 * V1_Minv + (e_max - d11) * V2_Minv;\\n\\t\\t\\tV2_ = d12 * V1_Minv + (e_min - d11) * V2_Minv;\\n\\t\\t} else {\\n\\t\\t\\tV1_ = d12*V2_Minv + (e_max - d22)*V1_Minv;\\n\\t\\t\\tV2_ = d12*V2_Minv + (e_min - d22)*V1_Minv;\\n\\t\\t}\\n\\t\\ta = 1.0 / e_max;\\n\\t\\tb = 1.0 / e_min;\\n\\t\\tV1 = normalize(V1_);\\n\\t\\tV2 = normalize(V2_);\\n\\t} else {\\n\\t\\ta = 1.0 / dot(V1_Minv, V1_Minv);\\n\\t\\tb = 1.0 / dot(V2_Minv, V2_Minv);\\n\\t\\tV1 = V1_Minv * sqrt(a);\\n\\t\\tV2 = V2_Minv * sqrt(b);\\n\\t}\\n\\tvar V3: vec3f = normalize(cross(V1, V2));\\n\\tif (dot(C_Minv, V3) < 0.0) {\\n\\t\\tV3 = V3 * -1.0;\\n\\t}\\n\\tlet L: f32  = dot(V3, C_Minv);\\n\\tlet x0: f32 = dot(V1, C_Minv) / L;\\n\\tlet y0: f32 = dot(V2, C_Minv) / L;\\n\\tlet E1: f32 = inverseSqrt(a);\\n\\tlet E2: f32 = inverseSqrt(b);\\n\\tlet a_scaled = a * L * L;\\n\\tlet b_scaled = b * L * L;\\n\\tlet c0: f32 = a_scaled * b_scaled;\\n\\tlet c1: f32 = a_scaled * b_scaled * (1.0 + x0 * x0 + y0 * y0) - a_scaled - b_scaled;\\n\\tlet c2: f32 = 1.0 - a_scaled * (1.0 + x0 * x0) - b_scaled * (1.0 + y0 * y0);\\n\\tlet c3: f32 = 1.0;\\n\\tlet roots: vec3f = SolveCubic(vec4f(c0, c1, c2, c3));\\n\\tlet e1: f32 = roots.x;\\n\\tlet e2: f32 = roots.y;\\n\\tlet e3: f32 = roots.z;\\n\\tvar avgDir: vec3f = vec3f(a_scaled * x0 / (a_scaled - e2), b_scaled * y0 / (b_scaled - e2), 1.0);\\n\\tlet rotate: mat3x3f = mat3x3f(V1, V2, V3);\\n\\tavgDir = rotate * avgDir;\\n\\tavgDir = normalize(avgDir);\\n\\tlet L1: f32 = sqrt(-e2 / e3);\\n\\tlet L2: f32 = sqrt(-e2 / e1);\\n\\tlet formFactor: f32 = max(0.0, L1 * L2 * inverseSqrt((1.0 + L1 * L1) * (1.0 + L2 * L2)));\\n\\tconst LUT_SIZE_disk: f32 = 64.0;\\n\\tconst LUT_SCALE_disk: f32 = ( LUT_SIZE_disk - 1.0 ) / LUT_SIZE_disk;\\n\\tconst LUT_BIAS_disk: f32 = 0.5 / LUT_SIZE_disk;\\n\\tvar uv: vec2f = vec2f(avgDir.z * 0.5 + 0.5, formFactor);\\n\\tuv = uv * LUT_SCALE_disk + LUT_BIAS_disk;\\n\\tlet scale: f32 = textureSampleLevel(areaLightsLutTex2, areaLightsLutTex2Sampler, uv, 0.0).w;\\n\\treturn formFactor * scale;\\n}\\nfn FixNan(value: f32) -> f32 {\\n\\treturn select(value, 0.0, value != value);\\n}\\nfn getRectLightDiffuse(worldNormal: vec3f, viewDir: vec3f, lightDir: vec3f, lightDirNorm: vec3f) -> f32 {\\n\\tlet identityMat = mat3x3f(vec3f(1.0, 0.0, 0.0), vec3f(0.0, 1.0, 0.0), vec3f(0.0, 0.0, 1.0));\\n\\treturn LTC_EvaluateRect( worldNormal, viewDir, vPositionW, identityMat, dLTCCoords );\\n}\\nfn getDiskLightDiffuse(worldNormal: vec3f, viewDir: vec3f, lightDir: vec3f, lightDirNorm: vec3f) -> f32 {\\n\\tlet identityMat = mat3x3f(vec3f(1.0, 0.0, 0.0), vec3f(0.0, 1.0, 0.0), vec3f(0.0, 0.0, 1.0));\\n\\treturn FixNan(LTC_EvaluateDisk( worldNormal, viewDir, vPositionW, identityMat, dLTCCoords ));\\n}\\nfn getSphereLightDiffuse(worldNormal: vec3f, viewDir: vec3f, lightDir: vec3f, lightDirNorm: vec3f) -> f32 {\\n\\tlet falloff: f32 = dSphereRadius / (dot(lightDir, lightDir) + dSphereRadius);\\n\\treturn FixNan(getLightDiffuse(worldNormal, viewDir, lightDirNorm) * falloff);\\n}\\nfn getLTCLightInvMat(uv: vec2f) -> mat3x3f {\\n\\tlet t1: vec4f = textureSampleLevel(areaLightsLutTex1, areaLightsLutTex1Sampler, uv, 0.0);\\n\\treturn mat3x3f(\\n\\t\\tvec3f( t1.x, 0.0, t1.y ),\\n\\t\\tvec3f( 0.0, 1.0, 0.0 ),\\n\\t\\tvec3f( t1.z, 0.0, t1.w )\\n\\t);\\n}\\nfn calcRectLightSpecular(worldNormal: vec3f, viewDir: vec3f, uv: vec2f) -> f32 {\\n\\tlet mInv: mat3x3f = getLTCLightInvMat(uv);\\n\\treturn LTC_EvaluateRect( worldNormal, viewDir, vPositionW, mInv, dLTCCoords );\\n}\\nfn getRectLightSpecular(worldNormal: vec3f, viewDir: vec3f) -> f32 {\\n\\treturn calcRectLightSpecular(worldNormal, viewDir, dLTCUV);\\n}\\nfn calcDiskLightSpecular(worldNormal: vec3f, viewDir: vec3f, uv: vec2f) -> f32 {\\n\\tlet mInv: mat3x3f = getLTCLightInvMat(uv);\\n\\treturn LTC_EvaluateDisk( worldNormal, viewDir, vPositionW, mInv, dLTCCoords );\\n}\\nfn getDiskLightSpecular(worldNormal: vec3f, viewDir: vec3f) -> f32 {\\n\\treturn calcDiskLightSpecular(worldNormal, viewDir, dLTCUV);\\n}\\nfn getSphereLightSpecular(worldNormal: vec3f, viewDir: vec3f) -> f32 {\\n\\treturn calcDiskLightSpecular(worldNormal, viewDir, dLTCUV);\\n}\\n`;\\n\\nvar metalness_default = `\\n#ifdef STD_METALNESS_CONSTANT\\nuniform material_metalness: f32;\\n#endif\\nfn getMetalness() {\\n\\tvar metalness: f32 = 1.0;\\n\\t#ifdef STD_METALNESS_CONSTANT\\n\\t\\tmetalness = metalness * uniform.material_metalness;\\n\\t#endif\\n\\t#ifdef STD_METALNESS_TEXTURE\\n\\t\\tmetalness = metalness * textureSampleBias({STD_METALNESS_TEXTURE_NAME}, {STD_METALNESS_TEXTURE_NAME}Sampler, {STD_METALNESS_TEXTURE_UV}, uniform.textureBias).{STD_METALNESS_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_METALNESS_VERTEX\\n\\tmetalness = metalness * saturate(vVertexColor.{STD_METALNESS_VERTEX_CHANNEL});\\n\\t#endif\\n\\tdMetalness = metalness;\\n}\\n`;\\n\\nvar msdf_default$1 = `\\nvar texture_msdfMap: texture_2d<f32>;\\nvar texture_msdfMapSampler: sampler;\\nfn median(r: f32, g: f32, b: f32) -> f32 {\\n\\treturn max(min(r, g), min(max(r, g), b));\\n}\\nfn map(min: f32, max: f32, v: f32) -> f32 {\\n\\treturn (v - min) / (max - min);\\n}\\nuniform font_sdfIntensity: f32;\\nuniform font_pxrange: f32;\\nuniform font_textureWidth: f32;\\n#ifndef LIT_MSDF_TEXT_ATTRIBUTE\\n\\tuniform outline_color: vec4f;\\n\\tuniform outline_thickness: f32;\\n\\tuniform shadow_color: vec4f;\\n\\tuniform shadow_offset: vec2f;\\n#else\\n\\tvarying outline_color: vec4f;\\n\\tvarying outline_thickness: f32;\\n\\tvarying shadow_color: vec4f;\\n\\tvarying shadow_offset: vec2f;\\n#endif\\nfn applyMsdf(color_in: vec4f) -> vec4f {\\n\\t#ifndef LIT_MSDF_TEXT_ATTRIBUTE\\n\\t\\tvar outline_colorValue = uniform.outline_color;\\n\\t\\tvar outline_thicknessValue = uniform.outline_thickness;\\n\\t\\tvar shadow_colorValue = uniform.shadow_color;\\n\\t\\tvar shadow_offsetValue = uniform.shadow_offset;\\n\\t#else\\n\\t\\tvar outline_colorValue = outline_color;\\n\\t\\tvar outline_thicknessValue = outline_thickness;\\n\\t\\tvar shadow_colorValue = shadow_color;\\n\\t\\tvar shadow_offsetValue = shadow_offset;\\n\\t#endif\\n\\tvar color = vec4f(gammaCorrectInputVec3(color_in.rgb), color_in.a);\\n\\tlet tsample: vec3f = textureSample(texture_msdfMap, texture_msdfMapSampler, vUv0).rgb;\\n\\tlet uvShdw: vec2f = vUv0 - shadow_offsetValue;\\n\\tlet ssample: vec3f = textureSample(texture_msdfMap, texture_msdfMapSampler, uvShdw).rgb;\\n\\tlet sigDist: f32 = median(tsample.r, tsample.g, tsample.b);\\n\\tvar sigDistShdw: f32 = median(ssample.r, ssample.g, ssample.b);\\n\\tlet smoothingMax: f32 = 0.2;\\n\\tlet w: vec2f = abs(dpdx(vUv0)) + abs(dpdy(vUv0));\\n\\tlet smoothing: f32 = clamp(w.x * uniform.font_textureWidth / uniform.font_pxrange, 0.0, smoothingMax);\\n\\tlet mapMin: f32 = 0.05;\\n\\tlet mapMax: f32 = clamp(1.0 - uniform.font_sdfIntensity, mapMin, 1.0);\\n\\tlet sigDistInner: f32 = map(mapMin, mapMax, sigDist);\\n\\tlet sigDistOutline: f32 = map(mapMin, mapMax, sigDist + outline_thicknessValue);\\n\\tsigDistShdw = map(mapMin, mapMax, sigDistShdw + outline_thicknessValue);\\n\\tlet center: f32 = 0.5;\\n\\tlet inside: f32 = smoothstep(center - smoothing, center + smoothing, sigDistInner);\\n\\tlet outline: f32 = smoothstep(center - smoothing, center + smoothing, sigDistOutline);\\n\\tlet shadow: f32 = smoothstep(center - smoothing, center + smoothing, sigDistShdw);\\n\\tlet tcolor_outline: vec4f = outline * vec4f(outline_colorValue.a * outline_colorValue.rgb, outline_colorValue.a);\\n\\tvar tcolor: vec4f = select(vec4f(0.0), tcolor_outline, outline > inside);\\n\\ttcolor = mix(tcolor, color, inside);\\n\\tlet scolor_shadow: vec4f = shadow * vec4f(shadow_colorValue.a * shadow_colorValue.rgb, shadow_colorValue.a);\\n\\tlet scolor: vec4f = select(tcolor, scolor_shadow, shadow > outline);\\n\\ttcolor = mix(scolor, tcolor, outline);\\n\\ttcolor = vec4f(gammaCorrectOutput(tcolor.rgb), tcolor.a);\\n\\treturn tcolor;\\n}\\n`;\\n\\nvar metalnessModulate_default = `\\nfn getSpecularModulate(specularity: vec3f, albedo: vec3f, metalness: f32, f0: f32, specularityFactor: f32) -> vec3f {\\n\\tlet dielectricF0: vec3f = f0 * specularity * specularityFactor;\\n\\treturn mix(dielectricF0, albedo, metalness);\\n}\\nfn getAlbedoModulate(albedo: vec3f, metalness: f32) -> vec3f {\\n\\treturn albedo * (1.0 - metalness);\\n}\\n`;\\n\\nvar morph_default$1 = `\\n\\tvarying uv0: vec2f;\\n\\tvar morphTexture: texture_2d_array<f32>;\\n\\tuniform morphFactor: array<f32, {MORPH_TEXTURE_MAX_COUNT}>;\\n\\tuniform morphIndex: array<u32, {MORPH_TEXTURE_MAX_COUNT}>;\\n\\tuniform count: u32;\\n\\t@fragment\\n\\tfn fragmentMain(input : FragmentInput) -> FragmentOutput {\\n\\t\\tvar color = vec3f(0, 0, 0);\\n\\t\\tlet textureDims = textureDimensions(morphTexture);\\n\\t\\tlet pixelCoords = vec2i(input.uv0 * vec2f(textureDims));\\n\\t\\t\\n\\t\\tfor (var i: u32 = 0; i < uniform.count; i = i + 1) {\\n\\t\\t\\tvar textureIndex: u32 = uniform.morphIndex[i].element;\\n\\t\\t\\tvar delta = textureLoad(morphTexture, pixelCoords, textureIndex, 0).xyz;\\n\\t\\t\\tcolor += uniform.morphFactor[i].element * delta;\\n\\t\\t}\\n\\t\\tvar output: FragmentOutput;\\n\\t\\toutput.color = vec4f(color, 1.0);\\n\\t\\treturn output;\\n\\t}\\n`;\\n\\nvar morph_default = `\\n\\tattribute vertex_position: vec2f;\\n\\tvarying uv0: vec2f;\\n\\t@vertex\\n\\tfn vertexMain(input: VertexInput) -> VertexOutput {\\n\\t\\tvar output: VertexOutput;\\n\\t\\toutput.position = vec4f(input.vertex_position, 0.5, 1.0);\\n\\t\\toutput.uv0 = input.vertex_position * 0.5 + vec2f(0.5, 0.5);\\n\\t\\treturn output;\\n\\t}\\n`;\\n\\nvar msdf_default = `\\nattribute vertex_outlineParameters: vec3f;\\nattribute vertex_shadowParameters: vec3f;\\nvarying outline_color: vec4f;\\nvarying outline_thickness: f32;\\nvarying shadow_color: vec4f;\\nvarying shadow_offset: vec2f;\\nvar<private> dOutlineColor: vec4f;\\nvar<private> dOutlineThickness: f32;\\nvar<private> dShadowColor: vec4f;\\nvar<private> dShadowOffset: vec2f;\\nfn unpackMsdfParams() {\\n\\tlet little: vec3f = vertex_outlineParameters % vec3f(256.0);\\n\\tlet big: vec3f = (vertex_outlineParameters - little) / 256.0;\\n\\tdOutlineColor = vec4f(little.x, big.x, little.y, big.y) / 255.0;\\n\\tdOutlineThickness = little.z / 255.0 * 0.2;\\n\\tlet little_shadow = vertex_shadowParameters % vec3f(256.0);\\n\\tlet big_shadow = (vertex_shadowParameters - little_shadow) / 256.0;\\n\\tdShadowColor = vec4f(little_shadow.x, big_shadow.x, little_shadow.y, big_shadow.y) / 255.0;\\n\\tdShadowOffset = (vec2f(little_shadow.z, big_shadow.z) / 127.0 - 1.0) * 0.005;\\n}\\n`;\\n\\nvar normal_default = `\\nvar<private> dNormalMatrix: mat3x3f;\\nfn getNormal() -> vec3f {\\n\\tdNormalMatrix = getNormalMatrix(dModelMatrix);\\n\\tlet localNormal: vec3f = getLocalNormal(vertex_normal);\\n\\treturn normalize(dNormalMatrix * localNormal);\\n}`;\\n\\nvar normalCore_default = `\\nattribute vertex_normal: vec3f;\\nuniform matrix_normal: mat3x3f;\\n#ifdef MORPHING_NORMAL\\n\\t#ifdef MORPHING_INT\\n\\t\\tvar morphNormalTex: texture_2d<u32>;\\n\\t\\tvar morphNormalTexSampler: sampler;\\n\\t#else\\n\\t\\tvar morphNormalTex: texture_2d<f32>;\\n\\t\\tvar morphNormalTexSampler: sampler;\\n\\t#endif\\n#endif\\nfn getLocalNormal(vertexNormal: vec3f) -> vec3f {\\n\\tvar localNormal: vec3f = vertexNormal;\\n\\t#ifdef MORPHING_NORMAL\\n\\t\\tlet morphUV: vec2i = getTextureMorphCoords();\\n\\t\\t#ifdef MORPHING_INT\\n\\t\\t\\tlet morphNormalInt: vec4u = textureLoad(morphNormalTex, morphUV, 0);\\n\\t\\t\\tlet morphNormalF: vec3f = vec3f(morphNormalInt.xyz) / 65535.0 * 2.0 - 1.0;\\n\\t\\t\\tlocalNormal = localNormal + morphNormalF;\\n\\t\\t#else\\n\\t\\t\\tlet morphNormal: vec3f = textureLoad(morphNormalTex, morphUV, 0).xyz;\\n\\t\\t\\tlocalNormal = localNormal + morphNormal;\\n\\t\\t#endif\\n\\t#endif\\n\\treturn localNormal;\\n}\\n#if defined(SKIN) || defined(BATCH)\\n\\tfn getNormalMatrix(modelMatrix: mat4x4f) -> mat3x3f {\\n\\t\\treturn mat3x3f(modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz);\\n\\t}\\n#elif defined(INSTANCING)\\n\\tfn getNormalMatrix(modelMatrix: mat4x4f) -> mat3x3f {\\n\\t\\treturn mat3x3f(modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz);\\n\\t}\\n#else\\n\\tfn getNormalMatrix(modelMatrix: mat4x4f) -> mat3x3f {\\n\\t\\treturn uniform.matrix_normal;\\n\\t}\\n#endif\\n`;\\n\\nvar normalMap_default = `\\n#ifdef STD_NORMAL_TEXTURE\\n\\tuniform material_bumpiness: f32;\\n#endif\\n#ifdef STD_NORMALDETAIL_TEXTURE\\n\\tuniform material_normalDetailMapBumpiness: f32;\\n\\tfn blendNormals(inN1: vec3f, inN2: vec3f) -> vec3f {\\n\\t\\tlet n1: vec3f = inN1 + vec3f(0.0, 0.0, 1.0);\\n\\t\\tlet n2: vec3f = inN2 * vec3f(-1.0, -1.0, 1.0);\\n\\t\\treturn n1 * dot(n1, n2) / n1.z - n2;\\n\\t}\\n#endif\\nfn getNormal() {\\n#ifdef STD_NORMAL_TEXTURE\\n\\tvar normalMap: vec3f = {STD_NORMAL_TEXTURE_DECODE}(textureSampleBias({STD_NORMAL_TEXTURE_NAME}, {STD_NORMAL_TEXTURE_NAME}Sampler, {STD_NORMAL_TEXTURE_UV}, uniform.textureBias));\\n\\tnormalMap = mix(vec3f(0.0, 0.0, 1.0), normalMap, uniform.material_bumpiness);\\n\\t#ifdef STD_NORMALDETAIL_TEXTURE\\n\\t\\tvar normalDetailMap: vec3f = {STD_NORMALDETAIL_TEXTURE_DECODE}(textureSampleBias({STD_NORMALDETAIL_TEXTURE_NAME}, {STD_NORMALDETAIL_TEXTURE_NAME}Sampler, {STD_NORMALDETAIL_TEXTURE_UV}, uniform.textureBias));\\n\\t\\tnormalDetailMap = mix(vec3f(0.0, 0.0, 1.0), normalDetailMap, uniform.material_normalDetailMapBumpiness);\\n\\t\\tnormalMap = blendNormals(normalMap, normalDetailMap);\\n\\t#endif\\n\\tdNormalW = normalize(dTBN * normalMap);\\n#else\\n\\tdNormalW = dVertexNormalW;\\n#endif\\n}\\n`;\\n\\nvar opacity_default = `\\nuniform material_opacity: f32;\\nuniform material_alphaDitherScale: f32;\\nfn getOpacity() {\\n\\tdAlpha = uniform.material_opacity;\\n\\t#ifdef STD_OPACITY_TEXTURE\\n\\tdAlpha = dAlpha * textureSampleBias({STD_OPACITY_TEXTURE_NAME}, {STD_OPACITY_TEXTURE_NAME}Sampler, {STD_OPACITY_TEXTURE_UV}, uniform.textureBias).{STD_OPACITY_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_OPACITY_VERTEX\\n\\tdAlpha = dAlpha * clamp(vVertexColor.{STD_OPACITY_VERTEX_CHANNEL}, 0.0, 1.0);\\n\\t#endif\\n}\\n`;\\n\\nvar opacity_dither_default = `\\n#if STD_OPACITY_DITHER == BAYER8\\n\\t#include \\\"bayerPS\\\"\\n#endif\\nuniform blueNoiseJitter: vec4f;\\n#if STD_OPACITY_DITHER == BLUENOISE\\n\\tvar blueNoiseTex32 : texture_2d<f32>;\\n\\tvar blueNoiseTex32Sampler : sampler;\\n#endif\\nfn opacityDither(alpha: f32, id: f32) {\\n\\tif (alpha <= 0.0) {\\n\\t\\tdiscard;\\n\\t}\\n\\tif (alpha >= 1.0) {\\n\\t\\treturn;\\n\\t}\\n\\t#if STD_OPACITY_DITHER == BAYER8\\n\\t\\tvar noise: f32 = bayer8(floor((pcPosition.xy + uniform.blueNoiseJitter.xy + id) % vec2f(8.0))) / 64.0;\\n\\t#else\\n\\t\\t#if STD_OPACITY_DITHER == BLUENOISE\\n\\t\\t\\tvar uv = fract(pcPosition.xy / 32.0 + uniform.blueNoiseJitter.xy + id);\\n\\t\\t\\tvar noise: f32 = textureSampleLevel(blueNoiseTex32, blueNoiseTex32Sampler, uv, 0.0).y;\\n\\t\\t#endif\\n\\t\\t#if STD_OPACITY_DITHER == IGNNOISE\\n\\t\\t\\tvar magic = vec3f(0.06711056, 0.00583715, 52.9829189);\\n\\t\\t\\tvar noise: f32 = fract(magic.z * fract(dot(pcPosition.xy + uniform.blueNoiseJitter.xy + id, magic.xy)));\\n\\t\\t#endif\\n\\t#endif\\n\\tnoise = pow(noise, 2.2);\\n\\tif (alpha < noise) {\\n\\t\\tdiscard;\\n\\t}\\n}\\n`;\\n\\nvar output_default = `\\n`;\\n\\nvar outputAlpha_default = `\\n#if LIT_BLEND_TYPE == NORMAL || LIT_BLEND_TYPE == ADDITIVEALPHA || defined(LIT_ALPHA_TO_COVERAGE)\\n\\toutput.color = vec4f(output.color.rgb, litArgs_opacity);\\n#elif LIT_BLEND_TYPE == PREMULTIPLIED\\n\\toutput.color = vec4f(output.color.rgb * litArgs_opacity, litArgs_opacity);\\n#else\\n\\toutput.color = vec4f(output.color.rgb, 1.0);\\n#endif\\n`;\\n\\nvar outputTex2D_default = `\\nvarying vUv0: vec2f;\\nvar source: texture_2d<f32>;\\nvar sourceSampler: sampler;\\n@fragment fn fragmentMain(input : FragmentInput) -> FragmentOutput {\\n\\tvar output: FragmentOutput;\\n\\toutput.color = textureSample(source, sourceSampler, input.vUv0);\\n\\treturn output;\\n}\\n`;\\n\\nvar sheen_default = `\\nuniform material_sheen: vec3f;\\nfn getSheen() {\\n\\tvar sheenColor = uniform.material_sheen;\\n\\t#ifdef STD_SHEEN_TEXTURE\\n\\tsheenColor = sheenColor * {STD_SHEEN_TEXTURE_DECODE}(textureSampleBias({STD_SHEEN_TEXTURE_NAME}, {STD_SHEEN_TEXTURE_NAME}Sampler, {STD_SHEEN_TEXTURE_UV}, uniform.textureBias)).{STD_SHEEN_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_SHEEN_VERTEX\\n\\tsheenColor = sheenColor * saturate3(vVertexColor.{STD_SHEEN_VERTEX_CHANNEL});\\n\\t#endif\\n\\tsSpecularity = sheenColor;\\n}\\n`;\\n\\nvar sheenGloss_default = `\\nuniform material_sheenGloss: f32;\\nfn getSheenGlossiness() {\\n\\tvar sheenGlossiness = uniform.material_sheenGloss;\\n\\t#ifdef STD_SHEENGLOSS_TEXTURE\\n\\tsheenGlossiness = sheenGlossiness * textureSampleBias({STD_SHEENGLOSS_TEXTURE_NAME}, {STD_SHEENGLOSS_TEXTURE_NAME}Sampler, {STD_SHEENGLOSS_TEXTURE_UV}, uniform.textureBias).{STD_SHEENGLOSS_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_SHEENGLOSS_VERTEX\\n\\tsheenGlossiness = sheenGlossiness * saturate(vVertexColor.{STD_SHEENGLOSS_VERTEX_CHANNEL});\\n\\t#endif\\n\\t#ifdef STD_SHEENGLOSS_INVERT\\n\\tsheenGlossiness = 1.0 - sheenGlossiness;\\n\\t#endif\\n\\tsGlossiness = sheenGlossiness + 0.0000001;\\n}\\n`;\\n\\nvar parallax_default = `\\nuniform material_heightMapFactor: f32;\\nfn getParallax() {\\n\\tvar parallaxScale = uniform.material_heightMapFactor;\\n\\tvar height: f32 = textureSampleBias({STD_HEIGHT_TEXTURE_NAME}, {STD_HEIGHT_TEXTURE_NAME}Sampler, {STD_HEIGHT_TEXTURE_UV}, uniform.textureBias).{STD_HEIGHT_TEXTURE_CHANNEL};\\n\\theight = height * parallaxScale - parallaxScale * 0.5;\\n\\tvar viewDirT: vec3f = dViewDirW * dTBN;\\n\\tviewDirT.z = viewDirT.z + 0.42;\\n\\tdUvOffset = height * (viewDirT.xy / viewDirT.z);\\n}\\n`;\\n\\nvar pick_default = `\\nfn encodePickOutput(id: u32) -> vec4f {\\n\\tlet inv: vec4f = vec4f(1.0 / 255.0);\\n\\tlet shifts: vec4u = vec4u(16u, 8u, 0u, 24u);\\n\\tlet col: vec4u = (vec4u(id) >> shifts) & vec4u(0xffu);\\n\\treturn vec4f(col) * inv;\\n}\\n#ifndef PICK_CUSTOM_ID\\n\\tuniform meshInstanceId: u32;\\n\\tfn getPickOutput() -> vec4f {\\n\\t\\treturn encodePickOutput(uniform.meshInstanceId);\\n\\t}\\n#endif\\n#ifdef DEPTH_PICK_PASS\\n\\t#include \\\"floatAsUintPS\\\"\\n\\t#ifndef CAMERAPLANES\\n\\t\\t#define CAMERAPLANES\\n\\t\\tuniform camera_params: vec4f;\\n\\t#endif\\n\\tfn getPickDepth() -> vec4f {\\n\\t\\tvar linearDepth: f32;\\n\\t\\tif (uniform.camera_params.w > 0.5) {\\n\\t\\t\\tlinearDepth = pcPosition.z;\\n\\t\\t} else {\\n\\t\\t\\tlet viewDist = 1.0 / pcPosition.w;\\n\\t\\t\\tlinearDepth = (viewDist - uniform.camera_params.z) / (uniform.camera_params.y - uniform.camera_params.z);\\n\\t\\t}\\n\\t\\treturn float2uint(linearDepth);\\n\\t}\\n#endif\\n`;\\n\\nvar reflDir_default = `\\nfn getReflDir(worldNormal: vec3f, viewDir: vec3f, gloss: f32, tbn: mat3x3f) {\\n\\tdReflDirW = normalize(-reflect(viewDir, worldNormal));\\n}\\n`;\\n\\nvar reflDirAniso_default = `\\nfn getReflDir(worldNormal: vec3f, viewDir: vec3f, gloss: f32, tbn: mat3x3f) {\\n\\tlet roughness: f32 = sqrt(1.0 - min(gloss, 1.0));\\n\\tlet direction: vec2f = dAnisotropyRotation;\\n\\tlet anisotropicT: vec3f = normalize(tbn * vec3f(direction, 0.0));\\n\\tlet anisotropicB: vec3f = normalize(cross(tbn[2], anisotropicT));\\n\\tlet anisotropy: f32 = dAnisotropy;\\n\\tlet anisotropicDirection: vec3f = anisotropicB;\\n\\tlet anisotropicTangent: vec3f = cross(anisotropicDirection, viewDir);\\n\\tlet anisotropicNormal: vec3f = cross(anisotropicTangent, anisotropicDirection);\\n\\tlet bendFactor: f32 = 1.0 - anisotropy * (1.0 - roughness);\\n\\tlet bendFactor4: f32 = bendFactor * bendFactor * bendFactor * bendFactor;\\n\\tlet bentNormal: vec3f = normalize(mix(normalize(anisotropicNormal), normalize(worldNormal), bendFactor4));\\n\\tdReflDirW = reflect(-viewDir, bentNormal);\\n}`;\\n\\nvar reflectionCC_default = `\\n#ifdef LIT_CLEARCOAT\\nfn addReflectionCC(reflDir: vec3f, gloss: f32) {\\n\\tccReflection = ccReflection + calcReflection(reflDir, gloss);\\n}\\n#endif\\n`;\\n\\nvar reflectionCube_default = `\\nvar texture_cubeMap: texture_cube<f32>;\\nvar texture_cubeMapSampler: sampler;\\nuniform material_reflectivity: f32;\\nfn calcReflection(reflDir: vec3f, gloss: f32) -> vec3f {\\n\\tvar lookupVec: vec3f = cubeMapProject(reflDir);\\n\\tlookupVec.x = lookupVec.x * -1.0;\\n\\treturn {reflectionDecode}(textureSample(texture_cubeMap, texture_cubeMapSampler, lookupVec));\\n}\\nfn addReflection(reflDir: vec3f, gloss: f32) {\\n\\tdReflection = dReflection + vec4f(calcReflection(reflDir, gloss), uniform.material_reflectivity);\\n}\\n`;\\n\\nvar reflectionEnvHQ_default = `\\n#ifndef ENV_ATLAS\\n\\t#define ENV_ATLAS\\n\\tvar texture_envAtlas: texture_2d<f32>;\\n\\tvar texture_envAtlasSampler: sampler;\\n#endif\\nvar texture_cubeMap: texture_cube<f32>;\\nvar texture_cubeMapSampler: sampler;\\nuniform material_reflectivity: f32;\\nfn calcReflection(reflDir: vec3f, gloss: f32) -> vec3f {\\n\\tlet dir: vec3f = cubeMapProject(reflDir) * vec3f(-1.0, 1.0, 1.0);\\n\\tlet uv: vec2f = toSphericalUv(dir);\\n\\tlet level: f32 = saturate(1.0 - gloss) * 5.0;\\n\\tlet ilevel: f32 = floor(level);\\n\\tlet flevel: f32 = level - ilevel;\\n\\tlet sharp: vec3f = {reflectionCubemapDecode}(textureSample(texture_cubeMap, texture_cubeMapSampler, dir));\\n\\tlet roughA: vec3f = {reflectionDecode}(textureSample(texture_envAtlas, texture_envAtlasSampler, mapRoughnessUv(uv, ilevel)));\\n\\tlet roughB: vec3f = {reflectionDecode}(textureSample(texture_envAtlas, texture_envAtlasSampler, mapRoughnessUv(uv, ilevel + 1.0)));\\n\\treturn processEnvironment(mix(sharp, mix(roughA, roughB, flevel), min(level, 1.0)));\\n}\\nfn addReflection(reflDir: vec3f, gloss: f32) {\\n\\tdReflection = dReflection + vec4f(calcReflection(reflDir, gloss), uniform.material_reflectivity);\\n}\\n`;\\n\\nvar reflectionEnv_default = `\\n#ifndef ENV_ATLAS\\n#define ENV_ATLAS\\n\\tvar texture_envAtlas: texture_2d<f32>;\\n\\tvar texture_envAtlasSampler: sampler;\\n#endif\\nuniform material_reflectivity: f32;\\nfn shinyMipLevel(uv: vec2f) -> f32 {\\n\\tlet dx: vec2f = dpdx(uv);\\n\\tlet dy: vec2f = dpdy(uv);\\n\\tlet uv2: vec2f = vec2f(fract(uv.x + 0.5), uv.y);\\n\\tlet dx2: vec2f = dpdx(uv2);\\n\\tlet dy2: vec2f = dpdy(uv2);\\n\\tlet maxd: f32 = min(max(dot(dx, dx), dot(dy, dy)), max(dot(dx2, dx2), dot(dy2, dy2)));\\n\\treturn clamp(0.5 * log2(maxd) - 1.0 + uniform.textureBias, 0.0, 5.0);\\n}\\nfn calcReflection(reflDir: vec3f, gloss: f32) -> vec3f {\\n\\tlet dir: vec3f = cubeMapProject(reflDir) * vec3f(-1.0, 1.0, 1.0);\\n\\tlet uv: vec2f = toSphericalUv(dir);\\n\\tlet level: f32 = saturate(1.0 - gloss) * 5.0;\\n\\tlet ilevel: f32 = floor(level);\\n\\tlet level2: f32 = shinyMipLevel(uv * atlasSize);\\n\\tlet ilevel2: f32 = floor(level2);\\n\\tvar uv0: vec2f;\\n\\tvar uv1: vec2f;\\n\\tvar weight: f32;\\n\\tif (ilevel == 0.0) {\\n\\t\\tuv0 = mapShinyUv(uv, ilevel2);\\n\\t\\tuv1 = mapShinyUv(uv, ilevel2 + 1.0);\\n\\t\\tweight = level2 - ilevel2;\\n\\t} else {\\n\\t\\tuv0 = mapRoughnessUv(uv, ilevel);\\n\\t\\tuv1 = uv0;\\n\\t\\tweight = 0.0;\\n\\t}\\n\\tlet linearA: vec3f = {reflectionDecode}(textureSample(texture_envAtlas, texture_envAtlasSampler, uv0));\\n\\tlet linearB: vec3f = {reflectionDecode}(textureSample(texture_envAtlas, texture_envAtlasSampler, uv1));\\n\\tlet linear0: vec3f = mix(linearA, linearB, weight);\\n\\tlet linear1: vec3f = {reflectionDecode}(textureSample(texture_envAtlas, texture_envAtlasSampler, mapRoughnessUv(uv, ilevel + 1.0)));\\n\\treturn processEnvironment(mix(linear0, linear1, level - ilevel));\\n}\\nfn addReflection(reflDir: vec3f, gloss: f32) {\\n\\tdReflection = dReflection + vec4f(calcReflection(reflDir, gloss), uniform.material_reflectivity);\\n}\\n`;\\n\\nvar reflectionSphere_default = `\\n#ifndef VIEWMATRIX\\n\\t#define VIEWMATRIX\\n\\tuniform matrix_view: mat4x4f;\\n#endif\\nvar texture_sphereMap: texture_2d<f32>;\\nvar texture_sphereMapSampler: sampler;\\nuniform material_reflectivity: f32;\\nfn calcReflection(reflDir: vec3f, gloss: f32) -> vec3f {\\n\\tlet viewRotationMatrix = mat3x3f(uniform.matrix_view[0].xyz, uniform.matrix_view[1].xyz, uniform.matrix_view[2].xyz);\\n\\tlet reflDirV: vec3f = viewRotationMatrix * reflDir;\\n\\tlet m: f32 = 2.0 * sqrt(dot(reflDirV.xy, reflDirV.xy) + (reflDirV.z + 1.0) * (reflDirV.z + 1.0));\\n\\tlet sphereMapUv: vec2f = reflDirV.xy / m + 0.5;\\n\\treturn {reflectionDecode}(textureSample(texture_sphereMap, texture_sphereMapSampler, sphereMapUv));\\n}\\nfn addReflection(reflDir: vec3f, gloss: f32) {\\n\\tdReflection = dReflection + vec4f(calcReflection(reflDir, gloss), uniform.material_reflectivity);\\n}\\n`;\\n\\nvar reflectionSheen_default = `\\nfn addReflectionSheen(worldNormal: vec3f, viewDir: vec3f, gloss: f32) {\\n\\tlet NoV: f32 = dot(worldNormal, viewDir);\\n\\tlet alphaG: f32 = gloss * gloss;\\n\\tlet a: f32 = select(\\n\\t\\t-8.48 * alphaG + 14.3 * gloss - 9.95,\\n\\t\\t-339.2 * alphaG + 161.4 * gloss - 25.9,\\n\\t\\tgloss < 0.25\\n\\t);\\n\\tlet b: f32 = select(\\n\\t\\t1.97 * alphaG - 3.27 * gloss + 0.72,\\n\\t\\t44.0 * alphaG - 23.7 * gloss + 3.26,\\n\\t\\tgloss < 0.25\\n\\t);\\n\\tlet dg_add: f32 = select(\\n\\t\\t0.1 * ( gloss - 0.25 ),\\n\\t\\t0.0,\\n\\t\\tgloss < 0.25\\n\\t);\\n\\tlet dg: f32 = exp( a * NoV + b ) + dg_add;\\n\\tsReflection = sReflection + (calcReflection(worldNormal, 0.0) * saturate(dg));\\n}`;\\n\\nvar refractionCube_default = `\\nfn refract2(viewVec: vec3f, normal: vec3f, IOR: f32) -> vec3f {\\n\\tlet vn: f32 = dot(viewVec, normal);\\n\\tlet k: f32 = 1.0 - IOR * IOR * (1.0 - vn * vn);\\n\\tlet refrVec: vec3f = IOR * viewVec - (IOR * vn + sqrt(k)) * normal;\\n\\treturn refrVec;\\n}\\nfn addRefraction(\\n\\tworldNormal: vec3f,\\n\\tviewDir: vec3f,\\n\\tthickness: f32,\\n\\tgloss: f32,\\n\\tspecularity: vec3f,\\n\\talbedo: vec3f,\\n\\ttransmission: f32,\\n\\trefractionIndex: f32,\\n\\tdispersion: f32\\n#if defined(LIT_IRIDESCENCE)\\n\\t, iridescenceFresnel: vec3f,\\n\\tiridescenceIntensity: f32\\n#endif\\n) {\\n\\tlet tmpRefl: vec4f = dReflection;\\n\\tlet reflectionDir: vec3f = refract2(-viewDir, worldNormal, refractionIndex);\\n\\tdReflection = vec4f(0.0);\\n\\taddReflection(reflectionDir, gloss);\\n\\tdDiffuseLight = mix(dDiffuseLight, dReflection.rgb * albedo, transmission);\\n\\tdReflection = tmpRefl;\\n}\\n`;\\n\\nvar refractionDynamic_default = `\\nuniform material_invAttenuationDistance: f32;\\nuniform material_attenuation: vec3f;\\nfn evalRefractionColor(refractionVector: vec3f, gloss: f32, refractionIndex: f32) -> vec3f {\\n\\tlet pointOfRefraction: vec4f = vec4f(vPositionW + refractionVector, 1.0);\\n\\tlet projectionPoint: vec4f = uniform.matrix_viewProjection * pointOfRefraction;\\n\\tlet uv: vec2f = getGrabScreenPos(projectionPoint);\\n\\tlet iorToRoughness: f32 = (1.0 - gloss) * clamp((1.0 / refractionIndex) * 2.0 - 2.0, 0.0, 1.0);\\n\\tlet refractionLod: f32 = log2(uniform.uScreenSize.x) * iorToRoughness;\\n\\tvar refraction: vec3f = textureSampleLevel(uSceneColorMap, uSceneColorMapSampler, uv, refractionLod).rgb;\\n\\t#ifdef SCENE_COLORMAP_GAMMA\\n\\t\\trefraction = decodeGamma3(refraction);\\n\\t#endif\\n\\treturn refraction;\\n}\\nfn addRefraction(\\n\\tworldNormal: vec3f,\\n\\tviewDir: vec3f,\\n\\tthickness: f32,\\n\\tgloss: f32,\\n\\tspecularity: vec3f,\\n\\talbedo: vec3f,\\n\\ttransmission: f32,\\n\\trefractionIndex: f32,\\n\\tdispersion: f32,\\n#if defined(LIT_IRIDESCENCE)\\n\\tiridescenceFresnel: vec3f,\\n\\tiridescenceIntensity: f32\\n#endif\\n) {\\n\\tvar modelScale: vec3f;\\n\\tmodelScale.x = length(uniform.matrix_model[0].xyz);\\n\\tmodelScale.y = length(uniform.matrix_model[1].xyz);\\n\\tmodelScale.z = length(uniform.matrix_model[2].xyz);\\n\\tlet scale: vec3f = thickness * modelScale;\\n\\tvar refractionVector = normalize(refract(-viewDir, worldNormal, refractionIndex)) * scale;\\n\\tvar refraction = evalRefractionColor(refractionVector, gloss, refractionIndex);\\n\\t#ifdef LIT_DISPERSION\\n\\t\\tlet halfSpread: f32 = (1.0 / refractionIndex - 1.0) * 0.025 * dispersion;\\n\\t\\tlet refractionIndexR: f32 = refractionIndex - halfSpread;\\n\\t\\trefractionVector = normalize(refract(-viewDir, worldNormal, refractionIndexR)) * scale;\\n\\t\\trefraction.r = evalRefractionColor(refractionVector, gloss, refractionIndexR).r;\\n\\t\\tlet refractionIndexB: f32 = refractionIndex + halfSpread;\\n\\t\\trefractionVector = normalize(refract(-viewDir, worldNormal, refractionIndexB)) * scale;\\n\\t\\trefraction.b = evalRefractionColor(refractionVector, gloss, refractionIndexB).b;\\n\\t#endif\\n\\tvar transmittance: vec3f;\\n\\tif (uniform.material_invAttenuationDistance != 0.0)\\n\\t{\\n\\t\\tlet attenuation: vec3f = -log(uniform.material_attenuation) * uniform.material_invAttenuationDistance;\\n\\t\\ttransmittance = exp(-attenuation * length(refractionVector));\\n\\t}\\n\\telse\\n\\t{\\n\\t\\ttransmittance = vec3f(1.0);\\n\\t}\\n\\tlet fresnel: vec3f = vec3f(1.0) -\\n\\t\\tgetFresnel(\\n\\t\\t\\tdot(viewDir, worldNormal),\\n\\t\\t\\tgloss,\\n\\t\\t\\tspecularity\\n\\t\\t#if defined(LIT_IRIDESCENCE)\\n\\t\\t\\t, iridescenceFresnel,\\n\\t\\t\\tiridescenceIntensity\\n\\t\\t#endif\\n\\t\\t);\\n\\tdDiffuseLight = mix(dDiffuseLight, refraction * transmittance * fresnel, transmission);\\n}\\n`;\\n\\nvar reproject_default$1 = `\\nvarying vUv0: vec2f;\\n#ifdef CUBEMAP_SOURCE\\n\\tvar sourceCube: texture_cube<f32>;\\n\\tvar sourceCubeSampler : sampler;\\n#else\\n\\tvar sourceTex: texture_2d<f32>;\\n\\tvar sourceTexSampler : sampler;\\n#endif\\n#ifdef USE_SAMPLES_TEX\\n\\tvar samplesTex: texture_2d<f32>;\\n\\tvar samplesTexSampler : sampler;\\n\\tuniform samplesTexInverseSize: vec2f;\\n#endif\\nuniform params: vec3f;\\nfn targetFace() -> f32 { return uniform.params.x; }\\nfn targetTotalPixels() -> f32 { return uniform.params.y; }\\nfn sourceTotalPixels() -> f32 { return uniform.params.z; }\\nconst PI: f32 = 3.141592653589793;\\nfn saturate(x: f32) -> f32 {\\n\\treturn clamp(x, 0.0, 1.0);\\n}\\n#include \\\"decodePS\\\"\\n#include \\\"encodePS\\\"\\nfn modifySeams(dir: vec3f, scale: f32) -> vec3f {\\n\\tlet adir = abs(dir);\\n\\tlet M = max(max(adir.x, adir.y), adir.z);\\n\\treturn dir / M * vec3f(\\n\\t\\tselect(scale, 1.0, adir.x == M),\\n\\t\\tselect(scale, 1.0, adir.y == M),\\n\\t\\tselect(scale, 1.0, adir.z == M)\\n\\t);\\n}\\nfn toSpherical(dir: vec3f) -> vec2f {\\n\\tlet nonZeroXZ = any(dir.xz != vec2f(0.0, 0.0));\\n\\treturn vec2f(select(0.0, atan2(dir.x, dir.z), nonZeroXZ), asin(dir.y));\\n}\\nfn fromSpherical(uv: vec2f) -> vec3f {\\n\\treturn vec3f(cos(uv.y) * sin(uv.x),\\n\\t\\t\\t\\tsin(uv.y),\\n\\t\\t\\t\\tcos(uv.y) * cos(uv.x));\\n}\\nfn getDirectionEquirect(uv: vec2f) -> vec3f {\\n\\treturn fromSpherical((vec2f(uv.x, 1.0 - uv.y) * 2.0 - 1.0) * vec2f(PI, PI * 0.5));\\n}\\nfn signNotZero(k: f32) -> f32 {\\n\\treturn select(-1.0, 1.0, k >= 0.0);\\n}\\nfn signNotZeroVec2(v: vec2f) -> vec2f {\\n\\treturn vec2f(signNotZero(v.x), signNotZero(v.y));\\n}\\nfn octDecode(o: vec2f) -> vec3f {\\n\\tvar v = vec3f(o.x, 1.0 - abs(o.x) - abs(o.y), o.y);\\n\\tif (v.y < 0.0) {\\n\\t\\tvar temp: vec2f = (1.0 - abs(v.zx)) * signNotZeroVec2(v.xz);\\n\\t\\tv = vec3f(temp.x, v.y, temp.y);\\n\\t}\\n\\treturn normalize(v);\\n}\\nfn getDirectionOctahedral(uv: vec2f) -> vec3f {\\n\\treturn octDecode(vec2f(uv.x, 1.0 - uv.y) * 2.0 - 1.0);\\n}\\nfn octEncode(v: vec3f) -> vec2f {\\n\\tlet l1norm = abs(v.x) + abs(v.y) + abs(v.z);\\n\\tvar result = v.xz * (1.0 / l1norm);\\n\\tif (v.y < 0.0) {\\n\\t\\tresult = (1.0 - abs(result.yx)) * signNotZeroVec2(result.xy);\\n\\t}\\n\\treturn result;\\n}\\n#ifdef CUBEMAP_SOURCE\\n\\tfn sampleCubemapDir(dir: vec3f) -> vec4f {\\n\\t\\treturn textureSample(sourceCube, sourceCubeSampler, modifySeams(dir, 1.0));\\n\\t}\\n\\tfn sampleCubemapSph(sph: vec2f) -> vec4f {\\n\\t\\treturn sampleCubemapDir(fromSpherical(sph));\\n\\t}\\n\\tfn sampleCubemapDirLod(dir: vec3f, mipLevel: f32) -> vec4f {\\n\\t\\treturn textureSampleLevel(sourceCube, sourceCubeSampler, modifySeams(dir, 1.0), mipLevel);\\n\\t}\\n\\tfn sampleCubemapSphLod(sph: vec2f, mipLevel: f32) -> vec4f {\\n\\t\\treturn sampleCubemapDirLod(fromSpherical(sph), mipLevel);\\n\\t}\\n#else\\n\\tfn sampleEquirectSph(sph: vec2f) -> vec4f {\\n\\t\\tlet uv = sph / vec2f(PI * 2.0, PI) + 0.5;\\n\\t\\treturn textureSample(sourceTex, sourceTexSampler, vec2f(uv.x, 1.0 - uv.y));\\n\\t}\\n\\tfn sampleEquirectDir(dir: vec3f) -> vec4f {\\n\\t\\treturn sampleEquirectSph(toSpherical(dir));\\n\\t}\\n\\tfn sampleEquirectSphLod(sph: vec2f, mipLevel: f32) -> vec4f {\\n\\t\\tlet uv = sph / vec2f(PI * 2.0, PI) + 0.5;\\n\\t\\treturn textureSampleLevel(sourceTex, sourceTexSampler, vec2f(uv.x, 1.0 - uv.y), mipLevel);\\n\\t}\\n\\tfn sampleEquirectDirLod(dir: vec3f, mipLevel: f32) -> vec4f {\\n\\t\\treturn sampleEquirectSphLod(toSpherical(dir), mipLevel);\\n\\t}\\n\\tfn sampleOctahedralDir(dir: vec3f) -> vec4f {\\n\\t\\tlet uv = octEncode(dir) * 0.5 + 0.5;\\n\\t\\treturn textureSample(sourceTex, sourceTexSampler, vec2f(uv.x, 1.0 - uv.y));\\n\\t}\\n\\tfn sampleOctahedralSph(sph: vec2f) -> vec4f {\\n\\t\\treturn sampleOctahedralDir(fromSpherical(sph));\\n\\t}\\n\\tfn sampleOctahedralDirLod(dir: vec3f, mipLevel: f32) -> vec4f {\\n\\t\\tlet uv = octEncode(dir) * 0.5 + 0.5;\\n\\t\\treturn textureSampleLevel(sourceTex, sourceTexSampler, vec2f(uv.x, 1.0 - uv.y), mipLevel);\\n\\t}\\n\\tfn sampleOctahedralSphLod(sph: vec2f, mipLevel: f32) -> vec4f {\\n\\t\\treturn sampleOctahedralDirLod(fromSpherical(sph), mipLevel);\\n\\t}\\n#endif\\nfn getDirectionCubemap(uv: vec2f) -> vec3f {\\n\\tlet st = uv * 2.0 - 1.0;\\n\\tlet face = targetFace();\\n\\tvar vec: vec3f;\\n\\tif (face == 0.0) {\\n\\t\\tvec = vec3f(1, -st.y, -st.x);\\n\\t} else if (face == 1.0) {\\n\\t\\tvec = vec3f(-1, -st.y, st.x);\\n\\t} else if (face == 2.0) {\\n\\t\\tvec = vec3f(st.x, 1, st.y);\\n\\t} else if (face == 3.0) {\\n\\t\\tvec = vec3f(st.x, -1, -st.y);\\n\\t} else if (face == 4.0) {\\n\\t\\tvec = vec3f(st.x, -st.y, 1);\\n\\t} else {\\n\\t\\tvec = vec3f(-st.x, -st.y, -1);\\n\\t}\\n\\treturn normalize(modifySeams(vec, 1.0));\\n}\\nfn matrixFromVector(n: vec3f) -> mat3x3f {\\n\\tlet a = 1.0 / (1.0 + n.z);\\n\\tlet b = -n.x * n.y * a;\\n\\tlet b1 = vec3f(1.0 - n.x * n.x * a, b, -n.x);\\n\\tlet b2 = vec3f(b, 1.0 - n.y * n.y * a, -n.y);\\n\\treturn mat3x3f(b1, b2, n);\\n}\\nfn matrixFromVectorSlow(n: vec3f) -> mat3x3f {\\n\\tlet up = select(vec3f(0.0, 0.0, select(-1.0, 1.0, n.y > 0.0)), vec3f(0.0, 1.0, 0.0), abs(n.y) > 0.0000001);\\n\\tlet x = normalize(cross(up, n));\\n\\tlet y = cross(n, x);\\n\\treturn mat3x3f(x, y, n);\\n}\\nfn reproject(uv: vec2f) -> vec4f {\\n\\tif ({NUM_SAMPLES} <= 1) {\\n\\t\\treturn {ENCODE_FUNC}({DECODE_FUNC}({SOURCE_FUNC}Dir({TARGET_FUNC}(uv))));\\n\\t} else {\\n\\t\\tlet t = {TARGET_FUNC}(uv);\\n\\t\\tlet tu = dpdx(t);\\n\\t\\tlet tv = dpdy(t);\\n\\t\\tvar result = vec3f(0.0);\\n\\t\\tfor (var u = 0.0; u < {NUM_SAMPLES_SQRT}; u += 1.0) {\\n\\t\\t\\tfor (var v = 0.0; v < {NUM_SAMPLES_SQRT}; v += 1.0) {\\n\\t\\t\\t\\tresult += {DECODE_FUNC}({SOURCE_FUNC}Dir(normalize(t +\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttu * (u / {NUM_SAMPLES_SQRT} - 0.5) +\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttv * (v / {NUM_SAMPLES_SQRT} - 0.5))));\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn {ENCODE_FUNC}(result / ({NUM_SAMPLES_SQRT} * {NUM_SAMPLES_SQRT}));\\n\\t}\\n}\\nconst unpackFloat: vec4f = vec4f(1.0, 1.0 / 255.0, 1.0 / 65025.0, 1.0 / 16581375.0);\\n#ifdef USE_SAMPLES_TEX\\n\\tfn unpackSample(i: i32, L: ptr<function, vec3f>, mipLevel: ptr<function, f32>) {\\n\\t\\tvar u = (f32(i * 4) + 0.5) * uniform.samplesTexInverseSize.x;\\n\\t\\tvar v = (floor(u) + 0.5) * uniform.samplesTexInverseSize.y;\\n\\t\\tvar raw: vec4f;\\n\\t\\traw.x = dot(textureSample(samplesTex, samplesTexSampler, vec2f(u, v)), unpackFloat); u += uniform.samplesTexInverseSize.x;\\n\\t\\traw.y = dot(textureSample(samplesTex, samplesTexSampler, vec2f(u, v)), unpackFloat); u += uniform.samplesTexInverseSize.x;\\n\\t\\traw.z = dot(textureSample(samplesTex, samplesTexSampler, vec2f(u, v)), unpackFloat); u += uniform.samplesTexInverseSize.x;\\n\\t\\traw.w = dot(textureSample(samplesTex, samplesTexSampler, vec2f(u, v)), unpackFloat);\\n\\t\\t*L = raw.xyz * 2.0 - 1.0;\\n\\t\\t*mipLevel = raw.w * 8.0;\\n\\t}\\n\\tfn prefilterSamples(uv: vec2f) -> vec4f {\\n\\t\\tlet vecSpace = matrixFromVectorSlow({TARGET_FUNC}(uv));\\n\\t\\tvar L: vec3f;\\n\\t\\tvar mipLevel: f32;\\n\\t\\tvar result = vec3f(0.0);\\n\\t\\tvar totalWeight = 0.0;\\n\\t\\tfor (var i = 0; i < {NUM_SAMPLES}; i += 1) {\\n\\t\\t\\tunpackSample(i, &L, &mipLevel);\\n\\t\\t\\tresult += {DECODE_FUNC}({SOURCE_FUNC}DirLod(vecSpace * L, mipLevel)) * L.z;\\n\\t\\t\\ttotalWeight += L.z;\\n\\t\\t}\\n\\t\\treturn {ENCODE_FUNC}(result / totalWeight);\\n\\t}\\n\\tfn prefilterSamplesUnweighted(uv: vec2f) -> vec4f {\\n\\t\\tlet vecSpace = matrixFromVectorSlow({TARGET_FUNC}(uv));\\n\\t\\tvar L: vec3f;\\n\\t\\tvar mipLevel: f32;\\n\\t\\tvar result = vec3f(0.0);\\n\\t\\tfor (var i = 0; i < {NUM_SAMPLES}; i += 1) {\\n\\t\\t\\tunpackSample(i, &L, &mipLevel);\\n\\t\\t\\tresult += {DECODE_FUNC}({SOURCE_FUNC}DirLod(vecSpace * L, mipLevel));\\n\\t\\t}\\n\\t\\treturn {ENCODE_FUNC}(result / f32({NUM_SAMPLES}));\\n\\t}\\n#endif\\n@fragment\\nfn fragmentMain(input : FragmentInput) -> FragmentOutput {\\n\\tvar output: FragmentOutput;\\n\\toutput.color = {PROCESS_FUNC}(input.vUv0);\\n\\treturn output;\\n}\\n`;\\n\\nvar reproject_default = `\\nattribute vertex_position: vec2f;\\nuniform uvMod: vec4f;\\nvarying vUv0: vec2f;\\n@vertex\\nfn vertexMain(input: VertexInput) -> VertexOutput {\\n\\tvar output: VertexOutput;\\n\\toutput.position = vec4f(input.vertex_position, 0.5, 1.0);\\n\\toutput.vUv0 = getImageEffectUV((input.vertex_position * 0.5 + vec2f(0.5, 0.5)) * uniform.uvMod.xy + uniform.uvMod.zw);\\n\\treturn output;\\n}\\n`;\\n\\nvar screenDepth_default = `\\nvar uSceneDepthMap: texture_2d<uff>;\\n#ifndef SCREENSIZE\\n\\t#define SCREENSIZE\\n\\tuniform uScreenSize: vec4f;\\n#endif\\n#ifndef VIEWMATRIX\\n\\t#define VIEWMATRIX\\n\\tuniform matrix_view: mat4x4f;\\n#endif\\n#ifndef LINEARIZE_DEPTH\\n\\t#define LINEARIZE_DEPTH\\n\\t#ifndef CAMERAPLANES\\n\\t\\t#define CAMERAPLANES\\n\\t\\tuniform camera_params: vec4f;\\n\\t#endif\\n\\tfn linearizeDepth(z: f32) -> f32 {\\n\\t\\tif (uniform.camera_params.w == 0.0) {\\n\\t\\t\\treturn (uniform.camera_params.z * uniform.camera_params.y) / (uniform.camera_params.y + z * (uniform.camera_params.z - uniform.camera_params.y));\\n\\t\\t} else {\\n\\t\\t\\treturn uniform.camera_params.z + z * (uniform.camera_params.y - uniform.camera_params.z);\\n\\t\\t}\\n\\t}\\n#endif\\nfn delinearizeDepth(linearDepth: f32) -> f32 {\\n\\tif (uniform.camera_params.w == 0.0) {\\n\\t\\treturn (uniform.camera_params.y * (uniform.camera_params.z - linearDepth)) / (linearDepth * (uniform.camera_params.z - uniform.camera_params.y));\\n\\t} else {\\n\\t\\treturn (linearDepth - uniform.camera_params.z) / (uniform.camera_params.y - uniform.camera_params.z);\\n\\t}\\n}\\nfn getLinearScreenDepth(uv: vec2f) -> f32 {\\n\\tlet textureSize = textureDimensions(uSceneDepthMap, 0);\\n\\tlet texel: vec2i = vec2i(uv * vec2f(textureSize));\\n\\t#ifdef SCENE_DEPTHMAP_LINEAR\\n\\t\\treturn textureLoad(uSceneDepthMap, texel, 0).r;\\n\\t#else\\n\\t\\treturn linearizeDepth(textureLoad(uSceneDepthMap, texel, 0).r);\\n\\t#endif\\n}\\n#ifndef VERTEXSHADER\\n\\tfn getLinearScreenDepthFrag() -> f32 {\\n\\t\\tlet uv: vec2f = pcPosition.xy * uniform.uScreenSize.zw;\\n\\t\\treturn getLinearScreenDepth(uv);\\n\\t}\\n#endif\\nfn getLinearDepth(pos: vec3f) -> f32 {\\n\\treturn -(uniform.matrix_view * vec4f(pos, 1.0)).z;\\n}\\n`;\\n\\nvar shadowCascades_default = `\\nfn getShadowCascadeIndex(shadowCascadeDistances: vec4f, shadowCascadeCount: i32) -> i32 {\\n\\tlet depth: f32 = 1.0 / pcPosition.w;\\n\\tlet comparisons: vec4f = step(shadowCascadeDistances, vec4f(depth));\\n\\tlet cascadeIndex: i32 = i32(dot(comparisons, vec4f(1.0)));\\n\\treturn min(cascadeIndex, shadowCascadeCount - 1);\\n}\\nfn ditherShadowCascadeIndex(cascadeIndex_in: i32, shadowCascadeDistances: vec4f, shadowCascadeCount: i32, blendFactor: f32) -> i32 {\\n\\tvar cascadeIndex: i32 = cascadeIndex_in;\\n\\tif (cascadeIndex < shadowCascadeCount - 1) {\\n\\t\\tlet currentRangeEnd: f32 = shadowCascadeDistances[cascadeIndex];\\n\\t\\tlet transitionStart: f32 = blendFactor * currentRangeEnd;\\n\\t\\tlet depth: f32 = 1.0 / pcPosition.w;\\n\\t\\tif (depth > transitionStart) {\\n\\t\\t\\tlet transitionFactor: f32 = smoothstep(transitionStart, currentRangeEnd, depth);\\n\\t\\t\\tlet dither: f32 = fract(sin(dot(pcPosition.xy, vec2f(12.9898, 78.233))) * 43758.5453);\\n\\t\\t\\tif (dither < transitionFactor) {\\n\\t\\t\\t\\tcascadeIndex = cascadeIndex + 1;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\treturn cascadeIndex;\\n}\\nfn fadeShadow(shadowCoord_in: vec3f, shadowCascadeDistances: vec4f) -> vec3f {\\n\\tvar shadowCoord: vec3f = shadowCoord_in;\\n\\tlet depth: f32 = 1.0 / pcPosition.w;\\n\\tif (depth > shadowCascadeDistances.w) {\\n\\t\\tshadowCoord.z = -9999999.0;\\n\\t}\\n\\treturn shadowCoord;\\n}\\n`;\\n\\nvar shadowEVSM_default = `\\nfn linstep(a: f32, b: f32, v: f32) -> f32 {\\n\\treturn clamp((v - a) / (b - a), 0.0, 1.0);\\n}\\nfn reduceLightBleeding(pMax: f32, amount: f32) -> f32 {\\n\\t return linstep(amount, 1.0, pMax);\\n}\\nfn chebyshevUpperBound(moments: vec2f, mean: f32, minVariance: f32, lightBleedingReduction: f32) -> f32 {\\n\\tvar variance: f32 = moments.y - (moments.x * moments.x);\\n\\tvariance = max(variance, minVariance);\\n\\tlet d: f32 = mean - moments.x;\\n\\tvar pMax: f32 = variance / (variance + (d * d));\\n\\tpMax = reduceLightBleeding(pMax, lightBleedingReduction);\\n\\treturn select(pMax, 1.0, mean <= moments.x);\\n}\\nfn calculateEVSM(moments_in: vec3f, Z_in: f32, vsmBias: f32, exponent: f32) -> f32 {\\n\\tlet Z: f32 = 2.0 * Z_in - 1.0;\\n\\tlet warpedDepth: f32 = exp(exponent * Z);\\n\\tlet moments: vec2f = moments_in.xy + vec2f(warpedDepth, warpedDepth*warpedDepth) * (1.0 - moments_in.z);\\n\\tlet VSMBias: f32 = vsmBias;\\n\\tlet depthScale: f32 = VSMBias * exponent * warpedDepth;\\n\\tlet minVariance1: f32 = depthScale * depthScale;\\n\\treturn chebyshevUpperBound(moments, warpedDepth, minVariance1, 0.1);\\n}\\nfn VSM16(tex: texture_2d<f32>, texSampler: sampler, texCoords: vec2f, resolution: f32, Z: f32, vsmBias: f32, exponent: f32) -> f32 {\\n\\tlet moments: vec3f = textureSampleLevel(tex, texSampler, texCoords, 0.0).xyz;\\n\\treturn calculateEVSM(moments, Z, vsmBias, exponent);\\n}\\nfn getShadowVSM16(shadowMap: texture_2d<f32>, shadowMapSampler: sampler, shadowCoord: vec3f, shadowParams: vec4f, exponent: f32) -> f32 {\\n\\treturn VSM16(shadowMap, shadowMapSampler, shadowCoord.xy, shadowParams.x, shadowCoord.z, shadowParams.y, exponent);\\n}\\nfn getShadowSpotVSM16(shadowMap: texture_2d<f32>, shadowMapSampler: sampler, shadowCoord: vec3f, shadowParams: vec4f, exponent: f32, lightDir: vec3f) -> f32 {\\n\\tlet Z: f32 = length(lightDir) * shadowParams.w + shadowParams.z;\\n\\treturn VSM16(shadowMap, shadowMapSampler, shadowCoord.xy, shadowParams.x, Z, shadowParams.y, exponent);\\n}\\nfn VSM32(tex: texture_2d<f32>, texSampler: sampler, texCoords_in: vec2f, resolution: f32, Z: f32, vsmBias: f32, exponent: f32) -> f32 {\\n\\t#ifdef CAPS_TEXTURE_FLOAT_FILTERABLE\\n\\t\\tvar moments: vec3f = textureSampleLevel(tex, texSampler, texCoords_in, 0.0).xyz;\\n\\t#else\\n\\t\\tvar pixelSize : f32 = 1.0 / resolution;\\n\\t\\tlet texCoords: vec2f = texCoords_in - vec2f(pixelSize);\\n\\t\\tlet s00: vec3f = textureSampleLevel(tex, texSampler, texCoords, 0.0).xyz;\\n\\t\\tlet s10: vec3f = textureSampleLevel(tex, texSampler, texCoords + vec2f(pixelSize, 0.0), 0.0).xyz;\\n\\t\\tlet s01: vec3f = textureSampleLevel(tex, texSampler, texCoords + vec2f(0.0, pixelSize), 0.0).xyz;\\n\\t\\tlet s11: vec3f = textureSampleLevel(tex, texSampler, texCoords + vec2f(pixelSize), 0.0).xyz;\\n\\t\\tlet fr: vec2f = fract(texCoords * resolution);\\n\\t\\tlet h0: vec3f = mix(s00, s10, fr.x);\\n\\t\\tlet h1: vec3f = mix(s01, s11, fr.x);\\n\\t\\tvar moments: vec3f = mix(h0, h1, fr.y);\\n\\t#endif\\n\\treturn calculateEVSM(moments, Z, vsmBias, exponent);\\n}\\nfn getShadowVSM32(shadowMap: texture_2d<f32>, shadowMapSampler: sampler, shadowCoord: vec3f, shadowParams: vec4f, exponent: f32) -> f32 {\\n\\treturn VSM32(shadowMap, shadowMapSampler, shadowCoord.xy, shadowParams.x, shadowCoord.z, shadowParams.y, exponent);\\n}\\nfn getShadowSpotVSM32(shadowMap: texture_2d<f32>, shadowMapSampler: sampler, shadowCoord: vec3f, shadowParams: vec4f, exponent: f32, lightDir: vec3f) -> f32 {\\n\\tlet Z: f32 = length(lightDir) * shadowParams.w + shadowParams.z;\\n\\treturn VSM32(shadowMap, shadowMapSampler, shadowCoord.xy, shadowParams.x, Z, shadowParams.y, exponent);\\n}\\n`;\\n\\nvar shadowPCF1_default = `\\nfn getShadowPCF1x1(shadowMap: texture_depth_2d, shadowMapSampler: sampler_comparison, shadowCoord: vec3f, shadowParams: vec4f) -> f32 {\\n\\treturn textureSampleCompareLevel(shadowMap, shadowMapSampler, shadowCoord.xy, shadowCoord.z);\\n}\\nfn getShadowSpotPCF1x1(shadowMap: texture_depth_2d, shadowMapSampler: sampler_comparison, shadowCoord: vec3f, shadowParams: vec4f) -> f32 {\\n\\treturn textureSampleCompareLevel(shadowMap, shadowMapSampler, shadowCoord.xy, shadowCoord.z);\\n}\\n`;\\n\\nvar shadowPCF3_default = `\\nfn _getShadowPCF3x3(shadowMap: texture_depth_2d, shadowMapSampler: sampler_comparison, shadowCoord: vec3f, shadowParams: vec3f) -> f32 {\\n\\tlet z: f32 = shadowCoord.z;\\n\\tlet uv: vec2f = shadowCoord.xy * shadowParams.x;\\n\\tlet shadowMapSizeInv: f32 = 1.0 / shadowParams.x;\\n\\tlet base_uv_temp: vec2f = floor(uv + 0.5);\\n\\tlet s: f32 = (uv.x + 0.5 - base_uv_temp.x);\\n\\tlet t: f32 = (uv.y + 0.5 - base_uv_temp.y);\\n\\tlet base_uv: vec2f = (base_uv_temp - vec2f(0.5)) * shadowMapSizeInv;\\n\\tvar sum: f32 = 0.0;\\n\\tlet uw0: f32 = (3.0 - 2.0 * s);\\n\\tlet uw1: f32 = (1.0 + 2.0 * s);\\n\\tlet u0_offset: f32 = (2.0 - s) / uw0 - 1.0;\\n\\tlet u1_offset: f32 = s / uw1 + 1.0;\\n\\tlet vw0: f32 = (3.0 - 2.0 * t);\\n\\tlet vw1: f32 = (1.0 + 2.0 * t);\\n\\tlet v0_offset: f32 = (2.0 - t) / vw0 - 1.0;\\n\\tlet v1_offset: f32 = t / vw1 + 1.0;\\n\\tlet u0: f32 = u0_offset * shadowMapSizeInv + base_uv.x;\\n\\tlet v0: f32 = v0_offset * shadowMapSizeInv + base_uv.y;\\n\\tlet u1: f32 = u1_offset * shadowMapSizeInv + base_uv.x;\\n\\tlet v1: f32 = v1_offset * shadowMapSizeInv + base_uv.y;\\n\\tsum = sum + uw0 * vw0 * textureSampleCompareLevel(shadowMap, shadowMapSampler, vec2f(u0, v0), z);\\n\\tsum = sum + uw1 * vw0 * textureSampleCompareLevel(shadowMap, shadowMapSampler, vec2f(u1, v0), z);\\n\\tsum = sum + uw0 * vw1 * textureSampleCompareLevel(shadowMap, shadowMapSampler, vec2f(u0, v1), z);\\n\\tsum = sum + uw1 * vw1 * textureSampleCompareLevel(shadowMap, shadowMapSampler, vec2f(u1, v1), z);\\n\\tsum = sum * (1.0 / 16.0);\\n\\treturn sum;\\n}\\nfn getShadowPCF3x3(shadowMap: texture_depth_2d, shadowMapSampler: sampler_comparison, shadowCoord: vec3f, shadowParams: vec4f) -> f32 {\\n\\treturn _getShadowPCF3x3(shadowMap, shadowMapSampler, shadowCoord, shadowParams.xyz);\\n}\\nfn getShadowSpotPCF3x3(shadowMap: texture_depth_2d, shadowMapSampler: sampler_comparison, shadowCoord: vec3f, shadowParams: vec4f) -> f32 {\\n\\treturn _getShadowPCF3x3(shadowMap, shadowMapSampler, shadowCoord, shadowParams.xyz);\\n}\\n`;\\n\\nvar shadowPCF5_default = `\\nfn _getShadowPCF5x5(shadowMap: texture_depth_2d, shadowMapSampler: sampler_comparison, shadowCoord: vec3f, shadowParams: vec3f) -> f32 {\\n\\tlet z: f32 = shadowCoord.z;\\n\\tlet uv: vec2f = shadowCoord.xy * shadowParams.x;\\n\\tlet shadowMapSizeInv: f32 = 1.0 / shadowParams.x;\\n\\tlet base_uv_temp: vec2f = floor(uv + 0.5);\\n\\tlet s: f32 = (uv.x + 0.5 - base_uv_temp.x);\\n\\tlet t: f32 = (uv.y + 0.5 - base_uv_temp.y);\\n\\tlet base_uv: vec2f = (base_uv_temp - vec2f(0.5)) * shadowMapSizeInv;\\n\\tlet uw0: f32 = (4.0 - 3.0 * s);\\n\\tlet uw1: f32 = 7.0;\\n\\tlet uw2: f32 = (1.0 + 3.0 * s);\\n\\tlet u0_offset: f32 = (3.0 - 2.0 * s) / uw0 - 2.0;\\n\\tlet u1_offset: f32 = (3.0 + s) / uw1;\\n\\tlet u2_offset: f32 = s / uw2 + 2.0;\\n\\tlet vw0: f32 = (4.0 - 3.0 * t);\\n\\tlet vw1: f32 = 7.0;\\n\\tlet vw2: f32 = (1.0 + 3.0 * t);\\n\\tlet v0_offset: f32 = (3.0 - 2.0 * t) / vw0 - 2.0;\\n\\tlet v1_offset: f32 = (3.0 + t) / vw1;\\n\\tlet v2_offset: f32 = t / vw2 + 2.0;\\n\\tvar sum: f32 = 0.0;\\n\\tlet u0: f32 = u0_offset * shadowMapSizeInv + base_uv.x;\\n\\tlet v0: f32 = v0_offset * shadowMapSizeInv + base_uv.y;\\n\\tlet u1: f32 = u1_offset * shadowMapSizeInv + base_uv.x;\\n\\tlet v1: f32 = v1_offset * shadowMapSizeInv + base_uv.y;\\n\\tlet u2: f32 = u2_offset * shadowMapSizeInv + base_uv.x;\\n\\tlet v2: f32 = v2_offset * shadowMapSizeInv + base_uv.y;\\n\\tsum = sum + uw0 * vw0 * textureSampleCompareLevel(shadowMap, shadowMapSampler, vec2f(u0, v0), z);\\n\\tsum = sum + uw1 * vw0 * textureSampleCompareLevel(shadowMap, shadowMapSampler, vec2f(u1, v0), z);\\n\\tsum = sum + uw2 * vw0 * textureSampleCompareLevel(shadowMap, shadowMapSampler, vec2f(u2, v0), z);\\n\\tsum = sum + uw0 * vw1 * textureSampleCompareLevel(shadowMap, shadowMapSampler, vec2f(u0, v1), z);\\n\\tsum = sum + uw1 * vw1 * textureSampleCompareLevel(shadowMap, shadowMapSampler, vec2f(u1, v1), z);\\n\\tsum = sum + uw2 * vw1 * textureSampleCompareLevel(shadowMap, shadowMapSampler, vec2f(u2, v1), z);\\n\\tsum = sum + uw0 * vw2 * textureSampleCompareLevel(shadowMap, shadowMapSampler, vec2f(u0, v2), z);\\n\\tsum = sum + uw1 * vw2 * textureSampleCompareLevel(shadowMap, shadowMapSampler, vec2f(u1, v2), z);\\n\\tsum = sum + uw2 * vw2 * textureSampleCompareLevel(shadowMap, shadowMapSampler, vec2f(u2, v2), z);\\n\\tsum = sum * (1.0 / 144.0);\\n\\tsum = saturate(sum);\\n\\treturn sum;\\n}\\nfn getShadowPCF5x5(shadowMap: texture_depth_2d, shadowMapSampler: sampler_comparison, shadowCoord: vec3f, shadowParams: vec4f) -> f32 {\\n\\treturn _getShadowPCF5x5(shadowMap, shadowMapSampler, shadowCoord, shadowParams.xyz);\\n}\\nfn getShadowSpotPCF5x5(shadowMap: texture_depth_2d, shadowMapSampler: sampler_comparison, shadowCoord: vec3f, shadowParams: vec4f) -> f32 {\\n\\treturn _getShadowPCF5x5(shadowMap, shadowMapSampler, shadowCoord, shadowParams.xyz);\\n}\\n`;\\n\\nvar shadowSoft_default = `\\nfn fractSinRand(uv: vec2f) -> f32 {\\n\\tlet PI: f32 = 3.141592653589793;\\n\\tlet a: f32 = 12.9898; let b: f32 = 78.233; let c: f32 = 43758.5453;\\n\\tlet dt: f32 = dot(uv.xy, vec2f(a, b));\\n\\tlet sn: f32 = dt % PI;\\n\\treturn fract(sin(sn) * c);\\n}\\nstruct VogelDiskData {\\n\\tinvNumSamples: f32,\\n\\tinitialAngle: f32,\\n\\tcurrentPointId: f32,\\n}\\nfn prepareDiskConstants(data: ptr<function, VogelDiskData>, sampleCount: i32, randomSeed: f32) {\\n\\tlet pi2: f32 = 6.28318530718;\\n\\tdata.invNumSamples = 1.0 / f32(sampleCount);\\n\\tdata.initialAngle = randomSeed * pi2;\\n\\tdata.currentPointId = 0.0;\\n}\\nfn generateDiskSample(data: ptr<function, VogelDiskData>) -> vec2f {\\n\\tlet GOLDEN_ANGLE: f32 = 2.399963;\\n\\tlet r: f32 = sqrt((data.currentPointId + 0.5) * data.invNumSamples);\\n\\tlet theta: f32 = data.currentPointId * GOLDEN_ANGLE + data.initialAngle;\\n\\tlet offset: vec2f = vec2f(cos(theta), sin(theta)) * pow(r, 1.33);\\n\\tdata.currentPointId = data.currentPointId + 1.0;\\n\\treturn offset;\\n}\\nfn PCSSFindBlocker(shadowMap: texture_2d<f32>, shadowMapSampler: sampler, avgBlockerDepth: ptr<function, f32>, numBlockers: ptr<function, i32>,\\n\\tshadowCoords: vec2f, z: f32, shadowBlockerSamples: i32, penumbraSize: f32, invShadowMapSize: f32, randomSeed: f32) {\\n\\tvar diskData: VogelDiskData;\\n\\tprepareDiskConstants(&diskData, shadowBlockerSamples, randomSeed);\\n\\tlet searchWidth: f32 = penumbraSize * invShadowMapSize;\\n\\tvar blockerSum: f32 = 0.0;\\n\\tvar numBlockers_local: i32 = 0;\\n\\tfor( var i: i32 = 0; i < shadowBlockerSamples; i = i + 1 ) {\\n\\t\\tlet diskUV: vec2f = generateDiskSample(&diskData);\\n\\t\\tlet sampleUV: vec2f = shadowCoords + diskUV * searchWidth;\\n\\t\\tlet shadowMapDepth: f32 = textureSampleLevel(shadowMap, shadowMapSampler, sampleUV, 0.0).r;\\n\\t\\tif ( shadowMapDepth < z ) {\\n\\t\\t\\tblockerSum = blockerSum + shadowMapDepth;\\n\\t\\t\\tnumBlockers_local = numBlockers_local + 1;\\n\\t\\t}\\n\\t}\\n\\t*avgBlockerDepth = blockerSum / f32(numBlockers_local);\\n\\t*numBlockers = numBlockers_local;\\n}\\nfn PCSSFilter(shadowMap: texture_2d<f32>, shadowMapSampler: sampler, uv: vec2f, receiverDepth: f32, shadowSamples: i32, filterRadius: f32, randomSeed: f32) -> f32 {\\n\\tvar diskData: VogelDiskData;\\n\\tprepareDiskConstants(&diskData, shadowSamples, randomSeed);\\n\\tvar sum: f32 = 0.0;\\n\\tfor (var i: i32 = 0; i < shadowSamples; i = i + 1) {\\n\\t\\tlet offsetUV: vec2f = generateDiskSample(&diskData) * filterRadius;\\n\\t\\tlet depth: f32 = textureSampleLevel(shadowMap, shadowMapSampler, uv + offsetUV, 0.0).r;\\n\\t\\tsum = sum + step(receiverDepth, depth);\\n\\t}\\n\\treturn sum / f32(shadowSamples);\\n}\\nfn getPenumbra(dblocker: f32, dreceiver: f32, penumbraSize: f32, penumbraFalloff: f32) -> f32 {\\n\\tlet dist: f32 = dreceiver - dblocker;\\n\\tlet penumbra: f32 = 1.0 - pow(1.0 - dist, penumbraFalloff);\\n\\treturn penumbra * penumbraSize;\\n}\\nfn PCSSDirectional(shadowMap: texture_2d<f32>, shadowMapSampler: sampler, shadowCoords: vec3f, cameraParams: vec4f, softShadowParams: vec4f) -> f32 {\\n\\tlet receiverDepth: f32 = shadowCoords.z;\\n\\tlet randomSeed: f32 = fractSinRand(pcPosition.xy);\\n\\tlet shadowSamples: i32 = i32(softShadowParams.x);\\n\\tlet shadowBlockerSamples: i32 = i32(softShadowParams.y);\\n\\tlet penumbraSize: f32 = softShadowParams.z;\\n\\tlet penumbraFalloff: f32 = softShadowParams.w;\\n\\tlet shadowMapSize: i32 = i32(textureDimensions(shadowMap, 0).x);\\n\\tvar invShadowMapSize: f32 = 1.0 / f32(shadowMapSize);\\n\\tinvShadowMapSize = invShadowMapSize * (f32(shadowMapSize) / 2048.0);\\n\\tvar penumbra: f32;\\n\\tif (shadowBlockerSamples > 0) {\\n\\t\\tvar avgBlockerDepth: f32 = 0.0;\\n\\t\\tvar numBlockers: i32 = 0;\\n\\t\\tPCSSFindBlocker(shadowMap, shadowMapSampler, &avgBlockerDepth, &numBlockers, shadowCoords.xy, receiverDepth, shadowBlockerSamples, penumbraSize, invShadowMapSize, randomSeed);\\n\\t\\tif (numBlockers < 1) {\\n\\t\\t\\treturn 1.0;\\n\\t\\t}\\n\\t\\tpenumbra = getPenumbra(avgBlockerDepth, shadowCoords.z, penumbraSize, penumbraFalloff);\\n\\t} else {\\n\\t\\tpenumbra = penumbraSize;\\n\\t}\\n\\tlet filterRadius: f32 = penumbra * invShadowMapSize;\\n\\treturn PCSSFilter(shadowMap, shadowMapSampler, shadowCoords.xy, receiverDepth, shadowSamples, filterRadius, randomSeed);\\n}\\nfn getShadowPCSS(shadowMap: texture_2d<f32>, shadowMapSampler: sampler, shadowCoord: vec3f, shadowParams: vec4f, cameraParams: vec4f, softShadowParams: vec4f, lightDir: vec3f) -> f32 {\\n\\treturn PCSSDirectional(shadowMap, shadowMapSampler, shadowCoord, cameraParams, softShadowParams);\\n}\\n`;\\n\\nvar skinBatch_default = `\\nattribute vertex_boneIndices: f32;\\nvar texture_poseMap: texture_2d<uff>;\\nfn getBoneMatrix(indexFloat: f32) -> mat4x4f {\\n\\tlet width = i32(textureDimensions(texture_poseMap).x);\\n\\tlet index: i32 = i32(indexFloat + 0.5) * 3;\\n\\tlet iy: i32 = index / width;\\n\\tlet ix: i32 = index % width;\\n\\tlet v1: vec4f = textureLoad(texture_poseMap, vec2i(ix + 0, iy), 0);\\n\\tlet v2: vec4f = textureLoad(texture_poseMap, vec2i(ix + 1, iy), 0);\\n\\tlet v3: vec4f = textureLoad(texture_poseMap, vec2i(ix + 2, iy), 0);\\n\\treturn mat4x4f(\\n\\t\\tv1.x, v2.x, v3.x, 0,\\n\\t\\tv1.y, v2.y, v3.y, 0,\\n\\t\\tv1.z, v2.z, v3.z, 0,\\n\\t\\tv1.w, v2.w, v3.w, 1.0\\n\\t);\\n}\\n`;\\n\\nvar skin_default = `\\nattribute vertex_boneWeights: vec4f;\\nattribute vertex_boneIndices: vec4f;\\nvar texture_poseMap: texture_2d<uff>;\\nstruct BoneMatrix {\\n\\tv1: vec4f,\\n\\tv2: vec4f,\\n\\tv3: vec4f,\\n}\\nfn getBoneMatrix(width: i32, index: i32) -> BoneMatrix {\\n\\tlet v = index / width;\\n\\tlet u = index % width;\\n\\tvar result: BoneMatrix;\\n\\tresult.v1 = textureLoad(texture_poseMap, vec2i(u + 0, v), 0);\\n\\tresult.v2 = textureLoad(texture_poseMap, vec2i(u + 1, v), 0);\\n\\tresult.v3 = textureLoad(texture_poseMap, vec2i(u + 2, v), 0);\\n\\treturn result;\\n}\\nfn getSkinMatrix(indicesFloat: vec4f, weights: vec4f) -> mat4x4f {\\n\\tlet width = i32(textureDimensions(texture_poseMap).x);\\n\\tvar indices = vec4i(indicesFloat + 0.5) * 3;\\n\\tlet boneA = getBoneMatrix(width, indices.x);\\n\\tlet boneB = getBoneMatrix(width, indices.y);\\n\\tlet boneC = getBoneMatrix(width, indices.z);\\n\\tlet boneD = getBoneMatrix(width, indices.w);\\n\\tlet v1 = boneA.v1 * weights.x + boneB.v1 * weights.y + boneC.v1 * weights.z + boneD.v1 * weights.w;\\n\\tlet v2 = boneA.v2 * weights.x + boneB.v2 * weights.y + boneC.v2 * weights.z + boneD.v2 * weights.w;\\n\\tlet v3 = boneA.v3 * weights.x + boneB.v3 * weights.y + boneC.v3 * weights.z + boneD.v3 * weights.w;\\n\\tlet one = dot(weights, vec4f(1.0, 1.0, 1.0, 1.0));\\n\\treturn mat4x4f(\\n\\t\\tv1.x, v2.x, v3.x, 0,\\n\\t\\tv1.y, v2.y, v3.y, 0,\\n\\t\\tv1.z, v2.z, v3.z, 0,\\n\\t\\tv1.w, v2.w, v3.w, one\\n\\t);\\n}\\n`;\\n\\nvar skybox_default$1 = `\\n\\t#define LIT_SKYBOX_INTENSITY\\n\\t#include \\\"envProcPS\\\"\\n\\t#include \\\"gammaPS\\\"\\n\\t#include \\\"tonemappingPS\\\"\\n\\t#ifdef PREPASS_PASS\\n\\t\\tvarying vLinearDepth: f32;\\n\\t\\t#include \\\"floatAsUintPS\\\"\\n\\t#endif\\n\\tvarying vViewDir : vec3f;\\n\\tuniform skyboxHighlightMultiplier : f32;\\n\\t#if defined(SKY_FISHEYE) && !defined(SKYMESH)\\n\\t\\tuniform fisheye_k : f32;\\n\\t\\tuniform fisheye_invK : f32;\\n\\t\\tuniform fisheye_projMat00 : f32;\\n\\t\\tuniform fisheye_projMat11 : f32;\\n\\t\\tuniform matrix_view : mat4x4f;\\n\\t\\tuniform cubeMapRotationMatrix : mat3x3f;\\n\\t\\tvarying vClipXYW : vec3f;\\n\\t#endif\\n\\t#ifdef SKY_CUBEMAP\\n\\t\\tvar texture_cubeMap : texture_cube<f32>;\\n\\t\\tvar texture_cubeMap_sampler : sampler;\\n\\t\\t#ifdef SKYMESH\\n\\t\\t\\tvarying vWorldPos : vec3f;\\n\\t\\t\\tuniform cubeMapRotationMatrix : mat3x3f;\\n\\t\\t\\tuniform projectedSkydomeCenter : vec3f;\\n\\t\\t#endif\\n\\t#else\\n\\t\\t#include \\\"sphericalPS\\\"\\n\\t\\t#include \\\"envAtlasPS\\\"\\n\\t\\tvar texture_envAtlas : texture_2d<f32>;\\n\\t\\tvar texture_envAtlas_sampler : sampler;\\n\\t\\tuniform mipLevel : f32;\\n\\t#endif\\n\\t@fragment\\n\\tfn fragmentMain(input : FragmentInput) -> FragmentOutput {\\n\\t\\tvar output: FragmentOutput;\\n\\t\\t#ifdef PREPASS_PASS\\n\\t\\t\\toutput.color = float2vec4(vLinearDepth);\\n\\t\\t#else\\n\\t\\t\\tvar linear : vec3f;\\n\\t\\t\\tvar dir : vec3f;\\n\\t\\t\\t#if defined(SKY_FISHEYE) && !defined(SKYMESH)\\n\\t\\t\\t\\tlet ndc : vec2f = input.vClipXYW.xy / input.vClipXYW.z;\\n\\t\\t\\t\\tlet px : f32 = ndc.x / uniform.fisheye_projMat00;\\n\\t\\t\\t\\tlet py : f32 = ndc.y / uniform.fisheye_projMat11;\\n\\t\\t\\t\\tlet r : f32 = sqrt(px * px + py * py);\\n\\t\\t\\t\\tlet theta : f32 = uniform.fisheye_k * atan(r * uniform.fisheye_invK);\\n\\t\\t\\t\\tlet sinT : f32 = sin(theta);\\n\\t\\t\\t\\tlet cosT : f32 = cos(theta);\\n\\t\\t\\t\\tvar camDir : vec3f;\\n\\t\\t\\t\\tif (r > 1e-6) {\\n\\t\\t\\t\\t\\tcamDir = vec3f(px / r * sinT, py / r * sinT, -cosT);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tcamDir = vec3f(0.0, 0.0, -1.0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet viewMat3 : mat3x3f = mat3x3f(\\n\\t\\t\\t\\t\\tuniform.matrix_view[0].xyz,\\n\\t\\t\\t\\t\\tuniform.matrix_view[1].xyz,\\n\\t\\t\\t\\t\\tuniform.matrix_view[2].xyz\\n\\t\\t\\t\\t);\\n\\t\\t\\t\\tdir = transpose(viewMat3) * camDir;\\n\\t\\t\\t\\tdir = dir * uniform.cubeMapRotationMatrix;\\n\\t\\t\\t#elif defined(SKY_CUBEMAP) && defined(SKYMESH)\\n\\t\\t\\t\\tvar envDir : vec3f = normalize(input.vWorldPos - uniform.projectedSkydomeCenter);\\n\\t\\t\\t\\tdir = envDir * uniform.cubeMapRotationMatrix;\\n\\t\\t\\t#else\\n\\t\\t\\t\\tdir = input.vViewDir;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef SKY_CUBEMAP\\n\\t\\t\\t\\tdir.x *= -1.0;\\n\\t\\t\\t\\tlinear = {SKYBOX_DECODE_FNC}(textureSample(texture_cubeMap, texture_cubeMap_sampler, dir));\\n\\t\\t\\t#else\\n\\t\\t\\t\\tdir *= vec3f(-1.0, 1.0, 1.0);\\n\\t\\t\\t\\tlet uv : vec2f = toSphericalUv(normalize(dir));\\n\\t\\t\\t\\tlinear = {SKYBOX_DECODE_FNC}(textureSample(texture_envAtlas, texture_envAtlas_sampler, mapRoughnessUv(uv, uniform.mipLevel)));\\n\\t\\t\\t#endif\\n\\t\\t\\tif (any(linear >= vec3f(64.0))) {\\n\\t\\t\\t\\tlinear *= uniform.skyboxHighlightMultiplier;\\n\\t\\t\\t}\\n\\t\\t\\t\\n\\t\\t\\toutput.color = vec4f(gammaCorrectOutput(toneMap(processEnvironment(linear))), 1.0);\\n\\t\\t#endif\\n\\t\\treturn output;\\n\\t}\\n`;\\n\\nvar skybox_default = `\\n\\tattribute aPosition : vec4f;\\n\\tuniform matrix_view : mat4x4f;\\n\\tuniform matrix_projectionSkybox : mat4x4f;\\n\\tuniform cubeMapRotationMatrix : mat3x3f;\\n\\tvarying vViewDir : vec3f;\\n\\t#ifdef SKY_FISHEYE\\n\\t\\tvarying vClipXYW : vec3f;\\n\\t#endif\\n\\t#ifdef PREPASS_PASS\\n\\t\\tvarying vLinearDepth: f32;\\n\\t#endif\\n\\t#ifdef SKYMESH\\n\\t\\tuniform matrix_model : mat4x4f;\\n\\t\\tvarying vWorldPos : vec3f;\\n\\t#endif\\n\\t@vertex\\n\\tfn vertexMain(input : VertexInput) -> VertexOutput {\\n\\t\\tvar output : VertexOutput;\\n\\t\\tvar view : mat4x4f = uniform.matrix_view;\\n\\t\\t#ifdef SKYMESH\\n\\t\\t\\tvar worldPos : vec4f = uniform.matrix_model * input.aPosition;\\n\\t\\t\\toutput.vWorldPos = worldPos.xyz;\\n\\t\\t\\toutput.position = uniform.matrix_projectionSkybox * (view * worldPos);\\n\\t\\t\\t#ifdef PREPASS_PASS\\n\\t\\t\\t\\toutput.vLinearDepth = -(uniform.matrix_view * vec4f(worldPos.xyz, 1.0)).z;\\n\\t\\t\\t#endif\\n\\t\\t#else\\n\\t\\t\\tview[3][0] = 0.0;\\n\\t\\t\\tview[3][1] = 0.0;\\n\\t\\t\\tview[3][2] = 0.0;\\n\\t\\t\\toutput.vViewDir = input.aPosition.xyz * uniform.cubeMapRotationMatrix;\\n\\t\\t\\t#ifdef SKY_FISHEYE\\n\\t\\t\\t\\tvar viewPos : vec4f = view * input.aPosition;\\n\\t\\t\\t\\toutput.position = vec4f(viewPos.xy, 0.0, -viewPos.z);\\n\\t\\t\\t\\toutput.vClipXYW = vec3f(output.position.xy, output.position.w);\\n\\t\\t\\t#else\\n\\t\\t\\t\\toutput.position = uniform.matrix_projectionSkybox * (view * input.aPosition);\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef PREPASS_PASS\\n\\t\\t\\t\\toutput.vLinearDepth = -pcPosition.w;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\toutput.position.z = output.position.w - 1.0e-7;\\n\\t\\treturn output;\\n\\t}\\n`;\\n\\nvar sort_indirect_args_default = `\\nfn writeSortIndirectArgs(\\n\\tbaseSlot: u32,\\n\\tcount: u32,\\n\\tslotInfo: vec4<u32>\\n) {\\n\\tlet n = slotInfo.x;\\n\\tif (n >= 1u) {\\n\\t\\tlet g = slotInfo.y;\\n\\t\\tlet wc = (count + g - 1u) / g;\\n\\t\\tlet off = baseSlot * 3u;\\n\\t\\tindirectDispatchArgs[off + 0u] = wc;\\n\\t\\tindirectDispatchArgs[off + 1u] = 1u;\\n\\t\\tindirectDispatchArgs[off + 2u] = 1u;\\n\\t}\\n\\tif (n >= 2u) {\\n\\t\\tlet g = slotInfo.z;\\n\\t\\tlet wc = (count + g - 1u) / g;\\n\\t\\tlet off = (baseSlot + 1u) * 3u;\\n\\t\\tindirectDispatchArgs[off + 0u] = wc;\\n\\t\\tindirectDispatchArgs[off + 1u] = 1u;\\n\\t\\tindirectDispatchArgs[off + 2u] = 1u;\\n\\t}\\n\\tif (n >= 3u) {\\n\\t\\tlet g = slotInfo.w;\\n\\t\\tlet wc = (count + g - 1u) / g;\\n\\t\\tlet off = (baseSlot + 2u) * 3u;\\n\\t\\tindirectDispatchArgs[off + 0u] = wc;\\n\\t\\tindirectDispatchArgs[off + 1u] = 1u;\\n\\t\\tindirectDispatchArgs[off + 2u] = 1u;\\n\\t}\\n}\\n`;\\n\\nvar specular_default = `\\n#ifdef STD_SPECULAR_CONSTANT\\n\\tuniform material_specular: vec3f;\\n#endif\\nfn getSpecularity() {\\n\\tvar specularColor = vec3f(1.0, 1.0, 1.0);\\n\\t#ifdef STD_SPECULAR_CONSTANT\\n\\tspecularColor = specularColor * uniform.material_specular;\\n\\t#endif\\n\\t#ifdef STD_SPECULAR_TEXTURE\\n\\tspecularColor = specularColor * {STD_SPECULAR_TEXTURE_DECODE}(textureSampleBias({STD_SPECULAR_TEXTURE_NAME}, {STD_SPECULAR_TEXTURE_NAME}Sampler, {STD_SPECULAR_TEXTURE_UV}, uniform.textureBias)).{STD_SPECULAR_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_SPECULAR_VERTEX\\n\\tspecularColor = specularColor * saturate3(vVertexColor.{STD_SPECULAR_VERTEX_CHANNEL});\\n\\t#endif\\n\\tdSpecularity = specularColor;\\n}\\n`;\\n\\nvar spherical_default = `\\nfn toSpherical(dir: vec3f) -> vec2f {\\n\\tlet angle_xz = select(0.0, atan2(dir.x, dir.z), any(dir.xz != vec2f(0.0)));\\n\\treturn vec2f(angle_xz, asin(dir.y));\\n}\\nfn toSphericalUv(dir : vec3f) -> vec2f {\\n\\tconst PI : f32 = 3.141592653589793;\\n\\tlet uv : vec2f = toSpherical(dir) / vec2f(PI * 2.0, PI) + vec2f(0.5, 0.5);\\n\\treturn vec2f(uv.x, 1.0 - uv.y);\\n}\\n`;\\n\\nvar specularityFactor_default = `\\n#ifdef STD_SPECULARITYFACTOR_CONSTANT\\n\\tuniform material_specularityFactor: f32;\\n#endif\\nfn getSpecularityFactor() {\\n\\tvar specularityFactor = 1.0;\\n\\t#ifdef STD_SPECULARITYFACTOR_CONSTANT\\n\\tspecularityFactor = specularityFactor * uniform.material_specularityFactor;\\n\\t#endif\\n\\t#ifdef STD_SPECULARITYFACTOR_TEXTURE\\n\\tspecularityFactor = specularityFactor * textureSampleBias({STD_SPECULARITYFACTOR_TEXTURE_NAME}, {STD_SPECULARITYFACTOR_TEXTURE_NAME}Sampler, {STD_SPECULARITYFACTOR_TEXTURE_UV}, uniform.textureBias).{STD_SPECULARITYFACTOR_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_SPECULARITYFACTOR_VERTEX\\n\\tspecularityFactor = specularityFactor * saturate(vVertexColor.{STD_SPECULARITYFACTOR_VERTEX_CHANNEL});\\n\\t#endif\\n\\tdSpecularityFactor = specularityFactor;\\n}\\n`;\\n\\nvar spot_default = `\\nfn getSpotEffect(lightSpotDir: vec3f, lightInnerConeAngle: f32, lightOuterConeAngle: f32, lightDirNorm: vec3f) -> f32 {\\n\\tlet cosAngle: f32 = dot(lightDirNorm, lightSpotDir);\\n\\treturn smoothstep(lightOuterConeAngle, lightInnerConeAngle, cosAngle);\\n}`;\\n\\nvar startNineSliced_default = `\\n\\tnineSlicedUv = vec2f(vUv0.x, 1.0 - vUv0.y);\\n`;\\n\\nvar startNineSlicedTiled_default = `\\n\\tlet tileMask: vec2f = step(vMask, vec2f(0.99999));\\n\\tlet tileSize: vec2f = 0.5 * (innerOffset.xy + innerOffset.zw);\\n\\tlet tileScale: vec2f = vec2f(1.0) / (vec2f(1.0) - tileSize);\\n\\tvar clampedUv: vec2f = mix(innerOffset.xy * 0.5, vec2f(1.0) - innerOffset.zw * 0.5, fract((vTiledUv - tileSize) * tileScale));\\n\\tclampedUv = clampedUv * atlasRect.zw + atlasRect.xy;\\n\\tvar nineSlicedUv: vec2f = vUv0 * tileMask + clampedUv * (vec2f(1.0) - tileMask);\\n\\tnineSlicedUv.y = 1.0 - nineSlicedUv.y;\\n`;\\n\\nvar stdDeclaration_default = `\\n\\tvar<private> dAlpha: f32 = 1.0;\\n\\t#if LIT_BLEND_TYPE != NONE || defined(LIT_ALPHA_TEST) || defined(LIT_ALPHA_TO_COVERAGE) || STD_OPACITY_DITHER != NONE\\n\\t\\t#ifdef STD_OPACITY_TEXTURE_ALLOCATE\\n\\t\\t\\tvar texture_opacityMap : texture_2d<f32>;\\n\\t\\t\\tvar texture_opacityMapSampler : sampler;\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef FORWARD_PASS\\n\\t\\tvar<private> dAlbedo: vec3f;\\n\\t\\tvar<private> dNormalW: vec3f;\\n\\t\\tvar<private> dSpecularity: vec3f = vec3f(0.0, 0.0, 0.0);\\n\\t\\tvar<private> dGlossiness: f32 = 0.0;\\n\\t\\t#ifdef LIT_REFRACTION\\n\\t\\t\\tvar<private> dTransmission: f32;\\n\\t\\t\\tvar<private> dThickness: f32;\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_SCENE_COLOR\\n\\t\\t\\tvar uSceneColorMap : texture_2d<f32>;\\n\\t\\t\\tvar uSceneColorMapSampler : sampler;\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_SCREEN_SIZE\\n\\t\\t\\tuniform uScreenSize: vec4f;\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_TRANSFORMS\\n\\t\\t\\tvar<private> matrix_viewProjection: mat4x4f;\\n\\t\\t\\tvar<private> matrix_model: mat4x4f;\\n\\t\\t#endif\\n\\t\\t#ifdef STD_HEIGHT_MAP\\n\\t\\t\\tvar<private> dUvOffset: vec2f;\\n\\t\\t\\t#ifdef STD_HEIGHT_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tvar texture_heightMap : texture_2d<f32>;\\n\\t\\t\\t\\tvar texture_heightMapSampler : sampler;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#ifdef STD_DIFFUSE_TEXTURE_ALLOCATE\\n\\t\\t\\tvar texture_diffuseMap : texture_2d<f32>;\\n\\t\\t\\tvar texture_diffuseMapSampler : sampler;\\n\\t\\t#endif\\n\\t\\t#ifdef STD_DIFFUSEDETAIL_TEXTURE_ALLOCATE\\n\\t\\t\\tvar texture_diffuseDetailMap : texture_2d<f32>;\\n\\t\\t\\tvar texture_diffuseDetailMapSampler : sampler;\\n\\t\\t#endif\\n\\t\\t#ifdef STD_NORMAL_TEXTURE_ALLOCATE\\n\\t\\t\\tvar texture_normalMap : texture_2d<f32>;\\n\\t\\t\\tvar texture_normalMapSampler : sampler;\\n\\t\\t#endif\\n\\t\\t#ifdef STD_NORMALDETAIL_TEXTURE_ALLOCATE\\n\\t\\t\\tvar texture_normalDetailMap : texture_2d<f32>;\\n\\t\\t\\tvar texture_normalDetailMapSampler : sampler;\\n\\t\\t#endif\\n\\t\\t#ifdef STD_THICKNESS_TEXTURE_ALLOCATE\\n\\t\\t\\tvar texture_thicknessMap : texture_2d<f32>;\\n\\t\\t\\tvar texture_thicknessMapSampler : sampler;\\n\\t\\t#endif\\n\\t\\t#ifdef STD_REFRACTION_TEXTURE_ALLOCATE\\n\\t\\t\\tvar texture_refractionMap : texture_2d<f32>;\\n\\t\\t\\tvar texture_refractionMapSampler : sampler;\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_IRIDESCENCE\\n\\t\\t\\tvar<private> dIridescence: f32;\\n\\t\\t\\tvar<private> dIridescenceThickness: f32;\\n\\t\\t\\t#ifdef STD_IRIDESCENCE_THICKNESS_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tvar texture_iridescenceThicknessMap : texture_2d<f32>;\\n\\t\\t\\t\\tvar texture_iridescenceThicknessMapSampler : sampler;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef STD_IRIDESCENCE_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tvar texture_iridescenceMap : texture_2d<f32>;\\n\\t\\t\\t\\tvar texture_iridescenceMapSampler : sampler;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\tvar<private> ccSpecularity: f32;\\n\\t\\t\\tvar<private> ccGlossiness: f32;\\n\\t\\t\\tvar<private> ccNormalW: vec3f;\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_GGX_SPECULAR\\n\\t\\t\\tvar<private> dAnisotropy: f32;\\n\\t\\t\\tvar<private> dAnisotropyRotation: vec2f;\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_SPECULAR_OR_REFLECTION\\n\\t\\t\\t#ifdef LIT_SHEEN\\n\\t\\t\\t\\tvar<private> sSpecularity: vec3f;\\n\\t\\t\\t\\tvar<private> sGlossiness: f32;\\n\\t\\t\\t\\t#ifdef STD_SHEEN_TEXTURE_ALLOCATE\\n\\t\\t\\t\\t\\tvar texture_sheenMap : texture_2d<f32>;\\n\\t\\t\\t\\t\\tvar texture_sheenMapSampler : sampler;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#ifdef STD_SHEENGLOSS_TEXTURE_ALLOCATE\\n\\t\\t\\t\\t\\tvar texture_sheenGlossMap : texture_2d<f32>;\\n\\t\\t\\t\\t\\tvar texture_sheenGlossMapSampler : sampler;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_METALNESS\\n\\t\\t\\t\\tvar<private> dMetalness: f32;\\n\\t\\t\\t\\tvar<private> dIor: f32;\\n\\t\\t\\t\\t#ifdef STD_METALNESS_TEXTURE_ALLOCATE\\n\\t\\t\\t\\t\\tvar texture_metalnessMap : texture_2d<f32>;\\n\\t\\t\\t\\t\\tvar texture_metalnessMapSampler : sampler;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SPECULARITY_FACTOR\\n\\t\\t\\t\\tvar<private> dSpecularityFactor: f32;\\n\\t\\t\\t\\t#ifdef STD_SPECULARITYFACTOR_TEXTURE_ALLOCATE\\n\\t\\t\\t\\t\\tvar texture_specularityFactorMap : texture_2d<f32>;\\n\\t\\t\\t\\t\\tvar texture_specularityFactorMapSampler : sampler;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef STD_SPECULAR_COLOR\\n\\t\\t\\t\\t#ifdef STD_SPECULAR_TEXTURE_ALLOCATE\\n\\t\\t\\t\\t\\tvar texture_specularMap : texture_2d<f32>;\\n\\t\\t\\t\\t\\tvar texture_specularMapSampler : sampler;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef STD_GLOSS_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tvar texture_glossMap : texture_2d<f32>;\\n\\t\\t\\t\\tvar texture_glossMapSampler : sampler;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#ifdef STD_AO\\n\\t\\t\\tvar <private> dAo: f32;\\n\\t\\t\\t#ifdef STD_AO_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tvar texture_aoMap : texture_2d<f32>;\\n\\t\\t\\t\\tvar texture_aoMapSampler : sampler;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef STD_AODETAIL_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tvar texture_aoDetailMap : texture_2d<f32>;\\n\\t\\t\\t\\tvar texture_aoDetailMapSampler : sampler;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\tvar <private> dEmission: vec3f;\\n\\t\\t#ifdef STD_EMISSIVE_TEXTURE_ALLOCATE\\n\\t\\t\\tvar texture_emissiveMap : texture_2d<f32>;\\n\\t\\t\\tvar texture_emissiveMapSampler : sampler;\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t#ifdef STD_CLEARCOAT_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tvar texture_clearCoatMap : texture_2d<f32>;\\n\\t\\t\\t\\tvar texture_clearCoatMapSampler : sampler;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef STD_CLEARCOATGLOSS_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tvar texture_clearCoatGlossMap : texture_2d<f32>;\\n\\t\\t\\t\\tvar texture_clearCoatGlossMapSampler : sampler;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef STD_CLEARCOATNORMAL_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tvar texture_clearCoatNormalMap : texture_2d<f32>;\\n\\t\\t\\t\\tvar texture_clearCoatNormalMapSampler : sampler;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_GGX_SPECULAR\\n\\t\\t\\t#ifdef STD_ANISOTROPY_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tvar texture_anisotropyMap : texture_2d<f32>;\\n\\t\\t\\t\\tvar texture_anisotropyMapSampler : sampler;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\t#if defined(STD_LIGHTMAP) || defined(STD_LIGHT_VERTEX_COLOR)\\n\\t\\t\\tvar<private> dLightmap: vec3f;\\n\\t\\t\\t#ifdef STD_LIGHT_TEXTURE_ALLOCATE\\n\\t\\t\\t\\tvar texture_lightMap : texture_2d<f32>;\\n\\t\\t\\t\\tvar texture_lightMapSampler : sampler;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t#endif\\n\\t#include \\\"litShaderCorePS\\\"\\n`;\\n\\nvar stdFrontEnd_default = `\\n\\t#if LIT_BLEND_TYPE != NONE || defined(LIT_ALPHA_TEST) || defined(LIT_ALPHA_TO_COVERAGE) || STD_OPACITY_DITHER != NONE\\n\\t\\t#include \\\"opacityPS\\\"\\n\\t\\t#if defined(LIT_ALPHA_TEST)\\n\\t\\t\\t#include \\\"alphaTestPS\\\"\\n\\t\\t#endif\\n\\t\\t#if STD_OPACITY_DITHER != NONE\\n\\t\\t\\t#include \\\"opacityDitherPS\\\"\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef FORWARD_PASS\\n\\t\\t#ifdef STD_HEIGHT_MAP\\n\\t\\t\\t#include \\\"parallaxPS\\\"\\n\\t\\t#endif\\n\\t\\t#include  \\\"diffusePS\\\"\\n\\t\\t#ifdef LIT_NEEDS_NORMAL\\n\\t\\t\\t#include \\\"normalMapPS\\\"\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_REFRACTION\\n\\t\\t\\t#include \\\"transmissionPS\\\"\\n\\t\\t\\t#include \\\"thicknessPS\\\"\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_IRIDESCENCE\\n\\t\\t\\t#include \\\"iridescencePS\\\"\\n\\t\\t\\t#include \\\"iridescenceThicknessPS\\\"\\n\\t\\t#endif\\n\\t\\t#ifdef LIT_SPECULAR_OR_REFLECTION\\n\\t\\t\\t#ifdef LIT_SHEEN\\n\\t\\t\\t\\t#include \\\"sheenPS\\\"\\n\\t\\t\\t\\t#include \\\"sheenGlossPS\\\"\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_METALNESS\\n\\t\\t\\t\\t#include \\\"metalnessPS\\\"\\n\\t\\t\\t\\t#include \\\"iorPS\\\"\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SPECULARITY_FACTOR\\n\\t\\t\\t\\t#include \\\"specularityFactorPS\\\"\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef STD_SPECULAR_COLOR\\n\\t\\t\\t\\t#include \\\"specularPS\\\"\\n\\t\\t\\t#else\\n\\t\\t\\t\\tfn getSpecularity() { \\n\\t\\t\\t\\t\\tdSpecularity = vec3f(1.0, 1.0, 1.0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t#endif\\n\\t\\t\\t#include \\\"glossPS\\\"\\n\\t\\t#endif\\n\\t\\t#ifdef STD_AO\\n\\t\\t\\t#include \\\"aoPS\\\"\\n\\t\\t#endif\\n\\t\\t#include \\\"emissivePS\\\"\\n\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t#include \\\"clearCoatPS\\\"\\n\\t\\t\\t#include \\\"clearCoatGlossPS\\\"\\n\\t\\t\\t#include \\\"clearCoatNormalPS\\\"\\n\\t\\t#endif\\n\\t\\t#if defined(LIT_SPECULAR) && defined(LIT_LIGHTING) && defined(LIT_GGX_SPECULAR)\\n\\t\\t\\t#include \\\"anisotropyPS\\\"\\n\\t\\t#endif\\n\\t\\t#if defined(STD_LIGHTMAP) || defined(STD_LIGHT_VERTEX_COLOR)\\n\\t\\t\\t#include \\\"lightmapPS\\\"\\n\\t\\t#endif\\n\\t#endif\\n\\tfn evaluateFrontend() {\\n\\t\\t#if LIT_BLEND_TYPE != NONE || defined(LIT_ALPHA_TEST) || defined(LIT_ALPHA_TO_COVERAGE) || STD_OPACITY_DITHER != NONE\\n\\t\\t\\tgetOpacity();\\n\\t\\t\\t#if defined(LIT_ALPHA_TEST)\\n\\t\\t\\t\\talphaTest(dAlpha);\\n\\t\\t\\t#endif\\n\\t\\t\\t#if STD_OPACITY_DITHER != NONE\\n\\t\\t\\t\\topacityDither(dAlpha * uniform.material_alphaDitherScale, 0.0);\\n\\t\\t\\t#endif\\n\\t\\t\\tlitArgs_opacity = dAlpha;\\n\\t\\t#endif\\n\\t\\t#ifdef FORWARD_PASS\\n\\t\\t\\t#ifdef STD_HEIGHT_MAP\\n\\t\\t\\t\\tgetParallax();\\n\\t\\t\\t#endif\\n\\t\\t\\tgetAlbedo();\\n\\t\\t\\tlitArgs_albedo = dAlbedo;\\n\\t\\t\\t#ifdef LIT_NEEDS_NORMAL\\n\\t\\t\\t\\tgetNormal();\\n\\t\\t\\t\\tlitArgs_worldNormal = dNormalW;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_REFRACTION\\n\\t\\t\\t\\tgetRefraction();\\n\\t\\t\\t\\tlitArgs_transmission = dTransmission;\\n\\t\\t\\t\\tgetThickness();\\n\\t\\t\\t\\tlitArgs_thickness = dThickness;\\n\\t\\t\\t\\t#ifdef LIT_DISPERSION\\n\\t\\t\\t\\t\\tlitArgs_dispersion = uniform.material_dispersion;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_IRIDESCENCE\\n\\t\\t\\t\\tgetIridescence();\\n\\t\\t\\t\\tgetIridescenceThickness();\\n\\t\\t\\t\\tlitArgs_iridescence_intensity = dIridescence;\\n\\t\\t\\t\\tlitArgs_iridescence_thickness = dIridescenceThickness;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef LIT_SPECULAR_OR_REFLECTION\\n\\t\\t\\t\\t#ifdef LIT_SHEEN\\n\\t\\t\\t\\t\\tgetSheen();\\n\\t\\t\\t\\t\\tlitArgs_sheen_specularity = sSpecularity;\\n\\t\\t\\t\\t\\tgetSheenGlossiness();\\n\\t\\t\\t\\t\\tlitArgs_sheen_gloss = sGlossiness;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#ifdef LIT_METALNESS\\n\\t\\t\\t\\t\\tgetMetalness();\\n\\t\\t\\t\\t\\tlitArgs_metalness = dMetalness;\\n\\t\\t\\t\\t\\tgetIor();\\n\\t\\t\\t\\t\\tlitArgs_ior = dIor;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#ifdef LIT_SPECULARITY_FACTOR\\n\\t\\t\\t\\t\\tgetSpecularityFactor();\\n\\t\\t\\t\\t\\tlitArgs_specularityFactor = dSpecularityFactor;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\tgetGlossiness();\\n\\t\\t\\t\\tgetSpecularity();\\n\\t\\t\\t\\tlitArgs_specularity = dSpecularity;\\n\\t\\t\\t\\tlitArgs_gloss = dGlossiness;\\n\\t\\t\\t#endif\\n\\t\\t\\t#ifdef STD_AO\\n\\t\\t\\t\\tgetAO();\\n\\t\\t\\t\\tlitArgs_ao = dAo;\\n\\t\\t\\t#endif\\n\\t\\t\\tgetEmission();\\n\\t\\t\\tlitArgs_emission = dEmission;\\n\\t\\t\\t#ifdef LIT_CLEARCOAT\\n\\t\\t\\t\\tgetClearCoat();\\n\\t\\t\\t\\tgetClearCoatGlossiness();\\n\\t\\t\\t\\tgetClearCoatNormal();\\n\\t\\t\\t\\tlitArgs_clearcoat_specularity = ccSpecularity;\\n\\t\\t\\t\\tlitArgs_clearcoat_gloss = ccGlossiness;\\n\\t\\t\\t\\tlitArgs_clearcoat_worldNormal = ccNormalW;\\n\\t\\t\\t#endif\\n\\t\\t\\t#if defined(LIT_SPECULAR) && defined(LIT_LIGHTING) && defined(LIT_GGX_SPECULAR)\\n\\t\\t\\t\\tgetAnisotropy();\\n\\t\\t\\t#endif\\n\\t\\t\\t#if defined(STD_LIGHTMAP) || defined(STD_LIGHT_VERTEX_COLOR)\\n\\t\\t\\t\\tgetLightMap();\\n\\t\\t\\t\\tlitArgs_lightmap = dLightmap;\\n\\t\\t\\t\\t#ifdef STD_LIGHTMAP_DIR\\n\\t\\t\\t\\t\\tlitArgs_lightmapDir = dLightmapDir;\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t}\\n`;\\n\\nvar TBN_default = `\\n#ifdef LIT_TANGENTS\\n\\t#define TBN_TANGENTS\\n#else\\n\\t#if defined(LIT_USE_NORMALS) || defined(LIT_USE_CLEARCOAT_NORMALS)\\n\\t\\t#define TBN_DERIVATIVES\\n\\t#endif\\n#endif\\n#if defined(TBN_DERIVATIVES)\\n\\tuniform tbnBasis: f32;\\n#endif\\nfn getTBN(tangent: vec3f, binormal: vec3f, normal: vec3f) {\\n\\t#ifdef TBN_TANGENTS\\n\\t\\tdTBN = mat3x3f(normalize(tangent), normalize(binormal), normalize(normal));\\n\\t#elif defined(TBN_DERIVATIVES)\\n\\t\\tlet uv: vec2f = {lightingUv};\\n\\t\\tlet dp1: vec3f = dpdx( vPositionW );\\n\\t\\tlet dp2: vec3f = dpdy( vPositionW );\\n\\t\\tlet duv1: vec2f = dpdx( uv );\\n\\t\\tlet duv2: vec2f = dpdy( uv );\\n\\t\\tlet dp2perp: vec3f = cross( dp2, normal );\\n\\t\\tlet dp1perp: vec3f = cross( normal, dp1 );\\n\\t\\tlet T: vec3f = dp2perp * duv1.x + dp1perp * duv2.x;\\n\\t\\tlet B: vec3f = dp2perp * duv1.y + dp1perp * duv2.y;\\n\\t\\tlet denom: f32 = max( dot(T, T), dot(B, B) );\\n\\t\\tlet invmax: f32 = select(uniform.tbnBasis / sqrt( denom ), 0.0, denom == 0.0);\\n\\t\\tdTBN = mat3x3f(T * invmax, -B * invmax, normal );\\n\\t#else\\n\\t\\tvar B: vec3f = cross(normal, vObjectSpaceUpW);\\n\\t\\tvar T: vec3f = cross(normal, B);\\n\\t\\tif (dot(B,B) == 0.0)\\n\\t\\t{\\n\\t\\t\\tlet major: f32 = max(max(normal.x, normal.y), normal.z);\\n\\t\\t\\tif (normal.x == major)\\n\\t\\t\\t{\\n\\t\\t\\t\\tB = cross(normal, vec3f(0.0, 1.0, 0.0));\\n\\t\\t\\t\\tT = cross(normal, B);\\n\\t\\t\\t}\\n\\t\\t\\telse if (normal.y == major)\\n\\t\\t\\t{\\n\\t\\t\\t\\tB = cross(normal, vec3f(0.0, 0.0, 1.0));\\n\\t\\t\\t\\tT = cross(normal, B);\\n\\t\\t\\t}\\n\\t\\t\\telse\\n\\t\\t\\t{\\n\\t\\t\\t\\tB = cross(normal, vec3f(1.0, 0.0, 0.0));\\n\\t\\t\\t\\tT = cross(normal, B);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdTBN = mat3x3f(normalize(T), normalize(B), normalize(normal));\\n\\t#endif\\n}`;\\n\\nvar thickness_default = `\\n#ifdef STD_THICKNESS_CONSTANT\\nuniform material_thickness: f32;\\n#endif\\nfn getThickness() {\\n\\tdThickness = 1.0;\\n\\t#ifdef STD_THICKNESS_CONSTANT\\n\\tdThickness = dThickness * uniform.material_thickness;\\n\\t#endif\\n\\t#ifdef STD_THICKNESS_TEXTURE\\n\\tdThickness = dThickness * textureSampleBias({STD_THICKNESS_TEXTURE_NAME}, {STD_THICKNESS_TEXTURE_NAME}Sampler, {STD_THICKNESS_TEXTURE_UV}, uniform.textureBias).{STD_THICKNESS_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_THICKNESS_VERTEX\\n\\tdThickness = dThickness * saturate(vVertexColor.{STD_THICKNESS_VERTEX_CHANNEL});\\n\\t#endif\\n}\\n`;\\n\\nvar tonemapping_default = `\\n#ifndef TONEMAP_NO_EXPOSURE_UNIFORM\\n\\t#if TONEMAP != NONE\\n\\t\\tuniform exposure: f32;\\n\\t\\tfn getExposure() -> f32 { return uniform.exposure; }\\n\\t#else\\n\\t\\tfn getExposure() -> f32 { return 1.0; }\\n\\t#endif\\n#else\\n\\t#if TONEMAP != NONE\\n\\t\\tfn getExposure() -> f32 { return uniforms.exposure; }\\n\\t#else\\n\\t\\tfn getExposure() -> f32 { return 1.0; }\\n\\t#endif\\n#endif\\n#if (TONEMAP == NONE)\\n\\t#include \\\"tonemappingNonePS\\\"\\n#elif TONEMAP == FILMIC\\n\\t#include \\\"tonemappingFilmicPS\\\"\\n#elif TONEMAP == LINEAR\\n\\t#include \\\"tonemappingLinearPS\\\"\\n#elif TONEMAP == HEJL\\n\\t#include \\\"tonemappingHejlPS\\\"\\n#elif TONEMAP == ACES\\n\\t#include \\\"tonemappingAcesPS\\\"\\n#elif TONEMAP == ACES2\\n\\t#include \\\"tonemappingAces2PS\\\"\\n#elif TONEMAP == NEUTRAL\\n\\t#include \\\"tonemappingNeutralPS\\\"\\n#endif\\n`;\\n\\nvar tonemappingAces_default = `\\nfn toneMap(color: vec3f) -> vec3f {\\n\\tlet tA: f32 = 2.51;\\n\\tlet tB: f32 = 0.03;\\n\\tlet tC: f32 = 2.43;\\n\\tlet tD: f32 = 0.59;\\n\\tlet tE: f32 = 0.14;\\n\\tlet x: vec3f = color * getExposure();\\n\\treturn (x * (tA * x + tB)) / (x * (tC * x + tD) + tE);\\n}\\n`;\\n\\nvar tonemappingAces2_default = `\\nconst ACESInputMat: mat3x3f = mat3x3f(\\n\\tvec3f(0.59719, 0.35458, 0.04823),\\n\\tvec3f(0.07600, 0.90834, 0.01566),\\n\\tvec3f(0.02840, 0.13383, 0.83777)\\n);\\nconst ACESOutputMat: mat3x3f = mat3x3f(\\n\\tvec3f( 1.60475, -0.53108, -0.07367),\\n\\tvec3f(-0.10208,  1.10813, -0.00605),\\n\\tvec3f(-0.00327, -0.07276,  1.07602)\\n);\\nfn RRTAndODTFit(v: vec3f) -> vec3f {\\n\\tlet a: vec3f = v * (v + vec3f(0.0245786)) - vec3f(0.000090537);\\n\\tlet b: vec3f = v * (vec3f(0.983729) * v + vec3f(0.4329510)) + vec3f(0.238081);\\n\\treturn a / b;\\n}\\nfn toneMap(color: vec3f) -> vec3f {\\n\\tvar c: vec3f = color * (getExposure() / 0.6);\\n\\tc = c * ACESInputMat;\\n\\tc = RRTAndODTFit(c);\\n\\tc = c * ACESOutputMat;\\n\\treturn clamp(c, vec3f(0.0), vec3f(1.0));\\n}\\n`;\\n\\nvar tonemappingFilmic_default = `\\nconst A: f32 = 0.15;\\nconst B: f32 = 0.50;\\nconst C: f32 = 0.10;\\nconst D: f32 = 0.20;\\nconst E: f32 = 0.02;\\nconst F: f32 = 0.30;\\nconst W: f32 = 11.2;\\nfn uncharted2Tonemap(x: vec3f) -> vec3f {\\n\\treturn ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - vec3f(E / F);\\n}\\nfn toneMap(color: vec3f) -> vec3f {\\n\\tvar c: vec3f = uncharted2Tonemap(color * getExposure());\\n\\tlet whiteScale: vec3f = vec3f(1.0) / uncharted2Tonemap(vec3f(W, W, W));\\n\\tc *= whiteScale;\\n\\treturn c;\\n}\\n`;\\n\\nvar tonemappingHejl_default = `\\nfn toneMap(color: vec3f) -> vec3f {\\n\\tlet A: f32 = 0.22;\\n\\tlet B: f32 = 0.3;\\n\\tlet C: f32 = 0.1;\\n\\tlet D: f32 = 0.2;\\n\\tlet E: f32 = 0.01;\\n\\tlet F: f32 = 0.3;\\n\\tlet Scl: f32 = 1.25;\\n\\tlet adjusted_color = color * getExposure();\\n\\tlet h = max(vec3f(0.0), adjusted_color - vec3f(0.004));\\n\\treturn (h * ((Scl * A) * h + Scl * vec3f(C * B)) + Scl * vec3f(D * E)) /\\n\\t\\t   (h * (A * h + vec3f(B)) + vec3f(D * F)) -\\n\\t\\t   Scl * vec3f(E / F);\\n}\\n`;\\n\\nvar tonemappingLinear_default = `\\nfn toneMap(color: vec3f) -> vec3f {\\n\\treturn color * getExposure();\\n}\\n`;\\n\\nvar tonemappingNeutral_default = `\\nfn toneMap(col: vec3f) -> vec3f {\\n\\tvar color = col * getExposure();\\n\\tlet startCompression = 0.8 - 0.04;\\n\\tlet desaturation = 0.15;\\n\\tlet x = min(color.r, min(color.g, color.b));\\n\\tlet offset = select(0.04, x - 6.25 * x * x, x < 0.08);\\n\\tcolor -= vec3f(offset);\\n\\tlet peak = max(color.r, max(color.g, color.b));\\n\\tif (peak < startCompression) {\\n\\t\\treturn color;\\n\\t}\\n\\tlet d = 1.0 - startCompression;\\n\\tlet newPeak = 1.0 - d * d / (peak + d - startCompression);\\n\\tcolor *= newPeak / peak;\\n\\tlet g = 1.0 - 1.0 / (desaturation * (peak - newPeak) + 1.0);\\n\\treturn mix(color, vec3f(newPeak), vec3f(g));\\n}\\n`;\\n\\nvar tonemappingNone_default = `\\nfn toneMap(color: vec3f) -> vec3f {\\n\\treturn color;\\n}\\n`;\\n\\nvar transform_default = `\\n#ifdef PIXELSNAP\\n\\tuniform uScreenSize: vec4f;\\n#endif\\n#ifdef SCREENSPACE\\n\\tuniform projectionFlipY: f32;\\n#endif\\nfn evalWorldPosition(vertexPosition: vec3f, modelMatrix: mat4x4f) -> vec4f {\\n\\tvar localPos: vec3f = getLocalPosition(vertexPosition);\\n\\t#ifdef NINESLICED\\n\\t\\tvar localPosXZ: vec2f = localPos.xz;\\n\\t\\tlocalPosXZ = localPosXZ * uniform.outerScale;\\n\\t\\tlet positiveUnitOffset: vec2f = clamp(vertexPosition.xz, vec2f(0.0), vec2f(1.0));\\n\\t\\tlet negativeUnitOffset: vec2f = clamp(-vertexPosition.xz, vec2f(0.0), vec2f(1.0));\\n\\t\\tlocalPosXZ = localPosXZ + (-positiveUnitOffset * uniform.innerOffset.xy + negativeUnitOffset * uniform.innerOffset.zw) * vertex_texCoord0.xy;\\n\\t\\tdTiledUvGlobal = (localPosXZ - uniform.outerScale + uniform.innerOffset.xy) * -0.5 + 1.0;\\n\\t\\tlocalPosXZ = localPosXZ * -0.5;\\n\\t\\tlocalPos = vec3f(localPosXZ.x, localPosXZ.y, localPos.y);\\n\\t#endif\\n\\tvar posW: vec4f = modelMatrix * vec4f(localPos, 1.0);\\n\\t#ifdef SCREENSPACE\\n\\t\\tposW = vec4f(posW.xy, 0.0, 1.0);\\n\\t#endif\\n\\treturn posW;\\n}\\nfn getPosition() -> vec4f {\\n\\tdModelMatrix = getModelMatrix();\\n\\tlet posW: vec4f = evalWorldPosition(vertex_position.xyz, dModelMatrix);\\n\\tdPositionW = posW.xyz;\\n\\tvar screenPos: vec4f;\\n\\t#ifdef UV1LAYOUT\\n\\t\\tscreenPos = vec4f(vertex_texCoord1.xy * 2.0 - 1.0, 0.5, 1.0);\\n\\t\\tscreenPos.y *= -1.0;\\n\\t#else\\n\\t\\t#ifdef SCREENSPACE\\n\\t\\t\\tscreenPos = posW;\\n\\t\\t\\tscreenPos.y *= uniform.projectionFlipY;\\n\\t\\t#else\\n\\t\\t\\tscreenPos = uniform.matrix_viewProjection * posW;\\n\\t\\t#endif\\n\\t\\t#ifdef PIXELSNAP\\n\\t\\t\\tscreenPos.xy = (screenPos.xy * 0.5) + 0.5;\\n\\t\\t\\tscreenPos.xy *= uniforms.uScreenSize.xy;\\n\\t\\t\\tscreenPos.xy = floor(screenPos.xy);\\n\\t\\t\\tscreenPos.xy *= uniforms.uScreenSize.zw;\\n\\t\\t\\tscreenPos.xy = (screenPos.xy * 2.0) - 1.0;\\n\\t\\t#endif\\n\\t#endif\\n\\treturn screenPos;\\n}\\nfn getWorldPosition() -> vec3f {\\n\\treturn dPositionW;\\n}\\n`;\\n\\nvar transformCore_default = `\\n\\tattribute vertex_position: vec4f;\\n\\tuniform matrix_viewProjection: mat4x4f;\\n\\tuniform matrix_model: mat4x4f;\\n\\t\\n\\t#ifdef MORPHING\\n\\t\\tuniform morph_tex_params: vec2f;\\n\\t\\tattribute morph_vertex_id: u32;\\n\\t\\tfn getTextureMorphCoords() -> vec2i {\\n\\t\\t\\tvar textureSize: vec2i = vec2i(uniform.morph_tex_params);\\n\\t\\t\\tvar morphGridV: i32 = i32(morph_vertex_id) / textureSize.x;\\n\\t\\t\\tvar morphGridU: i32 = i32(morph_vertex_id) - (morphGridV * textureSize.x);\\n\\t\\t\\tmorphGridV = textureSize.y - morphGridV - 1;\\n\\t\\t\\treturn vec2i(morphGridU, morphGridV);\\n\\t\\t}\\n\\t\\t#ifdef MORPHING_POSITION\\n\\t\\t\\t#ifdef MORPHING_INT\\n\\t\\t\\t\\tuniform aabbSize: vec3f;\\n\\t\\t\\t\\tuniform aabbMin: vec3f;\\n\\t\\t\\t\\tvar morphPositionTex: texture_2d<u32>;\\n\\t\\t\\t#else\\n\\t\\t\\t\\tvar morphPositionTex: texture_2d<f32>;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t#endif\\n\\t#ifdef defined(BATCH)\\n\\t\\t#include \\\"skinBatchVS\\\"\\n\\t\\tfn getModelMatrix() -> mat4x4f {\\n\\t\\t\\treturn getBoneMatrix(vertex_boneIndices);\\n\\t\\t}\\n\\t#elif defined(SKIN)\\n\\t\\t#include \\\"skinVS\\\"\\n\\t\\tfn getModelMatrix() -> mat4x4f {\\n\\t\\t\\treturn uniform.matrix_model * getSkinMatrix(vertex_boneIndices, vertex_boneWeights);\\n\\t\\t}\\n\\t#elif defined(INSTANCING)\\n\\t\\t#include \\\"transformInstancingVS\\\"\\n\\t#else\\n\\t\\tfn getModelMatrix() -> mat4x4f {\\n\\t\\t\\treturn uniform.matrix_model;\\n\\t\\t}\\n\\t#endif\\n\\tfn getLocalPosition(vertexPosition: vec3f) -> vec3f {\\n\\t\\tvar localPos: vec3f = vertexPosition;\\n\\t\\t#ifdef MORPHING_POSITION\\n\\t\\t\\tvar morphUV: vec2i = getTextureMorphCoords();\\n\\t\\t\\t#ifdef MORPHING_INT\\n\\t\\t\\t\\tvar morphPos: vec3f = vec3f(textureLoad(morphPositionTex, morphUV, 0).xyz) / 65535.0 * uniform.aabbSize + uniform.aabbMin;\\n\\t\\t\\t#else\\n\\t\\t\\t\\tvar morphPos: vec3f = textureLoad(morphPositionTex, morphUV, 0).xyz;\\n\\t\\t\\t#endif\\n\\t\\t\\tlocalPos += morphPos;\\n\\t\\t#endif\\n\\t\\treturn localPos;\\n\\t}\\n`;\\n\\nvar transformInstancing_default = `\\nattribute instance_line1: vec4f;\\nattribute instance_line2: vec4f;\\nattribute instance_line3: vec4f;\\nattribute instance_line4: vec4f;\\nfn getModelMatrix() -> mat4x4f {\\n\\treturn uniform.matrix_model * mat4x4f(instance_line1, instance_line2, instance_line3, instance_line4);\\n}\\n`;\\n\\nvar transmission_default = `\\n#ifdef STD_REFRACTION_CONSTANT\\n\\tuniform material_refraction: f32;\\n#endif\\nfn getRefraction() {\\n\\tvar refraction: f32 = 1.0;\\n\\t#ifdef STD_REFRACTION_CONSTANT\\n\\trefraction = uniform.material_refraction;\\n\\t#endif\\n\\t#ifdef STD_REFRACTION_TEXTURE\\n\\trefraction = refraction * textureSampleBias({STD_REFRACTION_TEXTURE_NAME}, {STD_REFRACTION_TEXTURE_NAME}Sampler, {STD_REFRACTION_TEXTURE_UV}, uniform.textureBias).{STD_REFRACTION_TEXTURE_CHANNEL};\\n\\t#endif\\n\\t#ifdef STD_REFRACTION_VERTEX\\n\\trefraction = refraction * saturate(vVertexColor.{STD_REFRACTION_VERTEX_CHANNEL});\\n\\t#endif\\n\\tdTransmission = refraction;\\n}\\n`;\\n\\nvar twoSidedLighting_default = `\\nfn handleTwoSidedLighting() {\\n\\tif (!pcFrontFacing) { dTBN[2] = -dTBN[2]; }\\n}\\n`;\\n\\nvar uv0_default = `\\n#ifdef NINESLICED\\n\\tfn getUv0() -> vec2f {\\n\\t\\tvar uv = vertex_position.xz;\\n\\t\\tlet positiveUnitOffset = clamp(vertex_position.xz, vec2f(0.0, 0.0), vec2f(1.0, 1.0));\\n\\t\\tlet negativeUnitOffset = clamp(-vertex_position.xz, vec2f(0.0, 0.0), vec2f(1.0, 1.0));\\n\\t\\tuv = uv + ((-positiveUnitOffset * uniform.innerOffset.xy) + (negativeUnitOffset * uniform.innerOffset.zw)) * vertex_texCoord0.xy;\\n\\t\\tuv = uv * -0.5 + vec2f(0.5, 0.5);\\n\\t\\tuv = uv * uniform.atlasRect.zw + uniform.atlasRect.xy;\\n\\t\\tdMaskGlobal = vertex_texCoord0.xy;\\n\\t\\treturn uv;\\n\\t}\\n#else\\n\\tfn getUv0() -> vec2f {\\n\\t\\treturn vertex_texCoord0;\\n\\t}\\n#endif\\n`;\\n\\nvar uv1_default = `\\nfn getUv1() -> vec2f {\\n\\treturn vertex_texCoord1;\\n}\\n`;\\n\\nvar uvTransform_default = `\\noutput.vUV{TRANSFORM_UV_{i}}_{TRANSFORM_ID_{i}} = vec2f(\\n\\tdot(vec3f(uv{TRANSFORM_UV_{i}}, 1), uniform.{TRANSFORM_NAME_{i}}0),\\n\\tdot(vec3f(uv{TRANSFORM_UV_{i}}, 1), uniform.{TRANSFORM_NAME_{i}}1)\\n);\\n`;\\n\\nvar uvTransformUniforms_default = `\\n\\tuniform {TRANSFORM_NAME_{i}}0: vec3f;\\n\\tuniform {TRANSFORM_NAME_{i}}1: vec3f;\\n`;\\n\\nvar viewDir_default = `\\nfn getViewDir() {\\n\\tdViewDirW = normalize(uniform.view_position - vPositionW);\\n}\\n`;\\n\\nconst shaderChunksWGSL = {\\n\\talphaTestPS: alphaTest_default,\\n\\tambientPS: ambient_default,\\n\\tanisotropyPS: anisotropy_default,\\n\\taoPS: ao_default,\\n\\taoDiffuseOccPS: aoDiffuseOcc_default,\\n\\taoSpecOccPS: aoSpecOcc_default,\\n\\tbakeDirLmEndPS: bakeDirLmEnd_default,\\n\\tbakeLmEndPS: bakeLmEnd_default,\\n\\tbasePS: base_default,\\n\\tbaseNineSlicedPS: baseNineSliced_default,\\n\\tbaseNineSlicedTiledPS: baseNineSlicedTiled_default,\\n\\tbayerPS: bayer_default,\\n\\tblurVSMPS: blurVSM_default,\\n\\tclearCoatPS: clearCoat_default,\\n\\tclearCoatGlossPS: clearCoatGloss_default,\\n\\tclearCoatNormalPS: clearCoatNormal_default,\\n\\tclusteredLightCookiesPS: clusteredLightCookies_default,\\n\\tclusteredLightShadowsPS: clusteredLightShadows_default,\\n\\tclusteredLightUtilsPS: clusteredLightUtils_default,\\n\\tclusteredLightPS: clusteredLight_default,\\n\\tcombinePS: combine_default,\\n\\tcookieBlit2DPS: cookie_blit_2d_default,\\n\\tcookieBlitCubePS: cookie_blit_cube_default,\\n\\tcookieBlitVS: cookie_blit_default,\\n\\t// cookiePS,\\n\\tcubeMapProjectPS: cubeMapProject_default,\\n\\tcubeMapRotatePS: cubeMapRotate_default,\\n\\tdebugOutputPS: debug_output_default,\\n\\tdebugProcessFrontendPS: debug_process_frontend_default,\\n\\tdetailModesPS: detailModes_default,\\n\\tdiffusePS: diffuse_default,\\n\\tdecodePS: decode_default,\\n\\temissivePS: emissive_default,\\n\\tencodePS: encode_default,\\n\\tendPS: end_default,\\n\\tenvAtlasPS: envAtlas_default,\\n\\tenvProcPS: envProc_default,\\n\\tfalloffInvSquaredPS: falloffInvSquared_default,\\n\\tfalloffLinearPS: falloffLinear_default,\\n\\tfloatAsUintPS: float_as_uint_default,\\n\\tfogPS: fog_default,\\n\\tfogMathPS: fogMath_default,\\n\\tfresnelSchlickPS: fresnelSchlick_default,\\n\\tfrontendCodePS: \\\"\\\",\\n\\t// empty chunk, supplied by the shader generator\\n\\tfrontendDeclPS: \\\"\\\",\\n\\t// empty chunk, supplied by the shader generator\\n\\tfullscreenQuadVS: fullscreenQuad_default,\\n\\tgammaPS: gamma_default,\\n\\tglossPS: gloss_default,\\n\\tquadVS: quad_default,\\n\\tindirectCoreCS: indirect_core_default,\\n\\timmediateLinePS: immediateLine_default$1,\\n\\timmediateLineVS: immediateLine_default,\\n\\tiridescenceDiffractionPS: iridescenceDiffraction_default,\\n\\tiridescencePS: iridescence_default,\\n\\tiridescenceThicknessPS: iridescenceThickness_default,\\n\\tiorPS: ior_default,\\n\\tlightDeclarationPS: lightDeclaration_default,\\n\\tlightDiffuseLambertPS: lightDiffuseLambert_default,\\n\\tlightDirPointPS: lightDirPoint_default,\\n\\tlightEvaluationPS: lightEvaluation_default,\\n\\tlightFunctionLightPS: lightFunctionLight_default,\\n\\tlightFunctionShadowPS: lightFunctionShadow_default,\\n\\tlightingPS: lighting_default,\\n\\tlightmapAddPS: lightmapAdd_default,\\n\\tlightmapPS: lightmap_default,\\n\\tlightSpecularAnisoGGXPS: lightSpecularAnisoGGX_default,\\n\\tlightSpecularGGXPS: lightSpecularGGX_default,\\n\\tlightSpecularBlinnPS: lightSpecularBlinn_default,\\n\\tlightSheenPS: lightSheen_default,\\n\\tlinearizeDepthPS: linearizeDepth_default,\\n\\tlitForwardBackendPS: litForwardBackend_default,\\n\\tlitForwardDeclarationPS: litForwardDeclaration_default,\\n\\tlitForwardMainPS: litForwardMain_default,\\n\\tlitForwardPostCodePS: litForwardPostCode_default,\\n\\tlitForwardPreCodePS: litForwardPreCode_default,\\n\\tlitMainPS: litMain_default$1,\\n\\tlitMainVS: litMain_default,\\n\\tlitOtherMainPS: litOtherMain_default,\\n\\tlitShaderArgsPS: litShaderArgs_default,\\n\\tlitShaderCorePS: litShaderCore_default,\\n\\tlitShadowMainPS: litShadowMain_default,\\n\\tlitUserDeclarationPS: \\\"\\\",\\n\\t// empty chunk allowing user to add custom code\\n\\tlitUserDeclarationVS: \\\"\\\",\\n\\t// empty chunk allowing user to add custom code\\n\\tlitUserCodePS: \\\"\\\",\\n\\t// empty chunk allowing user to add custom code\\n\\tlitUserCodeVS: \\\"\\\",\\n\\t// empty chunk allowing user to add custom code\\n\\tlitUserMainStartPS: \\\"\\\",\\n\\t// empty chunk allowing user to add custom code\\n\\tlitUserMainStartVS: \\\"\\\",\\n\\t// empty chunk allowing user to add custom code\\n\\tlitUserMainEndPS: \\\"\\\",\\n\\t// empty chunk allowing user to add custom code\\n\\tlitUserMainEndVS: \\\"\\\",\\n\\t// empty chunk allowing user to add custom code\\n\\tltcPS: ltc_default,\\n\\tmetalnessPS: metalness_default,\\n\\tmetalnessModulatePS: metalnessModulate_default,\\n\\tmorphPS: morph_default$1,\\n\\tmorphVS: morph_default,\\n\\tmsdfPS: msdf_default$1,\\n\\tmsdfVS: msdf_default,\\n\\tnormalVS: normal_default,\\n\\tnormalCoreVS: normalCore_default,\\n\\tnormalMapPS: normalMap_default,\\n\\topacityPS: opacity_default,\\n\\topacityDitherPS: opacity_dither_default,\\n\\toutputPS: output_default,\\n\\toutputAlphaPS: outputAlpha_default,\\n\\toutputTex2DPS: outputTex2D_default,\\n\\tsheenPS: sheen_default,\\n\\tsheenGlossPS: sheenGloss_default,\\n\\tparallaxPS: parallax_default,\\n\\tpickPS: pick_default,\\n\\treflDirPS: reflDir_default,\\n\\treflDirAnisoPS: reflDirAniso_default,\\n\\treflectionCCPS: reflectionCC_default,\\n\\treflectionCubePS: reflectionCube_default,\\n\\treflectionEnvHQPS: reflectionEnvHQ_default,\\n\\treflectionEnvPS: reflectionEnv_default,\\n\\treflectionSpherePS: reflectionSphere_default,\\n\\treflectionSheenPS: reflectionSheen_default,\\n\\trefractionCubePS: refractionCube_default,\\n\\trefractionDynamicPS: refractionDynamic_default,\\n\\treprojectPS: reproject_default$1,\\n\\treprojectVS: reproject_default,\\n\\tscreenDepthPS: screenDepth_default,\\n\\tshadowCascadesPS: shadowCascades_default,\\n\\tshadowEVSMPS: shadowEVSM_default,\\n\\tshadowPCF1PS: shadowPCF1_default,\\n\\tshadowPCF3PS: shadowPCF3_default,\\n\\tshadowPCF5PS: shadowPCF5_default,\\n\\t// shadowPCSSPS,\\n\\tshadowSoftPS: shadowSoft_default,\\n\\tskinBatchVS: skinBatch_default,\\n\\tskinVS: skin_default,\\n\\tskyboxPS: skybox_default$1,\\n\\tskyboxVS: skybox_default,\\n\\tsortIndirectArgsCS: sort_indirect_args_default,\\n\\tspecularPS: specular_default,\\n\\tsphericalPS: spherical_default,\\n\\tspecularityFactorPS: specularityFactor_default,\\n\\tspotPS: spot_default,\\n\\tstartNineSlicedPS: startNineSliced_default,\\n\\tstartNineSlicedTiledPS: startNineSlicedTiled_default,\\n\\tstdDeclarationPS: stdDeclaration_default,\\n\\tstdFrontEndPS: stdFrontEnd_default,\\n\\tTBNPS: TBN_default,\\n\\tthicknessPS: thickness_default,\\n\\ttonemappingPS: tonemapping_default,\\n\\ttonemappingAcesPS: tonemappingAces_default,\\n\\ttonemappingAces2PS: tonemappingAces2_default,\\n\\ttonemappingFilmicPS: tonemappingFilmic_default,\\n\\ttonemappingHejlPS: tonemappingHejl_default,\\n\\ttonemappingLinearPS: tonemappingLinear_default,\\n\\ttonemappingNeutralPS: tonemappingNeutral_default,\\n\\ttonemappingNonePS: tonemappingNone_default,\\n\\ttransformVS: transform_default,\\n\\ttransformCoreVS: transformCore_default,\\n\\ttransformInstancingVS: transformInstancing_default,\\n\\ttransmissionPS: transmission_default,\\n\\ttwoSidedLightingPS: twoSidedLighting_default,\\n\\tuv0VS: uv0_default,\\n\\tuv1VS: uv1_default,\\n\\tuvTransformVS: uvTransform_default,\\n\\tuvTransformUniformsPS: uvTransformUniforms_default,\\n\\tviewDirPS: viewDir_default,\\n\\twebgpuPS: webgpu_wgsl_default$1,\\n\\twebgpuVS: webgpu_wgsl_default\\n};\\n\\nclass AppBase extends EventHandler {\\n\\t_batcher = null;\\n\\t_destroyRequested = false;\\n\\t_inFrameUpdate = false;\\n\\t_librariesLoaded = false;\\n\\t_fillMode = FILLMODE_KEEP_ASPECT;\\n\\t_resolutionMode = RESOLUTION_FIXED;\\n\\t_allowResize = true;\\n\\t_skyboxAsset = null;\\n\\t_soundManager;\\n\\t_visibilityChangeHandler;\\n\\t_entityIndex = {};\\n\\t_inTools = false;\\n\\t_scriptPrefix = \\\"\\\";\\n\\t_time = 0;\\n\\tenableBundles = typeof TextDecoder !== \\\"undefined\\\";\\n\\tframeRequestId;\\n\\ttick = (timestamp, xrFrame) => {\\n\\t\\tif (!this.graphicsDevice) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this.frameRequestId) {\\n\\t\\t\\tthis.xr?.session?.cancelAnimationFrame(this.frameRequestId);\\n\\t\\t\\tcancelAnimationFrame(this.frameRequestId);\\n\\t\\t\\tthis.frameRequestId = null;\\n\\t\\t}\\n\\t\\tthis._inFrameUpdate = true;\\n\\t\\tsetApplication(this);\\n\\t\\tconst currentTime = this._processTimestamp(timestamp) || now();\\n\\t\\tconst ms = currentTime - (this._time || currentTime);\\n\\t\\tlet dt = ms / 1e3;\\n\\t\\tdt = math.clamp(dt, 0, this.maxDeltaTime);\\n\\t\\tdt *= this.timeScale;\\n\\t\\tthis._time = currentTime;\\n\\t\\tthis.requestAnimationFrame();\\n\\t\\tif (this.graphicsDevice.contextLost) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.stats.updateBasic(currentTime, dt, ms, this.renderer, this.graphicsDevice);\\n\\t\\tthis.fire(\\\"frameupdate\\\", ms);\\n\\t\\tlet skipUpdate = false;\\n\\t\\tif (xrFrame) {\\n\\t\\t\\tskipUpdate = !this.xr?.update(xrFrame);\\n\\t\\t}\\n\\t\\tif (!skipUpdate) {\\n\\t\\t\\tthis.update(dt);\\n\\t\\t\\tthis.fire(\\\"framerender\\\");\\n\\t\\t\\tif (this.autoRender || this.renderNextFrame) {\\n\\t\\t\\t\\tthis.render();\\n\\t\\t\\t\\tthis.renderNextFrame = false;\\n\\t\\t\\t}\\n\\t\\t\\tthis.fire(\\\"frameend\\\");\\n\\t\\t\\tthis.stats.frameEnd();\\n\\t\\t}\\n\\t\\tthis._inFrameUpdate = false;\\n\\t\\tif (this._destroyRequested) {\\n\\t\\t\\tthis.destroy();\\n\\t\\t}\\n\\t};\\n\\ttimeScale = 1;\\n\\tmaxDeltaTime = 0.1;\\n\\t// Maximum delta is 0.1s or 10 fps.\\n\\tframe = 0;\\n\\tframeGraph = new FrameGraph();\\n\\trenderer;\\n\\tscriptsOrder = [];\\n\\tstats;\\n\\tautoRender = true;\\n\\trenderNextFrame = false;\\n\\tgraphicsDevice;\\n\\troot;\\n\\tscene;\\n\\tlightmapper = null;\\n\\tloader = new ResourceLoader(this);\\n\\tassets;\\n\\tbundles;\\n\\tscenes = new SceneRegistry(this);\\n\\tscripts = new ScriptRegistry(this);\\n\\tsystems = new ComponentSystemRegistry();\\n\\ti18n = new I18n(this);\\n\\tkeyboard = null;\\n\\tmouse = null;\\n\\ttouch = null;\\n\\tgamepads = null;\\n\\telementInput = null;\\n\\txr = null;\\n\\tconstructor(canvas) {\\n\\t\\tsuper();\\n\\t\\tAppBase._applications[canvas.id] = this;\\n\\t\\tsetApplication(this);\\n\\t\\tthis.root = new Entity();\\n\\t\\tthis.root._enabledInHierarchy = true;\\n\\t}\\n\\tinit(appOptions) {\\n\\t\\tconst {\\n\\t\\t\\tassetPrefix,\\n\\t\\t\\tbatchManager,\\n\\t\\t\\tcomponentSystems,\\n\\t\\t\\telementInput,\\n\\t\\t\\tgamepads,\\n\\t\\t\\tgraphicsDevice,\\n\\t\\t\\tkeyboard,\\n\\t\\t\\tlightmapper,\\n\\t\\t\\tmouse,\\n\\t\\t\\tresourceHandlers,\\n\\t\\t\\tscriptsOrder,\\n\\t\\t\\tscriptPrefix,\\n\\t\\t\\tsoundManager,\\n\\t\\t\\ttouch,\\n\\t\\t\\txr\\n\\t\\t} = appOptions;\\n\\t\\tthis.graphicsDevice = graphicsDevice;\\n\\t\\tShaderChunks.get(graphicsDevice, SHADERLANGUAGE_GLSL).add(shaderChunksGLSL);\\n\\t\\tShaderChunks.get(graphicsDevice, SHADERLANGUAGE_WGSL).add(shaderChunksWGSL);\\n\\t\\tthis._initDefaultMaterial();\\n\\t\\tthis._initProgramLibrary();\\n\\t\\tthis.stats = new ApplicationStats(graphicsDevice);\\n\\t\\tthis._soundManager = soundManager;\\n\\t\\tthis.scene = new Scene(graphicsDevice);\\n\\t\\tthis._registerSceneImmediate(this.scene);\\n\\t\\tthis.assets = new AssetRegistry(this.loader);\\n\\t\\tif (assetPrefix) this.assets.prefix = assetPrefix;\\n\\t\\tthis.bundles = new BundleRegistry(this.assets);\\n\\t\\tthis.scriptsOrder = scriptsOrder || [];\\n\\t\\tthis.defaultLayerWorld = new Layer({ name: \\\"World\\\", id: LAYERID_WORLD });\\n\\t\\tthis.defaultLayerDepth = new Layer({ name: \\\"Depth\\\", id: LAYERID_DEPTH, enabled: false, opaqueSortMode: SORTMODE_NONE });\\n\\t\\tthis.defaultLayerSkybox = new Layer({ name: \\\"Skybox\\\", id: LAYERID_SKYBOX, opaqueSortMode: SORTMODE_NONE });\\n\\t\\tthis.defaultLayerUi = new Layer({ name: \\\"UI\\\", id: LAYERID_UI, transparentSortMode: SORTMODE_MANUAL });\\n\\t\\tthis.defaultLayerImmediate = new Layer({ name: \\\"Immediate\\\", id: LAYERID_IMMEDIATE, opaqueSortMode: SORTMODE_NONE });\\n\\t\\tconst defaultLayerComposition = new LayerComposition(\\\"default\\\");\\n\\t\\tdefaultLayerComposition.pushOpaque(this.defaultLayerWorld);\\n\\t\\tdefaultLayerComposition.pushOpaque(this.defaultLayerDepth);\\n\\t\\tdefaultLayerComposition.pushOpaque(this.defaultLayerSkybox);\\n\\t\\tdefaultLayerComposition.pushTransparent(this.defaultLayerWorld);\\n\\t\\tdefaultLayerComposition.pushOpaque(this.defaultLayerImmediate);\\n\\t\\tdefaultLayerComposition.pushTransparent(this.defaultLayerImmediate);\\n\\t\\tdefaultLayerComposition.pushTransparent(this.defaultLayerUi);\\n\\t\\tthis.scene.layers = defaultLayerComposition;\\n\\t\\tAreaLightLuts.createPlaceholder(graphicsDevice);\\n\\t\\tthis.renderer = new ForwardRenderer(graphicsDevice, this.scene);\\n\\t\\tif (lightmapper) {\\n\\t\\t\\tthis.lightmapper = new lightmapper(graphicsDevice, this.root, this.scene, this.renderer, this.assets);\\n\\t\\t\\tthis.once(\\\"prerender\\\", this._firstBake, this);\\n\\t\\t}\\n\\t\\tif (batchManager) {\\n\\t\\t\\tthis._batcher = new batchManager(graphicsDevice, this.root, this.scene);\\n\\t\\t\\tthis.once(\\\"prerender\\\", this._firstBatch, this);\\n\\t\\t}\\n\\t\\tthis.keyboard = keyboard || null;\\n\\t\\tthis.mouse = mouse || null;\\n\\t\\tthis.touch = touch || null;\\n\\t\\tthis.gamepads = gamepads || null;\\n\\t\\tif (elementInput) {\\n\\t\\t\\tthis.elementInput = elementInput;\\n\\t\\t\\tthis.elementInput.app = this;\\n\\t\\t}\\n\\t\\tthis.xr = xr ? new xr(this) : null;\\n\\t\\tif (this.elementInput) this.elementInput.attachSelectEvents();\\n\\t\\tthis._scriptPrefix = scriptPrefix || \\\"\\\";\\n\\t\\tif (this.enableBundles) {\\n\\t\\t\\tthis.loader.addHandler(\\\"bundle\\\", new BundleHandler(this));\\n\\t\\t}\\n\\t\\tresourceHandlers.forEach((resourceHandler) => {\\n\\t\\t\\tconst handler = new resourceHandler(this);\\n\\t\\t\\tthis.loader.addHandler(handler.handlerType, handler);\\n\\t\\t});\\n\\t\\tthis.loader.enableRetry();\\n\\t\\tcomponentSystems.forEach((componentSystem) => {\\n\\t\\t\\tthis.systems.add(new componentSystem(this));\\n\\t\\t});\\n\\t\\tthis._visibilityChangeHandler = this.onVisibilityChange.bind(this);\\n\\t\\tif (typeof document !== \\\"undefined\\\") {\\n\\t\\t\\tdocument.addEventListener(\\\"visibilitychange\\\", this._visibilityChangeHandler, false);\\n\\t\\t}\\n\\t}\\n\\tstatic _applications = {};\\n\\tstatic getApplication(id) {\\n\\t\\treturn id ? AppBase._applications[id] : getApplication();\\n\\t}\\n\\t_initDefaultMaterial() {\\n\\t\\tconst material = new StandardMaterial();\\n\\t\\tmaterial.name = \\\"Default Material\\\";\\n\\t\\tsetDefaultMaterial(this.graphicsDevice, material);\\n\\t}\\n\\t_initProgramLibrary() {\\n\\t\\tconst library = new ProgramLibrary(this.graphicsDevice, new StandardMaterial());\\n\\t\\tsetProgramLibrary(this.graphicsDevice, library);\\n\\t}\\n\\tget soundManager() {\\n\\t\\treturn this._soundManager;\\n\\t}\\n\\tget batcher() {\\n\\t\\treturn this._batcher;\\n\\t}\\n\\tget fillMode() {\\n\\t\\treturn this._fillMode;\\n\\t}\\n\\tget resolutionMode() {\\n\\t\\treturn this._resolutionMode;\\n\\t}\\n\\tconfigure(url, callback) {\\n\\t\\thttp.get(url, (err, response) => {\\n\\t\\t\\tif (err) {\\n\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tconst props = response.application_properties;\\n\\t\\t\\tconst scenes = response.scenes;\\n\\t\\t\\tconst assets = response.assets;\\n\\t\\t\\tthis._parseApplicationProperties(props, (err2) => {\\n\\t\\t\\t\\tthis._parseScenes(scenes);\\n\\t\\t\\t\\tthis._parseAssets(assets);\\n\\t\\t\\t\\tif (!err2) {\\n\\t\\t\\t\\t\\tcallback(null);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tcallback(err2);\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t});\\n\\t}\\n\\tpreload(callback) {\\n\\t\\tthis.fire(\\\"preload:start\\\");\\n\\t\\tconst assets = this.assets.list({\\n\\t\\t\\tpreload: true\\n\\t\\t});\\n\\t\\tif (assets.length === 0) {\\n\\t\\t\\tthis.fire(\\\"preload:end\\\");\\n\\t\\t\\tcallback();\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tlet loadedCount = 0;\\n\\t\\tconst onAssetLoadOrError = () => {\\n\\t\\t\\tloadedCount++;\\n\\t\\t\\tthis.fire(\\\"preload:progress\\\", loadedCount / assets.length);\\n\\t\\t\\tif (loadedCount === assets.length) {\\n\\t\\t\\t\\tthis.fire(\\\"preload:end\\\");\\n\\t\\t\\t\\tcallback();\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tassets.forEach((asset) => {\\n\\t\\t\\tif (!asset.loaded) {\\n\\t\\t\\t\\tasset.once(\\\"load\\\", onAssetLoadOrError);\\n\\t\\t\\t\\tasset.once(\\\"error\\\", onAssetLoadOrError);\\n\\t\\t\\t\\tthis.assets.load(asset);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tonAssetLoadOrError();\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n\\t_preloadScripts(sceneData, callback) {\\n\\t\\tcallback();\\n\\t}\\n\\t// set application properties from data file\\n\\t_parseApplicationProperties(props, callback) {\\n\\t\\tif (typeof props.maxAssetRetries === \\\"number\\\" && props.maxAssetRetries > 0) {\\n\\t\\t\\tthis.loader.enableRetry(props.maxAssetRetries);\\n\\t\\t}\\n\\t\\tif (!props.useDevicePixelRatio) {\\n\\t\\t\\tprops.useDevicePixelRatio = props.use_device_pixel_ratio;\\n\\t\\t}\\n\\t\\tif (!props.resolutionMode) {\\n\\t\\t\\tprops.resolutionMode = props.resolution_mode;\\n\\t\\t}\\n\\t\\tif (!props.fillMode) {\\n\\t\\t\\tprops.fillMode = props.fill_mode;\\n\\t\\t}\\n\\t\\tthis._width = props.width;\\n\\t\\tthis._height = props.height;\\n\\t\\tif (props.useDevicePixelRatio) {\\n\\t\\t\\tthis.graphicsDevice.maxPixelRatio = window.devicePixelRatio;\\n\\t\\t}\\n\\t\\tthis.setCanvasResolution(props.resolutionMode, this._width, this._height);\\n\\t\\tthis.setCanvasFillMode(props.fillMode, this._width, this._height);\\n\\t\\tif (props.layers && props.layerOrder) {\\n\\t\\t\\tconst composition = new LayerComposition(\\\"application\\\");\\n\\t\\t\\tconst layers = {};\\n\\t\\t\\tfor (const key in props.layers) {\\n\\t\\t\\t\\tconst data = props.layers[key];\\n\\t\\t\\t\\tdata.id = parseInt(key, 10);\\n\\t\\t\\t\\tdata.enabled = data.id !== LAYERID_DEPTH;\\n\\t\\t\\t\\tlayers[key] = new Layer(data);\\n\\t\\t\\t}\\n\\t\\t\\tfor (let i = 0, len = props.layerOrder.length; i < len; i++) {\\n\\t\\t\\t\\tconst sublayer = props.layerOrder[i];\\n\\t\\t\\t\\tconst layer = layers[sublayer.layer];\\n\\t\\t\\t\\tif (!layer) continue;\\n\\t\\t\\t\\tif (sublayer.transparent) {\\n\\t\\t\\t\\t\\tcomposition.pushTransparent(layer);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tcomposition.pushOpaque(layer);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcomposition.subLayerEnabled[i] = sublayer.enabled;\\n\\t\\t\\t}\\n\\t\\t\\tthis.scene.layers = composition;\\n\\t\\t}\\n\\t\\tif (props.batchGroups) {\\n\\t\\t\\tconst batcher = this.batcher;\\n\\t\\t\\tif (batcher) {\\n\\t\\t\\t\\tfor (let i = 0, len = props.batchGroups.length; i < len; i++) {\\n\\t\\t\\t\\t\\tconst grp = props.batchGroups[i];\\n\\t\\t\\t\\t\\tbatcher.addGroup(grp.name, grp.dynamic, grp.maxAabbSize, grp.id, grp.layers);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (props.i18nAssets) {\\n\\t\\t\\tthis.i18n.assets = props.i18nAssets;\\n\\t\\t}\\n\\t\\tthis._loadLibraries(props.libraries, callback);\\n\\t}\\n\\t_loadLibraries(urls, callback) {\\n\\t\\tconst len = urls.length;\\n\\t\\tlet count = len;\\n\\t\\tconst regex = /^https?:\\\\/\\\\//;\\n\\t\\tif (len) {\\n\\t\\t\\tconst onLoad = (err, script2) => {\\n\\t\\t\\t\\tcount--;\\n\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t} else if (count === 0) {\\n\\t\\t\\t\\t\\tthis.onLibrariesLoaded();\\n\\t\\t\\t\\t\\tcallback(null);\\n\\t\\t\\t\\t}\\n\\t\\t\\t};\\n\\t\\t\\tfor (let i = 0; i < len; ++i) {\\n\\t\\t\\t\\tlet url = urls[i];\\n\\t\\t\\t\\tif (!regex.test(url.toLowerCase()) && this._scriptPrefix) {\\n\\t\\t\\t\\t\\turl = path.join(this._scriptPrefix, url);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.loader.load(url, \\\"script\\\", onLoad);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis.onLibrariesLoaded();\\n\\t\\t\\tcallback(null);\\n\\t\\t}\\n\\t}\\n\\t_parseScenes(scenes) {\\n\\t\\tif (!scenes) return;\\n\\t\\tfor (let i = 0; i < scenes.length; i++) {\\n\\t\\t\\tthis.scenes.add(scenes[i].name, scenes[i].url);\\n\\t\\t}\\n\\t}\\n\\t_parseAssets(assets) {\\n\\t\\tconst list = [];\\n\\t\\tconst scriptsIndex = {};\\n\\t\\tconst bundlesIndex = {};\\n\\t\\tfor (let i = 0; i < this.scriptsOrder.length; i++) {\\n\\t\\t\\tconst id = this.scriptsOrder[i];\\n\\t\\t\\tif (!assets[id]) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tscriptsIndex[id] = true;\\n\\t\\t\\tlist.push(assets[id]);\\n\\t\\t}\\n\\t\\tif (this.enableBundles) {\\n\\t\\t\\tfor (const id in assets) {\\n\\t\\t\\t\\tif (assets[id].type === \\\"bundle\\\") {\\n\\t\\t\\t\\t\\tbundlesIndex[id] = true;\\n\\t\\t\\t\\t\\tlist.push(assets[id]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (const id in assets) {\\n\\t\\t\\tif (scriptsIndex[id] || bundlesIndex[id]) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tlist.push(assets[id]);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < list.length; i++) {\\n\\t\\t\\tconst data = list[i];\\n\\t\\t\\tconst asset = new Asset(data.name, data.type, data.file, data.data);\\n\\t\\t\\tasset.id = parseInt(data.id, 10);\\n\\t\\t\\tasset.preload = data.preload ? data.preload : false;\\n\\t\\t\\tasset.loaded = data.type === \\\"script\\\" && data.data && data.data.loadingType > 0;\\n\\t\\t\\tasset.tags.add(data.tags);\\n\\t\\t\\tif (data.i18n) {\\n\\t\\t\\t\\tfor (const locale in data.i18n) {\\n\\t\\t\\t\\t\\tasset.addLocalizedAssetId(locale, data.i18n[locale]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis.assets.add(asset);\\n\\t\\t}\\n\\t}\\n\\tstart() {\\n\\t\\tthis.frame = 0;\\n\\t\\tthis.fire(\\\"start\\\", {\\n\\t\\t\\ttimestamp: now(),\\n\\t\\t\\ttarget: this\\n\\t\\t});\\n\\t\\tif (!this._librariesLoaded) {\\n\\t\\t\\tthis.onLibrariesLoaded();\\n\\t\\t}\\n\\t\\tthis.systems.fire(\\\"initialize\\\", this.root);\\n\\t\\tthis.fire(\\\"initialize\\\");\\n\\t\\tthis.systems.fire(\\\"postInitialize\\\", this.root);\\n\\t\\tthis.systems.fire(\\\"postPostInitialize\\\", this.root);\\n\\t\\tthis.fire(\\\"postinitialize\\\");\\n\\t\\tthis.requestAnimationFrame();\\n\\t}\\n\\trequestAnimationFrame() {\\n\\t\\tif (this.xr?.session) {\\n\\t\\t\\tthis.frameRequestId = this.xr.session.requestAnimationFrame(this.tick);\\n\\t\\t} else {\\n\\t\\t\\tthis.frameRequestId = platform.browser || platform.worker ? requestAnimationFrame(this.tick) : null;\\n\\t\\t}\\n\\t}\\n\\tinputUpdate(dt) {\\n\\t\\tif (this.mouse) {\\n\\t\\t\\tthis.mouse.update();\\n\\t\\t}\\n\\t\\tif (this.keyboard) {\\n\\t\\t\\tthis.keyboard.update();\\n\\t\\t}\\n\\t\\tif (this.gamepads) {\\n\\t\\t\\tthis.gamepads.update();\\n\\t\\t}\\n\\t}\\n\\tupdate(dt) {\\n\\t\\tthis.frame++;\\n\\t\\tthis.graphicsDevice.update();\\n\\t\\tthis.stats.frame.scriptUpdateStart = now();\\n\\t\\tthis.systems.fire(this._inTools ? \\\"toolsUpdate\\\" : \\\"update\\\", dt);\\n\\t\\tthis.stats.frame.scriptUpdate = now() - this.stats.frame.scriptUpdateStart;\\n\\t\\tthis.stats.frame.animUpdateStart = now();\\n\\t\\tthis.systems.fire(\\\"animationUpdate\\\", dt);\\n\\t\\tthis.stats.frame.animUpdate = now() - this.stats.frame.animUpdateStart;\\n\\t\\tthis.stats.frame.scriptPostUpdateStart = now();\\n\\t\\tthis.systems.fire(\\\"postUpdate\\\", dt);\\n\\t\\tthis.stats.frame.scriptPostUpdate = now() - this.stats.frame.scriptPostUpdateStart;\\n\\t\\tthis.fire(\\\"update\\\", dt);\\n\\t\\tthis.inputUpdate(dt);\\n\\t}\\n\\trender() {\\n\\t\\tthis.updateCanvasSize();\\n\\t\\tthis.graphicsDevice.frameStart();\\n\\t\\tthis.fire(\\\"prerender\\\");\\n\\t\\tthis.root.syncHierarchy();\\n\\t\\tif (this._batcher) {\\n\\t\\t\\tthis._batcher.updateAll();\\n\\t\\t}\\n\\t\\tthis.renderComposition(this.scene.layers);\\n\\t\\tthis.fire(\\\"postrender\\\");\\n\\t\\tthis.stats.frame.renderTime = now() - this.stats.frame.renderStart;\\n\\t\\tthis.graphicsDevice.frameEnd();\\n\\t}\\n\\t// render a layer composition\\n\\trenderComposition(layerComposition) {\\n\\t\\tthis.renderer.update(layerComposition);\\n\\t\\tthis.renderer.buildFrameGraph(this.frameGraph, layerComposition);\\n\\t\\tthis.frameGraph.render(this.graphicsDevice);\\n\\t}\\n\\tsetCanvasFillMode(mode, width, height) {\\n\\t\\tthis._fillMode = mode;\\n\\t\\tthis.resizeCanvas(width, height);\\n\\t}\\n\\tsetCanvasResolution(mode, width, height) {\\n\\t\\tthis._resolutionMode = mode;\\n\\t\\tif (mode === RESOLUTION_AUTO && width === void 0) {\\n\\t\\t\\twidth = this.graphicsDevice.canvas.clientWidth;\\n\\t\\t\\theight = this.graphicsDevice.canvas.clientHeight;\\n\\t\\t}\\n\\t\\tthis.graphicsDevice.resizeCanvas(width, height);\\n\\t}\\n\\tisHidden() {\\n\\t\\treturn document.hidden;\\n\\t}\\n\\tonVisibilityChange() {\\n\\t\\tif (this.isHidden()) {\\n\\t\\t\\tif (this._soundManager) {\\n\\t\\t\\t\\tthis._soundManager.suspend();\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tif (this._soundManager) {\\n\\t\\t\\t\\tthis._soundManager.resume();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tresizeCanvas(width, height) {\\n\\t\\tif (!this._allowResize) return void 0;\\n\\t\\tif (this.xr && this.xr.session) {\\n\\t\\t\\treturn void 0;\\n\\t\\t}\\n\\t\\tconst windowWidth = window.innerWidth;\\n\\t\\tconst windowHeight = window.innerHeight;\\n\\t\\tif (this._fillMode === FILLMODE_KEEP_ASPECT) {\\n\\t\\t\\tconst r = this.graphicsDevice.canvas.width / this.graphicsDevice.canvas.height;\\n\\t\\t\\tconst winR = windowWidth / windowHeight;\\n\\t\\t\\tif (r > winR) {\\n\\t\\t\\t\\twidth = windowWidth;\\n\\t\\t\\t\\theight = width / r;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\theight = windowHeight;\\n\\t\\t\\t\\twidth = height * r;\\n\\t\\t\\t}\\n\\t\\t} else if (this._fillMode === FILLMODE_FILL_WINDOW) {\\n\\t\\t\\twidth = windowWidth;\\n\\t\\t\\theight = windowHeight;\\n\\t\\t}\\n\\t\\tthis.graphicsDevice.canvas.style.width = `${width}px`;\\n\\t\\tthis.graphicsDevice.canvas.style.height = `${height}px`;\\n\\t\\tthis.updateCanvasSize();\\n\\t\\treturn {\\n\\t\\t\\twidth,\\n\\t\\t\\theight\\n\\t\\t};\\n\\t}\\n\\tupdateCanvasSize() {\\n\\t\\tif (!this._allowResize || this.xr?.active) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._resolutionMode === RESOLUTION_AUTO) {\\n\\t\\t\\tconst canvas = this.graphicsDevice.canvas;\\n\\t\\t\\tthis.graphicsDevice.resizeCanvas(canvas.clientWidth, canvas.clientHeight);\\n\\t\\t}\\n\\t}\\n\\tonLibrariesLoaded() {\\n\\t\\tthis._librariesLoaded = true;\\n\\t\\tif (this.systems.rigidbody) {\\n\\t\\t\\tthis.systems.rigidbody.onLibraryLoaded();\\n\\t\\t}\\n\\t}\\n\\tapplySceneSettings(settings) {\\n\\t\\tlet asset;\\n\\t\\tif (this.systems.rigidbody && typeof Ammo !== \\\"undefined\\\") {\\n\\t\\t\\tconst [x, y, z] = settings.physics.gravity;\\n\\t\\t\\tthis.systems.rigidbody.gravity.set(x, y, z);\\n\\t\\t}\\n\\t\\tthis.scene.applySettings(settings);\\n\\t\\tif (settings.render.hasOwnProperty(\\\"skybox\\\")) {\\n\\t\\t\\tif (settings.render.skybox) {\\n\\t\\t\\t\\tasset = this.assets.get(settings.render.skybox);\\n\\t\\t\\t\\tif (asset) {\\n\\t\\t\\t\\t\\tthis.setSkybox(asset);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tthis.assets.once(`add:${settings.render.skybox}`, this.setSkybox, this);\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.setSkybox(null);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tsetAreaLightLuts(ltcMat1, ltcMat2) {\\n\\t\\tif (ltcMat1 && ltcMat2) {\\n\\t\\t\\tAreaLightLuts.set(this.graphicsDevice, ltcMat1, ltcMat2);\\n\\t\\t}\\n\\t}\\n\\tsetSkybox(asset) {\\n\\t\\tif (asset !== this._skyboxAsset) {\\n\\t\\t\\tconst onSkyboxRemoved = () => {\\n\\t\\t\\t\\tthis.setSkybox(null);\\n\\t\\t\\t};\\n\\t\\t\\tconst onSkyboxChanged = () => {\\n\\t\\t\\t\\tthis.scene.setSkybox(this._skyboxAsset ? this._skyboxAsset.resources : null);\\n\\t\\t\\t};\\n\\t\\t\\tif (this._skyboxAsset) {\\n\\t\\t\\t\\tthis.assets.off(`load:${this._skyboxAsset.id}`, onSkyboxChanged, this);\\n\\t\\t\\t\\tthis.assets.off(`remove:${this._skyboxAsset.id}`, onSkyboxRemoved, this);\\n\\t\\t\\t\\tthis._skyboxAsset.off(\\\"change\\\", onSkyboxChanged, this);\\n\\t\\t\\t}\\n\\t\\t\\tthis._skyboxAsset = asset;\\n\\t\\t\\tif (this._skyboxAsset) {\\n\\t\\t\\t\\tthis.assets.on(`load:${this._skyboxAsset.id}`, onSkyboxChanged, this);\\n\\t\\t\\t\\tthis.assets.once(`remove:${this._skyboxAsset.id}`, onSkyboxRemoved, this);\\n\\t\\t\\t\\tthis._skyboxAsset.on(\\\"change\\\", onSkyboxChanged, this);\\n\\t\\t\\t\\tif (this.scene.skyboxMip === 0 && !this._skyboxAsset.loadFaces) {\\n\\t\\t\\t\\t\\tthis._skyboxAsset.loadFaces = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.assets.load(this._skyboxAsset);\\n\\t\\t\\t}\\n\\t\\t\\tonSkyboxChanged();\\n\\t\\t}\\n\\t}\\n\\t_firstBake() {\\n\\t\\tthis.lightmapper?.bake(null, this.scene.lightmapMode);\\n\\t}\\n\\t_firstBatch() {\\n\\t\\tthis.batcher?.generate();\\n\\t}\\n\\t_processTimestamp(timestamp) {\\n\\t\\treturn timestamp;\\n\\t}\\n\\tdrawLine(start, end, color, depthTest, layer) {\\n\\t\\tthis.scene.drawLine(start, end, color, depthTest, layer);\\n\\t}\\n\\tdrawLines(positions, colors, depthTest = true, layer = this.scene.defaultDrawLayer) {\\n\\t\\tthis.scene.drawLines(positions, colors, depthTest, layer);\\n\\t}\\n\\tdrawLineArrays(positions, colors, depthTest = true, layer = this.scene.defaultDrawLayer) {\\n\\t\\tthis.scene.drawLineArrays(positions, colors, depthTest, layer);\\n\\t}\\n\\tdrawWireSphere(center, radius, color = Color.WHITE, segments = 20, depthTest = true, layer = this.scene.defaultDrawLayer) {\\n\\t\\tthis.scene.immediate.drawWireSphere(center, radius, color, segments, depthTest, layer);\\n\\t}\\n\\tdrawWireAlignedBox(minPoint, maxPoint, color = Color.WHITE, depthTest = true, layer = this.scene.defaultDrawLayer, mat) {\\n\\t\\tthis.scene.immediate.drawWireAlignedBox(minPoint, maxPoint, color, depthTest, layer, mat);\\n\\t}\\n\\tdrawMeshInstance(meshInstance, layer = this.scene.defaultDrawLayer) {\\n\\t\\tthis.scene.immediate.drawMesh(null, null, null, meshInstance, layer);\\n\\t}\\n\\tdrawMesh(mesh, material, matrix, layer = this.scene.defaultDrawLayer) {\\n\\t\\tthis.scene.immediate.drawMesh(material, matrix, mesh, null, layer);\\n\\t}\\n\\tdrawQuad(matrix, material, layer = this.scene.defaultDrawLayer) {\\n\\t\\tthis.scene.immediate.drawMesh(material, matrix, this.scene.immediate.getQuadMesh(), null, layer);\\n\\t}\\n\\tdrawTexture(x, y, width, height, texture, material, layer = this.scene.defaultDrawLayer, filterable = true) {\\n\\t\\tif (filterable === false && !this.graphicsDevice.isWebGPU) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst matrix = new Mat4();\\n\\t\\tmatrix.setTRS(new Vec3(x, y, 0), Quat.IDENTITY, new Vec3(width, -height, 0));\\n\\t\\tif (!material) {\\n\\t\\t\\tmaterial = new ShaderMaterial();\\n\\t\\t\\tmaterial.cull = CULLFACE_NONE;\\n\\t\\t\\tmaterial.setParameter(\\\"colorMap\\\", texture);\\n\\t\\t\\tmaterial.shaderDesc = filterable ? this.scene.immediate.getTextureShaderDesc(texture.encoding) : this.scene.immediate.getUnfilterableTextureShaderDesc();\\n\\t\\t\\tmaterial.update();\\n\\t\\t}\\n\\t\\tthis.drawQuad(matrix, material, layer);\\n\\t}\\n\\tdrawDepthTexture(x, y, width, height, layer = this.scene.defaultDrawLayer) {\\n\\t\\tconst material = new ShaderMaterial();\\n\\t\\tmaterial.cull = CULLFACE_NONE;\\n\\t\\tmaterial.shaderDesc = this.scene.immediate.getDepthTextureShaderDesc();\\n\\t\\tmaterial.update();\\n\\t\\tthis.drawTexture(x, y, width, height, null, material, layer);\\n\\t}\\n\\tdestroy() {\\n\\t\\tif (this._inFrameUpdate) {\\n\\t\\t\\tthis._destroyRequested = true;\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst canvasId = this.graphicsDevice.canvas.id;\\n\\t\\tthis.fire(\\\"destroy\\\", this);\\n\\t\\tthis.off(\\\"librariesloaded\\\");\\n\\t\\tthis._gsplatSortedEvt?.off();\\n\\t\\tthis._gsplatSortedEvt = null;\\n\\t\\tif (typeof document !== \\\"undefined\\\") {\\n\\t\\t\\tdocument.removeEventListener(\\\"visibilitychange\\\", this._visibilityChangeHandler, false);\\n\\t\\t}\\n\\t\\tthis._visibilityChangeHandler = null;\\n\\t\\tthis.root.destroy();\\n\\t\\tthis.root = null;\\n\\t\\tif (this.mouse) {\\n\\t\\t\\tthis.mouse.off();\\n\\t\\t\\tthis.mouse.detach();\\n\\t\\t\\tthis.mouse = null;\\n\\t\\t}\\n\\t\\tif (this.keyboard) {\\n\\t\\t\\tthis.keyboard.off();\\n\\t\\t\\tthis.keyboard.detach();\\n\\t\\t\\tthis.keyboard = null;\\n\\t\\t}\\n\\t\\tif (this.touch) {\\n\\t\\t\\tthis.touch.off();\\n\\t\\t\\tthis.touch.detach();\\n\\t\\t\\tthis.touch = null;\\n\\t\\t}\\n\\t\\tif (this.elementInput) {\\n\\t\\t\\tthis.elementInput.detach();\\n\\t\\t\\tthis.elementInput = null;\\n\\t\\t}\\n\\t\\tif (this.gamepads) {\\n\\t\\t\\tthis.gamepads.destroy();\\n\\t\\t\\tthis.gamepads = null;\\n\\t\\t}\\n\\t\\tthis.systems.destroy();\\n\\t\\tif (this.scene.layers) {\\n\\t\\t\\tthis.scene.layers.destroy();\\n\\t\\t}\\n\\t\\tthis.bundles.destroy();\\n\\t\\tthis.bundles = null;\\n\\t\\tthis.i18n.destroy();\\n\\t\\tthis.i18n = null;\\n\\t\\tconst scriptHandler = this.loader.getHandler(\\\"script\\\");\\n\\t\\tscriptHandler?.clearCache();\\n\\t\\tthis.loader.destroy();\\n\\t\\tthis.loader = null;\\n\\t\\tthis.systems = null;\\n\\t\\tthis.context = null;\\n\\t\\tthis.scripts.destroy();\\n\\t\\tthis.scripts = null;\\n\\t\\tthis.scenes.destroy();\\n\\t\\tthis.scenes = null;\\n\\t\\tthis.lightmapper?.destroy();\\n\\t\\tthis.lightmapper = null;\\n\\t\\tif (this._batcher) {\\n\\t\\t\\tthis._batcher.destroy();\\n\\t\\t\\tthis._batcher = null;\\n\\t\\t}\\n\\t\\tthis._entityIndex = {};\\n\\t\\tthis.defaultLayerDepth.onDisable = null;\\n\\t\\tthis.defaultLayerDepth.onEnable = null;\\n\\t\\tthis.defaultLayerDepth = null;\\n\\t\\tthis.defaultLayerWorld = null;\\n\\t\\tthis.xr?.end();\\n\\t\\tthis.xr?.destroy();\\n\\t\\tthis.renderer.destroy();\\n\\t\\tthis.renderer = null;\\n\\t\\tconst assets = this.assets.list();\\n\\t\\tfor (let i = 0; i < assets.length; i++) {\\n\\t\\t\\tassets[i].unload();\\n\\t\\t\\tassets[i].off();\\n\\t\\t}\\n\\t\\tthis.assets.off();\\n\\t\\tthis.scene.destroy();\\n\\t\\tthis.scene = null;\\n\\t\\tthis.graphicsDevice.destroy();\\n\\t\\tthis.graphicsDevice = null;\\n\\t\\tthis.off();\\n\\t\\tthis._soundManager?.destroy();\\n\\t\\tthis._soundManager = null;\\n\\t\\tAppBase._applications[canvasId] = null;\\n\\t\\tif (getApplication() === this) {\\n\\t\\t\\tsetApplication(null);\\n\\t\\t}\\n\\t\\tAppBase.cancelTick(this);\\n\\t}\\n\\tstatic cancelTick(app2) {\\n\\t\\tif (app2.frameRequestId) {\\n\\t\\t\\tcancelAnimationFrame(app2.frameRequestId);\\n\\t\\t\\tapp2.frameRequestId = void 0;\\n\\t\\t}\\n\\t}\\n\\tgetEntityFromIndex(guid) {\\n\\t\\treturn this._entityIndex[guid];\\n\\t}\\n\\t_registerSceneImmediate(scene) {\\n\\t\\tthis.on(\\\"postrender\\\", scene.immediate.onPostRender, scene.immediate);\\n\\t\\tthis._gsplatSortedEvt = scene.on(\\\"gsplat:sorted\\\", (sortTime) => {\\n\\t\\t\\tthis.stats.frame.gsplatSort += sortTime;\\n\\t\\t});\\n\\t}\\n}\\n\\nclass AppOptions {\\n\\telementInput;\\n\\tkeyboard;\\n\\tmouse;\\n\\ttouch;\\n\\tgamepads;\\n\\tscriptPrefix;\\n\\tassetPrefix;\\n\\tscriptsOrder;\\n\\tsoundManager;\\n\\tgraphicsDevice;\\n\\tlightmapper;\\n\\tbatchManager;\\n\\txr;\\n\\tcomponentSystems = [];\\n\\tresourceHandlers = [];\\n}\\n\\nclass Component extends EventHandler {\\n\\tstatic order = 0;\\n\\tsystem;\\n\\tentity;\\n\\tconstructor(system, entity) {\\n\\t\\tsuper();\\n\\t\\tthis.system = system;\\n\\t\\tthis.entity = entity;\\n\\t\\tif (this.system.schema && !this._accessorsBuilt) {\\n\\t\\t\\tthis.buildAccessors(this.system.schema);\\n\\t\\t}\\n\\t\\tthis.on(\\\"set\\\", function(name, oldValue, newValue) {\\n\\t\\t\\tthis.fire(`set_${name}`, name, oldValue, newValue);\\n\\t\\t});\\n\\t\\tthis.on(\\\"set_enabled\\\", this.onSetEnabled, this);\\n\\t}\\n\\tstatic _buildAccessors(obj, schema) {\\n\\t\\tschema.forEach((descriptor) => {\\n\\t\\t\\tconst name = typeof descriptor === \\\"object\\\" ? descriptor.name : descriptor;\\n\\t\\t\\tObject.defineProperty(obj, name, {\\n\\t\\t\\t\\tget: function() {\\n\\t\\t\\t\\t\\treturn this.data[name];\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\tset: function(value) {\\n\\t\\t\\t\\t\\tconst data = this.data;\\n\\t\\t\\t\\t\\tconst oldValue = data[name];\\n\\t\\t\\t\\t\\tdata[name] = value;\\n\\t\\t\\t\\t\\tthis.fire(\\\"set\\\", name, oldValue, value);\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\tconfigurable: true\\n\\t\\t\\t});\\n\\t\\t});\\n\\t\\tobj._accessorsBuilt = true;\\n\\t}\\n\\tbuildAccessors(schema) {\\n\\t\\tComponent._buildAccessors(this, schema);\\n\\t}\\n\\tonSetEnabled(name, oldValue, newValue) {\\n\\t\\tif (oldValue !== newValue) {\\n\\t\\t\\tif (this.entity.enabled) {\\n\\t\\t\\t\\tif (newValue) {\\n\\t\\t\\t\\t\\tthis.onEnable();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tthis.onDisable();\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tonEnable() {\\n\\t}\\n\\tonDisable() {\\n\\t}\\n\\tonPostStateChange() {\\n\\t}\\n\\tget data() {\\n\\t\\tconst record = this.system.store[this.entity.guid];\\n\\t\\treturn record ? record.data : null;\\n\\t}\\n\\tset enabled(arg) {\\n\\t}\\n\\tget enabled() {\\n\\t\\treturn true;\\n\\t}\\n}\\n\\nclass ComponentSystem extends EventHandler {\\n\\tid;\\n\\tconstructor(app) {\\n\\t\\tsuper();\\n\\t\\tthis.app = app;\\n\\t\\tthis.store = {};\\n\\t\\tthis.schema = [];\\n\\t}\\n\\taddComponent(entity, data = {}) {\\n\\t\\tconst component = new this.ComponentType(this, entity);\\n\\t\\tconst componentData = new this.DataType();\\n\\t\\tthis.store[entity.guid] = {\\n\\t\\t\\tentity,\\n\\t\\t\\tdata: componentData\\n\\t\\t};\\n\\t\\tentity[this.id] = component;\\n\\t\\tentity.c[this.id] = component;\\n\\t\\tthis.initializeComponentData(component, data, []);\\n\\t\\tthis.fire(\\\"add\\\", entity, component);\\n\\t\\treturn component;\\n\\t}\\n\\tremoveComponent(entity) {\\n\\t\\tconst id = this.id;\\n\\t\\tconst record = this.store[entity.guid];\\n\\t\\tconst component = entity.c[id];\\n\\t\\tcomponent.fire(\\\"beforeremove\\\");\\n\\t\\tthis.fire(\\\"beforeremove\\\", entity, component);\\n\\t\\tdelete this.store[entity.guid];\\n\\t\\tentity[id] = void 0;\\n\\t\\tdelete entity.c[id];\\n\\t\\tthis.fire(\\\"remove\\\", entity, record.data);\\n\\t}\\n\\tcloneComponent(entity, clone) {\\n\\t\\tconst src = this.store[entity.guid];\\n\\t\\treturn this.addComponent(clone, src.data);\\n\\t}\\n\\tinitializeComponentData(component, data = {}, properties) {\\n\\t\\tfor (let i = 0, len = properties.length; i < len; i++) {\\n\\t\\t\\tconst descriptor = properties[i];\\n\\t\\t\\tlet name, type;\\n\\t\\t\\tif (typeof descriptor === \\\"object\\\") {\\n\\t\\t\\t\\tname = descriptor.name;\\n\\t\\t\\t\\ttype = descriptor.type;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tname = descriptor;\\n\\t\\t\\t\\ttype = void 0;\\n\\t\\t\\t}\\n\\t\\t\\tlet value = data[name];\\n\\t\\t\\tif (value !== void 0) {\\n\\t\\t\\t\\tif (type !== void 0) {\\n\\t\\t\\t\\t\\tvalue = convertValue(value, type);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcomponent[name] = value;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tcomponent[name] = component.data[name];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (component.enabled && component.entity.enabled) {\\n\\t\\t\\tcomponent.onEnable();\\n\\t\\t}\\n\\t}\\n\\tgetPropertiesOfType(type) {\\n\\t\\tconst matchingProperties = [];\\n\\t\\tconst schema = this.schema || [];\\n\\t\\tschema.forEach((descriptor) => {\\n\\t\\t\\tif (descriptor && typeof descriptor === \\\"object\\\" && descriptor.type === type) {\\n\\t\\t\\t\\tmatchingProperties.push(descriptor);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\treturn matchingProperties;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.off();\\n\\t}\\n}\\nfunction convertValue(value, type) {\\n\\tif (!value) {\\n\\t\\treturn value;\\n\\t}\\n\\tswitch (type) {\\n\\t\\tcase \\\"rgb\\\":\\n\\t\\t\\tif (value instanceof Color) {\\n\\t\\t\\t\\treturn value.clone();\\n\\t\\t\\t}\\n\\t\\t\\treturn new Color(value[0], value[1], value[2]);\\n\\t\\tcase \\\"rgba\\\":\\n\\t\\t\\tif (value instanceof Color) {\\n\\t\\t\\t\\treturn value.clone();\\n\\t\\t\\t}\\n\\t\\t\\treturn new Color(value[0], value[1], value[2], value[3]);\\n\\t\\tcase \\\"vec2\\\":\\n\\t\\t\\tif (value instanceof Vec2) {\\n\\t\\t\\t\\treturn value.clone();\\n\\t\\t\\t}\\n\\t\\t\\treturn new Vec2(value[0], value[1]);\\n\\t\\tcase \\\"vec3\\\":\\n\\t\\t\\tif (value instanceof Vec3) {\\n\\t\\t\\t\\treturn value.clone();\\n\\t\\t\\t}\\n\\t\\t\\treturn new Vec3(value[0], value[1], value[2]);\\n\\t\\tcase \\\"vec4\\\":\\n\\t\\t\\tif (value instanceof Vec4) {\\n\\t\\t\\t\\treturn value.clone();\\n\\t\\t\\t}\\n\\t\\t\\treturn new Vec4(value[0], value[1], value[2], value[3]);\\n\\t\\tcase \\\"boolean\\\":\\n\\t\\tcase \\\"number\\\":\\n\\t\\tcase \\\"string\\\":\\n\\t\\t\\treturn value;\\n\\t\\tcase \\\"entity\\\":\\n\\t\\t\\treturn value;\\n\\t\\t// Entity fields should just be a string guid\\n\\t\\tdefault:\\n\\t\\t\\tthrow new Error(`Could not convert unhandled type: ${type}`);\\n\\t}\\n}\\n\\nconst INTERPOLATION_STEP = 0;\\nconst INTERPOLATION_LINEAR = 1;\\nconst INTERPOLATION_CUBIC = 2;\\n\\nclass AnimEvents {\\n\\tconstructor(events) {\\n\\t\\tthis._events = [...events];\\n\\t\\tthis._events.sort((a, b) => a.time - b.time);\\n\\t}\\n\\tget events() {\\n\\t\\treturn this._events;\\n\\t}\\n}\\n\\nclass AnimTrack {\\n\\tstatic EMPTY = Object.freeze(new AnimTrack(\\\"empty\\\", Number.MAX_VALUE, [], [], []));\\n\\tconstructor(name, duration, inputs, outputs, curves, animEvents = new AnimEvents([])) {\\n\\t\\tthis._name = name;\\n\\t\\tthis._duration = duration;\\n\\t\\tthis._inputs = inputs;\\n\\t\\tthis._outputs = outputs;\\n\\t\\tthis._curves = curves;\\n\\t\\tthis._animEvents = animEvents;\\n\\t}\\n\\tget name() {\\n\\t\\treturn this._name;\\n\\t}\\n\\tget duration() {\\n\\t\\treturn this._duration;\\n\\t}\\n\\tget inputs() {\\n\\t\\treturn this._inputs;\\n\\t}\\n\\tget outputs() {\\n\\t\\treturn this._outputs;\\n\\t}\\n\\tget curves() {\\n\\t\\treturn this._curves;\\n\\t}\\n\\tset events(animEvents) {\\n\\t\\tthis._animEvents = animEvents;\\n\\t}\\n\\tget events() {\\n\\t\\treturn this._animEvents.events;\\n\\t}\\n\\t// evaluate all track curves at the specified time and store results\\n\\t// in the provided snapshot.\\n\\teval(time, snapshot) {\\n\\t\\tsnapshot._time = time;\\n\\t\\tconst inputs = this._inputs;\\n\\t\\tconst outputs = this._outputs;\\n\\t\\tconst curves = this._curves;\\n\\t\\tconst cache = snapshot._cache;\\n\\t\\tconst results = snapshot._results;\\n\\t\\tfor (let i = 0; i < inputs.length; ++i) {\\n\\t\\t\\tcache[i].update(time, inputs[i]._data);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < curves.length; ++i) {\\n\\t\\t\\tconst curve = curves[i];\\n\\t\\t\\tconst output = outputs[curve._output];\\n\\t\\t\\tconst result = results[i];\\n\\t\\t\\tcache[curve._input].eval(result, curve._interpolation, output);\\n\\t\\t}\\n\\t}\\n}\\n\\nconst BODYTYPE_STATIC = \\\"static\\\";\\nconst BODYTYPE_DYNAMIC = \\\"dynamic\\\";\\nconst BODYTYPE_KINEMATIC = \\\"kinematic\\\";\\nconst BODYFLAG_KINEMATIC_OBJECT = 2;\\nconst BODYFLAG_NORESPONSE_OBJECT = 4;\\nconst BODYSTATE_ACTIVE_TAG = 1;\\nconst BODYSTATE_DISABLE_DEACTIVATION = 4;\\nconst BODYSTATE_DISABLE_SIMULATION = 5;\\nconst BODYGROUP_DYNAMIC = 1;\\nconst BODYGROUP_STATIC = 2;\\nconst BODYGROUP_KINEMATIC = 4;\\nconst BODYMASK_ALL = 65535;\\nconst BODYMASK_NOT_STATIC = 65535 ^ 2;\\n\\nclass PrimitivesCache {\\n\\tmap = /* @__PURE__ */ new Map();\\n\\t// destroy all created primitives when the device is destroyed\\n\\tdestroy(device) {\\n\\t\\tthis.map.forEach((primData) => primData.mesh.destroy());\\n\\t}\\n}\\nconst _primitivesCache = new DeviceCache();\\nconst getShapePrimitive = (device, type) => {\\n\\tconst cache = _primitivesCache.get(device, () => {\\n\\t\\treturn new PrimitivesCache();\\n\\t});\\n\\tlet primData = cache.map.get(type);\\n\\tif (!primData) {\\n\\t\\tlet mesh, area;\\n\\t\\tswitch (type) {\\n\\t\\t\\tcase \\\"box\\\":\\n\\t\\t\\t\\tmesh = Mesh.fromGeometry(device, new BoxGeometry());\\n\\t\\t\\t\\tarea = { x: 2, y: 2, z: 2, uv: 2 / 3 };\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase \\\"capsule\\\":\\n\\t\\t\\t\\tmesh = Mesh.fromGeometry(device, new CapsuleGeometry({ radius: 0.5, height: 2 }));\\n\\t\\t\\t\\tarea = { x: Math.PI * 2, y: Math.PI, z: Math.PI * 2, uv: 1 / 3 + 1 / 3 / 3 * 2 };\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase \\\"cone\\\":\\n\\t\\t\\t\\tmesh = Mesh.fromGeometry(device, new ConeGeometry({ baseRadius: 0.5, peakRadius: 0, height: 1 }));\\n\\t\\t\\t\\tarea = { x: 2.54, y: 2.54, z: 2.54, uv: 1 / 3 + 1 / 3 / 3 };\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase \\\"cylinder\\\":\\n\\t\\t\\t\\tmesh = Mesh.fromGeometry(device, new CylinderGeometry({ radius: 0.5, height: 1 }));\\n\\t\\t\\t\\tarea = { x: Math.PI, y: 0.79 * 2, z: Math.PI, uv: 1 / 3 + 1 / 3 / 3 * 2 };\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase \\\"plane\\\":\\n\\t\\t\\t\\tmesh = Mesh.fromGeometry(device, new PlaneGeometry({ halfExtents: new Vec2(0.5, 0.5), widthSegments: 1, lengthSegments: 1 }));\\n\\t\\t\\t\\tarea = { x: 0, y: 1, z: 0, uv: 1 };\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase \\\"sphere\\\":\\n\\t\\t\\t\\tmesh = Mesh.fromGeometry(device, new SphereGeometry({ radius: 0.5 }));\\n\\t\\t\\t\\tarea = { x: Math.PI, y: Math.PI, z: Math.PI, uv: 1 };\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase \\\"torus\\\":\\n\\t\\t\\t\\tmesh = Mesh.fromGeometry(device, new TorusGeometry({ tubeRadius: 0.2, ringRadius: 0.3 }));\\n\\t\\t\\t\\tarea = { x: Math.PI * 0.5 * 0.5 - Math.PI * 0.1 * 0.1, y: 0.4, z: 0.4, uv: 1 };\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tdefault:\\n\\t\\t\\t\\tthrow new Error(`Invalid primitive type: ${type}`);\\n\\t\\t}\\n\\t\\tmesh.incRefCount();\\n\\t\\tprimData = { mesh, area };\\n\\t\\tcache.map.set(type, primData);\\n\\t}\\n\\treturn primData;\\n};\\n\\nclass ModelComponent extends Component {\\n\\t_type = \\\"asset\\\";\\n\\t_asset = null;\\n\\t_model = null;\\n\\t_mapping = {};\\n\\t_castShadows = true;\\n\\t_receiveShadows = true;\\n\\t_materialAsset = null;\\n\\t_material;\\n\\t_castShadowsLightmap = true;\\n\\t_lightmapped = false;\\n\\t_lightmapSizeMultiplier = 1;\\n\\tisStatic = false;\\n\\t_layers = [LAYERID_WORLD];\\n\\t// assign to the default world layer\\n\\t_batchGroupId = -1;\\n\\t_customAabb = null;\\n\\t_area = null;\\n\\t_materialEvents = null;\\n\\t_clonedModel = false;\\n\\t_evtLayersChanged = null;\\n\\t_evtLayerAdded = null;\\n\\t_evtLayerRemoved = null;\\n\\tconstructor(system, entity) {\\n\\t\\tsuper(system, entity);\\n\\t\\tthis._material = system.defaultMaterial;\\n\\t\\tentity.on(\\\"remove\\\", this.onRemoveChild, this);\\n\\t\\tentity.on(\\\"removehierarchy\\\", this.onRemoveChild, this);\\n\\t\\tentity.on(\\\"insert\\\", this.onInsertChild, this);\\n\\t\\tentity.on(\\\"inserthierarchy\\\", this.onInsertChild, this);\\n\\t}\\n\\tset meshInstances(value) {\\n\\t\\tif (!this._model) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._model.meshInstances = value;\\n\\t}\\n\\tget meshInstances() {\\n\\t\\tif (!this._model) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\treturn this._model.meshInstances;\\n\\t}\\n\\tset customAabb(value) {\\n\\t\\tthis._customAabb = value;\\n\\t\\tif (this._model) {\\n\\t\\t\\tconst mi = this._model.meshInstances;\\n\\t\\t\\tif (mi) {\\n\\t\\t\\t\\tfor (let i = 0; i < mi.length; i++) {\\n\\t\\t\\t\\t\\tmi[i].setCustomAabb(this._customAabb);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget customAabb() {\\n\\t\\treturn this._customAabb;\\n\\t}\\n\\tset type(value) {\\n\\t\\tif (this._type === value) return;\\n\\t\\tthis._area = null;\\n\\t\\tthis._type = value;\\n\\t\\tif (value === \\\"asset\\\") {\\n\\t\\t\\tif (this._asset !== null) {\\n\\t\\t\\t\\tthis._bindModelAsset(this._asset);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.model = null;\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tconst primData = getShapePrimitive(this.system.app.graphicsDevice, value);\\n\\t\\t\\tthis._area = primData.area;\\n\\t\\t\\tconst mesh = primData.mesh;\\n\\t\\t\\tconst node = new GraphNode();\\n\\t\\t\\tconst model = new Model();\\n\\t\\t\\tmodel.graph = node;\\n\\t\\t\\tmodel.meshInstances = [new MeshInstance(mesh, this._material, node)];\\n\\t\\t\\tthis.model = model;\\n\\t\\t\\tthis._asset = null;\\n\\t\\t}\\n\\t}\\n\\tget type() {\\n\\t\\treturn this._type;\\n\\t}\\n\\tset asset(value) {\\n\\t\\tconst assets = this.system.app.assets;\\n\\t\\tlet _id = value;\\n\\t\\tif (value instanceof Asset) {\\n\\t\\t\\t_id = value.id;\\n\\t\\t}\\n\\t\\tif (this._asset !== _id) {\\n\\t\\t\\tif (this._asset) {\\n\\t\\t\\t\\tassets.off(`add:${this._asset}`, this._onModelAssetAdded, this);\\n\\t\\t\\t\\tconst _prev = assets.get(this._asset);\\n\\t\\t\\t\\tif (_prev) {\\n\\t\\t\\t\\t\\tthis._unbindModelAsset(_prev);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis._asset = _id;\\n\\t\\t\\tif (this._asset) {\\n\\t\\t\\t\\tconst asset = assets.get(this._asset);\\n\\t\\t\\t\\tif (!asset) {\\n\\t\\t\\t\\t\\tthis.model = null;\\n\\t\\t\\t\\t\\tassets.on(`add:${this._asset}`, this._onModelAssetAdded, this);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tthis._bindModelAsset(asset);\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.model = null;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget asset() {\\n\\t\\treturn this._asset;\\n\\t}\\n\\tset model(value) {\\n\\t\\tif (this._model === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (value && value._immutable) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._model) {\\n\\t\\t\\tthis._model._immutable = false;\\n\\t\\t\\tthis.removeModelFromLayers();\\n\\t\\t\\tthis._model.getGraph().destroy();\\n\\t\\t\\tdelete this._model._entity;\\n\\t\\t\\tif (this._clonedModel) {\\n\\t\\t\\t\\tthis._model.destroy();\\n\\t\\t\\t\\tthis._clonedModel = false;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._model = value;\\n\\t\\tif (this._model) {\\n\\t\\t\\tthis._model._immutable = true;\\n\\t\\t\\tconst meshInstances = this._model.meshInstances;\\n\\t\\t\\tfor (let i = 0; i < meshInstances.length; i++) {\\n\\t\\t\\t\\tmeshInstances[i].castShadow = this._castShadows;\\n\\t\\t\\t\\tmeshInstances[i].receiveShadow = this._receiveShadows;\\n\\t\\t\\t\\tmeshInstances[i].setCustomAabb(this._customAabb);\\n\\t\\t\\t}\\n\\t\\t\\tthis.lightmapped = this._lightmapped;\\n\\t\\t\\tthis.entity.addChild(this._model.graph);\\n\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\tthis.addModelToLayers();\\n\\t\\t\\t}\\n\\t\\t\\tthis._model._entity = this.entity;\\n\\t\\t\\tif (this.entity.animation) {\\n\\t\\t\\t\\tthis.entity.animation.setModel(this._model);\\n\\t\\t\\t}\\n\\t\\t\\tif (this.entity.anim) {\\n\\t\\t\\t\\tthis.entity.anim.rebind();\\n\\t\\t\\t}\\n\\t\\t\\tif (this.type === \\\"asset\\\") {\\n\\t\\t\\t\\tthis.mapping = this._mapping;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._unsetMaterialEvents();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget model() {\\n\\t\\treturn this._model;\\n\\t}\\n\\tset lightmapped(value) {\\n\\t\\tif (value !== this._lightmapped) {\\n\\t\\t\\tthis._lightmapped = value;\\n\\t\\t\\tif (this._model) {\\n\\t\\t\\t\\tconst mi = this._model.meshInstances;\\n\\t\\t\\t\\tfor (let i = 0; i < mi.length; i++) {\\n\\t\\t\\t\\t\\tmi[i].setLightmapped(value);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget lightmapped() {\\n\\t\\treturn this._lightmapped;\\n\\t}\\n\\tset castShadows(value) {\\n\\t\\tif (this._castShadows === value) return;\\n\\t\\tconst model = this._model;\\n\\t\\tif (model) {\\n\\t\\t\\tconst layers = this.layers;\\n\\t\\t\\tconst scene = this.system.app.scene;\\n\\t\\t\\tif (this._castShadows && !value) {\\n\\t\\t\\t\\tfor (let i = 0; i < layers.length; i++) {\\n\\t\\t\\t\\t\\tconst layer = this.system.app.scene.layers.getLayerById(this.layers[i]);\\n\\t\\t\\t\\t\\tif (!layer) continue;\\n\\t\\t\\t\\t\\tlayer.removeShadowCasters(model.meshInstances);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tconst meshInstances = model.meshInstances;\\n\\t\\t\\tfor (let i = 0; i < meshInstances.length; i++) {\\n\\t\\t\\t\\tmeshInstances[i].castShadow = value;\\n\\t\\t\\t}\\n\\t\\t\\tif (!this._castShadows && value) {\\n\\t\\t\\t\\tfor (let i = 0; i < layers.length; i++) {\\n\\t\\t\\t\\t\\tconst layer = scene.layers.getLayerById(layers[i]);\\n\\t\\t\\t\\t\\tif (!layer) continue;\\n\\t\\t\\t\\t\\tlayer.addShadowCasters(model.meshInstances);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._castShadows = value;\\n\\t}\\n\\tget castShadows() {\\n\\t\\treturn this._castShadows;\\n\\t}\\n\\tset receiveShadows(value) {\\n\\t\\tif (this._receiveShadows === value) return;\\n\\t\\tthis._receiveShadows = value;\\n\\t\\tif (this._model) {\\n\\t\\t\\tconst meshInstances = this._model.meshInstances;\\n\\t\\t\\tfor (let i = 0, len = meshInstances.length; i < len; i++) {\\n\\t\\t\\t\\tmeshInstances[i].receiveShadow = value;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget receiveShadows() {\\n\\t\\treturn this._receiveShadows;\\n\\t}\\n\\tset castShadowsLightmap(value) {\\n\\t\\tthis._castShadowsLightmap = value;\\n\\t}\\n\\tget castShadowsLightmap() {\\n\\t\\treturn this._castShadowsLightmap;\\n\\t}\\n\\tset lightmapSizeMultiplier(value) {\\n\\t\\tthis._lightmapSizeMultiplier = value;\\n\\t}\\n\\tget lightmapSizeMultiplier() {\\n\\t\\treturn this._lightmapSizeMultiplier;\\n\\t}\\n\\tset layers(value) {\\n\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\tif (this.meshInstances) {\\n\\t\\t\\tfor (let i = 0; i < this._layers.length; i++) {\\n\\t\\t\\t\\tconst layer = layers.getLayerById(this._layers[i]);\\n\\t\\t\\t\\tif (!layer) continue;\\n\\t\\t\\t\\tlayer.removeMeshInstances(this.meshInstances);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._layers.length = 0;\\n\\t\\tfor (let i = 0; i < value.length; i++) {\\n\\t\\t\\tthis._layers[i] = value[i];\\n\\t\\t}\\n\\t\\tif (!this.enabled || !this.entity.enabled || !this.meshInstances) return;\\n\\t\\tfor (let i = 0; i < this._layers.length; i++) {\\n\\t\\t\\tconst layer = layers.getLayerById(this._layers[i]);\\n\\t\\t\\tif (!layer) continue;\\n\\t\\t\\tlayer.addMeshInstances(this.meshInstances);\\n\\t\\t}\\n\\t}\\n\\tget layers() {\\n\\t\\treturn this._layers;\\n\\t}\\n\\tset batchGroupId(value) {\\n\\t\\tif (this._batchGroupId === value) return;\\n\\t\\tif (this.entity.enabled && this._batchGroupId >= 0) {\\n\\t\\t\\tthis.system.app.batcher?.remove(BatchGroup.MODEL, this.batchGroupId, this.entity);\\n\\t\\t}\\n\\t\\tif (this.entity.enabled && value >= 0) {\\n\\t\\t\\tthis.system.app.batcher?.insert(BatchGroup.MODEL, value, this.entity);\\n\\t\\t}\\n\\t\\tif (value < 0 && this._batchGroupId >= 0 && this.enabled && this.entity.enabled) {\\n\\t\\t\\tthis.addModelToLayers();\\n\\t\\t}\\n\\t\\tthis._batchGroupId = value;\\n\\t}\\n\\tget batchGroupId() {\\n\\t\\treturn this._batchGroupId;\\n\\t}\\n\\tset materialAsset(value) {\\n\\t\\tlet _id = value;\\n\\t\\tif (value instanceof Asset) {\\n\\t\\t\\t_id = value.id;\\n\\t\\t}\\n\\t\\tconst assets = this.system.app.assets;\\n\\t\\tif (_id !== this._materialAsset) {\\n\\t\\t\\tif (this._materialAsset) {\\n\\t\\t\\t\\tassets.off(`add:${this._materialAsset}`, this._onMaterialAssetAdd, this);\\n\\t\\t\\t\\tconst _prev = assets.get(this._materialAsset);\\n\\t\\t\\t\\tif (_prev) {\\n\\t\\t\\t\\t\\tthis._unbindMaterialAsset(_prev);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis._materialAsset = _id;\\n\\t\\t\\tif (this._materialAsset) {\\n\\t\\t\\t\\tconst asset = assets.get(this._materialAsset);\\n\\t\\t\\t\\tif (!asset) {\\n\\t\\t\\t\\t\\tthis._setMaterial(this.system.defaultMaterial);\\n\\t\\t\\t\\t\\tassets.on(`add:${this._materialAsset}`, this._onMaterialAssetAdd, this);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tthis._bindMaterialAsset(asset);\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._setMaterial(this.system.defaultMaterial);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget materialAsset() {\\n\\t\\treturn this._materialAsset;\\n\\t}\\n\\tset material(value) {\\n\\t\\tif (this._material === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.materialAsset = null;\\n\\t\\tthis._setMaterial(value);\\n\\t}\\n\\tget material() {\\n\\t\\treturn this._material;\\n\\t}\\n\\tset mapping(value) {\\n\\t\\tif (this._type !== \\\"asset\\\") {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._unsetMaterialEvents();\\n\\t\\tif (!value) {\\n\\t\\t\\tvalue = {};\\n\\t\\t}\\n\\t\\tthis._mapping = value;\\n\\t\\tif (!this._model) return;\\n\\t\\tconst meshInstances = this._model.meshInstances;\\n\\t\\tconst modelAsset = this.asset ? this.system.app.assets.get(this.asset) : null;\\n\\t\\tconst assetMapping = modelAsset ? modelAsset.data.mapping : null;\\n\\t\\tlet asset = null;\\n\\t\\tfor (let i = 0, len = meshInstances.length; i < len; i++) {\\n\\t\\t\\tif (value[i] !== void 0) {\\n\\t\\t\\t\\tif (value[i]) {\\n\\t\\t\\t\\t\\tasset = this.system.app.assets.get(value[i]);\\n\\t\\t\\t\\t\\tthis._loadAndSetMeshInstanceMaterial(asset, meshInstances[i], i);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tmeshInstances[i].material = this.system.defaultMaterial;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else if (assetMapping) {\\n\\t\\t\\t\\tif (assetMapping[i] && (assetMapping[i].material || assetMapping[i].path)) {\\n\\t\\t\\t\\t\\tif (assetMapping[i].material !== void 0) {\\n\\t\\t\\t\\t\\t\\tasset = this.system.app.assets.get(assetMapping[i].material);\\n\\t\\t\\t\\t\\t} else if (assetMapping[i].path !== void 0) {\\n\\t\\t\\t\\t\\t\\tconst url = this._getMaterialAssetUrl(assetMapping[i].path);\\n\\t\\t\\t\\t\\t\\tif (url) {\\n\\t\\t\\t\\t\\t\\t\\tasset = this.system.app.assets.getByUrl(url);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tthis._loadAndSetMeshInstanceMaterial(asset, meshInstances[i], i);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tmeshInstances[i].material = this.system.defaultMaterial;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget mapping() {\\n\\t\\treturn this._mapping;\\n\\t}\\n\\taddModelToLayers() {\\n\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\tfor (let i = 0; i < this._layers.length; i++) {\\n\\t\\t\\tconst layer = layers.getLayerById(this._layers[i]);\\n\\t\\t\\tif (layer) {\\n\\t\\t\\t\\tlayer.addMeshInstances(this.meshInstances);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tremoveModelFromLayers() {\\n\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\tfor (let i = 0; i < this._layers.length; i++) {\\n\\t\\t\\tconst layer = layers.getLayerById(this._layers[i]);\\n\\t\\t\\tif (!layer) continue;\\n\\t\\t\\tlayer.removeMeshInstances(this.meshInstances);\\n\\t\\t}\\n\\t}\\n\\tonRemoveChild() {\\n\\t\\tif (this._model) {\\n\\t\\t\\tthis.removeModelFromLayers();\\n\\t\\t}\\n\\t}\\n\\tonInsertChild() {\\n\\t\\tif (this._model && this.enabled && this.entity.enabled) {\\n\\t\\t\\tthis.addModelToLayers();\\n\\t\\t}\\n\\t}\\n\\tonRemove() {\\n\\t\\tthis.asset = null;\\n\\t\\tthis.model = null;\\n\\t\\tthis.materialAsset = null;\\n\\t\\tthis._unsetMaterialEvents();\\n\\t\\tthis.entity.off(\\\"remove\\\", this.onRemoveChild, this);\\n\\t\\tthis.entity.off(\\\"insert\\\", this.onInsertChild, this);\\n\\t}\\n\\tonLayersChanged(oldComp, newComp) {\\n\\t\\tthis.addModelToLayers();\\n\\t\\toldComp.off(\\\"add\\\", this.onLayerAdded, this);\\n\\t\\toldComp.off(\\\"remove\\\", this.onLayerRemoved, this);\\n\\t\\tnewComp.on(\\\"add\\\", this.onLayerAdded, this);\\n\\t\\tnewComp.on(\\\"remove\\\", this.onLayerRemoved, this);\\n\\t}\\n\\tonLayerAdded(layer) {\\n\\t\\tconst index = this.layers.indexOf(layer.id);\\n\\t\\tif (index < 0) return;\\n\\t\\tlayer.addMeshInstances(this.meshInstances);\\n\\t}\\n\\tonLayerRemoved(layer) {\\n\\t\\tconst index = this.layers.indexOf(layer.id);\\n\\t\\tif (index < 0) return;\\n\\t\\tlayer.removeMeshInstances(this.meshInstances);\\n\\t}\\n\\t_setMaterialEvent(index, event, id, handler) {\\n\\t\\tconst evt = `${event}:${id}`;\\n\\t\\tthis.system.app.assets.on(evt, handler, this);\\n\\t\\tif (!this._materialEvents) {\\n\\t\\t\\tthis._materialEvents = [];\\n\\t\\t}\\n\\t\\tif (!this._materialEvents[index]) {\\n\\t\\t\\tthis._materialEvents[index] = {};\\n\\t\\t}\\n\\t\\tthis._materialEvents[index][evt] = {\\n\\t\\t\\tid,\\n\\t\\t\\thandler\\n\\t\\t};\\n\\t}\\n\\t_unsetMaterialEvents() {\\n\\t\\tconst assets = this.system.app.assets;\\n\\t\\tconst events = this._materialEvents;\\n\\t\\tif (!events) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tfor (let i = 0, len = events.length; i < len; i++) {\\n\\t\\t\\tif (!events[i]) continue;\\n\\t\\t\\tconst evt = events[i];\\n\\t\\t\\tfor (const key in evt) {\\n\\t\\t\\t\\tassets.off(key, evt[key].handler, this);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._materialEvents = null;\\n\\t}\\n\\t_getAssetByIdOrPath(idOrPath) {\\n\\t\\tlet asset = null;\\n\\t\\tconst isPath = isNaN(parseInt(idOrPath, 10));\\n\\t\\tif (!isPath) {\\n\\t\\t\\tasset = this.system.app.assets.get(idOrPath);\\n\\t\\t} else if (this.asset) {\\n\\t\\t\\tconst url = this._getMaterialAssetUrl(idOrPath);\\n\\t\\t\\tif (url) {\\n\\t\\t\\t\\tasset = this.system.app.assets.getByUrl(url);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn asset;\\n\\t}\\n\\t_getMaterialAssetUrl(path) {\\n\\t\\tif (!this.asset) return null;\\n\\t\\tconst modelAsset = this.system.app.assets.get(this.asset);\\n\\t\\treturn modelAsset ? modelAsset.getAbsoluteUrl(path) : null;\\n\\t}\\n\\t_loadAndSetMeshInstanceMaterial(materialAsset, meshInstance, index) {\\n\\t\\tconst assets = this.system.app.assets;\\n\\t\\tif (!materialAsset) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (materialAsset.resource) {\\n\\t\\t\\tmeshInstance.material = materialAsset.resource;\\n\\t\\t\\tthis._setMaterialEvent(index, \\\"remove\\\", materialAsset.id, function() {\\n\\t\\t\\t\\tmeshInstance.material = this.system.defaultMaterial;\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\tthis._setMaterialEvent(index, \\\"load\\\", materialAsset.id, function(asset) {\\n\\t\\t\\t\\tmeshInstance.material = asset.resource;\\n\\t\\t\\t\\tthis._setMaterialEvent(index, \\\"remove\\\", materialAsset.id, function() {\\n\\t\\t\\t\\t\\tmeshInstance.material = this.system.defaultMaterial;\\n\\t\\t\\t\\t});\\n\\t\\t\\t});\\n\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\tassets.load(materialAsset);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tonEnable() {\\n\\t\\tconst app = this.system.app;\\n\\t\\tconst scene = app.scene;\\n\\t\\tconst layers = scene?.layers;\\n\\t\\tthis._evtLayersChanged = scene.on(\\\"set:layers\\\", this.onLayersChanged, this);\\n\\t\\tif (layers) {\\n\\t\\t\\tthis._evtLayerAdded = layers.on(\\\"add\\\", this.onLayerAdded, this);\\n\\t\\t\\tthis._evtLayerRemoved = layers.on(\\\"remove\\\", this.onLayerRemoved, this);\\n\\t\\t}\\n\\t\\tconst isAsset = this._type === \\\"asset\\\";\\n\\t\\tlet asset;\\n\\t\\tif (this._model) {\\n\\t\\t\\tthis.addModelToLayers();\\n\\t\\t} else if (isAsset && this._asset) {\\n\\t\\t\\tasset = app.assets.get(this._asset);\\n\\t\\t\\tif (asset && asset.resource !== this._model) {\\n\\t\\t\\t\\tthis._bindModelAsset(asset);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this._materialAsset) {\\n\\t\\t\\tasset = app.assets.get(this._materialAsset);\\n\\t\\t\\tif (asset && asset.resource !== this._material) {\\n\\t\\t\\t\\tthis._bindMaterialAsset(asset);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (isAsset) {\\n\\t\\t\\tif (this._mapping) {\\n\\t\\t\\t\\tfor (const index in this._mapping) {\\n\\t\\t\\t\\t\\tif (this._mapping[index]) {\\n\\t\\t\\t\\t\\t\\tasset = this._getAssetByIdOrPath(this._mapping[index]);\\n\\t\\t\\t\\t\\t\\tif (asset && !asset.resource) {\\n\\t\\t\\t\\t\\t\\t\\tapp.assets.load(asset);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this._batchGroupId >= 0) {\\n\\t\\t\\tapp.batcher?.insert(BatchGroup.MODEL, this.batchGroupId, this.entity);\\n\\t\\t}\\n\\t}\\n\\tonDisable() {\\n\\t\\tconst app = this.system.app;\\n\\t\\tconst scene = app.scene;\\n\\t\\tconst layers = scene.layers;\\n\\t\\tthis._evtLayersChanged?.off();\\n\\t\\tthis._evtLayersChanged = null;\\n\\t\\tif (layers) {\\n\\t\\t\\tthis._evtLayerAdded?.off();\\n\\t\\t\\tthis._evtLayerAdded = null;\\n\\t\\t\\tthis._evtLayerRemoved?.off();\\n\\t\\t\\tthis._evtLayerRemoved = null;\\n\\t\\t}\\n\\t\\tif (this._batchGroupId >= 0) {\\n\\t\\t\\tapp.batcher?.remove(BatchGroup.MODEL, this.batchGroupId, this.entity);\\n\\t\\t}\\n\\t\\tif (this._model) {\\n\\t\\t\\tthis.removeModelFromLayers();\\n\\t\\t}\\n\\t}\\n\\thide() {\\n\\t\\tif (this._model) {\\n\\t\\t\\tconst instances = this._model.meshInstances;\\n\\t\\t\\tfor (let i = 0, l = instances.length; i < l; i++) {\\n\\t\\t\\t\\tinstances[i].visible = false;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tshow() {\\n\\t\\tif (this._model) {\\n\\t\\t\\tconst instances = this._model.meshInstances;\\n\\t\\t\\tfor (let i = 0, l = instances.length; i < l; i++) {\\n\\t\\t\\t\\tinstances[i].visible = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_bindMaterialAsset(asset) {\\n\\t\\tasset.on(\\\"load\\\", this._onMaterialAssetLoad, this);\\n\\t\\tasset.on(\\\"unload\\\", this._onMaterialAssetUnload, this);\\n\\t\\tasset.on(\\\"remove\\\", this._onMaterialAssetRemove, this);\\n\\t\\tasset.on(\\\"change\\\", this._onMaterialAssetChange, this);\\n\\t\\tif (asset.resource) {\\n\\t\\t\\tthis._onMaterialAssetLoad(asset);\\n\\t\\t} else {\\n\\t\\t\\tif (!this.enabled || !this.entity.enabled) return;\\n\\t\\t\\tthis.system.app.assets.load(asset);\\n\\t\\t}\\n\\t}\\n\\t_unbindMaterialAsset(asset) {\\n\\t\\tasset.off(\\\"load\\\", this._onMaterialAssetLoad, this);\\n\\t\\tasset.off(\\\"unload\\\", this._onMaterialAssetUnload, this);\\n\\t\\tasset.off(\\\"remove\\\", this._onMaterialAssetRemove, this);\\n\\t\\tasset.off(\\\"change\\\", this._onMaterialAssetChange, this);\\n\\t}\\n\\t_onMaterialAssetAdd(asset) {\\n\\t\\tthis.system.app.assets.off(`add:${asset.id}`, this._onMaterialAssetAdd, this);\\n\\t\\tif (this._materialAsset === asset.id) {\\n\\t\\t\\tthis._bindMaterialAsset(asset);\\n\\t\\t}\\n\\t}\\n\\t_onMaterialAssetLoad(asset) {\\n\\t\\tthis._setMaterial(asset.resource);\\n\\t}\\n\\t_onMaterialAssetUnload(asset) {\\n\\t\\tthis._setMaterial(this.system.defaultMaterial);\\n\\t}\\n\\t_onMaterialAssetRemove(asset) {\\n\\t\\tthis._onMaterialAssetUnload(asset);\\n\\t}\\n\\t_onMaterialAssetChange(asset) {\\n\\t}\\n\\t_bindModelAsset(asset) {\\n\\t\\tthis._unbindModelAsset(asset);\\n\\t\\tasset.on(\\\"load\\\", this._onModelAssetLoad, this);\\n\\t\\tasset.on(\\\"unload\\\", this._onModelAssetUnload, this);\\n\\t\\tasset.on(\\\"change\\\", this._onModelAssetChange, this);\\n\\t\\tasset.on(\\\"remove\\\", this._onModelAssetRemove, this);\\n\\t\\tif (asset.resource) {\\n\\t\\t\\tthis._onModelAssetLoad(asset);\\n\\t\\t} else {\\n\\t\\t\\tif (!this.enabled || !this.entity.enabled) return;\\n\\t\\t\\tthis.system.app.assets.load(asset);\\n\\t\\t}\\n\\t}\\n\\t_unbindModelAsset(asset) {\\n\\t\\tasset.off(\\\"load\\\", this._onModelAssetLoad, this);\\n\\t\\tasset.off(\\\"unload\\\", this._onModelAssetUnload, this);\\n\\t\\tasset.off(\\\"change\\\", this._onModelAssetChange, this);\\n\\t\\tasset.off(\\\"remove\\\", this._onModelAssetRemove, this);\\n\\t}\\n\\t_onModelAssetAdded(asset) {\\n\\t\\tthis.system.app.assets.off(`add:${asset.id}`, this._onModelAssetAdded, this);\\n\\t\\tif (asset.id === this._asset) {\\n\\t\\t\\tthis._bindModelAsset(asset);\\n\\t\\t}\\n\\t}\\n\\t_onModelAssetLoad(asset) {\\n\\t\\tthis.model = asset.resource.clone();\\n\\t\\tthis._clonedModel = true;\\n\\t}\\n\\t_onModelAssetUnload(asset) {\\n\\t\\tthis.model = null;\\n\\t}\\n\\t_onModelAssetChange(asset, attr, _new, _old) {\\n\\t\\tif (attr === \\\"data\\\") {\\n\\t\\t\\tthis.mapping = this._mapping;\\n\\t\\t}\\n\\t}\\n\\t_onModelAssetRemove(asset) {\\n\\t\\tthis.model = null;\\n\\t}\\n\\t_setMaterial(material) {\\n\\t\\tif (this._material === material) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._material = material;\\n\\t\\tconst model = this._model;\\n\\t\\tif (model && this._type !== \\\"asset\\\") {\\n\\t\\t\\tconst meshInstances = model.meshInstances;\\n\\t\\t\\tfor (let i = 0, len = meshInstances.length; i < len; i++) {\\n\\t\\t\\t\\tmeshInstances[i].material = material;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\n\\nclass SkinInstanceCachedObject extends RefCountedObject {\\n\\tconstructor(skin, skinInstance) {\\n\\t\\tsuper();\\n\\t\\tthis.skin = skin;\\n\\t\\tthis.skinInstance = skinInstance;\\n\\t}\\n}\\nclass SkinInstanceCache {\\n\\t// map of SkinInstances allowing those to be shared between\\n\\t// (specifically a single glb with multiple render components)\\n\\t// It maps a rootBone to an array of SkinInstanceCachedObject\\n\\t// this allows us to find if a skin instance already exists for a rootbone, and a specific skin\\n\\tstatic _skinInstanceCache = /* @__PURE__ */ new Map();\\n\\t// returns cached or creates a skin instance for the skin and a rootBone, to be used by render component\\n\\t// on the specified entity\\n\\tstatic createCachedSkinInstance(skin, rootBone, entity) {\\n\\t\\tlet skinInst = SkinInstanceCache.getCachedSkinInstance(skin, rootBone);\\n\\t\\tif (!skinInst) {\\n\\t\\t\\tskinInst = new SkinInstance(skin);\\n\\t\\t\\tskinInst.resolve(rootBone, entity);\\n\\t\\t\\tSkinInstanceCache.addCachedSkinInstance(skin, rootBone, skinInst);\\n\\t\\t}\\n\\t\\treturn skinInst;\\n\\t}\\n\\t// returns already created skin instance from skin, for use on the rootBone\\n\\t// ref count of existing skinInstance is increased\\n\\tstatic getCachedSkinInstance(skin, rootBone) {\\n\\t\\tlet skinInstance = null;\\n\\t\\tconst cachedObjArray = SkinInstanceCache._skinInstanceCache.get(rootBone);\\n\\t\\tif (cachedObjArray) {\\n\\t\\t\\tconst cachedObj = cachedObjArray.find((element) => element.skin === skin);\\n\\t\\t\\tif (cachedObj) {\\n\\t\\t\\t\\tcachedObj.incRefCount();\\n\\t\\t\\t\\tskinInstance = cachedObj.skinInstance;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn skinInstance;\\n\\t}\\n\\t// adds skin instance to the cache, and increases ref count on it\\n\\tstatic addCachedSkinInstance(skin, rootBone, skinInstance) {\\n\\t\\tlet cachedObjArray = SkinInstanceCache._skinInstanceCache.get(rootBone);\\n\\t\\tif (!cachedObjArray) {\\n\\t\\t\\tcachedObjArray = [];\\n\\t\\t\\tSkinInstanceCache._skinInstanceCache.set(rootBone, cachedObjArray);\\n\\t\\t}\\n\\t\\tlet cachedObj = cachedObjArray.find((element) => element.skin === skin);\\n\\t\\tif (!cachedObj) {\\n\\t\\t\\tcachedObj = new SkinInstanceCachedObject(skin, skinInstance);\\n\\t\\t\\tcachedObjArray.push(cachedObj);\\n\\t\\t}\\n\\t\\tcachedObj.incRefCount();\\n\\t}\\n\\t// removes skin instance from the cache. This decreases ref count, and when that reaches 0 it gets destroyed\\n\\tstatic removeCachedSkinInstance(skinInstance) {\\n\\t\\tif (skinInstance) {\\n\\t\\t\\tconst rootBone = skinInstance.rootBone;\\n\\t\\t\\tif (rootBone) {\\n\\t\\t\\t\\tconst cachedObjArray = SkinInstanceCache._skinInstanceCache.get(rootBone);\\n\\t\\t\\t\\tif (cachedObjArray) {\\n\\t\\t\\t\\t\\tconst cachedObjIndex = cachedObjArray.findIndex((element) => element.skinInstance === skinInstance);\\n\\t\\t\\t\\t\\tif (cachedObjIndex >= 0) {\\n\\t\\t\\t\\t\\t\\tconst cachedObj = cachedObjArray[cachedObjIndex];\\n\\t\\t\\t\\t\\t\\tcachedObj.decRefCount();\\n\\t\\t\\t\\t\\t\\tif (cachedObj.refCount === 0) {\\n\\t\\t\\t\\t\\t\\t\\tcachedObjArray.splice(cachedObjIndex, 1);\\n\\t\\t\\t\\t\\t\\t\\tif (!cachedObjArray.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\tSkinInstanceCache._skinInstanceCache.delete(rootBone);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\tif (skinInstance) {\\n\\t\\t\\t\\t\\t\\t\\t\\tskinInstance.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\tcachedObj.skinInstance = null;\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\n\\nclass AssetReference {\\n\\t_evtLoadById = null;\\n\\t_evtUnloadById = null;\\n\\t_evtAddById = null;\\n\\t_evtRemoveById = null;\\n\\t_evtLoadByUrl = null;\\n\\t_evtAddByUrl = null;\\n\\t_evtRemoveByUrl = null;\\n\\tconstructor(propertyName, parent, registry, callbacks, scope) {\\n\\t\\tthis.propertyName = propertyName;\\n\\t\\tthis.parent = parent;\\n\\t\\tthis._scope = scope;\\n\\t\\tthis._registry = registry;\\n\\t\\tthis.id = null;\\n\\t\\tthis.url = null;\\n\\t\\tthis.asset = null;\\n\\t\\tthis._onAssetLoad = callbacks.load;\\n\\t\\tthis._onAssetAdd = callbacks.add;\\n\\t\\tthis._onAssetRemove = callbacks.remove;\\n\\t\\tthis._onAssetUnload = callbacks.unload;\\n\\t}\\n\\tset id(value) {\\n\\t\\tif (this.url) throw Error(\\\"Can't set id and url\\\");\\n\\t\\tthis._unbind();\\n\\t\\tthis._id = value;\\n\\t\\tthis.asset = this._registry.get(this._id);\\n\\t\\tthis._bind();\\n\\t}\\n\\tget id() {\\n\\t\\treturn this._id;\\n\\t}\\n\\tset url(value) {\\n\\t\\tif (this.id) throw Error(\\\"Can't set id and url\\\");\\n\\t\\tthis._unbind();\\n\\t\\tthis._url = value;\\n\\t\\tthis.asset = this._registry.getByUrl(this._url);\\n\\t\\tthis._bind();\\n\\t}\\n\\tget url() {\\n\\t\\treturn this._url;\\n\\t}\\n\\t_bind() {\\n\\t\\tif (this.id) {\\n\\t\\t\\tif (this._onAssetLoad) this._evtLoadById = this._registry.on(`load:${this.id}`, this._onLoad, this);\\n\\t\\t\\tif (this._onAssetAdd) this._evtAddById = this._registry.once(`add:${this.id}`, this._onAdd, this);\\n\\t\\t\\tif (this._onAssetRemove) this._evtRemoveById = this._registry.on(`remove:${this.id}`, this._onRemove, this);\\n\\t\\t\\tif (this._onAssetUnload) this._evtUnloadById = this._registry.on(`unload:${this.id}`, this._onUnload, this);\\n\\t\\t}\\n\\t\\tif (this.url) {\\n\\t\\t\\tif (this._onAssetLoad) this._evtLoadByUrl = this._registry.on(`load:url:${this.url}`, this._onLoad, this);\\n\\t\\t\\tif (this._onAssetAdd) this._evtAddByUrl = this._registry.once(`add:url:${this.url}`, this._onAdd, this);\\n\\t\\t\\tif (this._onAssetRemove) this._evtRemoveByUrl = this._registry.on(`remove:url:${this.url}`, this._onRemove, this);\\n\\t\\t}\\n\\t}\\n\\t_unbind() {\\n\\t\\tif (this.id) {\\n\\t\\t\\tthis._evtLoadById?.off();\\n\\t\\t\\tthis._evtLoadById = null;\\n\\t\\t\\tthis._evtAddById?.off();\\n\\t\\t\\tthis._evtAddById = null;\\n\\t\\t\\tthis._evtRemoveById?.off();\\n\\t\\t\\tthis._evtRemoveById = null;\\n\\t\\t\\tthis._evtUnloadById?.off();\\n\\t\\t\\tthis._evtUnloadById = null;\\n\\t\\t}\\n\\t\\tif (this.url) {\\n\\t\\t\\tthis._evtLoadByUrl?.off();\\n\\t\\t\\tthis._evtLoadByUrl = null;\\n\\t\\t\\tthis._evtAddByUrl?.off();\\n\\t\\t\\tthis._evtAddByUrl = null;\\n\\t\\t\\tthis._evtRemoveByUrl?.off();\\n\\t\\t\\tthis._evtRemoveByUrl = null;\\n\\t\\t}\\n\\t}\\n\\t_onLoad(asset) {\\n\\t\\tthis._onAssetLoad.call(this._scope, this.propertyName, this.parent, asset);\\n\\t}\\n\\t_onAdd(asset) {\\n\\t\\tthis.asset = asset;\\n\\t\\tthis._onAssetAdd.call(this._scope, this.propertyName, this.parent, asset);\\n\\t}\\n\\t_onRemove(asset) {\\n\\t\\tthis._onAssetRemove.call(this._scope, this.propertyName, this.parent, asset);\\n\\t\\tthis.asset = null;\\n\\t}\\n\\t_onUnload(asset) {\\n\\t\\tthis._onAssetUnload.call(this._scope, this.propertyName, this.parent, asset);\\n\\t}\\n}\\n\\nclass RenderComponent extends Component {\\n\\t_type = \\\"asset\\\";\\n\\t_castShadows = true;\\n\\t_receiveShadows = true;\\n\\t_castShadowsLightmap = true;\\n\\t_lightmapped = false;\\n\\t_lightmapSizeMultiplier = 1;\\n\\tisStatic = false;\\n\\t_batchGroupId = -1;\\n\\t_layers = [LAYERID_WORLD];\\n\\t// assign to the default world layer\\n\\t_renderStyle = RENDERSTYLE_SOLID;\\n\\t_meshInstances = [];\\n\\t_customAabb = null;\\n\\t_area = null;\\n\\t_assetReference;\\n\\t_materialReferences = [];\\n\\t_material;\\n\\t_rootBone = null;\\n\\t_evtLayersChanged = null;\\n\\t_evtLayerAdded = null;\\n\\t_evtLayerRemoved = null;\\n\\t_evtSetMeshes = null;\\n\\tconstructor(system, entity) {\\n\\t\\tsuper(system, entity);\\n\\t\\tthis._assetReference = new AssetReference(\\n\\t\\t\\t\\\"asset\\\",\\n\\t\\t\\tthis,\\n\\t\\t\\tsystem.app.assets,\\n\\t\\t\\t{\\n\\t\\t\\t\\tadd: this._onRenderAssetAdded,\\n\\t\\t\\t\\tload: this._onRenderAssetLoad,\\n\\t\\t\\t\\tremove: this._onRenderAssetRemove,\\n\\t\\t\\t\\tunload: this._onRenderAssetUnload\\n\\t\\t\\t},\\n\\t\\t\\tthis\\n\\t\\t);\\n\\t\\tthis._material = system.defaultMaterial;\\n\\t\\tentity.on(\\\"remove\\\", this.onRemoveChild, this);\\n\\t\\tentity.on(\\\"removehierarchy\\\", this.onRemoveChild, this);\\n\\t\\tentity.on(\\\"insert\\\", this.onInsertChild, this);\\n\\t\\tentity.on(\\\"inserthierarchy\\\", this.onInsertChild, this);\\n\\t}\\n\\tset renderStyle(renderStyle) {\\n\\t\\tif (this._renderStyle !== renderStyle) {\\n\\t\\t\\tthis._renderStyle = renderStyle;\\n\\t\\t\\tMeshInstance._prepareRenderStyleForArray(this._meshInstances, renderStyle);\\n\\t\\t}\\n\\t}\\n\\tget renderStyle() {\\n\\t\\treturn this._renderStyle;\\n\\t}\\n\\tset customAabb(value) {\\n\\t\\tthis._customAabb = value;\\n\\t\\tconst mi = this._meshInstances;\\n\\t\\tif (mi) {\\n\\t\\t\\tfor (let i = 0; i < mi.length; i++) {\\n\\t\\t\\t\\tmi[i].setCustomAabb(this._customAabb);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget customAabb() {\\n\\t\\treturn this._customAabb;\\n\\t}\\n\\tset type(value) {\\n\\t\\tif (this._type !== value) {\\n\\t\\t\\tthis._area = null;\\n\\t\\t\\tthis._type = value;\\n\\t\\t\\tthis.destroyMeshInstances();\\n\\t\\t\\tif (value !== \\\"asset\\\") {\\n\\t\\t\\t\\tlet material = this._material;\\n\\t\\t\\t\\tif (!material || material === this.system.defaultMaterial) {\\n\\t\\t\\t\\t\\tmaterial = this._materialReferences[0] && this._materialReferences[0].asset && this._materialReferences[0].asset.resource;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst primData = getShapePrimitive(this.system.app.graphicsDevice, value);\\n\\t\\t\\t\\tthis._area = primData.area;\\n\\t\\t\\t\\tthis.meshInstances = [new MeshInstance(primData.mesh, material || this.system.defaultMaterial, this.entity)];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget type() {\\n\\t\\treturn this._type;\\n\\t}\\n\\tset meshInstances(value) {\\n\\t\\tthis.destroyMeshInstances();\\n\\t\\tthis._meshInstances = value;\\n\\t\\tif (this._meshInstances) {\\n\\t\\t\\tconst mi = this._meshInstances;\\n\\t\\t\\tfor (let i = 0; i < mi.length; i++) {\\n\\t\\t\\t\\tif (!mi[i].node) {\\n\\t\\t\\t\\t\\tmi[i].node = this.entity;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tmi[i].castShadow = this._castShadows;\\n\\t\\t\\t\\tmi[i].receiveShadow = this._receiveShadows;\\n\\t\\t\\t\\tmi[i].renderStyle = this._renderStyle;\\n\\t\\t\\t\\tmi[i].setLightmapped(this._lightmapped);\\n\\t\\t\\t\\tmi[i].setCustomAabb(this._customAabb);\\n\\t\\t\\t}\\n\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\tthis.addToLayers();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget meshInstances() {\\n\\t\\treturn this._meshInstances;\\n\\t}\\n\\tset lightmapped(value) {\\n\\t\\tif (value !== this._lightmapped) {\\n\\t\\t\\tthis._lightmapped = value;\\n\\t\\t\\tconst mi = this._meshInstances;\\n\\t\\t\\tif (mi) {\\n\\t\\t\\t\\tfor (let i = 0; i < mi.length; i++) {\\n\\t\\t\\t\\t\\tmi[i].setLightmapped(value);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget lightmapped() {\\n\\t\\treturn this._lightmapped;\\n\\t}\\n\\tset castShadows(value) {\\n\\t\\tif (this._castShadows !== value) {\\n\\t\\t\\tconst mi = this._meshInstances;\\n\\t\\t\\tif (mi) {\\n\\t\\t\\t\\tconst layers = this.layers;\\n\\t\\t\\t\\tconst scene = this.system.app.scene;\\n\\t\\t\\t\\tif (this._castShadows && !value) {\\n\\t\\t\\t\\t\\tfor (let i = 0; i < layers.length; i++) {\\n\\t\\t\\t\\t\\t\\tconst layer = scene.layers.getLayerById(this.layers[i]);\\n\\t\\t\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\t\\tlayer.removeShadowCasters(mi);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (let i = 0; i < mi.length; i++) {\\n\\t\\t\\t\\t\\tmi[i].castShadow = value;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._castShadows && value) {\\n\\t\\t\\t\\t\\tfor (let i = 0; i < layers.length; i++) {\\n\\t\\t\\t\\t\\t\\tconst layer = scene.layers.getLayerById(layers[i]);\\n\\t\\t\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\t\\tlayer.addShadowCasters(mi);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis._castShadows = value;\\n\\t\\t}\\n\\t}\\n\\tget castShadows() {\\n\\t\\treturn this._castShadows;\\n\\t}\\n\\tset receiveShadows(value) {\\n\\t\\tif (this._receiveShadows !== value) {\\n\\t\\t\\tthis._receiveShadows = value;\\n\\t\\t\\tconst mi = this._meshInstances;\\n\\t\\t\\tif (mi) {\\n\\t\\t\\t\\tfor (let i = 0; i < mi.length; i++) {\\n\\t\\t\\t\\t\\tmi[i].receiveShadow = value;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget receiveShadows() {\\n\\t\\treturn this._receiveShadows;\\n\\t}\\n\\tset castShadowsLightmap(value) {\\n\\t\\tthis._castShadowsLightmap = value;\\n\\t}\\n\\tget castShadowsLightmap() {\\n\\t\\treturn this._castShadowsLightmap;\\n\\t}\\n\\tset lightmapSizeMultiplier(value) {\\n\\t\\tthis._lightmapSizeMultiplier = value;\\n\\t}\\n\\tget lightmapSizeMultiplier() {\\n\\t\\treturn this._lightmapSizeMultiplier;\\n\\t}\\n\\tset layers(value) {\\n\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\tlet layer;\\n\\t\\tif (this._meshInstances) {\\n\\t\\t\\tfor (let i = 0; i < this._layers.length; i++) {\\n\\t\\t\\t\\tlayer = layers.getLayerById(this._layers[i]);\\n\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\tlayer.removeMeshInstances(this._meshInstances);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._layers.length = 0;\\n\\t\\tfor (let i = 0; i < value.length; i++) {\\n\\t\\t\\tthis._layers[i] = value[i];\\n\\t\\t}\\n\\t\\tif (!this.enabled || !this.entity.enabled || !this._meshInstances) return;\\n\\t\\tfor (let i = 0; i < this._layers.length; i++) {\\n\\t\\t\\tlayer = layers.getLayerById(this._layers[i]);\\n\\t\\t\\tif (layer) {\\n\\t\\t\\t\\tlayer.addMeshInstances(this._meshInstances);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget layers() {\\n\\t\\treturn this._layers;\\n\\t}\\n\\tset batchGroupId(value) {\\n\\t\\tif (this._batchGroupId !== value) {\\n\\t\\t\\tif (this.entity.enabled && this._batchGroupId >= 0) {\\n\\t\\t\\t\\tthis.system.app.batcher?.remove(BatchGroup.RENDER, this.batchGroupId, this.entity);\\n\\t\\t\\t}\\n\\t\\t\\tif (this.entity.enabled && value >= 0) {\\n\\t\\t\\t\\tthis.system.app.batcher?.insert(BatchGroup.RENDER, value, this.entity);\\n\\t\\t\\t}\\n\\t\\t\\tif (value < 0 && this._batchGroupId >= 0 && this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\tthis.addToLayers();\\n\\t\\t\\t}\\n\\t\\t\\tthis._batchGroupId = value;\\n\\t\\t}\\n\\t}\\n\\tget batchGroupId() {\\n\\t\\treturn this._batchGroupId;\\n\\t}\\n\\tset material(value) {\\n\\t\\tif (this._material !== value) {\\n\\t\\t\\tthis._material = value;\\n\\t\\t\\tif (this._meshInstances && this._type !== \\\"asset\\\") {\\n\\t\\t\\t\\tfor (let i = 0; i < this._meshInstances.length; i++) {\\n\\t\\t\\t\\t\\tthis._meshInstances[i].material = value;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget material() {\\n\\t\\treturn this._material;\\n\\t}\\n\\tset materialAssets(value = []) {\\n\\t\\tif (this._materialReferences.length > value.length) {\\n\\t\\t\\tfor (let i = value.length; i < this._materialReferences.length; i++) {\\n\\t\\t\\t\\tthis._materialReferences[i].id = null;\\n\\t\\t\\t}\\n\\t\\t\\tthis._materialReferences.length = value.length;\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < value.length; i++) {\\n\\t\\t\\tif (!this._materialReferences[i]) {\\n\\t\\t\\t\\tthis._materialReferences.push(\\n\\t\\t\\t\\t\\tnew AssetReference(\\n\\t\\t\\t\\t\\t\\ti,\\n\\t\\t\\t\\t\\t\\tthis,\\n\\t\\t\\t\\t\\t\\tthis.system.app.assets,\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\tadd: this._onMaterialAdded,\\n\\t\\t\\t\\t\\t\\t\\tload: this._onMaterialLoad,\\n\\t\\t\\t\\t\\t\\t\\tremove: this._onMaterialRemove,\\n\\t\\t\\t\\t\\t\\t\\tunload: this._onMaterialUnload\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tthis\\n\\t\\t\\t\\t\\t)\\n\\t\\t\\t\\t);\\n\\t\\t\\t}\\n\\t\\t\\tif (value[i]) {\\n\\t\\t\\t\\tconst id = value[i] instanceof Asset ? value[i].id : value[i];\\n\\t\\t\\t\\tif (this._materialReferences[i].id !== id) {\\n\\t\\t\\t\\t\\tthis._materialReferences[i].id = id;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._materialReferences[i].asset) {\\n\\t\\t\\t\\t\\tthis._onMaterialAdded(i, this, this._materialReferences[i].asset);\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._materialReferences[i].id = null;\\n\\t\\t\\t\\tif (this._meshInstances[i]) {\\n\\t\\t\\t\\t\\tthis._meshInstances[i].material = this.system.defaultMaterial;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget materialAssets() {\\n\\t\\treturn this._materialReferences.map((ref) => {\\n\\t\\t\\treturn ref.id;\\n\\t\\t});\\n\\t}\\n\\tset asset(value) {\\n\\t\\tconst id = value instanceof Asset ? value.id : value;\\n\\t\\tif (this._assetReference.id === id) return;\\n\\t\\tif (this._assetReference.asset && this._assetReference.asset.resource) {\\n\\t\\t\\tthis._onRenderAssetRemove();\\n\\t\\t}\\n\\t\\tthis._assetReference.id = id;\\n\\t\\tif (this._assetReference.asset) {\\n\\t\\t\\tthis._onRenderAssetAdded();\\n\\t\\t}\\n\\t}\\n\\tget asset() {\\n\\t\\treturn this._assetReference.id;\\n\\t}\\n\\tassignAsset(asset) {\\n\\t\\tconst id = asset instanceof Asset ? asset.id : asset;\\n\\t\\tthis._assetReference.id = id;\\n\\t}\\n\\tset rootBone(value) {\\n\\t\\tif (this._rootBone !== value) {\\n\\t\\t\\tconst isString = typeof value === \\\"string\\\";\\n\\t\\t\\tif (this._rootBone && isString && this._rootBone.guid === value) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tif (this._rootBone) {\\n\\t\\t\\t\\tthis._clearSkinInstances();\\n\\t\\t\\t}\\n\\t\\t\\tif (value instanceof GraphNode) {\\n\\t\\t\\t\\tthis._rootBone = value;\\n\\t\\t\\t} else if (isString) {\\n\\t\\t\\t\\tthis._rootBone = this.system.app.getEntityFromIndex(value) || null;\\n\\t\\t\\t\\tif (!this._rootBone) ;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._rootBone = null;\\n\\t\\t\\t}\\n\\t\\t\\tif (this._rootBone) {\\n\\t\\t\\t\\tthis._cloneSkinInstances();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget rootBone() {\\n\\t\\treturn this._rootBone;\\n\\t}\\n\\tdestroyMeshInstances() {\\n\\t\\tconst meshInstances = this._meshInstances;\\n\\t\\tif (meshInstances) {\\n\\t\\t\\tthis.removeFromLayers();\\n\\t\\t\\tthis._clearSkinInstances();\\n\\t\\t\\tfor (let i = 0; i < meshInstances.length; i++) {\\n\\t\\t\\t\\tmeshInstances[i].destroy();\\n\\t\\t\\t}\\n\\t\\t\\tthis._meshInstances.length = 0;\\n\\t\\t}\\n\\t}\\n\\taddToLayers() {\\n\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\tfor (let i = 0; i < this._layers.length; i++) {\\n\\t\\t\\tconst layer = layers.getLayerById(this._layers[i]);\\n\\t\\t\\tif (layer) {\\n\\t\\t\\t\\tlayer.addMeshInstances(this._meshInstances);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tremoveFromLayers() {\\n\\t\\tif (this._meshInstances && this._meshInstances.length) {\\n\\t\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\t\\tfor (let i = 0; i < this._layers.length; i++) {\\n\\t\\t\\t\\tconst layer = layers.getLayerById(this._layers[i]);\\n\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\tlayer.removeMeshInstances(this._meshInstances);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tonRemoveChild() {\\n\\t\\tthis.removeFromLayers();\\n\\t}\\n\\tonInsertChild() {\\n\\t\\tif (this._meshInstances && this.enabled && this.entity.enabled) {\\n\\t\\t\\tthis.addToLayers();\\n\\t\\t}\\n\\t}\\n\\tonRemove() {\\n\\t\\tthis.destroyMeshInstances();\\n\\t\\tthis.asset = null;\\n\\t\\tthis.materialAsset = null;\\n\\t\\tthis._assetReference.id = null;\\n\\t\\tfor (let i = 0; i < this._materialReferences.length; i++) {\\n\\t\\t\\tthis._materialReferences[i].id = null;\\n\\t\\t}\\n\\t\\tthis.entity.off(\\\"remove\\\", this.onRemoveChild, this);\\n\\t\\tthis.entity.off(\\\"insert\\\", this.onInsertChild, this);\\n\\t}\\n\\tonLayersChanged(oldComp, newComp) {\\n\\t\\tthis.addToLayers();\\n\\t\\toldComp.off(\\\"add\\\", this.onLayerAdded, this);\\n\\t\\toldComp.off(\\\"remove\\\", this.onLayerRemoved, this);\\n\\t\\tnewComp.on(\\\"add\\\", this.onLayerAdded, this);\\n\\t\\tnewComp.on(\\\"remove\\\", this.onLayerRemoved, this);\\n\\t}\\n\\tonLayerAdded(layer) {\\n\\t\\tconst index = this.layers.indexOf(layer.id);\\n\\t\\tif (index < 0) return;\\n\\t\\tlayer.addMeshInstances(this._meshInstances);\\n\\t}\\n\\tonLayerRemoved(layer) {\\n\\t\\tconst index = this.layers.indexOf(layer.id);\\n\\t\\tif (index < 0) return;\\n\\t\\tlayer.removeMeshInstances(this._meshInstances);\\n\\t}\\n\\tonEnable() {\\n\\t\\tconst app = this.system.app;\\n\\t\\tconst scene = app.scene;\\n\\t\\tconst layers = scene.layers;\\n\\t\\tif (this._rootBone) {\\n\\t\\t\\tthis._cloneSkinInstances();\\n\\t\\t}\\n\\t\\tthis._evtLayersChanged = scene.on(\\\"set:layers\\\", this.onLayersChanged, this);\\n\\t\\tif (layers) {\\n\\t\\t\\tthis._evtLayerAdded = layers.on(\\\"add\\\", this.onLayerAdded, this);\\n\\t\\t\\tthis._evtLayerRemoved = layers.on(\\\"remove\\\", this.onLayerRemoved, this);\\n\\t\\t}\\n\\t\\tconst isAsset = this._type === \\\"asset\\\";\\n\\t\\tif (this._meshInstances && this._meshInstances.length) {\\n\\t\\t\\tthis.addToLayers();\\n\\t\\t} else if (isAsset && this.asset) {\\n\\t\\t\\tthis._onRenderAssetAdded();\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < this._materialReferences.length; i++) {\\n\\t\\t\\tif (this._materialReferences[i].asset) {\\n\\t\\t\\t\\tthis.system.app.assets.load(this._materialReferences[i].asset);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this._batchGroupId >= 0) {\\n\\t\\t\\tapp.batcher?.insert(BatchGroup.RENDER, this.batchGroupId, this.entity);\\n\\t\\t}\\n\\t}\\n\\tonDisable() {\\n\\t\\tconst app = this.system.app;\\n\\t\\tconst scene = app.scene;\\n\\t\\tconst layers = scene.layers;\\n\\t\\tthis._evtLayersChanged?.off();\\n\\t\\tthis._evtLayersChanged = null;\\n\\t\\tif (this._rootBone) {\\n\\t\\t\\tthis._clearSkinInstances();\\n\\t\\t}\\n\\t\\tif (layers) {\\n\\t\\t\\tthis._evtLayerAdded?.off();\\n\\t\\t\\tthis._evtLayerAdded = null;\\n\\t\\t\\tthis._evtLayerRemoved?.off();\\n\\t\\t\\tthis._evtLayerRemoved = null;\\n\\t\\t}\\n\\t\\tif (this._batchGroupId >= 0) {\\n\\t\\t\\tapp.batcher?.remove(BatchGroup.RENDER, this.batchGroupId, this.entity);\\n\\t\\t}\\n\\t\\tthis.removeFromLayers();\\n\\t}\\n\\thide() {\\n\\t\\tif (this._meshInstances) {\\n\\t\\t\\tfor (let i = 0; i < this._meshInstances.length; i++) {\\n\\t\\t\\t\\tthis._meshInstances[i].visible = false;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tshow() {\\n\\t\\tif (this._meshInstances) {\\n\\t\\t\\tfor (let i = 0; i < this._meshInstances.length; i++) {\\n\\t\\t\\t\\tthis._meshInstances[i].visible = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_onRenderAssetAdded() {\\n\\t\\tif (!this._assetReference.asset) return;\\n\\t\\tif (this._assetReference.asset.resource) {\\n\\t\\t\\tthis._onRenderAssetLoad();\\n\\t\\t} else if (this.enabled && this.entity.enabled) {\\n\\t\\t\\tthis.system.app.assets.load(this._assetReference.asset);\\n\\t\\t}\\n\\t}\\n\\t_onRenderAssetLoad() {\\n\\t\\tthis.destroyMeshInstances();\\n\\t\\tif (this._assetReference.asset) {\\n\\t\\t\\tconst render = this._assetReference.asset.resource;\\n\\t\\t\\tthis._evtSetMeshes?.off();\\n\\t\\t\\tthis._evtSetMeshes = render.on(\\\"set:meshes\\\", this._onSetMeshes, this);\\n\\t\\t\\tif (render.meshes) {\\n\\t\\t\\t\\tthis._onSetMeshes(render.meshes);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_onSetMeshes(meshes) {\\n\\t\\tthis._cloneMeshes(meshes);\\n\\t}\\n\\t_clearSkinInstances() {\\n\\t\\tfor (let i = 0; i < this._meshInstances.length; i++) {\\n\\t\\t\\tconst meshInstance = this._meshInstances[i];\\n\\t\\t\\tSkinInstanceCache.removeCachedSkinInstance(meshInstance.skinInstance);\\n\\t\\t\\tmeshInstance.skinInstance = null;\\n\\t\\t}\\n\\t}\\n\\t_cloneSkinInstances() {\\n\\t\\tif (this._meshInstances.length && this._rootBone instanceof GraphNode) {\\n\\t\\t\\tfor (let i = 0; i < this._meshInstances.length; i++) {\\n\\t\\t\\t\\tconst meshInstance = this._meshInstances[i];\\n\\t\\t\\t\\tconst mesh = meshInstance.mesh;\\n\\t\\t\\t\\tif (mesh.skin && !meshInstance.skinInstance) {\\n\\t\\t\\t\\t\\tmeshInstance.skinInstance = SkinInstanceCache.createCachedSkinInstance(mesh.skin, this._rootBone, this.entity);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_cloneMeshes(meshes) {\\n\\t\\tif (meshes && meshes.length) {\\n\\t\\t\\tconst meshInstances = [];\\n\\t\\t\\tfor (let i = 0; i < meshes.length; i++) {\\n\\t\\t\\t\\tconst mesh = meshes[i];\\n\\t\\t\\t\\tconst material = this._materialReferences[i] && this._materialReferences[i].asset && this._materialReferences[i].asset.resource;\\n\\t\\t\\t\\tconst meshInst = new MeshInstance(mesh, material || this.system.defaultMaterial, this.entity);\\n\\t\\t\\t\\tmeshInstances.push(meshInst);\\n\\t\\t\\t\\tif (mesh.morph) {\\n\\t\\t\\t\\t\\tmeshInst.morphInstance = new MorphInstance(mesh.morph);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis.meshInstances = meshInstances;\\n\\t\\t\\tthis._cloneSkinInstances();\\n\\t\\t}\\n\\t}\\n\\t_onRenderAssetUnload() {\\n\\t\\tif (this._type === \\\"asset\\\") {\\n\\t\\t\\tthis.destroyMeshInstances();\\n\\t\\t}\\n\\t}\\n\\t_onRenderAssetRemove() {\\n\\t\\tthis._evtSetMeshes?.off();\\n\\t\\tthis._evtSetMeshes = null;\\n\\t\\tthis._onRenderAssetUnload();\\n\\t}\\n\\t_onMaterialAdded(index, component, asset) {\\n\\t\\tif (asset.resource) {\\n\\t\\t\\tthis._onMaterialLoad(index, component, asset);\\n\\t\\t} else {\\n\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\tthis.system.app.assets.load(asset);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_updateMainMaterial(index, material) {\\n\\t\\tif (index === 0) {\\n\\t\\t\\tthis.material = material;\\n\\t\\t}\\n\\t}\\n\\t_onMaterialLoad(index, component, asset) {\\n\\t\\tif (this._meshInstances[index]) {\\n\\t\\t\\tthis._meshInstances[index].material = asset.resource;\\n\\t\\t}\\n\\t\\tthis._updateMainMaterial(index, asset.resource);\\n\\t}\\n\\t_onMaterialRemove(index, component, asset) {\\n\\t\\tif (this._meshInstances[index]) {\\n\\t\\t\\tthis._meshInstances[index].material = this.system.defaultMaterial;\\n\\t\\t}\\n\\t\\tthis._updateMainMaterial(index, this.system.defaultMaterial);\\n\\t}\\n\\t_onMaterialUnload(index, component, asset) {\\n\\t\\tif (this._meshInstances[index]) {\\n\\t\\t\\tthis._meshInstances[index].material = this.system.defaultMaterial;\\n\\t\\t}\\n\\t\\tthis._updateMainMaterial(index, this.system.defaultMaterial);\\n\\t}\\n\\tresolveDuplicatedEntityReferenceProperties(oldRender, duplicatedIdsMap) {\\n\\t\\tif (oldRender.rootBone) {\\n\\t\\t\\tthis.rootBone = duplicatedIdsMap[oldRender.rootBone.guid];\\n\\t\\t}\\n\\t}\\n}\\n\\nclass RenderComponentData {\\n\\tenabled = true;\\n}\\n\\nconst _schema$4 = [\\n\\t\\\"enabled\\\"\\n];\\nconst _properties$2 = [\\n\\t\\\"material\\\",\\n\\t\\\"meshInstances\\\",\\n\\t\\\"asset\\\",\\n\\t\\\"materialAssets\\\",\\n\\t\\\"castShadows\\\",\\n\\t\\\"receiveShadows\\\",\\n\\t\\\"castShadowsLightmap\\\",\\n\\t\\\"lightmapped\\\",\\n\\t\\\"lightmapSizeMultiplier\\\",\\n\\t\\\"renderStyle\\\",\\n\\t\\\"type\\\",\\n\\t\\\"layers\\\",\\n\\t\\\"isStatic\\\",\\n\\t\\\"batchGroupId\\\",\\n\\t\\\"rootBone\\\"\\n];\\nclass RenderComponentSystem extends ComponentSystem {\\n\\tconstructor(app) {\\n\\t\\tsuper(app);\\n\\t\\tthis.id = \\\"render\\\";\\n\\t\\tthis.ComponentType = RenderComponent;\\n\\t\\tthis.DataType = RenderComponentData;\\n\\t\\tthis.schema = _schema$4;\\n\\t\\tthis.defaultMaterial = getDefaultMaterial(app.graphicsDevice);\\n\\t\\tthis.on(\\\"beforeremove\\\", this.onRemove, this);\\n\\t}\\n\\tinitializeComponentData(component, _data, properties) {\\n\\t\\tif (_data.batchGroupId === null || _data.batchGroupId === void 0) {\\n\\t\\t\\t_data.batchGroupId = -1;\\n\\t\\t}\\n\\t\\tif (_data.layers && _data.layers.length) {\\n\\t\\t\\t_data.layers = _data.layers.slice(0);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < _properties$2.length; i++) {\\n\\t\\t\\tif (_data.hasOwnProperty(_properties$2[i])) {\\n\\t\\t\\t\\tcomponent[_properties$2[i]] = _data[_properties$2[i]];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (_data.aabbCenter && _data.aabbHalfExtents) {\\n\\t\\t\\tcomponent.customAabb = new BoundingBox(new Vec3(_data.aabbCenter), new Vec3(_data.aabbHalfExtents));\\n\\t\\t}\\n\\t\\tsuper.initializeComponentData(component, _data, _schema$4);\\n\\t}\\n\\tcloneComponent(entity, clone) {\\n\\t\\tconst data = {};\\n\\t\\tfor (let i = 0; i < _properties$2.length; i++) {\\n\\t\\t\\tdata[_properties$2[i]] = entity.render[_properties$2[i]];\\n\\t\\t}\\n\\t\\tdata.enabled = entity.render.enabled;\\n\\t\\tdelete data.meshInstances;\\n\\t\\tconst component = this.addComponent(clone, data);\\n\\t\\tconst srcMeshInstances = entity.render.meshInstances;\\n\\t\\tconst meshes = srcMeshInstances.map((mi) => mi.mesh);\\n\\t\\tcomponent._onSetMeshes(meshes);\\n\\t\\tfor (let m = 0; m < srcMeshInstances.length; m++) {\\n\\t\\t\\tcomponent.meshInstances[m].material = srcMeshInstances[m].material;\\n\\t\\t}\\n\\t\\tif (entity.render.customAabb) {\\n\\t\\t\\tcomponent.customAabb = entity.render.customAabb.clone();\\n\\t\\t}\\n\\t\\treturn component;\\n\\t}\\n\\tonRemove(entity, component) {\\n\\t\\tcomponent.onRemove();\\n\\t}\\n}\\nComponent._buildAccessors(RenderComponent.prototype, _schema$4);\\n\\nclass ObjectPool {\\n\\t_constructor;\\n\\t_pool = [];\\n\\t_count = 0;\\n\\tconstructor(constructorFunc, size) {\\n\\t\\tthis._constructor = constructorFunc;\\n\\t\\tthis._resize(size);\\n\\t}\\n\\t_resize(size) {\\n\\t\\tif (size > this._pool.length) {\\n\\t\\t\\tfor (let i = this._pool.length; i < size; i++) {\\n\\t\\t\\t\\tthis._pool[i] = new this._constructor();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tallocate() {\\n\\t\\tif (this._count >= this._pool.length) {\\n\\t\\t\\tthis._resize(this._pool.length * 2);\\n\\t\\t}\\n\\t\\treturn this._pool[this._count++];\\n\\t}\\n\\tfreeAll() {\\n\\t\\tthis._count = 0;\\n\\t}\\n}\\n\\nlet _ammoTransform;\\nlet _ammoVec1, _ammoVec2, _ammoQuat;\\nconst _quat1 = new Quat();\\nconst _quat2 = new Quat();\\nconst _vec3 = new Vec3();\\nclass RigidBodyComponent extends Component {\\n\\tstatic EVENT_CONTACT = \\\"contact\\\";\\n\\tstatic EVENT_COLLISIONSTART = \\\"collisionstart\\\";\\n\\tstatic EVENT_COLLISIONEND = \\\"collisionend\\\";\\n\\tstatic EVENT_TRIGGERENTER = \\\"triggerenter\\\";\\n\\tstatic EVENT_TRIGGERLEAVE = \\\"triggerleave\\\";\\n\\tstatic order = -1;\\n\\t_angularDamping = 0;\\n\\t_angularFactor = new Vec3(1, 1, 1);\\n\\t_angularVelocity = new Vec3();\\n\\t_body = null;\\n\\t_friction = 0.5;\\n\\t_group = BODYGROUP_STATIC;\\n\\t_linearDamping = 0;\\n\\t_linearFactor = new Vec3(1, 1, 1);\\n\\t_linearVelocity = new Vec3();\\n\\t_mask = BODYMASK_NOT_STATIC;\\n\\t_mass = 1;\\n\\t_restitution = 0;\\n\\t_rollingFriction = 0;\\n\\t_simulationEnabled = false;\\n\\t_type = BODYTYPE_STATIC;\\n\\tstatic onLibraryLoaded() {\\n\\t\\tif (typeof Ammo !== \\\"undefined\\\") {\\n\\t\\t\\t_ammoTransform = new Ammo.btTransform();\\n\\t\\t\\t_ammoVec1 = new Ammo.btVector3();\\n\\t\\t\\t_ammoVec2 = new Ammo.btVector3();\\n\\t\\t\\t_ammoQuat = new Ammo.btQuaternion();\\n\\t\\t}\\n\\t}\\n\\tstatic onAppDestroy() {\\n\\t\\tAmmo.destroy(_ammoTransform);\\n\\t\\tAmmo.destroy(_ammoVec1);\\n\\t\\tAmmo.destroy(_ammoVec2);\\n\\t\\tAmmo.destroy(_ammoQuat);\\n\\t\\t_ammoTransform = null;\\n\\t\\t_ammoVec1 = null;\\n\\t\\t_ammoVec2 = null;\\n\\t\\t_ammoQuat = null;\\n\\t}\\n\\tset angularDamping(damping) {\\n\\t\\tif (this._angularDamping !== damping) {\\n\\t\\t\\tthis._angularDamping = damping;\\n\\t\\t\\tif (this._body) {\\n\\t\\t\\t\\tthis._body.setDamping(this._linearDamping, damping);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget angularDamping() {\\n\\t\\treturn this._angularDamping;\\n\\t}\\n\\tset angularFactor(factor) {\\n\\t\\tif (!this._angularFactor.equals(factor)) {\\n\\t\\t\\tthis._angularFactor.copy(factor);\\n\\t\\t\\tif (this._body && this._type === BODYTYPE_DYNAMIC) {\\n\\t\\t\\t\\t_ammoVec1.setValue(factor.x, factor.y, factor.z);\\n\\t\\t\\t\\tthis._body.setAngularFactor(_ammoVec1);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget angularFactor() {\\n\\t\\treturn this._angularFactor;\\n\\t}\\n\\tset angularVelocity(velocity) {\\n\\t\\tif (this._body && this._type === BODYTYPE_DYNAMIC) {\\n\\t\\t\\tthis._body.activate();\\n\\t\\t\\t_ammoVec1.setValue(velocity.x, velocity.y, velocity.z);\\n\\t\\t\\tthis._body.setAngularVelocity(_ammoVec1);\\n\\t\\t\\tthis._angularVelocity.copy(velocity);\\n\\t\\t}\\n\\t}\\n\\tget angularVelocity() {\\n\\t\\tif (this._body && this._type === BODYTYPE_DYNAMIC) {\\n\\t\\t\\tconst velocity = this._body.getAngularVelocity();\\n\\t\\t\\tthis._angularVelocity.set(velocity.x(), velocity.y(), velocity.z());\\n\\t\\t}\\n\\t\\treturn this._angularVelocity;\\n\\t}\\n\\tset body(body) {\\n\\t\\tif (this._body !== body) {\\n\\t\\t\\tthis._body = body;\\n\\t\\t\\tif (body && this._simulationEnabled) {\\n\\t\\t\\t\\tbody.activate();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget body() {\\n\\t\\treturn this._body;\\n\\t}\\n\\tset friction(friction) {\\n\\t\\tif (this._friction !== friction) {\\n\\t\\t\\tthis._friction = friction;\\n\\t\\t\\tif (this._body) {\\n\\t\\t\\t\\tthis._body.setFriction(friction);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget friction() {\\n\\t\\treturn this._friction;\\n\\t}\\n\\tset group(group) {\\n\\t\\tif (this._group !== group) {\\n\\t\\t\\tthis._group = group;\\n\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\tthis.disableSimulation();\\n\\t\\t\\t\\tthis.enableSimulation();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget group() {\\n\\t\\treturn this._group;\\n\\t}\\n\\tset linearDamping(damping) {\\n\\t\\tif (this._linearDamping !== damping) {\\n\\t\\t\\tthis._linearDamping = damping;\\n\\t\\t\\tif (this._body) {\\n\\t\\t\\t\\tthis._body.setDamping(damping, this._angularDamping);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget linearDamping() {\\n\\t\\treturn this._linearDamping;\\n\\t}\\n\\tset linearFactor(factor) {\\n\\t\\tif (!this._linearFactor.equals(factor)) {\\n\\t\\t\\tthis._linearFactor.copy(factor);\\n\\t\\t\\tif (this._body && this._type === BODYTYPE_DYNAMIC) {\\n\\t\\t\\t\\t_ammoVec1.setValue(factor.x, factor.y, factor.z);\\n\\t\\t\\t\\tthis._body.setLinearFactor(_ammoVec1);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget linearFactor() {\\n\\t\\treturn this._linearFactor;\\n\\t}\\n\\tset linearVelocity(velocity) {\\n\\t\\tif (this._body && this._type === BODYTYPE_DYNAMIC) {\\n\\t\\t\\tthis._body.activate();\\n\\t\\t\\t_ammoVec1.setValue(velocity.x, velocity.y, velocity.z);\\n\\t\\t\\tthis._body.setLinearVelocity(_ammoVec1);\\n\\t\\t\\tthis._linearVelocity.copy(velocity);\\n\\t\\t}\\n\\t}\\n\\tget linearVelocity() {\\n\\t\\tif (this._body && this._type === BODYTYPE_DYNAMIC) {\\n\\t\\t\\tconst velocity = this._body.getLinearVelocity();\\n\\t\\t\\tthis._linearVelocity.set(velocity.x(), velocity.y(), velocity.z());\\n\\t\\t}\\n\\t\\treturn this._linearVelocity;\\n\\t}\\n\\tset mask(mask) {\\n\\t\\tif (this._mask !== mask) {\\n\\t\\t\\tthis._mask = mask;\\n\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\tthis.disableSimulation();\\n\\t\\t\\t\\tthis.enableSimulation();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget mask() {\\n\\t\\treturn this._mask;\\n\\t}\\n\\tset mass(mass) {\\n\\t\\tif (this._mass !== mass) {\\n\\t\\t\\tthis._mass = mass;\\n\\t\\t\\tif (this._body && this._type === BODYTYPE_DYNAMIC) {\\n\\t\\t\\t\\tconst enabled = this.enabled && this.entity.enabled;\\n\\t\\t\\t\\tif (enabled) {\\n\\t\\t\\t\\t\\tthis.disableSimulation();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._body.getCollisionShape().calculateLocalInertia(mass, _ammoVec1);\\n\\t\\t\\t\\tthis._body.setMassProps(mass, _ammoVec1);\\n\\t\\t\\t\\tthis._body.updateInertiaTensor();\\n\\t\\t\\t\\tif (enabled) {\\n\\t\\t\\t\\t\\tthis.enableSimulation();\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget mass() {\\n\\t\\treturn this._mass;\\n\\t}\\n\\tset restitution(restitution) {\\n\\t\\tif (this._restitution !== restitution) {\\n\\t\\t\\tthis._restitution = restitution;\\n\\t\\t\\tif (this._body) {\\n\\t\\t\\t\\tthis._body.setRestitution(restitution);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget restitution() {\\n\\t\\treturn this._restitution;\\n\\t}\\n\\tset rollingFriction(friction) {\\n\\t\\tif (this._rollingFriction !== friction) {\\n\\t\\t\\tthis._rollingFriction = friction;\\n\\t\\t\\tif (this._body) {\\n\\t\\t\\t\\tthis._body.setRollingFriction(friction);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget rollingFriction() {\\n\\t\\treturn this._rollingFriction;\\n\\t}\\n\\tset type(type) {\\n\\t\\tif (this._type !== type) {\\n\\t\\t\\tthis._type = type;\\n\\t\\t\\tthis.disableSimulation();\\n\\t\\t\\tswitch (type) {\\n\\t\\t\\t\\tcase BODYTYPE_DYNAMIC:\\n\\t\\t\\t\\t\\tthis._group = BODYGROUP_DYNAMIC;\\n\\t\\t\\t\\t\\tthis._mask = BODYMASK_ALL;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase BODYTYPE_KINEMATIC:\\n\\t\\t\\t\\t\\tthis._group = BODYGROUP_KINEMATIC;\\n\\t\\t\\t\\t\\tthis._mask = BODYMASK_ALL;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase BODYTYPE_STATIC:\\n\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\tthis._group = BODYGROUP_STATIC;\\n\\t\\t\\t\\t\\tthis._mask = BODYMASK_NOT_STATIC;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\tthis.createBody();\\n\\t\\t}\\n\\t}\\n\\tget type() {\\n\\t\\treturn this._type;\\n\\t}\\n\\tcreateBody() {\\n\\t\\tconst entity = this.entity;\\n\\t\\tlet shape;\\n\\t\\tif (entity.collision) {\\n\\t\\t\\tshape = entity.collision.shape;\\n\\t\\t\\tif (entity.trigger) {\\n\\t\\t\\t\\tentity.trigger.destroy();\\n\\t\\t\\t\\tdelete entity.trigger;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (shape) {\\n\\t\\t\\tif (this._body) {\\n\\t\\t\\t\\tthis.system.removeBody(this._body);\\n\\t\\t\\t\\tthis.system.destroyBody(this._body);\\n\\t\\t\\t\\tthis._body = null;\\n\\t\\t\\t}\\n\\t\\t\\tconst mass = this._type === BODYTYPE_DYNAMIC ? this._mass : 0;\\n\\t\\t\\tthis._getEntityTransform(_ammoTransform);\\n\\t\\t\\tconst body = this.system.createBody(mass, shape, _ammoTransform);\\n\\t\\t\\tbody.setRestitution(this._restitution);\\n\\t\\t\\tbody.setFriction(this._friction);\\n\\t\\t\\tbody.setRollingFriction(this._rollingFriction);\\n\\t\\t\\tbody.setDamping(this._linearDamping, this._angularDamping);\\n\\t\\t\\tif (this._type === BODYTYPE_DYNAMIC) {\\n\\t\\t\\t\\tconst linearFactor = this._linearFactor;\\n\\t\\t\\t\\t_ammoVec1.setValue(linearFactor.x, linearFactor.y, linearFactor.z);\\n\\t\\t\\t\\tbody.setLinearFactor(_ammoVec1);\\n\\t\\t\\t\\tconst angularFactor = this._angularFactor;\\n\\t\\t\\t\\t_ammoVec1.setValue(angularFactor.x, angularFactor.y, angularFactor.z);\\n\\t\\t\\t\\tbody.setAngularFactor(_ammoVec1);\\n\\t\\t\\t} else if (this._type === BODYTYPE_KINEMATIC) {\\n\\t\\t\\t\\tbody.setCollisionFlags(body.getCollisionFlags() | BODYFLAG_KINEMATIC_OBJECT);\\n\\t\\t\\t\\tbody.setActivationState(BODYSTATE_DISABLE_DEACTIVATION);\\n\\t\\t\\t}\\n\\t\\t\\tbody.entity = entity;\\n\\t\\t\\tthis.body = body;\\n\\t\\t\\tif (this.enabled && entity.enabled) {\\n\\t\\t\\t\\tthis.enableSimulation();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tisActive() {\\n\\t\\treturn this._body ? this._body.isActive() : false;\\n\\t}\\n\\tactivate() {\\n\\t\\tif (this._body) {\\n\\t\\t\\tthis._body.activate();\\n\\t\\t}\\n\\t}\\n\\tenableSimulation() {\\n\\t\\tconst entity = this.entity;\\n\\t\\tif (entity.collision && entity.collision.enabled && !this._simulationEnabled) {\\n\\t\\t\\tconst body = this._body;\\n\\t\\t\\tif (body) {\\n\\t\\t\\t\\tthis.system.addBody(body, this._group, this._mask);\\n\\t\\t\\t\\tswitch (this._type) {\\n\\t\\t\\t\\t\\tcase BODYTYPE_DYNAMIC:\\n\\t\\t\\t\\t\\t\\tthis.system._dynamic.push(this);\\n\\t\\t\\t\\t\\t\\tbody.forceActivationState(BODYSTATE_ACTIVE_TAG);\\n\\t\\t\\t\\t\\t\\tthis.syncEntityToBody();\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\tcase BODYTYPE_KINEMATIC:\\n\\t\\t\\t\\t\\t\\tthis.system._kinematic.push(this);\\n\\t\\t\\t\\t\\t\\tbody.forceActivationState(BODYSTATE_DISABLE_DEACTIVATION);\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\tcase BODYTYPE_STATIC:\\n\\t\\t\\t\\t\\t\\tbody.forceActivationState(BODYSTATE_ACTIVE_TAG);\\n\\t\\t\\t\\t\\t\\tthis.syncEntityToBody();\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (entity.collision.type === \\\"compound\\\") {\\n\\t\\t\\t\\t\\tthis.system._compounds.push(entity.collision);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tbody.activate();\\n\\t\\t\\t\\tthis._simulationEnabled = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tdisableSimulation() {\\n\\t\\tconst body = this._body;\\n\\t\\tif (body && this._simulationEnabled) {\\n\\t\\t\\tconst system = this.system;\\n\\t\\t\\tlet idx = system._compounds.indexOf(this.entity.collision);\\n\\t\\t\\tif (idx > -1) {\\n\\t\\t\\t\\tsystem._compounds.splice(idx, 1);\\n\\t\\t\\t}\\n\\t\\t\\tidx = system._dynamic.indexOf(this);\\n\\t\\t\\tif (idx > -1) {\\n\\t\\t\\t\\tsystem._dynamic.splice(idx, 1);\\n\\t\\t\\t}\\n\\t\\t\\tidx = system._kinematic.indexOf(this);\\n\\t\\t\\tif (idx > -1) {\\n\\t\\t\\t\\tsystem._kinematic.splice(idx, 1);\\n\\t\\t\\t}\\n\\t\\t\\tsystem.removeBody(body);\\n\\t\\t\\tbody.forceActivationState(BODYSTATE_DISABLE_SIMULATION);\\n\\t\\t\\tthis._simulationEnabled = false;\\n\\t\\t}\\n\\t}\\n\\tapplyForce(x, y, z, px, py, pz) {\\n\\t\\tconst body = this._body;\\n\\t\\tif (body) {\\n\\t\\t\\tbody.activate();\\n\\t\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\t\\t_ammoVec1.setValue(x.x, x.y, x.z);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\t_ammoVec1.setValue(x, y, z);\\n\\t\\t\\t}\\n\\t\\t\\tif (y instanceof Vec3) {\\n\\t\\t\\t\\t_ammoVec2.setValue(y.x, y.y, y.z);\\n\\t\\t\\t} else if (px !== void 0) {\\n\\t\\t\\t\\t_ammoVec2.setValue(px, py, pz);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\t_ammoVec2.setValue(0, 0, 0);\\n\\t\\t\\t}\\n\\t\\t\\tbody.applyForce(_ammoVec1, _ammoVec2);\\n\\t\\t}\\n\\t}\\n\\tapplyTorque(x, y, z) {\\n\\t\\tconst body = this._body;\\n\\t\\tif (body) {\\n\\t\\t\\tbody.activate();\\n\\t\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\t\\t_ammoVec1.setValue(x.x, x.y, x.z);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\t_ammoVec1.setValue(x, y, z);\\n\\t\\t\\t}\\n\\t\\t\\tbody.applyTorque(_ammoVec1);\\n\\t\\t}\\n\\t}\\n\\tapplyImpulse(x, y, z, px, py, pz) {\\n\\t\\tconst body = this._body;\\n\\t\\tif (body) {\\n\\t\\t\\tbody.activate();\\n\\t\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\t\\t_ammoVec1.setValue(x.x, x.y, x.z);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\t_ammoVec1.setValue(x, y, z);\\n\\t\\t\\t}\\n\\t\\t\\tif (y instanceof Vec3) {\\n\\t\\t\\t\\t_ammoVec2.setValue(y.x, y.y, y.z);\\n\\t\\t\\t} else if (px !== void 0) {\\n\\t\\t\\t\\t_ammoVec2.setValue(px, py, pz);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\t_ammoVec2.setValue(0, 0, 0);\\n\\t\\t\\t}\\n\\t\\t\\tbody.applyImpulse(_ammoVec1, _ammoVec2);\\n\\t\\t}\\n\\t}\\n\\tapplyTorqueImpulse(x, y, z) {\\n\\t\\tconst body = this._body;\\n\\t\\tif (body) {\\n\\t\\t\\tbody.activate();\\n\\t\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\t\\t_ammoVec1.setValue(x.x, x.y, x.z);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\t_ammoVec1.setValue(x, y, z);\\n\\t\\t\\t}\\n\\t\\t\\tbody.applyTorqueImpulse(_ammoVec1);\\n\\t\\t}\\n\\t}\\n\\tisStatic() {\\n\\t\\treturn this._type === BODYTYPE_STATIC;\\n\\t}\\n\\tisStaticOrKinematic() {\\n\\t\\treturn this._type === BODYTYPE_STATIC || this._type === BODYTYPE_KINEMATIC;\\n\\t}\\n\\tisKinematic() {\\n\\t\\treturn this._type === BODYTYPE_KINEMATIC;\\n\\t}\\n\\t_getEntityTransform(transform) {\\n\\t\\tconst entity = this.entity;\\n\\t\\tconst component = entity.collision;\\n\\t\\tif (component) {\\n\\t\\t\\tconst bodyPos = component.getShapePosition();\\n\\t\\t\\tconst bodyRot = component.getShapeRotation();\\n\\t\\t\\t_ammoVec1.setValue(bodyPos.x, bodyPos.y, bodyPos.z);\\n\\t\\t\\t_ammoQuat.setValue(bodyRot.x, bodyRot.y, bodyRot.z, bodyRot.w);\\n\\t\\t} else {\\n\\t\\t\\tconst pos = entity.getPosition();\\n\\t\\t\\tconst rot = entity.getRotation();\\n\\t\\t\\t_ammoVec1.setValue(pos.x, pos.y, pos.z);\\n\\t\\t\\t_ammoQuat.setValue(rot.x, rot.y, rot.z, rot.w);\\n\\t\\t}\\n\\t\\ttransform.setOrigin(_ammoVec1);\\n\\t\\ttransform.setRotation(_ammoQuat);\\n\\t}\\n\\tsyncEntityToBody() {\\n\\t\\tconst body = this._body;\\n\\t\\tif (body) {\\n\\t\\t\\tthis._getEntityTransform(_ammoTransform);\\n\\t\\t\\tbody.setWorldTransform(_ammoTransform);\\n\\t\\t\\tif (this._type === BODYTYPE_KINEMATIC) {\\n\\t\\t\\t\\tconst motionState = body.getMotionState();\\n\\t\\t\\t\\tif (motionState) {\\n\\t\\t\\t\\t\\tmotionState.setWorldTransform(_ammoTransform);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tbody.activate();\\n\\t\\t}\\n\\t}\\n\\t_updateDynamic() {\\n\\t\\tconst body = this._body;\\n\\t\\tif (body.isActive()) {\\n\\t\\t\\tconst motionState = body.getMotionState();\\n\\t\\t\\tif (motionState) {\\n\\t\\t\\t\\tconst entity = this.entity;\\n\\t\\t\\t\\tmotionState.getWorldTransform(_ammoTransform);\\n\\t\\t\\t\\tconst p = _ammoTransform.getOrigin();\\n\\t\\t\\t\\tconst q = _ammoTransform.getRotation();\\n\\t\\t\\t\\tconst component = entity.collision;\\n\\t\\t\\t\\tif (component && component._hasOffset) {\\n\\t\\t\\t\\t\\tconst lo = component.data.linearOffset;\\n\\t\\t\\t\\t\\tconst ao = component.data.angularOffset;\\n\\t\\t\\t\\t\\tconst invertedAo = _quat2.copy(ao).invert();\\n\\t\\t\\t\\t\\tconst entityRot = _quat1.set(q.x(), q.y(), q.z(), q.w()).mul(invertedAo);\\n\\t\\t\\t\\t\\tentityRot.transformVector(lo, _vec3);\\n\\t\\t\\t\\t\\tentity.setPosition(p.x() - _vec3.x, p.y() - _vec3.y, p.z() - _vec3.z);\\n\\t\\t\\t\\t\\tentity.setRotation(entityRot);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tentity.setPosition(p.x(), p.y(), p.z());\\n\\t\\t\\t\\t\\tentity.setRotation(q.x(), q.y(), q.z(), q.w());\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_updateKinematic() {\\n\\t\\tconst motionState = this._body.getMotionState();\\n\\t\\tif (motionState) {\\n\\t\\t\\tthis._getEntityTransform(_ammoTransform);\\n\\t\\t\\tmotionState.setWorldTransform(_ammoTransform);\\n\\t\\t}\\n\\t}\\n\\tteleport(x, y, z, rx, ry, rz) {\\n\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\tthis.entity.setPosition(x);\\n\\t\\t} else {\\n\\t\\t\\tthis.entity.setPosition(x, y, z);\\n\\t\\t}\\n\\t\\tif (y instanceof Quat) {\\n\\t\\t\\tthis.entity.setRotation(y);\\n\\t\\t} else if (y instanceof Vec3) {\\n\\t\\t\\tthis.entity.setEulerAngles(y);\\n\\t\\t} else if (rx !== void 0) {\\n\\t\\t\\tthis.entity.setEulerAngles(rx, ry, rz);\\n\\t\\t}\\n\\t\\tthis.syncEntityToBody();\\n\\t}\\n\\tonEnable() {\\n\\t\\tif (!this._body) {\\n\\t\\t\\tthis.createBody();\\n\\t\\t}\\n\\t\\tthis.enableSimulation();\\n\\t}\\n\\tonDisable() {\\n\\t\\tthis.disableSimulation();\\n\\t}\\n}\\n\\nclass RigidBodyComponentData {\\n\\tenabled = true;\\n}\\n\\nlet ammoRayStart, ammoRayEnd;\\nclass RaycastResult {\\n\\tentity;\\n\\tpoint;\\n\\tnormal;\\n\\thitFraction;\\n\\tconstructor(entity, point, normal, hitFraction) {\\n\\t\\tthis.entity = entity;\\n\\t\\tthis.point = point;\\n\\t\\tthis.normal = normal;\\n\\t\\tthis.hitFraction = hitFraction;\\n\\t}\\n}\\nclass SingleContactResult {\\n\\ta;\\n\\tb;\\n\\timpulse;\\n\\tlocalPointA;\\n\\tlocalPointB;\\n\\tpointA;\\n\\tpointB;\\n\\tnormal;\\n\\tconstructor(a, b, contactPoint) {\\n\\t\\tif (arguments.length !== 0) {\\n\\t\\t\\tthis.a = a;\\n\\t\\t\\tthis.b = b;\\n\\t\\t\\tthis.impulse = contactPoint.impulse;\\n\\t\\t\\tthis.localPointA = contactPoint.localPoint;\\n\\t\\t\\tthis.localPointB = contactPoint.localPointOther;\\n\\t\\t\\tthis.pointA = contactPoint.point;\\n\\t\\t\\tthis.pointB = contactPoint.pointOther;\\n\\t\\t\\tthis.normal = contactPoint.normal;\\n\\t\\t} else {\\n\\t\\t\\tthis.a = null;\\n\\t\\t\\tthis.b = null;\\n\\t\\t\\tthis.impulse = 0;\\n\\t\\t\\tthis.localPointA = new Vec3();\\n\\t\\t\\tthis.localPointB = new Vec3();\\n\\t\\t\\tthis.pointA = new Vec3();\\n\\t\\t\\tthis.pointB = new Vec3();\\n\\t\\t\\tthis.normal = new Vec3();\\n\\t\\t}\\n\\t}\\n}\\nclass ContactPoint {\\n\\tlocalPoint;\\n\\tlocalPointOther;\\n\\tpoint;\\n\\tpointOther;\\n\\tnormal;\\n\\timpulse;\\n\\tconstructor(localPoint = new Vec3(), localPointOther = new Vec3(), point = new Vec3(), pointOther = new Vec3(), normal = new Vec3(), impulse = 0) {\\n\\t\\tthis.localPoint = localPoint;\\n\\t\\tthis.localPointOther = localPointOther;\\n\\t\\tthis.point = point;\\n\\t\\tthis.pointOther = pointOther;\\n\\t\\tthis.normal = normal;\\n\\t\\tthis.impulse = impulse;\\n\\t}\\n}\\nclass ContactResult {\\n\\tother;\\n\\tcontacts;\\n\\tconstructor(other, contacts) {\\n\\t\\tthis.other = other;\\n\\t\\tthis.contacts = contacts;\\n\\t}\\n}\\nconst _schema$3 = [\\\"enabled\\\"];\\nclass RigidBodyComponentSystem extends ComponentSystem {\\n\\tstatic EVENT_CONTACT = \\\"contact\\\";\\n\\tmaxSubSteps = 10;\\n\\tfixedTimeStep = 1 / 60;\\n\\tgravity = new Vec3(0, -9.81, 0);\\n\\t_gravityFloat32 = new Float32Array(3);\\n\\t_dynamic = [];\\n\\t_kinematic = [];\\n\\t_triggers = [];\\n\\t_compounds = [];\\n\\tconstructor(app) {\\n\\t\\tsuper(app);\\n\\t\\tthis.id = \\\"rigidbody\\\";\\n\\t\\tthis._stats = app.stats.frame;\\n\\t\\tthis.ComponentType = RigidBodyComponent;\\n\\t\\tthis.DataType = RigidBodyComponentData;\\n\\t\\tthis.contactPointPool = null;\\n\\t\\tthis.contactResultPool = null;\\n\\t\\tthis.singleContactResultPool = null;\\n\\t\\tthis.schema = _schema$3;\\n\\t\\tthis.collisions = {};\\n\\t\\tthis.frameCollisions = {};\\n\\t\\tthis.on(\\\"beforeremove\\\", this.onBeforeRemove, this);\\n\\t}\\n\\tonLibraryLoaded() {\\n\\t\\tif (typeof Ammo !== \\\"undefined\\\") {\\n\\t\\t\\tthis.collisionConfiguration = new Ammo.btDefaultCollisionConfiguration();\\n\\t\\t\\tthis.dispatcher = new Ammo.btCollisionDispatcher(this.collisionConfiguration);\\n\\t\\t\\tthis.overlappingPairCache = new Ammo.btDbvtBroadphase();\\n\\t\\t\\tthis.solver = new Ammo.btSequentialImpulseConstraintSolver();\\n\\t\\t\\tthis.dynamicsWorld = new Ammo.btDiscreteDynamicsWorld(this.dispatcher, this.overlappingPairCache, this.solver, this.collisionConfiguration);\\n\\t\\t\\tif (this.dynamicsWorld.setInternalTickCallback) {\\n\\t\\t\\t\\tconst checkForCollisionsPointer = Ammo.addFunction(this._checkForCollisions.bind(this), \\\"vif\\\");\\n\\t\\t\\t\\tthis.dynamicsWorld.setInternalTickCallback(checkForCollisionsPointer);\\n\\t\\t\\t}\\n\\t\\t\\tammoRayStart = new Ammo.btVector3();\\n\\t\\t\\tammoRayEnd = new Ammo.btVector3();\\n\\t\\t\\tRigidBodyComponent.onLibraryLoaded();\\n\\t\\t\\tthis.contactPointPool = new ObjectPool(ContactPoint, 1);\\n\\t\\t\\tthis.contactResultPool = new ObjectPool(ContactResult, 1);\\n\\t\\t\\tthis.singleContactResultPool = new ObjectPool(SingleContactResult, 1);\\n\\t\\t\\tthis.app.systems.on(\\\"update\\\", this.onUpdate, this);\\n\\t\\t} else {\\n\\t\\t\\tthis.app.systems.off(\\\"update\\\", this.onUpdate, this);\\n\\t\\t}\\n\\t}\\n\\tinitializeComponentData(component, data, properties) {\\n\\t\\tconst props = [\\n\\t\\t\\t\\\"mass\\\",\\n\\t\\t\\t\\\"linearDamping\\\",\\n\\t\\t\\t\\\"angularDamping\\\",\\n\\t\\t\\t\\\"linearFactor\\\",\\n\\t\\t\\t\\\"angularFactor\\\",\\n\\t\\t\\t\\\"friction\\\",\\n\\t\\t\\t\\\"rollingFriction\\\",\\n\\t\\t\\t\\\"restitution\\\",\\n\\t\\t\\t\\\"type\\\",\\n\\t\\t\\t\\\"group\\\",\\n\\t\\t\\t\\\"mask\\\"\\n\\t\\t];\\n\\t\\tfor (const property of props) {\\n\\t\\t\\tif (data.hasOwnProperty(property)) {\\n\\t\\t\\t\\tconst value = data[property];\\n\\t\\t\\t\\tif (Array.isArray(value)) {\\n\\t\\t\\t\\t\\tcomponent[property] = new Vec3(value[0], value[1], value[2]);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tcomponent[property] = value;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsuper.initializeComponentData(component, data, [\\\"enabled\\\"]);\\n\\t}\\n\\tcloneComponent(entity, clone) {\\n\\t\\tconst rigidbody = entity.rigidbody;\\n\\t\\tconst data = {\\n\\t\\t\\tenabled: rigidbody.enabled,\\n\\t\\t\\tmass: rigidbody.mass,\\n\\t\\t\\tlinearDamping: rigidbody.linearDamping,\\n\\t\\t\\tangularDamping: rigidbody.angularDamping,\\n\\t\\t\\tlinearFactor: [rigidbody.linearFactor.x, rigidbody.linearFactor.y, rigidbody.linearFactor.z],\\n\\t\\t\\tangularFactor: [rigidbody.angularFactor.x, rigidbody.angularFactor.y, rigidbody.angularFactor.z],\\n\\t\\t\\tfriction: rigidbody.friction,\\n\\t\\t\\trollingFriction: rigidbody.rollingFriction,\\n\\t\\t\\trestitution: rigidbody.restitution,\\n\\t\\t\\ttype: rigidbody.type,\\n\\t\\t\\tgroup: rigidbody.group,\\n\\t\\t\\tmask: rigidbody.mask\\n\\t\\t};\\n\\t\\treturn this.addComponent(clone, data);\\n\\t}\\n\\tonBeforeRemove(entity, component) {\\n\\t\\tif (component.enabled) {\\n\\t\\t\\tcomponent.enabled = false;\\n\\t\\t}\\n\\t\\tif (component.body) {\\n\\t\\t\\tthis.destroyBody(component.body);\\n\\t\\t\\tcomponent.body = null;\\n\\t\\t}\\n\\t}\\n\\taddBody(body, group, mask) {\\n\\t\\tif (group !== void 0 && mask !== void 0) {\\n\\t\\t\\tthis.dynamicsWorld.addRigidBody(body, group, mask);\\n\\t\\t} else {\\n\\t\\t\\tthis.dynamicsWorld.addRigidBody(body);\\n\\t\\t}\\n\\t}\\n\\tremoveBody(body) {\\n\\t\\tthis.dynamicsWorld.removeRigidBody(body);\\n\\t}\\n\\tcreateBody(mass, shape, transform) {\\n\\t\\tconst localInertia = new Ammo.btVector3(0, 0, 0);\\n\\t\\tif (mass !== 0) {\\n\\t\\t\\tshape.calculateLocalInertia(mass, localInertia);\\n\\t\\t}\\n\\t\\tconst motionState = new Ammo.btDefaultMotionState(transform);\\n\\t\\tconst bodyInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, shape, localInertia);\\n\\t\\tconst body = new Ammo.btRigidBody(bodyInfo);\\n\\t\\tAmmo.destroy(bodyInfo);\\n\\t\\tAmmo.destroy(localInertia);\\n\\t\\treturn body;\\n\\t}\\n\\tdestroyBody(body) {\\n\\t\\tconst motionState = body.getMotionState();\\n\\t\\tif (motionState) {\\n\\t\\t\\tAmmo.destroy(motionState);\\n\\t\\t}\\n\\t\\tAmmo.destroy(body);\\n\\t}\\n\\traycastFirst(start, end, options = {}) {\\n\\t\\tif (options.filterTags || options.filterCallback) {\\n\\t\\t\\toptions.sort = true;\\n\\t\\t\\treturn this.raycastAll(start, end, options)[0] || null;\\n\\t\\t}\\n\\t\\tlet result = null;\\n\\t\\tammoRayStart.setValue(start.x, start.y, start.z);\\n\\t\\tammoRayEnd.setValue(end.x, end.y, end.z);\\n\\t\\tconst rayCallback = new Ammo.ClosestRayResultCallback(ammoRayStart, ammoRayEnd);\\n\\t\\tif (typeof options.filterCollisionGroup === \\\"number\\\") {\\n\\t\\t\\trayCallback.set_m_collisionFilterGroup(options.filterCollisionGroup);\\n\\t\\t}\\n\\t\\tif (typeof options.filterCollisionMask === \\\"number\\\") {\\n\\t\\t\\trayCallback.set_m_collisionFilterMask(options.filterCollisionMask);\\n\\t\\t}\\n\\t\\tthis.dynamicsWorld.rayTest(ammoRayStart, ammoRayEnd, rayCallback);\\n\\t\\tif (rayCallback.hasHit()) {\\n\\t\\t\\tconst collisionObj = rayCallback.get_m_collisionObject();\\n\\t\\t\\tconst body = Ammo.castObject(collisionObj, Ammo.btRigidBody);\\n\\t\\t\\tif (body) {\\n\\t\\t\\t\\tconst point = rayCallback.get_m_hitPointWorld();\\n\\t\\t\\t\\tconst normal = rayCallback.get_m_hitNormalWorld();\\n\\t\\t\\t\\tresult = new RaycastResult(\\n\\t\\t\\t\\t\\tbody.entity,\\n\\t\\t\\t\\t\\tnew Vec3(point.x(), point.y(), point.z()),\\n\\t\\t\\t\\t\\tnew Vec3(normal.x(), normal.y(), normal.z()),\\n\\t\\t\\t\\t\\trayCallback.get_m_closestHitFraction()\\n\\t\\t\\t\\t);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tAmmo.destroy(rayCallback);\\n\\t\\treturn result;\\n\\t}\\n\\traycastAll(start, end, options = {}) {\\n\\t\\tconst results = [];\\n\\t\\tammoRayStart.setValue(start.x, start.y, start.z);\\n\\t\\tammoRayEnd.setValue(end.x, end.y, end.z);\\n\\t\\tconst rayCallback = new Ammo.AllHitsRayResultCallback(ammoRayStart, ammoRayEnd);\\n\\t\\tif (typeof options.filterCollisionGroup === \\\"number\\\") {\\n\\t\\t\\trayCallback.set_m_collisionFilterGroup(options.filterCollisionGroup);\\n\\t\\t}\\n\\t\\tif (typeof options.filterCollisionMask === \\\"number\\\") {\\n\\t\\t\\trayCallback.set_m_collisionFilterMask(options.filterCollisionMask);\\n\\t\\t}\\n\\t\\tthis.dynamicsWorld.rayTest(ammoRayStart, ammoRayEnd, rayCallback);\\n\\t\\tif (rayCallback.hasHit()) {\\n\\t\\t\\tconst collisionObjs = rayCallback.get_m_collisionObjects();\\n\\t\\t\\tconst points = rayCallback.get_m_hitPointWorld();\\n\\t\\t\\tconst normals = rayCallback.get_m_hitNormalWorld();\\n\\t\\t\\tconst hitFractions = rayCallback.get_m_hitFractions();\\n\\t\\t\\tconst numHits = collisionObjs.size();\\n\\t\\t\\tfor (let i = 0; i < numHits; i++) {\\n\\t\\t\\t\\tconst body = Ammo.castObject(collisionObjs.at(i), Ammo.btRigidBody);\\n\\t\\t\\t\\tif (body && body.entity) {\\n\\t\\t\\t\\t\\tif (options.filterTags && !body.entity.tags.has(...options.filterTags) || options.filterCallback && !options.filterCallback(body.entity)) {\\n\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tconst point = points.at(i);\\n\\t\\t\\t\\t\\tconst normal = normals.at(i);\\n\\t\\t\\t\\t\\tconst result = new RaycastResult(\\n\\t\\t\\t\\t\\t\\tbody.entity,\\n\\t\\t\\t\\t\\t\\tnew Vec3(point.x(), point.y(), point.z()),\\n\\t\\t\\t\\t\\t\\tnew Vec3(normal.x(), normal.y(), normal.z()),\\n\\t\\t\\t\\t\\t\\thitFractions.at(i)\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\tresults.push(result);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (options.sort) {\\n\\t\\t\\t\\tresults.sort((a, b) => a.hitFraction - b.hitFraction);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tAmmo.destroy(rayCallback);\\n\\t\\treturn results;\\n\\t}\\n\\t_storeCollision(entity, other) {\\n\\t\\tlet isNewCollision = false;\\n\\t\\tconst guid = entity.guid;\\n\\t\\tthis.collisions[guid] = this.collisions[guid] || { others: [], entity };\\n\\t\\tif (this.collisions[guid].others.indexOf(other) < 0) {\\n\\t\\t\\tthis.collisions[guid].others.push(other);\\n\\t\\t\\tisNewCollision = true;\\n\\t\\t}\\n\\t\\tthis.frameCollisions[guid] = this.frameCollisions[guid] || { others: [], entity };\\n\\t\\tthis.frameCollisions[guid].others.push(other);\\n\\t\\treturn isNewCollision;\\n\\t}\\n\\t_createContactPointFromAmmo(contactPoint) {\\n\\t\\tconst localPointA = contactPoint.get_m_localPointA();\\n\\t\\tconst localPointB = contactPoint.get_m_localPointB();\\n\\t\\tconst positionWorldOnA = contactPoint.getPositionWorldOnA();\\n\\t\\tconst positionWorldOnB = contactPoint.getPositionWorldOnB();\\n\\t\\tconst normalWorldOnB = contactPoint.get_m_normalWorldOnB();\\n\\t\\tconst contact = this.contactPointPool.allocate();\\n\\t\\tcontact.localPoint.set(localPointA.x(), localPointA.y(), localPointA.z());\\n\\t\\tcontact.localPointOther.set(localPointB.x(), localPointB.y(), localPointB.z());\\n\\t\\tcontact.point.set(positionWorldOnA.x(), positionWorldOnA.y(), positionWorldOnA.z());\\n\\t\\tcontact.pointOther.set(positionWorldOnB.x(), positionWorldOnB.y(), positionWorldOnB.z());\\n\\t\\tcontact.normal.set(normalWorldOnB.x(), normalWorldOnB.y(), normalWorldOnB.z());\\n\\t\\tcontact.impulse = contactPoint.getAppliedImpulse();\\n\\t\\treturn contact;\\n\\t}\\n\\t_createReverseContactPointFromAmmo(contactPoint) {\\n\\t\\tconst localPointA = contactPoint.get_m_localPointA();\\n\\t\\tconst localPointB = contactPoint.get_m_localPointB();\\n\\t\\tconst positionWorldOnA = contactPoint.getPositionWorldOnA();\\n\\t\\tconst positionWorldOnB = contactPoint.getPositionWorldOnB();\\n\\t\\tconst normalWorldOnB = contactPoint.get_m_normalWorldOnB();\\n\\t\\tconst contact = this.contactPointPool.allocate();\\n\\t\\tcontact.localPointOther.set(localPointA.x(), localPointA.y(), localPointA.z());\\n\\t\\tcontact.localPoint.set(localPointB.x(), localPointB.y(), localPointB.z());\\n\\t\\tcontact.pointOther.set(positionWorldOnA.x(), positionWorldOnA.y(), positionWorldOnA.z());\\n\\t\\tcontact.point.set(positionWorldOnB.x(), positionWorldOnB.y(), positionWorldOnB.z());\\n\\t\\tcontact.normal.set(normalWorldOnB.x(), normalWorldOnB.y(), normalWorldOnB.z());\\n\\t\\tcontact.impulse = contactPoint.getAppliedImpulse();\\n\\t\\treturn contact;\\n\\t}\\n\\t_createSingleContactResult(a, b, contactPoint) {\\n\\t\\tconst result = this.singleContactResultPool.allocate();\\n\\t\\tresult.a = a;\\n\\t\\tresult.b = b;\\n\\t\\tresult.localPointA = contactPoint.localPoint;\\n\\t\\tresult.localPointB = contactPoint.localPointOther;\\n\\t\\tresult.pointA = contactPoint.point;\\n\\t\\tresult.pointB = contactPoint.pointOther;\\n\\t\\tresult.normal = contactPoint.normal;\\n\\t\\tresult.impulse = contactPoint.impulse;\\n\\t\\treturn result;\\n\\t}\\n\\t_createContactResult(other, contacts) {\\n\\t\\tconst result = this.contactResultPool.allocate();\\n\\t\\tresult.other = other;\\n\\t\\tresult.contacts = contacts;\\n\\t\\treturn result;\\n\\t}\\n\\t_cleanOldCollisions() {\\n\\t\\tfor (const guid in this.collisions) {\\n\\t\\t\\tif (this.collisions.hasOwnProperty(guid)) {\\n\\t\\t\\t\\tconst frameCollision = this.frameCollisions[guid];\\n\\t\\t\\t\\tconst collision = this.collisions[guid];\\n\\t\\t\\t\\tconst entity = collision.entity;\\n\\t\\t\\t\\tconst entityCollision = entity.collision;\\n\\t\\t\\t\\tconst entityRigidbody = entity.rigidbody;\\n\\t\\t\\t\\tconst others = collision.others;\\n\\t\\t\\t\\tconst length = others.length;\\n\\t\\t\\t\\tlet i = length;\\n\\t\\t\\t\\twhile (i--) {\\n\\t\\t\\t\\t\\tconst other = others[i];\\n\\t\\t\\t\\t\\tif (!frameCollision || frameCollision.others.indexOf(other) < 0) {\\n\\t\\t\\t\\t\\t\\tothers.splice(i, 1);\\n\\t\\t\\t\\t\\t\\tif (entity.trigger) {\\n\\t\\t\\t\\t\\t\\t\\tif (entityCollision) {\\n\\t\\t\\t\\t\\t\\t\\t\\tentityCollision.fire(\\\"triggerleave\\\", other);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\tif (other.rigidbody) {\\n\\t\\t\\t\\t\\t\\t\\t\\tother.rigidbody.fire(\\\"triggerleave\\\", entity);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else if (!other.trigger) {\\n\\t\\t\\t\\t\\t\\t\\tif (entityRigidbody) {\\n\\t\\t\\t\\t\\t\\t\\t\\tentityRigidbody.fire(\\\"collisionend\\\", other);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\tif (entityCollision) {\\n\\t\\t\\t\\t\\t\\t\\t\\tentityCollision.fire(\\\"collisionend\\\", other);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (others.length === 0) {\\n\\t\\t\\t\\t\\tdelete this.collisions[guid];\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_hasContactEvent(entity) {\\n\\t\\tconst c = entity.collision;\\n\\t\\tif (c && (c.hasEvent(\\\"collisionstart\\\") || c.hasEvent(\\\"collisionend\\\") || c.hasEvent(\\\"contact\\\"))) {\\n\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tconst r = entity.rigidbody;\\n\\t\\treturn r && (r.hasEvent(\\\"collisionstart\\\") || r.hasEvent(\\\"collisionend\\\") || r.hasEvent(\\\"contact\\\"));\\n\\t}\\n\\t_checkForCollisions(world, timeStep) {\\n\\t\\tconst dynamicsWorld = Ammo.wrapPointer(world, Ammo.btDynamicsWorld);\\n\\t\\tconst dispatcher = dynamicsWorld.getDispatcher();\\n\\t\\tconst numManifolds = dispatcher.getNumManifolds();\\n\\t\\tthis.frameCollisions = {};\\n\\t\\tfor (let i = 0; i < numManifolds; i++) {\\n\\t\\t\\tconst manifold = dispatcher.getManifoldByIndexInternal(i);\\n\\t\\t\\tconst body0 = manifold.getBody0();\\n\\t\\t\\tconst body1 = manifold.getBody1();\\n\\t\\t\\tconst wb0 = Ammo.castObject(body0, Ammo.btRigidBody);\\n\\t\\t\\tconst wb1 = Ammo.castObject(body1, Ammo.btRigidBody);\\n\\t\\t\\tconst e0 = wb0.entity;\\n\\t\\t\\tconst e1 = wb1.entity;\\n\\t\\t\\tif (!e0 || !e1) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tconst flags0 = wb0.getCollisionFlags();\\n\\t\\t\\tconst flags1 = wb1.getCollisionFlags();\\n\\t\\t\\tconst numContacts = manifold.getNumContacts();\\n\\t\\t\\tconst forwardContacts = [];\\n\\t\\t\\tconst reverseContacts = [];\\n\\t\\t\\tlet newCollision;\\n\\t\\t\\tif (numContacts > 0) {\\n\\t\\t\\t\\tif (flags0 & BODYFLAG_NORESPONSE_OBJECT || flags1 & BODYFLAG_NORESPONSE_OBJECT) {\\n\\t\\t\\t\\t\\tconst e0Events = e0.collision && (e0.collision.hasEvent(\\\"triggerenter\\\") || e0.collision.hasEvent(\\\"triggerleave\\\"));\\n\\t\\t\\t\\t\\tconst e1Events = e1.collision && (e1.collision.hasEvent(\\\"triggerenter\\\") || e1.collision.hasEvent(\\\"triggerleave\\\"));\\n\\t\\t\\t\\t\\tconst e0BodyEvents = e0.rigidbody && (e0.rigidbody.hasEvent(\\\"triggerenter\\\") || e0.rigidbody.hasEvent(\\\"triggerleave\\\"));\\n\\t\\t\\t\\t\\tconst e1BodyEvents = e1.rigidbody && (e1.rigidbody.hasEvent(\\\"triggerenter\\\") || e1.rigidbody.hasEvent(\\\"triggerleave\\\"));\\n\\t\\t\\t\\t\\tif (e0Events) {\\n\\t\\t\\t\\t\\t\\tnewCollision = this._storeCollision(e0, e1);\\n\\t\\t\\t\\t\\t\\tif (newCollision && !(flags1 & BODYFLAG_NORESPONSE_OBJECT)) {\\n\\t\\t\\t\\t\\t\\t\\te0.collision.fire(\\\"triggerenter\\\", e1);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (e1Events) {\\n\\t\\t\\t\\t\\t\\tnewCollision = this._storeCollision(e1, e0);\\n\\t\\t\\t\\t\\t\\tif (newCollision && !(flags0 & BODYFLAG_NORESPONSE_OBJECT)) {\\n\\t\\t\\t\\t\\t\\t\\te1.collision.fire(\\\"triggerenter\\\", e0);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (e0BodyEvents) {\\n\\t\\t\\t\\t\\t\\tif (!newCollision) {\\n\\t\\t\\t\\t\\t\\t\\tnewCollision = this._storeCollision(e1, e0);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (newCollision) {\\n\\t\\t\\t\\t\\t\\t\\te0.rigidbody.fire(\\\"triggerenter\\\", e1);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (e1BodyEvents) {\\n\\t\\t\\t\\t\\t\\tif (!newCollision) {\\n\\t\\t\\t\\t\\t\\t\\tnewCollision = this._storeCollision(e0, e1);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (newCollision) {\\n\\t\\t\\t\\t\\t\\t\\te1.rigidbody.fire(\\\"triggerenter\\\", e0);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tconst e0Events = this._hasContactEvent(e0);\\n\\t\\t\\t\\t\\tconst e1Events = this._hasContactEvent(e1);\\n\\t\\t\\t\\t\\tconst globalEvents = this.hasEvent(\\\"contact\\\");\\n\\t\\t\\t\\t\\tif (globalEvents || e0Events || e1Events) {\\n\\t\\t\\t\\t\\t\\tfor (let j = 0; j < numContacts; j++) {\\n\\t\\t\\t\\t\\t\\t\\tconst btContactPoint = manifold.getContactPoint(j);\\n\\t\\t\\t\\t\\t\\t\\tconst contactPoint = this._createContactPointFromAmmo(btContactPoint);\\n\\t\\t\\t\\t\\t\\t\\tif (e0Events || e1Events) {\\n\\t\\t\\t\\t\\t\\t\\t\\tforwardContacts.push(contactPoint);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst reverseContactPoint = this._createReverseContactPointFromAmmo(btContactPoint);\\n\\t\\t\\t\\t\\t\\t\\t\\treverseContacts.push(reverseContactPoint);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\tif (globalEvents) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst result = this._createSingleContactResult(e0, e1, contactPoint);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire(\\\"contact\\\", result);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (e0Events) {\\n\\t\\t\\t\\t\\t\\t\\tconst forwardResult = this._createContactResult(e1, forwardContacts);\\n\\t\\t\\t\\t\\t\\t\\tnewCollision = this._storeCollision(e0, e1);\\n\\t\\t\\t\\t\\t\\t\\tif (e0.collision) {\\n\\t\\t\\t\\t\\t\\t\\t\\te0.collision.fire(\\\"contact\\\", forwardResult);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (newCollision) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\te0.collision.fire(\\\"collisionstart\\\", forwardResult);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\tif (e0.rigidbody) {\\n\\t\\t\\t\\t\\t\\t\\t\\te0.rigidbody.fire(\\\"contact\\\", forwardResult);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (newCollision) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\te0.rigidbody.fire(\\\"collisionstart\\\", forwardResult);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (e1Events) {\\n\\t\\t\\t\\t\\t\\t\\tconst reverseResult = this._createContactResult(e0, reverseContacts);\\n\\t\\t\\t\\t\\t\\t\\tnewCollision = this._storeCollision(e1, e0);\\n\\t\\t\\t\\t\\t\\t\\tif (e1.collision) {\\n\\t\\t\\t\\t\\t\\t\\t\\te1.collision.fire(\\\"contact\\\", reverseResult);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (newCollision) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\te1.collision.fire(\\\"collisionstart\\\", reverseResult);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\tif (e1.rigidbody) {\\n\\t\\t\\t\\t\\t\\t\\t\\te1.rigidbody.fire(\\\"contact\\\", reverseResult);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (newCollision) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\te1.rigidbody.fire(\\\"collisionstart\\\", reverseResult);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._cleanOldCollisions();\\n\\t\\tthis.contactPointPool.freeAll();\\n\\t\\tthis.contactResultPool.freeAll();\\n\\t\\tthis.singleContactResultPool.freeAll();\\n\\t}\\n\\tonUpdate(dt) {\\n\\t\\tlet i, len;\\n\\t\\tthis._stats.physicsStart = now();\\n\\t\\tthis._gravityFloat32[0] = this.gravity.x;\\n\\t\\tthis._gravityFloat32[1] = this.gravity.y;\\n\\t\\tthis._gravityFloat32[2] = this.gravity.z;\\n\\t\\tconst gravity = this.dynamicsWorld.getGravity();\\n\\t\\tif (gravity.x() !== this._gravityFloat32[0] || gravity.y() !== this._gravityFloat32[1] || gravity.z() !== this._gravityFloat32[2]) {\\n\\t\\t\\tgravity.setValue(this.gravity.x, this.gravity.y, this.gravity.z);\\n\\t\\t\\tthis.dynamicsWorld.setGravity(gravity);\\n\\t\\t}\\n\\t\\tconst triggers = this._triggers;\\n\\t\\tfor (i = 0, len = triggers.length; i < len; i++) {\\n\\t\\t\\ttriggers[i].updateTransform();\\n\\t\\t}\\n\\t\\tconst compounds = this._compounds;\\n\\t\\tfor (i = 0, len = compounds.length; i < len; i++) {\\n\\t\\t\\tcompounds[i]._updateCompound();\\n\\t\\t}\\n\\t\\tconst kinematic = this._kinematic;\\n\\t\\tfor (i = 0, len = kinematic.length; i < len; i++) {\\n\\t\\t\\tkinematic[i]._updateKinematic();\\n\\t\\t}\\n\\t\\tthis.dynamicsWorld.stepSimulation(dt, this.maxSubSteps, this.fixedTimeStep);\\n\\t\\tconst dynamic = this._dynamic;\\n\\t\\tfor (i = 0, len = dynamic.length; i < len; i++) {\\n\\t\\t\\tdynamic[i]._updateDynamic();\\n\\t\\t}\\n\\t\\tif (!this.dynamicsWorld.setInternalTickCallback) {\\n\\t\\t\\tthis._checkForCollisions(Ammo.getPointer(this.dynamicsWorld), dt);\\n\\t\\t}\\n\\t\\tthis._stats.physicsTime = now() - this._stats.physicsStart;\\n\\t}\\n\\tdestroy() {\\n\\t\\tsuper.destroy();\\n\\t\\tthis.app.systems.off(\\\"update\\\", this.onUpdate, this);\\n\\t\\tif (typeof Ammo !== \\\"undefined\\\") {\\n\\t\\t\\tAmmo.destroy(this.dynamicsWorld);\\n\\t\\t\\tAmmo.destroy(this.solver);\\n\\t\\t\\tAmmo.destroy(this.overlappingPairCache);\\n\\t\\t\\tAmmo.destroy(this.dispatcher);\\n\\t\\t\\tAmmo.destroy(this.collisionConfiguration);\\n\\t\\t\\tAmmo.destroy(ammoRayStart);\\n\\t\\t\\tAmmo.destroy(ammoRayEnd);\\n\\t\\t\\tthis.dynamicsWorld = null;\\n\\t\\t\\tthis.solver = null;\\n\\t\\t\\tthis.overlappingPairCache = null;\\n\\t\\t\\tthis.dispatcher = null;\\n\\t\\t\\tthis.collisionConfiguration = null;\\n\\t\\t\\tammoRayStart = null;\\n\\t\\t\\tammoRayEnd = null;\\n\\t\\t\\tRigidBodyComponent.onAppDestroy();\\n\\t\\t}\\n\\t}\\n}\\nComponent._buildAccessors(RigidBodyComponent.prototype, _schema$3);\\n\\nclass PostEffectEntry {\\n\\tconstructor(effect, inputTarget) {\\n\\t\\tthis.effect = effect;\\n\\t\\tthis.inputTarget = inputTarget;\\n\\t\\tthis.outputTarget = null;\\n\\t\\tthis.name = effect.constructor.name;\\n\\t}\\n}\\nclass PostEffectQueue {\\n\\tconstructor(app, camera) {\\n\\t\\tthis.app = app;\\n\\t\\tthis.camera = camera;\\n\\t\\tthis.destinationRenderTarget = null;\\n\\t\\tthis.effects = [];\\n\\t\\tthis.enabled = false;\\n\\t\\tthis.depthTarget = null;\\n\\t\\tcamera.on(\\\"set:rect\\\", this.onCameraRectChanged, this);\\n\\t}\\n\\t_allocateColorBuffer(format, name) {\\n\\t\\tconst rect = this.camera.rect;\\n\\t\\tconst renderTarget = this.destinationRenderTarget;\\n\\t\\tconst device = this.app.graphicsDevice;\\n\\t\\tconst width = Math.floor(rect.z * (renderTarget?.width ?? device.width));\\n\\t\\tconst height = Math.floor(rect.w * (renderTarget?.height ?? device.height));\\n\\t\\tconst colorBuffer = Texture.createDataTexture2D(device, name, width, height, format);\\n\\t\\treturn colorBuffer;\\n\\t}\\n\\t_createOffscreenTarget(useDepth, hdr) {\\n\\t\\tconst device = this.app.graphicsDevice;\\n\\t\\tconst outputRt = this.destinationRenderTarget ?? device.backBuffer;\\n\\t\\tconst srgb = outputRt.isColorBufferSrgb(0);\\n\\t\\tconst format = (hdr && device.getRenderableHdrFormat([PIXELFORMAT_RGBA16F, PIXELFORMAT_RGBA32F], true)) ?? (srgb ? PIXELFORMAT_SRGBA8 : PIXELFORMAT_RGBA8);\\n\\t\\tconst name = `${this.camera.entity.name}-posteffect-${this.effects.length}`;\\n\\t\\tconst colorBuffer = this._allocateColorBuffer(format, name);\\n\\t\\treturn new RenderTarget({\\n\\t\\t\\tcolorBuffer,\\n\\t\\t\\tdepth: useDepth,\\n\\t\\t\\tstencil: useDepth && this.app.graphicsDevice.supportsStencil,\\n\\t\\t\\tsamples: useDepth ? device.samples : 1\\n\\t\\t});\\n\\t}\\n\\t_resizeOffscreenTarget(rt) {\\n\\t\\tconst format = rt.colorBuffer.format;\\n\\t\\tconst name = rt.colorBuffer.name;\\n\\t\\trt.destroyFrameBuffers();\\n\\t\\trt.destroyTextureBuffers();\\n\\t\\trt._colorBuffer = this._allocateColorBuffer(format, name);\\n\\t\\trt._colorBuffers = [rt._colorBuffer];\\n\\t\\trt.evaluateDimensions();\\n\\t}\\n\\t_destroyOffscreenTarget(rt) {\\n\\t\\trt.destroyTextureBuffers();\\n\\t\\trt.destroy();\\n\\t}\\n\\taddEffect(effect) {\\n\\t\\tconst effects = this.effects;\\n\\t\\tconst isFirstEffect = effects.length === 0;\\n\\t\\tconst inputTarget = this._createOffscreenTarget(isFirstEffect, effect.hdr);\\n\\t\\tconst newEntry = new PostEffectEntry(effect, inputTarget);\\n\\t\\teffects.push(newEntry);\\n\\t\\tthis._sourceTarget = newEntry.inputTarget;\\n\\t\\tif (effects.length > 1) {\\n\\t\\t\\teffects[effects.length - 2].outputTarget = newEntry.inputTarget;\\n\\t\\t}\\n\\t\\tthis._newPostEffect = effect;\\n\\t\\tif (effect.needsDepthBuffer) {\\n\\t\\t\\tthis._requestDepthMap();\\n\\t\\t}\\n\\t\\tthis.enable();\\n\\t\\tthis._newPostEffect = void 0;\\n\\t}\\n\\tremoveEffect(effect) {\\n\\t\\tlet index = -1;\\n\\t\\tfor (let i = 0, len = this.effects.length; i < len; i++) {\\n\\t\\t\\tif (this.effects[i].effect === effect) {\\n\\t\\t\\t\\tindex = i;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (index >= 0) {\\n\\t\\t\\tif (index > 0) {\\n\\t\\t\\t\\tthis.effects[index - 1].outputTarget = index + 1 < this.effects.length ? this.effects[index + 1].inputTarget : null;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (this.effects.length > 1) {\\n\\t\\t\\t\\t\\tif (!this.effects[1].inputTarget._depth) {\\n\\t\\t\\t\\t\\t\\tthis._destroyOffscreenTarget(this.effects[1].inputTarget);\\n\\t\\t\\t\\t\\t\\tthis.effects[1].inputTarget = this._createOffscreenTarget(true, this.effects[1].hdr);\\n\\t\\t\\t\\t\\t\\tthis._sourceTarget = this.effects[1].inputTarget;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tthis.camera.renderTarget = this.effects[1].inputTarget;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis._destroyOffscreenTarget(this.effects[index].inputTarget);\\n\\t\\t\\tthis.effects.splice(index, 1);\\n\\t\\t}\\n\\t\\tif (this.enabled) {\\n\\t\\t\\tif (effect.needsDepthBuffer) {\\n\\t\\t\\t\\tthis._releaseDepthMap();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this.effects.length === 0) {\\n\\t\\t\\tthis.disable();\\n\\t\\t}\\n\\t}\\n\\t_requestDepthMaps() {\\n\\t\\tfor (let i = 0, len = this.effects.length; i < len; i++) {\\n\\t\\t\\tconst effect = this.effects[i].effect;\\n\\t\\t\\tif (this._newPostEffect === effect) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tif (effect.needsDepthBuffer) {\\n\\t\\t\\t\\tthis._requestDepthMap();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_releaseDepthMaps() {\\n\\t\\tfor (let i = 0, len = this.effects.length; i < len; i++) {\\n\\t\\t\\tconst effect = this.effects[i].effect;\\n\\t\\t\\tif (effect.needsDepthBuffer) {\\n\\t\\t\\t\\tthis._releaseDepthMap();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_requestDepthMap() {\\n\\t\\tconst depthLayer = this.app.scene.layers.getLayerById(LAYERID_DEPTH);\\n\\t\\tif (depthLayer) {\\n\\t\\t\\tdepthLayer.incrementCounter();\\n\\t\\t\\tthis.camera.requestSceneDepthMap(true);\\n\\t\\t}\\n\\t}\\n\\t_releaseDepthMap() {\\n\\t\\tconst depthLayer = this.app.scene.layers.getLayerById(LAYERID_DEPTH);\\n\\t\\tif (depthLayer) {\\n\\t\\t\\tdepthLayer.decrementCounter();\\n\\t\\t\\tthis.camera.requestSceneDepthMap(false);\\n\\t\\t}\\n\\t}\\n\\tdestroy() {\\n\\t\\tfor (let i = 0, len = this.effects.length; i < len; i++) {\\n\\t\\t\\tthis.effects[i].inputTarget.destroy();\\n\\t\\t}\\n\\t\\tthis.effects.length = 0;\\n\\t\\tthis.disable();\\n\\t}\\n\\tenable() {\\n\\t\\tif (!this.enabled && this.effects.length) {\\n\\t\\t\\tthis.enabled = true;\\n\\t\\t\\tthis._requestDepthMaps();\\n\\t\\t\\tthis.app.graphicsDevice.on(\\\"resizecanvas\\\", this._onCanvasResized, this);\\n\\t\\t\\tthis.destinationRenderTarget = this.camera.renderTarget;\\n\\t\\t\\tthis.camera.renderTarget = this.effects[0].inputTarget;\\n\\t\\t\\tthis.camera.onPostprocessing = () => {\\n\\t\\t\\t\\tif (this.enabled) {\\n\\t\\t\\t\\t\\tlet rect = null;\\n\\t\\t\\t\\t\\tconst len = this.effects.length;\\n\\t\\t\\t\\t\\tif (len) {\\n\\t\\t\\t\\t\\t\\tfor (let i = 0; i < len; i++) {\\n\\t\\t\\t\\t\\t\\t\\tconst fx = this.effects[i];\\n\\t\\t\\t\\t\\t\\t\\tlet destTarget = fx.outputTarget;\\n\\t\\t\\t\\t\\t\\t\\tif (i === len - 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\trect = this.camera.rect;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.destinationRenderTarget) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tdestTarget = this.destinationRenderTarget;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\tfx.effect.render(fx.inputTarget, destTarget, rect);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t};\\n\\t\\t}\\n\\t}\\n\\tdisable() {\\n\\t\\tif (this.enabled) {\\n\\t\\t\\tthis.enabled = false;\\n\\t\\t\\tthis.app.graphicsDevice.off(\\\"resizecanvas\\\", this._onCanvasResized, this);\\n\\t\\t\\tthis._releaseDepthMaps();\\n\\t\\t\\tthis._destroyOffscreenTarget(this._sourceTarget);\\n\\t\\t\\tthis.camera.renderTarget = this.destinationRenderTarget;\\n\\t\\t\\tthis.camera.onPostprocessing = null;\\n\\t\\t}\\n\\t}\\n\\t_onCanvasResized(width, height) {\\n\\t\\tconst rect = this.camera.rect;\\n\\t\\tconst renderTarget = this.destinationRenderTarget;\\n\\t\\twidth = renderTarget?.width ?? width;\\n\\t\\theight = renderTarget?.height ?? height;\\n\\t\\tthis.camera.camera.aspectRatio = width * rect.z / (height * rect.w);\\n\\t\\tthis.resizeRenderTargets();\\n\\t}\\n\\tresizeRenderTargets() {\\n\\t\\tconst device = this.app.graphicsDevice;\\n\\t\\tconst renderTarget = this.destinationRenderTarget;\\n\\t\\tconst width = renderTarget?.width ?? device.width;\\n\\t\\tconst height = renderTarget?.height ?? device.height;\\n\\t\\tconst rect = this.camera.rect;\\n\\t\\tconst desiredWidth = Math.floor(rect.z * width);\\n\\t\\tconst desiredHeight = Math.floor(rect.w * height);\\n\\t\\tconst effects = this.effects;\\n\\t\\tfor (let i = 0, len = effects.length; i < len; i++) {\\n\\t\\t\\tconst fx = effects[i];\\n\\t\\t\\tif (fx.inputTarget.width !== desiredWidth || fx.inputTarget.height !== desiredHeight) {\\n\\t\\t\\t\\tthis._resizeOffscreenTarget(fx.inputTarget);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tonCameraRectChanged(name, oldValue, newValue) {\\n\\t\\tif (this.enabled) {\\n\\t\\t\\tthis.resizeRenderTargets();\\n\\t\\t}\\n\\t}\\n}\\n\\nclass CameraComponent extends Component {\\n\\tonPostprocessing = null;\\n\\t_renderSceneDepthMap = 0;\\n\\t_renderSceneColorMap = 0;\\n\\t_sceneDepthMapRequested = false;\\n\\t_sceneColorMapRequested = false;\\n\\t_priority = 0;\\n\\t_disablePostEffectsLayer = LAYERID_UI;\\n\\t_camera;\\n\\t_evtLayersChanged = null;\\n\\t_evtLayerAdded = null;\\n\\t_evtLayerRemoved = null;\\n\\tconstructor(system, entity) {\\n\\t\\tsuper(system, entity);\\n\\t\\tthis._camera = new Camera$1(system.app.graphicsDevice);\\n\\t\\tthis._camera.node = entity;\\n\\t\\tthis._postEffects = new PostEffectQueue(system.app, this);\\n\\t}\\n\\tsetShaderPass(name) {\\n\\t\\tconst shaderPass = ShaderPass.get(this.system.app.graphicsDevice);\\n\\t\\tconst shaderPassInfo = name ? shaderPass.allocate(name, {\\n\\t\\t\\tisForward: true\\n\\t\\t}) : null;\\n\\t\\tthis._camera.shaderPassInfo = shaderPassInfo;\\n\\t\\treturn shaderPassInfo.index;\\n\\t}\\n\\tgetShaderPass() {\\n\\t\\treturn this._camera.shaderPassInfo?.name;\\n\\t}\\n\\tset framePasses(passes) {\\n\\t\\tthis._camera.framePasses = passes || [];\\n\\t\\tthis.dirtyLayerCompositionCameras();\\n\\t\\tthis.system.app.scene.updateShaders = true;\\n\\t}\\n\\tget framePasses() {\\n\\t\\treturn this._camera.framePasses;\\n\\t}\\n\\tset renderPasses(passes) {\\n\\t\\tthis.framePasses = passes;\\n\\t}\\n\\tget renderPasses() {\\n\\t\\treturn this.framePasses;\\n\\t}\\n\\tget shaderParams() {\\n\\t\\treturn this._camera.shaderParams;\\n\\t}\\n\\tset gammaCorrection(value) {\\n\\t\\tthis.camera.shaderParams.gammaCorrection = value;\\n\\t}\\n\\tget gammaCorrection() {\\n\\t\\treturn this.camera.shaderParams.gammaCorrection;\\n\\t}\\n\\tset toneMapping(value) {\\n\\t\\tthis.camera.shaderParams.toneMapping = value;\\n\\t}\\n\\tget toneMapping() {\\n\\t\\treturn this.camera.shaderParams.toneMapping;\\n\\t}\\n\\tset fog(value) {\\n\\t\\tthis._camera.fogParams = value;\\n\\t}\\n\\tget fog() {\\n\\t\\treturn this._camera.fogParams;\\n\\t}\\n\\tset aperture(value) {\\n\\t\\tthis._camera.aperture = value;\\n\\t}\\n\\tget aperture() {\\n\\t\\treturn this._camera.aperture;\\n\\t}\\n\\tset aspectRatio(value) {\\n\\t\\tthis._camera.aspectRatio = value;\\n\\t}\\n\\tget aspectRatio() {\\n\\t\\treturn this._camera.aspectRatio;\\n\\t}\\n\\tset aspectRatioMode(value) {\\n\\t\\tthis._camera.aspectRatioMode = value;\\n\\t}\\n\\tget aspectRatioMode() {\\n\\t\\treturn this._camera.aspectRatioMode;\\n\\t}\\n\\tset calculateProjection(value) {\\n\\t\\tthis._camera.calculateProjection = value;\\n\\t}\\n\\tget calculateProjection() {\\n\\t\\treturn this._camera.calculateProjection;\\n\\t}\\n\\tset calculateTransform(value) {\\n\\t\\tthis._camera.calculateTransform = value;\\n\\t}\\n\\tget calculateTransform() {\\n\\t\\treturn this._camera.calculateTransform;\\n\\t}\\n\\tget camera() {\\n\\t\\treturn this._camera;\\n\\t}\\n\\tset clearColor(value) {\\n\\t\\tthis._camera.clearColor = value;\\n\\t}\\n\\tget clearColor() {\\n\\t\\treturn this._camera.clearColor;\\n\\t}\\n\\tset clearColorBuffer(value) {\\n\\t\\tthis._camera.clearColorBuffer = value;\\n\\t\\tthis.dirtyLayerCompositionCameras();\\n\\t}\\n\\tget clearColorBuffer() {\\n\\t\\treturn this._camera.clearColorBuffer;\\n\\t}\\n\\tset clearDepth(value) {\\n\\t\\tthis._camera.clearDepth = value;\\n\\t}\\n\\tget clearDepth() {\\n\\t\\treturn this._camera.clearDepth;\\n\\t}\\n\\tset clearDepthBuffer(value) {\\n\\t\\tthis._camera.clearDepthBuffer = value;\\n\\t\\tthis.dirtyLayerCompositionCameras();\\n\\t}\\n\\tget clearDepthBuffer() {\\n\\t\\treturn this._camera.clearDepthBuffer;\\n\\t}\\n\\tset clearStencilBuffer(value) {\\n\\t\\tthis._camera.clearStencilBuffer = value;\\n\\t\\tthis.dirtyLayerCompositionCameras();\\n\\t}\\n\\tget clearStencilBuffer() {\\n\\t\\treturn this._camera.clearStencilBuffer;\\n\\t}\\n\\tset cullFaces(value) {\\n\\t\\tthis._camera.cullFaces = value;\\n\\t}\\n\\tget cullFaces() {\\n\\t\\treturn this._camera.cullFaces;\\n\\t}\\n\\tset disablePostEffectsLayer(layer) {\\n\\t\\tthis._disablePostEffectsLayer = layer;\\n\\t\\tthis.dirtyLayerCompositionCameras();\\n\\t}\\n\\tget disablePostEffectsLayer() {\\n\\t\\treturn this._disablePostEffectsLayer;\\n\\t}\\n\\tset farClip(value) {\\n\\t\\tthis._camera.farClip = value;\\n\\t}\\n\\tget farClip() {\\n\\t\\treturn this._camera.farClip;\\n\\t}\\n\\tset flipFaces(value) {\\n\\t\\tthis._camera.flipFaces = value;\\n\\t}\\n\\tget flipFaces() {\\n\\t\\treturn this._camera.flipFaces;\\n\\t}\\n\\tset fov(value) {\\n\\t\\tthis._camera.fov = value;\\n\\t}\\n\\tget fov() {\\n\\t\\treturn this._camera.fov;\\n\\t}\\n\\tget frustum() {\\n\\t\\treturn this._camera.frustum;\\n\\t}\\n\\tset frustumCulling(value) {\\n\\t\\tthis._camera.frustumCulling = value;\\n\\t}\\n\\tget frustumCulling() {\\n\\t\\treturn this._camera.frustumCulling;\\n\\t}\\n\\tset horizontalFov(value) {\\n\\t\\tthis._camera.horizontalFov = value;\\n\\t}\\n\\tget horizontalFov() {\\n\\t\\treturn this._camera.horizontalFov;\\n\\t}\\n\\tset layers(newValue) {\\n\\t\\tconst oldLayers = this._camera.layers;\\n\\t\\tconst scene = this.system.app.scene;\\n\\t\\toldLayers.forEach((layerId) => {\\n\\t\\t\\tconst layer = scene.layers.getLayerById(layerId);\\n\\t\\t\\tlayer?.removeCamera(this);\\n\\t\\t});\\n\\t\\tthis._camera.layers = newValue;\\n\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\tnewValue.forEach((layerId) => {\\n\\t\\t\\t\\tconst layer = scene.layers.getLayerById(layerId);\\n\\t\\t\\t\\tlayer?.addCamera(this);\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tthis.fire(\\\"set:layers\\\");\\n\\t}\\n\\tget layers() {\\n\\t\\treturn this._camera.layers;\\n\\t}\\n\\tget layersSet() {\\n\\t\\treturn this._camera.layersSet;\\n\\t}\\n\\tset jitter(value) {\\n\\t\\tthis._camera.jitter = value;\\n\\t}\\n\\tget jitter() {\\n\\t\\treturn this._camera.jitter;\\n\\t}\\n\\tset nearClip(value) {\\n\\t\\tthis._camera.nearClip = value;\\n\\t}\\n\\tget nearClip() {\\n\\t\\treturn this._camera.nearClip;\\n\\t}\\n\\tset orthoHeight(value) {\\n\\t\\tthis._camera.orthoHeight = value;\\n\\t}\\n\\tget orthoHeight() {\\n\\t\\treturn this._camera.orthoHeight;\\n\\t}\\n\\tget postEffects() {\\n\\t\\treturn this._postEffects;\\n\\t}\\n\\tget postEffectsEnabled() {\\n\\t\\treturn this._postEffects.enabled;\\n\\t}\\n\\tset priority(newValue) {\\n\\t\\tthis._priority = newValue;\\n\\t\\tthis.dirtyLayerCompositionCameras();\\n\\t}\\n\\tget priority() {\\n\\t\\treturn this._priority;\\n\\t}\\n\\tset projection(value) {\\n\\t\\tthis._camera.projection = value;\\n\\t}\\n\\tget projection() {\\n\\t\\treturn this._camera.projection;\\n\\t}\\n\\tget projectionMatrix() {\\n\\t\\treturn this._camera.projectionMatrix;\\n\\t}\\n\\tset rect(value) {\\n\\t\\tthis._camera.rect = value;\\n\\t\\tthis.fire(\\\"set:rect\\\", this._camera.rect);\\n\\t}\\n\\tget rect() {\\n\\t\\treturn this._camera.rect;\\n\\t}\\n\\tset renderSceneColorMap(value) {\\n\\t\\tif (value && !this._sceneColorMapRequested) {\\n\\t\\t\\tthis.requestSceneColorMap(true);\\n\\t\\t\\tthis._sceneColorMapRequested = true;\\n\\t\\t} else if (!value && this._sceneColorMapRequested) {\\n\\t\\t\\tthis.requestSceneColorMap(false);\\n\\t\\t\\tthis._sceneColorMapRequested = false;\\n\\t\\t}\\n\\t}\\n\\tget renderSceneColorMap() {\\n\\t\\treturn this._renderSceneColorMap > 0;\\n\\t}\\n\\tset renderSceneDepthMap(value) {\\n\\t\\tif (value && !this._sceneDepthMapRequested) {\\n\\t\\t\\tthis.requestSceneDepthMap(true);\\n\\t\\t\\tthis._sceneDepthMapRequested = true;\\n\\t\\t} else if (!value && this._sceneDepthMapRequested) {\\n\\t\\t\\tthis.requestSceneDepthMap(false);\\n\\t\\t\\tthis._sceneDepthMapRequested = false;\\n\\t\\t}\\n\\t}\\n\\tget renderSceneDepthMap() {\\n\\t\\treturn this._renderSceneDepthMap > 0;\\n\\t}\\n\\tset renderTarget(value) {\\n\\t\\tthis._camera.renderTarget = value;\\n\\t\\tthis.dirtyLayerCompositionCameras();\\n\\t}\\n\\tget renderTarget() {\\n\\t\\treturn this._camera.renderTarget;\\n\\t}\\n\\tset scissorRect(value) {\\n\\t\\tthis._camera.scissorRect = value;\\n\\t}\\n\\tget scissorRect() {\\n\\t\\treturn this._camera.scissorRect;\\n\\t}\\n\\tset sensitivity(value) {\\n\\t\\tthis._camera.sensitivity = value;\\n\\t}\\n\\tget sensitivity() {\\n\\t\\treturn this._camera.sensitivity;\\n\\t}\\n\\tset shutter(value) {\\n\\t\\tthis._camera.shutter = value;\\n\\t}\\n\\tget shutter() {\\n\\t\\treturn this._camera.shutter;\\n\\t}\\n\\tget viewMatrix() {\\n\\t\\treturn this._camera.viewMatrix;\\n\\t}\\n\\t_enableDepthLayer(value) {\\n\\t\\tconst hasDepthLayer = this.layers.find((layerId) => layerId === LAYERID_DEPTH);\\n\\t\\tif (hasDepthLayer) {\\n\\t\\t\\tconst depthLayer = this.system.app.scene.layers.getLayerById(LAYERID_DEPTH);\\n\\t\\t\\tif (value) {\\n\\t\\t\\t\\tdepthLayer?.incrementCounter();\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tdepthLayer?.decrementCounter();\\n\\t\\t\\t}\\n\\t\\t} else if (value) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\treturn true;\\n\\t}\\n\\trequestSceneColorMap(enabled) {\\n\\t\\tthis._renderSceneColorMap += enabled ? 1 : -1;\\n\\t\\tthis._enableDepthLayer(enabled);\\n\\t\\tthis.camera._enableRenderPassColorGrab(this.system.app.graphicsDevice, this.renderSceneColorMap);\\n\\t\\tthis.system.app.scene.layers.markDirty();\\n\\t}\\n\\trequestSceneDepthMap(enabled) {\\n\\t\\tthis._renderSceneDepthMap += enabled ? 1 : -1;\\n\\t\\tthis._enableDepthLayer(enabled);\\n\\t\\tthis.camera._enableRenderPassDepthGrab(this.system.app.graphicsDevice, this.system.app.renderer, this.renderSceneDepthMap);\\n\\t\\tthis.system.app.scene.layers.markDirty();\\n\\t}\\n\\tdirtyLayerCompositionCameras() {\\n\\t\\tconst layerComp = this.system.app.scene.layers;\\n\\t\\tlayerComp._dirty = true;\\n\\t}\\n\\tscreenToWorld(screenx, screeny, cameraz, worldCoord) {\\n\\t\\tconst device = this.system.app.graphicsDevice;\\n\\t\\tconst { width, height } = device.clientRect;\\n\\t\\treturn this._camera.screenToWorld(screenx, screeny, cameraz, width, height, worldCoord);\\n\\t}\\n\\tworldToScreen(worldCoord, screenCoord) {\\n\\t\\tconst device = this.system.app.graphicsDevice;\\n\\t\\tconst { width, height } = device.clientRect;\\n\\t\\treturn this._camera.worldToScreen(worldCoord, width, height, screenCoord);\\n\\t}\\n\\tonAppPrerender() {\\n\\t\\tthis._camera._viewMatDirty = true;\\n\\t\\tthis._camera._viewProjMatDirty = true;\\n\\t}\\n\\taddCameraToLayers() {\\n\\t\\tconst layers = this.layers;\\n\\t\\tfor (let i = 0; i < layers.length; i++) {\\n\\t\\t\\tconst layer = this.system.app.scene.layers.getLayerById(layers[i]);\\n\\t\\t\\tif (layer) {\\n\\t\\t\\t\\tlayer.addCamera(this);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tremoveCameraFromLayers() {\\n\\t\\tconst layers = this.layers;\\n\\t\\tfor (let i = 0; i < layers.length; i++) {\\n\\t\\t\\tconst layer = this.system.app.scene.layers.getLayerById(layers[i]);\\n\\t\\t\\tif (layer) {\\n\\t\\t\\t\\tlayer.removeCamera(this);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tonLayersChanged(oldComp, newComp) {\\n\\t\\tthis.addCameraToLayers();\\n\\t\\toldComp.off(\\\"add\\\", this.onLayerAdded, this);\\n\\t\\toldComp.off(\\\"remove\\\", this.onLayerRemoved, this);\\n\\t\\tnewComp.on(\\\"add\\\", this.onLayerAdded, this);\\n\\t\\tnewComp.on(\\\"remove\\\", this.onLayerRemoved, this);\\n\\t}\\n\\tonLayerAdded(layer) {\\n\\t\\tconst index = this.layers.indexOf(layer.id);\\n\\t\\tif (index < 0) return;\\n\\t\\tlayer.addCamera(this);\\n\\t}\\n\\tonLayerRemoved(layer) {\\n\\t\\tconst index = this.layers.indexOf(layer.id);\\n\\t\\tif (index < 0) return;\\n\\t\\tlayer.removeCamera(this);\\n\\t}\\n\\tonEnable() {\\n\\t\\tconst scene = this.system.app.scene;\\n\\t\\tconst layers = scene.layers;\\n\\t\\tthis.system.addCamera(this);\\n\\t\\tthis._evtLayersChanged?.off();\\n\\t\\tthis._evtLayersChanged = scene.on(\\\"set:layers\\\", this.onLayersChanged, this);\\n\\t\\tif (layers) {\\n\\t\\t\\tthis._evtLayerAdded?.off();\\n\\t\\t\\tthis._evtLayerAdded = layers.on(\\\"add\\\", this.onLayerAdded, this);\\n\\t\\t\\tthis._evtLayerRemoved?.off();\\n\\t\\t\\tthis._evtLayerRemoved = layers.on(\\\"remove\\\", this.onLayerRemoved, this);\\n\\t\\t}\\n\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\tthis.addCameraToLayers();\\n\\t\\t}\\n\\t\\tthis.postEffects.enable();\\n\\t}\\n\\tonDisable() {\\n\\t\\tconst scene = this.system.app.scene;\\n\\t\\tconst layers = scene.layers;\\n\\t\\tthis.postEffects.disable();\\n\\t\\tthis.removeCameraFromLayers();\\n\\t\\tthis._evtLayersChanged?.off();\\n\\t\\tthis._evtLayersChanged = null;\\n\\t\\tif (layers) {\\n\\t\\t\\tthis._evtLayerAdded?.off();\\n\\t\\t\\tthis._evtLayerAdded = null;\\n\\t\\t\\tthis._evtLayerRemoved?.off();\\n\\t\\t\\tthis._evtLayerRemoved = null;\\n\\t\\t}\\n\\t\\tthis.system.removeCamera(this);\\n\\t}\\n\\tonRemove() {\\n\\t\\tthis.onDisable();\\n\\t\\tthis.off();\\n\\t\\tthis.camera.destroy();\\n\\t}\\n\\tcalculateAspectRatio(rt) {\\n\\t\\treturn this._camera.calculateAspectRatio(rt);\\n\\t}\\n\\tframeUpdate(rt) {\\n\\t\\tif (this.aspectRatioMode === ASPECT_AUTO) {\\n\\t\\t\\tthis.aspectRatio = this.calculateAspectRatio(rt);\\n\\t\\t}\\n\\t}\\n\\tstartXr(type, spaceType, options) {\\n\\t\\tthis.system.app.xr.start(this, type, spaceType, options);\\n\\t}\\n\\tendXr(callback) {\\n\\t\\tif (!this._camera.xr) {\\n\\t\\t\\tif (callback) callback(new Error(\\\"Camera is not in XR\\\"));\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._camera.xr.end(callback);\\n\\t}\\n\\tcopy(source) {\\n\\t\\tthis.aperture = source.aperture;\\n\\t\\tthis.aspectRatio = source.aspectRatio;\\n\\t\\tthis.aspectRatioMode = source.aspectRatioMode;\\n\\t\\tthis.calculateProjection = source.calculateProjection;\\n\\t\\tthis.calculateTransform = source.calculateTransform;\\n\\t\\tthis.clearColor = source.clearColor;\\n\\t\\tthis.clearColorBuffer = source.clearColorBuffer;\\n\\t\\tthis.clearDepthBuffer = source.clearDepthBuffer;\\n\\t\\tthis.clearStencilBuffer = source.clearStencilBuffer;\\n\\t\\tthis.cullFaces = source.cullFaces;\\n\\t\\tthis.disablePostEffectsLayer = source.disablePostEffectsLayer;\\n\\t\\tthis.farClip = source.farClip;\\n\\t\\tthis.flipFaces = source.flipFaces;\\n\\t\\tthis.fov = source.fov;\\n\\t\\tthis.frustumCulling = source.frustumCulling;\\n\\t\\tthis.horizontalFov = source.horizontalFov;\\n\\t\\tthis.layers = source.layers;\\n\\t\\tthis.nearClip = source.nearClip;\\n\\t\\tthis.orthoHeight = source.orthoHeight;\\n\\t\\tthis.priority = source.priority;\\n\\t\\tthis.projection = source.projection;\\n\\t\\tthis.rect = source.rect;\\n\\t\\tthis.renderTarget = source.renderTarget;\\n\\t\\tthis.scissorRect = source.scissorRect;\\n\\t\\tthis.sensitivity = source.sensitivity;\\n\\t\\tthis.shutter = source.shutter;\\n\\t}\\n}\\n\\nclass CameraComponentData {\\n\\tenabled = true;\\n}\\n\\nconst _schema$2 = [\\\"enabled\\\"];\\nclass CameraComponentSystem extends ComponentSystem {\\n\\tcameras = [];\\n\\tconstructor(app) {\\n\\t\\tsuper(app);\\n\\t\\tthis.id = \\\"camera\\\";\\n\\t\\tthis.ComponentType = CameraComponent;\\n\\t\\tthis.DataType = CameraComponentData;\\n\\t\\tthis.schema = _schema$2;\\n\\t\\tthis.on(\\\"beforeremove\\\", this.onBeforeRemove, this);\\n\\t\\tthis.app.on(\\\"prerender\\\", this.onAppPrerender, this);\\n\\t}\\n\\tinitializeComponentData(component, data, properties) {\\n\\t\\tproperties = [\\n\\t\\t\\t\\\"aspectRatio\\\",\\n\\t\\t\\t\\\"aspectRatioMode\\\",\\n\\t\\t\\t\\\"calculateProjection\\\",\\n\\t\\t\\t\\\"calculateTransform\\\",\\n\\t\\t\\t\\\"clearColor\\\",\\n\\t\\t\\t\\\"clearColorBuffer\\\",\\n\\t\\t\\t\\\"clearDepth\\\",\\n\\t\\t\\t\\\"clearDepthBuffer\\\",\\n\\t\\t\\t\\\"clearStencilBuffer\\\",\\n\\t\\t\\t\\\"renderSceneColorMap\\\",\\n\\t\\t\\t\\\"renderSceneDepthMap\\\",\\n\\t\\t\\t\\\"cullFaces\\\",\\n\\t\\t\\t\\\"farClip\\\",\\n\\t\\t\\t\\\"flipFaces\\\",\\n\\t\\t\\t\\\"fog\\\",\\n\\t\\t\\t\\\"fov\\\",\\n\\t\\t\\t\\\"frustumCulling\\\",\\n\\t\\t\\t\\\"horizontalFov\\\",\\n\\t\\t\\t\\\"layers\\\",\\n\\t\\t\\t\\\"renderTarget\\\",\\n\\t\\t\\t\\\"nearClip\\\",\\n\\t\\t\\t\\\"orthoHeight\\\",\\n\\t\\t\\t\\\"projection\\\",\\n\\t\\t\\t\\\"priority\\\",\\n\\t\\t\\t\\\"rect\\\",\\n\\t\\t\\t\\\"scissorRect\\\",\\n\\t\\t\\t\\\"aperture\\\",\\n\\t\\t\\t\\\"shutter\\\",\\n\\t\\t\\t\\\"sensitivity\\\",\\n\\t\\t\\t\\\"gammaCorrection\\\",\\n\\t\\t\\t\\\"toneMapping\\\"\\n\\t\\t];\\n\\t\\tfor (let i = 0; i < properties.length; i++) {\\n\\t\\t\\tconst property = properties[i];\\n\\t\\t\\tif (data.hasOwnProperty(property)) {\\n\\t\\t\\t\\tconst value = data[property];\\n\\t\\t\\t\\tswitch (property) {\\n\\t\\t\\t\\t\\tcase \\\"rect\\\":\\n\\t\\t\\t\\t\\tcase \\\"scissorRect\\\":\\n\\t\\t\\t\\t\\t\\tif (Array.isArray(value)) {\\n\\t\\t\\t\\t\\t\\t\\tcomponent[property] = new Vec4(value[0], value[1], value[2], value[3]);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tcomponent[property] = value;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\tcase \\\"clearColor\\\":\\n\\t\\t\\t\\t\\t\\tif (Array.isArray(value)) {\\n\\t\\t\\t\\t\\t\\t\\tcomponent[property] = new Color(value[0], value[1], value[2], value[3]);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tcomponent[property] = value;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\tcomponent[property] = value;\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsuper.initializeComponentData(component, data, [\\\"enabled\\\"]);\\n\\t}\\n\\tcloneComponent(entity, clone) {\\n\\t\\tconst c = entity.camera;\\n\\t\\treturn this.addComponent(clone, {\\n\\t\\t\\taspectRatio: c.aspectRatio,\\n\\t\\t\\taspectRatioMode: c.aspectRatioMode,\\n\\t\\t\\tcalculateProjection: c.calculateProjection,\\n\\t\\t\\tcalculateTransform: c.calculateTransform,\\n\\t\\t\\tclearColor: c.clearColor,\\n\\t\\t\\tclearColorBuffer: c.clearColorBuffer,\\n\\t\\t\\tclearDepthBuffer: c.clearDepthBuffer,\\n\\t\\t\\tclearStencilBuffer: c.clearStencilBuffer,\\n\\t\\t\\trenderSceneDepthMap: c.renderSceneDepthMap,\\n\\t\\t\\trenderSceneColorMap: c.renderSceneColorMap,\\n\\t\\t\\tcullFaces: c.cullFaces,\\n\\t\\t\\tenabled: c.enabled,\\n\\t\\t\\tfarClip: c.farClip,\\n\\t\\t\\tflipFaces: c.flipFaces,\\n\\t\\t\\tfov: c.fov,\\n\\t\\t\\tfrustumCulling: c.frustumCulling,\\n\\t\\t\\thorizontalFov: c.horizontalFov,\\n\\t\\t\\tlayers: c.layers,\\n\\t\\t\\trenderTarget: c.renderTarget,\\n\\t\\t\\tnearClip: c.nearClip,\\n\\t\\t\\torthoHeight: c.orthoHeight,\\n\\t\\t\\tprojection: c.projection,\\n\\t\\t\\tpriority: c.priority,\\n\\t\\t\\trect: c.rect,\\n\\t\\t\\tscissorRect: c.scissorRect,\\n\\t\\t\\taperture: c.aperture,\\n\\t\\t\\tsensitivity: c.sensitivity,\\n\\t\\t\\tshutter: c.shutter,\\n\\t\\t\\tgammaCorrection: c.gammaCorrection,\\n\\t\\t\\ttoneMapping: c.toneMapping\\n\\t\\t});\\n\\t}\\n\\tonBeforeRemove(entity, component) {\\n\\t\\tthis.removeCamera(component);\\n\\t\\tcomponent.onRemove();\\n\\t}\\n\\tonAppPrerender() {\\n\\t\\tfor (let i = 0, len = this.cameras.length; i < len; i++) {\\n\\t\\t\\tthis.cameras[i].onAppPrerender();\\n\\t\\t}\\n\\t}\\n\\taddCamera(camera) {\\n\\t\\tthis.cameras.push(camera);\\n\\t\\tsortPriority(this.cameras);\\n\\t}\\n\\tremoveCamera(camera) {\\n\\t\\tconst index = this.cameras.indexOf(camera);\\n\\t\\tif (index >= 0) {\\n\\t\\t\\tthis.cameras.splice(index, 1);\\n\\t\\t\\tsortPriority(this.cameras);\\n\\t\\t}\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.app.off(\\\"prerender\\\", this.onAppPrerender, this);\\n\\t\\tsuper.destroy();\\n\\t}\\n}\\nComponent._buildAccessors(CameraComponent.prototype, _schema$2);\\n\\nconst _properties$1 = [\\n\\t\\\"type\\\",\\n\\t\\\"color\\\",\\n\\t\\\"intensity\\\",\\n\\t\\\"luminance\\\",\\n\\t\\\"shape\\\",\\n\\t\\\"affectSpecularity\\\",\\n\\t\\\"castShadows\\\",\\n\\t\\\"shadowDistance\\\",\\n\\t\\\"shadowIntensity\\\",\\n\\t\\\"shadowResolution\\\",\\n\\t\\\"shadowBias\\\",\\n\\t\\\"numCascades\\\",\\n\\t\\\"cascadeBlend\\\",\\n\\t\\\"bakeNumSamples\\\",\\n\\t\\\"bakeArea\\\",\\n\\t\\\"cascadeDistribution\\\",\\n\\t\\\"normalOffsetBias\\\",\\n\\t\\\"range\\\",\\n\\t\\\"innerConeAngle\\\",\\n\\t\\\"outerConeAngle\\\",\\n\\t\\\"falloffMode\\\",\\n\\t\\\"shadowType\\\",\\n\\t\\\"vsmBlurSize\\\",\\n\\t\\\"vsmBlurMode\\\",\\n\\t\\\"vsmBias\\\",\\n\\t\\\"cookieAsset\\\",\\n\\t\\\"cookie\\\",\\n\\t\\\"cookieIntensity\\\",\\n\\t\\\"cookieFalloff\\\",\\n\\t\\\"cookieChannel\\\",\\n\\t\\\"cookieAngle\\\",\\n\\t\\\"cookieScale\\\",\\n\\t\\\"cookieOffset\\\",\\n\\t\\\"shadowUpdateMode\\\",\\n\\t\\\"mask\\\",\\n\\t\\\"affectDynamic\\\",\\n\\t\\\"affectLightmapped\\\",\\n\\t\\\"bake\\\",\\n\\t\\\"bakeDir\\\",\\n\\t\\\"isStatic\\\",\\n\\t\\\"layers\\\",\\n\\t\\\"penumbraSize\\\",\\n\\t\\\"penumbraFalloff\\\",\\n\\t\\\"shadowSamples\\\",\\n\\t\\\"shadowBlockerSamples\\\"\\n];\\nclass LightComponent extends Component {\\n\\t_light;\\n\\t_evtLayersChanged = null;\\n\\t_evtLayerAdded = null;\\n\\t_evtLayerRemoved = null;\\n\\t_cookieAsset = null;\\n\\t_cookieAssetId = null;\\n\\t_cookieAssetAdd = false;\\n\\t_cookieMatrix = null;\\n\\t_shadowBias = 0.05;\\n\\t_cookieAngle = 0;\\n\\t_cookieScale = null;\\n\\t_castShadows = false;\\n\\t_affectSpecularity = true;\\n\\t_affectDynamic = true;\\n\\t_affectLightmapped = false;\\n\\t_bake = false;\\n\\t_layers = [LAYERID_WORLD];\\n\\t_type = \\\"directional\\\";\\n\\tconstructor(system, entity) {\\n\\t\\tsuper(system, entity);\\n\\t\\tthis._light = new Light(system.app.graphicsDevice, system.app.scene.clusteredLightingEnabled);\\n\\t\\tthis._light._node = entity;\\n\\t\\tthis._light.setColor(1, 1, 1);\\n\\t}\\n\\tget light() {\\n\\t\\treturn this._light;\\n\\t}\\n\\tset type(value) {\\n\\t\\tif (this._type === value) return;\\n\\t\\tthis.removeLightFromLayers();\\n\\t\\tthis._type = value;\\n\\t\\tthis._light.type = lightTypes[value];\\n\\t\\tthis.refreshProperties();\\n\\t}\\n\\tget type() {\\n\\t\\treturn this._type;\\n\\t}\\n\\tset color(value) {\\n\\t\\tthis._light.setColor(value);\\n\\t}\\n\\tget color() {\\n\\t\\treturn this._light.getColor();\\n\\t}\\n\\tset intensity(value) {\\n\\t\\tthis._light.intensity = value;\\n\\t}\\n\\tget intensity() {\\n\\t\\treturn this._light.intensity;\\n\\t}\\n\\tset luminance(value) {\\n\\t\\tthis._light.luminance = value;\\n\\t}\\n\\tget luminance() {\\n\\t\\treturn this._light.luminance;\\n\\t}\\n\\tset shape(value) {\\n\\t\\tthis._light.shape = value;\\n\\t}\\n\\tget shape() {\\n\\t\\treturn this._light.shape;\\n\\t}\\n\\tset affectSpecularity(value) {\\n\\t\\tthis._affectSpecularity = value;\\n\\t\\tthis._light.affectSpecularity = value;\\n\\t}\\n\\tget affectSpecularity() {\\n\\t\\treturn this._affectSpecularity;\\n\\t}\\n\\tset castShadows(value) {\\n\\t\\tthis._castShadows = value;\\n\\t\\tthis._light.castShadows = value;\\n\\t}\\n\\tget castShadows() {\\n\\t\\treturn this._castShadows;\\n\\t}\\n\\tset shadowDistance(value) {\\n\\t\\tthis._light.shadowDistance = value;\\n\\t}\\n\\tget shadowDistance() {\\n\\t\\treturn this._light.shadowDistance;\\n\\t}\\n\\tset shadowIntensity(value) {\\n\\t\\tthis._light.shadowIntensity = value;\\n\\t}\\n\\tget shadowIntensity() {\\n\\t\\treturn this._light.shadowIntensity;\\n\\t}\\n\\tset shadowResolution(value) {\\n\\t\\tthis._light.shadowResolution = value;\\n\\t}\\n\\tget shadowResolution() {\\n\\t\\treturn this._light.shadowResolution;\\n\\t}\\n\\tset shadowBias(value) {\\n\\t\\tthis._shadowBias = value;\\n\\t\\tthis._light.shadowBias = -0.01 * math.clamp(value, 0, 1);\\n\\t}\\n\\tget shadowBias() {\\n\\t\\treturn this._shadowBias;\\n\\t}\\n\\tset numCascades(value) {\\n\\t\\tthis._light.numCascades = math.clamp(Math.floor(value), 1, 4);\\n\\t}\\n\\tget numCascades() {\\n\\t\\treturn this._light.numCascades;\\n\\t}\\n\\tset cascadeBlend(value) {\\n\\t\\tthis._light.cascadeBlend = math.clamp(value, 0, 1);\\n\\t}\\n\\tget cascadeBlend() {\\n\\t\\treturn this._light.cascadeBlend;\\n\\t}\\n\\tset bakeNumSamples(value) {\\n\\t\\tthis._light.bakeNumSamples = math.clamp(Math.floor(value), 1, 255);\\n\\t}\\n\\tget bakeNumSamples() {\\n\\t\\treturn this._light.bakeNumSamples;\\n\\t}\\n\\tset bakeArea(value) {\\n\\t\\tthis._light.bakeArea = math.clamp(value, 0, 180);\\n\\t}\\n\\tget bakeArea() {\\n\\t\\treturn this._light.bakeArea;\\n\\t}\\n\\tset cascadeDistribution(value) {\\n\\t\\tthis._light.cascadeDistribution = math.clamp(value, 0, 1);\\n\\t}\\n\\tget cascadeDistribution() {\\n\\t\\treturn this._light.cascadeDistribution;\\n\\t}\\n\\tset normalOffsetBias(value) {\\n\\t\\tthis._light.normalOffsetBias = math.clamp(value, 0, 1);\\n\\t}\\n\\tget normalOffsetBias() {\\n\\t\\treturn this._light.normalOffsetBias;\\n\\t}\\n\\tset range(value) {\\n\\t\\tthis._light.attenuationEnd = value;\\n\\t}\\n\\tget range() {\\n\\t\\treturn this._light.attenuationEnd;\\n\\t}\\n\\tset innerConeAngle(value) {\\n\\t\\tthis._light.innerConeAngle = value;\\n\\t}\\n\\tget innerConeAngle() {\\n\\t\\treturn this._light.innerConeAngle;\\n\\t}\\n\\tset outerConeAngle(value) {\\n\\t\\tthis._light.outerConeAngle = value;\\n\\t}\\n\\tget outerConeAngle() {\\n\\t\\treturn this._light.outerConeAngle;\\n\\t}\\n\\tset falloffMode(value) {\\n\\t\\tthis._light.falloffMode = value;\\n\\t}\\n\\tget falloffMode() {\\n\\t\\treturn this._light.falloffMode;\\n\\t}\\n\\tset shadowType(value) {\\n\\t\\tthis._light.shadowType = value;\\n\\t}\\n\\tget shadowType() {\\n\\t\\treturn this._light.shadowType;\\n\\t}\\n\\tset vsmBlurSize(value) {\\n\\t\\tthis._light.vsmBlurSize = value;\\n\\t}\\n\\tget vsmBlurSize() {\\n\\t\\treturn this._light.vsmBlurSize;\\n\\t}\\n\\tset vsmBlurMode(value) {\\n\\t\\tthis._light.vsmBlurMode = value;\\n\\t}\\n\\tget vsmBlurMode() {\\n\\t\\treturn this._light.vsmBlurMode;\\n\\t}\\n\\tset vsmBias(value) {\\n\\t\\tthis._light.vsmBias = math.clamp(value, 0, 1);\\n\\t}\\n\\tget vsmBias() {\\n\\t\\treturn this._light.vsmBias;\\n\\t}\\n\\tset cookieAsset(value) {\\n\\t\\tif (this._cookieAssetId && (value instanceof Asset && value.id === this._cookieAssetId || value === this._cookieAssetId)) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.onCookieAssetRemove();\\n\\t\\tthis._cookieAssetId = null;\\n\\t\\tif (value instanceof Asset) {\\n\\t\\t\\tthis._cookieAssetId = value.id;\\n\\t\\t\\tthis.onCookieAssetAdd(value);\\n\\t\\t} else if (typeof value === \\\"number\\\") {\\n\\t\\t\\tthis._cookieAssetId = value;\\n\\t\\t\\tconst asset = this.system.app.assets.get(value);\\n\\t\\t\\tif (asset) {\\n\\t\\t\\t\\tthis.onCookieAssetAdd(asset);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._cookieAssetAdd = true;\\n\\t\\t\\t\\tthis.system.app.assets.on(`add:${this._cookieAssetId}`, this.onCookieAssetAdd, this);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget cookieAsset() {\\n\\t\\treturn this._cookieAssetId;\\n\\t}\\n\\tset cookie(value) {\\n\\t\\tthis._light.cookie = value;\\n\\t}\\n\\tget cookie() {\\n\\t\\treturn this._light.cookie;\\n\\t}\\n\\tset cookieIntensity(value) {\\n\\t\\tthis._light.cookieIntensity = math.clamp(value, 0, 1);\\n\\t}\\n\\tget cookieIntensity() {\\n\\t\\treturn this._light.cookieIntensity;\\n\\t}\\n\\tset cookieFalloff(value) {\\n\\t\\tthis._light.cookieFalloff = value;\\n\\t}\\n\\tget cookieFalloff() {\\n\\t\\treturn this._light.cookieFalloff;\\n\\t}\\n\\tset cookieChannel(value) {\\n\\t\\tthis._light.cookieChannel = value;\\n\\t}\\n\\tget cookieChannel() {\\n\\t\\treturn this._light.cookieChannel;\\n\\t}\\n\\tset cookieAngle(value) {\\n\\t\\tif (this._cookieAngle === value) return;\\n\\t\\tthis._cookieAngle = value;\\n\\t\\tif (value !== 0 || this._cookieScale !== null) {\\n\\t\\t\\tif (!this._cookieMatrix) this._cookieMatrix = new Vec4();\\n\\t\\t\\tlet scx = 1;\\n\\t\\t\\tlet scy = 1;\\n\\t\\t\\tif (this._cookieScale) {\\n\\t\\t\\t\\tscx = this._cookieScale.x;\\n\\t\\t\\t\\tscy = this._cookieScale.y;\\n\\t\\t\\t}\\n\\t\\t\\tconst c = Math.cos(value * math.DEG_TO_RAD);\\n\\t\\t\\tconst s = Math.sin(value * math.DEG_TO_RAD);\\n\\t\\t\\tthis._cookieMatrix.set(c / scx, -s / scx, s / scy, c / scy);\\n\\t\\t\\tthis._light.cookieTransform = this._cookieMatrix;\\n\\t\\t} else {\\n\\t\\t\\tthis._light.cookieTransform = null;\\n\\t\\t}\\n\\t}\\n\\tget cookieAngle() {\\n\\t\\treturn this._cookieAngle;\\n\\t}\\n\\tset cookieScale(value) {\\n\\t\\tthis._cookieScale = value;\\n\\t\\tif (value !== null || this._cookieAngle !== 0) {\\n\\t\\t\\tif (!this._cookieMatrix) this._cookieMatrix = new Vec4();\\n\\t\\t\\tconst scx = value ? value.x : 1;\\n\\t\\t\\tconst scy = value ? value.y : 1;\\n\\t\\t\\tconst c = Math.cos(this._cookieAngle * math.DEG_TO_RAD);\\n\\t\\t\\tconst s = Math.sin(this._cookieAngle * math.DEG_TO_RAD);\\n\\t\\t\\tthis._cookieMatrix.set(c / scx, -s / scx, s / scy, c / scy);\\n\\t\\t\\tthis._light.cookieTransform = this._cookieMatrix;\\n\\t\\t} else {\\n\\t\\t\\tthis._light.cookieTransform = null;\\n\\t\\t}\\n\\t}\\n\\tget cookieScale() {\\n\\t\\treturn this._cookieScale;\\n\\t}\\n\\tset cookieOffset(value) {\\n\\t\\tthis._light.cookieOffset = value;\\n\\t}\\n\\tget cookieOffset() {\\n\\t\\treturn this._light.cookieOffset;\\n\\t}\\n\\tset shadowUpdateMode(value) {\\n\\t\\tthis._light.shadowUpdateMode = value;\\n\\t}\\n\\tget shadowUpdateMode() {\\n\\t\\treturn this._light.shadowUpdateMode;\\n\\t}\\n\\tset mask(value) {\\n\\t\\tthis._light.mask = value;\\n\\t}\\n\\tget mask() {\\n\\t\\treturn this._light.mask;\\n\\t}\\n\\tset affectDynamic(value) {\\n\\t\\tif (this._affectDynamic === value) return;\\n\\t\\tthis._affectDynamic = value;\\n\\t\\tif (value) {\\n\\t\\t\\tthis._light.mask |= MASK_AFFECT_DYNAMIC;\\n\\t\\t} else {\\n\\t\\t\\tthis._light.mask &= ~MASK_AFFECT_DYNAMIC;\\n\\t\\t}\\n\\t\\tthis._light.layersDirty();\\n\\t}\\n\\tget affectDynamic() {\\n\\t\\treturn this._affectDynamic;\\n\\t}\\n\\tset affectLightmapped(value) {\\n\\t\\tif (this._affectLightmapped === value) return;\\n\\t\\tthis._affectLightmapped = value;\\n\\t\\tif (value) {\\n\\t\\t\\tthis._light.mask |= MASK_AFFECT_LIGHTMAPPED;\\n\\t\\t\\tif (this._bake) this._light.mask &= ~MASK_BAKE;\\n\\t\\t} else {\\n\\t\\t\\tthis._light.mask &= ~MASK_AFFECT_LIGHTMAPPED;\\n\\t\\t\\tif (this._bake) this._light.mask |= MASK_BAKE;\\n\\t\\t}\\n\\t}\\n\\tget affectLightmapped() {\\n\\t\\treturn this._affectLightmapped;\\n\\t}\\n\\tset bake(value) {\\n\\t\\tif (this._bake === value) return;\\n\\t\\tthis._bake = value;\\n\\t\\tif (value) {\\n\\t\\t\\tthis._light.mask |= MASK_BAKE;\\n\\t\\t\\tif (this._affectLightmapped) this._light.mask &= ~MASK_AFFECT_LIGHTMAPPED;\\n\\t\\t} else {\\n\\t\\t\\tthis._light.mask &= ~MASK_BAKE;\\n\\t\\t\\tif (this._affectLightmapped) this._light.mask |= MASK_AFFECT_LIGHTMAPPED;\\n\\t\\t}\\n\\t\\tthis._light.layersDirty();\\n\\t}\\n\\tget bake() {\\n\\t\\treturn this._bake;\\n\\t}\\n\\tset bakeDir(value) {\\n\\t\\tthis._light.bakeDir = value;\\n\\t}\\n\\tget bakeDir() {\\n\\t\\treturn this._light.bakeDir;\\n\\t}\\n\\tset isStatic(value) {\\n\\t\\tthis._light.isStatic = value;\\n\\t}\\n\\tget isStatic() {\\n\\t\\treturn this._light.isStatic;\\n\\t}\\n\\tset layers(value) {\\n\\t\\tconst oldValue = this._layers;\\n\\t\\tfor (let i = 0; i < oldValue.length; i++) {\\n\\t\\t\\tconst layer = this.system.app.scene.layers.getLayerById(oldValue[i]);\\n\\t\\t\\tif (!layer) continue;\\n\\t\\t\\tlayer.removeLight(this);\\n\\t\\t\\tthis._light.removeLayer(layer);\\n\\t\\t}\\n\\t\\tthis._layers = value;\\n\\t\\tfor (let i = 0; i < value.length; i++) {\\n\\t\\t\\tconst layer = this.system.app.scene.layers.getLayerById(value[i]);\\n\\t\\t\\tif (!layer) continue;\\n\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\tlayer.addLight(this);\\n\\t\\t\\t\\tthis._light.addLayer(layer);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget layers() {\\n\\t\\treturn this._layers;\\n\\t}\\n\\tset shadowUpdateOverrides(values) {\\n\\t\\tthis._light.shadowUpdateOverrides = values;\\n\\t}\\n\\tget shadowUpdateOverrides() {\\n\\t\\treturn this._light.shadowUpdateOverrides;\\n\\t}\\n\\tset shadowSamples(value) {\\n\\t\\tthis._light.shadowSamples = value;\\n\\t}\\n\\tget shadowSamples() {\\n\\t\\treturn this._light.shadowSamples;\\n\\t}\\n\\tset shadowBlockerSamples(value) {\\n\\t\\tthis._light.shadowBlockerSamples = value;\\n\\t}\\n\\tget shadowBlockerSamples() {\\n\\t\\treturn this._light.shadowBlockerSamples;\\n\\t}\\n\\tset penumbraSize(value) {\\n\\t\\tthis._light.penumbraSize = value;\\n\\t}\\n\\tget penumbraSize() {\\n\\t\\treturn this._light.penumbraSize;\\n\\t}\\n\\tset penumbraFalloff(value) {\\n\\t\\tthis._light.penumbraFalloff = value;\\n\\t}\\n\\tget penumbraFalloff() {\\n\\t\\treturn this._light.penumbraFalloff;\\n\\t}\\n\\taddLightToLayers() {\\n\\t\\tfor (let i = 0; i < this._layers.length; i++) {\\n\\t\\t\\tconst layer = this.system.app.scene.layers.getLayerById(this._layers[i]);\\n\\t\\t\\tif (layer) {\\n\\t\\t\\t\\tlayer.addLight(this);\\n\\t\\t\\t\\tthis._light.addLayer(layer);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tremoveLightFromLayers() {\\n\\t\\tfor (let i = 0; i < this._layers.length; i++) {\\n\\t\\t\\tconst layer = this.system.app.scene.layers.getLayerById(this._layers[i]);\\n\\t\\t\\tif (layer) {\\n\\t\\t\\t\\tlayer.removeLight(this);\\n\\t\\t\\t\\tthis._light.removeLayer(layer);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tonLayersChanged(oldComp, newComp) {\\n\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\tthis.addLightToLayers();\\n\\t\\t}\\n\\t\\toldComp.off(\\\"add\\\", this.onLayerAdded, this);\\n\\t\\toldComp.off(\\\"remove\\\", this.onLayerRemoved, this);\\n\\t\\tnewComp.on(\\\"add\\\", this.onLayerAdded, this);\\n\\t\\tnewComp.on(\\\"remove\\\", this.onLayerRemoved, this);\\n\\t}\\n\\tonLayerAdded(layer) {\\n\\t\\tconst index = this._layers.indexOf(layer.id);\\n\\t\\tif (index >= 0 && this.enabled && this.entity.enabled) {\\n\\t\\t\\tlayer.addLight(this);\\n\\t\\t\\tthis._light.addLayer(layer);\\n\\t\\t}\\n\\t}\\n\\tonLayerRemoved(layer) {\\n\\t\\tconst index = this._layers.indexOf(layer.id);\\n\\t\\tif (index >= 0) {\\n\\t\\t\\tlayer.removeLight(this);\\n\\t\\t\\tthis._light.removeLayer(layer);\\n\\t\\t}\\n\\t}\\n\\trefreshProperties() {\\n\\t\\tfor (let i = 0; i < _properties$1.length; i++) {\\n\\t\\t\\tconst name = _properties$1[i];\\n\\t\\t\\tthis[name] = this[name];\\n\\t\\t}\\n\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\tthis.onEnable();\\n\\t\\t}\\n\\t}\\n\\tonCookieAssetSet() {\\n\\t\\tlet forceLoad = false;\\n\\t\\tif (this._cookieAsset.type === \\\"cubemap\\\" && !this._cookieAsset.loadFaces) {\\n\\t\\t\\tthis._cookieAsset.loadFaces = true;\\n\\t\\t\\tforceLoad = true;\\n\\t\\t}\\n\\t\\tif (!this._cookieAsset.resource || forceLoad) this.system.app.assets.load(this._cookieAsset);\\n\\t\\tif (this._cookieAsset.resource) {\\n\\t\\t\\tthis.onCookieAssetLoad();\\n\\t\\t}\\n\\t}\\n\\tonCookieAssetAdd(asset) {\\n\\t\\tif (this._cookieAssetId !== asset.id) return;\\n\\t\\tthis._cookieAsset = asset;\\n\\t\\tif (this._light.enabled) {\\n\\t\\t\\tthis.onCookieAssetSet();\\n\\t\\t}\\n\\t\\tthis._cookieAsset.on(\\\"load\\\", this.onCookieAssetLoad, this);\\n\\t\\tthis._cookieAsset.on(\\\"remove\\\", this.onCookieAssetRemove, this);\\n\\t}\\n\\tonCookieAssetLoad() {\\n\\t\\tif (!this._cookieAsset || !this._cookieAsset.resource) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.cookie = this._cookieAsset.resource;\\n\\t}\\n\\tonCookieAssetRemove() {\\n\\t\\tif (!this._cookieAssetId) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._cookieAssetAdd) {\\n\\t\\t\\tthis.system.app.assets.off(`add:${this._cookieAssetId}`, this.onCookieAssetAdd, this);\\n\\t\\t\\tthis._cookieAssetAdd = false;\\n\\t\\t}\\n\\t\\tif (this._cookieAsset) {\\n\\t\\t\\tthis._cookieAsset.off(\\\"load\\\", this.onCookieAssetLoad, this);\\n\\t\\t\\tthis._cookieAsset.off(\\\"remove\\\", this.onCookieAssetRemove, this);\\n\\t\\t\\tthis._cookieAsset = null;\\n\\t\\t}\\n\\t\\tthis.cookie = null;\\n\\t}\\n\\tonEnable() {\\n\\t\\tconst scene = this.system.app.scene;\\n\\t\\tconst layers = scene.layers;\\n\\t\\tthis._light.enabled = true;\\n\\t\\tthis._evtLayersChanged?.off();\\n\\t\\tthis._evtLayersChanged = scene.on(\\\"set:layers\\\", this.onLayersChanged, this);\\n\\t\\tif (layers) {\\n\\t\\t\\tthis._evtLayerAdded?.off();\\n\\t\\t\\tthis._evtLayerAdded = layers.on(\\\"add\\\", this.onLayerAdded, this);\\n\\t\\t\\tthis._evtLayerRemoved?.off();\\n\\t\\t\\tthis._evtLayerRemoved = layers.on(\\\"remove\\\", this.onLayerRemoved, this);\\n\\t\\t}\\n\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\tthis.addLightToLayers();\\n\\t\\t}\\n\\t\\tif (this._cookieAsset && !this.cookie) {\\n\\t\\t\\tthis.onCookieAssetSet();\\n\\t\\t}\\n\\t}\\n\\tonDisable() {\\n\\t\\tconst scene = this.system.app.scene;\\n\\t\\tconst layers = scene.layers;\\n\\t\\tthis._light.enabled = false;\\n\\t\\tthis._evtLayersChanged?.off();\\n\\t\\tthis._evtLayersChanged = null;\\n\\t\\tif (layers) {\\n\\t\\t\\tthis._evtLayerAdded?.off();\\n\\t\\t\\tthis._evtLayerAdded = null;\\n\\t\\t\\tthis._evtLayerRemoved?.off();\\n\\t\\t\\tthis._evtLayerRemoved = null;\\n\\t\\t}\\n\\t\\tthis.removeLightFromLayers();\\n\\t}\\n\\tonRemove() {\\n\\t\\tthis.onDisable();\\n\\t\\tthis._light.destroy();\\n\\t\\tthis.cookieAsset = null;\\n\\t}\\n}\\n\\nclass LightComponentData {\\n\\tenabled = true;\\n}\\n\\nconst _schema$1 = [\\\"enabled\\\"];\\nclass LightComponentSystem extends ComponentSystem {\\n\\tconstructor(app) {\\n\\t\\tsuper(app);\\n\\t\\tthis.id = \\\"light\\\";\\n\\t\\tthis.ComponentType = LightComponent;\\n\\t\\tthis.DataType = LightComponentData;\\n\\t\\tthis.schema = _schema$1;\\n\\t\\tthis.on(\\\"beforeremove\\\", this._onRemoveComponent, this);\\n\\t}\\n\\tinitializeComponentData(component, _data) {\\n\\t\\tconst data = { ..._data };\\n\\t\\tif (data.layers && Array.isArray(data.layers)) {\\n\\t\\t\\tdata.layers = data.layers.slice(0);\\n\\t\\t}\\n\\t\\tif (data.color && Array.isArray(data.color)) {\\n\\t\\t\\tdata.color = new Color(data.color[0], data.color[1], data.color[2]);\\n\\t\\t}\\n\\t\\tif (data.cookieOffset && data.cookieOffset instanceof Array) {\\n\\t\\t\\tdata.cookieOffset = new Vec2(data.cookieOffset[0], data.cookieOffset[1]);\\n\\t\\t}\\n\\t\\tif (data.cookieScale && data.cookieScale instanceof Array) {\\n\\t\\t\\tdata.cookieScale = new Vec2(data.cookieScale[0], data.cookieScale[1]);\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty(\\\"enable\\\")) {\\n\\t\\t\\tconsole.warn(\\\"WARNING: enable: Property is deprecated. Set enabled property instead.\\\");\\n\\t\\t\\tdata.enabled = data.enable;\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < _properties$1.length; i++) {\\n\\t\\t\\tconst property = _properties$1[i];\\n\\t\\t\\tif (data.hasOwnProperty(property)) {\\n\\t\\t\\t\\tcomponent[property] = data[property];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsuper.initializeComponentData(component, data, [\\\"enabled\\\"]);\\n\\t}\\n\\t_onRemoveComponent(entity, component) {\\n\\t\\tcomponent.onRemove();\\n\\t}\\n\\tcloneComponent(entity, clone) {\\n\\t\\tconst c = entity.light;\\n\\t\\tconst data = {\\n\\t\\t\\tenabled: c.enabled\\n\\t\\t};\\n\\t\\tfor (let i = 0; i < _properties$1.length; i++) {\\n\\t\\t\\tconst name = _properties$1[i];\\n\\t\\t\\tconst value = c[name];\\n\\t\\t\\tif (value && value.clone) {\\n\\t\\t\\t\\tdata[name] = value.clone();\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tdata[name] = value;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn this.addComponent(clone, data);\\n\\t}\\n}\\nComponent._buildAccessors(LightComponent.prototype, _schema$1);\\n\\nconst components = [\\\"x\\\", \\\"y\\\", \\\"z\\\", \\\"w\\\"];\\nconst vecLookup = [void 0, void 0, Vec2, Vec3, Vec4];\\nfunction rawToValue(app, args, value, old) {\\n\\tswitch (args.type) {\\n\\t\\tcase \\\"boolean\\\":\\n\\t\\t\\treturn !!value;\\n\\t\\tcase \\\"number\\\":\\n\\t\\t\\tif (typeof value === \\\"number\\\") {\\n\\t\\t\\t\\treturn value;\\n\\t\\t\\t} else if (typeof value === \\\"string\\\") {\\n\\t\\t\\t\\tconst v = parseInt(value, 10);\\n\\t\\t\\t\\tif (isNaN(v)) return null;\\n\\t\\t\\t\\treturn v;\\n\\t\\t\\t} else if (typeof value === \\\"boolean\\\") {\\n\\t\\t\\t\\treturn 0 + value;\\n\\t\\t\\t}\\n\\t\\t\\treturn null;\\n\\t\\tcase \\\"json\\\": {\\n\\t\\t\\tconst result = {};\\n\\t\\t\\tif (Array.isArray(args.schema)) {\\n\\t\\t\\t\\tif (!value || typeof value !== \\\"object\\\") {\\n\\t\\t\\t\\t\\tvalue = {};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (let i = 0; i < args.schema.length; i++) {\\n\\t\\t\\t\\t\\tconst field = args.schema[i];\\n\\t\\t\\t\\t\\tif (!field.name) continue;\\n\\t\\t\\t\\t\\tif (field.array) {\\n\\t\\t\\t\\t\\t\\tresult[field.name] = [];\\n\\t\\t\\t\\t\\t\\tconst arr = Array.isArray(value[field.name]) ? value[field.name] : [];\\n\\t\\t\\t\\t\\t\\tfor (let j = 0; j < arr.length; j++) {\\n\\t\\t\\t\\t\\t\\t\\tresult[field.name].push(rawToValue(app, field, arr[j]));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst val = value.hasOwnProperty(field.name) ? value[field.name] : field.default;\\n\\t\\t\\t\\t\\t\\tresult[field.name] = rawToValue(app, field, val);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tcase \\\"asset\\\":\\n\\t\\t\\tif (value instanceof Asset) {\\n\\t\\t\\t\\treturn value;\\n\\t\\t\\t} else if (typeof value === \\\"number\\\") {\\n\\t\\t\\t\\treturn app.assets.get(value) || null;\\n\\t\\t\\t} else if (typeof value === \\\"string\\\") {\\n\\t\\t\\t\\treturn app.assets.get(parseInt(value, 10)) || null;\\n\\t\\t\\t}\\n\\t\\t\\treturn null;\\n\\t\\tcase \\\"entity\\\":\\n\\t\\t\\tif (value instanceof GraphNode) {\\n\\t\\t\\t\\treturn value;\\n\\t\\t\\t} else if (typeof value === \\\"string\\\") {\\n\\t\\t\\t\\treturn app.getEntityFromIndex(value);\\n\\t\\t\\t}\\n\\t\\t\\treturn null;\\n\\t\\tcase \\\"rgb\\\":\\n\\t\\tcase \\\"rgba\\\":\\n\\t\\t\\tif (value instanceof Color) {\\n\\t\\t\\t\\tif (old instanceof Color) {\\n\\t\\t\\t\\t\\told.copy(value);\\n\\t\\t\\t\\t\\treturn old;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn value.clone();\\n\\t\\t\\t} else if (value instanceof Array && value.length >= 3 && value.length <= 4) {\\n\\t\\t\\t\\tfor (let i = 0; i < value.length; i++) {\\n\\t\\t\\t\\t\\tif (typeof value[i] !== \\\"number\\\") {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!old) old = new Color();\\n\\t\\t\\t\\told.r = value[0];\\n\\t\\t\\t\\told.g = value[1];\\n\\t\\t\\t\\told.b = value[2];\\n\\t\\t\\t\\told.a = value.length === 3 ? 1 : value[3];\\n\\t\\t\\t\\treturn old;\\n\\t\\t\\t} else if (typeof value === \\\"string\\\" && /#(?:[0-9a-f]{2}){3,4}/i.test(value)) {\\n\\t\\t\\t\\tif (!old) {\\n\\t\\t\\t\\t\\told = new Color();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\told.fromString(value);\\n\\t\\t\\t\\treturn old;\\n\\t\\t\\t}\\n\\t\\t\\treturn null;\\n\\t\\tcase \\\"vec2\\\":\\n\\t\\tcase \\\"vec3\\\":\\n\\t\\tcase \\\"vec4\\\": {\\n\\t\\t\\tconst len = parseInt(args.type.slice(3), 10);\\n\\t\\t\\tconst vecType = vecLookup[len];\\n\\t\\t\\tif (value instanceof vecType) {\\n\\t\\t\\t\\tif (old instanceof vecType) {\\n\\t\\t\\t\\t\\told.copy(value);\\n\\t\\t\\t\\t\\treturn old;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn value.clone();\\n\\t\\t\\t} else if (value instanceof Array && value.length === len) {\\n\\t\\t\\t\\tfor (let i = 0; i < value.length; i++) {\\n\\t\\t\\t\\t\\tif (typeof value[i] !== \\\"number\\\") {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!old) old = new vecType();\\n\\t\\t\\t\\tfor (let i = 0; i < len; i++) {\\n\\t\\t\\t\\t\\told[components[i]] = value[i];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn old;\\n\\t\\t\\t}\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tcase \\\"curve\\\":\\n\\t\\t\\tif (value) {\\n\\t\\t\\t\\tlet curve;\\n\\t\\t\\t\\tif (value instanceof Curve || value instanceof CurveSet) {\\n\\t\\t\\t\\t\\tcurve = value.clone();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tconst CurveType = value.keys[0] instanceof Array ? CurveSet : Curve;\\n\\t\\t\\t\\t\\tcurve = new CurveType(value.keys);\\n\\t\\t\\t\\t\\tcurve.type = value.type;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn curve;\\n\\t\\t\\t}\\n\\t\\t\\tbreak;\\n\\t}\\n\\treturn value;\\n}\\nfunction attributeToValue(app, schema, value, current) {\\n\\tif (schema.array) {\\n\\t\\treturn value.map((item, index) => rawToValue(app, schema, item, current ? current[index] : null));\\n\\t}\\n\\treturn rawToValue(app, schema, value, current);\\n}\\nfunction assignAttributesToScript(app, attributeSchemaMap, data, script) {\\n\\tif (!data) return;\\n\\tfor (const attributeName in attributeSchemaMap) {\\n\\t\\tconst attributeSchema = attributeSchemaMap[attributeName];\\n\\t\\tconst dataToAssign = data[attributeName];\\n\\t\\tif (dataToAssign === void 0) continue;\\n\\t\\tscript[attributeName] = attributeToValue(app, attributeSchema, dataToAssign, script[attributeName]);\\n\\t}\\n}\\nclass ScriptAttributes {\\n\\tstatic assignAttributesToScript = assignAttributesToScript;\\n\\tstatic attributeToValue = attributeToValue;\\n\\tconstructor(scriptType) {\\n\\t\\tthis.scriptType = scriptType;\\n\\t\\tthis.index = {};\\n\\t}\\n\\tstatic reservedNames = /* @__PURE__ */ new Set([\\n\\t\\t\\\"app\\\",\\n\\t\\t\\\"entity\\\",\\n\\t\\t\\\"enabled\\\",\\n\\t\\t\\\"_enabled\\\",\\n\\t\\t\\\"_enabledOld\\\",\\n\\t\\t\\\"_destroyed\\\",\\n\\t\\t\\\"__attributes\\\",\\n\\t\\t\\\"__attributesRaw\\\",\\n\\t\\t\\\"__scriptType\\\",\\n\\t\\t\\\"__executionOrder\\\",\\n\\t\\t\\\"_callbacks\\\",\\n\\t\\t\\\"_callbackActive\\\",\\n\\t\\t\\\"has\\\",\\n\\t\\t\\\"get\\\",\\n\\t\\t\\\"on\\\",\\n\\t\\t\\\"off\\\",\\n\\t\\t\\\"fire\\\",\\n\\t\\t\\\"once\\\",\\n\\t\\t\\\"hasEvent\\\"\\n\\t]);\\n\\tadd(name, args) {\\n\\t\\tif (!args) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!args.type) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this.index[name]) {\\n\\t\\t\\treturn;\\n\\t\\t} else if (ScriptAttributes.reservedNames.has(name)) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.index[name] = args;\\n\\t\\tObject.defineProperty(this.scriptType.prototype, name, {\\n\\t\\t\\tget: function() {\\n\\t\\t\\t\\treturn this.__attributes[name];\\n\\t\\t\\t},\\n\\t\\t\\tset: function(raw) {\\n\\t\\t\\t\\tconst evt = \\\"attr\\\";\\n\\t\\t\\t\\tconst evtName = `attr:${name}`;\\n\\t\\t\\t\\tconst old = this.__attributes[name];\\n\\t\\t\\t\\tlet oldCopy = old;\\n\\t\\t\\t\\tif (old && args.type !== \\\"json\\\" && args.type !== \\\"entity\\\" && old.clone) {\\n\\t\\t\\t\\t\\tif (this.hasEvent(evt) || this.hasEvent(evtName)) {\\n\\t\\t\\t\\t\\t\\toldCopy = old.clone();\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (args.array) {\\n\\t\\t\\t\\t\\tthis.__attributes[name] = [];\\n\\t\\t\\t\\t\\tif (raw) {\\n\\t\\t\\t\\t\\t\\tfor (let i = 0, len = raw.length; i < len; i++) {\\n\\t\\t\\t\\t\\t\\t\\tthis.__attributes[name].push(rawToValue(this.app, args, raw[i], old ? old[i] : null));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tthis.__attributes[name] = rawToValue(this.app, args, raw, old);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.fire(evt, name, this.__attributes[name], oldCopy);\\n\\t\\t\\t\\tthis.fire(evtName, this.__attributes[name], oldCopy);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n\\tremove(name) {\\n\\t\\tif (!this.index[name]) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tdelete this.index[name];\\n\\t\\tdelete this.scriptType.prototype[name];\\n\\t\\treturn true;\\n\\t}\\n\\thas(name) {\\n\\t\\treturn !!this.index[name];\\n\\t}\\n\\tget(name) {\\n\\t\\treturn this.index[name] || null;\\n\\t}\\n}\\n\\nconst SCRIPT_INITIALIZE = \\\"initialize\\\";\\nconst SCRIPT_POST_INITIALIZE = \\\"postInitialize\\\";\\nconst SCRIPT_UPDATE = \\\"update\\\";\\nconst SCRIPT_POST_UPDATE = \\\"postUpdate\\\";\\nconst SCRIPT_SWAP = \\\"swap\\\";\\n\\nclass Script extends EventHandler {\\n\\tstatic EVENT_ENABLE = \\\"enable\\\";\\n\\tstatic EVENT_DISABLE = \\\"disable\\\";\\n\\tstatic EVENT_STATE = \\\"state\\\";\\n\\tstatic EVENT_DESTROY = \\\"destroy\\\";\\n\\tstatic EVENT_ATTR = \\\"attr\\\";\\n\\tstatic EVENT_ERROR = \\\"error\\\";\\n\\tapp;\\n\\tentity;\\n\\t_enabled;\\n\\t_enabledOld;\\n\\t_initialized;\\n\\t_postInitialized;\\n\\t__destroyed;\\n\\t__scriptType;\\n\\t__executionOrder;\\n\\tconstructor(args) {\\n\\t\\tsuper();\\n\\t\\tthis.initScript(args);\\n\\t}\\n\\tset enabled(value) {\\n\\t\\tthis._enabled = !!value;\\n\\t\\tif (this.enabled === this._enabledOld) return;\\n\\t\\tthis._enabledOld = this.enabled;\\n\\t\\tthis.fire(this.enabled ? \\\"enable\\\" : \\\"disable\\\");\\n\\t\\tthis.fire(\\\"state\\\", this.enabled);\\n\\t\\tif (!this._initialized && this.enabled) {\\n\\t\\t\\tthis._initialized = true;\\n\\t\\t\\tthis.fire(\\\"preInitialize\\\");\\n\\t\\t\\tif (this.initialize) {\\n\\t\\t\\t\\tthis.entity.script._scriptMethod(this, SCRIPT_INITIALIZE);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this._initialized && !this._postInitialized && this.enabled && !this.entity.script._beingEnabled) {\\n\\t\\t\\tthis._postInitialized = true;\\n\\t\\t\\tif (this.postInitialize) {\\n\\t\\t\\t\\tthis.entity.script._scriptMethod(this, SCRIPT_POST_INITIALIZE);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget enabled() {\\n\\t\\treturn this._enabled && !this._destroyed && this.entity.script.enabled && this.entity.enabled;\\n\\t}\\n\\tinitScript(args) {\\n\\t\\tconst script = this.constructor;\\n\\t\\tthis.app = args.app;\\n\\t\\tthis.entity = args.entity;\\n\\t\\tthis._enabled = typeof args.enabled === \\\"boolean\\\" ? args.enabled : true;\\n\\t\\tthis._enabledOld = this.enabled;\\n\\t\\tthis.__destroyed = false;\\n\\t\\tthis.__scriptType = script;\\n\\t\\tthis.__executionOrder = -1;\\n\\t}\\n\\tstatic __name = null;\\n\\t// Will be assigned when calling createScript or registerScript.\\n\\tstatic __getScriptName = getScriptName;\\n\\tstatic set scriptName(value) {\\n\\t\\tthis.__name = value;\\n\\t}\\n\\tstatic get scriptName() {\\n\\t\\treturn this.__name;\\n\\t}\\n}\\nconst funcNameRegex = /^\\\\s*function(?:\\\\s|\\\\s*\\\\/\\\\*.*\\\\*\\\\/\\\\s*)+([^(\\\\s\\\\/]*)\\\\s*/;\\nfunction getScriptName(constructorFn) {\\n\\tif (typeof constructorFn !== \\\"function\\\") return void 0;\\n\\tif (constructorFn.scriptName) return constructorFn.scriptName;\\n\\tif (\\\"name\\\" in Function.prototype) return constructorFn.name;\\n\\tif (constructorFn === Function || constructorFn === Function.prototype.constructor) return \\\"Function\\\";\\n\\tconst match = `${constructorFn}`.match(funcNameRegex);\\n\\treturn match ? match[1] : void 0;\\n}\\n\\nclass ScriptType extends Script {\\n\\t__attributes;\\n\\t__attributesRaw;\\n\\tconstructor(args) {\\n\\t\\tsuper(args);\\n\\t\\tthis.initScriptType(args);\\n\\t}\\n\\tstatic get attributes() {\\n\\t\\tif (!this.hasOwnProperty(\\\"__attributes\\\")) this.__attributes = new ScriptAttributes(this);\\n\\t\\treturn this.__attributes;\\n\\t}\\n\\tinitScript(args) {\\n\\t\\tScript.prototype.initScript.call(this, args);\\n\\t\\tthis.__attributes = {};\\n\\t\\tthis.__attributesRaw = args.attributes || {};\\n\\t}\\n\\tinitScriptType(args) {\\n\\t\\tthis.initScript(args);\\n\\t}\\n\\t__initializeAttributes(force) {\\n\\t\\tif (!force && !this.__attributesRaw) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tfor (const key in this.__scriptType.attributes.index) {\\n\\t\\t\\tif (this.__attributesRaw && this.__attributesRaw.hasOwnProperty(key)) {\\n\\t\\t\\t\\tthis[key] = this.__attributesRaw[key];\\n\\t\\t\\t} else if (!this.__attributes.hasOwnProperty(key)) {\\n\\t\\t\\t\\tif (this.__scriptType.attributes.index[key].hasOwnProperty(\\\"default\\\")) {\\n\\t\\t\\t\\t\\tthis[key] = this.__scriptType.attributes.index[key].default;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tthis[key] = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.__attributesRaw = null;\\n\\t}\\n\\tstatic extend(methods) {\\n\\t\\tfor (const key in methods) {\\n\\t\\t\\tif (!methods.hasOwnProperty(key)) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tthis.prototype[key] = methods[key];\\n\\t\\t}\\n\\t}\\n}\\n\\nconst toLowerCamelCase = (str) => str[0].toLowerCase() + str.substring(1);\\nclass ScriptComponent extends Component {\\n\\t_attributeDataMap = /* @__PURE__ */ new Map();\\n\\tstatic EVENT_CREATE = \\\"create\\\";\\n\\tstatic EVENT_DESTROY = \\\"destroy\\\";\\n\\tstatic EVENT_ENABLE = \\\"enable\\\";\\n\\tstatic EVENT_DISABLE = \\\"disable\\\";\\n\\tstatic EVENT_REMOVE = \\\"remove\\\";\\n\\tstatic EVENT_STATE = \\\"state\\\";\\n\\tstatic EVENT_MOVE = \\\"move\\\";\\n\\tstatic EVENT_ERROR = \\\"error\\\";\\n\\tconstructor(system, entity) {\\n\\t\\tsuper(system, entity);\\n\\t\\tthis._scripts = [];\\n\\t\\tthis._updateList = new SortedLoopArray({ sortBy: \\\"__executionOrder\\\" });\\n\\t\\tthis._postUpdateList = new SortedLoopArray({ sortBy: \\\"__executionOrder\\\" });\\n\\t\\tthis._scriptsIndex = {};\\n\\t\\tthis._destroyedScripts = [];\\n\\t\\tthis._destroyed = false;\\n\\t\\tthis._scriptsData = null;\\n\\t\\tthis._oldState = true;\\n\\t\\tthis._enabled = true;\\n\\t\\tthis._beingEnabled = false;\\n\\t\\tthis._isLoopingThroughScripts = false;\\n\\t\\tthis._executionOrder = -1;\\n\\t\\tthis.on(\\\"set_enabled\\\", this._onSetEnabled, this);\\n\\t}\\n\\tset scripts(value) {\\n\\t\\tthis._scriptsData = value;\\n\\t\\tfor (const key in value) {\\n\\t\\t\\tif (!value.hasOwnProperty(key)) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tconst script = this._scriptsIndex[key];\\n\\t\\t\\tif (script) {\\n\\t\\t\\t\\tif (typeof value[key].enabled === \\\"boolean\\\") {\\n\\t\\t\\t\\t\\tscript.once(\\\"preInitialize\\\", () => {\\n\\t\\t\\t\\t\\t\\tthis.initializeAttributes(script);\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\tscript.enabled = !!value[key].enabled;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (typeof value[key].attributes === \\\"object\\\") {\\n\\t\\t\\t\\t\\tfor (const attr in value[key].attributes) {\\n\\t\\t\\t\\t\\t\\tif (ScriptAttributes.reservedNames.has(attr)) {\\n\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!script.__attributes.hasOwnProperty(attr)) {\\n\\t\\t\\t\\t\\t\\t\\tconst scriptType = this.system.app.scripts.get(key);\\n\\t\\t\\t\\t\\t\\t\\tif (scriptType) {\\n\\t\\t\\t\\t\\t\\t\\t\\tscriptType.attributes.add(attr, {});\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tscript[attr] = value[key].attributes[attr];\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconsole.log(this.order);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget scripts() {\\n\\t\\treturn this._scripts;\\n\\t}\\n\\tset enabled(value) {\\n\\t\\tconst oldValue = this._enabled;\\n\\t\\tthis._enabled = value;\\n\\t\\tthis.fire(\\\"set\\\", \\\"enabled\\\", oldValue, value);\\n\\t}\\n\\tget enabled() {\\n\\t\\treturn this._enabled;\\n\\t}\\n\\tonEnable() {\\n\\t\\tthis._beingEnabled = true;\\n\\t\\tthis._checkState();\\n\\t\\tif (!this.entity._beingEnabled) {\\n\\t\\t\\tthis.onPostStateChange();\\n\\t\\t}\\n\\t\\tthis._beingEnabled = false;\\n\\t}\\n\\tonDisable() {\\n\\t\\tthis._checkState();\\n\\t}\\n\\tonPostStateChange() {\\n\\t\\tconst wasLooping = this._beginLooping();\\n\\t\\tfor (let i = 0, len = this.scripts.length; i < len; i++) {\\n\\t\\t\\tconst script = this.scripts[i];\\n\\t\\t\\tif (script._initialized && !script._postInitialized && script.enabled) {\\n\\t\\t\\t\\tscript._postInitialized = true;\\n\\t\\t\\t\\tif (script.postInitialize) {\\n\\t\\t\\t\\t\\tthis._scriptMethod(script, SCRIPT_POST_INITIALIZE);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._endLooping(wasLooping);\\n\\t}\\n\\t// Sets isLoopingThroughScripts to false and returns\\n\\t// its previous value\\n\\t_beginLooping() {\\n\\t\\tconst looping = this._isLoopingThroughScripts;\\n\\t\\tthis._isLoopingThroughScripts = true;\\n\\t\\treturn looping;\\n\\t}\\n\\t// Restores isLoopingThroughScripts to the specified parameter\\n\\t// If all loops are over then remove destroyed scripts form the _scripts array\\n\\t_endLooping(wasLoopingBefore) {\\n\\t\\tthis._isLoopingThroughScripts = wasLoopingBefore;\\n\\t\\tif (!this._isLoopingThroughScripts) {\\n\\t\\t\\tthis._removeDestroyedScripts();\\n\\t\\t}\\n\\t}\\n\\t// We also need this handler because it is fired\\n\\t// when value === old instead of onEnable and onDisable\\n\\t// which are only fired when value !== old\\n\\t_onSetEnabled(prop, old, value) {\\n\\t\\tthis._beingEnabled = true;\\n\\t\\tthis._checkState();\\n\\t\\tthis._beingEnabled = false;\\n\\t}\\n\\t_checkState() {\\n\\t\\tconst state = this.enabled && this.entity.enabled;\\n\\t\\tif (state === this._oldState) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._oldState = state;\\n\\t\\tthis.fire(state ? \\\"enable\\\" : \\\"disable\\\");\\n\\t\\tthis.fire(\\\"state\\\", state);\\n\\t\\tif (state) {\\n\\t\\t\\tthis.system._addComponentToEnabled(this);\\n\\t\\t} else {\\n\\t\\t\\tthis.system._removeComponentFromEnabled(this);\\n\\t\\t}\\n\\t\\tconst wasLooping = this._beginLooping();\\n\\t\\tfor (let i = 0, len = this.scripts.length; i < len; i++) {\\n\\t\\t\\tconst script = this.scripts[i];\\n\\t\\t\\tscript.once(\\\"preInitialize\\\", () => {\\n\\t\\t\\t\\tthis.initializeAttributes(script);\\n\\t\\t\\t});\\n\\t\\t\\tscript.enabled = script._enabled;\\n\\t\\t}\\n\\t\\tthis._endLooping(wasLooping);\\n\\t}\\n\\t_onBeforeRemove() {\\n\\t\\tthis.fire(\\\"remove\\\");\\n\\t\\tconst wasLooping = this._beginLooping();\\n\\t\\tfor (let i = 0; i < this.scripts.length; i++) {\\n\\t\\t\\tconst script = this.scripts[i];\\n\\t\\t\\tif (!script) continue;\\n\\t\\t\\tthis.destroy(script.__scriptType.__name);\\n\\t\\t}\\n\\t\\tthis._endLooping(wasLooping);\\n\\t}\\n\\t_removeDestroyedScripts() {\\n\\t\\tconst len = this._destroyedScripts.length;\\n\\t\\tif (!len) return;\\n\\t\\tfor (let i = 0; i < len; i++) {\\n\\t\\t\\tconst script = this._destroyedScripts[i];\\n\\t\\t\\tthis._removeScriptInstance(script);\\n\\t\\t}\\n\\t\\tthis._destroyedScripts.length = 0;\\n\\t\\tthis._resetExecutionOrder(0, this._scripts.length);\\n\\t}\\n\\t_onInitializeAttributes() {\\n\\t\\tfor (let i = 0, len = this.scripts.length; i < len; i++) {\\n\\t\\t\\tconst script = this.scripts[i];\\n\\t\\t\\tthis.initializeAttributes(script);\\n\\t\\t}\\n\\t}\\n\\tinitializeAttributes(script) {\\n\\t\\tif (script instanceof ScriptType) {\\n\\t\\t\\tscript.__initializeAttributes();\\n\\t\\t} else {\\n\\t\\t\\tconst name = script.__scriptType.__name;\\n\\t\\t\\tconst data = this._attributeDataMap.get(name);\\n\\t\\t\\tif (!data) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tconst schema = this.system.app.scripts?.getSchema(name);\\n\\t\\t\\tassignAttributesToScript(this.system.app, schema.attributes, data, script);\\n\\t\\t}\\n\\t}\\n\\t_scriptMethod(script, method, arg) {\\n\\t\\tscript[method](arg);\\n\\t}\\n\\t_onInitialize() {\\n\\t\\tconst scripts = this._scripts;\\n\\t\\tconst wasLooping = this._beginLooping();\\n\\t\\tfor (let i = 0, len = scripts.length; i < len; i++) {\\n\\t\\t\\tconst script = scripts[i];\\n\\t\\t\\tif (!script._initialized && script.enabled) {\\n\\t\\t\\t\\tscript._initialized = true;\\n\\t\\t\\t\\tif (script.initialize) {\\n\\t\\t\\t\\t\\tthis._scriptMethod(script, SCRIPT_INITIALIZE);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._endLooping(wasLooping);\\n\\t}\\n\\t_onPostInitialize() {\\n\\t\\tthis.onPostStateChange();\\n\\t}\\n\\t_onUpdate(dt) {\\n\\t\\tconst list = this._updateList;\\n\\t\\tif (!list.length) return;\\n\\t\\tconst wasLooping = this._beginLooping();\\n\\t\\tfor (list.loopIndex = 0; list.loopIndex < list.length; list.loopIndex++) {\\n\\t\\t\\tconst script = list.items[list.loopIndex];\\n\\t\\t\\tif (script.enabled) {\\n\\t\\t\\t\\tthis._scriptMethod(script, SCRIPT_UPDATE, dt);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._endLooping(wasLooping);\\n\\t}\\n\\t_onPostUpdate(dt) {\\n\\t\\tconst list = this._postUpdateList;\\n\\t\\tif (!list.length) return;\\n\\t\\tconst wasLooping = this._beginLooping();\\n\\t\\tfor (list.loopIndex = 0; list.loopIndex < list.length; list.loopIndex++) {\\n\\t\\t\\tconst script = list.items[list.loopIndex];\\n\\t\\t\\tif (script.enabled) {\\n\\t\\t\\t\\tthis._scriptMethod(script, SCRIPT_POST_UPDATE, dt);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._endLooping(wasLooping);\\n\\t}\\n\\t_insertScriptInstance(scriptInstance, index, scriptsLength) {\\n\\t\\tif (index === -1) {\\n\\t\\t\\tthis._scripts.push(scriptInstance);\\n\\t\\t\\tscriptInstance.__executionOrder = scriptsLength;\\n\\t\\t\\tif (scriptInstance.update) {\\n\\t\\t\\t\\tthis._updateList.append(scriptInstance);\\n\\t\\t\\t}\\n\\t\\t\\tif (scriptInstance.postUpdate) {\\n\\t\\t\\t\\tthis._postUpdateList.append(scriptInstance);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis._scripts.splice(index, 0, scriptInstance);\\n\\t\\t\\tscriptInstance.__executionOrder = index;\\n\\t\\t\\tthis._resetExecutionOrder(index + 1, scriptsLength + 1);\\n\\t\\t\\tif (scriptInstance.update) {\\n\\t\\t\\t\\tthis._updateList.insert(scriptInstance);\\n\\t\\t\\t}\\n\\t\\t\\tif (scriptInstance.postUpdate) {\\n\\t\\t\\t\\tthis._postUpdateList.insert(scriptInstance);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_removeScriptInstance(scriptInstance) {\\n\\t\\tconst idx = this._scripts.indexOf(scriptInstance);\\n\\t\\tif (idx === -1) return idx;\\n\\t\\tthis._scripts.splice(idx, 1);\\n\\t\\tif (scriptInstance.update) {\\n\\t\\t\\tthis._updateList.remove(scriptInstance);\\n\\t\\t}\\n\\t\\tif (scriptInstance.postUpdate) {\\n\\t\\t\\tthis._postUpdateList.remove(scriptInstance);\\n\\t\\t}\\n\\t\\treturn idx;\\n\\t}\\n\\t_resetExecutionOrder(startIndex, scriptsLength) {\\n\\t\\tfor (let i = startIndex; i < scriptsLength; i++) {\\n\\t\\t\\tthis._scripts[i].__executionOrder = i;\\n\\t\\t}\\n\\t}\\n\\t_resolveEntityScriptAttribute(attribute, attributeName, oldValue, useGuid, newAttributes, duplicatedIdsMap) {\\n\\t\\tif (attribute.array) {\\n\\t\\t\\tconst len = oldValue.length;\\n\\t\\t\\tif (!len) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tconst newGuidArray = oldValue.slice();\\n\\t\\t\\tfor (let i = 0; i < len; i++) {\\n\\t\\t\\t\\tconst guid = newGuidArray[i] instanceof Entity ? newGuidArray[i].guid : newGuidArray[i];\\n\\t\\t\\t\\tif (duplicatedIdsMap[guid]) {\\n\\t\\t\\t\\t\\tnewGuidArray[i] = useGuid ? duplicatedIdsMap[guid].guid : duplicatedIdsMap[guid];\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tnewAttributes[attributeName] = newGuidArray;\\n\\t\\t} else {\\n\\t\\t\\tif (oldValue instanceof Entity) {\\n\\t\\t\\t\\toldValue = oldValue.guid;\\n\\t\\t\\t} else if (typeof oldValue !== \\\"string\\\") {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tif (duplicatedIdsMap[oldValue]) {\\n\\t\\t\\t\\tnewAttributes[attributeName] = duplicatedIdsMap[oldValue];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\thas(nameOrType) {\\n\\t\\tif (typeof nameOrType === \\\"string\\\") {\\n\\t\\t\\treturn !!this._scriptsIndex[nameOrType];\\n\\t\\t}\\n\\t\\tif (!nameOrType) return false;\\n\\t\\tconst scriptType = nameOrType;\\n\\t\\tconst scriptName = scriptType.__name;\\n\\t\\tconst scriptData = this._scriptsIndex[scriptName];\\n\\t\\tconst scriptInstance = scriptData && scriptData.instance;\\n\\t\\treturn scriptInstance instanceof scriptType;\\n\\t}\\n\\tget(nameOrType) {\\n\\t\\tif (typeof nameOrType === \\\"string\\\") {\\n\\t\\t\\tconst data = this._scriptsIndex[nameOrType];\\n\\t\\t\\treturn data ? data.instance : null;\\n\\t\\t}\\n\\t\\tif (!nameOrType) return null;\\n\\t\\tconst scriptType = nameOrType;\\n\\t\\tconst scriptName = scriptType.__name;\\n\\t\\tconst scriptData = this._scriptsIndex[scriptName];\\n\\t\\tconst scriptInstance = scriptData && scriptData.instance;\\n\\t\\treturn scriptInstance instanceof scriptType ? scriptInstance : null;\\n\\t}\\n\\tcreate(nameOrType, args = {}) {\\n\\t\\tconst self = this;\\n\\t\\tlet scriptType = nameOrType;\\n\\t\\tlet scriptName = nameOrType;\\n\\t\\tif (typeof scriptType === \\\"string\\\") {\\n\\t\\t\\tscriptType = this.system.app.scripts.get(scriptType);\\n\\t\\t} else if (scriptType) {\\n\\t\\t\\tconst inferredScriptName = getScriptName(scriptType);\\n\\t\\t\\tconst lowerInferredScriptName = toLowerCamelCase(inferredScriptName);\\n\\t\\t\\tif (!(scriptType.prototype instanceof ScriptType) && !scriptType.scriptName) ;\\n\\t\\t\\tscriptType.__name ?? (scriptType.__name = scriptType.scriptName ?? lowerInferredScriptName);\\n\\t\\t\\tscriptName = scriptType.__name;\\n\\t\\t}\\n\\t\\tif (scriptType) {\\n\\t\\t\\tif (!this._scriptsIndex[scriptName] || !this._scriptsIndex[scriptName].instance) {\\n\\t\\t\\t\\tconst scriptInstance = new scriptType({\\n\\t\\t\\t\\t\\tapp: this.system.app,\\n\\t\\t\\t\\t\\tentity: this.entity,\\n\\t\\t\\t\\t\\tenabled: args.hasOwnProperty(\\\"enabled\\\") ? args.enabled : true,\\n\\t\\t\\t\\t\\tattributes: args.attributes || {}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (args.properties && typeof args.properties === \\\"object\\\") {\\n\\t\\t\\t\\t\\tObject.assign(scriptInstance, args.properties);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!(scriptInstance instanceof ScriptType) && args.attributes) {\\n\\t\\t\\t\\t\\tthis._attributeDataMap.set(scriptName, { ...args.attributes });\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst len = this._scripts.length;\\n\\t\\t\\t\\tlet ind = -1;\\n\\t\\t\\t\\tif (typeof args.ind === \\\"number\\\" && args.ind !== -1 && len > args.ind) {\\n\\t\\t\\t\\t\\tind = args.ind;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._insertScriptInstance(scriptInstance, ind, len);\\n\\t\\t\\t\\tthis._scriptsIndex[scriptName] = {\\n\\t\\t\\t\\t\\tinstance: scriptInstance,\\n\\t\\t\\t\\t\\tonSwap: function() {\\n\\t\\t\\t\\t\\t\\tself.swap(scriptName);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis[scriptName] = scriptInstance;\\n\\t\\t\\t\\tif (!args.preloading) {\\n\\t\\t\\t\\t\\tthis.initializeAttributes(scriptInstance);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.fire(\\\"create\\\", scriptName, scriptInstance);\\n\\t\\t\\t\\tthis.fire(`create:${scriptName}`, scriptInstance);\\n\\t\\t\\t\\tthis.system.app.scripts.on(`swap:${scriptName}`, this._scriptsIndex[scriptName].onSwap);\\n\\t\\t\\t\\tif (!args.preloading) {\\n\\t\\t\\t\\t\\tif (scriptInstance.enabled && !scriptInstance._initialized) {\\n\\t\\t\\t\\t\\t\\tscriptInstance._initialized = true;\\n\\t\\t\\t\\t\\t\\tif (scriptInstance.initialize) {\\n\\t\\t\\t\\t\\t\\t\\tthis._scriptMethod(scriptInstance, SCRIPT_INITIALIZE);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (scriptInstance.enabled && !scriptInstance._postInitialized) {\\n\\t\\t\\t\\t\\t\\tscriptInstance._postInitialized = true;\\n\\t\\t\\t\\t\\t\\tif (scriptInstance.postInitialize) {\\n\\t\\t\\t\\t\\t\\t\\tthis._scriptMethod(scriptInstance, SCRIPT_POST_INITIALIZE);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn scriptInstance;\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis._scriptsIndex[scriptName] = {\\n\\t\\t\\t\\tawaiting: true,\\n\\t\\t\\t\\tind: this._scripts.length\\n\\t\\t\\t};\\n\\t\\t}\\n\\t\\treturn null;\\n\\t}\\n\\tdestroy(nameOrType) {\\n\\t\\tlet scriptName = nameOrType;\\n\\t\\tlet scriptType = nameOrType;\\n\\t\\tif (typeof scriptType === \\\"string\\\") {\\n\\t\\t\\tscriptType = this.system.app.scripts.get(scriptType);\\n\\t\\t} else if (scriptType) {\\n\\t\\t\\tscriptName = scriptType.__name;\\n\\t\\t}\\n\\t\\tconst scriptData = this._scriptsIndex[scriptName];\\n\\t\\tdelete this._scriptsIndex[scriptName];\\n\\t\\tif (!scriptData) return false;\\n\\t\\tthis._attributeDataMap.delete(scriptName);\\n\\t\\tconst scriptInstance = scriptData.instance;\\n\\t\\tif (scriptInstance && !scriptInstance._destroyed) {\\n\\t\\t\\tscriptInstance.enabled = false;\\n\\t\\t\\tscriptInstance._destroyed = true;\\n\\t\\t\\tif (!this._isLoopingThroughScripts) {\\n\\t\\t\\t\\tconst ind = this._removeScriptInstance(scriptInstance);\\n\\t\\t\\t\\tif (ind >= 0) {\\n\\t\\t\\t\\t\\tthis._resetExecutionOrder(ind, this._scripts.length);\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._destroyedScripts.push(scriptInstance);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.system.app.scripts.off(`swap:${scriptName}`, scriptData.onSwap);\\n\\t\\tdelete this[scriptName];\\n\\t\\tthis.fire(\\\"destroy\\\", scriptName, scriptInstance || null);\\n\\t\\tthis.fire(`destroy:${scriptName}`, scriptInstance || null);\\n\\t\\tif (scriptInstance) {\\n\\t\\t\\tscriptInstance.fire(\\\"destroy\\\");\\n\\t\\t}\\n\\t\\treturn true;\\n\\t}\\n\\tswap(nameOrType) {\\n\\t\\tlet scriptName = nameOrType;\\n\\t\\tlet scriptType = nameOrType;\\n\\t\\tif (typeof scriptType === \\\"string\\\") {\\n\\t\\t\\tscriptType = this.system.app.scripts.get(scriptType);\\n\\t\\t} else if (scriptType) {\\n\\t\\t\\tscriptName = scriptType.__name;\\n\\t\\t}\\n\\t\\tconst old = this._scriptsIndex[scriptName];\\n\\t\\tif (!old || !old.instance) return false;\\n\\t\\tconst scriptInstanceOld = old.instance;\\n\\t\\tconst ind = this._scripts.indexOf(scriptInstanceOld);\\n\\t\\tconst scriptInstance = new scriptType({\\n\\t\\t\\tapp: this.system.app,\\n\\t\\t\\tentity: this.entity,\\n\\t\\t\\tenabled: scriptInstanceOld.enabled,\\n\\t\\t\\tattributes: scriptInstanceOld.__attributes\\n\\t\\t});\\n\\t\\tif (!scriptInstance.swap) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tthis.initializeAttributes(scriptInstance);\\n\\t\\tthis._scripts[ind] = scriptInstance;\\n\\t\\tthis._scriptsIndex[scriptName].instance = scriptInstance;\\n\\t\\tthis[scriptName] = scriptInstance;\\n\\t\\tscriptInstance.__executionOrder = ind;\\n\\t\\tif (scriptInstanceOld.update) {\\n\\t\\t\\tthis._updateList.remove(scriptInstanceOld);\\n\\t\\t}\\n\\t\\tif (scriptInstanceOld.postUpdate) {\\n\\t\\t\\tthis._postUpdateList.remove(scriptInstanceOld);\\n\\t\\t}\\n\\t\\tif (scriptInstance.update) {\\n\\t\\t\\tthis._updateList.insert(scriptInstance);\\n\\t\\t}\\n\\t\\tif (scriptInstance.postUpdate) {\\n\\t\\t\\tthis._postUpdateList.insert(scriptInstance);\\n\\t\\t}\\n\\t\\tthis._scriptMethod(scriptInstance, SCRIPT_SWAP, scriptInstanceOld);\\n\\t\\tthis.fire(\\\"swap\\\", scriptName, scriptInstance);\\n\\t\\tthis.fire(`swap:${scriptName}`, scriptInstance);\\n\\t\\treturn true;\\n\\t}\\n\\tresolveDuplicatedEntityReferenceProperties(oldScriptComponent, duplicatedIdsMap) {\\n\\t\\tconst newScriptComponent = this.entity.script;\\n\\t\\tfor (const scriptName in oldScriptComponent._scriptsIndex) {\\n\\t\\t\\tconst scriptType = this.system.app.scripts.get(scriptName);\\n\\t\\t\\tif (!scriptType) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tconst script = oldScriptComponent._scriptsIndex[scriptName];\\n\\t\\t\\tif (!script || !script.instance) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tconst newAttributesRaw = newScriptComponent[scriptName].__attributesRaw ?? newScriptComponent._attributeDataMap.get(scriptName);\\n\\t\\t\\tconst newAttributes = newScriptComponent[scriptName].__attributes;\\n\\t\\t\\tif (!newAttributesRaw && !newAttributes) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tconst useGuid = !!newAttributesRaw;\\n\\t\\t\\tconst oldAttributes = script.instance.__attributes ?? newScriptComponent._attributeDataMap.get(scriptName);\\n\\t\\t\\tfor (const attributeName in oldAttributes) {\\n\\t\\t\\t\\tif (!oldAttributes[attributeName]) {\\n\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst attribute = scriptType.attributes?.get(attributeName) ?? this.system.app.scripts.getSchema(scriptName)?.attributes?.[attributeName];\\n\\t\\t\\t\\tif (!attribute) {\\n\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (attribute.type === \\\"entity\\\") {\\n\\t\\t\\t\\t\\tthis._resolveEntityScriptAttribute(\\n\\t\\t\\t\\t\\t\\tattribute,\\n\\t\\t\\t\\t\\t\\tattributeName,\\n\\t\\t\\t\\t\\t\\toldAttributes[attributeName],\\n\\t\\t\\t\\t\\t\\tuseGuid,\\n\\t\\t\\t\\t\\t\\tnewAttributesRaw || newAttributes,\\n\\t\\t\\t\\t\\t\\tduplicatedIdsMap\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t} else if (attribute.type === \\\"json\\\" && Array.isArray(attribute.schema)) {\\n\\t\\t\\t\\t\\tconst oldValue = oldAttributes[attributeName];\\n\\t\\t\\t\\t\\tconst newJsonValue = newAttributesRaw ? newAttributesRaw[attributeName] : newAttributes[attributeName];\\n\\t\\t\\t\\t\\tfor (let i = 0; i < attribute.schema.length; i++) {\\n\\t\\t\\t\\t\\t\\tconst field = attribute.schema[i];\\n\\t\\t\\t\\t\\t\\tif (field.type !== \\\"entity\\\") {\\n\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (attribute.array) {\\n\\t\\t\\t\\t\\t\\t\\tfor (let j = 0; j < oldValue.length; j++) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._resolveEntityScriptAttribute(\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tfield,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tfield.name,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\toldValue[j][field.name],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tuseGuid,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tnewJsonValue[j],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tduplicatedIdsMap\\n\\t\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tthis._resolveEntityScriptAttribute(\\n\\t\\t\\t\\t\\t\\t\\t\\tfield,\\n\\t\\t\\t\\t\\t\\t\\t\\tfield.name,\\n\\t\\t\\t\\t\\t\\t\\t\\toldValue[field.name],\\n\\t\\t\\t\\t\\t\\t\\t\\tuseGuid,\\n\\t\\t\\t\\t\\t\\t\\t\\tnewJsonValue,\\n\\t\\t\\t\\t\\t\\t\\t\\tduplicatedIdsMap\\n\\t\\t\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tmove(nameOrType, ind) {\\n\\t\\tconst len = this._scripts.length;\\n\\t\\tif (ind >= len || ind < 0) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tlet scriptType = nameOrType;\\n\\t\\tlet scriptName = nameOrType;\\n\\t\\tif (typeof scriptName !== \\\"string\\\") {\\n\\t\\t\\tscriptName = nameOrType.__name;\\n\\t\\t} else {\\n\\t\\t\\tscriptType = null;\\n\\t\\t}\\n\\t\\tconst scriptData = this._scriptsIndex[scriptName];\\n\\t\\tif (!scriptData || !scriptData.instance) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tconst scriptInstance = scriptData.instance;\\n\\t\\tif (scriptType && !(scriptInstance instanceof scriptType)) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tconst indOld = this._scripts.indexOf(scriptInstance);\\n\\t\\tif (indOld === -1 || indOld === ind) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tthis._scripts.splice(ind, 0, this._scripts.splice(indOld, 1)[0]);\\n\\t\\tthis._resetExecutionOrder(0, len);\\n\\t\\tthis._updateList.sort();\\n\\t\\tthis._postUpdateList.sort();\\n\\t\\tthis.fire(\\\"move\\\", scriptName, scriptInstance, ind, indOld);\\n\\t\\tthis.fire(`move:${scriptName}`, scriptInstance, ind, indOld);\\n\\t\\treturn true;\\n\\t}\\n}\\n\\nclass ScriptComponentData {\\n\\tenabled = true;\\n}\\n\\nconst METHOD_INITIALIZE_ATTRIBUTES = \\\"_onInitializeAttributes\\\";\\nconst METHOD_INITIALIZE = \\\"_onInitialize\\\";\\nconst METHOD_POST_INITIALIZE = \\\"_onPostInitialize\\\";\\nconst METHOD_UPDATE = \\\"_onUpdate\\\";\\nconst METHOD_POST_UPDATE = \\\"_onPostUpdate\\\";\\nlet executionOrderCounter = 0;\\nclass ScriptComponentSystem extends ComponentSystem {\\n\\tconstructor(app) {\\n\\t\\tsuper(app);\\n\\t\\tthis.id = \\\"script\\\";\\n\\t\\tthis.ComponentType = ScriptComponent;\\n\\t\\tthis.DataType = ScriptComponentData;\\n\\t\\tthis._components = new SortedLoopArray({\\n\\t\\t\\tsortBy: \\\"_executionOrder\\\"\\n\\t\\t});\\n\\t\\tthis._enabledComponents = new SortedLoopArray({\\n\\t\\t\\tsortBy: \\\"_executionOrder\\\"\\n\\t\\t});\\n\\t\\tthis.preloading = true;\\n\\t\\tthis.on(\\\"beforeremove\\\", this._onBeforeRemove, this);\\n\\t\\tthis.app.systems.on(\\\"initialize\\\", this._onInitialize, this);\\n\\t\\tthis.app.systems.on(\\\"postInitialize\\\", this._onPostInitialize, this);\\n\\t\\tthis.app.systems.on(\\\"update\\\", this._onUpdate, this);\\n\\t\\tthis.app.systems.on(\\\"postUpdate\\\", this._onPostUpdate, this);\\n\\t}\\n\\tinitializeComponentData(component, data) {\\n\\t\\tcomponent._executionOrder = executionOrderCounter++;\\n\\t\\tthis._components.append(component);\\n\\t\\tif (executionOrderCounter > Number.MAX_SAFE_INTEGER) {\\n\\t\\t\\tthis._resetExecutionOrder();\\n\\t\\t}\\n\\t\\tcomponent.enabled = data.hasOwnProperty(\\\"enabled\\\") ? !!data.enabled : true;\\n\\t\\tif (component.enabled && component.entity.enabled) {\\n\\t\\t\\tthis._enabledComponents.append(component);\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty(\\\"order\\\") && data.hasOwnProperty(\\\"scripts\\\")) {\\n\\t\\t\\tcomponent._scriptsData = data.scripts;\\n\\t\\t\\tfor (let i = 0; i < data.order.length; i++) {\\n\\t\\t\\t\\tcomponent.create(data.order[i], {\\n\\t\\t\\t\\t\\tenabled: data.scripts[data.order[i]].enabled,\\n\\t\\t\\t\\t\\tattributes: data.scripts[data.order[i]].attributes,\\n\\t\\t\\t\\t\\tpreloading: this.preloading\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tcloneComponent(entity, clone) {\\n\\t\\tconst order = [];\\n\\t\\tconst scripts = {};\\n\\t\\tfor (let i = 0; i < entity.script._scripts.length; i++) {\\n\\t\\t\\tconst scriptInstance = entity.script._scripts[i];\\n\\t\\t\\tconst scriptName = scriptInstance.__scriptType.__name;\\n\\t\\t\\torder.push(scriptName);\\n\\t\\t\\tconst attributes = entity.script._attributeDataMap?.get(scriptName) || {};\\n\\t\\t\\tfor (const key in scriptInstance.__attributes) {\\n\\t\\t\\t\\tattributes[key] = scriptInstance.__attributes[key];\\n\\t\\t\\t}\\n\\t\\t\\tscripts[scriptName] = {\\n\\t\\t\\t\\tenabled: scriptInstance._enabled,\\n\\t\\t\\t\\tattributes\\n\\t\\t\\t};\\n\\t\\t}\\n\\t\\tfor (const key in entity.script._scriptsIndex) {\\n\\t\\t\\tif (key.awaiting) {\\n\\t\\t\\t\\torder.splice(key.ind, 0, key);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst data = {\\n\\t\\t\\tenabled: entity.script.enabled,\\n\\t\\t\\torder,\\n\\t\\t\\tscripts\\n\\t\\t};\\n\\t\\treturn this.addComponent(clone, data);\\n\\t}\\n\\t_resetExecutionOrder() {\\n\\t\\texecutionOrderCounter = 0;\\n\\t\\tfor (let i = 0, len = this._components.length; i < len; i++) {\\n\\t\\t\\tthis._components.items[i]._executionOrder = executionOrderCounter++;\\n\\t\\t}\\n\\t}\\n\\t_callComponentMethod(components, name, dt) {\\n\\t\\tfor (components.loopIndex = 0; components.loopIndex < components.length; components.loopIndex++) {\\n\\t\\t\\tcomponents.items[components.loopIndex][name](dt);\\n\\t\\t}\\n\\t}\\n\\t_onInitialize() {\\n\\t\\tthis.preloading = false;\\n\\t\\tthis._callComponentMethod(this._components, METHOD_INITIALIZE_ATTRIBUTES);\\n\\t\\tthis._callComponentMethod(this._enabledComponents, METHOD_INITIALIZE);\\n\\t}\\n\\t_onPostInitialize() {\\n\\t\\tthis._callComponentMethod(this._enabledComponents, METHOD_POST_INITIALIZE);\\n\\t}\\n\\t_onUpdate(dt) {\\n\\t\\tthis._callComponentMethod(this._enabledComponents, METHOD_UPDATE, dt);\\n\\t}\\n\\t_onPostUpdate(dt) {\\n\\t\\tthis._callComponentMethod(this._enabledComponents, METHOD_POST_UPDATE, dt);\\n\\t}\\n\\t// inserts the component into the enabledComponents array\\n\\t// which finds the right slot based on component._executionOrder\\n\\t_addComponentToEnabled(component) {\\n\\t\\tthis._enabledComponents.insert(component);\\n\\t}\\n\\t// removes the component from the enabledComponents array\\n\\t_removeComponentFromEnabled(component) {\\n\\t\\tthis._enabledComponents.remove(component);\\n\\t}\\n\\t_onBeforeRemove(entity, component) {\\n\\t\\tconst ind = this._components.items.indexOf(component);\\n\\t\\tif (ind >= 0) {\\n\\t\\t\\tcomponent._onBeforeRemove();\\n\\t\\t}\\n\\t\\tthis._removeComponentFromEnabled(component);\\n\\t\\tthis._components.remove(component);\\n\\t}\\n\\tdestroy() {\\n\\t\\tsuper.destroy();\\n\\t\\tthis.app.systems.off(\\\"initialize\\\", this._onInitialize, this);\\n\\t\\tthis.app.systems.off(\\\"postInitialize\\\", this._onPostInitialize, this);\\n\\t\\tthis.app.systems.off(\\\"update\\\", this._onUpdate, this);\\n\\t\\tthis.app.systems.off(\\\"postUpdate\\\", this._onPostUpdate, this);\\n\\t}\\n}\\n\\nconst tmpSize = new Vec2();\\nlet subDrawDataArray = new Uint32Array(0);\\nconst _fullRangeInterval = [0, 0];\\nclass GSplatInfo {\\n\\tdevice;\\n\\tresource;\\n\\tnode;\\n\\tlodIndex;\\n\\tplacementId;\\n\\tallocId;\\n\\tparentPlacementId;\\n\\tnumSplats;\\n\\tactiveSplats = 0;\\n\\tintervals = [];\\n\\tintervalOffsets = [];\\n\\tintervalAllocIds = [];\\n\\tintervalNodeIndices = [];\\n\\tpreviousWorldTransform = new Mat4();\\n\\taabb = new BoundingBox();\\n\\tsubDrawTexture = null;\\n\\tsubDrawCount = 0;\\n\\tnumBoundsEntries = 0;\\n\\tboundsBaseIndex = 0;\\n\\toctreeNodes = null;\\n\\tnodeInfos = null;\\n\\tcolorAccumulatedTranslation = 0;\\n\\tparameters = null;\\n\\tgetWorkBufferModifier = null;\\n\\tgetInstanceStreams = null;\\n\\t_consumeRenderDirty = null;\\n\\tconstructor(device, resource, placement, consumeRenderDirty = null, octreeNodes = null, nodeInfos = null) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.resource = resource;\\n\\t\\tthis.node = placement.node;\\n\\t\\tthis.lodIndex = placement.lodIndex;\\n\\t\\tthis.placementId = placement.id;\\n\\t\\tthis.allocId = placement.allocId;\\n\\t\\tthis.parentPlacementId = octreeNodes && placement.parentPlacement ? placement.parentPlacement.allocId : placement.allocId;\\n\\t\\tthis.numSplats = resource.numSplats;\\n\\t\\tthis.aabb.copy(placement.aabb);\\n\\t\\tthis.parameters = placement.parameters;\\n\\t\\tthis.getWorkBufferModifier = () => placement.workBufferModifier;\\n\\t\\tthis.getInstanceStreams = () => placement.streams;\\n\\t\\tthis._consumeRenderDirty = consumeRenderDirty;\\n\\t\\tthis.octreeNodes = octreeNodes;\\n\\t\\tthis.nodeInfos = nodeInfos;\\n\\t\\tthis.updateIntervals(placement.intervals);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.intervals.length = 0;\\n\\t\\tthis.intervalOffsets.length = 0;\\n\\t\\tthis.intervalAllocIds.length = 0;\\n\\t\\tthis.intervalNodeIndices.length = 0;\\n\\t\\tthis.subDrawTexture?.destroy();\\n\\t\\tthis.subDrawTexture = null;\\n\\t\\tthis.subDrawCount = 0;\\n\\t}\\n\\tsetLayout(intervalOffsets) {\\n\\t\\tthis.intervalOffsets = intervalOffsets;\\n\\t\\tthis.subDrawTexture?.destroy();\\n\\t\\tthis.subDrawTexture = null;\\n\\t\\tthis.subDrawCount = 0;\\n\\t}\\n\\tensureSubDrawTexture(textureWidth) {\\n\\t\\tif (!this.subDrawTexture && textureWidth > 0) {\\n\\t\\t\\tthis.updateSubDraws(textureWidth);\\n\\t\\t}\\n\\t}\\n\\tupdateIntervals(intervals) {\\n\\t\\tconst resource = this.resource;\\n\\t\\tthis.intervals.length = 0;\\n\\t\\tthis.intervalAllocIds.length = 0;\\n\\t\\tthis.intervalNodeIndices.length = 0;\\n\\t\\tthis.activeSplats = resource.numSplats;\\n\\t\\tif (intervals.size > 0) {\\n\\t\\t\\tlet totalCount = 0;\\n\\t\\t\\tlet k = 0;\\n\\t\\t\\tthis.intervals.length = intervals.size * 2;\\n\\t\\t\\tfor (const [nodeIndex, interval] of intervals) {\\n\\t\\t\\t\\tthis.intervals[k++] = interval.x;\\n\\t\\t\\t\\tthis.intervals[k++] = interval.y + 1;\\n\\t\\t\\t\\ttotalCount += interval.y - interval.x + 1;\\n\\t\\t\\t\\tif (this.nodeInfos) {\\n\\t\\t\\t\\t\\tthis.intervalAllocIds.push(this.nodeInfos[nodeIndex].allocId);\\n\\t\\t\\t\\t\\tthis.intervalNodeIndices.push(nodeIndex);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (this.octreeNodes) {\\n\\t\\t\\t\\tthis.activeSplats = totalCount;\\n\\t\\t\\t\\tthis.numBoundsEntries = this.octreeNodes.length;\\n\\t\\t\\t} else if (totalCount === this.numSplats) {\\n\\t\\t\\t\\tthis.intervals.length = 0;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.activeSplats = totalCount;\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis.numBoundsEntries = 1;\\n\\t\\t\\tthis.intervalAllocIds.push(this.allocId);\\n\\t\\t\\tconst totalCapacity = resource.maxSplats;\\n\\t\\t\\tif (totalCapacity && this.activeSplats < totalCapacity) {\\n\\t\\t\\t\\tthis.intervals[0] = 0;\\n\\t\\t\\t\\tthis.intervals[1] = this.activeSplats;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tappendSubDraws(subDrawData, subDrawCount, sourceBase, size, targetOffset, textureWidth) {\\n\\t\\tlet remaining = size;\\n\\t\\tlet row = targetOffset / textureWidth | 0;\\n\\t\\tconst col = targetOffset % textureWidth;\\n\\t\\tif (col > 0) {\\n\\t\\t\\tconst count = Math.min(remaining, textureWidth - col);\\n\\t\\t\\tconst idx = subDrawCount * 4;\\n\\t\\t\\tsubDrawData[idx] = row | 1 << 16;\\n\\t\\t\\tsubDrawData[idx + 1] = col;\\n\\t\\t\\tsubDrawData[idx + 2] = col + count;\\n\\t\\t\\tsubDrawData[idx + 3] = sourceBase;\\n\\t\\t\\tsubDrawCount++;\\n\\t\\t\\tsourceBase += count;\\n\\t\\t\\tremaining -= count;\\n\\t\\t\\trow++;\\n\\t\\t}\\n\\t\\tconst fullRows = remaining / textureWidth | 0;\\n\\t\\tif (fullRows > 0) {\\n\\t\\t\\tconst idx = subDrawCount * 4;\\n\\t\\t\\tsubDrawData[idx] = row | fullRows << 16;\\n\\t\\t\\tsubDrawData[idx + 1] = 0;\\n\\t\\t\\tsubDrawData[idx + 2] = textureWidth;\\n\\t\\t\\tsubDrawData[idx + 3] = sourceBase;\\n\\t\\t\\tsubDrawCount++;\\n\\t\\t\\tsourceBase += fullRows * textureWidth;\\n\\t\\t\\tremaining -= fullRows * textureWidth;\\n\\t\\t\\trow += fullRows;\\n\\t\\t}\\n\\t\\tif (remaining > 0) {\\n\\t\\t\\tconst idx = subDrawCount * 4;\\n\\t\\t\\tsubDrawData[idx] = row | 1 << 16;\\n\\t\\t\\tsubDrawData[idx + 1] = 0;\\n\\t\\t\\tsubDrawData[idx + 2] = remaining;\\n\\t\\t\\tsubDrawData[idx + 3] = sourceBase;\\n\\t\\t\\tsubDrawCount++;\\n\\t\\t}\\n\\t\\treturn subDrawCount;\\n\\t}\\n\\tupdateSubDraws(textureWidth) {\\n\\t\\tlet intervals = this.intervals;\\n\\t\\tlet numIntervals = intervals.length / 2;\\n\\t\\tif (numIntervals === 0) {\\n\\t\\t\\t_fullRangeInterval[0] = 0;\\n\\t\\t\\t_fullRangeInterval[1] = this.activeSplats;\\n\\t\\t\\tintervals = _fullRangeInterval;\\n\\t\\t\\tnumIntervals = 1;\\n\\t\\t}\\n\\t\\tconst maxSubDraws = numIntervals * 3;\\n\\t\\tconst requiredSize = maxSubDraws * 4;\\n\\t\\tif (subDrawDataArray.length < requiredSize) {\\n\\t\\t\\tsubDrawDataArray = new Uint32Array(requiredSize);\\n\\t\\t}\\n\\t\\tconst subDrawData = subDrawDataArray;\\n\\t\\tlet subDrawCount = 0;\\n\\t\\tfor (let i = 0; i < numIntervals; i++) {\\n\\t\\t\\tsubDrawCount = this.appendSubDraws(\\n\\t\\t\\t\\tsubDrawData,\\n\\t\\t\\t\\tsubDrawCount,\\n\\t\\t\\t\\tintervals[i * 2],\\n\\t\\t\\t\\tintervals[i * 2 + 1] - intervals[i * 2],\\n\\t\\t\\t\\tthis.intervalOffsets[i],\\n\\t\\t\\t\\ttextureWidth\\n\\t\\t\\t);\\n\\t\\t}\\n\\t\\tthis.subDrawCount = subDrawCount;\\n\\t\\tconst { x: texWidth, y: texHeight } = TextureUtils.calcTextureSize(subDrawCount, tmpSize);\\n\\t\\tthis.subDrawTexture = Texture.createDataTexture2D(this.device, \\\"subDrawData\\\", texWidth, texHeight, PIXELFORMAT_RGBA32U);\\n\\t\\tconst texData = this.subDrawTexture.lock();\\n\\t\\ttexData.set(subDrawData.subarray(0, subDrawCount * 4));\\n\\t\\tthis.subDrawTexture.unlock();\\n\\t}\\n\\tupdate() {\\n\\t\\tconst worldMatrix = this.node.getWorldTransform();\\n\\t\\tconst worldMatrixChanged = !this.previousWorldTransform.equals(worldMatrix);\\n\\t\\tif (worldMatrixChanged) {\\n\\t\\t\\tthis.previousWorldTransform.copy(worldMatrix);\\n\\t\\t}\\n\\t\\tconst renderDirty = this._consumeRenderDirty ? this._consumeRenderDirty() : false;\\n\\t\\treturn worldMatrixChanged || renderDirty;\\n\\t}\\n\\twriteBoundsSpheres(data, offset) {\\n\\t\\tif (this.octreeNodes) {\\n\\t\\t\\tfor (let i = 0; i < this.octreeNodes.length; i++) {\\n\\t\\t\\t\\tconst s = this.octreeNodes[i].boundingSphere;\\n\\t\\t\\t\\tdata[offset++] = s.x;\\n\\t\\t\\t\\tdata[offset++] = s.y;\\n\\t\\t\\t\\tdata[offset++] = s.z;\\n\\t\\t\\t\\tdata[offset++] = s.w;\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tconst aabb = this.resource.aabb;\\n\\t\\t\\tconst he = aabb.halfExtents;\\n\\t\\t\\tconst r = Math.sqrt(he.x * he.x + he.y * he.y + he.z * he.z);\\n\\t\\t\\tdata[offset++] = aabb.center.x;\\n\\t\\t\\tdata[offset++] = aabb.center.y;\\n\\t\\t\\tdata[offset++] = aabb.center.z;\\n\\t\\t\\tdata[offset++] = r;\\n\\t\\t}\\n\\t}\\n\\tget hasSphericalHarmonics() {\\n\\t\\treturn this.resource.gsplatData?.shBands > 0;\\n\\t}\\n}\\n\\nfunction UnifiedSortWorker() {\\n\\tconst myself = typeof self !== \\\"undefined\\\" && self || require(\\\"node:worker_threads\\\").parentPort;\\n\\tconst centersMap = /* @__PURE__ */ new Map();\\n\\tlet centersData;\\n\\tlet distances;\\n\\tlet countBuffer;\\n\\tlet indexMap;\\n\\tlet _radialSort = false;\\n\\tlet _warnedSortKeyOverflow = false;\\n\\tconst numBins = 32;\\n\\tconst binBase = new Float32Array(numBins + 1);\\n\\tconst binDivider = new Float32Array(numBins + 1);\\n\\tconst binWeightsUtil = new GSplatSortBinWeights();\\n\\tconst unpackBinWeights = (binWeights) => {\\n\\t\\tfor (let i = 0; i < numBins; i++) {\\n\\t\\t\\tbinBase[i] = binWeights[i * 2];\\n\\t\\t\\tbinDivider[i] = binWeights[i * 2 + 1];\\n\\t\\t}\\n\\t\\tbinBase[numBins] = binBase[numBins - 1] + binDivider[numBins - 1];\\n\\t\\tbinDivider[numBins] = 0;\\n\\t};\\n\\tconst evaluateSortKeysCommon = (sortParams, minDist, range, distances2, countBuffer2, centersData2, processSplatFn) => {\\n\\t\\tconst { ids, intervals } = centersData2;\\n\\t\\tconst invBinRange = numBins / range;\\n\\t\\tlet compactIdx = 0;\\n\\t\\tfor (let paramIdx = 0; paramIdx < sortParams.length; paramIdx++) {\\n\\t\\t\\tconst params = sortParams[paramIdx];\\n\\t\\t\\tconst id = ids[paramIdx];\\n\\t\\t\\tconst centers = centersMap.get(id);\\n\\t\\t\\tif (!centers) {\\n\\t\\t\\t\\tconsole.error(\\\"UnifiedSortWorker: No centers found for id\\\", id);\\n\\t\\t\\t}\\n\\t\\t\\tconst intervalsArray = intervals[paramIdx].length > 0 ? intervals[paramIdx] : [0, centers.length / 3];\\n\\t\\t\\tfor (let i = 0; i < intervalsArray.length; i += 2) {\\n\\t\\t\\t\\tconst intervalStart = intervalsArray[i] * 3;\\n\\t\\t\\t\\tconst intervalEnd = intervalsArray[i + 1] * 3;\\n\\t\\t\\t\\tcompactIdx = processSplatFn(\\n\\t\\t\\t\\t\\tcenters,\\n\\t\\t\\t\\t\\tparams,\\n\\t\\t\\t\\t\\tintervalStart,\\n\\t\\t\\t\\t\\tintervalEnd,\\n\\t\\t\\t\\t\\tcompactIdx,\\n\\t\\t\\t\\t\\tinvBinRange,\\n\\t\\t\\t\\t\\tminDist,\\n\\t\\t\\t\\t\\trange,\\n\\t\\t\\t\\t\\tdistances2,\\n\\t\\t\\t\\t\\tcountBuffer2\\n\\t\\t\\t\\t);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t};\\n\\tconst evaluateSortKeysLinear = (sortParams, minDist, range, distances2, countBuffer2, centersData2) => {\\n\\t\\tevaluateSortKeysCommon(\\n\\t\\t\\tsortParams,\\n\\t\\t\\tminDist,\\n\\t\\t\\trange,\\n\\t\\t\\tdistances2,\\n\\t\\t\\tcountBuffer2,\\n\\t\\t\\tcentersData2,\\n\\t\\t\\t(centers, params, intervalStart, intervalEnd, compactIdx, invBinRange, minDist2, range2, distances3, countBuffer3) => {\\n\\t\\t\\t\\tconst { transformedDirection, offset, scale } = params;\\n\\t\\t\\t\\tconst dx = transformedDirection.x;\\n\\t\\t\\t\\tconst dy = transformedDirection.y;\\n\\t\\t\\t\\tconst dz = transformedDirection.z;\\n\\t\\t\\t\\tconst sdx = dx * scale;\\n\\t\\t\\t\\tconst sdy = dy * scale;\\n\\t\\t\\t\\tconst sdz = dz * scale;\\n\\t\\t\\t\\tconst add = offset - minDist2;\\n\\t\\t\\t\\tfor (let srcIndex = intervalStart; srcIndex < intervalEnd; srcIndex += 3) {\\n\\t\\t\\t\\t\\tconst x = centers[srcIndex];\\n\\t\\t\\t\\t\\tconst y = centers[srcIndex + 1];\\n\\t\\t\\t\\t\\tconst z = centers[srcIndex + 2];\\n\\t\\t\\t\\t\\tconst dist = x * sdx + y * sdy + z * sdz + add;\\n\\t\\t\\t\\t\\tconst d = dist * invBinRange;\\n\\t\\t\\t\\t\\tconst bin = d >>> 0;\\n\\t\\t\\t\\t\\tconst sortKey = binBase[bin] + binDivider[bin] * (d - bin) >>> 0;\\n\\t\\t\\t\\t\\tdistances3[compactIdx++] = sortKey;\\n\\t\\t\\t\\t\\tcountBuffer3[sortKey]++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn compactIdx;\\n\\t\\t\\t}\\n\\t\\t);\\n\\t};\\n\\tconst evaluateSortKeysRadial = (sortParams, minDist, range, distances2, countBuffer2, centersData2) => {\\n\\t\\tevaluateSortKeysCommon(\\n\\t\\t\\tsortParams,\\n\\t\\t\\tminDist,\\n\\t\\t\\trange,\\n\\t\\t\\tdistances2,\\n\\t\\t\\tcountBuffer2,\\n\\t\\t\\tcentersData2,\\n\\t\\t\\t(centers, params, intervalStart, intervalEnd, compactIdx, invBinRange, minDist2, range2, distances3, countBuffer3) => {\\n\\t\\t\\t\\tconst { transformedPosition, scale } = params;\\n\\t\\t\\t\\tconst cx = transformedPosition.x;\\n\\t\\t\\t\\tconst cy = transformedPosition.y;\\n\\t\\t\\t\\tconst cz = transformedPosition.z;\\n\\t\\t\\t\\tfor (let srcIndex = intervalStart; srcIndex < intervalEnd; srcIndex += 3) {\\n\\t\\t\\t\\t\\tconst dx = centers[srcIndex] - cx;\\n\\t\\t\\t\\t\\tconst dy = centers[srcIndex + 1] - cy;\\n\\t\\t\\t\\t\\tconst dz = centers[srcIndex + 2] - cz;\\n\\t\\t\\t\\t\\tconst distSq = dx * dx + dy * dy + dz * dz;\\n\\t\\t\\t\\t\\tconst dist = Math.sqrt(distSq) * scale;\\n\\t\\t\\t\\t\\tconst invertedDist = range2 - dist;\\n\\t\\t\\t\\t\\tconst d = invertedDist * invBinRange;\\n\\t\\t\\t\\t\\tconst bin = d >>> 0;\\n\\t\\t\\t\\t\\tconst sortKey = binBase[bin] + binDivider[bin] * (d - bin) >>> 0;\\n\\t\\t\\t\\t\\tdistances3[compactIdx++] = sortKey;\\n\\t\\t\\t\\t\\tcountBuffer3[sortKey]++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn compactIdx;\\n\\t\\t\\t}\\n\\t\\t);\\n\\t};\\n\\tconst countingSort = (bucketCount, countBuffer2, numVertices, distances2, order) => {\\n\\t\\tfor (let i = 1; i < bucketCount; i++) {\\n\\t\\t\\tcountBuffer2[i] += countBuffer2[i - 1];\\n\\t\\t}\\n\\t\\tconst validCount = countBuffer2[bucketCount - 1];\\n\\t\\tif (validCount !== numVertices && !_warnedSortKeyOverflow) {\\n\\t\\t\\t_warnedSortKeyOverflow = true;\\n\\t\\t\\tconsole.warn(`[SortWorker] ${numVertices - validCount} splats lost due to sortKey overflow. Check resource AABB bounds contain all the splats.`);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < numVertices; i++) {\\n\\t\\t\\tconst distance = distances2[i];\\n\\t\\t\\tconst destIndex = --countBuffer2[distance];\\n\\t\\t\\torder[destIndex] = indexMap[i];\\n\\t\\t}\\n\\t};\\n\\tconst computeEffectiveDistanceRangeLinear = (sortParams) => {\\n\\t\\tlet minDist = Infinity;\\n\\t\\tlet maxDist = -Infinity;\\n\\t\\tfor (let paramIdx = 0; paramIdx < sortParams.length; paramIdx++) {\\n\\t\\t\\tconst params = sortParams[paramIdx];\\n\\t\\t\\tconst { transformedDirection, offset, scale, aabbMin, aabbMax } = params;\\n\\t\\t\\tconst dx = transformedDirection.x;\\n\\t\\t\\tconst dy = transformedDirection.y;\\n\\t\\t\\tconst dz = transformedDirection.z;\\n\\t\\t\\tconst pxMin = dx >= 0 ? aabbMin[0] : aabbMax[0];\\n\\t\\t\\tconst pyMin = dy >= 0 ? aabbMin[1] : aabbMax[1];\\n\\t\\t\\tconst pzMin = dz >= 0 ? aabbMin[2] : aabbMax[2];\\n\\t\\t\\tconst pxMax = dx >= 0 ? aabbMax[0] : aabbMin[0];\\n\\t\\t\\tconst pyMax = dy >= 0 ? aabbMax[1] : aabbMin[1];\\n\\t\\t\\tconst pzMax = dz >= 0 ? aabbMax[2] : aabbMin[2];\\n\\t\\t\\tconst dMin = pxMin * dx + pyMin * dy + pzMin * dz;\\n\\t\\t\\tconst dMax = pxMax * dx + pyMax * dy + pzMax * dz;\\n\\t\\t\\tconst eMin = dMin * scale + offset;\\n\\t\\t\\tconst eMax = dMax * scale + offset;\\n\\t\\t\\tconst localMin = Math.min(eMin, eMax);\\n\\t\\t\\tconst localMax = Math.max(eMin, eMax);\\n\\t\\t\\tif (localMin < minDist) minDist = localMin;\\n\\t\\t\\tif (localMax > maxDist) maxDist = localMax;\\n\\t\\t}\\n\\t\\tif (minDist === Infinity) {\\n\\t\\t\\tminDist = 0;\\n\\t\\t\\tmaxDist = 0;\\n\\t\\t}\\n\\t\\treturn { minDist, maxDist };\\n\\t};\\n\\tconst computeEffectiveDistanceRangeRadial = (sortParams) => {\\n\\t\\tlet maxDist = -Infinity;\\n\\t\\tfor (let paramIdx = 0; paramIdx < sortParams.length; paramIdx++) {\\n\\t\\t\\tconst params = sortParams[paramIdx];\\n\\t\\t\\tconst { transformedPosition, scale, aabbMin, aabbMax } = params;\\n\\t\\t\\tconst cx = transformedPosition.x;\\n\\t\\t\\tconst cy = transformedPosition.y;\\n\\t\\t\\tconst cz = transformedPosition.z;\\n\\t\\t\\tfor (let i = 0; i < 8; i++) {\\n\\t\\t\\t\\tconst px = i & 1 ? aabbMax[0] : aabbMin[0];\\n\\t\\t\\t\\tconst py = i & 2 ? aabbMax[1] : aabbMin[1];\\n\\t\\t\\t\\tconst pz = i & 4 ? aabbMax[2] : aabbMin[2];\\n\\t\\t\\t\\tconst dx = px - cx;\\n\\t\\t\\t\\tconst dy = py - cy;\\n\\t\\t\\t\\tconst dz = pz - cz;\\n\\t\\t\\t\\tconst distSq = dx * dx + dy * dy + dz * dz;\\n\\t\\t\\t\\tconst dist = Math.sqrt(distSq) * scale;\\n\\t\\t\\t\\tif (dist > maxDist) maxDist = dist;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst minDist = 0;\\n\\t\\tif (maxDist < 0) {\\n\\t\\t\\tmaxDist = 0;\\n\\t\\t}\\n\\t\\treturn { minDist, maxDist };\\n\\t};\\n\\tconst sort = (sortParams, order, centersData2) => {\\n\\t\\tconst sortStartTime = performance.now();\\n\\t\\tconst { minDist, maxDist } = _radialSort ? computeEffectiveDistanceRangeRadial(sortParams) : computeEffectiveDistanceRangeLinear(sortParams);\\n\\t\\tconst numVertices = centersData2.totalActiveSplats;\\n\\t\\tconst compareBits = Math.max(10, Math.min(20, Math.round(Math.log2(numVertices / 4))));\\n\\t\\tconst bucketCount = 2 ** compareBits + 1;\\n\\t\\tif (distances?.length !== numVertices) {\\n\\t\\t\\tdistances = new Uint32Array(numVertices);\\n\\t\\t}\\n\\t\\tif (!countBuffer || countBuffer.length !== bucketCount) {\\n\\t\\t\\tcountBuffer = new Uint32Array(bucketCount);\\n\\t\\t} else {\\n\\t\\t\\tcountBuffer.fill(0);\\n\\t\\t}\\n\\t\\tconst range = maxDist - minDist;\\n\\t\\tconst cameraBin = GSplatSortBinWeights.computeCameraBin(_radialSort, minDist, range);\\n\\t\\tconst binWeights = binWeightsUtil.compute(cameraBin, bucketCount);\\n\\t\\tunpackBinWeights(binWeights);\\n\\t\\tif (_radialSort) {\\n\\t\\t\\tevaluateSortKeysRadial(sortParams, minDist, range, distances, countBuffer, centersData2);\\n\\t\\t} else {\\n\\t\\t\\tevaluateSortKeysLinear(sortParams, minDist, range, distances, countBuffer, centersData2);\\n\\t\\t}\\n\\t\\tcountingSort(bucketCount, countBuffer, numVertices, distances, order);\\n\\t\\tconst count = numVertices;\\n\\t\\tconst sortTime = performance.now() - sortStartTime;\\n\\t\\tconst transferList = [order.buffer];\\n\\t\\tconst response = {\\n\\t\\t\\torder: order.buffer,\\n\\t\\t\\tcount,\\n\\t\\t\\tversion: centersData2.version,\\n\\t\\t\\tsortTime\\n\\t\\t};\\n\\t\\tmyself.postMessage(response, transferList);\\n\\t};\\n\\tconst buildIndexMap = (data) => {\\n\\t\\tconst { ids, pixelOffsets, intervals, totalActiveSplats } = data;\\n\\t\\tif (!indexMap || indexMap.length < totalActiveSplats) {\\n\\t\\t\\tindexMap = new Uint32Array(totalActiveSplats);\\n\\t\\t}\\n\\t\\tlet compactIdx = 0;\\n\\t\\tfor (let paramIdx = 0; paramIdx < ids.length; paramIdx++) {\\n\\t\\t\\tconst centers = centersMap.get(ids[paramIdx]);\\n\\t\\t\\tconst offsets = pixelOffsets[paramIdx];\\n\\t\\t\\tconst intervalsArray = intervals[paramIdx].length > 0 ? intervals[paramIdx] : [0, centers.length / 3];\\n\\t\\t\\tfor (let i = 0; i < intervalsArray.length; i += 2) {\\n\\t\\t\\t\\tlet workBufferIndex = offsets[i / 2];\\n\\t\\t\\t\\tconst count = intervalsArray[i + 1] - intervalsArray[i];\\n\\t\\t\\t\\tfor (let j = 0; j < count; j++) {\\n\\t\\t\\t\\t\\tindexMap[compactIdx++] = workBufferIndex++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t};\\n\\tmyself.addEventListener(\\\"message\\\", (message) => {\\n\\t\\tconst msgData = message.data ?? message;\\n\\t\\tswitch (msgData.command) {\\n\\t\\t\\t// add centers to map\\n\\t\\t\\tcase \\\"addCenters\\\": {\\n\\t\\t\\t\\tcentersMap.set(msgData.id, new Float32Array(msgData.centers));\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\t// remove centers from map\\n\\t\\t\\tcase \\\"removeCenters\\\": {\\n\\t\\t\\t\\tcentersMap.delete(msgData.id);\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\t// sort\\n\\t\\t\\tcase \\\"sort\\\": {\\n\\t\\t\\t\\t_radialSort = msgData.radialSorting || false;\\n\\t\\t\\t\\tconst order = new Uint32Array(msgData.order);\\n\\t\\t\\t\\tsort(msgData.sortParams, order, centersData);\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\t// intervals\\n\\t\\t\\tcase \\\"intervals\\\": {\\n\\t\\t\\t\\tcentersData = msgData;\\n\\t\\t\\t\\tbuildIndexMap(centersData);\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t});\\n}\\n\\nlet GSplatSortBinWeights$1 = class GSplatSortBinWeights {\\n\\tstatic get NUM_BINS() {\\n\\t\\treturn 32;\\n\\t}\\n\\tstatic get WEIGHT_TIERS() {\\n\\t\\treturn [\\n\\t\\t\\t{ maxDistance: 0, weight: 40 },\\n\\t\\t\\t// Camera bin\\n\\t\\t\\t{ maxDistance: 2, weight: 20 },\\n\\t\\t\\t// Adjacent bins\\n\\t\\t\\t{ maxDistance: 5, weight: 8 },\\n\\t\\t\\t// Nearby bins\\n\\t\\t\\t{ maxDistance: 10, weight: 3 },\\n\\t\\t\\t// Medium distance\\n\\t\\t\\t{ maxDistance: Infinity, weight: 1 }\\n\\t\\t\\t// Far bins\\n\\t\\t];\\n\\t}\\n\\tconstructor() {\\n\\t\\tconst numBins = GSplatSortBinWeights.NUM_BINS;\\n\\t\\tconst weightTiers = GSplatSortBinWeights.WEIGHT_TIERS;\\n\\t\\tthis.binWeights = new Float32Array(numBins * 2);\\n\\t\\tthis.bitsPerBin = new Float32Array(numBins);\\n\\t\\tthis.weightByDistance = new Float32Array(numBins);\\n\\t\\tfor (let dist = 0; dist < numBins; dist++) {\\n\\t\\t\\tlet weight = 1;\\n\\t\\t\\tfor (let j = 0; j < weightTiers.length; j++) {\\n\\t\\t\\t\\tif (dist <= weightTiers[j].maxDistance) {\\n\\t\\t\\t\\t\\tweight = weightTiers[j].weight;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis.weightByDistance[dist] = weight;\\n\\t\\t}\\n\\t\\tthis.lastCameraBin = -1;\\n\\t\\tthis.lastBucketCount = -1;\\n\\t}\\n\\tstatic computeCameraBin(radialSort, minDist, range) {\\n\\t\\tconst numBins = GSplatSortBinWeights.NUM_BINS;\\n\\t\\tif (radialSort) {\\n\\t\\t\\treturn numBins - 1;\\n\\t\\t}\\n\\t\\tconst cameraOffsetFromRangeStart = -minDist;\\n\\t\\tconst cameraBinFloat = cameraOffsetFromRangeStart / range * numBins;\\n\\t\\treturn Math.max(0, Math.min(numBins - 1, Math.floor(cameraBinFloat)));\\n\\t}\\n\\tcompute(cameraBin, bucketCount) {\\n\\t\\tif (cameraBin === this.lastCameraBin && bucketCount === this.lastBucketCount) {\\n\\t\\t\\treturn this.binWeights;\\n\\t\\t}\\n\\t\\tthis.lastCameraBin = cameraBin;\\n\\t\\tthis.lastBucketCount = bucketCount;\\n\\t\\tconst numBins = GSplatSortBinWeights.NUM_BINS;\\n\\t\\tconst bitsPerBin = this.bitsPerBin;\\n\\t\\tfor (let i = 0; i < numBins; i++) {\\n\\t\\t\\tconst distFromCamera = Math.abs(i - cameraBin);\\n\\t\\t\\tbitsPerBin[i] = this.weightByDistance[distFromCamera];\\n\\t\\t}\\n\\t\\tlet totalWeight = 0;\\n\\t\\tfor (let i = 0; i < numBins; i++) {\\n\\t\\t\\ttotalWeight += bitsPerBin[i];\\n\\t\\t}\\n\\t\\tlet accumulated = 0;\\n\\t\\tfor (let i = 0; i < numBins; i++) {\\n\\t\\t\\tconst divider = Math.max(1, Math.floor(bitsPerBin[i] / totalWeight * bucketCount));\\n\\t\\t\\tthis.binWeights[i * 2] = accumulated;\\n\\t\\t\\tthis.binWeights[i * 2 + 1] = divider;\\n\\t\\t\\taccumulated += divider;\\n\\t\\t}\\n\\t\\tif (accumulated > bucketCount) {\\n\\t\\t\\tconst excess = accumulated - bucketCount;\\n\\t\\t\\tconst lastDividerIdx = (numBins - 1) * 2 + 1;\\n\\t\\t\\tthis.binWeights[lastDividerIdx] = Math.max(1, this.binWeights[lastDividerIdx] - excess);\\n\\t\\t}\\n\\t\\treturn this.binWeights;\\n\\t}\\n};\\n\\nconst _neededIds = /* @__PURE__ */ new Set();\\nclass GSplatUnifiedSorter extends EventHandler {\\n\\tworker;\\n\\tbufferLength = 0;\\n\\tavailableOrderData = [];\\n\\t// track how many jobs are in flight\\n\\tjobsInFlight = 0;\\n\\t// true if we have new version to process\\n\\thasNewVersion = false;\\n\\tpendingSorted = null;\\n\\tcentersSet = /* @__PURE__ */ new Set();\\n\\t_destroyed = false;\\n\\tscene = null;\\n\\tconstructor(scene) {\\n\\t\\tsuper();\\n\\t\\tthis.scene = scene ?? null;\\n\\t\\tconst workerSource = `\\n\\t\\t\\t\\t\\t\\tconst GSplatSortBinWeights = ${GSplatSortBinWeights$1.toString()};\\n\\t\\t\\t\\t\\t\\t(${UnifiedSortWorker.toString()})()\\n\\t\\t\\t\\t`;\\n\\t\\tif (platform.environment === \\\"node\\\") {\\n\\t\\t\\tthis.worker = new Worker(workerSource, {\\n\\t\\t\\t\\teval: true\\n\\t\\t\\t});\\n\\t\\t\\tthis.worker.on(\\\"message\\\", this.onSorted.bind(this));\\n\\t\\t} else {\\n\\t\\t\\tthis.worker = new Worker(URL.createObjectURL(new Blob([workerSource], {\\n\\t\\t\\t\\ttype: \\\"application/javascript\\\"\\n\\t\\t\\t})));\\n\\t\\t\\tthis.worker.addEventListener(\\\"message\\\", this.onSorted.bind(this));\\n\\t\\t}\\n\\t}\\n\\tonSorted(message) {\\n\\t\\tif (this._destroyed) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst msgData = message.data ?? message;\\n\\t\\tif (this.scene && msgData.sortTime !== void 0) {\\n\\t\\t\\tthis.scene.fire(\\\"gsplat:sorted\\\", msgData.sortTime);\\n\\t\\t}\\n\\t\\tconst orderData = new Uint32Array(msgData.order);\\n\\t\\tthis.jobsInFlight--;\\n\\t\\tif (this.pendingSorted) {\\n\\t\\t\\tthis.releaseOrderData(this.pendingSorted.orderData);\\n\\t\\t}\\n\\t\\tthis.pendingSorted = {\\n\\t\\t\\tcount: msgData.count,\\n\\t\\t\\tversion: msgData.version,\\n\\t\\t\\torderData\\n\\t\\t};\\n\\t}\\n\\tapplyPendingSorted() {\\n\\t\\tif (this.pendingSorted) {\\n\\t\\t\\tconst { count, version, orderData } = this.pendingSorted;\\n\\t\\t\\tthis.pendingSorted = null;\\n\\t\\t\\tthis.fire(\\\"sorted\\\", count, version, orderData);\\n\\t\\t\\tthis.releaseOrderData(orderData);\\n\\t\\t}\\n\\t}\\n\\treleaseOrderData(orderData) {\\n\\t\\tif (orderData.length === this.bufferLength) {\\n\\t\\t\\tthis.availableOrderData.push(orderData);\\n\\t\\t}\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._destroyed = true;\\n\\t\\tthis.pendingSorted = null;\\n\\t\\tthis.worker.terminate();\\n\\t\\tthis.worker = null;\\n\\t}\\n\\tsetCenters(id, centers) {\\n\\t\\tif (centers) {\\n\\t\\t\\tif (!this.centersSet.has(id)) {\\n\\t\\t\\t\\tthis.centersSet.add(id);\\n\\t\\t\\t\\tconst centersBuffer = centers.buffer.slice();\\n\\t\\t\\t\\tthis.worker.postMessage({\\n\\t\\t\\t\\t\\tcommand: \\\"addCenters\\\",\\n\\t\\t\\t\\t\\tid,\\n\\t\\t\\t\\t\\tcenters: centersBuffer\\n\\t\\t\\t\\t}, [centersBuffer]);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tif (this.centersSet.has(id)) {\\n\\t\\t\\t\\tthis.centersSet.delete(id);\\n\\t\\t\\t\\tthis.worker.postMessage({\\n\\t\\t\\t\\t\\tcommand: \\\"removeCenters\\\",\\n\\t\\t\\t\\t\\tid\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tupdateCentersForSplats(splats) {\\n\\t\\tfor (const splat of splats) {\\n\\t\\t\\tconst id = splat.resource.id;\\n\\t\\t\\t_neededIds.add(id);\\n\\t\\t\\tif (!this.centersSet.has(id)) {\\n\\t\\t\\t\\tthis.setCenters(id, splat.resource.centers);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (const id of this.centersSet) {\\n\\t\\t\\tif (!_neededIds.has(id)) {\\n\\t\\t\\t\\tthis.setCenters(id, null);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_neededIds.clear();\\n\\t}\\n\\tsetSortParameters(payload) {\\n\\t\\tthis.hasNewVersion = true;\\n\\t\\tconst { textureSize } = payload;\\n\\t\\tconst newLength = textureSize * textureSize;\\n\\t\\tif (newLength !== this.bufferLength) {\\n\\t\\t\\tthis.bufferLength = newLength;\\n\\t\\t\\tthis.availableOrderData.length = 0;\\n\\t\\t}\\n\\t\\tthis.worker.postMessage(payload);\\n\\t}\\n\\tsetSortParams(params, radialSorting) {\\n\\t\\tif (this.hasNewVersion || this.jobsInFlight === 0) {\\n\\t\\t\\tlet orderData = this.availableOrderData.pop();\\n\\t\\t\\tif (!orderData) {\\n\\t\\t\\t\\torderData = new Uint32Array(this.bufferLength);\\n\\t\\t\\t}\\n\\t\\t\\tthis.jobsInFlight++;\\n\\t\\t\\tthis.hasNewVersion = false;\\n\\t\\t\\tthis.worker.postMessage({\\n\\t\\t\\t\\tcommand: \\\"sort\\\",\\n\\t\\t\\t\\tsortParams: params,\\n\\t\\t\\t\\tradialSorting,\\n\\t\\t\\t\\torder: orderData.buffer\\n\\t\\t\\t}, [\\n\\t\\t\\t\\torderData.buffer\\n\\t\\t\\t]);\\n\\t\\t}\\n\\t}\\n}\\n\\nvar gsplatOutput_default$1 = `\\n#include \\\"tonemappingPS\\\"\\n#include \\\"decodePS\\\"\\n#include \\\"gammaPS\\\"\\n#include \\\"fogPS\\\"\\n#if FOG != NONE && !defined(GSPLAT_NO_FOG)\\n\\t#define GSPLAT_FOG\\n#endif\\nfn prepareOutputFromGamma(gammaColor: vec3f, depth: f32) -> vec3f {\\n\\tvar color = gammaColor;\\n\\t#if TONEMAP != NONE || GAMMA == NONE || defined(GSPLAT_FOG)\\n\\t\\tcolor = decodeGamma3(color);\\n\\t#endif\\n\\t#ifdef GSPLAT_FOG\\n\\t\\tcolor = addFog(color, depth);\\n\\t#endif\\n\\t#if TONEMAP != NONE\\n\\t\\tcolor = toneMap(color);\\n\\t#endif\\n\\t#if TONEMAP != NONE || (GAMMA != NONE && defined(GSPLAT_FOG))\\n\\t\\tcolor = gammaCorrectOutput(color);\\n\\t#endif\\n\\treturn color;\\n}\\n`;\\n\\nclass GSplatRenderer {\\n\\tdevice;\\n\\tnode;\\n\\tcameraNode;\\n\\tlayer;\\n\\tworkBuffer;\\n\\trenderMode;\\n\\t_workBufferFormatVersion = -1;\\n\\tfisheyeProj = new FisheyeProjection();\\n\\tconstructor(device, node, cameraNode, layer, workBuffer) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.node = node;\\n\\t\\tthis.cameraNode = cameraNode;\\n\\t\\tthis.layer = layer;\\n\\t\\tthis.workBuffer = workBuffer;\\n\\t\\tthis._workBufferFormatVersion = workBuffer?.format.extraStreamsVersion ?? -1;\\n\\t}\\n\\tdestroy() {\\n\\t}\\n\\tsetRenderMode(renderMode) {\\n\\t\\tthis.renderMode = renderMode;\\n\\t}\\n\\tget material() {\\n\\t\\treturn null;\\n\\t}\\n\\tsetDataSource(source) {\\n\\t\\tthis.workBuffer = source;\\n\\t\\tthis.onWorkBufferFormatChanged();\\n\\t}\\n\\tonWorkBufferFormatChanged() {\\n\\t}\\n\\tupdate(count, textureSize) {\\n\\t}\\n\\tsetGpuSortedRendering(drawSlot, sortedIds, numSplatsBuffer, textureSize) {\\n\\t}\\n\\tsetCpuSortedRendering() {\\n\\t}\\n\\tsetOrderData() {\\n\\t}\\n\\tframeUpdate(params, exposure, fogParams) {\\n\\t}\\n\\tupdateOverdrawMode(params) {\\n\\t}\\n\\t_createTonemapIncludes(cincludes) {\\n\\t\\tcincludes.set(\\\"gsplatOutputVS\\\", gsplatOutput_default$1);\\n\\t\\tconst chunkNames = [\\n\\t\\t\\t\\\"tonemappingPS\\\",\\n\\t\\t\\t\\\"tonemappingNonePS\\\",\\n\\t\\t\\t\\\"tonemappingLinearPS\\\",\\n\\t\\t\\t\\\"tonemappingFilmicPS\\\",\\n\\t\\t\\t\\\"tonemappingHejlPS\\\",\\n\\t\\t\\t\\\"tonemappingAcesPS\\\",\\n\\t\\t\\t\\\"tonemappingAces2PS\\\",\\n\\t\\t\\t\\\"tonemappingNeutralPS\\\",\\n\\t\\t\\t\\\"decodePS\\\",\\n\\t\\t\\t\\\"gammaPS\\\"\\n\\t\\t];\\n\\t\\tfor (const name of chunkNames) {\\n\\t\\t\\tcincludes.set(name, shaderChunksWGSL[name]);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass GSplatQuadRenderer extends GSplatRenderer {\\n\\t_material;\\n\\tmeshInstance;\\n\\toriginalBlendType = BLEND_ADDITIVE;\\n\\t_internalDefines = /* @__PURE__ */ new Set();\\n\\tforceCopyMaterial = true;\\n\\t_lastFisheyeEnabled = false;\\n\\t_lastSourceChunksKey = \\\"\\\";\\n\\tconstructor(device, node, cameraNode, layer, workBuffer) {\\n\\t\\tsuper(device, node, cameraNode, layer, workBuffer);\\n\\t\\tthis._material = new ShaderMaterial({\\n\\t\\t\\tuniqueName: \\\"UnifiedSplatMaterial\\\",\\n\\t\\t\\tvertexGLSL: '#include \\\"gsplatVS\\\"',\\n\\t\\t\\tfragmentGLSL: '#include \\\"gsplatPS\\\"',\\n\\t\\t\\tvertexWGSL: '#include \\\"gsplatVS\\\"',\\n\\t\\t\\tfragmentWGSL: '#include \\\"gsplatPS\\\"',\\n\\t\\t\\tattributes: {\\n\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tthis._material.setDefine(\\\"{GSPLAT_INSTANCE_SIZE}\\\", GSplatResourceBase.instanceSize);\\n\\t\\tthis.configureMaterial();\\n\\t\\tthis._material.defines.forEach((value, key) => {\\n\\t\\t\\tthis._internalDefines.add(key);\\n\\t\\t});\\n\\t\\tthis._internalDefines.add(\\\"{GSPLAT_INSTANCE_SIZE}\\\");\\n\\t\\tthis._internalDefines.add(\\\"GSPLAT_UNIFIED_ID\\\");\\n\\t\\tthis._internalDefines.add(\\\"PICK_CUSTOM_ID\\\");\\n\\t\\tthis._internalDefines.add(\\\"GSPLAT_INDIRECT_DRAW\\\");\\n\\t\\tthis._internalDefines.add(\\\"GSPLAT_SEPARATE_OPACITY\\\");\\n\\t\\tthis._internalDefines.add(\\\"GSPLAT_FISHEYE\\\");\\n\\t\\tthis.meshInstance = this.createMeshInstance();\\n\\t}\\n\\tsetRenderMode(renderMode) {\\n\\t\\tconst oldRenderMode = this.renderMode ?? 0;\\n\\t\\tconst wasForward = (oldRenderMode & GSPLAT_FORWARD) !== 0;\\n\\t\\tconst wasShadow = (oldRenderMode & GSPLAT_SHADOW) !== 0;\\n\\t\\tconst isForward = (renderMode & GSPLAT_FORWARD) !== 0;\\n\\t\\tconst isShadow = (renderMode & GSPLAT_SHADOW) !== 0;\\n\\t\\tthis.meshInstance.castShadow = isShadow;\\n\\t\\tif (wasForward && !isForward) {\\n\\t\\t\\tthis.layer.removeMeshInstances([this.meshInstance], true);\\n\\t\\t}\\n\\t\\tif (wasShadow && !isShadow) {\\n\\t\\t\\tthis.layer.removeShadowCasters([this.meshInstance]);\\n\\t\\t}\\n\\t\\tif (!wasForward && isForward) {\\n\\t\\t\\tthis.layer.addMeshInstances([this.meshInstance], true);\\n\\t\\t}\\n\\t\\tif (!wasShadow && isShadow) {\\n\\t\\t\\tthis.layer.addShadowCasters([this.meshInstance]);\\n\\t\\t}\\n\\t\\tsuper.setRenderMode(renderMode);\\n\\t}\\n\\tdestroy() {\\n\\t\\tif (this.renderMode) {\\n\\t\\t\\tif (this.renderMode & GSPLAT_FORWARD) {\\n\\t\\t\\t\\tthis.layer.removeMeshInstances([this.meshInstance], true);\\n\\t\\t\\t}\\n\\t\\t\\tif (this.renderMode & GSPLAT_SHADOW) {\\n\\t\\t\\t\\tthis.layer.removeShadowCasters([this.meshInstance]);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._material.destroy();\\n\\t\\tthis.meshInstance.destroy();\\n\\t\\tsuper.destroy();\\n\\t}\\n\\tget material() {\\n\\t\\treturn this._material;\\n\\t}\\n\\tonWorkBufferFormatChanged() {\\n\\t\\tthis.configureMaterial();\\n\\t}\\n\\tconfigureMaterial() {\\n\\t\\tconst { workBuffer } = this;\\n\\t\\tthis._injectFormatChunks();\\n\\t\\tthis._material.setDefine(\\\"SH_BANDS\\\", \\\"0\\\");\\n\\t\\tthis._material.setDefine(\\\"GSPLAT_SEPARATE_OPACITY\\\", \\\"\\\");\\n\\t\\tconst colorStream = workBuffer.format.getStream(\\\"dataColor\\\");\\n\\t\\tif (colorStream && colorStream.format !== PIXELFORMAT_RGBA16U) {\\n\\t\\t\\tthis._material.setDefine(\\\"GSPLAT_COLOR_FLOAT\\\", \\\"\\\");\\n\\t\\t}\\n\\t\\tthis._updateIdDefines();\\n\\t\\tthis._bindWorkBufferTextures();\\n\\t\\tthis._material.setParameter(\\\"numSplats\\\", 0);\\n\\t\\tthis.setOrderData();\\n\\t\\tthis._material.setDefine(`DITHER_${\\\"NONE\\\"}`, \\\"\\\");\\n\\t\\tthis._material.cull = CULLFACE_NONE;\\n\\t\\tthis._material.blendType = BLEND_PREMULTIPLIED;\\n\\t\\tthis._material.depthWrite = false;\\n\\t\\tthis._material.update();\\n\\t}\\n\\t_bindWorkBufferTextures() {\\n\\t\\tconst { workBuffer } = this;\\n\\t\\tfor (const stream of workBuffer.format.resourceStreams) {\\n\\t\\t\\tconst texture = workBuffer.getTexture(stream.name);\\n\\t\\t\\tif (texture) {\\n\\t\\t\\t\\tthis._material.setParameter(stream.name, texture);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_injectFormatChunks() {\\n\\t\\tconst chunks = this.device.isWebGPU ? this._material.shaderChunks.wgsl : this._material.shaderChunks.glsl;\\n\\t\\tconst wbFormat = this.workBuffer.format;\\n\\t\\tchunks.set(\\\"gsplatDeclarationsVS\\\", wbFormat.getInputDeclarations());\\n\\t\\tchunks.set(\\\"gsplatReadVS\\\", wbFormat.getReadCode());\\n\\t}\\n\\tupdate(count, textureSize) {\\n\\t\\tthis.meshInstance.instancingCount = Math.ceil(count / GSplatResourceBase.instanceSize);\\n\\t\\tthis._material.setParameter(\\\"numSplats\\\", count);\\n\\t\\tthis._material.setParameter(\\\"splatTextureSize\\\", textureSize);\\n\\t\\tthis.meshInstance.visible = count > 0;\\n\\t}\\n\\tsetGpuSortedRendering(drawSlot, sortedIds, numSplatsBuffer, textureSize) {\\n\\t\\tthis.meshInstance.setIndirect(null, drawSlot, 1);\\n\\t\\tthis._material.setParameter(\\\"compactedSplatIds\\\", sortedIds);\\n\\t\\tthis._material.setParameter(\\\"numSplatsStorage\\\", numSplatsBuffer);\\n\\t\\tif (!this._material.getDefine(\\\"GSPLAT_INDIRECT_DRAW\\\")) {\\n\\t\\t\\tthis._material.setDefine(\\\"GSPLAT_INDIRECT_DRAW\\\", true);\\n\\t\\t\\tthis._material.update();\\n\\t\\t}\\n\\t\\tthis._material.setParameter(\\\"splatTextureSize\\\", textureSize);\\n\\t\\tthis.meshInstance.visible = true;\\n\\t\\tif (this.meshInstance.instancingCount <= 0) {\\n\\t\\t\\tthis.meshInstance.instancingCount = 1;\\n\\t\\t}\\n\\t}\\n\\tsetCpuSortedRendering() {\\n\\t\\tthis.meshInstance.setIndirect(null, -1);\\n\\t\\tif (this._material.getDefine(\\\"GSPLAT_INDIRECT_DRAW\\\")) {\\n\\t\\t\\tthis._material.setDefine(\\\"GSPLAT_INDIRECT_DRAW\\\", false);\\n\\t\\t\\tthis._material.update();\\n\\t\\t}\\n\\t\\tthis.setOrderData();\\n\\t\\tthis.meshInstance.visible = false;\\n\\t}\\n\\tsetOrderData() {\\n\\t\\tif (this.device.isWebGPU) {\\n\\t\\t\\tthis._material.setParameter(\\\"splatOrder\\\", this.workBuffer.orderBuffer);\\n\\t\\t} else {\\n\\t\\t\\tthis._material.setParameter(\\\"splatOrder\\\", this.workBuffer.orderTexture);\\n\\t\\t}\\n\\t}\\n\\tframeUpdate(params) {\\n\\t\\tif (params.colorRamp) {\\n\\t\\t\\tthis._material.setParameter(\\\"colorRampIntensity\\\", params.colorRampIntensity);\\n\\t\\t}\\n\\t\\tconst cam = this.cameraNode.camera;\\n\\t\\tthis.fisheyeProj.update(params.fisheye, cam.fov, cam.projectionMatrix);\\n\\t\\tconst fisheyeEnabled = this.fisheyeProj.enabled;\\n\\t\\tif (fisheyeEnabled !== this._lastFisheyeEnabled) {\\n\\t\\t\\tthis._lastFisheyeEnabled = fisheyeEnabled;\\n\\t\\t\\tthis._material.setDefine(\\\"GSPLAT_FISHEYE\\\", fisheyeEnabled);\\n\\t\\t\\tthis._material.update();\\n\\t\\t}\\n\\t\\tif (fisheyeEnabled) {\\n\\t\\t\\tconst fp = this.fisheyeProj;\\n\\t\\t\\tthis._material.setParameter(\\\"fisheye_k\\\", fp.k);\\n\\t\\t\\tthis._material.setParameter(\\\"fisheye_inv_k\\\", fp.invK);\\n\\t\\t\\tthis._material.setParameter(\\\"fisheye_projMat00\\\", fp.projMat00);\\n\\t\\t\\tthis._material.setParameter(\\\"fisheye_projMat11\\\", fp.projMat11);\\n\\t\\t}\\n\\t\\tconst noFog = !params.useFog;\\n\\t\\tif (noFog !== this._lastNoFog) {\\n\\t\\t\\tthis._lastNoFog = noFog;\\n\\t\\t\\tthis._material.setDefine(\\\"GSPLAT_NO_FOG\\\", noFog);\\n\\t\\t\\tthis._material.update();\\n\\t\\t}\\n\\t\\tthis._syncWithWorkBufferFormat();\\n\\t\\tif (this.forceCopyMaterial || params.material.dirty) {\\n\\t\\t\\tthis.copyMaterialSettings(params.material);\\n\\t\\t\\tthis.forceCopyMaterial = false;\\n\\t\\t}\\n\\t}\\n\\t_updateIdDefines() {\\n\\t\\tconst hasPcId = !!this.workBuffer.format.getStream(\\\"pcId\\\");\\n\\t\\tthis._material.setDefine(\\\"GSPLAT_UNIFIED_ID\\\", hasPcId);\\n\\t\\tthis._material.setDefine(\\\"PICK_CUSTOM_ID\\\", hasPcId);\\n\\t}\\n\\t_syncWithWorkBufferFormat() {\\n\\t\\tconst wbFormat = this.workBuffer.format;\\n\\t\\tif (this._workBufferFormatVersion !== wbFormat.extraStreamsVersion) {\\n\\t\\t\\tthis._workBufferFormatVersion = wbFormat.extraStreamsVersion;\\n\\t\\t\\tthis.workBuffer.syncWithFormat();\\n\\t\\t\\tthis._injectFormatChunks();\\n\\t\\t\\tthis._bindWorkBufferTextures();\\n\\t\\t\\tthis._updateIdDefines();\\n\\t\\t\\tthis._material.update();\\n\\t\\t}\\n\\t}\\n\\tcopyMaterialSettings(sourceMaterial) {\\n\\t\\tconst keysToDelete = [];\\n\\t\\tthis._material.defines.forEach((value, key) => {\\n\\t\\t\\tif (!this._internalDefines.has(key) && !sourceMaterial.defines.has(key)) {\\n\\t\\t\\t\\tkeysToDelete.push(key);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tkeysToDelete.forEach((key) => this._material.setDefine(key, void 0));\\n\\t\\tsourceMaterial.defines.forEach((value, key) => {\\n\\t\\t\\tthis._material.setDefine(key, value);\\n\\t\\t});\\n\\t\\tconst srcParams = sourceMaterial.parameters;\\n\\t\\tfor (const paramName in srcParams) {\\n\\t\\t\\tif (srcParams.hasOwnProperty(paramName)) {\\n\\t\\t\\t\\tthis._material.setParameter(paramName, srcParams[paramName].data);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (sourceMaterial.hasShaderChunks) {\\n\\t\\t\\tconst sourceChunksKey = sourceMaterial.shaderChunks.key;\\n\\t\\t\\tif (sourceChunksKey !== this._lastSourceChunksKey) {\\n\\t\\t\\t\\tthis._material.shaderChunks.copy(sourceMaterial.shaderChunks);\\n\\t\\t\\t\\tthis._injectFormatChunks();\\n\\t\\t\\t\\tthis._lastSourceChunksKey = sourceChunksKey;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._material.update();\\n\\t}\\n\\tupdateOverdrawMode(params) {\\n\\t\\tconst overdrawEnabled = !!params.colorRamp;\\n\\t\\tconst wasOverdrawEnabled = this._material.getDefine(\\\"GSPLAT_OVERDRAW\\\");\\n\\t\\tif (overdrawEnabled) {\\n\\t\\t\\tthis._material.setParameter(\\\"colorRamp\\\", params.colorRamp);\\n\\t\\t\\tthis._material.setParameter(\\\"colorRampIntensity\\\", params.colorRampIntensity);\\n\\t\\t}\\n\\t\\tif (overdrawEnabled !== wasOverdrawEnabled) {\\n\\t\\t\\tthis._material.setDefine(\\\"GSPLAT_OVERDRAW\\\", overdrawEnabled);\\n\\t\\t\\tif (overdrawEnabled) {\\n\\t\\t\\t\\tthis.originalBlendType = this._material.blendType;\\n\\t\\t\\t\\tthis._material.blendType = BLEND_ADDITIVE;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._material.blendType = this.originalBlendType;\\n\\t\\t\\t}\\n\\t\\t\\tthis._material.update();\\n\\t\\t}\\n\\t}\\n\\tcreateMeshInstance() {\\n\\t\\tconst mesh = GSplatResourceBase.createMesh(this.device);\\n\\t\\tconst meshInstance = new MeshInstance(mesh, this._material);\\n\\t\\tmeshInstance.node = this.node;\\n\\t\\tmeshInstance.setInstancing(true, true);\\n\\t\\tmeshInstance.instancingCount = 0;\\n\\t\\tconst thisCamera = this.cameraNode.camera;\\n\\t\\tmeshInstance.isVisibleFunc = (camera) => {\\n\\t\\t\\tconst renderMode = this.renderMode ?? 0;\\n\\t\\t\\tif (thisCamera.camera === camera && renderMode & GSPLAT_FORWARD) {\\n\\t\\t\\t\\treturn true;\\n\\t\\t\\t}\\n\\t\\t\\tif (renderMode & GSPLAT_SHADOW) {\\n\\t\\t\\t\\treturn camera.node?.name === SHADOWCAMERA_NAME;\\n\\t\\t\\t}\\n\\t\\t\\treturn false;\\n\\t\\t};\\n\\t\\treturn meshInstance;\\n\\t}\\n}\\n\\nconst CACHE_STRIDE$1 = 8;\\n\\nconst _invProjMat = new Mat4();\\nconst _shaderProjMat$2 = new Mat4();\\nclass GSplatHybridRenderer extends GSplatRenderer {\\n\\t_material;\\n\\tmeshInstance;\\n\\t_pickMaterial = null;\\n\\t_pickMeshInstance = null;\\n\\t_clipToViewZ = new Float32Array(4);\\n\\t_clipToViewZPick = null;\\n\\toriginalBlendType = BLEND_ADDITIVE;\\n\\t_internalDefines = /* @__PURE__ */ new Set();\\n\\tforceCopyMaterial = true;\\n\\tconstructor(device, node, cameraNode, layer, workBuffer) {\\n\\t\\tsuper(device, node, cameraNode, layer, workBuffer);\\n\\t\\tthis._material = new ShaderMaterial({\\n\\t\\t\\tuniqueName: \\\"UnifiedSplatHybridMaterial\\\",\\n\\t\\t\\tvertexWGSL: '#include \\\"gsplatHybridVS\\\"',\\n\\t\\t\\tfragmentWGSL: '#include \\\"gsplatPS\\\"',\\n\\t\\t\\tattributes: {\\n\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tthis._material.setDefine(\\\"{GSPLAT_INSTANCE_SIZE}\\\", GSplatResourceBase.instanceSize);\\n\\t\\tthis._material.setDefine(\\\"{CACHE_STRIDE}\\\", CACHE_STRIDE$1);\\n\\t\\tthis.configureMaterial();\\n\\t\\tthis._material.defines.forEach((value, key) => {\\n\\t\\t\\tthis._internalDefines.add(key);\\n\\t\\t});\\n\\t\\tthis._internalDefines.add(\\\"{GSPLAT_INSTANCE_SIZE}\\\");\\n\\t\\tthis._internalDefines.add(\\\"{CACHE_STRIDE}\\\");\\n\\t\\tthis._internalDefines.add(\\\"GSPLAT_UNIFIED_ID\\\");\\n\\t\\tthis._internalDefines.add(\\\"PICK_CUSTOM_ID\\\");\\n\\t\\tthis._internalDefines.add(\\\"GSPLAT_OVERDRAW\\\");\\n\\t\\tthis._internalDefines.add(\\\"GSPLAT_NO_FOG\\\");\\n\\t\\tthis.meshInstance = this.createMeshInstance();\\n\\t}\\n\\tsetRenderMode(renderMode) {\\n\\t\\tconst oldRenderMode = this.renderMode ?? 0;\\n\\t\\tconst wasForward = (oldRenderMode & GSPLAT_FORWARD) !== 0;\\n\\t\\tconst isForward = (renderMode & GSPLAT_FORWARD) !== 0;\\n\\t\\tif (wasForward && !isForward) {\\n\\t\\t\\tthis.layer.removeMeshInstances([this.meshInstance], true);\\n\\t\\t}\\n\\t\\tif (!wasForward && isForward) {\\n\\t\\t\\tthis.layer.addMeshInstances([this.meshInstance], true);\\n\\t\\t}\\n\\t\\tsuper.setRenderMode(renderMode);\\n\\t}\\n\\tdestroy() {\\n\\t\\tif (this.renderMode && this.renderMode & GSPLAT_FORWARD) {\\n\\t\\t\\tthis.layer.removeMeshInstances([this.meshInstance], true);\\n\\t\\t}\\n\\t\\tthis._material.destroy();\\n\\t\\tthis._pickMaterial?.destroy();\\n\\t\\tthis.meshInstance.destroy();\\n\\t\\tthis._pickMeshInstance?.destroy();\\n\\t\\tsuper.destroy();\\n\\t}\\n\\tget material() {\\n\\t\\treturn this._material;\\n\\t}\\n\\tonWorkBufferFormatChanged() {\\n\\t\\tthis.configureMaterial();\\n\\t}\\n\\tconfigureMaterial() {\\n\\t\\tthis._material.setDefine(\\\"SH_BANDS\\\", \\\"0\\\");\\n\\t\\tthis._material.setDefine(\\\"GSPLAT_INDIRECT_DRAW\\\", true);\\n\\t\\tthis._updateIdDefines(this._material);\\n\\t\\tthis._material.setDefine(`DITHER_${\\\"NONE\\\"}`, \\\"\\\");\\n\\t\\tthis._material.cull = CULLFACE_NONE;\\n\\t\\tthis._material.blendType = BLEND_PREMULTIPLIED;\\n\\t\\tthis._material.depthWrite = false;\\n\\t\\tthis._material.update();\\n\\t}\\n\\tupdate(count, textureSize) {\\n\\t\\tif (this.meshInstance.instancingCount <= 0) {\\n\\t\\t\\tthis.meshInstance.instancingCount = 1;\\n\\t\\t}\\n\\t\\tthis.meshInstance.visible = count > 0;\\n\\t}\\n\\tsetHybridSortedRendering(drawSlot, sortedIndices, projCache, numSplatsBuffer) {\\n\\t\\tthis.meshInstance.setIndirect(null, drawSlot, 1);\\n\\t\\tthis._material.setParameter(\\\"sortedIndices\\\", sortedIndices);\\n\\t\\tthis._material.setParameter(\\\"projCache\\\", projCache);\\n\\t\\tthis._material.setParameter(\\\"numSplatsStorage\\\", numSplatsBuffer);\\n\\t\\tthis._computeClipToViewZ(this.cameraNode, this._clipToViewZ);\\n\\t\\tthis._material.setParameter(\\\"clipToViewZ\\\", this._clipToViewZ);\\n\\t\\tthis.meshInstance.visible = true;\\n\\t\\tif (this.meshInstance.instancingCount <= 0) {\\n\\t\\t\\tthis.meshInstance.instancingCount = 1;\\n\\t\\t}\\n\\t}\\n\\tprepareForPicking(drawSlot, sortedIndices, projCache, numSplatsBuffer, alphaClip, alphaClipForward, cameraNode) {\\n\\t\\tif (!this._pickMaterial) {\\n\\t\\t\\tthis._pickMaterial = new ShaderMaterial({\\n\\t\\t\\t\\tuniqueName: \\\"UnifiedSplatHybridPickMaterial\\\",\\n\\t\\t\\t\\tvertexWGSL: '#include \\\"gsplatHybridVS\\\"',\\n\\t\\t\\t\\tfragmentWGSL: '#include \\\"gsplatPS\\\"',\\n\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t\\tthis._pickMaterial.setDefine(\\\"{GSPLAT_INSTANCE_SIZE}\\\", GSplatResourceBase.instanceSize);\\n\\t\\t\\tthis._pickMaterial.setDefine(\\\"{CACHE_STRIDE}\\\", CACHE_STRIDE$1);\\n\\t\\t\\tthis._pickMaterial.setDefine(\\\"SH_BANDS\\\", \\\"0\\\");\\n\\t\\t\\tthis._pickMaterial.setDefine(\\\"GSPLAT_INDIRECT_DRAW\\\", true);\\n\\t\\t\\tthis._pickMaterial.setDefine(\\\"DITHER_NONE\\\", \\\"\\\");\\n\\t\\t\\tthis._updateIdDefines(this._pickMaterial);\\n\\t\\t\\tthis._pickMaterial.cull = CULLFACE_NONE;\\n\\t\\t\\tthis._pickMaterial.blendType = BLEND_NONE;\\n\\t\\t\\tthis._pickMaterial.depthWrite = false;\\n\\t\\t\\tthis._pickMaterial.update();\\n\\t\\t\\tconst mesh = GSplatResourceBase.createMesh(this.device);\\n\\t\\t\\tthis._pickMeshInstance = new MeshInstance(mesh, this._pickMaterial);\\n\\t\\t\\tthis._pickMeshInstance.node = this.node;\\n\\t\\t\\tthis._pickMeshInstance.setInstancing(true, true);\\n\\t\\t\\tthis._pickMeshInstance.instancingCount = 1;\\n\\t\\t} else {\\n\\t\\t\\tif (this._updateIdDefines(this._pickMaterial)) {\\n\\t\\t\\t\\tthis._pickMaterial.update();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst pickMaterial = this._pickMaterial;\\n\\t\\tconst pickMeshInstance = this._pickMeshInstance;\\n\\t\\tpickMeshInstance.setIndirect(null, drawSlot, 1);\\n\\t\\tpickMaterial.setParameter(\\\"sortedIndices\\\", sortedIndices);\\n\\t\\tpickMaterial.setParameter(\\\"projCache\\\", projCache);\\n\\t\\tpickMaterial.setParameter(\\\"numSplatsStorage\\\", numSplatsBuffer);\\n\\t\\tpickMaterial.setParameter(\\\"alphaClip\\\", alphaClip);\\n\\t\\tpickMaterial.setParameter(\\\"alphaClipForward\\\", alphaClipForward);\\n\\t\\tthis._clipToViewZPick ?? (this._clipToViewZPick = new Float32Array(4));\\n\\t\\tthis._computeClipToViewZ(cameraNode, this._clipToViewZPick);\\n\\t\\tpickMaterial.setParameter(\\\"clipToViewZ\\\", this._clipToViewZPick);\\n\\t\\treturn pickMeshInstance;\\n\\t}\\n\\t_computeClipToViewZ(cameraNode, dst) {\\n\\t\\tconst camComp = cameraNode.camera;\\n\\t\\tconst cam = camComp.camera;\\n\\t\\tif (this.fisheyeProj.enabled) {\\n\\t\\t\\tconst near = cam.nearClip;\\n\\t\\t\\tconst far = cam.farClip;\\n\\t\\t\\tdst[0] = 0;\\n\\t\\t\\tdst[1] = 0;\\n\\t\\t\\tdst[2] = far - near;\\n\\t\\t\\tdst[3] = near;\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst flipY = !!camComp.renderTarget?.flipY;\\n\\t\\t_invProjMat.copy(Camera$1.applyShaderProjectionTransform(cam.projectionMatrix, _shaderProjMat$2, flipY, this.device.isWebGPU)).invert();\\n\\t\\tconst d = _invProjMat.data;\\n\\t\\tdst[0] = -d[2];\\n\\t\\tdst[1] = -d[6];\\n\\t\\tdst[2] = -d[10];\\n\\t\\tdst[3] = -d[14];\\n\\t}\\n\\tsetCpuSortedRendering() {\\n\\t\\tthis.meshInstance.setIndirect(null, -1);\\n\\t\\tthis.meshInstance.visible = false;\\n\\t}\\n\\tsetOrderData() {\\n\\t}\\n\\tframeUpdate(params) {\\n\\t\\tthis._material.setParameter(\\\"alphaClip\\\", params.alphaClip);\\n\\t\\tthis._material.setParameter(\\\"alphaClipForward\\\", params.alphaClipForward);\\n\\t\\tthis._pickMaterial?.setParameter(\\\"alphaClip\\\", params.alphaClip);\\n\\t\\tthis._pickMaterial?.setParameter(\\\"alphaClipForward\\\", params.alphaClipForward);\\n\\t\\tif (params.colorRamp) {\\n\\t\\t\\tthis._material.setParameter(\\\"colorRampIntensity\\\", params.colorRampIntensity);\\n\\t\\t}\\n\\t\\tconst noFog = !params.useFog;\\n\\t\\tif (noFog !== this._lastNoFog) {\\n\\t\\t\\tthis._lastNoFog = noFog;\\n\\t\\t\\tthis._material.setDefine(\\\"GSPLAT_NO_FOG\\\", noFog);\\n\\t\\t\\tthis._material.update();\\n\\t\\t}\\n\\t}\\n\\t_updateIdDefines(material) {\\n\\t\\tconst hasPcId = !!this.workBuffer.format.getStream(\\\"pcId\\\");\\n\\t\\tconst changed = material.getDefine(\\\"GSPLAT_UNIFIED_ID\\\") !== hasPcId || material.getDefine(\\\"PICK_CUSTOM_ID\\\") !== hasPcId;\\n\\t\\tmaterial.setDefine(\\\"GSPLAT_UNIFIED_ID\\\", hasPcId);\\n\\t\\tmaterial.setDefine(\\\"PICK_CUSTOM_ID\\\", hasPcId);\\n\\t\\treturn changed;\\n\\t}\\n\\tupdateOverdrawMode(params) {\\n\\t\\tconst overdrawEnabled = !!params.colorRamp;\\n\\t\\tconst wasOverdrawEnabled = this._material.getDefine(\\\"GSPLAT_OVERDRAW\\\");\\n\\t\\tif (overdrawEnabled) {\\n\\t\\t\\tthis._material.setParameter(\\\"colorRamp\\\", params.colorRamp);\\n\\t\\t\\tthis._material.setParameter(\\\"colorRampIntensity\\\", params.colorRampIntensity);\\n\\t\\t}\\n\\t\\tif (overdrawEnabled !== wasOverdrawEnabled) {\\n\\t\\t\\tthis._material.setDefine(\\\"GSPLAT_OVERDRAW\\\", overdrawEnabled);\\n\\t\\t\\tif (overdrawEnabled) {\\n\\t\\t\\t\\tthis.originalBlendType = this._material.blendType;\\n\\t\\t\\t\\tthis._material.blendType = BLEND_ADDITIVE;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._material.blendType = this.originalBlendType;\\n\\t\\t\\t}\\n\\t\\t\\tthis._material.update();\\n\\t\\t}\\n\\t}\\n\\tcreateMeshInstance() {\\n\\t\\tconst mesh = GSplatResourceBase.createMesh(this.device);\\n\\t\\tconst meshInstance = new MeshInstance(mesh, this._material);\\n\\t\\tmeshInstance.node = this.node;\\n\\t\\tmeshInstance.setInstancing(true, true);\\n\\t\\tmeshInstance.instancingCount = 0;\\n\\t\\tmeshInstance.pick = false;\\n\\t\\tconst thisCamera = this.cameraNode.camera;\\n\\t\\tmeshInstance.isVisibleFunc = (camera) => {\\n\\t\\t\\tconst renderMode = this.renderMode ?? 0;\\n\\t\\t\\tif (thisCamera.camera === camera && renderMode & GSPLAT_FORWARD) {\\n\\t\\t\\t\\treturn true;\\n\\t\\t\\t}\\n\\t\\t\\tif (camera.node?.name === SHADOWCAMERA_NAME) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t\\t}\\n\\t\\t\\treturn false;\\n\\t\\t};\\n\\t\\treturn meshInstance;\\n\\t}\\n}\\n\\nclass FramePassGSplatComputeLocal extends FramePass {\\n\\trenderer;\\n\\tconstructor(renderer) {\\n\\t\\tsuper(renderer.device);\\n\\t\\tthis.renderer = renderer;\\n\\t\\tthis.name = \\\"FramePassGSplatComputeLocal\\\";\\n\\t}\\n\\tframeUpdate() {\\n\\t\\tconst renderer = this.renderer;\\n\\t\\tconst camera = renderer.cameraNode.camera;\\n\\t\\tconst rt = camera.renderTarget;\\n\\t\\tconst rtWidth = rt ? rt.width : this.device.width;\\n\\t\\tconst rtHeight = rt ? rt.height : this.device.height;\\n\\t\\tconst rect = camera.rect;\\n\\t\\tconst width = Math.floor(rtWidth * rect.z);\\n\\t\\tconst height = Math.floor(rtHeight * rect.w);\\n\\t\\trenderer.resizeOutputTexture(width, height);\\n\\t}\\n\\texecute() {\\n\\t\\tthis.renderer.dispatch();\\n\\t}\\n}\\n\\nconst computeGsplatLocalDispatchPrepSource = `\\n@group(0) @binding(0) var<storage, read> sortElementCount: array<u32>;\\n@group(0) @binding(1) var<storage, read_write> dispatchArgs: array<u32>;\\n@compute @workgroup_size(1)\\nfn main() {\\n\\tlet count = sortElementCount[0];\\n\\tlet maxDim = {MAX_DIM}u;\\n\\tlet countWg = (count + {SPLATS_PER_WG_MINUS_1}u) / {SPLATS_PER_WG}u;\\n\\tif (countWg <= maxDim) {\\n\\t\\tdispatchArgs[0] = countWg;\\n\\t\\tdispatchArgs[1] = 1u;\\n\\t} else {\\n\\t\\tlet y = (countWg + maxDim - 1u) / maxDim;\\n\\t\\tlet x = (countWg + y - 1u) / y;\\n\\t\\tdispatchArgs[0] = x;\\n\\t\\tdispatchArgs[1] = y;\\n\\t}\\n\\tdispatchArgs[2] = 1u;\\n\\tlet placeWg = (count + 255u) / 256u;\\n\\tif (placeWg <= maxDim) {\\n\\t\\tdispatchArgs[3] = placeWg;\\n\\t\\tdispatchArgs[4] = 1u;\\n\\t} else {\\n\\t\\tlet y = (placeWg + maxDim - 1u) / maxDim;\\n\\t\\tlet x = (placeWg + y - 1u) / y;\\n\\t\\tdispatchArgs[3] = x;\\n\\t\\tdispatchArgs[4] = y;\\n\\t}\\n\\tdispatchArgs[5] = 1u;\\n}\\n`;\\n\\nconst computeGsplatLocalDispatchPrepLargeSource = `\\n@group(0) @binding(0) var<storage, read> countersBuffer: array<u32>;\\n@group(0) @binding(1) var<storage, read_write> dispatchArgs: array<u32>;\\n@group(0) @binding(2) var<storage, read> largeSplatIds: array<u32>;\\n@compute @workgroup_size(1)\\nfn main() {\\n\\tlet count = min(countersBuffer[1], arrayLength(&largeSplatIds));\\n\\tlet maxDim = {MAX_DIM}u;\\n\\tif (count <= maxDim) {\\n\\t\\tdispatchArgs[0] = count;\\n\\t\\tdispatchArgs[1] = 1u;\\n\\t} else {\\n\\t\\tlet y = (count + maxDim - 1u) / maxDim;\\n\\t\\tlet x = (count + y - 1u) / y;\\n\\t\\tdispatchArgs[0] = x;\\n\\t\\tdispatchArgs[1] = y;\\n\\t}\\n\\tdispatchArgs[2] = 1u;\\n}\\n`;\\n\\nconst computeGsplatLocalTileCountSource = `\\n#include \\\"gsplatCommonCS\\\"\\n#include \\\"gsplatTileIntersectCS\\\"\\nconst MAX_TILE_ENTRIES: u32 = 0xFFFFu;\\nconst BITMASK_W: u32 = 8u;\\nconst BITMASK_H: u32 = 4u;\\nconst LARGE_AABB_THRESHOLD: u32 = 64u;\\n@group(0) @binding(0) var<storage, read> compactedSplatIds: array<u32>;\\n@group(0) @binding(1) var<storage, read> sortElementCount: array<u32>;\\n@group(0) @binding(2) var<storage, read_write> projCache: array<u32>;\\n@group(0) @binding(3) var<storage, read_write> tileSplatCounts: array<atomic<u32>>;\\nstruct Uniforms {\\n\\tsplatTextureSize: u32,\\n\\tnumTilesX: u32,\\n\\tnumTilesY: u32,\\n\\tviewProj: mat4x4f,\\n\\tviewMatrix: mat4x4f,\\n\\tfocal: f32,\\n\\tviewportWidth: f32,\\n\\tviewportHeight: f32,\\n\\tnearClip: f32,\\n\\tfarClip: f32,\\n\\tminPixelSize: f32,\\n\\tisOrtho: u32,\\n\\texposure: f32,\\n\\talphaClip: f32,\\n\\tminContribution: f32,\\n\\t#ifdef GSPLAT_FISHEYE\\n\\t\\tfisheye_k: f32,\\n\\t\\tfisheye_inv_k: f32,\\n\\t\\tfisheye_projMat00: f32,\\n\\t\\tfisheye_projMat11: f32,\\n\\t#endif\\n}\\n@group(0) @binding(4) var<uniform> uniforms: Uniforms;\\n@group(0) @binding(5) var<storage, read_write> pairBuffer: array<u32>;\\n@group(0) @binding(6) var<storage, read_write> countersBuffer: array<atomic<u32>>;\\n@group(0) @binding(7) var<storage, read_write> splatPairStart: array<u32>;\\n@group(0) @binding(8) var<storage, read_write> splatPairCount: array<u32>;\\n@group(0) @binding(9) var<storage, read_write> largeSplatIds: array<u32>;\\n@group(0) @binding(10) var<storage, read_write> depthBuffer: array<u32>;\\n#include \\\"gsplatComputeSplatCS\\\"\\n#include \\\"gsplatFormatDeclCS\\\"\\n#include \\\"gsplatFormatReadCS\\\"\\n#include \\\"gsplatProjectCommonCS\\\"\\n@compute @workgroup_size(256)\\nfn main(\\n\\t@builtin(global_invocation_id) gid: vec3u,\\n\\t@builtin(num_workgroups) numWorkgroups: vec3u\\n) {\\n\\tlet threadIdx = gid.y * (numWorkgroups.x * 256u) + gid.x;\\n\\tlet numVisible = sortElementCount[0];\\n\\tlet projected = projectSplatCommon(\\n\\t\\tthreadIdx,\\n\\t\\tnumVisible,\\n\\t\\tuniforms.alphaClip,\\n\\t\\tuniforms.minPixelSize,\\n\\t\\tuniforms.minContribution,\\n\\t\\tuniforms.viewMatrix,\\n\\t\\tuniforms.viewProj,\\n\\t\\tuniforms.focal,\\n\\t\\tuniforms.viewportWidth,\\n\\t\\tuniforms.viewportHeight,\\n\\t\\tuniforms.nearClip,\\n\\t\\tuniforms.farClip,\\n\\t\\tuniforms.isOrtho,\\n\\t\\t#ifdef GSPLAT_FISHEYE\\n\\t\\t\\tuniforms.fisheye_k, uniforms.fisheye_inv_k,\\n\\t\\t\\tuniforms.fisheye_projMat00, uniforms.fisheye_projMat11,\\n\\t\\t#endif\\n\\t);\\n\\tif (!projected.valid) {\\n\\t\\tif (threadIdx < numVisible) {\\n\\t\\t\\tprojCache[threadIdx * {CACHE_STRIDE}u + 6u] = 0u;\\n\\t\\t\\tsplatPairStart[threadIdx] = 0u;\\n\\t\\t\\tsplatPairCount[threadIdx] = 0u;\\n\\t\\t}\\n\\t\\treturn;\\n\\t}\\n\\tlet opacity = projected.opacity;\\n\\tlet proj = projected.proj;\\n\\tlet det = proj.a * proj.c - proj.b * proj.b;\\n\\tlet invDet = 1.0 / det;\\n\\tlet cx = 4.0 * proj.c * invDet;\\n\\tlet cy = -4.0 * proj.b * invDet;\\n\\tlet cz = 4.0 * proj.a * invDet;\\n\\tlet base = threadIdx * {CACHE_STRIDE}u;\\n\\tprojCache[base + 0u] = bitcast<u32>(proj.screen.x);\\n\\tprojCache[base + 1u] = bitcast<u32>(proj.screen.y);\\n\\tprojCache[base + 2u] = bitcast<u32>(cx);\\n\\tprojCache[base + 3u] = bitcast<u32>(cy);\\n\\tprojCache[base + 4u] = bitcast<u32>(cz);\\n#ifdef PICK_MODE\\n\\tlet pcIdVal = loadPcId().r;\\n\\tprojCache[base + 5u] = pcIdVal;\\n\\tprojCache[base + 6u] = pack2x16float(vec2f(0.0, opacity));\\n#else\\n\\tlet color = getColor();\\n\\tvar rgb = max(color, vec3f(0.0));\\n\\tprojCache[base + 5u] = pack2x16float(vec2f(rgb.x, rgb.y));\\n\\tprojCache[base + 6u] = pack2x16float(vec2f(rgb.z, opacity));\\n#endif\\n\\tdepthBuffer[threadIdx] = bitcast<u32>(proj.viewDepth);\\n\\tlet screen = proj.screen;\\n\\tlet eval = computeSplatTileEval(screen, cx, cy, cz, half(opacity),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tuniforms.viewportWidth, uniforms.viewportHeight,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tuniforms.alphaClip);\\n\\tlet radiusFactor = eval.radiusFactor;\\n\\tprojCache[base + 7u] = bitcast<u32>(-0.5 * radiusFactor);\\n\\tlet minTileX = max(0i, i32(floor(eval.splatMin.x / f32(TILE_SIZE))));\\n\\tlet maxTileX = min(i32(uniforms.numTilesX) - 1i, i32(floor(eval.splatMax.x / f32(TILE_SIZE))));\\n\\tlet minTileY = max(0i, i32(floor(eval.splatMin.y / f32(TILE_SIZE))));\\n\\tlet maxTileY = min(i32(uniforms.numTilesY) - 1i, i32(floor(eval.splatMax.y / f32(TILE_SIZE))));\\n\\tlet aabbW = u32(maxTileX - minTileX + 1i);\\n\\tvar deferredToLarge = false;\\n\\tif (maxTileX >= minTileX && maxTileY >= minTileY &&\\n\\t\\taabbW * u32(maxTileY - minTileY + 1i) > LARGE_AABB_THRESHOLD) {\\n\\t\\tlet idx = atomicAdd(&countersBuffer[1], 1u);\\n\\t\\tif (idx < arrayLength(&largeSplatIds)) {\\n\\t\\t\\tlargeSplatIds[idx] = threadIdx;\\n\\t\\t\\tdeferredToLarge = true;\\n\\t\\t}\\n\\t}\\n\\tif (deferredToLarge) {\\n\\t\\tsplatPairStart[threadIdx] = 0u;\\n\\t\\tsplatPairCount[threadIdx] = 0u;\\n\\t\\treturn;\\n\\t}\\n\\tvar myPairCount: u32 = 0u;\\n\\tvar bitmask: u32 = 0u;\\n\\tif (minTileX == maxTileX && minTileY == maxTileY) {\\n\\t\\tmyPairCount = 1u;\\n\\t\\tbitmask = 1u;\\n\\t} else {\\n\\t\\tfor (var ty = minTileY; ty <= maxTileY; ty++) {\\n\\t\\t\\tfor (var tx = minTileX; tx <= maxTileX; tx++) {\\n\\t\\t\\t\\tlet tMin = vec2f(f32(tx) * f32(TILE_SIZE), f32(ty) * f32(TILE_SIZE));\\n\\t\\t\\t\\tlet tMax = tMin + vec2f(f32(TILE_SIZE));\\n\\t\\t\\t\\tif (tileIntersectsEllipse(tMin, tMax, screen, cx, cy, cz, radiusFactor)) {\\n\\t\\t\\t\\t\\tmyPairCount++;\\n\\t\\t\\t\\t\\tlet localX = u32(tx - minTileX);\\n\\t\\t\\t\\t\\tlet localY = u32(ty - minTileY);\\n\\t\\t\\t\\t\\tif (localX < BITMASK_W && localY < BITMASK_H) {\\n\\t\\t\\t\\t\\t\\tlet bitIdx = localY * BITMASK_W + localX;\\n\\t\\t\\t\\t\\t\\tbitmask |= (1u << bitIdx);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tif (myPairCount == 0u) {\\n\\t\\tsplatPairStart[threadIdx] = 0u;\\n\\t\\tsplatPairCount[threadIdx] = 0u;\\n\\t\\treturn;\\n\\t}\\n\\tlet pairBase = atomicAdd(&countersBuffer[0], myPairCount);\\n\\tsplatPairStart[threadIdx] = pairBase;\\n\\tsplatPairCount[threadIdx] = myPairCount;\\n\\tvar j: u32 = 0u;\\n\\tfor (var ty = minTileY; ty <= maxTileY; ty++) {\\n\\t\\tfor (var tx = minTileX; tx <= maxTileX; tx++) {\\n\\t\\t\\tlet localX = u32(tx - minTileX);\\n\\t\\t\\tlet localY = u32(ty - minTileY);\\n\\t\\t\\tvar hits: bool;\\n\\t\\t\\tif (localX < BITMASK_W && localY < BITMASK_H) {\\n\\t\\t\\t\\tlet bitIdx = localY * BITMASK_W + localX;\\n\\t\\t\\t\\thits = (bitmask & (1u << bitIdx)) != 0u;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tlet tMin = vec2f(f32(tx) * f32(TILE_SIZE), f32(ty) * f32(TILE_SIZE));\\n\\t\\t\\t\\tlet tMax = tMin + vec2f(f32(TILE_SIZE));\\n\\t\\t\\t\\thits = tileIntersectsEllipse(tMin, tMax, screen, cx, cy, cz, radiusFactor);\\n\\t\\t\\t}\\n\\t\\t\\tif (hits) {\\n\\t\\t\\t\\tlet tileIdx = u32(ty) * uniforms.numTilesX + u32(tx);\\n\\t\\t\\t\\tlet localOff = atomicAdd(&tileSplatCounts[tileIdx], 1u);\\n\\t\\t\\t\\tif (localOff < MAX_TILE_ENTRIES) {\\n\\t\\t\\t\\t\\tpairBuffer[pairBase + j] = (tileIdx << 16u) | (localOff & 0xFFFFu);\\n\\t\\t\\t\\t\\tj++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tif (j != myPairCount) {\\n\\t\\tsplatPairCount[threadIdx] = j;\\n\\t}\\n}\\n`;\\n\\nconst computeGsplatLocalTileCountLargeSource = `\\n#include \\\"gsplatCommonCS\\\"\\n#include \\\"gsplatTileIntersectCS\\\"\\nconst WG_SIZE: u32 = 256u;\\nconst MAX_TILE_ENTRIES: u32 = 0xFFFFu;\\n@group(0) @binding(0) var<storage, read> projCache: array<u32>;\\n@group(0) @binding(1) var<storage, read_write> tileSplatCounts: array<atomic<u32>>;\\n@group(0) @binding(2) var<storage, read_write> pairBuffer: array<u32>;\\n@group(0) @binding(3) var<storage, read_write> countersBuffer: array<atomic<u32>>;\\n@group(0) @binding(4) var<storage, read_write> splatPairStart: array<u32>;\\n@group(0) @binding(5) var<storage, read_write> splatPairCount: array<u32>;\\n@group(0) @binding(6) var<storage, read> largeSplatIds: array<u32>;\\nstruct Uniforms {\\n\\tnumTilesX: u32,\\n\\tnumTilesY: u32,\\n\\tviewportWidth: f32,\\n\\tviewportHeight: f32,\\n\\talphaClip: f32,\\n}\\n@group(0) @binding(7) var<uniform> uniforms: Uniforms;\\nvar<workgroup> wgPairCounts: array<u32, WG_SIZE>;\\nvar<workgroup> wgPairOffsets: array<u32, WG_SIZE>;\\nvar<workgroup> wgBase: u32;\\n@compute @workgroup_size(256)\\nfn main(\\n\\t@builtin(workgroup_id) wgId: vec3u,\\n\\t@builtin(num_workgroups) numWorkgroups: vec3u,\\n\\t@builtin(local_invocation_index) lid: u32\\n) {\\n\\tlet largeSplatIdx = wgId.y * numWorkgroups.x + wgId.x;\\n\\tlet count = min(atomicLoad(&countersBuffer[1]), arrayLength(&largeSplatIds));\\n\\tlet isActive = largeSplatIdx < count;\\n\\tvar threadIdx = u32(0);\\n\\tvar minTileX = 0i;\\n\\tvar maxTileX = 0i;\\n\\tvar minTileY = 0i;\\n\\tvar maxTileY = 0i;\\n\\tvar aabbW = u32(0);\\n\\tvar totalTiles = u32(0);\\n\\tvar screen = vec2f(0.0);\\n\\tvar cx = 0.0f;\\n\\tvar cy = 0.0f;\\n\\tvar cz = 0.0f;\\n\\tvar radiusFactor = 0.0f;\\n\\tif (isActive) {\\n\\t\\tthreadIdx = largeSplatIds[largeSplatIdx];\\n\\t\\tlet cacheBase = threadIdx * {CACHE_STRIDE}u;\\n\\t\\tscreen = vec2f(bitcast<f32>(projCache[cacheBase + 0u]), bitcast<f32>(projCache[cacheBase + 1u]));\\n\\t\\tcx = bitcast<f32>(projCache[cacheBase + 2u]);\\n\\t\\tcy = bitcast<f32>(projCache[cacheBase + 3u]);\\n\\t\\tcz = bitcast<f32>(projCache[cacheBase + 4u]);\\n\\t\\tlet opacity = unpack2x16float(projCache[cacheBase + 6u]).y;\\n\\t\\tlet eval = computeSplatTileEval(screen, cx, cy, cz, half(opacity),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuniforms.viewportWidth, uniforms.viewportHeight,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuniforms.alphaClip);\\n\\t\\tradiusFactor = eval.radiusFactor;\\n\\t\\tminTileX = max(0i, i32(floor(eval.splatMin.x / f32(TILE_SIZE))));\\n\\t\\tmaxTileX = min(i32(uniforms.numTilesX) - 1i, i32(floor(eval.splatMax.x / f32(TILE_SIZE))));\\n\\t\\tminTileY = max(0i, i32(floor(eval.splatMin.y / f32(TILE_SIZE))));\\n\\t\\tmaxTileY = min(i32(uniforms.numTilesY) - 1i, i32(floor(eval.splatMax.y / f32(TILE_SIZE))));\\n\\t\\tif (maxTileX >= minTileX && maxTileY >= minTileY) {\\n\\t\\t\\taabbW = u32(maxTileX - minTileX + 1i);\\n\\t\\t\\ttotalTiles = aabbW * u32(maxTileY - minTileY + 1i);\\n\\t\\t}\\n\\t}\\n\\tvar myHitCount: u32 = 0u;\\n\\tfor (var i = lid; i < totalTiles; i += WG_SIZE) {\\n\\t\\tlet localX = i % aabbW;\\n\\t\\tlet localY = i / aabbW;\\n\\t\\tlet tx = minTileX + i32(localX);\\n\\t\\tlet ty = minTileY + i32(localY);\\n\\t\\tlet tMin = vec2f(f32(tx) * f32(TILE_SIZE), f32(ty) * f32(TILE_SIZE));\\n\\t\\tlet tMax = tMin + vec2f(f32(TILE_SIZE));\\n\\t\\tif (tileIntersectsEllipse(tMin, tMax, screen, cx, cy, cz, radiusFactor)) {\\n\\t\\t\\tmyHitCount++;\\n\\t\\t}\\n\\t}\\n\\twgPairCounts[lid] = myHitCount;\\n\\tworkgroupBarrier();\\n\\tif (lid == 0u && isActive) {\\n\\t\\tvar sum: u32 = 0u;\\n\\t\\tfor (var i: u32 = 0u; i < WG_SIZE; i++) {\\n\\t\\t\\twgPairOffsets[i] = sum;\\n\\t\\t\\tsum += wgPairCounts[i];\\n\\t\\t}\\n\\t\\tif (sum > 0u) {\\n\\t\\t\\twgBase = atomicAdd(&countersBuffer[0], sum);\\n\\t\\t} else {\\n\\t\\t\\twgBase = 0u;\\n\\t\\t}\\n\\t\\tsplatPairStart[threadIdx] = wgBase;\\n\\t\\tsplatPairCount[threadIdx] = sum | 0x80000000u;\\n\\t}\\n\\tworkgroupBarrier();\\n\\tlet myBase = wgBase + wgPairOffsets[lid];\\n\\tvar j: u32 = 0u;\\n\\tfor (var i = lid; i < totalTiles; i += WG_SIZE) {\\n\\t\\tlet localX = i % aabbW;\\n\\t\\tlet localY = i / aabbW;\\n\\t\\tlet tx = minTileX + i32(localX);\\n\\t\\tlet ty = minTileY + i32(localY);\\n\\t\\tlet tMin = vec2f(f32(tx) * f32(TILE_SIZE), f32(ty) * f32(TILE_SIZE));\\n\\t\\tlet tMax = tMin + vec2f(f32(TILE_SIZE));\\n\\t\\tif (tileIntersectsEllipse(tMin, tMax, screen, cx, cy, cz, radiusFactor)) {\\n\\t\\t\\tlet tileIdx = u32(ty) * uniforms.numTilesX + u32(tx);\\n\\t\\t\\tlet localOff = atomicAdd(&tileSplatCounts[tileIdx], 1u);\\n\\t\\t\\tif (localOff < MAX_TILE_ENTRIES) {\\n\\t\\t\\t\\tpairBuffer[myBase + j] = (tileIdx << 16u) | (localOff & 0xFFFFu);\\n\\t\\t\\t\\tj++;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\twgPairCounts[lid] = j;\\n\\tworkgroupBarrier();\\n\\tif (lid == 0u && isActive) {\\n\\t\\tvar actualTotal: u32 = 0u;\\n\\t\\tfor (var i: u32 = 0u; i < WG_SIZE; i++) {\\n\\t\\t\\tactualTotal += wgPairCounts[i];\\n\\t\\t}\\n\\t\\tlet storedCount = splatPairCount[threadIdx] & 0x7FFFFFFFu;\\n\\t\\tif (actualTotal != storedCount) {\\n\\t\\t\\tsplatPairCount[threadIdx] = actualTotal | 0x80000000u;\\n\\t\\t}\\n\\t}\\n}\\n`;\\n\\nconst computeGsplatLocalPlaceEntriesSource = `\\n@group(0) @binding(0) var<storage, read> pairBuffer: array<u32>;\\n@group(0) @binding(1) var<storage, read> splatPairStart: array<u32>;\\n@group(0) @binding(2) var<storage, read> splatPairCount: array<u32>;\\n@group(0) @binding(3) var<storage, read> tileSplatCounts: array<u32>;\\n@group(0) @binding(4) var<storage, read_write> tileEntries: array<u32>;\\n@group(0) @binding(5) var<storage, read> sortElementCount: array<u32>;\\n@compute @workgroup_size(256)\\nfn main(@builtin(global_invocation_id) gid: vec3u, @builtin(num_workgroups) numWorkgroups: vec3u) {\\n\\tlet threadIdx = gid.y * (numWorkgroups.x * 256u) + gid.x;\\n\\tlet numVisible = sortElementCount[0];\\n\\tif (threadIdx >= numVisible) {\\n\\t\\treturn;\\n\\t}\\n\\tlet rawCount = splatPairCount[threadIdx];\\n\\tif (rawCount == 0u || (rawCount & 0x80000000u) != 0u) {\\n\\t\\treturn;\\n\\t}\\n\\tlet count = rawCount;\\n\\tlet start = splatPairStart[threadIdx];\\n\\tlet pairLen = arrayLength(&pairBuffer);\\n\\tlet tileEntriesLen = arrayLength(&tileEntries);\\n\\tfor (var j: u32 = 0u; j < count; j++) {\\n\\t\\tlet pairIdx = start + j;\\n\\t\\tif (pairIdx >= pairLen) { break; }\\n\\t\\tlet packed = pairBuffer[pairIdx];\\n\\t\\tlet tileIdx = packed >> 16u;\\n\\t\\tlet localOff = packed & 0xFFFFu;\\n\\t\\tlet entryIdx = tileSplatCounts[tileIdx] + localOff;\\n\\t\\tif (entryIdx < tileEntriesLen) {\\n\\t\\t\\ttileEntries[entryIdx] = threadIdx;\\n\\t\\t}\\n\\t}\\n}\\n`;\\n\\nconst computeGsplatLocalPlaceEntriesLargeSource = `\\nconst WG_SIZE: u32 = 256u;\\n@group(0) @binding(0) var<storage, read> pairBuffer: array<u32>;\\n@group(0) @binding(1) var<storage, read> splatPairStart: array<u32>;\\n@group(0) @binding(2) var<storage, read> splatPairCount: array<u32>;\\n@group(0) @binding(3) var<storage, read> tileSplatCounts: array<u32>;\\n@group(0) @binding(4) var<storage, read_write> tileEntries: array<u32>;\\n@group(0) @binding(5) var<storage, read> largeSplatIds: array<u32>;\\n@group(0) @binding(6) var<storage, read> countersBuffer: array<u32>;\\n@compute @workgroup_size(256)\\nfn main(\\n\\t@builtin(workgroup_id) wgId: vec3u,\\n\\t@builtin(num_workgroups) numWorkgroups: vec3u,\\n\\t@builtin(local_invocation_index) lid: u32\\n) {\\n\\tlet largeSplatIdx = wgId.y * numWorkgroups.x + wgId.x;\\n\\tlet numLarge = min(countersBuffer[1], arrayLength(&largeSplatIds));\\n\\tif (largeSplatIdx >= numLarge) {\\n\\t\\treturn;\\n\\t}\\n\\tlet threadIdx = largeSplatIds[largeSplatIdx];\\n\\tlet pairCount = splatPairCount[threadIdx] & 0x7FFFFFFFu;\\n\\tif (pairCount == 0u) {\\n\\t\\treturn;\\n\\t}\\n\\tlet start = splatPairStart[threadIdx];\\n\\tlet pairLen = arrayLength(&pairBuffer);\\n\\tlet tileEntriesLen = arrayLength(&tileEntries);\\n\\tfor (var j = lid; j < pairCount; j += WG_SIZE) {\\n\\t\\tlet pairIdx = start + j;\\n\\t\\tif (pairIdx >= pairLen) { break; }\\n\\t\\tlet packed = pairBuffer[pairIdx];\\n\\t\\tlet tileIdx = packed >> 16u;\\n\\t\\tlet localOff = packed & 0xFFFFu;\\n\\t\\tlet entryIdx = tileSplatCounts[tileIdx] + localOff;\\n\\t\\tif (entryIdx < tileEntriesLen) {\\n\\t\\t\\ttileEntries[entryIdx] = threadIdx;\\n\\t\\t}\\n\\t}\\n}\\n`;\\n\\nconst computeGsplatLocalTileSortSource = `\\n#include \\\"gsplatLocalBitonicCS\\\"\\n@group(0) @binding(0) var<storage, read_write> tileEntries: array<u32>;\\n@group(0) @binding(1) var<storage, read> tileSplatCounts: array<u32>;\\n@group(0) @binding(2) var<storage, read> depthBuffer: array<u32>;\\n@group(0) @binding(3) var<storage, read> smallTileList: array<u32>;\\n@group(0) @binding(4) var<storage, read> tileListCounts: array<u32>;\\n@compute @workgroup_size(256)\\nfn main(\\n\\t@builtin(local_invocation_index) localIdx: u32,\\n\\t@builtin(workgroup_id) wid: vec3u,\\n\\t@builtin(num_workgroups) numWorkgroups: vec3u\\n) {\\n\\tlet workgroupIdx = wid.y * numWorkgroups.x + wid.x;\\n\\tif (workgroupIdx >= tileListCounts[0]) {\\n\\t\\treturn;\\n\\t}\\n\\tlet tileIdx = smallTileList[workgroupIdx];\\n\\tlet tStart = tileSplatCounts[tileIdx];\\n\\tlet tEnd = tileSplatCounts[tileIdx + 1u];\\n\\tlet count = tEnd - tStart;\\n\\tbitonicSortRange(localIdx, tStart, count);\\n}\\n`;\\n\\nvar dispatch_core_default = `\\nfn calcDispatch2D(count: u32, maxDim: u32) -> vec2u {\\n\\tif (count <= maxDim) {\\n\\t\\treturn vec2u(count, 1u);\\n\\t}\\n\\tlet y = (count + maxDim - 1u) / maxDim;\\n\\tlet x = (count + y - 1u) / y;\\n\\treturn vec2u(x, y);\\n}\\n`;\\n\\nconst computeGsplatLocalClassifySource = `\\n${indirect_core_default}\\n${dispatch_core_default}\\nconst MAX_TILE_ENTRIES: u32 = 4096u;\\nconst CLASSIFY_WORKGROUP: u32 = 256u;\\n@group(0) @binding(0) var<storage, read> tileSplatCounts: array<u32>;\\n@group(0) @binding(1) var<storage, read_write> smallTileList: array<u32>;\\n@group(0) @binding(2) var<storage, read_write> largeTileList: array<u32>;\\n@group(0) @binding(3) var<storage, read_write> rasterizeTileList: array<u32>;\\n@group(0) @binding(4) var<storage, read_write> tileListCounts: array<atomic<u32>>;\\n@group(0) @binding(5) var<storage, read_write> indirectDispatchArgs: array<u32>;\\n@group(0) @binding(6) var<storage, read_write> largeTileOverflowBases: array<u32>;\\n@group(0) @binding(8) var<storage, read_write> indirectDrawArgs: array<DrawIndirectArgs>;\\nstruct Uniforms {\\n\\tnumTiles: u32,\\n\\tdispatchSlotOffset: u32,\\n\\tbufferCapacity: u32,\\n\\tmaxWorkgroupsPerDim: u32,\\n\\tdrawSlot: u32,\\n}\\n@group(0) @binding(7) var<uniform> uniforms: Uniforms;\\n@compute @workgroup_size(256)\\nfn main(@builtin(local_invocation_index) localIdx: u32) {\\n\\tlet numTiles = uniforms.numTiles;\\n\\tlet totalEntries = tileSplatCounts[numTiles];\\n\\tfor (var i: u32 = localIdx; i < numTiles; i += CLASSIFY_WORKGROUP) {\\n\\t\\tlet tStart = tileSplatCounts[i];\\n\\t\\tlet tEnd = tileSplatCounts[i + 1u];\\n\\t\\tlet count = tEnd - tStart;\\n\\t\\tif (count == 0u || tEnd > uniforms.bufferCapacity) {\\n\\t\\t\\tcontinue;\\n\\t\\t}\\n\\t\\tlet rIdx = atomicAdd(&tileListCounts[2], 1u);\\n\\t\\trasterizeTileList[rIdx] = i;\\n\\t\\tif (count <= MAX_TILE_ENTRIES) {\\n\\t\\t\\tlet sIdx = atomicAdd(&tileListCounts[0], 1u);\\n\\t\\t\\tsmallTileList[sIdx] = i;\\n\\t\\t} else {\\n\\t\\t\\tlet overflowOffset = atomicAdd(&tileListCounts[3], count);\\n\\t\\t\\tlet lIdx = atomicAdd(&tileListCounts[1], 1u);\\n\\t\\t\\tlargeTileList[lIdx] = i;\\n\\t\\t\\tlargeTileOverflowBases[lIdx] = totalEntries + overflowOffset;\\n\\t\\t}\\n\\t}\\n\\tworkgroupBarrier();\\n\\tif (localIdx == 0u) {\\n\\t\\tlet smallCount = atomicLoad(&tileListCounts[0]);\\n\\t\\tlet largeCount = atomicLoad(&tileListCounts[1]);\\n\\t\\tlet rasterizeCount = atomicLoad(&tileListCounts[2]);\\n\\t\\tlet off = uniforms.dispatchSlotOffset;\\n\\t\\tlet maxDim = uniforms.maxWorkgroupsPerDim;\\n\\t\\tlet smallDim = calcDispatch2D(smallCount, maxDim);\\n\\t\\tindirectDispatchArgs[off + 0u] = smallDim.x;\\n\\t\\tindirectDispatchArgs[off + 1u] = smallDim.y;\\n\\t\\tindirectDispatchArgs[off + 2u] = 1u;\\n\\t\\tlet largeDim = calcDispatch2D(largeCount, maxDim);\\n\\t\\tindirectDispatchArgs[off + 3u] = largeDim.x;\\n\\t\\tindirectDispatchArgs[off + 4u] = largeDim.y;\\n\\t\\tindirectDispatchArgs[off + 5u] = 1u;\\n\\t\\tlet rasterDim = calcDispatch2D(rasterizeCount, maxDim);\\n\\t\\tindirectDispatchArgs[off + 6u] = rasterDim.x;\\n\\t\\tindirectDispatchArgs[off + 7u] = rasterDim.y;\\n\\t\\tindirectDispatchArgs[off + 8u] = 1u;\\n\\t\\tindirectDrawArgs[uniforms.drawSlot] = DrawIndirectArgs(rasterizeCount * 6u, 1u, 0u, 0u, 0u);\\n\\t}\\n}\\n`;\\n\\nconst NUM_BUCKETS$1 = 128;\\nconst computeGsplatLocalBucketSortSource = `\\nconst NUM_BUCKETS: u32 = ${NUM_BUCKETS$1}u;\\nconst MAX_CHUNK_SIZE: u32 = 4096u;\\nconst WG_SIZE: u32 = 256u;\\n@group(0) @binding(0) var<storage, read_write> tileEntries: array<u32>;\\n@group(0) @binding(1) var<storage, read> largeTileOverflowBases: array<u32>;\\n@group(0) @binding(2) var<storage, read> tileSplatCounts: array<u32>;\\n@group(0) @binding(3) var<storage, read> depthBuffer: array<u32>;\\n@group(0) @binding(4) var<storage, read> largeTileList: array<u32>;\\n@group(0) @binding(5) var<storage, read_write> chunkRanges: array<u32>;\\n@group(0) @binding(6) var<storage, read_write> totalChunks: array<atomic<u32>>;\\n@group(0) @binding(7) var<storage, read> tileListCounts: array<u32>;\\nstruct Uniforms {\\n\\tbufferCapacity: u32,\\n\\tmaxChunks: u32,\\n}\\n@group(0) @binding(8) var<uniform> uniforms: Uniforms;\\nvar<workgroup> sDepthMin: atomic<u32>;\\nvar<workgroup> sDepthMax: atomic<u32>;\\nvar<workgroup> sBucketCounts: array<atomic<u32>, NUM_BUCKETS>;\\nvar<workgroup> sBucketOffsets: array<u32, NUM_BUCKETS + 1>;\\nvar<workgroup> sBucketCursors: array<atomic<u32>, NUM_BUCKETS>;\\n@compute @workgroup_size(256)\\nfn main(\\n\\t@builtin(local_invocation_index) localIdx: u32,\\n\\t@builtin(workgroup_id) wid: vec3u,\\n\\t@builtin(num_workgroups) numWorkgroups: vec3u\\n) {\\n\\tlet largeTileIdx = wid.y * numWorkgroups.x + wid.x;\\n\\tif (largeTileIdx >= tileListCounts[1]) {\\n\\t\\treturn;\\n\\t}\\n\\tlet tileIdx = largeTileList[largeTileIdx];\\n\\tlet tStart = tileSplatCounts[tileIdx];\\n\\tlet tEnd = tileSplatCounts[tileIdx + 1u];\\n\\tlet count = tEnd - tStart;\\n\\tlet overflowBase = largeTileOverflowBases[largeTileIdx];\\n\\tif (overflowBase + count > uniforms.bufferCapacity) {\\n\\t\\treturn;\\n\\t}\\n\\tif (localIdx == 0u) {\\n\\t\\tatomicStore(&sDepthMin, 0xFFFFFFFFu);\\n\\t\\tatomicStore(&sDepthMax, 0u);\\n\\t}\\n\\tif (localIdx < NUM_BUCKETS) {\\n\\t\\tatomicStore(&sBucketCounts[localIdx], 0u);\\n\\t\\tatomicStore(&sBucketCursors[localIdx], 0u);\\n\\t}\\n\\tworkgroupBarrier();\\n\\tfor (var i: u32 = localIdx; i < count; i += WG_SIZE) {\\n\\t\\tlet entryIdx = tileEntries[tStart + i];\\n\\t\\tlet depthU = depthBuffer[entryIdx];\\n\\t\\tatomicMin(&sDepthMin, depthU);\\n\\t\\tatomicMax(&sDepthMax, depthU);\\n\\t}\\n\\tworkgroupBarrier();\\n\\tlet depthMinU = atomicLoad(&sDepthMin);\\n\\tlet depthMaxU = atomicLoad(&sDepthMax);\\n\\tlet depthMin = bitcast<f32>(depthMinU);\\n\\tlet depthMax = bitcast<f32>(depthMaxU);\\n\\tlet logMin = log(max(depthMin, 1e-6));\\n\\tlet logRange = log(max(depthMax, 1e-6)) - logMin;\\n\\tlet bucketScale = select(f32(NUM_BUCKETS) / logRange, 0.0, logRange < 1e-10);\\n\\tfor (var i: u32 = localIdx; i < count; i += WG_SIZE) {\\n\\t\\tlet entryIdx = tileEntries[tStart + i];\\n\\t\\tlet depth = bitcast<f32>(depthBuffer[entryIdx]);\\n\\t\\tlet bucket = min(u32((log(max(depth, 1e-6)) - logMin) * bucketScale), NUM_BUCKETS - 1u);\\n\\t\\tatomicAdd(&sBucketCounts[bucket], 1u);\\n\\t\\ttileEntries[overflowBase + i] = entryIdx;\\n\\t}\\n\\tworkgroupBarrier();\\n\\tif (localIdx == 0u) {\\n\\t\\tsBucketOffsets[0] = 0u;\\n\\t\\tfor (var b: u32 = 0u; b < NUM_BUCKETS; b++) {\\n\\t\\t\\tsBucketOffsets[b + 1u] = sBucketOffsets[b] + atomicLoad(&sBucketCounts[b]);\\n\\t\\t}\\n\\t}\\n\\tworkgroupBarrier();\\n\\tfor (var i: u32 = localIdx; i < count; i += WG_SIZE) {\\n\\t\\tlet entryIdx = tileEntries[overflowBase + i];\\n\\t\\tlet depth = bitcast<f32>(depthBuffer[entryIdx]);\\n\\t\\tlet bucket = min(u32((log(max(depth, 1e-6)) - logMin) * bucketScale), NUM_BUCKETS - 1u);\\n\\t\\tlet writePos = sBucketOffsets[bucket] + atomicAdd(&sBucketCursors[bucket], 1u);\\n\\t\\ttileEntries[tStart + writePos] = entryIdx;\\n\\t}\\n\\tworkgroupBarrier();\\n\\tif (localIdx == 0u) {\\n\\t\\tvar chunkStart: u32 = 0u;\\n\\t\\tvar currentSize: u32 = 0u;\\n\\t\\tlet maxChunks = uniforms.maxChunks;\\n\\t\\tfor (var b: u32 = 0u; b < NUM_BUCKETS; b++) {\\n\\t\\t\\tvar bRemaining = sBucketOffsets[b + 1u] - sBucketOffsets[b];\\n\\t\\t\\tif (bRemaining == 0u) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\twhile (bRemaining > 0u) {\\n\\t\\t\\t\\tlet space = MAX_CHUNK_SIZE - currentSize;\\n\\t\\t\\t\\tlet take = min(bRemaining, space);\\n\\t\\t\\t\\tcurrentSize += take;\\n\\t\\t\\t\\tbRemaining -= take;\\n\\t\\t\\t\\tif (currentSize == MAX_CHUNK_SIZE) {\\n\\t\\t\\t\\t\\tlet cIdx = atomicAdd(&totalChunks[0], 1u);\\n\\t\\t\\t\\t\\tif (cIdx < maxChunks) {\\n\\t\\t\\t\\t\\t\\tchunkRanges[cIdx * 2u] = tStart + chunkStart;\\n\\t\\t\\t\\t\\t\\tchunkRanges[cIdx * 2u + 1u] = currentSize;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tchunkStart += currentSize;\\n\\t\\t\\t\\t\\tcurrentSize = 0u;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (currentSize > 0u) {\\n\\t\\t\\tlet cIdx = atomicAdd(&totalChunks[0], 1u);\\n\\t\\t\\tif (cIdx < maxChunks) {\\n\\t\\t\\t\\tchunkRanges[cIdx * 2u] = tStart + chunkStart;\\n\\t\\t\\t\\tchunkRanges[cIdx * 2u + 1u] = currentSize;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\n`;\\n\\nconst computeGsplatLocalChunkSortSource = `\\n#include \\\"gsplatLocalBitonicCS\\\"\\n@group(0) @binding(0) var<storage, read_write> tileEntries: array<u32>;\\n@group(0) @binding(1) var<storage, read> depthBuffer: array<u32>;\\n@group(0) @binding(2) var<storage, read> chunkRanges: array<u32>;\\n@group(0) @binding(3) var<storage, read> totalChunks: array<u32>;\\nstruct Uniforms {\\n\\tmaxChunks: u32,\\n}\\n@group(0) @binding(4) var<uniform> uniforms: Uniforms;\\n@compute @workgroup_size(256)\\nfn main(\\n\\t@builtin(local_invocation_index) localIdx: u32,\\n\\t@builtin(workgroup_id) wid: vec3u,\\n\\t@builtin(num_workgroups) numWorkgroups: vec3u\\n) {\\n\\tlet chunkIdx = wid.y * numWorkgroups.x + wid.x;\\n\\tif (chunkIdx >= min(totalChunks[0], uniforms.maxChunks)) {\\n\\t\\treturn;\\n\\t}\\n\\tlet tStart = chunkRanges[chunkIdx * 2u];\\n\\tlet count = chunkRanges[chunkIdx * 2u + 1u];\\n\\tbitonicSortRange(localIdx, tStart, count);\\n}\\n`;\\n\\nconst computeGsplatLocalCopySource = `\\n${dispatch_core_default}\\n@group(0) @binding(0) var<storage, read> totalChunks: array<u32>;\\n@group(0) @binding(1) var<storage, read_write> chunkSortIndirect: array<u32>;\\nstruct Uniforms {\\n\\tmaxChunks: u32,\\n\\tmaxWorkgroupsPerDim: u32,\\n}\\n@group(0) @binding(2) var<uniform> uniforms: Uniforms;\\n@compute @workgroup_size(1)\\nfn main() {\\n\\tlet count = min(totalChunks[0], uniforms.maxChunks);\\n\\tlet dim = calcDispatch2D(count, uniforms.maxWorkgroupsPerDim);\\n\\tchunkSortIndirect[0] = dim.x;\\n\\tchunkSortIndirect[1] = dim.y;\\n\\tchunkSortIndirect[2] = 1u;\\n}\\n`;\\n\\nconst computeGsplatLocalBitonicSource = `\\nconst MAX_TILE_ENTRIES: u32 = 4096u;\\nconst INDEX_BITS: u32 = 12u;\\nconst INDEX_MASK: u32 = 0xFFFu;\\nconst DEPTH_LEVELS: f32 = 1048575.0;\\nconst BITONIC_WG_SIZE: u32 = 256u;\\nvar<workgroup> sData: array<u32, 4096>;\\nvar<workgroup> sDepthMin: atomic<u32>;\\nvar<workgroup> sDepthMax: atomic<u32>;\\nfn insertZeroBit(v: u32, bitPos: u32) -> u32 {\\n\\tlet mask = (1u << bitPos) - 1u;\\n\\treturn ((v >> bitPos) << (bitPos + 1u)) | (v & mask);\\n}\\nfn bitonicSortRange(localIdx: u32, tStart: u32, count: u32) {\\n\\tlet clampedCount = min(count, MAX_TILE_ENTRIES);\\n\\tif (clampedCount <= 1u) {\\n\\t\\treturn;\\n\\t}\\n\\tif (localIdx == 0u) {\\n\\t\\tatomicStore(&sDepthMin, 0xFFFFFFFFu);\\n\\t\\tatomicStore(&sDepthMax, 0u);\\n\\t}\\n\\tvar sortN: u32 = 1u;\\n\\twhile (sortN < clampedCount) {\\n\\t\\tsortN = sortN << 1u;\\n\\t}\\n\\tfor (var i: u32 = localIdx; i < sortN; i += BITONIC_WG_SIZE) {\\n\\t\\tif (i < clampedCount) {\\n\\t\\t\\tlet entryIdx = tileEntries[tStart + i];\\n\\t\\t\\tsData[i] = depthBuffer[entryIdx];\\n\\t\\t} else {\\n\\t\\t\\tsData[i] = 0xFFFFFFFFu;\\n\\t\\t}\\n\\t}\\n\\tworkgroupBarrier();\\n\\tfor (var i: u32 = localIdx; i < clampedCount; i += BITONIC_WG_SIZE) {\\n\\t\\tatomicMin(&sDepthMin, sData[i]);\\n\\t\\tatomicMax(&sDepthMax, sData[i]);\\n\\t}\\n\\tworkgroupBarrier();\\n\\tlet depthMinU = atomicLoad(&sDepthMin);\\n\\tlet depthMaxU = atomicLoad(&sDepthMax);\\n\\tlet depthMin = bitcast<f32>(depthMinU);\\n\\tlet depthMax = bitcast<f32>(depthMaxU);\\n\\tlet logMin = log(max(depthMin, 1e-6));\\n\\tlet logRange = log(max(depthMax, 1e-6)) - logMin;\\n\\tlet invLogRange = select(DEPTH_LEVELS / logRange, 0.0, logRange < 1e-10);\\n\\tfor (var i: u32 = localIdx; i < sortN; i += BITONIC_WG_SIZE) {\\n\\t\\tif (i < clampedCount) {\\n\\t\\t\\tlet depth = bitcast<f32>(sData[i]);\\n\\t\\t\\tlet logDepth = log(max(depth, 1e-6));\\n\\t\\t\\tlet depth20 = min(u32((logDepth - logMin) * invLogRange + 0.5), u32(DEPTH_LEVELS));\\n\\t\\t\\tsData[i] = (depth20 << INDEX_BITS) | i;\\n\\t\\t} else {\\n\\t\\t\\tsData[i] = 0xFFFFFFFFu;\\n\\t\\t}\\n\\t}\\n\\tworkgroupBarrier();\\n\\tfor (var k: u32 = 2u; k <= sortN; k = k << 1u) {\\n\\t\\tfor (var j: u32 = k >> 1u; j > 0u; j = j >> 1u) {\\n\\t\\t\\tlet bitPos = countTrailingZeros(j);\\n\\t\\t\\tlet halfN = sortN >> 1u;\\n\\t\\t\\tfor (var c: u32 = localIdx; c < halfN; c += BITONIC_WG_SIZE) {\\n\\t\\t\\t\\tlet l = insertZeroBit(c, bitPos);\\n\\t\\t\\t\\tlet r = l | j;\\n\\t\\t\\t\\tlet ascending = (l & k) == 0u;\\n\\t\\t\\t\\tlet shouldSwap = select(sData[l] < sData[r], sData[l] > sData[r], ascending);\\n\\t\\t\\t\\tif (shouldSwap) {\\n\\t\\t\\t\\t\\tlet tmp = sData[l]; sData[l] = sData[r]; sData[r] = tmp;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tworkgroupBarrier();\\n\\t\\t}\\n\\t}\\n\\tfor (var i: u32 = localIdx; i < clampedCount; i += BITONIC_WG_SIZE) {\\n\\t\\tlet localIndex = sData[i] & INDEX_MASK;\\n\\t\\tsData[i] = tileEntries[tStart + localIndex];\\n\\t}\\n\\tworkgroupBarrier();\\n\\tfor (var i: u32 = localIdx; i < clampedCount; i += BITONIC_WG_SIZE) {\\n\\t\\ttileEntries[tStart + i] = sData[i];\\n\\t}\\n}\\n`;\\n\\nconst computeGsplatProjectCommonSource = `\\nstruct ProjectedSplatCommon {\\n\\tvalid: bool,\\n\\tsplatId: u32,\\n\\tcenter: vec3f,\\n\\topacity: f32,\\n\\tproj: SplatCov2D\\n}\\nfn invalidProjectedSplatCommon() -> ProjectedSplatCommon {\\n\\tvar cov: SplatCov2D;\\n\\tcov.screen = vec2f(0.0);\\n\\tcov.a = 0.0;\\n\\tcov.b = 0.0;\\n\\tcov.c = 0.0;\\n\\tcov.viewDepth = 0.0;\\n\\tcov.valid = false;\\n\\treturn ProjectedSplatCommon(false, 0u, vec3f(0.0), 0.0, cov);\\n}\\nfn projectSplatCommon(\\n\\tthreadIdx: u32,\\n\\tnumVisible: u32,\\n\\talphaClip: f32,\\n\\tminPixelSize: f32,\\n\\tminContribution: f32,\\n\\tviewMatrix: mat4x4f,\\n\\tviewProj: mat4x4f,\\n\\tfocal: f32,\\n\\tviewportWidth: f32,\\n\\tviewportHeight: f32,\\n\\tnearClip: f32,\\n\\tfarClip: f32,\\n\\tisOrtho: u32,\\n\\t#ifdef GSPLAT_FISHEYE\\n\\t\\tfisheye_k: f32,\\n\\t\\tfisheye_inv_k: f32,\\n\\t\\tfisheye_projMat00: f32,\\n\\t\\tfisheye_projMat11: f32,\\n\\t#endif\\n) -> ProjectedSplatCommon {\\n\\tif (threadIdx >= numVisible) {\\n\\t\\treturn invalidProjectedSplatCommon();\\n\\t}\\n\\tlet splatId = compactedSplatIds[threadIdx];\\n\\tsetSplat(splatId);\\n\\tlet center = getCenter();\\n\\tlet opacity = getOpacity();\\n\\tif (opacity <= alphaClip) {\\n\\t\\treturn invalidProjectedSplatCommon();\\n\\t}\\n\\tlet rotation = half4(getRotation());\\n\\tlet scale = half3(getScale());\\n\\tlet proj = computeSplatCov(\\n\\t\\tcenter, rotation, scale,\\n\\t\\tviewMatrix, viewProj,\\n\\t\\tfocal, viewportWidth, viewportHeight,\\n\\t\\tnearClip, farClip, opacity, minPixelSize,\\n\\t\\tisOrtho, alphaClip, minContribution,\\n\\t\\t#ifdef GSPLAT_FISHEYE\\n\\t\\t\\tfisheye_k, fisheye_inv_k,\\n\\t\\t\\tfisheye_projMat00, fisheye_projMat11,\\n\\t\\t#endif\\n\\t);\\n\\tif (!proj.valid) {\\n\\t\\treturn invalidProjectedSplatCommon();\\n\\t}\\n\\treturn ProjectedSplatCommon(true, splatId, center, opacity, proj);\\n}\\n`;\\n\\nconst computeGsplatCommonSource = `\\n#include \\\"halfTypesCS\\\"\\nconst TILE_SIZE: u32 = 16u;\\nfn quatToMat3(r: half4) -> half3x3 {\\n\\tlet r2: half4 = r + r;\\n\\tlet x: half   = r2.x * r.w;\\n\\tlet y: half4  = r2.y * r;\\n\\tlet z: half4  = r2.z * r;\\n\\tlet w: half   = r2.w * r.w;\\n\\treturn half3x3(\\n\\t\\thalf(1.0) - z.z - w,  y.z + x,\\t\\t\\t  y.w - z.x,\\n\\t\\ty.z - x,\\t\\t\\t  half(1.0) - y.y - w,   z.w + y.x,\\n\\t\\ty.w + z.x,\\t\\t\\tz.w - y.x,\\t\\t\\t half(1.0) - y.y - z.z\\n\\t);\\n}\\nstruct SplatCov2D {\\n\\tscreen: vec2f,\\n\\ta: f32,\\n\\tb: f32,\\n\\tc: f32,\\n\\tviewDepth: f32,\\n\\tvalid: bool,\\n\\t#if GSPLAT_AA\\n\\t\\taaFactor: f32,\\n\\t#endif\\n}\\nfn computeSplatCov(\\n\\tworldCenter: vec3f,\\n\\trotation: half4,\\n\\tscale: half3,\\n\\tviewMatrix: mat4x4f,\\n\\tviewProj: mat4x4f,\\n\\tfocal: f32,\\n\\tviewportWidth: f32,\\n\\tviewportHeight: f32,\\n\\tnearClip: f32,\\n\\tfarClip: f32,\\n\\topacity: f32,\\n\\tminPixelSize: f32,\\n\\tisOrtho: u32,\\n\\talphaClip: f32,\\n\\tminContribution: f32,\\n\\t#ifdef GSPLAT_FISHEYE\\n\\t\\tfisheye_k: f32,\\n\\t\\tfisheye_inv_k: f32,\\n\\t\\tfisheye_projMat00: f32,\\n\\t\\tfisheye_projMat11: f32,\\n\\t#endif\\n) -> SplatCov2D {\\n\\tvar result: SplatCov2D;\\n\\tresult.valid = false;\\n\\tlet viewCenter = (viewMatrix * vec4f(worldCenter, 1.0)).xyz;\\n\\t#ifdef GSPLAT_FISHEYE\\n\\t\\tlet fv = viewCenter;\\n\\t\\tlet r_xy = length(fv.xy);\\n\\t\\tlet neg_z = -fv.z;\\n\\t\\tlet theta = atan2(r_xy, neg_z);\\n\\t\\tlet maxTheta = min(fisheye_k * 1.5707963, 3.13);\\n\\t\\tif (theta > maxTheta - 0.01 || dot(fv, fv) < 0.0001) {\\n\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tlet tk = theta * fisheye_inv_k;\\n\\t\\tlet sin_tk = sin(tk);\\n\\t\\tlet cos_tk = cos(tk);\\n\\t\\tlet g_theta = fisheye_k * sin_tk / cos_tk;\\n\\t\\tlet fisheye_s = select(select(0.0, 1.0 / neg_z, neg_z > 0.0), g_theta / r_xy, r_xy > 1e-4);\\n\\t\\tlet fndc = vec2f(fisheye_projMat00 * fisheye_s * fv.x, fisheye_projMat11 * fisheye_s * fv.y);\\n\\t\\tlet screen = vec2f(\\n\\t\\t\\t(fndc.x * 0.5 + 0.5) * viewportWidth,\\n\\t\\t\\t(fndc.y * 0.5 + 0.5) * viewportHeight\\n\\t\\t);\\n\\t#else\\n\\t\\tif (viewCenter.z > 0.0) {\\n\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tlet clip = viewProj * vec4f(worldCenter, 1.0);\\n\\t\\tlet ndc = clip.xy / clip.w;\\n\\t\\tlet screen = vec2f(\\n\\t\\t\\t(ndc.x * 0.5 + 0.5) * viewportWidth,\\n\\t\\t\\t(ndc.y * 0.5 + 0.5) * viewportHeight\\n\\t\\t);\\n\\t#endif\\n\\tlet rot: half3x3 = quatToMat3(rotation);\\n\\tlet s: vec3f = vec3f(scale);\\n\\tlet M: mat3x3f = transpose(mat3x3f(\\n\\t\\ts.x * vec3f(rot[0]),\\n\\t\\ts.y * vec3f(rot[1]),\\n\\t\\ts.z * vec3f(rot[2])\\n\\t));\\n\\tlet w0 = vec3f(viewMatrix[0].x, viewMatrix[1].x, viewMatrix[2].x);\\n\\tlet w1 = vec3f(viewMatrix[0].y, viewMatrix[1].y, viewMatrix[2].y);\\n\\tlet w2 = vec3f(viewMatrix[0].z, viewMatrix[1].z, viewMatrix[2].z);\\n\\t#ifdef GSPLAT_FISHEYE\\n\\t\\tlet fisheyeFocal = viewportWidth * fisheye_projMat00;\\n\\t\\tlet g_prime = 1.0 / (cos_tk * cos_tk);\\n\\t\\tlet d2 = dot(fv, fv);\\n\\t\\tlet r_sq = max(r_xy * r_xy, 1e-8);\\n\\t\\tlet K_coeff = select(0.0, (g_prime * neg_z / d2 - fisheye_s) / r_sq, r_xy > 1e-4);\\n\\t\\tlet Jxx = fisheyeFocal * (fisheye_s + K_coeff * fv.x * fv.x);\\n\\t\\tlet Jxy = fisheyeFocal * K_coeff * fv.x * fv.y;\\n\\t\\tlet Jyy = fisheyeFocal * (fisheye_s + K_coeff * fv.y * fv.y);\\n\\t\\tlet Jzx = fisheyeFocal * g_prime * fv.x / d2;\\n\\t\\tlet Jzy = fisheyeFocal * g_prime * fv.y / d2;\\n\\t\\tlet tt0 = Jxx * w0 + Jxy * w1 + Jzx * w2;\\n\\t\\tlet tt1 = Jxy * w0 + Jyy * w1 + Jzy * w2;\\n\\t#else\\n\\t\\tlet ortho = isOrtho == 1u;\\n\\t\\tlet v = select(viewCenter.xyz, vec3f(0.0, 0.0, 1.0), ortho);\\n\\t\\tlet vz = select(min(v.z, -0.001), v.z, ortho);\\n\\t\\tlet J1 = focal / vz;\\n\\t\\tlet J2 = -J1 / vz * v.xy;\\n\\t\\tlet tt0 = J1 * w0 + J2.x * w2;\\n\\t\\tlet tt1 = J1 * w1 + J2.y * w2;\\n\\t#endif\\n\\tlet b0 = M * tt0;\\n\\tlet b1 = M * tt1;\\n\\tlet aRaw = dot(b0, b0);\\n\\tlet b = dot(b0, b1);\\n\\tlet cRaw = dot(b1, b1);\\n\\tlet a = aRaw + 0.3;\\n\\tlet c = cRaw + 0.3;\\n\\tlet det = a * c - b * b;\\n\\tif (det <= 0.0) {\\n\\t\\treturn result;\\n\\t}\\n\\t#if GSPLAT_AA\\n\\t\\tlet detOrig = aRaw * cRaw - b * b;\\n\\t\\tresult.aaFactor = sqrt(max(detOrig / det, 0.0));\\n\\t#endif\\n\\tlet totalContribution = opacity * 6.283185 * sqrt(det);\\n\\tif (totalContribution < minContribution) {\\n\\t\\treturn result;\\n\\t}\\n\\tlet radiusFactor = computeRadiusFactor(half(opacity), alphaClip);\\n\\tlet vmin = min(1024.0, min(viewportWidth, viewportHeight));\\n\\tlet maxRadius = vmin;\\n\\tlet radiusXUncapped = sqrt(2.0 * a);\\n\\tlet radiusYUncapped = sqrt(2.0 * c);\\n\\tlet radiusX = min(radiusXUncapped, maxRadius);\\n\\tlet radiusY = min(radiusYUncapped, maxRadius);\\n\\tif (max(radiusX, radiusY) < minPixelSize) {\\n\\t\\treturn result;\\n\\t}\\n\\tif (screen.x + radiusX < 0.0 || screen.x - radiusX > viewportWidth ||\\n\\t\\tscreen.y + radiusY < 0.0 || screen.y - radiusY > viewportHeight) {\\n\\t\\treturn result;\\n\\t}\\n\\tlet capScale = max(1.0, max(radiusXUncapped, radiusYUncapped) / maxRadius);\\n\\tlet invCapScale2 = 1.0 / (capScale * capScale);\\n\\tresult.screen = screen;\\n\\tlet scaledCov = vec3f(a, b, c) * invCapScale2;\\n\\tresult.a = scaledCov.x;\\n\\tresult.b = scaledCov.y;\\n\\tresult.c = scaledCov.z;\\n\\t#ifdef GSPLAT_FISHEYE\\n\\t\\tresult.viewDepth = sqrt(d2);\\n\\t#else\\n\\t\\tresult.viewDepth = -viewCenter.z;\\n\\t#endif\\n\\tresult.valid = true;\\n\\treturn result;\\n}\\n`;\\n\\nconst computeGsplatTileIntersectSource = `\\nstruct SplatTileEval {\\n\\tradiusFactor: f32,\\n\\tsplatMin: vec2f,\\n\\tsplatMax: vec2f,\\n}\\nfn computeRadiusFactor(opacity: half, alphaClip: f32) -> f32 {\\n\\treturn min(8.0, 2.0 * log(f32(opacity) / alphaClip));\\n}\\nfn computeSplatTileEval(\\n\\tscreen: vec2f,\\n\\tcx: f32, cy: f32, cz: f32,\\n\\topacity: half,\\n\\tviewportWidth: f32, viewportHeight: f32,\\n\\talphaClip: f32\\n) -> SplatTileEval {\\n\\tlet K = cx * cz - cy * cy;\\n\\tlet a = 4.0 * cz / K;\\n\\tlet c = 4.0 * cx / K;\\n\\tlet radiusFactor = computeRadiusFactor(opacity, alphaClip);\\n\\tlet vmin = min(1024.0, min(viewportWidth, viewportHeight));\\n\\tlet radius = vec2f(min(sqrt(2.0 * a), vmin), min(sqrt(2.0 * c), vmin));\\n\\tvar result: SplatTileEval;\\n\\tresult.radiusFactor = radiusFactor;\\n\\tresult.splatMin = screen - radius;\\n\\tresult.splatMax = screen + radius;\\n\\treturn result;\\n}\\nfn segmentIntersectsEllipse(a: f32, b: f32, c: f32, d: f32, l: f32, r: f32) -> bool {\\n\\tlet delta = b * b - 4.0 * a * c;\\n\\tlet t1 = (l - d) * (2.0 * a) + b;\\n\\tlet t2 = (r - d) * (2.0 * a) + b;\\n\\treturn delta >= 0.0 && (t1 <= 0.0 || t1 * t1 <= delta) && (t2 >= 0.0 || t2 * t2 <= delta);\\n}\\nfn tileIntersectsEllipse(\\n\\ttileMin: vec2f, tileMax: vec2f, center: vec2f,\\n\\tcx: f32, cy: f32, cz: f32,\\n\\tradiusFactor: f32\\n) -> bool {\\n\\tif (center.x >= tileMin.x && center.x <= tileMax.x &&\\n\\t\\tcenter.y >= tileMin.y && center.y <= tileMax.y) {\\n\\t\\treturn true;\\n\\t}\\n\\tlet w = radiusFactor;\\n\\tvar dx: f32;\\n\\tif (center.x * 2.0 < tileMin.x + tileMax.x) {\\n\\t\\tdx = center.x - tileMin.x;\\n\\t} else {\\n\\t\\tdx = center.x - tileMax.x;\\n\\t}\\n\\tif (segmentIntersectsEllipse(cz, -2.0 * cy * dx, cx * dx * dx - w, center.y, tileMin.y, tileMax.y)) {\\n\\t\\treturn true;\\n\\t}\\n\\tvar dy: f32;\\n\\tif (center.y * 2.0 < tileMin.y + tileMax.y) {\\n\\t\\tdy = center.y - tileMin.y;\\n\\t} else {\\n\\t\\tdy = center.y - tileMax.y;\\n\\t}\\n\\tif (segmentIntersectsEllipse(cx, -2.0 * cy * dy, cz * dy * dy - w, center.x, tileMin.x, tileMax.x)) {\\n\\t\\treturn true;\\n\\t}\\n\\treturn false;\\n}\\n`;\\n\\nclass GSplatTileComposite {\\n\\tdevice;\\n\\t_material;\\n\\t_mesh;\\n\\t_meshInstance;\\n\\t_pickMaterial = null;\\n\\t_pickMeshInstance = null;\\n\\t_node;\\n\\tconstructor(device, node, isVisibleFunc) {\\n\\t\\tthis.device = device;\\n\\t\\tthis._node = node;\\n\\t\\tthis._material = new ShaderMaterial({\\n\\t\\t\\tuniqueName: \\\"GSplatTileComposite\\\",\\n\\t\\t\\tvertexWGSL: '#include \\\"gsplatTileCompositeVS\\\"',\\n\\t\\t\\tfragmentWGSL: '#include \\\"gsplatTileCompositePS\\\"'\\n\\t\\t});\\n\\t\\tthis._material.blendType = BLEND_PREMULTIPLIED;\\n\\t\\tthis._material.cull = CULLFACE_NONE;\\n\\t\\tthis._material.depthWrite = false;\\n\\t\\tthis._material.update();\\n\\t\\tthis._mesh = new Mesh(device);\\n\\t\\tthis._mesh.primitive[0].type = PRIMITIVE_TRIANGLES;\\n\\t\\tthis._mesh.primitive[0].base = 0;\\n\\t\\tthis._mesh.primitive[0].count = 0;\\n\\t\\tthis._mesh.primitive[0].indexed = false;\\n\\t\\tthis._meshInstance = new MeshInstance(this._mesh, this._material);\\n\\t\\tthis._meshInstance.node = node;\\n\\t\\tthis._meshInstance.instancingCount = 1;\\n\\t\\tthis._meshInstance.isVisibleFunc = isVisibleFunc;\\n\\t\\tthis._meshInstance.pick = false;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._material.destroy();\\n\\t\\tthis._mesh.destroy();\\n\\t\\tthis._meshInstance.destroy();\\n\\t\\tthis._pickMaterial?.destroy();\\n\\t\\tthis._pickMeshInstance?.destroy();\\n\\t}\\n\\tget material() {\\n\\t\\treturn this._material;\\n\\t}\\n\\tget meshInstance() {\\n\\t\\treturn this._meshInstance;\\n\\t}\\n\\tupdate(drawSlot, outputTexture, rasterizeTileList, numTilesX, screenWidth, screenHeight) {\\n\\t\\tthis._meshInstance.setIndirect(null, drawSlot, 1);\\n\\t\\tthis._material.setParameter(\\\"source\\\", outputTexture);\\n\\t\\tthis._material.setParameter(\\\"rasterizeTileList\\\", rasterizeTileList);\\n\\t\\tthis._material.setParameter(\\\"numTilesX\\\", numTilesX);\\n\\t\\tthis._material.setParameter(\\\"screenWidth\\\", screenWidth);\\n\\t\\tthis._material.setParameter(\\\"screenHeight\\\", screenHeight);\\n\\t}\\n\\tprepareForPicking(drawSlot, pickIdTexture, pickDepthTexture, rasterizeTileList, numTilesX, screenWidth, screenHeight) {\\n\\t\\tif (!this._pickMaterial) {\\n\\t\\t\\tthis._pickMaterial = new ShaderMaterial({\\n\\t\\t\\t\\tuniqueName: \\\"GSplatTileCompositePick\\\",\\n\\t\\t\\t\\tvertexWGSL: '#include \\\"gsplatTileCompositeVS\\\"',\\n\\t\\t\\t\\tfragmentWGSL: '#include \\\"gsplatTileCompositePS\\\"'\\n\\t\\t\\t});\\n\\t\\t\\tthis._pickMaterial.setDefine(\\\"PICK_MODE\\\", true);\\n\\t\\t\\tthis._pickMaterial.cull = CULLFACE_NONE;\\n\\t\\t\\tthis._pickMaterial.depthWrite = false;\\n\\t\\t\\tthis._pickMaterial.update();\\n\\t\\t\\tthis._pickMeshInstance = new MeshInstance(this._mesh, this._pickMaterial);\\n\\t\\t\\tthis._pickMeshInstance.node = this._node;\\n\\t\\t\\tthis._pickMeshInstance.instancingCount = 1;\\n\\t\\t}\\n\\t\\tconst pickMI = this._pickMeshInstance;\\n\\t\\tconst pickMat = this._pickMaterial;\\n\\t\\tpickMI.setIndirect(null, drawSlot, 1);\\n\\t\\tpickMat.setParameter(\\\"pickIdTexture\\\", pickIdTexture);\\n\\t\\tpickMat.setParameter(\\\"pickDepthTexture\\\", pickDepthTexture);\\n\\t\\tpickMat.setParameter(\\\"rasterizeTileList\\\", rasterizeTileList);\\n\\t\\tpickMat.setParameter(\\\"numTilesX\\\", numTilesX);\\n\\t\\tpickMat.setParameter(\\\"screenWidth\\\", screenWidth);\\n\\t\\tpickMat.setParameter(\\\"screenHeight\\\", screenHeight);\\n\\t\\treturn pickMI;\\n\\t}\\n}\\n\\nconst computeGsplatLocalRasterizeSource = `\\n#include \\\"halfTypesCS\\\"\\n#ifndef PICK_MODE\\n\\t#include \\\"decodePS\\\"\\n\\t#if FOG != NONE\\n\\t\\t#include \\\"fogMathPS\\\"\\n\\t\\t#include \\\"gammaPS\\\"\\n\\t#endif\\n#endif\\nconst BATCH_SIZE: u32 = 64u;\\nconst ALPHA_THRESHOLD: half = half(1.0) / half(255.0);\\nconst EXP4: half = exp(half(-4.0));\\nconst INV_EXP4: half = half(1.0) / (half(1.0) - EXP4);\\nstruct Uniforms {\\n\\tscreenWidth: u32,\\n\\tscreenHeight: u32,\\n\\tnumTilesX: u32,\\n\\tnearClip: f32,\\n\\tfarClip: f32,\\n\\talphaClip: f32,\\n\\t#if FOG != NONE\\n\\t\\tfog_color: vec3f,\\n\\t\\tfog_start: f32,\\n\\t\\tfog_end: f32,\\n\\t\\tfog_density: f32,\\n\\t#endif\\n}\\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\\n@group(0) @binding(1) var<storage, read> tileEntries: array<u32>;\\n@group(0) @binding(2) var<storage, read> tileSplatCounts: array<u32>;\\n@group(0) @binding(3) var<storage, read> projCache: array<u32>;\\n@group(0) @binding(4) var<storage, read> rasterizeTileList: array<u32>;\\n@group(0) @binding(5) var<storage, read> tileListCounts: array<u32>;\\n@group(0) @binding(6) var<storage, read> depthBuffer: array<u32>;\\n#ifdef PICK_MODE\\n\\t@group(0) @binding(7) var pickIdTexture: texture_storage_2d<r32uint, write>;\\n\\t@group(0) @binding(8) var pickDepthTexture: texture_storage_2d<rgba16float, write>;\\n#else\\n\\t@group(0) @binding(7) var outputTexture: texture_storage_2d<rgba16float, write>;\\n\\t#ifdef DEPTH_TEST\\n\\t\\t@group(0) @binding(8) var sceneDepthMap: texture_2d<f32>;\\n\\t#endif\\n#endif\\nvar<workgroup> sharedCenterScreen: array<vec2f, 64>;\\nvar<workgroup> sharedCoeffs: array<vec3f, 64>;\\nvar<workgroup> sharedPowerCutoff: array<f32, 64>;\\n#ifdef HEATMAP_MODE\\n\\tvar<workgroup> sharedHeatCount: atomic<u32>;\\n#endif\\n#ifdef PICK_MODE\\n\\tvar<workgroup> sharedOpacity: array<half, 64>;\\n\\tvar<workgroup> sharedPickId: array<u32, 64>;\\n\\tvar<workgroup> sharedViewDepth: array<f32, 64>;\\n#else\\n\\tvar<workgroup> sharedColor: array<half4, 64>;\\n\\t#ifdef DEPTH_TEST\\n\\t\\tvar<workgroup> sharedViewDepth: array<f32, 64>;\\n\\t#endif\\n#endif\\n#ifdef PICK_MODE\\nfn evalSplatPick(pixelCoord: vec2f, center: vec2f, coeffX: f32, coeffY: f32, coeffXY: f32,\\n\\t\\t\\t\\t opacity: half, pickId: u32, viewDepth: f32, alphaClip: half,\\n\\t\\t\\t\\t bestPickId: ptr<function, u32>, depthAccum: ptr<function, f32>,\\n\\t\\t\\t\\t weightAccum: ptr<function, f32>, T: ptr<function, half>) {\\n\\tlet dx = pixelCoord - center;\\n\\tlet power = coeffX * dx.x * dx.x + coeffXY * dx.x * dx.y + coeffY * dx.y * dx.y;\\n\\tlet gauss = (half(exp(power)) - EXP4) * INV_EXP4;\\n\\tlet alpha = half(min(half(0.99), opacity * gauss));\\n\\tlet newT = *T * (half(1.0) - alpha);\\n\\tlet visible = power > -4.0 && alpha > ALPHA_THRESHOLD && *T >= ALPHA_THRESHOLD;\\n\\tif (!visible) { return; }\\n\\tif (alpha >= alphaClip) {\\n\\t\\tif (*bestPickId == 0xFFFFFFFFu) {\\n\\t\\t\\t*bestPickId = pickId;\\n\\t\\t}\\n\\t\\tlet normalizedDepth = saturate((viewDepth - uniforms.nearClip) / (uniforms.farClip - uniforms.nearClip));\\n\\t\\tlet w = f32(alpha) * f32(*T);\\n\\t\\t*depthAccum += w * normalizedDepth;\\n\\t\\t*weightAccum += w;\\n\\t}\\n\\t*T = newT;\\n}\\n#endif\\n#ifdef HEATMAP_MODE\\nfn heatmapColor(v: f32) -> vec3f {\\n\\tlet t = saturate(v / 2000.0);\\n\\tif (t < 0.2) {\\n\\t\\treturn mix(vec3f(0.0, 0.0, 1.0), vec3f(0.0, 1.0, 1.0), t * 5.0);\\n\\t} else if (t < 0.4) {\\n\\t\\treturn mix(vec3f(0.0, 1.0, 1.0), vec3f(1.0, 1.0, 0.0), (t - 0.2) * 5.0);\\n\\t} else if (t < 0.6) {\\n\\t\\treturn mix(vec3f(1.0, 1.0, 0.0), vec3f(1.0, 0.0, 0.0), (t - 0.4) * 5.0);\\n\\t}\\n\\treturn mix(vec3f(1.0, 0.0, 0.0), vec3f(0.15, 0.0, 0.0), (t - 0.6) * 2.5);\\n}\\n#endif\\n@compute @workgroup_size(8, 8)\\nfn main(\\n\\t@builtin(local_invocation_id) lid: vec3u,\\n\\t@builtin(local_invocation_index) localIdx: u32,\\n\\t@builtin(workgroup_id) wid: vec3u,\\n\\t@builtin(num_workgroups) numWorkgroups: vec3u\\n) {\\n\\tlet workgroupIdx = wid.y * numWorkgroups.x + wid.x;\\n\\tif (workgroupIdx >= tileListCounts[2]) {\\n\\t\\treturn;\\n\\t}\\n\\tlet tileIdx = rasterizeTileList[workgroupIdx];\\n\\tlet tileX = tileIdx % uniforms.numTilesX;\\n\\tlet tileY = tileIdx / uniforms.numTilesX;\\n\\tlet tStart = tileSplatCounts[tileIdx];\\n\\tlet tEnd = tileSplatCounts[tileIdx + 1u];\\n\\tlet basePixel = vec2u(tileX * 16u + lid.x * 2u, tileY * 16u + lid.y * 2u);\\n\\tlet p00 = vec2f(f32(basePixel.x) + 0.5, f32(basePixel.y) + 0.5);\\n\\tlet p10 = p00 + vec2f(1.0, 0.0);\\n\\tlet p01 = p00 + vec2f(0.0, 1.0);\\n\\tlet p11 = p00 + vec2f(1.0, 1.0);\\n\\t#ifdef PICK_MODE\\n\\t\\tvar T00: half = half(1.0); var T10: half = half(1.0);\\n\\t\\tvar T01: half = half(1.0); var T11: half = half(1.0);\\n\\t\\tvar pickId00: u32 = 0xFFFFFFFFu; var pickId10: u32 = 0xFFFFFFFFu;\\n\\t\\tvar pickId01: u32 = 0xFFFFFFFFu; var pickId11: u32 = 0xFFFFFFFFu;\\n\\t\\tvar dAcc00: f32 = 0.0; var dAcc10: f32 = 0.0;\\n\\t\\tvar dAcc01: f32 = 0.0; var dAcc11: f32 = 0.0;\\n\\t\\tvar wAcc00: f32 = 0.0; var wAcc10: f32 = 0.0;\\n\\t\\tvar wAcc01: f32 = 0.0; var wAcc11: f32 = 0.0;\\n\\t\\tlet clipH = half(uniforms.alphaClip);\\n\\t#else\\n\\t\\tvar T = half4(1.0);\\n\\t\\tvar c00 = half3(0.0); var c10 = half3(0.0);\\n\\t\\tvar c01 = half3(0.0); var c11 = half3(0.0);\\n\\t\\t#ifdef DEPTH_TEST\\n\\t\\t\\tvar sceneDepth = vec4f(1e20);\\n\\t\\t\\tlet depthY0 = uniforms.screenHeight - 1u - basePixel.y;\\n\\t\\t\\tlet depthY1 = depthY0 - 1u;\\n\\t\\t\\tif (basePixel.x < uniforms.screenWidth && basePixel.y < uniforms.screenHeight) {\\n\\t\\t\\t\\tsceneDepth.x = textureLoad(sceneDepthMap, vec2i(vec2u(basePixel.x, depthY0)), 0).r;\\n\\t\\t\\t}\\n\\t\\t\\tif (basePixel.x + 1u < uniforms.screenWidth && basePixel.y < uniforms.screenHeight) {\\n\\t\\t\\t\\tsceneDepth.y = textureLoad(sceneDepthMap, vec2i(vec2u(basePixel.x + 1u, depthY0)), 0).r;\\n\\t\\t\\t}\\n\\t\\t\\tif (basePixel.x < uniforms.screenWidth && basePixel.y + 1u < uniforms.screenHeight) {\\n\\t\\t\\t\\tsceneDepth.z = textureLoad(sceneDepthMap, vec2i(vec2u(basePixel.x, depthY1)), 0).r;\\n\\t\\t\\t}\\n\\t\\t\\tif (basePixel.x + 1u < uniforms.screenWidth && basePixel.y + 1u < uniforms.screenHeight) {\\n\\t\\t\\t\\tsceneDepth.w = textureLoad(sceneDepthMap, vec2i(vec2u(basePixel.x + 1u, depthY1)), 0).r;\\n\\t\\t\\t}\\n\\t\\t#endif\\n\\t#endif\\n\\tlet tileCount = tEnd - tStart;\\n\\t#ifdef HEATMAP_MODE\\n\\t\\tif (localIdx == 0u) { atomicStore(&sharedHeatCount, 0u); }\\n\\t\\tworkgroupBarrier();\\n\\t\\tvar processedCount: u32 = 0u;\\n\\t#endif\\n\\tlet numBatches = (tileCount + BATCH_SIZE - 1u) / BATCH_SIZE;\\n\\tvar threadDone = false;\\n\\tfor (var batch: u32 = 0u; batch < numBatches; batch++) {\\n\\t\\tlet batchOffset = batch * BATCH_SIZE + localIdx;\\n\\t\\tif (batchOffset < tileCount) {\\n\\t\\t\\tlet cacheIdx = tileEntries[tStart + batchOffset];\\n\\t\\t\\tlet base = cacheIdx * {CACHE_STRIDE}u;\\n\\t\\t\\tsharedCenterScreen[localIdx] = vec2f(\\n\\t\\t\\t\\tbitcast<f32>(projCache[base + 0u]),\\n\\t\\t\\t\\tbitcast<f32>(projCache[base + 1u])\\n\\t\\t\\t);\\n\\t\\t\\tlet cx = bitcast<f32>(projCache[base + 2u]);\\n\\t\\t\\tlet cy = bitcast<f32>(projCache[base + 3u]);\\n\\t\\t\\tlet cz = bitcast<f32>(projCache[base + 4u]);\\n\\t\\t\\tsharedCoeffs[localIdx] = vec3f(cx * -0.5, cz * -0.5, -cy);\\n\\t\\t\\tsharedPowerCutoff[localIdx] = bitcast<f32>(projCache[base + 7u]);\\n\\t\\t\\t#ifdef PICK_MODE\\n\\t\\t\\t\\tsharedPickId[localIdx] = projCache[base + 5u];\\n\\t\\t\\t\\tsharedOpacity[localIdx] = half(unpack2x16float(projCache[base + 6u]).y);\\n\\t\\t\\t\\tsharedViewDepth[localIdx] = bitcast<f32>(depthBuffer[cacheIdx]);\\n\\t\\t\\t#else\\n\\t\\t\\t\\tlet rg = unpack2x16float(projCache[base + 5u]);\\n\\t\\t\\t\\tlet ba = unpack2x16float(projCache[base + 6u]);\\n\\t\\t\\t\\t#if FOG != NONE\\n\\t\\t\\t\\t\\tlet viewDepth = bitcast<f32>(depthBuffer[cacheIdx]);\\n\\t\\t\\t\\t\\t#if (FOG == LINEAR)\\n\\t\\t\\t\\t\\t\\tlet fogFactor = evaluateFogFactorLinear(viewDepth, uniforms.fog_start, uniforms.fog_end);\\n\\t\\t\\t\\t\\t#elif (FOG == EXP)\\n\\t\\t\\t\\t\\t\\tlet fogFactor = evaluateFogFactorExp(viewDepth, uniforms.fog_density);\\n\\t\\t\\t\\t\\t#elif (FOG == EXP2)\\n\\t\\t\\t\\t\\t\\tlet fogFactor = evaluateFogFactorExp2(viewDepth, uniforms.fog_density);\\n\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\tvar foggedColor = decodeGamma3(vec3f(rg.x, rg.y, ba.x));\\n\\t\\t\\t\\t\\tfoggedColor = mix(uniforms.fog_color, foggedColor, fogFactor);\\n\\t\\t\\t\\t\\tsharedColor[localIdx] = half4(half3(gammaCorrectOutput(foggedColor)), half(ba.y));\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\tsharedColor[localIdx] = half4(half(rg.x), half(rg.y), half(ba.x), half(ba.y));\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t#ifdef DEPTH_TEST\\n\\t\\t\\t\\t\\tsharedViewDepth[localIdx] = bitcast<f32>(depthBuffer[cacheIdx]);\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t#endif\\n\\t\\t}\\n\\t\\tworkgroupBarrier();\\n\\t\\tif (!threadDone) {\\n\\t\\t\\tlet batchCount = min(BATCH_SIZE, tileCount - batch * BATCH_SIZE);\\n\\t\\t\\tfor (var i: u32 = 0u; i < batchCount; i++) {\\n\\t\\t\\t\\tlet center = sharedCenterScreen[i];\\n\\t\\t\\t\\tlet coeffs = sharedCoeffs[i];\\n\\t\\t\\t\\t#ifdef PICK_MODE\\n\\t\\t\\t\\t\\tlet splatOpacity = sharedOpacity[i];\\n\\t\\t\\t\\t\\tlet splatPickId = sharedPickId[i];\\n\\t\\t\\t\\t\\tlet splatDepth = sharedViewDepth[i];\\n\\t\\t\\t\\t\\tlet d = p00 - center;\\n\\t\\t\\t\\t\\tlet dxV = vec4f(d.x, d.x + 1.0, d.x, d.x + 1.0);\\n\\t\\t\\t\\t\\tlet dyV = vec4f(d.y, d.y, d.y + 1.0, d.y + 1.0);\\n\\t\\t\\t\\t\\tlet power4 = coeffs.x * dxV * dxV + coeffs.z * dxV * dyV + coeffs.y * dyV * dyV;\\n\\t\\t\\t\\t\\tif (all(power4 <= vec4f(sharedPowerCutoff[i]))) {\\n\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tevalSplatPick(p00, center, coeffs.x, coeffs.y, coeffs.z, splatOpacity, splatPickId, splatDepth, clipH, &pickId00, &dAcc00, &wAcc00, &T00);\\n\\t\\t\\t\\t\\tevalSplatPick(p10, center, coeffs.x, coeffs.y, coeffs.z, splatOpacity, splatPickId, splatDepth, clipH, &pickId10, &dAcc10, &wAcc10, &T10);\\n\\t\\t\\t\\t\\tevalSplatPick(p01, center, coeffs.x, coeffs.y, coeffs.z, splatOpacity, splatPickId, splatDepth, clipH, &pickId01, &dAcc01, &wAcc01, &T01);\\n\\t\\t\\t\\t\\tevalSplatPick(p11, center, coeffs.x, coeffs.y, coeffs.z, splatOpacity, splatPickId, splatDepth, clipH, &pickId11, &dAcc11, &wAcc11, &T11);\\n\\t\\t\\t\\t\\tif (all(vec4<half>(T00, T10, T01, T11) < half4(ALPHA_THRESHOLD))) {\\n\\t\\t\\t\\t\\t\\tthreadDone = true;\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\tlet splatColor = sharedColor[i];\\n\\t\\t\\t\\t\\t#ifdef DEPTH_TEST\\n\\t\\t\\t\\t\\t\\tlet splatDepth = sharedViewDepth[i];\\n\\t\\t\\t\\t\\t\\tif (all(vec4f(splatDepth) > sceneDepth)) {\\n\\t\\t\\t\\t\\t\\t\\tthreadDone = true;\\n\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\tlet d = p00 - center;\\n\\t\\t\\t\\t\\tlet dxV = vec4f(d.x, d.x + 1.0, d.x, d.x + 1.0);\\n\\t\\t\\t\\t\\tlet dyV = vec4f(d.y, d.y, d.y + 1.0, d.y + 1.0);\\n\\t\\t\\t\\t\\tlet power4 = coeffs.x * dxV * dxV + coeffs.z * dxV * dyV + coeffs.y * dyV * dyV;\\n\\t\\t\\t\\t\\tif (all(power4 <= vec4f(sharedPowerCutoff[i]))) {\\n\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tlet gauss4 = (half4(exp(power4)) - half4(EXP4)) * half4(INV_EXP4);\\n\\t\\t\\t\\t\\tlet alpha4 = min(half4(0.99), half4(splatColor.a) * gauss4);\\n\\t\\t\\t\\t\\tlet newT = T * (half4(1.0) - alpha4);\\n\\t\\t\\t\\t\\tvar valid = (power4 > vec4f(-4.0)) & (alpha4 > half4(ALPHA_THRESHOLD)) & (T >= half4(ALPHA_THRESHOLD));\\n\\t\\t\\t\\t\\t#ifdef DEPTH_TEST\\n\\t\\t\\t\\t\\t\\tvalid = valid & (vec4f(splatDepth) <= sceneDepth);\\n\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\tlet weight = alpha4 * T * select(half4(0.0), half4(1.0), valid);\\n\\t\\t\\t\\t\\tc00 += splatColor.rgb * weight.x;\\n\\t\\t\\t\\t\\tc10 += splatColor.rgb * weight.y;\\n\\t\\t\\t\\t\\tc01 += splatColor.rgb * weight.z;\\n\\t\\t\\t\\t\\tc11 += splatColor.rgb * weight.w;\\n\\t\\t\\t\\t\\tT = select(T, newT, valid);\\n\\t\\t\\t\\t\\t#ifdef HEATMAP_MODE\\n\\t\\t\\t\\t\\t\\tprocessedCount += 1u;\\n\\t\\t\\t\\t\\t#endif\\n\\t\\t\\t\\t\\tif (all(T < half4(ALPHA_THRESHOLD))) {\\n\\t\\t\\t\\t\\t\\tthreadDone = true;\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t#endif\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tworkgroupBarrier();\\n\\t}\\n\\t#ifdef HEATMAP_MODE\\n\\t\\tatomicAdd(&sharedHeatCount, processedCount);\\n\\t\\tworkgroupBarrier();\\n\\t\\tlet avgCount = f32(atomicLoad(&sharedHeatCount)) / 64.0;\\n\\t\\tlet heatColor = vec4f(heatmapColor(avgCount), 1.0);\\n\\t\\tif (basePixel.x < uniforms.screenWidth && basePixel.y < uniforms.screenHeight) {\\n\\t\\t\\ttextureStore(outputTexture, basePixel, heatColor);\\n\\t\\t}\\n\\t\\tif (basePixel.x + 1u < uniforms.screenWidth && basePixel.y < uniforms.screenHeight) {\\n\\t\\t\\ttextureStore(outputTexture, vec2u(basePixel.x + 1u, basePixel.y), heatColor);\\n\\t\\t}\\n\\t\\tif (basePixel.x < uniforms.screenWidth && basePixel.y + 1u < uniforms.screenHeight) {\\n\\t\\t\\ttextureStore(outputTexture, vec2u(basePixel.x, basePixel.y + 1u), heatColor);\\n\\t\\t}\\n\\t\\tif (basePixel.x + 1u < uniforms.screenWidth && basePixel.y + 1u < uniforms.screenHeight) {\\n\\t\\t\\ttextureStore(outputTexture, vec2u(basePixel.x + 1u, basePixel.y + 1u), heatColor);\\n\\t\\t}\\n\\t#else\\n\\t\\tif (basePixel.x < uniforms.screenWidth && basePixel.y < uniforms.screenHeight) {\\n\\t\\t\\t#ifdef PICK_MODE\\n\\t\\t\\t\\ttextureStore(pickIdTexture, basePixel, vec4u(pickId00, 0u, 0u, 0u));\\n\\t\\t\\t\\ttextureStore(pickDepthTexture, basePixel, vec4f(dAcc00, wAcc00, 0.0, 0.0));\\n\\t\\t\\t#else\\n\\t\\t\\t\\ttextureStore(outputTexture, basePixel, vec4f(decodeGamma3(vec3f(c00)), f32(half(1.0) - T.x)));\\n\\t\\t\\t#endif\\n\\t\\t}\\n\\t\\tif (basePixel.x + 1u < uniforms.screenWidth && basePixel.y < uniforms.screenHeight) {\\n\\t\\t\\tlet px10 = vec2u(basePixel.x + 1u, basePixel.y);\\n\\t\\t\\t#ifdef PICK_MODE\\n\\t\\t\\t\\ttextureStore(pickIdTexture, px10, vec4u(pickId10, 0u, 0u, 0u));\\n\\t\\t\\t\\ttextureStore(pickDepthTexture, px10, vec4f(dAcc10, wAcc10, 0.0, 0.0));\\n\\t\\t\\t#else\\n\\t\\t\\t\\ttextureStore(outputTexture, px10, vec4f(decodeGamma3(vec3f(c10)), f32(half(1.0) - T.y)));\\n\\t\\t\\t#endif\\n\\t\\t}\\n\\t\\tif (basePixel.x < uniforms.screenWidth && basePixel.y + 1u < uniforms.screenHeight) {\\n\\t\\t\\tlet px01 = vec2u(basePixel.x, basePixel.y + 1u);\\n\\t\\t\\t#ifdef PICK_MODE\\n\\t\\t\\t\\ttextureStore(pickIdTexture, px01, vec4u(pickId01, 0u, 0u, 0u));\\n\\t\\t\\t\\ttextureStore(pickDepthTexture, px01, vec4f(dAcc01, wAcc01, 0.0, 0.0));\\n\\t\\t\\t#else\\n\\t\\t\\t\\ttextureStore(outputTexture, px01, vec4f(decodeGamma3(vec3f(c01)), f32(half(1.0) - T.z)));\\n\\t\\t\\t#endif\\n\\t\\t}\\n\\t\\tif (basePixel.x + 1u < uniforms.screenWidth && basePixel.y + 1u < uniforms.screenHeight) {\\n\\t\\t\\tlet px11 = vec2u(basePixel.x + 1u, basePixel.y + 1u);\\n\\t\\t\\t#ifdef PICK_MODE\\n\\t\\t\\t\\ttextureStore(pickIdTexture, px11, vec4u(pickId11, 0u, 0u, 0u));\\n\\t\\t\\t\\ttextureStore(pickDepthTexture, px11, vec4f(dAcc11, wAcc11, 0.0, 0.0));\\n\\t\\t\\t#else\\n\\t\\t\\t\\ttextureStore(outputTexture, px11, vec4f(decodeGamma3(vec3f(c11)), f32(half(1.0) - T.w)));\\n\\t\\t\\t#endif\\n\\t\\t}\\n\\t#endif\\n}\\n`;\\n\\nconst ALPHA_VISIBILITY_THRESHOLD = 1 / 255;\\nconst CACHE_STRIDE = 8;\\nconst NUM_BUCKETS = 64;\\n\\nconst MAX_CHUNKS_PER_TILE$1 = 8;\\nclass GSplatLocalDispatchSet {\\n\\tdevice;\\n\\tpickMode;\\n\\t// Count compute caching: standard and fisheye variants, created lazily\\n\\t_countShader = null;\\n\\t_countBindGroupFormat = null;\\n\\t_countCompute = null;\\n\\t_countShaderFisheye = null;\\n\\t_countBindGroupFormatFisheye = null;\\n\\t_countComputeFisheye = null;\\n\\tplaceEntriesCompute;\\n\\tlargeSplatCompute;\\n\\tlargePlaceEntriesCompute;\\n\\tclassifyCompute;\\n\\tsortCompute;\\n\\tbucketSortCompute;\\n\\tcopyCompute;\\n\\tchunkSortCompute;\\n\\t_rasterizeVariants = /* @__PURE__ */ new Map();\\n\\tprefixSumKernel;\\n\\t_tileSplatCountsBuffer = null;\\n\\t_smallTileListBuffer = null;\\n\\t_largeTileListBuffer = null;\\n\\t_largeTileOverflowBasesBuffer = null;\\n\\t_rasterizeTileListBuffer = null;\\n\\t_tileListCountsBuffer = null;\\n\\t_chunkRangesBuffer = null;\\n\\t_totalChunksBuffer = null;\\n\\t_chunkSortIndirectBuffer = null;\\n\\t_allocatedTileCapacity = 0;\\n\\toutputTexture = null;\\n\\tpickIdTexture = null;\\n\\tpickDepthTexture = null;\\n\\tconstructor(device, pickMode) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.pickMode = pickMode;\\n\\t\\tthis.prefixSumKernel = new PrefixSumKernel(device);\\n\\t\\tif (pickMode) {\\n\\t\\t\\tthis.pickIdTexture = new Texture(device, {\\n\\t\\t\\t\\tname: \\\"GSplatLocalPickId\\\",\\n\\t\\t\\t\\twidth: 4,\\n\\t\\t\\t\\theight: 4,\\n\\t\\t\\t\\tformat: PIXELFORMAT_R32U,\\n\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\tstorage: true\\n\\t\\t\\t});\\n\\t\\t\\tthis.pickDepthTexture = new Texture(device, {\\n\\t\\t\\t\\tname: \\\"GSplatLocalPickDepth\\\",\\n\\t\\t\\t\\twidth: 4,\\n\\t\\t\\t\\theight: 4,\\n\\t\\t\\t\\tformat: PIXELFORMAT_RGBA16F,\\n\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\tstorage: true\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\tthis.outputTexture = new Texture(device, {\\n\\t\\t\\t\\tname: \\\"GSplatLocalComputeOutput\\\",\\n\\t\\t\\t\\twidth: 4,\\n\\t\\t\\t\\theight: 4,\\n\\t\\t\\t\\tformat: PIXELFORMAT_RGBA16F,\\n\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\tstorage: true\\n\\t\\t\\t});\\n\\t\\t}\\n\\t}\\n\\tresizeOutputTextures(width, height) {\\n\\t\\tif (this.pickMode) {\\n\\t\\t\\tthis.pickIdTexture?.resize(width, height);\\n\\t\\t\\tthis.pickDepthTexture?.resize(width, height);\\n\\t\\t} else {\\n\\t\\t\\tthis.outputTexture?.resize(width, height);\\n\\t\\t}\\n\\t}\\n\\tensureTileBuffers(numTiles) {\\n\\t\\tconst requiredTileSlots = numTiles + 1;\\n\\t\\tif (requiredTileSlots <= this._allocatedTileCapacity) return;\\n\\t\\tthis._tileSplatCountsBuffer?.destroy();\\n\\t\\tthis._smallTileListBuffer?.destroy();\\n\\t\\tthis._largeTileListBuffer?.destroy();\\n\\t\\tthis._largeTileOverflowBasesBuffer?.destroy();\\n\\t\\tthis._rasterizeTileListBuffer?.destroy();\\n\\t\\tthis._tileListCountsBuffer?.destroy();\\n\\t\\tthis._chunkRangesBuffer?.destroy();\\n\\t\\tthis._totalChunksBuffer?.destroy();\\n\\t\\tthis._chunkSortIndirectBuffer?.destroy();\\n\\t\\tthis._allocatedTileCapacity = requiredTileSlots;\\n\\t\\tthis._tileSplatCountsBuffer = new StorageBuffer(this.device, requiredTileSlots * 4, BUFFERUSAGE_COPY_DST | BUFFERUSAGE_COPY_SRC);\\n\\t\\tthis._smallTileListBuffer = new StorageBuffer(this.device, numTiles * 4);\\n\\t\\tthis._largeTileListBuffer = new StorageBuffer(this.device, numTiles * 4);\\n\\t\\tthis._largeTileOverflowBasesBuffer = new StorageBuffer(this.device, numTiles * 4);\\n\\t\\tthis._rasterizeTileListBuffer = new StorageBuffer(this.device, numTiles * 4);\\n\\t\\tthis._tileListCountsBuffer = new StorageBuffer(this.device, 4 * 4, BUFFERUSAGE_COPY_DST | BUFFERUSAGE_COPY_SRC);\\n\\t\\tconst maxChunks = numTiles * MAX_CHUNKS_PER_TILE$1;\\n\\t\\tthis._chunkRangesBuffer = new StorageBuffer(this.device, maxChunks * 8);\\n\\t\\tthis._totalChunksBuffer = new StorageBuffer(this.device, 1 * 4, BUFFERUSAGE_COPY_DST);\\n\\t\\tthis._chunkSortIndirectBuffer = new StorageBuffer(this.device, 3 * 4, BUFFERUSAGE_COPY_DST | BUFFERUSAGE_INDIRECT);\\n\\t\\tthis.prefixSumKernel.destroyPasses();\\n\\t}\\n\\tgetCountCompute(fisheyeEnabled, createShaderAndFormat) {\\n\\t\\tif (fisheyeEnabled) {\\n\\t\\t\\tif (!this._countComputeFisheye) {\\n\\t\\t\\t\\tconst { shader, bindGroupFormat } = createShaderAndFormat(this.pickMode, true);\\n\\t\\t\\t\\tthis._countShaderFisheye = shader;\\n\\t\\t\\t\\tthis._countBindGroupFormatFisheye = bindGroupFormat;\\n\\t\\t\\t\\tconst label = this.pickMode ? \\\"GSplatPickTileCountFisheye\\\" : \\\"GSplatLocalTileCountFisheye\\\";\\n\\t\\t\\t\\tthis._countComputeFisheye = new Compute(this.device, shader, label);\\n\\t\\t\\t}\\n\\t\\t\\treturn this._countComputeFisheye;\\n\\t\\t}\\n\\t\\tif (!this._countCompute) {\\n\\t\\t\\tconst { shader, bindGroupFormat } = createShaderAndFormat(this.pickMode, false);\\n\\t\\t\\tthis._countShader = shader;\\n\\t\\t\\tthis._countBindGroupFormat = bindGroupFormat;\\n\\t\\t\\tconst label = this.pickMode ? \\\"GSplatPickTileCount\\\" : \\\"GSplatLocalTileCount\\\";\\n\\t\\t\\tthis._countCompute = new Compute(this.device, shader, label);\\n\\t\\t}\\n\\t\\treturn this._countCompute;\\n\\t}\\n\\tdestroyCountResources() {\\n\\t\\tthis._countShader?.destroy();\\n\\t\\tthis._countBindGroupFormat?.destroy();\\n\\t\\tthis._countCompute?.destroy();\\n\\t\\tthis._countShaderFisheye?.destroy();\\n\\t\\tthis._countBindGroupFormatFisheye?.destroy();\\n\\t\\tthis._countComputeFisheye?.destroy();\\n\\t\\tthis._countShader = null;\\n\\t\\tthis._countBindGroupFormat = null;\\n\\t\\tthis._countCompute = null;\\n\\t\\tthis._countShaderFisheye = null;\\n\\t\\tthis._countBindGroupFormatFisheye = null;\\n\\t\\tthis._countComputeFisheye = null;\\n\\t}\\n\\tgetRasterizeCompute(pickMode, depthTest, fogType = \\\"none\\\", heatmap = false) {\\n\\t\\tlet key = pickMode ? \\\"pick\\\" : \\\"color\\\";\\n\\t\\tif (depthTest) key += \\\"-depth\\\";\\n\\t\\tif (fogType !== \\\"none\\\") key += `-fog-${fogType}`;\\n\\t\\tif (heatmap) key += \\\"-heatmap\\\";\\n\\t\\tlet variant = this._rasterizeVariants.get(key);\\n\\t\\tif (!variant) {\\n\\t\\t\\tconst { shader, bindGroupFormat } = this._createRasterizeShaderAndFormat(pickMode, depthTest, fogType, heatmap);\\n\\t\\t\\tconst compute = new Compute(this.device, shader, `GSplatRasterize-${key}`);\\n\\t\\t\\tvariant = { shader, bindGroupFormat, compute };\\n\\t\\t\\tthis._rasterizeVariants.set(key, variant);\\n\\t\\t}\\n\\t\\treturn variant.compute;\\n\\t}\\n\\t_createRasterizeShaderAndFormat(pickMode, depthTest = false, fogType = \\\"none\\\", heatmap = false) {\\n\\t\\tconst device = this.device;\\n\\t\\tconst hasFog = fogType !== \\\"none\\\";\\n\\t\\tconst uniforms = [\\n\\t\\t\\tnew UniformFormat(\\\"screenWidth\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"screenHeight\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"numTilesX\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"nearClip\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"farClip\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"alphaClip\\\", UNIFORMTYPE_FLOAT)\\n\\t\\t];\\n\\t\\tif (hasFog) {\\n\\t\\t\\tuniforms.push(\\n\\t\\t\\t\\tnew UniformFormat(\\\"fog_color\\\", UNIFORMTYPE_VEC3),\\n\\t\\t\\t\\tnew UniformFormat(\\\"fog_start\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"fog_end\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"fog_density\\\", UNIFORMTYPE_FLOAT)\\n\\t\\t\\t);\\n\\t\\t}\\n\\t\\tconst ubf = new UniformBufferFormat(device, uniforms);\\n\\t\\tconst sharedBindings = [\\n\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"tileEntries\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"tileSplatCounts\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"projCache\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"rasterizeTileList\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"tileListCounts\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"depthBuffer\\\", SHADERSTAGE_COMPUTE, true)\\n\\t\\t];\\n\\t\\tconst outputBindings = pickMode ? [\\n\\t\\t\\tnew BindStorageTextureFormat(\\\"pickIdTexture\\\", PIXELFORMAT_R32U),\\n\\t\\t\\tnew BindStorageTextureFormat(\\\"pickDepthTexture\\\", PIXELFORMAT_RGBA16F)\\n\\t\\t] : [\\n\\t\\t\\tnew BindStorageTextureFormat(\\\"outputTexture\\\", PIXELFORMAT_RGBA16F)\\n\\t\\t];\\n\\t\\tconst depthBindings = depthTest ? [\\n\\t\\t\\tnew BindTextureFormat(\\\"sceneDepthMap\\\", SHADERSTAGE_COMPUTE, TEXTUREDIMENSION_2D, SAMPLETYPE_UNFILTERABLE_FLOAT, false)\\n\\t\\t] : [];\\n\\t\\tconst bgf = new BindGroupFormat(device, [...sharedBindings, ...outputBindings, ...depthBindings]);\\n\\t\\tconst cdefines = /* @__PURE__ */ new Map();\\n\\t\\tcdefines.set(\\\"{CACHE_STRIDE}\\\", CACHE_STRIDE.toString());\\n\\t\\tif (pickMode) cdefines.set(\\\"PICK_MODE\\\", \\\"\\\");\\n\\t\\tif (depthTest) cdefines.set(\\\"DEPTH_TEST\\\", \\\"\\\");\\n\\t\\tif (heatmap) cdefines.set(\\\"HEATMAP_MODE\\\", \\\"\\\");\\n\\t\\tcdefines.set(\\\"GAMMA\\\", \\\"SRGB\\\");\\n\\t\\tcdefines.set(\\\"FOG\\\", hasFog ? fogType.toUpperCase() : \\\"NONE\\\");\\n\\t\\tconst cincludes = pickMode ? void 0 : /* @__PURE__ */ new Map([[\\\"decodePS\\\", shaderChunksWGSL.decodePS]]);\\n\\t\\tif (hasFog && cincludes) {\\n\\t\\t\\tcincludes.set(\\\"fogMathPS\\\", shaderChunksWGSL.fogMathPS);\\n\\t\\t\\tcincludes.set(\\\"gammaPS\\\", shaderChunksWGSL.gammaPS);\\n\\t\\t}\\n\\t\\tlet name = \\\"GSplatLocalRasterize\\\";\\n\\t\\tif (pickMode) name = \\\"GSplatLocalRasterizePick\\\";\\n\\t\\telse if (depthTest) name = \\\"GSplatLocalRasterizeDepth\\\";\\n\\t\\tconst shader = new Shader(device, {\\n\\t\\t\\tname,\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tcshader: computeGsplatLocalRasterizeSource,\\n\\t\\t\\tcdefines: cdefines.size > 0 ? cdefines : void 0,\\n\\t\\t\\tcincludes,\\n\\t\\t\\tcomputeBindGroupFormat: bgf,\\n\\t\\t\\tcomputeUniformBufferFormats: { uniforms: ubf }\\n\\t\\t});\\n\\t\\treturn { shader, bindGroupFormat: bgf };\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.destroyCountResources();\\n\\t\\tfor (const { shader, bindGroupFormat, compute } of this._rasterizeVariants.values()) {\\n\\t\\t\\tcompute.destroy();\\n\\t\\t\\tshader.destroy();\\n\\t\\t\\tbindGroupFormat.destroy();\\n\\t\\t}\\n\\t\\tthis._tileSplatCountsBuffer?.destroy();\\n\\t\\tthis._smallTileListBuffer?.destroy();\\n\\t\\tthis._largeTileListBuffer?.destroy();\\n\\t\\tthis._largeTileOverflowBasesBuffer?.destroy();\\n\\t\\tthis._rasterizeTileListBuffer?.destroy();\\n\\t\\tthis._tileListCountsBuffer?.destroy();\\n\\t\\tthis._chunkRangesBuffer?.destroy();\\n\\t\\tthis._totalChunksBuffer?.destroy();\\n\\t\\tthis._chunkSortIndirectBuffer?.destroy();\\n\\t\\tthis.prefixSumKernel.destroy();\\n\\t\\tthis.outputTexture?.destroy();\\n\\t\\tthis.pickIdTexture?.destroy();\\n\\t\\tthis.pickDepthTexture?.destroy();\\n\\t}\\n}\\n\\nvar gsplatComputeSplat_default = `\\nstruct Splat {\\n\\tindex: u32,\\n\\tuv: vec2i\\n}\\nvar<private> splat: Splat;\\nfn setSplat(idx: u32) {\\n\\tsplat.index = idx;\\n\\tsplat.uv = vec2i(i32(idx % uniforms.splatTextureSize), i32(idx / uniforms.splatTextureSize));\\n}\\n`;\\n\\nconst INITIAL_TILE_ENTRY_MULTIPLIER = 2.5;\\nconst ENTRY_HEADROOM_MULTIPLIER = 2;\\nconst SHRINK_THRESHOLD = 200;\\nconst INITIAL_LARGE_SPLAT_CAPACITY = 16384;\\nconst TILE_SIZE = 16;\\nconst MAX_TILES = 65535;\\nconst MAX_CHUNKS_PER_TILE = 8;\\nconst _viewProjMat$1 = new Mat4();\\nconst _viewProjData$1 = new Float32Array(16);\\nconst _viewData$1 = new Float32Array(16);\\nconst _shaderProjMat$1 = new Mat4();\\nconst _fogColorLinear = new Color();\\nconst _fogColorArray = new Float32Array(3);\\nclass GSplatComputeLocalRenderer extends GSplatRenderer {\\n\\t_mainSet;\\n\\t_pickSet = null;\\n\\tframePass;\\n\\ttileComposite;\\n\\t_needsFramePassRegister = false;\\n\\t_textureSize = 0;\\n\\t_minPixelSize = 2;\\n\\t_minContribution = 3;\\n\\t_alphaClip = 0.3;\\n\\t_alphaClipForward = ALPHA_VISIBILITY_THRESHOLD;\\n\\t_exposure = 1;\\n\\t_numSplats = 0;\\n\\t_compactedSplatIds = null;\\n\\t_sortElementCountBuffer = null;\\n\\t// --- Shared splat/entry-dependent buffers ---\\n\\t_projCacheBuffer = null;\\n\\t_tileEntriesBuffer = null;\\n\\t// Pair buffer for scatter-free tile binning: stores packed (tileIdx << 16 | localOffset)\\n\\t// per splat-tile intersection. Same size as tileEntries (one u32 per pair).\\n\\t_pairBuffer = null;\\n\\t_countersBuffer = null;\\n\\t_splatPairStartBuffer = null;\\n\\t_splatPairCountBuffer = null;\\n\\t// --- Large-splat deferred processing buffers ---\\n\\t_largeSplatIdsBuffer = null;\\n\\t_largeSplatIdsCapacity = INITIAL_LARGE_SPLAT_CAPACITY;\\n\\t_allocatedLargeSplatCapacity = 0;\\n\\t_allocatedSplatCapacity = 0;\\n\\t_allocatedEntryCapacity = 0;\\n\\t_tileEntryMultiplier = INITIAL_TILE_ENTRY_MULTIPLIER;\\n\\t_lastBufferSubmitVersion = -1;\\n\\t_lastReadbackEntryCount = -1;\\n\\t_shrinkFrameCount = 0;\\n\\t_fisheye = 0;\\n\\t_dataSource;\\n\\t_placeEntriesShader;\\n\\t_placeEntriesBindGroupFormat;\\n\\t_placeEntryPrepShader;\\n\\t_placeEntryPrepBindGroupFormat;\\n\\t_placeEntryPrepDispatchBuffer = null;\\n\\t_placeEntryPrepCompute = null;\\n\\t_largeSplatShader;\\n\\t_largeSplatBindGroupFormat;\\n\\t_largeSplatPrepShader;\\n\\t_largeSplatPrepBindGroupFormat;\\n\\t_largeSplatDispatchBuffer = null;\\n\\t_largeSplatPrepCompute = null;\\n\\t_largePlaceEntriesShader;\\n\\t_largePlaceEntriesBindGroupFormat;\\n\\t_classifyShader;\\n\\t_classifyBindGroupFormat;\\n\\t_sortShader;\\n\\t_sortBindGroupFormat;\\n\\t_bucketSortShader;\\n\\t_bucketSortBindGroupFormat;\\n\\t_copyShader;\\n\\t_copyBindGroupFormat;\\n\\t_chunkSortShader;\\n\\t_chunkSortBindGroupFormat;\\n\\tconstructor(device, node, cameraNode, layer, workBuffer) {\\n\\t\\tsuper(device, node, cameraNode, layer, workBuffer);\\n\\t\\tthis._dataSource = workBuffer;\\n\\t\\tthis._createSharedShaders();\\n\\t\\tthis._mainSet = this._createDispatchSet(false);\\n\\t\\tthis.framePass = new FramePassGSplatComputeLocal(this);\\n\\t\\tconst thisCamera = cameraNode.camera;\\n\\t\\tthis.tileComposite = new GSplatTileComposite(device, node, (camera) => {\\n\\t\\t\\tconst renderMode = this.renderMode ?? 0;\\n\\t\\t\\treturn thisCamera.camera === camera && (renderMode & GSPLAT_FORWARD) !== 0 && this._mainSet._rasterizeTileListBuffer !== null;\\n\\t\\t});\\n\\t}\\n\\tsetDataSource(source) {\\n\\t\\tthis._dataSource = source;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._unregisterFramePass();\\n\\t\\tif (this.renderMode) {\\n\\t\\t\\tif (this.renderMode & GSPLAT_FORWARD) {\\n\\t\\t\\t\\tthis.layer.removeMeshInstances([this.tileComposite.meshInstance], true);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._mainSet.destroy();\\n\\t\\tthis._pickSet?.destroy();\\n\\t\\tthis._placeEntriesShader.destroy();\\n\\t\\tthis._placeEntriesBindGroupFormat.destroy();\\n\\t\\tthis._placeEntryPrepShader.destroy();\\n\\t\\tthis._placeEntryPrepBindGroupFormat.destroy();\\n\\t\\tthis._placeEntryPrepDispatchBuffer?.destroy();\\n\\t\\tthis._largeSplatShader.destroy();\\n\\t\\tthis._largeSplatBindGroupFormat.destroy();\\n\\t\\tthis._largeSplatPrepShader.destroy();\\n\\t\\tthis._largeSplatPrepBindGroupFormat.destroy();\\n\\t\\tthis._largeSplatDispatchBuffer?.destroy();\\n\\t\\tthis._largePlaceEntriesShader.destroy();\\n\\t\\tthis._largePlaceEntriesBindGroupFormat.destroy();\\n\\t\\tthis._classifyShader.destroy();\\n\\t\\tthis._classifyBindGroupFormat.destroy();\\n\\t\\tthis._sortShader.destroy();\\n\\t\\tthis._sortBindGroupFormat.destroy();\\n\\t\\tthis._bucketSortShader.destroy();\\n\\t\\tthis._bucketSortBindGroupFormat.destroy();\\n\\t\\tthis._copyShader.destroy();\\n\\t\\tthis._copyBindGroupFormat.destroy();\\n\\t\\tthis._chunkSortShader.destroy();\\n\\t\\tthis._chunkSortBindGroupFormat.destroy();\\n\\t\\tthis._projCacheBuffer?.destroy();\\n\\t\\tthis._depthBuffer?.destroy();\\n\\t\\tthis._tileEntriesBuffer?.destroy();\\n\\t\\tthis._pairBuffer?.destroy();\\n\\t\\tthis._countersBuffer?.destroy();\\n\\t\\tthis._splatPairStartBuffer?.destroy();\\n\\t\\tthis._splatPairCountBuffer?.destroy();\\n\\t\\tthis._largeSplatIdsBuffer?.destroy();\\n\\t\\tthis.tileComposite.destroy();\\n\\t\\tsuper.destroy();\\n\\t}\\n\\tget material() {\\n\\t\\treturn this.tileComposite.material;\\n\\t}\\n\\tsetRenderMode(renderMode) {\\n\\t\\tconst oldRenderMode = this.renderMode ?? 0;\\n\\t\\tconst wasForward = (oldRenderMode & GSPLAT_FORWARD) !== 0;\\n\\t\\tconst isForward = (renderMode & GSPLAT_FORWARD) !== 0;\\n\\t\\tif (!wasForward && isForward) {\\n\\t\\t\\tthis.layer.addMeshInstances([this.tileComposite.meshInstance], true);\\n\\t\\t\\tthis._registerFramePass();\\n\\t\\t}\\n\\t\\tif (wasForward && !isForward) {\\n\\t\\t\\tthis.layer.removeMeshInstances([this.tileComposite.meshInstance], true);\\n\\t\\t\\tthis._unregisterFramePass();\\n\\t\\t}\\n\\t\\tsuper.setRenderMode(renderMode);\\n\\t}\\n\\tframeUpdate(gsplat, exposure, fogParams) {\\n\\t\\tif (this._needsFramePassRegister) {\\n\\t\\t\\tthis._registerFramePass();\\n\\t\\t}\\n\\t\\tthis._minPixelSize = gsplat.minPixelSize;\\n\\t\\tthis._minContribution = gsplat.minContribution;\\n\\t\\tthis._alphaClip = gsplat.alphaClip;\\n\\t\\tthis._alphaClipForward = gsplat.alphaClipForward;\\n\\t\\tthis._exposure = exposure ?? 1;\\n\\t\\tthis._fisheye = gsplat.fisheye;\\n\\t\\tthis._fogParams = fogParams ?? null;\\n\\t\\tthis._debugMode = gsplat.debug;\\n\\t\\tconst formatHash = this._dataSource.format.hash;\\n\\t\\tif (formatHash !== this._formatHash) {\\n\\t\\t\\tthis._formatHash = formatHash;\\n\\t\\t\\tthis._invalidateCountCompute();\\n\\t\\t}\\n\\t}\\n\\tsetCompactedData(compactedSplatIds, sortElementCountBuffer, textureSize, numSplats) {\\n\\t\\tthis._compactedSplatIds = compactedSplatIds;\\n\\t\\tthis._sortElementCountBuffer = sortElementCountBuffer;\\n\\t\\tthis._textureSize = textureSize;\\n\\t\\tthis._numSplats = numSplats;\\n\\t}\\n\\t_registerFramePass() {\\n\\t\\tconst camera = this.cameraNode.camera?.camera;\\n\\t\\tif (camera) {\\n\\t\\t\\tif (!camera.beforePasses.includes(this.framePass)) {\\n\\t\\t\\t\\tcamera.beforePasses.push(this.framePass);\\n\\t\\t\\t}\\n\\t\\t\\tthis._needsFramePassRegister = false;\\n\\t\\t} else {\\n\\t\\t\\tthis._needsFramePassRegister = true;\\n\\t\\t}\\n\\t}\\n\\t_unregisterFramePass() {\\n\\t\\tthis._needsFramePassRegister = false;\\n\\t\\tconst camera = this.cameraNode.camera?.camera;\\n\\t\\tif (camera) {\\n\\t\\t\\tconst idx = camera.beforePasses.indexOf(this.framePass);\\n\\t\\t\\tif (idx !== -1) {\\n\\t\\t\\t\\tcamera.beforePasses.splice(idx, 1);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tresizeOutputTexture(width, height) {\\n\\t\\tthis._mainSet.resizeOutputTextures(width, height);\\n\\t}\\n\\t_ensureSharedBuffers(numSplats) {\\n\\t\\tconst device = this.device;\\n\\t\\tconst canResize = device.submitVersion !== this._lastBufferSubmitVersion;\\n\\t\\tconst readbackValue = this._lastReadbackEntryCount;\\n\\t\\tif (readbackValue !== -1) {\\n\\t\\t\\tthis._lastReadbackEntryCount = -1;\\n\\t\\t\\tconst currentCapacity = this._allocatedEntryCapacity;\\n\\t\\t\\tif (currentCapacity > 0 && readbackValue < currentCapacity / 2) {\\n\\t\\t\\t\\tthis._shrinkFrameCount++;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._shrinkFrameCount = 0;\\n\\t\\t\\t}\\n\\t\\t\\tif (this._shrinkFrameCount >= SHRINK_THRESHOLD && numSplats > 0) {\\n\\t\\t\\t\\tconst target = Math.max(INITIAL_TILE_ENTRY_MULTIPLIER, readbackValue / numSplats * ENTRY_HEADROOM_MULTIPLIER);\\n\\t\\t\\t\\tthis._tileEntryMultiplier = Math.max(target, this._tileEntryMultiplier * 0.9);\\n\\t\\t\\t\\tthis._shrinkFrameCount = 0;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (!canResize) return;\\n\\t\\tif (numSplats > this._allocatedSplatCapacity) {\\n\\t\\t\\tthis._projCacheBuffer?.destroy();\\n\\t\\t\\tthis._depthBuffer?.destroy();\\n\\t\\t\\tthis._splatPairStartBuffer?.destroy();\\n\\t\\t\\tthis._splatPairCountBuffer?.destroy();\\n\\t\\t\\tthis._allocatedSplatCapacity = numSplats;\\n\\t\\t\\tthis._projCacheBuffer = new StorageBuffer(device, numSplats * CACHE_STRIDE * 4);\\n\\t\\t\\tthis._depthBuffer = new StorageBuffer(device, numSplats * 4);\\n\\t\\t\\tthis._splatPairStartBuffer = new StorageBuffer(device, numSplats * 4);\\n\\t\\t\\tthis._splatPairCountBuffer = new StorageBuffer(device, numSplats * 4);\\n\\t\\t}\\n\\t\\tif (!this._countersBuffer) {\\n\\t\\t\\tthis._countersBuffer = new StorageBuffer(device, 8, BUFFERUSAGE_COPY_DST | BUFFERUSAGE_COPY_SRC);\\n\\t\\t}\\n\\t\\tif (this._largeSplatIdsCapacity > this._allocatedLargeSplatCapacity) {\\n\\t\\t\\tthis._largeSplatIdsBuffer?.destroy();\\n\\t\\t\\tthis._allocatedLargeSplatCapacity = this._largeSplatIdsCapacity;\\n\\t\\t\\tthis._largeSplatIdsBuffer = new StorageBuffer(device, this._largeSplatIdsCapacity * 4);\\n\\t\\t}\\n\\t\\tconst requiredEntryCapacity = Math.ceil(numSplats * this._tileEntryMultiplier);\\n\\t\\tconst needsGrow = requiredEntryCapacity > this._allocatedEntryCapacity;\\n\\t\\tconst needsShrink = this._allocatedEntryCapacity > 0 && requiredEntryCapacity * 2 < this._allocatedEntryCapacity;\\n\\t\\tif (needsGrow || needsShrink) {\\n\\t\\t\\tthis._tileEntriesBuffer?.destroy();\\n\\t\\t\\tthis._pairBuffer?.destroy();\\n\\t\\t\\tthis._allocatedEntryCapacity = requiredEntryCapacity;\\n\\t\\t\\tthis._tileEntriesBuffer = new StorageBuffer(device, requiredEntryCapacity * 4, BUFFERUSAGE_COPY_DST);\\n\\t\\t\\tthis._pairBuffer = new StorageBuffer(device, requiredEntryCapacity * 4);\\n\\t\\t}\\n\\t\\tthis._lastBufferSubmitVersion = device.submitVersion;\\n\\t}\\n\\tdispatch() {\\n\\t\\tconst set = this._mainSet;\\n\\t\\tconst outputTex = set.outputTexture;\\n\\t\\tif (!outputTex) return;\\n\\t\\tconst width = outputTex.width;\\n\\t\\tconst height = outputTex.height;\\n\\t\\tthis._dispatchPipeline(set, width, height, false);\\n\\t\\tthis.tileComposite.update(\\n\\t\\t\\tthis._lastDrawSlot,\\n\\t\\t\\toutputTex,\\n\\t\\t\\tset._rasterizeTileListBuffer,\\n\\t\\t\\tthis._lastNumTilesX,\\n\\t\\t\\twidth,\\n\\t\\t\\theight\\n\\t\\t);\\n\\t}\\n\\tdispatchPick(cam, width, height) {\\n\\t\\tif (!this._pickSet) {\\n\\t\\t\\tthis._pickSet = this._createDispatchSet(true);\\n\\t\\t}\\n\\t\\tconst set = this._pickSet;\\n\\t\\tset.resizeOutputTextures(width, height);\\n\\t\\tthis._dispatchPipeline(set, width, height, true);\\n\\t\\treturn this.tileComposite.prepareForPicking(\\n\\t\\t\\tthis._lastDrawSlot,\\n\\t\\t\\tset.pickIdTexture,\\n\\t\\t\\tset.pickDepthTexture,\\n\\t\\t\\tset._rasterizeTileListBuffer,\\n\\t\\t\\tthis._lastNumTilesX,\\n\\t\\t\\twidth,\\n\\t\\t\\theight\\n\\t\\t);\\n\\t}\\n\\t_lastDrawSlot = 0;\\n\\t_lastNumTilesX = 0;\\n\\t_dispatchPipeline(set, width, height, pickMode) {\\n\\t\\tconst numSplats = this._numSplats;\\n\\t\\tif (!this._compactedSplatIds || !this._sortElementCountBuffer || numSplats === 0) return;\\n\\t\\tconst device = this.device;\\n\\t\\tlet numTilesX = Math.ceil(width / TILE_SIZE);\\n\\t\\tlet numTilesY = Math.ceil(height / TILE_SIZE);\\n\\t\\tif (numTilesX * numTilesY > MAX_TILES) {\\n\\t\\t\\tconst scale = Math.sqrt(MAX_TILES / (numTilesX * numTilesY));\\n\\t\\t\\tnumTilesX = Math.max(1, Math.floor(numTilesX * scale));\\n\\t\\t\\tnumTilesY = Math.max(1, Math.floor(numTilesY * scale));\\n\\t\\t}\\n\\t\\tconst numTiles = numTilesX * numTilesY;\\n\\t\\tthis._ensureSharedBuffers(numSplats);\\n\\t\\tset.ensureTileBuffers(numTiles);\\n\\t\\tconst maxEntries = this._allocatedEntryCapacity;\\n\\t\\tconst ds = this._dataSource;\\n\\t\\tconst camera = this.cameraNode.camera;\\n\\t\\tconst cam = camera.camera;\\n\\t\\tconst view = cam.viewMatrix;\\n\\t\\tconst flipY = !!camera.renderTarget?.flipY;\\n\\t\\tconst webgpu = device.isWebGPU;\\n\\t\\t_viewProjMat$1.mul2(Camera$1.applyShaderProjectionTransform(cam.projectionMatrix, _shaderProjMat$1, flipY, webgpu), view);\\n\\t\\t_viewProjData$1.set(_viewProjMat$1.data);\\n\\t\\t_viewData$1.set(view.data);\\n\\t\\tconst focal = width * _shaderProjMat$1.data[0];\\n\\t\\tconst alphaClip = pickMode ? this._alphaClip : Math.max(ALPHA_VISIBILITY_THRESHOLD, this._alphaClipForward);\\n\\t\\tthis.fisheyeProj.update(this._fisheye, camera.fov, cam.projectionMatrix);\\n\\t\\tconst fisheyeEnabled = this.fisheyeProj.enabled;\\n\\t\\tconst createCountShader = (pick, fisheye) => this._createCountShaderAndFormat(pick, fisheye);\\n\\t\\tconst countCompute = set.getCountCompute(fisheyeEnabled, createCountShader);\\n\\t\\tthis._placeEntryPrepCompute.setParameter(\\\"sortElementCount\\\", this._sortElementCountBuffer);\\n\\t\\tthis._placeEntryPrepCompute.setParameter(\\\"dispatchArgs\\\", this._placeEntryPrepDispatchBuffer);\\n\\t\\tthis._placeEntryPrepCompute.setupDispatch(1, 1, 1);\\n\\t\\tdevice.computeDispatch([this._placeEntryPrepCompute], \\\"GSplatLocalDispatchPrep\\\");\\n\\t\\tset._tileSplatCountsBuffer.clear();\\n\\t\\tthis._countersBuffer.clear();\\n\\t\\tcountCompute.setParameter(\\\"compactedSplatIds\\\", this._compactedSplatIds);\\n\\t\\tcountCompute.setParameter(\\\"sortElementCount\\\", this._sortElementCountBuffer);\\n\\t\\tcountCompute.setParameter(\\\"projCache\\\", this._projCacheBuffer);\\n\\t\\tcountCompute.setParameter(\\\"tileSplatCounts\\\", set._tileSplatCountsBuffer);\\n\\t\\tcountCompute.setParameter(\\\"pairBuffer\\\", this._pairBuffer);\\n\\t\\tcountCompute.setParameter(\\\"countersBuffer\\\", this._countersBuffer);\\n\\t\\tcountCompute.setParameter(\\\"splatPairStart\\\", this._splatPairStartBuffer);\\n\\t\\tcountCompute.setParameter(\\\"splatPairCount\\\", this._splatPairCountBuffer);\\n\\t\\tcountCompute.setParameter(\\\"largeSplatIds\\\", this._largeSplatIdsBuffer);\\n\\t\\tcountCompute.setParameter(\\\"depthBuffer\\\", this._depthBuffer);\\n\\t\\tfor (const stream of ds.format.streams) {\\n\\t\\t\\tcountCompute.setParameter(stream.name, ds.getTexture(stream.name));\\n\\t\\t}\\n\\t\\tfor (const stream of ds.format.extraStreams) {\\n\\t\\t\\tcountCompute.setParameter(stream.name, ds.getTexture(stream.name));\\n\\t\\t}\\n\\t\\tcountCompute.setParameter(\\\"splatTextureSize\\\", this._textureSize);\\n\\t\\tcountCompute.setParameter(\\\"numTilesX\\\", numTilesX);\\n\\t\\tcountCompute.setParameter(\\\"numTilesY\\\", numTilesY);\\n\\t\\tcountCompute.setParameter(\\\"viewProj\\\", _viewProjData$1);\\n\\t\\tcountCompute.setParameter(\\\"viewMatrix\\\", _viewData$1);\\n\\t\\tcountCompute.setParameter(\\\"focal\\\", focal);\\n\\t\\tcountCompute.setParameter(\\\"viewportWidth\\\", width);\\n\\t\\tcountCompute.setParameter(\\\"viewportHeight\\\", height);\\n\\t\\tcountCompute.setParameter(\\\"nearClip\\\", cam.nearClip);\\n\\t\\tcountCompute.setParameter(\\\"farClip\\\", cam.farClip);\\n\\t\\tcountCompute.setParameter(\\\"minPixelSize\\\", this._minPixelSize * 0.5);\\n\\t\\tcountCompute.setParameter(\\\"isOrtho\\\", cam.projection === PROJECTION_ORTHOGRAPHIC ? 1 : 0);\\n\\t\\tcountCompute.setParameter(\\\"exposure\\\", this._exposure);\\n\\t\\tcountCompute.setParameter(\\\"alphaClip\\\", alphaClip);\\n\\t\\tcountCompute.setParameter(\\\"minContribution\\\", this._minContribution);\\n\\t\\tif (fisheyeEnabled) {\\n\\t\\t\\tconst fp = this.fisheyeProj;\\n\\t\\t\\tcountCompute.setParameter(\\\"fisheye_k\\\", fp.k);\\n\\t\\t\\tcountCompute.setParameter(\\\"fisheye_inv_k\\\", fp.invK);\\n\\t\\t\\tcountCompute.setParameter(\\\"fisheye_projMat00\\\", fp.projMat00);\\n\\t\\t\\tcountCompute.setParameter(\\\"fisheye_projMat11\\\", fp.projMat11);\\n\\t\\t}\\n\\t\\tcountCompute.setupIndirectDispatch(0, this._placeEntryPrepDispatchBuffer);\\n\\t\\tdevice.computeDispatch([countCompute], pickMode ? \\\"GSplatPickTileCount\\\" : \\\"GSplatLocalTileCount\\\");\\n\\t\\tthis._largeSplatPrepCompute.setParameter(\\\"countersBuffer\\\", this._countersBuffer);\\n\\t\\tthis._largeSplatPrepCompute.setParameter(\\\"dispatchArgs\\\", this._largeSplatDispatchBuffer);\\n\\t\\tthis._largeSplatPrepCompute.setParameter(\\\"largeSplatIds\\\", this._largeSplatIdsBuffer);\\n\\t\\tthis._largeSplatPrepCompute.setupDispatch(1, 1, 1);\\n\\t\\tdevice.computeDispatch([this._largeSplatPrepCompute], pickMode ? \\\"GSplatPickLargeSplatPrep\\\" : \\\"GSplatLocalLargeSplatPrep\\\");\\n\\t\\tset.largeSplatCompute.setParameter(\\\"projCache\\\", this._projCacheBuffer);\\n\\t\\tset.largeSplatCompute.setParameter(\\\"tileSplatCounts\\\", set._tileSplatCountsBuffer);\\n\\t\\tset.largeSplatCompute.setParameter(\\\"pairBuffer\\\", this._pairBuffer);\\n\\t\\tset.largeSplatCompute.setParameter(\\\"countersBuffer\\\", this._countersBuffer);\\n\\t\\tset.largeSplatCompute.setParameter(\\\"splatPairStart\\\", this._splatPairStartBuffer);\\n\\t\\tset.largeSplatCompute.setParameter(\\\"splatPairCount\\\", this._splatPairCountBuffer);\\n\\t\\tset.largeSplatCompute.setParameter(\\\"largeSplatIds\\\", this._largeSplatIdsBuffer);\\n\\t\\tset.largeSplatCompute.setParameter(\\\"numTilesX\\\", numTilesX);\\n\\t\\tset.largeSplatCompute.setParameter(\\\"numTilesY\\\", numTilesY);\\n\\t\\tset.largeSplatCompute.setParameter(\\\"viewportWidth\\\", width);\\n\\t\\tset.largeSplatCompute.setParameter(\\\"viewportHeight\\\", height);\\n\\t\\tset.largeSplatCompute.setParameter(\\\"alphaClip\\\", alphaClip);\\n\\t\\tset.largeSplatCompute.setupIndirectDispatch(0, this._largeSplatDispatchBuffer);\\n\\t\\tdevice.computeDispatch([set.largeSplatCompute], pickMode ? \\\"GSplatPickLargeTileCount\\\" : \\\"GSplatLocalLargeTileCount\\\");\\n\\t\\tset.prefixSumKernel.resize(set._tileSplatCountsBuffer, numTiles + 1);\\n\\t\\tset.prefixSumKernel.dispatch(device);\\n\\t\\tset.placeEntriesCompute.setParameter(\\\"pairBuffer\\\", this._pairBuffer);\\n\\t\\tset.placeEntriesCompute.setParameter(\\\"splatPairStart\\\", this._splatPairStartBuffer);\\n\\t\\tset.placeEntriesCompute.setParameter(\\\"splatPairCount\\\", this._splatPairCountBuffer);\\n\\t\\tset.placeEntriesCompute.setParameter(\\\"tileSplatCounts\\\", set._tileSplatCountsBuffer);\\n\\t\\tset.placeEntriesCompute.setParameter(\\\"tileEntries\\\", this._tileEntriesBuffer);\\n\\t\\tset.placeEntriesCompute.setParameter(\\\"sortElementCount\\\", this._sortElementCountBuffer);\\n\\t\\tset.placeEntriesCompute.setupIndirectDispatch(1, this._placeEntryPrepDispatchBuffer);\\n\\t\\tdevice.computeDispatch([set.placeEntriesCompute], pickMode ? \\\"GSplatPickPlaceEntries\\\" : \\\"GSplatLocalPlaceEntries\\\");\\n\\t\\tset.largePlaceEntriesCompute.setParameter(\\\"pairBuffer\\\", this._pairBuffer);\\n\\t\\tset.largePlaceEntriesCompute.setParameter(\\\"splatPairStart\\\", this._splatPairStartBuffer);\\n\\t\\tset.largePlaceEntriesCompute.setParameter(\\\"splatPairCount\\\", this._splatPairCountBuffer);\\n\\t\\tset.largePlaceEntriesCompute.setParameter(\\\"tileSplatCounts\\\", set._tileSplatCountsBuffer);\\n\\t\\tset.largePlaceEntriesCompute.setParameter(\\\"tileEntries\\\", this._tileEntriesBuffer);\\n\\t\\tset.largePlaceEntriesCompute.setParameter(\\\"largeSplatIds\\\", this._largeSplatIdsBuffer);\\n\\t\\tset.largePlaceEntriesCompute.setParameter(\\\"countersBuffer\\\", this._countersBuffer);\\n\\t\\tset.largePlaceEntriesCompute.setupIndirectDispatch(0, this._largeSplatDispatchBuffer);\\n\\t\\tdevice.computeDispatch([set.largePlaceEntriesCompute], pickMode ? \\\"GSplatPickLargePlaceEntries\\\" : \\\"GSplatLocalLargePlaceEntries\\\");\\n\\t\\tset._tileListCountsBuffer.clear();\\n\\t\\tset._totalChunksBuffer.clear();\\n\\t\\tset._chunkSortIndirectBuffer.clear();\\n\\t\\tconst indirectSlot = device.getIndirectDispatchSlot(3);\\n\\t\\tconst drawSlot = device.getIndirectDrawSlot(1);\\n\\t\\tset.classifyCompute.setParameter(\\\"tileSplatCounts\\\", set._tileSplatCountsBuffer);\\n\\t\\tset.classifyCompute.setParameter(\\\"smallTileList\\\", set._smallTileListBuffer);\\n\\t\\tset.classifyCompute.setParameter(\\\"largeTileList\\\", set._largeTileListBuffer);\\n\\t\\tset.classifyCompute.setParameter(\\\"rasterizeTileList\\\", set._rasterizeTileListBuffer);\\n\\t\\tset.classifyCompute.setParameter(\\\"tileListCounts\\\", set._tileListCountsBuffer);\\n\\t\\tset.classifyCompute.setParameter(\\\"indirectDispatchArgs\\\", device.indirectDispatchBuffer);\\n\\t\\tset.classifyCompute.setParameter(\\\"largeTileOverflowBases\\\", set._largeTileOverflowBasesBuffer);\\n\\t\\tset.classifyCompute.setParameter(\\\"indirectDrawArgs\\\", device.indirectDrawBuffer);\\n\\t\\tset.classifyCompute.setParameter(\\\"numTiles\\\", numTiles);\\n\\t\\tset.classifyCompute.setParameter(\\\"dispatchSlotOffset\\\", indirectSlot * 3);\\n\\t\\tset.classifyCompute.setParameter(\\\"bufferCapacity\\\", maxEntries);\\n\\t\\tset.classifyCompute.setParameter(\\\"maxWorkgroupsPerDim\\\", device.limits.maxComputeWorkgroupsPerDimension || 65535);\\n\\t\\tset.classifyCompute.setParameter(\\\"drawSlot\\\", drawSlot);\\n\\t\\tset.classifyCompute.setupDispatch(1, 1, 1);\\n\\t\\tdevice.computeDispatch([set.classifyCompute], pickMode ? \\\"GSplatPickClassify\\\" : \\\"GSplatLocalClassify\\\");\\n\\t\\tset.bucketSortCompute.setParameter(\\\"tileEntries\\\", this._tileEntriesBuffer);\\n\\t\\tset.bucketSortCompute.setParameter(\\\"largeTileOverflowBases\\\", set._largeTileOverflowBasesBuffer);\\n\\t\\tset.bucketSortCompute.setParameter(\\\"tileSplatCounts\\\", set._tileSplatCountsBuffer);\\n\\t\\tset.bucketSortCompute.setParameter(\\\"depthBuffer\\\", this._depthBuffer);\\n\\t\\tset.bucketSortCompute.setParameter(\\\"largeTileList\\\", set._largeTileListBuffer);\\n\\t\\tset.bucketSortCompute.setParameter(\\\"chunkRanges\\\", set._chunkRangesBuffer);\\n\\t\\tset.bucketSortCompute.setParameter(\\\"totalChunks\\\", set._totalChunksBuffer);\\n\\t\\tset.bucketSortCompute.setParameter(\\\"tileListCounts\\\", set._tileListCountsBuffer);\\n\\t\\tset.bucketSortCompute.setParameter(\\\"bufferCapacity\\\", maxEntries);\\n\\t\\tset.bucketSortCompute.setParameter(\\\"maxChunks\\\", numTiles * MAX_CHUNKS_PER_TILE);\\n\\t\\tset.bucketSortCompute.setupIndirectDispatch(indirectSlot + 1);\\n\\t\\tdevice.computeDispatch([set.bucketSortCompute], pickMode ? \\\"GSplatPickBucketSort\\\" : \\\"GSplatLocalBucketSort\\\");\\n\\t\\tset.copyCompute.setParameter(\\\"totalChunks\\\", set._totalChunksBuffer);\\n\\t\\tset.copyCompute.setParameter(\\\"chunkSortIndirect\\\", set._chunkSortIndirectBuffer);\\n\\t\\tset.copyCompute.setParameter(\\\"maxChunks\\\", numTiles * MAX_CHUNKS_PER_TILE);\\n\\t\\tset.copyCompute.setParameter(\\\"maxWorkgroupsPerDim\\\", device.limits.maxComputeWorkgroupsPerDimension || 65535);\\n\\t\\tset.copyCompute.setupDispatch(1, 1, 1);\\n\\t\\tdevice.computeDispatch([set.copyCompute], pickMode ? \\\"GSplatPickCopy\\\" : \\\"GSplatLocalCopy\\\");\\n\\t\\tset.sortCompute.setParameter(\\\"tileEntries\\\", this._tileEntriesBuffer);\\n\\t\\tset.sortCompute.setParameter(\\\"tileSplatCounts\\\", set._tileSplatCountsBuffer);\\n\\t\\tset.sortCompute.setParameter(\\\"depthBuffer\\\", this._depthBuffer);\\n\\t\\tset.sortCompute.setParameter(\\\"smallTileList\\\", set._smallTileListBuffer);\\n\\t\\tset.sortCompute.setParameter(\\\"tileListCounts\\\", set._tileListCountsBuffer);\\n\\t\\tset.sortCompute.setupIndirectDispatch(indirectSlot);\\n\\t\\tdevice.computeDispatch([set.sortCompute], pickMode ? \\\"GSplatPickTileSort\\\" : \\\"GSplatLocalTileSort\\\");\\n\\t\\tset.chunkSortCompute.setParameter(\\\"tileEntries\\\", this._tileEntriesBuffer);\\n\\t\\tset.chunkSortCompute.setParameter(\\\"depthBuffer\\\", this._depthBuffer);\\n\\t\\tset.chunkSortCompute.setParameter(\\\"chunkRanges\\\", set._chunkRangesBuffer);\\n\\t\\tset.chunkSortCompute.setParameter(\\\"totalChunks\\\", set._totalChunksBuffer);\\n\\t\\tset.chunkSortCompute.setParameter(\\\"maxChunks\\\", numTiles * MAX_CHUNKS_PER_TILE);\\n\\t\\tset.chunkSortCompute.setupIndirectDispatch(0, set._chunkSortIndirectBuffer);\\n\\t\\tdevice.computeDispatch([set.chunkSortCompute], pickMode ? \\\"GSplatPickChunkSort\\\" : \\\"GSplatLocalChunkSort\\\");\\n\\t\\tconst hasLinearDepth = cam.shaderParams.sceneDepthMapLinear;\\n\\t\\tconst sceneDepthMap = hasLinearDepth ? device.scope.resolve(\\\"uSceneDepthMap\\\").value : null;\\n\\t\\tconst useDepth = !pickMode && sceneDepthMap;\\n\\t\\tconst fogParams = this._fogParams;\\n\\t\\tconst fogType = fogParams && fogParams.type !== FOG_NONE ? fogParams.type : \\\"none\\\";\\n\\t\\tconst heatmap = !pickMode && this._debugMode === GSPLAT_DEBUG_HEATMAP;\\n\\t\\tconst rasterizeCompute = set.getRasterizeCompute(pickMode, useDepth, fogType, heatmap);\\n\\t\\trasterizeCompute.setParameter(\\\"screenWidth\\\", width);\\n\\t\\trasterizeCompute.setParameter(\\\"screenHeight\\\", height);\\n\\t\\trasterizeCompute.setParameter(\\\"numTilesX\\\", numTilesX);\\n\\t\\trasterizeCompute.setParameter(\\\"nearClip\\\", cam.nearClip);\\n\\t\\trasterizeCompute.setParameter(\\\"farClip\\\", cam.farClip);\\n\\t\\trasterizeCompute.setParameter(\\\"alphaClip\\\", alphaClip);\\n\\t\\tif (fogType !== \\\"none\\\") {\\n\\t\\t\\t_fogColorLinear.linear(fogParams.color);\\n\\t\\t\\t_fogColorArray[0] = _fogColorLinear.r;\\n\\t\\t\\t_fogColorArray[1] = _fogColorLinear.g;\\n\\t\\t\\t_fogColorArray[2] = _fogColorLinear.b;\\n\\t\\t\\trasterizeCompute.setParameter(\\\"fog_color\\\", _fogColorArray);\\n\\t\\t\\trasterizeCompute.setParameter(\\\"fog_start\\\", fogParams.start);\\n\\t\\t\\trasterizeCompute.setParameter(\\\"fog_end\\\", fogParams.end);\\n\\t\\t\\trasterizeCompute.setParameter(\\\"fog_density\\\", fogParams.density);\\n\\t\\t}\\n\\t\\trasterizeCompute.setParameter(\\\"tileEntries\\\", this._tileEntriesBuffer);\\n\\t\\trasterizeCompute.setParameter(\\\"tileSplatCounts\\\", set._tileSplatCountsBuffer);\\n\\t\\trasterizeCompute.setParameter(\\\"projCache\\\", this._projCacheBuffer);\\n\\t\\trasterizeCompute.setParameter(\\\"rasterizeTileList\\\", set._rasterizeTileListBuffer);\\n\\t\\trasterizeCompute.setParameter(\\\"tileListCounts\\\", set._tileListCountsBuffer);\\n\\t\\trasterizeCompute.setParameter(\\\"depthBuffer\\\", this._depthBuffer);\\n\\t\\tif (pickMode) {\\n\\t\\t\\trasterizeCompute.setParameter(\\\"pickIdTexture\\\", set.pickIdTexture);\\n\\t\\t\\trasterizeCompute.setParameter(\\\"pickDepthTexture\\\", set.pickDepthTexture);\\n\\t\\t} else {\\n\\t\\t\\trasterizeCompute.setParameter(\\\"outputTexture\\\", set.outputTexture);\\n\\t\\t\\tif (useDepth) {\\n\\t\\t\\t\\trasterizeCompute.setParameter(\\\"sceneDepthMap\\\", sceneDepthMap);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\trasterizeCompute.setupIndirectDispatch(indirectSlot + 2);\\n\\t\\tdevice.computeDispatch([rasterizeCompute], pickMode ? \\\"GSplatPickRasterize\\\" : \\\"GSplatLocalRasterize\\\");\\n\\t\\tthis._lastDrawSlot = drawSlot;\\n\\t\\tthis._lastNumTilesX = numTilesX;\\n\\t\\tthis._scheduleReadback(numSplats, numTiles, set);\\n\\t}\\n\\t_scheduleReadback(numSplats, numTiles, set) {\\n\\t\\tif (numSplats === 0) return;\\n\\t\\tconst capturedNumSplats = numSplats;\\n\\t\\tconst readback1 = set._tileSplatCountsBuffer.read(numTiles * 4, 4);\\n\\t\\tconst readback2 = set._tileListCountsBuffer.read(3 * 4, 4);\\n\\t\\tconst readback3 = this._countersBuffer.read(4, 4);\\n\\t\\tPromise.all([readback1, readback2, readback3]).then(([r1, r2, r3]) => {\\n\\t\\t\\tconst totalEntries = new Uint32Array(r1.buffer, r1.byteOffset, 1)[0];\\n\\t\\t\\tconst totalOverflow = new Uint32Array(r2.buffer, r2.byteOffset, 1)[0];\\n\\t\\t\\tconst needed = totalEntries + totalOverflow;\\n\\t\\t\\tif (capturedNumSplats > 0) {\\n\\t\\t\\t\\tthis._tileEntryMultiplier = Math.max(this._tileEntryMultiplier, needed / capturedNumSplats * ENTRY_HEADROOM_MULTIPLIER);\\n\\t\\t\\t\\tthis._tileEntryMultiplier = Math.max(this._tileEntryMultiplier, INITIAL_TILE_ENTRY_MULTIPLIER);\\n\\t\\t\\t}\\n\\t\\t\\tthis._lastReadbackEntryCount = needed;\\n\\t\\t\\tconst largeSplatDemand = new Uint32Array(r3.buffer, r3.byteOffset, 1)[0];\\n\\t\\t\\tif (largeSplatDemand > this._largeSplatIdsCapacity) {\\n\\t\\t\\t\\tthis._largeSplatIdsCapacity = Math.ceil(largeSplatDemand * 1.2);\\n\\t\\t\\t}\\n\\t\\t}).catch(() => {\\n\\t\\t});\\n\\t}\\n\\t_invalidateCountCompute() {\\n\\t\\tthis._mainSet.destroyCountResources();\\n\\t\\tthis._pickSet?.destroyCountResources();\\n\\t}\\n\\t// ---- Shader / BindGroupFormat creation ----\\n\\t_createCommonIncludes() {\\n\\t\\tconst cincludes = /* @__PURE__ */ new Map();\\n\\t\\tcincludes.set(\\\"gsplatCommonCS\\\", computeGsplatCommonSource);\\n\\t\\tcincludes.set(\\\"gsplatTileIntersectCS\\\", computeGsplatTileIntersectSource);\\n\\t\\treturn cincludes;\\n\\t}\\n\\t_createBitonicIncludes() {\\n\\t\\tconst cincludes = /* @__PURE__ */ new Map();\\n\\t\\tcincludes.set(\\\"gsplatLocalBitonicCS\\\", computeGsplatLocalBitonicSource);\\n\\t\\treturn cincludes;\\n\\t}\\n\\t_createSharedShaders() {\\n\\t\\tconst device = this.device;\\n\\t\\tthis._placeEntriesBindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"pairBuffer\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"splatPairStart\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"splatPairCount\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"tileSplatCounts\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"tileEntries\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"sortElementCount\\\", SHADERSTAGE_COMPUTE, true)\\n\\t\\t]);\\n\\t\\tthis._placeEntriesShader = new Shader(device, {\\n\\t\\t\\tname: \\\"GSplatLocalPlaceEntries\\\",\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tcshader: computeGsplatLocalPlaceEntriesSource,\\n\\t\\t\\tcomputeBindGroupFormat: this._placeEntriesBindGroupFormat\\n\\t\\t});\\n\\t\\t{\\n\\t\\t\\tconst maxDim = device.limits.maxComputeWorkgroupsPerDimension || 65535;\\n\\t\\t\\tconst prepDefines = /* @__PURE__ */ new Map();\\n\\t\\t\\tprepDefines.set(\\\"{MAX_DIM}\\\", maxDim.toString());\\n\\t\\t\\tprepDefines.set(\\\"{SPLATS_PER_WG}\\\", \\\"256\\\");\\n\\t\\t\\tprepDefines.set(\\\"{SPLATS_PER_WG_MINUS_1}\\\", \\\"255\\\");\\n\\t\\t\\tthis._placeEntryPrepBindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"sortElementCount\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"dispatchArgs\\\", SHADERSTAGE_COMPUTE)\\n\\t\\t\\t]);\\n\\t\\t\\tthis._placeEntryPrepShader = new Shader(device, {\\n\\t\\t\\t\\tname: \\\"GSplatLocalPlaceEntryPrep\\\",\\n\\t\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\t\\tcshader: computeGsplatLocalDispatchPrepSource,\\n\\t\\t\\t\\tcdefines: prepDefines,\\n\\t\\t\\t\\tcomputeBindGroupFormat: this._placeEntryPrepBindGroupFormat\\n\\t\\t\\t});\\n\\t\\t\\tthis._placeEntryPrepDispatchBuffer = new StorageBuffer(device, 6 * 4, BUFFERUSAGE_INDIRECT);\\n\\t\\t\\tthis._placeEntryPrepCompute = new Compute(device, this._placeEntryPrepShader);\\n\\t\\t}\\n\\t\\t{\\n\\t\\t\\tconst cincludes = this._createCommonIncludes();\\n\\t\\t\\tconst ubf = new UniformBufferFormat(device, [\\n\\t\\t\\t\\tnew UniformFormat(\\\"numTilesX\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"numTilesY\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"viewportWidth\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"viewportHeight\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"alphaClip\\\", UNIFORMTYPE_FLOAT)\\n\\t\\t\\t]);\\n\\t\\t\\tthis._largeSplatBindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"projCache\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"tileSplatCounts\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"pairBuffer\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"countersBuffer\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"splatPairStart\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"splatPairCount\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"largeSplatIds\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE)\\n\\t\\t\\t]);\\n\\t\\t\\tconst cdefines = /* @__PURE__ */ new Map();\\n\\t\\t\\tcdefines.set(\\\"{CACHE_STRIDE}\\\", CACHE_STRIDE.toString());\\n\\t\\t\\tthis._largeSplatShader = new Shader(device, {\\n\\t\\t\\t\\tname: \\\"GSplatLocalTileCountLarge\\\",\\n\\t\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\t\\tcshader: computeGsplatLocalTileCountLargeSource,\\n\\t\\t\\t\\tcincludes,\\n\\t\\t\\t\\tcdefines,\\n\\t\\t\\t\\tcomputeBindGroupFormat: this._largeSplatBindGroupFormat,\\n\\t\\t\\t\\tcomputeUniformBufferFormats: { uniforms: ubf }\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\t{\\n\\t\\t\\tconst maxDim = device.limits.maxComputeWorkgroupsPerDimension || 65535;\\n\\t\\t\\tconst largePrepDefines = /* @__PURE__ */ new Map();\\n\\t\\t\\tlargePrepDefines.set(\\\"{MAX_DIM}\\\", maxDim.toString());\\n\\t\\t\\tthis._largeSplatPrepBindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"countersBuffer\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"dispatchArgs\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"largeSplatIds\\\", SHADERSTAGE_COMPUTE, true)\\n\\t\\t\\t]);\\n\\t\\t\\tthis._largeSplatPrepShader = new Shader(device, {\\n\\t\\t\\t\\tname: \\\"GSplatLocalLargeSplatPrep\\\",\\n\\t\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\t\\tcshader: computeGsplatLocalDispatchPrepLargeSource,\\n\\t\\t\\t\\tcdefines: largePrepDefines,\\n\\t\\t\\t\\tcomputeBindGroupFormat: this._largeSplatPrepBindGroupFormat\\n\\t\\t\\t});\\n\\t\\t\\tthis._largeSplatDispatchBuffer = new StorageBuffer(device, 3 * 4, BUFFERUSAGE_INDIRECT);\\n\\t\\t\\tthis._largeSplatPrepCompute = new Compute(device, this._largeSplatPrepShader);\\n\\t\\t}\\n\\t\\tthis._largePlaceEntriesBindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"pairBuffer\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"splatPairStart\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"splatPairCount\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"tileSplatCounts\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"tileEntries\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"largeSplatIds\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"countersBuffer\\\", SHADERSTAGE_COMPUTE, true)\\n\\t\\t]);\\n\\t\\tthis._largePlaceEntriesShader = new Shader(device, {\\n\\t\\t\\tname: \\\"GSplatLocalPlaceEntriesLarge\\\",\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tcshader: computeGsplatLocalPlaceEntriesLargeSource,\\n\\t\\t\\tcomputeBindGroupFormat: this._largePlaceEntriesBindGroupFormat\\n\\t\\t});\\n\\t\\t{\\n\\t\\t\\tconst ubf = new UniformBufferFormat(device, [\\n\\t\\t\\t\\tnew UniformFormat(\\\"numTiles\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"dispatchSlotOffset\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"bufferCapacity\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"maxWorkgroupsPerDim\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"drawSlot\\\", UNIFORMTYPE_UINT)\\n\\t\\t\\t]);\\n\\t\\t\\tthis._classifyBindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"tileSplatCounts\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"smallTileList\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"largeTileList\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"rasterizeTileList\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"tileListCounts\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"indirectDispatchArgs\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"largeTileOverflowBases\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"indirectDrawArgs\\\", SHADERSTAGE_COMPUTE)\\n\\t\\t\\t]);\\n\\t\\t\\tthis._classifyShader = new Shader(device, {\\n\\t\\t\\t\\tname: \\\"GSplatLocalClassify\\\",\\n\\t\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\t\\tcshader: computeGsplatLocalClassifySource,\\n\\t\\t\\t\\tcomputeBindGroupFormat: this._classifyBindGroupFormat,\\n\\t\\t\\t\\tcomputeUniformBufferFormats: { uniforms: ubf }\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tthis._sortBindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"tileEntries\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"tileSplatCounts\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"depthBuffer\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"smallTileList\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"tileListCounts\\\", SHADERSTAGE_COMPUTE, true)\\n\\t\\t]);\\n\\t\\tthis._sortShader = new Shader(device, {\\n\\t\\t\\tname: \\\"GSplatLocalTileSort\\\",\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tcshader: computeGsplatLocalTileSortSource,\\n\\t\\t\\tcincludes: this._createBitonicIncludes(),\\n\\t\\t\\tcomputeBindGroupFormat: this._sortBindGroupFormat\\n\\t\\t});\\n\\t\\t{\\n\\t\\t\\tconst ubf = new UniformBufferFormat(device, [\\n\\t\\t\\t\\tnew UniformFormat(\\\"bufferCapacity\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"maxChunks\\\", UNIFORMTYPE_UINT)\\n\\t\\t\\t]);\\n\\t\\t\\tthis._bucketSortBindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"tileEntries\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"largeTileOverflowBases\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"tileSplatCounts\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"depthBuffer\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"largeTileList\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"chunkRanges\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"totalChunks\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"tileListCounts\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE)\\n\\t\\t\\t]);\\n\\t\\t\\tthis._bucketSortShader = new Shader(device, {\\n\\t\\t\\t\\tname: \\\"GSplatLocalBucketSort\\\",\\n\\t\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\t\\tcshader: computeGsplatLocalBucketSortSource,\\n\\t\\t\\t\\tcomputeBindGroupFormat: this._bucketSortBindGroupFormat,\\n\\t\\t\\t\\tcomputeUniformBufferFormats: { uniforms: ubf }\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\t{\\n\\t\\t\\tconst ubf = new UniformBufferFormat(device, [\\n\\t\\t\\t\\tnew UniformFormat(\\\"maxChunks\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"maxWorkgroupsPerDim\\\", UNIFORMTYPE_UINT)\\n\\t\\t\\t]);\\n\\t\\t\\tthis._copyBindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"totalChunks\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"chunkSortIndirect\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE)\\n\\t\\t\\t]);\\n\\t\\t\\tthis._copyShader = new Shader(device, {\\n\\t\\t\\t\\tname: \\\"GSplatLocalCopy\\\",\\n\\t\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\t\\tcshader: computeGsplatLocalCopySource,\\n\\t\\t\\t\\tcomputeBindGroupFormat: this._copyBindGroupFormat,\\n\\t\\t\\t\\tcomputeUniformBufferFormats: { uniforms: ubf }\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\t{\\n\\t\\t\\tconst ubf = new UniformBufferFormat(device, [\\n\\t\\t\\t\\tnew UniformFormat(\\\"maxChunks\\\", UNIFORMTYPE_UINT)\\n\\t\\t\\t]);\\n\\t\\t\\tthis._chunkSortBindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"tileEntries\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"depthBuffer\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"chunkRanges\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\tnew BindStorageBufferFormat(\\\"totalChunks\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE)\\n\\t\\t\\t]);\\n\\t\\t\\tthis._chunkSortShader = new Shader(device, {\\n\\t\\t\\t\\tname: \\\"GSplatLocalChunkSort\\\",\\n\\t\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\t\\tcshader: computeGsplatLocalChunkSortSource,\\n\\t\\t\\t\\tcincludes: this._createBitonicIncludes(),\\n\\t\\t\\t\\tcomputeBindGroupFormat: this._chunkSortBindGroupFormat,\\n\\t\\t\\t\\tcomputeUniformBufferFormats: { uniforms: ubf }\\n\\t\\t\\t});\\n\\t\\t}\\n\\t}\\n\\t_createCountShaderAndFormat(pickMode, fisheyeEnabled) {\\n\\t\\tconst device = this.device;\\n\\t\\tconst uniforms = [\\n\\t\\t\\tnew UniformFormat(\\\"splatTextureSize\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"numTilesX\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"numTilesY\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"viewProj\\\", UNIFORMTYPE_MAT4),\\n\\t\\t\\tnew UniformFormat(\\\"viewMatrix\\\", UNIFORMTYPE_MAT4),\\n\\t\\t\\tnew UniformFormat(\\\"focal\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"viewportWidth\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"viewportHeight\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"nearClip\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"farClip\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"minPixelSize\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"isOrtho\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"exposure\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"alphaClip\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"minContribution\\\", UNIFORMTYPE_FLOAT)\\n\\t\\t];\\n\\t\\tif (fisheyeEnabled) {\\n\\t\\t\\tuniforms.push(\\n\\t\\t\\t\\tnew UniformFormat(\\\"fisheye_k\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"fisheye_inv_k\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"fisheye_projMat00\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\t\\tnew UniformFormat(\\\"fisheye_projMat11\\\", UNIFORMTYPE_FLOAT)\\n\\t\\t\\t);\\n\\t\\t}\\n\\t\\tconst uniformBufferFormat = new UniformBufferFormat(device, uniforms);\\n\\t\\tconst wbFormat = this._dataSource.format;\\n\\t\\tconst fixedBindings = [\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"compactedSplatIds\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"sortElementCount\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"projCache\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"tileSplatCounts\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"pairBuffer\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"countersBuffer\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"splatPairStart\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"splatPairCount\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"largeSplatIds\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"depthBuffer\\\", SHADERSTAGE_COMPUTE)\\n\\t\\t];\\n\\t\\tconst bindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\t...fixedBindings,\\n\\t\\t\\t...wbFormat.getComputeBindFormats()\\n\\t\\t]);\\n\\t\\tconst cincludes = this._createCommonIncludes();\\n\\t\\tcincludes.set(\\\"gsplatComputeSplatCS\\\", gsplatComputeSplat_default);\\n\\t\\tcincludes.set(\\\"gsplatFormatDeclCS\\\", wbFormat.getComputeInputDeclarations(fixedBindings.length));\\n\\t\\tcincludes.set(\\\"gsplatFormatReadCS\\\", wbFormat.getReadCode());\\n\\t\\tcincludes.set(\\\"gsplatProjectCommonCS\\\", computeGsplatProjectCommonSource);\\n\\t\\tconst cdefines = /* @__PURE__ */ new Map();\\n\\t\\tcdefines.set(\\\"{CACHE_STRIDE}\\\", CACHE_STRIDE.toString());\\n\\t\\tif (fisheyeEnabled) {\\n\\t\\t\\tcdefines.set(\\\"GSPLAT_FISHEYE\\\", \\\"\\\");\\n\\t\\t}\\n\\t\\tif (pickMode) {\\n\\t\\t\\tcdefines.set(\\\"PICK_MODE\\\", \\\"\\\");\\n\\t\\t}\\n\\t\\tconst colorStream = wbFormat.getStream(\\\"dataColor\\\");\\n\\t\\tif (colorStream && colorStream.format !== PIXELFORMAT_RGBA16U) {\\n\\t\\t\\tcdefines.set(\\\"GSPLAT_COLOR_FLOAT\\\", \\\"\\\");\\n\\t\\t}\\n\\t\\tconst suffix = fisheyeEnabled ? \\\"Fisheye\\\" : \\\"\\\";\\n\\t\\tconst shader = new Shader(device, {\\n\\t\\t\\tname: pickMode ? `GSplatLocalTileCountPick${suffix}` : `GSplatLocalTileCount${suffix}`,\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tcshader: computeGsplatLocalTileCountSource,\\n\\t\\t\\tcincludes,\\n\\t\\t\\tcdefines,\\n\\t\\t\\tcomputeBindGroupFormat: bindGroupFormat,\\n\\t\\t\\tcomputeUniformBufferFormats: { uniforms: uniformBufferFormat }\\n\\t\\t});\\n\\t\\treturn { shader, bindGroupFormat };\\n\\t}\\n\\t_createDispatchSet(pickMode) {\\n\\t\\tconst device = this.device;\\n\\t\\tconst set = new GSplatLocalDispatchSet(device, pickMode);\\n\\t\\tset.placeEntriesCompute = new Compute(device, this._placeEntriesShader, pickMode ? \\\"GSplatPickPlaceEntries\\\" : \\\"GSplatLocalPlaceEntries\\\");\\n\\t\\tset.largeSplatCompute = new Compute(device, this._largeSplatShader, pickMode ? \\\"GSplatPickLargeTileCount\\\" : \\\"GSplatLocalLargeTileCount\\\");\\n\\t\\tset.largePlaceEntriesCompute = new Compute(device, this._largePlaceEntriesShader, pickMode ? \\\"GSplatPickLargePlaceEntries\\\" : \\\"GSplatLocalLargePlaceEntries\\\");\\n\\t\\tset.classifyCompute = new Compute(device, this._classifyShader, pickMode ? \\\"GSplatPickClassify\\\" : \\\"GSplatLocalClassify\\\");\\n\\t\\tset.sortCompute = new Compute(device, this._sortShader, pickMode ? \\\"GSplatPickTileSort\\\" : \\\"GSplatLocalTileSort\\\");\\n\\t\\tset.bucketSortCompute = new Compute(device, this._bucketSortShader, pickMode ? \\\"GSplatPickBucketSort\\\" : \\\"GSplatLocalBucketSort\\\");\\n\\t\\tset.copyCompute = new Compute(device, this._copyShader, pickMode ? \\\"GSplatPickCopy\\\" : \\\"GSplatLocalCopy\\\");\\n\\t\\tset.chunkSortCompute = new Compute(device, this._chunkSortShader, pickMode ? \\\"GSplatPickChunkSort\\\" : \\\"GSplatLocalChunkSort\\\");\\n\\t\\treturn set;\\n\\t}\\n}\\n\\nconst computeGsplatProjectorSource = `\\n#include \\\"gsplatCommonCS\\\"\\n#include \\\"gsplatTileIntersectCS\\\"\\n@group(0) @binding(0) var<storage, read> compactedSplatIds: array<u32>;\\n@group(0) @binding(1) var<storage, read> sortElementCount: array<u32>;\\n@group(0) @binding(2) var<storage, read_write> projCache: array<u32>;\\n@group(0) @binding(3) var<storage, read_write> sortKeys: array<u32>;\\n@group(0) @binding(4) var<storage, read_write> renderCounter: array<atomic<u32>>;\\nstruct BinWeight {\\n\\tbase: f32,\\n\\tdivider: f32\\n}\\n@group(0) @binding(5) var<storage, read> binWeights: array<BinWeight>;\\nstruct ProjectorUniforms {\\n\\tsplatTextureSize: u32,\\n\\tnumBins: u32,\\n\\tisOrtho: u32,\\n\\tpad0: u32,\\n\\tviewProj: mat4x4f,\\n\\tviewMatrix: mat4x4f,\\n\\tcameraPosition: vec3f,\\n\\tminPixelSize: f32,\\n\\tcameraDirection: vec3f,\\n\\tfocal: f32,\\n\\tviewportWidth: f32,\\n\\tviewportHeight: f32,\\n\\tnearClip: f32,\\n\\tfarClip: f32,\\n\\talphaClip: f32,\\n\\tminContribution: f32,\\n\\tminDist: f32,\\n\\tinvRange: f32,\\n\\t#ifdef GSPLAT_FISHEYE\\n\\t\\tfisheye_k: f32,\\n\\t\\tfisheye_inv_k: f32,\\n\\t\\tfisheye_projMat00: f32,\\n\\t\\tfisheye_projMat11: f32,\\n\\t#endif\\n}\\n@group(0) @binding(6) var<uniform> uniforms: ProjectorUniforms;\\n#include \\\"gsplatComputeSplatCS\\\"\\n#include \\\"gsplatFormatDeclCS\\\"\\n#include \\\"gsplatFormatReadCS\\\"\\n#include \\\"gsplatProjectCommonCS\\\"\\nvar<workgroup> wgCount: atomic<u32>;\\nvar<workgroup> wgBase: u32;\\n@compute @workgroup_size(256)\\nfn main(\\n\\t@builtin(global_invocation_id) gid: vec3u,\\n\\t@builtin(num_workgroups) numWorkgroups: vec3u,\\n\\t@builtin(local_invocation_index) localIdx: u32\\n) {\\n\\tif (localIdx == 0u) {\\n\\t\\tatomicStore(&wgCount, 0u);\\n\\t}\\n\\tworkgroupBarrier();\\n\\tlet threadIdx = gid.y * (numWorkgroups.x * 256u) + gid.x;\\n\\tlet numVisible = sortElementCount[0];\\n\\tvar valid = false;\\n\\tvar clipPos: vec4f = vec4f(0.0);\\n\\tvar v1: vec2f = vec2f(0.0);\\n\\tvar v2: vec2f = vec2f(0.0);\\n\\tvar rgb: vec3f = vec3f(0.0);\\n\\tvar alpha: f32 = 0.0;\\n\\tvar pcId: u32 = 0u;\\n\\tvar sortKey: u32 = 0u;\\n\\tlet projected = projectSplatCommon(\\n\\t\\tthreadIdx,\\n\\t\\tnumVisible,\\n\\t\\tuniforms.alphaClip,\\n\\t\\tuniforms.minPixelSize,\\n\\t\\tuniforms.minContribution,\\n\\t\\tuniforms.viewMatrix,\\n\\t\\tuniforms.viewProj,\\n\\t\\tuniforms.focal,\\n\\t\\tuniforms.viewportWidth,\\n\\t\\tuniforms.viewportHeight,\\n\\t\\tuniforms.nearClip,\\n\\t\\tuniforms.farClip,\\n\\t\\tuniforms.isOrtho,\\n\\t\\t#ifdef GSPLAT_FISHEYE\\n\\t\\t\\tuniforms.fisheye_k,\\n\\t\\t\\tuniforms.fisheye_inv_k,\\n\\t\\t\\tuniforms.fisheye_projMat00,\\n\\t\\t\\tuniforms.fisheye_projMat11,\\n\\t\\t#endif\\n\\t);\\n\\tif (projected.valid) {\\n\\t\\tlet center = projected.center;\\n\\t\\tlet opacity = projected.opacity;\\n\\t\\tlet proj = projected.proj;\\n\\t\\tlet mid = 0.5 * (proj.a + proj.c);\\n\\t\\tlet radius = length(vec2f(0.5 * (proj.a - proj.c), proj.b));\\n\\t\\tlet lambda1 = mid + radius;\\n\\t\\tlet lambda2 = max(mid - radius, 0.1);\\n\\t\\tlet vmin = min(1024.0, min(uniforms.viewportWidth, uniforms.viewportHeight));\\n\\t\\tlet l1 = 2.0 * min(sqrt(2.0 * lambda1), vmin);\\n\\t\\tlet l2 = 2.0 * min(sqrt(2.0 * lambda2), vmin);\\n\\t\\tlet dir = normalize(vec2f(proj.b, lambda1 - proj.a));\\n\\t\\tv1 = l1 * dir;\\n\\t\\tv2 = l2 * vec2f(dir.y, -dir.x);\\n\\t\\t#ifdef GSPLAT_FISHEYE\\n\\t\\t\\tlet viewCenter = uniforms.viewMatrix * vec4f(center, 1.0);\\n\\t\\t\\tlet neg_z = -viewCenter.z;\\n\\t\\t\\tlet ndcX = proj.screen.x / uniforms.viewportWidth * 2.0 - 1.0;\\n\\t\\t\\tlet ndcY = proj.screen.y / uniforms.viewportHeight * 2.0 - 1.0;\\n\\t\\t\\tlet depthNdc = clamp(\\n\\t\\t\\t\\t(neg_z - uniforms.nearClip) / (uniforms.farClip - uniforms.nearClip),\\n\\t\\t\\t\\t0.0, 1.0\\n\\t\\t\\t);\\n\\t\\t\\tclipPos = vec4f(ndcX, ndcY, depthNdc, 1.0);\\n\\t\\t#else\\n\\t\\t\\tclipPos = uniforms.viewProj * vec4f(center, 1.0);\\n\\t\\t\\tclipPos.z = clamp(clipPos.z, 0.0, abs(clipPos.w));\\n\\t\\t#endif\\n\\t\\t#ifdef RADIAL_SORT\\n\\t\\t\\tlet delta = center - uniforms.cameraPosition;\\n\\t\\t\\tlet radialDist = length(delta);\\n\\t\\t\\tlet dist = (1.0 / uniforms.invRange) - radialDist - uniforms.minDist;\\n\\t\\t#else\\n\\t\\t\\tlet toSplat = center - uniforms.cameraPosition;\\n\\t\\t\\tlet dist = dot(toSplat, uniforms.cameraDirection) - uniforms.minDist;\\n\\t\\t#endif\\n\\t\\tlet d = dist * uniforms.invRange * f32(uniforms.numBins);\\n\\t\\tlet binFloat = clamp(d, 0.0, f32(uniforms.numBins) - 0.001);\\n\\t\\tlet bin = u32(binFloat);\\n\\t\\tlet binFrac = binFloat - f32(bin);\\n\\t\\tsortKey = u32(binWeights[bin].base + binWeights[bin].divider * binFrac);\\n\\t\\t#ifdef PICK_MODE\\n\\t\\t\\tpcId = loadPcId().r;\\n\\t\\t\\talpha = opacity;\\n\\t\\t#else\\n\\t\\t\\tlet color = getColor();\\n\\t\\t\\trgb = max(color, vec3f(0.0));\\n\\t\\t\\t#if GSPLAT_AA\\n\\t\\t\\t\\talpha = opacity * proj.aaFactor;\\n\\t\\t\\t#else\\n\\t\\t\\t\\talpha = opacity;\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\tvalid = true;\\n\\t}\\n\\tvar localDst: u32 = 0u;\\n\\tif (valid) {\\n\\t\\tlocalDst = atomicAdd(&wgCount, 1u);\\n\\t}\\n\\tworkgroupBarrier();\\n\\tif (localIdx == 0u) {\\n\\t\\tlet total = atomicLoad(&wgCount);\\n\\t\\twgBase = atomicAdd(&renderCounter[0], total);\\n\\t}\\n\\tworkgroupBarrier();\\n\\tif (valid) {\\n\\t\\tlet dst = wgBase + localDst;\\n\\t\\tlet base = dst * {CACHE_STRIDE}u;\\n\\t\\tprojCache[base + 0u] = bitcast<u32>(clipPos.x);\\n\\t\\tprojCache[base + 1u] = bitcast<u32>(clipPos.y);\\n\\t\\tprojCache[base + 2u] = bitcast<u32>(clipPos.z);\\n\\t\\tprojCache[base + 3u] = bitcast<u32>(clipPos.w);\\n\\t\\tprojCache[base + 4u] = pack2x16float(v1);\\n\\t\\tprojCache[base + 5u] = pack2x16float(v2);\\n\\t\\t#ifdef PICK_MODE\\n\\t\\t\\tprojCache[base + 6u] = pcId;\\n\\t\\t\\tprojCache[base + 7u] = pack2x16float(vec2f(0.0, alpha));\\n\\t\\t#else\\n\\t\\t\\tprojCache[base + 6u] = pack2x16float(vec2f(rgb.x, rgb.y));\\n\\t\\t\\tprojCache[base + 7u] = pack2x16float(vec2f(rgb.z, alpha));\\n\\t\\t#endif\\n\\t\\tsortKeys[dst] = sortKey;\\n\\t}\\n}\\n`;\\n\\nconst computeGsplatProjectorWriteIndirectArgsSource = `\\n${indirect_core_default}\\n${dispatch_core_default}\\n${sort_indirect_args_default}\\n@group(0) @binding(0) var<storage, read> renderCounter: array<u32>;\\n@group(0) @binding(1) var<storage, read_write> indirectDrawArgs: array<DrawIndexedIndirectArgs>;\\n@group(0) @binding(2) var<storage, read_write> numSplatsBuf: array<u32>;\\n@group(0) @binding(3) var<storage, read_write> indirectDispatchArgs: array<u32>;\\n@group(0) @binding(4) var<storage, read_write> sortElementCountBuf: array<u32>;\\nstruct WriteArgsUniforms {\\n\\tdrawSlot: u32,\\n\\tindexCount: u32,\\n\\tsortSlotBase: u32,\\n\\tpad0: u32,\\n\\tsortIndirectInfo: vec4<u32>\\n};\\n@group(0) @binding(5) var<uniform> uniforms: WriteArgsUniforms;\\n@compute @workgroup_size(1)\\nfn main() {\\n\\tlet count = renderCounter[0];\\n\\tlet instanceCount = (count + {INSTANCE_SIZE}u - 1u) / {INSTANCE_SIZE}u;\\n\\tindirectDrawArgs[uniforms.drawSlot] = DrawIndexedIndirectArgs(\\n\\t\\tuniforms.indexCount,\\n\\t\\tinstanceCount,\\n\\t\\t0u,\\n\\t\\t0,\\n\\t\\t0u\\n\\t);\\n\\tnumSplatsBuf[0] = count;\\n\\tsortElementCountBuf[0] = count;\\n\\twriteSortIndirectArgs(uniforms.sortSlotBase, count, uniforms.sortIndirectInfo);\\n}\\n`;\\n\\nconst INDEX_COUNT$1 = 6 * GSplatResourceBase.instanceSize;\\nconst PROJECTOR_WORKGROUP_SIZE = 256;\\nconst _cameraDir = new Vec3();\\nconst _dispatchSize = new Vec2();\\nconst _viewProjMat = new Mat4();\\nconst _viewProjData = new Float32Array(16);\\nconst _viewData = new Float32Array(16);\\nconst _shaderProjMat = new Mat4();\\nclass GSplatProjector {\\n\\tdevice;\\n\\tprojCache = null;\\n\\tsortKeys = null;\\n\\trenderCounter = null;\\n\\tbinWeightsBuffer = null;\\n\\tbinWeightsUtil;\\n\\t_projectorComputes = /* @__PURE__ */ new Map();\\n\\t_projectorBindGroupFormat = null;\\n\\t_projectorUniformBufferFormat = null;\\n\\t_projectorUniformBufferFormatFisheye = null;\\n\\t_writeIndirectArgsCompute = null;\\n\\t_writeArgsBindGroupFormat = null;\\n\\t_writeArgsUniformBufferFormat = null;\\n\\t_formatVersion = -1;\\n\\t_allocatedCacheCount = 0;\\n\\tcameraPositionData = new Float32Array(3);\\n\\tcameraDirectionData = new Float32Array(3);\\n\\tconstructor(device) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.binWeightsUtil = new GSplatSortBinWeights$1();\\n\\t\\tthis.binWeightsBuffer = new StorageBuffer(\\n\\t\\t\\tdevice,\\n\\t\\t\\tGSplatSortBinWeights$1.NUM_BINS * 2 * 4,\\n\\t\\t\\tBUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST\\n\\t\\t);\\n\\t\\tthis.renderCounter = new StorageBuffer(device, 4, BUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST);\\n\\t\\tthis._createUniformBufferFormats();\\n\\t\\tthis._createWriteIndirectArgsCompute();\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.projCache?.destroy();\\n\\t\\tthis.sortKeys?.destroy();\\n\\t\\tthis.renderCounter?.destroy();\\n\\t\\tthis.binWeightsBuffer?.destroy();\\n\\t\\tfor (const compute of this._projectorComputes.values()) {\\n\\t\\t\\tcompute.shader?.destroy();\\n\\t\\t}\\n\\t\\tthis._projectorComputes.clear();\\n\\t\\tthis._projectorBindGroupFormat?.destroy();\\n\\t\\tthis._writeIndirectArgsCompute?.shader?.destroy();\\n\\t\\tthis._writeArgsBindGroupFormat?.destroy();\\n\\t\\tthis.projCache = null;\\n\\t\\tthis.sortKeys = null;\\n\\t\\tthis.renderCounter = null;\\n\\t\\tthis.binWeightsBuffer = null;\\n\\t\\tthis._projectorBindGroupFormat = null;\\n\\t\\tthis._projectorUniformBufferFormat = null;\\n\\t\\tthis._projectorUniformBufferFormatFisheye = null;\\n\\t\\tthis._writeIndirectArgsCompute = null;\\n\\t\\tthis._writeArgsBindGroupFormat = null;\\n\\t\\tthis._writeArgsUniformBufferFormat = null;\\n\\t}\\n\\t_createUniformBufferFormats() {\\n\\t\\tconst device = this.device;\\n\\t\\tconst baseFields = [\\n\\t\\t\\tnew UniformFormat(\\\"splatTextureSize\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"numBins\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"isOrtho\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"pad0\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"viewProj\\\", UNIFORMTYPE_MAT4),\\n\\t\\t\\tnew UniformFormat(\\\"viewMatrix\\\", UNIFORMTYPE_MAT4),\\n\\t\\t\\tnew UniformFormat(\\\"cameraPosition\\\", UNIFORMTYPE_VEC3),\\n\\t\\t\\tnew UniformFormat(\\\"minPixelSize\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"cameraDirection\\\", UNIFORMTYPE_VEC3),\\n\\t\\t\\tnew UniformFormat(\\\"focal\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"viewportWidth\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"viewportHeight\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"nearClip\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"farClip\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"alphaClip\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"minContribution\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"minDist\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"invRange\\\", UNIFORMTYPE_FLOAT)\\n\\t\\t];\\n\\t\\tthis._projectorUniformBufferFormat = new UniformBufferFormat(device, baseFields);\\n\\t\\tthis._projectorUniformBufferFormatFisheye = new UniformBufferFormat(device, [\\n\\t\\t\\t...baseFields.map((f) => new UniformFormat(f.name, f.type)),\\n\\t\\t\\tnew UniformFormat(\\\"fisheye_k\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"fisheye_inv_k\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"fisheye_projMat00\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"fisheye_projMat11\\\", UNIFORMTYPE_FLOAT)\\n\\t\\t]);\\n\\t\\tthis._writeArgsUniformBufferFormat = new UniformBufferFormat(device, [\\n\\t\\t\\tnew UniformFormat(\\\"drawSlot\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"indexCount\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"sortSlotBase\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"pad0\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"sortIndirectInfo\\\", UNIFORMTYPE_UVEC4)\\n\\t\\t]);\\n\\t}\\n\\t_createWriteIndirectArgsCompute() {\\n\\t\\tconst device = this.device;\\n\\t\\tthis._writeArgsBindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"renderCounter\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"indirectDrawArgs\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"numSplatsBuf\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"indirectDispatchArgs\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"sortElementCountBuf\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE)\\n\\t\\t]);\\n\\t\\tconst cdefines = /* @__PURE__ */ new Map([\\n\\t\\t\\t[\\\"{INSTANCE_SIZE}\\\", GSplatResourceBase.instanceSize.toString()]\\n\\t\\t]);\\n\\t\\tconst shader = new Shader(device, {\\n\\t\\t\\tname: \\\"GSplatProjectorWriteIndirectArgs\\\",\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tcshader: computeGsplatProjectorWriteIndirectArgsSource,\\n\\t\\t\\tcdefines,\\n\\t\\t\\tcomputeBindGroupFormat: this._writeArgsBindGroupFormat,\\n\\t\\t\\tcomputeUniformBufferFormats: { uniforms: this._writeArgsUniformBufferFormat }\\n\\t\\t});\\n\\t\\tthis._writeIndirectArgsCompute = new Compute(device, shader, \\\"GSplatProjectorWriteIndirectArgs\\\");\\n\\t}\\n\\t_destroyProjectorComputes() {\\n\\t\\tfor (const compute of this._projectorComputes.values()) {\\n\\t\\t\\tcompute.shader?.destroy();\\n\\t\\t}\\n\\t\\tthis._projectorComputes.clear();\\n\\t\\tthis._projectorBindGroupFormat?.destroy();\\n\\t\\tthis._projectorBindGroupFormat = null;\\n\\t}\\n\\t_projectorKey(radialSort, pickMode, fisheyeMode, antiAlias) {\\n\\t\\treturn `${radialSort ? \\\"r\\\" : \\\"l\\\"}${pickMode ? \\\"p\\\" : \\\"\\\"}${fisheyeMode ? \\\"f\\\" : \\\"\\\"}${antiAlias ? \\\"a\\\" : \\\"\\\"}`;\\n\\t}\\n\\t_createProjectorCompute(workBuffer, radialSort, pickMode, fisheyeMode, antiAlias) {\\n\\t\\tconst device = this.device;\\n\\t\\tconst wbFormat = workBuffer.format;\\n\\t\\tconst fixedBindings = [\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"compactedSplatIds\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"sortElementCount\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"projCache\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"sortKeys\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"renderCounter\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"binWeights\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE)\\n\\t\\t];\\n\\t\\tif (!this._projectorBindGroupFormat) {\\n\\t\\t\\tthis._projectorBindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\t\\t...fixedBindings,\\n\\t\\t\\t\\t...wbFormat.getComputeBindFormats()\\n\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tconst cincludes = /* @__PURE__ */ new Map();\\n\\t\\tcincludes.set(\\\"gsplatCommonCS\\\", computeGsplatCommonSource);\\n\\t\\tcincludes.set(\\\"gsplatTileIntersectCS\\\", computeGsplatTileIntersectSource);\\n\\t\\tcincludes.set(\\\"gsplatComputeSplatCS\\\", gsplatComputeSplat_default);\\n\\t\\tcincludes.set(\\\"gsplatFormatDeclCS\\\", wbFormat.getComputeInputDeclarations(fixedBindings.length));\\n\\t\\tcincludes.set(\\\"gsplatFormatReadCS\\\", wbFormat.getReadCode());\\n\\t\\tcincludes.set(\\\"gsplatProjectCommonCS\\\", computeGsplatProjectCommonSource);\\n\\t\\tconst cdefines = /* @__PURE__ */ new Map();\\n\\t\\tcdefines.set(\\\"{CACHE_STRIDE}\\\", CACHE_STRIDE$1.toString());\\n\\t\\tif (radialSort) {\\n\\t\\t\\tcdefines.set(\\\"RADIAL_SORT\\\", \\\"\\\");\\n\\t\\t}\\n\\t\\tif (pickMode) {\\n\\t\\t\\tcdefines.set(\\\"PICK_MODE\\\", \\\"\\\");\\n\\t\\t}\\n\\t\\tif (fisheyeMode) {\\n\\t\\t\\tcdefines.set(\\\"GSPLAT_FISHEYE\\\", \\\"\\\");\\n\\t\\t}\\n\\t\\tif (antiAlias) {\\n\\t\\t\\tcdefines.set(\\\"GSPLAT_AA\\\", \\\"\\\");\\n\\t\\t}\\n\\t\\tconst colorStream = wbFormat.getStream(\\\"dataColor\\\");\\n\\t\\tif (colorStream && colorStream.format !== PIXELFORMAT_RGBA16U) {\\n\\t\\t\\tcdefines.set(\\\"GSPLAT_COLOR_FLOAT\\\", \\\"\\\");\\n\\t\\t}\\n\\t\\tconst name = `GSplatProjector${radialSort ? \\\"Radial\\\" : \\\"Linear\\\"}${pickMode ? \\\"Pick\\\" : \\\"\\\"}${fisheyeMode ? \\\"Fisheye\\\" : \\\"\\\"}${antiAlias ? \\\"Aa\\\" : \\\"\\\"}`;\\n\\t\\tconst ubFormat = fisheyeMode ? this._projectorUniformBufferFormatFisheye : this._projectorUniformBufferFormat;\\n\\t\\tconst shader = new Shader(device, {\\n\\t\\t\\tname,\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tcshader: computeGsplatProjectorSource,\\n\\t\\t\\tcincludes,\\n\\t\\t\\tcdefines,\\n\\t\\t\\tcomputeBindGroupFormat: this._projectorBindGroupFormat,\\n\\t\\t\\tcomputeUniformBufferFormats: { uniforms: ubFormat }\\n\\t\\t});\\n\\t\\treturn new Compute(device, shader, name);\\n\\t}\\n\\t_getProjectorCompute(workBuffer, radialSort, pickMode = false, fisheyeMode = false, antiAlias = false) {\\n\\t\\tconst wbFormat = workBuffer.format;\\n\\t\\tif (this._formatVersion !== wbFormat.extraStreamsVersion) {\\n\\t\\t\\tthis._destroyProjectorComputes();\\n\\t\\t\\tthis._formatVersion = wbFormat.extraStreamsVersion;\\n\\t\\t}\\n\\t\\tconst key = this._projectorKey(radialSort, pickMode, fisheyeMode, antiAlias);\\n\\t\\tlet compute = this._projectorComputes.get(key);\\n\\t\\tif (!compute) {\\n\\t\\t\\tcompute = this._createProjectorCompute(workBuffer, radialSort, pickMode, fisheyeMode, antiAlias);\\n\\t\\t\\tthis._projectorComputes.set(key, compute);\\n\\t\\t}\\n\\t\\treturn compute;\\n\\t}\\n\\t_ensureCapacity(capacity) {\\n\\t\\tif (capacity > this._allocatedCacheCount) {\\n\\t\\t\\tthis.projCache?.destroy();\\n\\t\\t\\tthis.sortKeys?.destroy();\\n\\t\\t\\tthis._allocatedCacheCount = capacity;\\n\\t\\t\\tthis.projCache = new StorageBuffer(this.device, capacity * CACHE_STRIDE$1 * 4);\\n\\t\\t\\tthis.sortKeys = new StorageBuffer(this.device, capacity * 4, BUFFERUSAGE_COPY_SRC);\\n\\t\\t}\\n\\t}\\n\\tdispatch(params) {\\n\\t\\tconst {\\n\\t\\t\\tworkBuffer,\\n\\t\\t\\tcameraNode,\\n\\t\\t\\tcompactedSplatIds,\\n\\t\\t\\tsortElementCountBuffer,\\n\\t\\t\\ttotalCapacity,\\n\\t\\t\\tradialSort,\\n\\t\\t\\tnumBits,\\n\\t\\t\\tminDist,\\n\\t\\t\\tmaxDist,\\n\\t\\t\\talphaClip,\\n\\t\\t\\tminPixelSize,\\n\\t\\t\\tminContribution,\\n\\t\\t\\tviewportWidth,\\n\\t\\t\\tviewportHeight,\\n\\t\\t\\tflipY,\\n\\t\\t\\tpickMode = false,\\n\\t\\t\\tfisheyeProj,\\n\\t\\t\\tantiAlias = false\\n\\t\\t} = params;\\n\\t\\tconst fisheyeMode = !!fisheyeProj?.enabled;\\n\\t\\tconst aaMode = antiAlias && !pickMode;\\n\\t\\tthis._ensureCapacity(totalCapacity);\\n\\t\\tthis.renderCounter.clear();\\n\\t\\tconst compute = this._getProjectorCompute(workBuffer, radialSort, pickMode, fisheyeMode, aaMode);\\n\\t\\tconst cameraPos = cameraNode.getPosition();\\n\\t\\tconst cameraMat = cameraNode.getWorldTransform();\\n\\t\\tconst cameraDir = cameraMat.getZ(_cameraDir).normalize();\\n\\t\\tconst range = maxDist - minDist;\\n\\t\\tconst invRange = range > 0 ? 1 / range : 1;\\n\\t\\tconst bucketCount = 1 << numBits;\\n\\t\\tconst cameraBin = GSplatSortBinWeights$1.computeCameraBin(radialSort, minDist, range);\\n\\t\\tconst binWeights = this.binWeightsUtil.compute(cameraBin, bucketCount);\\n\\t\\tthis.binWeightsBuffer.write(0, binWeights);\\n\\t\\tcompute.setParameter(\\\"compactedSplatIds\\\", compactedSplatIds);\\n\\t\\tcompute.setParameter(\\\"sortElementCount\\\", sortElementCountBuffer);\\n\\t\\tcompute.setParameter(\\\"projCache\\\", this.projCache);\\n\\t\\tcompute.setParameter(\\\"sortKeys\\\", this.sortKeys);\\n\\t\\tcompute.setParameter(\\\"renderCounter\\\", this.renderCounter);\\n\\t\\tcompute.setParameter(\\\"binWeights\\\", this.binWeightsBuffer);\\n\\t\\tfor (const stream of workBuffer.format.resourceStreams) {\\n\\t\\t\\tconst texture = workBuffer.getTexture(stream.name);\\n\\t\\t\\tif (texture) {\\n\\t\\t\\t\\tcompute.setParameter(stream.name, texture);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst cameraComponent = cameraNode.camera;\\n\\t\\tconst cam = cameraComponent.camera;\\n\\t\\tconst view = cam.viewMatrix;\\n\\t\\tconst webgpu = this.device.isWebGPU;\\n\\t\\t_viewProjMat.mul2(Camera$1.applyShaderProjectionTransform(cam.projectionMatrix, _shaderProjMat, flipY, webgpu), view);\\n\\t\\t_viewProjData.set(_viewProjMat.data);\\n\\t\\t_viewData.set(view.data);\\n\\t\\tconst focal = viewportWidth * _shaderProjMat.data[0];\\n\\t\\tthis.cameraPositionData[0] = cameraPos.x;\\n\\t\\tthis.cameraPositionData[1] = cameraPos.y;\\n\\t\\tthis.cameraPositionData[2] = cameraPos.z;\\n\\t\\tcompute.setParameter(\\\"cameraPosition\\\", this.cameraPositionData);\\n\\t\\tthis.cameraDirectionData[0] = cameraDir.x;\\n\\t\\tthis.cameraDirectionData[1] = cameraDir.y;\\n\\t\\tthis.cameraDirectionData[2] = cameraDir.z;\\n\\t\\tcompute.setParameter(\\\"cameraDirection\\\", this.cameraDirectionData);\\n\\t\\tcompute.setParameter(\\\"viewMatrix\\\", _viewData);\\n\\t\\tcompute.setParameter(\\\"viewProj\\\", _viewProjData);\\n\\t\\tcompute.setParameter(\\\"focal\\\", focal);\\n\\t\\tcompute.setParameter(\\\"viewportWidth\\\", viewportWidth);\\n\\t\\tcompute.setParameter(\\\"viewportHeight\\\", viewportHeight);\\n\\t\\tcompute.setParameter(\\\"nearClip\\\", cam.nearClip);\\n\\t\\tcompute.setParameter(\\\"farClip\\\", cam.farClip);\\n\\t\\tcompute.setParameter(\\\"alphaClip\\\", alphaClip);\\n\\t\\tcompute.setParameter(\\\"minPixelSize\\\", minPixelSize);\\n\\t\\tcompute.setParameter(\\\"minContribution\\\", minContribution);\\n\\t\\tcompute.setParameter(\\\"isOrtho\\\", cam.projection === PROJECTION_ORTHOGRAPHIC ? 1 : 0);\\n\\t\\tcompute.setParameter(\\\"splatTextureSize\\\", workBuffer.textureSize);\\n\\t\\tcompute.setParameter(\\\"numBins\\\", GSplatSortBinWeights$1.NUM_BINS);\\n\\t\\tcompute.setParameter(\\\"minDist\\\", minDist);\\n\\t\\tcompute.setParameter(\\\"invRange\\\", invRange);\\n\\t\\tcompute.setParameter(\\\"pad0\\\", 0);\\n\\t\\tif (fisheyeMode) {\\n\\t\\t\\tcompute.setParameter(\\\"fisheye_k\\\", fisheyeProj.k);\\n\\t\\t\\tcompute.setParameter(\\\"fisheye_inv_k\\\", fisheyeProj.invK);\\n\\t\\t\\tcompute.setParameter(\\\"fisheye_projMat00\\\", fisheyeProj.projMat00);\\n\\t\\t\\tcompute.setParameter(\\\"fisheye_projMat11\\\", fisheyeProj.projMat11);\\n\\t\\t}\\n\\t\\tconst workgroupCount = Math.ceil(totalCapacity / PROJECTOR_WORKGROUP_SIZE);\\n\\t\\tCompute.calcDispatchSize(\\n\\t\\t\\tworkgroupCount,\\n\\t\\t\\t_dispatchSize,\\n\\t\\t\\tthis.device.limits.maxComputeWorkgroupsPerDimension || 65535\\n\\t\\t);\\n\\t\\tcompute.setupDispatch(_dispatchSize.x, _dispatchSize.y, 1);\\n\\t\\tthis.device.computeDispatch([compute], \\\"GSplatProjector\\\");\\n\\t}\\n\\twriteIndirectArgs(drawSlot, sortSlotBase, numSplatsBuffer, sortElementCountBuffer, sortIndirectInfo) {\\n\\t\\tconst compute = this._writeIndirectArgsCompute;\\n\\t\\tcompute.setParameter(\\\"renderCounter\\\", this.renderCounter);\\n\\t\\tcompute.setParameter(\\\"indirectDrawArgs\\\", this.device.indirectDrawBuffer);\\n\\t\\tcompute.setParameter(\\\"numSplatsBuf\\\", numSplatsBuffer);\\n\\t\\tcompute.setParameter(\\\"indirectDispatchArgs\\\", this.device.indirectDispatchBuffer);\\n\\t\\tcompute.setParameter(\\\"sortElementCountBuf\\\", sortElementCountBuffer);\\n\\t\\tcompute.setParameter(\\\"drawSlot\\\", drawSlot);\\n\\t\\tcompute.setParameter(\\\"indexCount\\\", INDEX_COUNT$1);\\n\\t\\tcompute.setParameter(\\\"sortSlotBase\\\", sortSlotBase);\\n\\t\\tcompute.setParameter(\\\"pad0\\\", 0);\\n\\t\\tcompute.setParameter(\\\"sortIndirectInfo\\\", sortIndirectInfo);\\n\\t\\tcompute.setupDispatch(1);\\n\\t\\tthis.device.computeDispatch([compute], \\\"GSplatProjectorWriteIndirectArgs\\\");\\n\\t}\\n}\\n\\nconst GsplatAllocId = new NumericIds();\\n\\nclass GSplatPlacement {\\n\\tresource;\\n\\tnode;\\n\\tintervals = /* @__PURE__ */ new Map();\\n\\tid = 0;\\n\\tallocId = GsplatAllocId.get();\\n\\tlodIndex = 0;\\n\\t_lodBaseDistance = 5;\\n\\t_lodMultiplier = 3;\\n\\tset lodBaseDistance(value) {\\n\\t\\tif (this._lodBaseDistance !== value) {\\n\\t\\t\\tthis._lodBaseDistance = value;\\n\\t\\t\\tthis.lodDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget lodBaseDistance() {\\n\\t\\treturn this._lodBaseDistance;\\n\\t}\\n\\tset lodMultiplier(value) {\\n\\t\\tif (this._lodMultiplier !== value) {\\n\\t\\t\\tthis._lodMultiplier = value;\\n\\t\\t\\tthis.lodDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget lodMultiplier() {\\n\\t\\treturn this._lodMultiplier;\\n\\t}\\n\\t_aabb = null;\\n\\tparameters = null;\\n\\t_streams = null;\\n\\tlodDirty = false;\\n\\trenderDirty = false;\\n\\tworkBufferUpdate = WORKBUFFER_UPDATE_AUTO;\\n\\t_lastFormatVersion = -1;\\n\\t_workBufferModifier = null;\\n\\tparentPlacement = null;\\n\\tconstructor(resource, node, lodIndex = 0, parameters = null, parentPlacement = null, id = null) {\\n\\t\\tthis.id = id ?? parentPlacement?.id ?? 0;\\n\\t\\tthis.resource = resource;\\n\\t\\tthis.node = node;\\n\\t\\tthis.lodIndex = lodIndex;\\n\\t\\tthis.parameters = parameters ?? parentPlacement?.parameters ?? null;\\n\\t\\tthis.parentPlacement = parentPlacement;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._streams?.destroy();\\n\\t\\tthis._streams = null;\\n\\t\\tthis.intervals.clear();\\n\\t\\tthis.resource = null;\\n\\t}\\n\\tset workBufferModifier(value) {\\n\\t\\tthis._workBufferModifier = value;\\n\\t\\tthis.renderDirty = true;\\n\\t}\\n\\tget workBufferModifier() {\\n\\t\\treturn this.parentPlacement?.workBufferModifier ?? this._workBufferModifier;\\n\\t}\\n\\tconsumeRenderDirty() {\\n\\t\\tconst format = this.resource?.format;\\n\\t\\tif (format && this._lastFormatVersion !== format.extraStreamsVersion) {\\n\\t\\t\\tthis._lastFormatVersion = format.extraStreamsVersion;\\n\\t\\t\\tthis.renderDirty = true;\\n\\t\\t}\\n\\t\\tif (this.workBufferUpdate === WORKBUFFER_UPDATE_ALWAYS) {\\n\\t\\t\\tthis.renderDirty = true;\\n\\t\\t} else if (this.workBufferUpdate === WORKBUFFER_UPDATE_ONCE) {\\n\\t\\t\\tthis.renderDirty = true;\\n\\t\\t\\tthis.workBufferUpdate = WORKBUFFER_UPDATE_AUTO;\\n\\t\\t}\\n\\t\\tconst dirty = this.renderDirty;\\n\\t\\tthis.renderDirty = false;\\n\\t\\treturn dirty;\\n\\t}\\n\\tset aabb(aabb) {\\n\\t\\tthis._aabb = aabb?.clone() ?? null;\\n\\t}\\n\\tget aabb() {\\n\\t\\tconst aabb = this._aabb ?? this.resource?.aabb;\\n\\t\\treturn aabb;\\n\\t}\\n\\tgetLodDistance(level) {\\n\\t\\treturn this.lodBaseDistance * Math.pow(this.lodMultiplier, level);\\n\\t}\\n\\tgetInstanceTexture(name, device) {\\n\\t\\tconst resource = this.resource;\\n\\t\\tif (!resource?.format) {\\n\\t\\t\\treturn void 0;\\n\\t\\t}\\n\\t\\tif (!this._streams && resource.format.instanceStreams.length > 0) {\\n\\t\\t\\tthis._streams = new GSplatStreams(device, true);\\n\\t\\t\\tthis._streams.textureDimensions.copy(resource.streams.textureDimensions);\\n\\t\\t\\tthis._streams.syncWithFormat(resource.format);\\n\\t\\t}\\n\\t\\treturn this._streams?.getTexture(name);\\n\\t}\\n\\tget streams() {\\n\\t\\treturn this.parentPlacement?.streams ?? this._streams;\\n\\t}\\n\\tensureInstanceStreams(device) {\\n\\t\\tconst resource = this.resource;\\n\\t\\tif (!resource?.format) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!this._streams && resource.format.instanceStreams.length > 0) {\\n\\t\\t\\tthis._streams = new GSplatStreams(device, true);\\n\\t\\t\\tthis._streams.textureDimensions.copy(resource.streams.textureDimensions);\\n\\t\\t\\tthis._streams.syncWithFormat(resource.format);\\n\\t\\t}\\n\\t}\\n}\\n\\nconst _invWorldMat = new Mat4();\\nconst _localCameraPos = new Vec3();\\nconst _localCameraFwd = new Vec3();\\nconst _tempCompletedUrls = [];\\nnew BoundingBox();\\nconst REF_TAN_HALF_FOV = Math.tan(22.5 * math.DEG_TO_RAD);\\n[\\n\\tnew Color(1, 0, 0),\\n\\tnew Color(0, 1, 0),\\n\\tnew Color(0, 0, 1),\\n\\tnew Color(1, 1, 0),\\n\\tnew Color(1, 0, 1)\\n];\\nclass NodeInfo {\\n\\tcurrentLod = -1;\\n\\toptimalLod = -1;\\n\\tworldDistance = 0;\\n\\tcolorAccumulatedTranslation = 0;\\n\\tinst = null;\\n\\tlods = null;\\n\\tbudgetBucket = 0;\\n\\tallocId = GsplatAllocId.get();\\n\\tresetLod() {\\n\\t\\tthis.currentLod = -1;\\n\\t\\tthis.optimalLod = -1;\\n\\t}\\n}\\nclass GSplatOctreeInstance {\\n\\toctree;\\n\\tplacement;\\n\\tactivePlacements = /* @__PURE__ */ new Set();\\n\\tdirtyModifiedPlacements = false;\\n\\tdirtyPlacementSetChanged = false;\\n\\tdevice;\\n\\tnodeInfos;\\n\\tfilePlacements;\\n\\tpending = /* @__PURE__ */ new Set();\\n\\tpendingDecrements = /* @__PURE__ */ new Map();\\n\\tremovedCandidates = /* @__PURE__ */ new Set();\\n\\trangeMin = 0;\\n\\trangeMax = 0;\\n\\tpreviousPosition = new Vec3();\\n\\tneedsLodUpdate = false;\\n\\tprefetchPending = /* @__PURE__ */ new Set();\\n\\tpendingVisibleAdds = /* @__PURE__ */ new Map();\\n\\tget pendingLoadCount() {\\n\\t\\tlet count = this.pending.size + this.prefetchPending.size;\\n\\t\\tif (this.octree.environmentUrl && !this.environmentPlacement) {\\n\\t\\t\\tcount++;\\n\\t\\t}\\n\\t\\treturn count;\\n\\t}\\n\\tenvironmentPlacement = null;\\n\\t_deviceLostEvent = null;\\n\\t_lodMinDistThresholds = null;\\n\\tconstructor(device, octree, placement) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.octree = octree;\\n\\t\\tthis.placement = placement;\\n\\t\\tthis.nodeInfos = new Array(octree.nodes.length);\\n\\t\\tfor (let i = 0; i < octree.nodes.length; i++) {\\n\\t\\t\\tconst nodeInfo = new NodeInfo();\\n\\t\\t\\tnodeInfo.inst = this;\\n\\t\\t\\tthis.nodeInfos[i] = nodeInfo;\\n\\t\\t}\\n\\t\\tconst numFiles = octree.files.length;\\n\\t\\tthis.filePlacements = new Array(numFiles).fill(null);\\n\\t\\tif (octree.environmentUrl) {\\n\\t\\t\\toctree.incEnvironmentRefCount();\\n\\t\\t\\toctree.ensureEnvironmentResource();\\n\\t\\t}\\n\\t\\tthis._deviceLostEvent = device.on(\\\"devicelost\\\", this._onDeviceLost, this);\\n\\t}\\n\\tdestroy(skipRefCounting = false) {\\n\\t\\tif (!skipRefCounting && this.octree && !this.octree.destroyed) {\\n\\t\\t\\tconst filesToDecRef = this.getFileDecrements();\\n\\t\\t\\tfor (const fileIndex of filesToDecRef) {\\n\\t\\t\\t\\tthis.octree.decRefCount(fileIndex, 0);\\n\\t\\t\\t}\\n\\t\\t\\tfor (const fileIndex of this.pending) {\\n\\t\\t\\t\\tif (!this.filePlacements[fileIndex]) {\\n\\t\\t\\t\\t\\tthis.octree.unloadResource(fileIndex);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tfor (const fileIndex of this.prefetchPending) {\\n\\t\\t\\t\\tif (!this.filePlacements[fileIndex]) {\\n\\t\\t\\t\\t\\tthis.octree.unloadResource(fileIndex);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (this.environmentPlacement) {\\n\\t\\t\\t\\tthis.octree.decEnvironmentRefCount();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.pending.clear();\\n\\t\\tthis.pendingDecrements.clear();\\n\\t\\tthis.filePlacements.length = 0;\\n\\t\\tif (this.environmentPlacement) {\\n\\t\\t\\tthis.activePlacements.delete(this.environmentPlacement);\\n\\t\\t\\tthis.environmentPlacement = null;\\n\\t\\t}\\n\\t\\tthis._deviceLostEvent?.off();\\n\\t\\tthis._deviceLostEvent = null;\\n\\t}\\n\\t_onDeviceLost() {\\n\\t\\tfor (let i = 0; i < this.filePlacements.length; i++) {\\n\\t\\t\\tif (this.filePlacements[i]) {\\n\\t\\t\\t\\tthis.octree.decRefCount(i, 0);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.filePlacements.fill(null);\\n\\t\\tthis.activePlacements.clear();\\n\\t\\tthis.pending.clear();\\n\\t\\tthis.pendingDecrements.clear();\\n\\t\\tthis.removedCandidates.clear();\\n\\t\\tthis.prefetchPending.clear();\\n\\t\\tthis.pendingVisibleAdds.clear();\\n\\t\\tfor (const nodeInfo of this.nodeInfos) {\\n\\t\\t\\tnodeInfo.resetLod();\\n\\t\\t}\\n\\t\\tif (this.environmentPlacement) {\\n\\t\\t\\tthis.activePlacements.delete(this.environmentPlacement);\\n\\t\\t\\tthis.environmentPlacement = null;\\n\\t\\t\\tthis.octree.unloadEnvironmentResource();\\n\\t\\t}\\n\\t\\tthis.dirtyModifiedPlacements = true;\\n\\t\\tthis.dirtyPlacementSetChanged = true;\\n\\t\\tthis.needsLodUpdate = true;\\n\\t}\\n\\tgetFileDecrements() {\\n\\t\\tconst toRelease = [];\\n\\t\\tfor (let i = 0; i < this.filePlacements.length; i++) {\\n\\t\\t\\tif (this.filePlacements[i]) {\\n\\t\\t\\t\\ttoRelease.push(i);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn toRelease;\\n\\t}\\n\\tselectDesiredLodIndex(node, optimalLodIndex, maxLod, lodUnderfillLimit) {\\n\\t\\tif (lodUnderfillLimit > 0) {\\n\\t\\t\\tconst allowedMaxCoarseLod = Math.min(maxLod, optimalLodIndex + lodUnderfillLimit);\\n\\t\\t\\tfor (let lod = optimalLodIndex; lod <= allowedMaxCoarseLod; lod++) {\\n\\t\\t\\t\\tconst fi = node.lods[lod].fileIndex;\\n\\t\\t\\t\\tif (fi !== -1 && this.octree.getFileResource(fi)) {\\n\\t\\t\\t\\t\\treturn lod;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tfor (let lod = allowedMaxCoarseLod; lod >= optimalLodIndex; lod--) {\\n\\t\\t\\t\\tconst fi = node.lods[lod].fileIndex;\\n\\t\\t\\t\\tif (fi !== -1) {\\n\\t\\t\\t\\t\\treturn lod;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn optimalLodIndex;\\n\\t}\\n\\tprefetchNextLod(node, desiredLodIndex, optimalLodIndex) {\\n\\t\\tif (desiredLodIndex === -1 || optimalLodIndex === -1) return;\\n\\t\\tif (desiredLodIndex === optimalLodIndex) {\\n\\t\\t\\tconst fi = node.lods[optimalLodIndex].fileIndex;\\n\\t\\t\\tif (fi !== -1) {\\n\\t\\t\\t\\tthis.octree.ensureFileResource(fi);\\n\\t\\t\\t\\tif (!this.octree.getFileResource(fi)) {\\n\\t\\t\\t\\t\\tthis.prefetchPending.add(fi);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst targetLod = Math.max(optimalLodIndex, desiredLodIndex - 1);\\n\\t\\tfor (let lod = targetLod; lod >= optimalLodIndex; lod--) {\\n\\t\\t\\tconst fi = node.lods[lod].fileIndex;\\n\\t\\t\\tif (fi !== -1) {\\n\\t\\t\\t\\tthis.octree.ensureFileResource(fi);\\n\\t\\t\\t\\tif (!this.octree.getFileResource(fi)) {\\n\\t\\t\\t\\t\\tthis.prefetchPending.add(fi);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tupdateLod(cameraNode, params) {\\n\\t\\tconst maxLod = this.octree.lodLevels - 1;\\n\\t\\tconst { lodBaseDistance, lodMultiplier } = this.placement;\\n\\t\\tconst { lodRangeMin, lodRangeMax } = params;\\n\\t\\tconst rangeMin = Math.max(0, Math.min(lodRangeMin ?? 0, maxLod));\\n\\t\\tconst rangeMax = Math.max(rangeMin, Math.min(lodRangeMax ?? maxLod, maxLod));\\n\\t\\tconst uniformScale = this.placement.node.getWorldTransform().getScale().x;\\n\\t\\tthis.evaluateNodeLods(cameraNode, maxLod, lodBaseDistance, lodMultiplier, rangeMin, rangeMax, params, uniformScale, false);\\n\\t\\tthis.applyLodChanges(maxLod, params);\\n\\t}\\n\\t_ensureLodMinDistThresholds(maxLod, d0, m) {\\n\\t\\tconst needLen = maxLod + 1;\\n\\t\\tlet buf = this._lodMinDistThresholds;\\n\\t\\tif (!buf || buf.length < needLen) {\\n\\t\\t\\tbuf = new Float32Array(needLen);\\n\\t\\t\\tthis._lodMinDistThresholds = buf;\\n\\t\\t}\\n\\t\\tlet t = d0;\\n\\t\\tbuf[1] = t;\\n\\t\\tfor (let k = 2; k <= maxLod; k++) {\\n\\t\\t\\tt *= m;\\n\\t\\t\\tbuf[k] = t;\\n\\t\\t}\\n\\t\\treturn buf;\\n\\t}\\n\\tevaluateNodeLods(cameraNode, maxLod, lodBaseDistance, lodMultiplier, rangeMin, rangeMax, params, uniformScale, accumulateSplats = true, globalMaxDistanceForBuckets = 0) {\\n\\t\\tconst { lodBehindPenalty } = params;\\n\\t\\tconst camera = cameraNode.camera;\\n\\t\\tlet tanHalfVFov = Math.tan(camera.fov * 0.5 * math.DEG_TO_RAD);\\n\\t\\tif (camera.horizontalFov) {\\n\\t\\t\\ttanHalfVFov /= camera.aspectRatio;\\n\\t\\t}\\n\\t\\tconst tanHalfHFov = tanHalfVFov * camera.aspectRatio;\\n\\t\\tconst fovScale = Math.min(tanHalfVFov, tanHalfHFov) / REF_TAN_HALF_FOV;\\n\\t\\tconst worldCameraPosition = cameraNode.getPosition();\\n\\t\\tconst octreeWorldTransform = this.placement.node.getWorldTransform();\\n\\t\\t_invWorldMat.copy(octreeWorldTransform).invert();\\n\\t\\tconst localCameraPosition = _invWorldMat.transformPoint(worldCameraPosition, _localCameraPos);\\n\\t\\tconst worldCameraForward = cameraNode.forward;\\n\\t\\tconst localCameraForward = _invWorldMat.transformVector(worldCameraForward, _localCameraFwd).normalize();\\n\\t\\tconst nodes = this.octree.nodes;\\n\\t\\tconst nodeInfos = this.nodeInfos;\\n\\t\\tconst boundsFlat = this.octree.nodeBoundsMinMax;\\n\\t\\tconst px = localCameraPosition.x;\\n\\t\\tconst py = localCameraPosition.y;\\n\\t\\tconst pz = localCameraPosition.z;\\n\\t\\tconst fwx = localCameraForward.x;\\n\\t\\tconst fwy = localCameraForward.y;\\n\\t\\tconst fwz = localCameraForward.z;\\n\\t\\tlet totalSplats = 0;\\n\\t\\tlet minDistBuf = null;\\n\\t\\tif (maxLod >= 1) {\\n\\t\\t\\tminDistBuf = this._ensureLodMinDistThresholds(maxLod, lodBaseDistance, lodMultiplier);\\n\\t\\t}\\n\\t\\tconst bucketScale = globalMaxDistanceForBuckets > 0 ? NUM_BUCKETS / Math.sqrt(globalMaxDistanceForBuckets) : 0;\\n\\t\\tfor (let nodeIndex = 0; nodeIndex < nodes.length; nodeIndex++) {\\n\\t\\t\\tconst nodeInfo = nodeInfos[nodeIndex];\\n\\t\\t\\tconst b = nodeIndex * 6;\\n\\t\\t\\tlet qx = px;\\n\\t\\t\\tconst minX = boundsFlat[b];\\n\\t\\t\\tconst maxX = boundsFlat[b + 3];\\n\\t\\t\\tif (qx < minX) qx = minX;\\n\\t\\t\\telse if (qx > maxX) qx = maxX;\\n\\t\\t\\tlet qy = py;\\n\\t\\t\\tconst minY = boundsFlat[b + 1];\\n\\t\\t\\tconst maxY = boundsFlat[b + 4];\\n\\t\\t\\tif (qy < minY) qy = minY;\\n\\t\\t\\telse if (qy > maxY) qy = maxY;\\n\\t\\t\\tlet qz = pz;\\n\\t\\t\\tconst minZ = boundsFlat[b + 2];\\n\\t\\t\\tconst maxZ = boundsFlat[b + 5];\\n\\t\\t\\tif (qz < minZ) qz = minZ;\\n\\t\\t\\telse if (qz > maxZ) qz = maxZ;\\n\\t\\t\\tconst dx = qx - px;\\n\\t\\t\\tconst dy = qy - py;\\n\\t\\t\\tconst dz = qz - pz;\\n\\t\\t\\tconst actualDistance = Math.sqrt(dx * dx + dy * dy + dz * dz);\\n\\t\\t\\tlet penalizedDistance = actualDistance;\\n\\t\\t\\tif (lodBehindPenalty > 1 && actualDistance > 0.01) {\\n\\t\\t\\t\\tconst dotOverDistance = (fwx * dx + fwy * dy + fwz * dz) / actualDistance;\\n\\t\\t\\t\\tif (dotOverDistance < 0) {\\n\\t\\t\\t\\t\\tconst t = -dotOverDistance;\\n\\t\\t\\t\\t\\tconst factor = 1 + t * (lodBehindPenalty - 1);\\n\\t\\t\\t\\t\\tpenalizedDistance = actualDistance * factor;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tconst fovAdjustedDistance = penalizedDistance * fovScale;\\n\\t\\t\\tlet optimalLodIndex;\\n\\t\\t\\tif (maxLod === 0 || fovAdjustedDistance < lodBaseDistance) {\\n\\t\\t\\t\\toptimalLodIndex = 0;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\toptimalLodIndex = maxLod;\\n\\t\\t\\t\\twhile (optimalLodIndex > 1 && fovAdjustedDistance < minDistBuf[optimalLodIndex]) {\\n\\t\\t\\t\\t\\toptimalLodIndex--;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (optimalLodIndex < rangeMin) optimalLodIndex = rangeMin;\\n\\t\\t\\tif (optimalLodIndex > rangeMax) optimalLodIndex = rangeMax;\\n\\t\\t\\tnodeInfo.optimalLod = optimalLodIndex;\\n\\t\\t\\tnodeInfo.worldDistance = fovAdjustedDistance * uniformScale;\\n\\t\\t\\tif (bucketScale > 0 && optimalLodIndex >= 0) {\\n\\t\\t\\t\\tconst bucket = Math.sqrt(nodeInfo.worldDistance) * bucketScale >>> 0;\\n\\t\\t\\t\\tnodeInfo.budgetBucket = bucket < NUM_BUCKETS ? bucket : NUM_BUCKETS - 1;\\n\\t\\t\\t}\\n\\t\\t\\tif (accumulateSplats) {\\n\\t\\t\\t\\tconst lod = nodes[nodeIndex].lods[optimalLodIndex];\\n\\t\\t\\t\\tif (lod && lod.count) {\\n\\t\\t\\t\\t\\ttotalSplats += lod.count;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn totalSplats;\\n\\t}\\n\\tevaluateOptimalLods(cameraNode, params, budgetScale = 1, globalMaxDistanceForBuckets = 0) {\\n\\t\\tconst maxLod = this.octree.lodLevels - 1;\\n\\t\\tconst { lodBaseDistance, lodMultiplier } = this.placement;\\n\\t\\tconst { lodRangeMin, lodRangeMax } = params;\\n\\t\\tconst rangeMin = Math.max(0, Math.min(lodRangeMin ?? 0, maxLod));\\n\\t\\tconst rangeMax = Math.max(rangeMin, Math.min(lodRangeMax ?? maxLod, maxLod));\\n\\t\\tthis.rangeMin = rangeMin;\\n\\t\\tthis.rangeMax = rangeMax;\\n\\t\\tconst uniformScale = this.placement.node.getWorldTransform().getScale().x;\\n\\t\\tconst effectiveBase = lodBaseDistance * budgetScale;\\n\\t\\tconst effectiveMult = Math.max(1.2, lodMultiplier * Math.pow(budgetScale, -0.2));\\n\\t\\treturn this.evaluateNodeLods(\\n\\t\\t\\tcameraNode,\\n\\t\\t\\tmaxLod,\\n\\t\\t\\teffectiveBase,\\n\\t\\t\\teffectiveMult,\\n\\t\\t\\trangeMin,\\n\\t\\t\\trangeMax,\\n\\t\\t\\tparams,\\n\\t\\t\\tuniformScale,\\n\\t\\t\\ttrue,\\n\\t\\t\\tglobalMaxDistanceForBuckets\\n\\t\\t);\\n\\t}\\n\\tapplyLodChanges(maxLod, params) {\\n\\t\\tconst nodes = this.octree.nodes;\\n\\t\\tconst { lodUnderfillLimit = 0 } = params;\\n\\t\\tfor (let nodeIndex = 0; nodeIndex < nodes.length; nodeIndex++) {\\n\\t\\t\\tconst node = nodes[nodeIndex];\\n\\t\\t\\tconst nodeInfo = this.nodeInfos[nodeIndex];\\n\\t\\t\\tconst optimalLodIndex = nodeInfo.optimalLod;\\n\\t\\t\\tconst currentLodIndex = nodeInfo.currentLod;\\n\\t\\t\\tconst desiredLodIndex = this.selectDesiredLodIndex(node, optimalLodIndex, maxLod, lodUnderfillLimit);\\n\\t\\t\\tif (desiredLodIndex !== currentLodIndex) {\\n\\t\\t\\t\\tconst currentFileIndex = currentLodIndex >= 0 ? node.lods[currentLodIndex].fileIndex : -1;\\n\\t\\t\\t\\tconst desiredFileIndex = desiredLodIndex >= 0 ? node.lods[desiredLodIndex].fileIndex : -1;\\n\\t\\t\\t\\tconst wasVisible = currentFileIndex !== -1;\\n\\t\\t\\t\\tconst willBeVisible = desiredFileIndex !== -1;\\n\\t\\t\\t\\tconst pendingEntry = this.pendingDecrements.get(nodeIndex);\\n\\t\\t\\t\\tif (pendingEntry) {\\n\\t\\t\\t\\t\\tif (pendingEntry.newFileIndex !== desiredFileIndex) {\\n\\t\\t\\t\\t\\t\\tconst prevPendingPlacement = this.filePlacements[pendingEntry.newFileIndex];\\n\\t\\t\\t\\t\\t\\tif (prevPendingPlacement) {\\n\\t\\t\\t\\t\\t\\t\\tthis.decrementFileRef(pendingEntry.newFileIndex, nodeIndex);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (wasVisible && willBeVisible) {\\n\\t\\t\\t\\t\\t\\t\\tthis.pendingDecrements.set(nodeIndex, { oldFileIndex: pendingEntry.oldFileIndex, newFileIndex: desiredFileIndex });\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tthis.pendingDecrements.delete(nodeIndex);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!wasVisible && willBeVisible) {\\n\\t\\t\\t\\t\\tconst prevPendingFi = this.pendingVisibleAdds.get(nodeIndex);\\n\\t\\t\\t\\t\\tif (prevPendingFi !== void 0 && prevPendingFi !== desiredFileIndex) {\\n\\t\\t\\t\\t\\t\\tthis.decrementFileRef(prevPendingFi, nodeIndex);\\n\\t\\t\\t\\t\\t\\tthis.pendingVisibleAdds.delete(nodeIndex);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tthis.incrementFileRef(desiredFileIndex, nodeIndex, desiredLodIndex);\\n\\t\\t\\t\\t\\tconst newPlacement = this.filePlacements[desiredFileIndex];\\n\\t\\t\\t\\t\\tif (newPlacement?.resource) {\\n\\t\\t\\t\\t\\t\\tnodeInfo.currentLod = desiredLodIndex;\\n\\t\\t\\t\\t\\t\\tthis.pendingVisibleAdds.delete(nodeIndex);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.pendingVisibleAdds.set(nodeIndex, desiredFileIndex);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else if (wasVisible && !willBeVisible) {\\n\\t\\t\\t\\t\\tconst pendingEntry2 = this.pendingDecrements.get(nodeIndex);\\n\\t\\t\\t\\t\\tif (pendingEntry2) {\\n\\t\\t\\t\\t\\t\\tthis.decrementFileRef(pendingEntry2.newFileIndex, nodeIndex);\\n\\t\\t\\t\\t\\t\\tthis.pendingDecrements.delete(nodeIndex);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tthis.decrementFileRef(currentFileIndex, nodeIndex);\\n\\t\\t\\t\\t\\tnodeInfo.currentLod = -1;\\n\\t\\t\\t\\t\\tthis.pendingVisibleAdds.delete(nodeIndex);\\n\\t\\t\\t\\t} else if (wasVisible && willBeVisible) {\\n\\t\\t\\t\\t\\tthis.incrementFileRef(desiredFileIndex, nodeIndex, desiredLodIndex);\\n\\t\\t\\t\\t\\tconst newPlacement = this.filePlacements[desiredFileIndex];\\n\\t\\t\\t\\t\\tif (newPlacement?.resource) {\\n\\t\\t\\t\\t\\t\\tthis.decrementFileRef(currentFileIndex, nodeIndex);\\n\\t\\t\\t\\t\\t\\tthis.pendingDecrements.delete(nodeIndex);\\n\\t\\t\\t\\t\\t\\tnodeInfo.currentLod = desiredLodIndex;\\n\\t\\t\\t\\t\\t\\tthis.pendingVisibleAdds.delete(nodeIndex);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.pendingDecrements.set(nodeIndex, { oldFileIndex: currentFileIndex, newFileIndex: desiredFileIndex });\\n\\t\\t\\t\\t\\t\\tthis.pendingVisibleAdds.delete(nodeIndex);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis.prefetchNextLod(node, desiredLodIndex, optimalLodIndex);\\n\\t\\t}\\n\\t}\\n\\tincrementFileRef(fileIndex, nodeIndex, lodIndex) {\\n\\t\\tif (fileIndex === -1) return;\\n\\t\\tlet placement = this.filePlacements[fileIndex];\\n\\t\\tif (!placement) {\\n\\t\\t\\tplacement = new GSplatPlacement(null, this.placement.node, lodIndex, null, this.placement);\\n\\t\\t\\tthis.filePlacements[fileIndex] = placement;\\n\\t\\t\\tconst removeScheduled = this.removedCandidates.delete(fileIndex);\\n\\t\\t\\tif (!removeScheduled) {\\n\\t\\t\\t\\tthis.octree.incRefCount(fileIndex);\\n\\t\\t\\t}\\n\\t\\t\\tif (!this.addFilePlacement(fileIndex)) {\\n\\t\\t\\t\\tthis.octree.ensureFileResource(fileIndex);\\n\\t\\t\\t\\tthis.pending.add(fileIndex);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst nodes = this.octree.nodes;\\n\\t\\tconst node = nodes[nodeIndex];\\n\\t\\tconst lod = node.lods[lodIndex];\\n\\t\\tconst interval = new Vec2(lod.offset, lod.offset + lod.count - 1);\\n\\t\\tplacement.intervals.set(nodeIndex, interval);\\n\\t\\tthis.dirtyModifiedPlacements = true;\\n\\t}\\n\\tdecrementFileRef(fileIndex, nodeIndex) {\\n\\t\\tif (fileIndex === -1) return;\\n\\t\\tconst placement = this.filePlacements[fileIndex];\\n\\t\\tif (!placement) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (placement) {\\n\\t\\t\\tplacement.intervals.delete(nodeIndex);\\n\\t\\t\\tthis.dirtyModifiedPlacements = true;\\n\\t\\t\\tif (placement.intervals.size === 0) {\\n\\t\\t\\t\\tif (placement.resource) {\\n\\t\\t\\t\\t\\tthis.activePlacements.delete(placement);\\n\\t\\t\\t\\t\\tif (this.activePlacements.size === 0) {\\n\\t\\t\\t\\t\\t\\tthis.dirtyPlacementSetChanged = true;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.removedCandidates.add(fileIndex);\\n\\t\\t\\t\\tthis.filePlacements[fileIndex] = null;\\n\\t\\t\\t\\tthis.pending.delete(fileIndex);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\taddFilePlacement(fileIndex) {\\n\\t\\tconst res = this.octree.getFileResource(fileIndex);\\n\\t\\tif (res) {\\n\\t\\t\\tconst placement = this.filePlacements[fileIndex];\\n\\t\\t\\tif (placement) {\\n\\t\\t\\t\\tplacement.resource = res;\\n\\t\\t\\t\\tif (this.activePlacements.size === 0) {\\n\\t\\t\\t\\t\\tthis.dirtyPlacementSetChanged = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.activePlacements.add(placement);\\n\\t\\t\\t\\tthis.dirtyModifiedPlacements = true;\\n\\t\\t\\t\\tthis.removedCandidates.delete(fileIndex);\\n\\t\\t\\t\\treturn true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn false;\\n\\t}\\n\\ttestMoved(threshold) {\\n\\t\\tconst position = this.placement.node.getPosition();\\n\\t\\tconst length = position.distance(this.previousPosition);\\n\\t\\tif (length > threshold) {\\n\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\treturn false;\\n\\t}\\n\\tupdateMoved() {\\n\\t\\tthis.previousPosition.copy(this.placement.node.getPosition());\\n\\t}\\n\\tupdate() {\\n\\t\\tif (this.placement.lodDirty) {\\n\\t\\t\\tthis.placement.lodDirty = false;\\n\\t\\t\\tthis.needsLodUpdate = true;\\n\\t\\t}\\n\\t\\tif (this.pending.size) {\\n\\t\\t\\tfor (const fileIndex of this.pending) {\\n\\t\\t\\t\\tthis.octree.ensureFileResource(fileIndex);\\n\\t\\t\\t\\tif (this.addFilePlacement(fileIndex)) {\\n\\t\\t\\t\\t\\t_tempCompletedUrls.push(fileIndex);\\n\\t\\t\\t\\t\\tfor (const [nodeIndex, { oldFileIndex, newFileIndex }] of this.pendingDecrements) {\\n\\t\\t\\t\\t\\t\\tif (newFileIndex === fileIndex) {\\n\\t\\t\\t\\t\\t\\t\\tthis.decrementFileRef(oldFileIndex, nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\tthis.pendingDecrements.delete(nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\tlet newLodIndex = 0;\\n\\t\\t\\t\\t\\t\\t\\tconst nodeLods = this.octree.nodes[nodeIndex].lods;\\n\\t\\t\\t\\t\\t\\t\\tfor (let li = 0; li < nodeLods.length; li++) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (nodeLods[li].fileIndex === newFileIndex) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tnewLodIndex = li;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\tthis.nodeInfos[nodeIndex].currentLod = newLodIndex;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (_tempCompletedUrls.length > 0) {\\n\\t\\t\\t\\tthis.needsLodUpdate = true;\\n\\t\\t\\t}\\n\\t\\t\\tfor (const fileIndex of _tempCompletedUrls) {\\n\\t\\t\\t\\tthis.pending.delete(fileIndex);\\n\\t\\t\\t}\\n\\t\\t\\t_tempCompletedUrls.length = 0;\\n\\t\\t}\\n\\t\\tthis.pollPrefetchCompletions();\\n\\t\\tif (this.octree.environmentUrl && !this.environmentPlacement) {\\n\\t\\t\\tthis.octree.ensureEnvironmentResource();\\n\\t\\t\\tconst envResource = this.octree.environmentResource;\\n\\t\\t\\tif (envResource) {\\n\\t\\t\\t\\tthis.environmentPlacement = new GSplatPlacement(envResource, this.placement.node, 0, null, this.placement);\\n\\t\\t\\t\\tthis.environmentPlacement.aabb.copy(envResource.aabb);\\n\\t\\t\\t\\tthis.activePlacements.add(this.environmentPlacement);\\n\\t\\t\\t\\tthis.dirtyModifiedPlacements = true;\\n\\t\\t\\t\\tthis.dirtyPlacementSetChanged = true;\\n\\t\\t\\t\\tenvResource.releaseTextureSources?.();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst dirty = this.dirtyModifiedPlacements;\\n\\t\\tthis.dirtyModifiedPlacements = false;\\n\\t\\treturn dirty;\\n\\t}\\n\\tconsumePlacementSetChanged() {\\n\\t\\tconst changed = this.dirtyPlacementSetChanged;\\n\\t\\tthis.dirtyPlacementSetChanged = false;\\n\\t\\treturn changed;\\n\\t}\\n\\t// debug render world space bounds for octree nodes based on current LOD selection\\n\\tdebugRender(scene) {\\n\\t}\\n\\tconsumeNeedsLodUpdate() {\\n\\t\\tconst v = this.needsLodUpdate;\\n\\t\\tthis.needsLodUpdate = false;\\n\\t\\treturn v;\\n\\t}\\n\\tpollPrefetchCompletions() {\\n\\t\\tif (this.prefetchPending.size) {\\n\\t\\t\\tfor (const fileIndex of this.prefetchPending) {\\n\\t\\t\\t\\tthis.octree.ensureFileResource(fileIndex);\\n\\t\\t\\t\\tif (this.octree.getFileResource(fileIndex)) {\\n\\t\\t\\t\\t\\t_tempCompletedUrls.push(fileIndex);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (_tempCompletedUrls.length > 0) {\\n\\t\\t\\t\\tthis.needsLodUpdate = true;\\n\\t\\t\\t}\\n\\t\\t\\tfor (const fileIndex of _tempCompletedUrls) {\\n\\t\\t\\t\\tthis.prefetchPending.delete(fileIndex);\\n\\t\\t\\t}\\n\\t\\t\\t_tempCompletedUrls.length = 0;\\n\\t\\t}\\n\\t}\\n}\\n\\nconst tmpMin = new Vec3();\\nconst tmpMax = new Vec3();\\nclass GSplatOctreeNode {\\n\\tlods;\\n\\tbounds = new BoundingBox();\\n\\tboundingSphere = new Vec4();\\n\\tconstructor(lods, boundData) {\\n\\t\\tthis.lods = lods;\\n\\t\\ttmpMin.set(boundData.min[0], boundData.min[1], boundData.min[2]);\\n\\t\\ttmpMax.set(boundData.max[0], boundData.max[1], boundData.max[2]);\\n\\t\\tthis.bounds.setMinMax(tmpMin, tmpMax);\\n\\t\\tconst center = this.bounds.center;\\n\\t\\tconst he = this.bounds.halfExtents;\\n\\t\\tconst radius = Math.sqrt(he.x * he.x + he.y * he.y + he.z * he.z);\\n\\t\\tthis.boundingSphere.set(center.x, center.y, center.z, radius);\\n\\t}\\n}\\n\\nconst _toDelete = [];\\nclass GSplatOctree {\\n\\tnodes;\\n\\tnodeBoundsMinMax;\\n\\tfiles;\\n\\tlodLevels;\\n\\tassetFileUrl;\\n\\tfileResources = /* @__PURE__ */ new Map();\\n\\tfileRefCounts;\\n\\tcooldowns = /* @__PURE__ */ new Map();\\n\\tenvironmentUrl = null;\\n\\tenvironmentResource = null;\\n\\tenvironmentRefCount = 0;\\n\\tassetLoader = null;\\n\\tdestroyed = false;\\n\\tcooldownTicks = 100;\\n\\tconstructor(assetFileUrl, data) {\\n\\t\\tthis.lodLevels = data.lodLevels;\\n\\t\\tthis.assetFileUrl = assetFileUrl;\\n\\t\\tconst baseDir = path.getDirectory(assetFileUrl);\\n\\t\\tthis.files = data.filenames.map((url) => ({\\n\\t\\t\\turl: path.isRelativePath(url) ? path.join(baseDir, url) : url,\\n\\t\\t\\tlodLevel: -1\\n\\t\\t}));\\n\\t\\tthis.fileRefCounts = new Int32Array(this.files.length);\\n\\t\\tif (data.environment) {\\n\\t\\t\\tthis.environmentUrl = path.isRelativePath(data.environment) ? path.join(baseDir, data.environment) : data.environment;\\n\\t\\t}\\n\\t\\tconst leafNodes = [];\\n\\t\\tthis._extractLeafNodes(data.tree, leafNodes);\\n\\t\\tthis.nodes = leafNodes.map((nodeData) => {\\n\\t\\t\\tconst lods = [];\\n\\t\\t\\tfor (let i = 0; i < this.lodLevels; i++) {\\n\\t\\t\\t\\tconst lodData = nodeData.lods[i.toString()];\\n\\t\\t\\t\\tif (lodData) {\\n\\t\\t\\t\\t\\tlods.push({\\n\\t\\t\\t\\t\\t\\tfile: this.files[lodData.file].url || \\\"\\\",\\n\\t\\t\\t\\t\\t\\tfileIndex: lodData.file,\\n\\t\\t\\t\\t\\t\\toffset: lodData.offset || 0,\\n\\t\\t\\t\\t\\t\\tcount: lodData.count || 0\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\tthis.files[lodData.file].lodLevel = i;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tlods.push({\\n\\t\\t\\t\\t\\t\\tfile: \\\"\\\",\\n\\t\\t\\t\\t\\t\\tfileIndex: -1,\\n\\t\\t\\t\\t\\t\\toffset: 0,\\n\\t\\t\\t\\t\\t\\tcount: 0\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\treturn new GSplatOctreeNode(lods, nodeData.bound);\\n\\t\\t});\\n\\t\\tconst nodeCount = this.nodes.length;\\n\\t\\tconst boundsFlat = new Float32Array(nodeCount * 6);\\n\\t\\tfor (let i = 0; i < nodeCount; i++) {\\n\\t\\t\\tconst bounds = this.nodes[i].bounds;\\n\\t\\t\\tconst mn = bounds.getMin();\\n\\t\\t\\tconst mx = bounds.getMax();\\n\\t\\t\\tconst b = i * 6;\\n\\t\\t\\tboundsFlat[b + 0] = mn.x;\\n\\t\\t\\tboundsFlat[b + 1] = mn.y;\\n\\t\\t\\tboundsFlat[b + 2] = mn.z;\\n\\t\\t\\tboundsFlat[b + 3] = mx.x;\\n\\t\\t\\tboundsFlat[b + 4] = mx.y;\\n\\t\\t\\tboundsFlat[b + 5] = mx.z;\\n\\t\\t}\\n\\t\\tthis.nodeBoundsMinMax = boundsFlat;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.destroyed = true;\\n\\t\\tthis.fileResources.clear();\\n\\t\\tthis.cooldowns.clear();\\n\\t\\tthis.assetLoader?.destroy();\\n\\t\\tthis.assetLoader = null;\\n\\t\\tthis.environmentResource = null;\\n\\t}\\n\\t_traceLodCounts() {\\n\\t}\\n\\t_extractLeafNodes(node, leafNodes) {\\n\\t\\tif (node.lods) {\\n\\t\\t\\tleafNodes.push({\\n\\t\\t\\t\\tlods: node.lods,\\n\\t\\t\\t\\tbound: node.bound\\n\\t\\t\\t});\\n\\t\\t} else if (node.children) {\\n\\t\\t\\tfor (const child of node.children) {\\n\\t\\t\\t\\tthis._extractLeafNodes(child, leafNodes);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tgetFileResource(fileIndex) {\\n\\t\\treturn this.fileResources.get(fileIndex);\\n\\t}\\n\\tincRefCount(fileIndex) {\\n\\t\\tconst count = this.fileRefCounts[fileIndex] + 1;\\n\\t\\tthis.fileRefCounts[fileIndex] = count;\\n\\t\\tthis.cooldowns.delete(fileIndex);\\n\\t}\\n\\tdecRefCount(fileIndex, cooldownTicks) {\\n\\t\\tconst count = this.fileRefCounts[fileIndex] - 1;\\n\\t\\tthis.fileRefCounts[fileIndex] = count;\\n\\t\\tif (count === 0) {\\n\\t\\t\\tif (cooldownTicks === 0) {\\n\\t\\t\\t\\tthis.unloadResource(fileIndex);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.cooldowns.set(fileIndex, cooldownTicks);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tunloadResource(fileIndex) {\\n\\t\\tif (!this.assetLoader) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst fullUrl = this.files[fileIndex].url;\\n\\t\\tthis.assetLoader.unload(fullUrl);\\n\\t\\tif (this.fileResources.has(fileIndex)) {\\n\\t\\t\\tthis.fileResources.delete(fileIndex);\\n\\t\\t\\tthis._traceLodCounts();\\n\\t\\t}\\n\\t}\\n\\tupdateCooldownTick(cooldownTicks) {\\n\\t\\tthis.cooldownTicks = cooldownTicks;\\n\\t\\tif (this.cooldowns.size > 0) {\\n\\t\\t\\tthis.cooldowns.forEach((remaining, fileIndex) => {\\n\\t\\t\\t\\tif (remaining <= 1) {\\n\\t\\t\\t\\t\\tif (this.fileRefCounts[fileIndex] === 0) {\\n\\t\\t\\t\\t\\t\\tthis.unloadResource(fileIndex);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t_toDelete.push(fileIndex);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tthis.cooldowns.set(fileIndex, remaining - 1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t\\t_toDelete.forEach((idx) => this.cooldowns.delete(idx));\\n\\t\\t\\t_toDelete.length = 0;\\n\\t\\t}\\n\\t}\\n\\tensureFileResource(fileIndex) {\\n\\t\\tif (this.fileResources.has(fileIndex)) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst fullUrl = this.files[fileIndex].url;\\n\\t\\tconst res = this.assetLoader?.getResource(fullUrl);\\n\\t\\tif (res) {\\n\\t\\t\\tthis.fileResources.set(fileIndex, res);\\n\\t\\t\\tres.releaseTextureSources?.();\\n\\t\\t\\tif (this.fileRefCounts[fileIndex] === 0) {\\n\\t\\t\\t\\tthis.cooldowns.set(fileIndex, this.cooldownTicks);\\n\\t\\t\\t}\\n\\t\\t\\tthis._traceLodCounts();\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.assetLoader?.load(fullUrl);\\n\\t}\\n\\tincEnvironmentRefCount() {\\n\\t\\tthis.environmentRefCount++;\\n\\t}\\n\\tdecEnvironmentRefCount() {\\n\\t\\tthis.environmentRefCount--;\\n\\t\\tif (this.environmentRefCount === 0) {\\n\\t\\t\\tthis.unloadEnvironmentResource();\\n\\t\\t}\\n\\t}\\n\\tensureEnvironmentResource() {\\n\\t\\tif (!this.assetLoader) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!this.environmentUrl) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this.environmentResource) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst res = this.assetLoader.getResource(this.environmentUrl);\\n\\t\\tif (res) {\\n\\t\\t\\tthis.environmentResource = res;\\n\\t\\t\\tif (this.environmentRefCount === 0) {\\n\\t\\t\\t\\tthis.unloadEnvironmentResource();\\n\\t\\t\\t}\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.assetLoader.load(this.environmentUrl);\\n\\t}\\n\\tunloadEnvironmentResource() {\\n\\t\\tif (!this.assetLoader) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this.environmentResource && this.environmentUrl) {\\n\\t\\t\\tthis.assetLoader.unload(this.environmentUrl);\\n\\t\\t\\tthis.environmentResource = null;\\n\\t\\t}\\n\\t}\\n}\\n\\nclass GSplatOctreeResource {\\n\\taabb = new BoundingBox();\\n\\tcentersVersion = 0;\\n\\toctree;\\n\\tdata;\\n\\tconstructor(assetFileUrl, data, assetLoader) {\\n\\t\\tthis.octree = new GSplatOctree(assetFileUrl, data);\\n\\t\\tthis.octree.assetLoader = assetLoader;\\n\\t\\tthis.aabb.setMinMax(new Vec3(data.tree.bound.min), new Vec3(data.tree.bound.max));\\n\\t\\tthis.data = data;\\n\\t\\tthis.data.tree = null;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.octree?.destroy();\\n\\t\\tthis.octree = null;\\n\\t}\\n}\\n\\nconst _newAllocIds = /* @__PURE__ */ new Set();\\nconst _toAllocateIds = [];\\nconst _toAllocate = [];\\nconst _toFree = [];\\nclass GSplatWorldState {\\n\\tversion = 0;\\n\\tsortParametersSet = false;\\n\\tsortedBefore = false;\\n\\tsplats = [];\\n\\ttextureSize = 0;\\n\\ttotalActiveSplats = 0;\\n\\ttotalIntervals = 0;\\n\\tboundsGroups = [];\\n\\tpendingReleases = [];\\n\\tneedsUpload = [];\\n\\tneedsUploadIds = /* @__PURE__ */ new Set();\\n\\tallocIdToSplat = /* @__PURE__ */ new Map();\\n\\tfullRebuild = false;\\n\\tconstructor(device, version, splats, allocator, allocationMap) {\\n\\t\\tthis.version = version;\\n\\t\\tthis.splats = splats;\\n\\t\\tif (splats.length === 0) {\\n\\t\\t\\tfor (const [, block] of allocationMap) {\\n\\t\\t\\t\\tallocator.free(block);\\n\\t\\t\\t}\\n\\t\\t\\tallocationMap.clear();\\n\\t\\t\\tthis.totalActiveSplats = 0;\\n\\t\\t\\tthis.totalIntervals = 0;\\n\\t\\t\\tthis.textureSize = 1;\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.computeAllocationDiff(splats, allocationMap);\\n\\t\\tconst { fullRebuild, changedAllocIds } = this.applyAllocations(device, allocator, allocationMap);\\n\\t\\tthis.assignSplatOffsets(splats, allocationMap, fullRebuild, changedAllocIds);\\n\\t\\tthis.buildBoundsGroups(splats);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.splats.forEach((splat) => splat.destroy());\\n\\t\\tthis.splats.length = 0;\\n\\t\\tthis.needsUpload.length = 0;\\n\\t\\tthis.needsUploadIds.clear();\\n\\t\\tthis.allocIdToSplat.clear();\\n\\t\\tthis.boundsGroups.length = 0;\\n\\t}\\n\\tcomputeAllocationDiff(splats, allocationMap) {\\n\\t\\tfor (let i = 0; i < splats.length; i++) {\\n\\t\\t\\tconst splat = splats[i];\\n\\t\\t\\tconst allocIds = splat.intervalAllocIds;\\n\\t\\t\\tconst intervals = splat.intervals;\\n\\t\\t\\tconst numIntervals = intervals.length / 2;\\n\\t\\t\\tif (numIntervals > 0 && allocIds.length === numIntervals) {\\n\\t\\t\\t\\tfor (let j = 0; j < numIntervals; j++) {\\n\\t\\t\\t\\t\\tthis._diffAlloc(allocIds[j], intervals[j * 2 + 1] - intervals[j * 2], allocationMap);\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._diffAlloc(splat.allocId, splat.activeSplats, allocationMap);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (const [allocId, block] of allocationMap) {\\n\\t\\t\\tif (!_newAllocIds.has(allocId)) {\\n\\t\\t\\t\\t_toFree.push(block);\\n\\t\\t\\t\\tallocationMap.delete(allocId);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_diffAlloc(allocId, size, allocationMap) {\\n\\t\\t_newAllocIds.add(allocId);\\n\\t\\tconst existing = allocationMap.get(allocId);\\n\\t\\tif (existing) {\\n\\t\\t\\tif (existing.size !== size) {\\n\\t\\t\\t\\t_toFree.push(existing);\\n\\t\\t\\t\\tallocationMap.delete(allocId);\\n\\t\\t\\t\\tif (size > 0) {\\n\\t\\t\\t\\t\\t_toAllocateIds.push(allocId);\\n\\t\\t\\t\\t\\t_toAllocate.push(size);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t} else if (size > 0) {\\n\\t\\t\\t_toAllocateIds.push(allocId);\\n\\t\\t\\t_toAllocate.push(size);\\n\\t\\t}\\n\\t}\\n\\tapplyAllocations(device, allocator, allocationMap) {\\n\\t\\tlet fullRebuild = false;\\n\\t\\tif (_toFree.length > 0 || _toAllocate.length > 0) {\\n\\t\\t\\tfullRebuild = allocator.updateAllocation(_toFree, _toAllocate);\\n\\t\\t\\tfor (let i = 0; i < _toAllocateIds.length; i++) {\\n\\t\\t\\t\\tallocationMap.set(_toAllocateIds[i], _toAllocate[i]);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.fullRebuild = fullRebuild;\\n\\t\\tconst churn = _toFree.length + _toAllocateIds.length;\\n\\t\\tconst incrementalDefragMoves = Math.max(50, churn);\\n\\t\\tif (!fullRebuild && allocator.fragmentation > 0.3) {\\n\\t\\t\\tconst moved = allocator.defrag(incrementalDefragMoves);\\n\\t\\t\\tif (moved.size > 0) {\\n\\t\\t\\t\\tfor (const [allocId, block] of allocationMap) {\\n\\t\\t\\t\\t\\tif (moved.has(block)) {\\n\\t\\t\\t\\t\\t\\t_toAllocateIds.push(allocId);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst cap = allocator.capacity;\\n\\t\\tthis.textureSize = cap > 0 ? Math.ceil(Math.sqrt(cap)) : 1;\\n\\t\\tconst changedAllocIds = _toAllocateIds.length > 0 ? new Set(_toAllocateIds) : null;\\n\\t\\t_newAllocIds.clear();\\n\\t\\t_toAllocateIds.length = 0;\\n\\t\\t_toAllocate.length = 0;\\n\\t\\t_toFree.length = 0;\\n\\t\\treturn { fullRebuild, changedAllocIds };\\n\\t}\\n\\tassignSplatOffsets(splats, allocationMap, fullRebuild, changedAllocIds) {\\n\\t\\tlet totalActiveSplats = 0;\\n\\t\\tlet totalIntervals = 0;\\n\\t\\tfor (let i = 0; i < splats.length; i++) {\\n\\t\\t\\tconst splat = splats[i];\\n\\t\\t\\tconst allocIds = splat.intervalAllocIds;\\n\\t\\t\\tconst intervals = splat.intervals;\\n\\t\\t\\tconst numIntervals = intervals.length / 2;\\n\\t\\t\\ttotalIntervals += numIntervals > 0 ? numIntervals : 1;\\n\\t\\t\\tlet splatChanged = fullRebuild;\\n\\t\\t\\tconst intervalOffsets = [];\\n\\t\\t\\tif (numIntervals > 0 && allocIds.length === numIntervals) {\\n\\t\\t\\t\\tfor (let j = 0; j < numIntervals; j++) {\\n\\t\\t\\t\\t\\tthis.allocIdToSplat.set(allocIds[j], splat);\\n\\t\\t\\t\\t\\tconst block = allocationMap.get(allocIds[j]);\\n\\t\\t\\t\\t\\tif (block) {\\n\\t\\t\\t\\t\\t\\tintervalOffsets.push(block.offset);\\n\\t\\t\\t\\t\\t\\ttotalActiveSplats += intervals[j * 2 + 1] - intervals[j * 2];\\n\\t\\t\\t\\t\\t\\tif (changedAllocIds && changedAllocIds.has(allocIds[j])) {\\n\\t\\t\\t\\t\\t\\t\\tsplatChanged = true;\\n\\t\\t\\t\\t\\t\\t\\tthis.needsUploadIds.add(allocIds[j]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.allocIdToSplat.set(splat.allocId, splat);\\n\\t\\t\\t\\tconst block = allocationMap.get(splat.allocId);\\n\\t\\t\\t\\tif (block) {\\n\\t\\t\\t\\t\\tintervalOffsets.push(block.offset);\\n\\t\\t\\t\\t\\ttotalActiveSplats += splat.activeSplats;\\n\\t\\t\\t\\t\\tif (changedAllocIds && changedAllocIds.has(splat.allocId)) {\\n\\t\\t\\t\\t\\t\\tsplatChanged = true;\\n\\t\\t\\t\\t\\t\\tthis.needsUploadIds.add(splat.allocId);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (intervalOffsets.length > 0) {\\n\\t\\t\\t\\tsplat.setLayout(intervalOffsets);\\n\\t\\t\\t\\tif (splatChanged) {\\n\\t\\t\\t\\t\\tthis.needsUpload.push(splat);\\n\\t\\t\\t\\t\\tif (fullRebuild) {\\n\\t\\t\\t\\t\\t\\tfor (let j = 0; j < allocIds.length; j++) {\\n\\t\\t\\t\\t\\t\\t\\tthis.needsUploadIds.add(allocIds[j]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.totalActiveSplats = totalActiveSplats;\\n\\t\\tthis.totalIntervals = totalIntervals;\\n\\t}\\n\\tbuildBoundsGroups(splats) {\\n\\t\\tconst groupMap = /* @__PURE__ */ new Map();\\n\\t\\tfor (let i = 0; i < splats.length; i++) {\\n\\t\\t\\tconst splat = splats[i];\\n\\t\\t\\tconst key = splat.parentPlacementId;\\n\\t\\t\\tif (!groupMap.has(key)) {\\n\\t\\t\\t\\tgroupMap.set(key, {\\n\\t\\t\\t\\t\\tsplat,\\n\\t\\t\\t\\t\\tboundsBaseIndex: 0,\\n\\t\\t\\t\\t\\tnumBoundsEntries: splat.numBoundsEntries\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tlet boundsIndex = 0;\\n\\t\\tfor (const group of groupMap.values()) {\\n\\t\\t\\tgroup.boundsBaseIndex = boundsIndex;\\n\\t\\t\\tboundsIndex += group.numBoundsEntries;\\n\\t\\t\\tthis.boundsGroups.push(group);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < splats.length; i++) {\\n\\t\\t\\tconst group = groupMap.get(splats[i].parentPlacementId);\\n\\t\\t\\tsplats[i].boundsBaseIndex = group.boundsBaseIndex;\\n\\t\\t}\\n\\t}\\n}\\n\\nclass GSplatPlacementStateTracker {\\n\\t_states = /* @__PURE__ */ new WeakMap();\\n\\thasChanges(placements) {\\n\\t\\tlet changed = false;\\n\\t\\tfor (const p of placements) {\\n\\t\\t\\tif (!p.resource) continue;\\n\\t\\t\\tconst formatVersion = p.resource.format?.extraStreamsVersion ?? 0;\\n\\t\\t\\tconst modifierHash = p.workBufferModifier?.hash ?? 0;\\n\\t\\t\\tconst numSplats = p.resource.numSplats ?? 0;\\n\\t\\t\\tconst centersVersion = p.resource.centersVersion;\\n\\t\\t\\tconst state = this._states.get(p);\\n\\t\\t\\tif (!state) {\\n\\t\\t\\t\\tthis._states.set(p, { formatVersion, modifierHash, numSplats, centersVersion });\\n\\t\\t\\t\\tchanged = true;\\n\\t\\t\\t} else if (state.formatVersion !== formatVersion || state.modifierHash !== modifierHash || state.numSplats !== numSplats || state.centersVersion !== centersVersion) {\\n\\t\\t\\t\\tstate.formatVersion = formatVersion;\\n\\t\\t\\t\\tstate.modifierHash = modifierHash;\\n\\t\\t\\t\\tstate.numSplats = numSplats;\\n\\t\\t\\t\\tstate.centersVersion = centersVersion;\\n\\t\\t\\t\\tchanged = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn changed;\\n\\t}\\n}\\n\\nconst computeGsplatIntervalCullSource = `\\nstruct Interval {\\n\\tworkBufferBase: u32,\\n\\tsplatCount: u32,\\n\\tboundsIndex: u32,\\n\\tpad: u32\\n};\\nstruct BoundsEntry {\\n\\tcenterX: f32,\\n\\tcenterY: f32,\\n\\tcenterZ: f32,\\n\\tradius: f32,\\n\\ttransformIndex: u32,\\n\\tpad0: u32,\\n\\tpad1: u32,\\n\\tpad2: u32\\n};\\nstruct CullUniforms {\\n#ifdef GSPLAT_FISHEYE\\n\\tcameraWorldPos: vec3f,\\n\\tmaxTheta: f32,\\n\\tcameraForward: vec3f,\\n\\tnumIntervals: u32,\\n#else\\n\\tfrustumPlanes: array<vec4f, 6>,\\n\\tnumIntervals: u32\\n#endif\\n};\\n@group(0) @binding(0) var<uniform> uniforms: CullUniforms;\\n@group(0) @binding(1) var<storage, read> intervals: array<Interval>;\\n@group(0) @binding(2) var<storage, read_write> countBuffer: array<u32>;\\n@group(0) @binding(3) var<storage, read> boundsBuffer: array<BoundsEntry>;\\n@group(0) @binding(4) var<storage, read> transformsBuffer: array<vec4f>;\\n@compute @workgroup_size({WORKGROUP_SIZE})\\nfn main(@builtin(global_invocation_id) gid: vec3u) {\\n\\tlet idx = gid.x;\\n\\tif (idx < uniforms.numIntervals) {\\n\\t\\tlet interval = intervals[idx];\\n\\t\\tlet entry = boundsBuffer[interval.boundsIndex];\\n\\t\\tlet localCenter = vec3f(entry.centerX, entry.centerY, entry.centerZ);\\n\\t\\tlet radius = entry.radius;\\n\\t\\tlet base = entry.transformIndex * 3u;\\n\\t\\tlet row0 = transformsBuffer[base];\\n\\t\\tlet row1 = transformsBuffer[base + 1u];\\n\\t\\tlet row2 = transformsBuffer[base + 2u];\\n\\t\\tlet worldCenter = vec3f(\\n\\t\\t\\tdot(vec4f(localCenter, 1.0), row0),\\n\\t\\t\\tdot(vec4f(localCenter, 1.0), row1),\\n\\t\\t\\tdot(vec4f(localCenter, 1.0), row2)\\n\\t\\t);\\n\\t\\tlet worldRadius = radius * length(vec3f(row0.x, row1.x, row2.x));\\n\\t#ifdef GSPLAT_FISHEYE\\n\\t\\tlet v = worldCenter - uniforms.cameraWorldPos;\\n\\t\\tlet d = length(v);\\n\\t\\tvar visible = true;\\n\\t\\tif (d > worldRadius) {\\n\\t\\t\\tlet cosAngle = dot(v / d, uniforms.cameraForward);\\n\\t\\t\\tlet theta = acos(clamp(cosAngle, -1.0, 1.0));\\n\\t\\t\\tlet angularRadius = asin(min(worldRadius / d, 1.0));\\n\\t\\t\\tvisible = (theta - angularRadius) < uniforms.maxTheta;\\n\\t\\t}\\n\\t#else\\n\\t\\tvar visible = true;\\n\\t\\tfor (var p = 0; p < 6; p++) {\\n\\t\\t\\tlet plane = uniforms.frustumPlanes[p];\\n\\t\\t\\tlet dist = dot(plane.xyz, worldCenter) + plane.w;\\n\\t\\t\\tif (dist <= -worldRadius) {\\n\\t\\t\\t\\tvisible = false;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t#endif\\n\\t\\tcountBuffer[idx] = select(0u, interval.splatCount, visible);\\n\\t}\\n\\tif (idx == 0u) {\\n\\t\\tcountBuffer[uniforms.numIntervals] = 0u;\\n\\t}\\n}\\n`;\\n\\nconst computeGsplatIntervalScatterSource = `\\nstruct Interval {\\n\\tworkBufferBase: u32,\\n\\tsplatCount: u32,\\n\\tboundsIndex: u32,\\n\\tpad: u32\\n};\\nstruct ScatterUniforms {\\n\\tnumIntervals: u32,\\n\\tpad0: u32,\\n\\tpad1: u32,\\n\\tpad2: u32\\n};\\n@group(0) @binding(0) var<uniform> uniforms: ScatterUniforms;\\n@group(0) @binding(1) var<storage, read> intervals: array<Interval>;\\n@group(0) @binding(2) var<storage, read> prefixSumBuffer: array<u32>;\\n@group(0) @binding(3) var<storage, read_write> compactedOutput: array<u32>;\\n@compute @workgroup_size({WORKGROUP_SIZE})\\nfn main(@builtin(workgroup_id) wgId: vec3u, @builtin(local_invocation_id) lid: vec3u) {\\n\\tlet intervalIdx = wgId.x;\\n\\tif (intervalIdx >= uniforms.numIntervals) { return; }\\n\\tlet outputOffset = prefixSumBuffer[intervalIdx];\\n\\tlet nextOffset = prefixSumBuffer[intervalIdx + 1u];\\n\\tlet count = nextOffset - outputOffset;\\n\\tif (count == 0u) { return; }\\n\\tlet workBufferBase = intervals[intervalIdx].workBufferBase;\\n\\tlet tid = lid.x;\\n\\tfor (var j = tid; j < count; j += {WORKGROUP_SIZE}u) {\\n\\t\\tcompactedOutput[outputOffset + j] = workBufferBase + j;\\n\\t}\\n}\\n`;\\n\\nconst computeGsplatWriteIndirectArgsSource = `\\n${indirect_core_default}\\n${dispatch_core_default}\\n${sort_indirect_args_default}\\n@group(0) @binding(0) var<storage, read> prefixSumBuffer: array<u32>;\\n@group(0) @binding(1) var<storage, read_write> indirectDrawArgs: array<DrawIndexedIndirectArgs>;\\n@group(0) @binding(2) var<storage, read_write> numSplatsBuf: array<u32>;\\n@group(0) @binding(3) var<storage, read_write> indirectDispatchArgs: array<u32>;\\n@group(0) @binding(4) var<storage, read_write> sortElementCountBuf: array<u32>;\\nstruct WriteArgsUniforms {\\n\\tdrawSlot: u32,\\n\\tindexCount: u32,\\n\\tdispatchSlotBase: u32,\\n\\ttotalSplats: u32,\\n\\tsortIndirectInfo: vec4<u32>\\n};\\n@group(0) @binding(5) var<uniform> uniforms: WriteArgsUniforms;\\n@compute @workgroup_size(1)\\nfn main(@builtin(global_invocation_id) gid: vec3u) {\\n\\tlet count = prefixSumBuffer[uniforms.totalSplats];\\n\\tlet instanceCount = (count + {INSTANCE_SIZE}u - 1u) / {INSTANCE_SIZE}u;\\n\\tindirectDrawArgs[uniforms.drawSlot] = DrawIndexedIndirectArgs(\\n\\t\\tuniforms.indexCount,\\n\\t\\tinstanceCount,\\n\\t\\t0u,\\n\\t\\t0,\\n\\t\\t0u\\n\\t);\\n\\tnumSplatsBuf[0] = count;\\n\\tlet keygenSlot = uniforms.dispatchSlotBase;\\n\\tlet keygenOffset = keygenSlot * 3u;\\n\\tlet keygenWorkgroupCount = (count + {KEYGEN_THREADS_PER_WORKGROUP}u - 1u) / {KEYGEN_THREADS_PER_WORKGROUP}u;\\n\\tlet keygenDim = calcDispatch2D(keygenWorkgroupCount, {MAX_WORKGROUPS_PER_DIM}u);\\n\\tindirectDispatchArgs[keygenOffset + 0u] = keygenDim.x;\\n\\tindirectDispatchArgs[keygenOffset + 1u] = keygenDim.y;\\n\\tindirectDispatchArgs[keygenOffset + 2u] = 1u;\\n\\twriteSortIndirectArgs(keygenSlot + 1u, count, uniforms.sortIndirectInfo);\\n\\tsortElementCountBuf[0] = count;\\n}\\n`;\\n\\nconst WORKGROUP_SIZE = 256;\\nconst INDEX_COUNT = 6 * GSplatResourceBase.instanceSize;\\nconst INTERVAL_STRIDE = 4;\\nclass GSplatIntervalCompaction {\\n\\tdevice;\\n\\tcompactedSplatIds = null;\\n\\tintervalsBuffer = null;\\n\\tcountBuffer = null;\\n\\tprefixSumKernel = null;\\n\\tnumSplatsBuffer = null;\\n\\tsortElementCountBuffer = null;\\n\\tallocatedCompactedCount = 0;\\n\\tallocatedIntervalCount = 0;\\n\\tallocatedCountBufferSize = 0;\\n\\t_uploadedVersion = -1;\\n\\t_cullComputePerspective = null;\\n\\t_cullComputeFisheye = null;\\n\\t_scatterCompute = null;\\n\\t_writeIndirectArgsCompute = null;\\n\\t_cullBindGroupFormatPerspective = null;\\n\\t_cullBindGroupFormatFisheye = null;\\n\\t_scatterBindGroupFormat = null;\\n\\t_writeArgsBindGroupFormat = null;\\n\\t_scatterUniformBufferFormat = null;\\n\\t_writeArgsUniformBufferFormat = null;\\n\\tconstructor(device) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.numSplatsBuffer = new StorageBuffer(device, 4, BUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST);\\n\\t\\tthis.sortElementCountBuffer = new StorageBuffer(device, 4, BUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST);\\n\\t\\tthis.prefixSumKernel = new PrefixSumKernel(device);\\n\\t\\tthis._createUniformBufferFormats();\\n\\t\\tthis._createScatterCompute();\\n\\t\\tthis._createWriteIndirectArgsCompute();\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.compactedSplatIds?.destroy();\\n\\t\\tthis.intervalsBuffer?.destroy();\\n\\t\\tthis.countBuffer?.destroy();\\n\\t\\tthis.prefixSumKernel?.destroy();\\n\\t\\tthis.numSplatsBuffer?.destroy();\\n\\t\\tthis.sortElementCountBuffer?.destroy();\\n\\t\\tthis._destroyCullPass();\\n\\t\\tthis._scatterCompute?.shader?.destroy();\\n\\t\\tthis._scatterBindGroupFormat?.destroy();\\n\\t\\tthis._writeIndirectArgsCompute?.shader?.destroy();\\n\\t\\tthis._writeArgsBindGroupFormat?.destroy();\\n\\t\\tthis.compactedSplatIds = null;\\n\\t\\tthis.intervalsBuffer = null;\\n\\t\\tthis.countBuffer = null;\\n\\t\\tthis.prefixSumKernel = null;\\n\\t\\tthis.numSplatsBuffer = null;\\n\\t\\tthis.sortElementCountBuffer = null;\\n\\t\\tthis._scatterCompute = null;\\n\\t\\tthis._scatterBindGroupFormat = null;\\n\\t\\tthis._writeIndirectArgsCompute = null;\\n\\t\\tthis._writeArgsBindGroupFormat = null;\\n\\t\\tthis._scatterUniformBufferFormat = null;\\n\\t\\tthis._writeArgsUniformBufferFormat = null;\\n\\t}\\n\\t_destroyCullPass() {\\n\\t\\tthis._cullComputePerspective?.shader?.destroy();\\n\\t\\tthis._cullBindGroupFormatPerspective?.destroy();\\n\\t\\tthis._cullComputePerspective = null;\\n\\t\\tthis._cullBindGroupFormatPerspective = null;\\n\\t\\tthis._cullComputeFisheye?.shader?.destroy();\\n\\t\\tthis._cullBindGroupFormatFisheye?.destroy();\\n\\t\\tthis._cullComputeFisheye = null;\\n\\t\\tthis._cullBindGroupFormatFisheye = null;\\n\\t}\\n\\t_createUniformBufferFormats() {\\n\\t\\tconst device = this.device;\\n\\t\\tthis._scatterUniformBufferFormat = new UniformBufferFormat(device, [\\n\\t\\t\\tnew UniformFormat(\\\"numIntervals\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"pad0\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"pad1\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"pad2\\\", UNIFORMTYPE_UINT)\\n\\t\\t]);\\n\\t\\tthis._writeArgsUniformBufferFormat = new UniformBufferFormat(device, [\\n\\t\\t\\tnew UniformFormat(\\\"drawSlot\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"indexCount\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"dispatchSlotBase\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"totalSplats\\\", UNIFORMTYPE_UINT),\\n\\t\\t\\tnew UniformFormat(\\\"sortIndirectInfo\\\", UNIFORMTYPE_UVEC4)\\n\\t\\t]);\\n\\t}\\n\\t_createCullPass(fisheye) {\\n\\t\\tconst device = this.device;\\n\\t\\tconst suffix = fisheye ? \\\"Fisheye\\\" : \\\"\\\";\\n\\t\\tconst bindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"intervals\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"countBuffer\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"boundsBuffer\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"transformsBuffer\\\", SHADERSTAGE_COMPUTE, true)\\n\\t\\t]);\\n\\t\\tconst cdefines = /* @__PURE__ */ new Map([[\\\"{WORKGROUP_SIZE}\\\", WORKGROUP_SIZE.toString()]]);\\n\\t\\tif (fisheye) {\\n\\t\\t\\tcdefines.set(\\\"GSPLAT_FISHEYE\\\", \\\"\\\");\\n\\t\\t}\\n\\t\\tconst uniformBufferFormat = fisheye ? new UniformBufferFormat(device, [\\n\\t\\t\\tnew UniformFormat(\\\"cameraWorldPos\\\", UNIFORMTYPE_VEC3),\\n\\t\\t\\tnew UniformFormat(\\\"maxTheta\\\", UNIFORMTYPE_FLOAT),\\n\\t\\t\\tnew UniformFormat(\\\"cameraForward\\\", UNIFORMTYPE_VEC3),\\n\\t\\t\\tnew UniformFormat(\\\"numIntervals\\\", UNIFORMTYPE_UINT)\\n\\t\\t]) : new UniformBufferFormat(device, [\\n\\t\\t\\tnew UniformFormat(\\\"frustumPlanes\\\", UNIFORMTYPE_VEC4, 6),\\n\\t\\t\\tnew UniformFormat(\\\"numIntervals\\\", UNIFORMTYPE_UINT)\\n\\t\\t]);\\n\\t\\tconst shader = new Shader(device, {\\n\\t\\t\\tname: `GSplatIntervalCull${suffix}`,\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tcshader: computeGsplatIntervalCullSource,\\n\\t\\t\\tcdefines,\\n\\t\\t\\tcomputeBindGroupFormat: bindGroupFormat,\\n\\t\\t\\tcomputeUniformBufferFormats: { uniforms: uniformBufferFormat }\\n\\t\\t});\\n\\t\\tconst compute = new Compute(device, shader, `GSplatIntervalCull${suffix}`);\\n\\t\\treturn { compute, bindGroupFormat };\\n\\t}\\n\\t_getCullCompute(fisheye) {\\n\\t\\tif (fisheye) {\\n\\t\\t\\tif (!this._cullComputeFisheye) {\\n\\t\\t\\t\\tconst { compute, bindGroupFormat } = this._createCullPass(true);\\n\\t\\t\\t\\tthis._cullComputeFisheye = compute;\\n\\t\\t\\t\\tthis._cullBindGroupFormatFisheye = bindGroupFormat;\\n\\t\\t\\t}\\n\\t\\t\\treturn this._cullComputeFisheye;\\n\\t\\t}\\n\\t\\tif (!this._cullComputePerspective) {\\n\\t\\t\\tconst { compute, bindGroupFormat } = this._createCullPass(false);\\n\\t\\t\\tthis._cullComputePerspective = compute;\\n\\t\\t\\tthis._cullBindGroupFormatPerspective = bindGroupFormat;\\n\\t\\t}\\n\\t\\treturn this._cullComputePerspective;\\n\\t}\\n\\t_createScatterCompute() {\\n\\t\\tconst device = this.device;\\n\\t\\tthis._scatterBindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"intervals\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"prefixSumBuffer\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"compactedOutput\\\", SHADERSTAGE_COMPUTE, false)\\n\\t\\t]);\\n\\t\\tconst cdefines = /* @__PURE__ */ new Map([\\n\\t\\t\\t[\\\"{WORKGROUP_SIZE}\\\", WORKGROUP_SIZE.toString()]\\n\\t\\t]);\\n\\t\\tconst shader = new Shader(device, {\\n\\t\\t\\tname: \\\"GSplatIntervalScatter\\\",\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tcshader: computeGsplatIntervalScatterSource,\\n\\t\\t\\tcdefines,\\n\\t\\t\\tcomputeBindGroupFormat: this._scatterBindGroupFormat,\\n\\t\\t\\tcomputeUniformBufferFormats: { uniforms: this._scatterUniformBufferFormat }\\n\\t\\t});\\n\\t\\tthis._scatterCompute = new Compute(device, shader, \\\"GSplatIntervalScatter\\\");\\n\\t}\\n\\t_createWriteIndirectArgsCompute() {\\n\\t\\tconst device = this.device;\\n\\t\\tthis._writeArgsBindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"prefixSumBuffer\\\", SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"indirectDrawArgs\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"numSplatsBuf\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"indirectDispatchArgs\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindStorageBufferFormat(\\\"sortElementCountBuf\\\", SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\tnew BindUniformBufferFormat(\\\"uniforms\\\", SHADERSTAGE_COMPUTE)\\n\\t\\t]);\\n\\t\\tconst cdefines = /* @__PURE__ */ new Map([\\n\\t\\t\\t[\\\"{INSTANCE_SIZE}\\\", GSplatResourceBase.instanceSize],\\n\\t\\t\\t[\\\"{KEYGEN_THREADS_PER_WORKGROUP}\\\", 256],\\n\\t\\t\\t[\\\"{MAX_WORKGROUPS_PER_DIM}\\\", device.limits.maxComputeWorkgroupsPerDimension || 65535]\\n\\t\\t]);\\n\\t\\tconst shader = new Shader(device, {\\n\\t\\t\\tname: \\\"GSplatIntervalWriteIndirectArgs\\\",\\n\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\tcshader: computeGsplatWriteIndirectArgsSource,\\n\\t\\t\\tcdefines,\\n\\t\\t\\tcomputeBindGroupFormat: this._writeArgsBindGroupFormat,\\n\\t\\t\\tcomputeUniformBufferFormats: { uniforms: this._writeArgsUniformBufferFormat }\\n\\t\\t});\\n\\t\\tthis._writeIndirectArgsCompute = new Compute(device, shader, \\\"GSplatIntervalWriteIndirectArgs\\\");\\n\\t}\\n\\t_ensureCapacity(numIntervals, totalActiveSplats) {\\n\\t\\tif (totalActiveSplats > this.allocatedCompactedCount) {\\n\\t\\t\\tthis.compactedSplatIds?.destroy();\\n\\t\\t\\tthis.allocatedCompactedCount = totalActiveSplats;\\n\\t\\t\\tthis.compactedSplatIds = new StorageBuffer(this.device, totalActiveSplats * 4, BUFFERUSAGE_COPY_SRC);\\n\\t\\t}\\n\\t\\tconst requiredCountSize = numIntervals + 1;\\n\\t\\tif (requiredCountSize > this.allocatedCountBufferSize) {\\n\\t\\t\\tthis.countBuffer?.destroy();\\n\\t\\t\\tthis.allocatedCountBufferSize = requiredCountSize;\\n\\t\\t\\tthis.countBuffer = new StorageBuffer(this.device, requiredCountSize * 4);\\n\\t\\t\\tif (this.prefixSumKernel) {\\n\\t\\t\\t\\tthis.prefixSumKernel.destroyPasses();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tuploadIntervals(worldState) {\\n\\t\\tif (worldState.version === this._uploadedVersion) return;\\n\\t\\tthis._uploadedVersion = worldState.version;\\n\\t\\tconst splats = worldState.splats;\\n\\t\\tconst numIntervals = worldState.totalIntervals;\\n\\t\\tif (numIntervals === 0) return;\\n\\t\\tif (numIntervals > this.allocatedIntervalCount) {\\n\\t\\t\\tthis.intervalsBuffer?.destroy();\\n\\t\\t\\tthis.allocatedIntervalCount = numIntervals;\\n\\t\\t\\tthis.intervalsBuffer = new StorageBuffer(this.device, numIntervals * INTERVAL_STRIDE * 4, BUFFERUSAGE_COPY_DST);\\n\\t\\t}\\n\\t\\tconst data = new Uint32Array(numIntervals * INTERVAL_STRIDE);\\n\\t\\tlet writeIdx = 0;\\n\\t\\tfor (let s = 0; s < splats.length; s++) {\\n\\t\\t\\tconst splat = splats[s];\\n\\t\\t\\tif (splat.intervals.length > 0) {\\n\\t\\t\\t\\tconst nodeIndices = splat.intervalNodeIndices;\\n\\t\\t\\t\\tfor (let i = 0; i < splat.intervals.length; i += 2) {\\n\\t\\t\\t\\t\\tconst count = splat.intervals[i + 1] - splat.intervals[i];\\n\\t\\t\\t\\t\\tdata[writeIdx++] = splat.intervalOffsets[i / 2];\\n\\t\\t\\t\\t\\tdata[writeIdx++] = count;\\n\\t\\t\\t\\t\\tdata[writeIdx++] = splat.boundsBaseIndex + (nodeIndices.length > 0 ? nodeIndices[i / 2] : 0);\\n\\t\\t\\t\\t\\tdata[writeIdx++] = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tdata[writeIdx++] = splat.intervalOffsets[0];\\n\\t\\t\\t\\tdata[writeIdx++] = splat.activeSplats;\\n\\t\\t\\t\\tdata[writeIdx++] = splat.boundsBaseIndex;\\n\\t\\t\\t\\tdata[writeIdx++] = 0;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.intervalsBuffer.write(0, data, 0, numIntervals * INTERVAL_STRIDE);\\n\\t}\\n\\tdispatchCompact(frustumCuller, numIntervals, totalActiveSplats, fisheyeEnabled) {\\n\\t\\tif (numIntervals === 0) return;\\n\\t\\tthis._ensureCapacity(numIntervals, totalActiveSplats);\\n\\t\\tconst cullCompute = this._getCullCompute(fisheyeEnabled);\\n\\t\\tcullCompute.setParameter(\\\"intervals\\\", this.intervalsBuffer);\\n\\t\\tcullCompute.setParameter(\\\"countBuffer\\\", this.countBuffer);\\n\\t\\tcullCompute.setParameter(\\\"boundsBuffer\\\", frustumCuller.boundsBuffer);\\n\\t\\tcullCompute.setParameter(\\\"transformsBuffer\\\", frustumCuller.transformsBuffer);\\n\\t\\tif (fisheyeEnabled) {\\n\\t\\t\\tcullCompute.setParameter(\\\"cameraWorldPos\\\", frustumCuller.fisheyeCameraPos);\\n\\t\\t\\tcullCompute.setParameter(\\\"maxTheta\\\", frustumCuller.fisheyeMaxTheta);\\n\\t\\t\\tcullCompute.setParameter(\\\"cameraForward\\\", frustumCuller.fisheyeCameraForward);\\n\\t\\t} else {\\n\\t\\t\\tcullCompute.setParameter(\\\"frustumPlanes[0]\\\", frustumCuller.frustumPlanes);\\n\\t\\t}\\n\\t\\tcullCompute.setParameter(\\\"numIntervals\\\", numIntervals);\\n\\t\\tconst cullWorkgroups = Math.ceil(numIntervals / WORKGROUP_SIZE);\\n\\t\\tcullCompute.setupDispatch(cullWorkgroups);\\n\\t\\tthis.device.computeDispatch([cullCompute], \\\"GSplatIntervalCull\\\");\\n\\t\\tconst prefixCount = numIntervals + 1;\\n\\t\\tthis.prefixSumKernel.resize(this.countBuffer, prefixCount);\\n\\t\\tthis.prefixSumKernel.dispatch(this.device);\\n\\t\\tconst scatterCompute = this._scatterCompute;\\n\\t\\tscatterCompute.setParameter(\\\"intervals\\\", this.intervalsBuffer);\\n\\t\\tscatterCompute.setParameter(\\\"prefixSumBuffer\\\", this.countBuffer);\\n\\t\\tscatterCompute.setParameter(\\\"compactedOutput\\\", this.compactedSplatIds);\\n\\t\\tscatterCompute.setParameter(\\\"numIntervals\\\", numIntervals);\\n\\t\\tscatterCompute.setParameter(\\\"pad0\\\", 0);\\n\\t\\tscatterCompute.setParameter(\\\"pad1\\\", 0);\\n\\t\\tscatterCompute.setParameter(\\\"pad2\\\", 0);\\n\\t\\tscatterCompute.setupDispatch(numIntervals);\\n\\t\\tthis.device.computeDispatch([scatterCompute], \\\"GSplatIntervalScatter\\\");\\n\\t}\\n\\twriteIndirectArgs(drawSlot, dispatchSlotBase, numIntervals, sortIndirectInfo) {\\n\\t\\tconst compute = this._writeIndirectArgsCompute;\\n\\t\\tcompute.setParameter(\\\"prefixSumBuffer\\\", this.countBuffer);\\n\\t\\tcompute.setParameter(\\\"indirectDrawArgs\\\", this.device.indirectDrawBuffer);\\n\\t\\tcompute.setParameter(\\\"numSplatsBuf\\\", this.numSplatsBuffer);\\n\\t\\tcompute.setParameter(\\\"indirectDispatchArgs\\\", this.device.indirectDispatchBuffer);\\n\\t\\tcompute.setParameter(\\\"sortElementCountBuf\\\", this.sortElementCountBuffer);\\n\\t\\tcompute.setParameter(\\\"drawSlot\\\", drawSlot);\\n\\t\\tcompute.setParameter(\\\"indexCount\\\", INDEX_COUNT);\\n\\t\\tcompute.setParameter(\\\"dispatchSlotBase\\\", dispatchSlotBase);\\n\\t\\tcompute.setParameter(\\\"totalSplats\\\", numIntervals);\\n\\t\\tcompute.setParameter(\\\"sortIndirectInfo\\\", sortIndirectInfo);\\n\\t\\tcompute.setupDispatch(1);\\n\\t\\tthis.device.computeDispatch([compute], \\\"GSplatIntervalWriteIndirectArgs\\\");\\n\\t}\\n}\\n\\nclass GSplatBudgetBalancer {\\n\\t_buckets = null;\\n\\t_initBuckets() {\\n\\t\\tif (!this._buckets) {\\n\\t\\t\\tthis._buckets = new Array(NUM_BUCKETS);\\n\\t\\t\\tfor (let i = 0; i < NUM_BUCKETS; i++) {\\n\\t\\t\\t\\tthis._buckets[i] = [];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tbalance(octreeInstances, budget) {\\n\\t\\tthis._initBuckets();\\n\\t\\tfor (let i = 0; i < NUM_BUCKETS; i++) {\\n\\t\\t\\tthis._buckets[i].length = 0;\\n\\t\\t}\\n\\t\\tlet totalOptimalSplats = 0;\\n\\t\\tfor (const [, inst] of octreeInstances) {\\n\\t\\t\\tconst nodes = inst.octree.nodes;\\n\\t\\t\\tconst nodeInfos = inst.nodeInfos;\\n\\t\\t\\tfor (let nodeIndex = 0, len = nodes.length; nodeIndex < len; nodeIndex++) {\\n\\t\\t\\t\\tconst nodeInfo = nodeInfos[nodeIndex];\\n\\t\\t\\t\\tconst optimalLod = nodeInfo.optimalLod;\\n\\t\\t\\t\\tif (optimalLod < 0) continue;\\n\\t\\t\\t\\tconst lods = nodes[nodeIndex].lods;\\n\\t\\t\\t\\tnodeInfo.lods = lods;\\n\\t\\t\\t\\tthis._buckets[nodeInfo.budgetBucket].push(nodeInfo);\\n\\t\\t\\t\\ttotalOptimalSplats += lods[optimalLod].count;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tlet currentSplats = totalOptimalSplats;\\n\\t\\tif (currentSplats === budget) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst isOverBudget = currentSplats > budget;\\n\\t\\tlet done = false;\\n\\t\\twhile (!done && (isOverBudget ? currentSplats > budget : currentSplats < budget)) {\\n\\t\\t\\tlet modified = false;\\n\\t\\t\\tif (isOverBudget) {\\n\\t\\t\\t\\tfor (let b = NUM_BUCKETS - 1; b >= 0 && !done; b--) {\\n\\t\\t\\t\\t\\tconst bucket = this._buckets[b];\\n\\t\\t\\t\\t\\tfor (let i = 0, len = bucket.length; i < len; i++) {\\n\\t\\t\\t\\t\\t\\tconst nodeInfo = bucket[i];\\n\\t\\t\\t\\t\\t\\tif (nodeInfo.optimalLod < nodeInfo.inst.rangeMax) {\\n\\t\\t\\t\\t\\t\\t\\tconst lods = nodeInfo.lods;\\n\\t\\t\\t\\t\\t\\t\\tconst optimalLod = nodeInfo.optimalLod;\\n\\t\\t\\t\\t\\t\\t\\tcurrentSplats -= lods[optimalLod].count - lods[optimalLod + 1].count;\\n\\t\\t\\t\\t\\t\\t\\tnodeInfo.optimalLod = optimalLod + 1;\\n\\t\\t\\t\\t\\t\\t\\tmodified = true;\\n\\t\\t\\t\\t\\t\\t\\tif (currentSplats <= budget) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdone = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tfor (let b = 0; b < NUM_BUCKETS && !done; b++) {\\n\\t\\t\\t\\t\\tconst bucket = this._buckets[b];\\n\\t\\t\\t\\t\\tfor (let i = 0, len = bucket.length; i < len; i++) {\\n\\t\\t\\t\\t\\t\\tconst nodeInfo = bucket[i];\\n\\t\\t\\t\\t\\t\\tif (nodeInfo.optimalLod > nodeInfo.inst.rangeMin) {\\n\\t\\t\\t\\t\\t\\t\\tconst lods = nodeInfo.lods;\\n\\t\\t\\t\\t\\t\\t\\tconst optimalLod = nodeInfo.optimalLod;\\n\\t\\t\\t\\t\\t\\t\\tconst splatsAdded = lods[optimalLod - 1].count - lods[optimalLod].count;\\n\\t\\t\\t\\t\\t\\t\\tif (currentSplats + splatsAdded <= budget) {\\n\\t\\t\\t\\t\\t\\t\\t\\tnodeInfo.optimalLod = optimalLod - 1;\\n\\t\\t\\t\\t\\t\\t\\t\\tcurrentSplats += splatsAdded;\\n\\t\\t\\t\\t\\t\\t\\t\\tmodified = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (currentSplats >= budget) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tdone = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tdone = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (!modified) {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\n\\nclass MemBlock {\\n\\t_offset = 0;\\n\\t_size = 0;\\n\\t_free = true;\\n\\t_prev = null;\\n\\t_next = null;\\n\\t_prevFree = null;\\n\\t_nextFree = null;\\n\\t_bucket = -1;\\n\\tget offset() {\\n\\t\\treturn this._offset;\\n\\t}\\n\\tget size() {\\n\\t\\treturn this._size;\\n\\t}\\n}\\nclass BlockAllocator {\\n\\t_headAll = null;\\n\\t_tailAll = null;\\n\\t_freeBucketHeads = [];\\n\\t_pool = [];\\n\\t_capacity = 0;\\n\\t_usedSize = 0;\\n\\t_freeSize = 0;\\n\\t_freeRegionCount = 0;\\n\\t_growMultiplier;\\n\\tconstructor(capacity = 0, growMultiplier = 1.1) {\\n\\t\\tthis._growMultiplier = growMultiplier;\\n\\t\\tif (capacity > 0) {\\n\\t\\t\\tthis._capacity = capacity;\\n\\t\\t\\tthis._freeSize = capacity;\\n\\t\\t\\tconst block = this._obtain(0, capacity, true);\\n\\t\\t\\tthis._headAll = block;\\n\\t\\t\\tthis._tailAll = block;\\n\\t\\t\\tthis._addToBucket(block);\\n\\t\\t}\\n\\t}\\n\\tget capacity() {\\n\\t\\treturn this._capacity;\\n\\t}\\n\\tget usedSize() {\\n\\t\\treturn this._usedSize;\\n\\t}\\n\\tget freeSize() {\\n\\t\\treturn this._freeSize;\\n\\t}\\n\\tget fragmentation() {\\n\\t\\treturn this._freeSize > 0 ? 1 - 1 / this._freeRegionCount : 0;\\n\\t}\\n\\t_bucketFor(size) {\\n\\t\\treturn 31 - Math.clz32(size);\\n\\t}\\n\\t_addToBucket(block) {\\n\\t\\tconst b = this._bucketFor(block._size);\\n\\t\\tblock._bucket = b;\\n\\t\\twhile (b >= this._freeBucketHeads.length) {\\n\\t\\t\\tthis._freeBucketHeads.push(null);\\n\\t\\t}\\n\\t\\tblock._prevFree = null;\\n\\t\\tblock._nextFree = this._freeBucketHeads[b];\\n\\t\\tif (this._freeBucketHeads[b]) this._freeBucketHeads[b]._prevFree = block;\\n\\t\\tthis._freeBucketHeads[b] = block;\\n\\t\\tthis._freeRegionCount++;\\n\\t}\\n\\t_removeFromBucket(block) {\\n\\t\\tconst b = block._bucket;\\n\\t\\tif (block._prevFree) block._prevFree._nextFree = block._nextFree;\\n\\t\\telse this._freeBucketHeads[b] = block._nextFree;\\n\\t\\tif (block._nextFree) block._nextFree._prevFree = block._prevFree;\\n\\t\\tblock._prevFree = null;\\n\\t\\tblock._nextFree = null;\\n\\t\\tblock._bucket = -1;\\n\\t\\tthis._freeRegionCount--;\\n\\t}\\n\\t_rebucket(block) {\\n\\t\\tconst newBucket = this._bucketFor(block._size);\\n\\t\\tif (newBucket !== block._bucket) {\\n\\t\\t\\tthis._removeFromBucket(block);\\n\\t\\t\\tthis._addToBucket(block);\\n\\t\\t}\\n\\t}\\n\\t_obtain(offset, size, free) {\\n\\t\\tlet block;\\n\\t\\tif (this._pool.length > 0) {\\n\\t\\t\\tblock = this._pool.pop();\\n\\t\\t} else {\\n\\t\\t\\tblock = new MemBlock();\\n\\t\\t}\\n\\t\\tblock._offset = offset;\\n\\t\\tblock._size = size;\\n\\t\\tblock._free = free;\\n\\t\\tblock._prev = null;\\n\\t\\tblock._next = null;\\n\\t\\tblock._prevFree = null;\\n\\t\\tblock._nextFree = null;\\n\\t\\tblock._bucket = -1;\\n\\t\\treturn block;\\n\\t}\\n\\t_release(block) {\\n\\t\\tblock._prev = null;\\n\\t\\tblock._next = null;\\n\\t\\tblock._prevFree = null;\\n\\t\\tblock._nextFree = null;\\n\\t\\tblock._bucket = -1;\\n\\t\\tthis._pool.push(block);\\n\\t}\\n\\t_insertAfterInMainList(block, after) {\\n\\t\\tif (after === null) {\\n\\t\\t\\tblock._prev = null;\\n\\t\\t\\tblock._next = this._headAll;\\n\\t\\t\\tif (this._headAll) this._headAll._prev = block;\\n\\t\\t\\tthis._headAll = block;\\n\\t\\t\\tif (!this._tailAll) this._tailAll = block;\\n\\t\\t} else {\\n\\t\\t\\tblock._prev = after;\\n\\t\\t\\tblock._next = after._next;\\n\\t\\t\\tif (after._next) after._next._prev = block;\\n\\t\\t\\tafter._next = block;\\n\\t\\t\\tif (this._tailAll === after) this._tailAll = block;\\n\\t\\t}\\n\\t}\\n\\t_removeFromMainList(block) {\\n\\t\\tif (block._prev) block._prev._next = block._next;\\n\\t\\telse this._headAll = block._next;\\n\\t\\tif (block._next) block._next._prev = block._prev;\\n\\t\\telse this._tailAll = block._prev;\\n\\t\\tblock._prev = null;\\n\\t\\tblock._next = null;\\n\\t}\\n\\t_findFreeBlock(size) {\\n\\t\\tconst startBucket = this._bucketFor(size);\\n\\t\\tconst len = this._freeBucketHeads.length;\\n\\t\\tif (startBucket < len) {\\n\\t\\t\\tlet best = null;\\n\\t\\t\\tlet node = this._freeBucketHeads[startBucket];\\n\\t\\t\\twhile (node) {\\n\\t\\t\\t\\tif (node._size >= size) {\\n\\t\\t\\t\\t\\tif (!best || node._size < best._size) {\\n\\t\\t\\t\\t\\t\\tbest = node;\\n\\t\\t\\t\\t\\t\\tif (node._size === size) break;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tnode = node._nextFree;\\n\\t\\t\\t}\\n\\t\\t\\tif (best) return best;\\n\\t\\t}\\n\\t\\tfor (let b = startBucket + 1; b < len; b++) {\\n\\t\\t\\tif (this._freeBucketHeads[b]) {\\n\\t\\t\\t\\treturn this._freeBucketHeads[b];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn null;\\n\\t}\\n\\tallocate(size) {\\n\\t\\tconst gap = this._findFreeBlock(size);\\n\\t\\tif (!gap) return null;\\n\\t\\tthis._usedSize += size;\\n\\t\\tthis._freeSize -= size;\\n\\t\\tif (gap._size === size) {\\n\\t\\t\\tgap._free = false;\\n\\t\\t\\tthis._removeFromBucket(gap);\\n\\t\\t\\treturn gap;\\n\\t\\t}\\n\\t\\tconst alloc = this._obtain(gap._offset, size, false);\\n\\t\\tgap._offset += size;\\n\\t\\tgap._size -= size;\\n\\t\\tthis._rebucket(gap);\\n\\t\\tthis._insertAfterInMainList(alloc, gap._prev);\\n\\t\\treturn alloc;\\n\\t}\\n\\tfree(block) {\\n\\t\\tblock._free = true;\\n\\t\\tthis._usedSize -= block._size;\\n\\t\\tthis._freeSize += block._size;\\n\\t\\tconst prev = block._prev;\\n\\t\\tconst next = block._next;\\n\\t\\tconst prevFree = prev && prev._free;\\n\\t\\tconst nextFree = next && next._free;\\n\\t\\tif (prevFree && nextFree) {\\n\\t\\t\\tprev._size += block._size + next._size;\\n\\t\\t\\tthis._removeFromMainList(block);\\n\\t\\t\\tthis._removeFromMainList(next);\\n\\t\\t\\tthis._removeFromBucket(next);\\n\\t\\t\\tthis._release(block);\\n\\t\\t\\tthis._release(next);\\n\\t\\t\\tthis._rebucket(prev);\\n\\t\\t} else if (prevFree) {\\n\\t\\t\\tprev._size += block._size;\\n\\t\\t\\tthis._removeFromMainList(block);\\n\\t\\t\\tthis._release(block);\\n\\t\\t\\tthis._rebucket(prev);\\n\\t\\t} else if (nextFree) {\\n\\t\\t\\tblock._size += next._size;\\n\\t\\t\\tthis._removeFromMainList(next);\\n\\t\\t\\tthis._removeFromBucket(next);\\n\\t\\t\\tthis._release(next);\\n\\t\\t\\tthis._addToBucket(block);\\n\\t\\t} else {\\n\\t\\t\\tthis._addToBucket(block);\\n\\t\\t}\\n\\t}\\n\\tgrow(newCapacity) {\\n\\t\\tif (newCapacity <= this._capacity) return;\\n\\t\\tconst added = newCapacity - this._capacity;\\n\\t\\tthis._capacity = newCapacity;\\n\\t\\tthis._freeSize += added;\\n\\t\\tif (this._tailAll && this._tailAll._free) {\\n\\t\\t\\tthis._tailAll._size += added;\\n\\t\\t\\tthis._rebucket(this._tailAll);\\n\\t\\t} else {\\n\\t\\t\\tconst block = this._obtain(this._capacity - added, added, true);\\n\\t\\t\\tthis._insertAfterInMainList(block, this._tailAll);\\n\\t\\t\\tthis._addToBucket(block);\\n\\t\\t}\\n\\t}\\n\\tdefrag(maxMoves = 0, result = /* @__PURE__ */ new Set()) {\\n\\t\\tresult.clear();\\n\\t\\tif (this._freeRegionCount === 0) return result;\\n\\t\\tif (maxMoves === 0) {\\n\\t\\t\\tthis._defragFull(result);\\n\\t\\t} else {\\n\\t\\t\\tthis._defragIncremental(maxMoves, result);\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n\\t_defragFull(result) {\\n\\t\\tfor (let b = 0; b < this._freeBucketHeads.length; b++) {\\n\\t\\t\\tlet node = this._freeBucketHeads[b];\\n\\t\\t\\twhile (node) {\\n\\t\\t\\t\\tconst nextFree = node._nextFree;\\n\\t\\t\\t\\tthis._removeFromMainList(node);\\n\\t\\t\\t\\tnode._prevFree = null;\\n\\t\\t\\t\\tnode._nextFree = null;\\n\\t\\t\\t\\tnode._bucket = -1;\\n\\t\\t\\t\\tthis._pool.push(node);\\n\\t\\t\\t\\tnode = nextFree;\\n\\t\\t\\t}\\n\\t\\t\\tthis._freeBucketHeads[b] = null;\\n\\t\\t}\\n\\t\\tthis._freeRegionCount = 0;\\n\\t\\tlet offset = 0;\\n\\t\\tlet block = this._headAll;\\n\\t\\twhile (block) {\\n\\t\\t\\tif (block._offset !== offset) {\\n\\t\\t\\t\\tblock._offset = offset;\\n\\t\\t\\t\\tresult.add(block);\\n\\t\\t\\t}\\n\\t\\t\\toffset += block._size;\\n\\t\\t\\tblock = block._next;\\n\\t\\t}\\n\\t\\tconst remaining = this._capacity - offset;\\n\\t\\tif (remaining > 0) {\\n\\t\\t\\tconst freeBlock = this._obtain(offset, remaining, true);\\n\\t\\t\\tthis._insertAfterInMainList(freeBlock, this._tailAll);\\n\\t\\t\\tthis._addToBucket(freeBlock);\\n\\t\\t}\\n\\t}\\n\\t_defragIncremental(maxMoves, result) {\\n\\t\\tconst phase1Moves = Math.ceil(maxMoves / 2);\\n\\t\\tconst phase2Moves = maxMoves - phase1Moves;\\n\\t\\tfor (let i = 0; i < phase1Moves; i++) {\\n\\t\\t\\tlet lastAlloc = this._tailAll;\\n\\t\\t\\twhile (lastAlloc && lastAlloc._free) lastAlloc = lastAlloc._prev;\\n\\t\\t\\tif (!lastAlloc) break;\\n\\t\\t\\tconst gap = this._findFreeBlock(lastAlloc._size);\\n\\t\\t\\tif (!gap || gap._offset >= lastAlloc._offset) break;\\n\\t\\t\\tthis._moveBlock(lastAlloc, gap);\\n\\t\\t\\tresult.add(lastAlloc);\\n\\t\\t}\\n\\t\\tlet block = this._headAll;\\n\\t\\tfor (let i = 0; i < phase2Moves && block; ) {\\n\\t\\t\\tconst next = block._next;\\n\\t\\t\\tif (block._free && next && !next._free) {\\n\\t\\t\\t\\tconst allocBlock = next;\\n\\t\\t\\t\\tconst freeBlock = block;\\n\\t\\t\\t\\tallocBlock._offset = freeBlock._offset;\\n\\t\\t\\t\\tfreeBlock._offset = allocBlock._offset + allocBlock._size;\\n\\t\\t\\t\\tconst a = freeBlock._prev;\\n\\t\\t\\t\\tconst b = allocBlock._next;\\n\\t\\t\\t\\tallocBlock._prev = a;\\n\\t\\t\\t\\tallocBlock._next = freeBlock;\\n\\t\\t\\t\\tfreeBlock._prev = allocBlock;\\n\\t\\t\\t\\tfreeBlock._next = b;\\n\\t\\t\\t\\tif (a) a._next = allocBlock;\\n\\t\\t\\t\\telse this._headAll = allocBlock;\\n\\t\\t\\t\\tif (b) b._prev = freeBlock;\\n\\t\\t\\t\\telse this._tailAll = freeBlock;\\n\\t\\t\\t\\tif (freeBlock._next && freeBlock._next._free) {\\n\\t\\t\\t\\t\\tconst right = freeBlock._next;\\n\\t\\t\\t\\t\\tfreeBlock._size += right._size;\\n\\t\\t\\t\\t\\tthis._removeFromMainList(right);\\n\\t\\t\\t\\t\\tthis._removeFromBucket(right);\\n\\t\\t\\t\\t\\tthis._release(right);\\n\\t\\t\\t\\t\\tthis._rebucket(freeBlock);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tresult.add(allocBlock);\\n\\t\\t\\t\\ti++;\\n\\t\\t\\t\\tblock = freeBlock._next;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tblock = next;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_moveBlock(block, gap) {\\n\\t\\tconst blockSize = block._size;\\n\\t\\tconst newOffset = gap._offset;\\n\\t\\tconst prev = block._prev;\\n\\t\\tthis._removeFromMainList(block);\\n\\t\\tconst freed = this._obtain(block._offset, blockSize, true);\\n\\t\\tthis._insertAfterInMainList(freed, prev);\\n\\t\\tthis._addToBucket(freed);\\n\\t\\tif (freed._next && freed._next._free) {\\n\\t\\t\\tconst right = freed._next;\\n\\t\\t\\tfreed._size += right._size;\\n\\t\\t\\tthis._removeFromMainList(right);\\n\\t\\t\\tthis._removeFromBucket(right);\\n\\t\\t\\tthis._release(right);\\n\\t\\t\\tthis._rebucket(freed);\\n\\t\\t}\\n\\t\\tif (freed._prev && freed._prev._free) {\\n\\t\\t\\tconst left = freed._prev;\\n\\t\\t\\tleft._size += freed._size;\\n\\t\\t\\tthis._removeFromMainList(freed);\\n\\t\\t\\tthis._removeFromBucket(freed);\\n\\t\\t\\tthis._release(freed);\\n\\t\\t\\tthis._rebucket(left);\\n\\t\\t}\\n\\t\\tblock._offset = newOffset;\\n\\t\\tif (gap._size === blockSize) {\\n\\t\\t\\tconst gapPrev = gap._prev;\\n\\t\\t\\tthis._removeFromMainList(gap);\\n\\t\\t\\tthis._removeFromBucket(gap);\\n\\t\\t\\tthis._release(gap);\\n\\t\\t\\tthis._insertAfterInMainList(block, gapPrev);\\n\\t\\t} else {\\n\\t\\t\\tgap._offset += blockSize;\\n\\t\\t\\tgap._size -= blockSize;\\n\\t\\t\\tthis._rebucket(gap);\\n\\t\\t\\tthis._insertAfterInMainList(block, gap._prev);\\n\\t\\t}\\n\\t}\\n\\tupdateAllocation(toFree, toAllocate) {\\n\\t\\tfor (let i = 0; i < toFree.length; i++) {\\n\\t\\t\\tthis.free(toFree[i]);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < toAllocate.length; i++) {\\n\\t\\t\\tconst size = toAllocate[i];\\n\\t\\t\\tconst block = this.allocate(size);\\n\\t\\t\\tif (block) {\\n\\t\\t\\t\\ttoAllocate[i] = block;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tlet totalRemaining = size;\\n\\t\\t\\t\\tfor (let j = i + 1; j < toAllocate.length; j++) {\\n\\t\\t\\t\\t\\ttotalRemaining += toAllocate[j];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst neededCapacity = this._usedSize + totalRemaining;\\n\\t\\t\\t\\tconst headroomCapacity = Math.ceil(neededCapacity * this._growMultiplier);\\n\\t\\t\\t\\tif (headroomCapacity > this._capacity) {\\n\\t\\t\\t\\t\\tthis.grow(headroomCapacity);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.defrag(0);\\n\\t\\t\\t\\tfor (let j = i; j < toAllocate.length; j++) {\\n\\t\\t\\t\\t\\tconst s = toAllocate[j];\\n\\t\\t\\t\\t\\tconst b = this.allocate(s);\\n\\t\\t\\t\\t\\ttoAllocate[j] = b;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn false;\\n\\t}\\n}\\n\\nconst cameraPosition = new Vec3();\\nconst cameraDirection = new Vec3();\\nconst translation = new Vec3();\\nconst _tempVec3 = new Vec3();\\nconst invModelMat = new Mat4();\\nconst NO_SORT_INDIRECT_INFO = new Uint32Array([0, 0, 0, 0]);\\nconst tempNonOctreePlacements = /* @__PURE__ */ new Set();\\nconst tempOctreePlacements = /* @__PURE__ */ new Set();\\nconst _updatedSplats = [];\\nconst _splatsWithSH = [];\\nconst _changedColorAllocIds = /* @__PURE__ */ new Set();\\nconst _cameraDeltas = { translationDelta: 0 };\\nconst _localCamPos = new Vec3();\\nconst _closestPt = new Vec3();\\nconst tempOctreesTicked = /* @__PURE__ */ new Set();\\nconst _queuedSplats = /* @__PURE__ */ new Set();\\nconst _lodColorsRaw = [\\n\\t[1, 0, 0],\\n\\t// red\\n\\t[0, 1, 0],\\n\\t// green\\n\\t[0, 0, 1],\\n\\t// blue\\n\\t[1, 1, 0],\\n\\t// yellow\\n\\t[1, 0, 1],\\n\\t// magenta\\n\\t[0, 1, 1],\\n\\t// cyan\\n\\t[1, 0.5, 0],\\n\\t// orange\\n\\t[0.5, 0, 1]\\n\\t// purple\\n];\\n[\\n\\tnew Color(1, 0, 0),\\n\\tnew Color(0, 1, 0),\\n\\tnew Color(0, 0, 1),\\n\\tnew Color(1, 1, 0),\\n\\tnew Color(1, 0, 1),\\n\\tnew Color(0, 1, 1),\\n\\tnew Color(1, 0.5, 0),\\n\\tnew Color(0.5, 0, 1)\\n];\\nlet _randomColorRaw = null;\\nclass GSplatManager {\\n\\tdevice;\\n\\tnode = new GraphNode(\\\"GSplatManager\\\");\\n\\tworkBuffer;\\n\\trenderer;\\n\\tworldStates = /* @__PURE__ */ new Map();\\n\\tlastWorldStateVersion = 0;\\n\\tactiveRenderer;\\n\\t_worldStateDirty = false;\\n\\tcpuSorter = null;\\n\\tgpuSorter = null;\\n\\tintervalCompaction = null;\\n\\tprojector = null;\\n\\tindirectDrawSlot = -1;\\n\\tindirectDispatchSlot = -1;\\n\\tlastCompactedNumIntervals = 0;\\n\\tsortedVersion = 0;\\n\\t_awaitingLodUpdate = false;\\n\\t_workBufferFormatVersion = -1;\\n\\t_workBufferRebuildRequired = false;\\n\\tbufferCopyUploaded = 0;\\n\\tbufferCopyTotal = 0;\\n\\t_stateTracker = new GSplatPlacementStateTracker();\\n\\t_centersVersions = /* @__PURE__ */ new Map();\\n\\tframesTillFullUpdate = 0;\\n\\tlastLodCameraPos = new Vec3(Infinity, Infinity, Infinity);\\n\\tlastLodCameraFwd = new Vec3(Infinity, Infinity, Infinity);\\n\\tlastLodCameraFov = -1;\\n\\tlastSortCameraPos = new Vec3(Infinity, Infinity, Infinity);\\n\\tlastSortCameraFwd = new Vec3(Infinity, Infinity, Infinity);\\n\\tlastCullingCameraFwd = new Vec3(Infinity, Infinity, Infinity);\\n\\tlastCullingProjMat = new Mat4();\\n\\tsortNeeded = true;\\n\\t_budgetBalancer = new GSplatBudgetBalancer();\\n\\t_budgetScale = 1;\\n\\t_allocator;\\n\\t_allocationMap = /* @__PURE__ */ new Map();\\n\\tlastColorUpdateCameraPos = new Vec3(Infinity, Infinity, Infinity);\\n\\tcameraNode;\\n\\tscene;\\n\\tlayerPlacements = [];\\n\\tlayerPlacementsDirty = false;\\n\\t_placementSetChanged = false;\\n\\toctreeInstances = /* @__PURE__ */ new Map();\\n\\toctreeInstancesToDestroy = [];\\n\\thasNewOctreeInstances = false;\\n\\trenderMode;\\n\\tconstructor(device, director, layer, cameraNode) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.scene = director.scene;\\n\\t\\tthis.director = director;\\n\\t\\tthis.cameraNode = cameraNode;\\n\\t\\tconst allocatorGrowMultiplier = 1.15;\\n\\t\\tconst budget = this.scene.gsplat.splatBudget;\\n\\t\\tthis._allocator = new BlockAllocator(budget > 0 ? Math.ceil(budget * allocatorGrowMultiplier) : 0, allocatorGrowMultiplier);\\n\\t\\tthis.workBuffer = new GSplatWorkBuffer(device, this.scene.gsplat.format);\\n\\t\\tthis.layer = layer;\\n\\t\\tthis._createRenderer(this.scene.gsplat.currentRenderer);\\n\\t\\tthis._workBufferFormatVersion = this.workBuffer.format.extraStreamsVersion;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._destroyed = true;\\n\\t\\tfor (const [, worldState] of this.worldStates) {\\n\\t\\t\\tfor (const splat of worldState.splats) {\\n\\t\\t\\t\\tsplat.resource.decRefCount();\\n\\t\\t\\t}\\n\\t\\t\\tworldState.destroy();\\n\\t\\t}\\n\\t\\tthis.worldStates.clear();\\n\\t\\tfor (const [, instance] of this.octreeInstances) {\\n\\t\\t\\tinstance.destroy();\\n\\t\\t}\\n\\t\\tthis.octreeInstances.clear();\\n\\t\\tfor (const instance of this.octreeInstancesToDestroy) {\\n\\t\\t\\tinstance.destroy();\\n\\t\\t}\\n\\t\\tthis.octreeInstancesToDestroy.length = 0;\\n\\t\\tthis.destroyGpuSorting();\\n\\t\\tthis.destroyCpuSorting();\\n\\t\\tthis.workBuffer.destroy();\\n\\t\\tthis.renderer.destroy();\\n\\t}\\n\\tdestroyGpuSorting() {\\n\\t\\tthis.gpuSorter?.destroy();\\n\\t\\tthis.gpuSorter = null;\\n\\t\\tthis.projector?.destroy();\\n\\t\\tthis.projector = null;\\n\\t\\tconst useCpuSort = false;\\n\\t\\tthis.renderer.setCpuSortedRendering();\\n\\t\\tthis.destroyIntervalCompaction(useCpuSort);\\n\\t}\\n\\tdestroyIntervalCompaction(useCpuSort = true) {\\n\\t\\tif (this.intervalCompaction) {\\n\\t\\t\\tif (useCpuSort) {\\n\\t\\t\\t\\tthis.renderer.setCpuSortedRendering();\\n\\t\\t\\t}\\n\\t\\t\\tthis.intervalCompaction.destroy();\\n\\t\\t\\tthis.intervalCompaction = null;\\n\\t\\t}\\n\\t}\\n\\tdestroyCpuSorting() {\\n\\t\\tthis.cpuSorter?.destroy();\\n\\t\\tthis.cpuSorter = null;\\n\\t}\\n\\tinitHybridSorting() {\\n\\t\\tif (!this.gpuSorter) {\\n\\t\\t\\tthis.gpuSorter = new ComputeRadixSort(this.device, { indirect: true });\\n\\t\\t}\\n\\t\\tif (!this.projector) {\\n\\t\\t\\tthis.projector = new GSplatProjector(this.device);\\n\\t\\t}\\n\\t}\\n\\tinitCpuSorting() {\\n\\t\\tif (!this.cpuSorter) {\\n\\t\\t\\tthis.cpuSorter = this.createSorter();\\n\\t\\t}\\n\\t\\tconst currentState = this.worldStates.get(this.sortedVersion);\\n\\t\\tif (currentState) {\\n\\t\\t\\tcurrentState.sortParametersSet = false;\\n\\t\\t\\tcurrentState.sortedBefore = false;\\n\\t\\t\\tthis.cpuSorter.updateCentersForSplats(currentState.splats);\\n\\t\\t}\\n\\t\\tthis.renderer.setCpuSortedRendering();\\n\\t}\\n\\tget material() {\\n\\t\\treturn this.renderer.material;\\n\\t}\\n\\tprepareForPicking(camera, width, height) {\\n\\t\\tif (this.activeRenderer === GSPLAT_RENDERER_RASTER_GPU_SORT) {\\n\\t\\t\\tconst sortedState = this.worldStates.get(this.sortedVersion);\\n\\t\\t\\tif (!sortedState?.sortedBefore || !camera.node) return null;\\n\\t\\t\\tconst sortedIndices = this.sortGpuHybridForCamera(\\n\\t\\t\\t\\tsortedState,\\n\\t\\t\\t\\tcamera.node,\\n\\t\\t\\t\\twidth,\\n\\t\\t\\t\\theight,\\n\\t\\t\\t\\tMath.max(ALPHA_VISIBILITY_THRESHOLD, this.scene.gsplat.alphaClip),\\n\\t\\t\\t\\t!!this.workBuffer.format.getStream(\\\"pcId\\\")\\n\\t\\t\\t);\\n\\t\\t\\tif (!sortedIndices) return null;\\n\\t\\t\\tconst proj = this.projector;\\n\\t\\t\\tconst ic = this.intervalCompaction;\\n\\t\\t\\treturn this.renderer.prepareForPicking(\\n\\t\\t\\t\\tthis.indirectDrawSlot,\\n\\t\\t\\t\\tsortedIndices,\\n\\t\\t\\t\\tproj.projCache,\\n\\t\\t\\t\\tic.numSplatsBuffer,\\n\\t\\t\\t\\tthis.scene.gsplat.alphaClip,\\n\\t\\t\\t\\tthis.scene.gsplat.alphaClipForward,\\n\\t\\t\\t\\tcamera.node\\n\\t\\t\\t);\\n\\t\\t}\\n\\t\\tif (this.activeRenderer !== GSPLAT_RENDERER_COMPUTE) return null;\\n\\t\\tconst localRenderer = this.renderer;\\n\\t\\treturn localRenderer.dispatchPick(camera, width, height);\\n\\t}\\n\\tcreateSorter() {\\n\\t\\tconst sorter = new GSplatUnifiedSorter(this.scene);\\n\\t\\tsorter.on(\\\"sorted\\\", (count, version, orderData) => {\\n\\t\\t\\tthis.onSorted(count, version, orderData);\\n\\t\\t});\\n\\t\\treturn sorter;\\n\\t}\\n\\tsetRenderMode(renderMode) {\\n\\t\\tthis.renderMode = renderMode;\\n\\t\\tthis.renderer.setRenderMode(renderMode);\\n\\t}\\n\\tget canCull() {\\n\\t\\treturn this.activeRenderer !== GSPLAT_RENDERER_RASTER_CPU_SORT && this.workBuffer.frustumCuller.totalBoundsEntries > 0;\\n\\t}\\n\\t_createRenderer(mode) {\\n\\t\\tif (mode === GSPLAT_RENDERER_COMPUTE) {\\n\\t\\t\\tthis.renderer = new GSplatComputeLocalRenderer(this.device, this.node, this.cameraNode, this.layer, this.workBuffer);\\n\\t\\t} else if (mode === GSPLAT_RENDERER_RASTER_GPU_SORT) {\\n\\t\\t\\tthis.renderer = new GSplatHybridRenderer(this.device, this.node, this.cameraNode, this.layer, this.workBuffer);\\n\\t\\t\\tthis.initHybridSorting();\\n\\t\\t} else {\\n\\t\\t\\tthis.renderer = new GSplatQuadRenderer(this.device, this.node, this.cameraNode, this.layer, this.workBuffer);\\n\\t\\t\\tthis.initCpuSorting();\\n\\t\\t}\\n\\t\\tthis.activeRenderer = mode;\\n\\t}\\n\\tprepareRendererMode() {\\n\\t\\tconst requested = this.scene.gsplat.currentRenderer;\\n\\t\\tif (requested === this.activeRenderer) return;\\n\\t\\tthis._worldStateDirty = true;\\n\\t\\tthis.destroyGpuSorting();\\n\\t\\tthis.destroyCpuSorting();\\n\\t\\tthis.renderer.destroy();\\n\\t\\tthis._createRenderer(requested);\\n\\t\\tthis.renderer.setRenderMode(this.renderMode);\\n\\t\\tthis._workBufferRebuildRequired = true;\\n\\t\\tthis.sortNeeded = true;\\n\\t}\\n\\treconcile(placements) {\\n\\t\\ttempNonOctreePlacements.clear();\\n\\t\\tfor (const p of placements) {\\n\\t\\t\\tif (p.resource instanceof GSplatOctreeResource) {\\n\\t\\t\\t\\tif (!this.octreeInstances.has(p)) {\\n\\t\\t\\t\\t\\tthis.octreeInstances.set(p, new GSplatOctreeInstance(this.device, p.resource.octree, p));\\n\\t\\t\\t\\t\\tthis.hasNewOctreeInstances = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttempOctreePlacements.add(p);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\ttempNonOctreePlacements.add(p);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (const [placement, inst] of this.octreeInstances) {\\n\\t\\t\\tif (!tempOctreePlacements.has(placement)) {\\n\\t\\t\\t\\tthis.octreeInstances.delete(placement);\\n\\t\\t\\t\\tthis.layerPlacementsDirty = true;\\n\\t\\t\\t\\tthis._placementSetChanged = true;\\n\\t\\t\\t\\tthis.octreeInstancesToDestroy.push(inst);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.layerPlacementsDirty || (this.layerPlacementsDirty = this.layerPlacements.length !== tempNonOctreePlacements.size);\\n\\t\\tif (!this.layerPlacementsDirty) {\\n\\t\\t\\tfor (let i = 0; i < this.layerPlacements.length; i++) {\\n\\t\\t\\t\\tconst existing = this.layerPlacements[i];\\n\\t\\t\\t\\tif (!tempNonOctreePlacements.has(existing)) {\\n\\t\\t\\t\\t\\tthis.layerPlacementsDirty = true;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._placementSetChanged || (this._placementSetChanged = this.layerPlacementsDirty);\\n\\t\\tthis.layerPlacements.length = 0;\\n\\t\\tfor (const p of tempNonOctreePlacements) {\\n\\t\\t\\tthis.layerPlacements.push(p);\\n\\t\\t}\\n\\t\\ttempNonOctreePlacements.clear();\\n\\t\\ttempOctreePlacements.clear();\\n\\t}\\n\\tupdateWorldState() {\\n\\t\\tlet stateChanged = this._stateTracker.hasChanges(this.layerPlacements);\\n\\t\\tfor (const [, inst] of this.octreeInstances) {\\n\\t\\t\\tif (this._stateTracker.hasChanges(inst.activePlacements)) {\\n\\t\\t\\t\\tstateChanged = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst placementsChanged = this.layerPlacementsDirty;\\n\\t\\tconst worldChanged = placementsChanged || stateChanged || this.worldStates.size === 0 || this._worldStateDirty;\\n\\t\\tif (worldChanged) {\\n\\t\\t\\tthis.lastWorldStateVersion++;\\n\\t\\t\\tconst splats = [];\\n\\t\\t\\tfor (const p of this.layerPlacements) {\\n\\t\\t\\t\\tif (this.cpuSorter && !p.resource.hasCenters) {\\n\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tp.ensureInstanceStreams(this.device);\\n\\t\\t\\t\\tconst splatInfo = new GSplatInfo(this.device, p.resource, p, p.consumeRenderDirty.bind(p));\\n\\t\\t\\t\\tsplats.push(splatInfo);\\n\\t\\t\\t}\\n\\t\\t\\tfor (const [, inst] of this.octreeInstances) {\\n\\t\\t\\t\\tinst.activePlacements.forEach((p) => {\\n\\t\\t\\t\\t\\tif (p.resource) {\\n\\t\\t\\t\\t\\t\\tconst leafResource = p.resource;\\n\\t\\t\\t\\t\\t\\tif (this.cpuSorter && !leafResource.hasCenters) {\\n\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tp.ensureInstanceStreams(this.device);\\n\\t\\t\\t\\t\\t\\tconst octreeNodes = p.intervals.size > 0 ? inst.octree.nodes : null;\\n\\t\\t\\t\\t\\t\\tconst nodeInfos = octreeNodes ? inst.nodeInfos : null;\\n\\t\\t\\t\\t\\t\\tconst splatInfo = new GSplatInfo(this.device, p.resource, p, p.consumeRenderDirty.bind(p), octreeNodes, nodeInfos);\\n\\t\\t\\t\\t\\t\\tsplats.push(splatInfo);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t\\tif (this.cpuSorter) {\\n\\t\\t\\t\\tfor (const splat of splats) {\\n\\t\\t\\t\\t\\tconst resource = splat.resource;\\n\\t\\t\\t\\t\\tconst lastVersion = this._centersVersions.get(resource.id);\\n\\t\\t\\t\\t\\tif (lastVersion !== resource.centersVersion) {\\n\\t\\t\\t\\t\\t\\tthis._centersVersions.set(resource.id, resource.centersVersion);\\n\\t\\t\\t\\t\\t\\tthis.cpuSorter.setCenters(resource.id, null);\\n\\t\\t\\t\\t\\t\\tthis.cpuSorter.setCenters(resource.id, resource.centers);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis.cpuSorter?.updateCentersForSplats(splats);\\n\\t\\t\\tconst newState = new GSplatWorldState(\\n\\t\\t\\t\\tthis.device,\\n\\t\\t\\t\\tthis.lastWorldStateVersion,\\n\\t\\t\\t\\tsplats,\\n\\t\\t\\t\\tthis._allocator,\\n\\t\\t\\t\\tthis._allocationMap\\n\\t\\t\\t);\\n\\t\\t\\tfor (const splat of newState.splats) {\\n\\t\\t\\t\\tsplat.resource.incRefCount();\\n\\t\\t\\t}\\n\\t\\t\\tfor (const [, inst] of this.octreeInstances) {\\n\\t\\t\\t\\tif (inst.removedCandidates && inst.removedCandidates.size) {\\n\\t\\t\\t\\t\\tfor (const fileIndex of inst.removedCandidates) {\\n\\t\\t\\t\\t\\t\\tnewState.pendingReleases.push([inst.octree, fileIndex]);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tinst.removedCandidates.clear();\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (this.octreeInstancesToDestroy.length) {\\n\\t\\t\\t\\tfor (const inst of this.octreeInstancesToDestroy) {\\n\\t\\t\\t\\t\\tif (inst.removedCandidates && inst.removedCandidates.size) {\\n\\t\\t\\t\\t\\t\\tfor (const fileIndex of inst.removedCandidates) {\\n\\t\\t\\t\\t\\t\\t\\tnewState.pendingReleases.push([inst.octree, fileIndex]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tinst.removedCandidates.clear();\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tconst toRelease = inst.getFileDecrements();\\n\\t\\t\\t\\t\\tfor (const fileIndex of toRelease) {\\n\\t\\t\\t\\t\\t\\tnewState.pendingReleases.push([inst.octree, fileIndex]);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tinst.destroy(true);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.octreeInstancesToDestroy.length = 0;\\n\\t\\t\\t}\\n\\t\\t\\tif (this._placementSetChanged) {\\n\\t\\t\\t\\tnewState.fullRebuild = true;\\n\\t\\t\\t}\\n\\t\\t\\tthis.worldStates.set(this.lastWorldStateVersion, newState);\\n\\t\\t\\tthis.layerPlacementsDirty = false;\\n\\t\\t\\tthis._placementSetChanged = false;\\n\\t\\t\\tthis._worldStateDirty = false;\\n\\t\\t\\tthis.sortNeeded = true;\\n\\t\\t}\\n\\t}\\n\\tonSorted(count, version, orderData) {\\n\\t\\tthis.cleanupOldWorldStates(version);\\n\\t\\tthis.sortedVersion = version;\\n\\t\\tconst worldState = this.worldStates.get(version);\\n\\t\\tif (worldState) {\\n\\t\\t\\tif (!worldState.sortedBefore) {\\n\\t\\t\\t\\tworldState.sortedBefore = true;\\n\\t\\t\\t\\tthis.rebuildWorkBuffer(worldState, count);\\n\\t\\t\\t}\\n\\t\\t\\tthis.workBuffer.setOrderData(orderData);\\n\\t\\t\\tthis.renderer.setOrderData();\\n\\t\\t}\\n\\t}\\n\\trebuildWorkBuffer(worldState, count, forceFullRebuild = false) {\\n\\t\\tconst textureSize = worldState.textureSize;\\n\\t\\tif (textureSize !== this.workBuffer.textureSize) {\\n\\t\\t\\tthis.workBuffer.resize(textureSize);\\n\\t\\t}\\n\\t\\tif (this.activeRenderer !== GSPLAT_RENDERER_RASTER_CPU_SORT) {\\n\\t\\t\\tthis.workBuffer.frustumCuller.updateBoundsData(worldState.boundsGroups);\\n\\t\\t\\tthis.workBuffer.frustumCuller.updateTransformsData(worldState.boundsGroups);\\n\\t\\t}\\n\\t\\tconst renderAll = forceFullRebuild || worldState.fullRebuild;\\n\\t\\tconst splatsToRender = renderAll ? worldState.splats : worldState.needsUpload;\\n\\t\\tconst changedAllocIds = renderAll ? null : worldState.needsUploadIds;\\n\\t\\tif (splatsToRender.length > 0) {\\n\\t\\t\\tconst totalBlocks = this._allocationMap.size;\\n\\t\\t\\tconst uploadBlocks = renderAll ? totalBlocks : worldState.needsUploadIds.size;\\n\\t\\t\\tthis.bufferCopyUploaded += uploadBlocks;\\n\\t\\t\\tthis.bufferCopyTotal = totalBlocks;\\n\\t\\t\\tthis.workBuffer.render(splatsToRender, this.cameraNode, this.getDebugColors(), changedAllocIds);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < worldState.splats.length; i++) {\\n\\t\\t\\tworldState.splats[i].update();\\n\\t\\t}\\n\\t\\tthis.updateColorCameraTracking();\\n\\t\\tif (worldState.pendingReleases && worldState.pendingReleases.length) {\\n\\t\\t\\tconst cooldownTicks = this.scene.gsplat.cooldownTicks;\\n\\t\\t\\tfor (const [octree, fileIndex] of worldState.pendingReleases) {\\n\\t\\t\\t\\toctree.decRefCount(fileIndex, cooldownTicks);\\n\\t\\t\\t}\\n\\t\\t\\tworldState.pendingReleases.length = 0;\\n\\t\\t}\\n\\t\\tthis.renderer.update(count, textureSize);\\n\\t}\\n\\tcleanupOldWorldStates(newVersion) {\\n\\t\\tconst activeState = this.worldStates.get(newVersion);\\n\\t\\tif (!activeState.fullRebuild) {\\n\\t\\t\\tfor (let v = this.sortedVersion + 1; v < newVersion; v++) {\\n\\t\\t\\t\\tif (this.worldStates.get(v)?.fullRebuild) {\\n\\t\\t\\t\\t\\tactiveState.fullRebuild = true;\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (!activeState.fullRebuild) {\\n\\t\\t\\tconst activeIds = activeState.needsUploadIds;\\n\\t\\t\\tconst lookup = activeState.allocIdToSplat;\\n\\t\\t\\tfor (let v = this.sortedVersion + 1; v < newVersion; v++) {\\n\\t\\t\\t\\tconst oldState = this.worldStates.get(v);\\n\\t\\t\\t\\tif (oldState) {\\n\\t\\t\\t\\t\\tfor (const allocId of oldState.needsUploadIds) {\\n\\t\\t\\t\\t\\t\\tif (!activeIds.has(allocId)) {\\n\\t\\t\\t\\t\\t\\t\\tactiveIds.add(allocId);\\n\\t\\t\\t\\t\\t\\t\\tconst splat = lookup.get(allocId);\\n\\t\\t\\t\\t\\t\\t\\tif (splat && !_queuedSplats.has(splat)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tactiveState.needsUpload.push(splat);\\n\\t\\t\\t\\t\\t\\t\\t\\t_queuedSplats.add(splat);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\t_queuedSplats.clear();\\n\\t\\t}\\n\\t\\tfor (let v = this.sortedVersion; v < newVersion; v++) {\\n\\t\\t\\tconst oldState = this.worldStates.get(v);\\n\\t\\t\\tif (oldState) {\\n\\t\\t\\t\\tfor (const splat of oldState.splats) {\\n\\t\\t\\t\\t\\tsplat.resource.decRefCount();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.worldStates.delete(v);\\n\\t\\t\\t\\toldState.destroy();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tapplyWorkBufferUpdates(state) {\\n\\t\\tconst { colorUpdateAngle } = this.scene.gsplat;\\n\\t\\tconst ratio = Math.tan(colorUpdateAngle * math.DEG_TO_RAD);\\n\\t\\tconst cameraPos = this.cameraNode.getPosition();\\n\\t\\tconst { translationDelta } = this.calculateColorCameraDeltas();\\n\\t\\tconst hasCameraMovement = translationDelta > 0;\\n\\t\\tlet uploadedBlocks = 0;\\n\\t\\tstate.splats.forEach((splat) => {\\n\\t\\t\\tif (splat.update()) {\\n\\t\\t\\t\\t_updatedSplats.push(splat);\\n\\t\\t\\t\\tuploadedBlocks += splat.intervalAllocIds.length;\\n\\t\\t\\t\\tif (splat.nodeInfos) {\\n\\t\\t\\t\\t\\tfor (const ni of splat.intervalNodeIndices) {\\n\\t\\t\\t\\t\\t\\tsplat.nodeInfos[ni].colorAccumulatedTranslation = 0;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tsplat.colorAccumulatedTranslation = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.sortNeeded = true;\\n\\t\\t\\t} else if (hasCameraMovement && splat.hasSphericalHarmonics) {\\n\\t\\t\\t\\t_splatsWithSH.push(splat);\\n\\t\\t\\t\\tif (splat.nodeInfos) {\\n\\t\\t\\t\\t\\tconst nodeIndices = splat.intervalNodeIndices;\\n\\t\\t\\t\\t\\tfor (let j = 0; j < nodeIndices.length; j++) {\\n\\t\\t\\t\\t\\t\\tconst nodeInfo = splat.nodeInfos[nodeIndices[j]];\\n\\t\\t\\t\\t\\t\\tnodeInfo.colorAccumulatedTranslation += translationDelta;\\n\\t\\t\\t\\t\\t\\tconst threshold = ratio * Math.max(1, nodeInfo.worldDistance);\\n\\t\\t\\t\\t\\t\\tif (nodeInfo.colorAccumulatedTranslation >= threshold) {\\n\\t\\t\\t\\t\\t\\t\\t_changedColorAllocIds.add(splat.intervalAllocIds[j]);\\n\\t\\t\\t\\t\\t\\t\\tnodeInfo.colorAccumulatedTranslation = 0;\\n\\t\\t\\t\\t\\t\\t\\tuploadedBlocks++;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tsplat.colorAccumulatedTranslation += translationDelta;\\n\\t\\t\\t\\t\\tinvModelMat.copy(splat.node.getWorldTransform()).invert();\\n\\t\\t\\t\\t\\tinvModelMat.transformPoint(cameraPos, _localCamPos);\\n\\t\\t\\t\\t\\tsplat.aabb.closestPoint(_localCamPos, _closestPt);\\n\\t\\t\\t\\t\\tconst dist = _localCamPos.distance(_closestPt) * splat.node.getWorldTransform().getScale().x;\\n\\t\\t\\t\\t\\tconst threshold = ratio * Math.max(1, dist);\\n\\t\\t\\t\\t\\tif (splat.colorAccumulatedTranslation >= threshold) {\\n\\t\\t\\t\\t\\t\\t_changedColorAllocIds.add(splat.allocId);\\n\\t\\t\\t\\t\\t\\tuploadedBlocks += splat.intervalAllocIds.length;\\n\\t\\t\\t\\t\\t\\tsplat.colorAccumulatedTranslation = 0;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tthis.bufferCopyUploaded += uploadedBlocks;\\n\\t\\tthis.bufferCopyTotal = this._allocationMap.size;\\n\\t\\tif (_updatedSplats.length > 0) {\\n\\t\\t\\tthis.workBuffer.render(_updatedSplats, this.cameraNode, this.getDebugColors());\\n\\t\\t\\t_updatedSplats.length = 0;\\n\\t\\t}\\n\\t\\tif (_changedColorAllocIds.size > 0) {\\n\\t\\t\\tthis.workBuffer.renderColor(\\n\\t\\t\\t\\t_splatsWithSH,\\n\\t\\t\\t\\tthis.cameraNode,\\n\\t\\t\\t\\tthis.getDebugColors(),\\n\\t\\t\\t\\t_changedColorAllocIds\\n\\t\\t\\t);\\n\\t\\t\\t_changedColorAllocIds.clear();\\n\\t\\t}\\n\\t\\t_splatsWithSH.length = 0;\\n\\t}\\n\\ttestCameraMovedForLod() {\\n\\t\\tconst distanceThreshold = this.scene.gsplat.lodUpdateDistance;\\n\\t\\tconst currentCameraPos = this.cameraNode.getPosition();\\n\\t\\tconst cameraMoved = this.lastLodCameraPos.distance(currentCameraPos) > distanceThreshold;\\n\\t\\tif (cameraMoved) {\\n\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tlet cameraRotated = false;\\n\\t\\tconst lodUpdateAngleDeg = this.scene.gsplat.lodUpdateAngle;\\n\\t\\tif (lodUpdateAngleDeg > 0) {\\n\\t\\t\\tif (Number.isFinite(this.lastLodCameraFwd.x)) {\\n\\t\\t\\t\\tconst currentCameraFwd = this.cameraNode.forward;\\n\\t\\t\\t\\tconst dot = Math.min(1, Math.max(-1, this.lastLodCameraFwd.dot(currentCameraFwd)));\\n\\t\\t\\t\\tconst angle = Math.acos(dot);\\n\\t\\t\\t\\tconst rotThreshold = lodUpdateAngleDeg * math.DEG_TO_RAD;\\n\\t\\t\\t\\tcameraRotated = angle > rotThreshold;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tcameraRotated = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst currentFov = this.cameraNode.camera.fov;\\n\\t\\tconst fovChanged = this.lastLodCameraFov < 0 || Math.abs(currentFov - this.lastLodCameraFov) > this.lastLodCameraFov * 0.02;\\n\\t\\treturn cameraMoved || cameraRotated || fovChanged;\\n\\t}\\n\\ttestCameraMovedForSort() {\\n\\t\\tconst epsilon = 1e-3;\\n\\t\\tif (this.scene.gsplat.radialSorting) {\\n\\t\\t\\tconst currentCameraPos = this.cameraNode.getPosition();\\n\\t\\t\\treturn this.lastSortCameraPos.distance(currentCameraPos) > epsilon;\\n\\t\\t}\\n\\t\\tif (Number.isFinite(this.lastSortCameraFwd.x)) {\\n\\t\\t\\tconst currentCameraFwd = this.cameraNode.forward;\\n\\t\\t\\tconst dot = Math.min(1, Math.max(-1, this.lastSortCameraFwd.dot(currentCameraFwd)));\\n\\t\\t\\treturn Math.acos(dot) > epsilon;\\n\\t\\t}\\n\\t\\treturn true;\\n\\t}\\n\\ttestFrustumChanged() {\\n\\t\\tconst epsilon = 1e-3;\\n\\t\\tif (!this.lastCullingProjMat.equals(this.cameraNode.camera.projectionMatrix)) {\\n\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tconst currentCameraFwd = this.cameraNode.forward;\\n\\t\\tconst dot = Math.min(1, Math.max(-1, this.lastCullingCameraFwd.dot(currentCameraFwd)));\\n\\t\\treturn Math.acos(dot) > epsilon;\\n\\t}\\n\\tupdateColorCameraTracking() {\\n\\t\\tthis.lastColorUpdateCameraPos.copy(this.cameraNode.getPosition());\\n\\t}\\n\\tgetDebugColors() {\\n\\t\\tconst debug = this.scene.gsplat.debug;\\n\\t\\tif (debug === GSPLAT_DEBUG_SH_UPDATE) {\\n\\t\\t\\t_randomColorRaw ?? (_randomColorRaw = []);\\n\\t\\t\\tconst r = Math.random();\\n\\t\\t\\tconst g = Math.random();\\n\\t\\t\\tconst b = Math.random();\\n\\t\\t\\tfor (let i = 0; i < _lodColorsRaw.length; i++) {\\n\\t\\t\\t\\t_randomColorRaw[i] ?? (_randomColorRaw[i] = [0, 0, 0]);\\n\\t\\t\\t\\t_randomColorRaw[i][0] = r;\\n\\t\\t\\t\\t_randomColorRaw[i][1] = g;\\n\\t\\t\\t\\t_randomColorRaw[i][2] = b;\\n\\t\\t\\t}\\n\\t\\t\\treturn _randomColorRaw;\\n\\t\\t} else if (debug === GSPLAT_DEBUG_LOD) {\\n\\t\\t\\treturn _lodColorsRaw;\\n\\t\\t}\\n\\t\\treturn void 0;\\n\\t}\\n\\tcalculateColorCameraDeltas() {\\n\\t\\t_cameraDeltas.translationDelta = 0;\\n\\t\\tif (isFinite(this.lastColorUpdateCameraPos.x)) {\\n\\t\\t\\tconst currentCameraPos = this.cameraNode.getPosition();\\n\\t\\t\\t_cameraDeltas.translationDelta = this.lastColorUpdateCameraPos.distance(currentCameraPos);\\n\\t\\t}\\n\\t\\treturn _cameraDeltas;\\n\\t}\\n\\tfireFrameReadyEvent() {\\n\\t\\tconst ready = this.sortedVersion === this.lastWorldStateVersion && !this._awaitingLodUpdate;\\n\\t\\tlet loadingCount = 0;\\n\\t\\tfor (const [, inst] of this.octreeInstances) {\\n\\t\\t\\tloadingCount += inst.pendingLoadCount;\\n\\t\\t}\\n\\t\\tthis.director.eventHandler.fire(\\\"frame:ready\\\", this.cameraNode.camera, this.renderer.layer, ready, loadingCount);\\n\\t}\\n\\tcomputeGlobalMaxDistance() {\\n\\t\\tlet maxDist = 0;\\n\\t\\tcameraPosition.copy(this.cameraNode.getPosition());\\n\\t\\tfor (const [, inst] of this.octreeInstances) {\\n\\t\\t\\tconst worldTransform = inst.placement.node.getWorldTransform();\\n\\t\\t\\tconst aabb = inst.placement.aabb;\\n\\t\\t\\tworldTransform.transformPoint(aabb.center, _tempVec3);\\n\\t\\t\\tconst scale = worldTransform.getScale().x;\\n\\t\\t\\tconst dist = _tempVec3.distance(cameraPosition) + aabb.halfExtents.length() * scale;\\n\\t\\t\\tif (dist > maxDist) maxDist = dist;\\n\\t\\t}\\n\\t\\treturn Math.max(maxDist, 1);\\n\\t}\\n\\t_enforceBudget(budget) {\\n\\t\\tconst textureWidth = this.workBuffer.textureSize;\\n\\t\\tlet fixedSplats = 0;\\n\\t\\tlet paddingEstimate = 0;\\n\\t\\tfor (const p of this.layerPlacements) {\\n\\t\\t\\tconst resource = p.resource;\\n\\t\\t\\tif (resource) {\\n\\t\\t\\t\\tconst numSplats = resource.numSplats ?? 0;\\n\\t\\t\\t\\tfixedSplats += numSplats;\\n\\t\\t\\t\\tpaddingEstimate += (textureWidth - numSplats % textureWidth) % textureWidth;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst octreeBudget = Math.max(1, budget - fixedSplats);\\n\\t\\tconst globalMaxDistance = this.computeGlobalMaxDistance();\\n\\t\\tlet totalOptimalSplats = 0;\\n\\t\\tfor (const [, inst] of this.octreeInstances) {\\n\\t\\t\\ttotalOptimalSplats += inst.evaluateOptimalLods(this.cameraNode, this.scene.gsplat, this._budgetScale, globalMaxDistance);\\n\\t\\t\\tfor (const placement of inst.activePlacements) {\\n\\t\\t\\t\\tconst resource = placement.resource;\\n\\t\\t\\t\\tconst numSplats = resource?.numSplats ?? 0;\\n\\t\\t\\t\\tpaddingEstimate += (textureWidth - numSplats % textureWidth) % textureWidth;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst adjustedBudget = Math.max(1, octreeBudget - paddingEstimate);\\n\\t\\tif (totalOptimalSplats > 0) {\\n\\t\\t\\tconst ratio = totalOptimalSplats / adjustedBudget;\\n\\t\\t\\tconst budgetScaleDeadZone = 0.4;\\n\\t\\t\\tconst budgetScaleBlendRate = 0.3;\\n\\t\\t\\tif (ratio > 1 + budgetScaleDeadZone || ratio < 1 - budgetScaleDeadZone) {\\n\\t\\t\\t\\tconst invCorrection = 1 / Math.sqrt(ratio);\\n\\t\\t\\t\\tthis._budgetScale *= 1 + (invCorrection - 1) * budgetScaleBlendRate;\\n\\t\\t\\t\\tthis._budgetScale = Math.max(0.01, Math.min(this._budgetScale, 100));\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._budgetBalancer.balance(this.octreeInstances, adjustedBudget);\\n\\t\\tfor (const [, inst] of this.octreeInstances) {\\n\\t\\t\\tconst maxLod = inst.octree.lodLevels - 1;\\n\\t\\t\\tinst.applyLodChanges(maxLod, this.scene.gsplat);\\n\\t\\t}\\n\\t}\\n\\thandleFormatChange() {\\n\\t\\tconst currentFormat = this.scene.gsplat.format;\\n\\t\\tif (this.workBuffer.format !== currentFormat) {\\n\\t\\t\\tthis.workBuffer.destroy();\\n\\t\\t\\tthis.workBuffer = new GSplatWorkBuffer(this.device, currentFormat);\\n\\t\\t\\tthis.renderer.setDataSource(this.workBuffer);\\n\\t\\t\\tthis._workBufferFormatVersion = this.workBuffer.format.extraStreamsVersion;\\n\\t\\t\\tthis._workBufferRebuildRequired = true;\\n\\t\\t\\tthis.sortNeeded = true;\\n\\t\\t}\\n\\t}\\n\\tupdate() {\\n\\t\\tthis.bufferCopyUploaded = 0;\\n\\t\\tthis.bufferCopyTotal = 0;\\n\\t\\tthis.handleFormatChange();\\n\\t\\tconst wbFormatVersion = this.workBuffer.format.extraStreamsVersion;\\n\\t\\tif (this._workBufferFormatVersion !== wbFormatVersion) {\\n\\t\\t\\tthis._workBufferFormatVersion = wbFormatVersion;\\n\\t\\t\\tthis.workBuffer.syncWithFormat();\\n\\t\\t\\tthis._workBufferRebuildRequired = true;\\n\\t\\t\\tthis.sortNeeded = true;\\n\\t\\t}\\n\\t\\tthis.prepareRendererMode();\\n\\t\\tif (this.cpuSorter) {\\n\\t\\t\\tthis.cpuSorter.applyPendingSorted();\\n\\t\\t}\\n\\t\\tconst sorterAvailable = this.activeRenderer !== GSPLAT_RENDERER_RASTER_CPU_SORT || this.cpuSorter && this.cpuSorter.jobsInFlight < 3;\\n\\t\\tlet fullUpdate = false;\\n\\t\\tthis.framesTillFullUpdate--;\\n\\t\\tif (this.framesTillFullUpdate <= 0) {\\n\\t\\t\\tthis.framesTillFullUpdate = 10;\\n\\t\\t\\tif (sorterAvailable) {\\n\\t\\t\\t\\tfullUpdate = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst hasNewInstances = this.hasNewOctreeInstances && sorterAvailable;\\n\\t\\tif (hasNewInstances) this.hasNewOctreeInstances = false;\\n\\t\\tlet anyInstanceNeedsLodUpdate = false;\\n\\t\\tlet anyOctreeMoved = false;\\n\\t\\tlet cameraMovedOrRotatedForLod = false;\\n\\t\\tif (fullUpdate) {\\n\\t\\t\\tfor (const [, inst] of this.octreeInstances) {\\n\\t\\t\\t\\tconst isDirty = inst.update();\\n\\t\\t\\t\\tthis.layerPlacementsDirty || (this.layerPlacementsDirty = isDirty);\\n\\t\\t\\t\\tthis._placementSetChanged || (this._placementSetChanged = inst.consumePlacementSetChanged());\\n\\t\\t\\t\\tconst instNeeds = inst.consumeNeedsLodUpdate();\\n\\t\\t\\t\\tanyInstanceNeedsLodUpdate || (anyInstanceNeedsLodUpdate = instNeeds);\\n\\t\\t\\t}\\n\\t\\t\\tconst threshold = this.scene.gsplat.lodUpdateDistance;\\n\\t\\t\\tfor (const [, inst] of this.octreeInstances) {\\n\\t\\t\\t\\tconst moved = inst.testMoved(threshold);\\n\\t\\t\\t\\tanyOctreeMoved || (anyOctreeMoved = moved);\\n\\t\\t\\t}\\n\\t\\t\\tcameraMovedOrRotatedForLod = this.testCameraMovedForLod();\\n\\t\\t\\tthis._awaitingLodUpdate = false;\\n\\t\\t}\\n\\t\\tif (this.testCameraMovedForSort()) {\\n\\t\\t\\tthis.sortNeeded = true;\\n\\t\\t}\\n\\t\\tif (this.intervalCompaction && !this.sortNeeded && this.testFrustumChanged()) {\\n\\t\\t\\tthis.lastCullingCameraFwd.copy(this.cameraNode.forward);\\n\\t\\t\\tthis.lastCullingProjMat.copy(this.cameraNode.camera.projectionMatrix);\\n\\t\\t\\tthis.sortNeeded = true;\\n\\t\\t}\\n\\t\\tif (this.scene.gsplat.dirty) {\\n\\t\\t\\tthis.layerPlacementsDirty = true;\\n\\t\\t\\tthis.renderer.updateOverdrawMode(this.scene.gsplat);\\n\\t\\t\\tthis._workBufferRebuildRequired = true;\\n\\t\\t\\tthis.sortNeeded = true;\\n\\t\\t\\tif (this.octreeInstances.size > 0) {\\n\\t\\t\\t\\tthis._awaitingLodUpdate = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (cameraMovedOrRotatedForLod || anyOctreeMoved || this.scene.gsplat.dirty || anyInstanceNeedsLodUpdate || hasNewInstances) {\\n\\t\\t\\tfor (const [, inst] of this.octreeInstances) {\\n\\t\\t\\t\\tinst.updateMoved();\\n\\t\\t\\t}\\n\\t\\t\\tconst cameraNode = this.cameraNode;\\n\\t\\t\\tthis.lastLodCameraPos.copy(cameraNode.getPosition());\\n\\t\\t\\tthis.lastLodCameraFwd.copy(cameraNode.forward);\\n\\t\\t\\tthis.lastLodCameraFov = cameraNode.camera.fov;\\n\\t\\t\\tconst budget = this.scene.gsplat.splatBudget;\\n\\t\\t\\tif (budget > 0) {\\n\\t\\t\\t\\tthis._enforceBudget(budget);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._budgetScale = 1;\\n\\t\\t\\t\\tfor (const [, inst] of this.octreeInstances) {\\n\\t\\t\\t\\t\\tinst.updateLod(this.cameraNode, this.scene.gsplat);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.updateWorldState();\\n\\t\\tconst lastState = this.worldStates.get(this.lastWorldStateVersion);\\n\\t\\tif (lastState) {\\n\\t\\t\\tif (this.cpuSorter && !lastState.sortParametersSet) {\\n\\t\\t\\t\\tlastState.sortParametersSet = true;\\n\\t\\t\\t\\tconst payload = this.prepareSortParameters(lastState);\\n\\t\\t\\t\\tthis.cpuSorter.setSortParameters(payload);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst sortedState = this.worldStates.get(this.sortedVersion);\\n\\t\\tif (sortedState?.sortedBefore) {\\n\\t\\t\\tif (this._workBufferRebuildRequired) {\\n\\t\\t\\t\\tconst count = sortedState.totalActiveSplats;\\n\\t\\t\\t\\tthis.rebuildWorkBuffer(sortedState, count, true);\\n\\t\\t\\t\\tthis._workBufferRebuildRequired = false;\\n\\t\\t\\t\\tthis.renderer.setOrderData();\\n\\t\\t\\t\\tif (this.intervalCompaction) {\\n\\t\\t\\t\\t\\tthis.intervalCompaction._uploadedVersion = -1;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.applyWorkBufferUpdates(sortedState);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tlet gpuSortedThisFrame = false;\\n\\t\\tif (this.sortNeeded && lastState) {\\n\\t\\t\\tif (this.activeRenderer === GSPLAT_RENDERER_COMPUTE) {\\n\\t\\t\\t\\tthis.compactGpu(lastState);\\n\\t\\t\\t\\tgpuSortedThisFrame = true;\\n\\t\\t\\t} else if (this.activeRenderer === GSPLAT_RENDERER_RASTER_GPU_SORT) {\\n\\t\\t\\t\\tthis.sortGpuHybrid(lastState);\\n\\t\\t\\t\\tgpuSortedThisFrame = true;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.sortCpu(lastState);\\n\\t\\t\\t}\\n\\t\\t\\tthis.sortNeeded = false;\\n\\t\\t\\tthis.lastSortCameraPos.copy(this.cameraNode.getPosition());\\n\\t\\t\\tthis.lastSortCameraFwd.copy(this.cameraNode.forward);\\n\\t\\t\\tthis.lastCullingCameraFwd.copy(this.cameraNode.forward);\\n\\t\\t\\tthis.lastCullingProjMat.copy(this.cameraNode.camera.projectionMatrix);\\n\\t\\t}\\n\\t\\tif (this.activeRenderer === GSPLAT_RENDERER_RASTER_GPU_SORT && lastState && !gpuSortedThisFrame) {\\n\\t\\t\\tthis.sortGpuHybrid(lastState);\\n\\t\\t\\tgpuSortedThisFrame = true;\\n\\t\\t}\\n\\t\\tif (sortedState?.sortedBefore) {\\n\\t\\t\\tthis.updateColorCameraTracking();\\n\\t\\t}\\n\\t\\tif (this.octreeInstances.size) {\\n\\t\\t\\tconst cooldownTicks = this.scene.gsplat.cooldownTicks;\\n\\t\\t\\tfor (const [, inst] of this.octreeInstances) {\\n\\t\\t\\t\\tconst octree = inst.octree;\\n\\t\\t\\t\\tif (!tempOctreesTicked.has(octree)) {\\n\\t\\t\\t\\t\\ttempOctreesTicked.add(octree);\\n\\t\\t\\t\\t\\toctree.updateCooldownTick(cooldownTicks);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\ttempOctreesTicked.clear();\\n\\t\\t}\\n\\t\\tthis.fireFrameReadyEvent();\\n\\t\\tif (this.scene.gsplat.dirty) {\\n\\t\\t\\tfor (const [, inst] of this.octreeInstances) {\\n\\t\\t\\t\\tinst.needsLodUpdate = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst fogParams = this.scene.gsplat.useFog ? this.cameraNode.camera.fogParams ?? this.scene.fog : null;\\n\\t\\tthis.renderer.frameUpdate(this.scene.gsplat, this.scene.exposure, fogParams);\\n\\t\\treturn sortedState ? sortedState.totalActiveSplats : 0;\\n\\t}\\n\\tsortGpuHybrid(worldState) {\\n\\t\\tconst cam = this.cameraNode.camera;\\n\\t\\tconst sceneCam = cam.camera;\\n\\t\\tconst rt = cam.renderTarget;\\n\\t\\tconst rect = cam.rect;\\n\\t\\tconst xrView = sceneCam.xr?.session ? sceneCam.xr.views.list[0] : null;\\n\\t\\tconst viewportWidth = Math.floor((xrView ? xrView.viewport.z : rt ? rt.width : this.device.width) * rect.z);\\n\\t\\tconst viewportHeight = Math.floor((xrView ? xrView.viewport.w : rt ? rt.height : this.device.height) * rect.w);\\n\\t\\tconst sortedIndices = this.sortGpuHybridForCamera(\\n\\t\\t\\tworldState,\\n\\t\\t\\tthis.cameraNode,\\n\\t\\t\\tviewportWidth,\\n\\t\\t\\tviewportHeight,\\n\\t\\t\\tMath.max(ALPHA_VISIBILITY_THRESHOLD, this.scene.gsplat.alphaClipForward),\\n\\t\\t\\tfalse\\n\\t\\t);\\n\\t\\tif (sortedIndices) {\\n\\t\\t\\tthis.applyGpuSortResults(sortedIndices);\\n\\t\\t}\\n\\t}\\n\\tsortGpuHybridForCamera(worldState, cameraNode, viewportWidth, viewportHeight, alphaClip, pickMode) {\\n\\t\\tconst gpuSorter = this.gpuSorter;\\n\\t\\tconst projector = this.projector;\\n\\t\\tif (!gpuSorter || !projector) return null;\\n\\t\\tconst elementCount = worldState.totalActiveSplats;\\n\\t\\tif (elementCount === 0) return null;\\n\\t\\tif (!this.intervalCompaction) {\\n\\t\\t\\tthis.intervalCompaction = new GSplatIntervalCompaction(this.device);\\n\\t\\t}\\n\\t\\tif (!worldState.sortedBefore) {\\n\\t\\t\\tworldState.sortedBefore = true;\\n\\t\\t\\tthis.cleanupOldWorldStates(worldState.version);\\n\\t\\t\\tthis.sortedVersion = worldState.version;\\n\\t\\t\\tthis.rebuildWorkBuffer(worldState, elementCount);\\n\\t\\t}\\n\\t\\tthis.intervalCompaction.uploadIntervals(worldState);\\n\\t\\tif (this.canCull) {\\n\\t\\t\\tconst state = this.worldStates.get(this.sortedVersion);\\n\\t\\t\\tif (state) {\\n\\t\\t\\t\\tthis._runFrustumCulling(state, cameraNode);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst fisheyeProj = this.renderer.fisheyeProj;\\n\\t\\tconst numIntervals = worldState.totalIntervals;\\n\\t\\tconst totalActiveSplats = worldState.totalActiveSplats;\\n\\t\\tthis.intervalCompaction.dispatchCompact(this.workBuffer.frustumCuller, numIntervals, totalActiveSplats, fisheyeProj.enabled);\\n\\t\\tthis.allocateAndWriteIntervalIndirectArgs(numIntervals);\\n\\t\\tconst ic = this.intervalCompaction;\\n\\t\\tconst compactedSplatIds = ic.compactedSplatIds;\\n\\t\\tconst gsplat = this.scene.gsplat;\\n\\t\\tconst numBits = Math.max(10, Math.min(20, Math.round(Math.log2(elementCount / 4))));\\n\\t\\tconst radixBits = gpuSorter.radixBits;\\n\\t\\tconst roundedNumBits = Math.ceil(numBits / radixBits) * radixBits;\\n\\t\\tconst { minDist, maxDist } = this.computeDistanceRange(worldState, cameraNode);\\n\\t\\tconst sortIndirectInfo = gpuSorter.prepareIndirect();\\n\\t\\tprojector.dispatch({\\n\\t\\t\\tworkBuffer: this.workBuffer,\\n\\t\\t\\tcameraNode,\\n\\t\\t\\tcompactedSplatIds,\\n\\t\\t\\tsortElementCountBuffer: ic.sortElementCountBuffer,\\n\\t\\t\\ttotalCapacity: elementCount,\\n\\t\\t\\tradialSort: gsplat.radialSorting,\\n\\t\\t\\tnumBits: roundedNumBits,\\n\\t\\t\\tminDist,\\n\\t\\t\\tmaxDist,\\n\\t\\t\\talphaClip,\\n\\t\\t\\tminPixelSize: gsplat.minPixelSize * 0.5,\\n\\t\\t\\tminContribution: gsplat.minContribution,\\n\\t\\t\\tviewportWidth,\\n\\t\\t\\tviewportHeight,\\n\\t\\t\\tflipY: !!cameraNode.camera.renderTarget?.flipY,\\n\\t\\t\\tpickMode,\\n\\t\\t\\tfisheyeProj,\\n\\t\\t\\tantiAlias: gsplat.antiAlias\\n\\t\\t});\\n\\t\\tprojector.writeIndirectArgs(\\n\\t\\t\\tthis.indirectDrawSlot,\\n\\t\\t\\tthis.indirectDispatchSlot + 1,\\n\\t\\t\\tic.numSplatsBuffer,\\n\\t\\t\\tic.sortElementCountBuffer,\\n\\t\\t\\tsortIndirectInfo\\n\\t\\t);\\n\\t\\treturn gpuSorter.sortIndirect(\\n\\t\\t\\tprojector.sortKeys,\\n\\t\\t\\telementCount,\\n\\t\\t\\troundedNumBits,\\n\\t\\t\\tthis.indirectDispatchSlot + 1,\\n\\t\\t\\tic.sortElementCountBuffer,\\n\\t\\t\\tvoid 0,\\n\\t\\t\\tfalse,\\n\\t\\t\\ttrue\\n\\t\\t\\t// destructiveKeys: projector overwrites sortKeys each frame before the sort\\n\\t\\t);\\n\\t}\\n\\tcompactGpu(worldState) {\\n\\t\\tif (!this.intervalCompaction) {\\n\\t\\t\\tthis.intervalCompaction = new GSplatIntervalCompaction(this.device);\\n\\t\\t}\\n\\t\\tconst elementCount = worldState.totalActiveSplats;\\n\\t\\tif (elementCount === 0) return;\\n\\t\\tif (!worldState.sortedBefore) {\\n\\t\\t\\tworldState.sortedBefore = true;\\n\\t\\t\\tthis.cleanupOldWorldStates(worldState.version);\\n\\t\\t\\tthis.sortedVersion = worldState.version;\\n\\t\\t\\tthis.rebuildWorkBuffer(worldState, elementCount);\\n\\t\\t}\\n\\t\\tthis.intervalCompaction.uploadIntervals(worldState);\\n\\t\\tif (this.canCull) {\\n\\t\\t\\tconst state = this.worldStates.get(this.sortedVersion);\\n\\t\\t\\tif (state) {\\n\\t\\t\\t\\tthis._runFrustumCulling(state);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst numIntervals = worldState.totalIntervals;\\n\\t\\tconst totalActiveSplats = worldState.totalActiveSplats;\\n\\t\\tthis.intervalCompaction.dispatchCompact(this.workBuffer.frustumCuller, numIntervals, totalActiveSplats, this.renderer.fisheyeProj.enabled);\\n\\t\\tthis.allocateAndWriteIntervalIndirectArgs(numIntervals);\\n\\t\\tconst ic = this.intervalCompaction;\\n\\t\\tconst localRenderer = this.renderer;\\n\\t\\tlocalRenderer.setCompactedData(\\n\\t\\t\\tic.compactedSplatIds,\\n\\t\\t\\tic.sortElementCountBuffer,\\n\\t\\t\\tworldState.textureSize,\\n\\t\\t\\ttotalActiveSplats\\n\\t\\t);\\n\\t}\\n\\tallocateAndWriteIntervalIndirectArgs(numIntervals) {\\n\\t\\tconst gpuSorter = this.gpuSorter;\\n\\t\\tconst sortInfo = gpuSorter ? gpuSorter.prepareIndirect() : NO_SORT_INDIRECT_INFO;\\n\\t\\tconst sortSlotCount = sortInfo[0];\\n\\t\\tthis.indirectDrawSlot = this.device.getIndirectDrawSlot(1);\\n\\t\\tthis.indirectDispatchSlot = this.device.getIndirectDispatchSlot(1 + sortSlotCount);\\n\\t\\tconst ic = this.intervalCompaction;\\n\\t\\tic.writeIndirectArgs(this.indirectDrawSlot, this.indirectDispatchSlot, numIntervals, sortInfo);\\n\\t\\tthis.lastCompactedNumIntervals = numIntervals;\\n\\t}\\n\\tapplyGpuSortResults(sortedIndices) {\\n\\t\\tconst proj = this.projector;\\n\\t\\tconst ic = this.intervalCompaction;\\n\\t\\tthis.renderer.setHybridSortedRendering(\\n\\t\\t\\tthis.indirectDrawSlot,\\n\\t\\t\\tsortedIndices,\\n\\t\\t\\tproj.projCache,\\n\\t\\t\\tic.numSplatsBuffer\\n\\t\\t);\\n\\t}\\n\\t_runFrustumCulling(worldState, cameraNode = this.cameraNode) {\\n\\t\\tthis.workBuffer.frustumCuller.updateTransformsData(worldState.boundsGroups);\\n\\t\\tconst cam = cameraNode.camera;\\n\\t\\tthis.workBuffer.frustumCuller.computeFrustumPlanes(cam.projectionMatrix, cam.viewMatrix);\\n\\t\\tconst gsplat = this.scene.gsplat;\\n\\t\\tconst fp = this.renderer.fisheyeProj;\\n\\t\\tfp.update(gsplat.fisheye, cam.fov, cam.projectionMatrix);\\n\\t\\tif (fp.enabled) {\\n\\t\\t\\tthis.workBuffer.frustumCuller.setFisheyeData(\\n\\t\\t\\t\\tcameraNode.getPosition(),\\n\\t\\t\\t\\tcameraNode.forward,\\n\\t\\t\\t\\tfp.maxTheta\\n\\t\\t\\t);\\n\\t\\t}\\n\\t}\\n\\tcomputeDistanceRange(worldState, cameraNode = this.cameraNode) {\\n\\t\\tconst cameraMat = cameraNode.getWorldTransform();\\n\\t\\tcameraMat.getTranslation(cameraPosition);\\n\\t\\tcameraMat.getZ(cameraDirection).normalize();\\n\\t\\tconst radialSort = this.scene.gsplat.radialSorting;\\n\\t\\tlet minDist = radialSort ? 0 : Infinity;\\n\\t\\tlet maxDist = radialSort ? 0 : -Infinity;\\n\\t\\tfor (const splat of worldState.splats) {\\n\\t\\t\\tconst modelMat = splat.node.getWorldTransform();\\n\\t\\t\\tconst aabbMin = splat.aabb.getMin();\\n\\t\\t\\tconst aabbMax = splat.aabb.getMax();\\n\\t\\t\\tfor (let i = 0; i < 8; i++) {\\n\\t\\t\\t\\t_tempVec3.x = i & 1 ? aabbMax.x : aabbMin.x;\\n\\t\\t\\t\\t_tempVec3.y = i & 2 ? aabbMax.y : aabbMin.y;\\n\\t\\t\\t\\t_tempVec3.z = i & 4 ? aabbMax.z : aabbMin.z;\\n\\t\\t\\t\\tmodelMat.transformPoint(_tempVec3, _tempVec3);\\n\\t\\t\\t\\tif (radialSort) {\\n\\t\\t\\t\\t\\tconst dist = _tempVec3.distance(cameraPosition);\\n\\t\\t\\t\\t\\tif (dist > maxDist) maxDist = dist;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tconst dist = _tempVec3.sub(cameraPosition).dot(cameraDirection);\\n\\t\\t\\t\\t\\tif (dist < minDist) minDist = dist;\\n\\t\\t\\t\\t\\tif (dist > maxDist) maxDist = dist;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (maxDist === 0 || maxDist === -Infinity) {\\n\\t\\t\\treturn { minDist: 0, maxDist: 1 };\\n\\t\\t}\\n\\t\\treturn { minDist, maxDist };\\n\\t}\\n\\tsortCpu(lastState) {\\n\\t\\tif (!this.cpuSorter) return;\\n\\t\\tconst cameraNode = this.cameraNode;\\n\\t\\tconst cameraMat = cameraNode.getWorldTransform();\\n\\t\\tcameraMat.getTranslation(cameraPosition);\\n\\t\\tcameraMat.getZ(cameraDirection).normalize();\\n\\t\\tconst sorterRequest = [];\\n\\t\\tlastState.splats.forEach((splat) => {\\n\\t\\t\\tconst modelMat = splat.node.getWorldTransform();\\n\\t\\t\\tinvModelMat.copy(modelMat).invert();\\n\\t\\t\\tconst uniformScale = modelMat.getScale().x;\\n\\t\\t\\tconst transformedDirection = invModelMat.transformVector(cameraDirection).normalize();\\n\\t\\t\\tconst transformedPosition = invModelMat.transformPoint(cameraPosition);\\n\\t\\t\\tmodelMat.getTranslation(translation);\\n\\t\\t\\tconst offset = translation.sub(cameraPosition).dot(cameraDirection);\\n\\t\\t\\tconst aabbMin = splat.aabb.getMin();\\n\\t\\t\\tconst aabbMax = splat.aabb.getMax();\\n\\t\\t\\tsorterRequest.push({\\n\\t\\t\\t\\ttransformedDirection,\\n\\t\\t\\t\\ttransformedPosition,\\n\\t\\t\\t\\toffset,\\n\\t\\t\\t\\tscale: uniformScale,\\n\\t\\t\\t\\tmodelMat: modelMat.data.slice(),\\n\\t\\t\\t\\taabbMin: [aabbMin.x, aabbMin.y, aabbMin.z],\\n\\t\\t\\t\\taabbMax: [aabbMax.x, aabbMax.y, aabbMax.z]\\n\\t\\t\\t});\\n\\t\\t});\\n\\t\\tthis.cpuSorter.setSortParams(sorterRequest, this.scene.gsplat.radialSorting);\\n\\t}\\n\\tprepareSortParameters(worldState) {\\n\\t\\treturn {\\n\\t\\t\\tcommand: \\\"intervals\\\",\\n\\t\\t\\ttextureSize: worldState.textureSize,\\n\\t\\t\\ttotalActiveSplats: worldState.totalActiveSplats,\\n\\t\\t\\tversion: worldState.version,\\n\\t\\t\\tids: worldState.splats.map((splat) => splat.resource.id),\\n\\t\\t\\tpixelOffsets: worldState.splats.map((splat) => splat.intervalOffsets),\\n\\t\\t\\t// TODO: consider storing this in typed array and transfer it to sorter worker\\n\\t\\t\\tintervals: worldState.splats.map((splat) => splat.intervals)\\n\\t\\t};\\n\\t}\\n}\\n\\nclass SetUtils {\\n\\tstatic equals(setA, setB) {\\n\\t\\tif (setA.size !== setB.size) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tfor (const elem of setA) {\\n\\t\\t\\tif (!setB.has(elem)) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn true;\\n\\t}\\n}\\n\\nconst tempLayersToRemove = [];\\nclass GSplatLayerData {\\n\\tgsplatManager = null;\\n\\tgsplatManagerShadow = null;\\n\\tconstructor(device, director, layer, camera) {\\n\\t\\tthis.updateConfiguration(device, director, layer, camera);\\n\\t}\\n\\tcreateManager(device, director, layer, cameraNode, camera, renderMode) {\\n\\t\\tconst manager = new GSplatManager(device, director, layer, cameraNode);\\n\\t\\tmanager.setRenderMode(renderMode);\\n\\t\\tif (director.eventHandler) {\\n\\t\\t\\tdirector.eventHandler.fire(\\\"material:created\\\", manager.material, camera, layer);\\n\\t\\t}\\n\\t\\treturn manager;\\n\\t}\\n\\tupdateConfiguration(device, director, layer, camera) {\\n\\t\\tconst cameraNode = camera.node;\\n\\t\\tconst hasNormalPlacements = layer.gsplatPlacements.length > 0;\\n\\t\\tconst hasShadowCasters = layer.gsplatShadowCasters.length > 0;\\n\\t\\tconst setsEqual = SetUtils.equals(layer.gsplatPlacementsSet, layer.gsplatShadowCastersSet);\\n\\t\\tconst useSharedManager = setsEqual && hasNormalPlacements;\\n\\t\\tconst desiredMainMode = useSharedManager ? GSPLAT_FORWARD | GSPLAT_SHADOW : hasNormalPlacements ? GSPLAT_FORWARD : 0;\\n\\t\\tconst desiredShadowMode = useSharedManager ? 0 : hasShadowCasters ? GSPLAT_SHADOW : 0;\\n\\t\\tif (desiredMainMode) {\\n\\t\\t\\tif (this.gsplatManager) {\\n\\t\\t\\t\\tthis.gsplatManager.setRenderMode(desiredMainMode);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.gsplatManager = this.createManager(device, director, layer, cameraNode, camera, desiredMainMode);\\n\\t\\t\\t}\\n\\t\\t} else if (this.gsplatManager) {\\n\\t\\t\\tthis.gsplatManager.destroy();\\n\\t\\t\\tthis.gsplatManager = null;\\n\\t\\t}\\n\\t\\tif (desiredShadowMode) {\\n\\t\\t\\tif (this.gsplatManagerShadow) {\\n\\t\\t\\t\\tthis.gsplatManagerShadow.setRenderMode(desiredShadowMode);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.gsplatManagerShadow = this.createManager(device, director, layer, cameraNode, camera, desiredShadowMode);\\n\\t\\t\\t}\\n\\t\\t} else if (this.gsplatManagerShadow) {\\n\\t\\t\\tthis.gsplatManagerShadow.destroy();\\n\\t\\t\\tthis.gsplatManagerShadow = null;\\n\\t\\t}\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.gsplatManager?.destroy();\\n\\t\\tthis.gsplatManager = null;\\n\\t\\tthis.gsplatManagerShadow?.destroy();\\n\\t\\tthis.gsplatManagerShadow = null;\\n\\t}\\n}\\nclass GSplatCameraData {\\n\\tlayersMap = /* @__PURE__ */ new Map();\\n\\tdestroy() {\\n\\t\\tthis.layersMap.forEach((layerData) => layerData.destroy());\\n\\t\\tthis.layersMap.clear();\\n\\t}\\n\\tremoveLayerData(layer) {\\n\\t\\tconst layerData = this.layersMap.get(layer);\\n\\t\\tif (layerData) {\\n\\t\\t\\tlayerData.destroy();\\n\\t\\t\\tthis.layersMap.delete(layer);\\n\\t\\t}\\n\\t}\\n\\tgetLayerData(device, director, layer, camera) {\\n\\t\\tlet layerData = this.layersMap.get(layer);\\n\\t\\tif (!layerData) {\\n\\t\\t\\tlayerData = new GSplatLayerData(device, director, layer, camera);\\n\\t\\t\\tthis.layersMap.set(layer, layerData);\\n\\t\\t}\\n\\t\\treturn layerData;\\n\\t}\\n}\\nclass GSplatDirector {\\n\\tdevice;\\n\\tcamerasMap = /* @__PURE__ */ new Map();\\n\\tscene;\\n\\teventHandler;\\n\\tconstructor(device, renderer, scene, eventHandler) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.renderer = renderer;\\n\\t\\tthis.scene = scene;\\n\\t\\tthis.eventHandler = eventHandler;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.camerasMap.forEach((cameraData) => cameraData.destroy());\\n\\t\\tthis.camerasMap.clear();\\n\\t}\\n\\tgetCameraData(camera) {\\n\\t\\tlet cameraData = this.camerasMap.get(camera);\\n\\t\\tif (!cameraData) {\\n\\t\\t\\tcameraData = new GSplatCameraData();\\n\\t\\t\\tthis.camerasMap.set(camera, cameraData);\\n\\t\\t}\\n\\t\\treturn cameraData;\\n\\t}\\n\\tprepareForPicking(camera, width, height, layer) {\\n\\t\\tconst cameraData = this.camerasMap.get(camera);\\n\\t\\tif (!cameraData) return null;\\n\\t\\tconst layerData = cameraData.layersMap.get(layer);\\n\\t\\tif (!layerData?.gsplatManager) return null;\\n\\t\\treturn layerData.gsplatManager.prepareForPicking(camera, width, height);\\n\\t}\\n\\tupdate(comp) {\\n\\t\\tGSplatResourceCleanup.process(this.device);\\n\\t\\tthis.camerasMap.forEach((cameraData, camera) => {\\n\\t\\t\\tif (!comp.camerasSet.has(camera)) {\\n\\t\\t\\t\\tcameraData.destroy();\\n\\t\\t\\t\\tthis.camerasMap.delete(camera);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tcameraData.layersMap.forEach((layerData, layer) => {\\n\\t\\t\\t\\t\\tif (!camera.layersSet.has(layer.id) || !layer.enabled) {\\n\\t\\t\\t\\t\\t\\ttempLayersToRemove.push(layer);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tfor (let i = 0; i < tempLayersToRemove.length; i++) {\\n\\t\\t\\t\\t\\tconst layer = tempLayersToRemove[i];\\n\\t\\t\\t\\t\\tconst layerData = cameraData.layersMap.get(layer);\\n\\t\\t\\t\\t\\tif (layerData) {\\n\\t\\t\\t\\t\\t\\tlayerData.destroy();\\n\\t\\t\\t\\t\\t\\tcameraData.layersMap.delete(layer);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttempLayersToRemove.length = 0;\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tlet gsplatCount = 0;\\n\\t\\tlet bufferCopyUploaded = 0;\\n\\t\\tlet bufferCopyTotal = 0;\\n\\t\\tconst camerasComponents = comp.cameras;\\n\\t\\tfor (let i = 0; i < camerasComponents.length; i++) {\\n\\t\\t\\tconst camera = camerasComponents[i].camera;\\n\\t\\t\\tlet cameraData = this.camerasMap.get(camera);\\n\\t\\t\\tconst layerIds = camera.layers;\\n\\t\\t\\tfor (let j = 0; j < layerIds.length; j++) {\\n\\t\\t\\t\\tconst layer = comp.getLayerById(layerIds[j]);\\n\\t\\t\\t\\tif (layer?.enabled) {\\n\\t\\t\\t\\t\\tif (layer.gsplatPlacementsDirty || !cameraData) {\\n\\t\\t\\t\\t\\t\\tconst hasNormalPlacements = layer.gsplatPlacements.length > 0;\\n\\t\\t\\t\\t\\t\\tconst hasShadowCasters = layer.gsplatShadowCasters.length > 0;\\n\\t\\t\\t\\t\\t\\tif (!hasNormalPlacements && !hasShadowCasters) {\\n\\t\\t\\t\\t\\t\\t\\tif (cameraData) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcameraData.removeLayerData(layer);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tcameraData ?? (cameraData = this.getCameraData(camera));\\n\\t\\t\\t\\t\\t\\t\\tconst layerData = cameraData.getLayerData(this.device, this, layer, camera);\\n\\t\\t\\t\\t\\t\\t\\tlayerData.updateConfiguration(this.device, this, layer, camera);\\n\\t\\t\\t\\t\\t\\t\\tif (layerData.gsplatManager) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlayerData.gsplatManager.reconcile(layer.gsplatPlacements);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\tif (layerData.gsplatManagerShadow) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlayerData.gsplatManagerShadow.reconcile(layer.gsplatShadowCasters);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (cameraData) {\\n\\t\\t\\t\\tfor (const layerData of cameraData.layersMap.values()) {\\n\\t\\t\\t\\t\\tif (layerData.gsplatManager) {\\n\\t\\t\\t\\t\\t\\tgsplatCount += layerData.gsplatManager.update();\\n\\t\\t\\t\\t\\t\\tbufferCopyUploaded += layerData.gsplatManager.bufferCopyUploaded;\\n\\t\\t\\t\\t\\t\\tbufferCopyTotal += layerData.gsplatManager.bufferCopyTotal;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (layerData.gsplatManagerShadow) {\\n\\t\\t\\t\\t\\t\\tgsplatCount += layerData.gsplatManagerShadow.update();\\n\\t\\t\\t\\t\\t\\tbufferCopyUploaded += layerData.gsplatManagerShadow.bufferCopyUploaded;\\n\\t\\t\\t\\t\\t\\tbufferCopyTotal += layerData.gsplatManagerShadow.bufferCopyTotal;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.renderer._gsplatCount = gsplatCount;\\n\\t\\tthis.renderer._gsplatBufferCopy = bufferCopyTotal > 0 ? bufferCopyUploaded / bufferCopyTotal * 100 : 0;\\n\\t\\tthis.scene.gsplat.frameEnd();\\n\\t\\tfor (let i = 0; i < comp.layerList.length; i++) {\\n\\t\\t\\tcomp.layerList[i].gsplatPlacementsDirty = false;\\n\\t\\t}\\n\\t}\\n}\\n\\nclass GSplatComponent extends Component {\\n\\t_layers = [LAYERID_WORLD];\\n\\t// assign to the default world layer\\n\\t_instance = null;\\n\\t_placement = null;\\n\\t_id = PickerId.get();\\n\\t_materialTmp = null;\\n\\t_highQualitySH = true;\\n\\t_lodBaseDistance = 5;\\n\\t_lodMultiplier = 3;\\n\\t_customAabb = null;\\n\\t_assetReference;\\n\\t_resource = null;\\n\\t_evtLayersChanged = null;\\n\\t_evtLayerAdded = null;\\n\\t_evtLayerRemoved = null;\\n\\t_castShadows = false;\\n\\t_unified = true;\\n\\t_parameters = /* @__PURE__ */ new Map();\\n\\t_workBufferUpdate = WORKBUFFER_UPDATE_AUTO;\\n\\t_workBufferModifier = null;\\n\\tconstructor(system, entity) {\\n\\t\\tsuper(system, entity);\\n\\t\\tthis._assetReference = new AssetReference(\\n\\t\\t\\t\\\"asset\\\",\\n\\t\\t\\tthis,\\n\\t\\t\\tsystem.app.assets,\\n\\t\\t\\t{\\n\\t\\t\\t\\tadd: this._onGSplatAssetAdded,\\n\\t\\t\\t\\tload: this._onGSplatAssetLoad,\\n\\t\\t\\t\\tremove: this._onGSplatAssetRemove,\\n\\t\\t\\t\\tunload: this._onGSplatAssetUnload\\n\\t\\t\\t},\\n\\t\\t\\tthis\\n\\t\\t);\\n\\t\\tentity.on(\\\"remove\\\", this.onRemoveChild, this);\\n\\t\\tentity.on(\\\"removehierarchy\\\", this.onRemoveChild, this);\\n\\t\\tentity.on(\\\"insert\\\", this.onInsertChild, this);\\n\\t\\tentity.on(\\\"inserthierarchy\\\", this.onInsertChild, this);\\n\\t}\\n\\tset customAabb(value) {\\n\\t\\tthis._customAabb = value;\\n\\t\\tthis._instance?.meshInstance?.setCustomAabb(this._customAabb);\\n\\t\\tif (this._placement) {\\n\\t\\t\\tthis._placement.aabb = this._customAabb;\\n\\t\\t}\\n\\t}\\n\\tget customAabb() {\\n\\t\\treturn this._customAabb ?? this._placement?.aabb ?? this.resource?.aabb ?? null;\\n\\t}\\n\\tset instance(value) {\\n\\t\\tif (this.unified) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.destroyInstance();\\n\\t\\tthis._instance = value;\\n\\t\\tif (this._instance) {\\n\\t\\t\\tconst mi = this._instance.meshInstance;\\n\\t\\t\\tif (!mi.node) {\\n\\t\\t\\t\\tmi.node = this.entity;\\n\\t\\t\\t}\\n\\t\\t\\tmi.castShadow = this._castShadows;\\n\\t\\t\\tmi.setCustomAabb(this._customAabb);\\n\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\tthis.addToLayers();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget instance() {\\n\\t\\tif (this.unified) ;\\n\\t\\treturn this._instance;\\n\\t}\\n\\tset material(value) {\\n\\t\\tif (this.unified) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._instance) {\\n\\t\\t\\tthis._instance.material = value;\\n\\t\\t} else {\\n\\t\\t\\tthis._materialTmp = value;\\n\\t\\t}\\n\\t}\\n\\tget material() {\\n\\t\\tif (this.unified) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\treturn this._instance?.material ?? this._materialTmp ?? null;\\n\\t}\\n\\tset highQualitySH(value) {\\n\\t\\tif (value !== this._highQualitySH) {\\n\\t\\t\\tthis._highQualitySH = value;\\n\\t\\t\\tthis._instance?.setHighQualitySH(value);\\n\\t\\t}\\n\\t}\\n\\tget highQualitySH() {\\n\\t\\treturn this._highQualitySH;\\n\\t}\\n\\tset castShadows(value) {\\n\\t\\tif (this._castShadows !== value) {\\n\\t\\t\\tconst layers = this.layers;\\n\\t\\t\\tconst scene = this.system.app.scene;\\n\\t\\t\\tif (this._placement) {\\n\\t\\t\\t\\tif (value) {\\n\\t\\t\\t\\t\\tfor (let i = 0; i < layers.length; i++) {\\n\\t\\t\\t\\t\\t\\tconst layer = scene.layers.getLayerById(layers[i]);\\n\\t\\t\\t\\t\\t\\tlayer?.addGSplatShadowCaster(this._placement);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tfor (let i = 0; i < layers.length; i++) {\\n\\t\\t\\t\\t\\t\\tconst layer = scene.layers.getLayerById(layers[i]);\\n\\t\\t\\t\\t\\t\\tlayer?.removeGSplatShadowCaster(this._placement);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tconst mi = this._instance?.meshInstance;\\n\\t\\t\\tif (mi) {\\n\\t\\t\\t\\tif (this._castShadows && !value) {\\n\\t\\t\\t\\t\\tfor (let i = 0; i < layers.length; i++) {\\n\\t\\t\\t\\t\\t\\tconst layer = scene.layers.getLayerById(this.layers[i]);\\n\\t\\t\\t\\t\\t\\tlayer?.removeShadowCasters([mi]);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tmi.castShadow = value;\\n\\t\\t\\t\\tif (!this._castShadows && value) {\\n\\t\\t\\t\\t\\tfor (let i = 0; i < layers.length; i++) {\\n\\t\\t\\t\\t\\t\\tconst layer = scene.layers.getLayerById(layers[i]);\\n\\t\\t\\t\\t\\t\\tlayer?.addShadowCasters([mi]);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tthis._castShadows = value;\\n\\t\\t}\\n\\t}\\n\\tget castShadows() {\\n\\t\\treturn this._castShadows;\\n\\t}\\n\\tset lodBaseDistance(value) {\\n\\t\\tthis._lodBaseDistance = Math.max(0.1, value);\\n\\t\\tif (this._placement) {\\n\\t\\t\\tthis._placement.lodBaseDistance = this._lodBaseDistance;\\n\\t\\t}\\n\\t}\\n\\tget lodBaseDistance() {\\n\\t\\treturn this._lodBaseDistance;\\n\\t}\\n\\tset lodMultiplier(value) {\\n\\t\\tthis._lodMultiplier = Math.max(1.2, value);\\n\\t\\tif (this._placement) {\\n\\t\\t\\tthis._placement.lodMultiplier = this._lodMultiplier;\\n\\t\\t}\\n\\t}\\n\\tget lodMultiplier() {\\n\\t\\treturn this._lodMultiplier;\\n\\t}\\n\\tset lodDistances(value) {\\n\\t\\tif (Array.isArray(value) && value.length > 0) {\\n\\t\\t\\tthis.lodBaseDistance = value[0];\\n\\t\\t\\tthis.lodMultiplier = 3;\\n\\t\\t}\\n\\t}\\n\\tget lodDistances() {\\n\\t\\treturn [];\\n\\t}\\n\\tset splatBudget(value) {\\n\\t}\\n\\tget splatBudget() {\\n\\t\\treturn 0;\\n\\t}\\n\\tset unified(value) {\\n\\t\\tif (this._unified !== value) {\\n\\t\\t\\tthis._unified = value;\\n\\t\\t\\tthis._onGSplatAssetAdded();\\n\\t\\t}\\n\\t}\\n\\tget unified() {\\n\\t\\treturn this._unified;\\n\\t}\\n\\tget id() {\\n\\t\\treturn this._id;\\n\\t}\\n\\tset workBufferUpdate(value) {\\n\\t\\tthis._workBufferUpdate = value;\\n\\t\\tif (this._placement) {\\n\\t\\t\\tthis._placement.workBufferUpdate = value;\\n\\t\\t}\\n\\t}\\n\\tget workBufferUpdate() {\\n\\t\\treturn this._workBufferUpdate;\\n\\t}\\n\\tsetWorkBufferModifier(value) {\\n\\t\\tif (value) {\\n\\t\\t\\tconst device = this.system.app.graphicsDevice;\\n\\t\\t\\tconst code = (device.isWebGPU ? value.wgsl : value.glsl) ?? null;\\n\\t\\t\\tthis._workBufferModifier = code ? { code, hash: hashCode(code) } : null;\\n\\t\\t} else {\\n\\t\\t\\tthis._workBufferModifier = null;\\n\\t\\t}\\n\\t\\tif (this._placement) {\\n\\t\\t\\tthis._placement.workBufferModifier = this._workBufferModifier;\\n\\t\\t}\\n\\t}\\n\\tset layers(value) {\\n\\t\\tthis.removeFromLayers();\\n\\t\\tthis._layers.length = 0;\\n\\t\\tfor (let i = 0; i < value.length; i++) {\\n\\t\\t\\tthis._layers[i] = value[i];\\n\\t\\t}\\n\\t\\tif (!this.enabled || !this.entity.enabled) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.addToLayers();\\n\\t}\\n\\tget layers() {\\n\\t\\treturn this._layers;\\n\\t}\\n\\tset asset(value) {\\n\\t\\tconst id = value instanceof Asset ? value.id : value;\\n\\t\\tif (this._assetReference.id === id) return;\\n\\t\\tif (this._assetReference.asset && this._assetReference.asset.resource) {\\n\\t\\t\\tthis._onGSplatAssetRemove();\\n\\t\\t}\\n\\t\\tthis._assetReference.id = id;\\n\\t\\tif (this._assetReference.asset) {\\n\\t\\t\\tthis._onGSplatAssetAdded();\\n\\t\\t}\\n\\t}\\n\\tget asset() {\\n\\t\\treturn this._assetReference.id;\\n\\t}\\n\\tset resource(value) {\\n\\t\\tif (this._resource === value) return;\\n\\t\\tif (this._resource || this._assetReference.asset?.resource) {\\n\\t\\t\\tthis._onGSplatAssetRemove();\\n\\t\\t}\\n\\t\\tif (value && this._assetReference.id) {\\n\\t\\t\\tthis._assetReference.id = null;\\n\\t\\t}\\n\\t\\tthis._resource = value;\\n\\t\\tif (this._resource && this.enabled && this.entity.enabled) {\\n\\t\\t\\tthis._onGSplatAssetLoad();\\n\\t\\t}\\n\\t}\\n\\tget resource() {\\n\\t\\treturn this._resource ?? this._assetReference.asset?.resource ?? null;\\n\\t}\\n\\tdestroyInstance() {\\n\\t\\tif (this._placement) {\\n\\t\\t\\tthis.removeFromLayers();\\n\\t\\t\\tthis._placement.destroy();\\n\\t\\t\\tthis._placement = null;\\n\\t\\t}\\n\\t\\tif (this._instance) {\\n\\t\\t\\tthis.removeFromLayers();\\n\\t\\t\\tthis._instance?.destroy();\\n\\t\\t\\tthis._instance = null;\\n\\t\\t}\\n\\t}\\n\\taddToLayers() {\\n\\t\\tif (this._placement) {\\n\\t\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\t\\tfor (let i = 0; i < this._layers.length; i++) {\\n\\t\\t\\t\\tconst layer = layers.getLayerById(this._layers[i]);\\n\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\tlayer.addGSplatPlacement(this._placement);\\n\\t\\t\\t\\t\\tif (this._castShadows) {\\n\\t\\t\\t\\t\\t\\tlayer.addGSplatShadowCaster(this._placement);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst meshInstance = this._instance?.meshInstance;\\n\\t\\tif (meshInstance) {\\n\\t\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\t\\tfor (let i = 0; i < this._layers.length; i++) {\\n\\t\\t\\t\\tlayers.getLayerById(this._layers[i])?.addMeshInstances([meshInstance]);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tremoveFromLayers() {\\n\\t\\tif (this._placement) {\\n\\t\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\t\\tfor (let i = 0; i < this._layers.length; i++) {\\n\\t\\t\\t\\tconst layer = layers.getLayerById(this._layers[i]);\\n\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\tlayer.removeGSplatPlacement(this._placement);\\n\\t\\t\\t\\t\\tlayer.removeGSplatShadowCaster(this._placement);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst meshInstance = this._instance?.meshInstance;\\n\\t\\tif (meshInstance) {\\n\\t\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\t\\tfor (let i = 0; i < this._layers.length; i++) {\\n\\t\\t\\t\\tlayers.getLayerById(this._layers[i])?.removeMeshInstances([meshInstance]);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tonRemoveChild() {\\n\\t\\tthis.removeFromLayers();\\n\\t}\\n\\tonInsertChild() {\\n\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\tif (this._instance || this._placement) {\\n\\t\\t\\t\\tthis.addToLayers();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tonRemove() {\\n\\t\\tthis.destroyInstance();\\n\\t\\tthis.asset = null;\\n\\t\\tthis._assetReference.id = null;\\n\\t\\tthis.entity.off(\\\"remove\\\", this.onRemoveChild, this);\\n\\t\\tthis.entity.off(\\\"insert\\\", this.onInsertChild, this);\\n\\t}\\n\\tonLayersChanged(oldComp, newComp) {\\n\\t\\tthis.addToLayers();\\n\\t\\toldComp.off(\\\"add\\\", this.onLayerAdded, this);\\n\\t\\toldComp.off(\\\"remove\\\", this.onLayerRemoved, this);\\n\\t\\tnewComp.on(\\\"add\\\", this.onLayerAdded, this);\\n\\t\\tnewComp.on(\\\"remove\\\", this.onLayerRemoved, this);\\n\\t}\\n\\tonLayerAdded(layer) {\\n\\t\\tconst index = this.layers.indexOf(layer.id);\\n\\t\\tif (index < 0) return;\\n\\t\\tif (this.unified) return;\\n\\t\\tif (this._instance) {\\n\\t\\t\\tlayer.addMeshInstances(this._instance.meshInstance);\\n\\t\\t}\\n\\t}\\n\\tonLayerRemoved(layer) {\\n\\t\\tconst index = this.layers.indexOf(layer.id);\\n\\t\\tif (index < 0) return;\\n\\t\\tif (this.unified) return;\\n\\t\\tif (this._instance) {\\n\\t\\t\\tlayer.removeMeshInstances(this._instance.meshInstance);\\n\\t\\t}\\n\\t}\\n\\tonEnable() {\\n\\t\\tconst scene = this.system.app.scene;\\n\\t\\tconst layers = scene.layers;\\n\\t\\tthis._evtLayersChanged = scene.on(\\\"set:layers\\\", this.onLayersChanged, this);\\n\\t\\tif (layers) {\\n\\t\\t\\tthis._evtLayerAdded = layers.on(\\\"add\\\", this.onLayerAdded, this);\\n\\t\\t\\tthis._evtLayerRemoved = layers.on(\\\"remove\\\", this.onLayerRemoved, this);\\n\\t\\t}\\n\\t\\tif (this._instance || this._placement) {\\n\\t\\t\\tthis.addToLayers();\\n\\t\\t} else if (this.asset) {\\n\\t\\t\\tthis._onGSplatAssetAdded();\\n\\t\\t} else if (this._resource) {\\n\\t\\t\\tthis._onGSplatAssetLoad();\\n\\t\\t}\\n\\t}\\n\\tonDisable() {\\n\\t\\tconst scene = this.system.app.scene;\\n\\t\\tconst layers = scene.layers;\\n\\t\\tthis._evtLayersChanged?.off();\\n\\t\\tthis._evtLayersChanged = null;\\n\\t\\tif (layers) {\\n\\t\\t\\tthis._evtLayerAdded?.off();\\n\\t\\t\\tthis._evtLayerAdded = null;\\n\\t\\t\\tthis._evtLayerRemoved?.off();\\n\\t\\t\\tthis._evtLayerRemoved = null;\\n\\t\\t}\\n\\t\\tthis.removeFromLayers();\\n\\t}\\n\\thide() {\\n\\t\\tif (this._instance) {\\n\\t\\t\\tthis._instance.meshInstance.visible = false;\\n\\t\\t}\\n\\t}\\n\\tshow() {\\n\\t\\tif (this._instance) {\\n\\t\\t\\tthis._instance.meshInstance.visible = true;\\n\\t\\t}\\n\\t}\\n\\tsetParameter(name, data) {\\n\\t\\tconst scopeId = this.system.app.graphicsDevice.scope.resolve(name);\\n\\t\\tthis._parameters.set(name, { scopeId, data });\\n\\t\\tif (this._placement) this._placement.renderDirty = true;\\n\\t}\\n\\tgetParameter(name) {\\n\\t\\treturn this._parameters.get(name)?.data;\\n\\t}\\n\\tdeleteParameter(name) {\\n\\t\\tthis._parameters.delete(name);\\n\\t\\tif (this._placement) this._placement.renderDirty = true;\\n\\t}\\n\\tgetInstanceTexture(name) {\\n\\t\\tif (!this._placement) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\treturn this._placement.getInstanceTexture(name, this.system.app.graphicsDevice) ?? null;\\n\\t}\\n\\t_onGSplatAssetAdded() {\\n\\t\\tif (!this._assetReference.asset) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._assetReference.asset.resource) {\\n\\t\\t\\tthis._onGSplatAssetLoad();\\n\\t\\t} else if (this.enabled && this.entity.enabled) {\\n\\t\\t\\tthis.system.app.assets.load(this._assetReference.asset);\\n\\t\\t}\\n\\t}\\n\\t_onGSplatAssetLoad() {\\n\\t\\tthis.destroyInstance();\\n\\t\\tconst resource = this._resource ?? this._assetReference.asset?.resource;\\n\\t\\tif (!resource) return;\\n\\t\\tif (this.unified) {\\n\\t\\t\\tthis._placement = null;\\n\\t\\t\\tthis._placement = new GSplatPlacement(resource, this.entity, 0, this._parameters, null, this._id);\\n\\t\\t\\tthis._placement.lodBaseDistance = this._lodBaseDistance;\\n\\t\\t\\tthis._placement.lodMultiplier = this._lodMultiplier;\\n\\t\\t\\tthis._placement.workBufferUpdate = this._workBufferUpdate;\\n\\t\\t\\tthis._placement.workBufferModifier = this._workBufferModifier;\\n\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\tthis.addToLayers();\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis.instance = new GSplatInstance(resource, {\\n\\t\\t\\t\\tmaterial: this._materialTmp,\\n\\t\\t\\t\\thighQualitySH: this._highQualitySH,\\n\\t\\t\\t\\tscene: this.system.app.scene\\n\\t\\t\\t});\\n\\t\\t\\tthis._materialTmp = null;\\n\\t\\t}\\n\\t}\\n\\t_onGSplatAssetUnload() {\\n\\t\\tthis.destroyInstance();\\n\\t}\\n\\t_onGSplatAssetRemove() {\\n\\t\\tthis._onGSplatAssetUnload();\\n\\t}\\n}\\n\\nclass GSplatComponentData {\\n\\tenabled = true;\\n}\\n\\nvar gsplatCenter_default$1 = `\\nuniform mat4 matrix_model;\\nuniform mat4 matrix_view;\\n#ifndef GSPLAT_CENTER_NOPROJ\\n\\tuniform vec4 camera_params;\\n\\tuniform mat4 matrix_projection;\\n\\t#ifdef GSPLAT_FISHEYE\\n\\t\\tuniform float fisheye_k;\\n\\t\\tuniform float fisheye_inv_k;\\n\\t\\tuniform float fisheye_projMat00;\\n\\t\\tuniform float fisheye_projMat11;\\n\\t#endif\\n#endif\\nbool initCenter(vec3 modelCenter, inout SplatCenter center) {\\n\\tmat4 modelView = matrix_view * matrix_model;\\n\\tvec4 centerView = modelView * vec4(modelCenter, 1.0);\\n\\t#ifndef GSPLAT_CENTER_NOPROJ\\n\\t\\t#ifdef GSPLAT_FISHEYE\\n\\t\\t\\tvec3 v = centerView.xyz;\\n\\t\\t\\tfloat r_xy = length(v.xy);\\n\\t\\t\\tfloat neg_z = -v.z;\\n\\t\\t\\tfloat theta = atan(r_xy, neg_z);\\n\\t\\t\\tfloat maxTheta = min(fisheye_k * 1.5707963, 3.13);\\n\\t\\t\\tif (theta > maxTheta - 0.01 || dot(v, v) < 0.0001) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t\\t}\\n\\t\\t\\tfloat tk = theta * fisheye_inv_k;\\n\\t\\t\\tfloat sin_tk = sin(tk);\\n\\t\\t\\tfloat cos_tk = cos(tk);\\n\\t\\t\\tfloat g_theta = fisheye_k * sin_tk / cos_tk;\\n\\t\\t\\tfloat fisheye_s = (r_xy > 1e-4) ? g_theta / r_xy : (neg_z > 0.0 ? 1.0 / neg_z : 0.0);\\n\\t\\t\\tvec2 ndc = vec2(fisheye_projMat00 * fisheye_s * v.x, fisheye_projMat11 * fisheye_s * v.y);\\n\\t\\t\\tfloat near = camera_params.z;\\n\\t\\t\\tfloat far = camera_params.y;\\n\\t\\t\\tfloat linearDepth = neg_z;\\n\\t\\t\\t#if WEBGPU\\n\\t\\t\\t\\tfloat depthNdc = clamp((linearDepth - near) / (far - near), 0.0, 1.0);\\n\\t\\t\\t#else\\n\\t\\t\\t\\tfloat depthNdc = clamp(2.0 * (linearDepth - near) / (far - near) - 1.0, -1.0, 1.0);\\n\\t\\t\\t#endif\\n\\t\\t\\tcenter.proj = vec4(ndc, depthNdc, 1.0);\\n\\t\\t\\tcenter.projMat00 = fisheye_projMat00;\\n\\t\\t\\tcenter.fisheyeSinTK = sin_tk;\\n\\t\\t\\tcenter.fisheyeCosTK = cos_tk;\\n\\t\\t\\tcenter.fisheyeRxy = r_xy;\\n\\t\\t#else\\n\\t\\t\\tif (camera_params.w != 1.0 && centerView.z > 0.0) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t\\t}\\n\\t\\t\\tvec4 centerProj = matrix_projection * centerView;\\n\\t\\t\\t#if WEBGPU\\n\\t\\t\\t\\tcenterProj.z = clamp(centerProj.z, 0, abs(centerProj.w));\\n\\t\\t\\t#else\\n\\t\\t\\t\\tcenterProj.z = clamp(centerProj.z, -abs(centerProj.w), abs(centerProj.w));\\n\\t\\t\\t#endif\\n\\t\\t\\tcenter.proj = centerProj;\\n\\t\\t\\tcenter.projMat00 = matrix_projection[0][0];\\n\\t\\t#endif\\n\\t#endif\\n\\tcenter.view = centerView.xyz / centerView.w;\\n\\tcenter.modelView = modelView;\\n\\treturn true;\\n}\\n`;\\n\\nvar gsplatCommon_default$1 = `\\n#include \\\"gsplatHelpersVS\\\"\\n#include \\\"gsplatFormatVS\\\"\\n#include \\\"gsplatStructsVS\\\"\\n#include \\\"gsplatDeclarationsVS\\\"\\n#include \\\"gsplatModifyVS\\\"\\n#include \\\"gsplatEvalSHVS\\\"\\n#include \\\"gsplatQuatToMat3VS\\\"\\n#include \\\"gsplatReadVS\\\"\\n#include \\\"gsplatSourceVS\\\"\\n#include \\\"gsplatCenterVS\\\"\\n#include \\\"gsplatCornerVS\\\"\\n#include \\\"gsplatOutputVS\\\"\\n#if defined(SHADOW_PASS) || defined(PICK_PASS) || defined(PREPASS_PASS)\\nuniform float alphaClip;\\n#else\\nuniform float alphaClipForward;\\n#endif\\nvoid clipCorner(inout SplatCorner corner, float alpha) {\\n\\t#if defined(SHADOW_PASS) || defined(PICK_PASS) || defined(PREPASS_PASS)\\n\\t\\tfloat alphaClipValue = alphaClip;\\n\\t#else\\n\\t\\tfloat alphaClipValue = alphaClipForward;\\n\\t#endif\\n\\tfloat clip = min(1.0, sqrt(max(0.0, log(alpha / alphaClipValue))) * 0.5);\\n\\tcorner.offset *= clip;\\n\\tcorner.uv *= clip;\\n}\\n`;\\n\\nvar gsplatSplat_default$1 = `\\nstruct Splat {\\n\\tuint index;\\n\\tivec2 uv;\\n};\\nSplat splat;\\nvoid setSplat(uint idx) {\\n\\tsplat.index = idx;\\n\\tsplat.uv = ivec2(idx % splatTextureSize, idx / splatTextureSize);\\n}\\n`;\\n\\nvar gsplatEvalSH_default$1 = `\\n\\t#if SH_BANDS == 1\\n\\t\\t#define SH_COEFFS 3\\n\\t#elif SH_BANDS == 2\\n\\t\\t#define SH_COEFFS 8\\n\\t#elif SH_BANDS == 3\\n\\t\\t#define SH_COEFFS 15\\n\\t#else\\n\\t\\t#define SH_COEFFS 0\\n\\t#endif\\n\\t#if SH_BANDS > 0\\n\\tconst float SH_C1 = 0.4886025119029199f;\\n\\t#if SH_BANDS > 1\\n\\t\\tconst float SH_C2_0 = 1.0925484305920792f;\\n\\t\\tconst float SH_C2_1 = -1.0925484305920792f;\\n\\t\\tconst float SH_C2_2 = 0.31539156525252005f;\\n\\t\\tconst float SH_C2_3 = -1.0925484305920792f;\\n\\t\\tconst float SH_C2_4 = 0.5462742152960396f;\\n\\t#endif\\n\\t#if SH_BANDS > 2\\n\\t\\tconst float SH_C3_0 = -0.5900435899266435f;\\n\\t\\tconst float SH_C3_1 = 2.890611442640554f;\\n\\t\\tconst float SH_C3_2 = -0.4570457994644658f;\\n\\t\\tconst float SH_C3_3 = 0.3731763325901154f;\\n\\t\\tconst float SH_C3_4 = -0.4570457994644658f;\\n\\t\\tconst float SH_C3_5 = 1.445305721320277f;\\n\\t\\tconst float SH_C3_6 = -0.5900435899266435f;\\n\\t#endif\\n\\tvec3 evalSH(in vec3 sh[SH_COEFFS], in vec3 dir) {\\n\\t\\tfloat x = dir.x;\\n\\t\\tfloat y = dir.y;\\n\\t\\tfloat z = dir.z;\\n\\t\\tvec3 result = SH_C1 * (-sh[0] * y + sh[1] * z - sh[2] * x);\\n\\t\\t#if SH_BANDS > 1\\n\\t\\t\\tfloat xx = x * x;\\n\\t\\t\\tfloat yy = y * y;\\n\\t\\t\\tfloat zz = z * z;\\n\\t\\t\\tfloat xy = x * y;\\n\\t\\t\\tfloat yz = y * z;\\n\\t\\t\\tfloat xz = x * z;\\n\\t\\t\\tresult +=\\n\\t\\t\\t\\tsh[3] * (SH_C2_0 * xy) +\\n\\t\\t\\t\\tsh[4] * (SH_C2_1 * yz) +\\n\\t\\t\\t\\tsh[5] * (SH_C2_2 * (2.0 * zz - xx - yy)) +\\n\\t\\t\\t\\tsh[6] * (SH_C2_3 * xz) +\\n\\t\\t\\t\\tsh[7] * (SH_C2_4 * (xx - yy));\\n\\t\\t#endif\\n\\t\\t#if SH_BANDS > 2\\n\\t\\t\\tresult +=\\n\\t\\t\\t\\tsh[8]  * (SH_C3_0 * y * (3.0 * xx - yy)) +\\n\\t\\t\\t\\tsh[9]  * (SH_C3_1 * xy * z) +\\n\\t\\t\\t\\tsh[10] * (SH_C3_2 * y * (4.0 * zz - xx - yy)) +\\n\\t\\t\\t\\tsh[11] * (SH_C3_3 * z * (2.0 * zz - 3.0 * xx - 3.0 * yy)) +\\n\\t\\t\\t\\tsh[12] * (SH_C3_4 * x * (4.0 * zz - xx - yy)) +\\n\\t\\t\\t\\tsh[13] * (SH_C3_5 * z * (xx - yy)) +\\n\\t\\t\\t\\tsh[14] * (SH_C3_6 * x * (xx - 3.0 * yy));\\n\\t\\t#endif\\n\\t\\treturn result;\\n\\t}\\n\\t#endif\\n`;\\n\\nvar gsplatHelpers_default$1 = `\\nvoid gsplatMakeSpherical(inout vec3 scale, float size) {\\n\\tscale = vec3(size);\\n}\\nfloat gsplatGetSizeFromScale(vec3 scale) {\\n\\treturn sqrt((scale.x * scale.x + scale.y * scale.y + scale.z * scale.z) / 3.0);\\n}\\n`;\\n\\nvar gsplatModify_default$1 = `\\nvoid modifySplatCenter(inout vec3 center) {\\n}\\nvoid modifySplatRotationScale(vec3 originalCenter, vec3 modifiedCenter, inout vec4 rotation, inout vec3 scale) {\\n}\\nvoid modifySplatColor(vec3 center, inout vec4 color) {\\n}\\n`;\\n\\nvar gsplatQuatToMat3_default$1 = `\\nmat3 quatToMat3(vec4 R) {\\n\\tvec4 R2 = R + R;\\n\\tfloat X = R2.x * R.w;\\n\\tvec4 Y  = R2.y * R;\\n\\tvec4 Z  = R2.z * R;\\n\\tfloat W = R2.w * R.w;\\n\\treturn mat3(\\n\\t\\t1.0 - Z.z - W,\\n\\t\\t\\t  Y.z + X,\\n\\t\\t\\t  Y.w - Z.x,\\n\\t\\t\\t  Y.z - X,\\n\\t\\t1.0 - Y.y - W,\\n\\t\\t\\t  Z.w + Y.x,\\n\\t\\t\\t  Y.w + Z.x,\\n\\t\\t\\t  Z.w - Y.x,\\n\\t\\t1.0 - Y.y - Z.z\\n\\t);\\n}\\nvec4 quatMul(vec4 a, vec4 b) {\\n\\treturn vec4(\\n\\t\\ta.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,\\n\\t\\ta.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x,\\n\\t\\ta.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w,\\n\\t\\ta.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z\\n\\t);\\n}\\n`;\\n\\nvar gsplatStructs_default$1 = `\\n#include \\\"gsplatSplatVS\\\"\\nstruct SplatSource {\\n\\tuint order;\\n\\tvec2 cornerUV;\\n};\\nstruct SplatCenter {\\n\\tvec3 view;\\n\\tvec4 proj;\\n\\tmat4 modelView;\\n\\tfloat projMat00;\\n\\tvec3 modelCenterOriginal;\\n\\tvec3 modelCenterModified;\\n\\t#ifdef GSPLAT_FISHEYE\\n\\t\\tfloat fisheyeSinTK;\\n\\t\\tfloat fisheyeCosTK;\\n\\t\\tfloat fisheyeRxy;\\n\\t#endif\\n};\\nstruct SplatCorner {\\n\\tvec3 offset;\\n\\tvec2 uv;\\n\\t#if GSPLAT_AA\\n\\t\\tfloat aaFactor;\\n\\t#endif\\n\\tvec2 v;\\n\\tfloat dlen;\\n};\\n`;\\n\\nvar gsplatCorner_default$1 = `\\nuniform vec4 viewport_size;\\nuniform float minPixelSize;\\nvoid computeCovariance(vec4 rotation, vec3 scale, out vec3 covA, out vec3 covB) {\\n\\tmat3 rot = quatToMat3(rotation);\\n\\tmat3 M = transpose(mat3(\\n\\t\\tscale.x * rot[0],\\n\\t\\tscale.y * rot[1],\\n\\t\\tscale.z * rot[2]\\n\\t));\\n\\tcovA = vec3(dot(M[0], M[0]), dot(M[0], M[1]), dot(M[0], M[2]));\\n\\tcovB = vec3(dot(M[1], M[1]), dot(M[1], M[2]), dot(M[2], M[2]));\\n}\\nbool initCornerCov(SplatSource source, SplatCenter center, out SplatCorner corner, vec3 covA, vec3 covB) {\\n\\tmat3 Vrk = mat3(\\n\\t\\tcovA.x, covA.y, covA.z, \\n\\t\\tcovA.y, covB.x, covB.y,\\n\\t\\tcovA.z, covB.y, covB.z\\n\\t);\\n\\tfloat focal = viewport_size.x * center.projMat00;\\n\\tvec3 v = center.view.xyz;\\n\\t#ifdef GSPLAT_FISHEYE\\n\\t\\tfloat r_sq = max(center.fisheyeRxy * center.fisheyeRxy, 1e-8);\\n\\t\\tfloat d2 = dot(v, v);\\n\\t\\tfloat neg_z = -v.z;\\n\\t\\tfloat g_prime = 1.0 / (center.fisheyeCosTK * center.fisheyeCosTK);\\n\\t\\tfloat g_theta = fisheye_k * center.fisheyeSinTK / center.fisheyeCosTK;\\n\\t\\tfloat sv = (center.fisheyeRxy > 1e-4) ? g_theta / center.fisheyeRxy : (neg_z > 0.0 ? 1.0 / neg_z : 0.0);\\n\\t\\tfloat K = (center.fisheyeRxy > 1e-4) ? (g_prime * neg_z / d2 - sv) / r_sq : 0.0;\\n\\t\\tmat3 J = mat3(\\n\\t\\t\\tfocal * (sv + K * v.x * v.x),  focal * K * v.x * v.y,\\t\\t focal * g_prime * v.x / d2,\\n\\t\\t\\tfocal * K * v.x * v.y,\\t\\tfocal * (sv + K * v.y * v.y),\\tfocal * g_prime * v.y / d2,\\n\\t\\t\\t0.0,\\t\\t\\t\\t\\t\\t   0.0,\\t\\t\\t\\t\\t\\t\\t0.0\\n\\t\\t);\\n\\t#else\\n\\t\\tvec3 vp = camera_params.w == 1.0 ? vec3(0.0, 0.0, 1.0) : v;\\n\\t\\tfloat J1 = focal / vp.z;\\n\\t\\tvec2 J2 = -J1 / vp.z * vp.xy;\\n\\t\\tmat3 J = mat3(\\n\\t\\t\\tJ1, 0.0, J2.x,\\n\\t\\t\\t0.0, J1, J2.y,\\n\\t\\t\\t0.0, 0.0, 0.0\\n\\t\\t);\\n\\t#endif\\n\\tmat3 W = transpose(mat3(center.modelView));\\n\\tmat3 T = W * J;\\n\\tmat3 cov = transpose(T) * Vrk * T;\\n\\t#if GSPLAT_AA\\n\\t\\tfloat detOrig = cov[0][0] * cov[1][1] - cov[0][1] * cov[0][1];\\n\\t\\tfloat detBlur = (cov[0][0] + 0.3) * (cov[1][1] + 0.3) - cov[0][1] * cov[0][1];\\n\\t\\tcorner.aaFactor = sqrt(max(detOrig / detBlur, 0.0));\\n\\t#endif\\n\\tfloat diagonal1 = cov[0][0] + 0.3;\\n\\tfloat offDiagonal = cov[0][1];\\n\\tfloat diagonal2 = cov[1][1] + 0.3;\\n\\tfloat mid = 0.5 * (diagonal1 + diagonal2);\\n\\tfloat radius = length(vec2((diagonal1 - diagonal2) / 2.0, offDiagonal));\\n\\tfloat lambda1 = mid + radius;\\n\\tfloat lambda2 = max(mid - radius, 0.1);\\n\\tfloat vmin = min(1024.0, min(viewport_size.x, viewport_size.y));\\n\\tfloat l1 = 2.0 * min(sqrt(2.0 * lambda1), vmin);\\n\\tfloat l2 = 2.0 * min(sqrt(2.0 * lambda2), vmin);\\n\\tif (max(l1, l2) < minPixelSize) {\\n\\t\\treturn false;\\n\\t}\\n\\tvec2 c = center.proj.ww * viewport_size.zw;\\n\\tif (any(greaterThan(abs(center.proj.xy) - vec2(max(l1, l2)) * c, center.proj.ww))) {\\n\\t\\treturn false;\\n\\t}\\n\\tvec2 diagonalVector = normalize(vec2(offDiagonal, lambda1 - diagonal1));\\n\\tvec2 v1 = l1 * diagonalVector;\\n\\tvec2 v2 = l2 * vec2(diagonalVector.y, -diagonalVector.x);\\n\\tcorner.offset = vec3((source.cornerUV.x * v1 + source.cornerUV.y * v2) * c, 0.0);\\n\\tcorner.uv = source.cornerUV;\\n\\treturn true;\\n}\\n#if GSPLAT_2DGS\\nvoid initCorner2DGS(SplatSource source, vec4 rotation, vec3 scale, out SplatCorner corner) {\\n\\tvec2 localPos = source.cornerUV * vec2(scale.x, scale.y) * 3.0;\\n\\tvec3 v = vec3(localPos, 0.0);\\n\\tvec3 t = 2.0 * cross(rotation.xyz, v);\\n\\tcorner.offset = v + rotation.w * t + cross(rotation.xyz, t);\\n\\tcorner.uv = source.cornerUV;\\n}\\n#endif\\nbool initCorner(SplatSource source, SplatCenter center, out SplatCorner corner) {\\n\\tvec4 rotation = getRotation().yzwx;\\n\\tvec3 scale = getScale();\\n\\tmodifySplatRotationScale(center.modelCenterOriginal, center.modelCenterModified, rotation, scale);\\n\\t#if GSPLAT_2DGS\\n\\t\\tinitCorner2DGS(source, rotation, scale, corner);\\n\\t\\treturn true;\\n\\t#else\\n\\t\\tvec3 covA, covB;\\n\\t\\tcomputeCovariance(rotation.wxyz, scale, covA, covB);\\n\\t\\treturn initCornerCov(source, center, corner, covA, covB);\\n\\t#endif\\n}\\n`;\\n\\nvar gsplatOutput_default = `\\n#include \\\"tonemappingPS\\\"\\n#include \\\"decodePS\\\"\\n#include \\\"gammaPS\\\"\\n#include \\\"fogPS\\\"\\n#if FOG != NONE && !defined(GSPLAT_NO_FOG)\\n\\t#define GSPLAT_FOG\\n#endif\\nvec3 prepareOutputFromGamma(vec3 gammaColor, float depth) {\\n\\tvec3 color = gammaColor;\\n\\t#if TONEMAP != NONE || GAMMA == NONE || defined(GSPLAT_FOG)\\n\\t\\tcolor = decodeGamma(color);\\n\\t#endif\\n\\t#ifdef GSPLAT_FOG\\n\\t\\tcolor = addFog(color, depth);\\n\\t#endif\\n\\t#if TONEMAP != NONE\\n\\t\\tcolor = toneMap(color);\\n\\t#endif\\n\\t#if TONEMAP != NONE || (GAMMA != NONE && defined(GSPLAT_FOG))\\n\\t\\tcolor = gammaCorrectOutput(color);\\n\\t#endif\\n\\treturn color;\\n}\\n`;\\n\\nvar gsplat_default$3 = `\\n#ifndef DITHER_NONE\\n\\t#include \\\"bayerPS\\\"\\n\\t#include \\\"opacityDitherPS\\\"\\n\\tvarying float id;\\n#endif\\n#if defined(SHADOW_PASS) || defined(PICK_PASS) || defined(PREPASS_PASS)\\n\\tuniform float alphaClip;\\n#endif\\n#ifdef PREPASS_PASS\\n\\tvarying float vLinearDepth;\\n\\t#include \\\"floatAsUintPS\\\"\\n#endif\\n#if !defined(SHADOW_PASS) && !defined(PICK_PASS) && !defined(PREPASS_PASS)\\n\\tuniform float alphaClipForward;\\n#endif\\nvarying mediump vec2 gaussianUV;\\nvarying mediump vec4 gaussianColor;\\n#if defined(GSPLAT_UNIFIED_ID) && defined(PICK_PASS)\\n\\tflat varying uint vPickId;\\n#endif\\n#ifdef PICK_PASS\\n\\t#include \\\"pickPS\\\"\\n#endif\\nconst float EXP4 = exp(-4.0);\\nconst float INV_EXP4 = 1.0 / (1.0 - EXP4);\\nfloat normExp(float x) {\\n\\treturn (exp(x * -4.0) - EXP4) * INV_EXP4;\\n}\\nvoid main(void) {\\n\\tmediump float A = dot(gaussianUV, gaussianUV);\\n\\tif (A > 1.0) {\\n\\t\\tdiscard;\\n\\t}\\n\\tmediump float alpha = normExp(A) * gaussianColor.a;\\n\\t#if defined(SHADOW_PASS) || defined(PICK_PASS) || defined(PREPASS_PASS)\\n\\t\\tif (alpha < alphaClip) {\\n\\t\\t\\tdiscard;\\n\\t\\t}\\n\\t#endif\\n\\t#ifdef PICK_PASS\\n\\t\\t#ifdef GSPLAT_UNIFIED_ID\\n\\t\\t\\tpcFragColor0 = encodePickOutput(vPickId);\\n\\t\\t#else\\n\\t\\t\\tpcFragColor0 = getPickOutput();\\n\\t\\t#endif\\n\\t\\t#ifdef DEPTH_PICK_PASS\\n\\t\\t\\tpcFragColor1 = getPickDepth();\\n\\t\\t#endif\\n\\t#elif SHADOW_PASS\\n\\t\\tgl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\\n\\t#elif PREPASS_PASS\\n\\t\\tgl_FragColor = float2vec4(vLinearDepth);\\n\\t#else\\n\\t\\tif (alpha < alphaClipForward) {\\n\\t\\t\\tdiscard;\\n\\t\\t}\\n\\t\\t#ifndef DITHER_NONE\\n\\t\\t\\topacityDither(alpha, id * 0.013);\\n\\t\\t#endif\\n\\t\\tgl_FragColor = vec4(gaussianColor.xyz * alpha, alpha);\\n\\t#endif\\n}\\n`;\\n\\nvar gsplatSource_default$1 = `\\nattribute vec3 vertex_position;\\nuniform uint numSplats;\\nuniform highp usampler2D splatOrder;\\nbool initSource(out SplatSource source) {\\n\\tsource.order = uint(gl_InstanceID) * {GSPLAT_INSTANCE_SIZE}u + uint(vertex_position.z);\\n\\tif (source.order >= numSplats) {\\n\\t\\treturn false;\\n\\t}\\n\\tivec2 orderUV = ivec2(source.order % splatTextureSize, source.order / splatTextureSize);\\n\\tuint splatId = texelFetch(splatOrder, orderUV, 0).r;\\n\\tsetSplat(splatId);\\n\\tsource.cornerUV = vertex_position.xy;\\n\\treturn true;\\n}\\n`;\\n\\nvar gsplat_default$2 = `\\n#include \\\"gsplatCommonVS\\\"\\nvarying mediump vec2 gaussianUV;\\nvarying mediump vec4 gaussianColor;\\n#ifndef DITHER_NONE\\n\\tvarying float id;\\n#endif\\nmediump vec4 discardVec = vec4(0.0, 0.0, 2.0, 1.0);\\n#ifdef PREPASS_PASS\\n\\tvarying float vLinearDepth;\\n#endif\\n#if defined(GSPLAT_UNIFIED_ID) && defined(PICK_PASS)\\n\\tflat varying uint vPickId;\\n#endif\\n#ifdef GSPLAT_OVERDRAW\\n\\tuniform sampler2D colorRamp;\\n\\tuniform float colorRampIntensity;\\n#endif\\nvoid main(void) {\\n\\tSplatSource source;\\n\\tif (!initSource(source)) {\\n\\t\\tgl_Position = discardVec;\\n\\t\\treturn;\\n\\t}\\n\\tvec3 modelCenter = getCenter();\\n\\tSplatCenter center;\\n\\tcenter.modelCenterOriginal = modelCenter;\\n\\t\\n\\tmodifySplatCenter(modelCenter);\\n\\tcenter.modelCenterModified = modelCenter;\\n\\tif (!initCenter(modelCenter, center)) {\\n\\t\\tgl_Position = discardVec;\\n\\t\\treturn;\\n\\t}\\n\\tSplatCorner corner;\\n\\tif (!initCorner(source, center, corner)) {\\n\\t\\tgl_Position = discardVec;\\n\\t\\treturn;\\n\\t}\\n\\t#ifdef GSPLAT_SEPARATE_OPACITY\\n\\t\\tfloat opacity = getOpacity();\\n\\t\\tvec4 clr = vec4(getColor(), opacity);\\n\\t#else\\n\\t\\tvec4 clr = getColor();\\n\\t#endif\\n\\t#if GSPLAT_AA\\n\\t\\tclr.a *= corner.aaFactor;\\n\\t#endif\\n\\t#if SH_BANDS > 0\\n\\t\\tvec3 dir = normalize(center.view * mat3(center.modelView));\\n\\t\\tvec3 sh[SH_COEFFS];\\n\\t\\tfloat scale;\\n\\t\\treadSHData(sh, scale);\\n\\t\\tclr.xyz += evalSH(sh, dir) * scale;\\n\\t#endif\\n\\tmodifySplatColor(modelCenter, clr);\\n\\t#if defined(SHADOW_PASS) || defined(PICK_PASS) || defined(PREPASS_PASS)\\n\\t\\tfloat alphaClipValue = alphaClip;\\n\\t#else\\n\\t\\tfloat alphaClipValue = alphaClipForward;\\n\\t#endif\\n\\tif (clr.w <= alphaClipValue) {\\n\\t\\tgl_Position = discardVec;\\n\\t\\treturn;\\n\\t}\\n\\tclipCorner(corner, clr.w);\\n\\t#if GSPLAT_2DGS\\n\\t\\tvec3 modelCorner = center.modelCenterModified + corner.offset;\\n\\t\\tgl_Position = matrix_projection * center.modelView * vec4(modelCorner, 1.0);\\n\\t#else\\n\\t\\tgl_Position = center.proj + vec4(corner.offset.xyz, 0);\\n\\t#endif\\n\\tgaussianUV = corner.uv;\\n\\t#ifdef GSPLAT_OVERDRAW\\n\\t\\tfloat t = clamp(modelCenter.y / 20.0, 0.0, 1.0);\\n\\t\\tvec3 rampColor = textureLod(colorRamp, vec2(t, 0.5), 0.0).rgb;\\n\\t\\tclr.a *= (1.0 / 32.0) * colorRampIntensity;\\n\\t\\tgaussianColor = vec4(rampColor, clr.a);\\n\\t#else\\n\\t\\tgaussianColor = vec4(prepareOutputFromGamma(max(clr.xyz, 0.0), -center.view.z), clr.w);\\n\\t#endif\\n\\t#ifndef DITHER_NONE\\n\\t\\tid = float(splat.index);\\n\\t#endif\\n\\t#ifdef PREPASS_PASS\\n\\t\\tvLinearDepth = -center.view.z;\\n\\t#endif\\n\\t#if defined(GSPLAT_UNIFIED_ID) && defined(PICK_PASS)\\n\\t\\tvPickId = loadPcId().r;\\n\\t#endif\\n}\\n`;\\n\\nvar gsplatPacking_default$1 = `\\nuint pack8888(vec4 v) {\\n\\tuvec4 t = uvec4(v * 255.0) << uvec4(24u, 16u, 8u, 0u);\\n\\treturn t.x | t.y | t.z | t.w;\\n}\\nuint pack101010(vec3 v) {\\n\\tuvec3 t = uvec3(v * 1023.0) << uvec3(20u, 10u, 0u);\\n\\treturn t.x | t.y | t.z;\\n}\\nuint pack111110(vec3 v) {\\n\\tuvec3 t = uvec3(v * vec3(2047.0, 2047.0, 1023.0)) << uvec3(21u, 10u, 0u);\\n\\treturn t.x | t.y | t.z;\\n}\\nvec4 unpack8888(uint v) {\\n\\treturn vec4((uvec4(v) >> uvec4(24u, 16u, 8u, 0u)) & 0xffu) / 255.0;\\n}\\nvec3 unpack101010(uint v) {\\n\\treturn vec3((uvec3(v) >> uvec3(20u, 10u, 0u)) & 0x3ffu) / 1023.0;\\n}\\nvec3 unpack111110(uint v) {\\n\\treturn vec3((uvec3(v) >> uvec3(21u, 10u, 0u)) & uvec3(0x7ffu, 0x7ffu, 0x3ffu)) / vec3(2047.0, 2047.0, 1023.0);\\n}\\nvec3 resolveCodebook(vec3 s, vec4 codebook[64]) {\\n\\tuvec3 idx = uvec3(s * 255.0);\\n\\tvec3 v = vec3(\\n\\t\\tcodebook[idx.x >> 2u][idx.x & 3u],\\n\\t\\tcodebook[idx.y >> 2u][idx.y & 3u],\\n\\t\\tcodebook[idx.z >> 2u][idx.z & 3u]\\n\\t);\\n\\treturn (v - codebook[0].x) / (codebook[63].w - codebook[0].x);\\n}\\n`;\\n\\nvar gsplatFormat_default$1 = `\\nuniform uint splatTextureSize;\\n`;\\n\\nvar uncompressed_default$1 = `\\nuint tAw;\\nvec4 tBcached;\\nvec4 unpackRotation(vec3 data) {\\n\\treturn vec4(data.xyz, sqrt(max(0.0, 1.0 - dot(data, data))));\\n}\\nvec3 getCenter() {\\n\\tuvec4 tA = loadTransformA();\\n\\ttAw = tA.w;\\n\\ttBcached = loadTransformB();\\n\\treturn uintBitsToFloat(tA.xyz);\\n}\\nvec4 getColor() {\\n\\treturn loadSplatColor();\\n}\\nvec4 getRotation() {\\n\\treturn unpackRotation(vec3(unpackHalf2x16(tAw), tBcached.w)).wxyz;\\n}\\nvec3 getScale() {\\n\\treturn tBcached.xyz;\\n}\\n#include \\\"gsplatUncompressedSHVS\\\"\\n`;\\n\\nvar uncompressedSH_default$1 = `\\n#if SH_BANDS > 0\\nvec3 unpack111011s(uint bits) {\\n\\treturn vec3((uvec3(bits) >> uvec3(21u, 11u, 0u)) & uvec3(0x7ffu, 0x3ffu, 0x7ffu)) / vec3(2047.0, 1023.0, 2047.0) * 2.0 - 1.0;\\n}\\nvoid fetchScale(in uvec4 t, out float scale, out vec3 a, out vec3 b, out vec3 c) {\\n\\tscale = uintBitsToFloat(t.x);\\n\\ta = unpack111011s(t.y);\\n\\tb = unpack111011s(t.z);\\n\\tc = unpack111011s(t.w);\\n}\\nvoid fetch(in uvec4 t, out vec3 a, out vec3 b, out vec3 c, out vec3 d) {\\n\\ta = unpack111011s(t.x);\\n\\tb = unpack111011s(t.y);\\n\\tc = unpack111011s(t.z);\\n\\td = unpack111011s(t.w);\\n}\\nvoid fetch(in uint t, out vec3 a) {\\n\\ta = unpack111011s(t);\\n}\\n#if SH_BANDS == 1\\n\\tvoid readSHData(out vec3 sh[3], out float scale) {\\n\\t\\tfetchScale(loadSplatSH_1to3(), scale, sh[0], sh[1], sh[2]);\\n\\t}\\n#elif SH_BANDS == 2\\n\\tvoid readSHData(out vec3 sh[8], out float scale) {\\n\\t\\tfetchScale(loadSplatSH_1to3(), scale, sh[0], sh[1], sh[2]);\\n\\t\\tfetch(loadSplatSH_4to7(), sh[3], sh[4], sh[5], sh[6]);\\n\\t\\tfetch(loadSplatSH_8to11().x, sh[7]);\\n\\t}\\n#else\\n\\tvoid readSHData(out vec3 sh[15], out float scale) {\\n\\t\\tfetchScale(loadSplatSH_1to3(), scale, sh[0], sh[1], sh[2]);\\n\\t\\tfetch(loadSplatSH_4to7(), sh[3], sh[4], sh[5], sh[6]);\\n\\t\\tfetch(loadSplatSH_8to11(), sh[7], sh[8], sh[9], sh[10]);\\n\\t\\tfetch(loadSplatSH_12to15(), sh[11], sh[12], sh[13], sh[14]);\\n\\t}\\n#endif\\n#endif\\n`;\\n\\nvar compressed_default$1 = `\\n#include \\\"gsplatPackingPS\\\"\\nuniform highp sampler2D chunkTexture;\\nvec4 chunkDataA;\\nvec4 chunkDataB;\\nvec4 chunkDataC;\\nvec4 chunkDataD;\\nvec4 chunkDataE;\\nuvec4 packedData;\\nvec3 unpack111011(uint bits) {\\n\\treturn vec3(\\n\\t\\tfloat(bits >> 21u) / 2047.0,\\n\\t\\tfloat((bits >> 11u) & 0x3ffu) / 1023.0,\\n\\t\\tfloat(bits & 0x7ffu) / 2047.0\\n\\t);\\n}\\nconst float norm = sqrt(2.0);\\nvec4 unpackRotation(uint bits) {\\n\\tfloat a = (float((bits >> 20u) & 0x3ffu) / 1023.0 - 0.5) * norm;\\n\\tfloat b = (float((bits >> 10u) & 0x3ffu) / 1023.0 - 0.5) * norm;\\n\\tfloat c = (float(bits & 0x3ffu) / 1023.0 - 0.5) * norm;\\n\\tfloat m = sqrt(1.0 - (a * a + b * b + c * c));\\n\\tuint mode = bits >> 30u;\\n\\tif (mode == 0u) return vec4(m, a, b, c);\\n\\tif (mode == 1u) return vec4(a, m, b, c);\\n\\tif (mode == 2u) return vec4(a, b, m, c);\\n\\treturn vec4(a, b, c, m);\\n}\\nvec3 getCenter() {\\n\\tuint w = uint(textureSize(chunkTexture, 0).x) / 5u;\\n\\tuint chunkId = splat.index / 256u;\\n\\tivec2 chunkUV = ivec2((chunkId % w) * 5u, chunkId / w);\\n\\tchunkDataA = texelFetch(chunkTexture, chunkUV, 0);\\n\\tchunkDataB = texelFetch(chunkTexture, chunkUV + ivec2(1, 0), 0);\\n\\tchunkDataC = texelFetch(chunkTexture, chunkUV + ivec2(2, 0), 0);\\n\\tchunkDataD = texelFetch(chunkTexture, chunkUV + ivec2(3, 0), 0);\\n\\tchunkDataE = texelFetch(chunkTexture, chunkUV + ivec2(4, 0), 0);\\n\\tpackedData = loadPackedTexture();\\n\\treturn mix(chunkDataA.xyz, vec3(chunkDataA.w, chunkDataB.xy), unpack111011(packedData.x));\\n}\\nvec4 getColor() {\\n\\tvec4 r = unpack8888(packedData.w);\\n\\treturn vec4(mix(chunkDataD.xyz, vec3(chunkDataD.w, chunkDataE.xy), r.rgb), r.w);\\n}\\nvec4 getRotation() {\\n\\treturn unpackRotation(packedData.y);\\n}\\nvec3 getScale() {\\n\\treturn exp(mix(vec3(chunkDataB.zw, chunkDataC.x), chunkDataC.yzw, unpack111011(packedData.z)));\\n}\\n#include \\\"gsplatCompressedSHVS\\\"\\n`;\\n\\nvar compressedSH_default$1 = `\\n#if SH_BANDS > 0\\nvec4 unpack8888s(in uint bits) {\\n\\treturn vec4((uvec4(bits) >> uvec4(0u, 8u, 16u, 24u)) & 0xffu) * (8.0 / 255.0) - 4.0;\\n}\\nvoid readSHData(out vec3 sh[15], out float scale) {\\n\\tuvec4 shData0 = loadShTexture0();\\n\\tuvec4 shData1 = loadShTexture1();\\n\\tuvec4 shData2 = loadShTexture2();\\n\\tvec4 r0 = unpack8888s(shData0.x);\\n\\tvec4 r1 = unpack8888s(shData0.y);\\n\\tvec4 r2 = unpack8888s(shData0.z);\\n\\tvec4 r3 = unpack8888s(shData0.w);\\n\\tvec4 g0 = unpack8888s(shData1.x);\\n\\tvec4 g1 = unpack8888s(shData1.y);\\n\\tvec4 g2 = unpack8888s(shData1.z);\\n\\tvec4 g3 = unpack8888s(shData1.w);\\n\\tvec4 b0 = unpack8888s(shData2.x);\\n\\tvec4 b1 = unpack8888s(shData2.y);\\n\\tvec4 b2 = unpack8888s(shData2.z);\\n\\tvec4 b3 = unpack8888s(shData2.w);\\n\\tsh[0] =  vec3(r0.x, g0.x, b0.x);\\n\\tsh[1] =  vec3(r0.y, g0.y, b0.y);\\n\\tsh[2] =  vec3(r0.z, g0.z, b0.z);\\n\\tsh[3] =  vec3(r0.w, g0.w, b0.w);\\n\\tsh[4] =  vec3(r1.x, g1.x, b1.x);\\n\\tsh[5] =  vec3(r1.y, g1.y, b1.y);\\n\\tsh[6] =  vec3(r1.z, g1.z, b1.z);\\n\\tsh[7] =  vec3(r1.w, g1.w, b1.w);\\n\\tsh[8] =  vec3(r2.x, g2.x, b2.x);\\n\\tsh[9] =  vec3(r2.y, g2.y, b2.y);\\n\\tsh[10] = vec3(r2.z, g2.z, b2.z);\\n\\tsh[11] = vec3(r2.w, g2.w, b2.w);\\n\\tsh[12] = vec3(r3.x, g3.x, b3.x);\\n\\tsh[13] = vec3(r3.y, g3.y, b3.y);\\n\\tsh[14] = vec3(r3.z, g3.z, b3.z);\\n\\tscale = 1.0;\\n}\\n#endif\\n`;\\n\\nvar sog_default$1 = `\\nuniform vec3 means_mins;\\nuniform vec3 means_maxs;\\n#ifndef SOG_V2\\n\\tuniform vec3 scales_mins;\\n\\tuniform vec3 scales_maxs;\\n\\tuniform vec4 sh0_mins;\\n\\tuniform vec4 sh0_maxs;\\n#endif\\nconst float SH_C0 = 0.28209479177387814;\\nconst float norm = sqrt(2.0);\\n#ifdef SOG_V2\\n\\tfloat lutScales(int b) { return texelFetch(sogCodebook, ivec2(b, 0), 0).r; }\\n\\tfloat lutSh0(int b)\\t{ return texelFetch(sogCodebook, ivec2(b, 0), 0).g; }\\n\\tfloat lutShN(int b)\\t{ return texelFetch(sogCodebook, ivec2(b, 0), 0).b; }\\n#endif\\nvec3 getCenter() {\\n\\tvec3 l = texelFetch(means_l, splat.uv, 0).xyz;\\n\\tvec3 u = texelFetch(means_u, splat.uv, 0).xyz;\\n\\tvec3 n = (l + u * 256.0) / 257.0;\\n\\tvec3 v = mix(means_mins, means_maxs, n);\\n\\treturn sign(v) * (exp(abs(v)) - 1.0);\\n}\\nvec4 getRotation() {\\n\\tvec4 q = texelFetch(quats, splat.uv, 0);\\n\\tuint qmode = uint(q.w * 255.0 + 0.5) - 252u;\\n\\tvec3 abc = (q.xyz - 0.5) * norm;\\n\\tfloat d = sqrt(max(0.0, 1.0 - dot(abc, abc)));\\n\\treturn (qmode == 0u) ? vec4(d, abc) :\\n\\t\\t   ((qmode == 1u) ? vec4(abc.x, d, abc.yz) :\\n\\t\\t   ((qmode == 2u) ? vec4(abc.xy, d, abc.z) : vec4(abc, d)));\\n}\\nvec3 getScale() {\\n\\tvec3 s = texelFetch(scales, splat.uv, 0).xyz;\\n\\t#ifdef SOG_V2\\n\\t\\tivec3 i = ivec3(s * 255.0 + 0.5);\\n\\t\\tvec3 logS = vec3(lutScales(i.x), lutScales(i.y), lutScales(i.z));\\n\\t#else\\n\\t\\tvec3 logS = mix(scales_mins, scales_maxs, s);\\n\\t#endif\\n\\treturn exp(logS);\\n}\\nvec4 getColor() {\\n\\tvec4 c = texelFetch(sh0, splat.uv, 0);\\n\\t#ifdef SOG_V2\\n\\t\\tivec3 i = ivec3(c.xyz * 255.0 + 0.5);\\n\\t\\tvec3 rgb = vec3(lutSh0(i.x), lutSh0(i.y), lutSh0(i.z));\\n\\t\\tfloat alpha = c.w;\\n\\t#else\\n\\t\\tvec3 rgb = mix(sh0_mins.xyz, sh0_maxs.xyz, c.xyz);\\n\\t\\tfloat logitAlpha = mix(sh0_mins.w, sh0_maxs.w, c.w);\\n\\t\\tfloat alpha = 1.0 / (1.0 + exp(-logitAlpha));\\n\\t#endif\\n\\treturn vec4(vec3(0.5) + rgb * SH_C0, alpha);\\n}\\n#include \\\"gsplatSogSHVS\\\"\\n`;\\n\\nvar sogSH_default$1 = `\\n#if SH_BANDS > 0\\n\\t#ifndef SOG_V2\\n\\t\\tuniform float shN_mins;\\n\\t\\tuniform float shN_maxs;\\n\\t#endif\\n\\tvoid readSHData(out vec3 sh[SH_COEFFS], out float scale) {\\n\\t\\tvec4 labels = texelFetch(sh_labels, splat.uv, 0);\\n\\t\\tint n = int(labels.x * 255.0 + 0.5) + int(labels.y * 255.0 + 0.5) * 256;\\n\\t\\tint u = (n % 64) * SH_COEFFS;\\n\\t\\tint v = n / 64;\\n\\t\\tfor (int i = 0; i < SH_COEFFS; i++) {\\n\\t\\t\\tvec4 t = texelFetch(sh_centroids, ivec2(u + i, v), 0);\\n\\t\\t\\t#ifdef SOG_V2\\n\\t\\t\\t\\tivec3 idx = ivec3(t.xyz * 255.0 + 0.5);\\n\\t\\t\\t\\tsh[i] = vec3(lutShN(idx.x), lutShN(idx.y), lutShN(idx.z));\\n\\t\\t\\t#else\\n\\t\\t\\t\\tsh[i] = mix(vec3(shN_mins), vec3(shN_maxs), t.xyz);\\n\\t\\t\\t#endif\\n\\t\\t}\\n\\t\\tscale = 1.0;\\n\\t}\\n#endif\\n`;\\n\\nvar containerDecl_default$1 = `\\n#include \\\"gsplatContainerDeclarationsVS\\\"\\nvec3 splatCenter;\\nvec4 splatColor;\\nvec3 splatScale;\\nvec4 splatRotation;\\n`;\\n\\nvar containerRead_default$1 = `\\nvec3 getCenter() {\\n\\t#include \\\"gsplatContainerUserReadVS\\\"\\n\\treturn splatCenter;\\n}\\nvec4 getRotation() {\\n\\treturn splatRotation;\\n}\\nvec3 getScale() {\\n\\treturn splatScale;\\n}\\nvec4 getColor() {\\n\\treturn splatColor;\\n}\\n`;\\n\\nconst gsplatChunksGLSL = {\\n\\tgsplatCenterVS: gsplatCenter_default$1,\\n\\tgsplatCornerVS: gsplatCorner_default$1,\\n\\tgsplatCommonVS: gsplatCommon_default$1,\\n\\tgsplatSplatVS: gsplatSplat_default$1,\\n\\tgsplatEvalSHVS: gsplatEvalSH_default$1,\\n\\tgsplatHelpersVS: gsplatHelpers_default$1,\\n\\tgsplatModifyVS: gsplatModify_default$1,\\n\\tgsplatQuatToMat3VS: gsplatQuatToMat3_default$1,\\n\\tgsplatStructsVS: gsplatStructs_default$1,\\n\\tgsplatOutputVS: gsplatOutput_default,\\n\\tgsplatPS: gsplat_default$3,\\n\\tgsplatSourceVS: gsplatSource_default$1,\\n\\tgsplatVS: gsplat_default$2,\\n\\tgsplatPackingPS: gsplatPacking_default$1,\\n\\tgsplatFormatVS: gsplatFormat_default$1,\\n\\tgsplatUncompressedVS: uncompressed_default$1,\\n\\tgsplatUncompressedSHVS: uncompressedSH_default$1,\\n\\tgsplatCompressedVS: compressed_default$1,\\n\\tgsplatCompressedSHVS: compressedSH_default$1,\\n\\tgsplatSogVS: sog_default$1,\\n\\tgsplatSogSHVS: sogSH_default$1,\\n\\tgsplatContainerDeclVS: containerDecl_default$1,\\n\\tgsplatContainerReadVS: containerRead_default$1,\\n\\tgsplatContainerFloatReadVS: containerFloatRead_default$1\\n};\\n\\nvar gsplatCenter_default = `\\nuniform matrix_model: mat4x4f;\\nuniform matrix_view: mat4x4f;\\n#ifndef GSPLAT_CENTER_NOPROJ\\n\\tuniform camera_params: vec4f;\\n\\tuniform matrix_projection: mat4x4f;\\n\\t#ifdef GSPLAT_FISHEYE\\n\\t\\tuniform fisheye_k: f32;\\n\\t\\tuniform fisheye_inv_k: f32;\\n\\t\\tuniform fisheye_projMat00: f32;\\n\\t\\tuniform fisheye_projMat11: f32;\\n\\t#endif\\n#endif\\nfn initCenter(modelCenter: vec3f, center: ptr<function, SplatCenter>) -> bool {\\n\\tlet modelView: mat4x4f = uniform.matrix_view * uniform.matrix_model;\\n\\tlet centerView: vec4f = modelView * vec4f(modelCenter, 1.0);\\n\\t#ifndef GSPLAT_CENTER_NOPROJ\\n\\t\\t#ifdef GSPLAT_FISHEYE\\n\\t\\t\\tlet v: vec3f = centerView.xyz;\\n\\t\\t\\tlet r_xy: f32 = length(v.xy);\\n\\t\\t\\tlet neg_z: f32 = -v.z;\\n\\t\\t\\tlet theta: f32 = atan2(r_xy, neg_z);\\n\\t\\t\\tlet maxTheta: f32 = min(uniform.fisheye_k * 1.5707963, 3.13);\\n\\t\\t\\tif (theta > maxTheta - 0.01 || dot(v, v) < 0.0001) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t\\t}\\n\\t\\t\\tlet tk: f32 = theta * uniform.fisheye_inv_k;\\n\\t\\t\\tlet sin_tk: f32 = sin(tk);\\n\\t\\t\\tlet cos_tk: f32 = cos(tk);\\n\\t\\t\\tlet g_theta: f32 = uniform.fisheye_k * sin_tk / cos_tk;\\n\\t\\t\\tlet fisheye_s: f32 = select(select(0.0, 1.0 / neg_z, neg_z > 0.0), g_theta / r_xy, r_xy > 1e-4);\\n\\t\\t\\tlet ndc: vec2f = vec2f(uniform.fisheye_projMat00 * fisheye_s * v.x, uniform.fisheye_projMat11 * fisheye_s * v.y);\\n\\t\\t\\tlet near: f32 = uniform.camera_params.z;\\n\\t\\t\\tlet far: f32 = uniform.camera_params.y;\\n\\t\\t\\tlet linearDepth: f32 = neg_z;\\n\\t\\t\\tlet depthNdc: f32 = clamp((linearDepth - near) / (far - near), 0.0, 1.0);\\n\\t\\t\\tcenter.proj = vec4f(ndc, depthNdc, 1.0);\\n\\t\\t\\tcenter.projMat00 = uniform.fisheye_projMat00;\\n\\t\\t\\tcenter.fisheyeSinTK = sin_tk;\\n\\t\\t\\tcenter.fisheyeCosTK = cos_tk;\\n\\t\\t\\tcenter.fisheyeRxy = r_xy;\\n\\t\\t#else\\n\\t\\t\\tif (uniform.camera_params.w != 1.0 && centerView.z > 0.0) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t\\t}\\n\\t\\t\\tvar centerProj: vec4f = uniform.matrix_projection * centerView;\\n\\t\\t\\tcenterProj.z = clamp(centerProj.z, 0.0, abs(centerProj.w));\\n\\t\\t\\tcenter.proj = centerProj;\\n\\t\\t\\tcenter.projMat00 = uniform.matrix_projection[0][0];\\n\\t\\t#endif\\n\\t#endif\\n\\tcenter.view = centerView.xyz / centerView.w;\\n\\tcenter.modelView = modelView;\\n\\treturn true;\\n}\\n`;\\n\\nvar gsplatCommon_default = `\\n#include \\\"gsplatHelpersVS\\\"\\n#include \\\"gsplatFormatVS\\\"\\n#include \\\"gsplatStructsVS\\\"\\n#include \\\"gsplatDeclarationsVS\\\"\\n#include \\\"gsplatModifyVS\\\"\\n#include \\\"gsplatEvalSHVS\\\"\\n#include \\\"gsplatQuatToMat3VS\\\"\\n#include \\\"gsplatReadVS\\\"\\n#include \\\"gsplatSourceVS\\\"\\n#include \\\"gsplatCenterVS\\\"\\n#include \\\"gsplatCornerVS\\\"\\n#include \\\"gsplatOutputVS\\\"\\n#if defined(SHADOW_PASS) || defined(PICK_PASS) || defined(PREPASS_PASS)\\nuniform alphaClip: f32;\\n#else\\nuniform alphaClipForward: f32;\\n#endif\\nfn clipCorner(corner: ptr<function, SplatCorner>, alpha: half) {\\n\\t#if defined(SHADOW_PASS) || defined(PICK_PASS) || defined(PREPASS_PASS)\\n\\t\\tlet alphaClipValue = half(uniform.alphaClip);\\n\\t#else\\n\\t\\tlet alphaClipValue = half(uniform.alphaClipForward);\\n\\t#endif\\n\\tlet clip = min(half(1.0), sqrt(max(half(0.0), log(alpha / alphaClipValue))) * half(0.5));\\n\\tcorner.offset = corner.offset * f32(clip);\\n\\tcorner.uv = corner.uv * clip;\\n}\\n`;\\n\\nvar gsplatSplat_default = `\\nstruct Splat {\\n\\tindex: u32,\\n\\tuv: vec2i\\n}\\nvar<private> splat: Splat;\\nfn setSplat(idx: u32) {\\n\\tsplat.index = idx;\\n\\tsplat.uv = vec2i(i32(idx % uniform.splatTextureSize), i32(idx / uniform.splatTextureSize));\\n}\\n`;\\n\\nvar gsplatEvalSH_default = `\\n\\t#if SH_BANDS == 1\\n\\t\\tconst SH_COEFFS: i32 = 3;\\n\\t#elif SH_BANDS == 2\\n\\t\\tconst SH_COEFFS: i32 = 8;\\n\\t#elif SH_BANDS == 3\\n\\t\\tconst SH_COEFFS: i32 = 15;\\n\\t#else\\n\\t\\tconst SH_COEFFS: i32 = 0;\\n\\t#endif\\n\\t#if SH_BANDS > 0\\n\\tconst SH_C1: half = half(0.4886025119029199);\\n\\t#if SH_BANDS > 1\\n\\t\\tconst SH_C2_0: half = half(1.0925484305920792);\\n\\t\\tconst SH_C2_1: half = half(-1.0925484305920792);\\n\\t\\tconst SH_C2_2: half = half(0.31539156525252005);\\n\\t\\tconst SH_C2_3: half = half(-1.0925484305920792);\\n\\t\\tconst SH_C2_4: half = half(0.5462742152960396);\\n\\t#endif\\n\\t#if SH_BANDS > 2\\n\\t\\tconst SH_C3_0: half = half(-0.5900435899266435);\\n\\t\\tconst SH_C3_1: half = half(2.890611442640554);\\n\\t\\tconst SH_C3_2: half = half(-0.4570457994644658);\\n\\t\\tconst SH_C3_3: half = half(0.3731763325901154);\\n\\t\\tconst SH_C3_4: half = half(-0.4570457994644658);\\n\\t\\tconst SH_C3_5: half = half(1.445305721320277);\\n\\t\\tconst SH_C3_6: half = half(-0.5900435899266435);\\n\\t#endif\\n\\tfn evalSH(sh: ptr<function, array<half3, SH_COEFFS>>, dir: vec3f) -> half3 {\\n\\t\\tlet d: half3 = half3(dir);\\n\\t\\tvar result: half3 = SH_C1 * (-sh[0] * d.y + sh[1] * d.z - sh[2] * d.x);\\n\\t\\t#if SH_BANDS > 1\\n\\t\\t\\tlet xx: half = d.x * d.x;\\n\\t\\t\\tlet yy: half = d.y * d.y;\\n\\t\\t\\tlet zz: half = d.z * d.z;\\n\\t\\t\\tlet xy: half = d.x * d.y;\\n\\t\\t\\tlet yz: half = d.y * d.z;\\n\\t\\t\\tlet xz: half = d.x * d.z;\\n\\t\\t\\tresult = result + (\\n\\t\\t\\t\\tsh[3] * (SH_C2_0 * xy) +\\n\\t\\t\\t\\tsh[4] * (SH_C2_1 * yz) +\\n\\t\\t\\t\\tsh[5] * (SH_C2_2 * (half(2.0) * zz - xx - yy)) +\\n\\t\\t\\t\\tsh[6] * (SH_C2_3 * xz) +\\n\\t\\t\\t\\tsh[7] * (SH_C2_4 * (xx - yy))\\n\\t\\t\\t);\\n\\t\\t#endif\\n\\t\\t#if SH_BANDS > 2\\n\\t\\t\\tresult = result + (\\n\\t\\t\\t\\tsh[8]  * (SH_C3_0 * d.y * (half(3.0) * xx - yy)) +\\n\\t\\t\\t\\tsh[9]  * (SH_C3_1 * xy * d.z) +\\n\\t\\t\\t\\tsh[10] * (SH_C3_2 * d.y * (half(4.0) * zz - xx - yy)) +\\n\\t\\t\\t\\tsh[11] * (SH_C3_3 * d.z * (half(2.0) * zz - half(3.0) * xx - half(3.0) * yy)) +\\n\\t\\t\\t\\tsh[12] * (SH_C3_4 * d.x * (half(4.0) * zz - xx - yy)) +\\n\\t\\t\\t\\tsh[13] * (SH_C3_5 * d.z * (xx - yy)) +\\n\\t\\t\\t\\tsh[14] * (SH_C3_6 * d.x * (xx - half(3.0) * yy))\\n\\t\\t\\t);\\n\\t\\t#endif\\n\\t\\treturn result;\\n\\t}\\n\\t#endif\\n`;\\n\\nvar gsplatHelpers_default = `\\nfn gsplatMakeSpherical(scale: ptr<function, vec3f>, size: f32) {\\n\\t*scale = vec3f(size);\\n}\\nfn gsplatGetSizeFromScale(scale: vec3f) -> f32 {\\n\\treturn sqrt((scale.x * scale.x + scale.y * scale.y + scale.z * scale.z) / 3.0);\\n}\\n`;\\n\\nvar gsplatModify_default = `\\nfn modifySplatCenter(center: ptr<function, vec3f>) {\\n}\\nfn modifySplatRotationScale(originalCenter: vec3f, modifiedCenter: vec3f, rotation: ptr<function, vec4f>, scale: ptr<function, vec3f>) {\\n}\\nfn modifySplatColor(center: vec3f, color: ptr<function, vec4f>) {\\n}\\n`;\\n\\nvar gsplatQuatToMat3_default = `\\nfn quatToMat3(r: half4) -> half3x3 {\\n\\tlet r2: half4 = r + r;\\n\\tlet x: half   = r2.x * r.w;\\n\\tlet y: half4  = r2.y * r;\\n\\tlet z: half4  = r2.z * r;\\n\\tlet w: half   = r2.w * r.w;\\n\\treturn half3x3(\\n\\t\\thalf(1.0) - z.z - w,  y.z + x,\\t\\t\\t  y.w - z.x,\\n\\t\\ty.z - x,\\t\\t\\t  half(1.0) - y.y - w,   z.w + y.x,\\n\\t\\ty.w + z.x,\\t\\t\\tz.w - y.x,\\t\\t\\t half(1.0) - y.y - z.z\\n\\t);\\n}\\nfn quatMul(a: half4, b: half4) -> half4 {\\n\\treturn half4(\\n\\t\\ta.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,\\n\\t\\ta.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x,\\n\\t\\ta.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w,\\n\\t\\ta.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z\\n\\t);\\n}\\n`;\\n\\nvar gsplatStructs_default = `\\n#include \\\"gsplatSplatVS\\\"\\nstruct SplatSource {\\n\\torder: u32,\\n\\tcornerUV: half2\\n}\\nstruct SplatCenter {\\n\\tview: vec3f,\\n\\tproj: vec4f,\\n\\tmodelView: mat4x4f,\\n\\tprojMat00: f32,\\n\\tmodelCenterOriginal: vec3f,\\n\\tmodelCenterModified: vec3f,\\n\\t#ifdef GSPLAT_FISHEYE\\n\\t\\tfisheyeSinTK: f32,\\n\\t\\tfisheyeCosTK: f32,\\n\\t\\tfisheyeRxy: f32,\\n\\t#endif\\n}\\nstruct SplatCorner {\\n\\toffset: vec3f,\\n\\tuv: half2,\\n\\t#if GSPLAT_AA\\n\\t\\taaFactor: half,\\n\\t#endif\\n}\\n`;\\n\\nvar gsplatCorner_default = `\\nuniform viewport_size: vec4f;\\nuniform minPixelSize: f32;\\nfn computeCovariance(rotation: half4, scale: half3, covA_ptr: ptr<function, vec3f>, covB_ptr: ptr<function, vec3f>) {\\n\\tlet rot: half3x3 = quatToMat3(rotation);\\n\\tlet s: vec3f = vec3f(scale);\\n\\tlet M: mat3x3f = transpose(mat3x3f(\\n\\t\\ts.x * vec3f(rot[0]),\\n\\t\\ts.y * vec3f(rot[1]),\\n\\t\\ts.z * vec3f(rot[2])\\n\\t));\\n\\t*covA_ptr = vec3f(dot(M[0], M[0]), dot(M[0], M[1]), dot(M[0], M[2]));\\n\\t*covB_ptr = vec3f(dot(M[1], M[1]), dot(M[1], M[2]), dot(M[2], M[2]));\\n}\\nfn initCornerCov(source: ptr<function, SplatSource>, center: ptr<function, SplatCenter>, corner: ptr<function, SplatCorner>, covA: vec3f, covB: vec3f) -> bool {\\n\\tlet Vrk = mat3x3f(\\n\\t\\tvec3f(covA.x, covA.y, covA.z),\\n\\t\\tvec3f(covA.y, covB.x, covB.y),\\n\\t\\tvec3f(covA.z, covB.y, covB.z)\\n\\t);\\n\\tlet focal = uniform.viewport_size.x * center.projMat00;\\n\\tlet v = center.view.xyz;\\n\\t#ifdef GSPLAT_FISHEYE\\n\\t\\tlet r_sq = max(center.fisheyeRxy * center.fisheyeRxy, 1e-8);\\n\\t\\tlet d2 = dot(v, v);\\n\\t\\tlet neg_z = -v.z;\\n\\t\\tlet g_prime = 1.0 / (center.fisheyeCosTK * center.fisheyeCosTK);\\n\\t\\tlet g_theta = uniform.fisheye_k * center.fisheyeSinTK / center.fisheyeCosTK;\\n\\t\\tlet sv = select(select(0.0, 1.0 / neg_z, neg_z > 0.0), g_theta / center.fisheyeRxy, center.fisheyeRxy > 1e-4);\\n\\t\\tlet K = select(0.0, (g_prime * neg_z / d2 - sv) / r_sq, center.fisheyeRxy > 1e-4);\\n\\t\\tlet J = mat3x3f(\\n\\t\\t\\tvec3f(focal * (sv + K * v.x * v.x),  focal * K * v.x * v.y,\\t   focal * g_prime * v.x / d2),\\n\\t\\t\\tvec3f(focal * K * v.x * v.y,\\t\\t focal * (sv + K * v.y * v.y), focal * g_prime * v.y / d2),\\n\\t\\t\\tvec3f(0.0, 0.0, 0.0)\\n\\t\\t);\\n\\t#else\\n\\t\\tlet vp = select(center.view.xyz, vec3f(0.0, 0.0, 1.0), uniform.camera_params.w == 1.0);\\n\\t\\tlet J1 = focal / vp.z;\\n\\t\\tlet J2 = -J1 / vp.z * vp.xy;\\n\\t\\tlet J = mat3x3f(\\n\\t\\t\\tvec3f(J1, 0.0, J2.x),\\n\\t\\t\\tvec3f(0.0, J1, J2.y),\\n\\t\\t\\tvec3f(0.0, 0.0, 0.0)\\n\\t\\t);\\n\\t#endif\\n\\tlet W = transpose(mat3x3f(center.modelView[0].xyz, center.modelView[1].xyz, center.modelView[2].xyz));\\n\\tlet T = W * J;\\n\\tlet cov = transpose(T) * Vrk * T;\\n\\t#if GSPLAT_AA\\n\\t\\tlet detOrig = cov[0][0] * cov[1][1] - cov[0][1] * cov[1][0];\\n\\t\\tlet detBlur = (cov[0][0] + 0.3) * (cov[1][1] + 0.3) - cov[0][1] * cov[1][0];\\n\\t\\tcorner.aaFactor = half(sqrt(max(detOrig / detBlur, 0.0)));\\n\\t#endif\\n\\tlet diagonal1 = cov[0][0] + 0.3;\\n\\tlet offDiagonal = cov[0][1];\\n\\tlet diagonal2 = cov[1][1] + 0.3;\\n\\tlet mid = 0.5 * (diagonal1 + diagonal2);\\n\\tlet radius = length(vec2f((diagonal1 - diagonal2) / 2.0, offDiagonal));\\n\\tlet lambda1 = mid + radius;\\n\\tlet lambda2 = max(mid - radius, 0.1);\\n\\tlet vmin = min(1024.0, min(uniform.viewport_size.x, uniform.viewport_size.y));\\n\\tlet l1 = 2.0 * min(sqrt(2.0 * lambda1), vmin);\\n\\tlet l2 = 2.0 * min(sqrt(2.0 * lambda2), vmin);\\n\\tif (max(l1, l2) < uniform.minPixelSize) {\\n\\t\\treturn false;\\n\\t}\\n\\tlet c = center.proj.ww * uniform.viewport_size.zw;\\n\\tif (any((abs(center.proj.xy) - vec2f(max(l1, l2)) * c) > center.proj.ww)) {\\n\\t\\treturn false;\\n\\t}\\n\\tlet diagonalVector = normalize(vec2f(offDiagonal, lambda1 - diagonal1));\\n\\tlet v1 = l1 * diagonalVector;\\n\\tlet v2 = l2 * vec2f(diagonalVector.y, -diagonalVector.x);\\n\\tcorner.offset = vec3f((f32(source.cornerUV.x) * v1 + f32(source.cornerUV.y) * v2) * c, 0.0);\\n\\tcorner.uv = source.cornerUV;\\n\\treturn true;\\n}\\n#if GSPLAT_2DGS\\nfn initCorner2DGS(source: ptr<function, SplatSource>, rotation: vec4f, scale: vec3f, corner: ptr<function, SplatCorner>) {\\n\\tlet localPos: vec2f = vec2f(source.cornerUV) * vec2f(scale.x, scale.y) * 3.0;\\n\\tlet v: vec3f = vec3f(localPos, 0.0);\\n\\tlet t: vec3f = 2.0 * cross(rotation.xyz, v);\\n\\tcorner.offset = v + rotation.w * t + cross(rotation.xyz, t);\\n\\tcorner.uv = source.cornerUV;\\n}\\n#endif\\nfn initCorner(source: ptr<function, SplatSource>, center: ptr<function, SplatCenter>, corner: ptr<function, SplatCorner>) -> bool {\\n\\tvar rotation: vec4f = getRotation().yzwx;\\n\\tvar scale: vec3f = getScale();\\n\\tmodifySplatRotationScale(center.modelCenterOriginal, center.modelCenterModified, &rotation, &scale);\\n\\t#if GSPLAT_2DGS\\n\\t\\tinitCorner2DGS(source, rotation, scale, corner);\\n\\t\\treturn true;\\n\\t#else\\n\\t\\tvar covA: vec3f;\\n\\t\\tvar covB: vec3f;\\n\\t\\tcomputeCovariance(half4(rotation.wxyz), half3(scale), &covA, &covB);\\n\\t\\treturn initCornerCov(source, center, corner, covA, covB);\\n\\t#endif\\n}\\n`;\\n\\nvar gsplatTileComposite_default$1 = `\\nvarying vUv0: vec2f;\\nvar<storage, read> rasterizeTileList: array<u32>;\\nuniform numTilesX: u32;\\nuniform screenWidth: f32;\\nuniform screenHeight: f32;\\n@vertex\\nfn vertexMain(input: VertexInput) -> VertexOutput {\\n\\tvar output: VertexOutput;\\n\\tlet quadIdx = pcVertexIndex / 6u;\\n\\tlet cornerIdx = pcVertexIndex % 6u;\\n\\tlet tileIdx = rasterizeTileList[quadIdx];\\n\\tlet tileX = tileIdx % uniform.numTilesX;\\n\\tlet tileY = tileIdx / uniform.numTilesX;\\n\\tlet corners = array<vec2f, 6>(\\n\\t\\tvec2f(0.0, 0.0), vec2f(1.0, 0.0), vec2f(1.0, 1.0),\\n\\t\\tvec2f(0.0, 0.0), vec2f(1.0, 1.0), vec2f(0.0, 1.0)\\n\\t);\\n\\tlet corner = corners[cornerIdx];\\n\\tlet x0 = f32(tileX * 16u);\\n\\tlet y0 = f32(tileY * 16u);\\n\\tlet pixelX = x0 + corner.x * 16.0;\\n\\tlet pixelY = y0 + corner.y * 16.0;\\n\\toutput.position = vec4f(\\n\\t\\tpixelX / uniform.screenWidth * 2.0 - 1.0,\\n\\t\\tpixelY / uniform.screenHeight * 2.0 - 1.0,\\n\\t\\t0.5, 1.0\\n\\t);\\n\\toutput.vUv0 = vec2f(pixelX / uniform.screenWidth,\\n\\t\\t\\t\\t\\t\\tpixelY / uniform.screenHeight);\\n\\treturn output;\\n}\\n`;\\n\\nvar gsplat_default$1 = `\\n#ifndef DITHER_NONE\\n\\t#include \\\"bayerPS\\\"\\n\\t#include \\\"opacityDitherPS\\\"\\n\\tvarying id: f32;\\n#endif\\n#if defined(SHADOW_PASS) || defined(PICK_PASS) || defined(PREPASS_PASS)\\n\\tuniform alphaClip: f32;\\n#endif\\n#ifdef PREPASS_PASS\\n\\tvarying vLinearDepth: f32;\\n\\t#include \\\"floatAsUintPS\\\"\\n#endif\\n#if !defined(SHADOW_PASS) && !defined(PICK_PASS) && !defined(PREPASS_PASS)\\n\\tuniform alphaClipForward: f32;\\n#endif\\nconst EXP4: half = exp(half(-4.0));\\nconst INV_EXP4: half = half(1.0) / (half(1.0) - EXP4);\\nfn normExp(x: half) -> half {\\n\\treturn (exp(x * half(-4.0)) - EXP4) * INV_EXP4;\\n}\\nvarying gaussianUV: half2;\\nvarying gaussianColor: half4;\\n#if defined(GSPLAT_UNIFIED_ID) && defined(PICK_PASS)\\n\\tvarying @interpolate(flat) vPickId: u32;\\n#endif\\n#ifdef PICK_PASS\\n\\t#include \\\"pickPS\\\"\\n#endif\\n@fragment\\nfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\tvar output: FragmentOutput;\\n\\tlet A: half = dot(gaussianUV, gaussianUV);\\n\\tif (A > half(1.0)) {\\n\\t\\tdiscard;\\n\\t\\treturn output;\\n\\t}\\n\\tvar alpha: half = normExp(A) * gaussianColor.a;\\n\\t#if defined(SHADOW_PASS) || defined(PICK_PASS) || defined(PREPASS_PASS)\\n\\t\\tif (alpha < half(uniform.alphaClip)) {\\n\\t\\t\\tdiscard;\\n\\t\\t\\treturn output;\\n\\t\\t}\\n\\t#endif\\n\\t#ifdef PICK_PASS\\n\\t\\t#ifdef GSPLAT_UNIFIED_ID\\n\\t\\t\\toutput.color = encodePickOutput(vPickId);\\n\\t\\t#else\\n\\t\\t\\toutput.color = getPickOutput();\\n\\t\\t#endif\\n\\t\\t#ifdef DEPTH_PICK_PASS\\n\\t\\t\\toutput.color1 = getPickDepth();\\n\\t\\t#endif\\n\\t#elif SHADOW_PASS\\n\\t\\toutput.color = vec4f(0.0, 0.0, 0.0, 1.0);\\n\\t#elif PREPASS_PASS\\n\\t\\toutput.color = float2vec4(vLinearDepth);\\n\\t#else\\n\\t\\tif (alpha < half(uniform.alphaClipForward)) {\\n\\t\\t\\tdiscard;\\n\\t\\t\\treturn output;\\n\\t\\t}\\n\\t\\t#ifndef DITHER_NONE\\n\\t\\t\\topacityDither(f32(alpha), id * 0.013);\\n\\t\\t#endif\\n\\t\\toutput.color = vec4f(vec3f(gaussianColor.xyz * alpha), f32(alpha));\\n\\t#endif\\n\\treturn output;\\n}`;\\n\\nvar gsplatTileComposite_default = `\\n#ifdef PICK_MODE\\n\\t#include \\\"pickPS\\\"\\n\\t#include \\\"floatAsUintPS\\\"\\n\\tvar pickIdTexture: texture_2d<u32>;\\n\\tvar pickDepthTexture: texture_2d<f32>;\\n#else\\n\\t#include \\\"tonemappingPS\\\"\\n\\t#include \\\"gammaPS\\\"\\n\\tvar source: texture_2d<f32>;\\n#endif\\nvarying vUv0: vec2f;\\n@fragment fn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\tvar output: FragmentOutput;\\n\\t#ifdef PICK_MODE\\n\\t\\tlet texSize = vec2f(textureDimensions(pickIdTexture));\\n\\t\\tlet coord = vec2u(input.vUv0 * texSize);\\n\\t\\tlet pickId = textureLoad(pickIdTexture, coord, 0).r;\\n\\t\\tif (pickId == 0xFFFFFFFFu) {\\n\\t\\t\\tdiscard;\\n\\t\\t\\treturn output;\\n\\t\\t}\\n\\t\\toutput.color = encodePickOutput(pickId);\\n\\t\\tlet depthData = textureLoad(pickDepthTexture, coord, 0);\\n\\t\\tlet normalizedDepth = select(depthData.r / depthData.g, 1.0, depthData.g < 1e-6);\\n\\t\\toutput.color1 = float2uint(normalizedDepth);\\n\\t#else\\n\\t\\tlet texSize = vec2f(textureDimensions(source));\\n\\t\\tlet coord = vec2u(input.vUv0 * texSize);\\n\\t\\tlet linear = textureLoad(source, coord, 0);\\n\\t\\toutput.color = vec4f(gammaCorrectOutput(toneMap(linear.rgb)), linear.a);\\n\\t#endif\\n\\treturn output;\\n}\\n`;\\n\\nvar gsplatSource_default = `\\nattribute vertex_position: vec3f;\\n#ifdef GSPLAT_INDIRECT_DRAW\\n\\tvar<storage, read> numSplatsStorage: array<u32>;\\n\\tvar<storage, read> compactedSplatIds: array<u32>;\\n#else\\n\\tuniform numSplats: u32;\\n\\tvar<storage, read> splatOrder: array<u32>;\\n#endif\\nfn initSource(source: ptr<function, SplatSource>) -> bool {\\n\\tsource.order = pcInstanceIndex * {GSPLAT_INSTANCE_SIZE}u + u32(vertex_position.z);\\n\\t#ifdef GSPLAT_INDIRECT_DRAW\\n\\t\\tlet numSplats = numSplatsStorage[0];\\n\\t#else\\n\\t\\tlet numSplats = uniform.numSplats;\\n\\t#endif\\n\\tif (source.order >= numSplats) {\\n\\t\\treturn false;\\n\\t}\\n\\tvar splatId: u32;\\n\\t#ifdef GSPLAT_INDIRECT_DRAW\\n\\t\\tsplatId = compactedSplatIds[source.order];\\n\\t#else\\n\\t\\tsplatId = splatOrder[source.order];\\n\\t#endif\\n\\tsetSplat(splatId);\\n\\tsource.cornerUV = half2(vertex_position.xy);\\n\\treturn true;\\n}\\n`;\\n\\nvar gsplat_default = `\\n#include \\\"gsplatCommonVS\\\"\\nvarying gaussianUV: half2;\\nvarying gaussianColor: half4;\\n#ifndef DITHER_NONE\\n\\tvarying id: f32;\\n#endif\\nconst discardVec: vec4f = vec4f(0.0, 0.0, 2.0, 1.0);\\n#ifdef PREPASS_PASS\\n\\tvarying vLinearDepth: f32;\\n#endif\\n#if defined(GSPLAT_UNIFIED_ID) && defined(PICK_PASS)\\n\\tvarying @interpolate(flat) vPickId: u32;\\n#endif\\n#ifdef GSPLAT_OVERDRAW\\n\\tuniform colorRampIntensity: f32;\\n\\tvar colorRamp: texture_2d<f32>;\\n\\tvar colorRampSampler: sampler;\\n#endif\\n@vertex\\nfn vertexMain(input: VertexInput) -> VertexOutput {\\n\\tvar output: VertexOutput;\\n\\tvar source: SplatSource;\\n\\tif (!initSource(&source)) {\\n\\t\\toutput.position = discardVec;\\n\\t\\treturn output;\\n\\t}\\n\\tvar modelCenter: vec3f = getCenter();\\n\\tvar center: SplatCenter;\\n\\tcenter.modelCenterOriginal = modelCenter;\\n\\t\\n\\tmodifySplatCenter(&modelCenter);\\n\\tcenter.modelCenterModified = modelCenter;\\n\\tif (!initCenter(modelCenter, &center)) {\\n\\t\\toutput.position = discardVec;\\n\\t\\treturn output;\\n\\t}\\n\\tvar corner: SplatCorner;\\n\\tif (!initCorner(&source, &center, &corner)) {\\n\\t\\toutput.position = discardVec;\\n\\t\\treturn output;\\n\\t}\\n\\t#ifdef GSPLAT_SEPARATE_OPACITY\\n\\t\\tlet opacity = getOpacity();\\n\\t\\tvar clr: half4 = half4(vec4f(getColor(), opacity));\\n\\t#else\\n\\t\\tvar clr: half4 = half4(getColor());\\n\\t#endif\\n\\t#if GSPLAT_AA\\n\\t\\tclr.a = clr.a * corner.aaFactor;\\n\\t#endif\\n\\t#if SH_BANDS > 0\\n\\t\\tlet modelView3x3 = mat3x3f(center.modelView[0].xyz, center.modelView[1].xyz, center.modelView[2].xyz);\\n\\t\\tlet dir = normalize(center.view * modelView3x3);\\n\\t\\tvar sh: array<half3, SH_COEFFS>;\\n\\t\\tvar scale: f32;\\n\\t\\treadSHData(&sh, &scale);\\n\\t\\tclr = half4(clr.xyz + evalSH(&sh, dir) * half(scale), clr.a);\\n\\t#endif\\n\\tvar clrF32 = vec4f(clr);\\n\\tmodifySplatColor(modelCenter, &clrF32);\\n\\tclr = half4(clrF32);\\n\\t#if defined(SHADOW_PASS) || defined(PICK_PASS) || defined(PREPASS_PASS)\\n\\t\\tlet alphaClipValue = half(uniform.alphaClip);\\n\\t#else\\n\\t\\tlet alphaClipValue = half(uniform.alphaClipForward);\\n\\t#endif\\n\\tif (clr.w <= alphaClipValue) {\\n\\t\\toutput.position = discardVec;\\n\\t\\treturn output;\\n\\t}\\n\\tclipCorner(&corner, clr.w);\\n\\t#if GSPLAT_2DGS\\n\\t\\tlet modelCorner: vec3f = center.modelCenterModified + corner.offset;\\n\\t\\toutput.position = uniform.matrix_projection * center.modelView * vec4f(modelCorner, 1.0);\\n\\t#else\\n\\t\\toutput.position = center.proj + vec4f(corner.offset.xyz, 0.0);\\n\\t#endif\\n\\toutput.gaussianUV = corner.uv;\\n\\t#ifdef GSPLAT_OVERDRAW\\n\\t\\tlet t: f32 = clamp(center.modelCenterOriginal.y / 20.0, 0.0, 1.0);\\n\\t\\tlet rampColor: vec3f = textureSampleLevel(colorRamp, colorRampSampler, vec2f(t, 0.5), 0.0).rgb;\\n\\t\\tclr.a = clr.a * half(1.0 / 32.0) * half(uniform.colorRampIntensity);\\n\\t\\toutput.gaussianColor = half4(half3(rampColor), clr.a);\\n\\t#else\\n\\t\\toutput.gaussianColor = half4(half3(prepareOutputFromGamma(max(vec3f(clr.xyz), vec3f(0.0)), -center.view.z)), clr.w);\\n\\t#endif\\n\\t#ifndef DITHER_NONE\\n\\t\\toutput.id = f32(splat.index);\\n\\t#endif\\n\\t#ifdef PREPASS_PASS\\n\\t\\toutput.vLinearDepth = -center.view.z;\\n\\t#endif\\n\\t#if defined(GSPLAT_UNIFIED_ID) && defined(PICK_PASS)\\n\\t\\toutput.vPickId = loadPcId().r;\\n\\t#endif\\n\\treturn output;\\n}\\n`;\\n\\nvar gsplatHybrid_default = `\\n#include \\\"gsplatHelpersVS\\\"\\n#include \\\"gsplatOutputVS\\\"\\nattribute vertex_position: vec3f;\\nuniform viewport_size: vec4f;\\nuniform clipToViewZ: vec4f;\\n#if defined(SHADOW_PASS) || defined(PICK_PASS) || defined(PREPASS_PASS)\\n\\tuniform alphaClip: f32;\\n#else\\n\\tuniform alphaClipForward: f32;\\n#endif\\nvar<storage, read> sortedIndices: array<u32>;\\nvar<storage, read> projCache: array<u32>;\\nvar<storage, read> numSplatsStorage: array<u32>;\\nvarying gaussianUV: half2;\\nvarying gaussianColor: half4;\\n#ifndef DITHER_NONE\\n\\tvarying id: f32;\\n#endif\\n#ifdef PREPASS_PASS\\n\\tvarying vLinearDepth: f32;\\n#endif\\n#if defined(GSPLAT_UNIFIED_ID) && defined(PICK_PASS)\\n\\tvarying @interpolate(flat) vPickId: u32;\\n#endif\\n#ifdef GSPLAT_OVERDRAW\\n\\tuniform colorRampIntensity: f32;\\n\\tvar colorRamp: texture_2d<f32>;\\n\\tvar colorRampSampler: sampler;\\n#endif\\nconst discardVec: vec4f = vec4f(0.0, 0.0, 2.0, 1.0);\\n@vertex\\nfn vertexMain(input: VertexInput) -> VertexOutput {\\n\\tvar output: VertexOutput;\\n\\tlet order = pcInstanceIndex * {GSPLAT_INSTANCE_SIZE}u + u32(vertex_position.z);\\n\\tlet numSplats = numSplatsStorage[0];\\n\\tif (order >= numSplats) {\\n\\t\\toutput.position = discardVec;\\n\\t\\treturn output;\\n\\t}\\n\\tlet cacheIdx = sortedIndices[order];\\n\\tlet base = cacheIdx * {CACHE_STRIDE}u;\\n\\tlet proj = vec4f(\\n\\t\\tbitcast<f32>(projCache[base + 0u]),\\n\\t\\tbitcast<f32>(projCache[base + 1u]),\\n\\t\\tbitcast<f32>(projCache[base + 2u]),\\n\\t\\tbitcast<f32>(projCache[base + 3u])\\n\\t);\\n\\tlet v1 = unpack2x16float(projCache[base + 4u]);\\n\\tlet v2 = unpack2x16float(projCache[base + 5u]);\\n\\tlet ba = unpack2x16float(projCache[base + 7u]);\\n\\tlet alpha = half(ba.y);\\n\\t#if defined(GSPLAT_UNIFIED_ID) && defined(PICK_PASS)\\n\\t\\tlet pickId = projCache[base + 6u];\\n\\t#endif\\n\\t#ifdef PICK_PASS\\n\\t\\tvar clr: half4 = half4(half(0.0), half(0.0), half(0.0), alpha);\\n\\t#else\\n\\t\\tlet rg = unpack2x16float(projCache[base + 6u]);\\n\\t\\tvar clr: half4 = half4(half(rg.x), half(rg.y), half(ba.x), alpha);\\n\\t#endif\\n\\tlet cornerUV = vec2f(vertex_position.xy);\\n\\t#if defined(SHADOW_PASS) || defined(PICK_PASS) || defined(PREPASS_PASS)\\n\\t\\tlet alphaClipValue = half(uniform.alphaClip);\\n\\t#else\\n\\t\\tlet alphaClipValue = half(uniform.alphaClipForward);\\n\\t#endif\\n\\tlet clip = min(half(1.0), sqrt(max(half(0.0), log(alpha / alphaClipValue))) * half(0.5));\\n\\tlet cornerClipped = cornerUV * f32(clip);\\n\\tlet c = vec2f(proj.w) * uniform.viewport_size.zw;\\n\\tlet pixelOffset = cornerClipped.x * v1 + cornerClipped.y * v2;\\n\\tlet clipOffset = pixelOffset * c;\\n\\toutput.position = proj + vec4f(clipOffset, 0.0, 0.0);\\n\\toutput.gaussianUV = half2(cornerClipped);\\n\\tlet viewDepth = dot(uniform.clipToViewZ, proj);\\n\\t#ifdef GSPLAT_OVERDRAW\\n\\t\\tlet t: f32 = clamp(viewDepth / 20.0, 0.0, 1.0);\\n\\t\\tlet rampColor: vec3f = textureSampleLevel(colorRamp, colorRampSampler, vec2f(t, 0.5), 0.0).rgb;\\n\\t\\tlet outAlpha = alpha * half(1.0 / 32.0) * half(uniform.colorRampIntensity);\\n\\t\\toutput.gaussianColor = half4(half3(rampColor), outAlpha);\\n\\t#else\\n\\t\\toutput.gaussianColor = half4(\\n\\t\\t\\thalf3(prepareOutputFromGamma(max(vec3f(clr.xyz), vec3f(0.0)), viewDepth)),\\n\\t\\t\\talpha\\n\\t\\t);\\n\\t#endif\\n\\t#ifndef DITHER_NONE\\n\\t\\toutput.id = f32(cacheIdx);\\n\\t#endif\\n\\t#ifdef PREPASS_PASS\\n\\t\\toutput.vLinearDepth = viewDepth;\\n\\t#endif\\n\\t#if defined(GSPLAT_UNIFIED_ID) && defined(PICK_PASS)\\n\\t\\toutput.vPickId = pickId;\\n\\t#endif\\n\\treturn output;\\n}\\n`;\\n\\nvar gsplatPacking_default = `\\nfn pack8888(v: vec4f) -> u32 {\\n\\tlet t = vec4u(v * 255.0) << vec4u(24u, 16u, 8u, 0u);\\n\\treturn t.x | t.y | t.z | t.w;\\n}\\nfn pack101010(v: vec3f) -> u32 {\\n\\tlet t = vec3u(v * vec3f(1023.0, 1023.0, 1023.0)) << vec3u(20u, 10u, 0u);\\n\\treturn t.x | t.y | t.z;\\n}\\nfn pack111110(v: vec3f) -> u32 {\\n\\tlet t = vec3u(v * vec3f(2047.0, 2047.0, 1023.0)) << vec3u(21u, 10u, 0u);\\n\\treturn t.x | t.y | t.z;\\n}\\nfn unpack8888(v: u32) -> vec4f {\\n\\treturn vec4f((vec4u(v) >> vec4u(24u, 16u, 8u, 0u)) & vec4u(0xffu)) / 255.0;\\n}\\nfn unpack101010(v: u32) -> vec3f {\\n\\treturn vec3f((vec3u(v) >> vec3u(20u, 10u, 0u)) & vec3u(0x3ffu)) / 1023.0;\\n}\\nfn unpack111110(v: u32) -> vec3f {\\n\\treturn vec3f((vec3u(v) >> vec3u(21u, 10u, 0u)) & vec3u(0x7ffu, 0x7ffu, 0x3ffu)) / vec3f(2047.0, 2047.0, 1023.0);\\n}`;\\n\\nvar gsplatFormat_default = `\\nuniform splatTextureSize: u32;\\n`;\\n\\nvar uncompressed_default = `\\nvar<private> tAw: u32;\\nvar<private> tBcached: vec4f;\\nfn unpackRotation(data: vec3f) -> vec4f {\\n\\treturn vec4f(data.xyz, sqrt(max(0.0, 1.0 - dot(data, data))));\\n}\\nfn getCenter() -> vec3f {\\n\\tlet tA: vec4<u32> = loadTransformA();\\n\\ttAw = tA.w;\\n\\ttBcached = loadTransformB();\\n\\treturn bitcast<vec3f>(tA.xyz);\\n}\\nfn getColor() -> vec4f {\\n\\treturn loadSplatColor();\\n}\\nfn getRotation() -> vec4f {\\n\\treturn unpackRotation(vec3f(unpack2x16float(tAw), tBcached.w)).wxyz;\\n}\\nfn getScale() -> vec3f {\\n\\treturn tBcached.xyz;\\n}\\n#include \\\"gsplatUncompressedSHVS\\\"\\n`;\\n\\nvar uncompressedSH_default = `\\n#if SH_BANDS > 0\\nfn unpack111011s(bits: u32) -> vec3f {\\n\\treturn (vec3f((vec3<u32>(bits) >> vec3<u32>(21u, 11u, 0u)) & vec3<u32>(0x7ffu, 0x3ffu, 0x7ffu)) / vec3f(2047.0, 1023.0, 2047.0)) * 2.0 - 1.0;\\n}\\nstruct ScaleAndSH {\\n\\tscale: f32,\\n\\ta: vec3f,\\n\\tb: vec3f,\\n\\tc: vec3f\\n};\\nfn fetchScale(t_in: vec4<u32>) -> ScaleAndSH {\\n\\tvar result: ScaleAndSH;\\n\\tresult.scale = bitcast<f32>(t_in.x);\\n\\tresult.a = unpack111011s(t_in.y);\\n\\tresult.b = unpack111011s(t_in.z);\\n\\tresult.c = unpack111011s(t_in.w);\\n\\treturn result;\\n}\\nstruct SH {\\n\\ta: vec3f,\\n\\tb: vec3f,\\n\\tc: vec3f,\\n\\td: vec3f\\n};\\nfn fetch4(t_in: vec4<u32>) -> SH {\\n\\tvar result: SH;\\n\\tresult.a = unpack111011s(t_in.x);\\n\\tresult.b = unpack111011s(t_in.y);\\n\\tresult.c = unpack111011s(t_in.z);\\n\\tresult.d = unpack111011s(t_in.w);\\n\\treturn result;\\n}\\nfn fetch1(t_in: u32) -> vec3f {\\n\\treturn unpack111011s(t_in);\\n}\\n#if SH_BANDS == 1\\n\\tfn readSHData(sh: ptr<function, array<half3, 3>>, scale: ptr<function, f32>) {\\n\\t\\tlet result = fetchScale(loadSplatSH_1to3());\\n\\t\\t*scale = result.scale;\\n\\t\\tsh[0] = half3(result.a);\\n\\t\\tsh[1] = half3(result.b);\\n\\t\\tsh[2] = half3(result.c);\\n\\t}\\n#elif SH_BANDS == 2\\n\\tfn readSHData(sh: ptr<function, array<half3, 8>>, scale: ptr<function, f32>) {\\n\\t\\tlet first: ScaleAndSH = fetchScale(loadSplatSH_1to3());\\n\\t\\t*scale = first.scale;\\n\\t\\tsh[0] = half3(first.a);\\n\\t\\tsh[1] = half3(first.b);\\n\\t\\tsh[2] = half3(first.c);\\n\\t\\tlet second: SH = fetch4(loadSplatSH_4to7());\\n\\t\\tsh[3] = half3(second.a);\\n\\t\\tsh[4] = half3(second.b);\\n\\t\\tsh[5] = half3(second.c);\\n\\t\\tsh[6] = half3(second.d);\\n\\t\\tsh[7] = half3(fetch1(loadSplatSH_8to11().x));\\n\\t}\\n#else\\n\\tfn readSHData(sh: ptr<function, array<half3, 15>>, scale: ptr<function, f32>) {\\n\\t\\tlet first: ScaleAndSH = fetchScale(loadSplatSH_1to3());\\n\\t\\t*scale = first.scale;\\n\\t\\tsh[0] = half3(first.a);\\n\\t\\tsh[1] = half3(first.b);\\n\\t\\tsh[2] = half3(first.c);\\n\\t\\tlet second: SH = fetch4(loadSplatSH_4to7());\\n\\t\\tsh[3] = half3(second.a);\\n\\t\\tsh[4] = half3(second.b);\\n\\t\\tsh[5] = half3(second.c);\\n\\t\\tsh[6] = half3(second.d);\\n\\t\\tlet third: SH = fetch4(loadSplatSH_8to11());\\n\\t\\tsh[7] = half3(third.a);\\n\\t\\tsh[8] = half3(third.b);\\n\\t\\tsh[9] = half3(third.c);\\n\\t\\tsh[10] = half3(third.d);\\n\\t\\tlet fourth: SH = fetch4(loadSplatSH_12to15());\\n\\t\\tsh[11] = half3(fourth.a);\\n\\t\\tsh[12] = half3(fourth.b);\\n\\t\\tsh[13] = half3(fourth.c);\\n\\t\\tsh[14] = half3(fourth.d);\\n\\t}\\n#endif\\n#endif\\n`;\\n\\nvar compressed_default = `\\n#include \\\"gsplatPackingPS\\\"\\nvar chunkTexture: texture_2d<uff>;\\nvar<private> chunkDataA: vec4f;\\nvar<private> chunkDataB: vec4f;\\nvar<private> chunkDataC: vec4f;\\nvar<private> chunkDataD: vec4f;\\nvar<private> chunkDataE: vec4f;\\nvar<private> packedData: vec4u;\\nfn unpack111011(bits: u32) -> vec3f {\\n\\treturn (vec3f((vec3<u32>(bits) >> vec3<u32>(21u, 11u, 0u)) & vec3<u32>(0x7ffu, 0x3ffu, 0x7ffu))) / vec3f(2047.0, 1023.0, 2047.0);\\n}\\nconst norm_const: f32 = sqrt(2.0);\\nfn unpackRotation(bits: u32) -> vec4f {\\n\\tlet a = (f32((bits >> 20u) & 0x3ffu) / 1023.0 - 0.5) * norm_const;\\n\\tlet b = (f32((bits >> 10u) & 0x3ffu) / 1023.0 - 0.5) * norm_const;\\n\\tlet c = (f32(bits & 0x3ffu) / 1023.0 - 0.5) * norm_const;\\n\\tlet m = sqrt(1.0 - (a * a + b * b + c * c));\\n\\tlet mode = bits >> 30u;\\n\\tif (mode == 0u) { return vec4f(m, a, b, c); }\\n\\tif (mode == 1u) { return vec4f(a, m, b, c); }\\n\\tif (mode == 2u) { return vec4f(a, b, m, c); }\\n\\treturn vec4f(a, b, c, m);\\n}\\nfn getCenter() -> vec3f {\\n\\tlet tex_size_u = textureDimensions(chunkTexture, 0);\\n\\tlet w: u32 = tex_size_u.x / 5u;\\n\\tlet chunkId: u32 = splat.index / 256u;\\n\\tlet chunkUV: vec2<i32> = vec2<i32>(i32((chunkId % w) * 5u), i32(chunkId / w));\\n\\tchunkDataA = textureLoad(chunkTexture, chunkUV + vec2<i32>(0, 0), 0);\\n\\tchunkDataB = textureLoad(chunkTexture, chunkUV + vec2<i32>(1, 0), 0);\\n\\tchunkDataC = textureLoad(chunkTexture, chunkUV + vec2<i32>(2, 0), 0);\\n\\tchunkDataD = textureLoad(chunkTexture, chunkUV + vec2<i32>(3, 0), 0);\\n\\tchunkDataE = textureLoad(chunkTexture, chunkUV + vec2<i32>(4, 0), 0);\\n\\tpackedData = loadPackedTexture();\\n\\treturn mix(chunkDataA.xyz, vec3f(chunkDataA.w, chunkDataB.xy), unpack111011(packedData.x));\\n}\\nfn getColor() -> vec4f {\\n\\tlet r = unpack8888(packedData.w);\\n\\treturn vec4f(mix(chunkDataD.xyz, vec3f(chunkDataD.w, chunkDataE.xy), r.rgb), r.w);\\n}\\nfn getRotation() -> vec4f {\\n\\treturn unpackRotation(packedData.y);\\n}\\nfn getScale() -> vec3f {\\n\\treturn exp(mix(vec3f(chunkDataB.zw, chunkDataC.x), chunkDataC.yzw, unpack111011(packedData.z)));\\n}\\n#include \\\"gsplatCompressedSHVS\\\"\\n`;\\n\\nvar compressedSH_default = `\\n#if SH_BANDS > 0\\nfn unpack8888s(bits: u32) -> half4 {\\n\\tlet unpacked_u = (vec4<u32>(bits) >> vec4<u32>(0u, 8u, 16u, 24u)) & vec4<u32>(0xffu);\\n\\treturn half4(vec4f(unpacked_u) * (8.0 / 255.0) - 4.0);\\n}\\nfn readSHData(sh: ptr<function, array<half3, 15>>, scale: ptr<function, f32>) {\\n\\tlet shData0: vec4<u32> = loadShTexture0();\\n\\tlet shData1: vec4<u32> = loadShTexture1();\\n\\tlet shData2: vec4<u32> = loadShTexture2();\\n\\tlet r0: half4 = unpack8888s(shData0.x);\\n\\tlet r1: half4 = unpack8888s(shData0.y);\\n\\tlet r2: half4 = unpack8888s(shData0.z);\\n\\tlet r3: half4 = unpack8888s(shData0.w);\\n\\tlet g0: half4 = unpack8888s(shData1.x);\\n\\tlet g1: half4 = unpack8888s(shData1.y);\\n\\tlet g2: half4 = unpack8888s(shData1.z);\\n\\tlet g3: half4 = unpack8888s(shData1.w);\\n\\tlet b0: half4 = unpack8888s(shData2.x);\\n\\tlet b1: half4 = unpack8888s(shData2.y);\\n\\tlet b2: half4 = unpack8888s(shData2.z);\\n\\tlet b3: half4 = unpack8888s(shData2.w);\\n\\tsh[0] =  half3(r0.x, g0.x, b0.x);\\n\\tsh[1] =  half3(r0.y, g0.y, b0.y);\\n\\tsh[2] =  half3(r0.z, g0.z, b0.z);\\n\\tsh[3] =  half3(r0.w, g0.w, b0.w);\\n\\tsh[4] =  half3(r1.x, g1.x, b1.x);\\n\\tsh[5] =  half3(r1.y, g1.y, b1.y);\\n\\tsh[6] =  half3(r1.z, g1.z, b1.z);\\n\\tsh[7] =  half3(r1.w, g1.w, b1.w);\\n\\tsh[8] =  half3(r2.x, g2.x, b2.x);\\n\\tsh[9] =  half3(r2.y, g2.y, b2.y);\\n\\tsh[10] = half3(r2.z, g2.z, b2.z);\\n\\tsh[11] = half3(r2.w, g2.w, b2.w);\\n\\tsh[12] = half3(r3.x, g3.x, b3.x);\\n\\tsh[13] = half3(r3.y, g3.y, b3.y);\\n\\tsh[14] = half3(r3.z, g3.z, b3.z);\\n\\t*scale = 1.0;\\n}\\n#endif\\n`;\\n\\nvar sog_default = `\\nuniform means_mins: vec3f;\\nuniform means_maxs: vec3f;\\n#ifndef SOG_V2\\n\\tuniform scales_mins: vec3f;\\n\\tuniform scales_maxs: vec3f;\\n\\tuniform sh0_mins: vec4f;\\n\\tuniform sh0_maxs: vec4f;\\n#endif\\nconst SH_C0: f32 = 0.28209479177387814;\\nconst norm: f32 = sqrt(2.0);\\n#ifdef SOG_V2\\n\\tfn lutScales(b: i32) -> f32 { return textureLoad(sogCodebook, vec2i(b, 0), 0).r; }\\n\\tfn lutSh0(b: i32) -> f32\\t{ return textureLoad(sogCodebook, vec2i(b, 0), 0).g; }\\n\\tfn lutShN(b: i32) -> f32\\t{ return textureLoad(sogCodebook, vec2i(b, 0), 0).b; }\\n#endif\\nfn getCenter() -> vec3f {\\n\\tlet l = textureLoad(means_l, splat.uv, 0).xyz;\\n\\tlet u = textureLoad(means_u, splat.uv, 0).xyz;\\n\\tlet n = (l + u * 256.0) / 257.0;\\n\\tlet v = mix(uniform.means_mins, uniform.means_maxs, n);\\n\\treturn sign(v) * (exp(abs(v)) - 1.0);\\n}\\nfn getRotation() -> vec4f {\\n\\tlet q = textureLoad(quats, splat.uv, 0);\\n\\tlet qmode = u32(q.w * 255.0 + 0.5) - 252u;\\n\\tlet abc = (q.xyz - 0.5) * norm;\\n\\tlet d = sqrt(max(0.0, 1.0 - dot(abc, abc)));\\n\\tvar quat: vec4f;\\n\\tif (qmode == 0u) {\\n\\t\\tquat = vec4f(d, abc);\\n\\t} else if (qmode == 1u) {\\n\\t\\tquat = vec4f(abc.x, d, abc.y, abc.z);\\n\\t} else if (qmode == 2u) {\\n\\t\\tquat = vec4f(abc.x, abc.y, d, abc.z);\\n\\t} else {\\n\\t\\tquat = vec4f(abc.x, abc.y, abc.z, d);\\n\\t}\\n\\treturn quat;\\n}\\nfn getScale() -> vec3f {\\n\\tlet s = textureLoad(scales, splat.uv, 0).xyz;\\n\\tvar logS: vec3f;\\n\\t#ifdef SOG_V2\\n\\t\\tlet i = vec3i(s * 255.0 + 0.5);\\n\\t\\tlogS = vec3f(lutScales(i.x), lutScales(i.y), lutScales(i.z));\\n\\t#else\\n\\t\\tlogS = mix(uniform.scales_mins, uniform.scales_maxs, s);\\n\\t#endif\\n\\treturn exp(logS);\\n}\\nfn getColor() -> vec4f {\\n\\tlet c = textureLoad(sh0, splat.uv, 0);\\n\\tvar rgb: vec3f;\\n\\tvar alpha: f32;\\n\\t#ifdef SOG_V2\\n\\t\\tlet i = vec3i(c.xyz * 255.0 + 0.5);\\n\\t\\trgb = vec3f(lutSh0(i.x), lutSh0(i.y), lutSh0(i.z));\\n\\t\\talpha = c.w;\\n\\t#else\\n\\t\\trgb = mix(uniform.sh0_mins.xyz, uniform.sh0_maxs.xyz, c.xyz);\\n\\t\\tlet logitAlpha = mix(uniform.sh0_mins.w, uniform.sh0_maxs.w, c.w);\\n\\t\\talpha = 1.0 / (1.0 + exp(-logitAlpha));\\n\\t#endif\\n\\treturn vec4f(vec3f(0.5) + rgb * SH_C0, alpha);\\n}\\n#include \\\"gsplatSogSHVS\\\"\\n`;\\n\\nvar sogSH_default = `\\n#if SH_BANDS > 0\\n\\t#ifndef SOG_V2\\n\\t\\tuniform shN_mins: f32;\\n\\t\\tuniform shN_maxs: f32;\\n\\t#endif\\n\\tfn readSHTexel(u: i32, v: i32) -> half3 {\\n\\t\\tlet t = textureLoad(sh_centroids, vec2i(u, v), 0);\\n\\t\\t#ifdef SOG_V2\\n\\t\\t\\tlet idx = vec3i(t.xyz * 255.0 + 0.5);\\n\\t\\t\\treturn half3(vec3f(lutShN(idx.x), lutShN(idx.y), lutShN(idx.z)));\\n\\t\\t#else\\n\\t\\t\\treturn mix(half3(half(uniform.shN_mins)), half3(half(uniform.shN_maxs)), half3(t.xyz));\\n\\t\\t#endif\\n\\t}\\n\\tfn readSHData(sh: ptr<function, array<half3, SH_COEFFS>>, scale: ptr<function, f32>) {\\n\\t\\tlet labels = textureLoad(sh_labels, splat.uv, 0);\\n\\t\\tlet n = i32(labels.x * 255.0 + 0.5) + i32(labels.y * 255.0 + 0.5) * 256;\\n\\t\\tlet u = (n % 64) * SH_COEFFS;\\n\\t\\tlet v = n / 64;\\n\\t\\tsh[0] = readSHTexel(u, v);\\n\\t\\tsh[1] = readSHTexel(u + 1, v);\\n\\t\\tsh[2] = readSHTexel(u + 2, v);\\n\\t\\t#if SH_BANDS > 1\\n\\t\\t\\tsh[3] = readSHTexel(u + 3, v);\\n\\t\\t\\tsh[4] = readSHTexel(u + 4, v);\\n\\t\\t\\tsh[5] = readSHTexel(u + 5, v);\\n\\t\\t\\tsh[6] = readSHTexel(u + 6, v);\\n\\t\\t\\tsh[7] = readSHTexel(u + 7, v);\\n\\t\\t#endif\\n\\t\\t#if SH_BANDS > 2\\n\\t\\t\\tsh[8]  = readSHTexel(u + 8, v);\\n\\t\\t\\tsh[9]  = readSHTexel(u + 9, v);\\n\\t\\t\\tsh[10] = readSHTexel(u + 10, v);\\n\\t\\t\\tsh[11] = readSHTexel(u + 11, v);\\n\\t\\t\\tsh[12] = readSHTexel(u + 12, v);\\n\\t\\t\\tsh[13] = readSHTexel(u + 13, v);\\n\\t\\t\\tsh[14] = readSHTexel(u + 14, v);\\n\\t\\t#endif\\n\\t\\t*scale = 1.0;\\n\\t}\\n#endif\\n`;\\n\\nvar containerDecl_default = `\\n#include \\\"gsplatContainerDeclarationsVS\\\"\\nvar<private> splatCenter: vec3f;\\nvar<private> splatColor: vec4f;\\nvar<private> splatScale: vec3f;\\nvar<private> splatRotation: vec4f;\\n`;\\n\\nvar containerRead_default = `\\nfn getCenter() -> vec3f {\\n\\t#include \\\"gsplatContainerUserReadVS\\\"\\n\\treturn splatCenter;\\n}\\nfn getRotation() -> vec4f {\\n\\treturn splatRotation;\\n}\\nfn getScale() -> vec3f {\\n\\treturn splatScale;\\n}\\nfn getColor() -> vec4f {\\n\\treturn splatColor;\\n}\\n`;\\n\\nconst gsplatChunksWGSL = {\\n\\tgsplatCenterVS: gsplatCenter_default,\\n\\tgsplatCornerVS: gsplatCorner_default,\\n\\tgsplatTileCompositeVS: gsplatTileComposite_default$1,\\n\\tgsplatCommonVS: gsplatCommon_default,\\n\\tgsplatSplatVS: gsplatSplat_default,\\n\\tgsplatEvalSHVS: gsplatEvalSH_default,\\n\\tgsplatHelpersVS: gsplatHelpers_default,\\n\\tgsplatModifyVS: gsplatModify_default,\\n\\tgsplatStructsVS: gsplatStructs_default,\\n\\tgsplatQuatToMat3VS: gsplatQuatToMat3_default,\\n\\tgsplatOutputVS: gsplatOutput_default$1,\\n\\tgsplatPS: gsplat_default$1,\\n\\tgsplatTileCompositePS: gsplatTileComposite_default,\\n\\tgsplatSourceVS: gsplatSource_default,\\n\\tgsplatVS: gsplat_default,\\n\\tgsplatHybridVS: gsplatHybrid_default,\\n\\tgsplatPackingPS: gsplatPacking_default,\\n\\tgsplatFormatVS: gsplatFormat_default,\\n\\tgsplatUncompressedVS: uncompressed_default,\\n\\tgsplatUncompressedSHVS: uncompressedSH_default,\\n\\tgsplatCompressedVS: compressed_default,\\n\\tgsplatCompressedSHVS: compressedSH_default,\\n\\tgsplatSogVS: sog_default,\\n\\tgsplatSogSHVS: sogSH_default,\\n\\tgsplatContainerDeclVS: containerDecl_default,\\n\\tgsplatContainerReadVS: containerRead_default,\\n\\tgsplatContainerFloatReadVS: containerFloatRead_default\\n};\\n\\nconst _schema = [\\n\\t\\\"enabled\\\"\\n];\\nconst _properties = [\\n\\t\\\"unified\\\",\\n\\t\\\"lodBaseDistance\\\",\\n\\t\\\"lodMultiplier\\\",\\n\\t\\\"castShadows\\\",\\n\\t\\\"material\\\",\\n\\t\\\"highQualitySH\\\",\\n\\t\\\"asset\\\",\\n\\t\\\"resource\\\",\\n\\t\\\"layers\\\"\\n];\\nclass GSplatComponentSystem extends ComponentSystem {\\n\\tstatic EVENT_MATERIALCREATED = \\\"material:created\\\";\\n\\tstatic EVENT_FRAMEREADY = \\\"frame:ready\\\";\\n\\tconstructor(app) {\\n\\t\\tsuper(app);\\n\\t\\tthis.id = \\\"gsplat\\\";\\n\\t\\tthis.ComponentType = GSplatComponent;\\n\\t\\tthis.DataType = GSplatComponentData;\\n\\t\\tthis.schema = _schema;\\n\\t\\tapp.renderer.gsplatDirector = new GSplatDirector(app.graphicsDevice, app.renderer, app.scene, this);\\n\\t\\tShaderChunks.get(app.graphicsDevice, SHADERLANGUAGE_GLSL).add(gsplatChunksGLSL);\\n\\t\\tShaderChunks.get(app.graphicsDevice, SHADERLANGUAGE_WGSL).add(gsplatChunksWGSL);\\n\\t\\tthis.on(\\\"beforeremove\\\", this.onRemove, this);\\n\\t}\\n\\tinitializeComponentData(component, _data, properties) {\\n\\t\\tif (_data.layers && _data.layers.length) {\\n\\t\\t\\t_data.layers = _data.layers.slice(0);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < _properties.length; i++) {\\n\\t\\t\\tif (_data.hasOwnProperty(_properties[i])) {\\n\\t\\t\\t\\tcomponent[_properties[i]] = _data[_properties[i]];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (_data.aabbCenter && _data.aabbHalfExtents) {\\n\\t\\t\\tcomponent.customAabb = new BoundingBox(new Vec3(_data.aabbCenter), new Vec3(_data.aabbHalfExtents));\\n\\t\\t}\\n\\t\\tsuper.initializeComponentData(component, _data, _schema);\\n\\t}\\n\\tcloneComponent(entity, clone) {\\n\\t\\tconst gSplatComponent = entity.gsplat;\\n\\t\\tconst data = {};\\n\\t\\t_properties.forEach((prop) => {\\n\\t\\t\\tif (prop === \\\"material\\\") {\\n\\t\\t\\t\\tif (!gSplatComponent.unified) {\\n\\t\\t\\t\\t\\tconst srcMaterial = gSplatComponent[prop];\\n\\t\\t\\t\\t\\tif (srcMaterial) {\\n\\t\\t\\t\\t\\t\\tdata[prop] = srcMaterial.clone();\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tdata[prop] = gSplatComponent[prop];\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tdata.enabled = gSplatComponent.enabled;\\n\\t\\tconst component = this.addComponent(clone, data);\\n\\t\\tcomponent.customAabb = gSplatComponent.customAabb?.clone() ?? null;\\n\\t\\treturn component;\\n\\t}\\n\\tonRemove(entity, component) {\\n\\t\\tcomponent.onRemove();\\n\\t}\\n\\tgetMaterial(camera, layer) {\\n\\t\\tconst director = this.app.renderer.gsplatDirector;\\n\\t\\tif (!director) return null;\\n\\t\\tconst cameraData = director.camerasMap.get(camera);\\n\\t\\tif (!cameraData) return null;\\n\\t\\tconst layerData = cameraData.layersMap.get(layer);\\n\\t\\treturn layerData?.gsplatManager?.material ?? null;\\n\\t}\\n\\tgetGSplatMaterial(camera, layer) {\\n\\t\\treturn this.getMaterial(camera, layer);\\n\\t}\\n}\\nComponent._buildAccessors(GSplatComponent.prototype, _schema);\\n\\nclass Render extends EventHandler {\\n\\tstatic EVENT_SETMESHES = \\\"set:meshes\\\";\\n\\t_meshes = null;\\n\\tset meshes(value) {\\n\\t\\tthis.decRefMeshes();\\n\\t\\tthis._meshes = value;\\n\\t\\tthis.incRefMeshes();\\n\\t\\tthis.fire(\\\"set:meshes\\\", value);\\n\\t}\\n\\tget meshes() {\\n\\t\\treturn this._meshes;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.meshes = null;\\n\\t}\\n\\tdecRefMeshes() {\\n\\t\\tthis._meshes?.forEach((mesh, index) => {\\n\\t\\t\\tif (mesh) {\\n\\t\\t\\t\\tmesh.decRefCount();\\n\\t\\t\\t\\tif (mesh.refCount < 1) {\\n\\t\\t\\t\\t\\tmesh.destroy();\\n\\t\\t\\t\\t\\tthis._meshes[index] = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n\\tincRefMeshes() {\\n\\t\\tthis._meshes?.forEach((mesh) => {\\n\\t\\t\\tmesh?.incRefCount();\\n\\t\\t});\\n\\t}\\n}\\n\\nclass AnimCurve {\\n\\tconstructor(paths, input, output, interpolation) {\\n\\t\\tthis._paths = paths;\\n\\t\\tthis._input = input;\\n\\t\\tthis._output = output;\\n\\t\\tthis._interpolation = interpolation;\\n\\t}\\n\\tget paths() {\\n\\t\\treturn this._paths;\\n\\t}\\n\\tget input() {\\n\\t\\treturn this._input;\\n\\t}\\n\\tget output() {\\n\\t\\treturn this._output;\\n\\t}\\n\\tget interpolation() {\\n\\t\\treturn this._interpolation;\\n\\t}\\n}\\n\\nclass AnimData {\\n\\tconstructor(components, data) {\\n\\t\\tthis._components = components;\\n\\t\\tthis._data = data;\\n\\t}\\n\\tget components() {\\n\\t\\treturn this._components;\\n\\t}\\n\\tget data() {\\n\\t\\treturn this._data;\\n\\t}\\n}\\n\\nfunction DracoWorker(jsUrl, wasmUrl) {\\n\\tlet draco;\\n\\tconst POSITION_ATTRIBUTE = 0;\\n\\tconst NORMAL_ATTRIBUTE = 1;\\n\\tconst wrap = (typedArray, dataType) => {\\n\\t\\tswitch (dataType) {\\n\\t\\t\\tcase draco.DT_INT8:\\n\\t\\t\\t\\treturn new Int8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);\\n\\t\\t\\tcase draco.DT_INT16:\\n\\t\\t\\t\\treturn new Int16Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength / 2);\\n\\t\\t\\tcase draco.DT_INT32:\\n\\t\\t\\t\\treturn new Int32Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength / 4);\\n\\t\\t\\tcase draco.DT_UINT8:\\n\\t\\t\\t\\treturn new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);\\n\\t\\t\\tcase draco.DT_UINT16:\\n\\t\\t\\t\\treturn new Uint16Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength / 2);\\n\\t\\t\\tcase draco.DT_UINT32:\\n\\t\\t\\t\\treturn new Uint32Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength / 4);\\n\\t\\t\\tcase draco.DT_FLOAT32:\\n\\t\\t\\t\\treturn new Float32Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength / 4);\\n\\t\\t}\\n\\t\\treturn null;\\n\\t};\\n\\tconst componentSizeInBytes = (dataType) => {\\n\\t\\tswitch (dataType) {\\n\\t\\t\\tcase draco.DT_INT8:\\n\\t\\t\\t\\treturn 1;\\n\\t\\t\\tcase draco.DT_INT16:\\n\\t\\t\\t\\treturn 2;\\n\\t\\t\\tcase draco.DT_INT32:\\n\\t\\t\\t\\treturn 4;\\n\\t\\t\\tcase draco.DT_UINT8:\\n\\t\\t\\t\\treturn 1;\\n\\t\\t\\tcase draco.DT_UINT16:\\n\\t\\t\\t\\treturn 2;\\n\\t\\t\\tcase draco.DT_UINT32:\\n\\t\\t\\t\\treturn 4;\\n\\t\\t\\tcase draco.DT_FLOAT32:\\n\\t\\t\\t\\treturn 4;\\n\\t\\t}\\n\\t\\treturn 1;\\n\\t};\\n\\tconst toEngineDataType = (dataType) => {\\n\\t\\tswitch (dataType) {\\n\\t\\t\\tcase draco.DT_INT8:\\n\\t\\t\\t\\treturn 0;\\n\\t\\t\\tcase draco.DT_UINT8:\\n\\t\\t\\t\\treturn 1;\\n\\t\\t\\tcase draco.DT_INT16:\\n\\t\\t\\t\\treturn 2;\\n\\t\\t\\tcase draco.DT_UINT16:\\n\\t\\t\\t\\treturn 3;\\n\\t\\t\\tcase draco.DT_INT32:\\n\\t\\t\\t\\treturn 4;\\n\\t\\t\\tcase draco.DT_UINT32:\\n\\t\\t\\t\\treturn 5;\\n\\t\\t\\tcase draco.DT_FLOAT32:\\n\\t\\t\\t\\treturn 6;\\n\\t\\t\\tdefault:\\n\\t\\t\\t\\treturn 6;\\n\\t\\t}\\n\\t};\\n\\tconst attributeSizeInBytes = (attribute) => {\\n\\t\\treturn attribute.num_components() * componentSizeInBytes(attribute.data_type());\\n\\t};\\n\\tconst attributeOrder = {\\n\\t\\t0: 0,\\n\\t\\t// position\\n\\t\\t1: 1,\\n\\t\\t// normal\\n\\t\\t5: 2,\\n\\t\\t// tangent\\n\\t\\t2: 3,\\n\\t\\t// color\\n\\t\\t7: 4,\\n\\t\\t// joints\\n\\t\\t8: 5,\\n\\t\\t// weights\\n\\t\\t4: 6,\\n\\t\\t// generic (used for blend indices and weights)\\n\\t\\t3: 7\\n\\t\\t// texcoord\\n\\t};\\n\\tconst generateNormals = (vertices, indices) => {\\n\\t\\tconst subtract = (dst, a2, b2) => {\\n\\t\\t\\tdst[0] = a2[0] - b2[0];\\n\\t\\t\\tdst[1] = a2[1] - b2[1];\\n\\t\\t\\tdst[2] = a2[2] - b2[2];\\n\\t\\t};\\n\\t\\tconst cross = (dst, a2, b2) => {\\n\\t\\t\\tdst[0] = a2[1] * b2[2] - b2[1] * a2[2];\\n\\t\\t\\tdst[1] = a2[2] * b2[0] - b2[2] * a2[0];\\n\\t\\t\\tdst[2] = a2[0] * b2[1] - b2[0] * a2[1];\\n\\t\\t};\\n\\t\\tconst normalize = (dst, offset) => {\\n\\t\\t\\tconst a2 = dst[offset + 0];\\n\\t\\t\\tconst b2 = dst[offset + 1];\\n\\t\\t\\tconst c2 = dst[offset + 2];\\n\\t\\t\\tconst l = 1 / Math.sqrt(a2 * a2 + b2 * b2 + c2 * c2);\\n\\t\\t\\tdst[offset + 0] *= l;\\n\\t\\t\\tdst[offset + 1] *= l;\\n\\t\\t\\tdst[offset + 2] *= l;\\n\\t\\t};\\n\\t\\tconst copy = (dst, src, srcOffset) => {\\n\\t\\t\\tfor (let i = 0; i < 3; ++i) {\\n\\t\\t\\t\\tdst[i] = src[srcOffset + i];\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tconst numTriangles = indices.length / 3;\\n\\t\\tconst numVertices = vertices.length / 3;\\n\\t\\tconst result = new Float32Array(vertices.length);\\n\\t\\tconst a = [0, 0, 0], b = [0, 0, 0], c = [0, 0, 0], t1 = [0, 0, 0], t2 = [0, 0, 0], n = [0, 0, 0];\\n\\t\\tfor (let i = 0; i < numTriangles; ++i) {\\n\\t\\t\\tconst v0 = indices[i * 3 + 0] * 3;\\n\\t\\t\\tconst v1 = indices[i * 3 + 1] * 3;\\n\\t\\t\\tconst v2 = indices[i * 3 + 2] * 3;\\n\\t\\t\\tcopy(a, vertices, v0);\\n\\t\\t\\tcopy(b, vertices, v1);\\n\\t\\t\\tcopy(c, vertices, v2);\\n\\t\\t\\tsubtract(t1, b, a);\\n\\t\\t\\tsubtract(t2, c, a);\\n\\t\\t\\tcross(n, t1, t2);\\n\\t\\t\\tnormalize(n, 0);\\n\\t\\t\\tfor (let j = 0; j < 3; ++j) {\\n\\t\\t\\t\\tresult[v0 + j] += n[j];\\n\\t\\t\\t\\tresult[v1 + j] += n[j];\\n\\t\\t\\t\\tresult[v2 + j] += n[j];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < numVertices; ++i) {\\n\\t\\t\\tnormalize(result, i * 3);\\n\\t\\t}\\n\\t\\treturn new Uint8Array(result.buffer);\\n\\t};\\n\\tconst decodeMesh = (inputBuffer) => {\\n\\t\\tconst result = {};\\n\\t\\tconst buffer = new draco.DecoderBuffer();\\n\\t\\tbuffer.Init(inputBuffer, inputBuffer.length);\\n\\t\\tconst decoder = new draco.Decoder();\\n\\t\\tif (decoder.GetEncodedGeometryType(buffer) !== draco.TRIANGULAR_MESH) {\\n\\t\\t\\tresult.error = \\\"Failed to decode draco mesh: not a mesh\\\";\\n\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tconst mesh = new draco.Mesh();\\n\\t\\tconst status = decoder.DecodeBufferToMesh(buffer, mesh);\\n\\t\\tif (!status || !status.ok() || draco.getPointer(mesh) === 0) {\\n\\t\\t\\tresult.error = \\\"Failed to decode draco asset\\\";\\n\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tconst numIndices = mesh.num_faces() * 3;\\n\\t\\tconst shortIndices = mesh.num_points() <= 65535;\\n\\t\\tconst indicesSize = numIndices * (shortIndices ? 2 : 4);\\n\\t\\tconst indicesPtr = draco._malloc(indicesSize);\\n\\t\\tif (shortIndices) {\\n\\t\\t\\tdecoder.GetTrianglesUInt16Array(mesh, indicesSize, indicesPtr);\\n\\t\\t\\tresult.indices = new Uint16Array(draco.HEAPU16.buffer, indicesPtr, numIndices).slice().buffer;\\n\\t\\t} else {\\n\\t\\t\\tdecoder.GetTrianglesUInt32Array(mesh, indicesSize, indicesPtr);\\n\\t\\t\\tresult.indices = new Uint32Array(draco.HEAPU32.buffer, indicesPtr, numIndices).slice().buffer;\\n\\t\\t}\\n\\t\\tdraco._free(indicesPtr);\\n\\t\\tconst attributes = [];\\n\\t\\tfor (let i = 0; i < mesh.num_attributes(); ++i) {\\n\\t\\t\\tattributes.push(decoder.GetAttribute(mesh, i));\\n\\t\\t}\\n\\t\\tattributes.sort((a, b) => {\\n\\t\\t\\treturn (attributeOrder[a.attribute_type()] ?? attributeOrder.length) - (attributeOrder[b.attribute_type()] ?? attributeOrder.length);\\n\\t\\t});\\n\\t\\tlet totalVertexSize = 0;\\n\\t\\tconst offsets = attributes.map((a) => {\\n\\t\\t\\tconst offset = totalVertexSize;\\n\\t\\t\\ttotalVertexSize += Math.ceil(attributeSizeInBytes(a) / 4) * 4;\\n\\t\\t\\treturn offset;\\n\\t\\t});\\n\\t\\tconst hasNormals = attributes.some((a) => a.attribute_type() === NORMAL_ATTRIBUTE);\\n\\t\\tlet normalOffset = offsets[1] ?? 0;\\n\\t\\tif (!hasNormals) {\\n\\t\\t\\tnormalOffset = offsets[0] + Math.ceil(attributeSizeInBytes(attributes[0]) / 4) * 4;\\n\\t\\t\\tfor (let i = 1; i < offsets.length; ++i) {\\n\\t\\t\\t\\toffsets[i] += 12;\\n\\t\\t\\t}\\n\\t\\t\\ttotalVertexSize += 12;\\n\\t\\t}\\n\\t\\tresult.attributes = attributes.map((a, i) => ({\\n\\t\\t\\tid: a.unique_id(),\\n\\t\\t\\tdataType: toEngineDataType(a.data_type()),\\n\\t\\t\\tnumComponents: a.num_components(),\\n\\t\\t\\toffset: offsets[i]\\n\\t\\t}));\\n\\t\\tif (!hasNormals) {\\n\\t\\t\\tresult.attributes.splice(1, 0, {\\n\\t\\t\\t\\tid: -1,\\n\\t\\t\\t\\t// special id to indicate generated normals\\n\\t\\t\\t\\tdataType: 6,\\n\\t\\t\\t\\t// TYPE_FLOAT32\\n\\t\\t\\t\\tnumComponents: 3,\\n\\t\\t\\t\\toffset: normalOffset\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tresult.stride = totalVertexSize;\\n\\t\\tresult.vertices = new ArrayBuffer(mesh.num_points() * totalVertexSize);\\n\\t\\tconst dst = new Uint8Array(result.vertices);\\n\\t\\tfor (let i = 0; i < mesh.num_attributes(); ++i) {\\n\\t\\t\\tconst attribute = attributes[i];\\n\\t\\t\\tconst sizeInBytes = attributeSizeInBytes(attribute);\\n\\t\\t\\tconst ptrSize = mesh.num_points() * sizeInBytes;\\n\\t\\t\\tconst ptr = draco._malloc(ptrSize);\\n\\t\\t\\tdecoder.GetAttributeDataArrayForAllPoints(mesh, attribute, attribute.data_type(), ptrSize, ptr);\\n\\t\\t\\tconst src = new Uint8Array(draco.HEAPU8.buffer, ptr, ptrSize);\\n\\t\\t\\tfor (let j = 0; j < mesh.num_points(); ++j) {\\n\\t\\t\\t\\tfor (let c = 0; c < sizeInBytes; ++c) {\\n\\t\\t\\t\\t\\tdst[j * totalVertexSize + offsets[i] + c] = src[j * sizeInBytes + c];\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (!hasNormals && attribute.attribute_type() === POSITION_ATTRIBUTE) {\\n\\t\\t\\t\\tconst normals = generateNormals(\\n\\t\\t\\t\\t\\twrap(src, attribute.data_type()),\\n\\t\\t\\t\\t\\tshortIndices ? new Uint16Array(result.indices) : new Uint32Array(result.indices)\\n\\t\\t\\t\\t);\\n\\t\\t\\t\\tfor (let j = 0; j < mesh.num_points(); ++j) {\\n\\t\\t\\t\\t\\tfor (let c = 0; c < 12; ++c) {\\n\\t\\t\\t\\t\\t\\tdst[j * totalVertexSize + normalOffset + c] = normals[j * 12 + c];\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tdraco._free(ptr);\\n\\t\\t}\\n\\t\\tdraco.destroy(mesh);\\n\\t\\tdraco.destroy(decoder);\\n\\t\\tdraco.destroy(buffer);\\n\\t\\treturn result;\\n\\t};\\n\\tconst decode = (data) => {\\n\\t\\tconst result = decodeMesh(new Uint8Array(data.buffer));\\n\\t\\tself.postMessage({\\n\\t\\t\\tjobId: data.jobId,\\n\\t\\t\\terror: result.error,\\n\\t\\t\\tindices: result.indices,\\n\\t\\t\\tvertices: result.vertices,\\n\\t\\t\\tattributes: result.attributes,\\n\\t\\t\\tstride: result.stride\\n\\t\\t}, [result.indices, result.vertices].filter((t) => t != null));\\n\\t};\\n\\tconst workQueue = [];\\n\\tself.onmessage = (message) => {\\n\\t\\tconst data = message.data;\\n\\t\\tswitch (data.type) {\\n\\t\\t\\tcase \\\"init\\\":\\n\\t\\t\\t\\tself.DracoDecoderModule({\\n\\t\\t\\t\\t\\tinstantiateWasm: (imports, successCallback) => {\\n\\t\\t\\t\\t\\t\\tWebAssembly.instantiate(data.module, imports).then((result) => successCallback(result)).catch((reason) => console.error(`instantiate failed + ${reason}`));\\n\\t\\t\\t\\t\\t\\treturn {};\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}).then((instance) => {\\n\\t\\t\\t\\t\\tdraco = instance;\\n\\t\\t\\t\\t\\tworkQueue.forEach((data2) => decode(data2));\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase \\\"decodeMesh\\\":\\n\\t\\t\\t\\tif (draco) {\\n\\t\\t\\t\\t\\tdecode(data);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tworkQueue.push(data);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tbreak;\\n\\t\\t}\\n\\t};\\n}\\n\\nconst downloadMaxRetries = 3;\\nclass JobQueue {\\n\\tconstructor() {\\n\\t\\tthis.workers = [[], [], []];\\n\\t\\tthis.jobId = 0;\\n\\t\\tthis.jobQueue = [];\\n\\t\\tthis.jobCallbacks = /* @__PURE__ */ new Map();\\n\\t\\tthis.run = (worker, job) => {\\n\\t\\t\\tworker.postMessage({\\n\\t\\t\\t\\ttype: \\\"decodeMesh\\\",\\n\\t\\t\\t\\tjobId: job.jobId,\\n\\t\\t\\t\\tbuffer: job.buffer\\n\\t\\t\\t}, [job.buffer]);\\n\\t\\t};\\n\\t}\\n\\t// initialize the queue with worker instances\\n\\tinit(workers) {\\n\\t\\tworkers.forEach((worker) => {\\n\\t\\t\\tworker.addEventListener(\\\"message\\\", (message) => {\\n\\t\\t\\t\\tconst data = message.data;\\n\\t\\t\\t\\tconst callback = this.jobCallbacks.get(data.jobId);\\n\\t\\t\\t\\tif (callback) {\\n\\t\\t\\t\\t\\tcallback(data.error, {\\n\\t\\t\\t\\t\\t\\tindices: data.indices,\\n\\t\\t\\t\\t\\t\\tvertices: data.vertices,\\n\\t\\t\\t\\t\\t\\tattributes: data.attributes,\\n\\t\\t\\t\\t\\t\\tstride: data.stride\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.jobCallbacks.delete(data.jobId);\\n\\t\\t\\t\\tif (this.jobQueue.length > 0) {\\n\\t\\t\\t\\t\\tconst job = this.jobQueue.shift();\\n\\t\\t\\t\\t\\tthis.run(worker, job);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tconst index2 = this.workers[2].indexOf(worker);\\n\\t\\t\\t\\t\\tif (index2 !== -1) {\\n\\t\\t\\t\\t\\t\\tthis.workers[2].splice(index2, 1);\\n\\t\\t\\t\\t\\t\\tthis.workers[1].push(worker);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst index1 = this.workers[1].indexOf(worker);\\n\\t\\t\\t\\t\\t\\tif (index1 !== -1) {\\n\\t\\t\\t\\t\\t\\t\\tthis.workers[1].splice(index1, 1);\\n\\t\\t\\t\\t\\t\\t\\tthis.workers[0].push(worker);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t});\\n\\t\\tthis.workers[0] = workers;\\n\\t\\twhile (this.jobQueue.length && (this.workers[0].length || this.workers[1].length)) {\\n\\t\\t\\tconst job = this.jobQueue.shift();\\n\\t\\t\\tif (this.workers[0].length > 0) {\\n\\t\\t\\t\\tconst worker = this.workers[0].shift();\\n\\t\\t\\t\\tthis.workers[1].push(worker);\\n\\t\\t\\t\\tthis.run(worker, job);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconst worker = this.workers[1].shift();\\n\\t\\t\\t\\tthis.workers[2].push(worker);\\n\\t\\t\\t\\tthis.run(worker, job);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tenqueueJob(buffer, callback) {\\n\\t\\tconst job = {\\n\\t\\t\\tjobId: this.jobId++,\\n\\t\\t\\tbuffer\\n\\t\\t};\\n\\t\\tthis.jobCallbacks.set(job.jobId, callback);\\n\\t\\tif (this.workers[0].length > 0) {\\n\\t\\t\\tconst worker = this.workers[0].shift();\\n\\t\\t\\tthis.workers[1].push(worker);\\n\\t\\t\\tthis.run(worker, job);\\n\\t\\t} else if (this.workers[1].length > 0) {\\n\\t\\t\\tconst worker = this.workers[1].shift();\\n\\t\\t\\tthis.workers[2].push(worker);\\n\\t\\t\\tthis.run(worker, job);\\n\\t\\t} else {\\n\\t\\t\\tthis.jobQueue.push(job);\\n\\t\\t}\\n\\t}\\n}\\nconst downloadScript = (url) => {\\n\\treturn new Promise((resolve, reject) => {\\n\\t\\tconst options = {\\n\\t\\t\\tcache: true,\\n\\t\\t\\tresponseType: \\\"text\\\",\\n\\t\\t\\tretry: downloadMaxRetries > 0,\\n\\t\\t\\tmaxRetries: downloadMaxRetries\\n\\t\\t};\\n\\t\\thttp.get(url, options, (err, response) => {\\n\\t\\t\\tif (err) {\\n\\t\\t\\t\\treject(err);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tresolve(response);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t});\\n};\\nconst compileModule = (url) => {\\n\\tconst compileManual = () => {\\n\\t\\treturn fetch(url).then((result) => result.arrayBuffer()).then((buffer) => WebAssembly.compile(buffer));\\n\\t};\\n\\tconst compileStreaming = () => {\\n\\t\\treturn WebAssembly.compileStreaming(fetch(url)).catch((err) => {\\n\\t\\t\\treturn compileManual();\\n\\t\\t});\\n\\t};\\n\\treturn WebAssembly.compileStreaming ? compileStreaming() : compileManual();\\n};\\nconst defaultNumWorkers$1 = 1;\\nlet jobQueue;\\nconst initializeWorkers = (config) => {\\n\\tif (jobQueue) {\\n\\t\\treturn true;\\n\\t}\\n\\tif (!config) {\\n\\t\\t{\\n\\t\\t\\tconst moduleConfig = WasmModule.getConfig(\\\"DracoDecoderModule\\\");\\n\\t\\t\\tif (moduleConfig) {\\n\\t\\t\\t\\tconfig = {\\n\\t\\t\\t\\t\\tjsUrl: moduleConfig.glueUrl,\\n\\t\\t\\t\\t\\twasmUrl: moduleConfig.wasmUrl,\\n\\t\\t\\t\\t\\tnumWorkers: moduleConfig.numWorkers\\n\\t\\t\\t\\t};\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconfig = {\\n\\t\\t\\t\\t\\tjsUrl: \\\"draco.wasm.js\\\",\\n\\t\\t\\t\\t\\twasmUrl: \\\"draco.wasm.wasm\\\",\\n\\t\\t\\t\\t\\tnumWorkers: defaultNumWorkers$1\\n\\t\\t\\t\\t};\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tif (!config.jsUrl || !config.wasmUrl) {\\n\\t\\treturn false;\\n\\t}\\n\\tjobQueue = new JobQueue();\\n\\tPromise.all([downloadScript(config.jsUrl), compileModule(config.wasmUrl)]).then(([dracoSource, dracoModule]) => {\\n\\t\\tconst code = [\\n\\t\\t\\t\\\"/* draco */\\\",\\n\\t\\t\\tdracoSource,\\n\\t\\t\\t\\\"/* worker */\\\",\\n\\t\\t\\t`(\\n${DracoWorker.toString()}\\n)()\\n\\n`\\n\\t\\t].join(\\\"\\\\n\\\");\\n\\t\\tconst blob = new Blob([code], { type: \\\"application/javascript\\\" });\\n\\t\\tconst workerUrl = URL.createObjectURL(blob);\\n\\t\\tconst numWorkers = Math.max(1, Math.min(16, config.numWorkers || defaultNumWorkers$1));\\n\\t\\tconst workers = [];\\n\\t\\tfor (let i = 0; i < numWorkers; ++i) {\\n\\t\\t\\tconst worker = new Worker(workerUrl);\\n\\t\\t\\tworker.postMessage({\\n\\t\\t\\t\\ttype: \\\"init\\\",\\n\\t\\t\\t\\tmodule: dracoModule\\n\\t\\t\\t});\\n\\t\\t\\tworkers.push(worker);\\n\\t\\t}\\n\\t\\tjobQueue.init(workers);\\n\\t});\\n\\treturn true;\\n};\\nconst dracoDecode = (buffer, callback) => {\\n\\tif (!initializeWorkers()) {\\n\\t\\treturn false;\\n\\t}\\n\\tjobQueue.enqueueJob(buffer, callback);\\n\\treturn true;\\n};\\n\\nclass GlbResources {\\n\\tgltf;\\n\\tnodes;\\n\\tscenes;\\n\\tanimations;\\n\\ttextures;\\n\\tmaterials;\\n\\tvariants;\\n\\tmeshVariants;\\n\\tmeshDefaultMaterials;\\n\\trenders;\\n\\tskins;\\n\\tlights;\\n\\tcameras;\\n\\tnodeInstancingMap;\\n\\tdestroy() {\\n\\t\\tif (this.renders) {\\n\\t\\t\\tthis.renders.forEach((render) => {\\n\\t\\t\\t\\trender.meshes = null;\\n\\t\\t\\t});\\n\\t\\t}\\n\\t}\\n}\\nconst isDataURI = (uri) => {\\n\\treturn /^data:[^\\\\n\\\\r,\\\\u2028\\\\u2029]*,.*$/i.test(uri);\\n};\\nconst getDataURIMimeType = (uri) => {\\n\\treturn uri.substring(uri.indexOf(\\\":\\\") + 1, uri.indexOf(\\\";\\\"));\\n};\\nconst getNumComponents = (accessorType) => {\\n\\tswitch (accessorType) {\\n\\t\\tcase \\\"SCALAR\\\":\\n\\t\\t\\treturn 1;\\n\\t\\tcase \\\"VEC2\\\":\\n\\t\\t\\treturn 2;\\n\\t\\tcase \\\"VEC3\\\":\\n\\t\\t\\treturn 3;\\n\\t\\tcase \\\"VEC4\\\":\\n\\t\\t\\treturn 4;\\n\\t\\tcase \\\"MAT2\\\":\\n\\t\\t\\treturn 4;\\n\\t\\tcase \\\"MAT3\\\":\\n\\t\\t\\treturn 9;\\n\\t\\tcase \\\"MAT4\\\":\\n\\t\\t\\treturn 16;\\n\\t\\tdefault:\\n\\t\\t\\treturn 3;\\n\\t}\\n};\\nconst getComponentType = (componentType) => {\\n\\tswitch (componentType) {\\n\\t\\tcase 5120:\\n\\t\\t\\treturn TYPE_INT8;\\n\\t\\tcase 5121:\\n\\t\\t\\treturn TYPE_UINT8;\\n\\t\\tcase 5122:\\n\\t\\t\\treturn TYPE_INT16;\\n\\t\\tcase 5123:\\n\\t\\t\\treturn TYPE_UINT16;\\n\\t\\tcase 5124:\\n\\t\\t\\treturn TYPE_INT32;\\n\\t\\tcase 5125:\\n\\t\\t\\treturn TYPE_UINT32;\\n\\t\\tcase 5126:\\n\\t\\t\\treturn TYPE_FLOAT32;\\n\\t\\tdefault:\\n\\t\\t\\treturn 0;\\n\\t}\\n};\\nconst getComponentSizeInBytes = (componentType) => {\\n\\tswitch (componentType) {\\n\\t\\tcase 5120:\\n\\t\\t\\treturn 1;\\n\\t\\t// int8\\n\\t\\tcase 5121:\\n\\t\\t\\treturn 1;\\n\\t\\t// uint8\\n\\t\\tcase 5122:\\n\\t\\t\\treturn 2;\\n\\t\\t// int16\\n\\t\\tcase 5123:\\n\\t\\t\\treturn 2;\\n\\t\\t// uint16\\n\\t\\tcase 5124:\\n\\t\\t\\treturn 4;\\n\\t\\t// int32\\n\\t\\tcase 5125:\\n\\t\\t\\treturn 4;\\n\\t\\t// uint32\\n\\t\\tcase 5126:\\n\\t\\t\\treturn 4;\\n\\t\\t// float32\\n\\t\\tdefault:\\n\\t\\t\\treturn 0;\\n\\t}\\n};\\nconst getComponentDataType = (componentType) => {\\n\\tswitch (componentType) {\\n\\t\\tcase 5120:\\n\\t\\t\\treturn Int8Array;\\n\\t\\tcase 5121:\\n\\t\\t\\treturn Uint8Array;\\n\\t\\tcase 5122:\\n\\t\\t\\treturn Int16Array;\\n\\t\\tcase 5123:\\n\\t\\t\\treturn Uint16Array;\\n\\t\\tcase 5124:\\n\\t\\t\\treturn Int32Array;\\n\\t\\tcase 5125:\\n\\t\\t\\treturn Uint32Array;\\n\\t\\tcase 5126:\\n\\t\\t\\treturn Float32Array;\\n\\t\\tdefault:\\n\\t\\t\\treturn null;\\n\\t}\\n};\\nconst gltfToEngineSemanticMap = {\\n\\t\\\"POSITION\\\": SEMANTIC_POSITION,\\n\\t\\\"NORMAL\\\": SEMANTIC_NORMAL,\\n\\t\\\"TANGENT\\\": SEMANTIC_TANGENT,\\n\\t\\\"COLOR_0\\\": SEMANTIC_COLOR,\\n\\t\\\"JOINTS_0\\\": SEMANTIC_BLENDINDICES,\\n\\t\\\"WEIGHTS_0\\\": SEMANTIC_BLENDWEIGHT,\\n\\t\\\"TEXCOORD_0\\\": SEMANTIC_TEXCOORD0,\\n\\t\\\"TEXCOORD_1\\\": SEMANTIC_TEXCOORD1,\\n\\t\\\"TEXCOORD_2\\\": SEMANTIC_TEXCOORD2,\\n\\t\\\"TEXCOORD_3\\\": SEMANTIC_TEXCOORD3,\\n\\t\\\"TEXCOORD_4\\\": SEMANTIC_TEXCOORD4,\\n\\t\\\"TEXCOORD_5\\\": SEMANTIC_TEXCOORD5,\\n\\t\\\"TEXCOORD_6\\\": SEMANTIC_TEXCOORD6,\\n\\t\\\"TEXCOORD_7\\\": SEMANTIC_TEXCOORD7\\n};\\nconst attributeOrder = {\\n\\t[SEMANTIC_POSITION]: 0,\\n\\t[SEMANTIC_NORMAL]: 1,\\n\\t[SEMANTIC_TANGENT]: 2,\\n\\t[SEMANTIC_COLOR]: 3,\\n\\t[SEMANTIC_BLENDINDICES]: 4,\\n\\t[SEMANTIC_BLENDWEIGHT]: 5,\\n\\t[SEMANTIC_TEXCOORD0]: 6,\\n\\t[SEMANTIC_TEXCOORD1]: 7,\\n\\t[SEMANTIC_TEXCOORD2]: 8,\\n\\t[SEMANTIC_TEXCOORD3]: 9,\\n\\t[SEMANTIC_TEXCOORD4]: 10,\\n\\t[SEMANTIC_TEXCOORD5]: 11,\\n\\t[SEMANTIC_TEXCOORD6]: 12,\\n\\t[SEMANTIC_TEXCOORD7]: 13\\n};\\nconst getDequantizeFunc = (srcType) => {\\n\\tswitch (srcType) {\\n\\t\\tcase TYPE_INT8:\\n\\t\\t\\treturn (x) => Math.max(x / 127, -1);\\n\\t\\tcase TYPE_UINT8:\\n\\t\\t\\treturn (x) => x / 255;\\n\\t\\tcase TYPE_INT16:\\n\\t\\t\\treturn (x) => Math.max(x / 32767, -1);\\n\\t\\tcase TYPE_UINT16:\\n\\t\\t\\treturn (x) => x / 65535;\\n\\t\\tdefault:\\n\\t\\t\\treturn (x) => x;\\n\\t}\\n};\\nconst dequantizeArray = (dstArray, srcArray, srcType) => {\\n\\tconst convFunc = getDequantizeFunc(srcType);\\n\\tconst len = srcArray.length;\\n\\tfor (let i = 0; i < len; ++i) {\\n\\t\\tdstArray[i] = convFunc(srcArray[i]);\\n\\t}\\n\\treturn dstArray;\\n};\\nconst getAccessorData = (gltfAccessor, bufferViews, flatten = false) => {\\n\\tconst numComponents = getNumComponents(gltfAccessor.type);\\n\\tconst dataType = getComponentDataType(gltfAccessor.componentType);\\n\\tif (!dataType) {\\n\\t\\treturn null;\\n\\t}\\n\\tlet result;\\n\\tif (gltfAccessor.sparse) {\\n\\t\\tconst sparse = gltfAccessor.sparse;\\n\\t\\tconst indicesAccessor = {\\n\\t\\t\\tcount: sparse.count,\\n\\t\\t\\ttype: \\\"SCALAR\\\"\\n\\t\\t};\\n\\t\\tconst indices = getAccessorData(Object.assign(indicesAccessor, sparse.indices), bufferViews, true);\\n\\t\\tconst valuesAccessor = {\\n\\t\\t\\tcount: sparse.count,\\n\\t\\t\\ttype: gltfAccessor.type,\\n\\t\\t\\tcomponentType: gltfAccessor.componentType\\n\\t\\t};\\n\\t\\tconst values = getAccessorData(Object.assign(valuesAccessor, sparse.values), bufferViews, true);\\n\\t\\tif (gltfAccessor.hasOwnProperty(\\\"bufferView\\\")) {\\n\\t\\t\\tconst baseAccessor = {\\n\\t\\t\\t\\tbufferView: gltfAccessor.bufferView,\\n\\t\\t\\t\\tbyteOffset: gltfAccessor.byteOffset,\\n\\t\\t\\t\\tcomponentType: gltfAccessor.componentType,\\n\\t\\t\\t\\tcount: gltfAccessor.count,\\n\\t\\t\\t\\ttype: gltfAccessor.type\\n\\t\\t\\t};\\n\\t\\t\\tresult = getAccessorData(baseAccessor, bufferViews, true).slice();\\n\\t\\t} else {\\n\\t\\t\\tresult = new dataType(gltfAccessor.count * numComponents);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < sparse.count; ++i) {\\n\\t\\t\\tconst targetIndex = indices[i];\\n\\t\\t\\tfor (let j = 0; j < numComponents; ++j) {\\n\\t\\t\\t\\tresult[targetIndex * numComponents + j] = values[i * numComponents + j];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t} else {\\n\\t\\tif (gltfAccessor.hasOwnProperty(\\\"bufferView\\\")) {\\n\\t\\t\\tconst bufferView = bufferViews[gltfAccessor.bufferView];\\n\\t\\t\\tif (flatten && bufferView.hasOwnProperty(\\\"byteStride\\\")) {\\n\\t\\t\\t\\tconst bytesPerElement = numComponents * dataType.BYTES_PER_ELEMENT;\\n\\t\\t\\t\\tconst storage = new ArrayBuffer(gltfAccessor.count * bytesPerElement);\\n\\t\\t\\t\\tconst tmpArray = new Uint8Array(storage);\\n\\t\\t\\t\\tlet dstOffset = 0;\\n\\t\\t\\t\\tfor (let i = 0; i < gltfAccessor.count; ++i) {\\n\\t\\t\\t\\t\\tlet srcOffset = (gltfAccessor.byteOffset || 0) + i * bufferView.byteStride;\\n\\t\\t\\t\\t\\tfor (let b = 0; b < bytesPerElement; ++b) {\\n\\t\\t\\t\\t\\t\\ttmpArray[dstOffset++] = bufferView[srcOffset++];\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tresult = new dataType(storage);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tresult = new dataType(\\n\\t\\t\\t\\t\\tbufferView.buffer,\\n\\t\\t\\t\\t\\tbufferView.byteOffset + (gltfAccessor.byteOffset || 0),\\n\\t\\t\\t\\t\\tgltfAccessor.count * numComponents\\n\\t\\t\\t\\t);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tresult = new dataType(gltfAccessor.count * numComponents);\\n\\t\\t}\\n\\t}\\n\\treturn result;\\n};\\nconst getAccessorDataFloat32 = (gltfAccessor, bufferViews) => {\\n\\tconst data = getAccessorData(gltfAccessor, bufferViews, true);\\n\\tif (data instanceof Float32Array || !gltfAccessor.normalized) {\\n\\t\\treturn data;\\n\\t}\\n\\tconst float32Data = new Float32Array(data.length);\\n\\tdequantizeArray(float32Data, data, getComponentType(gltfAccessor.componentType));\\n\\treturn float32Data;\\n};\\nconst getAccessorBoundingBox = (gltfAccessor) => {\\n\\tlet min = gltfAccessor.min;\\n\\tlet max = gltfAccessor.max;\\n\\tif (!min || !max) {\\n\\t\\treturn null;\\n\\t}\\n\\tif (gltfAccessor.normalized) {\\n\\t\\tconst ctype = getComponentType(gltfAccessor.componentType);\\n\\t\\tmin = dequantizeArray([], min, ctype);\\n\\t\\tmax = dequantizeArray([], max, ctype);\\n\\t}\\n\\treturn new BoundingBox(\\n\\t\\tnew Vec3((max[0] + min[0]) * 0.5, (max[1] + min[1]) * 0.5, (max[2] + min[2]) * 0.5),\\n\\t\\tnew Vec3((max[0] - min[0]) * 0.5, (max[1] - min[1]) * 0.5, (max[2] - min[2]) * 0.5)\\n\\t);\\n};\\nconst getPrimitiveType = (primitive) => {\\n\\tif (!primitive.hasOwnProperty(\\\"mode\\\")) {\\n\\t\\treturn PRIMITIVE_TRIANGLES;\\n\\t}\\n\\tswitch (primitive.mode) {\\n\\t\\tcase 0:\\n\\t\\t\\treturn PRIMITIVE_POINTS;\\n\\t\\tcase 1:\\n\\t\\t\\treturn PRIMITIVE_LINES;\\n\\t\\tcase 2:\\n\\t\\t\\treturn PRIMITIVE_LINELOOP;\\n\\t\\tcase 3:\\n\\t\\t\\treturn PRIMITIVE_LINESTRIP;\\n\\t\\tcase 4:\\n\\t\\t\\treturn PRIMITIVE_TRIANGLES;\\n\\t\\tcase 5:\\n\\t\\t\\treturn PRIMITIVE_TRISTRIP;\\n\\t\\tcase 6:\\n\\t\\t\\treturn PRIMITIVE_TRIFAN;\\n\\t\\tdefault:\\n\\t\\t\\treturn PRIMITIVE_TRIANGLES;\\n\\t}\\n};\\nconst generateIndices = (numVertices) => {\\n\\tconst dummyIndices = new Uint16Array(numVertices);\\n\\tfor (let i = 0; i < numVertices; i++) {\\n\\t\\tdummyIndices[i] = i;\\n\\t}\\n\\treturn dummyIndices;\\n};\\nconst generateNormals = (sourceDesc, indices) => {\\n\\tconst p = sourceDesc[SEMANTIC_POSITION];\\n\\tif (!p || p.components !== 3) {\\n\\t\\treturn;\\n\\t}\\n\\tlet positions;\\n\\tif (p.size !== p.stride) {\\n\\t\\tconst srcStride = p.stride / typedArrayTypesByteSize[p.type];\\n\\t\\tconst src = new typedArrayTypes[p.type](p.buffer, p.offset, p.count * srcStride);\\n\\t\\tpositions = new typedArrayTypes[p.type](p.count * 3);\\n\\t\\tfor (let i = 0; i < p.count; ++i) {\\n\\t\\t\\tpositions[i * 3 + 0] = src[i * srcStride + 0];\\n\\t\\t\\tpositions[i * 3 + 1] = src[i * srcStride + 1];\\n\\t\\t\\tpositions[i * 3 + 2] = src[i * srcStride + 2];\\n\\t\\t}\\n\\t} else {\\n\\t\\tpositions = new typedArrayTypes[p.type](p.buffer, p.offset, p.count * 3);\\n\\t}\\n\\tconst numVertices = p.count;\\n\\tif (!indices) {\\n\\t\\tindices = generateIndices(numVertices);\\n\\t}\\n\\tconst normalsTemp = calculateNormals(positions, indices);\\n\\tconst normals = new Float32Array(normalsTemp.length);\\n\\tnormals.set(normalsTemp);\\n\\tsourceDesc[SEMANTIC_NORMAL] = {\\n\\t\\tbuffer: normals.buffer,\\n\\t\\tsize: 12,\\n\\t\\toffset: 0,\\n\\t\\tstride: 12,\\n\\t\\tcount: numVertices,\\n\\t\\tcomponents: 3,\\n\\t\\ttype: TYPE_FLOAT32\\n\\t};\\n};\\nconst cloneTexture = (texture) => {\\n\\tconst shallowCopyLevels = (texture2) => {\\n\\t\\tconst result2 = [];\\n\\t\\tfor (let mip = 0; mip < texture2._levels.length; ++mip) {\\n\\t\\t\\tlet level = [];\\n\\t\\t\\tif (texture2.cubemap) {\\n\\t\\t\\t\\tfor (let face = 0; face < 6; ++face) {\\n\\t\\t\\t\\t\\tlevel.push(texture2._levels[mip][face]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tlevel = texture2._levels[mip];\\n\\t\\t\\t}\\n\\t\\t\\tresult2.push(level);\\n\\t\\t}\\n\\t\\treturn result2;\\n\\t};\\n\\tconst result = new Texture(texture.device, texture);\\n\\tresult._levels = shallowCopyLevels(texture);\\n\\treturn result;\\n};\\nconst cloneTextureAsset = (src) => {\\n\\tconst result = new Asset(\\n\\t\\t`${src.name}_clone`,\\n\\t\\tsrc.type,\\n\\t\\tsrc.file,\\n\\t\\tsrc.data,\\n\\t\\tsrc.options\\n\\t);\\n\\tresult.loaded = true;\\n\\tresult.resource = cloneTexture(src.resource);\\n\\tsrc.registry.add(result);\\n\\treturn result;\\n};\\nconst createVertexBufferInternal = (device, sourceDesc) => {\\n\\tconst positionDesc = sourceDesc[SEMANTIC_POSITION];\\n\\tif (!positionDesc) {\\n\\t\\treturn null;\\n\\t}\\n\\tconst numVertices = positionDesc.count;\\n\\tconst vertexDesc = [];\\n\\tfor (const semantic in sourceDesc) {\\n\\t\\tif (sourceDesc.hasOwnProperty(semantic)) {\\n\\t\\t\\tconst element = {\\n\\t\\t\\t\\tsemantic,\\n\\t\\t\\t\\tcomponents: sourceDesc[semantic].components,\\n\\t\\t\\t\\ttype: sourceDesc[semantic].type,\\n\\t\\t\\t\\tnormalize: !!sourceDesc[semantic].normalize\\n\\t\\t\\t};\\n\\t\\t\\tif (!VertexFormat.isElementValid(device, element)) {\\n\\t\\t\\t\\telement.components++;\\n\\t\\t\\t}\\n\\t\\t\\tvertexDesc.push(element);\\n\\t\\t}\\n\\t}\\n\\tvertexDesc.sort((lhs, rhs) => {\\n\\t\\treturn attributeOrder[lhs.semantic] - attributeOrder[rhs.semantic];\\n\\t});\\n\\tlet i, j, k;\\n\\tlet source, target, sourceOffset;\\n\\tconst vertexFormat = new VertexFormat(device, vertexDesc);\\n\\tlet isCorrectlyInterleaved = true;\\n\\tfor (i = 0; i < vertexFormat.elements.length; ++i) {\\n\\t\\ttarget = vertexFormat.elements[i];\\n\\t\\tsource = sourceDesc[target.name];\\n\\t\\tsourceOffset = source.offset - positionDesc.offset;\\n\\t\\tif (source.buffer !== positionDesc.buffer || source.stride !== target.stride || source.size !== target.size || sourceOffset !== target.offset) {\\n\\t\\t\\tisCorrectlyInterleaved = false;\\n\\t\\t\\tbreak;\\n\\t\\t}\\n\\t}\\n\\tconst vertexBuffer = new VertexBuffer(device, vertexFormat, numVertices);\\n\\tconst vertexData = vertexBuffer.lock();\\n\\tconst targetArray = new Uint32Array(vertexData);\\n\\tlet sourceArray;\\n\\tif (isCorrectlyInterleaved) {\\n\\t\\tsourceArray = new Uint32Array(\\n\\t\\t\\tpositionDesc.buffer,\\n\\t\\t\\tpositionDesc.offset,\\n\\t\\t\\tnumVertices * vertexBuffer.format.size / 4\\n\\t\\t);\\n\\t\\ttargetArray.set(sourceArray);\\n\\t} else {\\n\\t\\tlet targetStride, sourceStride;\\n\\t\\tfor (i = 0; i < vertexBuffer.format.elements.length; ++i) {\\n\\t\\t\\ttarget = vertexBuffer.format.elements[i];\\n\\t\\t\\ttargetStride = target.stride / 4;\\n\\t\\t\\tsource = sourceDesc[target.name];\\n\\t\\t\\tsourceStride = source.stride / 4;\\n\\t\\t\\tsourceArray = new Uint32Array(source.buffer, source.offset, (source.count - 1) * sourceStride + (source.size + 3) / 4);\\n\\t\\t\\tlet src = 0;\\n\\t\\t\\tlet dst = target.offset / 4;\\n\\t\\t\\tconst kend = Math.floor((source.size + 3) / 4);\\n\\t\\t\\tfor (j = 0; j < numVertices; ++j) {\\n\\t\\t\\t\\tfor (k = 0; k < kend; ++k) {\\n\\t\\t\\t\\t\\ttargetArray[dst + k] = sourceArray[src + k];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tsrc += sourceStride;\\n\\t\\t\\t\\tdst += targetStride;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tvertexBuffer.unlock();\\n\\treturn vertexBuffer;\\n};\\nconst createVertexBuffer = (device, attributes, indices, accessors, bufferViews, vertexBufferDict) => {\\n\\tconst useAttributes = {};\\n\\tconst attribIds = [];\\n\\tfor (const attrib in attributes) {\\n\\t\\tif (attributes.hasOwnProperty(attrib) && gltfToEngineSemanticMap.hasOwnProperty(attrib)) {\\n\\t\\t\\tuseAttributes[attrib] = attributes[attrib];\\n\\t\\t\\tattribIds.push(`${attrib}:${attributes[attrib]}`);\\n\\t\\t}\\n\\t}\\n\\tattribIds.sort();\\n\\tconst vbKey = attribIds.join();\\n\\tlet vb = vertexBufferDict[vbKey];\\n\\tif (!vb) {\\n\\t\\tconst sourceDesc = {};\\n\\t\\tfor (const attrib in useAttributes) {\\n\\t\\t\\tconst accessor = accessors[attributes[attrib]];\\n\\t\\t\\tconst accessorData = getAccessorData(accessor, bufferViews);\\n\\t\\t\\tconst bufferView = bufferViews[accessor.bufferView];\\n\\t\\t\\tconst semantic = gltfToEngineSemanticMap[attrib];\\n\\t\\t\\tconst size = getNumComponents(accessor.type) * getComponentSizeInBytes(accessor.componentType);\\n\\t\\t\\tconst stride = bufferView && bufferView.hasOwnProperty(\\\"byteStride\\\") ? bufferView.byteStride : size;\\n\\t\\t\\tsourceDesc[semantic] = {\\n\\t\\t\\t\\tbuffer: accessorData.buffer,\\n\\t\\t\\t\\tsize,\\n\\t\\t\\t\\toffset: accessorData.byteOffset,\\n\\t\\t\\t\\tstride,\\n\\t\\t\\t\\tcount: accessor.count,\\n\\t\\t\\t\\tcomponents: getNumComponents(accessor.type),\\n\\t\\t\\t\\ttype: getComponentType(accessor.componentType),\\n\\t\\t\\t\\tnormalize: accessor.normalized\\n\\t\\t\\t};\\n\\t\\t}\\n\\t\\tif (!sourceDesc.hasOwnProperty(SEMANTIC_NORMAL)) {\\n\\t\\t\\tgenerateNormals(sourceDesc, indices);\\n\\t\\t}\\n\\t\\tvb = createVertexBufferInternal(device, sourceDesc);\\n\\t\\tvertexBufferDict[vbKey] = vb;\\n\\t}\\n\\treturn vb;\\n};\\nconst createSkin = (device, gltfSkin, accessors, bufferViews, nodes, glbSkins) => {\\n\\tlet i, j, bindMatrix;\\n\\tconst joints = gltfSkin.joints;\\n\\tconst numJoints = joints.length;\\n\\tconst ibp = [];\\n\\tif (gltfSkin.hasOwnProperty(\\\"inverseBindMatrices\\\")) {\\n\\t\\tconst inverseBindMatrices = gltfSkin.inverseBindMatrices;\\n\\t\\tconst ibmData = getAccessorData(accessors[inverseBindMatrices], bufferViews, true);\\n\\t\\tconst ibmValues = [];\\n\\t\\tfor (i = 0; i < numJoints; i++) {\\n\\t\\t\\tfor (j = 0; j < 16; j++) {\\n\\t\\t\\t\\tibmValues[j] = ibmData[i * 16 + j];\\n\\t\\t\\t}\\n\\t\\t\\tbindMatrix = new Mat4();\\n\\t\\t\\tbindMatrix.set(ibmValues);\\n\\t\\t\\tibp.push(bindMatrix);\\n\\t\\t}\\n\\t} else {\\n\\t\\tfor (i = 0; i < numJoints; i++) {\\n\\t\\t\\tbindMatrix = new Mat4();\\n\\t\\t\\tibp.push(bindMatrix);\\n\\t\\t}\\n\\t}\\n\\tconst boneNames = [];\\n\\tfor (i = 0; i < numJoints; i++) {\\n\\t\\tboneNames[i] = nodes[joints[i]].name;\\n\\t}\\n\\tconst key = boneNames.join(\\\"#\\\");\\n\\tlet skin = glbSkins.get(key);\\n\\tif (!skin) {\\n\\t\\tskin = new Skin(device, ibp, boneNames);\\n\\t\\tglbSkins.set(key, skin);\\n\\t}\\n\\treturn skin;\\n};\\nconst createDracoMesh = (device, primitive, accessors, bufferViews, meshVariants, meshDefaultMaterials, promises) => {\\n\\tconst result = new Mesh(device);\\n\\tresult.aabb = getAccessorBoundingBox(accessors[primitive.attributes.POSITION]);\\n\\tpromises.push(new Promise((resolve, reject) => {\\n\\t\\tconst dracoExt = primitive.extensions.KHR_draco_mesh_compression;\\n\\t\\tdracoDecode(bufferViews[dracoExt.bufferView].slice().buffer, (err, decompressedData) => {\\n\\t\\t\\tif (err) {\\n\\t\\t\\t\\tconsole.log(err);\\n\\t\\t\\t\\treject(err);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconst idToSemantic = {};\\n\\t\\t\\t\\tfor (const [name, id] of Object.entries(dracoExt.attributes)) {\\n\\t\\t\\t\\t\\tidToSemantic[id] = gltfToEngineSemanticMap[name];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tidToSemantic[-1] = SEMANTIC_NORMAL;\\n\\t\\t\\t\\tconst vertexDesc = [];\\n\\t\\t\\t\\tfor (const attr of decompressedData.attributes) {\\n\\t\\t\\t\\t\\tconst semantic = idToSemantic[attr.id];\\n\\t\\t\\t\\t\\tif (semantic !== void 0) {\\n\\t\\t\\t\\t\\t\\tlet normalize = false;\\n\\t\\t\\t\\t\\t\\tif (attr.id !== -1) {\\n\\t\\t\\t\\t\\t\\t\\tfor (const [name, id] of Object.entries(dracoExt.attributes)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (id === attr.id && primitive.attributes[name] !== void 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tconst accessor = accessors[primitive.attributes[name]];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tnormalize = accessor.normalized ?? (semantic === SEMANTIC_COLOR && (attr.dataType === TYPE_UINT8 || attr.dataType === TYPE_UINT16));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tvertexDesc.push({\\n\\t\\t\\t\\t\\t\\t\\tsemantic,\\n\\t\\t\\t\\t\\t\\t\\tcomponents: attr.numComponents,\\n\\t\\t\\t\\t\\t\\t\\ttype: attr.dataType,\\n\\t\\t\\t\\t\\t\\t\\tnormalize,\\n\\t\\t\\t\\t\\t\\t\\t// use offset and stride from worker to handle cases where Draco mesh\\n\\t\\t\\t\\t\\t\\t\\t// has additional attributes not listed in glTF\\n\\t\\t\\t\\t\\t\\t\\toffset: attr.offset,\\n\\t\\t\\t\\t\\t\\t\\tstride: decompressedData.stride\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst vertexFormat = new VertexFormat(device, vertexDesc);\\n\\t\\t\\t\\tconst numVertices = decompressedData.vertices.byteLength / decompressedData.stride;\\n\\t\\t\\t\\tconst indexFormat = numVertices <= 65535 ? INDEXFORMAT_UINT16 : INDEXFORMAT_UINT32;\\n\\t\\t\\t\\tconst numIndices = decompressedData.indices.byteLength / (numVertices <= 65535 ? 2 : 4);\\n\\t\\t\\t\\tconst vertexBuffer = new VertexBuffer(device, vertexFormat, numVertices, {\\n\\t\\t\\t\\t\\tdata: decompressedData.vertices\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst indexBuffer = new IndexBuffer(device, indexFormat, numIndices, BUFFER_STATIC, decompressedData.indices);\\n\\t\\t\\t\\tresult.vertexBuffer = vertexBuffer;\\n\\t\\t\\t\\tresult.indexBuffer[0] = indexBuffer;\\n\\t\\t\\t\\tresult.primitive[0].type = getPrimitiveType(primitive);\\n\\t\\t\\t\\tresult.primitive[0].base = 0;\\n\\t\\t\\t\\tresult.primitive[0].count = indexBuffer ? numIndices : numVertices;\\n\\t\\t\\t\\tresult.primitive[0].indexed = !!indexBuffer;\\n\\t\\t\\t\\tresolve();\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}));\\n\\tif (primitive?.extensions?.KHR_materials_variants) {\\n\\t\\tconst variants = primitive.extensions.KHR_materials_variants;\\n\\t\\tconst tempMapping = {};\\n\\t\\tvariants.mappings.forEach((mapping) => {\\n\\t\\t\\tmapping.variants.forEach((variant) => {\\n\\t\\t\\t\\ttempMapping[variant] = mapping.material;\\n\\t\\t\\t});\\n\\t\\t});\\n\\t\\tmeshVariants[result.id] = tempMapping;\\n\\t}\\n\\tmeshDefaultMaterials[result.id] = primitive.material;\\n\\treturn result;\\n};\\nconst createMesh = (device, gltfMesh, accessors, bufferViews, vertexBufferDict, meshVariants, meshDefaultMaterials, assetOptions, promises) => {\\n\\tconst meshes = [];\\n\\tgltfMesh.primitives.forEach((primitive) => {\\n\\t\\tif (primitive.extensions?.KHR_draco_mesh_compression) {\\n\\t\\t\\tmeshes.push(createDracoMesh(device, primitive, accessors, bufferViews, meshVariants, meshDefaultMaterials, promises));\\n\\t\\t} else {\\n\\t\\t\\tlet indices = primitive.hasOwnProperty(\\\"indices\\\") ? getAccessorData(accessors[primitive.indices], bufferViews, true) : null;\\n\\t\\t\\tconst vertexBuffer = createVertexBuffer(device, primitive.attributes, indices, accessors, bufferViews, vertexBufferDict);\\n\\t\\t\\tconst primitiveType = getPrimitiveType(primitive);\\n\\t\\t\\tconst mesh = new Mesh(device);\\n\\t\\t\\tmesh.vertexBuffer = vertexBuffer;\\n\\t\\t\\tmesh.primitive[0].type = primitiveType;\\n\\t\\t\\tmesh.primitive[0].base = 0;\\n\\t\\t\\tmesh.primitive[0].indexed = indices !== null;\\n\\t\\t\\tif (indices !== null) {\\n\\t\\t\\t\\tlet indexFormat;\\n\\t\\t\\t\\tif (indices instanceof Uint8Array) {\\n\\t\\t\\t\\t\\tindexFormat = INDEXFORMAT_UINT8;\\n\\t\\t\\t\\t} else if (indices instanceof Uint16Array) {\\n\\t\\t\\t\\t\\tindexFormat = INDEXFORMAT_UINT16;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tindexFormat = INDEXFORMAT_UINT32;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (indexFormat === INDEXFORMAT_UINT8 && device.isWebGPU) {\\n\\t\\t\\t\\t\\tindexFormat = INDEXFORMAT_UINT16;\\n\\t\\t\\t\\t\\tindices = new Uint16Array(indices);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst indexBuffer = new IndexBuffer(device, indexFormat, indices.length, BUFFER_STATIC, indices);\\n\\t\\t\\t\\tmesh.indexBuffer[0] = indexBuffer;\\n\\t\\t\\t\\tmesh.primitive[0].count = indices.length;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tmesh.primitive[0].count = vertexBuffer.numVertices;\\n\\t\\t\\t}\\n\\t\\t\\tif (primitive.hasOwnProperty(\\\"extensions\\\") && primitive.extensions.hasOwnProperty(\\\"KHR_materials_variants\\\")) {\\n\\t\\t\\t\\tconst variants = primitive.extensions.KHR_materials_variants;\\n\\t\\t\\t\\tconst tempMapping = {};\\n\\t\\t\\t\\tvariants.mappings.forEach((mapping) => {\\n\\t\\t\\t\\t\\tmapping.variants.forEach((variant) => {\\n\\t\\t\\t\\t\\t\\ttempMapping[variant] = mapping.material;\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tmeshVariants[mesh.id] = tempMapping;\\n\\t\\t\\t}\\n\\t\\t\\tmeshDefaultMaterials[mesh.id] = primitive.material;\\n\\t\\t\\tlet accessor = accessors[primitive.attributes.POSITION];\\n\\t\\t\\tmesh.aabb = getAccessorBoundingBox(accessor);\\n\\t\\t\\tif (primitive.hasOwnProperty(\\\"targets\\\")) {\\n\\t\\t\\t\\tconst targets = [];\\n\\t\\t\\t\\tprimitive.targets.forEach((target, index) => {\\n\\t\\t\\t\\t\\tconst options = {};\\n\\t\\t\\t\\t\\tif (target.hasOwnProperty(\\\"POSITION\\\")) {\\n\\t\\t\\t\\t\\t\\taccessor = accessors[target.POSITION];\\n\\t\\t\\t\\t\\t\\toptions.deltaPositions = getAccessorDataFloat32(accessor, bufferViews);\\n\\t\\t\\t\\t\\t\\toptions.aabb = getAccessorBoundingBox(accessor);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (target.hasOwnProperty(\\\"NORMAL\\\")) {\\n\\t\\t\\t\\t\\t\\taccessor = accessors[target.NORMAL];\\n\\t\\t\\t\\t\\t\\toptions.deltaNormals = getAccessorDataFloat32(accessor, bufferViews);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (gltfMesh.hasOwnProperty(\\\"extras\\\") && gltfMesh.extras.hasOwnProperty(\\\"targetNames\\\")) {\\n\\t\\t\\t\\t\\t\\toptions.name = gltfMesh.extras.targetNames[index];\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\toptions.name = index.toString(10);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (gltfMesh.hasOwnProperty(\\\"weights\\\")) {\\n\\t\\t\\t\\t\\t\\toptions.defaultWeight = gltfMesh.weights[index];\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\toptions.preserveData = assetOptions.morphPreserveData;\\n\\t\\t\\t\\t\\ttargets.push(new MorphTarget(options));\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tmesh.morph = new Morph(targets, device, {\\n\\t\\t\\t\\t\\tpreferHighPrecision: assetOptions.morphPreferHighPrecision\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t\\tmeshes.push(mesh);\\n\\t\\t}\\n\\t});\\n\\treturn meshes;\\n};\\nconst extractTextureTransform = (source, material, maps) => {\\n\\tlet map;\\n\\tconst texCoord = source.texCoord;\\n\\tif (texCoord) {\\n\\t\\tfor (map = 0; map < maps.length; ++map) {\\n\\t\\t\\tmaterial[`${maps[map]}MapUv`] = texCoord;\\n\\t\\t}\\n\\t}\\n\\tconst zeros = [0, 0];\\n\\tconst ones = [1, 1];\\n\\tconst textureTransform = source.extensions?.KHR_texture_transform;\\n\\tif (textureTransform) {\\n\\t\\tconst offset = textureTransform.offset || zeros;\\n\\t\\tconst scale = textureTransform.scale || ones;\\n\\t\\tconst rotation = textureTransform.rotation ? -textureTransform.rotation * math.RAD_TO_DEG : 0;\\n\\t\\tconst tilingVec = new Vec2(scale[0], scale[1]);\\n\\t\\tconst offsetVec = new Vec2(offset[0], 1 - scale[1] - offset[1]);\\n\\t\\tfor (map = 0; map < maps.length; ++map) {\\n\\t\\t\\tmaterial[`${maps[map]}MapTiling`] = tilingVec;\\n\\t\\t\\tmaterial[`${maps[map]}MapOffset`] = offsetVec;\\n\\t\\t\\tmaterial[`${maps[map]}MapRotation`] = rotation;\\n\\t\\t}\\n\\t}\\n};\\nconst extensionPbrSpecGlossiness = (data, material, textures) => {\\n\\tlet texture;\\n\\tif (data.hasOwnProperty(\\\"diffuseFactor\\\")) {\\n\\t\\tconst [r, g, b, a] = data.diffuseFactor;\\n\\t\\tmaterial.diffuse.set(r, g, b).gamma();\\n\\t\\tmaterial.opacity = a;\\n\\t} else {\\n\\t\\tmaterial.diffuse.set(1, 1, 1);\\n\\t\\tmaterial.opacity = 1;\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"diffuseTexture\\\")) {\\n\\t\\tconst diffuseTexture = data.diffuseTexture;\\n\\t\\ttexture = textures[diffuseTexture.index];\\n\\t\\tmaterial.diffuseMap = texture;\\n\\t\\tmaterial.diffuseMapChannel = \\\"rgb\\\";\\n\\t\\tmaterial.opacityMap = texture;\\n\\t\\tmaterial.opacityMapChannel = \\\"a\\\";\\n\\t\\textractTextureTransform(diffuseTexture, material, [\\\"diffuse\\\", \\\"opacity\\\"]);\\n\\t}\\n\\tmaterial.useMetalness = false;\\n\\tif (data.hasOwnProperty(\\\"specularFactor\\\")) {\\n\\t\\tconst [r, g, b] = data.specularFactor;\\n\\t\\tmaterial.specular.set(r, g, b).gamma();\\n\\t} else {\\n\\t\\tmaterial.specular.set(1, 1, 1);\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"glossinessFactor\\\")) {\\n\\t\\tmaterial.gloss = data.glossinessFactor;\\n\\t} else {\\n\\t\\tmaterial.gloss = 1;\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"specularGlossinessTexture\\\")) {\\n\\t\\tconst specularGlossinessTexture = data.specularGlossinessTexture;\\n\\t\\tmaterial.specularMap = material.glossMap = textures[specularGlossinessTexture.index];\\n\\t\\tmaterial.specularMapChannel = \\\"rgb\\\";\\n\\t\\tmaterial.glossMapChannel = \\\"a\\\";\\n\\t\\textractTextureTransform(specularGlossinessTexture, material, [\\\"gloss\\\", \\\"metalness\\\"]);\\n\\t}\\n};\\nconst extensionClearCoat = (data, material, textures) => {\\n\\tif (data.hasOwnProperty(\\\"clearcoatFactor\\\")) {\\n\\t\\tmaterial.clearCoat = data.clearcoatFactor * 0.25;\\n\\t} else {\\n\\t\\tmaterial.clearCoat = 0;\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"clearcoatTexture\\\")) {\\n\\t\\tconst clearcoatTexture = data.clearcoatTexture;\\n\\t\\tmaterial.clearCoatMap = textures[clearcoatTexture.index];\\n\\t\\tmaterial.clearCoatMapChannel = \\\"r\\\";\\n\\t\\textractTextureTransform(clearcoatTexture, material, [\\\"clearCoat\\\"]);\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"clearcoatRoughnessFactor\\\")) {\\n\\t\\tmaterial.clearCoatGloss = data.clearcoatRoughnessFactor;\\n\\t} else {\\n\\t\\tmaterial.clearCoatGloss = 0;\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"clearcoatRoughnessTexture\\\")) {\\n\\t\\tconst clearcoatRoughnessTexture = data.clearcoatRoughnessTexture;\\n\\t\\tmaterial.clearCoatGlossMap = textures[clearcoatRoughnessTexture.index];\\n\\t\\tmaterial.clearCoatGlossMapChannel = \\\"g\\\";\\n\\t\\textractTextureTransform(clearcoatRoughnessTexture, material, [\\\"clearCoatGloss\\\"]);\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"clearcoatNormalTexture\\\")) {\\n\\t\\tconst clearcoatNormalTexture = data.clearcoatNormalTexture;\\n\\t\\tmaterial.clearCoatNormalMap = textures[clearcoatNormalTexture.index];\\n\\t\\textractTextureTransform(clearcoatNormalTexture, material, [\\\"clearCoatNormal\\\"]);\\n\\t\\tif (clearcoatNormalTexture.hasOwnProperty(\\\"scale\\\")) {\\n\\t\\t\\tmaterial.clearCoatBumpiness = clearcoatNormalTexture.scale;\\n\\t\\t} else {\\n\\t\\t\\tmaterial.clearCoatBumpiness = 1;\\n\\t\\t}\\n\\t}\\n\\tmaterial.clearCoatGlossInvert = true;\\n};\\nconst extensionUnlit = (data, material, textures) => {\\n\\tmaterial.useLighting = false;\\n\\tmaterial.emissive.copy(material.diffuse);\\n\\tmaterial.emissiveMap = material.diffuseMap;\\n\\tmaterial.emissiveMapUv = material.diffuseMapUv;\\n\\tmaterial.emissiveMapTiling.copy(material.diffuseMapTiling);\\n\\tmaterial.emissiveMapOffset.copy(material.diffuseMapOffset);\\n\\tmaterial.emissiveMapRotation = material.diffuseMapRotation;\\n\\tmaterial.emissiveMapChannel = material.diffuseMapChannel;\\n\\tmaterial.emissiveVertexColor = material.diffuseVertexColor;\\n\\tmaterial.emissiveVertexColorChannel = material.diffuseVertexColorChannel;\\n\\tmaterial.useLighting = false;\\n\\tmaterial.useSkybox = false;\\n\\tmaterial.diffuse.set(1, 1, 1);\\n\\tmaterial.diffuseMap = null;\\n\\tmaterial.diffuseVertexColor = false;\\n};\\nconst extensionSpecular = (data, material, textures) => {\\n\\tmaterial.useMetalnessSpecularColor = true;\\n\\tif (data.hasOwnProperty(\\\"specularColorTexture\\\")) {\\n\\t\\tmaterial.specularMap = textures[data.specularColorTexture.index];\\n\\t\\tmaterial.specularMapChannel = \\\"rgb\\\";\\n\\t\\textractTextureTransform(data.specularColorTexture, material, [\\\"specular\\\"]);\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"specularColorFactor\\\")) {\\n\\t\\tconst [r, g, b] = data.specularColorFactor;\\n\\t\\tmaterial.specular.set(r, g, b).gamma();\\n\\t} else {\\n\\t\\tmaterial.specular.set(1, 1, 1);\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"specularFactor\\\")) {\\n\\t\\tmaterial.specularityFactor = data.specularFactor;\\n\\t} else {\\n\\t\\tmaterial.specularityFactor = 1;\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"specularTexture\\\")) {\\n\\t\\tmaterial.specularityFactorMapChannel = \\\"a\\\";\\n\\t\\tmaterial.specularityFactorMap = textures[data.specularTexture.index];\\n\\t\\textractTextureTransform(data.specularTexture, material, [\\\"specularityFactor\\\"]);\\n\\t}\\n};\\nconst extensionIor = (data, material, textures) => {\\n\\tif (data.hasOwnProperty(\\\"ior\\\")) {\\n\\t\\tmaterial.refractionIndex = 1 / data.ior;\\n\\t}\\n};\\nconst extensionDispersion = (data, material, textures) => {\\n\\tif (data.hasOwnProperty(\\\"dispersion\\\")) {\\n\\t\\tmaterial.dispersion = data.dispersion;\\n\\t}\\n};\\nconst extensionTransmission = (data, material, textures) => {\\n\\tmaterial.blendType = BLEND_NORMAL;\\n\\tmaterial.useDynamicRefraction = true;\\n\\tif (data.hasOwnProperty(\\\"transmissionFactor\\\")) {\\n\\t\\tmaterial.refraction = data.transmissionFactor;\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"transmissionTexture\\\")) {\\n\\t\\tmaterial.refractionMapChannel = \\\"r\\\";\\n\\t\\tmaterial.refractionMap = textures[data.transmissionTexture.index];\\n\\t\\textractTextureTransform(data.transmissionTexture, material, [\\\"refraction\\\"]);\\n\\t}\\n};\\nconst extensionSheen = (data, material, textures) => {\\n\\tmaterial.useSheen = true;\\n\\tif (data.hasOwnProperty(\\\"sheenColorFactor\\\")) {\\n\\t\\tconst [r, g, b] = data.sheenColorFactor;\\n\\t\\tmaterial.sheen.set(r, g, b).gamma();\\n\\t} else {\\n\\t\\tmaterial.sheen.set(1, 1, 1);\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"sheenColorTexture\\\")) {\\n\\t\\tmaterial.sheenMap = textures[data.sheenColorTexture.index];\\n\\t\\textractTextureTransform(data.sheenColorTexture, material, [\\\"sheen\\\"]);\\n\\t}\\n\\tmaterial.sheenGloss = data.hasOwnProperty(\\\"sheenRoughnessFactor\\\") ? data.sheenRoughnessFactor : 0;\\n\\tif (data.hasOwnProperty(\\\"sheenRoughnessTexture\\\")) {\\n\\t\\tmaterial.sheenGlossMap = textures[data.sheenRoughnessTexture.index];\\n\\t\\tmaterial.sheenGlossMapChannel = \\\"a\\\";\\n\\t\\textractTextureTransform(data.sheenRoughnessTexture, material, [\\\"sheenGloss\\\"]);\\n\\t}\\n\\tmaterial.sheenGlossInvert = true;\\n};\\nconst extensionVolume = (data, material, textures) => {\\n\\tmaterial.blendType = BLEND_NORMAL;\\n\\tmaterial.useDynamicRefraction = true;\\n\\tif (data.hasOwnProperty(\\\"thicknessFactor\\\")) {\\n\\t\\tmaterial.thickness = data.thicknessFactor;\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"thicknessTexture\\\")) {\\n\\t\\tmaterial.thicknessMap = textures[data.thicknessTexture.index];\\n\\t\\tmaterial.thicknessMapChannel = \\\"g\\\";\\n\\t\\textractTextureTransform(data.thicknessTexture, material, [\\\"thickness\\\"]);\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"attenuationDistance\\\")) {\\n\\t\\tmaterial.attenuationDistance = data.attenuationDistance;\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"attenuationColor\\\")) {\\n\\t\\tconst [r, g, b] = data.attenuationColor;\\n\\t\\tmaterial.attenuation.set(r, g, b).gamma();\\n\\t}\\n};\\nconst extensionEmissiveStrength = (data, material, textures) => {\\n\\tif (data.hasOwnProperty(\\\"emissiveStrength\\\")) {\\n\\t\\tmaterial.emissiveIntensity = data.emissiveStrength;\\n\\t}\\n};\\nconst extensionIridescence = (data, material, textures) => {\\n\\tmaterial.useIridescence = true;\\n\\tif (data.hasOwnProperty(\\\"iridescenceFactor\\\")) {\\n\\t\\tmaterial.iridescence = data.iridescenceFactor;\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"iridescenceTexture\\\")) {\\n\\t\\tmaterial.iridescenceMapChannel = \\\"r\\\";\\n\\t\\tmaterial.iridescenceMap = textures[data.iridescenceTexture.index];\\n\\t\\textractTextureTransform(data.iridescenceTexture, material, [\\\"iridescence\\\"]);\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"iridescenceIor\\\")) {\\n\\t\\tmaterial.iridescenceRefractionIndex = data.iridescenceIor;\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"iridescenceThicknessMinimum\\\")) {\\n\\t\\tmaterial.iridescenceThicknessMin = data.iridescenceThicknessMinimum;\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"iridescenceThicknessMaximum\\\")) {\\n\\t\\tmaterial.iridescenceThicknessMax = data.iridescenceThicknessMaximum;\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"iridescenceThicknessTexture\\\")) {\\n\\t\\tmaterial.iridescenceThicknessMapChannel = \\\"g\\\";\\n\\t\\tmaterial.iridescenceThicknessMap = textures[data.iridescenceThicknessTexture.index];\\n\\t\\textractTextureTransform(data.iridescenceThicknessTexture, material, [\\\"iridescenceThickness\\\"]);\\n\\t}\\n};\\nconst extensionAnisotropy = (data, material, textures) => {\\n\\tmaterial.enableGGXSpecular = true;\\n\\tif (data.hasOwnProperty(\\\"anisotropyStrength\\\")) {\\n\\t\\tmaterial.anisotropyIntensity = data.anisotropyStrength;\\n\\t} else {\\n\\t\\tmaterial.anisotropyIntensity = 0;\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"anisotropyTexture\\\")) {\\n\\t\\tconst anisotropyTexture = data.anisotropyTexture;\\n\\t\\tmaterial.anisotropyMap = textures[anisotropyTexture.index];\\n\\t\\textractTextureTransform(anisotropyTexture, material, [\\\"anisotropy\\\"]);\\n\\t}\\n\\tif (data.hasOwnProperty(\\\"anisotropyRotation\\\")) {\\n\\t\\tmaterial.anisotropyRotation = data.anisotropyRotation * math.RAD_TO_DEG;\\n\\t} else {\\n\\t\\tmaterial.anisotropyRotation = 0;\\n\\t}\\n};\\nconst createMaterial = (gltfMaterial, textures) => {\\n\\tconst material = new StandardMaterial();\\n\\tif (gltfMaterial.hasOwnProperty(\\\"name\\\")) {\\n\\t\\tmaterial.name = gltfMaterial.name;\\n\\t}\\n\\tmaterial.occludeSpecular = SPECOCC_AO;\\n\\tmaterial.diffuseVertexColor = true;\\n\\tmaterial.specularTint = true;\\n\\tmaterial.specularVertexColor = true;\\n\\tmaterial.specular.set(1, 1, 1);\\n\\tmaterial.gloss = 1;\\n\\tmaterial.glossInvert = true;\\n\\tmaterial.useMetalness = true;\\n\\tlet texture;\\n\\tif (gltfMaterial.hasOwnProperty(\\\"pbrMetallicRoughness\\\")) {\\n\\t\\tconst pbrData = gltfMaterial.pbrMetallicRoughness;\\n\\t\\tif (pbrData.hasOwnProperty(\\\"baseColorFactor\\\")) {\\n\\t\\t\\tconst [r, g, b, a] = pbrData.baseColorFactor;\\n\\t\\t\\tmaterial.diffuse.set(r, g, b).gamma();\\n\\t\\t\\tmaterial.opacity = a;\\n\\t\\t}\\n\\t\\tif (pbrData.hasOwnProperty(\\\"baseColorTexture\\\")) {\\n\\t\\t\\tconst baseColorTexture = pbrData.baseColorTexture;\\n\\t\\t\\ttexture = textures[baseColorTexture.index];\\n\\t\\t\\tmaterial.diffuseMap = texture;\\n\\t\\t\\tmaterial.diffuseMapChannel = \\\"rgb\\\";\\n\\t\\t\\tmaterial.opacityMap = texture;\\n\\t\\t\\tmaterial.opacityMapChannel = \\\"a\\\";\\n\\t\\t\\textractTextureTransform(baseColorTexture, material, [\\\"diffuse\\\", \\\"opacity\\\"]);\\n\\t\\t}\\n\\t\\tif (pbrData.hasOwnProperty(\\\"metallicFactor\\\")) {\\n\\t\\t\\tmaterial.metalness = pbrData.metallicFactor;\\n\\t\\t}\\n\\t\\tif (pbrData.hasOwnProperty(\\\"roughnessFactor\\\")) {\\n\\t\\t\\tmaterial.gloss = pbrData.roughnessFactor;\\n\\t\\t}\\n\\t\\tif (pbrData.hasOwnProperty(\\\"metallicRoughnessTexture\\\")) {\\n\\t\\t\\tconst metallicRoughnessTexture = pbrData.metallicRoughnessTexture;\\n\\t\\t\\tmaterial.metalnessMap = material.glossMap = textures[metallicRoughnessTexture.index];\\n\\t\\t\\tmaterial.metalnessMapChannel = \\\"b\\\";\\n\\t\\t\\tmaterial.glossMapChannel = \\\"g\\\";\\n\\t\\t\\textractTextureTransform(metallicRoughnessTexture, material, [\\\"gloss\\\", \\\"metalness\\\"]);\\n\\t\\t}\\n\\t}\\n\\tif (gltfMaterial.hasOwnProperty(\\\"normalTexture\\\")) {\\n\\t\\tconst normalTexture = gltfMaterial.normalTexture;\\n\\t\\tmaterial.normalMap = textures[normalTexture.index];\\n\\t\\textractTextureTransform(normalTexture, material, [\\\"normal\\\"]);\\n\\t\\tif (normalTexture.hasOwnProperty(\\\"scale\\\")) {\\n\\t\\t\\tmaterial.bumpiness = normalTexture.scale;\\n\\t\\t}\\n\\t}\\n\\tif (gltfMaterial.hasOwnProperty(\\\"occlusionTexture\\\")) {\\n\\t\\tconst occlusionTexture = gltfMaterial.occlusionTexture;\\n\\t\\tmaterial.aoMap = textures[occlusionTexture.index];\\n\\t\\tmaterial.aoMapChannel = \\\"r\\\";\\n\\t\\textractTextureTransform(occlusionTexture, material, [\\\"ao\\\"]);\\n\\t}\\n\\tif (gltfMaterial.hasOwnProperty(\\\"emissiveFactor\\\")) {\\n\\t\\tconst [r, g, b] = gltfMaterial.emissiveFactor;\\n\\t\\tmaterial.emissive.set(r, g, b).gamma();\\n\\t}\\n\\tif (gltfMaterial.hasOwnProperty(\\\"emissiveTexture\\\")) {\\n\\t\\tconst emissiveTexture = gltfMaterial.emissiveTexture;\\n\\t\\tmaterial.emissiveMap = textures[emissiveTexture.index];\\n\\t\\textractTextureTransform(emissiveTexture, material, [\\\"emissive\\\"]);\\n\\t}\\n\\tif (gltfMaterial.hasOwnProperty(\\\"alphaMode\\\")) {\\n\\t\\tswitch (gltfMaterial.alphaMode) {\\n\\t\\t\\tcase \\\"MASK\\\":\\n\\t\\t\\t\\tmaterial.blendType = BLEND_NONE;\\n\\t\\t\\t\\tif (gltfMaterial.hasOwnProperty(\\\"alphaCutoff\\\")) {\\n\\t\\t\\t\\t\\tmaterial.alphaTest = gltfMaterial.alphaCutoff;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tmaterial.alphaTest = 0.5;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase \\\"BLEND\\\":\\n\\t\\t\\t\\tmaterial.blendType = BLEND_NORMAL;\\n\\t\\t\\t\\tmaterial.depthWrite = false;\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tdefault:\\n\\t\\t\\tcase \\\"OPAQUE\\\":\\n\\t\\t\\t\\tmaterial.blendType = BLEND_NONE;\\n\\t\\t\\t\\tbreak;\\n\\t\\t}\\n\\t} else {\\n\\t\\tmaterial.blendType = BLEND_NONE;\\n\\t}\\n\\tif (gltfMaterial.hasOwnProperty(\\\"doubleSided\\\")) {\\n\\t\\tmaterial.twoSidedLighting = gltfMaterial.doubleSided;\\n\\t\\tmaterial.cull = gltfMaterial.doubleSided ? CULLFACE_NONE : CULLFACE_BACK;\\n\\t} else {\\n\\t\\tmaterial.twoSidedLighting = false;\\n\\t\\tmaterial.cull = CULLFACE_BACK;\\n\\t}\\n\\tconst extensions = {\\n\\t\\t\\\"KHR_materials_clearcoat\\\": extensionClearCoat,\\n\\t\\t\\\"KHR_materials_emissive_strength\\\": extensionEmissiveStrength,\\n\\t\\t\\\"KHR_materials_ior\\\": extensionIor,\\n\\t\\t\\\"KHR_materials_dispersion\\\": extensionDispersion,\\n\\t\\t\\\"KHR_materials_iridescence\\\": extensionIridescence,\\n\\t\\t\\\"KHR_materials_pbrSpecularGlossiness\\\": extensionPbrSpecGlossiness,\\n\\t\\t\\\"KHR_materials_sheen\\\": extensionSheen,\\n\\t\\t\\\"KHR_materials_specular\\\": extensionSpecular,\\n\\t\\t\\\"KHR_materials_transmission\\\": extensionTransmission,\\n\\t\\t\\\"KHR_materials_unlit\\\": extensionUnlit,\\n\\t\\t\\\"KHR_materials_volume\\\": extensionVolume,\\n\\t\\t\\\"KHR_materials_anisotropy\\\": extensionAnisotropy\\n\\t};\\n\\tif (gltfMaterial.hasOwnProperty(\\\"extensions\\\")) {\\n\\t\\tfor (const key in gltfMaterial.extensions) {\\n\\t\\t\\tconst extensionFunc = extensions[key];\\n\\t\\t\\tif (extensionFunc !== void 0) {\\n\\t\\t\\t\\textensionFunc(gltfMaterial.extensions[key], material, textures);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tmaterial.update();\\n\\treturn material;\\n};\\nconst createAnimation = (gltfAnimation, animationIndex, gltfAccessors, bufferViews, nodes, meshes, gltfNodes) => {\\n\\tconst createAnimData = (gltfAccessor) => {\\n\\t\\treturn new AnimData(getNumComponents(gltfAccessor.type), getAccessorDataFloat32(gltfAccessor, bufferViews));\\n\\t};\\n\\tconst interpMap = {\\n\\t\\t\\\"STEP\\\": INTERPOLATION_STEP,\\n\\t\\t\\\"LINEAR\\\": INTERPOLATION_LINEAR,\\n\\t\\t\\\"CUBICSPLINE\\\": INTERPOLATION_CUBIC\\n\\t};\\n\\tconst inputMap = {};\\n\\tconst outputMap = {};\\n\\tconst curveMap = {};\\n\\tlet outputCounter = 1;\\n\\tlet i;\\n\\tfor (i = 0; i < gltfAnimation.samplers.length; ++i) {\\n\\t\\tconst sampler = gltfAnimation.samplers[i];\\n\\t\\tif (!inputMap.hasOwnProperty(sampler.input)) {\\n\\t\\t\\tinputMap[sampler.input] = createAnimData(gltfAccessors[sampler.input]);\\n\\t\\t}\\n\\t\\tif (!outputMap.hasOwnProperty(sampler.output)) {\\n\\t\\t\\toutputMap[sampler.output] = createAnimData(gltfAccessors[sampler.output]);\\n\\t\\t}\\n\\t\\tconst interpolation = sampler.hasOwnProperty(\\\"interpolation\\\") && interpMap.hasOwnProperty(sampler.interpolation) ? interpMap[sampler.interpolation] : INTERPOLATION_LINEAR;\\n\\t\\tconst curve = {\\n\\t\\t\\tpaths: [],\\n\\t\\t\\tinput: sampler.input,\\n\\t\\t\\toutput: sampler.output,\\n\\t\\t\\tinterpolation\\n\\t\\t};\\n\\t\\tcurveMap[i] = curve;\\n\\t}\\n\\tconst quatArrays = [];\\n\\tconst transformSchema = {\\n\\t\\t\\\"translation\\\": \\\"localPosition\\\",\\n\\t\\t\\\"rotation\\\": \\\"localRotation\\\",\\n\\t\\t\\\"scale\\\": \\\"localScale\\\"\\n\\t};\\n\\tconst constructNodePath = (node) => {\\n\\t\\tconst path2 = [];\\n\\t\\twhile (node) {\\n\\t\\t\\tpath2.unshift(node.name);\\n\\t\\t\\tnode = node.parent;\\n\\t\\t}\\n\\t\\treturn path2;\\n\\t};\\n\\tconst createMorphTargetCurves = (curve, gltfNode, entityPath) => {\\n\\t\\tconst out = outputMap[curve.output];\\n\\t\\tif (!out) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tlet targetNames;\\n\\t\\tif (meshes && meshes[gltfNode.mesh]) {\\n\\t\\t\\tconst mesh = meshes[gltfNode.mesh];\\n\\t\\t\\tif (mesh.hasOwnProperty(\\\"extras\\\") && mesh.extras.hasOwnProperty(\\\"targetNames\\\")) {\\n\\t\\t\\t\\ttargetNames = mesh.extras.targetNames;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst outData = out.data;\\n\\t\\tconst morphTargetCount = outData.length / inputMap[curve.input].data.length;\\n\\t\\tconst keyframeCount = outData.length / morphTargetCount;\\n\\t\\tconst singleBufferSize = keyframeCount * 4;\\n\\t\\tconst buffer = new ArrayBuffer(singleBufferSize * morphTargetCount);\\n\\t\\tfor (let j = 0; j < morphTargetCount; j++) {\\n\\t\\t\\tconst morphTargetOutput = new Float32Array(buffer, singleBufferSize * j, keyframeCount);\\n\\t\\t\\tfor (let k = 0; k < keyframeCount; k++) {\\n\\t\\t\\t\\tmorphTargetOutput[k] = outData[k * morphTargetCount + j];\\n\\t\\t\\t}\\n\\t\\t\\tconst output = new AnimData(1, morphTargetOutput);\\n\\t\\t\\tconst weightName = targetNames?.[j] ? `name.${targetNames[j]}` : j;\\n\\t\\t\\toutputMap[-outputCounter] = output;\\n\\t\\t\\tconst morphCurve = {\\n\\t\\t\\t\\tpaths: [{\\n\\t\\t\\t\\t\\tentityPath,\\n\\t\\t\\t\\t\\tcomponent: \\\"graph\\\",\\n\\t\\t\\t\\t\\tpropertyPath: [`weight.${weightName}`]\\n\\t\\t\\t\\t}],\\n\\t\\t\\t\\t// each morph target curve input can use the same sampler.input from the channel they were all in\\n\\t\\t\\t\\tinput: curve.input,\\n\\t\\t\\t\\t// but each morph target curve should reference its individual output that was just created\\n\\t\\t\\t\\toutput: -outputCounter,\\n\\t\\t\\t\\tinterpolation: curve.interpolation\\n\\t\\t\\t};\\n\\t\\t\\toutputCounter++;\\n\\t\\t\\tcurveMap[`morphCurve-${i}-${j}`] = morphCurve;\\n\\t\\t}\\n\\t};\\n\\tfor (i = 0; i < gltfAnimation.channels.length; ++i) {\\n\\t\\tconst channel = gltfAnimation.channels[i];\\n\\t\\tconst target = channel.target;\\n\\t\\tconst curve = curveMap[channel.sampler];\\n\\t\\tconst node = nodes[target.node];\\n\\t\\tconst gltfNode = gltfNodes[target.node];\\n\\t\\tconst entityPath = constructNodePath(node);\\n\\t\\tif (target.path.startsWith(\\\"weights\\\")) {\\n\\t\\t\\tcreateMorphTargetCurves(curve, gltfNode, entityPath);\\n\\t\\t\\tcurveMap[channel.sampler].morphCurve = true;\\n\\t\\t} else {\\n\\t\\t\\tcurve.paths.push({\\n\\t\\t\\t\\tentityPath,\\n\\t\\t\\t\\tcomponent: \\\"graph\\\",\\n\\t\\t\\t\\tpropertyPath: [transformSchema[target.path]]\\n\\t\\t\\t});\\n\\t\\t}\\n\\t}\\n\\tconst inputs = [];\\n\\tconst outputs = [];\\n\\tconst curves = [];\\n\\tfor (const inputKey in inputMap) {\\n\\t\\tinputs.push(inputMap[inputKey]);\\n\\t\\tinputMap[inputKey] = inputs.length - 1;\\n\\t}\\n\\tfor (const outputKey in outputMap) {\\n\\t\\toutputs.push(outputMap[outputKey]);\\n\\t\\toutputMap[outputKey] = outputs.length - 1;\\n\\t}\\n\\tfor (const curveKey in curveMap) {\\n\\t\\tconst curveData = curveMap[curveKey];\\n\\t\\tif (curveData.morphCurve) {\\n\\t\\t\\tcontinue;\\n\\t\\t}\\n\\t\\tcurves.push(new AnimCurve(\\n\\t\\t\\tcurveData.paths,\\n\\t\\t\\tinputMap[curveData.input],\\n\\t\\t\\toutputMap[curveData.output],\\n\\t\\t\\tcurveData.interpolation\\n\\t\\t));\\n\\t\\tif (curveData.paths.length > 0 && curveData.paths[0].propertyPath[0] === \\\"localRotation\\\" && curveData.interpolation !== INTERPOLATION_CUBIC) {\\n\\t\\t\\tquatArrays.push(curves[curves.length - 1].output);\\n\\t\\t}\\n\\t}\\n\\tquatArrays.sort();\\n\\tlet prevIndex = null;\\n\\tlet data;\\n\\tfor (i = 0; i < quatArrays.length; ++i) {\\n\\t\\tconst index = quatArrays[i];\\n\\t\\tif (i === 0 || index !== prevIndex) {\\n\\t\\t\\tdata = outputs[index];\\n\\t\\t\\tif (data.components === 4) {\\n\\t\\t\\t\\tconst d = data.data;\\n\\t\\t\\t\\tconst len = d.length - 4;\\n\\t\\t\\t\\tfor (let j = 0; j < len; j += 4) {\\n\\t\\t\\t\\t\\tconst dp = d[j + 0] * d[j + 4] + d[j + 1] * d[j + 5] + d[j + 2] * d[j + 6] + d[j + 3] * d[j + 7];\\n\\t\\t\\t\\t\\tif (dp < 0) {\\n\\t\\t\\t\\t\\t\\td[j + 4] *= -1;\\n\\t\\t\\t\\t\\t\\td[j + 5] *= -1;\\n\\t\\t\\t\\t\\t\\td[j + 6] *= -1;\\n\\t\\t\\t\\t\\t\\td[j + 7] *= -1;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tprevIndex = index;\\n\\t\\t}\\n\\t}\\n\\tlet duration = 0;\\n\\tfor (i = 0; i < inputs.length; i++) {\\n\\t\\tdata = inputs[i]._data;\\n\\t\\tduration = Math.max(duration, data.length === 0 ? 0 : data[data.length - 1]);\\n\\t}\\n\\treturn new AnimTrack(\\n\\t\\tgltfAnimation.hasOwnProperty(\\\"name\\\") ? gltfAnimation.name : `animation_${animationIndex}`,\\n\\t\\tduration,\\n\\t\\tinputs,\\n\\t\\toutputs,\\n\\t\\tcurves\\n\\t);\\n};\\nconst tempMat = new Mat4();\\nconst tempVec = new Vec3();\\nconst tempQuat = new Quat();\\nconst createNode = (gltfNode, nodeIndex, nodeInstancingMap) => {\\n\\tconst entity = new GraphNode();\\n\\tif (gltfNode.hasOwnProperty(\\\"name\\\") && gltfNode.name.length > 0) {\\n\\t\\tentity.name = gltfNode.name;\\n\\t} else {\\n\\t\\tentity.name = `node_${nodeIndex}`;\\n\\t}\\n\\tif (gltfNode.hasOwnProperty(\\\"matrix\\\")) {\\n\\t\\ttempMat.data.set(gltfNode.matrix);\\n\\t\\ttempMat.getTranslation(tempVec);\\n\\t\\tentity.setLocalPosition(tempVec);\\n\\t\\ttempQuat.setFromMat4(tempMat);\\n\\t\\tentity.setLocalRotation(tempQuat);\\n\\t\\ttempMat.getScale(tempVec);\\n\\t\\ttempVec.x *= tempMat.scaleSign;\\n\\t\\tentity.setLocalScale(tempVec);\\n\\t}\\n\\tif (gltfNode.hasOwnProperty(\\\"rotation\\\")) {\\n\\t\\tconst r = gltfNode.rotation;\\n\\t\\tentity.setLocalRotation(r[0], r[1], r[2], r[3]);\\n\\t}\\n\\tif (gltfNode.hasOwnProperty(\\\"translation\\\")) {\\n\\t\\tconst t = gltfNode.translation;\\n\\t\\tentity.setLocalPosition(t[0], t[1], t[2]);\\n\\t}\\n\\tif (gltfNode.hasOwnProperty(\\\"scale\\\")) {\\n\\t\\tconst s = gltfNode.scale;\\n\\t\\tentity.setLocalScale(s[0], s[1], s[2]);\\n\\t}\\n\\tif (gltfNode.hasOwnProperty(\\\"extensions\\\") && gltfNode.extensions.EXT_mesh_gpu_instancing) {\\n\\t\\tnodeInstancingMap.set(gltfNode, {\\n\\t\\t\\text: gltfNode.extensions.EXT_mesh_gpu_instancing\\n\\t\\t});\\n\\t}\\n\\treturn entity;\\n};\\nconst createCamera$1 = (gltfCamera, node) => {\\n\\tconst isOrthographic = gltfCamera.type === \\\"orthographic\\\";\\n\\tconst gltfProperties = isOrthographic ? gltfCamera.orthographic : gltfCamera.perspective;\\n\\tconst componentData = {\\n\\t\\tenabled: false,\\n\\t\\tprojection: isOrthographic ? PROJECTION_ORTHOGRAPHIC : PROJECTION_PERSPECTIVE,\\n\\t\\tnearClip: gltfProperties.znear,\\n\\t\\taspectRatioMode: ASPECT_AUTO\\n\\t};\\n\\tif (gltfProperties.zfar) {\\n\\t\\tcomponentData.farClip = gltfProperties.zfar;\\n\\t}\\n\\tif (isOrthographic) {\\n\\t\\tcomponentData.orthoHeight = gltfProperties.ymag;\\n\\t\\tif (gltfProperties.xmag && gltfProperties.ymag) {\\n\\t\\t\\tcomponentData.aspectRatioMode = ASPECT_MANUAL;\\n\\t\\t\\tcomponentData.aspectRatio = gltfProperties.xmag / gltfProperties.ymag;\\n\\t\\t}\\n\\t} else {\\n\\t\\tcomponentData.fov = gltfProperties.yfov * math.RAD_TO_DEG;\\n\\t\\tif (gltfProperties.aspectRatio) {\\n\\t\\t\\tcomponentData.aspectRatioMode = ASPECT_MANUAL;\\n\\t\\t\\tcomponentData.aspectRatio = gltfProperties.aspectRatio;\\n\\t\\t}\\n\\t}\\n\\tconst cameraEntity = new Entity(gltfCamera.name);\\n\\tcameraEntity.addComponent(\\\"camera\\\", componentData);\\n\\treturn cameraEntity;\\n};\\nconst createLight = (gltfLight, node) => {\\n\\tconst lightProps = {\\n\\t\\tenabled: false,\\n\\t\\ttype: gltfLight.type === \\\"point\\\" ? \\\"omni\\\" : gltfLight.type,\\n\\t\\tcolor: gltfLight.hasOwnProperty(\\\"color\\\") ? new Color(gltfLight.color) : Color.WHITE,\\n\\t\\t// when range is not defined, infinity should be used - but that causes infinity in bounds calculations\\n\\t\\trange: gltfLight.hasOwnProperty(\\\"range\\\") ? gltfLight.range : 9999,\\n\\t\\tfalloffMode: LIGHTFALLOFF_INVERSESQUARED,\\n\\t\\t// TODO: (engine issue #3252) Set intensity to match glTF specification, which uses physically based values:\\n\\t\\t// - Omni and spot lights use luminous intensity in candela (lm/sr)\\n\\t\\t// - Directional lights use illuminance in lux (lm/m2).\\n\\t\\t// Current implementation: clamps specified intensity to 0..2 range\\n\\t\\tintensity: gltfLight.hasOwnProperty(\\\"intensity\\\") ? math.clamp(gltfLight.intensity, 0, 2) : 1\\n\\t};\\n\\tif (gltfLight.hasOwnProperty(\\\"spot\\\")) {\\n\\t\\tlightProps.innerConeAngle = gltfLight.spot.hasOwnProperty(\\\"innerConeAngle\\\") ? gltfLight.spot.innerConeAngle * math.RAD_TO_DEG : 0;\\n\\t\\tlightProps.outerConeAngle = gltfLight.spot.hasOwnProperty(\\\"outerConeAngle\\\") ? gltfLight.spot.outerConeAngle * math.RAD_TO_DEG : 45;\\n\\t}\\n\\tif (gltfLight.hasOwnProperty(\\\"intensity\\\")) {\\n\\t\\tconst outerAngleRad = gltfLight.spot?.outerConeAngle ?? Math.PI / 4;\\n\\t\\tconst innerAngleRad = gltfLight.spot?.innerConeAngle ?? 0;\\n\\t\\tlightProps.luminance = gltfLight.intensity * Light.getLightUnitConversion(lightTypes[lightProps.type], outerAngleRad, innerAngleRad);\\n\\t}\\n\\tconst lightEntity = new Entity(node.name);\\n\\tlightEntity.rotateLocal(90, 0, 0);\\n\\tlightEntity.addComponent(\\\"light\\\", lightProps);\\n\\treturn lightEntity;\\n};\\nconst createSkins = (device, gltf, nodes, bufferViews) => {\\n\\tif (!gltf.hasOwnProperty(\\\"skins\\\") || gltf.skins.length === 0) {\\n\\t\\treturn [];\\n\\t}\\n\\tconst glbSkins = /* @__PURE__ */ new Map();\\n\\treturn gltf.skins.map((gltfSkin) => {\\n\\t\\treturn createSkin(device, gltfSkin, gltf.accessors, bufferViews, nodes, glbSkins);\\n\\t});\\n};\\nconst createMeshes = (device, gltf, bufferViews, options) => {\\n\\tconst vertexBufferDict = {};\\n\\tconst meshVariants = {};\\n\\tconst meshDefaultMaterials = {};\\n\\tconst promises = [];\\n\\tconst valid = !options.skipMeshes && gltf?.meshes?.length && gltf?.accessors?.length && gltf?.bufferViews?.length;\\n\\tconst meshes = valid ? gltf.meshes.map((gltfMesh) => {\\n\\t\\treturn createMesh(device, gltfMesh, gltf.accessors, bufferViews, vertexBufferDict, meshVariants, meshDefaultMaterials, options, promises);\\n\\t}) : [];\\n\\treturn {\\n\\t\\tmeshes,\\n\\t\\tmeshVariants,\\n\\t\\tmeshDefaultMaterials,\\n\\t\\tpromises\\n\\t};\\n};\\nconst createMaterials = (gltf, textures, options) => {\\n\\tif (!gltf.hasOwnProperty(\\\"materials\\\") || gltf.materials.length === 0) {\\n\\t\\treturn [];\\n\\t}\\n\\tconst preprocess = options?.material?.preprocess;\\n\\tconst process = options?.material?.process ?? createMaterial;\\n\\tconst postprocess = options?.material?.postprocess;\\n\\treturn gltf.materials.map((gltfMaterial) => {\\n\\t\\tif (preprocess) {\\n\\t\\t\\tpreprocess(gltfMaterial);\\n\\t\\t}\\n\\t\\tconst material = process(gltfMaterial, textures);\\n\\t\\tif (postprocess) {\\n\\t\\t\\tpostprocess(gltfMaterial, material);\\n\\t\\t}\\n\\t\\treturn material;\\n\\t});\\n};\\nconst createVariants = (gltf) => {\\n\\tif (!gltf.hasOwnProperty(\\\"extensions\\\") || !gltf.extensions.hasOwnProperty(\\\"KHR_materials_variants\\\")) {\\n\\t\\treturn null;\\n\\t}\\n\\tconst data = gltf.extensions.KHR_materials_variants.variants;\\n\\tconst variants = {};\\n\\tfor (let i = 0; i < data.length; i++) {\\n\\t\\tvariants[data[i].name] = i;\\n\\t}\\n\\treturn variants;\\n};\\nconst createAnimations = (gltf, nodes, bufferViews, options) => {\\n\\tif (!gltf.hasOwnProperty(\\\"animations\\\") || gltf.animations.length === 0) {\\n\\t\\treturn [];\\n\\t}\\n\\tconst preprocess = options?.animation?.preprocess;\\n\\tconst postprocess = options?.animation?.postprocess;\\n\\treturn gltf.animations.map((gltfAnimation, index) => {\\n\\t\\tif (preprocess) {\\n\\t\\t\\tpreprocess(gltfAnimation);\\n\\t\\t}\\n\\t\\tconst animation = createAnimation(gltfAnimation, index, gltf.accessors, bufferViews, nodes, gltf.meshes, gltf.nodes);\\n\\t\\tif (postprocess) {\\n\\t\\t\\tpostprocess(gltfAnimation, animation);\\n\\t\\t}\\n\\t\\treturn animation;\\n\\t});\\n};\\nconst createInstancing = (device, gltf, nodeInstancingMap, bufferViews) => {\\n\\tconst accessors = gltf.accessors;\\n\\tnodeInstancingMap.forEach((data, entity) => {\\n\\t\\tconst attributes = data.ext.attributes;\\n\\t\\tlet translations;\\n\\t\\tif (attributes.hasOwnProperty(\\\"TRANSLATION\\\")) {\\n\\t\\t\\tconst accessor = accessors[attributes.TRANSLATION];\\n\\t\\t\\ttranslations = getAccessorDataFloat32(accessor, bufferViews);\\n\\t\\t}\\n\\t\\tlet rotations;\\n\\t\\tif (attributes.hasOwnProperty(\\\"ROTATION\\\")) {\\n\\t\\t\\tconst accessor = accessors[attributes.ROTATION];\\n\\t\\t\\trotations = getAccessorDataFloat32(accessor, bufferViews);\\n\\t\\t}\\n\\t\\tlet scales;\\n\\t\\tif (attributes.hasOwnProperty(\\\"SCALE\\\")) {\\n\\t\\t\\tconst accessor = accessors[attributes.SCALE];\\n\\t\\t\\tscales = getAccessorDataFloat32(accessor, bufferViews);\\n\\t\\t}\\n\\t\\tconst instanceCount = (translations ? translations.length / 3 : 0) || (rotations ? rotations.length / 4 : 0) || (scales ? scales.length / 3 : 0);\\n\\t\\tif (instanceCount) {\\n\\t\\t\\tconst matrices = new Float32Array(instanceCount * 16);\\n\\t\\t\\tconst pos = new Vec3();\\n\\t\\t\\tconst rot = new Quat();\\n\\t\\t\\tconst scl = new Vec3(1, 1, 1);\\n\\t\\t\\tconst matrix = new Mat4();\\n\\t\\t\\tlet matrixIndex = 0;\\n\\t\\t\\tfor (let i = 0; i < instanceCount; i++) {\\n\\t\\t\\t\\tconst i3 = i * 3;\\n\\t\\t\\t\\tif (translations) {\\n\\t\\t\\t\\t\\tpos.set(translations[i3], translations[i3 + 1], translations[i3 + 2]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (rotations) {\\n\\t\\t\\t\\t\\tconst i4 = i * 4;\\n\\t\\t\\t\\t\\trot.set(rotations[i4], rotations[i4 + 1], rotations[i4 + 2], rotations[i4 + 3]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (scales) {\\n\\t\\t\\t\\t\\tscl.set(scales[i3], scales[i3 + 1], scales[i3 + 2]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tmatrix.setTRS(pos, rot, scl);\\n\\t\\t\\t\\tfor (let m = 0; m < 16; m++) {\\n\\t\\t\\t\\t\\tmatrices[matrixIndex++] = matrix.data[m];\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tdata.matrices = matrices;\\n\\t\\t}\\n\\t});\\n};\\nconst createNodes = (gltf, options, nodeInstancingMap) => {\\n\\tif (!gltf.hasOwnProperty(\\\"nodes\\\") || gltf.nodes.length === 0) {\\n\\t\\treturn [];\\n\\t}\\n\\tconst preprocess = options?.node?.preprocess;\\n\\tconst process = options?.node?.process ?? createNode;\\n\\tconst postprocess = options?.node?.postprocess;\\n\\tconst nodes = gltf.nodes.map((gltfNode, index) => {\\n\\t\\tif (preprocess) {\\n\\t\\t\\tpreprocess(gltfNode);\\n\\t\\t}\\n\\t\\tconst node = process(gltfNode, index, nodeInstancingMap);\\n\\t\\tif (postprocess) {\\n\\t\\t\\tpostprocess(gltfNode, node);\\n\\t\\t}\\n\\t\\treturn node;\\n\\t});\\n\\tfor (let i = 0; i < gltf.nodes.length; ++i) {\\n\\t\\tconst gltfNode = gltf.nodes[i];\\n\\t\\tif (gltfNode.hasOwnProperty(\\\"children\\\")) {\\n\\t\\t\\tconst parent = nodes[i];\\n\\t\\t\\tconst uniqueNames = {};\\n\\t\\t\\tfor (let j = 0; j < gltfNode.children.length; ++j) {\\n\\t\\t\\t\\tconst child = nodes[gltfNode.children[j]];\\n\\t\\t\\t\\tif (!child.parent) {\\n\\t\\t\\t\\t\\tif (uniqueNames.hasOwnProperty(child.name)) {\\n\\t\\t\\t\\t\\t\\tchild.name += uniqueNames[child.name]++;\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tuniqueNames[child.name] = 1;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tparent.addChild(child);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\treturn nodes;\\n};\\nconst createScenes = (gltf, nodes) => {\\n\\tconst scenes = [];\\n\\tconst count = gltf.scenes.length;\\n\\tif (count === 1 && gltf.scenes[0].nodes?.length === 1) {\\n\\t\\tconst nodeIndex = gltf.scenes[0].nodes[0];\\n\\t\\tscenes.push(nodes[nodeIndex]);\\n\\t} else {\\n\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\tconst scene = gltf.scenes[i];\\n\\t\\t\\tif (scene.nodes) {\\n\\t\\t\\t\\tconst sceneRoot = new GraphNode(scene.name);\\n\\t\\t\\t\\tfor (let n = 0; n < scene.nodes.length; n++) {\\n\\t\\t\\t\\t\\tconst childNode = nodes[scene.nodes[n]];\\n\\t\\t\\t\\t\\tsceneRoot.addChild(childNode);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tscenes.push(sceneRoot);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\treturn scenes;\\n};\\nconst createCameras = (gltf, nodes, options) => {\\n\\tlet cameras = null;\\n\\tif (gltf.hasOwnProperty(\\\"nodes\\\") && gltf.hasOwnProperty(\\\"cameras\\\") && gltf.cameras.length > 0) {\\n\\t\\tconst preprocess = options?.camera?.preprocess;\\n\\t\\tconst process = options?.camera?.process ?? createCamera$1;\\n\\t\\tconst postprocess = options?.camera?.postprocess;\\n\\t\\tgltf.nodes.forEach((gltfNode, nodeIndex) => {\\n\\t\\t\\tif (gltfNode.hasOwnProperty(\\\"camera\\\")) {\\n\\t\\t\\t\\tconst gltfCamera = gltf.cameras[gltfNode.camera];\\n\\t\\t\\t\\tif (gltfCamera) {\\n\\t\\t\\t\\t\\tif (preprocess) {\\n\\t\\t\\t\\t\\t\\tpreprocess(gltfCamera);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tconst camera = process(gltfCamera, nodes[nodeIndex]);\\n\\t\\t\\t\\t\\tif (postprocess) {\\n\\t\\t\\t\\t\\t\\tpostprocess(gltfCamera, camera);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (camera) {\\n\\t\\t\\t\\t\\t\\tif (!cameras) cameras = /* @__PURE__ */ new Map();\\n\\t\\t\\t\\t\\t\\tcameras.set(gltfNode, camera);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n\\treturn cameras;\\n};\\nconst createLights = (gltf, nodes, options) => {\\n\\tlet lights = null;\\n\\tif (gltf.hasOwnProperty(\\\"nodes\\\") && gltf.hasOwnProperty(\\\"extensions\\\") && gltf.extensions.hasOwnProperty(\\\"KHR_lights_punctual\\\") && gltf.extensions.KHR_lights_punctual.hasOwnProperty(\\\"lights\\\")) {\\n\\t\\tconst gltfLights = gltf.extensions.KHR_lights_punctual.lights;\\n\\t\\tif (gltfLights.length) {\\n\\t\\t\\tconst preprocess = options?.light?.preprocess;\\n\\t\\t\\tconst process = options?.light?.process ?? createLight;\\n\\t\\t\\tconst postprocess = options?.light?.postprocess;\\n\\t\\t\\tgltf.nodes.forEach((gltfNode, nodeIndex) => {\\n\\t\\t\\t\\tif (gltfNode.hasOwnProperty(\\\"extensions\\\") && gltfNode.extensions.hasOwnProperty(\\\"KHR_lights_punctual\\\") && gltfNode.extensions.KHR_lights_punctual.hasOwnProperty(\\\"light\\\")) {\\n\\t\\t\\t\\t\\tconst lightIndex = gltfNode.extensions.KHR_lights_punctual.light;\\n\\t\\t\\t\\t\\tconst gltfLight = gltfLights[lightIndex];\\n\\t\\t\\t\\t\\tif (gltfLight) {\\n\\t\\t\\t\\t\\t\\tif (preprocess) {\\n\\t\\t\\t\\t\\t\\t\\tpreprocess(gltfLight);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst light = process(gltfLight, nodes[nodeIndex]);\\n\\t\\t\\t\\t\\t\\tif (postprocess) {\\n\\t\\t\\t\\t\\t\\t\\tpostprocess(gltfLight, light);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (light) {\\n\\t\\t\\t\\t\\t\\t\\tif (!lights) lights = /* @__PURE__ */ new Map();\\n\\t\\t\\t\\t\\t\\t\\tlights.set(gltfNode, light);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t}\\n\\t}\\n\\treturn lights;\\n};\\nconst linkSkins = (gltf, renders, skins) => {\\n\\tgltf.nodes.forEach((gltfNode) => {\\n\\t\\tif (gltfNode.hasOwnProperty(\\\"mesh\\\") && gltfNode.hasOwnProperty(\\\"skin\\\")) {\\n\\t\\t\\tconst meshGroup = renders[gltfNode.mesh].meshes;\\n\\t\\t\\tmeshGroup.forEach((mesh) => {\\n\\t\\t\\t\\tmesh.skin = skins[gltfNode.skin];\\n\\t\\t\\t});\\n\\t\\t}\\n\\t});\\n};\\nconst createResources = async (device, gltf, bufferViews, textures, options) => {\\n\\tconst preprocess = options?.global?.preprocess;\\n\\tconst postprocess = options?.global?.postprocess;\\n\\tif (preprocess) {\\n\\t\\tpreprocess(gltf);\\n\\t}\\n\\tif (gltf.asset && gltf.asset.generator === \\\"PlayCanvas\\\") ;\\n\\tconst nodeInstancingMap = /* @__PURE__ */ new Map();\\n\\tconst nodes = createNodes(gltf, options, nodeInstancingMap);\\n\\tconst scenes = createScenes(gltf, nodes);\\n\\tconst lights = createLights(gltf, nodes, options);\\n\\tconst cameras = createCameras(gltf, nodes, options);\\n\\tconst variants = createVariants(gltf);\\n\\tconst bufferViewData = await Promise.all(bufferViews);\\n\\tconst { meshes, meshVariants, meshDefaultMaterials, promises } = createMeshes(device, gltf, bufferViewData, options);\\n\\tconst animations = createAnimations(gltf, nodes, bufferViewData, options);\\n\\tcreateInstancing(device, gltf, nodeInstancingMap, bufferViewData);\\n\\tconst textureAssets = await Promise.all(textures);\\n\\tconst textureInstances = textureAssets.map((t) => t.resource);\\n\\tconst materials = createMaterials(gltf, textureInstances, options);\\n\\tconst skins = createSkins(device, gltf, nodes, bufferViewData);\\n\\tconst renders = [];\\n\\tfor (let i = 0; i < meshes.length; i++) {\\n\\t\\trenders[i] = new Render();\\n\\t\\trenders[i].meshes = meshes[i];\\n\\t}\\n\\tlinkSkins(gltf, renders, skins);\\n\\tconst result = new GlbResources();\\n\\tresult.gltf = gltf;\\n\\tresult.nodes = nodes;\\n\\tresult.scenes = scenes;\\n\\tresult.animations = animations;\\n\\tresult.textures = textureAssets;\\n\\tresult.materials = materials;\\n\\tresult.variants = variants;\\n\\tresult.meshVariants = meshVariants;\\n\\tresult.meshDefaultMaterials = meshDefaultMaterials;\\n\\tresult.renders = renders;\\n\\tresult.skins = skins;\\n\\tresult.lights = lights;\\n\\tresult.cameras = cameras;\\n\\tresult.nodeInstancingMap = nodeInstancingMap;\\n\\tif (postprocess) {\\n\\t\\tpostprocess(gltf, result);\\n\\t}\\n\\tawait Promise.all(promises);\\n\\treturn result;\\n};\\nconst applySampler = (texture, gltfSampler) => {\\n\\tconst getFilter = (filter, defaultValue) => {\\n\\t\\tswitch (filter) {\\n\\t\\t\\tcase 9728:\\n\\t\\t\\t\\treturn FILTER_NEAREST;\\n\\t\\t\\tcase 9729:\\n\\t\\t\\t\\treturn FILTER_LINEAR;\\n\\t\\t\\tcase 9984:\\n\\t\\t\\t\\treturn FILTER_NEAREST_MIPMAP_NEAREST;\\n\\t\\t\\tcase 9985:\\n\\t\\t\\t\\treturn FILTER_LINEAR_MIPMAP_NEAREST;\\n\\t\\t\\tcase 9986:\\n\\t\\t\\t\\treturn FILTER_NEAREST_MIPMAP_LINEAR;\\n\\t\\t\\tcase 9987:\\n\\t\\t\\t\\treturn FILTER_LINEAR_MIPMAP_LINEAR;\\n\\t\\t\\tdefault:\\n\\t\\t\\t\\treturn defaultValue;\\n\\t\\t}\\n\\t};\\n\\tconst getWrap = (wrap, defaultValue) => {\\n\\t\\tswitch (wrap) {\\n\\t\\t\\tcase 33071:\\n\\t\\t\\t\\treturn ADDRESS_CLAMP_TO_EDGE;\\n\\t\\t\\tcase 33648:\\n\\t\\t\\t\\treturn ADDRESS_MIRRORED_REPEAT;\\n\\t\\t\\tcase 10497:\\n\\t\\t\\t\\treturn ADDRESS_REPEAT;\\n\\t\\t\\tdefault:\\n\\t\\t\\t\\treturn defaultValue;\\n\\t\\t}\\n\\t};\\n\\tif (texture) {\\n\\t\\tgltfSampler = gltfSampler ?? {};\\n\\t\\ttexture.minFilter = getFilter(gltfSampler.minFilter, FILTER_LINEAR_MIPMAP_LINEAR);\\n\\t\\ttexture.magFilter = getFilter(gltfSampler.magFilter, FILTER_LINEAR);\\n\\t\\ttexture.addressU = getWrap(gltfSampler.wrapS, ADDRESS_REPEAT);\\n\\t\\ttexture.addressV = getWrap(gltfSampler.wrapT, ADDRESS_REPEAT);\\n\\t}\\n};\\nlet gltfTextureUniqueId = 0;\\nconst getTextureSource = (gltfTexture) => gltfTexture.extensions?.KHR_texture_basisu?.source ?? gltfTexture.extensions?.EXT_texture_webp?.source ?? gltfTexture.source;\\nconst createImages = (gltf, bufferViews, urlBase, registry, options) => {\\n\\tif (!gltf.images || gltf.images.length === 0) {\\n\\t\\treturn [];\\n\\t}\\n\\tconst preprocess = options?.image?.preprocess;\\n\\tconst processAsync = options?.image?.processAsync;\\n\\tconst postprocess = options?.image?.postprocess;\\n\\tconst mimeTypeFileExtensions = {\\n\\t\\t\\\"image/png\\\": \\\"png\\\",\\n\\t\\t\\\"image/jpeg\\\": \\\"jpg\\\",\\n\\t\\t\\\"image/basis\\\": \\\"basis\\\",\\n\\t\\t\\\"image/ktx\\\": \\\"ktx\\\",\\n\\t\\t\\\"image/ktx2\\\": \\\"ktx2\\\",\\n\\t\\t\\\"image/vnd-ms.dds\\\": \\\"dds\\\"\\n\\t};\\n\\tconst getGammaTextures = (gltf2) => {\\n\\t\\tconst set = /* @__PURE__ */ new Set();\\n\\t\\tif (gltf2.hasOwnProperty(\\\"materials\\\")) {\\n\\t\\t\\tgltf2.materials.forEach((gltfMaterial) => {\\n\\t\\t\\t\\tif (gltfMaterial.hasOwnProperty(\\\"pbrMetallicRoughness\\\")) {\\n\\t\\t\\t\\t\\tconst pbrData = gltfMaterial.pbrMetallicRoughness;\\n\\t\\t\\t\\t\\tif (pbrData.hasOwnProperty(\\\"baseColorTexture\\\")) {\\n\\t\\t\\t\\t\\t\\tconst gltfTexture = gltf2.textures[pbrData.baseColorTexture.index];\\n\\t\\t\\t\\t\\t\\tset.add(getTextureSource(gltfTexture));\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (gltfMaterial.hasOwnProperty(\\\"emissiveTexture\\\")) {\\n\\t\\t\\t\\t\\tconst gltfTexture = gltf2.textures[gltfMaterial.emissiveTexture.index];\\n\\t\\t\\t\\t\\tset.add(getTextureSource(gltfTexture));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (gltfMaterial.hasOwnProperty(\\\"extensions\\\")) {\\n\\t\\t\\t\\t\\tconst sheen = gltfMaterial.extensions.KHR_materials_sheen;\\n\\t\\t\\t\\t\\tif (sheen) {\\n\\t\\t\\t\\t\\t\\tif (sheen.hasOwnProperty(\\\"sheenColorTexture\\\")) {\\n\\t\\t\\t\\t\\t\\t\\tconst gltfTexture = gltf2.textures[sheen.sheenColorTexture.index];\\n\\t\\t\\t\\t\\t\\t\\tset.add(getTextureSource(gltfTexture));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tconst specularGlossiness = gltfMaterial.extensions.KHR_materials_pbrSpecularGlossiness;\\n\\t\\t\\t\\t\\tif (specularGlossiness) {\\n\\t\\t\\t\\t\\t\\tif (specularGlossiness.hasOwnProperty(\\\"specularGlossinessTexture\\\")) {\\n\\t\\t\\t\\t\\t\\t\\tconst gltfTexture = gltf2.textures[specularGlossiness.specularGlossinessTexture.index];\\n\\t\\t\\t\\t\\t\\t\\tset.add(getTextureSource(gltfTexture));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tconst specular = gltfMaterial.extensions.KHR_materials_specular;\\n\\t\\t\\t\\t\\tif (specular) {\\n\\t\\t\\t\\t\\t\\tif (specular.hasOwnProperty(\\\"specularColorTexture\\\")) {\\n\\t\\t\\t\\t\\t\\t\\tconst gltfTexture = gltf2.textures[specular.specularColorTexture.index];\\n\\t\\t\\t\\t\\t\\t\\tset.add(getTextureSource(gltfTexture));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\treturn set;\\n\\t};\\n\\tconst loadTexture = (gltfImage, url, bufferView, mimeType, options2, srgb) => {\\n\\t\\treturn new Promise((resolve, reject) => {\\n\\t\\t\\tconst continuation = (bufferViewData) => {\\n\\t\\t\\t\\tconst name = `${gltfImage.name || \\\"gltf-texture\\\"}-${gltfTextureUniqueId++}`;\\n\\t\\t\\t\\tconst file = {\\n\\t\\t\\t\\t\\turl: url || name\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (bufferViewData) {\\n\\t\\t\\t\\t\\tfile.contents = bufferViewData.slice(0).buffer;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (mimeType) {\\n\\t\\t\\t\\t\\tconst extension = mimeTypeFileExtensions[mimeType];\\n\\t\\t\\t\\t\\tif (extension) {\\n\\t\\t\\t\\t\\t\\tfile.filename = `${file.url}.${extension}`;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst data = { srgb };\\n\\t\\t\\t\\tconst asset = new Asset(name, \\\"texture\\\", file, data, options2);\\n\\t\\t\\t\\tasset.on(\\\"load\\\", (asset2) => resolve(asset2));\\n\\t\\t\\t\\tasset.on(\\\"error\\\", (err) => reject(err));\\n\\t\\t\\t\\tregistry.add(asset);\\n\\t\\t\\t\\tregistry.load(asset);\\n\\t\\t\\t};\\n\\t\\t\\tif (bufferView) {\\n\\t\\t\\t\\tbufferView.then((bufferViewData) => continuation(bufferViewData));\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tcontinuation(null);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t};\\n\\tconst gammaTextures = getGammaTextures(gltf);\\n\\treturn gltf.images.map((gltfImage, i) => {\\n\\t\\tif (preprocess) {\\n\\t\\t\\tpreprocess(gltfImage);\\n\\t\\t}\\n\\t\\tlet promise;\\n\\t\\tif (processAsync) {\\n\\t\\t\\tpromise = new Promise((resolve, reject) => {\\n\\t\\t\\t\\tprocessAsync(gltfImage, (err, textureAsset) => {\\n\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\treject(err);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tresolve(textureAsset);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\tpromise = new Promise((resolve) => {\\n\\t\\t\\t\\tresolve(null);\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tpromise = promise.then((textureAsset) => {\\n\\t\\t\\tconst srgb = gammaTextures.has(i);\\n\\t\\t\\tif (textureAsset) {\\n\\t\\t\\t\\treturn textureAsset;\\n\\t\\t\\t} else if (gltfImage.hasOwnProperty(\\\"uri\\\")) {\\n\\t\\t\\t\\tif (isDataURI(gltfImage.uri)) {\\n\\t\\t\\t\\t\\treturn loadTexture(gltfImage, gltfImage.uri, null, getDataURIMimeType(gltfImage.uri), null, srgb);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn loadTexture(gltfImage, ABSOLUTE_URL.test(gltfImage.uri) ? gltfImage.uri : path.join(urlBase, gltfImage.uri), null, null, { crossOrigin: \\\"anonymous\\\" }, srgb);\\n\\t\\t\\t} else if (gltfImage.hasOwnProperty(\\\"bufferView\\\") && gltfImage.hasOwnProperty(\\\"mimeType\\\")) {\\n\\t\\t\\t\\treturn loadTexture(gltfImage, null, bufferViews[gltfImage.bufferView], gltfImage.mimeType, null, srgb);\\n\\t\\t\\t}\\n\\t\\t\\treturn Promise.reject(new Error(`Invalid image found in gltf (neither uri or bufferView found). index=${i}`));\\n\\t\\t});\\n\\t\\tif (postprocess) {\\n\\t\\t\\tpromise = promise.then((textureAsset) => {\\n\\t\\t\\t\\tpostprocess(gltfImage, textureAsset);\\n\\t\\t\\t\\treturn textureAsset;\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\treturn promise;\\n\\t});\\n};\\nconst createTextures = (gltf, images, options) => {\\n\\tif (!gltf?.images?.length || !gltf?.textures?.length) {\\n\\t\\treturn [];\\n\\t}\\n\\tconst preprocess = options?.texture?.preprocess;\\n\\tconst processAsync = options?.texture?.processAsync;\\n\\tconst postprocess = options?.texture?.postprocess;\\n\\tconst seenImages = /* @__PURE__ */ new Set();\\n\\treturn gltf.textures.map((gltfTexture) => {\\n\\t\\tif (preprocess) {\\n\\t\\t\\tpreprocess(gltfTexture);\\n\\t\\t}\\n\\t\\tlet promise;\\n\\t\\tif (processAsync) {\\n\\t\\t\\tpromise = new Promise((resolve, reject) => {\\n\\t\\t\\t\\tprocessAsync(gltfTexture, gltf.images, (err, gltfImageIndex) => {\\n\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\treject(err);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tresolve(gltfImageIndex);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\tpromise = new Promise((resolve) => {\\n\\t\\t\\t\\tresolve(null);\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tpromise = promise.then((gltfImageIndex) => {\\n\\t\\t\\tgltfImageIndex = gltfImageIndex ?? getTextureSource(gltfTexture);\\n\\t\\t\\tconst cloneAsset = seenImages.has(gltfImageIndex);\\n\\t\\t\\tseenImages.add(gltfImageIndex);\\n\\t\\t\\treturn images[gltfImageIndex].then((imageAsset) => {\\n\\t\\t\\t\\tconst asset = cloneAsset ? cloneTextureAsset(imageAsset) : imageAsset;\\n\\t\\t\\t\\tapplySampler(asset.resource, (gltf.samplers ?? [])[gltfTexture.sampler]);\\n\\t\\t\\t\\treturn asset;\\n\\t\\t\\t});\\n\\t\\t});\\n\\t\\tif (postprocess) {\\n\\t\\t\\tpromise = promise.then((textureAsset) => {\\n\\t\\t\\t\\tpostprocess(gltfTexture, textureAsset);\\n\\t\\t\\t\\treturn textureAsset;\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\treturn promise;\\n\\t});\\n};\\nconst loadBuffers = (gltf, binaryChunk, urlBase, options) => {\\n\\tif (!gltf.buffers || gltf.buffers.length === 0) {\\n\\t\\treturn [];\\n\\t}\\n\\tconst preprocess = options?.buffer?.preprocess;\\n\\tconst processAsync = options?.buffer?.processAsync;\\n\\tconst postprocess = options?.buffer?.postprocess;\\n\\treturn gltf.buffers.map((gltfBuffer, i) => {\\n\\t\\tif (preprocess) {\\n\\t\\t\\tpreprocess(gltfBuffer);\\n\\t\\t}\\n\\t\\tlet promise;\\n\\t\\tif (processAsync) {\\n\\t\\t\\tpromise = new Promise((resolve, reject) => {\\n\\t\\t\\t\\tprocessAsync(gltfBuffer, (err, arrayBuffer) => {\\n\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\treject(err);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tresolve(arrayBuffer);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\tpromise = new Promise((resolve) => {\\n\\t\\t\\t\\tresolve(null);\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tpromise = promise.then((arrayBuffer) => {\\n\\t\\t\\tif (arrayBuffer) {\\n\\t\\t\\t\\treturn arrayBuffer;\\n\\t\\t\\t} else if (gltfBuffer.hasOwnProperty(\\\"uri\\\")) {\\n\\t\\t\\t\\tif (isDataURI(gltfBuffer.uri)) {\\n\\t\\t\\t\\t\\tconst byteString = atob(gltfBuffer.uri.split(\\\",\\\")[1]);\\n\\t\\t\\t\\t\\tconst binaryArray = new Uint8Array(byteString.length);\\n\\t\\t\\t\\t\\tfor (let j = 0; j < byteString.length; j++) {\\n\\t\\t\\t\\t\\t\\tbinaryArray[j] = byteString.charCodeAt(j);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\treturn binaryArray;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn new Promise((resolve, reject) => {\\n\\t\\t\\t\\t\\thttp.get(\\n\\t\\t\\t\\t\\t\\tABSOLUTE_URL.test(gltfBuffer.uri) ? gltfBuffer.uri : path.join(urlBase, gltfBuffer.uri),\\n\\t\\t\\t\\t\\t\\t{ cache: true, responseType: \\\"arraybuffer\\\", retry: false },\\n\\t\\t\\t\\t\\t\\t(err, result) => {\\n\\t\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\treject(err);\\n\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tresolve(new Uint8Array(result));\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t);\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t\\treturn binaryChunk;\\n\\t\\t});\\n\\t\\tif (postprocess) {\\n\\t\\t\\tpromise = promise.then((buffer) => {\\n\\t\\t\\t\\tpostprocess(gltf.buffers[i], buffer);\\n\\t\\t\\t\\treturn buffer;\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\treturn promise;\\n\\t});\\n};\\nconst parseGltf = (gltfChunk, callback) => {\\n\\tconst decodeBinaryUtf8 = (array) => {\\n\\t\\tif (typeof TextDecoder !== \\\"undefined\\\") {\\n\\t\\t\\treturn new TextDecoder().decode(array);\\n\\t\\t}\\n\\t\\tlet str = \\\"\\\";\\n\\t\\tfor (let i = 0; i < array.length; i++) {\\n\\t\\t\\tstr += String.fromCharCode(array[i]);\\n\\t\\t}\\n\\t\\treturn decodeURIComponent(escape(str));\\n\\t};\\n\\tconst gltf = JSON.parse(decodeBinaryUtf8(gltfChunk));\\n\\tif (gltf.asset && gltf.asset.version && parseFloat(gltf.asset.version) < 2) {\\n\\t\\tcallback(`Invalid gltf version. Expected version 2.0 or above but found version '${gltf.asset.version}'.`);\\n\\t\\treturn;\\n\\t}\\n\\tcallback(null, gltf);\\n};\\nconst parseGlb = (glbData, callback) => {\\n\\tconst data = glbData instanceof ArrayBuffer ? new DataView(glbData) : new DataView(glbData.buffer, glbData.byteOffset, glbData.byteLength);\\n\\tconst magic = data.getUint32(0, true);\\n\\tconst version = data.getUint32(4, true);\\n\\tconst length = data.getUint32(8, true);\\n\\tif (magic !== 1179937895) {\\n\\t\\tcallback(`Invalid magic number found in glb header. Expected 0x46546C67, found 0x${magic.toString(16)}`);\\n\\t\\treturn;\\n\\t}\\n\\tif (version !== 2) {\\n\\t\\tcallback(`Invalid version number found in glb header. Expected 2, found ${version}`);\\n\\t\\treturn;\\n\\t}\\n\\tif (length <= 0 || length > data.byteLength) {\\n\\t\\tcallback(`Invalid length found in glb header. Found ${length}`);\\n\\t\\treturn;\\n\\t}\\n\\tconst chunks = [];\\n\\tlet offset = 12;\\n\\twhile (offset < length) {\\n\\t\\tconst chunkLength = data.getUint32(offset, true);\\n\\t\\tif (offset + chunkLength + 8 > data.byteLength) {\\n\\t\\t\\tcallback(`Invalid chunk length found in glb. Found ${chunkLength}`);\\n\\t\\t}\\n\\t\\tconst chunkType = data.getUint32(offset + 4, true);\\n\\t\\tconst chunkData = new Uint8Array(data.buffer, data.byteOffset + offset + 8, chunkLength);\\n\\t\\tchunks.push({ length: chunkLength, type: chunkType, data: chunkData });\\n\\t\\toffset += chunkLength + 8;\\n\\t}\\n\\tif (chunks.length !== 1 && chunks.length !== 2) {\\n\\t\\tcallback(\\\"Invalid number of chunks found in glb file.\\\");\\n\\t\\treturn;\\n\\t}\\n\\tif (chunks[0].type !== 1313821514) {\\n\\t\\tcallback(`Invalid chunk type found in glb file. Expected 0x4E4F534A, found 0x${chunks[0].type.toString(16)}`);\\n\\t\\treturn;\\n\\t}\\n\\tif (chunks.length > 1 && chunks[1].type !== 5130562) {\\n\\t\\tcallback(`Invalid chunk type found in glb file. Expected 0x004E4942, found 0x${chunks[1].type.toString(16)}`);\\n\\t\\treturn;\\n\\t}\\n\\tcallback(null, {\\n\\t\\tgltfChunk: chunks[0].data,\\n\\t\\tbinaryChunk: chunks.length === 2 ? chunks[1].data : null\\n\\t});\\n};\\nconst parseChunk = (filename, data, callback) => {\\n\\tconst hasGlbHeader = () => {\\n\\t\\tconst u8 = new Uint8Array(data);\\n\\t\\treturn u8[0] === 103 && u8[1] === 108 && u8[2] === 84 && u8[3] === 70;\\n\\t};\\n\\tif (filename && filename.toLowerCase().endsWith(\\\".glb\\\") || hasGlbHeader()) {\\n\\t\\tparseGlb(data, callback);\\n\\t} else {\\n\\t\\tcallback(null, {\\n\\t\\t\\tgltfChunk: data,\\n\\t\\t\\tbinaryChunk: null\\n\\t\\t});\\n\\t}\\n};\\nconst createBufferViews = (gltf, buffers, options) => {\\n\\tconst result = [];\\n\\tconst preprocess = options?.bufferView?.preprocess;\\n\\tconst processAsync = options?.bufferView?.processAsync;\\n\\tconst postprocess = options?.bufferView?.postprocess;\\n\\tif (!gltf.bufferViews?.length) {\\n\\t\\treturn result;\\n\\t}\\n\\tfor (let i = 0; i < gltf.bufferViews.length; ++i) {\\n\\t\\tconst gltfBufferView = gltf.bufferViews[i];\\n\\t\\tif (preprocess) {\\n\\t\\t\\tpreprocess(gltfBufferView);\\n\\t\\t}\\n\\t\\tlet promise;\\n\\t\\tif (processAsync) {\\n\\t\\t\\tpromise = new Promise((resolve, reject) => {\\n\\t\\t\\t\\tprocessAsync(gltfBufferView, buffers, (err, result2) => {\\n\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\treject(err);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tresolve(result2);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\tpromise = new Promise((resolve) => {\\n\\t\\t\\t\\tresolve(null);\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tpromise = promise.then((buffer) => {\\n\\t\\t\\tif (buffer) {\\n\\t\\t\\t\\treturn buffer;\\n\\t\\t\\t}\\n\\t\\t\\treturn buffers[gltfBufferView.buffer].then((buffer2) => {\\n\\t\\t\\t\\treturn new Uint8Array(\\n\\t\\t\\t\\t\\tbuffer2.buffer,\\n\\t\\t\\t\\t\\tbuffer2.byteOffset + (gltfBufferView.byteOffset || 0),\\n\\t\\t\\t\\t\\tgltfBufferView.byteLength\\n\\t\\t\\t\\t);\\n\\t\\t\\t});\\n\\t\\t});\\n\\t\\tif (gltfBufferView.hasOwnProperty(\\\"byteStride\\\")) {\\n\\t\\t\\tpromise = promise.then((typedArray) => {\\n\\t\\t\\t\\ttypedArray.byteStride = gltfBufferView.byteStride;\\n\\t\\t\\t\\treturn typedArray;\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tif (postprocess) {\\n\\t\\t\\tpromise = promise.then((typedArray) => {\\n\\t\\t\\t\\tpostprocess(gltfBufferView, typedArray);\\n\\t\\t\\t\\treturn typedArray;\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tresult.push(promise);\\n\\t}\\n\\treturn result;\\n};\\nclass GlbParser {\\n\\t// parse the gltf or glb data asynchronously, loading external resources\\n\\tstatic parse(filename, urlBase, data, device, registry, options, callback) {\\n\\t\\tparseChunk(filename, data, (err, chunks) => {\\n\\t\\t\\tif (err) {\\n\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tparseGltf(chunks.gltfChunk, (err2, gltf) => {\\n\\t\\t\\t\\tif (err2) {\\n\\t\\t\\t\\t\\tcallback(err2);\\n\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst buffers = loadBuffers(gltf, chunks.binaryChunk, urlBase, options);\\n\\t\\t\\t\\tconst bufferViews = createBufferViews(gltf, buffers, options);\\n\\t\\t\\t\\tconst images = createImages(gltf, bufferViews, urlBase, registry, options);\\n\\t\\t\\t\\tconst textures = createTextures(gltf, images, options);\\n\\t\\t\\t\\tcreateResources(device, gltf, bufferViews, textures, options).then((result) => callback(null, result)).catch((err3) => callback(err3));\\n\\t\\t\\t});\\n\\t\\t});\\n\\t}\\n\\tstatic createDefaultMaterial() {\\n\\t\\treturn createMaterial({\\n\\t\\t\\tname: \\\"defaultGlbMaterial\\\"\\n\\t\\t}, []);\\n\\t}\\n}\\n\\nclass BinaryHandler extends ResourceHandler {\\n\\tconstructor(app) {\\n\\t\\tsuper(app, \\\"binary\\\");\\n\\t}\\n\\tload(url, callback) {\\n\\t\\tif (typeof url === \\\"string\\\") {\\n\\t\\t\\turl = {\\n\\t\\t\\t\\tload: url,\\n\\t\\t\\t\\toriginal: url\\n\\t\\t\\t};\\n\\t\\t}\\n\\t\\thttp.get(url.load, {\\n\\t\\t\\tresponseType: Http.ResponseType.ARRAY_BUFFER,\\n\\t\\t\\tretry: this.maxRetries > 0,\\n\\t\\t\\tmaxRetries: this.maxRetries\\n\\t\\t}, (err, response) => {\\n\\t\\t\\tif (!err) {\\n\\t\\t\\t\\tcallback(null, response);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tcallback(`Error loading binary resource: ${url.original} [${err}]`);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n\\topenBinary(data) {\\n\\t\\treturn data.buffer;\\n\\t}\\n}\\n\\nclass GlbContainerResource {\\n\\tconstructor(data, asset, assets, defaultMaterial) {\\n\\t\\tconst createAsset = function(type, resource, index) {\\n\\t\\t\\tconst subAsset = GlbContainerResource.createAsset(asset.name, type, resource, index);\\n\\t\\t\\tassets.add(subAsset);\\n\\t\\t\\treturn subAsset;\\n\\t\\t};\\n\\t\\tconst renders = [];\\n\\t\\tfor (let i = 0; i < data.renders.length; ++i) {\\n\\t\\t\\trenders.push(createAsset(\\\"render\\\", data.renders[i], i));\\n\\t\\t}\\n\\t\\tconst materials = [];\\n\\t\\tfor (let i = 0; i < data.materials.length; ++i) {\\n\\t\\t\\tmaterials.push(createAsset(\\\"material\\\", data.materials[i], i));\\n\\t\\t}\\n\\t\\tconst animations = [];\\n\\t\\tfor (let i = 0; i < data.animations.length; ++i) {\\n\\t\\t\\tanimations.push(createAsset(\\\"animation\\\", data.animations[i], i));\\n\\t\\t}\\n\\t\\tthis.data = data;\\n\\t\\tthis._model = null;\\n\\t\\tthis._assetName = asset.name;\\n\\t\\tthis._assets = assets;\\n\\t\\tthis._defaultMaterial = defaultMaterial;\\n\\t\\tthis.renders = renders;\\n\\t\\tthis.materials = materials;\\n\\t\\tthis.textures = data.textures;\\n\\t\\tthis.animations = animations;\\n\\t}\\n\\tget model() {\\n\\t\\tif (!this._model) {\\n\\t\\t\\tconst model = GlbContainerResource.createModel(this.data, this._defaultMaterial);\\n\\t\\t\\tconst modelAsset = GlbContainerResource.createAsset(this._assetName, \\\"model\\\", model, 0);\\n\\t\\t\\tthis._assets.add(modelAsset);\\n\\t\\t\\tthis._model = modelAsset;\\n\\t\\t}\\n\\t\\treturn this._model;\\n\\t}\\n\\tstatic createAsset(assetName, type, resource, index) {\\n\\t\\tconst subAsset = new Asset(`${assetName}/${type}/${index}`, type, {\\n\\t\\t\\turl: \\\"\\\"\\n\\t\\t});\\n\\t\\tsubAsset.resource = resource;\\n\\t\\tsubAsset.loaded = true;\\n\\t\\treturn subAsset;\\n\\t}\\n\\tinstantiateModelEntity(options) {\\n\\t\\tconst entity = new Entity(void 0, this._assets._loader._app);\\n\\t\\tentity.addComponent(\\\"model\\\", Object.assign({ type: \\\"asset\\\", asset: this.model }, options));\\n\\t\\treturn entity;\\n\\t}\\n\\tinstantiateRenderEntity(options) {\\n\\t\\tconst defaultMaterial = this._defaultMaterial;\\n\\t\\tconst skinnedMeshInstances = [];\\n\\t\\tconst createMeshInstance = function(root, entity, mesh, materials, meshDefaultMaterials, skins, gltfNode, nodeInstancingMap) {\\n\\t\\t\\tconst materialIndex = meshDefaultMaterials[mesh.id];\\n\\t\\t\\tconst material = materialIndex === void 0 ? defaultMaterial : materials[materialIndex];\\n\\t\\t\\tconst meshInstance = new MeshInstance(mesh, material);\\n\\t\\t\\tif (mesh.morph) {\\n\\t\\t\\t\\tmeshInstance.morphInstance = new MorphInstance(mesh.morph);\\n\\t\\t\\t}\\n\\t\\t\\tif (gltfNode.hasOwnProperty(\\\"skin\\\")) {\\n\\t\\t\\t\\tskinnedMeshInstances.push({\\n\\t\\t\\t\\t\\tmeshInstance,\\n\\t\\t\\t\\t\\trootBone: root,\\n\\t\\t\\t\\t\\tentity\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t\\tconst instData = nodeInstancingMap.get(gltfNode);\\n\\t\\t\\tif (instData) {\\n\\t\\t\\t\\tconst matrices = instData.matrices;\\n\\t\\t\\t\\tconst vbFormat = VertexFormat.getDefaultInstancingFormat(mesh.device);\\n\\t\\t\\t\\tconst vb = new VertexBuffer(mesh.device, vbFormat, matrices.length / 16, {\\n\\t\\t\\t\\t\\tdata: matrices\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tmeshInstance.setInstancing(vb);\\n\\t\\t\\t\\tmeshInstance.instancingData._destroyVertexBuffer = true;\\n\\t\\t\\t}\\n\\t\\t\\treturn meshInstance;\\n\\t\\t};\\n\\t\\tconst cloneHierarchy = (root, node, glb) => {\\n\\t\\t\\tconst entity = new Entity(void 0, this._assets._loader._app);\\n\\t\\t\\tnode._cloneInternal(entity);\\n\\t\\t\\tif (!root) root = entity;\\n\\t\\t\\tlet attachedMi = null;\\n\\t\\t\\tlet renderAsset = null;\\n\\t\\t\\tfor (let i = 0; i < glb.nodes.length; i++) {\\n\\t\\t\\t\\tconst glbNode = glb.nodes[i];\\n\\t\\t\\t\\tif (glbNode === node) {\\n\\t\\t\\t\\t\\tconst gltfNode = glb.gltf.nodes[i];\\n\\t\\t\\t\\t\\tif (gltfNode.hasOwnProperty(\\\"mesh\\\")) {\\n\\t\\t\\t\\t\\t\\tconst meshGroup = glb.renders[gltfNode.mesh].meshes;\\n\\t\\t\\t\\t\\t\\trenderAsset = this.renders[gltfNode.mesh];\\n\\t\\t\\t\\t\\t\\tfor (let mi = 0; mi < meshGroup.length; mi++) {\\n\\t\\t\\t\\t\\t\\t\\tconst mesh = meshGroup[mi];\\n\\t\\t\\t\\t\\t\\t\\tif (mesh) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst cloneMi = createMeshInstance(root, entity, mesh, glb.materials, glb.meshDefaultMaterials, glb.skins, gltfNode, glb.nodeInstancingMap);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!attachedMi) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\tattachedMi = [];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tattachedMi.push(cloneMi);\\n\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (glb.lights) {\\n\\t\\t\\t\\t\\t\\tconst lightEntity = glb.lights.get(gltfNode);\\n\\t\\t\\t\\t\\t\\tif (lightEntity) {\\n\\t\\t\\t\\t\\t\\t\\tentity.addChild(lightEntity.clone());\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tif (glb.cameras) {\\n\\t\\t\\t\\t\\t\\tconst cameraEntity = glb.cameras.get(gltfNode);\\n\\t\\t\\t\\t\\t\\tif (cameraEntity) {\\n\\t\\t\\t\\t\\t\\t\\tcameraEntity.camera.system.cloneComponent(cameraEntity, entity);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (attachedMi) {\\n\\t\\t\\t\\tentity.addComponent(\\\"render\\\", Object.assign({\\n\\t\\t\\t\\t\\ttype: \\\"asset\\\",\\n\\t\\t\\t\\t\\tmeshInstances: attachedMi\\n\\t\\t\\t\\t}, options));\\n\\t\\t\\t\\tentity.render.assignAsset(renderAsset);\\n\\t\\t\\t}\\n\\t\\t\\tconst children = node.children;\\n\\t\\t\\tfor (let i = 0; i < children.length; i++) {\\n\\t\\t\\t\\tconst childClone = cloneHierarchy(root, children[i], glb);\\n\\t\\t\\t\\tentity.addChild(childClone);\\n\\t\\t\\t}\\n\\t\\t\\treturn entity;\\n\\t\\t};\\n\\t\\tconst sceneClones = [];\\n\\t\\tfor (const scene of this.data.scenes) {\\n\\t\\t\\tsceneClones.push(cloneHierarchy(null, scene, this.data));\\n\\t\\t}\\n\\t\\tskinnedMeshInstances.forEach((data) => {\\n\\t\\t\\tdata.meshInstance.skinInstance = SkinInstanceCache.createCachedSkinInstance(data.meshInstance.mesh.skin, data.rootBone, data.entity);\\n\\t\\t\\tdata.meshInstance.node.render.rootBone = data.rootBone;\\n\\t\\t});\\n\\t\\treturn GlbContainerResource.createSceneHierarchy(sceneClones, Entity);\\n\\t}\\n\\t// get material variants\\n\\tgetMaterialVariants() {\\n\\t\\treturn this.data.variants ? Object.keys(this.data.variants) : [];\\n\\t}\\n\\t// apply material variant to entity\\n\\tapplyMaterialVariant(entity, name) {\\n\\t\\tconst variant = name ? this.data.variants[name] : null;\\n\\t\\tif (variant === void 0) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst renders = entity.findComponents(\\\"render\\\");\\n\\t\\tfor (let i = 0; i < renders.length; i++) {\\n\\t\\t\\tconst renderComponent = renders[i];\\n\\t\\t\\tthis._applyMaterialVariant(variant, renderComponent.meshInstances);\\n\\t\\t}\\n\\t}\\n\\t// apply material variant to mesh instances\\n\\tapplyMaterialVariantInstances(instances, name) {\\n\\t\\tconst variant = name ? this.data.variants[name] : null;\\n\\t\\tif (variant === void 0) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._applyMaterialVariant(variant, instances);\\n\\t}\\n\\t// internally apply variant to instances\\n\\t_applyMaterialVariant(variant, instances) {\\n\\t\\tinstances.forEach((instance) => {\\n\\t\\t\\tif (variant === null) {\\n\\t\\t\\t\\tinstance.material = this._defaultMaterial;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconst meshVariants = this.data.meshVariants[instance.mesh.id];\\n\\t\\t\\t\\tif (meshVariants) {\\n\\t\\t\\t\\t\\tinstance.material = this.data.materials[meshVariants[variant]];\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n\\t// helper function to create a single hierarchy from an array of nodes\\n\\tstatic createSceneHierarchy(sceneNodes, nodeType) {\\n\\t\\tlet root = null;\\n\\t\\tif (sceneNodes.length === 1) {\\n\\t\\t\\troot = sceneNodes[0];\\n\\t\\t} else {\\n\\t\\t\\troot = new nodeType(\\\"SceneGroup\\\");\\n\\t\\t\\tfor (const scene of sceneNodes) {\\n\\t\\t\\t\\troot.addChild(scene);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn root;\\n\\t}\\n\\t// create a pc.Model from the parsed GLB data structures\\n\\tstatic createModel(glb, defaultMaterial) {\\n\\t\\tconst createMeshInstance = function(model2, mesh, skins, skinInstances2, materials, node, gltfNode) {\\n\\t\\t\\tconst materialIndex = glb.meshDefaultMaterials[mesh.id];\\n\\t\\t\\tconst material = materialIndex === void 0 ? defaultMaterial : materials[materialIndex];\\n\\t\\t\\tconst meshInstance = new MeshInstance(mesh, material, node);\\n\\t\\t\\tif (mesh.morph) {\\n\\t\\t\\t\\tconst morphInstance = new MorphInstance(mesh.morph);\\n\\t\\t\\t\\tmeshInstance.morphInstance = morphInstance;\\n\\t\\t\\t\\tmodel2.morphInstances.push(morphInstance);\\n\\t\\t\\t}\\n\\t\\t\\tif (gltfNode.hasOwnProperty(\\\"skin\\\")) {\\n\\t\\t\\t\\tconst skinIndex = gltfNode.skin;\\n\\t\\t\\t\\tconst skin = skins[skinIndex];\\n\\t\\t\\t\\tmesh.skin = skin;\\n\\t\\t\\t\\tconst skinInstance = skinInstances2[skinIndex];\\n\\t\\t\\t\\tmeshInstance.skinInstance = skinInstance;\\n\\t\\t\\t\\tmodel2.skinInstances.push(skinInstance);\\n\\t\\t\\t}\\n\\t\\t\\tmodel2.meshInstances.push(meshInstance);\\n\\t\\t};\\n\\t\\tconst model = new Model();\\n\\t\\tconst skinInstances = [];\\n\\t\\tfor (const skin of glb.skins) {\\n\\t\\t\\tconst skinInstance = new SkinInstance(skin);\\n\\t\\t\\tskinInstance.bones = skin.bones;\\n\\t\\t\\tskinInstances.push(skinInstance);\\n\\t\\t}\\n\\t\\tmodel.graph = GlbContainerResource.createSceneHierarchy(glb.scenes, GraphNode);\\n\\t\\tfor (let i = 0; i < glb.nodes.length; i++) {\\n\\t\\t\\tconst node = glb.nodes[i];\\n\\t\\t\\tif (node.root === model.graph) {\\n\\t\\t\\t\\tconst gltfNode = glb.gltf.nodes[i];\\n\\t\\t\\t\\tif (gltfNode.hasOwnProperty(\\\"mesh\\\")) {\\n\\t\\t\\t\\t\\tconst meshGroup = glb.renders[gltfNode.mesh].meshes;\\n\\t\\t\\t\\t\\tfor (let mi = 0; mi < meshGroup.length; mi++) {\\n\\t\\t\\t\\t\\t\\tconst mesh = meshGroup[mi];\\n\\t\\t\\t\\t\\t\\tif (mesh) {\\n\\t\\t\\t\\t\\t\\t\\tcreateMeshInstance(model, mesh, glb.skins, skinInstances, glb.materials, node, gltfNode);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn model;\\n\\t}\\n\\tdestroy() {\\n\\t\\tconst registry = this._assets;\\n\\t\\tconst destroyAsset = function(asset) {\\n\\t\\t\\tregistry.remove(asset);\\n\\t\\t\\tasset.unload();\\n\\t\\t};\\n\\t\\tconst destroyAssets = function(assets) {\\n\\t\\t\\tassets.forEach((asset) => {\\n\\t\\t\\t\\tdestroyAsset(asset);\\n\\t\\t\\t});\\n\\t\\t};\\n\\t\\tif (this.animations) {\\n\\t\\t\\tdestroyAssets(this.animations);\\n\\t\\t\\tthis.animations = null;\\n\\t\\t}\\n\\t\\tif (this.textures) {\\n\\t\\t\\tdestroyAssets(this.textures);\\n\\t\\t\\tthis.textures = null;\\n\\t\\t}\\n\\t\\tif (this.materials) {\\n\\t\\t\\tdestroyAssets(this.materials);\\n\\t\\t\\tthis.materials = null;\\n\\t\\t}\\n\\t\\tif (this.renders) {\\n\\t\\t\\tdestroyAssets(this.renders);\\n\\t\\t\\tthis.renders = null;\\n\\t\\t}\\n\\t\\tif (this._model) {\\n\\t\\t\\tdestroyAsset(this._model);\\n\\t\\t\\tthis._model = null;\\n\\t\\t}\\n\\t\\tthis.data = null;\\n\\t\\tthis.assets = null;\\n\\t}\\n}\\n\\nclass GlbContainerParser {\\n\\tconstructor(device, assets, maxRetries) {\\n\\t\\tthis._device = device;\\n\\t\\tthis._assets = assets;\\n\\t\\tthis._defaultMaterial = GlbParser.createDefaultMaterial();\\n\\t\\tthis.maxRetries = maxRetries;\\n\\t}\\n\\t_getUrlWithoutParams(url) {\\n\\t\\treturn url.indexOf(\\\"?\\\") >= 0 ? url.split(\\\"?\\\")[0] : url;\\n\\t}\\n\\tload(url, callback, asset) {\\n\\t\\tAsset.fetchArrayBuffer(url.load, (err, result) => {\\n\\t\\t\\tif (err) {\\n\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tGlbParser.parse(\\n\\t\\t\\t\\t\\tthis._getUrlWithoutParams(url.original),\\n\\t\\t\\t\\t\\tpath.extractPath(url.load),\\n\\t\\t\\t\\t\\tresult,\\n\\t\\t\\t\\t\\tthis._device,\\n\\t\\t\\t\\t\\tasset.registry,\\n\\t\\t\\t\\t\\tasset.options,\\n\\t\\t\\t\\t\\t(err2, result2) => {\\n\\t\\t\\t\\t\\t\\tif (err2) {\\n\\t\\t\\t\\t\\t\\t\\tcallback(err2);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\tcallback(null, new GlbContainerResource(result2, asset, this._assets, this._defaultMaterial));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t);\\n\\t\\t\\t}\\n\\t\\t}, asset, this.maxRetries);\\n\\t}\\n\\topen(url, data, asset) {\\n\\t\\treturn data;\\n\\t}\\n\\tpatch(asset, assets) {\\n\\t}\\n}\\n\\nclass ContainerHandler extends ResourceHandler {\\n\\tconstructor(app) {\\n\\t\\tsuper(app, \\\"container\\\");\\n\\t\\tthis.glbContainerParser = new GlbContainerParser(app.graphicsDevice, app.assets, 0);\\n\\t\\tthis.parsers = {};\\n\\t}\\n\\tset maxRetries(value) {\\n\\t\\tthis.glbContainerParser.maxRetries = value;\\n\\t\\tfor (const parser in this.parsers) {\\n\\t\\t\\tif (this.parsers.hasOwnProperty(parser)) {\\n\\t\\t\\t\\tthis.parsers[parser].maxRetries = value;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget maxRetries() {\\n\\t\\treturn this.glbContainerParser.maxRetries;\\n\\t}\\n\\t_getUrlWithoutParams(url) {\\n\\t\\treturn url.indexOf(\\\"?\\\") >= 0 ? url.split(\\\"?\\\")[0] : url;\\n\\t}\\n\\t_getParser(url) {\\n\\t\\tconst ext = url ? path.getExtension(this._getUrlWithoutParams(url)).toLowerCase().replace(\\\".\\\", \\\"\\\") : null;\\n\\t\\treturn this.parsers[ext] || this.glbContainerParser;\\n\\t}\\n\\tload(url, callback, asset) {\\n\\t\\tif (typeof url === \\\"string\\\") {\\n\\t\\t\\turl = {\\n\\t\\t\\t\\tload: url,\\n\\t\\t\\t\\toriginal: url\\n\\t\\t\\t};\\n\\t\\t}\\n\\t\\tthis._getParser(url.original).load(url, callback, asset);\\n\\t}\\n\\topen(url, data, asset) {\\n\\t\\treturn this._getParser(url).open(url, data, asset);\\n\\t}\\n}\\n\\nconst SH_C0 = 0.28209479177387814;\\nclass SplatCompressedIterator {\\n\\tconstructor(gsplatData, p, r, s, c, sh) {\\n\\t\\tconst unpackUnorm = (value, bits) => {\\n\\t\\t\\tconst t = (1 << bits) - 1;\\n\\t\\t\\treturn (value & t) / t;\\n\\t\\t};\\n\\t\\tconst unpack111011 = (result, value) => {\\n\\t\\t\\tresult.x = unpackUnorm(value >>> 21, 11);\\n\\t\\t\\tresult.y = unpackUnorm(value >>> 11, 10);\\n\\t\\t\\tresult.z = unpackUnorm(value, 11);\\n\\t\\t};\\n\\t\\tconst unpack8888 = (result, value) => {\\n\\t\\t\\tresult.x = unpackUnorm(value >>> 24, 8);\\n\\t\\t\\tresult.y = unpackUnorm(value >>> 16, 8);\\n\\t\\t\\tresult.z = unpackUnorm(value >>> 8, 8);\\n\\t\\t\\tresult.w = unpackUnorm(value, 8);\\n\\t\\t};\\n\\t\\tconst unpackRot = (result, value) => {\\n\\t\\t\\tconst norm = Math.SQRT2;\\n\\t\\t\\tconst a = (unpackUnorm(value >>> 20, 10) - 0.5) * norm;\\n\\t\\t\\tconst b = (unpackUnorm(value >>> 10, 10) - 0.5) * norm;\\n\\t\\t\\tconst c2 = (unpackUnorm(value, 10) - 0.5) * norm;\\n\\t\\t\\tconst m = Math.sqrt(1 - (a * a + b * b + c2 * c2));\\n\\t\\t\\tswitch (value >>> 30) {\\n\\t\\t\\t\\tcase 0:\\n\\t\\t\\t\\t\\tresult.set(a, b, c2, m);\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase 1:\\n\\t\\t\\t\\t\\tresult.set(m, b, c2, a);\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase 2:\\n\\t\\t\\t\\t\\tresult.set(b, m, c2, a);\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase 3:\\n\\t\\t\\t\\t\\tresult.set(b, c2, m, a);\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tconst lerp = (a, b, t) => a * (1 - t) + b * t;\\n\\t\\tconst { chunkData, chunkSize, vertexData, shData0, shData1, shData2, shBands } = gsplatData;\\n\\t\\tconst shCoeffs = [3, 8, 15][shBands - 1];\\n\\t\\tthis.read = (i) => {\\n\\t\\t\\tconst ci = Math.floor(i / 256) * chunkSize;\\n\\t\\t\\tif (p) {\\n\\t\\t\\t\\tunpack111011(p, vertexData[i * 4 + 0]);\\n\\t\\t\\t\\tp.x = lerp(chunkData[ci + 0], chunkData[ci + 3], p.x);\\n\\t\\t\\t\\tp.y = lerp(chunkData[ci + 1], chunkData[ci + 4], p.y);\\n\\t\\t\\t\\tp.z = lerp(chunkData[ci + 2], chunkData[ci + 5], p.z);\\n\\t\\t\\t}\\n\\t\\t\\tif (r) {\\n\\t\\t\\t\\tunpackRot(r, vertexData[i * 4 + 1]);\\n\\t\\t\\t}\\n\\t\\t\\tif (s) {\\n\\t\\t\\t\\tunpack111011(s, vertexData[i * 4 + 2]);\\n\\t\\t\\t\\ts.x = lerp(chunkData[ci + 6], chunkData[ci + 9], s.x);\\n\\t\\t\\t\\ts.y = lerp(chunkData[ci + 7], chunkData[ci + 10], s.y);\\n\\t\\t\\t\\ts.z = lerp(chunkData[ci + 8], chunkData[ci + 11], s.z);\\n\\t\\t\\t}\\n\\t\\t\\tif (c) {\\n\\t\\t\\t\\tunpack8888(c, vertexData[i * 4 + 3]);\\n\\t\\t\\t\\tif (chunkSize > 12) {\\n\\t\\t\\t\\t\\tc.x = lerp(chunkData[ci + 12], chunkData[ci + 15], c.x);\\n\\t\\t\\t\\t\\tc.y = lerp(chunkData[ci + 13], chunkData[ci + 16], c.y);\\n\\t\\t\\t\\t\\tc.z = lerp(chunkData[ci + 14], chunkData[ci + 17], c.z);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (sh && shBands > 0) {\\n\\t\\t\\t\\tconst shData = [shData0, shData1, shData2];\\n\\t\\t\\t\\tfor (let j = 0; j < 3; ++j) {\\n\\t\\t\\t\\t\\tfor (let k = 0; k < 15; ++k) {\\n\\t\\t\\t\\t\\t\\tsh[j * 15 + k] = k < shCoeffs ? shData[j][i * 16 + k] * (8 / 255) - 4 : 0;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t};\\n\\t}\\n}\\nclass GSplatCompressedData {\\n\\tnumSplats;\\n\\tcomments;\\n\\tchunkData;\\n\\tvertexData;\\n\\tshData0;\\n\\tshData1;\\n\\tshData2;\\n\\tshBands;\\n\\tcreateIter(p, r, s, c, sh) {\\n\\t\\treturn new SplatCompressedIterator(this, p, r, s, c, sh);\\n\\t}\\n\\tcalcAabb(result) {\\n\\t\\tconst { chunkData, numChunks, chunkSize } = this;\\n\\t\\tlet s = Math.exp(Math.max(chunkData[9], chunkData[10], chunkData[11]));\\n\\t\\tlet mx = chunkData[0] - s;\\n\\t\\tlet my = chunkData[1] - s;\\n\\t\\tlet mz = chunkData[2] - s;\\n\\t\\tlet Mx = chunkData[3] + s;\\n\\t\\tlet My = chunkData[4] + s;\\n\\t\\tlet Mz = chunkData[5] + s;\\n\\t\\tfor (let i = 1; i < numChunks; ++i) {\\n\\t\\t\\tconst off = i * chunkSize;\\n\\t\\t\\ts = Math.exp(Math.max(chunkData[off + 9], chunkData[off + 10], chunkData[off + 11]));\\n\\t\\t\\tmx = Math.min(mx, chunkData[off + 0] - s);\\n\\t\\t\\tmy = Math.min(my, chunkData[off + 1] - s);\\n\\t\\t\\tmz = Math.min(mz, chunkData[off + 2] - s);\\n\\t\\t\\tMx = Math.max(Mx, chunkData[off + 3] + s);\\n\\t\\t\\tMy = Math.max(My, chunkData[off + 4] + s);\\n\\t\\t\\tMz = Math.max(Mz, chunkData[off + 5] + s);\\n\\t\\t}\\n\\t\\tresult.center.set((mx + Mx) * 0.5, (my + My) * 0.5, (mz + Mz) * 0.5);\\n\\t\\tresult.halfExtents.set((Mx - mx) * 0.5, (My - my) * 0.5, (Mz - mz) * 0.5);\\n\\t\\treturn true;\\n\\t}\\n\\tgetCenters() {\\n\\t\\tconst { vertexData, chunkData, numChunks, chunkSize } = this;\\n\\t\\tconst result = new Float32Array(this.numSplats * 3);\\n\\t\\tlet mx, my, mz, Mx, My, Mz;\\n\\t\\tfor (let c = 0; c < numChunks; ++c) {\\n\\t\\t\\tconst off = c * chunkSize;\\n\\t\\t\\tmx = chunkData[off + 0];\\n\\t\\t\\tmy = chunkData[off + 1];\\n\\t\\t\\tmz = chunkData[off + 2];\\n\\t\\t\\tMx = chunkData[off + 3];\\n\\t\\t\\tMy = chunkData[off + 4];\\n\\t\\t\\tMz = chunkData[off + 5];\\n\\t\\t\\tconst end = Math.min(this.numSplats, (c + 1) * 256);\\n\\t\\t\\tfor (let i = c * 256; i < end; ++i) {\\n\\t\\t\\t\\tconst p = vertexData[i * 4];\\n\\t\\t\\t\\tconst px = (p >>> 21) / 2047;\\n\\t\\t\\t\\tconst py = (p >>> 11 & 1023) / 1023;\\n\\t\\t\\t\\tconst pz = (p & 2047) / 2047;\\n\\t\\t\\t\\tresult[i * 3 + 0] = (1 - px) * mx + px * Mx;\\n\\t\\t\\t\\tresult[i * 3 + 1] = (1 - py) * my + py * My;\\n\\t\\t\\t\\tresult[i * 3 + 2] = (1 - pz) * mz + pz * Mz;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn result;\\n\\t}\\n\\tgetChunks(result) {\\n\\t\\tconst { chunkData, numChunks, chunkSize } = this;\\n\\t\\tlet mx, my, mz, Mx, My, Mz;\\n\\t\\tfor (let c = 0; c < numChunks; ++c) {\\n\\t\\t\\tconst off = c * chunkSize;\\n\\t\\t\\tmx = chunkData[off + 0];\\n\\t\\t\\tmy = chunkData[off + 1];\\n\\t\\t\\tmz = chunkData[off + 2];\\n\\t\\t\\tMx = chunkData[off + 3];\\n\\t\\t\\tMy = chunkData[off + 4];\\n\\t\\t\\tMz = chunkData[off + 5];\\n\\t\\t\\tresult[c * 6 + 0] = mx;\\n\\t\\t\\tresult[c * 6 + 1] = my;\\n\\t\\t\\tresult[c * 6 + 2] = mz;\\n\\t\\t\\tresult[c * 6 + 3] = Mx;\\n\\t\\t\\tresult[c * 6 + 4] = My;\\n\\t\\t\\tresult[c * 6 + 5] = Mz;\\n\\t\\t}\\n\\t}\\n\\tcalcFocalPoint(result) {\\n\\t\\tconst { chunkData, numChunks, chunkSize } = this;\\n\\t\\tresult.x = 0;\\n\\t\\tresult.y = 0;\\n\\t\\tresult.z = 0;\\n\\t\\tfor (let i = 0; i < numChunks; ++i) {\\n\\t\\t\\tconst off = i * chunkSize;\\n\\t\\t\\tresult.x += chunkData[off + 0] + chunkData[off + 3];\\n\\t\\t\\tresult.y += chunkData[off + 1] + chunkData[off + 4];\\n\\t\\t\\tresult.z += chunkData[off + 2] + chunkData[off + 5];\\n\\t\\t}\\n\\t\\tresult.mulScalar(0.5 / numChunks);\\n\\t}\\n\\tget isCompressed() {\\n\\t\\treturn true;\\n\\t}\\n\\tget numChunks() {\\n\\t\\treturn Math.ceil(this.numSplats / 256);\\n\\t}\\n\\tget chunkSize() {\\n\\t\\treturn this.chunkData.length / this.numChunks;\\n\\t}\\n\\t// decompress into GSplatData\\n\\tdecompress() {\\n\\t\\tconst members = [\\n\\t\\t\\t\\\"x\\\",\\n\\t\\t\\t\\\"y\\\",\\n\\t\\t\\t\\\"z\\\",\\n\\t\\t\\t\\\"f_dc_0\\\",\\n\\t\\t\\t\\\"f_dc_1\\\",\\n\\t\\t\\t\\\"f_dc_2\\\",\\n\\t\\t\\t\\\"opacity\\\",\\n\\t\\t\\t\\\"scale_0\\\",\\n\\t\\t\\t\\\"scale_1\\\",\\n\\t\\t\\t\\\"scale_2\\\",\\n\\t\\t\\t\\\"rot_0\\\",\\n\\t\\t\\t\\\"rot_1\\\",\\n\\t\\t\\t\\\"rot_2\\\",\\n\\t\\t\\t\\\"rot_3\\\"\\n\\t\\t];\\n\\t\\tconst { shBands } = this;\\n\\t\\tif (shBands > 0) {\\n\\t\\t\\tconst shMembers = [];\\n\\t\\t\\tfor (let i = 0; i < 45; ++i) {\\n\\t\\t\\t\\tshMembers.push(`f_rest_${i}`);\\n\\t\\t\\t}\\n\\t\\t\\tconst location = Math.max(...[\\\"f_dc_0\\\", \\\"f_dc_1\\\", \\\"f_dc_2\\\"].map((name) => members.indexOf(name)));\\n\\t\\t\\tmembers.splice(location + 1, 0, ...shMembers);\\n\\t\\t}\\n\\t\\tconst data = {};\\n\\t\\tmembers.forEach((name) => {\\n\\t\\t\\tdata[name] = new Float32Array(this.numSplats);\\n\\t\\t});\\n\\t\\tconst p = new Vec3();\\n\\t\\tconst r = new Quat();\\n\\t\\tconst s = new Vec3();\\n\\t\\tconst c = new Vec4();\\n\\t\\tconst sh = shBands > 0 ? new Float32Array(45) : null;\\n\\t\\tconst iter = this.createIter(p, r, s, c, sh);\\n\\t\\tfor (let i = 0; i < this.numSplats; ++i) {\\n\\t\\t\\titer.read(i);\\n\\t\\t\\tdata.x[i] = p.x;\\n\\t\\t\\tdata.y[i] = p.y;\\n\\t\\t\\tdata.z[i] = p.z;\\n\\t\\t\\tdata.rot_1[i] = r.x;\\n\\t\\t\\tdata.rot_2[i] = r.y;\\n\\t\\t\\tdata.rot_3[i] = r.z;\\n\\t\\t\\tdata.rot_0[i] = r.w;\\n\\t\\t\\tdata.scale_0[i] = s.x;\\n\\t\\t\\tdata.scale_1[i] = s.y;\\n\\t\\t\\tdata.scale_2[i] = s.z;\\n\\t\\t\\tdata.f_dc_0[i] = (c.x - 0.5) / SH_C0;\\n\\t\\t\\tdata.f_dc_1[i] = (c.y - 0.5) / SH_C0;\\n\\t\\t\\tdata.f_dc_2[i] = (c.z - 0.5) / SH_C0;\\n\\t\\t\\tdata.opacity[i] = c.w <= 0 ? -40 : c.w >= 1 ? 40 : -Math.log(1 / c.w - 1);\\n\\t\\t\\tif (sh) {\\n\\t\\t\\t\\tfor (let c2 = 0; c2 < 45; ++c2) {\\n\\t\\t\\t\\t\\tdata[`f_rest_${c2}`][i] = sh[c2];\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn new GSplatData([{\\n\\t\\t\\tname: \\\"vertex\\\",\\n\\t\\t\\tcount: this.numSplats,\\n\\t\\t\\tproperties: members.map((name) => {\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\tname,\\n\\t\\t\\t\\t\\ttype: \\\"float\\\",\\n\\t\\t\\t\\t\\tbyteSize: 4,\\n\\t\\t\\t\\t\\tstorage: data[name]\\n\\t\\t\\t\\t};\\n\\t\\t\\t})\\n\\t\\t}], this.comments);\\n\\t}\\n}\\n\\nconst strideCopy = (target, targetStride, src, srcStride, numEntries) => {\\n\\tfor (let i = 0; i < numEntries; ++i) {\\n\\t\\tfor (let j = 0; j < srcStride; ++j) {\\n\\t\\t\\ttarget[i * targetStride + j] = src[i * srcStride + j];\\n\\t\\t}\\n\\t}\\n};\\nclass GSplatCompressedResource extends GSplatResourceBase {\\n\\tconstructor(device, gsplatData, options = {}) {\\n\\t\\tsuper(device, gsplatData, options);\\n\\t\\tconst { chunkData, chunkSize, numChunks, numSplats, vertexData, shBands } = gsplatData;\\n\\t\\tthis.chunks = new Float32Array(numChunks * 6);\\n\\t\\tgsplatData.getChunks(this.chunks);\\n\\t\\tconst formatStreams = [\\n\\t\\t\\t{ name: \\\"packedTexture\\\", format: PIXELFORMAT_RGBA32U }\\n\\t\\t];\\n\\t\\tif (shBands > 0) {\\n\\t\\t\\tformatStreams.push({ name: \\\"shTexture0\\\", format: PIXELFORMAT_RGBA32U });\\n\\t\\t\\tformatStreams.push({ name: \\\"shTexture1\\\", format: PIXELFORMAT_RGBA32U });\\n\\t\\t\\tformatStreams.push({ name: \\\"shTexture2\\\", format: PIXELFORMAT_RGBA32U });\\n\\t\\t}\\n\\t\\tthis._format = new GSplatFormat(device, formatStreams, {\\n\\t\\t\\treadGLSL: '#include \\\"gsplatCompressedVS\\\"',\\n\\t\\t\\treadWGSL: '#include \\\"gsplatCompressedVS\\\"'\\n\\t\\t});\\n\\t\\tthis.streams.init(this.format, numSplats);\\n\\t\\tconst packedTexture = this.streams.getTexture(\\\"packedTexture\\\");\\n\\t\\tconst packedData = packedTexture.lock();\\n\\t\\tpackedData.set(vertexData);\\n\\t\\tpackedTexture.unlock();\\n\\t\\tif (shBands > 0) {\\n\\t\\t\\tconst shTexture0 = this.streams.getTexture(\\\"shTexture0\\\");\\n\\t\\t\\tconst shTexture1 = this.streams.getTexture(\\\"shTexture1\\\");\\n\\t\\t\\tconst shTexture2 = this.streams.getTexture(\\\"shTexture2\\\");\\n\\t\\t\\tconst sh0Data = shTexture0.lock();\\n\\t\\t\\tsh0Data.set(new Uint32Array(gsplatData.shData0.buffer));\\n\\t\\t\\tshTexture0.unlock();\\n\\t\\t\\tconst sh1Data = shTexture1.lock();\\n\\t\\t\\tsh1Data.set(new Uint32Array(gsplatData.shData1.buffer));\\n\\t\\t\\tshTexture1.unlock();\\n\\t\\t\\tconst sh2Data = shTexture2.lock();\\n\\t\\t\\tsh2Data.set(new Uint32Array(gsplatData.shData2.buffer));\\n\\t\\t\\tshTexture2.unlock();\\n\\t\\t}\\n\\t\\tconst chunkTextureSize = this.evalChunkTextureSize(numChunks);\\n\\t\\tconst chunkTexture = this.streams.createTexture(\\\"chunkTexture\\\", PIXELFORMAT_RGBA32F, chunkTextureSize);\\n\\t\\tthis.streams.textures.set(\\\"chunkTexture\\\", chunkTexture);\\n\\t\\tconst chunkTextureData = chunkTexture.lock();\\n\\t\\tstrideCopy(chunkTextureData, 20, chunkData, chunkSize, numChunks);\\n\\t\\tif (chunkSize === 12) {\\n\\t\\t\\tfor (let i = 0; i < numChunks; ++i) {\\n\\t\\t\\t\\tchunkTextureData[i * 20 + 15] = 1;\\n\\t\\t\\t\\tchunkTextureData[i * 20 + 16] = 1;\\n\\t\\t\\t\\tchunkTextureData[i * 20 + 17] = 1;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tchunkTexture.unlock();\\n\\t}\\n\\tdestroy() {\\n\\t\\tsuper.destroy();\\n\\t}\\n\\tconfigureMaterialDefines(defines) {\\n\\t\\tdefines.set(\\\"SH_BANDS\\\", this.streams.textures.has(\\\"shTexture0\\\") ? 3 : 0);\\n\\t}\\n\\tevalChunkTextureSize(numChunks) {\\n\\t\\tconst width = Math.ceil(Math.sqrt(numChunks));\\n\\t\\tconst height = Math.ceil(numChunks / width);\\n\\t\\treturn new Vec2(width * 5, height);\\n\\t}\\n}\\n\\nconst magicBytes = new Uint8Array([112, 108, 121, 10]);\\nconst endHeaderBytes = new Uint8Array([10, 101, 110, 100, 95, 104, 101, 97, 100, 101, 114, 10]);\\nconst dataTypeMap = /* @__PURE__ */ new Map([\\n\\t[\\\"char\\\", Int8Array],\\n\\t[\\\"uchar\\\", Uint8Array],\\n\\t[\\\"short\\\", Int16Array],\\n\\t[\\\"ushort\\\", Uint16Array],\\n\\t[\\\"int\\\", Int32Array],\\n\\t[\\\"uint\\\", Uint32Array],\\n\\t[\\\"float\\\", Float32Array],\\n\\t[\\\"double\\\", Float64Array]\\n]);\\nclass StreamBuf {\\n\\treader;\\n\\tprogressFunc;\\n\\tdata;\\n\\tview;\\n\\thead = 0;\\n\\ttail = 0;\\n\\tconstructor(reader, progressFunc) {\\n\\t\\tthis.reader = reader;\\n\\t\\tthis.progressFunc = progressFunc;\\n\\t}\\n\\t// read the next chunk of data\\n\\tasync read() {\\n\\t\\tconst { value, done } = await this.reader.read();\\n\\t\\tif (done) {\\n\\t\\t\\tthrow new Error(\\\"Stream finished before end of header\\\");\\n\\t\\t}\\n\\t\\tthis.push(value);\\n\\t\\tthis.progressFunc?.(value.byteLength);\\n\\t}\\n\\t// append data to the buffer\\n\\tpush(data) {\\n\\t\\tif (!this.data) {\\n\\t\\t\\tthis.data = data;\\n\\t\\t\\tthis.view = new DataView(this.data.buffer);\\n\\t\\t\\tthis.tail = data.length;\\n\\t\\t} else {\\n\\t\\t\\tconst remaining = this.tail - this.head;\\n\\t\\t\\tconst newSize = remaining + data.length;\\n\\t\\t\\tif (this.data.length >= newSize) {\\n\\t\\t\\t\\tif (this.head > 0) {\\n\\t\\t\\t\\t\\tthis.data.copyWithin(0, this.head, this.tail);\\n\\t\\t\\t\\t\\tthis.data.set(data, remaining);\\n\\t\\t\\t\\t\\tthis.head = 0;\\n\\t\\t\\t\\t\\tthis.tail = newSize;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tthis.data.set(data, this.tail);\\n\\t\\t\\t\\t\\tthis.tail += data.length;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconst tmp = new Uint8Array(newSize);\\n\\t\\t\\t\\tif (this.head > 0 || this.tail < this.data.length) {\\n\\t\\t\\t\\t\\ttmp.set(this.data.subarray(this.head, this.tail), 0);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\ttmp.set(this.data, 0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttmp.set(data, remaining);\\n\\t\\t\\t\\tthis.data = tmp;\\n\\t\\t\\t\\tthis.view = new DataView(this.data.buffer);\\n\\t\\t\\t\\tthis.head = 0;\\n\\t\\t\\t\\tthis.tail = newSize;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t// remove the read data from the head of the buffer\\n\\tcompact() {\\n\\t\\tif (this.head > 0) {\\n\\t\\t\\tthis.data.copyWithin(0, this.head, this.tail);\\n\\t\\t\\tthis.tail -= this.head;\\n\\t\\t\\tthis.head = 0;\\n\\t\\t}\\n\\t}\\n\\tget remaining() {\\n\\t\\treturn this.tail - this.head;\\n\\t}\\n\\t// helpers for extracting data from head\\n\\tgetInt8() {\\n\\t\\tconst result = this.view.getInt8(this.head);\\n\\t\\tthis.head++;\\n\\t\\treturn result;\\n\\t}\\n\\tgetUint8() {\\n\\t\\tconst result = this.view.getUint8(this.head);\\n\\t\\tthis.head++;\\n\\t\\treturn result;\\n\\t}\\n\\tgetInt16() {\\n\\t\\tconst result = this.view.getInt16(this.head, true);\\n\\t\\tthis.head += 2;\\n\\t\\treturn result;\\n\\t}\\n\\tgetUint16() {\\n\\t\\tconst result = this.view.getUint16(this.head, true);\\n\\t\\tthis.head += 2;\\n\\t\\treturn result;\\n\\t}\\n\\tgetInt32() {\\n\\t\\tconst result = this.view.getInt32(this.head, true);\\n\\t\\tthis.head += 4;\\n\\t\\treturn result;\\n\\t}\\n\\tgetUint32() {\\n\\t\\tconst result = this.view.getUint32(this.head, true);\\n\\t\\tthis.head += 4;\\n\\t\\treturn result;\\n\\t}\\n\\tgetFloat32() {\\n\\t\\tconst result = this.view.getFloat32(this.head, true);\\n\\t\\tthis.head += 4;\\n\\t\\treturn result;\\n\\t}\\n\\tgetFloat64() {\\n\\t\\tconst result = this.view.getFloat64(this.head, true);\\n\\t\\tthis.head += 8;\\n\\t\\treturn result;\\n\\t}\\n}\\nconst parseHeader = (lines) => {\\n\\tconst elements = [];\\n\\tconst comments = [];\\n\\tlet format;\\n\\tfor (let i = 1; i < lines.length; ++i) {\\n\\t\\tconst words = lines[i].split(\\\" \\\");\\n\\t\\tswitch (words[0]) {\\n\\t\\t\\tcase \\\"comment\\\":\\n\\t\\t\\t\\tcomments.push(words.slice(1).join(\\\" \\\"));\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase \\\"format\\\":\\n\\t\\t\\t\\tformat = words[1];\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase \\\"element\\\":\\n\\t\\t\\t\\telements.push({\\n\\t\\t\\t\\t\\tname: words[1],\\n\\t\\t\\t\\t\\tcount: parseInt(words[2], 10),\\n\\t\\t\\t\\t\\tproperties: []\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase \\\"property\\\": {\\n\\t\\t\\t\\tif (!dataTypeMap.has(words[1])) {\\n\\t\\t\\t\\t\\tthrow new Error(`Unrecognized property data type '${words[1]}' in ply header`);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst element = elements[elements.length - 1];\\n\\t\\t\\t\\telement.properties.push({\\n\\t\\t\\t\\t\\ttype: words[1],\\n\\t\\t\\t\\t\\tname: words[2],\\n\\t\\t\\t\\t\\tstorage: null,\\n\\t\\t\\t\\t\\tbyteSize: dataTypeMap.get(words[1]).BYTES_PER_ELEMENT\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\tdefault:\\n\\t\\t\\t\\tthrow new Error(`Unrecognized header value '${words[0]}' in ply header`);\\n\\t\\t}\\n\\t}\\n\\treturn { elements, format, comments };\\n};\\nconst isCompressedPly = (elements) => {\\n\\tconst chunkProperties = [\\n\\t\\t\\\"min_x\\\",\\n\\t\\t\\\"min_y\\\",\\n\\t\\t\\\"min_z\\\",\\n\\t\\t\\\"max_x\\\",\\n\\t\\t\\\"max_y\\\",\\n\\t\\t\\\"max_z\\\",\\n\\t\\t\\\"min_scale_x\\\",\\n\\t\\t\\\"min_scale_y\\\",\\n\\t\\t\\\"min_scale_z\\\",\\n\\t\\t\\\"max_scale_x\\\",\\n\\t\\t\\\"max_scale_y\\\",\\n\\t\\t\\\"max_scale_z\\\",\\n\\t\\t\\\"min_r\\\",\\n\\t\\t\\\"min_g\\\",\\n\\t\\t\\\"min_b\\\",\\n\\t\\t\\\"max_r\\\",\\n\\t\\t\\\"max_g\\\",\\n\\t\\t\\\"max_b\\\"\\n\\t];\\n\\tconst vertexProperties = [\\n\\t\\t\\\"packed_position\\\",\\n\\t\\t\\\"packed_rotation\\\",\\n\\t\\t\\\"packed_scale\\\",\\n\\t\\t\\\"packed_color\\\"\\n\\t];\\n\\tconst shProperties = new Array(45).fill(\\\"\\\").map((_, i) => `f_rest_${i}`);\\n\\tconst hasBaseElements = () => {\\n\\t\\treturn elements[0].name === \\\"chunk\\\" && elements[0].properties.every((p, i) => p.name === chunkProperties[i] && p.type === \\\"float\\\") && elements[1].name === \\\"vertex\\\" && elements[1].properties.every((p, i) => p.name === vertexProperties[i] && p.type === \\\"uint\\\");\\n\\t};\\n\\tconst hasSHElements = () => {\\n\\t\\treturn elements[2].name === \\\"sh\\\" && [9, 24, 45].indexOf(elements[2].properties.length) !== -1 && elements[2].properties.every((p, i) => p.name === shProperties[i] && p.type === \\\"uchar\\\");\\n\\t};\\n\\treturn elements.length === 2 && hasBaseElements() || elements.length === 3 && hasBaseElements() && hasSHElements();\\n};\\nconst isFloatPly = (elements) => {\\n\\treturn elements.length === 1 && elements[0].name === \\\"vertex\\\" && elements[0].properties.every((p) => p.type === \\\"float\\\");\\n};\\nconst readCompressedPly = async (streamBuf, elements, comments) => {\\n\\tconst result = new GSplatCompressedData();\\n\\tresult.comments = comments;\\n\\tconst numChunks = elements[0].count;\\n\\tconst numChunkProperties = elements[0].properties.length;\\n\\tconst numVertices = elements[1].count;\\n\\tconst evalStorageSize = (count) => {\\n\\t\\tconst width = Math.ceil(Math.sqrt(count));\\n\\t\\tconst height = Math.ceil(count / width);\\n\\t\\treturn width * height;\\n\\t};\\n\\tconst storageSize = evalStorageSize(numVertices);\\n\\tresult.numSplats = numVertices;\\n\\tresult.chunkData = new Float32Array(numChunks * numChunkProperties);\\n\\tresult.vertexData = new Uint32Array(storageSize * 4);\\n\\tconst read = async (buffer, length) => {\\n\\t\\tconst target = new Uint8Array(buffer);\\n\\t\\tlet cursor = 0;\\n\\t\\twhile (cursor < length) {\\n\\t\\t\\twhile (streamBuf.remaining === 0) {\\n\\t\\t\\t\\tawait streamBuf.read();\\n\\t\\t\\t}\\n\\t\\t\\tconst toCopy = Math.min(length - cursor, streamBuf.remaining);\\n\\t\\t\\tconst src = streamBuf.data;\\n\\t\\t\\tfor (let i = 0; i < toCopy; ++i) {\\n\\t\\t\\t\\ttarget[cursor++] = src[streamBuf.head++];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t};\\n\\tawait read(result.chunkData.buffer, numChunks * numChunkProperties * 4);\\n\\tawait read(result.vertexData.buffer, numVertices * 4 * 4);\\n\\tif (elements.length === 3) {\\n\\t\\tconst texStorageSize = storageSize * 16;\\n\\t\\tconst shData0 = new Uint8Array(texStorageSize);\\n\\t\\tconst shData1 = new Uint8Array(texStorageSize);\\n\\t\\tconst shData2 = new Uint8Array(texStorageSize);\\n\\t\\tconst chunkSize = 1024;\\n\\t\\tconst srcCoeffs = elements[2].properties.length / 3;\\n\\t\\tconst tmpBuf = new Uint8Array(chunkSize * srcCoeffs * 3);\\n\\t\\tfor (let i = 0; i < result.numSplats; i += chunkSize) {\\n\\t\\t\\tconst toRead = Math.min(chunkSize, result.numSplats - i);\\n\\t\\t\\tawait read(tmpBuf.buffer, toRead * srcCoeffs * 3);\\n\\t\\t\\tfor (let j = 0; j < toRead; ++j) {\\n\\t\\t\\t\\tfor (let k = 0; k < 15; ++k) {\\n\\t\\t\\t\\t\\tconst tidx = (i + j) * 16 + k;\\n\\t\\t\\t\\t\\tif (k < srcCoeffs) {\\n\\t\\t\\t\\t\\t\\tshData0[tidx] = tmpBuf[(j * 3 + 0) * srcCoeffs + k];\\n\\t\\t\\t\\t\\t\\tshData1[tidx] = tmpBuf[(j * 3 + 1) * srcCoeffs + k];\\n\\t\\t\\t\\t\\t\\tshData2[tidx] = tmpBuf[(j * 3 + 2) * srcCoeffs + k];\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tshData0[tidx] = 127;\\n\\t\\t\\t\\t\\t\\tshData1[tidx] = 127;\\n\\t\\t\\t\\t\\t\\tshData2[tidx] = 127;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tresult.shData0 = shData0;\\n\\t\\tresult.shData1 = shData1;\\n\\t\\tresult.shData2 = shData2;\\n\\t\\tresult.shBands = { 3: 1, 8: 2, 15: 3 }[srcCoeffs];\\n\\t} else {\\n\\t\\tresult.shBands = 0;\\n\\t}\\n\\treturn result;\\n};\\nconst readFloatPly = async (streamBuf, elements, comments) => {\\n\\tconst element = elements[0];\\n\\tconst properties = element.properties;\\n\\tconst numProperties = properties.length;\\n\\tconst storage = properties.map((p) => p.storage);\\n\\tconst inputSize = properties.reduce((a, p) => a + p.byteSize, 0);\\n\\tlet vertexIdx = 0;\\n\\tlet floatData;\\n\\tconst checkFloatData = () => {\\n\\t\\tconst buffer = streamBuf.data.buffer;\\n\\t\\tif (floatData?.buffer !== buffer) {\\n\\t\\t\\tfloatData = new Float32Array(buffer, 0, buffer.byteLength / 4);\\n\\t\\t}\\n\\t};\\n\\tcheckFloatData();\\n\\twhile (vertexIdx < element.count) {\\n\\t\\twhile (streamBuf.remaining < inputSize) {\\n\\t\\t\\tawait streamBuf.read();\\n\\t\\t\\tcheckFloatData();\\n\\t\\t}\\n\\t\\tconst toRead = Math.min(element.count - vertexIdx, Math.floor(streamBuf.remaining / inputSize));\\n\\t\\tfor (let j = 0; j < numProperties; ++j) {\\n\\t\\t\\tconst s = storage[j];\\n\\t\\t\\tfor (let n = 0; n < toRead; ++n) {\\n\\t\\t\\t\\ts[n + vertexIdx] = floatData[n * numProperties + j];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tvertexIdx += toRead;\\n\\t\\tstreamBuf.head += toRead * inputSize;\\n\\t}\\n\\treturn new GSplatData(elements, comments);\\n};\\nconst readGeneralPly = async (streamBuf, elements, comments) => {\\n\\tfor (let i = 0; i < elements.length; ++i) {\\n\\t\\tconst element = elements[i];\\n\\t\\tconst inputSize = element.properties.reduce((a, p) => a + p.byteSize, 0);\\n\\t\\tconst propertyParsingFunctions = element.properties.map((p) => {\\n\\t\\t\\tif (p.storage) {\\n\\t\\t\\t\\tswitch (p.type) {\\n\\t\\t\\t\\t\\tcase \\\"char\\\":\\n\\t\\t\\t\\t\\t\\treturn (streamBuf2, c2) => {\\n\\t\\t\\t\\t\\t\\t\\tp.storage[c2] = streamBuf2.getInt8();\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\tcase \\\"uchar\\\":\\n\\t\\t\\t\\t\\t\\treturn (streamBuf2, c2) => {\\n\\t\\t\\t\\t\\t\\t\\tp.storage[c2] = streamBuf2.getUint8();\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\tcase \\\"short\\\":\\n\\t\\t\\t\\t\\t\\treturn (streamBuf2, c2) => {\\n\\t\\t\\t\\t\\t\\t\\tp.storage[c2] = streamBuf2.getInt16();\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\tcase \\\"ushort\\\":\\n\\t\\t\\t\\t\\t\\treturn (streamBuf2, c2) => {\\n\\t\\t\\t\\t\\t\\t\\tp.storage[c2] = streamBuf2.getUint16();\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\tcase \\\"int\\\":\\n\\t\\t\\t\\t\\t\\treturn (streamBuf2, c2) => {\\n\\t\\t\\t\\t\\t\\t\\tp.storage[c2] = streamBuf2.getInt32();\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\tcase \\\"uint\\\":\\n\\t\\t\\t\\t\\t\\treturn (streamBuf2, c2) => {\\n\\t\\t\\t\\t\\t\\t\\tp.storage[c2] = streamBuf2.getUint32();\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\tcase \\\"float\\\":\\n\\t\\t\\t\\t\\t\\treturn (streamBuf2, c2) => {\\n\\t\\t\\t\\t\\t\\t\\tp.storage[c2] = streamBuf2.getFloat32();\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\tcase \\\"double\\\":\\n\\t\\t\\t\\t\\t\\treturn (streamBuf2, c2) => {\\n\\t\\t\\t\\t\\t\\t\\tp.storage[c2] = streamBuf2.getFloat64();\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\tthrow new Error(`Unsupported property data type '${p.type}' in ply header`);\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\treturn (streamBuf2) => {\\n\\t\\t\\t\\t\\tstreamBuf2.head += p.byteSize;\\n\\t\\t\\t\\t};\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tlet c = 0;\\n\\t\\twhile (c < element.count) {\\n\\t\\t\\twhile (streamBuf.remaining < inputSize) {\\n\\t\\t\\t\\tawait streamBuf.read();\\n\\t\\t\\t}\\n\\t\\t\\tconst toRead = Math.min(element.count - c, Math.floor(streamBuf.remaining / inputSize));\\n\\t\\t\\tfor (let n = 0; n < toRead; ++n) {\\n\\t\\t\\t\\tfor (let j = 0; j < element.properties.length; ++j) {\\n\\t\\t\\t\\t\\tpropertyParsingFunctions[j](streamBuf, c);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tc++;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\treturn new GSplatData(elements, comments);\\n};\\nconst readPly = async (reader, propertyFilter = null, progressFunc = null) => {\\n\\tconst find = (buf, search) => {\\n\\t\\tconst endIndex = buf.length - search.length;\\n\\t\\tlet i, j;\\n\\t\\tfor (i = 0; i <= endIndex; ++i) {\\n\\t\\t\\tfor (j = 0; j < search.length; ++j) {\\n\\t\\t\\t\\tif (buf[i + j] !== search[j]) {\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (j === search.length) {\\n\\t\\t\\t\\treturn i;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn -1;\\n\\t};\\n\\tconst startsWith = (a, b) => {\\n\\t\\tif (a.length < b.length) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < b.length; ++i) {\\n\\t\\t\\tif (a[i] !== b[i]) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn true;\\n\\t};\\n\\tconst streamBuf = new StreamBuf(reader, progressFunc);\\n\\tlet headerLength;\\n\\twhile (true) {\\n\\t\\tawait streamBuf.read();\\n\\t\\tif (streamBuf.tail >= magicBytes.length && !startsWith(streamBuf.data, magicBytes)) {\\n\\t\\t\\tthrow new Error(\\\"Invalid ply header\\\");\\n\\t\\t}\\n\\t\\theaderLength = find(streamBuf.data, endHeaderBytes);\\n\\t\\tif (headerLength !== -1) {\\n\\t\\t\\tbreak;\\n\\t\\t}\\n\\t}\\n\\tconst lines = new TextDecoder(\\\"ascii\\\").decode(streamBuf.data.subarray(0, headerLength)).split(\\\"\\\\n\\\");\\n\\tconst { elements, format, comments } = parseHeader(lines);\\n\\tif (format !== \\\"binary_little_endian\\\") {\\n\\t\\tthrow new Error(\\\"Unsupported ply format\\\");\\n\\t}\\n\\tstreamBuf.head = headerLength + endHeaderBytes.length;\\n\\tstreamBuf.compact();\\n\\tconst readData = async () => {\\n\\t\\tif (isCompressedPly(elements)) {\\n\\t\\t\\treturn await readCompressedPly(streamBuf, elements, comments);\\n\\t\\t}\\n\\t\\telements.forEach((e) => {\\n\\t\\t\\te.properties.forEach((p) => {\\n\\t\\t\\t\\tconst storageType = dataTypeMap.get(p.type);\\n\\t\\t\\t\\tif (storageType) {\\n\\t\\t\\t\\t\\tconst storage = !propertyFilter || propertyFilter(p.name) ? new storageType(e.count) : null;\\n\\t\\t\\t\\t\\tp.storage = storage;\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t});\\n\\t\\tif (isFloatPly(elements)) {\\n\\t\\t\\treturn await readFloatPly(streamBuf, elements, comments);\\n\\t\\t}\\n\\t\\treturn await readGeneralPly(streamBuf, elements, comments);\\n\\t};\\n\\treturn await readData();\\n};\\nconst defaultElementFilter = (val) => true;\\nclass PlyParser {\\n\\tapp;\\n\\tmaxRetries;\\n\\tconstructor(app, maxRetries) {\\n\\t\\tthis.app = app;\\n\\t\\tthis.maxRetries = maxRetries;\\n\\t}\\n\\tasync load(url, callback, asset) {\\n\\t\\tconst gsplatCentersEnabledAtLoad = this.app.scene?.gsplatCentersEnabled !== false;\\n\\t\\ttry {\\n\\t\\t\\tconst response = await (asset.file?.contents ?? fetch(url.load));\\n\\t\\t\\tif (!response || !response.body) {\\n\\t\\t\\t\\tcallback(\\\"Error loading resource\\\", null);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconst totalLength = parseInt(response.headers.get(\\\"content-length\\\") ?? \\\"0\\\", 10);\\n\\t\\t\\t\\tlet totalReceived = 0;\\n\\t\\t\\t\\tconst data = await readPly(\\n\\t\\t\\t\\t\\tresponse.body.getReader(),\\n\\t\\t\\t\\t\\tasset.data.elementFilter ?? defaultElementFilter,\\n\\t\\t\\t\\t\\t(bytes) => {\\n\\t\\t\\t\\t\\t\\ttotalReceived += bytes;\\n\\t\\t\\t\\t\\t\\tif (asset) {\\n\\t\\t\\t\\t\\t\\t\\tasset.fire(\\\"progress\\\", totalReceived, totalLength);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t);\\n\\t\\t\\t\\tasset.fire(\\\"load:data\\\", data);\\n\\t\\t\\t\\tif (!data.isCompressed) {\\n\\t\\t\\t\\t\\tif (asset.data.reorder ?? true) {\\n\\t\\t\\t\\t\\t\\tdata.reorderData();\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst prepareCenters = gsplatCentersEnabledAtLoad;\\n\\t\\t\\t\\tconst resource = data.isCompressed && !asset.data.decompress ? new GSplatCompressedResource(this.app.graphicsDevice, data, { prepareCenters }) : new GSplatResource(this.app.graphicsDevice, data.isCompressed ? data.decompress() : data, { prepareCenters });\\n\\t\\t\\t\\tcallback(null, resource);\\n\\t\\t\\t}\\n\\t\\t} catch (err) {\\n\\t\\t\\tcallback(err, null);\\n\\t\\t}\\n\\t}\\n\\topen(url, data) {\\n\\t\\treturn data;\\n\\t}\\n}\\n\\nconst combineProgress = (target, assets) => {\\n\\tconst map = /* @__PURE__ */ new Map();\\n\\tconst count = assets.length;\\n\\tconst fire = () => {\\n\\t\\tlet loaded = 0;\\n\\t\\tlet total = 0;\\n\\t\\tmap.forEach((value) => {\\n\\t\\t\\tloaded += value.loaded;\\n\\t\\t\\ttotal += value.total;\\n\\t\\t});\\n\\t\\tconst reporting = map.size;\\n\\t\\tif (reporting > 0 && reporting < count) {\\n\\t\\t\\ttotal = Math.ceil(total * count / reporting);\\n\\t\\t}\\n\\t\\ttarget.fire(\\\"progress\\\", loaded, total);\\n\\t};\\n\\tassets.forEach((asset) => {\\n\\t\\tconst progress = (loaded, total) => {\\n\\t\\t\\tmap.set(asset, { loaded, total });\\n\\t\\t\\tfire();\\n\\t\\t};\\n\\t\\tconst done = () => {\\n\\t\\t\\tasset.off(\\\"progress\\\", progress);\\n\\t\\t\\tasset.off(\\\"load\\\", done);\\n\\t\\t\\tasset.off(\\\"error\\\", done);\\n\\t\\t};\\n\\t\\tasset.on(\\\"progress\\\", progress);\\n\\t\\tasset.on(\\\"load\\\", done);\\n\\t\\tasset.on(\\\"error\\\", done);\\n\\t});\\n};\\nconst upgradeMeta = (meta) => {\\n\\tconst result = {\\n\\t\\tversion: 1,\\n\\t\\tcount: meta.means.shape[0],\\n\\t\\tmeans: {\\n\\t\\t\\tmins: meta.means.mins,\\n\\t\\t\\tmaxs: meta.means.maxs,\\n\\t\\t\\tfiles: meta.means.files\\n\\t\\t},\\n\\t\\tscales: {\\n\\t\\t\\tmins: meta.scales.mins,\\n\\t\\t\\tmaxs: meta.scales.maxs,\\n\\t\\t\\tfiles: meta.scales.files\\n\\t\\t},\\n\\t\\tquats: {\\n\\t\\t\\tfiles: meta.quats.files\\n\\t\\t},\\n\\t\\tsh0: {\\n\\t\\t\\tmins: meta.sh0.mins,\\n\\t\\t\\tmaxs: meta.sh0.maxs,\\n\\t\\t\\tfiles: meta.sh0.files\\n\\t\\t}\\n\\t};\\n\\tif (meta.shN) {\\n\\t\\tresult.shN = {\\n\\t\\t\\tmins: meta.shN.mins,\\n\\t\\t\\tmaxs: meta.shN.maxs,\\n\\t\\t\\tfiles: meta.shN.files\\n\\t\\t};\\n\\t}\\n\\treturn result;\\n};\\nclass SogParser {\\n\\tapp;\\n\\tmaxRetries;\\n\\tconstructor(app, maxRetries) {\\n\\t\\tthis.app = app;\\n\\t\\tthis.maxRetries = maxRetries;\\n\\t}\\n\\t_shouldAbort(asset, unloaded) {\\n\\t\\tif (unloaded || !this.app.assets.get(asset.id)) return true;\\n\\t\\tif (!this.app?.graphicsDevice || this.app.graphicsDevice._destroyed) return true;\\n\\t\\treturn false;\\n\\t}\\n\\tasync loadTextures(url, callback, asset, meta) {\\n\\t\\tconst gsplatCentersEnabledAtLoad = this.app.scene?.gsplatCentersEnabled !== false;\\n\\t\\tif (meta.version !== 2) {\\n\\t\\t\\tmeta = upgradeMeta(meta);\\n\\t\\t}\\n\\t\\tconst { assets } = this.app;\\n\\t\\tconst subs = [\\\"means\\\", \\\"quats\\\", \\\"scales\\\", \\\"sh0\\\", \\\"shN\\\"];\\n\\t\\tconst textures = {};\\n\\t\\tconst promises = [];\\n\\t\\tconst base = window.document?.baseURI ?? window.location.href;\\n\\t\\tsubs.forEach((sub) => {\\n\\t\\t\\tconst files = meta[sub]?.files ?? [];\\n\\t\\t\\ttextures[sub] = files.map((filename) => {\\n\\t\\t\\t\\tconst texture = new Asset(filename, \\\"texture\\\", {\\n\\t\\t\\t\\t\\turl: asset.options?.mapUrl?.(filename) ?? new URL(filename, new URL(url.load, base).toString()).toString(),\\n\\t\\t\\t\\t\\tfilename\\n\\t\\t\\t\\t}, {\\n\\t\\t\\t\\t\\tmipmaps: false\\n\\t\\t\\t\\t}, {\\n\\t\\t\\t\\t\\tcrossOrigin: \\\"anonymous\\\"\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst promise = new Promise((resolve, reject) => {\\n\\t\\t\\t\\t\\ttexture.on(\\\"load\\\", () => resolve(null));\\n\\t\\t\\t\\t\\ttexture.on(\\\"error\\\", (err) => reject(err));\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tassets.add(texture);\\n\\t\\t\\t\\tpromises.push(promise);\\n\\t\\t\\t\\treturn texture;\\n\\t\\t\\t});\\n\\t\\t});\\n\\t\\tconst textureAssets = subs.map((sub) => textures[sub]).flat();\\n\\t\\tlet unloaded = false;\\n\\t\\tasset.once(\\\"unload\\\", () => {\\n\\t\\t\\tunloaded = true;\\n\\t\\t\\ttextureAssets.forEach((t) => {\\n\\t\\t\\t\\tassets.remove(t);\\n\\t\\t\\t\\tt.unload();\\n\\t\\t\\t});\\n\\t\\t});\\n\\t\\tcombineProgress(asset, textureAssets);\\n\\t\\ttextureAssets.forEach((t) => assets.load(t));\\n\\t\\tawait Promise.allSettled(promises);\\n\\t\\tif (this._shouldAbort(asset, unloaded)) {\\n\\t\\t\\ttextureAssets.forEach((t) => {\\n\\t\\t\\t\\tassets.remove(t);\\n\\t\\t\\t\\tt.unload();\\n\\t\\t\\t});\\n\\t\\t\\tcallback(null, null);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst data = new GSplatSogData();\\n\\t\\tdata.url = url.original;\\n\\t\\tdata.meta = meta;\\n\\t\\tdata.numSplats = meta.count;\\n\\t\\tdata.means_l = textures.means[0].resource;\\n\\t\\tdata.means_u = textures.means[1].resource;\\n\\t\\tdata.quats = textures.quats[0].resource;\\n\\t\\tdata.scales = textures.scales[0].resource;\\n\\t\\tdata.sh0 = textures.sh0[0].resource;\\n\\t\\tdata.sh_centroids = textures.shN?.[0]?.resource;\\n\\t\\tdata.sh_labels = textures.shN?.[1]?.resource;\\n\\t\\tdata.shBands = GSplatSogData.calcBands(data.sh_centroids?.width);\\n\\t\\tconst decompress = asset.data?.decompress;\\n\\t\\tif (!decompress) {\\n\\t\\t\\tif (this._shouldAbort(asset, unloaded)) {\\n\\t\\t\\t\\tdata.destroy();\\n\\t\\t\\t\\tcallback(null, null);\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tdata.prepareCodebook();\\n\\t\\t\\tif (gsplatCentersEnabledAtLoad) {\\n\\t\\t\\t\\tawait data.prepareGpuData();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this._shouldAbort(asset, unloaded)) {\\n\\t\\t\\tdata.destroy();\\n\\t\\t\\tcallback(null, null);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst prepareCenters = gsplatCentersEnabledAtLoad;\\n\\t\\tconst resource = decompress ? new GSplatResource(this.app.graphicsDevice, await data.decompress(), { prepareCenters }) : new GSplatSogResource(this.app.graphicsDevice, data, { prepareCenters });\\n\\t\\tif (this._shouldAbort(asset, unloaded)) {\\n\\t\\t\\tresource.destroy();\\n\\t\\t\\tcallback(null, null);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tcallback(null, resource);\\n\\t}\\n\\tload(url, callback, asset) {\\n\\t\\tif (asset.data?.means) {\\n\\t\\t\\tthis.loadTextures(url, callback, asset, asset.data);\\n\\t\\t} else {\\n\\t\\t\\tif (typeof url === \\\"string\\\") {\\n\\t\\t\\t\\turl = {\\n\\t\\t\\t\\t\\tload: url,\\n\\t\\t\\t\\t\\toriginal: url\\n\\t\\t\\t\\t};\\n\\t\\t\\t}\\n\\t\\t\\tconst options = {\\n\\t\\t\\t\\tretry: this.maxRetries > 0,\\n\\t\\t\\t\\tmaxRetries: this.maxRetries,\\n\\t\\t\\t\\tresponseType: Http.ResponseType.JSON\\n\\t\\t\\t};\\n\\t\\t\\thttp.get(url.load, options, (err, meta) => {\\n\\t\\t\\t\\tif (this._shouldAbort(asset, false)) {\\n\\t\\t\\t\\t\\tcallback(null, null);\\n\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!err) {\\n\\t\\t\\t\\t\\tthis.loadTextures(url, callback, asset, meta);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tcallback(`Error loading gsplat meta: ${url.original} [${err}]`);\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t}\\n\\t}\\n}\\n\\nconst parseZipArchive = (data) => {\\n\\tconst dataView = new DataView(data);\\n\\tconst u16 = (offset2) => dataView.getUint16(offset2, true);\\n\\tconst u32 = (offset2) => dataView.getUint32(offset2, true);\\n\\tconst extractEocd = (offset2) => {\\n\\t\\treturn {\\n\\t\\t\\tmagic: u32(offset2),\\n\\t\\t\\tnumFiles: u16(offset2 + 8),\\n\\t\\t\\tcdSizeBytes: u32(offset2 + 12),\\n\\t\\t\\tcdOffsetBytes: u32(offset2 + 16)\\n\\t\\t};\\n\\t};\\n\\tconst extractCdr = (offset2) => {\\n\\t\\tconst filenameLength = u16(offset2 + 28);\\n\\t\\tconst extraFieldLength = u16(offset2 + 30);\\n\\t\\tconst fileCommentLength = u16(offset2 + 32);\\n\\t\\treturn {\\n\\t\\t\\tmagic: u32(offset2),\\n\\t\\t\\tcompressionMethod: u16(offset2 + 10),\\n\\t\\t\\tcompressedSizeBytes: u32(offset2 + 20),\\n\\t\\t\\tuncompressedSizeBytes: u32(offset2 + 24),\\n\\t\\t\\tlfhOffsetBytes: u32(offset2 + 42),\\n\\t\\t\\tfilename: new TextDecoder().decode(new Uint8Array(data, offset2 + 46, filenameLength)),\\n\\t\\t\\trecordSizeBytes: 46 + filenameLength + extraFieldLength + fileCommentLength\\n\\t\\t};\\n\\t};\\n\\tconst extractLfh = (offset2) => {\\n\\t\\tconst filenameLength = u16(offset2 + 26);\\n\\t\\tconst extraLength = u16(offset2 + 28);\\n\\t\\treturn {\\n\\t\\t\\tmagic: u32(offset2),\\n\\t\\t\\toffsetBytes: offset2 + 30 + filenameLength + extraLength\\n\\t\\t};\\n\\t};\\n\\tconst eocd = extractEocd(dataView.byteLength - 22);\\n\\tif (eocd.magic !== 101010256) {\\n\\t\\tthrow new Error(\\\"Invalid zip file: EOCDR not found\\\");\\n\\t}\\n\\tif (eocd.cdOffsetBytes === 4294967295 || eocd.cdSizeBytes === 4294967295) {\\n\\t\\tthrow new Error(\\\"Invalid zip file: Zip64 not supported\\\");\\n\\t}\\n\\tconst result = [];\\n\\tlet offset = eocd.cdOffsetBytes;\\n\\tfor (let i = 0; i < eocd.numFiles; i++) {\\n\\t\\tconst cdr = extractCdr(offset);\\n\\t\\tif (cdr.magic !== 33639248) {\\n\\t\\t\\tthrow new Error(\\\"Invalid zip file: CDR not found\\\");\\n\\t\\t}\\n\\t\\tconst lfh = extractLfh(cdr.lfhOffsetBytes);\\n\\t\\tif (lfh.magic !== 67324752) {\\n\\t\\t\\tthrow new Error(\\\"Invalid zip file: LFH not found\\\");\\n\\t\\t}\\n\\t\\tresult.push({\\n\\t\\t\\tfilename: cdr.filename,\\n\\t\\t\\tcompression: { 0: \\\"none\\\", 8: \\\"deflate\\\" }[cdr.compressionMethod] ?? \\\"unknown\\\",\\n\\t\\t\\tdata: new Uint8Array(data, lfh.offsetBytes, cdr.compressedSizeBytes)\\n\\t\\t});\\n\\t\\toffset += cdr.recordSizeBytes;\\n\\t}\\n\\treturn result;\\n};\\nconst inflate = async (compressed) => {\\n\\tconst ds = new DecompressionStream(\\\"deflate-raw\\\");\\n\\tconst out = new Blob([compressed]).stream().pipeThrough(ds);\\n\\tconst ab = await new Response(out).arrayBuffer();\\n\\treturn new Uint8Array(ab);\\n};\\nconst downloadArrayBuffer = async (url, asset) => {\\n\\tconst response = await (asset.file?.contents ?? fetch(url.load));\\n\\tif (!response) {\\n\\t\\tthrow new Error(\\\"Error loading resource\\\");\\n\\t}\\n\\tif (response instanceof Response) {\\n\\t\\tif (!response.ok) {\\n\\t\\t\\tthrow new Error(`Error loading resource: ${response.status} ${response.statusText}`);\\n\\t\\t}\\n\\t\\tconst totalLength = parseInt(response.headers.get(\\\"content-length\\\") ?? \\\"0\\\", 10);\\n\\t\\tif (!response.body || !response.body.getReader) {\\n\\t\\t\\tconst buf = await response.arrayBuffer();\\n\\t\\t\\tasset.fire(\\\"progress\\\", buf.byteLength, totalLength);\\n\\t\\t\\treturn buf;\\n\\t\\t}\\n\\t\\tconst reader = response.body.getReader();\\n\\t\\tconst chunks = [];\\n\\t\\tlet totalReceived = 0;\\n\\t\\ttry {\\n\\t\\t\\twhile (true) {\\n\\t\\t\\t\\tconst { done, value } = await reader.read();\\n\\t\\t\\t\\tif (done) {\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tchunks.push(value);\\n\\t\\t\\t\\ttotalReceived += value.byteLength;\\n\\t\\t\\t\\tasset.fire(\\\"progress\\\", totalReceived, totalLength);\\n\\t\\t\\t}\\n\\t\\t} finally {\\n\\t\\t\\treader.releaseLock();\\n\\t\\t}\\n\\t\\treturn new Blob(chunks).arrayBuffer();\\n\\t}\\n\\treturn response;\\n};\\nclass SogBundleParser {\\n\\tapp;\\n\\tmaxRetries;\\n\\tconstructor(app, maxRetries = 3) {\\n\\t\\tthis.app = app;\\n\\t\\tthis.maxRetries = maxRetries;\\n\\t}\\n\\tasync load(url, callback, asset) {\\n\\t\\tconst gsplatCentersEnabledAtLoad = this.app.scene?.gsplatCentersEnabled !== false;\\n\\t\\ttry {\\n\\t\\t\\tconst arrayBuffer = await downloadArrayBuffer(url, asset);\\n\\t\\t\\tconst files = parseZipArchive(arrayBuffer);\\n\\t\\t\\tfor (const file of files) {\\n\\t\\t\\t\\tif (file.compression === \\\"deflate\\\") {\\n\\t\\t\\t\\t\\tfile.data = await inflate(file.data);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tconst metaFile = files.find((f) => f.filename === \\\"meta.json\\\");\\n\\t\\t\\tif (!metaFile) {\\n\\t\\t\\t\\tcallback(\\\"Error: meta.json not found\\\");\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tlet meta;\\n\\t\\t\\ttry {\\n\\t\\t\\t\\tmeta = JSON.parse(new TextDecoder().decode(metaFile.data));\\n\\t\\t\\t} catch (err) {\\n\\t\\t\\t\\tcallback(`Error parsing meta.json: ${err}`);\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tconst filenames = [\\\"means\\\", \\\"scales\\\", \\\"quats\\\", \\\"sh0\\\", \\\"shN\\\"].map((key) => meta[key]?.files ?? []).flat();\\n\\t\\t\\tconst textures = {};\\n\\t\\t\\tconst promises = [];\\n\\t\\t\\tfor (const filename of filenames) {\\n\\t\\t\\t\\tconst file = files.find((f) => f.filename === filename);\\n\\t\\t\\t\\tlet texture;\\n\\t\\t\\t\\tif (file) {\\n\\t\\t\\t\\t\\ttexture = new Asset(filename, \\\"texture\\\", {\\n\\t\\t\\t\\t\\t\\turl: `${url.load}/${filename}`,\\n\\t\\t\\t\\t\\t\\tfilename,\\n\\t\\t\\t\\t\\t\\tcontents: file.data\\n\\t\\t\\t\\t\\t}, {\\n\\t\\t\\t\\t\\t\\tmipmaps: false\\n\\t\\t\\t\\t\\t}, {\\n\\t\\t\\t\\t\\t\\tcrossOrigin: \\\"anonymous\\\"\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tconst url2 = new URL(filename, new URL(filename, window.location.href).toString()).toString();\\n\\t\\t\\t\\t\\ttexture = new Asset(filename, \\\"texture\\\", {\\n\\t\\t\\t\\t\\t\\turl: url2,\\n\\t\\t\\t\\t\\t\\tfilename\\n\\t\\t\\t\\t\\t}, {\\n\\t\\t\\t\\t\\t\\tmipmaps: false\\n\\t\\t\\t\\t\\t}, {\\n\\t\\t\\t\\t\\t\\tcrossOrigin: \\\"anonymous\\\"\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst promise = new Promise((resolve, reject) => {\\n\\t\\t\\t\\t\\ttexture.on(\\\"load\\\", () => resolve(null));\\n\\t\\t\\t\\t\\ttexture.on(\\\"error\\\", (err) => reject(err));\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.app.assets.add(texture);\\n\\t\\t\\t\\ttextures[filename] = texture;\\n\\t\\t\\t\\tpromises.push(promise);\\n\\t\\t\\t}\\n\\t\\t\\tObject.values(textures).forEach((t) => this.app.assets.load(t));\\n\\t\\t\\tawait Promise.allSettled(promises);\\n\\t\\t\\tconst { assets } = this.app;\\n\\t\\t\\tasset.once(\\\"unload\\\", () => {\\n\\t\\t\\t\\tObject.values(textures).forEach((t) => {\\n\\t\\t\\t\\t\\tassets.remove(t);\\n\\t\\t\\t\\t\\tt.unload();\\n\\t\\t\\t\\t});\\n\\t\\t\\t});\\n\\t\\t\\tconst decompress = asset.data?.decompress;\\n\\t\\t\\tconst data = new GSplatSogData();\\n\\t\\t\\tdata.url = url.original;\\n\\t\\t\\tdata.meta = meta;\\n\\t\\t\\tdata.numSplats = meta.count;\\n\\t\\t\\tdata.means_l = textures[meta.means.files[0]].resource;\\n\\t\\t\\tdata.means_u = textures[meta.means.files[1]].resource;\\n\\t\\t\\tdata.quats = textures[meta.quats.files[0]].resource;\\n\\t\\t\\tdata.scales = textures[meta.scales.files[0]].resource;\\n\\t\\t\\tdata.sh0 = textures[meta.sh0.files[0]].resource;\\n\\t\\t\\tdata.sh_centroids = textures[meta.shN?.files[0]]?.resource;\\n\\t\\t\\tdata.sh_labels = textures[meta.shN?.files[1]]?.resource;\\n\\t\\t\\tdata.shBands = GSplatSogData.calcBands(data.sh_centroids?.width);\\n\\t\\t\\tif (!decompress) {\\n\\t\\t\\t\\tdata.prepareCodebook();\\n\\t\\t\\t\\tif (gsplatCentersEnabledAtLoad) {\\n\\t\\t\\t\\t\\tawait data.prepareGpuData();\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tconst prepareCenters = gsplatCentersEnabledAtLoad;\\n\\t\\t\\tconst resource = decompress ? new GSplatResource(this.app.graphicsDevice, await data.decompress(), { prepareCenters }) : new GSplatSogResource(this.app.graphicsDevice, data, { prepareCenters });\\n\\t\\t\\tcallback(null, resource);\\n\\t\\t} catch (err) {\\n\\t\\t\\tcallback(err);\\n\\t\\t}\\n\\t}\\n}\\n\\nclass GSplatAssetLoaderBase {\\n\\tload(url) {\\n\\t}\\n\\tunload(url) {\\n\\t}\\n\\tgetResource(url) {\\n\\t}\\n\\tdestroy() {\\n\\t}\\n}\\n\\nclass GSplatAssetLoader extends GSplatAssetLoaderBase {\\n\\t_urlToAsset = /* @__PURE__ */ new Map();\\n\\t_registry;\\n\\tmaxConcurrentLoads = 2;\\n\\tmaxRetries = 2;\\n\\t_currentlyLoading = /* @__PURE__ */ new Set();\\n\\t_loadQueue = [];\\n\\t_retryCount = /* @__PURE__ */ new Map();\\n\\t_destroyed = false;\\n\\tconstructor(registry) {\\n\\t\\tsuper();\\n\\t\\tthis._registry = registry;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._destroyed = true;\\n\\t\\tfor (const asset of this._urlToAsset.values()) {\\n\\t\\t\\tasset.fire(\\\"unload\\\", asset);\\n\\t\\t\\tasset.off(\\\"load\\\");\\n\\t\\t\\tasset.off(\\\"error\\\");\\n\\t\\t\\tthis._registry.remove(asset);\\n\\t\\t\\tasset.unload();\\n\\t\\t}\\n\\t\\tthis._urlToAsset.clear();\\n\\t\\tthis._loadQueue.length = 0;\\n\\t\\tthis._currentlyLoading.clear();\\n\\t\\tthis._retryCount.clear();\\n\\t}\\n\\t_canLoad() {\\n\\t\\treturn !!this._registry.loader?.getHandler(\\\"gsplat\\\");\\n\\t}\\n\\tload(url) {\\n\\t\\tconst asset = this._urlToAsset.get(url);\\n\\t\\tif (asset?.loaded || this._currentlyLoading.has(url)) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._loadQueue.includes(url)) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._currentlyLoading.size < this.maxConcurrentLoads) {\\n\\t\\t\\tthis._startLoading(url);\\n\\t\\t} else {\\n\\t\\t\\tthis._loadQueue.push(url);\\n\\t\\t}\\n\\t}\\n\\t_startLoading(url) {\\n\\t\\tthis._currentlyLoading.add(url);\\n\\t\\tlet asset = this._urlToAsset.get(url);\\n\\t\\tif (!asset) {\\n\\t\\t\\tasset = new Asset(url, \\\"gsplat\\\", { url });\\n\\t\\t\\tthis._registry.add(asset);\\n\\t\\t\\tthis._urlToAsset.set(url, asset);\\n\\t\\t}\\n\\t\\tasset.once(\\\"load\\\", () => this._onAssetLoadSuccess(url, asset));\\n\\t\\tasset.once(\\\"error\\\", (err) => this._onAssetLoadError(url, asset, err));\\n\\t\\tif (!asset.loaded && !asset.loading) {\\n\\t\\t\\tthis._registry.load(asset);\\n\\t\\t}\\n\\t}\\n\\t_onAssetLoadSuccess(url, asset) {\\n\\t\\tif (this._destroyed || !this._urlToAsset.has(url)) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._currentlyLoading.delete(url);\\n\\t\\tthis._retryCount.delete(url);\\n\\t\\tthis._processQueue();\\n\\t}\\n\\t_onAssetLoadError(url, asset, err) {\\n\\t\\tif (this._destroyed || !this._canLoad() || !this._urlToAsset.has(url)) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst retryCount = this._retryCount.get(url) || 0;\\n\\t\\tif (retryCount < this.maxRetries) {\\n\\t\\t\\tthis._retryCount.set(url, retryCount + 1);\\n\\t\\t\\tasset.loaded = false;\\n\\t\\t\\tasset.loading = false;\\n\\t\\t\\tthis._registry.load(asset);\\n\\t\\t} else {\\n\\t\\t\\tthis._currentlyLoading.delete(url);\\n\\t\\t\\tthis._retryCount.delete(url);\\n\\t\\t\\tthis._processQueue();\\n\\t\\t}\\n\\t}\\n\\t_processQueue() {\\n\\t\\tif (this._destroyed || !this._canLoad()) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\twhile (this._currentlyLoading.size < this.maxConcurrentLoads && this._loadQueue.length > 0) {\\n\\t\\t\\tconst url = this._loadQueue.shift();\\n\\t\\t\\tif (url) {\\n\\t\\t\\t\\tthis._startLoading(url);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tunload(url) {\\n\\t\\tthis._currentlyLoading.delete(url);\\n\\t\\tconst queueIndex = this._loadQueue.indexOf(url);\\n\\t\\tif (queueIndex !== -1) {\\n\\t\\t\\tthis._loadQueue.splice(queueIndex, 1);\\n\\t\\t}\\n\\t\\tthis._retryCount.delete(url);\\n\\t\\tconst asset = this._urlToAsset.get(url);\\n\\t\\tif (asset) {\\n\\t\\t\\tasset.fire(\\\"unload\\\", asset);\\n\\t\\t\\tasset.off(\\\"load\\\");\\n\\t\\t\\tasset.off(\\\"error\\\");\\n\\t\\t\\tthis._registry.remove(asset);\\n\\t\\t\\tasset.unload();\\n\\t\\t\\tthis._urlToAsset.delete(url);\\n\\t\\t}\\n\\t\\tthis._processQueue();\\n\\t}\\n\\tgetResource(url) {\\n\\t\\tconst asset = this._urlToAsset.get(url);\\n\\t\\treturn asset?.resource;\\n\\t}\\n}\\n\\nclass GSplatOctreeParser {\\n\\tapp;\\n\\tmaxRetries;\\n\\tconstructor(app, maxRetries) {\\n\\t\\tthis.app = app;\\n\\t\\tthis.maxRetries = maxRetries;\\n\\t}\\n\\tload(url, callback, asset) {\\n\\t\\tif (typeof url === \\\"string\\\") {\\n\\t\\t\\turl = {\\n\\t\\t\\t\\tload: url,\\n\\t\\t\\t\\toriginal: url\\n\\t\\t\\t};\\n\\t\\t}\\n\\t\\tconst options = {\\n\\t\\t\\tretry: this.maxRetries > 0,\\n\\t\\t\\tmaxRetries: this.maxRetries,\\n\\t\\t\\tresponseType: Http.ResponseType.JSON\\n\\t\\t};\\n\\t\\thttp.get(url.load, options, (err, data) => {\\n\\t\\t\\tif (!err) {\\n\\t\\t\\t\\tconst assetLoader = new GSplatAssetLoader(this.app.assets);\\n\\t\\t\\t\\tconst resource = new GSplatOctreeResource(asset.file.url, data, assetLoader);\\n\\t\\t\\t\\tcallback(null, resource);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tcallback(`Error loading gsplat octree: ${url.original} [${err}]`);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n}\\n\\nclass GSplatHandler extends ResourceHandler {\\n\\tconstructor(app) {\\n\\t\\tsuper(app, \\\"gsplat\\\");\\n\\t\\tthis.parsers = {\\n\\t\\t\\tply: new PlyParser(app, 3),\\n\\t\\t\\tsog: new SogBundleParser(app),\\n\\t\\t\\tjson: new SogParser(app, 3),\\n\\t\\t\\toctree: new GSplatOctreeParser(app, 3)\\n\\t\\t};\\n\\t}\\n\\t_getUrlWithoutParams(url) {\\n\\t\\treturn url.indexOf(\\\"?\\\") >= 0 ? url.split(\\\"?\\\")[0] : url;\\n\\t}\\n\\t_getParser(url) {\\n\\t\\tconst basename = path.getBasename(this._getUrlWithoutParams(url)).toLowerCase();\\n\\t\\tif (basename === \\\"lod-meta.json\\\") {\\n\\t\\t\\treturn this.parsers.octree;\\n\\t\\t}\\n\\t\\tconst ext = path.getExtension(basename).replace(\\\".\\\", \\\"\\\");\\n\\t\\treturn this.parsers[ext] || this.parsers.ply;\\n\\t}\\n\\tload(url, callback, asset) {\\n\\t\\tif (typeof url === \\\"string\\\") {\\n\\t\\t\\turl = {\\n\\t\\t\\t\\tload: url,\\n\\t\\t\\t\\toriginal: url\\n\\t\\t\\t};\\n\\t\\t}\\n\\t\\tthis._getParser(url.original).load(url, callback, asset);\\n\\t}\\n\\topen(url, data, asset) {\\n\\t\\treturn data;\\n\\t}\\n}\\n\\nfunction BasisWorker() {\\n\\tconst BASIS_FORMAT = {\\n\\t\\tcTFETC1: 0,\\n\\t\\t// etc1\\n\\t\\tcTFETC2: 1,\\n\\t\\t// etc2\\n\\t\\tcTFBC1: 2,\\n\\t\\t// dxt1\\n\\t\\tcTFBC3: 3,\\n\\t\\t// dxt5\\n\\t\\tcTFPVRTC1_4_RGB: 8,\\n\\t\\t// PVRTC1 rgb\\n\\t\\tcTFPVRTC1_4_RGBA: 9,\\n\\t\\t// PVRTC1 rgba\\n\\t\\tcTFASTC_4x4: 10,\\n\\t\\t// ASTC\\n\\t\\tcTFATC_RGB: 11,\\n\\t\\t// ATC rgb\\n\\t\\tcTFATC_RGBA_INTERPOLATED_ALPHA: 12,\\n\\t\\t// ATC rgba\\n\\t\\t// uncompressed (fallback) formats\\n\\t\\tcTFRGBA32: 13,\\n\\t\\t// rgba 8888\\n\\t\\tcTFRGB565: 14,\\n\\t\\t// rgb 565\\n\\t\\tcTFRGBA4444: 16\\n\\t\\t// rgba 4444\\n\\t};\\n\\tconst opaqueMapping = {\\n\\t\\tastc: BASIS_FORMAT.cTFASTC_4x4,\\n\\t\\tdxt: BASIS_FORMAT.cTFBC1,\\n\\t\\tetc1: BASIS_FORMAT.cTFETC1,\\n\\t\\tetc2: BASIS_FORMAT.cTFETC1,\\n\\t\\tpvr: BASIS_FORMAT.cTFPVRTC1_4_RGB,\\n\\t\\tatc: BASIS_FORMAT.cTFATC_RGB,\\n\\t\\tnone: BASIS_FORMAT.cTFRGB565\\n\\t};\\n\\tconst alphaMapping = {\\n\\t\\tastc: BASIS_FORMAT.cTFASTC_4x4,\\n\\t\\tdxt: BASIS_FORMAT.cTFBC3,\\n\\t\\tetc1: BASIS_FORMAT.cTFRGBA4444,\\n\\t\\tetc2: BASIS_FORMAT.cTFETC2,\\n\\t\\tpvr: BASIS_FORMAT.cTFPVRTC1_4_RGBA,\\n\\t\\tatc: BASIS_FORMAT.cTFATC_RGBA_INTERPOLATED_ALPHA,\\n\\t\\tnone: BASIS_FORMAT.cTFRGBA4444\\n\\t};\\n\\tconst PIXEL_FORMAT = {\\n\\t\\tETC1: 21,\\n\\t\\tETC2_RGB: 22,\\n\\t\\tETC2_RGBA: 23,\\n\\t\\tDXT1: 8,\\n\\t\\tDXT5: 10,\\n\\t\\tPVRTC_4BPP_RGB_1: 26,\\n\\t\\tPVRTC_4BPP_RGBA_1: 27,\\n\\t\\tASTC_4x4: 28,\\n\\t\\tATC_RGB: 29,\\n\\t\\tATC_RGBA: 30,\\n\\t\\tR8_G8_B8_A8: 7,\\n\\t\\tR5_G6_B5: 3,\\n\\t\\tR4_G4_B4_A4: 5\\n\\t};\\n\\tconst basisToEngineMapping = (basisFormat, deviceDetails) => {\\n\\t\\tswitch (basisFormat) {\\n\\t\\t\\tcase BASIS_FORMAT.cTFETC1:\\n\\t\\t\\t\\treturn deviceDetails.formats.etc2 ? PIXEL_FORMAT.ETC2_RGB : PIXEL_FORMAT.ETC1;\\n\\t\\t\\tcase BASIS_FORMAT.cTFETC2:\\n\\t\\t\\t\\treturn PIXEL_FORMAT.ETC2_RGBA;\\n\\t\\t\\tcase BASIS_FORMAT.cTFBC1:\\n\\t\\t\\t\\treturn PIXEL_FORMAT.DXT1;\\n\\t\\t\\tcase BASIS_FORMAT.cTFBC3:\\n\\t\\t\\t\\treturn PIXEL_FORMAT.DXT5;\\n\\t\\t\\tcase BASIS_FORMAT.cTFPVRTC1_4_RGB:\\n\\t\\t\\t\\treturn PIXEL_FORMAT.PVRTC_4BPP_RGB_1;\\n\\t\\t\\tcase BASIS_FORMAT.cTFPVRTC1_4_RGBA:\\n\\t\\t\\t\\treturn PIXEL_FORMAT.PVRTC_4BPP_RGBA_1;\\n\\t\\t\\tcase BASIS_FORMAT.cTFASTC_4x4:\\n\\t\\t\\t\\treturn PIXEL_FORMAT.ASTC_4x4;\\n\\t\\t\\tcase BASIS_FORMAT.cTFATC_RGB:\\n\\t\\t\\t\\treturn PIXEL_FORMAT.ATC_RGB;\\n\\t\\t\\tcase BASIS_FORMAT.cTFATC_RGBA_INTERPOLATED_ALPHA:\\n\\t\\t\\t\\treturn PIXEL_FORMAT.ATC_RGBA;\\n\\t\\t\\tcase BASIS_FORMAT.cTFRGBA32:\\n\\t\\t\\t\\treturn PIXEL_FORMAT.R8_G8_B8_A8;\\n\\t\\t\\tcase BASIS_FORMAT.cTFRGB565:\\n\\t\\t\\t\\treturn PIXEL_FORMAT.R5_G6_B5;\\n\\t\\t\\tcase BASIS_FORMAT.cTFRGBA4444:\\n\\t\\t\\t\\treturn PIXEL_FORMAT.R4_G4_B4_A4;\\n\\t\\t}\\n\\t};\\n\\tconst unswizzleGGGR = (data) => {\\n\\t\\tconst genB = function(R, G) {\\n\\t\\t\\tconst r = R * (2 / 255) - 1;\\n\\t\\t\\tconst g = G * (2 / 255) - 1;\\n\\t\\t\\tconst b = Math.sqrt(1 - Math.min(1, r * r + g * g));\\n\\t\\t\\treturn Math.max(0, Math.min(255, Math.floor((b + 1) * 0.5 * 255)));\\n\\t\\t};\\n\\t\\tfor (let offset = 0; offset < data.length; offset += 4) {\\n\\t\\t\\tconst R = data[offset + 3];\\n\\t\\t\\tconst G = data[offset + 1];\\n\\t\\t\\tdata[offset + 0] = R;\\n\\t\\t\\tdata[offset + 2] = genB(R, G);\\n\\t\\t\\tdata[offset + 3] = 255;\\n\\t\\t}\\n\\t\\treturn data;\\n\\t};\\n\\tconst pack565 = (data) => {\\n\\t\\tconst result = new Uint16Array(data.length / 4);\\n\\t\\tfor (let offset = 0; offset < data.length; offset += 4) {\\n\\t\\t\\tconst R = data[offset + 0];\\n\\t\\t\\tconst G = data[offset + 1];\\n\\t\\t\\tconst B = data[offset + 2];\\n\\t\\t\\tresult[offset / 4] = (R & 248) << 8 | // 5\\n\\t\\t\\t(G & 252) << 3 | // 6\\n\\t\\t\\tB >> 3;\\n\\t\\t}\\n\\t\\treturn result;\\n\\t};\\n\\tconst isPOT = (width, height) => {\\n\\t\\treturn (width & width - 1) === 0 && (height & height - 1) === 0;\\n\\t};\\n\\tconst performanceNow = () => {\\n\\t\\treturn typeof performance !== \\\"undefined\\\" ? performance.now() : 0;\\n\\t};\\n\\tlet basis;\\n\\tlet rgbPriority;\\n\\tlet rgbaPriority;\\n\\tconst chooseTargetFormat = (deviceDetails, hasAlpha, isUASTC) => {\\n\\t\\tif (isUASTC) {\\n\\t\\t\\tif (deviceDetails.formats.astc) {\\n\\t\\t\\t\\treturn \\\"astc\\\";\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tif (hasAlpha) {\\n\\t\\t\\t\\tif (deviceDetails.formats.etc2) {\\n\\t\\t\\t\\t\\treturn \\\"etc2\\\";\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (deviceDetails.formats.etc2) {\\n\\t\\t\\t\\t\\treturn \\\"etc2\\\";\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (deviceDetails.formats.etc1) {\\n\\t\\t\\t\\t\\treturn \\\"etc1\\\";\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst testInOrder = (priority) => {\\n\\t\\t\\tfor (let i = 0; i < priority.length; ++i) {\\n\\t\\t\\t\\tconst format = priority[i];\\n\\t\\t\\t\\tif (deviceDetails.formats[format]) {\\n\\t\\t\\t\\t\\treturn format;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\treturn \\\"none\\\";\\n\\t\\t};\\n\\t\\treturn testInOrder(hasAlpha ? rgbaPriority : rgbPriority);\\n\\t};\\n\\tconst dimensionsValid = (width, height, format) => {\\n\\t\\tswitch (format) {\\n\\t\\t\\t// etc1, 2\\n\\t\\t\\tcase BASIS_FORMAT.cTFETC1:\\n\\t\\t\\tcase BASIS_FORMAT.cTFETC2:\\n\\t\\t\\t\\treturn true;\\n\\t\\t\\t// dxt1, 5\\n\\t\\t\\tcase BASIS_FORMAT.cTFBC1:\\n\\t\\t\\tcase BASIS_FORMAT.cTFBC3:\\n\\t\\t\\t\\treturn (width & 3) === 0 && (height & 3) === 0;\\n\\t\\t\\t// pvrtc\\n\\t\\t\\tcase BASIS_FORMAT.cTFPVRTC1_4_RGB:\\n\\t\\t\\tcase BASIS_FORMAT.cTFPVRTC1_4_RGBA:\\n\\t\\t\\t\\treturn isPOT(width, height);\\n\\t\\t\\t// astc\\n\\t\\t\\tcase BASIS_FORMAT.cTFASTC_4x4:\\n\\t\\t\\t\\treturn true;\\n\\t\\t\\t// atc\\n\\t\\t\\tcase BASIS_FORMAT.cTFATC_RGB:\\n\\t\\t\\tcase BASIS_FORMAT.cTFATC_RGBA_INTERPOLATED_ALPHA:\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\treturn false;\\n\\t};\\n\\tconst transcodeKTX2 = (url, data, options) => {\\n\\t\\tif (!basis.KTX2File) {\\n\\t\\t\\tthrow new Error(\\\"Basis transcoder module does not include support for KTX2.\\\");\\n\\t\\t}\\n\\t\\tconst funcStart = performanceNow();\\n\\t\\tconst basisFile = new basis.KTX2File(new Uint8Array(data));\\n\\t\\tconst width = basisFile.getWidth();\\n\\t\\tconst height = basisFile.getHeight();\\n\\t\\tconst levels = basisFile.getLevels();\\n\\t\\tconst hasAlpha = !!basisFile.getHasAlpha();\\n\\t\\tconst isUASTC = basisFile.isUASTC && basisFile.isUASTC();\\n\\t\\tif (!width || !height || !levels) {\\n\\t\\t\\tbasisFile.close();\\n\\t\\t\\tbasisFile.delete();\\n\\t\\t\\tthrow new Error(`Invalid image dimensions url=${url} width=${width} height=${height} levels=${levels}`);\\n\\t\\t}\\n\\t\\tconst format = chooseTargetFormat(options.deviceDetails, hasAlpha, isUASTC);\\n\\t\\tconst unswizzle = !!options.isGGGR && format === \\\"pvr\\\";\\n\\t\\tlet basisFormat;\\n\\t\\tif (unswizzle) {\\n\\t\\t\\tbasisFormat = BASIS_FORMAT.cTFRGBA32;\\n\\t\\t} else {\\n\\t\\t\\tbasisFormat = hasAlpha ? alphaMapping[format] : opaqueMapping[format];\\n\\t\\t\\tif (!dimensionsValid(width, height, basisFormat)) {\\n\\t\\t\\t\\tbasisFormat = hasAlpha ? BASIS_FORMAT.cTFRGBA32 : BASIS_FORMAT.cTFRGB565;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (!basisFile.startTranscoding()) {\\n\\t\\t\\tbasisFile.close();\\n\\t\\t\\tbasisFile.delete();\\n\\t\\t\\tthrow new Error(`Failed to start transcoding url=${url}`);\\n\\t\\t}\\n\\t\\tlet i;\\n\\t\\tconst levelData = [];\\n\\t\\tfor (let mip = 0; mip < levels; ++mip) {\\n\\t\\t\\tconst dstSize = basisFile.getImageTranscodedSizeInBytes(mip, 0, 0, basisFormat);\\n\\t\\t\\tconst dst = new Uint8Array(dstSize);\\n\\t\\t\\tif (!basisFile.transcodeImage(dst, mip, 0, 0, basisFormat, 0, -1, -1)) {\\n\\t\\t\\t\\tbasisFile.close();\\n\\t\\t\\t\\tbasisFile.delete();\\n\\t\\t\\t\\tthrow new Error(`Failed to transcode image url=${url}`);\\n\\t\\t\\t}\\n\\t\\t\\tconst is16BitFormat = basisFormat === BASIS_FORMAT.cTFRGB565 || basisFormat === BASIS_FORMAT.cTFRGBA4444;\\n\\t\\t\\tlevelData.push(is16BitFormat ? new Uint16Array(dst.buffer) : dst);\\n\\t\\t}\\n\\t\\tbasisFile.close();\\n\\t\\tbasisFile.delete();\\n\\t\\tif (unswizzle) {\\n\\t\\t\\tbasisFormat = BASIS_FORMAT.cTFRGB565;\\n\\t\\t\\tfor (i = 0; i < levelData.length; ++i) {\\n\\t\\t\\t\\tlevelData[i] = pack565(unswizzleGGGR(levelData[i]));\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn {\\n\\t\\t\\tformat: basisToEngineMapping(basisFormat, options.deviceDetails),\\n\\t\\t\\twidth,\\n\\t\\t\\theight,\\n\\t\\t\\tlevels: levelData,\\n\\t\\t\\tcubemap: false,\\n\\t\\t\\ttranscodeTime: performanceNow() - funcStart,\\n\\t\\t\\turl,\\n\\t\\t\\tunswizzledGGGR: unswizzle\\n\\t\\t};\\n\\t};\\n\\tconst transcodeBasis = (url, data, options) => {\\n\\t\\tconst funcStart = performanceNow();\\n\\t\\tconst basisFile = new basis.BasisFile(new Uint8Array(data));\\n\\t\\tconst width = basisFile.getImageWidth(0, 0);\\n\\t\\tconst height = basisFile.getImageHeight(0, 0);\\n\\t\\tconst images = basisFile.getNumImages();\\n\\t\\tconst levels = basisFile.getNumLevels(0);\\n\\t\\tconst hasAlpha = !!basisFile.getHasAlpha();\\n\\t\\tconst isUASTC = basisFile.isUASTC && basisFile.isUASTC();\\n\\t\\tif (!width || !height || !images || !levels) {\\n\\t\\t\\tbasisFile.close();\\n\\t\\t\\tbasisFile.delete();\\n\\t\\t\\tthrow new Error(`Invalid image dimensions url=${url} width=${width} height=${height} images=${images} levels=${levels}`);\\n\\t\\t}\\n\\t\\tconst format = chooseTargetFormat(options.deviceDetails, hasAlpha, isUASTC);\\n\\t\\tconst unswizzle = !!options.isGGGR && format === \\\"pvr\\\";\\n\\t\\tlet basisFormat;\\n\\t\\tif (unswizzle) {\\n\\t\\t\\tbasisFormat = BASIS_FORMAT.cTFRGBA32;\\n\\t\\t} else {\\n\\t\\t\\tbasisFormat = hasAlpha ? alphaMapping[format] : opaqueMapping[format];\\n\\t\\t\\tif (!dimensionsValid(width, height, basisFormat)) {\\n\\t\\t\\t\\tbasisFormat = hasAlpha ? BASIS_FORMAT.cTFRGBA32 : BASIS_FORMAT.cTFRGB565;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (!basisFile.startTranscoding()) {\\n\\t\\t\\tbasisFile.close();\\n\\t\\t\\tbasisFile.delete();\\n\\t\\t\\tthrow new Error(`Failed to start transcoding url=${url}`);\\n\\t\\t}\\n\\t\\tlet i;\\n\\t\\tconst levelData = [];\\n\\t\\tfor (let mip = 0; mip < levels; ++mip) {\\n\\t\\t\\tconst dstSize = basisFile.getImageTranscodedSizeInBytes(0, mip, basisFormat);\\n\\t\\t\\tconst dst = new Uint8Array(dstSize);\\n\\t\\t\\tif (!basisFile.transcodeImage(dst, 0, mip, basisFormat, 0, 0)) {\\n\\t\\t\\t\\tif (mip === levels - 1 && dstSize === levelData[mip - 1].buffer.byteLength) {\\n\\t\\t\\t\\t\\tdst.set(new Uint8Array(levelData[mip - 1].buffer));\\n\\t\\t\\t\\t\\tconsole.warn(`Failed to transcode last mipmap level, using previous level instead url=${url}`);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tbasisFile.close();\\n\\t\\t\\t\\t\\tbasisFile.delete();\\n\\t\\t\\t\\t\\tthrow new Error(`Failed to transcode image url=${url}`);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tconst is16BitFormat = basisFormat === BASIS_FORMAT.cTFRGB565 || basisFormat === BASIS_FORMAT.cTFRGBA4444;\\n\\t\\t\\tlevelData.push(is16BitFormat ? new Uint16Array(dst.buffer) : dst);\\n\\t\\t}\\n\\t\\tbasisFile.close();\\n\\t\\tbasisFile.delete();\\n\\t\\tif (unswizzle) {\\n\\t\\t\\tbasisFormat = BASIS_FORMAT.cTFRGB565;\\n\\t\\t\\tfor (i = 0; i < levelData.length; ++i) {\\n\\t\\t\\t\\tlevelData[i] = pack565(unswizzleGGGR(levelData[i]));\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn {\\n\\t\\t\\tformat: basisToEngineMapping(basisFormat, options.deviceDetails),\\n\\t\\t\\twidth,\\n\\t\\t\\theight,\\n\\t\\t\\tlevels: levelData,\\n\\t\\t\\tcubemap: false,\\n\\t\\t\\ttranscodeTime: performanceNow() - funcStart,\\n\\t\\t\\turl,\\n\\t\\t\\tunswizzledGGGR: unswizzle\\n\\t\\t};\\n\\t};\\n\\tconst transcode = (url, data, options) => {\\n\\t\\treturn options.isKTX2 ? transcodeKTX2(url, data, options) : transcodeBasis(url, data, options);\\n\\t};\\n\\tconst workerTranscode = (url, data, options) => {\\n\\t\\ttry {\\n\\t\\t\\tconst result = transcode(url, data, options);\\n\\t\\t\\tresult.levels = result.levels.map((v) => v.buffer);\\n\\t\\t\\tself.postMessage({ url, data: result }, result.levels);\\n\\t\\t} catch (err) {\\n\\t\\t\\tself.postMessage({ url, err }, null);\\n\\t\\t}\\n\\t};\\n\\tconst workerInit = (config, callback) => {\\n\\t\\tconst instantiateWasmFunc = (imports, successCallback) => {\\n\\t\\t\\tWebAssembly.instantiate(config.module, imports).then((result) => {\\n\\t\\t\\t\\tsuccessCallback(result);\\n\\t\\t\\t}).catch((reason) => {\\n\\t\\t\\t\\tconsole.error(`instantiate failed + ${reason}`);\\n\\t\\t\\t});\\n\\t\\t\\treturn {};\\n\\t\\t};\\n\\t\\tself.BASIS(config.module ? { instantiateWasm: instantiateWasmFunc } : null).then((instance) => {\\n\\t\\t\\tinstance.initializeBasis();\\n\\t\\t\\tbasis = instance;\\n\\t\\t\\trgbPriority = config.rgbPriority;\\n\\t\\t\\trgbaPriority = config.rgbaPriority;\\n\\t\\t\\tcallback(null);\\n\\t\\t});\\n\\t};\\n\\tconst queue = [];\\n\\tself.onmessage = (message) => {\\n\\t\\tconst data = message.data;\\n\\t\\tswitch (data.type) {\\n\\t\\t\\tcase \\\"init\\\":\\n\\t\\t\\t\\tworkerInit(data.config, () => {\\n\\t\\t\\t\\t\\tfor (let i = 0; i < queue.length; ++i) {\\n\\t\\t\\t\\t\\t\\tworkerTranscode(queue[i].url, queue[i].data, queue[i].options);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tqueue.length = 0;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\tcase \\\"transcode\\\":\\n\\t\\t\\t\\tif (basis) {\\n\\t\\t\\t\\t\\tworkerTranscode(data.url, data.data, data.options);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tqueue.push(data);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tbreak;\\n\\t\\t}\\n\\t};\\n}\\n\\nconst getCompressionFormats = (device) => {\\n\\treturn {\\n\\t\\tastc: !!device.extCompressedTextureASTC,\\n\\t\\tatc: !!device.extCompressedTextureATC,\\n\\t\\tdxt: !!device.extCompressedTextureS3TC,\\n\\t\\tetc1: !!device.extCompressedTextureETC1,\\n\\t\\tetc2: !!device.extCompressedTextureETC,\\n\\t\\tpvr: !!device.extCompressedTexturePVRTC\\n\\t};\\n};\\nconst prepareWorkerModules = (config, callback) => {\\n\\tconst getWorkerBlob = (basisCode) => {\\n\\t\\tconst code = [\\n\\t\\t\\t\\\"/* basis */\\\",\\n\\t\\t\\tbasisCode,\\n\\t\\t\\t\\\"\\\",\\n\\t\\t\\t`(${BasisWorker.toString()})()\\n\\n`\\n\\t\\t].join(\\\"\\\\n\\\");\\n\\t\\treturn new Blob([code], { type: \\\"application/javascript\\\" });\\n\\t};\\n\\tconst wasmSupported = () => {\\n\\t\\ttry {\\n\\t\\t\\tif (typeof WebAssembly === \\\"object\\\" && typeof WebAssembly.instantiate === \\\"function\\\") {\\n\\t\\t\\t\\tconst module = new WebAssembly.Module(Uint8Array.of(0, 97, 115, 109, 1, 0, 0, 0));\\n\\t\\t\\t\\tif (module instanceof WebAssembly.Module) {\\n\\t\\t\\t\\t\\treturn new WebAssembly.Instance(module) instanceof WebAssembly.Instance;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t} catch (e) {\\n\\t\\t}\\n\\t\\treturn false;\\n\\t};\\n\\tconst sendResponse = (basisCode, module) => {\\n\\t\\tcallback(null, {\\n\\t\\t\\tworkerUrl: URL.createObjectURL(getWorkerBlob(basisCode)),\\n\\t\\t\\tmodule,\\n\\t\\t\\trgbPriority: config.rgbPriority,\\n\\t\\t\\trgbaPriority: config.rgbaPriority\\n\\t\\t});\\n\\t};\\n\\tconst options = {\\n\\t\\tcache: true,\\n\\t\\tresponseType: \\\"text\\\",\\n\\t\\tretry: config.maxRetries > 0,\\n\\t\\tmaxRetries: config.maxRetries\\n\\t};\\n\\tif (config.glueUrl && config.wasmUrl && wasmSupported()) {\\n\\t\\tlet basisCode = null;\\n\\t\\tlet module = null;\\n\\t\\thttp.get(config.glueUrl, options, (err, response) => {\\n\\t\\t\\tif (err) {\\n\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tif (module) {\\n\\t\\t\\t\\t\\tsendResponse(response, module);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tbasisCode = response;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tconst fetchPromise = fetch(config.wasmUrl);\\n\\t\\tconst compileManual = () => {\\n\\t\\t\\tfetchPromise.then((result) => result.arrayBuffer()).then((buffer) => WebAssembly.compile(buffer)).then((module_) => {\\n\\t\\t\\t\\tif (basisCode) {\\n\\t\\t\\t\\t\\tsendResponse(basisCode, module_);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tmodule = module_;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}).catch((err) => {\\n\\t\\t\\t\\tcallback(err, null);\\n\\t\\t\\t});\\n\\t\\t};\\n\\t\\tif (WebAssembly.compileStreaming) {\\n\\t\\t\\tWebAssembly.compileStreaming(fetchPromise).then((module_) => {\\n\\t\\t\\t\\tif (basisCode) {\\n\\t\\t\\t\\t\\tsendResponse(basisCode, module_);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tmodule = module_;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}).catch((err) => {\\n\\t\\t\\t\\tcompileManual();\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\tcompileManual();\\n\\t\\t}\\n\\t} else {\\n\\t\\thttp.get(config.fallbackUrl, options, (err, response) => {\\n\\t\\t\\tif (err) {\\n\\t\\t\\t\\tcallback(err, null);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tsendResponse(response, null);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n};\\nclass BasisQueue {\\n\\tconstructor() {\\n\\t\\tthis.callbacks = {};\\n\\t\\tthis.queue = [];\\n\\t\\tthis.clients = [];\\n\\t}\\n\\tenqueueJob(url, data, callback, options) {\\n\\t\\tif (this.callbacks.hasOwnProperty(url)) {\\n\\t\\t\\tthis.callbacks[url].push(callback);\\n\\t\\t} else {\\n\\t\\t\\tthis.callbacks[url] = [callback];\\n\\t\\t\\tconst job = {\\n\\t\\t\\t\\turl,\\n\\t\\t\\t\\tdata,\\n\\t\\t\\t\\toptions\\n\\t\\t\\t};\\n\\t\\t\\tif (this.clients.length > 0) {\\n\\t\\t\\t\\tthis.clients.shift().run(job);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.queue.push(job);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tenqueueClient(client) {\\n\\t\\tif (this.queue.length > 0) {\\n\\t\\t\\tclient.run(this.queue.shift());\\n\\t\\t} else {\\n\\t\\t\\tthis.clients.push(client);\\n\\t\\t}\\n\\t}\\n\\thandleResponse(url, err, data) {\\n\\t\\tconst callback = this.callbacks[url];\\n\\t\\tif (err) {\\n\\t\\t\\tfor (let i = 0; i < callback.length; ++i) {\\n\\t\\t\\t\\tcallback[i](err);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tif (data.format === PIXELFORMAT_RGB565 || data.format === PIXELFORMAT_RGBA4) {\\n\\t\\t\\t\\tdata.levels = data.levels.map((v) => {\\n\\t\\t\\t\\t\\treturn new Uint16Array(v);\\n\\t\\t\\t\\t});\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tdata.levels = data.levels.map((v) => {\\n\\t\\t\\t\\t\\treturn new Uint8Array(v);\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t\\tfor (let i = 0; i < callback.length; ++i) {\\n\\t\\t\\t\\tcallback[i](null, data);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdelete this.callbacks[url];\\n\\t}\\n}\\nclass BasisClient {\\n\\tconstructor(queue2, config, eager) {\\n\\t\\tthis.queue = queue2;\\n\\t\\tthis.worker = new Worker(config.workerUrl);\\n\\t\\tthis.worker.addEventListener(\\\"message\\\", (message) => {\\n\\t\\t\\tconst data = message.data;\\n\\t\\t\\tthis.queue.handleResponse(data.url, data.err, data.data);\\n\\t\\t\\tif (!this.eager) {\\n\\t\\t\\t\\tthis.queue.enqueueClient(this);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tthis.worker.postMessage({ type: \\\"init\\\", config });\\n\\t\\tthis.eager = eager;\\n\\t}\\n\\trun(job) {\\n\\t\\tconst transfer = [];\\n\\t\\tif (job.data instanceof ArrayBuffer) {\\n\\t\\t\\ttransfer.push(job.data);\\n\\t\\t}\\n\\t\\tthis.worker.postMessage({\\n\\t\\t\\ttype: \\\"transcode\\\",\\n\\t\\t\\turl: job.url,\\n\\t\\t\\tformat: job.format,\\n\\t\\t\\tdata: job.data,\\n\\t\\t\\toptions: job.options\\n\\t\\t}, transfer);\\n\\t\\tif (this.eager) {\\n\\t\\t\\tthis.queue.enqueueClient(this);\\n\\t\\t}\\n\\t}\\n}\\nconst defaultNumWorkers = 1;\\nconst defaultRgbPriority = [\\\"etc2\\\", \\\"etc1\\\", \\\"astc\\\", \\\"dxt\\\", \\\"pvr\\\", \\\"atc\\\"];\\nconst defaultRgbaPriority = [\\\"astc\\\", \\\"dxt\\\", \\\"etc2\\\", \\\"pvr\\\", \\\"atc\\\"];\\nconst defaultMaxRetries = 5;\\nconst queue = new BasisQueue();\\nlet lazyConfig = null;\\nlet initializing = false;\\nfunction basisInitialize(config) {\\n\\tif (initializing) {\\n\\t\\treturn;\\n\\t}\\n\\tif (!config) {\\n\\t\\tconfig = lazyConfig || {};\\n\\t} else if (config.lazyInit) {\\n\\t\\tlazyConfig = config;\\n\\t\\treturn;\\n\\t}\\n\\tif (!config.glueUrl || !config.wasmUrl || !config.fallbackUrl) {\\n\\t\\tconst moduleConfig = WasmModule.getConfig(\\\"BASIS\\\");\\n\\t\\tif (moduleConfig) {\\n\\t\\t\\tconfig = {\\n\\t\\t\\t\\tglueUrl: moduleConfig.glueUrl,\\n\\t\\t\\t\\twasmUrl: moduleConfig.wasmUrl,\\n\\t\\t\\t\\tfallbackUrl: moduleConfig.fallbackUrl,\\n\\t\\t\\t\\tnumWorkers: moduleConfig.numWorkers\\n\\t\\t\\t};\\n\\t\\t}\\n\\t}\\n\\tif (config.glueUrl || config.wasmUrl || config.fallbackUrl) {\\n\\t\\tinitializing = true;\\n\\t\\tconst numWorkers = Math.max(1, Math.min(16, config.numWorkers || defaultNumWorkers));\\n\\t\\tconst eagerWorkers = config.numWorkers === 1 || (config.hasOwnProperty(\\\"eagerWorkers\\\") ? config.eagerWorkers : true);\\n\\t\\tconfig.rgbPriority = config.rgbPriority || defaultRgbPriority;\\n\\t\\tconfig.rgbaPriority = config.rgbaPriority || defaultRgbaPriority;\\n\\t\\tconfig.maxRetries = config.hasOwnProperty(\\\"maxRetries\\\") ? config.maxRetries : defaultMaxRetries;\\n\\t\\tprepareWorkerModules(config, (err, clientConfig) => {\\n\\t\\t\\tif (err) {\\n\\t\\t\\t\\tconsole.error(`failed to initialize basis worker: ${err}`);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tfor (let i = 0; i < numWorkers; ++i) {\\n\\t\\t\\t\\t\\tqueue.enqueueClient(new BasisClient(queue, clientConfig, eagerWorkers));\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n}\\nlet deviceDetails = null;\\nfunction basisTranscode(device, url, data, callback, options) {\\n\\tbasisInitialize();\\n\\tif (!deviceDetails) {\\n\\t\\tdeviceDetails = {\\n\\t\\t\\tformats: getCompressionFormats(device)\\n\\t\\t};\\n\\t}\\n\\tqueue.enqueueJob(url, data, callback, {\\n\\t\\tdeviceDetails,\\n\\t\\tisGGGR: !!options?.isGGGR,\\n\\t\\tisKTX2: !!options?.isKTX2\\n\\t});\\n\\treturn initializing;\\n}\\n\\nclass TextureParser {\\n\\tload(url, callback, asset) {\\n\\t\\tthrow new Error(\\\"not implemented\\\");\\n\\t}\\n\\t/* eslint-disable jsdoc/require-returns-check */\\n\\topen(url, data, device) {\\n\\t\\tthrow new Error(\\\"not implemented\\\");\\n\\t}\\n\\t/* eslint-enable jsdoc/require-returns-check */\\n}\\n\\nclass BasisParser extends TextureParser {\\n\\tconstructor(registry, device) {\\n\\t\\tsuper();\\n\\t\\tthis.device = device;\\n\\t\\tthis.maxRetries = 0;\\n\\t}\\n\\tload(url, callback, asset) {\\n\\t\\tconst device = this.device;\\n\\t\\tconst transcode = (data) => {\\n\\t\\t\\tconst basisModuleFound = basisTranscode(\\n\\t\\t\\t\\tdevice,\\n\\t\\t\\t\\turl.load,\\n\\t\\t\\t\\tdata,\\n\\t\\t\\t\\tcallback,\\n\\t\\t\\t\\t{ isGGGR: (asset?.file?.variants?.basis?.opt & 8) !== 0 }\\n\\t\\t\\t);\\n\\t\\t\\tif (!basisModuleFound) {\\n\\t\\t\\t\\tcallback(`Basis module not found. Asset [${asset.name}](${asset.getFileUrl()}) basis texture variant will not be loaded.`);\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tAsset.fetchArrayBuffer(url.load, (err, result) => {\\n\\t\\t\\tif (err) {\\n\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\ttranscode(result);\\n\\t\\t\\t}\\n\\t\\t}, asset, this.maxRetries);\\n\\t}\\n\\t// our async transcode call provides the neat structure we need to create the texture instance\\n\\topen(url, data, device, textureOptions = {}) {\\n\\t\\tconst format = textureOptions.srgb ? pixelFormatLinearToGamma(data.format) : data.format;\\n\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\tname: url,\\n\\t\\t\\taddressU: data.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,\\n\\t\\t\\taddressV: data.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,\\n\\t\\t\\twidth: data.width,\\n\\t\\t\\theight: data.height,\\n\\t\\t\\tformat,\\n\\t\\t\\tcubemap: data.cubemap,\\n\\t\\t\\tlevels: data.levels,\\n\\t\\t\\t...textureOptions\\n\\t\\t});\\n\\t\\ttexture.upload();\\n\\t\\treturn texture;\\n\\t}\\n}\\n\\nclass ImgParser extends TextureParser {\\n\\tconstructor(registry, device) {\\n\\t\\tsuper();\\n\\t\\tthis.crossOrigin = registry.prefix ? \\\"anonymous\\\" : null;\\n\\t\\tthis.maxRetries = 0;\\n\\t\\tthis.device = device;\\n\\t}\\n\\tload(url, callback, asset) {\\n\\t\\tconst hasContents = !!asset?.file?.contents;\\n\\t\\tif (hasContents) {\\n\\t\\t\\tif (this.device.supportsImageBitmap) {\\n\\t\\t\\t\\tthis._loadImageBitmapFromBlob(new Blob([asset.file.contents]), callback);\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\turl = {\\n\\t\\t\\t\\tload: URL.createObjectURL(new Blob([asset.file.contents])),\\n\\t\\t\\t\\toriginal: url.original\\n\\t\\t\\t};\\n\\t\\t}\\n\\t\\tconst handler = (err, result) => {\\n\\t\\t\\tif (hasContents) {\\n\\t\\t\\t\\tURL.revokeObjectURL(url.load);\\n\\t\\t\\t}\\n\\t\\t\\tcallback(err, result);\\n\\t\\t};\\n\\t\\tlet crossOrigin;\\n\\t\\tif (asset && asset.options && asset.options.hasOwnProperty(\\\"crossOrigin\\\")) {\\n\\t\\t\\tcrossOrigin = asset.options.crossOrigin;\\n\\t\\t} else if (ABSOLUTE_URL.test(url.load)) {\\n\\t\\t\\tcrossOrigin = this.crossOrigin;\\n\\t\\t}\\n\\t\\tif (this.device.supportsImageBitmap) {\\n\\t\\t\\tthis._loadImageBitmap(url.load, url.original, crossOrigin, handler, asset);\\n\\t\\t} else {\\n\\t\\t\\tthis._loadImage(url.load, url.original, crossOrigin, handler, asset);\\n\\t\\t}\\n\\t}\\n\\topen(url, data, device, textureOptions = {}) {\\n\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\tname: url,\\n\\t\\t\\twidth: data.width,\\n\\t\\t\\theight: data.height,\\n\\t\\t\\tformat: textureOptions.srgb ? PIXELFORMAT_SRGBA8 : PIXELFORMAT_RGBA8,\\n\\t\\t\\t...textureOptions\\n\\t\\t});\\n\\t\\ttexture.setSource(data);\\n\\t\\treturn texture;\\n\\t}\\n\\t_loadImage(url, originalUrl, crossOrigin, callback, asset) {\\n\\t\\tconst image = new Image();\\n\\t\\tif (crossOrigin) {\\n\\t\\t\\timage.crossOrigin = crossOrigin;\\n\\t\\t}\\n\\t\\tlet retries = 0;\\n\\t\\tconst maxRetries = this.maxRetries;\\n\\t\\tlet retryTimeout;\\n\\t\\tconst dummySize = 1024 * 1024;\\n\\t\\tasset?.fire(\\\"progress\\\", 0, dummySize);\\n\\t\\timage.onload = function() {\\n\\t\\t\\tasset?.fire(\\\"progress\\\", dummySize, dummySize);\\n\\t\\t\\tcallback(null, image);\\n\\t\\t};\\n\\t\\timage.onerror = function() {\\n\\t\\t\\tif (retryTimeout) return;\\n\\t\\t\\tif (maxRetries > 0 && ++retries <= maxRetries) {\\n\\t\\t\\t\\tconst retryDelay = Math.pow(2, retries) * 100;\\n\\t\\t\\t\\tconsole.log(`Error loading Texture from: '${originalUrl}' - Retrying in ${retryDelay}ms...`);\\n\\t\\t\\t\\tconst idx = url.indexOf(\\\"?\\\");\\n\\t\\t\\t\\tconst separator = idx >= 0 ? \\\"&\\\" : \\\"?\\\";\\n\\t\\t\\t\\tretryTimeout = setTimeout(() => {\\n\\t\\t\\t\\t\\timage.src = `${url + separator}retry=${Date.now()}`;\\n\\t\\t\\t\\t\\tretryTimeout = null;\\n\\t\\t\\t\\t}, retryDelay);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tcallback(`Error loading Texture from: '${originalUrl}'`);\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\timage.src = url;\\n\\t}\\n\\t_loadImageBitmap(url, originalUrl, crossOrigin, callback, asset) {\\n\\t\\tconst options = {\\n\\t\\t\\tcache: true,\\n\\t\\t\\tresponseType: \\\"blob\\\",\\n\\t\\t\\tretry: this.maxRetries > 0,\\n\\t\\t\\tmaxRetries: this.maxRetries,\\n\\t\\t\\tprogress: asset\\n\\t\\t};\\n\\t\\thttp.get(url, options, (err, blob) => {\\n\\t\\t\\tif (err) {\\n\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._loadImageBitmapFromBlob(blob, callback);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n\\t_loadImageBitmapFromBlob(blob, callback) {\\n\\t\\tcreateImageBitmap(blob, {\\n\\t\\t\\tpremultiplyAlpha: \\\"none\\\",\\n\\t\\t\\tcolorSpaceConversion: \\\"none\\\"\\n\\t\\t}).then((imageBitmap) => callback(null, imageBitmap)).catch((e) => callback(e));\\n\\t}\\n}\\n\\nconst IDENTIFIER = [1481919403, 3140563232, 169478669];\\nconst KNOWN_FORMATS = {\\n\\t// compressed formats\\n\\t33776: PIXELFORMAT_DXT1,\\n\\t33778: PIXELFORMAT_DXT3,\\n\\t33779: PIXELFORMAT_DXT5,\\n\\t36196: PIXELFORMAT_ETC1,\\n\\t37492: PIXELFORMAT_ETC2_RGB,\\n\\t37496: PIXELFORMAT_ETC2_RGBA,\\n\\t35840: PIXELFORMAT_PVRTC_4BPP_RGB_1,\\n\\t35841: PIXELFORMAT_PVRTC_2BPP_RGB_1,\\n\\t35842: PIXELFORMAT_PVRTC_4BPP_RGBA_1,\\n\\t35843: PIXELFORMAT_PVRTC_2BPP_RGBA_1,\\n\\t// uncompressed formats\\n\\t32849: PIXELFORMAT_RGB8,\\n\\t// GL_RGB8\\n\\t32856: PIXELFORMAT_RGBA8,\\n\\t// GL_RGBA8\\n\\t35905: PIXELFORMAT_SRGB8,\\n\\t// GL_SRGB8\\n\\t35907: PIXELFORMAT_SRGBA8,\\n\\t// GL_SRGB8_ALPHA8\\n\\t35898: PIXELFORMAT_111110F,\\n\\t// GL_R11F_G11F_B10F\\n\\t34843: PIXELFORMAT_RGB16F,\\n\\t// GL_RGB16F\\n\\t34842: PIXELFORMAT_RGBA16F\\n\\t// GL_RGBA16F\\n};\\nfunction createContainer(pixelFormat, buffer, byteOffset, byteSize) {\\n\\treturn pixelFormat === PIXELFORMAT_111110F ? new Uint32Array(buffer, byteOffset, byteSize / 4) : new Uint8Array(buffer, byteOffset, byteSize);\\n}\\nclass KtxParser extends TextureParser {\\n\\tconstructor(registry) {\\n\\t\\tsuper();\\n\\t\\tthis.maxRetries = 0;\\n\\t}\\n\\tload(url, callback, asset) {\\n\\t\\tAsset.fetchArrayBuffer(url.load, callback, asset, this.maxRetries);\\n\\t}\\n\\topen(url, data, device, textureOptions = {}) {\\n\\t\\tconst textureData = this.parse(data);\\n\\t\\tif (!textureData) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tconst format = textureOptions.srgb ? pixelFormatLinearToGamma(textureData.format) : textureData.format;\\n\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\tname: url,\\n\\t\\t\\taddressU: textureData.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,\\n\\t\\t\\taddressV: textureData.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,\\n\\t\\t\\twidth: textureData.width,\\n\\t\\t\\theight: textureData.height,\\n\\t\\t\\tformat,\\n\\t\\t\\tcubemap: textureData.cubemap,\\n\\t\\t\\tlevels: textureData.levels,\\n\\t\\t\\t...textureOptions\\n\\t\\t});\\n\\t\\ttexture.upload();\\n\\t\\treturn texture;\\n\\t}\\n\\tparse(data) {\\n\\t\\tconst dataU32 = new Uint32Array(data);\\n\\t\\tif (IDENTIFIER[0] !== dataU32[0] || IDENTIFIER[1] !== dataU32[1] || IDENTIFIER[2] !== dataU32[2]) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tconst header = {\\n\\t\\t\\tendianness: dataU32[3],\\n\\t\\t\\t// todo: Use this information\\n\\t\\t\\tglType: dataU32[4],\\n\\t\\t\\tglTypeSize: dataU32[5],\\n\\t\\t\\tglFormat: dataU32[6],\\n\\t\\t\\tglInternalFormat: dataU32[7],\\n\\t\\t\\tglBaseInternalFormat: dataU32[8],\\n\\t\\t\\tpixelWidth: dataU32[9],\\n\\t\\t\\tpixelHeight: dataU32[10],\\n\\t\\t\\tpixelDepth: dataU32[11],\\n\\t\\t\\tnumberOfArrayElements: dataU32[12],\\n\\t\\t\\tnumberOfFaces: dataU32[13],\\n\\t\\t\\tnumberOfMipmapLevels: dataU32[14],\\n\\t\\t\\tbytesOfKeyValueData: dataU32[15]\\n\\t\\t};\\n\\t\\tif (header.pixelDepth > 1) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tif (header.numberOfArrayElements !== 0) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tconst format = KNOWN_FORMATS[header.glInternalFormat];\\n\\t\\tif (format === void 0) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tlet offset = 16 + header.bytesOfKeyValueData / 4;\\n\\t\\tconst isCubemap = header.numberOfFaces > 1;\\n\\t\\tconst levels = [];\\n\\t\\tfor (let mipmapLevel = 0; mipmapLevel < (header.numberOfMipmapLevels || 1); mipmapLevel++) {\\n\\t\\t\\tconst imageSizeInBytes = dataU32[offset++];\\n\\t\\t\\tif (isCubemap) {\\n\\t\\t\\t\\tlevels.push([]);\\n\\t\\t\\t}\\n\\t\\t\\tconst target = isCubemap ? levels[mipmapLevel] : levels;\\n\\t\\t\\tfor (let face = 0; face < (isCubemap ? 6 : 1); ++face) {\\n\\t\\t\\t\\ttarget.push(createContainer(format, data, offset * 4, imageSizeInBytes));\\n\\t\\t\\t\\toffset += imageSizeInBytes + 3 >> 2;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn {\\n\\t\\t\\tformat,\\n\\t\\t\\twidth: header.pixelWidth,\\n\\t\\t\\theight: header.pixelHeight,\\n\\t\\t\\tlevels,\\n\\t\\t\\tcubemap: isCubemap\\n\\t\\t};\\n\\t}\\n}\\n\\nconst KHRConstants = {\\n\\tKHR_DF_MODEL_UASTC: 166\\n};\\nclass Ktx2Parser extends TextureParser {\\n\\tconstructor(registry, device) {\\n\\t\\tsuper();\\n\\t\\tthis.maxRetries = 0;\\n\\t\\tthis.device = device;\\n\\t}\\n\\tload(url, callback, asset) {\\n\\t\\tAsset.fetchArrayBuffer(url.load, (err, result) => {\\n\\t\\t\\tif (err) {\\n\\t\\t\\t\\tcallback(err, result);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.parse(result, url, callback, asset);\\n\\t\\t\\t}\\n\\t\\t}, asset, this.maxRetries);\\n\\t}\\n\\topen(url, data, device, textureOptions = {}) {\\n\\t\\tconst format = textureOptions.srgb ? pixelFormatLinearToGamma(data.format) : data.format;\\n\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\tname: url,\\n\\t\\t\\taddressU: data.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,\\n\\t\\t\\taddressV: data.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,\\n\\t\\t\\twidth: data.width,\\n\\t\\t\\theight: data.height,\\n\\t\\t\\tformat,\\n\\t\\t\\tcubemap: data.cubemap,\\n\\t\\t\\tlevels: data.levels,\\n\\t\\t\\t...textureOptions\\n\\t\\t});\\n\\t\\ttexture.upload();\\n\\t\\treturn texture;\\n\\t}\\n\\tparse(arraybuffer, url, callback, asset) {\\n\\t\\tconst rs = new ReadStream(arraybuffer);\\n\\t\\tconst magic = [rs.readU32be(), rs.readU32be(), rs.readU32be()];\\n\\t\\tif (magic[0] !== 2873840728 || magic[1] !== 540160187 || magic[2] !== 218765834) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tconst header = {\\n\\t\\t\\tvkFormat: rs.readU32(),\\n\\t\\t\\ttypeSize: rs.readU32(),\\n\\t\\t\\tpixelWidth: rs.readU32(),\\n\\t\\t\\tpixelHeight: rs.readU32(),\\n\\t\\t\\tpixelDepth: rs.readU32(),\\n\\t\\t\\tlayerCount: rs.readU32(),\\n\\t\\t\\tfaceCount: rs.readU32(),\\n\\t\\t\\tlevelCount: rs.readU32(),\\n\\t\\t\\tsupercompressionScheme: rs.readU32()\\n\\t\\t};\\n\\t\\tconst index = {\\n\\t\\t\\tdfdByteOffset: rs.readU32(),\\n\\t\\t\\tdfdByteLength: rs.readU32(),\\n\\t\\t\\tkvdByteOffset: rs.readU32(),\\n\\t\\t\\tkvdByteLength: rs.readU32(),\\n\\t\\t\\tsgdByteOffset: rs.readU64(),\\n\\t\\t\\tsgdByteLength: rs.readU64()\\n\\t\\t};\\n\\t\\tconst levels = [];\\n\\t\\tfor (let i = 0; i < Math.max(1, header.levelCount); ++i) {\\n\\t\\t\\tlevels.push({\\n\\t\\t\\t\\tbyteOffset: rs.readU64(),\\n\\t\\t\\t\\tbyteLength: rs.readU64(),\\n\\t\\t\\t\\tuncompressedByteLength: rs.readU64()\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tconst dfdTotalSize = rs.readU32();\\n\\t\\tif (dfdTotalSize !== index.kvdByteOffset - index.dfdByteOffset) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\trs.skip(8);\\n\\t\\tconst colorModel = rs.readU8();\\n\\t\\trs.skip(index.dfdByteLength - 9);\\n\\t\\trs.skip(index.kvdByteLength);\\n\\t\\tif (header.supercompressionScheme === 1 || colorModel === KHRConstants.KHR_DF_MODEL_UASTC) {\\n\\t\\t\\tconst basisModuleFound = basisTranscode(\\n\\t\\t\\t\\tthis.device,\\n\\t\\t\\t\\turl.load,\\n\\t\\t\\t\\tarraybuffer,\\n\\t\\t\\t\\tcallback,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\tisGGGR: (asset?.file?.variants?.basis?.opt & 8) !== 0,\\n\\t\\t\\t\\t\\tisKTX2: true\\n\\t\\t\\t\\t}\\n\\t\\t\\t);\\n\\t\\t\\tif (!basisModuleFound) {\\n\\t\\t\\t\\tcallback(`Basis module not found. Asset [${asset.name}](${asset.getFileUrl()}) basis texture variant will not be loaded.`);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tcallback(\\\"unsupported KTX2 pixel format\\\");\\n\\t\\t}\\n\\t}\\n}\\n\\nclass DdsParser extends TextureParser {\\n\\tconstructor(registry) {\\n\\t\\tsuper();\\n\\t\\tthis.maxRetries = 0;\\n\\t}\\n\\tload(url, callback, asset) {\\n\\t\\tAsset.fetchArrayBuffer(url.load, callback, asset, this.maxRetries);\\n\\t}\\n\\topen(url, data, device, textureOptions = {}) {\\n\\t\\tconst header = new Uint32Array(data, 0, 128 / 4);\\n\\t\\tconst width = header[4];\\n\\t\\tconst height = header[3];\\n\\t\\tconst mips = Math.max(header[7], 1);\\n\\t\\tconst isFourCc = header[20] === 4;\\n\\t\\tconst fcc = header[21];\\n\\t\\tconst bpp = header[22];\\n\\t\\tconst isCubemap = header[28] === 65024;\\n\\t\\tconst FCC_DXT1 = 827611204;\\n\\t\\tconst FCC_DXT5 = 894720068;\\n\\t\\tconst FCC_FP16 = 113;\\n\\t\\tconst FCC_FP32 = 116;\\n\\t\\tconst FCC_ETC1 = 826496069;\\n\\t\\tconst FCC_PVRTC_2BPP_RGB_1 = 825438800;\\n\\t\\tconst FCC_PVRTC_2BPP_RGBA_1 = 825504336;\\n\\t\\tconst FCC_PVRTC_4BPP_RGB_1 = 825439312;\\n\\t\\tconst FCC_PVRTC_4BPP_RGBA_1 = 825504848;\\n\\t\\tlet compressed = false;\\n\\t\\tlet etc1 = false;\\n\\t\\tlet pvrtc2 = false;\\n\\t\\tlet pvrtc4 = false;\\n\\t\\tlet format = null;\\n\\t\\tlet componentSize = 1;\\n\\t\\tlet texture;\\n\\t\\tif (isFourCc) {\\n\\t\\t\\tif (fcc === FCC_DXT1) {\\n\\t\\t\\t\\tformat = PIXELFORMAT_DXT1;\\n\\t\\t\\t\\tcompressed = true;\\n\\t\\t\\t} else if (fcc === FCC_DXT5) {\\n\\t\\t\\t\\tformat = PIXELFORMAT_DXT5;\\n\\t\\t\\t\\tcompressed = true;\\n\\t\\t\\t} else if (fcc === FCC_FP16) {\\n\\t\\t\\t\\tformat = PIXELFORMAT_RGBA16F;\\n\\t\\t\\t\\tcomponentSize = 2;\\n\\t\\t\\t} else if (fcc === FCC_FP32) {\\n\\t\\t\\t\\tformat = PIXELFORMAT_RGBA32F;\\n\\t\\t\\t\\tcomponentSize = 4;\\n\\t\\t\\t} else if (fcc === FCC_ETC1) {\\n\\t\\t\\t\\tformat = PIXELFORMAT_ETC1;\\n\\t\\t\\t\\tcompressed = true;\\n\\t\\t\\t\\tetc1 = true;\\n\\t\\t\\t} else if (fcc === FCC_PVRTC_2BPP_RGB_1 || fcc === FCC_PVRTC_2BPP_RGBA_1) {\\n\\t\\t\\t\\tformat = fcc === FCC_PVRTC_2BPP_RGB_1 ? PIXELFORMAT_PVRTC_2BPP_RGB_1 : PIXELFORMAT_PVRTC_2BPP_RGBA_1;\\n\\t\\t\\t\\tcompressed = true;\\n\\t\\t\\t\\tpvrtc2 = true;\\n\\t\\t\\t} else if (fcc === FCC_PVRTC_4BPP_RGB_1 || fcc === FCC_PVRTC_4BPP_RGBA_1) {\\n\\t\\t\\t\\tformat = fcc === FCC_PVRTC_4BPP_RGB_1 ? PIXELFORMAT_PVRTC_4BPP_RGB_1 : PIXELFORMAT_PVRTC_4BPP_RGBA_1;\\n\\t\\t\\t\\tcompressed = true;\\n\\t\\t\\t\\tpvrtc4 = true;\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tif (bpp === 32) {\\n\\t\\t\\t\\tformat = PIXELFORMAT_RGBA8;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (!format) {\\n\\t\\t\\ttexture = new Texture(device, {\\n\\t\\t\\t\\twidth: 4,\\n\\t\\t\\t\\theight: 4,\\n\\t\\t\\t\\tformat: PIXELFORMAT_RGB8,\\n\\t\\t\\t\\tname: \\\"dds-legacy-empty\\\"\\n\\t\\t\\t});\\n\\t\\t\\treturn texture;\\n\\t\\t}\\n\\t\\ttexture = new Texture(device, {\\n\\t\\t\\tname: url,\\n\\t\\t\\taddressU: isCubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,\\n\\t\\t\\taddressV: isCubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,\\n\\t\\t\\twidth,\\n\\t\\t\\theight,\\n\\t\\t\\tformat,\\n\\t\\t\\tcubemap: isCubemap,\\n\\t\\t\\tmipmaps: mips > 1,\\n\\t\\t\\t...textureOptions\\n\\t\\t});\\n\\t\\tlet offset = 128;\\n\\t\\tconst faces = isCubemap ? 6 : 1;\\n\\t\\tlet mipSize;\\n\\t\\tconst DXT_BLOCK_WIDTH = 4;\\n\\t\\tconst DXT_BLOCK_HEIGHT = 4;\\n\\t\\tconst blockSize = fcc === FCC_DXT1 ? 8 : 16;\\n\\t\\tlet numBlocksAcross, numBlocksDown, numBlocks;\\n\\t\\tfor (let face = 0; face < faces; face++) {\\n\\t\\t\\tlet mipWidth = width;\\n\\t\\t\\tlet mipHeight = height;\\n\\t\\t\\tfor (let i = 0; i < mips; i++) {\\n\\t\\t\\t\\tif (compressed) {\\n\\t\\t\\t\\t\\tif (etc1) {\\n\\t\\t\\t\\t\\t\\tmipSize = Math.floor((mipWidth + 3) / 4) * Math.floor((mipHeight + 3) / 4) * 8;\\n\\t\\t\\t\\t\\t} else if (pvrtc2) {\\n\\t\\t\\t\\t\\t\\tmipSize = Math.max(mipWidth, 16) * Math.max(mipHeight, 8) / 4;\\n\\t\\t\\t\\t\\t} else if (pvrtc4) {\\n\\t\\t\\t\\t\\t\\tmipSize = Math.max(mipWidth, 8) * Math.max(mipHeight, 8) / 2;\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tnumBlocksAcross = Math.floor((mipWidth + DXT_BLOCK_WIDTH - 1) / DXT_BLOCK_WIDTH);\\n\\t\\t\\t\\t\\t\\tnumBlocksDown = Math.floor((mipHeight + DXT_BLOCK_HEIGHT - 1) / DXT_BLOCK_HEIGHT);\\n\\t\\t\\t\\t\\t\\tnumBlocks = numBlocksAcross * numBlocksDown;\\n\\t\\t\\t\\t\\t\\tmipSize = numBlocks * blockSize;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tmipSize = mipWidth * mipHeight * 4;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst mipBuff = format === PIXELFORMAT_RGBA32F ? new Float32Array(data, offset, mipSize) : format === PIXELFORMAT_RGBA16F ? new Uint16Array(data, offset, mipSize) : new Uint8Array(data, offset, mipSize);\\n\\t\\t\\t\\tif (!isCubemap) {\\n\\t\\t\\t\\t\\ttexture._levels[i] = mipBuff;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tif (!texture._levels[i]) texture._levels[i] = [];\\n\\t\\t\\t\\t\\ttexture._levels[i][face] = mipBuff;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\toffset += mipSize * componentSize;\\n\\t\\t\\t\\tmipWidth = Math.max(mipWidth * 0.5, 1);\\n\\t\\t\\t\\tmipHeight = Math.max(mipHeight * 0.5, 1);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\ttexture.upload();\\n\\t\\treturn texture;\\n\\t}\\n}\\n\\nclass HdrParser extends TextureParser {\\n\\tconstructor(registry) {\\n\\t\\tsuper();\\n\\t\\tthis.maxRetries = 0;\\n\\t}\\n\\tload(url, callback, asset) {\\n\\t\\tAsset.fetchArrayBuffer(url.load, callback, asset, this.maxRetries);\\n\\t\\tif (asset.data && !asset.data.type) {\\n\\t\\t\\tasset.data.type = TEXTURETYPE_RGBE;\\n\\t\\t}\\n\\t}\\n\\topen(url, data, device, textureOptions = {}) {\\n\\t\\tconst textureData = this.parse(data);\\n\\t\\tif (!textureData) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\tname: url,\\n\\t\\t\\taddressU: ADDRESS_REPEAT,\\n\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\twidth: textureData.width,\\n\\t\\t\\theight: textureData.height,\\n\\t\\t\\tlevels: textureData.levels,\\n\\t\\t\\tformat: PIXELFORMAT_RGBA8,\\n\\t\\t\\ttype: TEXTURETYPE_RGBE,\\n\\t\\t\\t// RGBE can't be filtered, so mipmaps are out of the question! (unless we generated them ourselves)\\n\\t\\t\\tmipmaps: false,\\n\\t\\t\\t...textureOptions\\n\\t\\t});\\n\\t\\ttexture.upload();\\n\\t\\treturn texture;\\n\\t}\\n\\t// https://floyd.lbl.gov/radiance/refer/filefmts.pdf with help from http://www.graphics.cornell.edu/~bjw/rgbe/rgbe.c\\n\\tparse(data) {\\n\\t\\tconst readStream = new ReadStream(data);\\n\\t\\tconst magic = readStream.readLine();\\n\\t\\tif (!magic.startsWith(\\\"#?RADIANCE\\\")) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tconst variables = {};\\n\\t\\twhile (true) {\\n\\t\\t\\tconst line = readStream.readLine();\\n\\t\\t\\tif (line.length === 0) {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tconst parts = line.split(\\\"=\\\");\\n\\t\\t\\t\\tif (parts.length === 2) {\\n\\t\\t\\t\\t\\tvariables[parts[0]] = parts[1];\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (!variables.hasOwnProperty(\\\"FORMAT\\\")) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tconst resolution = readStream.readLine().split(\\\" \\\");\\n\\t\\tif (resolution.length !== 4) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tconst height = parseInt(resolution[1], 10);\\n\\t\\tconst width = parseInt(resolution[3], 10);\\n\\t\\tconst pixels = this._readPixels(readStream, width, height, resolution[0] === \\\"-Y\\\");\\n\\t\\tif (!pixels) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\treturn {\\n\\t\\t\\twidth,\\n\\t\\t\\theight,\\n\\t\\t\\tlevels: [pixels]\\n\\t\\t};\\n\\t}\\n\\t_readPixels(readStream, width, height, flipY) {\\n\\t\\tif (width < 8 || width > 32767) {\\n\\t\\t\\treturn this._readPixelsFlat(readStream, width, height);\\n\\t\\t}\\n\\t\\tconst rgbe = [0, 0, 0, 0];\\n\\t\\treadStream.readArray(rgbe);\\n\\t\\tif (rgbe[0] !== 2 || rgbe[1] !== 2 || (rgbe[2] & 128) !== 0) {\\n\\t\\t\\treadStream.skip(-4);\\n\\t\\t\\treturn this._readPixelsFlat(readStream, width, height);\\n\\t\\t}\\n\\t\\tconst buffer = new ArrayBuffer(width * height * 4);\\n\\t\\tconst view = new Uint8Array(buffer);\\n\\t\\tlet scanstart = flipY ? 0 : width * 4 * (height - 1);\\n\\t\\tlet x, y, i, channel, count, value;\\n\\t\\tfor (y = 0; y < height; ++y) {\\n\\t\\t\\tif (y) {\\n\\t\\t\\t\\treadStream.readArray(rgbe);\\n\\t\\t\\t}\\n\\t\\t\\tif ((rgbe[2] << 8) + rgbe[3] !== width) {\\n\\t\\t\\t\\treturn null;\\n\\t\\t\\t}\\n\\t\\t\\tfor (channel = 0; channel < 4; ++channel) {\\n\\t\\t\\t\\tx = 0;\\n\\t\\t\\t\\twhile (x < width) {\\n\\t\\t\\t\\t\\tcount = readStream.readU8();\\n\\t\\t\\t\\t\\tif (count > 128) {\\n\\t\\t\\t\\t\\t\\tcount -= 128;\\n\\t\\t\\t\\t\\t\\tif (x + count > width) {\\n\\t\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tvalue = readStream.readU8();\\n\\t\\t\\t\\t\\t\\tfor (i = 0; i < count; ++i) {\\n\\t\\t\\t\\t\\t\\t\\tview[scanstart + channel + 4 * x++] = value;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (count === 0 || x + count > width) {\\n\\t\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor (i = 0; i < count; ++i) {\\n\\t\\t\\t\\t\\t\\t\\tview[scanstart + channel + 4 * x++] = readStream.readU8();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tscanstart += width * 4 * (flipY ? 1 : -1);\\n\\t\\t}\\n\\t\\treturn view;\\n\\t}\\n\\t_readPixelsFlat(readStream, width, height) {\\n\\t\\treturn readStream.remainingBytes === width * height * 4 ? new Uint8Array(readStream.arraybuffer, readStream.offset) : null;\\n\\t}\\n}\\n\\nconst JSON_ADDRESS_MODE = {\\n\\t\\\"repeat\\\": ADDRESS_REPEAT,\\n\\t\\\"clamp\\\": ADDRESS_CLAMP_TO_EDGE,\\n\\t\\\"mirror\\\": ADDRESS_MIRRORED_REPEAT\\n};\\nconst JSON_FILTER_MODE = {\\n\\t\\\"nearest\\\": FILTER_NEAREST,\\n\\t\\\"linear\\\": FILTER_LINEAR,\\n\\t\\\"nearest_mip_nearest\\\": FILTER_NEAREST_MIPMAP_NEAREST,\\n\\t\\\"linear_mip_nearest\\\": FILTER_LINEAR_MIPMAP_NEAREST,\\n\\t\\\"nearest_mip_linear\\\": FILTER_NEAREST_MIPMAP_LINEAR,\\n\\t\\\"linear_mip_linear\\\": FILTER_LINEAR_MIPMAP_LINEAR\\n};\\nconst JSON_TEXTURE_TYPE = {\\n\\t\\\"default\\\": TEXTURETYPE_DEFAULT,\\n\\t\\\"rgbm\\\": TEXTURETYPE_RGBM,\\n\\t\\\"rgbe\\\": TEXTURETYPE_RGBE,\\n\\t\\\"rgbp\\\": TEXTURETYPE_RGBP,\\n\\t\\\"swizzleGGGR\\\": TEXTURETYPE_SWIZZLEGGGR\\n};\\nconst _completePartialMipmapChain = function(texture) {\\n\\tconst requiredMipLevels = TextureUtils.calcMipLevelsCount(texture._width, texture._height);\\n\\tconst isHtmlElement = function(object) {\\n\\t\\treturn object instanceof HTMLCanvasElement || object instanceof HTMLImageElement || object instanceof HTMLVideoElement;\\n\\t};\\n\\tif (!(texture._format === PIXELFORMAT_RGBA8 || texture._format === PIXELFORMAT_RGBA32F) || texture._volume || texture._compressed || texture._levels.length === 1 || texture._levels.length === requiredMipLevels || isHtmlElement(texture._cubemap ? texture._levels[0][0] : texture._levels[0])) {\\n\\t\\treturn;\\n\\t}\\n\\tconst downsample = function(width, height, data) {\\n\\t\\tconst sampledWidth = Math.max(1, width >> 1);\\n\\t\\tconst sampledHeight = Math.max(1, height >> 1);\\n\\t\\tconst sampledData = new data.constructor(sampledWidth * sampledHeight * 4);\\n\\t\\tconst xs = Math.floor(width / sampledWidth);\\n\\t\\tconst ys = Math.floor(height / sampledHeight);\\n\\t\\tconst xsys = xs * ys;\\n\\t\\tfor (let y = 0; y < sampledHeight; ++y) {\\n\\t\\t\\tfor (let x = 0; x < sampledWidth; ++x) {\\n\\t\\t\\t\\tfor (let e = 0; e < 4; ++e) {\\n\\t\\t\\t\\t\\tlet sum = 0;\\n\\t\\t\\t\\t\\tfor (let sy = 0; sy < ys; ++sy) {\\n\\t\\t\\t\\t\\t\\tfor (let sx = 0; sx < xs; ++sx) {\\n\\t\\t\\t\\t\\t\\t\\tsum += data[(x * xs + sx + (y * ys + sy) * width) * 4 + e];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tsampledData[(x + y * sampledWidth) * 4 + e] = sum / xsys;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn sampledData;\\n\\t};\\n\\tfor (let level = texture._levels.length; level < requiredMipLevels; ++level) {\\n\\t\\tconst width = Math.max(1, texture._width >> level - 1);\\n\\t\\tconst height = Math.max(1, texture._height >> level - 1);\\n\\t\\tif (texture._cubemap) {\\n\\t\\t\\tconst mips = [];\\n\\t\\t\\tfor (let face = 0; face < 6; ++face) {\\n\\t\\t\\t\\tmips.push(downsample(width, height, texture._levels[level - 1][face]));\\n\\t\\t\\t}\\n\\t\\t\\ttexture._levels.push(mips);\\n\\t\\t} else {\\n\\t\\t\\ttexture._levels.push(downsample(width, height, texture._levels[level - 1]));\\n\\t\\t}\\n\\t}\\n\\ttexture._levelsUpdated = texture._cubemap ? [[true, true, true, true, true, true]] : [true];\\n};\\nclass TextureHandler extends ResourceHandler {\\n\\tconstructor(app) {\\n\\t\\tsuper(app, \\\"texture\\\");\\n\\t\\tconst assets = app.assets;\\n\\t\\tconst device = app.graphicsDevice;\\n\\t\\tthis._device = device;\\n\\t\\tthis._assets = assets;\\n\\t\\tthis.imgParser = new ImgParser(assets, device);\\n\\t\\tthis.parsers = {\\n\\t\\t\\tdds: new DdsParser(assets),\\n\\t\\t\\tktx: new KtxParser(assets),\\n\\t\\t\\tktx2: new Ktx2Parser(assets, device),\\n\\t\\t\\tbasis: new BasisParser(assets, device),\\n\\t\\t\\thdr: new HdrParser(assets)\\n\\t\\t};\\n\\t}\\n\\tset crossOrigin(value) {\\n\\t\\tthis.imgParser.crossOrigin = value;\\n\\t}\\n\\tget crossOrigin() {\\n\\t\\treturn this.imgParser.crossOrigin;\\n\\t}\\n\\tset maxRetries(value) {\\n\\t\\tthis.imgParser.maxRetries = value;\\n\\t\\tfor (const parser in this.parsers) {\\n\\t\\t\\tif (this.parsers.hasOwnProperty(parser)) {\\n\\t\\t\\t\\tthis.parsers[parser].maxRetries = value;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget maxRetries() {\\n\\t\\treturn this.imgParser.maxRetries;\\n\\t}\\n\\t_getUrlWithoutParams(url) {\\n\\t\\treturn url.indexOf(\\\"?\\\") >= 0 ? url.split(\\\"?\\\")[0] : url;\\n\\t}\\n\\t_getParser(url) {\\n\\t\\tconst ext = path.getExtension(this._getUrlWithoutParams(url)).toLowerCase().replace(\\\".\\\", \\\"\\\");\\n\\t\\treturn this.parsers[ext] || this.imgParser;\\n\\t}\\n\\t_getTextureOptions(asset) {\\n\\t\\tconst options = {};\\n\\t\\tif (asset) {\\n\\t\\t\\tif (asset.name?.length > 0) {\\n\\t\\t\\t\\toptions.name = asset.name;\\n\\t\\t\\t}\\n\\t\\t\\tconst assetData = asset.data;\\n\\t\\t\\tif (assetData.hasOwnProperty(\\\"minfilter\\\")) {\\n\\t\\t\\t\\toptions.minFilter = JSON_FILTER_MODE[assetData.minfilter];\\n\\t\\t\\t}\\n\\t\\t\\tif (assetData.hasOwnProperty(\\\"magfilter\\\")) {\\n\\t\\t\\t\\toptions.magFilter = JSON_FILTER_MODE[assetData.magfilter];\\n\\t\\t\\t}\\n\\t\\t\\tif (assetData.hasOwnProperty(\\\"addressu\\\")) {\\n\\t\\t\\t\\toptions.addressU = JSON_ADDRESS_MODE[assetData.addressu];\\n\\t\\t\\t}\\n\\t\\t\\tif (assetData.hasOwnProperty(\\\"addressv\\\")) {\\n\\t\\t\\t\\toptions.addressV = JSON_ADDRESS_MODE[assetData.addressv];\\n\\t\\t\\t}\\n\\t\\t\\tif (assetData.hasOwnProperty(\\\"mipmaps\\\")) {\\n\\t\\t\\t\\toptions.mipmaps = assetData.mipmaps;\\n\\t\\t\\t}\\n\\t\\t\\tif (assetData.hasOwnProperty(\\\"anisotropy\\\")) {\\n\\t\\t\\t\\toptions.anisotropy = assetData.anisotropy;\\n\\t\\t\\t}\\n\\t\\t\\tif (assetData.hasOwnProperty(\\\"flipY\\\")) {\\n\\t\\t\\t\\toptions.flipY = !!assetData.flipY;\\n\\t\\t\\t}\\n\\t\\t\\tif (assetData.hasOwnProperty(\\\"srgb\\\")) {\\n\\t\\t\\t\\toptions.srgb = !!assetData.srgb;\\n\\t\\t\\t}\\n\\t\\t\\toptions.type = TEXTURETYPE_DEFAULT;\\n\\t\\t\\tif (assetData.hasOwnProperty(\\\"type\\\")) {\\n\\t\\t\\t\\toptions.type = JSON_TEXTURE_TYPE[assetData.type];\\n\\t\\t\\t} else if (assetData.hasOwnProperty(\\\"rgbm\\\") && assetData.rgbm) {\\n\\t\\t\\t\\toptions.type = TEXTURETYPE_RGBM;\\n\\t\\t\\t} else if (asset.file && (asset.file.opt & 8) !== 0) {\\n\\t\\t\\t\\toptions.type = TEXTURETYPE_SWIZZLEGGGR;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn options;\\n\\t}\\n\\tload(url, callback, asset) {\\n\\t\\tif (typeof url === \\\"string\\\") {\\n\\t\\t\\turl = {\\n\\t\\t\\t\\tload: url,\\n\\t\\t\\t\\toriginal: url\\n\\t\\t\\t};\\n\\t\\t}\\n\\t\\tthis._getParser(url.original).load(url, callback, asset);\\n\\t}\\n\\topen(url, data, asset) {\\n\\t\\tif (!url) {\\n\\t\\t\\treturn void 0;\\n\\t\\t}\\n\\t\\tconst textureOptions = this._getTextureOptions(asset);\\n\\t\\tlet texture = this._getParser(url).open(url, data, this._device, textureOptions);\\n\\t\\tif (texture === null) {\\n\\t\\t\\ttexture = new Texture(this._device, {\\n\\t\\t\\t\\twidth: 4,\\n\\t\\t\\t\\theight: 4,\\n\\t\\t\\t\\tformat: PIXELFORMAT_RGB8\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\t_completePartialMipmapChain(texture);\\n\\t\\t\\tif (data.unswizzledGGGR) {\\n\\t\\t\\t\\tasset.file.variants.basis.opt &= -9;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn texture;\\n\\t}\\n\\tpatch(asset, assets) {\\n\\t\\tconst texture = asset.resource;\\n\\t\\tif (!texture) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst options = this._getTextureOptions(asset);\\n\\t\\tfor (const key of Object.keys(options)) {\\n\\t\\t\\ttexture[key] = options[key];\\n\\t\\t}\\n\\t}\\n}\\n\\nconst XRTYPE_INLINE = \\\"inline\\\";\\nconst XRTYPE_VR = \\\"immersive-vr\\\";\\nconst XRTYPE_AR = \\\"immersive-ar\\\";\\nconst XRSPACE_VIEWER = \\\"viewer\\\";\\nconst XRHAND_LEFT = \\\"left\\\";\\nconst XRDEPTHSENSINGUSAGE_CPU = \\\"cpu-optimized\\\";\\nconst XRDEPTHSENSINGUSAGE_GPU = \\\"gpu-optimized\\\";\\nconst XRDEPTHSENSINGFORMAT_L8A8 = \\\"luminance-alpha\\\";\\nconst XRDEPTHSENSINGFORMAT_R16U = \\\"unsigned-short\\\";\\nconst XRDEPTHSENSINGFORMAT_F32 = \\\"float32\\\";\\n\\nclass XrDomOverlay {\\n\\t_manager;\\n\\t_supported = platform.browser && !!window.XRDOMOverlayState;\\n\\t_root = null;\\n\\tconstructor(manager) {\\n\\t\\tthis._manager = manager;\\n\\t}\\n\\tget supported() {\\n\\t\\treturn this._supported;\\n\\t}\\n\\tget available() {\\n\\t\\treturn this._supported && this._manager.active && this._manager._session.domOverlayState !== null;\\n\\t}\\n\\tget state() {\\n\\t\\tif (!this._supported || !this._manager.active || !this._manager._session.domOverlayState) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\treturn this._manager._session.domOverlayState.type;\\n\\t}\\n\\tset root(value) {\\n\\t\\tif (!this._supported || this._manager.active) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._root = value;\\n\\t}\\n\\tget root() {\\n\\t\\treturn this._root;\\n\\t}\\n}\\n\\nconst poolVec3 = [];\\nconst poolQuat = [];\\nclass XrHitTestSource extends EventHandler {\\n\\tstatic EVENT_REMOVE = \\\"remove\\\";\\n\\tstatic EVENT_RESULT = \\\"result\\\";\\n\\tmanager;\\n\\t_xrHitTestSource;\\n\\t_transient;\\n\\t_inputSource;\\n\\tconstructor(manager, xrHitTestSource, transient, inputSource = null) {\\n\\t\\tsuper();\\n\\t\\tthis.manager = manager;\\n\\t\\tthis._xrHitTestSource = xrHitTestSource;\\n\\t\\tthis._transient = transient;\\n\\t\\tthis._inputSource = inputSource;\\n\\t}\\n\\tremove() {\\n\\t\\tif (!this._xrHitTestSource) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst sources = this.manager.hitTest.sources;\\n\\t\\tconst ind = sources.indexOf(this);\\n\\t\\tif (ind !== -1) sources.splice(ind, 1);\\n\\t\\tthis.onStop();\\n\\t}\\n\\tonStop() {\\n\\t\\tthis._xrHitTestSource.cancel();\\n\\t\\tthis._xrHitTestSource = null;\\n\\t\\tthis.fire(\\\"remove\\\");\\n\\t\\tthis.manager.hitTest.fire(\\\"remove\\\", this);\\n\\t}\\n\\tupdate(frame) {\\n\\t\\tif (this._transient) {\\n\\t\\t\\tconst transientResults = frame.getHitTestResultsForTransientInput(this._xrHitTestSource);\\n\\t\\t\\tfor (let i = 0; i < transientResults.length; i++) {\\n\\t\\t\\t\\tconst transientResult = transientResults[i];\\n\\t\\t\\t\\tif (!transientResult.results.length) {\\n\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet inputSource;\\n\\t\\t\\t\\tif (transientResult.inputSource) {\\n\\t\\t\\t\\t\\tinputSource = this.manager.input._getByInputSource(transientResult.inputSource);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.updateHitResults(transientResult.results, inputSource);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tconst results = frame.getHitTestResults(this._xrHitTestSource);\\n\\t\\t\\tif (!results.length) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tthis.updateHitResults(results);\\n\\t\\t}\\n\\t}\\n\\tupdateHitResults(results, inputSource) {\\n\\t\\tif (this._inputSource && this._inputSource !== inputSource) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst origin = poolVec3.pop() ?? new Vec3();\\n\\t\\tif (inputSource) {\\n\\t\\t\\torigin.copy(inputSource.getOrigin());\\n\\t\\t} else {\\n\\t\\t\\torigin.copy(this.manager.camera.getPosition());\\n\\t\\t}\\n\\t\\tlet candidateDistance = Infinity;\\n\\t\\tlet candidateHitTestResult = null;\\n\\t\\tconst position = poolVec3.pop() ?? new Vec3();\\n\\t\\tconst rotation = poolQuat.pop() ?? new Quat();\\n\\t\\tfor (let i = 0; i < results.length; i++) {\\n\\t\\t\\tconst pose = results[i].getPose(this.manager._referenceSpace);\\n\\t\\t\\tconst distance = origin.distance(pose.transform.position);\\n\\t\\t\\tif (distance >= candidateDistance) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tcandidateDistance = distance;\\n\\t\\t\\tcandidateHitTestResult = results[i];\\n\\t\\t\\tposition.copy(pose.transform.position);\\n\\t\\t\\trotation.copy(pose.transform.orientation);\\n\\t\\t}\\n\\t\\tthis.fire(\\\"result\\\", position, rotation, inputSource || this._inputSource, candidateHitTestResult);\\n\\t\\tthis.manager.hitTest.fire(\\\"result\\\", this, position, rotation, inputSource || this._inputSource, candidateHitTestResult);\\n\\t\\tpoolVec3.push(origin);\\n\\t\\tpoolVec3.push(position);\\n\\t\\tpoolQuat.push(rotation);\\n\\t}\\n}\\n\\nclass XrHitTest extends EventHandler {\\n\\tstatic EVENT_AVAILABLE = \\\"available\\\";\\n\\tstatic EVENT_UNAVAILABLE = \\\"unavailable\\\";\\n\\tstatic EVENT_ADD = \\\"add\\\";\\n\\tstatic EVENT_REMOVE = \\\"remove\\\";\\n\\tstatic EVENT_RESULT = \\\"result\\\";\\n\\tstatic EVENT_ERROR = \\\"error\\\";\\n\\tmanager;\\n\\t_supported = platform.browser && !!(window.XRSession && window.XRSession.prototype.requestHitTestSource);\\n\\t_available = false;\\n\\t_checkingAvailability = false;\\n\\tsources = [];\\n\\tconstructor(manager) {\\n\\t\\tsuper();\\n\\t\\tthis.manager = manager;\\n\\t\\tif (this._supported) {\\n\\t\\t\\tthis.manager.on(\\\"start\\\", this._onSessionStart, this);\\n\\t\\t\\tthis.manager.on(\\\"end\\\", this._onSessionEnd, this);\\n\\t\\t}\\n\\t}\\n\\t_onSessionStart() {\\n\\t\\tif (this.manager.session.enabledFeatures) {\\n\\t\\t\\tconst available = this.manager.session.enabledFeatures.indexOf(\\\"hit-test\\\") !== -1;\\n\\t\\t\\tif (!available) return;\\n\\t\\t\\tthis._available = available;\\n\\t\\t\\tthis.fire(\\\"available\\\");\\n\\t\\t} else if (!this._checkingAvailability) {\\n\\t\\t\\tthis._checkingAvailability = true;\\n\\t\\t\\tthis.manager.session.requestReferenceSpace(XRSPACE_VIEWER).then((referenceSpace) => {\\n\\t\\t\\t\\tthis.manager.session.requestHitTestSource({\\n\\t\\t\\t\\t\\tspace: referenceSpace\\n\\t\\t\\t\\t}).then((hitTestSource) => {\\n\\t\\t\\t\\t\\thitTestSource.cancel();\\n\\t\\t\\t\\t\\tif (this.manager.active) {\\n\\t\\t\\t\\t\\t\\tthis._available = true;\\n\\t\\t\\t\\t\\t\\tthis.fire(\\\"available\\\");\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}).catch(() => {\\n\\t\\t\\t\\t});\\n\\t\\t\\t}).catch(() => {\\n\\t\\t\\t});\\n\\t\\t}\\n\\t}\\n\\t_onSessionEnd() {\\n\\t\\tif (!this._available) return;\\n\\t\\tthis._available = false;\\n\\t\\tfor (let i = 0; i < this.sources.length; i++) {\\n\\t\\t\\tthis.sources[i].onStop();\\n\\t\\t}\\n\\t\\tthis.sources = [];\\n\\t\\tthis.fire(\\\"unavailable\\\");\\n\\t}\\n\\tstart(options = {}) {\\n\\t\\tif (!this._supported) {\\n\\t\\t\\toptions.callback?.(new Error(\\\"XR HitTest is not supported\\\"), null);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!this._available) {\\n\\t\\t\\toptions.callback?.(new Error(\\\"XR HitTest is not available\\\"), null);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!options.profile && !options.spaceType) {\\n\\t\\t\\toptions.spaceType = XRSPACE_VIEWER;\\n\\t\\t}\\n\\t\\tlet xrRay;\\n\\t\\tconst offsetRay = options.offsetRay;\\n\\t\\tif (offsetRay) {\\n\\t\\t\\tconst origin = new DOMPoint(offsetRay.origin.x, offsetRay.origin.y, offsetRay.origin.z, 1);\\n\\t\\t\\tconst direction = new DOMPoint(offsetRay.direction.x, offsetRay.direction.y, offsetRay.direction.z, 0);\\n\\t\\t\\txrRay = new XRRay(origin, direction);\\n\\t\\t}\\n\\t\\tconst callback = options.callback;\\n\\t\\tif (options.spaceType) {\\n\\t\\t\\tthis.manager.session.requestReferenceSpace(options.spaceType).then((referenceSpace) => {\\n\\t\\t\\t\\tif (!this.manager.session) {\\n\\t\\t\\t\\t\\tconst err = new Error(\\\"XR Session is not started (2)\\\");\\n\\t\\t\\t\\t\\tif (callback) callback(err);\\n\\t\\t\\t\\t\\tthis.fire(\\\"error\\\", err);\\n\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.manager.session.requestHitTestSource({\\n\\t\\t\\t\\t\\tspace: referenceSpace,\\n\\t\\t\\t\\t\\tentityTypes: options.entityTypes || void 0,\\n\\t\\t\\t\\t\\toffsetRay: xrRay\\n\\t\\t\\t\\t}).then((xrHitTestSource) => {\\n\\t\\t\\t\\t\\tthis._onHitTestSource(xrHitTestSource, false, options.inputSource, callback);\\n\\t\\t\\t\\t}).catch((ex) => {\\n\\t\\t\\t\\t\\tif (callback) callback(ex);\\n\\t\\t\\t\\t\\tthis.fire(\\\"error\\\", ex);\\n\\t\\t\\t\\t});\\n\\t\\t\\t}).catch((ex) => {\\n\\t\\t\\t\\tif (callback) callback(ex);\\n\\t\\t\\t\\tthis.fire(\\\"error\\\", ex);\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\tthis.manager.session.requestHitTestSourceForTransientInput({\\n\\t\\t\\t\\tprofile: options.profile,\\n\\t\\t\\t\\tentityTypes: options.entityTypes || void 0,\\n\\t\\t\\t\\toffsetRay: xrRay\\n\\t\\t\\t}).then((xrHitTestSource) => {\\n\\t\\t\\t\\tthis._onHitTestSource(xrHitTestSource, true, options.inputSource, callback);\\n\\t\\t\\t}).catch((ex) => {\\n\\t\\t\\t\\tif (callback) callback(ex);\\n\\t\\t\\t\\tthis.fire(\\\"error\\\", ex);\\n\\t\\t\\t});\\n\\t\\t}\\n\\t}\\n\\t_onHitTestSource(xrHitTestSource, transient, inputSource, callback) {\\n\\t\\tif (!this.manager.session) {\\n\\t\\t\\txrHitTestSource.cancel();\\n\\t\\t\\tconst err = new Error(\\\"XR Session is not started (3)\\\");\\n\\t\\t\\tif (callback) callback(err);\\n\\t\\t\\tthis.fire(\\\"error\\\", err);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst hitTestSource = new XrHitTestSource(this.manager, xrHitTestSource, transient, inputSource ?? null);\\n\\t\\tthis.sources.push(hitTestSource);\\n\\t\\tif (callback) callback(null, hitTestSource);\\n\\t\\tthis.fire(\\\"add\\\", hitTestSource);\\n\\t}\\n\\tupdate(frame) {\\n\\t\\tif (!this._available) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < this.sources.length; i++) {\\n\\t\\t\\tthis.sources[i].update(frame);\\n\\t\\t}\\n\\t}\\n\\tget supported() {\\n\\t\\treturn this._supported;\\n\\t}\\n\\tget available() {\\n\\t\\treturn this._available;\\n\\t}\\n}\\n\\nclass XrTrackedImage extends EventHandler {\\n\\tstatic EVENT_TRACKED = \\\"tracked\\\";\\n\\tstatic EVENT_UNTRACKED = \\\"untracked\\\";\\n\\t_image;\\n\\t_width;\\n\\t_bitmap = null;\\n\\t_measuredWidth = 0;\\n\\t_trackable = false;\\n\\t_tracking = false;\\n\\t_emulated = false;\\n\\t_pose = null;\\n\\t_position = new Vec3();\\n\\t_rotation = new Quat();\\n\\tconstructor(image, width) {\\n\\t\\tsuper();\\n\\t\\tthis._image = image;\\n\\t\\tthis._width = width;\\n\\t}\\n\\tget image() {\\n\\t\\treturn this._image;\\n\\t}\\n\\tset width(value) {\\n\\t\\tthis._width = value;\\n\\t}\\n\\tget width() {\\n\\t\\treturn this._width;\\n\\t}\\n\\tget trackable() {\\n\\t\\treturn this._trackable;\\n\\t}\\n\\tget tracking() {\\n\\t\\treturn this._tracking;\\n\\t}\\n\\tget emulated() {\\n\\t\\treturn this._emulated;\\n\\t}\\n\\tprepare() {\\n\\t\\tif (this._bitmap) {\\n\\t\\t\\treturn {\\n\\t\\t\\t\\timage: this._bitmap,\\n\\t\\t\\t\\twidthInMeters: this._width\\n\\t\\t\\t};\\n\\t\\t}\\n\\t\\treturn createImageBitmap(this._image).then((bitmap) => {\\n\\t\\t\\tthis._bitmap = bitmap;\\n\\t\\t\\treturn {\\n\\t\\t\\t\\timage: this._bitmap,\\n\\t\\t\\t\\twidthInMeters: this._width\\n\\t\\t\\t};\\n\\t\\t});\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._image = null;\\n\\t\\tthis._pose = null;\\n\\t\\tif (this._bitmap) {\\n\\t\\t\\tthis._bitmap.close();\\n\\t\\t\\tthis._bitmap = null;\\n\\t\\t}\\n\\t}\\n\\tgetPosition() {\\n\\t\\tif (this._pose) this._position.copy(this._pose.transform.position);\\n\\t\\treturn this._position;\\n\\t}\\n\\tgetRotation() {\\n\\t\\tif (this._pose) this._rotation.copy(this._pose.transform.orientation);\\n\\t\\treturn this._rotation;\\n\\t}\\n}\\n\\nclass XrImageTracking extends EventHandler {\\n\\tstatic EVENT_ERROR = \\\"error\\\";\\n\\t_manager;\\n\\t_supported = platform.browser && !!window.XRImageTrackingResult;\\n\\t_available = false;\\n\\t_images = [];\\n\\tconstructor(manager) {\\n\\t\\tsuper();\\n\\t\\tthis._manager = manager;\\n\\t\\tif (this._supported) {\\n\\t\\t\\tthis._manager.on(\\\"start\\\", this._onSessionStart, this);\\n\\t\\t\\tthis._manager.on(\\\"end\\\", this._onSessionEnd, this);\\n\\t\\t}\\n\\t}\\n\\tadd(image, width) {\\n\\t\\tif (!this._supported || this._manager.active) return null;\\n\\t\\tconst trackedImage = new XrTrackedImage(image, width);\\n\\t\\tthis._images.push(trackedImage);\\n\\t\\treturn trackedImage;\\n\\t}\\n\\tremove(trackedImage) {\\n\\t\\tif (this._manager.active) return;\\n\\t\\tconst ind = this._images.indexOf(trackedImage);\\n\\t\\tif (ind !== -1) {\\n\\t\\t\\ttrackedImage.destroy();\\n\\t\\t\\tthis._images.splice(ind, 1);\\n\\t\\t}\\n\\t}\\n\\t_onSessionStart() {\\n\\t\\tthis._manager.session.getTrackedImageScores().then((images) => {\\n\\t\\t\\tthis._available = true;\\n\\t\\t\\tfor (let i = 0; i < images.length; i++) {\\n\\t\\t\\t\\tthis._images[i]._trackable = images[i] === \\\"trackable\\\";\\n\\t\\t\\t}\\n\\t\\t}).catch((err) => {\\n\\t\\t\\tthis._available = false;\\n\\t\\t\\tthis.fire(\\\"error\\\", err);\\n\\t\\t});\\n\\t}\\n\\t_onSessionEnd() {\\n\\t\\tthis._available = false;\\n\\t\\tfor (let i = 0; i < this._images.length; i++) {\\n\\t\\t\\tconst image = this._images[i];\\n\\t\\t\\timage._pose = null;\\n\\t\\t\\timage._measuredWidth = 0;\\n\\t\\t\\tif (image._tracking) {\\n\\t\\t\\t\\timage._tracking = false;\\n\\t\\t\\t\\timage.fire(\\\"untracked\\\");\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tprepareImages(callback) {\\n\\t\\tif (this._images.length) {\\n\\t\\t\\tPromise.all(this._images.map((trackedImage) => {\\n\\t\\t\\t\\treturn trackedImage.prepare();\\n\\t\\t\\t})).then((bitmaps) => {\\n\\t\\t\\t\\tcallback(null, bitmaps);\\n\\t\\t\\t}).catch((err) => {\\n\\t\\t\\t\\tcallback(err, null);\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\tcallback(null, null);\\n\\t\\t}\\n\\t}\\n\\tupdate(frame) {\\n\\t\\tif (!this._available) return;\\n\\t\\tconst results = frame.getImageTrackingResults();\\n\\t\\tconst index = {};\\n\\t\\tfor (let i = 0; i < results.length; i++) {\\n\\t\\t\\tindex[results[i].index] = results[i];\\n\\t\\t\\tconst trackedImage = this._images[results[i].index];\\n\\t\\t\\ttrackedImage._emulated = results[i].trackingState === \\\"emulated\\\";\\n\\t\\t\\ttrackedImage._measuredWidth = results[i].measuredWidthInMeters;\\n\\t\\t\\ttrackedImage._pose = frame.getPose(results[i].imageSpace, this._manager._referenceSpace);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < this._images.length; i++) {\\n\\t\\t\\tif (this._images[i]._tracking && !index[i]) {\\n\\t\\t\\t\\tthis._images[i]._tracking = false;\\n\\t\\t\\t\\tthis._images[i].fire(\\\"untracked\\\");\\n\\t\\t\\t} else if (!this._images[i]._tracking && index[i]) {\\n\\t\\t\\t\\tthis._images[i]._tracking = true;\\n\\t\\t\\t\\tthis._images[i].fire(\\\"tracked\\\");\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget supported() {\\n\\t\\treturn this._supported;\\n\\t}\\n\\tget available() {\\n\\t\\treturn this._available;\\n\\t}\\n\\tget images() {\\n\\t\\treturn this._images;\\n\\t}\\n}\\n\\nclass XrFinger {\\n\\t_index;\\n\\t_hand;\\n\\t_joints = [];\\n\\t_tip = null;\\n\\tconstructor(index, hand) {\\n\\t\\tthis._index = index;\\n\\t\\tthis._hand = hand;\\n\\t\\tthis._hand._fingers.push(this);\\n\\t}\\n\\tget index() {\\n\\t\\treturn this._index;\\n\\t}\\n\\tget hand() {\\n\\t\\treturn this._hand;\\n\\t}\\n\\tget joints() {\\n\\t\\treturn this._joints;\\n\\t}\\n\\tget tip() {\\n\\t\\treturn this._tip;\\n\\t}\\n}\\n\\nconst tipJointIds = platform.browser && window.XRHand ? [\\n\\t\\\"thumb-tip\\\",\\n\\t\\\"index-finger-tip\\\",\\n\\t\\\"middle-finger-tip\\\",\\n\\t\\\"ring-finger-tip\\\",\\n\\t\\\"pinky-finger-tip\\\"\\n] : [];\\nconst tipJointIdsIndex = {};\\nfor (let i = 0; i < tipJointIds.length; i++) {\\n\\ttipJointIdsIndex[tipJointIds[i]] = true;\\n}\\nclass XrJoint {\\n\\t_index;\\n\\t_id;\\n\\t_hand;\\n\\t_finger;\\n\\t_wrist;\\n\\t_tip;\\n\\t_radius = null;\\n\\t_localTransform = new Mat4();\\n\\t_worldTransform = new Mat4();\\n\\t_localPosition = new Vec3();\\n\\t_localRotation = new Quat();\\n\\t_position = new Vec3();\\n\\t_rotation = new Quat();\\n\\t_dirtyLocal = true;\\n\\tconstructor(index, id, hand, finger = null) {\\n\\t\\tthis._index = index;\\n\\t\\tthis._id = id;\\n\\t\\tthis._hand = hand;\\n\\t\\tthis._finger = finger;\\n\\t\\tthis._wrist = id === \\\"wrist\\\";\\n\\t\\tthis._tip = this._finger && !!tipJointIdsIndex[id];\\n\\t}\\n\\tupdate(pose) {\\n\\t\\tthis._dirtyLocal = true;\\n\\t\\tthis._radius = pose.radius;\\n\\t\\tthis._localPosition.copy(pose.transform.position);\\n\\t\\tthis._localRotation.copy(pose.transform.orientation);\\n\\t}\\n\\t_updateTransforms() {\\n\\t\\tif (this._dirtyLocal) {\\n\\t\\t\\tthis._dirtyLocal = false;\\n\\t\\t\\tthis._localTransform.setTRS(this._localPosition, this._localRotation, Vec3.ONE);\\n\\t\\t}\\n\\t\\tconst manager = this._hand._manager;\\n\\t\\tconst parent = manager.camera.parent;\\n\\t\\tif (parent) {\\n\\t\\t\\tthis._worldTransform.mul2(parent.getWorldTransform(), this._localTransform);\\n\\t\\t} else {\\n\\t\\t\\tthis._worldTransform.copy(this._localTransform);\\n\\t\\t}\\n\\t}\\n\\tgetPosition() {\\n\\t\\tthis._updateTransforms();\\n\\t\\tthis._worldTransform.getTranslation(this._position);\\n\\t\\treturn this._position;\\n\\t}\\n\\tgetRotation() {\\n\\t\\tthis._updateTransforms();\\n\\t\\tthis._rotation.setFromMat4(this._worldTransform);\\n\\t\\treturn this._rotation;\\n\\t}\\n\\tget id() {\\n\\t\\treturn this._id;\\n\\t}\\n\\tget index() {\\n\\t\\treturn this._index;\\n\\t}\\n\\tget hand() {\\n\\t\\treturn this._hand;\\n\\t}\\n\\tget finger() {\\n\\t\\treturn this._finger;\\n\\t}\\n\\tget wrist() {\\n\\t\\treturn this._wrist;\\n\\t}\\n\\tget tip() {\\n\\t\\treturn this._tip;\\n\\t}\\n\\tget radius() {\\n\\t\\treturn this._radius || 5e-3;\\n\\t}\\n}\\n\\nlet fingerJointIds = [];\\nconst vecA = new Vec3();\\nconst vecB = new Vec3();\\nconst vecC = new Vec3();\\nif (platform.browser && window.XRHand) {\\n\\tfingerJointIds = [\\n\\t\\t[\\\"thumb-metacarpal\\\", \\\"thumb-phalanx-proximal\\\", \\\"thumb-phalanx-distal\\\", \\\"thumb-tip\\\"],\\n\\t\\t[\\\"index-finger-metacarpal\\\", \\\"index-finger-phalanx-proximal\\\", \\\"index-finger-phalanx-intermediate\\\", \\\"index-finger-phalanx-distal\\\", \\\"index-finger-tip\\\"],\\n\\t\\t[\\\"middle-finger-metacarpal\\\", \\\"middle-finger-phalanx-proximal\\\", \\\"middle-finger-phalanx-intermediate\\\", \\\"middle-finger-phalanx-distal\\\", \\\"middle-finger-tip\\\"],\\n\\t\\t[\\\"ring-finger-metacarpal\\\", \\\"ring-finger-phalanx-proximal\\\", \\\"ring-finger-phalanx-intermediate\\\", \\\"ring-finger-phalanx-distal\\\", \\\"ring-finger-tip\\\"],\\n\\t\\t[\\\"pinky-finger-metacarpal\\\", \\\"pinky-finger-phalanx-proximal\\\", \\\"pinky-finger-phalanx-intermediate\\\", \\\"pinky-finger-phalanx-distal\\\", \\\"pinky-finger-tip\\\"]\\n\\t];\\n}\\nclass XrHand extends EventHandler {\\n\\tstatic EVENT_TRACKING = \\\"tracking\\\";\\n\\tstatic EVENT_TRACKINGLOST = \\\"trackinglost\\\";\\n\\t_manager;\\n\\t_inputSource;\\n\\t_tracking = false;\\n\\t_fingers = [];\\n\\t_joints = [];\\n\\t_jointsById = {};\\n\\t_tips = [];\\n\\t_wrist = null;\\n\\tconstructor(inputSource) {\\n\\t\\tsuper();\\n\\t\\tconst xrHand = inputSource._xrInputSource.hand;\\n\\t\\tthis._manager = inputSource._manager;\\n\\t\\tthis._inputSource = inputSource;\\n\\t\\tif (xrHand.get(\\\"wrist\\\")) {\\n\\t\\t\\tconst joint = new XrJoint(0, \\\"wrist\\\", this, null);\\n\\t\\t\\tthis._wrist = joint;\\n\\t\\t\\tthis._joints.push(joint);\\n\\t\\t\\tthis._jointsById.wrist = joint;\\n\\t\\t}\\n\\t\\tfor (let f = 0; f < fingerJointIds.length; f++) {\\n\\t\\t\\tconst finger = new XrFinger(f, this);\\n\\t\\t\\tfor (let j = 0; j < fingerJointIds[f].length; j++) {\\n\\t\\t\\t\\tconst jointId = fingerJointIds[f][j];\\n\\t\\t\\t\\tif (!xrHand.get(jointId)) continue;\\n\\t\\t\\t\\tconst joint = new XrJoint(j, jointId, this, finger);\\n\\t\\t\\t\\tthis._joints.push(joint);\\n\\t\\t\\t\\tthis._jointsById[jointId] = joint;\\n\\t\\t\\t\\tif (joint.tip) {\\n\\t\\t\\t\\t\\tthis._tips.push(joint);\\n\\t\\t\\t\\t\\tfinger._tip = joint;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfinger._joints.push(joint);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tupdate(frame) {\\n\\t\\tconst xrInputSource = this._inputSource._xrInputSource;\\n\\t\\tfor (let j = 0; j < this._joints.length; j++) {\\n\\t\\t\\tconst joint = this._joints[j];\\n\\t\\t\\tconst jointSpace = xrInputSource.hand.get(joint._id);\\n\\t\\t\\tif (jointSpace) {\\n\\t\\t\\t\\tlet pose;\\n\\t\\t\\t\\tif (frame.session.visibilityState !== \\\"hidden\\\") {\\n\\t\\t\\t\\t\\tpose = frame.getJointPose(jointSpace, this._manager._referenceSpace);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (pose) {\\n\\t\\t\\t\\t\\tjoint.update(pose);\\n\\t\\t\\t\\t\\tif (joint.wrist && !this._tracking) {\\n\\t\\t\\t\\t\\t\\tthis._tracking = true;\\n\\t\\t\\t\\t\\t\\tthis.fire(\\\"tracking\\\");\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else if (joint.wrist) {\\n\\t\\t\\t\\t\\tif (this._tracking) {\\n\\t\\t\\t\\t\\t\\tthis._tracking = false;\\n\\t\\t\\t\\t\\t\\tthis.fire(\\\"trackinglost\\\");\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst j1 = this._jointsById[\\\"thumb-metacarpal\\\"];\\n\\t\\tconst j4 = this._jointsById[\\\"thumb-tip\\\"];\\n\\t\\tconst j6 = this._jointsById[\\\"index-finger-phalanx-proximal\\\"];\\n\\t\\tconst j9 = this._jointsById[\\\"index-finger-tip\\\"];\\n\\t\\tconst j16 = this._jointsById[\\\"ring-finger-phalanx-proximal\\\"];\\n\\t\\tconst j21 = this._jointsById[\\\"pinky-finger-phalanx-proximal\\\"];\\n\\t\\tif (j1 && j4 && j6 && j9 && j16 && j21) {\\n\\t\\t\\tthis._inputSource._dirtyRay = true;\\n\\t\\t\\tthis._inputSource._rayLocal.origin.lerp(j4._localPosition, j9._localPosition, 0.5);\\n\\t\\t\\tlet jointL = j1;\\n\\t\\t\\tlet jointR = j21;\\n\\t\\t\\tif (this._inputSource.handedness === XRHAND_LEFT) {\\n\\t\\t\\t\\tconst t = jointL;\\n\\t\\t\\t\\tjointL = jointR;\\n\\t\\t\\t\\tjointR = t;\\n\\t\\t\\t}\\n\\t\\t\\tvecA.sub2(jointL._localPosition, this._wrist._localPosition);\\n\\t\\t\\tvecB.sub2(jointR._localPosition, this._wrist._localPosition);\\n\\t\\t\\tvecC.cross(vecA, vecB).normalize();\\n\\t\\t\\tvecA.lerp(j6._localPosition, j16._localPosition, 0.5);\\n\\t\\t\\tvecA.sub(this._wrist._localPosition).normalize();\\n\\t\\t\\tthis._inputSource._rayLocal.direction.lerp(vecC, vecA, 0.5).normalize();\\n\\t\\t}\\n\\t\\tconst squeezing = this._fingerIsClosed(1) && this._fingerIsClosed(2) && this._fingerIsClosed(3) && this._fingerIsClosed(4);\\n\\t\\tif (squeezing) {\\n\\t\\t\\tif (!this._inputSource._squeezing) {\\n\\t\\t\\t\\tthis._inputSource._squeezing = true;\\n\\t\\t\\t\\tthis._inputSource.fire(\\\"squeezestart\\\");\\n\\t\\t\\t\\tthis._manager.input.fire(\\\"squeezestart\\\", this._inputSource);\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tif (this._inputSource._squeezing) {\\n\\t\\t\\t\\tthis._inputSource._squeezing = false;\\n\\t\\t\\t\\tthis._inputSource.fire(\\\"squeeze\\\");\\n\\t\\t\\t\\tthis._manager.input.fire(\\\"squeeze\\\", this._inputSource);\\n\\t\\t\\t\\tthis._inputSource.fire(\\\"squeezeend\\\");\\n\\t\\t\\t\\tthis._manager.input.fire(\\\"squeezeend\\\", this._inputSource);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_fingerIsClosed(index) {\\n\\t\\tconst finger = this._fingers[index];\\n\\t\\tvecA.sub2(finger.joints[0]._localPosition, finger.joints[1]._localPosition).normalize();\\n\\t\\tvecB.sub2(finger.joints[2]._localPosition, finger.joints[3]._localPosition).normalize();\\n\\t\\treturn vecA.dot(vecB) < -0.8;\\n\\t}\\n\\tgetJointById(id) {\\n\\t\\treturn this._jointsById[id] || null;\\n\\t}\\n\\tget fingers() {\\n\\t\\treturn this._fingers;\\n\\t}\\n\\tget joints() {\\n\\t\\treturn this._joints;\\n\\t}\\n\\tget tips() {\\n\\t\\treturn this._tips;\\n\\t}\\n\\tget wrist() {\\n\\t\\treturn this._wrist;\\n\\t}\\n\\tget tracking() {\\n\\t\\treturn this._tracking;\\n\\t}\\n}\\n\\nconst vec3A$1 = new Vec3();\\nconst quat = new Quat();\\nlet ids$1 = 0;\\nclass XrInputSource extends EventHandler {\\n\\tstatic EVENT_REMOVE = \\\"remove\\\";\\n\\tstatic EVENT_SELECT = \\\"select\\\";\\n\\tstatic EVENT_SELECTSTART = \\\"selectstart\\\";\\n\\tstatic EVENT_SELECTEND = \\\"selectend\\\";\\n\\tstatic EVENT_SQUEEZE = \\\"squeeze\\\";\\n\\tstatic EVENT_SQUEEZESTART = \\\"squeezestart\\\";\\n\\tstatic EVENT_SQUEEZEEND = \\\"squeezeend\\\";\\n\\tstatic EVENT_HITTESTADD = \\\"hittest:add\\\";\\n\\tstatic EVENT_HITTESTREMOVE = \\\"hittest:remove\\\";\\n\\tstatic EVENT_HITTESTRESULT = \\\"hittest:result\\\";\\n\\t_id;\\n\\t_manager;\\n\\t_xrInputSource;\\n\\t_ray = new Ray();\\n\\t_rayLocal = new Ray();\\n\\t_grip = false;\\n\\t_hand = null;\\n\\t_velocitiesAvailable = false;\\n\\t_velocitiesTimestamp = now();\\n\\t_localTransform = null;\\n\\t_worldTransform = null;\\n\\t_position = new Vec3();\\n\\t_rotation = new Quat();\\n\\t_localPosition = null;\\n\\t_localPositionLast = null;\\n\\t_localRotation = null;\\n\\t_linearVelocity = null;\\n\\t_dirtyLocal = true;\\n\\t_dirtyRay = false;\\n\\t_selecting = false;\\n\\t_squeezing = false;\\n\\t_elementInput = true;\\n\\t_elementEntity = null;\\n\\t_hitTestSources = [];\\n\\tconstructor(manager, xrInputSource) {\\n\\t\\tsuper();\\n\\t\\tthis._id = ++ids$1;\\n\\t\\tthis._manager = manager;\\n\\t\\tthis._xrInputSource = xrInputSource;\\n\\t\\tif (xrInputSource.hand) {\\n\\t\\t\\tthis._hand = new XrHand(this);\\n\\t\\t}\\n\\t}\\n\\tget id() {\\n\\t\\treturn this._id;\\n\\t}\\n\\tget inputSource() {\\n\\t\\treturn this._xrInputSource;\\n\\t}\\n\\tget targetRayMode() {\\n\\t\\treturn this._xrInputSource.targetRayMode;\\n\\t}\\n\\tget handedness() {\\n\\t\\treturn this._xrInputSource.handedness;\\n\\t}\\n\\tget profiles() {\\n\\t\\treturn this._xrInputSource.profiles;\\n\\t}\\n\\tget grip() {\\n\\t\\treturn this._grip;\\n\\t}\\n\\tget hand() {\\n\\t\\treturn this._hand;\\n\\t}\\n\\tget gamepad() {\\n\\t\\treturn this._xrInputSource.gamepad || null;\\n\\t}\\n\\tget selecting() {\\n\\t\\treturn this._selecting;\\n\\t}\\n\\tget squeezing() {\\n\\t\\treturn this._squeezing;\\n\\t}\\n\\tset elementInput(value) {\\n\\t\\tif (this._elementInput === value) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._elementInput = value;\\n\\t\\tif (!this._elementInput) {\\n\\t\\t\\tthis._elementEntity = null;\\n\\t\\t}\\n\\t}\\n\\tget elementInput() {\\n\\t\\treturn this._elementInput;\\n\\t}\\n\\tget elementEntity() {\\n\\t\\treturn this._elementEntity;\\n\\t}\\n\\tget hitTestSources() {\\n\\t\\treturn this._hitTestSources;\\n\\t}\\n\\tupdate(frame) {\\n\\t\\tif (this._hand) {\\n\\t\\t\\tthis._hand.update(frame);\\n\\t\\t} else {\\n\\t\\t\\tconst gripSpace = this._xrInputSource.gripSpace;\\n\\t\\t\\tif (gripSpace) {\\n\\t\\t\\t\\tconst gripPose = frame.getPose(gripSpace, this._manager._referenceSpace);\\n\\t\\t\\t\\tif (gripPose) {\\n\\t\\t\\t\\t\\tif (!this._grip) {\\n\\t\\t\\t\\t\\t\\tthis._grip = true;\\n\\t\\t\\t\\t\\t\\tthis._localTransform = new Mat4();\\n\\t\\t\\t\\t\\t\\tthis._worldTransform = new Mat4();\\n\\t\\t\\t\\t\\t\\tthis._localPositionLast = new Vec3();\\n\\t\\t\\t\\t\\t\\tthis._localPosition = new Vec3();\\n\\t\\t\\t\\t\\t\\tthis._localRotation = new Quat();\\n\\t\\t\\t\\t\\t\\tthis._linearVelocity = new Vec3();\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tconst timestamp = now();\\n\\t\\t\\t\\t\\tconst dt = (timestamp - this._velocitiesTimestamp) / 1e3;\\n\\t\\t\\t\\t\\tthis._velocitiesTimestamp = timestamp;\\n\\t\\t\\t\\t\\tthis._dirtyLocal = true;\\n\\t\\t\\t\\t\\tthis._localPositionLast.copy(this._localPosition);\\n\\t\\t\\t\\t\\tthis._localPosition.copy(gripPose.transform.position);\\n\\t\\t\\t\\t\\tthis._localRotation.copy(gripPose.transform.orientation);\\n\\t\\t\\t\\t\\tthis._velocitiesAvailable = true;\\n\\t\\t\\t\\t\\tif (this._manager.input.velocitiesSupported && gripPose.linearVelocity) {\\n\\t\\t\\t\\t\\t\\tthis._linearVelocity.copy(gripPose.linearVelocity);\\n\\t\\t\\t\\t\\t} else if (dt > 0) {\\n\\t\\t\\t\\t\\t\\tvec3A$1.sub2(this._localPosition, this._localPositionLast).divScalar(dt);\\n\\t\\t\\t\\t\\t\\tthis._linearVelocity.lerp(this._linearVelocity, vec3A$1, 0.15);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tthis._velocitiesAvailable = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tconst targetRayPose = frame.getPose(this._xrInputSource.targetRaySpace, this._manager._referenceSpace);\\n\\t\\t\\tif (targetRayPose) {\\n\\t\\t\\t\\tthis._dirtyRay = true;\\n\\t\\t\\t\\tthis._rayLocal.origin.copy(targetRayPose.transform.position);\\n\\t\\t\\t\\tthis._rayLocal.direction.set(0, 0, -1);\\n\\t\\t\\t\\tquat.copy(targetRayPose.transform.orientation);\\n\\t\\t\\t\\tquat.transformVector(this._rayLocal.direction, this._rayLocal.direction);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_updateTransforms() {\\n\\t\\tif (this._dirtyLocal) {\\n\\t\\t\\tthis._dirtyLocal = false;\\n\\t\\t\\tthis._localTransform.setTRS(this._localPosition, this._localRotation, Vec3.ONE);\\n\\t\\t}\\n\\t\\tconst parent = this._manager.camera.parent;\\n\\t\\tif (parent) {\\n\\t\\t\\tthis._worldTransform.mul2(parent.getWorldTransform(), this._localTransform);\\n\\t\\t} else {\\n\\t\\t\\tthis._worldTransform.copy(this._localTransform);\\n\\t\\t}\\n\\t}\\n\\t_updateRayTransforms() {\\n\\t\\tconst dirty = this._dirtyRay;\\n\\t\\tthis._dirtyRay = false;\\n\\t\\tconst parent = this._manager.camera.parent;\\n\\t\\tif (parent) {\\n\\t\\t\\tconst parentTransform = parent.getWorldTransform();\\n\\t\\t\\tparentTransform.getTranslation(this._position);\\n\\t\\t\\tthis._rotation.setFromMat4(parentTransform);\\n\\t\\t\\tthis._rotation.transformVector(this._rayLocal.origin, this._ray.origin);\\n\\t\\t\\tthis._ray.origin.add(this._position);\\n\\t\\t\\tthis._rotation.transformVector(this._rayLocal.direction, this._ray.direction);\\n\\t\\t} else if (dirty) {\\n\\t\\t\\tthis._ray.origin.copy(this._rayLocal.origin);\\n\\t\\t\\tthis._ray.direction.copy(this._rayLocal.direction);\\n\\t\\t}\\n\\t}\\n\\tgetPosition() {\\n\\t\\tif (!this._grip) return null;\\n\\t\\tthis._updateTransforms();\\n\\t\\tthis._worldTransform.getTranslation(this._position);\\n\\t\\treturn this._position;\\n\\t}\\n\\tgetLocalPosition() {\\n\\t\\treturn this._localPosition;\\n\\t}\\n\\tgetRotation() {\\n\\t\\tif (!this._grip) return null;\\n\\t\\tthis._updateTransforms();\\n\\t\\tthis._rotation.setFromMat4(this._worldTransform);\\n\\t\\treturn this._rotation;\\n\\t}\\n\\tgetLocalRotation() {\\n\\t\\treturn this._localRotation;\\n\\t}\\n\\tgetLinearVelocity() {\\n\\t\\tif (!this._velocitiesAvailable) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\treturn this._linearVelocity;\\n\\t}\\n\\tgetOrigin() {\\n\\t\\tthis._updateRayTransforms();\\n\\t\\treturn this._ray.origin;\\n\\t}\\n\\tgetDirection() {\\n\\t\\tthis._updateRayTransforms();\\n\\t\\treturn this._ray.direction;\\n\\t}\\n\\thitTestStart(options = {}) {\\n\\t\\toptions.inputSource = this;\\n\\t\\toptions.profile = this._xrInputSource.profiles[0];\\n\\t\\tconst callback = options.callback;\\n\\t\\toptions.callback = (err, hitTestSource) => {\\n\\t\\t\\tif (hitTestSource) this.onHitTestSourceAdd(hitTestSource);\\n\\t\\t\\tif (callback) callback(err, hitTestSource);\\n\\t\\t};\\n\\t\\tthis._manager.hitTest.start(options);\\n\\t}\\n\\tonHitTestSourceAdd(hitTestSource) {\\n\\t\\tthis._hitTestSources.push(hitTestSource);\\n\\t\\tthis.fire(\\\"hittest:add\\\", hitTestSource);\\n\\t\\thitTestSource.on(\\\"result\\\", (position, rotation, inputSource, hitTestResult) => {\\n\\t\\t\\tif (inputSource !== this) return;\\n\\t\\t\\tthis.fire(\\\"hittest:result\\\", hitTestSource, position, rotation, hitTestResult);\\n\\t\\t});\\n\\t\\thitTestSource.once(\\\"remove\\\", () => {\\n\\t\\t\\tthis.onHitTestSourceRemove(hitTestSource);\\n\\t\\t\\tthis.fire(\\\"hittest:remove\\\", hitTestSource);\\n\\t\\t});\\n\\t}\\n\\tonHitTestSourceRemove(hitTestSource) {\\n\\t\\tconst ind = this._hitTestSources.indexOf(hitTestSource);\\n\\t\\tif (ind !== -1) this._hitTestSources.splice(ind, 1);\\n\\t}\\n}\\n\\nclass XrInput extends EventHandler {\\n\\tstatic EVENT_ADD = \\\"add\\\";\\n\\tstatic EVENT_REMOVE = \\\"remove\\\";\\n\\tstatic EVENT_SELECT = \\\"select\\\";\\n\\tstatic EVENT_SELECTSTART = \\\"selectstart\\\";\\n\\tstatic EVENT_SELECTEND = \\\"selectend\\\";\\n\\tstatic EVENT_SQUEEZE = \\\"squeeze\\\";\\n\\tstatic EVENT_SQUEEZESTART = \\\"squeezestart\\\";\\n\\tstatic EVENT_SQUEEZEEND = \\\"squeezeend\\\";\\n\\tmanager;\\n\\t_inputSources = [];\\n\\t_onInputSourcesChangeEvt;\\n\\tvelocitiesSupported = false;\\n\\tconstructor(manager) {\\n\\t\\tsuper();\\n\\t\\tthis.manager = manager;\\n\\t\\tthis.velocitiesSupported = !!(platform.browser && window.XRPose?.prototype?.hasOwnProperty(\\\"linearVelocity\\\"));\\n\\t\\tthis._onInputSourcesChangeEvt = (evt) => {\\n\\t\\t\\tthis._onInputSourcesChange(evt);\\n\\t\\t};\\n\\t\\tthis.manager.on(\\\"start\\\", this._onSessionStart, this);\\n\\t\\tthis.manager.on(\\\"end\\\", this._onSessionEnd, this);\\n\\t}\\n\\t_onSessionStart() {\\n\\t\\tconst session = this.manager.session;\\n\\t\\tsession.addEventListener(\\\"inputsourceschange\\\", this._onInputSourcesChangeEvt);\\n\\t\\tsession.addEventListener(\\\"select\\\", (evt) => {\\n\\t\\t\\tconst inputSource = this._getByInputSource(evt.inputSource);\\n\\t\\t\\tinputSource.update(evt.frame);\\n\\t\\t\\tinputSource.fire(\\\"select\\\", evt);\\n\\t\\t\\tthis.fire(\\\"select\\\", inputSource, evt);\\n\\t\\t});\\n\\t\\tsession.addEventListener(\\\"selectstart\\\", (evt) => {\\n\\t\\t\\tconst inputSource = this._getByInputSource(evt.inputSource);\\n\\t\\t\\tinputSource.update(evt.frame);\\n\\t\\t\\tinputSource._selecting = true;\\n\\t\\t\\tinputSource.fire(\\\"selectstart\\\", evt);\\n\\t\\t\\tthis.fire(\\\"selectstart\\\", inputSource, evt);\\n\\t\\t});\\n\\t\\tsession.addEventListener(\\\"selectend\\\", (evt) => {\\n\\t\\t\\tconst inputSource = this._getByInputSource(evt.inputSource);\\n\\t\\t\\tinputSource.update(evt.frame);\\n\\t\\t\\tinputSource._selecting = false;\\n\\t\\t\\tinputSource.fire(\\\"selectend\\\", evt);\\n\\t\\t\\tthis.fire(\\\"selectend\\\", inputSource, evt);\\n\\t\\t});\\n\\t\\tsession.addEventListener(\\\"squeeze\\\", (evt) => {\\n\\t\\t\\tconst inputSource = this._getByInputSource(evt.inputSource);\\n\\t\\t\\tinputSource.update(evt.frame);\\n\\t\\t\\tinputSource.fire(\\\"squeeze\\\", evt);\\n\\t\\t\\tthis.fire(\\\"squeeze\\\", inputSource, evt);\\n\\t\\t});\\n\\t\\tsession.addEventListener(\\\"squeezestart\\\", (evt) => {\\n\\t\\t\\tconst inputSource = this._getByInputSource(evt.inputSource);\\n\\t\\t\\tinputSource.update(evt.frame);\\n\\t\\t\\tinputSource._squeezing = true;\\n\\t\\t\\tinputSource.fire(\\\"squeezestart\\\", evt);\\n\\t\\t\\tthis.fire(\\\"squeezestart\\\", inputSource, evt);\\n\\t\\t});\\n\\t\\tsession.addEventListener(\\\"squeezeend\\\", (evt) => {\\n\\t\\t\\tconst inputSource = this._getByInputSource(evt.inputSource);\\n\\t\\t\\tinputSource.update(evt.frame);\\n\\t\\t\\tinputSource._squeezing = false;\\n\\t\\t\\tinputSource.fire(\\\"squeezeend\\\", evt);\\n\\t\\t\\tthis.fire(\\\"squeezeend\\\", inputSource, evt);\\n\\t\\t});\\n\\t\\tconst inputSources = session.inputSources;\\n\\t\\tfor (let i = 0; i < inputSources.length; i++) {\\n\\t\\t\\tthis._addInputSource(inputSources[i]);\\n\\t\\t}\\n\\t}\\n\\t_onSessionEnd() {\\n\\t\\tlet i = this._inputSources.length;\\n\\t\\twhile (i--) {\\n\\t\\t\\tconst inputSource = this._inputSources[i];\\n\\t\\t\\tthis._inputSources.splice(i, 1);\\n\\t\\t\\tinputSource.fire(\\\"remove\\\");\\n\\t\\t\\tthis.fire(\\\"remove\\\", inputSource);\\n\\t\\t}\\n\\t\\tconst session = this.manager.session;\\n\\t\\tsession.removeEventListener(\\\"inputsourceschange\\\", this._onInputSourcesChangeEvt);\\n\\t}\\n\\t_onInputSourcesChange(evt) {\\n\\t\\tfor (let i = 0; i < evt.removed.length; i++) {\\n\\t\\t\\tthis._removeInputSource(evt.removed[i]);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < evt.added.length; i++) {\\n\\t\\t\\tthis._addInputSource(evt.added[i]);\\n\\t\\t}\\n\\t}\\n\\t_getByInputSource(xrInputSource) {\\n\\t\\tfor (let i = 0; i < this._inputSources.length; i++) {\\n\\t\\t\\tif (this._inputSources[i].inputSource === xrInputSource) {\\n\\t\\t\\t\\treturn this._inputSources[i];\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn null;\\n\\t}\\n\\t_addInputSource(xrInputSource) {\\n\\t\\tif (this._getByInputSource(xrInputSource)) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst inputSource = new XrInputSource(this.manager, xrInputSource);\\n\\t\\tthis._inputSources.push(inputSource);\\n\\t\\tthis.fire(\\\"add\\\", inputSource);\\n\\t}\\n\\t_removeInputSource(xrInputSource) {\\n\\t\\tfor (let i = 0; i < this._inputSources.length; i++) {\\n\\t\\t\\tif (this._inputSources[i].inputSource !== xrInputSource) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tconst inputSource = this._inputSources[i];\\n\\t\\t\\tthis._inputSources.splice(i, 1);\\n\\t\\t\\tlet h = inputSource.hitTestSources.length;\\n\\t\\t\\twhile (h--) {\\n\\t\\t\\t\\tinputSource.hitTestSources[h].remove();\\n\\t\\t\\t}\\n\\t\\t\\tinputSource.fire(\\\"remove\\\");\\n\\t\\t\\tthis.fire(\\\"remove\\\", inputSource);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t}\\n\\tupdate(frame) {\\n\\t\\tfor (let i = 0; i < this._inputSources.length; i++) {\\n\\t\\t\\tthis._inputSources[i].update(frame);\\n\\t\\t}\\n\\t}\\n\\tget inputSources() {\\n\\t\\treturn this._inputSources;\\n\\t}\\n}\\n\\nconst vec3A = new Vec3();\\nconst vec3B = new Vec3();\\nconst mat4A = new Mat4();\\nconst mat4B = new Mat4();\\nclass XrLightEstimation extends EventHandler {\\n\\tstatic EVENT_AVAILABLE = \\\"available\\\";\\n\\tstatic EVENT_ERROR = \\\"error\\\";\\n\\t_manager;\\n\\t_supported = false;\\n\\t_available = false;\\n\\t_lightProbeRequested = false;\\n\\t_lightProbe = null;\\n\\t_intensity = 0;\\n\\t_rotation = new Quat();\\n\\t_color = new Color();\\n\\t_sphericalHarmonics = new Float32Array(27);\\n\\tconstructor(manager) {\\n\\t\\tsuper();\\n\\t\\tthis._manager = manager;\\n\\t\\tthis._manager.on(\\\"start\\\", this._onSessionStart, this);\\n\\t\\tthis._manager.on(\\\"end\\\", this._onSessionEnd, this);\\n\\t}\\n\\t_onSessionStart() {\\n\\t\\tconst supported = !!this._manager.session.requestLightProbe;\\n\\t\\tif (!supported) return;\\n\\t\\tthis._supported = true;\\n\\t}\\n\\t_onSessionEnd() {\\n\\t\\tthis._supported = false;\\n\\t\\tthis._available = false;\\n\\t\\tthis._lightProbeRequested = false;\\n\\t\\tthis._lightProbe = null;\\n\\t}\\n\\tstart() {\\n\\t\\tlet err;\\n\\t\\tif (!this._manager.session) {\\n\\t\\t\\terr = new Error(\\\"XR session is not running\\\");\\n\\t\\t}\\n\\t\\tif (!err && this._manager.type !== XRTYPE_AR) {\\n\\t\\t\\terr = new Error(\\\"XR session type is not AR\\\");\\n\\t\\t}\\n\\t\\tif (!err && !this._supported) {\\n\\t\\t\\terr = new Error(\\\"light-estimation is not supported\\\");\\n\\t\\t}\\n\\t\\tif (!err && this._lightProbe || this._lightProbeRequested) {\\n\\t\\t\\terr = new Error(\\\"light estimation is already requested\\\");\\n\\t\\t}\\n\\t\\tif (err) {\\n\\t\\t\\tthis.fire(\\\"error\\\", err);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._lightProbeRequested = true;\\n\\t\\tthis._manager.session.requestLightProbe().then((lightProbe) => {\\n\\t\\t\\tconst wasRequested = this._lightProbeRequested;\\n\\t\\t\\tthis._lightProbeRequested = false;\\n\\t\\t\\tif (this._manager.active) {\\n\\t\\t\\t\\tif (wasRequested) {\\n\\t\\t\\t\\t\\tthis._lightProbe = lightProbe;\\n\\t\\t\\t\\t}\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.fire(\\\"error\\\", new Error(\\\"XR session is not active\\\"));\\n\\t\\t\\t}\\n\\t\\t}).catch((ex) => {\\n\\t\\t\\tthis._lightProbeRequested = false;\\n\\t\\t\\tthis.fire(\\\"error\\\", ex);\\n\\t\\t});\\n\\t}\\n\\tend() {\\n\\t\\tthis._lightProbeRequested = false;\\n\\t\\tthis._lightProbe = null;\\n\\t\\tthis._available = false;\\n\\t}\\n\\tupdate(frame) {\\n\\t\\tif (!this._lightProbe) return;\\n\\t\\tconst lightEstimate = frame.getLightEstimate(this._lightProbe);\\n\\t\\tif (!lightEstimate) return;\\n\\t\\tif (!this._available) {\\n\\t\\t\\tthis._available = true;\\n\\t\\t\\tthis.fire(\\\"available\\\");\\n\\t\\t}\\n\\t\\tconst pli = lightEstimate.primaryLightIntensity;\\n\\t\\tthis._intensity = Math.max(1, Math.max(pli.x, Math.max(pli.y, pli.z)));\\n\\t\\tvec3A.copy(pli).mulScalar(1 / this._intensity);\\n\\t\\tthis._color.set(vec3A.x, vec3A.y, vec3A.z);\\n\\t\\tvec3A.set(0, 0, 0);\\n\\t\\tvec3B.copy(lightEstimate.primaryLightDirection);\\n\\t\\tmat4A.setLookAt(vec3B, vec3A, Vec3.UP);\\n\\t\\tmat4B.setFromAxisAngle(Vec3.RIGHT, 90);\\n\\t\\tmat4A.mul(mat4B);\\n\\t\\tthis._rotation.setFromMat4(mat4A);\\n\\t\\tthis._sphericalHarmonics.set(lightEstimate.sphericalHarmonicsCoefficients);\\n\\t}\\n\\tget supported() {\\n\\t\\treturn this._supported;\\n\\t}\\n\\tget available() {\\n\\t\\treturn this._available;\\n\\t}\\n\\tget intensity() {\\n\\t\\treturn this._available ? this._intensity : null;\\n\\t}\\n\\tget color() {\\n\\t\\treturn this._available ? this._color : null;\\n\\t}\\n\\tget rotation() {\\n\\t\\treturn this._available ? this._rotation : null;\\n\\t}\\n\\tget sphericalHarmonics() {\\n\\t\\treturn this._available ? this._sphericalHarmonics : null;\\n\\t}\\n}\\n\\nlet ids = 0;\\nclass XrPlane extends EventHandler {\\n\\tstatic EVENT_REMOVE = \\\"remove\\\";\\n\\tstatic EVENT_CHANGE = \\\"change\\\";\\n\\t_id;\\n\\t_planeDetection;\\n\\t_xrPlane;\\n\\t_lastChangedTime;\\n\\t_orientation;\\n\\t_position = new Vec3();\\n\\t_rotation = new Quat();\\n\\tconstructor(planeDetection, xrPlane) {\\n\\t\\tsuper();\\n\\t\\tthis._id = ++ids;\\n\\t\\tthis._planeDetection = planeDetection;\\n\\t\\tthis._xrPlane = xrPlane;\\n\\t\\tthis._lastChangedTime = xrPlane.lastChangedTime;\\n\\t\\tthis._orientation = xrPlane.orientation;\\n\\t}\\n\\tdestroy() {\\n\\t\\tif (!this._xrPlane) return;\\n\\t\\tthis._xrPlane = null;\\n\\t\\tthis.fire(\\\"remove\\\");\\n\\t}\\n\\tupdate(frame) {\\n\\t\\tconst manager = this._planeDetection._manager;\\n\\t\\tconst pose = frame.getPose(this._xrPlane.planeSpace, manager._referenceSpace);\\n\\t\\tif (pose) {\\n\\t\\t\\tthis._position.copy(pose.transform.position);\\n\\t\\t\\tthis._rotation.copy(pose.transform.orientation);\\n\\t\\t}\\n\\t\\tif (this._lastChangedTime !== this._xrPlane.lastChangedTime) {\\n\\t\\t\\tthis._lastChangedTime = this._xrPlane.lastChangedTime;\\n\\t\\t\\tthis.fire(\\\"change\\\");\\n\\t\\t}\\n\\t}\\n\\tgetPosition() {\\n\\t\\treturn this._position;\\n\\t}\\n\\tgetRotation() {\\n\\t\\treturn this._rotation;\\n\\t}\\n\\tget id() {\\n\\t\\treturn this._id;\\n\\t}\\n\\tget orientation() {\\n\\t\\treturn this._orientation;\\n\\t}\\n\\tget points() {\\n\\t\\treturn this._xrPlane.polygon;\\n\\t}\\n\\tget label() {\\n\\t\\treturn this._xrPlane.semanticLabel || \\\"\\\";\\n\\t}\\n}\\n\\nclass XrPlaneDetection extends EventHandler {\\n\\tstatic EVENT_AVAILABLE = \\\"available\\\";\\n\\tstatic EVENT_UNAVAILABLE = \\\"unavailable\\\";\\n\\tstatic EVENT_ADD = \\\"add\\\";\\n\\tstatic EVENT_REMOVE = \\\"remove\\\";\\n\\t_manager;\\n\\t_supported = platform.browser && !!window.XRPlane;\\n\\t_available = false;\\n\\t_planesIndex = /* @__PURE__ */ new Map();\\n\\t_planes = [];\\n\\tconstructor(manager) {\\n\\t\\tsuper();\\n\\t\\tthis._manager = manager;\\n\\t\\tif (this._supported) {\\n\\t\\t\\tthis._manager.on(\\\"start\\\", this._onSessionStart, this);\\n\\t\\t\\tthis._manager.on(\\\"end\\\", this._onSessionEnd, this);\\n\\t\\t}\\n\\t}\\n\\t_onSessionStart() {\\n\\t\\tif (this._manager.session.enabledFeatures) {\\n\\t\\t\\tconst available = this._manager.session.enabledFeatures.indexOf(\\\"plane-detection\\\") !== -1;\\n\\t\\t\\tif (available) {\\n\\t\\t\\t\\tthis._available = true;\\n\\t\\t\\t\\tthis.fire(\\\"available\\\");\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\t_onSessionEnd() {\\n\\t\\tfor (let i = 0; i < this._planes.length; i++) {\\n\\t\\t\\tthis._planes[i].destroy();\\n\\t\\t\\tthis.fire(\\\"remove\\\", this._planes[i]);\\n\\t\\t}\\n\\t\\tthis._planesIndex.clear();\\n\\t\\tthis._planes.length = 0;\\n\\t\\tif (this._available) {\\n\\t\\t\\tthis._available = false;\\n\\t\\t\\tthis.fire(\\\"unavailable\\\");\\n\\t\\t}\\n\\t}\\n\\tupdate(frame) {\\n\\t\\tif (!this._available) {\\n\\t\\t\\tif (!this._manager.session.enabledFeatures && frame.detectedPlanes.size) {\\n\\t\\t\\t\\tthis._available = true;\\n\\t\\t\\t\\tthis.fire(\\\"available\\\");\\n\\t\\t\\t} else {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst detectedPlanes = frame.detectedPlanes;\\n\\t\\tfor (const [xrPlane, plane] of this._planesIndex) {\\n\\t\\t\\tif (detectedPlanes.has(xrPlane)) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tthis._planesIndex.delete(xrPlane);\\n\\t\\t\\tthis._planes.splice(this._planes.indexOf(plane), 1);\\n\\t\\t\\tplane.destroy();\\n\\t\\t\\tthis.fire(\\\"remove\\\", plane);\\n\\t\\t}\\n\\t\\tfor (const xrPlane of detectedPlanes) {\\n\\t\\t\\tlet plane = this._planesIndex.get(xrPlane);\\n\\t\\t\\tif (!plane) {\\n\\t\\t\\t\\tplane = new XrPlane(this, xrPlane);\\n\\t\\t\\t\\tthis._planesIndex.set(xrPlane, plane);\\n\\t\\t\\t\\tthis._planes.push(plane);\\n\\t\\t\\t\\tplane.update(frame);\\n\\t\\t\\t\\tthis.fire(\\\"add\\\", plane);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tplane.update(frame);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget supported() {\\n\\t\\treturn this._supported;\\n\\t}\\n\\tget available() {\\n\\t\\treturn this._available;\\n\\t}\\n\\tget planes() {\\n\\t\\treturn this._planes;\\n\\t}\\n}\\n\\nclass XrAnchor extends EventHandler {\\n\\tstatic EVENT_DESTROY = \\\"destroy\\\";\\n\\tstatic EVENT_CHANGE = \\\"change\\\";\\n\\tstatic EVENT_PERSIST = \\\"persist\\\";\\n\\tstatic EVENT_FORGET = \\\"forget\\\";\\n\\t_position = new Vec3();\\n\\t_rotation = new Quat();\\n\\t_uuid = null;\\n\\t_uuidRequests = null;\\n\\tconstructor(anchors, xrAnchor, uuid = null) {\\n\\t\\tsuper();\\n\\t\\tthis._anchors = anchors;\\n\\t\\tthis._xrAnchor = xrAnchor;\\n\\t\\tthis._uuid = uuid;\\n\\t}\\n\\tdestroy() {\\n\\t\\tif (!this._xrAnchor) return;\\n\\t\\tconst xrAnchor = this._xrAnchor;\\n\\t\\tthis._xrAnchor.delete();\\n\\t\\tthis._xrAnchor = null;\\n\\t\\tthis.fire(\\\"destroy\\\", xrAnchor, this);\\n\\t}\\n\\tupdate(frame) {\\n\\t\\tif (!this._xrAnchor) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst pose = frame.getPose(this._xrAnchor.anchorSpace, this._anchors.manager._referenceSpace);\\n\\t\\tif (pose) {\\n\\t\\t\\tif (this._position.equals(pose.transform.position) && this._rotation.equals(pose.transform.orientation)) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tthis._position.copy(pose.transform.position);\\n\\t\\t\\tthis._rotation.copy(pose.transform.orientation);\\n\\t\\t\\tthis.fire(\\\"change\\\");\\n\\t\\t}\\n\\t}\\n\\tgetPosition() {\\n\\t\\treturn this._position;\\n\\t}\\n\\tgetRotation() {\\n\\t\\treturn this._rotation;\\n\\t}\\n\\tpersist(callback) {\\n\\t\\tif (!this._anchors.persistence) {\\n\\t\\t\\tcallback?.(new Error(\\\"Persistent Anchors are not supported\\\"), null);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._uuid) {\\n\\t\\t\\tcallback?.(null, this._uuid);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._uuidRequests) {\\n\\t\\t\\tif (callback) this._uuidRequests.push(callback);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._uuidRequests = [];\\n\\t\\tthis._xrAnchor.requestPersistentHandle().then((uuid) => {\\n\\t\\t\\tthis._uuid = uuid;\\n\\t\\t\\tthis._anchors._indexByUuid.set(this._uuid, this);\\n\\t\\t\\tcallback?.(null, uuid);\\n\\t\\t\\tfor (const uuidRequest of this._uuidRequests) {\\n\\t\\t\\t\\tuuidRequest(null, uuid);\\n\\t\\t\\t}\\n\\t\\t\\tthis._uuidRequests = null;\\n\\t\\t\\tthis.fire(\\\"persist\\\", uuid);\\n\\t\\t}).catch((ex) => {\\n\\t\\t\\tcallback?.(ex, null);\\n\\t\\t\\tfor (const uuidRequest of this._uuidRequests) {\\n\\t\\t\\t\\tuuidRequest(ex, null);\\n\\t\\t\\t}\\n\\t\\t\\tthis._uuidRequests = null;\\n\\t\\t});\\n\\t}\\n\\tforget(callback) {\\n\\t\\tif (!this._uuid) {\\n\\t\\t\\tcallback?.(new Error(\\\"Anchor is not persistent\\\"));\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._anchors.forget(this._uuid, (ex) => {\\n\\t\\t\\tthis._uuid = null;\\n\\t\\t\\tcallback?.(ex);\\n\\t\\t\\tthis.fire(\\\"forget\\\");\\n\\t\\t});\\n\\t}\\n\\tget uuid() {\\n\\t\\treturn this._uuid;\\n\\t}\\n\\tget persistent() {\\n\\t\\treturn !!this._uuid;\\n\\t}\\n}\\n\\nclass XrAnchors extends EventHandler {\\n\\tstatic EVENT_AVAILABLE = \\\"available\\\";\\n\\tstatic EVENT_UNAVAILABLE = \\\"unavailable\\\";\\n\\tstatic EVENT_ERROR = \\\"error\\\";\\n\\tstatic EVENT_ADD = \\\"add\\\";\\n\\tstatic EVENT_DESTROY = \\\"destroy\\\";\\n\\tmanager;\\n\\t_supported = platform.browser && !!window.XRAnchor;\\n\\t_available = false;\\n\\t_checkingAvailability = false;\\n\\t_persistence = platform.browser && !!window?.XRSession?.prototype.restorePersistentAnchor;\\n\\t_creationQueue = [];\\n\\t_index = /* @__PURE__ */ new Map();\\n\\t_indexByUuid = /* @__PURE__ */ new Map();\\n\\t_list = [];\\n\\t_callbacksAnchors = /* @__PURE__ */ new Map();\\n\\tconstructor(manager) {\\n\\t\\tsuper();\\n\\t\\tthis.manager = manager;\\n\\t\\tif (this._supported) {\\n\\t\\t\\tthis.manager.on(\\\"start\\\", this._onSessionStart, this);\\n\\t\\t\\tthis.manager.on(\\\"end\\\", this._onSessionEnd, this);\\n\\t\\t}\\n\\t}\\n\\t_onSessionStart() {\\n\\t\\tconst available = this.manager.session.enabledFeatures?.indexOf(\\\"anchors\\\") >= 0;\\n\\t\\tif (!available) return;\\n\\t\\tthis._available = available;\\n\\t\\tthis.fire(\\\"available\\\");\\n\\t}\\n\\t_onSessionEnd() {\\n\\t\\tif (!this._available) return;\\n\\t\\tthis._available = false;\\n\\t\\tfor (let i2 = 0; i2 < this._creationQueue.length; i2++) {\\n\\t\\t\\tif (!this._creationQueue[i2].callback) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tthis._creationQueue[i2].callback(new Error(\\\"session ended\\\"), null);\\n\\t\\t}\\n\\t\\tthis._creationQueue.length = 0;\\n\\t\\tthis._index.clear();\\n\\t\\tthis._indexByUuid.clear();\\n\\t\\tlet i = this._list.length;\\n\\t\\twhile (i--) {\\n\\t\\t\\tthis._list[i].destroy();\\n\\t\\t}\\n\\t\\tthis._list.length = 0;\\n\\t\\tthis.fire(\\\"unavailable\\\");\\n\\t}\\n\\t_createAnchor(xrAnchor, uuid = null) {\\n\\t\\tconst anchor = new XrAnchor(this, xrAnchor, uuid);\\n\\t\\tthis._index.set(xrAnchor, anchor);\\n\\t\\tif (uuid) this._indexByUuid.set(uuid, anchor);\\n\\t\\tthis._list.push(anchor);\\n\\t\\tanchor.once(\\\"destroy\\\", this._onAnchorDestroy, this);\\n\\t\\treturn anchor;\\n\\t}\\n\\t_onAnchorDestroy(xrAnchor, anchor) {\\n\\t\\tthis._index.delete(xrAnchor);\\n\\t\\tif (anchor.uuid) this._indexByUuid.delete(anchor.uuid);\\n\\t\\tconst ind = this._list.indexOf(anchor);\\n\\t\\tif (ind !== -1) this._list.splice(ind, 1);\\n\\t\\tthis.fire(\\\"destroy\\\", anchor);\\n\\t}\\n\\tcreate(position, rotation, callback) {\\n\\t\\tif (!this._available) {\\n\\t\\t\\tcallback?.(new Error(\\\"Anchors API is not available\\\"), null);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (window.XRHitTestResult && position instanceof XRHitTestResult) {\\n\\t\\t\\tconst hitResult = position;\\n\\t\\t\\tcallback = rotation;\\n\\t\\t\\tif (!this._supported) {\\n\\t\\t\\t\\tcallback?.(new Error(\\\"Anchors API is not supported\\\"), null);\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tif (!hitResult.createAnchor) {\\n\\t\\t\\t\\tcallback?.(new Error(\\\"Creating Anchor from Hit Test is not supported\\\"), null);\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\thitResult.createAnchor().then((xrAnchor) => {\\n\\t\\t\\t\\tconst anchor = this._createAnchor(xrAnchor);\\n\\t\\t\\t\\tcallback?.(null, anchor);\\n\\t\\t\\t\\tthis.fire(\\\"add\\\", anchor);\\n\\t\\t\\t}).catch((ex) => {\\n\\t\\t\\t\\tcallback?.(ex, null);\\n\\t\\t\\t\\tthis.fire(\\\"error\\\", ex);\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\tthis._creationQueue.push({\\n\\t\\t\\t\\ttransform: new XRRigidTransform(position, rotation),\\n\\t\\t\\t\\tcallback\\n\\t\\t\\t});\\n\\t\\t}\\n\\t}\\n\\trestore(uuid, callback) {\\n\\t\\tif (!this._available) {\\n\\t\\t\\tcallback?.(new Error(\\\"Anchors API is not available\\\"), null);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!this._persistence) {\\n\\t\\t\\tcallback?.(new Error(\\\"Anchor Persistence is not supported\\\"), null);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!this.manager.active) {\\n\\t\\t\\tcallback?.(new Error(\\\"WebXR session is not active\\\"), null);\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.manager.session.restorePersistentAnchor(uuid).then((xrAnchor) => {\\n\\t\\t\\tconst anchor = this._createAnchor(xrAnchor, uuid);\\n\\t\\t\\tcallback?.(null, anchor);\\n\\t\\t\\tthis.fire(\\\"add\\\", anchor);\\n\\t\\t}).catch((ex) => {\\n\\t\\t\\tcallback?.(ex, null);\\n\\t\\t\\tthis.fire(\\\"error\\\", ex);\\n\\t\\t});\\n\\t}\\n\\tforget(uuid, callback) {\\n\\t\\tif (!this._available) {\\n\\t\\t\\tcallback?.(new Error(\\\"Anchors API is not available\\\"));\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!this._persistence) {\\n\\t\\t\\tcallback?.(new Error(\\\"Anchor Persistence is not supported\\\"));\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!this.manager.active) {\\n\\t\\t\\tcallback?.(new Error(\\\"WebXR session is not active\\\"));\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.manager.session.deletePersistentAnchor(uuid).then(() => {\\n\\t\\t\\tcallback?.(null);\\n\\t\\t}).catch((ex) => {\\n\\t\\t\\tcallback?.(ex);\\n\\t\\t\\tthis.fire(\\\"error\\\", ex);\\n\\t\\t});\\n\\t}\\n\\tupdate(frame) {\\n\\t\\tif (!this._available) {\\n\\t\\t\\tif (!this.manager.session.enabledFeatures && !this._checkingAvailability) {\\n\\t\\t\\t\\tthis._checkingAvailability = true;\\n\\t\\t\\t\\tframe.createAnchor(new XRRigidTransform(), this.manager._referenceSpace).then((xrAnchor) => {\\n\\t\\t\\t\\t\\txrAnchor.delete();\\n\\t\\t\\t\\t\\tif (this.manager.active) {\\n\\t\\t\\t\\t\\t\\tthis._available = true;\\n\\t\\t\\t\\t\\t\\tthis.fire(\\\"available\\\");\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}).catch(() => {\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._creationQueue.length) {\\n\\t\\t\\tfor (let i = 0; i < this._creationQueue.length; i++) {\\n\\t\\t\\t\\tconst request = this._creationQueue[i];\\n\\t\\t\\t\\tframe.createAnchor(request.transform, this.manager._referenceSpace).then((xrAnchor) => {\\n\\t\\t\\t\\t\\tif (request.callback) {\\n\\t\\t\\t\\t\\t\\tthis._callbacksAnchors.set(xrAnchor, request.callback);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}).catch((ex) => {\\n\\t\\t\\t\\t\\tif (request.callback) {\\n\\t\\t\\t\\t\\t\\trequest.callback(ex, null);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\tthis.fire(\\\"error\\\", ex);\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t\\tthis._creationQueue.length = 0;\\n\\t\\t}\\n\\t\\tfor (const [xrAnchor, anchor] of this._index) {\\n\\t\\t\\tif (frame.trackedAnchors.has(xrAnchor)) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tthis._index.delete(xrAnchor);\\n\\t\\t\\tanchor.destroy();\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < this._list.length; i++) {\\n\\t\\t\\tthis._list[i].update(frame);\\n\\t\\t}\\n\\t\\tfor (const xrAnchor of frame.trackedAnchors) {\\n\\t\\t\\tif (this._index.has(xrAnchor)) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\ttry {\\n\\t\\t\\t\\tconst tmp = xrAnchor.anchorSpace;\\n\\t\\t\\t} catch (ex) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tconst anchor = this._createAnchor(xrAnchor);\\n\\t\\t\\tanchor.update(frame);\\n\\t\\t\\tconst callback = this._callbacksAnchors.get(xrAnchor);\\n\\t\\t\\tif (callback) {\\n\\t\\t\\t\\tthis._callbacksAnchors.delete(xrAnchor);\\n\\t\\t\\t\\tcallback(null, anchor);\\n\\t\\t\\t}\\n\\t\\t\\tthis.fire(\\\"add\\\", anchor);\\n\\t\\t}\\n\\t}\\n\\tget supported() {\\n\\t\\treturn this._supported;\\n\\t}\\n\\tget available() {\\n\\t\\treturn this._available;\\n\\t}\\n\\tget persistence() {\\n\\t\\treturn this._persistence;\\n\\t}\\n\\tget uuids() {\\n\\t\\tif (!this._available) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tif (!this._persistence) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tif (!this.manager.active) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\treturn this.manager.session.persistentAnchors;\\n\\t}\\n\\tget list() {\\n\\t\\treturn this._list;\\n\\t}\\n}\\n\\nclass XrMesh extends EventHandler {\\n\\tstatic EVENT_REMOVE = \\\"remove\\\";\\n\\tstatic EVENT_CHANGE = \\\"change\\\";\\n\\t_meshDetection;\\n\\t_xrMesh;\\n\\t_lastChanged = 0;\\n\\t_position = new Vec3();\\n\\t_rotation = new Quat();\\n\\tconstructor(meshDetection, xrMesh) {\\n\\t\\tsuper();\\n\\t\\tthis._meshDetection = meshDetection;\\n\\t\\tthis._xrMesh = xrMesh;\\n\\t\\tthis._lastChanged = this._xrMesh.lastChangedTime;\\n\\t}\\n\\tget xrMesh() {\\n\\t\\treturn this._xrMesh;\\n\\t}\\n\\tget label() {\\n\\t\\treturn this._xrMesh.semanticLabel || \\\"\\\";\\n\\t}\\n\\tget vertices() {\\n\\t\\treturn this._xrMesh.vertices;\\n\\t}\\n\\tget indices() {\\n\\t\\treturn this._xrMesh.indices;\\n\\t}\\n\\tdestroy() {\\n\\t\\tif (!this._xrMesh) return;\\n\\t\\tthis._xrMesh = null;\\n\\t\\tthis.fire(\\\"remove\\\");\\n\\t}\\n\\tupdate(frame) {\\n\\t\\tconst manager = this._meshDetection._manager;\\n\\t\\tconst pose = frame.getPose(this._xrMesh.meshSpace, manager._referenceSpace);\\n\\t\\tif (pose) {\\n\\t\\t\\tthis._position.copy(pose.transform.position);\\n\\t\\t\\tthis._rotation.copy(pose.transform.orientation);\\n\\t\\t}\\n\\t\\tif (this._lastChanged !== this._xrMesh.lastChangedTime) {\\n\\t\\t\\tthis._lastChanged = this._xrMesh.lastChangedTime;\\n\\t\\t\\tthis.fire(\\\"change\\\");\\n\\t\\t}\\n\\t}\\n\\tgetPosition() {\\n\\t\\treturn this._position;\\n\\t}\\n\\tgetRotation() {\\n\\t\\treturn this._rotation;\\n\\t}\\n}\\n\\nclass XrMeshDetection extends EventHandler {\\n\\tstatic EVENT_AVAILABLE = \\\"available\\\";\\n\\tstatic EVENT_UNAVAILABLE = \\\"unavailable\\\";\\n\\tstatic EVENT_ADD = \\\"add\\\";\\n\\tstatic EVENT_REMOVE = \\\"remove\\\";\\n\\t_manager;\\n\\t_supported = platform.browser && !!window.XRMesh;\\n\\t_available = false;\\n\\t_index = /* @__PURE__ */ new Map();\\n\\t_list = [];\\n\\tconstructor(manager) {\\n\\t\\tsuper();\\n\\t\\tthis._manager = manager;\\n\\t\\tif (this._supported) {\\n\\t\\t\\tthis._manager.on(\\\"start\\\", this._onSessionStart, this);\\n\\t\\t\\tthis._manager.on(\\\"end\\\", this._onSessionEnd, this);\\n\\t\\t}\\n\\t}\\n\\tupdate(frame) {\\n\\t\\tif (!this._available) {\\n\\t\\t\\tif (!this._manager.session.enabledFeatures && frame.detectedMeshes.size) {\\n\\t\\t\\t\\tthis._available = true;\\n\\t\\t\\t\\tthis.fire(\\\"available\\\");\\n\\t\\t\\t} else {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (const xrMesh of frame.detectedMeshes) {\\n\\t\\t\\tlet mesh = this._index.get(xrMesh);\\n\\t\\t\\tif (!mesh) {\\n\\t\\t\\t\\tmesh = new XrMesh(this, xrMesh);\\n\\t\\t\\t\\tthis._index.set(xrMesh, mesh);\\n\\t\\t\\t\\tthis._list.push(mesh);\\n\\t\\t\\t\\tmesh.update(frame);\\n\\t\\t\\t\\tthis.fire(\\\"add\\\", mesh);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tmesh.update(frame);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (const mesh of this._index.values()) {\\n\\t\\t\\tif (frame.detectedMeshes.has(mesh.xrMesh)) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tthis._removeMesh(mesh);\\n\\t\\t}\\n\\t}\\n\\t_removeMesh(mesh) {\\n\\t\\tthis._index.delete(mesh.xrMesh);\\n\\t\\tthis._list.splice(this._list.indexOf(mesh), 1);\\n\\t\\tmesh.destroy();\\n\\t\\tthis.fire(\\\"remove\\\", mesh);\\n\\t}\\n\\t_onSessionStart() {\\n\\t\\tif (this._manager.session.enabledFeatures) {\\n\\t\\t\\tconst available = this._manager.session.enabledFeatures.indexOf(\\\"mesh-detection\\\") !== -1;\\n\\t\\t\\tif (!available) return;\\n\\t\\t\\tthis._available = available;\\n\\t\\t\\tthis.fire(\\\"available\\\");\\n\\t\\t}\\n\\t}\\n\\t_onSessionEnd() {\\n\\t\\tif (!this._available) return;\\n\\t\\tthis._available = false;\\n\\t\\tfor (const mesh of this._index.values()) {\\n\\t\\t\\tthis._removeMesh(mesh);\\n\\t\\t}\\n\\t\\tthis.fire(\\\"unavailable\\\");\\n\\t}\\n\\tget supported() {\\n\\t\\treturn this._supported;\\n\\t}\\n\\tget available() {\\n\\t\\treturn this._available;\\n\\t}\\n\\tget meshes() {\\n\\t\\treturn this._list;\\n\\t}\\n}\\n\\nclass XrView extends EventHandler {\\n\\tstatic EVENT_DEPTHRESIZE = \\\"depth:resize\\\";\\n\\t_manager;\\n\\t_xrView;\\n\\t_positionData = new Float32Array(3);\\n\\t_viewport = new Vec4();\\n\\t_projMat = new Mat4();\\n\\t_projViewOffMat = new Mat4();\\n\\t_viewMat = new Mat4();\\n\\t_viewOffMat = new Mat4();\\n\\t_viewMat3 = new Mat3();\\n\\t_viewInvMat = new Mat4();\\n\\t_viewInvOffMat = new Mat4();\\n\\t_xrCamera = null;\\n\\t_textureColor = null;\\n\\t_textureDepth = null;\\n\\t_depthInfo = null;\\n\\t_emptyDepthBuffer = new Uint8Array(32);\\n\\t_depthMatrix = new Mat4();\\n\\tconstructor(manager, xrView, viewsCount) {\\n\\t\\tsuper();\\n\\t\\tthis._manager = manager;\\n\\t\\tthis._xrView = xrView;\\n\\t\\tconst device = this._manager.app.graphicsDevice;\\n\\t\\tif (this._manager.views.supportedColor) {\\n\\t\\t\\tthis._xrCamera = this._xrView.camera;\\n\\t\\t\\tif (this._manager.views.availableColor && this._xrCamera) {\\n\\t\\t\\t\\tthis._textureColor = new Texture(device, {\\n\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGB8,\\n\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\tminFilter: FILTER_LINEAR,\\n\\t\\t\\t\\t\\tmagFilter: FILTER_LINEAR,\\n\\t\\t\\t\\t\\twidth: this._xrCamera.width,\\n\\t\\t\\t\\t\\theight: this._xrCamera.height,\\n\\t\\t\\t\\t\\tname: `XrView-${this._xrView.eye}-Color`\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this._manager.views.supportedDepth && this._manager.views.availableDepth) {\\n\\t\\t\\tconst filtering = this._manager.views.depthGpuOptimized ? FILTER_NEAREST : FILTER_LINEAR;\\n\\t\\t\\tthis._textureDepth = new Texture(device, {\\n\\t\\t\\t\\tformat: this._manager.views.depthPixelFormat,\\n\\t\\t\\t\\tarrayLength: viewsCount === 1 ? 0 : viewsCount,\\n\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\tminFilter: filtering,\\n\\t\\t\\t\\tmagFilter: filtering,\\n\\t\\t\\t\\twidth: 4,\\n\\t\\t\\t\\theight: 4,\\n\\t\\t\\t\\tname: `XrView-${this._xrView.eye}-Depth`\\n\\t\\t\\t});\\n\\t\\t\\tfor (let i = 0; i < this._textureDepth._levels.length; i++) {\\n\\t\\t\\t\\tthis._textureDepth._levels[i] = this._emptyDepthBuffer;\\n\\t\\t\\t}\\n\\t\\t\\tthis._textureDepth.upload();\\n\\t\\t}\\n\\t\\tif (this._textureColor || this._textureDepth) {\\n\\t\\t\\tdevice.on(\\\"devicelost\\\", this._onDeviceLost, this);\\n\\t\\t}\\n\\t}\\n\\tget textureColor() {\\n\\t\\treturn this._textureColor;\\n\\t}\\n\\tget textureDepth() {\\n\\t\\treturn this._textureDepth;\\n\\t}\\n\\tget depthUvMatrix() {\\n\\t\\treturn this._depthMatrix;\\n\\t}\\n\\tget depthValueToMeters() {\\n\\t\\treturn this._depthInfo?.rawValueToMeters || 0;\\n\\t}\\n\\tget eye() {\\n\\t\\treturn this._xrView.eye;\\n\\t}\\n\\tget viewport() {\\n\\t\\treturn this._viewport;\\n\\t}\\n\\tget projMat() {\\n\\t\\treturn this._projMat;\\n\\t}\\n\\tget projViewOffMat() {\\n\\t\\treturn this._projViewOffMat;\\n\\t}\\n\\tget viewOffMat() {\\n\\t\\treturn this._viewOffMat;\\n\\t}\\n\\tget viewInvOffMat() {\\n\\t\\treturn this._viewInvOffMat;\\n\\t}\\n\\tget viewMat3() {\\n\\t\\treturn this._viewMat3;\\n\\t}\\n\\tget positionData() {\\n\\t\\treturn this._positionData;\\n\\t}\\n\\tupdate(frame, xrView) {\\n\\t\\tthis._xrView = xrView;\\n\\t\\tif (this._manager.views.availableColor) {\\n\\t\\t\\tthis._xrCamera = this._xrView.camera;\\n\\t\\t}\\n\\t\\tconst viewport = this._manager.xrBridge.getViewport(frame, this._xrView);\\n\\t\\tthis._viewport.x = viewport.x;\\n\\t\\tthis._viewport.y = viewport.y;\\n\\t\\tthis._viewport.z = viewport.width;\\n\\t\\tthis._viewport.w = viewport.height;\\n\\t\\tthis._projMat.set(this._xrView.projectionMatrix);\\n\\t\\tthis._viewMat.set(this._xrView.transform.inverse.matrix);\\n\\t\\tthis._viewInvMat.set(this._xrView.transform.matrix);\\n\\t\\tthis._updateTextureColor();\\n\\t\\tthis._updateDepth(frame);\\n\\t}\\n\\t_updateTextureColor() {\\n\\t\\tif (!this._manager.views.availableColor || !this._xrCamera || !this._textureColor) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._manager.xrBridge?.syncCameraColorTexture(this._xrCamera, this._textureColor);\\n\\t}\\n\\t_updateDepth(frame) {\\n\\t\\tif (!this._manager.views.availableDepth || !this._textureDepth) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst gpu = this._manager.views.depthGpuOptimized;\\n\\t\\tconst infoSource = gpu ? this._manager.graphicsBinding : frame;\\n\\t\\tif (!infoSource) {\\n\\t\\t\\tthis._depthInfo = null;\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst depthInfo = infoSource.getDepthInformation(this._xrView);\\n\\t\\tif (!depthInfo) {\\n\\t\\t\\tthis._depthInfo = null;\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tlet matrixDirty = !this._depthInfo !== !depthInfo;\\n\\t\\tthis._depthInfo = depthInfo;\\n\\t\\tconst width = this._depthInfo?.width || 4;\\n\\t\\tconst height = this._depthInfo?.height || 4;\\n\\t\\tlet resized = false;\\n\\t\\tif (this._textureDepth.width !== width || this._textureDepth.height !== height) {\\n\\t\\t\\tthis._textureDepth._width = width;\\n\\t\\t\\tthis._textureDepth._height = height;\\n\\t\\t\\tmatrixDirty = true;\\n\\t\\t\\tresized = true;\\n\\t\\t}\\n\\t\\tif (matrixDirty) {\\n\\t\\t\\tif (this._depthInfo) {\\n\\t\\t\\t\\tthis._depthMatrix.data.set(this._depthInfo.normDepthBufferFromNormView.matrix);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._depthMatrix.setIdentity();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this._depthInfo) {\\n\\t\\t\\tif (gpu) {\\n\\t\\t\\t\\tthis._manager.xrBridge?.syncCameraDepthTexture(\\n\\t\\t\\t\\t\\tthis._depthInfo,\\n\\t\\t\\t\\t\\tthis._textureDepth,\\n\\t\\t\\t\\t\\tthis._manager.views.depthPixelFormat ?? PIXELFORMAT_R32F\\n\\t\\t\\t\\t);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis._textureDepth._levels[0] = new Uint8Array(this._depthInfo.data);\\n\\t\\t\\t\\tthis._textureDepth.upload();\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis._textureDepth._levels[0] = this._emptyDepthBuffer;\\n\\t\\t\\tthis._textureDepth.upload();\\n\\t\\t}\\n\\t\\tif (resized) this.fire(\\\"depth:resize\\\", width, height);\\n\\t}\\n\\tupdateTransforms(transform) {\\n\\t\\tif (transform) {\\n\\t\\t\\tthis._viewInvOffMat.mul2(transform, this._viewInvMat);\\n\\t\\t\\tthis.viewOffMat.copy(this._viewInvOffMat).invert();\\n\\t\\t} else {\\n\\t\\t\\tthis._viewInvOffMat.copy(this._viewInvMat);\\n\\t\\t\\tthis.viewOffMat.copy(this._viewMat);\\n\\t\\t}\\n\\t\\tthis._viewMat3.setFromMat4(this._viewOffMat);\\n\\t\\tthis._projViewOffMat.mul2(this._projMat, this._viewOffMat);\\n\\t\\tthis._positionData[0] = this._viewInvOffMat.data[12];\\n\\t\\tthis._positionData[1] = this._viewInvOffMat.data[13];\\n\\t\\tthis._positionData[2] = this._viewInvOffMat.data[14];\\n\\t}\\n\\t_onDeviceLost() {\\n\\t\\tthis._depthInfo = null;\\n\\t}\\n\\tgetDepth(u, v) {\\n\\t\\tif (this._manager.views.depthGpuOptimized) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\treturn this._depthInfo?.getDepthInMeters(u, v) ?? null;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis._depthInfo = null;\\n\\t\\tif (this._textureColor) {\\n\\t\\t\\tthis._textureColor.destroy();\\n\\t\\t\\tthis._textureColor = null;\\n\\t\\t}\\n\\t\\tif (this._textureDepth) {\\n\\t\\t\\tthis._textureDepth.destroy();\\n\\t\\t\\tthis._textureDepth = null;\\n\\t\\t}\\n\\t}\\n}\\n\\nclass XrViews extends EventHandler {\\n\\tstatic EVENT_ADD = \\\"add\\\";\\n\\tstatic EVENT_REMOVE = \\\"remove\\\";\\n\\t_manager;\\n\\t_index = /* @__PURE__ */ new Map();\\n\\t_indexTmp = /* @__PURE__ */ new Map();\\n\\t_list = [];\\n\\t_supportedColor = false;\\n\\t_supportedDepth = platform.browser && !!window.XRDepthInformation;\\n\\t_availableColor = false;\\n\\t_availableDepth = false;\\n\\t_depthUsage = \\\"\\\";\\n\\t_depthFormat = \\\"\\\";\\n\\t_depthFormats = {\\n\\t\\t[XRDEPTHSENSINGFORMAT_L8A8]: PIXELFORMAT_LA8,\\n\\t\\t[XRDEPTHSENSINGFORMAT_R16U]: PIXELFORMAT_DEPTH,\\n\\t\\t[XRDEPTHSENSINGFORMAT_F32]: PIXELFORMAT_R32F\\n\\t};\\n\\tconstructor(manager) {\\n\\t\\tsuper();\\n\\t\\tthis._manager = manager;\\n\\t\\tconst gd = manager.app?.graphicsDevice;\\n\\t\\tif (platform.browser && !!window.XRCamera) {\\n\\t\\t\\tif (gd?.isWebGL2 && !!window.XRWebGLBinding) {\\n\\t\\t\\t\\tthis._supportedColor = true;\\n\\t\\t\\t} else if (gd?.isWebGPU && !!window.XRGPUBinding) {\\n\\t\\t\\t\\tthis._supportedColor = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis._manager.on(\\\"start\\\", this._onSessionStart, this);\\n\\t\\tthis._manager.on(\\\"end\\\", this._onSessionEnd, this);\\n\\t}\\n\\tget list() {\\n\\t\\treturn this._list;\\n\\t}\\n\\tget supportedColor() {\\n\\t\\treturn this._supportedColor;\\n\\t}\\n\\tget supportedDepth() {\\n\\t\\treturn this._supportedDepth;\\n\\t}\\n\\tget availableColor() {\\n\\t\\treturn this._availableColor;\\n\\t}\\n\\tget availableDepth() {\\n\\t\\treturn this._availableDepth;\\n\\t}\\n\\tget depthUsage() {\\n\\t\\treturn this._depthUsage;\\n\\t}\\n\\tget depthGpuOptimized() {\\n\\t\\treturn this._depthUsage === XRDEPTHSENSINGUSAGE_GPU;\\n\\t}\\n\\tget depthFormat() {\\n\\t\\treturn this._depthFormat;\\n\\t}\\n\\tget depthPixelFormat() {\\n\\t\\treturn this._depthFormats[this._depthFormat] ?? null;\\n\\t}\\n\\tupdate(frame, xrViews) {\\n\\t\\tfor (let i = 0; i < xrViews.length; i++) {\\n\\t\\t\\tthis._indexTmp.set(xrViews[i].eye, xrViews[i]);\\n\\t\\t}\\n\\t\\tfor (const [eye, xrView] of this._indexTmp) {\\n\\t\\t\\tlet view = this._index.get(eye);\\n\\t\\t\\tif (!view) {\\n\\t\\t\\t\\tview = new XrView(this._manager, xrView, xrViews.length);\\n\\t\\t\\t\\tthis._index.set(eye, view);\\n\\t\\t\\t\\tthis._list.push(view);\\n\\t\\t\\t\\tview.update(frame, xrView);\\n\\t\\t\\t\\tthis.fire(\\\"add\\\", view);\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tview.update(frame, xrView);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (const [eye, view] of this._index) {\\n\\t\\t\\tif (this._indexTmp.has(eye)) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tview.destroy();\\n\\t\\t\\tthis._index.delete(eye);\\n\\t\\t\\tconst ind = this._list.indexOf(view);\\n\\t\\t\\tif (ind !== -1) this._list.splice(ind, 1);\\n\\t\\t\\tthis.fire(\\\"remove\\\", view);\\n\\t\\t}\\n\\t\\tthis._indexTmp.clear();\\n\\t}\\n\\tget(eye) {\\n\\t\\treturn this._index.get(eye) || null;\\n\\t}\\n\\t_onSessionStart() {\\n\\t\\tif (this._manager.type !== XRTYPE_AR) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!this._manager.session.enabledFeatures) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._availableColor = this._manager.session.enabledFeatures.indexOf(\\\"camera-access\\\") !== -1;\\n\\t\\tthis._availableDepth = this._manager.session.enabledFeatures.indexOf(\\\"depth-sensing\\\") !== -1;\\n\\t\\tif (this._availableDepth) {\\n\\t\\t\\tconst session = this._manager.session;\\n\\t\\t\\tthis._depthUsage = session.depthUsage;\\n\\t\\t\\tthis._depthFormat = session.depthDataFormat;\\n\\t\\t}\\n\\t}\\n\\t_onSessionEnd() {\\n\\t\\tfor (const view of this._index.values()) {\\n\\t\\t\\tview.destroy();\\n\\t\\t}\\n\\t\\tthis._index.clear();\\n\\t\\tthis._availableColor = false;\\n\\t\\tthis._availableDepth = false;\\n\\t\\tthis._depthUsage = \\\"\\\";\\n\\t\\tthis._depthFormat = \\\"\\\";\\n\\t\\tthis._list.length = 0;\\n\\t}\\n}\\n\\nclass XrBridge {\\n\\tdevice;\\n\\teventHandler;\\n\\timpl;\\n\\t_evtDeviceLost = null;\\n\\t_evtDeviceRestored = null;\\n\\t_session = null;\\n\\t_framebufferScaleFactor = 1;\\n\\t_onBindingError;\\n\\tconstructor(device, eventHandler) {\\n\\t\\tthis.device = device;\\n\\t\\tthis.eventHandler = eventHandler;\\n\\t\\tthis.impl = device.createXrBridgeImpl(this);\\n\\t\\tthis._evtDeviceLost = device.on(\\\"devicelost\\\", this._onDeviceLost, this);\\n\\t\\tthis._evtDeviceRestored = device.on(\\\"devicerestored\\\", this._onDeviceRestored, this);\\n\\t}\\n\\tdestroy() {\\n\\t\\tconst device = this.device;\\n\\t\\tif (device) {\\n\\t\\t\\tthis._evtDeviceLost?.off();\\n\\t\\t\\tthis._evtDeviceLost = null;\\n\\t\\t\\tthis._evtDeviceRestored?.off();\\n\\t\\t\\tthis._evtDeviceRestored = null;\\n\\t\\t\\tthis.impl.endFrame();\\n\\t\\t\\tthis.impl.destroy(device);\\n\\t\\t\\tthis.impl = null;\\n\\t\\t\\tthis._session = null;\\n\\t\\t\\tthis._framebufferScaleFactor = 1;\\n\\t\\t\\tthis._onBindingError = void 0;\\n\\t\\t\\tthis.device = null;\\n\\t\\t\\tthis.eventHandler = null;\\n\\t\\t}\\n\\t}\\n\\t_onDeviceLost() {\\n\\t\\tthis.impl.onGraphicsDeviceLost();\\n\\t}\\n\\t_onDeviceRestored() {\\n\\t\\tthis.impl.onGraphicsDeviceRestored();\\n\\t}\\n\\tattachPresentation(session, options) {\\n\\t\\tthis._session = session;\\n\\t\\tthis._framebufferScaleFactor = options.framebufferScaleFactor;\\n\\t\\tthis._onBindingError = options.onBindingError;\\n\\t\\tthis.impl.attachPresentation(session, options);\\n\\t}\\n\\treleasePresentation() {\\n\\t\\tthis.impl.releasePresentation();\\n\\t}\\n\\tbeginFrame(frame, referenceSpace) {\\n\\t\\tthis.impl.beginFrame(frame, referenceSpace);\\n\\t}\\n\\tendFrame() {\\n\\t\\tthis.impl.endFrame();\\n\\t}\\n\\tgetFramebufferSize(frame, out) {\\n\\t\\tthis.impl.getFramebufferSize(frame, out);\\n\\t}\\n\\tgetViewport(frame, xrView) {\\n\\t\\treturn this.impl.getViewport(frame, xrView);\\n\\t}\\n\\tsyncCameraColorTexture(xrCamera, texture) {\\n\\t\\tthis.impl?.syncCameraColorTexture?.(xrCamera, texture);\\n\\t}\\n\\tsyncCameraDepthTexture(depthInfo, texture, depthPixelFormat) {\\n\\t\\tthis.impl?.syncCameraDepthTexture?.(depthInfo, texture, depthPixelFormat);\\n\\t}\\n\\tget presentationLayer() {\\n\\t\\treturn this.impl.presentationLayer ?? null;\\n\\t}\\n\\tget graphicsBinding() {\\n\\t\\treturn this.impl.graphicsBinding ?? null;\\n\\t}\\n}\\n\\nclass XrManager extends EventHandler {\\n\\tstatic EVENT_AVAILABLE = \\\"available\\\";\\n\\tstatic EVENT_START = \\\"start\\\";\\n\\tstatic EVENT_END = \\\"end\\\";\\n\\tstatic EVENT_UPDATE = \\\"update\\\";\\n\\tstatic EVENT_ERROR = \\\"error\\\";\\n\\tapp;\\n\\t_supported = platform.browser && !!navigator.xr;\\n\\t_available = {};\\n\\t_type = null;\\n\\t_spaceType = null;\\n\\t_session = null;\\n\\txrBridge = null;\\n\\tget graphicsBinding() {\\n\\t\\treturn this.xrBridge?.graphicsBinding ?? null;\\n\\t}\\n\\t_referenceSpace = null;\\n\\tdomOverlay;\\n\\thitTest;\\n\\timageTracking;\\n\\tplaneDetection;\\n\\tmeshDetection;\\n\\tinput;\\n\\tlightEstimation;\\n\\tviews;\\n\\tanchors;\\n\\t_camera = null;\\n\\t_localPosition = new Vec3();\\n\\t_localRotation = new Quat();\\n\\t_depthNear = 0.1;\\n\\t_depthFar = 1e3;\\n\\t_supportedFrameRates = null;\\n\\t_width = 0;\\n\\t_height = 0;\\n\\t_framebufferSize = new Vec2();\\n\\t_framebufferScaleFactor = 1;\\n\\tconstructor(app) {\\n\\t\\tsuper();\\n\\t\\tthis.app = app;\\n\\t\\tthis._available[XRTYPE_INLINE] = false;\\n\\t\\tthis._available[XRTYPE_VR] = false;\\n\\t\\tthis._available[XRTYPE_AR] = false;\\n\\t\\tthis.domOverlay = new XrDomOverlay(this);\\n\\t\\tthis.hitTest = new XrHitTest(this);\\n\\t\\tthis.imageTracking = new XrImageTracking(this);\\n\\t\\tthis.planeDetection = new XrPlaneDetection(this);\\n\\t\\tthis.meshDetection = new XrMeshDetection(this);\\n\\t\\tthis.input = new XrInput(this);\\n\\t\\tthis.lightEstimation = new XrLightEstimation(this);\\n\\t\\tthis.anchors = new XrAnchors(this);\\n\\t\\tthis.views = new XrViews(this);\\n\\t\\tif (this._supported) {\\n\\t\\t\\tnavigator.xr.addEventListener(\\\"devicechange\\\", () => {\\n\\t\\t\\t\\tthis._deviceAvailabilityCheck();\\n\\t\\t\\t});\\n\\t\\t\\tthis._deviceAvailabilityCheck();\\n\\t\\t}\\n\\t}\\n\\tdestroy() {\\n\\t\\tif (this.xrBridge) {\\n\\t\\t\\tthis.xrBridge.destroy();\\n\\t\\t\\tthis.xrBridge = null;\\n\\t\\t}\\n\\t}\\n\\tstart(camera, type, spaceType, options) {\\n\\t\\tlet callback = options;\\n\\t\\tif (typeof options === \\\"object\\\") {\\n\\t\\t\\tcallback = options.callback;\\n\\t\\t}\\n\\t\\tif (!this._available[type]) {\\n\\t\\t\\tif (callback) callback(new Error(\\\"XR is not available\\\"));\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._session) {\\n\\t\\t\\tif (callback) callback(new Error(\\\"XR session is already started\\\"));\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._camera = camera;\\n\\t\\tthis._camera.camera.xr = this;\\n\\t\\tthis._type = type;\\n\\t\\tthis._spaceType = spaceType;\\n\\t\\tthis._framebufferScaleFactor = options?.framebufferScaleFactor ?? 1;\\n\\t\\tthis._setClipPlanes(camera.nearClip, camera.farClip);\\n\\t\\tconst opts = {\\n\\t\\t\\trequiredFeatures: [spaceType],\\n\\t\\t\\toptionalFeatures: []\\n\\t\\t};\\n\\t\\tconst device = this.app.graphicsDevice;\\n\\t\\tif (device?.isWebGPU) {\\n\\t\\t\\topts.requiredFeatures.push(\\\"webgpu\\\");\\n\\t\\t}\\n\\t\\tif (type === XRTYPE_AR) {\\n\\t\\t\\topts.optionalFeatures.push(\\\"light-estimation\\\");\\n\\t\\t\\topts.optionalFeatures.push(\\\"hit-test\\\");\\n\\t\\t\\tif (options) {\\n\\t\\t\\t\\tif (options.imageTracking && this.imageTracking.supported) {\\n\\t\\t\\t\\t\\topts.optionalFeatures.push(\\\"image-tracking\\\");\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.planeDetection) {\\n\\t\\t\\t\\t\\topts.optionalFeatures.push(\\\"plane-detection\\\");\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.meshDetection) {\\n\\t\\t\\t\\t\\topts.optionalFeatures.push(\\\"mesh-detection\\\");\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (this.domOverlay.supported && this.domOverlay.root) {\\n\\t\\t\\t\\topts.optionalFeatures.push(\\\"dom-overlay\\\");\\n\\t\\t\\t\\topts.domOverlay = { root: this.domOverlay.root };\\n\\t\\t\\t}\\n\\t\\t\\tif (options && options.anchors && this.anchors.supported) {\\n\\t\\t\\t\\topts.optionalFeatures.push(\\\"anchors\\\");\\n\\t\\t\\t}\\n\\t\\t\\tif (options && options.depthSensing && this.views.supportedDepth) {\\n\\t\\t\\t\\topts.optionalFeatures.push(\\\"depth-sensing\\\");\\n\\t\\t\\t\\tconst usagePreference = [];\\n\\t\\t\\t\\tconst dataFormatPreference = [];\\n\\t\\t\\t\\tusagePreference.push(XRDEPTHSENSINGUSAGE_GPU, XRDEPTHSENSINGUSAGE_CPU);\\n\\t\\t\\t\\tdataFormatPreference.push(XRDEPTHSENSINGFORMAT_F32, XRDEPTHSENSINGFORMAT_L8A8, XRDEPTHSENSINGFORMAT_R16U);\\n\\t\\t\\t\\tif (options.depthSensing.usagePreference) {\\n\\t\\t\\t\\t\\tconst ind = usagePreference.indexOf(options.depthSensing.usagePreference);\\n\\t\\t\\t\\t\\tif (ind !== -1) usagePreference.splice(ind, 1);\\n\\t\\t\\t\\t\\tusagePreference.unshift(options.depthSensing.usagePreference);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.depthSensing.dataFormatPreference) {\\n\\t\\t\\t\\t\\tconst ind = dataFormatPreference.indexOf(options.depthSensing.dataFormatPreference);\\n\\t\\t\\t\\t\\tif (ind !== -1) dataFormatPreference.splice(ind, 1);\\n\\t\\t\\t\\t\\tdataFormatPreference.unshift(options.depthSensing.dataFormatPreference);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\topts.depthSensing = {\\n\\t\\t\\t\\t\\tusagePreference,\\n\\t\\t\\t\\t\\tdataFormatPreference\\n\\t\\t\\t\\t};\\n\\t\\t\\t}\\n\\t\\t\\tif (options && options.cameraColor && this.views.supportedColor) {\\n\\t\\t\\t\\topts.optionalFeatures.push(\\\"camera-access\\\");\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\topts.optionalFeatures.push(\\\"hand-tracking\\\");\\n\\t\\tif (options && options.optionalFeatures) {\\n\\t\\t\\topts.optionalFeatures = opts.optionalFeatures.concat(options.optionalFeatures);\\n\\t\\t}\\n\\t\\tif (this.imageTracking.supported && this.imageTracking.images.length) {\\n\\t\\t\\tthis.imageTracking.prepareImages((err, trackedImages) => {\\n\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\tif (callback) callback(err);\\n\\t\\t\\t\\t\\tthis.fire(\\\"error\\\", err);\\n\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (trackedImages !== null) {\\n\\t\\t\\t\\t\\topts.trackedImages = trackedImages;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._onStartOptionsReady(type, spaceType, opts, callback);\\n\\t\\t\\t});\\n\\t\\t} else {\\n\\t\\t\\tthis._onStartOptionsReady(type, spaceType, opts, callback);\\n\\t\\t}\\n\\t}\\n\\t_onStartOptionsReady(type, spaceType, options, callback) {\\n\\t\\tnavigator.xr.requestSession(type, options).then((session) => {\\n\\t\\t\\tthis._onSessionStart(session, spaceType, callback);\\n\\t\\t}).catch((ex) => {\\n\\t\\t\\tthis._camera.camera.xr = null;\\n\\t\\t\\tthis._camera = null;\\n\\t\\t\\tthis._type = null;\\n\\t\\t\\tthis._spaceType = null;\\n\\t\\t\\tif (callback) callback(ex);\\n\\t\\t\\tthis.fire(\\\"error\\\", ex);\\n\\t\\t});\\n\\t}\\n\\tend(callback) {\\n\\t\\tif (!this._session) {\\n\\t\\t\\tif (callback) callback(new Error(\\\"XR Session is not initialized\\\"));\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis.xrBridge?.releasePresentation();\\n\\t\\tif (callback) this.once(\\\"end\\\", callback);\\n\\t\\tthis._session.end();\\n\\t}\\n\\tisAvailable(type) {\\n\\t\\treturn this._available[type];\\n\\t}\\n\\t_deviceAvailabilityCheck() {\\n\\t\\tfor (const key in this._available) {\\n\\t\\t\\tthis._sessionSupportCheck(key);\\n\\t\\t}\\n\\t}\\n\\tinitiateRoomCapture(callback) {\\n\\t\\tif (!this._session) {\\n\\t\\t\\tcallback(new Error(\\\"Session is not active\\\"));\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!this._session.initiateRoomCapture) {\\n\\t\\t\\tcallback(new Error(\\\"Session does not support manual room capture\\\"));\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._session.initiateRoomCapture().then(() => {\\n\\t\\t\\tif (callback) callback(null);\\n\\t\\t}).catch((err) => {\\n\\t\\t\\tif (callback) callback(err);\\n\\t\\t});\\n\\t}\\n\\tupdateTargetFrameRate(frameRate, callback) {\\n\\t\\tif (!this._session?.updateTargetFrameRate) {\\n\\t\\t\\tcallback?.(new Error(\\\"unable to update frameRate\\\"));\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._session.updateTargetFrameRate(frameRate).then(() => {\\n\\t\\t\\tcallback?.();\\n\\t\\t}).catch((err) => {\\n\\t\\t\\tcallback?.(err);\\n\\t\\t});\\n\\t}\\n\\t_sessionSupportCheck(type) {\\n\\t\\tnavigator.xr.isSessionSupported(type).then((available) => {\\n\\t\\t\\tif (this._available[type] === available) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tthis._available[type] = available;\\n\\t\\t\\tthis.fire(\\\"available\\\", type, available);\\n\\t\\t\\tthis.fire(`available:${type}`, available);\\n\\t\\t}).catch((ex) => {\\n\\t\\t\\tthis.fire(\\\"error\\\", ex);\\n\\t\\t});\\n\\t}\\n\\t_onSessionStart(session, spaceType, callback) {\\n\\t\\tlet failed = false;\\n\\t\\tthis._session = session;\\n\\t\\tthis.xrBridge = new XrBridge(this.app.graphicsDevice, this);\\n\\t\\tconst onVisibilityChange = () => {\\n\\t\\t\\tthis.fire(\\\"visibility:change\\\", session.visibilityState);\\n\\t\\t};\\n\\t\\tconst onClipPlanesChange = () => {\\n\\t\\t\\tthis._setClipPlanes(this._camera.nearClip, this._camera.farClip);\\n\\t\\t};\\n\\t\\tconst onFrameRateChange = () => {\\n\\t\\t\\tthis.fire(\\\"frameratechange\\\", this._session?.frameRate);\\n\\t\\t};\\n\\t\\tconst onEnd = () => {\\n\\t\\t\\tif (this._camera) {\\n\\t\\t\\t\\tthis._camera.off(\\\"set_nearClip\\\", onClipPlanesChange);\\n\\t\\t\\t\\tthis._camera.off(\\\"set_farClip\\\", onClipPlanesChange);\\n\\t\\t\\t\\tthis._camera.camera.xr = null;\\n\\t\\t\\t\\tthis._camera = null;\\n\\t\\t\\t}\\n\\t\\t\\tsession.removeEventListener(\\\"end\\\", onEnd);\\n\\t\\t\\tsession.removeEventListener(\\\"visibilitychange\\\", onVisibilityChange);\\n\\t\\t\\tsession.removeEventListener(\\\"frameratechange\\\", onFrameRateChange);\\n\\t\\t\\tif (!failed) this.fire(\\\"end\\\");\\n\\t\\t\\tif (this.xrBridge) {\\n\\t\\t\\t\\tthis.xrBridge.destroy();\\n\\t\\t\\t\\tthis.xrBridge = null;\\n\\t\\t\\t}\\n\\t\\t\\tthis._session = null;\\n\\t\\t\\tthis._referenceSpace = null;\\n\\t\\t\\tthis._width = 0;\\n\\t\\t\\tthis._height = 0;\\n\\t\\t\\tthis._type = null;\\n\\t\\t\\tthis._spaceType = null;\\n\\t\\t\\tif (this.app.systems) {\\n\\t\\t\\t\\tthis.app.requestAnimationFrame();\\n\\t\\t\\t}\\n\\t\\t};\\n\\t\\tsession.addEventListener(\\\"end\\\", onEnd);\\n\\t\\tsession.addEventListener(\\\"visibilitychange\\\", onVisibilityChange);\\n\\t\\tthis._camera.on(\\\"set_nearClip\\\", onClipPlanesChange);\\n\\t\\tthis._camera.on(\\\"set_farClip\\\", onClipPlanesChange);\\n\\t\\tconst gd = this.app.graphicsDevice;\\n\\t\\tconst framebufferScaleFactor = gd.maxPixelRatio / window.devicePixelRatio * this._framebufferScaleFactor;\\n\\t\\tthis.xrBridge.attachPresentation(this._session, {\\n\\t\\t\\tframebufferScaleFactor,\\n\\t\\t\\tdepthNear: this._depthNear,\\n\\t\\t\\tdepthFar: this._depthFar,\\n\\t\\t\\tonBindingError: (ex) => {\\n\\t\\t\\t\\tthis.fire(\\\"error\\\", ex);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tif (this.session.supportedFrameRates) {\\n\\t\\t\\tthis._supportedFrameRates = Array.from(this.session.supportedFrameRates);\\n\\t\\t} else {\\n\\t\\t\\tthis._supportedFrameRates = null;\\n\\t\\t}\\n\\t\\tthis._session.addEventListener(\\\"frameratechange\\\", onFrameRateChange);\\n\\t\\tsession.requestReferenceSpace(spaceType).then((referenceSpace) => {\\n\\t\\t\\tthis._referenceSpace = referenceSpace;\\n\\t\\t\\tthis.app.requestAnimationFrame();\\n\\t\\t\\tif (callback) callback(null);\\n\\t\\t\\tthis.fire(\\\"start\\\");\\n\\t\\t}).catch((ex) => {\\n\\t\\t\\tfailed = true;\\n\\t\\t\\tsession.end();\\n\\t\\t\\tif (callback) callback(ex);\\n\\t\\t\\tthis.fire(\\\"error\\\", ex);\\n\\t\\t});\\n\\t}\\n\\t_setClipPlanes(near, far) {\\n\\t\\tif (this._depthNear === near && this._depthFar === far) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._depthNear = near;\\n\\t\\tthis._depthFar = far;\\n\\t\\tif (!this._session) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._session.updateRenderState({\\n\\t\\t\\tdepthNear: this._depthNear,\\n\\t\\t\\tdepthFar: this._depthFar\\n\\t\\t});\\n\\t}\\n\\tupdate(frame) {\\n\\t\\tif (!this._session) return false;\\n\\t\\tthis.xrBridge.getFramebufferSize(frame, this._framebufferSize);\\n\\t\\tconst width = this._framebufferSize.x;\\n\\t\\tconst height = this._framebufferSize.y;\\n\\t\\tif (this._width !== width || this._height !== height) {\\n\\t\\t\\tthis._width = width;\\n\\t\\t\\tthis._height = height;\\n\\t\\t\\tthis.app.graphicsDevice.setResolution(width, height);\\n\\t\\t}\\n\\t\\tconst pose = frame.getViewerPose(this._referenceSpace);\\n\\t\\tif (!pose) return false;\\n\\t\\tconst lengthOld = this.views.list.length;\\n\\t\\tthis.views.update(frame, pose.views);\\n\\t\\tconst posePosition = pose.transform.position;\\n\\t\\tconst poseOrientation = pose.transform.orientation;\\n\\t\\tthis._localPosition.set(posePosition.x, posePosition.y, posePosition.z);\\n\\t\\tthis._localRotation.set(poseOrientation.x, poseOrientation.y, poseOrientation.z, poseOrientation.w);\\n\\t\\tif (lengthOld === 0 && this.views.list.length > 0) {\\n\\t\\t\\tconst viewProjMat = new Mat4();\\n\\t\\t\\tconst view = this.views.list[0];\\n\\t\\t\\tviewProjMat.copy(view.projMat);\\n\\t\\t\\tconst data = viewProjMat.data;\\n\\t\\t\\tconst fov = 2 * Math.atan(1 / data[5]) * 180 / Math.PI;\\n\\t\\t\\tconst aspectRatio = data[5] / data[0];\\n\\t\\t\\tconst farClip = data[14] / (data[10] + 1);\\n\\t\\t\\tconst nearClip = data[14] / (data[10] - 1);\\n\\t\\t\\tconst horizontalFov = false;\\n\\t\\t\\tconst camera = this._camera.camera;\\n\\t\\t\\tcamera.setXrProperties({\\n\\t\\t\\t\\taspectRatio,\\n\\t\\t\\t\\tfarClip,\\n\\t\\t\\t\\tfov,\\n\\t\\t\\t\\thorizontalFov,\\n\\t\\t\\t\\tnearClip\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tthis._camera.camera._node.setLocalPosition(this._localPosition);\\n\\t\\tthis._camera.camera._node.setLocalRotation(this._localRotation);\\n\\t\\tthis.input.update(frame);\\n\\t\\tif (this._type === XRTYPE_AR) {\\n\\t\\t\\tif (this.hitTest.supported) {\\n\\t\\t\\t\\tthis.hitTest.update(frame);\\n\\t\\t\\t}\\n\\t\\t\\tif (this.lightEstimation.supported) {\\n\\t\\t\\t\\tthis.lightEstimation.update(frame);\\n\\t\\t\\t}\\n\\t\\t\\tif (this.imageTracking.supported) {\\n\\t\\t\\t\\tthis.imageTracking.update(frame);\\n\\t\\t\\t}\\n\\t\\t\\tif (this.anchors.supported) {\\n\\t\\t\\t\\tthis.anchors.update(frame);\\n\\t\\t\\t}\\n\\t\\t\\tif (this.planeDetection.supported) {\\n\\t\\t\\t\\tthis.planeDetection.update(frame);\\n\\t\\t\\t}\\n\\t\\t\\tif (this.meshDetection.supported) {\\n\\t\\t\\t\\tthis.meshDetection.update(frame);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.fire(\\\"update\\\", frame);\\n\\t\\tthis.xrBridge.beginFrame(frame, this._referenceSpace);\\n\\t\\treturn true;\\n\\t}\\n\\tget supported() {\\n\\t\\treturn this._supported;\\n\\t}\\n\\tget active() {\\n\\t\\treturn !!this._session;\\n\\t}\\n\\tget type() {\\n\\t\\treturn this._type;\\n\\t}\\n\\tget spaceType() {\\n\\t\\treturn this._spaceType;\\n\\t}\\n\\tget session() {\\n\\t\\treturn this._session;\\n\\t}\\n\\tget frameRate() {\\n\\t\\treturn this._session?.frameRate ?? null;\\n\\t}\\n\\tget supportedFrameRates() {\\n\\t\\treturn this._supportedFrameRates;\\n\\t}\\n\\tget framebufferScaleFactor() {\\n\\t\\treturn this._framebufferScaleFactor;\\n\\t}\\n\\tset fixedFoveation(value) {\\n\\t\\tconst layer = this.xrBridge?.presentationLayer;\\n\\t\\tif ((layer?.fixedFoveation ?? null) !== null) {\\n\\t\\t\\tif (this.app.graphicsDevice.samples > 1) ;\\n\\t\\t\\tlayer.fixedFoveation = value;\\n\\t\\t}\\n\\t}\\n\\tget fixedFoveation() {\\n\\t\\tconst layer = this.xrBridge?.presentationLayer;\\n\\t\\treturn layer?.fixedFoveation ?? null;\\n\\t}\\n\\tget camera() {\\n\\t\\treturn this._camera ? this._camera.entity : null;\\n\\t}\\n\\tget visibilityState() {\\n\\t\\tif (!this._session) {\\n\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\treturn this._session.visibilityState;\\n\\t}\\n}\\n\\nconst tempMeshInstances$1 = [];\\nconst lights = [[], [], []];\\nconst defaultShadowAtlasParams = new Float32Array(2);\\nclass RenderPassPicker extends RenderPass {\\n\\tviewBindGroups = [];\\n\\tblendState = BlendState.NOBLEND;\\n\\tcamera;\\n\\tscene;\\n\\tlayers;\\n\\tmapping;\\n\\tdepth;\\n\\t_qualifiedLayerIndices = [];\\n\\t_pickMeshInstances = /* @__PURE__ */ new Map();\\n\\tconstructor(device, renderer) {\\n\\t\\tsuper(device);\\n\\t\\tthis.renderer = renderer;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.viewBindGroups.forEach((bg) => {\\n\\t\\t\\tbg.defaultUniformBuffer.destroy();\\n\\t\\t\\tbg.destroy();\\n\\t\\t});\\n\\t\\tthis.viewBindGroups.length = 0;\\n\\t}\\n\\tupdate(camera, scene, layers, mapping, depth) {\\n\\t\\tthis.camera = camera;\\n\\t\\tthis.scene = scene;\\n\\t\\tthis.layers = layers;\\n\\t\\tthis.mapping = mapping;\\n\\t\\tthis.depth = depth;\\n\\t\\tif (scene.clusteredLightingEnabled) {\\n\\t\\t\\tthis.emptyWorldClusters = this.renderer.worldClustersAllocator.empty;\\n\\t\\t}\\n\\t}\\n\\t// Filter qualifying layers and prepare gsplat pick mesh instances for the compute-based\\n\\t// renderer. The execute() loop iterates the pre-built list instead of re-filtering.\\n\\tbefore() {\\n\\t\\tthis._qualifiedLayerIndices.length = 0;\\n\\t\\tthis._pickMeshInstances.clear();\\n\\t\\tconst { camera, scene, layers } = this;\\n\\t\\tconst srcLayers = scene.layers.layerList;\\n\\t\\tconst subLayerEnabled = scene.layers.subLayerEnabled;\\n\\t\\tconst gsplatDirector = this.renderer.gsplatDirector;\\n\\t\\tconst pickerWidth = this.renderTarget?.width ?? 1;\\n\\t\\tconst pickerHeight = this.renderTarget?.height ?? 1;\\n\\t\\tfor (let i = 0; i < srcLayers.length; i++) {\\n\\t\\t\\tconst srcLayer = srcLayers[i];\\n\\t\\t\\tif (layers && layers.indexOf(srcLayer) < 0) continue;\\n\\t\\t\\tif (!srcLayer.enabled || !subLayerEnabled[i]) continue;\\n\\t\\t\\tif (!srcLayer.camerasSet.has(camera.camera)) continue;\\n\\t\\t\\tthis._qualifiedLayerIndices.push(i);\\n\\t\\t\\tif (gsplatDirector) {\\n\\t\\t\\t\\tconst pickMI = gsplatDirector.prepareForPicking(camera.camera, pickerWidth, pickerHeight, srcLayer);\\n\\t\\t\\t\\tif (pickMI) {\\n\\t\\t\\t\\t\\tthis._pickMeshInstances.set(i, pickMI);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\texecute() {\\n\\t\\tconst device = this.device;\\n\\t\\tconst { renderer, camera, scene, mapping, renderTarget } = this;\\n\\t\\tconst srcLayers = scene.layers.layerList;\\n\\t\\tconst isTransparent = scene.layers.subLayerList;\\n\\t\\tfor (const i of this._qualifiedLayerIndices) {\\n\\t\\t\\tconst srcLayer = srcLayers[i];\\n\\t\\t\\tconst transparent = isTransparent[i];\\n\\t\\t\\tif (srcLayer._clearDepthBuffer) {\\n\\t\\t\\t\\trenderer.clear(camera.camera, false, true, false);\\n\\t\\t\\t}\\n\\t\\t\\tconst meshInstances = srcLayer.meshInstances;\\n\\t\\t\\tfor (let j = 0; j < meshInstances.length; j++) {\\n\\t\\t\\t\\tconst meshInstance = meshInstances[j];\\n\\t\\t\\t\\tif (meshInstance.pick && meshInstance.transparent === transparent) {\\n\\t\\t\\t\\t\\ttempMeshInstances$1.push(meshInstance);\\n\\t\\t\\t\\t\\tmapping.set(meshInstance.id, meshInstance);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tconst pickMI = this._pickMeshInstances.get(i);\\n\\t\\t\\tif (pickMI) {\\n\\t\\t\\t\\ttempMeshInstances$1.push(pickMI);\\n\\t\\t\\t}\\n\\t\\t\\tif (scene.gsplat.enableIds) {\\n\\t\\t\\t\\tconst placements = srcLayer.gsplatPlacements;\\n\\t\\t\\t\\tfor (let j = 0; j < placements.length; j++) {\\n\\t\\t\\t\\t\\tconst placement = placements[j];\\n\\t\\t\\t\\t\\tconst component = placement.node?.gsplat;\\n\\t\\t\\t\\t\\tif (component) {\\n\\t\\t\\t\\t\\t\\tmapping.set(placement.id, component);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (tempMeshInstances$1.length > 0) {\\n\\t\\t\\t\\tconst clusteredLightingEnabled = scene.clusteredLightingEnabled;\\n\\t\\t\\t\\tif (clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\tconst lightClusters = this.emptyWorldClusters;\\n\\t\\t\\t\\t\\tlightClusters.activate();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\trenderer.setCameraUniforms(camera.camera, renderTarget);\\n\\t\\t\\t\\trenderer.dispatchGlobalLights(scene);\\n\\t\\t\\t\\tdevice.scope.resolve(\\\"shadowAtlasParams\\\").setValue(defaultShadowAtlasParams);\\n\\t\\t\\t\\tif (device.supportsUniformBuffers) {\\n\\t\\t\\t\\t\\trenderer.initViewBindGroupFormat(clusteredLightingEnabled);\\n\\t\\t\\t\\t\\trenderer.setupViewUniformBuffers(this.viewBindGroups, renderer.viewUniformFormat, renderer.viewBindGroupFormat, null);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst shaderPass = this.depth ? SHADER_DEPTH_PICK : SHADER_PICK;\\n\\t\\t\\t\\trenderer.renderForward(camera.camera, renderTarget, tempMeshInstances$1, lights, shaderPass, (meshInstance) => {\\n\\t\\t\\t\\t\\tdevice.setBlendState(this.blendState);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\ttempMeshInstances$1.length = 0;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n}\\n\\nVec2.prototype.scale = Vec2.prototype.mulScalar;\\nVec3.prototype.scale = Vec3.prototype.mulScalar;\\nVec4.prototype.scale = Vec4.prototype.mulScalar;\\nnew Vec4();\\nObject.defineProperties(RenderTarget.prototype, {\\n\\t_glFrameBuffer: {\\n\\t\\tget: function() {\\n\\t\\t\\treturn this.impl._glFrameBuffer;\\n\\t\\t},\\n\\t\\tset: function(rgbm) {\\n\\t\\t}\\n\\t}\\n});\\nObject.defineProperty(VertexFormat, \\\"defaultInstancingFormat\\\", {\\n\\tget: function() {\\n\\t\\treturn null;\\n\\t}\\n});\\nObject.defineProperties(Texture.prototype, {\\n\\trgbm: {\\n\\t\\tget: function() {\\n\\t\\t\\treturn this.type === TEXTURETYPE_RGBM;\\n\\t\\t},\\n\\t\\tset: function(rgbm) {\\n\\t\\t\\tthis.type = rgbm ? TEXTURETYPE_RGBM : TEXTURETYPE_DEFAULT;\\n\\t\\t}\\n\\t},\\n\\tswizzleGGGR: {\\n\\t\\tget: function() {\\n\\t\\t\\treturn this.type === TEXTURETYPE_SWIZZLEGGGR;\\n\\t\\t},\\n\\t\\tset: function(swizzleGGGR) {\\n\\t\\t\\tthis.type = swizzleGGGR ? TEXTURETYPE_SWIZZLEGGGR : TEXTURETYPE_DEFAULT;\\n\\t\\t}\\n\\t},\\n\\t_glTexture: {\\n\\t\\tget: function() {\\n\\t\\t\\treturn this.impl._glTexture;\\n\\t\\t}\\n\\t}\\n});\\nObject.defineProperty(GraphicsDevice.prototype, \\\"boneLimit\\\", {\\n\\tget: function() {\\n\\t\\treturn 1024;\\n\\t}\\n});\\nObject.defineProperty(GraphicsDevice.prototype, \\\"webgl2\\\", {\\n\\tget: function() {\\n\\t\\treturn this.isWebGL2;\\n\\t}\\n});\\nObject.defineProperty(GraphicsDevice.prototype, \\\"textureFloatHighPrecision\\\", {\\n\\tget: function() {\\n\\t\\treturn true;\\n\\t}\\n});\\nObject.defineProperty(GraphicsDevice.prototype, \\\"extBlendMinmax\\\", {\\n\\tget: function() {\\n\\t\\treturn true;\\n\\t}\\n});\\nObject.defineProperty(GraphicsDevice.prototype, \\\"extTextureHalfFloat\\\", {\\n\\tget: function() {\\n\\t\\treturn true;\\n\\t}\\n});\\nObject.defineProperty(GraphicsDevice.prototype, \\\"extTextureLod\\\", {\\n\\tget: function() {\\n\\t\\treturn true;\\n\\t}\\n});\\nObject.defineProperty(GraphicsDevice.prototype, \\\"textureHalfFloatFilterable\\\", {\\n\\tget: function() {\\n\\t\\treturn true;\\n\\t}\\n});\\nObject.defineProperty(GraphicsDevice.prototype, \\\"supportsMrt\\\", {\\n\\tget: function() {\\n\\t\\treturn true;\\n\\t}\\n});\\nObject.defineProperty(GraphicsDevice.prototype, \\\"supportsVolumeTextures\\\", {\\n\\tget: function() {\\n\\t\\treturn true;\\n\\t}\\n});\\nObject.defineProperty(GraphicsDevice.prototype, \\\"supportsInstancing\\\", {\\n\\tget: function() {\\n\\t\\treturn true;\\n\\t}\\n});\\nObject.defineProperty(GraphicsDevice.prototype, \\\"textureHalfFloatUpdatable\\\", {\\n\\tget: function() {\\n\\t\\treturn true;\\n\\t}\\n});\\nObject.defineProperty(GraphicsDevice.prototype, \\\"extTextureFloat\\\", {\\n\\tget: function() {\\n\\t\\treturn true;\\n\\t}\\n});\\nObject.defineProperty(GraphicsDevice.prototype, \\\"extStandardDerivatives\\\", {\\n\\tget: function() {\\n\\t\\treturn true;\\n\\t}\\n});\\nBlendState.DEFAULT = Object.freeze(new BlendState());\\nconst _tempBlendState = new BlendState();\\nconst _tempDepthState = new DepthState();\\nGraphicsDevice.prototype.setBlendFunction = function(blendSrc, blendDst) {\\n\\tconst currentBlendState = this.blendState;\\n\\t_tempBlendState.copy(currentBlendState);\\n\\t_tempBlendState.setColorBlend(currentBlendState.colorOp, blendSrc, blendDst);\\n\\t_tempBlendState.setAlphaBlend(currentBlendState.alphaOp, blendSrc, blendDst);\\n\\tthis.setBlendState(_tempBlendState);\\n};\\nGraphicsDevice.prototype.setBlendFunctionSeparate = function(blendSrc, blendDst, blendSrcAlpha, blendDstAlpha) {\\n\\tconst currentBlendState = this.blendState;\\n\\t_tempBlendState.copy(currentBlendState);\\n\\t_tempBlendState.setColorBlend(currentBlendState.colorOp, blendSrc, blendDst);\\n\\t_tempBlendState.setAlphaBlend(currentBlendState.alphaOp, blendSrcAlpha, blendDstAlpha);\\n\\tthis.setBlendState(_tempBlendState);\\n};\\nGraphicsDevice.prototype.setBlendEquation = function(blendEquation) {\\n\\tconst currentBlendState = this.blendState;\\n\\t_tempBlendState.copy(currentBlendState);\\n\\t_tempBlendState.setColorBlend(blendEquation, currentBlendState.colorSrcFactor, currentBlendState.colorDstFactor);\\n\\t_tempBlendState.setAlphaBlend(blendEquation, currentBlendState.alphaSrcFactor, currentBlendState.alphaDstFactor);\\n\\tthis.setBlendState(_tempBlendState);\\n};\\nGraphicsDevice.prototype.setBlendEquationSeparate = function(blendEquation, blendAlphaEquation) {\\n\\tconst currentBlendState = this.blendState;\\n\\t_tempBlendState.copy(currentBlendState);\\n\\t_tempBlendState.setColorBlend(blendEquation, currentBlendState.colorSrcFactor, currentBlendState.colorDstFactor);\\n\\t_tempBlendState.setAlphaBlend(blendAlphaEquation, currentBlendState.alphaSrcFactor, currentBlendState.alphaDstFactor);\\n\\tthis.setBlendState(_tempBlendState);\\n};\\nGraphicsDevice.prototype.setColorWrite = function(redWrite, greenWrite, blueWrite, alphaWrite) {\\n\\tconst currentBlendState = this.blendState;\\n\\t_tempBlendState.copy(currentBlendState);\\n\\t_tempBlendState.setColorWrite(redWrite, greenWrite, blueWrite, alphaWrite);\\n\\tthis.setBlendState(_tempBlendState);\\n};\\nGraphicsDevice.prototype.getBlending = function() {\\n\\treturn this.blendState.blend;\\n};\\nGraphicsDevice.prototype.setBlending = function(blending) {\\n\\t_tempBlendState.copy(this.blendState);\\n\\t_tempBlendState.blend = blending;\\n\\tthis.setBlendState(_tempBlendState);\\n};\\nGraphicsDevice.prototype.setDepthWrite = function(write) {\\n\\t_tempDepthState.copy(this.depthState);\\n\\t_tempDepthState.write = write;\\n\\tthis.setDepthState(_tempDepthState);\\n};\\nGraphicsDevice.prototype.setDepthFunc = function(func) {\\n\\t_tempDepthState.copy(this.depthState);\\n\\t_tempDepthState.func = func;\\n\\tthis.setDepthState(_tempDepthState);\\n};\\nGraphicsDevice.prototype.setDepthTest = function(test) {\\n\\t_tempDepthState.copy(this.depthState);\\n\\t_tempDepthState.test = test;\\n\\tthis.setDepthState(_tempDepthState);\\n};\\nGraphicsDevice.prototype.getCullMode = function() {\\n\\treturn this.cullMode;\\n};\\nnew Proxy({}, {\\n\\tget(target, prop) {\\n\\t\\treturn ShaderChunks.get(getApplication().graphicsDevice, SHADERLANGUAGE_GLSL).get(prop);\\n\\t},\\n\\tset(target, prop, value) {\\n\\t\\tShaderChunks.get(getApplication().graphicsDevice, SHADERLANGUAGE_GLSL).set(prop, value);\\n\\t\\treturn true;\\n\\t}\\n});\\nObject.defineProperty(Scene.prototype, \\\"defaultMaterial\\\", {\\n\\tget: function() {\\n\\t\\treturn getDefaultMaterial(getApplication().graphicsDevice);\\n\\t}\\n});\\nObject.defineProperty(Scene.prototype, \\\"fogColor\\\", {\\n\\tset: function(value) {\\n\\t\\tthis.fog.color = value;\\n\\t},\\n\\tget: function() {\\n\\t\\treturn this.fog.color;\\n\\t}\\n});\\nObject.defineProperty(Scene.prototype, \\\"fogEnd\\\", {\\n\\tset: function(value) {\\n\\t\\tthis.fog.end = value;\\n\\t},\\n\\tget: function() {\\n\\t\\treturn this.fog.end;\\n\\t}\\n});\\nObject.defineProperty(Scene.prototype, \\\"fogStart\\\", {\\n\\tset: function(value) {\\n\\t\\tthis.fog.start = value;\\n\\t},\\n\\tget: function() {\\n\\t\\treturn this.fog.start;\\n\\t}\\n});\\nObject.defineProperty(Scene.prototype, \\\"fogDensity\\\", {\\n\\tset: function(value) {\\n\\t\\tthis.fog.density = value;\\n\\t},\\n\\tget: function() {\\n\\t\\treturn this.fog.density;\\n\\t}\\n});\\nObject.defineProperty(Scene.prototype, \\\"toneMapping\\\", {\\n\\tset: function(value) {\\n\\t},\\n\\tget: function() {\\n\\t\\treturn void 0;\\n\\t}\\n});\\nObject.defineProperty(Scene.prototype, \\\"gammaCorrection\\\", {\\n\\tset: function(value) {\\n\\t},\\n\\tget: function() {\\n\\t\\treturn void 0;\\n\\t}\\n});\\nObject.defineProperty(Scene.prototype, \\\"rendering\\\", {\\n\\tset: function(value) {\\n\\t},\\n\\tget: function() {\\n\\t\\treturn void 0;\\n\\t}\\n});\\nObject.defineProperty(LayerComposition.prototype, \\\"_meshInstances\\\", {\\n\\tget: function() {\\n\\t\\treturn null;\\n\\t}\\n});\\nObject.defineProperty(Scene.prototype, \\\"drawCalls\\\", {\\n\\tget: function() {\\n\\t\\treturn null;\\n\\t}\\n});\\n[\\\"128\\\", \\\"64\\\", \\\"32\\\", \\\"16\\\", \\\"8\\\", \\\"4\\\"].forEach((size, index) => {\\n\\tObject.defineProperty(Scene.prototype, `skyboxPrefiltered${size}`, {\\n\\t\\tget: function() {\\n\\t\\t\\treturn this._prefilteredCubemaps[index];\\n\\t\\t},\\n\\t\\tset: function(value) {\\n\\t\\t\\tthis._prefilteredCubemaps[index] = value;\\n\\t\\t\\tthis.updateShaders = true;\\n\\t\\t}\\n\\t});\\n});\\nObject.defineProperty(Scene.prototype, \\\"models\\\", {\\n\\tget: function() {\\n\\t\\tif (!this._models) {\\n\\t\\t\\tthis._models = [];\\n\\t\\t}\\n\\t\\treturn this._models;\\n\\t}\\n});\\nfunction _removedClassProperty(targetClass, name, comment = \\\"\\\") {\\n\\tObject.defineProperty(targetClass.prototype, name, {\\n\\t\\tset: function(value) {\\n\\t\\t},\\n\\t\\tget: function() {\\n\\t\\t\\treturn void 0;\\n\\t\\t}\\n\\t});\\n}\\n_removedClassProperty(Layer, \\\"renderTarget\\\");\\n_removedClassProperty(Layer, \\\"onPreCull\\\");\\n_removedClassProperty(Layer, \\\"onPreRender\\\");\\n_removedClassProperty(Layer, \\\"onPreRenderOpaque\\\");\\n_removedClassProperty(Layer, \\\"onPreRenderTransparent\\\");\\n_removedClassProperty(Layer, \\\"onPostCull\\\");\\n_removedClassProperty(Layer, \\\"onPostRender\\\");\\n_removedClassProperty(Layer, \\\"onPostRenderOpaque\\\");\\n_removedClassProperty(Layer, \\\"onPostRenderTransparent\\\");\\n_removedClassProperty(Layer, \\\"onDrawCall\\\");\\n_removedClassProperty(Layer, \\\"layerReference\\\");\\n_removedClassProperty(CameraComponent, \\\"onPreCull\\\", \\\"Use Scene#EVENT_PRECULL event instead.\\\");\\n_removedClassProperty(CameraComponent, \\\"onPostCull\\\", \\\"Use Scene#EVENT_POSTCULL event instead.\\\");\\n_removedClassProperty(CameraComponent, \\\"onPreRender\\\", \\\"Use Scene#EVENT_PRERENDER event instead.\\\");\\n_removedClassProperty(CameraComponent, \\\"onPostRender\\\", \\\"Use Scene#EVENT_POSTRENDER event instead.\\\");\\n_removedClassProperty(CameraComponent, \\\"onPreRenderLayer\\\", \\\"Use Scene#EVENT_PRERENDER_LAYER event instead.\\\");\\n_removedClassProperty(CameraComponent, \\\"onPostRenderLayer\\\", \\\"Use Scene#EVENT_POSTRENDER_LAYER event instead.\\\");\\nForwardRenderer.prototype.renderComposition = function(comp) {\\n\\tgetApplication().renderComposition(comp);\\n};\\nMeshInstance.prototype.syncAabb = function() {\\n};\\nMorph.prototype.getTarget = function(index) {\\n\\treturn this.targets[index];\\n};\\nGraphNode.prototype.getChildren = function() {\\n\\treturn this.children;\\n};\\nGraphNode.prototype.getName = function() {\\n\\treturn this.name;\\n};\\nGraphNode.prototype.getPath = function() {\\n\\treturn this.path;\\n};\\nGraphNode.prototype.getRoot = function() {\\n\\treturn this.root;\\n};\\nGraphNode.prototype.getParent = function() {\\n\\treturn this.parent;\\n};\\nGraphNode.prototype.setName = function(name) {\\n\\tthis.name = name;\\n};\\nObject.defineProperty(Material.prototype, \\\"shader\\\", {\\n\\tset: function(value) {\\n\\t},\\n\\tget: function() {\\n\\t\\treturn null;\\n\\t}\\n});\\nObject.defineProperty(Material.prototype, \\\"blend\\\", {\\n\\tset: function(value) {\\n\\t\\tthis.blendState.blend = value;\\n\\t},\\n\\tget: function() {\\n\\t\\treturn this.blendState.blend;\\n\\t}\\n});\\nObject.defineProperty(StandardMaterial.prototype, \\\"shininess\\\", {\\n\\tget: function() {\\n\\t\\treturn this.gloss * 100;\\n\\t},\\n\\tset: function(value) {\\n\\t\\tthis.gloss = value * 0.01;\\n\\t}\\n});\\nObject.defineProperty(StandardMaterial.prototype, \\\"useGammaTonemap\\\", {\\n\\tget: function() {\\n\\t\\treturn this.useTonemap;\\n\\t},\\n\\tset: function(value) {\\n\\t\\tthis.useTonemap = value;\\n\\t}\\n});\\nObject.defineProperty(StandardMaterial.prototype, \\\"anisotropy\\\", {\\n\\tget: function() {\\n\\t\\tconst sign = Math.sign(Math.cos(this.anisotropyRotation * math.DEG_TO_RAD * 2));\\n\\t\\treturn this.anisotropyIntensity * sign;\\n\\t},\\n\\tset: function(value) {\\n\\t\\tthis.anisotropyIntensity = Math.abs(value);\\n\\t\\tif (value >= 0) {\\n\\t\\t\\tthis.anisotropyRotation = 0;\\n\\t\\t} else {\\n\\t\\t\\tthis.anisotropyRotation = 90;\\n\\t\\t}\\n\\t}\\n});\\nfunction _defineAlias(newName, oldName) {\\n\\tObject.defineProperty(StandardMaterial.prototype, oldName, {\\n\\t\\tget: function() {\\n\\t\\t\\treturn this[newName];\\n\\t\\t},\\n\\t\\tset: function(value) {\\n\\t\\t\\tthis[newName] = value;\\n\\t\\t}\\n\\t});\\n}\\nfunction _deprecateTint(name) {\\n\\tObject.defineProperty(StandardMaterial.prototype, name, {\\n\\t\\tget: function() {\\n\\t\\t\\treturn true;\\n\\t\\t},\\n\\t\\tset: function(value) {\\n\\t\\t}\\n\\t});\\n}\\n_deprecateTint(\\\"sheenTint\\\");\\n_deprecateTint(\\\"diffuseTint\\\");\\n_deprecateTint(\\\"emissiveTint\\\");\\n_deprecateTint(\\\"ambientTint\\\");\\n_defineAlias(\\\"specularTint\\\", \\\"specularMapTint\\\");\\n_defineAlias(\\\"aoVertexColor\\\", \\\"aoMapVertexColor\\\");\\n_defineAlias(\\\"diffuseVertexColor\\\", \\\"diffuseMapVertexColor\\\");\\n_defineAlias(\\\"specularVertexColor\\\", \\\"specularMapVertexColor\\\");\\n_defineAlias(\\\"emissiveVertexColor\\\", \\\"emissiveMapVertexColor\\\");\\n_defineAlias(\\\"metalnessVertexColor\\\", \\\"metalnessMapVertexColor\\\");\\n_defineAlias(\\\"glossVertexColor\\\", \\\"glossMapVertexColor\\\");\\n_defineAlias(\\\"opacityVertexColor\\\", \\\"opacityMapVertexColor\\\");\\n_defineAlias(\\\"lightVertexColor\\\", \\\"lightMapVertexColor\\\");\\n_defineAlias(\\\"sheenGloss\\\", \\\"sheenGlossiess\\\");\\n_defineAlias(\\\"clearCoatGloss\\\", \\\"clearCostGlossiness\\\");\\nfunction _defineOption(name, newName) {\\n\\tif (name !== \\\"pass\\\") {\\n\\t\\tObject.defineProperty(StandardMaterialOptions.prototype, name, {\\n\\t\\t\\tget: function() {\\n\\t\\t\\t\\treturn this.litOptions[newName || name];\\n\\t\\t\\t},\\n\\t\\t\\tset: function(value) {\\n\\t\\t\\t\\tthis.litOptions[newName || name] = value;\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n}\\n_defineOption(\\\"refraction\\\", \\\"useRefraction\\\");\\nconst tempOptions = new LitShaderOptions();\\nconst litOptionProperties = Object.getOwnPropertyNames(tempOptions);\\nfor (const litOption in litOptionProperties) {\\n\\t_defineOption(litOptionProperties[litOption]);\\n}\\nAssetRegistry.prototype.getAssetById = function(id) {\\n\\treturn this.get(id);\\n};\\nObject.defineProperty(XrInputSource.prototype, \\\"ray\\\", {\\n\\tget: function() {\\n\\t\\treturn this._rayLocal;\\n\\t}\\n});\\nObject.defineProperty(XrInputSource.prototype, \\\"position\\\", {\\n\\tget: function() {\\n\\t\\treturn this._localPosition;\\n\\t}\\n});\\nObject.defineProperty(XrInputSource.prototype, \\\"rotation\\\", {\\n\\tget: function() {\\n\\t\\treturn this._localRotation;\\n\\t}\\n});\\nObject.defineProperty(MouseEvent$1.prototype, \\\"wheel\\\", {\\n\\tget: function() {\\n\\t\\treturn this.wheelDelta * -2;\\n\\t}\\n});\\nAppBase.prototype.isFullscreen = function() {\\n\\treturn !!document.fullscreenElement;\\n};\\nAppBase.prototype.enableFullscreen = function(element, success, error) {\\n\\telement = element || this.graphicsDevice.canvas;\\n\\tconst s = function() {\\n\\t\\tsuccess();\\n\\t\\tdocument.removeEventListener(\\\"fullscreenchange\\\", s);\\n\\t};\\n\\tconst e = function() {\\n\\t\\terror();\\n\\t\\tdocument.removeEventListener(\\\"fullscreenerror\\\", e);\\n\\t};\\n\\tif (success) {\\n\\t\\tdocument.addEventListener(\\\"fullscreenchange\\\", s, false);\\n\\t}\\n\\tif (error) {\\n\\t\\tdocument.addEventListener(\\\"fullscreenerror\\\", e, false);\\n\\t}\\n\\tif (element.requestFullscreen) {\\n\\t\\telement.requestFullscreen(Element.ALLOW_KEYBOARD_INPUT);\\n\\t} else {\\n\\t\\terror();\\n\\t}\\n};\\nAppBase.prototype.disableFullscreen = function(success) {\\n\\tconst s = function() {\\n\\t\\tsuccess();\\n\\t\\tdocument.removeEventListener(\\\"fullscreenchange\\\", s);\\n\\t};\\n\\tif (success) {\\n\\t\\tdocument.addEventListener(\\\"fullscreenchange\\\", s, false);\\n\\t}\\n\\tdocument.exitFullscreen();\\n};\\nAppBase.prototype.getSceneUrl = function(name) {\\n\\tconst entry = this.scenes.find(name);\\n\\tif (entry) {\\n\\t\\treturn entry.url;\\n\\t}\\n\\treturn null;\\n};\\nAppBase.prototype.loadScene = function(url, callback) {\\n\\tthis.scenes.loadScene(url, callback);\\n};\\nAppBase.prototype.loadSceneHierarchy = function(url, callback) {\\n\\tthis.scenes.loadSceneHierarchy(url, callback);\\n};\\nAppBase.prototype.loadSceneSettings = function(url, callback) {\\n\\tthis.scenes.loadSceneSettings(url, callback);\\n};\\nModelComponent.prototype.setVisible = function(visible) {\\n\\tthis.enabled = visible;\\n};\\nObject.defineProperty(RigidBodyComponent.prototype, \\\"bodyType\\\", {\\n\\tget: function() {\\n\\t\\treturn this.type;\\n\\t},\\n\\tset: function(type) {\\n\\t\\tthis.type = type;\\n\\t}\\n});\\nRigidBodyComponent.prototype.syncBodyToEntity = function() {\\n\\tthis._updateDynamic();\\n};\\nRigidBodyComponentSystem.prototype.setGravity = function() {\\n\\tif (arguments.length === 1) {\\n\\t\\tthis.gravity.copy(arguments[0]);\\n\\t} else {\\n\\t\\tthis.gravity.set(arguments[0], arguments[1], arguments[2]);\\n\\t}\\n};\\n\\nclass CpuTimer {\\n\\tconstructor(app) {\\n\\t\\tthis._frameIndex = 0;\\n\\t\\tthis._frameTimings = [];\\n\\t\\tthis._timings = [];\\n\\t\\tthis._prevTimings = [];\\n\\t\\tthis.unitsName = \\\"ms\\\";\\n\\t\\tthis.decimalPlaces = 1;\\n\\t\\tthis.enabled = true;\\n\\t\\tapp.on(\\\"frameupdate\\\", this.begin.bind(this, \\\"update\\\"));\\n\\t\\tapp.on(\\\"framerender\\\", this.mark.bind(this, \\\"render\\\"));\\n\\t\\tapp.on(\\\"frameend\\\", this.mark.bind(this, \\\"other\\\"));\\n\\t}\\n\\t// mark the beginning of the frame\\n\\tbegin(name) {\\n\\t\\tif (!this.enabled) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._frameIndex < this._frameTimings.length) {\\n\\t\\t\\tthis._frameTimings.splice(this._frameIndex);\\n\\t\\t}\\n\\t\\tconst tmp = this._prevTimings;\\n\\t\\tthis._prevTimings = this._timings;\\n\\t\\tthis._timings = this._frameTimings;\\n\\t\\tthis._frameTimings = tmp;\\n\\t\\tthis._frameIndex = 0;\\n\\t\\tthis.mark(name);\\n\\t}\\n\\t// mark\\n\\tmark(name) {\\n\\t\\tif (!this.enabled) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst timestamp = now();\\n\\t\\tif (this._frameIndex > 0) {\\n\\t\\t\\tconst prev = this._frameTimings[this._frameIndex - 1];\\n\\t\\t\\tprev[1] = timestamp - prev[1];\\n\\t\\t} else if (this._timings.length > 0) {\\n\\t\\t\\tconst prev = this._timings[this._timings.length - 1];\\n\\t\\t\\tprev[1] = timestamp - prev[1];\\n\\t\\t}\\n\\t\\tif (this._frameIndex >= this._frameTimings.length) {\\n\\t\\t\\tthis._frameTimings.push([name, timestamp]);\\n\\t\\t} else {\\n\\t\\t\\tconst timing = this._frameTimings[this._frameIndex];\\n\\t\\t\\ttiming[0] = name;\\n\\t\\t\\ttiming[1] = timestamp;\\n\\t\\t}\\n\\t\\tthis._frameIndex++;\\n\\t}\\n\\tget timings() {\\n\\t\\treturn this._timings.slice(0, -1).map((v) => v[1]);\\n\\t}\\n}\\n\\nclass GpuTimer {\\n\\tconstructor(device) {\\n\\t\\tthis.device = device;\\n\\t\\tif (device.gpuProfiler) {\\n\\t\\t\\tdevice.gpuProfiler.enabled = true;\\n\\t\\t}\\n\\t\\tthis.enabled = true;\\n\\t\\tthis.unitsName = \\\"ms\\\";\\n\\t\\tthis.decimalPlaces = 1;\\n\\t\\tthis._timings = [];\\n\\t}\\n\\tget timings() {\\n\\t\\tthis._timings[0] = this.device.gpuProfiler?._frameTime ?? 0;\\n\\t\\treturn this._timings;\\n\\t}\\n}\\n\\nclass StatsTimer {\\n\\tconstructor(app, statNames, decimalPlaces, unitsName, multiplier) {\\n\\t\\tthis.app = app;\\n\\t\\tthis.values = [];\\n\\t\\tthis.statNames = statNames;\\n\\t\\tthis.unitsName = unitsName;\\n\\t\\tthis.decimalPlaces = decimalPlaces;\\n\\t\\tthis.multiplier = multiplier || 1;\\n\\t\\tconst resolve = (path, obj) => {\\n\\t\\t\\treturn path.split(\\\".\\\").reduce((prev, curr) => {\\n\\t\\t\\t\\tif (!prev) return null;\\n\\t\\t\\t\\tif (prev instanceof Map) {\\n\\t\\t\\t\\t\\treturn prev.get(curr);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn prev[curr];\\n\\t\\t\\t}, obj || this);\\n\\t\\t};\\n\\t\\tapp.on(\\\"frameupdate\\\", (ms) => {\\n\\t\\t\\tfor (let i = 0; i < this.statNames.length; i++) {\\n\\t\\t\\t\\tconst value = resolve(this.statNames[i], this.app.stats);\\n\\t\\t\\t\\tthis.values[i] = (value ?? 0) * this.multiplier;\\n\\t\\t\\t}\\n\\t\\t});\\n\\t}\\n\\tget timings() {\\n\\t\\treturn this.values;\\n\\t}\\n}\\n\\nclass Graph {\\n\\tconstructor(name, app, watermark, textRefreshRate, timer) {\\n\\t\\tthis.app = app;\\n\\t\\tthis.name = name;\\n\\t\\tthis.device = app.graphicsDevice;\\n\\t\\tthis.timer = timer;\\n\\t\\tthis.watermark = watermark;\\n\\t\\tthis.enabled = false;\\n\\t\\tthis.textRefreshRate = textRefreshRate;\\n\\t\\tthis.avgTotal = 0;\\n\\t\\tthis.avgTimer = 0;\\n\\t\\tthis.avgCount = 0;\\n\\t\\tthis.maxValue = 0;\\n\\t\\tthis.timingText = \\\"\\\";\\n\\t\\tthis.maxText = \\\"\\\";\\n\\t\\tthis.texture = null;\\n\\t\\tthis.yOffset = 0;\\n\\t\\tthis.graphType = 0;\\n\\t\\tthis.cursor = 0;\\n\\t\\tthis.sample = new Uint8ClampedArray(4);\\n\\t\\tthis.sample.set([0, 0, 0, 255]);\\n\\t\\tthis.needsClear = false;\\n\\t\\tthis.counter = 0;\\n\\t\\tthis.app.on(\\\"frameupdate\\\", this.update, this);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.app.off(\\\"frameupdate\\\", this.update, this);\\n\\t}\\n\\t// called when context was lost, function releases all context related resources\\n\\tloseContext() {\\n\\t\\tif (this.timer && typeof this.timer.loseContext === \\\"function\\\") {\\n\\t\\t\\tthis.timer.loseContext();\\n\\t\\t}\\n\\t}\\n\\tupdate(ms) {\\n\\t\\tconst timings = this.timer.timings;\\n\\t\\tconst total = timings.reduce((a, v) => a + v, 0);\\n\\t\\tthis.avgTotal += total;\\n\\t\\tthis.avgTimer += ms;\\n\\t\\tthis.avgCount++;\\n\\t\\tthis.maxValue = Math.max(this.maxValue, total);\\n\\t\\tif (this.avgTimer > this.textRefreshRate) {\\n\\t\\t\\tthis.timingText = (this.avgTotal / this.avgCount).toFixed(this.timer.decimalPlaces);\\n\\t\\t\\tthis.maxText = this.maxValue.toFixed(this.timer.decimalPlaces);\\n\\t\\t\\tthis.avgTimer = 0;\\n\\t\\t\\tthis.avgTotal = 0;\\n\\t\\t\\tthis.avgCount = 0;\\n\\t\\t\\tthis.maxValue = 0;\\n\\t\\t}\\n\\t\\tif (this.enabled) {\\n\\t\\t\\tconst range = 1.5 * this.watermark;\\n\\t\\t\\tthis.sample[0] = Math.floor(total / range * 255);\\n\\t\\t\\tthis.sample[1] = 0;\\n\\t\\t\\tthis.sample[2] = 0;\\n\\t\\t\\tthis.sample[3] = this.watermark / range * 255;\\n\\t\\t\\tif (this.yOffset >= this.texture.height) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t\\tconst data = this.texture.lock();\\n\\t\\t\\tif (this.needsClear) {\\n\\t\\t\\t\\tconst rowOffset = this.yOffset * this.texture.width * 4;\\n\\t\\t\\t\\tdata.fill(0, rowOffset, rowOffset + this.texture.width * 4);\\n\\t\\t\\t\\tthis.needsClear = false;\\n\\t\\t\\t}\\n\\t\\t\\tdata.set(this.sample, (this.cursor + this.yOffset * this.texture.width) * 4);\\n\\t\\t\\tthis.texture.unlock();\\n\\t\\t\\tthis.cursor++;\\n\\t\\t\\tif (this.cursor === this.texture.width) {\\n\\t\\t\\t\\tthis.cursor = 0;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\trender(render2d, x, y, w, h) {\\n\\t\\trender2d.quad(\\n\\t\\t\\tx + w,\\n\\t\\t\\ty,\\n\\t\\t\\t-w,\\n\\t\\t\\th,\\n\\t\\t\\tthis.enabled ? this.cursor : 0,\\n\\t\\t\\tthis.enabled ? 0.5 + this.yOffset : this.texture.height - 1,\\n\\t\\t\\t-w,\\n\\t\\t\\t0,\\n\\t\\t\\tthis.texture,\\n\\t\\t\\tthis.graphType\\n\\t\\t);\\n\\t}\\n}\\n\\nclass WordAtlas {\\n\\tconstructor(device, words) {\\n\\t\\tconst initContext = (context2) => {\\n\\t\\t\\tcontext2.font = '10px \\\"Lucida Console\\\", Monaco, monospace';\\n\\t\\t\\tcontext2.textAlign = \\\"left\\\";\\n\\t\\t\\tcontext2.textBaseline = \\\"alphabetic\\\";\\n\\t\\t};\\n\\t\\tconst isNumber = (word) => {\\n\\t\\t\\treturn word === \\\".\\\" || word.length === 1 && word.charCodeAt(0) >= 48 && word.charCodeAt(0) <= 57;\\n\\t\\t};\\n\\t\\tconst canvas = document.createElement(\\\"canvas\\\");\\n\\t\\tconst context = canvas.getContext(\\\"2d\\\", { alpha: true });\\n\\t\\tinitContext(context);\\n\\t\\tconst placements = /* @__PURE__ */ new Map();\\n\\t\\tconst padding = 5;\\n\\t\\tconst width = 512;\\n\\t\\tlet x = padding;\\n\\t\\tlet y = padding;\\n\\t\\twords.forEach((word) => {\\n\\t\\t\\tconst measurement = context.measureText(word);\\n\\t\\t\\tconst l = Math.ceil(-measurement.actualBoundingBoxLeft);\\n\\t\\t\\tconst r = Math.ceil(measurement.actualBoundingBoxRight);\\n\\t\\t\\tconst a = Math.ceil(measurement.actualBoundingBoxAscent);\\n\\t\\t\\tconst d = Math.ceil(measurement.actualBoundingBoxDescent);\\n\\t\\t\\tconst w = l + r;\\n\\t\\t\\tconst h = a + d;\\n\\t\\t\\tif (x + w + padding >= width) {\\n\\t\\t\\t\\tx = padding;\\n\\t\\t\\t\\ty += 16;\\n\\t\\t\\t}\\n\\t\\t\\tplacements.set(word, { l, r, a, d, w, h, x, y });\\n\\t\\t\\tx += w + padding;\\n\\t\\t});\\n\\t\\tcanvas.width = 512;\\n\\t\\tcanvas.height = math.nextPowerOfTwo(y + 16 + padding);\\n\\t\\tinitContext(context);\\n\\t\\tcontext.fillStyle = \\\"rgb(0, 0, 0)\\\";\\n\\t\\tcontext.fillRect(0, 0, canvas.width, canvas.height);\\n\\t\\tplacements.forEach((m, word) => {\\n\\t\\t\\tcontext.fillStyle = isNumber(word) ? \\\"rgb(255, 240, 100)\\\" : \\\"rgb(150, 220, 230)\\\";\\n\\t\\t\\tcontext.fillText(word, m.x - m.l, m.y + m.a);\\n\\t\\t});\\n\\t\\tthis.placements = placements;\\n\\t\\tconst data = context.getImageData(0, 0, canvas.width, canvas.height).data;\\n\\t\\tfor (let i = 0; i < data.length; i += 4) {\\n\\t\\t\\tconst maxChannel = Math.max(data[i + 0], data[i + 1], data[i + 2]);\\n\\t\\t\\tdata[i + 3] = Math.min(maxChannel * 2, 255);\\n\\t\\t}\\n\\t\\tthis.texture = new Texture(device, {\\n\\t\\t\\tname: \\\"mini-stats-word-atlas\\\",\\n\\t\\t\\twidth: canvas.width,\\n\\t\\t\\theight: canvas.height,\\n\\t\\t\\tmipmaps: false,\\n\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\tlevels: [data]\\n\\t\\t});\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.texture.destroy();\\n\\t\\tthis.texture = null;\\n\\t}\\n\\trender(render2d, word, x, y) {\\n\\t\\tconst p = this.placements.get(word);\\n\\t\\tif (p) {\\n\\t\\t\\tconst padding = 1;\\n\\t\\t\\trender2d.quad(\\n\\t\\t\\t\\tx + p.l - padding,\\n\\t\\t\\t\\ty - p.d + padding,\\n\\t\\t\\t\\tp.w + padding * 2,\\n\\t\\t\\t\\tp.h + padding * 2,\\n\\t\\t\\t\\tp.x - padding,\\n\\t\\t\\t\\tthis.texture.height - p.y - p.h - padding,\\n\\t\\t\\t\\tvoid 0,\\n\\t\\t\\t\\tvoid 0,\\n\\t\\t\\t\\tthis.texture,\\n\\t\\t\\t\\t1\\n\\t\\t\\t);\\n\\t\\t\\treturn p.w;\\n\\t\\t}\\n\\t\\tlet totalWidth = 0;\\n\\t\\tfor (let i = 0; i < word.length; i++) {\\n\\t\\t\\tconst char = word[i];\\n\\t\\t\\tif (char === \\\" \\\") {\\n\\t\\t\\t\\ttotalWidth += 5;\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tconst charPlacement = this.placements.get(char);\\n\\t\\t\\tif (charPlacement) {\\n\\t\\t\\t\\tconst padding = 1;\\n\\t\\t\\t\\trender2d.quad(\\n\\t\\t\\t\\t\\tx + totalWidth + charPlacement.l - padding,\\n\\t\\t\\t\\t\\ty - charPlacement.d + padding,\\n\\t\\t\\t\\t\\tcharPlacement.w + padding * 2,\\n\\t\\t\\t\\t\\tcharPlacement.h + padding * 2,\\n\\t\\t\\t\\t\\tcharPlacement.x - padding,\\n\\t\\t\\t\\t\\tthis.texture.height - charPlacement.y - charPlacement.h - padding,\\n\\t\\t\\t\\t\\tvoid 0,\\n\\t\\t\\t\\t\\tvoid 0,\\n\\t\\t\\t\\t\\tthis.texture,\\n\\t\\t\\t\\t\\t1\\n\\t\\t\\t\\t);\\n\\t\\t\\t\\ttotalWidth += charPlacement.w;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn totalWidth;\\n\\t}\\n}\\n\\nconst graphColorDefault = \\\"1.0, 0.412, 0.380\\\";\\nconst graphColorGpu = \\\"0.467, 0.867, 0.467\\\";\\nconst graphColorCpu = \\\"0.424, 0.627, 0.863\\\";\\nconst mainBackgroundColor = \\\"0.0, 0.0, 0.0\\\";\\nconst gpuBackgroundColor = \\\"0.15, 0.15, 0.0\\\";\\nconst cpuBackgroundColor = \\\"0.15, 0.0, 0.1\\\";\\nconst vertexShaderGLSL = `\\n\\tattribute vec3 vertex_position;\\n\\tattribute vec4 vertex_texCoord0;\\n\\tvarying vec4 uv0;\\n\\tvarying float wordFlag;\\n\\tvoid main(void) {\\n\\t\\tgl_Position = vec4(vertex_position.xy * 2.0 - 1.0, 0.5, 1.0);\\n\\t\\tuv0 = vertex_texCoord0;\\n\\t\\twordFlag = vertex_position.z;\\n\\t}\\n`;\\nconst vertexShaderWGSL = `\\n\\tattribute vertex_position: vec3f;\\n\\tattribute vertex_texCoord0: vec4f;\\n\\tvarying uv0: vec4f;\\n\\tvarying wordFlag: f32;\\n\\t@vertex fn vertexMain(input : VertexInput) -> VertexOutput {\\n\\t\\tvar output : VertexOutput;\\n\\t\\toutput.position = vec4(input.vertex_position.xy * 2.0 - 1.0, 0.5, 1.0);\\n\\t\\toutput.uv0 = input.vertex_texCoord0;\\n\\t\\toutput.wordFlag = input.vertex_position.z;\\n\\t\\treturn output;\\n\\t}\\n`;\\nconst fragmentShaderGLSL = `\\n\\tvarying vec4 uv0;\\n\\tvarying float wordFlag;\\n\\tuniform vec4 clr;\\n\\tuniform sampler2D graphTex;\\n\\tuniform sampler2D wordsTex;\\n\\tvoid main (void) {\\n\\t\\tvec3 graphColor = vec3(${graphColorDefault});\\n\\t\\tif (wordFlag > 0.5) {\\n\\t\\t\\tgraphColor = vec3(${graphColorCpu});\\n\\t\\t} else if (wordFlag > 0.2) {\\n\\t\\t\\tgraphColor = vec3(${graphColorGpu});\\n\\t\\t}\\n\\t\\tvec4 graphSample = texture2D(graphTex, uv0.xy);\\n\\t\\tvec4 graph;\\n\\t\\tif (uv0.w < graphSample.r)\\n\\t\\t\\tgraph = vec4(graphColor, 1.0);\\n\\t\\telse {\\n\\t\\t\\tvec3 bgColor = vec3(${mainBackgroundColor});\\n\\t\\t\\tif (wordFlag > 0.5) {\\n\\t\\t\\t\\tbgColor = vec3(${cpuBackgroundColor});\\n\\t\\t\\t} else if (wordFlag > 0.2) {\\n\\t\\t\\t\\tbgColor = vec3(${gpuBackgroundColor});\\n\\t\\t\\t}\\n\\t\\t\\tgraph = vec4(bgColor, 1.0);\\n\\t\\t}\\n\\t\\tvec4 words = texture2D(wordsTex, vec2(uv0.x, 1.0 - uv0.y));\\n\\t\\tif (wordFlag > 0.99) {\\n\\t\\t\\tgl_FragColor = words * clr;\\n\\t\\t} else {\\n\\t\\t\\tgl_FragColor = graph * clr;\\n\\t\\t}\\n\\t}\\n`;\\nconst fragmentShaderWGSL = `\\n\\tvarying uv0: vec4f;\\n\\tvarying wordFlag: f32;\\n\\tuniform clr: vec4f;\\n\\tvar graphTex : texture_2d<f32>;\\n\\tvar graphTex_sampler : sampler;\\n\\tvar wordsTex : texture_2d<f32>;\\n\\tvar wordsTex_sampler : sampler;\\n\\t@fragment fn fragmentMain(input : FragmentInput) -> FragmentOutput {\\n\\t\\tvar uv0: vec4f = input.uv0;\\n\\t\\tvar graphColor: vec3f = vec3f(${graphColorDefault});\\n\\t\\tif (input.wordFlag > 0.5) {\\n\\t\\t\\tgraphColor = vec3f(${graphColorCpu});\\n\\t\\t} else if (input.wordFlag > 0.2) {\\n\\t\\t\\tgraphColor = vec3f(${graphColorGpu});\\n\\t\\t}\\n\\t\\tvar graphSample: vec4f = textureSample(graphTex, graphTex_sampler, uv0.xy);\\n\\t\\tvar graph: vec4f;\\n\\t\\tif (uv0.w < graphSample.r) {\\n\\t\\t\\tgraph = vec4f(graphColor, 1.0);\\n\\t\\t} else {\\n\\t\\t\\tvar bgColor: vec3f = vec3f(${mainBackgroundColor});\\n\\t\\t\\tif (input.wordFlag > 0.5) {\\n\\t\\t\\t\\tbgColor = vec3f(${cpuBackgroundColor});\\n\\t\\t\\t} else if (input.wordFlag > 0.2) {\\n\\t\\t\\t\\tbgColor = vec3f(${gpuBackgroundColor});\\n\\t\\t\\t}\\n\\t\\t\\tgraph = vec4f(bgColor, 1.0);\\n\\t\\t}\\n\\t\\tvar words: vec4f = textureSample(wordsTex, wordsTex_sampler, vec2f(uv0.x, 1.0 - uv0.y));\\n\\t\\tvar output: FragmentOutput;\\n\\t\\tif (input.wordFlag > 0.99) {\\n\\t\\t\\toutput.color = words * uniform.clr;\\n\\t\\t} else {\\n\\t\\t\\toutput.color = graph * uniform.clr;\\n\\t\\t}\\n\\t\\treturn output;\\n\\t}\\n`;\\nclass Render2d {\\n\\tconstructor(device, maxQuads = 2048) {\\n\\t\\tconst format = new VertexFormat(device, [\\n\\t\\t\\t{ semantic: SEMANTIC_POSITION, components: 3, type: TYPE_FLOAT32 },\\n\\t\\t\\t{ semantic: SEMANTIC_TEXCOORD0, components: 4, type: TYPE_FLOAT32 }\\n\\t\\t]);\\n\\t\\tconst indices = new Uint16Array(maxQuads * 6);\\n\\t\\tfor (let i = 0; i < maxQuads; ++i) {\\n\\t\\t\\tindices[i * 6 + 0] = i * 4;\\n\\t\\t\\tindices[i * 6 + 1] = i * 4 + 1;\\n\\t\\t\\tindices[i * 6 + 2] = i * 4 + 2;\\n\\t\\t\\tindices[i * 6 + 3] = i * 4;\\n\\t\\t\\tindices[i * 6 + 4] = i * 4 + 2;\\n\\t\\t\\tindices[i * 6 + 5] = i * 4 + 3;\\n\\t\\t}\\n\\t\\tthis.device = device;\\n\\t\\tthis.maxQuads = maxQuads;\\n\\t\\tthis.buffer = new VertexBuffer(device, format, maxQuads * 4, {\\n\\t\\t\\tusage: BUFFER_STREAM\\n\\t\\t});\\n\\t\\tthis.data = new Float32Array(this.buffer.numBytes / 4);\\n\\t\\tthis.indexBuffer = new IndexBuffer(device, INDEXFORMAT_UINT16, maxQuads * 6, BUFFER_STATIC, indices);\\n\\t\\tthis.prim = {\\n\\t\\t\\ttype: PRIMITIVE_TRIANGLES,\\n\\t\\t\\tindexed: true,\\n\\t\\t\\tbase: 0,\\n\\t\\t\\tbaseVertex: 0,\\n\\t\\t\\tcount: 0\\n\\t\\t};\\n\\t\\tthis.quads = 0;\\n\\t\\tthis.mesh = new Mesh(device);\\n\\t\\tthis.mesh.vertexBuffer = this.buffer;\\n\\t\\tthis.mesh.indexBuffer[0] = this.indexBuffer;\\n\\t\\tthis.mesh.primitive = [this.prim];\\n\\t\\tconst material = new ShaderMaterial({\\n\\t\\t\\tuniqueName: \\\"MiniStats\\\",\\n\\t\\t\\tvertexGLSL: vertexShaderGLSL,\\n\\t\\t\\tfragmentGLSL: fragmentShaderGLSL,\\n\\t\\t\\tvertexWGSL: vertexShaderWGSL,\\n\\t\\t\\tfragmentWGSL: fragmentShaderWGSL,\\n\\t\\t\\tattributes: {\\n\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION,\\n\\t\\t\\t\\tvertex_texCoord0: SEMANTIC_TEXCOORD0\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tthis.material = material;\\n\\t\\tmaterial.cull = CULLFACE_NONE;\\n\\t\\tmaterial.depthState = DepthState.NODEPTH;\\n\\t\\tmaterial.blendState = new BlendState(\\n\\t\\t\\ttrue,\\n\\t\\t\\tBLENDEQUATION_ADD,\\n\\t\\t\\tBLENDMODE_SRC_ALPHA,\\n\\t\\t\\tBLENDMODE_ONE_MINUS_SRC_ALPHA,\\n\\t\\t\\tBLENDEQUATION_ADD,\\n\\t\\t\\tBLENDMODE_ONE,\\n\\t\\t\\tBLENDMODE_ONE\\n\\t\\t);\\n\\t\\tmaterial.update();\\n\\t\\tthis.meshInstance = new MeshInstance(this.mesh, material, new GraphNode(\\\"MiniStatsMesh\\\"));\\n\\t\\tthis.uniforms = {\\n\\t\\t\\tclr: new Float32Array(4)\\n\\t\\t};\\n\\t\\tthis.targetSize = {\\n\\t\\t\\twidth: device.width,\\n\\t\\t\\theight: device.height\\n\\t\\t};\\n\\t}\\n\\tquad(x, y, w, h, u, v, uw, uh, texture, wordFlag = 0) {\\n\\t\\tif (this.quads >= this.maxQuads) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst rw = this.targetSize.width;\\n\\t\\tconst rh = this.targetSize.height;\\n\\t\\tconst x0 = x / rw;\\n\\t\\tconst y0 = y / rh;\\n\\t\\tconst x1 = (x + w) / rw;\\n\\t\\tconst y1 = (y + h) / rh;\\n\\t\\tconst tw = texture.width;\\n\\t\\tconst th = texture.height;\\n\\t\\tconst u0 = u / tw;\\n\\t\\tconst v0 = v / th;\\n\\t\\tconst u1 = (u + (uw ?? w)) / tw;\\n\\t\\tconst v1 = (v + (uh ?? h)) / th;\\n\\t\\tthis.data.set([\\n\\t\\t\\tx0,\\n\\t\\t\\ty0,\\n\\t\\t\\twordFlag,\\n\\t\\t\\tu0,\\n\\t\\t\\tv0,\\n\\t\\t\\t0,\\n\\t\\t\\t0,\\n\\t\\t\\tx1,\\n\\t\\t\\ty0,\\n\\t\\t\\twordFlag,\\n\\t\\t\\tu1,\\n\\t\\t\\tv0,\\n\\t\\t\\t1,\\n\\t\\t\\t0,\\n\\t\\t\\tx1,\\n\\t\\t\\ty1,\\n\\t\\t\\twordFlag,\\n\\t\\t\\tu1,\\n\\t\\t\\tv1,\\n\\t\\t\\t1,\\n\\t\\t\\t1,\\n\\t\\t\\tx0,\\n\\t\\t\\ty1,\\n\\t\\t\\twordFlag,\\n\\t\\t\\tu0,\\n\\t\\t\\tv1,\\n\\t\\t\\t0,\\n\\t\\t\\t1\\n\\t\\t], 4 * 7 * this.quads);\\n\\t\\tthis.quads++;\\n\\t\\tthis.prim.count += 6;\\n\\t}\\n\\tstartFrame() {\\n\\t\\tthis.quads = 0;\\n\\t\\tthis.prim.count = 0;\\n\\t\\tthis.targetSize.width = this.device.canvas.scrollWidth;\\n\\t\\tthis.targetSize.height = this.device.canvas.scrollHeight;\\n\\t}\\n\\trender(app, layer, graphTexture, wordsTexture, clr, height) {\\n\\t\\tthis.buffer.setData(this.data.buffer);\\n\\t\\tthis.uniforms.clr.set(clr, 0);\\n\\t\\tthis.material.setParameter(\\\"clr\\\", this.uniforms.clr);\\n\\t\\tthis.material.setParameter(\\\"graphTex\\\", graphTexture);\\n\\t\\tthis.material.setParameter(\\\"wordsTex\\\", wordsTexture);\\n\\t\\tapp.drawMeshInstance(this.meshInstance, layer);\\n\\t}\\n}\\n\\nconst cpuStatDisplayNames = {\\n\\tanimUpdate: \\\"anim\\\",\\n\\tphysicsTime: \\\"physics\\\",\\n\\trenderTime: \\\"render\\\",\\n\\tgsplatSort: \\\"gsplatSort\\\"\\n};\\nconst delayedStartStats = /* @__PURE__ */ new Set([\\n\\t\\\"physicsTime\\\",\\n\\t\\\"animUpdate\\\",\\n\\t\\\"gsplatSort\\\"\\n]);\\nclass MiniStats {\\n\\tconstructor(app, options = MiniStats.getDefaultOptions()) {\\n\\t\\tconst device = app.graphicsDevice;\\n\\t\\tthis.graphRows = /* @__PURE__ */ new Map();\\n\\t\\tthis.freeRows = [];\\n\\t\\tthis.nextRowIndex = 0;\\n\\t\\tthis.sizes = options.sizes;\\n\\t\\tthis.initGraphs(app, device, options);\\n\\t\\tconst words = new Set(\\n\\t\\t\\t[\\\"\\\", \\\"ms\\\", \\\"0\\\", \\\"1\\\", \\\"2\\\", \\\"3\\\", \\\"4\\\", \\\"5\\\", \\\"6\\\", \\\"7\\\", \\\"8\\\", \\\"9\\\", \\\".\\\", \\\"-\\\", \\\" \\\"].concat(this.graphs.map((graph) => graph.name)).concat(options.stats ? options.stats.map((stat) => stat.unitsName) : []).filter((item) => !!item)\\n\\t\\t);\\n\\t\\tfor (let i = 97; i <= 122; i++) {\\n\\t\\t\\twords.add(String.fromCharCode(i));\\n\\t\\t}\\n\\t\\tfor (let i = 65; i <= 90; i++) {\\n\\t\\t\\twords.add(String.fromCharCode(i));\\n\\t\\t}\\n\\t\\tthis.wordAtlas = new WordAtlas(device, words);\\n\\t\\tthis._activeSizeIndex = options.startSizeIndex;\\n\\t\\tconst gpuTimingMinSize = options.gpuTimingMinSize ?? 1;\\n\\t\\tconst cpuTimingMinSize = options.cpuTimingMinSize ?? 1;\\n\\t\\tconst vramTimingMinSize = options.vramTimingMinSize ?? 1;\\n\\t\\tif (gpuTimingMinSize < this.sizes.length || cpuTimingMinSize < this.sizes.length || vramTimingMinSize < this.sizes.length) {\\n\\t\\t\\tconst lastWidth = this.sizes[this.sizes.length - 1].width;\\n\\t\\t\\tfor (let i = 1; i < this.sizes.length - 1; i++) {\\n\\t\\t\\t\\tthis.sizes[i].width = lastWidth;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst div = document.createElement(\\\"div\\\");\\n\\t\\tdiv.setAttribute(\\\"id\\\", \\\"mini-stats\\\");\\n\\t\\tdiv.style.cssText = \\\"position:fixed;bottom:0;left:0;background:transparent;\\\";\\n\\t\\tdocument.body.appendChild(div);\\n\\t\\tdiv.addEventListener(\\\"mouseenter\\\", (event) => {\\n\\t\\t\\tthis.opacity = 1;\\n\\t\\t});\\n\\t\\tdiv.addEventListener(\\\"mouseleave\\\", (event) => {\\n\\t\\t\\tthis.opacity = this._activeSizeIndex > 0 ? 0.85 : 0.7;\\n\\t\\t});\\n\\t\\tdiv.addEventListener(\\\"click\\\", (event) => {\\n\\t\\t\\tevent.preventDefault();\\n\\t\\t\\tif (this._enabled) {\\n\\t\\t\\t\\tthis.activeSizeIndex = (this.activeSizeIndex + 1) % this.sizes.length;\\n\\t\\t\\t\\tthis.resize(this.sizes[this.activeSizeIndex].width, this.sizes[this.activeSizeIndex].height, this.sizes[this.activeSizeIndex].graphs);\\n\\t\\t\\t}\\n\\t\\t});\\n\\t\\tdevice.on(\\\"resizecanvas\\\", this.updateDiv, this);\\n\\t\\tdevice.on(\\\"losecontext\\\", this.loseContext, this);\\n\\t\\tapp.on(\\\"postrender\\\", this.postRender, this);\\n\\t\\tthis.app = app;\\n\\t\\tthis.drawLayer = app.scene.layers.getLayerById(LAYERID_UI);\\n\\t\\tthis.device = device;\\n\\t\\tthis.render2d = new Render2d(device);\\n\\t\\tthis.div = div;\\n\\t\\tthis.width = 0;\\n\\t\\tthis.height = 0;\\n\\t\\tthis.gspacing = 2;\\n\\t\\tthis.clr = [1, 1, 1, options.startSizeIndex > 0 ? 0.85 : 0.7];\\n\\t\\tthis._enabled = true;\\n\\t\\tthis.gpuTimingMinSize = gpuTimingMinSize;\\n\\t\\tthis.gpuPassGraphs = /* @__PURE__ */ new Map();\\n\\t\\tthis.cpuTimingMinSize = cpuTimingMinSize;\\n\\t\\tthis.cpuGraphs = /* @__PURE__ */ new Map();\\n\\t\\tthis.vramTimingMinSize = vramTimingMinSize;\\n\\t\\tthis.vramGraphs = /* @__PURE__ */ new Map();\\n\\t\\tthis.frameIndex = 0;\\n\\t\\tthis.textRefreshRate = options.textRefreshRate;\\n\\t\\tthis.activeSizeIndex = this._activeSizeIndex;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.device.off(\\\"resizecanvas\\\", this.updateDiv, this);\\n\\t\\tthis.device.off(\\\"losecontext\\\", this.loseContext, this);\\n\\t\\tthis.app.off(\\\"postrender\\\", this.postRender, this);\\n\\t\\tthis.graphs.forEach((graph) => graph.destroy());\\n\\t\\tthis.gpuPassGraphs.clear();\\n\\t\\tthis.cpuGraphs.clear();\\n\\t\\tthis.vramGraphs.clear();\\n\\t\\tthis.wordAtlas.destroy();\\n\\t\\tthis.texture.destroy();\\n\\t\\tthis.div.remove();\\n\\t}\\n\\tstatic statPresets = {\\n\\t\\tgsplats: [\\n\\t\\t\\t{ name: \\\"GSplats\\\", stats: [\\\"frame.gsplats\\\"], decimalPlaces: 3, multiplier: 1 / 1e6, unitsName: \\\"M\\\", watermark: 10 }\\n\\t\\t],\\n\\t\\tgsplatsCopy: [\\n\\t\\t\\t{ name: \\\"GsplatsCopy\\\", stats: [\\\"frame.gsplatBufferCopy\\\"], decimalPlaces: 1, multiplier: 1, unitsName: \\\"%\\\", watermark: 100 }\\n\\t\\t]\\n\\t};\\n\\tstatic getDefaultOptions(extraStats = []) {\\n\\t\\tconst options = {\\n\\t\\t\\t// sizes of area to render individual graphs in and spacing between individual graphs\\n\\t\\t\\tsizes: [\\n\\t\\t\\t\\t{ width: 100, height: 16, spacing: 0, graphs: false },\\n\\t\\t\\t\\t{ width: 128, height: 32, spacing: 2, graphs: true },\\n\\t\\t\\t\\t{ width: 256, height: 64, spacing: 2, graphs: true }\\n\\t\\t\\t],\\n\\t\\t\\t// index into sizes array for initial setting\\n\\t\\t\\tstartSizeIndex: 0,\\n\\t\\t\\t// refresh rate of text stats in ms\\n\\t\\t\\ttextRefreshRate: 500,\\n\\t\\t\\t// cpu graph options\\n\\t\\t\\tcpu: {\\n\\t\\t\\t\\tenabled: true,\\n\\t\\t\\t\\twatermark: 33\\n\\t\\t\\t},\\n\\t\\t\\t// gpu graph options\\n\\t\\t\\tgpu: {\\n\\t\\t\\t\\tenabled: true,\\n\\t\\t\\t\\twatermark: 33\\n\\t\\t\\t},\\n\\t\\t\\t// array of options to render additional graphs based on stats collected into Application.stats\\n\\t\\t\\tstats: [\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t// display name\\n\\t\\t\\t\\t\\tname: \\\"Frame\\\",\\n\\t\\t\\t\\t\\t// path to data inside Application.stats\\n\\t\\t\\t\\t\\tstats: [\\\"frame.ms\\\"],\\n\\t\\t\\t\\t\\t// number of decimal places (defaults to none)\\n\\t\\t\\t\\t\\tdecimalPlaces: 1,\\n\\t\\t\\t\\t\\t// units (defaults to \\\"\\\")\\n\\t\\t\\t\\t\\tunitsName: \\\"ms\\\",\\n\\t\\t\\t\\t\\t// watermark - shown as a line on the graph, useful for displaying a budget\\n\\t\\t\\t\\t\\twatermark: 33\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\t// total number of draw calls\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\tname: \\\"DrawCalls\\\",\\n\\t\\t\\t\\t\\tstats: [\\\"drawCalls.total\\\"],\\n\\t\\t\\t\\t\\twatermark: 1e3\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\t// used VRAM in MB\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\tname: \\\"VRAM\\\",\\n\\t\\t\\t\\t\\tstats: [\\\"vram.totalUsed\\\"],\\n\\t\\t\\t\\t\\tdecimalPlaces: 1,\\n\\t\\t\\t\\t\\tmultiplier: 1 / (1024 * 1024),\\n\\t\\t\\t\\t\\tunitsName: \\\"MB\\\",\\n\\t\\t\\t\\t\\twatermark: 1024\\n\\t\\t\\t\\t}\\n\\t\\t\\t],\\n\\t\\t\\t// minimum size index to show GPU pass timing graphs\\n\\t\\t\\tgpuTimingMinSize: 1,\\n\\t\\t\\t// minimum size index to show CPU sub-timing graphs\\n\\t\\t\\tcpuTimingMinSize: 1,\\n\\t\\t\\t// minimum size index to show VRAM subcategory graphs\\n\\t\\t\\tvramTimingMinSize: 1\\n\\t\\t};\\n\\t\\tif (extraStats.length > 0) {\\n\\t\\t\\tconst frameIndex = options.stats.findIndex((s) => s.name === \\\"Frame\\\");\\n\\t\\t\\tconst insertIndex = frameIndex !== -1 ? frameIndex + 1 : options.stats.length;\\n\\t\\t\\tconst extra = extraStats.flatMap((name) => MiniStats.statPresets[name] ?? []).reverse();\\n\\t\\t\\toptions.stats.splice(insertIndex, 0, ...extra);\\n\\t\\t}\\n\\t\\treturn options;\\n\\t}\\n\\tset activeSizeIndex(value) {\\n\\t\\tthis._activeSizeIndex = value;\\n\\t\\tthis.gspacing = this.sizes[value].spacing;\\n\\t\\tthis.resize(this.sizes[value].width, this.sizes[value].height, this.sizes[value].graphs);\\n\\t\\tthis.opacity = value > 0 ? 0.85 : 0.7;\\n\\t\\tif (value < this.gpuTimingMinSize && this.gpuPassGraphs) {\\n\\t\\t\\tthis.clearSubGraphs(this.gpuPassGraphs, \\\"GPU\\\", 0.33);\\n\\t\\t}\\n\\t\\tif (value < this.cpuTimingMinSize && this.cpuGraphs) {\\n\\t\\t\\tthis.clearSubGraphs(this.cpuGraphs, \\\"CPU\\\", 0.66);\\n\\t\\t}\\n\\t\\tif (value < this.vramTimingMinSize && this.vramGraphs) {\\n\\t\\t\\tthis.clearSubGraphs(this.vramGraphs);\\n\\t\\t}\\n\\t}\\n\\tget activeSizeIndex() {\\n\\t\\treturn this._activeSizeIndex;\\n\\t}\\n\\tset opacity(value) {\\n\\t\\tthis.clr[3] = value;\\n\\t}\\n\\tget opacity() {\\n\\t\\treturn this.clr[3];\\n\\t}\\n\\tget overallHeight() {\\n\\t\\tconst graphs = this.graphs;\\n\\t\\tconst spacing = this.gspacing;\\n\\t\\treturn this.height * graphs.length + spacing * (graphs.length - 1);\\n\\t}\\n\\tset enabled(value) {\\n\\t\\tif (value !== this._enabled) {\\n\\t\\t\\tthis._enabled = value;\\n\\t\\t\\tfor (let i = 0; i < this.graphs.length; ++i) {\\n\\t\\t\\t\\tthis.graphs[i].enabled = value;\\n\\t\\t\\t\\tthis.graphs[i].timer.enabled = value;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tget enabled() {\\n\\t\\treturn this._enabled;\\n\\t}\\n\\tinitGraphs(app, device, options) {\\n\\t\\tthis.graphs = [];\\n\\t\\tif (options.stats) {\\n\\t\\t\\toptions.stats.forEach((entry) => {\\n\\t\\t\\t\\tif (entry.name === \\\"VRAM\\\") {\\n\\t\\t\\t\\t\\tconst timer = new StatsTimer(app, entry.stats, entry.decimalPlaces, entry.unitsName, entry.multiplier);\\n\\t\\t\\t\\t\\tconst graph = new Graph(entry.name, app, entry.watermark, options.textRefreshRate, timer);\\n\\t\\t\\t\\t\\tthis.graphs.push(graph);\\n\\t\\t\\t\\t}\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tif (options.cpu.enabled) {\\n\\t\\t\\tconst timer = new CpuTimer(app);\\n\\t\\t\\tconst graph = new Graph(\\\"CPU\\\", app, options.cpu.watermark, options.textRefreshRate, timer);\\n\\t\\t\\tgraph.graphType = 0.66;\\n\\t\\t\\tthis.graphs.push(graph);\\n\\t\\t}\\n\\t\\tif (options.gpu.enabled) {\\n\\t\\t\\tconst timer = new GpuTimer(device);\\n\\t\\t\\tconst graph = new Graph(\\\"GPU\\\", app, options.gpu.watermark, options.textRefreshRate, timer);\\n\\t\\t\\tgraph.graphType = 0.33;\\n\\t\\t\\tthis.graphs.push(graph);\\n\\t\\t}\\n\\t\\tif (options.stats) {\\n\\t\\t\\toptions.stats.forEach((entry) => {\\n\\t\\t\\t\\tif (entry.name === \\\"VRAM\\\") {\\n\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst timer = new StatsTimer(app, entry.stats, entry.decimalPlaces, entry.unitsName, entry.multiplier);\\n\\t\\t\\t\\tconst graph = new Graph(entry.name, app, entry.watermark, options.textRefreshRate, timer);\\n\\t\\t\\t\\tthis.graphs.push(graph);\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tthis.texture = new Texture(device, {\\n\\t\\t\\tname: \\\"mini-stats-graph-texture\\\",\\n\\t\\t\\twidth: 1,\\n\\t\\t\\theight: 1,\\n\\t\\t\\tmipmaps: false,\\n\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\taddressU: ADDRESS_REPEAT,\\n\\t\\t\\taddressV: ADDRESS_REPEAT\\n\\t\\t});\\n\\t\\tthis.graphs.forEach((graph) => {\\n\\t\\t\\tgraph.texture = this.texture;\\n\\t\\t\\tthis.allocateRow(graph);\\n\\t\\t});\\n\\t}\\n\\trender() {\\n\\t\\tconst graphs = this.graphs;\\n\\t\\tconst wordAtlas = this.wordAtlas;\\n\\t\\tconst render2d = this.render2d;\\n\\t\\tconst width = this.width;\\n\\t\\tconst height = this.height;\\n\\t\\tconst gspacing = this.gspacing;\\n\\t\\trender2d.startFrame();\\n\\t\\tfor (let i = 0; i < graphs.length; ++i) {\\n\\t\\t\\tconst graph = graphs[i];\\n\\t\\t\\tlet y = i * (height + gspacing);\\n\\t\\t\\tgraph.render(render2d, 0, y, width, height);\\n\\t\\t\\tlet x = 1;\\n\\t\\t\\ty += height - 13;\\n\\t\\t\\tx += wordAtlas.render(render2d, graph.name, x, y) + 10;\\n\\t\\t\\tconst timingText = graph.timingText;\\n\\t\\t\\tfor (let j = 0; j < timingText.length; ++j) {\\n\\t\\t\\t\\tx += wordAtlas.render(render2d, timingText[j], x, y);\\n\\t\\t\\t}\\n\\t\\t\\tif (graph.maxText && this._activeSizeIndex > 0) {\\n\\t\\t\\t\\tx += 5;\\n\\t\\t\\t\\tx += wordAtlas.render(render2d, \\\"max\\\", x, y);\\n\\t\\t\\t\\tx += 5;\\n\\t\\t\\t\\tconst maxText = graph.maxText;\\n\\t\\t\\t\\tfor (let j = 0; j < maxText.length; ++j) {\\n\\t\\t\\t\\t\\tx += wordAtlas.render(render2d, maxText[j], x, y);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (graph.timer.unitsName) {\\n\\t\\t\\t\\tx += wordAtlas.render(render2d, graph.timer.unitsName, x, y);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\trender2d.render(this.app, this.drawLayer, this.texture, this.wordAtlas.texture, this.clr, height);\\n\\t}\\n\\tresize(width, height, showGraphs) {\\n\\t\\tconst graphs = this.graphs;\\n\\t\\tfor (let i = 0; i < graphs.length; ++i) {\\n\\t\\t\\tgraphs[i].enabled = showGraphs;\\n\\t\\t}\\n\\t\\tthis.width = width;\\n\\t\\tthis.height = height;\\n\\t\\tthis.updateDiv();\\n\\t}\\n\\tupdateDiv() {\\n\\t\\tconst rect = this.device.canvas.getBoundingClientRect();\\n\\t\\tthis.div.style.left = `${rect.left}px`;\\n\\t\\tthis.div.style.bottom = `${window.innerHeight - rect.bottom}px`;\\n\\t\\tthis.div.style.width = `${this.width}px`;\\n\\t\\tthis.div.style.height = `${this.overallHeight}px`;\\n\\t}\\n\\tloseContext() {\\n\\t\\tthis.graphs.forEach((graph) => graph.loseContext());\\n\\t}\\n\\tupdateSubStats(subGraphs, mainGraphName, stats, statPathPrefix, removeAfterFrames) {\\n\\t\\tconst passesToRemove = [];\\n\\t\\tfor (const [statName, statData] of subGraphs) {\\n\\t\\t\\tconst timing = stats instanceof Map ? stats.get(statName) || 0 : stats[statName] || 0;\\n\\t\\t\\tif (timing > 0) {\\n\\t\\t\\t\\tstatData.lastNonZeroFrame = this.frameIndex;\\n\\t\\t\\t} else if (removeAfterFrames > 0) {\\n\\t\\t\\t\\tconst shouldAutoHide = statPathPrefix === \\\"gpu\\\";\\n\\t\\t\\t\\tif (shouldAutoHide && this.frameIndex - statData.lastNonZeroFrame > removeAfterFrames) {\\n\\t\\t\\t\\t\\tpassesToRemove.push(statName);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfor (const statName of passesToRemove) {\\n\\t\\t\\tconst statData = subGraphs.get(statName);\\n\\t\\t\\tif (statData) {\\n\\t\\t\\t\\tconst index = this.graphs.indexOf(statData.graph);\\n\\t\\t\\t\\tif (index !== -1) {\\n\\t\\t\\t\\t\\tthis.graphs.splice(index, 1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.freeRow(statData.graph);\\n\\t\\t\\t\\tstatData.graph.destroy();\\n\\t\\t\\t\\tsubGraphs.delete(statName);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst statsEntries = stats instanceof Map ? stats : Object.entries(stats);\\n\\t\\tconst mainGraph = this.graphs.find((g) => g.name === mainGraphName);\\n\\t\\tfor (const [statName, timing] of statsEntries) {\\n\\t\\t\\tif (!subGraphs.has(statName)) {\\n\\t\\t\\t\\tconst isDelayedStart = statPathPrefix === \\\"gpu\\\" || delayedStartStats.has(statName);\\n\\t\\t\\t\\tif (isDelayedStart && timing === 0) {\\n\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet displayName = statName;\\n\\t\\t\\t\\tif (statPathPrefix === \\\"frame\\\") {\\n\\t\\t\\t\\t\\tdisplayName = cpuStatDisplayNames[statName] || statName;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst graphName = `  ${displayName}`;\\n\\t\\t\\t\\tconst watermark = mainGraph?.watermark ?? 10;\\n\\t\\t\\t\\tconst decimalPlaces = 1;\\n\\t\\t\\t\\tconst unitsName = statPathPrefix === \\\"vram\\\" ? \\\"MB\\\" : \\\"ms\\\";\\n\\t\\t\\t\\tconst multiplier = statPathPrefix === \\\"vram\\\" ? 1 / (1024 * 1024) : 1;\\n\\t\\t\\t\\tconst statPath = `${statPathPrefix}.${statName}`;\\n\\t\\t\\t\\tconst timer = new StatsTimer(this.app, [statPath], decimalPlaces, unitsName, multiplier);\\n\\t\\t\\t\\tconst graph = new Graph(graphName, this.app, watermark, this.textRefreshRate, timer);\\n\\t\\t\\t\\tif (statPathPrefix === \\\"gpu\\\") {\\n\\t\\t\\t\\t\\tgraph.graphType = 0.33;\\n\\t\\t\\t\\t} else if (statPathPrefix === \\\"frame\\\") {\\n\\t\\t\\t\\t\\tgraph.graphType = 0.66;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tgraph.texture = this.texture;\\n\\t\\t\\t\\tthis.allocateRow(graph);\\n\\t\\t\\t\\tconst currentSize = this.sizes[this._activeSizeIndex];\\n\\t\\t\\t\\tgraph.enabled = currentSize.graphs;\\n\\t\\t\\t\\tlet mainGraphIndex = this.graphs.findIndex((g) => g.name === mainGraphName);\\n\\t\\t\\t\\tif (mainGraphIndex === -1) {\\n\\t\\t\\t\\t\\tmainGraphIndex = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet insertIndex = mainGraphIndex;\\n\\t\\t\\t\\tfor (let i = mainGraphIndex - 1; i >= 0; i--) {\\n\\t\\t\\t\\t\\tif (this.graphs[i].name.startsWith(\\\" \\\")) {\\n\\t\\t\\t\\t\\t\\tinsertIndex = i;\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.graphs.splice(insertIndex, 0, graph);\\n\\t\\t\\t\\tsubGraphs.set(statName, {\\n\\t\\t\\t\\t\\tgraph,\\n\\t\\t\\t\\t\\tlastNonZeroFrame: timing > 0 ? this.frameIndex : this.frameIndex - removeAfterFrames - 1\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (mainGraph) {\\n\\t\\t\\tfor (const statData of subGraphs.values()) {\\n\\t\\t\\t\\tstatData.graph.watermark = mainGraph.watermark;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tallocateRow(graph) {\\n\\t\\tlet row;\\n\\t\\tif (this.freeRows.length > 0) {\\n\\t\\t\\trow = this.freeRows.pop();\\n\\t\\t} else {\\n\\t\\t\\trow = this.nextRowIndex++;\\n\\t\\t\\tthis.ensureTextureHeight(this.nextRowIndex);\\n\\t\\t}\\n\\t\\tthis.graphRows.set(graph, row);\\n\\t\\tgraph.yOffset = row;\\n\\t\\tgraph.needsClear = true;\\n\\t\\treturn row;\\n\\t}\\n\\tfreeRow(graph) {\\n\\t\\tconst row = this.graphRows.get(graph);\\n\\t\\tif (row !== void 0) {\\n\\t\\t\\tthis.freeRows.push(row);\\n\\t\\t\\tthis.graphRows.delete(graph);\\n\\t\\t}\\n\\t}\\n\\tclearSubGraphs(subGraphs, mainGraphName, graphType) {\\n\\t\\tfor (const statData of subGraphs.values()) {\\n\\t\\t\\tconst index = this.graphs.indexOf(statData.graph);\\n\\t\\t\\tif (index !== -1) {\\n\\t\\t\\t\\tthis.graphs.splice(index, 1);\\n\\t\\t\\t}\\n\\t\\t\\tthis.freeRow(statData.graph);\\n\\t\\t\\tstatData.graph.destroy();\\n\\t\\t}\\n\\t\\tsubGraphs.clear();\\n\\t\\tif (mainGraphName) {\\n\\t\\t\\tconst mainGraph = this.graphs.find((g) => g.name === mainGraphName);\\n\\t\\t\\tif (mainGraph) mainGraph.graphType = graphType;\\n\\t\\t}\\n\\t}\\n\\tensureTextureHeight(requiredRows) {\\n\\t\\tconst maxWidth = this.sizes[this.sizes.length - 1].width;\\n\\t\\tconst requiredWidth = math.nextPowerOfTwo(maxWidth);\\n\\t\\tconst requiredHeight = math.nextPowerOfTwo(requiredRows);\\n\\t\\tif (requiredHeight > this.texture.height) {\\n\\t\\t\\tthis.texture.resize(requiredWidth, requiredHeight);\\n\\t\\t}\\n\\t}\\n\\tpostRender() {\\n\\t\\tif (this._enabled) {\\n\\t\\t\\tthis.render();\\n\\t\\t\\tif (this._activeSizeIndex >= this.gpuTimingMinSize) {\\n\\t\\t\\t\\tconst gpuStats = this.app.stats.gpu;\\n\\t\\t\\t\\tif (gpuStats) {\\n\\t\\t\\t\\t\\tthis.updateSubStats(this.gpuPassGraphs, \\\"GPU\\\", gpuStats, \\\"gpu\\\", 240);\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tif (this._activeSizeIndex >= this.cpuTimingMinSize) {\\n\\t\\t\\t\\tconst cpuStats = {\\n\\t\\t\\t\\t\\tscriptUpdate: this.app.stats.frame.scriptUpdate,\\n\\t\\t\\t\\t\\tscriptPostUpdate: this.app.stats.frame.scriptPostUpdate,\\n\\t\\t\\t\\t\\tanimUpdate: this.app.stats.frame.animUpdate,\\n\\t\\t\\t\\t\\tphysicsTime: this.app.stats.frame.physicsTime,\\n\\t\\t\\t\\t\\trenderTime: this.app.stats.frame.renderTime,\\n\\t\\t\\t\\t\\tgsplatSort: this.app.stats.frame.gsplatSort\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.updateSubStats(this.cpuGraphs, \\\"CPU\\\", cpuStats, \\\"frame\\\", 240);\\n\\t\\t\\t}\\n\\t\\t\\tif (this._activeSizeIndex >= this.vramTimingMinSize) {\\n\\t\\t\\t\\tconst vram = this.app.stats.vram;\\n\\t\\t\\t\\tconst vramStats = {\\n\\t\\t\\t\\t\\ttex: vram.tex,\\n\\t\\t\\t\\t\\tgeom: vram.geom\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (this.device.isWebGPU) {\\n\\t\\t\\t\\t\\tvramStats.buffers = vram.buffers;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.updateSubStats(this.vramGraphs, \\\"VRAM\\\", vramStats, \\\"vram\\\", 0);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.frameIndex++;\\n\\t}\\n}\\n\\nconst SSAOTYPE_NONE = \\\"none\\\";\\nconst SSAOTYPE_LIGHTING = \\\"lighting\\\";\\nconst SSAOTYPE_COMBINE = \\\"combine\\\";\\n\\nvar downsample_default$1 = `\\nuniform sampler2D sourceTexture;\\nuniform vec2 sourceInvResolution;\\nvarying vec2 uv0;\\n#ifdef PREMULTIPLY\\n\\tuniform sampler2D premultiplyTexture;\\n#endif\\nvoid main()\\n{\\n\\tvec3 e = texture2D (sourceTexture, uv0).rgb;\\n\\t#ifdef BOXFILTER\\n\\t\\tvec3 value = e;\\n\\t\\t#ifdef PREMULTIPLY\\n\\t\\t\\tfloat premultiply = texture2D(premultiplyTexture, uv0).{PREMULTIPLY_SRC_CHANNEL};\\n\\t\\t\\tvalue *= vec3(premultiply);\\n\\t\\t#endif\\n\\t#else\\n\\t\\tfloat x = sourceInvResolution.x;\\n\\t\\tfloat y = sourceInvResolution.y;\\n\\t\\tvec3 a = texture2D(sourceTexture, vec2 (uv0.x - 2.0 * x, uv0.y + 2.0 * y)).rgb;\\n\\t\\tvec3 b = texture2D(sourceTexture, vec2 (uv0.x,\\t\\t   uv0.y + 2.0 * y)).rgb;\\n\\t\\tvec3 c = texture2D(sourceTexture, vec2 (uv0.x + 2.0 * x, uv0.y + 2.0 * y)).rgb;\\n\\t\\tvec3 d = texture2D(sourceTexture, vec2 (uv0.x - 2.0 * x, uv0.y)).rgb;\\n\\t\\tvec3 f = texture2D(sourceTexture, vec2 (uv0.x + 2.0 * x, uv0.y)).rgb;\\n\\t\\tvec3 g = texture2D(sourceTexture, vec2 (uv0.x - 2.0 * x, uv0.y - 2.0 * y)).rgb;\\n\\t\\tvec3 h = texture2D(sourceTexture, vec2 (uv0.x,\\t\\t   uv0.y - 2.0 * y)).rgb;\\n\\t\\tvec3 i = texture2D(sourceTexture, vec2 (uv0.x + 2.0 * x, uv0.y - 2.0 * y)).rgb;\\n\\t\\tvec3 j = texture2D(sourceTexture, vec2 (uv0.x - x, uv0.y + y)).rgb;\\n\\t\\tvec3 k = texture2D(sourceTexture, vec2 (uv0.x + x, uv0.y + y)).rgb;\\n\\t\\tvec3 l = texture2D(sourceTexture, vec2 (uv0.x - x, uv0.y - y)).rgb;\\n\\t\\tvec3 m = texture2D(sourceTexture, vec2 (uv0.x + x, uv0.y - y)).rgb;\\n\\t\\tvec3 value = e * 0.125;\\n\\t\\tvalue += (a + c + g + i) * 0.03125;\\n\\t\\tvalue += (b + d + f + h) * 0.0625;\\n\\t\\tvalue += (j + k + l + m) * 0.125;\\n\\t#endif\\n\\t#ifdef REMOVE_INVALID\\n\\t\\tvalue = max(value, vec3(0.0));\\n\\t#endif\\n\\tgl_FragColor = vec4(value, 1.0);\\n}\\n`;\\n\\nvar downsample_default = `\\nvar sourceTexture: texture_2d<f32>;\\nvar sourceTextureSampler: sampler;\\nuniform sourceInvResolution: vec2f;\\nvarying uv0: vec2f;\\n#ifdef PREMULTIPLY\\n\\tvar premultiplyTexture: texture_2d<f32>;\\n\\tvar premultiplyTextureSampler: sampler;\\n#endif\\n@fragment\\nfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\tvar output: FragmentOutput;\\n\\tlet e: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, input.uv0).rgb);\\n\\t#ifdef BOXFILTER\\n\\t\\tvar value: half3 = e;\\n\\t\\t#ifdef PREMULTIPLY\\n\\t\\t\\tlet premultiply: half = half(textureSample(premultiplyTexture, premultiplyTextureSampler, input.uv0).{PREMULTIPLY_SRC_CHANNEL});\\n\\t\\t\\tvalue *= premultiply;\\n\\t\\t#endif\\n\\t#else\\n\\t\\tlet x: f32 = uniform.sourceInvResolution.x;\\n\\t\\tlet y: f32 = uniform.sourceInvResolution.y;\\n\\t\\tlet a: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x - 2.0 * x, input.uv0.y + 2.0 * y)).rgb);\\n\\t\\tlet b: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x,\\t\\t   input.uv0.y + 2.0 * y)).rgb);\\n\\t\\tlet c: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x + 2.0 * x, input.uv0.y + 2.0 * y)).rgb);\\n\\t\\tlet d: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x - 2.0 * x, input.uv0.y)).rgb);\\n\\t\\tlet f: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x + 2.0 * x, input.uv0.y)).rgb);\\n\\t\\tlet g: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x - 2.0 * x, input.uv0.y - 2.0 * y)).rgb);\\n\\t\\tlet h: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x,\\t\\t   input.uv0.y - 2.0 * y)).rgb);\\n\\t\\tlet i: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x + 2.0 * x, input.uv0.y - 2.0 * y)).rgb);\\n\\t\\tlet j: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x - x, input.uv0.y + y)).rgb);\\n\\t\\tlet k: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x + x, input.uv0.y + y)).rgb);\\n\\t\\tlet l: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x - x, input.uv0.y - y)).rgb);\\n\\t\\tlet m: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x + x, input.uv0.y - y)).rgb);\\n\\t\\tvar value: half3 = e * half(0.125);\\n\\t\\tvalue += (a + c + g + i) * half(0.03125);\\n\\t\\tvalue += (b + d + f + h) * half(0.0625);\\n\\t\\tvalue += (j + k + l + m) * half(0.125);\\n\\t#endif\\n\\t#ifdef REMOVE_INVALID\\n\\t\\tvalue = max(value, half3(0.0));\\n\\t#endif\\n\\toutput.color = vec4f(vec3f(value), 1.0);\\n\\treturn output;\\n}\\n`;\\n\\nclass RenderPassDownsample extends RenderPassShaderQuad {\\n\\tconstructor(device, sourceTexture, options = {}) {\\n\\t\\tsuper(device);\\n\\t\\tthis.sourceTexture = sourceTexture;\\n\\t\\tthis.premultiplyTexture = options.premultiplyTexture;\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set(\\\"downsamplePS\\\", downsample_default$1);\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set(\\\"downsamplePS\\\", downsample_default);\\n\\t\\tconst boxFilter = options.boxFilter ?? false;\\n\\t\\tconst key = `${boxFilter ? \\\"Box\\\" : \\\"\\\"}-${options.premultiplyTexture ? \\\"Premultiply\\\" : \\\"\\\"}-${options.premultiplySrcChannel ?? \\\"\\\"}-${options.removeInvalid ? \\\"RemoveInvalid\\\" : \\\"\\\"}`;\\n\\t\\tconst defines = /* @__PURE__ */ new Map();\\n\\t\\tif (boxFilter) defines.set(\\\"BOXFILTER\\\", \\\"\\\");\\n\\t\\tif (options.premultiplyTexture) defines.set(\\\"PREMULTIPLY\\\", \\\"\\\");\\n\\t\\tif (options.removeInvalid) defines.set(\\\"REMOVE_INVALID\\\", \\\"\\\");\\n\\t\\tdefines.set(\\\"{PREMULTIPLY_SRC_CHANNEL}\\\", options.premultiplySrcChannel ?? \\\"x\\\");\\n\\t\\tthis.shader = ShaderUtils.createShader(device, {\\n\\t\\t\\tuniqueName: `DownSampleShader:${key}`,\\n\\t\\t\\tattributes: { aPosition: SEMANTIC_POSITION },\\n\\t\\t\\tvertexChunk: \\\"quadVS\\\",\\n\\t\\t\\tfragmentChunk: \\\"downsamplePS\\\",\\n\\t\\t\\tfragmentDefines: defines\\n\\t\\t});\\n\\t\\tthis.sourceTextureId = device.scope.resolve(\\\"sourceTexture\\\");\\n\\t\\tthis.premultiplyTextureId = device.scope.resolve(\\\"premultiplyTexture\\\");\\n\\t\\tthis.sourceInvResolutionId = device.scope.resolve(\\\"sourceInvResolution\\\");\\n\\t\\tthis.sourceInvResolutionValue = new Float32Array(2);\\n\\t}\\n\\tsetSourceTexture(value) {\\n\\t\\tthis._sourceTexture = value;\\n\\t\\tthis.options.resizeSource = value;\\n\\t}\\n\\texecute() {\\n\\t\\tthis.sourceTextureId.setValue(this.sourceTexture);\\n\\t\\tif (this.premultiplyTexture) {\\n\\t\\t\\tthis.premultiplyTextureId.setValue(this.premultiplyTexture);\\n\\t\\t}\\n\\t\\tthis.sourceInvResolutionValue[0] = 1 / this.sourceTexture.width;\\n\\t\\tthis.sourceInvResolutionValue[1] = 1 / this.sourceTexture.height;\\n\\t\\tthis.sourceInvResolutionId.setValue(this.sourceInvResolutionValue);\\n\\t\\tsuper.execute();\\n\\t}\\n}\\n\\nvar upsample_default$1 = `\\n\\tuniform sampler2D sourceTexture;\\n\\tuniform vec2 sourceInvResolution;\\n\\tvarying vec2 uv0;\\n\\tvoid main()\\n\\t{\\n\\t\\tfloat x = sourceInvResolution.x;\\n\\t\\tfloat y = sourceInvResolution.y;\\n\\t\\tvec3 a = texture2D (sourceTexture, vec2 (uv0.x - x, uv0.y + y)).rgb;\\n\\t\\tvec3 b = texture2D (sourceTexture, vec2 (uv0.x,\\t uv0.y + y)).rgb;\\n\\t\\tvec3 c = texture2D (sourceTexture, vec2 (uv0.x + x, uv0.y + y)).rgb;\\n\\t\\tvec3 d = texture2D (sourceTexture, vec2 (uv0.x - x, uv0.y)).rgb;\\n\\t\\tvec3 e = texture2D (sourceTexture, vec2 (uv0.x,\\t uv0.y)).rgb;\\n\\t\\tvec3 f = texture2D (sourceTexture, vec2 (uv0.x + x, uv0.y)).rgb;\\n\\t\\tvec3 g = texture2D (sourceTexture, vec2 (uv0.x - x, uv0.y - y)).rgb;\\n\\t\\tvec3 h = texture2D (sourceTexture, vec2 (uv0.x,\\t uv0.y - y)).rgb;\\n\\t\\tvec3 i = texture2D (sourceTexture, vec2 (uv0.x + x, uv0.y - y)).rgb;\\n\\t\\tvec3 value = e * 0.25;\\n\\t\\tvalue += (b + d + f + h) * 0.125;\\n\\t\\tvalue += (a + c + g + i) * 0.0625;\\n\\t\\tgl_FragColor = vec4(value, 1.0);\\n\\t}\\n`;\\n\\nvar upsample_default = `\\n\\tvar sourceTexture: texture_2d<f32>;\\n\\tvar sourceTextureSampler: sampler;\\n\\tuniform sourceInvResolution: vec2f;\\n\\tvarying uv0: vec2f;\\n\\t@fragment\\n\\tfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\t\\tvar output: FragmentOutput;\\n\\t\\tlet x: f32 = uniform.sourceInvResolution.x;\\n\\t\\tlet y: f32 = uniform.sourceInvResolution.y;\\n\\t\\tlet a: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x - x, input.uv0.y + y)).rgb);\\n\\t\\tlet b: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x,\\t input.uv0.y + y)).rgb);\\n\\t\\tlet c: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x + x, input.uv0.y + y)).rgb);\\n\\t\\tlet d: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x - x, input.uv0.y)).rgb);\\n\\t\\tlet e: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x,\\t input.uv0.y)).rgb);\\n\\t\\tlet f: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x + x, input.uv0.y)).rgb);\\n\\t\\tlet g: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x - x, input.uv0.y - y)).rgb);\\n\\t\\tlet h: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x,\\t input.uv0.y - y)).rgb);\\n\\t\\tlet i: half3 = half3(textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x + x, input.uv0.y - y)).rgb);\\n\\t\\tvar value: half3 = e * half(0.25);\\n\\t\\tvalue += (b + d + f + h) * half(0.125);\\n\\t\\tvalue += (a + c + g + i) * half(0.0625);\\n\\t\\toutput.color = vec4f(vec3f(value), 1.0);\\n\\t\\treturn output;\\n\\t}\\n`;\\n\\nclass RenderPassUpsample extends RenderPassShaderQuad {\\n\\tconstructor(device, sourceTexture) {\\n\\t\\tsuper(device);\\n\\t\\tthis.sourceTexture = sourceTexture;\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set(\\\"upsamplePS\\\", upsample_default$1);\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set(\\\"upsamplePS\\\", upsample_default);\\n\\t\\tthis.shader = ShaderUtils.createShader(device, {\\n\\t\\t\\tuniqueName: \\\"UpSampleShader\\\",\\n\\t\\t\\tattributes: { aPosition: SEMANTIC_POSITION },\\n\\t\\t\\tvertexChunk: \\\"quadVS\\\",\\n\\t\\t\\tfragmentChunk: \\\"upsamplePS\\\"\\n\\t\\t});\\n\\t\\tthis.sourceTextureId = device.scope.resolve(\\\"sourceTexture\\\");\\n\\t\\tthis.sourceInvResolutionId = device.scope.resolve(\\\"sourceInvResolution\\\");\\n\\t\\tthis.sourceInvResolutionValue = new Float32Array(2);\\n\\t}\\n\\texecute() {\\n\\t\\tthis.sourceTextureId.setValue(this.sourceTexture);\\n\\t\\tthis.sourceInvResolutionValue[0] = 1 / this.sourceTexture.width;\\n\\t\\tthis.sourceInvResolutionValue[1] = 1 / this.sourceTexture.height;\\n\\t\\tthis.sourceInvResolutionId.setValue(this.sourceInvResolutionValue);\\n\\t\\tsuper.execute();\\n\\t}\\n}\\n\\nclass FramePassBloom extends FramePass {\\n\\tbloomTexture;\\n\\tblurLevel = 16;\\n\\tbloomRenderTarget;\\n\\ttextureFormat;\\n\\trenderTargets = [];\\n\\tconstructor(device, sourceTexture, format) {\\n\\t\\tsuper(device);\\n\\t\\tthis._sourceTexture = sourceTexture;\\n\\t\\tthis.textureFormat = format;\\n\\t\\tthis.bloomRenderTarget = this.createRenderTarget(0);\\n\\t\\tthis.bloomTexture = this.bloomRenderTarget.colorBuffer;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.destroyRenderPasses();\\n\\t\\tthis.destroyRenderTargets();\\n\\t}\\n\\tdestroyRenderTargets(startIndex = 0) {\\n\\t\\tfor (let i = startIndex; i < this.renderTargets.length; i++) {\\n\\t\\t\\tconst rt = this.renderTargets[i];\\n\\t\\t\\trt.destroyTextureBuffers();\\n\\t\\t\\trt.destroy();\\n\\t\\t}\\n\\t\\tthis.renderTargets.length = 0;\\n\\t}\\n\\tdestroyRenderPasses() {\\n\\t\\tfor (let i = 0; i < this.beforePasses.length; i++) {\\n\\t\\t\\tthis.beforePasses[i].destroy();\\n\\t\\t}\\n\\t\\tthis.beforePasses.length = 0;\\n\\t}\\n\\tcreateRenderTarget(index) {\\n\\t\\treturn new RenderTarget({\\n\\t\\t\\tdepth: false,\\n\\t\\t\\tcolorBuffer: new Texture(this.device, {\\n\\t\\t\\t\\tname: `BloomTexture${index}`,\\n\\t\\t\\t\\twidth: 1,\\n\\t\\t\\t\\theight: 1,\\n\\t\\t\\t\\tformat: this.textureFormat,\\n\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\tminFilter: FILTER_LINEAR,\\n\\t\\t\\t\\tmagFilter: FILTER_LINEAR,\\n\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t\\t})\\n\\t\\t});\\n\\t}\\n\\tcreateRenderTargets(count) {\\n\\t\\tfor (let i = 0; i < count; i++) {\\n\\t\\t\\tconst rt = i === 0 ? this.bloomRenderTarget : this.createRenderTarget(i);\\n\\t\\t\\tthis.renderTargets.push(rt);\\n\\t\\t}\\n\\t}\\n\\t// number of levels till hitting min size\\n\\tcalcMipLevels(width, height, minSize) {\\n\\t\\tconst min = Math.min(width, height);\\n\\t\\treturn Math.floor(Math.log2(min) - Math.log2(minSize));\\n\\t}\\n\\tcreateRenderPasses(numPasses) {\\n\\t\\tconst device = this.device;\\n\\t\\tlet passSourceTexture = this._sourceTexture;\\n\\t\\tfor (let i = 0; i < numPasses; i++) {\\n\\t\\t\\tconst pass = new RenderPassDownsample(device, passSourceTexture);\\n\\t\\t\\tconst rt = this.renderTargets[i];\\n\\t\\t\\tpass.init(rt, {\\n\\t\\t\\t\\tresizeSource: passSourceTexture,\\n\\t\\t\\t\\tscaleX: 0.5,\\n\\t\\t\\t\\tscaleY: 0.5\\n\\t\\t\\t});\\n\\t\\t\\tpass.setClearColor(Color.BLACK);\\n\\t\\t\\tthis.beforePasses.push(pass);\\n\\t\\t\\tpassSourceTexture = rt.colorBuffer;\\n\\t\\t}\\n\\t\\tpassSourceTexture = this.renderTargets[numPasses - 1].colorBuffer;\\n\\t\\tfor (let i = numPasses - 2; i >= 0; i--) {\\n\\t\\t\\tconst pass = new RenderPassUpsample(device, passSourceTexture);\\n\\t\\t\\tconst rt = this.renderTargets[i];\\n\\t\\t\\tpass.init(rt);\\n\\t\\t\\tpass.blendState = BlendState.ADDBLEND;\\n\\t\\t\\tthis.beforePasses.push(pass);\\n\\t\\t\\tpassSourceTexture = rt.colorBuffer;\\n\\t\\t}\\n\\t}\\n\\tonDisable() {\\n\\t\\tthis.renderTargets[0]?.resize(1, 1);\\n\\t\\tthis.destroyRenderPasses();\\n\\t\\tthis.destroyRenderTargets(1);\\n\\t}\\n\\tframeUpdate() {\\n\\t\\tsuper.frameUpdate();\\n\\t\\tconst maxNumPasses = this.calcMipLevels(this._sourceTexture.width, this._sourceTexture.height, 1);\\n\\t\\tconst numPasses = math.clamp(maxNumPasses, 1, this.blurLevel);\\n\\t\\tif (this.renderTargets.length !== numPasses) {\\n\\t\\t\\tthis.destroyRenderPasses();\\n\\t\\t\\tthis.destroyRenderTargets(1);\\n\\t\\t\\tthis.createRenderTargets(numPasses);\\n\\t\\t\\tthis.createRenderPasses(numPasses);\\n\\t\\t}\\n\\t}\\n}\\n\\nvar compose_default$1 = `\\n\\t#include \\\"tonemappingPS\\\"\\n\\t#include \\\"gammaPS\\\"\\n\\tvarying vec2 uv0;\\n\\tuniform sampler2D sceneTexture;\\n\\tuniform vec2 sceneTextureInvRes;\\n\\t#include \\\"composeBloomPS\\\"\\n\\t#include \\\"composeDofPS\\\"\\n\\t#include \\\"composeSsaoPS\\\"\\n\\t#include \\\"composeGradingPS\\\"\\n\\t#include \\\"composeColorEnhancePS\\\"\\n\\t#include \\\"composeVignettePS\\\"\\n\\t#include \\\"composeFringingPS\\\"\\n\\t#include \\\"composeCasPS\\\"\\n\\t#include \\\"composeColorLutPS\\\"\\n\\t#include \\\"composeDeclarationsPS\\\"\\n\\tvoid main() {\\n\\t\\t#include \\\"composeMainStartPS\\\"\\n\\t\\tvec2 uv = uv0;\\n\\t\\tvec4 scene = texture2DLod(sceneTexture, uv, 0.0);\\n\\t\\tvec3 result = scene.rgb;\\n\\t\\t#ifdef CAS\\n\\t\\t\\tresult = applyCas(result, uv, sharpness);\\n\\t\\t#endif\\n\\t\\t#ifdef DOF\\n\\t\\t\\tresult = applyDof(result, uv0);\\n\\t\\t#endif\\n\\t\\t#ifdef SSAO_TEXTURE\\n\\t\\t\\tresult = applySsao(result, uv0);\\n\\t\\t#endif\\n\\t\\t#ifdef FRINGING\\n\\t\\t\\tresult = applyFringing(result, uv);\\n\\t\\t#endif\\n\\t\\t#ifdef BLOOM\\n\\t\\t\\tresult = applyBloom(result, uv0);\\n\\t\\t#endif\\n\\t\\t#ifdef COLOR_ENHANCE\\n\\t\\t\\tresult = applyColorEnhance(result);\\n\\t\\t#endif\\n\\t\\t#ifdef GRADING\\n\\t\\t\\tresult = applyGrading(result);\\n\\t\\t#endif\\n\\t\\tresult = toneMap(max(vec3(0.0), result));\\n\\t\\t#ifdef COLOR_LUT\\n\\t\\t\\tresult = applyColorLUT(result);\\n\\t\\t#endif\\n\\t\\t#ifdef VIGNETTE\\n\\t\\t\\tresult = applyVignette(result, uv);\\n\\t\\t#endif\\n\\t\\t#include \\\"composeMainEndPS\\\"\\n\\t\\t#ifdef DEBUG_COMPOSE\\n\\t\\t\\t#if DEBUG_COMPOSE == scene\\n\\t\\t\\t\\tresult = scene.rgb;\\n\\t\\t\\t#elif defined(BLOOM) && DEBUG_COMPOSE == bloom\\n\\t\\t\\t\\tresult = dBloom * bloomIntensity;\\n\\t\\t\\t#elif defined(DOF) && DEBUG_COMPOSE == dofcoc\\n\\t\\t\\t\\tresult = vec3(dCoc, 0.0);\\n\\t\\t\\t#elif defined(DOF) && DEBUG_COMPOSE == dofblur\\n\\t\\t\\t\\tresult = dBlur;\\n\\t\\t\\t#elif defined(SSAO_TEXTURE) && DEBUG_COMPOSE == ssao\\n\\t\\t\\t\\tresult = vec3(dSsao);\\n\\t\\t\\t#elif defined(VIGNETTE) && DEBUG_COMPOSE == vignette\\n\\t\\t\\t\\tresult = vec3(dVignette);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\tresult = gammaCorrectOutput(result);\\n\\t\\tgl_FragColor = vec4(result, scene.a);\\n\\t}\\n`;\\n\\nvar compose_bloom_default$1 = `\\n\\t#ifdef BLOOM\\n\\t\\tuniform sampler2D bloomTexture;\\n\\t\\tuniform float bloomIntensity;\\n\\t\\t\\n\\t\\tvec3 dBloom;\\n\\t\\t\\n\\t\\tvec3 applyBloom(vec3 color, vec2 uv) {\\n\\t\\t\\tdBloom = texture2DLod(bloomTexture, uv, 0.0).rgb;\\n\\t\\t\\treturn color + dBloom * bloomIntensity;\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar compose_dof_default$1 = `\\n\\t#ifdef DOF\\n\\t\\tuniform sampler2D cocTexture;\\n\\t\\tuniform sampler2D blurTexture;\\n\\t\\t\\n\\t\\tvec2 dCoc;\\n\\t\\tvec3 dBlur;\\n\\t\\tvec3 getDofBlur(vec2 uv) {\\n\\t\\t\\tdCoc = texture2DLod(cocTexture, uv, 0.0).rg;\\n\\t\\t\\t#if DOF_UPSCALE\\n\\t\\t\\t\\tvec2 blurTexelSize = 1.0 / vec2(textureSize(blurTexture, 0));\\n\\t\\t\\t\\tvec3 bilinearBlur = vec3(0.0);\\n\\t\\t\\t\\tfloat totalWeight = 0.0;\\n\\t\\t\\t\\tfor (int i = -1; i <= 1; i++) {\\n\\t\\t\\t\\t\\tfor (int j = -1; j <= 1; j++) {\\n\\t\\t\\t\\t\\t\\tvec2 offset = vec2(i, j) * blurTexelSize;\\n\\t\\t\\t\\t\\t\\tvec2 cocSample = texture2DLod(cocTexture, uv + offset, 0.0).rg;\\n\\t\\t\\t\\t\\t\\tvec3 blurSample = texture2DLod(blurTexture, uv + offset, 0.0).rgb;\\n\\t\\t\\t\\t\\t\\tfloat cocWeight = clamp(cocSample.r + cocSample.g, 0.0, 1.0);\\n\\t\\t\\t\\t\\t\\tbilinearBlur += blurSample * cocWeight;\\n\\t\\t\\t\\t\\t\\ttotalWeight += cocWeight;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (totalWeight > 0.0) {\\n\\t\\t\\t\\t\\tbilinearBlur /= totalWeight;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdBlur = bilinearBlur;\\n\\t\\t\\t\\treturn bilinearBlur;\\n\\t\\t\\t#else\\n\\t\\t\\t\\tdBlur = texture2DLod(blurTexture, uv, 0.0).rgb;\\n\\t\\t\\t\\treturn dBlur;\\n\\t\\t\\t#endif\\n\\t\\t}\\n\\t\\tvec3 applyDof(vec3 color, vec2 uv) {\\n\\t\\t\\tvec3 blur = getDofBlur(uv);\\n\\t\\t\\treturn mix(color, blur, dCoc.r + dCoc.g);\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar compose_ssao_default$1 = `\\n\\t#ifdef SSAO\\n\\t\\t#define SSAO_TEXTURE\\n\\t#endif\\n\\t#if DEBUG_COMPOSE == ssao\\n\\t\\t#define SSAO_TEXTURE\\n\\t#endif\\n\\t#ifdef SSAO_TEXTURE\\n\\t\\tuniform sampler2D ssaoTexture;\\n\\t\\t\\n\\t\\tfloat dSsao;\\n\\t\\t\\n\\t\\tvec3 applySsao(vec3 color, vec2 uv) {\\n\\t\\t\\tdSsao = texture2DLod(ssaoTexture, uv, 0.0).r;\\n\\t\\t\\t\\n\\t\\t\\t#ifdef SSAO\\n\\t\\t\\t\\treturn color * dSsao;\\n\\t\\t\\t#else\\n\\t\\t\\t\\treturn color;\\n\\t\\t\\t#endif\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar compose_grading_default$1 = `\\n\\t#ifdef GRADING\\n\\t\\tuniform vec3 brightnessContrastSaturation;\\n\\t\\tuniform vec3 tint;\\n\\t\\tvec3 colorGradingHDR(vec3 color, float brt, float sat, float con) {\\n\\t\\t\\tcolor *= tint;\\n\\t\\t\\tcolor = color * brt;\\n\\t\\t\\tfloat grey = dot(color, vec3(0.3, 0.59, 0.11));\\n\\t\\t\\tgrey = grey / max(1.0, max(color.r, max(color.g, color.b)));\\n\\t\\t\\tcolor = mix(vec3(grey), color, sat);\\n\\t\\t\\treturn mix(vec3(0.5), color, con);\\n\\t\\t}\\n\\t\\tvec3 applyGrading(vec3 color) {\\n\\t\\t\\treturn colorGradingHDR(color, \\n\\t\\t\\t\\tbrightnessContrastSaturation.x, \\n\\t\\t\\t\\tbrightnessContrastSaturation.z, \\n\\t\\t\\t\\tbrightnessContrastSaturation.y);\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar compose_color_enhance_default$1 = `\\n\\t#ifdef COLOR_ENHANCE\\n\\t\\tuniform vec4 colorEnhanceParams;\\n\\t\\tuniform float colorEnhanceMidtones;\\n\\t\\tvec3 applyColorEnhance(vec3 color) {\\n\\t\\t\\tfloat maxChannel = max(color.r, max(color.g, color.b));\\n\\t\\t\\tfloat lum = dot(color, vec3(0.2126, 0.7152, 0.0722));\\n\\t\\t\\tif (colorEnhanceParams.x != 0.0 || colorEnhanceParams.y != 0.0) {\\n\\t\\t\\t\\tfloat logLum = log2(max(lum, 0.001)) / 10.0 + 0.5;\\n\\t\\t\\t\\tlogLum = clamp(logLum, 0.0, 1.0);\\n\\t\\t\\t\\tfloat shadowWeight = pow(1.0 - logLum, 2.0);\\n\\t\\t\\t\\tfloat highlightWeight = pow(logLum, 2.0);\\n\\t\\t\\t\\tcolor *= pow(2.0, colorEnhanceParams.x * shadowWeight);\\n\\t\\t\\t\\tcolor *= pow(2.0, colorEnhanceParams.y * highlightWeight);\\n\\t\\t\\t}\\n\\t\\t\\tif (colorEnhanceMidtones != 0.0) {\\n\\t\\t\\t\\tconst float pivot = 0.18;\\n\\t\\t\\t\\tconst float widthStops = 1.25;\\n\\t\\t\\t\\tconst float maxStops = 2.0;\\n\\t\\t\\t\\tfloat y = max(dot(color, vec3(0.2126, 0.7152, 0.0722)), 1e-6);\\n\\t\\t\\t\\tfloat d = log2(y / pivot);\\n\\t\\t\\t\\tfloat w = exp(-(d * d) / (2.0 * widthStops * widthStops));\\n\\t\\t\\t\\tfloat stops = colorEnhanceMidtones * maxStops * w;\\n\\t\\t\\t\\tcolor *= exp2(stops);\\n\\t\\t\\t}\\n\\t\\t\\tif (colorEnhanceParams.z != 0.0) {\\n\\t\\t\\t\\tfloat minChannel = min(color.r, min(color.g, color.b));\\n\\t\\t\\t\\tmaxChannel = max(color.r, max(color.g, color.b));\\n\\t\\t\\t\\tfloat sat = (maxChannel - minChannel) / max(maxChannel, 0.001);\\n\\t\\t\\t\\tlum = dot(color, vec3(0.2126, 0.7152, 0.0722));\\n\\t\\t\\t\\tfloat normalizedLum = lum / max(1.0, maxChannel);\\n\\t\\t\\t\\tvec3 grey = vec3(normalizedLum) * maxChannel;\\n\\t\\t\\t\\tfloat satBoost = colorEnhanceParams.z * (1.0 - sat);\\n\\t\\t\\t\\tcolor = mix(grey, color, 1.0 + satBoost);\\n\\t\\t\\t}\\n\\t\\t\\tif (colorEnhanceParams.w != 0.0) {\\n\\t\\t\\t\\tmaxChannel = max(color.r, max(color.g, color.b));\\n\\t\\t\\t\\tfloat scale = max(1.0, maxChannel);\\n\\t\\t\\t\\tvec3 normalized = color / scale;\\n\\t\\t\\t\\tfloat darkChannel = min(normalized.r, min(normalized.g, normalized.b));\\n\\t\\t\\t\\tfloat atmosphericLight = 0.95;\\n\\t\\t\\t\\tfloat t = 1.0 - colorEnhanceParams.w * darkChannel / atmosphericLight;\\n\\t\\t\\t\\tt = max(t, 0.1);\\n\\t\\t\\t\\tvec3 dehazed = (normalized - atmosphericLight) / t + atmosphericLight;\\n\\t\\t\\t\\tcolor = dehazed * scale;\\n\\t\\t\\t}\\n\\t\\t\\treturn max(vec3(0.0), color);\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar compose_vignette_default$1 = `\\n\\t#ifdef VIGNETTE\\n\\t\\tuniform vec4 vignetterParams;\\n\\t\\tuniform vec3 vignetteColor;\\n\\t\\t\\n\\t\\tfloat dVignette;\\n\\t\\t\\n\\t\\tfloat calcVignette(vec2 uv) {\\n\\t\\t\\tfloat inner = vignetterParams.x;\\n\\t\\t\\tfloat outer = vignetterParams.y;\\n\\t\\t\\tfloat curvature = vignetterParams.z;\\n\\t\\t\\tfloat intensity = vignetterParams.w;\\n\\t\\t\\tvec2 curve = pow(abs(uv * 2.0 -1.0), vec2(1.0 / curvature));\\n\\t\\t\\tfloat edge = pow(length(curve), curvature);\\n\\t\\t\\tdVignette = 1.0 - intensity * smoothstep(inner, outer, edge);\\n\\t\\t\\treturn dVignette;\\n\\t\\t}\\n\\t\\tvec3 applyVignette(vec3 color, vec2 uv) {\\n\\t\\t\\treturn mix(vignetteColor, color, calcVignette(uv));\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar compose_fringing_default$1 = `\\n\\t#ifdef FRINGING\\n\\t\\tuniform float fringingIntensity;\\n\\t\\tvec3 applyFringing(vec3 color, vec2 uv) {\\n\\t\\t\\tvec2 centerDistance = uv - 0.5;\\n\\t\\t\\tvec2 offset = fringingIntensity * centerDistance * centerDistance;\\n\\t\\t\\tcolor.r = texture2D(sceneTexture, uv - offset).r;\\n\\t\\t\\tcolor.b = texture2D(sceneTexture, uv + offset).b;\\n\\t\\t\\treturn color;\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar compose_cas_default$1 = `\\n\\t#ifdef CAS\\n\\t\\tuniform float sharpness;\\n\\t\\t#ifdef CAS_HDR\\n\\t\\t\\tfloat maxComponent(float x, float y, float z) { return max(x, max(y, z)); }\\n\\t\\t\\tvec3 toSDR(vec3 c) { return c / (1.0 + maxComponent(c.r, c.g, c.b)); }\\n\\t\\t\\tvec3 toHDR(vec3 c) { return c / max(1.0 - maxComponent(c.r, c.g, c.b), 1e-4); }\\n\\t\\t#else\\n\\t\\t\\tvec3 toSDR(vec3 c) { return c; }\\n\\t\\t\\tvec3 toHDR(vec3 c) { return c; }\\n\\t\\t#endif\\n\\t\\tvec3 applyCas(vec3 color, vec2 uv, float sharpness) {\\n\\t\\t\\tfloat x = sceneTextureInvRes.x;\\n\\t\\t\\tfloat y = sceneTextureInvRes.y;\\n\\t\\t\\tvec3 a = toSDR(texture2DLod(sceneTexture, uv + vec2(0.0, -y), 0.0).rgb);\\n\\t\\t\\tvec3 b = toSDR(texture2DLod(sceneTexture, uv + vec2(-x, 0.0), 0.0).rgb);\\n\\t\\t\\tvec3 c = toSDR(color.rgb);\\n\\t\\t\\tvec3 d = toSDR(texture2DLod(sceneTexture, uv + vec2(x, 0.0), 0.0).rgb);\\n\\t\\t\\tvec3 e = toSDR(texture2DLod(sceneTexture, uv + vec2(0.0, y), 0.0).rgb);\\n\\t\\t\\tfloat min_g = min(a.g, min(b.g, min(c.g, min(d.g, e.g))));\\n\\t\\t\\tfloat max_g = max(a.g, max(b.g, max(c.g, max(d.g, e.g))));\\n\\t\\t\\tfloat sharpening_amount = sqrt(min(1.0 - max_g, min_g) / max(max_g, 1e-4));\\n\\t\\t\\tfloat w = sharpening_amount * sharpness;\\n\\t\\t\\tvec3 res = (w * (a + b + d + e) + c) / (4.0 * w + 1.0);\\n\\t\\t\\tres = max(res, 0.0);\\n\\t\\t\\treturn toHDR(res);\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar compose_color_lut_default$1 = `\\n\\t#ifdef COLOR_LUT\\n\\t\\tconst float COLOR_LUT_N = 16.0;\\n\\t\\tconst float COLOR_LUT_W = 256.0;\\n\\t\\tconst float COLOR_LUT_MAX = COLOR_LUT_N - 1.0;\\n\\t\\tconst float COLOR_LUT_HALF_PX_X = 0.5 / COLOR_LUT_W;\\n\\t\\tconst float COLOR_LUT_HALF_PX_Y = 0.5 / COLOR_LUT_N;\\n\\t\\tconst float COLOR_LUT_R_SCALE = COLOR_LUT_MAX / COLOR_LUT_W;\\n\\t\\tconst float COLOR_LUT_G_SCALE = COLOR_LUT_MAX / COLOR_LUT_N;\\n\\t\\tconst float COLOR_LUT_SLICE = 1.0 / COLOR_LUT_N;\\n\\t\\tuniform vec3 colorLUTParams;\\n\\t\\tuniform sampler2D colorLUT;\\n\\t\\t#ifdef COLOR_LUT2\\n\\t\\t\\tuniform sampler2D colorLUT2;\\n\\t\\t#endif\\n\\t\\tvec3 sampleColorLUT(sampler2D lut, vec2 uv_l, vec2 uv_h, float t) {\\n\\t\\t\\tvec3 color_l = texture2DLod(lut, uv_l, 0.0).rgb;\\n\\t\\t\\tvec3 color_h = texture2DLod(lut, uv_h, 0.0).rgb;\\n\\t\\t\\treturn mix(color_l, color_h, t);\\n\\t\\t}\\n\\t\\tvec3 applyColorLUT(vec3 color) {\\n\\t\\t\\tvec3 srgbCoord = pow(max(color, vec3(0.0)) + 0.0000001, vec3(1.0 / 2.2));\\n\\t\\t\\tvec3 c = clamp(srgbCoord, 0.0, 1.0);\\n\\t\\t\\tfloat cell = c.b * COLOR_LUT_MAX;\\n\\t\\t\\tfloat cell_l = floor(cell);\\n\\t\\t\\tfloat cell_h = ceil(cell);\\n\\t\\t\\tfloat t = fract(cell);\\n\\t\\t\\tfloat r_offset = COLOR_LUT_HALF_PX_X + c.r * COLOR_LUT_R_SCALE;\\n\\t\\t\\tfloat g_offset = COLOR_LUT_HALF_PX_Y + c.g * COLOR_LUT_G_SCALE;\\n\\t\\t\\tvec2 uv_l = vec2(cell_l * COLOR_LUT_SLICE + r_offset, g_offset);\\n\\t\\t\\tvec2 uv_h = vec2(cell_h * COLOR_LUT_SLICE + r_offset, g_offset);\\n\\t\\t\\tvec3 lut1 = sampleColorLUT(colorLUT, uv_l, uv_h, t);\\n\\t\\t\\t#ifdef COLOR_LUT2\\n\\t\\t\\t\\tvec3 lut2 = sampleColorLUT(colorLUT2, uv_l, uv_h, t);\\n\\t\\t\\t\\tfloat w1 = colorLUTParams.x * (1.0 - colorLUTParams.z);\\n\\t\\t\\t\\tfloat w2 = colorLUTParams.y * colorLUTParams.z;\\n\\t\\t\\t\\treturn color + (lut1 - color) * w1 + (lut2 - color) * w2;\\n\\t\\t\\t#else\\n\\t\\t\\t\\treturn mix(color, lut1, colorLUTParams.x);\\n\\t\\t\\t#endif\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nconst composeChunksGLSL = {\\n\\tcomposePS: compose_default$1,\\n\\tcomposeBloomPS: compose_bloom_default$1,\\n\\tcomposeDofPS: compose_dof_default$1,\\n\\tcomposeSsaoPS: compose_ssao_default$1,\\n\\tcomposeGradingPS: compose_grading_default$1,\\n\\tcomposeColorEnhancePS: compose_color_enhance_default$1,\\n\\tcomposeVignettePS: compose_vignette_default$1,\\n\\tcomposeFringingPS: compose_fringing_default$1,\\n\\tcomposeCasPS: compose_cas_default$1,\\n\\tcomposeColorLutPS: compose_color_lut_default$1,\\n\\t// empty chunks for user customizations\\n\\tcomposeDeclarationsPS: \\\"\\\",\\n\\tcomposeMainStartPS: \\\"\\\",\\n\\tcomposeMainEndPS: \\\"\\\"\\n};\\n\\nvar compose_default = `\\n\\t#include \\\"tonemappingPS\\\"\\n\\t#include \\\"gammaPS\\\"\\n\\tvarying uv0: vec2f;\\n\\tvar sceneTexture: texture_2d<f32>;\\n\\tvar sceneTextureSampler: sampler;\\n\\tuniform sceneTextureInvRes: vec2f;\\n\\t#include \\\"composeBloomPS\\\"\\n\\t#include \\\"composeDofPS\\\"\\n\\t#include \\\"composeSsaoPS\\\"\\n\\t#include \\\"composeGradingPS\\\"\\n\\t#include \\\"composeColorEnhancePS\\\"\\n\\t#include \\\"composeVignettePS\\\"\\n\\t#include \\\"composeFringingPS\\\"\\n\\t#include \\\"composeCasPS\\\"\\n\\t#include \\\"composeColorLutPS\\\"\\n\\t#include \\\"composeDeclarationsPS\\\"\\n\\t@fragment\\n\\tfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\t\\t#include \\\"composeMainStartPS\\\"\\n\\t\\tvar output: FragmentOutput;\\n\\t\\tvar uv = uv0;\\n\\t\\tlet scene = textureSampleLevel(sceneTexture, sceneTextureSampler, uv, 0.0);\\n\\t\\tvar result = scene.rgb;\\n\\t\\t#ifdef CAS\\n\\t\\t\\tresult = applyCas(result, uv, uniform.sharpness);\\n\\t\\t#endif\\n\\t\\t#ifdef DOF\\n\\t\\t\\tresult = applyDof(result, uv0);\\n\\t\\t#endif\\n\\t\\t#ifdef SSAO_TEXTURE\\n\\t\\t\\tresult = applySsao(result, uv0);\\n\\t\\t#endif\\n\\t\\t#ifdef FRINGING\\n\\t\\t\\tresult = applyFringing(result, uv);\\n\\t\\t#endif\\n\\t\\t#ifdef BLOOM\\n\\t\\t\\tresult = applyBloom(result, uv0);\\n\\t\\t#endif\\n\\t\\t#ifdef COLOR_ENHANCE\\n\\t\\t\\tresult = applyColorEnhance(result);\\n\\t\\t#endif\\n\\t\\t#ifdef GRADING\\n\\t\\t\\tresult = applyGrading(result);\\n\\t\\t#endif\\n\\t\\tresult = toneMap(max(vec3f(0.0), result));\\n\\t\\t#ifdef COLOR_LUT\\n\\t\\t\\tresult = applyColorLUT(result);\\n\\t\\t#endif\\n\\t\\t#ifdef VIGNETTE\\n\\t\\t\\tresult = applyVignette(result, uv);\\n\\t\\t#endif\\n\\t\\t#include \\\"composeMainEndPS\\\"\\n\\t\\t#ifdef DEBUG_COMPOSE\\n\\t\\t\\t#if DEBUG_COMPOSE == scene\\n\\t\\t\\t\\tresult = scene.rgb;\\n\\t\\t\\t#elif defined(BLOOM) && DEBUG_COMPOSE == bloom\\n\\t\\t\\t\\tresult = dBloom * uniform.bloomIntensity;\\n\\t\\t\\t#elif defined(DOF) && DEBUG_COMPOSE == dofcoc\\n\\t\\t\\t\\tresult = vec3f(dCoc, 0.0);\\n\\t\\t\\t#elif defined(DOF) && DEBUG_COMPOSE == dofblur\\n\\t\\t\\t\\tresult = dBlur;\\n\\t\\t\\t#elif defined(SSAO_TEXTURE) && DEBUG_COMPOSE == ssao\\n\\t\\t\\t\\tresult = vec3f(dSsao);\\n\\t\\t\\t#elif defined(VIGNETTE) && DEBUG_COMPOSE == vignette\\n\\t\\t\\t\\tresult = vec3f(dVignette);\\n\\t\\t\\t#endif\\n\\t\\t#endif\\n\\t\\tresult = gammaCorrectOutput(result);\\n\\t\\toutput.color = vec4f(result, scene.a);\\n\\t\\treturn output;\\n\\t}\\n`;\\n\\nvar compose_bloom_default = `\\n\\t#ifdef BLOOM\\n\\t\\tvar bloomTexture: texture_2d<f32>;\\n\\t\\tvar bloomTextureSampler: sampler;\\n\\t\\tuniform bloomIntensity: f32;\\n\\t\\t\\n\\t\\tvar<private> dBloom: vec3f;\\n\\t\\t\\n\\t\\tfn applyBloom(color: vec3f, uv: vec2f) -> vec3f {\\n\\t\\t\\tdBloom = textureSampleLevel(bloomTexture, bloomTextureSampler, uv, 0.0).rgb;\\n\\t\\t\\treturn color + dBloom * uniform.bloomIntensity;\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar compose_dof_default = `\\n\\t#ifdef DOF\\n\\t\\tvar cocTexture: texture_2d<f32>;\\n\\t\\tvar cocTextureSampler: sampler;\\n\\t\\tvar blurTexture: texture_2d<f32>;\\n\\t\\tvar blurTextureSampler: sampler;\\n\\t\\t\\n\\t\\tvar<private> dCoc: vec2f;\\n\\t\\tvar<private> dBlur: vec3f;\\n\\t\\tfn getDofBlur(uv: vec2f) -> vec3f {\\n\\t\\t\\tdCoc = textureSampleLevel(cocTexture, cocTextureSampler, uv, 0.0).rg;\\n\\t\\t\\t#if DOF_UPSCALE\\n\\t\\t\\t\\tlet blurTexelSize = 1.0 / vec2f(textureDimensions(blurTexture, 0));\\n\\t\\t\\t\\tvar bilinearBlur = vec3f(0.0);\\n\\t\\t\\t\\tvar totalWeight = 0.0;\\n\\t\\t\\t\\tfor (var i = -1; i <= 1; i++) {\\n\\t\\t\\t\\t\\tfor (var j = -1; j <= 1; j++) {\\n\\t\\t\\t\\t\\t\\tlet offset = vec2f(f32(i), f32(j)) * blurTexelSize;\\n\\t\\t\\t\\t\\t\\tlet cocSample = textureSampleLevel(cocTexture, cocTextureSampler, uv + offset, 0.0).rg;\\n\\t\\t\\t\\t\\t\\tlet blurSample = textureSampleLevel(blurTexture, blurTextureSampler, uv + offset, 0.0).rgb;\\n\\t\\t\\t\\t\\t\\tlet cocWeight = clamp(cocSample.r + cocSample.g, 0.0, 1.0);\\n\\t\\t\\t\\t\\t\\tbilinearBlur += blurSample * cocWeight;\\n\\t\\t\\t\\t\\t\\ttotalWeight += cocWeight;\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (totalWeight > 0.0) {\\n\\t\\t\\t\\t\\tbilinearBlur /= totalWeight;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdBlur = bilinearBlur;\\n\\t\\t\\t\\treturn bilinearBlur;\\n\\t\\t\\t#else\\n\\t\\t\\t\\tdBlur = textureSampleLevel(blurTexture, blurTextureSampler, uv, 0.0).rgb;\\n\\t\\t\\t\\treturn dBlur;\\n\\t\\t\\t#endif\\n\\t\\t}\\n\\t\\tfn applyDof(color: vec3f, uv: vec2f) -> vec3f {\\n\\t\\t\\tlet blur = getDofBlur(uv);\\n\\t\\t\\treturn mix(color, blur, dCoc.r + dCoc.g);\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar compose_ssao_default = `\\n\\t#ifdef SSAO\\n\\t\\t#define SSAO_TEXTURE\\n\\t#endif\\n\\t#if DEBUG_COMPOSE == ssao\\n\\t\\t#define SSAO_TEXTURE\\n\\t#endif\\n\\t#ifdef SSAO_TEXTURE\\n\\t\\tvar ssaoTexture: texture_2d<f32>;\\n\\t\\tvar ssaoTextureSampler: sampler;\\n\\t\\t\\n\\t\\tvar<private> dSsao: f32;\\n\\t\\t\\n\\t\\tfn applySsao(color: vec3f, uv: vec2f) -> vec3f {\\n\\t\\t\\tdSsao = textureSampleLevel(ssaoTexture, ssaoTextureSampler, uv, 0.0).r;\\n\\t\\t\\t\\n\\t\\t\\t#ifdef SSAO\\n\\t\\t\\t\\treturn color * dSsao;\\n\\t\\t\\t#else\\n\\t\\t\\t\\treturn color;\\n\\t\\t\\t#endif\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar compose_grading_default = `\\n\\t#ifdef GRADING\\n\\t\\tuniform brightnessContrastSaturation: vec3f;\\n\\t\\tuniform tint: vec3f;\\n\\t\\tfn colorGradingHDR(color: vec3f, brt: f32, sat: f32, con: f32) -> vec3f {\\n\\t\\t\\tvar colorOut = color * uniform.tint;\\n\\t\\t\\tcolorOut = colorOut * brt;\\n\\t\\t\\tlet grey = dot(colorOut, vec3f(0.3, 0.59, 0.11));\\n\\t\\t\\tlet normalizedGrey = grey / max(1.0, max(colorOut.r, max(colorOut.g, colorOut.b)));\\n\\t\\t\\tcolorOut = mix(vec3f(normalizedGrey), colorOut, sat);\\n\\t\\t\\treturn mix(vec3f(0.5), colorOut, con);\\n\\t\\t}\\n\\t\\tfn applyGrading(color: vec3f) -> vec3f {\\n\\t\\t\\treturn colorGradingHDR(color, \\n\\t\\t\\t\\tuniform.brightnessContrastSaturation.x, \\n\\t\\t\\t\\tuniform.brightnessContrastSaturation.z, \\n\\t\\t\\t\\tuniform.brightnessContrastSaturation.y);\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar compose_color_enhance_default = `\\n\\t#ifdef COLOR_ENHANCE\\n\\t\\tuniform colorEnhanceParams: vec4f;\\n\\t\\tuniform colorEnhanceMidtones: f32;\\n\\t\\tfn applyColorEnhance(color: vec3f) -> vec3f {\\n\\t\\t\\tvar colorOut = color;\\n\\t\\t\\tvar maxChannel = max(colorOut.r, max(colorOut.g, colorOut.b));\\n\\t\\t\\tvar lum = dot(colorOut, vec3f(0.2126, 0.7152, 0.0722));\\n\\t\\t\\tif (uniform.colorEnhanceParams.x != 0.0 || uniform.colorEnhanceParams.y != 0.0) {\\n\\t\\t\\t\\tvar logLum = log2(max(lum, 0.001)) / 10.0 + 0.5;\\n\\t\\t\\t\\tlogLum = clamp(logLum, 0.0, 1.0);\\n\\t\\t\\t\\tlet shadowWeight = pow(1.0 - logLum, 2.0);\\n\\t\\t\\t\\tlet highlightWeight = pow(logLum, 2.0);\\n\\t\\t\\t\\tcolorOut *= pow(2.0, uniform.colorEnhanceParams.x * shadowWeight);\\n\\t\\t\\t\\tcolorOut *= pow(2.0, uniform.colorEnhanceParams.y * highlightWeight);\\n\\t\\t\\t}\\n\\t\\t\\tif (uniform.colorEnhanceMidtones != 0.0) {\\n\\t\\t\\t\\tlet pivot = 0.18;\\n\\t\\t\\t\\tlet widthStops = 1.25;\\n\\t\\t\\t\\tlet maxStops = 2.0;\\n\\t\\t\\t\\tlet y = max(dot(colorOut, vec3f(0.2126, 0.7152, 0.0722)), 1e-6);\\n\\t\\t\\t\\tlet d = log2(y / pivot);\\n\\t\\t\\t\\tlet w = exp(-(d * d) / (2.0 * widthStops * widthStops));\\n\\t\\t\\t\\tlet stops = uniform.colorEnhanceMidtones * maxStops * w;\\n\\t\\t\\t\\tcolorOut *= exp2(stops);\\n\\t\\t\\t}\\n\\t\\t\\tif (uniform.colorEnhanceParams.z != 0.0) {\\n\\t\\t\\t\\tlet minChannel = min(colorOut.r, min(colorOut.g, colorOut.b));\\n\\t\\t\\t\\tmaxChannel = max(colorOut.r, max(colorOut.g, colorOut.b));\\n\\t\\t\\t\\tlet sat = (maxChannel - minChannel) / max(maxChannel, 0.001);\\n\\t\\t\\t\\tlum = dot(colorOut, vec3f(0.2126, 0.7152, 0.0722));\\n\\t\\t\\t\\tlet normalizedLum = lum / max(1.0, maxChannel);\\n\\t\\t\\t\\tlet grey = vec3f(normalizedLum) * maxChannel;\\n\\t\\t\\t\\tlet satBoost = uniform.colorEnhanceParams.z * (1.0 - sat);\\n\\t\\t\\t\\tcolorOut = mix(grey, colorOut, 1.0 + satBoost);\\n\\t\\t\\t}\\n\\t\\t\\tif (uniform.colorEnhanceParams.w != 0.0) {\\n\\t\\t\\t\\tmaxChannel = max(colorOut.r, max(colorOut.g, colorOut.b));\\n\\t\\t\\t\\tlet scale = max(1.0, maxChannel);\\n\\t\\t\\t\\tlet normalized = colorOut / scale;\\n\\t\\t\\t\\tlet darkChannel = min(normalized.r, min(normalized.g, normalized.b));\\n\\t\\t\\t\\tlet atmosphericLight = 0.95;\\n\\t\\t\\t\\tvar t = 1.0 - uniform.colorEnhanceParams.w * darkChannel / atmosphericLight;\\n\\t\\t\\t\\tt = max(t, 0.1);\\n\\t\\t\\t\\tlet dehazed = (normalized - atmosphericLight) / t + atmosphericLight;\\n\\t\\t\\t\\tcolorOut = dehazed * scale;\\n\\t\\t\\t}\\n\\t\\t\\treturn max(vec3f(0.0), colorOut);\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar compose_vignette_default = `\\n\\t#ifdef VIGNETTE\\n\\t\\tuniform vignetterParams: vec4f;\\n\\t\\tuniform vignetteColor: vec3f;\\n\\t\\t\\n\\t\\tvar<private> dVignette: f32;\\n\\t\\t\\n\\t\\tfn calcVignette(uv: vec2f) -> f32 {\\n\\t\\t\\tlet inner = uniform.vignetterParams.x;\\n\\t\\t\\tlet outer = uniform.vignetterParams.y;\\n\\t\\t\\tlet curvature = uniform.vignetterParams.z;\\n\\t\\t\\tlet intensity = uniform.vignetterParams.w;\\n\\t\\t\\tlet curve = pow(abs(uv * 2.0 - 1.0), vec2f(1.0 / curvature));\\n\\t\\t\\tlet edge = pow(length(curve), curvature);\\n\\t\\t\\tdVignette = 1.0 - intensity * smoothstep(inner, outer, edge);\\n\\t\\t\\treturn dVignette;\\n\\t\\t}\\n\\t\\tfn applyVignette(color: vec3f, uv: vec2f) -> vec3f {\\n\\t\\t\\treturn mix(uniform.vignetteColor, color, calcVignette(uv));\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar compose_fringing_default = `\\n\\t#ifdef FRINGING\\n\\t\\tuniform fringingIntensity: f32;\\n\\t\\tfn applyFringing(color: vec3f, uv: vec2f) -> vec3f {\\n\\t\\t\\tlet centerDistance = uv - 0.5;\\n\\t\\t\\tlet offset = uniform.fringingIntensity * centerDistance * centerDistance;\\n\\t\\t\\tvar colorOut = color;\\n\\t\\t\\tcolorOut.r = textureSample(sceneTexture, sceneTextureSampler, uv - offset).r;\\n\\t\\t\\tcolorOut.b = textureSample(sceneTexture, sceneTextureSampler, uv + offset).b;\\n\\t\\t\\treturn colorOut;\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar compose_cas_default = `\\n\\t#ifdef CAS\\n\\t\\tuniform sharpness: f32;\\n\\t\\t#ifdef CAS_HDR\\n\\t\\t\\tfn maxComponent(x: f32, y: f32, z: f32) -> f32 { return max(x, max(y, z)); }\\n\\t\\t\\tfn toSDR(c: vec3f) -> vec3f { return c / (1.0 + maxComponent(c.r, c.g, c.b)); }\\n\\t\\t\\tfn toHDR(c: vec3f) -> vec3f { return c / max(1.0 - maxComponent(c.r, c.g, c.b), 1e-4); }\\n\\t\\t#else\\n\\t\\t\\tfn toSDR(c: vec3f) -> vec3f { return c; }\\n\\t\\t\\tfn toHDR(c: vec3f) -> vec3f { return c; }\\n\\t\\t#endif\\n\\t\\tfn applyCas(color: vec3f, uv: vec2f, sharpness: f32) -> vec3f {\\n\\t\\t\\tlet x = uniform.sceneTextureInvRes.x;\\n\\t\\t\\tlet y = uniform.sceneTextureInvRes.y;\\n\\t\\t\\tlet a: half3 = half3(toSDR(textureSampleLevel(sceneTexture, sceneTextureSampler, uv + vec2f(0.0, -y), 0.0).rgb));\\n\\t\\t\\tlet b: half3 = half3(toSDR(textureSampleLevel(sceneTexture, sceneTextureSampler, uv + vec2f(-x, 0.0), 0.0).rgb));\\n\\t\\t\\tlet c: half3 = half3(toSDR(color.rgb));\\n\\t\\t\\tlet d: half3 = half3(toSDR(textureSampleLevel(sceneTexture, sceneTextureSampler, uv + vec2f(x, 0.0), 0.0).rgb));\\n\\t\\t\\tlet e: half3 = half3(toSDR(textureSampleLevel(sceneTexture, sceneTextureSampler, uv + vec2f(0.0, y), 0.0).rgb));\\n\\t\\t\\tlet min_g = min(a.g, min(b.g, min(c.g, min(d.g, e.g))));\\n\\t\\t\\tlet max_g = max(a.g, max(b.g, max(c.g, max(d.g, e.g))));\\n\\t\\t\\tlet sharpening_amount = sqrt(min(half(1.0) - max_g, min_g) / max(max_g, half(1e-4)));\\n\\t\\t\\tlet w = sharpening_amount * half(sharpness);\\n\\t\\t\\tvar res = (w * (a + b + d + e) + c) / (half(4.0) * w + half(1.0));\\n\\t\\t\\tres = max(res, half3(0.0));\\n\\t\\t\\treturn toHDR(vec3f(res));\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar compose_color_lut_default = `\\n\\t#ifdef COLOR_LUT\\n\\t\\tconst COLOR_LUT_N: f32 = 16.0;\\n\\t\\tconst COLOR_LUT_W: f32 = 256.0;\\n\\t\\tconst COLOR_LUT_MAX: f32 = COLOR_LUT_N - 1.0;\\n\\t\\tconst COLOR_LUT_HALF_PX_X: f32 = 0.5 / COLOR_LUT_W;\\n\\t\\tconst COLOR_LUT_HALF_PX_Y: f32 = 0.5 / COLOR_LUT_N;\\n\\t\\tconst COLOR_LUT_R_SCALE: f32 = COLOR_LUT_MAX / COLOR_LUT_W;\\n\\t\\tconst COLOR_LUT_G_SCALE: f32 = COLOR_LUT_MAX / COLOR_LUT_N;\\n\\t\\tconst COLOR_LUT_SLICE: f32 = 1.0 / COLOR_LUT_N;\\n\\t\\tuniform colorLUTParams: vec3f;\\n\\t\\tvar colorLUT: texture_2d<f32>;\\n\\t\\tvar colorLUTSampler: sampler;\\n\\t\\t#ifdef COLOR_LUT2\\n\\t\\t\\tvar colorLUT2: texture_2d<f32>;\\n\\t\\t\\tvar colorLUT2Sampler: sampler;\\n\\t\\t#endif\\n\\t\\tfn sampleColorLUT(lut: texture_2d<f32>, lutSampler: sampler, uv_l: vec2f, uv_h: vec2f, t: f32) -> vec3f {\\n\\t\\t\\tlet color_l: vec3f = textureSampleLevel(lut, lutSampler, uv_l, 0.0).rgb;\\n\\t\\t\\tlet color_h: vec3f = textureSampleLevel(lut, lutSampler, uv_h, 0.0).rgb;\\n\\t\\t\\treturn mix(color_l, color_h, vec3f(t));\\n\\t\\t}\\n\\t\\tfn applyColorLUT(color: vec3f) -> vec3f {\\n\\t\\t\\tlet srgbCoord: vec3f = pow(max(color, vec3f(0.0)) + vec3f(0.0000001), vec3f(1.0 / 2.2));\\n\\t\\t\\tlet c: vec3f = clamp(srgbCoord, vec3f(0.0), vec3f(1.0));\\n\\t\\t\\tlet cell: f32 = c.b * COLOR_LUT_MAX;\\n\\t\\t\\tlet cell_l: f32 = floor(cell);\\n\\t\\t\\tlet cell_h: f32 = ceil(cell);\\n\\t\\t\\tlet t: f32 = fract(cell);\\n\\t\\t\\tlet r_offset: f32 = COLOR_LUT_HALF_PX_X + c.r * COLOR_LUT_R_SCALE;\\n\\t\\t\\tlet g_offset: f32 = COLOR_LUT_HALF_PX_Y + c.g * COLOR_LUT_G_SCALE;\\n\\t\\t\\tlet uv_l: vec2f = vec2f(cell_l * COLOR_LUT_SLICE + r_offset, g_offset);\\n\\t\\t\\tlet uv_h: vec2f = vec2f(cell_h * COLOR_LUT_SLICE + r_offset, g_offset);\\n\\t\\t\\tlet lut1: vec3f = sampleColorLUT(colorLUT, colorLUTSampler, uv_l, uv_h, t);\\n\\t\\t\\t#ifdef COLOR_LUT2\\n\\t\\t\\t\\tlet lut2: vec3f = sampleColorLUT(colorLUT2, colorLUT2Sampler, uv_l, uv_h, t);\\n\\t\\t\\t\\tlet w1: f32 = uniform.colorLUTParams.x * (1.0 - uniform.colorLUTParams.z);\\n\\t\\t\\t\\tlet w2: f32 = uniform.colorLUTParams.y * uniform.colorLUTParams.z;\\n\\t\\t\\t\\treturn color + (lut1 - color) * w1 + (lut2 - color) * w2;\\n\\t\\t\\t#else\\n\\t\\t\\t\\treturn mix(color, lut1, vec3f(uniform.colorLUTParams.x));\\n\\t\\t\\t#endif\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nconst composeChunksWGSL = {\\n\\tcomposePS: compose_default,\\n\\tcomposeBloomPS: compose_bloom_default,\\n\\tcomposeDofPS: compose_dof_default,\\n\\tcomposeSsaoPS: compose_ssao_default,\\n\\tcomposeGradingPS: compose_grading_default,\\n\\tcomposeColorEnhancePS: compose_color_enhance_default,\\n\\tcomposeVignettePS: compose_vignette_default,\\n\\tcomposeFringingPS: compose_fringing_default,\\n\\tcomposeCasPS: compose_cas_default,\\n\\tcomposeColorLutPS: compose_color_lut_default,\\n\\t// empty chunks for user customizations\\n\\tcomposeDeclarationsPS: \\\"\\\",\\n\\tcomposeMainStartPS: \\\"\\\",\\n\\tcomposeMainEndPS: \\\"\\\"\\n};\\n\\nclass RenderPassCompose extends RenderPassShaderQuad {\\n\\tsceneTexture = null;\\n\\tbloomIntensity = 0.01;\\n\\t_bloomTexture = null;\\n\\t_cocTexture = null;\\n\\tblurTexture = null;\\n\\tblurTextureUpscale = false;\\n\\t_ssaoTexture = null;\\n\\t_toneMapping = TONEMAP_LINEAR;\\n\\t_gradingEnabled = false;\\n\\tgradingSaturation = 1;\\n\\tgradingContrast = 1;\\n\\tgradingBrightness = 1;\\n\\tgradingTint = new Color(1, 1, 1, 1);\\n\\t_shaderDirty = true;\\n\\t_vignetteEnabled = false;\\n\\tvignetteInner = 0.5;\\n\\tvignetteOuter = 1;\\n\\tvignetteCurvature = 0.5;\\n\\tvignetteIntensity = 0.3;\\n\\tvignetteColor = new Color(0, 0, 0);\\n\\t_fringingEnabled = false;\\n\\tfringingIntensity = 10;\\n\\t_colorEnhanceEnabled = false;\\n\\tcolorEnhanceShadows = 0;\\n\\tcolorEnhanceHighlights = 0;\\n\\tcolorEnhanceVibrance = 0;\\n\\tcolorEnhanceDehaze = 0;\\n\\tcolorEnhanceMidtones = 0;\\n\\t_taaEnabled = false;\\n\\t_hdrScene = true;\\n\\t_sharpness = 0.5;\\n\\t_gammaCorrection = GAMMA_SRGB;\\n\\t_colorLUT = null;\\n\\t_colorLUT2 = null;\\n\\tcolorLUTIntensity = 1;\\n\\tcolorLUT2Intensity = 1;\\n\\tcolorLUTBlend = 0;\\n\\t_key = \\\"\\\";\\n\\t_debug = null;\\n\\t// track user-provided custom compose chunks\\n\\t_customComposeChunks = /* @__PURE__ */ new Map([\\n\\t\\t[\\\"composeDeclarationsPS\\\", \\\"\\\"],\\n\\t\\t[\\\"composeMainStartPS\\\", \\\"\\\"],\\n\\t\\t[\\\"composeMainEndPS\\\", \\\"\\\"]\\n\\t]);\\n\\tconstructor(graphicsDevice) {\\n\\t\\tsuper(graphicsDevice);\\n\\t\\tShaderChunks.get(graphicsDevice, SHADERLANGUAGE_GLSL).add(composeChunksGLSL, false);\\n\\t\\tShaderChunks.get(graphicsDevice, SHADERLANGUAGE_WGSL).add(composeChunksWGSL, false);\\n\\t\\tconst { scope } = graphicsDevice;\\n\\t\\tthis.sceneTextureId = scope.resolve(\\\"sceneTexture\\\");\\n\\t\\tthis.bloomTextureId = scope.resolve(\\\"bloomTexture\\\");\\n\\t\\tthis.cocTextureId = scope.resolve(\\\"cocTexture\\\");\\n\\t\\tthis.ssaoTextureId = scope.resolve(\\\"ssaoTexture\\\");\\n\\t\\tthis.blurTextureId = scope.resolve(\\\"blurTexture\\\");\\n\\t\\tthis.bloomIntensityId = scope.resolve(\\\"bloomIntensity\\\");\\n\\t\\tthis.bcsId = scope.resolve(\\\"brightnessContrastSaturation\\\");\\n\\t\\tthis.tintId = scope.resolve(\\\"tint\\\");\\n\\t\\tthis.vignetterParamsId = scope.resolve(\\\"vignetterParams\\\");\\n\\t\\tthis.vignetteColorId = scope.resolve(\\\"vignetteColor\\\");\\n\\t\\tthis.fringingIntensityId = scope.resolve(\\\"fringingIntensity\\\");\\n\\t\\tthis.sceneTextureInvResId = scope.resolve(\\\"sceneTextureInvRes\\\");\\n\\t\\tthis.sceneTextureInvResValue = new Float32Array(2);\\n\\t\\tthis.sharpnessId = scope.resolve(\\\"sharpness\\\");\\n\\t\\tthis.colorLUTId = scope.resolve(\\\"colorLUT\\\");\\n\\t\\tthis.colorLUT2Id = scope.resolve(\\\"colorLUT2\\\");\\n\\t\\tthis.colorLUTParams = new Float32Array(3);\\n\\t\\tthis.colorLUTParamsId = scope.resolve(\\\"colorLUTParams\\\");\\n\\t\\tthis.colorEnhanceParamsId = scope.resolve(\\\"colorEnhanceParams\\\");\\n\\t\\tthis.colorEnhanceMidtonesId = scope.resolve(\\\"colorEnhanceMidtones\\\");\\n\\t}\\n\\tset debug(value) {\\n\\t\\tif (this._debug !== value) {\\n\\t\\t\\tthis._debug = value;\\n\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget debug() {\\n\\t\\treturn this._debug;\\n\\t}\\n\\tset colorLUT(value) {\\n\\t\\tif (this._colorLUT !== value) {\\n\\t\\t\\tthis._colorLUT = value;\\n\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t\\tthis._validateColorLUT(value, \\\"colorLUT\\\");\\n\\t\\t}\\n\\t}\\n\\tget colorLUT() {\\n\\t\\treturn this._colorLUT;\\n\\t}\\n\\tset colorLUT2(value) {\\n\\t\\tif (this._colorLUT2 !== value) {\\n\\t\\t\\tthis._colorLUT2 = value;\\n\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t\\tthis._validateColorLUT(value, \\\"colorLUT2\\\");\\n\\t\\t}\\n\\t}\\n\\tget colorLUT2() {\\n\\t\\treturn this._colorLUT2;\\n\\t}\\n\\t// Validate that a LUT texture is configured as a 256x16 sRGB strip with no mipmaps and\\n\\t// linear filtering. Stripped in release builds.\\n\\t_validateColorLUT(value, slotName) {\\n\\t}\\n\\tset bloomTexture(value) {\\n\\t\\tif (this._bloomTexture !== value) {\\n\\t\\t\\tthis._bloomTexture = value;\\n\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget bloomTexture() {\\n\\t\\treturn this._bloomTexture;\\n\\t}\\n\\tset cocTexture(value) {\\n\\t\\tif (this._cocTexture !== value) {\\n\\t\\t\\tthis._cocTexture = value;\\n\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget cocTexture() {\\n\\t\\treturn this._cocTexture;\\n\\t}\\n\\tset ssaoTexture(value) {\\n\\t\\tif (this._ssaoTexture !== value) {\\n\\t\\t\\tthis._ssaoTexture = value;\\n\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget ssaoTexture() {\\n\\t\\treturn this._ssaoTexture;\\n\\t}\\n\\tset taaEnabled(value) {\\n\\t\\tif (this._taaEnabled !== value) {\\n\\t\\t\\tthis._taaEnabled = value;\\n\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget taaEnabled() {\\n\\t\\treturn this._taaEnabled;\\n\\t}\\n\\tset gradingEnabled(value) {\\n\\t\\tif (this._gradingEnabled !== value) {\\n\\t\\t\\tthis._gradingEnabled = value;\\n\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget gradingEnabled() {\\n\\t\\treturn this._gradingEnabled;\\n\\t}\\n\\tset vignetteEnabled(value) {\\n\\t\\tif (this._vignetteEnabled !== value) {\\n\\t\\t\\tthis._vignetteEnabled = value;\\n\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget vignetteEnabled() {\\n\\t\\treturn this._vignetteEnabled;\\n\\t}\\n\\tset fringingEnabled(value) {\\n\\t\\tif (this._fringingEnabled !== value) {\\n\\t\\t\\tthis._fringingEnabled = value;\\n\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget fringingEnabled() {\\n\\t\\treturn this._fringingEnabled;\\n\\t}\\n\\tset colorEnhanceEnabled(value) {\\n\\t\\tif (this._colorEnhanceEnabled !== value) {\\n\\t\\t\\tthis._colorEnhanceEnabled = value;\\n\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget colorEnhanceEnabled() {\\n\\t\\treturn this._colorEnhanceEnabled;\\n\\t}\\n\\tset toneMapping(value) {\\n\\t\\tif (this._toneMapping !== value) {\\n\\t\\t\\tthis._toneMapping = value;\\n\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget toneMapping() {\\n\\t\\treturn this._toneMapping;\\n\\t}\\n\\tset sharpness(value) {\\n\\t\\tif (this._sharpness !== value) {\\n\\t\\t\\tthis._sharpness = value;\\n\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget sharpness() {\\n\\t\\treturn this._sharpness;\\n\\t}\\n\\tget isSharpnessEnabled() {\\n\\t\\treturn this._sharpness > 0;\\n\\t}\\n\\tset hdrScene(value) {\\n\\t\\tif (this._hdrScene !== value) {\\n\\t\\t\\tthis._hdrScene = value;\\n\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t}\\n\\t}\\n\\tget hdrScene() {\\n\\t\\treturn this._hdrScene;\\n\\t}\\n\\tpostInit() {\\n\\t\\tthis.setClearColor(Color.BLACK);\\n\\t\\tthis.setClearDepth(1);\\n\\t\\tthis.setClearStencil(0);\\n\\t}\\n\\tframeUpdate() {\\n\\t\\tconst rt = this.renderTarget ?? this.device.backBuffer;\\n\\t\\tconst srgb = rt.isColorBufferSrgb(0);\\n\\t\\tconst neededGammaCorrection = srgb ? GAMMA_NONE : GAMMA_SRGB;\\n\\t\\tif (this._gammaCorrection !== neededGammaCorrection) {\\n\\t\\t\\tthis._gammaCorrection = neededGammaCorrection;\\n\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t}\\n\\t\\tconst shaderChunks = ShaderChunks.get(this.device, this.device.isWebGPU ? SHADERLANGUAGE_WGSL : SHADERLANGUAGE_GLSL);\\n\\t\\tfor (const [name, prevValue] of this._customComposeChunks.entries()) {\\n\\t\\t\\tconst currentValue = shaderChunks.get(name);\\n\\t\\t\\tif (currentValue !== prevValue) {\\n\\t\\t\\t\\tthis._customComposeChunks.set(name, currentValue);\\n\\t\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this._shaderDirty) {\\n\\t\\t\\tthis._shaderDirty = false;\\n\\t\\t\\tconst gammaCorrectionName = gammaNames[this._gammaCorrection];\\n\\t\\t\\tconst customChunks = this._customComposeChunks;\\n\\t\\t\\tconst declHash = hashCode(customChunks.get(\\\"composeDeclarationsPS\\\") ?? \\\"\\\");\\n\\t\\t\\tconst startHash = hashCode(customChunks.get(\\\"composeMainStartPS\\\") ?? \\\"\\\");\\n\\t\\t\\tconst endHash = hashCode(customChunks.get(\\\"composeMainEndPS\\\") ?? \\\"\\\");\\n\\t\\t\\tconst key = `${this.toneMapping}-${gammaCorrectionName}-${this.bloomTexture ? \\\"bloom\\\" : \\\"nobloom\\\"}-${this.cocTexture ? \\\"dof\\\" : \\\"nodof\\\"}-${this.blurTextureUpscale ? \\\"dofupscale\\\" : \\\"\\\"}-${this.ssaoTexture ? \\\"ssao\\\" : \\\"nossao\\\"}-${this.gradingEnabled ? \\\"grading\\\" : \\\"nograding\\\"}-${this.colorEnhanceEnabled ? \\\"colorenhance\\\" : \\\"nocolorenhance\\\"}-${this.colorLUT ? \\\"colorlut\\\" : \\\"nocolorlut\\\"}-${this.colorLUT2 ? \\\"colorlut2\\\" : \\\"nocolorlut2\\\"}-${this.vignetteEnabled ? \\\"vignette\\\" : \\\"novignette\\\"}-${this.fringingEnabled ? \\\"fringing\\\" : \\\"nofringing\\\"}-${this.taaEnabled ? \\\"taa\\\" : \\\"notaa\\\"}-${this.isSharpnessEnabled ? this._hdrScene ? \\\"cashdr\\\" : \\\"cas\\\" : \\\"nocas\\\"}-${this._debug ?? \\\"\\\"}-decl${declHash}-start${startHash}-end${endHash}`;\\n\\t\\t\\tif (this._key !== key) {\\n\\t\\t\\t\\tthis._key = key;\\n\\t\\t\\t\\tconst defines = /* @__PURE__ */ new Map();\\n\\t\\t\\t\\tdefines.set(\\\"TONEMAP\\\", tonemapNames[this.toneMapping]);\\n\\t\\t\\t\\tdefines.set(\\\"GAMMA\\\", gammaCorrectionName);\\n\\t\\t\\t\\tif (this.bloomTexture) defines.set(\\\"BLOOM\\\", true);\\n\\t\\t\\t\\tif (this.cocTexture) defines.set(\\\"DOF\\\", true);\\n\\t\\t\\t\\tif (this.blurTextureUpscale) defines.set(\\\"DOF_UPSCALE\\\", true);\\n\\t\\t\\t\\tif (this.ssaoTexture) defines.set(\\\"SSAO\\\", true);\\n\\t\\t\\t\\tif (this.gradingEnabled) defines.set(\\\"GRADING\\\", true);\\n\\t\\t\\t\\tif (this.colorEnhanceEnabled) defines.set(\\\"COLOR_ENHANCE\\\", true);\\n\\t\\t\\t\\tif (this.colorLUT) defines.set(\\\"COLOR_LUT\\\", true);\\n\\t\\t\\t\\tif (this.colorLUT && this.colorLUT2) defines.set(\\\"COLOR_LUT2\\\", true);\\n\\t\\t\\t\\tif (this.vignetteEnabled) defines.set(\\\"VIGNETTE\\\", true);\\n\\t\\t\\t\\tif (this.fringingEnabled) defines.set(\\\"FRINGING\\\", true);\\n\\t\\t\\t\\tif (this.taaEnabled) defines.set(\\\"TAA\\\", true);\\n\\t\\t\\t\\tif (this.isSharpnessEnabled) {\\n\\t\\t\\t\\t\\tdefines.set(\\\"CAS\\\", true);\\n\\t\\t\\t\\t\\tif (this._hdrScene) defines.set(\\\"CAS_HDR\\\", true);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._debug) defines.set(\\\"DEBUG_COMPOSE\\\", this._debug);\\n\\t\\t\\t\\tthis.shader = ShaderUtils.createShader(this.device, {\\n\\t\\t\\t\\t\\tuniqueName: `ComposeShader-${key}`,\\n\\t\\t\\t\\t\\tattributes: { aPosition: SEMANTIC_POSITION },\\n\\t\\t\\t\\t\\tvertexChunk: \\\"quadVS\\\",\\n\\t\\t\\t\\t\\tfragmentChunk: \\\"composePS\\\",\\n\\t\\t\\t\\t\\tfragmentDefines: defines\\n\\t\\t\\t\\t});\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\texecute() {\\n\\t\\tconst sceneTex = this.sceneTexture;\\n\\t\\tthis.sceneTextureId.setValue(sceneTex);\\n\\t\\tthis.sceneTextureInvResValue[0] = 1 / sceneTex.width;\\n\\t\\tthis.sceneTextureInvResValue[1] = 1 / sceneTex.height;\\n\\t\\tthis.sceneTextureInvResId.setValue(this.sceneTextureInvResValue);\\n\\t\\tif (this._bloomTexture) {\\n\\t\\t\\tthis.bloomTextureId.setValue(this._bloomTexture);\\n\\t\\t\\tthis.bloomIntensityId.setValue(this.bloomIntensity);\\n\\t\\t}\\n\\t\\tif (this._cocTexture) {\\n\\t\\t\\tthis.cocTextureId.setValue(this._cocTexture);\\n\\t\\t\\tthis.blurTextureId.setValue(this.blurTexture);\\n\\t\\t}\\n\\t\\tif (this._ssaoTexture) {\\n\\t\\t\\tthis.ssaoTextureId.setValue(this._ssaoTexture);\\n\\t\\t}\\n\\t\\tif (this._gradingEnabled) {\\n\\t\\t\\tthis.bcsId.setValue([this.gradingBrightness, this.gradingContrast, this.gradingSaturation]);\\n\\t\\t\\tthis.tintId.setValue([this.gradingTint.r, this.gradingTint.g, this.gradingTint.b]);\\n\\t\\t}\\n\\t\\tif (this._colorEnhanceEnabled) {\\n\\t\\t\\tthis.colorEnhanceParamsId.setValue([this.colorEnhanceShadows, this.colorEnhanceHighlights, this.colorEnhanceVibrance, this.colorEnhanceDehaze]);\\n\\t\\t\\tthis.colorEnhanceMidtonesId.setValue(this.colorEnhanceMidtones);\\n\\t\\t}\\n\\t\\tconst lutTexture = this._colorLUT;\\n\\t\\tif (lutTexture) {\\n\\t\\t\\tthis.colorLUTParams[0] = this.colorLUTIntensity;\\n\\t\\t\\tthis.colorLUTParams[1] = this.colorLUT2Intensity;\\n\\t\\t\\tthis.colorLUTParams[2] = this.colorLUTBlend;\\n\\t\\t\\tthis.colorLUTParamsId.setValue(this.colorLUTParams);\\n\\t\\t\\tthis.colorLUTId.setValue(lutTexture);\\n\\t\\t\\tif (this._colorLUT2) {\\n\\t\\t\\t\\tthis.colorLUT2Id.setValue(this._colorLUT2);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (this._vignetteEnabled) {\\n\\t\\t\\tthis.vignetterParamsId.setValue([this.vignetteInner, this.vignetteOuter, this.vignetteCurvature, this.vignetteIntensity]);\\n\\t\\t\\tthis.vignetteColorId.setValue([this.vignetteColor.r, this.vignetteColor.g, this.vignetteColor.b]);\\n\\t\\t}\\n\\t\\tif (this._fringingEnabled) {\\n\\t\\t\\tthis.fringingIntensityId.setValue(this.fringingIntensity / 1024);\\n\\t\\t}\\n\\t\\tif (this.isSharpnessEnabled) {\\n\\t\\t\\tthis.sharpnessId.setValue(math.lerp(-0.125, -0.2, this.sharpness));\\n\\t\\t}\\n\\t\\tsuper.execute();\\n\\t}\\n}\\n\\nvar sampleCatmullRom_default$1 = `\\nvec4 SampleTextureCatmullRom(TEXTURE_ACCEPT(tex), vec2 uv, vec2 texSize) {\\n\\tvec2 samplePos = uv * texSize;\\n\\tvec2 texPos1 = floor(samplePos - 0.5) + 0.5;\\n\\tvec2 f = samplePos - texPos1;\\n\\tvec2 w0 = f * (-0.5 + f * (1.0 - 0.5 * f));\\n\\tvec2 w1 = 1.0 + f * f * (-2.5 + 1.5 * f);\\n\\tvec2 w2 = f * (0.5 + f * (2.0 - 1.5 * f));\\n\\tvec2 w3 = f * f * (-0.5 + 0.5 * f);\\n\\tvec2 w12 = w1 + w2;\\n\\tvec2 offset12 = w2 / (w1 + w2);\\n\\tvec2 texPos0 = (texPos1 - 1.0) / texSize;\\n\\tvec2 texPos3 = (texPos1 + 2.0) / texSize;\\n\\tvec2 texPos12 = (texPos1 + offset12) / texSize;\\n\\tvec4 result = vec4(0.0);\\n\\tresult += texture2DLod(tex, vec2(texPos0.x, texPos0.y), 0.0) * w0.x * w0.y;\\n\\tresult += texture2DLod(tex, vec2(texPos12.x, texPos0.y), 0.0) * w12.x * w0.y;\\n\\tresult += texture2DLod(tex, vec2(texPos3.x, texPos0.y), 0.0) * w3.x * w0.y;\\n\\tresult += texture2DLod(tex, vec2(texPos0.x, texPos12.y), 0.0) * w0.x * w12.y;\\n\\tresult += texture2DLod(tex, vec2(texPos12.x, texPos12.y), 0.0) * w12.x * w12.y;\\n\\tresult += texture2DLod(tex, vec2(texPos3.x, texPos12.y), 0.0) * w3.x * w12.y;\\n\\tresult += texture2DLod(tex, vec2(texPos0.x, texPos3.y), 0.0) * w0.x * w3.y;\\n\\tresult += texture2DLod(tex, vec2(texPos12.x, texPos3.y), 0.0) * w12.x * w3.y;\\n\\tresult += texture2DLod(tex, vec2(texPos3.x, texPos3.y), 0.0) * w3.x * w3.y;\\n\\treturn result;\\n}\\n`;\\n\\nvar sampleCatmullRom_default = `\\nfn SampleTextureCatmullRom(tex: texture_2d<f32>, texSampler: sampler, uv: vec2f, texSize: vec2f) -> vec4f {\\n\\tlet samplePos: vec2f = uv * texSize;\\n\\tlet texPos1: vec2f = floor(samplePos - 0.5) + 0.5;\\n\\tlet f: vec2f = samplePos - texPos1;\\n\\tlet w0: vec2f = f * (-0.5 + f * (1.0 - 0.5 * f));\\n\\tlet w1: vec2f = 1.0 + f * f * (-2.5 + 1.5 * f);\\n\\tlet w2: vec2f = f * (0.5 + f * (2.0 - 1.5 * f));\\n\\tlet w3: vec2f = f * f * (-0.5 + 0.5 * f);\\n\\tlet w12: vec2f = w1 + w2;\\n\\tlet offset12: vec2f = w2 / w12;\\n\\tlet texPos0: vec2f = (texPos1 - 1.0) / texSize;\\n\\tlet texPos3: vec2f = (texPos1 + 2.0) / texSize;\\n\\tlet texPos12: vec2f = (texPos1 + offset12) / texSize;\\n\\tvar result: vec4f = vec4f(0.0);\\n\\tresult = result + textureSampleLevel(tex, texSampler, vec2f(texPos0.x, texPos0.y), 0.0) * w0.x * w0.y;\\n\\tresult = result + textureSampleLevel(tex, texSampler, vec2f(texPos12.x, texPos0.y), 0.0) * w12.x * w0.y;\\n\\tresult = result + textureSampleLevel(tex, texSampler, vec2f(texPos3.x, texPos0.y), 0.0) * w3.x * w0.y;\\n\\tresult = result + textureSampleLevel(tex, texSampler, vec2f(texPos0.x, texPos12.y), 0.0) * w0.x * w12.y;\\n\\tresult = result + textureSampleLevel(tex, texSampler, vec2f(texPos12.x, texPos12.y), 0.0) * w12.x * w12.y;\\n\\tresult = result + textureSampleLevel(tex, texSampler, vec2f(texPos3.x, texPos12.y), 0.0) * w3.x * w12.y;\\n\\tresult = result + textureSampleLevel(tex, texSampler, vec2f(texPos0.x, texPos3.y), 0.0) * w0.x * w3.y;\\n\\tresult = result + textureSampleLevel(tex, texSampler, vec2f(texPos12.x, texPos3.y), 0.0) * w12.x * w3.y;\\n\\tresult = result + textureSampleLevel(tex, texSampler, vec2f(texPos3.x, texPos3.y), 0.0) * w3.x * w3.y;\\n\\treturn result;\\n}\\n`;\\n\\nvar taaResolve_default$1 = `\\n\\t#include  \\\"sampleCatmullRomPS\\\"\\n\\t#include  \\\"screenDepthPS\\\"\\n\\tuniform sampler2D sourceTexture;\\n\\tuniform sampler2D historyTexture;\\n\\tuniform mat4 matrix_viewProjectionPrevious;\\n\\tuniform mat4 matrix_viewProjectionInverse;\\n\\tuniform vec4 jitters;\\n\\tuniform vec2 textureSize;\\n\\tvarying vec2 uv0;\\n\\tvec2 reproject(vec2 uv, float depth) {\\n\\t\\tdepth = depth * 2.0 - 1.0;\\n\\t\\tvec4 ndc = vec4(uv * 2.0 - 1.0, depth, 1.0);\\n\\t\\tndc.xy -= jitters.xy;\\n\\t\\tvec4 worldPosition = matrix_viewProjectionInverse * ndc;\\n\\t\\tworldPosition /= worldPosition.w;\\n\\t\\tvec4 screenPrevious = matrix_viewProjectionPrevious * worldPosition;\\n\\t\\treturn (screenPrevious.xy / screenPrevious.w) * 0.5 + 0.5;\\n\\t}\\n\\tvec3 colorClampPremul(vec2 uv, vec3 historyPremul) {\\n\\t\\tvec3 minPremul = vec3(9999.0);\\n\\t\\tvec3 maxPremul = vec3(-9999.0);\\n\\t\\tfor(float x = -1.0; x <= 1.0; ++x) {\\n\\t\\t\\tfor(float y = -1.0; y <= 1.0; ++y) {\\n\\t\\t\\t\\tvec4 s = texture2D(sourceTexture, uv + vec2(x, y) / textureSize);\\n\\t\\t\\t\\tvec3 premul = s.rgb * s.a;\\n\\t\\t\\t\\tminPremul = min(minPremul, premul);\\n\\t\\t\\t\\tmaxPremul = max(maxPremul, premul);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn clamp(historyPremul, minPremul, maxPremul);\\n\\t}\\n\\tvoid main()\\n\\t{\\n\\t\\tvec4 srcColor = texture2D(sourceTexture, uv0);\\n\\t\\tfloat linearDepth = getLinearScreenDepth(uv0);\\n\\t\\tfloat depth = delinearizeDepth(linearDepth);\\n\\t\\tvec2 historyUv = reproject(uv0, depth);\\n\\t\\t#ifdef QUALITY_HIGH\\n\\t\\t\\tvec4 historySample = SampleTextureCatmullRom(TEXTURE_PASS(historyTexture), historyUv, textureSize);\\n\\t\\t#else\\n\\t\\t\\tvec4 historySample = texture2D(historyTexture, historyUv);\\n\\t\\t#endif\\n\\t\\tvec3 historyPremul = historySample.rgb * historySample.a;\\n\\t\\tvec3 srcPremul = srcColor.rgb * srcColor.a;\\n\\t\\tvec3 historyPremulClamped = colorClampPremul(uv0, historyPremul);\\n\\t\\tfloat mixFactor = (historyUv.x < 0.0 || historyUv.x > 1.0 || historyUv.y < 0.0 || historyUv.y > 1.0) ?\\n\\t\\t\\t1.0 : 0.05;\\n\\t\\tvec3 mixedPremul = mix(historyPremulClamped, srcPremul, mixFactor);\\n\\t\\tfloat a = srcColor.a;\\n\\t\\tconst float UNPREMUL_EPS = 1.0 / 255.0;\\n\\t\\tvec3 rgbStraight = (a > UNPREMUL_EPS) ? (mixedPremul / a) : srcColor.rgb;\\n\\t\\tgl_FragColor = vec4(rgbStraight, a);\\n\\t}\\n`;\\n\\nvar taaResolve_default = `\\n\\t#include \\\"sampleCatmullRomPS\\\"\\n\\t#include \\\"screenDepthPS\\\"\\n\\tvar sourceTexture: texture_2d<f32>;\\n\\tvar sourceTextureSampler: sampler;\\n\\tvar historyTexture: texture_2d<f32>;\\n\\tvar historyTextureSampler: sampler;\\n\\tuniform matrix_viewProjectionPrevious: mat4x4f;\\n\\tuniform matrix_viewProjectionInverse: mat4x4f;\\n\\tuniform jitters: vec4f;\\n\\tuniform textureSize: vec2f;\\n\\tvarying uv0: vec2f;\\n\\tfn reproject(uv_in: vec2f, depth: f32) -> vec2f {\\n\\t\\tvar uv = vec2f(uv_in.x, 1.0 - uv_in.y);\\n\\t\\tvar ndc = vec4f(uv * 2.0 - 1.0, depth, 1.0);\\n\\t\\tndc = vec4f(ndc.xy - uniform.jitters.xy, ndc.zw);\\n\\t\\tvar worldPosition = uniform.matrix_viewProjectionInverse * ndc;\\n\\t\\tworldPosition = worldPosition / worldPosition.w;\\n\\t\\tlet screenPrevious = uniform.matrix_viewProjectionPrevious * worldPosition;\\n\\t\\tvar result = (screenPrevious.xy / screenPrevious.w) * 0.5 + 0.5;\\n\\t\\tresult.y = 1.0 - result.y;\\n\\t\\treturn result;\\n\\t}\\n\\tfn colorClampPremul(uv: vec2f, historyPremul: vec3f) -> vec3f {\\n\\t\\tvar minPremul = vec3f(9999.0);\\n\\t\\tvar maxPremul = vec3f(-9999.0);\\n\\t\\tfor (var ix: i32 = -1; ix <= 1; ix = ix + 1) {\\n\\t\\t\\tfor (var iy: i32 = -1; iy <= 1; iy = iy + 1) {\\n\\t\\t\\t\\tlet s = textureSample(sourceTexture, sourceTextureSampler, uv + vec2f(f32(ix), f32(iy)) / uniform.textureSize);\\n\\t\\t\\t\\tlet premul = s.rgb * s.a;\\n\\t\\t\\t\\tminPremul = min(minPremul, premul);\\n\\t\\t\\t\\tmaxPremul = max(maxPremul, premul);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn clamp(historyPremul, minPremul, maxPremul);\\n\\t}\\n\\t@fragment\\n\\tfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\t\\tvar output: FragmentOutput;\\n\\t\\tlet srcColor = textureSample(sourceTexture, sourceTextureSampler, uv0);\\n\\t\\tlet linearDepth = getLinearScreenDepth(uv0);\\n\\t\\tlet depth = delinearizeDepth(linearDepth);\\n\\t\\tlet historyUv = reproject(uv0, depth);\\n\\t\\t#ifdef QUALITY_HIGH\\n\\t\\t\\tvar historySample: vec4f = SampleTextureCatmullRom(historyTexture, historyTextureSampler, historyUv, uniform.textureSize);\\n\\t\\t#else\\n\\t\\t\\tvar historySample: vec4f = textureSample(historyTexture, historyTextureSampler, historyUv);\\n\\t\\t#endif\\n\\t\\tlet historyPremul = historySample.rgb * historySample.a;\\n\\t\\tlet srcPremul = srcColor.rgb * srcColor.a;\\n\\t\\tlet historyPremulClamped = colorClampPremul(uv0, historyPremul);\\n\\t\\tlet mixFactor_condition = historyUv.x < 0.0 || historyUv.x > 1.0 || historyUv.y < 0.0 || historyUv.y > 1.0;\\n\\t\\tlet mixFactor = select(0.05, 1.0, mixFactor_condition);\\n\\t\\tlet mixedPremul = mix(historyPremulClamped, srcPremul, mixFactor);\\n\\t\\tlet a = srcColor.a;\\n\\t\\tlet UNPREMUL_EPS = 1.0 / 255.0;\\n\\t\\tlet rgbStraight = select(srcColor.rgb, mixedPremul / a, a > UNPREMUL_EPS);\\n\\t\\toutput.color = vec4f(rgbStraight, a);\\n\\t\\treturn output;\\n\\t}\\n`;\\n\\nclass RenderPassTAA extends RenderPassShaderQuad {\\n\\thistoryIndex = 0;\\n\\thistoryTexture = null;\\n\\thistoryTextures = [];\\n\\thistoryRenderTargets = [];\\n\\tconstructor(device, sourceTexture, cameraComponent) {\\n\\t\\tsuper(device);\\n\\t\\tthis.sourceTexture = sourceTexture;\\n\\t\\tthis.cameraComponent = cameraComponent;\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set(\\\"sampleCatmullRomPS\\\", sampleCatmullRom_default$1);\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set(\\\"sampleCatmullRomPS\\\", sampleCatmullRom_default);\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set(\\\"taaResolvePS\\\", taaResolve_default$1);\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set(\\\"taaResolvePS\\\", taaResolve_default);\\n\\t\\tconst defines = /* @__PURE__ */ new Map();\\n\\t\\tdefines.set(\\\"QUALITY_HIGH\\\", true);\\n\\t\\tShaderUtils.addScreenDepthChunkDefines(device, cameraComponent.shaderParams, defines);\\n\\t\\tthis.shader = ShaderUtils.createShader(device, {\\n\\t\\t\\tuniqueName: \\\"TaaResolveShader\\\",\\n\\t\\t\\tattributes: { aPosition: SEMANTIC_POSITION },\\n\\t\\t\\tvertexChunk: \\\"quadVS\\\",\\n\\t\\t\\tfragmentChunk: \\\"taaResolvePS\\\",\\n\\t\\t\\tfragmentDefines: defines\\n\\t\\t});\\n\\t\\tconst { scope } = device;\\n\\t\\tthis.sourceTextureId = scope.resolve(\\\"sourceTexture\\\");\\n\\t\\tthis.textureSizeId = scope.resolve(\\\"textureSize\\\");\\n\\t\\tthis.textureSize = new Float32Array(2);\\n\\t\\tthis.historyTextureId = scope.resolve(\\\"historyTexture\\\");\\n\\t\\tthis.viewProjPrevId = scope.resolve(\\\"matrix_viewProjectionPrevious\\\");\\n\\t\\tthis.viewProjInvId = scope.resolve(\\\"matrix_viewProjectionInverse\\\");\\n\\t\\tthis.jittersId = scope.resolve(\\\"jitters\\\");\\n\\t\\tthis.cameraParams = new Float32Array(4);\\n\\t\\tthis.cameraParamsId = scope.resolve(\\\"camera_params\\\");\\n\\t\\tthis.setup();\\n\\t}\\n\\tdestroy() {\\n\\t\\tif (this.renderTarget) {\\n\\t\\t\\tthis.renderTarget.destroyTextureBuffers();\\n\\t\\t\\tthis.renderTarget.destroy();\\n\\t\\t\\tthis.renderTarget = null;\\n\\t\\t}\\n\\t}\\n\\tsetup() {\\n\\t\\tfor (let i = 0; i < 2; ++i) {\\n\\t\\t\\tthis.historyTextures[i] = new Texture(this.device, {\\n\\t\\t\\t\\tname: `TAA-History-${i}`,\\n\\t\\t\\t\\twidth: 4,\\n\\t\\t\\t\\theight: 4,\\n\\t\\t\\t\\tformat: this.sourceTexture.format,\\n\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\tminFilter: FILTER_LINEAR,\\n\\t\\t\\t\\tmagFilter: FILTER_LINEAR,\\n\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t\\t});\\n\\t\\t\\tthis.historyRenderTargets[i] = new RenderTarget({\\n\\t\\t\\t\\tcolorBuffer: this.historyTextures[i],\\n\\t\\t\\t\\tdepth: false\\n\\t\\t\\t});\\n\\t\\t}\\n\\t\\tthis.historyTexture = this.historyTextures[0];\\n\\t\\tthis.init(this.historyRenderTargets[0], {\\n\\t\\t\\tresizeSource: this.sourceTexture\\n\\t\\t});\\n\\t}\\n\\tbefore() {\\n\\t\\tthis.sourceTextureId.setValue(this.sourceTexture);\\n\\t\\tthis.historyTextureId.setValue(this.historyTextures[1 - this.historyIndex]);\\n\\t\\tthis.textureSize[0] = this.sourceTexture.width;\\n\\t\\tthis.textureSize[1] = this.sourceTexture.height;\\n\\t\\tthis.textureSizeId.setValue(this.textureSize);\\n\\t\\tconst camera = this.cameraComponent.camera;\\n\\t\\tthis.viewProjPrevId.setValue(camera._viewProjPrevious.data);\\n\\t\\tthis.viewProjInvId.setValue(camera._viewProjInverse.data);\\n\\t\\tthis.jittersId.setValue(camera._jitters);\\n\\t\\tthis.cameraParamsId.setValue(camera.fillShaderParams(this.cameraParams));\\n\\t}\\n\\t// called when the parent render pass gets added to the frame graph\\n\\tupdate() {\\n\\t\\tthis.historyIndex = 1 - this.historyIndex;\\n\\t\\tthis.historyTexture = this.historyTextures[this.historyIndex];\\n\\t\\tthis.renderTarget = this.historyRenderTargets[this.historyIndex];\\n\\t\\treturn this.historyTexture;\\n\\t}\\n}\\n\\nvar coc_default$1 = `\\n\\t#include \\\"screenDepthPS\\\"\\n\\tvarying vec2 uv0;\\n\\tuniform vec3 params;\\n\\tvoid main()\\n\\t{\\n\\t\\tfloat depth = getLinearScreenDepth(uv0);\\n\\t\\tfloat focusDistance = params.x;\\n\\t\\tfloat focusRange = params.y;\\n\\t\\tfloat invRange = params.z;\\n\\t\\tfloat farRange = focusDistance + focusRange * 0.5;\\n\\t\\t\\n\\t\\tfloat cocFar = min((depth - farRange) * invRange, 1.0);\\n\\t\\t#ifdef NEAR_BLUR\\n\\t\\t\\tfloat nearRange = focusDistance - focusRange * 0.5;\\n\\t\\t\\tfloat cocNear = min((nearRange - depth) * invRange, 1.0);\\n\\t\\t#else\\n\\t\\t\\tfloat cocNear = 0.0;\\n\\t\\t#endif\\n\\t\\tgl_FragColor = vec4(cocFar, cocNear, 0.0, 0.0);\\n\\t}\\n`;\\n\\nvar coc_default = `\\n#include \\\"screenDepthPS\\\"\\nvarying uv0: vec2f;\\nuniform params: vec3f;\\n@fragment\\nfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\tvar output: FragmentOutput;\\n\\tlet depth: f32 = getLinearScreenDepth(uv0);\\n\\tlet focusDistance: f32 = uniform.params.x;\\n\\tlet focusRange: f32 = uniform.params.y;\\n\\tlet invRange: f32 = uniform.params.z;\\n\\tlet farRange: f32 = focusDistance + focusRange * 0.5;\\n\\tlet cocFar: f32 = min((depth - farRange) * invRange, 1.0);\\n\\t#ifdef NEAR_BLUR\\n\\t\\tlet nearRange: f32 = focusDistance - focusRange * 0.5;\\n\\t\\tvar cocNear: f32 = min((nearRange - depth) * invRange, 1.0);\\n\\t#else\\n\\t\\tvar cocNear: f32 = 0.0;\\n\\t#endif\\n\\toutput.color = vec4f(cocFar, cocNear, 0.0, 0.0);\\n\\treturn output;\\n}\\n`;\\n\\nclass RenderPassCoC extends RenderPassShaderQuad {\\n\\tfocusDistance;\\n\\tfocusRange;\\n\\tconstructor(device, cameraComponent, nearBlur) {\\n\\t\\tsuper(device);\\n\\t\\tthis.cameraComponent = cameraComponent;\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set(\\\"cocPS\\\", coc_default$1);\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set(\\\"cocPS\\\", coc_default);\\n\\t\\tconst defines = /* @__PURE__ */ new Map();\\n\\t\\tif (nearBlur) defines.set(\\\"NEAR_BLUR\\\", \\\"\\\");\\n\\t\\tShaderUtils.addScreenDepthChunkDefines(device, cameraComponent.shaderParams, defines);\\n\\t\\tthis.shader = ShaderUtils.createShader(device, {\\n\\t\\t\\tuniqueName: `CocShader-${nearBlur}`,\\n\\t\\t\\tattributes: { aPosition: SEMANTIC_POSITION },\\n\\t\\t\\tvertexChunk: \\\"quadVS\\\",\\n\\t\\t\\tfragmentChunk: \\\"cocPS\\\",\\n\\t\\t\\tfragmentDefines: defines\\n\\t\\t});\\n\\t\\tthis.paramsId = device.scope.resolve(\\\"params\\\");\\n\\t\\tthis.paramsValue = new Float32Array(3);\\n\\t\\tthis.cameraParams = new Float32Array(4);\\n\\t\\tthis.cameraParamsId = device.scope.resolve(\\\"camera_params\\\");\\n\\t}\\n\\texecute() {\\n\\t\\tconst { paramsValue, focusRange } = this;\\n\\t\\tparamsValue[0] = this.focusDistance + 1e-3;\\n\\t\\tparamsValue[1] = focusRange;\\n\\t\\tparamsValue[2] = 1 / focusRange;\\n\\t\\tthis.paramsId.setValue(paramsValue);\\n\\t\\tconst camera = this.cameraComponent.camera;\\n\\t\\tthis.cameraParamsId.setValue(camera.fillShaderParams(this.cameraParams));\\n\\t\\tsuper.execute();\\n\\t}\\n}\\n\\nvar dofBlur_default$1 = `\\n\\t#if defined(NEAR_BLUR)\\n\\t\\tuniform sampler2D nearTexture;\\n\\t#endif\\n\\tuniform sampler2D farTexture;\\n\\tuniform sampler2D cocTexture;\\n\\tuniform vec2 kernel[{KERNEL_COUNT}];\\n\\tuniform float blurRadiusNear;\\n\\tuniform float blurRadiusFar;\\n\\tvarying vec2 uv0;\\n\\tvoid main()\\n\\t{\\n\\t\\tvec2 coc = texture2D(cocTexture, uv0).rg;\\n\\t\\tfloat cocFar = coc.r;\\n\\t\\tvec3 sum = vec3(0.0, 0.0, 0.0);\\n\\t\\t#if defined(NEAR_BLUR)\\n\\t\\t\\tfloat cocNear = coc.g;\\n\\t\\t\\tif (cocNear > 0.0001) {\\n\\t\\t\\t\\tivec2 nearTextureSize = textureSize(nearTexture, 0);\\n\\t\\t\\t\\tvec2 step = cocNear * blurRadiusNear / vec2(nearTextureSize);\\n\\t\\t\\t\\tfor (int i = 0; i < {KERNEL_COUNT}; i++) {\\n\\t\\t\\t\\t\\tvec2 uv = uv0 + step * kernel[i];\\n\\t\\t\\t\\t\\tvec3 tap = texture2DLod(nearTexture, uv, 0.0).rgb;\\n\\t\\t\\t\\t\\tsum += tap.rgb;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tsum *= float({INV_KERNEL_COUNT});\\n\\t\\t\\t} else\\n\\t\\t#endif\\n\\t\\t\\t\\n\\t\\t\\tif (cocFar > 0.0001) {\\n\\t\\t\\tivec2 farTextureSize = textureSize(farTexture, 0);\\n\\t\\t\\tvec2 step = cocFar * blurRadiusFar / vec2(farTextureSize);\\n\\t\\t\\tfloat sumCoC = 0.0; \\n\\t\\t\\tfor (int i = 0; i < {KERNEL_COUNT}; i++) {\\n\\t\\t\\t\\tvec2 uv = uv0 + step * kernel[i];\\n\\t\\t\\t\\tvec3 tap = texture2DLod(farTexture, uv, 0.0).rgb;\\n\\t\\t\\t\\tfloat cocThis = texture2DLod(cocTexture, uv, 0.0).r;\\n\\t\\t\\t\\ttap *= cocThis;\\n\\t\\t\\t\\tsumCoC += cocThis;\\n\\t\\t\\t\\tsum += tap;\\n\\t\\t\\t}\\n\\t\\t\\tif (sumCoC > 0.0)\\n\\t\\t\\t\\tsum /= sumCoC;\\n\\t\\t\\tsum /= cocFar;\\n\\t\\t}\\n\\t\\tpcFragColor0 = vec4(sum, 1.0);\\n\\t}\\n`;\\n\\nvar dofBlur_default = `\\n#if defined(NEAR_BLUR)\\n\\tvar nearTexture: texture_2d<f32>;\\n\\tvar nearTextureSampler: sampler;\\n#endif\\nvar farTexture: texture_2d<f32>;\\nvar farTextureSampler: sampler;\\nvar cocTexture: texture_2d<f32>;\\nvar cocTextureSampler: sampler;\\nuniform kernel: array<vec2f, {KERNEL_COUNT}>;\\nuniform blurRadiusNear: f32;\\nuniform blurRadiusFar: f32;\\nvarying uv0: vec2f;\\n@fragment\\nfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\tvar output: FragmentOutput;\\n\\tlet coc: vec2f = textureSample(cocTexture, cocTextureSampler, input.uv0).rg;\\n\\tlet cocFar: f32 = coc.r;\\n\\tvar sum: vec3f = vec3f(0.0, 0.0, 0.0);\\n\\t#if defined(NEAR_BLUR)\\n\\t\\tlet cocNear: f32 = coc.g;\\n\\t\\tif (cocNear > 0.0001) {\\n\\t\\t\\tlet nearTextureSize: vec2f = vec2f(textureDimensions(nearTexture, 0));\\n\\t\\t\\tlet step: vec2f = cocNear * uniform.blurRadiusNear / nearTextureSize;\\n\\t\\t\\tfor (var i: i32 = 0; i < {KERNEL_COUNT}; i = i + 1) {\\n\\t\\t\\t\\tlet uv: vec2f = uv0 + step * uniform.kernel[i].element;\\n\\t\\t\\t\\tlet tap: vec3f = textureSampleLevel(nearTexture, nearTextureSampler, uv, 0.0).rgb;\\n\\t\\t\\t\\tsum = sum + tap;\\n\\t\\t\\t}\\n\\t\\t\\tsum = sum * f32({INV_KERNEL_COUNT});\\n\\t\\t} else\\n\\t#endif\\n\\t\\tif (cocFar > 0.0001) {\\n\\t\\t\\tlet farTextureSize: vec2f = vec2f(textureDimensions(farTexture, 0));\\n\\t\\t\\tlet step: vec2f = cocFar * uniform.blurRadiusFar / farTextureSize;\\n\\t\\t\\tvar sumCoC: f32 = 0.0;\\n\\t\\t\\tfor (var i: i32 = 0; i < {KERNEL_COUNT}; i = i + 1) {\\n\\t\\t\\t\\tlet uv: vec2f = uv0 + step * uniform.kernel[i].element;\\n\\t\\t\\t\\tvar tap: vec3f = textureSampleLevel(farTexture, farTextureSampler, uv, 0.0).rgb;\\n\\t\\t\\t\\tlet cocThis: f32 = textureSampleLevel(cocTexture, cocTextureSampler, uv, 0.0).r;\\n\\t\\t\\t\\ttap = tap * cocThis;\\n\\t\\t\\t\\tsumCoC = sumCoC + cocThis;\\n\\t\\t\\t\\tsum = sum + tap;\\n\\t\\t\\t}\\n\\t\\t\\tif (sumCoC > 0.0) {\\n\\t\\t\\t\\tsum = sum / sumCoC;\\n\\t\\t\\t}\\n\\t\\t\\tsum = sum / cocFar;\\n\\t\\t}\\n\\toutput.color = vec4f(sum, 1.0);\\n\\treturn output;\\n}\\n`;\\n\\nclass RenderPassDofBlur extends RenderPassShaderQuad {\\n\\tblurRadiusNear = 1;\\n\\tblurRadiusFar = 1;\\n\\t_blurRings = 3;\\n\\t_blurRingPoints = 3;\\n\\tconstructor(device, nearTexture, farTexture, cocTexture) {\\n\\t\\tsuper(device);\\n\\t\\tthis.nearTexture = nearTexture;\\n\\t\\tthis.farTexture = farTexture;\\n\\t\\tthis.cocTexture = cocTexture;\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set(\\\"dofBlurPS\\\", dofBlur_default$1);\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set(\\\"dofBlurPS\\\", dofBlur_default);\\n\\t\\tconst { scope } = device;\\n\\t\\tthis.kernelId = scope.resolve(\\\"kernel[0]\\\");\\n\\t\\tthis.kernelCountId = scope.resolve(\\\"kernelCount\\\");\\n\\t\\tthis.blurRadiusNearId = scope.resolve(\\\"blurRadiusNear\\\");\\n\\t\\tthis.blurRadiusFarId = scope.resolve(\\\"blurRadiusFar\\\");\\n\\t\\tthis.nearTextureId = scope.resolve(\\\"nearTexture\\\");\\n\\t\\tthis.farTextureId = scope.resolve(\\\"farTexture\\\");\\n\\t\\tthis.cocTextureId = scope.resolve(\\\"cocTexture\\\");\\n\\t}\\n\\tset blurRings(value) {\\n\\t\\tif (this._blurRings !== value) {\\n\\t\\t\\tthis._blurRings = value;\\n\\t\\t\\tthis.shader = null;\\n\\t\\t}\\n\\t}\\n\\tget blurRings() {\\n\\t\\treturn this._blurRings;\\n\\t}\\n\\tset blurRingPoints(value) {\\n\\t\\tif (this._blurRingPoints !== value) {\\n\\t\\t\\tthis._blurRingPoints = value;\\n\\t\\t\\tthis.shader = null;\\n\\t\\t}\\n\\t}\\n\\tget blurRingPoints() {\\n\\t\\treturn this._blurRingPoints;\\n\\t}\\n\\tcreateShader() {\\n\\t\\tthis.kernel = new Float32Array(Kernel.concentric(this.blurRings, this.blurRingPoints));\\n\\t\\tconst kernelCount = this.kernel.length >> 1;\\n\\t\\tconst nearBlur = this.nearTexture !== null;\\n\\t\\tconst defines = /* @__PURE__ */ new Map();\\n\\t\\tdefines.set(\\\"{KERNEL_COUNT}\\\", kernelCount);\\n\\t\\tdefines.set(\\\"{INV_KERNEL_COUNT}\\\", 1 / kernelCount);\\n\\t\\tif (nearBlur) defines.set(\\\"NEAR_BLUR\\\", \\\"\\\");\\n\\t\\tthis.shader = ShaderUtils.createShader(this.device, {\\n\\t\\t\\tuniqueName: `DofBlurShader-${kernelCount}-${nearBlur ? \\\"nearBlur\\\" : \\\"noNearBlur\\\"}`,\\n\\t\\t\\tattributes: { aPosition: SEMANTIC_POSITION },\\n\\t\\t\\tvertexChunk: \\\"quadVS\\\",\\n\\t\\t\\tfragmentChunk: \\\"dofBlurPS\\\",\\n\\t\\t\\tfragmentDefines: defines\\n\\t\\t});\\n\\t}\\n\\texecute() {\\n\\t\\tif (!this.shader) {\\n\\t\\t\\tthis.createShader();\\n\\t\\t}\\n\\t\\tthis.nearTextureId.setValue(this.nearTexture);\\n\\t\\tthis.farTextureId.setValue(this.farTexture);\\n\\t\\tthis.cocTextureId.setValue(this.cocTexture);\\n\\t\\tthis.kernelId.setValue(this.kernel);\\n\\t\\tthis.kernelCountId.setValue(this.kernel.length >> 1);\\n\\t\\tthis.blurRadiusNearId.setValue(this.blurRadiusNear);\\n\\t\\tthis.blurRadiusFarId.setValue(this.blurRadiusFar);\\n\\t\\tsuper.execute();\\n\\t}\\n}\\n\\nclass FramePassDof extends FramePass {\\n\\tfocusDistance = 100;\\n\\tfocusRange = 50;\\n\\tblurRadius = 1;\\n\\tblurRings = 3;\\n\\tblurRingPoints = 3;\\n\\thighQuality = true;\\n\\tcocTexture = null;\\n\\tblurTexture = null;\\n\\tcocPass = null;\\n\\tfarPass = null;\\n\\tblurPass = null;\\n\\tconstructor(device, cameraComponent, sceneTexture, sceneTextureHalf, highQuality, nearBlur) {\\n\\t\\tsuper(device);\\n\\t\\tthis.highQuality = highQuality;\\n\\t\\tthis.cocPass = this.setupCocPass(device, cameraComponent, sceneTexture, nearBlur);\\n\\t\\tthis.beforePasses.push(this.cocPass);\\n\\t\\tconst sourceTexture = highQuality ? sceneTexture : sceneTextureHalf;\\n\\t\\tthis.farPass = this.setupFarPass(device, sourceTexture, 0.5);\\n\\t\\tthis.beforePasses.push(this.farPass);\\n\\t\\tthis.blurPass = this.setupBlurPass(device, sceneTextureHalf, nearBlur, highQuality ? 2 : 0.5);\\n\\t\\tthis.beforePasses.push(this.blurPass);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.destroyRenderPasses();\\n\\t\\tthis.cocPass = null;\\n\\t\\tthis.farPass = null;\\n\\t\\tthis.blurPass = null;\\n\\t\\tthis.destroyRT(this.cocRT);\\n\\t\\tthis.destroyRT(this.farRt);\\n\\t\\tthis.destroyRT(this.blurRt);\\n\\t\\tthis.cocRT = null;\\n\\t\\tthis.farRt = null;\\n\\t\\tthis.blurRt = null;\\n\\t}\\n\\tdestroyRenderPasses() {\\n\\t\\tfor (let i = 0; i < this.beforePasses.length; i++) {\\n\\t\\t\\tthis.beforePasses[i].destroy();\\n\\t\\t}\\n\\t\\tthis.beforePasses.length = 0;\\n\\t}\\n\\tdestroyRT(rt) {\\n\\t\\tif (rt) {\\n\\t\\t\\trt.destroyTextureBuffers();\\n\\t\\t\\trt.destroy();\\n\\t\\t}\\n\\t}\\n\\tsetupCocPass(device, cameraComponent, sourceTexture, nearBlur) {\\n\\t\\tconst format = nearBlur ? PIXELFORMAT_RG8 : PIXELFORMAT_R8;\\n\\t\\tthis.cocRT = this.createRenderTarget(\\\"CoCTexture\\\", format);\\n\\t\\tthis.cocTexture = this.cocRT.colorBuffer;\\n\\t\\tconst cocPass = new RenderPassCoC(device, cameraComponent, nearBlur);\\n\\t\\tcocPass.init(this.cocRT, {\\n\\t\\t\\tresizeSource: sourceTexture\\n\\t\\t});\\n\\t\\tcocPass.setClearColor(Color.BLACK);\\n\\t\\treturn cocPass;\\n\\t}\\n\\tsetupFarPass(device, sourceTexture, scale) {\\n\\t\\tthis.farRt = this.createRenderTarget(\\\"FarDofTexture\\\", sourceTexture.format);\\n\\t\\tconst farPass = new RenderPassDownsample(device, sourceTexture, {\\n\\t\\t\\tboxFilter: true,\\n\\t\\t\\tpremultiplyTexture: this.cocTexture,\\n\\t\\t\\tpremultiplySrcChannel: \\\"r\\\"\\n\\t\\t\\t// far CoC\\n\\t\\t});\\n\\t\\tfarPass.init(this.farRt, {\\n\\t\\t\\tresizeSource: sourceTexture,\\n\\t\\t\\tscaleX: scale,\\n\\t\\t\\tscaleY: scale\\n\\t\\t});\\n\\t\\tfarPass.setClearColor(Color.BLACK);\\n\\t\\treturn farPass;\\n\\t}\\n\\tsetupBlurPass(device, nearTexture, nearBlur, scale) {\\n\\t\\tconst farTexture = this.farRt?.colorBuffer;\\n\\t\\tthis.blurRt = this.createRenderTarget(\\\"DofBlurTexture\\\", nearTexture.format);\\n\\t\\tthis.blurTexture = this.blurRt.colorBuffer;\\n\\t\\tconst blurPass = new RenderPassDofBlur(device, nearBlur ? nearTexture : null, farTexture, this.cocTexture);\\n\\t\\tblurPass.init(this.blurRt, {\\n\\t\\t\\tresizeSource: nearTexture,\\n\\t\\t\\tscaleX: scale,\\n\\t\\t\\tscaleY: scale\\n\\t\\t});\\n\\t\\tblurPass.setClearColor(Color.BLACK);\\n\\t\\treturn blurPass;\\n\\t}\\n\\tcreateTexture(name, format) {\\n\\t\\treturn new Texture(this.device, {\\n\\t\\t\\tname,\\n\\t\\t\\twidth: 1,\\n\\t\\t\\theight: 1,\\n\\t\\t\\tformat,\\n\\t\\t\\tmipmaps: false,\\n\\t\\t\\tminFilter: FILTER_LINEAR,\\n\\t\\t\\tmagFilter: FILTER_LINEAR,\\n\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t});\\n\\t}\\n\\tcreateRenderTarget(name, format) {\\n\\t\\treturn new RenderTarget({\\n\\t\\t\\tcolorBuffer: this.createTexture(name, format),\\n\\t\\t\\tdepth: false,\\n\\t\\t\\tstencil: false\\n\\t\\t});\\n\\t}\\n\\tframeUpdate() {\\n\\t\\tsuper.frameUpdate();\\n\\t\\tthis.cocPass.focusDistance = this.focusDistance;\\n\\t\\tthis.cocPass.focusRange = this.focusRange;\\n\\t\\tthis.blurPass.blurRadiusNear = this.blurRadius;\\n\\t\\tthis.blurPass.blurRadiusFar = this.blurRadius * (this.highQuality ? 1 : 0.5);\\n\\t\\tthis.blurPass.blurRings = this.blurRings;\\n\\t\\tthis.blurPass.blurRingPoints = this.blurRingPoints;\\n\\t}\\n}\\n\\nconst tempMeshInstances = [];\\nconst DEPTH_UNIFORM_NAME = \\\"uSceneDepthMap\\\";\\nclass RenderPassPrepass extends RenderPass {\\n\\tviewBindGroups = [];\\n\\tlinearDepthTexture;\\n\\tlinearDepthClearValue = new Color(0, 0, 0, 0);\\n\\tconstructor(device, scene, renderer, camera, options) {\\n\\t\\tsuper(device);\\n\\t\\tthis.scene = scene;\\n\\t\\tthis.renderer = renderer;\\n\\t\\tthis.camera = camera;\\n\\t\\tthis.setupRenderTarget(options);\\n\\t}\\n\\tdestroy() {\\n\\t\\tsuper.destroy();\\n\\t\\tthis.camera.shaderParams.sceneDepthMapLinear = false;\\n\\t\\tthis.renderTarget?.destroy();\\n\\t\\tthis.renderTarget = null;\\n\\t\\tthis.linearDepthTexture?.destroy();\\n\\t\\tthis.linearDepthTexture = null;\\n\\t\\tthis.viewBindGroups.forEach((bg) => {\\n\\t\\t\\tbg.defaultUniformBuffer.destroy();\\n\\t\\t\\tbg.destroy();\\n\\t\\t});\\n\\t\\tthis.viewBindGroups.length = 0;\\n\\t}\\n\\tsetupRenderTarget(options) {\\n\\t\\tconst { device } = this;\\n\\t\\tthis.linearDepthFormat = device.textureFloatRenderable ? PIXELFORMAT_R32F : PIXELFORMAT_RGBA8;\\n\\t\\tthis.linearDepthTexture = Texture.createDataTexture2D(device, \\\"SceneLinearDepthTexture\\\", 1, 1, this.linearDepthFormat);\\n\\t\\tconst renderTarget = new RenderTarget({\\n\\t\\t\\tname: \\\"PrepassRT\\\",\\n\\t\\t\\tcolorBuffer: this.linearDepthTexture,\\n\\t\\t\\t// use depth buffer, but this can be discarded after the prepass as the depth is stored in the linearDepthTexture\\n\\t\\t\\tdepth: true,\\n\\t\\t\\t// always single sampled\\n\\t\\t\\tsamples: 1\\n\\t\\t});\\n\\t\\tthis.camera.shaderParams.sceneDepthMapLinear = true;\\n\\t\\tthis.init(renderTarget, options);\\n\\t}\\n\\tafter() {\\n\\t\\tthis.device.scope.resolve(DEPTH_UNIFORM_NAME).setValue(this.linearDepthTexture);\\n\\t}\\n\\texecute() {\\n\\t\\tconst { renderer, scene, renderTarget } = this;\\n\\t\\tconst camera = this.camera.camera;\\n\\t\\tconst layers = scene.layers.layerList;\\n\\t\\tconst subLayerEnabled = scene.layers.subLayerEnabled;\\n\\t\\tconst isTransparent = scene.layers.subLayerList;\\n\\t\\tfor (let i = 0; i < layers.length; i++) {\\n\\t\\t\\tconst layer = layers[i];\\n\\t\\t\\tif (layer.id === LAYERID_DEPTH) {\\n\\t\\t\\t\\tbreak;\\n\\t\\t\\t}\\n\\t\\t\\tif (layer.enabled && subLayerEnabled[i]) {\\n\\t\\t\\t\\tif (layer.camerasSet.has(camera)) {\\n\\t\\t\\t\\t\\tconst culledInstances = layer.getCulledInstances(camera);\\n\\t\\t\\t\\t\\tconst meshInstances = isTransparent[i] ? culledInstances.transparent : culledInstances.opaque;\\n\\t\\t\\t\\t\\tfor (let j = 0; j < meshInstances.length; j++) {\\n\\t\\t\\t\\t\\t\\tconst meshInstance = meshInstances[j];\\n\\t\\t\\t\\t\\t\\tif (meshInstance.material?.depthWrite) {\\n\\t\\t\\t\\t\\t\\t\\ttempMeshInstances.push(meshInstance);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\trenderer.renderForwardLayer(camera, renderTarget, null, void 0, SHADER_PREPASS, this.viewBindGroups, {\\n\\t\\t\\t\\t\\t\\tmeshInstances: tempMeshInstances\\n\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\ttempMeshInstances.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\tframeUpdate() {\\n\\t\\tsuper.frameUpdate();\\n\\t\\tconst { camera } = this;\\n\\t\\tthis.setClearDepth(camera.clearDepthBuffer ? 1 : void 0);\\n\\t\\tlet clearValue;\\n\\t\\tif (camera.clearDepthBuffer) {\\n\\t\\t\\tconst farClip = camera.farClip - Number.MIN_VALUE;\\n\\t\\t\\tclearValue = this.linearDepthClearValue;\\n\\t\\t\\tif (this.linearDepthFormat === PIXELFORMAT_R32F) {\\n\\t\\t\\t\\tclearValue.r = farClip;\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tFloatPacking.float2RGBA8(farClip, clearValue);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.setClearColor(clearValue);\\n\\t}\\n}\\n\\nvar depthAwareBlur_default$1 = `\\n\\t#include \\\"screenDepthPS\\\"\\n\\tvarying vec2 uv0;\\n\\tuniform sampler2D sourceTexture;\\n\\tuniform vec2 sourceInvResolution;\\n\\tuniform int filterSize;\\n\\tfloat random(const highp vec2 w) {\\n\\t\\tconst vec3 m = vec3(0.06711056, 0.00583715, 52.9829189);\\n\\t\\treturn fract(m.z * fract(dot(w, m.xy)));\\n\\t}\\n\\tmediump float bilateralWeight(in mediump float depth, in mediump float sampleDepth) {\\n\\t\\tmediump float diff = (sampleDepth - depth);\\n\\t\\treturn max(0.0, 1.0 - diff * diff);\\n\\t}\\n\\tvoid tap(inout float sum, inout float totalWeight, float weight, float depth, vec2 position) {\\n\\t\\tmediump float color = texture2D(sourceTexture, position).r;\\n\\t\\tmediump float textureDepth = -getLinearScreenDepth(position);\\n\\t\\n\\t\\tmediump float bilateral = bilateralWeight(depth, textureDepth);\\n\\t\\tbilateral *= weight;\\n\\t\\tsum += color * bilateral;\\n\\t\\ttotalWeight += bilateral;\\n\\t}\\n\\tvoid main() {\\n\\t\\tmediump float depth = -getLinearScreenDepth(uv0);\\n\\t\\tmediump float totalWeight = 1.0;\\n\\t\\tmediump float color = texture2D(sourceTexture, uv0 ).r;\\n\\t\\tmediump float sum = color * totalWeight;\\n\\t\\tfor (mediump int i = -filterSize; i <= filterSize; i++) {\\n\\t\\t\\tmediump float weight = 1.0;\\n\\t\\t\\t#ifdef HORIZONTAL\\n\\t\\t\\t\\tvec2 offset = vec2(i, 0) * sourceInvResolution;\\n\\t\\t\\t#else\\n\\t\\t\\t\\tvec2 offset = vec2(0, i) * sourceInvResolution;\\n\\t\\t\\t#endif\\n\\t\\t\\ttap(sum, totalWeight, weight, depth, uv0 + offset);\\n\\t\\t}\\n\\t\\tmediump float ao = sum / totalWeight;\\n\\t\\tgl_FragColor.r = ao;\\n\\t}\\n`;\\n\\nvar depthAwareBlur_default = `\\n#include \\\"screenDepthPS\\\"\\nvarying uv0: vec2f;\\nvar sourceTexture: texture_2d<f32>;\\nvar sourceTextureSampler: sampler;\\nuniform sourceInvResolution: vec2f;\\nuniform filterSize: i32;\\nfn random(w: vec2f) -> f32 {\\n\\tconst m: vec3f = vec3f(0.06711056, 0.00583715, 52.9829189);\\n\\treturn fract(m.z * fract(dot(w, m.xy)));\\n}\\nfn bilateralWeight(depth: f32, sampleDepth: f32) -> f32 {\\n\\tlet diff: f32 = (sampleDepth - depth);\\n\\treturn max(0.0, 1.0 - diff * diff);\\n}\\nfn tap(sum_ptr: ptr<function, f32>, totalWeight_ptr: ptr<function, f32>, weight: f32, depth: f32, position: vec2f) {\\n\\tlet color: f32 = textureSample(sourceTexture, sourceTextureSampler, position).r;\\n\\tlet textureDepth: f32 = -getLinearScreenDepth(position);\\n\\tlet bilateral: f32 = bilateralWeight(depth, textureDepth) * weight;\\n\\t*sum_ptr = *sum_ptr + color * bilateral;\\n\\t*totalWeight_ptr = *totalWeight_ptr + bilateral;\\n}\\n@fragment\\nfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\tvar output: FragmentOutput;\\n\\tlet depth: f32 = -getLinearScreenDepth(input.uv0);\\n\\tvar totalWeight: f32 = 1.0;\\n\\tlet color: f32 = textureSample(sourceTexture, sourceTextureSampler, input.uv0 ).r;\\n\\tvar sum: f32 = color * totalWeight;\\n\\tfor (var i: i32 = -uniform.filterSize; i <= uniform.filterSize; i = i + 1) {\\n\\t\\tlet weight: f32 = 1.0;\\n\\t\\t#ifdef HORIZONTAL\\n\\t\\t\\tvar offset: vec2f = vec2f(f32(i), 0.0) * uniform.sourceInvResolution;\\n\\t\\t#else\\n\\t\\t\\tvar offset: vec2f = vec2f(0.0, f32(i)) * uniform.sourceInvResolution;\\n\\t\\t#endif\\n\\t\\ttap(&sum, &totalWeight, weight, depth, input.uv0 + offset);\\n\\t}\\n\\tlet ao: f32 = sum / totalWeight;\\n\\toutput.color = vec4f(ao, ao, ao, 1.0);\\n\\treturn output;\\n}\\n`;\\n\\nclass RenderPassDepthAwareBlur extends RenderPassShaderQuad {\\n\\tconstructor(device, sourceTexture, cameraComponent, horizontal) {\\n\\t\\tsuper(device);\\n\\t\\tthis.sourceTexture = sourceTexture;\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set(\\\"depthAwareBlurPS\\\", depthAwareBlur_default$1);\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set(\\\"depthAwareBlurPS\\\", depthAwareBlur_default);\\n\\t\\tconst defines = /* @__PURE__ */ new Map();\\n\\t\\tif (horizontal) defines.set(\\\"HORIZONTAL\\\", \\\"\\\");\\n\\t\\tShaderUtils.addScreenDepthChunkDefines(device, cameraComponent.shaderParams, defines);\\n\\t\\tthis.shader = ShaderUtils.createShader(device, {\\n\\t\\t\\tuniqueName: `DepthAware${horizontal ? \\\"Horizontal\\\" : \\\"Vertical\\\"}BlurShader`,\\n\\t\\t\\tattributes: { aPosition: SEMANTIC_POSITION },\\n\\t\\t\\tvertexChunk: \\\"quadVS\\\",\\n\\t\\t\\tfragmentChunk: \\\"depthAwareBlurPS\\\",\\n\\t\\t\\tfragmentDefines: defines\\n\\t\\t});\\n\\t\\tconst scope = this.device.scope;\\n\\t\\tthis.sourceTextureId = scope.resolve(\\\"sourceTexture\\\");\\n\\t\\tthis.sourceInvResolutionId = scope.resolve(\\\"sourceInvResolution\\\");\\n\\t\\tthis.sourceInvResolutionValue = new Float32Array(2);\\n\\t\\tthis.filterSizeId = scope.resolve(\\\"filterSize\\\");\\n\\t}\\n\\texecute() {\\n\\t\\tthis.filterSizeId.setValue(4);\\n\\t\\tthis.sourceTextureId.setValue(this.sourceTexture);\\n\\t\\tconst { width, height } = this.sourceTexture;\\n\\t\\tthis.sourceInvResolutionValue[0] = 1 / width;\\n\\t\\tthis.sourceInvResolutionValue[1] = 1 / height;\\n\\t\\tthis.sourceInvResolutionId.setValue(this.sourceInvResolutionValue);\\n\\t\\tsuper.execute();\\n\\t}\\n}\\n\\nvar ssao_default$1 = `\\n\\t#include \\\"screenDepthPS\\\"\\n\\t\\n\\tvarying vec2 uv0;\\n\\tuniform vec2 uInvResolution;\\n\\tuniform float uAspect;\\n\\t#define saturate(x) clamp(x,0.0,1.0)\\n\\thighp float getWFromProjectionMatrix(const mat4 p, const vec3 v) {\\n\\t\\treturn -v.z;\\n\\t}\\n\\thighp float getViewSpaceZFromW(const mat4 p, const float w) {\\n\\t\\treturn -w;\\n\\t}\\n\\tconst float kLog2LodRate = 3.0;\\n\\tfloat random(const highp vec2 w) {\\n\\t\\tconst vec3 m = vec3(0.06711056, 0.00583715, 52.9829189);\\n\\t\\treturn fract(m.z * fract(dot(w, m.xy)));\\n\\t}\\n\\thighp vec2 getFragCoord() {\\n\\t\\treturn gl_FragCoord.xy;\\n\\t}\\n\\thighp vec3 computeViewSpacePositionFromDepth(highp vec2 uv, highp float linearDepth) {\\n\\t\\treturn vec3((0.5 - uv) * vec2(uAspect, 1.0) * linearDepth, linearDepth);\\n\\t}\\n\\thighp vec3 faceNormal(highp vec3 dpdx, highp vec3 dpdy) {\\n\\t\\treturn normalize(cross(dpdx, dpdy));\\n\\t}\\n\\thighp vec3 computeViewSpaceNormal(const highp vec3 position) {\\n\\t\\treturn faceNormal(dFdx(position), dFdy(position));\\n\\t}\\n\\thighp vec3 computeViewSpaceNormal(const highp vec3 position, const highp vec2 uv) {\\n\\t\\thighp vec2 uvdx = uv + vec2(uInvResolution.x, 0.0);\\n\\t\\thighp vec2 uvdy = uv + vec2(0.0, uInvResolution.y);\\n\\t\\thighp vec3 px = computeViewSpacePositionFromDepth(uvdx, -getLinearScreenDepth(uvdx));\\n\\t\\thighp vec3 py = computeViewSpacePositionFromDepth(uvdy, -getLinearScreenDepth(uvdy));\\n\\t\\thighp vec3 dpdx = px - position;\\n\\t\\thighp vec3 dpdy = py - position;\\n\\t\\treturn faceNormal(dpdx, dpdy);\\n\\t}\\n\\tuniform vec2 uSampleCount;\\n\\tuniform float uSpiralTurns;\\n\\t#define PI (3.14159)\\n\\tmediump vec3 tapLocation(mediump float i, const mediump float noise) {\\n\\t\\tmediump float offset = ((2.0 * PI) * 2.4) * noise;\\n\\t\\tmediump float angle = ((i * uSampleCount.y) * uSpiralTurns) * (2.0 * PI) + offset;\\n\\t\\tmediump float radius = (i + noise + 0.5) * uSampleCount.y;\\n\\t\\treturn vec3(cos(angle), sin(angle), radius * radius);\\n\\t}\\n\\thighp vec2 startPosition(const float noise) {\\n\\t\\tfloat angle = ((2.0 * PI) * 2.4) * noise;\\n\\t\\treturn vec2(cos(angle), sin(angle));\\n\\t}\\n\\tuniform vec2 uAngleIncCosSin;\\n\\thighp mat2 tapAngleStep() {\\n\\t\\thighp vec2 t = uAngleIncCosSin;\\n\\t\\treturn mat2(t.x, t.y, -t.y, t.x);\\n\\t}\\n\\tmediump vec3 tapLocationFast(mediump float i, mediump vec2 p, const mediump float noise) {\\n\\t\\tmediump float radius = (i + noise + 0.5) * uSampleCount.y;\\n\\t\\treturn vec3(p, radius * radius);\\n\\t}\\n\\tuniform float uMaxLevel;\\n\\tuniform float uInvRadiusSquared;\\n\\tuniform float uMinHorizonAngleSineSquared;\\n\\tuniform float uBias;\\n\\tuniform float uPeak2;\\n\\tvoid computeAmbientOcclusionSAO(inout mediump float occlusion, mediump float i, mediump float ssDiskRadius,\\n\\t\\t\\tconst highp vec2 uv, const highp vec3 origin, const mediump vec3 normal,\\n\\t\\t\\tconst mediump vec2 tapPosition, const float noise) {\\n\\t\\tmediump vec3 tap = tapLocationFast(i, tapPosition, noise);\\n\\t\\tmediump float ssRadius = max(1.0, tap.z * ssDiskRadius);\\n\\t\\tmediump vec2 uvSamplePos = uv + vec2(ssRadius * tap.xy) * uInvResolution;\\n\\t\\tmediump float level = clamp(floor(log2(ssRadius)) - kLog2LodRate, 0.0, float(uMaxLevel));\\n\\t\\thighp float occlusionDepth = -getLinearScreenDepth(uvSamplePos);\\n\\t\\thighp vec3 p = computeViewSpacePositionFromDepth(uvSamplePos, occlusionDepth);\\n\\t\\tvec3 v = p - origin;\\n\\t\\tfloat vv = dot(v, v);\\n\\t\\tfloat vn = dot(v, normal);\\n\\t\\tmediump float w = max(0.0, 1.0 - vv * uInvRadiusSquared);\\n\\t\\tw = w * w;\\n\\t\\tw *= step(vv * uMinHorizonAngleSineSquared, vn * vn);\\n\\t\\tocclusion += w * max(0.0, vn + origin.z * uBias) / (vv + uPeak2);\\n\\t}\\n\\tuniform float uProjectionScaleRadius;\\n\\tuniform float uIntensity;\\n\\tuniform float uRandomize;\\n\\tfloat scalableAmbientObscurance(highp vec2 uv, highp vec3 origin, vec3 normal) {\\n\\t\\tfloat noise = random(getFragCoord()) + uRandomize;\\n\\t\\thighp vec2 tapPosition = startPosition(noise);\\n\\t\\thighp mat2 angleStep = tapAngleStep();\\n\\t\\tfloat ssDiskRadius = -(uProjectionScaleRadius / origin.z);\\n\\t\\tfloat occlusion = 0.0;\\n\\t\\tfor (float i = 0.0; i < uSampleCount.x; i += 1.0) {\\n\\t\\t\\tcomputeAmbientOcclusionSAO(occlusion, i, ssDiskRadius, uv, origin, normal, tapPosition, noise);\\n\\t\\t\\ttapPosition = angleStep * tapPosition;\\n\\t\\t}\\n\\t\\treturn occlusion;\\n\\t}\\n\\tuniform float uPower;\\n\\tvoid main() {\\n\\t\\thighp vec2 uv = uv0;\\n\\t\\thighp float depth = -getLinearScreenDepth(uv0);\\n\\t\\thighp vec3 origin = computeViewSpacePositionFromDepth(uv, depth);\\n\\t\\tvec3 normal = computeViewSpaceNormal(origin, uv);\\n\\t\\tfloat occlusion = 0.0;\\n\\t\\tif (uIntensity > 0.0) {\\n\\t\\t\\tocclusion = scalableAmbientObscurance(uv, origin, normal);\\n\\t\\t}\\n\\t\\tfloat ao = max(0.0, 1.0 - occlusion * uIntensity);\\n\\t\\tao = pow(ao, uPower);\\n\\t\\tgl_FragColor = vec4(ao, ao, ao, 1.0);\\n\\t}\\n`;\\n\\nvar ssao_default = `\\n\\t#include \\\"screenDepthPS\\\"\\n\\tvarying uv0: vec2f;\\n\\tuniform uInvResolution: vec2f;\\n\\tuniform uAspect: f32;\\n\\tfn getWFromProjectionMatrix(p: mat4x4f, v: vec3f) -> f32 {\\n\\t\\treturn -v.z;\\n\\t}\\n\\tfn getViewSpaceZFromW(p: mat4x4f, w: f32) -> f32 {\\n\\t\\treturn -w;\\n\\t}\\n\\tconst kLog2LodRate: f32 = 3.0;\\n\\tfn random(w: vec2f) -> f32 {\\n\\t\\tconst m: vec3f = vec3f(0.06711056, 0.00583715, 52.9829189);\\n\\t\\treturn fract(m.z * fract(dot(w, m.xy)));\\n\\t}\\n\\tfn getFragCoord() -> vec2f {\\n\\t\\treturn pcPosition.xy;\\n\\t}\\n\\tfn computeViewSpacePositionFromDepth(uv: vec2f, linearDepth: f32) -> vec3f {\\n\\t\\treturn vec3f((0.5 - uv) * vec2f(uniform.uAspect, 1.0) * linearDepth, linearDepth);\\n\\t}\\n\\tfn faceNormal(dpdx: vec3f, dpdy: vec3f) -> vec3f {\\n\\t\\treturn normalize(cross(dpdx, dpdy));\\n\\t}\\n\\tfn computeViewSpaceNormalDeriv(position: vec3f) -> vec3f {\\n\\t\\treturn faceNormal(dpdx(position), dpdy(position));\\n\\t}\\n\\tfn computeViewSpaceNormalDepth(position: vec3f, uv: vec2f) -> vec3f {\\n\\t\\tlet uvdx: vec2f = uv + vec2f(uniform.uInvResolution.x, 0.0);\\n\\t\\tlet uvdy: vec2f = uv + vec2f(0.0, uniform.uInvResolution.y);\\n\\t\\tlet px: vec3f = computeViewSpacePositionFromDepth(uvdx, -getLinearScreenDepth(uvdx));\\n\\t\\tlet py: vec3f = computeViewSpacePositionFromDepth(uvdy, -getLinearScreenDepth(uvdy));\\n\\t\\tlet dpdx: vec3f = px - position;\\n\\t\\tlet dpdy: vec3f = py - position;\\n\\t\\treturn faceNormal(dpdx, dpdy);\\n\\t}\\n\\tuniform uSampleCount: vec2f;\\n\\tuniform uSpiralTurns: f32;\\n\\tconst PI: f32 = 3.14159;\\n\\tfn tapLocation(i: f32, noise: f32) -> vec3f {\\n\\t\\tlet offset: f32 = ((2.0 * PI) * 2.4) * noise;\\n\\t\\tlet angle: f32 = ((i * uniform.uSampleCount.y) * uniform.uSpiralTurns) * (2.0 * PI) + offset;\\n\\t\\tlet radius: f32 = (i + noise + 0.5) * uniform.uSampleCount.y;\\n\\t\\treturn vec3f(cos(angle), sin(angle), radius * radius);\\n\\t}\\n\\tfn startPosition(noise: f32) -> vec2f {\\n\\t\\tlet angle: f32 = ((2.0 * PI) * 2.4) * noise;\\n\\t\\treturn vec2f(cos(angle), sin(angle));\\n\\t}\\n\\tuniform uAngleIncCosSin: vec2f;\\n\\tfn tapAngleStep() -> mat2x2f {\\n\\t\\tlet t: vec2f = uniform.uAngleIncCosSin;\\n\\t\\treturn mat2x2f(vec2f(t.x, t.y), vec2f(-t.y, t.x));\\n\\t}\\n\\tfn tapLocationFast(i: f32, p: vec2f, noise_in: f32) -> vec3f {\\n\\t\\tlet radius: f32 = (i + noise_in + 0.5) * uniform.uSampleCount.y;\\n\\t\\treturn vec3f(p.x, p.y, radius * radius);\\n\\t}\\n\\tuniform uMaxLevel: f32;\\n\\tuniform uInvRadiusSquared: f32;\\n\\tuniform uMinHorizonAngleSineSquared: f32;\\n\\tuniform uBias: f32;\\n\\tuniform uPeak2: f32;\\n\\tfn computeAmbientOcclusionSAO(occlusion_ptr: ptr<function, f32>, i: f32, ssDiskRadius: f32,\\n\\t\\t\\tuv: vec2f, origin: vec3f, normal: vec3f,\\n\\t\\t\\ttapPosition: vec2f, noise: f32) {\\n\\t\\tlet tap: vec3f = tapLocationFast(i, tapPosition, noise);\\n\\t\\tlet ssRadius: f32 = max(1.0, tap.z * ssDiskRadius);\\n\\t\\tlet uvSamplePos: vec2f = uv + (ssRadius * tap.xy) * uniform.uInvResolution;\\n\\t\\tlet level: f32 = clamp(floor(log2(ssRadius)) - kLog2LodRate, 0.0, uniform.uMaxLevel);\\n\\t\\tlet occlusionDepth: f32 = -getLinearScreenDepth(uvSamplePos);\\n\\t\\tlet p: vec3f = computeViewSpacePositionFromDepth(uvSamplePos, occlusionDepth);\\n\\t\\tlet v: vec3f = p - origin;\\n\\t\\tlet vv: f32 = dot(v, v);\\n\\t\\tlet vn: f32 = dot(v, normal);\\n\\t\\tvar w_val: f32 = max(0.0, 1.0 - vv * uniform.uInvRadiusSquared);\\n\\t\\tw_val = w_val * w_val;\\n\\t\\tw_val = w_val * step(vv * uniform.uMinHorizonAngleSineSquared, vn * vn);\\n\\t\\t*occlusion_ptr = *occlusion_ptr + w_val * max(0.0, vn + origin.z * uniform.uBias) / (vv + uniform.uPeak2);\\n\\t}\\n\\tuniform uProjectionScaleRadius: f32;\\n\\tuniform uIntensity: f32;\\n\\tuniform uRandomize: f32;\\n\\tfn scalableAmbientObscurance(uv: vec2f, origin: vec3f, normal: vec3f) -> f32 {\\n\\t\\tlet noise: f32 = random(getFragCoord()) + uniform.uRandomize;\\n\\t\\tvar tapPosition: vec2f = startPosition(noise);\\n\\t\\tlet angleStep: mat2x2f = tapAngleStep();\\n\\t\\tlet ssDiskRadius: f32 = -(uniform.uProjectionScaleRadius / origin.z);\\n\\t\\tvar occlusion: f32 = 0.0;\\n\\t\\tfor (var i: i32 = 0; i < i32(uniform.uSampleCount.x); i = i + 1) {\\n\\t\\t\\tcomputeAmbientOcclusionSAO(&occlusion, f32(i), ssDiskRadius, uv, origin, normal, tapPosition, noise);\\n\\t\\t\\ttapPosition = angleStep * tapPosition;\\n\\t\\t}\\n\\t\\treturn occlusion;\\n\\t}\\n\\tuniform uPower: f32;\\n\\t@fragment\\n\\tfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\t\\tvar output: FragmentOutput;\\n\\t\\tlet uv: vec2f = input.uv0;\\n\\t\\tlet depth: f32 = -getLinearScreenDepth(input.uv0);\\n\\t\\tlet origin: vec3f = computeViewSpacePositionFromDepth(uv, depth);\\n\\t\\tlet normal: vec3f = computeViewSpaceNormalDepth(origin, uv);\\n\\t\\tvar occlusion: f32 = 0.0;\\n\\t\\tif (uniform.uIntensity > 0.0) {\\n\\t\\t\\tocclusion = scalableAmbientObscurance(uv, origin, normal);\\n\\t\\t}\\n\\t\\tvar ao: f32 = max(0.0, 1.0 - occlusion * uniform.uIntensity);\\n\\t\\tao = pow(ao, uniform.uPower);\\n\\t\\toutput.color = vec4f(ao, ao, ao, 1.0);\\n\\t\\treturn output;\\n\\t}\\n`;\\n\\nclass RenderPassSsao extends RenderPassShaderQuad {\\n\\tradius = 5;\\n\\tintensity = 1;\\n\\tpower = 1;\\n\\tsampleCount = 10;\\n\\tminAngle = 5;\\n\\trandomize = false;\\n\\tssaoTexture;\\n\\t_scale = 1;\\n\\t_blueNoise = new BlueNoise(19);\\n\\tconstructor(device, sourceTexture, cameraComponent, blurEnabled) {\\n\\t\\tsuper(device);\\n\\t\\tthis.sourceTexture = sourceTexture;\\n\\t\\tthis.cameraComponent = cameraComponent;\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set(\\\"ssaoPS\\\", ssao_default$1);\\n\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set(\\\"ssaoPS\\\", ssao_default);\\n\\t\\tconst defines = /* @__PURE__ */ new Map();\\n\\t\\tShaderUtils.addScreenDepthChunkDefines(device, cameraComponent.shaderParams, defines);\\n\\t\\tthis.shader = ShaderUtils.createShader(device, {\\n\\t\\t\\tuniqueName: \\\"SsaoShader\\\",\\n\\t\\t\\tattributes: { aPosition: SEMANTIC_POSITION },\\n\\t\\t\\tvertexChunk: \\\"quadVS\\\",\\n\\t\\t\\tfragmentChunk: \\\"ssaoPS\\\",\\n\\t\\t\\tfragmentDefines: defines\\n\\t\\t});\\n\\t\\tconst rt = this.createRenderTarget(\\\"SsaoFinalTexture\\\");\\n\\t\\tthis.ssaoTexture = rt.colorBuffer;\\n\\t\\tthis.init(rt, {\\n\\t\\t\\tresizeSource: this.sourceTexture\\n\\t\\t});\\n\\t\\tconst clearColor = new Color(0, 0, 0, 0);\\n\\t\\tthis.setClearColor(clearColor);\\n\\t\\tif (blurEnabled) {\\n\\t\\t\\tconst blurRT = this.createRenderTarget(\\\"SsaoTempTexture\\\");\\n\\t\\t\\tconst blurPassHorizontal = new RenderPassDepthAwareBlur(device, rt.colorBuffer, cameraComponent, true);\\n\\t\\t\\tblurPassHorizontal.init(blurRT, {\\n\\t\\t\\t\\tresizeSource: rt.colorBuffer\\n\\t\\t\\t});\\n\\t\\t\\tblurPassHorizontal.setClearColor(clearColor);\\n\\t\\t\\tconst blurPassVertical = new RenderPassDepthAwareBlur(device, blurRT.colorBuffer, cameraComponent, false);\\n\\t\\t\\tblurPassVertical.init(rt, {\\n\\t\\t\\t\\tresizeSource: rt.colorBuffer\\n\\t\\t\\t});\\n\\t\\t\\tblurPassVertical.setClearColor(clearColor);\\n\\t\\t\\tthis.afterPasses.push(blurPassHorizontal);\\n\\t\\t\\tthis.afterPasses.push(blurPassVertical);\\n\\t\\t}\\n\\t\\tthis.ssaoTextureId = device.scope.resolve(\\\"ssaoTexture\\\");\\n\\t\\tthis.ssaoTextureSizeInvId = device.scope.resolve(\\\"ssaoTextureSizeInv\\\");\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.renderTarget?.destroyTextureBuffers();\\n\\t\\tthis.renderTarget?.destroy();\\n\\t\\tthis.renderTarget = null;\\n\\t\\tif (this.afterPasses.length > 0) {\\n\\t\\t\\tconst blurRt = this.afterPasses[0].renderTarget;\\n\\t\\t\\tblurRt?.destroyTextureBuffers();\\n\\t\\t\\tblurRt?.destroy();\\n\\t\\t}\\n\\t\\tthis.afterPasses.forEach((pass) => pass.destroy());\\n\\t\\tthis.afterPasses.length = 0;\\n\\t\\tsuper.destroy();\\n\\t}\\n\\tset scale(value) {\\n\\t\\tthis._scale = value;\\n\\t\\tthis.scaleX = value;\\n\\t\\tthis.scaleY = value;\\n\\t}\\n\\tget scale() {\\n\\t\\treturn this._scale;\\n\\t}\\n\\tcreateRenderTarget(name) {\\n\\t\\treturn new RenderTarget({\\n\\t\\t\\tdepth: false,\\n\\t\\t\\tcolorBuffer: Texture.createDataTexture2D(this.device, name, 1, 1, PIXELFORMAT_R8)\\n\\t\\t});\\n\\t}\\n\\texecute() {\\n\\t\\tconst { device, sourceTexture, sampleCount, minAngle, scale } = this;\\n\\t\\tconst { width, height } = this.renderTarget.colorBuffer;\\n\\t\\tconst scope = device.scope;\\n\\t\\tscope.resolve(\\\"uAspect\\\").setValue(width / height);\\n\\t\\tscope.resolve(\\\"uInvResolution\\\").setValue([1 / width, 1 / height]);\\n\\t\\tscope.resolve(\\\"uSampleCount\\\").setValue([sampleCount, 1 / sampleCount]);\\n\\t\\tconst minAngleSin = Math.sin(minAngle * math.DEG_TO_RAD);\\n\\t\\tscope.resolve(\\\"uMinHorizonAngleSineSquared\\\").setValue(minAngleSin * minAngleSin);\\n\\t\\tconst spiralTurns = 10;\\n\\t\\tconst step = 1 / (sampleCount - 0.5) * spiralTurns * 2 * 3.141;\\n\\t\\tconst radius = this.radius / scale;\\n\\t\\tconst bias = 1e-3;\\n\\t\\tconst peak = 0.1 * radius;\\n\\t\\tconst intensity = 2 * (peak * 2 * 3.141) * this.intensity / sampleCount;\\n\\t\\tconst projectionScale = 0.5 * sourceTexture.height;\\n\\t\\tscope.resolve(\\\"uSpiralTurns\\\").setValue(spiralTurns);\\n\\t\\tscope.resolve(\\\"uAngleIncCosSin\\\").setValue([Math.cos(step), Math.sin(step)]);\\n\\t\\tscope.resolve(\\\"uMaxLevel\\\").setValue(0);\\n\\t\\tscope.resolve(\\\"uInvRadiusSquared\\\").setValue(1 / (radius * radius));\\n\\t\\tscope.resolve(\\\"uBias\\\").setValue(bias);\\n\\t\\tscope.resolve(\\\"uPeak2\\\").setValue(peak * peak);\\n\\t\\tscope.resolve(\\\"uIntensity\\\").setValue(intensity);\\n\\t\\tscope.resolve(\\\"uPower\\\").setValue(this.power);\\n\\t\\tscope.resolve(\\\"uProjectionScaleRadius\\\").setValue(projectionScale * radius);\\n\\t\\tscope.resolve(\\\"uRandomize\\\").setValue(this.randomize ? this._blueNoise.value() : 0);\\n\\t\\tsuper.execute();\\n\\t}\\n\\tafter() {\\n\\t\\tthis.ssaoTextureId.setValue(this.ssaoTexture);\\n\\t\\tconst srcTexture = this.sourceTexture;\\n\\t\\tthis.ssaoTextureSizeInvId.setValue([1 / srcTexture.width, 1 / srcTexture.height]);\\n\\t}\\n}\\n\\nclass CameraFrameOptions {\\n\\tformats;\\n\\tstencil = false;\\n\\tsamples = 1;\\n\\tsceneColorMap = false;\\n\\t// skybox is the last layer rendered before the grab passes\\n\\tlastGrabLayerId = LAYERID_SKYBOX;\\n\\tlastGrabLayerIsTransparent = false;\\n\\t// immediate layer is the last layer rendered before the post-processing\\n\\tlastSceneLayerId = LAYERID_IMMEDIATE;\\n\\tlastSceneLayerIsTransparent = true;\\n\\t// TAA\\n\\ttaaEnabled = false;\\n\\t// Bloom\\n\\tbloomEnabled = false;\\n\\t// SSAO\\n\\tssaoType = SSAOTYPE_NONE;\\n\\tssaoBlurEnabled = true;\\n\\tprepassEnabled = false;\\n\\t// DOF\\n\\tdofEnabled = false;\\n\\tdofNearBlur = false;\\n\\tdofHighQuality = true;\\n}\\nconst _defaultOptions = new CameraFrameOptions();\\nclass FramePassCameraFrame extends FramePass {\\n\\tapp;\\n\\tprePass;\\n\\tscenePass;\\n\\tcomposePass;\\n\\tbloomPass;\\n\\tssaoPass;\\n\\ttaaPass;\\n\\tscenePassHalf;\\n\\tdofPass;\\n\\t_renderTargetScale = 1;\\n\\tlayersDirty = false;\\n\\tcameraFrame;\\n\\trt = null;\\n\\tconstructor(app, cameraFrame, cameraComponent, options = {}) {\\n\\t\\tsuper(app.graphicsDevice);\\n\\t\\tthis.app = app;\\n\\t\\tthis.cameraComponent = cameraComponent;\\n\\t\\tthis.cameraFrame = cameraFrame;\\n\\t\\tthis.options = this.sanitizeOptions(options);\\n\\t\\tthis.setupRenderPasses(this.options);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.reset();\\n\\t}\\n\\treset() {\\n\\t\\tthis.sceneTexture = null;\\n\\t\\tthis.sceneTextureHalf = null;\\n\\t\\tif (this.rt) {\\n\\t\\t\\tthis.rt.destroyTextureBuffers();\\n\\t\\t\\tthis.rt.destroy();\\n\\t\\t\\tthis.rt = null;\\n\\t\\t}\\n\\t\\tif (this.rtHalf) {\\n\\t\\t\\tthis.rtHalf.destroyTextureBuffers();\\n\\t\\t\\tthis.rtHalf.destroy();\\n\\t\\t\\tthis.rtHalf = null;\\n\\t\\t}\\n\\t\\tthis.beforePasses.forEach((pass) => pass.destroy());\\n\\t\\tthis.beforePasses.length = 0;\\n\\t\\tthis.prePass = null;\\n\\t\\tthis.scenePass = null;\\n\\t\\tthis.scenePassTransparent = null;\\n\\t\\tthis.colorGrabPass = null;\\n\\t\\tthis.composePass = null;\\n\\t\\tthis.bloomPass = null;\\n\\t\\tthis.ssaoPass = null;\\n\\t\\tthis.taaPass = null;\\n\\t\\tthis.afterPass = null;\\n\\t\\tthis.scenePassHalf = null;\\n\\t\\tthis.dofPass = null;\\n\\t}\\n\\tsanitizeOptions(options) {\\n\\t\\toptions = Object.assign({}, _defaultOptions, options);\\n\\t\\tif (options.taaEnabled || options.ssaoType !== SSAOTYPE_NONE || options.dofEnabled) {\\n\\t\\t\\toptions.prepassEnabled = true;\\n\\t\\t}\\n\\t\\treturn options;\\n\\t}\\n\\tset renderTargetScale(value) {\\n\\t\\tthis._renderTargetScale = value;\\n\\t\\tif (this.scenePass) {\\n\\t\\t\\tthis.scenePass.scaleX = value;\\n\\t\\t\\tthis.scenePass.scaleY = value;\\n\\t\\t}\\n\\t}\\n\\tget renderTargetScale() {\\n\\t\\treturn this._renderTargetScale;\\n\\t}\\n\\tneedsReset(options) {\\n\\t\\tconst currentOptions = this.options;\\n\\t\\tconst arraysNotEqual = (arr1, arr2) => arr1 !== arr2 && (!(Array.isArray(arr1) && Array.isArray(arr2)) || arr1.length !== arr2.length || !arr1.every((value, index) => value === arr2[index]));\\n\\t\\treturn options.ssaoType !== currentOptions.ssaoType || options.ssaoBlurEnabled !== currentOptions.ssaoBlurEnabled || options.taaEnabled !== currentOptions.taaEnabled || options.samples !== currentOptions.samples || options.stencil !== currentOptions.stencil || options.bloomEnabled !== currentOptions.bloomEnabled || options.prepassEnabled !== currentOptions.prepassEnabled || options.sceneColorMap !== currentOptions.sceneColorMap || options.dofEnabled !== currentOptions.dofEnabled || options.dofNearBlur !== currentOptions.dofNearBlur || options.dofHighQuality !== currentOptions.dofHighQuality || arraysNotEqual(options.formats, currentOptions.formats);\\n\\t}\\n\\t// manually called, applies changes\\n\\tupdate(options) {\\n\\t\\toptions = this.sanitizeOptions(options);\\n\\t\\tif (this.needsReset(options) || this.layersDirty) {\\n\\t\\t\\tthis.layersDirty = false;\\n\\t\\t\\tthis.reset();\\n\\t\\t}\\n\\t\\tthis.options = options;\\n\\t\\tif (!this.sceneTexture) {\\n\\t\\t\\tthis.setupRenderPasses(this.options);\\n\\t\\t}\\n\\t}\\n\\tcreateRenderTarget(name, depth, stencil, samples, flipY) {\\n\\t\\tconst texture = new Texture(this.device, {\\n\\t\\t\\tname,\\n\\t\\t\\twidth: 4,\\n\\t\\t\\theight: 4,\\n\\t\\t\\tformat: this.hdrFormat,\\n\\t\\t\\tmipmaps: false,\\n\\t\\t\\tminFilter: FILTER_LINEAR,\\n\\t\\t\\tmagFilter: FILTER_LINEAR,\\n\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t});\\n\\t\\treturn new RenderTarget({\\n\\t\\t\\tcolorBuffer: texture,\\n\\t\\t\\tdepth,\\n\\t\\t\\tstencil,\\n\\t\\t\\tsamples,\\n\\t\\t\\tflipY\\n\\t\\t});\\n\\t}\\n\\tsetupRenderPasses(options) {\\n\\t\\tconst { device } = this;\\n\\t\\tconst cameraComponent = this.cameraComponent;\\n\\t\\tconst targetRenderTarget = cameraComponent.renderTarget;\\n\\t\\tthis.hdrFormat = device.getRenderableHdrFormat(options.formats, true, options.samples) || PIXELFORMAT_RGBA8;\\n\\t\\tthis._bloomEnabled = options.bloomEnabled && this.hdrFormat !== PIXELFORMAT_RGBA8;\\n\\t\\tthis._sceneHalfEnabled = this._bloomEnabled || options.dofEnabled;\\n\\t\\tcameraComponent.shaderParams.ssaoEnabled = options.ssaoType === SSAOTYPE_LIGHTING;\\n\\t\\tconst flipY = !!targetRenderTarget?.flipY;\\n\\t\\tthis.rt = this.createRenderTarget(\\\"SceneColor\\\", true, options.stencil, options.samples, flipY);\\n\\t\\tthis.sceneTexture = this.rt.colorBuffer;\\n\\t\\tif (this._sceneHalfEnabled) {\\n\\t\\t\\tthis.rtHalf = this.createRenderTarget(\\\"SceneColorHalf\\\", false, false, 1, flipY);\\n\\t\\t\\tthis.sceneTextureHalf = this.rtHalf.colorBuffer;\\n\\t\\t}\\n\\t\\tthis.sceneOptions = {\\n\\t\\t\\tresizeSource: targetRenderTarget,\\n\\t\\t\\tscaleX: this.renderTargetScale,\\n\\t\\t\\tscaleY: this.renderTargetScale\\n\\t\\t};\\n\\t\\tthis.createPasses(options);\\n\\t\\tconst allPasses = this.collectPasses();\\n\\t\\tthis.beforePasses = allPasses.filter((element) => element !== void 0 && element !== null);\\n\\t\\tthis.updateCameraUseFlags();\\n\\t}\\n\\tupdateCameraUseFlags() {\\n\\t\\tconst firstSeen = /* @__PURE__ */ new Map();\\n\\t\\tconst lastSeen = /* @__PURE__ */ new Map();\\n\\t\\tfor (let i = 0; i < this.beforePasses.length; i++) {\\n\\t\\t\\tconst pass = this.beforePasses[i];\\n\\t\\t\\tif (pass instanceof RenderPassForward) {\\n\\t\\t\\t\\tconst actions = pass.renderActions;\\n\\t\\t\\t\\tfor (let j = 0; j < actions.length; j++) {\\n\\t\\t\\t\\t\\tconst ra = actions[j];\\n\\t\\t\\t\\t\\tconst cam = ra.camera;\\n\\t\\t\\t\\t\\tif (cam) {\\n\\t\\t\\t\\t\\t\\tif (!firstSeen.has(cam)) {\\n\\t\\t\\t\\t\\t\\t\\tfirstSeen.set(cam, ra);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlastSeen.set(cam, ra);\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfirstSeen.forEach((ra) => {\\n\\t\\t\\tra.firstCameraUse = true;\\n\\t\\t});\\n\\t\\tlastSeen.forEach((ra) => {\\n\\t\\t\\tra.lastCameraUse = true;\\n\\t\\t});\\n\\t}\\n\\tcollectPasses() {\\n\\t\\treturn [this.prePass, this.ssaoPass, this.scenePass, this.colorGrabPass, this.scenePassTransparent, this.taaPass, this.scenePassHalf, this.bloomPass, this.dofPass, this.composePass, this.afterPass];\\n\\t}\\n\\tcreatePasses(options) {\\n\\t\\tthis.setupScenePrepass(options);\\n\\t\\tthis.setupSsaoPass(options);\\n\\t\\tconst scenePassesInfo = this.setupScenePass(options);\\n\\t\\tconst sceneTextureWithTaa = this.setupTaaPass(options);\\n\\t\\tthis.setupSceneHalfPass(options, sceneTextureWithTaa);\\n\\t\\tthis.setupBloomPass(options, this.sceneTextureHalf);\\n\\t\\tthis.setupDofPass(options, this.sceneTexture, this.sceneTextureHalf);\\n\\t\\tthis.setupComposePass(options);\\n\\t\\tthis.setupAfterPass(options, scenePassesInfo);\\n\\t}\\n\\tsetupScenePrepass(options) {\\n\\t\\tif (options.prepassEnabled) {\\n\\t\\t\\tconst { app, device, cameraComponent } = this;\\n\\t\\t\\tconst { scene, renderer } = app;\\n\\t\\t\\tthis.prePass = new RenderPassPrepass(device, scene, renderer, cameraComponent, this.sceneOptions);\\n\\t\\t}\\n\\t}\\n\\tsetupScenePassSettings(pass) {\\n\\t\\tpass.gammaCorrection = GAMMA_NONE;\\n\\t\\tpass.toneMapping = TONEMAP_NONE;\\n\\t}\\n\\tsetupScenePass(options) {\\n\\t\\tconst { app, device, cameraComponent } = this;\\n\\t\\tconst { scene, renderer } = app;\\n\\t\\tconst composition = scene.layers;\\n\\t\\tthis.scenePass = new RenderPassForward(device, composition, scene, renderer);\\n\\t\\tthis.setupScenePassSettings(this.scenePass);\\n\\t\\tthis.scenePass.init(this.rt, this.sceneOptions);\\n\\t\\tconst lastLayerId = options.sceneColorMap ? options.lastGrabLayerId : options.lastSceneLayerId;\\n\\t\\tconst lastLayerIsTransparent = options.sceneColorMap ? options.lastGrabLayerIsTransparent : options.lastSceneLayerIsTransparent;\\n\\t\\tconst ret = {\\n\\t\\t\\tlastAddedIndex: 0,\\n\\t\\t\\t// the last layer index added to the scene pass\\n\\t\\t\\tclearRenderTarget: true\\n\\t\\t\\t// true if the render target should be cleared\\n\\t\\t};\\n\\t\\tret.lastAddedIndex = this.scenePass.addLayers(composition, cameraComponent, ret.lastAddedIndex, ret.clearRenderTarget, lastLayerId, lastLayerIsTransparent);\\n\\t\\tret.clearRenderTarget = false;\\n\\t\\tif (options.sceneColorMap) {\\n\\t\\t\\tthis.colorGrabPass = new FramePassColorGrab(device);\\n\\t\\t\\tthis.colorGrabPass.source = this.rt;\\n\\t\\t\\tthis.scenePassTransparent = new RenderPassForward(device, composition, scene, renderer);\\n\\t\\t\\tthis.setupScenePassSettings(this.scenePassTransparent);\\n\\t\\t\\tthis.scenePassTransparent.init(this.rt);\\n\\t\\t\\tret.lastAddedIndex = this.scenePassTransparent.addLayers(composition, cameraComponent, ret.lastAddedIndex, ret.clearRenderTarget, options.lastSceneLayerId, options.lastSceneLayerIsTransparent);\\n\\t\\t\\tif (!this.scenePassTransparent.rendersAnything) {\\n\\t\\t\\t\\tthis.scenePassTransparent.destroy();\\n\\t\\t\\t\\tthis.scenePassTransparent = null;\\n\\t\\t\\t}\\n\\t\\t\\tif (this.scenePassTransparent) {\\n\\t\\t\\t\\tif (options.prepassEnabled) {\\n\\t\\t\\t\\t\\tthis.scenePassTransparent.depthStencilOps.storeDepth = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn ret;\\n\\t}\\n\\tsetupSsaoPass(options) {\\n\\t\\tconst { ssaoBlurEnabled, ssaoType } = options;\\n\\t\\tconst { device, cameraComponent } = this;\\n\\t\\tif (ssaoType !== SSAOTYPE_NONE) {\\n\\t\\t\\tthis.ssaoPass = new RenderPassSsao(device, this.sceneTexture, cameraComponent, ssaoBlurEnabled);\\n\\t\\t}\\n\\t}\\n\\tsetupSceneHalfPass(options, sourceTexture) {\\n\\t\\tif (this._sceneHalfEnabled) {\\n\\t\\t\\tthis.scenePassHalf = new RenderPassDownsample(this.device, this.sceneTexture, {\\n\\t\\t\\t\\tboxFilter: true,\\n\\t\\t\\t\\tremoveInvalid: true\\n\\t\\t\\t\\t// remove invalid pixels to avoid bloom / dof artifacts\\n\\t\\t\\t});\\n\\t\\t\\tthis.scenePassHalf.name = \\\"RenderPassSceneHalf\\\";\\n\\t\\t\\tthis.scenePassHalf.init(this.rtHalf, {\\n\\t\\t\\t\\tresizeSource: sourceTexture,\\n\\t\\t\\t\\tscaleX: 0.5,\\n\\t\\t\\t\\tscaleY: 0.5\\n\\t\\t\\t});\\n\\t\\t\\tthis.scenePassHalf.setClearColor(Color.BLACK);\\n\\t\\t}\\n\\t}\\n\\tsetupBloomPass(options, inputTexture) {\\n\\t\\tif (this._bloomEnabled) {\\n\\t\\t\\tthis.bloomPass = new FramePassBloom(this.device, inputTexture, this.hdrFormat);\\n\\t\\t}\\n\\t}\\n\\tsetupDofPass(options, inputTexture, inputTextureHalf) {\\n\\t\\tif (options.dofEnabled) {\\n\\t\\t\\tthis.dofPass = new FramePassDof(this.device, this.cameraComponent, inputTexture, inputTextureHalf, options.dofHighQuality, options.dofNearBlur);\\n\\t\\t}\\n\\t}\\n\\tsetupTaaPass(options) {\\n\\t\\tlet textureWithTaa = this.sceneTexture;\\n\\t\\tif (options.taaEnabled) {\\n\\t\\t\\tthis.taaPass = new RenderPassTAA(this.device, this.sceneTexture, this.cameraComponent);\\n\\t\\t\\ttextureWithTaa = this.taaPass.historyTexture;\\n\\t\\t}\\n\\t\\treturn textureWithTaa;\\n\\t}\\n\\tsetupComposePass(options) {\\n\\t\\tthis.composePass = new RenderPassCompose(this.device);\\n\\t\\tthis.composePass.bloomTexture = this.bloomPass?.bloomTexture;\\n\\t\\tthis.composePass.hdrScene = this.hdrFormat !== PIXELFORMAT_RGBA8;\\n\\t\\tthis.composePass.taaEnabled = options.taaEnabled;\\n\\t\\tthis.composePass.cocTexture = this.dofPass?.cocTexture;\\n\\t\\tthis.composePass.blurTexture = this.dofPass?.blurTexture;\\n\\t\\tthis.composePass.blurTextureUpscale = !this.dofPass?.highQuality;\\n\\t\\tconst cameraComponent = this.cameraComponent;\\n\\t\\tconst targetRenderTarget = cameraComponent.renderTarget;\\n\\t\\tthis.composePass.init(targetRenderTarget);\\n\\t\\tthis.composePass.ssaoTexture = options.ssaoType === SSAOTYPE_COMBINE ? this.ssaoPass.ssaoTexture : null;\\n\\t}\\n\\tsetupAfterPass(options, scenePassesInfo) {\\n\\t\\tconst { app, cameraComponent } = this;\\n\\t\\tconst { scene, renderer } = app;\\n\\t\\tconst composition = scene.layers;\\n\\t\\tconst targetRenderTarget = cameraComponent.renderTarget;\\n\\t\\tthis.afterPass = new RenderPassForward(this.device, composition, scene, renderer);\\n\\t\\tthis.afterPass.init(targetRenderTarget);\\n\\t\\tthis.afterPass.addLayers(composition, cameraComponent, scenePassesInfo.lastAddedIndex, scenePassesInfo.clearRenderTarget);\\n\\t}\\n\\tframeUpdate() {\\n\\t\\tif (this.layersDirty) {\\n\\t\\t\\tthis.cameraFrame.update();\\n\\t\\t}\\n\\t\\tsuper.frameUpdate();\\n\\t\\tconst sceneTexture = this.taaPass?.update() ?? this.rt.colorBuffer;\\n\\t\\tthis.composePass.sceneTexture = sceneTexture;\\n\\t\\tthis.scenePassHalf?.setSourceTexture(sceneTexture);\\n\\t}\\n}\\n\\nclass CameraFrame {\\n\\t_enabled = true;\\n\\trendering = {\\n\\t\\trenderFormats: [PIXELFORMAT_111110F, PIXELFORMAT_RGBA16F, PIXELFORMAT_RGBA32F],\\n\\t\\tstencil: false,\\n\\t\\trenderTargetScale: 1,\\n\\t\\tsamples: 1,\\n\\t\\tsceneColorMap: false,\\n\\t\\tsceneDepthMap: false,\\n\\t\\ttoneMapping: 0,\\n\\t\\tsharpness: 0\\n\\t};\\n\\tssao = {\\n\\t\\ttype: SSAOTYPE_NONE,\\n\\t\\tblurEnabled: true,\\n\\t\\trandomize: false,\\n\\t\\tintensity: 0.5,\\n\\t\\tradius: 30,\\n\\t\\tsamples: 12,\\n\\t\\tpower: 6,\\n\\t\\tminAngle: 10,\\n\\t\\tscale: 1\\n\\t};\\n\\tbloom = {\\n\\t\\tintensity: 0,\\n\\t\\tblurLevel: 16\\n\\t};\\n\\tgrading = {\\n\\t\\tenabled: false,\\n\\t\\tbrightness: 1,\\n\\t\\tcontrast: 1,\\n\\t\\tsaturation: 1,\\n\\t\\ttint: new Color(1, 1, 1, 1)\\n\\t};\\n\\tcolorLUT = {\\n\\t\\ttexture: null,\\n\\t\\tintensity: 1,\\n\\t\\ttexture2: null,\\n\\t\\tintensity2: 1,\\n\\t\\tblend: 0\\n\\t};\\n\\tvignette = {\\n\\t\\tintensity: 0,\\n\\t\\tinner: 0.5,\\n\\t\\touter: 1,\\n\\t\\tcurvature: 0.5,\\n\\t\\tcolor: new Color(0, 0, 0)\\n\\t};\\n\\ttaa = {\\n\\t\\tenabled: false,\\n\\t\\tjitter: 1\\n\\t};\\n\\tfringing = {\\n\\t\\tintensity: 0\\n\\t};\\n\\tcolorEnhance = {\\n\\t\\tenabled: false,\\n\\t\\tshadows: 0,\\n\\t\\thighlights: 0,\\n\\t\\tvibrance: 0,\\n\\t\\tmidtones: 0,\\n\\t\\tdehaze: 0\\n\\t};\\n\\tdof = {\\n\\t\\tenabled: false,\\n\\t\\tnearBlur: false,\\n\\t\\tfocusDistance: 100,\\n\\t\\tfocusRange: 10,\\n\\t\\tblurRadius: 3,\\n\\t\\tblurRings: 4,\\n\\t\\tblurRingPoints: 5,\\n\\t\\thighQuality: true\\n\\t};\\n\\tdebug = null;\\n\\toptions = new CameraFrameOptions();\\n\\trenderPassCamera = null;\\n\\tconstructor(app, cameraComponent) {\\n\\t\\tthis.app = app;\\n\\t\\tthis.cameraComponent = cameraComponent;\\n\\t\\tthis.updateOptions();\\n\\t\\tthis.enable();\\n\\t\\tthis.cameraLayersChanged = cameraComponent.on(\\\"set:layers\\\", () => {\\n\\t\\t\\tif (this.renderPassCamera) this.renderPassCamera.layersDirty = true;\\n\\t\\t});\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.disable();\\n\\t\\tthis.cameraLayersChanged.off();\\n\\t}\\n\\tenable() {\\n\\t\\tthis.renderPassCamera = this.createRenderPass();\\n\\t\\tthis.cameraComponent.framePasses = [this.renderPassCamera];\\n\\t}\\n\\tdisable() {\\n\\t\\tconst cameraComponent = this.cameraComponent;\\n\\t\\tcameraComponent.framePasses?.forEach((renderPass) => {\\n\\t\\t\\trenderPass.destroy();\\n\\t\\t});\\n\\t\\tcameraComponent.framePasses = [];\\n\\t\\tcameraComponent.rendering = null;\\n\\t\\tcameraComponent.jitter = 0;\\n\\t\\tcameraComponent.shaderParams.ssaoEnabled = false;\\n\\t\\tthis.renderPassCamera = null;\\n\\t}\\n\\tcreateRenderPass() {\\n\\t\\treturn new FramePassCameraFrame(this.app, this, this.cameraComponent, this.options);\\n\\t}\\n\\tset enabled(value) {\\n\\t\\tif (this._enabled !== value) {\\n\\t\\t\\tif (value) {\\n\\t\\t\\t\\tthis.enable();\\n\\t\\t\\t} else {\\n\\t\\t\\t\\tthis.disable();\\n\\t\\t\\t}\\n\\t\\t\\tthis._enabled = value;\\n\\t\\t}\\n\\t}\\n\\tget enabled() {\\n\\t\\treturn this._enabled;\\n\\t}\\n\\tupdateOptions() {\\n\\t\\tconst { options, rendering, bloom, taa, ssao } = this;\\n\\t\\toptions.stencil = rendering.stencil;\\n\\t\\toptions.samples = rendering.samples;\\n\\t\\toptions.sceneColorMap = rendering.sceneColorMap;\\n\\t\\toptions.prepassEnabled = rendering.sceneDepthMap;\\n\\t\\toptions.bloomEnabled = bloom.intensity > 0;\\n\\t\\toptions.taaEnabled = taa.enabled;\\n\\t\\toptions.ssaoType = ssao.type;\\n\\t\\toptions.ssaoBlurEnabled = ssao.blurEnabled;\\n\\t\\toptions.formats = rendering.renderFormats.slice();\\n\\t\\toptions.dofEnabled = this.dof.enabled;\\n\\t\\toptions.dofNearBlur = this.dof.nearBlur;\\n\\t\\toptions.dofHighQuality = this.dof.highQuality;\\n\\t}\\n\\tupdate() {\\n\\t\\tif (!this._enabled) return;\\n\\t\\tconst cameraComponent = this.cameraComponent;\\n\\t\\tconst { options, renderPassCamera, rendering, bloom, grading, colorEnhance, vignette, fringing, taa, ssao } = this;\\n\\t\\tthis.updateOptions();\\n\\t\\trenderPassCamera.update(options);\\n\\t\\tconst { composePass, bloomPass, ssaoPass, dofPass } = renderPassCamera;\\n\\t\\trenderPassCamera.renderTargetScale = math.clamp(rendering.renderTargetScale, 0.1, 1);\\n\\t\\tcomposePass.toneMapping = rendering.toneMapping;\\n\\t\\tcomposePass.sharpness = rendering.sharpness;\\n\\t\\tif (options.bloomEnabled && bloomPass) {\\n\\t\\t\\tcomposePass.bloomIntensity = bloom.intensity;\\n\\t\\t\\tbloomPass.blurLevel = bloom.blurLevel;\\n\\t\\t}\\n\\t\\tif (options.dofEnabled) {\\n\\t\\t\\tdofPass.focusDistance = this.dof.focusDistance;\\n\\t\\t\\tdofPass.focusRange = this.dof.focusRange;\\n\\t\\t\\tdofPass.blurRadius = this.dof.blurRadius;\\n\\t\\t\\tdofPass.blurRings = this.dof.blurRings;\\n\\t\\t\\tdofPass.blurRingPoints = this.dof.blurRingPoints;\\n\\t\\t}\\n\\t\\tif (options.ssaoType !== SSAOTYPE_NONE) {\\n\\t\\t\\tssaoPass.intensity = ssao.intensity;\\n\\t\\t\\tssaoPass.power = ssao.power;\\n\\t\\t\\tssaoPass.radius = ssao.radius;\\n\\t\\t\\tssaoPass.sampleCount = ssao.samples;\\n\\t\\t\\tssaoPass.minAngle = ssao.minAngle;\\n\\t\\t\\tssaoPass.scale = ssao.scale;\\n\\t\\t\\tssaoPass.randomize = ssao.randomize;\\n\\t\\t}\\n\\t\\tcomposePass.gradingEnabled = grading.enabled;\\n\\t\\tif (grading.enabled) {\\n\\t\\t\\tcomposePass.gradingSaturation = grading.saturation;\\n\\t\\t\\tcomposePass.gradingBrightness = grading.brightness;\\n\\t\\t\\tcomposePass.gradingContrast = grading.contrast;\\n\\t\\t\\tcomposePass.gradingTint = grading.tint;\\n\\t\\t}\\n\\t\\tcomposePass.colorLUT = this.colorLUT.texture;\\n\\t\\tcomposePass.colorLUTIntensity = this.colorLUT.intensity;\\n\\t\\tcomposePass.colorLUT2 = this.colorLUT.texture2;\\n\\t\\tcomposePass.colorLUT2Intensity = this.colorLUT.intensity2;\\n\\t\\tcomposePass.colorLUTBlend = this.colorLUT.blend;\\n\\t\\tcomposePass.vignetteEnabled = vignette.intensity > 0;\\n\\t\\tif (composePass.vignetteEnabled) {\\n\\t\\t\\tcomposePass.vignetteInner = vignette.inner;\\n\\t\\t\\tcomposePass.vignetteOuter = vignette.outer;\\n\\t\\t\\tcomposePass.vignetteCurvature = vignette.curvature;\\n\\t\\t\\tcomposePass.vignetteIntensity = vignette.intensity;\\n\\t\\t\\tcomposePass.vignetteColor.copy(vignette.color);\\n\\t\\t}\\n\\t\\tcomposePass.fringingEnabled = fringing.intensity > 0;\\n\\t\\tif (composePass.fringingEnabled) {\\n\\t\\t\\tcomposePass.fringingIntensity = fringing.intensity;\\n\\t\\t}\\n\\t\\tcomposePass.colorEnhanceEnabled = colorEnhance.enabled;\\n\\t\\tif (colorEnhance.enabled) {\\n\\t\\t\\tcomposePass.colorEnhanceShadows = colorEnhance.shadows;\\n\\t\\t\\tcomposePass.colorEnhanceHighlights = colorEnhance.highlights;\\n\\t\\t\\tcomposePass.colorEnhanceVibrance = colorEnhance.vibrance;\\n\\t\\t\\tcomposePass.colorEnhanceMidtones = colorEnhance.midtones;\\n\\t\\t\\tcomposePass.colorEnhanceDehaze = colorEnhance.dehaze;\\n\\t\\t}\\n\\t\\tcameraComponent.jitter = taa.enabled ? taa.jitter : 0;\\n\\t\\tcomposePass.debug = this.debug;\\n\\t\\tif (composePass.debug === \\\"ssao\\\" && options.ssaoType === SSAOTYPE_NONE) composePass.debug = null;\\n\\t\\tif (composePass.debug === \\\"vignette\\\" && !composePass.vignetteEnabled) composePass.debug = null;\\n\\t}\\n}\\n\\nconst tmpV1$1 = new Vec3();\\nconst rotation$3 = new Quat();\\nclass Pose {\\n\\tposition = new Vec3();\\n\\tangles = new Vec3();\\n\\tdistance = 0;\\n\\tpitchRange = new Vec2(-Infinity, Infinity);\\n\\tyawRange = new Vec2(-Infinity, Infinity);\\n\\txRange = new Vec2(-Infinity, Infinity);\\n\\tyRange = new Vec2(-Infinity, Infinity);\\n\\tzRange = new Vec2(-Infinity, Infinity);\\n\\tconstructor(position = Vec3.ZERO, angles = Vec3.ZERO, distance = 0) {\\n\\t\\tthis.set(position, angles, distance);\\n\\t}\\n\\tcopy(other) {\\n\\t\\treturn this.set(other.position, other.angles, other.distance);\\n\\t}\\n\\tclone() {\\n\\t\\treturn new Pose(this.position.clone(), this.angles.clone(), this.distance);\\n\\t}\\n\\tequalsApprox(other, epsilon = 1e-6) {\\n\\t\\treturn this.position.equalsApprox(other.position, epsilon) && this.angles.equalsApprox(other.angles, epsilon) && Math.abs(this.distance - other.distance) < epsilon;\\n\\t}\\n\\tlerp(lhs, rhs, alpha1, alpha2 = alpha1, alpha3 = alpha1) {\\n\\t\\tthis.position.lerp(lhs.position, rhs.position, alpha1);\\n\\t\\tthis.angles.x = math.lerpAngle(lhs.angles.x, rhs.angles.x, alpha2) % 360;\\n\\t\\tthis.angles.y = math.lerpAngle(lhs.angles.y, rhs.angles.y, alpha2) % 360;\\n\\t\\tthis.angles.z = math.lerpAngle(lhs.angles.z, rhs.angles.z, alpha2) % 360;\\n\\t\\tthis.distance = math.lerp(lhs.distance, rhs.distance, alpha3);\\n\\t\\treturn this;\\n\\t}\\n\\tmove(offset) {\\n\\t\\tthis.position.add(offset);\\n\\t\\tthis.position.x = math.clamp(this.position.x, this.xRange.x, this.xRange.y);\\n\\t\\tthis.position.y = math.clamp(this.position.y, this.yRange.x, this.yRange.y);\\n\\t\\tthis.position.z = math.clamp(this.position.z, this.zRange.x, this.zRange.y);\\n\\t\\treturn this;\\n\\t}\\n\\trotate(euler) {\\n\\t\\tthis.angles.add(euler);\\n\\t\\tthis.angles.x %= 360;\\n\\t\\tthis.angles.y %= 360;\\n\\t\\tthis.angles.z %= 360;\\n\\t\\tthis.angles.x = math.clamp(this.angles.x, this.pitchRange.x, this.pitchRange.y);\\n\\t\\tthis.angles.y = math.clamp(this.angles.y, this.yawRange.x, this.yawRange.y);\\n\\t\\treturn this;\\n\\t}\\n\\tset(position, angles, distance) {\\n\\t\\tthis.position.copy(position);\\n\\t\\tthis.angles.copy(angles);\\n\\t\\tthis.distance = distance;\\n\\t\\treturn this;\\n\\t}\\n\\tlook(from, to) {\\n\\t\\tthis.position.copy(from);\\n\\t\\tthis.distance = from.distance(to);\\n\\t\\tconst dir = tmpV1$1.sub2(to, from).normalize();\\n\\t\\tconst elev = Math.atan2(-dir.y, Math.sqrt(dir.x * dir.x + dir.z * dir.z)) * math.RAD_TO_DEG;\\n\\t\\tconst azim = Math.atan2(-dir.x, -dir.z) * math.RAD_TO_DEG;\\n\\t\\tthis.angles.set(-elev, azim, 0);\\n\\t\\treturn this;\\n\\t}\\n\\tgetFocus(out) {\\n\\t\\treturn rotation$3.setFromEulerAngles(this.angles).transformVector(Vec3.FORWARD, out).mulScalar(this.distance).add(this.position);\\n\\t}\\n}\\n\\nclass InputDelta {\\n\\t_value;\\n\\tconstructor(arg) {\\n\\t\\tif (Array.isArray(arg)) {\\n\\t\\t\\tthis._value = arg.slice();\\n\\t\\t} else {\\n\\t\\t\\tthis._value = new Array(+arg).fill(0);\\n\\t\\t}\\n\\t}\\n\\tadd(other) {\\n\\t\\tfor (let i = 0; i < this._value.length; i++) {\\n\\t\\t\\tthis._value[i] += other._value[i] || 0;\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\tappend(offsets) {\\n\\t\\tfor (let i = 0; i < this._value.length; i++) {\\n\\t\\t\\tthis._value[i] += offsets[i] || 0;\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\tcopy(other) {\\n\\t\\tfor (let i = 0; i < this._value.length; i++) {\\n\\t\\t\\tthis._value[i] = other._value[i] || 0;\\n\\t\\t}\\n\\t\\treturn this;\\n\\t}\\n\\tlength() {\\n\\t\\tlet sum = 0;\\n\\t\\tfor (const value of this._value) {\\n\\t\\t\\tsum += value * value;\\n\\t\\t}\\n\\t\\treturn Math.sqrt(sum);\\n\\t}\\n\\tread() {\\n\\t\\tconst value = this._value.slice();\\n\\t\\tthis._value.fill(0);\\n\\t\\treturn value;\\n\\t}\\n}\\nclass InputFrame {\\n\\tdeltas = {};\\n\\tconstructor(data) {\\n\\t\\tfor (const name in data) {\\n\\t\\t\\tthis.deltas[name] = new InputDelta(data[name]);\\n\\t\\t}\\n\\t}\\n\\tread() {\\n\\t\\tconst frame = {};\\n\\t\\tfor (const name in this.deltas) {\\n\\t\\t\\tframe[name] = this.deltas[name].read();\\n\\t\\t}\\n\\t\\treturn frame;\\n\\t}\\n}\\nclass InputSource extends InputFrame {\\n\\t_element = null;\\n\\t_events = new EventHandler();\\n\\ton(event, callback) {\\n\\t\\tthis._events.on(event, callback);\\n\\t}\\n\\toff(event, callback) {\\n\\t\\tthis._events.off(event, callback);\\n\\t}\\n\\tfire(event, ...args) {\\n\\t\\tthis._events.fire(event, ...args);\\n\\t}\\n\\tattach(element) {\\n\\t\\tif (this._element) {\\n\\t\\t\\tthis.detach();\\n\\t\\t}\\n\\t\\tthis._element = element;\\n\\t}\\n\\tdetach() {\\n\\t\\tif (!this._element) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._element = null;\\n\\t\\tthis.read();\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.detach();\\n\\t\\tthis._events.off();\\n\\t}\\n}\\nclass InputConsumer {\\n\\tupdate(frame, dt) {\\n\\t\\tframe.read();\\n\\t}\\n}\\nlet InputController$1 = class InputController extends InputConsumer {\\n\\t_pose = new Pose();\\n\\tattach(pose, smooth = true) {\\n\\t}\\n\\tdetach() {\\n\\t}\\n\\tupdate(frame, dt) {\\n\\t\\tsuper.update(frame, dt);\\n\\t\\treturn this._pose;\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.detach();\\n\\t}\\n};\\n\\nconst movementState = () => {\\n\\tconst state = /* @__PURE__ */ new Map();\\n\\treturn {\\n\\t\\tdown: (event) => {\\n\\t\\t\\tstate.set(event.pointerId, [event.screenX, event.screenY]);\\n\\t\\t},\\n\\t\\tmove: (event) => {\\n\\t\\t\\tif (!state.has(event.pointerId)) {\\n\\t\\t\\t\\treturn [0, 0];\\n\\t\\t\\t}\\n\\t\\t\\tconst prev = state.get(event.pointerId);\\n\\t\\t\\tconst mvX = event.screenX - prev[0];\\n\\t\\t\\tconst mvY = event.screenY - prev[1];\\n\\t\\t\\tprev[0] = event.screenX;\\n\\t\\t\\tprev[1] = event.screenY;\\n\\t\\t\\treturn [mvX, mvY];\\n\\t\\t},\\n\\t\\tup: (event) => {\\n\\t\\t\\tstate.delete(event.pointerId);\\n\\t\\t}\\n\\t};\\n};\\n\\nconst tmpVa = new Vec2();\\nclass MultiTouchSource extends InputSource {\\n\\t_movementState = movementState();\\n\\t_pointerEvents = /* @__PURE__ */ new Map();\\n\\t_pointerPos = new Vec2();\\n\\t_pinchDist = -1;\\n\\tconstructor() {\\n\\t\\tsuper({\\n\\t\\t\\ttouch: [0, 0],\\n\\t\\t\\tcount: [0],\\n\\t\\t\\tpinch: [0]\\n\\t\\t});\\n\\t\\tthis._onPointerDown = this._onPointerDown.bind(this);\\n\\t\\tthis._onPointerMove = this._onPointerMove.bind(this);\\n\\t\\tthis._onPointerUp = this._onPointerUp.bind(this);\\n\\t\\tthis._onContextMenu = this._onContextMenu.bind(this);\\n\\t}\\n\\t_onPointerDown(event) {\\n\\t\\tconst { pointerId, pointerType } = event;\\n\\t\\tthis._movementState.down(event);\\n\\t\\tif (pointerType !== \\\"touch\\\") {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._element?.setPointerCapture(pointerId);\\n\\t\\tthis._pointerEvents.set(pointerId, event);\\n\\t\\tthis.deltas.count.append([1]);\\n\\t\\tif (this._pointerEvents.size > 1) {\\n\\t\\t\\tthis._getMidPoint(this._pointerPos);\\n\\t\\t\\tthis._pinchDist = this._getPinchDist();\\n\\t\\t}\\n\\t}\\n\\t_onPointerMove(event) {\\n\\t\\tconst { pointerType, target, pointerId } = event;\\n\\t\\tconst [movementX, movementY] = this._movementState.move(event);\\n\\t\\tif (pointerType !== \\\"touch\\\") {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (target !== this._element) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._pointerEvents.size === 0) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._pointerEvents.set(pointerId, event);\\n\\t\\tif (this._pointerEvents.size > 1) {\\n\\t\\t\\tconst mid = this._getMidPoint(tmpVa);\\n\\t\\t\\tthis.deltas.touch.append([mid.x - this._pointerPos.x, mid.y - this._pointerPos.y]);\\n\\t\\t\\tthis._pointerPos.copy(mid);\\n\\t\\t\\tconst pinchDist = this._getPinchDist();\\n\\t\\t\\tif (this._pinchDist > 0) {\\n\\t\\t\\t\\tthis.deltas.pinch.append([this._pinchDist - pinchDist]);\\n\\t\\t\\t}\\n\\t\\t\\tthis._pinchDist = pinchDist;\\n\\t\\t} else {\\n\\t\\t\\tthis.deltas.touch.append([movementX, movementY]);\\n\\t\\t}\\n\\t}\\n\\t_onPointerUp(event) {\\n\\t\\tconst { pointerType, pointerId } = event;\\n\\t\\tthis._movementState.up(event);\\n\\t\\tif (pointerType !== \\\"touch\\\") {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._element?.releasePointerCapture(pointerId);\\n\\t\\tthis._pointerEvents.delete(pointerId);\\n\\t\\tthis.deltas.count.append([-1]);\\n\\t\\tif (this._pointerEvents.size < 2) {\\n\\t\\t\\tthis._pinchDist = -1;\\n\\t\\t}\\n\\t\\tthis._pointerPos.set(0, 0);\\n\\t}\\n\\t_onContextMenu(event) {\\n\\t\\tevent.preventDefault();\\n\\t}\\n\\t_getMidPoint(out) {\\n\\t\\tif (this._pointerEvents.size < 2) {\\n\\t\\t\\treturn out.set(0, 0);\\n\\t\\t}\\n\\t\\tconst [a, b] = this._pointerEvents.values();\\n\\t\\tconst dx = a.clientX - b.clientX;\\n\\t\\tconst dy = a.clientY - b.clientY;\\n\\t\\treturn out.set(b.clientX + dx * 0.5, b.clientY + dy * 0.5);\\n\\t}\\n\\t_getPinchDist() {\\n\\t\\tif (this._pointerEvents.size < 2) {\\n\\t\\t\\treturn 0;\\n\\t\\t}\\n\\t\\tconst [a, b] = this._pointerEvents.values();\\n\\t\\tconst dx = a.clientX - b.clientX;\\n\\t\\tconst dy = a.clientY - b.clientY;\\n\\t\\treturn Math.sqrt(dx * dx + dy * dy);\\n\\t}\\n\\tattach(element) {\\n\\t\\tsuper.attach(element);\\n\\t\\tthis._element = element;\\n\\t\\tthis._element.addEventListener(\\\"pointerdown\\\", this._onPointerDown);\\n\\t\\tthis._element.addEventListener(\\\"pointermove\\\", this._onPointerMove);\\n\\t\\tthis._element.addEventListener(\\\"pointerup\\\", this._onPointerUp);\\n\\t\\tthis._element.addEventListener(\\\"pointercancel\\\", this._onPointerUp);\\n\\t\\tthis._element.addEventListener(\\\"contextmenu\\\", this._onContextMenu);\\n\\t}\\n\\tdetach() {\\n\\t\\tif (!this._element) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._element.removeEventListener(\\\"pointerdown\\\", this._onPointerDown);\\n\\t\\tthis._element.removeEventListener(\\\"pointermove\\\", this._onPointerMove);\\n\\t\\tthis._element.removeEventListener(\\\"pointerup\\\", this._onPointerUp);\\n\\t\\tthis._element.removeEventListener(\\\"pointercancel\\\", this._onPointerUp);\\n\\t\\tthis._element.removeEventListener(\\\"contextmenu\\\", this._onContextMenu);\\n\\t\\tthis._pointerEvents.clear();\\n\\t\\tsuper.detach();\\n\\t}\\n}\\n\\nconst PASSIVE = { passive: false };\\nconst KEY_CODES = {\\n\\tA: 0,\\n\\tB: 1,\\n\\tC: 2,\\n\\tD: 3,\\n\\tE: 4,\\n\\tF: 5,\\n\\tG: 6,\\n\\tH: 7,\\n\\tI: 8,\\n\\tJ: 9,\\n\\tK: 10,\\n\\tL: 11,\\n\\tM: 12,\\n\\tN: 13,\\n\\tO: 14,\\n\\tP: 15,\\n\\tQ: 16,\\n\\tR: 17,\\n\\tS: 18,\\n\\tT: 19,\\n\\tU: 20,\\n\\tV: 21,\\n\\tW: 22,\\n\\tX: 23,\\n\\tY: 24,\\n\\tZ: 25,\\n\\t\\\"0\\\": 26,\\n\\t\\\"1\\\": 27,\\n\\t\\\"2\\\": 28,\\n\\t\\\"3\\\": 29,\\n\\t\\\"4\\\": 30,\\n\\t\\\"5\\\": 31,\\n\\t\\\"6\\\": 32,\\n\\t\\\"7\\\": 33,\\n\\t\\\"8\\\": 34,\\n\\t\\\"9\\\": 35,\\n\\tUP: 36,\\n\\tDOWN: 37,\\n\\tLEFT: 38,\\n\\tRIGHT: 39,\\n\\tSPACE: 40,\\n\\tSHIFT: 41,\\n\\tCTRL: 42\\n};\\nconst KEY_COUNT = Object.keys(KEY_CODES).length;\\nconst array = Array(KEY_COUNT).fill(0);\\nclass KeyboardMouseSource extends InputSource {\\n\\t_movementState = movementState();\\n\\tstatic keyCode = KEY_CODES;\\n\\t_pointerId = -1;\\n\\t_pointerLock;\\n\\t_keyMap = /* @__PURE__ */ new Map();\\n\\t_keyPrev = Array(KEY_COUNT).fill(0);\\n\\t_keyNow = Array(KEY_COUNT).fill(0);\\n\\t_button = Array(3).fill(0);\\n\\tconstructor({ pointerLock = false } = {}) {\\n\\t\\tsuper({\\n\\t\\t\\tkey: Array(KEY_COUNT).fill(0),\\n\\t\\t\\tbutton: [0, 0, 0],\\n\\t\\t\\tmouse: [0, 0],\\n\\t\\t\\twheel: [0]\\n\\t\\t});\\n\\t\\tthis._pointerLock = pointerLock ?? false;\\n\\t\\tconst { keyCode } = KeyboardMouseSource;\\n\\t\\tfor (let i = 0; i < 26; i++) {\\n\\t\\t\\tconst code = `Key${String.fromCharCode(\\\"A\\\".charCodeAt(0) + i)}`;\\n\\t\\t\\tthis._keyMap.set(code, keyCode.A + i);\\n\\t\\t}\\n\\t\\tfor (let i = 0; i < 10; i++) {\\n\\t\\t\\tconst code = `Digit${i}`;\\n\\t\\t\\tthis._keyMap.set(code, keyCode[\\\"0\\\"] + i);\\n\\t\\t}\\n\\t\\tthis._keyMap.set(\\\"ArrowUp\\\", keyCode.UP);\\n\\t\\tthis._keyMap.set(\\\"ArrowDown\\\", keyCode.DOWN);\\n\\t\\tthis._keyMap.set(\\\"ArrowLeft\\\", keyCode.LEFT);\\n\\t\\tthis._keyMap.set(\\\"ArrowRight\\\", keyCode.RIGHT);\\n\\t\\tthis._keyMap.set(\\\"Space\\\", keyCode.SPACE);\\n\\t\\tthis._keyMap.set(\\\"ShiftLeft\\\", keyCode.SHIFT);\\n\\t\\tthis._keyMap.set(\\\"ShiftRight\\\", keyCode.SHIFT);\\n\\t\\tthis._keyMap.set(\\\"ControlLeft\\\", keyCode.CTRL);\\n\\t\\tthis._keyMap.set(\\\"ControlRight\\\", keyCode.CTRL);\\n\\t\\tthis._onWheel = this._onWheel.bind(this);\\n\\t\\tthis._onPointerDown = this._onPointerDown.bind(this);\\n\\t\\tthis._onPointerMove = this._onPointerMove.bind(this);\\n\\t\\tthis._onPointerUp = this._onPointerUp.bind(this);\\n\\t\\tthis._onContextMenu = this._onContextMenu.bind(this);\\n\\t\\tthis._onKeyDown = this._onKeyDown.bind(this);\\n\\t\\tthis._onKeyUp = this._onKeyUp.bind(this);\\n\\t}\\n\\t_onWheel(event) {\\n\\t\\tevent.preventDefault();\\n\\t\\tthis.deltas.wheel.append([event.deltaY]);\\n\\t}\\n\\t_onPointerDown(event) {\\n\\t\\tthis._movementState.down(event);\\n\\t\\tif (event.pointerType !== \\\"mouse\\\") {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._pointerLock) {\\n\\t\\t\\tif (document.pointerLockElement !== this._element) {\\n\\t\\t\\t\\tthis._element?.requestPointerLock();\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tthis._element?.setPointerCapture(event.pointerId);\\n\\t\\t}\\n\\t\\tthis._clearButtons();\\n\\t\\tthis._button[event.button] = 1;\\n\\t\\tthis.deltas.button.append(this._button);\\n\\t\\tif (this._pointerId !== -1) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._pointerId = event.pointerId;\\n\\t}\\n\\t_onPointerMove(event) {\\n\\t\\tconst [movementX, movementY] = this._pointerLock && document.pointerLockElement === this._element ? [event.movementX, event.movementY] : this._movementState.move(event);\\n\\t\\tif (event.pointerType !== \\\"mouse\\\") {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (event.target !== this._element) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (this._pointerLock) {\\n\\t\\t\\tif (document.pointerLockElement !== this._element) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\tif (this._pointerId !== event.pointerId) {\\n\\t\\t\\t\\treturn;\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tthis.deltas.mouse.append([movementX, movementY]);\\n\\t}\\n\\t_onPointerUp(event) {\\n\\t\\tthis._movementState.up(event);\\n\\t\\tif (event.pointerType !== \\\"mouse\\\") {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!this._pointerLock) {\\n\\t\\t\\tthis._element?.releasePointerCapture(event.pointerId);\\n\\t\\t}\\n\\t\\tthis._clearButtons();\\n\\t\\tthis.deltas.button.append(this._button);\\n\\t\\tif (this._pointerId !== event.pointerId) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._pointerId = -1;\\n\\t}\\n\\t_onContextMenu(event) {\\n\\t\\tevent.preventDefault();\\n\\t}\\n\\t_onKeyDown(event) {\\n\\t\\tif (this._pointerLock && document.pointerLockElement !== this._element) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tevent.stopPropagation();\\n\\t\\tthis._setKey(event.code, 1);\\n\\t}\\n\\t_onKeyUp(event) {\\n\\t\\tevent.stopPropagation();\\n\\t\\tthis._setKey(event.code, 0);\\n\\t}\\n\\t_clearButtons() {\\n\\t\\tfor (let i = 0; i < this._button.length; i++) {\\n\\t\\t\\tif (this._button[i] === 1) {\\n\\t\\t\\t\\tthis._button[i] = -1;\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tthis._button[i] = 0;\\n\\t\\t}\\n\\t}\\n\\t_setKey(code, value) {\\n\\t\\tif (!this._keyMap.has(code)) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._keyNow[this._keyMap.get(code) ?? 0] = value;\\n\\t}\\n\\tattach(element) {\\n\\t\\tsuper.attach(element);\\n\\t\\tthis._element = element;\\n\\t\\tthis._element.addEventListener(\\\"wheel\\\", this._onWheel, PASSIVE);\\n\\t\\tthis._element.addEventListener(\\\"pointerdown\\\", this._onPointerDown);\\n\\t\\tthis._element.addEventListener(\\\"pointermove\\\", this._onPointerMove);\\n\\t\\tthis._element.addEventListener(\\\"pointerup\\\", this._onPointerUp);\\n\\t\\tthis._element.addEventListener(\\\"pointercancel\\\", this._onPointerUp);\\n\\t\\tthis._element.addEventListener(\\\"pointerleave\\\", this._onPointerUp);\\n\\t\\tthis._element.addEventListener(\\\"lostpointercapture\\\", this._onPointerUp);\\n\\t\\tthis._element.addEventListener(\\\"contextmenu\\\", this._onContextMenu);\\n\\t\\twindow.addEventListener(\\\"keydown\\\", this._onKeyDown, false);\\n\\t\\twindow.addEventListener(\\\"keyup\\\", this._onKeyUp, false);\\n\\t}\\n\\tdetach() {\\n\\t\\tif (!this._element) {\\n\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tthis._element.removeEventListener(\\\"wheel\\\", this._onWheel, PASSIVE);\\n\\t\\tthis._element.removeEventListener(\\\"pointerdown\\\", this._onPointerDown);\\n\\t\\tthis._element.removeEventListener(\\\"pointermove\\\", this._onPointerMove);\\n\\t\\tthis._element.removeEventListener(\\\"pointerup\\\", this._onPointerUp);\\n\\t\\tthis._element.removeEventListener(\\\"pointercancel\\\", this._onPointerUp);\\n\\t\\tthis._element.removeEventListener(\\\"pointerleave\\\", this._onPointerUp);\\n\\t\\tthis._element.removeEventListener(\\\"lostpointercapture\\\", this._onPointerUp);\\n\\t\\tthis._element.removeEventListener(\\\"contextmenu\\\", this._onContextMenu);\\n\\t\\twindow.removeEventListener(\\\"keydown\\\", this._onKeyDown, false);\\n\\t\\twindow.removeEventListener(\\\"keyup\\\", this._onKeyUp, false);\\n\\t\\tthis._keyNow.fill(0);\\n\\t\\tthis._keyPrev.fill(0);\\n\\t\\tsuper.detach();\\n\\t}\\n\\tread() {\\n\\t\\tfor (let i = 0; i < array.length; i++) {\\n\\t\\t\\tarray[i] = this._keyNow[i] - this._keyPrev[i];\\n\\t\\t\\tthis._keyPrev[i] = this._keyNow[i];\\n\\t\\t}\\n\\t\\tthis.deltas.key.append(array);\\n\\t\\treturn super.read();\\n\\t}\\n}\\n\\nconst BUTTON_CODES = {\\n\\tA: 0,\\n\\tB: 1,\\n\\tX: 2,\\n\\tY: 3,\\n\\tLB: 4,\\n\\tRB: 5,\\n\\tLT: 6,\\n\\tRT: 7,\\n\\tSELECT: 8,\\n\\tSTART: 9,\\n\\tLEFT_STICK: 10,\\n\\tRIGHT_STICK: 11\\n};\\nconst BUTTON_COUNT = Object.keys(BUTTON_CODES).length;\\nclass GamepadSource extends InputSource {\\n\\tstatic buttonCode = BUTTON_CODES;\\n\\t_buttonPrev = Array(BUTTON_COUNT).fill(0);\\n\\tconstructor() {\\n\\t\\tsuper({\\n\\t\\t\\tbuttons: Array(BUTTON_COUNT).fill(0),\\n\\t\\t\\tleftStick: [0, 0],\\n\\t\\t\\trightStick: [0, 0]\\n\\t\\t});\\n\\t}\\n\\tread() {\\n\\t\\tconst gamepads = navigator.getGamepads();\\n\\t\\tfor (let i = 0; i < gamepads.length; i++) {\\n\\t\\t\\tconst gp = gamepads[i];\\n\\t\\t\\tif (!gp) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tif (gp.mapping !== \\\"standard\\\") {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tif (gp.axes.length < 4) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tif (gp.buttons.length < BUTTON_COUNT) {\\n\\t\\t\\t\\tcontinue;\\n\\t\\t\\t}\\n\\t\\t\\tconst { buttons, axes } = gp;\\n\\t\\t\\tfor (let j = 0; j < this._buttonPrev.length; j++) {\\n\\t\\t\\t\\tconst state = +buttons[j].pressed;\\n\\t\\t\\t\\tthis.deltas.buttons[j] = state - this._buttonPrev[j];\\n\\t\\t\\t\\tthis._buttonPrev[j] = state;\\n\\t\\t\\t}\\n\\t\\t\\tthis.deltas.leftStick.append([axes[0], axes[1]]);\\n\\t\\t\\tthis.deltas.rightStick.append([axes[2], axes[3]]);\\n\\t\\t}\\n\\t\\treturn super.read();\\n\\t}\\n}\\n\\nconst damp$1 = (damping, dt) => 1 - Math.pow(damping, dt * 1e3);\\n\\nconst dir = new Vec3();\\nconst offset$2 = new Vec3();\\nconst angles = new Vec3();\\nconst rotation$2 = new Quat();\\nlet OrbitController$1 = class OrbitController extends InputController$1 {\\n\\t_targetRootPose = new Pose();\\n\\t_rootPose = new Pose();\\n\\t_targetChildPose = new Pose();\\n\\t_childPose = new Pose();\\n\\trotateDamping = 0.98;\\n\\tmoveDamping = 0.98;\\n\\tzoomDamping = 0.98;\\n\\tset pitchRange(range) {\\n\\t\\tthis._targetRootPose.pitchRange.copy(range);\\n\\t\\tthis._rootPose.copy(this._targetRootPose.rotate(Vec3.ZERO));\\n\\t}\\n\\tget pitchRange() {\\n\\t\\treturn this._targetRootPose.pitchRange;\\n\\t}\\n\\tset yawRange(range) {\\n\\t\\tthis._targetRootPose.yawRange.copy(range);\\n\\t\\tthis._rootPose.copy(this._targetRootPose.rotate(Vec3.ZERO));\\n\\t}\\n\\tget yawRange() {\\n\\t\\treturn this._targetRootPose.yawRange;\\n\\t}\\n\\tset zoomRange(range) {\\n\\t\\tthis._targetChildPose.zRange.copy(range);\\n\\t\\tthis._childPose.copy(this._targetChildPose.move(Vec3.ZERO));\\n\\t}\\n\\tget zoomRange() {\\n\\t\\treturn this._targetRootPose.zRange;\\n\\t}\\n\\tattach(pose, smooth = true) {\\n\\t\\tthis._targetRootPose.set(pose.getFocus(dir), pose.angles, 0);\\n\\t\\tthis._targetChildPose.position.set(0, 0, pose.distance);\\n\\t\\tif (!smooth) {\\n\\t\\t\\tthis._rootPose.copy(this._targetRootPose);\\n\\t\\t\\tthis._childPose.copy(this._targetChildPose);\\n\\t\\t}\\n\\t}\\n\\tdetach() {\\n\\t\\tthis._targetRootPose.copy(this._rootPose);\\n\\t\\tthis._targetChildPose.copy(this._childPose);\\n\\t}\\n\\tupdate(frame, dt) {\\n\\t\\tconst { move, rotate } = frame.read();\\n\\t\\toffset$2.set(move[0], move[1], 0);\\n\\t\\trotation$2.setFromEulerAngles(this._rootPose.angles).transformVector(offset$2, offset$2);\\n\\t\\tthis._targetRootPose.move(offset$2);\\n\\t\\tconst { z: dist } = this._targetChildPose.position;\\n\\t\\tthis._targetChildPose.move(offset$2.set(0, 0, dist * (1 + move[2]) - dist));\\n\\t\\tthis._targetRootPose.rotate(angles.set(-rotate[1], -rotate[0], 0));\\n\\t\\tthis._rootPose.lerp(\\n\\t\\t\\tthis._rootPose,\\n\\t\\t\\tthis._targetRootPose,\\n\\t\\t\\tdamp$1(this.moveDamping, dt),\\n\\t\\t\\tdamp$1(this.rotateDamping, dt),\\n\\t\\t\\t1\\n\\t\\t);\\n\\t\\tthis._childPose.lerp(\\n\\t\\t\\tthis._childPose,\\n\\t\\t\\tthis._targetChildPose,\\n\\t\\t\\tdamp$1(this.zoomDamping, dt),\\n\\t\\t\\t1,\\n\\t\\t\\t1\\n\\t\\t);\\n\\t\\trotation$2.setFromEulerAngles(this._rootPose.angles).transformVector(this._childPose.position, offset$2).add(this._rootPose.position);\\n\\t\\treturn this._pose.set(offset$2, this._rootPose.angles, this._childPose.position.z);\\n\\t}\\n\\tdestroy() {\\n\\t\\tthis.detach();\\n\\t}\\n};\\n\\nclass App extends AppBase {\\n    constructor(canvas, options) {\\n        super(canvas);\\n        const appOptions = new AppOptions();\\n        appOptions.graphicsDevice = options.graphicsDevice;\\n        appOptions.componentSystems = [\\n            CameraComponentSystem,\\n            LightComponentSystem,\\n            RenderComponentSystem,\\n            GSplatComponentSystem,\\n            ScriptComponentSystem\\n        ];\\n        appOptions.resourceHandlers = [\\n            ContainerHandler,\\n            TextureHandler,\\n            GSplatHandler,\\n            BinaryHandler\\n        ];\\n        appOptions.mouse = options.mouse;\\n        appOptions.touch = options.touch;\\n        appOptions.keyboard = options.keyboard;\\n        appOptions.xr = XrManager;\\n        this.init(appOptions);\\n    }\\n}\\n\\n/**\\n * Fallback voxel cell size for mesh collision, which doesn't carry the carve\\n * metadata itself. Assumes the mesh was generated from a voxel grid at this\\n * resolution (matches the default `splat-transform --voxel-carve` output).\\n */\\nconst DEFAULT_VOXEL_RESOLUTION = 0.05;\\n/** Minimum penetration depth to report (avoids floating-point noise) */\\nconst PENETRATION_EPSILON = 1e-4;\\n/** Maximum iterations for iterative sphere/capsule resolution */\\nconst MAX_RESOLVE_ITERATIONS = 4;\\n/**\\n * Iteratively resolve penetrations by repeatedly querying the deepest overlap,\\n * projecting against previous constraint normals, and accumulating the push-out.\\n * Shared by both MeshCollision and VoxelCollision for sphere and capsule queries.\\n *\\n * @param cx - Initial query center X.\\n * @param cy - Initial query center Y.\\n * @param cz - Initial query center Z.\\n * @param findPenetration - Callback that finds the deepest penetration from (cx, cy, cz)\\n * and writes the push vector into `scratch`. Returns true if a penetration was found.\\n * @param constraintNormals - Pre-allocated array of at least 3 normal vectors (mutated).\\n * @param scratch - Pre-allocated PushOut for the callback to write into (mutated).\\n * @param out - Receives the total accumulated push-out vector on success.\\n * @returns True if a meaningful push-out was computed.\\n */\\nfunction resolveIterative(cx, cy, cz, findPenetration, constraintNormals, scratch, out) {\\n    let resolvedX = cx;\\n    let resolvedY = cy;\\n    let resolvedZ = cz;\\n    let totalPushX = 0;\\n    let totalPushY = 0;\\n    let totalPushZ = 0;\\n    let hadCollision = false;\\n    let numNormals = 0;\\n    for (let iter = 0; iter < MAX_RESOLVE_ITERATIONS; iter++) {\\n        if (!findPenetration(resolvedX, resolvedY, resolvedZ, scratch))\\n            break;\\n        hadCollision = true;\\n        let px = scratch.x;\\n        let py = scratch.y;\\n        let pz = scratch.z;\\n        for (let i = 0; i < numNormals; i++) {\\n            const n = constraintNormals[i];\\n            const dot = px * n.x + py * n.y + pz * n.z;\\n            if (dot < 0) {\\n                px -= dot * n.x;\\n                py -= dot * n.y;\\n                pz -= dot * n.z;\\n            }\\n        }\\n        const len = Math.sqrt(scratch.x * scratch.x + scratch.y * scratch.y + scratch.z * scratch.z);\\n        if (len > PENETRATION_EPSILON && numNormals < 3) {\\n            const invLen = 1.0 / len;\\n            const n = constraintNormals[numNormals];\\n            n.x = scratch.x * invLen;\\n            n.y = scratch.y * invLen;\\n            n.z = scratch.z * invLen;\\n            numNormals++;\\n        }\\n        resolvedX += px;\\n        resolvedY += py;\\n        resolvedZ += pz;\\n        totalPushX += px;\\n        totalPushY += py;\\n        totalPushZ += pz;\\n    }\\n    const totalPushSq = totalPushX * totalPushX + totalPushY * totalPushY + totalPushZ * totalPushZ;\\n    const hasSignificantPush = hadCollision && totalPushSq > PENETRATION_EPSILON * PENETRATION_EPSILON;\\n    if (hasSignificantPush) {\\n        out.x = totalPushX;\\n        out.y = totalPushY;\\n        out.z = totalPushZ;\\n    }\\n    return hasSignificantPush;\\n}\\n\\n// ---- BVH construction ----\\nconst MAX_LEAF_TRIS = 4;\\nfunction computeTriangleBounds(tris, idx, out) {\\n    const i = tris.indices[idx];\\n    out.minX = Math.min(tris.v0x[i], tris.v1x[i], tris.v2x[i]);\\n    out.minY = Math.min(tris.v0y[i], tris.v1y[i], tris.v2y[i]);\\n    out.minZ = Math.min(tris.v0z[i], tris.v1z[i], tris.v2z[i]);\\n    out.maxX = Math.max(tris.v0x[i], tris.v1x[i], tris.v2x[i]);\\n    out.maxY = Math.max(tris.v0y[i], tris.v1y[i], tris.v2y[i]);\\n    out.maxZ = Math.max(tris.v0z[i], tris.v1z[i], tris.v2z[i]);\\n}\\nfunction buildBVH(tris, start, count) {\\n    const bounds = { minX: Infinity, minY: Infinity, minZ: Infinity, maxX: -Infinity, maxY: -Infinity, maxZ: -Infinity };\\n    const tb = { minX: 0, minY: 0, minZ: 0, maxX: 0, maxY: 0, maxZ: 0 };\\n    for (let i = start; i < start + count; i++) {\\n        computeTriangleBounds(tris, i, tb);\\n        bounds.minX = Math.min(bounds.minX, tb.minX);\\n        bounds.minY = Math.min(bounds.minY, tb.minY);\\n        bounds.minZ = Math.min(bounds.minZ, tb.minZ);\\n        bounds.maxX = Math.max(bounds.maxX, tb.maxX);\\n        bounds.maxY = Math.max(bounds.maxY, tb.maxY);\\n        bounds.maxZ = Math.max(bounds.maxZ, tb.maxZ);\\n    }\\n    if (count <= MAX_LEAF_TRIS) {\\n        return {\\n            ...bounds,\\n            left: null,\\n            right: null,\\n            triStart: start,\\n            triCount: count\\n        };\\n    }\\n    // Split along longest axis using midpoint\\n    const dx = bounds.maxX - bounds.minX;\\n    const dy = bounds.maxY - bounds.minY;\\n    const dz = bounds.maxZ - bounds.minZ;\\n    const axis = dx >= dy && dx >= dz ? 0 : (dy >= dz ? 1 : 2);\\n    const mid = axis === 0 ? (bounds.minX + bounds.maxX) * 0.5 :\\n        axis === 1 ? (bounds.minY + bounds.maxY) * 0.5 :\\n            (bounds.minZ + bounds.maxZ) * 0.5;\\n    // Partition indices[start..start+count) around the midpoint\\n    let left = start;\\n    let right = start + count - 1;\\n    while (left <= right) {\\n        const i = tris.indices[left];\\n        const cx = axis === 0 ? (tris.v0x[i] + tris.v1x[i] + tris.v2x[i]) / 3 :\\n            axis === 1 ? (tris.v0y[i] + tris.v1y[i] + tris.v2y[i]) / 3 :\\n                (tris.v0z[i] + tris.v1z[i] + tris.v2z[i]) / 3;\\n        if (cx < mid) {\\n            left++;\\n        }\\n        else {\\n            const tmp = tris.indices[left];\\n            tris.indices[left] = tris.indices[right];\\n            tris.indices[right] = tmp;\\n            right--;\\n        }\\n    }\\n    // Fall back to median split when midpoint produces a degenerate partition\\n    let leftCount = left - start;\\n    if (leftCount === 0 || leftCount === count)\\n        leftCount = count >> 1;\\n    return {\\n        ...bounds,\\n        left: buildBVH(tris, start, leftCount),\\n        right: buildBVH(tris, start + leftCount, count - leftCount),\\n        triStart: 0,\\n        triCount: 0\\n    };\\n}\\n// ---- Ray-AABB intersection ----\\nfunction rayAABB(ox, oy, oz, idx, idy, idz, minX, minY, minZ, maxX, maxY, maxZ, maxDist) {\\n    const t1x = (minX - ox) * idx;\\n    const t2x = (maxX - ox) * idx;\\n    const t1y = (minY - oy) * idy;\\n    const t2y = (maxY - oy) * idy;\\n    const t1z = (minZ - oz) * idz;\\n    const t2z = (maxZ - oz) * idz;\\n    const tmin = Math.max(Math.min(t1x, t2x), Math.min(t1y, t2y), Math.min(t1z, t2z));\\n    const tmax = Math.min(Math.max(t1x, t2x), Math.max(t1y, t2y), Math.max(t1z, t2z));\\n    if (tmax < 0 || tmin > tmax || tmin > maxDist)\\n        return -1;\\n    return tmin >= 0 ? tmin : 0;\\n}\\n// ---- Moller-Trumbore ray-triangle ----\\nfunction rayTriangle(ox, oy, oz, dx, dy, dz, ax, ay, az, bx, by, bz, cx, cy, cz) {\\n    const e1x = bx - ax, e1y = by - ay, e1z = bz - az;\\n    const e2x = cx - ax, e2y = cy - ay, e2z = cz - az;\\n    const px = dy * e2z - dz * e2y;\\n    const py = dz * e2x - dx * e2z;\\n    const pz = dx * e2y - dy * e2x;\\n    const det = e1x * px + e1y * py + e1z * pz;\\n    if (Math.abs(det) < 1e-10)\\n        return -1;\\n    const invDet = 1.0 / det;\\n    const tx = ox - ax, ty = oy - ay, tz = oz - az;\\n    const u = (tx * px + ty * py + tz * pz) * invDet;\\n    if (u < 0 || u > 1)\\n        return -1;\\n    const qx = ty * e1z - tz * e1y;\\n    const qy = tz * e1x - tx * e1z;\\n    const qz = tx * e1y - ty * e1x;\\n    const v = (dx * qx + dy * qy + dz * qz) * invDet;\\n    if (v < 0 || u + v > 1)\\n        return -1;\\n    const t = (e2x * qx + e2y * qy + e2z * qz) * invDet;\\n    return t >= 0 ? t : -1;\\n}\\n// ---- Sphere-AABB overlap test ----\\nfunction sphereAABBOverlap(cx, cy, cz, radius, minX, minY, minZ, maxX, maxY, maxZ) {\\n    const nx = Math.max(minX, Math.min(cx, maxX));\\n    const ny = Math.max(minY, Math.min(cy, maxY));\\n    const nz = Math.max(minZ, Math.min(cz, maxZ));\\n    const dx = cx - nx, dy = cy - ny, dz = cz - nz;\\n    return dx * dx + dy * dy + dz * dz <= radius * radius;\\n}\\n// ---- Closest point on triangle to a point ----\\nfunction closestPointOnTriangle(px, py, pz, ax, ay, az, bx, by, bz, cx, cy, cz, out) {\\n    const abx = bx - ax, aby = by - ay, abz = bz - az;\\n    const acx = cx - ax, acy = cy - ay, acz = cz - az;\\n    const apx = px - ax, apy = py - ay, apz = pz - az;\\n    const d1 = abx * apx + aby * apy + abz * apz;\\n    const d2 = acx * apx + acy * apy + acz * apz;\\n    if (d1 <= 0 && d2 <= 0) {\\n        out.x = ax;\\n        out.y = ay;\\n        out.z = az;\\n        return;\\n    }\\n    const bpx = px - bx, bpy = py - by, bpz = pz - bz;\\n    const d3 = abx * bpx + aby * bpy + abz * bpz;\\n    const d4 = acx * bpx + acy * bpy + acz * bpz;\\n    if (d3 >= 0 && d4 <= d3) {\\n        out.x = bx;\\n        out.y = by;\\n        out.z = bz;\\n        return;\\n    }\\n    const vc = d1 * d4 - d3 * d2;\\n    if (vc <= 0 && d1 >= 0 && d3 <= 0) {\\n        const v = d1 / (d1 - d3);\\n        out.x = ax + abx * v;\\n        out.y = ay + aby * v;\\n        out.z = az + abz * v;\\n        return;\\n    }\\n    const cpx = px - cx, cpy = py - cy, cpz = pz - cz;\\n    const d5 = abx * cpx + aby * cpy + abz * cpz;\\n    const d6 = acx * cpx + acy * cpy + acz * cpz;\\n    if (d6 >= 0 && d5 <= d6) {\\n        out.x = cx;\\n        out.y = cy;\\n        out.z = cz;\\n        return;\\n    }\\n    const vb = d5 * d2 - d1 * d6;\\n    if (vb <= 0 && d2 >= 0 && d6 <= 0) {\\n        const w = d2 / (d2 - d6);\\n        out.x = ax + acx * w;\\n        out.y = ay + acy * w;\\n        out.z = az + acz * w;\\n        return;\\n    }\\n    const va = d3 * d6 - d5 * d4;\\n    if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0) {\\n        const w = (d4 - d3) / ((d4 - d3) + (d5 - d6));\\n        out.x = bx + (cx - bx) * w;\\n        out.y = by + (cy - by) * w;\\n        out.z = bz + (cz - bz) * w;\\n        return;\\n    }\\n    const denom = 1.0 / (va + vb + vc);\\n    const v = vb * denom;\\n    const w = vc * denom;\\n    out.x = ax + abx * v + acx * w;\\n    out.y = ay + aby * v + acy * w;\\n    out.z = az + abz * v + acz * w;\\n}\\n// ---- Closest point on a line segment to a point ----\\nfunction closestPointOnSegment(px, py, pz, ax, ay, az, bx, by, bz, out) {\\n    const abx = bx - ax, aby = by - ay, abz = bz - az;\\n    const lenSq = abx * abx + aby * aby + abz * abz;\\n    if (lenSq < 1e-20) {\\n        out.x = ax;\\n        out.y = ay;\\n        out.z = az;\\n        return;\\n    }\\n    const apx = px - ax, apy = py - ay, apz = pz - az;\\n    let t = (apx * abx + apy * aby + apz * abz) / lenSq;\\n    t = Math.max(0, Math.min(1, t));\\n    out.x = ax + abx * t;\\n    out.y = ay + aby * t;\\n    out.z = az + abz * t;\\n}\\n// ---- Closest point on segment to triangle (returns distance squared) ----\\nconst _segPt = { x: 0, y: 0, z: 0 };\\nconst _triPt = { x: 0, y: 0, z: 0 };\\nconst _tmpSegPt = { x: 0, y: 0, z: 0 };\\nconst _tmpTriPt = { x: 0, y: 0, z: 0 };\\n// Approximate closest points between a line segment and a triangle.\\n// Uses discrete sampling (6 points along the segment) followed by one\\n// refinement pass. Sufficient for vertical capsule collision (walk/fly mode)\\n// where the segment is always Y-aligned and triangles are near-axis-aligned.\\nfunction closestSegmentTriangle(s0x, s0y, s0z, s1x, s1y, s1z, ax, ay, az, bx, by, bz, cx, cy, cz, outSeg, outTri) {\\n    const SAMPLES = 5;\\n    let bestDistSq = Infinity;\\n    for (let i = 0; i <= SAMPLES; i++) {\\n        const t = i / SAMPLES;\\n        const sx = s0x + (s1x - s0x) * t;\\n        const sy = s0y + (s1y - s0y) * t;\\n        const sz = s0z + (s1z - s0z) * t;\\n        closestPointOnTriangle(sx, sy, sz, ax, ay, az, bx, by, bz, cx, cy, cz, _tmpTriPt);\\n        const dx = sx - _tmpTriPt.x, dy = sy - _tmpTriPt.y, dz = sz - _tmpTriPt.z;\\n        const distSq = dx * dx + dy * dy + dz * dz;\\n        if (distSq < bestDistSq) {\\n            bestDistSq = distSq;\\n            _segPt.x = sx;\\n            _segPt.y = sy;\\n            _segPt.z = sz;\\n            _triPt.x = _tmpTriPt.x;\\n            _triPt.y = _tmpTriPt.y;\\n            _triPt.z = _tmpTriPt.z;\\n        }\\n    }\\n    // Refine: find closest point on segment to the best triangle point, then re-test\\n    closestPointOnSegment(_triPt.x, _triPt.y, _triPt.z, s0x, s0y, s0z, s1x, s1y, s1z, _tmpSegPt);\\n    closestPointOnTriangle(_tmpSegPt.x, _tmpSegPt.y, _tmpSegPt.z, ax, ay, az, bx, by, bz, cx, cy, cz, _tmpTriPt);\\n    const dx = _tmpSegPt.x - _tmpTriPt.x;\\n    const dy = _tmpSegPt.y - _tmpTriPt.y;\\n    const dz = _tmpSegPt.z - _tmpTriPt.z;\\n    const distSq = dx * dx + dy * dy + dz * dz;\\n    if (distSq < bestDistSq) {\\n        bestDistSq = distSq;\\n        _segPt.x = _tmpSegPt.x;\\n        _segPt.y = _tmpSegPt.y;\\n        _segPt.z = _tmpSegPt.z;\\n        _triPt.x = _tmpTriPt.x;\\n        _triPt.y = _tmpTriPt.y;\\n        _triPt.z = _tmpTriPt.z;\\n    }\\n    outSeg.x = _segPt.x;\\n    outSeg.y = _segPt.y;\\n    outSeg.z = _segPt.z;\\n    outTri.x = _triPt.x;\\n    outTri.y = _triPt.y;\\n    outTri.z = _triPt.z;\\n    return bestDistSq;\\n}\\n// ---- MeshCollision ----\\nconst _closest = { x: 0, y: 0, z: 0 };\\nconst _segClosest = { x: 0, y: 0, z: 0 };\\nconst _triClosest = { x: 0, y: 0, z: 0 };\\nclass MeshCollision {\\n    /**\\n     * Assumed voxel resolution of the source carve that produced this mesh.\\n     * The mesh itself doesn't carry this metadata, so we fall back to the\\n     * default; can be overridden post-construction if a loader knows better.\\n     */\\n    voxelResolution = DEFAULT_VOXEL_RESOLUTION;\\n    _tris;\\n    _root;\\n    _normalResult = { nx: 0, ny: 0, nz: 0 };\\n    _push = { x: 0, y: 0, z: 0 };\\n    _constraintNormals = [\\n        { x: 0, y: 0, z: 0 },\\n        { x: 0, y: 0, z: 0 },\\n        { x: 0, y: 0, z: 0 }\\n    ];\\n    _stack = [];\\n    _rayResult = { t: -1, triIdx: -1 };\\n    constructor(positions, indices) {\\n        const numTris = Math.floor(indices.length / 3);\\n        const tris = {\\n            v0x: new Float32Array(numTris),\\n            v0y: new Float32Array(numTris),\\n            v0z: new Float32Array(numTris),\\n            v1x: new Float32Array(numTris),\\n            v1y: new Float32Array(numTris),\\n            v1z: new Float32Array(numTris),\\n            v2x: new Float32Array(numTris),\\n            v2y: new Float32Array(numTris),\\n            v2z: new Float32Array(numTris),\\n            nx: new Float32Array(numTris),\\n            ny: new Float32Array(numTris),\\n            nz: new Float32Array(numTris),\\n            indices: new Uint32Array(numTris),\\n            count: numTris\\n        };\\n        for (let i = 0; i < numTris; i++) {\\n            const i0 = indices[i * 3] * 3;\\n            const i1 = indices[i * 3 + 1] * 3;\\n            const i2 = indices[i * 3 + 2] * 3;\\n            tris.v0x[i] = positions[i0];\\n            tris.v0y[i] = positions[i0 + 1];\\n            tris.v0z[i] = positions[i0 + 2];\\n            tris.v1x[i] = positions[i1];\\n            tris.v1y[i] = positions[i1 + 1];\\n            tris.v1z[i] = positions[i1 + 2];\\n            tris.v2x[i] = positions[i2];\\n            tris.v2y[i] = positions[i2 + 1];\\n            tris.v2z[i] = positions[i2 + 2];\\n            // face normal\\n            const e1x = tris.v1x[i] - tris.v0x[i];\\n            const e1y = tris.v1y[i] - tris.v0y[i];\\n            const e1z = tris.v1z[i] - tris.v0z[i];\\n            const e2x = tris.v2x[i] - tris.v0x[i];\\n            const e2y = tris.v2y[i] - tris.v0y[i];\\n            const e2z = tris.v2z[i] - tris.v0z[i];\\n            let fnx = e1y * e2z - e1z * e2y;\\n            let fny = e1z * e2x - e1x * e2z;\\n            let fnz = e1x * e2y - e1y * e2x;\\n            const len = Math.sqrt(fnx * fnx + fny * fny + fnz * fnz);\\n            if (len > 1e-10) {\\n                const invLen = 1.0 / len;\\n                fnx *= invLen;\\n                fny *= invLen;\\n                fnz *= invLen;\\n            }\\n            tris.nx[i] = fnx;\\n            tris.ny[i] = fny;\\n            tris.nz[i] = fnz;\\n            tris.indices[i] = i;\\n        }\\n        this._tris = tris;\\n        this._root = buildBVH(tris, 0, numTris);\\n    }\\n    // ---- Public accessors ----\\n    /**\\n     * Read-only view of the de-indexed triangle data, used by debug overlays.\\n     * The underlying typed arrays are reused and must not be mutated.\\n     *\\n     * @returns the triangle SoA backing this collision.\\n     */\\n    get triangles() {\\n        return this._tris;\\n    }\\n    // ---- Collision interface ----\\n    queryRay(ox, oy, oz, dx, dy, dz, maxDist) {\\n        const len = Math.sqrt(dx * dx + dy * dy + dz * dz);\\n        if (len < 1e-10)\\n            return null;\\n        const invLen = 1.0 / len;\\n        dx *= invLen;\\n        dy *= invLen;\\n        dz *= invLen;\\n        const idx = 1.0 / (Math.abs(dx) > 1e-12 ? dx : (dx >= 0 ? 1e-12 : -1e-12));\\n        const idy = 1.0 / (Math.abs(dy) > 1e-12 ? dy : (dy >= 0 ? 1e-12 : -1e-12));\\n        const idz = 1.0 / (Math.abs(dz) > 1e-12 ? dz : (dz >= 0 ? 1e-12 : -1e-12));\\n        const hit = this._queryRayBVH(ox, oy, oz, dx, dy, dz, idx, idy, idz, maxDist);\\n        if (!hit)\\n            return null;\\n        return {\\n            x: ox + dx * hit.t,\\n            y: oy + dy * hit.t,\\n            z: oz + dz * hit.t\\n        };\\n    }\\n    querySphere(cx, cy, cz, radius, out) {\\n        return resolveIterative(cx, cy, cz, (rx, ry, rz, push) => this._deepestSpherePenetration(rx, ry, rz, radius, push), this._constraintNormals, this._push, out);\\n    }\\n    queryCapsule(cx, cy, cz, halfHeight, radius, out) {\\n        return resolveIterative(cx, cy, cz, (rx, ry, rz, push) => this._deepestCapsulePenetration(rx, ry, rz, halfHeight, radius, push), this._constraintNormals, this._push, out);\\n    }\\n    isFreeAt(x, y, z) {\\n        // Approximation: a point is in free space iff no triangle is within\\n        // half a voxel of it. Matches the voxel-grid notion for data derived\\n        // from the same carve.\\n        return !this._deepestSpherePenetration(x, y, z, this.voxelResolution * 0.5, this._push);\\n    }\\n    querySurfaceNormal(x, y, z, rdx, rdy, rdz) {\\n        const len = Math.sqrt(rdx * rdx + rdy * rdy + rdz * rdz);\\n        if (len < 1e-10) {\\n            this._normalResult.nx = 0;\\n            this._normalResult.ny = 1;\\n            this._normalResult.nz = 0;\\n            return this._normalResult;\\n        }\\n        const invLen = 1.0 / len;\\n        const dx = rdx * invLen;\\n        const dy = rdy * invLen;\\n        const dz = rdz * invLen;\\n        const idx = 1.0 / (Math.abs(dx) > 1e-12 ? dx : (dx >= 0 ? 1e-12 : -1e-12));\\n        const idy = 1.0 / (Math.abs(dy) > 1e-12 ? dy : (dy >= 0 ? 1e-12 : -1e-12));\\n        const idz = 1.0 / (Math.abs(dz) > 1e-12 ? dz : (dz >= 0 ? 1e-12 : -1e-12));\\n        const hit = this._queryRayBVH(x, y, z, dx, dy, dz, idx, idy, idz, 1.0);\\n        const result = this._normalResult;\\n        if (hit) {\\n            const i = hit.triIdx;\\n            result.nx = this._tris.nx[i];\\n            result.ny = this._tris.ny[i];\\n            result.nz = this._tris.nz[i];\\n            // Ensure normal faces toward the ray origin (against the ray direction)\\n            const dot = result.nx * dx + result.ny * dy + result.nz * dz;\\n            if (dot > 0) {\\n                result.nx = -result.nx;\\n                result.ny = -result.ny;\\n                result.nz = -result.nz;\\n            }\\n        }\\n        else {\\n            result.nx = 0;\\n            result.ny = 1;\\n            result.nz = 0;\\n        }\\n        return result;\\n    }\\n    // ---- BVH ray traversal (iterative, returns both t and triangle index) ----\\n    _queryRayBVH(ox, oy, oz, dx, dy, dz, idx, idy, idz, maxDist) {\\n        const root = this._root;\\n        if (rayAABB(ox, oy, oz, idx, idy, idz, root.minX, root.minY, root.minZ, root.maxX, root.maxY, root.maxZ, maxDist) < 0) {\\n            return null;\\n        }\\n        const stack = this._stack;\\n        let top = 0;\\n        stack[top++] = root;\\n        let bestT = maxDist + 1;\\n        let bestTriIdx = -1;\\n        const { _tris: tris } = this;\\n        while (top > 0) {\\n            const node = stack[--top];\\n            if (node.left === null) {\\n                for (let j = node.triStart; j < node.triStart + node.triCount; j++) {\\n                    const i = tris.indices[j];\\n                    const ht = rayTriangle(ox, oy, oz, dx, dy, dz, tris.v0x[i], tris.v0y[i], tris.v0z[i], tris.v1x[i], tris.v1y[i], tris.v1z[i], tris.v2x[i], tris.v2y[i], tris.v2z[i]);\\n                    if (ht >= 0 && ht <= maxDist && ht < bestT) {\\n                        bestT = ht;\\n                        bestTriIdx = i;\\n                    }\\n                }\\n                continue;\\n            }\\n            const tLeft = rayAABB(ox, oy, oz, idx, idy, idz, node.left.minX, node.left.minY, node.left.minZ, node.left.maxX, node.left.maxY, node.left.maxZ, bestT);\\n            const tRight = rayAABB(ox, oy, oz, idx, idy, idz, node.right.minX, node.right.minY, node.right.minZ, node.right.maxX, node.right.maxY, node.right.maxZ, bestT);\\n            // Push farther child first so nearer child is popped first\\n            if (tLeft >= 0 && tRight >= 0) {\\n                if (tLeft <= tRight) {\\n                    stack[top++] = node.right;\\n                    stack[top++] = node.left;\\n                }\\n                else {\\n                    stack[top++] = node.left;\\n                    stack[top++] = node.right;\\n                }\\n            }\\n            else if (tLeft >= 0) {\\n                stack[top++] = node.left;\\n            }\\n            else if (tRight >= 0) {\\n                stack[top++] = node.right;\\n            }\\n        }\\n        if (bestTriIdx < 0)\\n            return null;\\n        const result = this._rayResult;\\n        result.t = bestT;\\n        result.triIdx = bestTriIdx;\\n        return result;\\n    }\\n    // ---- Sphere deepest penetration (single triangle) ----\\n    _deepestSpherePenetration(cx, cy, cz, radius, out) {\\n        let bestPen = PENETRATION_EPSILON;\\n        let bestPx = 0, bestPy = 0, bestPz = 0;\\n        let found = false;\\n        this._sphereBVH(this._root, cx, cy, cz, radius, (triIdx) => {\\n            const tris = this._tris;\\n            closestPointOnTriangle(cx, cy, cz, tris.v0x[triIdx], tris.v0y[triIdx], tris.v0z[triIdx], tris.v1x[triIdx], tris.v1y[triIdx], tris.v1z[triIdx], tris.v2x[triIdx], tris.v2y[triIdx], tris.v2z[triIdx], _closest);\\n            const dx = cx - _closest.x;\\n            const dy = cy - _closest.y;\\n            const dz = cz - _closest.z;\\n            const distSq = dx * dx + dy * dy + dz * dz;\\n            if (distSq >= radius * radius)\\n                return;\\n            const dist = Math.sqrt(distSq);\\n            const penetration = radius - dist;\\n            if (penetration > bestPen) {\\n                bestPen = penetration;\\n                if (dist > 1e-10) {\\n                    const invDist = 1.0 / dist;\\n                    bestPx = dx * invDist * penetration;\\n                    bestPy = dy * invDist * penetration;\\n                    bestPz = dz * invDist * penetration;\\n                }\\n                else {\\n                    bestPx = tris.nx[triIdx] * penetration;\\n                    bestPy = tris.ny[triIdx] * penetration;\\n                    bestPz = tris.nz[triIdx] * penetration;\\n                }\\n                found = true;\\n            }\\n        });\\n        if (found) {\\n            out.x = bestPx;\\n            out.y = bestPy;\\n            out.z = bestPz;\\n        }\\n        return found;\\n    }\\n    // ---- Capsule deepest penetration (single triangle) ----\\n    _deepestCapsulePenetration(cx, cy, cz, halfHeight, radius, out) {\\n        let bestPen = PENETRATION_EPSILON;\\n        let bestPx = 0, bestPy = 0, bestPz = 0;\\n        let found = false;\\n        const s0x = cx, s0y = cy - halfHeight, s0z = cz;\\n        const s1x = cx, s1y = cy + halfHeight, s1z = cz;\\n        const capsuleRadius = radius;\\n        const capsuleCenterY = cy;\\n        const capsuleHalfExtentY = halfHeight + radius;\\n        this._capsuleBVH(this._root, cx, capsuleCenterY, cz, capsuleHalfExtentY, capsuleRadius, (triIdx) => {\\n            const tris = this._tris;\\n            closestSegmentTriangle(s0x, s0y, s0z, s1x, s1y, s1z, tris.v0x[triIdx], tris.v0y[triIdx], tris.v0z[triIdx], tris.v1x[triIdx], tris.v1y[triIdx], tris.v1z[triIdx], tris.v2x[triIdx], tris.v2y[triIdx], tris.v2z[triIdx], _segClosest, _triClosest);\\n            const dx = _segClosest.x - _triClosest.x;\\n            const dy = _segClosest.y - _triClosest.y;\\n            const dz = _segClosest.z - _triClosest.z;\\n            const distSq = dx * dx + dy * dy + dz * dz;\\n            if (distSq >= radius * radius)\\n                return;\\n            const dist = Math.sqrt(distSq);\\n            const penetration = radius - dist;\\n            if (penetration > bestPen) {\\n                bestPen = penetration;\\n                if (dist > 1e-10) {\\n                    const invDist = 1.0 / dist;\\n                    bestPx = dx * invDist * penetration;\\n                    bestPy = dy * invDist * penetration;\\n                    bestPz = dz * invDist * penetration;\\n                }\\n                else {\\n                    bestPx = tris.nx[triIdx] * penetration;\\n                    bestPy = tris.ny[triIdx] * penetration;\\n                    bestPz = tris.nz[triIdx] * penetration;\\n                }\\n                found = true;\\n            }\\n        });\\n        if (found) {\\n            out.x = bestPx;\\n            out.y = bestPy;\\n            out.z = bestPz;\\n        }\\n        return found;\\n    }\\n    // ---- BVH sphere traversal (iterative) ----\\n    _sphereBVH(root, cx, cy, cz, radius, callback) {\\n        const stack = this._stack;\\n        let top = 0;\\n        stack[top++] = root;\\n        while (top > 0) {\\n            const node = stack[--top];\\n            if (!sphereAABBOverlap(cx, cy, cz, radius, node.minX, node.minY, node.minZ, node.maxX, node.maxY, node.maxZ)) {\\n                continue;\\n            }\\n            if (node.left === null) {\\n                const { _tris: tris } = this;\\n                for (let j = node.triStart; j < node.triStart + node.triCount; j++) {\\n                    callback(tris.indices[j]);\\n                }\\n                continue;\\n            }\\n            stack[top++] = node.right;\\n            stack[top++] = node.left;\\n        }\\n    }\\n    // ---- BVH capsule traversal (iterative, uses AABB of the capsule) ----\\n    _capsuleBVH(root, cx, cy, cz, halfExtentY, radius, callback) {\\n        const capMinX = cx - radius;\\n        const capMaxX = cx + radius;\\n        const capMinY = cy - halfExtentY;\\n        const capMaxY = cy + halfExtentY;\\n        const capMinZ = cz - radius;\\n        const capMaxZ = cz + radius;\\n        const stack = this._stack;\\n        let top = 0;\\n        stack[top++] = root;\\n        while (top > 0) {\\n            const node = stack[--top];\\n            if (capMaxX < node.minX || capMinX > node.maxX ||\\n                capMaxY < node.minY || capMinY > node.maxY ||\\n                capMaxZ < node.minZ || capMinZ > node.maxZ) {\\n                continue;\\n            }\\n            if (node.left === null) {\\n                const { _tris: tris } = this;\\n                for (let j = node.triStart; j < node.triStart + node.triCount; j++) {\\n                    callback(tris.indices[j]);\\n                }\\n                continue;\\n            }\\n            stack[top++] = node.right;\\n            stack[top++] = node.left;\\n        }\\n    }\\n    // ---- Static factory ----\\n    /**\\n     * Load a GLB file via the PlayCanvas asset system, extract mesh geometry,\\n     * and construct a MeshCollision. The GLB entity is not added to the scene;\\n     * only the vertex/index data is used.\\n     *\\n     * @param app - PlayCanvas application instance.\\n     * @param url - URL to the .glb file.\\n     * @returns A promise resolving to a MeshCollision.\\n     */\\n    static fromGlb(app, url) {\\n        return new Promise((resolve, reject) => {\\n            const asset = new Asset(url, 'container', { url });\\n            const cleanup = () => {\\n                app.assets.remove(asset);\\n                asset.unload();\\n            };\\n            asset.on('load', () => {\\n                const renders = asset.resource.renders;\\n                if (!renders || renders.length === 0) {\\n                    cleanup();\\n                    reject(new Error('GLB contains no mesh data'));\\n                    return;\\n                }\\n                const allPositions = [];\\n                const allIndices = [];\\n                let vertexOffset = 0;\\n                for (const renderAsset of renders) {\\n                    const render = renderAsset.resource;\\n                    for (let m = 0; m < render.meshes.length; m++) {\\n                        const mesh = render.meshes[m];\\n                        const vb = mesh.vertexBuffer;\\n                        const ib = mesh.indexBuffer[0];\\n                        if (!vb || !ib)\\n                            continue;\\n                        const format = vb.format;\\n                        let posElement = null;\\n                        for (let e = 0; e < format.elements.length; e++) {\\n                            if (format.elements[e].name === SEMANTIC_POSITION) {\\n                                posElement = format.elements[e];\\n                                break;\\n                            }\\n                        }\\n                        if (!posElement)\\n                            continue;\\n                        const data = new Float32Array(vb.storage);\\n                        const stride = format.size / 4;\\n                        const offset = posElement.offset / 4;\\n                        const numVerts = vb.numVertices;\\n                        for (let v = 0; v < numVerts; v++) {\\n                            const base = v * stride + offset;\\n                            allPositions.push(data[base], data[base + 1], data[base + 2]);\\n                        }\\n                        const indexData = ib.format === INDEXFORMAT_UINT32 ?\\n                            new Uint32Array(ib.storage) :\\n                            new Uint16Array(ib.storage);\\n                        for (const prim of mesh.primitive) {\\n                            for (let i = 0; i < prim.count; i++) {\\n                                allIndices.push(indexData[prim.base + i] + vertexOffset);\\n                            }\\n                        }\\n                        vertexOffset += numVerts;\\n                    }\\n                }\\n                if (allIndices.length === 0) {\\n                    cleanup();\\n                    reject(new Error('GLB meshes contain no triangle data'));\\n                    return;\\n                }\\n                const collision = new MeshCollision(new Float32Array(allPositions), new Uint32Array(allIndices));\\n                cleanup();\\n                resolve(collision);\\n            });\\n            asset.on('error', (err) => {\\n                cleanup();\\n                reject(new Error(err));\\n            });\\n            app.assets.add(asset);\\n            app.assets.load(asset);\\n        });\\n    }\\n}\\n\\n/**\\n * Solid leaf node marker: childMask = 0xFF, baseOffset = 0.\\n * Unambiguous because BFS layout guarantees children always come after their parent,\\n * so baseOffset = 0 is never valid for an interior node.\\n */\\nconst SOLID_LEAF_MARKER = 0xFF000000 >>> 0;\\n/** Half-extent of the flatness sampling patch (5x5 when R=2). */\\nconst FLAT_R = 2;\\n/** 1/sqrt(2), used to normalise 45-degree diagonal normals. */\\nconst INV_SQRT2$1 = 1 / Math.sqrt(2);\\n/**\\n * Surface normal candidate directions for querySurfaceNormal.\\n * Each entry: [dx, dy, dz, t1x, t1y, t1z, t2x, t2y, t2z]\\n *   (dx,dy,dz) = canonical normal direction (components 0 or +/-1)\\n *   (t1,t2) = orthogonal tangent vectors spanning the perpendicular sampling plane\\n */\\nconst SURFACE_CANDIDATES = [\\n    // Axis-aligned\\n    [1, 0, 0, 0, 1, 0, 0, 0, 1],\\n    [0, 1, 0, 1, 0, 0, 0, 0, 1],\\n    [0, 0, 1, 1, 0, 0, 0, 1, 0],\\n    // XZ diagonals (vertical walls at 45 degrees)\\n    [1, 0, 1, 0, 1, 0, -1, 0, 1],\\n    [1, 0, -1, 0, 1, 0, 1, 0, 1],\\n    // XY diagonals (walls tilted from vertical)\\n    [1, 1, 0, 0, 0, 1, -1, 1, 0],\\n    [1, -1, 0, 0, 0, 1, 1, 1, 0],\\n    // YZ diagonals (sloped floors/ceilings)\\n    [0, 1, 1, 1, 0, 0, 0, -1, 1],\\n    [0, 1, -1, 1, 0, 0, 0, 1, 1]\\n];\\n/**\\n * Score a surface candidate direction by sampling a 5x5 patch at three depth layers\\n * shifted along the step direction. Returns the best (maximum) layer score. A \\\"surface\\n * hit\\\" at each sample is a solid voxel whose neighbour in the step direction is empty.\\n *\\n * @param collision - The voxel collision instance.\\n * @param ix - Voxel X index of the surface point.\\n * @param iy - Voxel Y index of the surface point.\\n * @param iz - Voxel Z index of the surface point.\\n * @param sx - Step X component (camera-facing direction).\\n * @param sy - Step Y component.\\n * @param sz - Step Z component.\\n * @param t1x - First tangent vector X.\\n * @param t1y - First tangent vector Y.\\n * @param t1z - First tangent vector Z.\\n * @param t2x - Second tangent vector X.\\n * @param t2y - Second tangent vector Y.\\n * @param t2z - Second tangent vector Z.\\n * @returns The best score across the three depth layers.\\n */\\nfunction scoreSurfaceCandidate(collision, ix, iy, iz, sx, sy, sz, t1x, t1y, t1z, t2x, t2y, t2z) {\\n    let best = 0;\\n    for (let depth = 1; depth >= -1; depth--) {\\n        let s = 0;\\n        for (let da = -FLAT_R; da <= FLAT_R; da++) {\\n            for (let db = -FLAT_R; db <= FLAT_R; db++) {\\n                const px = ix + da * t1x + db * t2x - sx * depth;\\n                const py = iy + da * t1y + db * t2y - sy * depth;\\n                const pz = iz + da * t1z + db * t2z - sz * depth;\\n                if (collision.isVoxelSolid(px, py, pz) &&\\n                    !collision.isVoxelSolid(px + sx, py + sy, pz + sz)) {\\n                    s++;\\n                }\\n            }\\n        }\\n        if (s > best)\\n            best = s;\\n    }\\n    return best;\\n}\\n/**\\n * Count the number of set bits in a 32-bit integer.\\n *\\n * @param n - 32-bit integer.\\n * @returns Number of bits set to 1.\\n */\\nfunction popcount(n) {\\n    n >>>= 0;\\n    n -= ((n >>> 1) & 0x55555555);\\n    n = (n & 0x33333333) + ((n >>> 2) & 0x33333333);\\n    return (((n + (n >>> 4)) & 0x0F0F0F0F) * 0x01010101) >>> 24;\\n}\\n/**\\n * Runtime sparse voxel octree collider.\\n *\\n * Loads the two-file format (.voxel.json + .voxel.bin) produced by\\n * splat-transform's writeVoxel and provides point and sphere collision queries.\\n */\\nclass VoxelCollision {\\n    /** Grid-aligned bounds (min xyz) */\\n    _gridMinX;\\n    _gridMinY;\\n    _gridMinZ;\\n    /** Number of voxels along each axis */\\n    _numVoxelsX;\\n    _numVoxelsY;\\n    _numVoxelsZ;\\n    /** Size of each voxel in world units */\\n    _voxelResolution;\\n    /** Voxels per leaf dimension (always 4) */\\n    _leafSize;\\n    /** Maximum tree depth (number of octree levels above the leaf level) */\\n    _treeDepth;\\n    /** Flat Laine-Karras node array */\\n    _nodes;\\n    /** Leaf voxel masks: pairs of (lo, hi) Uint32 per mixed leaf */\\n    _leafData;\\n    /** Pre-allocated scratch push-out vector to avoid per-frame allocations */\\n    _push = { x: 0, y: 0, z: 0 };\\n    /** Pre-allocated result for querySurfaceNormal to avoid per-call allocation */\\n    _normalResult = { nx: 0, ny: 0, nz: 0 };\\n    /** Pre-allocated constraint normals for iterative corner resolution (max 3 walls) */\\n    _constraintNormals = [\\n        { x: 0, y: 0, z: 0 },\\n        { x: 0, y: 0, z: 0 },\\n        { x: 0, y: 0, z: 0 }\\n    ];\\n    constructor(metadata, nodes, leafData) {\\n        this._gridMinX = metadata.gridBounds.min[0];\\n        this._gridMinY = metadata.gridBounds.min[1];\\n        this._gridMinZ = metadata.gridBounds.min[2];\\n        const res = metadata.voxelResolution;\\n        this._numVoxelsX = Math.round((metadata.gridBounds.max[0] - metadata.gridBounds.min[0]) / res);\\n        this._numVoxelsY = Math.round((metadata.gridBounds.max[1] - metadata.gridBounds.min[1]) / res);\\n        this._numVoxelsZ = Math.round((metadata.gridBounds.max[2] - metadata.gridBounds.min[2]) / res);\\n        this._voxelResolution = res;\\n        this._leafSize = metadata.leafSize;\\n        this._treeDepth = metadata.treeDepth;\\n        this._nodes = nodes;\\n        this._leafData = leafData;\\n    }\\n    /**\\n     * Grid-aligned bounds minimum X in world units.\\n     *\\n     * @returns {number} The minimum X coordinate.\\n     */\\n    get gridMinX() {\\n        return this._gridMinX;\\n    }\\n    /**\\n     * Grid-aligned bounds minimum Y in world units.\\n     *\\n     * @returns {number} The minimum Y coordinate.\\n     */\\n    get gridMinY() {\\n        return this._gridMinY;\\n    }\\n    /**\\n     * Grid-aligned bounds minimum Z in world units.\\n     *\\n     * @returns {number} The minimum Z coordinate.\\n     */\\n    get gridMinZ() {\\n        return this._gridMinZ;\\n    }\\n    /**\\n     * Number of voxels along the X axis.\\n     *\\n     * @returns {number} The voxel count on X.\\n     */\\n    get numVoxelsX() {\\n        return this._numVoxelsX;\\n    }\\n    /**\\n     * Number of voxels along the Y axis.\\n     *\\n     * @returns {number} The voxel count on Y.\\n     */\\n    get numVoxelsY() {\\n        return this._numVoxelsY;\\n    }\\n    /**\\n     * Number of voxels along the Z axis.\\n     *\\n     * @returns {number} The voxel count on Z.\\n     */\\n    get numVoxelsZ() {\\n        return this._numVoxelsZ;\\n    }\\n    /**\\n     * Size of each voxel in world units.\\n     *\\n     * @returns {number} The voxel resolution.\\n     */\\n    get voxelResolution() {\\n        return this._voxelResolution;\\n    }\\n    /**\\n     * Voxels per leaf dimension (always 4).\\n     *\\n     * @returns {number} The leaf size.\\n     */\\n    get leafSize() {\\n        return this._leafSize;\\n    }\\n    /**\\n     * Maximum tree depth (number of octree levels above the leaf level).\\n     *\\n     * @returns {number} The tree depth.\\n     */\\n    get treeDepth() {\\n        return this._treeDepth;\\n    }\\n    /**\\n     * Flat Laine-Karras node array (read-only access for GPU upload).\\n     *\\n     * @returns {Uint32Array} The node array.\\n     */\\n    get nodes() {\\n        return this._nodes;\\n    }\\n    /**\\n     * Leaf voxel masks: pairs of (lo, hi) Uint32 per mixed leaf (read-only access for GPU upload).\\n     *\\n     * @returns {Uint32Array} The leaf data array.\\n     */\\n    get leafData() {\\n        return this._leafData;\\n    }\\n    /**\\n     * Whether this data requires X/Y negation (legacy v1.0 format).\\n     *\\n     * @returns {boolean} True if coordinates need flipping.\\n     */\\n    get flipXY() {\\n        return false;\\n    }\\n    isFreeAt(x, y, z) {\\n        // Without voxel data, there's no carve to consult — report not-free\\n        // rather than have the lattice search treat the world as wide open.\\n        if (this._nodes.length === 0) {\\n            return false;\\n        }\\n        const res = this._voxelResolution;\\n        const ix = Math.floor((x - this._gridMinX) / res);\\n        const iy = Math.floor((y - this._gridMinY) / res);\\n        const iz = Math.floor((z - this._gridMinZ) / res);\\n        // Outside the carved grid is \\\"no data\\\" — also not-free. Without this\\n        // check the lattice search would spend candidates on out-of-bounds\\n        // cells (and `isVoxelSolid` would mislead callers by returning false).\\n        if (ix < 0 || iy < 0 || iz < 0 ||\\n            ix >= this._numVoxelsX || iy >= this._numVoxelsY || iz >= this._numVoxelsZ) {\\n            return false;\\n        }\\n        return !this.isVoxelSolid(ix, iy, iz);\\n    }\\n    querySurfaceNormal(x, y, z, rdx, rdy, rdz) {\\n        const nudge = this._voxelResolution * 0.25;\\n        const ix = Math.floor((x + Math.sign(rdx) * nudge - this._gridMinX) / this._voxelResolution);\\n        const iy = Math.floor((y + Math.sign(rdy) * nudge - this._gridMinY) / this._voxelResolution);\\n        const iz = Math.floor((z + Math.sign(rdz) * nudge - this._gridMinZ) / this._voxelResolution);\\n        const result = this._normalResult;\\n        let bestScore = -1;\\n        let bestNx = 0;\\n        let bestNy = 1;\\n        let bestNz = 0;\\n        for (let c = 0; c < SURFACE_CANDIDATES.length; c++) {\\n            const cand = SURFACE_CANDIDATES[c];\\n            const dx = cand[0];\\n            const dy = cand[1];\\n            const dz = cand[2];\\n            const dot = rdx * dx + rdy * dy + rdz * dz;\\n            if (Math.abs(dot) < 1e-6)\\n                continue;\\n            const sign = dot < 0 ? 1 : -1;\\n            const sx = dx * sign;\\n            const sy = dy * sign;\\n            const sz = dz * sign;\\n            const score = scoreSurfaceCandidate(this, ix, iy, iz, sx, sy, sz, cand[3], cand[4], cand[5], cand[6], cand[7], cand[8]);\\n            if (score > bestScore) {\\n                bestScore = score;\\n                const mag = (Math.abs(dx) + Math.abs(dy) + Math.abs(dz)) > 1 ? INV_SQRT2$1 : 1;\\n                bestNx = sx * mag;\\n                bestNy = sy * mag;\\n                bestNz = sz * mag;\\n            }\\n        }\\n        result.nx = bestNx;\\n        result.ny = bestNy;\\n        result.nz = bestNz;\\n        return result;\\n    }\\n    queryRay(ox, oy, oz, dx, dy, dz, maxDist) {\\n        if (this._nodes.length === 0) {\\n            return null;\\n        }\\n        const res = this._voxelResolution;\\n        const gMinX = this._gridMinX;\\n        const gMinY = this._gridMinY;\\n        const gMinZ = this._gridMinZ;\\n        const gMaxX = gMinX + this._numVoxelsX * res;\\n        const gMaxY = gMinY + this._numVoxelsY * res;\\n        const gMaxZ = gMinZ + this._numVoxelsZ * res;\\n        const EPS = 1e-12;\\n        // Ray-AABB slab intersection to find the range [tNear, tFar]\\n        let tNear = 0;\\n        let tFar = maxDist;\\n        if (Math.abs(dx) > EPS) {\\n            let t1 = (gMinX - ox) / dx;\\n            let t2 = (gMaxX - ox) / dx;\\n            if (t1 > t2) {\\n                const tmp = t1;\\n                t1 = t2;\\n                t2 = tmp;\\n            }\\n            if (t1 > tNear) {\\n                tNear = t1;\\n            }\\n            tFar = Math.min(tFar, t2);\\n            if (tNear > tFar)\\n                return null;\\n        }\\n        else if (ox < gMinX || ox >= gMaxX) {\\n            return null;\\n        }\\n        if (Math.abs(dy) > EPS) {\\n            let t1 = (gMinY - oy) / dy;\\n            let t2 = (gMaxY - oy) / dy;\\n            if (t1 > t2) {\\n                const tmp = t1;\\n                t1 = t2;\\n                t2 = tmp;\\n            }\\n            if (t1 > tNear) {\\n                tNear = t1;\\n            }\\n            tFar = Math.min(tFar, t2);\\n            if (tNear > tFar)\\n                return null;\\n        }\\n        else if (oy < gMinY || oy >= gMaxY) {\\n            return null;\\n        }\\n        if (Math.abs(dz) > EPS) {\\n            let t1 = (gMinZ - oz) / dz;\\n            let t2 = (gMaxZ - oz) / dz;\\n            if (t1 > t2) {\\n                const tmp = t1;\\n                t1 = t2;\\n                t2 = tmp;\\n            }\\n            if (t1 > tNear) {\\n                tNear = t1;\\n            }\\n            tFar = Math.min(tFar, t2);\\n            if (tNear > tFar)\\n                return null;\\n        }\\n        else if (oz < gMinZ || oz >= gMaxZ) {\\n            return null;\\n        }\\n        // Entry point on the grid AABB (or origin if already inside)\\n        const entryX = ox + dx * tNear;\\n        const entryY = oy + dy * tNear;\\n        const entryZ = oz + dz * tNear;\\n        // Convert to voxel indices, clamping to valid range for boundary cases\\n        let ix = Math.max(0, Math.min(Math.floor((entryX - gMinX) / res), this._numVoxelsX - 1));\\n        let iy = Math.max(0, Math.min(Math.floor((entryY - gMinY) / res), this._numVoxelsY - 1));\\n        let iz = Math.max(0, Math.min(Math.floor((entryZ - gMinZ) / res), this._numVoxelsZ - 1));\\n        // DDA setup\\n        const stepX = dx > 0 ? 1 : (dx < 0 ? -1 : 0);\\n        const stepY = dy > 0 ? 1 : (dy < 0 ? -1 : 0);\\n        const stepZ = dz > 0 ? 1 : (dz < 0 ? -1 : 0);\\n        const invDx = Math.abs(dx) > EPS ? 1.0 / dx : 0;\\n        const invDy = Math.abs(dy) > EPS ? 1.0 / dy : 0;\\n        const invDz = Math.abs(dz) > EPS ? 1.0 / dz : 0;\\n        let tMaxX = Math.abs(dx) > EPS ? (gMinX + (ix + (dx > 0 ? 1 : 0)) * res - ox) * invDx : Infinity;\\n        let tMaxY = Math.abs(dy) > EPS ? (gMinY + (iy + (dy > 0 ? 1 : 0)) * res - oy) * invDy : Infinity;\\n        let tMaxZ = Math.abs(dz) > EPS ? (gMinZ + (iz + (dz > 0 ? 1 : 0)) * res - oz) * invDz : Infinity;\\n        const tDeltaX = Math.abs(dx) > EPS ? res * Math.abs(invDx) : Infinity;\\n        const tDeltaY = Math.abs(dy) > EPS ? res * Math.abs(invDy) : Infinity;\\n        const tDeltaZ = Math.abs(dz) > EPS ? res * Math.abs(invDz) : Infinity;\\n        let currentT = tNear;\\n        const maxSteps = this._numVoxelsX + this._numVoxelsY + this._numVoxelsZ;\\n        for (let step = 0; step < maxSteps; step++) {\\n            if (this.isVoxelSolid(ix, iy, iz)) {\\n                return {\\n                    x: ox + dx * currentT,\\n                    y: oy + dy * currentT,\\n                    z: oz + dz * currentT\\n                };\\n            }\\n            // Advance along the axis with the smallest tMax\\n            if (tMaxX < tMaxY) {\\n                if (tMaxX < tMaxZ) {\\n                    currentT = tMaxX;\\n                    ix += stepX;\\n                    tMaxX += tDeltaX;\\n                }\\n                else {\\n                    currentT = tMaxZ;\\n                    iz += stepZ;\\n                    tMaxZ += tDeltaZ;\\n                }\\n            }\\n            else if (tMaxY < tMaxZ) {\\n                currentT = tMaxY;\\n                iy += stepY;\\n                tMaxY += tDeltaY;\\n            }\\n            else {\\n                currentT = tMaxZ;\\n                iz += stepZ;\\n                tMaxZ += tDeltaZ;\\n            }\\n            if (ix < 0 || iy < 0 || iz < 0 ||\\n                ix >= this._numVoxelsX || iy >= this._numVoxelsY || iz >= this._numVoxelsZ ||\\n                currentT > maxDist) {\\n                return null;\\n            }\\n        }\\n        return null;\\n    }\\n    querySphere(cx, cy, cz, radius, out) {\\n        if (this.nodes.length === 0) {\\n            return false;\\n        }\\n        return resolveIterative(cx, cy, cz, (rx, ry, rz, push) => this.resolveDeepestPenetration(rx, ry, rz, radius, push), this._constraintNormals, this._push, out);\\n    }\\n    queryCapsule(cx, cy, cz, halfHeight, radius, out) {\\n        if (this.nodes.length === 0) {\\n            return false;\\n        }\\n        return resolveIterative(cx, cy, cz, (rx, ry, rz, push) => this.resolveDeepestPenetrationCapsule(rx, ry, rz, halfHeight, radius, push), this._constraintNormals, this._push, out);\\n    }\\n    /**\\n     * Find the single deepest penetrating voxel for the given sphere.\\n     *\\n     * @param cx - Sphere center X.\\n     * @param cy - Sphere center Y.\\n     * @param cz - Sphere center Z.\\n     * @param radius - Sphere radius.\\n     * @param out - Receives the push-out vector on success.\\n     * @returns True if a penetrating voxel was found.\\n     */\\n    resolveDeepestPenetration(cx, cy, cz, radius, out) {\\n        const { voxelResolution, gridMinX, gridMinY, gridMinZ } = this;\\n        const radiusSq = radius * radius;\\n        // Compute bounding box of the sphere in voxel indices\\n        const ixMin = Math.floor((cx - radius - gridMinX) / voxelResolution);\\n        const iyMin = Math.floor((cy - radius - gridMinY) / voxelResolution);\\n        const izMin = Math.floor((cz - radius - gridMinZ) / voxelResolution);\\n        const ixMax = Math.floor((cx + radius - gridMinX) / voxelResolution);\\n        const iyMax = Math.floor((cy + radius - gridMinY) / voxelResolution);\\n        const izMax = Math.floor((cz + radius - gridMinZ) / voxelResolution);\\n        let bestPushX = 0;\\n        let bestPushY = 0;\\n        let bestPushZ = 0;\\n        let bestPenetration = PENETRATION_EPSILON;\\n        let found = false;\\n        for (let iz = izMin; iz <= izMax; iz++) {\\n            for (let iy = iyMin; iy <= iyMax; iy++) {\\n                for (let ix = ixMin; ix <= ixMax; ix++) {\\n                    if (!this.isVoxelSolid(ix, iy, iz)) {\\n                        continue;\\n                    }\\n                    // Compute the world-space AABB of this voxel\\n                    const vMinX = gridMinX + ix * voxelResolution;\\n                    const vMinY = gridMinY + iy * voxelResolution;\\n                    const vMinZ = gridMinZ + iz * voxelResolution;\\n                    const vMaxX = vMinX + voxelResolution;\\n                    const vMaxY = vMinY + voxelResolution;\\n                    const vMaxZ = vMinZ + voxelResolution;\\n                    // Find the nearest point on the voxel AABB to the sphere center\\n                    const nearX = Math.max(vMinX, Math.min(cx, vMaxX));\\n                    const nearY = Math.max(vMinY, Math.min(cy, vMaxY));\\n                    const nearZ = Math.max(vMinZ, Math.min(cz, vMaxZ));\\n                    // Vector from nearest point to sphere center\\n                    const dx = cx - nearX;\\n                    const dy = cy - nearY;\\n                    const dz = cz - nearZ;\\n                    const distSq = dx * dx + dy * dy + dz * dz;\\n                    if (distSq >= radiusSq) {\\n                        continue;\\n                    }\\n                    let px;\\n                    let py;\\n                    let pz;\\n                    let penetration;\\n                    if (distSq > 1e-12) {\\n                        // Center is outside the voxel: push radially outward\\n                        const dist = Math.sqrt(distSq);\\n                        penetration = radius - dist;\\n                        const invDist = 1.0 / dist;\\n                        px = dx * invDist * penetration;\\n                        py = dy * invDist * penetration;\\n                        pz = dz * invDist * penetration;\\n                    }\\n                    else {\\n                        // Center is inside the voxel: push to nearest face + radius\\n                        // so the sphere surface ends up flush with the face\\n                        const distNegX = cx - vMinX;\\n                        const distPosX = vMaxX - cx;\\n                        const distNegY = cy - vMinY;\\n                        const distPosY = vMaxY - cy;\\n                        const distNegZ = cz - vMinZ;\\n                        const distPosZ = vMaxZ - cz;\\n                        const escapeX = distNegX < distPosX ? -(distNegX + radius) : (distPosX + radius);\\n                        const escapeY = distNegY < distPosY ? -(distNegY + radius) : (distPosY + radius);\\n                        const escapeZ = distNegZ < distPosZ ? -(distNegZ + radius) : (distPosZ + radius);\\n                        const absX = Math.abs(escapeX);\\n                        const absY = Math.abs(escapeY);\\n                        const absZ = Math.abs(escapeZ);\\n                        px = 0;\\n                        py = 0;\\n                        pz = 0;\\n                        if (absX <= absY && absX <= absZ) {\\n                            px = escapeX;\\n                            penetration = absX;\\n                        }\\n                        else if (absY <= absZ) {\\n                            py = escapeY;\\n                            penetration = absY;\\n                        }\\n                        else {\\n                            pz = escapeZ;\\n                            penetration = absZ;\\n                        }\\n                    }\\n                    if (penetration > bestPenetration) {\\n                        bestPenetration = penetration;\\n                        bestPushX = px;\\n                        bestPushY = py;\\n                        bestPushZ = pz;\\n                        found = true;\\n                    }\\n                }\\n            }\\n        }\\n        if (found) {\\n            out.x = bestPushX;\\n            out.y = bestPushY;\\n            out.z = bestPushZ;\\n        }\\n        return found;\\n    }\\n    /**\\n     * Find the single deepest penetrating voxel for the given vertical capsule.\\n     * The capsule is a line segment from (cx, cy - halfHeight, cz) to (cx, cy + halfHeight, cz)\\n     * swept by radius. For each voxel, the closest point on the segment to the AABB is found,\\n     * then a sphere-AABB penetration test is performed from that point.\\n     *\\n     * @param cx - Capsule center X.\\n     * @param cy - Capsule center Y.\\n     * @param cz - Capsule center Z.\\n     * @param halfHeight - Half-height of the capsule's inner line segment.\\n     * @param radius - Capsule radius.\\n     * @param out - Receives the push-out vector on success.\\n     * @returns True if a penetrating voxel was found.\\n     */\\n    resolveDeepestPenetrationCapsule(cx, cy, cz, halfHeight, radius, out) {\\n        const { voxelResolution, gridMinX, gridMinY, gridMinZ } = this;\\n        const radiusSq = radius * radius;\\n        const segBottomY = cy - halfHeight;\\n        const segTopY = cy + halfHeight;\\n        // Compute bounding box of the capsule in voxel indices\\n        const ixMin = Math.floor((cx - radius - gridMinX) / voxelResolution);\\n        const iyMin = Math.floor((segBottomY - radius - gridMinY) / voxelResolution);\\n        const izMin = Math.floor((cz - radius - gridMinZ) / voxelResolution);\\n        const ixMax = Math.floor((cx + radius - gridMinX) / voxelResolution);\\n        const iyMax = Math.floor((segTopY + radius - gridMinY) / voxelResolution);\\n        const izMax = Math.floor((cz + radius - gridMinZ) / voxelResolution);\\n        let bestPushX = 0;\\n        let bestPushY = 0;\\n        let bestPushZ = 0;\\n        let bestPenetration = PENETRATION_EPSILON;\\n        let found = false;\\n        for (let iz = izMin; iz <= izMax; iz++) {\\n            for (let iy = iyMin; iy <= iyMax; iy++) {\\n                for (let ix = ixMin; ix <= ixMax; ix++) {\\n                    if (!this.isVoxelSolid(ix, iy, iz)) {\\n                        continue;\\n                    }\\n                    // Compute the world-space AABB of this voxel\\n                    const vMinX = gridMinX + ix * voxelResolution;\\n                    const vMinY = gridMinY + iy * voxelResolution;\\n                    const vMinZ = gridMinZ + iz * voxelResolution;\\n                    const vMaxX = vMinX + voxelResolution;\\n                    const vMaxY = vMinY + voxelResolution;\\n                    const vMaxZ = vMinZ + voxelResolution;\\n                    // Find the closest Y on the capsule segment to this AABB.\\n                    // For a vertical segment, X and Z are fixed so we only optimize Y.\\n                    let segY;\\n                    if (segTopY < vMinY) {\\n                        // segment entirely below AABB\\n                        segY = segTopY;\\n                    }\\n                    else if (segBottomY > vMaxY) {\\n                        // segment entirely above AABB\\n                        segY = segBottomY;\\n                    }\\n                    else {\\n                        // ranges overlap - pick segment Y closest to AABB center\\n                        const aabbCenterY = (vMinY + vMaxY) * 0.5;\\n                        segY = Math.max(segBottomY, Math.min(segTopY, aabbCenterY));\\n                    }\\n                    // Now do sphere-AABB penetration from (cx, segY, cz)\\n                    const nearX = Math.max(vMinX, Math.min(cx, vMaxX));\\n                    const nearY = Math.max(vMinY, Math.min(segY, vMaxY));\\n                    const nearZ = Math.max(vMinZ, Math.min(cz, vMaxZ));\\n                    // Vector from nearest point to sphere center on segment\\n                    const dx = cx - nearX;\\n                    const dy = segY - nearY;\\n                    const dz = cz - nearZ;\\n                    const distSq = dx * dx + dy * dy + dz * dz;\\n                    if (distSq >= radiusSq) {\\n                        continue;\\n                    }\\n                    let px;\\n                    let py;\\n                    let pz;\\n                    let penetration;\\n                    if (distSq > 1e-12) {\\n                        // Sphere center is outside the voxel: push radially outward\\n                        const dist = Math.sqrt(distSq);\\n                        penetration = radius - dist;\\n                        const invDist = 1.0 / dist;\\n                        px = dx * invDist * penetration;\\n                        py = dy * invDist * penetration;\\n                        pz = dz * invDist * penetration;\\n                    }\\n                    else {\\n                        // Segment point is inside the voxel: push to nearest face + radius\\n                        // so the capsule surface ends up flush with the face\\n                        const distNegX = cx - vMinX;\\n                        const distPosX = vMaxX - cx;\\n                        const distNegY = segY - vMinY;\\n                        const distPosY = vMaxY - segY;\\n                        const distNegZ = cz - vMinZ;\\n                        const distPosZ = vMaxZ - cz;\\n                        const escapeX = distNegX < distPosX ? -(distNegX + radius) : (distPosX + radius);\\n                        const escapeY = distNegY < distPosY ? -(distNegY + radius) : (distPosY + radius);\\n                        const escapeZ = distNegZ < distPosZ ? -(distNegZ + radius) : (distPosZ + radius);\\n                        const absX = Math.abs(escapeX);\\n                        const absY = Math.abs(escapeY);\\n                        const absZ = Math.abs(escapeZ);\\n                        px = 0;\\n                        py = 0;\\n                        pz = 0;\\n                        if (absX <= absY && absX <= absZ) {\\n                            px = escapeX;\\n                            penetration = absX;\\n                        }\\n                        else if (absY <= absZ) {\\n                            py = escapeY;\\n                            penetration = absY;\\n                        }\\n                        else {\\n                            pz = escapeZ;\\n                            penetration = absZ;\\n                        }\\n                    }\\n                    if (penetration > bestPenetration) {\\n                        bestPenetration = penetration;\\n                        bestPushX = px;\\n                        bestPushY = py;\\n                        bestPushZ = pz;\\n                        found = true;\\n                    }\\n                }\\n            }\\n        }\\n        if (found) {\\n            out.x = bestPushX;\\n            out.y = bestPushY;\\n            out.z = bestPushZ;\\n        }\\n        return found;\\n    }\\n    /**\\n     * Test whether a voxel at the given grid indices is solid.\\n     *\\n     * @param ix - Global voxel X index.\\n     * @param iy - Global voxel Y index.\\n     * @param iz - Global voxel Z index.\\n     * @returns True if the voxel is solid.\\n     */\\n    isVoxelSolid(ix, iy, iz) {\\n        if (this.nodes.length === 0 ||\\n            ix < 0 || iy < 0 || iz < 0 ||\\n            ix >= this.numVoxelsX || iy >= this.numVoxelsY || iz >= this.numVoxelsZ) {\\n            return false;\\n        }\\n        const { leafSize, treeDepth } = this;\\n        // Convert voxel indices to block coordinates\\n        const blockX = Math.floor(ix / leafSize);\\n        const blockY = Math.floor(iy / leafSize);\\n        const blockZ = Math.floor(iz / leafSize);\\n        // Traverse octree from root to leaf\\n        let nodeIndex = 0;\\n        for (let level = treeDepth - 1; level >= 0; level--) {\\n            const node = this.nodes[nodeIndex] >>> 0;\\n            // Check for solid leaf sentinel first (has nonzero high byte)\\n            if (node === SOLID_LEAF_MARKER) {\\n                return true;\\n            }\\n            const childMask = (node >>> 24) & 0xFF;\\n            // If childMask is 0, this is a mixed leaf node\\n            if (childMask === 0) {\\n                return this.checkLeafByIndex(node, ix, iy, iz);\\n            }\\n            // Determine which octant the block falls into at this level\\n            const bitX = (blockX >>> level) & 1;\\n            const bitY = (blockY >>> level) & 1;\\n            const bitZ = (blockZ >>> level) & 1;\\n            const octant = (bitZ << 2) | (bitY << 1) | bitX;\\n            // Check if this octant has a child\\n            if ((childMask & (1 << octant)) === 0) {\\n                return false;\\n            }\\n            // Calculate child offset using popcount of lower bits\\n            const baseOffset = node & 0x00FFFFFF;\\n            const prefix = (1 << octant) - 1;\\n            const childOffset = popcount(childMask & prefix);\\n            nodeIndex = baseOffset + childOffset;\\n        }\\n        // We've reached the leaf level\\n        const node = this.nodes[nodeIndex] >>> 0;\\n        if (node === SOLID_LEAF_MARKER) {\\n            return true;\\n        }\\n        return this.checkLeafByIndex(node, ix, iy, iz);\\n    }\\n    /**\\n     * Check a mixed leaf node using voxel grid indices.\\n     * The solid leaf sentinel must be checked before calling this method.\\n     *\\n     * @param node - The mixed leaf node value (lower 24 bits = leafData index).\\n     * @param ix - Global voxel X index.\\n     * @param iy - Global voxel Y index.\\n     * @param iz - Global voxel Z index.\\n     * @returns True if the voxel is solid.\\n     */\\n    checkLeafByIndex(node, ix, iy, iz) {\\n        const leafDataIndex = node & 0x00FFFFFF;\\n        // Compute voxel coordinates within the 4x4x4 block\\n        const vx = ix & 3;\\n        const vy = iy & 3;\\n        const vz = iz & 3;\\n        // Bit index within the 64-bit mask: z * 16 + y * 4 + x\\n        const bitIndex = vz * 16 + vy * 4 + vx;\\n        // Read the appropriate 32-bit word (lo or hi)\\n        if (bitIndex < 32) {\\n            const lo = this.leafData[leafDataIndex * 2] >>> 0;\\n            return ((lo >>> bitIndex) & 1) === 1;\\n        }\\n        const hi = this.leafData[leafDataIndex * 2 + 1] >>> 0;\\n        return ((hi >>> (bitIndex - 32)) & 1) === 1;\\n    }\\n}\\n/**\\n * Legacy v1.0 adapter that negates X/Y on inputs and outputs to convert\\n * between PlayCanvas world space and the raw voxel data coordinate system.\\n */\\nclass FlippedVoxelCollision extends VoxelCollision {\\n    get flipXY() {\\n        return true;\\n    }\\n    querySurfaceNormal(x, y, z, rdx, rdy, rdz) {\\n        const result = super.querySurfaceNormal(-x, -y, z, -rdx, -rdy, rdz);\\n        result.nx = -result.nx;\\n        result.ny = -result.ny;\\n        return result;\\n    }\\n    queryRay(ox, oy, oz, dx, dy, dz, maxDist) {\\n        const hit = super.queryRay(-ox, -oy, oz, -dx, -dy, dz, maxDist);\\n        if (hit) {\\n            hit.x = -hit.x;\\n            hit.y = -hit.y;\\n        }\\n        return hit;\\n    }\\n    querySphere(cx, cy, cz, radius, out) {\\n        const result = super.querySphere(-cx, -cy, cz, radius, out);\\n        if (result) {\\n            out.x = -out.x;\\n            out.y = -out.y;\\n        }\\n        return result;\\n    }\\n    queryCapsule(cx, cy, cz, halfHeight, radius, out) {\\n        const result = super.queryCapsule(-cx, -cy, cz, halfHeight, radius, out);\\n        if (result) {\\n            out.x = -out.x;\\n            out.y = -out.y;\\n        }\\n        return result;\\n    }\\n    isFreeAt(x, y, z) {\\n        return super.isFreeAt(-x, -y, z);\\n    }\\n}\\n/**\\n * Load a VoxelCollision from a .voxel.json URL.\\n * The corresponding .voxel.bin is inferred by replacing the extension.\\n * Returns a FlippedVoxelCollision for legacy v1.0 data.\\n *\\n * @param jsonUrl - URL to the .voxel.json metadata file.\\n * @returns A promise resolving to a VoxelCollision instance.\\n */\\nconst loadVoxelCollision = async (jsonUrl) => {\\n    const metaResponse = await fetch(jsonUrl);\\n    if (!metaResponse.ok) {\\n        throw new Error(`Failed to fetch voxel metadata: ${metaResponse.statusText}`);\\n    }\\n    const metadata = await metaResponse.json();\\n    const binUrl = jsonUrl.replace('.voxel.json', '.voxel.bin');\\n    const binResponse = await fetch(binUrl);\\n    if (!binResponse.ok) {\\n        throw new Error(`Failed to fetch voxel binary: ${binResponse.statusText}`);\\n    }\\n    const buffer = await binResponse.arrayBuffer();\\n    const view = new Uint32Array(buffer);\\n    const nodes = view.slice(0, metadata.nodeCount);\\n    const leafData = view.slice(metadata.nodeCount, metadata.nodeCount + metadata.leafDataCount);\\n    const isLegacy = !metadata.version || parseFloat(metadata.version) < 1.1;\\n    if (isLegacy) {\\n        return new FlippedVoxelCollision(metadata, nodes, leafData);\\n    }\\n    return new VoxelCollision(metadata, nodes, leafData);\\n};\\n\\n// creates an observer proxy object to wrap some target object. fires events when properties change.\\nconst observe = (events, target) => {\\n    const members = new Set(Object.keys(target));\\n    return new Proxy(target, {\\n        set(target, property, value, receiver) {\\n            // prevent setting symbol properties\\n            if (typeof property === 'symbol') {\\n                console.error('Cannot set symbol property on target');\\n                return false;\\n            }\\n            // not allowed to set a new value on target\\n            if (!members.has(property)) {\\n                console.error('Cannot set new property on target');\\n                return false;\\n            }\\n            // set and fire event if value changed\\n            if (target[property] !== value) {\\n                const prev = target[property];\\n                target[property] = value;\\n                events.fire(`${property}:changed`, value, prev);\\n            }\\n            return true;\\n        }\\n    });\\n};\\n\\nvar deJson = {\\n\\t\\\"settings.performance-mode\\\": \\\"Leistungsmodus\\\",\\n\\t\\\"settings.gaming-controls\\\": \\\"Gaming-Steuerung\\\",\\n\\t\\\"settings.frame\\\": \\\"Einpassen\\\",\\n\\t\\\"settings.reset\\\": \\\"Zurücksetzen\\\",\\n\\t\\\"tooltip.play\\\": \\\"Wiedergabe\\\",\\n\\t\\\"tooltip.pause\\\": \\\"Pause\\\",\\n\\t\\\"tooltip.orbit-camera\\\": \\\"Umlaufkamera\\\",\\n\\t\\\"tooltip.fly-camera\\\": \\\"Flugkamera\\\",\\n\\t\\\"tooltip.walk-mode\\\": \\\"Gehmodus\\\",\\n\\t\\\"tooltip.reset-camera\\\": \\\"Kamera zurücksetzen\\\",\\n\\t\\\"tooltip.frame-scene\\\": \\\"Szene einpassen\\\",\\n\\t\\\"tooltip.show-collision\\\": \\\"Kollision anzeigen\\\",\\n\\t\\\"tooltip.settings\\\": \\\"Einstellungen\\\",\\n\\t\\\"tooltip.help\\\": \\\"Hilfe\\\",\\n\\t\\\"tooltip.enter-ar\\\": \\\"AR starten\\\",\\n\\t\\\"tooltip.enter-vr\\\": \\\"VR starten\\\",\\n\\t\\\"tooltip.fullscreen\\\": \\\"Vollbild\\\",\\n\\t\\\"help.tab.desktop\\\": \\\"Desktop\\\",\\n\\t\\\"help.tab.touch\\\": \\\"Touch\\\",\\n\\t\\\"help.section.orbit\\\": \\\"Umlaufmodus\\\",\\n\\t\\\"help.section.fly\\\": \\\"Flugmodus\\\",\\n\\t\\\"help.section.walk\\\": \\\"Gehmodus\\\",\\n\\t\\\"help.section.modes\\\": \\\"Modus wechseln\\\",\\n\\t\\\"help.action.orbit\\\": \\\"Umkreisen\\\",\\n\\t\\\"help.action.pan\\\": \\\"Schwenken\\\",\\n\\t\\\"help.action.zoom\\\": \\\"Zoomen\\\",\\n\\t\\\"help.action.set-focus\\\": \\\"Fokus setzen\\\",\\n\\t\\\"help.action.fly-to\\\": \\\"Fliegen zu\\\",\\n\\t\\\"help.action.fly-to-point\\\": \\\"Zum Punkt fliegen\\\",\\n\\t\\\"help.action.walk-to\\\": \\\"Gehen zu\\\",\\n\\t\\\"help.action.look-around\\\": \\\"Umsehen\\\",\\n\\t\\\"help.action.move\\\": \\\"Bewegen\\\",\\n\\t\\\"help.action.vertical\\\": \\\"Vertikal\\\",\\n\\t\\\"help.action.jump\\\": \\\"Springen\\\",\\n\\t\\\"help.action.run-slow\\\": \\\"Rennen / Gehen\\\",\\n\\t\\\"help.action.focus-point\\\": \\\"Fokuspunkt\\\",\\n\\t\\\"help.action.frame-scene\\\": \\\"Szene einpassen\\\",\\n\\t\\\"help.action.reset-camera\\\": \\\"Kamera zurücksetzen\\\",\\n\\t\\\"help.action.orbit-mode\\\": \\\"Umlaufmodus\\\",\\n\\t\\\"help.action.fly-mode\\\": \\\"Flugmodus\\\",\\n\\t\\\"help.action.toggle-walk\\\": \\\"Gehen umschalten\\\",\\n\\t\\\"help.action.toggle-gaming\\\": \\\"Gaming-Steuerung umschalten\\\",\\n\\t\\\"help.action.show-collision\\\": \\\"Kollision anzeigen\\\",\\n\\t\\\"help.action.play-pause\\\": \\\"Wiedergabe / Pause\\\",\\n\\t\\\"help.action.toggle-help\\\": \\\"Hilfe umschalten\\\",\\n\\t\\\"help.action.exit-cancel\\\": \\\"Beenden / Abbrechen\\\",\\n\\t\\\"help.key.left-click\\\": \\\"Linksklick\\\",\\n\\t\\\"help.key.left-click-drag\\\": \\\"Linksklick + Ziehen\\\",\\n\\t\\\"help.key.right-click-drag\\\": \\\"Rechtsklick + Ziehen\\\",\\n\\t\\\"help.key.mouse-wheel\\\": \\\"Mausrad\\\",\\n\\t\\\"help.key.mouse\\\": \\\"Maus\\\",\\n\\t\\\"help.key.double-click\\\": \\\"Doppelklick\\\",\\n\\t\\\"help.key.double-tap\\\": \\\"Doppeltippen\\\",\\n\\t\\\"help.key.tap\\\": \\\"Tippen\\\",\\n\\t\\\"help.key.touch-drag\\\": \\\"Berühren + Ziehen\\\",\\n\\t\\\"help.key.one-finger-drag\\\": \\\"Mit einem Finger ziehen\\\",\\n\\t\\\"help.key.two-finger-drag\\\": \\\"Mit zwei Fingern ziehen\\\",\\n\\t\\\"help.key.pinch\\\": \\\"Zwei-Finger-Zoom\\\",\\n\\t\\\"help.key.pinch-two-finger\\\": \\\"Zwei-Finger-Zoom / Ziehen\\\",\\n\\t\\\"help.key.joystick\\\": \\\"Joystick\\\",\\n\\t\\\"help.key.shift-ctrl\\\": \\\"Umschalt / Strg\\\",\\n\\t\\\"help.key.space\\\": \\\"Leertaste\\\",\\n\\t\\\"help.key.esc\\\": \\\"Esc\\\",\\n\\t\\\"xr-modal.title\\\": \\\"WebGL erforderlich\\\",\\n\\t\\\"xr-modal.message\\\": \\\"AR und VR werden vom WebGPU-Renderer nicht unterstützt. Mit OK wird der Viewer mit WebGL neu geladen.\\\",\\n\\t\\\"xr-modal.cancel\\\": \\\"Abbrechen\\\",\\n\\t\\\"xr-modal.ok\\\": \\\"OK\\\",\\n\\t\\\"walk-hint.desktop\\\": \\\"Zum Gehen klicken. WASD für freie Bewegung.\\\",\\n\\t\\\"walk-hint.touch-tap\\\": \\\"Zum Gehen tippen. Ziehen, um sich umzusehen.\\\",\\n\\t\\\"walk-hint.touch-gaming\\\": \\\"Mit dem Joystick bewegen. Ziehen, um sich umzusehen. Zum Springen tippen.\\\"\\n};\\n\\nvar enJson = {\\n\\t\\\"settings.performance-mode\\\": \\\"Performance Mode\\\",\\n\\t\\\"settings.gaming-controls\\\": \\\"Gaming Controls\\\",\\n\\t\\\"settings.frame\\\": \\\"Frame\\\",\\n\\t\\\"settings.reset\\\": \\\"Reset\\\",\\n\\t\\\"tooltip.play\\\": \\\"Play\\\",\\n\\t\\\"tooltip.pause\\\": \\\"Pause\\\",\\n\\t\\\"tooltip.orbit-camera\\\": \\\"Orbit Camera\\\",\\n\\t\\\"tooltip.fly-camera\\\": \\\"Fly Camera\\\",\\n\\t\\\"tooltip.walk-mode\\\": \\\"Walk Mode\\\",\\n\\t\\\"tooltip.reset-camera\\\": \\\"Reset Camera\\\",\\n\\t\\\"tooltip.frame-scene\\\": \\\"Frame Scene\\\",\\n\\t\\\"tooltip.show-collision\\\": \\\"Show Collision\\\",\\n\\t\\\"tooltip.settings\\\": \\\"Settings\\\",\\n\\t\\\"tooltip.help\\\": \\\"Help\\\",\\n\\t\\\"tooltip.enter-ar\\\": \\\"Enter AR\\\",\\n\\t\\\"tooltip.enter-vr\\\": \\\"Enter VR\\\",\\n\\t\\\"tooltip.fullscreen\\\": \\\"Fullscreen\\\",\\n\\t\\\"help.tab.desktop\\\": \\\"Desktop\\\",\\n\\t\\\"help.tab.touch\\\": \\\"Touch\\\",\\n\\t\\\"help.section.orbit\\\": \\\"Orbit Mode\\\",\\n\\t\\\"help.section.fly\\\": \\\"Fly Mode\\\",\\n\\t\\\"help.section.walk\\\": \\\"Walk Mode\\\",\\n\\t\\\"help.section.modes\\\": \\\"Mode Switching\\\",\\n\\t\\\"help.action.orbit\\\": \\\"Orbit\\\",\\n\\t\\\"help.action.pan\\\": \\\"Pan\\\",\\n\\t\\\"help.action.zoom\\\": \\\"Zoom\\\",\\n\\t\\\"help.action.set-focus\\\": \\\"Set Focus\\\",\\n\\t\\\"help.action.fly-to\\\": \\\"Fly To\\\",\\n\\t\\\"help.action.fly-to-point\\\": \\\"Fly to Point\\\",\\n\\t\\\"help.action.walk-to\\\": \\\"Walk To\\\",\\n\\t\\\"help.action.look-around\\\": \\\"Look Around\\\",\\n\\t\\\"help.action.move\\\": \\\"Move\\\",\\n\\t\\\"help.action.vertical\\\": \\\"Vertical\\\",\\n\\t\\\"help.action.jump\\\": \\\"Jump\\\",\\n\\t\\\"help.action.run-slow\\\": \\\"Run / Slow\\\",\\n\\t\\\"help.action.focus-point\\\": \\\"Focus Point\\\",\\n\\t\\\"help.action.frame-scene\\\": \\\"Frame Scene\\\",\\n\\t\\\"help.action.reset-camera\\\": \\\"Reset Camera\\\",\\n\\t\\\"help.action.orbit-mode\\\": \\\"Orbit Mode\\\",\\n\\t\\\"help.action.fly-mode\\\": \\\"Fly Mode\\\",\\n\\t\\\"help.action.toggle-walk\\\": \\\"Toggle Walk\\\",\\n\\t\\\"help.action.toggle-gaming\\\": \\\"Toggle Gaming Controls\\\",\\n\\t\\\"help.action.show-collision\\\": \\\"Show Collision\\\",\\n\\t\\\"help.action.play-pause\\\": \\\"Play / Pause\\\",\\n\\t\\\"help.action.toggle-help\\\": \\\"Toggle Help\\\",\\n\\t\\\"help.action.exit-cancel\\\": \\\"Exit / Cancel\\\",\\n\\t\\\"help.key.left-click\\\": \\\"Left Click\\\",\\n\\t\\\"help.key.left-click-drag\\\": \\\"Left Click + Drag\\\",\\n\\t\\\"help.key.right-click-drag\\\": \\\"Right Click + Drag\\\",\\n\\t\\\"help.key.mouse-wheel\\\": \\\"Mouse Wheel\\\",\\n\\t\\\"help.key.mouse\\\": \\\"Mouse\\\",\\n\\t\\\"help.key.double-click\\\": \\\"Double-click\\\",\\n\\t\\\"help.key.double-tap\\\": \\\"Double-tap\\\",\\n\\t\\\"help.key.tap\\\": \\\"Tap\\\",\\n\\t\\\"help.key.touch-drag\\\": \\\"Touch + Drag\\\",\\n\\t\\\"help.key.one-finger-drag\\\": \\\"One Finger Drag\\\",\\n\\t\\\"help.key.two-finger-drag\\\": \\\"Two Finger Drag\\\",\\n\\t\\\"help.key.pinch\\\": \\\"Pinch\\\",\\n\\t\\\"help.key.pinch-two-finger\\\": \\\"Pinch / Two Finger Drag\\\",\\n\\t\\\"help.key.joystick\\\": \\\"Joystick\\\",\\n\\t\\\"help.key.shift-ctrl\\\": \\\"Shift / Ctrl\\\",\\n\\t\\\"help.key.space\\\": \\\"Space\\\",\\n\\t\\\"help.key.esc\\\": \\\"Esc\\\",\\n\\t\\\"xr-modal.title\\\": \\\"WebGL Required\\\",\\n\\t\\\"xr-modal.message\\\": \\\"AR and VR are not supported on the WebGPU renderer. Pressing OK will reload the viewer with WebGL.\\\",\\n\\t\\\"xr-modal.cancel\\\": \\\"Cancel\\\",\\n\\t\\\"xr-modal.ok\\\": \\\"OK\\\",\\n\\t\\\"walk-hint.desktop\\\": \\\"Click to walk. WASD to move freely.\\\",\\n\\t\\\"walk-hint.touch-tap\\\": \\\"Tap to walk. Drag to look around.\\\",\\n\\t\\\"walk-hint.touch-gaming\\\": \\\"Use the joystick to move. Drag to look around. Tap to jump.\\\"\\n};\\n\\nvar esJson = {\\n\\t\\\"settings.performance-mode\\\": \\\"Modo rendimiento\\\",\\n\\t\\\"settings.gaming-controls\\\": \\\"Controles de juego\\\",\\n\\t\\\"settings.frame\\\": \\\"Encuadrar\\\",\\n\\t\\\"settings.reset\\\": \\\"Restablecer\\\",\\n\\t\\\"tooltip.play\\\": \\\"Reproducir\\\",\\n\\t\\\"tooltip.pause\\\": \\\"Pausar\\\",\\n\\t\\\"tooltip.orbit-camera\\\": \\\"Cámara orbital\\\",\\n\\t\\\"tooltip.fly-camera\\\": \\\"Cámara de vuelo\\\",\\n\\t\\\"tooltip.walk-mode\\\": \\\"Modo caminar\\\",\\n\\t\\\"tooltip.reset-camera\\\": \\\"Restablecer cámara\\\",\\n\\t\\\"tooltip.frame-scene\\\": \\\"Encuadrar escena\\\",\\n\\t\\\"tooltip.show-collision\\\": \\\"Mostrar colisión\\\",\\n\\t\\\"tooltip.settings\\\": \\\"Ajustes\\\",\\n\\t\\\"tooltip.help\\\": \\\"Ayuda\\\",\\n\\t\\\"tooltip.enter-ar\\\": \\\"Entrar en AR\\\",\\n\\t\\\"tooltip.enter-vr\\\": \\\"Entrar en VR\\\",\\n\\t\\\"tooltip.fullscreen\\\": \\\"Pantalla completa\\\",\\n\\t\\\"help.tab.desktop\\\": \\\"Escritorio\\\",\\n\\t\\\"help.tab.touch\\\": \\\"Táctil\\\",\\n\\t\\\"help.section.orbit\\\": \\\"Modo orbital\\\",\\n\\t\\\"help.section.fly\\\": \\\"Modo vuelo\\\",\\n\\t\\\"help.section.walk\\\": \\\"Modo caminar\\\",\\n\\t\\\"help.section.modes\\\": \\\"Cambio de modo\\\",\\n\\t\\\"help.action.orbit\\\": \\\"Orbitar\\\",\\n\\t\\\"help.action.pan\\\": \\\"Desplazar\\\",\\n\\t\\\"help.action.zoom\\\": \\\"Zoom\\\",\\n\\t\\\"help.action.set-focus\\\": \\\"Fijar foco\\\",\\n\\t\\\"help.action.fly-to\\\": \\\"Volar a\\\",\\n\\t\\\"help.action.fly-to-point\\\": \\\"Volar al punto\\\",\\n\\t\\\"help.action.walk-to\\\": \\\"Caminar a\\\",\\n\\t\\\"help.action.look-around\\\": \\\"Mirar alrededor\\\",\\n\\t\\\"help.action.move\\\": \\\"Mover\\\",\\n\\t\\\"help.action.vertical\\\": \\\"Vertical\\\",\\n\\t\\\"help.action.jump\\\": \\\"Saltar\\\",\\n\\t\\\"help.action.run-slow\\\": \\\"Correr / Lento\\\",\\n\\t\\\"help.action.focus-point\\\": \\\"Punto focal\\\",\\n\\t\\\"help.action.frame-scene\\\": \\\"Encuadrar escena\\\",\\n\\t\\\"help.action.reset-camera\\\": \\\"Restablecer cámara\\\",\\n\\t\\\"help.action.orbit-mode\\\": \\\"Modo orbital\\\",\\n\\t\\\"help.action.fly-mode\\\": \\\"Modo vuelo\\\",\\n\\t\\\"help.action.toggle-walk\\\": \\\"Alternar caminar\\\",\\n\\t\\\"help.action.toggle-gaming\\\": \\\"Alternar controles de juego\\\",\\n\\t\\\"help.action.show-collision\\\": \\\"Mostrar colisión\\\",\\n\\t\\\"help.action.play-pause\\\": \\\"Reproducir / Pausar\\\",\\n\\t\\\"help.action.toggle-help\\\": \\\"Alternar ayuda\\\",\\n\\t\\\"help.action.exit-cancel\\\": \\\"Salir / Cancelar\\\",\\n\\t\\\"help.key.left-click\\\": \\\"Clic izquierdo\\\",\\n\\t\\\"help.key.left-click-drag\\\": \\\"Clic izquierdo + arrastrar\\\",\\n\\t\\\"help.key.right-click-drag\\\": \\\"Clic derecho + arrastrar\\\",\\n\\t\\\"help.key.mouse-wheel\\\": \\\"Rueda del ratón\\\",\\n\\t\\\"help.key.mouse\\\": \\\"Ratón\\\",\\n\\t\\\"help.key.double-click\\\": \\\"Doble clic\\\",\\n\\t\\\"help.key.double-tap\\\": \\\"Doble toque\\\",\\n\\t\\\"help.key.tap\\\": \\\"Toque\\\",\\n\\t\\\"help.key.touch-drag\\\": \\\"Toque + arrastrar\\\",\\n\\t\\\"help.key.one-finger-drag\\\": \\\"Arrastre con un dedo\\\",\\n\\t\\\"help.key.two-finger-drag\\\": \\\"Arrastre con dos dedos\\\",\\n\\t\\\"help.key.pinch\\\": \\\"Pellizcar\\\",\\n\\t\\\"help.key.pinch-two-finger\\\": \\\"Pellizcar / Arrastre con dos dedos\\\",\\n\\t\\\"help.key.joystick\\\": \\\"Joystick\\\",\\n\\t\\\"help.key.shift-ctrl\\\": \\\"Mayús / Ctrl\\\",\\n\\t\\\"help.key.space\\\": \\\"Espacio\\\",\\n\\t\\\"help.key.esc\\\": \\\"Esc\\\",\\n\\t\\\"xr-modal.title\\\": \\\"Se requiere WebGL\\\",\\n\\t\\\"xr-modal.message\\\": \\\"AR y VR no son compatibles con el renderizador WebGPU. Al pulsar OK se recargará el visor con WebGL.\\\",\\n\\t\\\"xr-modal.cancel\\\": \\\"Cancelar\\\",\\n\\t\\\"xr-modal.ok\\\": \\\"OK\\\",\\n\\t\\\"walk-hint.desktop\\\": \\\"Haz clic para caminar. WASD para moverte libremente.\\\",\\n\\t\\\"walk-hint.touch-tap\\\": \\\"Toca para caminar. Arrastra para mirar alrededor.\\\",\\n\\t\\\"walk-hint.touch-gaming\\\": \\\"Usa el joystick para moverte. Arrastra para mirar. Toca para saltar.\\\"\\n};\\n\\nvar frJson = {\\n\\t\\\"settings.performance-mode\\\": \\\"Mode performance\\\",\\n\\t\\\"settings.gaming-controls\\\": \\\"Commandes de jeu\\\",\\n\\t\\\"settings.frame\\\": \\\"Cadrer\\\",\\n\\t\\\"settings.reset\\\": \\\"Réinitialiser\\\",\\n\\t\\\"tooltip.play\\\": \\\"Lecture\\\",\\n\\t\\\"tooltip.pause\\\": \\\"Pause\\\",\\n\\t\\\"tooltip.orbit-camera\\\": \\\"Caméra orbitale\\\",\\n\\t\\\"tooltip.fly-camera\\\": \\\"Caméra volante\\\",\\n\\t\\\"tooltip.walk-mode\\\": \\\"Mode marche\\\",\\n\\t\\\"tooltip.reset-camera\\\": \\\"Réinitialiser la caméra\\\",\\n\\t\\\"tooltip.frame-scene\\\": \\\"Cadrer la scène\\\",\\n\\t\\\"tooltip.show-collision\\\": \\\"Afficher les collisions\\\",\\n\\t\\\"tooltip.settings\\\": \\\"Paramètres\\\",\\n\\t\\\"tooltip.help\\\": \\\"Aide\\\",\\n\\t\\\"tooltip.enter-ar\\\": \\\"Entrer en AR\\\",\\n\\t\\\"tooltip.enter-vr\\\": \\\"Entrer en VR\\\",\\n\\t\\\"tooltip.fullscreen\\\": \\\"Plein écran\\\",\\n\\t\\\"help.tab.desktop\\\": \\\"Bureau\\\",\\n\\t\\\"help.tab.touch\\\": \\\"Tactile\\\",\\n\\t\\\"help.section.orbit\\\": \\\"Mode orbital\\\",\\n\\t\\\"help.section.fly\\\": \\\"Mode vol\\\",\\n\\t\\\"help.section.walk\\\": \\\"Mode marche\\\",\\n\\t\\\"help.section.modes\\\": \\\"Changement de mode\\\",\\n\\t\\\"help.action.orbit\\\": \\\"Orbiter\\\",\\n\\t\\\"help.action.pan\\\": \\\"Panoramique\\\",\\n\\t\\\"help.action.zoom\\\": \\\"Zoom\\\",\\n\\t\\\"help.action.set-focus\\\": \\\"Définir le focus\\\",\\n\\t\\\"help.action.fly-to\\\": \\\"Voler vers\\\",\\n\\t\\\"help.action.fly-to-point\\\": \\\"Voler vers le point\\\",\\n\\t\\\"help.action.walk-to\\\": \\\"Marcher vers\\\",\\n\\t\\\"help.action.look-around\\\": \\\"Regarder autour\\\",\\n\\t\\\"help.action.move\\\": \\\"Se déplacer\\\",\\n\\t\\\"help.action.vertical\\\": \\\"Vertical\\\",\\n\\t\\\"help.action.jump\\\": \\\"Sauter\\\",\\n\\t\\\"help.action.run-slow\\\": \\\"Courir / Lent\\\",\\n\\t\\\"help.action.focus-point\\\": \\\"Point focal\\\",\\n\\t\\\"help.action.frame-scene\\\": \\\"Cadrer la scène\\\",\\n\\t\\\"help.action.reset-camera\\\": \\\"Réinitialiser la caméra\\\",\\n\\t\\\"help.action.orbit-mode\\\": \\\"Mode orbital\\\",\\n\\t\\\"help.action.fly-mode\\\": \\\"Mode vol\\\",\\n\\t\\\"help.action.toggle-walk\\\": \\\"Basculer la marche\\\",\\n\\t\\\"help.action.toggle-gaming\\\": \\\"Basculer les commandes de jeu\\\",\\n\\t\\\"help.action.show-collision\\\": \\\"Afficher les collisions\\\",\\n\\t\\\"help.action.play-pause\\\": \\\"Lecture / Pause\\\",\\n\\t\\\"help.action.toggle-help\\\": \\\"Basculer l'aide\\\",\\n\\t\\\"help.action.exit-cancel\\\": \\\"Quitter / Annuler\\\",\\n\\t\\\"help.key.left-click\\\": \\\"Clic gauche\\\",\\n\\t\\\"help.key.left-click-drag\\\": \\\"Clic gauche + glisser\\\",\\n\\t\\\"help.key.right-click-drag\\\": \\\"Clic droit + glisser\\\",\\n\\t\\\"help.key.mouse-wheel\\\": \\\"Molette\\\",\\n\\t\\\"help.key.mouse\\\": \\\"Souris\\\",\\n\\t\\\"help.key.double-click\\\": \\\"Double clic\\\",\\n\\t\\\"help.key.double-tap\\\": \\\"Double tape\\\",\\n\\t\\\"help.key.tap\\\": \\\"Tape\\\",\\n\\t\\\"help.key.touch-drag\\\": \\\"Toucher + glisser\\\",\\n\\t\\\"help.key.one-finger-drag\\\": \\\"Glisser à un doigt\\\",\\n\\t\\\"help.key.two-finger-drag\\\": \\\"Glisser à deux doigts\\\",\\n\\t\\\"help.key.pinch\\\": \\\"Pincer\\\",\\n\\t\\\"help.key.pinch-two-finger\\\": \\\"Pincer / Glisser à deux doigts\\\",\\n\\t\\\"help.key.joystick\\\": \\\"Joystick\\\",\\n\\t\\\"help.key.shift-ctrl\\\": \\\"Maj / Ctrl\\\",\\n\\t\\\"help.key.space\\\": \\\"Espace\\\",\\n\\t\\\"help.key.esc\\\": \\\"Échap\\\",\\n\\t\\\"xr-modal.title\\\": \\\"WebGL requis\\\",\\n\\t\\\"xr-modal.message\\\": \\\"L'AR et la VR ne sont pas prises en charge par le moteur de rendu WebGPU. Cliquer sur OK rechargera le visualiseur avec WebGL.\\\",\\n\\t\\\"xr-modal.cancel\\\": \\\"Annuler\\\",\\n\\t\\\"xr-modal.ok\\\": \\\"OK\\\",\\n\\t\\\"walk-hint.desktop\\\": \\\"Cliquez pour marcher. WASD pour vous déplacer librement.\\\",\\n\\t\\\"walk-hint.touch-tap\\\": \\\"Tapez pour marcher. Glissez pour regarder autour.\\\",\\n\\t\\\"walk-hint.touch-gaming\\\": \\\"Utilisez le joystick pour vous déplacer. Glissez pour regarder. Tapez pour sauter.\\\"\\n};\\n\\nvar jaJson = {\\n\\t\\\"settings.performance-mode\\\": \\\"パフォーマンスモード\\\",\\n\\t\\\"settings.gaming-controls\\\": \\\"ゲームコントロール\\\",\\n\\t\\\"settings.frame\\\": \\\"フィット\\\",\\n\\t\\\"settings.reset\\\": \\\"リセット\\\",\\n\\t\\\"tooltip.play\\\": \\\"再生\\\",\\n\\t\\\"tooltip.pause\\\": \\\"一時停止\\\",\\n\\t\\\"tooltip.orbit-camera\\\": \\\"オービットカメラ\\\",\\n\\t\\\"tooltip.fly-camera\\\": \\\"フライカメラ\\\",\\n\\t\\\"tooltip.walk-mode\\\": \\\"ウォークモード\\\",\\n\\t\\\"tooltip.reset-camera\\\": \\\"カメラをリセット\\\",\\n\\t\\\"tooltip.frame-scene\\\": \\\"シーンにフィット\\\",\\n\\t\\\"tooltip.show-collision\\\": \\\"コリジョンを表示\\\",\\n\\t\\\"tooltip.settings\\\": \\\"設定\\\",\\n\\t\\\"tooltip.help\\\": \\\"ヘルプ\\\",\\n\\t\\\"tooltip.enter-ar\\\": \\\"ARを開始\\\",\\n\\t\\\"tooltip.enter-vr\\\": \\\"VRを開始\\\",\\n\\t\\\"tooltip.fullscreen\\\": \\\"全画面表示\\\",\\n\\t\\\"help.tab.desktop\\\": \\\"デスクトップ\\\",\\n\\t\\\"help.tab.touch\\\": \\\"タッチ\\\",\\n\\t\\\"help.section.orbit\\\": \\\"オービットモード\\\",\\n\\t\\\"help.section.fly\\\": \\\"フライモード\\\",\\n\\t\\\"help.section.walk\\\": \\\"ウォークモード\\\",\\n\\t\\\"help.section.modes\\\": \\\"モード切り替え\\\",\\n\\t\\\"help.action.orbit\\\": \\\"オービット\\\",\\n\\t\\\"help.action.pan\\\": \\\"パン\\\",\\n\\t\\\"help.action.zoom\\\": \\\"ズーム\\\",\\n\\t\\\"help.action.set-focus\\\": \\\"フォーカスを設定\\\",\\n\\t\\\"help.action.fly-to\\\": \\\"飛ぶ\\\",\\n\\t\\\"help.action.fly-to-point\\\": \\\"ポイントへ飛ぶ\\\",\\n\\t\\\"help.action.walk-to\\\": \\\"歩く\\\",\\n\\t\\\"help.action.look-around\\\": \\\"周りを見る\\\",\\n\\t\\\"help.action.move\\\": \\\"移動\\\",\\n\\t\\\"help.action.vertical\\\": \\\"垂直\\\",\\n\\t\\\"help.action.jump\\\": \\\"ジャンプ\\\",\\n\\t\\\"help.action.run-slow\\\": \\\"走る / 歩く\\\",\\n\\t\\\"help.action.focus-point\\\": \\\"フォーカスポイント\\\",\\n\\t\\\"help.action.frame-scene\\\": \\\"シーンにフィット\\\",\\n\\t\\\"help.action.reset-camera\\\": \\\"カメラをリセット\\\",\\n\\t\\\"help.action.orbit-mode\\\": \\\"オービットモード\\\",\\n\\t\\\"help.action.fly-mode\\\": \\\"フライモード\\\",\\n\\t\\\"help.action.toggle-walk\\\": \\\"ウォークを切り替え\\\",\\n\\t\\\"help.action.toggle-gaming\\\": \\\"ゲームコントロールを切り替え\\\",\\n\\t\\\"help.action.show-collision\\\": \\\"コリジョンを表示\\\",\\n\\t\\\"help.action.play-pause\\\": \\\"再生 / 一時停止\\\",\\n\\t\\\"help.action.toggle-help\\\": \\\"ヘルプを切り替え\\\",\\n\\t\\\"help.action.exit-cancel\\\": \\\"終了 / キャンセル\\\",\\n\\t\\\"help.key.left-click\\\": \\\"左クリック\\\",\\n\\t\\\"help.key.left-click-drag\\\": \\\"左クリック + ドラッグ\\\",\\n\\t\\\"help.key.right-click-drag\\\": \\\"右クリック + ドラッグ\\\",\\n\\t\\\"help.key.mouse-wheel\\\": \\\"マウスホイール\\\",\\n\\t\\\"help.key.mouse\\\": \\\"マウス\\\",\\n\\t\\\"help.key.double-click\\\": \\\"ダブルクリック\\\",\\n\\t\\\"help.key.double-tap\\\": \\\"ダブルタップ\\\",\\n\\t\\\"help.key.tap\\\": \\\"タップ\\\",\\n\\t\\\"help.key.touch-drag\\\": \\\"タッチ + ドラッグ\\\",\\n\\t\\\"help.key.one-finger-drag\\\": \\\"1本指でドラッグ\\\",\\n\\t\\\"help.key.two-finger-drag\\\": \\\"2本指でドラッグ\\\",\\n\\t\\\"help.key.pinch\\\": \\\"ピンチ\\\",\\n\\t\\\"help.key.pinch-two-finger\\\": \\\"ピンチ / 2本指でドラッグ\\\",\\n\\t\\\"help.key.joystick\\\": \\\"ジョイスティック\\\",\\n\\t\\\"help.key.shift-ctrl\\\": \\\"Shift / Ctrl\\\",\\n\\t\\\"help.key.space\\\": \\\"スペース\\\",\\n\\t\\\"help.key.esc\\\": \\\"Esc\\\",\\n\\t\\\"xr-modal.title\\\": \\\"WebGLが必要です\\\",\\n\\t\\\"xr-modal.message\\\": \\\"ARとVRはWebGPUレンダラーでは利用できません。OKを押すとWebGLでビューアーを再読み込みします。\\\",\\n\\t\\\"xr-modal.cancel\\\": \\\"キャンセル\\\",\\n\\t\\\"xr-modal.ok\\\": \\\"OK\\\",\\n\\t\\\"walk-hint.desktop\\\": \\\"クリックで歩行。WASDで自由に移動。\\\",\\n\\t\\\"walk-hint.touch-tap\\\": \\\"タップで歩行。ドラッグで視点移動。\\\",\\n\\t\\\"walk-hint.touch-gaming\\\": \\\"ジョイスティックで移動。ドラッグで視点移動。タップでジャンプ。\\\"\\n};\\n\\nvar koJson = {\\n\\t\\\"settings.performance-mode\\\": \\\"성능 모드\\\",\\n\\t\\\"settings.gaming-controls\\\": \\\"게임 컨트롤\\\",\\n\\t\\\"settings.frame\\\": \\\"맞춤\\\",\\n\\t\\\"settings.reset\\\": \\\"재설정\\\",\\n\\t\\\"tooltip.play\\\": \\\"재생\\\",\\n\\t\\\"tooltip.pause\\\": \\\"일시 정지\\\",\\n\\t\\\"tooltip.orbit-camera\\\": \\\"오빗 카메라\\\",\\n\\t\\\"tooltip.fly-camera\\\": \\\"플라이 카메라\\\",\\n\\t\\\"tooltip.walk-mode\\\": \\\"워크 모드\\\",\\n\\t\\\"tooltip.reset-camera\\\": \\\"카메라 재설정\\\",\\n\\t\\\"tooltip.frame-scene\\\": \\\"씬에 맞춤\\\",\\n\\t\\\"tooltip.show-collision\\\": \\\"충돌 표시\\\",\\n\\t\\\"tooltip.settings\\\": \\\"설정\\\",\\n\\t\\\"tooltip.help\\\": \\\"도움말\\\",\\n\\t\\\"tooltip.enter-ar\\\": \\\"AR 시작\\\",\\n\\t\\\"tooltip.enter-vr\\\": \\\"VR 시작\\\",\\n\\t\\\"tooltip.fullscreen\\\": \\\"전체 화면\\\",\\n\\t\\\"help.tab.desktop\\\": \\\"데스크톱\\\",\\n\\t\\\"help.tab.touch\\\": \\\"터치\\\",\\n\\t\\\"help.section.orbit\\\": \\\"오빗 모드\\\",\\n\\t\\\"help.section.fly\\\": \\\"플라이 모드\\\",\\n\\t\\\"help.section.walk\\\": \\\"워크 모드\\\",\\n\\t\\\"help.section.modes\\\": \\\"모드 전환\\\",\\n\\t\\\"help.action.orbit\\\": \\\"오빗\\\",\\n\\t\\\"help.action.pan\\\": \\\"팬\\\",\\n\\t\\\"help.action.zoom\\\": \\\"줌\\\",\\n\\t\\\"help.action.set-focus\\\": \\\"포커스 설정\\\",\\n\\t\\\"help.action.fly-to\\\": \\\"비행\\\",\\n\\t\\\"help.action.fly-to-point\\\": \\\"지점으로 비행\\\",\\n\\t\\\"help.action.walk-to\\\": \\\"걷기\\\",\\n\\t\\\"help.action.look-around\\\": \\\"둘러보기\\\",\\n\\t\\\"help.action.move\\\": \\\"이동\\\",\\n\\t\\\"help.action.vertical\\\": \\\"수직\\\",\\n\\t\\\"help.action.jump\\\": \\\"점프\\\",\\n\\t\\\"help.action.run-slow\\\": \\\"달리기 / 천천히\\\",\\n\\t\\\"help.action.focus-point\\\": \\\"포커스 포인트\\\",\\n\\t\\\"help.action.frame-scene\\\": \\\"씬에 맞춤\\\",\\n\\t\\\"help.action.reset-camera\\\": \\\"카메라 재설정\\\",\\n\\t\\\"help.action.orbit-mode\\\": \\\"오빗 모드\\\",\\n\\t\\\"help.action.fly-mode\\\": \\\"플라이 모드\\\",\\n\\t\\\"help.action.toggle-walk\\\": \\\"워크 전환\\\",\\n\\t\\\"help.action.toggle-gaming\\\": \\\"게임 컨트롤 전환\\\",\\n\\t\\\"help.action.show-collision\\\": \\\"충돌 표시\\\",\\n\\t\\\"help.action.play-pause\\\": \\\"재생 / 일시 정지\\\",\\n\\t\\\"help.action.toggle-help\\\": \\\"도움말 전환\\\",\\n\\t\\\"help.action.exit-cancel\\\": \\\"나가기 / 취소\\\",\\n\\t\\\"help.key.left-click\\\": \\\"왼쪽 클릭\\\",\\n\\t\\\"help.key.left-click-drag\\\": \\\"왼쪽 클릭 + 드래그\\\",\\n\\t\\\"help.key.right-click-drag\\\": \\\"오른쪽 클릭 + 드래그\\\",\\n\\t\\\"help.key.mouse-wheel\\\": \\\"마우스 휠\\\",\\n\\t\\\"help.key.mouse\\\": \\\"마우스\\\",\\n\\t\\\"help.key.double-click\\\": \\\"더블 클릭\\\",\\n\\t\\\"help.key.double-tap\\\": \\\"더블 탭\\\",\\n\\t\\\"help.key.tap\\\": \\\"탭\\\",\\n\\t\\\"help.key.touch-drag\\\": \\\"터치 + 드래그\\\",\\n\\t\\\"help.key.one-finger-drag\\\": \\\"한 손가락 드래그\\\",\\n\\t\\\"help.key.two-finger-drag\\\": \\\"두 손가락 드래그\\\",\\n\\t\\\"help.key.pinch\\\": \\\"핀치\\\",\\n\\t\\\"help.key.pinch-two-finger\\\": \\\"핀치 / 두 손가락 드래그\\\",\\n\\t\\\"help.key.joystick\\\": \\\"조이스틱\\\",\\n\\t\\\"help.key.shift-ctrl\\\": \\\"Shift / Ctrl\\\",\\n\\t\\\"help.key.space\\\": \\\"스페이스\\\",\\n\\t\\\"help.key.esc\\\": \\\"Esc\\\",\\n\\t\\\"xr-modal.title\\\": \\\"WebGL 필요\\\",\\n\\t\\\"xr-modal.message\\\": \\\"AR과 VR은 WebGPU 렌더러에서 지원되지 않습니다. 확인을 누르면 WebGL로 뷰어를 다시 불러옵니다.\\\",\\n\\t\\\"xr-modal.cancel\\\": \\\"취소\\\",\\n\\t\\\"xr-modal.ok\\\": \\\"확인\\\",\\n\\t\\\"walk-hint.desktop\\\": \\\"클릭하여 걷기. WASD로 자유롭게 이동.\\\",\\n\\t\\\"walk-hint.touch-tap\\\": \\\"탭하여 걷기. 드래그하여 둘러보기.\\\",\\n\\t\\\"walk-hint.touch-gaming\\\": \\\"조이스틱으로 이동. 드래그하여 둘러보기. 탭하여 점프.\\\"\\n};\\n\\nvar ptBRJson = {\\n\\t\\\"settings.performance-mode\\\": \\\"Modo de desempenho\\\",\\n\\t\\\"settings.gaming-controls\\\": \\\"Controles de jogo\\\",\\n\\t\\\"settings.frame\\\": \\\"Enquadrar\\\",\\n\\t\\\"settings.reset\\\": \\\"Redefinir\\\",\\n\\t\\\"tooltip.play\\\": \\\"Reproduzir\\\",\\n\\t\\\"tooltip.pause\\\": \\\"Pausar\\\",\\n\\t\\\"tooltip.orbit-camera\\\": \\\"Câmera orbital\\\",\\n\\t\\\"tooltip.fly-camera\\\": \\\"Câmera de voo\\\",\\n\\t\\\"tooltip.walk-mode\\\": \\\"Modo caminhar\\\",\\n\\t\\\"tooltip.reset-camera\\\": \\\"Redefinir câmera\\\",\\n\\t\\\"tooltip.frame-scene\\\": \\\"Enquadrar cena\\\",\\n\\t\\\"tooltip.show-collision\\\": \\\"Mostrar colisão\\\",\\n\\t\\\"tooltip.settings\\\": \\\"Configurações\\\",\\n\\t\\\"tooltip.help\\\": \\\"Ajuda\\\",\\n\\t\\\"tooltip.enter-ar\\\": \\\"Entrar em AR\\\",\\n\\t\\\"tooltip.enter-vr\\\": \\\"Entrar em VR\\\",\\n\\t\\\"tooltip.fullscreen\\\": \\\"Tela cheia\\\",\\n\\t\\\"help.tab.desktop\\\": \\\"Desktop\\\",\\n\\t\\\"help.tab.touch\\\": \\\"Toque\\\",\\n\\t\\\"help.section.orbit\\\": \\\"Modo orbital\\\",\\n\\t\\\"help.section.fly\\\": \\\"Modo voo\\\",\\n\\t\\\"help.section.walk\\\": \\\"Modo caminhar\\\",\\n\\t\\\"help.section.modes\\\": \\\"Troca de modo\\\",\\n\\t\\\"help.action.orbit\\\": \\\"Orbitar\\\",\\n\\t\\\"help.action.pan\\\": \\\"Deslocar\\\",\\n\\t\\\"help.action.zoom\\\": \\\"Zoom\\\",\\n\\t\\\"help.action.set-focus\\\": \\\"Definir foco\\\",\\n\\t\\\"help.action.fly-to\\\": \\\"Voar para\\\",\\n\\t\\\"help.action.fly-to-point\\\": \\\"Voar até o ponto\\\",\\n\\t\\\"help.action.walk-to\\\": \\\"Caminhar para\\\",\\n\\t\\\"help.action.look-around\\\": \\\"Olhar em volta\\\",\\n\\t\\\"help.action.move\\\": \\\"Mover\\\",\\n\\t\\\"help.action.vertical\\\": \\\"Vertical\\\",\\n\\t\\\"help.action.jump\\\": \\\"Pular\\\",\\n\\t\\\"help.action.run-slow\\\": \\\"Correr / Devagar\\\",\\n\\t\\\"help.action.focus-point\\\": \\\"Ponto focal\\\",\\n\\t\\\"help.action.frame-scene\\\": \\\"Enquadrar cena\\\",\\n\\t\\\"help.action.reset-camera\\\": \\\"Redefinir câmera\\\",\\n\\t\\\"help.action.orbit-mode\\\": \\\"Modo orbital\\\",\\n\\t\\\"help.action.fly-mode\\\": \\\"Modo voo\\\",\\n\\t\\\"help.action.toggle-walk\\\": \\\"Alternar caminhar\\\",\\n\\t\\\"help.action.toggle-gaming\\\": \\\"Alternar controles de jogo\\\",\\n\\t\\\"help.action.show-collision\\\": \\\"Mostrar colisão\\\",\\n\\t\\\"help.action.play-pause\\\": \\\"Reproduzir / Pausar\\\",\\n\\t\\\"help.action.toggle-help\\\": \\\"Alternar ajuda\\\",\\n\\t\\\"help.action.exit-cancel\\\": \\\"Sair / Cancelar\\\",\\n\\t\\\"help.key.left-click\\\": \\\"Clique esquerdo\\\",\\n\\t\\\"help.key.left-click-drag\\\": \\\"Clique esquerdo + arrastar\\\",\\n\\t\\\"help.key.right-click-drag\\\": \\\"Clique direito + arrastar\\\",\\n\\t\\\"help.key.mouse-wheel\\\": \\\"Roda do mouse\\\",\\n\\t\\\"help.key.mouse\\\": \\\"Mouse\\\",\\n\\t\\\"help.key.double-click\\\": \\\"Clique duplo\\\",\\n\\t\\\"help.key.double-tap\\\": \\\"Toque duplo\\\",\\n\\t\\\"help.key.tap\\\": \\\"Toque\\\",\\n\\t\\\"help.key.touch-drag\\\": \\\"Toque + arrastar\\\",\\n\\t\\\"help.key.one-finger-drag\\\": \\\"Arrastar com um dedo\\\",\\n\\t\\\"help.key.two-finger-drag\\\": \\\"Arrastar com dois dedos\\\",\\n\\t\\\"help.key.pinch\\\": \\\"Pinçar\\\",\\n\\t\\\"help.key.pinch-two-finger\\\": \\\"Pinçar / Arrastar com dois dedos\\\",\\n\\t\\\"help.key.joystick\\\": \\\"Joystick\\\",\\n\\t\\\"help.key.shift-ctrl\\\": \\\"Shift / Ctrl\\\",\\n\\t\\\"help.key.space\\\": \\\"Espaço\\\",\\n\\t\\\"help.key.esc\\\": \\\"Esc\\\",\\n\\t\\\"xr-modal.title\\\": \\\"WebGL necessário\\\",\\n\\t\\\"xr-modal.message\\\": \\\"AR e VR não são compatíveis com o renderizador WebGPU. Ao pressionar OK, o visualizador será recarregado com WebGL.\\\",\\n\\t\\\"xr-modal.cancel\\\": \\\"Cancelar\\\",\\n\\t\\\"xr-modal.ok\\\": \\\"OK\\\",\\n\\t\\\"walk-hint.desktop\\\": \\\"Clique para caminhar. WASD para se mover livremente.\\\",\\n\\t\\\"walk-hint.touch-tap\\\": \\\"Toque para caminhar. Arraste para olhar em volta.\\\",\\n\\t\\\"walk-hint.touch-gaming\\\": \\\"Use o joystick para se mover. Arraste para olhar. Toque para pular.\\\"\\n};\\n\\nvar ruJson = {\\n\\t\\\"settings.performance-mode\\\": \\\"Режим производительности\\\",\\n\\t\\\"settings.gaming-controls\\\": \\\"Игровое управление\\\",\\n\\t\\\"settings.frame\\\": \\\"Кадрировать\\\",\\n\\t\\\"settings.reset\\\": \\\"Сбросить\\\",\\n\\t\\\"tooltip.play\\\": \\\"Воспроизвести\\\",\\n\\t\\\"tooltip.pause\\\": \\\"Пауза\\\",\\n\\t\\\"tooltip.orbit-camera\\\": \\\"Орбитальная камера\\\",\\n\\t\\\"tooltip.fly-camera\\\": \\\"Полётная камера\\\",\\n\\t\\\"tooltip.walk-mode\\\": \\\"Режим ходьбы\\\",\\n\\t\\\"tooltip.reset-camera\\\": \\\"Сбросить камеру\\\",\\n\\t\\\"tooltip.frame-scene\\\": \\\"Кадрировать сцену\\\",\\n\\t\\\"tooltip.show-collision\\\": \\\"Показать коллизию\\\",\\n\\t\\\"tooltip.settings\\\": \\\"Настройки\\\",\\n\\t\\\"tooltip.help\\\": \\\"Справка\\\",\\n\\t\\\"tooltip.enter-ar\\\": \\\"Войти в AR\\\",\\n\\t\\\"tooltip.enter-vr\\\": \\\"Войти в VR\\\",\\n\\t\\\"tooltip.fullscreen\\\": \\\"Полный экран\\\",\\n\\t\\\"help.tab.desktop\\\": \\\"Десктоп\\\",\\n\\t\\\"help.tab.touch\\\": \\\"Сенсор\\\",\\n\\t\\\"help.section.orbit\\\": \\\"Орбитальный режим\\\",\\n\\t\\\"help.section.fly\\\": \\\"Режим полёта\\\",\\n\\t\\\"help.section.walk\\\": \\\"Режим ходьбы\\\",\\n\\t\\\"help.section.modes\\\": \\\"Смена режимов\\\",\\n\\t\\\"help.action.orbit\\\": \\\"Вращение\\\",\\n\\t\\\"help.action.pan\\\": \\\"Панорама\\\",\\n\\t\\\"help.action.zoom\\\": \\\"Масштаб\\\",\\n\\t\\\"help.action.set-focus\\\": \\\"Задать фокус\\\",\\n\\t\\\"help.action.fly-to\\\": \\\"Лететь к\\\",\\n\\t\\\"help.action.fly-to-point\\\": \\\"Лететь к точке\\\",\\n\\t\\\"help.action.walk-to\\\": \\\"Идти к\\\",\\n\\t\\\"help.action.look-around\\\": \\\"Осмотреться\\\",\\n\\t\\\"help.action.move\\\": \\\"Движение\\\",\\n\\t\\\"help.action.vertical\\\": \\\"Вертикально\\\",\\n\\t\\\"help.action.jump\\\": \\\"Прыжок\\\",\\n\\t\\\"help.action.run-slow\\\": \\\"Бег / Медленно\\\",\\n\\t\\\"help.action.focus-point\\\": \\\"Точка фокуса\\\",\\n\\t\\\"help.action.frame-scene\\\": \\\"Кадрировать сцену\\\",\\n\\t\\\"help.action.reset-camera\\\": \\\"Сбросить камеру\\\",\\n\\t\\\"help.action.orbit-mode\\\": \\\"Орбитальный режим\\\",\\n\\t\\\"help.action.fly-mode\\\": \\\"Режим полёта\\\",\\n\\t\\\"help.action.toggle-walk\\\": \\\"Переключить ходьбу\\\",\\n\\t\\\"help.action.toggle-gaming\\\": \\\"Переключить игровое управление\\\",\\n\\t\\\"help.action.show-collision\\\": \\\"Показать коллизию\\\",\\n\\t\\\"help.action.play-pause\\\": \\\"Воспроизведение / Пауза\\\",\\n\\t\\\"help.action.toggle-help\\\": \\\"Переключить справку\\\",\\n\\t\\\"help.action.exit-cancel\\\": \\\"Выход / Отмена\\\",\\n\\t\\\"help.key.left-click\\\": \\\"Левый клик\\\",\\n\\t\\\"help.key.left-click-drag\\\": \\\"Левый клик + перетаскивание\\\",\\n\\t\\\"help.key.right-click-drag\\\": \\\"Правый клик + перетаскивание\\\",\\n\\t\\\"help.key.mouse-wheel\\\": \\\"Колесо мыши\\\",\\n\\t\\\"help.key.mouse\\\": \\\"Мышь\\\",\\n\\t\\\"help.key.double-click\\\": \\\"Двойной клик\\\",\\n\\t\\\"help.key.double-tap\\\": \\\"Двойной тап\\\",\\n\\t\\\"help.key.tap\\\": \\\"Тап\\\",\\n\\t\\\"help.key.touch-drag\\\": \\\"Касание + перетаскивание\\\",\\n\\t\\\"help.key.one-finger-drag\\\": \\\"Перетаскивание одним пальцем\\\",\\n\\t\\\"help.key.two-finger-drag\\\": \\\"Перетаскивание двумя пальцами\\\",\\n\\t\\\"help.key.pinch\\\": \\\"Щипок\\\",\\n\\t\\\"help.key.pinch-two-finger\\\": \\\"Щипок / Перетаскивание двумя пальцами\\\",\\n\\t\\\"help.key.joystick\\\": \\\"Джойстик\\\",\\n\\t\\\"help.key.shift-ctrl\\\": \\\"Shift / Ctrl\\\",\\n\\t\\\"help.key.space\\\": \\\"Пробел\\\",\\n\\t\\\"help.key.esc\\\": \\\"Esc\\\",\\n\\t\\\"xr-modal.title\\\": \\\"Требуется WebGL\\\",\\n\\t\\\"xr-modal.message\\\": \\\"AR и VR не поддерживаются рендером WebGPU. Нажмите OK, чтобы перезагрузить просмотрщик с WebGL.\\\",\\n\\t\\\"xr-modal.cancel\\\": \\\"Отмена\\\",\\n\\t\\\"xr-modal.ok\\\": \\\"OK\\\",\\n\\t\\\"walk-hint.desktop\\\": \\\"Кликните для ходьбы. WASD для свободного движения.\\\",\\n\\t\\\"walk-hint.touch-tap\\\": \\\"Тапните для ходьбы. Перетаскивайте, чтобы осмотреться.\\\",\\n\\t\\\"walk-hint.touch-gaming\\\": \\\"Используйте джойстик для движения. Перетаскивайте, чтобы осмотреться. Тапните для прыжка.\\\"\\n};\\n\\nvar zhCNJson = {\\n\\t\\\"settings.performance-mode\\\": \\\"性能模式\\\",\\n\\t\\\"settings.gaming-controls\\\": \\\"游戏控制\\\",\\n\\t\\\"settings.frame\\\": \\\"适应\\\",\\n\\t\\\"settings.reset\\\": \\\"重置\\\",\\n\\t\\\"tooltip.play\\\": \\\"播放\\\",\\n\\t\\\"tooltip.pause\\\": \\\"暂停\\\",\\n\\t\\\"tooltip.orbit-camera\\\": \\\"环绕相机\\\",\\n\\t\\\"tooltip.fly-camera\\\": \\\"飞行相机\\\",\\n\\t\\\"tooltip.walk-mode\\\": \\\"行走模式\\\",\\n\\t\\\"tooltip.reset-camera\\\": \\\"重置相机\\\",\\n\\t\\\"tooltip.frame-scene\\\": \\\"适应场景\\\",\\n\\t\\\"tooltip.show-collision\\\": \\\"显示碰撞\\\",\\n\\t\\\"tooltip.settings\\\": \\\"设置\\\",\\n\\t\\\"tooltip.help\\\": \\\"帮助\\\",\\n\\t\\\"tooltip.enter-ar\\\": \\\"进入 AR\\\",\\n\\t\\\"tooltip.enter-vr\\\": \\\"进入 VR\\\",\\n\\t\\\"tooltip.fullscreen\\\": \\\"全屏\\\",\\n\\t\\\"help.tab.desktop\\\": \\\"桌面\\\",\\n\\t\\\"help.tab.touch\\\": \\\"触屏\\\",\\n\\t\\\"help.section.orbit\\\": \\\"环绕模式\\\",\\n\\t\\\"help.section.fly\\\": \\\"飞行模式\\\",\\n\\t\\\"help.section.walk\\\": \\\"行走模式\\\",\\n\\t\\\"help.section.modes\\\": \\\"模式切换\\\",\\n\\t\\\"help.action.orbit\\\": \\\"环绕\\\",\\n\\t\\\"help.action.pan\\\": \\\"平移\\\",\\n\\t\\\"help.action.zoom\\\": \\\"缩放\\\",\\n\\t\\\"help.action.set-focus\\\": \\\"设置焦点\\\",\\n\\t\\\"help.action.fly-to\\\": \\\"飞至\\\",\\n\\t\\\"help.action.fly-to-point\\\": \\\"飞至该点\\\",\\n\\t\\\"help.action.walk-to\\\": \\\"走到\\\",\\n\\t\\\"help.action.look-around\\\": \\\"环顾\\\",\\n\\t\\\"help.action.move\\\": \\\"移动\\\",\\n\\t\\\"help.action.vertical\\\": \\\"垂直\\\",\\n\\t\\\"help.action.jump\\\": \\\"跳跃\\\",\\n\\t\\\"help.action.run-slow\\\": \\\"奔跑 / 慢走\\\",\\n\\t\\\"help.action.focus-point\\\": \\\"焦点\\\",\\n\\t\\\"help.action.frame-scene\\\": \\\"适应场景\\\",\\n\\t\\\"help.action.reset-camera\\\": \\\"重置相机\\\",\\n\\t\\\"help.action.orbit-mode\\\": \\\"环绕模式\\\",\\n\\t\\\"help.action.fly-mode\\\": \\\"飞行模式\\\",\\n\\t\\\"help.action.toggle-walk\\\": \\\"切换行走\\\",\\n\\t\\\"help.action.toggle-gaming\\\": \\\"切换游戏控制\\\",\\n\\t\\\"help.action.show-collision\\\": \\\"显示碰撞\\\",\\n\\t\\\"help.action.play-pause\\\": \\\"播放 / 暂停\\\",\\n\\t\\\"help.action.toggle-help\\\": \\\"切换帮助\\\",\\n\\t\\\"help.action.exit-cancel\\\": \\\"退出 / 取消\\\",\\n\\t\\\"help.key.left-click\\\": \\\"左键点击\\\",\\n\\t\\\"help.key.left-click-drag\\\": \\\"左键点击 + 拖动\\\",\\n\\t\\\"help.key.right-click-drag\\\": \\\"右键点击 + 拖动\\\",\\n\\t\\\"help.key.mouse-wheel\\\": \\\"鼠标滚轮\\\",\\n\\t\\\"help.key.mouse\\\": \\\"鼠标\\\",\\n\\t\\\"help.key.double-click\\\": \\\"双击\\\",\\n\\t\\\"help.key.double-tap\\\": \\\"双击\\\",\\n\\t\\\"help.key.tap\\\": \\\"点击\\\",\\n\\t\\\"help.key.touch-drag\\\": \\\"触摸 + 拖动\\\",\\n\\t\\\"help.key.one-finger-drag\\\": \\\"单指拖动\\\",\\n\\t\\\"help.key.two-finger-drag\\\": \\\"双指拖动\\\",\\n\\t\\\"help.key.pinch\\\": \\\"捏合\\\",\\n\\t\\\"help.key.pinch-two-finger\\\": \\\"捏合 / 双指拖动\\\",\\n\\t\\\"help.key.joystick\\\": \\\"摇杆\\\",\\n\\t\\\"help.key.shift-ctrl\\\": \\\"Shift / Ctrl\\\",\\n\\t\\\"help.key.space\\\": \\\"空格\\\",\\n\\t\\\"help.key.esc\\\": \\\"Esc\\\",\\n\\t\\\"xr-modal.title\\\": \\\"需要 WebGL\\\",\\n\\t\\\"xr-modal.message\\\": \\\"WebGPU 渲染器不支持 AR 和 VR。按下确定将以 WebGL 重新加载查看器。\\\",\\n\\t\\\"xr-modal.cancel\\\": \\\"取消\\\",\\n\\t\\\"xr-modal.ok\\\": \\\"确定\\\",\\n\\t\\\"walk-hint.desktop\\\": \\\"点击行走。WASD 自由移动。\\\",\\n\\t\\\"walk-hint.touch-tap\\\": \\\"点击行走。拖动环顾四周。\\\",\\n\\t\\\"walk-hint.touch-gaming\\\": \\\"使用摇杆移动。拖动环顾四周。点击跳跃。\\\"\\n};\\n\\nconst en = enJson;\\nconst dictionaries = {\\n    de: deJson,\\n    en,\\n    es: esJson,\\n    fr: frJson,\\n    ja: jaJson,\\n    ko: koJson,\\n    'pt-BR': ptBRJson,\\n    ru: ruJson,\\n    'zh-CN': zhCNJson\\n};\\nlet current = en;\\nconst detectLocale = () => {\\n    const candidates = [\\n        new URLSearchParams(location.search).get('lang'),\\n        ...(navigator.languages ?? [navigator.language])\\n    ];\\n    const keys = Object.keys(dictionaries);\\n    for (const c of candidates) {\\n        if (!c)\\n            continue;\\n        const lc = c.toLowerCase();\\n        const base = lc.split('-')[0];\\n        // 1. exact tag match (case-insensitive: \\\"DE\\\" → \\\"de\\\", \\\"pt-br\\\" → \\\"pt-BR\\\")\\n        // 2. base-language match (\\\"fr-CA\\\" → \\\"fr\\\")\\n        // 3. any region variant sharing the base (\\\"pt\\\" → \\\"pt-BR\\\", \\\"zh\\\" → \\\"zh-CN\\\")\\n        const match = keys.find(k => k.toLowerCase() === lc) ??\\n            keys.find(k => k.toLowerCase() === base) ??\\n            keys.find(k => k.toLowerCase().split('-')[0] === base);\\n        if (match)\\n            return match;\\n    }\\n    return 'en';\\n};\\n// Look up a key in the active locale, falling back to English, then the key\\n// itself so missing translations are visible rather than blank.\\nconst localize = (key) => current[key] ?? en[key] ?? key;\\n// Detect the preferred locale and replace the text of every `[data-i18n]`\\n// element with its translation. Call once after the DOM is parsed and before\\n// any code reads localized strings.\\nconst initLocalization = () => {\\n    const locale = detectLocale();\\n    current = dictionaries[locale];\\n    document.documentElement.lang = locale;\\n    document.querySelectorAll('[data-i18n]').forEach((el) => {\\n        el.textContent = localize(el.dataset.i18n);\\n    });\\n};\\n\\nconst migrateV1 = (settings) => {\\n    if (settings.animTracks) {\\n        settings.animTracks?.forEach((track) => {\\n            // some early settings did not have frameRate set on anim tracks\\n            if (!track.frameRate) {\\n                const defaultFrameRate = 30;\\n                track.frameRate = defaultFrameRate;\\n                const times = track.keyframes.times;\\n                for (let i = 0; i < times.length; i++) {\\n                    times[i] *= defaultFrameRate;\\n                }\\n            }\\n            // smoothness property added in v1.4.0\\n            if (!track.hasOwnProperty('smoothness')) {\\n                track.smoothness = 0;\\n            }\\n        });\\n    }\\n    else {\\n        // some scenes were published without animTracks\\n        settings.animTracks = [];\\n    }\\n    return settings;\\n};\\nconst migrateAnimTrackV2 = (animTrackV1, fov) => {\\n    return {\\n        name: animTrackV1.name,\\n        duration: animTrackV1.duration,\\n        frameRate: animTrackV1.frameRate,\\n        loopMode: animTrackV1.loopMode,\\n        interpolation: animTrackV1.interpolation,\\n        smoothness: animTrackV1.smoothness,\\n        keyframes: {\\n            times: animTrackV1.keyframes.times,\\n            values: {\\n                position: animTrackV1.keyframes.values.position,\\n                target: animTrackV1.keyframes.values.target,\\n                fov: new Array(animTrackV1.keyframes.times.length).fill(fov)\\n            }\\n        }\\n    };\\n};\\nconst migrateV2 = (v1) => {\\n    return {\\n        version: 2,\\n        tonemapping: 'none',\\n        highPrecisionRendering: false,\\n        background: {\\n            color: v1.background.color || [0, 0, 0]\\n        },\\n        postEffectSettings: {\\n            sharpness: {\\n                enabled: false,\\n                amount: 0\\n            },\\n            bloom: {\\n                enabled: false,\\n                intensity: 1,\\n                blurLevel: 2\\n            },\\n            grading: {\\n                enabled: false,\\n                brightness: 0,\\n                contrast: 1,\\n                saturation: 1,\\n                tint: [1, 1, 1]\\n            },\\n            vignette: {\\n                enabled: false,\\n                intensity: 0.5,\\n                inner: 0.3,\\n                outer: 0.75,\\n                curvature: 1\\n            },\\n            fringing: {\\n                enabled: false,\\n                intensity: 0.5\\n            }\\n        },\\n        animTracks: v1.animTracks.map((animTrackV1) => {\\n            return migrateAnimTrackV2(animTrackV1, v1.camera.fov || 60);\\n        }),\\n        cameras: (v1.camera.position && v1.camera.target) ? [{\\n                initial: {\\n                    position: v1.camera.position,\\n                    target: v1.camera.target,\\n                    fov: v1.camera.fov || 75\\n                }\\n            }] : [],\\n        annotations: [],\\n        startMode: v1.camera.startAnim === 'animTrack' ? 'animTrack' : 'default'\\n    };\\n};\\n// migrate a JSON object to the latest settings schema (assumes valid input)\\nconst importSettings = (settings) => {\\n    let result;\\n    const version = settings.version;\\n    if (version === undefined) {\\n        // v1 -> v2\\n        result = migrateV2(migrateV1(settings));\\n    }\\n    else if (version === 2) {\\n        // already v2\\n        result = settings;\\n    }\\n    else {\\n        throw new Error(`Unsupported experience settings version: ${version}`);\\n    }\\n    return result;\\n};\\n\\nvar version = \\\"1.26.2\\\";\\n\\nclass Tooltip {\\n    register;\\n    unregister;\\n    destroy;\\n    constructor(dom) {\\n        const { style } = dom;\\n        style.display = 'none';\\n        const targets = new Map();\\n        let timer = 0;\\n        this.register = (target, textString, direction = 'bottom') => {\\n            const activate = () => {\\n                const rect = target.getBoundingClientRect();\\n                const midx = Math.floor((rect.left + rect.right) * 0.5);\\n                const midy = Math.floor((rect.top + rect.bottom) * 0.5);\\n                switch (direction) {\\n                    case 'left':\\n                        style.left = `${rect.left}px`;\\n                        style.top = `${midy}px`;\\n                        style.transform = 'translate(calc(-100% - 10px), -50%)';\\n                        break;\\n                    case 'right':\\n                        style.left = `${rect.right}px`;\\n                        style.top = `${midy}px`;\\n                        style.transform = 'translate(10px, -50%)';\\n                        break;\\n                    case 'top':\\n                        style.left = `${midx}px`;\\n                        style.top = `${rect.top}px`;\\n                        style.transform = 'translate(-50%, calc(-100% - 10px))';\\n                        break;\\n                    case 'bottom':\\n                        style.left = `${midx}px`;\\n                        style.top = `${rect.bottom}px`;\\n                        style.transform = 'translate(-50%, 10px)';\\n                        break;\\n                }\\n                dom.textContent = textString;\\n                style.display = 'inline';\\n            };\\n            const startTimer = (fn) => {\\n                timer = window.setTimeout(() => {\\n                    fn();\\n                    timer = -1;\\n                }, 250);\\n            };\\n            const cancelTimer = () => {\\n                if (timer >= 0) {\\n                    clearTimeout(timer);\\n                    timer = -1;\\n                }\\n            };\\n            const enter = () => {\\n                cancelTimer();\\n                if (style.display === 'inline') {\\n                    activate();\\n                }\\n                else {\\n                    startTimer(() => activate());\\n                }\\n            };\\n            const leave = () => {\\n                cancelTimer();\\n                if (style.display === 'inline') {\\n                    startTimer(() => {\\n                        style.display = 'none';\\n                    });\\n                }\\n            };\\n            target.addEventListener('pointerenter', enter);\\n            target.addEventListener('pointerleave', leave);\\n            targets.set(target, { enter, leave });\\n        };\\n        this.unregister = (target) => {\\n            const value = targets.get(target);\\n            if (value) {\\n                target.removeEventListener('pointerenter', value.enter);\\n                target.removeEventListener('pointerleave', value.leave);\\n                targets.delete(target);\\n            }\\n        };\\n        this.destroy = () => {\\n            for (const target of targets.keys()) {\\n                this.unregister(target);\\n            }\\n        };\\n    }\\n}\\n\\n// Initialize the touch joystick for fly mode camera control\\nconst initJoystick = (dom, events, state) => {\\n    // Joystick dimensions (matches SCSS: base height=100, stick size=40)\\n    const joystickHeight = 100;\\n    const stickSize = 40;\\n    const stickCenterY = (joystickHeight - stickSize) / 2; // 30px - top position when centered\\n    const stickCenterX = (joystickHeight - stickSize) / 2; // 30px - left position when centered (for 2D mode)\\n    const maxStickTravel = stickCenterY; // can travel 30px up or down from center\\n    // Fixed joystick position (bottom-left corner with safe area)\\n    const joystickFixedX = 70;\\n    const joystickFixedY = () => window.innerHeight - 140;\\n    // Joystick touch state\\n    let joystickPointerId = null;\\n    let joystickValueX = 0; // -1 to 1, negative = left, positive = right\\n    let joystickValueY = 0; // -1 to 1, negative = forward, positive = backward\\n    // Joystick mode: '1d' for vertical only, '2d' for full directional\\n    let joystickMode = '2d';\\n    // Double-tap detection for mode toggle\\n    let lastTapTime = 0;\\n    // Update joystick visibility based on camera mode and input mode\\n    const updateJoystickVisibility = () => {\\n        if ((state.cameraMode === 'fly' || state.cameraMode === 'walk') && state.inputMode === 'touch' && state.gamingControls) {\\n            dom.joystickBase.classList.remove('hidden');\\n            dom.joystickBase.classList.toggle('mode-2d', joystickMode === '2d');\\n            dom.joystickBase.style.left = `${joystickFixedX}px`;\\n            dom.joystickBase.style.top = `${joystickFixedY()}px`;\\n            // Center the stick\\n            dom.joystick.style.top = `${stickCenterY}px`;\\n            if (joystickMode === '2d') {\\n                dom.joystick.style.left = `${stickCenterX}px`;\\n            }\\n            else {\\n                dom.joystick.style.left = '8px'; // Reset to 1D centered position\\n            }\\n        }\\n        else {\\n            dom.joystickBase.classList.add('hidden');\\n        }\\n    };\\n    events.on('cameraMode:changed', updateJoystickVisibility);\\n    events.on('inputMode:changed', updateJoystickVisibility);\\n    events.on('gamingControls:changed', updateJoystickVisibility);\\n    window.addEventListener('resize', updateJoystickVisibility);\\n    // Handle joystick touch input directly on the joystick element\\n    const updateJoystickStick = (clientX, clientY) => {\\n        const baseY = joystickFixedY();\\n        // Calculate Y offset from joystick center (positive = down/backward)\\n        const offsetY = clientY - baseY;\\n        // Clamp to max travel and normalize to -1 to 1\\n        const clampedOffsetY = Math.max(-maxStickTravel, Math.min(maxStickTravel, offsetY));\\n        joystickValueY = clampedOffsetY / maxStickTravel;\\n        // Update stick visual Y position\\n        dom.joystick.style.top = `${stickCenterY + clampedOffsetY}px`;\\n        // Handle X axis in 2D mode\\n        if (joystickMode === '2d') {\\n            const baseX = joystickFixedX;\\n            const offsetX = clientX - baseX;\\n            const clampedOffsetX = Math.max(-maxStickTravel, Math.min(maxStickTravel, offsetX));\\n            joystickValueX = clampedOffsetX / maxStickTravel;\\n            // Update stick visual X position\\n            dom.joystick.style.left = `${stickCenterX + clampedOffsetX}px`;\\n        }\\n        else {\\n            joystickValueX = 0;\\n        }\\n        // Fire input event for the input controller\\n        events.fire('joystickInput', { x: joystickValueX, y: joystickValueY });\\n    };\\n    dom.joystickBase.addEventListener('pointerdown', (event) => {\\n        // Double-tap detection for mode toggle\\n        const now = Date.now();\\n        if (now - lastTapTime < 300) {\\n            joystickMode = joystickMode === '1d' ? '2d' : '1d';\\n            updateJoystickVisibility();\\n            lastTapTime = 0;\\n        }\\n        else {\\n            lastTapTime = now;\\n        }\\n        if (joystickPointerId !== null)\\n            return; // Already tracking a touch\\n        joystickPointerId = event.pointerId;\\n        dom.joystickBase.setPointerCapture(event.pointerId);\\n        updateJoystickStick(event.clientX, event.clientY);\\n        event.preventDefault();\\n        event.stopPropagation();\\n    });\\n    dom.joystickBase.addEventListener('pointermove', (event) => {\\n        if (event.pointerId !== joystickPointerId)\\n            return;\\n        updateJoystickStick(event.clientX, event.clientY);\\n        event.preventDefault();\\n    });\\n    const endJoystickTouch = (event) => {\\n        if (event.pointerId !== joystickPointerId)\\n            return;\\n        joystickPointerId = null;\\n        joystickValueX = 0;\\n        joystickValueY = 0;\\n        // Reset stick to center\\n        dom.joystick.style.top = `${stickCenterY}px`;\\n        if (joystickMode === '2d') {\\n            dom.joystick.style.left = `${stickCenterX}px`;\\n        }\\n        // Fire input event with zero values\\n        events.fire('joystickInput', { x: 0, y: 0 });\\n        dom.joystickBase.releasePointerCapture(event.pointerId);\\n    };\\n    dom.joystickBase.addEventListener('pointerup', endJoystickTouch);\\n    dom.joystickBase.addEventListener('pointercancel', endJoystickTouch);\\n};\\n// Initialize the annotation navigator for stepping between annotations\\nconst initAnnotationNav = (dom, events, state, annotations) => {\\n    // Only show navigator when there are at least 2 annotations\\n    if (annotations.length < 2)\\n        return;\\n    let currentIndex = 0;\\n    const updateDisplay = () => {\\n        dom.annotationNavTitle.textContent = annotations[currentIndex].title || '';\\n    };\\n    const updateMode = () => {\\n        if (!state.loaded)\\n            return;\\n        dom.annotationNav.classList.remove('desktop', 'touch', 'hidden');\\n        dom.annotationNav.classList.add(state.inputMode);\\n    };\\n    const updateFade = () => {\\n        if (!state.loaded)\\n            return;\\n        dom.annotationNav.classList.toggle('faded-in', !state.controlsHidden);\\n        dom.annotationNav.classList.toggle('faded-out', state.controlsHidden);\\n    };\\n    const goTo = (index) => {\\n        currentIndex = index;\\n        updateDisplay();\\n        events.fire('annotation.navigate', annotations[currentIndex]);\\n    };\\n    // Prev / Next\\n    dom.annotationPrev.addEventListener('click', (e) => {\\n        e.stopPropagation();\\n        goTo((currentIndex - 1 + annotations.length) % annotations.length);\\n    });\\n    dom.annotationNext.addEventListener('click', (e) => {\\n        e.stopPropagation();\\n        goTo((currentIndex + 1) % annotations.length);\\n    });\\n    // Sync when an annotation is activated externally (e.g. hotspot click)\\n    events.on('annotation.activate', (annotation) => {\\n        const idx = annotations.indexOf(annotation);\\n        if (idx !== -1) {\\n            currentIndex = idx;\\n            updateDisplay();\\n        }\\n    });\\n    // React to state changes\\n    events.on('loaded:changed', () => {\\n        updateMode();\\n        updateFade();\\n    });\\n    events.on('inputMode:changed', updateMode);\\n    events.on('controlsHidden:changed', updateFade);\\n    // Initial state\\n    updateDisplay();\\n};\\n// update the poster image to start blurry and then resolve to sharp during loading\\nconst initPoster = (events) => {\\n    const poster = document.getElementById('poster');\\n    events.on('loaded:changed', () => {\\n        poster.style.display = 'none';\\n        document.documentElement.style.setProperty('--canvas-opacity', '1');\\n    });\\n    const blur = (progress) => {\\n        poster.style.filter = `blur(${Math.floor((100 - progress) * 0.4)}px)`;\\n    };\\n    events.on('progress:changed', blur);\\n};\\nconst initUI = (global) => {\\n    const { config, events, state } = global;\\n    // Acquire Elements\\n    const docRoot = document.documentElement;\\n    const dom = [\\n        'ui',\\n        'controlsWrap',\\n        'arMode', 'vrMode',\\n        'enterFullscreen', 'exitFullscreen',\\n        'info', 'infoPanel', 'desktopTab', 'touchTab', 'desktopInfoPanel', 'touchInfoPanel',\\n        'timelineContainer', 'handle', 'time',\\n        'buttonContainer',\\n        'play', 'pause',\\n        'settings', 'settingsPanel',\\n        'orbitCamera', 'flyCamera', 'fpsCamera',\\n        'performanceModeRow', 'performanceModeCheck', 'performanceModeOption',\\n        'gamingControlsDivider', 'gamingControlsRow', 'gamingControlsCheck', 'gamingControlsOption',\\n        'desktopFlyClickToFly', 'desktopFlyGamingControls', 'desktopClickToWalk', 'desktopGamingControls',\\n        'touchFlyClickToWalk', 'touchFlyGamingControls',\\n        'touchClickToWalk', 'touchGamingControls',\\n        'walkHint',\\n        'reset', 'frame',\\n        'loadingText', 'loadingBar',\\n        'joystickBase', 'joystick',\\n        'showCollision', 'desktopShowCollisionHelp',\\n        'tooltip',\\n        'annotationNav', 'annotationPrev', 'annotationNext', 'annotationInfo', 'annotationNavTitle',\\n        'viewerBranding', 'viewerTitle', 'appVersionLabel',\\n        'xrModal', 'xrModalOk', 'xrModalCancel'\\n    ].reduce((acc, id) => {\\n        acc[id] = document.getElementById(id);\\n        return acc;\\n    }, {});\\n    // populate the info-panel title with the app version\\n    dom.appVersionLabel.textContent = version;\\n    // Remove focus from buttons after click so keyboard input isn't captured by the UI\\n    dom.ui.addEventListener('click', () => {\\n        document.activeElement?.blur();\\n    });\\n    // Forward wheel events from UI overlays to the canvas so the camera zooms\\n    // instead of the page scrolling (e.g. annotation nav, tooltips, hotspots).\\n    // The non-standard wheelDelta{X,Y} properties aren't part of WheelEventInit,\\n    // so they get dropped by `new WheelEvent(type, init)`. We re-attach them so\\n    // the trackpad-vs-mouse classifier in input-controller.ts behaves the same\\n    // whether the event originated on the canvas or was forwarded from the UI.\\n    const canvas = global.app.graphicsDevice.canvas;\\n    dom.ui.addEventListener('wheel', (event) => {\\n        event.preventDefault();\\n        const forwarded = new WheelEvent(event.type, event);\\n        const src = event;\\n        for (const key of ['wheelDelta', 'wheelDeltaX', 'wheelDeltaY']) {\\n            if (typeof src[key] === 'number') {\\n                Object.defineProperty(forwarded, key, { value: src[key], configurable: true });\\n            }\\n        }\\n        canvas.dispatchEvent(forwarded);\\n    }, { passive: false });\\n    // Handle loading progress updates\\n    events.on('progress:changed', (progress) => {\\n        dom.loadingText.textContent = `${progress}%`;\\n        if (progress < 100) {\\n            dom.loadingBar.style.backgroundImage = `linear-gradient(90deg, #F60 0%, #F60 ${progress}%, white ${progress}%, white 100%)`;\\n        }\\n        else {\\n            dom.loadingBar.style.backgroundImage = 'linear-gradient(90deg, #F60 0%, #F60 100%)';\\n        }\\n    });\\n    // Hide loading bar once loaded\\n    events.on('loaded:changed', () => {\\n        document.getElementById('loadingWrap').classList.add('hidden');\\n    });\\n    // Fullscreen support\\n    const hasFullscreenAPI = docRoot.requestFullscreen && document.exitFullscreen;\\n    const requestFullscreen = () => {\\n        if (hasFullscreenAPI) {\\n            docRoot.requestFullscreen();\\n        }\\n        else {\\n            window.parent.postMessage('requestFullscreen', '*');\\n            state.isFullscreen = true;\\n        }\\n    };\\n    const exitFullscreen = () => {\\n        if (hasFullscreenAPI) {\\n            if (document.fullscreenElement) {\\n                document.exitFullscreen().catch(() => { });\\n            }\\n        }\\n        else {\\n            window.parent.postMessage('exitFullscreen', '*');\\n            state.isFullscreen = false;\\n        }\\n    };\\n    if (hasFullscreenAPI) {\\n        document.addEventListener('fullscreenchange', () => {\\n            state.isFullscreen = !!document.fullscreenElement;\\n        });\\n    }\\n    dom.enterFullscreen.addEventListener('click', requestFullscreen);\\n    dom.exitFullscreen.addEventListener('click', exitFullscreen);\\n    // toggle fullscreen when user switches between landscape portrait\\n    // orientation\\n    screen?.orientation?.addEventListener('change', (event) => {\\n        if (['landscape-primary', 'landscape-secondary'].includes(screen.orientation.type)) {\\n            requestFullscreen();\\n        }\\n        else {\\n            exitFullscreen();\\n        }\\n    });\\n    // update UI when fullscreen state changes\\n    events.on('isFullscreen:changed', (value) => {\\n        dom.enterFullscreen.classList[value ? 'add' : 'remove']('hidden');\\n        dom.exitFullscreen.classList[value ? 'remove' : 'add']('hidden');\\n    });\\n    // Performance mode toggle\\n    dom.performanceModeRow.addEventListener('click', () => {\\n        state.performanceMode = !state.performanceMode;\\n    });\\n    const updatePerformanceMode = () => {\\n        dom.performanceModeCheck.classList.toggle('active', state.performanceMode);\\n        localStorage.setItem('performanceMode', String(state.performanceMode));\\n    };\\n    events.on('performanceMode:changed', updatePerformanceMode);\\n    updatePerformanceMode();\\n    // Gaming mode toggle (settings row visible on mobile only)\\n    dom.gamingControlsRow.addEventListener('click', () => {\\n        state.gamingControls = !state.gamingControls;\\n    });\\n    const updateGamingSettingsVisibility = () => {\\n        const isDesktop = state.inputMode === 'desktop';\\n        dom.gamingControlsDivider.classList.toggle('hidden', isDesktop);\\n        dom.gamingControlsRow.classList.toggle('hidden', isDesktop);\\n    };\\n    events.on('inputMode:changed', updateGamingSettingsVisibility);\\n    updateGamingSettingsVisibility();\\n    const updateGamingControls = () => {\\n        dom.gamingControlsCheck.classList.toggle('active', state.gamingControls);\\n        dom.desktopFlyClickToFly.classList.toggle('hidden', state.gamingControls);\\n        dom.desktopFlyGamingControls.classList.toggle('hidden', !state.gamingControls);\\n        dom.desktopClickToWalk.classList.toggle('hidden', state.gamingControls);\\n        dom.desktopGamingControls.classList.toggle('hidden', !state.gamingControls);\\n        dom.touchFlyClickToWalk.classList.toggle('hidden', state.gamingControls);\\n        dom.touchFlyGamingControls.classList.toggle('hidden', !state.gamingControls);\\n        dom.touchClickToWalk.classList.toggle('hidden', state.gamingControls);\\n        dom.touchGamingControls.classList.toggle('hidden', !state.gamingControls);\\n        localStorage.setItem('gamingControls', String(state.gamingControls));\\n    };\\n    events.on('gamingControls:changed', updateGamingControls);\\n    events.on('inputMode:changed', updateGamingControls);\\n    updateGamingControls();\\n    // AR/VR\\n    const arChanged = () => dom.arMode.classList[state.hasAR ? 'remove' : 'add']('hidden');\\n    const vrChanged = () => dom.vrMode.classList[state.hasVR ? 'remove' : 'add']('hidden');\\n    // XR sessions require a WebGL device. Under WebGPU, prompt the user to reload\\n    // the viewer with the WebGL renderer before starting AR/VR. Use replace() so\\n    // the renderer-switch reload doesn't add a back-button entry — important\\n    // because the viewer often runs inside an iframe (e.g. superspl.at /scene).\\n    const reloadWithWebgl = () => {\\n        const reloadUrl = new URL(location.href);\\n        reloadUrl.searchParams.set('webgl', '');\\n        location.replace(reloadUrl.toString());\\n    };\\n    const showXrModal = () => dom.xrModal.classList.remove('hidden');\\n    const hideXrModal = () => dom.xrModal.classList.add('hidden');\\n    dom.xrModalOk.addEventListener('click', reloadWithWebgl);\\n    dom.xrModalCancel.addEventListener('click', hideXrModal);\\n    dom.xrModal.addEventListener('pointerdown', hideXrModal);\\n    const handleXrClick = (type) => {\\n        if (global.renderer !== 'webgl') {\\n            showXrModal();\\n        }\\n        else {\\n            events.fire(type === 'AR' ? 'startAR' : 'startVR');\\n        }\\n    };\\n    dom.arMode.addEventListener('click', () => handleXrClick('AR'));\\n    dom.vrMode.addEventListener('click', () => handleXrClick('VR'));\\n    events.on('hasAR:changed', arChanged);\\n    events.on('hasVR:changed', vrChanged);\\n    arChanged();\\n    vrChanged();\\n    // Info panel\\n    const updateInfoTab = (tab) => {\\n        if (tab === 'desktop') {\\n            dom.desktopTab.classList.add('active');\\n            dom.touchTab.classList.remove('active');\\n            dom.desktopInfoPanel.classList.remove('hidden');\\n            dom.touchInfoPanel.classList.add('hidden');\\n        }\\n        else {\\n            dom.desktopTab.classList.remove('active');\\n            dom.touchTab.classList.add('active');\\n            dom.desktopInfoPanel.classList.add('hidden');\\n            dom.touchInfoPanel.classList.remove('hidden');\\n        }\\n    };\\n    dom.desktopTab.addEventListener('click', () => {\\n        updateInfoTab('desktop');\\n    });\\n    dom.touchTab.addEventListener('click', () => {\\n        updateInfoTab('touch');\\n    });\\n    const toggleHelp = () => {\\n        updateInfoTab(state.inputMode);\\n        dom.infoPanel.classList.toggle('hidden');\\n    };\\n    dom.info.addEventListener('click', toggleHelp);\\n    dom.infoPanel.addEventListener('pointerdown', () => {\\n        dom.infoPanel.classList.add('hidden');\\n    });\\n    events.on('inputEvent', (event) => {\\n        if (event === 'toggleHelp') {\\n            toggleHelp();\\n        }\\n        else if (event === 'cancel') {\\n            // close info panel on cancel\\n            dom.infoPanel.classList.add('hidden');\\n            dom.settingsPanel.classList.add('hidden');\\n            // close fullscreen on cancel\\n            if (state.isFullscreen) {\\n                exitFullscreen();\\n            }\\n        }\\n        else if (event === 'interrupt') {\\n            dom.settingsPanel.classList.add('hidden');\\n        }\\n    });\\n    // fade ui controls after 5 seconds of inactivity\\n    events.on('controlsHidden:changed', (value) => {\\n        dom.controlsWrap.classList.toggle('faded-out', value);\\n        dom.controlsWrap.classList.toggle('faded-in', !value);\\n    });\\n    // show the ui and start a timer to hide it again\\n    let uiTimeout = null;\\n    let annotationVisible = false;\\n    const isPointerCapturedMode = () => (state.inputMode === 'desktop' &&\\n        state.gamingControls &&\\n        (state.cameraMode === 'walk' || state.cameraMode === 'fly'));\\n    const hideUI = () => {\\n        if (uiTimeout) {\\n            clearTimeout(uiTimeout);\\n            uiTimeout = null;\\n        }\\n        dom.infoPanel.classList.add('hidden');\\n        dom.settingsPanel.classList.add('hidden');\\n        dom.walkHint.classList.add('hidden');\\n        state.controlsHidden = true;\\n    };\\n    const showUI = () => {\\n        if (isPointerCapturedMode()) {\\n            hideUI();\\n            return;\\n        }\\n        if (uiTimeout) {\\n            clearTimeout(uiTimeout);\\n        }\\n        state.controlsHidden = false;\\n        uiTimeout = setTimeout(() => {\\n            uiTimeout = null;\\n            if (!annotationVisible) {\\n                state.controlsHidden = true;\\n            }\\n        }, 4000);\\n    };\\n    // Show controls once loaded\\n    events.on('loaded:changed', () => {\\n        dom.controlsWrap.classList.remove('hidden');\\n        showUI();\\n    });\\n    events.on('inputEvent', showUI);\\n    const updateCapturedUI = () => {\\n        if (isPointerCapturedMode()) {\\n            hideUI();\\n        }\\n        else {\\n            showUI();\\n        }\\n    };\\n    events.on('cameraMode:changed', updateCapturedUI);\\n    events.on('inputMode:changed', updateCapturedUI);\\n    events.on('gamingControls:changed', updateCapturedUI);\\n    // keep UI visible while an annotation tooltip is shown\\n    events.on('annotation.activate', () => {\\n        annotationVisible = true;\\n        showUI();\\n    });\\n    events.on('annotation.deactivate', () => {\\n        annotationVisible = false;\\n        showUI();\\n    });\\n    // Animation controls\\n    events.on('hasAnimation:changed', (value, prev) => {\\n        // Start and Stop animation\\n        dom.play.addEventListener('click', () => {\\n            state.cameraMode = 'anim';\\n            state.animationPaused = false;\\n        });\\n        dom.pause.addEventListener('click', () => {\\n            state.cameraMode = 'anim';\\n            state.animationPaused = true;\\n        });\\n        const updatePlayPause = () => {\\n            if (state.cameraMode !== 'anim' || state.animationPaused) {\\n                dom.play.classList.remove('hidden');\\n                dom.pause.classList.add('hidden');\\n            }\\n            else {\\n                dom.play.classList.add('hidden');\\n                dom.pause.classList.remove('hidden');\\n            }\\n            if (state.cameraMode === 'anim') {\\n                dom.timelineContainer.classList.remove('hidden');\\n            }\\n            else {\\n                dom.timelineContainer.classList.add('hidden');\\n            }\\n        };\\n        // Update UI on animation changes\\n        events.on('cameraMode:changed', updatePlayPause);\\n        events.on('animationPaused:changed', updatePlayPause);\\n        const updateSlider = () => {\\n            dom.handle.style.left = `${state.animationTime / state.animationDuration * 100}%`;\\n            dom.time.style.left = `${state.animationTime / state.animationDuration * 100}%`;\\n            dom.time.innerText = `${state.animationTime.toFixed(1)}s`;\\n        };\\n        events.on('animationTime:changed', updateSlider);\\n        events.on('animationLength:changed', updateSlider);\\n        const handleScrub = (event) => {\\n            const rect = dom.timelineContainer.getBoundingClientRect();\\n            const t = Math.max(0, Math.min(rect.width - 1, event.clientX - rect.left)) / rect.width;\\n            events.fire('scrubAnim', state.animationDuration * t);\\n            showUI();\\n        };\\n        let paused = false;\\n        let captured = false;\\n        dom.timelineContainer.addEventListener('pointerdown', (event) => {\\n            if (!captured) {\\n                handleScrub(event);\\n                dom.timelineContainer.setPointerCapture(event.pointerId);\\n                dom.time.classList.remove('hidden');\\n                paused = state.animationPaused;\\n                state.animationPaused = true;\\n                captured = true;\\n            }\\n        });\\n        dom.timelineContainer.addEventListener('pointermove', (event) => {\\n            if (captured) {\\n                handleScrub(event);\\n            }\\n        });\\n        dom.timelineContainer.addEventListener('pointerup', (event) => {\\n            if (captured) {\\n                dom.timelineContainer.releasePointerCapture(event.pointerId);\\n                dom.time.classList.add('hidden');\\n                state.animationPaused = paused;\\n                captured = false;\\n            }\\n        });\\n    });\\n    // Camera mode UI\\n    const updateCameraModeUI = () => {\\n        dom.orbitCamera.classList.toggle('active', state.cameraMode === 'orbit');\\n        dom.flyCamera.classList.toggle('active', state.cameraMode === 'fly');\\n        dom.fpsCamera.classList.toggle('active', state.cameraMode === 'walk');\\n    };\\n    events.on('cameraMode:changed', updateCameraModeUI);\\n    // Walk mode hint banner (shown once per session on first FPS entry)\\n    let walkHintShown = false;\\n    const getWalkHintText = () => {\\n        if (state.inputMode === 'desktop') {\\n            return localize('walk-hint.desktop');\\n        }\\n        return localize(state.gamingControls ? 'walk-hint.touch-gaming' : 'walk-hint.touch-tap');\\n    };\\n    events.on('cameraMode:changed', (value) => {\\n        if (value === 'walk' && !walkHintShown && !isPointerCapturedMode()) {\\n            walkHintShown = true;\\n            dom.walkHint.textContent = getWalkHintText();\\n            dom.walkHint.classList.remove('hidden');\\n        }\\n        else if (value !== 'walk') {\\n            dom.walkHint.classList.add('hidden');\\n        }\\n    });\\n    const dismissWalkHint = () => dom.walkHint.classList.add('hidden');\\n    dom.walkHint.addEventListener('click', dismissWalkHint);\\n    events.on('inputEvent', (type) => {\\n        if (type === 'interrupt')\\n            dismissWalkHint();\\n    });\\n    // show/hide the FPS button based on whether walk mode is offered\\n    // (collision data exists AND scene is large enough to walk around in)\\n    events.on('walkAllowed:changed', (value) => {\\n        dom.fpsCamera.classList.toggle('hidden', !value);\\n        // adjust fly button shape: middle when FPS is visible, right when hidden\\n        dom.flyCamera.classList.toggle('middle', value);\\n        dom.flyCamera.classList.toggle('right', !value);\\n    });\\n    // Collision overlay toggle + matching help-panel row (only visible when overlay is available)\\n    events.on('hasCollisionOverlay:changed', (value) => {\\n        dom.showCollision.classList.toggle('hidden', !value);\\n        dom.desktopShowCollisionHelp.classList.toggle('hidden', !value);\\n    });\\n    dom.showCollision.addEventListener('click', () => {\\n        state.collisionOverlayEnabled = !state.collisionOverlayEnabled;\\n    });\\n    events.on('collisionOverlayEnabled:changed', (value) => {\\n        dom.showCollision.classList.toggle('active', value);\\n    });\\n    dom.settings.addEventListener('click', () => {\\n        dom.settingsPanel.classList.toggle('hidden');\\n    });\\n    dom.orbitCamera.addEventListener('click', () => {\\n        state.cameraMode = 'orbit';\\n    });\\n    dom.flyCamera.addEventListener('click', () => {\\n        state.cameraMode = 'fly';\\n    });\\n    dom.fpsCamera.addEventListener('click', () => {\\n        events.fire('inputEvent', 'toggleWalk');\\n    });\\n    dom.reset.addEventListener('click', (event) => {\\n        events.fire('inputEvent', 'reset', event);\\n    });\\n    dom.frame.addEventListener('click', (event) => {\\n        events.fire('inputEvent', 'frame', event);\\n    });\\n    // Initialize touch joystick for fly mode\\n    initJoystick(dom, events, state);\\n    // Initialize annotation navigator\\n    initAnnotationNav(dom, events, state, global.settings.annotations);\\n    // Hide all UI (poster, loading bar, controls)\\n    if (config.noui) {\\n        dom.ui.classList.add('hidden');\\n    }\\n    // tooltips\\n    const tooltip = new Tooltip(dom.tooltip);\\n    tooltip.register(dom.play, localize('tooltip.play'), 'top');\\n    tooltip.register(dom.pause, localize('tooltip.pause'), 'top');\\n    tooltip.register(dom.orbitCamera, localize('tooltip.orbit-camera'), 'top');\\n    tooltip.register(dom.flyCamera, localize('tooltip.fly-camera'), 'top');\\n    tooltip.register(dom.fpsCamera, localize('tooltip.walk-mode'), 'top');\\n    tooltip.register(dom.reset, localize('tooltip.reset-camera'), 'bottom');\\n    tooltip.register(dom.frame, localize('tooltip.frame-scene'), 'bottom');\\n    tooltip.register(dom.showCollision, localize('tooltip.show-collision'), 'top');\\n    tooltip.register(dom.settings, localize('tooltip.settings'), 'top');\\n    tooltip.register(dom.info, localize('tooltip.help'), 'top');\\n    tooltip.register(dom.arMode, localize('tooltip.enter-ar'), 'top');\\n    tooltip.register(dom.vrMode, localize('tooltip.enter-vr'), 'top');\\n    tooltip.register(dom.enterFullscreen, localize('tooltip.fullscreen'), 'top');\\n    tooltip.register(dom.exitFullscreen, localize('tooltip.fullscreen'), 'top');\\n    const isThirdPartyEmbedded = () => {\\n        try {\\n            return window.location.hostname !== window.parent.location.hostname;\\n        }\\n        catch (e) {\\n            // cross-origin iframe — parent location is inaccessible\\n            return true;\\n        }\\n    };\\n    if (window.parent !== window && isThirdPartyEmbedded()) {\\n        const viewUrl = new URL(window.location.href);\\n        if (viewUrl.pathname === '/s') {\\n            viewUrl.pathname = '/view';\\n        }\\n        dom.viewerBranding.href = viewUrl.toString();\\n        dom.viewerBranding.classList.remove('hidden');\\n        dom.viewerTitle.href = viewUrl.toString();\\n    }\\n};\\n\\n// clamp the vertices of the hotspot so it is never clipped by the near or far plane\\nconst depthClampGlsl = `\\n    float f = gl_Position.z / gl_Position.w;\\n    if (f > 1.0) {\\n        gl_Position.z = gl_Position.w;\\n    } else if (f < -1.0) {\\n        gl_Position.z = -gl_Position.w;\\n    }\\n`;\\nconst depthClampWgsl = `\\n    let f = output.position.z / output.position.w;\\n    if (f > 1.0) {\\n        output.position.z = output.position.w;\\n    } else if (f < -1.0) {\\n        output.position.z = -output.position.w;\\n    }\\n`;\\nconst vec$1 = new Vec3();\\n/**\\n * A script for creating interactive 3D annotations in a scene. Each annotation consists of:\\n *\\n * - A 3D hotspot that maintains constant screen-space size. The hotspot is rendered with muted\\n * appearance when obstructed by geometry but is still clickable. The hotspot relies on an\\n * invisible DOM element that matches the hotspot's size and position to detect clicks.\\n * - An annotation panel that shows title and description text.\\n */\\nclass Annotation extends Script {\\n    static scriptName = 'annotation';\\n    static hotspotSize = 25;\\n    static hotspotColor = new Color(0.8, 0.8, 0.8);\\n    static hoverColor = new Color(1.0, 0.4, 0.0);\\n    static parentDom = null;\\n    static styleSheet = null;\\n    static camera = null;\\n    static tooltipDom = null;\\n    static titleDom = null;\\n    static textDom = null;\\n    static layers = [];\\n    static mesh = null;\\n    static activeAnnotation = null;\\n    static hoverAnnotation = null;\\n    static opacity = 1.0;\\n    /**\\n     * @attribute\\n     */\\n    label;\\n    /**\\n     * @attribute\\n     */\\n    title;\\n    /**\\n     * @attribute\\n     */\\n    text;\\n    /**\\n     * @private\\n     */\\n    hotspotDom = null;\\n    /**\\n     * @private\\n     */\\n    texture = null;\\n    /**\\n     * @private\\n     */\\n    materials = [];\\n    /**\\n     * Injects required CSS styles into the document.\\n     * @param {number} size - The size of the hotspot in screen pixels.\\n     * @private\\n     */\\n    static _injectStyles(size) {\\n        const css = `\\n            .pc-annotation {\\n                display: block;\\n                position: absolute;\\n                background-color: rgba(0, 0, 0, 0.8);\\n                color: white;\\n                padding: 8px;\\n                border-radius: 4px;\\n                font-size: 14px;\\n                font-family: -apple-system, BlinkMacSystemFont, \\\"Segoe UI\\\", Roboto, Helvetica, Arial, sans-serif, \\\"Apple Color Emoji\\\", \\\"Segoe UI Emoji\\\";\\n                pointer-events: none;\\n                max-width: 200px;\\n                word-wrap: break-word;\\n                overflow-x: visible;\\n                white-space: normal;\\n                width: fit-content;\\n                opacity: 0;\\n                transition: opacity 0.2s ease-in-out;\\n                visibility: hidden;\\n            }\\n\\n            .pc-annotation-title {\\n                font-weight: bold;\\n                margin-bottom: 4px;\\n            }\\n\\n            /* Tooltip arrow */\\n            .pc-annotation.arrow-right::before,\\n            .pc-annotation.arrow-left::before {\\n                content: \\\"\\\";\\n                position: absolute;\\n                top: var(--arrow-top, 50%);\\n                transform: translateY(-50%);\\n                border-top: 8px solid transparent;\\n                border-bottom: 8px solid transparent;\\n            }\\n\\n            .pc-annotation.arrow-right::before {\\n                left: -8px;\\n                border-right: 8px solid rgba(0, 0, 0, 0.8);\\n            }\\n\\n            .pc-annotation.arrow-left::before {\\n                right: -8px;\\n                border-left: 8px solid rgba(0, 0, 0, 0.8);\\n            }\\n\\n            .pc-annotation-hotspot {\\n                display: none;\\n                position: absolute;\\n                width: ${size + 5}px;\\n                height: ${size + 5}px;\\n                opacity: 0;\\n                cursor: pointer;\\n                transform: translate(-50%, -50%);\\n            }\\n        `;\\n        const style = document.createElement('style');\\n        style.textContent = css;\\n        document.head.appendChild(style);\\n        Annotation.styleSheet = style;\\n    }\\n    /**\\n     * Initialize static resources.\\n     * @param {AppBase} app - The application instance\\n     * @private\\n     */\\n    static _initializeStatic(app) {\\n        if (Annotation.styleSheet) {\\n            return;\\n        }\\n        Annotation._injectStyles(Annotation.hotspotSize);\\n        if (Annotation.parentDom === null) {\\n            Annotation.parentDom = document.body;\\n        }\\n        const { layers } = app.scene;\\n        const worldLayer = layers.getLayerByName('World');\\n        const createLayer = (name, semitrans) => {\\n            const layer = new Layer({ name: name });\\n            const idx = semitrans ? layers.getTransparentIndex(worldLayer) : layers.getOpaqueIndex(worldLayer);\\n            layers.insert(layer, idx + 1);\\n            return layer;\\n        };\\n        Annotation.layers = [\\n            createLayer('HotspotBase', false),\\n            createLayer('HotspotOverlay', true)\\n        ];\\n        if (Annotation.camera === null) {\\n            Annotation.camera = app.root.findComponent('camera').entity;\\n        }\\n        Annotation.camera.camera.layers = [\\n            ...Annotation.camera.camera.layers,\\n            ...Annotation.layers.map(layer => layer.id)\\n        ];\\n        Annotation.mesh = Mesh.fromGeometry(app.graphicsDevice, new PlaneGeometry({\\n            widthSegments: 1,\\n            lengthSegments: 1\\n        }));\\n        // Initialize tooltip dom\\n        Annotation.tooltipDom = document.createElement('div');\\n        Annotation.tooltipDom.className = 'pc-annotation';\\n        Annotation.titleDom = document.createElement('div');\\n        Annotation.titleDom.className = 'pc-annotation-title';\\n        Annotation.tooltipDom.appendChild(Annotation.titleDom);\\n        Annotation.textDom = document.createElement('div');\\n        Annotation.textDom.className = 'pc-annotation-text';\\n        Annotation.tooltipDom.appendChild(Annotation.textDom);\\n        Annotation.parentDom.appendChild(Annotation.tooltipDom);\\n    }\\n    /**\\n     * Creates a circular hotspot texture.\\n     * @param {AppBase} app - The PlayCanvas AppBase\\n     * @param {string} label - Label text to draw on the hotspot\\n     * @param {number} [size] - The texture size (should be power of 2)\\n     * @param {number} [borderWidth] - The border width in pixels\\n     * @returns {Texture} The hotspot texture\\n     * @private\\n     */\\n    static _createHotspotTexture(app, label, size = 64, borderWidth = 6) {\\n        // Create canvas for hotspot texture\\n        const canvas = document.createElement('canvas');\\n        canvas.width = size;\\n        canvas.height = size;\\n        const ctx = canvas.getContext('2d');\\n        // First clear with stroke color at zero alpha\\n        ctx.fillStyle = 'white';\\n        ctx.globalAlpha = 0;\\n        ctx.fillRect(0, 0, size, size);\\n        ctx.globalAlpha = 1.0;\\n        // Draw dark circle with light border\\n        const centerX = size / 2;\\n        const centerY = size / 2;\\n        const radius = (size / 2) - 4; // Leave space for border\\n        // Draw main circle\\n        ctx.beginPath();\\n        ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);\\n        ctx.fillStyle = 'black';\\n        ctx.fill();\\n        // Draw border\\n        ctx.beginPath();\\n        ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);\\n        ctx.lineWidth = borderWidth;\\n        ctx.strokeStyle = 'white';\\n        ctx.stroke();\\n        // Draw text\\n        ctx.font = 'bold 32px Arial';\\n        ctx.textAlign = 'center';\\n        ctx.textBaseline = 'middle';\\n        ctx.fillStyle = 'white';\\n        ctx.fillText(label, Math.floor(canvas.width / 2), Math.floor(canvas.height / 2) + 1);\\n        // get pixel data\\n        const imageData = ctx.getImageData(0, 0, size, size);\\n        const data = imageData.data;\\n        // set the color channel of semitransparent pixels to white so the blending at\\n        // the edges is correct\\n        for (let i = 0; i < data.length; i += 4) {\\n            const a = data[i + 3];\\n            if (a < 255) {\\n                data[i] = 255;\\n                data[i + 1] = 255;\\n                data[i + 2] = 255;\\n            }\\n        }\\n        const texture = new Texture(app.graphicsDevice, {\\n            width: size,\\n            height: size,\\n            format: PIXELFORMAT_RGBA8,\\n            magFilter: FILTER_LINEAR,\\n            minFilter: FILTER_LINEAR,\\n            mipmaps: false,\\n            levels: [new Uint8Array(data.buffer)]\\n        });\\n        return texture;\\n    }\\n    /**\\n     * Creates a material for hotspot rendering.\\n     * @param {Texture} texture - The texture to use for emissive and opacity\\n     * @param {object} [options] - Material options\\n     * @param {number} [options.opacity] - Base opacity multiplier\\n     * @param {boolean} [options.depthTest] - Whether to perform depth testing\\n     * @param {boolean} [options.depthWrite] - Whether to write to depth buffer\\n     * @returns {StandardMaterial} The configured material\\n     * @private\\n     */\\n    static _createHotspotMaterial(texture, { opacity = 1, depthTest = true, depthWrite = true } = {}) {\\n        const material = new StandardMaterial();\\n        // Base properties\\n        material.diffuse = Color.BLACK;\\n        material.emissive.copy(Annotation.hotspotColor);\\n        material.emissiveMap = texture;\\n        material.opacityMap = texture;\\n        // Alpha properties\\n        material.opacity = opacity;\\n        material.alphaTest = 0.01;\\n        material.blendState = new BlendState(true, BLENDEQUATION_ADD, BLENDMODE_SRC_ALPHA, BLENDMODE_ONE_MINUS_SRC_ALPHA, BLENDEQUATION_ADD, BLENDMODE_ONE, BLENDMODE_ONE);\\n        // Depth properties\\n        material.depthTest = depthTest;\\n        material.depthWrite = depthWrite;\\n        // Rendering properties\\n        material.cull = CULLFACE_NONE;\\n        material.useLighting = false;\\n        material.shaderChunks.glsl.add({\\n            'litUserMainEndVS': depthClampGlsl\\n        });\\n        material.shaderChunks.wgsl.add({\\n            'litUserMainEndVS': depthClampWgsl\\n        });\\n        material.update();\\n        return material;\\n    }\\n    initialize() {\\n        // Ensure static resources are initialized\\n        Annotation._initializeStatic(this.app);\\n        // Create texture\\n        this.texture = Annotation._createHotspotTexture(this.app, this.label);\\n        // Create material the base and overlay material\\n        this.materials = [\\n            Annotation._createHotspotMaterial(this.texture, {\\n                opacity: 1,\\n                depthTest: true,\\n                depthWrite: true\\n            }),\\n            Annotation._createHotspotMaterial(this.texture, {\\n                opacity: 0.25,\\n                depthTest: false,\\n                depthWrite: false\\n            })\\n        ];\\n        const base = new Entity('base');\\n        const baseMi = new MeshInstance(Annotation.mesh, this.materials[0]);\\n        baseMi.cull = false;\\n        base.addComponent('render', {\\n            layers: [Annotation.layers[0].id],\\n            meshInstances: [baseMi]\\n        });\\n        const overlay = new Entity('overlay');\\n        const overlayMi = new MeshInstance(Annotation.mesh, this.materials[1]);\\n        overlayMi.cull = false;\\n        overlay.addComponent('render', {\\n            layers: [Annotation.layers[1].id],\\n            meshInstances: [overlayMi]\\n        });\\n        this.entity.addChild(base);\\n        this.entity.addChild(overlay);\\n        // Create hotspot dom\\n        this.hotspotDom = document.createElement('div');\\n        this.hotspotDom.className = 'pc-annotation-hotspot';\\n        // Add click handlers\\n        this.hotspotDom.addEventListener('click', (e) => {\\n            e.stopPropagation();\\n            this.showTooltip();\\n        });\\n        const leave = () => {\\n            if (Annotation.hoverAnnotation === this) {\\n                Annotation.hoverAnnotation = null;\\n                this.setHover(false);\\n            }\\n        };\\n        const enter = () => {\\n            if (Annotation.hoverAnnotation !== null) {\\n                Annotation.hoverAnnotation.setHover(false);\\n            }\\n            Annotation.hoverAnnotation = this;\\n            this.setHover(true);\\n        };\\n        this.hotspotDom.addEventListener('pointerenter', enter);\\n        this.hotspotDom.addEventListener('pointerleave', leave);\\n        document.addEventListener('click', () => {\\n            if (Annotation.activeAnnotation === this) {\\n                this.hideTooltip();\\n            }\\n        });\\n        Annotation.parentDom.appendChild(this.hotspotDom);\\n        // Clean up on entity destruction\\n        this.on('destroy', () => {\\n            this.hotspotDom.remove();\\n            if (Annotation.activeAnnotation === this) {\\n                this.hideTooltip();\\n            }\\n            this.materials.forEach(mat => mat.destroy());\\n            this.materials = [];\\n            this.texture.destroy();\\n            this.texture = null;\\n        });\\n        this.app.on('prerender', () => {\\n            this._update();\\n        });\\n    }\\n    /**\\n     * Update screen-space elements and materials for this annotation. Called each frame from the\\n     * prerender callback, and also directly from showTooltip to ensure the tooltip is positioned\\n     * correctly even when the camera hasn't moved (e.g. annotations sharing the same camera pose).\\n     * @private\\n     */\\n    _update() {\\n        if (!Annotation.camera)\\n            return;\\n        const position = this.entity.getPosition();\\n        const screenPos = Annotation.camera.camera.worldToScreen(position);\\n        const { viewMatrix } = Annotation.camera.camera;\\n        viewMatrix.transformPoint(position, vec$1);\\n        if (vec$1.z >= 0) {\\n            this._hideElements();\\n            return;\\n        }\\n        this._updatePositions(screenPos);\\n        this._updateRotationAndScale(-vec$1.z);\\n        // update material opacity and also directly on the uniform so we\\n        // can avoid a full material update\\n        this.materials[0].opacity = Annotation.opacity;\\n        this.materials[1].opacity = 0.25 * Annotation.opacity;\\n        this.materials[0].setParameter('material_opacity', Annotation.opacity);\\n        this.materials[1].setParameter('material_opacity', 0.25 * Annotation.opacity);\\n    }\\n    /**\\n     * Set the hover state of the annotation.\\n     * @param hover - Whether the annotation is hovered\\n     * @private\\n     */\\n    setHover(hover) {\\n        this.materials.forEach((material) => {\\n            material.emissive.copy(hover ? Annotation.hoverColor : Annotation.hotspotColor);\\n            material.update();\\n        });\\n        this.fire('hover', hover);\\n    }\\n    /**\\n     * @private\\n     */\\n    showTooltip() {\\n        Annotation.activeAnnotation = this;\\n        Annotation.tooltipDom.style.visibility = 'visible';\\n        Annotation.tooltipDom.style.opacity = '1';\\n        Annotation.titleDom.textContent = this.title;\\n        Annotation.textDom.textContent = this.text;\\n        // Immediately update incase the camera doesn't move\\n        this._update();\\n        this.fire('show', this);\\n    }\\n    /**\\n     * @private\\n     */\\n    hideTooltip() {\\n        Annotation.activeAnnotation = null;\\n        Annotation.tooltipDom.style.opacity = '0';\\n        // Wait for fade out before hiding\\n        setTimeout(() => {\\n            if (Annotation.tooltipDom.style.opacity === '0') {\\n                Annotation.tooltipDom.style.visibility = 'hidden';\\n                this.fire('hide');\\n            }\\n        }, 200); // Match the transition duration\\n    }\\n    /**\\n     * Hide all elements when annotation is behind camera.\\n     * @private\\n     */\\n    _hideElements() {\\n        this.hotspotDom.style.display = 'none';\\n        if (Annotation.activeAnnotation === this) {\\n            Annotation.tooltipDom.style.visibility = 'hidden';\\n            Annotation.tooltipDom.style.opacity = '0';\\n        }\\n    }\\n    /**\\n     * Update screen-space positions of HTML elements.\\n     * @param {Vec3} screenPos - Screen coordinate\\n     * @private\\n     */\\n    _updatePositions(screenPos) {\\n        // Show and position hotspot\\n        this.hotspotDom.style.display = 'block';\\n        this.hotspotDom.style.left = `${screenPos.x}px`;\\n        this.hotspotDom.style.top = `${screenPos.y}px`;\\n        // Re-show tooltip if it was hidden while behind camera\\n        if (Annotation.activeAnnotation === this) {\\n            Annotation.tooltipDom.style.visibility = 'visible';\\n            Annotation.tooltipDom.style.opacity = '1';\\n        }\\n        // Position tooltip, clamped to viewport\\n        if (Annotation.activeAnnotation === this) {\\n            const tooltip = Annotation.tooltipDom;\\n            const margin = 8;\\n            const arrowOffset = 25;\\n            const tw = tooltip.offsetWidth;\\n            const th = tooltip.offsetHeight;\\n            const vw = window.innerWidth;\\n            const vh = window.innerHeight;\\n            // Default position: to the right of hotspot, vertically centered\\n            let left = screenPos.x + arrowOffset;\\n            let top = screenPos.y - th / 2;\\n            let flipped = false;\\n            // If tooltip overflows right edge, flip to left side of hotspot\\n            if (left + tw > vw - margin) {\\n                left = screenPos.x - arrowOffset - tw;\\n                flipped = true;\\n            }\\n            // Clamp horizontal\\n            left = Math.max(margin, Math.min(left, vw - tw - margin));\\n            // Clamp vertical\\n            top = Math.max(margin, Math.min(top, vh - th - margin));\\n            // Position arrow to point at the hotspot, clamped within the tooltip\\n            const arrowY = Math.max(16, Math.min(screenPos.y - top, th - 16));\\n            tooltip.style.setProperty('--arrow-top', `${arrowY}px`);\\n            tooltip.classList.toggle('arrow-right', !flipped);\\n            tooltip.classList.toggle('arrow-left', flipped);\\n            tooltip.style.transform = 'none';\\n            tooltip.style.left = `${left}px`;\\n            tooltip.style.top = `${top}px`;\\n        }\\n    }\\n    /**\\n     * Update 3D rotation and scale of hotspot planes.\\n     * @param {number} viewDepth - The view-space depth (positive distance along the camera's forward direction)\\n     * @private\\n     */\\n    _updateRotationAndScale(viewDepth) {\\n        // Copy camera rotation to align with view plane\\n        const cameraRotation = Annotation.camera.getRotation();\\n        this._updateHotspotTransform(this.entity, cameraRotation);\\n        // Calculate scale based on view depth to maintain constant screen size\\n        const scale = this._calculateScreenSpaceScale(viewDepth);\\n        this.entity.setLocalScale(scale, scale, scale);\\n    }\\n    /**\\n     * Update rotation of a single hotspot entity.\\n     * @param {Entity} hotspot - The hotspot entity to update\\n     * @param {Quat} cameraRotation - The camera's current rotation\\n     * @private\\n     */\\n    _updateHotspotTransform(hotspot, cameraRotation) {\\n        hotspot.setRotation(cameraRotation);\\n        hotspot.rotateLocal(90, 0, 0);\\n    }\\n    /**\\n     * Calculate scale factor to maintain constant screen-space size.\\n     * @param {number} viewDepth - The view-space depth (positive distance along the camera's forward direction)\\n     * @returns {number} The scale to apply to hotspot entities\\n     * @private\\n     */\\n    _calculateScreenSpaceScale(viewDepth) {\\n        // Use the canvas's CSS/client height instead of graphics device height\\n        const canvas = this.app.graphicsDevice.canvas;\\n        const screenHeight = canvas.clientHeight;\\n        // Use view-space depth (not Euclidean distance) to match the projection matrix\\n        const projMatrix = Annotation.camera.camera.projectionMatrix;\\n        const worldSize = (Annotation.hotspotSize / screenHeight) * (2 * viewDepth / projMatrix.data[5]);\\n        return worldSize;\\n    }\\n}\\n\\nclass Annotations {\\n    annotations;\\n    parentDom;\\n    constructor(global, hasCameraFrame) {\\n        // create dom parent\\n        const parentDom = document.createElement('div');\\n        parentDom.id = 'annotations';\\n        Annotation.parentDom = parentDom;\\n        document.querySelector('#ui').appendChild(parentDom);\\n        this.annotations = global.settings.annotations;\\n        this.parentDom = parentDom;\\n        const { state } = global;\\n        const updateVisibility = () => {\\n            const firstPersonGamingControls = ((state.cameraMode === 'walk' || state.cameraMode === 'fly') &&\\n                state.gamingControls);\\n            const hidden = state.controlsHidden || firstPersonGamingControls;\\n            parentDom.style.display = hidden ? 'none' : 'block';\\n            Annotation.opacity = hidden ? 0.0 : 1.0;\\n            if (this.annotations.length > 0) {\\n                global.app.renderNextFrame = true;\\n            }\\n        };\\n        global.events.on('controlsHidden:changed', updateVisibility);\\n        global.events.on('cameraMode:changed', updateVisibility);\\n        global.events.on('gamingControls:changed', updateVisibility);\\n        updateVisibility();\\n        if (hasCameraFrame) {\\n            Annotation.hotspotColor.gamma();\\n            Annotation.hoverColor.gamma();\\n        }\\n        // create annotation entities\\n        const parent = global.app.root;\\n        const scriptMap = new Map();\\n        for (let i = 0; i < this.annotations.length; i++) {\\n            const ann = this.annotations[i];\\n            const entity = new Entity();\\n            entity.addComponent('script');\\n            entity.script.create(Annotation);\\n            const script = entity.script;\\n            script.annotation.label = (i + 1).toString();\\n            script.annotation.title = ann.title;\\n            script.annotation.text = ann.text;\\n            entity.setPosition(ann.position[0], ann.position[1], ann.position[2]);\\n            parent.addChild(entity);\\n            scriptMap.set(ann, script.annotation);\\n            // handle an annotation being activated/shown\\n            script.annotation.on('show', () => {\\n                global.events.fire('annotation.activate', ann);\\n            });\\n            script.annotation.on('hide', () => {\\n                global.events.fire('annotation.deactivate');\\n            });\\n            // re-render if hover state changes\\n            script.annotation.on('hover', (hover) => {\\n                global.app.renderNextFrame = true;\\n            });\\n        }\\n        // handle navigator requesting an annotation to be shown\\n        global.events.on('annotation.navigate', (ann) => {\\n            const script = scriptMap.get(ann);\\n            if (script) {\\n                script.showTooltip();\\n            }\\n        });\\n    }\\n}\\n\\n/**\\n * Creates a figure-8 (lemniscate / infinity sign) camera animation track.\\n * The camera traces a horizontal figure-8 centered at its initial position\\n * while looking at the target point.\\n *\\n * @param position - Starting location of the camera.\\n * @param target - Target point the camera looks at.\\n * @param fov - The camera field of view.\\n * @param size - Controls the scale of the figure-8 path. The left-right extent equals `size`\\n * and the forward-back extent is half that (`size * 0.5`).\\n * @param keys - The number of keyframes in the animation.\\n * @param duration - The duration of the animation in seconds.\\n * @returns The animation track object containing position and target keyframes.\\n */\\nconst createFigure8Track = (position, target, fov, size = 1, keys = 24, duration = 20) => {\\n    const times = new Array(keys).fill(0).map((_, i) => i / keys * duration);\\n    const positions = [];\\n    const targets = [];\\n    const fovs = new Array(keys).fill(fov);\\n    const amplitude = size * 0.5;\\n    const dx = position.x - target.x;\\n    const dz = position.z - target.z;\\n    const horizontalDist = Math.sqrt(dx * dx + dz * dz);\\n    // compute local horizontal axes relative to camera-target direction\\n    let rightX, rightZ;\\n    let fwdX, fwdZ;\\n    if (horizontalDist > 0.001) {\\n        fwdX = dx / horizontalDist;\\n        fwdZ = dz / horizontalDist;\\n        rightX = -fwdZ;\\n        rightZ = fwdX;\\n    }\\n    else {\\n        fwdX = 0;\\n        fwdZ = 1;\\n        rightX = 1;\\n        rightZ = 0;\\n    }\\n    for (let i = 0; i < keys; ++i) {\\n        const t = i / keys * Math.PI * 2;\\n        // lemniscate offsets: sin(t) for left-right, sin(2t)/2 for forward-back\\n        const offsetRight = amplitude * Math.sin(t);\\n        const offsetFwd = amplitude * Math.sin(2 * t) / 2;\\n        positions.push(position.x + rightX * offsetRight + fwdX * offsetFwd);\\n        positions.push(position.y);\\n        positions.push(position.z + rightZ * offsetRight + fwdZ * offsetFwd);\\n        targets.push(target.x);\\n        targets.push(target.y);\\n        targets.push(target.z);\\n    }\\n    return {\\n        name: 'figure8',\\n        duration,\\n        frameRate: 1,\\n        loopMode: 'repeat',\\n        interpolation: 'spline',\\n        smoothness: 1,\\n        keyframes: {\\n            times,\\n            values: {\\n                position: positions,\\n                target: targets,\\n                fov: fovs\\n            }\\n        }\\n    };\\n};\\n\\n/**\\n * Creates a rotation animation track\\n *\\n * @param position - Starting location of the camera.\\n * @param target - Target point around which to rotate\\n * @param fov - The camera field of view.\\n * @param keys - The number of keys in the animation.\\n * @param duration - The duration of the animation in seconds.\\n * @returns - The animation track object containing position and target keyframes.\\n */\\nconst createRotateTrack = (position, target, fov, keys = 12, duration = 20) => {\\n    const times = new Array(keys).fill(0).map((_, i) => i / keys * duration);\\n    const positions = [];\\n    const targets = [];\\n    const fovs = new Array(keys).fill(fov);\\n    const dx = position.x - target.x;\\n    const dy = position.y - target.y;\\n    const dz = position.z - target.z;\\n    const horizontalRadius = Math.sqrt(dx * dx + dz * dz);\\n    const totalDist = Math.sqrt(dx * dx + dy * dy + dz * dz);\\n    // when the offset is nearly vertical, use a fraction of the total distance\\n    // as the orbit radius so the camera actually moves in a circle\\n    const minRadius = totalDist * 0.3;\\n    const radius = Math.max(horizontalRadius, minRadius);\\n    const startAngle = Math.atan2(dx, dz);\\n    for (let i = 0; i < keys; ++i) {\\n        const angle = startAngle - i / keys * Math.PI * 2;\\n        positions.push(target.x + radius * Math.sin(angle));\\n        positions.push(target.y + dy);\\n        positions.push(target.z + radius * Math.cos(angle));\\n        targets.push(target.x);\\n        targets.push(target.y);\\n        targets.push(target.z);\\n    }\\n    return {\\n        name: 'rotate',\\n        duration,\\n        frameRate: 1,\\n        loopMode: 'repeat',\\n        interpolation: 'spline',\\n        smoothness: 1,\\n        keyframes: {\\n            times,\\n            values: {\\n                position: positions,\\n                target: targets,\\n                fov: fovs\\n            }\\n        }\\n    };\\n};\\n\\n/**\\n * Damping function to smooth out transitions.\\n *\\n * @param damping - Damping factor (0 < damping < 1).\\n * @param dt - Delta time in seconds.\\n * @returns - Damping factor adjusted for the delta time.\\n */\\nconst damp = (damping, dt) => 1 - Math.pow(damping, dt * 1000);\\n/**\\n * Easing function for smooth transitions.\\n *\\n * @param x - Input value in the range [0, 1].\\n * @returns - Output value in the range [0, 1].\\n */\\nconst easeOut = (x) => (1 - (2 ** (-10 * x))) / (1 - (2 ** -10));\\n/**\\n * Modulus function that handles negative values correctly.\\n *\\n * @param n - The number to be modulated.\\n * @param m - The modulus value.\\n * @returns - The result of n mod m, adjusted to be non-negative.\\n */\\nconst mod = (n, m) => ((n % m) + m) % m;\\nconst nearlyEquals = (a, b, epsilon = 1e-4) => {\\n    return !a.some((v, i) => Math.abs(v - b[i]) >= epsilon);\\n};\\nconst vecToAngles = (result, vec) => {\\n    const radToDeg = 180 / Math.PI;\\n    const horizLenSq = vec.x * vec.x + vec.z * vec.z;\\n    result.x = Math.asin(Math.max(-1, Math.min(1, vec.y))) * radToDeg;\\n    result.y = horizLenSq > 1e-8 ? Math.atan2(-vec.x, -vec.z) * radToDeg : 0;\\n    result.z = 0;\\n    return result;\\n};\\n\\n/**\\n * Shared damping factor for controller smoothing (rotate / move / zoom) so\\n * orbit, fly, and walk feel the same. Used as `damp(damping, dt)` →\\n * `1 - damping^(dt*1000)`. Higher means smoother / more lag. Not used for\\n * physics-style velocity decay (e.g. walk's grounded/air velocity damping),\\n * which has different tuning needs.\\n */\\nconst DEFAULT_CONTROLLER_DAMPING = 0.95;\\nconst rotation$1 = new Quat();\\n/**\\n * Apply a CameraFrame rotate delta to camera Euler angles.\\n *\\n * CameraFrame rotate uses [yaw, pitch, roll]-style input deltas, while camera\\n * angles are stored as [pitch, yaw, roll].\\n *\\n * @param angles - Camera Euler angles to mutate.\\n * @param rotate - Frame rotate delta.\\n * @param minPitch - Minimum pitch angle in degrees.\\n * @param maxPitch - Maximum pitch angle in degrees.\\n * @returns The mutated angles.\\n */\\nconst applyFrameRotation = (angles, rotate, minPitch = -90, maxPitch = 90) => {\\n    angles.x -= rotate[1];\\n    angles.y -= rotate[0];\\n    angles.z = 0;\\n    angles.x = math.clamp(angles.x, minPitch, maxPitch);\\n    return angles;\\n};\\n/**\\n * Calculate camera-relative basis vectors from Euler angles.\\n *\\n * @param angles - Camera Euler angles in degrees.\\n * @param forward - Receives the forward vector.\\n * @param right - Receives the right vector.\\n * @param up - Receives the up vector.\\n */\\nconst setCameraBasis = (angles, forward, right, up) => {\\n    rotation$1.setFromEulerAngles(angles);\\n    rotation$1.transformVector(Vec3.FORWARD, forward);\\n    rotation$1.transformVector(Vec3.RIGHT, right);\\n    rotation$1.transformVector(Vec3.UP, up);\\n};\\n/**\\n * Calculate a camera forward vector from Euler angles.\\n *\\n * @param angles - Camera Euler angles in degrees.\\n * @param forward - Receives the forward vector.\\n */\\nconst setCameraForward = (angles, forward) => {\\n    rotation$1.setFromEulerAngles(angles);\\n    rotation$1.transformVector(Vec3.FORWARD, forward);\\n};\\n/**\\n * Calculate yaw-only movement basis vectors.\\n *\\n * @param yaw - Camera yaw angle in degrees.\\n * @param forward - Receives the horizontal forward vector.\\n * @param right - Receives the horizontal right vector.\\n */\\nconst setYawBasis = (yaw, forward, right) => {\\n    rotation$1.setFromEulerAngles(0, yaw, 0);\\n    rotation$1.transformVector(Vec3.FORWARD, forward);\\n    rotation$1.transformVector(Vec3.RIGHT, right);\\n};\\n/**\\n * Build a world-space offset from local movement along camera basis vectors.\\n *\\n * @param out - Receives the world-space offset.\\n * @param x - Local right movement.\\n * @param y - Local up movement.\\n * @param z - Local forward movement.\\n * @param forward - Forward basis vector.\\n * @param right - Right basis vector.\\n * @param up - Up basis vector.\\n * @returns The mutated output vector.\\n */\\nconst setBasisOffset = (out, x, y, z, forward, right, up) => {\\n    out.set(right.x * x + up.x * y + forward.x * z, right.y * x + up.y * y + forward.y * z, right.z * x + up.z * y + forward.z * z);\\n    return out;\\n};\\n/**\\n * Lerp Euler angles toward a target using frame-rate-independent shortest-path\\n * interpolation. Yaw/roll on both `angles` and `target` are wrapped into\\n * `[0, 360)` so `lerpAngle`'s single-shift shortest-path stays valid after\\n * many full rotations (otherwise the camera takes the long way around). Pitch\\n * is left untouched since callers clamp it.\\n *\\n * @param angles - Current angles, mutated toward target.\\n * @param target - Target angles. Yaw/roll are wrapped in place to keep\\n * accumulated drift bounded across frames.\\n * @param damping - Damping factor in [0, 1]. Higher = smoother (1 = never moves).\\n * @param dt - Delta time in seconds.\\n * @returns The mutated angles.\\n */\\nconst dampAngles = (angles, target, damping, dt) => {\\n    if (dt <= 0) {\\n        return angles;\\n    }\\n    const t = damp(damping, dt);\\n    angles.y = mod(angles.y, 360);\\n    angles.z = mod(angles.z, 360);\\n    target.y = mod(target.y, 360);\\n    target.z = mod(target.z, 360);\\n    angles.x = math.lerpAngle(angles.x, target.x, t);\\n    angles.y = math.lerpAngle(angles.y, target.y, t);\\n    angles.z = math.lerpAngle(angles.z, target.z, t);\\n    return angles;\\n};\\n/**\\n * Discard any pending input deltas in the frame. `InputFrame.read()` zeros\\n * deltas as a side-effect of reading, so calling this prevents accumulated\\n * input from leaking into the next controller when a non-input-driven mode\\n * (e.g. animation) is active.\\n *\\n * @param frame - The camera frame whose deltas should be drained.\\n */\\nconst drainInputFrame = (frame) => {\\n    frame.read();\\n};\\n\\nclass CubicSpline {\\n    // control times\\n    times;\\n    // control data: in-tangent, point, out-tangent\\n    knots;\\n    // dimension of the knot points\\n    dim;\\n    constructor(times, knots) {\\n        this.times = times;\\n        this.knots = knots;\\n        this.dim = knots.length / times.length / 3;\\n    }\\n    evaluate(time, result) {\\n        const { times } = this;\\n        const last = times.length - 1;\\n        if (time <= times[0]) {\\n            this.getKnot(0, result);\\n        }\\n        else if (time >= times[last]) {\\n            this.getKnot(last, result);\\n        }\\n        else {\\n            let seg = 0;\\n            while (time >= times[seg + 1]) {\\n                seg++;\\n            }\\n            this.evaluateSegment(seg, (time - times[seg]) / (times[seg + 1] - times[seg]), result);\\n        }\\n    }\\n    getKnot(index, result) {\\n        const { knots, dim } = this;\\n        const idx = index * 3 * dim;\\n        for (let i = 0; i < dim; ++i) {\\n            result[i] = knots[idx + i * 3 + 1];\\n        }\\n    }\\n    // evaluate the spline segment at the given normalized time t\\n    evaluateSegment(segment, t, result) {\\n        const { knots, dim } = this;\\n        const t2 = t * t;\\n        const twot = t + t;\\n        const omt = 1 - t;\\n        const omt2 = omt * omt;\\n        let idx = segment * dim * 3; // each knot has 3 values: tangent in, value, tangent out\\n        for (let i = 0; i < dim; ++i) {\\n            const p0 = knots[idx + 1]; // p0\\n            const m0 = knots[idx + 2]; // outgoing tangent\\n            const m1 = knots[idx + dim * 3]; // incoming tangent\\n            const p1 = knots[idx + dim * 3 + 1]; // p1\\n            idx += 3;\\n            result[i] =\\n                p0 * ((1 + twot) * omt2) +\\n                    m0 * (t * omt2) +\\n                    p1 * (t2 * (3 - twot)) +\\n                    m1 * (t2 * (t - 1));\\n        }\\n    }\\n    // calculate cubic spline knots from points\\n    // times: time values for each control point\\n    // points: control point values to be interpolated (n dimensional)\\n    // smoothness: 0 = linear, 1 = smooth\\n    static calcKnots(times, points, smoothness) {\\n        const n = times.length;\\n        const dim = points.length / n;\\n        const knots = new Array(n * dim * 3);\\n        for (let i = 0; i < n; i++) {\\n            const t = times[i];\\n            for (let j = 0; j < dim; j++) {\\n                const idx = i * dim + j;\\n                const p = points[idx];\\n                let tangent;\\n                if (i === 0) {\\n                    tangent = (points[idx + dim] - p) / (times[i + 1] - t);\\n                }\\n                else if (i === n - 1) {\\n                    tangent = (p - points[idx - dim]) / (t - times[i - 1]);\\n                }\\n                else {\\n                    tangent = (points[idx + dim] - points[idx - dim]) / (times[i + 1] - times[i - 1]);\\n                }\\n                // convert to derivatives w.r.t normalized segment parameter\\n                const inScale = i > 0 ? (times[i] - times[i - 1]) : (times[1] - times[0]);\\n                const outScale = i < n - 1 ? (times[i + 1] - times[i]) : (times[i] - times[i - 1]);\\n                knots[idx * 3] = tangent * inScale * smoothness;\\n                knots[idx * 3 + 1] = p;\\n                knots[idx * 3 + 2] = tangent * outScale * smoothness;\\n            }\\n        }\\n        return knots;\\n    }\\n    static fromPoints(times, points, smoothness = 1) {\\n        return new CubicSpline(times, CubicSpline.calcKnots(times, points, smoothness));\\n    }\\n    // create a looping spline by duplicating animation points at the end and beginning\\n    static fromPointsLooping(length, times, points, smoothness = 1) {\\n        if (times.length < 2) {\\n            return CubicSpline.fromPoints(times, points);\\n        }\\n        const dim = points.length / times.length;\\n        const newTimes = times.slice();\\n        const newPoints = points.slice();\\n        // append first two points\\n        newTimes.push(length + times[0], length + times[1]);\\n        newPoints.push(...points.slice(0, dim * 2));\\n        // prepend last two points\\n        newTimes.splice(0, 0, times[times.length - 2] - length, times[times.length - 1] - length);\\n        newPoints.splice(0, 0, ...points.slice(points.length - dim * 2));\\n        return CubicSpline.fromPoints(newTimes, newPoints, smoothness);\\n    }\\n}\\n\\n// track an animation cursor with support for repeat and ping-pong loop modes\\nclass AnimCursor {\\n    duration = 0;\\n    loopMode = 'none';\\n    timer = 0;\\n    cursor = 0;\\n    constructor(duration, loopMode) {\\n        this.reset(duration, loopMode);\\n    }\\n    update(deltaTime) {\\n        // update animation timer\\n        this.timer += deltaTime;\\n        // update the track cursor\\n        this.cursor += deltaTime;\\n        if (this.cursor >= this.duration) {\\n            switch (this.loopMode) {\\n                case 'none':\\n                    this.cursor = this.duration;\\n                    break;\\n                case 'repeat':\\n                    this.cursor %= this.duration;\\n                    break;\\n                case 'pingpong':\\n                    this.cursor %= (this.duration * 2);\\n                    break;\\n            }\\n        }\\n    }\\n    reset(duration, loopMode) {\\n        this.duration = duration;\\n        this.loopMode = loopMode;\\n        this.timer = 0;\\n        this.cursor = 0;\\n    }\\n    set value(value) {\\n        this.cursor = mod(value, this.duration);\\n    }\\n    get value() {\\n        return this.cursor > this.duration ? 2 * this.duration - this.cursor : this.cursor;\\n    }\\n}\\n\\n// manage the state of a camera animation track\\nclass AnimState {\\n    spline;\\n    cursor = new AnimCursor(0, 'none');\\n    frameRate;\\n    result = [];\\n    position = new Vec3();\\n    target = new Vec3();\\n    fov = 90;\\n    constructor(spline, duration, loopMode, frameRate) {\\n        this.spline = spline;\\n        this.cursor.reset(duration, loopMode);\\n        this.frameRate = frameRate;\\n    }\\n    // update given delta time\\n    update(dt) {\\n        const { cursor, result, spline, frameRate, position, target } = this;\\n        // update the animation cursor\\n        cursor.update(dt);\\n        // evaluate the spline\\n        spline.evaluate(cursor.value * frameRate, result);\\n        if (result.every(isFinite)) {\\n            position.set(result[0], result[1], result[2]);\\n            target.set(result[3], result[4], result[5]);\\n            this.fov = result[6];\\n        }\\n    }\\n    // construct an animation from a settings track\\n    static fromTrack(track) {\\n        const { keyframes, duration, frameRate, loopMode, smoothness } = track;\\n        const { times, values } = keyframes;\\n        const { position, target, fov } = values;\\n        // construct the points array containing position, target and fov\\n        const points = [];\\n        for (let i = 0; i < times.length; i++) {\\n            points.push(position[i * 3], position[i * 3 + 1], position[i * 3 + 2]);\\n            points.push(target[i * 3], target[i * 3 + 1], target[i * 3 + 2]);\\n            points.push(fov[i]);\\n        }\\n        const extra = (duration === times[times.length - 1] / frameRate) ? 1 : 0;\\n        const spline = CubicSpline.fromPointsLooping((duration + extra) * frameRate, times, points, smoothness);\\n        return new AnimState(spline, duration, loopMode, frameRate);\\n    }\\n}\\n\\nclass AnimController {\\n    animState;\\n    constructor(animTrack) {\\n        this.animState = AnimState.fromTrack(animTrack);\\n        this.animState.update(0);\\n    }\\n    onEnter(camera) {\\n        camera.look(this.animState.position, this.animState.target);\\n        camera.fov = this.animState.fov;\\n    }\\n    update(deltaTime, inputFrame, camera) {\\n        this.animState.update(deltaTime);\\n        camera.look(this.animState.position, this.animState.target);\\n        camera.fov = this.animState.fov;\\n        drainInputFrame(inputFrame);\\n    }\\n    onExit(camera) {\\n    }\\n}\\n\\nconst rotation = new Quat();\\nconst avec = new Vec3();\\nconst bvec = new Vec3();\\nclass Camera {\\n    position = new Vec3();\\n    angles = new Vec3();\\n    distance = 1;\\n    fov = 65;\\n    constructor(other) {\\n        if (other) {\\n            this.copy(other);\\n        }\\n    }\\n    copy(source) {\\n        this.position.copy(source.position);\\n        this.angles.copy(source.angles);\\n        this.distance = source.distance;\\n        this.fov = source.fov;\\n    }\\n    lerp(a, b, t) {\\n        a.calcFocusPoint(avec);\\n        b.calcFocusPoint(bvec);\\n        this.position.lerp(a.position, b.position, t);\\n        avec.lerp(avec, bvec, t).sub(this.position);\\n        this.distance = avec.length();\\n        vecToAngles(this.angles, avec.mulScalar(1.0 / this.distance));\\n        this.fov = math.lerp(a.fov, b.fov, t);\\n    }\\n    look(from, to) {\\n        this.position.copy(from);\\n        this.distance = from.distance(to);\\n        const dir = avec.sub2(to, from).normalize();\\n        vecToAngles(this.angles, dir);\\n    }\\n    calcFocusPoint(result) {\\n        rotation.setFromEulerAngles(this.angles)\\n            .transformVector(Vec3.FORWARD, result)\\n            .mulScalar(this.distance)\\n            .add(this.position);\\n    }\\n}\\n\\n/**\\n * Captures a controller's pose at its initial spawn so it can be restored\\n * later (e.g. via the \\\"reset\\\" UI gesture). Shared by fly and walk controllers\\n * which both implement `resetToSpawn`.\\n *\\n * Position / angles / distance are the basic camera-pose components. Callers\\n * with extra controller-specific state (e.g. walk's grounded flag) keep that\\n * alongside as a separate field.\\n */\\nclass SpawnState {\\n    _position = new Vec3();\\n    _angles = new Vec3();\\n    _distance = 1;\\n    _has = false;\\n    /**\\n     * True once `store` has been called at least once.\\n     *\\n     * @returns Whether a spawn pose has been captured.\\n     */\\n    get has() {\\n        return this._has;\\n    }\\n    /**\\n     * Capture the given pose as the spawn state.\\n     *\\n     * @param position - World-space position to remember.\\n     * @param angles - Euler angles to remember.\\n     * @param distance - Camera distance (orbit-style) to remember.\\n     */\\n    store(position, angles, distance) {\\n        this._position.copy(position);\\n        this._angles.copy(angles);\\n        this._distance = distance;\\n        this._has = true;\\n    }\\n    /**\\n     * Forget any previously-stored spawn pose so a subsequent `has` check\\n     * reports false. Used by controllers that scope spawn to a single mode\\n     * entry (e.g. walk).\\n     */\\n    clear() {\\n        this._has = false;\\n    }\\n    /**\\n     * Copy the captured pose into the supplied targets. Caller must check\\n     * `has` first; calling `restore` before `store` returns the field\\n     * defaults (position and angles zeroed, distance `1`).\\n     *\\n     * @param position - Mutated with the stored world position.\\n     * @param angles - Mutated with the stored Euler angles.\\n     * @returns The stored camera distance.\\n     */\\n    restore(position, angles) {\\n        position.copy(this._position);\\n        angles.copy(this._angles);\\n        return this._distance;\\n    }\\n}\\n\\n/** Small clearance that keeps the sphere from resting exactly on a collision surface */\\nconst COLLISION_SKIN = 1e-3;\\n/** Maximum surface planes to slide along in a single frame */\\nconst MAX_SLIDE_ITERATIONS = 3;\\nconst MIN_MOVE_SQ = 1e-10;\\nconst INV_SQRT2 = 1 / Math.sqrt(2);\\nconst SWEEP_RAY_OFFSETS = [\\n    [0, 0, true],\\n    [1, 0, false],\\n    [-1, 0, false],\\n    [0, 1, false],\\n    [0, -1, false],\\n    [INV_SQRT2, INV_SQRT2, false],\\n    [-INV_SQRT2, INV_SQRT2, false],\\n    [-INV_SQRT2, -INV_SQRT2, false],\\n    [INV_SQRT2, -INV_SQRT2, false]\\n];\\nconst v$1 = new Vec3();\\nconst remainingMove = new Vec3();\\nconst collisionPush = new Vec3();\\nconst sweepDir = new Vec3();\\nconst sweepNormal = new Vec3();\\nconst sweepTangent = new Vec3();\\nconst sweepBitangent = new Vec3();\\nconst sweepOrigin = new Vec3();\\nconst worldUp = new Vec3(0, 1, 0);\\nconst worldRight = new Vec3(1, 0, 0);\\n/** Pre-allocated push-out vector for sphere collision */\\nconst pushOut = { x: 0, y: 0, z: 0 };\\nconst sweepHit = {\\n    x: 0,\\n    y: 0,\\n    z: 0,\\n    nx: 0,\\n    ny: 1,\\n    nz: 0,\\n    travel: 0\\n};\\nclass SphereMover {\\n    collision = null;\\n    radius;\\n    _lastClearPosition = new Vec3();\\n    _hasLastClearPosition = false;\\n    constructor(radius) {\\n        this.radius = radius;\\n    }\\n    reset(position) {\\n        this._setLastClearPosition(position);\\n    }\\n    move(position, move) {\\n        if (!this.collision) {\\n            position.add(move);\\n            this._setLastClearPosition(position);\\n            return;\\n        }\\n        remainingMove.copy(move);\\n        if (this._isMoveComplete(remainingMove)) {\\n            this.resolve(position);\\n            return;\\n        }\\n        for (let i = 0; i < MAX_SLIDE_ITERATIONS; i++) {\\n            if (this._isMoveComplete(remainingMove)) {\\n                break;\\n            }\\n            if (!this._moveAndSlide(position, remainingMove)) {\\n                break;\\n            }\\n        }\\n    }\\n    resolve(position) {\\n        if (!this.collision) {\\n            this._setLastClearPosition(position);\\n            return;\\n        }\\n        this._resolveSphere(position, collisionPush);\\n        if (!this._isSphereClear(position) && this._hasLastClearPosition) {\\n            position.copy(this._lastClearPosition);\\n        }\\n        if (this._isSphereClear(position)) {\\n            this._setLastClearPosition(position);\\n        }\\n    }\\n    _moveAndSlide(position, move) {\\n        const moveSq = move.x * move.x + move.y * move.y + move.z * move.z;\\n        const distance = Math.sqrt(moveSq);\\n        sweepDir.copy(move).mulScalar(1 / distance);\\n        if (!this._querySweep(position, sweepDir, distance, sweepHit)) {\\n            position.add(move);\\n            this.resolve(position);\\n            return false;\\n        }\\n        position.add(v$1.copy(sweepDir).mulScalar(sweepHit.travel));\\n        this.resolve(position);\\n        sweepNormal.set(sweepHit.nx, sweepHit.ny, sweepHit.nz);\\n        move.add(v$1.copy(sweepDir).mulScalar(-sweepHit.travel));\\n        this._clipMove(move, sweepNormal);\\n        return true;\\n    }\\n    _querySweep(position, dir, distance, out) {\\n        if (Math.abs(dir.y) < 0.99) {\\n            sweepTangent.cross(dir, worldUp).normalize();\\n        }\\n        else {\\n            sweepTangent.cross(dir, worldRight).normalize();\\n        }\\n        sweepBitangent.cross(dir, sweepTangent).normalize();\\n        let found = false;\\n        let bestTravel = Infinity;\\n        for (let i = 0; i < SWEEP_RAY_OFFSETS.length; i++) {\\n            const [tx, ty, centerRay] = SWEEP_RAY_OFFSETS[i];\\n            const radiusOffset = centerRay ? 0 : this.radius;\\n            const rayExtension = centerRay ? this.radius : 0;\\n            sweepOrigin.copy(position);\\n            if (!centerRay) {\\n                sweepOrigin.add(v$1.copy(sweepTangent).mulScalar(tx * radiusOffset));\\n                sweepOrigin.add(v$1.copy(sweepBitangent).mulScalar(ty * radiusOffset));\\n            }\\n            const hit = this.collision.queryRay(sweepOrigin.x, sweepOrigin.y, sweepOrigin.z, dir.x, dir.y, dir.z, distance + rayExtension + COLLISION_SKIN);\\n            if (!hit) {\\n                continue;\\n            }\\n            const hx = hit.x - sweepOrigin.x;\\n            const hy = hit.y - sweepOrigin.y;\\n            const hz = hit.z - sweepOrigin.z;\\n            const hitDistance = Math.max(0, hx * dir.x + hy * dir.y + hz * dir.z);\\n            const clearance = centerRay ? this.radius : 0;\\n            const travel = math.clamp(hitDistance - clearance - COLLISION_SKIN, 0, distance);\\n            if (travel >= bestTravel) {\\n                continue;\\n            }\\n            const surfaceNormal = this.collision.querySurfaceNormal(hit.x, hit.y, hit.z, dir.x, dir.y, dir.z);\\n            found = true;\\n            bestTravel = travel;\\n            out.x = hit.x;\\n            out.y = hit.y;\\n            out.z = hit.z;\\n            out.nx = surfaceNormal.nx;\\n            out.ny = surfaceNormal.ny;\\n            out.nz = surfaceNormal.nz;\\n            out.travel = travel;\\n        }\\n        return found;\\n    }\\n    _resolveSphere(position, push) {\\n        // `querySphere` is already corner-aware (resolveIterative inside the\\n        // collider iterates up to 4 passes with constraint-normal projection),\\n        // so a single call here is enough.\\n        if (!this.collision.querySphere(position.x, position.y, position.z, this.radius, pushOut)) {\\n            push.set(0, 0, 0);\\n            return false;\\n        }\\n        position.x += pushOut.x;\\n        position.y += pushOut.y;\\n        position.z += pushOut.z;\\n        push.x = pushOut.x;\\n        push.y = pushOut.y;\\n        push.z = pushOut.z;\\n        return true;\\n    }\\n    _clipMove(move, push) {\\n        const normalSq = push.x * push.x + push.y * push.y + push.z * push.z;\\n        if (normalSq <= MIN_MOVE_SQ) {\\n            return;\\n        }\\n        const invPushLen = 1 / Math.sqrt(normalSq);\\n        const nx = push.x * invPushLen;\\n        const ny = push.y * invPushLen;\\n        const nz = push.z * invPushLen;\\n        const dot = move.x * nx + move.y * ny + move.z * nz;\\n        if (dot < 0) {\\n            move.x -= dot * nx;\\n            move.y -= dot * ny;\\n            move.z -= dot * nz;\\n        }\\n    }\\n    _isMoveComplete(move) {\\n        return move.x * move.x + move.y * move.y + move.z * move.z <= MIN_MOVE_SQ;\\n    }\\n    _isSphereClear(position) {\\n        return !this.collision.querySphere(position.x, position.y, position.z, this.radius, pushOut);\\n    }\\n    _setLastClearPosition(position) {\\n        this._lastClearPosition.copy(position);\\n        this._hasLastClearPosition = !this.collision || this._isSphereClear(position);\\n    }\\n}\\n\\n/** Maximum Euclidean distance (metres) from the spawn origin to search for a valid placement. */\\nconst SEARCH_RADIUS = 5;\\nconst SEARCH_RADIUS_SQ = SEARCH_RADIUS * SEARCH_RADIUS;\\n/** Ray budget when probing for ground/ceiling under or above a candidate column. */\\nconst RAY_MAX_DIST = 1000;\\n// Scratch values reused across calls — these helpers run only at spawn time\\n// so the lack of re-entrancy is fine.\\nconst scratchPush = { x: 0, y: 0, z: 0 };\\n/**\\n * Find the closest sphere placement to (ox, oy, oz) where a sphere of `radius`\\n * fits clear of geometry. Output is the sphere centre. Used for fly-camera\\n * spawn — fly cameras have no ground constraint.\\n *\\n * Lattice search across voxel-spaced offsets from the origin (step =\\n * `collision.voxelResolution`), ordered by Chebyshev shell with Euclidean\\n * tie-break within a shell. Search bounded by `SEARCH_RADIUS`.\\n *\\n * @param collision - Active collision implementation.\\n * @param ox - Origin X (world space).\\n * @param oy - Origin Y (world space).\\n * @param oz - Origin Z (world space).\\n * @param radius - Sphere radius.\\n * @param out - Receives the sphere centre on success.\\n * @returns True if a valid placement was found.\\n */\\nconst findSphereSpawn = (collision, ox, oy, oz, radius, out) => {\\n    const step = collision.voxelResolution;\\n    const maxCells = Math.ceil(SEARCH_RADIUS / step);\\n    let bestDistSq = Infinity;\\n    let found = false;\\n    for (let r = 0; r <= maxCells; r++) {\\n        const shellMinDistSq = (r * step) * (r * step);\\n        if (shellMinDistSq >= bestDistSq)\\n            break;\\n        for (let dy = -r; dy <= r; dy++) {\\n            const absDy = dy < 0 ? -dy : dy;\\n            for (let dz = -r; dz <= r; dz++) {\\n                const absDz = dz < 0 ? -dz : dz;\\n                for (let dx = -r; dx <= r; dx++) {\\n                    const absDx = dx < 0 ? -dx : dx;\\n                    // Only cells on the Chebyshev shell of radius r.\\n                    if (absDx < r && absDy < r && absDz < r)\\n                        continue;\\n                    const distSq = (dx * dx + dy * dy + dz * dz) * step * step;\\n                    if (distSq >= bestDistSq || distSq > SEARCH_RADIUS_SQ)\\n                        continue;\\n                    const cx = ox + dx * step;\\n                    const cy = oy + dy * step;\\n                    const cz = oz + dz * step;\\n                    if (collision.querySphere(cx, cy, cz, radius, scratchPush))\\n                        continue;\\n                    bestDistSq = distSq;\\n                    out.x = cx;\\n                    out.y = cy;\\n                    out.z = cz;\\n                    found = true;\\n                }\\n            }\\n        }\\n    }\\n    return found;\\n};\\n/**\\n * Find the closest standable cylinder placement to (ox, oy, oz). Output is the\\n * floor world position the cylinder rests on (highest geometry hit across the\\n * footprint). Used for walk-camera spawn.\\n *\\n * The algorithm:\\n *\\n * 1. Lattice search for the closest free voxel `C` (per `isFreeAt`) that has\\n *    geometry somewhere below — i.e. a downward ray from `C` hits.\\n * 2. At `(C.x, C.z)`, fan rays up and down from `C.y` through every cell\\n *    (step = `collision.voxelResolution`) within the xz footprint disc.\\n *    Compute, across columns:\\n *      - `floor = max(yDown_i)`         (highest ground in the footprint)\\n *      - `ceiling = min(yUp_i)`         (lowest obstruction overhead, or ∞)\\n *    Every column must have a `yDown` hit; otherwise the cylinder is partly\\n *    unsupported and the candidate is discarded.\\n * 3. The cylinder fits iff `floor + halfHeight ≤ ceiling - halfHeight`,\\n *    i.e. enough vertical clearance for the full cylinder above the floor.\\n *    The \\\"resting on ground\\\" placement has centre at `floor + halfHeight`.\\n *\\n * Cylinder math (flat ends, no hemispheres) intentionally matches the carve,\\n * which used a separable XYZ dilation.\\n *\\n * @param collision - Active collision implementation.\\n * @param ox - Origin X (world space).\\n * @param oy - Origin Y (world space).\\n * @param oz - Origin Z (world space).\\n * @param halfHeight - Cylinder half-height (full height = 2 × halfHeight).\\n * @param radius - Cylinder radius.\\n * @param out - Receives the floor position the cylinder rests on.\\n * @returns True if a valid placement was found.\\n */\\nconst findCylinderSpawn = (collision, ox, oy, oz, halfHeight, radius, out) => {\\n    const step = collision.voxelResolution;\\n    const maxCells = Math.ceil(SEARCH_RADIUS / step);\\n    // Round up so float division (e.g. 0.2 / 0.05) can't accidentally drop\\n    // the outer ring of footprint cells; the Euclidean check below trims any\\n    // overshoot back to the true radius.\\n    const footCells = Math.ceil(radius / step);\\n    const radiusSq = radius * radius;\\n    let bestDistSq = Infinity;\\n    let found = false;\\n    for (let r = 0; r <= maxCells; r++) {\\n        const shellMinDistSq = (r * step) * (r * step);\\n        if (shellMinDistSq >= bestDistSq)\\n            break;\\n        for (let dy = -r; dy <= r; dy++) {\\n            const absDy = dy < 0 ? -dy : dy;\\n            for (let dz = -r; dz <= r; dz++) {\\n                const absDz = dz < 0 ? -dz : dz;\\n                for (let dx = -r; dx <= r; dx++) {\\n                    const absDx = dx < 0 ? -dx : dx;\\n                    if (absDx < r && absDy < r && absDz < r)\\n                        continue;\\n                    const distSq = (dx * dx + dy * dy + dz * dz) * step * step;\\n                    if (distSq >= bestDistSq || distSq > SEARCH_RADIUS_SQ)\\n                        continue;\\n                    const cx = ox + dx * step;\\n                    const cy = oy + dy * step;\\n                    const cz = oz + dz * step;\\n                    // Stage 1: cheap filter — only consider free voxels.\\n                    // The footprint loop below will reject candidates whose\\n                    // center column has no ground support, so no separate\\n                    // down-ray probe is needed here.\\n                    if (!collision.isFreeAt(cx, cy, cz))\\n                        continue;\\n                    // Stage 2/3: fan rays through the xz footprint.\\n                    let floor = -Infinity;\\n                    let ceiling = Infinity;\\n                    let supported = true;\\n                    for (let i = -footCells; i <= footCells && supported; i++) {\\n                        const fxOff = i * step;\\n                        const fxOffSq = fxOff * fxOff;\\n                        for (let j = -footCells; j <= footCells; j++) {\\n                            const fzOff = j * step;\\n                            if (fxOffSq + fzOff * fzOff > radiusSq)\\n                                continue;\\n                            const fx = cx + fxOff;\\n                            const fz = cz + fzOff;\\n                            const down = collision.queryRay(fx, cy, fz, 0, -1, 0, RAY_MAX_DIST);\\n                            if (!down) {\\n                                supported = false;\\n                                break;\\n                            }\\n                            if (down.y > floor)\\n                                floor = down.y;\\n                            const up = collision.queryRay(fx, cy, fz, 0, 1, 0, RAY_MAX_DIST);\\n                            if (up && up.y < ceiling)\\n                                ceiling = up.y;\\n                        }\\n                    }\\n                    if (!supported)\\n                        continue;\\n                    // Cylinder vertical extent = 2 × halfHeight. Need that\\n                    // much room between floor and ceiling.\\n                    if (floor + 2 * halfHeight > ceiling)\\n                        continue;\\n                    bestDistSq = distSq;\\n                    out.x = cx;\\n                    out.y = floor;\\n                    out.z = cz;\\n                    found = true;\\n                }\\n            }\\n        }\\n    }\\n    return found;\\n};\\n\\n/** Radius of the camera collision sphere (meters) */\\nconst CAMERA_RADIUS = 0.2;\\nconst forward$2 = new Vec3();\\nconst right$2 = new Vec3();\\nconst up$1 = new Vec3();\\nconst offset$1 = new Vec3();\\nconst spawnProbe$1 = new Vec3();\\nclass FlyController {\\n    fov = 90;\\n    rotateDamping = DEFAULT_CONTROLLER_DAMPING;\\n    _position = new Vec3();\\n    _angles = new Vec3();\\n    _targetAngles = new Vec3();\\n    _distance = 1;\\n    _spawn = new SpawnState();\\n    _mover = new SphereMover(CAMERA_RADIUS);\\n    /** Optional collision for sphere collision with sliding */\\n    set collision(value) {\\n        this._mover.collision = value;\\n        this._mover.reset(this._position);\\n    }\\n    get collision() {\\n        return this._mover.collision;\\n    }\\n    onEnter(camera) {\\n        this.goto(camera);\\n        if (this.collision &&\\n            findSphereSpawn(this.collision, this._position.x, this._position.y, this._position.z, CAMERA_RADIUS, spawnProbe$1)) {\\n            this._position.copy(spawnProbe$1);\\n            this._mover.reset(this._position);\\n        }\\n        this._storeSpawn();\\n    }\\n    update(deltaTime, inputFrame, camera) {\\n        const { move, rotate } = inputFrame.read();\\n        applyFrameRotation(this._targetAngles, rotate);\\n        dampAngles(this._angles, this._targetAngles, this.rotateDamping, deltaTime);\\n        this._step(move);\\n        camera.position.copy(this._position);\\n        camera.angles.set(this._angles.x, this._angles.y, 0);\\n        camera.distance = this._distance;\\n        camera.fov = this.fov;\\n    }\\n    onExit(_camera) {\\n    }\\n    goto(camera) {\\n        this._position.copy(camera.position);\\n        this._angles.set(camera.angles.x, camera.angles.y, 0);\\n        this._targetAngles.copy(this._angles);\\n        this._distance = camera.distance;\\n        this._mover.reset(this._position);\\n    }\\n    resetToSpawn(camera) {\\n        if (!this._spawn.has) {\\n            return false;\\n        }\\n        this._distance = this._spawn.restore(this._position, this._angles);\\n        this._targetAngles.copy(this._angles);\\n        this._mover.reset(this._position);\\n        camera.position.copy(this._position);\\n        camera.angles.copy(this._angles);\\n        camera.distance = this._distance;\\n        camera.fov = this.fov;\\n        return true;\\n    }\\n    _storeSpawn() {\\n        this._spawn.store(this._position, this._angles, this._distance);\\n    }\\n    _step(move) {\\n        setCameraBasis(this._angles, forward$2, right$2, up$1);\\n        setBasisOffset(offset$1, move[0], move[1], move[2], forward$2, right$2, up$1);\\n        this._mover.move(this._position, offset$1);\\n    }\\n}\\n\\nconst RAD_TO_DEG = 180 / Math.PI;\\nconst shortestAngle = (angle) => ((angle % 360) + 540) % 360 - 180;\\nconst smoothstep = (edge0, edge1, value) => {\\n    const t = math.clamp((value - edge0) / (edge1 - edge0), 0, 1);\\n    return t * t * (3 - 2 * t);\\n};\\nconst approach = (value, target, maxDelta) => {\\n    if (value < target) {\\n        return Math.min(target, value + maxDelta);\\n    }\\n    return Math.max(target, value - maxDelta);\\n};\\nconst smoothTurnRate = (currentRate, angleDiff, maxTurnRate, turnGain, dt) => {\\n    if (dt <= 0) {\\n        return currentRate;\\n    }\\n    const desiredRate = math.clamp(angleDiff * turnGain, -maxTurnRate, maxTurnRate);\\n    const smoothing = 1 - Math.exp(-4 * turnGain * dt);\\n    return currentRate + (desiredRate - currentRate) * smoothing;\\n};\\nconst clampTurnStep = (rate, remaining, dt) => {\\n    const step = rate * dt;\\n    if (Math.abs(remaining) < 1e-4) {\\n        return 0;\\n    }\\n    return Math.sign(step) === Math.sign(remaining) && Math.abs(step) > Math.abs(remaining) ?\\n        remaining :\\n        step;\\n};\\nconst getYawToTarget = (dx, dz) => Math.atan2(-dx, -dz) * RAD_TO_DEG;\\nconst getYawDiffToTarget = (dx, dz, yaw) => {\\n    return shortestAngle(getYawToTarget(dx, dz) - yaw);\\n};\\nconst getPitchToDirection = (dirY) => {\\n    return Math.asin(math.clamp(dirY, -1, 1)) * RAD_TO_DEG;\\n};\\nclass ProgressTracker {\\n    _blockedTime = 0;\\n    _prevDist = Infinity;\\n    reset() {\\n        this._blockedTime = 0;\\n        this._prevDist = Infinity;\\n    }\\n    update(distance, dt, blockedSpeed, blockedDuration, active = true) {\\n        if (active && this._prevDist !== Infinity && dt > 0) {\\n            const speed = (this._prevDist - distance) / dt;\\n            if (speed < blockedSpeed) {\\n                this._blockedTime += dt;\\n                if (this._blockedTime >= blockedDuration) {\\n                    this._prevDist = distance;\\n                    return true;\\n                }\\n            }\\n            else {\\n                this._blockedTime = 0;\\n            }\\n        }\\n        this._prevDist = distance;\\n        return false;\\n    }\\n}\\n\\nconst DEG_TO_RAD = Math.PI / 180;\\n/** Target-space radius to keep visible at the stopping distance */\\nconst STOP_VIEW_RADIUS = 0.75;\\n/** Minimum standoff from the target */\\nconst MIN_STOP_DIST = 0.75;\\n/** Maximum standoff from the target */\\nconst MAX_STOP_DIST = 4.0;\\n/** Distance from the standoff point below which arrival can complete */\\nconst ARRIVAL_EPSILON = 0.03;\\n/** Forward speed below which arrival can complete */\\nconst ARRIVAL_SPEED = 0.05;\\n/** Converts remaining standoff distance to final approach speed */\\nconst ARRIVAL_RATE = 1.75;\\n/** Minimum progress speed (m/s) to not count as blocked */\\nconst BLOCKED_SPEED$1 = 0.25;\\n/** Seconds of continuous low-progress before stopping the flight */\\nconst BLOCKED_DURATION$1 = 0.5;\\nconst toTarget = new Vec3();\\nconst forward$1 = new Vec3();\\nconst postTurnAngles = new Vec3();\\nconst getStopDistance = (fov) => {\\n    const halfFov = math.clamp(fov, 15, 120) * DEG_TO_RAD * 0.5;\\n    return math.clamp(STOP_VIEW_RADIUS / Math.tan(halfFov), MIN_STOP_DIST, MAX_STOP_DIST);\\n};\\n/**\\n * Generates synthetic move/rotate input to auto-fly toward a target position.\\n */\\nclass FlySource {\\n    /**\\n     * Forward input scale (matches InputController.moveSpeed).\\n     */\\n    flySpeed = 4;\\n    /**\\n     * Maximum pitch/yaw turn rate in degrees per second.\\n     */\\n    maxTurnRate = 180;\\n    /**\\n     * Proportional gain mapping angular error (degrees) to desired turn rate.\\n     */\\n    turnGain = 4;\\n    /**\\n     * Maximum forward acceleration in meters per second squared.\\n     */\\n    moveAcceleration = 6;\\n    /**\\n     * Maximum forward braking in meters per second squared.\\n     */\\n    moveDeceleration = 8;\\n    /**\\n     * Callback fired when an auto-flight completes or is cancelled.\\n     */\\n    onComplete = null;\\n    _target = null;\\n    _yawRate = 0;\\n    _pitchRate = 0;\\n    _speed = 0;\\n    _progress = new ProgressTracker();\\n    _speedMul = 1;\\n    get isActive() {\\n        return this._target !== null;\\n    }\\n    /**\\n     * Begin auto-flying toward a world-space target position.\\n     *\\n     * @param target - The destination.\\n     * @param speedMul - Forward-speed multiplier (mirrors gaming-controls\\n     * shift/ctrl: 4 for boost, 0.25 for slow). Defaults to 1.\\n     */\\n    navigateTo(target, speedMul = 1) {\\n        const wasFlying = this._target !== null;\\n        if (!this._target) {\\n            this._target = new Vec3();\\n        }\\n        this._target.copy(target);\\n        this._speedMul = speedMul;\\n        if (!wasFlying) {\\n            this._yawRate = 0;\\n            this._pitchRate = 0;\\n            this._speed = 0;\\n        }\\n        this._progress.reset();\\n    }\\n    /**\\n     * Cancel any active auto-flight.\\n     */\\n    cancel() {\\n        if (this._target) {\\n            this._target = null;\\n            this._yawRate = 0;\\n            this._pitchRate = 0;\\n            this._speed = 0;\\n            this._progress.reset();\\n            this.onComplete?.();\\n        }\\n    }\\n    /**\\n     * Compute fly deltas and append them to the frame. Must be called before\\n     * the camera controller reads the frame.\\n     *\\n     * @param dt - Frame delta time in seconds.\\n     * @param camera - The current camera state (read-only).\\n     * @param frame - The shared CameraFrame to append deltas to.\\n     */\\n    update(dt, camera, frame) {\\n        if (!this._target)\\n            return;\\n        const target = this._target;\\n        const cameraPosition = camera.position;\\n        const cameraAngles = camera.angles;\\n        toTarget.sub2(target, cameraPosition);\\n        const dist = toTarget.length();\\n        const stopDistance = getStopDistance(camera.fov);\\n        const remainingDist = dist - stopDistance;\\n        const activeRemainingDist = Math.max(0, remainingDist);\\n        if (activeRemainingDist <= ARRIVAL_EPSILON && this._speed <= ARRIVAL_SPEED) {\\n            this.cancel();\\n            return;\\n        }\\n        if (dt <= 0) {\\n            return;\\n        }\\n        const invDist = 1 / dist;\\n        const dirX = toTarget.x * invDist;\\n        const dirY = toTarget.y * invDist;\\n        const dirZ = toTarget.z * invDist;\\n        const yawDiff = getYawDiffToTarget(toTarget.x, toTarget.z, cameraAngles.y);\\n        const pitchDiff = getPitchToDirection(dirY) - cameraAngles.x;\\n        this._yawRate = smoothTurnRate(this._yawRate, yawDiff, this.maxTurnRate, this.turnGain, dt);\\n        this._pitchRate = smoothTurnRate(this._pitchRate, pitchDiff, this.maxTurnRate, this.turnGain, dt);\\n        const yawStep = clampTurnStep(this._yawRate, yawDiff, dt);\\n        const pitchStep = clampTurnStep(this._pitchRate, pitchDiff, dt);\\n        this._yawRate = yawStep / dt;\\n        this._pitchRate = pitchStep / dt;\\n        // FlyController applies: _angles += [-rotateY, -rotateX, 0]\\n        frame.deltas.rotate.append([-yawStep, -pitchStep, 0]);\\n        postTurnAngles.set(cameraAngles.x + pitchStep, cameraAngles.y + yawStep, 0);\\n        setCameraForward(postTurnAngles, forward$1);\\n        const alignment = math.clamp(forward$1.x * dirX + forward$1.y * dirY + forward$1.z * dirZ, 0, 1);\\n        const alignmentScale = smoothstep(0.05, 0.95, alignment);\\n        const brakeSpeed = Math.sqrt(2 * this.moveDeceleration * activeRemainingDist);\\n        const arrivalSpeed = activeRemainingDist * ARRIVAL_RATE;\\n        const maxSpeed = Math.min(this.flySpeed * this._speedMul, brakeSpeed, arrivalSpeed);\\n        if (maxSpeed > this._speed) {\\n            this._speed = approach(this._speed, maxSpeed, this.moveAcceleration * alignmentScale * dt);\\n        }\\n        else {\\n            this._speed = approach(this._speed, maxSpeed, this.moveDeceleration * dt);\\n        }\\n        const arrivalMove = activeRemainingDist * (1 - Math.exp(-ARRIVAL_RATE * dt));\\n        const moveDist = Math.min(this._speed * dt, arrivalMove);\\n        if (moveDist > 0) {\\n            frame.deltas.move.append([0, 0, moveDist]);\\n        }\\n        // Only treat low progress as blocked once the camera is substantially\\n        // facing the target; otherwise a large turn-in-place would cancel early.\\n        if (this._progress.update(dist, dt, BLOCKED_SPEED$1, BLOCKED_DURATION$1, alignment > 0.5 && this._speed > BLOCKED_SPEED$1)) {\\n            this.cancel();\\n        }\\n    }\\n}\\n\\nconst p = new Pose();\\nclass OrbitController {\\n    controller;\\n    fov = 90;\\n    constructor() {\\n        this.controller = new OrbitController$1();\\n        this.controller.zoomRange = new Vec2(0.01, Infinity);\\n        this.controller.pitchRange = new Vec2(-90, 90);\\n        this.controller.rotateDamping = DEFAULT_CONTROLLER_DAMPING;\\n        this.controller.moveDamping = DEFAULT_CONTROLLER_DAMPING;\\n        this.controller.zoomDamping = DEFAULT_CONTROLLER_DAMPING;\\n    }\\n    onEnter(camera) {\\n        this._attach(camera);\\n    }\\n    update(deltaTime, inputFrame, camera) {\\n        const pose = this.controller.update(inputFrame, deltaTime);\\n        camera.position.copy(pose.position);\\n        camera.angles.copy(pose.angles);\\n        camera.distance = pose.distance;\\n        camera.fov = this.fov;\\n    }\\n    onExit(_camera) {\\n    }\\n    goto(camera) {\\n        this.fov = camera.fov;\\n        this._attach(camera);\\n    }\\n    _attach(camera) {\\n        p.position.copy(camera.position);\\n        p.angles.copy(camera.angles);\\n        p.distance = Math.max(camera.distance, this.controller.zoomRange.x);\\n        this.controller.attach(p, false);\\n    }\\n}\\n\\nconst FIXED_DT = 1 / 60;\\nconst MAX_SUBSTEPS = 10;\\n/** Pre-allocated push-out vector for capsule collision */\\nconst out = { x: 0, y: 0, z: 0 };\\nconst v = new Vec3();\\nconst d = new Vec3();\\nconst forward = new Vec3();\\nconst right$1 = new Vec3();\\nconst moveStep = [0, 0, 0];\\nconst offset = new Vec3();\\nconst spawnProbe = new Vec3();\\n/**\\n * First-person camera controller with spring-damper suspension over collision terrain.\\n *\\n * Movement is constrained to the horizontal plane (XZ) relative to the camera yaw.\\n * Vertical positioning uses a spring-damper system that hovers the capsule above the\\n * collision surface, filtering out terrain noise for smooth camera motion. Capsule\\n * collision handles walls and obstacles. When airborne, normal gravity applies.\\n */\\nclass WalkController {\\n    /**\\n     * Optional collision for capsule collision with sliding\\n     */\\n    collision = null;\\n    /**\\n     * Field of view in degrees for walk mode.\\n     */\\n    fov = 90;\\n    /**\\n     * Total capsule height in meters (default: human proportion)\\n     */\\n    capsuleHeight = 1.5;\\n    /**\\n     * Capsule radius in meters\\n     */\\n    capsuleRadius = 0.2;\\n    /**\\n     * Camera height from the bottom of the capsule in meters\\n     */\\n    eyeHeight = 1.3;\\n    /**\\n     * Gravity acceleration in m/s^2\\n     */\\n    gravity = 9.8;\\n    /**\\n     * Jump velocity in m/s\\n     */\\n    jumpSpeed = 4;\\n    /**\\n     * Movement speed in m/s when grounded\\n     */\\n    moveGroundSpeed = 7;\\n    /**\\n     * Movement speed in m/s when in the air (for air control)\\n     */\\n    moveAirSpeed = 1;\\n    /**\\n     * Rotation damping factor (0 = no damping, 1 = full damping)\\n     */\\n    rotateDamping = DEFAULT_CONTROLLER_DAMPING;\\n    /**\\n     * Velocity damping factor when grounded (0 = no damping, 1 = full damping)\\n     */\\n    velocityDampingGround = 0.99;\\n    /**\\n     * Velocity damping factor when in the air (0 = no damping, 1 = full damping)\\n     */\\n    velocityDampingAir = 0.998;\\n    /**\\n     * Target clearance from capsule bottom to ground surface in meters.\\n     * The capsule hovers this far above terrain to avoid bouncing on noisy surfaces.\\n     */\\n    hoverHeight = 0.2;\\n    /**\\n     * Spring stiffness for ground-following suspension (higher = stiffer tracking).\\n     */\\n    springStiffness = 800;\\n    /**\\n     * Damping coefficient for ground-following suspension.\\n     * Critical damping is approximately 2 * sqrt(springStiffness).\\n     */\\n    springDamping = 57;\\n    /**\\n     * Maximum downward raycast distance to search for ground below the capsule.\\n     */\\n    groundProbeRange = 1.0;\\n    _position = new Vec3();\\n    _prevPosition = new Vec3();\\n    _angles = new Vec3();\\n    _targetAngles = new Vec3();\\n    _distance = 1;\\n    _spawn = new SpawnState();\\n    _spawnGrounded = false;\\n    _velocity = new Vec3();\\n    _pendingMove = [0, 0, 0];\\n    _accumulator = 0;\\n    _grounded = false;\\n    _jumping = false;\\n    _jumpHeld = false;\\n    onEnter(camera) {\\n        this.goto(camera);\\n        if (this.collision) {\\n            // Spawn is scoped to this walk-mode entry; reset so a stale spawn\\n            // from a previous entry can't be restored if this entry fails.\\n            this._spawn.clear();\\n            // Treat the walk capsule as a tight-superset cylinder for spawn.\\n            // The carve was produced with a separable XYZ dilation (flat ends,\\n            // no hemispheres), so cylinder math matches the data exactly.\\n            // Include `hoverHeight` in the height so the ceiling-clearance\\n            // check accounts for the placed capsule's full vertical envelope:\\n            // foot sits at `floor + hoverHeight`, head at `floor + hoverHeight\\n            // + capsuleHeight`.\\n            if (findCylinderSpawn(this.collision, camera.position.x, camera.position.y, camera.position.z, (this.capsuleHeight + this.hoverHeight) * 0.5, this.capsuleRadius, spawnProbe)) {\\n                // spawnProbe is the floor world position the cylinder rests\\n                // on. Eye sits hoverHeight + eyeHeight above the floor.\\n                this._position.set(spawnProbe.x, spawnProbe.y + this.hoverHeight + this.eyeHeight, spawnProbe.z);\\n                this._grounded = true;\\n                this._velocity.y = 0;\\n                this._storeSpawn();\\n            }\\n            this._prevPosition.copy(this._position);\\n        }\\n    }\\n    update(deltaTime, inputFrame, camera) {\\n        const { move, rotate } = inputFrame.read();\\n        // apply rotation at display rate for responsive mouse look\\n        applyFrameRotation(this._targetAngles, rotate);\\n        dampAngles(this._angles, this._targetAngles, this.rotateDamping, deltaTime);\\n        // accumulate movement input so frames without a physics step don't lose input\\n        this._pendingMove[0] += move[0];\\n        this._pendingMove[1] = this._pendingMove[1] || move[1];\\n        this._pendingMove[2] += move[2];\\n        this._accumulator = Math.min(this._accumulator + deltaTime, MAX_SUBSTEPS * FIXED_DT);\\n        const numSteps = Math.floor(this._accumulator / FIXED_DT);\\n        if (numSteps > 0) {\\n            const invSteps = 1 / numSteps;\\n            moveStep[0] = this._pendingMove[0] * invSteps;\\n            moveStep[1] = this._pendingMove[1];\\n            moveStep[2] = this._pendingMove[2] * invSteps;\\n            for (let i = 0; i < numSteps; i++) {\\n                this._prevPosition.copy(this._position);\\n                this._step(FIXED_DT, moveStep);\\n                this._accumulator -= FIXED_DT;\\n            }\\n            this._pendingMove[0] = 0;\\n            this._pendingMove[1] = 0;\\n            this._pendingMove[2] = 0;\\n        }\\n        const alpha = this._accumulator / FIXED_DT;\\n        camera.position.lerp(this._prevPosition, this._position, alpha);\\n        camera.angles.set(this._angles.x, this._angles.y, 0);\\n        camera.distance = this._distance;\\n        camera.fov = this.fov;\\n    }\\n    _step(dt, move) {\\n        // ground probe: cast a ray downward to find the terrain surface\\n        const groundY = this._probeGround(this._position);\\n        const hasGround = groundY !== null;\\n        // jump (require release before re-triggering)\\n        if (this._velocity.y < 0) {\\n            this._jumping = false;\\n        }\\n        if (move[1] && !this._jumping && this._grounded && !this._jumpHeld) {\\n            this._jumping = true;\\n            this._velocity.y = this.jumpSpeed;\\n            this._grounded = false;\\n        }\\n        this._jumpHeld = !!move[1];\\n        // vertical force: spring-damper when ground is detected, gravity when airborne\\n        if (hasGround && !this._jumping) {\\n            const targetY = groundY + this.hoverHeight + this.eyeHeight;\\n            const displacement = this._position.y - targetY;\\n            if (displacement > 0.1) {\\n                // well above target (jump/ledge): freefall, snap to rest height on arrival\\n                this._velocity.y -= this.gravity * dt;\\n                const nextY = this._position.y + this._velocity.y * dt;\\n                if (nextY <= targetY) {\\n                    this._position.y = targetY;\\n                    this._velocity.y = 0;\\n                }\\n                this._grounded = false;\\n            }\\n            else {\\n                // at or near target (walking/slopes): spring tracks terrain\\n                const springForce = -this.springStiffness * displacement - this.springDamping * this._velocity.y;\\n                this._velocity.y += springForce * dt;\\n                this._grounded = true;\\n            }\\n        }\\n        else {\\n            this._velocity.y -= this.gravity * dt;\\n            this._grounded = false;\\n        }\\n        // move\\n        setYawBasis(this._angles.y, forward, right$1);\\n        setBasisOffset(offset, move[0], 0, move[2], forward, right$1, Vec3.UP);\\n        this._velocity.add(offset.mulScalar(this._grounded ? this.moveGroundSpeed : this.moveAirSpeed));\\n        const dampFactor = this._grounded ? this.velocityDampingGround : this.velocityDampingAir;\\n        const alpha = damp(dampFactor, dt);\\n        this._velocity.x = math.lerp(this._velocity.x, 0, alpha);\\n        this._velocity.z = math.lerp(this._velocity.z, 0, alpha);\\n        this._position.add(v.copy(this._velocity).mulScalar(dt));\\n        // capsule collision: walls, ceiling, and fallback floor contact\\n        this._checkCollision(this._position, d);\\n    }\\n    onExit(_camera) {\\n        // nothing to clean up\\n    }\\n    /**\\n     * Teleport the controller to a given camera state (used for transitions).\\n     *\\n     * @param camera - The camera state to jump to.\\n     */\\n    goto(camera) {\\n        // position\\n        this._position.copy(camera.position);\\n        this._prevPosition.copy(this._position);\\n        // angles (clamp pitch to avoid gimbal lock)\\n        this._angles.set(camera.angles.x, camera.angles.y, 0);\\n        this._targetAngles.copy(this._angles);\\n        this._distance = camera.distance;\\n        // reset velocity and state\\n        this._resetMotion();\\n    }\\n    /**\\n     * Reset the controller to the spawn pose captured on the last walk-mode entry.\\n     *\\n     * @param camera - Camera state to update with the spawn pose.\\n     * @returns True if a spawn pose was available.\\n     */\\n    resetToSpawn(camera) {\\n        if (!this._spawn.has) {\\n            return false;\\n        }\\n        this._distance = this._spawn.restore(this._position, this._angles);\\n        this._prevPosition.copy(this._position);\\n        this._targetAngles.copy(this._angles);\\n        this._resetMotion();\\n        this._grounded = this._spawnGrounded;\\n        camera.position.copy(this._position);\\n        camera.angles.copy(this._angles);\\n        camera.distance = this._distance;\\n        camera.fov = this.fov;\\n        return true;\\n    }\\n    _storeSpawn() {\\n        this._spawn.store(this._position, this._angles, this._distance);\\n        this._spawnGrounded = this._grounded;\\n    }\\n    _resetMotion() {\\n        this._velocity.set(0, 0, 0);\\n        this._grounded = false;\\n        this._jumping = false;\\n        this._jumpHeld = false;\\n        this._pendingMove[0] = 0;\\n        this._pendingMove[1] = 0;\\n        this._pendingMove[2] = 0;\\n        this._accumulator = 0;\\n    }\\n    /**\\n     * Cast multiple rays downward to find the average ground surface height.\\n     * Uses 5 rays (center + 4 cardinal at capsule radius) to spatially filter\\n     * noisy collision heights, giving the spring a smoother target.\\n     *\\n     * @param pos - Eye position in PlayCanvas world space.\\n     * @returns Average ground surface Y in PlayCanvas space, or null if no ground found.\\n     */\\n    _probeGround(pos) {\\n        if (!this.collision)\\n            return null;\\n        const oy = pos.y - this.eyeHeight;\\n        const r = this.capsuleRadius;\\n        const range = this.groundProbeRange;\\n        let totalY = 0;\\n        let hitCount = 0;\\n        for (let i = 0; i < 5; i++) {\\n            let ox = pos.x;\\n            let oz = pos.z;\\n            if (i === 1)\\n                ox -= r;\\n            else if (i === 2)\\n                ox += r;\\n            else if (i === 3)\\n                oz += r;\\n            else if (i === 4)\\n                oz -= r;\\n            const hit = this.collision.queryRay(ox, oy, oz, 0, -1, 0, range);\\n            if (hit) {\\n                totalY += hit.y;\\n                hitCount++;\\n            }\\n        }\\n        return hitCount > 0 ? totalY / hitCount : null;\\n    }\\n    /**\\n     * Check for capsule collision and apply push-out displacement.\\n     * Handles walls, ceiling hits, and fallback floor contact when airborne.\\n     *\\n     * @param pos - Eye position in PlayCanvas world space.\\n     * @param disp - Pre-allocated vector to receive the collision push-out displacement.\\n     */\\n    _checkCollision(pos, disp) {\\n        const center = pos.y - this.eyeHeight + this.capsuleHeight * 0.5;\\n        const half = this.capsuleHeight * 0.5 - this.capsuleRadius;\\n        if (this.collision.queryCapsule(pos.x, center, pos.z, half, this.capsuleRadius, out)) {\\n            disp.set(out.x, out.y, out.z);\\n            pos.add(disp);\\n            // ceiling collision: cancel upward velocity\\n            if (disp.y < 0 && this._velocity.y > 0) {\\n                this._velocity.y = 0;\\n            }\\n            // airborne floor collision: transition to grounded as a fallback safety net\\n            if (!this._grounded && disp.y > 0 && this._velocity.y < 0) {\\n                this._velocity.y = 0;\\n                this._grounded = true;\\n            }\\n        }\\n    }\\n}\\n\\n/** XZ distance below which the walker considers itself arrived */\\nconst ARRIVAL_DIST = 0.5;\\n/** Minimum XZ speed (m/s) to not count as blocked */\\nconst BLOCKED_SPEED = 0.6;\\n/** Seconds of continuous low-progress before stopping the walk */\\nconst BLOCKED_DURATION = 0.2;\\n/**\\n * Generates synthetic move/rotate input to auto-walk toward a target position.\\n *\\n * Designed to feed into WalkController's existing update path so there is no\\n * duplicated physics. Each frame it appends yaw-rotation and forward-movement\\n * deltas to the shared CameraFrame, and monitors arrival / blocked conditions.\\n */\\nclass WalkSource {\\n    /**\\n     * Forward input scale (matches InputController.moveSpeed for consistent\\n     * speed with regular WASD walking).\\n     */\\n    walkSpeed = 4;\\n    /**\\n     * Maximum yaw turn rate in degrees per second.\\n     */\\n    maxTurnRate = 192;\\n    /**\\n     * Proportional gain mapping yaw error (degrees) to desired turn rate.\\n     * Below maxTurnRate / turnGain degrees the turn rate scales linearly;\\n     * above that it is capped at maxTurnRate. The rate filter is\\n     * automatically critically damped so there is no overshoot.\\n     */\\n    turnGain = 5;\\n    /**\\n     * Callback fired when an auto-walk completes (arrival or obstacle).\\n     */\\n    onComplete = null;\\n    _target = null;\\n    _yawRate = 0;\\n    _progress = new ProgressTracker();\\n    _speedMul = 1;\\n    get isActive() {\\n        return this._target !== null;\\n    }\\n    /**\\n     * Begin auto-walking toward a world-space target position.\\n     *\\n     * @param target - The destination (XZ used for navigation).\\n     * @param speedMul - Forward-speed multiplier (mirrors gaming-controls\\n     * shift/ctrl: 2 for run, 0.5 for crawl). Defaults to 1.\\n     */\\n    navigateTo(target, speedMul = 1) {\\n        if (!this._target) {\\n            this._target = new Vec3();\\n        }\\n        this._target.copy(target);\\n        this._speedMul = speedMul;\\n        this._progress.reset();\\n    }\\n    /**\\n     * Cancel any active auto-walk.\\n     */\\n    cancel() {\\n        if (this._target) {\\n            this._target = null;\\n            this._yawRate = 0;\\n            this._progress.reset();\\n            this.onComplete?.();\\n        }\\n    }\\n    /**\\n     * Compute walk deltas and append them to the frame. Must be called\\n     * before* the camera controller reads the frame.\\n     *\\n     * @param dt - Frame delta time in seconds.\\n     * @param camera - The current camera state (read-only).\\n     * @param frame - The shared CameraFrame to append deltas to.\\n     */\\n    update(dt, camera, frame) {\\n        if (!this._target)\\n            return;\\n        const target = this._target;\\n        const cameraPosition = camera.position;\\n        const cameraAngles = camera.angles;\\n        const dx = target.x - cameraPosition.x;\\n        const dz = target.z - cameraPosition.z;\\n        const xzDist = Math.sqrt(dx * dx + dz * dz);\\n        // arrival\\n        if (xzDist < ARRIVAL_DIST) {\\n            this.cancel();\\n            return;\\n        }\\n        // blocked detection: compare with previous frame's distance\\n        if (this._progress.update(xzDist, dt, BLOCKED_SPEED, BLOCKED_DURATION)) {\\n            this.cancel();\\n            return;\\n        }\\n        // yaw toward target with smoothed turn rate\\n        const yawDiff = getYawDiffToTarget(dx, dz, cameraAngles.y);\\n        this._yawRate = smoothTurnRate(this._yawRate, yawDiff, this.maxTurnRate, this.turnGain, dt);\\n        const yawStep = clampTurnStep(this._yawRate, yawDiff, dt);\\n        this._yawRate = dt > 0 ? yawStep / dt : this._yawRate;\\n        // WalkController applies: _angles.y += -rotate[0]\\n        frame.deltas.rotate.append([-yawStep, 0, 0]);\\n        // scale forward speed by alignment: turn in place first, then accelerate\\n        const alignment = Math.max(0, Math.cos(yawDiff * Math.PI / 180));\\n        frame.deltas.move.append([0, 0, this.walkSpeed * this._speedMul * dt * alignment]);\\n    }\\n}\\n\\nconst tmpCamera = new Camera();\\nconst tmpv = new Vec3();\\n// Walk mode is only enabled when the scene's horizontal footprint is large\\n// enough to walk around in. Vertical extent (Y) is irrelevant — a tall but\\n// narrow scene isn't walkable. Both X and Z ranges must exceed this\\n// minimum (in metres); below it walk mode is hidden and the viewer falls\\n// back to fly as the default first-person mode.\\nconst WALK_MIN_HORIZONTAL_RANGE = 5;\\nconst isWalkAllowed = (bbox, collision) => {\\n    const { x, z } = bbox.halfExtents;\\n    return !!collision && x * 2 >= WALK_MIN_HORIZONTAL_RANGE && z * 2 >= WALK_MIN_HORIZONTAL_RANGE;\\n};\\nconst createCamera = (position, target, fov) => {\\n    const result = new Camera();\\n    result.look(position, target);\\n    result.fov = fov;\\n    return result;\\n};\\nconst createFrameCamera = (bbox, fov) => {\\n    const sceneSize = bbox.halfExtents.length();\\n    const distance = sceneSize / Math.sin(fov / 180 * Math.PI * 0.5);\\n    return createCamera(new Vec3(2, 1, 2).normalize().mulScalar(distance).add(bbox.center), bbox.center, fov);\\n};\\nclass CameraManager {\\n    update;\\n    // Re-seed the active controller from the current camera pose and\\n    // cancel any in-progress transition lerp. Use after externally\\n    // mutating `camera` and/or `state.cameraMode` to make the change\\n    // visible instantly.\\n    snap;\\n    // holds the camera state\\n    camera = new Camera();\\n    constructor(global, bbox, collision = null) {\\n        const { events, settings, state } = global;\\n        const walkAllowed = isWalkAllowed(bbox, collision);\\n        const camera0 = settings.cameras[0]?.initial;\\n        const defaultFov = camera0?.fov ?? 75;\\n        const frameCamera = createFrameCamera(bbox, defaultFov);\\n        const resetCamera = camera0 ?\\n            createCamera(new Vec3(camera0.position), new Vec3(camera0.target), camera0.fov) :\\n            frameCamera;\\n        const getAnimTrack = (initial, isObjectExperience) => {\\n            const { animTracks } = settings;\\n            // extract the camera animation track from settings\\n            if (animTracks?.length > 0 && settings.startMode === 'animTrack') {\\n                // use the first animTrack\\n                return animTracks[0];\\n            }\\n            else if (isObjectExperience) {\\n                // create basic rotation animation if no anim track is specified\\n                initial.calcFocusPoint(tmpv);\\n                return createRotateTrack(initial.position, tmpv, initial.fov);\\n            }\\n            // non-object experience: gentle figure-8 motion from inside the scene\\n            initial.calcFocusPoint(tmpv);\\n            return createFigure8Track(initial.position, tmpv, initial.fov);\\n        };\\n        // object experience starts outside the bounding box\\n        const isObjectExperience = !bbox.containsPoint(resetCamera.position);\\n        const animTrack = getAnimTrack(resetCamera, isObjectExperience);\\n        const controllers = {\\n            orbit: new OrbitController(),\\n            fly: new FlyController(),\\n            walk: new WalkController(),\\n            anim: animTrack ? new AnimController(animTrack) : null\\n        };\\n        controllers.orbit.fov = resetCamera.fov;\\n        controllers.fly.fov = resetCamera.fov;\\n        controllers.fly.collision = collision;\\n        controllers.walk.collision = collision;\\n        const walkSource = new WalkSource();\\n        const flySource = new FlySource();\\n        const sourcesByMode = {\\n            walk: walkSource,\\n            fly: flySource\\n        };\\n        walkSource.onComplete = flySource.onComplete = () => {\\n            events.fire('navigateComplete');\\n        };\\n        const getController = (cameraMode) => {\\n            return controllers[cameraMode];\\n        };\\n        // set the global animation flag\\n        state.hasAnimation = !!controllers.anim;\\n        state.animationDuration = controllers.anim ? controllers.anim.animState.cursor.duration : 0;\\n        // initialize camera mode and initial camera position\\n        state.cameraMode = state.hasAnimation ? 'anim' : (isObjectExperience ? 'orbit' : (walkAllowed ? 'walk' : 'fly'));\\n        this.camera.copy(resetCamera);\\n        const target = new Camera(this.camera); // the active controller updates this\\n        const from = new Camera(this.camera); // stores the previous camera state during transition\\n        const defaultMode = isObjectExperience ? 'orbit' : (walkAllowed ? 'walk' : 'fly');\\n        let fromMode = defaultMode;\\n        // tracks the mode to restore when exiting walk\\n        let preWalkMode = isObjectExperience ? 'orbit' : 'fly';\\n        // enter the initial controller\\n        getController(state.cameraMode).onEnter(this.camera);\\n        // transition state\\n        const transitionSpeed = 1.0;\\n        let transitionTimer = 1;\\n        let clearOrbitTargetOnTransitionEnd = false;\\n        // start a new camera transition from the current pose\\n        const startTransition = () => {\\n            from.copy(this.camera);\\n            transitionTimer = 0;\\n        };\\n        this.snap = () => {\\n            getController(state.cameraMode).onEnter(this.camera);\\n            target.copy(this.camera);\\n            transitionTimer = 1;\\n            global.app.renderNextFrame = true;\\n        };\\n        // application update\\n        this.update = (deltaTime, frame) => {\\n            // use dt of 0 if animation is paused\\n            const dt = state.cameraMode === 'anim' && state.animationPaused ? 0 : deltaTime;\\n            // update transition timer\\n            const prevTransitionTimer = transitionTimer;\\n            transitionTimer = Math.min(1, transitionTimer + deltaTime * transitionSpeed);\\n            const controller = getController(state.cameraMode);\\n            sourcesByMode[state.cameraMode]?.update(dt, this.camera, frame);\\n            controller.update(dt, frame, target);\\n            if (transitionTimer < 1) {\\n                // lerp away from previous camera during transition\\n                this.camera.lerp(from, target, easeOut(transitionTimer));\\n            }\\n            else {\\n                this.camera.copy(target);\\n            }\\n            // update animation timeline\\n            if (state.cameraMode === 'anim') {\\n                state.animationTime = controllers.anim.animState.cursor.value;\\n            }\\n            if (clearOrbitTargetOnTransitionEnd && prevTransitionTimer < 1 && transitionTimer === 1) {\\n                clearOrbitTargetOnTransitionEnd = false;\\n                events.fire('orbitTarget:clear');\\n            }\\n        };\\n        // handle input events\\n        events.on('inputEvent', (eventName) => {\\n            switch (eventName) {\\n                case 'frame':\\n                    events.fire('orbitTarget:clear');\\n                    state.cameraMode = 'orbit';\\n                    controllers.orbit.goto(frameCamera);\\n                    startTransition();\\n                    break;\\n                case 'reset':\\n                    if (state.cameraMode === 'walk') {\\n                        walkSource.cancel();\\n                        events.fire('navTarget:clear');\\n                        startTransition();\\n                        controllers.walk.resetToSpawn(target);\\n                    }\\n                    else if (state.cameraMode === 'fly') {\\n                        flySource.cancel();\\n                        startTransition();\\n                        controllers.fly.resetToSpawn(target);\\n                    }\\n                    else {\\n                        events.fire('orbitTarget:clear');\\n                        state.cameraMode = 'orbit';\\n                        controllers.orbit.goto(resetCamera);\\n                        startTransition();\\n                    }\\n                    break;\\n                case 'playPause':\\n                    if (state.hasAnimation) {\\n                        if (state.cameraMode === 'anim') {\\n                            state.animationPaused = !state.animationPaused;\\n                        }\\n                        else {\\n                            state.cameraMode = 'anim';\\n                            state.animationPaused = false;\\n                        }\\n                    }\\n                    break;\\n                case 'requestFirstPerson':\\n                    state.cameraMode = 'fly';\\n                    break;\\n                case 'toggleWalk':\\n                    if (walkAllowed) {\\n                        if (state.cameraMode === 'walk') {\\n                            state.cameraMode = preWalkMode;\\n                        }\\n                        else {\\n                            preWalkMode = state.cameraMode;\\n                            state.cameraMode = 'walk';\\n                        }\\n                    }\\n                    break;\\n                case 'exitWalk':\\n                    if (state.cameraMode === 'walk') {\\n                        state.cameraMode = preWalkMode;\\n                    }\\n                    break;\\n                case 'cancel':\\n                    if (state.cameraMode === 'anim') {\\n                        state.cameraMode = fromMode;\\n                    }\\n                    break;\\n                case 'interrupt':\\n                    if (state.cameraMode === 'anim') {\\n                        state.cameraMode = fromMode;\\n                    }\\n                    break;\\n            }\\n        });\\n        // handle camera mode switching\\n        events.on('cameraMode:changed', (value, prev) => {\\n            sourcesByMode[prev]?.cancel();\\n            // snapshot the current pose before any controller mutation\\n            startTransition();\\n            target.copy(this.camera);\\n            fromMode = prev;\\n            // exit the old controller\\n            const prevController = getController(prev);\\n            prevController.onExit(this.camera);\\n            // enter new controller\\n            const newController = getController(value);\\n            newController.onEnter(this.camera);\\n        });\\n        // handle user scrubbing the animation timeline\\n        events.on('scrubAnim', (time) => {\\n            // switch to animation camera if we're not already there\\n            state.cameraMode = 'anim';\\n            // set time\\n            controllers.anim.animState.cursor.value = time;\\n        });\\n        // handle user picking in the scene\\n        events.on('pick', (position) => {\\n            // switch to orbit camera on pick\\n            state.cameraMode = 'orbit';\\n            // construct camera\\n            tmpCamera.copy(this.camera);\\n            tmpCamera.look(this.camera.position, position);\\n            controllers.orbit.goto(tmpCamera);\\n            startTransition();\\n            clearOrbitTargetOnTransitionEnd = true;\\n        });\\n        events.on('annotation.activate', (annotation) => {\\n            events.fire('orbitTarget:clear');\\n            // switch to orbit camera on pick\\n            state.cameraMode = 'orbit';\\n            const { initial } = annotation.camera;\\n            // construct camera\\n            tmpCamera.fov = initial.fov;\\n            tmpCamera.look(new Vec3(initial.position), new Vec3(initial.target));\\n            controllers.orbit.goto(tmpCamera);\\n            startTransition();\\n        });\\n        // tap-to-navigate: start auto-driving the active mode toward a picked position\\n        events.on('navigateTo', (position, normal, speedMul = 1) => {\\n            const source = sourcesByMode[state.cameraMode];\\n            if (source) {\\n                source.navigateTo(position, speedMul);\\n                events.fire('navTarget:set', position, normal);\\n            }\\n        });\\n        // cancel any active auto-navigation in the current mode\\n        events.on('navigateCancel', () => {\\n            sourcesByMode[state.cameraMode]?.cancel();\\n            events.fire('navTarget:clear');\\n        });\\n        events.on('navigateComplete', () => {\\n            events.fire('navTarget:clear');\\n        });\\n    }\\n}\\n\\nconst captureCameraState = (cm, state) => ({\\n    position: [cm.camera.position.x, cm.camera.position.y, cm.camera.position.z],\\n    angles: [cm.camera.angles.x, cm.camera.angles.y, cm.camera.angles.z],\\n    distance: cm.camera.distance,\\n    fov: cm.camera.fov,\\n    mode: state.cameraMode\\n});\\nconst restoreCameraState = (cm, state, snapshot) => {\\n    cm.camera.position.set(snapshot.position[0], snapshot.position[1], snapshot.position[2]);\\n    cm.camera.angles.set(snapshot.angles[0], snapshot.angles[1], snapshot.angles[2]);\\n    cm.camera.distance = snapshot.distance;\\n    cm.camera.fov = snapshot.fov;\\n    // Mode change (if any) fires cameraMode:changed which runs the new\\n    // controller's onEnter against our just-set pose; snap() then cancels\\n    // the resulting transition lerp. Same-mode case: snap() re-seeds the\\n    // active controller in place.\\n    if (state.cameraMode !== snapshot.mode) {\\n        state.cameraMode = snapshot.mode;\\n    }\\n    cm.snap();\\n};\\n\\n// Developer / debug panel. Hidden by default; surfaced via `?debug` URL\\n// param or Ctrl+Shift+D keyboard shortcut. DOM and styles are injected\\n// lazily on first show so there's no footprint on production URLs.\\nconst STYLE_ID = 'sse-debug-panel-style';\\nconst PANEL_ID = 'sse-debug-panel';\\nconst STYLES = `\\n#${PANEL_ID} {\\n    position: fixed;\\n    top: max(8px, env(safe-area-inset-top));\\n    left: max(8px, env(safe-area-inset-left));\\n    padding: 8px 10px;\\n    background: rgba(0, 0, 0, 0.7);\\n    color: #eee;\\n    font: 11px/1.4 ui-monospace, Menlo, Consolas, monospace;\\n    border: 1px solid rgba(255, 255, 255, 0.1);\\n    border-radius: 4px;\\n    z-index: 1000;\\n    pointer-events: auto;\\n    user-select: none;\\n    min-width: 220px;\\n}\\n#${PANEL_ID} .row {\\n    display: flex;\\n    justify-content: space-between;\\n    gap: 12px;\\n    white-space: nowrap;\\n}\\n#${PANEL_ID} .row .label {\\n    color: #888;\\n}\\n#${PANEL_ID} .row .value {\\n    color: #eee;\\n    font-variant-numeric: tabular-nums;\\n    cursor: text;\\n    padding: 0 4px;\\n    margin: 0 -4px;\\n    border-radius: 2px;\\n    transition: background-color 0.15s ease;\\n    outline: none;\\n}\\n#${PANEL_ID} .row .value:hover {\\n    background: rgba(255, 255, 255, 0.08);\\n}\\n#${PANEL_ID} .row .value:focus {\\n    background: rgba(255, 255, 255, 0.12);\\n    box-shadow: inset 0 0 0 1px rgba(120, 180, 255, 0.45);\\n}\\n#${PANEL_ID} .row .value.flash-ok {\\n    background: rgba(120, 220, 140, 0.35);\\n}\\n#${PANEL_ID} .row .value.flash-bad {\\n    background: rgba(220, 100, 100, 0.45);\\n}\\n#${PANEL_ID} .buttons {\\n    display: flex;\\n    gap: 6px;\\n    margin-top: 6px;\\n}\\n#${PANEL_ID} button {\\n    flex: 1;\\n    background: rgba(255, 255, 255, 0.08);\\n    color: #eee;\\n    border: 1px solid rgba(255, 255, 255, 0.12);\\n    border-radius: 3px;\\n    padding: 4px 8px;\\n    font: inherit;\\n    cursor: pointer;\\n    transition: background-color 0.15s ease;\\n}\\n#${PANEL_ID} button:hover {\\n    background: rgba(255, 255, 255, 0.16);\\n}\\n#${PANEL_ID} button.flash {\\n    background: rgba(120, 220, 140, 0.35);\\n}\\n`;\\nconst fmt = (v) => `${v.x.toFixed(3)}, ${v.y.toFixed(3)}, ${v.z.toFixed(3)}`;\\n// Accepts \\\"1,2,3\\\", \\\"1, 2, 3\\\", \\\"1 2 3\\\", with or without trailing whitespace.\\nconst parseVector = (text) => {\\n    const parts = text.trim().split(/[\\\\s,]+/).filter(p => p.length > 0);\\n    if (parts.length !== 3)\\n        return null;\\n    const nums = parts.map(Number);\\n    if (nums.some(n => !Number.isFinite(n)))\\n        return null;\\n    return [nums[0], nums[1], nums[2]];\\n};\\nclass DebugPanel {\\n    _global;\\n    _cameraManager;\\n    _focusTmp = new Vec3();\\n    _root = null;\\n    _positionValue = null;\\n    _focusValue = null;\\n    _copyButton = null;\\n    _pasteButton = null;\\n    _screenshotButton = null;\\n    _editing = null;\\n    _editCanceled = false;\\n    _visible = false;\\n    _onPrerender = () => this._render();\\n    _onKeyDown = (event) => {\\n        // Ctrl+Shift+D — also accept Meta+Shift+D on macOS for parity\\n        if (event.code === 'KeyD' && event.shiftKey && (event.ctrlKey || event.metaKey)) {\\n            event.preventDefault();\\n            this.toggle();\\n        }\\n    };\\n    constructor(global, cameraManager) {\\n        this._global = global;\\n        this._cameraManager = cameraManager;\\n        window.addEventListener('keydown', this._onKeyDown);\\n        if (global.config.debug) {\\n            this.show();\\n        }\\n    }\\n    show() {\\n        if (this._visible)\\n            return;\\n        this._visible = true;\\n        if (!this._root) {\\n            this._build();\\n        }\\n        this._root.style.display = '';\\n        this._global.app.on('prerender', this._onPrerender);\\n        window.getCameraState = () => captureCameraState(this._cameraManager, this._global.state);\\n        window.setCameraState = snapshot => restoreCameraState(this._cameraManager, this._global.state, snapshot);\\n        this._render();\\n    }\\n    hide() {\\n        if (!this._visible)\\n            return;\\n        this._visible = false;\\n        if (this._root) {\\n            this._root.style.display = 'none';\\n        }\\n        this._global.app.off('prerender', this._onPrerender);\\n        delete window.getCameraState;\\n        delete window.setCameraState;\\n    }\\n    toggle() {\\n        if (this._visible)\\n            this.hide();\\n        else\\n            this.show();\\n    }\\n    destroy() {\\n        this.hide();\\n        window.removeEventListener('keydown', this._onKeyDown);\\n        if (this._root) {\\n            this._root.remove();\\n            this._root = null;\\n        }\\n        document.getElementById(STYLE_ID)?.remove();\\n    }\\n    _build() {\\n        if (!document.getElementById(STYLE_ID)) {\\n            const style = document.createElement('style');\\n            style.id = STYLE_ID;\\n            style.textContent = STYLES;\\n            document.head.appendChild(style);\\n        }\\n        const root = document.createElement('div');\\n        root.id = PANEL_ID;\\n        root.innerHTML = `\\n            <div class=\\\"row\\\"><span class=\\\"label\\\">camera</span><span class=\\\"value\\\" data-id=\\\"position\\\" contenteditable=\\\"plaintext-only\\\" spellcheck=\\\"false\\\" title=\\\"Edit to set camera position\\\">—</span></div>\\n            <div class=\\\"row\\\"><span class=\\\"label\\\">focus</span><span class=\\\"value\\\" data-id=\\\"focus\\\" contenteditable=\\\"plaintext-only\\\" spellcheck=\\\"false\\\" title=\\\"Edit to look at this point\\\">—</span></div>\\n            <div class=\\\"buttons\\\">\\n                <button data-id=\\\"copy\\\">Copy</button>\\n                <button data-id=\\\"paste\\\">Paste</button>\\n            </div>\\n            <div class=\\\"buttons\\\">\\n                <button data-id=\\\"screenshot\\\">Screenshot</button>\\n            </div>\\n        `;\\n        document.body.appendChild(root);\\n        this._root = root;\\n        this._positionValue = root.querySelector('[data-id=\\\"position\\\"]');\\n        this._focusValue = root.querySelector('[data-id=\\\"focus\\\"]');\\n        this._copyButton = root.querySelector('[data-id=\\\"copy\\\"]');\\n        this._pasteButton = root.querySelector('[data-id=\\\"paste\\\"]');\\n        this._screenshotButton = root.querySelector('[data-id=\\\"screenshot\\\"]');\\n        this._copyButton.addEventListener('click', () => this._copy());\\n        this._pasteButton.addEventListener('click', () => this._paste());\\n        this._screenshotButton.addEventListener('click', () => this._screenshot());\\n        this._wireEditable(this._positionValue, 'position');\\n        this._wireEditable(this._focusValue, 'focus');\\n    }\\n    _wireEditable(span, kind) {\\n        span.addEventListener('focus', () => {\\n            this._editing = span;\\n            this._editCanceled = false;\\n            // select all text so the user can start typing to replace\\n            const range = document.createRange();\\n            range.selectNodeContents(span);\\n            const sel = window.getSelection();\\n            sel?.removeAllRanges();\\n            sel?.addRange(range);\\n        });\\n        // Stop key events from bubbling to the canvas / window listeners\\n        // (PlayCanvas KeyboardMouseSource and the wheel/key interrupt\\n        // listeners) so arrow keys, WASD, etc. behave as text editing\\n        // instead of moving the camera.\\n        const stopKey = (e) => e.stopPropagation();\\n        span.addEventListener('keydown', (e) => {\\n            stopKey(e);\\n            if (e.key === 'Enter') {\\n                e.preventDefault();\\n                span.blur();\\n            }\\n            else if (e.key === 'Escape') {\\n                e.preventDefault();\\n                this._editCanceled = true;\\n                span.blur();\\n            }\\n        });\\n        span.addEventListener('keyup', stopKey);\\n        span.addEventListener('keypress', stopKey);\\n        span.addEventListener('blur', () => {\\n            const wasCanceled = this._editCanceled;\\n            this._editing = null;\\n            this._editCanceled = false;\\n            // clear any leftover selection\\n            window.getSelection()?.removeAllRanges();\\n            if (wasCanceled) {\\n                this._render();\\n                return;\\n            }\\n            const parsed = parseVector(span.textContent ?? '');\\n            if (!parsed) {\\n                this._flashBad(span);\\n                this._render();\\n                return;\\n            }\\n            if (kind === 'position') {\\n                this._applyPosition(parsed);\\n            }\\n            else {\\n                this._applyFocus(parsed);\\n            }\\n            this._flashOk(span);\\n        });\\n    }\\n    _applyPosition(pos) {\\n        this._cameraManager.camera.position.set(pos[0], pos[1], pos[2]);\\n        this._cameraManager.snap();\\n    }\\n    _applyFocus(focus) {\\n        // Keep camera position fixed; recompute angles + distance so the\\n        // camera looks at the new focus point. Camera.look() does the math\\n        // in place; snap() then re-seeds the active controller.\\n        const cam = this._cameraManager.camera;\\n        const from = this._focusTmp.copy(cam.position);\\n        const to = new Vec3(focus[0], focus[1], focus[2]);\\n        cam.look(from, to);\\n        this._cameraManager.snap();\\n    }\\n    _render() {\\n        if (!this._visible || !this._positionValue || !this._focusValue)\\n            return;\\n        const cam = this._cameraManager.camera;\\n        cam.calcFocusPoint(this._focusTmp);\\n        // Skip the span currently being edited so user input isn't\\n        // overwritten by the per-frame refresh.\\n        if (this._editing !== this._positionValue) {\\n            this._positionValue.textContent = fmt(cam.position);\\n        }\\n        if (this._editing !== this._focusValue) {\\n            this._focusValue.textContent = fmt(this._focusTmp);\\n        }\\n    }\\n    async _copy() {\\n        const snapshot = captureCameraState(this._cameraManager, this._global.state);\\n        try {\\n            await navigator.clipboard.writeText(JSON.stringify(snapshot));\\n            this._flash(this._copyButton);\\n        }\\n        catch (err) {\\n            console.warn('[debug-panel] copy failed', err);\\n        }\\n    }\\n    async _paste() {\\n        try {\\n            const text = await navigator.clipboard.readText();\\n            const snapshot = JSON.parse(text);\\n            restoreCameraState(this._cameraManager, this._global.state, snapshot);\\n            this._flash(this._pasteButton);\\n        }\\n        catch (err) {\\n            console.warn('[debug-panel] paste failed', err);\\n        }\\n    }\\n    _screenshot() {\\n        const app = this._global.app;\\n        const canvas = app.graphicsDevice.canvas;\\n        // PlayCanvas runs with preserveDrawingBuffer off, so the canvas\\n        // pixels are only readable in the same task as the render. Force\\n        // a render and capture in frameend.\\n        app.renderNextFrame = true;\\n        app.once('frameend', () => {\\n            // Quality 1.0 with image/webp produces lossless WebP in\\n            // Chromium / Firefox. Safari (which lacks WebP encode) falls\\n            // back to PNG automatically — blob.type tells us which.\\n            canvas.toBlob((blob) => {\\n                if (!blob) {\\n                    console.warn('[debug-panel] screenshot toBlob returned null');\\n                    return;\\n                }\\n                const ext = blob.type === 'image/webp' ? 'webp' : 'png';\\n                const url = URL.createObjectURL(blob);\\n                const a = document.createElement('a');\\n                a.href = url;\\n                a.download = `supersplat-viewer.${ext}`;\\n                a.click();\\n                URL.revokeObjectURL(url);\\n                this._flash(this._screenshotButton);\\n            }, 'image/webp', 1.0);\\n        });\\n    }\\n    _flash(el) {\\n        if (!el)\\n            return;\\n        el.classList.add('flash');\\n        setTimeout(() => el.classList.remove('flash'), 250);\\n    }\\n    _flashOk(el) {\\n        el.classList.add('flash-ok');\\n        setTimeout(() => el.classList.remove('flash-ok'), 250);\\n    }\\n    _flashBad(el) {\\n        el.classList.add('flash-bad');\\n        setTimeout(() => el.classList.remove('flash-bad'), 400);\\n    }\\n}\\n\\n/**\\n * Watches global pointer events and updates `state.inputMode` to reflect\\n * whether the user is on a touch device or desktop.\\n */\\nclass InputModeTracker {\\n    _global = null;\\n    _onPointer = (event) => {\\n        if (this._global) {\\n            this._global.state.inputMode = event.pointerType === 'touch' ? 'touch' : 'desktop';\\n        }\\n    };\\n    attach(global) {\\n        this._global = global;\\n        window.addEventListener('pointerdown', this._onPointer);\\n        window.addEventListener('pointermove', this._onPointer);\\n    }\\n    detach() {\\n        window.removeEventListener('pointerdown', this._onPointer);\\n        window.removeEventListener('pointermove', this._onPointer);\\n        this._global = null;\\n    }\\n}\\n\\nconst isCaptureMode$1 = (mode) => mode === 'walk' || mode === 'fly';\\nconst isWasdKey = (event) => (event.code === 'KeyW' ||\\n    event.code === 'KeyA' ||\\n    event.code === 'KeyS' ||\\n    event.code === 'KeyD');\\n/**\\n * Keyboard shortcuts that switch camera mode and toggle UI affordances.\\n * Listens on `window` so the user can press 1/2/3, V, G, H, F, R, Space,\\n * or Escape regardless of which element has focus.\\n */\\nclass ModeShortcuts {\\n    _global = null;\\n    _pointerLock = null;\\n    _onKeyDown = (event) => {\\n        const global = this._global;\\n        if (!global)\\n            return;\\n        const { state, events } = global;\\n        if (event.key === 'Escape') {\\n            if (this._pointerLock?.recentlyExitedCapture) ;\\n            else if (isCaptureMode$1(state.cameraMode) && state.gamingControls && state.inputMode === 'desktop') {\\n                state.gamingControls = false;\\n            }\\n            else if (state.cameraMode === 'walk') {\\n                events.fire('inputEvent', 'exitWalk', event);\\n            }\\n            else {\\n                events.fire('inputEvent', 'cancel', event);\\n            }\\n            return;\\n        }\\n        if (event.ctrlKey || event.altKey || event.metaKey) {\\n            return;\\n        }\\n        switch (event.key) {\\n            case '1':\\n                state.cameraMode = 'orbit';\\n                break;\\n            case '2':\\n                state.cameraMode = 'fly';\\n                break;\\n            case '3':\\n                events.fire('inputEvent', 'toggleWalk');\\n                break;\\n            case 'v':\\n                if (state.hasCollisionOverlay) {\\n                    state.collisionOverlayEnabled = !state.collisionOverlayEnabled;\\n                }\\n                break;\\n            case 'g':\\n                state.gamingControls = !state.gamingControls;\\n                break;\\n            case 'h':\\n                events.fire('inputEvent', 'toggleHelp');\\n                break;\\n            case 'r':\\n                events.fire('inputEvent', 'reset', event);\\n                break;\\n            default:\\n                if (isWasdKey(event) && state.inputMode === 'desktop') {\\n                    if (!isCaptureMode$1(state.cameraMode)) {\\n                        state.cameraMode = 'fly';\\n                    }\\n                    if (!state.gamingControls) {\\n                        state.gamingControls = true;\\n                    }\\n                }\\n                break;\\n        }\\n        if (state.cameraMode !== 'walk') {\\n            switch (event.key) {\\n                case 'f':\\n                    events.fire('inputEvent', 'frame', event);\\n                    break;\\n                case ' ':\\n                    events.fire('inputEvent', 'playPause', event);\\n                    break;\\n            }\\n        }\\n    };\\n    attach(global, pointerLock) {\\n        this._global = global;\\n        this._pointerLock = pointerLock;\\n        window.addEventListener('keydown', this._onKeyDown);\\n    }\\n    detach() {\\n        window.removeEventListener('keydown', this._onKeyDown);\\n        this._global = null;\\n        this._pointerLock = null;\\n    }\\n}\\n\\n/**\\n * Displacement-based inputs (mouse, touch, wheel, pinch) return accumulated\\n * pixel offsets that already scale with frame time. This factor converts\\n * rate-based speed constants (tuned for degrees-per-second) to work with\\n * per-frame displacements, making them frame-rate-independent.\\n */\\nconst DISPLACEMENT_SCALE = 1 / 60;\\n/** Maximum accumulated touch movement (px) to still count as a tap. */\\nconst TAP_EPSILON = 15;\\nconst tmpHalfSize = new Vec3();\\n/**\\n * Converts screen-space pixel deltas to a world-space pan vector at the\\n * given depth.\\n *\\n * @param camera - The camera component.\\n * @param dx - Horizontal pixel delta.\\n * @param dy - Vertical pixel delta.\\n * @param dz - Depth (world-space) at which to project the delta.\\n * @param out - Optional output vector.\\n * @returns The pan vector in world space.\\n */\\nconst screenToWorld = (camera, dx, dy, dz, out = new Vec3()) => {\\n    const { system, fov, aspectRatio, horizontalFov, projection, orthoHeight } = camera;\\n    const { width, height } = system.app.graphicsDevice.clientRect;\\n    out.set(-(dx / width) * 2, (dy / height) * 2, 0);\\n    const halfSize = tmpHalfSize.set(0, 0, 0);\\n    if (projection === PROJECTION_PERSPECTIVE) {\\n        const halfSlice = dz * Math.tan(0.5 * fov * math.DEG_TO_RAD);\\n        if (horizontalFov) {\\n            halfSize.set(halfSlice, halfSlice / aspectRatio, 0);\\n        }\\n        else {\\n            halfSize.set(halfSlice * aspectRatio, halfSlice, 0);\\n        }\\n    }\\n    else {\\n        halfSize.set(orthoHeight * aspectRatio, orthoHeight, 0);\\n    }\\n    out.mul(halfSize);\\n    return out;\\n};\\n/**\\n * The orbit camera and the fly camera disagree on the sign of the z-axis\\n * for forward motion. Apply this when emitting a forward/back z-component\\n * so the same wheel-style delta drives both cameras correctly.\\n *\\n * @param mode - The current camera mode.\\n * @param z - The raw forward/back z-component.\\n * @returns The z-component flipped for orbit mode, unchanged otherwise.\\n */\\nconst flipZForOrbit = (mode, z) => (mode === 'orbit' ? -z : z);\\n\\nconst tmpV$4 = new Vec3();\\nconst canTargetFly = (global) => (global.state.cameraMode === 'fly' &&\\n    !(global.state.inputMode === 'desktop' && global.state.gamingControls));\\n// Mirror gaming-controls speed modifiers: shift = run/boost, ctrl = crawl/slow.\\n// Multipliers match keyboard-mouse.ts so click-nav and held-key movement feel the same.\\nconst computeClickSpeedMul = (event, mode) => {\\n    if (!event)\\n        return 1;\\n    if (mode === 'walk') {\\n        if (event.shiftKey)\\n            return 2;\\n        if (event.ctrlKey)\\n            return 0.5;\\n    }\\n    else if (mode === 'fly') {\\n        if (event.shiftKey)\\n            return 4;\\n        if (event.ctrlKey)\\n            return 0.25;\\n    }\\n    return 1;\\n};\\n/**\\n * Click-to-walk / click-to-fly / click-to-focus (desktop), tap equivalents\\n * on mobile, and double-click-to-pick fallback. Uses collision first and\\n * rendered-scene picking when collision is unavailable.\\n */\\nclass NavInteraction {\\n    collision = null;\\n    _picker;\\n    _global = null;\\n    _canvas = null;\\n    _lastPointerOffsetX = 0;\\n    _lastPointerOffsetY = 0;\\n    _mouseClickTracking = false;\\n    _mouseClickDelta = 0;\\n    _suppressClick = false;\\n    _targetPickRequest = 0;\\n    _lastTap = { time: 0, x: 0, y: 0 };\\n    constructor(picker) {\\n        this._picker = picker;\\n    }\\n    _updateCursor = () => {\\n        const global = this._global;\\n        const canvas = this._canvas;\\n        if (!global || !canvas)\\n            return;\\n        const { state } = global;\\n        const canClickTarget = state.inputMode === 'desktop' && ((state.cameraMode === 'walk' && !state.gamingControls) ||\\n            canTargetFly(global) ||\\n            state.cameraMode === 'orbit');\\n        if (canClickTarget) {\\n            canvas.style.cursor = this._mouseClickTracking ? 'default' : 'pointer';\\n        }\\n        else {\\n            canvas.style.cursor = '';\\n        }\\n    };\\n    _onCameraModeChanged = () => {\\n        this._targetPickRequest++;\\n        this._updateCursor();\\n    };\\n    _pickCollision(offsetX, offsetY) {\\n        if (!this.collision || !this._global)\\n            return null;\\n        const camera = this._global.camera;\\n        const cameraPos = camera.getPosition();\\n        camera.camera.screenToWorld(offsetX, offsetY, 1.0, tmpV$4);\\n        tmpV$4.sub(cameraPos).normalize();\\n        const hit = this.collision.queryRay(cameraPos.x, cameraPos.y, cameraPos.z, tmpV$4.x, tmpV$4.y, tmpV$4.z, camera.camera.farClip);\\n        if (!hit)\\n            return null;\\n        const sn = this.collision.querySurfaceNormal(hit.x, hit.y, hit.z, tmpV$4.x, tmpV$4.y, tmpV$4.z);\\n        return {\\n            position: new Vec3(hit.x, hit.y, hit.z),\\n            normal: new Vec3(sn.nx, sn.ny, sn.nz)\\n        };\\n    }\\n    async _pickSceneTarget(offsetX, offsetY) {\\n        const global = this._global;\\n        const canvas = this._canvas;\\n        if (!global || !canvas)\\n            return null;\\n        const collisionTarget = this._pickCollision(offsetX, offsetY);\\n        if (collisionTarget) {\\n            return collisionTarget;\\n        }\\n        const result = await this._picker.pickSurface(offsetX / canvas.clientWidth, offsetY / canvas.clientHeight);\\n        if (result) {\\n            return result;\\n        }\\n        return null;\\n    }\\n    async _flyToPickedPosition(offsetX, offsetY, event) {\\n        const global = this._global;\\n        if (!global || !canTargetFly(global))\\n            return;\\n        const request = ++this._targetPickRequest;\\n        const target = await this._pickSceneTarget(offsetX, offsetY);\\n        if (target && request === this._targetPickRequest && this._global && canTargetFly(this._global)) {\\n            const speedMul = computeClickSpeedMul(event, this._global.state.cameraMode);\\n            this._global.events.fire('navigateTo', target.position, target.normal, speedMul);\\n        }\\n    }\\n    async _focusPickedPosition(offsetX, offsetY) {\\n        const global = this._global;\\n        if (!global || global.state.cameraMode !== 'orbit')\\n            return;\\n        const request = ++this._targetPickRequest;\\n        const target = await this._pickSceneTarget(offsetX, offsetY);\\n        if (target && request === this._targetPickRequest && this._global?.state.cameraMode === 'orbit') {\\n            const { events } = this._global;\\n            events.fire('orbitTarget:set', target.position, target.normal);\\n            events.fire('pick', target.position);\\n        }\\n    }\\n    _onPointerDown = (event) => {\\n        const global = this._global;\\n        if (!global)\\n            return;\\n        const { events } = global;\\n        // record offsets for click/tap target picking\\n        this._lastPointerOffsetX = event.offsetX;\\n        this._lastPointerOffsetY = event.offsetY;\\n        // start desktop click target tracking\\n        if (event.pointerType !== 'touch' && event.button === 0) {\\n            this._mouseClickTracking = true;\\n            this._mouseClickDelta = 0;\\n            this._updateCursor();\\n        }\\n        // Manual double-click/tap detection for platforms that do not emit\\n        // reliable native dblclick events on the canvas.\\n        const now = Date.now();\\n        const delay = Math.max(0, now - this._lastTap.time);\\n        if (delay < 300 &&\\n            Math.abs(event.clientX - this._lastTap.x) < 8 &&\\n            Math.abs(event.clientY - this._lastTap.y) < 8) {\\n            this._suppressClick = true;\\n            events.fire('inputEvent', 'dblclick', event);\\n            this._lastTap.time = 0;\\n        }\\n        else {\\n            this._lastTap.time = now;\\n            this._lastTap.x = event.clientX;\\n            this._lastTap.y = event.clientY;\\n        }\\n    };\\n    _onPointerMove = (event) => {\\n        const global = this._global;\\n        if (!global)\\n            return;\\n        const { state, events } = global;\\n        if (this._mouseClickTracking && event.pointerType !== 'touch') {\\n            const prev = this._mouseClickDelta;\\n            this._mouseClickDelta += Math.abs(event.movementX) + Math.abs(event.movementY);\\n            if (prev < TAP_EPSILON && this._mouseClickDelta >= TAP_EPSILON) {\\n                if ((state.cameraMode === 'walk' && !state.gamingControls) || canTargetFly(global)) {\\n                    events.fire('navigateCancel');\\n                }\\n            }\\n        }\\n    };\\n    _onPointerUp = (event) => {\\n        const global = this._global;\\n        if (!global)\\n            return;\\n        const { state, events } = global;\\n        if (this._mouseClickTracking && event.pointerType !== 'touch' && event.button === 0) {\\n            this._mouseClickTracking = false;\\n            this._updateCursor();\\n            if (this._suppressClick) {\\n                this._suppressClick = false;\\n                return;\\n            }\\n            if (this._mouseClickDelta < TAP_EPSILON) {\\n                if (state.cameraMode === 'walk' && !state.gamingControls) {\\n                    const result = this._pickCollision(this._lastPointerOffsetX, this._lastPointerOffsetY);\\n                    if (result) {\\n                        const speedMul = computeClickSpeedMul(event, state.cameraMode);\\n                        events.fire('navigateTo', result.position, result.normal, speedMul);\\n                    }\\n                }\\n                else if (state.cameraMode === 'fly') {\\n                    this._flyToPickedPosition(this._lastPointerOffsetX, this._lastPointerOffsetY, event);\\n                }\\n                else if (state.cameraMode === 'orbit') {\\n                    this._focusPickedPosition(this._lastPointerOffsetX, this._lastPointerOffsetY);\\n                }\\n            }\\n        }\\n    };\\n    _onInputEvent = async (eventName, event) => {\\n        const global = this._global;\\n        const canvas = this._canvas;\\n        if (!global || !canvas)\\n            return;\\n        if (eventName !== 'dblclick')\\n            return;\\n        if (!(event instanceof MouseEvent))\\n            return;\\n        const { events, state } = global;\\n        // dblclick swaps the active mode and uses the picked target:\\n        //   fly          → orbit, focus orbit at point\\n        //   orbit / walk → fly, navigate fly toward point\\n        const request = ++this._targetPickRequest;\\n        const target = await this._pickSceneTarget(event.offsetX, event.offsetY);\\n        if (!target || request !== this._targetPickRequest)\\n            return;\\n        const currentMode = this._global?.state.cameraMode;\\n        if (currentMode === 'fly') {\\n            // 'pick' switches mode to orbit, which cancels the active fly nav\\n            // and would clobber any pre-set orbit target — set it after.\\n            events.fire('pick', target.position);\\n            events.fire('orbitTarget:set', target.position, target.normal);\\n        }\\n        else if (currentMode === 'orbit' || currentMode === 'walk') {\\n            state.cameraMode = 'fly';\\n            // Modifiers apply against the destination mode (fly), not the source.\\n            const speedMul = computeClickSpeedMul(event, 'fly');\\n            events.fire('navigateTo', target.position, target.normal, speedMul);\\n        }\\n    };\\n    _onMobileTap = () => {\\n        const global = this._global;\\n        if (!global)\\n            return;\\n        const { state, events } = global;\\n        if (this._suppressClick) {\\n            this._suppressClick = false;\\n            return;\\n        }\\n        if (state.cameraMode === 'walk' && !state.gamingControls) {\\n            const result = this._pickCollision(this._lastPointerOffsetX, this._lastPointerOffsetY);\\n            if (result) {\\n                events.fire('navigateTo', result.position, result.normal);\\n            }\\n        }\\n        else if (state.cameraMode === 'fly') {\\n            this._flyToPickedPosition(this._lastPointerOffsetX, this._lastPointerOffsetY);\\n        }\\n        else if (state.cameraMode === 'orbit') {\\n            this._focusPickedPosition(this._lastPointerOffsetX, this._lastPointerOffsetY);\\n        }\\n    };\\n    attach(canvas, global) {\\n        this._canvas = canvas;\\n        this._global = global;\\n        const { events } = global;\\n        canvas.addEventListener('pointerdown', this._onPointerDown);\\n        canvas.addEventListener('pointermove', this._onPointerMove);\\n        canvas.addEventListener('pointerup', this._onPointerUp);\\n        // double-click/tap fallback -> fly target or orbit focus (skipped in walk mode)\\n        events.on('inputEvent', this._onInputEvent);\\n        // mobile tap (no movement) → walk/fly target or orbit focus\\n        events.on('mobileTap', this._onMobileTap);\\n        // refresh cursor on mode / gaming-controls change\\n        events.on('cameraMode:changed', this._onCameraModeChanged);\\n        events.on('inputMode:changed', this._updateCursor);\\n        events.on('gamingControls:changed', this._updateCursor);\\n    }\\n    detach() {\\n        if (this._canvas) {\\n            this._canvas.removeEventListener('pointerdown', this._onPointerDown);\\n            this._canvas.removeEventListener('pointermove', this._onPointerMove);\\n            this._canvas.removeEventListener('pointerup', this._onPointerUp);\\n        }\\n        if (this._global) {\\n            const { events } = this._global;\\n            events.off('inputEvent', this._onInputEvent);\\n            events.off('mobileTap', this._onMobileTap);\\n            events.off('cameraMode:changed', this._onCameraModeChanged);\\n            events.off('inputMode:changed', this._updateCursor);\\n            events.off('gamingControls:changed', this._updateCursor);\\n        }\\n        this._canvas = null;\\n        this._global = null;\\n    }\\n}\\n\\nconst isCaptureMode = (mode) => mode === 'walk' || mode === 'fly';\\nconst hasUserActivation = () => (navigator.userActivation?.isActive === true);\\n/**\\n * Manages the browser's pointer-lock API for first-person gaming controls\\n * on desktop. Toggles in response to camera mode, input mode, and\\n * gaming-controls changes, and reverts state if the lock is exited or rejected.\\n *\\n * Also exposes `recentlyExitedCapture` so the keyboard-shortcut handler can\\n * de-duplicate the Escape keydown that triggered the lock exit.\\n */\\nclass PointerLockManager {\\n    _global = null;\\n    _canvas = null;\\n    _keyboardMouse = null;\\n    _recentlyExitedCapture = false;\\n    _onPointerLockChange = () => {\\n        const global = this._global;\\n        if (!global)\\n            return;\\n        const { state, events } = global;\\n        if (!document.pointerLockElement && isCaptureMode(state.cameraMode) && state.gamingControls) {\\n            this._recentlyExitedCapture = true;\\n            requestAnimationFrame(() => {\\n                this._recentlyExitedCapture = false;\\n            });\\n            if (state.inputMode === 'desktop') {\\n                state.gamingControls = false;\\n            }\\n            else if (state.cameraMode === 'walk') {\\n                events.fire('inputEvent', 'exitWalk');\\n            }\\n        }\\n    };\\n    _onPointerLockError = () => {\\n        // Pointer lock request rejected (no user gesture, document hidden,\\n        // etc). Revert state so we don't end up stuck in walk mode without\\n        // mouse capture.\\n        if (this._keyboardMouse) {\\n            this._keyboardMouse.source._pointerLock = false;\\n        }\\n        const global = this._global;\\n        if (!global)\\n            return;\\n        const { state, events } = global;\\n        if (state.inputMode === 'desktop' && isCaptureMode(state.cameraMode)) {\\n            state.gamingControls = false;\\n        }\\n        else if (state.cameraMode === 'walk') {\\n            events.fire('inputEvent', 'exitWalk');\\n        }\\n    };\\n    _onCameraModeChanged = (value, prev) => {\\n        const state = this._global?.state;\\n        if (!state)\\n            return;\\n        if (isCaptureMode(value) && state.inputMode === 'desktop' && state.gamingControls) {\\n            this._activate();\\n        }\\n        else if (isCaptureMode(prev)) {\\n            this._deactivate();\\n        }\\n    };\\n    _onGamingControlsChanged = (value) => {\\n        const state = this._global?.state;\\n        if (!state)\\n            return;\\n        if (isCaptureMode(state.cameraMode) && state.inputMode === 'desktop') {\\n            if (value) {\\n                this._activate();\\n            }\\n            else {\\n                this._deactivate();\\n            }\\n        }\\n    };\\n    _onInputModeChanged = (value) => {\\n        const state = this._global?.state;\\n        if (!state || !isCaptureMode(state.cameraMode) || !state.gamingControls) {\\n            return;\\n        }\\n        if (value === 'desktop' && hasUserActivation()) {\\n            this._activate();\\n        }\\n        else if (value !== 'desktop') {\\n            this._deactivate();\\n        }\\n    };\\n    _onPointerDown = () => {\\n        const state = this._global?.state;\\n        if (state && state.inputMode === 'desktop' && isCaptureMode(state.cameraMode) && state.gamingControls) {\\n            this._activate();\\n        }\\n    };\\n    _activate() {\\n        if (this._keyboardMouse) {\\n            this._keyboardMouse.source._pointerLock = true;\\n        }\\n        if (document.pointerLockElement !== this._canvas) {\\n            this._canvas?.requestPointerLock();\\n        }\\n    }\\n    _deactivate() {\\n        if (this._keyboardMouse) {\\n            this._keyboardMouse.source._pointerLock = false;\\n        }\\n        if (document.pointerLockElement === this._canvas) {\\n            document.exitPointerLock();\\n        }\\n    }\\n    get recentlyExitedCapture() {\\n        return this._recentlyExitedCapture;\\n    }\\n    attach(canvas, global, keyboardMouse) {\\n        this._canvas = canvas;\\n        this._global = global;\\n        this._keyboardMouse = keyboardMouse;\\n        const { events } = global;\\n        events.on('cameraMode:changed', this._onCameraModeChanged);\\n        events.on('gamingControls:changed', this._onGamingControlsChanged);\\n        events.on('inputMode:changed', this._onInputModeChanged);\\n        canvas.addEventListener('pointerdown', this._onPointerDown);\\n        document.addEventListener('pointerlockchange', this._onPointerLockChange);\\n        document.addEventListener('pointerlockerror', this._onPointerLockError);\\n    }\\n    detach() {\\n        if (this._global) {\\n            const { events } = this._global;\\n            events.off('cameraMode:changed', this._onCameraModeChanged);\\n            events.off('gamingControls:changed', this._onGamingControlsChanged);\\n            events.off('inputMode:changed', this._onInputModeChanged);\\n        }\\n        this._canvas?.removeEventListener('pointerdown', this._onPointerDown);\\n        document.removeEventListener('pointerlockchange', this._onPointerLockChange);\\n        document.removeEventListener('pointerlockerror', this._onPointerLockError);\\n        this._canvas = null;\\n        this._global = null;\\n        this._keyboardMouse = null;\\n    }\\n}\\n\\nconst tmpV$3 = new Vec3();\\nconst stickMove = new Vec3();\\nconst stickRotate = new Vec3();\\nclass GamepadDevice {\\n    moveSpeed = 4;\\n    orbitSpeed = 18;\\n    gamepadRotateSensitivity = 1.0;\\n    _source = new GamepadSource();\\n    _global = null;\\n    attach(_canvas, global) {\\n        this._global = global;\\n        // GamepadSource polls navigator.getGamepads() — no DOM attach needed.\\n    }\\n    detach() {\\n        this._global = null;\\n    }\\n    update(ctx, frame) {\\n        const { dt, cameraComponent, isFly, isFirstPerson } = ctx;\\n        const { leftStick, rightStick } = this._source.read();\\n        const orbitFactor = isFirstPerson ? cameraComponent.fov / 120 : 1;\\n        const { deltas } = frame;\\n        if (isFly && (leftStick[0] !== 0 || leftStick[1] !== 0 || rightStick[0] !== 0 || rightStick[1] !== 0)) {\\n            this._global?.events.fire('navigateCancel');\\n        }\\n        const v = tmpV$3.set(0, 0, 0);\\n        stickMove.set(leftStick[0], 0, -leftStick[1]);\\n        v.add(stickMove.mulScalar(this.moveSpeed * dt));\\n        deltas.move.append([v.x, v.y, v.z]);\\n        v.set(0, 0, 0);\\n        stickRotate.set(rightStick[0], rightStick[1], 0);\\n        v.add(stickRotate.mulScalar(this.orbitSpeed * orbitFactor * this.gamepadRotateSensitivity * dt));\\n        deltas.rotate.append([v.x, v.y, v.z]);\\n    }\\n}\\n\\nconst tmpV1 = new Vec3();\\nconst tmpV2 = new Vec3();\\nconst keyMove = new Vec3();\\nconst flyKeyVelocity = new Vec3();\\nconst panMove = new Vec3();\\nconst mouseRotate = new Vec3();\\nconst wheelMove = new Vec3();\\n// Patch keydown / keyup so meta-key combinations don't leave keys stuck on\\n// macOS (the OS swallows keyup for any key released while Cmd is held).\\nconst patchKeyboardMeta = (desktopInput) => {\\n    const origOnKeyDown = desktopInput._onKeyDown;\\n    desktopInput._onKeyDown = (event) => {\\n        if (event.key === 'Meta') {\\n            desktopInput._keyNow.fill(0);\\n        }\\n        else if (!event.metaKey) {\\n            origOnKeyDown(event);\\n        }\\n    };\\n    const origOnKeyUp = desktopInput._onKeyUp;\\n    desktopInput._onKeyUp = (event) => {\\n        if (event.key === 'Meta') {\\n            desktopInput._keyNow.fill(0);\\n        }\\n        else if (!event.metaKey) {\\n            origOnKeyUp(event);\\n        }\\n    };\\n};\\nclass KeyboardMouseDevice {\\n    moveSpeed = 4;\\n    orbitSpeed = 18;\\n    wheelSpeed = 0.06;\\n    mouseRotateSensitivity = 0.5;\\n    flyMoveAccelerationDamping = 0.992;\\n    flyMoveDecelerationDamping = 0.993;\\n    _source = new KeyboardMouseSource();\\n    _global = null;\\n    /** Running WASD/QE/arrow direction (sum of key states). */\\n    _axis = new Vec3();\\n    /** Running button-held state per index: [LMB, MMB, RMB]. */\\n    _buttons = [0, 0, 0];\\n    _shift = 0;\\n    _ctrl = 0;\\n    _jump = 0;\\n    _flyKeyVelocity = new Vec3();\\n    /**\\n     * Get the underlying source so other code (PointerLockManager) can\\n     * toggle its private pointer-lock flag, which gates how it consumes\\n     * mouse-delta events.\\n     *\\n     * @returns The PlayCanvas KeyboardMouseSource backing this device.\\n     */\\n    get source() {\\n        return this._source;\\n    }\\n    attach(canvas, global) {\\n        this._global = global;\\n        patchKeyboardMeta(this._source);\\n        this._source.attach(canvas);\\n    }\\n    detach() {\\n        // KeyboardMouseSource does not expose a detach; nothing to undo for\\n        // its DOM listeners here.\\n    }\\n    update(ctx, frame) {\\n        const { keyCode } = KeyboardMouseSource;\\n        const { key, button, mouse, wheel } = this._source.read();\\n        const { events } = this._global;\\n        // accumulate running input state\\n        this._axis.add(tmpV1.set((key[keyCode.D] - key[keyCode.A]) + (key[keyCode.RIGHT] - key[keyCode.LEFT]), (key[keyCode.E] - key[keyCode.Q]), (key[keyCode.W] - key[keyCode.S]) + (key[keyCode.UP] - key[keyCode.DOWN])));\\n        this._jump += key[keyCode.SPACE];\\n        this._shift += key[keyCode.SHIFT];\\n        this._ctrl += key[keyCode.CTRL];\\n        const n = Math.min(button.length, this._buttons.length);\\n        for (let i = 0; i < n; i++) {\\n            this._buttons[i] += button[i];\\n        }\\n        const { isFly, isWalk, isFirstPerson, gamingControls, dt, distance, cameraComponent, mode, touchCount } = ctx;\\n        const pan = this._buttons[2] || +(button[2] === -1) || +(touchCount > 1);\\n        // auto-move cancellation and requestFirstPerson events (driven by keyboard axes)\\n        if (isWalk && (this._axis.x !== 0 || this._axis.z !== 0)) {\\n            events.fire('navigateCancel');\\n        }\\n        if (isFly && (this._axis.x !== 0 || this._axis.y !== 0 || this._axis.z !== 0)) {\\n            events.fire('navigateCancel');\\n        }\\n        if (isFly && wheel[0] !== 0) {\\n            events.fire('navigateCancel');\\n        }\\n        if (isFly && (gamingControls || pan) && (mouse[0] !== 0 || mouse[1] !== 0)) {\\n            events.fire('navigateCancel');\\n        }\\n        if (!isFirstPerson && this._axis.length() > 0) {\\n            events.fire('inputEvent', 'requestFirstPerson');\\n        }\\n        const orbitFactor = isFirstPerson ? cameraComponent.fov / 120 : 1;\\n        const { deltas } = frame;\\n        // move (WASD + mouse-drag pan + wheel)\\n        const v = tmpV1.set(0, 0, 0);\\n        keyMove.copy(this._axis);\\n        if (isWalk) {\\n            // In walk mode normalize only horizontal axes so jump doesn't\\n            // reduce horizontal speed.\\n            keyMove.y = 0;\\n        }\\n        keyMove.normalize();\\n        const shiftMul = isWalk ? 2 : 4;\\n        const ctrlMul = isWalk ? 0.5 : 0.25;\\n        const speed = this.moveSpeed * (this._shift ? shiftMul : this._ctrl ? ctrlMul : 1);\\n        keyMove.mulScalar(speed);\\n        if (isFly) {\\n            flyKeyVelocity.copy(keyMove);\\n            const damping = flyKeyVelocity.lengthSq() > this._flyKeyVelocity.lengthSq() ?\\n                this.flyMoveAccelerationDamping :\\n                this.flyMoveDecelerationDamping;\\n            this._flyKeyVelocity.lerp(this._flyKeyVelocity, flyKeyVelocity, damp(damping, dt));\\n            if (flyKeyVelocity.lengthSq() === 0 && this._flyKeyVelocity.lengthSq() < 1e-4) {\\n                this._flyKeyVelocity.set(0, 0, 0);\\n            }\\n            keyMove.copy(this._flyKeyVelocity);\\n        }\\n        else {\\n            this._flyKeyVelocity.set(0, 0, 0);\\n        }\\n        v.add(tmpV2.copy(keyMove).mulScalar((isFirstPerson ? 1 : 0) * dt));\\n        if (isWalk) {\\n            // Pass jump signal as raw Y; WalkController uses move[1] > 0 as\\n            // a boolean trigger.\\n            v.y = this._jump > 0 ? 1 : 0;\\n        }\\n        screenToWorld(cameraComponent, mouse[0], mouse[1], distance, panMove);\\n        v.add(panMove.mulScalar(pan));\\n        wheelMove.set(0, 0, -wheel[0]);\\n        v.add(wheelMove.mulScalar(this.wheelSpeed * DISPLACEMENT_SCALE));\\n        deltas.move.append([v.x, v.y, flipZForOrbit(mode, v.z)]);\\n        // rotate (mouse-drag, masked when in pan mode)\\n        v.set(0, 0, 0);\\n        mouseRotate.set(mouse[0], mouse[1], 0);\\n        v.add(mouseRotate.mulScalar((1 - pan) * this.orbitSpeed * orbitFactor * this.mouseRotateSensitivity * DISPLACEMENT_SCALE));\\n        deltas.rotate.append([v.x, v.y, v.z]);\\n    }\\n}\\n\\nconst tmpV$2 = new Vec3();\\nconst orbitMove = new Vec3();\\nconst flyMoveTmp = new Vec3();\\nconst pinchMoveTmp = new Vec3();\\nconst orbitRotate = new Vec3();\\nconst flyRotate = new Vec3();\\nclass TouchDevice {\\n    orbitSpeed = 18;\\n    moveSpeed = 4;\\n    pinchSpeed = 0.4;\\n    touchRotateSensitivity = 1.5;\\n    _source = new MultiTouchSource();\\n    _global = null;\\n    /** Touches currently active (running count from .read() deltas). */\\n    _touchCount = 0;\\n    /** UI joystick value [x, y], -1..1. */\\n    _joystick = [0, 0];\\n    /** Tap-detection state — touch count, max touches, and accumulated movement. */\\n    _tapTouches = 0;\\n    _tapMaxTouches = 0;\\n    _tapDelta = 0;\\n    /** True for one frame after a tap is detected during gaming controls. */\\n    _tapJump = false;\\n    _onJoystickInput = (value) => {\\n        this._joystick[0] = value.x;\\n        this._joystick[1] = value.y;\\n    };\\n    get touchCount() {\\n        return this._touchCount;\\n    }\\n    attach(canvas, global) {\\n        this._global = global;\\n        this._source.attach(canvas);\\n        global.events.on('joystickInput', this._onJoystickInput);\\n    }\\n    detach() {\\n        // MultiTouchSource doesn't expose a detach.\\n        if (this._global) {\\n            this._global.events.off('joystickInput', this._onJoystickInput);\\n            this._global = null;\\n        }\\n    }\\n    update(ctx, frame) {\\n        const { touch, pinch, count } = this._source.read();\\n        const { isFly, isWalk, isFirstPerson, isOrbit, gamingControls, dt, distance, cameraComponent } = ctx;\\n        // running touch count\\n        this._touchCount += count[0];\\n        if (isFly && gamingControls && (this._joystick[0] !== 0 || this._joystick[1] !== 0)) {\\n            this._global.events.fire('navigateCancel');\\n        }\\n        // tap detection for click/tap target and focus modes\\n        if (isWalk || isFly || isOrbit) {\\n            const prevTaps = this._tapTouches;\\n            this._tapTouches = Math.max(0, this._tapTouches + count[0]);\\n            if (prevTaps === 0 && this._tapTouches > 0) {\\n                this._tapDelta = 0;\\n            }\\n            if (this._tapTouches > 0) {\\n                this._tapMaxTouches = Math.max(this._tapMaxTouches, this._tapTouches);\\n            }\\n            if (this._tapTouches > 0) {\\n                const prevDelta = this._tapDelta;\\n                this._tapDelta += Math.abs(touch[0]) + Math.abs(touch[1]) + Math.abs(pinch[0]);\\n                if (prevDelta < TAP_EPSILON && this._tapDelta >= TAP_EPSILON) {\\n                    if ((isWalk && !gamingControls) || isFly) {\\n                        this._global.events.fire('navigateCancel');\\n                    }\\n                }\\n            }\\n            if (prevTaps > 0 && this._tapTouches === 0) {\\n                if (this._tapDelta < TAP_EPSILON && this._tapMaxTouches === 1) {\\n                    if (isWalk && !gamingControls) {\\n                        // Walk-interaction listens for this and fires navigateTo\\n                        // after picking.\\n                        this._global.events.fire('mobileTap');\\n                    }\\n                    else if (isWalk) {\\n                        this._tapJump = true;\\n                    }\\n                    else if (isFly && !gamingControls) {\\n                        // Walk-interaction listens for this and fires navigateTo\\n                        // after picking.\\n                        this._global.events.fire('mobileTap');\\n                    }\\n                    else if (isOrbit) {\\n                        // Walk-interaction listens for this and sets orbit focus\\n                        // after picking.\\n                        this._global.events.fire('mobileTap');\\n                    }\\n                }\\n                this._tapMaxTouches = 0;\\n            }\\n        }\\n        else {\\n            this._tapTouches = 0;\\n            this._tapMaxTouches = 0;\\n        }\\n        const orbit = isOrbit ? 1 : 0;\\n        const fly = isFirstPerson ? 1 : 0;\\n        const double = this._touchCount > 1 ? 1 : 0;\\n        const orbitFactor = isFirstPerson ? cameraComponent.fov / 120 : 1;\\n        const dragInvert = (isFirstPerson && !gamingControls) ? -1 : 1;\\n        // First-person modes (fly and walk) opt into the direct two-finger\\n        // model only outside gaming controls (gaming uses the joystick).\\n        const directFirstPerson = fly * (gamingControls ? 0 : 1);\\n        const { deltas } = frame;\\n        // move\\n        const v = tmpV$2.set(0, 0, 0);\\n        // Two-finger pan: orbit pans the target; fly strafes/rises in the\\n        // camera basis; walk strafes along the ground plane. Identical 1:1\\n        // screen-space mapping in every mode so dragging feels the same —\\n        // what your fingers move, the camera moves. Walk zeros y because\\n        // WalkController treats any nonzero move[1] as a jump trigger.\\n        screenToWorld(cameraComponent, touch[0], touch[1], distance, orbitMove);\\n        if (isWalk) {\\n            orbitMove.y = 0;\\n        }\\n        v.add(orbitMove.mulScalar((orbit + directFirstPerson) * double));\\n        if (gamingControls) {\\n            // joystick UI drives strafe + forward/back in fly/walk\\n            flyMoveTmp.set(this._joystick[0], 0, -this._joystick[1]);\\n            v.add(flyMoveTmp.mulScalar(fly * this.moveSpeed * dt));\\n        }\\n        // Two-finger pinch z: orbit interprets +z as \\\"farther from target\\\"\\n        // (close-pinch = +pinch[0] = zoom out). First-person modes interpret\\n        // +z as \\\"forward\\\", so spreading (pinch[0] < 0) should move forward —\\n        // flip the sign there.\\n        pinchMoveTmp.set(0, 0, (orbit - directFirstPerson) * pinch[0]);\\n        v.add(pinchMoveTmp.mulScalar(double * this.pinchSpeed * DISPLACEMENT_SCALE));\\n        // tap-to-jump in walk + gaming controls\\n        if (isWalk && this._tapJump) {\\n            v.y = 1;\\n            this._tapJump = false;\\n        }\\n        deltas.move.append([v.x, v.y, v.z]);\\n        // rotate\\n        v.set(0, 0, 0);\\n        // single-touch orbit rotate (masked when there are 2+ touches)\\n        orbitRotate.set(touch[0], touch[1], 0);\\n        v.add(orbitRotate.mulScalar(orbit * (1 - double) * this.orbitSpeed * this.touchRotateSensitivity * DISPLACEMENT_SCALE));\\n        // single-touch fly look (inverted in non-gaming first-person)\\n        flyRotate.set(touch[0] * dragInvert, touch[1] * dragInvert, 0);\\n        v.add(flyRotate.mulScalar(fly * (1 - double) * this.orbitSpeed * orbitFactor * this.touchRotateSensitivity * DISPLACEMENT_SCALE));\\n        deltas.rotate.append([v.x, v.y, v.z]);\\n    }\\n}\\n\\nconst tmpV$1 = new Vec3();\\nclass TrackpadDevice {\\n    orbitSpeed = 18;\\n    wheelSpeed = 0.06;\\n    trackpadOrbitSensitivity = 0.75;\\n    trackpadPanSensitivity = 1.0;\\n    trackpadZoomSensitivity = 2.0;\\n    _global = null;\\n    _orbit = [0, 0];\\n    _pan = [0, 0];\\n    _zoom = 0;\\n    // Tracks physical Ctrl key state so we can distinguish macOS-synthesized\\n    // pinch events (wheel + ctrlKey, no physical Ctrl) from a user holding\\n    // Ctrl while spinning a mouse wheel. The synthetic-Ctrl signal is the\\n    // one reliable trackpad indicator the platform gives us — every other\\n    // per-event heuristic has been tried (wheelDelta % 120, deltaMode,\\n    // fractional/diagonal deltas) and misfires on hi-res mice or in\\n    // momentum tails. Modifier-key state we can trust 100%.\\n    _ctrlDown = false;\\n    _onKeyDown = (event) => {\\n        if (event.key === 'Control') {\\n            this._ctrlDown = true;\\n        }\\n    };\\n    _onKeyUp = (event) => {\\n        if (event.key === 'Control') {\\n            this._ctrlDown = false;\\n        }\\n    };\\n    // Window blur (alt-tab, focus another app) drops keyup events, so\\n    // clear Ctrl state defensively to avoid getting stuck.\\n    _onBlur = () => {\\n        this._ctrlDown = false;\\n    };\\n    _onWheel = (event) => {\\n        const mode = this._global.state.cameraMode;\\n        // Synthetic Ctrl (macOS pinch-to-zoom, Magic Mouse pinch): ctrlKey\\n        // is true on the event but the user isn't physically holding Ctrl.\\n        // Routes to trackpad-tuned zoom.\\n        const isPinch = event.ctrlKey && !this._ctrlDown;\\n        // Physical Ctrl + wheel/swipe: rotate. In orbit mode rotates around\\n        // the target; in fly/walk mode looks around. Applies to both mouse\\n        // wheel and trackpad swipe — we can't distinguish them, and the\\n        // modifier signals intent either way.\\n        // Corner case: user physically holds Ctrl AND pinches at the same\\n        // time — both flags are true, the gesture lands here as rotate\\n        // rather than pinch. Intentional: physical Ctrl is the explicit\\n        // signal, so it wins over the synthetic-Ctrl pinch heuristic.\\n        const isCtrlRotate = event.ctrlKey && this._ctrlDown;\\n        // Shift + wheel/swipe: pan (= strafe + vertical) in all modes. The\\n        // downstream camera controllers translate the screen-space pan\\n        // vector appropriately (orbit pans around the target plane; fly\\n        // strafes sideways and translates vertically; walk strafes).\\n        const isShiftPan = event.shiftKey;\\n        if (!isPinch && !isCtrlRotate && !isShiftPan) {\\n            // Bare wheel (mouse or trackpad swipe), unmodified fly/walk\\n            // wheels — all fall through to KeyboardMouseDevice for\\n            // standard forward/back motion (which dollys toward the orbit\\n            // target in orbit mode via flipZForOrbit, giving the universal\\n            // bare-scroll-zooms behavior).\\n            return;\\n        }\\n        event.preventDefault();\\n        // stopImmediatePropagation() blocks KeyboardMouseSource's wheel\\n        // handler (also attached to this canvas) so the wheel delta\\n        // doesn't double-up on the existing forward/back path. It also\\n        // blocks the canvas-level interrupt listener registered elsewhere,\\n        // so fire interrupt explicitly to keep parity with mouse-wheel.\\n        event.stopImmediatePropagation();\\n        this._global.events.fire('inputEvent', 'interrupt', event);\\n        if (mode === 'fly') {\\n            this._global.events.fire('navigateCancel');\\n        }\\n        const { deltaX, deltaY } = event;\\n        if (isPinch) {\\n            this._zoom += deltaY;\\n        }\\n        else if (isCtrlRotate) {\\n            this._orbit[0] += deltaX;\\n            this._orbit[1] += deltaY;\\n        }\\n        else {\\n            this._pan[0] += deltaX;\\n            this._pan[1] += deltaY;\\n        }\\n    };\\n    _canvas = null;\\n    /**\\n     * Trackpad must attach BEFORE KeyboardMouseSource so its\\n     * `stopImmediatePropagation()` blocks the mouse-source wheel handler\\n     * for trackpad bursts. The coordinator enforces this by attaching\\n     * trackpad before keyboard-mouse.\\n     *\\n     * Keyboard listeners attach on `window` (not the canvas) so we still\\n     * see Ctrl keydown/keyup when focus is on a UI overlay.\\n     *\\n     * @param canvas - The canvas element to listen to.\\n     * @param global - The global app context (state, events, etc.).\\n     */\\n    attach(canvas, global) {\\n        this._canvas = canvas;\\n        this._global = global;\\n        canvas.addEventListener('wheel', this._onWheel, { passive: false });\\n        window.addEventListener('keydown', this._onKeyDown);\\n        window.addEventListener('keyup', this._onKeyUp);\\n        window.addEventListener('blur', this._onBlur);\\n    }\\n    detach() {\\n        if (this._canvas) {\\n            this._canvas.removeEventListener('wheel', this._onWheel);\\n            this._canvas = null;\\n        }\\n        window.removeEventListener('keydown', this._onKeyDown);\\n        window.removeEventListener('keyup', this._onKeyUp);\\n        window.removeEventListener('blur', this._onBlur);\\n        this._global = null;\\n        this._ctrlDown = false;\\n        this._orbit[0] = this._orbit[1] = 0;\\n        this._pan[0] = this._pan[1] = 0;\\n        this._zoom = 0;\\n    }\\n    update(ctx, frame) {\\n        const { isOrbit, isFirstPerson, distance, cameraComponent } = ctx;\\n        const orbitFactor = isFirstPerson ? cameraComponent.fov / 120 : 1;\\n        const { deltas } = frame;\\n        if (isOrbit) {\\n            // Ctrl + scroll → orbit rotate\\n            const v = tmpV$1.set(this._orbit[0], this._orbit[1], 0);\\n            v.mulScalar(this.orbitSpeed * this.trackpadOrbitSensitivity * DISPLACEMENT_SCALE);\\n            deltas.rotate.append([v.x, v.y, 0]);\\n            // shift + scroll → pan in world space (matches desktop pan path); reuse tmpV after rotate append\\n            screenToWorld(cameraComponent, this._pan[0], this._pan[1], distance, tmpV$1);\\n            tmpV$1.mulScalar(this.trackpadPanSensitivity);\\n            deltas.move.append([tmpV$1.x, tmpV$1.y, 0]);\\n            // synthetic-Ctrl pinch → zoom along z; positive deltaY (scroll-down / pinch-in) → zoom out → +z for orbit\\n            const zoomZ = this._zoom * this.wheelSpeed * this.trackpadZoomSensitivity * DISPLACEMENT_SCALE;\\n            deltas.move.append([0, 0, zoomZ]);\\n        }\\n        else if (isFirstPerson) {\\n            // Ctrl + scroll → look around in fly/walk\\n            const v = tmpV$1.set(this._orbit[0], this._orbit[1], 0);\\n            v.mulScalar(this.orbitSpeed * orbitFactor * this.trackpadOrbitSensitivity * DISPLACEMENT_SCALE);\\n            deltas.rotate.append([v.x, v.y, 0]);\\n            // shift + scroll → strafe (X) + vertical (Y) via the same\\n            // screen-space pan pipeline as orbit mode; the fly/walk\\n            // controllers translate this into sideways/vertical motion\\n            screenToWorld(cameraComponent, this._pan[0], this._pan[1], distance, tmpV$1);\\n            tmpV$1.mulScalar(this.trackpadPanSensitivity);\\n            deltas.move.append([tmpV$1.x, tmpV$1.y, 0]);\\n            // synthetic-Ctrl pinch → forward/back along z (same sign as the\\n            // bare-wheel path in KeyboardMouseDevice, so pinch and scroll\\n            // produce identical motion in fly/walk modes)\\n            const moveZ = -this._zoom * this.wheelSpeed * this.trackpadZoomSensitivity * DISPLACEMENT_SCALE;\\n            deltas.move.append([0, 0, moveZ]);\\n        }\\n        this._orbit[0] = this._orbit[1] = 0;\\n        this._pan[0] = this._pan[1] = 0;\\n        this._zoom = 0;\\n    }\\n}\\n\\n/**\\n * Coordinator that wires together input devices (keyboard-mouse, touch,\\n * trackpad, gamepad) and app-level UX helpers (mode shortcuts, nav\\n * interaction, pointer lock, input-mode tracker), and exposes the\\n * resulting per-frame `InputFrame` for the camera manager to consume.\\n */\\nclass InputController {\\n    frame = new InputFrame({\\n        move: [0, 0, 0],\\n        rotate: [0, 0, 0]\\n    });\\n    _global;\\n    _trackpad = new TrackpadDevice();\\n    _keyboardMouse = new KeyboardMouseDevice();\\n    _touch = new TouchDevice();\\n    _gamepad = new GamepadDevice();\\n    _navInteraction;\\n    _pointerLock = new PointerLockManager();\\n    _modeShortcuts = new ModeShortcuts();\\n    _inputModeTracker = new InputModeTracker();\\n    set collision(value) {\\n        this._navInteraction.collision = value;\\n    }\\n    get collision() {\\n        return this._navInteraction.collision;\\n    }\\n    constructor(global, picker) {\\n        this._global = global;\\n        this._navInteraction = new NavInteraction(picker);\\n        const { app, events } = global;\\n        const canvas = app.graphicsDevice.canvas;\\n        // Trackpad MUST attach before KeyboardMouseDevice so its wheel\\n        // handler runs first; otherwise stopImmediatePropagation can't\\n        // block KeyboardMouseSource from also accumulating the wheel delta.\\n        this._trackpad.attach(canvas, global);\\n        this._keyboardMouse.attach(canvas, global);\\n        this._touch.attach(canvas, global);\\n        this._gamepad.attach(canvas, global);\\n        this._navInteraction.attach(canvas, global);\\n        this._pointerLock.attach(canvas, global, this._keyboardMouse);\\n        this._modeShortcuts.attach(global, this._pointerLock);\\n        this._inputModeTracker.attach(global);\\n        // canvas-level signals: anything that interrupts an animation /\\n        // closes the settings panel / dismisses the walk hint\\n        ['wheel', 'pointerdown', 'contextmenu', 'keydown'].forEach((eventName) => {\\n            canvas.addEventListener(eventName, (event) => {\\n                events.fire('inputEvent', 'interrupt', event);\\n            });\\n        });\\n        canvas.addEventListener('pointermove', (event) => {\\n            events.fire('inputEvent', 'interact', event);\\n        });\\n    }\\n    update(dt, distance) {\\n        const { state } = this._global;\\n        const cameraComponent = this._global.camera.camera;\\n        const isOrbit = state.cameraMode === 'orbit';\\n        const isFly = state.cameraMode === 'fly';\\n        const isWalk = state.cameraMode === 'walk';\\n        const isFirstPerson = isFly || isWalk;\\n        const ctx = {\\n            dt,\\n            distance,\\n            cameraComponent,\\n            mode: state.cameraMode,\\n            isOrbit,\\n            isFly,\\n            isWalk,\\n            isFirstPerson,\\n            gamingControls: state.gamingControls,\\n            // Touch must update first so the count is current; the running\\n            // count is also used by the keyboard-mouse pan flag.\\n            touchCount: this._touch.touchCount\\n        };\\n        // order: touch first (so touchCount in ctx reflects this frame's\\n        // count delta), then everyone else.\\n        this._touch.update(ctx, this.frame);\\n        ctx.touchCount = this._touch.touchCount;\\n        this._keyboardMouse.update(ctx, this.frame);\\n        this._trackpad.update(ctx, this.frame);\\n        this._gamepad.update(ctx, this.frame);\\n    }\\n}\\n\\n// Single-layer overlay rendered after the gaussians, three passes on a fresh\\n// depth buffer:\\n//\\n//   1. Surface depth pre-pass: color writes masked off, depth test/write on.\\n//      Stamps the front-most surface depth into the depth buffer.\\n//   2. Surface color pass: depthFunc EQUAL, depth write off, vertex-color\\n//      tinted via StandardMaterial. Only the front-most fragment from pass 1\\n//      survives so a single layer of semi-transparent surface color blends\\n//      onto the camera target.\\n//   3. Wireframe pass: opaque-looking black lines (RENDERSTYLE_WIREFRAME),\\n//      depth-tested against the surface depth so back-facing edges are\\n//      hidden.\\n//\\n// All three passes use BLEND_NORMAL so they share the layer's *transparent*\\n// render action. PlayCanvas creates separate opaque and transparent render\\n// actions per layer and `clearDepthBuffer` clears the depth buffer for each\\n// of them — if the depth pre-pass were opaque, the transparent action would\\n// wipe the depth before pass 2 and FUNC_EQUAL would always fail.\\n// Linear gray levels picked by dominant face axis, plus the surface alpha.\\n// These values are what we want the framebuffer to actually contain — pre-\\n// encoding below makes that true regardless of the gamma path taken.\\nconst SURFACE_GRAY_X = 0.85;\\nconst SURFACE_GRAY_Y = 0.55;\\nconst SURFACE_GRAY_Z = 0.30;\\nconst SURFACE_ALPHA = 0.30;\\n// Build an unindexed mesh where every triangle has three unique vertices that\\n// share the triangle's flat face color (tint by dominant axis of the face\\n// normal, alpha baked in). Per-triangle vertices give the surface a faceted\\n// look matching the voxel overlay.\\n//\\n// `cameraFrameEnabled` controls how the per-vertex color is encoded so the\\n// overlay looks identical between the WebGL (no CameraFrame) and\\n// WebGPU (CameraFrame) paths. With CameraFrame on, the engine's\\n// `gammaCorrectOutput` is a no-op (GAMMA_NONE) and the StandardMaterial\\n// output lands in the framebuffer as-is — so we feed the raw gray value.\\n// Without CameraFrame, `gammaCorrectOutput` applies `pow(1/2.2)` to the\\n// material output, so we feed `pow(gray, 2.2)` here and gamma-correct\\n// undoes it; the framebuffer ends up storing the same raw gray value.\\n// Encode the per-triangle gray + alpha into a flat Uint8 RGBA color stream\\n// (one entry per unwelded vertex, three vertices per triangle). Reuses an\\n// existing buffer if one is provided so colors can be re-baked when the\\n// CameraFrame state toggles at runtime (e.g. XR start/end).\\nconst encodeFlatColors = (tris, cameraFrameEnabled, out) => {\\n    const encode = (v) => Math.round((cameraFrameEnabled ? v : Math.pow(v, 2.2)) * 255);\\n    const grayX = encode(SURFACE_GRAY_X);\\n    const grayY = encode(SURFACE_GRAY_Y);\\n    const grayZ = encode(SURFACE_GRAY_Z);\\n    const alpha = Math.round(SURFACE_ALPHA * 255);\\n    const numTris = tris.count;\\n    const colors = out ?? new Uint8Array(numTris * 12);\\n    for (let i = 0; i < numTris; i++) {\\n        const ax = Math.abs(tris.nx[i]);\\n        const ay = Math.abs(tris.ny[i]);\\n        const az = Math.abs(tris.nz[i]);\\n        let gray;\\n        if (ax > ay && ax > az) {\\n            gray = grayX;\\n        }\\n        else if (ay > az) {\\n            gray = grayY;\\n        }\\n        else {\\n            gray = grayZ;\\n        }\\n        const oc = i * 12;\\n        for (let j = 0; j < 3; j++) {\\n            const k = oc + j * 4;\\n            colors[k] = gray;\\n            colors[k + 1] = gray;\\n            colors[k + 2] = gray;\\n            colors[k + 3] = alpha;\\n        }\\n    }\\n    return colors;\\n};\\nconst buildFlatMesh = (tris, cameraFrameEnabled) => {\\n    const numTris = tris.count;\\n    const flatPositions = new Float32Array(numTris * 9);\\n    const flatColors = encodeFlatColors(tris, cameraFrameEnabled);\\n    const flatIndices = new Uint32Array(numTris * 3);\\n    for (let i = 0; i < numTris; i++) {\\n        const op = i * 9;\\n        flatPositions[op] = tris.v0x[i];\\n        flatPositions[op + 1] = tris.v0y[i];\\n        flatPositions[op + 2] = tris.v0z[i];\\n        flatPositions[op + 3] = tris.v1x[i];\\n        flatPositions[op + 4] = tris.v1y[i];\\n        flatPositions[op + 5] = tris.v1z[i];\\n        flatPositions[op + 6] = tris.v2x[i];\\n        flatPositions[op + 7] = tris.v2y[i];\\n        flatPositions[op + 8] = tris.v2z[i];\\n        const oi = i * 3;\\n        flatIndices[oi] = oi;\\n        flatIndices[oi + 1] = oi + 1;\\n        flatIndices[oi + 2] = oi + 2;\\n    }\\n    return { flatPositions, flatColors, flatIndices };\\n};\\n// Configures a StandardMaterial that emits the per-vertex color directly. The\\n// depth pre-pass and the color pass use the same configuration (so they\\n// compile to identical shaders and produce bit-identical depth values for\\n// FUNC_EQUAL); only their write masks and depth state differ.\\nconst makeSurfaceMaterial = () => {\\n    const m = new StandardMaterial();\\n    m.useLighting = false;\\n    m.useSkybox = false;\\n    m.useFog = false;\\n    m.useTonemap = false;\\n    m.ambient = new Color(0, 0, 0);\\n    m.diffuse = new Color(0, 0, 0);\\n    m.specular = new Color(0, 0, 0);\\n    m.emissive = new Color(1, 1, 1);\\n    m.emissiveVertexColor = true;\\n    m.emissiveVertexColorChannel = 'rgb';\\n    m.opacityVertexColor = true;\\n    m.opacityVertexColorChannel = 'a';\\n    m.opacity = 1;\\n    return m;\\n};\\nclass MeshDebugOverlay {\\n    app;\\n    camera;\\n    layer;\\n    entity;\\n    mesh;\\n    triangles;\\n    flatColors;\\n    materials;\\n    _enabled = false;\\n    constructor(app, collision, camera, cameraFrameEnabled) {\\n        this.app = app;\\n        this.camera = camera;\\n        this.triangles = collision.triangles;\\n        const device = app.graphicsDevice;\\n        const { flatPositions, flatColors, flatIndices } = buildFlatMesh(this.triangles, cameraFrameEnabled);\\n        this.flatColors = flatColors;\\n        const mesh = new Mesh(device);\\n        mesh.setPositions(flatPositions);\\n        mesh.setColors32(flatColors);\\n        mesh.setIndices(flatIndices);\\n        mesh.update(PRIMITIVE_TRIANGLES);\\n        mesh.generateWireframe();\\n        this.mesh = mesh;\\n        this.layer = new Layer({\\n            name: 'CollisionOverlay',\\n            enabled: false,\\n            clearColorBuffer: false,\\n            clearDepthBuffer: true,\\n            opaqueSortMode: SORTMODE_MANUAL,\\n            transparentSortMode: SORTMODE_MANUAL\\n        });\\n        app.scene.layers.push(this.layer);\\n        camera.camera.layers = [...camera.camera.layers, this.layer.id];\\n        // Pass 1: depth pre-pass. Color writes masked off so only depth lands\\n        // in the buffer. Both this and pass 2 use the same depthBias /\\n        // slopeDepthBias so they write/test identical depth values\\n        // (FUNC_EQUAL relies on this) while still sitting slightly behind the\\n        // wireframe lines so pass 3's FUNC_LESSEQUAL passes reliably without\\n        // z-fighting.\\n        const depthMaterial = makeSurfaceMaterial();\\n        depthMaterial.cull = CULLFACE_BACK;\\n        depthMaterial.blendType = BLEND_NORMAL;\\n        depthMaterial.depthTest = true;\\n        depthMaterial.depthWrite = true;\\n        depthMaterial.depthBias = 1;\\n        depthMaterial.slopeDepthBias = 1;\\n        depthMaterial.redWrite = false;\\n        depthMaterial.greenWrite = false;\\n        depthMaterial.blueWrite = false;\\n        depthMaterial.alphaWrite = false;\\n        depthMaterial.update();\\n        const depthInstance = new MeshInstance(mesh, depthMaterial);\\n        depthInstance.drawOrder = 0;\\n        const depthEntity = new Entity('CollisionDepthPrepass');\\n        depthEntity.addComponent('render', {\\n            meshInstances: [depthInstance],\\n            layers: [this.layer.id]\\n        });\\n        // Pass 2: surface color, depth EQUAL. Only the front-most fragment\\n        // from pass 1 survives, so a single layer of vertex color blends onto\\n        // the camera target.\\n        const surfaceMaterial = makeSurfaceMaterial();\\n        surfaceMaterial.cull = CULLFACE_BACK;\\n        surfaceMaterial.blendType = BLEND_NORMAL;\\n        surfaceMaterial.depthTest = true;\\n        surfaceMaterial.depthFunc = FUNC_EQUAL;\\n        surfaceMaterial.depthWrite = false;\\n        surfaceMaterial.depthBias = 1;\\n        surfaceMaterial.slopeDepthBias = 1;\\n        surfaceMaterial.update();\\n        const surfaceInstance = new MeshInstance(mesh, surfaceMaterial);\\n        surfaceInstance.drawOrder = 1;\\n        const surfaceEntity = new Entity('CollisionSurface');\\n        surfaceEntity.addComponent('render', {\\n            meshInstances: [surfaceInstance],\\n            layers: [this.layer.id]\\n        });\\n        // Pass 3: wireframe — black lines depth-tested against the surface so\\n        // back-facing edges are hidden. BLEND_NORMAL with opacity = 1 looks\\n        // opaque but routes through the same transparent render action as the\\n        // other two passes, keeping all three under one depth clear.\\n        const wireframeMaterial = new StandardMaterial();\\n        wireframeMaterial.useLighting = false;\\n        wireframeMaterial.useSkybox = false;\\n        wireframeMaterial.useFog = false;\\n        wireframeMaterial.useTonemap = false;\\n        wireframeMaterial.ambient = new Color(0, 0, 0);\\n        wireframeMaterial.diffuse = new Color(0, 0, 0);\\n        wireframeMaterial.specular = new Color(0, 0, 0);\\n        wireframeMaterial.emissive = new Color(0, 0, 0);\\n        wireframeMaterial.opacity = 1;\\n        wireframeMaterial.blendType = BLEND_NORMAL;\\n        wireframeMaterial.depthTest = true;\\n        wireframeMaterial.depthFunc = FUNC_LESSEQUAL;\\n        wireframeMaterial.depthWrite = false;\\n        wireframeMaterial.cull = CULLFACE_NONE;\\n        wireframeMaterial.update();\\n        const wireframeInstance = new MeshInstance(mesh, wireframeMaterial);\\n        wireframeInstance.drawOrder = 2;\\n        const wireframeEntity = new Entity('CollisionWireframe');\\n        wireframeEntity.addComponent('render', {\\n            meshInstances: [wireframeInstance],\\n            layers: [this.layer.id]\\n        });\\n        wireframeEntity.render.renderStyle = RENDERSTYLE_WIREFRAME;\\n        this.materials = [depthMaterial, surfaceMaterial, wireframeMaterial];\\n        this.entity = new Entity('MeshCollisionDebug');\\n        this.entity.addChild(depthEntity);\\n        this.entity.addChild(surfaceEntity);\\n        this.entity.addChild(wireframeEntity);\\n        this.entity.enabled = false;\\n        app.root.addChild(this.entity);\\n    }\\n    set enabled(value) {\\n        this._enabled = value;\\n        this.entity.enabled = value;\\n        // Disable the layer too — otherwise its render actions still execute\\n        // each frame and the per-layer `clearDepthBuffer` would wipe depth\\n        // even when no overlay meshes are submitted.\\n        this.layer.enabled = value;\\n    }\\n    get enabled() {\\n        return this._enabled;\\n    }\\n    /**\\n     * Re-bake and re-upload the per-vertex colors so the overlay stays\\n     * correct if CameraFrame is destroyed or recreated at runtime (the\\n     * gamma path differs between the two states).\\n     *\\n     * @param cameraFrameEnabled - whether CameraFrame is currently active.\\n     */\\n    setCameraFrameEnabled(cameraFrameEnabled) {\\n        encodeFlatColors(this.triangles, cameraFrameEnabled, this.flatColors);\\n        this.mesh.setColors32(this.flatColors);\\n        this.mesh.update(PRIMITIVE_TRIANGLES);\\n    }\\n    destroy() {\\n        // Entity.destroy() removes child entities and tears down their render\\n        // components, which destroy the MeshInstances and decref the shared\\n        // Mesh (the last decref destroys its GPU buffers). Materials are not\\n        // owned by MeshInstance so destroy them explicitly here.\\n        this.entity?.destroy();\\n        for (const m of this.materials)\\n            m.destroy();\\n        this.materials.length = 0;\\n        this.app.scene.layers.remove(this.layer);\\n        this.camera.camera.layers = this.camera.camera.layers.filter(id => id !== this.layer.id);\\n    }\\n}\\n\\nconst SVGNS = 'http://www.w3.org/2000/svg';\\nconst NUM_SAMPLES = 12;\\nconst BASE_OUTER_RADIUS = 0.2;\\nconst INNER_OUTER_RATIO = 0.17 / 0.2;\\n// Screen-space diameter (in CSS pixels) used for both hover and target\\n// rings when the scene isn't walk-sized. Walk-sized scenes render\\n// world-space (BASE_OUTER_RADIUS) so the ring orients to the surface and\\n// reads as a physical footprint; smaller scenes (or no collision) fall\\n// back to a fixed pixel size, which keeps the ring legible when 0.2 world\\n// units would eat too much of the scene. Selection happens in\\n// screenPixelsForRing(), keyed on state.walkAllowed.\\nconst SCREEN_OUTER_PIXELS = 48;\\nconst BEZIER_K = 1 / 6;\\nconst NORMAL_SMOOTH_FACTOR = 0.25;\\nconst NORMAL_SNAP_ANGLE = Math.PI / 4;\\nconst NORMAL_EPSILON$1 = 1e-6;\\nconst createNormalSnapDirections = () => {\\n    const result = [];\\n    for (let pitchStep = -2; pitchStep <= 2; pitchStep++) {\\n        const pitch = pitchStep * NORMAL_SNAP_ANGLE;\\n        const cp = Math.cos(pitch);\\n        const sy = Math.sin(pitch);\\n        if (Math.abs(cp) <= NORMAL_EPSILON$1) {\\n            result.push(new Vec3(0, sy > 0 ? 1 : -1, 0));\\n            continue;\\n        }\\n        for (let yawStep = 0; yawStep < 8; yawStep++) {\\n            const yaw = yawStep * NORMAL_SNAP_ANGLE;\\n            result.push(new Vec3(Math.cos(yaw) * cp, sy, Math.sin(yaw) * cp));\\n        }\\n    }\\n    return result;\\n};\\nconst NORMAL_SNAP_DIRECTIONS = createNormalSnapDirections();\\nconst snapNormal = (nx, ny, nz, out) => {\\n    const len = Math.sqrt(nx * nx + ny * ny + nz * nz);\\n    if (len <= NORMAL_EPSILON$1) {\\n        return out.set(0, 1, 0);\\n    }\\n    const invLen = 1 / len;\\n    const x = nx * invLen;\\n    const y = ny * invLen;\\n    const z = nz * invLen;\\n    let best = NORMAL_SNAP_DIRECTIONS[0];\\n    let bestDot = -Infinity;\\n    for (let i = 0; i < NORMAL_SNAP_DIRECTIONS.length; i++) {\\n        const candidate = NORMAL_SNAP_DIRECTIONS[i];\\n        const dot = candidate.x * x + candidate.y * y + candidate.z * z;\\n        if (dot > bestDot) {\\n            bestDot = dot;\\n            best = candidate;\\n        }\\n    }\\n    return out.copy(best);\\n};\\nconst tmpV = new Vec3();\\nconst tmpScreen = new Vec3();\\nconst tangent = new Vec3();\\nconst bitangent = new Vec3();\\nconst worldPt = new Vec3();\\nconst up = new Vec3(0, 1, 0);\\nconst right = new Vec3(1, 0, 0);\\n// Compute the world-space radius such that a circle at `pos` projects to a\\n// ring of `pixelDiameter` on screen. Used by the no-collision sizing path\\n// (see screenPixelsForRing) to keep a constant on-screen diameter\\n// regardless of camera distance.\\nconst worldRadiusForPixels = (camera, canvasHeight, pos, pixelDiameter) => {\\n    const cam = camera.camera;\\n    if (cam.projection === PROJECTION_ORTHOGRAPHIC) {\\n        return pixelDiameter * cam.orthoHeight / canvasHeight;\\n    }\\n    const camPos = camera.getPosition();\\n    const dx = pos.x - camPos.x;\\n    const dy = pos.y - camPos.y;\\n    const dz = pos.z - camPos.z;\\n    const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);\\n    const halfFovTan = Math.tan(cam.fov * Math.PI / 360);\\n    return pixelDiameter * distance * halfFovTan / canvasHeight;\\n};\\nconst buildBezierRing = (sx, sy) => {\\n    const n = sx.length;\\n    let p = `M${sx[0].toFixed(1)},${sy[0].toFixed(1)}`;\\n    for (let i = 0; i < n; i++) {\\n        const i0 = (i - 1 + n) % n;\\n        const i1 = i;\\n        const i2 = (i + 1) % n;\\n        const i3 = (i + 2) % n;\\n        const cp1x = sx[i1] + (sx[i2] - sx[i0]) * BEZIER_K;\\n        const cp1y = sy[i1] + (sy[i2] - sy[i0]) * BEZIER_K;\\n        const cp2x = sx[i2] - (sx[i3] - sx[i1]) * BEZIER_K;\\n        const cp2y = sy[i2] - (sy[i3] - sy[i1]) * BEZIER_K;\\n        p += ` C${cp1x.toFixed(1)},${cp1y.toFixed(1)} ${cp2x.toFixed(1)},${cp2y.toFixed(1)} ${sx[i2].toFixed(1)},${sy[i2].toFixed(1)}`;\\n    }\\n    return `${p} Z`;\\n};\\nclass CursorRing {\\n    path;\\n    svg;\\n    canvas;\\n    camera;\\n    smoothing;\\n    smoothNx = 0;\\n    smoothNy = 1;\\n    smoothNz = 0;\\n    hasSmoothedNormal = false;\\n    outerX = new Float64Array(NUM_SAMPLES);\\n    outerY = new Float64Array(NUM_SAMPLES);\\n    innerX = new Float64Array(NUM_SAMPLES);\\n    innerY = new Float64Array(NUM_SAMPLES);\\n    constructor(svg, canvas, camera, smoothing) {\\n        this.svg = svg;\\n        this.canvas = canvas;\\n        this.camera = camera;\\n        this.smoothing = smoothing;\\n        this.path = document.createElementNS(SVGNS, 'path');\\n        this.path.setAttribute('fill', 'white');\\n        this.path.setAttribute('fill-opacity', '0.6');\\n        this.path.setAttribute('fill-rule', 'evenodd');\\n        this.path.setAttribute('stroke', 'none');\\n        this.path.style.display = 'none';\\n        svg.appendChild(this.path);\\n    }\\n    projectCircle(px, py, pz, nx, ny, nz, radius, outX, outY) {\\n        const normal = tmpV.set(nx, ny, nz);\\n        if (Math.abs(normal.y) < 0.99) {\\n            tangent.cross(normal, up).normalize();\\n        }\\n        else {\\n            tangent.cross(normal, right).normalize();\\n        }\\n        bitangent.cross(normal, tangent);\\n        const cam = this.camera.camera;\\n        const angleStep = (2 * Math.PI) / NUM_SAMPLES;\\n        for (let i = 0; i < NUM_SAMPLES; i++) {\\n            const theta = i * angleStep;\\n            const ct = Math.cos(theta);\\n            const st = Math.sin(theta);\\n            const tx = ct * tangent.x + st * bitangent.x;\\n            const ty = ct * tangent.y + st * bitangent.y;\\n            const tz = ct * tangent.z + st * bitangent.z;\\n            worldPt.set(px + tx * radius, py + ty * radius, pz + tz * radius);\\n            cam.worldToScreen(worldPt, tmpScreen);\\n            outX[i] = tmpScreen.x;\\n            outY[i] = tmpScreen.y;\\n        }\\n    }\\n    // screenPixels: null → world-space ring (fixed world radius, shrinks\\n    // with distance); number → constant on-screen diameter in CSS pixels.\\n    render(pos, normal, screenPixels) {\\n        snapNormal(normal.x, normal.y, normal.z, tmpV);\\n        let nx = tmpV.x;\\n        let ny = tmpV.y;\\n        let nz = tmpV.z;\\n        if (this.smoothing) {\\n            if (this.hasSmoothedNormal) {\\n                const t = NORMAL_SMOOTH_FACTOR;\\n                nx = this.smoothNx + (nx - this.smoothNx) * t;\\n                ny = this.smoothNy + (ny - this.smoothNy) * t;\\n                nz = this.smoothNz + (nz - this.smoothNz) * t;\\n                const len = Math.sqrt(nx * nx + ny * ny + nz * nz);\\n                if (len > 1e-6) {\\n                    const invLen = 1.0 / len;\\n                    nx *= invLen;\\n                    ny *= invLen;\\n                    nz *= invLen;\\n                }\\n            }\\n            this.smoothNx = nx;\\n            this.smoothNy = ny;\\n            this.smoothNz = nz;\\n            this.hasSmoothedNormal = true;\\n        }\\n        const outerRadius = screenPixels !== null ?\\n            worldRadiusForPixels(this.camera, this.canvas.clientHeight || 1, pos, screenPixels) :\\n            BASE_OUTER_RADIUS;\\n        const innerRadius = outerRadius * INNER_OUTER_RATIO;\\n        this.projectCircle(pos.x, pos.y, pos.z, nx, ny, nz, outerRadius, this.outerX, this.outerY);\\n        this.projectCircle(pos.x, pos.y, pos.z, nx, ny, nz, innerRadius, this.innerX, this.innerY);\\n        this.path.setAttribute('d', `${buildBezierRing(this.outerX, this.outerY)} ${buildBezierRing(this.innerX, this.innerY)}`);\\n        this.path.style.display = '';\\n        this.svg.style.display = '';\\n    }\\n    hide() {\\n        this.path.style.display = 'none';\\n        this.hasSmoothedNormal = false;\\n    }\\n}\\nclass NavCursor {\\n    svg;\\n    hoverRing;\\n    targetRing;\\n    camera;\\n    collision;\\n    canvas;\\n    state;\\n    app;\\n    onPrerender;\\n    // True when the hover ring should track the pointer. Only walk mode\\n    // (with mouse navigation, not gaming controls) shows the hover ring;\\n    // fly/orbit only show the target ring on click.\\n    hoverActive = false;\\n    navigating = false;\\n    targetPos = null;\\n    targetNormal = null;\\n    targetMode = null;\\n    onPointerMove;\\n    onPointerLeave;\\n    collisionTarget = {\\n        position: new Vec3(),\\n        normal: new Vec3()\\n    };\\n    constructor(app, camera, collision, events, state) {\\n        this.camera = camera;\\n        this.collision = collision;\\n        this.canvas = app.graphicsDevice.canvas;\\n        this.state = state;\\n        this.app = app;\\n        this.svg = document.createElementNS(SVGNS, 'svg');\\n        this.svg.style.cssText = 'position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;overflow:visible;z-index:1';\\n        this.canvas.parentElement.appendChild(this.svg);\\n        this.hoverRing = new CursorRing(this.svg, this.canvas, camera, true);\\n        this.targetRing = new CursorRing(this.svg, this.canvas, camera, false);\\n        this.svg.style.display = 'none';\\n        this.onPointerMove = (e) => {\\n            if (e.pointerType === 'touch' || e.buttons) {\\n                this.hoverRing.hide();\\n                return;\\n            }\\n            this.updateCursor(e.offsetX, e.offsetY);\\n        };\\n        this.onPointerLeave = () => {\\n            this.hoverRing.hide();\\n        };\\n        this.canvas.addEventListener('pointermove', this.onPointerMove);\\n        this.canvas.addEventListener('pointerleave', this.onPointerLeave);\\n        const updateActive = () => {\\n            // Hover ring only in walk mode with mouse navigation. Gaming\\n            // controls use pointer-lock and don't need a hover preview.\\n            this.hoverActive = state.cameraMode === 'walk' && !state.gamingControls;\\n            this.hoverRing.hide();\\n            if (this.targetMode && this.targetMode !== state.cameraMode) {\\n                this.navigating = false;\\n                this.clearTarget();\\n            }\\n        };\\n        events.on('cameraMode:changed', updateActive);\\n        events.on('inputMode:changed', updateActive);\\n        events.on('gamingControls:changed', updateActive);\\n        events.on('navigateTo', () => {\\n            this.navigating = true;\\n            this.hoverRing.hide();\\n        });\\n        events.on('navigateCancel', () => {\\n            this.navigating = false;\\n            this.clearTarget();\\n        });\\n        events.on('navigateComplete', () => {\\n            this.navigating = false;\\n            this.clearTarget();\\n        });\\n        events.on('navTarget:set', (pos, normal) => {\\n            const mode = state.cameraMode === 'walk' || state.cameraMode === 'fly' ?\\n                state.cameraMode : 'walk';\\n            this.setTarget(pos, normal, mode);\\n        });\\n        events.on('navTarget:clear', () => {\\n            this.clearTarget();\\n        });\\n        events.on('orbitTarget:set', (pos, normal) => {\\n            this.navigating = false;\\n            this.setTarget(pos, normal, 'orbit');\\n        });\\n        events.on('orbitTarget:clear', () => {\\n            if (this.targetMode === 'orbit') {\\n                this.clearTarget();\\n            }\\n        });\\n        this.onPrerender = () => {\\n            this.updateTarget();\\n        };\\n        app.on('prerender', this.onPrerender);\\n        updateActive();\\n    }\\n    // Ring sizing is per-scene: walk-sized scenes (collision present and\\n    // bbox large enough — same predicate as walk mode) get world-space\\n    // rings, which read as physical footprints on the surface with visible\\n    // orientation. Smaller scenes or scenes without collision use a fixed\\n    // screen-pixel ring — 0.2 world units would dominate a small scene,\\n    // and the pick already falls back to splat depth without collision.\\n    screenPixelsForRing() {\\n        return this.state.walkAllowed ? null : SCREEN_OUTER_PIXELS;\\n    }\\n    setTarget(pos, normal, mode) {\\n        this.targetPos = pos.clone();\\n        this.targetNormal = normal.clone();\\n        this.targetMode = mode;\\n        this.hoverRing.hide();\\n        this.targetRing.hide();\\n    }\\n    clearTarget() {\\n        this.targetPos = null;\\n        this.targetNormal = null;\\n        this.targetMode = null;\\n        this.targetRing.hide();\\n    }\\n    pickCollision(offsetX, offsetY) {\\n        if (!this.collision) {\\n            return null;\\n        }\\n        const { camera, collision } = this;\\n        const cameraPos = camera.getPosition();\\n        camera.camera.screenToWorld(offsetX, offsetY, 1.0, tmpV);\\n        tmpV.sub(cameraPos).normalize();\\n        const hit = collision.queryRay(cameraPos.x, cameraPos.y, cameraPos.z, tmpV.x, tmpV.y, tmpV.z, camera.camera.farClip);\\n        if (!hit) {\\n            return null;\\n        }\\n        const sn = collision.querySurfaceNormal(hit.x, hit.y, hit.z, tmpV.x, tmpV.y, tmpV.z);\\n        this.collisionTarget.position.set(hit.x, hit.y, hit.z);\\n        this.collisionTarget.normal.set(sn.nx, sn.ny, sn.nz);\\n        return this.collisionTarget;\\n    }\\n    updateCursor(offsetX, offsetY) {\\n        if (!this.hoverActive || this.navigating) {\\n            this.hoverRing.hide();\\n            return;\\n        }\\n        const target = this.pickCollision(offsetX, offsetY);\\n        if (!target) {\\n            this.hoverRing.hide();\\n            return;\\n        }\\n        this.hoverRing.render(target.position, target.normal, this.screenPixelsForRing());\\n    }\\n    updateTarget() {\\n        if (!this.targetPos || !this.targetNormal || !this.targetMode) {\\n            return;\\n        }\\n        const camPos = this.camera.getPosition();\\n        const dist = camPos.distance(this.targetPos);\\n        if (this.targetMode !== 'orbit' && dist < 2.0) {\\n            this.targetRing.hide();\\n            return;\\n        }\\n        this.targetRing.render(this.targetPos, this.targetNormal, this.screenPixelsForRing());\\n    }\\n    destroy() {\\n        this.app.off('prerender', this.onPrerender);\\n        this.canvas.removeEventListener('pointermove', this.onPointerMove);\\n        this.canvas.removeEventListener('pointerleave', this.onPointerLeave);\\n        this.svg.remove();\\n    }\\n}\\n\\n/**\\n * World picking for splat scenes.\\n *\\n * Uses a custom `pickPS` / `gsplatPS` patch plus `RGBA16F` alpha-weighted depth accumulation,\\n * because the stock pick pass encodes splat IDs / last-fragment depth rather than expected depth.\\n */\\n// Override global picking to pack alpha-weighted splat depth instead of meshInstance id.\\nconst pickDepthGlsl = /* glsl */ `\\nvec4 encodePickOutput(uint id) {\\n    const vec4 inv = vec4(1.0 / 255.0);\\n    const uvec4 shifts = uvec4(16, 8, 0, 24);\\n    uvec4 col = (uvec4(id) >> shifts) & uvec4(0xff);\\n    return vec4(col) * inv;\\n}\\n\\n#ifdef GSPLAT_PICK_DEPTH\\n    #ifndef CAMERAPLANES\\n        #define CAMERAPLANES\\n        uniform vec4 camera_params; // x: 1/far, y: far, z: near, w: isOrtho\\n    #endif\\n\\n    vec4 getPickOutput() {\\n        float normalizedDepth;\\n        if (camera_params.w > 0.5) {\\n            normalizedDepth = gl_FragCoord.z;\\n        } else {\\n            float linearDepth = 1.0 / gl_FragCoord.w;\\n            normalizedDepth = (linearDepth - camera_params.z) / (camera_params.y - camera_params.z);\\n        }\\n\\n        return vec4(gaussianColor.a * normalizedDepth, 0.0, 0.0, gaussianColor.a);\\n    }\\n#else\\n    #ifndef PICK_CUSTOM_ID\\n        uniform uint meshInstanceId;\\n\\n        vec4 getPickOutput() {\\n            return encodePickOutput(meshInstanceId);\\n        }\\n    #endif\\n#endif\\n\\n#ifdef DEPTH_PICK_PASS\\n    #include \\\"floatAsUintPS\\\"\\n    #ifndef CAMERAPLANES\\n        #define CAMERAPLANES\\n        uniform vec4 camera_params; // x: 1/far, y: far, z: near, w: isOrtho\\n    #endif\\n\\n    vec4 getPickDepth() {\\n        float linearDepth;\\n        if (camera_params.w > 0.5) {\\n            linearDepth = gl_FragCoord.z;\\n        } else {\\n            float viewDist = 1.0 / gl_FragCoord.w;\\n            linearDepth = (viewDist - camera_params.z) / (camera_params.y - camera_params.z);\\n        }\\n        return float2uint(linearDepth);\\n    }\\n#endif\\n`;\\nconst pickDepthWgsl = /* wgsl */ `\\nfn encodePickOutput(id: u32) -> vec4f {\\n    let inv: vec4f = vec4f(1.0 / 255.0);\\n    let shifts: vec4u = vec4u(16u, 8u, 0u, 24u);\\n    let col: vec4u = (vec4u(id) >> shifts) & vec4u(0xffu);\\n    return vec4f(col) * inv;\\n}\\n\\n#ifdef GSPLAT_PICK_DEPTH\\n    #ifndef CAMERAPLANES\\n        #define CAMERAPLANES\\n        uniform camera_params: vec4f; // x: 1/far, y: far, z: near, w: isOrtho\\n    #endif\\n\\n    fn getPickOutput() -> vec4f {\\n        var normalizedDepth: f32;\\n        if (uniform.camera_params.w > 0.5) {\\n            normalizedDepth = pcPosition.z;\\n        } else {\\n            let linearDepth = 1.0 / pcPosition.w;\\n            normalizedDepth = (linearDepth - uniform.camera_params.z) / (uniform.camera_params.y - uniform.camera_params.z);\\n        }\\n\\n        let a = f32(gaussianColor.a);\\n        return vec4f(a * normalizedDepth, 0.0, 0.0, a);\\n    }\\n#else\\n    #ifndef PICK_CUSTOM_ID\\n        uniform meshInstanceId: u32;\\n\\n        fn getPickOutput() -> vec4f {\\n            return encodePickOutput(uniform.meshInstanceId);\\n        }\\n    #endif\\n#endif\\n\\n#ifdef DEPTH_PICK_PASS\\n    #include \\\"floatAsUintPS\\\"\\n    #ifndef CAMERAPLANES\\n        #define CAMERAPLANES\\n        uniform camera_params: vec4f; // x: 1/far, y: far, z: near, w: isOrtho\\n    #endif\\n\\n    fn getPickDepth() -> vec4f {\\n        var linearDepth: f32;\\n        if (uniform.camera_params.w > 0.5) {\\n            linearDepth = pcPosition.z;\\n        } else {\\n            let viewDist = 1.0 / pcPosition.w;\\n            linearDepth = (viewDist - uniform.camera_params.z) / (uniform.camera_params.y - uniform.camera_params.z);\\n        }\\n        return float2uint(linearDepth);\\n    }\\n#endif\\n`;\\nconst pickPassChunkInjected = [\\n    '#ifdef PICK_PASS',\\n    '    #define GSPLAT_PICK_DEPTH',\\n    '    #include \\\"pickPS\\\"',\\n    '#endif'\\n].join('\\\\n');\\nconst safeChunkReplace = (s, find, repl) => {\\n    const out = s.replace(find, repl);\\n    if (out === s) {\\n        throw new Error('picker: engine gsplat/pick chunk patch failed (engine version mismatch?)');\\n    }\\n    return out;\\n};\\nconst patchGsplatPickGlsl = (chunk) => {\\n    return safeChunkReplace(safeChunkReplace(chunk, /#ifdef PICK_PASS\\\\s*#include \\\"pickPS\\\"\\\\s*#endif/, pickPassChunkInjected), 'pcFragColor0 = encodePickOutput(vPickId);', 'pcFragColor0 = getPickOutput();');\\n};\\nconst patchGsplatPickWgsl = (chunk) => {\\n    return safeChunkReplace(safeChunkReplace(chunk, /#ifdef PICK_PASS\\\\s*#include \\\"pickPS\\\"\\\\s*#endif/, pickPassChunkInjected), 'output.color = encodePickOutput(vPickId);', 'output.color = getPickOutput();');\\n};\\n/** Per-device original chunk strings + refcount so we can restore after the last Picker releases. */\\nconst pickerShaderPatchState = new WeakMap();\\nconst vec4 = new Vec4();\\nconst viewProjMat = new Mat4();\\nconst clearColor = new Color(0, 0, 0, 1);\\nconst NORMAL_EPSILON = 1e-12;\\nconst NORMAL_DEGENERATE_EPSILON = 1e-20;\\n// Sampling for the surface-normal estimator runs on a circular footprint of\\n// fixed *world* radius, projected to pixels at the picked-point's depth.\\n// Keeping the world area constant means adjacent cursor positions sample\\n// almost the same world cluster, which stabilises the plane fit. The pixel\\n// radius is clamped so distant picks still get enough samples and very-close\\n// picks don't blow the block read.\\nconst NORMAL_SAMPLE_WORLD_RADIUS = 0.2;\\nconst NORMAL_SAMPLE_MIN_PX = 6;\\nconst NORMAL_SAMPLE_MAX_PX = 48;\\nconst NORMAL_RING_FRACTIONS = [0.3, 0.55, 0.8, 1.0];\\nconst NORMAL_OUTLIER_THRESHOLD = 2.5;\\nconst NORMAL_SAMPLE_DIRECTIONS = [\\n    [1, 0],\\n    [1, 1],\\n    [0, 1],\\n    [-1, 1],\\n    [-1, 0],\\n    [-1, -1],\\n    [0, -1],\\n    [1, -1]\\n];\\n// Shared buffer for half-to-float conversion\\nconst float32 = new Float32Array(1);\\nconst uint32 = new Uint32Array(float32.buffer);\\n// Convert 16-bit half-float to 32-bit float using bit manipulation.\\nconst half2Float = (h) => {\\n    const sign = (h & 0x8000) << 16;\\n    const exponent = (h & 0x7C00) >> 10;\\n    const mantissa = h & 0x03FF;\\n    if (exponent === 0) {\\n        if (mantissa === 0) {\\n            uint32[0] = sign;\\n        }\\n        else {\\n            let e = -1;\\n            let m = mantissa;\\n            do {\\n                e++;\\n                m <<= 1;\\n            } while ((m & 0x0400) === 0);\\n            uint32[0] = sign | ((127 - 15 - e) << 23) | ((m & 0x03FF) << 13);\\n        }\\n    }\\n    else if (exponent === 31) {\\n        uint32[0] = sign | 0x7F800000 | (mantissa << 13);\\n    }\\n    else {\\n        uint32[0] = sign | ((exponent + 127 - 15) << 23) | (mantissa << 13);\\n    }\\n    return float32[0];\\n};\\nconst registerPickerShaderPatches = (app) => {\\n    const device = app.graphicsDevice;\\n    const existing = pickerShaderPatchState.get(device);\\n    if (existing) {\\n        existing.refCount++;\\n        return;\\n    }\\n    const glslChunks = ShaderChunks.get(device, 'glsl');\\n    const wgslChunks = ShaderChunks.get(device, 'wgsl');\\n    const glslPickPS = glslChunks.get('pickPS');\\n    const glslGsplatPS = glslChunks.get('gsplatPS');\\n    const wgslPickPS = wgslChunks.get('pickPS');\\n    const wgslGsplatPS = wgslChunks.get('gsplatPS');\\n    // Patch strings before mutating ShaderChunks so engine mismatches leave globals untouched.\\n    const patchedGlslGsplatPS = patchGsplatPickGlsl(glslGsplatPS);\\n    const patchedWgslGsplatPS = patchGsplatPickWgsl(wgslGsplatPS);\\n    const state = {\\n        glslPickPS,\\n        glslGsplatPS,\\n        wgslPickPS,\\n        wgslGsplatPS,\\n        refCount: 1\\n    };\\n    pickerShaderPatchState.set(device, state);\\n    glslChunks.set('pickPS', pickDepthGlsl);\\n    wgslChunks.set('pickPS', pickDepthWgsl);\\n    glslChunks.set('gsplatPS', patchedGlslGsplatPS);\\n    wgslChunks.set('gsplatPS', patchedWgslGsplatPS);\\n};\\nconst unregisterPickerShaderPatches = (app) => {\\n    const device = app.graphicsDevice;\\n    const state = pickerShaderPatchState.get(device);\\n    if (!state) {\\n        return;\\n    }\\n    state.refCount--;\\n    if (state.refCount > 0) {\\n        return;\\n    }\\n    const glslChunks = ShaderChunks.get(device, 'glsl');\\n    const wgslChunks = ShaderChunks.get(device, 'wgsl');\\n    glslChunks.set('pickPS', state.glslPickPS);\\n    glslChunks.set('gsplatPS', state.glslGsplatPS);\\n    wgslChunks.set('pickPS', state.wgslPickPS);\\n    wgslChunks.set('gsplatPS', state.wgslGsplatPS);\\n    pickerShaderPatchState.delete(device);\\n};\\nconst createPickCameraSnapshot = () => ({\\n    position: new Vec3(),\\n    viewMatrix: new Mat4(),\\n    projectionMatrix: new Mat4(),\\n    nearClip: 0,\\n    farClip: 0,\\n    projection: 0\\n});\\nconst captureCameraSnapshot = (camera, out) => {\\n    const cam = camera.camera;\\n    out.position.copy(camera.getPosition());\\n    out.viewMatrix.copy(cam.viewMatrix);\\n    out.projectionMatrix.copy(cam.projectionMatrix);\\n    out.nearClip = cam.nearClip;\\n    out.farClip = cam.farClip;\\n    out.projection = cam.projection;\\n};\\nconst getWorldPoint = (camera, x, y, width, height, normalizedDepth, out) => {\\n    if (!Number.isFinite(normalizedDepth) || normalizedDepth < 0 || normalizedDepth > 1) {\\n        return null;\\n    }\\n    const { farClip: far, nearClip: near } = camera;\\n    const ndcDepth = camera.projection === PROJECTION_ORTHOGRAPHIC ?\\n        normalizedDepth :\\n        far * normalizedDepth / (normalizedDepth * (far - near) + near);\\n    viewProjMat.mul2(camera.projectionMatrix, camera.viewMatrix).invert();\\n    vec4.set(x / width * 2 - 1, (1 - y / height) * 2 - 1, ndcDepth * 2 - 1, 1);\\n    viewProjMat.transformVec4(vec4, vec4);\\n    if (!Number.isFinite(vec4.w) || Math.abs(vec4.w) < 1e-8) {\\n        return null;\\n    }\\n    vec4.mulScalar(1 / vec4.w);\\n    if (!Number.isFinite(vec4.x) || !Number.isFinite(vec4.y) || !Number.isFinite(vec4.z)) {\\n        return null;\\n    }\\n    return (out ?? new Vec3()).set(vec4.x, vec4.y, vec4.z);\\n};\\nconst setCameraFacingNormal = (cameraPosition, position, normal) => {\\n    normal.sub2(cameraPosition, position);\\n    const len = normal.length();\\n    if (len > 1e-6) {\\n        normal.mulScalar(1 / len);\\n    }\\n    else {\\n        normal.set(0, 1, 0);\\n    }\\n    return normal;\\n};\\n// Project a world-space radius around `pos` to its on-screen pixel radius for\\n// the given camera. Uses the projection matrix's [1][1] entry (= 1/tan(fov/2)\\n// for perspective, = 1/orthoHeight for orthographic) so we don't need fov or\\n// orthoHeight on the snapshot.\\nconst worldRadiusToPixelRadius = (cam, pos, canvasHeight, worldRadius) => {\\n    const projY = cam.projectionMatrix.data[5];\\n    if (cam.projection === PROJECTION_ORTHOGRAPHIC) {\\n        return worldRadius * projY * canvasHeight / 2;\\n    }\\n    const dx = pos.x - cam.position.x;\\n    const dy = pos.y - cam.position.y;\\n    const dz = pos.z - cam.position.z;\\n    const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);\\n    if (distance < 1e-6)\\n        return Infinity;\\n    return worldRadius * projY * canvasHeight / (2 * distance);\\n};\\n// Single least-squares plane fit through a cluster of 3D points. The normal\\n// is the eigenvector of the smallest eigenvalue of the points' 3x3 covariance\\n// matrix, computed in closed form (analytic eigendecomposition for 3x3\\n// symmetric, Smith 1961). Returns null on degenerate input.\\nconst fitPlaneOnce = (points) => {\\n    const n = points.length;\\n    if (n < 3)\\n        return null;\\n    let cx = 0, cy = 0, cz = 0;\\n    for (let i = 0; i < n; i++) {\\n        cx += points[i].x;\\n        cy += points[i].y;\\n        cz += points[i].z;\\n    }\\n    cx /= n;\\n    cy /= n;\\n    cz /= n;\\n    let cxx = 0, cxy = 0, cxz = 0, cyy = 0, cyz = 0, czz = 0;\\n    for (let i = 0; i < n; i++) {\\n        const dx = points[i].x - cx;\\n        const dy = points[i].y - cy;\\n        const dz = points[i].z - cz;\\n        cxx += dx * dx;\\n        cxy += dx * dy;\\n        cxz += dx * dz;\\n        cyy += dy * dy;\\n        cyz += dy * dz;\\n        czz += dz * dz;\\n    }\\n    const q = (cxx + cyy + czz) / 3;\\n    const a = cxx - q, b = cyy - q, c = czz - q;\\n    const p2 = a * a + b * b + c * c + 2 * (cxy * cxy + cxz * cxz + cyz * cyz);\\n    if (p2 < NORMAL_DEGENERATE_EPSILON)\\n        return null;\\n    const p = Math.sqrt(p2 / 6);\\n    const inv = 1 / p;\\n    const Bxx = a * inv, Bxy = cxy * inv, Bxz = cxz * inv;\\n    const Byy = b * inv, Byz = cyz * inv, Bzz = c * inv;\\n    const detB = Bxx * (Byy * Bzz - Byz * Byz) -\\n        Bxy * (Bxy * Bzz - Byz * Bxz) +\\n        Bxz * (Bxy * Byz - Byy * Bxz);\\n    const r = Math.max(-1, Math.min(1, detB / 2));\\n    const phi = Math.acos(r) / 3;\\n    const lambdaMin = q + 2 * p * Math.cos(phi + 2 * Math.PI / 3);\\n    const Mxx = cxx - lambdaMin, Myy = cyy - lambdaMin, Mzz = czz - lambdaMin;\\n    const v1x = cxy * cyz - cxz * Myy;\\n    const v1y = cxz * cxy - Mxx * cyz;\\n    const v1z = Mxx * Myy - cxy * cxy;\\n    const v2x = cxy * Mzz - cxz * cyz;\\n    const v2y = cxz * cxz - Mxx * Mzz;\\n    const v2z = Mxx * cyz - cxy * cxz;\\n    const v3x = Myy * Mzz - cyz * cyz;\\n    const v3y = cyz * cxz - cxy * Mzz;\\n    const v3z = cxy * cyz - Myy * cxz;\\n    const l1 = v1x * v1x + v1y * v1y + v1z * v1z;\\n    const l2 = v2x * v2x + v2y * v2y + v2z * v2z;\\n    const l3 = v3x * v3x + v3y * v3y + v3z * v3z;\\n    let vx, vy, vz, lSq;\\n    if (l1 >= l2 && l1 >= l3) {\\n        vx = v1x;\\n        vy = v1y;\\n        vz = v1z;\\n        lSq = l1;\\n    }\\n    else if (l2 >= l3) {\\n        vx = v2x;\\n        vy = v2y;\\n        vz = v2z;\\n        lSq = l2;\\n    }\\n    else {\\n        vx = v3x;\\n        vy = v3y;\\n        vz = v3z;\\n        lSq = l3;\\n    }\\n    if (lSq < NORMAL_EPSILON)\\n        return null;\\n    const invLen = 1 / Math.sqrt(lSq);\\n    return { cx, cy, cz, vx: vx * invLen, vy: vy * invLen, vz: vz * invLen };\\n};\\n// Two-pass plane fit: first pass on all points, then drop points whose\\n// distance from the fitted plane exceeds NORMAL_OUTLIER_THRESHOLD * the mean\\n// residual, refit on the inliers. Sign-flips the result toward toCamera so\\n// the cursor's tangent basis stays consistent. Returns false on degenerate\\n// input (fewer than 3 points, collinear/coincident samples).\\nconst fitPlaneNormal = (points, toCamera, outNormal) => {\\n    const first = fitPlaneOnce(points);\\n    if (!first)\\n        return false;\\n    let residualSum = 0;\\n    for (let i = 0; i < points.length; i++) {\\n        const dx = points[i].x - first.cx;\\n        const dy = points[i].y - first.cy;\\n        const dz = points[i].z - first.cz;\\n        residualSum += Math.abs(dx * first.vx + dy * first.vy + dz * first.vz);\\n    }\\n    const threshold = (residualSum / points.length) * NORMAL_OUTLIER_THRESHOLD;\\n    const inliers = [];\\n    for (let i = 0; i < points.length; i++) {\\n        const dx = points[i].x - first.cx;\\n        const dy = points[i].y - first.cy;\\n        const dz = points[i].z - first.cz;\\n        if (Math.abs(dx * first.vx + dy * first.vy + dz * first.vz) <= threshold) {\\n            inliers.push(points[i]);\\n        }\\n    }\\n    let result = first;\\n    if (inliers.length >= 3 && inliers.length < points.length) {\\n        const refined = fitPlaneOnce(inliers);\\n        if (refined)\\n            result = refined;\\n    }\\n    let { vx, vy, vz } = result;\\n    if (vx * toCamera.x + vy * toCamera.y + vz * toCamera.z < 0) {\\n        vx = -vx;\\n        vy = -vy;\\n        vz = -vz;\\n    }\\n    outNormal.set(vx, vy, vz);\\n    return true;\\n};\\nclass Picker {\\n    pick;\\n    pickSurface;\\n    release;\\n    constructor(app, camera) {\\n        const { graphicsDevice } = app;\\n        let accumBuffer;\\n        let accumTarget;\\n        let accumPass;\\n        let chunksPatched = false;\\n        let pickQueue = Promise.resolve();\\n        let cacheValid = false;\\n        let cacheWidth = 0;\\n        let cacheHeight = 0;\\n        const cacheCamera = createPickCameraSnapshot();\\n        const initRasterAccum = (width, height) => {\\n            accumBuffer = new Texture(graphicsDevice, {\\n                format: PIXELFORMAT_RGBA16F,\\n                width,\\n                height,\\n                mipmaps: false,\\n                minFilter: FILTER_NEAREST,\\n                magFilter: FILTER_NEAREST,\\n                addressU: ADDRESS_CLAMP_TO_EDGE,\\n                addressV: ADDRESS_CLAMP_TO_EDGE,\\n                name: 'picker-accum'\\n            });\\n            accumTarget = new RenderTarget({\\n                colorBuffer: accumBuffer,\\n                depth: false // not needed — gaussians are rendered back to front\\n            });\\n            accumPass = new RenderPassPicker(graphicsDevice, app.renderer);\\n            // RGB: additive depth accumulation. Alpha: multiplicative transmittance.\\n            accumPass.blendState = new BlendState(true, BLENDEQUATION_ADD, BLENDMODE_ONE, BLENDMODE_ONE_MINUS_SRC_ALPHA, BLENDEQUATION_ADD, BLENDMODE_ZERO, BLENDMODE_ONE_MINUS_SRC_ALPHA);\\n        };\\n        const readTexture = (texture, x, y, target) => {\\n            const texY = graphicsDevice.isWebGL2 ? target.height - y - 1 : y;\\n            return texture.read(x, texY, 1, 1, {\\n                renderTarget: target,\\n                immediate: true\\n            });\\n        };\\n        const updateCache = (width, height) => {\\n            captureCameraSnapshot(camera, cacheCamera);\\n            cacheWidth = width;\\n            cacheHeight = height;\\n        };\\n        const cameraMatches = (width, height) => {\\n            const cam = camera.camera;\\n            return cacheValid &&\\n                cacheWidth === width &&\\n                cacheHeight === height &&\\n                cacheCamera.viewMatrix.equals(cam.viewMatrix) &&\\n                cacheCamera.projectionMatrix.equals(cam.projectionMatrix) &&\\n                cacheCamera.nearClip === cam.nearClip &&\\n                cacheCamera.farClip === cam.farClip &&\\n                cacheCamera.projection === cam.projection;\\n        };\\n        const getCacheCameraSnapshot = () => {\\n            const snapshot = createPickCameraSnapshot();\\n            snapshot.position.copy(cacheCamera.position);\\n            snapshot.viewMatrix.copy(cacheCamera.viewMatrix);\\n            snapshot.projectionMatrix.copy(cacheCamera.projectionMatrix);\\n            snapshot.nearClip = cacheCamera.nearClip;\\n            snapshot.farClip = cacheCamera.farClip;\\n            snapshot.projection = cacheCamera.projection;\\n            return snapshot;\\n        };\\n        const readRasterBlock = async (blockX, blockY, blockWidth, blockHeight, viewportWidth, viewportHeight, pickCamera) => {\\n            const texY = graphicsDevice.isWebGL2 ? accumTarget.height - blockY - blockHeight : blockY;\\n            const pixels = await accumBuffer.read(blockX, texY, blockWidth, blockHeight, {\\n                renderTarget: accumTarget,\\n                immediate: true\\n            });\\n            return (x, y) => {\\n                const localX = x - blockX;\\n                const localY = y - blockY;\\n                if (localX < 0 || localX >= blockWidth || localY < 0 || localY >= blockHeight) {\\n                    return null;\\n                }\\n                const row = graphicsDevice.isWebGL2 ? blockHeight - localY - 1 : localY;\\n                const index = (row * blockWidth + localX) * 4;\\n                const r = half2Float(pixels[index]);\\n                const transmittance = half2Float(pixels[index + 3]);\\n                const alpha = 1 - transmittance;\\n                if (!Number.isFinite(r) || !Number.isFinite(alpha) || alpha < 1e-6) {\\n                    return null;\\n                }\\n                const normalizedDepth = r / alpha;\\n                return getWorldPoint(pickCamera, x, y, viewportWidth, viewportHeight, normalizedDepth);\\n            };\\n        };\\n        const ensureRendered = (width, height, worldLayer) => {\\n            if (cameraMatches(width, height)) {\\n                return;\\n            }\\n            // Enable gsplat IDs only while rendering the pick target so we\\n            // don't pay the memory/perf cost between pick passes.\\n            const prevEnableIds = app.scene.gsplat.enableIds;\\n            app.scene.gsplat.enableIds = true;\\n            try {\\n                if (!chunksPatched) {\\n                    registerPickerShaderPatches(app);\\n                    chunksPatched = true;\\n                }\\n                if (!accumPass) {\\n                    initRasterAccum(width, height);\\n                }\\n                else if (cacheWidth !== width || cacheHeight !== height) {\\n                    cacheValid = false;\\n                    accumTarget.resize(width, height);\\n                }\\n                accumPass.init(accumTarget);\\n                accumPass.setClearColor(clearColor);\\n                accumPass.update(camera.camera, app.scene, [worldLayer], new Map(), false);\\n                accumPass.render();\\n                updateCache(width, height);\\n                cacheValid = true;\\n            }\\n            finally {\\n                app.scene.gsplat.enableIds = prevEnableIds;\\n            }\\n        };\\n        const prepareSample = (x, y) => {\\n            const width = Math.floor(graphicsDevice.width);\\n            const height = Math.floor(graphicsDevice.height);\\n            // bail out if the device hasn't been sized yet\\n            if (width <= 0 || height <= 0) {\\n                return null;\\n            }\\n            const worldLayer = app.scene.layers.getLayerByName('World');\\n            if (!worldLayer) {\\n                return null;\\n            }\\n            const screenX = Math.min(width - 1, Math.max(0, Math.floor(x * width)));\\n            const screenY = Math.min(height - 1, Math.max(0, Math.floor(y * height)));\\n            ensureRendered(width, height, worldLayer);\\n            const pickCamera = getCacheCameraSnapshot();\\n            return { width, height, screenX, screenY, pickCamera };\\n        };\\n        const pickPosition = async (x, y) => {\\n            const sample = prepareSample(x, y);\\n            if (!sample) {\\n                return null;\\n            }\\n            const { width, height, screenX, screenY, pickCamera } = sample;\\n            const pixels = await readTexture(accumBuffer, screenX, screenY, accumTarget);\\n            const r = half2Float(pixels[0]);\\n            const transmittance = half2Float(pixels[3]);\\n            const alpha = 1 - transmittance;\\n            if (!Number.isFinite(r) || !Number.isFinite(alpha) || alpha < 1e-6) {\\n                return null;\\n            }\\n            const normalizedDepth = r / alpha;\\n            const position = getWorldPoint(pickCamera, screenX, screenY, width, height, normalizedDepth);\\n            return position ? { position, camera: pickCamera, screenX, screenY, width, height } : null;\\n        };\\n        const serializePick = (operation) => {\\n            // The render targets are shared by all picks on this instance.\\n            const result = pickQueue.then(operation, operation);\\n            pickQueue = result.then(() => undefined, () => undefined);\\n            return result;\\n        };\\n        const pick = async (x, y) => {\\n            const result = await pickPosition(x, y);\\n            return result?.position ?? null;\\n        };\\n        const pickSurface = async (x, y) => {\\n            const sample = prepareSample(x, y);\\n            if (!sample) {\\n                return null;\\n            }\\n            const { width, height, screenX, screenY, pickCamera } = sample;\\n            // Single block read serves both depth (center pixel) and normal\\n            // samples. Sized to the maximum possible ring pixel-radius so the\\n            // dynamic ring offsets always lie inside the buffer we read.\\n            const blockX = Math.max(0, screenX - NORMAL_SAMPLE_MAX_PX);\\n            const blockY = Math.max(0, screenY - NORMAL_SAMPLE_MAX_PX);\\n            const blockWidth = Math.min(width - 1, screenX + NORMAL_SAMPLE_MAX_PX) - blockX + 1;\\n            const blockHeight = Math.min(height - 1, screenY + NORMAL_SAMPLE_MAX_PX) - blockY + 1;\\n            const rasterBlock = await readRasterBlock(blockX, blockY, blockWidth, blockHeight, width, height, pickCamera);\\n            const position = rasterBlock(screenX, screenY);\\n            if (!position) {\\n                return null;\\n            }\\n            const samplePixel = (px, py) => {\\n                if (px < 0 || px >= width || py < 0 || py >= height) {\\n                    return null;\\n                }\\n                return rasterBlock(px, py);\\n            };\\n            // Pixel radius corresponding to a fixed world radius at the\\n            // picked-point's depth. Clamped so distant picks still sample\\n            // enough pixels and very-close picks stay inside the block read.\\n            const pixelRadius = Math.max(NORMAL_SAMPLE_MIN_PX, Math.min(NORMAL_SAMPLE_MAX_PX, worldRadiusToPixelRadius(pickCamera, position, height, NORMAL_SAMPLE_WORLD_RADIUS)));\\n            const ringPixelRadii = NORMAL_RING_FRACTIONS.map(f => Math.max(1, Math.round(f * pixelRadius)));\\n            const sampleRings = ringPixelRadii.map((radius) => {\\n                return NORMAL_SAMPLE_DIRECTIONS.map(([dx, dy]) => {\\n                    return samplePixel(screenX + dx * radius, screenY + dy * radius);\\n                });\\n            });\\n            const toCamera = setCameraFacingNormal(pickCamera.position, position, new Vec3());\\n            // Collect every valid 3D sample: the picked position plus all ring\\n            // samples that didn't fall off-screen or fail the depth read.\\n            const fitPoints = [position];\\n            for (let i = 0; i < sampleRings.length; i++) {\\n                const ring = sampleRings[i];\\n                for (let j = 0; j < ring.length; j++) {\\n                    const pt = ring[j];\\n                    if (pt)\\n                        fitPoints.push(pt);\\n                }\\n            }\\n            const normal = new Vec3();\\n            if (!fitPlaneNormal(fitPoints, toCamera, normal)) {\\n                normal.copy(toCamera);\\n            }\\n            return {\\n                position,\\n                normal\\n            };\\n        };\\n        this.pick = (x, y) => serializePick(() => pick(x, y));\\n        this.pickSurface = (x, y) => serializePick(() => pickSurface(x, y));\\n        this.release = () => {\\n            if (chunksPatched) {\\n                unregisterPickerShaderPatches(app);\\n                chunksPatched = false;\\n            }\\n            accumPass?.destroy();\\n            accumTarget?.destroy();\\n            accumBuffer?.destroy();\\n            cacheValid = false;\\n        };\\n    }\\n}\\n\\n// ---------------------------------------------------------------------------\\n// WGSL compute shader: ray-march through the sparse voxel octree per pixel\\n// ---------------------------------------------------------------------------\\nconst voxelOverlayWGSL = /* wgsl */ `\\n\\n// Solid leaf sentinel: childMask=0xFF, baseOffset=0\\nconst SOLID_LEAF_MARKER: u32 = 0xFF000000u;\\n\\n// Maximum DDA steps to prevent infinite loops\\nconst MAX_STEPS: u32 = 512u;\\n\\n// Target wireframe edge width in pixels\\nconst EDGE_PIXELS: f32 = 1.5;\\n\\n// Wireframe edge alpha (1.0 = pure black opaque edges, matching the mesh\\n// overlay's wireframe pass).\\nconst EDGE_ALPHA: f32 = 0.8;\\n\\n// Interior fill alpha (matching the mesh overlay's surface alpha).\\nconst FILL_ALPHA: f32 = 0.30;\\n\\nstruct Uniforms {\\n    invVP: mat4x4<f32>,\\n    screenWidth: u32,\\n    screenHeight: u32,\\n    gridMinX: f32,\\n    gridMinY: f32,\\n    gridMinZ: f32,\\n    voxelRes: f32,\\n    numVoxelsX: u32,\\n    numVoxelsY: u32,\\n    numVoxelsZ: u32,\\n    leafSize: u32,\\n    treeDepth: u32,\\n    projScaleY: f32,\\n    displayMode: u32,\\n    inverted: u32\\n};\\n\\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\\n@group(0) @binding(1) var<storage, read> nodes: array<u32>;\\n@group(0) @binding(2) var<storage, read> leafData: array<u32>;\\n@group(0) @binding(3) var outputTexture: texture_storage_2d<rgba8unorm, write>;\\n\\n// ---- helpers ----\\n\\n// Traverse the octree for block (bx, by, bz). Returns vec2u(result, skipLevel):\\n//   result: 0 = empty, 1 = solid, 2+ = mixed leaf (2 + leafDataIndex)\\n//   skipLevel: octree level for multi-block skipping (meaningful when result == 0 or 1)\\nfn queryBlock(bx: i32, by: i32, bz: i32) -> vec2u {\\n    let depth = uniforms.treeDepth;\\n    var nodeIndex: u32 = 0u;\\n\\n    for (var level: u32 = depth - 1u; ; ) {\\n        let node = nodes[nodeIndex];\\n\\n        // Solid leaf sentinel -- return level + 1 so the caller can skip 2^(level+1) blocks\\n        if (node == SOLID_LEAF_MARKER) {\\n            return vec2u(1u, level + 1u);\\n        }\\n\\n        let childMask = (node >> 24u) & 0xFFu;\\n\\n        // childMask == 0 means this is a mixed leaf node\\n        if (childMask == 0u) {\\n            let leafIdx = node & 0x00FFFFFFu;\\n            return vec2u(2u + leafIdx, 0u);\\n        }\\n\\n        // Determine octant at this level\\n        let bitX = (u32(bx) >> level) & 1u;\\n        let bitY = (u32(by) >> level) & 1u;\\n        let bitZ = (u32(bz) >> level) & 1u;\\n        let octant = (bitZ << 2u) | (bitY << 1u) | bitX;\\n\\n        // Check if child exists\\n        if ((childMask & (1u << octant)) == 0u) {\\n            return vec2u(0u, level);\\n        }\\n\\n        // Compute child index\\n        let baseOffset = node & 0x00FFFFFFu;\\n        let prefix = (1u << octant) - 1u;\\n        let childOffset = countOneBits(childMask & prefix);\\n        nodeIndex = baseOffset + childOffset;\\n\\n        if (level == 0u) { break; }\\n        level -= 1u;\\n    }\\n\\n    // Reached leaf level\\n    let node = nodes[nodeIndex];\\n    if (node == SOLID_LEAF_MARKER) {\\n        return vec2u(1u, 0u);\\n    }\\n    let leafIdx = node & 0x00FFFFFFu;\\n    return vec2u(2u + leafIdx, 0u);\\n}\\n\\n// Ray-AABB intersection returning (tNear, tFar). If tNear > tFar → miss.\\nfn intersectAABB(ro: vec3f, invDir: vec3f, bmin: vec3f, bmax: vec3f) -> vec2f {\\n    let t1 = (bmin - ro) * invDir;\\n    let t2 = (bmax - ro) * invDir;\\n    let tmin = min(t1, t2);\\n    let tmax = max(t1, t2);\\n    let tNear = max(max(tmin.x, tmin.y), tmin.z);\\n    let tFar  = min(min(tmax.x, tmax.y), tmax.z);\\n    return vec2f(tNear, tFar);\\n}\\n\\n// Compute wireframe edge factor (0 = interior, 1 = on edge) for a hit point on a voxel cube.\\n// Uses the median of the three per-axis face distances so it works on ANY face.\\nfn edgeFactor(hitPos: vec3f, voxMin: vec3f, voxSize: f32, edgeWidth: f32) -> f32 {\\n    let local = (hitPos - voxMin) / voxSize;\\n\\n    // Distance to nearest face boundary for each axis\\n    let fx = min(local.x, 1.0 - local.x);\\n    let fy = min(local.y, 1.0 - local.y);\\n    let fz = min(local.z, 1.0 - local.z);\\n\\n    // Median of three values = second smallest = edge distance.\\n    // On a face, one of fx/fy/fz is ~0 (the face normal axis).\\n    // The median gives the smaller of the other two = distance to nearest edge.\\n    let edgeDist = max(min(fx, fy), min(max(fx, fy), fz));\\n\\n    return 1.0 - smoothstep(0.0, edgeWidth, edgeDist);\\n}\\n\\n// Shade a voxel hit, returning premultiplied RGBA. Uses the same face-axis\\n// grayscale palette as the mesh collision overlay (0.85 / 0.55 / 0.30 by\\n// dominant axis), with pure black at face edges to mimic that overlay's\\n// wireframe pass.\\nfn shadeVoxelHit(hitPos: vec3f, voxMin: vec3f, voxelRes: f32, ro: vec3f) -> vec4f {\\n    let dist = length(hitPos - ro);\\n    let pixelWorld = 2.0 * dist / (f32(uniforms.screenHeight) * uniforms.projScaleY);\\n    let ew = clamp(EDGE_PIXELS * pixelWorld / voxelRes, 0.01, 0.5);\\n\\n    let ef = edgeFactor(hitPos, voxMin, voxelRes, ew);\\n\\n    let local = (hitPos - voxMin) / voxelRes;\\n    let fx = min(local.x, 1.0 - local.x);\\n    let fy = min(local.y, 1.0 - local.y);\\n    let fz = min(local.z, 1.0 - local.z);\\n\\n    var faceAxis: u32 = 0u;\\n    if (fy <= fx && fy <= fz) {\\n        faceAxis = 1u;\\n    } else if (fz <= fx) {\\n        faceAxis = 2u;\\n    }\\n\\n    var baseColor: vec3f;\\n    if (faceAxis == 0u) { baseColor = vec3f(0.85); }\\n    else if (faceAxis == 1u) { baseColor = vec3f(0.55); }\\n    else { baseColor = vec3f(0.30); }\\n\\n    // Mix the surface base color toward black as the edge factor approaches 1\\n    // and ramp alpha from FILL_ALPHA up to EDGE_ALPHA so face edges read as\\n    // opaque black lines while the interior stays at the surface tint.\\n    let color = mix(baseColor, vec3f(0.0), ef);\\n    let alpha = mix(FILL_ALPHA, EDGE_ALPHA, ef);\\n\\n    return vec4f(color * alpha, alpha);\\n}\\n\\n// Blue (0) -> Cyan (0.25) -> Green (0.5) -> Yellow (0.75) -> Red (1.0)\\nfn heatmap(t: f32) -> vec3f {\\n    let c = clamp(t, 0.0, 1.0);\\n    let r = clamp(min(c - 0.5, 1.0) * 2.0, 0.0, 1.0);\\n    let g = select(clamp(c * 4.0, 0.0, 1.0), clamp((1.0 - c) * 4.0, 0.0, 1.0), c > 0.5);\\n    let b = clamp(1.0 - c * 2.0, 0.0, 1.0);\\n    return vec3f(r, g, b);\\n}\\n\\n// ---- main ----\\n\\n@compute @workgroup_size(8, 8, 1)\\nfn main(@builtin(global_invocation_id) gid: vec3u) {\\n    let px = i32(gid.x);\\n    let py = i32(gid.y);\\n    let sw = i32(uniforms.screenWidth);\\n    let sh = i32(uniforms.screenHeight);\\n\\n    if (px >= sw || py >= sh) {\\n        return;\\n    }\\n\\n    // Reconstruct world-space ray from pixel coordinates\\n    let ndcX = (f32(px) + 0.5) / f32(sw) * 2.0 - 1.0;\\n    let ndcY = -((f32(py) + 0.5) / f32(sh) * 2.0 - 1.0);\\n\\n    let clipNear = vec4f(ndcX, ndcY, 0.0, 1.0);\\n    let clipFar  = vec4f(ndcX, ndcY, 1.0, 1.0);\\n\\n    var worldNear = uniforms.invVP * clipNear;\\n    worldNear = worldNear / worldNear.w;\\n    var worldFar = uniforms.invVP * clipFar;\\n    worldFar = worldFar / worldFar.w;\\n\\n    let ro = worldNear.xyz;\\n    let rd = normalize(worldFar.xyz - worldNear.xyz);\\n\\n    // Grid AABB\\n    let gridMin = vec3f(uniforms.gridMinX, uniforms.gridMinY, uniforms.gridMinZ);\\n    let gridMax = gridMin + vec3f(\\n        f32(uniforms.numVoxelsX),\\n        f32(uniforms.numVoxelsY),\\n        f32(uniforms.numVoxelsZ)\\n    ) * uniforms.voxelRes;\\n\\n    let invDir = 1.0 / rd;\\n    let gridHit = intersectAABB(ro, invDir, gridMin, gridMax);\\n\\n    if (gridHit.x > gridHit.y) {\\n        textureStore(outputTexture, vec2i(px, py), vec4f(0.0));\\n        return;\\n    }\\n\\n    let tEntry = max(gridHit.x, 0.0) + 0.0001;\\n\\n    // Entry point in voxel-index space\\n    let entryWorld = ro + rd * tEntry;\\n    let voxelRes = uniforms.voxelRes;\\n    let lsf = f32(uniforms.leafSize);\\n    let blockRes = voxelRes * lsf;\\n    let leafSz = i32(uniforms.leafSize);\\n\\n    // Block-level DDA setup\\n    let entryBlock = (entryWorld - gridMin) / blockRes;\\n    let numBlocksX = i32(uniforms.numVoxelsX / uniforms.leafSize);\\n    let numBlocksY = i32(uniforms.numVoxelsY / uniforms.leafSize);\\n    let numBlocksZ = i32(uniforms.numVoxelsZ / uniforms.leafSize);\\n\\n    var bx = clamp(i32(floor(entryBlock.x)), 0, numBlocksX - 1);\\n    var by = clamp(i32(floor(entryBlock.y)), 0, numBlocksY - 1);\\n    var bz = clamp(i32(floor(entryBlock.z)), 0, numBlocksZ - 1);\\n\\n    let stepX = select(-1, 1, rd.x >= 0.0);\\n    let stepY = select(-1, 1, rd.y >= 0.0);\\n    let stepZ = select(-1, 1, rd.z >= 0.0);\\n\\n    let tDeltaX = abs(blockRes / rd.x);\\n    let tDeltaY = abs(blockRes / rd.y);\\n    let tDeltaZ = abs(blockRes / rd.z);\\n\\n    // tMax: t value to reach next block boundary along each axis\\n    let blockMinWorld = gridMin + vec3f(f32(bx), f32(by), f32(bz)) * blockRes;\\n    let nextBoundX = select(blockMinWorld.x, blockMinWorld.x + blockRes, rd.x >= 0.0);\\n    let nextBoundY = select(blockMinWorld.y, blockMinWorld.y + blockRes, rd.y >= 0.0);\\n    let nextBoundZ = select(blockMinWorld.z, blockMinWorld.z + blockRes, rd.z >= 0.0);\\n\\n    var tMaxX = (nextBoundX - ro.x) / rd.x;\\n    var tMaxY = (nextBoundY - ro.y) / rd.y;\\n    var tMaxZ = (nextBoundZ - ro.z) / rd.z;\\n\\n    let inv = uniforms.inverted != 0u;\\n    var totalWork: u32 = 0u;\\n\\n    for (var step: u32 = 0u; step < MAX_STEPS; step++) {\\n        totalWork += 1u;\\n\\n        let qResult = queryBlock(bx, by, bz);\\n        let blockResult = qResult.x;\\n        let skipLevel = qResult.y;\\n\\n        // Normal: skip large empty regions.  Inverted: skip large solid regions.\\n        let shouldSkip = select(\\n            blockResult == 0u && skipLevel >= 1u,\\n            blockResult == 1u && skipLevel >= 1u,\\n            inv\\n        );\\n\\n        if (shouldSkip) {\\n            let cellBlocks = i32(1u << skipLevel);\\n            let cellMask = ~(cellBlocks - 1);\\n            let cellXMin = bx & cellMask;\\n            let cellYMin = by & cellMask;\\n            let cellZMin = bz & cellMask;\\n\\n            for (var skip: u32 = 0u; skip < 128u; skip++) {\\n                totalWork += 1u;\\n\\n                if (tMaxX < tMaxY && tMaxX < tMaxZ) {\\n                    bx += stepX;\\n                    tMaxX += tDeltaX;\\n                    if (bx < cellXMin || bx >= cellXMin + cellBlocks) { break; }\\n                } else if (tMaxY < tMaxZ) {\\n                    by += stepY;\\n                    tMaxY += tDeltaY;\\n                    if (by < cellYMin || by >= cellYMin + cellBlocks) { break; }\\n                } else {\\n                    bz += stepZ;\\n                    tMaxZ += tDeltaZ;\\n                    if (bz < cellZMin || bz >= cellZMin + cellBlocks) { break; }\\n                }\\n            }\\n        } else {\\n            // Normal: enter voxel DDA for non-empty blocks.\\n            // Inverted: enter voxel DDA for non-solid blocks (empty or mixed).\\n            let enterDDA = select(blockResult != 0u, blockResult != 1u, inv);\\n\\n            if (enterDDA) {\\n                let blockOrigin = gridMin + vec3f(f32(bx), f32(by), f32(bz)) * blockRes;\\n\\n                let blockMax = blockOrigin + vec3f(blockRes);\\n                let bHit = intersectAABB(ro, invDir, blockOrigin, blockMax);\\n                let tBlockEntry = max(bHit.x, 0.0);\\n\\n                // Voxel-level DDA within the block\\n                let entryVoxWorld = ro + rd * (tBlockEntry + 0.0001);\\n                let entryLocal = (entryVoxWorld - blockOrigin) / voxelRes;\\n                var vx = clamp(i32(floor(entryLocal.x)), 0, leafSz - 1);\\n                var vy = clamp(i32(floor(entryLocal.y)), 0, leafSz - 1);\\n                var vz = clamp(i32(floor(entryLocal.z)), 0, leafSz - 1);\\n\\n                let vTDeltaX = abs(voxelRes / rd.x);\\n                let vTDeltaY = abs(voxelRes / rd.y);\\n                let vTDeltaZ = abs(voxelRes / rd.z);\\n\\n                let voxOrigin = blockOrigin + vec3f(f32(vx), f32(vy), f32(vz)) * voxelRes;\\n                let vNextX = select(voxOrigin.x, voxOrigin.x + voxelRes, rd.x >= 0.0);\\n                let vNextY = select(voxOrigin.y, voxOrigin.y + voxelRes, rd.y >= 0.0);\\n                let vNextZ = select(voxOrigin.z, voxOrigin.z + voxelRes, rd.z >= 0.0);\\n\\n                var vTMaxX = (vNextX - ro.x) / rd.x;\\n                var vTMaxY = (vNextY - ro.y) / rd.y;\\n                var vTMaxZ = (vNextZ - ro.z) / rd.z;\\n\\n                var maskLo: u32 = 0u;\\n                var maskHi: u32 = 0u;\\n                if (blockResult > 1u) {\\n                    let leafIdx = blockResult - 2u;\\n                    maskLo = leafData[leafIdx * 2u];\\n                    maskHi = leafData[leafIdx * 2u + 1u];\\n                }\\n\\n                for (var vStep: u32 = 0u; vStep < 12u; vStep++) {\\n                    totalWork += 1u;\\n\\n                    var isSolid = false;\\n\\n                    if (blockResult == 1u) {\\n                        isSolid = true;\\n                    } else {\\n                        let bitIndex = u32(vz) * 16u + u32(vy) * 4u + u32(vx);\\n                        isSolid = select(\\n                            (maskHi & (1u << (bitIndex - 32u))) != 0u,\\n                            (maskLo & (1u << bitIndex)) != 0u,\\n                            bitIndex < 32u\\n                        );\\n                    }\\n\\n                    let isHit = select(isSolid, !isSolid, inv);\\n\\n                    if (isHit) {\\n                        if (uniforms.displayMode == 0u) {\\n                            let voxMin = blockOrigin + vec3f(f32(vx), f32(vy), f32(vz)) * voxelRes;\\n                            let vHit = intersectAABB(ro, invDir, voxMin, voxMin + vec3f(voxelRes));\\n                            let hitPos = ro + rd * max(vHit.x, 0.0);\\n                            let result = shadeVoxelHit(hitPos, voxMin, voxelRes, ro);\\n                            textureStore(outputTexture, vec2i(px, py), result);\\n                        } else {\\n                            let effort = f32(totalWork) / 256.0;\\n                            let color = heatmap(effort);\\n                            textureStore(outputTexture, vec2i(px, py), vec4f(color, 1.0));\\n                        }\\n                        return;\\n                    }\\n\\n                    // Advance voxel DDA\\n                    if (vTMaxX < vTMaxY && vTMaxX < vTMaxZ) {\\n                        vx += stepX;\\n                        vTMaxX += vTDeltaX;\\n                        if (vx < 0 || vx >= leafSz) { break; }\\n                    } else if (vTMaxY < vTMaxZ) {\\n                        vy += stepY;\\n                        vTMaxY += vTDeltaY;\\n                        if (vy < 0 || vy >= leafSz) { break; }\\n                    } else {\\n                        vz += stepZ;\\n                        vTMaxZ += vTDeltaZ;\\n                        if (vz < 0 || vz >= leafSz) { break; }\\n                    }\\n                }\\n            }\\n\\n            // Advance block DDA\\n            if (tMaxX < tMaxY && tMaxX < tMaxZ) {\\n                bx += stepX;\\n                tMaxX += tDeltaX;\\n            } else if (tMaxY < tMaxZ) {\\n                by += stepY;\\n                tMaxY += tDeltaY;\\n            } else {\\n                bz += stepZ;\\n                tMaxZ += tDeltaZ;\\n            }\\n        }\\n\\n        if (bx < 0 || by < 0 || bz < 0 ||\\n            bx >= numBlocksX || by >= numBlocksY || bz >= numBlocksZ) {\\n            break;\\n        }\\n    }\\n\\n    textureStore(outputTexture, vec2i(px, py), vec4f(0.0));\\n}\\n`;\\n// ---------------------------------------------------------------------------\\n// VoxelDebugOverlay class\\n// ---------------------------------------------------------------------------\\nclass VoxelDebugOverlay {\\n    app;\\n    camera;\\n    compute;\\n    storageTexture;\\n    overlayMaterial;\\n    nodesBuffer;\\n    leafDataBuffer;\\n    collision;\\n    currentWidth = 0;\\n    currentHeight = 0;\\n    invVP = new Mat4();\\n    vpTemp = new Mat4();\\n    /** Whether the overlay is currently rendering. */\\n    enabled = false;\\n    /** Display mode: 'overlay' for wireframe debug, 'heatmap' for effort visualization. */\\n    mode = 'overlay';\\n    constructor(app, collision, camera) {\\n        this.app = app;\\n        this.camera = camera;\\n        this.collision = collision;\\n        const device = app.graphicsDevice;\\n        // Upload SVO node array as a read-only storage buffer\\n        const nodesData = collision.nodes;\\n        const nodesByteSize = Math.max(nodesData.byteLength, 4);\\n        this.nodesBuffer = new StorageBuffer(device, nodesByteSize, BUFFERUSAGE_COPY_DST);\\n        if (nodesData.byteLength > 0) {\\n            this.nodesBuffer.write(0, nodesData, 0, nodesData.length);\\n        }\\n        // Upload leaf data as a read-only storage buffer\\n        const leafDataArr = collision.leafData;\\n        const leafByteSize = Math.max(leafDataArr.byteLength, 4);\\n        this.leafDataBuffer = new StorageBuffer(device, leafByteSize, BUFFERUSAGE_COPY_DST);\\n        if (leafDataArr.byteLength > 0) {\\n            this.leafDataBuffer.write(0, leafDataArr, 0, leafDataArr.length);\\n        }\\n        // Create the initial storage texture (will be resized on first update)\\n        this.currentWidth = Math.max(device.width, 1);\\n        this.currentHeight = Math.max(device.height, 1);\\n        this.storageTexture = this.createStorageTexture(this.currentWidth, this.currentHeight);\\n        // Create compute shader\\n        const shaderDefinition = {\\n            name: 'VoxelDebugOverlay',\\n            shaderLanguage: SHADERLANGUAGE_WGSL,\\n            cshader: voxelOverlayWGSL,\\n            computeUniformBufferFormats: {\\n                uniforms: new UniformBufferFormat(device, [\\n                    new UniformFormat('invVP', UNIFORMTYPE_MAT4),\\n                    new UniformFormat('screenWidth', UNIFORMTYPE_UINT),\\n                    new UniformFormat('screenHeight', UNIFORMTYPE_UINT),\\n                    new UniformFormat('gridMinX', UNIFORMTYPE_FLOAT),\\n                    new UniformFormat('gridMinY', UNIFORMTYPE_FLOAT),\\n                    new UniformFormat('gridMinZ', UNIFORMTYPE_FLOAT),\\n                    new UniformFormat('voxelRes', UNIFORMTYPE_FLOAT),\\n                    new UniformFormat('numVoxelsX', UNIFORMTYPE_UINT),\\n                    new UniformFormat('numVoxelsY', UNIFORMTYPE_UINT),\\n                    new UniformFormat('numVoxelsZ', UNIFORMTYPE_UINT),\\n                    new UniformFormat('leafSize', UNIFORMTYPE_UINT),\\n                    new UniformFormat('treeDepth', UNIFORMTYPE_UINT),\\n                    new UniformFormat('projScaleY', UNIFORMTYPE_FLOAT),\\n                    new UniformFormat('displayMode', UNIFORMTYPE_UINT),\\n                    new UniformFormat('inverted', UNIFORMTYPE_UINT)\\n                ])\\n            },\\n            computeBindGroupFormat: new BindGroupFormat(device, [\\n                new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\\n                new BindStorageBufferFormat('nodes', SHADERSTAGE_COMPUTE, true),\\n                new BindStorageBufferFormat('leafData', SHADERSTAGE_COMPUTE, true),\\n                new BindStorageTextureFormat('outputTexture', PIXELFORMAT_RGBA8, TEXTUREDIMENSION_2D)\\n            ])\\n        };\\n        const shader = new Shader(device, shaderDefinition);\\n        // Create compute instance\\n        this.compute = new Compute(device, shader, 'VoxelDebugOverlay');\\n        // Create overlay material with premultiplied alpha blending and a custom\\n        // fragment shader that preserves the texture's alpha channel (the built-in\\n        // getTextureShaderDesc hardcodes alpha = 1.0, which prevents blending).\\n        this.overlayMaterial = new ShaderMaterial();\\n        this.overlayMaterial.cull = CULLFACE_NONE;\\n        this.overlayMaterial.blendType = BLEND_PREMULTIPLIED;\\n        this.overlayMaterial.depthTest = false;\\n        this.overlayMaterial.depthWrite = false;\\n        this.overlayMaterial.setParameter('colorMap', this.storageTexture);\\n        this.overlayMaterial.shaderDesc = {\\n            uniqueName: 'VoxelOverlayComposite',\\n            vertexGLSL: /* glsl */ `\\n                attribute vec2 vertex_position;\\n                uniform mat4 matrix_model;\\n                varying vec2 uv0;\\n                void main(void) {\\n                    gl_Position = matrix_model * vec4(vertex_position, 0, 1);\\n                    uv0 = vertex_position.xy + 0.5;\\n                }\\n            `,\\n            vertexWGSL: /* wgsl */ `\\n                attribute vertex_position: vec2f;\\n                uniform matrix_model: mat4x4f;\\n                varying uv0: vec2f;\\n                @vertex fn vertexMain(input: VertexInput) -> VertexOutput {\\n                    var output: VertexOutput;\\n                    output.position = uniform.matrix_model * vec4f(input.vertex_position, 0.0, 1.0);\\n                    output.uv0 = input.vertex_position.xy + vec2f(0.5);\\n                    return output;\\n                }\\n            `,\\n            fragmentGLSL: /* glsl */ `\\n                varying vec2 uv0;\\n                uniform sampler2D colorMap;\\n                void main(void) {\\n                    gl_FragColor = texture2D(colorMap, uv0);\\n                }\\n            `,\\n            fragmentWGSL: /* wgsl */ `\\n                varying uv0: vec2f;\\n                var colorMap: texture_2d<f32>;\\n                var colorMapSampler: sampler;\\n                @fragment fn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n                    var output: FragmentOutput;\\n                    output.color = textureSample(colorMap, colorMapSampler, input.uv0);\\n                    return output;\\n                }\\n            `,\\n            attributes: { vertex_position: SEMANTIC_POSITION }\\n        };\\n        this.overlayMaterial.update();\\n    }\\n    createStorageTexture(width, height) {\\n        return new Texture(this.app.graphicsDevice, {\\n            name: 'VoxelOverlay-Storage',\\n            width,\\n            height,\\n            format: PIXELFORMAT_RGBA8,\\n            mipmaps: false,\\n            addressU: 3, // ADDRESS_CLAMP_TO_EDGE\\n            addressV: 3, // ADDRESS_CLAMP_TO_EDGE\\n            storage: true\\n        });\\n    }\\n    update() {\\n        if (!this.enabled)\\n            return;\\n        const { app, camera, compute, collision } = this;\\n        const device = app.graphicsDevice;\\n        const width = device.width;\\n        const height = device.height;\\n        if (width <= 0 || height <= 0)\\n            return;\\n        // Resize storage texture if screen dimensions changed\\n        if (width !== this.currentWidth || height !== this.currentHeight) {\\n            this.storageTexture.destroy();\\n            this.currentWidth = width;\\n            this.currentHeight = height;\\n            this.storageTexture = this.createStorageTexture(width, height);\\n            // Update the overlay material to reference the new texture\\n            this.overlayMaterial.setParameter('colorMap', this.storageTexture);\\n            this.overlayMaterial.update();\\n        }\\n        // Compute inverse view-projection matrix\\n        const cam = camera.camera;\\n        this.vpTemp.mul2(cam.projectionMatrix, cam.viewMatrix);\\n        this.invVP.copy(this.vpTemp).invert();\\n        // For legacy v1.0 data, pre-multiply invVP by R_z180 (negate X/Y rows)\\n        // to transform rays from PlayCanvas world space into the raw voxel space\\n        if (collision.flipXY) {\\n            const d = this.invVP.data;\\n            d[0] = -d[0];\\n            d[1] = -d[1];\\n            d[4] = -d[4];\\n            d[5] = -d[5];\\n            d[8] = -d[8];\\n            d[9] = -d[9];\\n            d[12] = -d[12];\\n            d[13] = -d[13];\\n        }\\n        // Set compute uniforms\\n        compute.setParameter('invVP', this.invVP.data);\\n        compute.setParameter('screenWidth', width);\\n        compute.setParameter('screenHeight', height);\\n        compute.setParameter('gridMinX', collision.gridMinX);\\n        compute.setParameter('gridMinY', collision.gridMinY);\\n        compute.setParameter('gridMinZ', collision.gridMinZ);\\n        compute.setParameter('voxelRes', collision.voxelResolution);\\n        compute.setParameter('numVoxelsX', collision.numVoxelsX);\\n        compute.setParameter('numVoxelsY', collision.numVoxelsY);\\n        compute.setParameter('numVoxelsZ', collision.numVoxelsZ);\\n        compute.setParameter('leafSize', collision.leafSize);\\n        compute.setParameter('treeDepth', collision.treeDepth);\\n        compute.setParameter('projScaleY', cam.projectionMatrix.data[5]);\\n        compute.setParameter('displayMode', this.mode === 'heatmap' ? 1 : 0);\\n        const camPos = camera.getPosition();\\n        let wx = camPos.x, wy = camPos.y;\\n        const wz = camPos.z;\\n        if (collision.flipXY) {\\n            wx = -wx;\\n            wy = -wy;\\n        }\\n        const ix = Math.floor((wx - collision.gridMinX) / collision.voxelResolution);\\n        const iy = Math.floor((wy - collision.gridMinY) / collision.voxelResolution);\\n        const iz = Math.floor((wz - collision.gridMinZ) / collision.voxelResolution);\\n        compute.setParameter('inverted', collision.isVoxelSolid(ix, iy, iz) ? 1 : 0);\\n        // Set storage buffers and output texture\\n        compute.setParameter('nodes', this.nodesBuffer);\\n        compute.setParameter('leafData', this.leafDataBuffer);\\n        compute.setParameter('outputTexture', this.storageTexture);\\n        // Dispatch compute shader\\n        const workgroupsX = Math.ceil(width / 8);\\n        const workgroupsY = Math.ceil(height / 8);\\n        compute.setupDispatch(workgroupsX, workgroupsY, 1);\\n        device.computeDispatch([compute], 'VoxelDebugOverlay');\\n        // Composite overlay on top of the scene\\n        app.drawTexture(0, 0, 2, 2, null, this.overlayMaterial);\\n    }\\n    destroy() {\\n        this.nodesBuffer?.destroy();\\n        this.leafDataBuffer?.destroy();\\n        this.storageTexture?.destroy();\\n    }\\n}\\n\\n// String.replace wrapper that warns when the source substring is missing, so\\n// shader chunk patches against the engine fail loudly instead of silently\\n// producing the original chunk.\\nconst patchChunk = (source, search, replacement, name) => {\\n    if (!source.includes(search)) {\\n        console.warn(`patchChunk: substring not found in '${name}', shader chunk patch may be out of sync with the engine.`);\\n    }\\n    return source.replace(search, replacement);\\n};\\nconst gammaChunkGlsl = `\\nvec3 prepareOutputFromGamma(vec3 gammaColor, float depth) {\\n    return gammaColor;\\n}\\n`;\\nconst gammaChunkWgsl = `\\nfn prepareOutputFromGamma(gammaColor: vec3f, depth: f32) -> vec3f {\\n    return gammaColor;\\n}\\n`;\\nconst rendererTable = {\\n    'webgl': GSPLAT_RENDERER_RASTER_CPU_SORT,\\n    'webgpu': GSPLAT_RENDERER_RASTER_GPU_SORT\\n};\\nconst tonemapTable = {\\n    none: TONEMAP_NONE,\\n    linear: TONEMAP_LINEAR,\\n    filmic: TONEMAP_FILMIC,\\n    hejl: TONEMAP_HEJL,\\n    aces: TONEMAP_ACES,\\n    aces2: TONEMAP_ACES2,\\n    neutral: TONEMAP_NEUTRAL\\n};\\nconst applyPostEffectSettings = (cameraFrame, settings) => {\\n    if (settings.sharpness.enabled) {\\n        cameraFrame.rendering.sharpness = settings.sharpness.amount;\\n    }\\n    else {\\n        cameraFrame.rendering.sharpness = 0;\\n    }\\n    const { bloom } = cameraFrame;\\n    if (settings.bloom.enabled) {\\n        bloom.intensity = settings.bloom.intensity;\\n        bloom.blurLevel = settings.bloom.blurLevel;\\n    }\\n    else {\\n        bloom.intensity = 0;\\n    }\\n    const { grading } = cameraFrame;\\n    if (settings.grading.enabled) {\\n        grading.enabled = true;\\n        grading.brightness = settings.grading.brightness;\\n        grading.contrast = settings.grading.contrast;\\n        grading.saturation = settings.grading.saturation;\\n        grading.tint = new Color().fromArray(settings.grading.tint);\\n    }\\n    else {\\n        grading.enabled = false;\\n    }\\n    const { vignette } = cameraFrame;\\n    if (settings.vignette.enabled) {\\n        vignette.intensity = settings.vignette.intensity;\\n        vignette.inner = settings.vignette.inner;\\n        vignette.outer = settings.vignette.outer;\\n        vignette.curvature = settings.vignette.curvature;\\n    }\\n    else {\\n        vignette.intensity = 0;\\n    }\\n    const { fringing } = cameraFrame;\\n    if (settings.fringing.enabled) {\\n        fringing.intensity = settings.fringing.intensity;\\n    }\\n    else {\\n        fringing.intensity = 0;\\n    }\\n};\\nconst anyPostEffectEnabled = (settings) => {\\n    return (settings.sharpness.enabled && settings.sharpness.amount > 0) ||\\n        (settings.bloom.enabled && settings.bloom.intensity > 0) ||\\n        (settings.grading.enabled) ||\\n        (settings.vignette.enabled && settings.vignette.intensity > 0) ||\\n        (settings.fringing.enabled && settings.fringing.intensity > 0);\\n};\\nconst vec = new Vec3();\\n// store the original isColorBufferSrgb so the override in updatePostEffects is idempotent\\nconst origIsColorBufferSrgb = RenderTarget.prototype.isColorBufferSrgb;\\nclass Viewer {\\n    global;\\n    cameraFrame;\\n    inputController;\\n    cameraManager;\\n    picker;\\n    annotations;\\n    forceRenderNextFrame = false;\\n    voxelOverlay = null;\\n    meshOverlay = null;\\n    navCursor = null;\\n    debugPanel = null;\\n    origChunks;\\n    constructor(global, gsplatLoad, skyboxLoad, collisionLoad) {\\n        this.global = global;\\n        const { app, settings, config, events, state, camera, renderer } = global;\\n        const { graphicsDevice } = app;\\n        // render skybox as plain equirect\\n        const glsl = ShaderChunks.get(graphicsDevice, 'glsl');\\n        glsl.set('skyboxPS', patchChunk(glsl.get('skyboxPS'), 'mapRoughnessUv(uv, mipLevel)', 'uv', 'glsl skyboxPS'));\\n        const wgsl = ShaderChunks.get(graphicsDevice, 'wgsl');\\n        wgsl.set('skyboxPS', patchChunk(wgsl.get('skyboxPS'), 'mapRoughnessUv(uv, uniform.mipLevel)', 'uv', 'wgsl skyboxPS'));\\n        this.origChunks = {\\n            glsl: {\\n                gsplatOutputVS: glsl.get('gsplatOutputVS'),\\n                skyboxPS: glsl.get('skyboxPS')\\n            },\\n            wgsl: {\\n                gsplatOutputVS: wgsl.get('gsplatOutputVS'),\\n                skyboxPS: wgsl.get('skyboxPS')\\n            }\\n        };\\n        // disable auto render, we'll render only when camera changes\\n        app.autoRender = false;\\n        // configure the camera\\n        this.configureCamera(settings);\\n        // reconfigure camera when entering/exiting XR\\n        app.xr.on('start', () => this.configureCamera(settings));\\n        app.xr.on('end', () => this.configureCamera(settings));\\n        // construct debug ministats\\n        if (config.ministats) {\\n            const options = MiniStats.getDefaultOptions();\\n            options.cpu.enabled = false;\\n            options.stats = options.stats.filter((s) => s.name !== 'DrawCalls');\\n            options.stats.push({\\n                name: 'VRAM',\\n                stats: ['vram.tex'],\\n                decimalPlaces: 1,\\n                multiplier: 1 / (1024 * 1024),\\n                unitsName: 'MB',\\n                watermark: 1024\\n            }, {\\n                name: 'Splats',\\n                stats: ['frame.gsplats'],\\n                decimalPlaces: 3,\\n                multiplier: 1 / 1000000,\\n                unitsName: 'M',\\n                watermark: 5\\n            });\\n            // eslint-disable-next-line no-new\\n            new MiniStats(app, options);\\n        }\\n        const prevProj = new Mat4();\\n        const prevWorld = new Mat4();\\n        const sceneBound = new BoundingBox();\\n        // track the camera state and trigger a render when it changes\\n        app.on('framerender', () => {\\n            const world = camera.getWorldTransform();\\n            const proj = camera.camera.projectionMatrix;\\n            if (!app.renderNextFrame) {\\n                if (config.ministats ||\\n                    !nearlyEquals(world.data, prevWorld.data) ||\\n                    !nearlyEquals(proj.data, prevProj.data)) {\\n                    app.renderNextFrame = true;\\n                }\\n            }\\n            // suppress rendering till we're ready\\n            if (!state.readyToRender) {\\n                app.renderNextFrame = false;\\n            }\\n            if (this.forceRenderNextFrame) {\\n                app.renderNextFrame = true;\\n            }\\n            if (app.renderNextFrame) {\\n                prevWorld.copy(world);\\n                prevProj.copy(proj);\\n            }\\n        });\\n        const applyCamera = (camera) => {\\n            const cameraEntity = global.camera;\\n            cameraEntity.setPosition(camera.position);\\n            cameraEntity.setEulerAngles(camera.angles);\\n            cameraEntity.camera.fov = camera.fov;\\n            cameraEntity.camera.horizontalFov = graphicsDevice.width > graphicsDevice.height;\\n            // fit clipping planes to bounding box\\n            const boundRadius = sceneBound.halfExtents.length();\\n            // calculate the forward distance between the camera to the bound center\\n            vec.sub2(sceneBound.center, camera.position);\\n            const dist = vec.dot(cameraEntity.forward);\\n            const far = Math.max(dist + boundRadius, 1e-2);\\n            const near = Math.max(dist - boundRadius, far / (1024 * 16));\\n            cameraEntity.camera.farClip = far;\\n            cameraEntity.camera.nearClip = near;\\n        };\\n        // handle application update\\n        app.on('update', (deltaTime) => {\\n            // in xr mode we leave the camera alone\\n            if (app.xr.active) {\\n                return;\\n            }\\n            if (this.inputController && this.cameraManager) {\\n                // update inputs\\n                this.inputController.update(deltaTime, this.cameraManager.camera.distance);\\n                // update cameras\\n                this.cameraManager.update(deltaTime, this.inputController.frame);\\n                // apply to the camera entity\\n                applyCamera(this.cameraManager.camera);\\n            }\\n        });\\n        // Render voxel debug overlay\\n        app.on('prerender', () => {\\n            this.voxelOverlay?.update();\\n        });\\n        // update state on first frame\\n        events.on('firstFrame', () => {\\n            state.loaded = true;\\n            state.animationPaused = !!config.noanim;\\n            window.scrubTo = (time) => {\\n                if (!state.hasAnimation) {\\n                    return Promise.reject(new Error('No animation track'));\\n                }\\n                state.animationPaused = true;\\n                return new Promise((resolve) => {\\n                    events.fire('scrubAnim', time);\\n                    app.renderNextFrame = true;\\n                    app.once('frameend', () => resolve());\\n                });\\n            };\\n            window.animationDuration = state.animationDuration;\\n        });\\n        // wait for the model to load\\n        Promise.all([gsplatLoad, skyboxLoad, collisionLoad]).then((results) => {\\n            const gsplatComponent = results[0].gsplat;\\n            const collision = results[2];\\n            // get scene bounding box\\n            const gsplatBbox = gsplatComponent.customAabb;\\n            if (gsplatBbox) {\\n                sceneBound.setFromTransformedAabb(gsplatBbox, results[0].getWorldTransform());\\n            }\\n            if (!config.noui) {\\n                this.annotations = new Annotations(global, this.cameraFrame != null);\\n            }\\n            this.picker = new Picker(app, camera);\\n            this.inputController = new InputController(global, this.picker);\\n            this.inputController.collision = collision ?? null;\\n            // hasCollision = collision data exists (drives fly-mode collision\\n            // detection and the voxel/mesh debug overlay availability).\\n            // walkAllowed = walk mode is offered to the user; requires both\\n            // collision data and a scene large enough to walk around in.\\n            state.hasCollision = !!collision;\\n            state.walkAllowed = isWalkAllowed(sceneBound, collision ?? null);\\n            // Create collision debug overlay (voxel uses a compute shader, mesh\\n            // uses standard line rendering). The voxel path requires WebGPU.\\n            if (collision instanceof VoxelCollision && renderer !== 'webgl') {\\n                this.voxelOverlay = new VoxelDebugOverlay(app, collision, camera);\\n                this.voxelOverlay.mode = config.heatmap ? 'heatmap' : 'overlay';\\n                state.hasCollisionOverlay = true;\\n                events.on('collisionOverlayEnabled:changed', (value) => {\\n                    this.voxelOverlay.enabled = value;\\n                    app.renderNextFrame = true;\\n                });\\n            }\\n            else if (collision instanceof MeshCollision) {\\n                this.meshOverlay = new MeshDebugOverlay(app, collision, camera, !!this.cameraFrame);\\n                state.hasCollisionOverlay = true;\\n                events.on('collisionOverlayEnabled:changed', (value) => {\\n                    this.meshOverlay.enabled = value;\\n                    app.renderNextFrame = true;\\n                });\\n            }\\n            this.cameraManager = new CameraManager(global, sceneBound, collision);\\n            applyCamera(this.cameraManager.camera);\\n            if (!config.noui) {\\n                this.navCursor = new NavCursor(app, camera, collision ?? null, events, state);\\n            }\\n            this.debugPanel = new DebugPanel(global, this.cameraManager);\\n            const { gsplat } = app.scene;\\n            // quality budget\\n            const budgets = {\\n                mobile: {\\n                    low: 1,\\n                    high: 2\\n                },\\n                desktop: {\\n                    low: 2,\\n                    high: 4\\n                }\\n            };\\n            const applyPerfSettings = () => {\\n                const budget = () => {\\n                    if (config.budget !== undefined && Number.isFinite(config.budget) && config.budget > 0) {\\n                        return config.budget;\\n                    }\\n                    const quality = platform.mobile ? budgets.mobile : budgets.desktop;\\n                    return state.performanceMode ? quality.low : quality.high;\\n                };\\n                gsplat.splatBudget = budget() * 1000000;\\n                gsplat.lodRangeMin = 0;\\n                gsplat.lodRangeMax = 1000;\\n                gsplat.colorUpdateAngle = state.performanceMode ? 4 : 2;\\n                gsplat.minContribution = 1;\\n                gsplat.alphaClip = 1 / 255;\\n                gsplat.antiAlias = config.aa;\\n            };\\n            if (config.fullload) {\\n                // reveal once full quality has finished loading (used for screenshots)\\n                applyPerfSettings();\\n            }\\n            else {\\n                // reveal once low lod has loaded for fastest possible reveal\\n                const resource = results[0].gsplat.resource;\\n                const lodLevels = resource?.octree?.lodLevels;\\n                if (lodLevels) {\\n                    gsplat.lodRangeMax = gsplat.lodRangeMin = lodLevels - 1;\\n                }\\n            }\\n            // these two allow LOD behind camera to drop, saves lots of splats\\n            gsplat.lodUpdateAngle = 90;\\n            gsplat.lodBehindPenalty = 5;\\n            // same performance, but rotating on slow devices does not give us unsorted splats on sides\\n            gsplat.radialSorting = true;\\n            const eventHandler = app.systems.gsplat;\\n            // idle timer: force continuous rendering until 4s of inactivity\\n            let idleTime = 0;\\n            this.forceRenderNextFrame = true;\\n            app.on('update', (dt) => {\\n                idleTime += dt;\\n                this.forceRenderNextFrame = idleTime < 4;\\n            });\\n            events.on('inputEvent', (type) => {\\n                if (type !== 'interact') {\\n                    idleTime = 0;\\n                }\\n            });\\n            eventHandler.on('frame:ready', (_camera, _layer, ready, loading) => {\\n                if (loading > 0 || !ready) {\\n                    idleTime = 0;\\n                }\\n            });\\n            let current = 0;\\n            let watermark = 1;\\n            const readyHandler = (camera, layer, ready, loading) => {\\n                if (ready && loading === 0) {\\n                    // scene is done loading\\n                    eventHandler.off('frame:ready', readyHandler);\\n                    state.readyToRender = true;\\n                    // handle quality mode changes\\n                    events.on('performanceMode:changed', applyPerfSettings);\\n                    applyPerfSettings();\\n                    // debug colorize lods\\n                    gsplat.debug = config.colorize ? GSPLAT_DEBUG_LOD : GSPLAT_DEBUG_NONE;\\n                    gsplat.renderer = rendererTable[renderer];\\n                    // wait for the first valid frame to complete rendering\\n                    app.once('frameend', () => {\\n                        events.fire('firstFrame');\\n                        // emit first frame event on window\\n                        window.firstFrame?.();\\n                    });\\n                }\\n                // update loading status\\n                if (loading !== current) {\\n                    watermark = Math.max(watermark, loading);\\n                    current = watermark - loading;\\n                    state.progress = Math.trunc(current / watermark * 100);\\n                }\\n            };\\n            eventHandler.on('frame:ready', readyHandler);\\n        });\\n    }\\n    // configure camera based on application mode and post process settings\\n    configureCamera(settings) {\\n        const { global } = this;\\n        const { app, config, camera } = global;\\n        const { postEffectSettings } = settings;\\n        const { background } = settings;\\n        // hpr override takes precedence over settings.highPrecisionRendering\\n        const highPrecisionRendering = config.hpr ?? settings.highPrecisionRendering;\\n        const postFxRequested = !config.nofx &&\\n            (anyPostEffectEnabled(postEffectSettings) || highPrecisionRendering);\\n        const enableCameraFrame = !app.xr.active && postFxRequested;\\n        if (enableCameraFrame) {\\n            // create instance\\n            if (!this.cameraFrame) {\\n                this.cameraFrame = new CameraFrame(app, camera.camera);\\n            }\\n            const { cameraFrame } = this;\\n            cameraFrame.enabled = true;\\n            cameraFrame.rendering.toneMapping = tonemapTable[settings.tonemapping];\\n            cameraFrame.rendering.renderFormats = highPrecisionRendering ? [PIXELFORMAT_RGBA16F, PIXELFORMAT_RGBA32F] : [];\\n            applyPostEffectSettings(cameraFrame, postEffectSettings);\\n            cameraFrame.update();\\n            // force gsplat shader to write gamma-space colors\\n            ShaderChunks.get(app.graphicsDevice, 'glsl').set('gsplatOutputVS', gammaChunkGlsl);\\n            ShaderChunks.get(app.graphicsDevice, 'wgsl').set('gsplatOutputVS', gammaChunkWgsl);\\n            // force skybox shader to write gamma-space colors (inline pow replaces the\\n            // gammaCorrectOutput call which is a no-op under CameraFrame's GAMMA_NONE)\\n            ShaderChunks.get(app.graphicsDevice, 'glsl').set('skyboxPS', patchChunk(this.origChunks.glsl.skyboxPS, 'gammaCorrectOutput(toneMap(processEnvironment(linear)))', 'pow(toneMap(processEnvironment(linear)) + 0.0000001, vec3(1.0 / 2.2))', 'glsl skyboxPS gamma override'));\\n            ShaderChunks.get(app.graphicsDevice, 'wgsl').set('skyboxPS', patchChunk(this.origChunks.wgsl.skyboxPS, 'gammaCorrectOutput(toneMap(processEnvironment(linear)))', 'pow(toneMap(processEnvironment(linear)) + 0.0000001, vec3f(1.0 / 2.2))', 'wgsl skyboxPS gamma override'));\\n            // ensure the final compose blit doesn't perform linear->gamma conversion.\\n            RenderTarget.prototype.isColorBufferSrgb = function (index) {\\n                return this === app.graphicsDevice.backBuffer ? true : origIsColorBufferSrgb.call(this, index);\\n            };\\n            camera.camera.clearColor = new Color(background.color);\\n        }\\n        else {\\n            // no post effects needed, destroy camera frame if it exists\\n            if (this.cameraFrame) {\\n                this.cameraFrame.destroy();\\n                this.cameraFrame = null;\\n            }\\n            // restore shader chunks to engine defaults\\n            ShaderChunks.get(app.graphicsDevice, 'glsl').set('gsplatOutputVS', this.origChunks.glsl.gsplatOutputVS);\\n            ShaderChunks.get(app.graphicsDevice, 'wgsl').set('gsplatOutputVS', this.origChunks.wgsl.gsplatOutputVS);\\n            ShaderChunks.get(app.graphicsDevice, 'glsl').set('skyboxPS', this.origChunks.glsl.skyboxPS);\\n            ShaderChunks.get(app.graphicsDevice, 'wgsl').set('skyboxPS', this.origChunks.wgsl.skyboxPS);\\n            // restore original isColorBufferSrgb behavior\\n            RenderTarget.prototype.isColorBufferSrgb = origIsColorBufferSrgb;\\n            if (!app.xr.active) {\\n                camera.camera.toneMapping = tonemapTable[settings.tonemapping];\\n                camera.camera.clearColor = new Color(background.color);\\n            }\\n        }\\n        // Mesh overlay bakes its vertex colors based on the current gamma\\n        // path; reapply when CameraFrame is created/destroyed (e.g. on XR\\n        // start/end) so the overlay tracks the new path.\\n        this.meshOverlay?.setCameraFrameEnabled(!!this.cameraFrame);\\n    }\\n}\\n\\n/** @import { XrInputSource } from 'playcanvas' */\\n\\n/**\\n * Automatically loads and displays WebXR controller models (hands or gamepads) based on the\\n * WebXR Input Profiles specification. The script fetches controller models from the WebXR\\n * Input Profiles asset repository and updates their transforms each frame to match the\\n * tracked input sources.\\n *\\n * Features:\\n * - Automatic controller model loading from WebXR Input Profiles repository\\n * - Support for both hand tracking and gamepad controllers\\n * - Automatic cleanup on input source removal or XR session end\\n * - Visibility control for integration with other XR scripts\\n * - Fires events for controller lifecycle coordination\\n *\\n * This script should be attached to a parent entity (typically the same entity as XrSession).\\n * Use it in conjunction with the `XrNavigation` and `XrMenu` scripts.\\n *\\n * @example\\n * // Add to camera parent entity\\n * cameraParent.addComponent('script');\\n * cameraParent.script.create(XrControllers, {\\n *     properties: {\\n *         basePath: 'https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets/dist/profiles'\\n *     }\\n * });\\n */\\nclass XrControllers extends Script {\\n    static scriptName = 'xrControllers';\\n\\n    /**\\n     * The base URL for fetching the WebXR input profiles.\\n     *\\n     * @attribute\\n     * @type {string}\\n     */\\n    basePath = 'https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets/dist/profiles';\\n\\n    /**\\n     * Map of input sources to their controller data (entity, joint mappings, and asset).\\n     *\\n     * @type {Map<XrInputSource, { entity: import('playcanvas').Entity, jointMap: Map, asset: import('playcanvas').Asset }>}\\n     */\\n    controllers = new Map();\\n\\n    /**\\n     * Set of input sources currently being loaded (to handle race conditions).\\n     *\\n     * @type {Set<XrInputSource>}\\n     * @private\\n     */\\n    _pendingInputSources = new Set();\\n\\n    /**\\n     * Whether controller models are currently visible.\\n     *\\n     * @type {boolean}\\n     * @private\\n     */\\n    _visible = true;\\n\\n    /**\\n     * Bound event handlers for proper cleanup.\\n     *\\n     * @type {{ onAdd: (inputSource: XrInputSource) => void, onRemove: (inputSource: XrInputSource) => void, onXrEnd: () => void } | null}\\n     * @private\\n     */\\n    _handlers = null;\\n\\n    initialize() {\\n        if (!this.app.xr) {\\n            console.error('XrControllers script requires XR to be enabled on the application');\\n            return;\\n        }\\n\\n        // Create bound handlers for proper cleanup\\n        this._handlers = {\\n            onAdd: this._onInputSourceAdd.bind(this),\\n            onRemove: this._onInputSourceRemove.bind(this),\\n            onXrEnd: this._onXrEnd.bind(this)\\n        };\\n\\n        // Listen for input source changes\\n        this.app.xr.input.on('add', this._handlers.onAdd);\\n        this.app.xr.input.on('remove', this._handlers.onRemove);\\n\\n        // Listen for XR session end to clean up all controllers\\n        this.app.xr.on('end', this._handlers.onXrEnd);\\n\\n        // Clean up on script destroy\\n        this.once('destroy', () => {\\n            this._onDestroy();\\n        });\\n    }\\n\\n    /**\\n     * Cleans up all resources when the script is destroyed.\\n     *\\n     * @private\\n     */\\n    _onDestroy() {\\n        if (this._handlers && this.app.xr) {\\n            this.app.xr.input.off('add', this._handlers.onAdd);\\n            this.app.xr.input.off('remove', this._handlers.onRemove);\\n            this.app.xr.off('end', this._handlers.onXrEnd);\\n        }\\n\\n        // Destroy all controller entities\\n        this._destroyAllControllers();\\n\\n        this._handlers = null;\\n        this._pendingInputSources.clear();\\n    }\\n\\n    /**\\n     * Handles XR session end by cleaning up all controllers.\\n     *\\n     * @private\\n     */\\n    _onXrEnd() {\\n        this._destroyAllControllers();\\n        this._pendingInputSources.clear();\\n    }\\n\\n    /**\\n     * Destroys a single controller and its associated resources.\\n     *\\n     * @param {XrInputSource} inputSource - The input source to destroy.\\n     * @private\\n     */\\n    _destroyController(inputSource) {\\n        const controller = this.controllers.get(inputSource);\\n        if (!controller) return;\\n\\n        controller.entity.destroy();\\n\\n        if (controller.asset) {\\n            this.app.assets.remove(controller.asset);\\n            controller.asset.unload();\\n        }\\n\\n        this.controllers.delete(inputSource);\\n        this.app.fire('xr:controller:remove', inputSource);\\n    }\\n\\n    /**\\n     * Destroys all controller entities and clears the map.\\n     *\\n     * @private\\n     */\\n    _destroyAllControllers() {\\n        for (const inputSource of this.controllers.keys()) {\\n            this._destroyController(inputSource);\\n        }\\n    }\\n\\n    /**\\n     * Tries to load profiles sequentially, returning the first successful result.\\n     *\\n     * @param {XrInputSource} inputSource - The input source.\\n     * @param {string[]} profiles - Array of profile IDs to try.\\n     * @param {number} [index=0] - Current index in the profiles array.\\n     * @returns {Promise<{ profileId: string, asset: import('playcanvas').Asset } | null>} The result or null.\\n     * @private\\n     */\\n    async _tryLoadProfiles(inputSource, profiles, index = 0) {\\n        if (index >= profiles.length) return null;\\n        if (!this._pendingInputSources.has(inputSource)) return null;\\n\\n        const result = await this._loadProfile(inputSource, profiles[index]);\\n        if (result) return result;\\n\\n        return this._tryLoadProfiles(inputSource, profiles, index + 1);\\n    }\\n\\n    /**\\n     * Called when an input source is added.\\n     *\\n     * @param {XrInputSource} inputSource - The input source that was added.\\n     * @private\\n     */\\n    async _onInputSourceAdd(inputSource) {\\n        if (!inputSource.profiles?.length) {\\n            console.warn('XrControllers: No profiles available for input source');\\n            return;\\n        }\\n\\n        // Track this input source as pending to handle race conditions\\n        this._pendingInputSources.add(inputSource);\\n\\n        // Load profiles sequentially and stop on first success\\n        const successfulResult = await this._tryLoadProfiles(inputSource, inputSource.profiles);\\n\\n        // Check if input source was removed during loading\\n        if (!this._pendingInputSources.has(inputSource)) {\\n            // Clean up the loaded asset if we got one\\n            if (successfulResult?.asset) {\\n                this.app.assets.remove(successfulResult.asset);\\n                successfulResult.asset.unload();\\n            }\\n            return;\\n        }\\n\\n        // Remove from pending set\\n        this._pendingInputSources.delete(inputSource);\\n\\n        if (successfulResult) {\\n            const { asset } = successfulResult;\\n            const container = asset.resource;\\n            const entity = container.instantiateRenderEntity();\\n            this.app.root.addChild(entity);\\n\\n            // Apply current visibility state\\n            entity.enabled = this._visible;\\n\\n            // Build joint map for hand tracking\\n            const jointMap = new Map();\\n            if (inputSource.hand) {\\n                for (const joint of inputSource.hand.joints) {\\n                    const jointEntity = entity.findByName(joint.id);\\n                    if (jointEntity) {\\n                        jointMap.set(joint, jointEntity);\\n                    }\\n                }\\n            }\\n\\n            this.controllers.set(inputSource, { entity, jointMap, asset });\\n\\n            // Fire event for other scripts to coordinate\\n            this.app.fire('xr:controller:add', inputSource, entity);\\n        } else {\\n            console.warn('XrControllers: No compatible profiles found for input source');\\n        }\\n    }\\n\\n    /**\\n     * Loads a single profile and its model.\\n     *\\n     * @param {XrInputSource} inputSource - The input source.\\n     * @param {string} profileId - The profile ID to load.\\n     * @returns {Promise<{ profileId: string, asset: import('playcanvas').Asset } | null>} The result or null on failure.\\n     * @private\\n     */\\n    async _loadProfile(inputSource, profileId) {\\n        const profileUrl = `${this.basePath}/${profileId}/profile.json`;\\n\\n        try {\\n            const response = await fetch(profileUrl);\\n            if (!response.ok) {\\n                return null;\\n            }\\n\\n            const profile = await response.json();\\n            const layoutPath = profile.layouts[inputSource.handedness]?.assetPath || '';\\n            const assetPath = `${this.basePath}/${profile.profileId}/${inputSource.handedness}${layoutPath.replace(/^\\\\/?(left|right)/, '')}`;\\n\\n            // Load the model\\n            const asset = await new Promise((resolve, reject) => {\\n                this.app.assets.loadFromUrl(assetPath, 'container', (err, asset) => {\\n                    if (err) reject(err);\\n                    else resolve(asset);\\n                });\\n            });\\n\\n            return { profileId, asset };\\n        } catch (error) {\\n            // Silently fail for individual profiles - we'll try the next one\\n            return null;\\n        }\\n    }\\n\\n    /**\\n     * Called when an input source is removed.\\n     *\\n     * @param {XrInputSource} inputSource - The input source that was removed.\\n     * @private\\n     */\\n    _onInputSourceRemove(inputSource) {\\n        // Remove from pending set if still loading\\n        this._pendingInputSources.delete(inputSource);\\n        this._destroyController(inputSource);\\n    }\\n\\n    /**\\n     * Sets the visibility state of controller models.\\n     *\\n     * @type {boolean}\\n     */\\n    set visible(value) {\\n        if (this._visible === value) return;\\n\\n        this._visible = value;\\n\\n        for (const [, controller] of this.controllers) {\\n            controller.entity.enabled = value;\\n        }\\n    }\\n\\n    /**\\n     * Gets the visibility state of controller models.\\n     *\\n     * @type {boolean}\\n     */\\n    get visible() {\\n        return this._visible;\\n    }\\n\\n    update(dt) {\\n        if (!this.app.xr?.active || !this._visible) return;\\n\\n        for (const [inputSource, { entity, jointMap }] of this.controllers) {\\n            if (inputSource.hand) {\\n                // Update hand joint positions\\n                for (const [joint, jointEntity] of jointMap) {\\n                    jointEntity.setPosition(joint.getPosition());\\n                    jointEntity.setRotation(joint.getRotation());\\n                }\\n            } else {\\n                // Update controller position\\n                const position = inputSource.getPosition();\\n                const rotation = inputSource.getRotation();\\n                if (position) entity.setPosition(position);\\n                if (rotation) entity.setRotation(rotation);\\n            }\\n        }\\n    }\\n}\\n\\n/** @import { XrInputSource } from 'playcanvas' */\\n\\n/**\\n * Handles VR navigation with support for teleportation, smooth locomotion, snap or smooth\\n * turning, and snap vertical movement. All methods can be enabled simultaneously, allowing\\n * users to choose their preferred navigation method on the fly.\\n *\\n * Teleportation: Point and teleport using trigger/pinch gestures\\n * Smooth Locomotion: Use left thumbstick for XZ movement\\n * Turning: Right thumbstick X-axis — snap turn (default) or continuous smooth turn, selected\\n *   via {@link XrNavigation#turnMode}\\n * Snap Vertical: Use right thumbstick Y-axis to snap up/down (right grip for larger jumps)\\n *\\n * This script should be attached to a parent entity of the camera entity used for the XR\\n * session. The entity hierarchy should be: XrNavigationEntity > CameraEntity for proper\\n * locomotion handling. Use it in conjunction with the `XrControllers` script.\\n */\\nclass XrNavigation extends Script {\\n    static scriptName = 'xrNavigation';\\n\\n    /**\\n     * Enable teleportation navigation using trigger/pinch gestures.\\n     * @attribute\\n     */\\n    enableTeleport = true;\\n\\n    /**\\n     * Enable smooth locomotion using thumbsticks.\\n     * @attribute\\n     */\\n    enableMove = true;\\n\\n    /**\\n     * Speed of smooth locomotion movement in meters per second.\\n     * @attribute\\n     * @range [0.1, 10]\\n     * @enabledif {enableMove}\\n     */\\n    movementSpeed = 1.5;\\n\\n    /**\\n     * Selects the right-thumbstick turn behaviour. One of:\\n     * - `'snap'`: discrete rotation of {@link XrNavigation#rotateSpeed} degrees per gesture\\n     *   (default; existing behaviour).\\n     * - `'smooth'`: continuous rotation at {@link XrNavigation#smoothTurnSpeed} degrees/second\\n     *   while the thumbstick is past {@link XrNavigation#smoothTurnThreshold}.\\n     * - `'none'`: thumbstick X is ignored.\\n     * @attribute\\n     * @enabledif {enableMove}\\n     */\\n    turnMode = 'snap';\\n\\n    /**\\n     * Angle in degrees for each snap turn. Used when {@link XrNavigation#turnMode} is `'snap'`.\\n     * @attribute\\n     * @range [15, 180]\\n     * @enabledif {enableMove}\\n     */\\n    rotateSpeed = 45;\\n\\n    /**\\n     * Thumbstick deadzone threshold for movement.\\n     * @attribute\\n     * @range [0, 0.5]\\n     * @precision 0.01\\n     * @enabledif {enableMove}\\n     */\\n    movementThreshold = 0.1;\\n\\n    /**\\n     * Thumbstick threshold to trigger snap turning.\\n     * @attribute\\n     * @range [0.1, 1]\\n     * @precision 0.01\\n     * @enabledif {enableMove}\\n     */\\n    rotateThreshold = 0.5;\\n\\n    /**\\n     * Thumbstick threshold to reset snap turn state.\\n     * @attribute\\n     * @range [0.05, 0.5]\\n     * @precision 0.01\\n     * @enabledif {enableMove}\\n     */\\n    rotateResetThreshold = 0.25;\\n\\n    /**\\n     * Rotation speed in degrees per second when {@link XrNavigation#turnMode} is `'smooth'`.\\n     * @attribute\\n     * @range [30, 360]\\n     * @enabledif {enableMove}\\n     */\\n    smoothTurnSpeed = 90;\\n\\n    /**\\n     * Deadzone for the right-thumbstick X-axis when {@link XrNavigation#turnMode} is `'smooth'`.\\n     * Below this magnitude the stick is treated as centred.\\n     * @attribute\\n     * @range [0, 0.5]\\n     * @precision 0.01\\n     * @enabledif {enableMove}\\n     */\\n    smoothTurnThreshold = 0.15;\\n\\n    /**\\n     * Maximum distance for teleportation in meters.\\n     * @attribute\\n     * @range [1, 50]\\n     * @enabledif {enableTeleport}\\n     */\\n    maxTeleportDistance = 10;\\n\\n    /**\\n     * Radius of the teleport target indicator circle.\\n     * @attribute\\n     * @range [0.1, 2]\\n     * @precision 0.1\\n     * @enabledif {enableTeleport}\\n     */\\n    teleportIndicatorRadius = 0.2;\\n\\n    /**\\n     * Number of segments for the teleport indicator circle.\\n     * @attribute\\n     * @range [8, 64]\\n     * @enabledif {enableTeleport}\\n     */\\n    teleportIndicatorSegments = 16;\\n\\n    /**\\n     * Color for valid teleportation areas.\\n     * @attribute\\n     * @enabledif {enableTeleport}\\n     */\\n    validTeleportColor = new Color(0, 1, 0);\\n\\n    /**\\n     * Color for invalid teleportation areas.\\n     * @attribute\\n     * @enabledif {enableTeleport}\\n     */\\n    invalidTeleportColor = new Color(1, 0, 0);\\n\\n    /**\\n     * Color for controller rays.\\n     * @attribute\\n     * @enabledif {enableMove}\\n     */\\n    controllerRayColor = new Color(1, 1, 1);\\n\\n    /**\\n     * Enable snap vertical movement using right thumbstick Y (controllers only).\\n     * @attribute\\n     */\\n    enableSnapVertical = true;\\n\\n    /**\\n     * Height in meters for each vertical snap.\\n     * @attribute\\n     * @range [0.1, 2]\\n     * @precision 0.1\\n     * @enabledif {enableSnapVertical}\\n     */\\n    snapVerticalHeight = 0.5;\\n\\n    /**\\n     * Height in meters for each vertical snap when holding right grip (boost).\\n     * @attribute\\n     * @range [0.5, 10]\\n     * @precision 0.5\\n     * @enabledif {enableSnapVertical}\\n     */\\n    snapVerticalBoostHeight = 2.0;\\n\\n    /**\\n     * Thumbstick Y threshold to trigger vertical snap.\\n     * @attribute\\n     * @range [0.1, 1]\\n     * @precision 0.01\\n     * @enabledif {enableSnapVertical}\\n     */\\n    snapVerticalThreshold = 0.5;\\n\\n    /**\\n     * Thumbstick Y threshold to reset vertical snap state.\\n     * @attribute\\n     * @range [0.05, 0.5]\\n     * @precision 0.01\\n     * @enabledif {enableSnapVertical}\\n     */\\n    snapVerticalResetThreshold = 0.25;\\n\\n    /** @type {Set<XrInputSource>} */\\n    inputSources = new Set();\\n\\n    /** @type {Map<XrInputSource, boolean>} */\\n    activePointers = new Map();\\n\\n    /** @type {Map<XrInputSource, { handleSelectStart: Function, handleSelectEnd: Function }>} */\\n    inputHandlers = new Map();\\n\\n    // Rotation state for snap turning\\n    lastRotateValue = 0;\\n\\n    // Vertical state for snap vertical movement\\n    lastVerticalValue = 0;\\n\\n    // Pre-allocated objects for performance (object pooling)\\n    tmpVec2A = new Vec2();\\n\\n    tmpVec2B = new Vec2();\\n\\n    tmpVec3A = new Vec3();\\n\\n    tmpVec3B = new Vec3();\\n\\n    // Color objects\\n    validColor = new Color();\\n\\n    invalidColor = new Color();\\n\\n    rayColor = new Color();\\n\\n    // Camera reference for movement calculations\\n    /** @type {import('playcanvas').Entity | null} */\\n    cameraEntity = null;\\n\\n    initialize() {\\n        if (!this.app.xr) {\\n            console.error('XrNavigation script requires XR to be enabled on the application');\\n            return;\\n        }\\n\\n        // Log enabled navigation methods\\n        const methods = [];\\n        if (this.enableTeleport) methods.push('teleportation');\\n        if (this.enableMove) methods.push('smooth movement');\\n        if (this.enableSnapVertical) methods.push('snap vertical');\\n        console.log(`XrNavigation: Enabled methods - ${methods.join(', ')}`);\\n\\n        if (!this.enableTeleport && !this.enableMove && !this.enableSnapVertical) {\\n            console.warn('XrNavigation: All navigation methods are disabled. Navigation will not work.');\\n        }\\n\\n        // Initialize color objects from Color attributes\\n        this.validColor.copy(this.validTeleportColor);\\n        this.invalidColor.copy(this.invalidTeleportColor);\\n        this.rayColor.copy(this.controllerRayColor);\\n\\n        // Find camera entity - should be a child of this entity\\n        const cameraComponent = this.entity.findComponent('camera');\\n        this.cameraEntity = cameraComponent ? cameraComponent.entity : null;\\n\\n        if (!this.cameraEntity) {\\n            console.warn('XrNavigation: Camera entity not found. Looking for camera in children...');\\n\\n            // First try to find by name - cast to Entity since we know it should be one\\n            const foundByName = this.entity.findByName('camera');\\n            this.cameraEntity = /** @type {import('playcanvas').Entity | null} */ (foundByName);\\n\\n            // If not found, search children for entity with camera component\\n            if (!this.cameraEntity) {\\n                for (const child of this.entity.children) {\\n                    const childEntity = /** @type {import('playcanvas').Entity} */ (child);\\n                    if (childEntity.camera) {\\n                        this.cameraEntity = childEntity;\\n                        break;\\n                    }\\n                }\\n            }\\n\\n            if (!this.cameraEntity) {\\n                console.error('XrNavigation: No camera entity found. Movement calculations may not work correctly.');\\n            }\\n        }\\n\\n        this.app.xr.input.on('add', (inputSource) => {\\n            const handleSelectStart = () => {\\n                this.activePointers.set(inputSource, true);\\n            };\\n\\n            const handleSelectEnd = () => {\\n                this.activePointers.set(inputSource, false);\\n                this.tryTeleport(inputSource);\\n            };\\n\\n            // Attach the handlers\\n            inputSource.on('selectstart', handleSelectStart);\\n            inputSource.on('selectend', handleSelectEnd);\\n\\n            // Store the handlers in the map\\n            this.inputHandlers.set(inputSource, { handleSelectStart, handleSelectEnd });\\n            this.inputSources.add(inputSource);\\n        });\\n\\n        this.app.xr.input.on('remove', (inputSource) => {\\n            const handlers = this.inputHandlers.get(inputSource);\\n            if (handlers) {\\n                inputSource.off('selectstart', handlers.handleSelectStart);\\n                inputSource.off('selectend', handlers.handleSelectEnd);\\n                this.inputHandlers.delete(inputSource);\\n            }\\n            this.activePointers.delete(inputSource);\\n            this.inputSources.delete(inputSource);\\n        });\\n    }\\n\\n    findPlaneIntersection(origin, direction) {\\n        // Find intersection with y=0 plane\\n        if (Math.abs(direction.y) < 0.00001) return null;  // Ray is parallel to plane\\n\\n        const t = -origin.y / direction.y;\\n        if (t < 0) return null;  // Intersection is behind the ray\\n\\n        return new Vec3(\\n            origin.x + direction.x * t,\\n            0,\\n            origin.z + direction.z * t\\n        );\\n    }\\n\\n    tryTeleport(inputSource) {\\n        const origin = inputSource.getOrigin();\\n        const direction = inputSource.getDirection();\\n\\n        const hitPoint = this.findPlaneIntersection(origin, direction);\\n        if (hitPoint) {\\n            // Adjust for camera's local XZ offset so the user's head ends up at the target\\n            if (this.cameraEntity) {\\n                const cameraLocalPos = this.cameraEntity.getLocalPosition();\\n                hitPoint.x -= cameraLocalPos.x;\\n                hitPoint.z -= cameraLocalPos.z;\\n            }\\n\\n            const cameraY = this.entity.getPosition().y;\\n            hitPoint.y = cameraY;\\n            this.entity.setPosition(hitPoint);\\n        }\\n    }\\n\\n    update(dt) {\\n        // Handle smooth locomotion and snap turning\\n        if (this.enableMove) {\\n            this.handleSmoothLocomotion(dt);\\n        }\\n\\n        // Handle snap vertical movement (controllers only)\\n        if (this.enableSnapVertical) {\\n            this.handleSnapVertical();\\n        }\\n\\n        // Handle teleportation\\n        if (this.enableTeleport) {\\n            this.handleTeleportation();\\n        }\\n\\n        // Always show controller rays for debugging/visualization\\n        this.renderControllerRays();\\n    }\\n\\n    handleSmoothLocomotion(dt) {\\n        if (!this.cameraEntity) return;\\n\\n        for (const inputSource of this.inputSources) {\\n            // Only process controllers with gamepads\\n            if (!inputSource.gamepad) continue;\\n\\n            // Left controller - movement\\n            if (inputSource.handedness === 'left') {\\n                // Get thumbstick input (axes[2] = X, axes[3] = Y)\\n                this.tmpVec2A.set(inputSource.gamepad.axes[2], inputSource.gamepad.axes[3]);\\n\\n                // Check if input exceeds deadzone\\n                if (this.tmpVec2A.length() > this.movementThreshold) {\\n                    this.tmpVec2A.normalize();\\n\\n                    // Calculate camera-relative movement direction\\n                    const forward = this.cameraEntity.forward;\\n                    this.tmpVec2B.x = forward.x;\\n                    this.tmpVec2B.y = forward.z;\\n                    this.tmpVec2B.normalize();\\n\\n                    // Calculate rotation angle based on camera yaw\\n                    const rad = Math.atan2(this.tmpVec2B.x, this.tmpVec2B.y) - Math.PI / 2;\\n\\n                    // Apply rotation to movement vector\\n                    const t = this.tmpVec2A.x * Math.sin(rad) - this.tmpVec2A.y * Math.cos(rad);\\n                    this.tmpVec2A.y = this.tmpVec2A.y * Math.sin(rad) + this.tmpVec2A.x * Math.cos(rad);\\n                    this.tmpVec2A.x = t;\\n\\n                    // Scale by movement speed and delta time\\n                    this.tmpVec2A.mulScalar(this.movementSpeed * dt);\\n\\n                    // Apply movement to camera parent (this entity)\\n                    this.entity.translate(this.tmpVec2A.x, 0, this.tmpVec2A.y);\\n                }\\n            } else if (inputSource.handedness === 'right') { // Right controller - turning\\n                if (this.turnMode === 'smooth') {\\n                    this.handleSmoothTurning(inputSource, dt);\\n                } else if (this.turnMode === 'snap') {\\n                    this.handleSnapTurning(inputSource);\\n                }\\n                // 'none' → thumbstick X is ignored\\n            }\\n        }\\n    }\\n\\n    handleSnapTurning(inputSource) {\\n        // Get rotation input from right thumbstick X-axis\\n        const rotate = -inputSource.gamepad.axes[2];\\n\\n        // Hysteresis system to prevent multiple rotations from single gesture\\n        if (this.lastRotateValue > 0 && rotate < this.rotateResetThreshold) {\\n            this.lastRotateValue = 0;\\n        } else if (this.lastRotateValue < 0 && rotate > -this.rotateResetThreshold) {\\n            this.lastRotateValue = 0;\\n        }\\n\\n        // Only rotate when thumbstick crosses threshold from neutral position\\n        if (this.lastRotateValue === 0 && Math.abs(rotate) > this.rotateThreshold) {\\n            this.lastRotateValue = Math.sign(rotate);\\n\\n            if (this.cameraEntity) {\\n                // Rotate around camera position, not entity origin\\n                this.tmpVec3A.copy(this.cameraEntity.getLocalPosition());\\n                this.entity.translateLocal(this.tmpVec3A);\\n                this.entity.rotateLocal(0, Math.sign(rotate) * this.rotateSpeed, 0);\\n                this.entity.translateLocal(this.tmpVec3A.mulScalar(-1));\\n            }\\n        }\\n    }\\n\\n    /**\\n     * Continuous turn at {@link XrNavigation#smoothTurnSpeed} degrees per second while the\\n     * right thumbstick X-axis is held past {@link XrNavigation#smoothTurnThreshold}. Rotates\\n     * around the camera's local position so the view pivots in place rather than orbiting\\n     * the rig origin.\\n     *\\n     * @param {XrInputSource} inputSource - The right-hand input source.\\n     * @param {number} dt - Frame delta time in seconds.\\n     */\\n    handleSmoothTurning(inputSource, dt) {\\n        const turn = -inputSource.gamepad.axes[2];\\n        if (Math.abs(turn) <= this.smoothTurnThreshold) return;\\n        if (!this.cameraEntity) return;\\n\\n        this.tmpVec3A.copy(this.cameraEntity.getLocalPosition());\\n        this.entity.translateLocal(this.tmpVec3A);\\n        this.entity.rotateLocal(0, turn * this.smoothTurnSpeed * dt, 0);\\n        this.entity.translateLocal(this.tmpVec3A.mulScalar(-1));\\n    }\\n\\n    /**\\n     * Handles snap vertical movement using right thumbstick Y.\\n     * Uses hysteresis to prevent multiple snaps from a single gesture.\\n     * Hold right grip for larger snap height (boost).\\n     *\\n     * @private\\n     */\\n    handleSnapVertical() {\\n        // Find right controller\\n        let rightController = null;\\n\\n        for (const inputSource of this.inputSources) {\\n            if (!inputSource.gamepad) continue;\\n            if (inputSource.handedness === 'right') {\\n                rightController = inputSource;\\n                break;\\n            }\\n        }\\n\\n        if (!rightController || !rightController.gamepad) return;\\n\\n        // Get vertical input from right thumbstick Y axis (negative = up on stick)\\n        const vertical = -rightController.gamepad.axes[3];\\n\\n        // Hysteresis system to prevent multiple snaps from single gesture\\n        if (this.lastVerticalValue > 0 && vertical < this.snapVerticalResetThreshold) {\\n            this.lastVerticalValue = 0;\\n        } else if (this.lastVerticalValue < 0 && vertical > -this.snapVerticalResetThreshold) {\\n            this.lastVerticalValue = 0;\\n        }\\n\\n        // Only snap when thumbstick crosses threshold from neutral position\\n        if (this.lastVerticalValue === 0 && Math.abs(vertical) > this.snapVerticalThreshold) {\\n            this.lastVerticalValue = Math.sign(vertical);\\n\\n            // Check if right grip is held for boost\\n            const rightGripPressed = rightController.gamepad.buttons[1]?.pressed;\\n            const snapHeight = rightGripPressed ?\\n                this.snapVerticalBoostHeight :\\n                this.snapVerticalHeight;\\n\\n            // Apply vertical snap (positive = up, negative = down)\\n            this.entity.translate(0, Math.sign(vertical) * snapHeight, 0);\\n        }\\n    }\\n\\n    handleTeleportation() {\\n        for (const inputSource of this.inputSources) {\\n            // Only show teleportation ray when trigger/select is pressed\\n            if (!this.activePointers.get(inputSource)) continue;\\n\\n            const start = inputSource.getOrigin();\\n            const direction = inputSource.getDirection();\\n\\n            const hitPoint = this.findPlaneIntersection(start, direction);\\n\\n            if (hitPoint && this.isValidTeleportDistance(hitPoint)) {\\n                // Draw line to intersection point\\n                this.app.drawLine(start, hitPoint, this.validColor);\\n                this.drawTeleportIndicator(hitPoint);\\n            } else {\\n                // Draw full length ray if no intersection or invalid distance\\n                this.tmpVec3B.copy(direction).mulScalar(this.maxTeleportDistance).add(start);\\n                this.app.drawLine(start, this.tmpVec3B, this.invalidColor);\\n            }\\n        }\\n    }\\n\\n    renderControllerRays() {\\n        // Only render controller rays when smooth movement is enabled\\n        // (teleport rays are handled separately in handleTeleportation)\\n        if (!this.enableMove) return;\\n\\n        for (const inputSource of this.inputSources) {\\n            // Skip if currently teleporting (handled by handleTeleportation)\\n            if (this.activePointers.get(inputSource)) continue;\\n\\n            const start = inputSource.getOrigin();\\n            this.tmpVec3B.copy(inputSource.getDirection()).mulScalar(2).add(start);\\n            this.app.drawLine(start, this.tmpVec3B, this.rayColor);\\n        }\\n    }\\n\\n    isValidTeleportDistance(hitPoint) {\\n        const distance = hitPoint.distance(this.entity.getPosition());\\n        return distance <= this.maxTeleportDistance;\\n    }\\n\\n    drawTeleportIndicator(point) {\\n        // Draw a circle at the teleport point using configurable attributes\\n        const segments = this.teleportIndicatorSegments;\\n        const radius = this.teleportIndicatorRadius;\\n\\n        for (let i = 0; i < segments; i++) {\\n            const angle1 = (i / segments) * Math.PI * 2;\\n            const angle2 = ((i + 1) / segments) * Math.PI * 2;\\n\\n            const x1 = point.x + Math.cos(angle1) * radius;\\n            const z1 = point.z + Math.sin(angle1) * radius;\\n            const x2 = point.x + Math.cos(angle2) * radius;\\n            const z2 = point.z + Math.sin(angle2) * radius;\\n\\n            // Use pre-allocated vectors to avoid garbage collection\\n            this.tmpVec3A.set(x1, 0.01, z1);  // Slightly above ground to avoid z-fighting\\n            this.tmpVec3B.set(x2, 0.01, z2);\\n\\n            this.app.drawLine(this.tmpVec3A, this.tmpVec3B, this.validColor);\\n        }\\n    }\\n}\\n\\n// On entering/exiting AR, we need to set the camera clear color to transparent black\\nconst initXr = (global) => {\\n    const { app, events, state, camera, renderer } = global;\\n    state.hasAR = app.xr.isAvailable('immersive-ar');\\n    state.hasVR = app.xr.isAvailable('immersive-vr');\\n    // initialize ar/vr\\n    app.xr.on('available:immersive-ar', (available) => {\\n        state.hasAR = available;\\n    });\\n    app.xr.on('available:immersive-vr', (available) => {\\n        state.hasVR = available;\\n    });\\n    // XR sessions require a WebGL device; under WebGPU we only expose availability so\\n    // the UI can offer to reload the viewer in WebGL mode.\\n    if (renderer !== 'webgl') {\\n        return;\\n    }\\n    const parent = camera.parent;\\n    const clearColor = new Color();\\n    const parentPosition = new Vec3();\\n    const parentRotation = new Quat();\\n    const cameraPosition = new Vec3();\\n    const cameraRotation = new Quat();\\n    const angles = new Vec3();\\n    parent.addComponent('script');\\n    parent.script.create(XrControllers);\\n    parent.script.create(XrNavigation);\\n    app.xr.on('start', () => {\\n        app.autoRender = true;\\n        // cache original camera rig positions and rotations\\n        parentPosition.copy(parent.getPosition());\\n        parentRotation.copy(parent.getRotation());\\n        cameraPosition.copy(camera.getPosition());\\n        cameraRotation.copy(camera.getRotation());\\n        cameraRotation.getEulerAngles(angles);\\n        // copy transform to parent to XR/VR mode starts in the right place\\n        parent.setPosition(cameraPosition.x, 0, cameraPosition.z);\\n        parent.setEulerAngles(0, angles.y, 0);\\n        if (app.xr.type === 'immersive-ar') {\\n            clearColor.copy(camera.camera.clearColor);\\n            camera.camera.clearColor = new Color(0, 0, 0, 0);\\n        }\\n    });\\n    app.xr.on('end', () => {\\n        app.autoRender = false;\\n        // restore camera to pre-XR state\\n        parent.setPosition(parentPosition);\\n        parent.setRotation(parentRotation);\\n        camera.setPosition(cameraPosition);\\n        camera.setRotation(cameraRotation);\\n        if (app.xr.type === 'immersive-ar') {\\n            camera.camera.clearColor = clearColor;\\n        }\\n        // Restore the canvas to the correct position in the DOM after exiting XR. In\\n        // some browsers (e.g. Chrome on Android) the canvas is moved to a new root\\n        // during XR, and needs to be moved back on exit.\\n        requestAnimationFrame(() => {\\n            document.body.prepend(app.graphicsDevice.canvas);\\n            app.renderNextFrame = true;\\n        });\\n    });\\n    const start = (type) => {\\n        camera.camera.nearClip = 0.01;\\n        camera.camera.farClip = 1000;\\n        app.xr.start(app.root.findComponent('camera'), type, 'local-floor');\\n    };\\n    events.on('startAR', () => start('immersive-ar'));\\n    events.on('startVR', () => start('immersive-vr'));\\n    events.on('inputEvent', (event) => {\\n        if (event === 'cancel' && app.xr.active) {\\n            app.xr.end();\\n        }\\n    });\\n};\\n\\nconst loadGsplat = async (app, config, progressCallback) => {\\n    const { contents, contentUrl } = config;\\n    const c = contents;\\n    const filename = new URL(contentUrl, location.href).pathname.split('/').pop();\\n    const data = filename.toLowerCase() === 'meta.json' ? await (await contents).json() : undefined;\\n    const asset = new Asset(filename, 'gsplat', { url: contentUrl, filename, contents: c }, data);\\n    return new Promise((resolve, reject) => {\\n        asset.on('load', () => {\\n            const entity = new Entity('gsplat');\\n            entity.setLocalEulerAngles(0, 0, 180);\\n            entity.addComponent('gsplat', {\\n                unified: true,\\n                asset\\n            });\\n            app.root.addChild(entity);\\n            resolve(entity);\\n        });\\n        let watermark = 0;\\n        asset.on('progress', (received, length) => {\\n            const progress = Math.min(1, received / length) * 100;\\n            if (progress > watermark) {\\n                watermark = progress;\\n                progressCallback(Math.trunc(watermark));\\n            }\\n        });\\n        asset.on('error', (err) => {\\n            console.log(err);\\n            reject(err);\\n        });\\n        app.assets.add(asset);\\n        app.assets.load(asset);\\n    });\\n};\\nconst loadSkybox = (app, url) => {\\n    return new Promise((resolve, reject) => {\\n        const asset = new Asset('skybox', 'texture', {\\n            url\\n        }, {\\n            type: 'rgbp',\\n            mipmaps: false,\\n            addressu: 'repeat',\\n            addressv: 'clamp'\\n        });\\n        asset.on('load', () => {\\n            resolve(asset);\\n        });\\n        asset.on('error', (err) => {\\n            console.log(err);\\n            reject(err);\\n        });\\n        app.assets.add(asset);\\n        app.assets.load(asset);\\n    });\\n};\\nconst createApp = async (canvas, config) => {\\n    const useWebGPU = config.renderer === 'webgpu';\\n    // Create the graphics device. The engine auto-appends WebGL2/null fallbacks\\n    // when WebGPU isn't supported, so request xrCompatible so the WebGL fallback\\n    // is also usable for AR/VR.\\n    const device = await createGraphicsDevice(canvas, {\\n        deviceTypes: useWebGPU ? ['webgpu'] : [],\\n        antialias: false,\\n        depth: true,\\n        stencil: false,\\n        xrCompatible: true,\\n        powerPreference: 'high-performance'\\n    });\\n    console.log(`Renderer: ${device.deviceType}`);\\n    // The engine may have fallen back from WebGPU to WebGL2; downstream code\\n    // (voxel overlay, XR, gsplat renderer selection) needs the *actual* renderer.\\n    const renderer = device.deviceType === 'webgpu' ? 'webgpu' : 'webgl';\\n    // Set maxPixelRatio so the XR framebuffer scale factor is computed correctly.\\n    // Regular rendering bypasses maxPixelRatio via the custom initCanvas sizing.\\n    device.maxPixelRatio = window.devicePixelRatio;\\n    // Create the application\\n    const app = new App(canvas, {\\n        graphicsDevice: device,\\n        mouse: new Mouse(canvas),\\n        touch: new TouchDevice$1(canvas),\\n        keyboard: new Keyboard(window)\\n    });\\n    // enable anonymous CORS for image loading in safari (must be set before any\\n    // texture asset starts loading, otherwise the <img> is fetched without the\\n    // crossorigin attribute and WebGL rejects it with SecurityError)\\n    app.loader.getHandler('texture').imgParser.crossOrigin = 'anonymous';\\n    // Create entity hierarchy\\n    const cameraRoot = new Entity('camera root');\\n    app.root.addChild(cameraRoot);\\n    const camera = new Entity('camera');\\n    cameraRoot.addChild(camera);\\n    const light = new Entity('light');\\n    light.setEulerAngles(35, 45, 0);\\n    light.addComponent('light', {\\n        color: new Color(1.0, 0.98, 0.957),\\n        intensity: 1\\n    });\\n    app.root.addChild(light);\\n    app.scene.ambientLight.set(0.51, 0.55, 0.65);\\n    return { app, camera, renderer };\\n};\\n// initialize canvas size and resizing\\nconst initCanvas = (global) => {\\n    const { app, events, state } = global;\\n    const { canvas } = app.graphicsDevice;\\n    // maximum pixel dimension we will allow along the shortest screen dimension based on platform\\n    const maxPixelDim = platform.mobile ? 1080 : 2160;\\n    // cap pixel ratio to limit resolution on high-DPI devices\\n    const calcPixelRatio = () => Math.min(maxPixelDim / Math.min(screen.width, screen.height), window.devicePixelRatio);\\n    // last known device pixel size (full resolution, before any quality scaling)\\n    const deviceSize = { width: 0, height: 0 };\\n    const set = (width, height) => {\\n        const ratio = calcPixelRatio();\\n        deviceSize.width = width * ratio;\\n        deviceSize.height = height * ratio;\\n    };\\n    const apply = () => {\\n        // don't resize the canvas during XR - the XR system manages its own framebuffers\\n        // and resetting canvas dimensions can invalidate the XRWebGLLayer\\n        if (app.xr?.active)\\n            return;\\n        const s = state.performanceMode ? 0.5 : 1.0;\\n        const w = Math.ceil(deviceSize.width * s);\\n        const h = Math.ceil(deviceSize.height * s);\\n        if (w !== canvas.width || h !== canvas.height) {\\n            canvas.width = w;\\n            canvas.height = h;\\n        }\\n    };\\n    const resizeObserver = new ResizeObserver((entries) => {\\n        const e = entries[0]?.contentBoxSize?.[0];\\n        if (e) {\\n            set(e.inlineSize, e.blockSize);\\n            app.renderNextFrame = true;\\n        }\\n    });\\n    resizeObserver.observe(canvas);\\n    events.on('performanceMode:changed', () => {\\n        app.renderNextFrame = true;\\n    });\\n    // Resize canvas before render() so the swap chain texture is acquired at the correct size.\\n    app.on('framerender', apply);\\n    // Disable the engine's built-in canvas resize — we handle it via ResizeObserver\\n    // @ts-ignore\\n    app._allowResize = false;\\n    set(canvas.clientWidth, canvas.clientHeight);\\n    apply();\\n};\\nconst main = async (canvas, settingsJson, config) => {\\n    const { app, camera, renderer } = await createApp(canvas, config);\\n    // create events\\n    const events = new EventHandler();\\n    // migrate legacy `retinaDisplay` preference (inverted) to `performanceMode`\\n    const legacyRetina = localStorage.getItem('retinaDisplay');\\n    if (legacyRetina !== null && localStorage.getItem('performanceMode') === null) {\\n        localStorage.setItem('performanceMode', String(legacyRetina === 'false'));\\n        localStorage.removeItem('retinaDisplay');\\n    }\\n    const storedPerformanceMode = localStorage.getItem('performanceMode');\\n    const state = observe(events, {\\n        loaded: false,\\n        readyToRender: false,\\n        performanceMode: storedPerformanceMode !== null ? storedPerformanceMode === 'true' : platform.mobile,\\n        progress: 0,\\n        inputMode: platform.mobile ? 'touch' : 'desktop',\\n        cameraMode: 'orbit',\\n        hasAnimation: false,\\n        animationDuration: 0,\\n        animationTime: 0,\\n        animationPaused: true,\\n        hasAR: false,\\n        hasVR: false,\\n        hasCollision: false,\\n        hasCollisionOverlay: false,\\n        walkAllowed: false,\\n        collisionOverlayEnabled: false,\\n        isFullscreen: false,\\n        controlsHidden: false,\\n        gamingControls: localStorage.getItem('gamingControls') === 'true'\\n    });\\n    const global = {\\n        app,\\n        settings: importSettings(settingsJson),\\n        config,\\n        state,\\n        events,\\n        camera,\\n        renderer\\n    };\\n    initCanvas(global);\\n    // start the application\\n    app.start();\\n    // Initialize the load-time poster\\n    if (config.poster) {\\n        initPoster(events);\\n    }\\n    camera.addComponent('camera');\\n    // Initialize XR support (availability detection always runs so the UI can offer\\n    // a reload into WebGL when the user requests AR/VR under WebGPU)\\n    initXr(global);\\n    // Initialize user interface\\n    initLocalization();\\n    initUI(global);\\n    // Load model\\n    const gsplatLoad = loadGsplat(app, config, (progress) => {\\n        state.progress = progress;\\n    });\\n    // Load skybox (continue without if it fails — e.g. CORS, 404)\\n    const skyboxLoad = config.skyboxUrl &&\\n        loadSkybox(app, config.skyboxUrl).then((asset) => {\\n            app.scene.envAtlas = asset.resource;\\n        }).catch((err) => {\\n            console.warn('Failed to load skybox:', err);\\n        });\\n    // Load collision data (type determined by file extension)\\n    let collisionLoad;\\n    if (config.collisionUrl) {\\n        const ext = new URL(config.collisionUrl, location.href).pathname.split('.').pop()?.toLowerCase();\\n        if (ext === 'glb') {\\n            collisionLoad = MeshCollision.fromGlb(app, config.collisionUrl).catch((err) => {\\n                console.warn('Failed to load mesh collision:', err);\\n                return null;\\n            });\\n        }\\n        else {\\n            collisionLoad = loadVoxelCollision(config.collisionUrl).catch((err) => {\\n                console.warn('Failed to load voxel data:', err);\\n                return null;\\n            });\\n        }\\n    }\\n    // Load and play sound\\n    if (global.settings.soundUrl) {\\n        const sound = new Audio(global.settings.soundUrl);\\n        sound.crossOrigin = 'anonymous';\\n        document.body.addEventListener('click', () => {\\n            if (sound) {\\n                sound.play();\\n            }\\n        }, {\\n            capture: true,\\n            once: true\\n        });\\n    }\\n    // Create the viewer\\n    return new Viewer(global, gsplatLoad, skyboxLoad, collisionLoad);\\n};\\nconsole.log(`SuperSplat Viewer v${version} | Engine v${version$1} (${revision})`);\\n\\nexport { main };\\n//# sourceMappingURL=index.js.map\\n\";\n\nexport { index$2 as css, index$1 as html, index as js };\n//# sourceMappingURL=index.js.map\n","import { type FileSystem } from './file-system';\n\nconst writeFile = async (fs: FileSystem, filename: string, data: Uint8Array | string) => {\n    const outputFile = await fs.createWriter(filename);\n    await outputFile.write(data instanceof Uint8Array ? data : new TextEncoder().encode(data));\n    await outputFile.close();\n};\n\nexport { writeFile };\n","import { type FileSystem, type Writer } from './file-system';\n\n// write data to a memory buffer\nclass MemoryWriter implements Writer {\n    bytesWritten = 0;\n    write: (data: Uint8Array) => void;\n    close: () => void;\n\n    constructor(onclose: (buffers: Uint8Array[]) => void) {\n        const buffers: Uint8Array[] = [];\n        let buffer: Uint8Array;\n        let cursor = 0;\n\n        this.write = (data: Uint8Array) => {\n            let readcursor = 0;\n\n            while (readcursor < data.byteLength) {\n                const readSize = data.byteLength - readcursor;\n\n                // allocate buffer\n                if (!buffer) {\n                    buffer = new Uint8Array(Math.max(5 * 1024 * 1024, readSize));\n                }\n\n                const writeSize = buffer.byteLength - cursor;\n                const copySize = Math.min(readSize, writeSize);\n\n                buffer.set(data.subarray(readcursor, readcursor + copySize), cursor);\n\n                readcursor += copySize;\n                cursor += copySize;\n\n                if (cursor === buffer.byteLength) {\n                    buffers.push(buffer);\n                    buffer = null;\n                    cursor = 0;\n                }\n            }\n\n            this.bytesWritten += data.byteLength;\n        };\n\n        this.close = () => {\n            if (buffer) {\n                buffers.push(new Uint8Array(buffer.buffer, 0, cursor));\n                buffer = null;\n                cursor = 0;\n            }\n            onclose(buffers);\n        };\n    }\n}\n\n/**\n * A file system that writes files to in-memory buffers.\n *\n * Useful for generating output without writing to disk, such as when\n * creating data for download or further processing.\n *\n * @example\n * ```ts\n * const fs = new MemoryFileSystem();\n * await writeFile({ filename: 'output.ply', ... }, fs);\n *\n * // Get the generated data\n * const data = fs.results.get('output.ply');\n * ```\n */\nclass MemoryFileSystem implements FileSystem {\n    results: Map<string, Uint8Array> = new Map();\n\n    createWriter(filename: string): Writer {\n        return new MemoryWriter((result: Uint8Array[]) => {\n            // combine buffers\n            if (result.length === 1) {\n                this.results.set(filename, result[0]);\n            } else {\n                const combined = new Uint8Array(result.reduce((total, buf) => total + buf.byteLength, 0));\n                let offset = 0;\n                for (let i = 0; i < result.length; ++i) {\n                    combined.set(result[i], offset);\n                    offset += result[i].byteLength;\n                }\n                this.results.set(filename, combined);\n            }\n        });\n    }\n\n    async mkdir(_path: string): Promise<void> {\n        // no-op\n    }\n}\n\nexport { MemoryFileSystem };\n","const crc32_table = (() => {\n    const tbl = [];\n    let c;\n    for (let n = 0; n < 256; n++) {\n        c = n;\n        for (let k = 0; k < 8; k++) {\n            c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));\n        }\n        tbl[n] = c;\n    }\n    return tbl;\n})();\n\nclass Crc {\n    reset: () => void;\n    update: (data: Uint8Array) => void;\n    value: () => number;\n\n    constructor() {\n        let bits = -1;\n        this.update = (data: Uint8Array) => {\n            for (let i = 0; i < data.length; i++) {\n                bits = (bits >>> 8) ^ crc32_table[(bits ^ data[i]) & 0xFF];\n            }\n        };\n        this.value = () => (bits ^ (-1)) >>> 0;\n    }\n}\n\nexport { Crc };\n","import { Crc } from './crc';\nimport { type FileSystem, type Writer } from './file-system';\n\n// https://gist.github.com/rvaiya/4a2192df729056880a027789ae3cd4b7\n\ntype ZipEntry = {\n    filename: Uint8Array;\n    crc: Crc;\n    sizeBytes: number;\n};\n\n// Writer for a single zip entry\nclass ZipEntryWriter implements Writer {\n    write: (data: Uint8Array) => Promise<void>;\n    close: () => Promise<void>;\n    get bytesWritten(): number {\n        return this.entry.sizeBytes;\n    }\n    private entry: ZipEntry;\n\n    constructor(outputWriter: Writer, entry: ZipEntry) {\n        this.entry = entry;\n\n        this.write = async (data: Uint8Array) => {\n            entry.sizeBytes += data.length;\n            entry.crc.update(data);\n            await outputWriter.write(data);\n        };\n\n        this.close = async () => {\n            // no-op, finalization is handled by ZipFileSystem\n        };\n    }\n}\n\n/**\n * A file system that writes files into a ZIP archive.\n *\n * Creates a ZIP file containing all written files. Used internally\n * for bundled output formats like .sog files.\n *\n * @example\n * ```ts\n * const outputWriter = await fs.createWriter('bundle.zip');\n * const zipFs = new ZipFileSystem(outputWriter);\n *\n * // Write files into the zip\n * const writer = await zipFs.createWriter('data.json');\n * await writer.write(jsonData);\n * await writer.close();\n *\n * // Finalize the zip\n * await zipFs.close();\n * ```\n */\nclass ZipFileSystem implements FileSystem {\n    close: () => Promise<void>;\n    createWriter: (filename: string) => Promise<Writer>;\n    mkdir: (path: string) => Promise<void>;\n\n    constructor(writer: Writer) {\n        const textEncoder = new TextEncoder();\n        const files: ZipEntry[] = [];\n        let activeEntry: ZipEntry | null = null;\n\n        const date = new Date();\n        const dosTime = (date.getHours() << 11) | (date.getMinutes() << 5) | Math.floor(date.getSeconds() / 2);\n        const dosDate = ((date.getFullYear() - 1980) << 9) | ((date.getMonth() + 1) << 5) | date.getDate();\n\n        const writeEntryHeader = async (filename: string) => {\n            const filenameBuf = textEncoder.encode(filename);\n            const nameLen = filenameBuf.length;\n\n            const header = new Uint8Array(30 + nameLen);\n            const view = new DataView(header.buffer);\n\n            view.setUint32(0, 0x04034b50, true);\n            view.setUint16(4, 20, true);            // version needed to extract = 2.0\n            view.setUint16(6, 0x8 | 0x800, true);   // indicate crc and size comes after, utf-8 encoding\n            view.setUint16(8, 0, true);             // method = 0 (store)\n            view.setUint16(10, dosTime, true);\n            view.setUint16(12, dosDate, true);\n            view.setUint16(26, nameLen, true);\n            header.set(filenameBuf, 30);\n\n            await writer.write(header);\n\n            const entry: ZipEntry = { filename: filenameBuf, crc: new Crc(), sizeBytes: 0 };\n            files.push(entry);\n            return entry;\n        };\n\n        const writeEntryFooter = async (entry: ZipEntry) => {\n            const { crc, sizeBytes } = entry;\n            const data = new Uint8Array(16);\n            const view = new DataView(data.buffer);\n            view.setUint32(0, 0x08074b50, true);\n            view.setUint32(4, crc.value(), true);\n            view.setUint32(8, sizeBytes, true);\n            view.setUint32(12, sizeBytes, true);\n            await writer.write(data);\n        };\n\n        this.createWriter = async (filename: string): Promise<Writer> => {\n            // Close previous entry if exists\n            if (activeEntry) {\n                await writeEntryFooter(activeEntry);\n                activeEntry = null;\n            }\n\n            // Start new entry\n            const entry = await writeEntryHeader(filename);\n            activeEntry = entry;\n\n            return new ZipEntryWriter(writer, entry);\n        };\n\n        this.mkdir = async (_path: string): Promise<void> => {\n            // No-op for zip - directories are created implicitly from file paths\n        };\n\n        this.close = async () => {\n            // Close last entry if exists\n            if (activeEntry) {\n                await writeEntryFooter(activeEntry);\n                activeEntry = null;\n            }\n\n            // Write central directory records\n            let offset = 0;\n            for (const file of files) {\n                const { filename, crc, sizeBytes } = file;\n                const nameLen = filename.length;\n\n                const cdr = new Uint8Array(46 + nameLen);\n                const view = new DataView(cdr.buffer);\n                view.setUint32(0, 0x02014b50, true);\n                view.setUint16(4, 20, true);\n                view.setUint16(6, 20, true);\n                view.setUint16(8, 0x8 | 0x800, true);\n                view.setUint16(10, 0, true);\n                view.setUint16(12, dosTime, true);\n                view.setUint16(14, dosDate, true);\n                view.setUint32(16, crc.value(), true);\n                view.setUint32(20, sizeBytes, true);\n                view.setUint32(24, sizeBytes, true);\n                view.setUint16(28, nameLen, true);\n                view.setUint32(42, offset, true);\n                cdr.set(filename, 46);\n\n                await writer.write(cdr);\n\n                offset += 30 + nameLen + sizeBytes + 16; // 30 local header + name + data + 16 descriptor\n            }\n\n            const filenameLength = files.reduce((tot, file) => tot + file.filename.length, 0);\n            const dataLength = files.reduce((tot, file) => tot + file.sizeBytes, 0);\n\n            // Write end of central directory record\n            const eocd = new Uint8Array(22);\n            const eocdView = new DataView(eocd.buffer);\n            eocdView.setUint32(0, 0x06054b50, true);\n            eocdView.setUint16(8, files.length, true);\n            eocdView.setUint16(10, files.length, true);\n            eocdView.setUint32(12, filenameLength + files.length * 46, true);\n            eocdView.setUint32(16, filenameLength + files.length * (30 + 16) + dataLength, true);\n\n            await writer.write(eocd);\n\n            // Close the underlying writer\n            await writer.close();\n        };\n    }\n}\n\nexport { ZipFileSystem };\n","import { DataTable } from '../data-table';\nimport { quickselect } from '../utils';\n\nclass Aabb {\n    min: number[];\n    max: number[];\n\n    constructor(min: number[] = [], max: number[] = []) {\n        this.min = min;\n        this.max = max;\n    }\n\n    largestAxis(): number {\n        const { min, max } = this;\n        const { length } = min;\n        let result = -1;\n        let l = -Infinity;\n        for (let i = 0; i < length; ++i) {\n            const e = max[i] - min[i];\n            if (e > l) {\n                l = e;\n                result = i;\n            }\n        }\n        return result;\n    }\n\n    largestDim(): number {\n        const a = this.largestAxis();\n        return this.max[a] - this.min[a];\n    }\n\n    fromCentroids(centroids: DataTable, indices: Uint32Array) {\n        const { columns, numColumns } = centroids;\n        const { min, max } = this;\n        for (let j = 0; j < numColumns; j++) {\n            const data = columns[j].data;\n            let m = Infinity;\n            let M = -Infinity;\n            for (let i = 0; i < indices.length; i++) {\n                const v = data[indices[i]];\n                m = v < m ? v : m;\n                M = v > M ? v : M;\n            }\n            min[j] = m;\n            max[j] = M;\n        }\n        return this;\n    }\n}\n\ninterface BTreeNode {\n    count: number;\n    aabb: Aabb;\n    indices?: Uint32Array;       // only for leaf nodes\n    left?: BTreeNode;\n    right?: BTreeNode;\n}\n\nclass BTree {\n    centroids: DataTable;\n    root: BTreeNode;\n\n    constructor(centroids: DataTable) {\n        const recurse = (indices: Uint32Array): BTreeNode => {\n            const aabb = new Aabb().fromCentroids(centroids, indices);\n\n            if (indices.length <= 256) {\n                return {\n                    count: indices.length,\n                    aabb,\n                    indices\n                };\n            }\n\n            const col = aabb.largestAxis();\n            const values = centroids.columns[col].data;\n            const mid = indices.length >>> 1;\n\n            quickselect(values, indices, mid);\n\n            const left = recurse(indices.subarray(0, mid));\n            const right = recurse(indices.subarray(mid));\n\n            return {\n                count: left.count + right.count,\n                aabb,\n                left,\n                right\n            };\n        };\n\n        const { numRows } = centroids;\n        const indices = new Uint32Array(numRows);\n        for (let i = 0; i < numRows; ++i) {\n            indices[i] = i;\n        }\n\n        this.centroids = centroids;\n        this.root = recurse(indices);\n    }\n}\n\nexport { BTreeNode, BTree };\n","import { Vec3 } from 'playcanvas';\n\nimport { DataTable, type TypedArray } from '../data-table';\nimport { quickselect } from '../utils';\n\n/**\n * Axis-aligned bounding box for BVH nodes.\n */\ninterface BVHBounds {\n    minX: number;\n    minY: number;\n    minZ: number;\n    maxX: number;\n    maxY: number;\n    maxZ: number;\n}\n\n/**\n * BVH node for Gaussian AABBs.\n */\ninterface GaussianBVHNode {\n    /** Number of Gaussians in this subtree */\n    count: number;\n\n    /** Bounds of all Gaussian AABBs in this subtree */\n    bounds: BVHBounds;\n\n    /** Gaussian indices (only for leaf nodes) */\n    indices?: Uint32Array;\n\n    /** Left child (only for interior nodes) */\n    left?: GaussianBVHNode;\n\n    /** Right child (only for interior nodes) */\n    right?: GaussianBVHNode;\n}\n\n/**\n * Check if two AABBs overlap.\n *\n * @param a - First AABB (BVHBounds object)\n * @param bMinX - Second AABB minimum X\n * @param bMinY - Second AABB minimum Y\n * @param bMinZ - Second AABB minimum Z\n * @param bMaxX - Second AABB maximum X\n * @param bMaxY - Second AABB maximum Y\n * @param bMaxZ - Second AABB maximum Z\n * @returns True if the AABBs overlap\n */\nconst boundsOverlap = (a: BVHBounds, bMinX: number, bMinY: number, bMinZ: number, bMaxX: number, bMaxY: number, bMaxZ: number): boolean => {\n    return !(a.maxX < bMinX || a.minX > bMaxX ||\n             a.maxY < bMinY || a.minY > bMaxY ||\n             a.maxZ < bMinZ || a.minZ > bMaxZ);\n};\n\n/**\n * BVH (Bounding Volume Hierarchy) for efficient spatial queries on Gaussian AABBs.\n *\n * Unlike the centroid-based BTree, this BVH stores the full AABB for each node,\n * computed from position +/- extent for all Gaussians in the subtree.\n */\nclass GaussianBVH {\n    /** Root node of the BVH */\n    root: GaussianBVHNode;\n\n    /** Position data from the original DataTable */\n    private x: TypedArray;\n    private y: TypedArray;\n    private z: TypedArray;\n\n    /** Extent data */\n    private extentX: TypedArray;\n    private extentY: TypedArray;\n    private extentZ: TypedArray;\n\n    /** Maximum leaf size */\n    private static readonly MAX_LEAF_SIZE = 64;\n\n    /**\n     * Construct a BVH from Gaussian data.\n     *\n     * @param dataTable - DataTable containing position (x, y, z) columns\n     * @param extents - DataTable containing extent (extent_x, extent_y, extent_z) columns\n     */\n    constructor(dataTable: DataTable, extents: DataTable) {\n        // Cache column data for fast access\n        this.x = dataTable.getColumnByName('x').data;\n        this.y = dataTable.getColumnByName('y').data;\n        this.z = dataTable.getColumnByName('z').data;\n        this.extentX = extents.getColumnByName('extent_x').data;\n        this.extentY = extents.getColumnByName('extent_y').data;\n        this.extentZ = extents.getColumnByName('extent_z').data;\n\n        const numRows = dataTable.numRows;\n        const indices = new Uint32Array(numRows);\n        for (let i = 0; i < numRows; i++) {\n            indices[i] = i;\n        }\n\n        this.root = this.buildNode(indices);\n    }\n\n    /**\n     * Compute the AABB that bounds all Gaussian AABBs for the given indices.\n     *\n     * @param indices - Array of Gaussian indices\n     * @returns The bounding box that contains all specified Gaussians\n     */\n    private computeBounds(indices: Uint32Array): BVHBounds {\n        const { x, y, z, extentX, extentY, extentZ } = this;\n\n        let minX = Infinity;\n        let minY = Infinity;\n        let minZ = Infinity;\n        let maxX = -Infinity;\n        let maxY = -Infinity;\n        let maxZ = -Infinity;\n\n        for (let i = 0; i < indices.length; i++) {\n            const idx = indices[i];\n            const gMinX = x[idx] - extentX[idx];\n            const gMinY = y[idx] - extentY[idx];\n            const gMinZ = z[idx] - extentZ[idx];\n            const gMaxX = x[idx] + extentX[idx];\n            const gMaxY = y[idx] + extentY[idx];\n            const gMaxZ = z[idx] + extentZ[idx];\n\n            if (gMinX < minX) minX = gMinX;\n            if (gMinY < minY) minY = gMinY;\n            if (gMinZ < minZ) minZ = gMinZ;\n            if (gMaxX > maxX) maxX = gMaxX;\n            if (gMaxY > maxY) maxY = gMaxY;\n            if (gMaxZ > maxZ) maxZ = gMaxZ;\n        }\n\n        return { minX, minY, minZ, maxX, maxY, maxZ };\n    }\n\n    /**\n     * Build a BVH node recursively.\n     *\n     * @param indices - Array of Gaussian indices to include in this subtree\n     * @returns The constructed BVH node\n     */\n    private buildNode(indices: Uint32Array): GaussianBVHNode {\n        const bounds = this.computeBounds(indices);\n\n        // Create leaf node if small enough\n        if (indices.length <= GaussianBVH.MAX_LEAF_SIZE) {\n            return {\n                count: indices.length,\n                bounds,\n                indices\n            };\n        }\n\n        // Find the largest axis to split on (based on centroid positions for better balance)\n        const { x, y, z } = this;\n        let centroidMinX = Infinity, centroidMaxX = -Infinity;\n        let centroidMinY = Infinity, centroidMaxY = -Infinity;\n        let centroidMinZ = Infinity, centroidMaxZ = -Infinity;\n\n        for (let i = 0; i < indices.length; i++) {\n            const idx = indices[i];\n            const px = x[idx];\n            const py = y[idx];\n            const pz = z[idx];\n\n            if (px < centroidMinX) centroidMinX = px;\n            if (px > centroidMaxX) centroidMaxX = px;\n            if (py < centroidMinY) centroidMinY = py;\n            if (py > centroidMaxY) centroidMaxY = py;\n            if (pz < centroidMinZ) centroidMinZ = pz;\n            if (pz > centroidMaxZ) centroidMaxZ = pz;\n        }\n\n        const extX = centroidMaxX - centroidMinX;\n        const extY = centroidMaxY - centroidMinY;\n        const extZ = centroidMaxZ - centroidMinZ;\n\n        // Choose axis with largest extent\n        let splitAxis: TypedArray;\n        if (extX >= extY && extX >= extZ) {\n            splitAxis = x;\n        } else if (extY >= extZ) {\n            splitAxis = y;\n        } else {\n            splitAxis = z;\n        }\n\n        // Partition around median\n        const mid = indices.length >>> 1;\n        quickselect(splitAxis, indices, mid);\n\n        // Recursively build children\n        const left = this.buildNode(indices.subarray(0, mid));\n        const right = this.buildNode(indices.subarray(mid));\n\n        return {\n            count: left.count + right.count,\n            bounds,\n            left,\n            right\n        };\n    }\n\n    /**\n     * Query all Gaussian indices whose AABBs overlap the given box.\n     *\n     * @param boxMin - Minimum corner of query box\n     * @param boxMax - Maximum corner of query box\n     * @returns Array of Gaussian indices that overlap the box\n     */\n    queryOverlapping(boxMin: Vec3, boxMax: Vec3): number[] {\n        const result: number[] = [];\n        this.queryNode(this.root, boxMin.x, boxMin.y, boxMin.z, boxMax.x, boxMax.y, boxMax.z, result);\n        return result;\n    }\n\n    /**\n     * Query all Gaussian indices whose AABBs overlap the given box (using raw coordinates).\n     *\n     * @param minX - Minimum X of query box\n     * @param minY - Minimum Y of query box\n     * @param minZ - Minimum Z of query box\n     * @param maxX - Maximum X of query box\n     * @param maxY - Maximum Y of query box\n     * @param maxZ - Maximum Z of query box\n     * @returns Array of Gaussian indices that overlap the box\n     */\n    queryOverlappingRaw(minX: number, minY: number, minZ: number, maxX: number, maxY: number, maxZ: number): number[] {\n        const result: number[] = [];\n        this.queryNode(this.root, minX, minY, minZ, maxX, maxY, maxZ, result);\n        return result;\n    }\n\n    /**\n     * Query all Gaussian indices whose AABBs intersect a view frustum\n     * defined by 6 planes. Each plane is `(nx, ny, nz, d)` and points into\n     * the frustum: a point is inside the frustum iff `n · p >= d` for every\n     * plane. An AABB is rejected only when it lies fully on the negative\n     * side of some plane.\n     *\n     * Writes matching indices into `result` starting at `offset`, stopping\n     * if the buffer fills up. The total match count is still returned even\n     * when the buffer is too small, so the caller can grow and retry.\n     * Mirrors the `queryOverlappingRawInto` contract.\n     *\n     * @param planes - 24 floats (6 planes × 4 floats: nx, ny, nz, d).\n     * @param result - Output buffer of Gaussian indices.\n     * @param offset - Starting element offset in `result`.\n     * @returns Number of matching Gaussian indices.\n     */\n    queryFrustumRawInto(\n        planes: Float32Array,\n        result: Uint32Array,\n        offset: number\n    ): number {\n        return this.queryFrustumNode(this.root, planes, result, offset, 0);\n    }\n\n    /**\n     * Recursive frustum-plane query helper.\n     *\n     * @param node - Current BVH node.\n     * @param planes - 24 floats (6 planes × 4 floats).\n     * @param result - Buffer to append matching indices into.\n     * @param offset - Starting element offset in `result`.\n     * @param count - Number of matches already written for this query.\n     * @returns Updated match count.\n     */\n    private queryFrustumNode(\n        node: GaussianBVHNode,\n        planes: Float32Array,\n        result: Uint32Array,\n        offset: number,\n        count: number\n    ): number {\n        const b = node.bounds;\n        // Test node AABB against each frustum plane: reject only if the\n        // \"positive vertex\" (the AABB corner most aligned with the plane\n        // normal) lies on the negative side. If so the whole AABB is out.\n        for (let p = 0; p < 6; p++) {\n            const i = p * 4;\n            const nx = planes[i];\n            const ny = planes[i + 1];\n            const nz = planes[i + 2];\n            const d = planes[i + 3];\n            const px = nx >= 0 ? b.maxX : b.minX;\n            const py = ny >= 0 ? b.maxY : b.minY;\n            const pz = nz >= 0 ? b.maxZ : b.minZ;\n            if (nx * px + ny * py + nz * pz < d) {\n                return count;\n            }\n        }\n\n        if (node.indices) {\n            const { x, y, z, extentX, extentY, extentZ } = this;\n            for (let i = 0; i < node.indices.length; i++) {\n                const idx = node.indices[i];\n                const gMinX = x[idx] - extentX[idx];\n                const gMinY = y[idx] - extentY[idx];\n                const gMinZ = z[idx] - extentZ[idx];\n                const gMaxX = x[idx] + extentX[idx];\n                const gMaxY = y[idx] + extentY[idx];\n                const gMaxZ = z[idx] + extentZ[idx];\n\n                let outside = false;\n                for (let p = 0; p < 6; p++) {\n                    const ii = p * 4;\n                    const nx = planes[ii];\n                    const ny = planes[ii + 1];\n                    const nz = planes[ii + 2];\n                    const d = planes[ii + 3];\n                    const px = nx >= 0 ? gMaxX : gMinX;\n                    const py = ny >= 0 ? gMaxY : gMinY;\n                    const pz = nz >= 0 ? gMaxZ : gMinZ;\n                    if (nx * px + ny * py + nz * pz < d) {\n                        outside = true;\n                        break;\n                    }\n                }\n                if (!outside) {\n                    const writeIdx = offset + count;\n                    if (writeIdx < result.length) {\n                        result[writeIdx] = idx;\n                    }\n                    count++;\n                }\n            }\n            return count;\n        }\n\n        if (node.left) {\n            count = this.queryFrustumNode(node.left, planes, result, offset, count);\n        }\n        if (node.right) {\n            count = this.queryFrustumNode(node.right, planes, result, offset, count);\n        }\n        return count;\n    }\n\n    /**\n     * Query overlapping Gaussian indices directly into a caller-provided buffer.\n     *\n     * Returns the total number of matches even if the target buffer is too\n     * small; in that case only the prefix that fits is written and the caller\n     * can grow the buffer then retry.\n     *\n     * @param minX - Minimum X of query box\n     * @param minY - Minimum Y of query box\n     * @param minZ - Minimum Z of query box\n     * @param maxX - Maximum X of query box\n     * @param maxY - Maximum Y of query box\n     * @param maxZ - Maximum Z of query box\n     * @param result - Buffer to append matching Gaussian indices into.\n     * @param offset - Starting element offset in `result`.\n     * @returns Number of matching Gaussian indices.\n     */\n    queryOverlappingRawInto(\n        minX: number,\n        minY: number,\n        minZ: number,\n        maxX: number,\n        maxY: number,\n        maxZ: number,\n        result: Uint32Array,\n        offset: number\n    ): number {\n        return this.queryNodeInto(this.root, minX, minY, minZ, maxX, maxY, maxZ, result, offset, 0);\n    }\n\n    /**\n     * Recursive query helper.\n     *\n     * @param node - Current BVH node to query\n     * @param minX - Query box minimum X\n     * @param minY - Query box minimum Y\n     * @param minZ - Query box minimum Z\n     * @param maxX - Query box maximum X\n     * @param maxY - Query box maximum Y\n     * @param maxZ - Query box maximum Z\n     * @param result - Array to append matching indices to\n     */\n    private queryNode(\n        node: GaussianBVHNode,\n        minX: number,\n        minY: number,\n        minZ: number,\n        maxX: number,\n        maxY: number,\n        maxZ: number,\n        result: number[]\n    ): void {\n        // Early exit if node bounds don't overlap query box\n        if (!boundsOverlap(node.bounds, minX, minY, minZ, maxX, maxY, maxZ)) {\n            return;\n        }\n\n        // Leaf node: check each Gaussian individually\n        if (node.indices) {\n            const { x, y, z, extentX, extentY, extentZ } = this;\n\n            for (let i = 0; i < node.indices.length; i++) {\n                const idx = node.indices[i];\n                const gMinX = x[idx] - extentX[idx];\n                const gMinY = y[idx] - extentY[idx];\n                const gMinZ = z[idx] - extentZ[idx];\n                const gMaxX = x[idx] + extentX[idx];\n                const gMaxY = y[idx] + extentY[idx];\n                const gMaxZ = z[idx] + extentZ[idx];\n\n                // Check overlap\n                if (!(gMaxX < minX || gMinX > maxX ||\n                      gMaxY < minY || gMinY > maxY ||\n                      gMaxZ < minZ || gMinZ > maxZ)) {\n                    result.push(idx);\n                }\n            }\n            return;\n        }\n\n        // Interior node: recurse into children\n        if (node.left) {\n            this.queryNode(node.left, minX, minY, minZ, maxX, maxY, maxZ, result);\n        }\n        if (node.right) {\n            this.queryNode(node.right, minX, minY, minZ, maxX, maxY, maxZ, result);\n        }\n    }\n\n    /**\n     * Recursive typed-buffer query helper.\n     *\n     * @param node - Current BVH node to query\n     * @param minX - Query box minimum X\n     * @param minY - Query box minimum Y\n     * @param minZ - Query box minimum Z\n     * @param maxX - Query box maximum X\n     * @param maxY - Query box maximum Y\n     * @param maxZ - Query box maximum Z\n     * @param result - Buffer to append matching indices into\n     * @param offset - Starting element offset in `result`\n     * @param count - Number of matches already found for this query\n     * @returns Updated match count\n     */\n    private queryNodeInto(\n        node: GaussianBVHNode,\n        minX: number,\n        minY: number,\n        minZ: number,\n        maxX: number,\n        maxY: number,\n        maxZ: number,\n        result: Uint32Array,\n        offset: number,\n        count: number\n    ): number {\n        if (!boundsOverlap(node.bounds, minX, minY, minZ, maxX, maxY, maxZ)) {\n            return count;\n        }\n\n        if (node.indices) {\n            const { x, y, z, extentX, extentY, extentZ } = this;\n\n            for (let i = 0; i < node.indices.length; i++) {\n                const idx = node.indices[i];\n                const gMinX = x[idx] - extentX[idx];\n                const gMinY = y[idx] - extentY[idx];\n                const gMinZ = z[idx] - extentZ[idx];\n                const gMaxX = x[idx] + extentX[idx];\n                const gMaxY = y[idx] + extentY[idx];\n                const gMaxZ = z[idx] + extentZ[idx];\n\n                if (!(gMaxX < minX || gMinX > maxX ||\n                      gMaxY < minY || gMinY > maxY ||\n                      gMaxZ < minZ || gMinZ > maxZ)) {\n                    const writeIdx = offset + count;\n                    if (writeIdx < result.length) {\n                        result[writeIdx] = idx;\n                    }\n                    count++;\n                }\n            }\n            return count;\n        }\n\n        if (node.left) {\n            count = this.queryNodeInto(node.left, minX, minY, minZ, maxX, maxY, maxZ, result, offset, count);\n        }\n        if (node.right) {\n            count = this.queryNodeInto(node.right, minX, minY, minZ, maxX, maxY, maxZ, result, offset, count);\n        }\n        return count;\n    }\n\n    /**\n     * Get the total number of Gaussians in the BVH.\n     *\n     * @returns The total count of Gaussians\n     */\n    get count(): number {\n        return this.root.count;\n    }\n\n    /**\n     * Get the bounds of the entire scene.\n     *\n     * @returns The scene bounding box\n     */\n    get sceneBounds(): BVHBounds {\n        return this.root.bounds;\n    }\n}\n\nexport { GaussianBVH, GaussianBVHNode, BVHBounds };\n","import {\n    BUFFERUSAGE_COPY_DST,\n    BUFFERUSAGE_COPY_SRC,\n    SHADERLANGUAGE_WGSL,\n    SHADERSTAGE_COMPUTE,\n    UNIFORMTYPE_UINT,\n    BindGroupFormat,\n    BindStorageBufferFormat,\n    BindUniformBufferFormat,\n    Compute,\n    FloatPacking,\n    Shader,\n    StorageBuffer,\n    UniformBufferFormat,\n    UniformFormat,\n    GraphicsDevice\n} from 'playcanvas';\n\nimport { DataTable } from '../data-table';\n\nconst clusterWgsl = (numColumns: number, useF16: boolean) => {\n    const floatType = useF16 ? 'f16' : 'f32';\n\n    return /* wgsl */ `\n${useF16 ? 'enable f16;' : ''}\n\nstruct Uniforms {\n    numPoints: u32,\n    numCentroids: u32\n};\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var<storage, read> points: array<${floatType}>;\n@group(0) @binding(2) var<storage, read> centroids: array<${floatType}>;\n@group(0) @binding(3) var<storage, read_write> results: array<u32>;\n\nconst numColumns = ${numColumns};   // number of columns in the points and centroids tables\nconst chunkSize = 128u;             // must be a multiple of 64\nvar<workgroup> sharedChunk: array<${floatType}, numColumns * chunkSize>;\n\n// calculate the squared distance between the point and centroid\nfn calcDistanceSqr(point: array<${floatType}, numColumns>, centroid: u32) -> f32 {\n    var result = 0.0;\n\n    var ci = centroid * numColumns;\n\n    for (var i = 0u; i < numColumns; i++) {\n        let v = f32(point[i] - sharedChunk[ci+i]);\n        result += v * v;\n    }\n\n    return result;\n}\n\n@compute @workgroup_size(64)\nfn main(\n    @builtin(local_invocation_index) local_id : u32,\n    @builtin(global_invocation_id) global_id: vec3u,\n    @builtin(num_workgroups) num_workgroups: vec3u\n) {\n    // calculate row index for this thread point\n    let pointIndex = global_id.x + global_id.y * num_workgroups.x * 64u;\n\n    // copy the point data from global memory\n    var point: array<${floatType}, numColumns>;\n    if (pointIndex < uniforms.numPoints) {\n        for (var i = 0u; i < numColumns; i++) {\n            point[i] = points[pointIndex * numColumns + i];\n        }\n    }\n\n    var mind = 1000000.0;\n    var mini = 0u;\n\n    // work through the list of centroids in shared memory chunks\n    let numChunks = u32(ceil(f32(uniforms.numCentroids) / f32(chunkSize)));\n    for (var i = 0u; i < numChunks; i++) {\n\n        // copy this thread's slice of the centroid shared chunk data\n        let dstRow = local_id * (chunkSize / 64u);\n        let srcRow = min(uniforms.numCentroids, i * chunkSize + local_id * chunkSize / 64u);\n        let numRows = min(uniforms.numCentroids, srcRow + chunkSize / 64u) - srcRow;\n\n        var dst = dstRow * numColumns;\n        var src = srcRow * numColumns;\n\n        for (var c = 0u; c < numRows * numColumns; c++) {\n            sharedChunk[dst + c] = centroids[src + c];\n        }\n\n        // wait for all threads to finish writing their part of centroids shared memory buffer\n        workgroupBarrier();\n\n        // loop over the next chunk of centroids finding the closest\n        if (pointIndex < uniforms.numPoints) {\n            let thisChunkSize = min(chunkSize, uniforms.numCentroids - i * chunkSize);\n            for (var c = 0u; c < thisChunkSize; c++) {\n                let d = calcDistanceSqr(point, c);\n                if (d < mind) {\n                    mind = d;\n                    mini = i * chunkSize + c;\n                }\n            }\n        }\n\n        // next loop will overwrite the shared memory, so wait\n        workgroupBarrier();\n    }\n\n    if (pointIndex < uniforms.numPoints) {\n        results[pointIndex] = mini;\n    }\n}\n`;\n};\n\nconst roundUp = (value: number, multiple: number) => {\n    return Math.ceil(value / multiple) * multiple;\n};\n\nconst interleaveData = (result: Uint16Array | Float32Array, dataTable: DataTable, numRows: number, rowOffset: number) => {\n    const { numColumns } = dataTable;\n\n    if (result instanceof Uint16Array) {\n        // interleave shorts\n        for (let c = 0; c < numColumns; ++c) {\n            const column = dataTable.columns[c];\n            for (let r = 0; r < numRows; ++r) {\n                result[r * numColumns + c] = FloatPacking.float2Half(column.data[rowOffset + r]);\n            }\n        }\n    } else {\n        // interleave floats\n        for (let c = 0; c < numColumns; ++c) {\n            const column = dataTable.columns[c];\n            for (let r = 0; r < numRows; ++r) {\n                result[r * numColumns + c] = column.data[rowOffset + r];\n            }\n        }\n    }\n};\n\nclass GpuClustering {\n    execute: (points: DataTable, centroids: DataTable, labels: Uint32Array) => Promise<void>;\n    destroy: () => void;\n\n    constructor(device: GraphicsDevice, numColumns: number, numCentroids: number) {\n\n        // Check if device supports f16\n        const useF16 = !!('supportsShaderF16' in device && device.supportsShaderF16);\n\n        const workgroupSize = 64;\n        const workgroupsPerBatch = 1024;\n        const batchSize = workgroupsPerBatch * workgroupSize;\n\n        const bindGroupFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('pointsBuffer', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('centroidsBuffer', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('resultsBuffer', SHADERSTAGE_COMPUTE)\n        ]);\n\n        const shader = new Shader(device, {\n            name: 'compute-cluster',\n            shaderLanguage: SHADERLANGUAGE_WGSL,\n            cshader: clusterWgsl(numColumns, useF16),\n            // @ts-ignore\n            computeUniformBufferFormats: {\n                uniforms: new UniformBufferFormat(device, [\n                    new UniformFormat('numPoints', UNIFORMTYPE_UINT),\n                    new UniformFormat('numCentroids', UNIFORMTYPE_UINT)\n                ])\n            },\n            // @ts-ignore\n            computeBindGroupFormat: bindGroupFormat\n        });\n\n        const interleavedPoints = useF16 ? new Uint16Array(roundUp(numColumns * batchSize, 2)) : new Float32Array(numColumns * batchSize);\n        const interleavedCentroids = useF16 ? new Uint16Array(roundUp(numColumns * numCentroids, 2)) : new Float32Array(numColumns * numCentroids);\n        const resultsData = new Uint32Array(batchSize);\n\n        const pointsBuffer = new StorageBuffer(\n            device,\n            interleavedPoints.byteLength,\n            BUFFERUSAGE_COPY_DST\n        );\n\n        const centroidsBuffer = new StorageBuffer(\n            device,\n            interleavedCentroids.byteLength,\n            BUFFERUSAGE_COPY_DST\n        );\n\n        const resultsBuffer = new StorageBuffer(\n            device,\n            resultsData.byteLength,\n            BUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST\n        );\n\n        const compute = new Compute(device, shader, 'compute-cluster');\n        compute.setParameter('pointsBuffer', pointsBuffer);\n        compute.setParameter('centroidsBuffer', centroidsBuffer);\n        compute.setParameter('resultsBuffer', resultsBuffer);\n\n        this.execute = async (points: DataTable, centroids: DataTable, labels: Uint32Array) => {\n            const numPoints = points.numRows;\n            const numBatches = Math.ceil(numPoints / batchSize);\n\n            // upload centroid data to gpu\n            interleaveData(interleavedCentroids, centroids, numCentroids, 0);\n            centroidsBuffer.write(0, interleavedCentroids, 0, interleavedCentroids.length);\n            compute.setParameter('numCentroids', numCentroids);\n\n            for (let batch = 0; batch < numBatches; batch++) {\n                const currentBatchSize = Math.min(numPoints - batch * batchSize, batchSize);\n                const groups = Math.ceil(currentBatchSize / 64);\n\n                // write this batch of point data to gpu\n                interleaveData(interleavedPoints, points, currentBatchSize, batch * batchSize);\n                pointsBuffer.write(0, interleavedPoints, 0, useF16 ? roundUp(numColumns * currentBatchSize, 2) : numColumns * currentBatchSize);\n                compute.setParameter('numPoints', currentBatchSize);\n\n                // start compute job\n                compute.setupDispatch(groups);\n                device.computeDispatch([compute], `cluster-dispatch-${batch}`);\n\n                // read results from gpu and store in labels\n                await resultsBuffer.read(0, currentBatchSize * 4, resultsData, true);\n                labels.set(resultsData.subarray(0, currentBatchSize), batch * batchSize);\n            }\n        };\n\n        this.destroy = () => {\n            pointsBuffer.destroy();\n            centroidsBuffer.destroy();\n            resultsBuffer.destroy();\n            shader.destroy();\n            bindGroupFormat.destroy();\n        };\n    }\n}\n\nexport { GpuClustering };\n","/**\n * WGSL sources for the 5 compute shaders that make up the GPU dilation\n * pipeline (extract → clear → dilateX → dilateZ → dilateY → compact),\n * plus the small block-type + Fibonacci-hash constants block that the\n * extract and compact shaders share. Plain TS template-string\n * composition — the constants block is interpolated into each consuming\n * shader via `${dilationConstants}` rather than going through the\n * engine's `#include` preprocessor.\n *\n * The orchestrator class lives in `gpu-dilation.ts` and imports each\n * `xxxWgsl()` generator individually.\n */\n\n/**\n * Block-type enum and Fibonacci-hash constant, shared between the\n * extract and compact shaders. Mirrors the values used by the CPU\n * `BlockMaskMap.slot` formula so the GPU's hash probe lands in the same\n * slot.\n */\nconst dilationConstants = /* wgsl */`\nconst BLOCK_EMPTY: u32 = 0u;\nconst BLOCK_SOLID: u32 = 1u;\nconst BLOCK_MIXED: u32 = 2u;\nconst FIBONACCI_HASH: u32 = 0x9E3779B9u;\n`;\n\n/**\n * Extract shader — converts a `SparseVoxelGrid` (uploaded as types + open-\n * addressed mask hash) directly into a row-aligned dense bit buffer for one\n * outer chunk. One thread per source block in the chunk's outer block range.\n *\n * For MIXED blocks the shader does Fibonacci-hash linear-probe lookup against\n * the uploaded `srcKeys`/`srcLo`/`srcHi` arrays (matches the CPU\n * `BlockMaskMap.slot` formula bit-for-bit). The block's 4×4 X-row pattern\n * lands in a single dense word at bit offset `(blockX*4) & 31`; multiple\n * blocks share the same dense word at non-overlapping bit positions, so the\n * write is `atomicOr`. Caller must clear the dense buffer first.\n *\n * @returns WGSL source for the extract compute shader.\n */\nconst extractWgsl = () => /* wgsl */`\n${dilationConstants}\n\nstruct ExtractUniforms {\n    minBx: i32, minBy: i32, minBz: i32,\n\n    outerBx: u32, outerBy: u32, outerBz: u32,\n    numXWords: u32,\n\n    srcNbx: u32, srcNby: u32, srcNbz: u32,\n    srcBStride: u32,\n\n    srcCapMinusOne: u32\n}\n\n@group(0) @binding(0) var<uniform> u: ExtractUniforms;\n@group(0) @binding(1) var<storage, read> srcTypes: array<u32>;\n@group(0) @binding(2) var<storage, read> srcKeys: array<u32>;\n@group(0) @binding(3) var<storage, read> srcLo: array<u32>;\n@group(0) @binding(4) var<storage, read> srcHi: array<u32>;\n@group(0) @binding(5) var<storage, read_write> dstDense: array<atomic<u32>>;\n\n@compute @workgroup_size(8, 4, 8)\nfn main(@builtin(global_invocation_id) gid: vec3u) {\n    if (gid.x >= u.outerBx || gid.y >= u.outerBy || gid.z >= u.outerBz) {\n        return;\n    }\n\n    let chunkBx = i32(gid.x);\n    let chunkBy = i32(gid.y);\n    let chunkBz = i32(gid.z);\n\n    let globalBx = u.minBx + chunkBx;\n    let globalBy = u.minBy + chunkBy;\n    let globalBz = u.minBz + chunkBz;\n\n    if (globalBx < 0 || globalBy < 0 || globalBz < 0) { return; }\n    if (globalBx >= i32(u.srcNbx) || globalBy >= i32(u.srcNby) || globalBz >= i32(u.srcNbz)) { return; }\n\n    let blockIdx = u32(globalBx) + u32(globalBy) * u.srcNbx + u32(globalBz) * u.srcBStride;\n\n    let typeWord = srcTypes[blockIdx >> 4u];\n    let bt = (typeWord >> ((blockIdx & 15u) * 2u)) & 3u;\n\n    if (bt == BLOCK_EMPTY) { return; }\n\n    var lo: u32; var hi: u32;\n    if (bt == BLOCK_SOLID) {\n        lo = 0xFFFFFFFFu;\n        hi = 0xFFFFFFFFu;\n    } else {\n        // BLOCK_MIXED → hash lookup. Same constant as CPU BlockMaskMap.\n        var i = (blockIdx * FIBONACCI_HASH) & u.srcCapMinusOne;\n        loop {\n            let k = srcKeys[i];\n            if (k == blockIdx) {\n                lo = srcLo[i];\n                hi = srcHi[i];\n                break;\n            }\n            if (k == 0xFFFFFFFFu) {\n                return;  // not found (shouldn't happen for MIXED)\n            }\n            i = (i + 1u) & u.srcCapMinusOne;\n        }\n    }\n\n    // Write 64 voxel bits to dense at chunk-local position. dx0 is 4-aligned\n    // so each (ly, lz) row's 4 X-bits live in a single dense word.\n    let dx0 = u32(chunkBx) * 4u;\n    let wordOffsetX = dx0 / 32u;\n    let bitShiftX = dx0 & 31u;\n\n    let outerNy = u.outerBy * 4u;\n    let planeWords = u.numXWords * outerNy;\n\n    for (var lz: u32 = 0u; lz < 4u; lz = lz + 1u) {\n        let dz = u32(chunkBz) * 4u + lz;\n        let zBitBase = (lz & 1u) * 16u;\n        let word = select(lo, hi, lz >= 2u);\n        for (var ly: u32 = 0u; ly < 4u; ly = ly + 1u) {\n            let dy = u32(chunkBy) * 4u + ly;\n            let bitBase = zBitBase + ly * 4u;\n            let pattern = (word >> bitBase) & 0xFu;\n            if (pattern == 0u) { continue; }\n            let wordIdx = wordOffsetX + dy * u.numXWords + dz * planeWords;\n            atomicOr(&dstDense[wordIdx], pattern << bitShiftX);\n        }\n    }\n}\n`;\n\n/**\n * Compact shader — converts a dilated dense bit buffer back into per-block\n * `(type, lo, hi)` form for the chunk's INNER block region. One thread per\n * inner block; reads its 16 dense-word patterns to assemble the block's\n * 64-bit mask, classifies as EMPTY/SOLID/MIXED, and writes to two parallel\n * outputs:\n *   - `typesOut`: 2-bit-per-block packed (matches `dst.types` layout).\n *     Multiple threads write the same word, so atomicOr (caller clears).\n *   - `masksOut`: `[lo, hi]` pairs per inner block, indexed by inner-local\n *     block index. Always written (non-atomic; one thread per slot).\n *\n * @returns WGSL source for the compact compute shader.\n */\nconst compactWgsl = () => /* wgsl */`\n${dilationConstants}\n\nstruct CompactUniforms {\n    haloBx: u32, haloBy: u32, haloBz: u32,\n    numXWords: u32,             // outer chunk's\n\n    innerBx: u32, innerBy: u32, innerBz: u32,\n    outerBy: u32                 // for plane stride into dilatedDense\n}\n\n@group(0) @binding(0) var<uniform> u: CompactUniforms;\n@group(0) @binding(1) var<storage, read> dilatedDense: array<u32>;\n@group(0) @binding(2) var<storage, read_write> typesOut: array<atomic<u32>>;\n@group(0) @binding(3) var<storage, read_write> masksOut: array<u32>;\n\n@compute @workgroup_size(8, 4, 8)\nfn main(@builtin(global_invocation_id) gid: vec3u) {\n    if (gid.x >= u.innerBx || gid.y >= u.innerBy || gid.z >= u.innerBz) {\n        return;\n    }\n\n    let innerBlockIdx = gid.x + gid.y * u.innerBx + gid.z * u.innerBx * u.innerBy;\n\n    // Outer block coords (inner shifted by halo).\n    let outerBx = gid.x + u.haloBx;\n    let outerBy = gid.y + u.haloBy;\n    let outerBz = gid.z + u.haloBz;\n\n    let dx0 = outerBx * 4u;\n    let wordOffsetX = dx0 / 32u;\n    let bitShiftX = dx0 & 31u;\n\n    let outerNy = u.outerBy * 4u;\n    let numXWords = u.numXWords;\n    let planeWords = numXWords * outerNy;\n\n    var lo: u32 = 0u;\n    var hi: u32 = 0u;\n    for (var lz: u32 = 0u; lz < 4u; lz = lz + 1u) {\n        let dz = outerBz * 4u + lz;\n        let zBitBase = (lz & 1u) * 16u;\n        let inHi = lz >= 2u;\n        let planeBase = dz * planeWords;\n        for (var ly: u32 = 0u; ly < 4u; ly = ly + 1u) {\n            let dy = outerBy * 4u + ly;\n            let bitBase = zBitBase + ly * 4u;\n            let wordIdx = wordOffsetX + dy * numXWords + planeBase;\n            let pattern = (dilatedDense[wordIdx] >> bitShiftX) & 0xFu;\n            let bits = pattern << bitBase;\n            if (inHi) { hi = hi | bits; }\n            else { lo = lo | bits; }\n        }\n    }\n\n    masksOut[innerBlockIdx * 2u] = lo;\n    masksOut[innerBlockIdx * 2u + 1u] = hi;\n\n    var bt: u32 = BLOCK_EMPTY;\n    if (lo != 0u || hi != 0u) {\n        if (lo == 0xFFFFFFFFu && hi == 0xFFFFFFFFu) {\n            bt = BLOCK_SOLID;\n        } else {\n            bt = BLOCK_MIXED;\n        }\n    }\n\n    let typeWordIdx = innerBlockIdx >> 4u;\n    let typeBitShift = (innerBlockIdx & 15u) * 2u;\n    atomicOr(&typesOut[typeWordIdx], bt << typeBitShift);\n}\n`;\n\n/**\n * Clear shader — writes 0 to every word in the destination buffer up to\n * `numWords`. Dispatched in the same command encoder as the dilation passes\n * so it's ordered with them on the GPU; using `queue.writeBuffer` for inter-\n * pass clears would race because writes are queued separately from encoder\n * commands and execute *all writes first*, then the command buffer.\n *\n * @returns WGSL source for the clear compute shader.\n */\nconst clearWgsl = () => /* wgsl */`\nstruct ClearUniforms {\n    clearNumWords: u32,\n    clearRowStride: u32\n}\n\n@group(0) @binding(0) var<uniform> u: ClearUniforms;\n@group(0) @binding(1) var<storage, read_write> clearDst: array<u32>;\n\n// 2D dispatch (rowStride = wgX * 256) so we can clear buffers larger than\n// 65535 * 256 words without exceeding the WebGPU per-dimension workgroup\n// limit. Linear word index = gid.x + gid.y * rowStride.\n@compute @workgroup_size(256, 1, 1)\nfn main(@builtin(global_invocation_id) gid: vec3u) {\n    let i = gid.x + gid.y * u.clearRowStride;\n    if (i >= u.clearNumWords) {\n        return;\n    }\n    clearDst[i] = 0u;\n}\n`;\n\n/**\n * X-axis dilation shader — per-word.\n *\n * Each thread produces one 32-bit output word at `(xWord, y, z)` and writes\n * it directly (no atomics). The output bit at relative X position `b` (in\n * `[0, 31]`) is the OR of input bits in `[xWord*32 + b - r, xWord*32 + b + r]`.\n * For each distance `d` in `[1, r]`, the shader reads the source word(s)\n * containing bits shifted by `d`, so radii can span any number of 32-bit words.\n *\n * Bound by the chunk's `numXWords` (= ceil(nx / 32)). Out-of-bounds neighbors\n * are read as 0.\n *\n * @returns WGSL source for the X-axis dilation compute shader.\n */\nconst dilateXWgsl = () => /* wgsl */`\nstruct DilateXUniforms {\n    numXWords: u32,\n    ny: u32,\n    nz: u32,\n    halfExtent: u32\n}\n\n@group(0) @binding(0) var<uniform> u: DilateXUniforms;\n@group(0) @binding(1) var<storage, read> src: array<u32>;\n@group(0) @binding(2) var<storage, read_write> dst: array<u32>;\n\nfn readWord(rowOffset: u32, word: i32) -> u32 {\n    if (word < 0 || word >= i32(u.numXWords)) {\n        return 0u;\n    }\n    return src[rowOffset + u32(word)];\n}\n\n@compute @workgroup_size(8, 4, 8)\nfn main(@builtin(global_invocation_id) gid: vec3u) {\n    if (gid.x >= u.numXWords || gid.y >= u.ny || gid.z >= u.nz) {\n        return;\n    }\n\n    let xWord = gid.x;\n    let y = gid.y;\n    let z = gid.z;\n    let rowStride = u.numXWords;\n    let planeStride = rowStride * u.ny;\n    let rowOffset = y * rowStride + z * planeStride;\n\n    var output: u32 = src[rowOffset + xWord];\n    let rowBits = u.numXWords * 32u;\n    let r = min(u.halfExtent, rowBits);\n    for (var d: u32 = 1u; d <= r; d = d + 1u) {\n        let wordOffset = i32(d >> 5u);\n        let bitShift = d & 31u;\n        let baseWord = i32(xWord);\n\n        // Rightward shift: bit b ← input bit b+d.\n        var shifted_pos = readWord(rowOffset, baseWord + wordOffset);\n        if (bitShift != 0u) {\n            shifted_pos = (shifted_pos >> bitShift) |\n                (readWord(rowOffset, baseWord + wordOffset + 1) << (32u - bitShift));\n        }\n\n        // Leftward shift: bit b ← input bit b-d.\n        var shifted_neg = readWord(rowOffset, baseWord - wordOffset);\n        if (bitShift != 0u) {\n            shifted_neg = (shifted_neg << bitShift) |\n                (readWord(rowOffset, baseWord - wordOffset - 1) >> (32u - bitShift));\n        }\n\n        output = output | shifted_pos | shifted_neg;\n        if (output == 0xFFFFFFFFu) {\n            break;\n        }\n    }\n\n    dst[rowOffset + xWord] = output;\n}\n`;\n\n/**\n * Y/Z-axis dilation shader — per-word.\n *\n * Each thread reads up to `2 * halfExtent + 1` input words at the same\n * `xWord` along the chosen axis (Y or Z) and OR's them into one output word.\n * No bit shifts needed because words at the same `xWord` are bit-aligned\n * across rows (row stride is `numXWords` words). Caller picks the axis by\n * setting `stride` and `axisLen`:\n *  - Y-pass: `stride = numXWords`, `axisLen = ny`.\n *  - Z-pass: `stride = numXWords * ny`, `axisLen = nz`.\n *\n * @returns WGSL source for the Y/Z-axis dilation compute shader.\n */\nconst dilateYZWgsl = () => /* wgsl */`\nstruct DilateYZUniforms {\n    numXWords: u32,\n    ny: u32,\n    nz: u32,\n    halfExtent: u32,\n    stride: u32,\n    axisLen: u32\n}\n\n@group(0) @binding(0) var<uniform> u: DilateYZUniforms;\n@group(0) @binding(1) var<storage, read> src: array<u32>;\n@group(0) @binding(2) var<storage, read_write> dst: array<u32>;\n\n@compute @workgroup_size(8, 4, 8)\nfn main(@builtin(global_invocation_id) gid: vec3u) {\n    if (gid.x >= u.numXWords || gid.y >= u.ny || gid.z >= u.nz) {\n        return;\n    }\n\n    let xWord = gid.x;\n    let y = gid.y;\n    let z = gid.z;\n    let rowStride = u.numXWords;\n    let planeStride = rowStride * u.ny;\n    let outIdx = i32(xWord) + i32(y) * i32(rowStride) + i32(z) * i32(planeStride);\n\n    var pos: u32;\n    if (u.stride == rowStride) {\n        pos = y;\n    } else {\n        pos = z;\n    }\n\n    let r = i32(u.halfExtent);\n    let lo = max(0, i32(pos) - r);\n    let hi = min(i32(u.axisLen) - 1, i32(pos) + r);\n\n    let baseIdx = outIdx - i32(pos) * i32(u.stride);\n    var output: u32 = 0u;\n    for (var p: i32 = lo; p <= hi; p = p + 1) {\n        output = output | src[baseIdx + p * i32(u.stride)];\n        if (output == 0xFFFFFFFFu) {\n            break;\n        }\n    }\n\n    dst[outIdx] = output;\n}\n`;\n\nexport { extractWgsl, compactWgsl, clearWgsl, dilateXWgsl, dilateYZWgsl };\n","import {\n    BUFFERUSAGE_COPY_DST,\n    BUFFERUSAGE_COPY_SRC,\n    SHADERLANGUAGE_WGSL,\n    SHADERSTAGE_COMPUTE,\n    UNIFORMTYPE_UINT,\n    BindGroupFormat,\n    BindStorageBufferFormat,\n    BindUniformBufferFormat,\n    Compute,\n    GraphicsDevice,\n    Shader,\n    StorageBuffer,\n    UniformBufferFormat,\n    UniformFormat\n} from 'playcanvas';\n\nimport {\n    clearWgsl,\n    compactWgsl,\n    dilateXWgsl,\n    dilateYZWgsl,\n    extractWgsl\n} from './shaders/dilation';\nimport type { SparseVoxelGrid } from '../voxel/sparse-voxel-grid';\n\n/**\n * One double-buffered slot — the four `Compute` instances (X, Y, Z, clear)\n * each own a uniform buffer that mustn't be overwritten by a sibling\n * dispatch on the same submit, plus the ping-pong storage buffers. Two\n * slots let the CPU prepare chunk N+1 while the GPU is busy with chunk N.\n */\ninterface DilationSlot {\n    bufferA: StorageBuffer;\n    bufferB: StorageBuffer;\n    capacity: number;\n    dilateXCompute: Compute;\n    dilateYCompute: Compute;\n    dilateZCompute: Compute;\n    clearCompute: Compute;\n    extractCompute: Compute;\n    compactCompute: Compute;\n\n    typesOutBuffer: StorageBuffer;\n    masksOutBuffer: StorageBuffer;\n    typesOutCapacity: number;\n    masksOutCapacity: number;\n}\n\n/**\n * Separable 3D dilation on the GPU using a row-aligned dense bit grid\n * (1 bit per voxel, packed into u32 words; each row of bits along X starts\n * on a word boundary so per-word access is trivial). Each pass owns its\n * own `Compute` instance because their uniform buffers must not collide\n * within a single submit.\n */\nclass GpuDilation {\n    private device: GraphicsDevice;\n    private dilateXShader: Shader;\n    private dilateYZShader: Shader;\n    private clearShader: Shader;\n    private extractShader: Shader;\n    private compactShader: Shader;\n    private dilateXBindGroupFormat: BindGroupFormat;\n    private dilateYZBindGroupFormat: BindGroupFormat;\n    private clearBindGroupFormat: BindGroupFormat;\n    private extractBindGroupFormat: BindGroupFormat;\n    private compactBindGroupFormat: BindGroupFormat;\n\n    private slots: DilationSlot[];\n\n    // Source SparseVoxelGrid uploaded once per `gpuDilate3` call (shared\n    // across all chunks and slots). `extract` shaders read these.\n    private srcTypesBuffer: StorageBuffer | null = null;\n    private srcKeysBuffer: StorageBuffer | null = null;\n    private srcLoBuffer: StorageBuffer | null = null;\n    private srcHiBuffer: StorageBuffer | null = null;\n    private srcTypesCapacity = 0;\n    private srcMasksCapacity = 0;\n    private srcMeta = { nbx: 0, nby: 0, nbz: 0, bStride: 0, capMinusOne: 0 };\n\n    /** Number of double-buffered dispatch slots. */\n    static readonly NUM_SLOTS = 2;\n\n    constructor(device: GraphicsDevice) {\n        this.device = device;\n\n        this.dilateXBindGroupFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('src', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('dst', SHADERSTAGE_COMPUTE)\n        ]);\n\n        this.dilateYZBindGroupFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('src', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('dst', SHADERSTAGE_COMPUTE)\n        ]);\n\n        this.clearBindGroupFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('clearDst', SHADERSTAGE_COMPUTE)\n        ]);\n\n        this.extractBindGroupFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('srcTypes', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('srcKeys', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('srcLo', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('srcHi', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('dstDense', SHADERSTAGE_COMPUTE)\n        ]);\n\n        this.compactBindGroupFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('dilatedDense', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('typesOut', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('masksOut', SHADERSTAGE_COMPUTE)\n        ]);\n\n        this.dilateXShader = new Shader(device, {\n            name: 'gpu-dilation-x',\n            shaderLanguage: SHADERLANGUAGE_WGSL,\n            cshader: dilateXWgsl(),\n            // @ts-ignore\n            computeUniformBufferFormats: {\n                uniforms: new UniformBufferFormat(device, [\n                    new UniformFormat('numXWords', UNIFORMTYPE_UINT),\n                    new UniformFormat('ny', UNIFORMTYPE_UINT),\n                    new UniformFormat('nz', UNIFORMTYPE_UINT),\n                    new UniformFormat('halfExtent', UNIFORMTYPE_UINT)\n                ])\n            },\n            // @ts-ignore\n            computeBindGroupFormat: this.dilateXBindGroupFormat\n        });\n\n        this.dilateYZShader = new Shader(device, {\n            name: 'gpu-dilation-yz',\n            shaderLanguage: SHADERLANGUAGE_WGSL,\n            cshader: dilateYZWgsl(),\n            // @ts-ignore\n            computeUniformBufferFormats: {\n                uniforms: new UniformBufferFormat(device, [\n                    new UniformFormat('numXWords', UNIFORMTYPE_UINT),\n                    new UniformFormat('ny', UNIFORMTYPE_UINT),\n                    new UniformFormat('nz', UNIFORMTYPE_UINT),\n                    new UniformFormat('halfExtent', UNIFORMTYPE_UINT),\n                    new UniformFormat('stride', UNIFORMTYPE_UINT),\n                    new UniformFormat('axisLen', UNIFORMTYPE_UINT)\n                ])\n            },\n            // @ts-ignore\n            computeBindGroupFormat: this.dilateYZBindGroupFormat\n        });\n\n        this.clearShader = new Shader(device, {\n            name: 'gpu-dilation-clear',\n            shaderLanguage: SHADERLANGUAGE_WGSL,\n            cshader: clearWgsl(),\n            // @ts-ignore\n            computeUniformBufferFormats: {\n                uniforms: new UniformBufferFormat(device, [\n                    new UniformFormat('clearNumWords', UNIFORMTYPE_UINT),\n                    new UniformFormat('clearRowStride', UNIFORMTYPE_UINT)\n                ])\n            },\n            // @ts-ignore\n            computeBindGroupFormat: this.clearBindGroupFormat\n        });\n\n        this.extractShader = new Shader(device, {\n            name: 'gpu-dilation-extract',\n            shaderLanguage: SHADERLANGUAGE_WGSL,\n            cshader: extractWgsl(),\n            // @ts-ignore\n            computeUniformBufferFormats: {\n                uniforms: new UniformBufferFormat(device, [\n                    new UniformFormat('minBx', UNIFORMTYPE_UINT),  // signed reinterpret\n                    new UniformFormat('minBy', UNIFORMTYPE_UINT),\n                    new UniformFormat('minBz', UNIFORMTYPE_UINT),\n                    new UniformFormat('outerBx', UNIFORMTYPE_UINT),\n                    new UniformFormat('outerBy', UNIFORMTYPE_UINT),\n                    new UniformFormat('outerBz', UNIFORMTYPE_UINT),\n                    new UniformFormat('numXWords', UNIFORMTYPE_UINT),\n                    new UniformFormat('srcNbx', UNIFORMTYPE_UINT),\n                    new UniformFormat('srcNby', UNIFORMTYPE_UINT),\n                    new UniformFormat('srcNbz', UNIFORMTYPE_UINT),\n                    new UniformFormat('srcBStride', UNIFORMTYPE_UINT),\n                    new UniformFormat('srcCapMinusOne', UNIFORMTYPE_UINT)\n                ])\n            },\n            // @ts-ignore\n            computeBindGroupFormat: this.extractBindGroupFormat\n        });\n\n        this.compactShader = new Shader(device, {\n            name: 'gpu-dilation-compact',\n            shaderLanguage: SHADERLANGUAGE_WGSL,\n            cshader: compactWgsl(),\n            // @ts-ignore\n            computeUniformBufferFormats: {\n                uniforms: new UniformBufferFormat(device, [\n                    new UniformFormat('haloBx', UNIFORMTYPE_UINT),\n                    new UniformFormat('haloBy', UNIFORMTYPE_UINT),\n                    new UniformFormat('haloBz', UNIFORMTYPE_UINT),\n                    new UniformFormat('numXWords', UNIFORMTYPE_UINT),\n                    new UniformFormat('innerBx', UNIFORMTYPE_UINT),\n                    new UniformFormat('innerBy', UNIFORMTYPE_UINT),\n                    new UniformFormat('innerBz', UNIFORMTYPE_UINT),\n                    new UniformFormat('outerBy', UNIFORMTYPE_UINT)\n                ])\n            },\n            // @ts-ignore\n            computeBindGroupFormat: this.compactBindGroupFormat\n        });\n\n        this.slots = [];\n        for (let i = 0; i < GpuDilation.NUM_SLOTS; i++) {\n            const initialCapacity = 1024 * 1024 * 4;\n            const initialTypesOut = 64 * 1024;       // 16K blocks worth packed\n            const initialMasksOut = 1024 * 1024;     // 128K blocks worth (lo, hi)\n            this.slots.push({\n                bufferA: new StorageBuffer(device, initialCapacity, BUFFERUSAGE_COPY_DST | BUFFERUSAGE_COPY_SRC),\n                bufferB: new StorageBuffer(device, initialCapacity, BUFFERUSAGE_COPY_DST | BUFFERUSAGE_COPY_SRC),\n                capacity: initialCapacity,\n                dilateXCompute: new Compute(device, this.dilateXShader, `gpu-dilate-x-${i}`),\n                dilateYCompute: new Compute(device, this.dilateYZShader, `gpu-dilate-y-${i}`),\n                dilateZCompute: new Compute(device, this.dilateYZShader, `gpu-dilate-z-${i}`),\n                clearCompute: new Compute(device, this.clearShader, `gpu-dilate-clear-${i}`),\n                extractCompute: new Compute(device, this.extractShader, `gpu-dilate-extract-${i}`),\n                compactCompute: new Compute(device, this.compactShader, `gpu-dilate-compact-${i}`),\n                typesOutBuffer: new StorageBuffer(device, initialTypesOut, BUFFERUSAGE_COPY_DST | BUFFERUSAGE_COPY_SRC),\n                masksOutBuffer: new StorageBuffer(device, initialMasksOut, BUFFERUSAGE_COPY_DST | BUFFERUSAGE_COPY_SRC),\n                typesOutCapacity: initialTypesOut,\n                masksOutCapacity: initialMasksOut\n            });\n        }\n    }\n\n    private ensureSlotBuffers(slot: DilationSlot, numWords: number): void {\n        const neededBytes = numWords * 4;\n        if (neededBytes <= slot.capacity) return;\n\n        let cap = slot.capacity;\n        while (cap < neededBytes) cap *= 2;\n\n        slot.bufferA.destroy();\n        slot.bufferB.destroy();\n        slot.bufferA = new StorageBuffer(this.device, cap, BUFFERUSAGE_COPY_DST | BUFFERUSAGE_COPY_SRC);\n        slot.bufferB = new StorageBuffer(this.device, cap, BUFFERUSAGE_COPY_DST | BUFFERUSAGE_COPY_SRC);\n        slot.capacity = cap;\n    }\n\n    /**\n     * Dispatch a compute clear of `dst` to zero for the first `numWords` words.\n     * Uses the command encoder so it's correctly ordered with subsequent\n     * dilation passes (unlike `queue.writeBuffer`, which is queued separately\n     * and would race against the dispatches).\n     * @param slot - Per-chunk slot whose `clearCompute` pipeline is dispatched.\n     * @param dst - Destination buffer to zero.\n     * @param numWords - Number of leading u32 words to clear.\n     */\n    private dispatchClear(slot: DilationSlot, dst: StorageBuffer, numWords: number): void {\n        const totalWg = Math.ceil(numWords / 256);\n        const MAX_DIM = 65535;\n        const wgX = Math.min(totalWg, MAX_DIM);\n        const wgY = Math.ceil(totalWg / wgX);\n        const rowStride = wgX * 256;\n\n        slot.clearCompute.setParameter('clearDst', dst);\n        slot.clearCompute.setParameter('clearNumWords', numWords);\n        slot.clearCompute.setParameter('clearRowStride', rowStride);\n        slot.clearCompute.setupDispatch(wgX, wgY, 1);\n        this.device.computeDispatch([slot.clearCompute], 'gpu-dilate-clear');\n    }\n\n    /**\n     * Upload a `SparseVoxelGrid` to GPU storage buffers used by the extract\n     * shader. Reuses the existing buffers if they're large enough; otherwise\n     * destroys and reallocates. Designed to be called once per\n     * `gpuDilate3` call (the same `src` is read across all chunks).\n     * @param src - Source sparse grid to upload.\n     */\n    uploadSrc(src: SparseVoxelGrid): void {\n        const types = src.types;\n        const keys = src.masks.keys;     // Int32Array; -1 sentinel reads as 0xFFFFFFFF when interpreted as u32\n        const lo = src.masks.lo;\n        const hi = src.masks.hi;\n\n        const typesBytes = types.byteLength;\n        if (this.srcTypesBuffer === null || this.srcTypesCapacity < typesBytes) {\n            this.srcTypesBuffer?.destroy();\n            this.srcTypesBuffer = new StorageBuffer(this.device, typesBytes, BUFFERUSAGE_COPY_DST);\n            this.srcTypesCapacity = typesBytes;\n        }\n        this.srcTypesBuffer.write(0, types, 0, types.length);\n\n        const masksBytes = keys.byteLength;\n        if (this.srcKeysBuffer === null || this.srcMasksCapacity < masksBytes) {\n            this.srcKeysBuffer?.destroy();\n            this.srcLoBuffer?.destroy();\n            this.srcHiBuffer?.destroy();\n            this.srcKeysBuffer = new StorageBuffer(this.device, masksBytes, BUFFERUSAGE_COPY_DST);\n            this.srcLoBuffer = new StorageBuffer(this.device, masksBytes, BUFFERUSAGE_COPY_DST);\n            this.srcHiBuffer = new StorageBuffer(this.device, masksBytes, BUFFERUSAGE_COPY_DST);\n            this.srcMasksCapacity = masksBytes;\n        }\n        // Treat keys (Int32) as Uint32 — same byte pattern; -1 reads as 0xFFFFFFFF.\n        const keysU32 = new Uint32Array(keys.buffer, keys.byteOffset, keys.length);\n        this.srcKeysBuffer.write(0, keysU32, 0, keys.length);\n        this.srcLoBuffer.write(0, lo, 0, lo.length);\n        this.srcHiBuffer.write(0, hi, 0, hi.length);\n\n        this.srcMeta = {\n            nbx: src.nbx,\n            nby: src.nby,\n            nbz: src.nbz,\n            bStride: src.bStride,\n            capMinusOne: keys.length - 1\n        };\n    }\n\n    /** Free uploaded `src` buffers. Caller can call after `gpuDilate3` finishes. */\n    releaseSrc(): void {\n        this.srcTypesBuffer?.destroy();\n        this.srcKeysBuffer?.destroy();\n        this.srcLoBuffer?.destroy();\n        this.srcHiBuffer?.destroy();\n        this.srcTypesBuffer = null;\n        this.srcKeysBuffer = null;\n        this.srcLoBuffer = null;\n        this.srcHiBuffer = null;\n        this.srcTypesCapacity = 0;\n        this.srcMasksCapacity = 0;\n    }\n\n    private ensureSlotOutputBuffers(slot: DilationSlot, innerBlocks: number): void {\n        // typesOut: 2 bits per inner block, packed into u32 words.\n        const typesBytes = (((innerBlocks + 15) >>> 4) * 4);\n        if (slot.typesOutCapacity < typesBytes) {\n            slot.typesOutBuffer.destroy();\n            slot.typesOutBuffer = new StorageBuffer(this.device, typesBytes, BUFFERUSAGE_COPY_DST | BUFFERUSAGE_COPY_SRC);\n            slot.typesOutCapacity = typesBytes;\n        }\n        // masksOut: (lo, hi) per inner block.\n        const masksBytes = innerBlocks * 8;\n        if (slot.masksOutCapacity < masksBytes) {\n            slot.masksOutBuffer.destroy();\n            slot.masksOutBuffer = new StorageBuffer(this.device, masksBytes, BUFFERUSAGE_COPY_DST | BUFFERUSAGE_COPY_SRC);\n            slot.masksOutCapacity = masksBytes;\n        }\n    }\n\n    /**\n     * Sparse-path submit. Reads from the previously-uploaded `src` (via\n     * `uploadSrc`), runs extract → dilate → compact as GPU passes, and returns\n     * Promises for the per-block `typesOut` (packed 2-bit) and `masksOut`\n     * (lo/hi pairs). Caller integrates these into `dst` directly.\n     * @param slotIdx - Round-robin slot index (`0..NUM_SLOTS-1`).\n     * @param minBx - Outer chunk origin block X (in `src`'s block coords).\n     * @param minBy - Outer chunk origin block Y.\n     * @param minBz - Outer chunk origin block Z.\n     * @param outerBx - Outer chunk size in blocks along X.\n     * @param outerBy - Outer chunk size in blocks along Y.\n     * @param outerBz - Outer chunk size in blocks along Z.\n     * @param haloBx - Halo size in blocks along X (one side).\n     * @param haloBy - Halo size in blocks along Y (one side).\n     * @param haloBz - Halo size in blocks along Z (one side).\n     * @param innerBx - Inner (output) region size in blocks along X.\n     * @param innerBy - Inner region size in blocks along Y.\n     * @param innerBz - Inner region size in blocks along Z.\n     * @param halfExtentXZ - Dilation half-extent in voxels along X and Z.\n     * @param halfExtentY - Dilation half-extent in voxels along Y.\n     * @returns Promises for the inner region's packed types and `[lo, hi]` masks.\n     */\n    submitChunkSparse(\n        slotIdx: number,\n        // outer chunk in block coords (each is voxel/4)\n        minBx: number, minBy: number, minBz: number,\n        outerBx: number, outerBy: number, outerBz: number,\n        // halo in blocks\n        haloBx: number, haloBy: number, haloBz: number,\n        // inner chunk in block coords\n        innerBx: number, innerBy: number, innerBz: number,\n        halfExtentXZ: number,\n        halfExtentY: number\n    ): { types: Promise<Uint32Array>, masks: Promise<Uint32Array> } {\n        if (this.srcTypesBuffer === null) {\n            throw new Error('GpuDilation: must call uploadSrc() before submitChunkSparse()');\n        }\n        const slot = this.slots[slotIdx];\n\n        const outerNx = outerBx * 4;\n        const outerNy = outerBy * 4;\n        const outerNz = outerBz * 4;\n        const numXWords = (outerNx + 31) >>> 5;\n        const numWords = numXWords * outerNy * outerNz;\n        this.ensureSlotBuffers(slot, numWords);\n\n        const innerBlocks = innerBx * innerBy * innerBz;\n        this.ensureSlotOutputBuffers(slot, innerBlocks);\n\n        const typesOutWords = (innerBlocks + 15) >>> 4;\n\n        // Extract: clear bufferA, dispatch extract from sparse src into bufferA.\n        this.dispatchClear(slot, slot.bufferA, numWords);\n        this.dispatchExtract(slot, minBx, minBy, minBz, outerBx, outerBy, outerBz, numXWords);\n\n        // Force a queue submission boundary between the extract pass (which\n        // writes bufferA via atomicOr — bound as `storage, read_write` with\n        // `array<atomic<u32>>`) and the dilate-X pass (which reads bufferA\n        // bound as `storage, read` with `array<u32>`). Without this, the\n        // atomic writes are not reliably visible to the next pass — dilation\n        // produces empty output. Other inter-pass transitions in this\n        // pipeline (clear→extract, dilateX→Z→Y, Y→compact) rely on automatic\n        // intra-encoder synchronization without issue. Verified raw Dawn\n        // synchronizes this case correctly, so the bug is somewhere in\n        // PlayCanvas's compute dispatch / bind-group path.\n        (this.device as unknown as { submit: () => void }).submit();\n\n        // X-pass: A → B\n        this.dispatchX(slot, slot.bufferA, slot.bufferB, numXWords, outerNy, outerNz, halfExtentXZ);\n\n        // Z-pass: B → A\n        this.dispatchYZ(slot.dilateZCompute, slot.bufferB, slot.bufferA,\n            numXWords, outerNy, outerNz, halfExtentXZ, numXWords * outerNy, outerNz);\n\n        // Y-pass: A → B\n        this.dispatchYZ(slot.dilateYCompute, slot.bufferA, slot.bufferB,\n            numXWords, outerNy, outerNz, halfExtentY, numXWords, outerNy);\n\n        // Compact: clear typesOut (atomicOr accumulates), dispatch compact.\n        // masksOut is written non-atomically — no clear needed.\n        this.dispatchClear(slot, slot.typesOutBuffer, typesOutWords);\n        this.dispatchCompact(slot, haloBx, haloBy, haloBz, innerBx, innerBy, innerBz, numXWords, outerBy);\n\n        const typesPromise = slot.typesOutBuffer.read(0, typesOutWords * 4, null, true)\n        .then((readData: Uint8Array) => new Uint32Array(readData.buffer, readData.byteOffset, typesOutWords));\n        const masksPromise = slot.masksOutBuffer.read(0, innerBlocks * 8, null, true)\n        .then((readData: Uint8Array) => new Uint32Array(readData.buffer, readData.byteOffset, innerBlocks * 2));\n\n        return { types: typesPromise, masks: masksPromise };\n    }\n\n    private dispatchExtract(\n        slot: DilationSlot,\n        minBx: number, minBy: number, minBz: number,\n        outerBx: number, outerBy: number, outerBz: number,\n        numXWords: number\n    ): void {\n        const c = slot.extractCompute;\n        c.setParameter('srcTypes', this.srcTypesBuffer!);\n        c.setParameter('srcKeys', this.srcKeysBuffer!);\n        c.setParameter('srcLo', this.srcLoBuffer!);\n        c.setParameter('srcHi', this.srcHiBuffer!);\n        c.setParameter('dstDense', slot.bufferA);\n        // Reinterpret signed minB* as u32 bits via the i32 parameter slot —\n        // PlayCanvas treats UNIFORMTYPE_UINT as raw u32, and the WGSL struct\n        // declares these as i32 so they read back signed.\n        c.setParameter('minBx', (minBx >>> 0));\n        c.setParameter('minBy', (minBy >>> 0));\n        c.setParameter('minBz', (minBz >>> 0));\n        c.setParameter('outerBx', outerBx);\n        c.setParameter('outerBy', outerBy);\n        c.setParameter('outerBz', outerBz);\n        c.setParameter('numXWords', numXWords);\n        c.setParameter('srcNbx', this.srcMeta.nbx);\n        c.setParameter('srcNby', this.srcMeta.nby);\n        c.setParameter('srcNbz', this.srcMeta.nbz);\n        c.setParameter('srcBStride', this.srcMeta.bStride);\n        c.setParameter('srcCapMinusOne', this.srcMeta.capMinusOne);\n\n        const wgX = Math.ceil(outerBx / 8);\n        const wgY = Math.ceil(outerBy / 4);\n        const wgZ = Math.ceil(outerBz / 8);\n        c.setupDispatch(wgX, wgY, wgZ);\n        this.device.computeDispatch([c], c.name);\n    }\n\n    private dispatchCompact(\n        slot: DilationSlot,\n        haloBx: number, haloBy: number, haloBz: number,\n        innerBx: number, innerBy: number, innerBz: number,\n        numXWords: number,\n        outerBy: number\n    ): void {\n        const c = slot.compactCompute;\n        c.setParameter('dilatedDense', slot.bufferB);\n        c.setParameter('typesOut', slot.typesOutBuffer);\n        c.setParameter('masksOut', slot.masksOutBuffer);\n        c.setParameter('haloBx', haloBx);\n        c.setParameter('haloBy', haloBy);\n        c.setParameter('haloBz', haloBz);\n        c.setParameter('numXWords', numXWords);\n        c.setParameter('innerBx', innerBx);\n        c.setParameter('innerBy', innerBy);\n        c.setParameter('innerBz', innerBz);\n        c.setParameter('outerBy', outerBy);\n\n        const wgX = Math.ceil(innerBx / 8);\n        const wgY = Math.ceil(innerBy / 4);\n        const wgZ = Math.ceil(innerBz / 8);\n        c.setupDispatch(wgX, wgY, wgZ);\n        this.device.computeDispatch([c], c.name);\n    }\n\n    private dispatchX(\n        slot: DilationSlot,\n        src: StorageBuffer, dst: StorageBuffer,\n        numXWords: number, ny: number, nz: number,\n        halfExtent: number\n    ): void {\n        const c = slot.dilateXCompute;\n        c.setParameter('src', src);\n        c.setParameter('dst', dst);\n        c.setParameter('numXWords', numXWords);\n        c.setParameter('ny', ny);\n        c.setParameter('nz', nz);\n        c.setParameter('halfExtent', halfExtent);\n\n        const wgX = Math.ceil(numXWords / 8);\n        const wgY = Math.ceil(ny / 4);\n        const wgZ = Math.ceil(nz / 8);\n        c.setupDispatch(wgX, wgY, wgZ);\n        this.device.computeDispatch([c], c.name);\n    }\n\n    private dispatchYZ(\n        compute: Compute,\n        src: StorageBuffer, dst: StorageBuffer,\n        numXWords: number, ny: number, nz: number,\n        halfExtent: number,\n        stride: number, axisLen: number\n    ): void {\n        compute.setParameter('src', src);\n        compute.setParameter('dst', dst);\n        compute.setParameter('numXWords', numXWords);\n        compute.setParameter('ny', ny);\n        compute.setParameter('nz', nz);\n        compute.setParameter('halfExtent', halfExtent);\n        compute.setParameter('stride', stride);\n        compute.setParameter('axisLen', axisLen);\n\n        const wgX = Math.ceil(numXWords / 8);\n        const wgY = Math.ceil(ny / 4);\n        const wgZ = Math.ceil(nz / 8);\n        compute.setupDispatch(wgX, wgY, wgZ);\n        this.device.computeDispatch([compute], compute.name);\n    }\n\n    destroy(): void {\n        this.releaseSrc();\n        for (const slot of this.slots) {\n            slot.bufferA.destroy();\n            slot.bufferB.destroy();\n            slot.typesOutBuffer.destroy();\n            slot.masksOutBuffer.destroy();\n            slot.dilateXCompute.destroy();\n            slot.dilateYCompute.destroy();\n            slot.dilateZCompute.destroy();\n            slot.clearCompute.destroy();\n            slot.extractCompute.destroy();\n            slot.compactCompute.destroy();\n        }\n        this.dilateXShader.destroy();\n        this.dilateYZShader.destroy();\n        this.clearShader.destroy();\n        this.extractShader.destroy();\n        this.compactShader.destroy();\n        this.dilateXBindGroupFormat.destroy();\n        this.dilateYZBindGroupFormat.destroy();\n        this.clearBindGroupFormat.destroy();\n        this.extractBindGroupFormat.destroy();\n        this.compactBindGroupFormat.destroy();\n    }\n}\n\nexport { GpuDilation };\n","import {\n    AA_DILATION_COV,\n    DISCRIMINANT_FLOOR,\n    GAUSSIAN_FLOOR,\n    JACOBIAN_LIMIT_FACTOR,\n    MIN_ALPHA,\n    MIN_TRANSMITTANCE,\n    OPACITY_CAP,\n    POLE_EPS,\n    RADIUS_FADE_END_FRAC,\n    RADIUS_FADE_START_FRAC,\n    SIGMA_CUTOFF,\n    TILE_SIZE\n} from '../../../render/config';\n\n/**\n * Format a JS number as a WGSL `f32` literal. Adds an explicit `.0` so\n * integer-valued constants like `3` aren't parsed as `AbstractInt` —\n * keeps shaders readable when the constant flips to a fractional value.\n *\n * @param n - Numeric value to format.\n * @returns WGSL literal string with explicit `.0` for integer values.\n */\nconst wgslF32 = (n: number): string => {\n    const s = n.toString();\n    return s.includes('.') || s.includes('e') || s.includes('E') ? s : `${s}.0`;\n};\n\n/**\n * Shared render-time tunables declared as WGSL `const` so every shader can\n * reference them as plain identifiers. Bound to the JS-side values in\n * [render/config.ts](../../render/config.ts) — the single source of truth.\n *\n * The PlayCanvas WGSL preprocessor's `cdefines` mechanism only registers\n * symbols for `#ifdef` checks; it does not substitute bare identifiers\n * with their values. WGSL `const` declarations cover that gap and can\n * additionally be used inside `@workgroup_size(...)` and other const-\n * expression contexts.\n *\n * Included via `#include \"constants\"` (see `sharedCincludes` in\n * `gpu-splat-rasterizer.ts`).\n */\nconst constantsChunk = /* wgsl */`\nconst TILE_SIZE: u32 = ${TILE_SIZE}u;\nconst SIGMA_CUTOFF: f32 = ${wgslF32(SIGMA_CUTOFF)};\nconst GAUSSIAN_FLOOR: f32 = ${wgslF32(GAUSSIAN_FLOOR)};\nconst AA_DILATION_COV: f32 = ${wgslF32(AA_DILATION_COV)};\nconst DISCRIMINANT_FLOOR: f32 = ${wgslF32(DISCRIMINANT_FLOOR)};\nconst JACOBIAN_LIMIT_FACTOR: f32 = ${wgslF32(JACOBIAN_LIMIT_FACTOR)};\nconst MIN_ALPHA: f32 = ${wgslF32(MIN_ALPHA)};\nconst MIN_TRANSMITTANCE: f32 = ${wgslF32(MIN_TRANSMITTANCE)};\nconst OPACITY_CAP: f32 = ${wgslF32(OPACITY_CAP)};\nconst RADIUS_FADE_START_FRAC: f32 = ${wgslF32(RADIUS_FADE_START_FRAC)};\nconst RADIUS_FADE_END_FRAC: f32 = ${wgslF32(RADIUS_FADE_END_FRAC)};\nconst POLE_EPS: f32 = ${wgslF32(POLE_EPS)};\n`;\n\nexport { constantsChunk, wgslF32 };\n","/**\n * 3D world-space covariance Σ = M·Mᵀ where M = R·diag(scale), then\n * rotated into camera space via V·Σ·Vᵀ.\n *\n * Reads:   r00..r22 (world rotation), lsX, lsY, lsZ (log scales),\n *          uniforms.rightX/Y/Z, uniforms.downX/Y/Z, uniforms.forwardX/Y/Z\n *          (camera basis rows = view-rotation matrix V)\n * Defines: c00, c01, c02, c11, c12, c22 (camera-space 3D covariance,\n *          symmetric — only the upper triangle is stored)\n *\n * The output covariance feeds the Jacobian chunks (pinhole / equirect)\n * to derive the 2D screen-space covariance via cov2D = J · cov3D · Jᵀ.\n */\nconst covariance3D = /* wgsl */`\n    let sx = exp(lsX);\n    let sy = exp(lsY);\n    let sz = exp(lsZ);\n\n    let m00 = r00 * sx; let m01 = r01 * sy; let m02 = r02 * sz;\n    let m10 = r10 * sx; let m11 = r11 * sy; let m12 = r12 * sz;\n    let m20 = r20 * sx; let m21 = r21 * sy; let m22 = r22 * sz;\n\n    let sig00 = m00 * m00 + m01 * m01 + m02 * m02;\n    let sig01 = m00 * m10 + m01 * m11 + m02 * m12;\n    let sig02 = m00 * m20 + m01 * m21 + m02 * m22;\n    let sig11 = m10 * m10 + m11 * m11 + m12 * m12;\n    let sig12 = m10 * m20 + m11 * m21 + m12 * m22;\n    let sig22 = m20 * m20 + m21 * m21 + m22 * m22;\n\n    let v00 = uniforms.rightX; let v01 = uniforms.rightY; let v02 = uniforms.rightZ;\n    let v10 = uniforms.downX; let v11 = uniforms.downY; let v12 = uniforms.downZ;\n    let v20 = uniforms.forwardX; let v21 = uniforms.forwardY; let v22 = uniforms.forwardZ;\n\n    let t00 = v00 * sig00 + v01 * sig01 + v02 * sig02;\n    let t01 = v00 * sig01 + v01 * sig11 + v02 * sig12;\n    let t02 = v00 * sig02 + v01 * sig12 + v02 * sig22;\n    let t10 = v10 * sig00 + v11 * sig01 + v12 * sig02;\n    let t11 = v10 * sig01 + v11 * sig11 + v12 * sig12;\n    let t12 = v10 * sig02 + v11 * sig12 + v12 * sig22;\n    let t20 = v20 * sig00 + v21 * sig01 + v22 * sig02;\n    let t21 = v20 * sig01 + v21 * sig11 + v22 * sig12;\n    let t22 = v20 * sig02 + v21 * sig12 + v22 * sig22;\n\n    let c00 = t00 * v00 + t01 * v01 + t02 * v02;\n    let c01 = t00 * v10 + t01 * v11 + t02 * v12;\n    let c02 = t00 * v20 + t01 * v21 + t02 * v22;\n    let c11 = t10 * v10 + t11 * v11 + t12 * v12;\n    let c12 = t10 * v20 + t11 * v21 + t12 * v22;\n    let c22 = t20 * v20 + t21 * v21 + t22 * v22;\n`;\n\nexport { covariance3D };\n","/**\n * Equirect Jacobian + 2D EWA covariance.\n *\n * Reads:   cx, cy, cz, r2, rxz, rxzClamped, imgWf, imgHf, invTwoPi, invPi,\n *          c00, c01, c02, c11, c12, c22 (camera-space 3D covariance)\n * Defines: cov00 (var), cov01 (let), cov11 (var)\n *\n * With longitude θ = atan2(cx, cz) and latitude φ = asin(cy/r) (cy is\n * the camera-down axis, so φ > 0 = below the horizon), the per-axis\n * screen derivatives multiplied by the pixel scales (kx, ky) =\n * (W/(2π), H/π) give the 2×3 Jacobian:\n *\n *   ∂screenX/∂(cx,cy,cz) = kx · ( cz/rxz²,  0,             -cx/rxz² )\n *   ∂screenY/∂(cx,cy,cz) = ky · (-cx·cy/(r²·rxz),  rxz/r²,  -cy·cz/(r²·rxz) )\n *\n * rxzClamped (>= POLE_EPS·r, set by the projection chunk) keeps every\n * denominator finite as a splat approaches the pole. j[0][1] = 0 but\n * j[1][0] != 0, so cov = J·Σ·Jᵀ carries the extra u00·jy0 / u10·jy0 /\n * u11·jy0 terms that the pinhole simplification dropped.\n */\nconst jacobianEquirect = /* wgsl */`\n    let kx = imgWf * invTwoPi;\n    let ky = imgHf * invPi;\n    let invRxzC2 = 1.0 / (rxzClamped * rxzClamped);\n    let invR2 = 1.0 / r2;\n    let invR2Rxz = invR2 / rxzClamped;\n    let jx0 =  kx * cz * invRxzC2;\n    let jx2 = -kx * cx * invRxzC2;\n    let jy0 = -ky * cx * cy * invR2Rxz;\n    let jy1 =  ky * rxzClamped * invR2;\n    let jy2 = -ky * cy * cz * invR2Rxz;\n\n    let u00 = jx0 * c00 + jx2 * c02;\n    let u01 = jx0 * c01 + jx2 * c12;\n    let u02 = jx0 * c02 + jx2 * c22;\n    let u10 = jy0 * c00 + jy1 * c01 + jy2 * c02;\n    let u11 = jy0 * c01 + jy1 * c11 + jy2 * c12;\n    let u12 = jy0 * c02 + jy1 * c12 + jy2 * c22;\n\n    var cov00 = u00 * jx0 + u02 * jx2;\n    let cov01 = u00 * jy0 + u01 * jy1 + u02 * jy2;\n    var cov11 = u10 * jy0 + u11 * jy1 + u12 * jy2;\n`;\n\nexport { jacobianEquirect };\n","/**\n * Pinhole Jacobian + 2D EWA covariance.\n *\n * Reads:   cx, cy, cz, invZ, uniforms.focalX, uniforms.focalY,\n *          uniforms.imageWidth, uniforms.imageHeight,\n *          c00, c01, c02, c11, c12, c22 (camera-space 3D covariance),\n *          JACOBIAN_LIMIT_FACTOR (from constants chunk)\n * Defines: cov00 (var), cov01 (let), cov11 (var)\n *\n * J is the 2×3 matrix\n *   [[jx0,   0, jx2],\n *    [  0, jy1, jy2]]\n * with x/z and y/z clamped to JACOBIAN_LIMIT_FACTOR · tan(half-FOV) so\n * splats outside the cone don't blow up the EWA approximation. The zero\n * entries (j[0][1] = 0, j[1][0] = 0) let us drop the u01·jy0 / u10 /\n * u11·jy0 terms in cov = J·Σ·Jᵀ that the equirect path retains.\n */\nconst jacobianPinhole = /* wgsl */`\n    let limX = JACOBIAN_LIMIT_FACTOR * (f32(uniforms.imageWidth) * 0.5) / uniforms.focalX;\n    let limY = JACOBIAN_LIMIT_FACTOR * (f32(uniforms.imageHeight) * 0.5) / uniforms.focalY;\n    let txtz = clamp(cx * invZ, -limX, limX);\n    let tytz = clamp(cy * invZ, -limY, limY);\n    let jcx = txtz * cz;\n    let jcy = tytz * cz;\n    let jx0 = uniforms.focalX * invZ;\n    let jx2 = -uniforms.focalX * jcx * invZ * invZ;\n    let jy1 = uniforms.focalY * invZ;\n    let jy2 = -uniforms.focalY * jcy * invZ * invZ;\n\n    let u00 = jx0 * c00 + jx2 * c02;\n    let u01 = jx0 * c01 + jx2 * c12;\n    let u02 = jx0 * c02 + jx2 * c22;\n    let u11 = jy1 * c11 + jy2 * c12;\n    let u12 = jy1 * c12 + jy2 * c22;\n\n    var cov00 = u00 * jx0 + u02 * jx2;\n    let cov01 = u01 * jy1 + u02 * jy2;\n    var cov11 = u11 * jy1 + u12 * jy2;\n`;\n\nexport { jacobianPinhole };\n","/**\n * Equirect near-radius cull + spherical (atan2/asin) screen mapping +\n * pole-clamp setup used by the equirect Jacobian.\n *\n * Reads:   cx, cy, cz, uniforms.near, uniforms.imageWidth, uniforms.imageHeight,\n *          POLE_EPS (from constants chunk)\n * Defines: r2, r, rxz2, rxz, rxzClamped, invTwoPi, invPi, imgWf, imgHf,\n *          lon, sinLat, lat, screenX, screenY\n *\n * Splats inside the near sphere (r <= near) are written invalid and the\n * shader returns. The longitude atan2 is undefined at the camera origin\n * and degenerates near the poles where rxz → 0; rxzClamped (>= POLE_EPS·r)\n * keeps every denominator in the Jacobian chunk finite for splats\n * arbitrarily close to the zenith / nadir.\n *\n * Convention: cy is the camera-down axis, so cy > 0 = below horizon →\n * lat > 0 → screenY in the bottom half. screenY = 0 maps to the zenith\n * (above the camera).\n */\nconst projectionEquirect = /* wgsl */`\n    let r2 = cx * cx + cy * cy + cz * cz;\n    if (r2 <= uniforms.near * uniforms.near) { writeInvalid(i); return; }\n    let r = sqrt(r2);\n    let rxz2 = cx * cx + cz * cz;\n    let rxz = sqrt(rxz2);\n    let rxzClamped = max(rxz, POLE_EPS * r);\n\n    let invTwoPi: f32 = 0.15915494309189535;\n    let invPi:    f32 = 0.3183098861837907;\n    let imgWf = f32(uniforms.imageWidth);\n    let imgHf = f32(uniforms.imageHeight);\n    let lon = atan2(cx, cz);\n    let sinLat = clamp(cy / r, -1.0, 1.0);\n    let lat = asin(sinLat);\n    let screenX = (lon * invTwoPi + 0.5) * imgWf;\n    let screenY = (lat * invPi + 0.5) * imgHf;\n`;\n\nexport { projectionEquirect };\n","/**\n * Pinhole near-plane cull + perspective screen mapping.\n *\n * Reads:   cx, cy, cz, uniforms.near, uniforms.focalX, uniforms.focalY,\n *          uniforms.imageWidth, uniforms.imageHeight\n * Defines: invZ, screenX, screenY\n *\n * Splats with cz <= near are written invalid and the shader returns.\n */\nconst projectionPinhole = /* wgsl */`\n    if (cz <= uniforms.near) { writeInvalid(i); return; }\n\n    let invZ = 1.0 / cz;\n    let screenX = uniforms.focalX * cx * invZ + f32(uniforms.imageWidth) * 0.5;\n    let screenY = uniforms.focalY * cy * invZ + f32(uniforms.imageHeight) * 0.5;\n`;\n\nexport { projectionPinhole };\n","/**\n * Quaternion → 3×3 rotation matrix, with early-out on zero-length quat.\n *\n * Reads:   rotW, rotX, rotY, rotZ (raw input quat components from the\n *          splat decode)\n * Defines: r00..r22 (rotation matrix entries, row-major)\n * Returns: early via writeInvalid + return if the quaternion has zero\n *          length (degenerate splat)\n *\n * Normalises the quaternion first so the rotation matrix is orthonormal\n * even if the upstream data stored an unnormalised quat.\n */\nconst quatRotation = /* wgsl */`\n    let qlen2 = rotW * rotW + rotX * rotX + rotY * rotY + rotZ * rotZ;\n    if (qlen2 == 0.0) { writeInvalid(i); return; }\n    let invQ = inverseSqrt(qlen2);\n    let qw = rotW * invQ;\n    let qx = rotX * invQ;\n    let qy = rotY * invQ;\n    let qz = rotZ * invQ;\n\n    let xx = qx * qx; let yy = qy * qy; let zz = qz * qz;\n    let xy = qx * qy; let xzq = qx * qz; let yz = qy * qz;\n    let wxq = qw * qx; let wy_ = qw * qy; let wzq = qw * qz;\n    let r00 = 1.0 - 2.0 * (yy + zz);\n    let r01 = 2.0 * (xy - wzq);\n    let r02 = 2.0 * (xzq + wy_);\n    let r10 = 2.0 * (xy + wzq);\n    let r11 = 1.0 - 2.0 * (xx + zz);\n    let r12 = 2.0 * (yz - wxq);\n    let r20 = 2.0 * (xzq - wy_);\n    let r21 = 2.0 * (yz + wxq);\n    let r22 = 1.0 - 2.0 * (xx + yy);\n`;\n\nexport { quatRotation };\n","/**\n * Spherical-harmonics degree-1 evaluation (3 coefficients per channel).\n *\n * Reads:   dirX, dirY, dirZ, base, splats, COEFFS_PER_CHANNEL,\n *          SH_C1\n * Defines: (mutates) cR, cG, cB\n *\n * Appends the band-1 contribution to the accumulating per-channel color\n * radiance. Channel-major SH layout: `f_rest_0..N-1` red, then green,\n * then blue.\n */\nconst shBand1 = /* wgsl */`\n    {\n        let n = COEFFS_PER_CHANNEL;\n        let shBase = base + 14u;\n        let b0 = -SH_C1 * dirY;\n        let b1 = SH_C1 * dirZ;\n        let b2 = -SH_C1 * dirX;\n        cR = cR + b0 * splats[shBase + 0u] + b1 * splats[shBase + 1u] + b2 * splats[shBase + 2u];\n        cG = cG + b0 * splats[shBase + n + 0u] + b1 * splats[shBase + n + 1u] + b2 * splats[shBase + n + 2u];\n        cB = cB + b0 * splats[shBase + 2u * n + 0u] + b1 * splats[shBase + 2u * n + 1u] + b2 * splats[shBase + 2u * n + 2u];\n    }\n`;\n\nexport { shBand1 };\n","/**\n * Spherical-harmonics degree-2 evaluation (5 additional coefficients per\n * channel, indices [3..7]).\n *\n * Reads:   dirX, dirY, dirZ, base, splats, COEFFS_PER_CHANNEL,\n *          SH_C2_0, SH_C2_1, SH_C2_2, SH_C2_3, SH_C2_4\n * Defines: (mutates) cR, cG, cB\n */\nconst shBand2 = /* wgsl */`\n    {\n        let n = COEFFS_PER_CHANNEL;\n        let shBase = base + 14u;\n        let xx2 = dirX * dirX;\n        let yy2 = dirY * dirY;\n        let zz2 = dirZ * dirZ;\n        let xy2 = dirX * dirY;\n        let yz2 = dirY * dirZ;\n        let xz2 = dirX * dirZ;\n        let b3 = SH_C2_0 * xy2;\n        let b4 = SH_C2_1 * yz2;\n        let b5 = SH_C2_2 * (2.0 * zz2 - xx2 - yy2);\n        let b6 = SH_C2_3 * xz2;\n        let b7 = SH_C2_4 * (xx2 - yy2);\n        cR = cR + b3 * splats[shBase + 3u] + b4 * splats[shBase + 4u] + b5 * splats[shBase + 5u] + b6 * splats[shBase + 6u] + b7 * splats[shBase + 7u];\n        cG = cG + b3 * splats[shBase + n + 3u] + b4 * splats[shBase + n + 4u] + b5 * splats[shBase + n + 5u] + b6 * splats[shBase + n + 6u] + b7 * splats[shBase + n + 7u];\n        cB = cB + b3 * splats[shBase + 2u * n + 3u] + b4 * splats[shBase + 2u * n + 4u] + b5 * splats[shBase + 2u * n + 5u] + b6 * splats[shBase + 2u * n + 6u] + b7 * splats[shBase + 2u * n + 7u];\n    }\n`;\n\nexport { shBand2 };\n","/**\n * Spherical-harmonics degree-3 evaluation (7 additional coefficients per\n * channel, indices [8..14]).\n *\n * Reads:   dirX, dirY, dirZ, base, splats, COEFFS_PER_CHANNEL,\n *          SH_C3_0, SH_C3_1, SH_C3_2, SH_C3_3, SH_C3_4, SH_C3_5, SH_C3_6\n * Defines: (mutates) cR, cG, cB\n */\nconst shBand3 = /* wgsl */`\n    {\n        let n = COEFFS_PER_CHANNEL;\n        let shBase = base + 14u;\n        let xx2 = dirX * dirX;\n        let yy2 = dirY * dirY;\n        let zz2 = dirZ * dirZ;\n        let xy2 = dirX * dirY;\n        let b8 = SH_C3_0 * dirY * (3.0 * xx2 - yy2);\n        let b9 = SH_C3_1 * xy2 * dirZ;\n        let b10 = SH_C3_2 * dirY * (4.0 * zz2 - xx2 - yy2);\n        let b11 = SH_C3_3 * dirZ * (2.0 * zz2 - 3.0 * xx2 - 3.0 * yy2);\n        let b12 = SH_C3_4 * dirX * (4.0 * zz2 - xx2 - yy2);\n        let b13 = SH_C3_5 * dirZ * (xx2 - yy2);\n        let b14 = SH_C3_6 * dirX * (xx2 - 3.0 * yy2);\n        cR = cR + b8 * splats[shBase + 8u] + b9 * splats[shBase + 9u] + b10 * splats[shBase + 10u] + b11 * splats[shBase + 11u] + b12 * splats[shBase + 12u] + b13 * splats[shBase + 13u] + b14 * splats[shBase + 14u];\n        cG = cG + b8 * splats[shBase + n + 8u] + b9 * splats[shBase + n + 9u] + b10 * splats[shBase + n + 10u] + b11 * splats[shBase + n + 11u] + b12 * splats[shBase + n + 12u] + b13 * splats[shBase + n + 13u] + b14 * splats[shBase + n + 14u];\n        cB = cB + b8 * splats[shBase + 2u * n + 8u] + b9 * splats[shBase + 2u * n + 9u] + b10 * splats[shBase + 2u * n + 10u] + b11 * splats[shBase + 2u * n + 11u] + b12 * splats[shBase + 2u * n + 12u] + b13 * splats[shBase + 2u * n + 13u] + b14 * splats[shBase + 2u * n + 14u];\n    }\n`;\n\nexport { shBand3 };\n","/**\n * Equirect per-splat tile-coverage count.\n *\n * Reads:   screenX, screenY, radius, tsz, gox, goy,\n *          uniforms.groupTilesX, uniforms.groupTilesY\n * Defines: writes coverage[i]\n *\n * The X tile range can extend past the image edges into negative or\n * `> groupTilesX-1` indices — those represent the same splat seen\n * across the ±π longitude seam. Coverage is the raw X span (capped at\n * groupTilesX so a splat with radius > image_width doesn't emit\n * duplicate tile keys); emit-pairs walks [minTXraw .. maxTXraw] in\n * lock-step and applies a modular wrap when writing tile keys. Y is\n * clamped normally — equirect doesn't wrap across poles.\n *\n * @param maxCoveragePerSplat - Hard upper bound on per-splat tile count.\n * @returns WGSL source for the equirect tile-coverage block.\n */\nconst tileAabbEquirect = (maxCoveragePerSplat: number) => /* wgsl */`\n    let minTXraw = i32(floor((screenX - radius - gox) / tsz));\n    let maxTXraw = i32(floor((screenX + radius - gox) / tsz));\n    let txCountRaw = maxTXraw - minTXraw + 1;\n    let txCount = min(txCountRaw, i32(uniforms.groupTilesX));\n    let minTY = max(0, i32(floor((screenY - radius - goy) / tsz)));\n    let maxTY = min(i32(uniforms.groupTilesY) - 1, i32(floor((screenY + radius - goy) / tsz)));\n    if (txCount <= 0 || maxTY < minTY) {\n        coverage[i] = 0u;\n    } else {\n        let raw = u32(txCount) * u32(maxTY - minTY + 1);\n        coverage[i] = min(raw, ${maxCoveragePerSplat}u);\n    }\n`;\n\nexport { tileAabbEquirect };\n","/**\n * Pinhole per-splat tile-coverage count.\n *\n * Reads:   screenX, screenY, radius, tsz, gox, goy,\n *          uniforms.groupTilesX, uniforms.groupTilesY\n * Defines: writes coverage[i]\n *\n * Computes the splat's clamped tile bbox and stores the area\n * (`(maxTX - minTX + 1) · (maxTY - minTY + 1)`, capped at\n * MAX_COVERAGE_PER_SPLAT) into `coverage[i]`. The emit-pairs shader\n * later walks the same clamped bbox via its own pinhole tile-walk\n * chunk.\n *\n * Embeds the per-render MAX_COVERAGE_PER_SPLAT cap via JS-template\n * substitution because the value is fixed at shader-construction time\n * (it tracks the group's tile area).\n *\n * @param maxCoveragePerSplat - Hard upper bound on per-splat tile count.\n * @returns WGSL source for the pinhole tile-coverage block.\n */\nconst tileAabbPinhole = (maxCoveragePerSplat: number) => /* wgsl */`\n    let minTX = max(0, i32(floor((screenX - radius - gox) / tsz)));\n    let maxTX = min(i32(uniforms.groupTilesX) - 1, i32(floor((screenX + radius - gox) / tsz)));\n    let minTY = max(0, i32(floor((screenY - radius - goy) / tsz)));\n    let maxTY = min(i32(uniforms.groupTilesY) - 1, i32(floor((screenY + radius - goy) / tsz)));\n    if (maxTX < minTX || maxTY < minTY) {\n        coverage[i] = 0u;\n    } else {\n        let raw = u32(maxTX - minTX + 1) * u32(maxTY - minTY + 1);\n        coverage[i] = min(raw, ${maxCoveragePerSplat}u);\n    }\n`;\n\nexport { tileAabbPinhole };\n","/**\n * Equirect emit-pairs tile walk with ±π longitude seam wrap.\n *\n * Reads:   sX, sY, radius, tsz, gox, goy, cap, i,\n *          uniforms.groupTilesX, uniforms.groupTilesY\n * Defines: writes (tileKeys, splatValues) pairs for this splat's bbox\n * Returns: early if the bbox is empty\n *\n * Recomputes the raw X range (possibly wrapping past the seam) — must\n * match the project shader's `tile-aabb-equirect` coverage computation\n * exactly. Each emitted tx is wrapped into [0, groupTilesX-1] via\n * modular arithmetic. The rasterize-binned shader compensates by\n * wrapping its per-pixel dx into [-W/2, W/2], so a wrapped tile pulls\n * the splat's footprint from the correct copy across the seam.\n */\nconst tileWalkEquirect = /* wgsl */`\n    let minTXraw = i32(floor((sX - radius - gox) / tsz));\n    let maxTXraw = i32(floor((sX + radius - gox) / tsz));\n    let txCountRaw = maxTXraw - minTXraw + 1;\n    let groupTilesX_i = i32(uniforms.groupTilesX);\n    let txCount = min(txCountRaw, groupTilesX_i);\n    let minTY = max(0, i32(floor((sY - radius - goy) / tsz)));\n    let maxTY = min(i32(uniforms.groupTilesY) - 1, i32(floor((sY + radius - goy) / tsz)));\n    if (txCount <= 0 || maxTY < minTY) { return; }\n\n    var slot = emitOffset[i];\n    let end = slot + cap;\n    for (var ty: i32 = minTY; ty <= maxTY; ty = ty + 1) {\n        if (slot >= end) { break; }\n        for (var k: i32 = 0; k < txCount; k = k + 1) {\n            if (slot >= end) { break; }\n            var tx = (minTXraw + k) % groupTilesX_i;\n            if (tx < 0) { tx = tx + groupTilesX_i; }\n            let t = u32(ty) * uniforms.groupTilesX + u32(tx);\n            tileKeys[slot] = t;\n            splatValues[slot] = i;\n            slot = slot + 1u;\n        }\n    }\n`;\n\nexport { tileWalkEquirect };\n","/**\n * Pinhole emit-pairs tile walk.\n *\n * Reads:   sX, sY, radius, tsz, gox, goy, cap, i,\n *          uniforms.groupTilesX, uniforms.groupTilesY\n * Defines: writes (tileKeys, splatValues) pairs for this splat's bbox\n * Returns: early if the bbox is empty\n *\n * Walks the clamped per-splat tile bbox row-major and writes (tile,\n * splat) pair entries until either the bbox is exhausted or the\n * `coverage[i]` cap is hit. Mirrors the bbox computed by the pinhole\n * project shader's `tile-aabb-pinhole` chunk.\n */\nconst tileWalkPinhole = /* wgsl */`\n    let minTX = max(0, i32(floor((sX - radius - gox) / tsz)));\n    let maxTX = min(i32(uniforms.groupTilesX) - 1, i32(floor((sX + radius - gox) / tsz)));\n    let minTY = max(0, i32(floor((sY - radius - goy) / tsz)));\n    let maxTY = min(i32(uniforms.groupTilesY) - 1, i32(floor((sY + radius - goy) / tsz)));\n    if (maxTX < minTX || maxTY < minTY) { return; }\n\n    var slot = emitOffset[i];\n    let end = slot + cap;\n    for (var ty: i32 = minTY; ty <= maxTY; ty = ty + 1) {\n        if (slot >= end) { break; }\n        for (var tx: i32 = minTX; tx <= maxTX; tx = tx + 1) {\n            if (slot >= end) { break; }\n            let t = u32(ty) * uniforms.groupTilesX + u32(tx);\n            tileKeys[slot] = t;\n            splatValues[slot] = i;\n            slot = slot + 1u;\n        }\n    }\n`;\n\nexport { tileWalkPinhole };\n","/**\n * Packs the running-state (linear color + residual transmittance) into a\n * single RGBA8-packed u32 per group pixel. Composites the user-supplied\n * background under the residual transmittance so the final image carries\n * the chosen `bgR/bgG/bgB/bgA` everywhere the splats didn't fully cover.\n *\n * @returns WGSL source for the finalize compute shader.\n */\nconst finalizeWgsl = () => /* wgsl */`\n#include \"uniformsStruct\"\n#include \"constants\"\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var<storage, read> runningState: array<vec4<f32>>;\n@group(0) @binding(2) var<storage, read_write> output: array<u32>;\n\n@compute @workgroup_size(TILE_SIZE, TILE_SIZE, 1)\nfn main(\n    @builtin(workgroup_id) wgId: vec3<u32>,\n    @builtin(local_invocation_id) lid: vec3<u32>\n) {\n    if (wgId.x >= uniforms.groupTilesX || wgId.y >= uniforms.groupTilesY) { return; }\n\n    let localPixelX = wgId.x * TILE_SIZE + lid.x;\n    let localPixelY = wgId.y * TILE_SIZE + lid.y;\n    let groupPixelW = uniforms.groupTilesX * TILE_SIZE;\n\n    let pixelIdx = localPixelY * groupPixelW + localPixelX;\n    let state = runningState[pixelIdx];\n\n    let color = state.rgb + state.a * vec3<f32>(uniforms.bgR, uniforms.bgG, uniforms.bgB);\n    let alphaOut = (1.0 - state.a) + state.a * uniforms.bgA;\n\n    let r = u32(clamp(color.r, 0.0, 1.0) * 255.0 + 0.5);\n    let g = u32(clamp(color.g, 0.0, 1.0) * 255.0 + 0.5);\n    let bch = u32(clamp(color.b, 0.0, 1.0) * 255.0 + 0.5);\n    let aOut = u32(clamp(alphaOut, 0.0, 1.0) * 255.0 + 0.5);\n\n    output[pixelIdx] = r | (g << 8u) | (bch << 16u) | (aOut << 24u);\n}\n`;\n\nexport { finalizeWgsl };\n","/**\n * For every adjacent pair of sorted keys where the high-bit tile index\n * differs, atomicMin's the current position into `tileOffsets[t]` for\n * every tile `t` in `(prevTile, curTile]`. Combined with the sentinel\n * init this gives `tileOffsets[T]` = first index in `sortedKeys` whose\n * tile bits equal T (or the sentinel if T is empty).\n *\n * Dispatched indirectly with workgroup count `ceil(totalPairs / 64)` so\n * that we don't waste invocations on the unused tail of the pairs\n * buffer.\n *\n * @returns WGSL source for the find-boundaries compute shader.\n */\nconst findBoundariesWgsl = () => /* wgsl */`\n#include \"uniformsStruct\"\n#include \"constants\"\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var<storage, read> totalPairs: array<u32>;\n@group(0) @binding(2) var<storage, read> sortedTileKeys: array<u32>;\n@group(0) @binding(3) var<storage, read_write> tileOffsets: array<atomic<u32>>;\n\n@compute @workgroup_size(64)\nfn main(\n    @builtin(workgroup_id) wgId: vec3<u32>,\n    @builtin(num_workgroups) numWg: vec3<u32>,\n    @builtin(local_invocation_id) lid: vec3<u32>\n) {\n    // 2-D dispatch (prepare-indirect splits to stay under the 65535\n    // per-axis workgroup-count limit); linearise here.\n    let linearWg = wgId.x + wgId.y * numWg.x;\n    let i = linearWg * 64u + lid.x;\n    let n = totalPairs[0];\n    if (i >= n) { return; }\n\n    // Reference uniforms once so the binding isn't dead-code-stripped\n    // (keeps the BG format in sync with the shader expectations).\n    let _u = uniforms.groupTilesX;\n\n    let curTile = sortedTileKeys[i];\n    // Sentinel for \"no previous tile\" — overflow makes prevTile+1 = 0u\n    // so the for loop below cleanly handles the i = 0 case.\n    let prevTileBits = select(0xFFFFFFFFu, sortedTileKeys[i - 1u], i > 0u);\n    if (curTile == prevTileBits) { return; }\n    for (var t: u32 = prevTileBits + 1u; t <= curTile; t = t + 1u) {\n        atomicMin(&tileOffsets[t], i);\n    }\n}\n`;\n\nexport { findBoundariesWgsl };\n","/**\n * Initialises `tileOffsets[0 .. numTiles]` to the sentinel value\n * `totalPairs[0]` (= past-the-end). `findBoundaries` then atomicMin's\n * the actual first-pair-index for every non-empty tile; tiles with no\n * pairs keep the sentinel, which collapses to a zero-length slice when\n * the rasterize-binned shader reads `tileOffsets[T] .. tileOffsets[T+1]`.\n *\n * @returns WGSL source for the init-tile-offsets compute shader.\n */\nconst initTileOffsetsWgsl = () => /* wgsl */`\n#include \"uniformsStruct\"\n#include \"constants\"\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var<storage, read> totalPairs: array<u32>;\n@group(0) @binding(2) var<storage, read_write> tileOffsets: array<u32>;\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n    let i = gid.x;\n    let numTiles = uniforms.groupTilesX * uniforms.groupTilesY;\n    if (i > numTiles) { return; }\n    tileOffsets[i] = totalPairs[0];\n}\n`;\n\nexport { initTileOffsetsWgsl };\n","/**\n * Single-workgroup exclusive prefix-sum of the project shader's\n * per-splat `coverage[]` into `emitOffset[]`. Also writes the total\n * pair count into `totalPairs[0]` so downstream kernels and the radix\n * sort can size their dispatches without a CPU round trip.\n *\n * Layout: 256 threads, each processes `SCAN_PER_THREAD` elements\n * serially (chosen so that 256 × SCAN_PER_THREAD ≥ chunkCap). Phase 1\n * computes a per-thread partial sum; phase 2 has thread 0 scan the 256\n * partials in shared memory (negligible vs the 800-element block work);\n * phase 3 each thread re-walks its block writing the exclusive prefix.\n *\n * @param scanPerThread - Per-thread element budget; must satisfy `256 * scanPerThread >= chunkCap`.\n * @returns WGSL source for the prefix-sum compute shader.\n */\nconst prefixSumWgsl = (scanPerThread: number) => /* wgsl */`\n#include \"uniformsStruct\"\n#include \"constants\"\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var<storage, read> coverage: array<u32>;\n@group(0) @binding(2) var<storage, read_write> emitOffset: array<u32>;\n@group(0) @binding(3) var<storage, read_write> totalPairs: array<u32>;\n\nconst SCAN_THREADS: u32 = 256u;\nconst SCAN_PER_THREAD: u32 = ${scanPerThread}u;\n\nvar<workgroup> scratch: array<u32, SCAN_THREADS>;\n\n@compute @workgroup_size(SCAN_THREADS)\nfn main(@builtin(local_invocation_id) lid: vec3<u32>) {\n    let tid = lid.x;\n    let n = uniforms.chunkSize;\n    let base = tid * SCAN_PER_THREAD;\n\n    var partial: u32 = 0u;\n    for (var i: u32 = 0u; i < SCAN_PER_THREAD; i = i + 1u) {\n        let idx = base + i;\n        if (idx < n) {\n            partial = partial + coverage[idx];\n        }\n    }\n    scratch[tid] = partial;\n    workgroupBarrier();\n\n    if (tid == 0u) {\n        var acc: u32 = 0u;\n        for (var i: u32 = 0u; i < SCAN_THREADS; i = i + 1u) {\n            let v = scratch[i];\n            scratch[i] = acc;\n            acc = acc + v;\n        }\n        totalPairs[0] = acc;\n    }\n    workgroupBarrier();\n\n    var prefix: u32 = scratch[tid];\n    for (var i: u32 = 0u; i < SCAN_PER_THREAD; i = i + 1u) {\n        let idx = base + i;\n        if (idx < n) {\n            emitOffset[idx] = prefix;\n            prefix = prefix + coverage[idx];\n        }\n    }\n}\n`;\n\nexport { prefixSumWgsl };\n","/**\n * Prepares indirect-dispatch arguments by reading `totalPairs[0]` and\n * writing workgroup counts into two slots of the device's\n * `indirectDispatchBuffer` (each slot is 3 × u32 = `(x, y, z)`):\n *\n *   - `sortSlot`: workgroup count for `ComputeRadixSort.sortIndirect`,\n *     computed as `ceil(totalPairs / 2048)` (matches the radix sort's\n *     16×16 thread × 8 elements / thread = 2048 elements/workgroup).\n *   - `boundariesSlot`: workgroup count for `findBoundaries`, computed\n *     as `ceil(totalPairs / 64)`.\n *\n * Slot byte offsets are passed in via two u32 uniforms in a small ad-hoc\n * uniform block (NOT the shared `Uniforms` struct, because the slot\n * indices vary per chunk while the shared uniforms are set per group).\n *\n * @returns WGSL source for the prepare-indirect compute shader.\n */\nconst prepareIndirectWgsl = () => /* wgsl */`\nstruct PrepareUniforms {\n    sortSlotBase: u32,\n    boundariesSlotBase: u32,\n}\n\n@group(0) @binding(0) var<uniform> uniforms: PrepareUniforms;\n@group(0) @binding(1) var<storage, read> totalPairs: array<u32>;\n@group(0) @binding(2) var<storage, read_write> indirectBuffer: array<u32>;\n\nconst SORT_ELEMENTS_PER_WG: u32 = 2048u;\nconst BOUNDARIES_THREADS_PER_WG: u32 = 64u;\n// WebGPU spec minimum for maxComputeWorkgroupsPerDimension. Any larger\n// 1-D dispatch must be tiled into 2-D so both axes stay <= this bound.\n// The consumer shaders linearise via WORKGROUP_ID = w_id.x + w_id.y * w_dim.x.\nconst MAX_DIM: u32 = 65535u;\n\nfn splitWg(count: u32) -> vec2<u32> {\n    if (count <= MAX_DIM) {\n        return vec2<u32>(count, 1u);\n    }\n    let y = (count + MAX_DIM - 1u) / MAX_DIM;\n    let x = (count + y - 1u) / y;\n    return vec2<u32>(x, y);\n}\n\n@compute @workgroup_size(1)\nfn main() {\n    let n = totalPairs[0];\n    let sortWg = (n + SORT_ELEMENTS_PER_WG - 1u) / SORT_ELEMENTS_PER_WG;\n    let bndWg = (n + BOUNDARIES_THREADS_PER_WG - 1u) / BOUNDARIES_THREADS_PER_WG;\n    let sortDim = splitWg(sortWg);\n    let bndDim = splitWg(bndWg);\n    let s = uniforms.sortSlotBase;\n    let b = uniforms.boundariesSlotBase;\n    indirectBuffer[s + 0u] = sortDim.x;\n    indirectBuffer[s + 1u] = sortDim.y;\n    indirectBuffer[s + 2u] = 1u;\n    indirectBuffer[b + 0u] = bndDim.x;\n    indirectBuffer[b + 1u] = bndDim.y;\n    indirectBuffer[b + 2u] = 1u;\n}\n`;\n\nexport { prepareIndirectWgsl };\n","/**\n * WGSL source for the project compute. Reads raw splat fields from the\n * per-slot input buffer, evaluates SH for view-dependent color, computes\n * 2D inverse covariance + screen-space 3σ radius, and writes a packed\n * projection record per gaussian. Invalid splats (behind near, degenerate\n * covariance, outside group AABB) are written with `radius = 0` so the\n * rasterizer can early-out on the first vec4 load.\n *\n * Projection-mode variation (pinhole vs equirect) is handled at WGSL\n * preprocessor time via `#ifdef PROJECTION_EQUIRECT` blocks that pull\n * in the projection-specific chunks (screen mapping + Jacobian + tile\n * AABB). The per-render `MAX_COVERAGE_PER_SPLAT` cap is similarly\n * embedded by the tile-AABB chunk via JS-template substitution at\n * construction time (see `sharedCincludes` in the rasterizer ctor).\n *\n * @param coeffsPerChannel - Per-channel SH coefficient count (0/3/8/15).\n * @returns WGSL source for the project compute shader.\n */\nconst projectWgsl = (coeffsPerChannel: number) => /* wgsl */`\n#include \"uniformsStruct\"\n#include \"constants\"\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var<storage, read> splats: array<f32>;\n@group(0) @binding(2) var<storage, read_write> projected: array<vec4<f32>>;\n@group(0) @binding(3) var<storage, read_write> coverage: array<u32>;\n\nconst SH_C0: f32 = 0.28209479177387814;\nconst SH_C1: f32 = 0.4886025119029199;\nconst SH_C2_0: f32 = 1.0925484305920792;\nconst SH_C2_1: f32 = -1.0925484305920792;\nconst SH_C2_2: f32 = 0.31539156525252005;\nconst SH_C2_3: f32 = -1.0925484305920792;\nconst SH_C2_4: f32 = 0.5462742152960396;\nconst SH_C3_0: f32 = -0.5900435899266435;\nconst SH_C3_1: f32 = 2.890611442640554;\nconst SH_C3_2: f32 = -0.4570457994644658;\nconst SH_C3_3: f32 = 0.3731763325901154;\nconst SH_C3_4: f32 = -0.4570457994644658;\nconst SH_C3_5: f32 = 1.445305721320277;\nconst SH_C3_6: f32 = -0.5900435899266435;\n\nconst COEFFS_PER_CHANNEL: u32 = ${coeffsPerChannel}u;\n\nfn writeInvalid(idx: u32) {\n    projected[idx * 3u + 0u] = vec4<f32>(0.0, 0.0, 0.0, 0.0);\n    projected[idx * 3u + 1u] = vec4<f32>(0.0, 0.0, 0.0, 0.0);\n    projected[idx * 3u + 2u] = vec4<f32>(0.0, 0.0, 0.0, 0.0);\n    coverage[idx] = 0u;\n}\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n    let i = gid.x;\n    if (i >= uniforms.chunkSize) { return; }\n\n    let base = i * uniforms.splatStride;\n\n    let posX = splats[base + 0u];\n    let posY = splats[base + 1u];\n    let posZ = splats[base + 2u];\n    let rotW = splats[base + 3u];\n    let rotX = splats[base + 4u];\n    let rotY = splats[base + 5u];\n    let rotZ = splats[base + 6u];\n    let lsX = splats[base + 7u];\n    let lsY = splats[base + 8u];\n    let lsZ = splats[base + 9u];\n    let opacity = splats[base + 10u];\n    let fdcR = splats[base + 11u];\n    let fdcG = splats[base + 12u];\n    let fdcB = splats[base + 13u];\n\n    // World → camera\n    let wx = posX - uniforms.eyeX;\n    let wy = posY - uniforms.eyeY;\n    let wz = posZ - uniforms.eyeZ;\n    let cx = uniforms.rightX * wx + uniforms.rightY * wy + uniforms.rightZ * wz;\n    let cy = uniforms.downX * wx + uniforms.downY * wy + uniforms.downZ * wz;\n    let cz = uniforms.forwardX * wx + uniforms.forwardY * wy + uniforms.forwardZ * wz;\n\n#ifdef PROJECTION_EQUIRECT\n    #include \"projectionEquirect\"\n#else\n    #include \"projectionPinhole\"\n#endif\n\n    #include \"quatRotation\"\n    #include \"covariance3D\"\n\n#ifdef PROJECTION_EQUIRECT\n    #include \"jacobianEquirect\"\n#else\n    #include \"jacobianPinhole\"\n#endif\n\n    cov00 = cov00 + AA_DILATION_COV;\n    cov11 = cov11 + AA_DILATION_COV;\n\n#ifndef PROJECTION_EQUIRECT\n    // Defocus (DoF), pinhole only. Capture detPreDoF before dilating so the\n    // alpha rescale below conserves integrated energy — without it,\n    // defocused foreground splats over-occlude what is behind them.\n    let detPreDoF = cov00 * cov11 - cov01 * cov01;\n    let coc = uniforms.apertureScale * abs(1.0 - uniforms.focusDistance / cz);\n    let cocVar = coc * coc;\n    cov00 = cov00 + cocVar;\n    cov11 = cov11 + cocVar;\n#endif\n\n    let det = cov00 * cov11 - cov01 * cov01;\n    if (det <= 0.0) { writeInvalid(i); return; }\n\n    let invDet = 1.0 / det;\n    let covInvA = cov11 * invDet;\n    let covInvB = -cov01 * invDet;\n    let covInvC = cov00 * invDet;\n\n    let mid = 0.5 * (cov00 + cov11);\n    let disc = sqrt(max(DISCRIMINANT_FLOOR, mid * mid - det));\n    let lambdaMax = mid + disc;\n    let radiusRaw = SIGMA_CUTOFF * sqrt(lambdaMax);\n\n    // Outlier-splat fade: huge splats (close-by mega-splats or pathological\n    // training output) would otherwise project to a screen-spanning footprint\n    // and tint the whole frame. Linearly fade alpha from 1 to 0 as the\n    // un-clamped radius grows from fadeStart to fadeEnd, and discard\n    // beyond. The bbox we hand to the rasterizer is clamped at fadeEnd\n    // so the binner doesn't reserve tile coverage for a splat that\n    // contributes zero anyway. Softer than a hard clamp: prevents the\n    // visible pop as the camera approaches a clipped splat.\n    //\n    // Thresholds are fractions of image height so the SAME world-space\n    // splats fade at every render resolution — preserves cross-\n    // resolution consistency (e.g. 8K-downsampled-to-1080p matches\n    // 1080p direct).\n    let fadeStart = RADIUS_FADE_START_FRAC * f32(uniforms.imageHeight);\n    let fadeEnd = RADIUS_FADE_END_FRAC * f32(uniforms.imageHeight);\n    let radiusFade = clamp((fadeEnd - radiusRaw) / (fadeEnd - fadeStart), 0.0, 1.0);\n    if (radiusFade <= 0.0) { writeInvalid(i); return; }\n    let radius = ceil(min(radiusRaw, fadeEnd));\n\n    // Group AABB cull. The BVH frustum query may include splats whose\n    // 3D AABB grazes the frustum but whose 2D footprint misses the group.\n    let gx0 = f32(uniforms.groupPixelMinX);\n    let gx1 = f32(uniforms.groupPixelMaxX);\n    let gy0 = f32(uniforms.groupPixelMinY);\n    let gy1 = f32(uniforms.groupPixelMaxY);\n    if (screenX + radius < gx0 || screenX - radius >= gx1 ||\n        screenY + radius < gy0 || screenY - radius >= gy1) {\n        writeInvalid(i);\n        return;\n    }\n\n    // View-dependent color via SH evaluation.\n    let dpx = posX - uniforms.eyeX;\n    let dpy = posY - uniforms.eyeY;\n    let dpz = posZ - uniforms.eyeZ;\n    let dirLen = max(1e-30, sqrt(dpx * dpx + dpy * dpy + dpz * dpz));\n    let dirX = dpx / dirLen;\n    let dirY = dpy / dirLen;\n    let dirZ = dpz / dirLen;\n\n    var cR = SH_C0 * fdcR;\n    var cG = SH_C0 * fdcG;\n    var cB = SH_C0 * fdcB;\n\n#ifdef SH_BAND_1\n    #include \"shBand1\"\n#endif\n#ifdef SH_BAND_2\n    #include \"shBand2\"\n#endif\n#ifdef SH_BAND_3\n    #include \"shBand3\"\n#endif\n\n    let colR = max(0.0, cR + 0.5);\n    let colG = max(0.0, cG + 0.5);\n    let colB = max(0.0, cB + 0.5);\n\n#ifndef PROJECTION_EQUIRECT\n    // Energy-preserving alpha rescale for DoF. When apertureScale == 0,\n    // detPreDoF == det so dofAlphaScale == 1 (no-op).\n    let dofAlphaScale = sqrt(max(0.0, detPreDoF) / det);\n#else\n    let dofAlphaScale = 1.0;\n#endif\n\n    let alpha = (1.0 / (1.0 + exp(-opacity))) * radiusFade * dofAlphaScale;\n\n    projected[i * 3u + 0u] = vec4<f32>(screenX, screenY, radius, 0.0);\n    projected[i * 3u + 1u] = vec4<f32>(covInvA, covInvB, covInvC, alpha);\n    projected[i * 3u + 2u] = vec4<f32>(colR, colG, colB, 0.0);\n\n    // Per-splat tile-coverage count, clamped at maxCoveragePerSplat.\n    // Tile indices are GROUP-LOCAL (= image-tile-index minus the\n    // group's origin in tiles), so values cover [0, groupTilesX-1] ×\n    // [0, groupTilesY-1] for every group regardless of its position in\n    // the image. Splats outside the group's pixel rectangle were\n    // already culled by the AABB check above.\n    let tsz: f32 = f32(TILE_SIZE);\n    let gox = f32(uniforms.groupPixelOriginX);\n    let goy = f32(uniforms.groupPixelOriginY);\n#ifdef PROJECTION_EQUIRECT\n    #include \"tileAabbEquirect\"\n#else\n    #include \"tileAabbPinhole\"\n#endif\n}\n`;\n\nexport { projectWgsl };\n","/**\n * Binned rasterize shader. Each workgroup handles one tile and only walks\n * the splats that have been pre-binned into it (tile-bin pre-pass on CPU\n * or GPU). Replaces the \"walk all splats per pixel\" loop in a non-binned\n * rasterizer with \"walk this tile's slice\", which is the asymptotic\n * fix for performance at high splat counts.\n *\n * The slice is stored in two buffers:\n *   - `tileOffsets[T + 1]` — exclusive prefix sum: tile T's slice is\n *     `tileData[tileOffsets[T] .. tileOffsets[T + 1])`.\n *   - `tileData[]` — splat indices, grouped by tile, depth-sorted within\n *     each tile (the orchestrator's CPU pre-sort + stable per-splat\n *     binning produces this layout for free).\n *\n * Projection-mode variation: `PROJECTION_EQUIRECT` wraps the per-pixel\n * `dx = px - splat.x` into `[-W/2, W/2]` so a tile on the opposite side\n * of the ±π longitude seam evaluates against the splat's nearer copy.\n * Without the flag the raw delta is used.\n *\n * @returns WGSL source for the binned-rasterize compute shader.\n */\nconst rasterizeBinnedWgsl = () => /* wgsl */`\n#include \"uniformsStruct\"\n#include \"constants\"\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var<storage, read> projected: array<vec4<f32>>;\n@group(0) @binding(2) var<storage, read_write> runningState: array<vec4<f32>>;\n@group(0) @binding(3) var<storage, read> tileOffsets: array<u32>;\n@group(0) @binding(4) var<storage, read> sortedSplatIndices: array<u32>;\n\n@compute @workgroup_size(TILE_SIZE, TILE_SIZE, 1)\nfn main(\n    @builtin(workgroup_id) wgId: vec3<u32>,\n    @builtin(local_invocation_id) lid: vec3<u32>\n) {\n    if (wgId.x >= uniforms.groupTilesX || wgId.y >= uniforms.groupTilesY) { return; }\n\n    let tileIdx = wgId.y * uniforms.groupTilesX + wgId.x;\n    let sliceStart = tileOffsets[tileIdx];\n    let sliceEnd = tileOffsets[tileIdx + 1u];\n\n    let localPixelX = wgId.x * TILE_SIZE + lid.x;\n    let localPixelY = wgId.y * TILE_SIZE + lid.y;\n    let groupPixelW = uniforms.groupTilesX * TILE_SIZE;\n\n    let imagePixelX = uniforms.groupPixelOriginX + localPixelX;\n    let imagePixelY = uniforms.groupPixelOriginY + localPixelY;\n    if (imagePixelX >= uniforms.imageWidth || imagePixelY >= uniforms.imageHeight) { return; }\n\n    let pixelIdx = localPixelY * groupPixelW + localPixelX;\n    var state = runningState[pixelIdx];\n    var color = state.rgb;\n    var T = state.a;\n\n    if (T < MIN_TRANSMITTANCE) { return; }\n\n    let px = f32(imagePixelX) + 0.5;\n    let py = f32(imagePixelY) + 0.5;\n\n#ifdef PROJECTION_EQUIRECT\n    let imgWf2 = f32(uniforms.imageWidth);\n    let halfImgW = imgWf2 * 0.5;\n#endif\n    for (var i: u32 = sliceStart; i < sliceEnd; i = i + 1u) {\n        if (T < MIN_TRANSMITTANCE) { break; }\n        let splatIdx = sortedSplatIndices[i];\n        let v0 = projected[splatIdx * 3u + 0u];\n#ifdef PROJECTION_EQUIRECT\n        // Equirect: a splat near the ±π longitude seam is tile-binned on\n        // both sides of the image. Wrap dx into [-W/2, W/2] so a tile on\n        // the opposite side of the seam pulls the splat's footprint from\n        // the correct (nearer) copy.\n        var dx = px - v0.x;\n        if (dx > halfImgW) { dx = dx - imgWf2; }\n        else if (dx < -halfImgW) { dx = dx + imgWf2; }\n#else\n        let dx = px - v0.x;\n#endif\n        let dy = py - v0.y;\n        let r = v0.z;\n        if (r <= 0.0 || abs(dx) > r || abs(dy) > r) { continue; }\n        let v1 = projected[splatIdx * 3u + 1u];\n        let power = -0.5 * (v1.x * dx * dx + 2.0 * v1.y * dx * dy + v1.z * dy * dy);\n        if (power > 0.0) { continue; }\n        // Subtract GAUSSIAN_FLOOR so each splat's alpha reaches 0 exactly\n        // at the 3σ truncation radius instead of clipping at ~1.1% —\n        // eliminates faint ring artifacts at splat edges. Matches the\n        // PlayCanvas engine.\n        let alpha = min(OPACITY_CAP, v1.w * max(0.0, exp(power) - GAUSSIAN_FLOOR));\n        if (alpha < MIN_ALPHA) { continue; }\n        let weight = T * alpha;\n        let v2 = projected[splatIdx * 3u + 2u];\n        color = color + weight * v2.rgb;\n        T = T * (1.0 - alpha);\n    }\n\n    runningState[pixelIdx] = vec4<f32>(color, T);\n}\n`;\n\nexport { rasterizeBinnedWgsl };\n","/**\n * Tile-bin emit-pairs shader. For each projected splat, emits\n * `coverage[i]` (tile, splat) pairs into two parallel buffers,\n * starting at `emitOffset[i]`:\n *\n *   tileKeys [emitOffset[i] + j] = tileIdx\n *   splatValues[emitOffset[i] + j] = splatIdx (= i)\n *\n * The orchestrator sizes maxCoveragePerSplat to cover a sub-frame's\n * entire tile area, so a splat's `coverage[i]` always equals its full\n * bbox-in-group tile count — no truncation, no seams. The walk emits\n * row-major over the bbox-in-group. A subsequent key+value radix sort\n * groups pairs by tile; within each tile, the splatIdx-as-value sort\n * preserves the chunk's depth order (splatIdx is monotonic in depth\n * from the CPU pre-sort).\n *\n * Projection-mode variation: `PROJECTION_EQUIRECT` swaps in the\n * tile-walk-equirect chunk, which walks the un-clamped X range and\n * applies a modular wrap so a splat near the ±π longitude seam emits\n * tile keys on both sides of the image. Without the flag the\n * tile-walk-pinhole chunk walks the clamped bbox directly.\n *\n * @returns WGSL source for the emit-pairs compute shader.\n */\nconst tileBinEmitPairsWgsl = () => /* wgsl */`\n#include \"uniformsStruct\"\n#include \"constants\"\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var<storage, read> projected: array<vec4<f32>>;\n@group(0) @binding(2) var<storage, read> emitOffset: array<u32>;\n@group(0) @binding(3) var<storage, read> coverage: array<u32>;\n@group(0) @binding(4) var<storage, read_write> tileKeys: array<u32>;\n@group(0) @binding(5) var<storage, read_write> splatValues: array<u32>;\n\n@compute @workgroup_size(64)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n    let i = gid.x;\n    if (i >= uniforms.chunkSize) { return; }\n    let cap = coverage[i];\n    if (cap == 0u) { return; }\n    let v0 = projected[i * 3u + 0u];\n    let radius = v0.z;\n    if (radius <= 0.0) { return; }\n    let sX = v0.x;\n    let sY = v0.y;\n    let tsz: f32 = f32(TILE_SIZE);\n    // Group-local tile indices (see project shader for rationale).\n    let gox = f32(uniforms.groupPixelOriginX);\n    let goy = f32(uniforms.groupPixelOriginY);\n#ifdef PROJECTION_EQUIRECT\n    #include \"tileWalkEquirect\"\n#else\n    #include \"tileWalkPinhole\"\n#endif\n}\n`;\n\nexport { tileBinEmitPairsWgsl };\n","import {\n    UNIFORMTYPE_FLOAT,\n    UNIFORMTYPE_UINT,\n    UniformFormat\n} from 'playcanvas';\n\n/**\n * Shared WGSL declaration of the `struct Uniforms` block consumed by\n * every per-render compute shader (project, prefix-sum, emit-pairs,\n * init-tile-offsets, find-boundaries, rasterize-binned, finalize). The\n * matching JS layout produced by {@link uniformFormatEntries} sits\n * immediately below — when one changes the other must change in\n * lock-step. The pad fields keep f32 triples 16-byte aligned per\n * WGSL's uniform storage rules.\n *\n * Included into each consuming shader via the engine's WGSL preprocessor:\n * `#include \"uniformsStruct\"` at the top of the shader source replaces\n * the directive with the full struct declaration. See\n * `playcanvas/src/platform/graphics/shader.js` for the preprocessor\n * wiring (the `cincludes` Map on the `Shader` constructor's definition).\n */\nconst uniformsStruct = /* wgsl */`\nstruct Uniforms {\n    rightX: f32, rightY: f32, rightZ: f32, _p0: f32,\n    downX: f32, downY: f32, downZ: f32, _p1: f32,\n    forwardX: f32, forwardY: f32, forwardZ: f32, _p2: f32,\n    eyeX: f32, eyeY: f32, eyeZ: f32, _p3: f32,\n    focalX: f32, focalY: f32, near: f32, _p4: f32,\n    focusDistance: f32, apertureScale: f32, _p5: f32, _p6: f32,\n    imageWidth: u32, imageHeight: u32, splatStride: u32, chunkSize: u32,\n    groupPixelMinX: u32, groupPixelMinY: u32, groupPixelMaxX: u32, groupPixelMaxY: u32,\n    groupTilesX: u32, groupTilesY: u32, groupPixelOriginX: u32, groupPixelOriginY: u32,\n    bgR: f32, bgG: f32, bgB: f32, bgA: f32,\n}\n`;\n\n/**\n * Build the {@link UniformFormat} entries describing the WGSL `struct\n * Uniforms` block above, in declaration order. The PlayCanvas\n * UniformBuffer machinery expects a JS-side description that matches the\n * shader's uniform layout exactly; this function is the single source of\n * truth for that JS-side description and is consumed by every compute\n * shader that binds the shared Uniforms struct.\n *\n * @returns Array of UniformFormat entries in declaration order.\n */\nconst uniformFormatEntries = (): UniformFormat[] => [\n    new UniformFormat('rightX', UNIFORMTYPE_FLOAT),\n    new UniformFormat('rightY', UNIFORMTYPE_FLOAT),\n    new UniformFormat('rightZ', UNIFORMTYPE_FLOAT),\n    new UniformFormat('_p0', UNIFORMTYPE_FLOAT),\n    new UniformFormat('downX', UNIFORMTYPE_FLOAT),\n    new UniformFormat('downY', UNIFORMTYPE_FLOAT),\n    new UniformFormat('downZ', UNIFORMTYPE_FLOAT),\n    new UniformFormat('_p1', UNIFORMTYPE_FLOAT),\n    new UniformFormat('forwardX', UNIFORMTYPE_FLOAT),\n    new UniformFormat('forwardY', UNIFORMTYPE_FLOAT),\n    new UniformFormat('forwardZ', UNIFORMTYPE_FLOAT),\n    new UniformFormat('_p2', UNIFORMTYPE_FLOAT),\n    new UniformFormat('eyeX', UNIFORMTYPE_FLOAT),\n    new UniformFormat('eyeY', UNIFORMTYPE_FLOAT),\n    new UniformFormat('eyeZ', UNIFORMTYPE_FLOAT),\n    new UniformFormat('_p3', UNIFORMTYPE_FLOAT),\n    new UniformFormat('focalX', UNIFORMTYPE_FLOAT),\n    new UniformFormat('focalY', UNIFORMTYPE_FLOAT),\n    new UniformFormat('near', UNIFORMTYPE_FLOAT),\n    new UniformFormat('_p4', UNIFORMTYPE_FLOAT),\n    new UniformFormat('focusDistance', UNIFORMTYPE_FLOAT),\n    new UniformFormat('apertureScale', UNIFORMTYPE_FLOAT),\n    new UniformFormat('_p5', UNIFORMTYPE_FLOAT),\n    new UniformFormat('_p6', UNIFORMTYPE_FLOAT),\n    new UniformFormat('imageWidth', UNIFORMTYPE_UINT),\n    new UniformFormat('imageHeight', UNIFORMTYPE_UINT),\n    new UniformFormat('splatStride', UNIFORMTYPE_UINT),\n    new UniformFormat('chunkSize', UNIFORMTYPE_UINT),\n    new UniformFormat('groupPixelMinX', UNIFORMTYPE_UINT),\n    new UniformFormat('groupPixelMinY', UNIFORMTYPE_UINT),\n    new UniformFormat('groupPixelMaxX', UNIFORMTYPE_UINT),\n    new UniformFormat('groupPixelMaxY', UNIFORMTYPE_UINT),\n    new UniformFormat('groupTilesX', UNIFORMTYPE_UINT),\n    new UniformFormat('groupTilesY', UNIFORMTYPE_UINT),\n    new UniformFormat('groupPixelOriginX', UNIFORMTYPE_UINT),\n    new UniformFormat('groupPixelOriginY', UNIFORMTYPE_UINT),\n    new UniformFormat('bgR', UNIFORMTYPE_FLOAT),\n    new UniformFormat('bgG', UNIFORMTYPE_FLOAT),\n    new UniformFormat('bgB', UNIFORMTYPE_FLOAT),\n    new UniformFormat('bgA', UNIFORMTYPE_FLOAT)\n];\n\nexport { uniformsStruct, uniformFormatEntries };\n","import {\n    BUFFERUSAGE_COPY_DST,\n    BUFFERUSAGE_COPY_SRC,\n    SHADERLANGUAGE_WGSL,\n    SHADERSTAGE_COMPUTE,\n    UNIFORMTYPE_UINT,\n    BindGroupFormat,\n    BindStorageBufferFormat,\n    BindUniformBufferFormat,\n    Compute,\n    ComputeRadixSort,\n    GraphicsDevice,\n    Shader,\n    StorageBuffer,\n    UniformBufferFormat,\n    UniformFormat\n} from 'playcanvas';\n\nimport { constantsChunk } from './shaders/chunks/constants';\nimport { covariance3D } from './shaders/chunks/covariance-3d';\nimport { jacobianEquirect } from './shaders/chunks/jacobian-equirect';\nimport { jacobianPinhole } from './shaders/chunks/jacobian-pinhole';\nimport { projectionEquirect } from './shaders/chunks/projection-equirect';\nimport { projectionPinhole } from './shaders/chunks/projection-pinhole';\nimport { quatRotation } from './shaders/chunks/quat-rotation';\nimport { shBand1 } from './shaders/chunks/sh-band-1';\nimport { shBand2 } from './shaders/chunks/sh-band-2';\nimport { shBand3 } from './shaders/chunks/sh-band-3';\nimport { tileAabbEquirect } from './shaders/chunks/tile-aabb-equirect';\nimport { tileAabbPinhole } from './shaders/chunks/tile-aabb-pinhole';\nimport { tileWalkEquirect } from './shaders/chunks/tile-walk-equirect';\nimport { tileWalkPinhole } from './shaders/chunks/tile-walk-pinhole';\nimport { finalizeWgsl } from './shaders/finalize';\nimport { findBoundariesWgsl } from './shaders/find-boundaries';\nimport { initTileOffsetsWgsl } from './shaders/init-tile-offsets';\nimport { prefixSumWgsl } from './shaders/prefix-sum';\nimport { prepareIndirectWgsl } from './shaders/prepare-indirect';\nimport { projectWgsl } from './shaders/project';\nimport { rasterizeBinnedWgsl } from './shaders/rasterize-binned';\nimport { tileBinEmitPairsWgsl } from './shaders/tile-bin-emit-pairs';\nimport { uniformsStruct, uniformFormatEntries } from './shaders/uniforms';\nimport { type Projection } from '../render/camera';\nimport { TILE_SIZE } from '../render/config';\n\n/** 12 floats per projected splat: vec4 × 3. */\nconst PROJECTION_STRIDE_F32 = 12;\n\n/** 4 floats per group pixel: (R, G, B, T). */\nconst RUNNING_STATE_STRIDE_F32 = 4;\n\n/** RGBA8 output is one u32 per group pixel. */\nconst OUTPUT_STRIDE_U32 = 1;\n\n/**\n * Configuration for a `GpuSplatRasterizer`. Fixed across the lifetime of\n * a render — `numSHBands` and the group tile dimensions determine GPU\n * buffer sizes and shader uniform layouts.\n *\n * Sizes are expressed as a \"group\" tile rectangle (`groupTilesX ×\n * groupTilesY`). For a single-pass render the group covers the whole\n * image, so the buffers are exactly image-sized. The group abstraction\n * is retained as a hook for future subframe splitting (each subframe is\n * an independent group sharing the global depth sort) — the project\n * shader's group-AABB cull and group-pixel-origin uniforms still\n * exercise this code path.\n */\ninterface SplatRasterizerOptions {\n    /** Number of SH bands above DC (0–3). Determines input stride. */\n    numSHBands: 0 | 1 | 2 | 3;\n    /**\n     * Camera projection mode. Specializes the project, emit-pairs and\n     * rasterize-binned shaders. `pinhole` (default) uses the classical\n     * perspective + EWA Jacobian path; `equirect` uses spherical\n     * (atan2/asin) screen mapping, a non-linear Jacobian, radial view\n     * depth, and tile-bin / rasterize paths that wrap the X axis at the\n     * ±π longitude seam.\n     */\n    projection: Projection;\n    /** Tiles per group along X (≤ imageTilesX). Sizes runningState/output. */\n    groupTilesX: number;\n    /** Tiles per group along Y (≤ imageTilesY). Sizes runningState/output. */\n    groupTilesY: number;\n    /** Max gaussians per chunk; sizes the input + projection + pair buffers. */\n    chunkCap: number;\n    /**\n     * Hard upper bound on per-splat tile coverage. The project shader\n     * clamps `coverage[i] = min(rawBboxArea, maxCoveragePerSplat)`, so\n     * the pair buffer is bounded by `chunkCap × maxCoveragePerSplat`\n     * regardless of scene/screen size. If the cap ever bites, the\n     * emit-pairs shader walks the bbox row-major and stops once it\n     * has written `coverage[i]` pairs — i.e. it truncates the bbox at\n     * its bottom-right corner.\n     *\n     * The orchestrator sets this to the group's full tile area so the\n     * clamp is geometrically unreachable (any in-group bbox ≤ group\n     * area ≤ cap), making truncation a non-issue in practice. The cap\n     * is retained as a defensive ceiling on the pair buffer.\n     */\n    maxCoveragePerSplat: number;\n    /** Output image width in pixels (constant per render). */\n    imageWidth: number;\n    /** Output image height in pixels (constant per render). */\n    imageHeight: number;\n    /** Near plane distance in world units. */\n    near: number;\n    /** Camera basis: rows are (right, down, forward) of the world→camera rotation. */\n    rightX: number; rightY: number; rightZ: number;\n    downX: number; downY: number; downZ: number;\n    forwardX: number; forwardY: number; forwardZ: number;\n    /** Camera eye position in world space. */\n    eyeX: number; eyeY: number; eyeZ: number;\n    /** Focal lengths in pixel units. */\n    focalX: number; focalY: number;\n    /**\n     * Camera-space Z of the focus plane, world units. Pinhole-only;\n     * unused when `projection === 'equirect'`.\n     */\n    focusDistance: number;\n    /**\n     * DoF strength as a pixel-space scalar: the CoC radius in pixels when\n     * `|1 − focusDistance/cz| = 1`. `0` disables defocus. The writer\n     * derives this from `--f-stop` + `--sensor-size` using the thin-lens\n     * CoC formula. Pinhole-only.\n     */\n    apertureScale: number;\n    /** RGBA background, each channel in [0, 1]. */\n    bgR: number; bgG: number; bgB: number; bgA: number;\n}\n\nconst numSHCoeffsPerChannel = (bands: number): number => {\n    return bands === 0 ? 0 : bands === 1 ? 3 : bands === 2 ? 8 : 15;\n};\n\n\ninterface PipelineBuffers {\n    inputBuffer: StorageBuffer;\n    projBuffer: StorageBuffer;\n    runningStateBuffer: StorageBuffer;\n    outputBuffer: StorageBuffer;\n    /** Per-tile offset table for binned rasterize: `(numTiles + 1) × u32`. */\n    tileOffsetsBuffer: StorageBuffer;\n    /**\n     * Per-splat tile-coverage count, written by the project shader.\n     * Consumed by the GPU prefix-sum kernel; never read by the CPU.\n     */\n    coverageBuffer: StorageBuffer;\n    /**\n     * GPU-computed exclusive prefix-sum of `coverageBuffer`.\n     * `emitOffset[i]` is the first slot in `tileKeysBuffer`/`splatValuesBuffer`\n     * that splat i writes to in the emit-pairs pass.\n     */\n    emitOffsetBuffer: StorageBuffer;\n    /**\n     * Single u32 holding the total pair count produced by the prefix-sum.\n     * Read by `prepareIndirect`, `initTileOffsets`, `findBoundaries`,\n     * and the radix sort's indirect dispatch. Never touched by the CPU.\n     */\n    totalPairsBuffer: StorageBuffer;\n    /**\n     * `tileIdx` (sort key) for each (tile, splat) pair. Sorted in place\n     * by `ComputeRadixSort.sortIndirect` — afterwards `sortedKeys` on the\n     * radix sort instance holds the sorted tile keys.\n     */\n    tileKeysBuffer: StorageBuffer;\n    /**\n     * `splatIdx` (sort value) for each (tile, splat) pair, passed to the\n     * radix sort as `initialValues`. The sort writes the reordered splat\n     * indices to its internal `sortedIndices` buffer.\n     */\n    splatValuesBuffer: StorageBuffer;\n    projectCompute: Compute;\n    prefixSumCompute: Compute;\n    emitPairsCompute: Compute;\n    prepareIndirectCompute: Compute;\n    initTileOffsetsCompute: Compute;\n    findBoundariesCompute: Compute;\n    rasterizeBinnedCompute: Compute;\n    finalizeCompute: Compute;\n}\n\n\n/**\n * GPU-accelerated splat rasterizer.\n *\n * Owns eight compute shaders — project, prefix-sum, emit-pairs,\n * prepare-indirect, init-tile-offsets, find-boundaries, rasterize-binned,\n * finalize-pack — a shared `ComputeRadixSort` (used in indirect mode,\n * key + value), and GPU buffers. The per-chunk pipeline is fully\n * GPU-resident: the caller never reads back coverage, sorted keys, or\n * tile offsets.\n *\n * Per-render flow:\n *   1. `beginGroup(...)` — clears the running state and sets uniforms\n *      for this group (covers the whole image for a single-pass render).\n *   2. For each chunk of depth-sorted splats: `dispatchChunk(data,\n *      chunkSize)` runs the whole tile-bin + rasterize pipeline in one\n *      submission — project + coverage → prefix-sum (writes emitOffsets\n *      + totalPairs) → emit-pairs → prepare-indirect → radix sortIndirect\n *      → init-tile-offsets → find-boundaries → rasterize-binned. No\n *      readbacks; one `submit()` per chunk to capture each compute's\n *      uniform state before the next chunk overwrites it.\n *   3. `finishGroup()` — dispatches finalize-pack and starts an async\n *      readback. Returns a `Promise<Uint8Array>` resolved when the GPU has\n *      finished writing this group's RGBA bytes.\n */\nclass GpuSplatRasterizer {\n    private device: GraphicsDevice;\n    private options: SplatRasterizerOptions;\n    private projectShader: Shader;\n    private prefixSumShader: Shader;\n    private emitPairsShader: Shader;\n    private prepareIndirectShader: Shader;\n    private initTileOffsetsShader: Shader;\n    private findBoundariesShader: Shader;\n    private rasterizeBinnedShader: Shader;\n    private finalizeShader: Shader;\n    private projectBgFormat: BindGroupFormat;\n    private prefixSumBgFormat: BindGroupFormat;\n    private emitPairsBgFormat: BindGroupFormat;\n    private prepareIndirectBgFormat: BindGroupFormat;\n    private initTileOffsetsBgFormat: BindGroupFormat;\n    private findBoundariesBgFormat: BindGroupFormat;\n    private rasterizeBinnedBgFormat: BindGroupFormat;\n    private finalizeBgFormat: BindGroupFormat;\n    private buffers: PipelineBuffers;\n    /**\n     * Single shared `ComputeRadixSort` for the GPU tile-bin pipeline.\n     * Used in key+value mode: tile-index keys + splat-index values.\n     */\n    private radixSort: ComputeRadixSort;\n    /** sortIndirect numBits, derived from numTiles (multiple of 4). */\n    private sortKeyBits: number;\n    private clearStatePattern: Float32Array;\n    /** Active group's tile dimensions, set by `beginGroup`. */\n    private activeTilesX: number = 0;\n    private activeTilesY: number = 0;\n\n    /** Floats per gaussian in the input buffer (depends on SH band count). */\n    readonly inputStride: number;\n    /** Group tile dimensions (X). */\n    readonly groupTilesX: number;\n    /** Group tile dimensions (Y). */\n    readonly groupTilesY: number;\n    /** Max gaussians per chunk. */\n    readonly chunkCap: number;\n    /** Pixels per group axis (X). */\n    readonly groupPixelW: number;\n    /** Pixels per group axis (Y). */\n    readonly groupPixelH: number;\n\n    constructor(device: GraphicsDevice, options: SplatRasterizerOptions) {\n        this.device = device;\n        this.options = options;\n        this.groupTilesX = options.groupTilesX;\n        this.groupTilesY = options.groupTilesY;\n        this.chunkCap = options.chunkCap;\n        this.groupPixelW = options.groupTilesX * TILE_SIZE;\n        this.groupPixelH = options.groupTilesY * TILE_SIZE;\n\n        const numTiles = options.groupTilesX * options.groupTilesY;\n        // Round up to multiple of 4 (radix sort uses 4-bit passes). Min 4\n        // because ComputeRadixSort requires numBits ≥ 4. Max 32 (u32 key).\n        const tileBits = Math.max(4, Math.min(32, Math.ceil(Math.log2(Math.max(2, numTiles)) / 4) * 4));\n        this.sortKeyBits = tileBits;\n\n        const coeffs = numSHCoeffsPerChannel(options.numSHBands);\n        this.inputStride = 14 + 3 * coeffs;\n\n        this.projectBgFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('splats', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('projected', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('coverage', SHADERSTAGE_COMPUTE)\n        ]);\n        this.prefixSumBgFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('coverage', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('emitOffset', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('totalPairs', SHADERSTAGE_COMPUTE)\n        ]);\n        this.emitPairsBgFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('projected', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('emitOffset', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('coverage', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('tileKeys', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('splatValues', SHADERSTAGE_COMPUTE)\n        ]);\n        this.prepareIndirectBgFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('totalPairs', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('indirectBuffer', SHADERSTAGE_COMPUTE)\n        ]);\n        this.initTileOffsetsBgFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('totalPairs', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('tileOffsets', SHADERSTAGE_COMPUTE)\n        ]);\n        this.findBoundariesBgFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('totalPairs', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('sortedTileKeys', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('tileOffsets', SHADERSTAGE_COMPUTE)\n        ]);\n        this.rasterizeBinnedBgFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('projected', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('runningState', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('tileOffsets', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('sortedSplatIndices', SHADERSTAGE_COMPUTE, true)\n        ]);\n        this.finalizeBgFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('runningState', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('output', SHADERSTAGE_COMPUTE)\n        ]);\n\n        // WGSL chunks made available to every shader. The engine's\n        // compute-shader path runs the source through\n        // `Preprocessor.run(cshader, cincludes, ...)`, so any\n        // `#include \"name\"` directive resolves to the corresponding\n        // value in this Map. Lookup is by name only — chunk-order\n        // does not matter.\n        //\n        // Per-render-cap chunks (tileAabb / tileWalk) are constructed\n        // here with the resolved `maxCoveragePerSplat` so the chunk\n        // bodies stay JS-template-free.\n        const projection = options.projection;\n        const sharedCincludes = new Map<string, string>([\n            ['uniformsStruct', uniformsStruct],\n            ['constants', constantsChunk],\n            ['projectionPinhole', projectionPinhole],\n            ['projectionEquirect', projectionEquirect],\n            ['jacobianPinhole', jacobianPinhole],\n            ['jacobianEquirect', jacobianEquirect],\n            ['tileAabbPinhole', tileAabbPinhole(options.maxCoveragePerSplat)],\n            ['tileAabbEquirect', tileAabbEquirect(options.maxCoveragePerSplat)],\n            ['tileWalkPinhole', tileWalkPinhole],\n            ['tileWalkEquirect', tileWalkEquirect],\n            ['shBand1', shBand1],\n            ['shBand2', shBand2],\n            ['shBand3', shBand3],\n            ['quatRotation', quatRotation],\n            ['covariance3D', covariance3D]\n        ]);\n\n        // Per-render variant flags consumed by `#ifdef` directives in\n        // the WGSL sources. Presence-only — the empty value is fine\n        // because the preprocessor only checks `defines.has(name)` for\n        // `#ifdef`. See `engine/src/core/preprocessor.js` for how\n        // `cdefines` is consumed.\n        const sharedCdefines = new Map<string, string>();\n        if (projection === 'equirect') {\n            sharedCdefines.set('PROJECTION_EQUIRECT', '');\n        }\n        if (options.numSHBands >= 1) sharedCdefines.set('SH_BAND_1', '');\n        if (options.numSHBands >= 2) sharedCdefines.set('SH_BAND_2', '');\n        if (options.numSHBands >= 3) sharedCdefines.set('SH_BAND_3', '');\n\n        const mkShader = (\n            name: string,\n            source: string,\n            bgFormat: BindGroupFormat,\n            uniformEntries: UniformFormat[] = uniformFormatEntries(),\n            cincludes: Map<string, string> = sharedCincludes,\n            cdefines: Map<string, string> = sharedCdefines\n        ) => new Shader(device, {\n            name,\n            shaderLanguage: SHADERLANGUAGE_WGSL,\n            cshader: source,\n            // @ts-ignore - computeUniformBufferFormats / computeBindGroupFormat / cincludes / cdefines are not in public Shader types.\n            computeUniformBufferFormats: {\n                uniforms: new UniformBufferFormat(device, uniformEntries)\n            },\n            // @ts-ignore\n            computeBindGroupFormat: bgFormat,\n            // @ts-ignore\n            cincludes,\n            // @ts-ignore\n            cdefines\n        });\n\n        // The prefix-sum kernel processes the chunk in 256-thread blocks\n        // of `scanPerThread` elements; the constant is compile-time\n        // embedded so this product must cover the largest chunk we ever\n        // dispatch (= chunkCap).\n        const scanPerThread = Math.ceil(options.chunkCap / 256);\n\n        // Uniform format for the small prepareIndirect kernel — just the\n        // two slot-base indices into the device's indirect dispatch\n        // buffer. Different layout from the shared `Uniforms` block.\n        const prepareIndirectUniforms: UniformFormat[] = [\n            new UniformFormat('sortSlotBase', UNIFORMTYPE_UINT),\n            new UniformFormat('boundariesSlotBase', UNIFORMTYPE_UINT)\n        ];\n\n        this.projectShader = mkShader('splat-project', projectWgsl(coeffs), this.projectBgFormat);\n        this.prefixSumShader = mkShader('splat-tilebin-prefix-sum', prefixSumWgsl(scanPerThread), this.prefixSumBgFormat);\n        this.emitPairsShader = mkShader('splat-tilebin-emit-pairs', tileBinEmitPairsWgsl(), this.emitPairsBgFormat);\n        this.prepareIndirectShader = mkShader('splat-tilebin-prepare-indirect', prepareIndirectWgsl(), this.prepareIndirectBgFormat, prepareIndirectUniforms);\n        this.initTileOffsetsShader = mkShader('splat-tilebin-init-tile-offsets', initTileOffsetsWgsl(), this.initTileOffsetsBgFormat);\n        this.findBoundariesShader = mkShader('splat-tilebin-find-boundaries', findBoundariesWgsl(), this.findBoundariesBgFormat);\n        this.rasterizeBinnedShader = mkShader('splat-rasterize-binned', rasterizeBinnedWgsl(), this.rasterizeBinnedBgFormat);\n        this.finalizeShader = mkShader('splat-finalize-pack', finalizeWgsl(), this.finalizeBgFormat);\n\n        // Buffer sizing. runningState/output cover exactly the group's\n        // tile rectangle (groupTilesX × groupTilesY × TILE_SIZE²), not the\n        // bounding-square of the larger dimension as before.\n        const groupPixels = this.groupPixelW * this.groupPixelH;\n        const inputBytes = options.chunkCap * this.inputStride * 4;\n        const projBytes = options.chunkCap * PROJECTION_STRIDE_F32 * 4;\n        const stateBytes = groupPixels * RUNNING_STATE_STRIDE_F32 * 4;\n        const outputBytes = groupPixels * OUTPUT_STRIDE_U32 * 4;\n        // Tile-bin buffer sizes. tileOffsets has one slot per tile plus a\n        // trailing sentinel so a tile's slice end is just `tileOffsets[T + 1]`.\n        const tileOffsetsBytes = (numTiles + 1) * 4;\n\n        const coverageBytes = options.chunkCap * 4;\n        const emitOffsetBytes = options.chunkCap * 4;\n        // Pair buffers. Two parallel u32 buffers (tileKeys + splatValues)\n        // sized to chunkCap × maxCoveragePerSplat. The project shader\n        // clamps each splat's coverage at maxCoveragePerSplat so the\n        // sum never exceeds this cap regardless of scene density.\n        const pairsBytes = options.chunkCap * options.maxCoveragePerSplat * 4;\n        const totalPairsBytes = 4;\n\n        const inputBuffer = new StorageBuffer(device, inputBytes, BUFFERUSAGE_COPY_DST);\n        const projBuffer = new StorageBuffer(device, projBytes, 0);\n        const runningStateBuffer = new StorageBuffer(device, stateBytes, BUFFERUSAGE_COPY_DST);\n        const outputBuffer = new StorageBuffer(device, outputBytes, BUFFERUSAGE_COPY_SRC);\n        const tileOffsetsBuffer = new StorageBuffer(device, tileOffsetsBytes, 0);\n        const coverageBuffer = new StorageBuffer(device, coverageBytes, 0);\n        const emitOffsetBuffer = new StorageBuffer(device, emitOffsetBytes, 0);\n        const tileKeysBuffer = new StorageBuffer(device, pairsBytes, 0);\n        const splatValuesBuffer = new StorageBuffer(device, pairsBytes, 0);\n        const totalPairsBuffer = new StorageBuffer(device, totalPairsBytes, 0);\n\n        const projectCompute = new Compute(device, this.projectShader, 'splat-project');\n        projectCompute.setParameter('splats', inputBuffer);\n        projectCompute.setParameter('projected', projBuffer);\n        projectCompute.setParameter('coverage', coverageBuffer);\n\n        const prefixSumCompute = new Compute(device, this.prefixSumShader, 'splat-tilebin-prefix-sum');\n        prefixSumCompute.setParameter('coverage', coverageBuffer);\n        prefixSumCompute.setParameter('emitOffset', emitOffsetBuffer);\n        prefixSumCompute.setParameter('totalPairs', totalPairsBuffer);\n\n        const emitPairsCompute = new Compute(device, this.emitPairsShader, 'splat-tilebin-emit-pairs');\n        emitPairsCompute.setParameter('projected', projBuffer);\n        emitPairsCompute.setParameter('emitOffset', emitOffsetBuffer);\n        emitPairsCompute.setParameter('coverage', coverageBuffer);\n        emitPairsCompute.setParameter('tileKeys', tileKeysBuffer);\n        emitPairsCompute.setParameter('splatValues', splatValuesBuffer);\n\n        const prepareIndirectCompute = new Compute(device, this.prepareIndirectShader, 'splat-tilebin-prepare-indirect');\n        prepareIndirectCompute.setParameter('totalPairs', totalPairsBuffer);\n        // `indirectBuffer` is bound per-chunk after the device has\n        // allocated its indirect-dispatch buffer.\n\n        const initTileOffsetsCompute = new Compute(device, this.initTileOffsetsShader, 'splat-tilebin-init-tile-offsets');\n        initTileOffsetsCompute.setParameter('totalPairs', totalPairsBuffer);\n        initTileOffsetsCompute.setParameter('tileOffsets', tileOffsetsBuffer);\n\n        const findBoundariesCompute = new Compute(device, this.findBoundariesShader, 'splat-tilebin-find-boundaries');\n        findBoundariesCompute.setParameter('totalPairs', totalPairsBuffer);\n        findBoundariesCompute.setParameter('tileOffsets', tileOffsetsBuffer);\n        // `sortedTileKeys` is bound per-chunk after the radix sort runs.\n\n        const rasterizeBinnedCompute = new Compute(device, this.rasterizeBinnedShader, 'splat-rasterize-binned');\n        rasterizeBinnedCompute.setParameter('projected', projBuffer);\n        rasterizeBinnedCompute.setParameter('runningState', runningStateBuffer);\n        rasterizeBinnedCompute.setParameter('tileOffsets', tileOffsetsBuffer);\n        // `sortedSplatIndices` is bound per-chunk inside `dispatchChunk`,\n        // pointing at the radix sort's `sortedIndices` output buffer.\n\n        const finalizeCompute = new Compute(device, this.finalizeShader, 'splat-finalize');\n        finalizeCompute.setParameter('runningState', runningStateBuffer);\n        finalizeCompute.setParameter('output', outputBuffer);\n\n        this.buffers = {\n            inputBuffer,\n            projBuffer,\n            runningStateBuffer,\n            outputBuffer,\n            tileOffsetsBuffer,\n            coverageBuffer,\n            emitOffsetBuffer,\n            totalPairsBuffer,\n            tileKeysBuffer,\n            splatValuesBuffer,\n            projectCompute,\n            prefixSumCompute,\n            emitPairsCompute,\n            prepareIndirectCompute,\n            initTileOffsetsCompute,\n            findBoundariesCompute,\n            rasterizeBinnedCompute,\n            finalizeCompute\n        };\n\n        // CPU-side cleared running state: T = 1 per pixel, color = 0.\n        // Reused across groups; uploaded to runningStateBuffer at beginGroup.\n        this.clearStatePattern = new Float32Array(groupPixels * RUNNING_STATE_STRIDE_F32);\n        for (let i = 0; i < groupPixels; i++) {\n            this.clearStatePattern[i * 4 + 3] = 1; // T = 1\n        }\n\n        this.radixSort = new ComputeRadixSort(device);\n\n        // The per-chunk pipeline reserves 2 slots in the device's\n        // indirect-dispatch buffer (one for the radix sort, one for\n        // find-boundaries). PC resets the slot counter at frame-end\n        // only; for an offline render, the counter monotonically grows\n        // across (chunk × sub-frame) iterations. At 8K with sub-frame\n        // split and chunkCap squeezed down by binding limits we can\n        // hit ~70 k slots. Pre-allocate generously — each slot is only\n        // 12 bytes, so 256 k slots = 3 MB.\n        const wantedSlots = 256 * 1024;\n        // @ts-ignore - maxIndirectDispatchCount is a public property on\n        // the WebGPU device but not in the public GraphicsDevice type.\n        const cur = (device as { maxIndirectDispatchCount?: number }).maxIndirectDispatchCount ?? 0;\n        if (cur < wantedSlots) {\n            // @ts-ignore\n            (device as { maxIndirectDispatchCount: number }).maxIndirectDispatchCount = wantedSlots;\n        }\n    }\n\n    /**\n     * Apply the global (camera + image + background) uniforms to every\n     * pipeline compute instance, plus the per-group origin/extent fields.\n     *\n     * The group abstraction is retained as a hook for future subframe\n     * rendering — when a render is split into multiple groups, each call\n     * sets the current group's pixel rectangle so the project shader's\n     * AABB cull skips splats outside the group.\n     *\n     * @param groupX - Group index along X.\n     * @param groupY - Group index along Y.\n     * @param groupTilesX - Number of tiles in this group along X.\n     * @param groupTilesY - Number of tiles in this group along Y.\n     */\n    private setUniforms(\n        groupX: number,\n        groupY: number,\n        groupTilesX: number,\n        groupTilesY: number\n    ): void {\n        const o = this.options;\n        const originX = groupX * this.groupPixelW;\n        const originY = groupY * this.groupPixelH;\n        const maxX = originX + groupTilesX * TILE_SIZE;\n        const maxY = originY + groupTilesY * TILE_SIZE;\n\n        const b = this.buffers;\n        for (const c of [\n            b.projectCompute,\n            b.prefixSumCompute,\n            b.emitPairsCompute,\n            b.initTileOffsetsCompute,\n            b.findBoundariesCompute,\n            b.rasterizeBinnedCompute,\n            b.finalizeCompute\n        ]) {\n            c.setParameter('rightX', o.rightX); c.setParameter('rightY', o.rightY); c.setParameter('rightZ', o.rightZ);\n            c.setParameter('_p0', 0);\n            c.setParameter('downX', o.downX); c.setParameter('downY', o.downY); c.setParameter('downZ', o.downZ);\n            c.setParameter('_p1', 0);\n            c.setParameter('forwardX', o.forwardX); c.setParameter('forwardY', o.forwardY); c.setParameter('forwardZ', o.forwardZ);\n            c.setParameter('_p2', 0);\n            c.setParameter('eyeX', o.eyeX); c.setParameter('eyeY', o.eyeY); c.setParameter('eyeZ', o.eyeZ);\n            c.setParameter('_p3', 0);\n            c.setParameter('focalX', o.focalX); c.setParameter('focalY', o.focalY);\n            c.setParameter('near', o.near); c.setParameter('_p4', 0);\n            c.setParameter('focusDistance', o.focusDistance);\n            c.setParameter('apertureScale', o.apertureScale);\n            c.setParameter('_p5', 0); c.setParameter('_p6', 0);\n            c.setParameter('imageWidth', o.imageWidth); c.setParameter('imageHeight', o.imageHeight);\n            c.setParameter('splatStride', this.inputStride);\n            // chunkSize set per-dispatch\n            c.setParameter('groupPixelMinX', originX);\n            c.setParameter('groupPixelMinY', originY);\n            c.setParameter('groupPixelMaxX', maxX);\n            c.setParameter('groupPixelMaxY', maxY);\n            c.setParameter('groupTilesX', groupTilesX);\n            c.setParameter('groupTilesY', groupTilesY);\n            c.setParameter('groupPixelOriginX', originX);\n            c.setParameter('groupPixelOriginY', originY);\n            c.setParameter('bgR', o.bgR); c.setParameter('bgG', o.bgG);\n            c.setParameter('bgB', o.bgB); c.setParameter('bgA', o.bgA);\n        }\n    }\n\n    /**\n     * Begin processing a group. Clears running state and sets uniforms.\n     *\n     * @param groupX - Group index along X.\n     * @param groupY - Group index along Y.\n     * @param groupTilesX - Number of tiles in this group along X.\n     * @param groupTilesY - Number of tiles in this group along Y.\n     */\n    beginGroup(\n        groupX: number,\n        groupY: number,\n        groupTilesX: number,\n        groupTilesY: number\n    ): void {\n        this.setUniforms(groupX, groupY, groupTilesX, groupTilesY);\n        this.activeTilesX = groupTilesX;\n        this.activeTilesY = groupTilesY;\n        const groupPixels = groupTilesX * groupTilesY * TILE_SIZE * TILE_SIZE;\n        this.buffers.runningStateBuffer.write(\n            0, this.clearStatePattern, 0, groupPixels * RUNNING_STATE_STRIDE_F32\n        );\n    }\n\n    /**\n     * Commit pending GPU work. Called at chunk boundaries so each chunk's\n     * uniform-buffer values are captured before the next chunk overwrites\n     * them — a `Compute` instance's persistent uniform buffer is updated\n     * by `setParameter`, and the dispatch only captures the value on\n     * submit. Within a chunk, every dispatch uses a distinct `Compute`\n     * instance, so no internal submits are needed.\n     */\n    submit(): void {\n        // @ts-ignore - submit() is exposed by WebgpuGraphicsDevice but not on the public GraphicsDevice type.\n        const submit = (this.device as { submit?: () => void }).submit;\n        if (!submit) {\n            throw new Error('GpuSplatRasterizer requires a GraphicsDevice with a submit() method (WebGPU backend).');\n        }\n        submit.call(this.device);\n    }\n\n    /**\n     * Reserve a fresh sort + find-boundaries slot pair in the device's\n     * indirect-dispatch buffer for this chunk. The returned indices are\n     * consumed by `dispatchTileBinChunk` (internally) and exposed for\n     * cross-cutting use (e.g. the radix sort needs the sort slot).\n     *\n     * @returns Two fresh slot indices in the device's indirect dispatch\n     * buffer: one for the radix sort's indirect dispatch, one for the\n     * find-boundaries indirect dispatch.\n     */\n    private acquireIndirectSlots(): { sortSlot: number; boundariesSlot: number } {\n        // @ts-ignore - getIndirectDispatchSlot exists on WebgpuGraphicsDevice.\n        const get = (this.device as { getIndirectDispatchSlot?: (count?: number) => number }).getIndirectDispatchSlot;\n        if (!get) {\n            throw new Error('GpuSplatRasterizer requires a GraphicsDevice with getIndirectDispatchSlot() (WebGPU backend).');\n        }\n        const sortSlot = get.call(this.device, 1);\n        const boundariesSlot = get.call(this.device, 1);\n        return { sortSlot, boundariesSlot };\n    }\n\n    /**\n     * Dispatch the entire per-chunk tile-bin + rasterize pipeline on the\n     * GPU with zero CPU readbacks:\n     *\n     *   pack-and-upload → project + coverage → prefix-sum (writes\n     *   emitOffsets + totalPairs) → emit-pairs (writes tileKeys +\n     *   splatValues) → prepare-indirect (writes workgroup counts into\n     *   the device's indirect-dispatch buffer for the sort and\n     *   find-boundaries) → radix sortIndirect (key+value: tileKeys\n     *   sorted, splatValues reordered) → init tile-offsets to sentinel\n     *   → find-boundaries (atomicMin) → rasterize.\n     *\n     * All eight dispatches use distinct `Compute` instances, so their\n     * persistent uniform buffers don't alias each other within a chunk;\n     * a single `submit()` after the rasterize captures everything before\n     * the next chunk starts overwriting `setParameter` values.\n     *\n     * @param chunkData - Float32Array containing `chunkSize × inputStride` floats.\n     * @param chunkSize - Number of gaussians in this chunk (≤ chunkCap).\n     */\n    dispatchChunk(chunkData: Float32Array, chunkSize: number): void {\n        if (chunkSize === 0) return;\n        if (chunkSize > this.chunkCap) {\n            throw new Error(`chunkSize ${chunkSize} exceeds chunkCap ${this.chunkCap}`);\n        }\n        const b = this.buffers;\n\n        // --- 1. Upload chunk + project (writes projected, coverage). ---\n        b.inputBuffer.write(0, chunkData, 0, chunkSize * this.inputStride);\n        b.projectCompute.setParameter('chunkSize', chunkSize);\n        b.projectCompute.setupDispatch(Math.ceil(chunkSize / 64), 1, 1);\n        this.device.computeDispatch([b.projectCompute], 'splat-project');\n\n        // --- 2. GPU prefix-sum (coverage → emitOffsets + totalPairs). ---\n        b.prefixSumCompute.setParameter('chunkSize', chunkSize);\n        b.prefixSumCompute.setupDispatch(1, 1, 1);\n        this.device.computeDispatch([b.prefixSumCompute], 'splat-tilebin-prefix-sum');\n\n        // --- 3. Emit (tileKey, splatValue) pairs. ---\n        b.emitPairsCompute.setParameter('chunkSize', chunkSize);\n        b.emitPairsCompute.setupDispatch(Math.ceil(chunkSize / 64), 1, 1);\n        this.device.computeDispatch([b.emitPairsCompute], 'splat-tilebin-emit-pairs');\n\n        // --- 4. Prepare indirect dispatch params for sort + find-boundaries. ---\n        // @ts-ignore - indirectDispatchBuffer getter is WebGPU-only.\n        const indirectBuf = (this.device as { indirectDispatchBuffer?: StorageBuffer | null }).indirectDispatchBuffer;\n        const { sortSlot, boundariesSlot } = this.acquireIndirectSlots();\n        if (!indirectBuf) {\n            throw new Error('Device indirectDispatchBuffer not allocated (WebGPU backend required).');\n        }\n        b.prepareIndirectCompute.setParameter('indirectBuffer', indirectBuf);\n        // Each slot is 3 u32s in the buffer; the shader writes to\n        // indirectBuffer[base + {0,1,2}], so base = slot * 3.\n        b.prepareIndirectCompute.setParameter('sortSlotBase', sortSlot * 3);\n        b.prepareIndirectCompute.setParameter('boundariesSlotBase', boundariesSlot * 3);\n        b.prepareIndirectCompute.setupDispatch(1, 1, 1);\n        this.device.computeDispatch([b.prepareIndirectCompute], 'splat-tilebin-prepare-indirect');\n\n        // --- 5. Radix sort the pairs (indirect dispatch, key + value). ---\n        // tileKeysBuffer holds u32 tileIdx; splatValuesBuffer holds u32\n        // splatIdx as the initial-values payload. After the sort:\n        //   - radixSort.sortedKeys[i]    = the i-th sorted tile index\n        //   - radixSort.sortedIndices[i] = the splat index originally\n        //                                  paired with that tile\n        // The radix sort is stable, so within each tile the splatValues\n        // remain in their input order = depth-monotonic (from the CPU\n        // pre-sort), giving depth-ordered compositing per tile for free.\n        // numBits = sortKeyBits (rounded up to multiple of 4 from\n        // ceil(log2(numTiles))) — only the minimum required passes run.\n        const pairsCap = this.chunkCap * this.options.maxCoveragePerSplat;\n        this.radixSort.sortIndirect(\n            b.tileKeysBuffer, pairsCap, this.sortKeyBits, sortSlot,\n            b.totalPairsBuffer, b.splatValuesBuffer\n        );\n        const sortedTileKeysBuf = this.radixSort.sortedKeys;\n        const sortedSplatIndicesBuf = this.radixSort.sortedIndices;\n        if (!sortedTileKeysBuf || !sortedSplatIndicesBuf) {\n            throw new Error('ComputeRadixSort returned null sortedKeys/sortedIndices after sortIndirect()');\n        }\n\n        // --- 6. Init tile-offsets to the sentinel (= totalPairs). ---\n        const numTiles = this.groupTilesX * this.groupTilesY;\n        b.initTileOffsetsCompute.setupDispatch(Math.ceil((numTiles + 1) / 64), 1, 1);\n        this.device.computeDispatch([b.initTileOffsetsCompute], 'splat-tilebin-init-tile-offsets');\n\n        // --- 7. Find tile boundaries via atomicMin. ---\n        b.findBoundariesCompute.setParameter('sortedTileKeys', sortedTileKeysBuf);\n        b.findBoundariesCompute.setupIndirectDispatch(boundariesSlot);\n        this.device.computeDispatch([b.findBoundariesCompute], 'splat-tilebin-find-boundaries');\n\n        // --- 8. Rasterize: walk each tile's slice in depth order. ---\n        b.rasterizeBinnedCompute.setParameter('sortedSplatIndices', sortedSplatIndicesBuf);\n        b.rasterizeBinnedCompute.setParameter('chunkSize', chunkSize);\n        b.rasterizeBinnedCompute.setupDispatch(this.groupTilesX, this.groupTilesY, 1);\n        this.device.computeDispatch([b.rasterizeBinnedCompute], 'splat-rasterize-binned');\n\n        this.submit();\n    }\n\n    /**\n     * Finish processing a group. Dispatches finalize-pack and starts an\n     * async readback of the group's RGBA8 pixel bytes.\n     *\n     * Dispatch + readback are sized to the ACTIVE group dimensions (set\n     * by the most recent `beginGroup`), not the constructor-provided\n     * maximum, so edge sub-frames smaller than the max don't pay for\n     * unused workgroups or readback bytes.\n     *\n     * @returns Promise resolving to the active group's RGBA byte buffer\n     * (`activeTilesX·16 × activeTilesY·16 × 4` bytes).\n     */\n    finishGroup(): Promise<Uint8Array> {\n        const b = this.buffers;\n        b.finalizeCompute.setupDispatch(this.activeTilesX, this.activeTilesY, 1);\n        this.device.computeDispatch([b.finalizeCompute], 'splat-finalize');\n\n        const activePixelW = this.activeTilesX * TILE_SIZE;\n        const activePixelH = this.activeTilesY * TILE_SIZE;\n        const groupOutputBytes = activePixelW * activePixelH * 4;\n        return b.outputBuffer.read(0, groupOutputBytes, null, true) as Promise<Uint8Array>;\n    }\n\n    /**\n     * Release all GPU resources.\n     */\n    destroy(): void {\n        this.radixSort.destroy();\n        const b = this.buffers;\n        b.inputBuffer.destroy();\n        b.projBuffer.destroy();\n        b.runningStateBuffer.destroy();\n        b.outputBuffer.destroy();\n        b.tileOffsetsBuffer.destroy();\n        b.coverageBuffer.destroy();\n        b.emitOffsetBuffer.destroy();\n        b.totalPairsBuffer.destroy();\n        b.tileKeysBuffer.destroy();\n        b.splatValuesBuffer.destroy();\n        this.projectShader.destroy();\n        this.prefixSumShader.destroy();\n        this.emitPairsShader.destroy();\n        this.prepareIndirectShader.destroy();\n        this.initTileOffsetsShader.destroy();\n        this.findBoundariesShader.destroy();\n        this.rasterizeBinnedShader.destroy();\n        this.finalizeShader.destroy();\n        this.projectBgFormat.destroy();\n        this.prefixSumBgFormat.destroy();\n        this.emitPairsBgFormat.destroy();\n        this.prepareIndirectBgFormat.destroy();\n        this.initTileOffsetsBgFormat.destroy();\n        this.findBoundariesBgFormat.destroy();\n        this.rasterizeBinnedBgFormat.destroy();\n        this.finalizeBgFormat.destroy();\n    }\n}\n\nexport { GpuSplatRasterizer, type SplatRasterizerOptions };\n","import {\n    BUFFERUSAGE_COPY_DST,\n    BUFFERUSAGE_COPY_SRC,\n    SHADERLANGUAGE_WGSL,\n    SHADERSTAGE_COMPUTE,\n    UNIFORMTYPE_FLOAT,\n    UNIFORMTYPE_UINT,\n    BindGroupFormat,\n    BindStorageBufferFormat,\n    BindUniformBufferFormat,\n    Compute,\n    GraphicsDevice,\n    Shader,\n    StorageBuffer,\n    UniformBufferFormat,\n    UniformFormat\n} from 'playcanvas';\n\nimport { DataTable } from '../data-table';\n\n/**\n * WGSL shader for multi-batch voxelization of 4x4x4 blocks.\n *\n * Each workgroup processes one block in one batch.\n * - workgroup_id.z = batch index\n * - workgroup_id.x = flat block index within the batch\n * Per-batch metadata (index range, block origin, dimensions) comes from a storage buffer,\n * allowing many batches to be dispatched in a single GPU call.\n *\n * @returns WGSL shader code\n */\nconst voxelizeMultiBatchWgsl = () => {\n    return /* wgsl */ `\n\nstruct Uniforms {\n    opacityCutoff: f32,\n    voxelResolution: f32,\n    maxBlocksPerBatch: u32\n}\n\nstruct Gaussian {\n    posX: f32,\n    posY: f32,\n    posZ: f32,\n    opacityLogit: f32,\n    rotW: f32,\n    rotX: f32,\n    rotY: f32,\n    rotZ: f32,\n    scaleX: f32,\n    scaleY: f32,\n    scaleZ: f32,\n    extentX: f32,\n    extentY: f32,\n    extentZ: f32,\n    _padding0: f32,\n    _padding1: f32\n}\n\nstruct BatchInfo {\n    indexOffset: u32,\n    indexCount: u32,\n    numBlocksX: u32,\n    numBlocksY: u32,\n    numBlocksZ: u32,\n    blockMinX: f32,\n    blockMinY: f32,\n    blockMinZ: f32\n}\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var<storage, read> allGaussians: array<Gaussian>;\n@group(0) @binding(2) var<storage, read> indices: array<u32>;\n@group(0) @binding(3) var<storage, read_write> results: array<u32>;\n@group(0) @binding(4) var<storage, read> batchInfos: array<BatchInfo>;\n\n// Shared memory for cooperative Gaussian loading.\n// All 64 threads in a workgroup load one Gaussian each, then all threads\n// evaluate against the shared chunk — reducing global memory reads by 64x.\n// 64 Gaussians * 64 bytes each = 4 KB (well within 16 KB WebGPU minimum).\nconst tileSize = 64u;\nvar<workgroup> sharedGaussians: array<Gaussian, tileSize>;\nvar<workgroup> blockMasks: array<atomic<u32>, 2>;\n\nfn mortonToXYZ(m: u32) -> vec3u {\n    return vec3u(\n        (m & 1u) | ((m >> 2u) & 2u),\n        ((m >> 1u) & 1u) | ((m >> 3u) & 2u),\n        ((m >> 2u) & 1u) | ((m >> 4u) & 2u)\n    );\n}\n\n// Evaluate Gaussian contribution to a voxel.\n// Uses pre-computed AABB extents for accurate overlap check.\n// Returns raw density contribution for extinction-based accumulation.\nfn evaluateGaussianForVoxel(voxelCenter: vec3f, voxelHalfSize: f32, g: Gaussian) -> f32 {\n    let gaussianCenter = vec3f(g.posX, g.posY, g.posZ);\n    let diff = voxelCenter - gaussianCenter;\n    \n    // Use pre-computed world-space AABB half-extents (3-sigma, accounts for rotation)\n    let extent = vec3f(g.extentX, g.extentY, g.extentZ);\n    \n    // Per-axis AABB overlap check\n    if (any(abs(diff) > (extent + voxelHalfSize))) {\n        return 0.0;\n    }\n    \n    // Find closest point in voxel to Gaussian center\n    let closestPoint = clamp(gaussianCenter, voxelCenter - voxelHalfSize, voxelCenter + voxelHalfSize);\n    let closestDiff = closestPoint - gaussianCenter;\n    \n    // Inverse rotation using cross-product formula (Rodrigues rotation)\n    // For inverse: negate xyz components of quaternion\n    let qxyz = vec3f(-g.rotX, -g.rotY, -g.rotZ);\n    let t = 2.0 * cross(qxyz, closestDiff);\n    let localDiff = closestDiff + g.rotW * t + cross(qxyz, t);\n    \n    // Calculate Mahalanobis distance squared\n    let invScale = vec3f(exp(-g.scaleX), exp(-g.scaleY), exp(-g.scaleZ));\n    let scaled = localDiff * invScale;\n    let d2 = dot(scaled, scaled);\n    \n    // Get Gaussian opacity and return density contribution\n    let opacity = 1.0 / (1.0 + exp(-g.opacityLogit));\n    return opacity * exp(-0.5 * d2);\n}\n\n@compute @workgroup_size(64)\nfn main(\n    @builtin(local_invocation_index) voxelIdx: u32,\n    @builtin(workgroup_id) wgId: vec3u\n) {\n    let batchIdx = wgId.z;\n    let flatBlockId = wgId.x;\n    let info = batchInfos[batchIdx];\n    \n    // Skip padded workgroups beyond the batch's actual block count\n    let totalBlocks = info.numBlocksX * info.numBlocksY * info.numBlocksZ;\n    if (flatBlockId >= totalBlocks) { return; }\n    \n    // Decompose flat block ID to 3D coordinates within the batch\n    let blockX = flatBlockId % info.numBlocksX;\n    let blockY = (flatBlockId / info.numBlocksX) % info.numBlocksY;\n    let blockZ = flatBlockId / (info.numBlocksX * info.numBlocksY);\n    \n    let localPos = mortonToXYZ(voxelIdx);\n    let blockMin = vec3f(info.blockMinX, info.blockMinY, info.blockMinZ);\n    let blockOffset = vec3f(f32(blockX), f32(blockY), f32(blockZ)) * 4.0 * uniforms.voxelResolution;\n    let voxelCenter = blockMin + blockOffset + (vec3f(localPos) + 0.5) * uniforms.voxelResolution;\n    let voxelHalfSize = uniforms.voxelResolution * 0.5;\n\n    if (voxelIdx < 2u) {\n        atomicStore(&blockMasks[voxelIdx], 0u);\n    }\n    workgroupBarrier();\n    \n    // Extinction-based density accumulation with shared memory tiling.\n    // Instead of each thread independently reading Gaussians from global memory,\n    // all 64 threads cooperatively load a tile of 64 Gaussians into shared memory,\n    // then all threads evaluate against the shared tile before loading the next.\n    var totalSigma = 0.0;\n    let numIndices = info.indexCount;\n    let numTiles = (numIndices + tileSize - 1u) / tileSize;\n    \n    for (var tile = 0u; tile < numTiles; tile++) {\n        // Cooperative load: each thread loads one Gaussian into shared memory\n        let loadIdx = tile * tileSize + voxelIdx;\n        if (loadIdx < numIndices) {\n            let gaussianIdx = indices[info.indexOffset + loadIdx];\n            sharedGaussians[voxelIdx] = allGaussians[gaussianIdx];\n        }\n        \n        // Wait for all threads to finish loading the tile\n        workgroupBarrier();\n        \n        // Evaluate all Gaussians in this tile (skip math if already saturated)\n        if (totalSigma < 7.0) {\n            let thisTileSize = min(tileSize, numIndices - tile * tileSize);\n            for (var c = 0u; c < thisTileSize; c++) {\n                totalSigma += evaluateGaussianForVoxel(voxelCenter, voxelHalfSize, sharedGaussians[c]);\n                if (totalSigma >= 7.0) {\n                    break;\n                }\n            }\n        }\n        \n        // Wait before next tile overwrites shared memory\n        workgroupBarrier();\n    }\n    \n    // Convert accumulated density to opacity using Beer-Lambert law\n    let finalOpacity = 1.0 - exp(-totalSigma);\n    \n    // Determine if voxel is solid\n    let isSolid = finalOpacity >= uniforms.opacityCutoff;\n    \n    // Accumulate this block's 64 voxel bits in workgroup memory, then write the\n    // two packed u32 result words once. Each workgroup owns one output block.\n    let linearIdx = localPos.z * 16u + localPos.y * 4u + localPos.x;\n    if (isSolid) {\n        atomicOr(&blockMasks[linearIdx >> 5u], 1u << (linearIdx & 31u));\n    }\n    workgroupBarrier();\n\n    if (voxelIdx < 2u) {\n        let resultBase = batchIdx * uniforms.maxBlocksPerBatch * 2u + flatBlockId * 2u;\n        results[resultBase + voxelIdx] = atomicLoad(&blockMasks[voxelIdx]);\n    }\n}\n`;\n};\n\n/**\n * Specification for a single batch in a multi-batch dispatch.\n */\ninterface BatchSpec {\n    /** Offset into the concatenated index array */\n    indexOffset: number;\n\n    /** Number of Gaussian indices for this batch */\n    indexCount: number;\n\n    /** World-space minimum corner of the first block */\n    blockMin: { x: number; y: number; z: number };\n\n    /** Number of blocks in X direction */\n    numBlocksX: number;\n\n    /** Number of blocks in Y direction */\n    numBlocksY: number;\n\n    /** Number of blocks in Z direction */\n    numBlocksZ: number;\n}\n\n/**\n * Result of a multi-batch voxelization dispatch.\n */\ninterface MultiBatchResult {\n    /**\n     * Raw u32 masks for all batches.\n     * For batch i, block j: masks[(i * maxBlocksPerBatch + j) * 2] = low, [+1] = high\n     */\n    masks: Uint32Array;\n\n    /** Maximum blocks per batch, used for offset calculation */\n    maxBlocksPerBatch: number;\n}\n\n/**\n * A set of GPU buffers and compute instance for one dispatch slot.\n * Two slots allow double-buffered pipelining: while the GPU executes\n * a dispatch on slot A, the CPU can prepare data for slot B.\n */\ninterface DispatchSlot {\n    indexBuffer: StorageBuffer;\n    resultsBuffer: StorageBuffer;\n    batchInfoBuffer: StorageBuffer;\n    compute: Compute;\n    indexBufferSize: number;\n    resultsBufferSize: number;\n    batchInfoBufferSize: number;\n}\n\n/**\n * GPU-accelerated voxelization of Gaussian splat data.\n *\n * Uploads all Gaussian data once, then dispatches many batches in a single\n * GPU call using per-batch metadata to minimize CPU-GPU synchronization.\n *\n * Supports double-buffered pipelining via two dispatch slots: the CPU can\n * prepare the next mega-dispatch while the GPU is still executing the current one.\n */\nclass GpuVoxelization {\n    private device: GraphicsDevice;\n    private shader: Shader;\n    private bindGroupFormat: BindGroupFormat;\n\n    // Shared Gaussian buffer (read-only, uploaded once)\n    private gaussianBuffer: StorageBuffer | null = null;\n\n    // Double-buffered dispatch slots\n    private slots: DispatchSlot[];\n\n    private totalGaussians: number = 0;\n\n    /** Floats per Gaussian in the interleaved buffer (16 for alignment) */\n    private static readonly FLOATS_PER_GAUSSIAN = 16;\n\n    /** Gaussian rows per CPU staging chunk when uploading to the shared GPU buffer. */\n    private static readonly UPLOAD_CHUNK_GAUSSIANS = 1 << 18;\n\n    /** Maximum blocks per batch (16^3 = 4096 for 4x4x4 voxel blocks in a 16-block batch) */\n    static readonly MAX_BLOCKS_PER_BATCH = 4096;\n\n    /** Number of u32 fields per BatchInfo struct */\n    private static readonly BATCH_INFO_U32S = 8;\n\n    /** Number of dispatch slots (for double-buffered pipelining) */\n    static readonly NUM_SLOTS = 2;\n\n    /**\n     * Create a GPU voxelization instance.\n     *\n     * @param device - PlayCanvas graphics device (must support WebGPU compute)\n     */\n    constructor(device: GraphicsDevice) {\n        this.device = device;\n\n        // Create shared bind group format with 5 bindings:\n        // 0: uniforms, 1: allGaussians (read), 2: indices (read), 3: results (read_write), 4: batchInfos (read)\n        this.bindGroupFormat = new BindGroupFormat(device, [\n            new BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('allGaussians', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('indices', SHADERSTAGE_COMPUTE, true),\n            new BindStorageBufferFormat('results', SHADERSTAGE_COMPUTE),\n            new BindStorageBufferFormat('batchInfos', SHADERSTAGE_COMPUTE, true)\n        ]);\n\n        // Create shared shader\n        this.shader = new Shader(device, {\n            name: 'voxelize-multi-batch',\n            shaderLanguage: SHADERLANGUAGE_WGSL,\n            cshader: voxelizeMultiBatchWgsl(),\n            // @ts-ignore - computeUniformBufferFormats not in types\n            computeUniformBufferFormats: {\n                uniforms: new UniformBufferFormat(device, [\n                    new UniformFormat('opacityCutoff', UNIFORMTYPE_FLOAT),\n                    new UniformFormat('voxelResolution', UNIFORMTYPE_FLOAT),\n                    new UniformFormat('maxBlocksPerBatch', UNIFORMTYPE_UINT)\n                ])\n            },\n            // @ts-ignore - computeBindGroupFormat not in types\n            computeBindGroupFormat: this.bindGroupFormat\n        });\n\n        // Create double-buffered dispatch slots\n        this.slots = [];\n        for (let i = 0; i < GpuVoxelization.NUM_SLOTS; i++) {\n            const indexBufferSize = 1024 * 1024 * 4;  // 1M indices = 4 MB\n            const indexBuffer = new StorageBuffer(device, indexBufferSize, BUFFERUSAGE_COPY_DST);\n\n            // Initial capacity: 64 batches × 4096 blocks × 2 u32 × 4 bytes = 2 MB\n            const resultsBufferSize = 64 * GpuVoxelization.MAX_BLOCKS_PER_BATCH * 2 * 4;\n            const resultsBuffer = new StorageBuffer(device, resultsBufferSize, BUFFERUSAGE_COPY_SRC);\n\n            // 64 batches × 8 fields × 4 bytes = 2 KB\n            const batchInfoBufferSize = 64 * GpuVoxelization.BATCH_INFO_U32S * 4;\n            const batchInfoBuffer = new StorageBuffer(device, batchInfoBufferSize, BUFFERUSAGE_COPY_DST);\n\n            const compute = new Compute(device, this.shader, `voxelize-slot-${i}`);\n            compute.setParameter('indices', indexBuffer);\n            compute.setParameter('results', resultsBuffer);\n            compute.setParameter('batchInfos', batchInfoBuffer);\n\n            this.slots.push({\n                indexBuffer,\n                resultsBuffer,\n                batchInfoBuffer,\n                compute,\n                indexBufferSize,\n                resultsBufferSize,\n                batchInfoBufferSize\n            });\n        }\n\n    }\n\n    /**\n     * Upload all Gaussian data to GPU once.\n     * Must be called before any dispatch methods.\n     *\n     * @param dataTable - DataTable containing all Gaussian properties\n     * @param extents - DataTable containing pre-computed AABB extents (extent_x, extent_y, extent_z)\n     */\n    uploadAllGaussians(dataTable: DataTable, extents: DataTable): void {\n        const numGaussians = dataTable.numRows;\n        this.totalGaussians = numGaussians;\n\n        // Create buffer sized for ALL Gaussians\n        const bufferSize = numGaussians * GpuVoxelization.FLOATS_PER_GAUSSIAN * 4;\n\n        // Destroy old buffer if it exists\n        if (this.gaussianBuffer) {\n            this.gaussianBuffer.destroy();\n        }\n\n        this.gaussianBuffer = new StorageBuffer(this.device, bufferSize, BUFFERUSAGE_COPY_DST);\n\n        const x = dataTable.getColumnByName('x').data;\n        const y = dataTable.getColumnByName('y').data;\n        const z = dataTable.getColumnByName('z').data;\n        const opacity = dataTable.getColumnByName('opacity').data;\n        const rotW = dataTable.getColumnByName('rot_0').data;\n        const rotX = dataTable.getColumnByName('rot_1').data;\n        const rotY = dataTable.getColumnByName('rot_2').data;\n        const rotZ = dataTable.getColumnByName('rot_3').data;\n        const scaleX = dataTable.getColumnByName('scale_0').data;\n        const scaleY = dataTable.getColumnByName('scale_1').data;\n        const scaleZ = dataTable.getColumnByName('scale_2').data;\n        const extentX = extents.getColumnByName('extent_x').data;\n        const extentY = extents.getColumnByName('extent_y').data;\n        const extentZ = extents.getColumnByName('extent_z').data;\n\n        const stride = GpuVoxelization.FLOATS_PER_GAUSSIAN;\n        const chunkRows = Math.min(numGaussians, GpuVoxelization.UPLOAD_CHUNK_GAUSSIANS);\n        const interleavedData = new Float32Array(chunkRows * stride);\n\n        for (let chunkStart = 0; chunkStart < numGaussians; chunkStart += chunkRows) {\n            const chunkCount = Math.min(chunkRows, numGaussians - chunkStart);\n            for (let j = 0; j < chunkCount; j++) {\n                const i = chunkStart + j;\n                const offset = j * stride;\n                interleavedData[offset + 0] = x[i];\n                interleavedData[offset + 1] = y[i];\n                interleavedData[offset + 2] = z[i];\n                interleavedData[offset + 3] = opacity[i];\n\n                // Normalize quaternion — the Rodrigues rotation in the shader\n                // assumes unit quaternions; non-normalized ones (common in MCMC\n                // training) would produce incorrect Mahalanobis distances.\n                const qw = rotW[i], qx = rotX[i], qy = rotY[i], qz = rotZ[i];\n                const qlen = Math.sqrt(qw * qw + qx * qx + qy * qy + qz * qz);\n                const invLen = qlen > 0 ? 1 / qlen : 0;\n                interleavedData[offset + 4] = qw * invLen;\n                interleavedData[offset + 5] = qx * invLen;\n                interleavedData[offset + 6] = qy * invLen;\n                interleavedData[offset + 7] = qz * invLen;\n                interleavedData[offset + 8] = scaleX[i];\n                interleavedData[offset + 9] = scaleY[i];\n                interleavedData[offset + 10] = scaleZ[i];\n                interleavedData[offset + 11] = extentX[i];\n                interleavedData[offset + 12] = extentY[i];\n                interleavedData[offset + 13] = extentZ[i];\n                interleavedData[offset + 14] = 0; // padding\n                interleavedData[offset + 15] = 0; // padding\n            }\n\n            this.gaussianBuffer.write(chunkStart * stride * 4, interleavedData, 0, chunkCount * stride);\n        }\n\n        // Bind the shared Gaussian buffer to ALL slot compute instances\n        for (const slot of this.slots) {\n            slot.compute.setParameter('allGaussians', this.gaussianBuffer);\n        }\n    }\n\n    /**\n     * Ensure a slot's buffer is at least the given size, growing if needed.\n     *\n     * @param slot - Dispatch slot to check.\n     * @param bufferKey - Key of the StorageBuffer property on the slot.\n     * @param sizeKey - Key of the corresponding size-tracking property.\n     * @param neededSize - Minimum required buffer size in bytes.\n     * @param usage - GPU buffer usage flags for the new buffer.\n     * @param paramName - Compute parameter name to rebind after replacement.\n     */\n    private ensureSlotBuffer(\n        slot: DispatchSlot,\n        bufferKey: 'indexBuffer' | 'resultsBuffer' | 'batchInfoBuffer',\n        sizeKey: 'indexBufferSize' | 'resultsBufferSize' | 'batchInfoBufferSize',\n        neededSize: number,\n        usage: number,\n        paramName: string\n    ): void {\n        if (neededSize <= slot[sizeKey]) return;\n\n        slot[bufferKey].destroy();\n        const newBuffer = new StorageBuffer(this.device, neededSize, usage);\n        slot.compute.setParameter(paramName, newBuffer);\n        slot[bufferKey] = newBuffer;\n        slot[sizeKey] = neededSize;\n    }\n\n    /**\n     * Submit a multi-batch dispatch on the specified slot.\n     *\n     * Returns a Promise that resolves when GPU results are ready. The caller\n     * should NOT await immediately — do CPU work first (BVH queries, index\n     * copying for the next dispatch) to overlap CPU and GPU execution.\n     *\n     * Use different slot indices for consecutive calls to avoid buffer conflicts.\n     *\n     * @param slotIndex - Which dispatch slot to use (0 or 1)\n     * @param concatenatedIndices - Pre-built Uint32Array of all Gaussian indices\n     * @param totalIndices - Number of valid indices in the array\n     * @param batches - Per-batch metadata (index offset/count, block origin, dimensions)\n     * @param voxelResolution - Size of each voxel in world units\n     * @param opacityCutoff - Opacity threshold for solid voxels (0.0-1.0)\n     * @returns Promise resolving to multi-batch voxelization results\n     */\n    submitMultiBatch(\n        slotIndex: number,\n        concatenatedIndices: Uint32Array,\n        totalIndices: number,\n        batches: BatchSpec[],\n        voxelResolution: number,\n        opacityCutoff: number\n    ): Promise<MultiBatchResult> {\n        if (!this.gaussianBuffer) {\n            throw new Error('uploadAllGaussians must be called before submitMultiBatch');\n        }\n\n        const slot = this.slots[slotIndex];\n        const maxBlocks = GpuVoxelization.MAX_BLOCKS_PER_BATCH;\n        const numBatches = batches.length;\n\n        if (numBatches === 0) {\n            return Promise.resolve({ masks: new Uint32Array(0), maxBlocksPerBatch: maxBlocks });\n        }\n\n        // Ensure slot buffers are large enough\n        this.ensureSlotBuffer(\n            slot, 'indexBuffer', 'indexBufferSize',\n            totalIndices * 4, BUFFERUSAGE_COPY_DST, 'indices'\n        );\n\n        const resultsU32Count = numBatches * maxBlocks * 2;\n        this.ensureSlotBuffer(\n            slot, 'resultsBuffer', 'resultsBufferSize',\n            resultsU32Count * 4, BUFFERUSAGE_COPY_SRC, 'results'\n        );\n\n        const batchInfoU32Count = numBatches * GpuVoxelization.BATCH_INFO_U32S;\n        this.ensureSlotBuffer(\n            slot, 'batchInfoBuffer', 'batchInfoBufferSize',\n            batchInfoU32Count * 4, BUFFERUSAGE_COPY_DST, 'batchInfos'\n        );\n\n        // Upload concatenated indices\n        slot.indexBuffer.write(0, concatenatedIndices, 0, totalIndices);\n\n        // Build and upload batch info\n        const batchInfoF32 = new Float32Array(batchInfoU32Count);\n        const batchInfoU32 = new Uint32Array(batchInfoF32.buffer);\n\n        for (let i = 0; i < numBatches; i++) {\n            const batch = batches[i];\n            const base = i * GpuVoxelization.BATCH_INFO_U32S;\n\n            batchInfoU32[base + 0] = batch.indexOffset;\n            batchInfoU32[base + 1] = batch.indexCount;\n            batchInfoU32[base + 2] = batch.numBlocksX;\n            batchInfoU32[base + 3] = batch.numBlocksY;\n            batchInfoU32[base + 4] = batch.numBlocksZ;\n            batchInfoF32[base + 5] = batch.blockMin.x;\n            batchInfoF32[base + 6] = batch.blockMin.y;\n            batchInfoF32[base + 7] = batch.blockMin.z;\n        }\n\n        slot.batchInfoBuffer.write(0, batchInfoU32, 0, batchInfoU32Count);\n\n        // Set uniforms (global values only — per-batch values are in batchInfos)\n        slot.compute.setParameter('opacityCutoff', opacityCutoff);\n        slot.compute.setParameter('voxelResolution', voxelResolution);\n        slot.compute.setParameter('maxBlocksPerBatch', maxBlocks);\n\n        // Dispatch: x = max blocks per batch (padded), y = 1, z = num batches\n        slot.compute.setupDispatch(maxBlocks, 1, numBatches);\n        this.device.computeDispatch([slot.compute], `voxelize-slot-${slotIndex}`);\n\n        // Return promise for deferred readback — the caller controls when to await\n        const readSize = resultsU32Count * 4;\n        return slot.resultsBuffer.read(0, readSize, null, true).then((readData: Uint8Array) => {\n            const masks = new Uint32Array(readData.buffer, readData.byteOffset, resultsU32Count);\n            return { masks, maxBlocksPerBatch: maxBlocks };\n        });\n    }\n\n    /**\n     * Get the total number of Gaussians uploaded.\n     *\n     * @returns Total Gaussian count\n     */\n    get numGaussians(): number {\n        return this.totalGaussians;\n    }\n\n    /**\n     * Destroy GPU resources.\n     */\n    destroy(): void {\n        if (this.gaussianBuffer) {\n            this.gaussianBuffer.destroy();\n        }\n        for (const slot of this.slots) {\n            slot.indexBuffer.destroy();\n            slot.resultsBuffer.destroy();\n            slot.batchInfoBuffer.destroy();\n        }\n        this.shader.destroy();\n        this.bindGroupFormat.destroy();\n    }\n}\n\nexport { GpuVoxelization, type BatchSpec, type MultiBatchResult };\n","import { GraphicsDevice } from 'playcanvas';\n\nimport { KdTree } from './kd-tree';\nimport { Column, DataTable } from '../data-table';\nimport { GpuClustering } from '../gpu';\nimport { logger } from '../utils';\n\n// use floyd's algorithm to pick m unique random indices from 0..n-1\nconst pickRandomIndices = (n: number, m: number) => {\n    const chosen = new Set<number>();\n    for (let j = n - m; j < n; j++) {\n        const t = Math.floor(Math.random() * (j + 1));\n        chosen.add(chosen.has(t) ? j : t);\n    }\n    return [...chosen];\n};\n\nconst initializeCentroids = (dataTable: DataTable, centroids: DataTable, row: any) => {\n    const indices = pickRandomIndices(dataTable.numRows, centroids.numRows);\n    for (let i = 0; i < centroids.numRows; ++i) {\n        dataTable.getRow(indices[i], row);\n        centroids.setRow(i, row);\n    }\n};\n\n// in the 1d case we use quantile-based initialization for better handling of skewed data\nconst initializeCentroids1D = (dataTable: DataTable, centroids: DataTable) => {\n    const data = dataTable.getColumn(0).data;\n    const n = dataTable.numRows;\n    const k = centroids.numRows;\n\n    // Sort data to compute quantiles\n    const sorted = Float32Array.from(data).sort((a, b) => a - b);\n\n    const centroidsData = centroids.getColumn(0).data;\n    for (let i = 0; i < k; ++i) {\n        // Place centroid at the center of its expected cluster region\n        const quantile = (2 * i + 1) / (2 * k);\n        const index = Math.min(Math.floor(quantile * n), n - 1);\n        centroidsData[i] = sorted[index];\n    }\n};\n\nconst calcAverage = (dataTable: DataTable, cluster: number[], row: any) => {\n    const keys = dataTable.columnNames;\n\n    for (let i = 0; i < keys.length; ++i) {\n        row[keys[i]] = 0;\n    }\n\n    const dataRow: any = {};\n    for (let i = 0; i < cluster.length; ++i) {\n        dataTable.getRow(cluster[i], dataRow);\n\n        for (let j = 0; j < keys.length; ++j) {\n            const key = keys[j];\n            row[key] += dataRow[key];\n        }\n    }\n\n    if (cluster.length > 0) {\n        for (let i = 0; i < keys.length; ++i) {\n            row[keys[i]] /= cluster.length;\n        }\n    }\n};\n\nconst clusterKdTreeCpu = (points: DataTable, centroids: DataTable, labels: Uint32Array) => {\n    const kdTree = new KdTree(centroids);\n\n    // construct a kdtree over the centroids so we can find the nearest quickly\n    const point = new Float32Array(points.numColumns);\n    const row: any = {};\n\n    // assign each point to the nearest centroid\n    for (let i = 0; i < points.numRows; ++i) {\n        points.getRow(i, row);\n        points.columns.forEach((c, i) => {\n            point[i] = row[c.name];\n        });\n\n        const a = kdTree.findNearest(point);\n\n        labels[i] = a.index;\n    }\n};\n\nconst groupLabels = (labels: Uint32Array, k: number) => {\n    const clusters: number[][] = [];\n\n    for (let i = 0; i < k; ++i) {\n        clusters[i] = [];\n    }\n\n    for (let i = 0; i < labels.length; ++i) {\n        clusters[labels[i]].push(i);\n    }\n\n    return clusters;\n};\n\nconst kmeans = async (points: DataTable, k: number, iterations: number, device?: GraphicsDevice) => {\n    // too few data points\n    if (points.numRows < k) {\n        return {\n            centroids: points.clone(),\n            // use a typed array here so downstream code can rely on\n            // labels supporting subarray(), even in this early-return\n            // path used for very small datasets.\n            labels: new Uint32Array(points.numRows).map((_, i) => i)\n        };\n    }\n\n    const row: any = {};\n\n    // construct centroids data table and assign initial values\n    const centroids = new DataTable(points.columns.map(c => new Column(c.name, new Float32Array(k))));\n    if (points.numColumns === 1) {\n        initializeCentroids1D(points, centroids);\n    } else {\n        initializeCentroids(points, centroids, row);\n    }\n\n    const gpuClustering = device && new GpuClustering(device, points.numColumns, k);\n    const labels = new Uint32Array(points.numRows);\n\n    let converged = false;\n    let steps = 0;\n\n    logger.debug(`running k-means clustering: dims=${points.numColumns} points=${points.numRows} clusters=${k} iterations=${iterations}`);\n\n    const bar = logger.bar('k-means', iterations);\n    try {\n        while (!converged) {\n            if (gpuClustering) {\n                await gpuClustering.execute(points, centroids, labels);\n            } else {\n                clusterKdTreeCpu(points, centroids, labels);\n            }\n\n            // calculate the new centroid positions\n            const groups = groupLabels(labels, k);\n            for (let i = 0; i < centroids.numRows; ++i) {\n                if (groups[i].length === 0) {\n                    // re-seed this centroid to a random point to avoid zero vector\n                    const idx = Math.floor(Math.random() * points.numRows);\n                    points.getRow(idx, row);\n                    centroids.setRow(i, row);\n                } else {\n                    calcAverage(points, groups[i], row);\n                    centroids.setRow(i, row);\n                }\n            }\n\n            steps++;\n\n            if (steps >= iterations) {\n                converged = true;\n            }\n\n            bar.tick();\n        }\n    } catch (e) {\n        gpuClustering?.destroy();\n        throw e;\n    }\n\n    bar.end();\n    gpuClustering?.destroy();\n\n    return { centroids, labels };\n};\n\nexport { kmeans };\n","import { Column, DataTable } from '../data-table/data-table';\n\n/**\n * Optimal 1D quantization using dynamic programming on a histogram.\n *\n * Pools all columns of the input DataTable into a single 1D dataset,\n * sorts the values, bins them using a blend of uniform and quantile\n * positioning, then uses DP to find k centroids that minimize weighted\n * sum-of-squared-errors (SSE).\n *\n * Bin positions are an adaptive blend of uniform (value-space) and\n * quantile (rank-space) positioning. The blend ratio is computed from\n * the data's IQR-to-range ratio: extreme outlier distributions (small\n * IQR relative to range) use near-pure quantile to give the dense\n * center adequate bins, while moderate-tail distributions reduce\n * quantile bias (but keep at least 50% quantile weighting).\n *\n * Bin weights use sub-linear density weighting: weight = count^alpha.\n * With alpha < 1, sparse tail regions earn meaningful influence on\n * centroid placement.\n *\n * @param dataTable - Input data table whose columns are pooled into 1D.\n * @param k - Number of codebook entries (default 256).\n * @param alpha - Density weight exponent. 0 = uniform (each bin equal),\n * 0.5 = sqrt (balanced), 1.0 = standard MSE (dense regions dominate).\n * Default 0.5.\n * @returns Object with `centroids` (DataTable with one 'data' column of\n * k Float32 values, sorted ascending) and `labels` (DataTable with same\n * column layout as input, each column containing Uint8Array indices into\n * the codebook).\n */\nconst quantize1d = (dataTable: DataTable, k = 256, alpha = 0.5) => {\n    const { numColumns, numRows } = dataTable;\n\n    // pool all columns into a flat 1D array\n    const N = numRows * numColumns;\n\n    if (N === 0) {\n        const centroids = new DataTable([new Column('data', new Float32Array(k))]);\n        const labels = new DataTable(dataTable.columnNames.map(name => new Column(name, new Uint8Array(numRows))));\n        return { centroids, labels };\n    }\n\n    const data = new Float32Array(N);\n    for (let i = 0; i < numColumns; ++i) {\n        data.set(dataTable.getColumn(i).data, i * numRows);\n    }\n\n    // sort a copy for histogram binning (keep original for label assignment)\n    const sortedData = new Float32Array(data);\n    sortedData.sort();\n\n    const vMin = sortedData[0];\n    const vMax = sortedData[N - 1];\n\n    // handle degenerate case where all values are identical\n    if (vMax - vMin < 1e-20) {\n        const centroids = new DataTable([new Column('data', new Float32Array(k))]);\n        centroids.getColumn(0).data.fill(vMin);\n\n        const result = new DataTable(dataTable.columnNames.map(name => new Column(name, new Uint8Array(numRows))));\n        return { centroids, labels: result };\n    }\n\n    // build histogram using blended uniform/quantile bin positions\n    const H = Math.min(1024, N);\n    const vRange = vMax - vMin;\n\n    // adaptive blend ratio: when outliers are extreme (IQR << range), lean\n    // strongly toward quantile to give the dense center adequate bins; when\n    // the distribution has moderate tails (IQR ~ range), reduce quantile\n    // bias somewhat, but keep at least 50% quantile to preserve density\n    const iqr = sortedData[Math.floor(N * 0.75)] - sortedData[Math.floor(N * 0.25)];\n    const beta = Math.max(0.5, Math.min(0.999, 1 - iqr / vRange));\n\n    const counts = new Float64Array(H);\n    const sums = new Float64Array(H);\n\n    for (let i = 0; i < N; ++i) {\n        const uniformPos = (sortedData[i] - vMin) / vRange;\n        const quantilePos = i / N;\n        const bin = Math.min(H - 1, Math.floor(H * (beta * quantilePos + (1 - beta) * uniformPos)));\n        counts[bin]++;\n        sums[bin] += sortedData[i];\n    }\n\n    const centers = new Float64Array(H);\n    for (let i = 0; i < H; ++i) {\n        centers[i] = counts[i] > 0 ? sums[i] / counts[i] : vMin + (i + 0.5) / H * vRange;\n    }\n\n    // compute weights: w = count^alpha (sub-linear density weighting)\n    const weights = new Float64Array(H);\n    for (let i = 0; i < H; ++i) {\n        weights[i] = counts[i] > 0 ? Math.pow(counts[i], alpha) : 0;\n    }\n\n    // prefix sums for O(1) range cost queries\n    //   cost(a,b) = sum_wxx - sum_wx^2 / sum_w\n    //   centroid(a,b) = sum_wx / sum_w\n    const prefW = new Float64Array(H + 1);\n    const prefWX = new Float64Array(H + 1);\n    const prefWXX = new Float64Array(H + 1);\n    for (let i = 0; i < H; ++i) {\n        prefW[i + 1] = prefW[i] + weights[i];\n        prefWX[i + 1] = prefWX[i] + weights[i] * centers[i];\n        prefWXX[i + 1] = prefWXX[i] + weights[i] * centers[i] * centers[i];\n    }\n\n    const rangeCost = (a: number, b: number): number => {\n        const w = prefW[b + 1] - prefW[a];\n        if (w <= 0) return 0;\n        const wx = prefWX[b + 1] - prefWX[a];\n        const wxx = prefWXX[b + 1] - prefWXX[a];\n        return wxx - (wx * wx) / w;\n    };\n\n    const rangeMean = (a: number, b: number): number => {\n        const w = prefW[b + 1] - prefW[a];\n        if (w <= 0) return (centers[a] + centers[b]) * 0.5;\n        return (prefWX[b + 1] - prefWX[a]) / w;\n    };\n\n    const nonEmpty = counts.reduce((n, c) => n + (c > 0 ? 1 : 0), 0);\n    const effectiveK = Math.min(k, nonEmpty);\n\n    // DP: dp[m][j] = min weighted SSE of quantizing bins 0..j into m centroids\n    // Use two rows to save memory (only need previous row)\n    const INF = 1e30;\n    let dpPrev = new Float64Array(H).fill(INF);\n    let dpCurr = new Float64Array(H).fill(INF);\n    const splitTable = new Array(effectiveK + 1);\n\n    // base case: m = 1\n    const split1 = new Int32Array(H);\n    for (let j = 0; j < H; ++j) {\n        dpPrev[j] = rangeCost(0, j);\n        split1[j] = -1;\n    }\n    splitTable[1] = split1;\n\n    // fill DP for m = 2..effectiveK\n    for (let m = 2; m <= effectiveK; ++m) {\n        dpCurr.fill(INF);\n        const splitM = new Int32Array(H);\n\n        for (let j = m - 1; j < H; ++j) {\n            let bestCost = INF;\n            let bestS = m - 2;\n\n            for (let s = m - 2; s < j; ++s) {\n                const cost = dpPrev[s] + rangeCost(s + 1, j);\n                if (cost < bestCost) {\n                    bestCost = cost;\n                    bestS = s;\n                }\n            }\n\n            dpCurr[j] = bestCost;\n            splitM[j] = bestS;\n        }\n\n        splitTable[m] = splitM;\n\n        // swap rows\n        const tmp = dpPrev;\n        dpPrev = dpCurr;\n        dpCurr = tmp;\n    }\n\n    // backtrack to find centroid values\n    const centroidValues = new Float32Array(effectiveK);\n    let j = H - 1;\n    for (let m = effectiveK; m >= 1; --m) {\n        const s = m > 1 ? splitTable[m][j] : -1;\n        centroidValues[m - 1] = rangeMean(s + 1, j);\n        j = s;\n    }\n\n    // sort centroids (should already be sorted, but ensure)\n    centroidValues.sort();\n\n    // pad to k entries if effectiveK < k (duplicate last centroid)\n    const finalCentroids = new Float32Array(k);\n    finalCentroids.set(centroidValues);\n    for (let i = effectiveK; i < k; ++i) {\n        finalCentroids[i] = centroidValues[effectiveK - 1];\n    }\n\n    // assign each data point to nearest centroid via binary search\n    const labels = new Uint8Array(N);\n    for (let i = 0; i < N; ++i) {\n        const v = data[i];\n\n        // binary search for nearest centroid\n        let lo = 0;\n        let hi = k - 1;\n        while (lo < hi) {\n            const mid = (lo + hi) >> 1;\n            // compare against midpoint between centroids mid and mid+1\n            if (v < (finalCentroids[mid] + finalCentroids[mid + 1]) * 0.5) {\n                hi = mid;\n            } else {\n                lo = mid + 1;\n            }\n        }\n        labels[i] = lo;\n    }\n\n    const centroids = new DataTable([new Column('data', finalCentroids)]);\n\n    const result = new DataTable(dataTable.columnNames.map(name => new Column(name, new Uint8Array(numRows))));\n    for (let i = 0; i < numColumns; ++i) {\n        result.getColumn(i).data.set(labels.subarray(i * numRows, (i + 1) * numRows));\n    }\n\n    return { centroids, labels: result };\n};\n\nexport { quantize1d };\n","import { basename, dirname, resolve } from 'pathe';\n\nimport { logWrittenFile } from './utils';\nimport { Column, DataTable, sortMortonOrder, convertToSpace, getSHBands, shRestNames } from '../data-table';\nimport { type FileSystem, writeFile, ZipFileSystem } from '../io/write';\nimport { kmeans, quantize1d } from '../spatial';\nimport type { DeviceCreator } from '../types';\nimport { logger, sigmoid, Transform, WebPCodec } from '../utils';\nimport { version } from '../version';\n\nconst calcMinMax = (dataTable: DataTable, columnNames: string[], indices: Uint32Array) => {\n    const columns = columnNames.map(name => dataTable.getColumnByName(name));\n    const minMax = columnNames.map(() => [Infinity, -Infinity]);\n    const row = {};\n\n    for (let i = 0; i < indices.length; ++i) {\n        const r = dataTable.getRow(indices[i], row, columns);\n\n        for (let j = 0; j < columnNames.length; ++j) {\n            const value = r[columnNames[j]];\n            if (value < minMax[j][0]) minMax[j][0] = value;\n            if (value > minMax[j][1]) minMax[j][1] = value;\n        }\n    }\n\n    return minMax;\n};\n\nconst logTransform = (value: number) => {\n    return Math.sign(value) * Math.log(Math.abs(value) + 1);\n};\n\n// no packing\nconst identity = (index: number) => {\n    return index;\n};\n\nconst generateIndices = (dataTable: DataTable) => {\n    const result = new Uint32Array(dataTable.numRows);\n    for (let i = 0; i < result.length; ++i) {\n        result[i] = i;\n    }\n    sortMortonOrder(dataTable, result);\n    return result;\n};\n\nlet webPCodec: WebPCodec;\n\ntype WriteSogOptions = {\n    filename: string;\n    dataTable: DataTable;\n    indices?: Uint32Array;\n    bundle: boolean;\n    iterations: number;\n    createDevice?: DeviceCreator;\n    // Controls how writeSog reports its own progress. This only affects\n    // writeSog's `Writing` group and per-file size lines; nested algorithm\n    // logging (e.g. `kmeans()` SH compression progress bars) still goes to\n    // the global logger and is not suppressed by 'silent'.\n    //   'own'    — open a `Writing` group and emit per-file info lines (default)\n    //   'flat'   — no group; emit per-file info lines into caller's scope\n    //   'silent' — suppress writeSog's own group/per-file info lines (use\n    //              when writing to an in-memory fs and the caller will log\n    //              the final bundled size itself)\n    logging?: 'own' | 'flat' | 'silent';\n};\n\n/**\n * Writes Gaussian splat data to the PlayCanvas SOG format.\n *\n * SOG (Splat Optimized Graphics) uses WebP lossless compression and k-means\n * clustering to achieve high compression ratios. Data is stored in textures\n * for efficient GPU loading.\n *\n * @param options - Options including filename, data, and compression settings.\n * @param fs - File system for writing output files.\n * @ignore\n */\nconst writeSog = async (options: WriteSogOptions, fs: FileSystem) => {\n    const { filename: outputFilename, bundle, iterations, createDevice } = options;\n    const logging = options.logging ?? 'own';\n    const emitInfo = logging !== 'silent';\n    const openGroup = logging === 'own';\n    const dataTable = convertToSpace(options.dataTable, Transform.PLY);\n\n    // initialize output stream - use ZipFileSystem for bundled output. The\n    // underlying writer's `bytesWritten` is read after close to report the\n    // final archive size as a single log entry instead of per-internal-file\n    // lines.\n    const bundleWriter = bundle ? await fs.createWriter(outputFilename) : null;\n    const zipFs = bundleWriter ? new ZipFileSystem(bundleWriter) : null;\n    const outputFs = zipFs || fs;\n\n    const indices = options.indices || generateIndices(dataTable);\n    const numRows = indices.length;\n    const width = Math.ceil(Math.sqrt(numRows) / 4) * 4;\n    const height = Math.ceil(numRows / width / 4) * 4;\n    const channels = 4;\n\n    // Texture texels follow the provided or generated index order.\n    const layout = identity;\n\n    const writeWebp = async (filename: string, data: Uint8Array, w = width, h = height) => {\n        const pathname = zipFs ? filename : resolve(dirname(outputFilename), filename);\n\n        // construct the encoder on first use\n        if (!webPCodec) {\n            webPCodec = await WebPCodec.create();\n        }\n\n        const webp = await webPCodec.encodeLosslessRGBA(data, w, h);\n\n        await writeFile(outputFs, pathname, webp);\n\n        // For bundled output the per-file sizes are an internal detail; we\n        // report a single bundle size after the archive closes.\n        if (emitInfo && !zipFs) {\n            logWrittenFile(filename, webp.byteLength);\n        }\n    };\n\n    const writeTableData = (filename: string, dataTable: DataTable, w = width, h = height) => {\n        const data = new Uint8Array(w * h * channels);\n        const columns = dataTable.columns.map(c => c.data);\n        const numColumns = columns.length;\n\n        for (let i = 0; i < indices.length; ++i) {\n            const idx = indices[i];\n            const ti = layout(i);\n            data[ti * channels + 0] = columns[0][idx];\n            data[ti * channels + 1] = numColumns > 1 ? columns[1][idx] : 0;\n            data[ti * channels + 2] = numColumns > 2 ? columns[2][idx] : 0;\n            data[ti * channels + 3] = numColumns > 3 ? columns[3][idx] : 255;\n        }\n\n        return writeWebp(filename, data, w, h);\n    };\n\n    const row: any = {};\n\n    const writeMeans = async () => {\n        const meansL = new Uint8Array(width * height * channels);\n        const meansU = new Uint8Array(width * height * channels);\n        const meansNames = ['x', 'y', 'z'];\n        const meansMinMax = calcMinMax(dataTable, meansNames, indices).map(v => v.map(logTransform));\n        const meansColumns = meansNames.map(name => dataTable.getColumnByName(name));\n        for (let i = 0; i < indices.length; ++i) {\n            dataTable.getRow(indices[i], row, meansColumns);\n\n            const x = 65535 * (logTransform(row.x) - meansMinMax[0][0]) / (meansMinMax[0][1] - meansMinMax[0][0]);\n            const y = 65535 * (logTransform(row.y) - meansMinMax[1][0]) / (meansMinMax[1][1] - meansMinMax[1][0]);\n            const z = 65535 * (logTransform(row.z) - meansMinMax[2][0]) / (meansMinMax[2][1] - meansMinMax[2][0]);\n\n            const ti = layout(i);\n\n            meansL[ti * 4] = x & 0xff;\n            meansL[ti * 4 + 1] = y & 0xff;\n            meansL[ti * 4 + 2] = z & 0xff;\n            meansL[ti * 4 + 3] = 0xff;\n\n            meansU[ti * 4] = (x >> 8) & 0xff;\n            meansU[ti * 4 + 1] = (y >> 8) & 0xff;\n            meansU[ti * 4 + 2] = (z >> 8) & 0xff;\n            meansU[ti * 4 + 3] = 0xff;\n        }\n        await writeWebp('means_l.webp', meansL);\n        await writeWebp('means_u.webp', meansU);\n\n        return {\n            mins: meansMinMax.map(v => v[0]),\n            maxs: meansMinMax.map(v => v[1])\n        };\n    };\n\n    const writeQuaternions = async () => {\n        const quats = new Uint8Array(width * height * channels);\n        const quatNames = ['rot_0', 'rot_1', 'rot_2', 'rot_3'];\n        const quatColumns = quatNames.map(name => dataTable.getColumnByName(name));\n        const q = [0, 0, 0, 0];\n        for (let i = 0; i < indices.length; ++i) {\n            dataTable.getRow(indices[i], row, quatColumns);\n\n            q[0] = row.rot_0;\n            q[1] = row.rot_1;\n            q[2] = row.rot_2;\n            q[3] = row.rot_3;\n\n            const l = Math.sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);\n\n            // normalize\n            q.forEach((v, j) => {\n                q[j] = v / l;\n            });\n\n            // find max component\n            const maxComp = q.reduce((v, _, i) => (Math.abs(q[i]) > Math.abs(q[v]) ? i : v), 0);\n\n            // invert if max component is negative\n            if (q[maxComp] < 0) {\n                q.forEach((_v, j) => {\n                    q[j] *= -1;\n                });\n            }\n\n            // scale by sqrt(2) to fit in [-1, 1] range\n            const sqrt2 = Math.sqrt(2);\n            q.forEach((_v, j) => {\n                q[j] *= sqrt2;\n            });\n\n            const idx = [\n                [1, 2, 3],\n                [0, 2, 3],\n                [0, 1, 3],\n                [0, 1, 2]\n            ][maxComp];\n\n            const ti = layout(i);\n\n            quats[ti * 4]     = 255 * (q[idx[0]] * 0.5 + 0.5);\n            quats[ti * 4 + 1] = 255 * (q[idx[1]] * 0.5 + 0.5);\n            quats[ti * 4 + 2] = 255 * (q[idx[2]] * 0.5 + 0.5);\n            quats[ti * 4 + 3] = 252 + maxComp;\n        }\n        await writeWebp('quats.webp', quats);\n    };\n\n    const writeScales = async () => {\n        const scaleData = quantize1d(\n            new DataTable(['scale_0', 'scale_1', 'scale_2'].map(name => dataTable.getColumnByName(name)))\n        );\n\n        await writeTableData('scales.webp', scaleData.labels);\n\n        return Array.from(scaleData.centroids.getColumn(0).data);\n    };\n\n    const writeColors = async () => {\n        const colorData = quantize1d(\n            new DataTable(['f_dc_0', 'f_dc_1', 'f_dc_2'].map(name => dataTable.getColumnByName(name)))\n        );\n\n        // generate and store sigmoid(opacity) [0..1]\n        const opacity = dataTable.getColumnByName('opacity').data;\n        const opacityData = new Uint8Array(opacity.length);\n        for (let i = 0; i < numRows; ++i) {\n            opacityData[i] = Math.max(0, Math.min(255, sigmoid(opacity[i]) * 255));\n        }\n        colorData.labels.addColumn(new Column('opacity', opacityData));\n\n        await writeTableData('sh0.webp', colorData.labels);\n\n        return Array.from(colorData.centroids.getColumn(0).data);\n    };\n\n    const writeSH = async (shBands: number) => {\n        const shCoeffs = [0, 3, 8, 15][shBands];\n        const shColumnNames = shRestNames.slice(0, shCoeffs * 3);\n        const shColumns = shColumnNames.map(name => dataTable.getColumnByName(name));\n\n        // create a table with just spherical harmonics data\n        // NOTE: this step should also copy the rows referenced in indices, but that's a\n        // lot of duplicate data when it's unneeded (which is currently never). so that\n        // means k-means is clustering the full dataset, instead of the rows referenced in\n        // indices.\n        const shDataTable = new DataTable(shColumns);\n\n        const paletteSize = Math.min(64, 2 ** Math.floor(Math.log2(indices.length / 1024))) * 1024;\n\n        // Create GPU device lazily — only needed for SH k-means clustering\n        const gpuDevice = createDevice ? await createDevice() : undefined;\n\n        const { centroids, labels } = await kmeans(shDataTable, paletteSize, iterations, gpuDevice);\n\n        const codebook = quantize1d(centroids);\n\n        // write centroids\n        const centroidsBuf = new Uint8Array(64 * shCoeffs * Math.ceil(centroids.numRows / 64) * channels);\n        const centroidsRow: any = {};\n        for (let i = 0; i < centroids.numRows; ++i) {\n            codebook.labels.getRow(i, centroidsRow);\n\n            for (let j = 0; j < shCoeffs; ++j) {\n                const x = centroidsRow[shColumnNames[shCoeffs * 0 + j]];\n                const y = centroidsRow[shColumnNames[shCoeffs * 1 + j]];\n                const z = centroidsRow[shColumnNames[shCoeffs * 2 + j]];\n\n                centroidsBuf[i * shCoeffs * 4 + j * 4 + 0] = x;\n                centroidsBuf[i * shCoeffs * 4 + j * 4 + 1] = y;\n                centroidsBuf[i * shCoeffs * 4 + j * 4 + 2] = z;\n                centroidsBuf[i * shCoeffs * 4 + j * 4 + 3] = 0xff;\n            }\n        }\n        await writeWebp('shN_centroids.webp', centroidsBuf, 64 * shCoeffs, Math.ceil(centroids.numRows / 64));\n\n        // write labels\n        const labelsBuf = new Uint8Array(width * height * channels);\n        for (let i = 0; i < indices.length; ++i) {\n            const label = labels[indices[i]];\n            const ti = layout(i);\n\n            labelsBuf[ti * 4 + 0] = 0xff & label;\n            labelsBuf[ti * 4 + 1] = 0xff & (label >> 8);\n            labelsBuf[ti * 4 + 2] = 0;\n            labelsBuf[ti * 4 + 3] = 0xff;\n        }\n        await writeWebp('shN_labels.webp', labelsBuf);\n\n        return {\n            count: paletteSize,\n            bands: shBands,\n            codebook: Array.from(codebook.centroids.getColumn(0).data),\n            files: [\n                'shN_centroids.webp',\n                'shN_labels.webp'\n            ]\n        };\n    };\n\n    const shBands = getSHBands(dataTable);\n\n    const writingGroup = openGroup ? logger.group('Writing') : null;\n\n    try {\n        const meansMinMax = await writeMeans();\n        await writeQuaternions();\n        const scalesCodebook = await writeScales();\n        const colorsCodebook = await writeColors();\n\n        let shN = null;\n        if (shBands > 0) {\n            shN = await writeSH(shBands);\n        }\n\n        // construct meta.json\n        const meta: any = {\n            version: 2,\n            asset: {\n                generator: `splat-transform v${version}`\n            },\n            count: numRows,\n            means: {\n                mins: meansMinMax.mins,\n                maxs: meansMinMax.maxs,\n                files: [\n                    'means_l.webp',\n                    'means_u.webp'\n                ]\n            },\n            scales: {\n                codebook: scalesCodebook,\n                files: ['scales.webp']\n            },\n            quats: {\n                files: ['quats.webp']\n            },\n            sh0: {\n                codebook: colorsCodebook,\n                files: ['sh0.webp']\n            },\n            ...(shN ? { shN } : {})\n        };\n\n        const metaJson = (new TextEncoder()).encode(JSON.stringify(meta));\n\n        const metaFilename = zipFs ? 'meta.json' : outputFilename;\n\n        await writeFile(outputFs, metaFilename, metaJson);\n\n        if (emitInfo && !zipFs) {\n            logWrittenFile(basename(outputFilename), metaJson.byteLength);\n        }\n\n        // Close zip archive if bundling\n        if (zipFs) {\n            await zipFs.close();\n        }\n\n        if (emitInfo && bundleWriter) {\n            logWrittenFile(basename(outputFilename), bundleWriter.bytesWritten);\n        }\n\n        writingGroup?.end();\n    } catch (err) {\n        // Best-effort close of the underlying bundle writer to avoid a file\n        // handle leak / partially-written zip on failure. Leave `writingGroup`\n        // open so the caller's `logger.error()` -> `unwindAll(true)` marks it\n        // as failed.\n        if (bundleWriter) {\n            try {\n                await bundleWriter.close();\n            } catch {\n                // already failing — swallow secondary close errors\n            }\n        }\n        throw err;\n    }\n};\n\nexport { writeSog };\n","import { html, css, js } from '@playcanvas/supersplat-viewer';\nimport { basename, dirname, join } from 'pathe';\n\nimport { logWrittenFile } from './utils';\nimport { writeSog } from './write-sog';\nimport { DataTable } from '../data-table';\nimport { type FileSystem, MemoryFileSystem, writeFile } from '../io/write';\nimport type { DeviceCreator } from '../types';\nimport { logger, toBase64 } from '../utils';\n\nconst defaultSettings = {\n    version: 2,\n    tonemapping: 'none',\n    highPrecisionRendering: false,\n    background: { color: [0.4, 0.4, 0.4] },\n    postEffectSettings: {\n        sharpness: { enabled: false, amount: 0 },\n        bloom: { enabled: false, intensity: 1, blurLevel: 2 },\n        grading: { enabled: false, brightness: 0, contrast: 1, saturation: 1, tint: [1, 1, 1] },\n        vignette: { enabled: false, intensity: 0.5, inner: 0.3, outer: 0.75, curvature: 1 },\n        fringing: { enabled: false, intensity: 0.5 }\n    },\n    animTracks: [] as any[],\n    cameras: [{\n        initial: {\n            position: [2, 2, -2],\n            target: [0, 0, 0],\n            fov: 75\n        }\n    }],\n    annotations: [] as any[],\n    startMode: 'default'\n};\n\ntype WriteHtmlOptions = {\n    filename: string;\n    dataTable: DataTable;\n    viewerSettingsJson?: any;\n    bundle: boolean;\n    iterations: number;\n    createDevice?: DeviceCreator;\n};\n\n/**\n * Writes Gaussian splat data as a self-contained HTML viewer.\n *\n * Creates an interactive 3D viewer that can be opened directly in a browser.\n * Uses the PlayCanvas SuperSplat viewer for rendering.\n *\n * @param options - Options including filename, data, and viewer settings.\n * @param fs - File system for writing output files.\n * @ignore\n */\nconst writeHtml = async (options: WriteHtmlOptions, fs: FileSystem) => {\n    const { filename, dataTable, viewerSettingsJson, bundle, iterations, createDevice } = options;\n\n    const pad = (text: string, spaces: number) => {\n        const whitespace = ' '.repeat(spaces);\n        return text.split('\\n').map(line => whitespace + line).join('\\n');\n    };\n\n    const viewerSettings = viewerSettingsJson || defaultSettings;\n    const encoder = new TextEncoder();\n\n    if (bundle) {\n        // Bundled mode: embed everything in the HTML\n        const memoryFs = new MemoryFileSystem();\n\n        const sogFilename = 'temp.sog';\n        await writeSog({\n            filename: sogFilename,\n            dataTable,\n            bundle: true,\n            iterations,\n            createDevice,\n            logging: 'silent'\n        }, memoryFs);\n\n        // get the memory buffer\n        const sogData = toBase64(memoryFs.results.get(sogFilename));\n\n        const style = '<link rel=\"stylesheet\" href=\"./index.css\">';\n        const script = 'import { main } from \\'./index.js\\';';\n        const settings = 'settings: fetch(settingsUrl).then(response => response.json())';\n        const content = 'fetch(contentUrl)';\n\n        const resultHtml = html\n        .replace(style, `<style>\\n${pad(css, 12)}\\n        </style>`)\n        .replace(script, js)\n        .replace(settings, `settings: ${JSON.stringify(viewerSettings)}`)\n        .replace(content, `fetch(\"data:application/octet-stream;base64,${sogData}\")`)\n        .replace('.compressed.ply', '.sog');\n\n        const htmlBytes = encoder.encode(resultHtml);\n\n        const writingGroup = logger.group('Writing');\n        await writeFile(fs, filename, htmlBytes);\n        logWrittenFile(basename(filename), htmlBytes.byteLength);\n        writingGroup.end();\n    } else {\n        // Unbundled mode: write separate files\n        const outputDir = dirname(filename);\n        const baseFilename = basename(filename, '.html');\n        const sogFilename = `${baseFilename}.sog`;\n        const sogPath = join(outputDir, sogFilename);\n\n        const writingGroup = logger.group('Writing');\n\n        // Write .sog file (its files are emitted flat into our Writing group)\n        await writeSog({\n            filename: sogPath,\n            dataTable,\n            bundle: true,\n            iterations,\n            createDevice,\n            logging: 'flat'\n        }, fs);\n\n        // Write CSS file\n        const cssPath = join(outputDir, 'index.css');\n        const cssBytes = encoder.encode(css);\n        await writeFile(fs, cssPath, cssBytes);\n        logWrittenFile(basename(cssPath), cssBytes.byteLength);\n\n        // Write JS file\n        const jsPath = join(outputDir, 'index.js');\n        const jsBytes = encoder.encode(js);\n        await writeFile(fs, jsPath, jsBytes);\n        logWrittenFile(basename(jsPath), jsBytes.byteLength);\n\n        // Write settings file\n        const settingsPath = join(outputDir, 'settings.json');\n        const settingsBytes = encoder.encode(JSON.stringify(viewerSettings, null, 4));\n        await writeFile(fs, settingsPath, settingsBytes);\n        logWrittenFile(basename(settingsPath), settingsBytes.byteLength);\n\n        // Generate HTML with external references\n        const content = 'fetch(contentUrl)';\n\n        const resultHtml = html\n        .replace(content, `fetch(\"${sogFilename}\")`)\n        .replace('.compressed.ply', '.sog');\n\n        const htmlBytes = encoder.encode(resultHtml);\n        await writeFile(fs, filename, htmlBytes);\n        logWrittenFile(basename(filename), htmlBytes.byteLength);\n\n        writingGroup.end();\n    }\n};\n\nexport { writeHtml };\n","import { Vec3 } from 'playcanvas';\n\n/**\n * Camera projection mode for headless splat rendering.\n *\n * - `pinhole` — standard perspective projection with `fovY` as the\n *   vertical field of view. Splats are culled by camera-space `cz <= near`.\n * - `equirect` — full 360° × 180° equirectangular panorama from the\n *   camera position. `fovY` is unused (the projection covers the entire\n *   sphere); `width` must equal `2 × height` (standard 2:1 panorama\n *   aspect). Splats are culled by radial distance `r <= near`.\n *\n * For both modes the `right`/`down`/`forward` basis derived from\n * `position`, `target`, and `up` defines the orientation. In equirect\n * mode, image-x = 0 maps to azimuth -π (behind the camera, left edge)\n * and image-x = width/2 maps to the forward direction; image-y = 0 is\n * the zenith and image-y = height is the nadir.\n */\ntype Projection = 'pinhole' | 'equirect';\n\n/**\n * Parameters describing a camera for headless splat rendering.\n *\n * Convention: PlayCanvas right-handed, Y-up world. Camera-space axes are\n * `right` (image x increases), `down` (image y increases), `forward`\n * (positive depth in front of the camera). The basis is built from a\n * `target - eye` direction plus a world-up vector and assumes the camera\n * looks roughly opposite the world up's perpendicular plane in a\n * PlayCanvas-style scene (so e.g. camera at +Z looking at the origin\n * places world `+X` on the right of the image).\n */\ntype RenderCamera = {\n    /**\n     * Projection mode. Defaults to `'pinhole'` if omitted — back-compatible\n     * with callers (JS, or TS compiled against the pre-equirect type) that\n     * don't know the field exists.\n     */\n    projection?: Projection;\n    /** Camera position in world space. */\n    position: Vec3;\n    /** Point the camera looks at, in world space. */\n    target: Vec3;\n    /** World-space up vector (used to define camera roll). */\n    up: Vec3;\n    /** Vertical field of view in radians. Used only for `pinhole` projection. */\n    fovY: number;\n    /** Output image width in pixels. Equirect requires `width === 2 × height`. */\n    width: number;\n    /** Output image height in pixels. */\n    height: number;\n    /** Near clipping distance in world units. For pinhole, splats with `cz <= near` are culled; for equirect, splats with radial `r <= near`. */\n    near: number;\n    /**\n     * Camera-space Z of the focus plane in world units. Pinhole only;\n     * ignored for equirect. Optional — only meaningful when\n     * `apertureScale > 0`.\n     */\n    focusDistance?: number;\n    /**\n     * DoF strength as a pixel-space scalar: the CoC radius in pixels\n     * when `|1 − focusDistance/cz| = 1`. Pinhole only; ignored for\n     * equirect. Default `0` disables defocus.\n     */\n    apertureScale?: number;\n};\n\n/**\n * Derived camera basis and intrinsics in the conventions described on\n * RenderCamera. The 3x3 view rotation rows are (right, down, forward); the\n * translation is -R * eye. Focal lengths are in pixel units.\n */\ntype CameraBasis = {\n    /** Eye position (copy of camera.position). */\n    eye: Vec3;\n    /** Camera-space +X axis in world coords (rightward in image). */\n    right: Vec3;\n    /** Camera-space +Y axis in world coords (downward in image). */\n    down: Vec3;\n    /** Camera-space +Z axis in world coords (into the scene). */\n    forward: Vec3;\n    /** Horizontal focal length in pixels. */\n    focalX: number;\n    /** Vertical focal length in pixels. */\n    focalY: number;\n};\n\nconst sub = (a: Vec3, b: Vec3) => new Vec3(a.x - b.x, a.y - b.y, a.z - b.z);\nconst cross = (a: Vec3, b: Vec3) => new Vec3(\n    a.y * b.z - a.z * b.y,\n    a.z * b.x - a.x * b.z,\n    a.x * b.y - a.y * b.x\n);\nconst normalize = (v: Vec3): Vec3 => {\n    const len = Math.hypot(v.x, v.y, v.z);\n    if (len === 0) return new Vec3(0, 0, 0);\n    return new Vec3(v.x / len, v.y / len, v.z / len);\n};\n\nconst buildCameraBasis = (camera: RenderCamera): CameraBasis => {\n    const forward = normalize(sub(camera.target, camera.position));\n    if (forward.x === 0 && forward.y === 0 && forward.z === 0) {\n        throw new Error('Camera target equals camera position');\n    }\n\n    // right = forward × up_world (image x increases to the right).\n    // For a PlayCanvas-style camera at +Z looking toward the origin (forward\n    // pointing in world -Z), this yields right = world +X, so world +X\n    // appears on the right side of the image. The opposite ordering would\n    // be correct for a CV-style camera looking down +Z; we choose this one\n    // because the renderer always consumes PlayCanvas-identity-space data.\n    let right = cross(forward, camera.up);\n    if (right.x === 0 && right.y === 0 && right.z === 0) {\n        throw new Error('Camera up vector is parallel to view direction');\n    }\n    right = normalize(right);\n\n    // down = forward × right (image y increases downward)\n    const down = cross(forward, right);\n\n    // Pinhole focal lengths (pixels). Equirect ignores these — the\n    // equirect shader path derives its scale from imageWidth/Height\n    // directly — so we leave them at zero rather than evaluating\n    // `tan(fovY/2)`, which is meaningless when the caller has no FOV\n    // to provide.\n    let focalX = 0;\n    let focalY = 0;\n    // Default to pinhole when projection is omitted — keeps existing JS\n    // callers (no TS type-checking against the new field) working.\n    if ((camera.projection ?? 'pinhole') === 'pinhole') {\n        const halfTanY = Math.tan(camera.fovY * 0.5);\n        focalY = (camera.height * 0.5) / halfTanY;\n        focalX = focalY;\n    }\n\n    return {\n        eye: new Vec3(camera.position.x, camera.position.y, camera.position.z),\n        right,\n        down,\n        forward,\n        focalX,\n        focalY\n    };\n};\n\nexport { type Projection, type RenderCamera, type CameraBasis, buildCameraBasis };\n","import { DataTable, getSHBands } from '../data-table';\nimport { type CameraBasis, type Projection } from './camera';\nimport { RadixSortScratch, radixSortIndicesByFloat } from '../spatial/radix-sort';\n\n/**\n * Number of SH coefficients per color channel for the scene's SH band\n * count. Matches the `f_rest_*` layout in DataTable (channel-major).\n *\n * @param bands - 0–3.\n * @returns Coefficient count per channel.\n */\nconst numSHCoeffsPerChannel = (bands: number): number => {\n    return bands === 0 ? 0 : bands === 1 ? 3 : bands === 2 ? 8 : 15;\n};\n\n/**\n * Floats per gaussian in the chunk input buffer that gets uploaded to the\n * GPU project shader. Layout:\n *   [0..2]   pos.xyz\n *   [3..6]   rot.w, rot.x, rot.y, rot.z  (rot_0..rot_3)\n *   [7..9]   log_scale.xyz\n *   [10]     opacity (logit)\n *   [11..13] f_dc.rgb\n *   [14..14+3·N-1]  SH coefficients, channel-major: R[0..N-1], G[0..N-1], B[0..N-1]\n *\n * @param numSHBands - 0–3.\n * @returns Per-gaussian stride in 32-bit floats.\n */\nconst splatInputStride = (numSHBands: number): number => {\n    return 14 + 3 * numSHCoeffsPerChannel(numSHBands);\n};\n\n/**\n * Reusable scratch for `sortCandidatesByDepth`. Bundles the parallel-keys\n * Float32 depth buffer with the shared `RadixSortScratch`. One instance is\n * created per render in the orchestrator and reused across every group's\n * sort to avoid allocating multi-MB typed arrays on every call. Buffers\n * grow on demand and never shrink.\n */\nclass SortScratch {\n    /** Float32 depths in candidate order; parallel to the indices being sorted. */\n    depth: Float32Array;\n    /** Shared radix-sort working buffers. */\n    radix: RadixSortScratch;\n\n    constructor() {\n        this.depth = new Float32Array(0);\n        this.radix = new RadixSortScratch();\n    }\n\n    ensure(count: number): void {\n        if (count > this.depth.length) {\n            this.depth = new Float32Array(count);\n        }\n        this.radix.ensure(count);\n    }\n}\n\n/**\n * Sort `candidateIndices[0..count)` by view depth ascending\n * (front-to-back) so chunked dispatches process splats in correct blend\n * order. Mutates `candidateIndices` in place.\n *\n * Depth metric depends on the projection. Pinhole uses\n * `forward · (pos − eye)` (camera-space z). Equirect uses radial\n * distance `‖pos − eye‖` — the natural front-to-back ordering for a\n * spherical projection, since \"in front of\" is defined per direction\n * rather than per camera-z plane. Delegates the actual sort to the\n * shared `radixSortIndicesByFloat`, providing depths as the parallel\n * Float32 keys.\n *\n * @param cols - Pre-resolved column references (only `x`, `y`, `z` are read).\n * @param candidateIndices - Indices into dataTable rows (mutated).\n * @param count - Number of valid entries.\n * @param camera - Camera basis (forward used for pinhole, eye for both).\n * @param projection - Projection mode; selects the depth metric.\n * @param scratch - Reusable scratch buffers, grown on demand.\n */\nconst sortCandidatesByDepth = (\n    cols: SplatColumnRefs,\n    candidateIndices: Uint32Array,\n    count: number,\n    camera: CameraBasis,\n    projection: Projection,\n    scratch: SortScratch\n): void => {\n    if (count < 2) return;\n    scratch.ensure(count);\n    const { x, y, z } = cols;\n    const { depth, radix } = scratch;\n    const ex = camera.eye.x, ey = camera.eye.y, ez = camera.eye.z;\n\n    if (projection === 'pinhole') {\n        const fx = camera.forward.x, fy = camera.forward.y, fz = camera.forward.z;\n        for (let i = 0; i < count; i++) {\n            const s = candidateIndices[i];\n            depth[i] = fx * (x[s] - ex) + fy * (y[s] - ey) + fz * (z[s] - ez);\n        }\n    } else {\n        // Equirect: radial squared distance from the camera. r² is\n        // monotonic in r (all non-negative), so sorting on r² gives the\n        // same front-to-back order as sorting on r — saves the sqrt.\n        for (let i = 0; i < count; i++) {\n            const s = candidateIndices[i];\n            const dx = x[s] - ex;\n            const dy = y[s] - ey;\n            const dz = z[s] - ez;\n            depth[i] = dx * dx + dy * dy + dz * dz;\n        }\n    }\n\n    radixSortIndicesByFloat(candidateIndices, depth, count, radix);\n};\n\n/**\n * Cached typed-array references for the columns that `packChunkInput`\n * reads. Built once per render in the orchestrator and reused across\n * every group/chunk to avoid `getColumnByName` lookups and the SH-rest\n * array allocation on the hot path.\n */\ntype SplatColumnRefs = {\n    x: Float32Array;\n    y: Float32Array;\n    z: Float32Array;\n    rotW: Float32Array;\n    rotX: Float32Array;\n    rotY: Float32Array;\n    rotZ: Float32Array;\n    scaleX: Float32Array;\n    scaleY: Float32Array;\n    scaleZ: Float32Array;\n    opacity: Float32Array;\n    fdcR: Float32Array;\n    fdcG: Float32Array;\n    fdcB: Float32Array;\n    /** Channel-major SH coefficients: indices `[0..N-1]` red, then green, then blue. Empty when `numSHBands === 0`. */\n    shRest: Float32Array[];\n};\n\n/**\n * Resolve the typed-array references for every column `packChunkInput`\n * touches. Call once per render; reuse the result across all chunks.\n *\n * @param dataTable - Source splat data.\n * @param numSHBands - Scene's SH band count (0–3).\n * @returns Cached column references.\n */\nconst getSplatColumnRefs = (dataTable: DataTable, numSHBands: number): SplatColumnRefs => {\n    const coeffsPerChannel = numSHCoeffsPerChannel(numSHBands);\n    const shRest: Float32Array[] = new Array(coeffsPerChannel * 3);\n    for (let i = 0; i < coeffsPerChannel * 3; i++) {\n        shRest[i] = dataTable.getColumnByName(`f_rest_${i}`)!.data as Float32Array;\n    }\n    return {\n        x: dataTable.getColumnByName('x')!.data as Float32Array,\n        y: dataTable.getColumnByName('y')!.data as Float32Array,\n        z: dataTable.getColumnByName('z')!.data as Float32Array,\n        rotW: dataTable.getColumnByName('rot_0')!.data as Float32Array,\n        rotX: dataTable.getColumnByName('rot_1')!.data as Float32Array,\n        rotY: dataTable.getColumnByName('rot_2')!.data as Float32Array,\n        rotZ: dataTable.getColumnByName('rot_3')!.data as Float32Array,\n        scaleX: dataTable.getColumnByName('scale_0')!.data as Float32Array,\n        scaleY: dataTable.getColumnByName('scale_1')!.data as Float32Array,\n        scaleZ: dataTable.getColumnByName('scale_2')!.data as Float32Array,\n        opacity: dataTable.getColumnByName('opacity')!.data as Float32Array,\n        fdcR: dataTable.getColumnByName('f_dc_0')!.data as Float32Array,\n        fdcG: dataTable.getColumnByName('f_dc_1')!.data as Float32Array,\n        fdcB: dataTable.getColumnByName('f_dc_2')!.data as Float32Array,\n        shRest\n    };\n};\n\n/**\n * Pack a chunk's raw splat fields into a flat Float32Array suitable for\n * upload to the GPU project shader. The layout matches `splatInputStride`.\n *\n * @param cols - Pre-resolved column references (build once via `getSplatColumnRefs`).\n * @param chunkIndices - Indices into dataTable for this chunk's splats.\n * @param chunkStart - Offset into `chunkIndices` where the chunk begins.\n * @param chunkSize - Number of splats in this chunk.\n * @param numSHBands - Scene's SH band count (0–3).\n * @param out - Output buffer, length ≥ `chunkSize · stride`.\n */\nconst packChunkInput = (\n    cols: SplatColumnRefs,\n    chunkIndices: Uint32Array,\n    chunkStart: number,\n    chunkSize: number,\n    numSHBands: number,\n    out: Float32Array\n): void => {\n    const stride = splatInputStride(numSHBands);\n    const numShFloats = numSHCoeffsPerChannel(numSHBands) * 3;\n    const {\n        x, y, z, rotW, rotX, rotY, rotZ,\n        scaleX, scaleY, scaleZ, opacity,\n        fdcR, fdcG, fdcB, shRest\n    } = cols;\n\n    for (let i = 0; i < chunkSize; i++) {\n        const s = chunkIndices[chunkStart + i];\n        const base = i * stride;\n        out[base + 0] = x[s];\n        out[base + 1] = y[s];\n        out[base + 2] = z[s];\n        out[base + 3] = rotW[s];\n        out[base + 4] = rotX[s];\n        out[base + 5] = rotY[s];\n        out[base + 6] = rotZ[s];\n        out[base + 7] = scaleX[s];\n        out[base + 8] = scaleY[s];\n        out[base + 9] = scaleZ[s];\n        out[base + 10] = opacity[s];\n        out[base + 11] = fdcR[s];\n        out[base + 12] = fdcG[s];\n        out[base + 13] = fdcB[s];\n        // SH coefficients in channel-major order: f_rest_0..coeffsPerChannel-1 = red, etc.\n        for (let k = 0; k < numShFloats; k++) {\n            out[base + 14 + k] = shRest[k][s];\n        }\n    }\n};\n\n/**\n * Convenience: derive the scene's SH band count from the DataTable's\n * `f_rest_*` columns. Used by the renderer to size the input stride.\n *\n * @param dataTable - Splat data.\n * @returns SH band count clamped to 0–3.\n */\nconst sceneSHBands = (dataTable: DataTable): 0 | 1 | 2 | 3 => {\n    return getSHBands(dataTable) as 0 | 1 | 2 | 3;\n};\n\nexport {\n    splatInputStride,\n    numSHCoeffsPerChannel,\n    sortCandidatesByDepth,\n    SortScratch,\n    getSplatColumnRefs,\n    packChunkInput,\n    sceneSHBands,\n    type SplatColumnRefs\n};\n","import { GraphicsDevice } from 'playcanvas';\n\nimport { type Projection, type RenderCamera, buildCameraBasis } from './camera';\nimport {\n    AA_DILATION_COV,\n    DISCRIMINANT_FLOOR,\n    JACOBIAN_LIMIT_FACTOR,\n    PAIR_BUFFER_BUDGET_BYTES,\n    PAIR_BUFFER_TOTAL_BYTES_PER_ELEMENT,\n    SIGMA_CUTOFF,\n    TILE_SIZE\n} from './config';\nimport {\n    SortScratch,\n    getSplatColumnRefs,\n    packChunkInput,\n    sceneSHBands,\n    sortCandidatesByDepth,\n    splatInputStride\n} from './preprocess';\nimport { DataTable } from '../data-table';\nimport { GpuSplatRasterizer } from '../gpu';\nimport { logger } from '../utils';\n\n/**\n * Max gaussians per GPU dispatch. Bounds per-render input/projection\n * buffer sizes and the granularity of the depth-ordered chunked path.\n *\n * Each chunk dispatches its own project + rasterize-accumulate.\n * Running state persists across chunks; saturated pixels (T < 1e-4)\n * short-circuit on subsequent chunks via the rasterize shader's T\n * early-out.\n */\nconst CHUNK_CAP = 200_000;\n\n/**\n * Maximum sub-frame dimensions, in tiles. Renders larger than this get\n * split into a grid of independent sub-frames stitched together at the\n * end. At 1080p (120×68 tiles) this is exactly one sub-frame; at 4K it\n * becomes 2×2; at 8K it becomes 4×4.\n *\n * Why split: per-splat tile coverage scales with image_height² (focal\n * length is proportional to image height for a fixed FOV). At 8K a\n * splat that projects to ~few tiles at 1080p projects to ~hundreds of\n * tiles, which would either need a huge pair buffer or produce hard\n * truncation edges when clamped. Sub-frame rendering keeps each\n * sub-frame's working set ≤ 1080p-sized, so the per-splat coverage\n * stays in the same regime as the (well-tested) 1080p path. The\n * project shader's group-AABB cull skips splats outside the current\n * sub-frame, and the global CPU depth sort is shared across sub-frames\n * (no seam artifacts at sub-frame boundaries).\n */\nconst MAX_SUB_FRAME_TILES_X = Math.ceil(1920 / TILE_SIZE);  // 120\nconst MAX_SUB_FRAME_TILES_Y = Math.ceil(1080 / TILE_SIZE);  // 68\n\ninterface BackgroundRGBA {\n    r: number;\n    g: number;\n    b: number;\n    a: number;\n}\n\n/**\n * Render a splat scene to an RGBA byte buffer.\n *\n * Whole-image pipeline:\n *\n *   1. Linear frustum cull — one pass over all splats, testing each\n *      centre against the camera frustum in camera-space. No BVH or\n *      per-splat AABB precomputation.\n *   2. Sort visible splats globally by camera-space z (front-to-back).\n *   3. Split image into a grid of sub-frames (each ≤ MAX_SUB_FRAME_TILES\n *      in either dimension) and render each independently. The rasterizer\n *      retains its per-sub-frame running state; the project shader's\n *      group-AABB cull skips splats outside the current sub-frame. The\n *      CPU depth sort is global, so depth ordering is consistent across\n *      sub-frames and there are no boundary seams.\n *\n * Per-chunk (GPU tile-bin pipeline, fully GPU-resident): project (writes\n * per-splat tile coverage) → prefix-sum (writes emitOffsets + totalPairs)\n * → emit-pairs → prepare-indirect → radix sortIndirect (key + value:\n * tile keys sorted, splat indices reordered) → init-tile-offsets →\n * find-boundaries (atomicMin) → rasterize each tile's slice in depth\n * order. No per-chunk CPU readbacks.\n *\n * @param device - PlayCanvas WebGPU graphics device.\n * @param dataTable - Gaussian splat data in PlayCanvas-identity space.\n * @param camera - Camera parameters.\n * @param background - RGBA background composited under residual transmittance.\n * @returns RGBA byte array of length `camera.width × camera.height × 4`.\n */\nconst renderRasterPass = async (\n    device: GraphicsDevice,\n    dataTable: DataTable,\n    camera: RenderCamera,\n    background: BackgroundRGBA\n): Promise<Uint8Array> => {\n    if (!Number.isInteger(camera.width) || !Number.isInteger(camera.height) ||\n        camera.width <= 0 || camera.height <= 0) {\n        throw new Error(`Invalid resolution: ${camera.width}x${camera.height}`);\n    }\n\n    const width = camera.width;\n    const height = camera.height;\n    // Default to pinhole when projection is omitted — matches the\n    // back-compat treatment in buildCameraBasis. All downstream branches\n    // (CPU cull/sort, sub-frame split, GPU rasterizer) read this local.\n    const projection: Projection = camera.projection ?? 'pinhole';\n    const basis = buildCameraBasis(camera);\n\n    // ---- Frustum cull ----\n    // Linear, centre-only near-plane test. Pinhole tests cz > near (the\n    // GPU project shader's exact near-plane condition). Equirect has no\n    // forward direction in the cull sense — instead we cull a sphere of\n    // radius `near` around the camera, matching the GPU project shader's\n    // `r > near` test. In both modes we deliberately don't test the side\n    // cones on the CPU. A proper AABB-vs-cone test needs `exp(max(s))`\n    // per splat — on an 18 M scene that's ~275 ms of extra CPU work,\n    // and at typical reference-render FOVs (60–90°) the cone contains\n    // nearly every front-of-camera splat anyway (measured 95.8 %\n    // retention on windmill at 90°). The splats that the cone test\n    // *would* drop are caught by the GPU project shader's 2D image-rect\n    // test, which uses the actual screen-space radius — strictly\n    // tighter than the L∞-bound CPU test. For equirect the cone test\n    // doesn't apply at all: every direction is in-view.\n    const cullGroup = logger.group('Cull');\n    const xCol = dataTable.getColumnByName('x')!.data as Float32Array;\n    const yCol = dataTable.getColumnByName('y')!.data as Float32Array;\n    const zCol = dataTable.getColumnByName('z')!.data as Float32Array;\n    const numRows = dataTable.numRows;\n\n    const ex = basis.eye.x, ey = basis.eye.y, ez = basis.eye.z;\n    const fx = basis.forward.x, fy = basis.forward.y, fz = basis.forward.z;\n    const near = camera.near;\n\n    // Worst-case visible-count allocation. Right-sized at the end via subarray.\n    const candidates = new Uint32Array(numRows);\n    let candidateCount = 0;\n    if (projection === 'pinhole') {\n        for (let i = 0; i < numRows; i++) {\n            const cz = fx * (xCol[i] - ex) + fy * (yCol[i] - ey) + fz * (zCol[i] - ez);\n            if (cz > near) candidates[candidateCount++] = i;\n        }\n    } else {\n        const nearSq = near * near;\n        for (let i = 0; i < numRows; i++) {\n            const dx = xCol[i] - ex;\n            const dy = yCol[i] - ey;\n            const dz = zCol[i] - ez;\n            if (dx * dx + dy * dy + dz * dz > nearSq) candidates[candidateCount++] = i;\n        }\n    }\n    cullGroup.end();\n\n    // ---- Image tile grid + sub-frame partition ----\n    // Pinhole renders larger than ~1080p are split into sub-frames so\n    // per-splat tile coverage stays bounded (see MAX_SUB_FRAME_TILES_*).\n    // Equirect runs as a single sub-frame regardless of resolution: the\n    // sub-frame X-cull below relies on a perspective Jacobian bound\n    // that doesn't apply to equirect, and the wrap-around tile coverage\n    // assumes the X tile range covers the full longitude. TODO: derive\n    // an equirect-specific sub-frame bound (Jacobian magnitude ≤\n    // max(W/(2π), H/π · 1/POLE_EPS)) for >4K equirect renders.\n    const imageTilesX = Math.ceil(width / TILE_SIZE);\n    const imageTilesY = Math.ceil(height / TILE_SIZE);\n    const subFrameTilesX = projection === 'equirect' ?\n        imageTilesX :\n        Math.min(imageTilesX, MAX_SUB_FRAME_TILES_X);\n    const subFrameTilesY = projection === 'equirect' ?\n        imageTilesY :\n        Math.min(imageTilesY, MAX_SUB_FRAME_TILES_Y);\n    const numSubFramesX = Math.ceil(imageTilesX / subFrameTilesX);\n    const numSubFramesY = Math.ceil(imageTilesY / subFrameTilesY);\n    const numSubFrames = numSubFramesX * numSubFramesY;\n\n    // ---- Global depth sort ----\n    const numSHBands = sceneSHBands(dataTable);\n    const inputStride = splatInputStride(numSHBands);\n    const cols = getSplatColumnRefs(dataTable, numSHBands);\n    const sortScratch = new SortScratch();\n    sortCandidatesByDepth(cols, candidates, candidateCount, basis, projection, sortScratch);\n\n    // ---- Per-sub-frame CPU cull ----\n    // For multi-sub-frame renders, partition the depth-sorted candidate\n    // list into per-sub-frame sub-lists so each sub-frame only packs/\n    // uploads/projects the splats whose conservative screen bbox\n    // overlaps it. Without this, every sub-frame pays the full upload\n    // + project cost for every candidate (the GPU AABB cull only\n    // discards them at the end of projection) — at 8K that's 16×\n    // duplicate work.\n    //\n    // Bound is constructed to be ≥ the GPU project shader's computed\n    // radius, so the cull is byte-exact: every splat the GPU would\n    // include sits inside its bound bbox, and a \"definitely outside\"\n    // verdict means the GPU AABB cull would also drop it.\n    //\n    // Derivation. The GPU computes radius = SIGMA_CUTOFF · sqrt(lambdaMax)\n    // where lambdaMax is the larger eigenvalue of the projected 2D\n    // covariance (C2D = J·C3D·Jᵀ + AA_DILATION_COV·I, with the\n    // DISCRIMINANT_FLOOR safety also bumping it). Matrix theory:\n    //   maxEig(J·C3D·Jᵀ) ≤ maxEig(J·Jᵀ) · maxEig(C3D)\n    // and for our perspective Jacobian J = focal/cz · [[1, 0, -tx],\n    // [0, 1, -ty]]:\n    //   maxEig(J·Jᵀ) = (focal/cz)² · (1 + tx² + ty²)\n    // with tx, ty clamped per JACOBIAN_LIMIT_FACTOR (same as the GPU\n    // project shader's clamp). maxEig(C3D) = max-axis-scale² for an\n    // anisotropic Gaussian. Adding AA_DILATION_COV and the\n    // DISCRIMINANT_FLOOR safety bump:\n    //   lambdaMax ≤ (focal/cz)² · (1+tx²+ty²) · maxScale²\n    //              + AA_DILATION_COV + sqrt(DISCRIMINANT_FLOOR)\n    // Per-splat order is preserved → per-sub-frame lists stay\n    // depth-sorted.\n    let subFrameLists: Uint32Array[];\n    if (numSubFrames === 1) {\n        subFrameLists = [candidates.subarray(0, candidateCount)];\n    } else {\n        const subFramePixelsX = subFrameTilesX * TILE_SIZE;\n        const subFramePixelsY = subFrameTilesY * TILE_SIZE;\n        const rx2 = basis.right.x, ry2 = basis.right.y, rz2 = basis.right.z;\n        const dx2 = basis.down.x, dy2 = basis.down.y, dz2 = basis.down.z;\n        const focalX = basis.focalX, focalY = basis.focalY;\n        const halfW = width * 0.5, halfH = height * 0.5;\n        const sxColRef = cols.scaleX, syColRef = cols.scaleY, szColRef = cols.scaleZ;\n        // Tan-of-half-FOV cap; matches the project shader's Jacobian clamp.\n        const limX = JACOBIAN_LIMIT_FACTOR * halfW / focalX;\n        const limY = JACOBIAN_LIMIT_FACTOR * halfH / focalY;\n        const limX2 = limX * limX;\n        const limY2 = limY * limY;\n        // Additive squared-radius safety: AA dilation + disc-floor bump.\n        const lambdaSafety = AA_DILATION_COV + Math.sqrt(DISCRIMINANT_FLOOR);\n        // Per-buffer base focal scale (max of focals so the bound is\n        // valid against either axis).\n        const focalMax = Math.max(focalX, focalY);\n\n        // Packed Uint16 buffer of (sx0, sx1, sy0, sy1) per candidate.\n        // sx0 = 0xFFFF sentinel marks \"off-screen, skip in pass 2\".\n        // Uint16 (not Uint8) so sub-frame counts per axis aren't capped\n        // at 254 by the storage width / sentinel collision.\n        const SF_OFFSCREEN = 0xFFFF;\n        const ranges = new Uint16Array(candidateCount * 4);\n        const subFrameCounts = new Uint32Array(numSubFrames);\n\n        // Pass 1: compute ranges, count per sub-frame.\n        for (let i = 0; i < candidateCount; i++) {\n            const idx = candidates[i];\n            const wx = xCol[idx] - ex;\n            const wy = yCol[idx] - ey;\n            const wz = zCol[idx] - ez;\n            const cz = fx * wx + fy * wy + fz * wz;\n            // Candidate has already passed the near-plane CPU cull; cz > near\n            // is therefore an invariant here, no need to retest.\n            const cx = rx2 * wx + ry2 * wy + rz2 * wz;\n            const cy = dx2 * wx + dy2 * wy + dz2 * wz;\n            const invZ = 1.0 / cz;\n            const screenX = focalX * cx * invZ + halfW;\n            const screenY = focalY * cy * invZ + halfH;\n            const maxScale = Math.max(\n                Math.exp(sxColRef[idx]),\n                Math.exp(syColRef[idx]),\n                Math.exp(szColRef[idx])\n            );\n            // Jacobian factor: (focal/cz)² · (1 + tx² + ty²) with\n            // tx = cx/cz, ty = cy/cz both clamped to ±lim. Matches the\n            // project shader's clamp so the bound is tight.\n            const tx = cx * invZ;\n            const ty = cy * invZ;\n            const txClamped = tx > limX ? limX : (tx < -limX ? -limX : tx);\n            const tyClamped = ty > limY ? limY : (ty < -limY ? -limY : ty);\n            const tx2 = Math.min(txClamped * txClamped, limX2);\n            const ty2 = Math.min(tyClamped * tyClamped, limY2);\n            const jFactorSq = 1 + tx2 + ty2;\n            const lambdaMaxBound = (focalMax * invZ) * (focalMax * invZ) * jFactorSq * maxScale * maxScale + lambdaSafety;\n            // +1 px ceil safety to match the GPU's `ceil(radius)`.\n            const screenR = Math.ceil(SIGMA_CUTOFF * Math.sqrt(lambdaMaxBound)) + 1;\n            const minX = screenX - screenR;\n            const maxX = screenX + screenR;\n            const minY = screenY - screenR;\n            const maxY = screenY + screenR;\n            if (maxX < 0 || minX >= width || maxY < 0 || minY >= height) {\n                ranges[i * 4] = SF_OFFSCREEN;\n                continue;\n            }\n            const sx0 = Math.max(0, Math.floor(minX / subFramePixelsX));\n            const sx1 = Math.min(numSubFramesX - 1, Math.floor(maxX / subFramePixelsX));\n            const sy0 = Math.max(0, Math.floor(minY / subFramePixelsY));\n            const sy1 = Math.min(numSubFramesY - 1, Math.floor(maxY / subFramePixelsY));\n            ranges[i * 4 + 0] = sx0;\n            ranges[i * 4 + 1] = sx1;\n            ranges[i * 4 + 2] = sy0;\n            ranges[i * 4 + 3] = sy1;\n            for (let sy = sy0; sy <= sy1; sy++) {\n                for (let sx = sx0; sx <= sx1; sx++) {\n                    subFrameCounts[sy * numSubFramesX + sx]++;\n                }\n            }\n        }\n\n        // Allocate exact-size lists and fill (pass 2).\n        subFrameLists = new Array(numSubFrames);\n        const insertIdx = new Uint32Array(numSubFrames);\n        for (let s = 0; s < numSubFrames; s++) {\n            subFrameLists[s] = new Uint32Array(subFrameCounts[s]);\n        }\n        for (let i = 0; i < candidateCount; i++) {\n            const sx0 = ranges[i * 4 + 0];\n            if (sx0 === SF_OFFSCREEN) continue;\n            const sx1 = ranges[i * 4 + 1];\n            const sy0 = ranges[i * 4 + 2];\n            const sy1 = ranges[i * 4 + 3];\n            const idx = candidates[i];\n            for (let sy = sy0; sy <= sy1; sy++) {\n                for (let sx = sx0; sx <= sx1; sx++) {\n                    const s = sy * numSubFramesX + sx;\n                    subFrameLists[s][insertIdx[s]++] = idx;\n                }\n            }\n        }\n    }\n\n    // ---- Rasterizer (one instance, reused across sub-frames) ----\n    // The rasterizer's buffers are sized to the MAX sub-frame\n    // dimensions, not the full image. Each sub-frame calls beginGroup\n    // with its actual dimensions (≤ max) and gets a clean running state.\n    //\n    // maxCoveragePerSplat = sub-frame tile area. Then every splat's\n    // bbox-in-sub-frame ≤ maxCoveragePerSplat (since coverage is\n    // geometrically bounded by the sub-frame's area), so the project\n    // shader's coverage clamp never bites and emit-pairs writes the\n    // entire bbox-in-sub-frame. No truncation → no hard tile edges, no\n    // boundary seams. The cost is pair-buffer memory and chunkCap.\n    const subFrameTiles = subFrameTilesX * subFrameTilesY;\n    const maxCoveragePerSplat = 1 << Math.ceil(Math.log2(Math.max(1, subFrameTiles)));\n\n    // chunkCap is bounded by two GPU constraints:\n    //  (a) each individual pair buffer (tileKeys, splatValues, and the\n    //      four radix-sort internal ping-pong buffers) must fit inside\n    //      a single storage-buffer binding — capped at\n    //      `maxStorageBufferBindingSize` (typically 128 MiB baseline,\n    //      ~1 GiB on Apple Silicon, larger on desktop discrete GPUs).\n    //  (b) the TOTAL of all six pair-sized buffers combined must stay\n    //      within `PAIR_BUFFER_BUDGET_BYTES` — bounds the rasterizer's\n    //      peak GPU footprint when chunkCap could otherwise saturate\n    //      the binding limit on adapters with very large bindings.\n    // @ts-ignore - limits is exposed by WebgpuGraphicsDevice\n    const wgpuLimits = (device as { limits?: { maxStorageBufferBindingSize?: number } }).limits;\n    const maxBindingBytes = wgpuLimits?.maxStorageBufferBindingSize ?? 128 * 1024 * 1024;\n    const bindingChunkCap = Math.floor(maxBindingBytes / (maxCoveragePerSplat * 4));\n    const budgetChunkCap = Math.floor(PAIR_BUFFER_BUDGET_BYTES / (maxCoveragePerSplat * PAIR_BUFFER_TOTAL_BYTES_PER_ELEMENT));\n    const effectiveChunkCap = Math.max(\n        1,\n        Math.min(CHUNK_CAP, budgetChunkCap, bindingChunkCap, candidateCount)\n    );\n\n    const rasterizer = new GpuSplatRasterizer(device, {\n        numSHBands,\n        projection,\n        groupTilesX: subFrameTilesX,\n        groupTilesY: subFrameTilesY,\n        chunkCap: effectiveChunkCap,\n        maxCoveragePerSplat,\n        imageWidth: width,\n        imageHeight: height,\n        near: camera.near,\n        rightX: basis.right.x,\n        rightY: basis.right.y,\n        rightZ: basis.right.z,\n        downX: basis.down.x,\n        downY: basis.down.y,\n        downZ: basis.down.z,\n        forwardX: basis.forward.x,\n        forwardY: basis.forward.y,\n        forwardZ: basis.forward.z,\n        eyeX: basis.eye.x,\n        eyeY: basis.eye.y,\n        eyeZ: basis.eye.z,\n        focalX: basis.focalX,\n        focalY: basis.focalY,\n        focusDistance: camera.focusDistance ?? 0,\n        apertureScale: camera.apertureScale ?? 0,\n        bgR: background.r,\n        bgG: background.g,\n        bgB: background.b,\n        bgA: background.a\n    });\n\n    // Per-chunk CPU scratch.\n    const chunkInput = new Float32Array(effectiveChunkCap * inputStride);\n\n    // Final image buffer (image-sized) that each sub-frame's output is\n    // copied into.\n    const finalImage = new Uint8Array(width * height * 4);\n\n    // Total chunks across all sub-frames (each sub-frame's list is its\n    // own filtered count). Used only for progress reporting; counts\n    // actual dispatched chunks, so empty sub-frames contribute 0.\n    let totalChunks = 0;\n    for (let s = 0; s < numSubFrames; s++) {\n        totalChunks += Math.ceil(subFrameLists[s].length / effectiveChunkCap);\n    }\n    const rasterBar = logger.bar('rasterizing', Math.max(1, totalChunks));\n    let completed = 0;\n\n    for (let sy = 0; sy < numSubFramesY; sy++) {\n        for (let sx = 0; sx < numSubFramesX; sx++) {\n            const tilesX = Math.min(subFrameTilesX, imageTilesX - sx * subFrameTilesX);\n            const tilesY = Math.min(subFrameTilesY, imageTilesY - sy * subFrameTilesY);\n\n            rasterizer.beginGroup(sx, sy, tilesX, tilesY);\n\n            const sfCandidates = subFrameLists[sy * numSubFramesX + sx];\n            const sfCount = sfCandidates.length;\n            for (let chunkStart = 0; chunkStart < sfCount; chunkStart += effectiveChunkCap) {\n                const chunkSize = Math.min(effectiveChunkCap, sfCount - chunkStart);\n                packChunkInput(cols, sfCandidates, chunkStart, chunkSize, numSHBands, chunkInput);\n                rasterizer.dispatchChunk(chunkInput, chunkSize);\n                rasterBar.update(++completed);\n            }\n\n            const subFrameBytes = await rasterizer.finishGroup();\n\n            // Copy the sub-frame's pixels into the final image. The\n            // rasterizer's output buffer row stride is the sub-frame's\n            // pixel width (`tilesX × TILE_SIZE`), not the image width;\n            // copy row-by-row into the right offset.\n            const subPixelOriginX = sx * subFrameTilesX * TILE_SIZE;\n            const subPixelOriginY = sy * subFrameTilesY * TILE_SIZE;\n            const subPixelW = tilesX * TILE_SIZE;\n            const subPixelH = tilesY * TILE_SIZE;\n            const copyW = Math.min(subPixelW, width - subPixelOriginX);\n            const copyH = Math.min(subPixelH, height - subPixelOriginY);\n            for (let row = 0; row < copyH; row++) {\n                const srcOffset = row * subPixelW * 4;\n                const dstOffset = ((subPixelOriginY + row) * width + subPixelOriginX) * 4;\n                finalImage.set(\n                    subFrameBytes.subarray(srcOffset, srcOffset + copyW * 4),\n                    dstOffset\n                );\n            }\n        }\n    }\n    rasterBar.end();\n\n    rasterizer.destroy();\n\n    return finalImage;\n};\n\nexport { renderRasterPass, CHUNK_CAP };\n","import { basename } from 'pathe';\nimport { Vec3 } from 'playcanvas';\n\nimport { logWrittenFile } from './utils';\nimport { convertToSpace, DataTable } from '../data-table';\nimport { type FileSystem, writeFile } from '../io/write';\nimport { renderSplats } from '../render';\nimport { type Projection, type RenderCamera } from '../render/camera';\nimport type { DeviceCreator } from '../types';\nimport { logger, Transform, WebPCodec } from '../utils';\n\n// Cache the WebP codec across invocations; `WebPCodec.create()` instantiates\n// the WASM module which is expensive to repeat. Same pattern as write-sog.ts.\nlet webPCodec: WebPCodec | undefined;\n\n/**\n * Options for writing a rendered splat image.\n */\ntype WriteImageOptions = {\n    /** Output filename ending in `.webp`. */\n    filename: string;\n\n    /** Gaussian splat data to render. */\n    dataTable: DataTable;\n\n    /**\n     * Camera projection mode. Default: `'pinhole'`.\n     *\n     * - `'pinhole'` — perspective camera using `fov`.\n     * - `'equirect'` — full 360° × 180° equirectangular panorama from\n     *   `cameraPosition`. Ignores `fov`. Requires `width === 2 × height`;\n     *   default resolution is 2048 × 1024.\n     */\n    projection?: Projection;\n\n    /** Camera position in world space. Default: (2, 1, -2). */\n    cameraPosition?: { x: number; y: number; z: number };\n\n    /** Point the camera looks at, in world space. Default: (0, 0, 0). */\n    lookAt?: { x: number; y: number; z: number };\n\n    /** World-space up vector. Default: (0, 1, 0). */\n    up?: { x: number; y: number; z: number };\n\n    /** Vertical field of view in degrees. Default: 60 for `pinhole`. Must be omitted for `equirect` (throws if supplied). */\n    fov?: number;\n\n    /** Output image width in pixels. Default: 1280 (pinhole) or 2048 (equirect). */\n    width?: number;\n\n    /** Output image height in pixels. Default: 720 (pinhole) or 1024 (equirect). */\n    height?: number;\n\n    /** Near clip distance in world units. Splats with camera-space depth <= near are culled. Default: 0.2 (matches the reference 3DGS rasterizer). */\n    near?: number;\n\n    /** RGBA background, each channel in [0, 1]. Default: (0, 0, 0, 1). */\n    background?: { r: number; g: number; b: number; a: number };\n\n    /**\n     * Aperture as a photographic f-stop (e.g. 2.8, 5.6, 11). Enables\n     * defocus blur / depth-of-field: smaller numbers = stronger blur.\n     * Defaults to disabled. Pinhole only — passing this with\n     * `projection: 'equirect'` is an error.\n     */\n    fStop?: number;\n\n    /**\n     * Camera-space Z of the focus plane in world units. Defaults to the\n     * distance from `cameraPosition` to `lookAt` along the forward axis\n     * (i.e. focus on the look-at point) when `fStop` is set. Has no\n     * effect without `fStop`. Pinhole only — passing this with\n     * `projection: 'equirect'` is an error.\n     */\n    focusDistance?: number;\n\n    /**\n     * Vertical sensor height in world units, used to give `fStop` a\n     * defined physical meaning. Default `0.024` matches a 35mm\n     * full-frame sensor when world units are meters. Scale this with\n     * your scene's units (e.g. world unit = decimeter → 0.24, world\n     * unit = millimeter → 24). Has no effect without `fStop`.\n     */\n    sensorSize?: number;\n\n    /**\n     * End camera position for motion blur. When set, enables camera\n     * motion blur: the renderer averages `motionSamples` sub-frames\n     * with the camera interpolated from (`cameraPosition`, `lookAt`,\n     * `up`) at shutter-open to (`cameraEndPosition`, `lookAtEnd`,\n     * `upEnd`) at shutter-close.\n     */\n    cameraEndPosition?: { x: number; y: number; z: number };\n\n    /**\n     * End look-at target for motion blur. Defaults to `lookAt` when\n     * motion blur is enabled.\n     */\n    lookAtEnd?: { x: number; y: number; z: number };\n\n    /**\n     * End up vector for motion blur. Defaults to `up` when motion blur\n     * is enabled.\n     */\n    upEnd?: { x: number; y: number; z: number };\n\n    /**\n     * Shutter fraction in `[0, 1]`. Portion of the start→end segment\n     * actually integrated, centered on the midpoint (standard\n     * shutter-angle convention: 1.0 = full motion, 0.5 = 180° shutter).\n     * Default: `1`. Only meaningful with `cameraEndPosition`.\n     */\n    shutter?: number;\n\n    /**\n     * Number of sub-frames to accumulate for motion blur. Cost is N×\n     * a single render. Default: `16`. Only meaningful with\n     * `cameraEndPosition`.\n     */\n    motionSamples?: number;\n\n    /** Function returning a GraphicsDevice. Required — rasterization runs on GPU. */\n    createDevice?: DeviceCreator;\n};\n\n/**\n * Renders the splat scene to a lossless WebP image written via `fs`.\n *\n * @param options - Render parameters and target filename.\n * @param fs - File system abstraction for writing the output.\n *\n * @example\n * ```ts\n * await writeImage({\n *     filename: 'view.webp',\n *     dataTable,\n *     cameraPosition: { x: 0, y: 0, z: 5 },\n *     fov: 60,\n *     width: 1920, height: 1080,\n *     createDevice: async () => myDevice\n * }, fs);\n * ```\n */\nconst writeImage = async (options: WriteImageOptions, fs: FileSystem): Promise<void> => {\n    const {\n        filename,\n        dataTable,\n        projection = 'pinhole',\n        cameraPosition = { x: 2, y: 1, z: -2 },\n        lookAt = { x: 0, y: 0, z: 0 },\n        up = { x: 0, y: 1, z: 0 },\n        near = 0.2,\n        background = { r: 0, g: 0, b: 0, a: 1 },\n        fStop,\n        focusDistance,\n        sensorSize = 0.024,\n        cameraEndPosition,\n        lookAtEnd,\n        upEnd,\n        shutter,\n        motionSamples,\n        createDevice\n    } = options;\n\n    if (!createDevice) {\n        throw new Error('writeImage requires a createDevice function for GPU rasterization');\n    }\n\n    let { fov, width, height } = options;\n    if (projection === 'equirect') {\n        if (fov !== undefined) {\n            throw new Error('writeImage: --fov is not valid with --projection equirect (the projection covers a full 360°×180° sphere).');\n        }\n        if (fStop !== undefined) {\n            throw new Error('writeImage: --f-stop is not valid with --projection equirect (defocus blur needs a focal length, which the equirect projection does not have).');\n        }\n        if (focusDistance !== undefined) {\n            throw new Error('writeImage: --focus-distance is not valid with --projection equirect.');\n        }\n        if (options.sensorSize !== undefined) {\n            throw new Error('writeImage: --sensor-size is not valid with --projection equirect.');\n        }\n        if (width === undefined && height === undefined) {\n            width = 2048;\n            height = 1024;\n        } else if (width === undefined || height === undefined) {\n            throw new Error('writeImage: equirect requires either both width and height, or neither (defaults to 2048x1024).');\n        }\n        if (width !== 2 * height) {\n            throw new Error(`writeImage: equirect requires width === 2 × height (got ${width}x${height}).`);\n        }\n    } else {\n        fov ??= 60;\n        width ??= 1280;\n        height ??= 720;\n        if (fov <= 0 || fov >= 180) {\n            throw new Error(`Invalid fov: ${fov}. Must be in (0, 180).`);\n        }\n        if (fStop !== undefined && !(fStop > 0)) {\n            throw new Error(`Invalid f-stop: ${fStop}. Must be > 0.`);\n        }\n        if (focusDistance !== undefined && !(focusDistance > 0)) {\n            throw new Error(`Invalid focus-distance: ${focusDistance}. Must be > 0.`);\n        }\n        if (!(sensorSize > 0)) {\n            throw new Error(`Invalid sensor-size: ${sensorSize}. Must be > 0.`);\n        }\n    }\n\n    // Motion blur: enabled iff `--camera-end` is supplied. The end pose\n    // for missing `look-at-end` / `up-end` defaults to the start pose so\n    // pure translations don't need redundant flags.\n    const motionBlur = cameraEndPosition !== undefined;\n    const motionN = motionBlur ? (motionSamples ?? 16) : 1;\n    const motionShutter = motionBlur ? (shutter ?? 1) : 0;\n    if (motionBlur && (motionShutter < 0 || motionShutter > 1)) {\n        throw new Error(`writeImage: --shutter must be in [0, 1], got ${motionShutter}.`);\n    }\n    if (motionBlur && (!Number.isInteger(motionN) || motionN < 1)) {\n        throw new Error(`writeImage: --motion-samples must be a positive integer, got ${motionN}.`);\n    }\n    const camStart = cameraPosition;\n    const camEnd = cameraEndPosition ?? cameraPosition;\n    const lookStart = lookAt;\n    const lookEnd = lookAtEnd ?? lookAt;\n    const upStart = up;\n    const upEndR = upEnd ?? up;\n\n    const g = logger.group('Render');\n\n    const fovY = projection === 'equirect' ? 0 : (fov! * Math.PI) / 180;\n\n    // Precompute focal scaling used by the DoF aperture-scale formula. Only\n    // depends on intrinsics (sensor, fov, height), not on the camera pose,\n    // so it's safe to share across motion-blur sub-frames.\n    const dofEnabled = projection !== 'equirect' && fStop !== undefined;\n    const focalRealWorld = dofEnabled ? (sensorSize / 2) / Math.tan(fovY * 0.5) : 0;\n    const focalYPx = dofEnabled ? (height / 2) / Math.tan(fovY * 0.5) : 0;\n\n    // Resolve DoF for pinhole only. The project shader consumes a single\n    // pre-baked scalar `apertureScale` (pixel CoC per unit relative\n    // defocus) and the focus distance. Physical CoC for a thin lens is:\n    //\n    //     CoC_pixels = (focal_real² / (N · focus)) × |1 − focus/cz|\n    //                  × image_height / sensor_height\n    //\n    // where focal_real is the real lens focal length implied by\n    // `fovY` and `sensorSize`. Apply image_height / sensor_height to\n    // convert physical CoC (sensor units) to pixels. Defaulting\n    // `sensorSize` to 0.024 makes f-stops behave like a 35mm\n    // full-frame camera when world units are meters; scale to suit\n    // non-meter scenes. Focus defaults to the look-at point — which,\n    // under motion blur, moves with the interpolated camera pose\n    // (recomputed per sub-frame below).\n    const buildCamera = (pos: { x: number; y: number; z: number },\n        tgt: { x: number; y: number; z: number },\n        u: { x: number; y: number; z: number }): RenderCamera => {\n        let fDist = 0;\n        let aScale = 0;\n        if (dofEnabled) {\n            if (focusDistance !== undefined) {\n                fDist = focusDistance;\n            } else {\n                const fwdLen = Math.hypot(tgt.x - pos.x, tgt.y - pos.y, tgt.z - pos.z);\n                if (fwdLen === 0) {\n                    throw new Error('writeImage: cannot derive default --focus-distance because --camera equals --look-at.');\n                }\n                fDist = fwdLen;\n            }\n            aScale = focalRealWorld * focalYPx / (fStop! * fDist);\n        }\n        return {\n            projection,\n            position: new Vec3(pos.x, pos.y, pos.z),\n            target: new Vec3(tgt.x, tgt.y, tgt.z),\n            up: new Vec3(u.x, u.y, u.z),\n            fovY,\n            width: width!,\n            height: height!,\n            near,\n            focusDistance: fDist,\n            apertureScale: aScale\n        };\n    };\n\n    const device = await createDevice();\n\n    // The renderer's camera, defaults and convention all live in PlayCanvas\n    // default space. Convert the DataTable from its source-space (e.g.\n    // Transform.PLY) to identity so positions, rotations and SH bands align.\n    // `inPlace=true` is safe: the CLI builds a fresh combined DataTable per\n    // write and library callers passing data into a writer accept that the\n    // writer may consume the table.\n    const pcDataTable = convertToSpace(dataTable, Transform.IDENTITY, true);\n\n    // Pre-resolve the start-pose DoF info for the info log line.\n    const startCamera = buildCamera(camStart, lookStart, upStart);\n\n    if (projection === 'equirect') {\n        logger.info(`${width}x${height} equirect`);\n    } else if (startCamera.apertureScale! > 0) {\n        logger.info(`${width}x${height} fov ${fov}° f/${fStop} focus ${startCamera.focusDistance!.toFixed(3)} sensor ${sensorSize}`);\n    } else {\n        logger.info(`${width}x${height} fov ${fov}°`);\n    }\n    if (motionBlur) {\n        logger.info(`motion blur: ${motionN} samples, shutter ${motionShutter}`);\n    }\n\n    let rgba: Uint8Array;\n    if (!motionBlur) {\n        rgba = await renderSplats(device, pcDataTable, startCamera, background);\n    } else {\n        // Camera motion blur: average N sub-frames with the camera linearly\n        // interpolated between the start and end poses, stratified across\n        // the shutter window centered on the midpoint. Accumulate in float\n        // to avoid 8-bit truncation per sample.\n        const halfWin = motionShutter / 2;\n        const t0 = 0.5 - halfWin;\n        const t1 = 0.5 + halfWin;\n        const pixels = width! * height! * 4;\n        const accum = new Float32Array(pixels);\n        for (let i = 0; i < motionN; i++) {\n            const u = motionN === 1 ? 0.5 : (i + 0.5) / motionN;\n            const t = t0 + (t1 - t0) * u;\n            const pos = {\n                x: camStart.x + (camEnd.x - camStart.x) * t,\n                y: camStart.y + (camEnd.y - camStart.y) * t,\n                z: camStart.z + (camEnd.z - camStart.z) * t\n            };\n            const tgt = {\n                x: lookStart.x + (lookEnd.x - lookStart.x) * t,\n                y: lookStart.y + (lookEnd.y - lookStart.y) * t,\n                z: lookStart.z + (lookEnd.z - lookStart.z) * t\n            };\n            // Normalized lerp for `up` so it stays unit-length when the\n            // start/end up vectors differ in direction.\n            const ux = upStart.x + (upEndR.x - upStart.x) * t;\n            const uy = upStart.y + (upEndR.y - upStart.y) * t;\n            const uz = upStart.z + (upEndR.z - upStart.z) * t;\n            const ulen = Math.hypot(ux, uy, uz) || 1;\n            const upI = { x: ux / ulen, y: uy / ulen, z: uz / ulen };\n            const subCamera = buildCamera(pos, tgt, upI);\n            const frame = await renderSplats(device, pcDataTable, subCamera, background);\n            for (let p = 0; p < pixels; p++) accum[p] += frame[p];\n        }\n        rgba = new Uint8Array(pixels);\n        const inv = 1 / motionN;\n        for (let p = 0; p < pixels; p++) rgba[p] = Math.round(accum[p] * inv);\n    }\n\n    const encodingGroup = logger.group('Encoding');\n    if (!webPCodec) {\n        webPCodec = await WebPCodec.create();\n    }\n    const webp = webPCodec.encodeLosslessRGBA(rgba, width, height);\n    encodingGroup.end();\n\n    await writeFile(fs, filename, webp);\n    logWrittenFile(basename(filename), webp.byteLength);\n\n    g.end();\n};\n\nexport { writeImage, type WriteImageOptions };\n","import { basename, dirname, resolve } from 'pathe';\nimport { BoundingBox, Mat4, Quat, Vec3 } from 'playcanvas';\n\nimport { logWrittenFile } from './utils';\nimport { writeSog } from './write-sog.js';\nimport { type TypedArray, DataTable, sortMortonOrder, convertToSpace } from '../data-table';\nimport { type FileSystem } from '../io/write';\nimport { BTreeNode, BTree } from '../spatial';\nimport type { DeviceCreator } from '../types';\nimport { logger, Transform } from '../utils';\n\ntype Aabb = {\n    min: number[],\n    max: number[]\n};\n\ntype MetaLod = {\n    file: number;\n    offset: number;\n    count: number;\n};\n\ntype MetaNode = {\n    bound: Aabb;\n    children?: MetaNode[];\n    lods?: { [key: number]: MetaLod };\n};\n\ntype LodMeta = {\n    lodLevels: number,\n    environment?: string;\n    filenames: string[];\n    tree: MetaNode;\n};\n\nconst boundUnion = (result: Aabb, a: Aabb, b: Aabb) => {\n    const am = a.min;\n    const aM = a.max;\n    const bm = b.min;\n    const bM = b.max;\n    const rm = result.min;\n    const rM = result.max;\n\n    rm[0] = Math.min(am[0], bm[0]);\n    rm[1] = Math.min(am[1], bm[1]);\n    rm[2] = Math.min(am[2], bm[2]);\n    rM[0] = Math.max(aM[0], bM[0]);\n    rM[1] = Math.max(aM[1], bM[1]);\n    rM[2] = Math.max(aM[2], bM[2]);\n};\n\nconst calcBound = (dataTable: DataTable, indices: number[]): Aabb => {\n    const x = dataTable.getColumnByName('x').data;\n    const y = dataTable.getColumnByName('y').data;\n    const z = dataTable.getColumnByName('z').data;\n    const rx = dataTable.getColumnByName('rot_1').data;\n    const ry = dataTable.getColumnByName('rot_2').data;\n    const rz = dataTable.getColumnByName('rot_3').data;\n    const rw = dataTable.getColumnByName('rot_0').data;\n    const sx = dataTable.getColumnByName('scale_0').data;\n    const sy = dataTable.getColumnByName('scale_1').data;\n    const sz = dataTable.getColumnByName('scale_2').data;\n\n    const p = new Vec3();\n    const r = new Quat();\n    const s = new Vec3();\n    const mat4 = new Mat4();\n\n    const a = new BoundingBox();\n    const b = new BoundingBox();\n\n    const min = [Infinity, Infinity, Infinity];\n    const max = [-Infinity, -Infinity, -Infinity];\n\n    a.center.set(0, 0, 0);\n\n    for (const index of indices) {\n        p.set(x[index], y[index], z[index]);\n        r.set(rx[index], ry[index], rz[index], rw[index]).normalize();\n        s.set(Math.exp(sx[index]), Math.exp(sy[index]), Math.exp(sz[index]));\n        mat4.setTRS(p, r, Vec3.ONE);\n\n        a.halfExtents.set(s.x, s.y, s.z);\n        b.setFromTransformedAabb(a, mat4);\n\n        const m = b.getMin();\n        const M = b.getMax();\n\n        if (!isFinite(m.x) || !isFinite(m.y) || !isFinite(m.z) || !isFinite(M.x) || !isFinite(M.y) || !isFinite(M.z)) {\n            logger.warn(`skipping invalid bounding box at index ${index}: min=(${m.x}, ${m.y}, ${m.z}) max=(${M.x}, ${M.y}, ${M.z})`);\n            continue;\n        }\n\n        min[0] = Math.min(min[0], m.x);\n        min[1] = Math.min(min[1], m.y);\n        min[2] = Math.min(min[2], m.z);\n        max[0] = Math.max(max[0], M.x);\n        max[1] = Math.max(max[1], M.y);\n        max[2] = Math.max(max[2], M.z);\n    }\n\n    return { min, max };\n};\n\nconst binIndices = (parent: BTreeNode, lod: TypedArray) => {\n    const result = new Map<number, number[]>();\n\n    // we've reached a leaf node, gather indices\n    const recurse = (node: BTreeNode) => {\n        if (node.indices) {\n\n            for (let i = 0; i < node.indices.length; ++i) {\n                const v = node.indices[i];\n                const lodValue = lod[v];\n\n                if (!result.has(lodValue)) {\n                    result.set(lodValue, [v]);\n                } else {\n                    result.get(lodValue).push(v);\n                }\n            }\n        } else {\n            if (node.left) {\n                recurse(node.left);\n            }\n            if (node.right) {\n                recurse(node.right);\n            }\n        }\n    };\n\n    recurse(parent);\n\n    return result;\n};\n\ntype WriteLodOptions = {\n    filename: string;\n    dataTable: DataTable;\n    envDataTable: DataTable | null;\n    iterations: number;\n    createDevice?: DeviceCreator;\n    chunkCount: number;\n    chunkExtent: number;\n};\n\n/**\n * Writes Gaussian splat data to multi-LOD format with spatial chunking.\n *\n * Creates a hierarchical structure with multiple LOD levels, each stored\n * in separate SOG files. Includes spatial indexing via a binary tree for\n * efficient streaming and view-dependent loading.\n *\n * @param options - Options including filename, data, and chunking parameters.\n * @param fs - File system for writing output files.\n * @ignore\n */\nconst writeLod = async (options: WriteLodOptions, fs: FileSystem) => {\n    const { filename, iterations, createDevice, chunkCount, chunkExtent } = options;\n\n    // Operate in PLY space so per-leaf bounds in tree.bound are in the same\n    // coordinate frame as the SOG chunk data emitted by writeSog (which also\n    // converts to Transform.PLY). Without this, view-dependent streaming\n    // built on tree.bound picks the wrong chunks because the bounds are\n    // 180°-Z-rotated relative to the splat positions inside them.\n    // This intentionally mutates the input tables to avoid doubling peak\n    // memory during LOD export. Callers should treat writeLod as consuming its\n    // DataTable inputs.\n    const dataTable = convertToSpace(options.dataTable, Transform.PLY, true);\n    const envDataTable = options.envDataTable ? convertToSpace(options.envDataTable, Transform.PLY, true) : null;\n\n    const outputDir = dirname(filename);\n\n    // ensure top-level output folder exists\n    await fs.mkdir(outputDir);\n\n    // construct a kd-tree based on centroids from all lods\n    const centroidsTable = new DataTable([\n        dataTable.getColumnByName('x'),\n        dataTable.getColumnByName('y'),\n        dataTable.getColumnByName('z')\n    ]);\n\n    const bTree = new BTree(centroidsTable);\n\n    // approximate number of gaussians we'll place into file units\n    const binSize = chunkCount * 1024;\n    const binDim = chunkExtent;\n\n    // map of lod -> fileBin[]\n    // fileBin: number[][]\n    const lodFiles: Map<number, number[][][]> = new Map();\n    const lodColumn = dataTable.getColumnByName('lod')?.data;\n    const filenames: string[] = [];\n    let lodLevels = 0;\n\n    if (!lodColumn) {\n        throw new Error('Missing lod assignment');\n    }\n\n    const build = (node: BTreeNode): MetaNode => {\n        if (!node.indices && (node.count > binSize || (node.aabb && node.aabb.largestDim() > binDim))) {\n            const children = [\n                build(node.left),\n                build(node.right)\n            ];\n\n            const bound = {\n                min: [0, 0, 0],\n                max: [0, 0, 0]\n            };\n            boundUnion(bound, children[0].bound, children[1].bound);\n\n            return { bound, children };\n        }\n\n        const lods: { [key: number]: MetaLod } = { };\n        const bins = binIndices(node, lodColumn);\n\n        for (const [lodValue, indices] of bins) {\n            if (!lodFiles.has(lodValue)) {\n                lodFiles.set(lodValue, [[]]);\n            }\n            const fileList = lodFiles.get(lodValue);\n            const fileIndex = fileList.length - 1;\n            const lastFile = fileList[fileIndex];\n            const fileSize = lastFile.reduce((acc, curr) => acc + curr.length, 0);\n\n            const filename = `${lodValue}_${fileIndex}/meta.json`;\n            if (filenames.indexOf(filename) === -1) {\n                filenames.push(filename);\n            }\n\n            lods[lodValue] = {\n                file: filenames.indexOf(filename),\n                offset: fileSize,\n                count: indices.length\n            };\n\n            lastFile.push(indices);\n\n            if (fileSize + indices.length > binSize) {\n                fileList.push([]);\n            }\n\n            lodLevels = Math.max(lodLevels, lodValue + 1);\n        }\n\n        // combine indices from all lods so we can calcuate bound over them\n        const allIndices: number[] = Array.from(bins.values()).flat();\n\n        const bound = calcBound(dataTable, allIndices);\n\n        return { bound, lods };\n    };\n\n    const tree = build(bTree.root);\n    const meta: LodMeta = {\n        lodLevels,\n        environment: (envDataTable?.numRows > 0) ? 'env/meta.json' : null,\n        filenames,\n        tree\n    };\n\n    // write the meta file with float precision quantization (approx. 32-bit float => ~7 significant digits)\n    const replacer = (_key: string, value: any) => {\n        if (typeof value === 'number') {\n            if (!Number.isFinite(value)) return value;\n            return Number.isInteger(value) ? value : +value.toPrecision(7);\n        }\n        return value;\n    };\n\n    const writingGroup = logger.group('Writing');\n\n    // count the total number of sog units we'll write so the per-sog groups\n    // can render as a numbered series\n    let sogTotal = 0;\n    if (envDataTable?.numRows > 0) sogTotal += 1;\n    for (const [, fileUnits] of lodFiles) {\n        for (const fu of fileUnits) {\n            if (fu.length > 0) sogTotal += 1;\n        }\n    }\n\n    let sogIndex = 0;\n\n    // write the environment sog\n    if (envDataTable?.numRows > 0) {\n        sogIndex++;\n        const envGroup = logger.group('env', { index: sogIndex, total: sogTotal });\n        try {\n            const envPathname = resolve(outputDir, 'env/meta.json');\n\n            // ensure output folder exists before any files are written\n            await fs.mkdir(dirname(envPathname));\n\n            await writeSog({\n                filename: envPathname,\n                dataTable: envDataTable,\n                bundle: false,\n                iterations,\n                createDevice,\n                logging: 'flat'\n            }, fs);\n        } finally {\n            envGroup.end();\n        }\n    }\n\n    // write lod-meta.json\n    const metaJson = (new TextEncoder()).encode(JSON.stringify(meta, replacer));\n    const writer = await fs.createWriter(filename);\n    await writer.write(metaJson);\n    await writer.close();\n    logWrittenFile(basename(filename), writer.bytesWritten);\n\n    // write file units\n    for (const [lodValue, fileUnits] of lodFiles) {\n        for (let i = 0; i < fileUnits.length; ++i) {\n            const fileUnit = fileUnits[i];\n\n            if (fileUnit.length === 0) {\n                continue;\n            }\n\n            const groupName = `${lodValue}_${i}`;\n            sogIndex++;\n            const unitGroup = logger.group(groupName, { index: sogIndex, total: sogTotal });\n\n            try {\n                // ensure output folder exists before any files are written\n                const pathname = resolve(outputDir, `${lodValue}_${i}/meta.json`);\n                await fs.mkdir(dirname(pathname));\n\n                // generate an ordering for each subunit and append it to the unit's indices\n                const totalIndices = fileUnit.reduce((acc, curr) => acc + curr.length, 0);\n                const indices = new Uint32Array(totalIndices);\n                for (let j = 0, offset = 0; j < fileUnit.length; ++j) {\n                    indices.set(fileUnit[j], offset);\n                    sortMortonOrder(dataTable, indices.subarray(offset, offset + fileUnit[j].length));\n                    offset += fileUnit[j].length;\n                }\n\n                // construct a new table from the ordered data\n                const unitDataTable = dataTable.clone({ rows: indices });\n\n                // reset indices since we've generated ordering on the individual subunits\n                for (let j = 0; j < indices.length; ++j) {\n                    indices[j] = j;\n                }\n\n                // write file unit to sog\n                await writeSog({\n                    filename: pathname,\n                    dataTable: unitDataTable,\n                    indices,\n                    bundle: false,\n                    iterations,\n                    createDevice,\n                    logging: 'flat'\n                }, fs);\n            } finally {\n                unitGroup.end();\n            }\n        }\n    }\n\n    writingGroup.end();\n};\n\nexport { writeLod };\n","import { basename } from 'pathe';\n\nimport { logWrittenFile } from './utils';\nimport { convertToSpace } from '../data-table';\nimport { type FileSystem } from '../io/write';\nimport { PlyData } from '../readers';\nimport { logger, Transform } from '../utils';\n\nconst columnTypeToPlyType = (type: string): string => {\n    switch (type) {\n        case 'float32': return 'float';\n        case 'float64': return 'double';\n        case 'int8': return 'char';\n        case 'uint8': return 'uchar';\n        case 'int16': return 'short';\n        case 'uint16': return 'ushort';\n        case 'int32': return 'int';\n        case 'uint32': return 'uint';\n    }\n};\n\ntype WritePlyOptions = {\n    filename: string;\n    plyData: PlyData;\n};\n\n/**\n * Writes Gaussian splat data to a binary PLY file.\n *\n * The PLY format is the standard output from 3D Gaussian Splatting training\n * and is widely supported by visualization tools.\n *\n * @param options - Options including filename and PLY data to write.\n * @param fs - File system for writing the output file.\n * @ignore\n */\nconst writePly = async (options: WritePlyOptions, fs: FileSystem) => {\n    const { filename } = options;\n    const plyData: PlyData = {\n        ...options.plyData,\n        elements: options.plyData.elements.map(e => ({\n            ...e,\n            dataTable: convertToSpace(e.dataTable, Transform.PLY)\n        }))\n    };\n\n    const header = [\n        'ply',\n        'format binary_little_endian 1.0',\n        plyData.comments.map(c => `comment ${c}`),\n        plyData.elements.map((element) => {\n            return [\n                `element ${element.name} ${element.dataTable.numRows}`,\n                element.dataTable.columns.map((column) => {\n                    return `property ${columnTypeToPlyType(column.dataType)} ${column.name}`;\n                })\n            ];\n        }),\n        'end_header'\n    ];\n\n    const writingGroup = logger.group('Writing');\n\n    // write the header\n    const writer = await fs.createWriter(filename);\n    await writer.write((new TextEncoder()).encode(`${header.flat(3).join('\\n')}\\n`));\n\n    for (let i = 0; i < plyData.elements.length; ++i) {\n        const table = plyData.elements[i].dataTable;\n        const columns = table.columns;\n        const buffers = columns.map(c => new Uint8Array(c.data.buffer, c.data.byteOffset, c.data.byteLength));\n        const sizes = columns.map(c => c.data.BYTES_PER_ELEMENT);\n        const rowSize = sizes.reduce((total, size) => total + size, 0);\n\n        // write to file in chunks of 1024 rows\n        const chunkSize = 1024;\n        const numChunks = Math.ceil(table.numRows / chunkSize);\n        const chunkData = new Uint8Array(chunkSize * rowSize);\n\n        for (let c = 0; c < numChunks; ++c) {\n            const numRows = Math.min(chunkSize, table.numRows - c * chunkSize);\n\n            let offset = 0;\n\n            for (let r = 0; r < numRows; ++r) {\n                const rowOffset = c * chunkSize + r;\n\n                for (let p = 0; p < columns.length; ++p) {\n                    const s = sizes[p];\n                    const srcOffset = rowOffset * s;\n                    chunkData.set(buffers[p].subarray(srcOffset, srcOffset + s), offset);\n                    offset += s;\n                }\n            }\n\n            // write the chunk\n            await writer.write(chunkData.subarray(0, offset));\n        }\n    }\n\n    await writer.close();\n\n    logWrittenFile(basename(filename), writer.bytesWritten);\n    writingGroup.end();\n};\n\nexport { writePly };\n","import { basename } from 'pathe';\n\nimport { logWrittenFile } from './utils';\nimport { type FileSystem, writeFile } from '../io/write';\nimport { dataTableToGaussianCloud, getSpzModule, makeSpzPackOptions } from '../spz-module';\nimport { logger } from '../utils';\n\ntype WriteSpzOptions = {\n    filename: string;\n    dataTable: import('../data-table').DataTable;\n    version?: 3 | 4;\n};\n\n/**\n * Writes Gaussian splat data to a bundled SPZ file using the official SPZ\n * WebAssembly backend.\n *\n * @param options - Options including filename and dataTable.\n * @param fs - File system for writing the output file.\n * @ignore\n */\nconst writeSpz = async (options: WriteSpzOptions, fs: FileSystem) => {\n    const { filename, dataTable, version = 4 } = options;\n    const writingGroup = logger.group('Writing');\n\n    const spz = await getSpzModule();\n    const packOptions = await makeSpzPackOptions({ version });\n    const cloud = dataTableToGaussianCloud(dataTable);\n    const bytes = spz.saveSpzToBuffer(cloud, packOptions);\n\n    if (version === 4) {\n        if (!(bytes[0] === 0x4e && bytes[1] === 0x47 && bytes[2] === 0x53 && bytes[3] === 0x50)) {\n            throw new Error('SPZ writer requested version 4 but the backend did not emit an NGSP header');\n        }\n    } else if (!(bytes[0] === 0x1f && bytes[1] === 0x8b)) {\n        throw new Error('SPZ writer requested a legacy version but the backend did not emit gzip-compressed output');\n    }\n\n    await writeFile(fs, filename, bytes);\n\n    logWrittenFile(basename(filename), bytes.byteLength);\n    writingGroup.end();\n};\n\nexport { writeSpz };\n","/** All 64 bits set (as unsigned 32-bit) */\nconst SOLID_MASK = 0xFFFFFFFF >>> 0;\n\n/**\n * Encode block coordinates to Morton code (17 bits per axis = 51 bits total).\n * Supports up to 131,072 blocks per axis.\n *\n * @param x - Block X coordinate\n * @param y - Block Y coordinate\n * @param z - Block Z coordinate\n * @returns Morton code with interleaved bits: ...z2y2x2 z1y1x1 z0y0x0\n */\nfunction xyzToMorton(x: number, y: number, z: number): number {\n    let result = 0;\n    let shift = 1;\n    for (let i = 0; i < 17; i++) {\n        if (x & 1) result += shift;\n        if (y & 1) result += shift * 2;\n        if (z & 1) result += shift * 4;\n        x >>>= 1;\n        y >>>= 1;\n        z >>>= 1;\n        shift *= 8;\n    }\n    return result;\n}\n\n/**\n * Count the number of set bits in a 32-bit integer.\n *\n * @param n - 32-bit integer\n * @returns Number of bits set to 1\n */\nfunction popcount(n: number): number {\n    n >>>= 0;\n    n -= ((n >>> 1) & 0x55555555);\n    n = (n & 0x33333333) + ((n >>> 2) & 0x33333333);\n    return (((n + (n >>> 4)) & 0x0F0F0F0F) * 0x01010101) >>> 24;\n}\n\n/**\n * Check if a voxel mask represents a solid block (all 64 bits set).\n *\n * @param lo - Lower 32 bits of mask\n * @param hi - Upper 32 bits of mask\n * @returns True if all 64 voxels are solid\n */\nfunction isSolid(lo: number, hi: number): boolean {\n    return (lo >>> 0) === SOLID_MASK && (hi >>> 0) === SOLID_MASK;\n}\n\n/**\n * Check if a voxel mask represents an empty block (no bits set).\n *\n * @param lo - Lower 32 bits of mask\n * @param hi - Upper 32 bits of mask\n * @returns True if all 64 voxels are empty\n */\nfunction isEmpty(lo: number, hi: number): boolean {\n    return lo === 0 && hi === 0;\n}\n\nexport {\n    xyzToMorton,\n    popcount,\n    isSolid,\n    isEmpty\n};\n","import { isSolid, isEmpty } from './morton';\n\nconst INITIAL_CAPACITY = 1024;\n\nconst growFloat64 = (src: Float64Array, newCap: number): Float64Array => {\n    const grown = new Float64Array(newCap);\n    grown.set(src);\n    return grown;\n};\n\nconst growUint32 = (src: Uint32Array, newCap: number): Uint32Array => {\n    const grown = new Uint32Array(newCap);\n    grown.set(src);\n    return grown;\n};\n\n/**\n * Append-only buffer for streaming voxelization results.\n * Stores (linear blockIdx, voxel mask) pairs for non-empty 4x4x4 blocks.\n *\n * Block keys are linear block indices `bx + by*nbx + bz*nbx*nby` in the\n * producer's grid coordinate system. Producers and consumers must agree\n * on the grid dimensions; the buffer itself is dimension-agnostic.\n *\n * Backed by typed arrays that grow geometrically. Keys use Float64Array so\n * the per-buffer capacity exceeds V8's regular-array backing-store limit\n * (large grids exceed Smi range and would throw `RangeError: Invalid array\n * length` with a regular array).\n */\nclass BlockMaskBuffer {\n    /** Linear block indices for solid blocks (mask is implicitly all 1s) */\n    private _solidIdx: Float64Array = new Float64Array(0);\n    private _solidCount = 0;\n    private _solidCap = 0;\n\n    /** Linear block indices for mixed blocks */\n    private _mixedIdx: Float64Array = new Float64Array(0);\n    private _mixedCount = 0;\n    private _mixedCap = 0;\n\n    /** Interleaved voxel masks for mixed blocks: [lo0, hi0, lo1, hi1, ...] */\n    private _mixedMasks: Uint32Array = new Uint32Array(0);\n\n    /**\n     * Add a non-empty block to the buffer.\n     * Automatically classifies as solid or mixed based on mask values.\n     *\n     * @param blockIdx - Linear block index (`bx + by*nbx + bz*nbx*nby`)\n     * @param lo - Lower 32 bits of voxel mask\n     * @param hi - Upper 32 bits of voxel mask\n     */\n    addBlock(blockIdx: number, lo: number, hi: number): void {\n        if (isEmpty(lo, hi)) {\n            return;\n        }\n\n        if (isSolid(lo, hi)) {\n            if (this._solidCount === this._solidCap) {\n                // First grow: 0 → INITIAL_CAPACITY. Subsequent: double.\n                this._solidCap = this._solidCap === 0 ? INITIAL_CAPACITY : this._solidCap * 2;\n                this._solidIdx = growFloat64(this._solidIdx, this._solidCap);\n            }\n            this._solidIdx[this._solidCount++] = blockIdx;\n        } else {\n            if (this._mixedCount === this._mixedCap) {\n                this._mixedCap = this._mixedCap === 0 ? INITIAL_CAPACITY : this._mixedCap * 2;\n                this._mixedIdx = growFloat64(this._mixedIdx, this._mixedCap);\n                this._mixedMasks = growUint32(this._mixedMasks, this._mixedCap * 2);\n            }\n            this._mixedIdx[this._mixedCount] = blockIdx;\n            this._mixedMasks[this._mixedCount * 2] = lo;\n            this._mixedMasks[this._mixedCount * 2 + 1] = hi;\n            this._mixedCount++;\n        }\n    }\n\n    /**\n     * Get all mixed blocks as views into the underlying buffers.\n     * Index `i` of `blockIdx` corresponds to mask pair `(masks[i*2], masks[i*2+1])`.\n     *\n     * @returns Object with linear block indices and interleaved masks\n     */\n    getMixedBlocks(): { blockIdx: Float64Array; masks: Uint32Array } {\n        return {\n            blockIdx: this._mixedIdx.subarray(0, this._mixedCount),\n            masks: this._mixedMasks.subarray(0, this._mixedCount * 2)\n        };\n    }\n\n    /**\n     * Get all solid blocks as a view into the underlying buffer.\n     *\n     * @returns Array of linear block indices\n     */\n    getSolidBlocks(): Float64Array {\n        return this._solidIdx.subarray(0, this._solidCount);\n    }\n\n    /**\n     * Get total number of blocks stored.\n     *\n     * @returns Count of mixed + solid blocks\n     */\n    get count(): number {\n        return this._mixedCount + this._solidCount;\n    }\n\n    /**\n     * Get number of mixed blocks.\n     *\n     * @returns Count of mixed blocks\n     */\n    get mixedCount(): number {\n        return this._mixedCount;\n    }\n\n    /**\n     * Get number of solid blocks.\n     *\n     * @returns Count of solid blocks\n     */\n    get solidCount(): number {\n        return this._solidCount;\n    }\n\n    /**\n     * Clear all buffered blocks. Releases the underlying buffers so a cleared\n     * instance does not retain peak memory; the next `addBlock` re-allocates\n     * to `INITIAL_CAPACITY`.\n     */\n    clear(): void {\n        this._solidIdx = new Float64Array(0);\n        this._solidCount = 0;\n        this._solidCap = 0;\n\n        this._mixedIdx = new Float64Array(0);\n        this._mixedMasks = new Uint32Array(0);\n        this._mixedCount = 0;\n        this._mixedCap = 0;\n    }\n}\n\nexport { BlockMaskBuffer };\n","const EMPTY = -1;\n\n/**\n * Open-addressing hash map for voxel block masks backed by typed arrays.\n * Replaces Map<number, [number, number]> to eliminate V8 Map overhead and\n * per-entry tuple allocations that cause GC pressure.\n *\n * Keys are non-negative block indices. Values are lo/hi uint32 mask pairs.\n * Uses Fibonacci hashing with linear probing and backward-shift deletion.\n */\nclass BlockMaskMap {\n    keys: Int32Array;\n    lo: Uint32Array;\n    hi: Uint32Array;\n    private _size: number;\n    private _capacity: number;\n    private _mask: number;\n\n    constructor(initialCapacity = 4096) {\n        const cap = 1 << (32 - Math.clz32(Math.max(15, initialCapacity - 1)));\n        this._capacity = cap;\n        this._mask = cap - 1;\n        this._size = 0;\n        this.keys = new Int32Array(cap).fill(EMPTY);\n        this.lo = new Uint32Array(cap);\n        this.hi = new Uint32Array(cap);\n    }\n\n    get size(): number {\n        return this._size;\n    }\n\n    /**\n     * Find the slot for a key. If the key exists, keys[slot] === key.\n     * If the key doesn't exist, keys[slot] === -1 (empty slot for insertion).\n     *\n     * @param key - Block index to look up.\n     * @returns Slot index into keys/lo/hi arrays.\n     */\n    slot(key: number): number {\n        const mask = this._mask;\n        let i = (Math.imul(key, 0x9E3779B9) >>> 0) & mask;\n        while (true) {\n            const k = this.keys[i];\n            if (k === key || k === EMPTY) return i;\n            i = (i + 1) & mask;\n        }\n    }\n\n    has(key: number): boolean {\n        return this.keys[this.slot(key)] !== EMPTY;\n    }\n\n    /**\n     * Insert at a slot known to be empty (keys[slot] === -1).\n     * Caller must have obtained slot via slot() and verified it is empty.\n     *\n     * @param slot - Empty slot index.\n     * @param key - Block index to insert.\n     * @param loVal - Lower 32 bits of voxel mask.\n     * @param hiVal - Upper 32 bits of voxel mask.\n     */\n    insertAt(slot: number, key: number, loVal: number, hiVal: number): void {\n        this.keys[slot] = key;\n        this.lo[slot] = loVal;\n        this.hi[slot] = hiVal;\n        this._size++;\n        if (this._size > ((this._capacity * 0.7) | 0)) {\n            this._grow();\n        }\n    }\n\n    /**\n     * Set key to lo/hi values. Inserts if key doesn't exist, updates if it does.\n     *\n     * @param key - Block index.\n     * @param loVal - Lower 32 bits of voxel mask.\n     * @param hiVal - Upper 32 bits of voxel mask.\n     */\n    set(key: number, loVal: number, hiVal: number): void {\n        let s = this.slot(key);\n        if (this.keys[s] === EMPTY) {\n            this.keys[s] = key;\n            this._size++;\n            if (this._size > ((this._capacity * 0.7) | 0)) {\n                this._grow();\n                s = this.slot(key);\n            }\n        }\n        this.lo[s] = loVal;\n        this.hi[s] = hiVal;\n    }\n\n    /**\n     * Remove entry at slot using backward-shift deletion.\n     * Maintains probe chain integrity without tombstones.\n     *\n     * @param slot - Slot index of the entry to remove.\n     */\n    removeAt(slot: number): void {\n        this._size--;\n        const mask = this._mask;\n        let i = slot;\n        let j = slot;\n        while (true) {\n            j = (j + 1) & mask;\n            if (this.keys[j] === EMPTY) break;\n            const k = ((Math.imul(this.keys[j], 0x9E3779B9) >>> 0) & mask);\n            if ((i < j) ? (k <= i || k > j) : (k <= i && k > j)) {\n                this.keys[i] = this.keys[j];\n                this.lo[i] = this.lo[j];\n                this.hi[i] = this.hi[j];\n                i = j;\n            }\n        }\n        this.keys[i] = EMPTY;\n    }\n\n    delete(key: number): void {\n        const s = this.slot(key);\n        if (this.keys[s] !== EMPTY) {\n            this.removeAt(s);\n        }\n    }\n\n    clear(): void {\n        this.keys.fill(EMPTY);\n        this._size = 0;\n    }\n\n    /**\n     * Release all backing storage. The map should not be used again except by\n     * replacing it with a new instance.\n     */\n    releaseStorage(): void {\n        this.keys = new Int32Array(0);\n        this.lo = new Uint32Array(0);\n        this.hi = new Uint32Array(0);\n        this._size = 0;\n        this._capacity = 0;\n        this._mask = 0;\n    }\n\n    forEach(fn: (key: number, lo: number, hi: number) => void): void {\n        const keys = this.keys;\n        const cap = this._capacity;\n        for (let i = 0; i < cap; i++) {\n            if (keys[i] !== EMPTY) {\n                fn(keys[i], this.lo[i], this.hi[i]);\n            }\n        }\n    }\n\n    clone(): BlockMaskMap {\n        const c = new BlockMaskMap(this._capacity);\n        c.keys.set(this.keys);\n        c.lo.set(this.lo);\n        c.hi.set(this.hi);\n        c._size = this._size;\n        return c;\n    }\n\n    private _grow(): void {\n        const oldKeys = this.keys;\n        const oldLo = this.lo;\n        const oldHi = this.hi;\n        const oldCap = this._capacity;\n\n        this._capacity *= 2;\n        this._mask = this._capacity - 1;\n        this.keys = new Int32Array(this._capacity).fill(EMPTY);\n        this.lo = new Uint32Array(this._capacity);\n        this.hi = new Uint32Array(this._capacity);\n        this._size = 0;\n\n        for (let i = 0; i < oldCap; i++) {\n            if (oldKeys[i] !== EMPTY) {\n                const s = this.slot(oldKeys[i]);\n                this.keys[s] = oldKeys[i];\n                this.lo[s] = oldLo[i];\n                this.hi[s] = oldHi[i];\n                this._size++;\n            }\n        }\n    }\n}\n\nexport { BlockMaskMap };\n","import { BlockMaskBuffer } from './block-mask-buffer';\nimport { BlockMaskMap } from './block-mask-map';\n\nconst SOLID_LO = 0xFFFFFFFF >>> 0;\nconst SOLID_HI = 0xFFFFFFFF >>> 0;\n\nconst BLOCK_EMPTY = 0;\nconst BLOCK_SOLID = 1;\nconst BLOCK_MIXED = 2;\n\n// Face bitmasks for the 6 faces of a 4x4x4 block.\n// bitIdx layout: lx + (ly << 2) + (lz << 4), lo = bits 0-31, hi = bits 32-63.\n// Each pair [lo, hi] selects the 16 voxels on one face.\nconst FACE_MASKS_LO = [\n    0x11111111 >>> 0, // -X: lx=0\n    0x88888888 >>> 0, // +X: lx=3\n    0x000F000F >>> 0, // -Y: ly=0\n    0xF000F000 >>> 0, // +Y: ly=3\n    0x0000FFFF >>> 0, // -Z: lz=0\n    0x00000000 >>> 0  // +Z: lz=3\n];\nconst FACE_MASKS_HI = [\n    0x11111111 >>> 0,\n    0x88888888 >>> 0,\n    0x000F000F >>> 0,\n    0xF000F000 >>> 0,\n    0x00000000 >>> 0,\n    0xFFFF0000 >>> 0\n];\n\n// ============================================================================\n// SparseVoxelGrid (packed 2-bit types)\n//\n// Stores voxel data at 4x4x4 block granularity with exact voxel-level\n// precision. The per-block type {EMPTY=0, SOLID=1, MIXED=2} is packed into\n// a single Uint32Array at 2 bits per block (16 blocks per word):\n//\n//   block i  -> word index = i >>> 4, bit shift = (i & 15) << 1\n//   read     -> (types[w] >>> shift) & 0x3\n//   write    -> types[w] = (types[w] & ~(0x3 << shift)) | (value << shift)\n//\n// Per-word patterns:\n//   0x55555555 = all 16 lanes SOLID  (0b01 in each pair)\n//   0xAAAAAAAA = all 16 lanes MIXED  (0b10 in each pair)\n//\n// \"Find non-empty blocks\" iteration uses the trick:\n//   nonEmpty = (word & 0x55555555) | ((word >>> 1) & 0x55555555);\n// which sets bit 2k in `nonEmpty` whenever lane k is non-zero. Iterating\n// the set bits with `clz32(nonEmpty & -nonEmpty)` then yields lane indices\n// the same way the old occupancy bitfield did.\n//\n// MIXED blocks store their lo/hi voxel mask in `masks` keyed on the\n// global block index (bx + by*nbx + bz*bStride).\n//\n// Memory: 2 bits per block, vs 1 byte (blockType) + 1 bit (occupancy)\n// = 9 bits per block in the previous design. ~4.5x reduction on this\n// component.\n// ============================================================================\n\nconst TYPE_BITS_PER_BLOCK = 2;\nconst BLOCKS_PER_WORD = 32 / TYPE_BITS_PER_BLOCK; // 16\nconst TYPE_MASK = (1 << TYPE_BITS_PER_BLOCK) - 1; // 0b11\nconst SOLID_WORD = 0x55555555 >>> 0;             // 16 lanes, each = SOLID\nconst EVEN_BITS = 0x55555555 >>> 0;              // mask for even bit positions\n\n/**\n * Read the 2-bit block type directly from a packed `types` Uint32Array.\n * Module-level so V8 can inline it into hot loops without method dispatch.\n * Equivalent to `grid.getBlockType(blockIdx)` when `types === grid.types`.\n *\n * @param types - Packed types array (16 blocks per word).\n * @param blockIdx - Linear block index.\n * @returns Block type: `BLOCK_EMPTY`, `BLOCK_SOLID`, or `BLOCK_MIXED`.\n */\nconst readBlockType = (types: Uint32Array, blockIdx: number): number => {\n    return (types[blockIdx >>> 4] >>> ((blockIdx & 15) << 1)) & TYPE_MASK;\n};\n\n/**\n * Write the 2-bit block type directly into a packed `types` Uint32Array.\n * Module-level so V8 can inline it into hot loops without method dispatch.\n * Caller is responsible for keeping the grid's `masks` consistent (only\n * `MIXED` blocks should have a mask entry).\n *\n * @param types - Packed types array (16 blocks per word).\n * @param blockIdx - Linear block index.\n * @param value - Block type to set.\n */\nconst writeBlockType = (types: Uint32Array, blockIdx: number, value: number): void => {\n    const w = blockIdx >>> 4;\n    const shift = (blockIdx & 15) << 1;\n    types[w] = ((types[w] & ~(TYPE_MASK << shift)) | ((value & TYPE_MASK) << shift)) >>> 0;\n};\n\nclass SparseVoxelGrid {\n    readonly nx: number;\n    readonly ny: number;\n    readonly nz: number;\n    readonly nbx: number;\n    readonly nby: number;\n    readonly nbz: number;\n    readonly bStride: number;\n\n    /**\n     * Packed block types: 2 bits per block, 16 blocks per Uint32 word.\n     * Length = ceil(totalBlocks / 16).\n     */\n    types: Uint32Array;\n\n    /** Voxel masks for MIXED blocks, keyed on global block index. */\n    masks: BlockMaskMap;\n\n    constructor(nx: number, ny: number, nz: number) {\n        this.nx = nx;\n        this.ny = ny;\n        this.nz = nz;\n        this.nbx = nx >> 2;\n        this.nby = ny >> 2;\n        this.nbz = nz >> 2;\n        this.bStride = this.nbx * this.nby;\n        const totalBlocks = this.nbx * this.nby * this.nbz;\n        this.types = new Uint32Array((totalBlocks + BLOCKS_PER_WORD - 1) >>> 4);\n        this.masks = new BlockMaskMap();\n    }\n\n    /**\n     * Read the 2-bit block type at the given block index.\n     *\n     * @param blockIdx - Linear block index (`bx + by*nbx + bz*bStride`).\n     * @returns Block type: `BLOCK_EMPTY`, `BLOCK_SOLID`, or `BLOCK_MIXED`.\n     */\n    getBlockType(blockIdx: number): number {\n        return readBlockType(this.types, blockIdx);\n    }\n\n    /**\n     * Write the 2-bit block type at the given block index. Caller is\n     * responsible for keeping `masks` consistent (only `MIXED` blocks\n     * should have a mask entry; `EMPTY`/`SOLID` should not).\n     *\n     * @param blockIdx - Linear block index.\n     * @param value - Block type to set.\n     */\n    setBlockType(blockIdx: number, value: number): void {\n        writeBlockType(this.types, blockIdx, value);\n    }\n\n    getVoxel(ix: number, iy: number, iz: number): number {\n        const blockIdx = (ix >> 2) + (iy >> 2) * this.nbx + (iz >> 2) * this.bStride;\n        const bt = this.getBlockType(blockIdx);\n        if (bt === BLOCK_EMPTY) return 0;\n        if (bt === BLOCK_SOLID) return 1;\n        const s = this.masks.slot(blockIdx);\n        const bitIdx = (ix & 3) + ((iy & 3) << 2) + ((iz & 3) << 4);\n        return bitIdx < 32 ? (this.masks.lo[s] >>> bitIdx) & 1 : (this.masks.hi[s] >>> (bitIdx - 32)) & 1;\n    }\n\n    setVoxel(ix: number, iy: number, iz: number): void {\n        const blockIdx = (ix >> 2) + (iy >> 2) * this.nbx + (iz >> 2) * this.bStride;\n        const bt = this.getBlockType(blockIdx);\n        if (bt === BLOCK_SOLID) return;\n        const bitIdx = (ix & 3) + ((iy & 3) << 2) + ((iz & 3) << 4);\n        if (bt === BLOCK_MIXED) {\n            const s = this.masks.slot(blockIdx);\n            if (bitIdx < 32) this.masks.lo[s] = (this.masks.lo[s] | (1 << bitIdx)) >>> 0;\n            else this.masks.hi[s] = (this.masks.hi[s] | (1 << (bitIdx - 32))) >>> 0;\n            if (this.masks.lo[s] === SOLID_LO && this.masks.hi[s] === SOLID_HI) {\n                this.masks.removeAt(s);\n                this.setBlockType(blockIdx, BLOCK_SOLID);\n            }\n        } else {\n            this.setBlockType(blockIdx, BLOCK_MIXED);\n            this.masks.set(blockIdx,\n                bitIdx < 32 ? (1 << bitIdx) >>> 0 : 0,\n                bitIdx >= 32 ? (1 << (bitIdx - 32)) >>> 0 : 0\n            );\n        }\n    }\n\n    orBlock(blockIdx: number, lo: number, hi: number): void {\n        if (lo === 0 && hi === 0) return;\n        const bt = this.getBlockType(blockIdx);\n        if (bt === BLOCK_SOLID) return;\n        if (bt === BLOCK_MIXED) {\n            const s = this.masks.slot(blockIdx);\n            this.masks.lo[s] = (this.masks.lo[s] | lo) >>> 0;\n            this.masks.hi[s] = (this.masks.hi[s] | hi) >>> 0;\n            if (this.masks.lo[s] === SOLID_LO && this.masks.hi[s] === SOLID_HI) {\n                this.masks.removeAt(s);\n                this.setBlockType(blockIdx, BLOCK_SOLID);\n            }\n        } else {\n            if ((lo >>> 0) === SOLID_LO && (hi >>> 0) === SOLID_HI) {\n                this.setBlockType(blockIdx, BLOCK_SOLID);\n            } else {\n                this.setBlockType(blockIdx, BLOCK_MIXED);\n                this.masks.set(blockIdx, lo >>> 0, hi >>> 0);\n            }\n        }\n    }\n\n    clear(): void {\n        this.types.fill(0);\n        this.masks.clear();\n    }\n\n    /**\n     * Release the large backing arrays once a grid has been consumed.\n     */\n    releaseStorage(): void {\n        this.types = new Uint32Array(0);\n        this.masks.releaseStorage();\n    }\n\n    clone(): SparseVoxelGrid {\n        const g = new SparseVoxelGrid(this.nx, this.ny, this.nz);\n        g.types.set(this.types);\n        g.masks = this.masks.clone();\n        return g;\n    }\n\n    static fromBuffer(\n        acc: BlockMaskBuffer,\n        nx: number, ny: number, nz: number,\n        onProgress?: (done: number, total: number) => void\n    ): SparseVoxelGrid {\n        const g = new SparseVoxelGrid(nx, ny, nz);\n        const solidIdx = acc.getSolidBlocks();\n        const mixed = acc.getMixedBlocks();\n        const total = solidIdx.length + mixed.blockIdx.length;\n        const PROGRESS_INTERVAL = 1 << 16;\n        let nextTick = PROGRESS_INTERVAL;\n        for (let i = 0; i < solidIdx.length; i++) {\n            g.setBlockType(solidIdx[i], BLOCK_SOLID);\n            if (onProgress && i + 1 >= nextTick) {\n                onProgress(i + 1, total);\n                nextTick = i + 1 + PROGRESS_INTERVAL;\n            }\n        }\n        const baseMixed = solidIdx.length;\n        for (let i = 0; i < mixed.blockIdx.length; i++) {\n            const blockIdx = mixed.blockIdx[i];\n            g.setBlockType(blockIdx, BLOCK_MIXED);\n            g.masks.set(blockIdx, mixed.masks[i * 2], mixed.masks[i * 2 + 1]);\n            const done = baseMixed + i + 1;\n            if (onProgress && done >= nextTick) {\n                onProgress(done, total);\n                nextTick = done + PROGRESS_INTERVAL;\n            }\n        }\n        if (onProgress) onProgress(total, total);\n        return g;\n    }\n\n    toBuffer(\n        cropMinBx: number, cropMinBy: number, cropMinBz: number,\n        cropMaxBx: number, cropMaxBy: number, cropMaxBz: number,\n        onProgress?: (done: number, total: number) => void\n    ): BlockMaskBuffer {\n        const acc = new BlockMaskBuffer();\n        const outNbx = cropMaxBx - cropMinBx;\n        const outNby = cropMaxBy - cropMinBy;\n        const outBStride = outNbx * outNby;\n        const totalZ = cropMaxBz - cropMinBz;\n        for (let bz = cropMinBz; bz < cropMaxBz; bz++) {\n            if (onProgress) onProgress(bz - cropMinBz, totalZ);\n            for (let by = cropMinBy; by < cropMaxBy; by++) {\n                for (let bx = cropMinBx; bx < cropMaxBx; bx++) {\n                    const blockIdx = bx + by * this.nbx + bz * this.bStride;\n                    const bt = this.getBlockType(blockIdx);\n                    let lo: number, hi: number;\n                    if (bt === BLOCK_SOLID) {\n                        lo = SOLID_LO;\n                        hi = SOLID_HI;\n                    } else if (bt === BLOCK_MIXED) {\n                        const s = this.masks.slot(blockIdx);\n                        lo = this.masks.lo[s];\n                        hi = this.masks.hi[s];\n                    } else {\n                        continue;\n                    }\n                    if (lo || hi) {\n                        const outIdx = (bx - cropMinBx) +\n                            (by - cropMinBy) * outNbx +\n                            (bz - cropMinBz) * outBStride;\n                        acc.addBlock(outIdx, lo, hi);\n                    }\n                }\n            }\n        }\n        if (onProgress) onProgress(totalZ, totalZ);\n        return acc;\n    }\n\n    /**\n     * Crop this grid to a block-aligned sub-region. Returns a fresh grid of\n     * size `(cropMaxBx-cropMinBx)*4 x (cropMaxBy-cropMinBy)*4 x (cropMaxBz-cropMinBz)*4`\n     * containing the same data with origin shifted to (cropMinBx, cropMinBy, cropMinBz).\n     *\n     * Iterates only non-empty blocks of the source via word-level skipping.\n     *\n     * @param cropMinBx - Min block X (inclusive).\n     * @param cropMinBy - Min block Y (inclusive).\n     * @param cropMinBz - Min block Z (inclusive).\n     * @param cropMaxBx - Max block X (exclusive).\n     * @param cropMaxBy - Max block Y (exclusive).\n     * @param cropMaxBz - Max block Z (exclusive).\n     * @param onProgress - Optional progress callback over source `types` words.\n     * @returns Newly allocated cropped grid.\n     */\n    cropTo(\n        cropMinBx: number, cropMinBy: number, cropMinBz: number,\n        cropMaxBx: number, cropMaxBy: number, cropMaxBz: number,\n        onProgress?: (done: number, total: number) => void\n    ): SparseVoxelGrid {\n        const outNbx = cropMaxBx - cropMinBx;\n        const outNby = cropMaxBy - cropMinBy;\n        const outNbz = cropMaxBz - cropMinBz;\n        const out = new SparseVoxelGrid(outNbx * 4, outNby * 4, outNbz * 4);\n        const outBStride = outNbx * outNby;\n        const { nbx, nby } = this;\n        const totalBlocks = nbx * nby * this.nbz;\n        const types = this.types;\n        const masks = this.masks;\n        const outTypes = out.types;\n        const outMasks = out.masks;\n        if (out.nbx * out.nby * out.nbz === 0) {\n            if (onProgress) onProgress(0, 0);\n            return out;\n        }\n\n        const PROGRESS_INTERVAL = 1 << 13;\n        let nextTick = PROGRESS_INTERVAL;\n        for (let w = 0; w < types.length; w++) {\n            if (onProgress && w >= nextTick) {\n                onProgress(w, types.length);\n                nextTick = w + PROGRESS_INTERVAL;\n            }\n            const word = types[w];\n            if (word === 0) continue;\n            let nonEmpty = ((word & EVEN_BITS) | ((word >>> 1) & EVEN_BITS)) >>> 0;\n            const baseIdx = w * BLOCKS_PER_WORD;\n            let bx = baseIdx % nbx;\n            const byBz = (baseIdx / nbx) | 0;\n            let by = byBz % nby;\n            let bz = (byBz / nby) | 0;\n            let coordLane = 0;\n            while (nonEmpty) {\n                const bp = 31 - Math.clz32(nonEmpty & -nonEmpty);\n                const lane = bp >>> 1;\n                nonEmpty &= nonEmpty - 1;\n                const blockIdx = baseIdx + lane;\n                if (blockIdx >= totalBlocks) break;\n                bx += lane - coordLane;\n                coordLane = lane;\n                while (bx >= nbx) {\n                    bx -= nbx;\n                    by++;\n                    if (by >= nby) {\n                        by = 0;\n                        bz++;\n                    }\n                }\n                if (bx < cropMinBx || bx >= cropMaxBx ||\n                    by < cropMinBy || by >= cropMaxBy ||\n                    bz < cropMinBz || bz >= cropMaxBz) continue;\n                const outIdx = (bx - cropMinBx) +\n                    (by - cropMinBy) * outNbx +\n                    (bz - cropMinBz) * outBStride;\n                const bt = (word >>> (lane << 1)) & TYPE_MASK;\n                writeBlockType(outTypes, outIdx, bt);\n                if (bt === BLOCK_MIXED) {\n                    const s = masks.slot(blockIdx);\n                    outMasks.set(outIdx, masks.lo[s], masks.hi[s]);\n                }\n            }\n        }\n        if (onProgress) onProgress(types.length, types.length);\n        return out;\n    }\n\n    /**\n     * Crop this grid to a sub-region with inverted occupancy: source EMPTY\n     * becomes destination SOLID, source SOLID becomes destination EMPTY,\n     * source MIXED becomes destination MIXED with bitwise-inverted mask.\n     *\n     * The destination grid has dimensions matching the crop window. Used by\n     * carve to flip the navigable region (1=navigable) into the runtime's\n     * occupancy convention (1=blocked).\n     *\n     * Note: cropping the EMPTY-becomes-SOLID region is exact within the crop\n     * window only. Since the source grid's EMPTY blocks become SOLID in the\n     * output, the output's `types` for empty blocks must be set rather than\n     * left at their default. We therefore initialize the entire output to\n     * SOLID (word fill) and then patch any non-EMPTY source blocks.\n     *\n     * @param cropMinBx - Min block X (inclusive).\n     * @param cropMinBy - Min block Y (inclusive).\n     * @param cropMinBz - Min block Z (inclusive).\n     * @param cropMaxBx - Max block X (exclusive).\n     * @param cropMaxBy - Max block Y (exclusive).\n     * @param cropMaxBz - Max block Z (exclusive).\n     * @param onProgress - Optional progress callback over source `types` words.\n     * @returns Newly allocated cropped + inverted grid.\n     */\n    cropToInverted(\n        cropMinBx: number, cropMinBy: number, cropMinBz: number,\n        cropMaxBx: number, cropMaxBy: number, cropMaxBz: number,\n        onProgress?: (done: number, total: number) => void\n    ): SparseVoxelGrid {\n        const outNbx = cropMaxBx - cropMinBx;\n        const outNby = cropMaxBy - cropMinBy;\n        const outNbz = cropMaxBz - cropMinBz;\n        const out = new SparseVoxelGrid(outNbx * 4, outNby * 4, outNbz * 4);\n        const outBStride = outNbx * outNby;\n        const outTotalBlocks = outNbx * outNby * outNbz;\n        const outTypes = out.types;\n        const outMasks = out.masks;\n        if (outTotalBlocks === 0) {\n            if (onProgress) onProgress(0, 0);\n            return out;\n        }\n\n        // Default the output to SOLID everywhere (matches the source-EMPTY case).\n        // Trim trailing lanes past totalBlocks back to EMPTY.\n        outTypes.fill(SOLID_WORD);\n        const lastWord = outTypes.length - 1;\n        const lastLanes = outTotalBlocks - lastWord * BLOCKS_PER_WORD;\n        if (lastLanes < BLOCKS_PER_WORD) {\n            const validBits = (1 << (lastLanes * 2)) - 1;\n            outTypes[lastWord] = (outTypes[lastWord] & validBits) >>> 0;\n        }\n\n        // Now overwrite any non-EMPTY source block within the crop window.\n        const { nbx, nby } = this;\n        const types = this.types;\n        const masks = this.masks;\n        const totalBlocks = nbx * nby * this.nbz;\n        const PROGRESS_INTERVAL = 1 << 13;\n        let nextTick = PROGRESS_INTERVAL;\n        for (let w = 0; w < types.length; w++) {\n            if (onProgress && w >= nextTick) {\n                onProgress(w, types.length);\n                nextTick = w + PROGRESS_INTERVAL;\n            }\n            const word = types[w];\n            if (word === 0) continue;\n            let nonEmpty = ((word & EVEN_BITS) | ((word >>> 1) & EVEN_BITS)) >>> 0;\n            const baseIdx = w * BLOCKS_PER_WORD;\n            let bx = baseIdx % nbx;\n            const byBz = (baseIdx / nbx) | 0;\n            let by = byBz % nby;\n            let bz = (byBz / nby) | 0;\n            let coordLane = 0;\n            while (nonEmpty) {\n                const bp = 31 - Math.clz32(nonEmpty & -nonEmpty);\n                const lane = bp >>> 1;\n                nonEmpty &= nonEmpty - 1;\n                const blockIdx = baseIdx + lane;\n                if (blockIdx >= totalBlocks) break;\n                bx += lane - coordLane;\n                coordLane = lane;\n                while (bx >= nbx) {\n                    bx -= nbx;\n                    by++;\n                    if (by >= nby) {\n                        by = 0;\n                        bz++;\n                    }\n                }\n                if (bx < cropMinBx || bx >= cropMaxBx ||\n                    by < cropMinBy || by >= cropMaxBy ||\n                    bz < cropMinBz || bz >= cropMaxBz) continue;\n                const outIdx = (bx - cropMinBx) +\n                    (by - cropMinBy) * outNbx +\n                    (bz - cropMinBz) * outBStride;\n                const bt = (word >>> (lane << 1)) & TYPE_MASK;\n                if (bt === BLOCK_SOLID) {\n                    // Source SOLID → dest EMPTY (overwrite the SOLID default).\n                    writeBlockType(outTypes, outIdx, BLOCK_EMPTY);\n                } else {\n                    // Source MIXED → dest MIXED with inverted mask.\n                    writeBlockType(outTypes, outIdx, BLOCK_MIXED);\n                    const s = masks.slot(blockIdx);\n                    outMasks.set(outIdx, (~masks.lo[s]) >>> 0, (~masks.hi[s]) >>> 0);\n                }\n            }\n        }\n        if (onProgress) onProgress(types.length, types.length);\n        return out;\n    }\n\n    /**\n     * Get the bounding box of occupied blocks.\n     *\n     * @param onProgress - Optional progress callback over `types` words.\n     * @returns Block coordinate bounds, or null if no blocks are occupied.\n     */\n    getOccupiedBlockBounds(\n        onProgress?: (done: number, total: number) => void\n    ): {\n        minBx: number; minBy: number; minBz: number;\n        maxBx: number; maxBy: number; maxBz: number;\n    } | null {\n        const { nbx, nby } = this;\n        const totalBlocks = nbx * nby * this.nbz;\n        let minBx = nbx, minBy = nby, minBz = this.nbz;\n        let maxBx = 0, maxBy = 0, maxBz = 0;\n        let found = false;\n        const PROGRESS_INTERVAL = 1 << 13;\n        let nextTick = PROGRESS_INTERVAL;\n        for (let w = 0; w < this.types.length; w++) {\n            if (onProgress && w >= nextTick) {\n                onProgress(w, this.types.length);\n                nextTick = w + PROGRESS_INTERVAL;\n            }\n            const word = this.types[w];\n            if (word === 0) continue;\n            // Set bit at even position 2k iff lane k is non-empty.\n            let nonEmpty = ((word & EVEN_BITS) | ((word >>> 1) & EVEN_BITS)) >>> 0;\n            const baseIdx = w * BLOCKS_PER_WORD;\n            let bx = baseIdx % nbx;\n            const byBz = (baseIdx / nbx) | 0;\n            let by = byBz % nby;\n            let bz = (byBz / nby) | 0;\n            let coordLane = 0;\n            while (nonEmpty) {\n                const bp = 31 - Math.clz32(nonEmpty & -nonEmpty);\n                const lane = bp >>> 1;\n                const blockIdx = baseIdx + lane;\n                if (blockIdx >= totalBlocks) {\n                    nonEmpty = 0;\n                    break;\n                }\n                bx += lane - coordLane;\n                coordLane = lane;\n                while (bx >= nbx) {\n                    bx -= nbx;\n                    by++;\n                    if (by >= nby) {\n                        by = 0;\n                        bz++;\n                    }\n                }\n                if (bx < minBx) minBx = bx;\n                if (bx > maxBx) maxBx = bx;\n                if (by < minBy) minBy = by;\n                if (by > maxBy) maxBy = by;\n                if (bz < minBz) minBz = bz;\n                if (bz > maxBz) maxBz = bz;\n                found = true;\n                nonEmpty &= nonEmpty - 1;\n            }\n        }\n        if (onProgress) onProgress(this.types.length, this.types.length);\n        return found ? { minBx, minBy, minBz, maxBx, maxBy, maxBz } : null;\n    }\n\n    /**\n     * Get the bounding box of navigable (non-fully-solid) blocks. A block is\n     * navigable if it is EMPTY or MIXED (i.e. contains at least one empty\n     * voxel). Useful when the runtime treats out-of-grid as solid, so fully\n     * solid blocks beyond the navigable region can be cropped away.\n     *\n     * @param onProgress - Optional progress callback over `types` words.\n     * @returns Block coordinate bounds, or null if every block is solid.\n     */\n    getNavigableBlockBounds(\n        onProgress?: (done: number, total: number) => void\n    ): {\n        minBx: number; minBy: number; minBz: number;\n        maxBx: number; maxBy: number; maxBz: number;\n    } | null {\n        const { nbx, nby } = this;\n        const totalBlocks = nbx * nby * this.nbz;\n        if (totalBlocks === 0) {\n            if (onProgress) onProgress(0, 0);\n            return null;\n        }\n        // Mask of valid lanes in the last word (in terms of even bit positions).\n        const lastWordIdx = this.types.length - 1;\n        const lastLanes = totalBlocks - lastWordIdx * BLOCKS_PER_WORD;\n        // navMask in the last word: only the first `lastLanes` lanes are valid;\n        // each lane occupies 2 bits, so the valid even-bit mask spans\n        // 2 * lastLanes bits.\n        const lastNonEmptyMask = lastLanes >= BLOCKS_PER_WORD ?\n            EVEN_BITS :\n            (((1 << (lastLanes * 2)) - 1) >>> 0) & EVEN_BITS;\n\n        let minBx = nbx, minBy = nby, minBz = this.nbz;\n        let maxBx = -1, maxBy = 0, maxBz = 0;\n\n        const PROGRESS_INTERVAL = 1 << 13;\n        let nextTick = PROGRESS_INTERVAL;\n        for (let w = 0; w < this.types.length; w++) {\n            if (onProgress && w >= nextTick) {\n                onProgress(w, this.types.length);\n                nextTick = w + PROGRESS_INTERVAL;\n            }\n            const word = this.types[w];\n            // Lane is non-SOLID iff its 2 bits aren't (1, 0) i.e. iff\n            // word ^ SOLID_WORD has any bit set in that pair.\n            const flipped = (word ^ SOLID_WORD) >>> 0;\n            let navMask = ((flipped & EVEN_BITS) | ((flipped >>> 1) & EVEN_BITS)) >>> 0;\n            // For the final (possibly partial) word, drop lanes past totalBlocks.\n            if (w === lastWordIdx) navMask &= lastNonEmptyMask;\n\n            const baseIdx = w * BLOCKS_PER_WORD;\n            let bx = baseIdx % nbx;\n            const byBz = (baseIdx / nbx) | 0;\n            let by = byBz % nby;\n            let bz = (byBz / nby) | 0;\n            let coordLane = 0;\n            while (navMask) {\n                const bp = 31 - Math.clz32(navMask & -navMask);\n                const lane = bp >>> 1;\n                bx += lane - coordLane;\n                coordLane = lane;\n                while (bx >= nbx) {\n                    bx -= nbx;\n                    by++;\n                    if (by >= nby) {\n                        by = 0;\n                        bz++;\n                    }\n                }\n                if (bx < minBx) minBx = bx;\n                if (bx > maxBx) maxBx = bx;\n                if (by < minBy) minBy = by;\n                if (by > maxBy) maxBy = by;\n                if (bz < minBz) minBz = bz;\n                if (bz > maxBz) maxBz = bz;\n                navMask &= navMask - 1;\n            }\n        }\n\n        if (onProgress) onProgress(this.types.length, this.types.length);\n        return maxBx >= 0 ? { minBx, minBy, minBz, maxBx, maxBy, maxBz } : null;\n    }\n\n    /**\n     * Find the nearest free (unblocked) voxel to a seed position using\n     * expanding cube shells.\n     *\n     * @param blocked - Grid to search for free cells in.\n     * @param seedIx - Seed voxel X coordinate.\n     * @param seedIy - Seed voxel Y coordinate.\n     * @param seedIz - Seed voxel Z coordinate.\n     * @param maxRadius - Maximum search radius in voxels.\n     * @returns Coordinates of the nearest free voxel, or null.\n     */\n    static findNearestFreeCell(\n        blocked: SparseVoxelGrid,\n        seedIx: number, seedIy: number, seedIz: number,\n        maxRadius: number\n    ): { ix: number; iy: number; iz: number } | null {\n        const { nx, ny, nz } = blocked;\n        for (let r = 1; r <= maxRadius; r++) {\n            for (let dz = -r; dz <= r; dz++) {\n                for (let dy = -r; dy <= r; dy++) {\n                    for (let dx = -r; dx <= r; dx++) {\n                        if (Math.abs(dx) !== r && Math.abs(dy) !== r && Math.abs(dz) !== r) continue;\n                        const ix = seedIx + dx;\n                        const iy = seedIy + dy;\n                        const iz = seedIz + dz;\n                        if (ix < 0 || ix >= nx || iy < 0 || iy >= ny || iz < 0 || iz >= nz) continue;\n                        if (!blocked.getVoxel(ix, iy, iz)) return { ix, iy, iz };\n                    }\n                }\n            }\n        }\n        return null;\n    }\n}\n\nexport {\n    BLOCK_EMPTY,\n    BLOCK_MIXED,\n    BLOCK_SOLID,\n    BLOCKS_PER_WORD,\n    EVEN_BITS,\n    FACE_MASKS_HI,\n    FACE_MASKS_LO,\n    SOLID_HI,\n    SOLID_LO,\n    SOLID_WORD,\n    SparseVoxelGrid,\n    TYPE_MASK,\n    readBlockType,\n    writeBlockType\n};\n","import type { Bounds } from '../data-table';\nimport {\n    BLOCK_EMPTY,\n    BLOCK_SOLID,\n    BLOCKS_PER_WORD,\n    EVEN_BITS,\n    SparseVoxelGrid,\n    readBlockType\n} from '../voxel/sparse-voxel-grid';\n\n/**\n * A simple triangle mesh with positions and indices.\n */\ninterface Mesh {\n    /** Vertex positions (3 floats per vertex) */\n    positions: Float32Array;\n\n    /** Triangle indices (3 indices per triangle) */\n    indices: Uint32Array;\n}\n\n/**\n * Result of marching cubes surface extraction.\n */\ntype MarchingCubesMesh = Mesh;\n\n/**\n * Options for marching cubes extraction.\n */\ninterface MarchingCubesOptions {\n    /**\n     * Pre-merge exact full-face cells on flat axis-aligned regions before\n     * creating the mesh. Ambiguous and bevel cases still use normal marching\n     * cubes, so coplanarMerge can apply the final lossless optimization.\n     */\n    mergeFlatFaces?: boolean;\n}\n\n// ============================================================================\n// Voxel bit helpers\n// ============================================================================\n\n// Bit layout within a 4x4x4 block: bitIdx = lx + ly*4 + lz*16\n// lo = bits 0-31 (lz 0-1), hi = bits 32-63 (lz 2-3)\n\n/**\n * Test whether a voxel is occupied within a block's bitmask.\n *\n * @param lo - Lower 32 bits of the block mask\n * @param hi - Upper 32 bits of the block mask\n * @param lx - Local x coordinate (0-3)\n * @param ly - Local y coordinate (0-3)\n * @param lz - Local z coordinate (0-3)\n * @returns True if the voxel is occupied\n */\nfunction isVoxelSet(lo: number, hi: number, lx: number, ly: number, lz: number): boolean {\n    const bitIdx = lx + ly * 4 + lz * 16;\n    if (bitIdx < 32) {\n        return (lo & (1 << bitIdx)) !== 0;\n    }\n    return (hi & (1 << (bitIdx - 32))) !== 0;\n}\n\n// ============================================================================\n// Marching Cubes\n// ============================================================================\n\n// Sentinel values for the per-block 3x3x3 neighbor table.\nconst NEIGHBOR_EMPTY = -2;\nconst NEIGHBOR_SOLID = -1;\n\n/**\n * Extract a triangle mesh from a SparseVoxelGrid using marching cubes.\n *\n * Each voxel is treated as a cell in the marching cubes grid. Corner values\n * are binary (0 = empty, 1 = occupied) with a 0.5 threshold. Vertices are\n * placed at edge midpoints, producing the binary-field isosurface between\n * occupied and empty samples.\n *\n * @param grid - Voxel grid (after filtering / nav phases)\n * @param gridBounds - Grid bounds aligned to block boundaries\n * @param voxelResolution - Size of each voxel in world units\n * @param options - Optional extraction settings\n * @returns Mesh with positions and indices\n */\nfunction marchingCubes(\n    grid: SparseVoxelGrid,\n    gridBounds: Bounds,\n    voxelResolution: number,\n    options: MarchingCubesOptions = {}\n): MarchingCubesMesh {\n    const { nbx, nby, nbz, bStride, types, masks } = grid;\n    const totalBlocks = nbx * nby * nbz;\n    const mergeFlatFaces = options.mergeFlatFaces === true;\n\n    // Vertex deduplication: edge ID -> vertex index. Open-addressed typed-\n    // array hash table rather than `Map<number, number>` because (1) a single\n    // V8 Map is capped at ~2^24 entries (large carved scenes blow past this),\n    // and (2) per-entry overhead in Map is ~50 bytes vs 12 bytes (Float64 key\n    // + Uint32 value) here, which matters when the table holds tens of\n    // millions of vertices.\n    //\n    // Empty slots are marked with `key === -1` (real keys are non-negative).\n    // Hash uses Fibonacci constant on the lower 32 bits of the key. The same\n    // structure is used for orphan-cell deduplication, where `vVals` is unused.\n    let vCap = 1 << 14;\n    let vMask = vCap - 1;\n    let vSize = 0;\n    let vKeys = new Float64Array(vCap).fill(-1);\n    let vVals = new Uint32Array(vCap);\n\n    const vGrow = (): void => {\n        const oldKeys = vKeys;\n        const oldVals = vVals;\n        const oldCap = vCap;\n        vCap *= 2;\n        vMask = vCap - 1;\n        vKeys = new Float64Array(vCap).fill(-1);\n        vVals = new Uint32Array(vCap);\n        for (let j = 0; j < oldCap; j++) {\n            const k = oldKeys[j];\n            if (k === -1) continue;\n            let i = (Math.imul(k | 0, 0x9E3779B9) >>> 0) & vMask;\n            while (vKeys[i] !== -1) i = (i + 1) & vMask;\n            vKeys[i] = k;\n            vVals[i] = oldVals[j];\n        }\n    };\n\n    let oCap = 1 << 14;\n    let oMask = oCap - 1;\n    let oSize = 0;\n    let oKeys = new Float64Array(oCap).fill(-1);\n\n    const oGrow = (): void => {\n        const oldKeys = oKeys;\n        const oldCap = oCap;\n        oCap *= 2;\n        oMask = oCap - 1;\n        oKeys = new Float64Array(oCap).fill(-1);\n        for (let j = 0; j < oldCap; j++) {\n            const k = oldKeys[j];\n            if (k === -1) continue;\n            let i = (Math.imul(k | 0, 0x9E3779B9) >>> 0) & oMask;\n            while (oKeys[i] !== -1) i = (i + 1) & oMask;\n            oKeys[i] = k;\n        }\n    };\n\n    // Growable typed-array buffers. Capacity doubles on demand to avoid\n    // the GC churn of pushing into JS number[] for huge meshes.\n    let posCap = 1024;\n    let posLen = 0;\n    let positions = new Float32Array(posCap);\n    let idxCap = 1024;\n    let idxLen = 0;\n    let indices = new Uint32Array(idxCap);\n\n    const originX = gridBounds.min.x;\n    const originY = gridBounds.min.y;\n    const originZ = gridBounds.min.z;\n\n    const gridNx = Math.round((gridBounds.max.x - gridBounds.min.x) / voxelResolution);\n    const gridNy = Math.round((gridBounds.max.y - gridBounds.min.y) / voxelResolution);\n    const gridNz = Math.round((gridBounds.max.z - gridBounds.min.z) / voxelResolution);\n\n    // Compute strides from actual grid dimensions (+3 for the -1 boundary\n    // extension, the far edge +1, and one extra for safety).\n    const strideX = gridNx + 3;\n    const strideXY = strideX * (gridNy + 3);\n    const scaledCoordStride = (Math.max(gridNx, gridNy, gridNz) + 3) * 2 + 5;\n    const scaledCoordOffset = 3;\n\n    // Per-block 3x3x3 neighbor lookup table populated once per processed block.\n    // Index = (dx+1) + (dy+1)*3 + (dz+1)*9, dx/dy/dz in {-1, 0, 1}.\n    // neighborEntry: NEIGHBOR_EMPTY, NEIGHBOR_SOLID, or NEIGHBOR_MIXED (mask in neighborMasks).\n    const NEIGHBOR_MIXED = 0;\n    const neighborEntry = new Int32Array(27);\n    const neighborMasks = new Uint32Array(54);\n\n    // Reused scratch for emitted edge vertex indices.\n    const edgeVerts = new Int32Array(12);\n\n    // Block coordinate of the block currently being processed. Captured by\n    // isOccupiedLocal so it can fold the per-corner block lookup into a\n    // direct typed-array index instead of a hash lookup.\n    let bx = 0, by = 0, bz = 0;\n\n    const isOccupiedLocal = (cx: number, cy: number, cz: number): boolean => {\n        if (cx < 0 || cy < 0 || cz < 0) return false;\n        const idx = ((cx >> 2) - bx + 1) + ((cy >> 2) - by + 1) * 3 + ((cz >> 2) - bz + 1) * 9;\n        const entry = neighborEntry[idx];\n        if (entry === NEIGHBOR_EMPTY) return false;\n        if (entry === NEIGHBOR_SOLID) return true;\n        const lo = neighborMasks[idx * 2];\n        const hi = neighborMasks[idx * 2 + 1];\n        return isVoxelSet(lo, hi, cx & 3, cy & 3, cz & 3);\n    };\n\n    const addPosition = (px: number, py: number, pz: number): number => {\n        if (posLen + 3 > posCap) {\n            posCap *= 2;\n            const grown = new Float32Array(posCap);\n            grown.set(positions);\n            positions = grown;\n        }\n\n        const idx = posLen / 3;\n        positions[posLen++] = px;\n        positions[posLen++] = py;\n        positions[posLen++] = pz;\n        return idx;\n    };\n\n    const ensureIndexCapacity = (additional: number): void => {\n        if (idxLen + additional <= idxCap) return;\n        while (idxLen + additional > idxCap) {\n            idxCap *= 2;\n        }\n        const grown = new Uint32Array(idxCap);\n        grown.set(indices);\n        indices = grown;\n    };\n\n    const appendTri = (a: number, b: number, c: number): void => {\n        ensureIndexCapacity(3);\n        indices[idxLen++] = a;\n        indices[idxLen++] = b;\n        indices[idxLen++] = c;\n    };\n\n    // When flat MC face cells are merged into large rectangles, rectangle\n    // boundaries must still be split at any neighbouring raw-MC vertex that\n    // lies along the same edge. Otherwise the pre-merged mesh can contain\n    // T-junctions before the final coplanarMerge pass. Coordinates here use\n    // the exact binary-MC half-grid: voxel corners are even, MC edge\n    // midpoints are odd on the crossed edge axis.\n    const splitLinePoints = mergeFlatFaces ? new Map<number, number[]>() : undefined;\n    let collectSplitPoints = mergeFlatFaces;\n\n    const splitLineKey = (varAxis: number, x2: number, y2: number, z2: number): number => {\n        const x = x2 + scaledCoordOffset;\n        const y = y2 + scaledCoordOffset;\n        const z = z2 + scaledCoordOffset;\n        if (varAxis === 0) return (y * scaledCoordStride + z) * 3;\n        if (varAxis === 1) return (x * scaledCoordStride + z) * 3 + 1;\n        return (x * scaledCoordStride + y) * 3 + 2;\n    };\n\n    const addSplitLinePoint = (key: number, value: number): void => {\n        if (!splitLinePoints) return;\n        let points = splitLinePoints.get(key);\n        if (!points) {\n            points = [];\n            splitLinePoints.set(key, points);\n        }\n        points.push(value);\n    };\n\n    const addSplitPointForVertex = (vx: number, vy: number, vz: number, axis: number): void => {\n        if (!splitLinePoints || !collectSplitPoints) return;\n        const x2 = vx * 2 + (axis === 0 ? 1 : 0);\n        const y2 = vy * 2 + (axis === 1 ? 1 : 0);\n        const z2 = vz * 2 + (axis === 2 ? 1 : 0);\n\n        addSplitLinePoint(splitLineKey(0, x2, y2, z2), x2);\n        addSplitLinePoint(splitLineKey(1, x2, y2, z2), y2);\n        addSplitLinePoint(splitLineKey(2, x2, y2, z2), z2);\n    };\n\n    // Get or create a vertex at the midpoint of an edge.\n    // Edge is identified by the lower corner voxel coordinate and axis (0=x, 1=y, 2=z).\n    const getVertex = (vx: number, vy: number, vz: number, axis: number): number => {\n        // Pack (vx, vy, vz, axis) into a single key. Offset by 1 so that\n        // vx = -1 (from the boundary extension) maps to 0, keeping keys non-negative.\n        const key = ((vx + 1) + (vy + 1) * strideX + (vz + 1) * strideXY) * 3 + axis;\n\n        // Probe for either the matching slot or the next empty one.\n        let i = (Math.imul(key | 0, 0x9E3779B9) >>> 0) & vMask;\n        while (true) {\n            const k = vKeys[i];\n            if (k === key) return vVals[i];\n            if (k === -1) break;\n            i = (i + 1) & vMask;\n        }\n\n        let px = originX + vx * voxelResolution;\n        let py = originY + vy * voxelResolution;\n        let pz = originZ + vz * voxelResolution;\n\n        // Place vertex at edge midpoint (binary field -> always at 0.5)\n        if (axis === 0) px += voxelResolution * 0.5;\n        else if (axis === 1) py += voxelResolution * 0.5;\n        else pz += voxelResolution * 0.5;\n\n        const idx = addPosition(px, py, pz);\n        addSplitPointForVertex(vx, vy, vz, axis);\n        vKeys[i] = key;\n        vVals[i] = idx;\n        vSize++;\n        if (vSize > ((vCap * 0.7) | 0)) vGrow();\n        return idx;\n    };\n\n    // Full-face MC cases can be merged before vertex creation. Encode each\n    // unit face cell as a sortable integer in Float64: bucket / plane / u / v,\n    // where bucket = axis*2 + positiveNormalBit and coordinates are offset by\n    // +1 to cover the -1 boundary extension.\n    const faceCoordStride = Math.max(gridNx, gridNy, gridNz) + 3;\n    let faceCellCap = 0;\n    let faceCellLen = 0;\n    let faceCellKeys = new Float64Array(0);\n    const diagCoordStride = (Math.max(gridNx, gridNy, gridNz) + 3) * 8 + 9;\n    const diagCoordOffset = Math.floor(diagCoordStride / 2);\n    let diagCellCap = 0;\n    let diagCellLen = 0;\n    let diagCellKeys = new Float64Array(0);\n\n    const addFaceCell = (bucket: number, p: number, u: number, v: number): void => {\n        if (faceCellLen === faceCellCap) {\n            faceCellCap = faceCellCap === 0 ? 1024 : faceCellCap * 2;\n            const grown = new Float64Array(faceCellCap);\n            grown.set(faceCellKeys);\n            faceCellKeys = grown;\n        }\n        faceCellKeys[faceCellLen++] =\n            (((bucket * faceCoordStride + (p + 1)) * faceCoordStride + (u + 1)) *\n                faceCoordStride + (v + 1));\n    };\n\n    const addDiagCell = (bucket: number, plane: number, u: number, e: number): void => {\n        if (diagCellLen === diagCellCap) {\n            diagCellCap = diagCellCap === 0 ? 1024 : diagCellCap * 2;\n            const grown = new Float64Array(diagCellCap);\n            grown.set(diagCellKeys);\n            diagCellKeys = grown;\n        }\n        diagCellKeys[diagCellLen++] =\n            (((bucket * diagCoordStride + (plane + diagCoordOffset)) * diagCoordStride +\n                (u + diagCoordOffset)) * diagCoordStride + (e + diagCoordOffset));\n    };\n\n    const collectFlatFace = (cubeIndex: number, vx: number, vy: number, vz: number): boolean => {\n        if (!mergeFlatFaces) return false;\n\n        switch (cubeIndex) {\n            case 153: // low-X corners occupied, high-X corners empty => +X normal\n                addFaceCell(1, vx, vy, vz);\n                return true;\n            case 102: // high-X occupied => -X normal\n                addFaceCell(0, vx, vy, vz);\n                return true;\n            case 51: // low-Y occupied => +Y normal\n                addFaceCell(3, vy, vx, vz);\n                return true;\n            case 204: // high-Y occupied => -Y normal\n                addFaceCell(2, vy, vx, vz);\n                return true;\n            case 15: // low-Z occupied => +Z normal\n                addFaceCell(5, vz, vx, vy);\n                return true;\n            case 240: // high-Z occupied => -Z normal\n                addFaceCell(4, vz, vx, vy);\n                return true;\n            default:\n                return false;\n        }\n    };\n\n    const scaledFacePoint = (axis: number, p: number, u: number, v: number): [number, number, number] => {\n        if (axis === 0) return [p * 2 + 1, u * 2, v * 2];\n        if (axis === 1) return [u * 2, p * 2 + 1, v * 2];\n        return [u * 2, v * 2, p * 2 + 1];\n    };\n\n    const diagBucket = (axisA: number, axisB: number, signA: number, signB: number): number => {\n        const pair = axisA === 0 ? (axisB === 1 ? 0 : 1) : 2;\n        const signBits = (signA > 0 ? 1 : 0) | (signB > 0 ? 2 : 0);\n        return pair * 4 + signBits;\n    };\n\n    const decodeDiagBucket = (bucket: number): {\n        axisA: number;\n        axisB: number;\n        axisE: number;\n        signA: number;\n        signB: number;\n    } => {\n        const pair = (bucket / 4) | 0;\n        const signBits = bucket & 3;\n        const signA = (signBits & 1) !== 0 ? 1 : -1;\n        const signB = (signBits & 2) !== 0 ? 1 : -1;\n        if (pair === 0) return { axisA: 0, axisB: 1, axisE: 2, signA, signB };\n        if (pair === 1) return { axisA: 0, axisB: 2, axisE: 1, signA, signB };\n        return { axisA: 1, axisB: 2, axisE: 0, signA, signB };\n    };\n\n    const coordByAxis = (x: number, y: number, z: number, axis: number): number => {\n        if (axis === 0) return x;\n        if (axis === 1) return y;\n        return z;\n    };\n\n    const diagPoint = (bucket: number, plane: number, u: number, e: number): [number, number, number] => {\n        const { axisA, axisB, axisE, signA, signB } = decodeDiagBucket(bucket);\n        const out = [0, 0, 0];\n        out[axisA] = signA * ((plane + u) / 2);\n        out[axisB] = signB * ((plane - u) / 2);\n        out[axisE] = e;\n        return [out[0], out[1], out[2]];\n    };\n\n    const edgeScaledPoint = (\n        edge: number,\n        vx: number,\n        vy: number,\n        vz: number,\n        out: Int32Array,\n        offset: number\n    ): void => {\n        const x = vx * 2;\n        const y = vy * 2;\n        const z = vz * 2;\n        switch (edge) {\n            case 0: out[offset] = x + 1; out[offset + 1] = y; out[offset + 2] = z; break;\n            case 1: out[offset] = x + 2; out[offset + 1] = y + 1; out[offset + 2] = z; break;\n            case 2: out[offset] = x + 1; out[offset + 1] = y + 2; out[offset + 2] = z; break;\n            case 3: out[offset] = x; out[offset + 1] = y + 1; out[offset + 2] = z; break;\n            case 4: out[offset] = x + 1; out[offset + 1] = y; out[offset + 2] = z + 2; break;\n            case 5: out[offset] = x + 2; out[offset + 1] = y + 1; out[offset + 2] = z + 2; break;\n            case 6: out[offset] = x + 1; out[offset + 1] = y + 2; out[offset + 2] = z + 2; break;\n            case 7: out[offset] = x; out[offset + 1] = y + 1; out[offset + 2] = z + 2; break;\n            case 8: out[offset] = x; out[offset + 1] = y; out[offset + 2] = z + 1; break;\n            case 9: out[offset] = x + 2; out[offset + 1] = y; out[offset + 2] = z + 1; break;\n            case 10: out[offset] = x + 2; out[offset + 1] = y + 2; out[offset + 2] = z + 1; break;\n            default: out[offset] = x; out[offset + 1] = y + 2; out[offset + 2] = z + 1; break;\n        }\n    };\n\n    const pairVerts = new Int32Array(18);\n    const uniqueVerts = new Int32Array(12);\n\n    const samePoint = (\n        src: Int32Array,\n        a: number,\n        b: number\n    ): boolean => src[a] === src[b] && src[a + 1] === src[b + 1] && src[a + 2] === src[b + 2];\n\n    const pointInUnique = (x: number, y: number, z: number, uniqueCount: number): boolean => {\n        for (let i = 0; i < uniqueCount; i++) {\n            const o = i * 3;\n            if (uniqueVerts[o] === x && uniqueVerts[o + 1] === y && uniqueVerts[o + 2] === z) {\n                return true;\n            }\n        }\n        return false;\n    };\n\n    const collectDiagPair = (\n        triRow: number[],\n        triA: number,\n        triB: number,\n        vx: number,\n        vy: number,\n        vz: number\n    ): boolean => {\n        const edgesA = triA * 3;\n        const edgesB = triB * 3;\n        edgeScaledPoint(triRow[edgesA], vx, vy, vz, pairVerts, 0);\n        edgeScaledPoint(triRow[edgesA + 2], vx, vy, vz, pairVerts, 3);\n        edgeScaledPoint(triRow[edgesA + 1], vx, vy, vz, pairVerts, 6);\n        edgeScaledPoint(triRow[edgesB], vx, vy, vz, pairVerts, 9);\n        edgeScaledPoint(triRow[edgesB + 2], vx, vy, vz, pairVerts, 12);\n        edgeScaledPoint(triRow[edgesB + 1], vx, vy, vz, pairVerts, 15);\n\n        let uniqueCount = 0;\n        for (let i = 0; i < 6; i++) {\n            const src = i * 3;\n            let found = false;\n            for (let j = 0; j < uniqueCount; j++) {\n                const dst = j * 3;\n                if (pairVerts[src] === uniqueVerts[dst] &&\n                    pairVerts[src + 1] === uniqueVerts[dst + 1] &&\n                    pairVerts[src + 2] === uniqueVerts[dst + 2]) {\n                    found = true;\n                    break;\n                }\n            }\n            if (!found) {\n                if (uniqueCount === 4) return false;\n                const dst = uniqueCount * 3;\n                uniqueVerts[dst] = pairVerts[src];\n                uniqueVerts[dst + 1] = pairVerts[src + 1];\n                uniqueVerts[dst + 2] = pairVerts[src + 2];\n                uniqueCount++;\n            }\n        }\n        if (uniqueCount !== 4) return false;\n\n        const ax = pairVerts[3] - pairVerts[0];\n        const ay = pairVerts[4] - pairVerts[1];\n        const az = pairVerts[5] - pairVerts[2];\n        const bx = pairVerts[6] - pairVerts[0];\n        const by = pairVerts[7] - pairVerts[1];\n        const bz = pairVerts[8] - pairVerts[2];\n        const normal = [\n            ay * bz - az * by,\n            az * bx - ax * bz,\n            ax * by - ay * bx\n        ];\n        const absNormal = [Math.abs(normal[0]), Math.abs(normal[1]), Math.abs(normal[2])];\n        let axisE = -1;\n        let axisA = -1;\n        let axisB = -1;\n        for (let i = 0; i < 3; i++) {\n            if (absNormal[i] === 0) axisE = i;\n            else if (axisA === -1) axisA = i;\n            else axisB = i;\n        }\n        if (axisE === -1 || axisA === -1 || axisB === -1) return false;\n        if (absNormal[axisA] !== absNormal[axisB]) return false;\n\n        const signA = normal[axisA] > 0 ? 1 : -1;\n        const signB = normal[axisB] > 0 ? 1 : -1;\n        const bucket = diagBucket(axisA, axisB, signA, signB);\n        const plane = signA * coordByAxis(uniqueVerts[0], uniqueVerts[1], uniqueVerts[2], axisA) +\n            signB * coordByAxis(uniqueVerts[0], uniqueVerts[1], uniqueVerts[2], axisB);\n        let minU = Infinity;\n        let maxU = -Infinity;\n        let minE = Infinity;\n        let maxE = -Infinity;\n        for (let i = 0; i < uniqueCount; i++) {\n            const o = i * 3;\n            const a = coordByAxis(uniqueVerts[o], uniqueVerts[o + 1], uniqueVerts[o + 2], axisA);\n            const b = coordByAxis(uniqueVerts[o], uniqueVerts[o + 1], uniqueVerts[o + 2], axisB);\n            const e = coordByAxis(uniqueVerts[o], uniqueVerts[o + 1], uniqueVerts[o + 2], axisE);\n            if (signA * a + signB * b !== plane) return false;\n            const u = signA * a - signB * b;\n            if (u < minU) minU = u;\n            if (u > maxU) maxU = u;\n            if (e < minE) minE = e;\n            if (e > maxE) maxE = e;\n        }\n        if (maxU - minU !== 2 || maxE - minE !== 2) return false;\n\n        const p00 = diagPoint(bucket, plane, minU, minE);\n        const p10 = diagPoint(bucket, plane, maxU, minE);\n        const p11 = diagPoint(bucket, plane, maxU, maxE);\n        const p01 = diagPoint(bucket, plane, minU, maxE);\n        if (!pointInUnique(p00[0], p00[1], p00[2], uniqueCount) ||\n            !pointInUnique(p10[0], p10[1], p10[2], uniqueCount) ||\n            !pointInUnique(p11[0], p11[1], p11[2], uniqueCount) ||\n            !pointInUnique(p01[0], p01[1], p01[2], uniqueCount)) {\n            return false;\n        }\n\n        let sharedCount = 0;\n        let sharedU0 = 0;\n        let sharedE0 = 0;\n        let sharedU1 = 0;\n        let sharedE1 = 0;\n        for (let i = 0; i < 3; i++) {\n            const oi = i * 3;\n            for (let j = 3; j < 6; j++) {\n                const oj = j * 3;\n                if (!samePoint(pairVerts, oi, oj)) continue;\n                const a = coordByAxis(pairVerts[oi], pairVerts[oi + 1], pairVerts[oi + 2], axisA);\n                const b = coordByAxis(pairVerts[oi], pairVerts[oi + 1], pairVerts[oi + 2], axisB);\n                const e = coordByAxis(pairVerts[oi], pairVerts[oi + 1], pairVerts[oi + 2], axisE);\n                if (sharedCount === 0) {\n                    sharedU0 = signA * a - signB * b;\n                    sharedE0 = e;\n                } else {\n                    sharedU1 = signA * a - signB * b;\n                    sharedE1 = e;\n                }\n                sharedCount++;\n            }\n        }\n        if (sharedCount !== 2 || sharedU0 === sharedU1 || sharedE0 === sharedE1) return false;\n\n        addDiagCell(bucket, plane, minU, minE);\n        return true;\n    };\n\n    const collectDiagFaces = (triRow: number[], vx: number, vy: number, vz: number): number => {\n        if (!mergeFlatFaces) return 0;\n        const triCount = (triRow.length / 3) | 0;\n        let usedMask = 0;\n        for (let i = 0; i < triCount; i++) {\n            if ((usedMask & (1 << i)) !== 0) continue;\n            for (let j = i + 1; j < triCount; j++) {\n                if ((usedMask & (1 << j)) !== 0) continue;\n                if (collectDiagPair(triRow, i, j, vx, vy, vz)) {\n                    usedMask |= (1 << i) | (1 << j);\n                    break;\n                }\n            }\n        }\n        return usedMask;\n    };\n\n    const getScaledVertex = (x2: number, y2: number, z2: number): number => {\n        if ((x2 & 1) !== 0) return getVertex((x2 - 1) / 2, y2 / 2, z2 / 2, 0);\n        if ((y2 & 1) !== 0) return getVertex(x2 / 2, (y2 - 1) / 2, z2 / 2, 1);\n        return getVertex(x2 / 2, y2 / 2, (z2 - 1) / 2, 2);\n    };\n\n    let perimeterScratch = new Uint32Array(16);\n    let perimeterU = new Int32Array(16);\n    let perimeterV = new Int32Array(16);\n    let perimeterLen = 0;\n\n    const localFaceUv = (axis: number, x2: number, y2: number, z2: number): [number, number] => {\n        if (axis === 0) return [y2, z2];\n        if (axis === 1) return [x2, z2];\n        return [x2, y2];\n    };\n\n    const addPerimeterVertex = (vertex: number, u: number, v: number): void => {\n        if (perimeterLen > 0 && perimeterScratch[perimeterLen - 1] === vertex) return;\n        if (perimeterLen === perimeterScratch.length) {\n            const grown = new Uint32Array(perimeterScratch.length * 2);\n            grown.set(perimeterScratch);\n            perimeterScratch = grown;\n            const grownU = new Int32Array(perimeterU.length * 2);\n            grownU.set(perimeterU);\n            perimeterU = grownU;\n            const grownV = new Int32Array(perimeterV.length * 2);\n            grownV.set(perimeterV);\n            perimeterV = grownV;\n        }\n        perimeterScratch[perimeterLen] = vertex;\n        perimeterU[perimeterLen] = u;\n        perimeterV[perimeterLen] = v;\n        perimeterLen++;\n    };\n\n    const addPerimeterPoint = (axis: number, x2: number, y2: number, z2: number): void => {\n        const [u, v] = localFaceUv(axis, x2, y2, z2);\n        addPerimeterVertex(getScaledVertex(x2, y2, z2), u, v);\n    };\n\n    const addDiagPerimeterPoint = (bucket: number, x2: number, y2: number, z2: number): void => {\n        const { axisA, axisB, axisE, signA, signB } = decodeDiagBucket(bucket);\n        const a = coordByAxis(x2, y2, z2, axisA);\n        const b = coordByAxis(x2, y2, z2, axisB);\n        const e = coordByAxis(x2, y2, z2, axisE);\n        addPerimeterVertex(getScaledVertex(x2, y2, z2), signA * a - signB * b, e);\n    };\n\n    const addSplitSegment = (\n        x0: number, y0: number, z0: number,\n        x1: number, y1: number, z1: number\n    ): void => {\n        const changes = (x0 !== x1 ? 1 : 0) + (y0 !== y1 ? 1 : 0) + (z0 !== z1 ? 1 : 0);\n        if (changes !== 1) return;\n        if (x0 !== x1) {\n            const key = splitLineKey(0, x0, y0, z0);\n            addSplitLinePoint(key, x0);\n            addSplitLinePoint(key, x1);\n        } else if (y0 !== y1) {\n            const key = splitLineKey(1, x0, y0, z0);\n            addSplitLinePoint(key, y0);\n            addSplitLinePoint(key, y1);\n        } else {\n            const key = splitLineKey(2, x0, y0, z0);\n            addSplitLinePoint(key, z0);\n            addSplitLinePoint(key, z1);\n        }\n    };\n\n    const addSplitEdgeVertices = (\n        axis: number,\n        x0: number, y0: number, z0: number,\n        x1: number, y1: number, z1: number,\n        addPoint: (x2: number, y2: number, z2: number) => void = (px, py, pz) => {\n            addPerimeterPoint(axis, px, py, pz);\n        }\n    ): void => {\n        let varAxis: number;\n        let start: number;\n        let end: number;\n        if (x0 !== x1) {\n            varAxis = 0;\n            start = x0;\n            end = x1;\n        } else if (y0 !== y1) {\n            varAxis = 1;\n            start = y0;\n            end = y1;\n        } else {\n            varAxis = 2;\n            start = z0;\n            end = z1;\n        }\n\n        const points = splitLinePoints?.get(splitLineKey(varAxis, x0, y0, z0));\n        if (!points) return;\n\n        const lo = Math.min(start, end);\n        const hi = Math.max(start, end);\n        const forward = start <= end;\n\n        const emitPoint = (t: number): void => {\n            if (varAxis === 0) addPoint(t, y0, z0);\n            else if (varAxis === 1) addPoint(x0, t, z0);\n            else addPoint(x0, y0, t);\n        };\n\n        if (forward) {\n            for (let i = 0; i < points.length; i++) {\n                const t = points[i];\n                if (t < lo) continue;\n                if (t > hi) break;\n                emitPoint(t);\n            }\n        } else {\n            for (let i = points.length - 1; i >= 0; i--) {\n                const t = points[i];\n                if (t > hi) continue;\n                if (t < lo) break;\n                emitPoint(t);\n            }\n        }\n    };\n\n    const appendOrientedTri = (a: number, b: number, c: number, useLocalCcw: boolean): void => {\n        if (useLocalCcw) appendTri(a, b, c);\n        else appendTri(a, c, b);\n    };\n\n    const appendPerimeterTri = (a: number, b: number, c: number, useLocalCcw: boolean): void => {\n        const abx = perimeterU[b] - perimeterU[a];\n        const aby = perimeterV[b] - perimeterV[a];\n        const acx = perimeterU[c] - perimeterU[a];\n        const acy = perimeterV[c] - perimeterV[a];\n        if (abx * acy - aby * acx <= 0) return;\n        appendOrientedTri(perimeterScratch[a], perimeterScratch[b], perimeterScratch[c], useLocalCcw);\n    };\n\n    const triangulateTwoSideChain = (\n        chainAStart: number,\n        chainAEnd: number,\n        chainBStart: number,\n        chainBEnd: number,\n        useLocalCcw: boolean\n    ): void => {\n        const chainALen = chainAEnd - chainAStart;\n        const chainBLen = chainBEnd - chainBStart;\n        if (chainALen < 2 || chainBLen < 2) return;\n\n        const v2 = chainBEnd - 1;\n        for (let i = chainAStart; i < chainAEnd - 2; i++) {\n            appendPerimeterTri(v2, i, i + 1, useLocalCcw);\n        }\n\n        const pivot = chainALen > 1 ? chainAEnd - 2 : chainAStart;\n        for (let i = chainBStart; i < chainBEnd - 1; i++) {\n            appendPerimeterTri(pivot, i, i + 1, useLocalCcw);\n        }\n    };\n\n    const emitFaceRectangle = (\n        bucket: number,\n        p: number,\n        u0: number,\n        v0: number,\n        u1: number,\n        v1: number\n    ): void => {\n        const axis = bucket >> 1;\n        const positive = (bucket & 1) === 1;\n        const a = scaledFacePoint(axis, p, u0, v0);\n        const b = scaledFacePoint(axis, p, u1, v0);\n        const c = scaledFacePoint(axis, p, u1, v1);\n        const d = scaledFacePoint(axis, p, u0, v1);\n\n        perimeterLen = 0;\n        const side0Start = 0;\n        addSplitEdgeVertices(axis, a[0], a[1], a[2], b[0], b[1], b[2]);\n        const side0End = perimeterLen;\n        const side1Start = side0End - 1;\n        addSplitEdgeVertices(axis, b[0], b[1], b[2], c[0], c[1], c[2]);\n        const side1End = perimeterLen;\n        const side2Start = side1End - 1;\n        addSplitEdgeVertices(axis, c[0], c[1], c[2], d[0], d[1], d[2]);\n        const side2End = perimeterLen;\n        const side3Start = side2End - 1;\n        addSplitEdgeVertices(axis, d[0], d[1], d[2], a[0], a[1], a[2]);\n        const side3End = perimeterLen;\n\n        const localCcwIsPositive = axis !== 1;\n        const useLocalCcw = positive === localCcwIsPositive;\n        triangulateTwoSideChain(side0Start, side0End, side1Start, side1End, useLocalCcw);\n        triangulateTwoSideChain(side2Start, side2End, side3Start, side3End, useLocalCcw);\n    };\n\n    const emitDiagRectangle = (\n        bucket: number,\n        plane: number,\n        u0: number,\n        e0: number,\n        u1: number,\n        e1: number\n    ): void => {\n        const a = diagPoint(bucket, plane, u0, e0);\n        const b = diagPoint(bucket, plane, u1, e0);\n        const c = diagPoint(bucket, plane, u1, e1);\n        const d = diagPoint(bucket, plane, u0, e1);\n        const addPoint = (x2: number, y2: number, z2: number): void => {\n            addDiagPerimeterPoint(bucket, x2, y2, z2);\n        };\n\n        perimeterLen = 0;\n        const side0Start = 0;\n        addPoint(a[0], a[1], a[2]);\n        addPoint(b[0], b[1], b[2]);\n        const side0End = perimeterLen;\n        const side1Start = side0End - 1;\n        addSplitEdgeVertices(0, b[0], b[1], b[2], c[0], c[1], c[2], addPoint);\n        const side1End = perimeterLen;\n        const side2Start = side1End - 1;\n        addPoint(d[0], d[1], d[2]);\n        const side2End = perimeterLen;\n        const side3Start = side2End - 1;\n        addSplitEdgeVertices(0, d[0], d[1], d[2], a[0], a[1], a[2], addPoint);\n        const side3End = perimeterLen;\n\n        const { axisA, axisB, signA, signB } = decodeDiagBucket(bucket);\n        const abx = b[0] - a[0];\n        const aby = b[1] - a[1];\n        const abz = b[2] - a[2];\n        const bcx = c[0] - b[0];\n        const bcy = c[1] - b[1];\n        const bcz = c[2] - b[2];\n        const nx = aby * bcz - abz * bcy;\n        const ny = abz * bcx - abx * bcz;\n        const nz = abx * bcy - aby * bcx;\n        const normal = [0, 0, 0];\n        normal[axisA] = signA;\n        normal[axisB] = signB;\n        const useLocalCcw = nx * normal[0] + ny * normal[1] + nz * normal[2] > 0;\n\n        triangulateTwoSideChain(side0Start, side0End, side1Start, side1End, useLocalCcw);\n        triangulateTwoSideChain(side2Start, side2End, side3Start, side3End, useLocalCcw);\n    };\n\n    const flushFaceCells = (): void => {\n        if (faceCellLen === 0 && diagCellLen === 0) return;\n\n        const keys = faceCellKeys.subarray(0, faceCellLen);\n        faceCellKeys = new Float64Array(0);\n        keys.sort();\n\n        let rectCap = 1024;\n        let rectLen = 0;\n        let rectBucket = new Int32Array(rectCap);\n        let rectP = new Int32Array(rectCap);\n        let rectU0 = new Int32Array(rectCap);\n        let rectV0 = new Int32Array(rectCap);\n        let rectU1 = new Int32Array(rectCap);\n        let rectV1 = new Int32Array(rectCap);\n        let diagRectCap = 1024;\n        let diagRectLen = 0;\n        let diagRectBucket = new Int32Array(diagRectCap);\n        let diagRectPlane = new Int32Array(diagRectCap);\n        let diagRectU0 = new Int32Array(diagRectCap);\n        let diagRectE0 = new Int32Array(diagRectCap);\n        let diagRectU1 = new Int32Array(diagRectCap);\n        let diagRectE1 = new Int32Array(diagRectCap);\n\n        const addRect = (bucket: number, p: number, u0: number, v0: number, u1: number, v1: number): void => {\n            if (rectLen === rectCap) {\n                rectCap *= 2;\n                const grow = (src: Int32Array<ArrayBuffer>): Int32Array<ArrayBuffer> => {\n                    const out = new Int32Array(rectCap);\n                    out.set(src);\n                    return out;\n                };\n                rectBucket = grow(rectBucket);\n                rectP = grow(rectP);\n                rectU0 = grow(rectU0);\n                rectV0 = grow(rectV0);\n                rectU1 = grow(rectU1);\n                rectV1 = grow(rectV1);\n            }\n            rectBucket[rectLen] = bucket;\n            rectP[rectLen] = p;\n            rectU0[rectLen] = u0;\n            rectV0[rectLen] = v0;\n            rectU1[rectLen] = u1;\n            rectV1[rectLen] = v1;\n            rectLen++;\n        };\n\n        const addDiagRect = (bucket: number, plane: number, u0: number, e0: number, u1: number, e1: number): void => {\n            if (diagRectLen === diagRectCap) {\n                diagRectCap *= 2;\n                const grow = (src: Int32Array<ArrayBuffer>): Int32Array<ArrayBuffer> => {\n                    const out = new Int32Array(diagRectCap);\n                    out.set(src);\n                    return out;\n                };\n                diagRectBucket = grow(diagRectBucket);\n                diagRectPlane = grow(diagRectPlane);\n                diagRectU0 = grow(diagRectU0);\n                diagRectE0 = grow(diagRectE0);\n                diagRectU1 = grow(diagRectU1);\n                diagRectE1 = grow(diagRectE1);\n            }\n            diagRectBucket[diagRectLen] = bucket;\n            diagRectPlane[diagRectLen] = plane;\n            diagRectU0[diagRectLen] = u0;\n            diagRectE0[diagRectLen] = e0;\n            diagRectU1[diagRectLen] = u1;\n            diagRectE1[diagRectLen] = e1;\n            diagRectLen++;\n        };\n\n        const decodeGroup = (key: number): { bucket: number; pOff: number } => {\n            let q = Math.floor(key / faceCoordStride);\n            q = Math.floor(q / faceCoordStride);\n            const pOff = q % faceCoordStride;\n            const bucket = Math.floor(q / faceCoordStride);\n            return { bucket, pOff };\n        };\n\n        const decodeUvKey = (key: number): number => {\n            const vOff = key % faceCoordStride;\n            const q = Math.floor(key / faceCoordStride);\n            const uOff = q % faceCoordStride;\n            return uOff * faceCoordStride + vOff;\n        };\n\n        let start = 0;\n        while (start < keys.length) {\n            const { bucket, pOff } = decodeGroup(keys[start]);\n            let end = start + 1;\n            while (end < keys.length) {\n                const g = decodeGroup(keys[end]);\n                if (g.bucket !== bucket || g.pOff !== pOff) break;\n                end++;\n            }\n\n            const count = end - start;\n            let hCap = 1;\n            while (hCap < count / 0.7) hCap *= 2;\n            const hMask = hCap - 1;\n            const hKeys = new Float64Array(hCap).fill(-1);\n            const hVals = new Int32Array(hCap);\n\n            const hash = (key: number): number => {\n                const hi = (key / 0x100000000) | 0;\n                return (Math.imul((key | 0) ^ hi, 0x9E3779B9) >>> 0) & hMask;\n            };\n\n            for (let i = 0; i < count; i++) {\n                const uvKey = decodeUvKey(keys[start + i]);\n                let h = hash(uvKey);\n                while (hKeys[h] !== -1) h = (h + 1) & hMask;\n                hKeys[h] = uvKey;\n                hVals[h] = i;\n            }\n\n            const lookup = (uvKey: number): number => {\n                let h = hash(uvKey);\n                while (true) {\n                    const k = hKeys[h];\n                    if (k === uvKey) return hVals[h];\n                    if (k === -1) return -1;\n                    h = (h + 1) & hMask;\n                }\n            };\n\n            const visited = new Uint8Array(count);\n            const uvKeyOf = (uOff: number, vOff: number): number => uOff * faceCoordStride + vOff;\n            const p = pOff - 1;\n\n            for (let i = 0; i < count; i++) {\n                if (visited[i]) continue;\n                const uvKey = decodeUvKey(keys[start + i]);\n                const uOff = Math.floor(uvKey / faceCoordStride);\n                const vOff = uvKey % faceCoordStride;\n\n                let width = 1;\n                while (true) {\n                    const idx = lookup(uvKeyOf(uOff + width, vOff));\n                    if (idx === -1 || visited[idx]) break;\n                    width++;\n                }\n\n                let height = 1;\n                while (true) {\n                    let canGrow = true;\n                    for (let du = 0; du < width; du++) {\n                        const idx = lookup(uvKeyOf(uOff + du, vOff + height));\n                        if (idx === -1 || visited[idx]) {\n                            canGrow = false;\n                            break;\n                        }\n                    }\n                    if (!canGrow) break;\n                    height++;\n                }\n\n                for (let dv = 0; dv < height; dv++) {\n                    for (let du = 0; du < width; du++) {\n                        const idx = lookup(uvKeyOf(uOff + du, vOff + dv));\n                        visited[idx] = 1;\n                    }\n                }\n\n                addRect(bucket, p, uOff - 1, vOff - 1, uOff - 1 + width, vOff - 1 + height);\n            }\n\n            start = end;\n        }\n\n        if (diagCellLen > 0) {\n            const diagKeys = diagCellKeys.slice(0, diagCellLen);\n            diagCellKeys = new Float64Array(0);\n            diagKeys.sort();\n\n            const decodeDiagKey = (key: number): {\n                bucket: number;\n                plane: number;\n                u: number;\n                e: number;\n            } => {\n                const eOff = key % diagCoordStride;\n                let q = Math.floor(key / diagCoordStride);\n                const uOff = q % diagCoordStride;\n                q = Math.floor(q / diagCoordStride);\n                const planeOff = q % diagCoordStride;\n                const bucket = Math.floor(q / diagCoordStride);\n                return {\n                    bucket,\n                    plane: planeOff - diagCoordOffset,\n                    u: uOff - diagCoordOffset,\n                    e: eOff - diagCoordOffset\n                };\n            };\n\n            let diagStart = 0;\n            while (diagStart < diagKeys.length) {\n                const first = decodeDiagKey(diagKeys[diagStart]);\n                let diagEnd = diagStart + 1;\n                while (diagEnd < diagKeys.length) {\n                    const next = decodeDiagKey(diagKeys[diagEnd]);\n                    if (next.bucket !== first.bucket || next.plane !== first.plane || next.u !== first.u) {\n                        break;\n                    }\n                    diagEnd++;\n                }\n\n                let i = diagStart;\n                while (i < diagEnd) {\n                    const run = decodeDiagKey(diagKeys[i]);\n                    let e1 = run.e + 2;\n                    i++;\n                    while (i < diagEnd) {\n                        const next = decodeDiagKey(diagKeys[i]);\n                        if (next.e !== e1) break;\n                        e1 += 2;\n                        i++;\n                    }\n                    addDiagRect(run.bucket, run.plane, run.u, run.e, run.u + 2, e1);\n                }\n\n                diagStart = diagEnd;\n            }\n        }\n\n        for (let r = 0; r < rectLen; r++) {\n            const axis = rectBucket[r] >> 1;\n            const p = rectP[r];\n            const u0 = rectU0[r];\n            const v0 = rectV0[r];\n            const u1 = rectU1[r];\n            const v1 = rectV1[r];\n            const a = scaledFacePoint(axis, p, u0, v0);\n            const b = scaledFacePoint(axis, p, u1, v0);\n            const c = scaledFacePoint(axis, p, u1, v1);\n            const d = scaledFacePoint(axis, p, u0, v1);\n            addSplitSegment(a[0], a[1], a[2], b[0], b[1], b[2]);\n            addSplitSegment(b[0], b[1], b[2], c[0], c[1], c[2]);\n            addSplitSegment(c[0], c[1], c[2], d[0], d[1], d[2]);\n            addSplitSegment(d[0], d[1], d[2], a[0], a[1], a[2]);\n        }\n\n        for (let r = 0; r < diagRectLen; r++) {\n            const bucket = diagRectBucket[r];\n            const plane = diagRectPlane[r];\n            const u0 = diagRectU0[r];\n            const e0 = diagRectE0[r];\n            const u1 = diagRectU1[r];\n            const e1 = diagRectE1[r];\n            const a = diagPoint(bucket, plane, u0, e0);\n            const b = diagPoint(bucket, plane, u1, e0);\n            const c = diagPoint(bucket, plane, u1, e1);\n            const d = diagPoint(bucket, plane, u0, e1);\n            addSplitSegment(a[0], a[1], a[2], b[0], b[1], b[2]);\n            addSplitSegment(b[0], b[1], b[2], c[0], c[1], c[2]);\n            addSplitSegment(c[0], c[1], c[2], d[0], d[1], d[2]);\n            addSplitSegment(d[0], d[1], d[2], a[0], a[1], a[2]);\n        }\n\n        if (splitLinePoints) {\n            for (const points of splitLinePoints.values()) {\n                points.sort((a, b) => a - b);\n                let write = 0;\n                for (let i = 0; i < points.length; i++) {\n                    if (i === 0 || points[i] !== points[i - 1]) {\n                        points[write++] = points[i];\n                    }\n                }\n                points.length = write;\n            }\n        }\n\n        collectSplitPoints = false;\n        for (let r = 0; r < rectLen; r++) {\n            emitFaceRectangle(\n                rectBucket[r],\n                rectP[r],\n                rectU0[r],\n                rectV0[r],\n                rectU1[r],\n                rectV1[r]\n            );\n        }\n        for (let r = 0; r < diagRectLen; r++) {\n            emitDiagRectangle(\n                diagRectBucket[r],\n                diagRectPlane[r],\n                diagRectU0[r],\n                diagRectE0[r],\n                diagRectU1[r],\n                diagRectE1[r]\n            );\n        }\n        splitLinePoints?.clear();\n    };\n\n    // Track processed orphan cells to avoid duplicate triangles. When a cell's\n    // owner block doesn't exist, multiple neighboring blocks can reach it via\n    // the -1 boundary extension. The hash table ensures each orphan cell is\n    // only processed once. Same typed-array structure as the vertex hash —\n    // see `oKeys` / `oGrow` above. Stored separately because keys collide with\n    // vertex keys (same encoding, different namespace).\n\n    // Iterate non-empty blocks of the grid via word-level skipping.\n    // Each block is processed once; the inner loop also handles boundary cells\n    // that straddle into neighboring blocks (so we don't need a separate pass\n    // for orphan boundary cells along the negative grid edges).\n    for (let w = 0; w < types.length; w++) {\n        const word = types[w];\n        if (word === 0) continue;\n        let nonEmpty = ((word & EVEN_BITS) | ((word >>> 1) & EVEN_BITS)) >>> 0;\n        const baseBlockIdx = w * BLOCKS_PER_WORD;\n        while (nonEmpty) {\n            const bp = 31 - Math.clz32(nonEmpty & -nonEmpty);\n            const lane = bp >>> 1;\n            const blockIdx = baseBlockIdx + lane;\n            nonEmpty &= nonEmpty - 1;\n            if (blockIdx >= totalBlocks) break;\n\n            // Decode block coordinates.\n            bx = blockIdx % nbx;\n            const byBz = (blockIdx / nbx) | 0;\n            by = byBz % nby;\n            bz = (byBz / nby) | 0;\n\n            // Populate the 3x3x3 neighbor table for this block. After this loop,\n            // every per-cell occupancy query is a direct typed-array index.\n            //\n            // Track `allNeighborsSolid` so we can skip the entire cell loop\n            // for blocks deep inside an obstruction, where every cubeIndex is\n            // 255 and no triangles are emitted. On large carved scenes this\n            // is the bulk of SOLID blocks and dominates marching-cubes runtime.\n            let currentBlockIsSolid = false;\n            let allNeighborsSolid = true;\n            for (let dz = -1; dz <= 1; dz++) {\n                const nbZ = bz + dz;\n                for (let dy = -1; dy <= 1; dy++) {\n                    const nbY = by + dy;\n                    for (let dx = -1; dx <= 1; dx++) {\n                        const nbX = bx + dx;\n                        const slot = (dx + 1) + (dy + 1) * 3 + (dz + 1) * 9;\n                        if (nbX < 0 || nbY < 0 || nbZ < 0 ||\n                            nbX >= nbx || nbY >= nby || nbZ >= nbz) {\n                            neighborEntry[slot] = NEIGHBOR_EMPTY;\n                            allNeighborsSolid = false;\n                            continue;\n                        }\n                        const nbIdx = nbX + nbY * nbx + nbZ * bStride;\n                        const bt = readBlockType(types, nbIdx);\n                        if (bt === BLOCK_EMPTY) {\n                            neighborEntry[slot] = NEIGHBOR_EMPTY;\n                            allNeighborsSolid = false;\n                        } else if (bt === BLOCK_SOLID) {\n                            neighborEntry[slot] = NEIGHBOR_SOLID;\n                            if (dx === 0 && dy === 0 && dz === 0) currentBlockIsSolid = true;\n                        } else {\n                            neighborEntry[slot] = NEIGHBOR_MIXED;\n                            allNeighborsSolid = false;\n                            const ms = masks.slot(nbIdx);\n                            neighborMasks[slot * 2] = masks.lo[ms];\n                            neighborMasks[slot * 2 + 1] = masks.hi[ms];\n                        }\n                    }\n                }\n            }\n\n            // Block is fully interior to a solid region — every cubeIndex is\n            // 255, every cell would emit 0 triangles. Skip the cell loop.\n            if (currentBlockIsSolid && allNeighborsSolid) continue;\n\n            // Iterate cell origins from -1 through 3 on each axis. The -1 and\n            // 3 layers straddle block edges and close surfaces where no\n            // neighboring block exists.\n            for (let lz = -1; lz < 4; lz++) {\n                const lzInside = lz >= 0 && lz <= 2;\n                for (let ly = -1; ly < 4; ly++) {\n                    const lyInside = ly >= 0 && ly <= 2;\n                    for (let lx = -1; lx < 4; lx++) {\n                    // For solid blocks, the 27 cells with all axes in 0..2\n                    // are fully inside the block. All 8 corners are 1 so\n                    // cubeIndex == 255 and no triangles are emitted -- skip.\n                        if (currentBlockIsSolid && lzInside && lyInside && lx >= 0 && lx <= 2) continue;\n\n                        const vx = bx * 4 + lx;\n                        const vy = by * 4 + ly;\n                        const vz = bz * 4 + lz;\n\n                        // Determine which block owns this cell\n                        const ownerBx = vx >> 2;\n                        const ownerBy = vy >> 2;\n                        const ownerBz = vz >> 2;\n\n                        if (ownerBx !== bx || ownerBy !== by || ownerBz !== bz) {\n                        // Cell belongs to a different block — skip if that\n                        // block is non-empty (it will process the cell itself).\n                            if (ownerBx >= 0 && ownerBy >= 0 && ownerBz >= 0 &&\n                            ownerBx < nbx && ownerBy < nby && ownerBz < nbz) {\n                                const ownerIdx = ownerBx + ownerBy * nbx + ownerBz * bStride;\n                                if (readBlockType(types, ownerIdx) !== BLOCK_EMPTY) continue;\n                            }\n\n                            // Owner block doesn't exist or is out-of-bounds —\n                            // deduplicate so only the first neighboring block to\n                            // reach this cell emits triangles.\n                            const cellKey = (vx + 1) + (vy + 1) * strideX + (vz + 1) * strideXY;\n                            let oi = (Math.imul(cellKey | 0, 0x9E3779B9) >>> 0) & oMask;\n                            let oFound = false;\n                            while (true) {\n                                const ok = oKeys[oi];\n                                if (ok === cellKey) {\n                                    oFound = true;\n                                    break;\n                                }\n                                if (ok === -1) break;\n                                oi = (oi + 1) & oMask;\n                            }\n                            if (oFound) continue;\n                            oKeys[oi] = cellKey;\n                            oSize++;\n                            if (oSize > ((oCap * 0.7) | 0)) oGrow();\n                        }\n\n                        // Get corner values for this cell (8 corners)\n                        // Corners: (vx,vy,vz), (vx+1,vy,vz), (vx+1,vy+1,vz), (vx,vy+1,vz),\n                        //          (vx,vy,vz+1), (vx+1,vy,vz+1), (vx+1,vy+1,vz+1), (vx,vy+1,vz+1)\n                        const c0 = isOccupiedLocal(vx, vy, vz) ? 1 : 0;\n                        const c1 = isOccupiedLocal(vx + 1, vy, vz) ? 1 : 0;\n                        const c2 = isOccupiedLocal(vx + 1, vy + 1, vz) ? 1 : 0;\n                        const c3 = isOccupiedLocal(vx, vy + 1, vz) ? 1 : 0;\n                        const c4 = isOccupiedLocal(vx, vy, vz + 1) ? 1 : 0;\n                        const c5 = isOccupiedLocal(vx + 1, vy, vz + 1) ? 1 : 0;\n                        const c6 = isOccupiedLocal(vx + 1, vy + 1, vz + 1) ? 1 : 0;\n                        const c7 = isOccupiedLocal(vx, vy + 1, vz + 1) ? 1 : 0;\n\n                        const cubeIndex = c0 | (c1 << 1) | (c2 << 2) | (c3 << 3) |\n                                      (c4 << 4) | (c5 << 5) | (c6 << 6) | (c7 << 7);\n\n                        if (cubeIndex === 0 || cubeIndex === 255) continue;\n\n                        if (collectFlatFace(cubeIndex, vx, vy, vz)) continue;\n\n                        const edges = EDGE_TABLE[cubeIndex]; // eslint-disable-line no-use-before-define\n                        if (edges === 0) continue;\n\n                        const triRow = TRI_TABLE[cubeIndex]; // eslint-disable-line no-use-before-define\n                        const triLen = triRow.length;\n                        const usedMask = collectDiagFaces(triRow, vx, vy, vz);\n                        let neededEdges = 0;\n                        let emitTriLen = 0;\n                        for (let t = 0; t < triLen; t += 3) {\n                            const triIdx = (t / 3) | 0;\n                            if ((usedMask & (1 << triIdx)) !== 0) continue;\n                            neededEdges |= (1 << triRow[t]) | (1 << triRow[t + 1]) | (1 << triRow[t + 2]);\n                            emitTriLen += 3;\n                        }\n                        if (neededEdges === 0) continue;\n\n                        // Compute vertices on edges used by triangles that\n                        // were not absorbed into a merged binary-MC rectangle.\n                        if (neededEdges & 1)    edgeVerts[0]  = getVertex(vx, vy, vz, 0);       // edge 0: x-axis at (vx, vy, vz)\n                        if (neededEdges & 2)    edgeVerts[1]  = getVertex(vx + 1, vy, vz, 1);   // edge 1: y-axis at (vx+1, vy, vz)\n                        if (neededEdges & 4)    edgeVerts[2]  = getVertex(vx, vy + 1, vz, 0);   // edge 2: x-axis at (vx, vy+1, vz)\n                        if (neededEdges & 8)    edgeVerts[3]  = getVertex(vx, vy, vz, 1);       // edge 3: y-axis at (vx, vy, vz)\n                        if (neededEdges & 16)   edgeVerts[4]  = getVertex(vx, vy, vz + 1, 0);   // edge 4: x-axis at (vx, vy, vz+1)\n                        if (neededEdges & 32)   edgeVerts[5]  = getVertex(vx + 1, vy, vz + 1, 1); // edge 5: y-axis at (vx+1, vy, vz+1)\n                        if (neededEdges & 64)   edgeVerts[6]  = getVertex(vx, vy + 1, vz + 1, 0); // edge 6: x-axis at (vx, vy+1, vz+1)\n                        if (neededEdges & 128)  edgeVerts[7]  = getVertex(vx, vy, vz + 1, 1);   // edge 7: y-axis at (vx, vy, vz+1)\n                        if (neededEdges & 256)  edgeVerts[8]  = getVertex(vx, vy, vz, 2);       // edge 8: z-axis at (vx, vy, vz)\n                        if (neededEdges & 512)  edgeVerts[9]  = getVertex(vx + 1, vy, vz, 2);   // edge 9: z-axis at (vx+1, vy, vz)\n                        if (neededEdges & 1024) edgeVerts[10] = getVertex(vx + 1, vy + 1, vz, 2); // edge 10: z-axis at (vx+1, vy+1, vz)\n                        if (neededEdges & 2048) edgeVerts[11] = getVertex(vx, vy + 1, vz, 2);   // edge 11: z-axis at (vx, vy+1, vz)\n\n                        // Emit triangles (reversed winding to face outward)\n                        ensureIndexCapacity(emitTriLen);\n                        for (let t = 0; t < triLen; t += 3) {\n                            const triIdx = (t / 3) | 0;\n                            if ((usedMask & (1 << triIdx)) !== 0) continue;\n                            indices[idxLen++] = edgeVerts[triRow[t]];\n                            indices[idxLen++] = edgeVerts[triRow[t + 2]];\n                            indices[idxLen++] = edgeVerts[triRow[t + 1]];\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    flushFaceCells();\n\n    return {\n        positions: positions.slice(0, posLen),\n        indices: indices.slice(0, idxLen)\n    };\n}\n\n// ============================================================================\n// Marching Cubes Lookup Tables\n// ============================================================================\n// Standard tables from Paul Bourke's polygonising a scalar field.\n// EDGE_TABLE: 256 entries, each a 12-bit mask of which edges are intersected.\n// TRI_TABLE: 256 entries, each an array of edge indices forming triangles.\n\nconst EDGE_TABLE: number[] = [\n    0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,\n    0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,\n    0x190, 0x099, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,\n    0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,\n    0x230, 0x339, 0x033, 0x13a, 0x636, 0x73f, 0x435, 0x53c,\n    0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,\n    0x3a0, 0x2a9, 0x1a3, 0x0aa, 0x7a6, 0x6af, 0x5a5, 0x4ac,\n    0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,\n    0x460, 0x569, 0x663, 0x76a, 0x066, 0x16f, 0x265, 0x36c,\n    0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,\n    0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0x0ff, 0x3f5, 0x2fc,\n    0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,\n    0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x055, 0x15c,\n    0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,\n    0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0x0cc,\n    0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,\n    0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,\n    0x0cc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,\n    0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,\n    0x15c, 0x055, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,\n    0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,\n    0x2fc, 0x3f5, 0x0ff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,\n    0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,\n    0x36c, 0x265, 0x16f, 0x066, 0x76a, 0x663, 0x569, 0x460,\n    0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,\n    0x4ac, 0x5a5, 0x6af, 0x7a6, 0x0aa, 0x1a3, 0x2a9, 0x3a0,\n    0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,\n    0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x033, 0x339, 0x230,\n    0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,\n    0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x099, 0x190,\n    0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,\n    0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000\n];\n\nconst TRI_TABLE: number[][] = [\n    [],\n    [0, 8, 3],\n    [0, 1, 9],\n    [1, 8, 3, 9, 8, 1],\n    [1, 2, 10],\n    [0, 8, 3, 1, 2, 10],\n    [9, 2, 10, 0, 2, 9],\n    [2, 8, 3, 2, 10, 8, 10, 9, 8],\n    [3, 11, 2],\n    [0, 11, 2, 8, 11, 0],\n    [1, 9, 0, 2, 3, 11],\n    [1, 11, 2, 1, 9, 11, 9, 8, 11],\n    [3, 10, 1, 11, 10, 3],\n    [0, 10, 1, 0, 8, 10, 8, 11, 10],\n    [3, 9, 0, 3, 11, 9, 11, 10, 9],\n    [9, 8, 10, 10, 8, 11],\n    [4, 7, 8],\n    [4, 3, 0, 7, 3, 4],\n    [0, 1, 9, 8, 4, 7],\n    [4, 1, 9, 4, 7, 1, 7, 3, 1],\n    [1, 2, 10, 8, 4, 7],\n    [3, 4, 7, 3, 0, 4, 1, 2, 10],\n    [9, 2, 10, 9, 0, 2, 8, 4, 7],\n    [2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4],\n    [8, 4, 7, 3, 11, 2],\n    [11, 4, 7, 11, 2, 4, 2, 0, 4],\n    [9, 0, 1, 8, 4, 7, 2, 3, 11],\n    [4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1],\n    [3, 10, 1, 3, 11, 10, 7, 8, 4],\n    [1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4],\n    [4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3],\n    [4, 7, 11, 4, 11, 9, 9, 11, 10],\n    [9, 5, 4],\n    [9, 5, 4, 0, 8, 3],\n    [0, 5, 4, 1, 5, 0],\n    [8, 5, 4, 8, 3, 5, 3, 1, 5],\n    [1, 2, 10, 9, 5, 4],\n    [3, 0, 8, 1, 2, 10, 4, 9, 5],\n    [5, 2, 10, 5, 4, 2, 4, 0, 2],\n    [2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8],\n    [9, 5, 4, 2, 3, 11],\n    [0, 11, 2, 0, 8, 11, 4, 9, 5],\n    [0, 5, 4, 0, 1, 5, 2, 3, 11],\n    [2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5],\n    [10, 3, 11, 10, 1, 3, 9, 5, 4],\n    [4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10],\n    [5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3],\n    [5, 4, 8, 5, 8, 10, 10, 8, 11],\n    [9, 7, 8, 5, 7, 9],\n    [9, 3, 0, 9, 5, 3, 5, 7, 3],\n    [0, 7, 8, 0, 1, 7, 1, 5, 7],\n    [1, 5, 3, 3, 5, 7],\n    [9, 7, 8, 9, 5, 7, 10, 1, 2],\n    [10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3],\n    [8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2],\n    [2, 10, 5, 2, 5, 3, 3, 5, 7],\n    [7, 9, 5, 7, 8, 9, 3, 11, 2],\n    [9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11],\n    [2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7],\n    [11, 2, 1, 11, 1, 7, 7, 1, 5],\n    [9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11],\n    [5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0],\n    [11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0],\n    [11, 10, 5, 7, 11, 5],\n    [10, 6, 5],\n    [0, 8, 3, 5, 10, 6],\n    [9, 0, 1, 5, 10, 6],\n    [1, 8, 3, 1, 9, 8, 5, 10, 6],\n    [1, 6, 5, 2, 6, 1],\n    [1, 6, 5, 1, 2, 6, 3, 0, 8],\n    [9, 6, 5, 9, 0, 6, 0, 2, 6],\n    [5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8],\n    [2, 3, 11, 10, 6, 5],\n    [11, 0, 8, 11, 2, 0, 10, 6, 5],\n    [0, 1, 9, 2, 3, 11, 5, 10, 6],\n    [5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11],\n    [6, 3, 11, 6, 5, 3, 5, 1, 3],\n    [0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6],\n    [3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9],\n    [6, 5, 9, 6, 9, 11, 11, 9, 8],\n    [5, 10, 6, 4, 7, 8],\n    [4, 3, 0, 4, 7, 3, 6, 5, 10],\n    [1, 9, 0, 5, 10, 6, 8, 4, 7],\n    [10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4],\n    [6, 1, 2, 6, 5, 1, 4, 7, 8],\n    [1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7],\n    [8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6],\n    [7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9],\n    [3, 11, 2, 7, 8, 4, 10, 6, 5],\n    [5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11],\n    [0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6],\n    [9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6],\n    [8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6],\n    [5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11],\n    [0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7],\n    [6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9],\n    [10, 4, 9, 6, 4, 10],\n    [4, 10, 6, 4, 9, 10, 0, 8, 3],\n    [10, 0, 1, 10, 6, 0, 6, 4, 0],\n    [8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10],\n    [1, 4, 9, 1, 2, 4, 2, 6, 4],\n    [3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4],\n    [0, 2, 4, 4, 2, 6],\n    [8, 3, 2, 8, 2, 4, 4, 2, 6],\n    [10, 4, 9, 10, 6, 4, 11, 2, 3],\n    [0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6],\n    [3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10],\n    [6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1],\n    [9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3],\n    [8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1],\n    [3, 11, 6, 3, 6, 0, 0, 6, 4],\n    [6, 4, 8, 11, 6, 8],\n    [7, 10, 6, 7, 8, 10, 8, 9, 10],\n    [0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10],\n    [10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0],\n    [10, 6, 7, 10, 7, 1, 1, 7, 3],\n    [1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7],\n    [2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9],\n    [7, 8, 0, 7, 0, 6, 6, 0, 2],\n    [7, 3, 2, 6, 7, 2],\n    [2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7],\n    [2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7],\n    [1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11],\n    [11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1],\n    [8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6],\n    [0, 9, 1, 11, 6, 7],\n    [7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0],\n    [7, 11, 6],\n    [7, 6, 11],\n    [3, 0, 8, 11, 7, 6],\n    [0, 1, 9, 11, 7, 6],\n    [8, 1, 9, 8, 3, 1, 11, 7, 6],\n    [10, 1, 2, 6, 11, 7],\n    [1, 2, 10, 3, 0, 8, 6, 11, 7],\n    [2, 9, 0, 2, 10, 9, 6, 11, 7],\n    [6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8],\n    [7, 2, 3, 6, 2, 7],\n    [7, 0, 8, 7, 6, 0, 6, 2, 0],\n    [2, 7, 6, 2, 3, 7, 0, 1, 9],\n    [1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6],\n    [10, 7, 6, 10, 1, 7, 1, 3, 7],\n    [10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8],\n    [0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7],\n    [7, 6, 10, 7, 10, 8, 8, 10, 9],\n    [6, 8, 4, 11, 8, 6],\n    [3, 6, 11, 3, 0, 6, 0, 4, 6],\n    [8, 6, 11, 8, 4, 6, 9, 0, 1],\n    [9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6],\n    [6, 8, 4, 6, 11, 8, 2, 10, 1],\n    [1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6],\n    [4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9],\n    [10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3],\n    [8, 2, 3, 8, 4, 2, 4, 6, 2],\n    [0, 4, 2, 4, 6, 2],\n    [1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8],\n    [1, 9, 4, 1, 4, 2, 2, 4, 6],\n    [8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1],\n    [10, 1, 0, 10, 0, 6, 6, 0, 4],\n    [4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3],\n    [10, 9, 4, 6, 10, 4],\n    [4, 9, 5, 7, 6, 11],\n    [0, 8, 3, 4, 9, 5, 11, 7, 6],\n    [5, 0, 1, 5, 4, 0, 7, 6, 11],\n    [11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5],\n    [9, 5, 4, 10, 1, 2, 7, 6, 11],\n    [6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5],\n    [7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2],\n    [3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6],\n    [7, 2, 3, 7, 6, 2, 5, 4, 9],\n    [9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7],\n    [3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0],\n    [6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8],\n    [9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7],\n    [1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4],\n    [4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10],\n    [7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10],\n    [6, 9, 5, 6, 11, 9, 11, 8, 9],\n    [3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5],\n    [0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11],\n    [6, 11, 3, 6, 3, 5, 5, 3, 1],\n    [1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6],\n    [0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10],\n    [11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5],\n    [6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3],\n    [5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2],\n    [9, 5, 6, 9, 6, 0, 0, 6, 2],\n    [1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8],\n    [1, 5, 6, 2, 1, 6],\n    [1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6],\n    [10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0],\n    [0, 3, 8, 5, 6, 10],\n    [10, 5, 6],\n    [11, 5, 10, 7, 5, 11],\n    [11, 5, 10, 11, 7, 5, 8, 3, 0],\n    [5, 11, 7, 5, 10, 11, 1, 9, 0],\n    [10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1],\n    [11, 1, 2, 11, 7, 1, 7, 5, 1],\n    [0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11],\n    [9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7],\n    [7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2],\n    [2, 5, 10, 2, 3, 5, 3, 7, 5],\n    [8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5],\n    [9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2],\n    [9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2],\n    [1, 3, 5, 3, 7, 5],\n    [0, 8, 7, 0, 7, 1, 1, 7, 5],\n    [9, 0, 3, 9, 3, 5, 5, 3, 7],\n    [9, 8, 7, 5, 9, 7],\n    [5, 8, 4, 5, 10, 8, 10, 11, 8],\n    [5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0],\n    [0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5],\n    [10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4],\n    [2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8],\n    [0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11],\n    [0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5],\n    [9, 4, 5, 2, 11, 3],\n    [2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4],\n    [5, 10, 2, 5, 2, 4, 4, 2, 0],\n    [3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9],\n    [5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2],\n    [8, 4, 5, 8, 5, 3, 3, 5, 1],\n    [0, 4, 5, 1, 0, 5],\n    [8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5],\n    [9, 4, 5],\n    [4, 11, 7, 4, 9, 11, 9, 10, 11],\n    [0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11],\n    [1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11],\n    [3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4],\n    [4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2],\n    [9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3],\n    [11, 7, 4, 11, 4, 2, 2, 4, 0],\n    [11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4],\n    [2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9],\n    [9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7],\n    [3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10],\n    [1, 10, 2, 8, 7, 4],\n    [4, 9, 1, 4, 1, 7, 7, 1, 3],\n    [4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1],\n    [4, 0, 3, 7, 4, 3],\n    [4, 8, 7],\n    [9, 10, 8, 10, 11, 8],\n    [3, 0, 9, 3, 9, 11, 11, 9, 10],\n    [0, 1, 10, 0, 10, 8, 8, 10, 11],\n    [3, 1, 10, 11, 3, 10],\n    [1, 2, 11, 1, 11, 9, 9, 11, 8],\n    [3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9],\n    [0, 2, 11, 8, 0, 11],\n    [3, 2, 11],\n    [2, 3, 8, 2, 8, 10, 10, 8, 9],\n    [9, 10, 2, 0, 9, 2],\n    [2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8],\n    [1, 10, 2],\n    [1, 3, 8, 9, 1, 8],\n    [0, 9, 1],\n    [0, 3, 8],\n    []\n];\n\nexport { marchingCubes };\nexport type { Mesh, MarchingCubesMesh, MarchingCubesOptions };\n","import type { Mesh } from './marching-cubes';\n\nconst NORMAL_EPS = 1e-3;\nconst PLANE_REL_EPS = 1e-3;\nconst COLLINEAR_REL_EPS = 1e-3;\n\n/**\n * Losslessly reduce coplanar regions of a marching-cubes mesh by\n * topology-preserving vertex removal.\n *\n * For a closed manifold MC mesh, a vertex `v` is \"lossless-removable\" iff\n * its incident-tri fan, walked in cyclic order, falls into one of:\n *\n * 1. K=1 coplanar fan. Every triangle in v's fan lies on the same plane\n *    (same unit normal and same plane offset, within tolerance). Removing\n *    v is the inverse of vertex split: re-triangulate the boundary\n *    polygon in the same plane.\n *\n * 2. K=2 collinear seam. The fan splits into exactly two contiguous\n *    coplanar arcs (different planes). The two crease vertices `a` and\n *    `b` (the boundary points where the plane changes around v) are\n *    collinear with v in 3D, with v between them. Removing v collapses\n *    the two crease edges (v-a, v-b) into a single straight edge (a-b)\n *    that lies in both planes; each arc's polygon re-triangulates\n *    without v.\n *\n * Vertices with K >= 3 (multi-way corners) are kept.\n *\n * Removing a removable v is exact-lossless: the surface footprint is\n * identical, no vertex moves and none are created. The transformation\n * is the inverse of vertex split, so it is topology-preserving by\n * construction:\n *\n * - No T-junctions. Every old vertex on the polygon boundary remains a\n *   vertex of every triangle that previously touched it. Adjacent fused\n *   regions and verbatim regions stay coupled at every shared vertex.\n * - Watertight. The closed manifold structure is preserved across\n *   removal. Both the K=1 and K=2 cases preserve the K=2 seam edge as\n *   a single shared edge between the two plane groups.\n * - Bit-exact. Every output position is a verbatim copy of an input\n *   position; no vertex is fabricated.\n *\n * Algorithm:\n *\n * 1. Build per-vertex incident-tri lists and per-tri normalized normals\n *    and plane offsets.\n * 2. Process vertices via a dirty-flag worklist. Initially queue every\n *    vertex; after a successful removal, re-queue the ring neighbours\n *    so chains of K=1 / K=2 vertices collapse in one run.\n * 3. For each dequeued vertex `v`:\n *      a. Walk the fan to extract the cyclic ring vertices and the\n *         cyclic ordered tris (each tri (v, ring[i], ring[(i+1)%k]) is\n *         the i-th tri in fan order).\n *      b. Decide K. If all tris share a plane: K=1. Otherwise count\n *         transitions in cyclic order; K=2 if exactly two arcs.\n *      c. K>=3: skip. K=2: verify ring[i1], v, ring[i2] are collinear.\n *      d. For each arc, project its polygon to 2D using the arc's\n *         plane basis, ear-clip, and append the new tris.\n *      e. Mark v's old tris dead, register the new tris in each polygon\n *         vertex's incident list, and re-queue the ring.\n * 4. Compact: drop dead tris and unused vertices, remap indices.\n *\n * @param mesh - Input triangle mesh from {@link marchingCubes}.\n * @param voxelResolution - Size of one voxel in world units. Used to scale the plane-offset tolerance. (The K=2 collinearity check is purely angular and has no voxel-scaled term.)\n * @returns A new mesh with the same surface geometry, no T-junctions, and far fewer triangles.\n */\nconst coplanarMerge = (mesh: Mesh, voxelResolution: number): Mesh => {\n    const { positions, indices } = mesh;\n    const inputTriCount = (indices.length / 3) | 0;\n    const vertCount = (positions.length / 3) | 0;\n\n    if (inputTriCount === 0) {\n        return { positions: new Float32Array(0), indices: new Uint32Array(0) };\n    }\n\n    // Plane-offset tolerance for the coplanarity test. An absolute floor\n    // (voxelResolution * PLANE_REL_EPS) handles near-origin planes, while\n    // a relative term scaled by max(|da|, |db|) handles large-offset\n    // planes where Float32 position precision in d = n . p causes\n    // relative error proportional to |d|. Without the relative term,\n    // coplanar fans far from the origin would be seen as distinct planes.\n    const planeEps = (da: number, db: number): number => {\n        const absA = da < 0 ? -da : da;\n        const absB = db < 0 ? -db : db;\n        return PLANE_REL_EPS * (voxelResolution + (absA > absB ? absA : absB));\n    };\n\n    // Mutable triangle table. Flat typed arrays so we can append new tris\n    // (from ear-clipping) without per-tri allocations and without hitting\n    // V8's regular-Array backing-store size cap on large meshes.\n    // `triVertsArr` indexes are 3*t, everything else is t.\n    //\n    // Normals are stored as Float32 (unit vectors; ample precision for the\n    // dot-product coplanarity test against `1 - NORMAL_EPS`). The plane\n    // offset stays Float64 since it's an absolute world-space scalar that\n    // can be large for distant scenes.\n    let triCap = inputTriCount;\n    let triVertsArr: Uint32Array = new Uint32Array(triCap * 3);\n    let triNxArr: Float32Array = new Float32Array(triCap);\n    let triNyArr: Float32Array = new Float32Array(triCap);\n    let triNzArr: Float32Array = new Float32Array(triCap);\n    let triDArr: Float64Array = new Float64Array(triCap);\n    let triAliveArr: Uint8Array = new Uint8Array(triCap);\n    let triCount = inputTriCount;\n\n    // Capacity-doubling appenders for new tris generated by ear-clipping.\n    const ensureTriCap = () => {\n        if (triCount < triCap) return;\n        const newCap = triCap * 2;\n        const growF32 = (src: Float32Array): Float32Array => {\n            const out = new Float32Array(newCap);\n            out.set(src);\n            return out;\n        };\n        const growF64 = (src: Float64Array): Float64Array => {\n            const out = new Float64Array(newCap);\n            out.set(src);\n            return out;\n        };\n        const newVerts = new Uint32Array(newCap * 3);\n        newVerts.set(triVertsArr);\n        triVertsArr = newVerts;\n        triNxArr = growF32(triNxArr);\n        triNyArr = growF32(triNyArr);\n        triNzArr = growF32(triNzArr);\n        triDArr = growF64(triDArr);\n        const aliveOut = new Uint8Array(newCap);\n        aliveOut.set(triAliveArr);\n        triAliveArr = aliveOut;\n        triCap = newCap;\n    };\n\n    // Pass 0: compute per-tri normalized normal and plane offset.\n    for (let t = 0; t < inputTriCount; t++) {\n        const ia = indices[t * 3];\n        const ib = indices[t * 3 + 1];\n        const ic = indices[t * 3 + 2];\n        triVertsArr[t * 3] = ia;\n        triVertsArr[t * 3 + 1] = ib;\n        triVertsArr[t * 3 + 2] = ic;\n\n        const ax = positions[ia * 3];\n        const ay = positions[ia * 3 + 1];\n        const az = positions[ia * 3 + 2];\n        const bx = positions[ib * 3];\n        const by = positions[ib * 3 + 1];\n        const bz = positions[ib * 3 + 2];\n        const cx = positions[ic * 3];\n        const cy = positions[ic * 3 + 1];\n        const cz = positions[ic * 3 + 2];\n\n        const ex = bx - ax, ey = by - ay, ez = bz - az;\n        const fx = cx - ax, fy = cy - ay, fz = cz - az;\n        let nx = ey * fz - ez * fy;\n        let ny = ez * fx - ex * fz;\n        let nz = ex * fy - ey * fx;\n        const nLen = Math.sqrt(nx * nx + ny * ny + nz * nz);\n        if (nLen < 1e-12) {\n            // Degenerate input tri; drop it from the active set.\n            triAliveArr[t] = 0;\n            continue;\n        }\n        const inv = 1 / nLen;\n        nx *= inv; ny *= inv; nz *= inv;\n        triNxArr[t] = nx;\n        triNyArr[t] = ny;\n        triNzArr[t] = nz;\n        triDArr[t] = nx * ax + ny * ay + nz * az;\n        triAliveArr[t] = 1;\n    }\n\n    // Per-vertex incident-tri lists, stored as a singly-linked free-listed\n    // node pool backed by typed arrays. Each pool node `n` holds:\n    //   poolTri[n]  - the incident tri index\n    //   poolNext[n] - next node in the same vertex's list (or -1 = end)\n    // `vertHead[v]` is the head node for vertex v (or -1 if v has no\n    // incident tris). Removed nodes are pushed onto the `freeHead` chain\n    // for reuse, so the pool's max occupancy is the initial fan-mention\n    // count (3 * inputTriCount): the worklist's K=1/K=2 collapses are\n    // monotonically tri-reducing, so the free list serves all subsequent\n    // ear-clip allocations without ever growing the backing arrays.\n    //\n    // Footprint: 8 B/node * 3 * inputTriCount + 4 B/vert * vertCount.\n    // For 25.7M raw tris / 12.9M raw verts that's ~615 MB pool +\n    // ~52 MB heads, vs ~1.4 GB for the prior `number[][]` adjacency\n    // (V8 Array headers, FixedArray headers, hidden classes per inner\n    // array all inflate the boxed-SMI payload).\n    const poolCap = inputTriCount * 3;\n    const poolTri = new Int32Array(poolCap);\n    const poolNext = new Int32Array(poolCap);\n    let poolLen = 0;\n    let freeHead = -1;\n    const vertHead = new Int32Array(vertCount).fill(-1);\n\n    const allocNode = (): number => {\n        if (freeHead !== -1) {\n            const n = freeHead;\n            freeHead = poolNext[n];\n            return n;\n        }\n        return poolLen++;\n    };\n\n    const freeNode = (n: number) => {\n        poolNext[n] = freeHead;\n        freeHead = n;\n    };\n\n    const addTriToVert = (v: number, tri: number) => {\n        const n = allocNode();\n        poolTri[n] = tri;\n        poolNext[n] = vertHead[v];\n        vertHead[v] = n;\n    };\n\n    // O(degree) removal of `tri` from `v`'s incident list. Returns true\n    // if found and removed.\n    const removeTriFromVert = (v: number, tri: number): boolean => {\n        let prev = -1;\n        let cur = vertHead[v];\n        while (cur !== -1) {\n            if (poolTri[cur] === tri) {\n                const nxt = poolNext[cur];\n                if (prev === -1) vertHead[v] = nxt;\n                else poolNext[prev] = nxt;\n                freeNode(cur);\n                return true;\n            }\n            prev = cur;\n            cur = poolNext[cur];\n        }\n        return false;\n    };\n\n    for (let t = 0; t < inputTriCount; t++) {\n        if (triAliveArr[t] === 0) continue;\n        addTriToVert(triVertsArr[t * 3], t);\n        addTriToVert(triVertsArr[t * 3 + 1], t);\n        addTriToVert(triVertsArr[t * 3 + 2], t);\n    }\n\n    // Build a right-handed tangent / bitangent basis (t, b) on the plane\n    // with normal n, picking the cardinal axis least aligned with n to\n    // avoid precision loss in the cross product. By construction\n    // t x b = n, so a polygon traced CCW around +n in 3D projects to a\n    // CCW polygon in (t, b) coordinates (positive 2D signed area).\n    const buildBasis = (nx: number, ny: number, nz: number): [\n        number, number, number, number, number, number\n    ] => {\n        const ax = Math.abs(nx);\n        const ay = Math.abs(ny);\n        const az = Math.abs(nz);\n        let tx: number, ty: number, tz: number;\n        if (ax <= ay && ax <= az) {\n            // X axis least aligned: t = (1, 0, 0) x n\n            tx = 0; ty = -nz; tz = ny;\n        } else if (ay <= az) {\n            // Y axis least aligned: t = (0, 1, 0) x n\n            tx = nz; ty = 0; tz = -nx;\n        } else {\n            // Z axis least aligned: t = (0, 0, 1) x n\n            tx = -ny; ty = nx; tz = 0;\n        }\n        const tlen = Math.sqrt(tx * tx + ty * ty + tz * tz);\n        const inv = 1 / tlen;\n        tx *= inv; ty *= inv; tz *= inv;\n        // bitangent = n x t (unit length because n and t are unit and\n        // perpendicular).\n        const bx = ny * tz - nz * ty;\n        const by = nz * tx - nx * tz;\n        const bz = nx * ty - ny * tx;\n        return [tx, ty, tz, bx, by, bz];\n    };\n\n    // Reusable scratch buffers for extractFan. With typical MC fan sizes\n    // (k <= ~12), a linear scan over parallel typed arrays is cheaper than\n    // the Map-of-Map-of-Set allocations the previous version paid per\n    // vertex, and saves ~3 allocations per worklist iteration on meshes\n    // with tens of millions of vertices.\n    let fanScratchCap = 16;\n    let fanFromScratch = new Int32Array(fanScratchCap);\n    let fanToScratch = new Int32Array(fanScratchCap);\n    let fanTriScratch = new Int32Array(fanScratchCap);\n    let fanRingScratch = new Int32Array(fanScratchCap);\n    let fanTrisScratch = new Int32Array(fanScratchCap);\n    const growFanScratch = (need: number) => {\n        if (need <= fanScratchCap) return;\n        let c = fanScratchCap;\n        while (c < need) c *= 2;\n        fanFromScratch = new Int32Array(c);\n        fanToScratch = new Int32Array(c);\n        fanTriScratch = new Int32Array(c);\n        fanRingScratch = new Int32Array(c);\n        fanTrisScratch = new Int32Array(c);\n        fanScratchCap = c;\n    };\n\n    // Walk v's fan to extract its cyclic boundary polygon AND the matching\n    // cyclic ordered tris. ring[i] is the \"from\" vertex of the i-th tri\n    // (in fan order), and tris[i] = (v, ring[i], ring[(i+1) % k]) is the\n    // tri whose two non-v vertices are ring[i] and ring[(i+1) % k].\n    // Returns null when the fan is non-manifold (duplicate from-vertex,\n    // closes prematurely, or fails to close).\n    //\n    // Output aliases the module-level `fanRingScratch` / `fanTrisScratch`\n    // buffers; the caller must consume them before the next extractFan\n    // call. `k` is returned explicitly since the scratch buffers may be\n    // oversized.\n    const extractFan = (v: number): number => {\n        let k = 0;\n        for (let n = vertHead[v]; n !== -1; n = poolNext[n]) k++;\n        if (k < 3) return -1;\n        growFanScratch(k);\n\n        // Collect (from, to, tri) triples into parallel scratch arrays.\n        // The O(k^2) duplicate-from scan here and the O(k^2) cyclic walk\n        // below are cheap for small k and avoid per-vertex Map allocs.\n        let i = 0;\n        for (let n = vertHead[v]; n !== -1; n = poolNext[n]) {\n            const t = poolTri[n];\n            const a = triVertsArr[t * 3];\n            const b = triVertsArr[t * 3 + 1];\n            const c = triVertsArr[t * 3 + 2];\n            let from: number, to: number;\n            if (a === v) {\n                from = b; to = c;\n            } else if (b === v) {\n                from = c; to = a;\n            } else {\n                from = a; to = b;\n            }\n            for (let j = 0; j < i; j++) {\n                if (fanFromScratch[j] === from) return -1;\n            }\n            fanFromScratch[i] = from;\n            fanToScratch[i] = to;\n            fanTriScratch[i] = t;\n            i++;\n        }\n\n        const start = fanFromScratch[0];\n        let cur = start;\n        for (let step = 0; step < k; step++) {\n            fanRingScratch[step] = cur;\n            let found = -1;\n            for (let j = 0; j < k; j++) {\n                if (fanFromScratch[j] === cur) {\n                    found = j;\n                    break;\n                }\n            }\n            if (found === -1) return -1;\n            fanTrisScratch[step] = fanTriScratch[found];\n            const next = fanToScratch[found];\n            // Premature cycle close => fan is non-manifold (multi-component).\n            if (next === start && step < k - 1) return -1;\n            cur = next;\n        }\n        if (cur !== start) return -1;\n        return k;\n    };\n\n    // Reusable scratch for earClip's doubly-linked polygon traversal.\n    // Grows to the largest polygon seen and is reused across every\n    // worklist iteration.\n    let earPrevScratch = new Int32Array(16);\n    let earNextScratch = new Int32Array(16);\n    const growEarInternalScratch = (n: number) => {\n        if (n <= earPrevScratch.length) return;\n        let c = earPrevScratch.length;\n        while (c < n) c *= 2;\n        earPrevScratch = new Int32Array(c);\n        earNextScratch = new Int32Array(c);\n    };\n\n    // Ear-clip a planar simple polygon. `px, py` are the projected 2D\n    // coordinates of the first `n` polygon vertices (in CCW order); the\n    // arrays may be larger than `n` (scratch-buffer aliasing is fine,\n    // only [0, n) is read). Writes (n - 2) * 3 polygon-relative vertex\n    // indices into `out[outOffset..]` and returns the number of indices\n    // written on success, or -1 if the polygon is degenerate / not\n    // simple.\n    //\n    // Strictly-collinear interior vertices (cross product == 0) are not\n    // considered convex ear apices and so produce slivers as side\n    // vertices of neighbouring ears. These are transient: any such\n    // vertex is itself K=1 in the same plane and the worklist removes\n    // it in a subsequent iteration, replacing the slivers with a clean\n    // re-triangulation of its updated fan. An in-earClip pre-pass that\n    // drops the vertex from this polygon would create a T-junction\n    // with the vertex's other incident tris (which still reference it),\n    // so we leave the cleanup to the worklist.\n    const earClip = (\n        px: Float64Array,\n        py: Float64Array,\n        n: number,\n        out: Int32Array,\n        outOffset: number\n    ): number => {\n        if (n < 3) return -1;\n        if (n === 3) {\n            out[outOffset] = 0;\n            out[outOffset + 1] = 1;\n            out[outOffset + 2] = 2;\n            return 3;\n        }\n\n        // Verify CCW orientation. By construction (right-handed basis)\n        // valid input polygons are CCW with positive signed area.\n        let area2 = 0;\n        for (let i = 0; i < n; i++) {\n            const j = (i + 1) % n;\n            area2 += px[i] * py[j] - px[j] * py[i];\n        }\n        if (area2 <= 0) return -1;\n\n        growEarInternalScratch(n);\n        const prev = earPrevScratch;\n        const next = earNextScratch;\n        for (let i = 0; i < n; i++) {\n            prev[i] = (i - 1 + n) % n;\n            next[i] = (i + 1) % n;\n        }\n\n        const isConvex = (a: number, b: number, c: number): boolean => {\n            return (px[b] - px[a]) * (py[c] - py[a]) -\n                   (py[b] - py[a]) * (px[c] - px[a]) > 0;\n        };\n\n        const inTri = (p: number, a: number, b: number, c: number): boolean => {\n            const x = px[p], y = py[p];\n            const d1 = (x - px[b]) * (py[a] - py[b]) - (px[a] - px[b]) * (y - py[b]);\n            const d2 = (x - px[c]) * (py[b] - py[c]) - (px[b] - px[c]) * (y - py[c]);\n            const d3 = (x - px[a]) * (py[c] - py[a]) - (px[c] - px[a]) * (y - py[a]);\n            const hasNeg = d1 < 0 || d2 < 0 || d3 < 0;\n            const hasPos = d1 > 0 || d2 > 0 || d3 > 0;\n            return !(hasNeg && hasPos);\n        };\n\n        const isEar = (a: number, b: number, c: number): boolean => {\n            if (!isConvex(a, b, c)) return false;\n            let p = next[c];\n            while (p !== a) {\n                if (inTri(p, a, b, c)) return false;\n                p = next[p];\n            }\n            return true;\n        };\n\n        let resultLen = 0;\n        let count = n;\n        let i = 0;\n        let stalls = 0;\n\n        while (count > 3) {\n            if (stalls > count) return -1;\n            const p = prev[i];\n            const nxt = next[i];\n            if (isEar(p, i, nxt)) {\n                out[outOffset + resultLen++] = p;\n                out[outOffset + resultLen++] = i;\n                out[outOffset + resultLen++] = nxt;\n                next[p] = nxt;\n                prev[nxt] = p;\n                count--;\n                i = nxt;\n                stalls = 0;\n            } else {\n                i = next[i];\n                stalls++;\n            }\n        }\n        out[outOffset + resultLen++] = prev[i];\n        out[outOffset + resultLen++] = i;\n        out[outOffset + resultLen++] = next[i];\n        return resultLen;\n    };\n\n    // Worklist: iterative dirty-flag scheduler. Initially queue every\n    // vertex; on each successful removal, re-queue the ring neighbours so\n    // chains of K=1 / K=2 vertices collapse in a single run.\n    const inQueue = new Uint8Array(vertCount);\n    let queue = new Int32Array(Math.max(vertCount, 16));\n    let queueLen = 0;\n    let queueHead = 0;\n    const pushQueue = (u: number) => {\n        if (inQueue[u]) return;\n        inQueue[u] = 1;\n        if (queueLen >= queue.length) {\n            const grown = new Int32Array(queue.length * 2);\n            grown.set(queue);\n            queue = grown;\n        }\n        queue[queueLen++] = u;\n    };\n    const compactQueue = () => {\n        // Reclaim consumed prefix when slack exceeds 50% (and is large\n        // enough to be worth the copy). Bounded by O(total pushes).\n        if (queueHead > 4096 && queueHead * 2 > queueLen) {\n            queue.copyWithin(0, queueHead, queueLen);\n            queueLen -= queueHead;\n            queueHead = 0;\n        }\n    };\n    for (let v = 0; v < vertCount; v++) {\n        inQueue[v] = 1;\n        queue[queueLen++] = v;\n    }\n\n    // Tolerance for K=2 seam collinearity: cosine of the angle between\n    // (v -> a) and (v -> b) must be <= -(1 - COLLINEAR_REL_EPS), i.e.\n    // the two seam edges through v are nearly antiparallel (v lies on\n    // the segment from a to b in 3D).\n    const cosineMax = -1 + COLLINEAR_REL_EPS;\n\n    // Reusable scratch for the per-arc plane descriptor.\n    const arcStartIdx = new Int32Array(2);\n    const arcPolySize = new Int32Array(2);\n    const arcPlaneT = new Int32Array(2);\n\n    // Reusable per-arc scratch buffers (arcCount is always 1 or 2).\n    // Each slot holds the polygon vertex indices, the 2D-projected\n    // coordinates, and the ear-clip triangle indices for one arc. All\n    // grow monotonically to the largest polygon ever seen and are\n    // reused for every worklist iteration, so the hot loop is mostly\n    // allocation-free.\n    const arcPolyScratch: Int32Array[] = [new Int32Array(16), new Int32Array(16)];\n    const arcPxScratch: Float64Array[] = [new Float64Array(16), new Float64Array(16)];\n    const arcPyScratch: Float64Array[] = [new Float64Array(16), new Float64Array(16)];\n    const arcEarScratch: Int32Array[] = [new Int32Array(16), new Int32Array(16)];\n    const arcEarLen = new Int32Array(2);\n    const ensureArcScratch = (g: number, polySize: number) => {\n        if (polySize > arcPolyScratch[g].length) {\n            let c = arcPolyScratch[g].length;\n            while (c < polySize) c *= 2;\n            arcPolyScratch[g] = new Int32Array(c);\n            arcPxScratch[g] = new Float64Array(c);\n            arcPyScratch[g] = new Float64Array(c);\n        }\n        const earNeed = (polySize - 2) * 3;\n        if (earNeed > arcEarScratch[g].length) {\n            let c = arcEarScratch[g].length;\n            while (c < earNeed) c *= 2;\n            arcEarScratch[g] = new Int32Array(c);\n        }\n    };\n\n    while (queueHead < queueLen) {\n        const v = queue[queueHead++];\n        inQueue[v] = 0;\n        compactQueue();\n\n        // Cheap \"fan size < 3\" early-out without traversing the full\n        // linked list.\n        const h0 = vertHead[v];\n        if (h0 === -1) continue;\n        const h1 = poolNext[h0];\n        if (h1 === -1) continue;\n        if (poolNext[h1] === -1) continue;\n\n        const k = extractFan(v);\n        if (k === -1) continue;\n        const ring = fanRingScratch;\n        const fanTris = fanTrisScratch;\n\n        // Decide K. First check if all tris are coplanar with fanTris[0]\n        // (K=1 fast path).\n        const t0 = fanTris[0];\n        const n0x = triNxArr[t0];\n        const n0y = triNyArr[t0];\n        const n0z = triNzArr[t0];\n        const d0 = triDArr[t0];\n        let allCoplanar = true;\n        for (let i = 1; i < k; i++) {\n            const t = fanTris[i];\n            const dT = triDArr[t];\n            const dotN = triNxArr[t] * n0x + triNyArr[t] * n0y + triNzArr[t] * n0z;\n            if (dotN < 1 - NORMAL_EPS || Math.abs(dT - d0) > planeEps(dT, d0)) {\n                allCoplanar = false;\n                break;\n            }\n        }\n\n        let arcCount = 0;\n        if (allCoplanar) {\n            // K=1: single arc covering the whole ring (k vertices).\n            arcStartIdx[0] = 0;\n            arcPolySize[0] = k;\n            arcPlaneT[0] = t0;\n            arcCount = 1;\n        } else {\n            // Walk cyclically; mark transitions where plane changes vs.\n            // the previous tri in fan order. Exactly 2 transitions =>\n            // K=2 candidate.\n            let nTransitions = 0;\n            let i1 = -1;\n            let i2 = -1;\n            for (let i = 0; i < k; i++) {\n                const t = fanTris[i];\n                const prevT = fanTris[(i - 1 + k) % k];\n                const nx1 = triNxArr[t];\n                const ny1 = triNyArr[t];\n                const nz1 = triNzArr[t];\n                const d1 = triDArr[t];\n                const nx0 = triNxArr[prevT];\n                const ny0 = triNyArr[prevT];\n                const nz0 = triNzArr[prevT];\n                const dPrev = triDArr[prevT];\n                const dotN = nx1 * nx0 + ny1 * ny0 + nz1 * nz0;\n                if (dotN < 1 - NORMAL_EPS || Math.abs(d1 - dPrev) > planeEps(d1, dPrev)) {\n                    nTransitions++;\n                    if (nTransitions === 1) i1 = i;\n                    else if (nTransitions === 2) i2 = i;\n                    else break;\n                }\n            }\n            if (nTransitions !== 2) continue;\n\n            // K=2 collinearity: ring[i1], v, ring[i2] must be collinear\n            // with v between (cosine of va-vb angle near -1).\n            const a = ring[i1];\n            const b = ring[i2];\n            const ax = positions[a * 3] - positions[v * 3];\n            const ay = positions[a * 3 + 1] - positions[v * 3 + 1];\n            const az = positions[a * 3 + 2] - positions[v * 3 + 2];\n            const bx = positions[b * 3] - positions[v * 3];\n            const by = positions[b * 3 + 1] - positions[v * 3 + 1];\n            const bz = positions[b * 3 + 2] - positions[v * 3 + 2];\n            const lenA = Math.sqrt(ax * ax + ay * ay + az * az);\n            const lenB = Math.sqrt(bx * bx + by * by + bz * bz);\n            if (lenA < 1e-12 || lenB < 1e-12) continue;\n            const cosine = (ax * bx + ay * by + az * bz) / (lenA * lenB);\n            if (cosine > cosineMax) continue;\n\n            // Two arcs: arc 0 covers tris[i1..i2-1] (mA tris, mA+1 polygon\n            // verts ring[i1..i2]); arc 1 covers tris[i2..i1-1] cyclically\n            // (mB tris, mB+1 polygon verts).\n            const mA = i2 - i1;\n            const mB = k - mA;\n            arcStartIdx[0] = i1; arcPolySize[0] = mA + 1; arcPlaneT[0] = fanTris[i1];\n            arcStartIdx[1] = i2; arcPolySize[1] = mB + 1; arcPlaneT[1] = fanTris[i2];\n            arcCount = 2;\n        }\n\n        // Build polygons and triangulations into the reusable per-arc\n        // scratch slots. Bail (without committing) if any arc fails to\n        // triangulate.\n        let allArcsOk = true;\n        for (let g = 0; g < arcCount; g++) {\n            const polySize = arcPolySize[g];\n            const startIdx = arcStartIdx[g];\n            const planeT = arcPlaneT[g];\n            ensureArcScratch(g, polySize);\n            const poly = arcPolyScratch[g];\n            for (let j = 0; j < polySize; j++) {\n                poly[j] = ring[(startIdx + j) % k];\n            }\n\n            const nx = triNxArr[planeT];\n            const ny = triNyArr[planeT];\n            const nz = triNzArr[planeT];\n            const [tx, ty, tz, bx, by, bz] = buildBasis(nx, ny, nz);\n            const px = arcPxScratch[g];\n            const py = arcPyScratch[g];\n            for (let j = 0; j < polySize; j++) {\n                const u = poly[j];\n                const x = positions[u * 3];\n                const y = positions[u * 3 + 1];\n                const z = positions[u * 3 + 2];\n                px[j] = x * tx + y * ty + z * tz;\n                py[j] = x * bx + y * by + z * bz;\n            }\n\n            const earCount = earClip(px, py, polySize, arcEarScratch[g], 0);\n            if (earCount !== (polySize - 2) * 3) {\n                allArcsOk = false;\n                break;\n            }\n            arcEarLen[g] = earCount;\n        }\n        if (!allArcsOk) continue;\n\n        // Commit: walk v's linked-list of incident tris in place. For each\n        // tri, mark it dead, unlink it from each non-v vertex's list, and\n        // free v's own node. Iteration is safe because we only mutate\n        // OTHER vertices' lists during the walk.\n        let cur = vertHead[v];\n        while (cur !== -1) {\n            const t = poolTri[cur];\n            triAliveArr[t] = 0;\n            for (let j = 0; j < 3; j++) {\n                const u = triVertsArr[t * 3 + j];\n                if (u === v) continue;\n                removeTriFromVert(u, t);\n            }\n            const nxt = poolNext[cur];\n            freeNode(cur);\n            cur = nxt;\n        }\n        vertHead[v] = -1;\n\n        // Append new tris per arc, each carrying its arc's plane.\n        for (let g = 0; g < arcCount; g++) {\n            const planeT = arcPlaneT[g];\n            const nx = triNxArr[planeT];\n            const ny = triNyArr[planeT];\n            const nz = triNzArr[planeT];\n            const d = triDArr[planeT];\n            const earIdx = arcEarScratch[g];\n            const earIdxLen = arcEarLen[g];\n            const poly = arcPolyScratch[g];\n            for (let i = 0; i < earIdxLen; i += 3) {\n                const ua = poly[earIdx[i]];\n                const ub = poly[earIdx[i + 1]];\n                const uc = poly[earIdx[i + 2]];\n                ensureTriCap();\n                const newT = triCount++;\n                triVertsArr[newT * 3] = ua;\n                triVertsArr[newT * 3 + 1] = ub;\n                triVertsArr[newT * 3 + 2] = uc;\n                triNxArr[newT] = nx;\n                triNyArr[newT] = ny;\n                triNzArr[newT] = nz;\n                triDArr[newT] = d;\n                triAliveArr[newT] = 1;\n                addTriToVert(ua, newT);\n                addTriToVert(ub, newT);\n                addTriToVert(uc, newT);\n            }\n        }\n\n        // Re-queue every ring vertex: each may now satisfy K=1 or K=2 in\n        // its updated fan, allowing the collapse to propagate along long\n        // collinear chains in a single sweep.\n        for (let i = 0; i < k; i++) {\n            pushQueue(ring[i]);\n        }\n    }\n\n    // Compact: drop dead tris and unused vertices, remap indices.\n    const usedVerts = new Uint8Array(vertCount);\n    let outTriCount = 0;\n    for (let t = 0; t < triCount; t++) {\n        if (triAliveArr[t] === 0) continue;\n        outTriCount++;\n        usedVerts[triVertsArr[t * 3]] = 1;\n        usedVerts[triVertsArr[t * 3 + 1]] = 1;\n        usedVerts[triVertsArr[t * 3 + 2]] = 1;\n    }\n\n    let outVertCount = 0;\n    const vertRemap = new Int32Array(vertCount);\n    for (let v = 0; v < vertCount; v++) {\n        if (usedVerts[v] === 1) {\n            vertRemap[v] = outVertCount++;\n        } else {\n            vertRemap[v] = -1;\n        }\n    }\n\n    const outPositions = new Float32Array(outVertCount * 3);\n    for (let v = 0; v < vertCount; v++) {\n        if (usedVerts[v] === 0) continue;\n        const o = vertRemap[v] * 3;\n        outPositions[o] = positions[v * 3];\n        outPositions[o + 1] = positions[v * 3 + 1];\n        outPositions[o + 2] = positions[v * 3 + 2];\n    }\n\n    const outIndices = new Uint32Array(outTriCount * 3);\n    let oi = 0;\n    for (let t = 0; t < triCount; t++) {\n        if (triAliveArr[t] === 0) continue;\n        outIndices[oi++] = vertRemap[triVertsArr[t * 3]];\n        outIndices[oi++] = vertRemap[triVertsArr[t * 3 + 1]];\n        outIndices[oi++] = vertRemap[triVertsArr[t * 3 + 2]];\n    }\n\n    return { positions: outPositions, indices: outIndices };\n};\n\nexport { coplanarMerge };\n","import type { Bounds } from '../data-table';\nimport type { Mesh } from './marching-cubes';\nimport {\n    BLOCK_EMPTY,\n    BLOCK_SOLID,\n    BLOCKS_PER_WORD,\n    EVEN_BITS,\n    SparseVoxelGrid,\n    readBlockType\n} from '../voxel/sparse-voxel-grid';\n\nconst HASH_MUL = 0x9E3779B9;\n\n/**\n * Extract a watertight voxel-boundary mesh from a SparseVoxelGrid.\n *\n * Exposed voxel faces are first greedily merged into axis-aligned rectangles.\n * Rectangle boundaries are then split at every collinear rectangle corner\n * before triangulation, so adjacent rectangles share matching edges instead\n * of producing T-junctions.\n *\n * @param grid - Voxel grid after filtering / nav phases.\n * @param gridBounds - Grid bounds aligned to block boundaries.\n * @param voxelResolution - Size of each voxel in world units.\n * @returns Mesh with positions and indices.\n */\nconst voxelFaces = (\n    grid: SparseVoxelGrid,\n    gridBounds: Bounds,\n    voxelResolution: number\n): Mesh => {\n    const { nbx, nby, nbz, bStride, types, masks, nx, ny, nz } = grid;\n    const totalBlocks = nbx * nby * nbz;\n    const coordStride = Math.max(nx, ny, nz) + 1;\n\n    let faceCap = 1024;\n    let faceLen = 0;\n    let faceKeys = new Float64Array(faceCap);\n\n    const addFace = (bucket: number, p: number, u: number, v: number): void => {\n        if (faceLen === faceCap) {\n            faceCap *= 2;\n            const grown = new Float64Array(faceCap);\n            grown.set(faceKeys);\n            faceKeys = grown;\n        }\n        faceKeys[faceLen++] =\n            (((bucket * coordStride + p) * coordStride + u) * coordStride + v);\n    };\n\n    const blockTypeAt = (bx: number, by: number, bz: number): number => {\n        if (bx < 0 || by < 0 || bz < 0 || bx >= nbx || by >= nby || bz >= nbz) {\n            return BLOCK_EMPTY;\n        }\n        return readBlockType(types, bx + by * nbx + bz * bStride);\n    };\n\n    const isVoxelSetLocal = (lo: number, hi: number, lx: number, ly: number, lz: number): boolean => {\n        const bitIdx = lx + (ly << 2) + (lz << 4);\n        return bitIdx < 32 ?\n            ((lo >>> bitIdx) & 1) !== 0 :\n            ((hi >>> (bitIdx - 32)) & 1) !== 0;\n    };\n\n    const isVoxelSetGlobal = (ix: number, iy: number, iz: number): boolean => {\n        if (ix < 0 || iy < 0 || iz < 0 || ix >= nx || iy >= ny || iz >= nz) {\n            return false;\n        }\n        const blockIdx = (ix >> 2) + (iy >> 2) * nbx + (iz >> 2) * bStride;\n        const bt = readBlockType(types, blockIdx);\n        if (bt === BLOCK_EMPTY) return false;\n        if (bt === BLOCK_SOLID) return true;\n        const s = masks.slot(blockIdx);\n        return isVoxelSetLocal(masks.lo[s], masks.hi[s], ix & 3, iy & 3, iz & 3);\n    };\n\n    const addVoxelFace = (ix: number, iy: number, iz: number, bucket: number): void => {\n        switch (bucket) {\n            case 0: addFace(0, ix, iy, iz); break;         // -X\n            case 1: addFace(1, ix + 1, iy, iz); break;     // +X\n            case 2: addFace(2, iy, ix, iz); break;         // -Y\n            case 3: addFace(3, iy + 1, ix, iz); break;     // +Y\n            case 4: addFace(4, iz, ix, iy); break;         // -Z\n            default: addFace(5, iz + 1, ix, iy); break;    // +Z\n        }\n    };\n\n    const processSolidBlock = (bx: number, by: number, bz: number): void => {\n        const x0 = bx << 2;\n        const y0 = by << 2;\n        const z0 = bz << 2;\n\n        const emitX = (bucket: number, neighborBlockType: number, ix: number, nx2: number): void => {\n            if (neighborBlockType === BLOCK_SOLID) return;\n            for (let lz = 0; lz < 4; lz++) {\n                const iz = z0 + lz;\n                for (let ly = 0; ly < 4; ly++) {\n                    const iy = y0 + ly;\n                    if (neighborBlockType === BLOCK_EMPTY || !isVoxelSetGlobal(nx2, iy, iz)) {\n                        addVoxelFace(ix, iy, iz, bucket);\n                    }\n                }\n            }\n        };\n\n        const emitY = (bucket: number, neighborBlockType: number, iy: number, ny2: number): void => {\n            if (neighborBlockType === BLOCK_SOLID) return;\n            for (let lz = 0; lz < 4; lz++) {\n                const iz = z0 + lz;\n                for (let lx = 0; lx < 4; lx++) {\n                    const ix = x0 + lx;\n                    if (neighborBlockType === BLOCK_EMPTY || !isVoxelSetGlobal(ix, ny2, iz)) {\n                        addVoxelFace(ix, iy, iz, bucket);\n                    }\n                }\n            }\n        };\n\n        const emitZ = (bucket: number, neighborBlockType: number, iz: number, nz2: number): void => {\n            if (neighborBlockType === BLOCK_SOLID) return;\n            for (let ly = 0; ly < 4; ly++) {\n                const iy = y0 + ly;\n                for (let lx = 0; lx < 4; lx++) {\n                    const ix = x0 + lx;\n                    if (neighborBlockType === BLOCK_EMPTY || !isVoxelSetGlobal(ix, iy, nz2)) {\n                        addVoxelFace(ix, iy, iz, bucket);\n                    }\n                }\n            }\n        };\n\n        emitX(0, blockTypeAt(bx - 1, by, bz), x0, x0 - 1);\n        emitX(1, blockTypeAt(bx + 1, by, bz), x0 + 3, x0 + 4);\n        emitY(2, blockTypeAt(bx, by - 1, bz), y0, y0 - 1);\n        emitY(3, blockTypeAt(bx, by + 1, bz), y0 + 3, y0 + 4);\n        emitZ(4, blockTypeAt(bx, by, bz - 1), z0, z0 - 1);\n        emitZ(5, blockTypeAt(bx, by, bz + 1), z0 + 3, z0 + 4);\n    };\n\n    const processMixedBlock = (blockIdx: number, bx: number, by: number, bz: number): void => {\n        const s = masks.slot(blockIdx);\n        const lo = masks.lo[s];\n        const hi = masks.hi[s];\n        const x0 = bx << 2;\n        const y0 = by << 2;\n        const z0 = bz << 2;\n\n        for (let lz = 0; lz < 4; lz++) {\n            const iz = z0 + lz;\n            for (let ly = 0; ly < 4; ly++) {\n                const iy = y0 + ly;\n                for (let lx = 0; lx < 4; lx++) {\n                    if (!isVoxelSetLocal(lo, hi, lx, ly, lz)) continue;\n                    const ix = x0 + lx;\n                    if (!isVoxelSetGlobal(ix - 1, iy, iz)) addVoxelFace(ix, iy, iz, 0);\n                    if (!isVoxelSetGlobal(ix + 1, iy, iz)) addVoxelFace(ix, iy, iz, 1);\n                    if (!isVoxelSetGlobal(ix, iy - 1, iz)) addVoxelFace(ix, iy, iz, 2);\n                    if (!isVoxelSetGlobal(ix, iy + 1, iz)) addVoxelFace(ix, iy, iz, 3);\n                    if (!isVoxelSetGlobal(ix, iy, iz - 1)) addVoxelFace(ix, iy, iz, 4);\n                    if (!isVoxelSetGlobal(ix, iy, iz + 1)) addVoxelFace(ix, iy, iz, 5);\n                }\n            }\n        }\n    };\n\n    for (let w = 0; w < types.length; w++) {\n        const word = types[w];\n        if (word === 0) continue;\n        let nonEmpty = ((word & EVEN_BITS) | ((word >>> 1) & EVEN_BITS)) >>> 0;\n        const baseBlockIdx = w * BLOCKS_PER_WORD;\n        while (nonEmpty) {\n            const bp = 31 - Math.clz32(nonEmpty & -nonEmpty);\n            const lane = bp >>> 1;\n            const blockIdx = baseBlockIdx + lane;\n            nonEmpty &= nonEmpty - 1;\n            if (blockIdx >= totalBlocks) break;\n\n            const bx = blockIdx % nbx;\n            const byBz = (blockIdx / nbx) | 0;\n            const by = byBz % nby;\n            const bz = (byBz / nby) | 0;\n            const bt = (word >>> (lane << 1)) & 3;\n            if (bt === BLOCK_SOLID) {\n                processSolidBlock(bx, by, bz);\n            } else {\n                processMixedBlock(blockIdx, bx, by, bz);\n            }\n        }\n    }\n\n    if (faceLen === 0) {\n        return { positions: new Float32Array(0), indices: new Uint32Array(0) };\n    }\n\n    let rectCap = 1024;\n    let rectLen = 0;\n    let rectBucket = new Int32Array(rectCap);\n    let rectP = new Int32Array(rectCap);\n    let rectU0 = new Int32Array(rectCap);\n    let rectV0 = new Int32Array(rectCap);\n    let rectU1 = new Int32Array(rectCap);\n    let rectV1 = new Int32Array(rectCap);\n\n    const addRect = (bucket: number, p: number, u0: number, v0: number, u1: number, v1: number): void => {\n        if (rectLen === rectCap) {\n            rectCap *= 2;\n            const grow = (src: Int32Array<ArrayBuffer>): Int32Array<ArrayBuffer> => {\n                const out = new Int32Array(rectCap);\n                out.set(src);\n                return out;\n            };\n            rectBucket = grow(rectBucket);\n            rectP = grow(rectP);\n            rectU0 = grow(rectU0);\n            rectV0 = grow(rectV0);\n            rectU1 = grow(rectU1);\n            rectV1 = grow(rectV1);\n        }\n        rectBucket[rectLen] = bucket;\n        rectP[rectLen] = p;\n        rectU0[rectLen] = u0;\n        rectV0[rectLen] = v0;\n        rectU1[rectLen] = u1;\n        rectV1[rectLen] = v1;\n        rectLen++;\n    };\n\n    const keys = faceKeys.subarray(0, faceLen);\n    faceKeys = new Float64Array(0);\n    keys.sort();\n\n    const decodeGroup = (key: number): { bucket: number; p: number } => {\n        let q = Math.floor(key / coordStride);\n        q = Math.floor(q / coordStride);\n        const p = q % coordStride;\n        const bucket = Math.floor(q / coordStride);\n        return { bucket, p };\n    };\n\n    const decodeUvKey = (key: number): number => {\n        const v = key % coordStride;\n        const q = Math.floor(key / coordStride);\n        const u = q % coordStride;\n        return u * coordStride + v;\n    };\n\n    let groupStart = 0;\n    while (groupStart < keys.length) {\n        const { bucket, p } = decodeGroup(keys[groupStart]);\n        let groupEnd = groupStart + 1;\n        while (groupEnd < keys.length) {\n            const g = decodeGroup(keys[groupEnd]);\n            if (g.bucket !== bucket || g.p !== p) break;\n            groupEnd++;\n        }\n\n        const count = groupEnd - groupStart;\n        let hCap = 1;\n        while (hCap < count / 0.7) hCap *= 2;\n        const hMask = hCap - 1;\n        const hKeys = new Float64Array(hCap).fill(-1);\n        const hVals = new Int32Array(hCap);\n\n        const hash = (key: number): number => {\n            const hi = (key / 0x100000000) | 0;\n            return (Math.imul((key | 0) ^ hi, HASH_MUL) >>> 0) & hMask;\n        };\n\n        for (let i = 0; i < count; i++) {\n            const uvKey = decodeUvKey(keys[groupStart + i]);\n            let h = hash(uvKey);\n            while (hKeys[h] !== -1) h = (h + 1) & hMask;\n            hKeys[h] = uvKey;\n            hVals[h] = i;\n        }\n\n        const lookup = (uvKey: number): number => {\n            let h = hash(uvKey);\n            while (true) {\n                const k = hKeys[h];\n                if (k === uvKey) return hVals[h];\n                if (k === -1) return -1;\n                h = (h + 1) & hMask;\n            }\n        };\n\n        const visited = new Uint8Array(count);\n        const uvKeyOf = (u: number, v: number): number => u * coordStride + v;\n\n        for (let i = 0; i < count; i++) {\n            if (visited[i]) continue;\n            const uvKey = decodeUvKey(keys[groupStart + i]);\n            const u0 = Math.floor(uvKey / coordStride);\n            const v0 = uvKey % coordStride;\n\n            let width = 1;\n            while (true) {\n                const idx = lookup(uvKeyOf(u0 + width, v0));\n                if (idx === -1 || visited[idx]) break;\n                width++;\n            }\n\n            let height = 1;\n            while (true) {\n                let canGrow = true;\n                for (let du = 0; du < width; du++) {\n                    const idx = lookup(uvKeyOf(u0 + du, v0 + height));\n                    if (idx === -1 || visited[idx]) {\n                        canGrow = false;\n                        break;\n                    }\n                }\n                if (!canGrow) break;\n                height++;\n            }\n\n            for (let dv = 0; dv < height; dv++) {\n                for (let du = 0; du < width; du++) {\n                    visited[lookup(uvKeyOf(u0 + du, v0 + dv))] = 1;\n                }\n            }\n\n            addRect(bucket, p, u0, v0, u0 + width, v0 + height);\n        }\n\n        groupStart = groupEnd;\n    }\n\n    const globalPoint = (\n        axis: number,\n        p: number,\n        u: number,\n        v: number\n    ): [number, number, number] => {\n        if (axis === 0) return [p, u, v];\n        if (axis === 1) return [u, p, v];\n        return [u, v, p];\n    };\n\n    const lineKey = (varAxis: number, x: number, y: number, z: number): number => {\n        if (varAxis === 0) return (y + z * coordStride) * 3;\n        if (varAxis === 1) return (x + z * coordStride) * 3 + 1;\n        return (x + y * coordStride) * 3 + 2;\n    };\n\n    const linePoints = new Map<number, number[]>();\n\n    const addLinePoint = (key: number, value: number): void => {\n        let points = linePoints.get(key);\n        if (!points) {\n            points = [];\n            linePoints.set(key, points);\n        }\n        points.push(value);\n    };\n\n    const addLineSegment = (\n        x0: number, y0: number, z0: number,\n        x1: number, y1: number, z1: number\n    ): void => {\n        if (x0 !== x1) {\n            const key = lineKey(0, x0, y0, z0);\n            addLinePoint(key, x0);\n            addLinePoint(key, x1);\n        } else if (y0 !== y1) {\n            const key = lineKey(1, x0, y0, z0);\n            addLinePoint(key, y0);\n            addLinePoint(key, y1);\n        } else {\n            const key = lineKey(2, x0, y0, z0);\n            addLinePoint(key, z0);\n            addLinePoint(key, z1);\n        }\n    };\n\n    for (let r = 0; r < rectLen; r++) {\n        const axis = rectBucket[r] >> 1;\n        const p = rectP[r];\n        const a = globalPoint(axis, p, rectU0[r], rectV0[r]);\n        const b = globalPoint(axis, p, rectU1[r], rectV0[r]);\n        const c = globalPoint(axis, p, rectU1[r], rectV1[r]);\n        const d = globalPoint(axis, p, rectU0[r], rectV1[r]);\n        addLineSegment(a[0], a[1], a[2], b[0], b[1], b[2]);\n        addLineSegment(b[0], b[1], b[2], c[0], c[1], c[2]);\n        addLineSegment(c[0], c[1], c[2], d[0], d[1], d[2]);\n        addLineSegment(d[0], d[1], d[2], a[0], a[1], a[2]);\n    }\n\n    for (const points of linePoints.values()) {\n        points.sort((a, b) => a - b);\n        let write = 0;\n        for (let i = 0; i < points.length; i++) {\n            if (i === 0 || points[i] !== points[i - 1]) {\n                points[write++] = points[i];\n            }\n        }\n        points.length = write;\n    }\n\n    let posCap = 1024;\n    let posLen = 0;\n    let positions = new Float32Array(posCap);\n    let idxCap = 1024;\n    let idxLen = 0;\n    let indices = new Uint32Array(idxCap);\n    const vertexMap = new Map<number, number>();\n    let perimeterScratch = new Uint32Array(16);\n    let perimeterU = new Int32Array(16);\n    let perimeterV = new Int32Array(16);\n    let perimeterLen = 0;\n    let triPrev = new Int32Array(16);\n    let triNext = new Int32Array(16);\n\n    const addPosition = (x: number, y: number, z: number): number => {\n        if (posLen + 3 > posCap) {\n            posCap *= 2;\n            const grown = new Float32Array(posCap);\n            grown.set(positions);\n            positions = grown;\n        }\n        const idx = posLen / 3;\n        positions[posLen++] = gridBounds.min.x + x * voxelResolution;\n        positions[posLen++] = gridBounds.min.y + y * voxelResolution;\n        positions[posLen++] = gridBounds.min.z + z * voxelResolution;\n        return idx;\n    };\n\n    const vertexKey = (x: number, y: number, z: number): number => {\n        return (x + y * coordStride + z * coordStride * coordStride);\n    };\n\n    const getVertex = (x: number, y: number, z: number): number => {\n        const key = vertexKey(x, y, z);\n        const existing = vertexMap.get(key);\n        if (existing !== undefined) return existing;\n        const idx = addPosition(x, y, z);\n        vertexMap.set(key, idx);\n        return idx;\n    };\n\n    const ensureIndexCapacity = (additional: number): void => {\n        if (idxLen + additional <= idxCap) return;\n        while (idxLen + additional > idxCap) idxCap *= 2;\n        const grown = new Uint32Array(idxCap);\n        grown.set(indices);\n        indices = grown;\n    };\n\n    const appendTri = (a: number, b: number, c: number): void => {\n        ensureIndexCapacity(3);\n        indices[idxLen++] = a;\n        indices[idxLen++] = b;\n        indices[idxLen++] = c;\n    };\n\n    const resetPerimeter = (): void => {\n        perimeterLen = 0;\n    };\n\n    const localUv = (axis: number, x: number, y: number, z: number): [number, number] => {\n        if (axis === 0) return [y, z];\n        if (axis === 1) return [x, z];\n        return [x, y];\n    };\n\n    const addPerimeterVertex = (v: number, u: number, pv: number): void => {\n        if (perimeterLen > 0 && perimeterScratch[perimeterLen - 1] === v) return;\n        if (perimeterLen === perimeterScratch.length) {\n            const grown = new Uint32Array(perimeterScratch.length * 2);\n            grown.set(perimeterScratch);\n            perimeterScratch = grown;\n            const grownU = new Int32Array(perimeterU.length * 2);\n            grownU.set(perimeterU);\n            perimeterU = grownU;\n            const grownV = new Int32Array(perimeterV.length * 2);\n            grownV.set(perimeterV);\n            perimeterV = grownV;\n        }\n        perimeterScratch[perimeterLen++] = v;\n        perimeterU[perimeterLen - 1] = u;\n        perimeterV[perimeterLen - 1] = pv;\n    };\n\n    const addEdgeVertices = (\n        axis: number,\n        x0: number, y0: number, z0: number,\n        x1: number, y1: number, z1: number\n    ): void => {\n        let varAxis: number;\n        let start: number;\n        let end: number;\n        if (x0 !== x1) {\n            varAxis = 0;\n            start = x0;\n            end = x1;\n        } else if (y0 !== y1) {\n            varAxis = 1;\n            start = y0;\n            end = y1;\n        } else {\n            varAxis = 2;\n            start = z0;\n            end = z1;\n        }\n\n        const key = lineKey(varAxis, x0, y0, z0);\n        const points = linePoints.get(key);\n        if (!points) return;\n\n        const lo = Math.min(start, end);\n        const hi = Math.max(start, end);\n        const forward = start <= end;\n\n        const emitPoint = (x: number, y: number, z: number): void => {\n            const [u, v] = localUv(axis, x, y, z);\n            addPerimeterVertex(getVertex(x, y, z), u, v);\n        };\n\n        if (forward) {\n            for (let i = 0; i < points.length; i++) {\n                const t = points[i];\n                if (t < lo) continue;\n                if (t > hi) break;\n                if (varAxis === 0) emitPoint(t, y0, z0);\n                else if (varAxis === 1) emitPoint(x0, t, z0);\n                else emitPoint(x0, y0, t);\n            }\n        } else {\n            for (let i = points.length - 1; i >= 0; i--) {\n                const t = points[i];\n                if (t > hi) continue;\n                if (t < lo) break;\n                if (varAxis === 0) emitPoint(t, y0, z0);\n                else if (varAxis === 1) emitPoint(x0, t, z0);\n                else emitPoint(x0, y0, t);\n            }\n        }\n    };\n\n    const isConvexEar = (prev: number, curr: number, next: number): boolean => {\n        const ax = perimeterU[curr] - perimeterU[prev];\n        const ay = perimeterV[curr] - perimeterV[prev];\n        const bx = perimeterU[next] - perimeterU[prev];\n        const by = perimeterV[next] - perimeterV[prev];\n        return ax * by - ay * bx > 0;\n    };\n\n    const isNonDegenerateTri = (a: number, b: number, c: number): boolean => {\n        const ax = perimeterU[b] - perimeterU[a];\n        const ay = perimeterV[b] - perimeterV[a];\n        const bx = perimeterU[c] - perimeterU[a];\n        const by = perimeterV[c] - perimeterV[a];\n        return ax * by - ay * bx > 0;\n    };\n\n    const appendOrientedTri = (a: number, b: number, c: number, useLocalCcw: boolean): void => {\n        if (useLocalCcw) appendTri(a, b, c);\n        else appendTri(a, c, b);\n    };\n\n    const triangulatePerimeter = (useLocalCcw: boolean): void => {\n        if (perimeterLen < 3) return;\n\n        if (perimeterLen > triPrev.length) {\n            let cap = triPrev.length;\n            while (perimeterLen > cap) cap *= 2;\n            triPrev = new Int32Array(cap);\n            triNext = new Int32Array(cap);\n        }\n\n        for (let i = 0; i < perimeterLen; i++) {\n            triPrev[i] = i === 0 ? perimeterLen - 1 : i - 1;\n            triNext[i] = i === perimeterLen - 1 ? 0 : i + 1;\n        }\n\n        let remaining = perimeterLen;\n        let current = 0;\n        let attempts = 0;\n\n        while (remaining > 3 && attempts < remaining) {\n            const prev = triPrev[current];\n            const next = triNext[current];\n            const next2 = triNext[next];\n            const keepsArea = remaining !== 4 || isNonDegenerateTri(prev, next, next2);\n            if (keepsArea && isConvexEar(prev, current, next)) {\n                appendOrientedTri(\n                    perimeterScratch[prev],\n                    perimeterScratch[current],\n                    perimeterScratch[next],\n                    useLocalCcw\n                );\n                triNext[prev] = next;\n                triPrev[next] = prev;\n                current = next;\n                remaining--;\n                attempts = 0;\n            } else {\n                current = next;\n                attempts++;\n            }\n        }\n\n        if (remaining === 3) {\n            const a = current;\n            const b = triNext[a];\n            const c = triNext[b];\n            if (isConvexEar(a, b, c)) {\n                appendOrientedTri(\n                    perimeterScratch[a],\n                    perimeterScratch[b],\n                    perimeterScratch[c],\n                    useLocalCcw\n                );\n            }\n        }\n    };\n\n    for (let r = 0; r < rectLen; r++) {\n        const bucket = rectBucket[r];\n        const axis = bucket >> 1;\n        const positive = (bucket & 1) === 1;\n        const p = rectP[r];\n        const u0 = rectU0[r];\n        const v0 = rectV0[r];\n        const u1 = rectU1[r];\n        const v1 = rectV1[r];\n        const a = globalPoint(axis, p, u0, v0);\n        const b = globalPoint(axis, p, u1, v0);\n        const c = globalPoint(axis, p, u1, v1);\n        const d = globalPoint(axis, p, u0, v1);\n\n        resetPerimeter();\n        addEdgeVertices(axis, a[0], a[1], a[2], b[0], b[1], b[2]);\n        addEdgeVertices(axis, b[0], b[1], b[2], c[0], c[1], c[2]);\n        addEdgeVertices(axis, c[0], c[1], c[2], d[0], d[1], d[2]);\n        addEdgeVertices(axis, d[0], d[1], d[2], a[0], a[1], a[2]);\n        if (perimeterLen > 1 && perimeterScratch[0] === perimeterScratch[perimeterLen - 1]) {\n            perimeterLen--;\n        }\n        if (perimeterLen < 3) continue;\n\n        const localCcwIsPositive = axis !== 1;\n        const useLocalCcw = positive === localCcwIsPositive;\n\n        triangulatePerimeter(useLocalCcw);\n    }\n\n    return {\n        positions: positions.slice(0, posLen),\n        indices: indices.slice(0, idxLen)\n    };\n};\n\nexport { voxelFaces };\n","import type { Bounds } from '../data-table';\nimport { coplanarMerge, marchingCubes, voxelFaces, type Mesh } from '../mesh';\nimport type { CollisionMeshShape } from '../types';\nimport { fmtCount, logger } from '../utils';\nimport { SparseVoxelGrid } from '../voxel/sparse-voxel-grid';\n\n/**\n * Build a minimal GLB (glTF 2.0 binary) file containing a single triangle mesh.\n *\n * The output contains only positions and triangle indices — no normals,\n * UVs, or materials — suitable for collision meshes.\n *\n * @param positions - Vertex positions (3 floats per vertex)\n * @param indices - Triangle indices (3 per triangle, unsigned 32-bit)\n * @returns GLB file as a Uint8Array\n */\nfunction encodeGlb(positions: Float32Array, indices: Uint32Array): Uint8Array {\n    const vertexCount = positions.length / 3;\n    const indexCount = indices.length;\n\n    let minX = Infinity, minY = Infinity, minZ = Infinity;\n    let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;\n    for (let i = 0; i < positions.length; i += 3) {\n        const x = positions[i], y = positions[i + 1], z = positions[i + 2];\n        if (x < minX) minX = x;\n        if (y < minY) minY = y;\n        if (z < minZ) minZ = z;\n        if (x > maxX) maxX = x;\n        if (y > maxY) maxY = y;\n        if (z > maxZ) maxZ = z;\n    }\n\n    const positionsByteLength = positions.byteLength;\n    const indicesByteLength = indices.byteLength;\n    const totalBinSize = positionsByteLength + indicesByteLength;\n\n    const gltf = {\n        asset: { version: '2.0', generator: 'splat-transform' },\n        scene: 0,\n        scenes: [{ nodes: [0] }],\n        nodes: [{ mesh: 0 }],\n        meshes: [{\n            primitives: [{\n                attributes: { POSITION: 0 },\n                indices: 1\n            }]\n        }],\n        accessors: [\n            {\n                bufferView: 0,\n                componentType: 5126, // FLOAT\n                count: vertexCount,\n                type: 'VEC3',\n                min: [minX, minY, minZ],\n                max: [maxX, maxY, maxZ]\n            },\n            {\n                bufferView: 1,\n                componentType: 5125, // UNSIGNED_INT\n                count: indexCount,\n                type: 'SCALAR'\n            }\n        ],\n        bufferViews: [\n            {\n                buffer: 0,\n                byteOffset: 0,\n                byteLength: positionsByteLength,\n                target: 34962 // ARRAY_BUFFER\n            },\n            {\n                buffer: 0,\n                byteOffset: positionsByteLength,\n                byteLength: indicesByteLength,\n                target: 34963 // ELEMENT_ARRAY_BUFFER\n            }\n        ],\n        buffers: [{ byteLength: totalBinSize }]\n    };\n\n    const jsonString = JSON.stringify(gltf);\n    const jsonEncoder = new TextEncoder();\n    const jsonBytes = jsonEncoder.encode(jsonString);\n\n    // JSON chunk must be padded to 4-byte alignment with spaces (0x20)\n    const jsonPadding = (4 - (jsonBytes.length % 4)) % 4;\n    const jsonChunkLength = jsonBytes.length + jsonPadding;\n\n    // BIN chunk must be padded to 4-byte alignment with zeros\n    const binPadding = (4 - (totalBinSize % 4)) % 4;\n    const binChunkLength = totalBinSize + binPadding;\n\n    // GLB layout: header (12) + JSON chunk header (8) + JSON data + BIN chunk header (8) + BIN data\n    const totalLength = 12 + 8 + jsonChunkLength + 8 + binChunkLength;\n    const buffer = new ArrayBuffer(totalLength);\n    const view = new DataView(buffer);\n    const byteArray = new Uint8Array(buffer);\n    let offset = 0;\n\n    // GLB header\n    view.setUint32(offset, 0x46546C67, true); offset += 4; // magic: \"glTF\"\n    view.setUint32(offset, 2, true); offset += 4;           // version: 2\n    view.setUint32(offset, totalLength, true); offset += 4;  // total length\n\n    // JSON chunk header\n    view.setUint32(offset, jsonChunkLength, true); offset += 4;\n    view.setUint32(offset, 0x4E4F534A, true); offset += 4; // type: \"JSON\"\n\n    // JSON chunk data\n    byteArray.set(jsonBytes, offset); offset += jsonBytes.length;\n    for (let i = 0; i < jsonPadding; i++) {\n        byteArray[offset++] = 0x20;\n    }\n\n    // BIN chunk header\n    view.setUint32(offset, binChunkLength, true); offset += 4;\n    view.setUint32(offset, 0x004E4942, true); offset += 4; // type: \"BIN\\0\"\n\n    // BIN chunk data: positions then indices\n    byteArray.set(new Uint8Array(positions.buffer, positions.byteOffset, positionsByteLength), offset);\n    offset += positionsByteLength;\n    byteArray.set(new Uint8Array(indices.buffer, indices.byteOffset, indicesByteLength), offset);\n\n    return byteArray;\n}\n\n/**\n * Extract a collision mesh from voxel data and encode it as a GLB file.\n *\n * Generates collision geometry from voxel data using either the smooth\n * marching-cubes path or a direct watertight voxel-face mesh.\n *\n * @param grid - Voxel grid after filtering / nav phases\n * @param gridBounds - Grid bounds aligned to block boundaries\n * @param voxelResolution - Size of each voxel in world units\n * @param shape - Collision mesh shape to generate\n * @returns GLB bytes, or null if no triangles were generated\n */\nconst buildCollisionMesh = (\n    grid: SparseVoxelGrid,\n    gridBounds: Bounds,\n    voxelResolution: number,\n    shape: CollisionMeshShape = 'smooth'\n): Uint8Array | null => {\n    const g = logger.group('Collision mesh');\n\n    let finalMesh: Mesh;\n    if (shape === 'faces') {\n        const extractSub = logger.group('Extracting voxel faces');\n        finalMesh = voxelFaces(grid, gridBounds, voxelResolution);\n        logger.info(`vertices: ${fmtCount(finalMesh.positions.length / 3)}`);\n        logger.info(`triangles: ${fmtCount(finalMesh.indices.length / 3)}`);\n        extractSub.end();\n    } else {\n        const extractSub = logger.group('Extracting');\n        const preMergedMesh = marchingCubes(grid, gridBounds, voxelResolution, { mergeFlatFaces: true });\n        logger.info(`pre-merged vertices: ${fmtCount(preMergedMesh.positions.length / 3)}`);\n        logger.info(`pre-merged triangles: ${fmtCount(preMergedMesh.indices.length / 3)}`);\n        const preMergedIndexCount = preMergedMesh.indices.length;\n        extractSub.end();\n\n        if (preMergedIndexCount < 3) {\n            finalMesh = preMergedMesh;\n        } else {\n            const mergeSub = logger.group('Merging coplanar faces');\n            finalMesh = coplanarMerge(preMergedMesh, voxelResolution);\n\n            const reduction = (1 - finalMesh.indices.length / preMergedIndexCount) * 100;\n            logger.info(`merged vertices: ${fmtCount(finalMesh.positions.length / 3)}`);\n            logger.info(`merged triangles: ${fmtCount(finalMesh.indices.length / 3)}`);\n            logger.info(`reduction: ${reduction.toFixed(0)}%`);\n            mergeSub.end();\n        }\n    }\n\n    if (finalMesh.indices.length < 3) {\n        logger.warn('no triangles generated, skipping GLB output');\n        g.end();\n        return null;\n    }\n\n    g.end();\n    return encodeGlb(finalMesh.positions, finalMesh.indices);\n};\n\nexport { buildCollisionMesh };\n","import { Vec3 } from 'playcanvas';\n\nimport type { Bounds } from '../data-table';\nimport { logger } from '../utils';\nimport { popcount, xyzToMorton } from '../voxel/morton';\nimport {\n    BLOCK_EMPTY,\n    BLOCK_MIXED,\n    BLOCK_SOLID,\n    BLOCKS_PER_WORD,\n    EVEN_BITS,\n    SparseVoxelGrid,\n    TYPE_MASK,\n    readBlockType,\n    writeBlockType\n} from '../voxel/sparse-voxel-grid';\n\n/**\n * Solid leaf node marker: childMask = 0xFF, baseOffset = 0.\n * This is unambiguous because BFS layout guarantees children always come after\n * their parent, so baseOffset = 0 is never valid for an interior node.\n */\nconst SOLID_LEAF_MARKER = 0xFF000000 >>> 0;\n\n/**\n * Maximum value encodable in the low 24 bits of a Laine-Karras node word.\n * Both the interior `baseOffset` (child node index) and the mixed-leaf\n * `leafDataIndex` share this ceiling: indices range 0..MAX_24BIT_OFFSET\n * (= 0xFFFFFF = 16,777,215), giving up to 16,777,216 distinct encodable\n * values. (Interior nodes additionally reserve baseOffset=0 for\n * `SOLID_LEAF_MARKER`, so the practical interior cap is 16,777,215.)\n */\nconst MAX_24BIT_OFFSET = 0x00FFFFFF;\n\nconst DENSE_SOLID_STREAM_THRESHOLD = 8_000_000;\n\n// ============================================================================\n// Sparse Octree Types\n// ============================================================================\n\n/**\n * Sparse voxel octree using Laine-Karras node format.\n */\ninterface SparseOctree {\n    /** Grid bounds aligned to 4x4x4 block boundaries */\n    gridBounds: Bounds;\n\n    /** Original Gaussian scene bounds */\n    sceneBounds: Bounds;\n\n    /** Size of each voxel in world units */\n    voxelResolution: number;\n\n    /** Voxels per leaf dimension (always 4) */\n    leafSize: number;\n\n    /** Maximum tree depth */\n    treeDepth: number;\n\n    /** Number of interior nodes */\n    numInteriorNodes: number;\n\n    /** Number of mixed leaf nodes */\n    numMixedLeaves: number;\n\n    /** All nodes in Laine-Karras format (interior + leaves) */\n    nodes: Uint32Array;\n\n    /** Voxel masks for mixed leaves: pairs of u32 (lo, hi) */\n    leafData: Uint32Array;\n}\n\ninterface BuildSparseOctreeOptions {\n    /** Release the input grid's backing storage after the octree has copied the data it needs. */\n    consumeGrid?: boolean;\n    /** Force dense-mip construction; intended for tests and benchmarks. */\n    dense?: boolean;\n}\n\n// ============================================================================\n// Octree Node Types (during construction)\n// ============================================================================\n\n/** Block type enumeration */\nconst enum BlockType {\n    Empty = 0,\n    Solid = 1,\n    Mixed = 2\n}\n\n/**\n * Per-level data stored during bottom-up construction.\n * Uses Structure-of-Arrays layout to avoid per-node object allocation.\n *\n * After the dual-stream refactor, level 0 is held outside `interiorLevels`\n * (in `solidStream` + `mixedStream` + `mixedMasks`), so every entry stored\n * here is an interior node and `childMasks` is always non-null.\n */\ninterface LevelData {\n    /** Sorted Morton codes for nodes at this level */\n    mortons: number[];\n    /** Block type for each node (Solid or Mixed) */\n    types: number[];\n    /** 8-bit child presence mask for each node */\n    childMasks: number[];\n}\n\n/**\n * Interior nodes waiting for child emission during BFS flattening.\n * Children are written immediately, so this wave never contains leaves.\n */\ninterface InteriorWave {\n    pos: Uint32Array;\n    li: Uint32Array;\n    ii: Uint32Array;\n    length: number;\n}\n\ninterface DenseLevel {\n    types: Uint32Array;\n    nbx: number;\n    nby: number;\n    nbz: number;\n    nonEmptyCount: number;\n}\n\n// ============================================================================\n// Mixed-stream Sort\n// ============================================================================\n\n/**\n * Iterative quicksort that sorts mixed-block mortons in place, permuting the\n * paired interleaved [lo, hi] mask pairs alongside. Median-of-three pivot,\n * insertion-sort fallback for small partitions.\n *\n * Avoids `TypedArray.prototype.sort(comparefn)` so we are not bounded by\n * FixedArray::kMaxLength (~134M elements with V8 pointer compression).\n *\n * Tailored to the (Float64 morton, Uint32×2 mask) layout used by\n * `BlockMaskBuffer` so the buffer's typed arrays can serve as the sorted\n * data directly — no SoA copy required. The solid stream uses the native\n * `Float64Array.sort()` (no comparefn) and doesn't need a custom path.\n *\n * @param mortons - Morton codes; sort key.\n * @param masks - Interleaved [lo, hi] mask pairs (length = 2 * n).\n * @param n - Number of mixed entries to sort.\n */\nfunction sortMixedByMorton(\n    mortons: Float64Array,\n    masks: Uint32Array,\n    n: number\n): void {\n    if (n < 2) return;\n\n    const swap = (a: number, b: number): void => {\n        const tm = mortons[a]; mortons[a] = mortons[b]; mortons[b] = tm;\n        const a2 = a * 2, b2 = b * 2;\n        const tlo = masks[a2]; masks[a2] = masks[b2]; masks[b2] = tlo;\n        const thi = masks[a2 + 1]; masks[a2 + 1] = masks[b2 + 1]; masks[b2 + 1] = thi;\n    };\n\n    const stack = new Int32Array(64);\n    let sp = 0;\n    stack[sp++] = 0;\n    stack[sp++] = n - 1;\n\n    while (sp > 0) {\n        const hi = stack[--sp];\n        const lo = stack[--sp];\n\n        if (hi - lo < 16) {\n            // Insertion sort\n            for (let i = lo + 1; i <= hi; i++) {\n                const km = mortons[i];\n                const kl = masks[i * 2];\n                const kh = masks[i * 2 + 1];\n                let j = i - 1;\n                while (j >= lo && mortons[j] > km) {\n                    mortons[j + 1] = mortons[j];\n                    masks[(j + 1) * 2] = masks[j * 2];\n                    masks[(j + 1) * 2 + 1] = masks[j * 2 + 1];\n                    j--;\n                }\n                mortons[j + 1] = km;\n                masks[(j + 1) * 2] = kl;\n                masks[(j + 1) * 2 + 1] = kh;\n            }\n            continue;\n        }\n\n        const mid = (lo + hi) >>> 1;\n        if (mortons[lo] > mortons[mid]) swap(lo, mid);\n        if (mortons[lo] > mortons[hi]) swap(lo, hi);\n        if (mortons[mid] > mortons[hi]) swap(mid, hi);\n        swap(mid, hi - 1);\n        const pivot = mortons[hi - 1];\n\n        let i = lo;\n        let j = hi - 1;\n        while (true) {\n            while (mortons[++i] < pivot) { /* sentinel at hi */ }\n            while (mortons[--j] > pivot) { /* sentinel at lo */ }\n            if (i >= j) break;\n            swap(i, j);\n        }\n        swap(i, hi - 1);\n\n        const leftSize = i - 1 - lo;\n        const rightSize = hi - (i + 1);\n        if (leftSize > rightSize) {\n            stack[sp++] = lo;\n            stack[sp++] = i - 1;\n            if (rightSize > 0) {\n                stack[sp++] = i + 1;\n                stack[sp++] = hi;\n            }\n        } else {\n            if (rightSize > 0) {\n                stack[sp++] = i + 1;\n                stack[sp++] = hi;\n            }\n            if (leftSize > 0) {\n                stack[sp++] = lo;\n                stack[sp++] = i - 1;\n            }\n        }\n    }\n}\n\n/**\n * Binary-search lowest index i in `arr[0..n)` such that `arr[i] >= target`.\n * Returns `n` if all entries are less than `target`.\n *\n * @param arr - Sorted Float64Array.\n * @param target - Value to search for.\n * @param n - Upper bound of the search range (exclusive).\n * @returns Smallest index `i` with `arr[i] >= target`, or `n`.\n */\nfunction lowerBoundF64(arr: Float64Array, target: number, n: number): number {\n    let lo = 0;\n    let hi = n;\n    while (lo < hi) {\n        const mid = (lo + hi) >>> 1;\n        if (arr[mid] < target) lo = mid + 1;\n        else hi = mid;\n    }\n    return lo;\n}\n\n/**\n * Create an interior BFS wave buffer.\n *\n * @param initialCapacity - Initial entry capacity.\n * @returns Empty interior wave.\n */\nfunction createInteriorWave(initialCapacity: number): InteriorWave {\n    const cap = Math.max(16, initialCapacity);\n    return {\n        pos: new Uint32Array(cap),\n        li: new Uint32Array(cap),\n        ii: new Uint32Array(cap),\n        length: 0\n    };\n}\n\n/**\n * Append an interior node to a BFS wave, growing the typed arrays if needed.\n *\n * @param wave - Target wave.\n * @param pos - Already-emitted node position to backfill.\n * @param li - Interior level index.\n * @param ii - Node index within the level.\n */\nfunction pushInteriorWave(\n    wave: InteriorWave,\n    pos: number,\n    li: number,\n    ii: number\n): void {\n    if (wave.length === wave.pos.length) {\n        const cap = wave.pos.length * 2;\n        const grownPos = new Uint32Array(cap);\n        const grownLi = new Uint32Array(cap);\n        const grownIi = new Uint32Array(cap);\n        grownPos.set(wave.pos);\n        grownLi.set(wave.li);\n        grownIi.set(wave.ii);\n        wave.pos = grownPos;\n        wave.li = grownLi;\n        wave.ii = grownIi;\n    }\n    const i = wave.length++;\n    wave.pos[i] = pos;\n    wave.li[i] = li;\n    wave.ii[i] = ii;\n}\n\n/**\n * Tree depth needed for the occupied grid dimensions.\n *\n * @param gridBounds - Grid bounds aligned to block boundaries.\n * @param voxelResolution - Size of each voxel in world units.\n * @returns Octree depth in 4x4x4 block levels.\n */\nfunction calculateTreeDepth(gridBounds: Bounds, voxelResolution: number): number {\n    const gridSize = new Vec3(\n        gridBounds.max.x - gridBounds.min.x,\n        gridBounds.max.y - gridBounds.min.y,\n        gridBounds.max.z - gridBounds.min.z\n    );\n    const blockSize = voxelResolution * 4;\n    const blocksPerAxis = Math.max(\n        Math.ceil(gridSize.x / blockSize),\n        Math.ceil(gridSize.y / blockSize),\n        Math.ceil(gridSize.z / blockSize)\n    );\n    return Math.max(1, Math.ceil(Math.log2(blocksPerAxis)));\n}\n\n/**\n * Dense-mip octree construction is better when the grid contains many solid\n * blocks that will collapse. The sorted solid-leaf stream would otherwise be\n * enormous even though those leaves mostly disappear from the final tree.\n *\n * @param totalBlocks - Total 4x4x4 blocks in the grid.\n * @param nSolid - Number of solid blocks.\n * @param nMixed - Number of mixed blocks.\n * @returns True when dense construction is likely to use less memory.\n */\nfunction shouldUseDenseMipBuild(totalBlocks: number, nSolid: number, nMixed: number): boolean {\n    return nSolid >= DENSE_SOLID_STREAM_THRESHOLD &&\n        nSolid > nMixed * 4 &&\n        nSolid > totalBlocks * 0.25;\n}\n\n/**\n * Build dense 2-bit type mips from a SparseVoxelGrid. Level 0 is the input\n * block grid; higher levels aggregate 2x2x2 children.\n *\n * @param grid - Source sparse voxel grid.\n * @param maxDepth - Maximum octree depth to build.\n * @returns Dense type levels from leaf blocks to root.\n */\nfunction buildDenseTypeLevels(grid: SparseVoxelGrid, maxDepth: number): DenseLevel[] {\n    const levels: DenseLevel[] = [{\n        types: grid.types,\n        nbx: grid.nbx,\n        nby: grid.nby,\n        nbz: grid.nbz,\n        nonEmptyCount: 0\n    }];\n\n    for (let li = 1; li <= maxDepth; li++) {\n        const prev = levels[li - 1];\n        const nbx = Math.max(1, Math.ceil(prev.nbx / 2));\n        const nby = Math.max(1, Math.ceil(prev.nby / 2));\n        const nbz = Math.max(1, Math.ceil(prev.nbz / 2));\n        const total = nbx * nby * nbz;\n        const types = new Uint32Array((total + BLOCKS_PER_WORD - 1) >>> 4);\n        const prevStride = prev.nbx * prev.nby;\n        const stride = nbx * nby;\n        let nonEmptyCount = 0;\n\n        for (let pz = 0; pz < nbz; pz++) {\n            const childZ0 = pz << 1;\n            for (let py = 0; py < nby; py++) {\n                const childY0 = py << 1;\n                for (let px = 0; px < nbx; px++) {\n                    const childX0 = px << 1;\n                    let childMask = 0;\n                    let allSolid = true;\n                    let childCount = 0;\n\n                    for (let oct = 0; oct < 8; oct++) {\n                        const cx = childX0 + (oct & 1);\n                        const cy = childY0 + ((oct >> 1) & 1);\n                        const cz = childZ0 + ((oct >> 2) & 1);\n                        if (cx >= prev.nbx || cy >= prev.nby || cz >= prev.nbz) continue;\n                        const childIdx = cx + cy * prev.nbx + cz * prevStride;\n                        const bt = readBlockType(prev.types, childIdx);\n                        if (bt === BLOCK_EMPTY) continue;\n                        childMask |= 1 << oct;\n                        childCount++;\n                        if (bt !== BLOCK_SOLID) {\n                            allSolid = false;\n                        }\n                    }\n\n                    if (childMask !== 0) {\n                        const parentIdx = px + py * nbx + pz * stride;\n                        writeBlockType(types, parentIdx, allSolid && childCount === 8 ? BLOCK_SOLID : BLOCK_MIXED);\n                        nonEmptyCount++;\n                    }\n                }\n            }\n        }\n\n        levels.push({ types, nbx, nby, nbz, nonEmptyCount });\n\n        if (nonEmptyCount === 0) break;\n        if (nonEmptyCount === 1 && readBlockType(types, 0) !== BLOCK_EMPTY) break;\n    }\n\n    return levels;\n}\n\n/**\n * Flatten dense type mips into Laine-Karras node and leaf data arrays.\n *\n * @param levels - Dense type levels from leaf blocks to root.\n * @param grid - Original grid, used for mixed leaf masks.\n * @param gridBounds - Grid bounds aligned to block boundaries.\n * @param sceneBounds - Original Gaussian scene bounds.\n * @param voxelResolution - Size of each voxel in world units.\n * @returns Sparse octree structure.\n */\nfunction flattenDenseLevels(\n    levels: Array<DenseLevel | null>,\n    grid: SparseVoxelGrid,\n    gridBounds: Bounds,\n    sceneBounds: Bounds,\n    voxelResolution: number\n): SparseOctree {\n    const treeDepth = Math.max(1, levels.length - 1);\n    const rootLi = levels.length - 1;\n    const rootLevel = levels[rootLi]!;\n    const rootType = readBlockType(rootLevel.types, 0);\n\n    if (rootType === BLOCK_EMPTY) {\n        return {\n            gridBounds,\n            sceneBounds,\n            voxelResolution,\n            leafSize: 4,\n            treeDepth,\n            numInteriorNodes: 0,\n            numMixedLeaves: 0,\n            nodes: new Uint32Array(0),\n            leafData: new Uint32Array(0)\n        };\n    }\n\n    let nodes = new Uint32Array(Math.max(1024, Math.min(MAX_24BIT_OFFSET + 1, grid.masks.size * 3)));\n    let nodeLen = 0;\n    let leafData = new Uint32Array(Math.max(1024, grid.masks.size * 2));\n    let leafDataLen = 0;\n    let numInteriorNodes = 0;\n    let numMixedLeaves = 0;\n\n    const appendNode = (value: number): number => {\n        if (nodeLen === nodes.length) {\n            const grown = new Uint32Array(nodes.length * 2);\n            grown.set(nodes);\n            nodes = grown;\n        }\n        nodes[nodeLen] = value >>> 0;\n        return nodeLen++;\n    };\n\n    const appendMixedLeaf = (blockIdx: number): void => {\n        const leafDataIndex = leafDataLen >> 1;\n        if (leafDataIndex > MAX_24BIT_OFFSET) {\n            throw new Error(\n                `Sparse octree mixed-leaf count (${leafDataIndex + 1}) exceeds the ` +\n                `Laine-Karras 24-bit baseOffset limit (${MAX_24BIT_OFFSET + 1}). ` +\n                'Reduce the grid size or split the scene.'\n            );\n        }\n        if (leafDataLen + 2 > leafData.length) {\n            const grown = new Uint32Array(leafData.length * 2);\n            grown.set(leafData);\n            leafData = grown;\n        }\n        const s = grid.masks.slot(blockIdx);\n        leafData[leafDataLen++] = grid.masks.lo[s];\n        leafData[leafDataLen++] = grid.masks.hi[s];\n        appendNode(leafDataIndex);\n        numMixedLeaves++;\n    };\n\n    let curWave = createInteriorWave(1);\n    let nextWave = createInteriorWave(1024);\n\n    const appendDenseNode = (li: number, idx: number, wave: InteriorWave): void => {\n        const level = levels[li]!;\n        const bt = readBlockType(level.types, idx);\n        if (bt === BLOCK_SOLID) {\n            appendNode(SOLID_LEAF_MARKER);\n        } else if (bt === BLOCK_MIXED) {\n            const pos = appendNode(0);\n            pushInteriorWave(wave, pos, li, idx);\n            numInteriorNodes++;\n        }\n    };\n\n    appendDenseNode(rootLi, 0, curWave);\n\n    while (curWave.length > 0) {\n        nextWave.length = 0;\n        const currentLi = curWave.li[0];\n\n        for (let w = 0; w < curWave.length; w++) {\n            const li = curWave.li[w];\n            const parentLevel = levels[li]!;\n            const childLevel = levels[li - 1]!;\n            const parentIdx = curWave.ii[w];\n            const px = parentIdx % parentLevel.nbx;\n            const pyBz = (parentIdx / parentLevel.nbx) | 0;\n            const py = pyBz % parentLevel.nby;\n            const pz = (pyBz / parentLevel.nby) | 0;\n            const childX0 = px << 1;\n            const childY0 = py << 1;\n            const childZ0 = pz << 1;\n            const childStride = childLevel.nbx * childLevel.nby;\n            const childStart = nodeLen;\n            let childMask = 0;\n\n            if (childStart > MAX_24BIT_OFFSET) {\n                throw new Error(\n                    `Sparse octree node count (${childStart + 1}) exceeds the ` +\n                    `Laine-Karras 24-bit baseOffset limit (${MAX_24BIT_OFFSET + 1}). ` +\n                    'Reduce the grid size or split the scene.'\n                );\n            }\n\n            for (let oct = 0; oct < 8; oct++) {\n                const cx = childX0 + (oct & 1);\n                const cy = childY0 + ((oct >> 1) & 1);\n                const cz = childZ0 + ((oct >> 2) & 1);\n                if (cx >= childLevel.nbx || cy >= childLevel.nby || cz >= childLevel.nbz) continue;\n                const childIdx = cx + cy * childLevel.nbx + cz * childStride;\n                const bt = readBlockType(childLevel.types, childIdx);\n                if (bt === BLOCK_EMPTY) continue;\n\n                childMask |= 1 << oct;\n                if (li === 1) {\n                    if (bt === BLOCK_SOLID) {\n                        appendNode(SOLID_LEAF_MARKER);\n                    } else {\n                        appendMixedLeaf(childIdx);\n                    }\n                } else {\n                    appendDenseNode(li - 1, childIdx, nextWave);\n                }\n            }\n\n            nodes[curWave.pos[w]] = ((childMask & 0xFF) << 24) | childStart;\n        }\n\n        levels[currentLi] = null;\n        const tmp = curWave;\n        curWave = nextWave;\n        nextWave = tmp;\n    }\n\n    return {\n        gridBounds,\n        sceneBounds,\n        voxelResolution,\n        leafSize: 4,\n        treeDepth,\n        numInteriorNodes,\n        numMixedLeaves,\n        nodes: nodes.slice(0, nodeLen),\n        leafData: leafData.slice(0, leafDataLen)\n    };\n}\n\n/**\n * Build a sparse octree from dense type mips. This avoids the sorted solid\n * Morton stream for grids dominated by solid blocks.\n *\n * @param grid - Source grid.\n * @param gridBounds - Grid bounds aligned to block boundaries.\n * @param sceneBounds - Original Gaussian scene bounds.\n * @param voxelResolution - Size of each voxel in world units.\n * @param maxDepth - Maximum tree depth.\n * @param consumeGrid - Release grid storage after flattening.\n * @returns Sparse octree structure.\n */\nfunction buildSparseOctreeDense(\n    grid: SparseVoxelGrid,\n    gridBounds: Bounds,\n    sceneBounds: Bounds,\n    voxelResolution: number,\n    maxDepth: number,\n    consumeGrid: boolean\n): SparseOctree {\n    const bar = logger.bar('Building tree', 10);\n    const levels = buildDenseTypeLevels(grid, maxDepth);\n    for (let i = 0; i < 8; i++) {\n        bar.tick();\n    }\n    const result = flattenDenseLevels(levels, grid, gridBounds, sceneBounds, voxelResolution);\n    bar.tick();\n    if (consumeGrid) {\n        grid.releaseStorage();\n    }\n    bar.tick();\n    bar.end();\n    return result;\n}\n\n// ============================================================================\n// Octree Construction\n// ============================================================================\n\n/**\n * Build a sparse octree from a SparseVoxelGrid.\n *\n * Walks the grid's `types` array word-by-word (skipping empty words), counts\n * solid + mixed blocks, then emits Morton-keyed (solidStream, mixedStream,\n * mixedMasks) typed arrays sized exactly. The streams are then sorted; this\n * is the only place Morton encoding is paid in the post-voxelization pipeline.\n *\n * @param grid - SparseVoxelGrid containing voxelized blocks.\n * @param gridBounds - Grid bounds aligned to block boundaries\n * @param sceneBounds - Original scene bounds\n * @param voxelResolution - Size of each voxel in world units\n * @param options - Build options.\n * @returns Sparse octree structure\n */\nfunction buildSparseOctree(\n    grid: SparseVoxelGrid,\n    gridBounds: Bounds,\n    sceneBounds: Bounds,\n    voxelResolution: number,\n    options: BuildSparseOctreeOptions = {}\n): SparseOctree {\n    // --- Phase 1: Walk grid → emit Morton streams + sort ---\n    // Level 0 (leaves) is represented as TWO sorted streams — solid mortons\n    // and mixed mortons (with paired masks). Two passes:\n    //   1. Pre-count solid and mixed blocks (word-skip empty words).\n    //   2. Allocate and fill streams (Morton encode per non-empty block).\n    // Then sort both streams.\n    //\n    // We avoid `comparefn` typed-array sort because V8 routes it through a\n    // regular-array path bounded by FixedArray::kMaxLength (~134M with\n    // pointer compression) and throws past it. Instead:\n    //   - Native `Float64Array.sort()` (no comparefn) on the solid stream,\n    //     avoiding V8's FixedArray comparefn path.\n    //   - Custom `sortMixedByMorton` for the mixed stream: iterative\n    //     quicksort tailored to the (Float64 morton, Uint32×2 mask) layout.\n\n    const { nbx, nby, nbz, types: gridTypes, masks: gridMasks } = grid;\n    const totalBlocks = nbx * nby * nbz;\n    const treeDepth = calculateTreeDepth(gridBounds, voxelResolution);\n    const lastWordIdx = gridTypes.length - 1;\n    const lastLanes = totalBlocks - lastWordIdx * BLOCKS_PER_WORD;\n    const lastValidWordMask = lastLanes >= BLOCKS_PER_WORD ?\n        0xFFFFFFFF >>> 0 :\n        ((1 << (lastLanes * 2)) - 1) >>> 0;\n\n    // Pass 1: count.\n    let nSolid = 0;\n    let nMixed = 0;\n    for (let w = 0; w < gridTypes.length; w++) {\n        let word = gridTypes[w];\n        if (w === lastWordIdx) word = (word & lastValidWordMask) >>> 0;\n        if (word === 0) continue;\n        // Solid lanes: 0b01 = 1; Mixed lanes: 0b10 = 2.\n        const solidMask = (word & EVEN_BITS) & ~((word >>> 1) & EVEN_BITS);\n        const mixedMask = ((word >>> 1) & EVEN_BITS) & ~(word & EVEN_BITS);\n        nSolid += popcount(solidMask >>> 0);\n        nMixed += popcount(mixedMask >>> 0);\n    }\n\n    if (options.dense || shouldUseDenseMipBuild(totalBlocks, nSolid, nMixed)) {\n        return buildSparseOctreeDense(\n            grid, gridBounds, sceneBounds, voxelResolution, treeDepth, !!options.consumeGrid\n        );\n    }\n\n    const solidStream = new Float64Array(nSolid);\n    const mixedStream = new Float64Array(nMixed);\n    const mixedMasks = new Uint32Array(nMixed * 2);\n\n    // Pass 2: fill.\n    let solidWriteIdx = 0;\n    let mixedWriteIdx = 0;\n    for (let w = 0; w < gridTypes.length; w++) {\n        let word = gridTypes[w];\n        if (w === lastWordIdx) word = (word & lastValidWordMask) >>> 0;\n        if (word === 0) continue;\n        let nonEmpty = ((word & EVEN_BITS) | ((word >>> 1) & EVEN_BITS)) >>> 0;\n        const baseIdx = w * BLOCKS_PER_WORD;\n        while (nonEmpty) {\n            const bp = 31 - Math.clz32(nonEmpty & -nonEmpty);\n            const lane = bp >>> 1;\n            nonEmpty &= nonEmpty - 1;\n            const blockIdx = baseIdx + lane;\n            if (blockIdx >= totalBlocks) break;\n            const bx = blockIdx % nbx;\n            const byBz = (blockIdx / nbx) | 0;\n            const by = byBz % nby;\n            const bz = (byBz / nby) | 0;\n            const morton = xyzToMorton(bx, by, bz);\n            const bt = (word >>> (lane << 1)) & TYPE_MASK;\n            if (bt === BLOCK_SOLID) {\n                solidStream[solidWriteIdx++] = morton;\n            } else if (bt === BLOCK_MIXED) {\n                mixedStream[mixedWriteIdx] = morton;\n                const s = gridMasks.slot(blockIdx);\n                mixedMasks[mixedWriteIdx * 2] = gridMasks.lo[s];\n                mixedMasks[mixedWriteIdx * 2 + 1] = gridMasks.hi[s];\n                mixedWriteIdx++;\n            }\n        }\n    }\n\n    if (options.consumeGrid) {\n        grid.releaseStorage();\n    }\n\n    if (nSolid > 1) solidStream.sort();\n    if (nMixed > 1) sortMixedByMorton(mixedStream, mixedMasks, nMixed);\n\n    // --- Phase 2: Build tree bottom-up level by level using linear scan ---\n    // Level 0 lives in `solidStream` + `mixedStream` (dual streams, sorted).\n    // We build level 1 by a two-pointer merge of these streams; subsequent\n    // levels (2, 3, ...) are built from JS-array level data via the same\n    // single-array linear scan as before.\n    //\n    // `interiorLevels[]` holds INTERIOR levels only (no level 0).\n    // `interiorLevels[0]` is the first interior level (= original \"level 1\");\n    // `interiorLevels[length-1]` is the root. Phase 3 special-cases level 0\n    // access via a wave-entry sentinel (`li === -1`).\n\n    const bar = logger.bar('Building tree', 10);\n    let octreeStep = 0;\n\n    const interiorLevels: LevelData[] = [];\n\n    // === Build level 1 from dual-stream level 0 ===\n    // Two-pointer merge: at each step, the smaller-morton stream is the next\n    // child to process. Group children with the same `floor(morton/8)` parent.\n    // childMask records which octants are present; allSolid tracks whether we\n    // can collapse this parent into a SOLID leaf at level 1.\n    let curMortons: number[] = [];\n    let curTypes: number[] = [];\n    let curChildMasks: number[] = [];\n\n    {\n        let sI = 0;\n        let mI = 0;\n        while (sI < nSolid || mI < nMixed) {\n            const sM0 = sI < nSolid ? solidStream[sI] : Number.POSITIVE_INFINITY;\n            const mM0 = mI < nMixed ? mixedStream[mI] : Number.POSITIVE_INFINITY;\n            const minMorton = sM0 < mM0 ? sM0 : mM0;\n            const parentMorton = Math.floor(minMorton / 8);\n            let childMask = 0;\n            let allSolid = true;\n            let childCount = 0;\n\n            while (true) {\n                const sM = sI < nSolid ? solidStream[sI] : Number.POSITIVE_INFINITY;\n                const mM = mI < nMixed ? mixedStream[mI] : Number.POSITIVE_INFINITY;\n                const cur = sM < mM ? sM : mM;\n                if (!isFinite(cur) || Math.floor(cur / 8) !== parentMorton) break;\n                childMask |= 1 << (cur % 8);\n                childCount++;\n                if (sM < mM) {\n                    sI++;\n                } else {\n                    allSolid = false;\n                    mI++;\n                }\n            }\n\n            curMortons.push(parentMorton);\n            if (allSolid && childCount === 8) {\n                curTypes.push(BlockType.Solid);\n                curChildMasks.push(0);\n            } else {\n                curTypes.push(BlockType.Mixed);\n                curChildMasks.push(childMask);\n            }\n        }\n    }\n\n    // 1 step for init / level-1 build\n    bar.tick();\n    octreeStep++;\n\n    let actualDepth = treeDepth;\n    const levelSteps = 8;\n\n    // === Build levels 2..treeDepth from level 1 upward ===\n    // Same logic as before — single-array linear scan. We push each level\n    // before building the next, then push the final root after the loop.\n    if (curMortons.length === 0) {\n        // Empty input: nothing to push. interiorLevels stays empty.\n        actualDepth = 1;\n    } else if (curMortons.length === 1 && curMortons[0] === 0) {\n        // Level 1 IS the root.\n        actualDepth = 1;\n        interiorLevels.push({\n            mortons: curMortons,\n            types: curTypes,\n            childMasks: curChildMasks\n        });\n    } else {\n        for (let level = 1; level < treeDepth; level++) {\n            const targetStep = 1 + Math.min(levelSteps, Math.floor((level + 1) / treeDepth * levelSteps));\n            while (octreeStep < targetStep) {\n                bar.tick();\n                octreeStep++;\n            }\n\n            // Push current level before building one above it\n            interiorLevels.push({\n                mortons: curMortons,\n                types: curTypes,\n                childMasks: curChildMasks\n            });\n\n            // Build next level using linear scan on sorted data.\n            const n = curMortons.length;\n            const nextMortons: number[] = [];\n            const nextTypes: number[] = [];\n            const nextChildMasks: number[] = [];\n\n            let i = 0;\n            while (i < n) {\n                const parentMorton = Math.floor(curMortons[i] / 8);\n                let childMask = 0;\n                let allSolid = true;\n                let childCount = 0;\n\n                while (i < n && Math.floor(curMortons[i] / 8) === parentMorton) {\n                    const octant = curMortons[i] % 8;\n                    childMask |= (1 << octant);\n                    if (curTypes[i] !== BlockType.Solid) {\n                        allSolid = false;\n                    }\n                    childCount++;\n                    i++;\n                }\n\n                nextMortons.push(parentMorton);\n                if (allSolid && childCount === 8) {\n                    nextTypes.push(BlockType.Solid);\n                    nextChildMasks.push(0);\n                } else {\n                    nextTypes.push(BlockType.Mixed);\n                    nextChildMasks.push(childMask);\n                }\n            }\n\n            curMortons = nextMortons;\n            curTypes = nextTypes;\n            curChildMasks = nextChildMasks;\n\n            // Each iteration consumes n >= 1 entries and produces ceil(n/8) >= 1\n            // parents, so curMortons.length stays >= 1 here; we only need to\n            // check for convergence to a single root at morton 0.\n            if (curMortons.length === 1 && curMortons[0] === 0) {\n                actualDepth = level + 1;\n                break;\n            }\n        }\n\n        // Save root. By the invariant above, curMortons.length >= 1 always.\n        interiorLevels.push({\n            mortons: curMortons,\n            types: curTypes,\n            childMasks: curChildMasks\n        });\n    }\n\n    while (octreeStep < 9) {\n        bar.tick();\n        octreeStep++;\n    }\n\n    // --- Phase 3: Flatten tree to Laine-Karras format ---\n    const result = flattenTreeFromLevels(\n        interiorLevels, solidStream, mixedStream, mixedMasks, nSolid, nMixed,\n        gridBounds, sceneBounds, voxelResolution, actualDepth\n    );\n\n    bar.tick();\n    bar.end();\n\n    return result;\n}\n\n/**\n * Flatten the level-based tree into Laine-Karras format arrays using\n * wave-based BFS traversal from root down through levels.\n *\n * Level 0 (leaves) is represented as TWO sorted streams: `solidStream` (one\n * Float64 morton per solid leaf, no per-leaf data) and `mixedStream` (one\n * Float64 morton per mixed leaf, paired with `mixedMasks` at the same\n * index). Wave entries with `li === -1` refer to leaves: `ii < nMixed`\n * indicates a mixed leaf at `mixedStream[ii]`, while `ii >= nMixed`\n * indicates a solid leaf at `solidStream[ii - nMixed]`.\n *\n * `interiorLevels[i]` (for `i >= 0`) holds the i-th INTERIOR level (= original\n * \"level i+1\"), built bottom-up. `interiorLevels[length-1]` is the root.\n *\n * @param interiorLevels - Interior level data (index 0 = first interior level\n * above leaves, last = root).\n * @param solidStream - Sorted Float64 mortons for solid leaves.\n * @param mixedStream - Sorted Float64 mortons for mixed leaves (paired with\n * `mixedMasks` at the same index).\n * @param mixedMasks - Interleaved voxel masks for mixed leaves.\n * @param nSolid - Count of valid entries in `solidStream`.\n * @param nMixed - Count of valid entries in `mixedStream` (and pairs in\n * `mixedMasks`).\n * @param gridBounds - Grid bounds aligned to block boundaries.\n * @param sceneBounds - Original Gaussian scene bounds.\n * @param voxelResolution - Size of each voxel in world units.\n * @param treeDepth - Maximum tree depth.\n * @returns Sparse octree structure in Laine-Karras format.\n */\nfunction flattenTreeFromLevels(\n    interiorLevels: LevelData[],\n    solidStream: Float64Array,\n    mixedStream: Float64Array,\n    mixedMasks: Uint32Array,\n    nSolid: number,\n    nMixed: number,\n    gridBounds: Bounds,\n    sceneBounds: Bounds,\n    voxelResolution: number,\n    treeDepth: number\n): SparseOctree {\n    if (interiorLevels.length === 0) {\n        // Empty tree (no leaves and no interior levels).\n        return {\n            gridBounds,\n            sceneBounds,\n            voxelResolution,\n            leafSize: 4,\n            treeDepth,\n            numInteriorNodes: 0,\n            numMixedLeaves: 0,\n            nodes: new Uint32Array(0),\n            leafData: new Uint32Array(0)\n        };\n    }\n\n    const rootLevel = interiorLevels[interiorLevels.length - 1];\n\n    // Upper bound on total nodes (not all may be reachable if solids collapsed)\n    let maxNodes = nSolid + nMixed;\n    for (let l = 0; l < interiorLevels.length; l++) {\n        maxNodes += interiorLevels[l].mortons.length;\n    }\n\n    const nodes = new Uint32Array(maxNodes);\n    // Pre-size leafData to its upper bound (2 entries per mixed leaf).\n    const leafData = new Uint32Array(nMixed * 2);\n    let leafDataLen = 0;\n    let numInteriorNodes = 0;\n    let numMixedLeaves = 0;\n    let emitPos = 0;\n\n    // BFS wave as parallel arrays (avoids object allocation per queue entry)\n    let waveLi: number[] = [];\n    let waveIi: number[] = [];\n\n    // Initialize wave with root level entries.\n    const rootLi = interiorLevels.length - 1;\n    for (let i = 0; i < rootLevel.mortons.length; i++) {\n        waveLi.push(rootLi);\n        waveIi.push(i);\n    }\n\n    // Reusable arrays for tracking interior nodes within each wave\n    const intPos: number[] = [];\n    const intLi: number[] = [];\n    const intIi: number[] = [];\n    const intMask: number[] = [];\n\n    while (waveLi.length > 0) {\n        intPos.length = 0;\n        intLi.length = 0;\n        intIi.length = 0;\n        intMask.length = 0;\n\n        // --- Emit all nodes in this wave ---\n        for (let w = 0; w < waveLi.length; w++) {\n            const li = waveLi[w];\n            const ii = waveIi[w];\n\n            if (li === -1) {\n                // Level-0 leaf via dual-stream encoding.\n                if (ii < nMixed) {\n                    // Mixed leaf\n                    const leafDataIndex = leafDataLen >> 1;\n                    if (leafDataIndex > MAX_24BIT_OFFSET) {\n                        throw new Error(\n                            `Sparse octree mixed-leaf count (${leafDataIndex + 1}) exceeds the ` +\n                            `Laine-Karras 24-bit baseOffset limit (${MAX_24BIT_OFFSET + 1}). ` +\n                            'Reduce the grid size or split the scene.'\n                        );\n                    }\n                    leafData[leafDataLen++] = mixedMasks[ii * 2];\n                    leafData[leafDataLen++] = mixedMasks[ii * 2 + 1];\n                    nodes[emitPos] = leafDataIndex;\n                    numMixedLeaves++;\n                } else {\n                    // Solid leaf\n                    nodes[emitPos] = SOLID_LEAF_MARKER;\n                }\n                emitPos++;\n                continue;\n            }\n\n            const level = interiorLevels[li];\n            const type = level.types[ii];\n\n            // Level-0 leaves are emitted via the `li === -1` sentinel above;\n            // any solid interior-level node here is a collapsed solid leaf.\n            const isLeaf = type === BlockType.Solid;\n\n            if (isLeaf) {\n                nodes[emitPos] = SOLID_LEAF_MARKER;\n            } else {\n                // Interior node — record position for backfill after wave\n                intPos.push(emitPos);\n                intLi.push(li);\n                intIi.push(ii);\n                intMask.push(level.childMasks[ii]);\n                numInteriorNodes++;\n                nodes[emitPos] = 0;\n            }\n            emitPos++;\n        }\n\n        // --- Build next wave from children of interior nodes ---\n        const nextWaveLi: number[] = [];\n        const nextWaveIi: number[] = [];\n        let nextChildStart = emitPos;\n\n        for (let j = 0; j < intPos.length; j++) {\n            const childMask = intMask[j];\n            const childCount = popcount(childMask);\n\n            if (nextChildStart > MAX_24BIT_OFFSET) {\n                throw new Error(\n                    `Sparse octree node count (${nextChildStart + 1}) exceeds the ` +\n                    `Laine-Karras 24-bit baseOffset limit (${MAX_24BIT_OFFSET + 1}). ` +\n                    'Reduce the grid size or split the scene.'\n                );\n            }\n            nodes[intPos[j]] = ((childMask & 0xFF) << 24) | nextChildStart;\n\n            const myLi = intLi[j];\n            const myMorton = interiorLevels[myLi].mortons[intIi[j]];\n            const childMortonBase = myMorton * 8;\n            const childMortonEnd = childMortonBase + 8;\n\n            if (myLi === 0) {\n                // Children are at level 0 → dual-stream binary search.\n                // Walk both streams from their respective lower bounds in\n                // morton order, emitting wave entries with `li === -1` and\n                // `ii` encoded as: ii < nMixed for mixed leaves, ii >= nMixed\n                // (= nMixed + solidIdx) for solid leaves.\n                let sIdx = lowerBoundF64(solidStream, childMortonBase, nSolid);\n                let mIdx = lowerBoundF64(mixedStream, childMortonBase, nMixed);\n                while (true) {\n                    const sM = sIdx < nSolid && solidStream[sIdx] < childMortonEnd ?\n                        solidStream[sIdx] : Number.POSITIVE_INFINITY;\n                    const mM = mIdx < nMixed && mixedStream[mIdx] < childMortonEnd ?\n                        mixedStream[mIdx] : Number.POSITIVE_INFINITY;\n                    if (!isFinite(sM) && !isFinite(mM)) break;\n                    if (sM < mM) {\n                        nextWaveLi.push(-1);\n                        nextWaveIi.push(nMixed + sIdx);\n                        sIdx++;\n                    } else {\n                        nextWaveLi.push(-1);\n                        nextWaveIi.push(mIdx);\n                        mIdx++;\n                    }\n                }\n            } else {\n                // Children are at an interior level → single-array binary search.\n                const childLi = myLi - 1;\n                const childLevel = interiorLevels[childLi];\n                const childMortons = childLevel.mortons;\n\n                let lo = 0;\n                let hi = childMortons.length;\n                while (lo < hi) {\n                    const mid = (lo + hi) >> 1;\n                    if (childMortons[mid] < childMortonBase) lo = mid + 1;\n                    else hi = mid;\n                }\n\n                while (lo < childMortons.length && childMortons[lo] < childMortonEnd) {\n                    nextWaveLi.push(childLi);\n                    nextWaveIi.push(lo);\n                    lo++;\n                }\n            }\n\n            nextChildStart += childCount;\n        }\n\n        waveLi = nextWaveLi;\n        waveIi = nextWaveIi;\n    }\n\n    return {\n        gridBounds,\n        sceneBounds,\n        voxelResolution,\n        leafSize: 4,\n        treeDepth,\n        numInteriorNodes,\n        numMixedLeaves,\n        nodes: emitPos === maxNodes ? nodes : nodes.slice(0, emitPos),\n        leafData: leafDataLen === leafData.length ? leafData : leafData.slice(0, leafDataLen)\n    };\n}\n\nexport {\n    buildSparseOctree,\n    SOLID_LEAF_MARKER\n};\n\nexport type { SparseOctree };\n","import { BlockMaskBuffer } from './block-mask-buffer';\nimport { popcount } from './morton';\nimport { logger } from '../utils';\n\n// ============================================================================\n// Edge mask constants for 4x4x4 voxel blocks\n// ============================================================================\n// Bit layout: bitIdx = lx + ly*4 + lz*16\n// lo = bits 0-31 (lz=0: 0-15, lz=1: 16-31)\n// hi = bits 32-63 (lz=2: 0-15, lz=3: 16-31)\n\n/** lx=0 positions in each 32-bit word */\nconst FACE_X0 = 0x11111111;\n/** lx=3 positions in each 32-bit word */\nconst FACE_X3 = 0x88888888;\n/** ly=0 positions in each 32-bit word */\nconst FACE_Y0 = 0x000F000F;\n/** ly=3 positions in each 32-bit word */\nconst FACE_Y3 = 0xF000F000;\n/** lz=0 positions: lo bits 0-15 */\nconst FACE_Z0_LO = 0x0000FFFF;\n/** lz=3 positions: hi bits 16-31 */\nconst FACE_Z3_HI = 0xFFFF0000 >>> 0;\n\nconst SOLID_MASK = 0xFFFFFFFF >>> 0;\n\n// ============================================================================\n// Main function\n// ============================================================================\n\n/**\n * Remove isolated voxels and fill isolated empty voxels within mixed blocks.\n *\n * For each mixed block, computes 6 per-direction occupancy masks (in-block via\n * bit shifts + cross-block via adjacent block lookups), then:\n *   - Remove: keeps only voxels with at least one occupied 6-connected neighbor\n *   - Fill: fills empty voxels where all 6 neighbors are occupied\n *\n * Blocks that become empty or solid as a consequence are handled automatically.\n *\n * @param buffer - BlockMaskBuffer with voxelization results (linear-keyed).\n * @param nbx - Grid block dimension X (used to decode block indices).\n * @param nby - Grid block dimension Y (used to decode block indices).\n * @param nbz - Grid block dimension Z (used for neighbor bounds checks).\n * @returns New BlockMaskBuffer with filtered/filled data.\n */\nfunction filterAndFillBlocks(\n    buffer: BlockMaskBuffer,\n    nbx: number,\n    nby: number,\n    nbz: number\n): BlockMaskBuffer {\n    const mixed = buffer.getMixedBlocks();\n    const solid = buffer.getSolidBlocks();\n    const masks = mixed.masks;\n    const bStride = nbx * nby;\n\n    // Build lookup structures from original (unmodified) data\n    const solidSet = new Set<number>();\n    for (let i = 0; i < solid.length; i++) {\n        solidSet.add(solid[i]);\n    }\n\n    const mixedMap = new Map<number, number>();\n    for (let i = 0; i < mixed.blockIdx.length; i++) {\n        mixedMap.set(mixed.blockIdx[i], i);\n    }\n\n    // New masks array (snapshot: cross-block lookups always read the original masks)\n    const newMasks = new Uint32Array(masks.length);\n    let voxelsRemoved = 0;\n    let voxelsFilled = 0;\n\n    for (let i = 0; i < mixed.blockIdx.length; i++) {\n        const idx = mixed.blockIdx[i];\n        const origLo = masks[i * 2];\n        const origHi = masks[i * 2 + 1];\n\n        const bx = idx % nbx;\n        const byBz = (idx / nbx) | 0;\n        const by = byBz % nby;\n        const bz = (byBz / nby) | 0;\n\n        // --- In-block per-direction occupancy masks ---\n\n        // +X: result[p] = mask[p+1], valid for lx < 3\n        let pxLo = (origLo >>> 1) & ~FACE_X3;\n        let pxHi = (origHi >>> 1) & ~FACE_X3;\n\n        // -X: result[p] = mask[p-1], valid for lx > 0\n        let mxLo = (origLo << 1) & ~FACE_X0;\n        let mxHi = (origHi << 1) & ~FACE_X0;\n\n        // +Y: result[p] = mask[p+4], valid for ly < 3\n        let pyLo = (origLo >>> 4) & ~FACE_Y3;\n        let pyHi = (origHi >>> 4) & ~FACE_Y3;\n\n        // -Y: result[p] = mask[p-4], valid for ly > 0\n        let myLo = (origLo << 4) & ~FACE_Y0;\n        let myHi = (origHi << 4) & ~FACE_Y0;\n\n        // +Z: result[p] = mask[p+16], crosses lo/hi at lz=1->lz=2\n        let pzLo = (origLo >>> 16) | (origHi << 16);\n        let pzHi = origHi >>> 16;\n\n        // -Z: result[p] = mask[p-16], crosses lo/hi at lz=2->lz=1\n        let mzLo = origLo << 16;\n        let mzHi = (origHi << 16) | (origLo >>> 16);\n\n        // --- Cross-block contributions ---\n\n        // +X: our lx=3 face <- adjacent's lx=0 face (shifted left by 3)\n        addCrossFace(bx + 1, by, bz, nbx, nby, nbz, bStride, solidSet, mixedMap, masks,\n            FACE_X3, FACE_X0, 3, true, pxLo, pxHi,\n            (lo, hi) => {\n                pxLo = lo; pxHi = hi;\n            });\n\n        // -X: our lx=0 face <- adjacent's lx=3 face (shifted right by 3)\n        addCrossFace(bx - 1, by, bz, nbx, nby, nbz, bStride, solidSet, mixedMap, masks,\n            FACE_X0, FACE_X3, 3, false, mxLo, mxHi,\n            (lo, hi) => {\n                mxLo = lo; mxHi = hi;\n            });\n\n        // +Y: our ly=3 face <- adjacent's ly=0 face (shifted left by 12)\n        addCrossFace(bx, by + 1, bz, nbx, nby, nbz, bStride, solidSet, mixedMap, masks,\n            FACE_Y3, FACE_Y0, 12, true, pyLo, pyHi,\n            (lo, hi) => {\n                pyLo = lo; pyHi = hi;\n            });\n\n        // -Y: our ly=0 face <- adjacent's ly=3 face (shifted right by 12)\n        addCrossFace(bx, by - 1, bz, nbx, nby, nbz, bStride, solidSet, mixedMap, masks,\n            FACE_Y0, FACE_Y3, 12, false, myLo, myHi,\n            (lo, hi) => {\n                myLo = lo; myHi = hi;\n            });\n\n        // +Z: our lz=3 face (hi bits 16-31) <- adjacent's lz=0 face (lo bits 0-15)\n        addCrossFaceZ(bx, by, bz + 1, nbx, nby, nbz, bStride, solidSet, mixedMap, masks, true, pzLo, pzHi,\n            (lo, hi) => {\n                pzLo = lo; pzHi = hi;\n            });\n\n        // -Z: our lz=0 face (lo bits 0-15) <- adjacent's lz=3 face (hi bits 16-31)\n        addCrossFaceZ(bx, by, bz - 1, nbx, nby, nbz, bStride, solidSet, mixedMap, masks, false, mzLo, mzHi,\n            (lo, hi) => {\n                mzLo = lo; mzHi = hi;\n            });\n\n        // --- Apply operations ---\n\n        // Remove isolated voxels: keep only those with at least one occupied neighbor\n        const neighborLo = pxLo | mxLo | pyLo | myLo | pzLo | mzLo;\n        const neighborHi = pxHi | mxHi | pyHi | myHi | pzHi | mzHi;\n        let lo = origLo & neighborLo;\n        let hi = origHi & neighborHi;\n\n        // Fill isolated empties: fill where all 6 neighbors are occupied\n        const fillLo = ~lo & pxLo & mxLo & pyLo & myLo & pzLo & mzLo;\n        const fillHi = ~hi & pxHi & mxHi & pyHi & myHi & pzHi & mzHi;\n        lo |= fillLo;\n        hi |= fillHi;\n\n        voxelsRemoved += popcount(origLo & ~lo) + popcount(origHi & ~hi);\n        voxelsFilled += popcount(lo & ~origLo) + popcount(hi & ~origHi);\n\n        newMasks[i * 2] = lo;\n        newMasks[i * 2 + 1] = hi;\n    }\n\n    // Rebuild buffer with state transitions (mixed->empty, mixed->solid)\n    const result = new BlockMaskBuffer();\n\n    for (let i = 0; i < mixed.blockIdx.length; i++) {\n        const lo = newMasks[i * 2];\n        const hi = newMasks[i * 2 + 1];\n        result.addBlock(mixed.blockIdx[i], lo, hi);\n    }\n\n    for (let i = 0; i < solid.length; i++) {\n        result.addBlock(solid[i], SOLID_MASK, SOLID_MASK);\n    }\n\n    logger.debug(`block cleanup: ${voxelsRemoved} voxels removed, ${voxelsFilled} voxels filled`);\n\n    return result;\n}\n\n// ============================================================================\n// Cross-block face helpers\n// ============================================================================\n\nfunction addCrossFace(\n    nx: number, ny: number, nz: number,\n    nbx: number, nby: number, nbz: number, bStride: number,\n    solidSet: Set<number>,\n    mixedMap: Map<number, number>,\n    masks: Uint32Array,\n    ourFaceMask: number,\n    adjFaceMask: number,\n    shiftAmount: number,\n    shiftLeft: boolean,\n    curLo: number, curHi: number,\n    write: (lo: number, hi: number) => void\n): void {\n    if (nx < 0 || ny < 0 || nz < 0 || nx >= nbx || ny >= nby || nz >= nbz) {\n        write(curLo, curHi);\n        return;\n    }\n    const adjIdx = nx + ny * nbx + nz * bStride;\n\n    if (solidSet.has(adjIdx)) {\n        write(curLo | ourFaceMask, curHi | ourFaceMask);\n        return;\n    }\n\n    const mIdx = mixedMap.get(adjIdx);\n    if (mIdx === undefined) {\n        write(curLo, curHi);\n        return;\n    }\n\n    const adjLo = masks[mIdx * 2];\n    const adjHi = masks[mIdx * 2 + 1];\n    const faceLo = adjLo & adjFaceMask;\n    const faceHi = adjHi & adjFaceMask;\n\n    if (shiftLeft) {\n        write(curLo | (faceLo << shiftAmount), curHi | (faceHi << shiftAmount));\n    } else {\n        write(curLo | (faceLo >>> shiftAmount), curHi | (faceHi >>> shiftAmount));\n    }\n}\n\nfunction addCrossFaceZ(\n    nx: number, ny: number, nz: number,\n    nbx: number, nby: number, nbz: number, bStride: number,\n    solidSet: Set<number>,\n    mixedMap: Map<number, number>,\n    masks: Uint32Array,\n    plusZ: boolean,\n    curLo: number, curHi: number,\n    write: (lo: number, hi: number) => void\n): void {\n    if (nx < 0 || ny < 0 || nz < 0 || nx >= nbx || ny >= nby || nz >= nbz) {\n        write(curLo, curHi);\n        return;\n    }\n    const adjIdx = nx + ny * nbx + nz * bStride;\n\n    if (solidSet.has(adjIdx)) {\n        if (plusZ) {\n            write(curLo, curHi | FACE_Z3_HI);\n        } else {\n            write(curLo | FACE_Z0_LO, curHi);\n        }\n        return;\n    }\n\n    const mIdx = mixedMap.get(adjIdx);\n    if (mIdx === undefined) {\n        write(curLo, curHi);\n        return;\n    }\n\n    const adjLo = masks[mIdx * 2];\n    const adjHi = masks[mIdx * 2 + 1];\n\n    if (plusZ) {\n        write(curLo, curHi | ((adjLo & FACE_Z0_LO) << 16));\n    } else {\n        write(curLo | ((adjHi & FACE_Z3_HI) >>> 16), curHi);\n    }\n}\n\nexport { filterAndFillBlocks };\n","import { Vec3 } from 'playcanvas';\n\nimport { BlockMaskBuffer } from './block-mask-buffer';\nimport type { Bounds } from '../data-table';\nimport {\n    GpuVoxelization,\n    type BatchSpec,\n    type MultiBatchResult\n} from '../gpu';\nimport { type GaussianBVH } from '../spatial';\nimport { logger } from '../utils';\n\ninterface PendingBatch extends BatchSpec {\n    bx: number;\n    by: number;\n    bz: number;\n    numBlocksX: number;\n    numBlocksY: number;\n    numBlocksZ: number;\n}\n\n/**\n * GPU-accelerated voxelization of Gaussian splat data into a block mask buffer.\n *\n * Uses double-buffered pipelining: the CPU prepares the next mega-dispatch\n * (BVH queries + index copying) while the GPU executes the current one.\n *\n * @param bvh - Gaussian bounding volume hierarchy for spatial queries.\n * @param gpuVoxelization - GPU voxelization pipeline with Gaussians already uploaded.\n * @param gridBounds - Block-aligned grid bounds to voxelize within.\n * @param voxelResolution - Size of each voxel in world units.\n * @param opacityCutoff - Opacity threshold for solid voxels.\n * @returns Block mask buffer containing voxelization results.\n */\nconst voxelizeToBuffer = async (\n    bvh: GaussianBVH,\n    gpuVoxelization: GpuVoxelization,\n    gridBounds: Bounds,\n    voxelResolution: number,\n    opacityCutoff: number\n): Promise<BlockMaskBuffer> => {\n    const blockSize = 4 * voxelResolution;\n    const numBlocksX = Math.round((gridBounds.max.x - gridBounds.min.x) / blockSize);\n    const numBlocksY = Math.round((gridBounds.max.y - gridBounds.min.y) / blockSize);\n    const numBlocksZ = Math.round((gridBounds.max.z - gridBounds.min.z) / blockSize);\n\n    const buffer = new BlockMaskBuffer();\n    const bStride = numBlocksX * numBlocksY;\n    const batchSize = 16;\n\n    // Caps for one mega-flush. Sized to keep a single compute dispatch's\n    // wall-clock comfortably under Windows D3D12 TDR (~2s watchdog) on slower\n    // GPUs without materially affecting throughput on fast GPUs (the\n    // double-buffered slots keep the GPU fed across the extra flushes).\n    // Output is bit-identical regardless: each batch's full Gaussian list rides\n    // with it, and slot buffers grow on demand to accommodate any oversize batch.\n    const MEGA_MAX_BATCHES = 256;\n    const MEGA_MAX_INDICES = 2 * 1024 * 1024;\n\n    const maxBlocks = GpuVoxelization.MAX_BLOCKS_PER_BATCH;\n    const numSlots = GpuVoxelization.NUM_SLOTS;\n\n    const slotIndexArrays: Uint32Array[] = [];\n    const slotCapacities: number[] = [];\n    for (let i = 0; i < numSlots; i++) {\n        slotCapacities.push(1024 * 1024);\n        slotIndexArrays.push(new Uint32Array(1024 * 1024));\n    }\n\n    let currentSlot = 0;\n    let indexOffset = 0;\n    const pendingBatches: PendingBatch[] = [];\n\n    let inflight: {\n        resultPromise: Promise<MultiBatchResult>;\n        batches: PendingBatch[];\n    } | null = null;\n\n    const ensureSlotIndexCapacity = (slotIdx: number, needed: number, preserveCount: number): void => {\n        if (needed <= slotCapacities[slotIdx]) return;\n        slotCapacities[slotIdx] = Math.max(slotCapacities[slotIdx] * 2, needed);\n        const newArray = new Uint32Array(slotCapacities[slotIdx]);\n        newArray.set(slotIndexArrays[slotIdx].subarray(0, preserveCount));\n        slotIndexArrays[slotIdx] = newArray;\n    };\n\n    const processResults = (masks: Uint32Array, batches: PendingBatch[]): void => {\n        for (let b = 0; b < batches.length; b++) {\n            const batch = batches[b];\n            const batchResultOffset = b * maxBlocks * 2;\n            const totalBatchBlocks = batch.numBlocksX * batch.numBlocksY * batch.numBlocksZ;\n\n            for (let blockIdx = 0; blockIdx < totalBatchBlocks; blockIdx++) {\n                const maskLo = masks[batchResultOffset + blockIdx * 2];\n                const maskHi = masks[batchResultOffset + blockIdx * 2 + 1];\n\n                if (maskLo === 0 && maskHi === 0) continue;\n\n                const localX = blockIdx % batch.numBlocksX;\n                const localY = (blockIdx / batch.numBlocksX | 0) % batch.numBlocksY;\n                const localZ = (blockIdx / (batch.numBlocksX * batch.numBlocksY)) | 0;\n\n                const absBlockX = batch.bx + localX;\n                const absBlockY = batch.by + localY;\n                const absBlockZ = batch.bz + localZ;\n\n                const idx = absBlockX + absBlockY * numBlocksX + absBlockZ * bStride;\n                buffer.addBlock(idx, maskLo, maskHi);\n            }\n        }\n    };\n\n    const flushPendingBatches = async (): Promise<void> => {\n        if (pendingBatches.length === 0) return;\n\n        const batchesToSubmit = pendingBatches.slice();\n        const submitSlot = currentSlot;\n        const submitIndexArray = slotIndexArrays[submitSlot];\n        const submitIndexCount = indexOffset;\n\n        currentSlot = (currentSlot + 1) % numSlots;\n        pendingBatches.length = 0;\n        indexOffset = 0;\n\n        const resultPromise = gpuVoxelization.submitMultiBatch(\n            submitSlot,\n            submitIndexArray,\n            submitIndexCount,\n            batchesToSubmit,\n            voxelResolution,\n            opacityCutoff\n        );\n\n        if (inflight) {\n            const result = await inflight.resultPromise;\n            processResults(result.masks, inflight.batches);\n        }\n\n        inflight = { resultPromise, batches: batchesToSubmit };\n    };\n\n    const numZBatches = Math.max(1, Math.ceil(numBlocksZ / batchSize));\n    const bar = logger.bar('Voxelizing', numZBatches);\n    for (let bz = 0; bz < numBlocksZ; bz += batchSize) {\n        for (let by = 0; by < numBlocksY; by += batchSize) {\n            for (let bx = 0; bx < numBlocksX; bx += batchSize) {\n                const currBatchX = Math.min(batchSize, numBlocksX - bx);\n                const currBatchY = Math.min(batchSize, numBlocksY - by);\n                const currBatchZ = Math.min(batchSize, numBlocksZ - bz);\n\n                const blockMinX = gridBounds.min.x + bx * blockSize;\n                const blockMinY = gridBounds.min.y + by * blockSize;\n                const blockMinZ = gridBounds.min.z + bz * blockSize;\n                const blockMaxX = blockMinX + currBatchX * blockSize;\n                const blockMaxY = blockMinY + currBatchY * blockSize;\n                const blockMaxZ = blockMinZ + currBatchZ * blockSize;\n\n                let overlappingCount = bvh.queryOverlappingRawInto(\n                    blockMinX, blockMinY, blockMinZ,\n                    blockMaxX, blockMaxY, blockMaxZ,\n                    slotIndexArrays[currentSlot],\n                    indexOffset\n                );\n\n                if (overlappingCount === 0) {\n                    continue;\n                }\n\n                const needed = indexOffset + overlappingCount;\n                if (needed > slotCapacities[currentSlot]) {\n                    ensureSlotIndexCapacity(currentSlot, needed, indexOffset);\n                    overlappingCount = bvh.queryOverlappingRawInto(\n                        blockMinX, blockMinY, blockMinZ,\n                        blockMaxX, blockMaxY, blockMaxZ,\n                        slotIndexArrays[currentSlot],\n                        indexOffset\n                    );\n                }\n\n                pendingBatches.push({\n                    indexOffset,\n                    indexCount: overlappingCount,\n                    blockMin: { x: blockMinX, y: blockMinY, z: blockMinZ },\n                    numBlocksX: currBatchX,\n                    numBlocksY: currBatchY,\n                    numBlocksZ: currBatchZ,\n                    bx,\n                    by,\n                    bz\n                });\n\n                indexOffset += overlappingCount;\n\n                if (pendingBatches.length >= MEGA_MAX_BATCHES || indexOffset >= MEGA_MAX_INDICES) {\n                    await flushPendingBatches();\n                }\n            }\n        }\n\n        await flushPendingBatches();\n        bar.tick();\n    }\n\n    if (inflight) {\n        const result = await inflight.resultPromise;\n        processResults(result.masks, inflight.batches);\n        inflight = null;\n    }\n\n    bar.end();\n    return buffer;\n};\n\n/**\n * Align bounds to 4x4x4 block boundaries.\n *\n * @param minX - Scene minimum X\n * @param minY - Scene minimum Y\n * @param minZ - Scene minimum Z\n * @param maxX - Scene maximum X\n * @param maxY - Scene maximum Y\n * @param maxZ - Scene maximum Z\n * @param voxelResolution - Size of each voxel\n * @returns Aligned bounds\n */\nfunction alignGridBounds(\n    minX: number, minY: number, minZ: number,\n    maxX: number, maxY: number, maxZ: number,\n    voxelResolution: number\n): Bounds {\n    const blockSize = 4 * voxelResolution;\n    return {\n        min: new Vec3(\n            Math.floor(minX / blockSize) * blockSize,\n            Math.floor(minY / blockSize) * blockSize,\n            Math.floor(minZ / blockSize) * blockSize\n        ),\n        max: new Vec3(\n            Math.ceil(maxX / blockSize) * blockSize,\n            Math.ceil(maxY / blockSize) * blockSize,\n            Math.ceil(maxZ / blockSize) * blockSize\n        )\n    };\n}\n\nexport { voxelizeToBuffer, alignGridBounds };\n","import { type BlockGridParams } from './voxel-query';\nimport { Column, DataTable, computeGaussianExtents, type Bounds, type GaussianExtentsResult, type GaussianColumns, computeWriteTransform, transformColumns } from '../data-table';\nimport { GpuVoxelization } from '../gpu';\nimport { GaussianBVH } from '../spatial';\nimport type { DeviceCreator } from '../types';\nimport { Transform } from '../utils';\n\n/**\n * Context produced by the shared voxel filter setup pipeline.\n */\ninterface VoxelFilterContext {\n    pcDataTable: DataTable;\n    extentsResult: GaussianExtentsResult;\n    sceneBounds: Bounds;\n    bvh: GaussianBVH;\n    gpuVoxelization: GpuVoxelization | null;\n}\n\n/**\n * Set up the common voxelization pipeline used by both filterCluster and filterFloaters.\n *\n * Transforms columns to world space, computes Gaussian extents, builds a BVH,\n * creates a GPU device, and uploads all Gaussians.\n *\n * @param dataTable - Input Gaussian splat data.\n * @param createDevice - Function to create a GPU device for voxelization.\n * @returns Context containing all shared resources.\n */\nconst setupVoxelFilter = async (\n    dataTable: DataTable,\n    createDevice: DeviceCreator\n): Promise<VoxelFilterContext> => {\n    const voxelColumns = [\n        'x', 'y', 'z',\n        'rot_0', 'rot_1', 'rot_2', 'rot_3',\n        'scale_0', 'scale_1', 'scale_2',\n        'opacity'\n    ];\n    const delta = computeWriteTransform(dataTable.transform, Transform.IDENTITY);\n    const cols = transformColumns(dataTable, voxelColumns, delta);\n\n    const missing = voxelColumns.filter(name => !cols.has(name));\n    if (missing.length > 0) {\n        throw new Error(`setupVoxelFilter: input DataTable is missing required columns: ${missing.join(', ')}`);\n    }\n\n    const pcDataTable = new DataTable(voxelColumns.map(name => new Column(name, cols.get(name)!)));\n\n    const extentsResult = computeGaussianExtents(pcDataTable);\n    const sceneBounds = extentsResult.sceneBounds;\n\n    const bvh = new GaussianBVH(pcDataTable, extentsResult.extents);\n    const device = await createDevice();\n\n    let gpuVoxelization: GpuVoxelization | null = null;\n    try {\n        gpuVoxelization = new GpuVoxelization(device);\n        gpuVoxelization.uploadAllGaussians(pcDataTable, extentsResult.extents);\n    } catch (e) {\n        gpuVoxelization?.destroy();\n        throw e;\n    }\n\n    return { pcDataTable, extentsResult, sceneBounds, bvh, gpuVoxelization };\n};\n\n/**\n * Build GaussianColumns from a VoxelFilterContext.\n *\n * @param ctx - Voxel filter context.\n * @returns Column arrays for Gaussian evaluation.\n */\nconst buildGaussianColumns = (ctx: VoxelFilterContext): GaussianColumns => ({\n    posX: ctx.pcDataTable.getColumnByName('x').data,\n    posY: ctx.pcDataTable.getColumnByName('y').data,\n    posZ: ctx.pcDataTable.getColumnByName('z').data,\n    rotW: ctx.pcDataTable.getColumnByName('rot_0').data,\n    rotX: ctx.pcDataTable.getColumnByName('rot_1').data,\n    rotY: ctx.pcDataTable.getColumnByName('rot_2').data,\n    rotZ: ctx.pcDataTable.getColumnByName('rot_3').data,\n    scaleX: ctx.pcDataTable.getColumnByName('scale_0').data,\n    scaleY: ctx.pcDataTable.getColumnByName('scale_1').data,\n    scaleZ: ctx.pcDataTable.getColumnByName('scale_2').data,\n    opacity: ctx.pcDataTable.getColumnByName('opacity').data,\n    extentX: ctx.extentsResult.extents.getColumnByName('extent_x').data,\n    extentY: ctx.extentsResult.extents.getColumnByName('extent_y').data,\n    extentZ: ctx.extentsResult.extents.getColumnByName('extent_z').data\n});\n\n/**\n * Build BlockGridParams from grid bounds and voxel size.\n *\n * @param gridBounds - Block-aligned grid bounds.\n * @param voxelResolution - Size of each voxel in world units.\n * @returns Block grid parameters.\n */\nconst buildBlockGridParams = (gridBounds: Bounds, voxelResolution: number): BlockGridParams => {\n    const blockSize = 4 * voxelResolution;\n    const numBlocksX = Math.round((gridBounds.max.x - gridBounds.min.x) / blockSize);\n    const numBlocksY = Math.round((gridBounds.max.y - gridBounds.min.y) / blockSize);\n    const numBlocksZ = Math.round((gridBounds.max.z - gridBounds.min.z) / blockSize);\n    return {\n        gridMinX: gridBounds.min.x,\n        gridMinY: gridBounds.min.y,\n        gridMinZ: gridBounds.min.z,\n        blockSize,\n        voxelResolution,\n        numBlocksX,\n        numBlocksY,\n        numBlocksZ,\n        strideY: numBlocksX,\n        strideZ: numBlocksX * numBlocksY\n    };\n};\n\nexport {\n    setupVoxelFilter,\n    buildGaussianColumns,\n    buildBlockGridParams,\n    type VoxelFilterContext\n};\n","import {\n    BLOCK_EMPTY,\n    BLOCK_MIXED,\n    BLOCK_SOLID,\n    FACE_MASKS_HI,\n    FACE_MASKS_LO,\n    SOLID_HI,\n    SOLID_LO,\n    SparseVoxelGrid,\n    readBlockType,\n    writeBlockType\n} from './sparse-voxel-grid';\n\n/**\n * Two-level BFS on a sparse voxel grid.\n *\n * Exploits the fact that most blocks in the blocked grid are BLOCK_EMPTY (all\n * 64 voxels free). When BFS reaches such a block, ALL voxels are reachable\n * (mutually face-connected within the 4x4x4 cube), so we mark the entire\n * block as visited and propagate at block granularity -- 64x fewer operations.\n *\n * Two queues:\n *   Block queue  -- processes BLOCK_EMPTY (in blocked) blocks at block level\n *   Voxel queue  -- processes individual voxels in BLOCK_MIXED blocks\n *\n * When the voxel BFS enters a BLOCK_EMPTY block it switches to block fill.\n * When block fill hits a BLOCK_MIXED neighbor it enqueues free face voxels.\n *\n * @param blocked - Sparse voxel grid marking blocked voxels.\n * @param blockSeeds - Block indices to seed block-level BFS from.\n * @param voxelSeeds - Voxel coordinates to seed voxel-level BFS from.\n * @param nx - Grid dimension X in voxels.\n * @param ny - Grid dimension Y in voxels.\n * @param nz - Grid dimension Z in voxels.\n * @param onBlockFilled - Optional progress callback receiving the running\n * count of whole-block fills. Throttled internally so callers can wire it\n * directly to a progress bar without worrying about per-block overhead.\n * @returns Sparse voxel grid marking all reachable voxels.\n */\nfunction twoLevelBFS(\n    blocked: SparseVoxelGrid,\n    blockSeeds: number[],\n    voxelSeeds: { ix: number; iy: number; iz: number }[],\n    nx: number, ny: number, nz: number,\n    onBlockFilled?: (count: number) => void\n): SparseVoxelGrid {\n    const visited = new SparseVoxelGrid(nx, ny, nz);\n    const nbx = nx >> 2;\n    const nby = ny >> 2;\n    const nbz = nz >> 2;\n    const bStride = nbx * nby;\n\n    const blockedTypes = blocked.types;\n    const bMasks = blocked.masks;\n    const visitedTypes = visited.types;\n    const vMasks = visited.masks;\n\n    // Block queue (ring buffer of block indices)\n    let bqCap = 1 << 14;\n    let bqBuf = new Uint32Array(bqCap);\n    let bqMask = bqCap - 1;\n    let bqHead = 0;\n    let bqTail = 0;\n    let bqSize = 0;\n\n    // Voxel queue (ring buffer of coordinates)\n    let vqCap = 1 << 14;\n    let vqIx = new Uint32Array(vqCap);\n    let vqIy = new Uint32Array(vqCap);\n    let vqIz = new Uint32Array(vqCap);\n    let vqMask = vqCap - 1;\n    let vqHead = 0;\n    let vqTail = 0;\n    let vqSize = 0;\n\n    // Power-of-two cap that fits a Uint32Array index (2^30 entries = 4GB each).\n    const QUEUE_CAP_MAX = 1 << 30;\n\n    const growBlockQueue = (): void => {\n        if (bqCap >= QUEUE_CAP_MAX) {\n            throw new Error(`flood-fill: block queue exceeded ${QUEUE_CAP_MAX} entries — scene likely contains pathologically large gaussians or a connected component too large to flood-fill at this resolution. Try a coarser --filter-cluster resolution or pre-filter outliers (e.g. --filter-box).`);\n        }\n        const newCap = bqCap * 2;\n        const nb = new Uint32Array(newCap);\n        for (let i = 0; i < bqSize; i++) nb[i] = bqBuf[(bqHead + i) & bqMask];\n        bqBuf = nb;\n        bqCap = newCap;\n        bqMask = newCap - 1;\n        bqHead = 0;\n        bqTail = bqSize;\n    };\n\n    const growVoxelQueue = (): void => {\n        if (vqCap >= QUEUE_CAP_MAX) {\n            throw new Error(`flood-fill: voxel queue exceeded ${QUEUE_CAP_MAX} entries — scene likely contains pathologically large gaussians or a connected component too large to flood-fill at this resolution. Try a coarser --filter-cluster resolution or pre-filter outliers (e.g. --filter-box).`);\n        }\n        const newCap = vqCap * 2;\n        const nix = new Uint32Array(newCap);\n        const niy = new Uint32Array(newCap);\n        const niz = new Uint32Array(newCap);\n        for (let i = 0; i < vqSize; i++) {\n            const j = (vqHead + i) & vqMask;\n            nix[i] = vqIx[j];\n            niy[i] = vqIy[j];\n            niz[i] = vqIz[j];\n        }\n        vqIx = nix;\n        vqIy = niy;\n        vqIz = niz;\n        vqCap = newCap;\n        vqMask = newCap - 1;\n        vqHead = 0;\n        vqTail = vqSize;\n    };\n\n    const enqueueVoxel = (ix: number, iy: number, iz: number): void => {\n        if (vqSize >= vqCap) growVoxelQueue();\n        vqIx[vqTail] = ix;\n        vqIy[vqTail] = iy;\n        vqIz[vqTail] = iz;\n        vqTail = (vqTail + 1) & vqMask;\n        vqSize++;\n    };\n\n    const PROGRESS_INTERVAL = 1024;\n    let blockFillCount = 0;\n    let nextProgressAt = PROGRESS_INTERVAL;\n\n    const tryFillBlock = (blockIdx: number): boolean => {\n        if (readBlockType(blockedTypes, blockIdx) !== BLOCK_EMPTY) return false;\n        if (readBlockType(visitedTypes, blockIdx) !== BLOCK_EMPTY) return false;\n        writeBlockType(visitedTypes, blockIdx, BLOCK_SOLID);\n        if (bqSize >= bqCap) growBlockQueue();\n        bqBuf[bqTail] = blockIdx;\n        bqTail = (bqTail + 1) & bqMask;\n        bqSize++;\n        blockFillCount++;\n        if (onBlockFilled && blockFillCount >= nextProgressAt) {\n            onBlockFilled(blockFillCount);\n            nextProgressAt = blockFillCount + PROGRESS_INTERVAL;\n        }\n        return true;\n    };\n\n    const enqueueFaceVoxels = (nBlockIdx: number, face: number, nBx: number, nBy: number, nBz: number): void => {\n        const vbt = readBlockType(visitedTypes, nBlockIdx);\n        if (vbt === BLOCK_SOLID) return;\n\n        const bs = bMasks.slot(nBlockIdx);\n        let vLo = 0, vHi = 0;\n        let vs = -1;\n        if (vbt === BLOCK_MIXED) {\n            vs = vMasks.slot(nBlockIdx);\n            vLo = vMasks.lo[vs];\n            vHi = vMasks.hi[vs];\n        }\n\n        const freeLo = (FACE_MASKS_LO[face] & ~bMasks.lo[bs] & ~vLo) >>> 0;\n        const freeHi = (FACE_MASKS_HI[face] & ~bMasks.hi[bs] & ~vHi) >>> 0;\n        if (freeLo === 0 && freeHi === 0) return;\n\n        if (vbt === BLOCK_EMPTY) {\n            writeBlockType(visitedTypes, nBlockIdx, BLOCK_MIXED);\n            vMasks.set(nBlockIdx, freeLo, freeHi);\n        } else {\n            vMasks.lo[vs] = (vMasks.lo[vs] | freeLo) >>> 0;\n            vMasks.hi[vs] = (vMasks.hi[vs] | freeHi) >>> 0;\n            if (vMasks.lo[vs] === SOLID_LO && vMasks.hi[vs] === SOLID_HI) {\n                vMasks.removeAt(vs);\n                writeBlockType(visitedTypes, nBlockIdx, BLOCK_SOLID);\n            }\n        }\n\n        const baseIx = nBx << 2;\n        const baseIy = nBy << 2;\n        const baseIz = nBz << 2;\n\n        let bits = freeLo;\n        while (bits) {\n            const bp = 31 - Math.clz32(bits & -bits);\n            enqueueVoxel(baseIx + (bp & 3), baseIy + ((bp >> 2) & 3), baseIz + (bp >> 4));\n            bits &= bits - 1;\n        }\n        bits = freeHi;\n        while (bits) {\n            const bp = 31 - Math.clz32(bits & -bits);\n            const bi = bp + 32;\n            enqueueVoxel(baseIx + (bi & 3), baseIy + ((bi >> 2) & 3), baseIz + (bi >> 4));\n            bits &= bits - 1;\n        }\n    };\n\n    const processBlock = (blockIdx: number): void => {\n        const bx = blockIdx % nbx;\n        const byBz = (blockIdx / nbx) | 0;\n        const by = byBz % nby;\n        const bz = (byBz / nby) | 0;\n\n        if (bx > 0) {\n            const ni = blockIdx - 1;\n            const nbt = readBlockType(blockedTypes, ni);\n            if (nbt === BLOCK_EMPTY) tryFillBlock(ni);\n            else if (nbt === BLOCK_MIXED) enqueueFaceVoxels(ni, 1, bx - 1, by, bz);\n        }\n        if (bx < nbx - 1) {\n            const ni = blockIdx + 1;\n            const nbt = readBlockType(blockedTypes, ni);\n            if (nbt === BLOCK_EMPTY) tryFillBlock(ni);\n            else if (nbt === BLOCK_MIXED) enqueueFaceVoxels(ni, 0, bx + 1, by, bz);\n        }\n        if (by > 0) {\n            const ni = blockIdx - nbx;\n            const nbt = readBlockType(blockedTypes, ni);\n            if (nbt === BLOCK_EMPTY) tryFillBlock(ni);\n            else if (nbt === BLOCK_MIXED) enqueueFaceVoxels(ni, 3, bx, by - 1, bz);\n        }\n        if (by < nby - 1) {\n            const ni = blockIdx + nbx;\n            const nbt = readBlockType(blockedTypes, ni);\n            if (nbt === BLOCK_EMPTY) tryFillBlock(ni);\n            else if (nbt === BLOCK_MIXED) enqueueFaceVoxels(ni, 2, bx, by + 1, bz);\n        }\n        if (bz > 0) {\n            const ni = blockIdx - bStride;\n            const nbt = readBlockType(blockedTypes, ni);\n            if (nbt === BLOCK_EMPTY) tryFillBlock(ni);\n            else if (nbt === BLOCK_MIXED) enqueueFaceVoxels(ni, 5, bx, by, bz - 1);\n        }\n        if (bz < nbz - 1) {\n            const ni = blockIdx + bStride;\n            const nbt = readBlockType(blockedTypes, ni);\n            if (nbt === BLOCK_EMPTY) tryFillBlock(ni);\n            else if (nbt === BLOCK_MIXED) enqueueFaceVoxels(ni, 4, bx, by, bz + 1);\n        }\n    };\n\n    const tryEnqueueVoxel = (ix: number, iy: number, iz: number): void => {\n        const blockIdx = (ix >> 2) + (iy >> 2) * nbx + (iz >> 2) * bStride;\n\n        const bbt = readBlockType(blockedTypes, blockIdx);\n        if (bbt === BLOCK_SOLID) return;\n        if (bbt === BLOCK_EMPTY) {\n            tryFillBlock(blockIdx);\n            return;\n        }\n\n        const bs = bMasks.slot(blockIdx);\n        const bitIdx = (ix & 3) + ((iy & 3) << 2) + ((iz & 3) << 4);\n        if (bitIdx < 32 ? (bMasks.lo[bs] >>> bitIdx) & 1 : (bMasks.hi[bs] >>> (bitIdx - 32)) & 1) return;\n\n        const vbt = readBlockType(visitedTypes, blockIdx);\n        if (vbt === BLOCK_SOLID) return;\n        if (vbt === BLOCK_MIXED) {\n            const vs = vMasks.slot(blockIdx);\n            if (bitIdx < 32 ? (vMasks.lo[vs] >>> bitIdx) & 1 : (vMasks.hi[vs] >>> (bitIdx - 32)) & 1) return;\n            if (bitIdx < 32) vMasks.lo[vs] = (vMasks.lo[vs] | (1 << bitIdx)) >>> 0;\n            else vMasks.hi[vs] = (vMasks.hi[vs] | (1 << (bitIdx - 32))) >>> 0;\n            if (vMasks.lo[vs] === SOLID_LO && vMasks.hi[vs] === SOLID_HI) {\n                vMasks.removeAt(vs);\n                writeBlockType(visitedTypes, blockIdx, BLOCK_SOLID);\n            }\n        } else {\n            writeBlockType(visitedTypes, blockIdx, BLOCK_MIXED);\n            vMasks.set(blockIdx,\n                bitIdx < 32 ? (1 << bitIdx) >>> 0 : 0,\n                bitIdx >= 32 ? (1 << (bitIdx - 32)) >>> 0 : 0\n            );\n        }\n\n        enqueueVoxel(ix, iy, iz);\n    };\n\n    // --- Seeding ---\n\n    for (let i = 0; i < blockSeeds.length; i++) {\n        tryFillBlock(blockSeeds[i]);\n    }\n\n    for (let i = 0; i < voxelSeeds.length; i++) {\n        const s = voxelSeeds[i];\n        tryEnqueueVoxel(s.ix, s.iy, s.iz);\n    }\n\n    // --- Main BFS loop ---\n\n    while (bqSize > 0 || vqSize > 0) {\n        while (bqSize > 0) {\n            const blockIdx = bqBuf[bqHead];\n            bqHead = (bqHead + 1) & bqMask;\n            bqSize--;\n            processBlock(blockIdx);\n        }\n\n        if (vqSize > 0) {\n            const ix = vqIx[vqHead];\n            const iy = vqIy[vqHead];\n            const iz = vqIz[vqHead];\n            vqHead = (vqHead + 1) & vqMask;\n            vqSize--;\n\n            if (ix > 0) tryEnqueueVoxel(ix - 1, iy, iz);\n            if (ix < nx - 1) tryEnqueueVoxel(ix + 1, iy, iz);\n            if (iy > 0) tryEnqueueVoxel(ix, iy - 1, iz);\n            if (iy < ny - 1) tryEnqueueVoxel(ix, iy + 1, iz);\n            if (iz > 0) tryEnqueueVoxel(ix, iy, iz - 1);\n            if (iz < nz - 1) tryEnqueueVoxel(ix, iy, iz + 1);\n        }\n    }\n\n    if (onBlockFilled) onBlockFilled(blockFillCount);\n\n    return visited;\n}\n\nexport { twoLevelBFS };\n","import { BlockMaskBuffer } from './block-mask-buffer';\nimport {\n    computeGaussianInverse,\n    evaluateGaussianAt,\n    type GaussianColumns\n} from '../data-table';\n\n/**\n * Pre-computed lookup structures for efficient voxel block queries.\n */\ninterface BlockLookup {\n    solidSet: Set<number>;\n    mixedMap: Map<number, number>;\n    masks: Uint32Array;\n}\n\n/**\n * Grid parameters for block-based voxel queries.\n */\ninterface BlockGridParams {\n    gridMinX: number;\n    gridMinY: number;\n    gridMinZ: number;\n    blockSize: number;\n    voxelResolution: number;\n    numBlocksX: number;\n    numBlocksY: number;\n    numBlocksZ: number;\n    strideY: number;\n    strideZ: number;\n}\n\n/**\n * Build block lookup structures from the buffer's linear block indices.\n * The buffer's keys are already linear block indices, so this is a direct\n * copy into a Set / Map for O(1) random access.\n *\n * @param buffer - Block mask buffer containing voxelized blocks.\n * @returns Solid block set, mixed block map (linear index to masks array index), and masks.\n */\nconst buildBlockLookup = (\n    buffer: BlockMaskBuffer\n): BlockLookup => {\n    const solidSet = new Set<number>();\n    const solidIdx = buffer.getSolidBlocks();\n    for (let i = 0; i < solidIdx.length; i++) {\n        solidSet.add(solidIdx[i]);\n    }\n    const mixed = buffer.getMixedBlocks();\n    const mixedMap = new Map<number, number>();\n    for (let i = 0; i < mixed.blockIdx.length; i++) {\n        mixedMap.set(mixed.blockIdx[i], i);\n    }\n    return { solidSet, mixedMap, masks: mixed.masks };\n};\n\n/**\n * Test whether a Gaussian's center lies inside an occupied voxel.\n *\n * @param px - Gaussian center x.\n * @param py - Gaussian center y.\n * @param pz - Gaussian center z.\n * @param grid - Block grid parameters.\n * @param lookup - Block lookup structures.\n * @param blockFilter - Optional set of block indices to restrict the test to.\n * @returns True if the center is in an occupied (and optionally filtered) voxel.\n */\nconst isCenterInOccupiedVoxel = (\n    px: number, py: number, pz: number,\n    grid: BlockGridParams,\n    lookup: BlockLookup,\n    blockFilter?: Set<number>\n): boolean => {\n    const centerBx = Math.floor((px - grid.gridMinX) / grid.blockSize);\n    const centerBy = Math.floor((py - grid.gridMinY) / grid.blockSize);\n    const centerBz = Math.floor((pz - grid.gridMinZ) / grid.blockSize);\n\n    if (centerBx < 0 || centerBx >= grid.numBlocksX ||\n        centerBy < 0 || centerBy >= grid.numBlocksY ||\n        centerBz < 0 || centerBz >= grid.numBlocksZ) {\n        return false;\n    }\n\n    const centerBlockIdx = centerBx + centerBy * grid.strideY + centerBz * grid.strideZ;\n    if (blockFilter && !blockFilter.has(centerBlockIdx)) {\n        return false;\n    }\n\n    if (lookup.solidSet.has(centerBlockIdx)) {\n        return true;\n    }\n\n    const centerMixedIdx = lookup.mixedMap.get(centerBlockIdx);\n    if (centerMixedIdx !== undefined) {\n        const lx = Math.floor((px - grid.gridMinX - centerBx * grid.blockSize) / grid.voxelResolution);\n        const ly = Math.floor((py - grid.gridMinY - centerBy * grid.blockSize) / grid.voxelResolution);\n        const lz = Math.floor((pz - grid.gridMinZ - centerBz * grid.blockSize) / grid.voxelResolution);\n        const bitIdx = (lx & 3) + (ly & 3) * 4 + (lz & 3) * 16;\n        const word = bitIdx < 32 ? lookup.masks[centerMixedIdx * 2] : lookup.masks[centerMixedIdx * 2 + 1];\n        if ((word >>> (bitIdx & 31)) & 1) {\n            return true;\n        }\n    }\n\n    return false;\n};\n\n/**\n * Test whether a Gaussian has meaningful contribution at occupied voxel\n * centers in blocks that overlap its AABB.\n *\n * Iterates over blocks that overlap the Gaussian's AABB, then evaluates the\n * Gaussian's opacity contribution at each occupied voxel center in those\n * blocks. Returns true once `minHits` qualifying voxels are found. With the\n * default `minHits = 1` this short-circuits on the first hit; larger values\n * let callers reject elongated outliers (e.g. spikes) whose tails clip only\n * a single cluster voxel.\n *\n * @param gaussianIdx - Index of the Gaussian.\n * @param columns - Gaussian column data arrays.\n * @param grid - Block grid parameters.\n * @param lookup - Block lookup structures.\n * @param minContribution - Minimum contribution threshold.\n * @param blockFilter - Optional set of block indices to restrict the test to.\n * @param minHits - Minimum number of qualifying voxels required. Default 1.\n * @returns True if at least `minHits` qualifying voxels were found.\n */\nconst gaussianContributesToVoxels = (\n    gaussianIdx: number,\n    columns: GaussianColumns,\n    grid: BlockGridParams,\n    lookup: BlockLookup,\n    minContribution: number,\n    blockFilter?: Set<number>,\n    minHits: number = 1\n): boolean => {\n    const px = columns.posX[gaussianIdx];\n    const py = columns.posY[gaussianIdx];\n    const pz = columns.posZ[gaussianIdx];\n    const ex = columns.extentX[gaussianIdx];\n    const ey = columns.extentY[gaussianIdx];\n    const ez = columns.extentZ[gaussianIdx];\n\n    const aabbMinBx = Math.max(0, Math.floor((px - ex - grid.gridMinX) / grid.blockSize));\n    const aabbMaxBx = Math.min(grid.numBlocksX - 1, Math.floor((px + ex - grid.gridMinX) / grid.blockSize));\n    const aabbMinBy = Math.max(0, Math.floor((py - ey - grid.gridMinY) / grid.blockSize));\n    const aabbMaxBy = Math.min(grid.numBlocksY - 1, Math.floor((py + ey - grid.gridMinY) / grid.blockSize));\n    const aabbMinBz = Math.max(0, Math.floor((pz - ez - grid.gridMinZ) / grid.blockSize));\n    const aabbMaxBz = Math.min(grid.numBlocksZ - 1, Math.floor((pz + ez - grid.gridMinZ) / grid.blockSize));\n\n    const g = computeGaussianInverse(\n        columns.rotW[gaussianIdx], columns.rotX[gaussianIdx],\n        columns.rotY[gaussianIdx], columns.rotZ[gaussianIdx],\n        columns.scaleX[gaussianIdx], columns.scaleY[gaussianIdx],\n        columns.scaleZ[gaussianIdx], columns.opacity[gaussianIdx]\n    );\n\n    let hits = 0;\n    for (let bbz = aabbMinBz; bbz <= aabbMaxBz; bbz++) {\n        const zOff = bbz * grid.strideZ;\n        for (let bby = aabbMinBy; bby <= aabbMaxBy; bby++) {\n            const yzOff = bby * grid.strideY + zOff;\n            for (let bbx = aabbMinBx; bbx <= aabbMaxBx; bbx++) {\n                const blockIdx = bbx + yzOff;\n                if (blockFilter && !blockFilter.has(blockIdx)) continue;\n                const isSolid = lookup.solidSet.has(blockIdx);\n                const mixedIdx = isSolid ? -1 : lookup.mixedMap.get(blockIdx);\n                if (!isSolid && mixedIdx === undefined) continue;\n\n                const blockOriginX = grid.gridMinX + bbx * grid.blockSize;\n                const blockOriginY = grid.gridMinY + bby * grid.blockSize;\n                const blockOriginZ = grid.gridMinZ + bbz * grid.blockSize;\n\n                const lo = isSolid ? 0xFFFFFFFF : lookup.masks[mixedIdx * 2];\n                const hi = isSolid ? 0xFFFFFFFF : lookup.masks[mixedIdx * 2 + 1];\n\n                for (let lz = 0; lz < 4; lz++) {\n                    const vz = blockOriginZ + (lz + 0.5) * grid.voxelResolution;\n                    const word = lz < 2 ? lo : hi;\n                    const zBitBase = (lz & 1) * 16;\n\n                    for (let ly = 0; ly < 4; ly++) {\n                        const bitBase = zBitBase + ly * 4;\n                        const vy = blockOriginY + (ly + 0.5) * grid.voxelResolution;\n\n                        for (let lx = 0; lx < 4; lx++) {\n                            if (!((word >>> (bitBase + lx)) & 1)) continue;\n\n                            const vx = blockOriginX + (lx + 0.5) * grid.voxelResolution;\n\n                            if (evaluateGaussianAt(g, px, py, pz, vx, vy, vz) >= minContribution) {\n                                if (++hits >= minHits) return true;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    return false;\n};\n\nexport {\n    buildBlockLookup,\n    isCenterInOccupiedVoxel,\n    gaussianContributesToVoxels,\n    type BlockLookup,\n    type BlockGridParams\n};\n","import { Vec3 } from 'playcanvas';\n\nimport { BlockMaskBuffer } from './block-mask-buffer';\nimport {\n    setupVoxelFilter,\n    buildGaussianColumns,\n    buildBlockGridParams,\n    type VoxelFilterContext\n} from './filter-pipeline';\nimport { twoLevelBFS } from './flood-fill';\nimport {\n    BLOCK_EMPTY,\n    BLOCK_MIXED,\n    BLOCKS_PER_WORD,\n    EVEN_BITS,\n    SOLID_WORD,\n    SparseVoxelGrid\n} from './sparse-voxel-grid';\nimport {\n    buildBlockLookup,\n    isCenterInOccupiedVoxel,\n    gaussianContributesToVoxels\n} from './voxel-query';\nimport { alignGridBounds, voxelizeToBuffer } from './voxelize';\nimport { DataTable } from '../data-table';\nimport type { DeviceCreator } from '../types';\nimport { fmtCount, fmtDistance, logger } from '../utils';\n\n/**\n * Build an inverted SparseVoxelGrid from a BlockMaskBuffer for flood-filling\n * through occupied voxels. In the returned grid, originally-occupied voxels\n * are free (unblocked) and empty space is blocked.\n *\n * @param buffer - Block mask buffer with voxelization results.\n * @param nx - Grid dimension X in voxels.\n * @param ny - Grid dimension Y in voxels.\n * @param nz - Grid dimension Z in voxels.\n * @returns Inverted grid suitable for twoLevelBFS.\n */\nconst buildInvertedGrid = (\n    buffer: BlockMaskBuffer,\n    nx: number, ny: number, nz: number\n): SparseVoxelGrid => {\n    const grid = new SparseVoxelGrid(nx, ny, nz);\n\n    // Inverted grid: every block defaults to SOLID (fully blocked). SOLID is\n    // 0b01 in each 2-bit lane, so the SOLID-everywhere word is `SOLID_WORD`\n    // (0x55555555). Subsequent code clears the lanes corresponding to\n    // originally-occupied (i.e. unblocked-in-the-inverted-world) blocks.\n    grid.types.fill(SOLID_WORD);\n    // Trim the final word so the trailing lanes (past totalBlocks) read\n    // back as EMPTY rather than SOLID.\n    const totalBlocks = grid.nbx * grid.nby * grid.nbz;\n    if (totalBlocks === 0) {\n        return grid;\n    }\n    const lastWord = grid.types.length - 1;\n    const lastLanes = totalBlocks - lastWord * BLOCKS_PER_WORD;\n    if (lastLanes < BLOCKS_PER_WORD) {\n        const validBits = (1 << (lastLanes * 2)) - 1;\n        grid.types[lastWord] = (grid.types[lastWord] & validBits) >>> 0;\n    }\n\n    const solidIdx = buffer.getSolidBlocks();\n    for (let i = 0; i < solidIdx.length; i++) {\n        grid.setBlockType(solidIdx[i], BLOCK_EMPTY);\n    }\n\n    const mixed = buffer.getMixedBlocks();\n    for (let i = 0; i < mixed.blockIdx.length; i++) {\n        const blockIdx = mixed.blockIdx[i];\n        grid.setBlockType(blockIdx, BLOCK_MIXED);\n        grid.masks.set(blockIdx, (~mixed.masks[i * 2]) >>> 0, (~mixed.masks[i * 2 + 1]) >>> 0);\n    }\n\n    return grid;\n};\n\n/**\n * Find the connected component of occupied voxels reachable from a seed\n * position via 6-connected voxel-level flood fill. Returns the set of block\n * linear indices that contain at least one reachable voxel, the visited grid,\n * and the resolved seed position.\n *\n * If the seed voxel is not occupied, finds the nearest occupied voxel first.\n *\n * @param buffer - Block mask buffer with voxelization results.\n * @param nx - Grid dimension X in voxels.\n * @param ny - Grid dimension Y in voxels.\n * @param nz - Grid dimension Z in voxels.\n * @param seedIx - Seed voxel X coordinate.\n * @param seedIy - Seed voxel Y coordinate.\n * @param seedIz - Seed voxel Z coordinate.\n * @returns Object with ccSet, visited grid, and the resolved seed, or null if no occupied voxel found.\n */\nconst findClusterVoxelFlood = (\n    buffer: BlockMaskBuffer,\n    nx: number, ny: number, nz: number,\n    seedIx: number, seedIy: number, seedIz: number\n): { ccSet: Set<number>; visited: SparseVoxelGrid; resolvedSeed: { ix: number; iy: number; iz: number } } | null => {\n    const blocked = buildInvertedGrid(buffer, nx, ny, nz);\n    const nbx = nx >> 2;\n    const bStride = nbx * (ny >> 2);\n\n    // In the inverted grid, occupied voxels are \"free\" (unblocked).\n    // If seed is blocked (unoccupied), find nearest free (occupied) voxel.\n    if (blocked.getVoxel(seedIx, seedIy, seedIz)) {\n        const maxRadius = Math.max(nx, ny, nz);\n        const nearest = SparseVoxelGrid.findNearestFreeCell(blocked, seedIx, seedIy, seedIz, maxRadius);\n        if (!nearest) return null;\n        seedIx = nearest.ix;\n        seedIy = nearest.iy;\n        seedIz = nearest.iz;\n    }\n\n    const seedBlockIdx = (seedIx >> 2) + (seedIy >> 2) * nbx + (seedIz >> 2) * bStride;\n    const seedBt = blocked.getBlockType(seedBlockIdx);\n    const blockSeeds = seedBt === BLOCK_EMPTY ? [seedBlockIdx] : [];\n    const voxelSeeds = seedBt === BLOCK_EMPTY ? [] : [{ ix: seedIx, iy: seedIy, iz: seedIz }];\n\n    const visited = twoLevelBFS(blocked, blockSeeds, voxelSeeds, nx, ny, nz);\n\n    const ccSet = new Set<number>();\n    const totalBlocks = nbx * (ny >> 2) * (nz >> 2);\n    const visitedTypes = visited.types;\n    for (let w = 0; w < visitedTypes.length; w++) {\n        const word = visitedTypes[w];\n        if (word === 0) continue;\n        let nonEmpty = ((word & EVEN_BITS) | ((word >>> 1) & EVEN_BITS)) >>> 0;\n        const baseIdx = w * BLOCKS_PER_WORD;\n        while (nonEmpty) {\n            const bp = 31 - Math.clz32(nonEmpty & -nonEmpty);\n            const blockIdx = baseIdx + (bp >>> 1);\n            if (blockIdx < totalBlocks) {\n                ccSet.add(blockIdx);\n            }\n            nonEmpty &= nonEmpty - 1;\n        }\n    }\n\n    return { ccSet, visited, resolvedSeed: { ix: seedIx, iy: seedIy, iz: seedIz } };\n};\n\n/**\n * Filter a Gaussian splat DataTable to keep only Gaussians that contribute to\n * the connected component found by GPU voxelization from a seed position.\n *\n * @param dataTable - Input Gaussian splat data.\n * @param createDevice - Function to create a GPU device for voxelization.\n * @param voxelResolution - Voxel size in world units for coarse voxelization. Default: 1.0.\n * @param seed - Seed position in world space. Default: (0,0,0).\n * @param opacityCutoff - Opacity threshold for solid voxels. Default: 0.999.\n * @param minContribution - Minimum Gaussian contribution at a cluster voxel center to be kept. Default: 0.1.\n * @returns Filtered DataTable containing only Gaussians in the seed's cluster.\n */\nconst filterCluster = async (\n    dataTable: DataTable,\n    createDevice: DeviceCreator,\n    voxelResolution: number = 1.0,\n    seed: Vec3 = Vec3.ZERO,\n    opacityCutoff: number = 0.999,\n    minContribution: number = 0.1\n): Promise<DataTable> => {\n    if (!Number.isFinite(voxelResolution) || voxelResolution <= 0) {\n        throw new Error(`filterCluster: voxelResolution must be a positive finite number, got ${voxelResolution}`);\n    }\n    if (!Number.isFinite(opacityCutoff) || opacityCutoff < 0 || opacityCutoff > 1) {\n        throw new Error(`filterCluster: opacityCutoff must be a finite number in [0, 1], got ${opacityCutoff}`);\n    }\n    if (!Number.isFinite(minContribution) || minContribution < 0) {\n        throw new Error(`filterCluster: minContribution must be a non-negative finite number, got ${minContribution}`);\n    }\n\n    const numRows = dataTable.numRows;\n    if (numRows === 0) return dataTable;\n\n    const g = logger.group('Filter cluster');\n\n    // Emit the action's gaussian delta inside its own group, then close it.\n    // The \"filter-cluster:\" prefix would just restate the group header.\n    const finish = (out: DataTable): DataTable => {\n        const removed = numRows - out.numRows;\n        if (removed > 0) {\n            logger.info(`removed ${fmtCount(removed)} gaussians`);\n        }\n        g.end();\n        return out;\n    };\n\n    let ctx: VoxelFilterContext | undefined;\n    try {\n        ctx = await setupVoxelFilter(dataTable, createDevice);\n\n        const clampedResolution = Math.max(0.01, voxelResolution);\n        // Per-axis cap: 4096 voxels = 1024 blocks. Total blocks <= 1024^3 = 2^30,\n        // safely under the 2^32 limit imposed by uint32 block indexing in\n        // SparseVoxelGrid (readBlockType/writeBlockType use `blockIdx >>> 4`,\n        // which truncates indices >= 2^32 and corrupts visited-state tracking).\n        const maxGridExtent = 4096 * clampedResolution;\n\n        const sceneExtentX = ctx.sceneBounds.max.x - ctx.sceneBounds.min.x;\n        const sceneExtentY = ctx.sceneBounds.max.y - ctx.sceneBounds.min.y;\n        const sceneExtentZ = ctx.sceneBounds.max.z - ctx.sceneBounds.min.z;\n\n        const gridBounds = alignGridBounds(\n            ctx.sceneBounds.min.x, ctx.sceneBounds.min.y, ctx.sceneBounds.min.z,\n            ctx.sceneBounds.max.x, ctx.sceneBounds.max.y, ctx.sceneBounds.max.z,\n            clampedResolution\n        );\n\n        const clampAxis = (min: number, max: number, seedV: number) => {\n            const extent = max - min;\n            if (extent > maxGridExtent) {\n                const half = maxGridExtent * 0.5;\n                const c = Math.max(min + half, Math.min(seedV, max - half));\n                return { min: c - half, max: c + half };\n            }\n            return { min, max };\n        };\n\n        const cx = clampAxis(gridBounds.min.x, gridBounds.max.x, seed.x);\n        const cy = clampAxis(gridBounds.min.y, gridBounds.max.y, seed.y);\n        const cz = clampAxis(gridBounds.min.z, gridBounds.max.z, seed.z);\n        gridBounds.min.set(cx.min, cy.min, cz.min);\n        gridBounds.max.set(cx.max, cy.max, cz.max);\n\n        const grid = buildBlockGridParams(gridBounds, clampedResolution);\n        const nbx = grid.numBlocksX;\n        const nby = grid.numBlocksY;\n        const nbz = grid.numBlocksZ;\n        const nx = nbx * 4;\n        const ny = nby * 4;\n        const nz = nbz * 4;\n\n        const totalVoxels = nx * ny * nz;\n        logger.info(`scene: ${fmtDistance(sceneExtentX)} x ${fmtDistance(sceneExtentY)} x ${fmtDistance(sceneExtentZ)}, grid: ${nx} x ${ny} x ${nz} voxels (${fmtCount(totalVoxels)}) @ ${fmtDistance(clampedResolution)}`);\n\n        const buffer = await voxelizeToBuffer(\n            ctx.bvh, ctx.gpuVoxelization!, gridBounds, clampedResolution, opacityCutoff\n        );\n\n        ctx.gpuVoxelization.destroy();\n        ctx.gpuVoxelization = null;\n\n        if (buffer.count === 0) {\n            logger.warn('no occupied blocks found, returning empty result');\n            return finish(dataTable.clone({ rows: [] }));\n        }\n\n        const seedIx = Math.max(0, Math.min(Math.floor((seed.x - gridBounds.min.x) / clampedResolution), nx - 1));\n        const seedIy = Math.max(0, Math.min(Math.floor((seed.y - gridBounds.min.y) / clampedResolution), ny - 1));\n        const seedIz = Math.max(0, Math.min(Math.floor((seed.z - gridBounds.min.z) / clampedResolution), nz - 1));\n\n        const floodResult = findClusterVoxelFlood(buffer, nx, ny, nz, seedIx, seedIy, seedIz);\n        if (!floodResult) {\n            logger.warn('no occupied voxel found near seed, returning empty result');\n            return finish(dataTable.clone({ rows: [] }));\n        }\n\n        const { ccSet, visited: visitedGrid, resolvedSeed } = floodResult;\n        if (resolvedSeed.ix !== seedIx || resolvedSeed.iy !== seedIy || resolvedSeed.iz !== seedIz) {\n            const worldX = gridBounds.min.x + (resolvedSeed.ix + 0.5) * clampedResolution;\n            const worldY = gridBounds.min.y + (resolvedSeed.iy + 0.5) * clampedResolution;\n            const worldZ = gridBounds.min.z + (resolvedSeed.iz + 0.5) * clampedResolution;\n            logger.warn(`seed (${seed.x.toFixed(2)}, ${seed.y.toFixed(2)}, ${seed.z.toFixed(2)}) unoccupied; resolved to nearest at (${worldX.toFixed(2)}, ${worldY.toFixed(2)}, ${worldZ.toFixed(2)})`);\n        }\n\n        logger.info(`cluster is ${fmtCount(ccSet.size)} of ${fmtCount(buffer.count)} blocks`);\n\n        // Build lookup from visited voxels only (not all original voxels in ccSet blocks).\n        // Every visited voxel is originally-occupied (the BFS only traverses through them),\n        // so the visited grid is a correct subset of the original buffer.\n        const visitedBuffer = visitedGrid.toBuffer(0, 0, 0, nbx, nby, nbz);\n        const lookup = buildBlockLookup(visitedBuffer);\n\n        if (ccSet.size === buffer.count) {\n            logger.info('all blocks in one cluster, no filtering needed');\n            return finish(dataTable);\n        }\n\n        const gaussianCols = buildGaussianColumns(ctx);\n        const keepIndices: number[] = [];\n\n        // Gaussians whose AABB exceeds `largeThreshold` on any axis must hit\n        // at least `minOccupancyRatio` of the voxels in their AABB to be kept,\n        // rejecting elongated outliers (spikes whose tails clip a single\n        // cluster voxel) while preserving structural large gaussians.\n        const largeThreshold = 2.0 * clampedResolution;\n        const minOccupancyRatio = 0.1;\n        const invVoxel = 1 / clampedResolution;\n\n        for (let i = 0; i < numRows; i++) {\n            const px = gaussianCols.posX[i];\n            const py = gaussianCols.posY[i];\n            const pz = gaussianCols.posZ[i];\n\n            if (isCenterInOccupiedVoxel(px, py, pz, grid, lookup)) {\n                keepIndices.push(i);\n                continue;\n            }\n\n            const ex = gaussianCols.extentX[i];\n            const ey = gaussianCols.extentY[i];\n            const ez = gaussianCols.extentZ[i];\n\n            let minHits = 1;\n            if (Math.max(ex, ey, ez) * 2 > largeThreshold) {\n                const aabbVoxels = (2 * ex * invVoxel) * (2 * ey * invVoxel) * (2 * ez * invVoxel);\n                minHits = Math.max(1, Math.ceil(aabbVoxels * minOccupancyRatio));\n            }\n\n            if (gaussianContributesToVoxels(i, gaussianCols, grid, lookup, minContribution, undefined, minHits)) {\n                keepIndices.push(i);\n            }\n        }\n\n        if (keepIndices.length === numRows) {\n            return finish(dataTable);\n        }\n        return finish(dataTable.clone({ rows: keepIndices }));\n    } catch (e) {\n        ctx?.gpuVoxelization?.destroy();\n        throw e;\n    }\n};\n\nexport { buildInvertedGrid, findClusterVoxelFlood, filterCluster };\n","import {\n    setupVoxelFilter,\n    buildGaussianColumns,\n    buildBlockGridParams,\n    type VoxelFilterContext\n} from './filter-pipeline';\nimport {\n    buildBlockLookup,\n    isCenterInOccupiedVoxel,\n    gaussianContributesToVoxels\n} from './voxel-query';\nimport { alignGridBounds, voxelizeToBuffer } from './voxelize';\nimport { DataTable } from '../data-table';\nimport type { DeviceCreator } from '../types';\nimport { fmtCount, fmtDistance, logger } from '../utils';\n\n/**\n * Remove Gaussians that don't meaningfully contribute to any solid voxel.\n *\n * GPU-voxelizes the scene at a given resolution, then for each Gaussian evaluates\n * its opacity contribution at each occupied voxel center in its AABB range.\n * Discards Gaussians whose contribution is below `minContribution` at every\n * solid voxel.\n *\n * @param dataTable - Input Gaussian splat data.\n * @param createDevice - Function to create a GPU device for voxelization.\n * @param voxelResolution - Voxel size in world units. Default: 0.05.\n * @param opacityCutoff - Opacity threshold for solid voxels. Default: 0.1.\n * @param minContribution - Minimum Gaussian contribution at a voxel center to be kept. Default: 1/255.\n * @returns Filtered DataTable with floaters removed.\n */\nconst filterFloaters = async (\n    dataTable: DataTable,\n    createDevice: DeviceCreator,\n    voxelResolution: number = 0.05,\n    opacityCutoff: number = 0.1,\n    minContribution: number = 1 / 255\n): Promise<DataTable> => {\n    if (!Number.isFinite(voxelResolution) || voxelResolution <= 0) {\n        throw new Error(`filterFloaters: voxelResolution must be a positive finite number, got ${voxelResolution}`);\n    }\n    if (!Number.isFinite(opacityCutoff) || opacityCutoff < 0 || opacityCutoff > 1) {\n        throw new Error(`filterFloaters: opacityCutoff must be a finite number in [0, 1], got ${opacityCutoff}`);\n    }\n    if (!Number.isFinite(minContribution) || minContribution < 0) {\n        throw new Error(`filterFloaters: minContribution must be a non-negative finite number, got ${minContribution}`);\n    }\n\n    const numRows = dataTable.numRows;\n    if (numRows === 0) return dataTable;\n\n    const g = logger.group('Filter floaters');\n\n    // Emit the action's gaussian delta inside its own group, then close it.\n    // The \"filter-floaters:\" prefix would just restate the group header.\n    const finish = (out: DataTable): DataTable => {\n        const removed = numRows - out.numRows;\n        if (removed > 0) {\n            logger.info(`removed ${fmtCount(removed)} gaussians`);\n        }\n        g.end();\n        return out;\n    };\n\n    let ctx: VoxelFilterContext | undefined;\n    try {\n        ctx = await setupVoxelFilter(dataTable, createDevice);\n\n        const sceneExtentX = ctx.sceneBounds.max.x - ctx.sceneBounds.min.x;\n        const sceneExtentY = ctx.sceneBounds.max.y - ctx.sceneBounds.min.y;\n        const sceneExtentZ = ctx.sceneBounds.max.z - ctx.sceneBounds.min.z;\n\n        const gridBounds = alignGridBounds(\n            ctx.sceneBounds.min.x, ctx.sceneBounds.min.y, ctx.sceneBounds.min.z,\n            ctx.sceneBounds.max.x, ctx.sceneBounds.max.y, ctx.sceneBounds.max.z,\n            voxelResolution\n        );\n\n        const grid = buildBlockGridParams(gridBounds, voxelResolution);\n        const nx = grid.numBlocksX * 4;\n        const ny = grid.numBlocksY * 4;\n        const nz = grid.numBlocksZ * 4;\n        const totalVoxels = nx * ny * nz;\n\n        logger.info(`scene: ${fmtDistance(sceneExtentX)} x ${fmtDistance(sceneExtentY)} x ${fmtDistance(sceneExtentZ)}, grid: ${nx} x ${ny} x ${nz} voxels (${fmtCount(totalVoxels)}) @ ${fmtDistance(voxelResolution)}`);\n\n        const buffer = await voxelizeToBuffer(\n            ctx.bvh, ctx.gpuVoxelization!, gridBounds, voxelResolution, opacityCutoff\n        );\n\n        ctx.gpuVoxelization.destroy();\n        ctx.gpuVoxelization = null;\n\n        const lookup = buildBlockLookup(buffer);\n\n        logger.info(`occupied blocks: ${fmtCount(lookup.solidSet.size + lookup.mixedMap.size)} (${fmtCount(lookup.solidSet.size)} solid, ${fmtCount(lookup.mixedMap.size)} mixed)`);\n\n        const gaussianCols = buildGaussianColumns(ctx);\n        const keepIndices: number[] = [];\n\n        for (let i = 0; i < numRows; i++) {\n            const px = gaussianCols.posX[i];\n            const py = gaussianCols.posY[i];\n            const pz = gaussianCols.posZ[i];\n\n            if (isCenterInOccupiedVoxel(px, py, pz, grid, lookup)) {\n                keepIndices.push(i);\n                continue;\n            }\n\n            if (gaussianContributesToVoxels(i, gaussianCols, grid, lookup, minContribution)) {\n                keepIndices.push(i);\n            }\n        }\n\n        if (keepIndices.length === numRows) {\n            return finish(dataTable);\n        }\n        return finish(dataTable.clone({ rows: keepIndices }));\n    } catch (e) {\n        ctx?.gpuVoxelization?.destroy();\n        throw e;\n    }\n};\n\nexport { filterFloaters };\n","import {\n    BLOCK_EMPTY,\n    BLOCK_SOLID,\n    SOLID_WORD,\n    SparseVoxelGrid,\n    readBlockType\n} from './sparse-voxel-grid';\nimport { GpuDilation } from '../gpu';\nimport { logger } from '../utils';\n\n// ============================================================================\n// GPU Dilation\n//\n// Chunked GPU separable 3D dilation that returns a fresh `SparseVoxelGrid`.\n// Extracts each chunk (with halo) from the source as a dense bit grid, runs\n// X/Z/Y compute passes on the GPU without a CPU round-trip between them,\n// then OR's the inner-only output back into the destination. Source is\n// read-only across the whole call; destination is built up chunk by chunk.\n// ============================================================================\n\n/** Inner chunk size in voxels per axis (must be a multiple of 4). */\nconst CHUNK_INNER = 512;\n\nconst blockAlignedExtent = (halfExtent: number): number => {\n    return halfExtent === 0 ? 0 : Math.ceil(halfExtent / 4) * 4;\n};\n\n/**\n * Fast empty-chunk check. Scans only `types` (no mask reads) for the source\n * blocks that overlap the chunk's outer region; returns true if every block\n * is `BLOCK_EMPTY`. Lets `gpuDilate3` skip extract / dispatch / insert for\n * chunks far from the scene's occupied region.\n * @param src - Source sparse grid.\n * @param ox - Outer chunk origin X in voxels (may be negative when halo extends beyond grid).\n * @param oy - Outer chunk origin Y in voxels.\n * @param oz - Outer chunk origin Z in voxels.\n * @param cx - Outer chunk size X in voxels.\n * @param cy - Outer chunk size Y in voxels.\n * @param cz - Outer chunk size Z in voxels.\n * @returns `true` if every block overlapping the chunk is empty.\n */\nfunction chunkIsEmpty(\n    src: SparseVoxelGrid,\n    ox: number, oy: number, oz: number,\n    cx: number, cy: number, cz: number\n): boolean {\n    const minBx = Math.max(0, Math.floor(ox / 4));\n    const minBy = Math.max(0, Math.floor(oy / 4));\n    const minBz = Math.max(0, Math.floor(oz / 4));\n    const maxBx = Math.min(src.nbx, Math.ceil((ox + cx) / 4));\n    const maxBy = Math.min(src.nby, Math.ceil((oy + cy) / 4));\n    const maxBz = Math.min(src.nbz, Math.ceil((oz + cz) / 4));\n    if (maxBx <= minBx || maxBy <= minBy || maxBz <= minBz) return true;\n\n    const types = src.types;\n    for (let bz = minBz; bz < maxBz; bz++) {\n        for (let by = minBy; by < maxBy; by++) {\n            for (let bx = minBx; bx < maxBx; bx++) {\n                const blockIdx = bx + by * src.nbx + bz * src.bStride;\n                if (readBlockType(types, blockIdx) !== BLOCK_EMPTY) {\n                    return false;\n                }\n            }\n        }\n    }\n    return true;\n}\n\n/**\n * Fast saturated-chunk check. Returns true if the chunk's outer region is\n * entirely within `src` bounds AND every overlapping block is `BLOCK_SOLID`\n * (so extract would produce all 1s). Dilation of an all-solid input is\n * trivially all-solid, letting the caller skip GPU dispatch and write\n * `BLOCK_SOLID` directly into the destination's inner region.\n * @param src - Source sparse grid.\n * @param ox - Outer chunk origin X in voxels.\n * @param oy - Outer chunk origin Y in voxels.\n * @param oz - Outer chunk origin Z in voxels.\n * @param cx - Outer chunk size X in voxels.\n * @param cy - Outer chunk size Y in voxels.\n * @param cz - Outer chunk size Z in voxels.\n * @returns `true` if every block in the chunk is `BLOCK_SOLID` and the chunk lies within `src`.\n */\nfunction chunkIsSaturated(\n    src: SparseVoxelGrid,\n    ox: number, oy: number, oz: number,\n    cx: number, cy: number, cz: number\n): boolean {\n    // Halo extends past grid → those bits are 0, not saturated.\n    if (ox < 0 || oy < 0 || oz < 0) return false;\n    if (ox + cx > src.nx || oy + cy > src.ny || oz + cz > src.nz) return false;\n\n    const minBx = ox >> 2;\n    const minBy = oy >> 2;\n    const minBz = oz >> 2;\n    const maxBx = (ox + cx + 3) >> 2;\n    const maxBy = (oy + cy + 3) >> 2;\n    const maxBz = (oz + cz + 3) >> 2;\n\n    const types = src.types;\n    for (let bz = minBz; bz < maxBz; bz++) {\n        for (let by = minBy; by < maxBy; by++) {\n            for (let bx = minBx; bx < maxBx; bx++) {\n                const blockIdx = bx + by * src.nbx + bz * src.bStride;\n                if (readBlockType(types, blockIdx) !== BLOCK_SOLID) {\n                    return false;\n                }\n            }\n        }\n    }\n    return true;\n}\n\n/**\n * Insert a fully-solid inner region into `dst` without going through the\n * dense path. Used when the source chunk is saturated and dilation is\n * trivially saturated.\n *\n * For each X-row of inner blocks (varying `bx`, fixed `by, bz`), the\n * `dst.types` slots are contiguous; we set 2 bits per block to `BLOCK_SOLID`\n * via word-level writes (`SOLID_WORD = 0x55555555`) instead of millions of\n * `orBlock` calls. Chunks here are always disjoint and dst blocks empty\n * before this call, so no merge logic is needed.\n * @param dst - Destination sparse grid (mutated in place).\n * @param innerOx - Inner-region origin X in voxels.\n * @param innerOy - Inner-region origin Y in voxels.\n * @param innerOz - Inner-region origin Z in voxels.\n * @param innerCx - Inner-region size X in voxels.\n * @param innerCy - Inner-region size Y in voxels.\n * @param innerCz - Inner-region size Z in voxels.\n */\nfunction insertSaturatedInner(\n    dst: SparseVoxelGrid,\n    innerOx: number, innerOy: number, innerOz: number,\n    innerCx: number, innerCy: number, innerCz: number\n): void {\n    const minBx = Math.max(0, innerOx >> 2);\n    const minBy = Math.max(0, innerOy >> 2);\n    const minBz = Math.max(0, innerOz >> 2);\n    const maxBx = Math.min(dst.nbx, (innerOx + innerCx + 3) >> 2);\n    const maxBy = Math.min(dst.nby, (innerOy + innerCy + 3) >> 2);\n    const maxBz = Math.min(dst.nbz, (innerOz + innerCz + 3) >> 2);\n\n    const types = dst.types;\n    const nbx = dst.nbx;\n    const bStride = dst.bStride;\n\n    for (let bz = minBz; bz < maxBz; bz++) {\n        for (let by = minBy; by < maxBy; by++) {\n            const rowBase = by * nbx + bz * bStride;\n            const startIdx = rowBase + minBx;\n            const endIdx = rowBase + maxBx; // exclusive\n            let blockIdx = startIdx;\n            while (blockIdx < endIdx) {\n                const w = blockIdx >>> 4;\n                const shift = (blockIdx & 15) << 1;\n                const remainingInWord = 16 - (blockIdx & 15);\n                const remainingInRow = endIdx - blockIdx;\n                const blocksToWrite = remainingInWord < remainingInRow ? remainingInWord : remainingInRow;\n                if (blocksToWrite === 16) {\n                    types[w] = SOLID_WORD;\n                } else {\n                    const bits = blocksToWrite << 1;\n                    const mask = (((1 << bits) - 1) >>> 0) << shift;\n                    types[w] = ((types[w] & ~mask) | (SOLID_WORD & mask)) >>> 0;\n                }\n                blockIdx += blocksToWrite;\n            }\n        }\n    }\n}\n\n/**\n * Apply a chunk's GPU-produced output (`typesOut` + `masksOut`) to `dst`.\n * Iterates inner blocks; for each, reads the precomputed type and (if MIXED)\n * the precomputed `lo`/`hi`, then writes directly into `dst.types` and\n * `dst.masks`. Replaces the dense-bit-reading hot loop with O(blocks) work\n * dominated by hash inserts for mixed blocks.\n * @param dst - Destination sparse grid (mutated in place).\n * @param typesOut - GPU-produced packed 2-bit block types for the inner region.\n * @param masksOut - GPU-produced `[lo, hi]` mask pairs per inner block.\n * @param cx - Inner-region origin X in voxels.\n * @param cy - Inner-region origin Y in voxels.\n * @param cz - Inner-region origin Z in voxels.\n * @param innerNx - Inner-region size X in voxels.\n * @param innerNy - Inner-region size Y in voxels.\n * @param innerNz - Inner-region size Z in voxels.\n */\nfunction applyChunkToDst(\n    dst: SparseVoxelGrid,\n    typesOut: Uint32Array,\n    masksOut: Uint32Array,\n    cx: number, cy: number, cz: number,\n    innerNx: number, innerNy: number, innerNz: number\n): void {\n    const innerBx = innerNx >> 2;\n    const innerBy = innerNy >> 2;\n    const innerBz = innerNz >> 2;\n    const dstNbx = dst.nbx;\n    const dstBStride = dst.bStride;\n    const dstTypes = dst.types;\n    const dstMasks = dst.masks;\n\n    const baseBx = cx >> 2;\n    const baseBy = cy >> 2;\n    const baseBz = cz >> 2;\n\n    let innerIdx = 0;\n    for (let bz = 0; bz < innerBz; bz++) {\n        const globalBz = baseBz + bz;\n        for (let by = 0; by < innerBy; by++) {\n            const globalBy = baseBy + by;\n            const baseGlobalIdx = baseBx + globalBy * dstNbx + globalBz * dstBStride;\n            for (let bx = 0; bx < innerBx; bx++, innerIdx++) {\n                const wordIdx = innerIdx >>> 4;\n                const bitShift = (innerIdx & 15) << 1;\n                const bt = (typesOut[wordIdx] >>> bitShift) & 3;\n                if (bt === 0) continue;  // EMPTY\n\n                const globalBlockIdx = baseGlobalIdx + bx;\n                const w = globalBlockIdx >>> 4;\n                const shift = (globalBlockIdx & 15) << 1;\n                dstTypes[w] |= bt << shift;\n\n                if (bt === 2) {  // MIXED\n                    const m2 = innerIdx * 2;\n                    dstMasks.set(globalBlockIdx, masksOut[m2], masksOut[m2 + 1]);\n                }\n            }\n        }\n    }\n}\n\n/**\n * GPU separable 3D dilation. Chunks the grid into block-aligned inner regions plus\n * a halo on each side, runs three GPU passes per chunk, and OR's the\n * dilated inner region into a fresh destination `SparseVoxelGrid`.\n *\n * The exact requested half-extents are passed to the dilation shaders. The\n * sparse extraction halo is rounded up to the next 4-voxel block boundary so\n * chunk extract/compact math remains block-aligned without over-dilating.\n *\n * @param gpu - Reusable GPU dilation context (compiled shader + buffers).\n * @param src - Input sparse grid (read-only across the call).\n * @param halfExtentXZ - Dilation half-extent in voxels along X and Z.\n * @param halfExtentY - Dilation half-extent in voxels along Y.\n * @returns Newly allocated dilated sparse grid.\n */\nasync function gpuDilate3(\n    gpu: GpuDilation,\n    src: SparseVoxelGrid,\n    halfExtentXZ: number,\n    halfExtentY: number\n): Promise<SparseVoxelGrid> {\n    const dst = new SparseVoxelGrid(src.nx, src.ny, src.nz);\n\n    if (!Number.isInteger(halfExtentXZ) || halfExtentXZ < 0) {\n        throw new Error(`gpuDilate3: halfExtentXZ=${halfExtentXZ} must be a non-negative integer`);\n    }\n    if (!Number.isInteger(halfExtentY) || halfExtentY < 0) {\n        throw new Error(`gpuDilate3: halfExtentY=${halfExtentY} must be a non-negative integer`);\n    }\n\n    const haloX = blockAlignedExtent(halfExtentXZ);\n    const haloY = blockAlignedExtent(halfExtentY);\n    const haloZ = haloX;\n    const haloBx = haloX / 4;\n    const haloBy = haloY / 4;\n    const haloBz = haloZ / 4;\n\n    // Round inner chunk down to multiple of 4 (block alignment).\n    const innerStep = CHUNK_INNER & ~3;\n\n    const numChunksX = Math.ceil(src.nx / innerStep);\n    const numChunksY = Math.ceil(src.ny / innerStep);\n    const numChunksZ = Math.ceil(src.nz / innerStep);\n    const totalChunks = numChunksX * numChunksY * numChunksZ;\n\n    interface InFlight {\n        typesPromise: Promise<Uint32Array>;\n        masksPromise: Promise<Uint32Array>;\n        cx: number; cy: number; cz: number;\n        innerNx: number; innerNy: number; innerNz: number;\n    }\n\n    let currentSlot = 0;\n    let inflight: InFlight | null = null;\n\n    const drainInflight = async (): Promise<void> => {\n        if (!inflight) return;\n        const f = inflight;\n        inflight = null;\n        const [typesOut, masksOut] = await Promise.all([f.typesPromise, f.masksPromise]);\n        applyChunkToDst(dst, typesOut, masksOut, f.cx, f.cy, f.cz, f.innerNx, f.innerNy, f.innerNz);\n    };\n\n    gpu.uploadSrc(src);\n\n    const bar = logger.bar('Dilating', totalChunks);\n    try {\n        for (let cz = 0; cz < src.nz; cz += innerStep) {\n            for (let cy = 0; cy < src.ny; cy += innerStep) {\n                for (let cx = 0; cx < src.nx; cx += innerStep) {\n                    const innerNx = Math.min(innerStep, src.nx - cx);\n                    const innerNy = Math.min(innerStep, src.ny - cy);\n                    const innerNz = Math.min(innerStep, src.nz - cz);\n\n                    const ox = cx - haloX;\n                    const oy = cy - haloY;\n                    const oz = cz - haloZ;\n                    const outerNx = innerNx + 2 * haloX;\n                    const outerNy = innerNy + 2 * haloY;\n                    const outerNz = innerNz + 2 * haloZ;\n\n                    if (chunkIsEmpty(src, ox, oy, oz, outerNx, outerNy, outerNz)) {\n                        bar.tick();\n                        continue;\n                    }\n                    if (chunkIsSaturated(src, ox, oy, oz, outerNx, outerNy, outerNz)) {\n                        insertSaturatedInner(dst, cx, cy, cz, innerNx, innerNy, innerNz);\n                        bar.tick();\n                        continue;\n                    }\n\n                    const innerBx = innerNx >> 2;\n                    const innerBy = innerNy >> 2;\n                    const innerBz = innerNz >> 2;\n                    const outerBx = outerNx >> 2;\n                    const outerBy = outerNy >> 2;\n                    const outerBz = outerNz >> 2;\n                    const minBx = Math.floor(ox / 4);\n                    const minBy = Math.floor(oy / 4);\n                    const minBz = Math.floor(oz / 4);\n\n                    const { types: typesPromise, masks: masksPromise } = gpu.submitChunkSparse(\n                        currentSlot,\n                        minBx, minBy, minBz,\n                        outerBx, outerBy, outerBz,\n                        haloBx, haloBy, haloBz,\n                        innerBx, innerBy, innerBz,\n                        halfExtentXZ, halfExtentY\n                    );\n\n                    if (inflight) {\n                        await drainInflight();\n                    }\n\n                    inflight = {\n                        typesPromise,\n                        masksPromise,\n                        cx,\n                        cy,\n                        cz,\n                        innerNx,\n                        innerNy,\n                        innerNz\n                    };\n                    currentSlot = (currentSlot + 1) % GpuDilation.NUM_SLOTS;\n\n                    bar.tick();\n                }\n            }\n        }\n\n        if (inflight) {\n            await drainInflight();\n        }\n    } finally {\n        bar.end();\n        gpu.releaseSrc();\n    }\n    return dst;\n}\n\nexport { gpuDilate3 };\n","import {\n    BLOCK_EMPTY,\n    BLOCK_SOLID,\n    BLOCKS_PER_WORD,\n    EVEN_BITS,\n    SOLID_HI,\n    SOLID_LO,\n    SparseVoxelGrid,\n    TYPE_MASK,\n    readBlockType\n} from './sparse-voxel-grid';\n\n/**\n * Compute the grid of voxels that are visited but not blocked\n * (i.e. reachable empty voxels).\n *\n * @param visited - Grid of visited voxels (from BFS).\n * @param blocked - Grid of blocked voxels (obstacles).\n * @returns Grid containing only voxels that are visited AND not blocked.\n */\nfunction computeEmptyGrid(visited: SparseVoxelGrid, blocked: SparseVoxelGrid): SparseVoxelGrid {\n    const empty = new SparseVoxelGrid(visited.nx, visited.ny, visited.nz);\n    const totalBlocks = visited.nbx * visited.nby * visited.nbz;\n    const visitedTypes = visited.types;\n    const blockedTypes = blocked.types;\n    for (let w = 0; w < visitedTypes.length; w++) {\n        const word = visitedTypes[w];\n        if (word === 0) continue;\n        let nonEmpty = ((word & EVEN_BITS) | ((word >>> 1) & EVEN_BITS)) >>> 0;\n        const baseIdx = w * BLOCKS_PER_WORD;\n        while (nonEmpty) {\n            const bp = 31 - Math.clz32(nonEmpty & -nonEmpty);\n            const lane = bp >>> 1;\n            const blockIdx = baseIdx + lane;\n            if (blockIdx >= totalBlocks) {\n                nonEmpty = 0;\n                break;\n            }\n            const vbt = (word >>> (lane << 1)) & TYPE_MASK;\n            let vLo: number, vHi: number;\n            if (vbt === BLOCK_SOLID) {\n                vLo = SOLID_LO;\n                vHi = SOLID_HI;\n            } else {\n                const vs = visited.masks.slot(blockIdx);\n                vLo = visited.masks.lo[vs];\n                vHi = visited.masks.hi[vs];\n            }\n            const bbt = readBlockType(blockedTypes, blockIdx);\n            let lo: number, hi: number;\n            if (bbt === BLOCK_EMPTY) {\n                lo = vLo;\n                hi = vHi;\n            } else if (bbt === BLOCK_SOLID) {\n                lo = 0;\n                hi = 0;\n            } else {\n                const bs = blocked.masks.slot(blockIdx);\n                lo = (vLo & ~blocked.masks.lo[bs]) >>> 0;\n                hi = (vHi & ~blocked.masks.hi[bs]) >>> 0;\n            }\n            if (lo || hi) {\n                empty.orBlock(blockIdx, lo, hi);\n            }\n            nonEmpty &= nonEmpty - 1;\n        }\n    }\n    return empty;\n}\n\n/**\n * Compute the union of two sparse voxel grids (bitwise OR).\n *\n * @param a - First grid. By default a fresh clone is taken as the base;\n * with `consumeA=true` it is mutated in place and returned, saving one\n * full grid's worth of clone allocation.\n * @param b - Second grid (OR'd into the result).\n * @param consumeA - If true, `a` is mutated in place and returned. The\n * caller must not subsequently read `a` as an independent value\n * (the returned grid IS `a`).\n * @param onProgress - Optional progress callback over `b.types` words.\n * @returns Grid containing the union of both inputs. Equal to `a` when\n * `consumeA=true`, otherwise a freshly cloned grid.\n */\nfunction sparseOrGrids(\n    a: SparseVoxelGrid,\n    b: SparseVoxelGrid,\n    consumeA: boolean = false,\n    onProgress?: (done: number, total: number) => void\n): SparseVoxelGrid {\n    const result = consumeA ? a : a.clone();\n    const totalBlocks = b.nbx * b.nby * b.nbz;\n    const bTypes = b.types;\n    const PROGRESS_INTERVAL = 1 << 13;\n    let nextTick = PROGRESS_INTERVAL;\n    for (let w = 0; w < bTypes.length; w++) {\n        if (onProgress && w >= nextTick) {\n            onProgress(w, bTypes.length);\n            nextTick = w + PROGRESS_INTERVAL;\n        }\n        const word = bTypes[w];\n        if (word === 0) continue;\n        let nonEmpty = ((word & EVEN_BITS) | ((word >>> 1) & EVEN_BITS)) >>> 0;\n        const baseIdx = w * BLOCKS_PER_WORD;\n        while (nonEmpty) {\n            const bp = 31 - Math.clz32(nonEmpty & -nonEmpty);\n            const lane = bp >>> 1;\n            const blockIdx = baseIdx + lane;\n            if (blockIdx >= totalBlocks) {\n                nonEmpty = 0;\n                break;\n            }\n            const bt = (word >>> (lane << 1)) & TYPE_MASK;\n            if (bt === BLOCK_SOLID) {\n                result.orBlock(blockIdx, SOLID_LO, SOLID_HI);\n            } else {\n                const s = b.masks.slot(blockIdx);\n                result.orBlock(blockIdx, b.masks.lo[s], b.masks.hi[s]);\n            }\n            nonEmpty &= nonEmpty - 1;\n        }\n    }\n    if (onProgress) onProgress(bTypes.length, bTypes.length);\n    return result;\n}\n\nexport { computeEmptyGrid, sparseOrGrids };\n","import { Vec3 } from 'playcanvas';\n\nimport { gpuDilate3 } from './dilation';\nimport type { NavSeed, NavSimplifyResult } from './fill-exterior';\nimport { twoLevelBFS } from './flood-fill';\nimport { computeEmptyGrid } from './grid-ops';\nimport type { Bounds } from '../data-table';\nimport type { GpuDilation } from '../gpu';\nimport {\n    BLOCK_EMPTY,\n    SparseVoxelGrid\n} from './sparse-voxel-grid';\nimport { logger } from '../utils';\n\nconst carve = async (\n    gridA: SparseVoxelGrid,\n    gridBounds: Bounds,\n    voxelResolution: number,\n    capsuleHeight: number,\n    capsuleRadius: number,\n    seed: NavSeed,\n    gpu: GpuDilation\n): Promise<NavSimplifyResult> => {\n    if (!Number.isFinite(voxelResolution) || voxelResolution <= 0) {\n        throw new Error(`carve: voxelResolution must be finite and > 0, got ${voxelResolution}`);\n    }\n    if (!Number.isFinite(capsuleHeight) || capsuleHeight <= 0) {\n        throw new Error(`carve: capsuleHeight must be finite and > 0, got ${capsuleHeight}`);\n    }\n    if (!Number.isFinite(capsuleRadius) || capsuleRadius < 0) {\n        throw new Error(`carve: capsuleRadius must be finite and >= 0, got ${capsuleRadius}`);\n    }\n\n    const { nx, ny, nz, nbx, nby, nbz } = gridA;\n\n    if (nx % 4 !== 0 || ny % 4 !== 0 || nz % 4 !== 0) {\n        throw new Error(`Grid dimensions must be multiples of 4, got ${nx}x${ny}x${nz}`);\n    }\n\n    const kernelR = Math.ceil(capsuleRadius / voxelResolution);\n    const yHalfExtent = Math.ceil(capsuleHeight / (2 * voxelResolution));\n\n    let seedIx = Math.floor((seed.x - gridBounds.min.x) / voxelResolution);\n    let seedIy = Math.floor((seed.y - gridBounds.min.y) / voxelResolution);\n    let seedIz = Math.floor((seed.z - gridBounds.min.z) / voxelResolution);\n\n    if (seedIx < 0 || seedIx >= nx || seedIy < 0 || seedIy >= ny || seedIz < 0 || seedIz >= nz) {\n        logger.warn(`seed (${seed.x}, ${seed.y}, ${seed.z}) outside grid, skipping carve`);\n        return { grid: gridA, gridBounds };\n    }\n\n    const blocked = await gpuDilate3(gpu, gridA, kernelR, yHalfExtent);\n\n    if (blocked.getVoxel(seedIx, seedIy, seedIz)) {\n        const maxRadius = Math.max(kernelR, yHalfExtent) * 2;\n        const found = SparseVoxelGrid.findNearestFreeCell(blocked, seedIx, seedIy, seedIz, maxRadius);\n        if (!found) {\n            logger.warn(`seed (${seed.x}, ${seed.y}, ${seed.z}) blocked after dilation, no free cell within ${maxRadius} voxels, skipping carve`);\n            return { grid: gridA, gridBounds };\n        }\n        seedIx = found.ix;\n        seedIy = found.iy;\n        seedIz = found.iz;\n    }\n\n    const seedBlockIdx = (seedIx >> 2) + (seedIy >> 2) * nbx + (seedIz >> 2) * (nbx * nby);\n    const seedBt = blocked.getBlockType(seedBlockIdx);\n    const bSeeds = seedBt === BLOCK_EMPTY ? [seedBlockIdx] : [];\n    const vSeeds = seedBt === BLOCK_EMPTY ? [] : [{ ix: seedIx, iy: seedIy, iz: seedIz }];\n\n    // Approximate total: nbx*nby*nbz is an upper bound on whole-block fills,\n    // so the bar usually finishes shy of 100% (mixed/solid blocks aren't\n    // counted). Good enough for visual feedback on a long BFS.\n    const bfsBar = logger.bar('BFS', nbx * nby * nbz);\n    const visited = twoLevelBFS(\n        blocked, bSeeds, vSeeds, nx, ny, nz,\n        count => bfsBar.update(count)\n    );\n    bfsBar.end();\n\n    const emptyGrid = computeEmptyGrid(visited, blocked);\n\n    const navRegion = await gpuDilate3(gpu, emptyGrid, kernelR, yHalfExtent);\n\n    const boundsBar = logger.bar('Scanning bounds', navRegion.types.length);\n    const navBounds = navRegion.getOccupiedBlockBounds(done => boundsBar.update(done));\n    boundsBar.end();\n\n    if (!navBounds) {\n        logger.warn('no navigable cells remain after carve, returning empty result');\n        return {\n            grid: new SparseVoxelGrid(0, 0, 0),\n            gridBounds: { min: gridBounds.min.clone(), max: gridBounds.min.clone() }\n        };\n    }\n\n    const MARGIN = 1;\n    const cropMinBx = Math.max(0, navBounds.minBx - MARGIN);\n    const cropMinBy = Math.max(0, navBounds.minBy - MARGIN);\n    const cropMinBz = Math.max(0, navBounds.minBz - MARGIN);\n    const cropMaxBx = Math.min(nbx, navBounds.maxBx + 1 + MARGIN);\n    const cropMaxBy = Math.min(nby, navBounds.maxBy + 1 + MARGIN);\n    const cropMaxBz = Math.min(nbz, navBounds.maxBz + 1 + MARGIN);\n\n    const blockSize = 4 * voxelResolution;\n    const croppedMin = new Vec3(\n        gridBounds.min.x + cropMinBx * blockSize,\n        gridBounds.min.y + cropMinBy * blockSize,\n        gridBounds.min.z + cropMinBz * blockSize\n    );\n    const croppedBounds: Bounds = {\n        min: croppedMin,\n        max: new Vec3(\n            croppedMin.x + (cropMaxBx - cropMinBx) * blockSize,\n            croppedMin.y + (cropMaxBy - cropMinBy) * blockSize,\n            croppedMin.z + (cropMaxBz - cropMinBz) * blockSize\n        )\n    };\n\n    const buildBar = logger.bar('Building grid', navRegion.types.length);\n    const outGrid = navRegion.cropToInverted(\n        cropMinBx, cropMinBy, cropMinBz,\n        cropMaxBx, cropMaxBy, cropMaxBz,\n        done => buildBar.update(done)\n    );\n    buildBar.end();\n\n    return {\n        grid: outGrid,\n        gridBounds: croppedBounds\n    };\n};\n\nexport { carve };\n","import { Vec3 } from 'playcanvas';\n\nimport { gpuDilate3 } from './dilation';\nimport { twoLevelBFS } from './flood-fill';\nimport { sparseOrGrids } from './grid-ops';\nimport type { Bounds } from '../data-table';\nimport type { GpuDilation } from '../gpu';\nimport {\n    BLOCK_MIXED,\n    BLOCK_SOLID,\n    FACE_MASKS_HI,\n    FACE_MASKS_LO,\n    SOLID_HI,\n    SOLID_LO,\n    SparseVoxelGrid\n} from './sparse-voxel-grid';\nimport { logger } from '../utils';\n\ntype NavSeed = {\n    x: number;\n    y: number;\n    z: number;\n};\n\ntype NavSimplifyResult = {\n    grid: SparseVoxelGrid;\n    gridBounds: Bounds;\n};\n\nconst fillExterior = async (\n    gridOriginal: SparseVoxelGrid,\n    gridBounds: Bounds,\n    voxelResolution: number,\n    dilation: number,\n    seed: NavSeed,\n    gpu: GpuDilation\n): Promise<NavSimplifyResult> => {\n    if (!Number.isFinite(voxelResolution) || voxelResolution <= 0) {\n        throw new Error(`fillExterior: voxelResolution must be finite and > 0, got ${voxelResolution}`);\n    }\n    if (!Number.isFinite(dilation) || dilation <= 0) {\n        throw new Error(`fillExterior: dilation must be finite and > 0, got ${dilation}`);\n    }\n\n    const { nx, ny, nz, nbx, nby, nbz, bStride } = gridOriginal;\n\n    if (nx % 4 !== 0 || ny % 4 !== 0 || nz % 4 !== 0) {\n        throw new Error(`Grid dimensions must be multiples of 4, got ${nx}x${ny}x${nz}`);\n    }\n\n    const halfExtent = Math.ceil(dilation / voxelResolution);\n\n    const dilated = await gpuDilate3(gpu, gridOriginal, halfExtent, halfExtent);\n\n    const blockSeeds: number[] = [];\n    const faceVoxelSeeds: { ix: number; iy: number; iz: number }[] = [];\n\n    const seedBoundaryBlock = (blockIdx: number, bx: number, by: number, bz: number, face: number): void => {\n        const bt = dilated.getBlockType(blockIdx);\n        if (bt === BLOCK_SOLID) return;\n        if (bt === BLOCK_MIXED) {\n            const ms = dilated.masks.slot(blockIdx);\n            const faceLo = FACE_MASKS_LO[face];\n            const faceHi = FACE_MASKS_HI[face];\n            let freeLo = (faceLo & ~dilated.masks.lo[ms]) >>> 0;\n            let freeHi = (faceHi & ~dilated.masks.hi[ms]) >>> 0;\n            if (freeLo === 0 && freeHi === 0) return;\n            const baseIx = bx << 2;\n            const baseIy = by << 2;\n            const baseIz = bz << 2;\n            while (freeLo) {\n                const bp = 31 - Math.clz32(freeLo & -freeLo);\n                faceVoxelSeeds.push({ ix: baseIx + (bp & 3), iy: baseIy + ((bp >> 2) & 3), iz: baseIz + (bp >> 4) });\n                freeLo &= freeLo - 1;\n            }\n            while (freeHi) {\n                const bp = 31 - Math.clz32(freeHi & -freeHi);\n                const bi = bp + 32;\n                faceVoxelSeeds.push({ ix: baseIx + (bi & 3), iy: baseIy + ((bi >> 2) & 3), iz: baseIz + (bi >> 4) });\n                freeHi &= freeHi - 1;\n            }\n            return;\n        }\n        blockSeeds.push(blockIdx);\n    };\n\n    for (let bz = 0; bz < nbz; bz++) {\n        for (let by = 0; by < nby; by++) {\n            seedBoundaryBlock(by * nbx + bz * bStride, 0, by, bz, 0);\n        }\n    }\n\n    for (let bz = 0; bz < nbz; bz++) {\n        for (let by = 0; by < nby; by++) {\n            seedBoundaryBlock((nbx - 1) + by * nbx + bz * bStride, nbx - 1, by, bz, 1);\n        }\n    }\n\n    for (let bz = 0; bz < nbz; bz++) {\n        for (let bx = 0; bx < nbx; bx++) {\n            seedBoundaryBlock(bx + bz * bStride, bx, 0, bz, 2);\n        }\n    }\n\n    for (let bz = 0; bz < nbz; bz++) {\n        for (let bx = 0; bx < nbx; bx++) {\n            seedBoundaryBlock(bx + (nby - 1) * nbx + bz * bStride, bx, nby - 1, bz, 3);\n        }\n    }\n\n    for (let by = 0; by < nby; by++) {\n        for (let bx = 0; bx < nbx; bx++) {\n            seedBoundaryBlock(bx + by * nbx, bx, by, 0, 4);\n        }\n    }\n\n    for (let by = 0; by < nby; by++) {\n        for (let bx = 0; bx < nbx; bx++) {\n            seedBoundaryBlock(bx + by * nbx + (nbz - 1) * bStride, bx, by, nbz - 1, 5);\n        }\n    }\n\n    const visited = twoLevelBFS(dilated, blockSeeds, faceVoxelSeeds, nx, ny, nz);\n\n    const seedIx = Math.floor((seed.x - gridBounds.min.x) / voxelResolution);\n    const seedIy = Math.floor((seed.y - gridBounds.min.y) / voxelResolution);\n    const seedIz = Math.floor((seed.z - gridBounds.min.z) / voxelResolution);\n\n    if (seedIx >= 0 && seedIx < nx && seedIy >= 0 && seedIy < ny && seedIz >= 0 && seedIz < nz) {\n        if (visited.getVoxel(seedIx, seedIy, seedIz)) {\n            logger.info('seed reachable from outside, skipping exterior fill');\n            return { grid: gridOriginal, gridBounds };\n        }\n    } else {\n        logger.info('seed outside grid bounds, skipping exterior fill');\n        return { grid: gridOriginal, gridBounds };\n    }\n\n    const dilatedVisited = await gpuDilate3(gpu, visited, halfExtent, halfExtent);\n\n    const combined = sparseOrGrids(gridOriginal, dilatedVisited);\n\n    let minIx = nx, minIy = ny, minIz = nz;\n    let maxIx = 0, maxIy = 0, maxIz = 0;\n\n    for (let bz = 0; bz < nbz; bz++) {\n        for (let by = 0; by < nby; by++) {\n            for (let bx = 0; bx < nbx; bx++) {\n                const blockIdx = bx + by * nbx + bz * combined.bStride;\n                const bt = combined.getBlockType(blockIdx);\n                if (bt === BLOCK_SOLID) continue;\n                if (bt === BLOCK_MIXED) {\n                    const cs = combined.masks.slot(blockIdx);\n                    if (combined.masks.lo[cs] === SOLID_LO && combined.masks.hi[cs] === SOLID_HI) continue;\n                }\n                const baseX = bx << 2;\n                const baseY = by << 2;\n                const baseZ = bz << 2;\n                if (baseX < minIx) minIx = baseX;\n                if (baseX + 3 > maxIx) maxIx = baseX + 3;\n                if (baseY < minIy) minIy = baseY;\n                if (baseY + 3 > maxIy) maxIy = baseY + 3;\n                if (baseZ < minIz) minIz = baseZ;\n                if (baseZ + 3 > maxIz) maxIz = baseZ + 3;\n            }\n        }\n    }\n\n    if (minIx > maxIx) {\n        logger.warn('no navigable cells remain, returning empty result');\n        return {\n            grid: new SparseVoxelGrid(0, 0, 0),\n            gridBounds: { min: gridBounds.min.clone(), max: gridBounds.min.clone() }\n        };\n    }\n\n    const MARGIN = 1;\n    const cropMinBx = Math.max(0, (minIx >> 2) - MARGIN);\n    const cropMinBy = Math.max(0, (minIy >> 2) - MARGIN);\n    const cropMinBz = Math.max(0, (minIz >> 2) - MARGIN);\n    const cropMaxBx = Math.min(nbx, (maxIx >> 2) + 1 + MARGIN);\n    const cropMaxBy = Math.min(nby, (maxIy >> 2) + 1 + MARGIN);\n    const cropMaxBz = Math.min(nbz, (maxIz >> 2) + 1 + MARGIN);\n\n    const blockSize = 4 * voxelResolution;\n    const croppedMin = new Vec3(\n        gridBounds.min.x + cropMinBx * blockSize,\n        gridBounds.min.y + cropMinBy * blockSize,\n        gridBounds.min.z + cropMinBz * blockSize\n    );\n    const croppedBounds: Bounds = {\n        min: croppedMin,\n        max: new Vec3(\n            croppedMin.x + (cropMaxBx - cropMinBx) * blockSize,\n            croppedMin.y + (cropMaxBy - cropMinBy) * blockSize,\n            croppedMin.z + (cropMaxBz - cropMinBz) * blockSize\n        )\n    };\n\n    return {\n        grid: combined.cropTo(\n            cropMinBx, cropMinBy, cropMinBz,\n            cropMaxBx, cropMaxBy, cropMaxBz\n        ),\n        gridBounds: croppedBounds\n    };\n};\n\nexport { fillExterior };\nexport type { NavSeed, NavSimplifyResult };\n","import { gpuDilate3 } from './dilation';\nimport type { NavSimplifyResult } from './fill-exterior';\nimport { sparseOrGrids } from './grid-ops';\nimport type { Bounds } from '../data-table';\nimport type { GpuDilation } from '../gpu';\nimport {\n    BLOCK_EMPTY,\n    BLOCK_SOLID,\n    SOLID_HI,\n    SOLID_LO,\n    SparseVoxelGrid,\n    readBlockType\n} from './sparse-voxel-grid';\nimport { logger } from '../utils';\n\n/**\n * Floor-fill via XZ dilate -> per-column upward walk -> XZ dilate -> OR.\n *\n * Mirrors the shape of `fillExterior` (dilate -> traverse -> dilate -> OR) but\n * the traversal is a per-(lx, lz) upward walk through empty space instead of a\n * 3D boundary BFS, and the dilations operate only in X and Z.\n *\n * Steps with `r = ceil(dilation / voxelResolution)`:\n *   1. `S_xz = gpuDilate3(S, r, 0)` closes any XZ holes in horizontal\n *      surfaces smaller than `2 * r`.\n *   2. For every (lx, lz), walk `y = 0` upward through `S_xz`. Mark each\n *      visited empty voxel into `foundEmpty`. Stop on the first solid voxel\n *      of `S_xz` or at the grid top.\n *   3. `dilatedFound = gpuDilate3(foundEmpty, r, 0)` spreads the found\n *      under-surface volume back out in XZ to cover the kernel halo.\n *   4. `output = S | dilatedFound` adds the dilated under-surface region as\n *      solid on top of the original solids.\n *\n * Intended to run before `carve`: it seals the under-side of the floor\n * (and patches small XZ holes via the dilation), and the carve handles the\n * remaining hole plugging via its 3D dilate + capsule BFS.\n *\n * With `r = 0` the dilations are skipped and the algorithm degrades to\n * \"fill the under-side of every column up to the first solid\", matching the\n * original (pre-dilation) `fillFloor` behavior.\n *\n * @param grid - Voxel grid (linear-keyed) — mutated as the under-surface\n * region is OR'd into it. The same grid instance is returned in\n * `NavSimplifyResult.grid`.\n * @param gridBounds - Axis-aligned bounds of the voxel grid.\n * @param voxelResolution - Size of each voxel in world units.\n * @param dilation - XZ dilation radius in world units. 0 disables dilation.\n * @param gpu - Reusable GPU dilation context. Required when dilation > 0.\n * @returns Modified grid with under-surface regions filled.\n */\nconst fillFloor = async (\n    grid: SparseVoxelGrid,\n    gridBounds: Bounds,\n    voxelResolution: number,\n    dilation: number = 0,\n    gpu: GpuDilation | null = null\n): Promise<NavSimplifyResult> => {\n    if (!Number.isFinite(voxelResolution) || voxelResolution <= 0) {\n        throw new Error(`fillFloor: voxelResolution must be finite and > 0, got ${voxelResolution}`);\n    }\n    if (!Number.isFinite(dilation) || dilation < 0) {\n        throw new Error(`fillFloor: dilation must be finite and >= 0, got ${dilation}`);\n    }\n\n    const { nx, ny, nz, nbx, nby, nbz, bStride } = grid;\n\n    if (nx % 4 !== 0 || ny % 4 !== 0 || nz % 4 !== 0) {\n        throw new Error(`Grid dimensions must be multiples of 4, got ${nx}x${ny}x${nz}`);\n    }\n\n    const r = dilation > 0 ? Math.ceil(dilation / voxelResolution) : 0;\n    if (r > 0 && !gpu) {\n        throw new Error('fillFloor: gpu dilation context is required when dilation > 0');\n    }\n\n    logger.debug(`fill floor: ${nx}x${ny}x${nz} grid, dilation radius ${r} voxels`);\n\n    const dilatedSolid = r > 0 ? await gpuDilate3(gpu!, grid, r, 0) : grid;\n\n    const foundEmpty = new SparseVoxelGrid(nx, ny, nz);\n\n    const walkBar = logger.bar('Column walk', nbx * nbz);\n    const dilatedTypes = dilatedSolid.types;\n    for (let bz = 0; bz < nbz; bz++) {\n        for (let bx = 0; bx < nbx; bx++) {\n            let walking = 0xFFFF;\n\n            for (let by = 0; by < nby && walking; by++) {\n                const blockIdx = bx + by * nbx + bz * bStride;\n                const bt = readBlockType(dilatedTypes, blockIdx);\n\n                if (bt === BLOCK_SOLID) {\n                    break;\n                }\n\n                if (bt === BLOCK_EMPTY) {\n                    if (walking === 0xFFFF) {\n                        foundEmpty.orBlock(blockIdx, SOLID_LO, SOLID_HI);\n                    } else {\n                        let lo = 0, hi = 0;\n                        for (let lz = 0; lz < 4; lz++) {\n                            for (let lx = 0; lx < 4; lx++) {\n                                if (!(walking & (1 << (lz * 4 + lx)))) continue;\n                                for (let ly = 0; ly < 4; ly++) {\n                                    const bitIdx = lx + (ly << 2) + (lz << 4);\n                                    if (bitIdx < 32) lo |= (1 << bitIdx);\n                                    else hi |= (1 << (bitIdx - 32));\n                                }\n                            }\n                        }\n                        foundEmpty.orBlock(blockIdx, lo >>> 0, hi >>> 0);\n                    }\n                    continue;\n                }\n\n                // BLOCK_MIXED: per-voxel walk\n                const s = dilatedSolid.masks.slot(blockIdx);\n                const dLo = dilatedSolid.masks.lo[s];\n                const dHi = dilatedSolid.masks.hi[s];\n\n                let foundLo = 0;\n                let foundHi = 0;\n\n                for (let lz = 0; lz < 4; lz++) {\n                    for (let lx = 0; lx < 4; lx++) {\n                        const subCol = 1 << (lz * 4 + lx);\n                        if (!(walking & subCol)) continue;\n\n                        for (let ly = 0; ly < 4; ly++) {\n                            const bitIdx = lx + (ly << 2) + (lz << 4);\n                            const inHi = bitIdx >= 32;\n                            const word = inHi ? dHi : dLo;\n                            const bit = 1 << (inHi ? bitIdx - 32 : bitIdx);\n\n                            if (word & bit) {\n                                walking &= ~subCol;\n                                break;\n                            }\n\n                            if (inHi) foundHi |= bit;\n                            else foundLo |= bit;\n                        }\n                    }\n                }\n\n                if (foundLo || foundHi) {\n                    foundEmpty.orBlock(blockIdx, foundLo >>> 0, foundHi >>> 0);\n                }\n            }\n            walkBar.tick();\n        }\n    }\n    walkBar.end();\n\n    if (r > 0) dilatedSolid.clear();\n\n    const dilatedFound = r > 0 ? await gpuDilate3(gpu!, foundEmpty, r, 0) : foundEmpty;\n\n    // grid is the original voxelization; not read after this OR. Pass\n    // consumeA=true so sparseOrGrids mutates it in place rather than\n    // cloning — saves a full SparseVoxelGrid clone right at the end of\n    // the fill-floor phase.\n    const combineBar = logger.bar('Combining', grid.types.length);\n    const combined = sparseOrGrids(grid, dilatedFound, true, done => combineBar.update(done));\n    combineBar.end();\n\n    return { grid: combined, gridBounds };\n};\n\nexport { fillFloor };\n","import { basename } from 'pathe';\nimport { Vec3 } from 'playcanvas';\n\nimport { buildCollisionMesh } from './collision-glb';\nimport { logWrittenFile } from './utils';\nimport { Column, DataTable, computeGaussianExtents, computeWriteTransform, transformColumns, type Bounds } from '../data-table';\nimport { GpuDilation, GpuVoxelization } from '../gpu';\nimport { type FileSystem, writeFile } from '../io/write';\nimport { GaussianBVH } from '../spatial';\nimport type { CollisionMeshShape, DeviceCreator } from '../types';\nimport { fmtCount, logger, Transform } from '../utils';\nimport { buildSparseOctree, type SparseOctree } from './sparse-octree';\nimport {\n    filterAndFillBlocks,\n    alignGridBounds,\n    carve,\n    fillExterior,\n    fillFloor,\n    type NavSeed,\n    voxelizeToBuffer\n} from '../voxel';\nimport { SparseVoxelGrid } from '../voxel/sparse-voxel-grid';\n\n/**\n * Options for writing a voxel octree file.\n */\ntype WriteVoxelOptions = {\n    /** Output filename ending in .voxel.json */\n    filename: string;\n\n    /** Gaussian splat data to voxelize */\n    dataTable: DataTable;\n\n    /** Size of each voxel in world units. Default: 0.05 */\n    voxelResolution?: number;\n\n    /** Opacity threshold for solid voxels - voxels below this are considered empty. Default: 0.1 */\n    opacityCutoff?: number;\n\n    /** Optional function to create a GPU device for voxelization */\n    createDevice?: DeviceCreator;\n\n    /** Exterior fill radius in world units. Enables exterior fill when set. Requires navSeed; ignored without it. */\n    navExteriorRadius?: number;\n\n    /** Capsule dimensions for carve. Height of 0 disables carve. When height > 0, only voxels contactable from the seed are kept. Requires navSeed. */\n    navCapsule?: { height: number; radius: number };\n\n    /** Seed position in world space for exterior fill and carve flood fill. */\n    navSeed?: NavSeed;\n\n    /** Fill each voxel column upward from the bottom until hitting solid. Runs before carve so the carve's BFS is confined to the actual navigable bubble. Default: false */\n    floorFill?: boolean;\n\n    /** When `floorFill` is enabled, dilation radius in world units used to identify \"interior\" XZ columns to patch. Empty XZ areas larger than `2 * floorFillDilation` from any solid column are treated as exterior and left empty. Default: 0 (patch every empty column). */\n    floorFillDilation?: number;\n\n    /** When set, a collision mesh (.collision.glb) is generated alongside the voxel output. `true` is equivalent to `smooth`. */\n    collisionMesh?: boolean | CollisionMeshShape;\n};\n\n/**\n * Metadata for a voxel octree file.\n */\ninterface VoxelMetadata {\n    /** File format version */\n    version: string;\n\n    /** Grid bounds aligned to 4x4x4 block boundaries */\n    gridBounds: { min: number[]; max: number[] };\n\n    /** Scene bounds (in PlayCanvas coordinate space for v1.1+) */\n    sceneBounds: { min: number[]; max: number[] };\n\n    /** Size of each voxel in world units */\n    voxelResolution: number;\n\n    /** Voxels per leaf dimension (always 4) */\n    leafSize: number;\n\n    /** Maximum tree depth */\n    treeDepth: number;\n\n    /** Number of interior nodes */\n    numInteriorNodes: number;\n\n    /** Number of mixed leaf nodes */\n    numMixedLeaves: number;\n\n    /** Total number of Uint32 entries in the nodes array */\n    nodeCount: number;\n\n    /** Total number of Uint32 entries in the leafData array */\n    leafDataCount: number;\n}\n\n/**\n * Crop a voxel grid and its grid bounds to the occupied block range.\n * Removes empty padding that arises from Gaussian 3-sigma extents being\n * much larger than the actual solid voxel footprint.\n *\n * @param grid - Voxelized scene data.\n * @param gridBounds - Axis-aligned bounds of the voxel grid.\n * @param voxelResolution - Size of each voxel in world units.\n * @returns Cropped grid and grid bounds.\n */\nconst cropToOccupied = (\n    grid: SparseVoxelGrid,\n    gridBounds: Bounds,\n    voxelResolution: number\n): { grid: SparseVoxelGrid; gridBounds: Bounds } => {\n    const { nbx, nby, nbz } = grid;\n\n    const boundsBar = logger.bar('Scanning bounds', grid.types.length);\n    const occupiedBounds = grid.getOccupiedBlockBounds(done => boundsBar.update(done));\n    boundsBar.end();\n\n    if (!occupiedBounds) {\n        return { grid, gridBounds };\n    }\n\n    const { minBx, minBy, minBz, maxBx, maxBy, maxBz } = occupiedBounds;\n    const cropMaxBx = maxBx + 1;\n    const cropMaxBy = maxBy + 1;\n    const cropMaxBz = maxBz + 1;\n\n    if (minBx === 0 && minBy === 0 && minBz === 0 &&\n        cropMaxBx === nbx && cropMaxBy === nby && cropMaxBz === nbz) {\n        return { grid, gridBounds };\n    }\n\n    const cropBar = logger.bar('Cropping grid', grid.types.length);\n    const croppedGrid = grid.cropTo(\n        minBx, minBy, minBz, cropMaxBx, cropMaxBy, cropMaxBz,\n        done => cropBar.update(done)\n    );\n    cropBar.end();\n\n    const blockSize = 4 * voxelResolution;\n    const croppedMin = new Vec3(\n        gridBounds.min.x + minBx * blockSize,\n        gridBounds.min.y + minBy * blockSize,\n        gridBounds.min.z + minBz * blockSize\n    );\n    const croppedBounds: Bounds = {\n        min: croppedMin,\n        max: new Vec3(\n            croppedMin.x + (cropMaxBx - minBx) * blockSize,\n            croppedMin.y + (cropMaxBy - minBy) * blockSize,\n            croppedMin.z + (cropMaxBz - minBz) * blockSize\n        )\n    };\n\n    return { grid: croppedGrid, gridBounds: croppedBounds };\n};\n\n/**\n * Crop a voxel grid to fit the navigable (non-fully-solid) region tightly.\n * Since the runtime treats outside-the-grid as solid, we only need to include\n * blocks that contain at least one empty voxel. Fully-solid blocks beyond the\n * navigable boundary are redundant.\n *\n * @param grid - Voxelized scene data.\n * @param gridBounds - Axis-aligned bounds of the voxel grid.\n * @param voxelResolution - Size of each voxel in world units.\n * @returns Cropped grid and grid bounds.\n */\nconst cropToNavigable = (\n    grid: SparseVoxelGrid,\n    gridBounds: Bounds,\n    voxelResolution: number\n): { grid: SparseVoxelGrid; gridBounds: Bounds } => {\n    const { nbx, nby, nbz } = grid;\n\n    const boundsBar = logger.bar('Scanning bounds', grid.types.length);\n    const navBounds = grid.getNavigableBlockBounds(done => boundsBar.update(done));\n    boundsBar.end();\n    if (!navBounds) {\n        return { grid, gridBounds };\n    }\n\n    const { minBx, minBy, minBz, maxBx, maxBy, maxBz } = navBounds;\n\n    // Pad by 1 block on each side so the cropped grid retains the solid wall\n    // blocks immediately surrounding the navigable cavity. Matches the\n    // MARGIN = 1 pattern used by carve() before this re-crop strips it. The\n    // collision-mesh extractors treat out-of-grid as empty, so without this\n    // padding the mesh has holes wherever the cavity reaches the cropped\n    // boundary; with it, the mesh extractor sees a real SOLID→EMPTY\n    // transition at the cavity edge and emits a sealed wall there.\n    const MARGIN = 1;\n    const cropMinBx = Math.max(0, minBx - MARGIN);\n    const cropMinBy = Math.max(0, minBy - MARGIN);\n    const cropMinBz = Math.max(0, minBz - MARGIN);\n    const cropMaxBx = Math.min(nbx, maxBx + 1 + MARGIN);\n    const cropMaxBy = Math.min(nby, maxBy + 1 + MARGIN);\n    const cropMaxBz = Math.min(nbz, maxBz + 1 + MARGIN);\n\n    if (cropMinBx === 0 && cropMinBy === 0 && cropMinBz === 0 &&\n        cropMaxBx === nbx && cropMaxBy === nby && cropMaxBz === nbz) {\n        return { grid, gridBounds };\n    }\n\n    const cropBar = logger.bar('Cropping grid', grid.types.length);\n    const croppedGrid = grid.cropTo(\n        cropMinBx, cropMinBy, cropMinBz, cropMaxBx, cropMaxBy, cropMaxBz,\n        done => cropBar.update(done)\n    );\n    cropBar.end();\n\n    const blockSize = 4 * voxelResolution;\n    const croppedMin = new Vec3(\n        gridBounds.min.x + cropMinBx * blockSize,\n        gridBounds.min.y + cropMinBy * blockSize,\n        gridBounds.min.z + cropMinBz * blockSize\n    );\n    const croppedBounds: Bounds = {\n        min: croppedMin,\n        max: new Vec3(\n            croppedMin.x + (cropMaxBx - cropMinBx) * blockSize,\n            croppedMin.y + (cropMaxBy - cropMinBy) * blockSize,\n            croppedMin.z + (cropMaxBz - cropMinBz) * blockSize\n        )\n    };\n\n    return { grid: croppedGrid, gridBounds: croppedBounds };\n};\n\n/**\n * Write octree data to files.\n *\n * @param fs - File system for writing output files.\n * @param jsonFilename - Output filename for JSON metadata.\n * @param octree - Sparse octree structure to write.\n */\nconst writeOctreeFiles = async (\n    fs: FileSystem,\n    jsonFilename: string,\n    octree: SparseOctree\n): Promise<void> => {\n    // Build metadata object\n    const metadata: VoxelMetadata = {\n        version: '1.1',\n        gridBounds: {\n            min: [octree.gridBounds.min.x, octree.gridBounds.min.y, octree.gridBounds.min.z],\n            max: [octree.gridBounds.max.x, octree.gridBounds.max.y, octree.gridBounds.max.z]\n        },\n        sceneBounds: {\n            min: [octree.sceneBounds.min.x, octree.sceneBounds.min.y, octree.sceneBounds.min.z],\n            max: [octree.sceneBounds.max.x, octree.sceneBounds.max.y, octree.sceneBounds.max.z]\n        },\n        voxelResolution: octree.voxelResolution,\n        leafSize: octree.leafSize,\n        treeDepth: octree.treeDepth,\n        numInteriorNodes: octree.numInteriorNodes,\n        numMixedLeaves: octree.numMixedLeaves,\n        nodeCount: octree.nodes.length,\n        leafDataCount: octree.leafData.length\n    };\n\n    const jsonBytes = (new TextEncoder()).encode(JSON.stringify(metadata, null, 2));\n    await writeFile(fs, jsonFilename, jsonBytes);\n    logWrittenFile(basename(jsonFilename), jsonBytes.byteLength);\n\n    const binFilename = jsonFilename.replace('.voxel.json', '.voxel.bin');\n\n    const binarySize = (octree.nodes.length + octree.leafData.length) * 4;\n    const buffer = new ArrayBuffer(binarySize);\n    const view = new Uint32Array(buffer);\n    view.set(octree.nodes, 0);\n    view.set(octree.leafData, octree.nodes.length);\n\n    await writeFile(fs, binFilename, new Uint8Array(buffer));\n    logWrittenFile(basename(binFilename), binarySize);\n};\n\n/**\n * Voxelizes Gaussian splat data and writes the result as a sparse voxel octree.\n *\n * This function performs GPU-accelerated voxelization of Gaussian splat data\n * and outputs two or three files:\n * - `filename` (.voxel.json) - JSON metadata including bounds, resolution, and array sizes\n * - Corresponding .voxel.bin - Binary octree data (nodes + leafData as Uint32 arrays)\n * - Corresponding .collision.glb - Triangle mesh extracted from the voxel output (GLB format, optional)\n *\n * The binary file layout is:\n * - Bytes 0 to (nodeCount * 4 - 1): nodes array (Uint32, little-endian)\n * - Bytes (nodeCount * 4) to end: leafData array (Uint32, little-endian)\n *\n * @param options - Options including filename, data, and voxelization settings.\n * @param fs - File system for writing output files.\n *\n * @example\n * ```ts\n * import { writeVoxel, MemoryFileSystem } from '@playcanvas/splat-transform';\n *\n * const fs = new MemoryFileSystem();\n * await writeVoxel({\n *     filename: 'scene.voxel.json',\n *     dataTable: myDataTable,\n *     voxelResolution: 0.05,\n *     opacityCutoff: 0.1,\n *     collisionMesh: true,\n *     createDevice: async () => myGraphicsDevice\n * }, fs);\n * ```\n */\nconst writeVoxel = async (options: WriteVoxelOptions, fs: FileSystem): Promise<void> => {\n    const {\n        filename,\n        dataTable,\n        voxelResolution = 0.05,\n        opacityCutoff = 0.1,\n        createDevice,\n        navExteriorRadius,\n        floorFill = false,\n        floorFillDilation = 0,\n        navCapsule,\n        navSeed,\n        collisionMesh = false\n    } = options;\n\n    if (!createDevice) {\n        throw new Error('writeVoxel requires a createDevice function for GPU voxelization');\n    }\n\n    const collisionMeshShape = (() => {\n        if (collisionMesh === false || collisionMesh === undefined) return null;\n        if (collisionMesh === true) return 'smooth';\n        if (collisionMesh === 'smooth' || collisionMesh === 'faces') return collisionMesh;\n        throw new Error(`Invalid collisionMesh value: ${String(collisionMesh)}. Expected true, false, \"smooth\", or \"faces\"`);\n    })();\n\n    if (navCapsule && !navSeed) {\n        logger.warn('navCapsule requires navSeed for nav carving, skipping nav carving');\n    }\n    const hasNav = !!(navCapsule && navSeed && navCapsule.height > 0);\n    const hasFillExterior = !!(navExteriorRadius && navSeed);\n    const hasFloorFill = floorFill;\n\n    // Build a DataTable in engine space containing only the columns needed\n    // for voxelization (no SH, so SH rotation cost is never paid).\n    const voxelColumns = [\n        'x', 'y', 'z',\n        'rot_0', 'rot_1', 'rot_2', 'rot_3',\n        'scale_0', 'scale_1', 'scale_2',\n        'opacity'\n    ];\n    const missingColumns = voxelColumns.filter(name => !dataTable.hasColumn(name));\n    if (missingColumns.length > 0) {\n        throw new Error(`writeVoxel: missing required column(s): ${missingColumns.join(', ')}`);\n    }\n    const delta = computeWriteTransform(dataTable.transform, Transform.IDENTITY);\n    let cols: ReturnType<typeof transformColumns> | null = transformColumns(dataTable, voxelColumns, delta);\n    let pcDataTable: DataTable | null = new DataTable(voxelColumns.map(name => new Column(name, cols!.get(name)!)));\n\n    let extentsResult: ReturnType<typeof computeGaussianExtents> | null = computeGaussianExtents(pcDataTable);\n    const bounds = extentsResult.sceneBounds;\n\n    const g = logger.group('Build voxels');\n\n    // gpuVoxelization is the only resource not owned by a scope; its\n    // destruction is the sole job of the finally below. Open scopes on the\n    // error path are reaped by the embedder's logger.error() -> unwindAll.\n    let gpuVoxelization: GpuVoxelization | null = null;\n    let gpuDilation: GpuDilation | null = null;\n    let bvh: GaussianBVH | null = null;\n    try {\n        const bvhSub = logger.group('Building BVH');\n        logger.debug(`scene extents: (${bounds.min.x.toFixed(2)},${bounds.min.y.toFixed(2)},${bounds.min.z.toFixed(2)}) - (${bounds.max.x.toFixed(2)},${bounds.max.y.toFixed(2)},${bounds.max.z.toFixed(2)})`);\n\n        bvh = new GaussianBVH(pcDataTable, extentsResult.extents);\n        bvhSub.end();\n\n        const device = await createDevice();\n        gpuVoxelization = new GpuVoxelization(device);\n        gpuVoxelization.uploadAllGaussians(pcDataTable, extentsResult.extents);\n\n        // Align grid bounds to block boundaries BEFORE voxelization so the\n        // block coordinates used during voxelization match what the reader\n        // expects. fillExterior and fillFloor both need a margin of empty\n        // voxels outside the splat's tight 3-sigma extents to do their job:\n        // fillExterior so the boundary-face flood seeds survive its dilation\n        // (notably below the floor), fillFloor so its column walk has empty\n        // XZ columns to convert into wall pillars and the dilation halo to\n        // extend the floor footprint outward.\n        //\n        // Lateral pad combines both as `dilation_radius + 1` voxels per side.\n        // Vertical pad is only contributed by exteriorPad — fillFloor's\n        // dilation is XZ-only, and Y padding would extend the wall pillars\n        // above the splat's natural ceiling and below its floor.\n        const exteriorPad = hasFillExterior ?\n            (Math.ceil(navExteriorRadius! / voxelResolution) + 1) * voxelResolution :\n            0;\n        const floorPad = hasFloorFill ?\n            (Math.ceil(floorFillDilation / voxelResolution) + 1) * voxelResolution :\n            0;\n        const padXZ = Math.max(exteriorPad, floorPad);\n        const padY = exteriorPad;\n        let gridBounds = alignGridBounds(\n            bounds.min.x - padXZ, bounds.min.y - padY, bounds.min.z - padXZ,\n            bounds.max.x + padXZ, bounds.max.y + padY, bounds.max.z + padXZ,\n            voxelResolution\n        );\n\n        const buffer = await voxelizeToBuffer(\n            bvh, gpuVoxelization, gridBounds, voxelResolution, opacityCutoff\n        );\n        bvh = null;\n        pcDataTable = null;\n        extentsResult = null;\n        cols = null;\n\n        gpuVoxelization.destroy();\n        gpuVoxelization = null;\n\n        const filterSub = logger.group('Filtering');\n        const nbxInit = Math.round((gridBounds.max.x - gridBounds.min.x) / (4 * voxelResolution));\n        const nbyInit = Math.round((gridBounds.max.y - gridBounds.min.y) / (4 * voxelResolution));\n        const nbzInit = Math.round((gridBounds.max.z - gridBounds.min.z) / (4 * voxelResolution));\n        const filteredBuffer = filterAndFillBlocks(buffer, nbxInit, nbyInit, nbzInit);\n        buffer.clear();\n        filterSub.end();\n\n        // Buffer → grid: the single conversion in the pipeline. Every phase\n        // beyond this point operates on SparseVoxelGrid directly.\n        const loadSub = logger.group('Loading grid');\n        const nxInit = nbxInit << 2;\n        const nyInit = nbyInit << 2;\n        const nzInit = nbzInit << 2;\n        const loadBar = logger.bar('Loading grid', Math.max(1, filteredBuffer.count));\n        let grid = SparseVoxelGrid.fromBuffer(\n            filteredBuffer, nxInit, nyInit, nzInit,\n            (done, total) => loadBar.update(Math.min(done, total))\n        );\n        loadBar.end();\n        filteredBuffer.clear();\n        loadSub.end();\n\n        // Reuse the same device for GPU dilation across exterior, floor, carve.\n        const needsGpuDilation = hasFillExterior || hasNav || (hasFloorFill && floorFillDilation > 0);\n        if (needsGpuDilation) {\n            gpuDilation = new GpuDilation(device);\n        }\n\n        if (hasFillExterior) {\n            const sub = logger.group('Fill exterior');\n            const fillResult = await fillExterior(\n                grid, gridBounds, voxelResolution,\n                navExteriorRadius!, navSeed!,\n                gpuDilation!\n            );\n            grid = fillResult.grid;\n            gridBounds = fillResult.gridBounds;\n            sub.end();\n        }\n\n        if (hasFloorFill) {\n            const sub = logger.group('Fill floor');\n            const floorResult = await fillFloor(\n                grid, gridBounds, voxelResolution, floorFillDilation, gpuDilation\n            );\n            grid = floorResult.grid;\n            gridBounds = floorResult.gridBounds;\n            sub.end();\n        }\n\n        if (hasNav) {\n            const sub = logger.group('Carve');\n            const navResult = await carve(\n                grid, gridBounds, voxelResolution,\n                navCapsule!.height, navCapsule!.radius,\n                navSeed!,\n                gpuDilation!\n            );\n            grid = navResult.grid;\n            gridBounds = navResult.gridBounds;\n            sub.end();\n        }\n\n        const cropSub = logger.group('Cropping');\n        const finalCrop = hasFillExterior || hasFloorFill ?\n            cropToNavigable(grid, gridBounds, voxelResolution) :\n            cropToOccupied(grid, gridBounds, voxelResolution);\n        grid = finalCrop.grid;\n        gridBounds = finalCrop.gridBounds;\n        cropSub.end();\n\n        gpuDilation?.destroy();\n        gpuDilation = null;\n\n        const glbBytes = collisionMeshShape ?\n            buildCollisionMesh(grid, gridBounds, voxelResolution, collisionMeshShape) :\n            null;\n\n        const octree = buildSparseOctree(\n            grid,\n            gridBounds,\n            bounds,\n            voxelResolution,\n            { consumeGrid: true }\n        );\n\n        logger.info(`octree depth: ${octree.treeDepth}`);\n        logger.info(`interior nodes: ${fmtCount(octree.numInteriorNodes)}`);\n        logger.info(`mixed leaves: ${fmtCount(octree.numMixedLeaves)}`);\n\n        const writingSub = logger.group('Writing');\n        await writeOctreeFiles(fs, filename, octree);\n\n        if (glbBytes) {\n            const glbFilename = filename.replace('.voxel.json', '.collision.glb');\n            await writeFile(fs, glbFilename, glbBytes);\n            logWrittenFile(basename(glbFilename), glbBytes.length);\n        }\n        writingSub.end();\n\n        g.end();\n    } finally {\n        gpuVoxelization?.destroy();\n        gpuDilation?.destroy();\n    }\n};\n\nexport { writeVoxel, writeOctreeFiles, type WriteVoxelOptions, type VoxelMetadata };\n","import { DataTable } from './data-table';\nimport { type FileSystem } from './io/write';\nimport { type DeviceCreator, type Options } from './types';\nimport { writeCompressedPly, writeCsv, writeGlb, writeHtml, writeImage, writeLod, writePly, writeSog, writeSpz, writeVoxel } from './writers';\n\n/**\n * Supported output file formats for Gaussian splat data.\n *\n * - `ply` - Standard PLY format\n * - `compressed-ply` - Compressed PLY format\n * - `spz` - Niantic Labs SPZ format\n * - `glb` - Binary glTF with KHR_gaussian_splatting extension\n * - `csv` - CSV text format (for debugging/analysis)\n * - `sog` - PlayCanvas SOG format (separate files)\n * - `sog-bundle` - PlayCanvas SOG format (bundled into single .sog file)\n * - `lod` - Multi-LOD format with chunked data\n * - `html` - Self-contained HTML viewer (separate assets)\n * - `html-bundle` - Self-contained HTML viewer (all assets embedded)\n * - `voxel` - Sparse voxel octree format for collision detection\n * - `image` - Rasterized RGBA image (lossless WebP) rendered from a camera view\n */\ntype OutputFormat = 'csv' | 'sog' | 'sog-bundle' | 'lod' | 'compressed-ply' | 'ply' | 'spz' | 'glb' | 'html' | 'html-bundle' | 'voxel' | 'image';\n\n/**\n * Options for writing a Gaussian splat file.\n */\ntype WriteOptions = {\n    /** Path to the output file. */\n    filename: string;\n    /** The format to write. */\n    outputFormat: OutputFormat;\n    /** The splat data to write. */\n    dataTable: DataTable;\n    /** Optional environment/skybox splat data (for LOD format). */\n    envDataTable?: DataTable;\n    /** Processing options. */\n    options: Options;\n    /** Optional function to create a GPU device for compression. */\n    createDevice?: DeviceCreator;\n};\n\n/**\n * Determines the output format based on file extension and options.\n *\n * @param filename - The filename to analyze.\n * @param options - Options that may affect format selection.\n * @returns The detected output format.\n * @throws Error if the file extension is not recognized.\n *\n * @example\n * ```ts\n * const format = getOutputFormat('scene.ply', {});  // returns 'ply'\n * const format2 = getOutputFormat('scene.sog', {});  // returns 'sog-bundle'\n * ```\n */\nconst getOutputFormat = (filename: string, options: Options): OutputFormat => {\n    const lowerFilename = filename.toLowerCase();\n\n    if (lowerFilename.endsWith('.csv')) {\n        return 'csv';\n    } else if (lowerFilename.endsWith('.voxel.json')) {\n        return 'voxel';\n    } else if (lowerFilename.endsWith('lod-meta.json')) {\n        return 'lod';\n    } else if (lowerFilename.endsWith('.sog')) {\n        return 'sog-bundle';\n    } else if (lowerFilename.endsWith('meta.json')) {\n        return 'sog';\n    } else if (lowerFilename.endsWith('.compressed.ply')) {\n        return 'compressed-ply';\n    } else if (lowerFilename.endsWith('.ply')) {\n        return 'ply';\n    } else if (lowerFilename.endsWith('.spz')) {\n        return 'spz';\n    } else if (lowerFilename.endsWith('.glb')) {\n        return 'glb';\n    } else if (lowerFilename.endsWith('.html')) {\n        return options.unbundled ? 'html' : 'html-bundle';\n    } else if (lowerFilename.endsWith('.webp')) {\n        return 'image';\n    }\n\n    throw new Error(`Unsupported output file type: ${filename}`);\n};\n\n/**\n * Writes Gaussian splat data to a file in the specified format.\n *\n * Supports multiple output formats including PLY, compressed PLY, CSV, SOG, LOD, and HTML.\n *\n * @param writeOptions - Options specifying the data and format to write.\n * @param fs - File system abstraction for writing files.\n *\n * @example\n * ```ts\n * import { writeFile, getOutputFormat, MemoryFileSystem } from '@playcanvas/splat-transform';\n *\n * const fs = new MemoryFileSystem();\n * await writeFile({\n *     filename: 'output.sog',\n *     outputFormat: getOutputFormat('output.sog', {}),\n *     dataTable: myDataTable,\n *     options: { iterations: 8 }\n * }, fs);\n * ```\n */\nconst writeFile = async (writeOptions: WriteOptions, fs: FileSystem) => {\n    const { filename, outputFormat, dataTable, envDataTable, options, createDevice } = writeOptions;\n\n    // Each writer is responsible for opening its own `Writing` log group and\n    // emitting `filename (size)` info entries per output file.\n    switch (outputFormat) {\n        case 'csv':\n            await writeCsv({ filename, dataTable }, fs);\n            break;\n        case 'sog':\n        case 'sog-bundle':\n            await writeSog({\n                filename,\n                dataTable,\n                bundle: outputFormat === 'sog-bundle',\n                iterations: options.iterations,\n                createDevice\n            }, fs);\n            break;\n        case 'lod':\n            await writeLod({\n                filename,\n                dataTable,\n                envDataTable,\n                iterations: options.iterations,\n                createDevice,\n                chunkCount: options.lodChunkCount,\n                chunkExtent: options.lodChunkExtent\n            }, fs);\n            break;\n        case 'compressed-ply':\n            await writeCompressedPly({ filename, dataTable }, fs);\n            break;\n        case 'ply':\n            await writePly({\n                filename,\n                plyData: {\n                    comments: [],\n                    elements: [{\n                        name: 'vertex',\n                        dataTable\n                    }]\n                }\n            }, fs);\n            break;\n        case 'spz':\n            await writeSpz({\n                filename,\n                dataTable,\n                version: options.spzVersion ?? 4\n            }, fs);\n            break;\n        case 'glb':\n            await writeGlb({ filename, dataTable }, fs);\n            break;\n        case 'html':\n        case 'html-bundle':\n            await writeHtml({\n                filename,\n                dataTable,\n                viewerSettingsJson: options.viewerSettingsJson,\n                bundle: outputFormat === 'html-bundle',\n                iterations: options.iterations,\n                createDevice\n            }, fs);\n            break;\n        case 'voxel':\n            await writeVoxel({\n                filename,\n                dataTable,\n                voxelResolution: options.voxelResolution,\n                opacityCutoff: options.opacityCutoff,\n                navExteriorRadius: options.navExteriorRadius,\n                floorFill: options.floorFill,\n                floorFillDilation: options.floorFillDilation,\n                navCapsule: options.navCapsule,\n                navSeed: options.navSeed,\n                collisionMesh: options.collisionMesh,\n                createDevice\n            }, fs);\n            break;\n        case 'image':\n            await writeImage({\n                filename,\n                dataTable,\n                projection: options.renderProjection,\n                cameraPosition: options.renderCameraPosition,\n                lookAt: options.renderLookAt,\n                up: options.renderUp,\n                fov: options.renderFov,\n                width: options.renderWidth,\n                height: options.renderHeight,\n                near: options.renderNear,\n                background: options.renderBackground,\n                fStop: options.renderFStop,\n                focusDistance: options.renderFocusDistance,\n                sensorSize: options.renderSensorSize,\n                cameraEndPosition: options.renderCameraEndPosition,\n                lookAtEnd: options.renderLookAtEnd,\n                upEnd: options.renderUpEnd,\n                shutter: options.renderShutter,\n                motionSamples: options.renderMotionSamples,\n                createDevice\n            }, fs);\n            break;\n    }\n};\n\nexport { getOutputFormat, writeFile, type OutputFormat, type WriteOptions };\n","import { Vec3 } from 'playcanvas';\n\nimport { Column, DataTable, simplifyGaussians, sortMortonOrder, computeSummary, type SummaryData, convertToSpace, getSHBands } from './data-table';\nimport type { DeviceCreator } from './types';\nimport { fmtCount, type Group, logger, Transform } from './utils';\nimport { filterCluster as filterClusterFn } from './voxel/filter-cluster';\nimport { filterFloaters as filterFloatersFn } from './voxel/filter-floaters';\n\n/**\n * Translate splats by a 3D vector offset.\n */\ntype Translate = {\n    /** Action type identifier. */\n    kind: 'translate';\n    /** Translation offset. */\n    value: Vec3;\n};\n\n/**\n * Rotate splats by Euler angles.\n */\ntype Rotate = {\n    /** Action type identifier. */\n    kind: 'rotate';\n    /** Euler angles in degrees (x, y, z). */\n    value: Vec3;\n};\n\n/**\n * Uniformly scale all splats.\n */\ntype Scale = {\n    /** Action type identifier. */\n    kind: 'scale';\n    /** Scale factor. */\n    value: number;\n};\n\n/**\n * Remove splats containing NaN or Infinity values.\n */\ntype FilterNaN = {\n    /** Action type identifier. */\n    kind: 'filterNaN';\n};\n\n/**\n * Filter splats by comparing a column value.\n *\n * For `opacity`, `scale_0/1/2`, and `f_dc_0/1/2`, the value is specified in user-friendly\n * (transformed) space: linear opacity (0-1), linear scale, and linear color (0-1).\n * The value is automatically converted to raw PLY space before comparison.\n *\n * To compare against raw PLY values directly (without the user-friendly conversion),\n * use the `_raw` suffix (e.g. `opacity_raw`, `scale_0_raw`, `f_dc_0_raw`).\n *\n * If the DataTable has a pending spatial transform and the column is affected by it\n * (position, rotation, scale, or SH columns), the transform is applied (baked in)\n * before comparison. This applies to both regular and `_raw` columns.\n */\ntype FilterByValue = {\n    /** Action type identifier. */\n    kind: 'filterByValue';\n    /** Name of the column to compare. */\n    columnName: string;\n    /** Comparison operator. */\n    comparator: 'lt' | 'lte' | 'gt' | 'gte' | 'eq' | 'neq';\n    /** Value to compare against. */\n    value: number;\n};\n\n/**\n * Remove spherical harmonic bands above a threshold.\n */\ntype FilterBands = {\n    /** Action type identifier. */\n    kind: 'filterBands';\n    /** Maximum SH band to keep (0-3). */\n    value: 0 | 1 | 2 | 3;\n};\n\n/**\n * Keep only splats within a bounding box.\n */\ntype FilterBox = {\n    /** Action type identifier. */\n    kind: 'filterBox';\n    /** Minimum corner of the box. */\n    min: Vec3;\n    /** Maximum corner of the box. */\n    max: Vec3;\n};\n\n/**\n * Keep only splats within a sphere.\n */\ntype FilterSphere = {\n    /** Action type identifier. */\n    kind: 'filterSphere';\n    /** Center of the sphere. */\n    center: Vec3;\n    /** Radius of the sphere. */\n    radius: number;\n};\n\n/**\n * Parameter for .mjs generator modules.\n */\ntype Param = {\n    /** Action type identifier. */\n    kind: 'param';\n    /** Parameter name. */\n    name: string;\n    /** Parameter value. */\n    value: string;\n};\n\n/**\n * Assign a LOD level to all splats.\n */\ntype Lod = {\n    /** Action type identifier. */\n    kind: 'lod';\n    /** LOD level to assign. */\n    value: number;\n};\n\n/**\n * Print a statistical summary to the logger.\n */\ntype Summary = {\n    /** Action type identifier. */\n    kind: 'summary';\n};\n\n/**\n * Reorder splats by Morton code (Z-order curve) for improved spatial locality.\n */\ntype MortonOrder = {\n    /** Action type identifier. */\n    kind: 'mortonOrder';\n};\n\n/**\n * Simplify splats to a target count using NanoGS progressive pairwise merging.\n *\n * Instead of discarding low-visibility splats, this iteratively merges nearby\n * similar splats into single approximating Gaussians using Mass-Preserving\n * Moment Matching (MPMM), preserving scene structure and appearance.\n */\ntype Decimate = {\n    /** Action type identifier. */\n    kind: 'decimate';\n    /** Target number of splats to keep, or null for percentage mode. */\n    count: number | null;\n    /** Percentage of splats to keep (0-100), or null for count mode. */\n    percent: number | null;\n};\n\n/**\n * Remove Gaussians that don't meaningfully contribute to any solid voxel.\n *\n * GPU-voxelizes the scene at a given resolution, then evaluates each Gaussian's\n * opacity contribution at occupied voxel centers. Discards Gaussians whose\n * contribution is below a minimum threshold at every solid voxel.\n */\ntype FilterFloaters = {\n    /** Action type identifier. */\n    kind: 'filterFloaters';\n    /** Voxel size in world units. Default: 0.05 */\n    voxelResolution?: number;\n    /** Opacity threshold for solid voxels. Default: 0.1 */\n    opacityCutoff?: number;\n    /** Minimum Gaussian contribution at a voxel center to be kept. Default: 1/255 */\n    minContribution?: number;\n};\n\n/**\n * Filter Gaussians to keep only those in the connected cluster at a seed position.\n *\n * GPU-voxelizes the scene at a coarse resolution, finds the connected component\n * of occupied blocks containing the seed, and keeps only Gaussians whose AABB\n * overlaps that cluster.\n */\ntype FilterCluster = {\n    /** Action type identifier. */\n    kind: 'filterCluster';\n    /** Voxel size in world units for coarse voxelization. Default: 1.0 */\n    voxelResolution?: number;\n    /** Seed position for finding the connected component. Default: Vec3(0,0,0) */\n    seed?: Vec3;\n    /** Opacity threshold for solid voxels. Default: 0.999 */\n    opacityCutoff?: number;\n    /** Minimum Gaussian contribution at a cluster voxel center to be kept. Default: 0.1 */\n    minContribution?: number;\n};\n\n/**\n * Options for processing actions that require external resources.\n */\ntype ProcessOptions = {\n    /** Function to create a GPU device (required for filterFloaters, filterCluster). */\n    createDevice?: DeviceCreator;\n};\n\n/**\n * A processing action to apply to splat data.\n *\n * Actions can transform, filter, or analyze the data:\n * - `translate` - Move splats by a Vec3 offset\n * - `rotate` - Rotate splats by Euler angles (degrees)\n * - `scale` - Uniformly scale splats\n * - `filterNaN` - Remove splats with NaN/Inf values\n * - `filterByValue` - Keep splats matching a column condition\n * - `filterBands` - Remove spherical harmonic bands above a threshold\n * - `filterBox` - Keep splats within a bounding box\n * - `filterSphere` - Keep splats within a sphere\n * - `filterFloaters` - Remove splats not contributing to any occupied voxel (GPU)\n * - `filterCluster` - Keep splats in the connected cluster at a seed position (GPU)\n * - `lod` - Assign LOD level to all splats\n * - `summary` - Print statistical summary to logger\n * - `mortonOrder` - Reorder splats by Morton code for spatial locality\n * - `decimate` - Simplify to target count via progressive pairwise merging\n */\ntype ProcessAction = Translate | Rotate | Scale | FilterNaN | FilterByValue | FilterBands | FilterBox | FilterSphere | FilterFloaters | FilterCluster | Param | Lod | Summary | MortonOrder | Decimate;\n\nconst SH_C0 = 0.28209479177387814;\n\n// Inverse transforms: convert user-friendly values to raw PLY space.\n// All transforms are monotonic increasing, so comparison direction is preserved.\nconst inverseTransforms: Record<string, (v: number) => number> = {\n    'opacity': v => Math.log(v / (1 - v)),\n    'scale_0': Math.log,\n    'scale_1': Math.log,\n    'scale_2': Math.log,\n    'f_dc_0': v => (v - 0.5) / SH_C0,\n    'f_dc_1': v => (v - 0.5) / SH_C0,\n    'f_dc_2': v => (v - 0.5) / SH_C0\n};\n\n// Forward transforms: convert raw PLY values to user-friendly space (for summary display).\nconst forwardTransforms: Record<string, (v: number) => number> = {\n    'opacity': v => 1 / (1 + Math.exp(-v)),\n    'scale_0': Math.exp,\n    'scale_1': Math.exp,\n    'scale_2': Math.exp,\n    'f_dc_0': v => 0.5 + v * SH_C0,\n    'f_dc_1': v => 0.5 + v * SH_C0,\n    'f_dc_2': v => 0.5 + v * SH_C0\n};\n\n// Maps `_raw` suffixed column names to their underlying PLY column.\nconst rawColumnMap: Record<string, string> = {\n    'opacity_raw': 'opacity',\n    'scale_0_raw': 'scale_0',\n    'scale_1_raw': 'scale_1',\n    'scale_2_raw': 'scale_2',\n    'f_dc_0_raw': 'f_dc_0',\n    'f_dc_1_raw': 'f_dc_1',\n    'f_dc_2_raw': 'f_dc_2'\n};\n\nconst transformColumnNames = new Set([\n    'x', 'y', 'z',\n    'rot_0', 'rot_1', 'rot_2', 'rot_3',\n    'scale_0', 'scale_1', 'scale_2'\n]);\n\nconst isTransformColumn = (name: string): boolean => transformColumnNames.has(name) || /^f_rest_\\d+$/.test(name);\n\n// Describe a delta as \"removed N\" / \"added N\" relative to the previous count.\nconst describeDelta = (delta: number, noun: string): string => {\n    return delta > 0 ? `removed ${fmtCount(delta)} ${noun}` : `added ${fmtCount(-delta)} ${noun}`;\n};\n\n// Close a filter's group, emitting a single result line that summarizes the\n// row/column delta. Each filter case opens its own group at the top; this is\n// the symmetric \"finish\" that runs at the bottom.\nconst endFilterGroup = (g: Group, prev: DataTable, next: DataTable) => {\n    const removedRows = prev.numRows - next.numRows;\n    const removedCols = prev.columnNames.length - next.columnNames.length;\n    const parts: string[] = [];\n    if (removedRows !== 0) parts.push(describeDelta(removedRows, 'gaussians'));\n    if (removedCols !== 0) parts.push(describeDelta(removedCols, 'columns'));\n    logger.info(parts.length > 0 ? parts.join(', ') : 'no change');\n    g.end();\n};\n\nconst formatMarkdown = (summary: SummaryData): string => {\n    const lines: string[] = [];\n\n    lines.push('# Summary');\n    lines.push('');\n    lines.push(`**Row Count:** ${summary.rowCount}`);\n    lines.push('');\n\n    // Build header and data rows as string arrays\n    const headers = ['Column', 'min', 'max', 'median', 'mean', 'stdDev', 'nans', 'infs', 'histogram'];\n    const rows: string[][] = [];\n\n    for (const [name, stats] of Object.entries(summary.columns)) {\n        const fn = forwardTransforms[name];\n        const fmt = (v: number) => String(fn ? +(fn(v).toPrecision(6)) : v);\n        rows.push([\n            name,\n            fmt(stats.min),\n            fmt(stats.max),\n            fmt(stats.median),\n            fmt(stats.mean),\n            fmt(stats.stdDev),\n            String(stats.nanCount),\n            String(stats.infCount),\n            stats.histogram\n        ]);\n    }\n\n    // Calculate max width for each column\n    const colWidths = headers.map((header, colIndex) => {\n        const dataWidths = rows.map(row => row[colIndex].length);\n        return Math.max(header.length, ...dataWidths);\n    });\n\n    // Build aligned table\n    const padRow = (cells: string[]) => `| ${cells.map((cell, i) => cell.padEnd(colWidths[i])).join(' | ')} |`;\n\n    const separator = `|${colWidths.map(w => '-'.repeat(w + 2)).join('|')}|`;\n\n    lines.push(padRow(headers));\n    lines.push(separator);\n    for (const row of rows) {\n        lines.push(padRow(row));\n    }\n\n    return lines.join('\\n');\n};\n\nconst filter = (dataTable: DataTable, predicate: (row: any, rowIndex: number) => boolean): DataTable => {\n    const indices = new Uint32Array(dataTable.numRows);\n    let index = 0;\n    const row = {};\n\n    for (let i = 0; i < dataTable.numRows; i++) {\n        dataTable.getRow(i, row);\n\n        if (predicate(row, i)) {\n            indices[index++] = i;\n        }\n    }\n\n    return dataTable.clone({ rows: indices.subarray(0, index) });\n};\n\n/**\n * Applies a sequence of processing actions to splat data.\n *\n * Actions are applied in order and can include transformations (translate, rotate, scale),\n * filters (NaN, value, box, sphere, bands), and analysis (summary).\n *\n * @param dataTable - The input splat data.\n * @param processActions - Array of actions to apply in sequence.\n * @param options - Optional resources for GPU-dependent actions (e.g. filterCluster).\n * @returns The processed DataTable (may be a new instance if filtered).\n *\n * @example\n * ```ts\n * import { Vec3 } from 'playcanvas';\n *\n * const processed = await processDataTable(dataTable, [\n *     { kind: 'scale', value: 0.5 },\n *     { kind: 'translate', value: new Vec3(0, 1, 0) },\n *     { kind: 'filterNaN' },\n *     // opacity value is in linear space (0-1), automatically converted to logit for comparison\n *     { kind: 'filterByValue', columnName: 'opacity', comparator: 'gt', value: 0.1 }\n * ]);\n * ```\n */\nconst processDataTable = async (dataTable: DataTable, processActions: ProcessAction[], options?: ProcessOptions): Promise<DataTable> => {\n    let result = dataTable;\n\n    for (let i = 0; i < processActions.length; i++) {\n        const processAction = processActions[i];\n\n        switch (processAction.kind) {\n            case 'translate':\n                result.transform = new Transform(processAction.value).mul(result.transform);\n                break;\n            case 'rotate':\n                result.transform = new Transform().fromEulers(\n                    processAction.value.x,\n                    processAction.value.y,\n                    processAction.value.z\n                ).mul(result.transform);\n                break;\n            case 'scale':\n                result.transform = new Transform(undefined, undefined, processAction.value).mul(result.transform);\n                break;\n            case 'filterNaN': {\n                const g = logger.group('Filter NaN');\n                const prev = result;\n                const infOk = new Set(['opacity']);\n                const negInfOk = new Set(['scale_0', 'scale_1', 'scale_2']);\n                const columnNames = result.columnNames;\n\n                const predicate = (row: any) => {\n                    for (const key of columnNames) {\n                        const value = row[key];\n                        if (!isFinite(value)) {\n                            if (value === -Infinity && negInfOk.has(key)) continue;\n                            if (value === Infinity && infOk.has(key)) continue;\n                            return false;\n                        }\n                    }\n                    return true;\n                };\n                result = filter(result, predicate);\n                endFilterGroup(g, prev, result);\n                break;\n            }\n            case 'filterByValue': {\n                const g = logger.group('Filter by value');\n                const prev = result;\n                const { comparator } = processAction;\n                let { columnName, value } = processAction;\n\n                if (rawColumnMap[columnName]) {\n                    columnName = rawColumnMap[columnName];\n                } else if (inverseTransforms[columnName]) {\n                    if (columnName === 'opacity' && (value <= 0 || value >= 1)) {\n                        throw new Error(`filterByValue: opacity value must be between 0 and 1 (exclusive), got ${value}`);\n                    }\n                    value = inverseTransforms[columnName](value);\n                }\n\n                if (!result.hasColumn(columnName)) {\n                    throw new Error(`filterByValue: column '${columnName}' not found in DataTable`);\n                }\n\n                if (!result.transform.isIdentity() && isTransformColumn(columnName)) {\n                    result = convertToSpace(result, Transform.IDENTITY);\n                }\n\n                const Predicates = {\n                    'lt': (row: any) => row[columnName] < value,\n                    'lte': (row: any) => row[columnName] <= value,\n                    'gt': (row: any) => row[columnName] > value,\n                    'gte': (row: any) => row[columnName] >= value,\n                    'eq': (row: any) => row[columnName] === value,\n                    'neq': (row: any) => row[columnName] !== value\n                };\n                const predicate = Predicates[comparator as keyof typeof Predicates];\n                if (!predicate) {\n                    throw new Error(`filterByValue: unknown comparator '${comparator}', expected one of: ${Object.keys(Predicates).join(', ')}`);\n                }\n                result = filter(result, predicate);\n                endFilterGroup(g, prev, result);\n                break;\n            }\n            case 'filterBands': {\n                const g = logger.group('Filter bands');\n                const prev = result;\n                const currentTable = result;\n                const inputBands = getSHBands(currentTable);\n                const outputBands = processAction.value;\n\n                if (outputBands < inputBands) {\n                    const inputCoeffs = [0, 3, 8, 15][inputBands];\n                    const outputCoeffs = [0, 3, 8, 15][outputBands];\n\n                    const map: any = {};\n                    for (let i = 0; i < inputCoeffs; ++i) {\n                        for (let j = 0; j < 3; ++j) {\n                            const inputName = `f_rest_${i + j * inputCoeffs}`;\n                            map[inputName] = i < outputCoeffs ? `f_rest_${i + j * outputCoeffs}` : null;\n                        }\n                    }\n\n                    result = new DataTable(result.columns.map((column) => {\n                        if (map.hasOwnProperty(column.name)) {\n                            const name = map[column.name];\n                            return name ? new Column(name, column.data) : null;\n                        }\n                        return column;\n\n                    }).filter(c => c !== null), result.transform);\n                }\n                endFilterGroup(g, prev, result);\n                break;\n            }\n            case 'filterBox': {\n                const g = logger.group('Filter box');\n                const prev = result;\n                const { min, max } = processAction;\n\n                if (result.transform.isIdentity()) {\n                    const predicate = (row: any) => {\n                        const { x, y, z } = row;\n                        return x >= min.x && x <= max.x &&\n                               y >= min.y && y <= max.y &&\n                               z >= min.z && z <= max.z;\n                    };\n                    result = filter(result, predicate);\n                } else {\n                    const { translation, scale } = result.transform;\n                    if (scale === 0) {\n                        throw new Error('Cannot apply filterBox with scale 0');\n                    }\n                    const invRot = result.transform.rotation.clone().invert();\n\n                    const axes = [new Vec3(1, 0, 0), new Vec3(0, 1, 0), new Vec3(0, 0, 1)];\n                    const rawAxes = axes.map((a) => {\n                        const r = new Vec3();\n                        invRot.transformVector(a, r);\n                        return r;\n                    });\n\n                    const minArr = [min.x, min.y, min.z];\n                    const maxArr = [max.x, max.y, max.z];\n                    const rawMin = new Array(3);\n                    const rawMax = new Array(3);\n                    for (let j = 0; j < 3; j++) {\n                        const dot = axes[j].dot(translation);\n                        rawMin[j] = (minArr[j] - dot) / scale;\n                        rawMax[j] = (maxArr[j] - dot) / scale;\n                    }\n\n                    const predicate = (row: any) => {\n                        const { x, y, z } = row;\n                        for (let j = 0; j < 3; j++) {\n                            const proj = rawAxes[j].x * x + rawAxes[j].y * y + rawAxes[j].z * z;\n                            if (proj < rawMin[j] || proj > rawMax[j]) return false;\n                        }\n                        return true;\n                    };\n                    result = filter(result, predicate);\n                }\n                endFilterGroup(g, prev, result);\n                break;\n            }\n            case 'filterSphere': {\n                const g = logger.group('Filter sphere');\n                const prev = result;\n                const rawCenter = processAction.center.clone();\n                let rawRadius = processAction.radius;\n                if (!result.transform.isIdentity()) {\n                    result.transform.clone().invert().transformPoint(rawCenter, rawCenter);\n                    rawRadius /= result.transform.scale;\n                }\n                const radiusSq = rawRadius * rawRadius;\n                const predicate = (row: any) => {\n                    const { x, y, z } = row;\n                    return (x - rawCenter.x) ** 2 + (y - rawCenter.y) ** 2 + (z - rawCenter.z) ** 2 < radiusSq;\n                };\n                result = filter(result, predicate);\n                endFilterGroup(g, prev, result);\n                break;\n            }\n            case 'param': {\n                // skip params\n                break;\n            }\n            case 'lod': {\n                if (!result.getColumnByName('lod')) {\n                    result.addColumn(new Column('lod', new Float32Array(result.numRows)));\n                }\n                result.getColumnByName('lod').data.fill(processAction.value);\n                break;\n            }\n            case 'summary': {\n                const summary = computeSummary(result);\n                const markdown = formatMarkdown(summary);\n                logger.output(markdown);\n                break;\n            }\n            case 'mortonOrder': {\n                const indices = new Uint32Array(result.numRows);\n                for (let i = 0; i < indices.length; i++) {\n                    indices[i] = i;\n                }\n                sortMortonOrder(result, indices);\n                result.permuteRowsInPlace(indices);\n                break;\n            }\n            case 'decimate': {\n                let keepCount: number;\n                if (processAction.count !== null) {\n                    keepCount = Math.min(processAction.count, result.numRows);\n                } else {\n                    keepCount = Math.round(result.numRows * (processAction.percent ?? 100) / 100);\n                }\n                keepCount = Math.max(0, keepCount);\n\n                // Pass the factory (not an eagerly-created device) so\n                // `simplifyGaussians` can create the device lazily — and skip\n                // creation entirely when the input is already at or below the\n                // target count. The caller of `processDataTable` is\n                // responsible for caching the device if it should be reused\n                // across actions (see `DeviceCreator` contract in types.ts).\n                result = await simplifyGaussians(result, keepCount, options?.createDevice);\n                break;\n            }\n            case 'filterFloaters': {\n                if (!options?.createDevice) {\n                    throw new Error('filterFloaters requires a createDevice function (GPU voxelization)');\n                }\n                result = await filterFloatersFn(\n                    result,\n                    options.createDevice,\n                    processAction.voxelResolution,\n                    processAction.opacityCutoff,\n                    processAction.minContribution\n                );\n                break;\n            }\n            case 'filterCluster': {\n                if (!options?.createDevice) {\n                    throw new Error('filterCluster requires a createDevice function (GPU voxelization)');\n                }\n                result = await filterClusterFn(\n                    result,\n                    options.createDevice,\n                    processAction.voxelResolution,\n                    processAction.seed,\n                    processAction.opacityCutoff,\n                    processAction.minContribution\n                );\n                break;\n            }\n        }\n\n    }\n\n    return result;\n};\n\nexport {\n    processDataTable,\n    type ProcessAction,\n    type ProcessOptions,\n    type Translate,\n    type Rotate,\n    type Scale,\n    type FilterNaN,\n    type FilterByValue,\n    type FilterBands,\n    type FilterBox,\n    type FilterSphere,\n    type FilterFloaters,\n    type FilterCluster,\n    type Param,\n    type Lod,\n    type Summary,\n    type MortonOrder,\n    type Decimate\n};\n"],"names":["sigmoid","Vec3","Quat","require","createModule","Mat3","BindGroupFormat","BindUniformBufferFormat","SHADERSTAGE_COMPUTE","BindStorageBufferFormat","Shader","SHADERLANGUAGE_WGSL","UniformBufferFormat","UniformFormat","UNIFORMTYPE_UINT","UNIFORMTYPE_FLOAT","StorageBuffer","BUFFERUSAGE_COPY_DST","BUFFERUSAGE_COPY_SRC","Compute","Mat4","BoundingBox","readFile","normalize","TICK_BATCH","CHUNK_SIZE","decodeMeans","invLogTransform","unpackQuat","SH_C0","writeFile","FloatPacking","numSHCoeffsPerChannel","ComputeRadixSort","webPCodec","html","css","js","renderSplats","SOLID_MASK","filterFloatersFn","filterClusterFn"],"mappings":"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zC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAI,GAAG,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAI,GAAG,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAI,GAAG,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAI,GAAG,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAI,GAAG,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAI,GAAG,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAI,GAAG,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAI,GAAG,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAI,GAAG,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAI,GAAG,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAI,GAAG,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAI,GAAG,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;AAC1C,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;AACzC,MAAM,UAAU,GAAI,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;AAEzC,MAAM,EAAE,GAAG,CAAC,CAAS,EAAE,KAAa,EAAE,CAA0B,EAAE,CAA0B,KAAI;IAC5F,IAAI,GAAG,GAAG,CAAC;AACX,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;AACxB,QAAA,GAAG,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC9B;AACA,IAAA,OAAO,GAAG;AACd,CAAC;AAED,MAAM,QAAQ,GAAG,IAAI,YAAY,CAAC,EAAE,CAAC;AAErC;AACA;AACA;AACA,MAAM,WAAW,GAAG,CAAC,GAAe,EAAE,GAAe,EAAE,GAAe,KAAI;IACtE,MAAM,MAAM,GAAa,EAAE;IAC3B,MAAM,OAAO,GAAa,EAAE;IAC5B,MAAM,MAAM,GAAa,EAAE;IAE3B,MAAM,OAAO,GAAG,CAAC,MAAkB,EAAE,IAAY,EAAE,IAAY,KAAI;AAC/D,QAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE;YAC3B,IAAI,KAAK,GAAG,CAAC;AACb,YAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE;AAC3B,gBAAA,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,EAAE;AAChC,oBAAA,OAAO,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;oBACtB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzB,oBAAA,KAAK,EAAE;gBACX;YACJ;AACA,YAAA,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;QACtB;AACJ,IAAA,CAAC;AAED,IAAA,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;AAClB,IAAA,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;AAClB,IAAA,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;AAElB,IAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;AACtC,CAAC;AAED;AACA;AACA,MAAM,aAAa,GAAG,CAAC,GAAiB,KAAI;AACxC,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;QACxB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC1B,QAAA,IAAI,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI;AAAE,YAAA,OAAO,KAAK;IACxD;AACA,IAAA,OAAO,IAAI;AACf,CAAC;AAED;AACA;AACA;AACA;AACA,MAAM,QAAQ,CAAA;AACV,IAAA,KAAK;AAEL,IAAA,WAAA,CAAY,GAAS,EAAA;AACjB,QAAA,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI;;AAGpB,QAAA,MAAM,GAAG,GAAG;AACR,YAAA,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;AACzB,YAAA,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC1B,YAAA,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;SAC3B;;QAGD,MAAM,GAAG,GAAG,CAAC;AACT,gBAAA,UAAU,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClG,iBAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5D,gBAAA,UAAU,IAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/C,iBAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5D,gBAAA,UAAU,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAClH,EAAE;AACC,gBAAA,UAAU,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjG,gBAAA,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5D,gBAAA,UAAU,IAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9C,gBAAA,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5D,gBAAA,UAAU,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAClH,EAAE;gBACC,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC/K,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACpF,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAClG,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAClG,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI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AC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACjK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAA2C,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5H,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAA4B,UAAU,IAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5H,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAA4B,UAAU,IAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5H,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAA4B,UAAU,IAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,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,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnJ,gBAAA,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAA4B,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjK,gBAAA,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAA4B,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjK,gBAAA,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAChP,EAAE;gBACC,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC/K,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAA4B,UAAU,IAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5H,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAA4B,UAAU,IAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC9G,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAA4B,UAAU,IAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5H,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAA4B,UAAU,IAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5H,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAA4B,UAAU,IAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5H,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aACjL,EAAE;AACC,gBAAA,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9O,gBAAA,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAA4B,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnJ,gBAAA,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAA4B,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjK,gBAAA,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAA4B,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnJ,gBAAA,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAA4B,UAAU,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAA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AC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChH,gBAAA,UAAU,IAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7D,gBAAA,UAAU,IAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7D,gBAAA,UAAU,IAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7D,gBAAA,UAAU,IAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7D,gBAAA,UAAU,IAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7D,gBAAA,UAAU,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,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;AACtD,IAAA,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;AACtD,IAAA,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;AACtD,IAAA,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;AACtD,IAAA,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;AACtD,IAAA,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;AACtD,IAAA,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;AACtD,IAAA,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;AACtD,IAAA,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;AACtD,IAAA,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;AACtD,IAAA,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;AACtD,IAAA,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;AACtD,IAAA,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;AACtD,IAAA,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;AACtD,IAAA,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","x_google_ignoreList":[25,46]}