{"version":3,"file":"index.mjs","sources":["../src/lib/data-table/data-table.ts","../src/lib/data-table/combine.ts","../src/lib/utils/rotate-sh.ts","../src/lib/data-table/transform.ts","../src/lib/data-table/summary.ts","../src/lib/utils/logger.ts","../src/lib/data-table/morton-order.ts","../src/lib/data-table/filter-visibility.ts","../src/lib/io/read/file-system.ts","../src/lib/io/read/zip-file-system.ts","../src/lib/readers/read-ksplat.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/readers/read-lcc.ts","../src/lib/readers/read-mjs.ts","../src/lib/readers/decompress-ply.ts","../src/lib/readers/read-ply.ts","../lib/webp.mjs","../src/lib/utils/webp-codec.ts","../src/lib/readers/read-sog.ts","../src/lib/readers/read-splat.ts","../src/lib/readers/read-spz.ts","../src/lib/voxel/sparse-octree.ts","../src/lib/readers/read-voxel.ts","../src/lib/read.ts","../src/lib/utils/math.ts","../src/lib/writers/compressed-chunk.ts","../src/lib/writers/write-compressed-ply.ts","../src/lib/writers/write-csv.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/kd-tree.ts","../src/lib/gpu/gpu-clustering.ts","../src/lib/spatial/k-means.ts","../src/lib/spatial/quantize-1d.ts","../src/lib/writers/write-sog.ts","../src/lib/utils/base64.ts","../src/lib/writers/write-html.ts","../src/lib/spatial/b-tree.ts","../src/lib/writers/write-lod.ts","../src/lib/writers/write-ply.ts","../src/lib/voxel/gaussian-aabb.ts","../src/lib/voxel/gaussian-bvh.ts","../src/lib/voxel/gpu-voxelization.ts","../src/lib/voxel/voxel-filter.ts","../src/lib/writers/write-voxel.ts","../src/lib/write.ts","../src/lib/process.ts"],"sourcesContent":["/**\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\n    constructor(columns: Column[]) {\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    }\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 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    clone(): DataTable {\n        return new DataTable(this.columns.map(c => c.clone()));\n    }\n\n    // return a new table containing the rows referenced in indices\n    permuteRows(indices: Uint32Array | number[]): DataTable {\n        const result = new DataTable(this.columns.map((c) => {\n            const constructor = c.data.constructor as new (length: number) => TypedArray;\n            return new Column(c.name, new constructor(indices.length));\n        }));\n\n        for (let i = 0; i < this.numColumns; ++i) {\n            const src = this.getColumn(i).data;\n            const dst = result.getColumn(i).data;\n            for (let j = 0; j < indices.length; j++) {\n                dst[j] = src[indices[j]];\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 `permuteRows` 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 { Column, DataTable, TypedArray } from './data-table';\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 * @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        // nothing to combine\n        return dataTables[0];\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 much match\n    const columns = dataTables[0].columns.slice();\n    for (let i = 1; i < dataTables.length; ++i) {\n        const dataTable = dataTables[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 = dataTables.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);\n\n    // copy data\n    let rowOffset = 0;\n    for (let i = 0; i < dataTables.length; ++i) {\n        const dataTable = dataTables[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 { 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// 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        // rotate spherical harmonic coefficients, up to band 3\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\nexport { RotateSH };\n","import { Mat3, Mat4, Quat, Vec3 } from 'playcanvas';\n\nimport { DataTable } from './data-table';\nimport { RotateSH } from '../utils/rotate-sh';\n\nconst shNames = new Array(45).fill('').map((_, i) => `f_rest_${i}`);\n\nconst v = new Vec3();\nconst q = new Quat();\n\n/**\n * Applies a spatial transformation to splat data in-place.\n *\n * Transforms position, rotation, scale, and spherical harmonics data.\n * The transformation is applied as: scale first, then rotation, then translation.\n *\n * @param dataTable - The DataTable to transform (modified in-place).\n * @param t - Translation vector.\n * @param r - Rotation quaternion.\n * @param s - Uniform scale factor.\n *\n * @example\n * ```ts\n * import { Vec3, Quat } from 'playcanvas';\n *\n * // Scale by 2x, rotate 90° around Y, translate up\n * transform(dataTable, new Vec3(0, 5, 0), new Quat().setFromEulerAngles(0, 90, 0), 2.0);\n * ```\n */\nconst transform = (dataTable: DataTable, t: Vec3, r: Quat, s: number): void => {\n    const mat = new Mat4().setTRS(t, r, new Vec3(s, s, s));\n    const mat3 = new Mat3().setFromQuat(r);\n    const rotateSH = new RotateSH(mat3);\n\n    const hasTranslation = ['x', 'y', 'z'].every(c => dataTable.hasColumn(c));\n    const hasRotation = ['rot_0', 'rot_1', 'rot_2', 'rot_3'].every(c => dataTable.hasColumn(c));\n    const hasScale = ['scale_0', 'scale_1', 'scale_2'].every(c => dataTable.hasColumn(c));\n    const shBands = { '9': 1, '24': 2, '-1': 3 }[shNames.findIndex(v => !dataTable.hasColumn(v))] ?? 0;\n    const shCoeffs = new Float32Array([0, 3, 8, 15][shBands]);\n\n    const row: any = {};\n    for (let i = 0; i < dataTable.numRows; ++i) {\n        dataTable.getRow(i, row);\n\n        if (hasTranslation) {\n            v.set(row.x, row.y, row.z);\n            mat.transformPoint(v, v);\n            row.x = v.x;\n            row.y = v.y;\n            row.z = v.z;\n        }\n\n        if (hasRotation) {\n            q.set(row.rot_1, row.rot_2, row.rot_3, row.rot_0).mul2(r, q);\n            row.rot_0 = q.w;\n            row.rot_1 = q.x;\n            row.rot_2 = q.y;\n            row.rot_3 = q.z;\n        }\n\n        if (hasScale) {\n            row.scale_0 = Math.log(Math.exp(row.scale_0) * s);\n            row.scale_1 = Math.log(Math.exp(row.scale_1) * s);\n            row.scale_2 = Math.log(Math.exp(row.scale_2) * s);\n        }\n\n        if (shBands > 0) {\n            for (let j = 0; j < 3; ++j) {\n                for (let k = 0; k < shCoeffs.length; ++k) {\n                    shCoeffs[k] = row[shNames[k + j * shCoeffs.length]];\n                }\n\n                rotateSH.apply(shCoeffs);\n\n                for (let k = 0; k < shCoeffs.length; ++k) {\n                    row[shNames[k + j * shCoeffs.length]] = shCoeffs[k];\n                }\n            }\n        }\n\n        dataTable.setRow(i, row);\n    }\n};\n\nexport { transform };\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 * Progress node representing a step in a nested progress tree.\n * Walk up via `parent` to access enclosing steps.\n */\ninterface ProgressNode {\n    /** Current step number at this level. */\n    step: number;\n    /** Total number of steps at this level. */\n    totalSteps: number;\n    /** Name of the current step (undefined for anonymous steps). */\n    stepName?: string;\n    /** Parent node (undefined for root level). */\n    parent?: ProgressNode;\n    /** Nesting depth (0 for root level). */\n    depth: number;\n}\n\n/**\n * Logger interface for injectable logging implementation.\n */\ninterface Logger {\n    /** Log normal messages. */\n    log(...args: any[]): void;\n    /** Log warning messages. */\n    warn(...args: any[]): void;\n    /** Log error messages. */\n    error(...args: any[]): void;\n    /** Log debug/verbose messages. */\n    debug(...args: any[]): void;\n    /** Output data to stdout (for piping). */\n    output(text: string): void;\n    /** Called on progress step updates with the current node. */\n    onProgress(node: ProgressNode): void;\n}\n\n/**\n * Default logger implementation (browser-safe).\n */\nconst defaultLogger: Logger = {\n    log: (...args) => console.log(...args),\n    warn: (...args) => console.warn(...args),\n    error: (...args) => console.error(...args),\n    debug: (...args) => console.log(...args),\n    output: text => console.log(text),\n    onProgress: (node) => {\n        // step 0 is the begin notification - nothing to print\n        if (node.step === 0) return;\n\n        const indent = '  '.repeat(node.depth);\n        const name = node.stepName ?? '';\n        console.log(`${indent}[${node.step}/${node.totalSteps}] ${name}`);\n    }\n};\n\nlet impl: Logger = defaultLogger;\nlet quiet = false;\n\n/**\n * Progress tracking with nested step support.\n * Access via logger.progress.begin(), logger.progress.step()\n */\nclass Progress {\n    private currentNode: ProgressNode | undefined;\n\n    /**\n     * Start a multi-step progress operation. Creates a new node with current as parent.\n     * Calls onProgress with step: 0 to notify consumers of the new progress block.\n     * @param totalSteps - Total number of steps in the operation.\n     */\n    begin(totalSteps: number) {\n        this.currentNode = {\n            step: 0,\n            totalSteps,\n            stepName: undefined,\n            parent: this.currentNode,\n            depth: (this.currentNode?.depth ?? -1) + 1\n        };\n\n        if (!quiet) impl.onProgress(this.currentNode);\n    }\n\n    /**\n     * Advance to the next step. Auto-increments the step counter.\n     * Auto-ends when all steps are complete.\n     * @param name - Optional name of the step.\n     */\n    step(name?: string) {\n        if (!this.currentNode) return;\n\n        this.currentNode.step++;\n        this.currentNode.stepName = name;\n\n        if (!quiet) impl.onProgress(this.currentNode);\n\n        // Auto-end when all steps complete\n        if (this.currentNode.step === this.currentNode.totalSteps) {\n            this.currentNode = this.currentNode.parent;\n        }\n    }\n}\n\n/**\n * Global logger instance with injectable implementation.\n * Use setLogger() to provide a custom implementation (e.g., Node.js with process.stdout).\n * Use setQuiet() to suppress log/warn/progress output.\n */\nconst logger = {\n    /**\n     * Progress tracking with nested step support.\n     * Call begin(n) to start, then step() n times. Auto-ends when complete.\n     */\n    progress: new Progress(),\n\n    /**\n     * Set a custom logger implementation.\n     * @param l - The logger implementation to use.\n     */\n    setLogger(l: Logger) {\n        impl = l;\n    },\n\n    /**\n     * Set quiet mode. When quiet, log/warn/progress are suppressed. Errors always show.\n     * @param q - Whether to enable quiet mode.\n     */\n    setQuiet(q: boolean) {\n        quiet = q;\n    },\n\n    /**\n     * Log normal messages. Suppressed in quiet mode.\n     * @param args - The arguments to log.\n     */\n    log(...args: any[]) {\n        if (!quiet) impl.log(...args);\n    },\n\n    /**\n     * Log warning messages. Suppressed in quiet mode.\n     * @param args - The arguments to log.\n     */\n    warn(...args: any[]) {\n        if (!quiet) impl.warn(...args);\n    },\n\n    /**\n     * Log error messages. Always shown, even in quiet mode.\n     * @param args - The arguments to log.\n     */\n    error(...args: any[]) {\n        impl.error(...args);\n    },\n\n    /**\n     * Log debug/verbose messages. Suppressed in quiet mode.\n     * @param args - The arguments to log.\n     */\n    debug(...args: any[]) {\n        if (!quiet) impl.debug(...args);\n    },\n\n    /**\n     * Output data to stdout (for piping). Always shown, even in quiet mode.\n     * @param text - The text to output.\n     */\n    output(text: string) {\n        impl.output(text);\n    }\n};\n\nexport { logger };\nexport type { Logger, ProgressNode };\n","import { DataTable } from './data-table';\nimport { logger } from '../utils/logger.js';\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                // logger.debug('sorting', end - start);\n                generate(indices.subarray(start, end));\n            }\n\n            start = end;\n        }\n    };\n\n    generate(indices);\n};\n\nexport { sortMortonOrder };\n","import { DataTable } from './data-table';\nimport { logger } from '../utils/logger.js';\n\n/**\n * Sorts the provided indices by visibility score (descending order).\n *\n * Visibility is computed as: linear_opacity * volume\n * where:\n * - linear_opacity = sigmoid(opacity) = 1 / (1 + exp(-opacity))\n * - volume = exp(scale_0) * exp(scale_1) * exp(scale_2)\n *\n * After calling this function, indices[0] will contain the index of the most\n * visible splat, indices[1] the second most visible, and so on.\n *\n * @param dataTable - The DataTable containing splat data.\n * @param indices - Array of indices to sort in-place.\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\n    if (indices.length === 0) {\n        return;\n    }\n\n    const opacity = opacityCol.data;\n    const scale0 = scale0Col.data;\n    const scale1 = scale1Col.data;\n    const scale2 = scale2Col.data;\n\n    // Compute visibility scores for each splat\n    const scores = new Float32Array(indices.length);\n    for (let i = 0; i < indices.length; i++) {\n        const ri = indices[i];\n\n        // Convert logit opacity to linear using sigmoid\n        const logitOpacity = opacity[ri];\n        const linearOpacity = 1 / (1 + Math.exp(-logitOpacity));\n\n        // Convert log scales to linear and compute volume\n        // volume = exp(scale_0) * exp(scale_1) * exp(scale_2) = exp(scale_0 + scale_1 + scale_2)\n        const volume = Math.exp(scale0[ri] + scale1[ri] + scale2[ri]);\n\n        // Visibility score is opacity * volume\n        scores[i] = linearOpacity * volume;\n    }\n\n    // Sort indices by score (descending - most visible first)\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) => scores[b] - scores[a]);\n\n    // Apply the sorted order to indices\n    const tmpIndices = indices.slice();\n    for (let i = 0; i < indices.length; i++) {\n        indices[i] = tmpIndices[order[i]];\n    }\n};\n\nexport { sortByVisibility };\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 { 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/data-table';\nimport { ReadSource } from '../io/read';\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    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\n        currentSectionDataOffset += sectionDataSize + totalBucketStorageSize;\n    }\n\n    if (splatIndex !== numSplats) {\n        throw new Error(`Splat count mismatch: expected ${numSplats}, processed ${splatIndex}`);\n    }\n\n    return new DataTable(columns);\n};\n\nexport { readKsplat };\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 { Vec3 } from 'playcanvas';\n\nimport { Column, DataTable } from '../data-table/data-table';\nimport { dirname, join, ReadFileSystem, ReadSource, readFile } from '../io/read';\nimport { Options } from '../types';\n\nconst kSH_C0 = 0.28209479177387814;\nconst SQRT_2 = 1.414213562373095;\nconst SQRT_2_INV = 0.7071067811865475;\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// parameters used to convert LCC data into GSplatData\ntype LccParam = {\n    totalSplats: number;\n    targetLod: number;\n    compressInfo: CompressInfo;\n    unitInfos: Array<LccUnitInfo>;\n    dataSource: ReadSource;\n    shSource?: ReadSource;\n}\n\ntype ProcessUnitContext = {\n    info: LccUnitInfo;\n    targetLod: number;\n    dataSource: ReadSource;\n    shSource?: ReadSource;\n    compressInfo: CompressInfo;\n    propertyOffset: number;\n    properties: Record<string, Float32Array>;\n    properties_f_rest: Float32Array[] | null;\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    const compressInfo: CompressInfo = {\n        scaleMin,\n        scaleMax,\n        shMin,\n        shMax,\n        envScaleMin,\n        envScaleMax,\n        envShMin,\n        envShMax\n    };\n\n    return compressInfo;\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 mixVec3 = (min: Vec3, max: Vec3, v: Vec3): Vec3 => {\n    return new Vec3(\n        mix(min.x, max.x, v.x),\n        mix(min.y, max.y, v.y),\n        mix(min.z, max.z, v.z)\n    );\n};\n\nconst decodePacked_11_10_11 = (res: Vec3, enc: number) => {\n    res.x = (enc & 0x7FF) / 2047.0;\n    res.y = ((enc >> 11) & 0x3FF) / 1023.0;\n    res.z = ((enc >> 21) & 0x7FF) / 2047.0;\n};\n\nconst decodeRotation = (v: number) => {\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    let sum = qx * qx + qy * qy + qz * qz;\n    sum = Math.min(1.0, sum);\n    const qw = Math.sqrt(1 - sum);\n\n    if (d3 === 0) {\n        return [qw, qx, qy, qz];\n    } else if (d3 === 1) {\n        return [qx, qw, qy, qz];\n    } else if (d3 === 2) {\n        return [qx, qy, qw, qz];\n    }\n    return [qx, qy, qz, qw];\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 createStorage = (length: number) => new Float32Array(length);\n\nconst initProperties = (length: number): Record<string, Float32Array> => {\n    const props: Record<string, Float32Array> = {};\n    for (const key of floatProps) {\n        props[`property_${key}`] = createStorage(length);\n    }\n    return props;\n};\n\nconst vec3 = new Vec3();\n\nconst decodeSplat = (\n    dataView: DataView,\n    shDataView: DataView | null,\n    i: number,\n    compressInfo: CompressInfo,\n    unitProperties: Record<string, Float32Array>,\n    unitProperties_f_rest: Float32Array[] | null\n) => {\n    const off = i * 32;\n\n    // position\n    unitProperties.property_x[i] = dataView.getFloat32(off + 0, true);\n    unitProperties.property_y[i] = dataView.getFloat32(off + 4, true);\n    unitProperties.property_z[i] = dataView.getFloat32(off + 8, true);\n\n    // decode color\n    unitProperties.property_f_dc_0[i] = invSH0ToColor(dataView.getUint8(off + 12) / 255.0);\n    unitProperties.property_f_dc_1[i] = invSH0ToColor(dataView.getUint8(off + 13) / 255.0);\n    unitProperties.property_f_dc_2[i] = invSH0ToColor(dataView.getUint8(off + 14) / 255.0);\n    unitProperties.property_opacity[i] = invSigmoid(dataView.getUint8(off + 15) / 255.0);\n\n    // decode scale\n    const scaleMin = compressInfo.scaleMin;\n    const scaleMax = compressInfo.scaleMax;\n    unitProperties.property_scale_0[i] = invLinearScale(mix(scaleMin.x, scaleMax.x, dataView.getUint16(off + 16, true) / 65535.0));\n    unitProperties.property_scale_1[i] = invLinearScale(mix(scaleMin.y, scaleMax.y, dataView.getUint16(off + 18, true) / 65535.0));\n    unitProperties.property_scale_2[i] = invLinearScale(mix(scaleMin.z, scaleMax.z, dataView.getUint16(off + 20, true) / 65535.0));\n\n    // decode rotation\n    const q = decodeRotation(dataView.getUint32(off + 22, true));\n    unitProperties.property_rot_0[i] = q[3];// w\n    unitProperties.property_rot_1[i] = q[0];// x\n    unitProperties.property_rot_2[i] = q[1];// y\n    unitProperties.property_rot_3[i] = q[2];// z\n\n    // normal\n    unitProperties.property_nx[i] = dataView.getUint16(off + 26, true);\n    unitProperties.property_ny[i] = dataView.getUint16(off + 28, true);\n    unitProperties.property_nz[i] = dataView.getUint16(off + 30, true);\n\n    // SH\n    if (shDataView && unitProperties_f_rest) {\n        const shOff = off * 2;\n        const SHValues = Array.from({ length: 15 }, (_, idx) => shDataView.getUint32(shOff + idx * 4, true));\n        const { shMin, shMax } = compressInfo;\n        const vecSHValues = SHValues.map((sh) => {\n            decodePacked_11_10_11(vec3, sh);\n            return mixVec3(shMin, shMax, vec3);\n        });\n\n        for (let j = 0; j < 15; j++) {\n            unitProperties_f_rest[j][i] = vecSHValues[j].x;\n            unitProperties_f_rest[j + 15][i] = vecSHValues[j].y;\n            unitProperties_f_rest[j + 30][i] = vecSHValues[j].z;\n        }\n    }\n};\n\nconst processUnit = async (ctx: ProcessUnitContext) => {\n    const {\n        info,\n        targetLod,\n        dataSource,\n        shSource,\n        compressInfo,\n        propertyOffset,\n        properties,\n        properties_f_rest\n    } = ctx;\n\n    const lod = info.lods[targetLod];\n    const unitSplats = lod.points;\n    const offset = Number(lod.offset);\n    const size = lod.size;\n\n    if (unitSplats === 0) {\n        return propertyOffset;\n    }\n\n    // load data using range read\n    const dataBytes = await dataSource.read(offset, offset + size).readAll();\n    const dataView = new DataView(dataBytes.buffer, dataBytes.byteOffset, dataBytes.byteLength);\n\n    // load sh data using range read\n    let shDataView: DataView | null = null;\n    if (shSource) {\n        const shBytes = await shSource.read(offset * 2, offset * 2 + size * 2).readAll();\n        shDataView = new DataView(shBytes.buffer, shBytes.byteOffset, shBytes.byteLength);\n    }\n\n    const unitProperties = initProperties(unitSplats);\n    const unitProperties_f_rest = shSource ? Array.from({ length: 45 }, () => new Float32Array(unitSplats)) : null;\n\n    for (let i = 0; i < unitSplats; i++) {\n        decodeSplat(dataView, shDataView, i, compressInfo, unitProperties, unitProperties_f_rest);\n    }\n\n    for (const key of floatProps) {\n        properties[`property_${key}`].set(unitProperties[`property_${key}`], propertyOffset);\n    }\n\n    if (unitProperties_f_rest) {\n        for (let j = 0; j < 45; j++) {\n            properties_f_rest[j].set(unitProperties_f_rest[j], propertyOffset);\n        }\n    }\n\n    return propertyOffset + unitSplats;\n};\n\n// this function would stream data directly into GSplatData buffers\nconst deserializeFromLcc = async (param: LccParam) => {\n    const { totalSplats, unitInfos, targetLod, dataSource, shSource, compressInfo } = param;\n\n    // properties to GSplatData\n    const properties: Record<string, Float32Array> = initProperties(totalSplats);\n    const properties_f_rest = shSource ? Array.from({ length: 45 }, () => createStorage(totalSplats)) : null;\n\n    let propertyOffset = 0;\n    for (const info of unitInfos) {\n        propertyOffset = await processUnit({\n            info,\n            targetLod,\n            dataSource,\n            shSource,\n            compressInfo,\n            propertyOffset,\n            properties,\n            properties_f_rest\n        });\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    ];\n\n    return new DataTable(columns);\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    // 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        const q = decodeRotation(dataView.getUint32(off + 22, true));\n        columns[10].data[i] = q[3]; // rot_0 (w)\n        columns[11].data[i] = q[0]; // rot_1 (x)\n        columns[12].data[i] = q[1]; // rot_2 (y)\n        columns[13].data[i] = q[2]; // rot_3 (z)\n\n        // skip normal 26-32\n\n        if (hasSH) {\n            for (let j = 0; j < 15; ++j) {\n                decodePacked_11_10_11(vec3, dataView.getUint32(off + 32 + j * 4, true));\n\n                columns[14 + j].data[i] = mix(shMin.x, shMax.x, vec3.x);\n                columns[14 + j + 15].data[i] = mix(shMin.y, shMax.y, vec3.y);\n                columns[14 + j + 30].data[i] = mix(shMin.z, shMax.z, vec3.z);\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 * @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, one per LOD level plus 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    const dataSource = await fileSystem.createSource(relatedFilename('data.bin'));\n    const shSource = hasSH ? await fileSystem.createSource(relatedFilename('shcoef.bin')) : null;\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    const result = [];\n\n    try {\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            const dataTable = await deserializeFromLcc({\n                totalSplats,\n                unitInfos,\n                targetLod: inputLod,\n                dataSource,\n                shSource: shSource ?? undefined,\n                compressInfo\n            });\n\n            dataTable.addColumn(new Column('lod', new Float32Array(totalSplats).fill(outputLod)));\n\n            result.push(dataTable);\n        }\n    } finally {\n        // cleanup\n        dataSource.close();\n        if (shSource) {\n            shSource.close();\n        }\n    }\n\n    // load environment and tag as lod -1\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        result.push(envDataTable);\n    } catch (err) {\n        console.warn('Failed to load environment.bin', err);\n    }\n\n    return result;\n};\n\nexport { readLcc };\n","import { Column, DataTable } from '../data-table/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/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/data-table';\nimport { ReadSource, ReadStream } from '../io/read';\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    // 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        } 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        }\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    if (isCompressedPly(plyData)) {\n        return decompressPly(plyData);\n    }\n\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\n    return vertexElement.dataTable;\n};\n\nexport { PlyData, readPly };\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 { Column, DataTable } from '../data-table/data-table';\nimport { dirname, join, ReadFileSystem, readFile } from '../io/read';\nimport { WebPCodec } from '../utils/webp-codec';\n\ntype Meta = {\n    version: number;\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    for (let i = 0; i < count; i++) {\n        const o = i * 4;\n        xs[i] = lo[o + 0] | (hi[o + 0] << 8);\n    }\n    const ys = new Uint16Array(count);\n    for (let i = 0; i < count; i++) {\n        const o = i * 4;\n        ys[i] = lo[o + 1] | (hi[o + 1] << 8);\n    }\n    const zs = new Uint16Array(count);\n    for (let i = 0; i < count; i++) {\n        const o = i * 4;\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 * @param fileSystem - The file system to read from\n * @param filename - Path to meta.json (relative paths resolved from its directory)\n * @returns DataTable with Gaussian splat data\n * @ignore\n */\nconst readSog = async (fileSystem: ReadFileSystem, filename: string): Promise<DataTable> => {\n    const decoder = await WebPCodec.create();\n\n    // Resolve paths relative to the meta.json directory\n    const baseDir = dirname(filename);\n    const load = (name: string) => readFile(fileSystem, baseDir ? join(baseDir, name) : name);\n\n    // meta.json\n    const metaBytes = await load('meta.json');\n    const meta = JSON.parse(new TextDecoder().decode(metaBytes)) as Meta;\n    const count = meta.count;\n\n    // Prepare output columns\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    // means: two textures means_l and means_u\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    const total = width * height;\n    if (total < 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        const lx = xMin + xScale * (xs[i] / 65535);\n        const ly = yMin + yScale * (ys[i] / 65535);\n        const lz = zMin + zScale * (zs[i] / 65535);\n        xCol[i] = invLogTransform(lx);\n        yCol[i] = invLogTransform(ly);\n        zCol[i] = invLogTransform(lz);\n    }\n\n    // quats\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 identity\n            r0[i] = 0; r1[i] = 0; r2[i] = 0; r3[i] = 1;\n            continue;\n        }\n        const [x, y, z, wq] = unpackQuat(qr[o], qr[o + 1], qr[o + 2], tag);\n        r0[i] = x; r1[i] = y; r2[i] = z; r3[i] = wq;\n    }\n\n    // scales: labels + 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    for (let i = 0; i < count; i++) {\n        const o = i * 4;\n        (columns[3].data as Float32Array)[i] = sCode[sl[o]];\n        (columns[4].data as Float32Array)[i] = sCode[sl[o + 1]];\n        (columns[5].data as Float32Array)[i] = sCode[sl[o + 2]];\n    }\n\n    // colors + opacity: sh0.webp encodes 3 labels + opacity byte\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\n    // Note: If present, SH higher bands (shN) are reconstructed into columns below.\n    // Higher-order SH (optional)\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 } = decoder.decodeRGBA(labelsWebp);\n\n            // Prepare f_rest_i columns\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    }\n\n    return new DataTable(columns);\n};\n\nexport { readSog };\n","import { Column, DataTable } from '../data-table/data-table';\nimport { ReadSource } from '../io/read';\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    // 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\n            (columns[10].data as Float32Array)[splatIndex] = 0.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] = 1.0;\n        }\n    }\n\n    return new DataTable(columns);\n};\n\nexport { readSplat };\n","import { Column, DataTable } from '../data-table/data-table';\nimport { ReadSource } from '../io/read';\n\n// See https://github.com/nianticlabs/spz for reference implementation\n\nconst decompressGZIP = async (data: Uint8Array): Promise<Uint8Array> => {\n    // Convert to ArrayBuffer slice to satisfy Blob constructor type requirements\n    const arrayBuffer = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength) as ArrayBuffer;\n    const blob = new Blob([arrayBuffer], { type: 'application/gzip' });\n    const ds = new DecompressionStream('gzip');\n    const decompressionStream = blob.stream().pipeThrough(ds);\n    const decompressed = await new Response(decompressionStream).arrayBuffer();\n    return new Uint8Array(decompressed);\n};\n\n// Coefficient used by niantic labs spz to have better results with Spherical harmonics.\nconst SH_C0_2 = 0.15;\nfunction inverseConvertColorFromSPZ(y: number) {\n    return (y / 255.0 - 0.5) / SH_C0_2;\n}\n\nfunction getFixed24(positionsView: DataView, elementIndex: number, memberIndex: number) {\n    const sizeofMember = 3; // 24 bits is 3 bytes\n    const stride = 3 * sizeofMember; // x y z\n    let fixed32 = positionsView.getUint8(elementIndex * stride + memberIndex * sizeofMember + 0);\n    fixed32 |= positionsView.getUint8(elementIndex * stride + memberIndex * sizeofMember + 1) << 8;\n    fixed32 |= positionsView.getUint8(elementIndex * stride + memberIndex * sizeofMember + 2) << 16;\n    fixed32 |= (fixed32 & 0x800000) ? 0xff000000 : 0;  // sign extension\n\n    return fixed32;\n}\n\nconst HARMONICS_COMPONENT_COUNT = [0, 9, 24, 45];\n\n/**\n * Reads a .spz file containing Niantic Labs compressed Gaussian splat data.\n *\n * The .spz format uses GZIP compression and fixed-point encoding to achieve\n * compact file sizes. Supports version 2 and 3 of the format.\n *\n * @see https://github.com/nianticlabs/spz\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    // Load complete file\n    let fileBuffer = await source.read().readAll();\n\n    // Check if file is GZip compressed\n    const magicSize = 4;\n    let magicView = new DataView(fileBuffer.buffer, fileBuffer.byteOffset, magicSize);\n\n    // If file is GZip compressed, decompress it first.\n    if (magicView.getUint16(0) === 0x1F8B) { // '1F 8B' is the magic for gzip\n        fileBuffer = await decompressGZIP(fileBuffer);\n        magicView = new DataView(fileBuffer.buffer, fileBuffer.byteOffset, magicSize);\n    }\n\n    const magic = magicView.getUint32(0, true);\n    if (magic !== 0x5053474e) { // NGSP\n        throw new Error('invalid file header');\n    }\n\n    const HEADER_SIZE = 16;\n    const totalSize = fileBuffer.length;\n\n    if (totalSize < HEADER_SIZE) {\n        throw new Error('File too small to be valid .spz format');\n    }\n\n    // Parse header\n    const header = new DataView(fileBuffer.buffer, fileBuffer.byteOffset, HEADER_SIZE);\n\n    const version = header.getUint32(4, true);\n    if (!(version === 2 || version === 3)) {\n        throw new Error(`Unsupported version ${version}`);\n    }\n\n    const numSplats = header.getUint32(8, true);\n    const shDegree = header.getUint8(12);\n    const fractionalBits = header.getUint8(13);\n\n    const positionsByteSize = numSplats * 3 * 3; // 3 * 24bit values\n    const alphasByteSize = numSplats; // u8\n    const colorsByteSize = numSplats * 3; // u8 * 3\n    const scalesByteSize = numSplats * 3; // u8 * 3\n    const rotationsByteSize = numSplats * 3; // u8 * 3\n    const harmonicsComponentCount = HARMONICS_COMPONENT_COUNT[shDegree];\n    const shByteSize = numSplats * harmonicsComponentCount;\n\n    const positionsView = new DataView(fileBuffer.buffer, fileBuffer.byteOffset + HEADER_SIZE, positionsByteSize);\n    const alphasView = new DataView(fileBuffer.buffer, fileBuffer.byteOffset + HEADER_SIZE + positionsByteSize, alphasByteSize);\n    const colorsView = new DataView(fileBuffer.buffer, fileBuffer.byteOffset + HEADER_SIZE + positionsByteSize + alphasByteSize, colorsByteSize);\n    const scalesView = new DataView(fileBuffer.buffer, fileBuffer.byteOffset + HEADER_SIZE + positionsByteSize + alphasByteSize + colorsByteSize, scalesByteSize);\n    const rotationsView = new DataView(fileBuffer.buffer, fileBuffer.byteOffset + HEADER_SIZE + positionsByteSize + alphasByteSize + colorsByteSize + scalesByteSize, rotationsByteSize);\n    const shView = new DataView(fileBuffer.buffer, fileBuffer.byteOffset + HEADER_SIZE + positionsByteSize + alphasByteSize + colorsByteSize + scalesByteSize + rotationsByteSize, shByteSize);\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    // Add spherical harmonics columns based on maximum degree found\n    for (let i = 0; i < harmonicsComponentCount; i++) {\n        columns.push(new Column(`f_rest_${i}`, new Float32Array(numSplats)));\n    }\n\n    const scale = 1.0 / (1 << fractionalBits);\n    for (let splatIndex = 0; splatIndex < numSplats; splatIndex++) {\n        // Read position (3 × uint24)\n        const x = getFixed24(positionsView, splatIndex, 0) * scale;\n        const y = getFixed24(positionsView, splatIndex, 1) * scale;\n        const z = getFixed24(positionsView, splatIndex, 2) * scale;\n\n        // Read scale (3 × uint8 log encoded)\n        const scaleX = scalesView.getUint8(splatIndex * 3 + 0) / 16.0 - 10.0;\n        const scaleY = scalesView.getUint8(splatIndex * 3 + 1) / 16.0 - 10.0;\n        const scaleZ = scalesView.getUint8(splatIndex * 3 + 2) / 16.0 - 10.0;\n\n        // Read color and opacity (4 × uint8)\n        const red = colorsView.getUint8(splatIndex * 3 + 0);\n        const green = colorsView.getUint8(splatIndex * 3 + 1);\n        const blue = colorsView.getUint8(splatIndex * 3 + 2);\n        const opacity = alphasView.getUint8(splatIndex);\n\n        // Read rotation quaternion (4 × uint8)\n        const rotation = [0.0, 0.0, 0.0, 0.0];\n        if (version === 2) {\n            rotation[1] = rotationsView.getUint8(splatIndex * 3 + 0);\n            rotation[2] = rotationsView.getUint8(splatIndex * 3 + 1);\n            rotation[3] = rotationsView.getUint8(splatIndex * 3 + 2);\n        } else if (version === 3) {\n            // Copied from https://github.com/nianticlabs/spz/blob/e2101d6924b3936a6fb630cd4a881cb610c57d77/src/cc/load-spz.cc#L347\n            let packedRotation = rotationsView.getUint32(splatIndex);\n            const c_mask = (1 << 9) - 1;\n\n            const largestRotIndex = packedRotation >> 30;\n            let sum_squares = 0;\n            for (let i = 3; i >= 0; --i) {\n                if (i !== largestRotIndex) {\n                    const mag = packedRotation & c_mask;\n                    const negbit = (packedRotation >> 9) & 1;\n                    packedRotation >>= 10;\n                    rotation[i] = Math.SQRT1_2 * (mag) / c_mask;\n                    if (negbit === 1) {\n                        rotation[i] = -rotation[i];\n                    }\n                    sum_squares += rotation[i] * rotation[i];\n                }\n            }\n            rotation[largestRotIndex] = Math.sqrt(1.0 - sum_squares);\n        }\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 (No need to apply log since they are already log-encoded)\n        (columns[3].data as Float32Array)[splatIndex] = scaleX;\n        (columns[4].data as Float32Array)[splatIndex] = scaleY;\n        (columns[5].data as Float32Array)[splatIndex] = scaleZ;\n\n        // Store color (convert from uint8 back to spherical harmonics)\n        // Colors are already between 0 and 255 but multiplied by SH_C0_2. We need to revert the function to apply the correct SH_C0\n        (columns[6].data as Float32Array)[splatIndex] = inverseConvertColorFromSPZ(red);\n        (columns[7].data as Float32Array)[splatIndex] = inverseConvertColorFromSPZ(green);\n        (columns[8].data as Float32Array)[splatIndex] = inverseConvertColorFromSPZ(blue);\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])\n\n        let rot0Norm = 0.0;\n        const rot1Norm = (rotation[1] / 127.5) - 1.0;\n        const rot2Norm = (rotation[2] / 127.5) - 1.0;\n        const rot3Norm = (rotation[3] / 127.5) - 1.0;\n        if (version === 2) {\n            const rotationDot = rot1Norm * rot1Norm + rot2Norm * rot2Norm + rot3Norm * rot3Norm;\n            rot0Norm = Math.sqrt(Math.max(0.0, 1.0 - rotationDot));\n        } else if (version === 3) {\n            rot0Norm = (rotation[0] / 127.5) - 1.0;\n        }\n\n        (columns[10].data as Float32Array)[splatIndex] = rot0Norm;\n        (columns[11].data as Float32Array)[splatIndex] = rot1Norm;\n        (columns[12].data as Float32Array)[splatIndex] = rot2Norm;\n        (columns[13].data as Float32Array)[splatIndex] = rot3Norm;\n\n        // Store spherical harmonics\n        for (let i = 0; i < harmonicsComponentCount; i++) {\n            const channel = i % 3;\n            const coeff = Math.floor(i / 3);\n            const col = channel * (harmonicsComponentCount / 3) + coeff;\n            const shCoef = shView.getUint8(splatIndex * harmonicsComponentCount + i);\n            (columns[14 + col].data as Float32Array)[splatIndex] = (shCoef - 128) / 128;\n        }\n    }\n\n    return new DataTable(columns);\n};\n\nexport { readSpz };\n","import { Vec3 } from 'playcanvas';\n\nimport { logger } from '../utils/logger';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/** All 64 bits set (as unsigned 32-bit) */\nconst SOLID_MASK = 0xFFFFFFFF >>> 0;\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// Morton Code Functions\n// ============================================================================\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; // Running power: 2^(i*3), starts at 2^0 = 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 * Decode Morton code to block coordinates.\n *\n * @param m - Morton code\n * @returns Tuple of [x, y, z] block coordinates\n */\nfunction mortonToXYZ(m: number): [number, number, number] {\n    let x = 0, y = 0, z = 0;\n    let bit = 1;\n    while (m > 0) {\n        const triplet = m % 8;\n        if (triplet & 1) x |= bit;\n        if (triplet & 2) y |= bit;\n        if (triplet & 4) z |= bit;\n        bit <<= 1;\n        m = Math.trunc(m / 8);\n    }\n    return [x, y, z];\n}\n\n// ============================================================================\n// Utility Functions\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; // Ensure unsigned\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\n/**\n * Get the offset to a child node given a parent's child mask and octant.\n * Uses popcount to count how many children come before this octant.\n *\n * @param mask - 8-bit child mask from parent node\n * @param octant - Octant index (0-7)\n * @returns Offset from base child pointer\n */\nfunction getChildOffset(mask: number, octant: number): number {\n    const prefix = (1 << octant) - 1;\n    return popcount(mask & prefix);\n}\n\n// ============================================================================\n// Block Accumulator\n// ============================================================================\n\n/**\n * Accumulator for streaming voxelization results.\n * Stores blocks using Morton codes for efficient octree construction.\n */\nclass BlockAccumulator {\n    /** Morton codes for mixed blocks */\n    private _mixedMorton: number[] = [];\n\n    /** Interleaved voxel masks for mixed blocks: [lo0, hi0, lo1, hi1, ...] */\n    private _mixedMasks: number[] = [];\n\n    /** Morton codes for solid blocks (mask is implicitly all 1s) */\n    private _solidMorton: number[] = [];\n\n    /**\n     * Add a non-empty block to the accumulator.\n     * Automatically classifies as solid or mixed based on mask values.\n     *\n     * @param morton - Morton code encoding block position\n     * @param lo - Lower 32 bits of voxel mask\n     * @param hi - Upper 32 bits of voxel mask\n     */\n    addBlock(morton: number, lo: number, hi: number): void {\n        if (isEmpty(lo, hi)) {\n            // Empty blocks are discarded\n            return;\n        }\n\n        if (isSolid(lo, hi)) {\n            // Solid blocks only need Morton code\n            this._solidMorton.push(morton);\n        } else {\n            // Mixed blocks need Morton code + mask\n            this._mixedMorton.push(morton);\n            this._mixedMasks.push(lo, hi);\n        }\n    }\n\n    /**\n     * Get all mixed blocks.\n     *\n     * @returns Object with morton codes and interleaved masks\n     */\n    getMixedBlocks(): { morton: number[]; masks: number[] } {\n        return {\n            morton: this._mixedMorton,\n            masks: this._mixedMasks\n        };\n    }\n\n    /**\n     * Get all solid blocks.\n     *\n     * @returns Array of Morton codes\n     */\n    getSolidBlocks(): number[] {\n        return this._solidMorton;\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._mixedMorton.length + this._solidMorton.length;\n    }\n\n    /**\n     * Get number of mixed blocks.\n     *\n     * @returns Count of mixed blocks\n     */\n    get mixedCount(): number {\n        return this._mixedMorton.length;\n    }\n\n    /**\n     * Get number of solid blocks.\n     *\n     * @returns Count of solid blocks\n     */\n    get solidCount(): number {\n        return this._solidMorton.length;\n    }\n\n    /**\n     * Clear all accumulated blocks.\n     */\n    clear(): void {\n        this._mixedMorton.length = 0;\n        this._mixedMasks.length = 0;\n        this._solidMorton.length = 0;\n    }\n}\n\n// ============================================================================\n// Sparse Octree Types\n// ============================================================================\n\n/**\n * Bounds specification with min/max Vec3.\n */\ninterface Bounds {\n    min: Vec3;\n    max: Vec3;\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\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 */\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    /** For level-0 Mixed nodes: index into mixed.masks. Otherwise -1. */\n    maskIndices: number[];\n    /** For interior nodes (Mixed at level > 0): 8-bit child presence mask */\n    childMasks: number[];\n}\n\n// ============================================================================\n// Octree Construction\n// ============================================================================\n\n/**\n * Build a sparse octree from accumulated voxelization blocks.\n *\n * Uses Structure-of-Arrays (SoA) representation and linear scans on sorted\n * Morton codes instead of Maps and per-node objects for performance.\n *\n * @param accumulator - BlockAccumulator 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 * @returns Sparse octree structure\n */\nfunction buildSparseOctree(\n    accumulator: BlockAccumulator,\n    gridBounds: Bounds,\n    sceneBounds: Bounds,\n    voxelResolution: number\n): SparseOctree {\n    const tProfile = performance.now();\n\n    const mixed = accumulator.getMixedBlocks();\n    const solid = accumulator.getSolidBlocks();\n    const totalBlocks = mixed.morton.length + solid.length;\n\n    // --- Phase 1: Combine blocks into SoA arrays and sort by Morton code ---\n    // Avoids creating per-block objects (BlockEntry) — uses parallel arrays.\n\n    const mortons: number[] = new Array(totalBlocks);\n    const types: number[] = new Array(totalBlocks);\n    const maskIndices: number[] = new Array(totalBlocks);\n\n    let idx = 0;\n    for (let i = 0; i < mixed.morton.length; i++) {\n        mortons[idx] = mixed.morton[i];\n        types[idx] = BlockType.Mixed;\n        maskIndices[idx] = i;\n        idx++;\n    }\n    for (let i = 0; i < solid.length; i++) {\n        mortons[idx] = solid[i];\n        types[idx] = BlockType.Solid;\n        maskIndices[idx] = -1;\n        idx++;\n    }\n\n    // Co-sort by Morton code using an index permutation array\n    const sortOrder: number[] = new Array(totalBlocks);\n    for (let i = 0; i < totalBlocks; i++) sortOrder[i] = i;\n    sortOrder.sort((a: number, b: number) => mortons[a] - mortons[b]);\n\n    const sortedMortons: number[] = new Array(totalBlocks);\n    const sortedTypes: number[] = new Array(totalBlocks);\n    const sortedMaskIndices: number[] = new Array(totalBlocks);\n    for (let i = 0; i < totalBlocks; i++) {\n        const si = sortOrder[i];\n        sortedMortons[i] = mortons[si];\n        sortedTypes[i] = types[si];\n        sortedMaskIndices[i] = maskIndices[si];\n    }\n\n    const tSort = performance.now();\n\n    // --- Phase 2: Build tree bottom-up level by level using linear scan ---\n    // Instead of Map<number, BuildNode> per level, we use sorted parallel\n    // arrays and exploit the fact that sorted Morton codes make parent\n    // grouping a simple linear scan (consecutive entries with the same\n    // floor(morton/8) share a parent).\n\n    // Inner progress: 10 anonymous steps\n    logger.progress.begin(10);\n    let octreeStep = 0;\n\n    // Calculate tree depth based on grid size\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    const treeDepth = Math.max(1, Math.ceil(Math.log2(blocksPerAxis)));\n\n    // Store level data for each tree level (level 0 = leaves, higher = toward root)\n    const levels: LevelData[] = [];\n\n    // Current level data starts as the sorted leaf blocks\n    let curMortons = sortedMortons;\n    let curTypes = sortedTypes;\n    let curMaskIndices = sortedMaskIndices;\n    // Leaf level has no child masks (leaves have no children)\n    let curChildMasks: number[] = new Array(totalBlocks).fill(0);\n\n    // 1 step for init\n    logger.progress.step();\n    octreeStep++;\n\n    // Build up level by level\n    let actualDepth = treeDepth;\n    const levelSteps = 8;\n\n    for (let level = 0; level < treeDepth; level++) {\n        // Report inner progress scaled to levelSteps\n        const targetStep = 1 + Math.min(levelSteps, Math.floor((level + 1) / treeDepth * levelSteps));\n        while (octreeStep < targetStep) {\n            logger.progress.step();\n            octreeStep++;\n        }\n\n        // Save current level before building the next one above\n        levels.push({\n            mortons: curMortons,\n            types: curTypes,\n            maskIndices: curMaskIndices,\n            childMasks: curChildMasks\n        });\n\n        // Build next level using linear scan on sorted data.\n        // Since curMortons is sorted, entries sharing the same parent\n        // (floor(morton/8)) are contiguous — no Map needed.\n        const n = curMortons.length;\n        const nextMortons: number[] = [];\n        const nextTypes: number[] = [];\n        const nextMaskIndices: 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            // Scan all consecutive entries that share this parent\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            if (allSolid && childCount === 8) {\n                // All 8 children are solid — collapse to solid parent\n                nextMortons.push(parentMorton);\n                nextTypes.push(BlockType.Solid);\n                nextMaskIndices.push(-1);\n                nextChildMasks.push(0);\n            } else {\n                // Interior node with sparse children\n                nextMortons.push(parentMorton);\n                nextTypes.push(BlockType.Mixed);\n                nextMaskIndices.push(-1);\n                nextChildMasks.push(childMask);\n            }\n        }\n\n        curMortons = nextMortons;\n        curTypes = nextTypes;\n        curMaskIndices = nextMaskIndices;\n        curChildMasks = nextChildMasks;\n\n        // Break when the tree is empty or has converged to a single root at Morton 0.\n        // We must NOT break early if the single remaining node has a non-zero Morton,\n        // because the reader reconstructs Morton codes starting from root Morton 0.\n        if (curMortons.length === 0 ||\n            (curMortons.length === 1 && curMortons[0] === 0)) {\n            actualDepth = level + 1;\n            break;\n        }\n    }\n\n    // Save the root level\n    levels.push({\n        mortons: curMortons,\n        types: curTypes,\n        maskIndices: curMaskIndices,\n        childMasks: curChildMasks\n    });\n\n    // Flush remaining level steps\n    while (octreeStep < 9) {\n        logger.progress.step();\n        octreeStep++;\n    }\n\n    const tBuild = performance.now();\n\n    // --- Phase 3: Flatten tree to Laine-Karras format ---\n    // Uses wave-based BFS on level arrays, avoiding BuildNode objects\n    // and the O(n²) queue.shift() of the original approach.\n    const result = flattenTreeFromLevels(\n        levels, mixed.masks, gridBounds, sceneBounds, voxelResolution, actualDepth\n    );\n\n    const tFlatten = performance.now();\n\n    // Final step (10th)\n    logger.progress.step();\n\n    // Profiling output\n    logger.debug(\n        `[octree profiling] blocks: ${totalBlocks}, ` +\n        `sort: ${(tSort - tProfile).toFixed(1)}ms, ` +\n        `build: ${(tBuild - tSort).toFixed(1)}ms, ` +\n        `flatten: ${(tFlatten - tBuild).toFixed(1)}ms, ` +\n        `total: ${(tFlatten - tProfile).toFixed(1)}ms`\n    );\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 * Uses parallel arrays for BFS waves (no per-node object allocation)\n * and binary search on sorted level mortons to locate children.\n *\n * @param levels - Array of per-level SoA data (index 0 = leaves, last = root).\n * @param mixedMasks - Interleaved voxel masks for mixed leaf blocks.\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    levels: LevelData[],\n    mixedMasks: number[],\n    gridBounds: Bounds,\n    sceneBounds: Bounds,\n    voxelResolution: number,\n    treeDepth: number\n): SparseOctree {\n    const rootLevel = levels[levels.length - 1];\n\n    if (rootLevel.mortons.length === 0) {\n        // Empty tree\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    // Upper bound on total nodes (not all may be reachable if solids collapsed)\n    let maxNodes = 0;\n    for (let l = 0; l < levels.length; l++) {\n        maxNodes += levels[l].mortons.length;\n    }\n\n    const nodes = new Uint32Array(maxNodes);\n    const leafDataList: number[] = [];\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 = levels.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        // Clear interior tracking arrays\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            const level = levels[li];\n            const type = level.types[ii];\n\n            // A node is a leaf if it's Solid (at any level, collapsed or original)\n            // or if it's at level 0 (the leaf block level).\n            const isLeaf = (type === BlockType.Solid) || (li === 0);\n\n            if (isLeaf) {\n                if (type === BlockType.Solid) {\n                    nodes[emitPos] = SOLID_LEAF_MARKER;\n                } else {\n                    // Mixed leaf — store index into leafData\n                    const maskIdx = level.maskIndices[ii];\n                    const leafDataIndex = leafDataList.length >> 1;\n                    leafDataList.push(mixedMasks[maskIdx * 2]);\n                    leafDataList.push(mixedMasks[maskIdx * 2 + 1]);\n                    nodes[emitPos] = leafDataIndex & 0x00FFFFFF;\n                    numMixedLeaves++;\n                }\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                // Placeholder (will be filled below)\n                nodes[emitPos] = 0;\n            }\n            emitPos++;\n        }\n\n        // Build next wave from children of interior nodes.\n        // Backfill interior node encodings with correct baseOffset.\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            // Encode interior node: mask in high byte, baseOffset in low 24 bits\n            nodes[intPos[j]] = ((childMask & 0xFF) << 24) | (nextChildStart & 0x00FFFFFF);\n\n            // Find children in the level below using binary search.\n            // Since each level's mortons are sorted, this is O(log n) per lookup.\n            const childLi = intLi[j] - 1;\n            const childLevel = levels[childLi];\n            const myMorton = levels[intLi[j]].mortons[intIi[j]];\n            const childMortonBase = myMorton * 8;\n            const childMortonEnd = childMortonBase + 8;\n            const childMortons = childLevel.mortons;\n\n            // Binary search for first child with morton >= childMortonBase\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            // Collect all children in morton order (they are contiguous in sorted array)\n            while (lo < childMortons.length && childMortons[lo] < childMortonEnd) {\n                nextWaveLi.push(childLi);\n                nextWaveIi.push(lo);\n                lo++;\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: new Uint32Array(leafDataList)\n    };\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\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport {\n    // Morton code functions\n    xyzToMorton,\n    mortonToXYZ,\n\n    // Utility functions\n    popcount,\n    isSolid,\n    isEmpty,\n    getChildOffset,\n\n    // Accumulator\n    BlockAccumulator,\n\n    // Octree construction\n    buildSparseOctree,\n    alignGridBounds,\n\n    // Constants\n    SOLID_LEAF_MARKER\n};\n\nexport type { SparseOctree, Bounds };\n","import { basename, dirname, join } from 'pathe';\n\nimport { Column, DataTable } from '../data-table/data-table';\nimport { ReadFileSystem, readFile } from '../io/read';\nimport { getChildOffset, SOLID_LEAF_MARKER } from '../voxel/sparse-octree';\n\n/** SH coefficient for color conversion */\nconst C0 = 0.28209479177387814;\n\n/**\n * Metadata from a .voxel.json file.\n */\ninterface VoxelMetadata {\n    version: string;\n    gridBounds: { min: number[]; max: number[] };\n    sceneBounds: { min: number[]; max: number[] };\n    voxelResolution: number;\n    leafSize: number;\n    treeDepth: number;\n    numInteriorNodes: number;\n    numMixedLeaves: number;\n    nodeCount: number;\n    leafDataCount: number;\n}\n\n/**\n * Collected leaf blocks stored as parallel flat arrays to minimize GC pressure.\n */\ninterface LeafArrays {\n    /** Morton codes of each leaf block */\n    morton: number[];\n    /** Whether each leaf block is solid (true) or mixed (false) */\n    isSolid: Uint8Array;\n    /** Number of leaf blocks */\n    count: number;\n}\n\n/**\n * Iteratively expand a collapsed solid node into leaf-level solid blocks.\n * A collapsed solid at depth d with Morton m represents 8^(treeDepth-d) leaf blocks.\n * Uses an explicit stack instead of recursion for better performance.\n *\n * @param morton - Morton code of the solid node\n * @param depth - Current depth in the tree\n * @param treeDepth - Target leaf depth\n * @param outMorton - Output array to push leaf Morton codes into\n * @param outSolid - Output Uint8Array to mark leaves as solid\n * @param outCount - Current count of leaves (used as write index)\n * @param stack - Reusable stack array (pairs of [morton, depth])\n * @returns Updated leaf count after expansion\n */\nconst expandSolid = (\n    morton: number,\n    depth: number,\n    treeDepth: number,\n    outMorton: number[],\n    outSolid: Uint8Array,\n    outCount: number,\n    stack: number[]\n): number => {\n    stack.length = 0;\n    stack.push(morton, depth);\n\n    while (stack.length > 0) {\n        const d = stack.pop()!;\n        const m = stack.pop()!;\n\n        if (d === treeDepth) {\n            outMorton.push(m);\n            outSolid[outCount++] = 1;\n        } else {\n            // Push children in reverse order so octant 0 is processed first\n            for (let octant = 7; octant >= 0; octant--) {\n                stack.push(m * 8 + octant, d + 1);\n            }\n        }\n    }\n\n    return outCount;\n};\n\n/**\n * Traverse the octree and collect all leaf nodes with their Morton codes.\n * Collapsed solid parents are expanded back to leaf-level blocks.\n * Uses parallel flat arrays and index-based BFS for performance.\n *\n * @param nodes - Laine-Karras nodes array (Uint32)\n * @param _leafData - Leaf voxel masks (reserved for future use)\n * @param treeDepth - Maximum tree depth (leaf level)\n * @returns Parallel arrays of morton codes and solid flags\n */\nconst collectLeafBlocks = (\n    nodes: Uint32Array,\n    _leafData: Uint32Array,\n    treeDepth: number\n): LeafArrays => {\n    // Find root nodes: nodes that are never referenced as children.\n    const isChild = new Set<number>();\n    for (let i = 0; i < nodes.length; i++) {\n        const node = nodes[i] >>> 0;\n        if (node === SOLID_LEAF_MARKER) continue;\n        const highByte = (node >> 24) & 0xFF;\n        if (highByte !== 0x00) {\n            const childMask = highByte;\n            const baseOffset = node & 0x00FFFFFF;\n            for (let octant = 0; octant < 8; octant++) {\n                if (childMask & (1 << octant)) {\n                    const offset = getChildOffset(childMask, octant);\n                    isChild.add(baseOffset + offset);\n                }\n            }\n        }\n    }\n\n    // BFS using parallel arrays and index-based dequeue (O(1) per dequeue)\n    const qNodeIdx: number[] = [];\n    const qMorton: number[] = [];\n    const qDepth: number[] = [];\n\n    let rootMorton = 0;\n    for (let i = 0; i < nodes.length; i++) {\n        if (!isChild.has(i)) {\n            qNodeIdx.push(i);\n            qMorton.push(rootMorton);\n            qDepth.push(0);\n            rootMorton++;\n        }\n    }\n\n    // Output parallel arrays\n    const leafMorton: number[] = [];\n    // Pre-allocate a generous Uint8Array; will be trimmed at the end\n    let leafSolidCapacity = nodes.length;\n    let leafSolid = new Uint8Array(leafSolidCapacity);\n    let leafCount = 0;\n\n    // Reusable stack for expandSolid\n    const expandStack: number[] = [];\n\n    const ensureSolidCapacity = (needed: number) => {\n        if (needed > leafSolidCapacity) {\n            leafSolidCapacity = Math.max(leafSolidCapacity * 2, needed);\n            const newArr = new Uint8Array(leafSolidCapacity);\n            newArr.set(leafSolid);\n            leafSolid = newArr;\n        }\n    };\n\n    let head = 0;\n    while (head < qNodeIdx.length) {\n        const nodeIdx = qNodeIdx[head];\n        const morton = qMorton[head];\n        const depth = qDepth[head];\n        head++;\n\n        const node = nodes[nodeIdx] >>> 0;\n\n        if (node === SOLID_LEAF_MARKER) {\n            // Solid leaf - may be a collapsed parent if depth < treeDepth\n            const levelsToExpand = treeDepth - depth;\n            if (levelsToExpand === 0) {\n                // Already at leaf level, no expansion needed\n                leafMorton.push(morton);\n                ensureSolidCapacity(leafCount + 1);\n                leafSolid[leafCount++] = 1;\n            } else {\n                const expansionSize = 8 ** levelsToExpand;\n                ensureSolidCapacity(leafCount + expansionSize);\n                leafCount = expandSolid(morton, depth, treeDepth, leafMorton, leafSolid, leafCount, expandStack);\n            }\n        } else {\n            const highByte = (node >> 24) & 0xFF;\n            if (highByte === 0x00) {\n                // Mixed leaf\n                leafMorton.push(morton);\n                ensureSolidCapacity(leafCount + 1);\n                leafSolid[leafCount++] = 0;\n            } else {\n                // Interior node - queue children\n                const childMask = highByte;\n                const baseOffset = node & 0x00FFFFFF;\n                for (let octant = 0; octant < 8; octant++) {\n                    if (childMask & (1 << octant)) {\n                        const offset = getChildOffset(childMask, octant);\n                        qNodeIdx.push(baseOffset + offset);\n                        qMorton.push(morton * 8 + octant);\n                        qDepth.push(depth + 1);\n                    }\n                }\n            }\n        }\n    }\n\n    return {\n        morton: leafMorton,\n        isSolid: leafSolid.subarray(0, leafCount),\n        count: leafCount\n    };\n};\n\n/**\n * Read a .voxel.json file and convert to DataTable (finest/leaf LOD).\n *\n * Loads the voxel octree from .voxel.json + .voxel.bin, traverses to the leaf level,\n * and outputs a DataTable in the same Gaussian splat format as voxel-octree-node.mjs\n * at the leaf level. Users can then save to PLY, CSV, or any other format.\n *\n * @param fileSystem - File system for reading files\n * @param filename - Path to .voxel.json (the .voxel.bin must exist alongside it)\n * @returns DataTable with voxel block centers as Gaussian splats\n */\nconst readVoxel = async (\n    fileSystem: ReadFileSystem,\n    filename: string\n): Promise<DataTable> => {\n    const baseDir = dirname(filename);\n    const load = (name: string) => readFile(fileSystem, baseDir ? join(baseDir, name) : name);\n\n    // Load and parse JSON metadata\n    const jsonBytes = await load(basename(filename));\n    const metadata = JSON.parse(new TextDecoder().decode(jsonBytes)) as VoxelMetadata;\n\n    if (metadata.version !== '1.0') {\n        throw new Error(`Unsupported voxel format version: ${metadata.version}`);\n    }\n\n    // Load binary data\n    const binFilename = basename(filename).replace(/\\.voxel\\.json$/i, '.voxel.bin');\n    let binBytes: Uint8Array;\n    try {\n        binBytes = await load(binFilename);\n    } catch (e) {\n        throw new Error(\n            `Failed to load voxel binary file '${binFilename}'. ` +\n            `Ensure ${binFilename} exists alongside ${basename(filename)}.`\n        );\n    }\n\n    const nodeCount = metadata.nodeCount;\n    const leafDataCount = metadata.leafDataCount;\n    const expectedSize = (nodeCount + leafDataCount) * 4;\n    if (binBytes.length < expectedSize) {\n        throw new Error(\n            `Voxel binary file truncated: expected ${expectedSize} bytes, got ${binBytes.length}`\n        );\n    }\n\n    const nodes = new Uint32Array(binBytes.buffer, binBytes.byteOffset, nodeCount);\n    const leafData = new Uint32Array(\n        binBytes.buffer,\n        binBytes.byteOffset + nodeCount * 4,\n        leafDataCount\n    );\n\n    const leaves = collectLeafBlocks(nodes, leafData, metadata.treeDepth);\n\n    if (leaves.count === 0) {\n        return new DataTable([\n            new Column('x', new Float32Array(0)),\n            new Column('y', new Float32Array(0)),\n            new Column('z', new Float32Array(0)),\n            new Column('scale_0', new Float32Array(0)),\n            new Column('scale_1', new Float32Array(0)),\n            new Column('scale_2', new Float32Array(0)),\n            new Column('rot_0', new Float32Array(0)),\n            new Column('rot_1', new Float32Array(0)),\n            new Column('rot_2', new Float32Array(0)),\n            new Column('rot_3', new Float32Array(0)),\n            new Column('f_dc_0', new Float32Array(0)),\n            new Column('f_dc_1', new Float32Array(0)),\n            new Column('f_dc_2', new Float32Array(0)),\n            new Column('opacity', new Float32Array(0))\n        ]);\n    }\n\n    const gridMin = metadata.gridBounds.min;\n    const voxelResolution = metadata.voxelResolution;\n    const blockSize = 4 * voxelResolution;\n    const splatScale = Math.log(blockSize * 0.4);\n\n    const numBlocks = leaves.count;\n    const leavesMorton = leaves.morton;\n    const leavesSolid = leaves.isSolid;\n\n    const xArr = new Float32Array(numBlocks);\n    const yArr = new Float32Array(numBlocks);\n    const zArr = new Float32Array(numBlocks);\n    const scale0 = new Float32Array(numBlocks);\n    const scale1 = new Float32Array(numBlocks);\n    const scale2 = new Float32Array(numBlocks);\n    const rot0 = new Float32Array(numBlocks);\n    const rot1 = new Float32Array(numBlocks);\n    const rot2 = new Float32Array(numBlocks);\n    const rot3 = new Float32Array(numBlocks);\n    const fdc0 = new Float32Array(numBlocks);\n    const fdc1 = new Float32Array(numBlocks);\n    const fdc2 = new Float32Array(numBlocks);\n    const opacityArr = new Float32Array(numBlocks);\n\n    // Pre-compute constant SH values for solid blocks\n    const solidR = (0.9 - 0.5) / C0;\n    const solidG = (0.1 - 0.5) / C0;\n    const solidB = (0.1 - 0.5) / C0;\n\n    for (let i = 0; i < numBlocks; i++) {\n        const morton = leavesMorton[i];\n\n        // Inline Morton decode: extract x, y, z from interleaved 3-bit groups\n        // Avoids function call overhead and tuple allocation\n        let bx = 0, by = 0, bz = 0;\n        let m = morton;\n        let bit = 1;\n        while (m > 0) {\n            const triplet = m % 8;\n            if (triplet & 1) bx |= bit;\n            if (triplet & 2) by |= bit;\n            if (triplet & 4) bz |= bit;\n            bit <<= 1;\n            m = Math.trunc(m / 8);\n        }\n\n        xArr[i] = gridMin[0] + (bx + 0.5) * blockSize;\n        yArr[i] = gridMin[1] + (by + 0.5) * blockSize;\n        zArr[i] = gridMin[2] + (bz + 0.5) * blockSize;\n\n        scale0[i] = splatScale;\n        scale1[i] = splatScale;\n        scale2[i] = splatScale;\n\n        rot0[i] = 1.0;\n        // rot1, rot2, rot3 default to 0.0 from Float32Array initialization\n\n        if (leavesSolid[i]) {\n            fdc0[i] = solidR;\n            fdc1[i] = solidG;\n            fdc2[i] = solidB;\n        } else {\n            const gray = 0.3 + ((morton * 0.618033988749895) % 1.0) * 0.5;\n            fdc0[i] = (gray - 0.5) / C0;\n            fdc1[i] = (gray - 0.5) / C0;\n            fdc2[i] = (gray - 0.5) / C0;\n        }\n\n        opacityArr[i] = 5.0;\n    }\n\n    return new DataTable([\n        new Column('x', xArr),\n        new Column('y', yArr),\n        new Column('z', zArr),\n        new Column('scale_0', scale0),\n        new Column('scale_1', scale1),\n        new Column('scale_2', scale2),\n        new Column('rot_0', rot0),\n        new Column('rot_1', rot1),\n        new Column('rot_2', rot2),\n        new Column('rot_3', rot3),\n        new Column('f_dc_0', fdc0),\n        new Column('f_dc_1', fdc1),\n        new Column('f_dc_2', fdc2),\n        new Column('opacity', opacityArr)\n    ]);\n};\n\nexport { readVoxel };\n","import { DataTable } from './data-table/data-table';\nimport { ReadFileSystem } from './io/read';\nimport { ZipReadFileSystem } from './io/read/zip-file-system';\nimport { readKsplat } from './readers/read-ksplat';\nimport { readLcc } from './readers/read-lcc';\nimport { readMjs } from './readers/read-mjs';\nimport { readPly } from './readers/read-ply';\nimport { readSog } from './readers/read-sog';\nimport { readSplat } from './readers/read-splat';\nimport { readSpz } from './readers/read-spz';\nimport { readVoxel } from './readers/read-voxel';\nimport { Options, Param } from './types';\nimport { logger } from './utils/logger';\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 * - `voxel` - Sparse voxel octree format\n */\ntype InputFormat = 'mjs' | 'ksplat' | 'splat' | 'sog' | 'ply' | 'spz' | 'lcc' | 'voxel';\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 */\nconst getInputFormat = (filename: string): InputFormat => {\n    const lowerFilename = 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    } else if (lowerFilename.endsWith('.voxel.json')) {\n        return 'voxel';\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 * @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    logger.log(`reading '${filename}'...`);\n\n    if (inputFormat === 'mjs') {\n        result = [await readMjs(filename, params)];\n    } else if (inputFormat === 'sog') {\n        const lowerFilename = filename.toLowerCase();\n        if (lowerFilename.endsWith('.sog')) {\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        // LCC uses ReadFileSystem for multi-file access\n        result = await readLcc(fileSystem, filename, options);\n    } else if (inputFormat === 'voxel') {\n        result = [await readVoxel(fileSystem, filename)];\n    } else {\n        // All other formats use ReadSource\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","const sigmoid = (v: number) => 1 / (1 + Math.exp(-v));\n\nexport { sigmoid };\n","import { Quat } from 'playcanvas';\n\nimport { sigmoid } from '../utils/math';\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","import { CompressedChunk } from './compressed-chunk';\nimport { version } from '../../../package.json';\nimport { DataTable } from '../data-table/data-table';\nimport { sortMortonOrder } from '../data-table/morton-order';\nimport { type FileSystem } from '../io/write';\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\nconst shNames = new Array(45).fill('').map((_, i) => `f_rest_${i}`);\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, dataTable } = options;\n\n    const shBands = { '9': 1, '24': 2, '-1': 3 }[shNames.findIndex(v => !dataTable.hasColumn(v))] ?? 0;\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[shNames[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 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\nexport { writeCompressedPly };\n","import { DataTable } from '../data-table/data-table';\nimport { type FileSystem } from '../io/write';\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 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\nexport { writeCsv };\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\\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/* branding link for third-party embeds */\\n#supersplatBranding {\\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  color: #fff;\\n}\\n#supersplatBranding > 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#supersplatBranding > svg > g.stroke {\\n  fill: black;\\n  stroke: black;\\n  stroke-width: 2;\\n  stroke-linejoin: round;\\n  opacity: 0.4;\\n}\\n#supersplatBranding > svg > g.fill {\\n  fill: currentColor;\\n  stroke: none;\\n}\\n#supersplatBranding > 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: 380px;\\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: 10px;\\n  border-radius: 8px;\\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: #333;\\n}\\n#settingsPanel > .settingsRow {\\n  display: flex;\\n  gap: 4px;\\n  width: 100%;\\n}\\n#settingsPanel > .settingsRow > button {\\n  flex-grow: 1;\\n  height: 34px;\\n  padding: 0 20px;\\n  border: 0;\\n  cursor: pointer;\\n  color: #E0DCDD;\\n  background-color: #141414;\\n}\\n#settingsPanel > .settingsRow > button:hover {\\n  color: #fff;\\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.checkMark {\\n  width: 16px;\\n}\\n#settingsPanel > .settingsRow > div.checkMark:not(.active) {\\n  color: #333;\\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: #666;\\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: 40px;\\n  left: 50%;\\n  transform: translate(-50%, 0);\\n  min-height: 280px;\\n  min-width: 320px;\\n  padding: 8px;\\n  border-radius: 24px;\\n  display: flex;\\n  flex-direction: column;\\n  color: #E0DCDD;\\n  background-color: rgba(51, 51, 51, 0.8);\\n}\\n#infoPanel > #infoPanelContent > #tabs {\\n  display: flex;\\n  gap: 16px;\\n  padding: 8px;\\n  border-radius: 22px;\\n  background-color: #282828;\\n}\\n#infoPanel > #infoPanelContent > #tabs > .tab {\\n  padding: 8px;\\n  border-radius: 16px;\\n  cursor: pointer;\\n  flex-grow: 1;\\n  text-align: center;\\n  font-weight: bold;\\n  font-size: 14px;\\n  color: #E0DCDD;\\n  transition: background-color 250ms ease;\\n}\\n#infoPanel > #infoPanelContent > #tabs > .tab:hover {\\n  background-color: #444;\\n}\\n#infoPanel > #infoPanelContent > #tabs > .tab.active {\\n  background-color: #444;\\n}\\n#infoPanel > #infoPanelContent > #infoPanels {\\n  padding: 16px;\\n}\\n#infoPanel > #infoPanelContent > #infoPanels h1 {\\n  font-size: 14px;\\n  font-weight: bold;\\n  padding: 0 0 6px 0;\\n  color: #fff;\\n}\\n#infoPanel > #infoPanelContent > #infoPanels .control-item {\\n  display: flex;\\n  justify-content: space-between;\\n  gap: 32px;\\n  line-height: 1.5;\\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}\\n#infoPanel > #infoPanelContent > #infoPanels .control-spacer {\\n  border-bottom: 1px dashed #666;\\n  margin: 10px 0;\\n}\\n\\n#joystickBase {\\n  position: absolute;\\n  width: 64px;\\n  height: 120px;\\n  transform: translate(-50%, -50%);\\n  border-radius: 32px;\\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: 48px;\\n  height: 48px;\\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: 120px;\\n  height: 120px;\\n  border-radius: 60px;\\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: 36px;\\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\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 voxelUrl = 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 sseConfig = {\\n                poster: posterUrl && createImage(posterUrl),\\n                skyboxUrl,\\n                voxelUrl,\\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                unified: url.searchParams.has('unified'),\\n                webgpu: url.searchParams.has('webgpu'),\\n                gpusort: url.searchParams.has('gpusort'),\\n                aa: url.searchParams.has('aa'),\\n                heatmap: url.searchParams.has('heatmap'),\\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=\\\"supersplatBranding\\\" class=\\\"hidden\\\" target=\\\"_blank\\\" rel=\\\"noopener noreferrer\\\">\\n                <svg xmlns=\\\"http://www.w3.org/2000/svg\\\" width=\\\"16\\\" height=\\\"16\\\" 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>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=\\\"showVoxels\\\" 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            <!-- Settings Panel -->\\n            <div id=\\\"settingsPanel\\\" class=\\\"hidden\\\">\\n                <div class=\\\"settingsRow\\\">\\n                    <div id=\\\"hqCheck\\\" class=\\\"checkMark\\\">✓</div>\\n                    <div id=\\\"hqOption\\\">High Quality Render</div>\\n                </div>\\n                <div class=\\\"settingsRow\\\">\\n                    <div id=\\\"lqCheck\\\" class=\\\"checkMark\\\">✓</div>\\n                    <div id=\\\"lqOption\\\">Low Quality Render</div>\\n                </div>\\n                <div class=\\\"divider\\\"></div>\\n                <div class=\\\"settingsRow\\\">\\n                    <button id=\\\"frame\\\">Frame</button>\\n                    <button id=\\\"reset\\\">Reset</button>\\n                </div>\\n            </div>\\n\\n            <!-- Info Panel -->\\n            <div id=\\\"infoPanel\\\" class=\\\"hidden\\\">\\n                <div id=\\\"infoPanelContent\\\" onpointerdown=\\\"event.stopPropagation()\\\">\\n                    <div id=\\\"tabs\\\">\\n                        <div id=\\\"desktopTab\\\" class=\\\"tab active\\\">Desktop</div>\\n                        <div id=\\\"touchTab\\\" class=\\\"tab\\\">Touch</div>\\n                    </div>\\n                    <div id=\\\"infoPanels\\\">\\n                        <div id=\\\"desktopInfoPanel\\\">\\n                            <div class=\\\"control-spacer\\\"></div>\\n                            <h1>Orbit Mode</h1>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\">Orbit</span>\\n                                <span class=\\\"control-key\\\">Left Mouse</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\">Pan</span>\\n                                <span class=\\\"control-key\\\">Right Mouse</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\">Zoom</span>\\n                                <span class=\\\"control-key\\\">Mouse Wheel</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\">Set Focus</span>\\n                                <span class=\\\"control-key\\\">Double Click</span>\\n                            </div>\\n                            <div class=\\\"control-spacer\\\"></div>\\n                            <h1>Fly Mode</h1>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\">Look Around</span>\\n                                <span class=\\\"control-key\\\">Left Mouse</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\">Fly</span>\\n                                <span class=\\\"control-key\\\">W,S,A,D</span>\\n                            </div>\\n                            <div class=\\\"control-spacer\\\"></div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\">Frame Scene</span>\\n                                <span class=\\\"control-key\\\">F</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\">Reset Camera</span>\\n                                <span class=\\\"control-key\\\">R</span>\\n                            </div>\\n                        </div>\\n                        <div id=\\\"touchInfoPanel\\\" class=\\\"hidden\\\">\\n                            <div class=\\\"control-spacer\\\"></div>\\n                            <h1>Orbit Mode</h1>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\">Orbit</span>\\n                                <span class=\\\"control-key\\\">One Finger Drag</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\">Pan</span>\\n                                <span class=\\\"control-key\\\">Two Finger Drag</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\">Zoom</span>\\n                                <span class=\\\"control-key\\\">Pinch</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\">Set Focus</span>\\n                                <span class=\\\"control-key\\\">Double Tap</span>\\n                            </div>\\n                            <div class=\\\"control-spacer\\\"></div>\\n                            <h1>Fly Mode</h1>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\">Look Around</span>\\n                                <span class=\\\"control-key\\\">Touch on Right</span>\\n                            </div>\\n                            <div class=\\\"control-item\\\">\\n                                <span class=\\\"control-action\\\">Fly</span>\\n                                <span class=\\\"control-key\\\">Touch on Left</span>\\n                            </div>\\n                        </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        </div>\\n\\n        <!-- SVG Icons -->\\n        <svg>\\n            <symbol id=\\\"supersplatIcon\\\" viewBox=\\\"0 0 32 32\\\">\\n                <path d=\\\"M4.2638 11.4207C5.15691 11.4207 5.87964 10.697 5.87964 9.80481C5.87964 8.91262 5.15599 8.18896 4.2638 8.18896C3.3716 8.18896 2.64795 8.91262 2.64795 9.80481C2.64795 10.697 3.3716 11.4207 4.2638 11.4207Z\\\"/>\\n                <path d=\\\"M27.9805 14.8047C26.8392 14.8047 25.9131 15.7308 25.9131 16.8721C25.9131 18.0135 26.8392 18.9396 27.9805 18.9396C29.1219 18.9396 30.048 18.0135 30.048 16.8721C30.048 15.7308 29.1219 14.8047 27.9805 14.8047Z\\\"/>\\n                <path d=\\\"M23.9977 6.30034H23.9995C24.0334 6.29576 24.059 6.28019 24.0883 6.27011C25.6254 6.05759 26.8135 4.75228 26.8135 3.15658C26.8135 1.41249 25.4001 0 23.6569 0C21.9137 0 20.5003 1.41341 20.5003 3.15658C20.5003 3.54955 20.5809 3.92145 20.7128 4.26862C20.7165 4.27961 20.7119 4.29152 20.7165 4.30343C21.6829 6.97636 18.671 6.46705 17.1376 6.20324C17.0928 6.195 17.057 6.19683 17.0167 6.19316C16.6256 6.14187 16.2299 6.10431 15.8232 6.10431C10.8831 6.10431 6.87921 10.1082 6.87921 15.0483C6.87921 15.9496 7.01478 16.818 7.26393 17.6387C7.2676 17.6479 7.26393 17.6543 7.26851 17.6635C8.09018 20.4253 5.91006 19.9984 4.93085 20.0167C4.83558 20.0048 4.7394 19.9874 4.63955 19.9874C3.40202 19.9874 2.3999 20.9895 2.3999 22.2271C2.3999 23.4646 3.40202 24.4667 4.63955 24.4667C5.71037 24.4667 6.60349 23.7137 6.82424 22.7089H6.82608C7.40408 20.275 9.19855 21.0582 9.67946 21.5483C9.69778 21.5666 9.7161 21.5721 9.7335 21.5868C11.331 23.0753 13.4663 23.9922 15.8222 23.9922C15.8836 23.9922 15.945 23.984 16.0064 23.9831C16.0668 23.984 16.1264 23.9867 16.1932 23.9867C17.0818 23.9831 17.8256 24.9861 16.6457 26.7054H16.6576C16.2528 27.256 16.0073 27.9292 16.0073 28.6666C16.0073 30.5069 17.4995 32 19.3406 32C21.1818 32 22.674 30.5078 22.674 28.6666C22.674 27.256 21.7937 26.0569 20.5562 25.5696C20.5269 25.5558 20.5003 25.543 20.4664 25.5284C19.3416 25.0759 18.137 23.9079 19.8353 23.046L19.8316 23.0368C22.7565 21.5657 24.7671 18.5465 24.7671 15.0492C24.7671 13.1118 24.1442 11.3228 23.0972 9.85905C23.0853 9.83798 23.0761 9.816 23.0569 9.79126C20.9363 6.89025 22.8398 6.4872 24.0004 6.30217H23.9995L23.9977 6.30034ZM13.5121 17.6232C13.5121 18.3514 12.9221 18.9404 12.1948 18.9404C11.4675 18.9404 10.8776 18.3505 10.8776 17.6232V15.5209C10.8776 14.7927 11.4675 14.2037 12.1948 14.2037C12.9221 14.2037 13.5121 14.7936 13.5121 15.5209V17.6232ZM20.7476 17.6232C20.7476 18.3514 20.1577 18.9404 19.4304 18.9404C18.7031 18.9404 18.1132 18.3505 18.1132 17.6232V15.5209C18.1132 14.7927 18.7031 14.2037 19.4304 14.2037C20.1577 14.2037 20.7476 14.7936 20.7476 15.5209V17.6232Z\\\"/>\\n            </symbol>\\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.16.2';\\nconst revision = '5c8389e';\\nfunction extend(target, ex) {\\n\\t\\tfor(const prop in ex){\\n\\t\\t\\t\\tconst copy = ex[prop];\\n\\t\\t\\t\\tif (Array.isArray(copy)) {\\n\\t\\t\\t\\t\\t\\ttarget[prop] = extend([], copy);\\n\\t\\t\\t\\t} else if (copy && typeof copy === 'object') {\\n\\t\\t\\t\\t\\t\\ttarget[prop] = extend({}, copy);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\ttarget[prop] = copy;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn target;\\n}\\n\\nconst guid = {\\n\\t\\tcreate () {\\n\\t\\t\\t\\treturn 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c)=>{\\n\\t\\t\\t\\t\\t\\tconst r = Math.random() * 16 | 0;\\n\\t\\t\\t\\t\\t\\tconst v = c === 'x' ? r : r & 0x3 | 0x8;\\n\\t\\t\\t\\t\\t\\treturn v.toString(16);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n};\\n\\nconst path = {\\n\\t\\tdelimiter: '/',\\n\\t\\tjoin (...sections) {\\n\\t\\t\\t\\tlet result = sections[0];\\n\\t\\t\\t\\tfor(let i = 0; i < sections.length - 1; i++){\\n\\t\\t\\t\\t\\t\\tconst one = sections[i];\\n\\t\\t\\t\\t\\t\\tconst two = sections[i + 1];\\n\\t\\t\\t\\t\\t\\tif (two[0] === path.delimiter) {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult = two;\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (one && two && one[one.length - 1] !== path.delimiter && two[0] !== path.delimiter) {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult += path.delimiter + two;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult += two;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t},\\n\\t\\tnormalize (pathname) {\\n\\t\\t\\t\\tconst lead = pathname.startsWith(path.delimiter);\\n\\t\\t\\t\\tconst trail = pathname.endsWith(path.delimiter);\\n\\t\\t\\t\\tconst parts = pathname.split('/');\\n\\t\\t\\t\\tlet result = '';\\n\\t\\t\\t\\tlet cleaned = [];\\n\\t\\t\\t\\tfor(let i = 0; i < parts.length; i++){\\n\\t\\t\\t\\t\\t\\tif (parts[i] === '') continue;\\n\\t\\t\\t\\t\\t\\tif (parts[i] === '.') continue;\\n\\t\\t\\t\\t\\t\\tif (parts[i] === '..' && cleaned.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcleaned = cleaned.slice(0, cleaned.length - 2);\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (i > 0) cleaned.push(path.delimiter);\\n\\t\\t\\t\\t\\t\\tcleaned.push(parts[i]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tresult = cleaned.join('');\\n\\t\\t\\t\\tif (!lead && result[0] === path.delimiter) {\\n\\t\\t\\t\\t\\t\\tresult = result.slice(1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (trail && result[result.length - 1] !== path.delimiter) {\\n\\t\\t\\t\\t\\t\\tresult += path.delimiter;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t},\\n\\t\\tsplit (pathname) {\\n\\t\\t\\t\\tconst lastDelimiterIndex = pathname.lastIndexOf(path.delimiter);\\n\\t\\t\\t\\tif (lastDelimiterIndex !== -1) {\\n\\t\\t\\t\\t\\t\\treturn [\\n\\t\\t\\t\\t\\t\\t\\t\\tpathname.substring(0, lastDelimiterIndex),\\n\\t\\t\\t\\t\\t\\t\\t\\tpathname.substring(lastDelimiterIndex + 1)\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn [\\n\\t\\t\\t\\t\\t\\t'',\\n\\t\\t\\t\\t\\t\\tpathname\\n\\t\\t\\t\\t];\\n\\t\\t},\\n\\t\\tgetBasename (pathname) {\\n\\t\\t\\t\\treturn path.split(pathname)[1];\\n\\t\\t},\\n\\t\\tgetDirectory (pathname) {\\n\\t\\t\\t\\treturn path.split(pathname)[0];\\n\\t\\t},\\n\\t\\tgetExtension (pathname) {\\n\\t\\t\\t\\tconst ext = pathname.split('?')[0].split('.').pop();\\n\\t\\t\\t\\tif (ext !== pathname) {\\n\\t\\t\\t\\t\\t\\treturn `.${ext}`;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn '';\\n\\t\\t},\\n\\t\\tisRelativePath (pathname) {\\n\\t\\t\\t\\treturn pathname.charAt(0) !== '/' && pathname.match(/:\\\\/\\\\//) === null;\\n\\t\\t},\\n\\t\\textractPath (pathname) {\\n\\t\\t\\t\\tlet result = '';\\n\\t\\t\\t\\tconst parts = pathname.split('/');\\n\\t\\t\\t\\tlet i = 0;\\n\\t\\t\\t\\tif (parts.length > 1) {\\n\\t\\t\\t\\t\\t\\tif (path.isRelativePath(pathname)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (parts[0] === '.') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(i = 0; i < parts.length - 1; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult += i === 0 ? parts[i] : `/${parts[i]}`;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else if (parts[0] === '..') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(i = 0; i < parts.length - 1; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult += i === 0 ? parts[i] : `/${parts[i]}`;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult = '.';\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(i = 0; i < parts.length - 1; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult += `/${parts[i]}`;\\n\\t\\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} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(i = 0; i < parts.length - 1; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult += i === 0 ? parts[i] : `/${parts[i]}`;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n};\\n\\nconst detectPassiveEvents = ()=>{\\n\\t\\tlet result = false;\\n\\t\\ttry {\\n\\t\\t\\t\\tconst opts = Object.defineProperty({}, 'passive', {\\n\\t\\t\\t\\t\\t\\tget: function() {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult = true;\\n\\t\\t\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\twindow.addEventListener('testpassive', null, opts);\\n\\t\\t\\t\\twindow.removeEventListener('testpassive', null, opts);\\n\\t\\t} catch (e) {}\\n\\t\\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' : /Safari\\\\//.test(ua) ? 'safari' : /Firefox\\\\//.test(ua) ? 'firefox' : 'other';\\nconst passiveEvents = detectPassiveEvents();\\nconst platform = {\\n\\t\\tname: platformName,\\n\\t\\tenvironment: environment,\\n\\t\\tbrowser: environment === 'browser',\\n\\t\\tworker: environment === 'worker',\\n\\t\\tdesktop: [\\n\\t\\t\\t\\t'windows',\\n\\t\\t\\t\\t'osx',\\n\\t\\t\\t\\t'linux',\\n\\t\\t\\t\\t'cros'\\n\\t\\t].includes(platformName),\\n\\t\\tmobile: [\\n\\t\\t\\t\\t'android',\\n\\t\\t\\t\\t'ios'\\n\\t\\t].includes(platformName),\\n\\t\\tios: platformName === 'ios',\\n\\t\\tandroid: platformName === 'android',\\n\\t\\tpassiveEvents: passiveEvents,\\n\\t\\tbrowserName: browserName\\n};\\n\\nclass EventHandle {\\n\\t\\toff() {\\n\\t\\t\\t\\tif (this._removed) return;\\n\\t\\t\\t\\tthis.handler.offByHandle(this);\\n\\t\\t}\\n\\t\\ton(name, callback, scope = this) {\\n\\t\\t\\t\\treturn this.handler._addCallback(name, callback, scope, false);\\n\\t\\t}\\n\\t\\tonce(name, callback, scope = this) {\\n\\t\\t\\t\\treturn this.handler._addCallback(name, callback, scope, true);\\n\\t\\t}\\n\\t\\tset removed(value) {\\n\\t\\t\\t\\tif (!value) return;\\n\\t\\t\\t\\tthis._removed = true;\\n\\t\\t}\\n\\t\\tget removed() {\\n\\t\\t\\t\\treturn this._removed;\\n\\t\\t}\\n\\t\\ttoJSON(key) {\\n\\t\\t\\t\\treturn undefined;\\n\\t\\t}\\n\\t\\tconstructor(handler, name, callback, scope, once = false){\\n\\t\\t\\t\\tthis._removed = false;\\n\\t\\t\\t\\tthis.handler = handler;\\n\\t\\t\\t\\tthis.name = name;\\n\\t\\t\\t\\tthis.callback = callback;\\n\\t\\t\\t\\tthis.scope = scope;\\n\\t\\t\\t\\tthis._once = once;\\n\\t\\t}\\n}\\n\\nclass EventHandler {\\n\\t\\tinitEventHandler() {\\n\\t\\t\\t\\tthis._callbacks = new Map();\\n\\t\\t\\t\\tthis._callbackActive = new Map();\\n\\t\\t}\\n\\t\\t_addCallback(name, callback, scope, once) {\\n\\t\\t\\t\\tif (!this._callbacks.has(name)) {\\n\\t\\t\\t\\t\\t\\tthis._callbacks.set(name, []);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._callbackActive.has(name)) {\\n\\t\\t\\t\\t\\t\\tconst callbackActive = this._callbackActive.get(name);\\n\\t\\t\\t\\t\\t\\tif (callbackActive && callbackActive === this._callbacks.get(name)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._callbackActive.set(name, callbackActive.slice());\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst evt = new EventHandle(this, name, callback, scope, once);\\n\\t\\t\\t\\tthis._callbacks.get(name).push(evt);\\n\\t\\t\\t\\treturn evt;\\n\\t\\t}\\n\\t\\ton(name, callback, scope = this) {\\n\\t\\t\\t\\treturn this._addCallback(name, callback, scope, false);\\n\\t\\t}\\n\\t\\tonce(name, callback, scope = this) {\\n\\t\\t\\t\\treturn this._addCallback(name, callback, scope, true);\\n\\t\\t}\\n\\t\\toff(name, callback, scope) {\\n\\t\\t\\t\\tif (name) {\\n\\t\\t\\t\\t\\t\\tif (this._callbackActive.has(name) && this._callbackActive.get(name) === this._callbacks.get(name)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._callbackActive.set(name, this._callbackActive.get(name).slice());\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tfor (const [key, callbacks] of this._callbackActive){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this._callbacks.has(key)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._callbacks.get(key) !== callbacks) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._callbackActive.set(key, callbacks.slice());\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!name) {\\n\\t\\t\\t\\t\\t\\tfor (const callbacks of this._callbacks.values()){\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < callbacks.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallbacks[i].removed = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._callbacks.clear();\\n\\t\\t\\t\\t} else if (!callback) {\\n\\t\\t\\t\\t\\t\\tconst callbacks = this._callbacks.get(name);\\n\\t\\t\\t\\t\\t\\tif (callbacks) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < callbacks.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallbacks[i].removed = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._callbacks.delete(name);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst callbacks = this._callbacks.get(name);\\n\\t\\t\\t\\t\\t\\tif (!callbacks) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn this;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < callbacks.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (callbacks[i].callback !== callback) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (scope && callbacks[i].scope !== scope) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tcallbacks[i].removed = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tcallbacks.splice(i, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\ti--;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (callbacks.length === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._callbacks.delete(name);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\toffByHandle(handle) {\\n\\t\\t\\t\\tconst name = handle.name;\\n\\t\\t\\t\\thandle.removed = true;\\n\\t\\t\\t\\tif (this._callbackActive.has(name) && this._callbackActive.get(name) === this._callbacks.get(name)) {\\n\\t\\t\\t\\t\\t\\tthis._callbackActive.set(name, this._callbackActive.get(name).slice());\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst callbacks = this._callbacks.get(name);\\n\\t\\t\\t\\tif (!callbacks) {\\n\\t\\t\\t\\t\\t\\treturn this;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst ind = callbacks.indexOf(handle);\\n\\t\\t\\t\\tif (ind !== -1) {\\n\\t\\t\\t\\t\\t\\tcallbacks.splice(ind, 1);\\n\\t\\t\\t\\t\\t\\tif (callbacks.length === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._callbacks.delete(name);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tfire(name, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) {\\n\\t\\t\\t\\tif (!name) {\\n\\t\\t\\t\\t\\t\\treturn this;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst callbacksInitial = this._callbacks.get(name);\\n\\t\\t\\t\\tif (!callbacksInitial) {\\n\\t\\t\\t\\t\\t\\treturn this;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet callbacks;\\n\\t\\t\\t\\tif (!this._callbackActive.has(name)) {\\n\\t\\t\\t\\t\\t\\tthis._callbackActive.set(name, callbacksInitial);\\n\\t\\t\\t\\t} else if (this._callbackActive.get(name) !== callbacksInitial) {\\n\\t\\t\\t\\t\\t\\tcallbacks = callbacksInitial.slice();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; (callbacks || this._callbackActive.get(name)) && i < (callbacks || this._callbackActive.get(name)).length; i++){\\n\\t\\t\\t\\t\\t\\tconst evt = (callbacks || this._callbackActive.get(name))[i];\\n\\t\\t\\t\\t\\t\\tif (!evt.callback) continue;\\n\\t\\t\\t\\t\\t\\tevt.callback.call(evt.scope, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);\\n\\t\\t\\t\\t\\t\\tif (evt._once) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst existingCallback = this._callbacks.get(name);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst ind = existingCallback ? existingCallback.indexOf(evt) : -1;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (ind !== -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this._callbackActive.get(name) === existingCallback) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._callbackActive.set(name, this._callbackActive.get(name).slice());\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst callbacks = this._callbacks.get(name);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!callbacks) continue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallbacks[ind].removed = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallbacks.splice(ind, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (callbacks.length === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._callbacks.delete(name);\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!callbacks) {\\n\\t\\t\\t\\t\\t\\tthis._callbackActive.delete(name);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\thasEvent(name) {\\n\\t\\t\\t\\treturn !!this._callbacks.get(name)?.length;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis._callbacks = new Map();\\n\\t\\t\\t\\tthis._callbackActive = new Map();\\n\\t\\t}\\n}\\n\\nconst cachedResult = (func)=>{\\n\\t\\tconst uninitToken = {};\\n\\t\\tlet result = uninitToken;\\n\\t\\treturn ()=>{\\n\\t\\t\\t\\tif (result === uninitToken) {\\n\\t\\t\\t\\t\\t\\tresult = func();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t};\\n};\\nclass Impl {\\n\\t\\tstatic loadScript(url, callback) {\\n\\t\\t\\t\\tconst s = document.createElement(\\\"script\\\");\\n\\t\\t\\t\\ts.setAttribute('src', url);\\n\\t\\t\\t\\ts.onload = ()=>{\\n\\t\\t\\t\\t\\t\\tcallback(null);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\ts.onerror = ()=>{\\n\\t\\t\\t\\t\\t\\tcallback(`Failed to load script='${url}'`);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tdocument.body.appendChild(s);\\n\\t\\t}\\n\\t\\tstatic loadWasm(moduleName, config, callback) {\\n\\t\\t\\t\\tconst loadUrl = Impl.wasmSupported() && config.glueUrl && config.wasmUrl ? config.glueUrl : config.fallbackUrl;\\n\\t\\t\\t\\tif (loadUrl) {\\n\\t\\t\\t\\t\\t\\tImpl.loadScript(loadUrl, (err)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(err, null);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst module = window[moduleName];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twindow[moduleName] = undefined;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmodule({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlocateFile: ()=>config.wasmUrl,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tonAbort: ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback('wasm module aborted.');\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}).then((instance)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(null, instance);\\n\\t\\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});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tcallback('No supported wasm modules found.', null);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tstatic getModule(name) {\\n\\t\\t\\t\\tif (!Impl.modules.hasOwnProperty(name)) {\\n\\t\\t\\t\\t\\t\\tImpl.modules[name] = {\\n\\t\\t\\t\\t\\t\\t\\t\\tconfig: null,\\n\\t\\t\\t\\t\\t\\t\\t\\tinitializing: false,\\n\\t\\t\\t\\t\\t\\t\\t\\tinstance: null,\\n\\t\\t\\t\\t\\t\\t\\t\\tcallbacks: []\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn Impl.modules[name];\\n\\t\\t}\\n\\t\\tstatic initialize(moduleName, module) {\\n\\t\\t\\t\\tif (module.initializing) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst config = module.config;\\n\\t\\t\\t\\tif (config.glueUrl || config.wasmUrl || config.fallbackUrl) {\\n\\t\\t\\t\\t\\t\\tmodule.initializing = true;\\n\\t\\t\\t\\t\\t\\tImpl.loadWasm(moduleName, config, (err, instance)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (config.errorHandler) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconfig.errorHandler(err);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconsole.error(`failed to initialize module=${moduleName} error=${err}`);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmodule.instance = instance;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmodule.callbacks.forEach((callback)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(instance);\\n\\t\\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});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nImpl.modules = {};\\nImpl.wasmSupported = cachedResult(()=>{\\n\\t\\ttry {\\n\\t\\t\\t\\tif (typeof WebAssembly === 'object' && typeof WebAssembly.instantiate === 'function') {\\n\\t\\t\\t\\t\\t\\tconst module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));\\n\\t\\t\\t\\t\\t\\tif (module instanceof WebAssembly.Module) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn new WebAssembly.Instance(module) instanceof WebAssembly.Instance;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t} catch (e) {}\\n\\t\\treturn false;\\n});\\nclass WasmModule {\\n\\t\\tstatic setConfig(moduleName, config) {\\n\\t\\t\\t\\tconst module = Impl.getModule(moduleName);\\n\\t\\t\\t\\tmodule.config = config;\\n\\t\\t\\t\\tif (module.callbacks.length > 0) {\\n\\t\\t\\t\\t\\t\\tImpl.initialize(moduleName, module);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tstatic getConfig(moduleName) {\\n\\t\\t\\t\\treturn Impl.modules?.[moduleName]?.config;\\n\\t\\t}\\n\\t\\tstatic getInstance(moduleName, callback) {\\n\\t\\t\\t\\tconst module = Impl.getModule(moduleName);\\n\\t\\t\\t\\tif (module.instance) {\\n\\t\\t\\t\\t\\t\\tcallback(module.instance);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tmodule.callbacks.push(callback);\\n\\t\\t\\t\\t\\t\\tif (module.config) {\\n\\t\\t\\t\\t\\t\\t\\t\\tImpl.initialize(moduleName, module);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass ReadStream {\\n\\t\\tget remainingBytes() {\\n\\t\\t\\t\\treturn this.dataView.byteLength - this.offset;\\n\\t\\t}\\n\\t\\treset(offset = 0) {\\n\\t\\t\\t\\tthis.offset = offset;\\n\\t\\t}\\n\\t\\tskip(bytes) {\\n\\t\\t\\t\\tthis.offset += bytes;\\n\\t\\t}\\n\\t\\talign(bytes) {\\n\\t\\t\\t\\tthis.offset = this.offset + bytes - 1 & ~(bytes - 1);\\n\\t\\t}\\n\\t\\t_inc(amount) {\\n\\t\\t\\t\\tthis.offset += amount;\\n\\t\\t\\t\\treturn this.offset - amount;\\n\\t\\t}\\n\\t\\treadChar() {\\n\\t\\t\\t\\treturn String.fromCharCode(this.dataView.getUint8(this.offset++));\\n\\t\\t}\\n\\t\\treadChars(numChars) {\\n\\t\\t\\t\\tlet result = '';\\n\\t\\t\\t\\tfor(let i = 0; i < numChars; ++i){\\n\\t\\t\\t\\t\\t\\tresult += this.readChar();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\treadU8() {\\n\\t\\t\\t\\treturn this.dataView.getUint8(this.offset++);\\n\\t\\t}\\n\\t\\treadU16() {\\n\\t\\t\\t\\treturn this.dataView.getUint16(this._inc(2), true);\\n\\t\\t}\\n\\t\\treadU32() {\\n\\t\\t\\t\\treturn this.dataView.getUint32(this._inc(4), true);\\n\\t\\t}\\n\\t\\treadU64() {\\n\\t\\t\\t\\treturn this.readU32() + 2 ** 32 * this.readU32();\\n\\t\\t}\\n\\t\\treadU32be() {\\n\\t\\t\\t\\treturn this.dataView.getUint32(this._inc(4), false);\\n\\t\\t}\\n\\t\\treadArray(result) {\\n\\t\\t\\t\\tfor(let i = 0; i < result.length; ++i){\\n\\t\\t\\t\\t\\t\\tresult[i] = this.readU8();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treadLine() {\\n\\t\\t\\t\\tconst view = this.dataView;\\n\\t\\t\\t\\tlet result = '';\\n\\t\\t\\t\\twhile(true){\\n\\t\\t\\t\\t\\t\\tif (this.offset >= view.byteLength) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst c = String.fromCharCode(this.readU8());\\n\\t\\t\\t\\t\\t\\tif (c === '\\\\n') {\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tresult += c;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tconstructor(arraybuffer){\\n\\t\\t\\t\\tthis.offset = 0;\\n\\t\\t\\t\\tthis.arraybuffer = arraybuffer;\\n\\t\\t\\t\\tthis.dataView = new DataView(arraybuffer);\\n\\t\\t}\\n}\\n\\nclass SortedLoopArray {\\n\\t\\t_binarySearch(item) {\\n\\t\\t\\t\\tlet left = 0;\\n\\t\\t\\t\\tlet right = this.items.length - 1;\\n\\t\\t\\t\\tconst search = item[this._sortBy];\\n\\t\\t\\t\\tlet middle;\\n\\t\\t\\t\\tlet current;\\n\\t\\t\\t\\twhile(left <= right){\\n\\t\\t\\t\\t\\t\\tmiddle = Math.floor((left + right) / 2);\\n\\t\\t\\t\\t\\t\\tcurrent = this.items[middle][this._sortBy];\\n\\t\\t\\t\\t\\t\\tif (current <= search) {\\n\\t\\t\\t\\t\\t\\t\\t\\tleft = middle + 1;\\n\\t\\t\\t\\t\\t\\t} else if (current > search) {\\n\\t\\t\\t\\t\\t\\t\\t\\tright = middle - 1;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn left;\\n\\t\\t}\\n\\t\\t_doSort(a, b) {\\n\\t\\t\\t\\tconst sortBy = this._sortBy;\\n\\t\\t\\t\\treturn a[sortBy] - b[sortBy];\\n\\t\\t}\\n\\t\\tinsert(item) {\\n\\t\\t\\t\\tconst index = this._binarySearch(item);\\n\\t\\t\\t\\tthis.items.splice(index, 0, item);\\n\\t\\t\\t\\tthis.length++;\\n\\t\\t\\t\\tif (this.loopIndex >= index) {\\n\\t\\t\\t\\t\\t\\tthis.loopIndex++;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tappend(item) {\\n\\t\\t\\t\\tthis.items.push(item);\\n\\t\\t\\t\\tthis.length++;\\n\\t\\t}\\n\\t\\tremove(item) {\\n\\t\\t\\t\\tconst idx = this.items.indexOf(item);\\n\\t\\t\\t\\tif (idx < 0) return;\\n\\t\\t\\t\\tthis.items.splice(idx, 1);\\n\\t\\t\\t\\tthis.length--;\\n\\t\\t\\t\\tif (this.loopIndex >= idx) {\\n\\t\\t\\t\\t\\t\\tthis.loopIndex--;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsort() {\\n\\t\\t\\t\\tconst current = this.loopIndex >= 0 ? this.items[this.loopIndex] : null;\\n\\t\\t\\t\\tthis.items.sort(this._sortHandler);\\n\\t\\t\\t\\tif (current !== null) {\\n\\t\\t\\t\\t\\t\\tthis.loopIndex = this.items.indexOf(current);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(args){\\n\\t\\t\\t\\tthis.items = [];\\n\\t\\t\\t\\tthis.length = 0;\\n\\t\\t\\t\\tthis.loopIndex = -1;\\n\\t\\t\\t\\tthis._sortBy = args.sortBy;\\n\\t\\t\\t\\tthis._sortHandler = this._doSort.bind(this);\\n\\t\\t}\\n}\\n\\nclass Tags extends EventHandler {\\n\\t\\tadd(...args) {\\n\\t\\t\\t\\tlet changed = false;\\n\\t\\t\\t\\tconst tags = this._processArguments(args, true);\\n\\t\\t\\t\\tif (!tags.length) {\\n\\t\\t\\t\\t\\t\\treturn changed;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < tags.length; i++){\\n\\t\\t\\t\\t\\t\\tif (this._index[tags[i]]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tchanged = true;\\n\\t\\t\\t\\t\\t\\tthis._index[tags[i]] = true;\\n\\t\\t\\t\\t\\t\\tthis._list.push(tags[i]);\\n\\t\\t\\t\\t\\t\\tthis.fire('add', tags[i], this._parent);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (changed) {\\n\\t\\t\\t\\t\\t\\tthis.fire('change', this._parent);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn changed;\\n\\t\\t}\\n\\t\\tremove(...args) {\\n\\t\\t\\t\\tlet changed = false;\\n\\t\\t\\t\\tif (!this._list.length) {\\n\\t\\t\\t\\t\\t\\treturn changed;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst tags = this._processArguments(args, true);\\n\\t\\t\\t\\tif (!tags.length) {\\n\\t\\t\\t\\t\\t\\treturn changed;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < tags.length; i++){\\n\\t\\t\\t\\t\\t\\tif (!this._index[tags[i]]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tchanged = true;\\n\\t\\t\\t\\t\\t\\tdelete this._index[tags[i]];\\n\\t\\t\\t\\t\\t\\tthis._list.splice(this._list.indexOf(tags[i]), 1);\\n\\t\\t\\t\\t\\t\\tthis.fire('remove', tags[i], this._parent);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (changed) {\\n\\t\\t\\t\\t\\t\\tthis.fire('change', this._parent);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn changed;\\n\\t\\t}\\n\\t\\tclear() {\\n\\t\\t\\t\\tif (!this._list.length) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst tags = this._list.slice(0);\\n\\t\\t\\t\\tthis._list = [];\\n\\t\\t\\t\\tthis._index = {};\\n\\t\\t\\t\\tfor(let i = 0; i < tags.length; i++){\\n\\t\\t\\t\\t\\t\\tthis.fire('remove', tags[i], this._parent);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.fire('change', this._parent);\\n\\t\\t}\\n\\t\\thas(...query) {\\n\\t\\t\\t\\tif (!this._list.length) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._has(this._processArguments(query));\\n\\t\\t}\\n\\t\\t_has(tags) {\\n\\t\\t\\t\\tif (!this._list.length || !tags.length) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < tags.length; i++){\\n\\t\\t\\t\\t\\t\\tif (tags[i].length === 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._index[tags[i][0]]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tlet multiple = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let t = 0; t < tags[i].length; t++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this._index[tags[i][t]]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmultiple = false;\\n\\t\\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\\tif (multiple) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tlist() {\\n\\t\\t\\t\\treturn this._list.slice(0);\\n\\t\\t}\\n\\t\\t_processArguments(args, flat) {\\n\\t\\t\\t\\tconst tags = [];\\n\\t\\t\\t\\tlet tmp = [];\\n\\t\\t\\t\\tif (!args || !args.length) {\\n\\t\\t\\t\\t\\t\\treturn tags;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < args.length; i++){\\n\\t\\t\\t\\t\\t\\tif (args[i] instanceof Array) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!flat) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttmp = [];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let t = 0; t < args[i].length; t++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (typeof args[i][t] !== 'string') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (flat) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttags.push(args[i][t]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttmp.push(args[i][t]);\\n\\t\\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\\tif (!flat && tmp.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttags.push(tmp);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else if (typeof args[i] === 'string') {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (flat) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttags.push(args[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttags.push([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\targs[i]\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn tags;\\n\\t\\t}\\n\\t\\tget size() {\\n\\t\\t\\t\\treturn this._list.length;\\n\\t\\t}\\n\\t\\tconstructor(parent){\\n\\t\\t\\t\\tsuper(), this._index = {}, this._list = [];\\n\\t\\t\\t\\tthis._parent = parent;\\n\\t\\t}\\n}\\nTags.EVENT_ADD = 'add';\\nTags.EVENT_REMOVE = 'remove';\\nTags.EVENT_CHANGE = 'change';\\n\\nconst now = typeof window !== 'undefined' && window.performance && window.performance.now ? performance.now.bind(performance) : Date.now;\\n\\nconst re = /^(([^:/?#]+):)?(\\\\/\\\\/([^/?#]*))?([^?#]*)(\\\\?([^#]*))?(#(.*))?/;\\nclass URI {\\n\\t\\ttoString() {\\n\\t\\t\\t\\tlet s = '';\\n\\t\\t\\t\\tif (this.scheme) {\\n\\t\\t\\t\\t\\t\\ts += `${this.scheme}:`;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.authority) {\\n\\t\\t\\t\\t\\t\\ts += `//${this.authority}`;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ts += this.path;\\n\\t\\t\\t\\tif (this.query) {\\n\\t\\t\\t\\t\\t\\ts += `?${this.query}`;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.fragment) {\\n\\t\\t\\t\\t\\t\\ts += `#${this.fragment}`;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn s;\\n\\t\\t}\\n\\t\\tgetQuery() {\\n\\t\\t\\t\\tconst result = {};\\n\\t\\t\\t\\tif (this.query) {\\n\\t\\t\\t\\t\\t\\tconst queryParams = decodeURIComponent(this.query).split('&');\\n\\t\\t\\t\\t\\t\\tfor (const queryParam of queryParams){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst pair = queryParam.split('=');\\n\\t\\t\\t\\t\\t\\t\\t\\tresult[pair[0]] = pair[1];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tsetQuery(params) {\\n\\t\\t\\t\\tlet q = '';\\n\\t\\t\\t\\tfor(const key in params){\\n\\t\\t\\t\\t\\t\\tif (params.hasOwnProperty(key)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (q !== '') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tq += '&';\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tq += `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.query = q;\\n\\t\\t}\\n\\t\\tconstructor(uri){\\n\\t\\t\\t\\tconst result = uri.match(re);\\n\\t\\t\\t\\tthis.scheme = result[2];\\n\\t\\t\\t\\tthis.authority = result[4];\\n\\t\\t\\t\\tthis.path = result[5];\\n\\t\\t\\t\\tthis.query = result[7];\\n\\t\\t\\t\\tthis.fragment = result[9];\\n\\t\\t}\\n}\\n\\nclass Tracing {\\n\\t\\tstatic set(channel, enabled = true) {}\\n\\t\\tstatic get(channel) {\\n\\t\\t\\t\\treturn Tracing._traceChannels.has(channel);\\n\\t\\t}\\n}\\nTracing._traceChannels = new Set();\\nTracing.stack = false;\\n\\nconst CURVE_LINEAR = 0;\\nconst CURVE_SMOOTHSTEP = 1;\\nconst CURVE_SPLINE = 4;\\nconst CURVE_STEP = 5;\\n\\nconst math = {\\n\\t\\tDEG_TO_RAD: Math.PI / 180,\\n\\t\\tRAD_TO_DEG: 180 / Math.PI,\\n\\t\\tclamp (value, min, max) {\\n\\t\\t\\t\\tif (value >= max) return max;\\n\\t\\t\\t\\tif (value <= min) return min;\\n\\t\\t\\t\\treturn value;\\n\\t\\t},\\n\\t\\tintToBytes24 (i) {\\n\\t\\t\\t\\tconst r = i >> 16 & 0xff;\\n\\t\\t\\t\\tconst g = i >> 8 & 0xff;\\n\\t\\t\\t\\tconst b = i & 0xff;\\n\\t\\t\\t\\treturn [\\n\\t\\t\\t\\t\\t\\tr,\\n\\t\\t\\t\\t\\t\\tg,\\n\\t\\t\\t\\t\\t\\tb\\n\\t\\t\\t\\t];\\n\\t\\t},\\n\\t\\tintToBytes32 (i) {\\n\\t\\t\\t\\tconst r = i >> 24 & 0xff;\\n\\t\\t\\t\\tconst g = i >> 16 & 0xff;\\n\\t\\t\\t\\tconst b = i >> 8 & 0xff;\\n\\t\\t\\t\\tconst a = i & 0xff;\\n\\t\\t\\t\\treturn [\\n\\t\\t\\t\\t\\t\\tr,\\n\\t\\t\\t\\t\\t\\tg,\\n\\t\\t\\t\\t\\t\\tb,\\n\\t\\t\\t\\t\\t\\ta\\n\\t\\t\\t\\t];\\n\\t\\t},\\n\\t\\tbytesToInt24 (r, g, b) {\\n\\t\\t\\t\\tif (r.length) {\\n\\t\\t\\t\\t\\t\\tb = r[2];\\n\\t\\t\\t\\t\\t\\tg = r[1];\\n\\t\\t\\t\\t\\t\\tr = r[0];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn r << 16 | g << 8 | b;\\n\\t\\t},\\n\\t\\tbytesToInt32 (r, g, b, a) {\\n\\t\\t\\t\\tif (r.length) {\\n\\t\\t\\t\\t\\t\\ta = r[3];\\n\\t\\t\\t\\t\\t\\tb = r[2];\\n\\t\\t\\t\\t\\t\\tg = r[1];\\n\\t\\t\\t\\t\\t\\tr = r[0];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn (r << 24 | g << 16 | b << 8 | a) >>> 0;\\n\\t\\t},\\n\\t\\tlerp (a, b, alpha) {\\n\\t\\t\\t\\treturn a + (b - a) * math.clamp(alpha, 0, 1);\\n\\t\\t},\\n\\t\\tlerpAngle (a, b, alpha) {\\n\\t\\t\\t\\tif (b - a > 180) {\\n\\t\\t\\t\\t\\t\\tb -= 360;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (b - a < -180) {\\n\\t\\t\\t\\t\\t\\tb += 360;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn math.lerp(a, b, math.clamp(alpha, 0, 1));\\n\\t\\t},\\n\\t\\tpowerOfTwo (x) {\\n\\t\\t\\t\\treturn x !== 0 && !(x & x - 1);\\n\\t\\t},\\n\\t\\tnextPowerOfTwo (val) {\\n\\t\\t\\t\\tval--;\\n\\t\\t\\t\\tval |= val >> 1;\\n\\t\\t\\t\\tval |= val >> 2;\\n\\t\\t\\t\\tval |= val >> 4;\\n\\t\\t\\t\\tval |= val >> 8;\\n\\t\\t\\t\\tval |= val >> 16;\\n\\t\\t\\t\\tval++;\\n\\t\\t\\t\\treturn val;\\n\\t\\t},\\n\\t\\tnearestPowerOfTwo (val) {\\n\\t\\t\\t\\treturn Math.pow(2, Math.round(Math.log2(val)));\\n\\t\\t},\\n\\t\\trandom (min, max) {\\n\\t\\t\\t\\tconst diff = max - min;\\n\\t\\t\\t\\treturn Math.random() * diff + min;\\n\\t\\t},\\n\\t\\tsmoothstep (min, max, x) {\\n\\t\\t\\t\\tif (x <= min) return 0;\\n\\t\\t\\t\\tif (x >= max) return 1;\\n\\t\\t\\t\\tx = (x - min) / (max - min);\\n\\t\\t\\t\\treturn x * x * (3 - 2 * x);\\n\\t\\t},\\n\\t\\tsmootherstep (min, max, x) {\\n\\t\\t\\t\\tif (x <= min) return 0;\\n\\t\\t\\t\\tif (x >= max) return 1;\\n\\t\\t\\t\\tx = (x - min) / (max - min);\\n\\t\\t\\t\\treturn x * x * x * (x * (x * 6 - 15) + 10);\\n\\t\\t},\\n\\t\\troundUp (numToRound, multiple) {\\n\\t\\t\\t\\tif (multiple === 0) {\\n\\t\\t\\t\\t\\t\\treturn numToRound;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn Math.ceil(numToRound / multiple) * multiple;\\n\\t\\t},\\n\\t\\tbetween (num, a, b, inclusive) {\\n\\t\\t\\t\\tconst min = Math.min(a, b);\\n\\t\\t\\t\\tconst max = Math.max(a, b);\\n\\t\\t\\t\\treturn inclusive ? num >= min && num <= max : num > min && num < max;\\n\\t\\t}\\n};\\n\\nclass Color {\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst cstr = this.constructor;\\n\\t\\t\\t\\treturn new cstr(this.r, this.g, this.b, this.a);\\n\\t\\t}\\n\\t\\tcopy(rhs) {\\n\\t\\t\\t\\tthis.r = rhs.r;\\n\\t\\t\\t\\tthis.g = rhs.g;\\n\\t\\t\\t\\tthis.b = rhs.b;\\n\\t\\t\\t\\tthis.a = rhs.a;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tequals(rhs) {\\n\\t\\t\\t\\treturn this.r === rhs.r && this.g === rhs.g && this.b === rhs.b && this.a === rhs.a;\\n\\t\\t}\\n\\t\\tset(r, g, b, a = 1) {\\n\\t\\t\\t\\tthis.r = r;\\n\\t\\t\\t\\tthis.g = g;\\n\\t\\t\\t\\tthis.b = b;\\n\\t\\t\\t\\tthis.a = a;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tlerp(lhs, rhs, alpha) {\\n\\t\\t\\t\\tthis.r = lhs.r + alpha * (rhs.r - lhs.r);\\n\\t\\t\\t\\tthis.g = lhs.g + alpha * (rhs.g - lhs.g);\\n\\t\\t\\t\\tthis.b = lhs.b + alpha * (rhs.b - lhs.b);\\n\\t\\t\\t\\tthis.a = lhs.a + alpha * (rhs.a - lhs.a);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tlinear(src = this) {\\n\\t\\t\\t\\tthis.r = Math.pow(src.r, 2.2);\\n\\t\\t\\t\\tthis.g = Math.pow(src.g, 2.2);\\n\\t\\t\\t\\tthis.b = Math.pow(src.b, 2.2);\\n\\t\\t\\t\\tthis.a = src.a;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tgamma(src = this) {\\n\\t\\t\\t\\tthis.r = Math.pow(src.r, 1 / 2.2);\\n\\t\\t\\t\\tthis.g = Math.pow(src.g, 1 / 2.2);\\n\\t\\t\\t\\tthis.b = Math.pow(src.b, 1 / 2.2);\\n\\t\\t\\t\\tthis.a = src.a;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmulScalar(scalar) {\\n\\t\\t\\t\\tthis.r *= scalar;\\n\\t\\t\\t\\tthis.g *= scalar;\\n\\t\\t\\t\\tthis.b *= scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tfromString(hex) {\\n\\t\\t\\t\\tconst i = parseInt(hex.replace('#', '0x'), 16);\\n\\t\\t\\t\\tlet bytes;\\n\\t\\t\\t\\tif (hex.length > 7) {\\n\\t\\t\\t\\t\\t\\tbytes = math.intToBytes32(i);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tbytes = math.intToBytes24(i);\\n\\t\\t\\t\\t\\t\\tbytes[3] = 255;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.set(bytes[0] / 255, bytes[1] / 255, bytes[2] / 255, bytes[3] / 255);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tfromArray(arr, offset = 0) {\\n\\t\\t\\t\\tthis.r = arr[offset] ?? this.r;\\n\\t\\t\\t\\tthis.g = arr[offset + 1] ?? this.g;\\n\\t\\t\\t\\tthis.b = arr[offset + 2] ?? this.b;\\n\\t\\t\\t\\tthis.a = arr[offset + 3] ?? this.a;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\ttoString(alpha, asArray) {\\n\\t\\t\\t\\tconst { r, g, b, a } = this;\\n\\t\\t\\t\\tif (asArray || r > 1 || g > 1 || b > 1) {\\n\\t\\t\\t\\t\\t\\treturn `${r.toFixed(3)}, ${g.toFixed(3)}, ${b.toFixed(3)}, ${a.toFixed(3)}`;\\n\\t\\t\\t\\t}\\n\\t\\t\\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\\t\\t\\tif (alpha === true) {\\n\\t\\t\\t\\t\\t\\tconst aa = Math.round(a * 255).toString(16);\\n\\t\\t\\t\\t\\t\\tif (this.a < 16 / 255) {\\n\\t\\t\\t\\t\\t\\t\\t\\ts += `0${aa}`;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\ts += aa;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn s;\\n\\t\\t}\\n\\t\\ttoArray(arr = [], offset = 0, alpha = true) {\\n\\t\\t\\t\\tarr[offset] = this.r;\\n\\t\\t\\t\\tarr[offset + 1] = this.g;\\n\\t\\t\\t\\tarr[offset + 2] = this.b;\\n\\t\\t\\t\\tif (alpha) {\\n\\t\\t\\t\\t\\t\\tarr[offset + 3] = this.a;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn arr;\\n\\t\\t}\\n\\t\\tconstructor(r = 0, g = 0, b = 0, a = 1){\\n\\t\\t\\t\\tconst length = r.length;\\n\\t\\t\\t\\tif (length === 3 || length === 4) {\\n\\t\\t\\t\\t\\t\\tthis.r = r[0];\\n\\t\\t\\t\\t\\t\\tthis.g = r[1];\\n\\t\\t\\t\\t\\t\\tthis.b = r[2];\\n\\t\\t\\t\\t\\t\\tthis.a = r[3] ?? 1;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.r = r;\\n\\t\\t\\t\\t\\t\\tthis.g = g;\\n\\t\\t\\t\\t\\t\\tthis.b = b;\\n\\t\\t\\t\\t\\t\\tthis.a = a;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nColor.BLACK = Object.freeze(new Color(0, 0, 0, 1));\\nColor.BLUE = Object.freeze(new Color(0, 0, 1, 1));\\nColor.CYAN = Object.freeze(new Color(0, 1, 1, 1));\\nColor.GRAY = Object.freeze(new Color(0.5, 0.5, 0.5, 1));\\nColor.GREEN = Object.freeze(new Color(0, 1, 0, 1));\\nColor.MAGENTA = Object.freeze(new Color(1, 0, 1, 1));\\nColor.RED = Object.freeze(new Color(1, 0, 0, 1));\\nColor.WHITE = Object.freeze(new Color(1, 1, 1, 1));\\nColor.YELLOW = Object.freeze(new Color(1, 1, 0, 1));\\n\\nclass CurveEvaluator {\\n\\t\\tevaluate(time, forceReset = false) {\\n\\t\\t\\t\\tif (forceReset || time < this._left || time >= this._right) {\\n\\t\\t\\t\\t\\t\\tthis._reset(time);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet result;\\n\\t\\t\\t\\tconst type = this._curve.type;\\n\\t\\t\\t\\tif (type === CURVE_STEP) {\\n\\t\\t\\t\\t\\t\\tresult = this._p0;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst t = this._recip === 0 ? 0 : (time - this._left) * this._recip;\\n\\t\\t\\t\\t\\t\\tif (type === CURVE_LINEAR) {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult = math.lerp(this._p0, this._p1, t);\\n\\t\\t\\t\\t\\t\\t} else if (type === CURVE_SMOOTHSTEP) {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult = math.lerp(this._p0, this._p1, t * t * (3 - 2 * t));\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult = this._evaluateHermite(this._p0, this._p1, this._m0, this._m1, t);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\t_reset(time) {\\n\\t\\t\\t\\tconst keys = this._curve.keys;\\n\\t\\t\\t\\tconst len = keys.length;\\n\\t\\t\\t\\tif (!len) {\\n\\t\\t\\t\\t\\t\\tthis._left = -Infinity;\\n\\t\\t\\t\\t\\t\\tthis._right = Infinity;\\n\\t\\t\\t\\t\\t\\tthis._recip = 0;\\n\\t\\t\\t\\t\\t\\tthis._p0 = this._p1 = this._m0 = this._m1 = 0;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (time < keys[0][0]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._left = -Infinity;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._right = keys[0][0];\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._recip = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._p0 = this._p1 = keys[0][1];\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._m0 = this._m1 = 0;\\n\\t\\t\\t\\t\\t\\t} else if (time >= keys[len - 1][0]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._left = keys[len - 1][0];\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._right = Infinity;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._recip = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._p0 = this._p1 = keys[len - 1][1];\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._m0 = this._m1 = 0;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tlet index = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\twhile(time >= keys[index + 1][0]){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindex++;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._left = keys[index][0];\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._right = keys[index + 1][0];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst diff = 1.0 / (this._right - this._left);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._recip = isFinite(diff) ? diff : 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._p0 = keys[index][1];\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._p1 = keys[index + 1][1];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._curve.type === CURVE_SPLINE) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._calcTangents(keys, index);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_calcTangents(keys, index) {\\n\\t\\t\\t\\tlet a;\\n\\t\\t\\t\\tconst b = keys[index];\\n\\t\\t\\t\\tconst c = keys[index + 1];\\n\\t\\t\\t\\tlet d;\\n\\t\\t\\t\\tif (index === 0) {\\n\\t\\t\\t\\t\\t\\ta = [\\n\\t\\t\\t\\t\\t\\t\\t\\tkeys[0][0] + (keys[0][0] - keys[1][0]),\\n\\t\\t\\t\\t\\t\\t\\t\\tkeys[0][1] + (keys[0][1] - keys[1][1])\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\ta = keys[index - 1];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (index === keys.length - 2) {\\n\\t\\t\\t\\t\\t\\td = [\\n\\t\\t\\t\\t\\t\\t\\t\\tkeys[index + 1][0] + (keys[index + 1][0] - keys[index][0]),\\n\\t\\t\\t\\t\\t\\t\\t\\tkeys[index + 1][1] + (keys[index + 1][1] - keys[index][1])\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\td = keys[index + 2];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._curve.type === CURVE_SPLINE) {\\n\\t\\t\\t\\t\\t\\tconst s1_ = 2 * (c[0] - b[0]) / (c[0] - a[0]);\\n\\t\\t\\t\\t\\t\\tconst s2_ = 2 * (c[0] - b[0]) / (d[0] - b[0]);\\n\\t\\t\\t\\t\\t\\tthis._m0 = this._curve.tension * (isFinite(s1_) ? s1_ : 0) * (c[1] - a[1]);\\n\\t\\t\\t\\t\\t\\tthis._m1 = this._curve.tension * (isFinite(s2_) ? s2_ : 0) * (d[1] - b[1]);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst s1 = (c[0] - b[0]) / (b[0] - a[0]);\\n\\t\\t\\t\\t\\t\\tconst s2 = (c[0] - b[0]) / (d[0] - c[0]);\\n\\t\\t\\t\\t\\t\\tconst a_ = b[1] + (a[1] - b[1]) * (isFinite(s1) ? s1 : 0);\\n\\t\\t\\t\\t\\t\\tconst d_ = c[1] + (d[1] - c[1]) * (isFinite(s2) ? s2 : 0);\\n\\t\\t\\t\\t\\t\\tconst tension = this._curve.tension;\\n\\t\\t\\t\\t\\t\\tthis._m0 = tension * (c[1] - a_);\\n\\t\\t\\t\\t\\t\\tthis._m1 = tension * (d_ - b[1]);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_evaluateHermite(p0, p1, m0, m1, t) {\\n\\t\\t\\t\\tconst t2 = t * t;\\n\\t\\t\\t\\tconst twot = t + t;\\n\\t\\t\\t\\tconst omt = 1 - t;\\n\\t\\t\\t\\tconst omt2 = omt * omt;\\n\\t\\t\\t\\treturn p0 * ((1 + twot) * omt2) + m0 * (t * omt2) + p1 * (t2 * (3 - twot)) + m1 * (t2 * (t - 1));\\n\\t\\t}\\n\\t\\tconstructor(curve, time = 0){\\n\\t\\t\\t\\tthis._left = -Infinity;\\n\\t\\t\\t\\tthis._right = Infinity;\\n\\t\\t\\t\\tthis._recip = 0;\\n\\t\\t\\t\\tthis._p0 = 0;\\n\\t\\t\\t\\tthis._p1 = 0;\\n\\t\\t\\t\\tthis._m0 = 0;\\n\\t\\t\\t\\tthis._m1 = 0;\\n\\t\\t\\t\\tthis._curve = curve;\\n\\t\\t\\t\\tthis._reset(time);\\n\\t\\t}\\n}\\n\\nclass Curve {\\n\\t\\tget length() {\\n\\t\\t\\t\\treturn this.keys.length;\\n\\t\\t}\\n\\t\\tadd(time, value) {\\n\\t\\t\\t\\tconst keys = this.keys;\\n\\t\\t\\t\\tconst len = keys.length;\\n\\t\\t\\t\\tlet i = 0;\\n\\t\\t\\t\\tfor(; i < len; i++){\\n\\t\\t\\t\\t\\t\\tif (keys[i][0] > time) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst key = [\\n\\t\\t\\t\\t\\t\\ttime,\\n\\t\\t\\t\\t\\t\\tvalue\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.keys.splice(i, 0, key);\\n\\t\\t\\t\\treturn key;\\n\\t\\t}\\n\\t\\tget(index) {\\n\\t\\t\\t\\treturn this.keys[index];\\n\\t\\t}\\n\\t\\tsort() {\\n\\t\\t\\t\\tthis.keys.sort((a, b)=>a[0] - b[0]);\\n\\t\\t}\\n\\t\\tvalue(time) {\\n\\t\\t\\t\\treturn this._eval.evaluate(time, true);\\n\\t\\t}\\n\\t\\tclosest(time) {\\n\\t\\t\\t\\tconst keys = this.keys;\\n\\t\\t\\t\\tconst length = keys.length;\\n\\t\\t\\t\\tlet min = 2;\\n\\t\\t\\t\\tlet result = null;\\n\\t\\t\\t\\tfor(let i = 0; i < length; i++){\\n\\t\\t\\t\\t\\t\\tconst diff = Math.abs(time - keys[i][0]);\\n\\t\\t\\t\\t\\t\\tif (min >= diff) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmin = diff;\\n\\t\\t\\t\\t\\t\\t\\t\\tresult = keys[i];\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst result = new this.constructor();\\n\\t\\t\\t\\tresult.keys = this.keys.map((key)=>[\\n\\t\\t\\t\\t\\t\\t\\t\\t...key\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\tresult.type = this.type;\\n\\t\\t\\t\\tresult.tension = this.tension;\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tquantize(precision) {\\n\\t\\t\\t\\tprecision = Math.max(precision, 2);\\n\\t\\t\\t\\tconst values = new Float32Array(precision);\\n\\t\\t\\t\\tconst step = 1.0 / (precision - 1);\\n\\t\\t\\t\\tvalues[0] = this._eval.evaluate(0, true);\\n\\t\\t\\t\\tfor(let i = 1; i < precision; i++){\\n\\t\\t\\t\\t\\t\\tvalues[i] = this._eval.evaluate(step * i);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn values;\\n\\t\\t}\\n\\t\\tquantizeClamped(precision, min, max) {\\n\\t\\t\\t\\tconst result = this.quantize(precision);\\n\\t\\t\\t\\tfor(let i = 0; i < result.length; ++i){\\n\\t\\t\\t\\t\\t\\tresult[i] = Math.min(max, Math.max(min, result[i]));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tconstructor(data){\\n\\t\\t\\t\\tthis.keys = [];\\n\\t\\t\\t\\tthis.type = CURVE_SMOOTHSTEP;\\n\\t\\t\\t\\tthis.tension = 0.5;\\n\\t\\t\\t\\tthis._eval = new CurveEvaluator(this);\\n\\t\\t\\t\\tif (data) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < data.length - 1; i += 2){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.keys.push([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata[i],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata[i + 1]\\n\\t\\t\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.sort();\\n\\t\\t}\\n}\\n\\nclass CurveSet {\\n\\t\\tget length() {\\n\\t\\t\\t\\treturn this.curves.length;\\n\\t\\t}\\n\\t\\tset type(value) {\\n\\t\\t\\t\\tthis._type = value;\\n\\t\\t\\t\\tfor(let i = 0; i < this.curves.length; i++){\\n\\t\\t\\t\\t\\t\\tthis.curves[i].type = value;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget type() {\\n\\t\\t\\t\\treturn this._type;\\n\\t\\t}\\n\\t\\tget(index) {\\n\\t\\t\\t\\treturn this.curves[index];\\n\\t\\t}\\n\\t\\tvalue(time, result = []) {\\n\\t\\t\\t\\tconst length = this.curves.length;\\n\\t\\t\\t\\tresult.length = length;\\n\\t\\t\\t\\tfor(let i = 0; i < length; i++){\\n\\t\\t\\t\\t\\t\\tresult[i] = this.curves[i].value(time);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst result = new this.constructor();\\n\\t\\t\\t\\tresult.curves = [];\\n\\t\\t\\t\\tfor(let i = 0; i < this.curves.length; i++){\\n\\t\\t\\t\\t\\t\\tresult.curves.push(this.curves[i].clone());\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tresult._type = this._type;\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tquantize(precision) {\\n\\t\\t\\t\\tprecision = Math.max(precision, 2);\\n\\t\\t\\t\\tconst numCurves = this.curves.length;\\n\\t\\t\\t\\tconst values = new Float32Array(precision * numCurves);\\n\\t\\t\\t\\tconst step = 1.0 / (precision - 1);\\n\\t\\t\\t\\tfor(let c = 0; c < numCurves; c++){\\n\\t\\t\\t\\t\\t\\tconst ev = new CurveEvaluator(this.curves[c]);\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < precision; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tvalues[i * numCurves + c] = ev.evaluate(step * i);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn values;\\n\\t\\t}\\n\\t\\tquantizeClamped(precision, min, max) {\\n\\t\\t\\t\\tconst result = this.quantize(precision);\\n\\t\\t\\t\\tfor(let i = 0; i < result.length; ++i){\\n\\t\\t\\t\\t\\t\\tresult[i] = Math.min(max, Math.max(min, result[i]));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tconstructor(...args){\\n\\t\\t\\t\\tthis.curves = [];\\n\\t\\t\\t\\tthis._type = CURVE_SMOOTHSTEP;\\n\\t\\t\\t\\tif (args.length > 1) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < args.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.curves.push(new Curve(args[i]));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else if (args.length === 0) {\\n\\t\\t\\t\\t\\t\\tthis.curves.push(new Curve());\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst arg = args[0];\\n\\t\\t\\t\\t\\t\\tif (typeof arg === 'number') {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < arg; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.curves.push(new Curve());\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < arg.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.curves.push(new Curve(arg[i]));\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nconst floatView = new Float32Array(1);\\nconst int32View = new Int32Array(floatView.buffer);\\nclass FloatPacking {\\n\\t\\tstatic float2Half(value) {\\n\\t\\t\\t\\tfloatView[0] = value;\\n\\t\\t\\t\\tconst x = int32View[0];\\n\\t\\t\\t\\tlet bits = x >> 16 & 0x8000;\\n\\t\\t\\t\\tlet m = x >> 12 & 0x07ff;\\n\\t\\t\\t\\tconst e = x >> 23 & 0xff;\\n\\t\\t\\t\\tif (e < 103) {\\n\\t\\t\\t\\t\\t\\treturn bits;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (e > 142) {\\n\\t\\t\\t\\t\\t\\tbits |= 0x7c00;\\n\\t\\t\\t\\t\\t\\tbits |= (e === 255 ? 0 : 1) && x & 0x007fffff;\\n\\t\\t\\t\\t\\t\\treturn bits;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (e < 113) {\\n\\t\\t\\t\\t\\t\\tm |= 0x0800;\\n\\t\\t\\t\\t\\t\\tbits |= (m >> 114 - e) + (m >> 113 - e & 1);\\n\\t\\t\\t\\t\\t\\treturn bits;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tbits |= e - 112 << 10 | m >> 1;\\n\\t\\t\\t\\tbits += m & 1;\\n\\t\\t\\t\\treturn bits;\\n\\t\\t}\\n\\t\\tstatic float2RGBA8(value, data) {\\n\\t\\t\\t\\tfloatView[0] = value;\\n\\t\\t\\t\\tconst intBits = int32View[0];\\n\\t\\t\\t\\tdata.r = (intBits >> 24 & 0xFF) / 255.0;\\n\\t\\t\\t\\tdata.g = (intBits >> 16 & 0xFF) / 255.0;\\n\\t\\t\\t\\tdata.b = (intBits >> 8 & 0xFF) / 255.0;\\n\\t\\t\\t\\tdata.a = (intBits & 0xFF) / 255.0;\\n\\t\\t}\\n}\\n\\nclass Kernel {\\n\\t\\tstatic concentric(numRings, numPoints) {\\n\\t\\t\\t\\tconst kernel = [];\\n\\t\\t\\t\\tkernel.push(0, 0);\\n\\t\\t\\t\\tconst spacing = 2 * Math.PI / numRings / numPoints;\\n\\t\\t\\t\\tfor(let ring = 1; ring <= numRings; ring++){\\n\\t\\t\\t\\t\\t\\tconst radius = ring / numRings;\\n\\t\\t\\t\\t\\t\\tconst circumference = 2 * Math.PI * radius;\\n\\t\\t\\t\\t\\t\\tconst pointsPerRing = Math.max(1, Math.floor(circumference / spacing));\\n\\t\\t\\t\\t\\t\\tconst angleStep = 2 * Math.PI / pointsPerRing;\\n\\t\\t\\t\\t\\t\\tfor(let point = 0; point < pointsPerRing; point++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst angle = point * angleStep;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst x = radius * Math.cos(angle);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst y = radius * Math.sin(angle);\\n\\t\\t\\t\\t\\t\\t\\t\\tkernel.push(x, y);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn kernel;\\n\\t\\t}\\n}\\n\\nclass Vec3 {\\n\\t\\tadd(rhs) {\\n\\t\\t\\t\\tthis.x += rhs.x;\\n\\t\\t\\t\\tthis.y += rhs.y;\\n\\t\\t\\t\\tthis.z += rhs.z;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tadd2(lhs, rhs) {\\n\\t\\t\\t\\tthis.x = lhs.x + rhs.x;\\n\\t\\t\\t\\tthis.y = lhs.y + rhs.y;\\n\\t\\t\\t\\tthis.z = lhs.z + rhs.z;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\taddScalar(scalar) {\\n\\t\\t\\t\\tthis.x += scalar;\\n\\t\\t\\t\\tthis.y += scalar;\\n\\t\\t\\t\\tthis.z += scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\taddScaled(rhs, scalar) {\\n\\t\\t\\t\\tthis.x += rhs.x * scalar;\\n\\t\\t\\t\\tthis.y += rhs.y * scalar;\\n\\t\\t\\t\\tthis.z += rhs.z * scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst cstr = this.constructor;\\n\\t\\t\\t\\treturn new cstr(this.x, this.y, this.z);\\n\\t\\t}\\n\\t\\tcopy(rhs) {\\n\\t\\t\\t\\tthis.x = rhs.x;\\n\\t\\t\\t\\tthis.y = rhs.y;\\n\\t\\t\\t\\tthis.z = rhs.z;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tcross(lhs, rhs) {\\n\\t\\t\\t\\tconst lx = lhs.x;\\n\\t\\t\\t\\tconst ly = lhs.y;\\n\\t\\t\\t\\tconst lz = lhs.z;\\n\\t\\t\\t\\tconst rx = rhs.x;\\n\\t\\t\\t\\tconst ry = rhs.y;\\n\\t\\t\\t\\tconst rz = rhs.z;\\n\\t\\t\\t\\tthis.x = ly * rz - ry * lz;\\n\\t\\t\\t\\tthis.y = lz * rx - rz * lx;\\n\\t\\t\\t\\tthis.z = lx * ry - rx * ly;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tdistance(rhs) {\\n\\t\\t\\t\\tconst x = this.x - rhs.x;\\n\\t\\t\\t\\tconst y = this.y - rhs.y;\\n\\t\\t\\t\\tconst z = this.z - rhs.z;\\n\\t\\t\\t\\treturn Math.sqrt(x * x + y * y + z * z);\\n\\t\\t}\\n\\t\\tdiv(rhs) {\\n\\t\\t\\t\\tthis.x /= rhs.x;\\n\\t\\t\\t\\tthis.y /= rhs.y;\\n\\t\\t\\t\\tthis.z /= rhs.z;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tdiv2(lhs, rhs) {\\n\\t\\t\\t\\tthis.x = lhs.x / rhs.x;\\n\\t\\t\\t\\tthis.y = lhs.y / rhs.y;\\n\\t\\t\\t\\tthis.z = lhs.z / rhs.z;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tdivScalar(scalar) {\\n\\t\\t\\t\\tthis.x /= scalar;\\n\\t\\t\\t\\tthis.y /= scalar;\\n\\t\\t\\t\\tthis.z /= scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tdot(rhs) {\\n\\t\\t\\t\\treturn this.x * rhs.x + this.y * rhs.y + this.z * rhs.z;\\n\\t\\t}\\n\\t\\tequals(rhs) {\\n\\t\\t\\t\\treturn this.x === rhs.x && this.y === rhs.y && this.z === rhs.z;\\n\\t\\t}\\n\\t\\tequalsApprox(rhs, epsilon = 1e-6) {\\n\\t\\t\\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\\t}\\n\\t\\tlength() {\\n\\t\\t\\t\\treturn Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);\\n\\t\\t}\\n\\t\\tlengthSq() {\\n\\t\\t\\t\\treturn this.x * this.x + this.y * this.y + this.z * this.z;\\n\\t\\t}\\n\\t\\tlerp(lhs, rhs, alpha) {\\n\\t\\t\\t\\tthis.x = lhs.x + alpha * (rhs.x - lhs.x);\\n\\t\\t\\t\\tthis.y = lhs.y + alpha * (rhs.y - lhs.y);\\n\\t\\t\\t\\tthis.z = lhs.z + alpha * (rhs.z - lhs.z);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmul(rhs) {\\n\\t\\t\\t\\tthis.x *= rhs.x;\\n\\t\\t\\t\\tthis.y *= rhs.y;\\n\\t\\t\\t\\tthis.z *= rhs.z;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmul2(lhs, rhs) {\\n\\t\\t\\t\\tthis.x = lhs.x * rhs.x;\\n\\t\\t\\t\\tthis.y = lhs.y * rhs.y;\\n\\t\\t\\t\\tthis.z = lhs.z * rhs.z;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmulScalar(scalar) {\\n\\t\\t\\t\\tthis.x *= scalar;\\n\\t\\t\\t\\tthis.y *= scalar;\\n\\t\\t\\t\\tthis.z *= scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tnormalize(src = this) {\\n\\t\\t\\t\\tconst lengthSq = src.x * src.x + src.y * src.y + src.z * src.z;\\n\\t\\t\\t\\tif (lengthSq > 0) {\\n\\t\\t\\t\\t\\t\\tconst invLength = 1 / Math.sqrt(lengthSq);\\n\\t\\t\\t\\t\\t\\tthis.x = src.x * invLength;\\n\\t\\t\\t\\t\\t\\tthis.y = src.y * invLength;\\n\\t\\t\\t\\t\\t\\tthis.z = src.z * invLength;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tfloor(src = this) {\\n\\t\\t\\t\\tthis.x = Math.floor(src.x);\\n\\t\\t\\t\\tthis.y = Math.floor(src.y);\\n\\t\\t\\t\\tthis.z = Math.floor(src.z);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tceil(src = this) {\\n\\t\\t\\t\\tthis.x = Math.ceil(src.x);\\n\\t\\t\\t\\tthis.y = Math.ceil(src.y);\\n\\t\\t\\t\\tthis.z = Math.ceil(src.z);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tround(src = this) {\\n\\t\\t\\t\\tthis.x = Math.round(src.x);\\n\\t\\t\\t\\tthis.y = Math.round(src.y);\\n\\t\\t\\t\\tthis.z = Math.round(src.z);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmin(rhs) {\\n\\t\\t\\t\\tif (rhs.x < this.x) this.x = rhs.x;\\n\\t\\t\\t\\tif (rhs.y < this.y) this.y = rhs.y;\\n\\t\\t\\t\\tif (rhs.z < this.z) this.z = rhs.z;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmax(rhs) {\\n\\t\\t\\t\\tif (rhs.x > this.x) this.x = rhs.x;\\n\\t\\t\\t\\tif (rhs.y > this.y) this.y = rhs.y;\\n\\t\\t\\t\\tif (rhs.z > this.z) this.z = rhs.z;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tproject(rhs) {\\n\\t\\t\\t\\tconst a_dot_b = this.x * rhs.x + this.y * rhs.y + this.z * rhs.z;\\n\\t\\t\\t\\tconst b_dot_b = rhs.x * rhs.x + rhs.y * rhs.y + rhs.z * rhs.z;\\n\\t\\t\\t\\tconst s = a_dot_b / b_dot_b;\\n\\t\\t\\t\\tthis.x = rhs.x * s;\\n\\t\\t\\t\\tthis.y = rhs.y * s;\\n\\t\\t\\t\\tthis.z = rhs.z * s;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tset(x, y, z) {\\n\\t\\t\\t\\tthis.x = x;\\n\\t\\t\\t\\tthis.y = y;\\n\\t\\t\\t\\tthis.z = z;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsub(rhs) {\\n\\t\\t\\t\\tthis.x -= rhs.x;\\n\\t\\t\\t\\tthis.y -= rhs.y;\\n\\t\\t\\t\\tthis.z -= rhs.z;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsub2(lhs, rhs) {\\n\\t\\t\\t\\tthis.x = lhs.x - rhs.x;\\n\\t\\t\\t\\tthis.y = lhs.y - rhs.y;\\n\\t\\t\\t\\tthis.z = lhs.z - rhs.z;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsubScalar(scalar) {\\n\\t\\t\\t\\tthis.x -= scalar;\\n\\t\\t\\t\\tthis.y -= scalar;\\n\\t\\t\\t\\tthis.z -= scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tfromArray(arr, offset = 0) {\\n\\t\\t\\t\\tthis.x = arr[offset] ?? this.x;\\n\\t\\t\\t\\tthis.y = arr[offset + 1] ?? this.y;\\n\\t\\t\\t\\tthis.z = arr[offset + 2] ?? this.z;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\ttoString() {\\n\\t\\t\\t\\treturn `[${this.x}, ${this.y}, ${this.z}]`;\\n\\t\\t}\\n\\t\\ttoArray(arr = [], offset = 0) {\\n\\t\\t\\t\\tarr[offset] = this.x;\\n\\t\\t\\t\\tarr[offset + 1] = this.y;\\n\\t\\t\\t\\tarr[offset + 2] = this.z;\\n\\t\\t\\t\\treturn arr;\\n\\t\\t}\\n\\t\\tconstructor(x = 0, y = 0, z = 0){\\n\\t\\t\\t\\tif (x.length === 3) {\\n\\t\\t\\t\\t\\t\\tthis.x = x[0];\\n\\t\\t\\t\\t\\t\\tthis.y = x[1];\\n\\t\\t\\t\\t\\t\\tthis.z = x[2];\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.x = x;\\n\\t\\t\\t\\t\\t\\tthis.y = y;\\n\\t\\t\\t\\t\\t\\tthis.z = z;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nVec3.ZERO = Object.freeze(new Vec3(0, 0, 0));\\nVec3.HALF = Object.freeze(new Vec3(0.5, 0.5, 0.5));\\nVec3.ONE = Object.freeze(new Vec3(1, 1, 1));\\nVec3.UP = Object.freeze(new Vec3(0, 1, 0));\\nVec3.DOWN = Object.freeze(new Vec3(0, -1, 0));\\nVec3.RIGHT = Object.freeze(new Vec3(1, 0, 0));\\nVec3.LEFT = Object.freeze(new Vec3(-1, 0, 0));\\nVec3.FORWARD = Object.freeze(new Vec3(0, 0, -1));\\nVec3.BACK = Object.freeze(new Vec3(0, 0, 1));\\n\\nclass Mat3 {\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst cstr = this.constructor;\\n\\t\\t\\t\\treturn new cstr().copy(this);\\n\\t\\t}\\n\\t\\tcopy(rhs) {\\n\\t\\t\\t\\tconst src = rhs.data;\\n\\t\\t\\t\\tconst dst = this.data;\\n\\t\\t\\t\\tdst[0] = src[0];\\n\\t\\t\\t\\tdst[1] = src[1];\\n\\t\\t\\t\\tdst[2] = src[2];\\n\\t\\t\\t\\tdst[3] = src[3];\\n\\t\\t\\t\\tdst[4] = src[4];\\n\\t\\t\\t\\tdst[5] = src[5];\\n\\t\\t\\t\\tdst[6] = src[6];\\n\\t\\t\\t\\tdst[7] = src[7];\\n\\t\\t\\t\\tdst[8] = src[8];\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tset(src) {\\n\\t\\t\\t\\tconst dst = this.data;\\n\\t\\t\\t\\tdst[0] = src[0];\\n\\t\\t\\t\\tdst[1] = src[1];\\n\\t\\t\\t\\tdst[2] = src[2];\\n\\t\\t\\t\\tdst[3] = src[3];\\n\\t\\t\\t\\tdst[4] = src[4];\\n\\t\\t\\t\\tdst[5] = src[5];\\n\\t\\t\\t\\tdst[6] = src[6];\\n\\t\\t\\t\\tdst[7] = src[7];\\n\\t\\t\\t\\tdst[8] = src[8];\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tgetX(x = new Vec3()) {\\n\\t\\t\\t\\treturn x.set(this.data[0], this.data[1], this.data[2]);\\n\\t\\t}\\n\\t\\tgetY(y = new Vec3()) {\\n\\t\\t\\t\\treturn y.set(this.data[3], this.data[4], this.data[5]);\\n\\t\\t}\\n\\t\\tgetZ(z = new Vec3()) {\\n\\t\\t\\t\\treturn z.set(this.data[6], this.data[7], this.data[8]);\\n\\t\\t}\\n\\t\\tequals(rhs) {\\n\\t\\t\\t\\tconst l = this.data;\\n\\t\\t\\t\\tconst r = rhs.data;\\n\\t\\t\\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\\t}\\n\\t\\tisIdentity() {\\n\\t\\t\\t\\tconst m = this.data;\\n\\t\\t\\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\\t}\\n\\t\\tsetIdentity() {\\n\\t\\t\\t\\tconst m = this.data;\\n\\t\\t\\t\\tm[0] = 1;\\n\\t\\t\\t\\tm[1] = 0;\\n\\t\\t\\t\\tm[2] = 0;\\n\\t\\t\\t\\tm[3] = 0;\\n\\t\\t\\t\\tm[4] = 1;\\n\\t\\t\\t\\tm[5] = 0;\\n\\t\\t\\t\\tm[6] = 0;\\n\\t\\t\\t\\tm[7] = 0;\\n\\t\\t\\t\\tm[8] = 1;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\ttoString() {\\n\\t\\t\\t\\treturn `[${this.data.join(', ')}]`;\\n\\t\\t}\\n\\t\\ttranspose(src = this) {\\n\\t\\t\\t\\tconst s = src.data;\\n\\t\\t\\t\\tconst t = this.data;\\n\\t\\t\\t\\tif (s === t) {\\n\\t\\t\\t\\t\\t\\tlet tmp;\\n\\t\\t\\t\\t\\t\\ttmp = s[1];\\n\\t\\t\\t\\t\\t\\tt[1] = s[3];\\n\\t\\t\\t\\t\\t\\tt[3] = tmp;\\n\\t\\t\\t\\t\\t\\ttmp = s[2];\\n\\t\\t\\t\\t\\t\\tt[2] = s[6];\\n\\t\\t\\t\\t\\t\\tt[6] = tmp;\\n\\t\\t\\t\\t\\t\\ttmp = s[5];\\n\\t\\t\\t\\t\\t\\tt[5] = s[7];\\n\\t\\t\\t\\t\\t\\tt[7] = tmp;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tt[0] = s[0];\\n\\t\\t\\t\\t\\t\\tt[1] = s[3];\\n\\t\\t\\t\\t\\t\\tt[2] = s[6];\\n\\t\\t\\t\\t\\t\\tt[3] = s[1];\\n\\t\\t\\t\\t\\t\\tt[4] = s[4];\\n\\t\\t\\t\\t\\t\\tt[5] = s[7];\\n\\t\\t\\t\\t\\t\\tt[6] = s[2];\\n\\t\\t\\t\\t\\t\\tt[7] = s[5];\\n\\t\\t\\t\\t\\t\\tt[8] = s[8];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetFromMat4(m) {\\n\\t\\t\\t\\tconst src = m.data;\\n\\t\\t\\t\\tconst dst = this.data;\\n\\t\\t\\t\\tdst[0] = src[0];\\n\\t\\t\\t\\tdst[1] = src[1];\\n\\t\\t\\t\\tdst[2] = src[2];\\n\\t\\t\\t\\tdst[3] = src[4];\\n\\t\\t\\t\\tdst[4] = src[5];\\n\\t\\t\\t\\tdst[5] = src[6];\\n\\t\\t\\t\\tdst[6] = src[8];\\n\\t\\t\\t\\tdst[7] = src[9];\\n\\t\\t\\t\\tdst[8] = src[10];\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetFromQuat(r) {\\n\\t\\t\\t\\tconst qx = r.x;\\n\\t\\t\\t\\tconst qy = r.y;\\n\\t\\t\\t\\tconst qz = r.z;\\n\\t\\t\\t\\tconst qw = r.w;\\n\\t\\t\\t\\tconst x2 = qx + qx;\\n\\t\\t\\t\\tconst y2 = qy + qy;\\n\\t\\t\\t\\tconst z2 = qz + qz;\\n\\t\\t\\t\\tconst xx = qx * x2;\\n\\t\\t\\t\\tconst xy = qx * y2;\\n\\t\\t\\t\\tconst xz = qx * z2;\\n\\t\\t\\t\\tconst yy = qy * y2;\\n\\t\\t\\t\\tconst yz = qy * z2;\\n\\t\\t\\t\\tconst zz = qz * z2;\\n\\t\\t\\t\\tconst wx = qw * x2;\\n\\t\\t\\t\\tconst wy = qw * y2;\\n\\t\\t\\t\\tconst wz = qw * z2;\\n\\t\\t\\t\\tconst m = this.data;\\n\\t\\t\\t\\tm[0] = 1 - (yy + zz);\\n\\t\\t\\t\\tm[1] = xy + wz;\\n\\t\\t\\t\\tm[2] = xz - wy;\\n\\t\\t\\t\\tm[3] = xy - wz;\\n\\t\\t\\t\\tm[4] = 1 - (xx + zz);\\n\\t\\t\\t\\tm[5] = yz + wx;\\n\\t\\t\\t\\tm[6] = xz + wy;\\n\\t\\t\\t\\tm[7] = yz - wx;\\n\\t\\t\\t\\tm[8] = 1 - (xx + yy);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tinvertMat4(src) {\\n\\t\\t\\t\\tconst s = src.data;\\n\\t\\t\\t\\tconst a0 = s[0];\\n\\t\\t\\t\\tconst a1 = s[1];\\n\\t\\t\\t\\tconst a2 = s[2];\\n\\t\\t\\t\\tconst a4 = s[4];\\n\\t\\t\\t\\tconst a5 = s[5];\\n\\t\\t\\t\\tconst a6 = s[6];\\n\\t\\t\\t\\tconst a8 = s[8];\\n\\t\\t\\t\\tconst a9 = s[9];\\n\\t\\t\\t\\tconst a10 = s[10];\\n\\t\\t\\t\\tconst b11 = a10 * a5 - a6 * a9;\\n\\t\\t\\t\\tconst b21 = -a10 * a1 + a2 * a9;\\n\\t\\t\\t\\tconst b31 = a6 * a1 - a2 * a5;\\n\\t\\t\\t\\tconst b12 = -a10 * a4 + a6 * a8;\\n\\t\\t\\t\\tconst b22 = a10 * a0 - a2 * a8;\\n\\t\\t\\t\\tconst b32 = -a6 * a0 + a2 * a4;\\n\\t\\t\\t\\tconst b13 = a9 * a4 - a5 * a8;\\n\\t\\t\\t\\tconst b23 = -a9 * a0 + a1 * a8;\\n\\t\\t\\t\\tconst b33 = a5 * a0 - a1 * a4;\\n\\t\\t\\t\\tconst det = a0 * b11 + a1 * b12 + a2 * b13;\\n\\t\\t\\t\\tif (det === 0) {\\n\\t\\t\\t\\t\\t\\tthis.setIdentity();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst invDet = 1 / det;\\n\\t\\t\\t\\t\\t\\tconst t = this.data;\\n\\t\\t\\t\\t\\t\\tt[0] = b11 * invDet;\\n\\t\\t\\t\\t\\t\\tt[1] = b21 * invDet;\\n\\t\\t\\t\\t\\t\\tt[2] = b31 * invDet;\\n\\t\\t\\t\\t\\t\\tt[3] = b12 * invDet;\\n\\t\\t\\t\\t\\t\\tt[4] = b22 * invDet;\\n\\t\\t\\t\\t\\t\\tt[5] = b32 * invDet;\\n\\t\\t\\t\\t\\t\\tt[6] = b13 * invDet;\\n\\t\\t\\t\\t\\t\\tt[7] = b23 * invDet;\\n\\t\\t\\t\\t\\t\\tt[8] = b33 * invDet;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\ttransformVector(vec, res = new Vec3()) {\\n\\t\\t\\t\\tconst m = this.data;\\n\\t\\t\\t\\tconst { x, y, z } = vec;\\n\\t\\t\\t\\tres.x = x * m[0] + y * m[3] + z * m[6];\\n\\t\\t\\t\\tres.y = x * m[1] + y * m[4] + z * m[7];\\n\\t\\t\\t\\tres.z = x * m[2] + y * m[5] + z * m[8];\\n\\t\\t\\t\\treturn res;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.data = new Float32Array(9);\\n\\t\\t\\t\\tthis.data[0] = this.data[4] = this.data[8] = 1;\\n\\t\\t}\\n}\\nMat3.IDENTITY = Object.freeze(new Mat3());\\nMat3.ZERO = Object.freeze(new Mat3().set([\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0\\n]));\\n\\nclass Vec2 {\\n\\t\\tadd(rhs) {\\n\\t\\t\\t\\tthis.x += rhs.x;\\n\\t\\t\\t\\tthis.y += rhs.y;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tadd2(lhs, rhs) {\\n\\t\\t\\t\\tthis.x = lhs.x + rhs.x;\\n\\t\\t\\t\\tthis.y = lhs.y + rhs.y;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\taddScalar(scalar) {\\n\\t\\t\\t\\tthis.x += scalar;\\n\\t\\t\\t\\tthis.y += scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\taddScaled(rhs, scalar) {\\n\\t\\t\\t\\tthis.x += rhs.x * scalar;\\n\\t\\t\\t\\tthis.y += rhs.y * scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst cstr = this.constructor;\\n\\t\\t\\t\\treturn new cstr(this.x, this.y);\\n\\t\\t}\\n\\t\\tcopy(rhs) {\\n\\t\\t\\t\\tthis.x = rhs.x;\\n\\t\\t\\t\\tthis.y = rhs.y;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tcross(rhs) {\\n\\t\\t\\t\\treturn this.x * rhs.y - this.y * rhs.x;\\n\\t\\t}\\n\\t\\tdistance(rhs) {\\n\\t\\t\\t\\tconst x = this.x - rhs.x;\\n\\t\\t\\t\\tconst y = this.y - rhs.y;\\n\\t\\t\\t\\treturn Math.sqrt(x * x + y * y);\\n\\t\\t}\\n\\t\\tdiv(rhs) {\\n\\t\\t\\t\\tthis.x /= rhs.x;\\n\\t\\t\\t\\tthis.y /= rhs.y;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tdiv2(lhs, rhs) {\\n\\t\\t\\t\\tthis.x = lhs.x / rhs.x;\\n\\t\\t\\t\\tthis.y = lhs.y / rhs.y;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tdivScalar(scalar) {\\n\\t\\t\\t\\tthis.x /= scalar;\\n\\t\\t\\t\\tthis.y /= scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tdot(rhs) {\\n\\t\\t\\t\\treturn this.x * rhs.x + this.y * rhs.y;\\n\\t\\t}\\n\\t\\tequals(rhs) {\\n\\t\\t\\t\\treturn this.x === rhs.x && this.y === rhs.y;\\n\\t\\t}\\n\\t\\tequalsApprox(rhs, epsilon = 1e-6) {\\n\\t\\t\\t\\treturn Math.abs(this.x - rhs.x) < epsilon && Math.abs(this.y - rhs.y) < epsilon;\\n\\t\\t}\\n\\t\\tlength() {\\n\\t\\t\\t\\treturn Math.sqrt(this.x * this.x + this.y * this.y);\\n\\t\\t}\\n\\t\\tlengthSq() {\\n\\t\\t\\t\\treturn this.x * this.x + this.y * this.y;\\n\\t\\t}\\n\\t\\tlerp(lhs, rhs, alpha) {\\n\\t\\t\\t\\tthis.x = lhs.x + alpha * (rhs.x - lhs.x);\\n\\t\\t\\t\\tthis.y = lhs.y + alpha * (rhs.y - lhs.y);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmul(rhs) {\\n\\t\\t\\t\\tthis.x *= rhs.x;\\n\\t\\t\\t\\tthis.y *= rhs.y;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmul2(lhs, rhs) {\\n\\t\\t\\t\\tthis.x = lhs.x * rhs.x;\\n\\t\\t\\t\\tthis.y = lhs.y * rhs.y;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmulScalar(scalar) {\\n\\t\\t\\t\\tthis.x *= scalar;\\n\\t\\t\\t\\tthis.y *= scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tnormalize(src = this) {\\n\\t\\t\\t\\tconst lengthSq = src.x * src.x + src.y * src.y;\\n\\t\\t\\t\\tif (lengthSq > 0) {\\n\\t\\t\\t\\t\\t\\tconst invLength = 1 / Math.sqrt(lengthSq);\\n\\t\\t\\t\\t\\t\\tthis.x = src.x * invLength;\\n\\t\\t\\t\\t\\t\\tthis.y = src.y * invLength;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\trotate(degrees) {\\n\\t\\t\\t\\tconst angle = Math.atan2(this.x, this.y) + degrees * math.DEG_TO_RAD;\\n\\t\\t\\t\\tconst len = Math.sqrt(this.x * this.x + this.y * this.y);\\n\\t\\t\\t\\tthis.x = Math.sin(angle) * len;\\n\\t\\t\\t\\tthis.y = Math.cos(angle) * len;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tangle() {\\n\\t\\t\\t\\treturn Math.atan2(this.x, this.y) * math.RAD_TO_DEG;\\n\\t\\t}\\n\\t\\tangleTo(rhs) {\\n\\t\\t\\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\\t}\\n\\t\\tfloor(src = this) {\\n\\t\\t\\t\\tthis.x = Math.floor(src.x);\\n\\t\\t\\t\\tthis.y = Math.floor(src.y);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tceil(src = this) {\\n\\t\\t\\t\\tthis.x = Math.ceil(src.x);\\n\\t\\t\\t\\tthis.y = Math.ceil(src.y);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tround(src = this) {\\n\\t\\t\\t\\tthis.x = Math.round(src.x);\\n\\t\\t\\t\\tthis.y = Math.round(src.y);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmin(rhs) {\\n\\t\\t\\t\\tif (rhs.x < this.x) this.x = rhs.x;\\n\\t\\t\\t\\tif (rhs.y < this.y) this.y = rhs.y;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmax(rhs) {\\n\\t\\t\\t\\tif (rhs.x > this.x) this.x = rhs.x;\\n\\t\\t\\t\\tif (rhs.y > this.y) this.y = rhs.y;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tset(x, y) {\\n\\t\\t\\t\\tthis.x = x;\\n\\t\\t\\t\\tthis.y = y;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsub(rhs) {\\n\\t\\t\\t\\tthis.x -= rhs.x;\\n\\t\\t\\t\\tthis.y -= rhs.y;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsub2(lhs, rhs) {\\n\\t\\t\\t\\tthis.x = lhs.x - rhs.x;\\n\\t\\t\\t\\tthis.y = lhs.y - rhs.y;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsubScalar(scalar) {\\n\\t\\t\\t\\tthis.x -= scalar;\\n\\t\\t\\t\\tthis.y -= scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tfromArray(arr, offset = 0) {\\n\\t\\t\\t\\tthis.x = arr[offset] ?? this.x;\\n\\t\\t\\t\\tthis.y = arr[offset + 1] ?? this.y;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\ttoString() {\\n\\t\\t\\t\\treturn `[${this.x}, ${this.y}]`;\\n\\t\\t}\\n\\t\\ttoArray(arr = [], offset = 0) {\\n\\t\\t\\t\\tarr[offset] = this.x;\\n\\t\\t\\t\\tarr[offset + 1] = this.y;\\n\\t\\t\\t\\treturn arr;\\n\\t\\t}\\n\\t\\tstatic angleRad(lhs, rhs) {\\n\\t\\t\\t\\treturn Math.atan2(lhs.x * rhs.y - lhs.y * rhs.x, lhs.x * rhs.x + lhs.y * rhs.y);\\n\\t\\t}\\n\\t\\tconstructor(x = 0, y = 0){\\n\\t\\t\\t\\tif (x.length === 2) {\\n\\t\\t\\t\\t\\t\\tthis.x = x[0];\\n\\t\\t\\t\\t\\t\\tthis.y = x[1];\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.x = x;\\n\\t\\t\\t\\t\\t\\tthis.y = y;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nVec2.ZERO = Object.freeze(new Vec2(0, 0));\\nVec2.HALF = Object.freeze(new Vec2(0.5, 0.5));\\nVec2.ONE = Object.freeze(new Vec2(1, 1));\\nVec2.UP = Object.freeze(new Vec2(0, 1));\\nVec2.DOWN = Object.freeze(new Vec2(0, -1));\\nVec2.RIGHT = Object.freeze(new Vec2(1, 0));\\nVec2.LEFT = Object.freeze(new Vec2(-1, 0));\\n\\nclass Vec4 {\\n\\t\\tadd(rhs) {\\n\\t\\t\\t\\tthis.x += rhs.x;\\n\\t\\t\\t\\tthis.y += rhs.y;\\n\\t\\t\\t\\tthis.z += rhs.z;\\n\\t\\t\\t\\tthis.w += rhs.w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tadd2(lhs, rhs) {\\n\\t\\t\\t\\tthis.x = lhs.x + rhs.x;\\n\\t\\t\\t\\tthis.y = lhs.y + rhs.y;\\n\\t\\t\\t\\tthis.z = lhs.z + rhs.z;\\n\\t\\t\\t\\tthis.w = lhs.w + rhs.w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\taddScalar(scalar) {\\n\\t\\t\\t\\tthis.x += scalar;\\n\\t\\t\\t\\tthis.y += scalar;\\n\\t\\t\\t\\tthis.z += scalar;\\n\\t\\t\\t\\tthis.w += scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\taddScaled(rhs, scalar) {\\n\\t\\t\\t\\tthis.x += rhs.x * scalar;\\n\\t\\t\\t\\tthis.y += rhs.y * scalar;\\n\\t\\t\\t\\tthis.z += rhs.z * scalar;\\n\\t\\t\\t\\tthis.w += rhs.w * scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst cstr = this.constructor;\\n\\t\\t\\t\\treturn new cstr(this.x, this.y, this.z, this.w);\\n\\t\\t}\\n\\t\\tcopy(rhs) {\\n\\t\\t\\t\\tthis.x = rhs.x;\\n\\t\\t\\t\\tthis.y = rhs.y;\\n\\t\\t\\t\\tthis.z = rhs.z;\\n\\t\\t\\t\\tthis.w = rhs.w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tdiv(rhs) {\\n\\t\\t\\t\\tthis.x /= rhs.x;\\n\\t\\t\\t\\tthis.y /= rhs.y;\\n\\t\\t\\t\\tthis.z /= rhs.z;\\n\\t\\t\\t\\tthis.w /= rhs.w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tdiv2(lhs, rhs) {\\n\\t\\t\\t\\tthis.x = lhs.x / rhs.x;\\n\\t\\t\\t\\tthis.y = lhs.y / rhs.y;\\n\\t\\t\\t\\tthis.z = lhs.z / rhs.z;\\n\\t\\t\\t\\tthis.w = lhs.w / rhs.w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tdivScalar(scalar) {\\n\\t\\t\\t\\tthis.x /= scalar;\\n\\t\\t\\t\\tthis.y /= scalar;\\n\\t\\t\\t\\tthis.z /= scalar;\\n\\t\\t\\t\\tthis.w /= scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tdot(rhs) {\\n\\t\\t\\t\\treturn this.x * rhs.x + this.y * rhs.y + this.z * rhs.z + this.w * rhs.w;\\n\\t\\t}\\n\\t\\tequals(rhs) {\\n\\t\\t\\t\\treturn this.x === rhs.x && this.y === rhs.y && this.z === rhs.z && this.w === rhs.w;\\n\\t\\t}\\n\\t\\tequalsApprox(rhs, epsilon = 1e-6) {\\n\\t\\t\\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\\t}\\n\\t\\tlength() {\\n\\t\\t\\t\\treturn Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);\\n\\t\\t}\\n\\t\\tlengthSq() {\\n\\t\\t\\t\\treturn this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;\\n\\t\\t}\\n\\t\\tlerp(lhs, rhs, alpha) {\\n\\t\\t\\t\\tthis.x = lhs.x + alpha * (rhs.x - lhs.x);\\n\\t\\t\\t\\tthis.y = lhs.y + alpha * (rhs.y - lhs.y);\\n\\t\\t\\t\\tthis.z = lhs.z + alpha * (rhs.z - lhs.z);\\n\\t\\t\\t\\tthis.w = lhs.w + alpha * (rhs.w - lhs.w);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmul(rhs) {\\n\\t\\t\\t\\tthis.x *= rhs.x;\\n\\t\\t\\t\\tthis.y *= rhs.y;\\n\\t\\t\\t\\tthis.z *= rhs.z;\\n\\t\\t\\t\\tthis.w *= rhs.w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmul2(lhs, rhs) {\\n\\t\\t\\t\\tthis.x = lhs.x * rhs.x;\\n\\t\\t\\t\\tthis.y = lhs.y * rhs.y;\\n\\t\\t\\t\\tthis.z = lhs.z * rhs.z;\\n\\t\\t\\t\\tthis.w = lhs.w * rhs.w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmulScalar(scalar) {\\n\\t\\t\\t\\tthis.x *= scalar;\\n\\t\\t\\t\\tthis.y *= scalar;\\n\\t\\t\\t\\tthis.z *= scalar;\\n\\t\\t\\t\\tthis.w *= scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tnormalize(src = this) {\\n\\t\\t\\t\\tconst lengthSq = src.x * src.x + src.y * src.y + src.z * src.z + src.w * src.w;\\n\\t\\t\\t\\tif (lengthSq > 0) {\\n\\t\\t\\t\\t\\t\\tconst invLength = 1 / Math.sqrt(lengthSq);\\n\\t\\t\\t\\t\\t\\tthis.x = src.x * invLength;\\n\\t\\t\\t\\t\\t\\tthis.y = src.y * invLength;\\n\\t\\t\\t\\t\\t\\tthis.z = src.z * invLength;\\n\\t\\t\\t\\t\\t\\tthis.w = src.w * invLength;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tfloor(src = this) {\\n\\t\\t\\t\\tthis.x = Math.floor(src.x);\\n\\t\\t\\t\\tthis.y = Math.floor(src.y);\\n\\t\\t\\t\\tthis.z = Math.floor(src.z);\\n\\t\\t\\t\\tthis.w = Math.floor(src.w);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tceil(src = this) {\\n\\t\\t\\t\\tthis.x = Math.ceil(src.x);\\n\\t\\t\\t\\tthis.y = Math.ceil(src.y);\\n\\t\\t\\t\\tthis.z = Math.ceil(src.z);\\n\\t\\t\\t\\tthis.w = Math.ceil(src.w);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tround(src = this) {\\n\\t\\t\\t\\tthis.x = Math.round(src.x);\\n\\t\\t\\t\\tthis.y = Math.round(src.y);\\n\\t\\t\\t\\tthis.z = Math.round(src.z);\\n\\t\\t\\t\\tthis.w = Math.round(src.w);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmin(rhs) {\\n\\t\\t\\t\\tif (rhs.x < this.x) this.x = rhs.x;\\n\\t\\t\\t\\tif (rhs.y < this.y) this.y = rhs.y;\\n\\t\\t\\t\\tif (rhs.z < this.z) this.z = rhs.z;\\n\\t\\t\\t\\tif (rhs.w < this.w) this.w = rhs.w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmax(rhs) {\\n\\t\\t\\t\\tif (rhs.x > this.x) this.x = rhs.x;\\n\\t\\t\\t\\tif (rhs.y > this.y) this.y = rhs.y;\\n\\t\\t\\t\\tif (rhs.z > this.z) this.z = rhs.z;\\n\\t\\t\\t\\tif (rhs.w > this.w) this.w = rhs.w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tset(x, y, z, w) {\\n\\t\\t\\t\\tthis.x = x;\\n\\t\\t\\t\\tthis.y = y;\\n\\t\\t\\t\\tthis.z = z;\\n\\t\\t\\t\\tthis.w = w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsub(rhs) {\\n\\t\\t\\t\\tthis.x -= rhs.x;\\n\\t\\t\\t\\tthis.y -= rhs.y;\\n\\t\\t\\t\\tthis.z -= rhs.z;\\n\\t\\t\\t\\tthis.w -= rhs.w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsub2(lhs, rhs) {\\n\\t\\t\\t\\tthis.x = lhs.x - rhs.x;\\n\\t\\t\\t\\tthis.y = lhs.y - rhs.y;\\n\\t\\t\\t\\tthis.z = lhs.z - rhs.z;\\n\\t\\t\\t\\tthis.w = lhs.w - rhs.w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsubScalar(scalar) {\\n\\t\\t\\t\\tthis.x -= scalar;\\n\\t\\t\\t\\tthis.y -= scalar;\\n\\t\\t\\t\\tthis.z -= scalar;\\n\\t\\t\\t\\tthis.w -= scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tfromArray(arr, offset = 0) {\\n\\t\\t\\t\\tthis.x = arr[offset] ?? this.x;\\n\\t\\t\\t\\tthis.y = arr[offset + 1] ?? this.y;\\n\\t\\t\\t\\tthis.z = arr[offset + 2] ?? this.z;\\n\\t\\t\\t\\tthis.w = arr[offset + 3] ?? this.w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\ttoString() {\\n\\t\\t\\t\\treturn `[${this.x}, ${this.y}, ${this.z}, ${this.w}]`;\\n\\t\\t}\\n\\t\\ttoArray(arr = [], offset = 0) {\\n\\t\\t\\t\\tarr[offset] = this.x;\\n\\t\\t\\t\\tarr[offset + 1] = this.y;\\n\\t\\t\\t\\tarr[offset + 2] = this.z;\\n\\t\\t\\t\\tarr[offset + 3] = this.w;\\n\\t\\t\\t\\treturn arr;\\n\\t\\t}\\n\\t\\tconstructor(x = 0, y = 0, z = 0, w = 0){\\n\\t\\t\\t\\tif (x.length === 4) {\\n\\t\\t\\t\\t\\t\\tthis.x = x[0];\\n\\t\\t\\t\\t\\t\\tthis.y = x[1];\\n\\t\\t\\t\\t\\t\\tthis.z = x[2];\\n\\t\\t\\t\\t\\t\\tthis.w = x[3];\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.x = x;\\n\\t\\t\\t\\t\\t\\tthis.y = y;\\n\\t\\t\\t\\t\\t\\tthis.z = z;\\n\\t\\t\\t\\t\\t\\tthis.w = w;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nVec4.ZERO = Object.freeze(new Vec4(0, 0, 0, 0));\\nVec4.HALF = Object.freeze(new Vec4(0.5, 0.5, 0.5, 0.5));\\nVec4.ONE = Object.freeze(new Vec4(1, 1, 1, 1));\\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\\t\\tstatic _getPerspectiveHalfSize(halfSize, fov, aspect, znear, fovIsHorizontal) {\\n\\t\\t\\t\\tif (fovIsHorizontal) {\\n\\t\\t\\t\\t\\t\\thalfSize.x = znear * Math.tan(fov * Math.PI / 360);\\n\\t\\t\\t\\t\\t\\thalfSize.y = halfSize.x / aspect;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\thalfSize.y = znear * Math.tan(fov * Math.PI / 360);\\n\\t\\t\\t\\t\\t\\thalfSize.x = halfSize.y * aspect;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tadd2(lhs, rhs) {\\n\\t\\t\\t\\tconst a = lhs.data, b = rhs.data, r = this.data;\\n\\t\\t\\t\\tr[0] = a[0] + b[0];\\n\\t\\t\\t\\tr[1] = a[1] + b[1];\\n\\t\\t\\t\\tr[2] = a[2] + b[2];\\n\\t\\t\\t\\tr[3] = a[3] + b[3];\\n\\t\\t\\t\\tr[4] = a[4] + b[4];\\n\\t\\t\\t\\tr[5] = a[5] + b[5];\\n\\t\\t\\t\\tr[6] = a[6] + b[6];\\n\\t\\t\\t\\tr[7] = a[7] + b[7];\\n\\t\\t\\t\\tr[8] = a[8] + b[8];\\n\\t\\t\\t\\tr[9] = a[9] + b[9];\\n\\t\\t\\t\\tr[10] = a[10] + b[10];\\n\\t\\t\\t\\tr[11] = a[11] + b[11];\\n\\t\\t\\t\\tr[12] = a[12] + b[12];\\n\\t\\t\\t\\tr[13] = a[13] + b[13];\\n\\t\\t\\t\\tr[14] = a[14] + b[14];\\n\\t\\t\\t\\tr[15] = a[15] + b[15];\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tadd(rhs) {\\n\\t\\t\\t\\treturn this.add2(this, rhs);\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst cstr = this.constructor;\\n\\t\\t\\t\\treturn new cstr().copy(this);\\n\\t\\t}\\n\\t\\tcopy(rhs) {\\n\\t\\t\\t\\tconst src = rhs.data, dst = this.data;\\n\\t\\t\\t\\tdst[0] = src[0];\\n\\t\\t\\t\\tdst[1] = src[1];\\n\\t\\t\\t\\tdst[2] = src[2];\\n\\t\\t\\t\\tdst[3] = src[3];\\n\\t\\t\\t\\tdst[4] = src[4];\\n\\t\\t\\t\\tdst[5] = src[5];\\n\\t\\t\\t\\tdst[6] = src[6];\\n\\t\\t\\t\\tdst[7] = src[7];\\n\\t\\t\\t\\tdst[8] = src[8];\\n\\t\\t\\t\\tdst[9] = src[9];\\n\\t\\t\\t\\tdst[10] = src[10];\\n\\t\\t\\t\\tdst[11] = src[11];\\n\\t\\t\\t\\tdst[12] = src[12];\\n\\t\\t\\t\\tdst[13] = src[13];\\n\\t\\t\\t\\tdst[14] = src[14];\\n\\t\\t\\t\\tdst[15] = src[15];\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tequals(rhs) {\\n\\t\\t\\t\\tconst l = this.data, r = rhs.data;\\n\\t\\t\\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\\t}\\n\\t\\tisIdentity() {\\n\\t\\t\\t\\tconst m = this.data;\\n\\t\\t\\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\\t}\\n\\t\\tmul2(lhs, rhs) {\\n\\t\\t\\t\\tconst a = lhs.data;\\n\\t\\t\\t\\tconst b = rhs.data;\\n\\t\\t\\t\\tconst r = this.data;\\n\\t\\t\\t\\tconst a00 = a[0];\\n\\t\\t\\t\\tconst a01 = a[1];\\n\\t\\t\\t\\tconst a02 = a[2];\\n\\t\\t\\t\\tconst a03 = a[3];\\n\\t\\t\\t\\tconst a10 = a[4];\\n\\t\\t\\t\\tconst a11 = a[5];\\n\\t\\t\\t\\tconst a12 = a[6];\\n\\t\\t\\t\\tconst a13 = a[7];\\n\\t\\t\\t\\tconst a20 = a[8];\\n\\t\\t\\t\\tconst a21 = a[9];\\n\\t\\t\\t\\tconst a22 = a[10];\\n\\t\\t\\t\\tconst a23 = a[11];\\n\\t\\t\\t\\tconst a30 = a[12];\\n\\t\\t\\t\\tconst a31 = a[13];\\n\\t\\t\\t\\tconst a32 = a[14];\\n\\t\\t\\t\\tconst a33 = a[15];\\n\\t\\t\\t\\tlet b0, b1, b2, b3;\\n\\t\\t\\t\\tb0 = b[0];\\n\\t\\t\\t\\tb1 = b[1];\\n\\t\\t\\t\\tb2 = b[2];\\n\\t\\t\\t\\tb3 = b[3];\\n\\t\\t\\t\\tr[0] = a00 * b0 + a10 * b1 + a20 * b2 + a30 * b3;\\n\\t\\t\\t\\tr[1] = a01 * b0 + a11 * b1 + a21 * b2 + a31 * b3;\\n\\t\\t\\t\\tr[2] = a02 * b0 + a12 * b1 + a22 * b2 + a32 * b3;\\n\\t\\t\\t\\tr[3] = a03 * b0 + a13 * b1 + a23 * b2 + a33 * b3;\\n\\t\\t\\t\\tb0 = b[4];\\n\\t\\t\\t\\tb1 = b[5];\\n\\t\\t\\t\\tb2 = b[6];\\n\\t\\t\\t\\tb3 = b[7];\\n\\t\\t\\t\\tr[4] = a00 * b0 + a10 * b1 + a20 * b2 + a30 * b3;\\n\\t\\t\\t\\tr[5] = a01 * b0 + a11 * b1 + a21 * b2 + a31 * b3;\\n\\t\\t\\t\\tr[6] = a02 * b0 + a12 * b1 + a22 * b2 + a32 * b3;\\n\\t\\t\\t\\tr[7] = a03 * b0 + a13 * b1 + a23 * b2 + a33 * b3;\\n\\t\\t\\t\\tb0 = b[8];\\n\\t\\t\\t\\tb1 = b[9];\\n\\t\\t\\t\\tb2 = b[10];\\n\\t\\t\\t\\tb3 = b[11];\\n\\t\\t\\t\\tr[8] = a00 * b0 + a10 * b1 + a20 * b2 + a30 * b3;\\n\\t\\t\\t\\tr[9] = a01 * b0 + a11 * b1 + a21 * b2 + a31 * b3;\\n\\t\\t\\t\\tr[10] = a02 * b0 + a12 * b1 + a22 * b2 + a32 * b3;\\n\\t\\t\\t\\tr[11] = a03 * b0 + a13 * b1 + a23 * b2 + a33 * b3;\\n\\t\\t\\t\\tb0 = b[12];\\n\\t\\t\\t\\tb1 = b[13];\\n\\t\\t\\t\\tb2 = b[14];\\n\\t\\t\\t\\tb3 = b[15];\\n\\t\\t\\t\\tr[12] = a00 * b0 + a10 * b1 + a20 * b2 + a30 * b3;\\n\\t\\t\\t\\tr[13] = a01 * b0 + a11 * b1 + a21 * b2 + a31 * b3;\\n\\t\\t\\t\\tr[14] = a02 * b0 + a12 * b1 + a22 * b2 + a32 * b3;\\n\\t\\t\\t\\tr[15] = a03 * b0 + a13 * b1 + a23 * b2 + a33 * b3;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmulAffine2(lhs, rhs) {\\n\\t\\t\\t\\tconst a = lhs.data;\\n\\t\\t\\t\\tconst b = rhs.data;\\n\\t\\t\\t\\tconst r = this.data;\\n\\t\\t\\t\\tconst a00 = a[0];\\n\\t\\t\\t\\tconst a01 = a[1];\\n\\t\\t\\t\\tconst a02 = a[2];\\n\\t\\t\\t\\tconst a10 = a[4];\\n\\t\\t\\t\\tconst a11 = a[5];\\n\\t\\t\\t\\tconst a12 = a[6];\\n\\t\\t\\t\\tconst a20 = a[8];\\n\\t\\t\\t\\tconst a21 = a[9];\\n\\t\\t\\t\\tconst a22 = a[10];\\n\\t\\t\\t\\tconst a30 = a[12];\\n\\t\\t\\t\\tconst a31 = a[13];\\n\\t\\t\\t\\tconst a32 = a[14];\\n\\t\\t\\t\\tlet b0, b1, b2;\\n\\t\\t\\t\\tb0 = b[0];\\n\\t\\t\\t\\tb1 = b[1];\\n\\t\\t\\t\\tb2 = b[2];\\n\\t\\t\\t\\tr[0] = a00 * b0 + a10 * b1 + a20 * b2;\\n\\t\\t\\t\\tr[1] = a01 * b0 + a11 * b1 + a21 * b2;\\n\\t\\t\\t\\tr[2] = a02 * b0 + a12 * b1 + a22 * b2;\\n\\t\\t\\t\\tr[3] = 0;\\n\\t\\t\\t\\tb0 = b[4];\\n\\t\\t\\t\\tb1 = b[5];\\n\\t\\t\\t\\tb2 = b[6];\\n\\t\\t\\t\\tr[4] = a00 * b0 + a10 * b1 + a20 * b2;\\n\\t\\t\\t\\tr[5] = a01 * b0 + a11 * b1 + a21 * b2;\\n\\t\\t\\t\\tr[6] = a02 * b0 + a12 * b1 + a22 * b2;\\n\\t\\t\\t\\tr[7] = 0;\\n\\t\\t\\t\\tb0 = b[8];\\n\\t\\t\\t\\tb1 = b[9];\\n\\t\\t\\t\\tb2 = b[10];\\n\\t\\t\\t\\tr[8] = a00 * b0 + a10 * b1 + a20 * b2;\\n\\t\\t\\t\\tr[9] = a01 * b0 + a11 * b1 + a21 * b2;\\n\\t\\t\\t\\tr[10] = a02 * b0 + a12 * b1 + a22 * b2;\\n\\t\\t\\t\\tr[11] = 0;\\n\\t\\t\\t\\tb0 = b[12];\\n\\t\\t\\t\\tb1 = b[13];\\n\\t\\t\\t\\tb2 = b[14];\\n\\t\\t\\t\\tr[12] = a00 * b0 + a10 * b1 + a20 * b2 + a30;\\n\\t\\t\\t\\tr[13] = a01 * b0 + a11 * b1 + a21 * b2 + a31;\\n\\t\\t\\t\\tr[14] = a02 * b0 + a12 * b1 + a22 * b2 + a32;\\n\\t\\t\\t\\tr[15] = 1;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmul(rhs) {\\n\\t\\t\\t\\treturn this.mul2(this, rhs);\\n\\t\\t}\\n\\t\\ttransformPoint(vec, res = new Vec3()) {\\n\\t\\t\\t\\tconst m = this.data;\\n\\t\\t\\t\\tconst { x, y, z } = vec;\\n\\t\\t\\t\\tres.x = x * m[0] + y * m[4] + z * m[8] + m[12];\\n\\t\\t\\t\\tres.y = x * m[1] + y * m[5] + z * m[9] + m[13];\\n\\t\\t\\t\\tres.z = x * m[2] + y * m[6] + z * m[10] + m[14];\\n\\t\\t\\t\\treturn res;\\n\\t\\t}\\n\\t\\ttransformVector(vec, res = new Vec3()) {\\n\\t\\t\\t\\tconst m = this.data;\\n\\t\\t\\t\\tconst { x, y, z } = vec;\\n\\t\\t\\t\\tres.x = x * m[0] + y * m[4] + z * m[8];\\n\\t\\t\\t\\tres.y = x * m[1] + y * m[5] + z * m[9];\\n\\t\\t\\t\\tres.z = x * m[2] + y * m[6] + z * m[10];\\n\\t\\t\\t\\treturn res;\\n\\t\\t}\\n\\t\\ttransformVec4(vec, res = new Vec4()) {\\n\\t\\t\\t\\tconst m = this.data;\\n\\t\\t\\t\\tconst { x, y, z, w } = vec;\\n\\t\\t\\t\\tres.x = x * m[0] + y * m[4] + z * m[8] + w * m[12];\\n\\t\\t\\t\\tres.y = x * m[1] + y * m[5] + z * m[9] + w * m[13];\\n\\t\\t\\t\\tres.z = x * m[2] + y * m[6] + z * m[10] + w * m[14];\\n\\t\\t\\t\\tres.w = x * m[3] + y * m[7] + z * m[11] + w * m[15];\\n\\t\\t\\t\\treturn res;\\n\\t\\t}\\n\\t\\tsetLookAt(position, target, up) {\\n\\t\\t\\t\\tz.sub2(position, target).normalize();\\n\\t\\t\\t\\ty.copy(up).normalize();\\n\\t\\t\\t\\tx.cross(y, z).normalize();\\n\\t\\t\\t\\ty.cross(z, x);\\n\\t\\t\\t\\tconst r = this.data;\\n\\t\\t\\t\\tr[0] = x.x;\\n\\t\\t\\t\\tr[1] = x.y;\\n\\t\\t\\t\\tr[2] = x.z;\\n\\t\\t\\t\\tr[3] = 0;\\n\\t\\t\\t\\tr[4] = y.x;\\n\\t\\t\\t\\tr[5] = y.y;\\n\\t\\t\\t\\tr[6] = y.z;\\n\\t\\t\\t\\tr[7] = 0;\\n\\t\\t\\t\\tr[8] = z.x;\\n\\t\\t\\t\\tr[9] = z.y;\\n\\t\\t\\t\\tr[10] = z.z;\\n\\t\\t\\t\\tr[11] = 0;\\n\\t\\t\\t\\tr[12] = position.x;\\n\\t\\t\\t\\tr[13] = position.y;\\n\\t\\t\\t\\tr[14] = position.z;\\n\\t\\t\\t\\tr[15] = 1;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetFrustum(left, right, bottom, top, znear, zfar) {\\n\\t\\t\\t\\tconst temp1 = 2 * znear;\\n\\t\\t\\t\\tconst temp2 = right - left;\\n\\t\\t\\t\\tconst temp3 = top - bottom;\\n\\t\\t\\t\\tconst temp4 = zfar - znear;\\n\\t\\t\\t\\tconst r = this.data;\\n\\t\\t\\t\\tr[0] = temp1 / temp2;\\n\\t\\t\\t\\tr[1] = 0;\\n\\t\\t\\t\\tr[2] = 0;\\n\\t\\t\\t\\tr[3] = 0;\\n\\t\\t\\t\\tr[4] = 0;\\n\\t\\t\\t\\tr[5] = temp1 / temp3;\\n\\t\\t\\t\\tr[6] = 0;\\n\\t\\t\\t\\tr[7] = 0;\\n\\t\\t\\t\\tr[8] = (right + left) / temp2;\\n\\t\\t\\t\\tr[9] = (top + bottom) / temp3;\\n\\t\\t\\t\\tr[10] = (-zfar - znear) / temp4;\\n\\t\\t\\t\\tr[11] = -1;\\n\\t\\t\\t\\tr[12] = 0;\\n\\t\\t\\t\\tr[13] = 0;\\n\\t\\t\\t\\tr[14] = -temp1 * zfar / temp4;\\n\\t\\t\\t\\tr[15] = 0;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetPerspective(fov, aspect, znear, zfar, fovIsHorizontal) {\\n\\t\\t\\t\\tMat4._getPerspectiveHalfSize(_halfSize$1, fov, aspect, znear, fovIsHorizontal);\\n\\t\\t\\t\\treturn this.setFrustum(-_halfSize$1.x, _halfSize$1.x, -_halfSize$1.y, _halfSize$1.y, znear, zfar);\\n\\t\\t}\\n\\t\\tsetOrtho(left, right, bottom, top, near, far) {\\n\\t\\t\\t\\tconst r = this.data;\\n\\t\\t\\t\\tr[0] = 2 / (right - left);\\n\\t\\t\\t\\tr[1] = 0;\\n\\t\\t\\t\\tr[2] = 0;\\n\\t\\t\\t\\tr[3] = 0;\\n\\t\\t\\t\\tr[4] = 0;\\n\\t\\t\\t\\tr[5] = 2 / (top - bottom);\\n\\t\\t\\t\\tr[6] = 0;\\n\\t\\t\\t\\tr[7] = 0;\\n\\t\\t\\t\\tr[8] = 0;\\n\\t\\t\\t\\tr[9] = 0;\\n\\t\\t\\t\\tr[10] = -2 / (far - near);\\n\\t\\t\\t\\tr[11] = 0;\\n\\t\\t\\t\\tr[12] = -(right + left) / (right - left);\\n\\t\\t\\t\\tr[13] = -(top + bottom) / (top - bottom);\\n\\t\\t\\t\\tr[14] = -(far + near) / (far - near);\\n\\t\\t\\t\\tr[15] = 1;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetFromAxisAngle(axis, angle) {\\n\\t\\t\\t\\tangle *= math.DEG_TO_RAD;\\n\\t\\t\\t\\tconst { x, y, z } = axis;\\n\\t\\t\\t\\tconst c = Math.cos(angle);\\n\\t\\t\\t\\tconst s = Math.sin(angle);\\n\\t\\t\\t\\tconst t = 1 - c;\\n\\t\\t\\t\\tconst tx = t * x;\\n\\t\\t\\t\\tconst ty = t * y;\\n\\t\\t\\t\\tconst m = this.data;\\n\\t\\t\\t\\tm[0] = tx * x + c;\\n\\t\\t\\t\\tm[1] = tx * y + s * z;\\n\\t\\t\\t\\tm[2] = tx * z - s * y;\\n\\t\\t\\t\\tm[3] = 0;\\n\\t\\t\\t\\tm[4] = tx * y - s * z;\\n\\t\\t\\t\\tm[5] = ty * y + c;\\n\\t\\t\\t\\tm[6] = ty * z + s * x;\\n\\t\\t\\t\\tm[7] = 0;\\n\\t\\t\\t\\tm[8] = tx * z + s * y;\\n\\t\\t\\t\\tm[9] = ty * z - x * s;\\n\\t\\t\\t\\tm[10] = t * z * z + c;\\n\\t\\t\\t\\tm[11] = 0;\\n\\t\\t\\t\\tm[12] = 0;\\n\\t\\t\\t\\tm[13] = 0;\\n\\t\\t\\t\\tm[14] = 0;\\n\\t\\t\\t\\tm[15] = 1;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetTranslate(x, y, z) {\\n\\t\\t\\t\\tconst m = this.data;\\n\\t\\t\\t\\tm[0] = 1;\\n\\t\\t\\t\\tm[1] = 0;\\n\\t\\t\\t\\tm[2] = 0;\\n\\t\\t\\t\\tm[3] = 0;\\n\\t\\t\\t\\tm[4] = 0;\\n\\t\\t\\t\\tm[5] = 1;\\n\\t\\t\\t\\tm[6] = 0;\\n\\t\\t\\t\\tm[7] = 0;\\n\\t\\t\\t\\tm[8] = 0;\\n\\t\\t\\t\\tm[9] = 0;\\n\\t\\t\\t\\tm[10] = 1;\\n\\t\\t\\t\\tm[11] = 0;\\n\\t\\t\\t\\tm[12] = x;\\n\\t\\t\\t\\tm[13] = y;\\n\\t\\t\\t\\tm[14] = z;\\n\\t\\t\\t\\tm[15] = 1;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetScale(x, y, z) {\\n\\t\\t\\t\\tconst m = this.data;\\n\\t\\t\\t\\tm[0] = x;\\n\\t\\t\\t\\tm[1] = 0;\\n\\t\\t\\t\\tm[2] = 0;\\n\\t\\t\\t\\tm[3] = 0;\\n\\t\\t\\t\\tm[4] = 0;\\n\\t\\t\\t\\tm[5] = y;\\n\\t\\t\\t\\tm[6] = 0;\\n\\t\\t\\t\\tm[7] = 0;\\n\\t\\t\\t\\tm[8] = 0;\\n\\t\\t\\t\\tm[9] = 0;\\n\\t\\t\\t\\tm[10] = z;\\n\\t\\t\\t\\tm[11] = 0;\\n\\t\\t\\t\\tm[12] = 0;\\n\\t\\t\\t\\tm[13] = 0;\\n\\t\\t\\t\\tm[14] = 0;\\n\\t\\t\\t\\tm[15] = 1;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetViewport(x, y, width, height) {\\n\\t\\t\\t\\tconst m = this.data;\\n\\t\\t\\t\\tm[0] = width * 0.5;\\n\\t\\t\\t\\tm[1] = 0;\\n\\t\\t\\t\\tm[2] = 0;\\n\\t\\t\\t\\tm[3] = 0;\\n\\t\\t\\t\\tm[4] = 0;\\n\\t\\t\\t\\tm[5] = height * 0.5;\\n\\t\\t\\t\\tm[6] = 0;\\n\\t\\t\\t\\tm[7] = 0;\\n\\t\\t\\t\\tm[8] = 0;\\n\\t\\t\\t\\tm[9] = 0;\\n\\t\\t\\t\\tm[10] = 0.5;\\n\\t\\t\\t\\tm[11] = 0;\\n\\t\\t\\t\\tm[12] = x + width * 0.5;\\n\\t\\t\\t\\tm[13] = y + height * 0.5;\\n\\t\\t\\t\\tm[14] = 0.5;\\n\\t\\t\\t\\tm[15] = 1;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetReflection(normal, distance) {\\n\\t\\t\\t\\tconst a = normal.x;\\n\\t\\t\\t\\tconst b = normal.y;\\n\\t\\t\\t\\tconst c = normal.z;\\n\\t\\t\\t\\tconst data = this.data;\\n\\t\\t\\t\\tdata[0] = 1.0 - 2 * a * a;\\n\\t\\t\\t\\tdata[1] = -2 * a * b;\\n\\t\\t\\t\\tdata[2] = -2 * a * c;\\n\\t\\t\\t\\tdata[3] = 0;\\n\\t\\t\\t\\tdata[4] = -2 * a * b;\\n\\t\\t\\t\\tdata[5] = 1.0 - 2 * b * b;\\n\\t\\t\\t\\tdata[6] = -2 * b * c;\\n\\t\\t\\t\\tdata[7] = 0;\\n\\t\\t\\t\\tdata[8] = -2 * a * c;\\n\\t\\t\\t\\tdata[9] = -2 * b * c;\\n\\t\\t\\t\\tdata[10] = 1.0 - 2 * c * c;\\n\\t\\t\\t\\tdata[11] = 0;\\n\\t\\t\\t\\tdata[12] = -2 * a * distance;\\n\\t\\t\\t\\tdata[13] = -2 * b * distance;\\n\\t\\t\\t\\tdata[14] = -2 * c * distance;\\n\\t\\t\\t\\tdata[15] = 1;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tinvert(src = this) {\\n\\t\\t\\t\\tconst s = src.data;\\n\\t\\t\\t\\tconst a00 = s[0];\\n\\t\\t\\t\\tconst a01 = s[1];\\n\\t\\t\\t\\tconst a02 = s[2];\\n\\t\\t\\t\\tconst a03 = s[3];\\n\\t\\t\\t\\tconst a10 = s[4];\\n\\t\\t\\t\\tconst a11 = s[5];\\n\\t\\t\\t\\tconst a12 = s[6];\\n\\t\\t\\t\\tconst a13 = s[7];\\n\\t\\t\\t\\tconst a20 = s[8];\\n\\t\\t\\t\\tconst a21 = s[9];\\n\\t\\t\\t\\tconst a22 = s[10];\\n\\t\\t\\t\\tconst a23 = s[11];\\n\\t\\t\\t\\tconst a30 = s[12];\\n\\t\\t\\t\\tconst a31 = s[13];\\n\\t\\t\\t\\tconst a32 = s[14];\\n\\t\\t\\t\\tconst a33 = s[15];\\n\\t\\t\\t\\tconst b00 = a00 * a11 - a01 * a10;\\n\\t\\t\\t\\tconst b01 = a00 * a12 - a02 * a10;\\n\\t\\t\\t\\tconst b02 = a00 * a13 - a03 * a10;\\n\\t\\t\\t\\tconst b03 = a01 * a12 - a02 * a11;\\n\\t\\t\\t\\tconst b04 = a01 * a13 - a03 * a11;\\n\\t\\t\\t\\tconst b05 = a02 * a13 - a03 * a12;\\n\\t\\t\\t\\tconst b06 = a20 * a31 - a21 * a30;\\n\\t\\t\\t\\tconst b07 = a20 * a32 - a22 * a30;\\n\\t\\t\\t\\tconst b08 = a20 * a33 - a23 * a30;\\n\\t\\t\\t\\tconst b09 = a21 * a32 - a22 * a31;\\n\\t\\t\\t\\tconst b10 = a21 * a33 - a23 * a31;\\n\\t\\t\\t\\tconst b11 = a22 * a33 - a23 * a32;\\n\\t\\t\\t\\tconst det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\\n\\t\\t\\t\\tif (det === 0) {\\n\\t\\t\\t\\t\\t\\tthis.setIdentity();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst invDet = 1 / det;\\n\\t\\t\\t\\t\\t\\tconst t = this.data;\\n\\t\\t\\t\\t\\t\\tt[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet;\\n\\t\\t\\t\\t\\t\\tt[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet;\\n\\t\\t\\t\\t\\t\\tt[2] = (a31 * b05 - a32 * b04 + a33 * b03) * invDet;\\n\\t\\t\\t\\t\\t\\tt[3] = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet;\\n\\t\\t\\t\\t\\t\\tt[4] = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet;\\n\\t\\t\\t\\t\\t\\tt[5] = (a00 * b11 - a02 * b08 + a03 * b07) * invDet;\\n\\t\\t\\t\\t\\t\\tt[6] = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet;\\n\\t\\t\\t\\t\\t\\tt[7] = (a20 * b05 - a22 * b02 + a23 * b01) * invDet;\\n\\t\\t\\t\\t\\t\\tt[8] = (a10 * b10 - a11 * b08 + a13 * b06) * invDet;\\n\\t\\t\\t\\t\\t\\tt[9] = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet;\\n\\t\\t\\t\\t\\t\\tt[10] = (a30 * b04 - a31 * b02 + a33 * b00) * invDet;\\n\\t\\t\\t\\t\\t\\tt[11] = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet;\\n\\t\\t\\t\\t\\t\\tt[12] = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet;\\n\\t\\t\\t\\t\\t\\tt[13] = (a00 * b09 - a01 * b07 + a02 * b06) * invDet;\\n\\t\\t\\t\\t\\t\\tt[14] = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet;\\n\\t\\t\\t\\t\\t\\tt[15] = (a20 * b03 - a21 * b01 + a22 * b00) * invDet;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tset(src) {\\n\\t\\t\\t\\tconst dst = this.data;\\n\\t\\t\\t\\tdst[0] = src[0];\\n\\t\\t\\t\\tdst[1] = src[1];\\n\\t\\t\\t\\tdst[2] = src[2];\\n\\t\\t\\t\\tdst[3] = src[3];\\n\\t\\t\\t\\tdst[4] = src[4];\\n\\t\\t\\t\\tdst[5] = src[5];\\n\\t\\t\\t\\tdst[6] = src[6];\\n\\t\\t\\t\\tdst[7] = src[7];\\n\\t\\t\\t\\tdst[8] = src[8];\\n\\t\\t\\t\\tdst[9] = src[9];\\n\\t\\t\\t\\tdst[10] = src[10];\\n\\t\\t\\t\\tdst[11] = src[11];\\n\\t\\t\\t\\tdst[12] = src[12];\\n\\t\\t\\t\\tdst[13] = src[13];\\n\\t\\t\\t\\tdst[14] = src[14];\\n\\t\\t\\t\\tdst[15] = src[15];\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetIdentity() {\\n\\t\\t\\t\\tconst m = this.data;\\n\\t\\t\\t\\tm[0] = 1;\\n\\t\\t\\t\\tm[1] = 0;\\n\\t\\t\\t\\tm[2] = 0;\\n\\t\\t\\t\\tm[3] = 0;\\n\\t\\t\\t\\tm[4] = 0;\\n\\t\\t\\t\\tm[5] = 1;\\n\\t\\t\\t\\tm[6] = 0;\\n\\t\\t\\t\\tm[7] = 0;\\n\\t\\t\\t\\tm[8] = 0;\\n\\t\\t\\t\\tm[9] = 0;\\n\\t\\t\\t\\tm[10] = 1;\\n\\t\\t\\t\\tm[11] = 0;\\n\\t\\t\\t\\tm[12] = 0;\\n\\t\\t\\t\\tm[13] = 0;\\n\\t\\t\\t\\tm[14] = 0;\\n\\t\\t\\t\\tm[15] = 1;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetTRS(t, r, s) {\\n\\t\\t\\t\\tconst qx = r.x;\\n\\t\\t\\t\\tconst qy = r.y;\\n\\t\\t\\t\\tconst qz = r.z;\\n\\t\\t\\t\\tconst qw = r.w;\\n\\t\\t\\t\\tconst sx = s.x;\\n\\t\\t\\t\\tconst sy = s.y;\\n\\t\\t\\t\\tconst sz = s.z;\\n\\t\\t\\t\\tconst x2 = qx + qx;\\n\\t\\t\\t\\tconst y2 = qy + qy;\\n\\t\\t\\t\\tconst z2 = qz + qz;\\n\\t\\t\\t\\tconst xx = qx * x2;\\n\\t\\t\\t\\tconst xy = qx * y2;\\n\\t\\t\\t\\tconst xz = qx * z2;\\n\\t\\t\\t\\tconst yy = qy * y2;\\n\\t\\t\\t\\tconst yz = qy * z2;\\n\\t\\t\\t\\tconst zz = qz * z2;\\n\\t\\t\\t\\tconst wx = qw * x2;\\n\\t\\t\\t\\tconst wy = qw * y2;\\n\\t\\t\\t\\tconst wz = qw * z2;\\n\\t\\t\\t\\tconst m = this.data;\\n\\t\\t\\t\\tm[0] = (1 - (yy + zz)) * sx;\\n\\t\\t\\t\\tm[1] = (xy + wz) * sx;\\n\\t\\t\\t\\tm[2] = (xz - wy) * sx;\\n\\t\\t\\t\\tm[3] = 0;\\n\\t\\t\\t\\tm[4] = (xy - wz) * sy;\\n\\t\\t\\t\\tm[5] = (1 - (xx + zz)) * sy;\\n\\t\\t\\t\\tm[6] = (yz + wx) * sy;\\n\\t\\t\\t\\tm[7] = 0;\\n\\t\\t\\t\\tm[8] = (xz + wy) * sz;\\n\\t\\t\\t\\tm[9] = (yz - wx) * sz;\\n\\t\\t\\t\\tm[10] = (1 - (xx + yy)) * sz;\\n\\t\\t\\t\\tm[11] = 0;\\n\\t\\t\\t\\tm[12] = t.x;\\n\\t\\t\\t\\tm[13] = t.y;\\n\\t\\t\\t\\tm[14] = t.z;\\n\\t\\t\\t\\tm[15] = 1;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\ttranspose(src = this) {\\n\\t\\t\\t\\tconst s = src.data;\\n\\t\\t\\t\\tconst t = this.data;\\n\\t\\t\\t\\tif (s === t) {\\n\\t\\t\\t\\t\\t\\tlet tmp;\\n\\t\\t\\t\\t\\t\\ttmp = s[1];\\n\\t\\t\\t\\t\\t\\tt[1] = s[4];\\n\\t\\t\\t\\t\\t\\tt[4] = tmp;\\n\\t\\t\\t\\t\\t\\ttmp = s[2];\\n\\t\\t\\t\\t\\t\\tt[2] = s[8];\\n\\t\\t\\t\\t\\t\\tt[8] = tmp;\\n\\t\\t\\t\\t\\t\\ttmp = s[3];\\n\\t\\t\\t\\t\\t\\tt[3] = s[12];\\n\\t\\t\\t\\t\\t\\tt[12] = tmp;\\n\\t\\t\\t\\t\\t\\ttmp = s[6];\\n\\t\\t\\t\\t\\t\\tt[6] = s[9];\\n\\t\\t\\t\\t\\t\\tt[9] = tmp;\\n\\t\\t\\t\\t\\t\\ttmp = s[7];\\n\\t\\t\\t\\t\\t\\tt[7] = s[13];\\n\\t\\t\\t\\t\\t\\tt[13] = tmp;\\n\\t\\t\\t\\t\\t\\ttmp = s[11];\\n\\t\\t\\t\\t\\t\\tt[11] = s[14];\\n\\t\\t\\t\\t\\t\\tt[14] = tmp;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tt[0] = s[0];\\n\\t\\t\\t\\t\\t\\tt[1] = s[4];\\n\\t\\t\\t\\t\\t\\tt[2] = s[8];\\n\\t\\t\\t\\t\\t\\tt[3] = s[12];\\n\\t\\t\\t\\t\\t\\tt[4] = s[1];\\n\\t\\t\\t\\t\\t\\tt[5] = s[5];\\n\\t\\t\\t\\t\\t\\tt[6] = s[9];\\n\\t\\t\\t\\t\\t\\tt[7] = s[13];\\n\\t\\t\\t\\t\\t\\tt[8] = s[2];\\n\\t\\t\\t\\t\\t\\tt[9] = s[6];\\n\\t\\t\\t\\t\\t\\tt[10] = s[10];\\n\\t\\t\\t\\t\\t\\tt[11] = s[14];\\n\\t\\t\\t\\t\\t\\tt[12] = s[3];\\n\\t\\t\\t\\t\\t\\tt[13] = s[7];\\n\\t\\t\\t\\t\\t\\tt[14] = s[11];\\n\\t\\t\\t\\t\\t\\tt[15] = s[15];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tgetTranslation(t = new Vec3()) {\\n\\t\\t\\t\\treturn t.set(this.data[12], this.data[13], this.data[14]);\\n\\t\\t}\\n\\t\\tgetX(x = new Vec3()) {\\n\\t\\t\\t\\treturn x.set(this.data[0], this.data[1], this.data[2]);\\n\\t\\t}\\n\\t\\tgetY(y = new Vec3()) {\\n\\t\\t\\t\\treturn y.set(this.data[4], this.data[5], this.data[6]);\\n\\t\\t}\\n\\t\\tgetZ(z = new Vec3()) {\\n\\t\\t\\t\\treturn z.set(this.data[8], this.data[9], this.data[10]);\\n\\t\\t}\\n\\t\\tgetScale(scale = new Vec3()) {\\n\\t\\t\\t\\tthis.getX(x);\\n\\t\\t\\t\\tthis.getY(y);\\n\\t\\t\\t\\tthis.getZ(z);\\n\\t\\t\\t\\tscale.set(x.length(), y.length(), z.length());\\n\\t\\t\\t\\treturn scale;\\n\\t\\t}\\n\\t\\tget scaleSign() {\\n\\t\\t\\t\\tthis.getX(x);\\n\\t\\t\\t\\tthis.getY(y);\\n\\t\\t\\t\\tthis.getZ(z);\\n\\t\\t\\t\\tx.cross(x, y);\\n\\t\\t\\t\\treturn x.dot(z) < 0 ? -1 : 1;\\n\\t\\t}\\n\\t\\tsetFromEulerAngles(ex, ey, ez) {\\n\\t\\t\\t\\tex *= math.DEG_TO_RAD;\\n\\t\\t\\t\\tey *= math.DEG_TO_RAD;\\n\\t\\t\\t\\tez *= math.DEG_TO_RAD;\\n\\t\\t\\t\\tconst s1 = Math.sin(-ex);\\n\\t\\t\\t\\tconst c1 = Math.cos(-ex);\\n\\t\\t\\t\\tconst s2 = Math.sin(-ey);\\n\\t\\t\\t\\tconst c2 = Math.cos(-ey);\\n\\t\\t\\t\\tconst s3 = Math.sin(-ez);\\n\\t\\t\\t\\tconst c3 = Math.cos(-ez);\\n\\t\\t\\t\\tconst m = this.data;\\n\\t\\t\\t\\tm[0] = c2 * c3;\\n\\t\\t\\t\\tm[1] = -c2 * s3;\\n\\t\\t\\t\\tm[2] = s2;\\n\\t\\t\\t\\tm[3] = 0;\\n\\t\\t\\t\\tm[4] = c1 * s3 + c3 * s1 * s2;\\n\\t\\t\\t\\tm[5] = c1 * c3 - s1 * s2 * s3;\\n\\t\\t\\t\\tm[6] = -c2 * s1;\\n\\t\\t\\t\\tm[7] = 0;\\n\\t\\t\\t\\tm[8] = s1 * s3 - c1 * c3 * s2;\\n\\t\\t\\t\\tm[9] = c3 * s1 + c1 * s2 * s3;\\n\\t\\t\\t\\tm[10] = c1 * c2;\\n\\t\\t\\t\\tm[11] = 0;\\n\\t\\t\\t\\tm[12] = 0;\\n\\t\\t\\t\\tm[13] = 0;\\n\\t\\t\\t\\tm[14] = 0;\\n\\t\\t\\t\\tm[15] = 1;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tgetEulerAngles(eulers = new Vec3()) {\\n\\t\\t\\t\\tthis.getScale(scale);\\n\\t\\t\\t\\tconst sx = scale.x;\\n\\t\\t\\t\\tconst sy = scale.y;\\n\\t\\t\\t\\tconst sz = scale.z;\\n\\t\\t\\t\\tif (sx === 0 || sy === 0 || sz === 0) {\\n\\t\\t\\t\\t\\t\\treturn eulers.set(0, 0, 0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst m = this.data;\\n\\t\\t\\t\\tconst y = Math.asin(-m[2] / sx);\\n\\t\\t\\t\\tconst halfPi = Math.PI * 0.5;\\n\\t\\t\\t\\tlet x, z;\\n\\t\\t\\t\\tif (y < halfPi) {\\n\\t\\t\\t\\t\\t\\tif (y > -halfPi) {\\n\\t\\t\\t\\t\\t\\t\\t\\tx = Math.atan2(m[6] / sy, m[10] / sz);\\n\\t\\t\\t\\t\\t\\t\\t\\tz = Math.atan2(m[1] / sx, m[0] / sx);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tz = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tx = -Math.atan2(m[4] / sy, m[5] / sy);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tz = 0;\\n\\t\\t\\t\\t\\t\\tx = Math.atan2(m[4] / sy, m[5] / sy);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn eulers.set(x, y, z).mulScalar(math.RAD_TO_DEG);\\n\\t\\t}\\n\\t\\ttoString() {\\n\\t\\t\\t\\treturn `[${this.data.join(', ')}]`;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.data = new Float32Array(16);\\n\\t\\t\\t\\tthis.data[0] = this.data[5] = this.data[10] = this.data[15] = 1;\\n\\t\\t}\\n}\\nMat4.IDENTITY = Object.freeze(new Mat4());\\nMat4.ZERO = Object.freeze(new Mat4().set([\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0,\\n\\t\\t0\\n]));\\n\\nclass Quat {\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst cstr = this.constructor;\\n\\t\\t\\t\\treturn new cstr(this.x, this.y, this.z, this.w);\\n\\t\\t}\\n\\t\\tconjugate(src = this) {\\n\\t\\t\\t\\tthis.x = src.x * -1;\\n\\t\\t\\t\\tthis.y = src.y * -1;\\n\\t\\t\\t\\tthis.z = src.z * -1;\\n\\t\\t\\t\\tthis.w = src.w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tcopy(rhs) {\\n\\t\\t\\t\\tthis.x = rhs.x;\\n\\t\\t\\t\\tthis.y = rhs.y;\\n\\t\\t\\t\\tthis.z = rhs.z;\\n\\t\\t\\t\\tthis.w = rhs.w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tdot(other) {\\n\\t\\t\\t\\treturn this.x * other.x + this.y * other.y + this.z * other.z + this.w * other.w;\\n\\t\\t}\\n\\t\\tequals(rhs) {\\n\\t\\t\\t\\treturn this.x === rhs.x && this.y === rhs.y && this.z === rhs.z && this.w === rhs.w;\\n\\t\\t}\\n\\t\\tequalsApprox(rhs, epsilon = 1e-6) {\\n\\t\\t\\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\\t}\\n\\t\\tgetAxisAngle(axis) {\\n\\t\\t\\t\\tlet rad = Math.acos(this.w) * 2;\\n\\t\\t\\t\\tconst s = Math.sin(rad / 2);\\n\\t\\t\\t\\tif (s !== 0) {\\n\\t\\t\\t\\t\\t\\taxis.x = this.x / s;\\n\\t\\t\\t\\t\\t\\taxis.y = this.y / s;\\n\\t\\t\\t\\t\\t\\taxis.z = this.z / s;\\n\\t\\t\\t\\t\\t\\tif (axis.x < 0 || axis.y < 0 || axis.z < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\taxis.x *= -1;\\n\\t\\t\\t\\t\\t\\t\\t\\taxis.y *= -1;\\n\\t\\t\\t\\t\\t\\t\\t\\taxis.z *= -1;\\n\\t\\t\\t\\t\\t\\t\\t\\trad *= -1;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\taxis.x = 1;\\n\\t\\t\\t\\t\\t\\taxis.y = 0;\\n\\t\\t\\t\\t\\t\\taxis.z = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn rad * math.RAD_TO_DEG;\\n\\t\\t}\\n\\t\\tgetEulerAngles(eulers = new Vec3()) {\\n\\t\\t\\t\\tlet x, y, z;\\n\\t\\t\\t\\tconst qx = this.x;\\n\\t\\t\\t\\tconst qy = this.y;\\n\\t\\t\\t\\tconst qz = this.z;\\n\\t\\t\\t\\tconst qw = this.w;\\n\\t\\t\\t\\tconst a2 = 2 * (qw * qy - qx * qz);\\n\\t\\t\\t\\tif (a2 <= -0.99999) {\\n\\t\\t\\t\\t\\t\\tx = 2 * Math.atan2(qx, qw);\\n\\t\\t\\t\\t\\t\\ty = -Math.PI / 2;\\n\\t\\t\\t\\t\\t\\tz = 0;\\n\\t\\t\\t\\t} else if (a2 >= 0.99999) {\\n\\t\\t\\t\\t\\t\\tx = 2 * Math.atan2(qx, qw);\\n\\t\\t\\t\\t\\t\\ty = Math.PI / 2;\\n\\t\\t\\t\\t\\t\\tz = 0;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tx = Math.atan2(2 * (qw * qx + qy * qz), 1 - 2 * (qx * qx + qy * qy));\\n\\t\\t\\t\\t\\t\\ty = Math.asin(a2);\\n\\t\\t\\t\\t\\t\\tz = Math.atan2(2 * (qw * qz + qx * qy), 1 - 2 * (qy * qy + qz * qz));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn eulers.set(x, y, z).mulScalar(math.RAD_TO_DEG);\\n\\t\\t}\\n\\t\\tinvert(src = this) {\\n\\t\\t\\t\\treturn this.conjugate(src).normalize();\\n\\t\\t}\\n\\t\\tlength() {\\n\\t\\t\\t\\treturn Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);\\n\\t\\t}\\n\\t\\tlengthSq() {\\n\\t\\t\\t\\treturn this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;\\n\\t\\t}\\n\\t\\tlerp(lhs, rhs, alpha) {\\n\\t\\t\\t\\tconst omt = (1 - alpha) * (lhs.dot(rhs) < 0 ? -1 : 1);\\n\\t\\t\\t\\tthis.x = lhs.x * omt + rhs.x * alpha;\\n\\t\\t\\t\\tthis.y = lhs.y * omt + rhs.y * alpha;\\n\\t\\t\\t\\tthis.z = lhs.z * omt + rhs.z * alpha;\\n\\t\\t\\t\\tthis.w = lhs.w * omt + rhs.w * alpha;\\n\\t\\t\\t\\treturn this.normalize();\\n\\t\\t}\\n\\t\\tmul(rhs) {\\n\\t\\t\\t\\tconst q1x = this.x;\\n\\t\\t\\t\\tconst q1y = this.y;\\n\\t\\t\\t\\tconst q1z = this.z;\\n\\t\\t\\t\\tconst q1w = this.w;\\n\\t\\t\\t\\tconst q2x = rhs.x;\\n\\t\\t\\t\\tconst q2y = rhs.y;\\n\\t\\t\\t\\tconst q2z = rhs.z;\\n\\t\\t\\t\\tconst q2w = rhs.w;\\n\\t\\t\\t\\tthis.x = q1w * q2x + q1x * q2w + q1y * q2z - q1z * q2y;\\n\\t\\t\\t\\tthis.y = q1w * q2y + q1y * q2w + q1z * q2x - q1x * q2z;\\n\\t\\t\\t\\tthis.z = q1w * q2z + q1z * q2w + q1x * q2y - q1y * q2x;\\n\\t\\t\\t\\tthis.w = q1w * q2w - q1x * q2x - q1y * q2y - q1z * q2z;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmulScalar(scalar, src = this) {\\n\\t\\t\\t\\tthis.x = src.x * scalar;\\n\\t\\t\\t\\tthis.y = src.y * scalar;\\n\\t\\t\\t\\tthis.z = src.z * scalar;\\n\\t\\t\\t\\tthis.w = src.w * scalar;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmul2(lhs, rhs) {\\n\\t\\t\\t\\tconst q1x = lhs.x;\\n\\t\\t\\t\\tconst q1y = lhs.y;\\n\\t\\t\\t\\tconst q1z = lhs.z;\\n\\t\\t\\t\\tconst q1w = lhs.w;\\n\\t\\t\\t\\tconst q2x = rhs.x;\\n\\t\\t\\t\\tconst q2y = rhs.y;\\n\\t\\t\\t\\tconst q2z = rhs.z;\\n\\t\\t\\t\\tconst q2w = rhs.w;\\n\\t\\t\\t\\tthis.x = q1w * q2x + q1x * q2w + q1y * q2z - q1z * q2y;\\n\\t\\t\\t\\tthis.y = q1w * q2y + q1y * q2w + q1z * q2x - q1x * q2z;\\n\\t\\t\\t\\tthis.z = q1w * q2z + q1z * q2w + q1x * q2y - q1y * q2x;\\n\\t\\t\\t\\tthis.w = q1w * q2w - q1x * q2x - q1y * q2y - q1z * q2z;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tnormalize(src = this) {\\n\\t\\t\\t\\tlet len = src.length();\\n\\t\\t\\t\\tif (len === 0) {\\n\\t\\t\\t\\t\\t\\tthis.x = this.y = this.z = 0;\\n\\t\\t\\t\\t\\t\\tthis.w = 1;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tlen = 1 / len;\\n\\t\\t\\t\\t\\t\\tthis.x = src.x * len;\\n\\t\\t\\t\\t\\t\\tthis.y = src.y * len;\\n\\t\\t\\t\\t\\t\\tthis.z = src.z * len;\\n\\t\\t\\t\\t\\t\\tthis.w = src.w * len;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tset(x, y, z, w) {\\n\\t\\t\\t\\tthis.x = x;\\n\\t\\t\\t\\tthis.y = y;\\n\\t\\t\\t\\tthis.z = z;\\n\\t\\t\\t\\tthis.w = w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetFromAxisAngle(axis, angle) {\\n\\t\\t\\t\\tangle *= 0.5 * math.DEG_TO_RAD;\\n\\t\\t\\t\\tconst sa = Math.sin(angle);\\n\\t\\t\\t\\tconst ca = Math.cos(angle);\\n\\t\\t\\t\\tthis.x = sa * axis.x;\\n\\t\\t\\t\\tthis.y = sa * axis.y;\\n\\t\\t\\t\\tthis.z = sa * axis.z;\\n\\t\\t\\t\\tthis.w = ca;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetFromEulerAngles(ex, ey, ez) {\\n\\t\\t\\t\\tif (ex instanceof Vec3) {\\n\\t\\t\\t\\t\\t\\tconst vec = ex;\\n\\t\\t\\t\\t\\t\\tex = vec.x;\\n\\t\\t\\t\\t\\t\\tey = vec.y;\\n\\t\\t\\t\\t\\t\\tez = vec.z;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst halfToRad = 0.5 * math.DEG_TO_RAD;\\n\\t\\t\\t\\tex *= halfToRad;\\n\\t\\t\\t\\tey *= halfToRad;\\n\\t\\t\\t\\tez *= halfToRad;\\n\\t\\t\\t\\tconst sx = Math.sin(ex);\\n\\t\\t\\t\\tconst cx = Math.cos(ex);\\n\\t\\t\\t\\tconst sy = Math.sin(ey);\\n\\t\\t\\t\\tconst cy = Math.cos(ey);\\n\\t\\t\\t\\tconst sz = Math.sin(ez);\\n\\t\\t\\t\\tconst cz = Math.cos(ez);\\n\\t\\t\\t\\tthis.x = sx * cy * cz - cx * sy * sz;\\n\\t\\t\\t\\tthis.y = cx * sy * cz + sx * cy * sz;\\n\\t\\t\\t\\tthis.z = cx * cy * sz - sx * sy * cz;\\n\\t\\t\\t\\tthis.w = cx * cy * cz + sx * sy * sz;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetFromMat4(m) {\\n\\t\\t\\t\\tconst d = m.data;\\n\\t\\t\\t\\tlet m00 = d[0];\\n\\t\\t\\t\\tlet m01 = d[1];\\n\\t\\t\\t\\tlet m02 = d[2];\\n\\t\\t\\t\\tlet m10 = d[4];\\n\\t\\t\\t\\tlet m11 = d[5];\\n\\t\\t\\t\\tlet m12 = d[6];\\n\\t\\t\\t\\tlet m20 = d[8];\\n\\t\\t\\t\\tlet m21 = d[9];\\n\\t\\t\\t\\tlet m22 = d[10];\\n\\t\\t\\t\\tconst det = m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m12 * m20) + m02 * (m10 * m21 - m11 * m20);\\n\\t\\t\\t\\tif (det < 0) {\\n\\t\\t\\t\\t\\t\\tm00 = -m00;\\n\\t\\t\\t\\t\\t\\tm01 = -m01;\\n\\t\\t\\t\\t\\t\\tm02 = -m02;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet l;\\n\\t\\t\\t\\tl = m00 * m00 + m01 * m01 + m02 * m02;\\n\\t\\t\\t\\tif (l === 0) return this.set(0, 0, 0, 1);\\n\\t\\t\\t\\tl = 1 / Math.sqrt(l);\\n\\t\\t\\t\\tm00 *= l;\\n\\t\\t\\t\\tm01 *= l;\\n\\t\\t\\t\\tm02 *= l;\\n\\t\\t\\t\\tl = m10 * m10 + m11 * m11 + m12 * m12;\\n\\t\\t\\t\\tif (l === 0) return this.set(0, 0, 0, 1);\\n\\t\\t\\t\\tl = 1 / Math.sqrt(l);\\n\\t\\t\\t\\tm10 *= l;\\n\\t\\t\\t\\tm11 *= l;\\n\\t\\t\\t\\tm12 *= l;\\n\\t\\t\\t\\tl = m20 * m20 + m21 * m21 + m22 * m22;\\n\\t\\t\\t\\tif (l === 0) return this.set(0, 0, 0, 1);\\n\\t\\t\\t\\tl = 1 / Math.sqrt(l);\\n\\t\\t\\t\\tm20 *= l;\\n\\t\\t\\t\\tm21 *= l;\\n\\t\\t\\t\\tm22 *= l;\\n\\t\\t\\t\\tif (m22 < 0) {\\n\\t\\t\\t\\t\\t\\tif (m00 > m11) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.set(1 + m00 - m11 - m22, m01 + m10, m20 + m02, m12 - m21);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.set(m01 + m10, 1 - m00 + m11 - m22, m12 + m21, m20 - m02);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (m00 < -m11) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.set(m20 + m02, m12 + m21, 1 - m00 - m11 + m22, m01 - m10);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.set(m12 - m21, m20 - m02, m01 - m10, 1 + m00 + m11 + m22);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.mulScalar(1.0 / this.length());\\n\\t\\t}\\n\\t\\tsetFromDirections(from, to) {\\n\\t\\t\\t\\tconst dotProduct = 1 + from.dot(to);\\n\\t\\t\\t\\tif (dotProduct < Number.EPSILON) {\\n\\t\\t\\t\\t\\t\\tif (Math.abs(from.x) > Math.abs(from.y)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.x = -from.z;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.y = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.z = from.x;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.w = 0;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.x = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.y = -from.z;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.z = from.y;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.w = 0;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.x = from.y * to.z - from.z * to.y;\\n\\t\\t\\t\\t\\t\\tthis.y = from.z * to.x - from.x * to.z;\\n\\t\\t\\t\\t\\t\\tthis.z = from.x * to.y - from.y * to.x;\\n\\t\\t\\t\\t\\t\\tthis.w = dotProduct;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.normalize();\\n\\t\\t}\\n\\t\\tslerp(lhs, rhs, alpha) {\\n\\t\\t\\t\\tconst lx = lhs.x;\\n\\t\\t\\t\\tconst ly = lhs.y;\\n\\t\\t\\t\\tconst lz = lhs.z;\\n\\t\\t\\t\\tconst lw = lhs.w;\\n\\t\\t\\t\\tlet rx = rhs.x;\\n\\t\\t\\t\\tlet ry = rhs.y;\\n\\t\\t\\t\\tlet rz = rhs.z;\\n\\t\\t\\t\\tlet rw = rhs.w;\\n\\t\\t\\t\\tlet cosHalfTheta = lw * rw + lx * rx + ly * ry + lz * rz;\\n\\t\\t\\t\\tif (cosHalfTheta < 0) {\\n\\t\\t\\t\\t\\t\\trw = -rw;\\n\\t\\t\\t\\t\\t\\trx = -rx;\\n\\t\\t\\t\\t\\t\\try = -ry;\\n\\t\\t\\t\\t\\t\\trz = -rz;\\n\\t\\t\\t\\t\\t\\tcosHalfTheta = -cosHalfTheta;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (Math.abs(cosHalfTheta) >= 1) {\\n\\t\\t\\t\\t\\t\\tthis.w = lw;\\n\\t\\t\\t\\t\\t\\tthis.x = lx;\\n\\t\\t\\t\\t\\t\\tthis.y = ly;\\n\\t\\t\\t\\t\\t\\tthis.z = lz;\\n\\t\\t\\t\\t\\t\\treturn this;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst halfTheta = Math.acos(cosHalfTheta);\\n\\t\\t\\t\\tconst sinHalfTheta = Math.sqrt(1 - cosHalfTheta * cosHalfTheta);\\n\\t\\t\\t\\tif (Math.abs(sinHalfTheta) < 0.001) {\\n\\t\\t\\t\\t\\t\\tthis.w = lw * 0.5 + rw * 0.5;\\n\\t\\t\\t\\t\\t\\tthis.x = lx * 0.5 + rx * 0.5;\\n\\t\\t\\t\\t\\t\\tthis.y = ly * 0.5 + ry * 0.5;\\n\\t\\t\\t\\t\\t\\tthis.z = lz * 0.5 + rz * 0.5;\\n\\t\\t\\t\\t\\t\\treturn this;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst ratioA = Math.sin((1 - alpha) * halfTheta) / sinHalfTheta;\\n\\t\\t\\t\\tconst ratioB = Math.sin(alpha * halfTheta) / sinHalfTheta;\\n\\t\\t\\t\\tthis.w = lw * ratioA + rw * ratioB;\\n\\t\\t\\t\\tthis.x = lx * ratioA + rx * ratioB;\\n\\t\\t\\t\\tthis.y = ly * ratioA + ry * ratioB;\\n\\t\\t\\t\\tthis.z = lz * ratioA + rz * ratioB;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\ttransformVector(vec, res = new Vec3()) {\\n\\t\\t\\t\\tconst x = vec.x, y = vec.y, z = vec.z;\\n\\t\\t\\t\\tconst qx = this.x, qy = this.y, qz = this.z, qw = this.w;\\n\\t\\t\\t\\tconst ix = qw * x + qy * z - qz * y;\\n\\t\\t\\t\\tconst iy = qw * y + qz * x - qx * z;\\n\\t\\t\\t\\tconst iz = qw * z + qx * y - qy * x;\\n\\t\\t\\t\\tconst iw = -qx * x - qy * y - qz * z;\\n\\t\\t\\t\\tres.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;\\n\\t\\t\\t\\tres.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;\\n\\t\\t\\t\\tres.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;\\n\\t\\t\\t\\treturn res;\\n\\t\\t}\\n\\t\\tfromArray(arr, offset = 0) {\\n\\t\\t\\t\\tthis.x = arr[offset] ?? this.x;\\n\\t\\t\\t\\tthis.y = arr[offset + 1] ?? this.y;\\n\\t\\t\\t\\tthis.z = arr[offset + 2] ?? this.z;\\n\\t\\t\\t\\tthis.w = arr[offset + 3] ?? this.w;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\ttoString() {\\n\\t\\t\\t\\treturn `[${this.x}, ${this.y}, ${this.z}, ${this.w}]`;\\n\\t\\t}\\n\\t\\ttoArray(arr = [], offset = 0) {\\n\\t\\t\\t\\tarr[offset] = this.x;\\n\\t\\t\\t\\tarr[offset + 1] = this.y;\\n\\t\\t\\t\\tarr[offset + 2] = this.z;\\n\\t\\t\\t\\tarr[offset + 3] = this.w;\\n\\t\\t\\t\\treturn arr;\\n\\t\\t}\\n\\t\\tconstructor(x = 0, y = 0, z = 0, w = 1){\\n\\t\\t\\t\\tif (x.length === 4) {\\n\\t\\t\\t\\t\\t\\tthis.x = x[0];\\n\\t\\t\\t\\t\\t\\tthis.y = x[1];\\n\\t\\t\\t\\t\\t\\tthis.z = x[2];\\n\\t\\t\\t\\t\\t\\tthis.w = x[3];\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.x = x;\\n\\t\\t\\t\\t\\t\\tthis.y = y;\\n\\t\\t\\t\\t\\t\\tthis.z = z;\\n\\t\\t\\t\\t\\t\\tthis.w = w;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nQuat.IDENTITY = Object.freeze(new Quat(0, 0, 0, 1));\\nQuat.ZERO = Object.freeze(new Quat(0, 0, 0, 0));\\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\\t\\tadd(other) {\\n\\t\\t\\t\\tconst tc = this.center;\\n\\t\\t\\t\\tconst tcx = tc.x;\\n\\t\\t\\t\\tconst tcy = tc.y;\\n\\t\\t\\t\\tconst tcz = tc.z;\\n\\t\\t\\t\\tconst th = this.halfExtents;\\n\\t\\t\\t\\tconst thx = th.x;\\n\\t\\t\\t\\tconst thy = th.y;\\n\\t\\t\\t\\tconst thz = th.z;\\n\\t\\t\\t\\tlet tminx = tcx - thx;\\n\\t\\t\\t\\tlet tmaxx = tcx + thx;\\n\\t\\t\\t\\tlet tminy = tcy - thy;\\n\\t\\t\\t\\tlet tmaxy = tcy + thy;\\n\\t\\t\\t\\tlet tminz = tcz - thz;\\n\\t\\t\\t\\tlet tmaxz = tcz + thz;\\n\\t\\t\\t\\tconst oc = other.center;\\n\\t\\t\\t\\tconst ocx = oc.x;\\n\\t\\t\\t\\tconst ocy = oc.y;\\n\\t\\t\\t\\tconst ocz = oc.z;\\n\\t\\t\\t\\tconst oh = other.halfExtents;\\n\\t\\t\\t\\tconst ohx = oh.x;\\n\\t\\t\\t\\tconst ohy = oh.y;\\n\\t\\t\\t\\tconst ohz = oh.z;\\n\\t\\t\\t\\tconst ominx = ocx - ohx;\\n\\t\\t\\t\\tconst omaxx = ocx + ohx;\\n\\t\\t\\t\\tconst ominy = ocy - ohy;\\n\\t\\t\\t\\tconst omaxy = ocy + ohy;\\n\\t\\t\\t\\tconst ominz = ocz - ohz;\\n\\t\\t\\t\\tconst omaxz = ocz + ohz;\\n\\t\\t\\t\\tif (ominx < tminx) tminx = ominx;\\n\\t\\t\\t\\tif (omaxx > tmaxx) tmaxx = omaxx;\\n\\t\\t\\t\\tif (ominy < tminy) tminy = ominy;\\n\\t\\t\\t\\tif (omaxy > tmaxy) tmaxy = omaxy;\\n\\t\\t\\t\\tif (ominz < tminz) tminz = ominz;\\n\\t\\t\\t\\tif (omaxz > tmaxz) tmaxz = omaxz;\\n\\t\\t\\t\\ttc.x = (tminx + tmaxx) * 0.5;\\n\\t\\t\\t\\ttc.y = (tminy + tmaxy) * 0.5;\\n\\t\\t\\t\\ttc.z = (tminz + tmaxz) * 0.5;\\n\\t\\t\\t\\tth.x = (tmaxx - tminx) * 0.5;\\n\\t\\t\\t\\tth.y = (tmaxy - tminy) * 0.5;\\n\\t\\t\\t\\tth.z = (tmaxz - tminz) * 0.5;\\n\\t\\t}\\n\\t\\tcopy(src) {\\n\\t\\t\\t\\tthis.center.copy(src.center);\\n\\t\\t\\t\\tthis.halfExtents.copy(src.halfExtents);\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\treturn new BoundingBox(this.center, this.halfExtents);\\n\\t\\t}\\n\\t\\tintersects(other) {\\n\\t\\t\\t\\tconst aMax = this.getMax();\\n\\t\\t\\t\\tconst aMin = this.getMin();\\n\\t\\t\\t\\tconst bMax = other.getMax();\\n\\t\\t\\t\\tconst bMin = other.getMin();\\n\\t\\t\\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\\t}\\n\\t\\t_intersectsRay(ray, point) {\\n\\t\\t\\t\\tconst tMin = tmpVecA$1.copy(this.getMin()).sub(ray.origin);\\n\\t\\t\\t\\tconst tMax = tmpVecB$1.copy(this.getMax()).sub(ray.origin);\\n\\t\\t\\t\\tconst dir = ray.direction;\\n\\t\\t\\t\\tif (dir.x === 0) {\\n\\t\\t\\t\\t\\t\\ttMin.x = tMin.x < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;\\n\\t\\t\\t\\t\\t\\ttMax.x = tMax.x < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\ttMin.x /= dir.x;\\n\\t\\t\\t\\t\\t\\ttMax.x /= dir.x;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (dir.y === 0) {\\n\\t\\t\\t\\t\\t\\ttMin.y = tMin.y < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;\\n\\t\\t\\t\\t\\t\\ttMax.y = tMax.y < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\ttMin.y /= dir.y;\\n\\t\\t\\t\\t\\t\\ttMax.y /= dir.y;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (dir.z === 0) {\\n\\t\\t\\t\\t\\t\\ttMin.z = tMin.z < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;\\n\\t\\t\\t\\t\\t\\ttMax.z = tMax.z < 0 ? -Number.MAX_VALUE : Number.MAX_VALUE;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\ttMin.z /= dir.z;\\n\\t\\t\\t\\t\\t\\ttMax.z /= dir.z;\\n\\t\\t\\t\\t}\\n\\t\\t\\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\\t\\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\\t\\t\\tconst minMax = Math.min(Math.min(realMax.x, realMax.y), realMax.z);\\n\\t\\t\\t\\tconst maxMin = Math.max(Math.max(realMin.x, realMin.y), realMin.z);\\n\\t\\t\\t\\tconst intersects = minMax >= maxMin && maxMin >= 0;\\n\\t\\t\\t\\tif (intersects) {\\n\\t\\t\\t\\t\\t\\tpoint.copy(ray.direction).mulScalar(maxMin).add(ray.origin);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn intersects;\\n\\t\\t}\\n\\t\\t_fastIntersectsRay(ray) {\\n\\t\\t\\t\\tconst diff = tmpVecA$1;\\n\\t\\t\\t\\tconst cross = tmpVecB$1;\\n\\t\\t\\t\\tconst prod = tmpVecC;\\n\\t\\t\\t\\tconst absDiff = tmpVecD;\\n\\t\\t\\t\\tconst absDir = tmpVecE;\\n\\t\\t\\t\\tconst rayDir = ray.direction;\\n\\t\\t\\t\\tdiff.sub2(ray.origin, this.center);\\n\\t\\t\\t\\tabsDiff.set(Math.abs(diff.x), Math.abs(diff.y), Math.abs(diff.z));\\n\\t\\t\\t\\tprod.mul2(diff, rayDir);\\n\\t\\t\\t\\tif (absDiff.x > this.halfExtents.x && prod.x >= 0) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (absDiff.y > this.halfExtents.y && prod.y >= 0) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (absDiff.z > this.halfExtents.z && prod.z >= 0) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tabsDir.set(Math.abs(rayDir.x), Math.abs(rayDir.y), Math.abs(rayDir.z));\\n\\t\\t\\t\\tcross.cross(rayDir, diff);\\n\\t\\t\\t\\tcross.set(Math.abs(cross.x), Math.abs(cross.y), Math.abs(cross.z));\\n\\t\\t\\t\\tif (cross.x > this.halfExtents.y * absDir.z + this.halfExtents.z * absDir.y) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (cross.y > this.halfExtents.x * absDir.z + this.halfExtents.z * absDir.x) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (cross.z > this.halfExtents.x * absDir.y + this.halfExtents.y * absDir.x) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tintersectsRay(ray, point) {\\n\\t\\t\\t\\tif (point) {\\n\\t\\t\\t\\t\\t\\treturn this._intersectsRay(ray, point);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._fastIntersectsRay(ray);\\n\\t\\t}\\n\\t\\tsetMinMax(min, max) {\\n\\t\\t\\t\\tthis.center.add2(max, min).mulScalar(0.5);\\n\\t\\t\\t\\tthis.halfExtents.sub2(max, min).mulScalar(0.5);\\n\\t\\t}\\n\\t\\tgetMin() {\\n\\t\\t\\t\\treturn this._min.copy(this.center).sub(this.halfExtents);\\n\\t\\t}\\n\\t\\tgetMax() {\\n\\t\\t\\t\\treturn this._max.copy(this.center).add(this.halfExtents);\\n\\t\\t}\\n\\t\\tcontainsPoint(point) {\\n\\t\\t\\t\\tconst c = this.center;\\n\\t\\t\\t\\tconst h = this.halfExtents;\\n\\t\\t\\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\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tclosestPoint(point, result = new Vec3()) {\\n\\t\\t\\t\\tconst c = this.center;\\n\\t\\t\\t\\tconst h = this.halfExtents;\\n\\t\\t\\t\\treturn result.set(Math.max(c.x - h.x, Math.min(point.x, c.x + h.x)), Math.max(c.y - h.y, Math.min(point.y, c.y + h.y)), Math.max(c.z - h.z, Math.min(point.z, c.z + h.z)));\\n\\t\\t}\\n\\t\\tsetFromTransformedAabb(aabb, m, ignoreScale = false) {\\n\\t\\t\\t\\tconst ac = aabb.center;\\n\\t\\t\\t\\tconst ar = aabb.halfExtents;\\n\\t\\t\\t\\tconst d = m.data;\\n\\t\\t\\t\\tlet mx0 = d[0];\\n\\t\\t\\t\\tlet mx1 = d[4];\\n\\t\\t\\t\\tlet mx2 = d[8];\\n\\t\\t\\t\\tlet my0 = d[1];\\n\\t\\t\\t\\tlet my1 = d[5];\\n\\t\\t\\t\\tlet my2 = d[9];\\n\\t\\t\\t\\tlet mz0 = d[2];\\n\\t\\t\\t\\tlet mz1 = d[6];\\n\\t\\t\\t\\tlet mz2 = d[10];\\n\\t\\t\\t\\tif (ignoreScale) {\\n\\t\\t\\t\\t\\t\\tlet lengthSq = mx0 * mx0 + mx1 * mx1 + mx2 * mx2;\\n\\t\\t\\t\\t\\t\\tif (lengthSq > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst invLength = 1 / Math.sqrt(lengthSq);\\n\\t\\t\\t\\t\\t\\t\\t\\tmx0 *= invLength;\\n\\t\\t\\t\\t\\t\\t\\t\\tmx1 *= invLength;\\n\\t\\t\\t\\t\\t\\t\\t\\tmx2 *= invLength;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlengthSq = my0 * my0 + my1 * my1 + my2 * my2;\\n\\t\\t\\t\\t\\t\\tif (lengthSq > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst invLength = 1 / Math.sqrt(lengthSq);\\n\\t\\t\\t\\t\\t\\t\\t\\tmy0 *= invLength;\\n\\t\\t\\t\\t\\t\\t\\t\\tmy1 *= invLength;\\n\\t\\t\\t\\t\\t\\t\\t\\tmy2 *= invLength;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlengthSq = mz0 * mz0 + mz1 * mz1 + mz2 * mz2;\\n\\t\\t\\t\\t\\t\\tif (lengthSq > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst invLength = 1 / Math.sqrt(lengthSq);\\n\\t\\t\\t\\t\\t\\t\\t\\tmz0 *= invLength;\\n\\t\\t\\t\\t\\t\\t\\t\\tmz1 *= invLength;\\n\\t\\t\\t\\t\\t\\t\\t\\tmz2 *= invLength;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.center.set(d[12] + mx0 * ac.x + mx1 * ac.y + mx2 * ac.z, d[13] + my0 * ac.x + my1 * ac.y + my2 * ac.z, d[14] + mz0 * ac.x + mz1 * ac.y + mz2 * ac.z);\\n\\t\\t\\t\\tthis.halfExtents.set(Math.abs(mx0) * ar.x + Math.abs(mx1) * ar.y + Math.abs(mx2) * ar.z, Math.abs(my0) * ar.x + Math.abs(my1) * ar.y + Math.abs(my2) * ar.z, Math.abs(mz0) * ar.x + Math.abs(mz1) * ar.y + Math.abs(mz2) * ar.z);\\n\\t\\t}\\n\\t\\tstatic computeMinMax(vertices, min, max, numVerts = vertices.length / 3) {\\n\\t\\t\\t\\tif (numVerts > 0) {\\n\\t\\t\\t\\t\\t\\tlet minx = vertices[0];\\n\\t\\t\\t\\t\\t\\tlet miny = vertices[1];\\n\\t\\t\\t\\t\\t\\tlet minz = vertices[2];\\n\\t\\t\\t\\t\\t\\tlet maxx = minx;\\n\\t\\t\\t\\t\\t\\tlet maxy = miny;\\n\\t\\t\\t\\t\\t\\tlet maxz = minz;\\n\\t\\t\\t\\t\\t\\tconst n = numVerts * 3;\\n\\t\\t\\t\\t\\t\\tfor(let i = 3; i < n; i += 3){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst x = vertices[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst y = vertices[i + 1];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst z = vertices[i + 2];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (x < minx) minx = x;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (y < miny) miny = y;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (z < minz) minz = z;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (x > maxx) maxx = x;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (y > maxy) maxy = y;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (z > maxz) maxz = z;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tmin.set(minx, miny, minz);\\n\\t\\t\\t\\t\\t\\tmax.set(maxx, maxy, maxz);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcompute(vertices, numVerts) {\\n\\t\\t\\t\\tBoundingBox.computeMinMax(vertices, tmpVecA$1, tmpVecB$1, numVerts);\\n\\t\\t\\t\\tthis.setMinMax(tmpVecA$1, tmpVecB$1);\\n\\t\\t}\\n\\t\\tintersectsBoundingSphere(sphere) {\\n\\t\\t\\t\\tconst sq = this._distanceToBoundingSphereSq(sphere);\\n\\t\\t\\t\\tif (sq <= sphere.radius * sphere.radius) {\\n\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\t_distanceToBoundingSphereSq(sphere) {\\n\\t\\t\\t\\tconst boxMin = this.getMin();\\n\\t\\t\\t\\tconst boxMax = this.getMax();\\n\\t\\t\\t\\tlet sq = 0;\\n\\t\\t\\t\\tconst axis = [\\n\\t\\t\\t\\t\\t\\t'x',\\n\\t\\t\\t\\t\\t\\t'y',\\n\\t\\t\\t\\t\\t\\t'z'\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tfor(let i = 0; i < 3; ++i){\\n\\t\\t\\t\\t\\t\\tlet out = 0;\\n\\t\\t\\t\\t\\t\\tconst pn = sphere.center[axis[i]];\\n\\t\\t\\t\\t\\t\\tconst bMin = boxMin[axis[i]];\\n\\t\\t\\t\\t\\t\\tconst bMax = boxMax[axis[i]];\\n\\t\\t\\t\\t\\t\\tlet val = 0;\\n\\t\\t\\t\\t\\t\\tif (pn < bMin) {\\n\\t\\t\\t\\t\\t\\t\\t\\tval = bMin - pn;\\n\\t\\t\\t\\t\\t\\t\\t\\tout += val * val;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (pn > bMax) {\\n\\t\\t\\t\\t\\t\\t\\t\\tval = pn - bMax;\\n\\t\\t\\t\\t\\t\\t\\t\\tout += val * val;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tsq += out;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn sq;\\n\\t\\t}\\n\\t\\t_expand(expandMin, expandMax) {\\n\\t\\t\\t\\ttmpVecA$1.add2(this.getMin(), expandMin);\\n\\t\\t\\t\\ttmpVecB$1.add2(this.getMax(), expandMax);\\n\\t\\t\\t\\tthis.setMinMax(tmpVecA$1, tmpVecB$1);\\n\\t\\t}\\n\\t\\tconstructor(center, halfExtents){\\n\\t\\t\\t\\tthis.center = new Vec3();\\n\\t\\t\\t\\tthis.halfExtents = new Vec3(0.5, 0.5, 0.5);\\n\\t\\t\\t\\tthis._min = new Vec3();\\n\\t\\t\\t\\tthis._max = new Vec3();\\n\\t\\t\\t\\tif (center) {\\n\\t\\t\\t\\t\\t\\tthis.center.copy(center);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (halfExtents) {\\n\\t\\t\\t\\t\\t\\tthis.halfExtents.copy(halfExtents);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nconst tmpVecA = new Vec3();\\nconst tmpVecB = new Vec3();\\nclass BoundingSphere {\\n\\t\\tcontainsPoint(point) {\\n\\t\\t\\t\\tconst lenSq = tmpVecA.sub2(point, this.center).lengthSq();\\n\\t\\t\\t\\tconst r = this.radius;\\n\\t\\t\\t\\treturn lenSq < r * r;\\n\\t\\t}\\n\\t\\tintersectsRay(ray, point) {\\n\\t\\t\\t\\tconst m = tmpVecA.copy(ray.origin).sub(this.center);\\n\\t\\t\\t\\tconst b = m.dot(tmpVecB.copy(ray.direction).normalize());\\n\\t\\t\\t\\tconst c = m.dot(m) - this.radius * this.radius;\\n\\t\\t\\t\\tif (c > 0 && b > 0) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst discr = b * b - c;\\n\\t\\t\\t\\tif (discr < 0) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst t = Math.abs(-b - Math.sqrt(discr));\\n\\t\\t\\t\\tif (point) {\\n\\t\\t\\t\\t\\t\\tpoint.copy(ray.direction).mulScalar(t).add(ray.origin);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tintersectsBoundingSphere(sphere) {\\n\\t\\t\\t\\ttmpVecA.sub2(sphere.center, this.center);\\n\\t\\t\\t\\tconst totalRadius = sphere.radius + this.radius;\\n\\t\\t\\t\\tif (tmpVecA.lengthSq() <= totalRadius * totalRadius) {\\n\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tconstructor(center = new Vec3(), radius = 0.5){\\n\\t\\t\\t\\tthis.center = center;\\n\\t\\t\\t\\tthis.radius = radius;\\n\\t\\t}\\n}\\n\\nclass Plane {\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst cstr = this.constructor;\\n\\t\\t\\t\\treturn new cstr().copy(this);\\n\\t\\t}\\n\\t\\tcopy(src) {\\n\\t\\t\\t\\tthis.normal.copy(src.normal);\\n\\t\\t\\t\\tthis.distance = src.distance;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tintersectsLine(start, end, point) {\\n\\t\\t\\t\\tconst d = this.distance;\\n\\t\\t\\t\\tconst d0 = this.normal.dot(start) + d;\\n\\t\\t\\t\\tconst d1 = this.normal.dot(end) + d;\\n\\t\\t\\t\\tconst t = d0 / (d0 - d1);\\n\\t\\t\\t\\tconst intersects = t >= 0 && t <= 1;\\n\\t\\t\\t\\tif (intersects && point) {\\n\\t\\t\\t\\t\\t\\tpoint.lerp(start, end, t);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn intersects;\\n\\t\\t}\\n\\t\\tintersectsRay(ray, point) {\\n\\t\\t\\t\\tconst denominator = this.normal.dot(ray.direction);\\n\\t\\t\\t\\tif (denominator === 0) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst t = -(this.normal.dot(ray.origin) + this.distance) / denominator;\\n\\t\\t\\t\\tif (t >= 0 && point) {\\n\\t\\t\\t\\t\\t\\tpoint.copy(ray.direction).mulScalar(t).add(ray.origin);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn t >= 0;\\n\\t\\t}\\n\\t\\tnormalize() {\\n\\t\\t\\t\\tconst invLength = 1 / this.normal.length();\\n\\t\\t\\t\\tthis.normal.mulScalar(invLength);\\n\\t\\t\\t\\tthis.distance *= invLength;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tset(nx, ny, nz, d) {\\n\\t\\t\\t\\tthis.normal.set(nx, ny, nz);\\n\\t\\t\\t\\tthis.distance = d;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetFromPointNormal(point, normal) {\\n\\t\\t\\t\\tthis.normal.copy(normal);\\n\\t\\t\\t\\tthis.distance = -this.normal.dot(point);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tconstructor(normal = Vec3.UP, distance = 0){\\n\\t\\t\\t\\tthis.normal = new Vec3();\\n\\t\\t\\t\\tthis.normal.copy(normal);\\n\\t\\t\\t\\tthis.distance = distance;\\n\\t\\t}\\n}\\n\\nclass Frustum {\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst cstr = this.constructor;\\n\\t\\t\\t\\treturn new cstr().copy(this);\\n\\t\\t}\\n\\t\\tcopy(src) {\\n\\t\\t\\t\\tfor(let i = 0; i < 6; i++){\\n\\t\\t\\t\\t\\t\\tthis.planes[i].copy(src.planes[i]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetFromMat4(matrix) {\\n\\t\\t\\t\\tconst [m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33] = matrix.data;\\n\\t\\t\\t\\tconst planes = this.planes;\\n\\t\\t\\t\\tplanes[0].set(m03 - m00, m13 - m10, m23 - m20, m33 - m30).normalize();\\n\\t\\t\\t\\tplanes[1].set(m03 + m00, m13 + m10, m23 + m20, m33 + m30).normalize();\\n\\t\\t\\t\\tplanes[2].set(m03 + m01, m13 + m11, m23 + m21, m33 + m31).normalize();\\n\\t\\t\\t\\tplanes[3].set(m03 - m01, m13 - m11, m23 - m21, m33 - m31).normalize();\\n\\t\\t\\t\\tplanes[4].set(m03 - m02, m13 - m12, m23 - m22, m33 - m32).normalize();\\n\\t\\t\\t\\tplanes[5].set(m03 + m02, m13 + m12, m23 + m22, m33 + m32).normalize();\\n\\t\\t}\\n\\t\\tcontainsPoint(point) {\\n\\t\\t\\t\\tfor(let p = 0; p < 6; p++){\\n\\t\\t\\t\\t\\t\\tconst { normal, distance } = this.planes[p];\\n\\t\\t\\t\\t\\t\\tif (normal.dot(point) + distance <= 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tadd(other) {\\n\\t\\t\\t\\tconst planes = this.planes;\\n\\t\\t\\t\\tconst otherPlanes = other.planes;\\n\\t\\t\\t\\tfor(let p = 0; p < 6; p++){\\n\\t\\t\\t\\t\\t\\tif (otherPlanes[p].distance > planes[p].distance) {\\n\\t\\t\\t\\t\\t\\t\\t\\tplanes[p].copy(otherPlanes[p]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tcontainsSphere(sphere) {\\n\\t\\t\\t\\tconst { center, radius } = sphere;\\n\\t\\t\\t\\tlet c = 0;\\n\\t\\t\\t\\tfor(let p = 0; p < 6; p++){\\n\\t\\t\\t\\t\\t\\tconst { normal, distance } = this.planes[p];\\n\\t\\t\\t\\t\\t\\tconst d = normal.dot(center) + distance;\\n\\t\\t\\t\\t\\t\\tif (d <= -radius) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 0;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (d > radius) {\\n\\t\\t\\t\\t\\t\\t\\t\\tc++;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn c === 6 ? 2 : 1;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.planes = [];\\n\\t\\t\\t\\tfor(let i = 0; i < 6; i++){\\n\\t\\t\\t\\t\\t\\tthis.planes[i] = new Plane();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass Ray {\\n\\t\\tset(origin, direction) {\\n\\t\\t\\t\\tthis.origin.copy(origin);\\n\\t\\t\\t\\tthis.direction.copy(direction);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tcopy(src) {\\n\\t\\t\\t\\treturn this.set(src.origin, src.direction);\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\treturn new this.constructor(this.origin, this.direction);\\n\\t\\t}\\n\\t\\tconstructor(origin, direction){\\n\\t\\t\\t\\tthis.origin = new Vec3();\\n\\t\\t\\t\\tthis.direction = Vec3.FORWARD.clone();\\n\\t\\t\\t\\tif (origin) {\\n\\t\\t\\t\\t\\t\\tthis.origin.copy(origin);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (direction) {\\n\\t\\t\\t\\t\\t\\tthis.direction.copy(direction);\\n\\t\\t\\t\\t}\\n\\t\\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 = 0x0001;\\nconst BUFFERUSAGE_COPY_SRC = 0x0004;\\nconst BUFFERUSAGE_COPY_DST = 0x0008;\\nconst BUFFERUSAGE_INDEX = 0x0010;\\nconst BUFFERUSAGE_VERTEX = 0x0020;\\nconst BUFFERUSAGE_UNIFORM = 0x0040;\\nconst BUFFERUSAGE_STORAGE = 0x0080;\\nconst BUFFERUSAGE_INDIRECT = 0x0100;\\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 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_LESSEQUAL = 3;\\nconst FUNC_ALWAYS = 7;\\nconst INDEXFORMAT_UINT8 = 0;\\nconst INDEXFORMAT_UINT16 = 1;\\nconst INDEXFORMAT_UINT32 = 2;\\nconst indexFormatByteSize = [\\n\\t\\t1,\\n\\t\\t2,\\n\\t\\t4\\n];\\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 = new Map([\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_A8,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'A8',\\n\\t\\t\\t\\t\\t\\tsize: 1,\\n\\t\\t\\t\\t\\t\\tldr: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_R8,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'R8',\\n\\t\\t\\t\\t\\t\\tsize: 1,\\n\\t\\t\\t\\t\\t\\tldr: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_L8,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'L8',\\n\\t\\t\\t\\t\\t\\tsize: 1,\\n\\t\\t\\t\\t\\t\\tldr: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_LA8,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'LA8',\\n\\t\\t\\t\\t\\t\\tsize: 2,\\n\\t\\t\\t\\t\\t\\tldr: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RG8,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RG8',\\n\\t\\t\\t\\t\\t\\tsize: 2,\\n\\t\\t\\t\\t\\t\\tldr: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGB565,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGB565',\\n\\t\\t\\t\\t\\t\\tsize: 2,\\n\\t\\t\\t\\t\\t\\tldr: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGBA5551,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGBA5551',\\n\\t\\t\\t\\t\\t\\tsize: 2,\\n\\t\\t\\t\\t\\t\\tldr: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGBA4,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGBA4',\\n\\t\\t\\t\\t\\t\\tsize: 2,\\n\\t\\t\\t\\t\\t\\tldr: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGB8,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGB8',\\n\\t\\t\\t\\t\\t\\tsize: 4,\\n\\t\\t\\t\\t\\t\\tldr: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGBA8,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGBA8',\\n\\t\\t\\t\\t\\t\\tsize: 4,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgbFormat: PIXELFORMAT_SRGBA8\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_R16F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'R16F',\\n\\t\\t\\t\\t\\t\\tsize: 2\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RG16F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RG16F',\\n\\t\\t\\t\\t\\t\\tsize: 4\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGB16F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGB16F',\\n\\t\\t\\t\\t\\t\\tsize: 8\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGBA16F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGBA16F',\\n\\t\\t\\t\\t\\t\\tsize: 8\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGB32F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGB32F',\\n\\t\\t\\t\\t\\t\\tsize: 16\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGBA32F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGBA32F',\\n\\t\\t\\t\\t\\t\\tsize: 16\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_R32F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'R32F',\\n\\t\\t\\t\\t\\t\\tsize: 4\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RG32F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RG32F',\\n\\t\\t\\t\\t\\t\\tsize: 8\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGB9E5,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGB9E5',\\n\\t\\t\\t\\t\\t\\tsize: 4\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RG8S,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RG8S',\\n\\t\\t\\t\\t\\t\\tsize: 2\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGBA8S,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGBA8S',\\n\\t\\t\\t\\t\\t\\tsize: 4\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGB10A2,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGB10A2',\\n\\t\\t\\t\\t\\t\\tsize: 4\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGB10A2U,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGB10A2U',\\n\\t\\t\\t\\t\\t\\tsize: 4,\\n\\t\\t\\t\\t\\t\\tisUint: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_DEPTH,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'DEPTH',\\n\\t\\t\\t\\t\\t\\tsize: 4\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_DEPTH16,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'DEPTH16',\\n\\t\\t\\t\\t\\t\\tsize: 2\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_DEPTHSTENCIL,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'DEPTHSTENCIL',\\n\\t\\t\\t\\t\\t\\tsize: 4\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_111110F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: '111110F',\\n\\t\\t\\t\\t\\t\\tsize: 4\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_SRGB8,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'SRGB8',\\n\\t\\t\\t\\t\\t\\tsize: 4,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgb: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_SRGBA8,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'SRGBA8',\\n\\t\\t\\t\\t\\t\\tsize: 4,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgb: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_BGRA8,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'BGRA8',\\n\\t\\t\\t\\t\\t\\tsize: 4,\\n\\t\\t\\t\\t\\t\\tldr: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_SBGRA8,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'SBGRA8',\\n\\t\\t\\t\\t\\t\\tsize: 4,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgb: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_DXT1,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'DXT1',\\n\\t\\t\\t\\t\\t\\tblockSize: 8,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgbFormat: PIXELFORMAT_DXT1_SRGB\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_DXT3,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'DXT3',\\n\\t\\t\\t\\t\\t\\tblockSize: 16,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgbFormat: PIXELFORMAT_DXT3_SRGBA\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_DXT5,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'DXT5',\\n\\t\\t\\t\\t\\t\\tblockSize: 16,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgbFormat: PIXELFORMAT_DXT5_SRGBA\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_ETC1,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'ETC1',\\n\\t\\t\\t\\t\\t\\tblockSize: 8,\\n\\t\\t\\t\\t\\t\\tldr: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_ETC2_RGB,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'ETC2_RGB',\\n\\t\\t\\t\\t\\t\\tblockSize: 8,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgbFormat: PIXELFORMAT_ETC2_SRGB\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_ETC2_RGBA,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'ETC2_RGBA',\\n\\t\\t\\t\\t\\t\\tblockSize: 16,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgbFormat: PIXELFORMAT_ETC2_SRGBA\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_PVRTC_2BPP_RGB_1,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'PVRTC_2BPP_RGB_1',\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tblockSize: 8\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_PVRTC_2BPP_RGBA_1,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'PVRTC_2BPP_RGBA_1',\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tblockSize: 8\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_PVRTC_4BPP_RGB_1,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'PVRTC_4BPP_RGB_1',\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tblockSize: 8\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_PVRTC_4BPP_RGBA_1,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'PVRTC_4BPP_RGBA_1',\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tblockSize: 8\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_ASTC_4x4,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'ASTC_4x4',\\n\\t\\t\\t\\t\\t\\tblockSize: 16,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgbFormat: PIXELFORMAT_ASTC_4x4_SRGB\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_ATC_RGB,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'ATC_RGB',\\n\\t\\t\\t\\t\\t\\tblockSize: 8,\\n\\t\\t\\t\\t\\t\\tldr: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_ATC_RGBA,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'ATC_RGBA',\\n\\t\\t\\t\\t\\t\\tblockSize: 16,\\n\\t\\t\\t\\t\\t\\tldr: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_BC6F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'BC6H_RGBF',\\n\\t\\t\\t\\t\\t\\tblockSize: 16\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_BC6UF,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'BC6H_RGBUF',\\n\\t\\t\\t\\t\\t\\tblockSize: 16\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_BC7,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'BC7_RGBA',\\n\\t\\t\\t\\t\\t\\tblockSize: 16,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgbFormat: PIXELFORMAT_BC7_SRGBA\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_DXT1_SRGB,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'DXT1_SRGB',\\n\\t\\t\\t\\t\\t\\tblockSize: 8,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgb: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_DXT3_SRGBA,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'DXT3_SRGBA',\\n\\t\\t\\t\\t\\t\\tblockSize: 16,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgb: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_DXT5_SRGBA,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'DXT5_SRGBA',\\n\\t\\t\\t\\t\\t\\tblockSize: 16,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgb: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_ETC2_SRGB,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'ETC2_SRGB',\\n\\t\\t\\t\\t\\t\\tblockSize: 8,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgb: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_ETC2_SRGBA,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'ETC2_SRGBA',\\n\\t\\t\\t\\t\\t\\tblockSize: 16,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgb: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_ASTC_4x4_SRGB,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'ASTC_4x4_SRGB',\\n\\t\\t\\t\\t\\t\\tblockSize: 16,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgb: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_BC7_SRGBA,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'BC7_SRGBA',\\n\\t\\t\\t\\t\\t\\tblockSize: 16,\\n\\t\\t\\t\\t\\t\\tldr: true,\\n\\t\\t\\t\\t\\t\\tsrgb: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_R8I,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'R8I',\\n\\t\\t\\t\\t\\t\\tsize: 1,\\n\\t\\t\\t\\t\\t\\tisInt: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_R16I,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'R16I',\\n\\t\\t\\t\\t\\t\\tsize: 2,\\n\\t\\t\\t\\t\\t\\tisInt: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_R32I,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'R32I',\\n\\t\\t\\t\\t\\t\\tsize: 4,\\n\\t\\t\\t\\t\\t\\tisInt: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RG8I,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RG8I',\\n\\t\\t\\t\\t\\t\\tsize: 2,\\n\\t\\t\\t\\t\\t\\tisInt: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RG16I,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RG16I',\\n\\t\\t\\t\\t\\t\\tsize: 4,\\n\\t\\t\\t\\t\\t\\tisInt: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RG32I,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RG32I',\\n\\t\\t\\t\\t\\t\\tsize: 8,\\n\\t\\t\\t\\t\\t\\tisInt: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGBA8I,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGBA8I',\\n\\t\\t\\t\\t\\t\\tsize: 4,\\n\\t\\t\\t\\t\\t\\tisInt: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGBA16I,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGBA16I',\\n\\t\\t\\t\\t\\t\\tsize: 8,\\n\\t\\t\\t\\t\\t\\tisInt: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGBA32I,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGBA32I',\\n\\t\\t\\t\\t\\t\\tsize: 16,\\n\\t\\t\\t\\t\\t\\tisInt: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_R8U,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'R8U',\\n\\t\\t\\t\\t\\t\\tsize: 1,\\n\\t\\t\\t\\t\\t\\tisUint: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_R16U,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'R16U',\\n\\t\\t\\t\\t\\t\\tsize: 2,\\n\\t\\t\\t\\t\\t\\tisUint: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_R32U,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'R32U',\\n\\t\\t\\t\\t\\t\\tsize: 4,\\n\\t\\t\\t\\t\\t\\tisUint: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RG8U,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RG8U',\\n\\t\\t\\t\\t\\t\\tsize: 2,\\n\\t\\t\\t\\t\\t\\tisUint: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RG16U,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RG16U',\\n\\t\\t\\t\\t\\t\\tsize: 4,\\n\\t\\t\\t\\t\\t\\tisUint: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RG32U,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RG32U',\\n\\t\\t\\t\\t\\t\\tsize: 8,\\n\\t\\t\\t\\t\\t\\tisUint: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGBA8U,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGBA8U',\\n\\t\\t\\t\\t\\t\\tsize: 4,\\n\\t\\t\\t\\t\\t\\tisUint: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGBA16U,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGBA16U',\\n\\t\\t\\t\\t\\t\\tsize: 8,\\n\\t\\t\\t\\t\\t\\tisUint: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tPIXELFORMAT_RGBA32U,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'RGBA32U',\\n\\t\\t\\t\\t\\t\\tsize: 16,\\n\\t\\t\\t\\t\\t\\tisUint: true\\n\\t\\t\\t\\t}\\n\\t\\t]\\n]);\\nconst isCompressedPixelFormat = (format)=>{\\n\\t\\treturn pixelFormatInfo.get(format)?.blockSize !== undefined;\\n};\\nconst isSrgbPixelFormat = (format)=>{\\n\\t\\treturn pixelFormatInfo.get(format)?.srgb === true;\\n};\\nconst isIntegerPixelFormat = (format)=>{\\n\\t\\tconst info = pixelFormatInfo.get(format);\\n\\t\\treturn info?.isInt === true || info?.isUint === true;\\n};\\nconst GLSL_FLOAT = {\\n\\t\\tsampler: 'sampler2D',\\n\\t\\treturnType: 'vec4'\\n};\\nconst GLSL_UINT = {\\n\\t\\tsampler: 'usampler2D',\\n\\t\\treturnType: 'uvec4'\\n};\\nconst GLSL_INT = {\\n\\t\\tsampler: 'isampler2D',\\n\\t\\treturnType: 'ivec4'\\n};\\nconst WGSL_FLOAT = {\\n\\t\\ttextureType: 'texture_2d<f32>',\\n\\t\\treturnType: 'vec4f'\\n};\\nconst WGSL_UINT = {\\n\\t\\ttextureType: 'texture_2d<u32>',\\n\\t\\treturnType: 'vec4u'\\n};\\nconst WGSL_INT = {\\n\\t\\ttextureType: 'texture_2d<i32>',\\n\\t\\treturnType: 'vec4i'\\n};\\nconst getGlslShaderType = (format)=>{\\n\\t\\tconst info = pixelFormatInfo.get(format);\\n\\t\\tif (info?.isUint) return GLSL_UINT;\\n\\t\\tif (info?.isInt) return GLSL_INT;\\n\\t\\treturn GLSL_FLOAT;\\n};\\nconst getWgslShaderType = (format)=>{\\n\\t\\tconst info = pixelFormatInfo.get(format);\\n\\t\\tif (info?.isUint) return WGSL_UINT;\\n\\t\\tif (info?.isInt) return WGSL_INT;\\n\\t\\treturn WGSL_FLOAT;\\n};\\nconst pixelFormatLinearToGamma = (format)=>{\\n\\t\\treturn pixelFormatInfo.get(format)?.srgbFormat || format;\\n};\\nconst pixelFormatGammaToLinear = (format)=>{\\n\\t\\tfor (const [key, value] of pixelFormatInfo){\\n\\t\\t\\t\\tif (value.srgbFormat === format) {\\n\\t\\t\\t\\t\\t\\treturn key;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn format;\\n};\\nconst requiresManualGamma = (format)=>{\\n\\t\\tconst info = pixelFormatInfo.get(format);\\n\\t\\treturn !!(info?.ldr && !info?.srgb);\\n};\\nconst getPixelFormatArrayType = (format)=>{\\n\\t\\tswitch(format){\\n\\t\\t\\t\\tcase PIXELFORMAT_R32F:\\n\\t\\t\\t\\tcase PIXELFORMAT_RG32F:\\n\\t\\t\\t\\tcase PIXELFORMAT_RGB32F:\\n\\t\\t\\t\\tcase PIXELFORMAT_RGBA32F:\\n\\t\\t\\t\\t\\t\\treturn Float32Array;\\n\\t\\t\\t\\tcase PIXELFORMAT_R32I:\\n\\t\\t\\t\\tcase PIXELFORMAT_RG32I:\\n\\t\\t\\t\\tcase PIXELFORMAT_RGBA32I:\\n\\t\\t\\t\\t\\t\\treturn Int32Array;\\n\\t\\t\\t\\tcase PIXELFORMAT_R32U:\\n\\t\\t\\t\\tcase PIXELFORMAT_RG32U:\\n\\t\\t\\t\\tcase PIXELFORMAT_RGBA32U:\\n\\t\\t\\t\\tcase PIXELFORMAT_RGB9E5:\\n\\t\\t\\t\\tcase PIXELFORMAT_RGB10A2:\\n\\t\\t\\t\\tcase PIXELFORMAT_RGB10A2U:\\n\\t\\t\\t\\t\\t\\treturn Uint32Array;\\n\\t\\t\\t\\tcase PIXELFORMAT_R16I:\\n\\t\\t\\t\\tcase PIXELFORMAT_RG16I:\\n\\t\\t\\t\\tcase PIXELFORMAT_RGBA16I:\\n\\t\\t\\t\\t\\t\\treturn Int16Array;\\n\\t\\t\\t\\tcase PIXELFORMAT_R16U:\\n\\t\\t\\t\\tcase PIXELFORMAT_RG16U:\\n\\t\\t\\t\\tcase PIXELFORMAT_RGBA16U:\\n\\t\\t\\t\\tcase PIXELFORMAT_RGB565:\\n\\t\\t\\t\\tcase PIXELFORMAT_RGBA5551:\\n\\t\\t\\t\\tcase PIXELFORMAT_RGBA4:\\n\\t\\t\\t\\tcase PIXELFORMAT_R16F:\\n\\t\\t\\t\\tcase PIXELFORMAT_RG16F:\\n\\t\\t\\t\\tcase PIXELFORMAT_RGB16F:\\n\\t\\t\\t\\tcase PIXELFORMAT_RGBA16F:\\n\\t\\t\\t\\t\\t\\treturn Uint16Array;\\n\\t\\t\\t\\tcase PIXELFORMAT_R8I:\\n\\t\\t\\t\\tcase PIXELFORMAT_RG8I:\\n\\t\\t\\t\\tcase PIXELFORMAT_RGBA8I:\\n\\t\\t\\t\\tcase PIXELFORMAT_RG8S:\\n\\t\\t\\t\\tcase PIXELFORMAT_RGBA8S:\\n\\t\\t\\t\\t\\t\\treturn Int8Array;\\n\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\treturn Uint8Array;\\n\\t\\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\\t'bool',\\n\\t\\t'int',\\n\\t\\t'float',\\n\\t\\t'vec2',\\n\\t\\t'vec3',\\n\\t\\t'vec4',\\n\\t\\t'ivec2',\\n\\t\\t'ivec3',\\n\\t\\t'ivec4',\\n\\t\\t'bvec2',\\n\\t\\t'bvec3',\\n\\t\\t'bvec4',\\n\\t\\t'mat2',\\n\\t\\t'mat3',\\n\\t\\t'mat4',\\n\\t\\t'sampler2D',\\n\\t\\t'samplerCube',\\n\\t\\t'',\\n\\t\\t'sampler2DShadow',\\n\\t\\t'samplerCubeShadow',\\n\\t\\t'sampler3D',\\n\\t\\t'',\\n\\t\\t'',\\n\\t\\t'',\\n\\t\\t'',\\n\\t\\t'sampler2DArray',\\n\\t\\t'uint',\\n\\t\\t'uvec2',\\n\\t\\t'uvec3',\\n\\t\\t'uvec4',\\n\\t\\t'',\\n\\t\\t'',\\n\\t\\t'',\\n\\t\\t'',\\n\\t\\t'',\\n\\t\\t'',\\n\\t\\t'',\\n\\t\\t'',\\n\\t\\t'',\\n\\t\\t'',\\n\\t\\t'',\\n\\t\\t'',\\n\\t\\t'isampler2D',\\n\\t\\t'usampler2D',\\n\\t\\t'isamplerCube',\\n\\t\\t'usamplerCube',\\n\\t\\t'isampler3D',\\n\\t\\t'usampler3D',\\n\\t\\t'isampler2DArray',\\n\\t\\t'usampler2DArray'\\n];\\nconst uniformTypeToNameWGSL = [\\n\\t\\t[\\n\\t\\t\\t\\t'bool'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'i32'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'f32'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'vec2f',\\n\\t\\t\\t\\t'vec2<f32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'vec3f',\\n\\t\\t\\t\\t'vec3<f32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'vec4f',\\n\\t\\t\\t\\t'vec4<f32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'vec2i',\\n\\t\\t\\t\\t'vec2<i32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'vec3i',\\n\\t\\t\\t\\t'vec3<i32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'vec4i',\\n\\t\\t\\t\\t'vec4<i32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'vec2<bool>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'vec3<bool>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'vec4<bool>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'mat2x2f',\\n\\t\\t\\t\\t'mat2x2<f32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'mat3x3f',\\n\\t\\t\\t\\t'mat3x3<f32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'mat4x4f',\\n\\t\\t\\t\\t'mat4x4<f32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'texture_2d<f32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'texture_cube<f32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<f32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'texture_depth_2d'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'texture_depth_cube'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'texture_3d<f32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<vec2<f32>>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<vec3<f32>>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<vec4<f32>>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<mat4x4<f32>>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'texture_2d_array<f32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'u32'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'vec2u',\\n\\t\\t\\t\\t'vec2<u32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'vec3u',\\n\\t\\t\\t\\t'vec3<u32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'vec4u',\\n\\t\\t\\t\\t'vec4<u32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<i32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<u32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<bool>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<vec2i>',\\n\\t\\t\\t\\t'array<vec2<i32>>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<vec2u>',\\n\\t\\t\\t\\t'array<vec2<u32>>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<vec2b>',\\n\\t\\t\\t\\t'array<vec2<bool>>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<vec3i>',\\n\\t\\t\\t\\t'array<vec3<i32>>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<vec3u>',\\n\\t\\t\\t\\t'array<vec3<u32>>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<vec3b>',\\n\\t\\t\\t\\t'array<vec3<bool>>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<vec4i>',\\n\\t\\t\\t\\t'array<vec4<i32>>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<vec4u>',\\n\\t\\t\\t\\t'array<vec4<u32>>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'array<vec4b>',\\n\\t\\t\\t\\t'array<vec4<bool>>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'texture_2d<i32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'texture_2d<u32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'texture_cube<i32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'texture_cube<u32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'texture_3d<i32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'texture_3d<u32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'texture_2d_array<i32>'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'texture_2d_array<u32>'\\n\\t\\t]\\n];\\nconst uniformTypeToNameMapWGSL = new Map();\\nuniformTypeToNameWGSL.forEach((names, index)=>{\\n\\t\\tnames.forEach((name)=>uniformTypeToNameMapWGSL.set(name, index));\\n});\\nconst DEVICETYPE_WEBGL2 = 'webgl2';\\nconst DEVICETYPE_WEBGPU = 'webgpu';\\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 = [\\n\\t\\t'view',\\n\\t\\t'mesh',\\n\\t\\t'mesh_ub'\\n];\\nconst UNIFORM_BUFFER_DEFAULT_SLOT_NAME = 'default';\\nconst UNUSED_UNIFORM_NAME = '_unused_float_uniform';\\nconst typedArrayTypes = [\\n\\t\\tInt8Array,\\n\\t\\tUint8Array,\\n\\t\\tInt16Array,\\n\\t\\tUint16Array,\\n\\t\\tInt32Array,\\n\\t\\tUint32Array,\\n\\t\\tFloat32Array,\\n\\t\\tUint16Array\\n];\\nconst typedArrayTypesByteSize = [\\n\\t\\t1,\\n\\t\\t1,\\n\\t\\t2,\\n\\t\\t2,\\n\\t\\t4,\\n\\t\\t4,\\n\\t\\t4,\\n\\t\\t2\\n];\\nconst typedArrayIndexFormats = [\\n\\t\\tUint8Array,\\n\\t\\tUint16Array,\\n\\t\\tUint32Array\\n];\\nconst typedArrayIndexFormatsByteSize = [\\n\\t\\t1,\\n\\t\\t2,\\n\\t\\t4\\n];\\nconst primitiveGlslToWgslTypeMap = new Map([\\n\\t\\t[\\n\\t\\t\\t\\t'float',\\n\\t\\t\\t\\t'f32'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'vec2',\\n\\t\\t\\t\\t'vec2f'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'vec3',\\n\\t\\t\\t\\t'vec3f'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'vec4',\\n\\t\\t\\t\\t'vec4f'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'int',\\n\\t\\t\\t\\t'i32'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'ivec2',\\n\\t\\t\\t\\t'vec2i'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'ivec3',\\n\\t\\t\\t\\t'vec3i'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'ivec4',\\n\\t\\t\\t\\t'vec4i'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'uint',\\n\\t\\t\\t\\t'u32'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'uvec2',\\n\\t\\t\\t\\t'vec2u'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'uvec3',\\n\\t\\t\\t\\t'vec3u'\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'uvec4',\\n\\t\\t\\t\\t'vec4u'\\n\\t\\t]\\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\\t\\tconstructor(name, visibility){\\n\\t\\t\\t\\tthis.slot = -1;\\n\\t\\t\\t\\tthis.scopeId = null;\\n\\t\\t\\t\\tthis.name = name;\\n\\t\\t\\t\\tthis.visibility = visibility;\\n\\t\\t}\\n}\\nclass BindUniformBufferFormat extends BindBaseFormat {\\n}\\nclass BindStorageBufferFormat extends BindBaseFormat {\\n\\t\\tconstructor(name, visibility, readOnly = false){\\n\\t\\t\\t\\tsuper(name, visibility), this.format = '';\\n\\t\\t\\t\\tthis.readOnly = readOnly;\\n\\t\\t}\\n}\\nclass BindTextureFormat extends BindBaseFormat {\\n\\t\\tconstructor(name, visibility, textureDimension = TEXTUREDIMENSION_2D, sampleType = SAMPLETYPE_FLOAT, hasSampler = true, samplerName = null){\\n\\t\\t\\t\\tsuper(name, visibility);\\n\\t\\t\\t\\tthis.textureDimension = textureDimension;\\n\\t\\t\\t\\tthis.sampleType = sampleType;\\n\\t\\t\\t\\tthis.hasSampler = hasSampler;\\n\\t\\t\\t\\tthis.samplerName = samplerName ?? `${name}_sampler`;\\n\\t\\t}\\n}\\nclass BindStorageTextureFormat extends BindBaseFormat {\\n\\t\\tconstructor(name, format = PIXELFORMAT_RGBA8, textureDimension = TEXTUREDIMENSION_2D, write = true, read = false){\\n\\t\\t\\t\\tsuper(name, SHADERSTAGE_COMPUTE);\\n\\t\\t\\t\\tthis.format = format;\\n\\t\\t\\t\\tthis.textureDimension = textureDimension;\\n\\t\\t\\t\\tthis.write = write;\\n\\t\\t\\t\\tthis.read = read;\\n\\t\\t}\\n}\\nclass BindGroupFormat {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.impl.destroy();\\n\\t\\t}\\n\\t\\tgetTexture(name) {\\n\\t\\t\\t\\tconst index = this.textureFormatsMap.get(name);\\n\\t\\t\\t\\tif (index !== undefined) {\\n\\t\\t\\t\\t\\t\\treturn this.textureFormats[index];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tgetStorageTexture(name) {\\n\\t\\t\\t\\tconst index = this.storageTextureFormatsMap.get(name);\\n\\t\\t\\t\\tif (index !== undefined) {\\n\\t\\t\\t\\t\\t\\treturn this.storageTextureFormats[index];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tloseContext() {}\\n\\t\\tconstructor(graphicsDevice, formats){\\n\\t\\t\\t\\tthis.uniformBufferFormats = [];\\n\\t\\t\\t\\tthis.textureFormats = [];\\n\\t\\t\\t\\tthis.storageTextureFormats = [];\\n\\t\\t\\t\\tthis.storageBufferFormats = [];\\n\\t\\t\\t\\tthis.id = id$c++;\\n\\t\\t\\t\\tlet slot = 0;\\n\\t\\t\\t\\tformats.forEach((format)=>{\\n\\t\\t\\t\\t\\t\\tformat.slot = slot++;\\n\\t\\t\\t\\t\\t\\tif (format instanceof BindTextureFormat && format.hasSampler) {\\n\\t\\t\\t\\t\\t\\t\\t\\tslot++;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (format instanceof BindUniformBufferFormat) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.uniformBufferFormats.push(format);\\n\\t\\t\\t\\t\\t\\t} else if (format instanceof BindTextureFormat) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.textureFormats.push(format);\\n\\t\\t\\t\\t\\t\\t} else if (format instanceof BindStorageTextureFormat) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.storageTextureFormats.push(format);\\n\\t\\t\\t\\t\\t\\t} else if (format instanceof BindStorageBufferFormat) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.storageBufferFormats.push(format);\\n\\t\\t\\t\\t\\t\\t} else ;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t\\t\\tconst scope = graphicsDevice.scope;\\n\\t\\t\\t\\tthis.bufferFormatsMap = new Map();\\n\\t\\t\\t\\tthis.uniformBufferFormats.forEach((bf, i)=>this.bufferFormatsMap.set(bf.name, i));\\n\\t\\t\\t\\tthis.textureFormatsMap = new Map();\\n\\t\\t\\t\\tthis.textureFormats.forEach((tf, i)=>{\\n\\t\\t\\t\\t\\t\\tthis.textureFormatsMap.set(tf.name, i);\\n\\t\\t\\t\\t\\t\\ttf.scopeId = scope.resolve(tf.name);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.storageTextureFormatsMap = new Map();\\n\\t\\t\\t\\tthis.storageTextureFormats.forEach((tf, i)=>{\\n\\t\\t\\t\\t\\t\\tthis.storageTextureFormatsMap.set(tf.name, i);\\n\\t\\t\\t\\t\\t\\ttf.scopeId = scope.resolve(tf.name);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.storageBufferFormatsMap = new Map();\\n\\t\\t\\t\\tthis.storageBufferFormats.forEach((bf, i)=>{\\n\\t\\t\\t\\t\\t\\tthis.storageBufferFormatsMap.set(bf.name, i);\\n\\t\\t\\t\\t\\t\\tbf.scopeId = scope.resolve(bf.name);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.impl = graphicsDevice.createBindGroupFormatImpl(this);\\n\\t\\t}\\n}\\n\\nclass DeviceCache {\\n\\t\\tget(device, onCreate) {\\n\\t\\t\\t\\tif (!this._cache.has(device)) {\\n\\t\\t\\t\\t\\t\\tthis._cache.set(device, onCreate());\\n\\t\\t\\t\\t\\t\\tdevice.on('destroy', ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.remove(device);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tdevice.on('devicelost', ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._cache.get(device)?.loseContext?.(device);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._cache.get(device);\\n\\t\\t}\\n\\t\\tremove(device) {\\n\\t\\t\\t\\tthis._cache.get(device)?.destroy?.(device);\\n\\t\\t\\t\\tthis._cache.delete(device);\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis._cache = new Map();\\n\\t\\t}\\n}\\n\\nclass TextureUtils {\\n\\t\\tstatic calcLevelDimension(dimension, mipLevel) {\\n\\t\\t\\t\\treturn Math.max(dimension >> mipLevel, 1);\\n\\t\\t}\\n\\t\\tstatic calcMipLevelsCount(width, height, depth = 1) {\\n\\t\\t\\t\\treturn 1 + Math.floor(Math.log2(Math.max(width, height, depth)));\\n\\t\\t}\\n\\t\\tstatic calcLevelGpuSize(width, height, depth, format) {\\n\\t\\t\\t\\tconst formatInfo = pixelFormatInfo.get(format);\\n\\t\\t\\t\\tconst pixelSize = pixelFormatInfo.get(format)?.size ?? 0;\\n\\t\\t\\t\\tif (pixelSize > 0) {\\n\\t\\t\\t\\t\\t\\treturn width * height * depth * pixelSize;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst blockSize = formatInfo.blockSize ?? 0;\\n\\t\\t\\t\\tlet blockWidth = Math.floor((width + 3) / 4);\\n\\t\\t\\t\\tconst blockHeight = Math.floor((height + 3) / 4);\\n\\t\\t\\t\\tconst blockDepth = Math.floor((depth + 3) / 4);\\n\\t\\t\\t\\tif (format === PIXELFORMAT_PVRTC_2BPP_RGB_1 || format === PIXELFORMAT_PVRTC_2BPP_RGBA_1) {\\n\\t\\t\\t\\t\\t\\tblockWidth = Math.max(Math.floor(blockWidth / 2), 1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn blockWidth * blockHeight * blockDepth * blockSize;\\n\\t\\t}\\n\\t\\tstatic calcGpuSize(width, height, depth, format, mipmaps, cubemap) {\\n\\t\\t\\t\\tlet result = 0;\\n\\t\\t\\t\\twhile(1){\\n\\t\\t\\t\\t\\t\\tresult += TextureUtils.calcLevelGpuSize(width, height, depth, format);\\n\\t\\t\\t\\t\\t\\tif (!mipmaps || width === 1 && height === 1 && depth === 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\twidth = Math.max(width >> 1, 1);\\n\\t\\t\\t\\t\\t\\theight = Math.max(height >> 1, 1);\\n\\t\\t\\t\\t\\t\\tdepth = Math.max(depth >> 1, 1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result * (cubemap ? 6 : 1);\\n\\t\\t}\\n}\\n\\nclass StringIds {\\n\\t\\tget(name) {\\n\\t\\t\\t\\tlet value = this.map.get(name);\\n\\t\\t\\t\\tif (value === undefined) {\\n\\t\\t\\t\\t\\t\\tvalue = this.id++;\\n\\t\\t\\t\\t\\t\\tthis.map.set(name, value);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn value;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.map = new Map();\\n\\t\\t\\t\\tthis.id = 0;\\n\\t\\t}\\n}\\n\\nconst stringIds$5 = new StringIds();\\nclass TextureView {\\n\\t\\tconstructor(texture, baseMipLevel = 0, mipLevelCount = 1, baseArrayLayer = 0, arrayLayerCount = 1){\\n\\t\\t\\t\\tthis.texture = texture;\\n\\t\\t\\t\\tthis.baseMipLevel = baseMipLevel;\\n\\t\\t\\t\\tthis.mipLevelCount = mipLevelCount;\\n\\t\\t\\t\\tthis.baseArrayLayer = baseArrayLayer;\\n\\t\\t\\t\\tthis.arrayLayerCount = arrayLayerCount;\\n\\t\\t\\t\\tthis.key = stringIds$5.get(`${baseMipLevel}:${mipLevelCount}:${baseArrayLayer}:${arrayLayerCount}`);\\n\\t\\t}\\n}\\n\\nlet id$b = 0;\\nclass Texture {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tif (device) {\\n\\t\\t\\t\\t\\t\\tdevice.onTextureDestroyed(this);\\n\\t\\t\\t\\t\\t\\tthis.impl.destroy(device);\\n\\t\\t\\t\\t\\t\\tthis.adjustVramSizeTracking(device._vram, -this._gpuSize);\\n\\t\\t\\t\\t\\t\\tthis._levels = null;\\n\\t\\t\\t\\t\\t\\tthis.device = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\trecreateImpl(upload = true) {\\n\\t\\t\\t\\tconst { device } = this;\\n\\t\\t\\t\\tthis.impl?.destroy(device);\\n\\t\\t\\t\\tthis.impl = null;\\n\\t\\t\\t\\tthis.impl = device.createTextureImpl(this);\\n\\t\\t\\t\\tthis.dirtyAll();\\n\\t\\t\\t\\tif (upload) {\\n\\t\\t\\t\\t\\t\\tthis.upload();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_clearLevels() {\\n\\t\\t\\t\\tthis._levels = this._cubemap ? [\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\tnull,\\n\\t\\t\\t\\t\\t\\t\\t\\tnull,\\n\\t\\t\\t\\t\\t\\t\\t\\tnull,\\n\\t\\t\\t\\t\\t\\t\\t\\tnull,\\n\\t\\t\\t\\t\\t\\t\\t\\tnull,\\n\\t\\t\\t\\t\\t\\t\\t\\tnull\\n\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t] : [\\n\\t\\t\\t\\t\\t\\tnull\\n\\t\\t\\t\\t];\\n\\t\\t}\\n\\t\\tresize(width, height, depth = 1) {\\n\\t\\t\\t\\tif (this.width !== width || this.height !== height || this.depth !== depth) {\\n\\t\\t\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\t\\t\\tthis.adjustVramSizeTracking(device._vram, -this._gpuSize);\\n\\t\\t\\t\\t\\t\\tthis._gpuSize = 0;\\n\\t\\t\\t\\t\\t\\tthis.impl.destroy(device);\\n\\t\\t\\t\\t\\t\\tthis._clearLevels();\\n\\t\\t\\t\\t\\t\\tthis._width = Math.floor(width);\\n\\t\\t\\t\\t\\t\\tthis._height = Math.floor(height);\\n\\t\\t\\t\\t\\t\\tthis._depth = Math.floor(depth);\\n\\t\\t\\t\\t\\t\\tthis._updateNumLevel();\\n\\t\\t\\t\\t\\t\\tthis.impl = device.createTextureImpl(this);\\n\\t\\t\\t\\t\\t\\tthis.dirtyAll();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tthis.impl.loseContext();\\n\\t\\t\\t\\tthis.dirtyAll();\\n\\t\\t}\\n\\t\\tadjustVramSizeTracking(vram, size) {\\n\\t\\t\\t\\tvram.tex += size;\\n\\t\\t}\\n\\t\\tpropertyChanged(flag) {\\n\\t\\t\\t\\tthis.impl.propertyChanged(flag);\\n\\t\\t\\t\\tthis.renderVersionDirty = this.device.renderVersion;\\n\\t\\t}\\n\\t\\t_updateNumLevel() {\\n\\t\\t\\t\\tconst maxLevels = this.mipmaps ? TextureUtils.calcMipLevelsCount(this.width, this.height) : 1;\\n\\t\\t\\t\\tconst requestedLevels = this._numLevelsRequested;\\n\\t\\t\\t\\tthis._numLevels = Math.min(requestedLevels ?? maxLevels, maxLevels);\\n\\t\\t\\t\\tthis._mipmaps = this._numLevels > 1;\\n\\t\\t}\\n\\t\\tget lockedMode() {\\n\\t\\t\\t\\treturn this._lockedMode;\\n\\t\\t}\\n\\t\\tset minFilter(v) {\\n\\t\\t\\t\\tif (this._minFilter !== v) {\\n\\t\\t\\t\\t\\t\\tif (isIntegerPixelFormat(this._format)) ; else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._minFilter = v;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.propertyChanged(TEXPROPERTY_MIN_FILTER);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget minFilter() {\\n\\t\\t\\t\\treturn this._minFilter;\\n\\t\\t}\\n\\t\\tset magFilter(v) {\\n\\t\\t\\t\\tif (this._magFilter !== v) {\\n\\t\\t\\t\\t\\t\\tif (isIntegerPixelFormat(this._format)) ; else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._magFilter = v;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.propertyChanged(TEXPROPERTY_MAG_FILTER);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget magFilter() {\\n\\t\\t\\t\\treturn this._magFilter;\\n\\t\\t}\\n\\t\\tset addressU(v) {\\n\\t\\t\\t\\tif (this._addressU !== v) {\\n\\t\\t\\t\\t\\t\\tthis._addressU = v;\\n\\t\\t\\t\\t\\t\\tthis.propertyChanged(TEXPROPERTY_ADDRESS_U);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget addressU() {\\n\\t\\t\\t\\treturn this._addressU;\\n\\t\\t}\\n\\t\\tset addressV(v) {\\n\\t\\t\\t\\tif (this._addressV !== v) {\\n\\t\\t\\t\\t\\t\\tthis._addressV = v;\\n\\t\\t\\t\\t\\t\\tthis.propertyChanged(TEXPROPERTY_ADDRESS_V);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget addressV() {\\n\\t\\t\\t\\treturn this._addressV;\\n\\t\\t}\\n\\t\\tset addressW(addressW) {\\n\\t\\t\\t\\tif (!this._volume) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (addressW !== this._addressW) {\\n\\t\\t\\t\\t\\t\\tthis._addressW = addressW;\\n\\t\\t\\t\\t\\t\\tthis.propertyChanged(TEXPROPERTY_ADDRESS_W);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget addressW() {\\n\\t\\t\\t\\treturn this._addressW;\\n\\t\\t}\\n\\t\\tset compareOnRead(v) {\\n\\t\\t\\t\\tif (this._compareOnRead !== v) {\\n\\t\\t\\t\\t\\t\\tthis._compareOnRead = v;\\n\\t\\t\\t\\t\\t\\tthis.propertyChanged(TEXPROPERTY_COMPARE_ON_READ);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget compareOnRead() {\\n\\t\\t\\t\\treturn this._compareOnRead;\\n\\t\\t}\\n\\t\\tset compareFunc(v) {\\n\\t\\t\\t\\tif (this._compareFunc !== v) {\\n\\t\\t\\t\\t\\t\\tthis._compareFunc = v;\\n\\t\\t\\t\\t\\t\\tthis.propertyChanged(TEXPROPERTY_COMPARE_FUNC);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget compareFunc() {\\n\\t\\t\\t\\treturn this._compareFunc;\\n\\t\\t}\\n\\t\\tset anisotropy(v) {\\n\\t\\t\\t\\tif (this._anisotropy !== v) {\\n\\t\\t\\t\\t\\t\\tthis._anisotropy = v;\\n\\t\\t\\t\\t\\t\\tthis.propertyChanged(TEXPROPERTY_ANISOTROPY);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget anisotropy() {\\n\\t\\t\\t\\treturn this._anisotropy;\\n\\t\\t}\\n\\t\\tset mipmaps(v) {\\n\\t\\t\\t\\tif (this._mipmaps !== v) {\\n\\t\\t\\t\\t\\t\\tif (this.device.isWebGPU) ; else if (isIntegerPixelFormat(this._format)) ; else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._mipmaps = v;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (v) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._needsMipmapsUpload = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.device?.texturesToUpload?.add(this);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget mipmaps() {\\n\\t\\t\\t\\treturn this._mipmaps;\\n\\t\\t}\\n\\t\\tget numLevels() {\\n\\t\\t\\t\\treturn this._numLevels;\\n\\t\\t}\\n\\t\\tget storage() {\\n\\t\\t\\t\\treturn this._storage;\\n\\t\\t}\\n\\t\\tget width() {\\n\\t\\t\\t\\treturn this._width;\\n\\t\\t}\\n\\t\\tget height() {\\n\\t\\t\\t\\treturn this._height;\\n\\t\\t}\\n\\t\\tget depth() {\\n\\t\\t\\t\\treturn this._depth;\\n\\t\\t}\\n\\t\\tget format() {\\n\\t\\t\\t\\treturn this._format;\\n\\t\\t}\\n\\t\\tget cubemap() {\\n\\t\\t\\t\\treturn this._cubemap;\\n\\t\\t}\\n\\t\\tget gpuSize() {\\n\\t\\t\\t\\tconst mips = this.pot && this._mipmaps && !(this._compressed && this._levels.length === 1);\\n\\t\\t\\t\\treturn TextureUtils.calcGpuSize(this._width, this._height, this._depth, this._format, mips, this._cubemap);\\n\\t\\t}\\n\\t\\tget array() {\\n\\t\\t\\t\\treturn this._arrayLength > 0;\\n\\t\\t}\\n\\t\\tget arrayLength() {\\n\\t\\t\\t\\treturn this._arrayLength;\\n\\t\\t}\\n\\t\\tget volume() {\\n\\t\\t\\t\\treturn this._volume;\\n\\t\\t}\\n\\t\\tset type(value) {\\n\\t\\t\\t\\tif (this._type !== value) {\\n\\t\\t\\t\\t\\t\\tthis._type = value;\\n\\t\\t\\t\\t\\t\\tthis.device._shadersDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget type() {\\n\\t\\t\\t\\treturn this._type;\\n\\t\\t}\\n\\t\\tset srgb(value) {\\n\\t\\t\\t\\tconst currentSrgb = isSrgbPixelFormat(this.format);\\n\\t\\t\\t\\tif (value !== currentSrgb) {\\n\\t\\t\\t\\t\\t\\tif (value) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst srgbFormat = pixelFormatLinearToGamma(this.format);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._format !== srgbFormat) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._format = srgbFormat;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.recreateImpl();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.device._shadersDirty = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst linearFormat = pixelFormatGammaToLinear(this.format);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._format !== linearFormat) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._format = linearFormat;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.recreateImpl();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.device._shadersDirty = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget srgb() {\\n\\t\\t\\t\\treturn isSrgbPixelFormat(this.format);\\n\\t\\t}\\n\\t\\tset flipY(flipY) {\\n\\t\\t\\t\\tif (this._flipY !== flipY) {\\n\\t\\t\\t\\t\\t\\tthis._flipY = flipY;\\n\\t\\t\\t\\t\\t\\tthis.markForUpload();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget flipY() {\\n\\t\\t\\t\\treturn this._flipY;\\n\\t\\t}\\n\\t\\tset premultiplyAlpha(premultiplyAlpha) {\\n\\t\\t\\t\\tif (this._premultiplyAlpha !== premultiplyAlpha) {\\n\\t\\t\\t\\t\\t\\tthis._premultiplyAlpha = premultiplyAlpha;\\n\\t\\t\\t\\t\\t\\tthis.markForUpload();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget premultiplyAlpha() {\\n\\t\\t\\t\\treturn this._premultiplyAlpha;\\n\\t\\t}\\n\\t\\tget pot() {\\n\\t\\t\\t\\treturn math.powerOfTwo(this._width) && math.powerOfTwo(this._height);\\n\\t\\t}\\n\\t\\tget encoding() {\\n\\t\\t\\t\\tswitch(this.type){\\n\\t\\t\\t\\t\\t\\tcase TEXTURETYPE_RGBM:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 'rgbm';\\n\\t\\t\\t\\t\\t\\tcase TEXTURETYPE_RGBE:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 'rgbe';\\n\\t\\t\\t\\t\\t\\tcase TEXTURETYPE_RGBP:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 'rgbp';\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn requiresManualGamma(this.format) ? 'srgb' : 'linear';\\n\\t\\t}\\n\\t\\tdirtyAll() {\\n\\t\\t\\t\\tthis._levelsUpdated = this._cubemap ? [\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\ttrue,\\n\\t\\t\\t\\t\\t\\t\\t\\ttrue,\\n\\t\\t\\t\\t\\t\\t\\t\\ttrue,\\n\\t\\t\\t\\t\\t\\t\\t\\ttrue,\\n\\t\\t\\t\\t\\t\\t\\t\\ttrue,\\n\\t\\t\\t\\t\\t\\t\\t\\ttrue\\n\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t] : [\\n\\t\\t\\t\\t\\t\\ttrue\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.markForUpload();\\n\\t\\t\\t\\tthis._needsMipmapsUpload = this._mipmaps;\\n\\t\\t\\t\\tthis._mipmapsUploaded = false;\\n\\t\\t\\t\\tthis.propertyChanged(TEXPROPERTY_ALL);\\n\\t\\t}\\n\\t\\tlock(options = {}) {\\n\\t\\t\\t\\tvar _options, _options1, _options2;\\n\\t\\t\\t\\t(_options = options).level ?? (_options.level = 0);\\n\\t\\t\\t\\t(_options1 = options).face ?? (_options1.face = 0);\\n\\t\\t\\t\\t(_options2 = options).mode ?? (_options2.mode = TEXTURELOCK_WRITE);\\n\\t\\t\\t\\tthis._lockedMode = options.mode;\\n\\t\\t\\t\\tthis._lockedLevel = options.level;\\n\\t\\t\\t\\tconst levels = this.cubemap ? this._levels[options.face] : this._levels;\\n\\t\\t\\t\\tif (levels[options.level] === null) {\\n\\t\\t\\t\\t\\t\\tconst width = Math.max(1, this._width >> options.level);\\n\\t\\t\\t\\t\\t\\tconst height = Math.max(1, this._height >> options.level);\\n\\t\\t\\t\\t\\t\\tconst depth = Math.max(1, this._depth >> options.level);\\n\\t\\t\\t\\t\\t\\tconst data = new ArrayBuffer(TextureUtils.calcLevelGpuSize(width, height, depth, this._format));\\n\\t\\t\\t\\t\\t\\tlevels[options.level] = new (getPixelFormatArrayType(this._format))(data);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn levels[options.level];\\n\\t\\t}\\n\\t\\tsetSource(source, mipLevel = 0) {\\n\\t\\t\\t\\tlet invalid = false;\\n\\t\\t\\t\\tlet width, height;\\n\\t\\t\\t\\tif (this._cubemap) {\\n\\t\\t\\t\\t\\t\\tif (source[0]) {\\n\\t\\t\\t\\t\\t\\t\\t\\twidth = source[0].width || 0;\\n\\t\\t\\t\\t\\t\\t\\t\\theight = source[0].height || 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < 6; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst face = source[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!face || face.width !== width || face.height !== height || !this.device._isBrowserInterface(face)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinvalid = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\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} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tinvalid = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!invalid) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < 6; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this._levels[mipLevel][i] !== source[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._levelsUpdated[mipLevel][i] = true;\\n\\t\\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}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (!this.device._isBrowserInterface(source)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tinvalid = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!invalid) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (source !== this._levels[mipLevel]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._levelsUpdated[mipLevel] = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (source instanceof HTMLVideoElement) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twidth = source.videoWidth;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\theight = source.videoHeight;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twidth = source.width;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\theight = source.height;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (invalid) {\\n\\t\\t\\t\\t\\t\\tthis._width = 4;\\n\\t\\t\\t\\t\\t\\tthis._height = 4;\\n\\t\\t\\t\\t\\t\\tif (this._cubemap) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < 6; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._levels[mipLevel][i] = null;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._levelsUpdated[mipLevel][i] = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._levels[mipLevel] = null;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._levelsUpdated[mipLevel] = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (mipLevel === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._width = width;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._height = height;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._levels[mipLevel] = source;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._invalid !== invalid || !invalid) {\\n\\t\\t\\t\\t\\t\\tthis._invalid = invalid;\\n\\t\\t\\t\\t\\t\\tthis.upload();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetSource(mipLevel = 0) {\\n\\t\\t\\t\\treturn this._levels[mipLevel];\\n\\t\\t}\\n\\t\\tunlock() {\\n\\t\\t\\t\\tif (this._lockedMode === TEXTURELOCK_NONE) ;\\n\\t\\t\\t\\tif (this._lockedMode === TEXTURELOCK_WRITE) {\\n\\t\\t\\t\\t\\t\\tthis.upload();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._lockedLevel = -1;\\n\\t\\t\\t\\tthis._lockedMode = TEXTURELOCK_NONE;\\n\\t\\t}\\n\\t\\tmarkForUpload() {\\n\\t\\t\\t\\tthis._needsUpload = true;\\n\\t\\t\\t\\tthis.device?.texturesToUpload?.add(this);\\n\\t\\t}\\n\\t\\tupload() {\\n\\t\\t\\t\\tthis.markForUpload();\\n\\t\\t\\t\\tthis._needsMipmapsUpload = this._mipmaps;\\n\\t\\t\\t\\tthis.impl.uploadImmediate?.(this.device, this);\\n\\t\\t}\\n\\t\\tread(x, y, width, height, options = {}) {\\n\\t\\t\\t\\treturn this.impl.read?.(x, y, width, height, options);\\n\\t\\t}\\n\\t\\twrite(x, y, width, height, data) {\\n\\t\\t\\t\\treturn this.impl.write?.(x, y, width, height, data);\\n\\t\\t}\\n\\t\\tgetView(baseMipLevel = 0, mipLevelCount = 1, baseArrayLayer = 0, arrayLayerCount = 1) {\\n\\t\\t\\t\\treturn new TextureView(this, baseMipLevel, mipLevelCount, baseArrayLayer, arrayLayerCount);\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice, options = {}){\\n\\t\\t\\t\\tthis._gpuSize = 0;\\n\\t\\t\\t\\tthis.id = id$b++;\\n\\t\\t\\t\\tthis._invalid = false;\\n\\t\\t\\t\\tthis._lockedLevel = -1;\\n\\t\\t\\t\\tthis._lockedMode = TEXTURELOCK_NONE;\\n\\t\\t\\t\\tthis.renderVersionDirty = 0;\\n\\t\\t\\t\\tthis._storage = false;\\n\\t\\t\\t\\tthis._numLevels = 0;\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t\\t\\tthis.name = options.name ?? '';\\n\\t\\t\\t\\tthis._width = Math.floor(options.width ?? 4);\\n\\t\\t\\t\\tthis._height = Math.floor(options.height ?? 4);\\n\\t\\t\\t\\tthis._format = options.format ?? PIXELFORMAT_RGBA8;\\n\\t\\t\\t\\tthis._compressed = isCompressedPixelFormat(this._format);\\n\\t\\t\\t\\tthis._integerFormat = isIntegerPixelFormat(this._format);\\n\\t\\t\\t\\tif (this._integerFormat) {\\n\\t\\t\\t\\t\\t\\toptions.minFilter = FILTER_NEAREST;\\n\\t\\t\\t\\t\\t\\toptions.magFilter = FILTER_NEAREST;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._volume = options.volume ?? false;\\n\\t\\t\\t\\tthis._depth = Math.floor(options.depth ?? 1);\\n\\t\\t\\t\\tthis._arrayLength = Math.floor(options.arrayLength ?? 0);\\n\\t\\t\\t\\tthis._storage = options.storage ?? false;\\n\\t\\t\\t\\tthis._cubemap = options.cubemap ?? false;\\n\\t\\t\\t\\tthis._flipY = options.flipY ?? false;\\n\\t\\t\\t\\tthis._premultiplyAlpha = options.premultiplyAlpha ?? false;\\n\\t\\t\\t\\tthis._mipmaps = options.mipmaps ?? true;\\n\\t\\t\\t\\tthis._numLevelsRequested = options.numLevels;\\n\\t\\t\\t\\tif (options.numLevels !== undefined) {\\n\\t\\t\\t\\t\\t\\tthis._numLevels = options.numLevels;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._updateNumLevel();\\n\\t\\t\\t\\tthis._minFilter = options.minFilter ?? FILTER_LINEAR_MIPMAP_LINEAR;\\n\\t\\t\\t\\tthis._magFilter = options.magFilter ?? FILTER_LINEAR;\\n\\t\\t\\t\\tthis._anisotropy = options.anisotropy ?? 1;\\n\\t\\t\\t\\tthis._addressU = options.addressU ?? ADDRESS_REPEAT;\\n\\t\\t\\t\\tthis._addressV = options.addressV ?? ADDRESS_REPEAT;\\n\\t\\t\\t\\tthis._addressW = options.addressW ?? ADDRESS_REPEAT;\\n\\t\\t\\t\\tthis._compareOnRead = options.compareOnRead ?? false;\\n\\t\\t\\t\\tthis._compareFunc = options.compareFunc ?? FUNC_LESS;\\n\\t\\t\\t\\tthis._type = options.type ?? TEXTURETYPE_DEFAULT;\\n\\t\\t\\t\\tthis.projection = TEXTUREPROJECTION_NONE;\\n\\t\\t\\t\\tif (this._cubemap) {\\n\\t\\t\\t\\t\\t\\tthis.projection = TEXTUREPROJECTION_CUBE;\\n\\t\\t\\t\\t} else if (options.projection && options.projection !== TEXTUREPROJECTION_CUBE) {\\n\\t\\t\\t\\t\\t\\tthis.projection = options.projection;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._levels = options.levels;\\n\\t\\t\\t\\tconst upload = !!options.levels;\\n\\t\\t\\t\\tif (!this._levels) {\\n\\t\\t\\t\\t\\t\\tthis._clearLevels();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.recreateImpl(upload);\\n\\t\\t}\\n}\\n\\nconst textureData = {\\n\\t\\twhite: [\\n\\t\\t\\t\\t255,\\n\\t\\t\\t\\t255,\\n\\t\\t\\t\\t255,\\n\\t\\t\\t\\t255\\n\\t\\t],\\n\\t\\tgray: [\\n\\t\\t\\t\\t128,\\n\\t\\t\\t\\t128,\\n\\t\\t\\t\\t128,\\n\\t\\t\\t\\t255\\n\\t\\t],\\n\\t\\tblack: [\\n\\t\\t\\t\\t0,\\n\\t\\t\\t\\t0,\\n\\t\\t\\t\\t0,\\n\\t\\t\\t\\t255\\n\\t\\t],\\n\\t\\tnormal: [\\n\\t\\t\\t\\t128,\\n\\t\\t\\t\\t128,\\n\\t\\t\\t\\t255,\\n\\t\\t\\t\\t255\\n\\t\\t],\\n\\t\\tpink: [\\n\\t\\t\\t\\t255,\\n\\t\\t\\t\\t128,\\n\\t\\t\\t\\t255,\\n\\t\\t\\t\\t255\\n\\t\\t]\\n};\\nclass BuiltInTextures {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.map.forEach((texture)=>{\\n\\t\\t\\t\\t\\t\\ttexture.destroy();\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.map = new Map();\\n\\t\\t}\\n}\\nconst deviceCache$3 = new DeviceCache();\\nconst getBuiltInTexture = (device, name)=>{\\n\\t\\tconst cache = deviceCache$3.get(device, ()=>{\\n\\t\\t\\t\\treturn new BuiltInTextures();\\n\\t\\t});\\n\\t\\tif (!cache.map.has(name)) {\\n\\t\\t\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: `built-in-texture-${name}`,\\n\\t\\t\\t\\t\\t\\twidth: 1,\\n\\t\\t\\t\\t\\t\\theight: 1,\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA8\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst pixels = texture.lock();\\n\\t\\t\\t\\tconst data = textureData[name];\\n\\t\\t\\t\\tpixels.set(data);\\n\\t\\t\\t\\ttexture.unlock();\\n\\t\\t\\t\\tcache.map.set(name, texture);\\n\\t\\t}\\n\\t\\treturn cache.map.get(name);\\n};\\n\\nlet id$a = 0;\\nclass DynamicBindGroup {\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.offsets = [];\\n\\t\\t}\\n}\\nclass BindGroup {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.impl.destroy();\\n\\t\\t\\t\\tthis.impl = null;\\n\\t\\t\\t\\tthis.format = null;\\n\\t\\t\\t\\tthis.defaultUniformBuffer = null;\\n\\t\\t}\\n\\t\\tsetUniformBuffer(name, uniformBuffer) {\\n\\t\\t\\t\\tconst index = this.format.bufferFormatsMap.get(name);\\n\\t\\t\\t\\tif (this.uniformBuffers[index] !== uniformBuffer) {\\n\\t\\t\\t\\t\\t\\tthis.uniformBuffers[index] = uniformBuffer;\\n\\t\\t\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetStorageBuffer(name, storageBuffer) {\\n\\t\\t\\t\\tconst index = this.format.storageBufferFormatsMap.get(name);\\n\\t\\t\\t\\tif (this.storageBuffers[index] !== storageBuffer) {\\n\\t\\t\\t\\t\\t\\tthis.storageBuffers[index] = storageBuffer;\\n\\t\\t\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetTexture(name, value) {\\n\\t\\t\\t\\tconst index = this.format.textureFormatsMap.get(name);\\n\\t\\t\\t\\tconst texture = value instanceof TextureView ? value.texture : value;\\n\\t\\t\\t\\tif (this.textures[index] !== value) {\\n\\t\\t\\t\\t\\t\\tthis.textures[index] = value;\\n\\t\\t\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t\\t} else if (this.renderVersionUpdated < texture.renderVersionDirty) {\\n\\t\\t\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetStorageTexture(name, value) {\\n\\t\\t\\t\\tconst index = this.format.storageTextureFormatsMap.get(name);\\n\\t\\t\\t\\tconst texture = value instanceof TextureView ? value.texture : value;\\n\\t\\t\\t\\tif (this.storageTextures[index] !== value) {\\n\\t\\t\\t\\t\\t\\tthis.storageTextures[index] = value;\\n\\t\\t\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t\\t} else if (this.renderVersionUpdated < texture.renderVersionDirty) {\\n\\t\\t\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateUniformBuffers() {\\n\\t\\t\\t\\tfor(let i = 0; i < this.uniformBuffers.length; i++){\\n\\t\\t\\t\\t\\t\\tthis.uniformBuffers[i].update();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdate() {\\n\\t\\t\\t\\tconst { textureFormats, storageTextureFormats, storageBufferFormats } = this.format;\\n\\t\\t\\t\\tfor(let i = 0; i < textureFormats.length; i++){\\n\\t\\t\\t\\t\\t\\tconst textureFormat = textureFormats[i];\\n\\t\\t\\t\\t\\t\\tlet value = textureFormat.scopeId.value;\\n\\t\\t\\t\\t\\t\\tif (!value) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (textureFormat.name === 'uSceneDepthMap') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvalue = getBuiltInTexture(this.device, 'white');\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (textureFormat.name === 'uSceneColorMap') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvalue = getBuiltInTexture(this.device, 'pink');\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!value) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvalue = getBuiltInTexture(this.device, 'pink');\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.setTexture(textureFormat.name, value);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < storageTextureFormats.length; i++){\\n\\t\\t\\t\\t\\t\\tconst storageTextureFormat = storageTextureFormats[i];\\n\\t\\t\\t\\t\\t\\tconst value = storageTextureFormat.scopeId.value;\\n\\t\\t\\t\\t\\t\\tthis.setStorageTexture(storageTextureFormat.name, value);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < storageBufferFormats.length; i++){\\n\\t\\t\\t\\t\\t\\tconst storageBufferFormat = storageBufferFormats[i];\\n\\t\\t\\t\\t\\t\\tconst value = storageBufferFormat.scopeId.value;\\n\\t\\t\\t\\t\\t\\tthis.setStorageBuffer(storageBufferFormat.name, value);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.uniformBufferOffsets.length = this.uniformBuffers.length;\\n\\t\\t\\t\\tfor(let i = 0; i < this.uniformBuffers.length; i++){\\n\\t\\t\\t\\t\\t\\tconst uniformBuffer = this.uniformBuffers[i];\\n\\t\\t\\t\\t\\t\\tthis.uniformBufferOffsets[i] = uniformBuffer.offset;\\n\\t\\t\\t\\t\\t\\tif (this.renderVersionUpdated < uniformBuffer.renderVersionDirty) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.dirty) {\\n\\t\\t\\t\\t\\t\\tthis.dirty = false;\\n\\t\\t\\t\\t\\t\\tthis.renderVersionUpdated = this.device.renderVersion;\\n\\t\\t\\t\\t\\t\\tthis.impl.update(this);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice, format, defaultUniformBuffer){\\n\\t\\t\\t\\tthis.renderVersionUpdated = -1;\\n\\t\\t\\t\\tthis.uniformBufferOffsets = [];\\n\\t\\t\\t\\tthis.id = id$a++;\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t\\t\\tthis.format = format;\\n\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t\\tthis.impl = graphicsDevice.createBindGroupImpl(this);\\n\\t\\t\\t\\tthis.textures = [];\\n\\t\\t\\t\\tthis.storageTextures = [];\\n\\t\\t\\t\\tthis.storageBuffers = [];\\n\\t\\t\\t\\tthis.uniformBuffers = [];\\n\\t\\t\\t\\tthis.defaultUniformBuffer = defaultUniformBuffer;\\n\\t\\t\\t\\tif (defaultUniformBuffer) {\\n\\t\\t\\t\\t\\t\\tthis.setUniformBuffer(UNIFORM_BUFFER_DEFAULT_SLOT_NAME, defaultUniformBuffer);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nconst BitPacking = {\\n\\t\\tset (storage, value, shift, mask = 1) {\\n\\t\\t\\t\\tconst data = storage & ~(mask << shift);\\n\\t\\t\\t\\treturn data | value << shift;\\n\\t\\t},\\n\\t\\tget (storage, shift, mask = 1) {\\n\\t\\t\\t\\treturn storage >> shift & mask;\\n\\t\\t},\\n\\t\\tall (storage, shift, mask = 1) {\\n\\t\\t\\t\\tconst shifted = mask << shift;\\n\\t\\t\\t\\treturn (storage & shifted) === shifted;\\n\\t\\t},\\n\\t\\tany (storage, shift, mask = 1) {\\n\\t\\t\\t\\treturn (storage & mask << shift) !== 0;\\n\\t\\t}\\n};\\n\\nconst opMask = 0b111;\\nconst factorMask = 0b1111;\\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 = 0b1111;\\nconst allWriteShift = redWriteShift;\\nclass BlendState {\\n\\t\\tset blend(value) {\\n\\t\\t\\t\\tthis.target0 = BitPacking.set(this.target0, value ? 1 : 0, blendShift);\\n\\t\\t}\\n\\t\\tget blend() {\\n\\t\\t\\t\\treturn BitPacking.all(this.target0, blendShift);\\n\\t\\t}\\n\\t\\tsetColorBlend(op, srcFactor, dstFactor) {\\n\\t\\t\\t\\tthis.target0 = BitPacking.set(this.target0, op, colorOpShift, opMask);\\n\\t\\t\\t\\tthis.target0 = BitPacking.set(this.target0, srcFactor, colorSrcFactorShift, factorMask);\\n\\t\\t\\t\\tthis.target0 = BitPacking.set(this.target0, dstFactor, colorDstFactorShift, factorMask);\\n\\t\\t}\\n\\t\\tsetAlphaBlend(op, srcFactor, dstFactor) {\\n\\t\\t\\t\\tthis.target0 = BitPacking.set(this.target0, op, alphaOpShift, opMask);\\n\\t\\t\\t\\tthis.target0 = BitPacking.set(this.target0, srcFactor, alphaSrcFactorShift, factorMask);\\n\\t\\t\\t\\tthis.target0 = BitPacking.set(this.target0, dstFactor, alphaDstFactorShift, factorMask);\\n\\t\\t}\\n\\t\\tsetColorWrite(redWrite, greenWrite, blueWrite, alphaWrite) {\\n\\t\\t\\t\\tthis.redWrite = redWrite;\\n\\t\\t\\t\\tthis.greenWrite = greenWrite;\\n\\t\\t\\t\\tthis.blueWrite = blueWrite;\\n\\t\\t\\t\\tthis.alphaWrite = alphaWrite;\\n\\t\\t}\\n\\t\\tget colorOp() {\\n\\t\\t\\t\\treturn BitPacking.get(this.target0, colorOpShift, opMask);\\n\\t\\t}\\n\\t\\tget colorSrcFactor() {\\n\\t\\t\\t\\treturn BitPacking.get(this.target0, colorSrcFactorShift, factorMask);\\n\\t\\t}\\n\\t\\tget colorDstFactor() {\\n\\t\\t\\t\\treturn BitPacking.get(this.target0, colorDstFactorShift, factorMask);\\n\\t\\t}\\n\\t\\tget alphaOp() {\\n\\t\\t\\t\\treturn BitPacking.get(this.target0, alphaOpShift, opMask);\\n\\t\\t}\\n\\t\\tget alphaSrcFactor() {\\n\\t\\t\\t\\treturn BitPacking.get(this.target0, alphaSrcFactorShift, factorMask);\\n\\t\\t}\\n\\t\\tget alphaDstFactor() {\\n\\t\\t\\t\\treturn BitPacking.get(this.target0, alphaDstFactorShift, factorMask);\\n\\t\\t}\\n\\t\\tset redWrite(value) {\\n\\t\\t\\t\\tthis.target0 = BitPacking.set(this.target0, value ? 1 : 0, redWriteShift);\\n\\t\\t}\\n\\t\\tget redWrite() {\\n\\t\\t\\t\\treturn BitPacking.all(this.target0, redWriteShift);\\n\\t\\t}\\n\\t\\tset greenWrite(value) {\\n\\t\\t\\t\\tthis.target0 = BitPacking.set(this.target0, value ? 1 : 0, greenWriteShift);\\n\\t\\t}\\n\\t\\tget greenWrite() {\\n\\t\\t\\t\\treturn BitPacking.all(this.target0, greenWriteShift);\\n\\t\\t}\\n\\t\\tset blueWrite(value) {\\n\\t\\t\\t\\tthis.target0 = BitPacking.set(this.target0, value ? 1 : 0, blueWriteShift);\\n\\t\\t}\\n\\t\\tget blueWrite() {\\n\\t\\t\\t\\treturn BitPacking.all(this.target0, blueWriteShift);\\n\\t\\t}\\n\\t\\tset alphaWrite(value) {\\n\\t\\t\\t\\tthis.target0 = BitPacking.set(this.target0, value ? 1 : 0, alphaWriteShift);\\n\\t\\t}\\n\\t\\tget alphaWrite() {\\n\\t\\t\\t\\treturn BitPacking.all(this.target0, alphaWriteShift);\\n\\t\\t}\\n\\t\\tget allWrite() {\\n\\t\\t\\t\\treturn BitPacking.get(this.target0, allWriteShift, allWriteMasks);\\n\\t\\t}\\n\\t\\tcopy(rhs) {\\n\\t\\t\\t\\tthis.target0 = rhs.target0;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst clone = new this.constructor();\\n\\t\\t\\t\\treturn clone.copy(this);\\n\\t\\t}\\n\\t\\tget key() {\\n\\t\\t\\t\\treturn this.target0;\\n\\t\\t}\\n\\t\\tequals(rhs) {\\n\\t\\t\\t\\treturn this.target0 === rhs.target0;\\n\\t\\t}\\n\\t\\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\\t\\t\\tthis.target0 = 0;\\n\\t\\t\\t\\tthis.setColorBlend(colorOp, colorSrcFactor, colorDstFactor);\\n\\t\\t\\t\\tthis.setAlphaBlend(alphaOp ?? colorOp, alphaSrcFactor ?? colorSrcFactor, alphaDstFactor ?? colorDstFactor);\\n\\t\\t\\t\\tthis.setColorWrite(redWrite, greenWrite, blueWrite, alphaWrite);\\n\\t\\t\\t\\tthis.blend = blend;\\n\\t\\t}\\n}\\nBlendState.NOBLEND = Object.freeze(new BlendState());\\nBlendState.NOWRITE = Object.freeze(new BlendState(undefined, undefined, undefined, undefined, undefined, undefined, undefined, false, false, false, false));\\nBlendState.ALPHABLEND = Object.freeze(new BlendState(true, BLENDEQUATION_ADD, BLENDMODE_SRC_ALPHA, BLENDMODE_ONE_MINUS_SRC_ALPHA));\\nBlendState.ADDBLEND = Object.freeze(new BlendState(true, BLENDEQUATION_ADD, BLENDMODE_ONE, BLENDMODE_ONE));\\n\\nconst stringIds$4 = new StringIds();\\nconst funcMask = 0b111;\\nconst funcShift = 0;\\nconst writeShift = 3;\\nclass DepthState {\\n\\t\\tset test(value) {\\n\\t\\t\\t\\tthis.func = value ? FUNC_LESSEQUAL : FUNC_ALWAYS;\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t\\tget test() {\\n\\t\\t\\t\\treturn this.func !== FUNC_ALWAYS;\\n\\t\\t}\\n\\t\\tset write(value) {\\n\\t\\t\\t\\tthis.data = BitPacking.set(this.data, value ? 1 : 0, writeShift);\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t\\tget write() {\\n\\t\\t\\t\\treturn BitPacking.all(this.data, writeShift);\\n\\t\\t}\\n\\t\\tset func(value) {\\n\\t\\t\\t\\tthis.data = BitPacking.set(this.data, value, funcShift, funcMask);\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t\\tget func() {\\n\\t\\t\\t\\treturn BitPacking.get(this.data, funcShift, funcMask);\\n\\t\\t}\\n\\t\\tset depthBias(value) {\\n\\t\\t\\t\\tthis._depthBias = value;\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t\\tget depthBias() {\\n\\t\\t\\t\\treturn this._depthBias;\\n\\t\\t}\\n\\t\\tset depthBiasSlope(value) {\\n\\t\\t\\t\\tthis._depthBiasSlope = value;\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t\\tget depthBiasSlope() {\\n\\t\\t\\t\\treturn this._depthBiasSlope;\\n\\t\\t}\\n\\t\\tcopy(rhs) {\\n\\t\\t\\t\\tthis.data = rhs.data;\\n\\t\\t\\t\\tthis._depthBias = rhs._depthBias;\\n\\t\\t\\t\\tthis._depthBiasSlope = rhs._depthBiasSlope;\\n\\t\\t\\t\\tthis.key = rhs.key;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst clone = new this.constructor();\\n\\t\\t\\t\\treturn clone.copy(this);\\n\\t\\t}\\n\\t\\tupdateKey() {\\n\\t\\t\\t\\tconst { data, _depthBias, _depthBiasSlope } = this;\\n\\t\\t\\t\\tconst key = `${data}-${_depthBias}-${_depthBiasSlope}`;\\n\\t\\t\\t\\tthis.key = stringIds$4.get(key);\\n\\t\\t}\\n\\t\\tequals(rhs) {\\n\\t\\t\\t\\treturn this.key === rhs.key;\\n\\t\\t}\\n\\t\\tconstructor(func = FUNC_LESSEQUAL, write = true){\\n\\t\\t\\t\\tthis.data = 0;\\n\\t\\t\\t\\tthis._depthBias = 0;\\n\\t\\t\\t\\tthis._depthBiasSlope = 0;\\n\\t\\t\\t\\tthis.key = 0;\\n\\t\\t\\t\\tthis.func = func;\\n\\t\\t\\t\\tthis.write = write;\\n\\t\\t}\\n}\\nDepthState.DEFAULT = Object.freeze(new DepthState());\\nDepthState.NODEPTH = Object.freeze(new DepthState(FUNC_ALWAYS, false));\\nDepthState.WRITEDEPTH = Object.freeze(new DepthState(FUNC_ALWAYS, true));\\n\\nclass Version {\\n\\t\\tequals(other) {\\n\\t\\t\\t\\treturn this.globalId === other.globalId && this.revision === other.revision;\\n\\t\\t}\\n\\t\\tcopy(other) {\\n\\t\\t\\t\\tthis.globalId = other.globalId;\\n\\t\\t\\t\\tthis.revision = other.revision;\\n\\t\\t}\\n\\t\\treset() {\\n\\t\\t\\t\\tthis.globalId = 0;\\n\\t\\t\\t\\tthis.revision = 0;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.globalId = 0;\\n\\t\\t\\t\\tthis.revision = 0;\\n\\t\\t}\\n}\\n\\nlet idCounter = 0;\\nclass VersionedObject {\\n\\t\\tincrement() {\\n\\t\\t\\t\\tthis.version.revision++;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tidCounter++;\\n\\t\\t\\t\\tthis.version = new Version();\\n\\t\\t\\t\\tthis.version.globalId = idCounter;\\n\\t\\t}\\n}\\n\\nclass ScopeId {\\n\\t\\ttoJSON(key) {\\n\\t\\t\\t\\treturn undefined;\\n\\t\\t}\\n\\t\\tsetValue(value) {\\n\\t\\t\\t\\tthis.value = value;\\n\\t\\t\\t\\tthis.versionObject.increment();\\n\\t\\t}\\n\\t\\tgetValue() {\\n\\t\\t\\t\\treturn this.value;\\n\\t\\t}\\n\\t\\tconstructor(name){\\n\\t\\t\\t\\tthis.name = name;\\n\\t\\t\\t\\tthis.value = null;\\n\\t\\t\\t\\tthis.versionObject = new VersionedObject();\\n\\t\\t}\\n}\\n\\nclass ScopeSpace {\\n\\t\\tresolve(name) {\\n\\t\\t\\t\\tif (!this.variables.has(name)) {\\n\\t\\t\\t\\t\\t\\tthis.variables.set(name, new ScopeId(name));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.variables.get(name);\\n\\t\\t}\\n\\t\\tremoveValue(value) {\\n\\t\\t\\t\\tfor (const uniform of this.variables.values()){\\n\\t\\t\\t\\t\\t\\tif (uniform.value === value) {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniform.value = null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(name){\\n\\t\\t\\t\\tthis.name = name;\\n\\t\\t\\t\\tthis.variables = new Map();\\n\\t\\t}\\n}\\n\\nlet id$9 = 0;\\nclass VertexBuffer {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tdevice.buffers.delete(this);\\n\\t\\t\\t\\tif (this.impl.initialized) {\\n\\t\\t\\t\\t\\t\\tthis.impl.destroy(device);\\n\\t\\t\\t\\t\\t\\tthis.adjustVramSizeTracking(device._vram, -this.storage.byteLength);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tadjustVramSizeTracking(vram, size) {\\n\\t\\t\\t\\tvram.vb += size;\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tthis.impl.loseContext();\\n\\t\\t}\\n\\t\\tgetFormat() {\\n\\t\\t\\t\\treturn this.format;\\n\\t\\t}\\n\\t\\tgetUsage() {\\n\\t\\t\\t\\treturn this.usage;\\n\\t\\t}\\n\\t\\tgetNumVertices() {\\n\\t\\t\\t\\treturn this.numVertices;\\n\\t\\t}\\n\\t\\tlock() {\\n\\t\\t\\t\\treturn this.storage;\\n\\t\\t}\\n\\t\\tunlock() {\\n\\t\\t\\t\\tthis.impl.unlock(this);\\n\\t\\t}\\n\\t\\tsetData(data) {\\n\\t\\t\\t\\tif (data.byteLength !== this.numBytes) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.storage = data;\\n\\t\\t\\t\\tthis.unlock();\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice, format, numVertices, options){\\n\\t\\t\\t\\tthis.usage = BUFFER_STATIC;\\n\\t\\t\\t\\tthis.usage = options?.usage ?? BUFFER_STATIC;\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t\\t\\tthis.format = format;\\n\\t\\t\\t\\tthis.numVertices = numVertices;\\n\\t\\t\\t\\tthis.id = id$9++;\\n\\t\\t\\t\\tthis.impl = graphicsDevice.createVertexBufferImpl(this, format, options);\\n\\t\\t\\t\\tthis.numBytes = format.verticesByteSize ? format.verticesByteSize : format.size * numVertices;\\n\\t\\t\\t\\tthis.adjustVramSizeTracking(graphicsDevice._vram, this.numBytes);\\n\\t\\t\\t\\tconst initialData = options?.data;\\n\\t\\t\\t\\tif (initialData) {\\n\\t\\t\\t\\t\\t\\tthis.setData(initialData);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.storage = new ArrayBuffer(this.numBytes);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.device.buffers.add(this);\\n\\t\\t}\\n}\\n\\nfunction hashCode(str) {\\n\\t\\tif (str === null || str === undefined) {\\n\\t\\t\\t\\treturn 0;\\n\\t\\t}\\n\\t\\tlet hash = 0;\\n\\t\\tfor(let i = 0, len = str.length; i < len; i++){\\n\\t\\t\\t\\thash = (hash << 5) - hash + str.charCodeAt(i);\\n\\t\\t\\t\\thash |= 0;\\n\\t\\t}\\n\\t\\treturn hash;\\n}\\nfunction hash32Fnv1a(array) {\\n\\t\\tconst prime = 16777619;\\n\\t\\tlet hash = 2166136261;\\n\\t\\tfor(let i = 0; i < array.length; i++){\\n\\t\\t\\t\\thash ^= array[i];\\n\\t\\t\\t\\thash *= prime;\\n\\t\\t}\\n\\t\\treturn hash >>> 0;\\n}\\n\\nconst stringIds$3 = new StringIds();\\nconst webgpuValidElementSizes = [\\n\\t\\t2,\\n\\t\\t4,\\n\\t\\t8,\\n\\t\\t12,\\n\\t\\t16\\n];\\nconst deviceCache$2 = new DeviceCache();\\nclass VertexFormat {\\n\\t\\tget elements() {\\n\\t\\t\\t\\treturn this._elements;\\n\\t\\t}\\n\\t\\tstatic getDefaultInstancingFormat(graphicsDevice) {\\n\\t\\t\\t\\treturn deviceCache$2.get(graphicsDevice, ()=>{\\n\\t\\t\\t\\t\\t\\treturn new VertexFormat(graphicsDevice, [\\n\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsemantic: SEMANTIC_ATTR11,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcomponents: 4,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype: TYPE_FLOAT32\\n\\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\\t\\t\\tsemantic: SEMANTIC_ATTR12,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcomponents: 4,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype: TYPE_FLOAT32\\n\\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\\t\\t\\tsemantic: SEMANTIC_ATTR14,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcomponents: 4,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype: TYPE_FLOAT32\\n\\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\\t\\t\\tsemantic: SEMANTIC_ATTR15,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcomponents: 4,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype: TYPE_FLOAT32\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tstatic isElementValid(graphicsDevice, elementDesc) {\\n\\t\\t\\t\\tconst elementSize = elementDesc.components * typedArrayTypesByteSize[elementDesc.type];\\n\\t\\t\\t\\tif (graphicsDevice.isWebGPU && !webgpuValidElementSizes.includes(elementSize)) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tupdate() {\\n\\t\\t\\t\\tthis._evaluateHash();\\n\\t\\t}\\n\\t\\t_evaluateHash() {\\n\\t\\t\\t\\tconst stringElementsBatch = [];\\n\\t\\t\\t\\tconst stringElementsRender = [];\\n\\t\\t\\t\\tconst len = this._elements.length;\\n\\t\\t\\t\\tfor(let i = 0; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst { name, dataType, numComponents, normalize, offset, stride, size, asInt } = this._elements[i];\\n\\t\\t\\t\\t\\t\\tconst stringElementBatch = name + dataType + numComponents + normalize + asInt;\\n\\t\\t\\t\\t\\t\\tstringElementsBatch.push(stringElementBatch);\\n\\t\\t\\t\\t\\t\\tconst stringElementRender = stringElementBatch + offset + stride + size;\\n\\t\\t\\t\\t\\t\\tstringElementsRender.push(stringElementRender);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tstringElementsBatch.sort();\\n\\t\\t\\t\\tconst batchingString = stringElementsBatch.join();\\n\\t\\t\\t\\tthis.batchingHash = hashCode(batchingString);\\n\\t\\t\\t\\tthis.shaderProcessingHashString = batchingString;\\n\\t\\t\\t\\tthis.renderingHashString = stringElementsRender.join('_');\\n\\t\\t\\t\\tthis.renderingHash = stringIds$3.get(this.renderingHashString);\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice, description, vertexCount){\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t\\t\\tthis._elements = [];\\n\\t\\t\\t\\tthis.hasUv0 = false;\\n\\t\\t\\t\\tthis.hasUv1 = false;\\n\\t\\t\\t\\tthis.hasColor = false;\\n\\t\\t\\t\\tthis.hasTangents = false;\\n\\t\\t\\t\\tthis.verticesByteSize = 0;\\n\\t\\t\\t\\tthis.vertexCount = vertexCount;\\n\\t\\t\\t\\tthis.interleaved = vertexCount === undefined;\\n\\t\\t\\t\\tthis.instancing = false;\\n\\t\\t\\t\\tthis.size = description.reduce((total, desc)=>{\\n\\t\\t\\t\\t\\t\\treturn total + Math.ceil(desc.components * typedArrayTypesByteSize[desc.type] / 4) * 4;\\n\\t\\t\\t\\t}, 0);\\n\\t\\t\\t\\tlet offset = 0, elementSize;\\n\\t\\t\\t\\tfor(let i = 0, len = description.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst elementDesc = description[i];\\n\\t\\t\\t\\t\\t\\telementSize = elementDesc.components * typedArrayTypesByteSize[elementDesc.type];\\n\\t\\t\\t\\t\\t\\tif (vertexCount) {\\n\\t\\t\\t\\t\\t\\t\\t\\toffset = math.roundUp(offset, elementSize);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst asInt = elementDesc.asInt ?? false;\\n\\t\\t\\t\\t\\t\\tconst normalize = asInt ? false : elementDesc.normalize ?? false;\\n\\t\\t\\t\\t\\t\\tconst element = {\\n\\t\\t\\t\\t\\t\\t\\t\\tname: elementDesc.semantic,\\n\\t\\t\\t\\t\\t\\t\\t\\toffset: vertexCount ? offset : elementDesc.hasOwnProperty('offset') ? elementDesc.offset : offset,\\n\\t\\t\\t\\t\\t\\t\\t\\tstride: vertexCount ? elementSize : elementDesc.hasOwnProperty('stride') ? elementDesc.stride : this.size,\\n\\t\\t\\t\\t\\t\\t\\t\\tdataType: elementDesc.type,\\n\\t\\t\\t\\t\\t\\t\\t\\tnumComponents: elementDesc.components,\\n\\t\\t\\t\\t\\t\\t\\t\\tnormalize: normalize,\\n\\t\\t\\t\\t\\t\\t\\t\\tsize: elementSize,\\n\\t\\t\\t\\t\\t\\t\\t\\tasInt: asInt\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tthis._elements.push(element);\\n\\t\\t\\t\\t\\t\\tif (vertexCount) {\\n\\t\\t\\t\\t\\t\\t\\t\\toffset += elementSize * vertexCount;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\toffset += Math.ceil(elementSize / 4) * 4;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (elementDesc.semantic === SEMANTIC_TEXCOORD0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.hasUv0 = true;\\n\\t\\t\\t\\t\\t\\t} else if (elementDesc.semantic === SEMANTIC_TEXCOORD1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.hasUv1 = true;\\n\\t\\t\\t\\t\\t\\t} else if (elementDesc.semantic === SEMANTIC_COLOR) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.hasColor = true;\\n\\t\\t\\t\\t\\t\\t} else if (elementDesc.semantic === SEMANTIC_TANGENT) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.hasTangents = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (vertexCount) {\\n\\t\\t\\t\\t\\t\\tthis.verticesByteSize = offset;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._evaluateHash();\\n\\t\\t}\\n}\\n\\nconst stringIds$2 = new StringIds();\\nclass StencilParameters {\\n\\t\\tset func(value) {\\n\\t\\t\\t\\tthis._func = value;\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t}\\n\\t\\tget func() {\\n\\t\\t\\t\\treturn this._func;\\n\\t\\t}\\n\\t\\tset ref(value) {\\n\\t\\t\\t\\tthis._ref = value;\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t}\\n\\t\\tget ref() {\\n\\t\\t\\t\\treturn this._ref;\\n\\t\\t}\\n\\t\\tset fail(value) {\\n\\t\\t\\t\\tthis._fail = value;\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t}\\n\\t\\tget fail() {\\n\\t\\t\\t\\treturn this._fail;\\n\\t\\t}\\n\\t\\tset zfail(value) {\\n\\t\\t\\t\\tthis._zfail = value;\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t}\\n\\t\\tget zfail() {\\n\\t\\t\\t\\treturn this._zfail;\\n\\t\\t}\\n\\t\\tset zpass(value) {\\n\\t\\t\\t\\tthis._zpass = value;\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t}\\n\\t\\tget zpass() {\\n\\t\\t\\t\\treturn this._zpass;\\n\\t\\t}\\n\\t\\tset readMask(value) {\\n\\t\\t\\t\\tthis._readMask = value;\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t}\\n\\t\\tget readMask() {\\n\\t\\t\\t\\treturn this._readMask;\\n\\t\\t}\\n\\t\\tset writeMask(value) {\\n\\t\\t\\t\\tthis._writeMask = value;\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t}\\n\\t\\tget writeMask() {\\n\\t\\t\\t\\treturn this._writeMask;\\n\\t\\t}\\n\\t\\t_evalKey() {\\n\\t\\t\\t\\tconst { _func, _ref, _fail, _zfail, _zpass, _readMask, _writeMask } = this;\\n\\t\\t\\t\\tconst key = `${_func},${_ref},${_fail},${_zfail},${_zpass},${_readMask},${_writeMask}`;\\n\\t\\t\\t\\tthis._key = stringIds$2.get(key);\\n\\t\\t\\t\\tthis._dirty = false;\\n\\t\\t}\\n\\t\\tget key() {\\n\\t\\t\\t\\tif (this._dirty) {\\n\\t\\t\\t\\t\\t\\tthis._evalKey();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._key;\\n\\t\\t}\\n\\t\\tcopy(rhs) {\\n\\t\\t\\t\\tthis._func = rhs._func;\\n\\t\\t\\t\\tthis._ref = rhs._ref;\\n\\t\\t\\t\\tthis._readMask = rhs._readMask;\\n\\t\\t\\t\\tthis._writeMask = rhs._writeMask;\\n\\t\\t\\t\\tthis._fail = rhs._fail;\\n\\t\\t\\t\\tthis._zfail = rhs._zfail;\\n\\t\\t\\t\\tthis._zpass = rhs._zpass;\\n\\t\\t\\t\\tthis._dirty = rhs._dirty;\\n\\t\\t\\t\\tthis._key = rhs._key;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst clone = new this.constructor();\\n\\t\\t\\t\\treturn clone.copy(this);\\n\\t\\t}\\n\\t\\tconstructor(options = {}){\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t\\t\\tthis._func = options.func ?? FUNC_ALWAYS;\\n\\t\\t\\t\\tthis._ref = options.ref ?? 0;\\n\\t\\t\\t\\tthis._readMask = options.readMask ?? 0xFF;\\n\\t\\t\\t\\tthis._writeMask = options.writeMask ?? 0xFF;\\n\\t\\t\\t\\tthis._fail = options.fail ?? STENCILOP_KEEP;\\n\\t\\t\\t\\tthis._zfail = options.zfail ?? STENCILOP_KEEP;\\n\\t\\t\\t\\tthis._zpass = options.zpass ?? STENCILOP_KEEP;\\n\\t\\t\\t\\tthis._evalKey();\\n\\t\\t}\\n}\\nStencilParameters.DEFAULT = Object.freeze(new StencilParameters());\\n\\nclass GraphicsDevice extends EventHandler {\\n\\t\\tpostInit() {\\n\\t\\t\\t\\tconst vertexFormat = new VertexFormat(this, [\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tsemantic: SEMANTIC_POSITION,\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponents: 2,\\n\\t\\t\\t\\t\\t\\t\\t\\ttype: TYPE_FLOAT32\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tconst positions = new Float32Array([\\n\\t\\t\\t\\t\\t\\t-1,\\n\\t\\t\\t\\t\\t\\t-1,\\n\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t-1,\\n\\t\\t\\t\\t\\t\\t-1,\\n\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t1\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tthis.quadVertexBuffer = new VertexBuffer(this, vertexFormat, 4, {\\n\\t\\t\\t\\t\\t\\tdata: positions\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tinitCapsDefines() {\\n\\t\\t\\t\\tconst { capsDefines } = this;\\n\\t\\t\\t\\tcapsDefines.clear();\\n\\t\\t\\t\\tif (this.textureFloatFilterable) capsDefines.set('CAPS_TEXTURE_FLOAT_FILTERABLE', '');\\n\\t\\t\\t\\tif (this.textureFloatRenderable) capsDefines.set('CAPS_TEXTURE_FLOAT_RENDERABLE', '');\\n\\t\\t\\t\\tif (this.supportsMultiDraw) capsDefines.set('CAPS_MULTI_DRAW', '');\\n\\t\\t\\t\\tif (this.supportsPrimitiveIndex) capsDefines.set('CAPS_PRIMITIVE_INDEX', '');\\n\\t\\t\\t\\tif (platform.desktop) capsDefines.set('PLATFORM_DESKTOP', '');\\n\\t\\t\\t\\tif (platform.mobile) capsDefines.set('PLATFORM_MOBILE', '');\\n\\t\\t\\t\\tif (platform.android) capsDefines.set('PLATFORM_ANDROID', '');\\n\\t\\t\\t\\tif (platform.ios) capsDefines.set('PLATFORM_IOS', '');\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.fire('destroy');\\n\\t\\t\\t\\tthis.quadVertexBuffer?.destroy();\\n\\t\\t\\t\\tthis.quadVertexBuffer = null;\\n\\t\\t\\t\\tthis.dynamicBuffers?.destroy();\\n\\t\\t\\t\\tthis.dynamicBuffers = null;\\n\\t\\t\\t\\tthis.gpuProfiler?.destroy();\\n\\t\\t\\t\\tthis.gpuProfiler = null;\\n\\t\\t\\t\\tthis._destroyed = true;\\n\\t\\t}\\n\\t\\tonDestroyShader(shader) {\\n\\t\\t\\t\\tthis.fire('destroy:shader', shader);\\n\\t\\t\\t\\tconst idx = this.shaders.indexOf(shader);\\n\\t\\t\\t\\tif (idx !== -1) {\\n\\t\\t\\t\\t\\t\\tthis.shaders.splice(idx, 1);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonTextureDestroyed(texture) {\\n\\t\\t\\t\\tthis.textures.delete(texture);\\n\\t\\t\\t\\tthis.texturesToUpload.delete(texture);\\n\\t\\t\\t\\tthis.scope.removeValue(texture);\\n\\t\\t}\\n\\t\\tpostDestroy() {\\n\\t\\t\\t\\tthis.scope = null;\\n\\t\\t\\t\\tthis.canvas = null;\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tthis.contextLost = true;\\n\\t\\t\\t\\tthis.backBufferSize.set(-1, -1);\\n\\t\\t\\t\\tfor (const texture of this.textures){\\n\\t\\t\\t\\t\\t\\ttexture.loseContext();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const buffer of this.buffers){\\n\\t\\t\\t\\t\\t\\tbuffer.loseContext();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const target of this.targets){\\n\\t\\t\\t\\t\\t\\ttarget.loseContext();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.gpuProfiler?.loseContext();\\n\\t\\t}\\n\\t\\trestoreContext() {\\n\\t\\t\\t\\tthis.contextLost = false;\\n\\t\\t\\t\\tthis.initializeRenderState();\\n\\t\\t\\t\\tthis.initializeContextCaches();\\n\\t\\t\\t\\tfor (const buffer of this.buffers){\\n\\t\\t\\t\\t\\t\\tbuffer.unlock();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.gpuProfiler?.restoreContext?.();\\n\\t\\t}\\n\\t\\ttoJSON(key) {\\n\\t\\t\\t\\treturn undefined;\\n\\t\\t}\\n\\t\\tinitializeContextCaches() {\\n\\t\\t\\t\\tthis.vertexBuffers = [];\\n\\t\\t\\t\\tthis.shader = null;\\n\\t\\t\\t\\tthis.shaderValid = undefined;\\n\\t\\t\\t\\tthis.shaderAsyncCompile = false;\\n\\t\\t\\t\\tthis.renderTarget = null;\\n\\t\\t}\\n\\t\\tinitializeRenderState() {\\n\\t\\t\\t\\tthis.blendState = new BlendState();\\n\\t\\t\\t\\tthis.depthState = new DepthState();\\n\\t\\t\\t\\tthis.cullMode = CULLFACE_BACK;\\n\\t\\t\\t\\tthis.vx = this.vy = this.vw = this.vh = 0;\\n\\t\\t\\t\\tthis.sx = this.sy = this.sw = this.sh = 0;\\n\\t\\t\\t\\tthis.blendColor = new Color(0, 0, 0, 0);\\n\\t\\t}\\n\\t\\tsetStencilState(stencilFront, stencilBack) {}\\n\\t\\tsetBlendState(blendState) {}\\n\\t\\tsetBlendColor(r, g, b, a) {}\\n\\t\\tsetDepthState(depthState) {}\\n\\t\\tsetCullMode(cullMode) {}\\n\\t\\tsetRenderTarget(renderTarget) {\\n\\t\\t\\t\\tthis.renderTarget = renderTarget;\\n\\t\\t}\\n\\t\\tsetVertexBuffer(vertexBuffer) {\\n\\t\\t\\t\\tif (vertexBuffer) {\\n\\t\\t\\t\\t\\t\\tthis.vertexBuffers.push(vertexBuffer);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tclearVertexBuffer() {\\n\\t\\t\\t\\tthis.vertexBuffers.length = 0;\\n\\t\\t}\\n\\t\\tgetIndirectDrawSlot(count = 1) {\\n\\t\\t\\t\\treturn 0;\\n\\t\\t}\\n\\t\\tget indirectDrawBuffer() {\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tgetIndirectDispatchSlot(count = 1) {\\n\\t\\t\\t\\treturn 0;\\n\\t\\t}\\n\\t\\tget indirectDispatchBuffer() {\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tgetRenderTarget() {\\n\\t\\t\\t\\treturn this.renderTarget;\\n\\t\\t}\\n\\t\\tinitRenderTarget(target) {\\n\\t\\t\\t\\tif (target.initialized) return;\\n\\t\\t\\t\\ttarget.init();\\n\\t\\t\\t\\tthis.targets.add(target);\\n\\t\\t}\\n\\t\\tdraw(primitive, indexBuffer, numInstances, drawCommands, first = true, last = true) {}\\n\\t\\t_isBrowserInterface(texture) {\\n\\t\\t\\t\\treturn this._isImageBrowserInterface(texture) || this._isImageCanvasInterface(texture) || this._isImageVideoInterface(texture);\\n\\t\\t}\\n\\t\\t_isImageBrowserInterface(texture) {\\n\\t\\t\\t\\treturn typeof ImageBitmap !== 'undefined' && texture instanceof ImageBitmap || typeof HTMLImageElement !== 'undefined' && texture instanceof HTMLImageElement;\\n\\t\\t}\\n\\t\\t_isImageCanvasInterface(texture) {\\n\\t\\t\\t\\treturn typeof HTMLCanvasElement !== 'undefined' && texture instanceof HTMLCanvasElement;\\n\\t\\t}\\n\\t\\t_isImageVideoInterface(texture) {\\n\\t\\t\\t\\treturn typeof HTMLVideoElement !== 'undefined' && texture instanceof HTMLVideoElement;\\n\\t\\t}\\n\\t\\tresizeCanvas(width, height) {\\n\\t\\t\\t\\tconst pixelRatio = Math.min(this._maxPixelRatio, platform.browser ? window.devicePixelRatio : 1);\\n\\t\\t\\t\\tconst w = Math.floor(width * pixelRatio);\\n\\t\\t\\t\\tconst h = Math.floor(height * pixelRatio);\\n\\t\\t\\t\\tif (w !== this.canvas.width || h !== this.canvas.height) {\\n\\t\\t\\t\\t\\t\\tthis.setResolution(w, h);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetResolution(width, height) {\\n\\t\\t\\t\\tthis.canvas.width = width;\\n\\t\\t\\t\\tthis.canvas.height = height;\\n\\t\\t\\t\\tthis.fire(GraphicsDevice.EVENT_RESIZE, width, height);\\n\\t\\t}\\n\\t\\tupdate() {\\n\\t\\t\\t\\tthis.updateClientRect();\\n\\t\\t}\\n\\t\\tupdateClientRect() {\\n\\t\\t\\t\\tif (platform.worker) {\\n\\t\\t\\t\\t\\t\\tthis.clientRect.width = this.canvas.width;\\n\\t\\t\\t\\t\\t\\tthis.clientRect.height = this.canvas.height;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst rect = this.canvas.getBoundingClientRect();\\n\\t\\t\\t\\t\\t\\tthis.clientRect.width = rect.width;\\n\\t\\t\\t\\t\\t\\tthis.clientRect.height = rect.height;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget width() {\\n\\t\\t\\t\\treturn this.canvas.width;\\n\\t\\t}\\n\\t\\tget height() {\\n\\t\\t\\t\\treturn this.canvas.height;\\n\\t\\t}\\n\\t\\tset fullscreen(fullscreen) {}\\n\\t\\tget fullscreen() {\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tset maxPixelRatio(ratio) {\\n\\t\\t\\t\\tthis._maxPixelRatio = ratio;\\n\\t\\t}\\n\\t\\tget maxPixelRatio() {\\n\\t\\t\\t\\treturn this._maxPixelRatio;\\n\\t\\t}\\n\\t\\tget deviceType() {\\n\\t\\t\\t\\treturn this._deviceType;\\n\\t\\t}\\n\\t\\tstartRenderPass(renderPass) {}\\n\\t\\tendRenderPass(renderPass) {}\\n\\t\\tstartComputePass(name) {}\\n\\t\\tendComputePass() {}\\n\\t\\tframeStart() {\\n\\t\\t\\t\\tthis.renderPassIndex = 0;\\n\\t\\t\\t\\tthis.renderVersion++;\\n\\t\\t}\\n\\t\\tframeEnd() {\\n\\t\\t\\t\\tthis.mapsToClear.forEach((map)=>map.clear());\\n\\t\\t\\t\\tthis.mapsToClear.clear();\\n\\t\\t}\\n\\t\\tcomputeDispatch(computes, name = 'Unnamed') {}\\n\\t\\tgetRenderableHdrFormat(formats = [\\n\\t\\t\\t\\tPIXELFORMAT_111110F,\\n\\t\\t\\t\\tPIXELFORMAT_RGBA16F,\\n\\t\\t\\t\\tPIXELFORMAT_RGBA32F\\n\\t\\t], filterable = true, samples = 1) {\\n\\t\\t\\t\\tfor(let i = 0; i < formats.length; i++){\\n\\t\\t\\t\\t\\t\\tconst format = formats[i];\\n\\t\\t\\t\\t\\t\\tswitch(format){\\n\\t\\t\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_111110F:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this.textureRG11B10Renderable) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn format;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGBA16F:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this.textureHalfFloatRenderable) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn format;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGBA32F:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this.isWebGPU && samples > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this.textureFloatRenderable && (!filterable || this.textureFloatFilterable)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn format;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn undefined;\\n\\t\\t}\\n\\t\\tvalidateAttributes(shader, vb0Format, vb1Format) {}\\n\\t\\tconstructor(canvas, options){\\n\\t\\t\\t\\tvar _this_initOptions, _this_initOptions1, _this_initOptions2, _this_initOptions3, _this_initOptions4, _this_initOptions5;\\n\\t\\t\\t\\tsuper(), this.backBuffer = null, this.backBufferSize = new Vec2(), this.backBufferAntialias = false, this.isWebGPU = false, this.isWebGL2 = false, this.isNull = false, this.isHdr = false, this.maxIndirectDrawCount = 1024, this.maxIndirectDispatchCount = 256, this.maxColorAttachments = 1, this.maxSamples = 1, this.supportsMultiDraw = true, this.supportsCompute = false, this.supportsStorageTextureRead = false, this.supportsSubgroupUniformity = false, this.supportsSubgroupId = false, this.renderTarget = null, this.shaders = [], this.textures = new Set(), this.texturesToUpload = new Set(), this.targets = new Set(), this.renderVersion = 0, this.insideRenderPass = false, this.supportsUniformBuffers = false, this.supportsClipDistances = false, this.supportsPrimitiveIndex = false, this.textureRG11B10Renderable = false, this.textureFloatFilterable = false, this.blendState = new BlendState(), this.depthState = new DepthState(), this.stencilEnabled = false, this.stencilFront = new StencilParameters(), this.stencilBack = new StencilParameters(), this._destroyed = false, this.defaultClearOptions = {\\n\\t\\t\\t\\t\\t\\tcolor: [\\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\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t1\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\tdepth: 1,\\n\\t\\t\\t\\t\\t\\tstencil: 0,\\n\\t\\t\\t\\t\\t\\tflags: CLEARFLAG_COLOR | CLEARFLAG_DEPTH\\n\\t\\t\\t\\t}, this.clientRect = {\\n\\t\\t\\t\\t\\t\\twidth: 0,\\n\\t\\t\\t\\t\\t\\theight: 0\\n\\t\\t\\t\\t}, this._shadersDirty = false, this.capsDefines = new Map(), this.mapsToClear = new Set();\\n\\t\\t\\t\\tthis.canvas = canvas;\\n\\t\\t\\t\\tif ('setAttribute' in canvas) {\\n\\t\\t\\t\\t\\t\\tcanvas.setAttribute('data-engine', `PlayCanvas ${version$1}`);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.initOptions = {\\n\\t\\t\\t\\t\\t\\t...options\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\t(_this_initOptions = this.initOptions).alpha ?? (_this_initOptions.alpha = true);\\n\\t\\t\\t\\t(_this_initOptions1 = this.initOptions).depth ?? (_this_initOptions1.depth = true);\\n\\t\\t\\t\\t(_this_initOptions2 = this.initOptions).stencil ?? (_this_initOptions2.stencil = true);\\n\\t\\t\\t\\t(_this_initOptions3 = this.initOptions).antialias ?? (_this_initOptions3.antialias = true);\\n\\t\\t\\t\\t(_this_initOptions4 = this.initOptions).powerPreference ?? (_this_initOptions4.powerPreference = 'high-performance');\\n\\t\\t\\t\\t(_this_initOptions5 = this.initOptions).displayFormat ?? (_this_initOptions5.displayFormat = DISPLAYFORMAT_LDR);\\n\\t\\t\\t\\tthis._maxPixelRatio = platform.browser ? Math.min(1, window.devicePixelRatio) : 1;\\n\\t\\t\\t\\tthis.buffers = new Set();\\n\\t\\t\\t\\tthis._vram = {\\n\\t\\t\\t\\t\\t\\ttex: 0,\\n\\t\\t\\t\\t\\t\\tvb: 0,\\n\\t\\t\\t\\t\\t\\tib: 0,\\n\\t\\t\\t\\t\\t\\tub: 0,\\n\\t\\t\\t\\t\\t\\tsb: 0\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis._shaderStats = {\\n\\t\\t\\t\\t\\t\\tvsCompiled: 0,\\n\\t\\t\\t\\t\\t\\tfsCompiled: 0,\\n\\t\\t\\t\\t\\t\\tlinked: 0,\\n\\t\\t\\t\\t\\t\\tmaterialShaders: 0,\\n\\t\\t\\t\\t\\t\\tcompileTime: 0\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.initializeContextCaches();\\n\\t\\t\\t\\tthis._drawCallsPerFrame = 0;\\n\\t\\t\\t\\tthis._shaderSwitchesPerFrame = 0;\\n\\t\\t\\t\\tthis._primsPerFrame = [];\\n\\t\\t\\t\\tfor(let i = PRIMITIVE_POINTS; i <= PRIMITIVE_TRIFAN; i++){\\n\\t\\t\\t\\t\\t\\tthis._primsPerFrame[i] = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._renderTargetCreationTime = 0;\\n\\t\\t\\t\\tthis.scope = new ScopeSpace('Device');\\n\\t\\t\\t\\tthis.textureBias = this.scope.resolve('textureBias');\\n\\t\\t\\t\\tthis.textureBias.setValue(0.0);\\n\\t\\t}\\n}\\nGraphicsDevice.EVENT_RESIZE = 'resizecanvas';\\n\\nlet id$8 = 0;\\nclass RenderTarget {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tconst device = this._device;\\n\\t\\t\\t\\tif (device) {\\n\\t\\t\\t\\t\\t\\tdevice.targets.delete(this);\\n\\t\\t\\t\\t\\t\\tif (device.renderTarget === this) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.setRenderTarget(null);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.destroyFrameBuffers();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdestroyFrameBuffers() {\\n\\t\\t\\t\\tconst device = this._device;\\n\\t\\t\\t\\tif (device) {\\n\\t\\t\\t\\t\\t\\tthis.impl.destroy(device);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdestroyTextureBuffers() {\\n\\t\\t\\t\\tthis._depthBuffer?.destroy();\\n\\t\\t\\t\\tthis._depthBuffer = null;\\n\\t\\t\\t\\tthis._colorBuffers?.forEach((colorBuffer)=>{\\n\\t\\t\\t\\t\\t\\tcolorBuffer.destroy();\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis._colorBuffers = null;\\n\\t\\t\\t\\tthis._colorBuffer = null;\\n\\t\\t}\\n\\t\\tresize(width, height) {\\n\\t\\t\\t\\tif (this.mipLevel > 0) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._depthBuffer?.resize(width, height);\\n\\t\\t\\t\\tthis._colorBuffers?.forEach((colorBuffer)=>{\\n\\t\\t\\t\\t\\t\\tcolorBuffer.resize(width, height);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (this._width !== width || this._height !== height) {\\n\\t\\t\\t\\t\\t\\tthis.destroyFrameBuffers();\\n\\t\\t\\t\\t\\t\\tconst device = this._device;\\n\\t\\t\\t\\t\\t\\tif (device.renderTarget === this) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.setRenderTarget(null);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.evaluateDimensions();\\n\\t\\t\\t\\t\\t\\tthis.validateMrt();\\n\\t\\t\\t\\t\\t\\tthis.impl = device.createRenderTargetImpl(this);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tvalidateMrt() {}\\n\\t\\tevaluateDimensions() {\\n\\t\\t\\t\\tconst buffer = this._colorBuffer ?? this._depthBuffer;\\n\\t\\t\\t\\tif (buffer) {\\n\\t\\t\\t\\t\\t\\tthis._width = buffer.width;\\n\\t\\t\\t\\t\\t\\tthis._height = buffer.height;\\n\\t\\t\\t\\t\\t\\tif (this._mipLevel > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._width = TextureUtils.calcLevelDimension(this._width, this._mipLevel);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._height = TextureUtils.calcLevelDimension(this._height, this._mipLevel);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tinit() {\\n\\t\\t\\t\\tthis.impl.init(this._device, this);\\n\\t\\t}\\n\\t\\tget initialized() {\\n\\t\\t\\t\\treturn this.impl.initialized;\\n\\t\\t}\\n\\t\\tget device() {\\n\\t\\t\\t\\treturn this._device;\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tthis.impl.loseContext();\\n\\t\\t}\\n\\t\\tresolve(color = true, depth = !!this._depthBuffer) {\\n\\t\\t\\t\\tif (this._device && this._samples > 1) {\\n\\t\\t\\t\\t\\t\\tthis.impl.resolve(this._device, this, color, depth);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcopy(source, color, depth) {\\n\\t\\t\\t\\tif (!this._device) {\\n\\t\\t\\t\\t\\t\\tif (source._device) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._device = source._device;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst success = this._device.copyRenderTarget(source, this, color, depth);\\n\\t\\t\\t\\treturn success;\\n\\t\\t}\\n\\t\\tget samples() {\\n\\t\\t\\t\\treturn this._samples;\\n\\t\\t}\\n\\t\\tget depth() {\\n\\t\\t\\t\\treturn this._depth;\\n\\t\\t}\\n\\t\\tget stencil() {\\n\\t\\t\\t\\treturn this._stencil;\\n\\t\\t}\\n\\t\\tget colorBuffer() {\\n\\t\\t\\t\\treturn this._colorBuffer;\\n\\t\\t}\\n\\t\\tgetColorBuffer(index) {\\n\\t\\t\\t\\treturn this._colorBuffers?.[index];\\n\\t\\t}\\n\\t\\tget depthBuffer() {\\n\\t\\t\\t\\treturn this._depthBuffer;\\n\\t\\t}\\n\\t\\tget face() {\\n\\t\\t\\t\\treturn this._face;\\n\\t\\t}\\n\\t\\tget mipLevel() {\\n\\t\\t\\t\\treturn this._mipLevel;\\n\\t\\t}\\n\\t\\tget mipmaps() {\\n\\t\\t\\t\\treturn this._mipmaps;\\n\\t\\t}\\n\\t\\tget width() {\\n\\t\\t\\t\\treturn this._width ?? this._device.width;\\n\\t\\t}\\n\\t\\tget height() {\\n\\t\\t\\t\\treturn this._height ?? this._device.height;\\n\\t\\t}\\n\\t\\tisColorBufferSrgb(index = 0) {\\n\\t\\t\\t\\tif (this.device.backBuffer === this) {\\n\\t\\t\\t\\t\\t\\treturn isSrgbPixelFormat(this.device.backBufferFormat);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst colorBuffer = this.getColorBuffer(index);\\n\\t\\t\\t\\treturn colorBuffer ? isSrgbPixelFormat(colorBuffer.format) : false;\\n\\t\\t}\\n\\t\\tconstructor(options = {}){\\n\\t\\t\\t\\tthis.id = id$8++;\\n\\t\\t\\t\\tconst device = options.colorBuffer?.device ?? options.colorBuffers?.[0].device ?? options.depthBuffer?.device ?? options.graphicsDevice;\\n\\t\\t\\t\\tthis._device = device;\\n\\t\\t\\t\\tconst { maxSamples } = this._device;\\n\\t\\t\\t\\tthis._samples = Math.min(options.samples ?? 1, maxSamples);\\n\\t\\t\\t\\tif (device.isWebGPU) {\\n\\t\\t\\t\\t\\t\\tthis._samples = this._samples > 1 ? maxSamples : 1;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._colorBuffer = options.colorBuffer;\\n\\t\\t\\t\\tif (options.colorBuffer) {\\n\\t\\t\\t\\t\\t\\tthis._colorBuffers = [\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.colorBuffer\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._depthBuffer = options.depthBuffer;\\n\\t\\t\\t\\tthis._face = options.face ?? 0;\\n\\t\\t\\t\\tif (this._depthBuffer) {\\n\\t\\t\\t\\t\\t\\tconst format = this._depthBuffer._format;\\n\\t\\t\\t\\t\\t\\tif (format === PIXELFORMAT_DEPTH || format === PIXELFORMAT_DEPTH16) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._depth = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._stencil = false;\\n\\t\\t\\t\\t\\t\\t} else if (format === PIXELFORMAT_DEPTHSTENCIL) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._depth = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._stencil = true;\\n\\t\\t\\t\\t\\t\\t} else if (format === PIXELFORMAT_R32F && this._depthBuffer.device.isWebGPU && this._samples > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._depth = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._stencil = false;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._depth = false;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._stencil = false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._depth = options.depth ?? true;\\n\\t\\t\\t\\t\\t\\tthis._stencil = options.stencil ?? false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.colorBuffers) {\\n\\t\\t\\t\\t\\t\\tif (!this._colorBuffers) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._colorBuffers = [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t...options.colorBuffers\\n\\t\\t\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._colorBuffer = options.colorBuffers[0];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.autoResolve = options.autoResolve ?? true;\\n\\t\\t\\t\\tthis.name = options.name;\\n\\t\\t\\t\\tif (!this.name) {\\n\\t\\t\\t\\t\\t\\tthis.name = this._colorBuffer?.name;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this.name) {\\n\\t\\t\\t\\t\\t\\tthis.name = this._depthBuffer?.name;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this.name) {\\n\\t\\t\\t\\t\\t\\tthis.name = 'Untitled';\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.flipY = options.flipY ?? false;\\n\\t\\t\\t\\tthis._mipLevel = options.mipLevel ?? 0;\\n\\t\\t\\t\\tif (this._mipLevel > 0 && this._depth) {\\n\\t\\t\\t\\t\\t\\tthis._mipLevel = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._mipmaps = options.mipLevel === undefined;\\n\\t\\t\\t\\tthis.evaluateDimensions();\\n\\t\\t\\t\\tthis.validateMrt();\\n\\t\\t\\t\\tthis.impl = device.createRenderTargetImpl(this);\\n\\t\\t}\\n}\\n\\nclass WebgpuBindGroup {\\n\\t\\tupdate(bindGroup) {\\n\\t\\t\\t\\tthis.destroy();\\n\\t\\t\\t\\tconst device = bindGroup.device;\\n\\t\\t\\t\\tconst desc = this.createDescriptor(device, bindGroup);\\n\\t\\t\\t\\tthis.bindGroup = device.wgpu.createBindGroup(desc);\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.bindGroup = null;\\n\\t\\t}\\n\\t\\tcreateDescriptor(device, bindGroup) {\\n\\t\\t\\t\\tconst entries = [];\\n\\t\\t\\t\\tconst format = bindGroup.format;\\n\\t\\t\\t\\tconst uniformBufferFormats = bindGroup.format.uniformBufferFormats;\\n\\t\\t\\t\\tbindGroup.uniformBuffers.forEach((ub, i)=>{\\n\\t\\t\\t\\t\\t\\tconst slot = uniformBufferFormats[i].slot;\\n\\t\\t\\t\\t\\t\\tconst buffer = ub.persistent ? ub.impl.buffer : ub.allocation.gpuBuffer.buffer;\\n\\t\\t\\t\\t\\t\\tentries.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tbinding: slot,\\n\\t\\t\\t\\t\\t\\t\\t\\tresource: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbuffer: buffer,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toffset: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsize: ub.format.byteSize\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst textureFormats = bindGroup.format.textureFormats;\\n\\t\\t\\t\\tbindGroup.textures.forEach((value, textureIndex)=>{\\n\\t\\t\\t\\t\\t\\tconst isTextureView = value instanceof TextureView;\\n\\t\\t\\t\\t\\t\\tconst texture = isTextureView ? value.texture : value;\\n\\t\\t\\t\\t\\t\\tconst wgpuTexture = texture.impl;\\n\\t\\t\\t\\t\\t\\tconst textureFormat = format.textureFormats[textureIndex];\\n\\t\\t\\t\\t\\t\\tconst slot = textureFormats[textureIndex].slot;\\n\\t\\t\\t\\t\\t\\tconst view = wgpuTexture.getView(device, isTextureView ? value : undefined);\\n\\t\\t\\t\\t\\t\\tentries.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tbinding: slot,\\n\\t\\t\\t\\t\\t\\t\\t\\tresource: view\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tif (textureFormat.hasSampler) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst sampler = wgpuTexture.getSampler(device, textureFormat.sampleType);\\n\\t\\t\\t\\t\\t\\t\\t\\tentries.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbinding: slot + 1,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresource: sampler\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst storageTextureFormats = bindGroup.format.storageTextureFormats;\\n\\t\\t\\t\\tbindGroup.storageTextures.forEach((value, textureIndex)=>{\\n\\t\\t\\t\\t\\t\\tconst isTextureView = value instanceof TextureView;\\n\\t\\t\\t\\t\\t\\tconst texture = isTextureView ? value.texture : value;\\n\\t\\t\\t\\t\\t\\tconst wgpuTexture = texture.impl;\\n\\t\\t\\t\\t\\t\\tconst slot = storageTextureFormats[textureIndex].slot;\\n\\t\\t\\t\\t\\t\\tconst view = wgpuTexture.getView(device, isTextureView ? value : undefined);\\n\\t\\t\\t\\t\\t\\tentries.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tbinding: slot,\\n\\t\\t\\t\\t\\t\\t\\t\\tresource: view\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst storageBufferFormats = bindGroup.format.storageBufferFormats;\\n\\t\\t\\t\\tbindGroup.storageBuffers.forEach((buffer, bufferIndex)=>{\\n\\t\\t\\t\\t\\t\\tconst wgpuBuffer = buffer.impl.buffer;\\n\\t\\t\\t\\t\\t\\tconst slot = storageBufferFormats[bufferIndex].slot;\\n\\t\\t\\t\\t\\t\\tentries.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tbinding: slot,\\n\\t\\t\\t\\t\\t\\t\\t\\tresource: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbuffer: wgpuBuffer\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst desc = {\\n\\t\\t\\t\\t\\t\\tlayout: bindGroup.format.impl.bindGroupLayout,\\n\\t\\t\\t\\t\\t\\tentries: entries\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\treturn desc;\\n\\t\\t}\\n}\\n\\nclass WebgpuUtils {\\n\\t\\tstatic shaderStage(stage) {\\n\\t\\t\\t\\tlet ret = 0;\\n\\t\\t\\t\\tif (stage & SHADERSTAGE_VERTEX) ret |= GPUShaderStage.VERTEX;\\n\\t\\t\\t\\tif (stage & SHADERSTAGE_FRAGMENT) ret |= GPUShaderStage.FRAGMENT;\\n\\t\\t\\t\\tif (stage & SHADERSTAGE_COMPUTE) ret |= GPUShaderStage.COMPUTE;\\n\\t\\t\\t\\treturn ret;\\n\\t\\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\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.bindGroupLayout = null;\\n\\t\\t}\\n\\t\\tloseContext() {}\\n\\t\\tcreateDescriptor(bindGroupFormat) {\\n\\t\\t\\t\\tconst entries = [];\\n\\t\\t\\t\\tlet key = '';\\n\\t\\t\\t\\tbindGroupFormat.uniformBufferFormats.forEach((bufferFormat)=>{\\n\\t\\t\\t\\t\\t\\tconst visibility = WebgpuUtils.shaderStage(bufferFormat.visibility);\\n\\t\\t\\t\\t\\t\\tkey += `#${bufferFormat.slot}U:${visibility}`;\\n\\t\\t\\t\\t\\t\\tentries.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tbinding: bufferFormat.slot,\\n\\t\\t\\t\\t\\t\\t\\t\\tvisibility: visibility,\\n\\t\\t\\t\\t\\t\\t\\t\\tbuffer: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype: 'uniform',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\thasDynamicOffset: true\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tbindGroupFormat.textureFormats.forEach((textureFormat)=>{\\n\\t\\t\\t\\t\\t\\tconst visibility = WebgpuUtils.shaderStage(textureFormat.visibility);\\n\\t\\t\\t\\t\\t\\tconst sampleType = textureFormat.sampleType;\\n\\t\\t\\t\\t\\t\\tconst viewDimension = textureFormat.textureDimension;\\n\\t\\t\\t\\t\\t\\tconst multisampled = false;\\n\\t\\t\\t\\t\\t\\tconst gpuSampleType = sampleTypes[sampleType];\\n\\t\\t\\t\\t\\t\\tkey += `#${textureFormat.slot}T:${visibility}-${gpuSampleType}-${viewDimension}-${multisampled}`;\\n\\t\\t\\t\\t\\t\\tentries.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tbinding: textureFormat.slot,\\n\\t\\t\\t\\t\\t\\t\\t\\tvisibility: visibility,\\n\\t\\t\\t\\t\\t\\t\\t\\ttexture: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsampleType: gpuSampleType,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tviewDimension: viewDimension,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmultisampled: multisampled\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tif (textureFormat.hasSampler) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst gpuSamplerType = samplerTypes[sampleType];\\n\\t\\t\\t\\t\\t\\t\\t\\tkey += `#${textureFormat.slot + 1}S:${visibility}-${gpuSamplerType}`;\\n\\t\\t\\t\\t\\t\\t\\t\\tentries.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbinding: textureFormat.slot + 1,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvisibility: visibility,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsampler: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype: gpuSamplerType\\n\\t\\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}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tbindGroupFormat.storageTextureFormats.forEach((textureFormat)=>{\\n\\t\\t\\t\\t\\t\\tconst { format, textureDimension } = textureFormat;\\n\\t\\t\\t\\t\\t\\tconst { read, write } = textureFormat;\\n\\t\\t\\t\\t\\t\\tkey += `#${textureFormat.slot}ST:${format}-${textureDimension}-${read ? 'r1' : 'r0'}-${write ? 'w1' : 'w0'}`;\\n\\t\\t\\t\\t\\t\\tentries.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tbinding: textureFormat.slot,\\n\\t\\t\\t\\t\\t\\t\\t\\tvisibility: GPUShaderStage.COMPUTE,\\n\\t\\t\\t\\t\\t\\t\\t\\tstorageTexture: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taccess: read ? write ? 'read-write' : 'read-only' : 'write-only',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: gpuTextureFormats[format],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tviewDimension: textureDimension\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tbindGroupFormat.storageBufferFormats.forEach((bufferFormat)=>{\\n\\t\\t\\t\\t\\t\\tconst readOnly = bufferFormat.readOnly;\\n\\t\\t\\t\\t\\t\\tconst visibility = WebgpuUtils.shaderStage(bufferFormat.visibility);\\n\\t\\t\\t\\t\\t\\tkey += `#${bufferFormat.slot}SB:${visibility}-${readOnly ? 'ro' : 'rw'}`;\\n\\t\\t\\t\\t\\t\\tentries.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tbinding: bufferFormat.slot,\\n\\t\\t\\t\\t\\t\\t\\t\\tvisibility: visibility,\\n\\t\\t\\t\\t\\t\\t\\t\\tbuffer: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype: readOnly ? 'read-only-storage' : 'storage'\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst desc = {\\n\\t\\t\\t\\t\\t\\tentries: entries\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tkey,\\n\\t\\t\\t\\t\\t\\tdesc\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tconstructor(bindGroupFormat){\\n\\t\\t\\t\\tconst device = bindGroupFormat.device;\\n\\t\\t\\t\\tconst { key, desc } = this.createDescriptor(bindGroupFormat);\\n\\t\\t\\t\\tthis.key = stringIds$1.get(key);\\n\\t\\t\\t\\tthis.bindGroupLayout = device.wgpu.createBindGroupLayout(desc);\\n\\t\\t}\\n}\\n\\nclass WebgpuBuffer {\\n\\t\\tdestroy(device) {\\n\\t\\t\\t\\tif (this.buffer) {\\n\\t\\t\\t\\t\\t\\tthis.buffer.destroy();\\n\\t\\t\\t\\t\\t\\tthis.buffer = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget initialized() {\\n\\t\\t\\t\\treturn !!this.buffer;\\n\\t\\t}\\n\\t\\tloseContext() {}\\n\\t\\tallocate(device, size) {\\n\\t\\t\\t\\tthis.buffer = device.wgpu.createBuffer({\\n\\t\\t\\t\\t\\t\\tsize,\\n\\t\\t\\t\\t\\t\\tusage: this.usageFlags\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tunlock(device, storage) {\\n\\t\\t\\t\\tconst wgpu = device.wgpu;\\n\\t\\t\\t\\tif (!this.buffer) {\\n\\t\\t\\t\\t\\t\\tconst size = storage.byteLength + 3 & -4;\\n\\t\\t\\t\\t\\t\\tthis.usageFlags |= GPUBufferUsage.COPY_DST;\\n\\t\\t\\t\\t\\t\\tthis.allocate(device, size);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst srcOffset = storage.byteOffset ?? 0;\\n\\t\\t\\t\\tconst srcData = new Uint8Array(storage.buffer ?? storage, srcOffset, storage.byteLength);\\n\\t\\t\\t\\tconst data = new Uint8Array(this.buffer.size);\\n\\t\\t\\t\\tdata.set(srcData);\\n\\t\\t\\t\\twgpu.queue.writeBuffer(this.buffer, 0, data, 0, data.length);\\n\\t\\t}\\n\\t\\tread(device, offset, size, data, immediate) {\\n\\t\\t\\t\\treturn device.readStorageBuffer(this, offset, size, data, immediate);\\n\\t\\t}\\n\\t\\twrite(device, bufferOffset, data, dataOffset, size) {\\n\\t\\t\\t\\tdevice.writeStorageBuffer(this, bufferOffset, data, dataOffset, size);\\n\\t\\t}\\n\\t\\tclear(device, offset, size) {\\n\\t\\t\\t\\tdevice.clearStorageBuffer(this, offset, size);\\n\\t\\t}\\n\\t\\tconstructor(usageFlags = 0){\\n\\t\\t\\t\\tthis.buffer = null;\\n\\t\\t\\t\\tthis.usageFlags = 0;\\n\\t\\t\\t\\tthis.usageFlags = usageFlags;\\n\\t\\t}\\n}\\n\\nclass WebgpuIndexBuffer extends WebgpuBuffer {\\n\\t\\tunlock(indexBuffer) {\\n\\t\\t\\t\\tconst device = indexBuffer.device;\\n\\t\\t\\t\\tsuper.unlock(device, indexBuffer.storage);\\n\\t\\t}\\n\\t\\tconstructor(indexBuffer, options){\\n\\t\\t\\t\\tsuper(BUFFERUSAGE_INDEX | (options?.storage ? BUFFERUSAGE_STORAGE : 0)), this.format = null;\\n\\t\\t\\t\\tthis.format = indexBuffer.format === INDEXFORMAT_UINT16 ? 'uint16' : 'uint32';\\n\\t\\t}\\n}\\n\\nconst array$1 = {\\n\\t\\tequals (arr1, arr2) {\\n\\t\\t\\t\\tif (arr1.length !== arr2.length) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < arr1.length; i++){\\n\\t\\t\\t\\t\\t\\tif (arr1[i] !== arr2[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\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\\t\\tget(vertexFormat0, vertexFormat1 = null) {\\n\\t\\t\\t\\tconst key = this.getKey(vertexFormat0, vertexFormat1);\\n\\t\\t\\t\\tlet layout = this.cache.get(key);\\n\\t\\t\\t\\tif (!layout) {\\n\\t\\t\\t\\t\\t\\tlayout = this.create(vertexFormat0, vertexFormat1);\\n\\t\\t\\t\\t\\t\\tthis.cache.set(key, layout);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn layout;\\n\\t\\t}\\n\\t\\tgetKey(vertexFormat0, vertexFormat1 = null) {\\n\\t\\t\\t\\treturn `${vertexFormat0?.renderingHashString}-${vertexFormat1?.renderingHashString}`;\\n\\t\\t}\\n\\t\\tcreate(vertexFormat0, vertexFormat1) {\\n\\t\\t\\t\\tconst layout = [];\\n\\t\\t\\t\\tconst addFormat = (format)=>{\\n\\t\\t\\t\\t\\t\\tconst interleaved = format.interleaved;\\n\\t\\t\\t\\t\\t\\tconst stepMode = format.instancing ? 'instance' : 'vertex';\\n\\t\\t\\t\\t\\t\\tlet attributes = [];\\n\\t\\t\\t\\t\\t\\tconst elementCount = format.elements.length;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < elementCount; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst element = format.elements[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst location = semanticToLocation[element.name];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst formatTable = element.normalize ? gpuVertexFormatsNormalized : gpuVertexFormats;\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshaderLocation: location,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toffset: interleaved ? element.offset : 0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: `${formatTable[element.dataType]}${element.numComponents > 1 ? `x${element.numComponents}` : ''}`\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!interleaved || i === elementCount - 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayout.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tattributes: attributes,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tarrayStride: element.stride,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstepMode: stepMode\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tattributes = [];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (vertexFormat0) {\\n\\t\\t\\t\\t\\t\\taddFormat(vertexFormat0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (vertexFormat1) {\\n\\t\\t\\t\\t\\t\\taddFormat(vertexFormat1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn layout;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.cache = new Map();\\n\\t\\t}\\n}\\n\\nclass WebgpuPipeline {\\n\\t\\tgetPipelineLayout(bindGroupFormats) {\\n\\t\\t\\t\\tconst bindGroupLayouts = [];\\n\\t\\t\\t\\tbindGroupFormats.forEach((format)=>{\\n\\t\\t\\t\\t\\t\\tbindGroupLayouts.push(format.bindGroupLayout);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst desc = {\\n\\t\\t\\t\\t\\t\\tbindGroupLayouts: bindGroupLayouts\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst pipelineLayout = this.device.wgpu.createPipelineLayout(desc);\\n\\t\\t\\t\\treturn pipelineLayout;\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t}\\n}\\n\\nconst _primitiveTopology = [\\n\\t\\t'point-list',\\n\\t\\t'line-list',\\n\\t\\tundefined,\\n\\t\\t'line-strip',\\n\\t\\t'triangle-list',\\n\\t\\t'triangle-strip',\\n\\t\\tundefined\\n];\\nconst _blendOperation = [\\n\\t\\t'add',\\n\\t\\t'subtract',\\n\\t\\t'reverse-subtract',\\n\\t\\t'min',\\n\\t\\t'max'\\n];\\nconst _blendFactor = [\\n\\t\\t'zero',\\n\\t\\t'one',\\n\\t\\t'src',\\n\\t\\t'one-minus-src',\\n\\t\\t'dst',\\n\\t\\t'one-minus-dst',\\n\\t\\t'src-alpha',\\n\\t\\t'src-alpha-saturated',\\n\\t\\t'one-minus-src-alpha',\\n\\t\\t'dst-alpha',\\n\\t\\t'one-minus-dst-alpha',\\n\\t\\t'constant',\\n\\t\\t'one-minus-constant'\\n];\\nconst _compareFunction = [\\n\\t\\t'never',\\n\\t\\t'less',\\n\\t\\t'equal',\\n\\t\\t'less-equal',\\n\\t\\t'greater',\\n\\t\\t'not-equal',\\n\\t\\t'greater-equal',\\n\\t\\t'always'\\n];\\nconst _cullModes = [\\n\\t\\t'none',\\n\\t\\t'back',\\n\\t\\t'front'\\n];\\nconst _stencilOps = [\\n\\t\\t'keep',\\n\\t\\t'zero',\\n\\t\\t'replace',\\n\\t\\t'increment-clamp',\\n\\t\\t'increment-wrap',\\n\\t\\t'decrement-clamp',\\n\\t\\t'decrement-wrap',\\n\\t\\t'invert'\\n];\\nconst _indexFormat = [\\n\\t\\t'',\\n\\t\\t'uint16',\\n\\t\\t'uint32'\\n];\\nlet CacheEntry$1 = class CacheEntry {\\n};\\nclass WebgpuRenderPipeline extends WebgpuPipeline {\\n\\t\\tget(primitive, vertexFormat0, vertexFormat1, ibFormat, shader, renderTarget, bindGroupFormats, blendState, depthState, cullMode, stencilEnabled, stencilFront, stencilBack) {\\n\\t\\t\\t\\tconst primitiveType = primitive.type;\\n\\t\\t\\t\\tif (ibFormat && primitiveType !== PRIMITIVE_LINESTRIP && primitiveType !== PRIMITIVE_TRISTRIP) {\\n\\t\\t\\t\\t\\t\\tibFormat = undefined;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst lookupHashes = this.lookupHashes;\\n\\t\\t\\t\\tlookupHashes[0] = primitiveType;\\n\\t\\t\\t\\tlookupHashes[1] = shader.id;\\n\\t\\t\\t\\tlookupHashes[2] = cullMode;\\n\\t\\t\\t\\tlookupHashes[3] = depthState.key;\\n\\t\\t\\t\\tlookupHashes[4] = blendState.key;\\n\\t\\t\\t\\tlookupHashes[5] = vertexFormat0?.renderingHash ?? 0;\\n\\t\\t\\t\\tlookupHashes[6] = vertexFormat1?.renderingHash ?? 0;\\n\\t\\t\\t\\tlookupHashes[7] = renderTarget.impl.key;\\n\\t\\t\\t\\tlookupHashes[8] = bindGroupFormats[0]?.key ?? 0;\\n\\t\\t\\t\\tlookupHashes[9] = bindGroupFormats[1]?.key ?? 0;\\n\\t\\t\\t\\tlookupHashes[10] = bindGroupFormats[2]?.key ?? 0;\\n\\t\\t\\t\\tlookupHashes[11] = stencilEnabled ? stencilFront.key : 0;\\n\\t\\t\\t\\tlookupHashes[12] = stencilEnabled ? stencilBack.key : 0;\\n\\t\\t\\t\\tlookupHashes[13] = ibFormat ?? 0;\\n\\t\\t\\t\\tconst hash = hash32Fnv1a(lookupHashes);\\n\\t\\t\\t\\tlet cacheEntries = this.cache.get(hash);\\n\\t\\t\\t\\tif (cacheEntries) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < cacheEntries.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst entry = cacheEntries[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (array$1.equals(entry.hashes, lookupHashes)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn entry.pipeline;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst primitiveTopology = _primitiveTopology[primitiveType];\\n\\t\\t\\t\\tconst pipelineLayout = this.getPipelineLayout(bindGroupFormats);\\n\\t\\t\\t\\tconst vertexBufferLayout = this.vertexBufferLayout.get(vertexFormat0, vertexFormat1);\\n\\t\\t\\t\\tconst cacheEntry = new CacheEntry$1();\\n\\t\\t\\t\\tcacheEntry.hashes = new Uint32Array(lookupHashes);\\n\\t\\t\\t\\tcacheEntry.pipeline = this.create(primitiveTopology, ibFormat, shader, renderTarget, pipelineLayout, blendState, depthState, vertexBufferLayout, cullMode, stencilEnabled, stencilFront, stencilBack);\\n\\t\\t\\t\\tif (cacheEntries) {\\n\\t\\t\\t\\t\\t\\tcacheEntries.push(cacheEntry);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tcacheEntries = [\\n\\t\\t\\t\\t\\t\\t\\t\\tcacheEntry\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.cache.set(hash, cacheEntries);\\n\\t\\t\\t\\treturn cacheEntry.pipeline;\\n\\t\\t}\\n\\t\\tgetBlend(blendState) {\\n\\t\\t\\t\\tlet blend;\\n\\t\\t\\t\\tif (blendState.blend) {\\n\\t\\t\\t\\t\\t\\tblend = {\\n\\t\\t\\t\\t\\t\\t\\t\\tcolor: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toperation: _blendOperation[blendState.colorOp],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsrcFactor: _blendFactor[blendState.colorSrcFactor],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdstFactor: _blendFactor[blendState.colorDstFactor]\\n\\t\\t\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t\\t\\talpha: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toperation: _blendOperation[blendState.alphaOp],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsrcFactor: _blendFactor[blendState.alphaSrcFactor],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdstFactor: _blendFactor[blendState.alphaDstFactor]\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn blend;\\n\\t\\t}\\n\\t\\tgetDepthStencil(depthState, renderTarget, stencilEnabled, stencilFront, stencilBack, primitiveTopology) {\\n\\t\\t\\t\\tlet depthStencil;\\n\\t\\t\\t\\tconst { depth, stencil } = renderTarget;\\n\\t\\t\\t\\tif (depth || stencil) {\\n\\t\\t\\t\\t\\t\\tdepthStencil = {\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: renderTarget.impl.depthAttachment.format\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tif (depth) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthStencil.depthWriteEnabled = depthState.write;\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthStencil.depthCompare = _compareFunction[depthState.func];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst biasAllowed = primitiveTopology === 'triangle-list' || primitiveTopology === 'triangle-strip';\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthStencil.depthBias = biasAllowed ? depthState.depthBias : 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthStencil.depthBiasSlopeScale = biasAllowed ? depthState.depthBiasSlope : 0;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthStencil.depthWriteEnabled = false;\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthStencil.depthCompare = 'always';\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (stencil && stencilEnabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthStencil.stencilReadMas = stencilFront.readMask;\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthStencil.stencilWriteMask = stencilFront.writeMask;\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthStencil.stencilFront = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcompare: _compareFunction[stencilFront.func],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfailOp: _stencilOps[stencilFront.fail],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpassOp: _stencilOps[stencilFront.zpass],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdepthFailOp: _stencilOps[stencilFront.zfail]\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthStencil.stencilBack = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcompare: _compareFunction[stencilBack.func],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfailOp: _stencilOps[stencilBack.fail],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpassOp: _stencilOps[stencilBack.zpass],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdepthFailOp: _stencilOps[stencilBack.zfail]\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn depthStencil;\\n\\t\\t}\\n\\t\\tcreate(primitiveTopology, ibFormat, shader, renderTarget, pipelineLayout, blendState, depthState, vertexBufferLayout, cullMode, stencilEnabled, stencilFront, stencilBack) {\\n\\t\\t\\t\\tconst wgpu = this.device.wgpu;\\n\\t\\t\\t\\tconst webgpuShader = shader.impl;\\n\\t\\t\\t\\tconst desc = {\\n\\t\\t\\t\\t\\t\\tvertex: {\\n\\t\\t\\t\\t\\t\\t\\t\\tmodule: webgpuShader.getVertexShaderModule(),\\n\\t\\t\\t\\t\\t\\t\\t\\tentryPoint: webgpuShader.vertexEntryPoint,\\n\\t\\t\\t\\t\\t\\t\\t\\tbuffers: vertexBufferLayout\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tprimitive: {\\n\\t\\t\\t\\t\\t\\t\\t\\ttopology: primitiveTopology,\\n\\t\\t\\t\\t\\t\\t\\t\\tfrontFace: 'ccw',\\n\\t\\t\\t\\t\\t\\t\\t\\tcullMode: _cullModes[cullMode]\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tdepthStencil: this.getDepthStencil(depthState, renderTarget, stencilEnabled, stencilFront, stencilBack, primitiveTopology),\\n\\t\\t\\t\\t\\t\\tmultisample: {\\n\\t\\t\\t\\t\\t\\t\\t\\tcount: renderTarget.samples\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tlayout: pipelineLayout\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (ibFormat) {\\n\\t\\t\\t\\t\\t\\tdesc.primitive.stripIndexFormat = _indexFormat[ibFormat];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdesc.fragment = {\\n\\t\\t\\t\\t\\t\\tmodule: webgpuShader.getFragmentShaderModule(),\\n\\t\\t\\t\\t\\t\\tentryPoint: webgpuShader.fragmentEntryPoint,\\n\\t\\t\\t\\t\\t\\ttargets: []\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst colorAttachments = renderTarget.impl.colorAttachments;\\n\\t\\t\\t\\tif (colorAttachments.length > 0) {\\n\\t\\t\\t\\t\\t\\tlet writeMask = 0;\\n\\t\\t\\t\\t\\t\\tif (blendState.redWrite) writeMask |= GPUColorWrite.RED;\\n\\t\\t\\t\\t\\t\\tif (blendState.greenWrite) writeMask |= GPUColorWrite.GREEN;\\n\\t\\t\\t\\t\\t\\tif (blendState.blueWrite) writeMask |= GPUColorWrite.BLUE;\\n\\t\\t\\t\\t\\t\\tif (blendState.alphaWrite) writeMask |= GPUColorWrite.ALPHA;\\n\\t\\t\\t\\t\\t\\tconst blend = this.getBlend(blendState);\\n\\t\\t\\t\\t\\t\\tcolorAttachments.forEach((attachment)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tdesc.fragment.targets.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: attachment.format,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twriteMask: writeMask,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tblend: blend\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst pipeline = wgpu.createRenderPipeline(desc);\\n\\t\\t\\t\\treturn pipeline;\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tsuper(device), this.lookupHashes = new Uint32Array(14);\\n\\t\\t\\t\\tthis.vertexBufferLayout = new WebgpuVertexBufferLayout();\\n\\t\\t\\t\\tthis.cache = new Map();\\n\\t\\t}\\n}\\n\\nclass CacheEntry {\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.pipeline = null;\\n\\t\\t\\t\\tthis.hashes = null;\\n\\t\\t}\\n}\\nclass WebgpuComputePipeline extends WebgpuPipeline {\\n\\t\\tget(shader, bindGroupFormat) {\\n\\t\\t\\t\\tconst lookupHashes = this.lookupHashes;\\n\\t\\t\\t\\tlookupHashes[0] = shader.impl.computeKey;\\n\\t\\t\\t\\tlookupHashes[1] = bindGroupFormat.impl.key;\\n\\t\\t\\t\\tconst hash = hash32Fnv1a(lookupHashes);\\n\\t\\t\\t\\tlet cacheEntries = this.cache.get(hash);\\n\\t\\t\\t\\tif (cacheEntries) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < cacheEntries.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst entry = cacheEntries[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (array$1.equals(entry.hashes, lookupHashes)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn entry.pipeline;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst pipelineLayout = this.getPipelineLayout([\\n\\t\\t\\t\\t\\t\\tbindGroupFormat.impl\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tconst cacheEntry = new CacheEntry();\\n\\t\\t\\t\\tcacheEntry.hashes = new Uint32Array(lookupHashes);\\n\\t\\t\\t\\tcacheEntry.pipeline = this.create(shader, pipelineLayout);\\n\\t\\t\\t\\tif (cacheEntries) {\\n\\t\\t\\t\\t\\t\\tcacheEntries.push(cacheEntry);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tcacheEntries = [\\n\\t\\t\\t\\t\\t\\t\\t\\tcacheEntry\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.cache.set(hash, cacheEntries);\\n\\t\\t\\t\\treturn cacheEntry.pipeline;\\n\\t\\t}\\n\\t\\tcreate(shader, pipelineLayout) {\\n\\t\\t\\t\\tconst wgpu = this.device.wgpu;\\n\\t\\t\\t\\tconst webgpuShader = shader.impl;\\n\\t\\t\\t\\tconst desc = {\\n\\t\\t\\t\\t\\t\\tcompute: {\\n\\t\\t\\t\\t\\t\\t\\t\\tmodule: webgpuShader.getComputeShaderModule(),\\n\\t\\t\\t\\t\\t\\t\\t\\tentryPoint: webgpuShader.computeEntryPoint\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tlayout: pipelineLayout\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst pipeline = wgpu.createComputePipeline(desc);\\n\\t\\t\\t\\treturn pipeline;\\n\\t\\t}\\n\\t\\tconstructor(...args){\\n\\t\\t\\t\\tsuper(...args), this.lookupHashes = new Uint32Array(2), this.cache = new Map();\\n\\t\\t}\\n}\\n\\nclass RefCountedObject {\\n\\t\\tincRefCount() {\\n\\t\\t\\t\\tthis._refCount++;\\n\\t\\t}\\n\\t\\tdecRefCount() {\\n\\t\\t\\t\\tthis._refCount--;\\n\\t\\t}\\n\\t\\tget refCount() {\\n\\t\\t\\t\\treturn this._refCount;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis._refCount = 0;\\n\\t\\t}\\n}\\n\\nclass Entry extends RefCountedObject {\\n\\t\\tconstructor(obj){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.object = obj;\\n\\t\\t\\t\\tthis.incRefCount();\\n\\t\\t}\\n}\\nclass RefCountedKeyCache {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.cache.forEach((entry)=>{\\n\\t\\t\\t\\t\\t\\tentry.object?.destroy();\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.cache.clear();\\n\\t\\t}\\n\\t\\tclear() {\\n\\t\\t\\t\\tthis.cache.clear();\\n\\t\\t}\\n\\t\\tget(key) {\\n\\t\\t\\t\\tconst entry = this.cache.get(key);\\n\\t\\t\\t\\tif (entry) {\\n\\t\\t\\t\\t\\t\\tentry.incRefCount();\\n\\t\\t\\t\\t\\t\\treturn entry.object;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tset(key, object) {\\n\\t\\t\\t\\tthis.cache.set(key, new Entry(object));\\n\\t\\t}\\n\\t\\trelease(key) {\\n\\t\\t\\t\\tconst entry = this.cache.get(key);\\n\\t\\t\\t\\tif (entry) {\\n\\t\\t\\t\\t\\t\\tentry.decRefCount();\\n\\t\\t\\t\\t\\t\\tif (entry.refCount === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.cache.delete(key);\\n\\t\\t\\t\\t\\t\\t\\t\\tentry.object?.destroy();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.cache = new Map();\\n\\t\\t}\\n}\\n\\nclass MultisampledTextureCache extends RefCountedKeyCache {\\n\\t\\tloseContext(device) {\\n\\t\\t\\t\\tthis.clear();\\n\\t\\t}\\n}\\nconst multisampledTextureCache = new DeviceCache();\\nconst getMultisampledTextureCache = (device)=>{\\n\\t\\treturn multisampledTextureCache.get(device, ()=>{\\n\\t\\t\\t\\treturn new MultisampledTextureCache();\\n\\t\\t});\\n};\\n\\nconst stringIds = new StringIds();\\nclass ColorAttachment {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.multisampledBuffer?.destroy();\\n\\t\\t\\t\\tthis.multisampledBuffer = null;\\n\\t\\t}\\n}\\nclass DepthAttachment {\\n\\t\\tdestroy(device) {\\n\\t\\t\\t\\tif (this.depthTextureInternal) {\\n\\t\\t\\t\\t\\t\\tthis.depthTexture?.destroy();\\n\\t\\t\\t\\t\\t\\tthis.depthTexture = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.multisampledDepthBuffer) {\\n\\t\\t\\t\\t\\t\\tthis.multisampledDepthBuffer = null;\\n\\t\\t\\t\\t\\t\\tgetMultisampledTextureCache(device).release(this.multisampledDepthBufferKey);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(gpuFormat){\\n\\t\\t\\t\\tthis.depthTexture = null;\\n\\t\\t\\t\\tthis.depthTextureInternal = false;\\n\\t\\t\\t\\tthis.multisampledDepthBuffer = null;\\n\\t\\t\\t\\tthis.format = gpuFormat;\\n\\t\\t\\t\\tthis.hasStencil = gpuFormat === 'depth24plus-stencil8';\\n\\t\\t}\\n}\\nclass WebgpuRenderTarget {\\n\\t\\tdestroy(device) {\\n\\t\\t\\t\\tthis.initialized = false;\\n\\t\\t\\t\\tthis.assignedColorTexture = null;\\n\\t\\t\\t\\tthis.colorAttachments.forEach((colorAttachment)=>{\\n\\t\\t\\t\\t\\t\\tcolorAttachment.destroy();\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.colorAttachments.length = 0;\\n\\t\\t\\t\\tthis.depthAttachment?.destroy(device);\\n\\t\\t\\t\\tthis.depthAttachment = null;\\n\\t\\t}\\n\\t\\tupdateKey() {\\n\\t\\t\\t\\tconst rt = this.renderTarget;\\n\\t\\t\\t\\tlet key = `${rt.samples}:${this.depthAttachment ? this.depthAttachment.format : 'nodepth'}`;\\n\\t\\t\\t\\tthis.colorAttachments.forEach((colorAttachment)=>{\\n\\t\\t\\t\\t\\t\\tkey += `:${colorAttachment.format}`;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.key = stringIds.get(key);\\n\\t\\t}\\n\\t\\tassignColorTexture(device, gpuTexture) {\\n\\t\\t\\t\\tthis.assignedColorTexture = gpuTexture;\\n\\t\\t\\t\\tconst view = gpuTexture.createView({\\n\\t\\t\\t\\t\\t\\tformat: device.backBufferViewFormat\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst colorAttachment = this.renderPassDescriptor.colorAttachments[0];\\n\\t\\t\\t\\tconst samples = this.renderTarget.samples;\\n\\t\\t\\t\\tif (samples > 1) {\\n\\t\\t\\t\\t\\t\\tcolorAttachment.resolveTarget = view;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tcolorAttachment.view = view;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.setColorAttachment(0, undefined, device.backBufferViewFormat);\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t\\tsetColorAttachment(index, multisampledBuffer, format) {\\n\\t\\t\\t\\tif (!this.colorAttachments[index]) {\\n\\t\\t\\t\\t\\t\\tthis.colorAttachments[index] = new ColorAttachment();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (multisampledBuffer) {\\n\\t\\t\\t\\t\\t\\tthis.colorAttachments[index].multisampledBuffer = multisampledBuffer;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (format) {\\n\\t\\t\\t\\t\\t\\tthis.colorAttachments[index].format = format;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tinit(device, renderTarget) {\\n\\t\\t\\t\\tconst wgpu = device.wgpu;\\n\\t\\t\\t\\tthis.initDepthStencil(device, wgpu, renderTarget);\\n\\t\\t\\t\\tif (renderTarget._colorBuffers) {\\n\\t\\t\\t\\t\\t\\trenderTarget._colorBuffers.forEach((colorBuffer, index)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setColorAttachment(index, undefined, colorBuffer.impl.format);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.renderPassDescriptor.colorAttachments = [];\\n\\t\\t\\t\\tconst count = this.isBackbuffer ? 1 : renderTarget._colorBuffers?.length ?? 0;\\n\\t\\t\\t\\tfor(let i = 0; i < count; ++i){\\n\\t\\t\\t\\t\\t\\tconst colorAttachment = this.initColor(device, wgpu, renderTarget, i);\\n\\t\\t\\t\\t\\t\\tconst isDefaultFramebuffer = i === 0 && this.colorAttachments[0]?.format;\\n\\t\\t\\t\\t\\t\\tif (colorAttachment.view || isDefaultFramebuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.renderPassDescriptor.colorAttachments.push(colorAttachment);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t\\t\\tthis.initialized = true;\\n\\t\\t}\\n\\t\\tinitDepthStencil(device, wgpu, renderTarget) {\\n\\t\\t\\t\\tconst { samples, width, height, depth, depthBuffer } = renderTarget;\\n\\t\\t\\t\\tif (depth || depthBuffer) {\\n\\t\\t\\t\\t\\t\\tlet renderingView;\\n\\t\\t\\t\\t\\t\\tif (!depthBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.depthAttachment = new DepthAttachment('depth24plus-stencil8');\\n\\t\\t\\t\\t\\t\\t\\t\\tconst depthTextureDesc = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsize: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twidth,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\theight,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t1\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdimension: '2d',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsampleCount: samples,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: this.depthAttachment.format,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tusage: GPUTextureUsage.RENDER_ATTACHMENT\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\tif (samples > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdepthTextureDesc.usage |= GPUTextureUsage.TEXTURE_BINDING;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdepthTextureDesc.usage |= GPUTextureUsage.COPY_SRC;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst depthTexture = wgpu.createTexture(depthTextureDesc);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.depthAttachment.depthTexture = depthTexture;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.depthAttachment.depthTextureInternal = true;\\n\\t\\t\\t\\t\\t\\t\\t\\trenderingView = depthTexture.createView();\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.depthAttachment = new DepthAttachment(depthBuffer.impl.format);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (samples > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst depthFormat = 'depth24plus-stencil8';\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.depthAttachment.format = depthFormat;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.depthAttachment.hasStencil = depthFormat === 'depth24plus-stencil8';\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst key = `${depthBuffer.id}:${width}:${height}:${samples}:${depthFormat}`;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst msTextures = getMultisampledTextureCache(device);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet msDepthTexture = msTextures.get(key);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!msDepthTexture) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst multisampledDepthDesc = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsize: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twidth,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\theight,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t1\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdimension: '2d',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsampleCount: samples,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: depthFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tusage: GPUTextureUsage.RENDER_ATTACHMENT | (depthFormat !== depthBuffer.impl.format ? GPUTextureUsage.TEXTURE_BINDING : 0)\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmsDepthTexture = wgpu.createTexture(multisampledDepthDesc);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmsTextures.set(key, msDepthTexture);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.depthAttachment.multisampledDepthBuffer = msDepthTexture;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.depthAttachment.multisampledDepthBufferKey = key;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trenderingView = msDepthTexture.createView();\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst depthTexture = depthBuffer.impl.gpuTexture;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.depthAttachment.depthTexture = depthTexture;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trenderingView = depthTexture.createView();\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.renderPassDescriptor.depthStencilAttachment = {\\n\\t\\t\\t\\t\\t\\t\\t\\tview: renderingView\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tinitColor(device, wgpu, renderTarget, index) {\\n\\t\\t\\t\\tconst colorAttachment = {};\\n\\t\\t\\t\\tconst { samples, width, height, mipLevel } = renderTarget;\\n\\t\\t\\t\\tconst colorBuffer = renderTarget.getColorBuffer(index);\\n\\t\\t\\t\\tlet colorView = null;\\n\\t\\t\\t\\tif (colorBuffer) {\\n\\t\\t\\t\\t\\t\\tconst mipLevelCount = 1;\\n\\t\\t\\t\\t\\t\\tif (colorBuffer.cubemap) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcolorView = colorBuffer.impl.createView({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdimension: '2d',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbaseArrayLayer: renderTarget.face,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tarrayLayerCount: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmipLevelCount,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbaseMipLevel: mipLevel\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tcolorView = colorBuffer.impl.createView({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmipLevelCount,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbaseMipLevel: mipLevel\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (samples > 1) {\\n\\t\\t\\t\\t\\t\\tconst format = this.isBackbuffer ? device.backBufferViewFormat : colorBuffer.impl.format;\\n\\t\\t\\t\\t\\t\\tconst multisampledTextureDesc = {\\n\\t\\t\\t\\t\\t\\t\\t\\tsize: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twidth,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\theight,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t1\\n\\t\\t\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t\\t\\tdimension: '2d',\\n\\t\\t\\t\\t\\t\\t\\t\\tsampleCount: samples,\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\t\\t\\tusage: GPUTextureUsage.RENDER_ATTACHMENT\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tconst multisampledColorBuffer = wgpu.createTexture(multisampledTextureDesc);\\n\\t\\t\\t\\t\\t\\tthis.setColorAttachment(index, multisampledColorBuffer, multisampledTextureDesc.format);\\n\\t\\t\\t\\t\\t\\tcolorAttachment.view = multisampledColorBuffer.createView();\\n\\t\\t\\t\\t\\t\\tcolorAttachment.resolveTarget = colorView;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tcolorAttachment.view = colorView;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn colorAttachment;\\n\\t\\t}\\n\\t\\tsetupForRenderPass(renderPass, renderTarget) {\\n\\t\\t\\t\\tconst count = this.renderPassDescriptor.colorAttachments?.length ?? 0;\\n\\t\\t\\t\\tfor(let i = 0; i < count; ++i){\\n\\t\\t\\t\\t\\t\\tconst colorAttachment = this.renderPassDescriptor.colorAttachments[i];\\n\\t\\t\\t\\t\\t\\tconst colorOps = renderPass.colorArrayOps[i];\\n\\t\\t\\t\\t\\t\\tconst srgb = renderTarget.isColorBufferSrgb(i);\\n\\t\\t\\t\\t\\t\\tcolorAttachment.clearValue = srgb ? colorOps.clearValueLinear : colorOps.clearValue;\\n\\t\\t\\t\\t\\t\\tcolorAttachment.loadOp = colorOps.clear ? 'clear' : 'load';\\n\\t\\t\\t\\t\\t\\tcolorAttachment.storeOp = colorOps.store ? 'store' : 'discard';\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst depthAttachment = this.renderPassDescriptor.depthStencilAttachment;\\n\\t\\t\\t\\tif (depthAttachment) {\\n\\t\\t\\t\\t\\t\\tdepthAttachment.depthClearValue = renderPass.depthStencilOps.clearDepthValue;\\n\\t\\t\\t\\t\\t\\tdepthAttachment.depthLoadOp = renderPass.depthStencilOps.clearDepth ? 'clear' : 'load';\\n\\t\\t\\t\\t\\t\\tdepthAttachment.depthStoreOp = renderPass.depthStencilOps.storeDepth ? 'store' : 'discard';\\n\\t\\t\\t\\t\\t\\tdepthAttachment.depthReadOnly = false;\\n\\t\\t\\t\\t\\t\\tif (this.depthAttachment.hasStencil) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthAttachment.stencilClearValue = renderPass.depthStencilOps.clearStencilValue;\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthAttachment.stencilLoadOp = renderPass.depthStencilOps.clearStencil ? 'clear' : 'load';\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthAttachment.stencilStoreOp = renderPass.depthStencilOps.storeStencil ? 'store' : 'discard';\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthAttachment.stencilReadOnly = false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tthis.initialized = false;\\n\\t\\t}\\n\\t\\tresolve(device, target, color, depth) {}\\n\\t\\tconstructor(renderTarget){\\n\\t\\t\\t\\tthis.initialized = false;\\n\\t\\t\\t\\tthis.colorAttachments = [];\\n\\t\\t\\t\\tthis.depthAttachment = null;\\n\\t\\t\\t\\tthis.assignedColorTexture = null;\\n\\t\\t\\t\\tthis.renderPassDescriptor = {};\\n\\t\\t\\t\\tthis.isBackbuffer = false;\\n\\t\\t\\t\\tthis.renderTarget = renderTarget;\\n\\t\\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\\t\\tget isArrayType() {\\n\\t\\t\\t\\treturn this.count > 0;\\n\\t\\t}\\n\\t\\tcalculateOffset(offset) {\\n\\t\\t\\t\\tlet alignment = this.byteSize <= 8 ? this.byteSize : 16;\\n\\t\\t\\t\\tif (this.count) {\\n\\t\\t\\t\\t\\t\\talignment = 16;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\toffset = math.roundUp(offset, alignment);\\n\\t\\t\\t\\tthis.offset = offset / 4;\\n\\t\\t}\\n\\t\\tconstructor(name, type, count = 0){\\n\\t\\t\\t\\tthis.shortName = name;\\n\\t\\t\\t\\tthis.name = count ? `${name}[0]` : name;\\n\\t\\t\\t\\tthis.type = type;\\n\\t\\t\\t\\tthis.numComponents = uniformTypeToNumComponents[type];\\n\\t\\t\\t\\tthis.updateType = type;\\n\\t\\t\\t\\tif (count > 0) {\\n\\t\\t\\t\\t\\t\\tswitch(type){\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_FLOAT:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_FLOATARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_INT:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_INTARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_UINT:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_UINTARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_BOOL:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_BOOLARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_VEC2:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_VEC2ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_IVEC2:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_IVEC2ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_UVEC2:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_UVEC2ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_BVEC2:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_BVEC2ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_VEC3:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_VEC3ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_IVEC3:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_IVEC3ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_UVEC3:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_UVEC3ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_BVEC3:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_BVEC3ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_VEC4:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_VEC4ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_IVEC4:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_IVEC4ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_UVEC4:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_UVEC4ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_BVEC4:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_BVEC4ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_MAT4:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateType = UNIFORMTYPE_MAT4ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.count = count;\\n\\t\\t\\t\\tlet componentSize = this.numComponents;\\n\\t\\t\\t\\tif (count) {\\n\\t\\t\\t\\t\\t\\tcomponentSize = math.roundUp(componentSize, 4);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.byteSize = componentSize * 4;\\n\\t\\t\\t\\tif (count) {\\n\\t\\t\\t\\t\\t\\tthis.byteSize *= count;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nclass UniformBufferFormat {\\n\\t\\tget(name) {\\n\\t\\t\\t\\treturn this.map.get(name);\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice, uniforms){\\n\\t\\t\\t\\tthis.byteSize = 0;\\n\\t\\t\\t\\tthis.map = new Map();\\n\\t\\t\\t\\tthis.scope = graphicsDevice.scope;\\n\\t\\t\\t\\tthis.uniforms = uniforms;\\n\\t\\t\\t\\tlet offset = 0;\\n\\t\\t\\t\\tfor(let i = 0; i < uniforms.length; i++){\\n\\t\\t\\t\\t\\t\\tconst uniform = uniforms[i];\\n\\t\\t\\t\\t\\t\\tuniform.calculateOffset(offset);\\n\\t\\t\\t\\t\\t\\toffset = uniform.offset * 4 + uniform.byteSize;\\n\\t\\t\\t\\t\\t\\tuniform.scopeId = this.scope.resolve(uniform.name);\\n\\t\\t\\t\\t\\t\\tthis.map.set(uniform.name, uniform);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.byteSize = math.roundUp(offset, 16);\\n\\t\\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 = new Set([\\n\\t\\t'highp',\\n\\t\\t'mediump',\\n\\t\\t'lowp'\\n]);\\nconst shadowSamplers = new Set([\\n\\t\\t'sampler2DShadow',\\n\\t\\t'samplerCubeShadow',\\n\\t\\t'sampler2DArrayShadow'\\n]);\\nconst textureDimensions = {\\n\\t\\tsampler2D: TEXTUREDIMENSION_2D,\\n\\t\\tsampler3D: TEXTUREDIMENSION_3D,\\n\\t\\tsamplerCube: TEXTUREDIMENSION_CUBE,\\n\\t\\tsamplerCubeShadow: TEXTUREDIMENSION_CUBE,\\n\\t\\tsampler2DShadow: TEXTUREDIMENSION_2D,\\n\\t\\tsampler2DArray: TEXTUREDIMENSION_2D_ARRAY,\\n\\t\\tsampler2DArrayShadow: TEXTUREDIMENSION_2D_ARRAY,\\n\\t\\tisampler2D: TEXTUREDIMENSION_2D,\\n\\t\\tusampler2D: TEXTUREDIMENSION_2D,\\n\\t\\tisampler3D: TEXTUREDIMENSION_3D,\\n\\t\\tusampler3D: TEXTUREDIMENSION_3D,\\n\\t\\tisamplerCube: TEXTUREDIMENSION_CUBE,\\n\\t\\tusamplerCube: TEXTUREDIMENSION_CUBE,\\n\\t\\tisampler2DArray: TEXTUREDIMENSION_2D_ARRAY,\\n\\t\\tusampler2DArray: TEXTUREDIMENSION_2D_ARRAY\\n};\\nconst textureDimensionInfo = {\\n\\t\\t[TEXTUREDIMENSION_2D]: 'texture2D',\\n\\t\\t[TEXTUREDIMENSION_CUBE]: 'textureCube',\\n\\t\\t[TEXTUREDIMENSION_3D]: 'texture3D',\\n\\t\\t[TEXTUREDIMENSION_2D_ARRAY]: 'texture2DArray'\\n};\\nlet UniformLine$1 = class UniformLine {\\n\\t\\tconstructor(line, shader){\\n\\t\\t\\t\\tthis.line = line;\\n\\t\\t\\t\\tconst words = line.trim().split(/\\\\s+/);\\n\\t\\t\\t\\tif (precisionQualifiers.has(words[0])) {\\n\\t\\t\\t\\t\\t\\tthis.precision = words.shift();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.type = words.shift();\\n\\t\\t\\t\\tif (line.includes(',')) ;\\n\\t\\t\\t\\tif (line.includes('[')) {\\n\\t\\t\\t\\t\\t\\tconst rest = words.join(' ');\\n\\t\\t\\t\\t\\t\\tconst match = ARRAY_IDENTIFIER.exec(rest);\\n\\t\\t\\t\\t\\t\\tthis.name = match[1];\\n\\t\\t\\t\\t\\t\\tthis.arraySize = Number(match[2]);\\n\\t\\t\\t\\t\\t\\tif (isNaN(this.arraySize)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tshader.failed = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.name = words.shift();\\n\\t\\t\\t\\t\\t\\tthis.arraySize = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.isSampler = this.type.indexOf('sampler') !== -1;\\n\\t\\t\\t\\tthis.isSignedInt = this.type.indexOf('isampler') !== -1;\\n\\t\\t\\t\\tthis.isUnsignedInt = this.type.indexOf('usampler') !== -1;\\n\\t\\t}\\n};\\nclass ShaderProcessorGLSL {\\n\\t\\tstatic run(device, shaderDefinition, shader) {\\n\\t\\t\\t\\tconst varyingMap = new Map();\\n\\t\\t\\t\\tconst vertexExtracted = ShaderProcessorGLSL.extract(shaderDefinition.vshader);\\n\\t\\t\\t\\tconst fragmentExtracted = ShaderProcessorGLSL.extract(shaderDefinition.fshader);\\n\\t\\t\\t\\tconst attributesMap = new Map();\\n\\t\\t\\t\\tconst attributesBlock = ShaderProcessorGLSL.processAttributes(vertexExtracted.attributes, shaderDefinition.attributes, attributesMap, shaderDefinition.processingOptions);\\n\\t\\t\\t\\tconst vertexVaryingsBlock = ShaderProcessorGLSL.processVaryings(vertexExtracted.varyings, varyingMap, true);\\n\\t\\t\\t\\tconst fragmentVaryingsBlock = ShaderProcessorGLSL.processVaryings(fragmentExtracted.varyings, varyingMap, false);\\n\\t\\t\\t\\tconst outBlock = ShaderProcessorGLSL.processOuts(fragmentExtracted.outs);\\n\\t\\t\\t\\tconst concatUniforms = vertexExtracted.uniforms.concat(fragmentExtracted.uniforms);\\n\\t\\t\\t\\tconst uniforms = Array.from(new Set(concatUniforms));\\n\\t\\t\\t\\tconst parsedUniforms = uniforms.map((line)=>new UniformLine$1(line, shader));\\n\\t\\t\\t\\tconst uniformsData = ShaderProcessorGLSL.processUniforms(device, parsedUniforms, shaderDefinition.processingOptions, shader);\\n\\t\\t\\t\\tconst vBlock = `${attributesBlock}\\\\n${vertexVaryingsBlock}\\\\n${uniformsData.code}`;\\n\\t\\t\\t\\tconst vshader = vertexExtracted.src.replace(MARKER$1, vBlock);\\n\\t\\t\\t\\tconst fBlock = `${fragmentVaryingsBlock}\\\\n${outBlock}\\\\n${uniformsData.code}`;\\n\\t\\t\\t\\tconst fshader = fragmentExtracted.src.replace(MARKER$1, fBlock);\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tvshader: vshader,\\n\\t\\t\\t\\t\\t\\tfshader: fshader,\\n\\t\\t\\t\\t\\t\\tattributes: attributesMap,\\n\\t\\t\\t\\t\\t\\tmeshUniformBufferFormat: uniformsData.meshUniformBufferFormat,\\n\\t\\t\\t\\t\\t\\tmeshBindGroupFormat: uniformsData.meshBindGroupFormat\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tstatic extract(src) {\\n\\t\\t\\t\\tconst attributes = [];\\n\\t\\t\\t\\tconst varyings = [];\\n\\t\\t\\t\\tconst outs = [];\\n\\t\\t\\t\\tconst uniforms = [];\\n\\t\\t\\t\\tlet replacement = `${MARKER$1}\\\\n`;\\n\\t\\t\\t\\tlet match;\\n\\t\\t\\t\\twhile((match = KEYWORD$2.exec(src)) !== null){\\n\\t\\t\\t\\t\\t\\tconst keyword = match[1];\\n\\t\\t\\t\\t\\t\\tswitch(keyword){\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 'attribute':\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 'varying':\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 'uniform':\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 'out':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tKEYWORD_LINE$1.lastIndex = match.index;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst lineMatch = KEYWORD_LINE$1.exec(src);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (keyword === 'attribute') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tattributes.push(lineMatch[2]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else if (keyword === 'varying') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvaryings.push(lineMatch[2]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else if (keyword === 'out') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\touts.push(lineMatch[2]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else if (keyword === 'uniform') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuniforms.push(lineMatch[2]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsrc = ShaderProcessorGLSL.cutOut(src, match.index, KEYWORD_LINE$1.lastIndex, replacement);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tKEYWORD$2.lastIndex = match.index + replacement.length;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treplacement = '';\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tsrc,\\n\\t\\t\\t\\t\\t\\tattributes,\\n\\t\\t\\t\\t\\t\\tvaryings,\\n\\t\\t\\t\\t\\t\\touts,\\n\\t\\t\\t\\t\\t\\tuniforms\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tstatic processUniforms(device, uniforms, processingOptions, shader) {\\n\\t\\t\\t\\tconst uniformLinesSamplers = [];\\n\\t\\t\\t\\tconst uniformLinesNonSamplers = [];\\n\\t\\t\\t\\tuniforms.forEach((uniform)=>{\\n\\t\\t\\t\\t\\t\\tif (uniform.isSampler) {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformLinesSamplers.push(uniform);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformLinesNonSamplers.push(uniform);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst meshUniforms = [];\\n\\t\\t\\t\\tuniformLinesNonSamplers.forEach((uniform)=>{\\n\\t\\t\\t\\t\\t\\tif (!processingOptions.hasUniform(uniform.name)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst uniformType = uniformTypeToName.indexOf(uniform.type);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst uniformFormat = new UniformFormat(uniform.name, uniformType, uniform.arraySize);\\n\\t\\t\\t\\t\\t\\t\\t\\tmeshUniforms.push(uniformFormat);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (meshUniforms.length === 0) {\\n\\t\\t\\t\\t\\t\\tmeshUniforms.push(new UniformFormat(UNUSED_UNIFORM_NAME, UNIFORMTYPE_FLOAT));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst meshUniformBufferFormat = meshUniforms.length ? new UniformBufferFormat(device, meshUniforms) : null;\\n\\t\\t\\t\\tconst textureFormats = [];\\n\\t\\t\\t\\tuniformLinesSamplers.forEach((uniform)=>{\\n\\t\\t\\t\\t\\t\\tif (!processingOptions.hasTexture(uniform.name)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlet sampleType = SAMPLETYPE_FLOAT;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (uniform.isSignedInt) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsampleType = SAMPLETYPE_INT;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else if (uniform.isUnsignedInt) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsampleType = SAMPLETYPE_UINT;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (uniform.precision === 'highp') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsampleType = SAMPLETYPE_UNFILTERABLE_FLOAT;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (shadowSamplers.has(uniform.type)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsampleType = SAMPLETYPE_DEPTH;\\n\\t\\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 dimension = textureDimensions[uniform.type];\\n\\t\\t\\t\\t\\t\\t\\t\\ttextureFormats.push(new BindTextureFormat(uniform.name, SHADERSTAGE_VERTEX | SHADERSTAGE_FRAGMENT, dimension, sampleType));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst meshBindGroupFormat = new BindGroupFormat(device, textureFormats);\\n\\t\\t\\t\\tlet code = '';\\n\\t\\t\\t\\tprocessingOptions.uniformFormats.forEach((format, bindGroupIndex)=>{\\n\\t\\t\\t\\t\\t\\tif (format) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcode += ShaderProcessorGLSL.getUniformShaderDeclaration(format, bindGroupIndex, 0);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (meshUniformBufferFormat) {\\n\\t\\t\\t\\t\\t\\tcode += ShaderProcessorGLSL.getUniformShaderDeclaration(meshUniformBufferFormat, BINDGROUP_MESH_UB, 0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tprocessingOptions.bindGroupFormats.forEach((format, bindGroupIndex)=>{\\n\\t\\t\\t\\t\\t\\tif (format) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcode += ShaderProcessorGLSL.getTexturesShaderDeclaration(format, bindGroupIndex);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tcode += ShaderProcessorGLSL.getTexturesShaderDeclaration(meshBindGroupFormat, BINDGROUP_MESH);\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tcode,\\n\\t\\t\\t\\t\\t\\tmeshUniformBufferFormat,\\n\\t\\t\\t\\t\\t\\tmeshBindGroupFormat\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tstatic processVaryings(varyingLines, varyingMap, isVertex) {\\n\\t\\t\\t\\tlet block = '';\\n\\t\\t\\t\\tconst op = isVertex ? 'out' : 'in';\\n\\t\\t\\t\\tvaryingLines.forEach((line, index)=>{\\n\\t\\t\\t\\t\\t\\tconst words = ShaderProcessorGLSL.splitToWords(line);\\n\\t\\t\\t\\t\\t\\tconst type = words.slice(0, -1).join(' ');\\n\\t\\t\\t\\t\\t\\tconst name = words[words.length - 1];\\n\\t\\t\\t\\t\\t\\tif (isVertex) {\\n\\t\\t\\t\\t\\t\\t\\t\\tvaryingMap.set(name, index);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tindex = varyingMap.get(name);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tblock += `layout(location = ${index}) ${op} ${type} ${name};\\\\n`;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn block;\\n\\t\\t}\\n\\t\\tstatic processOuts(outsLines) {\\n\\t\\t\\t\\tlet block = '';\\n\\t\\t\\t\\toutsLines.forEach((line, index)=>{\\n\\t\\t\\t\\t\\t\\tblock += `layout(location = ${index}) out ${line};\\\\n`;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn block;\\n\\t\\t}\\n\\t\\tstatic getTypeCount(type) {\\n\\t\\t\\t\\tconst lastChar = type.substring(type.length - 1);\\n\\t\\t\\t\\tconst num = parseInt(lastChar, 10);\\n\\t\\t\\t\\treturn isNaN(num) ? 1 : num;\\n\\t\\t}\\n\\t\\tstatic processAttributes(attributeLines, shaderDefinitionAttributes, attributesMap, processingOptions) {\\n\\t\\t\\t\\tlet block = '';\\n\\t\\t\\t\\tattributeLines.forEach((line)=>{\\n\\t\\t\\t\\t\\t\\tconst words = ShaderProcessorGLSL.splitToWords(line);\\n\\t\\t\\t\\t\\t\\tlet type = words[0];\\n\\t\\t\\t\\t\\t\\tlet name = words[1];\\n\\t\\t\\t\\t\\t\\tif (shaderDefinitionAttributes.hasOwnProperty(name)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst semantic = shaderDefinitionAttributes[name];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst location = semanticToLocation[semantic];\\n\\t\\t\\t\\t\\t\\t\\t\\tattributesMap.set(location, name);\\n\\t\\t\\t\\t\\t\\t\\t\\tlet copyCode;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst element = processingOptions.getVertexElement(semantic);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (element) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst dataType = element.dataType;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (dataType !== TYPE_FLOAT32 && dataType !== TYPE_FLOAT16 && !element.normalize && !element.asInt) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst attribNumElements = ShaderProcessorGLSL.getTypeCount(type);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst newName = `_private_${name}`;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcopyCode = `vec${attribNumElements} ${name} = vec${attribNumElements}(${newName});\\\\n`;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tname = newName;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst isSignedType = dataType === TYPE_INT8 || dataType === TYPE_INT16 || dataType === TYPE_INT32;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (attribNumElements === 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = isSignedType ? 'int' : 'uint';\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = isSignedType ? `ivec${attribNumElements}` : `uvec${attribNumElements}`;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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\\tblock += `layout(location = ${location}) in ${type} ${name};\\\\n`;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (copyCode) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tblock += copyCode;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn block;\\n\\t\\t}\\n\\t\\tstatic splitToWords(line) {\\n\\t\\t\\t\\tline = line.replace(/\\\\s+/g, ' ').trim();\\n\\t\\t\\t\\treturn line.split(' ');\\n\\t\\t}\\n\\t\\tstatic cutOut(src, start, end, replacement) {\\n\\t\\t\\t\\treturn src.substring(0, start) + replacement + src.substring(end);\\n\\t\\t}\\n\\t\\tstatic getUniformShaderDeclaration(format, bindGroup, bindIndex) {\\n\\t\\t\\t\\tconst name = bindGroupNames[bindGroup];\\n\\t\\t\\t\\tlet code = `layout(set = ${bindGroup}, binding = ${bindIndex}, std140) uniform ub_${name} {\\\\n`;\\n\\t\\t\\t\\tformat.uniforms.forEach((uniform)=>{\\n\\t\\t\\t\\t\\t\\tconst typeString = uniformTypeToName[uniform.type];\\n\\t\\t\\t\\t\\t\\tcode += `    ${typeString} ${uniform.shortName}${uniform.count ? `[${uniform.count}]` : ''};\\\\n`;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn `${code}};\\\\n`;\\n\\t\\t}\\n\\t\\tstatic getTexturesShaderDeclaration(bindGroupFormat, bindGroup) {\\n\\t\\t\\t\\tlet code = '';\\n\\t\\t\\t\\tbindGroupFormat.textureFormats.forEach((format)=>{\\n\\t\\t\\t\\t\\t\\tlet textureType = textureDimensionInfo[format.textureDimension];\\n\\t\\t\\t\\t\\t\\tconst isArray = textureType === 'texture2DArray';\\n\\t\\t\\t\\t\\t\\tconst sampleTypePrefix = format.sampleType === SAMPLETYPE_UINT ? 'u' : format.sampleType === SAMPLETYPE_INT ? 'i' : '';\\n\\t\\t\\t\\t\\t\\ttextureType = `${sampleTypePrefix}${textureType}`;\\n\\t\\t\\t\\t\\t\\tlet namePostfix = '';\\n\\t\\t\\t\\t\\t\\tlet extraCode = '';\\n\\t\\t\\t\\t\\t\\tif (isArray) {\\n\\t\\t\\t\\t\\t\\t\\t\\tnamePostfix = '_texture';\\n\\t\\t\\t\\t\\t\\t\\t\\textraCode = `#define ${format.name} ${sampleTypePrefix}sampler2DArray(${format.name}${namePostfix}, ${format.name}_sampler)\\\\n`;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcode += `layout(set = ${bindGroup}, binding = ${format.slot}) uniform ${textureType} ${format.name}${namePostfix};\\\\n`;\\n\\t\\t\\t\\t\\t\\tif (format.hasSampler) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcode += `layout(set = ${bindGroup}, binding = ${format.slot + 1}) uniform sampler ${format.name}_sampler;\\\\n`;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcode += extraCode;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn code;\\n\\t\\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 textureBaseInfo = {\\n\\t\\t'texture_1d': {\\n\\t\\t\\t\\tviewDimension: TEXTUREDIMENSION_1D,\\n\\t\\t\\t\\tbaseSampleType: SAMPLETYPE_FLOAT\\n\\t\\t},\\n\\t\\t'texture_2d': {\\n\\t\\t\\t\\tviewDimension: TEXTUREDIMENSION_2D,\\n\\t\\t\\t\\tbaseSampleType: SAMPLETYPE_FLOAT\\n\\t\\t},\\n\\t\\t'texture_2d_array': {\\n\\t\\t\\t\\tviewDimension: TEXTUREDIMENSION_2D_ARRAY,\\n\\t\\t\\t\\tbaseSampleType: SAMPLETYPE_FLOAT\\n\\t\\t},\\n\\t\\t'texture_3d': {\\n\\t\\t\\t\\tviewDimension: TEXTUREDIMENSION_3D,\\n\\t\\t\\t\\tbaseSampleType: SAMPLETYPE_FLOAT\\n\\t\\t},\\n\\t\\t'texture_cube': {\\n\\t\\t\\t\\tviewDimension: TEXTUREDIMENSION_CUBE,\\n\\t\\t\\t\\tbaseSampleType: SAMPLETYPE_FLOAT\\n\\t\\t},\\n\\t\\t'texture_cube_array': {\\n\\t\\t\\t\\tviewDimension: TEXTUREDIMENSION_CUBE_ARRAY,\\n\\t\\t\\t\\tbaseSampleType: SAMPLETYPE_FLOAT\\n\\t\\t},\\n\\t\\t'texture_multisampled_2d': {\\n\\t\\t\\t\\tviewDimension: TEXTUREDIMENSION_2D,\\n\\t\\t\\t\\tbaseSampleType: SAMPLETYPE_FLOAT\\n\\t\\t},\\n\\t\\t'texture_depth_2d': {\\n\\t\\t\\t\\tviewDimension: TEXTUREDIMENSION_2D,\\n\\t\\t\\t\\tbaseSampleType: SAMPLETYPE_DEPTH\\n\\t\\t},\\n\\t\\t'texture_depth_2d_array': {\\n\\t\\t\\t\\tviewDimension: TEXTUREDIMENSION_2D_ARRAY,\\n\\t\\t\\t\\tbaseSampleType: SAMPLETYPE_DEPTH\\n\\t\\t},\\n\\t\\t'texture_depth_cube': {\\n\\t\\t\\t\\tviewDimension: TEXTUREDIMENSION_CUBE,\\n\\t\\t\\t\\tbaseSampleType: SAMPLETYPE_DEPTH\\n\\t\\t},\\n\\t\\t'texture_depth_cube_array': {\\n\\t\\t\\t\\tviewDimension: TEXTUREDIMENSION_CUBE_ARRAY,\\n\\t\\t\\t\\tbaseSampleType: SAMPLETYPE_DEPTH\\n\\t\\t},\\n\\t\\t'texture_external': {\\n\\t\\t\\t\\tviewDimension: TEXTUREDIMENSION_2D,\\n\\t\\t\\t\\tbaseSampleType: SAMPLETYPE_UNFILTERABLE_FLOAT\\n\\t\\t}\\n};\\nconst getTextureInfo = (baseType, componentType)=>{\\n\\t\\tconst baseInfo = textureBaseInfo[baseType];\\n\\t\\tlet finalSampleType = baseInfo.baseSampleType;\\n\\t\\tif (baseInfo.baseSampleType === SAMPLETYPE_FLOAT && baseType !== 'texture_multisampled_2d') {\\n\\t\\t\\t\\tswitch(componentType){\\n\\t\\t\\t\\t\\t\\tcase 'u32':\\n\\t\\t\\t\\t\\t\\t\\t\\tfinalSampleType = SAMPLETYPE_UINT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 'i32':\\n\\t\\t\\t\\t\\t\\t\\t\\tfinalSampleType = SAMPLETYPE_INT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 'f32':\\n\\t\\t\\t\\t\\t\\t\\t\\tfinalSampleType = SAMPLETYPE_FLOAT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 'uff':\\n\\t\\t\\t\\t\\t\\t\\t\\tfinalSampleType = SAMPLETYPE_UNFILTERABLE_FLOAT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn {\\n\\t\\t\\t\\tviewDimension: baseInfo.viewDimension,\\n\\t\\t\\t\\tsampleType: finalSampleType\\n\\t\\t};\\n};\\nconst getTextureDeclarationType = (viewDimension, sampleType)=>{\\n\\t\\tif (sampleType === SAMPLETYPE_DEPTH) {\\n\\t\\t\\t\\tswitch(viewDimension){\\n\\t\\t\\t\\t\\t\\tcase TEXTUREDIMENSION_2D:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 'texture_depth_2d';\\n\\t\\t\\t\\t\\t\\tcase TEXTUREDIMENSION_2D_ARRAY:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 'texture_depth_2d_array';\\n\\t\\t\\t\\t\\t\\tcase TEXTUREDIMENSION_CUBE:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 'texture_depth_cube';\\n\\t\\t\\t\\t\\t\\tcase TEXTUREDIMENSION_CUBE_ARRAY:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 'texture_depth_cube_array';\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tlet baseTypeString;\\n\\t\\tswitch(viewDimension){\\n\\t\\t\\t\\tcase TEXTUREDIMENSION_1D:\\n\\t\\t\\t\\t\\t\\tbaseTypeString = 'texture_1d';\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase TEXTUREDIMENSION_2D:\\n\\t\\t\\t\\t\\t\\tbaseTypeString = 'texture_2d';\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase TEXTUREDIMENSION_2D_ARRAY:\\n\\t\\t\\t\\t\\t\\tbaseTypeString = 'texture_2d_array';\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase TEXTUREDIMENSION_3D:\\n\\t\\t\\t\\t\\t\\tbaseTypeString = 'texture_3d';\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase TEXTUREDIMENSION_CUBE:\\n\\t\\t\\t\\t\\t\\tbaseTypeString = 'texture_cube';\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase TEXTUREDIMENSION_CUBE_ARRAY:\\n\\t\\t\\t\\t\\t\\tbaseTypeString = 'texture_cube_array';\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t}\\n\\t\\tlet coreFormatString;\\n\\t\\tswitch(sampleType){\\n\\t\\t\\t\\tcase SAMPLETYPE_FLOAT:\\n\\t\\t\\t\\tcase SAMPLETYPE_UNFILTERABLE_FLOAT:\\n\\t\\t\\t\\t\\t\\tcoreFormatString = 'f32';\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase SAMPLETYPE_UINT:\\n\\t\\t\\t\\t\\t\\tcoreFormatString = 'u32';\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\tcase SAMPLETYPE_INT:\\n\\t\\t\\t\\t\\t\\tcoreFormatString = 'i32';\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t}\\n\\t\\treturn `${baseTypeString}<${coreFormatString}>`;\\n};\\nconst wrappedArrayTypes = {\\n\\t\\t'f32': 'WrappedF32',\\n\\t\\t'i32': 'WrappedI32',\\n\\t\\t'u32': 'WrappedU32',\\n\\t\\t'vec2f': 'WrappedVec2F',\\n\\t\\t'vec2i': 'WrappedVec2I',\\n\\t\\t'vec2u': 'WrappedVec2U'\\n};\\nconst splitToWords = (line)=>{\\n\\t\\tline = line.replace(/\\\\s+/g, ' ').trim();\\n\\t\\treturn line.split(/[\\\\s:]+/);\\n};\\nconst UNIFORM_ARRAY_REGEX = /array<([^,]+),\\\\s*([^>]+)>/;\\nclass UniformLine {\\n\\t\\tconstructor(line, shader){\\n\\t\\t\\t\\tthis.ubName = null;\\n\\t\\t\\t\\tthis.arraySize = 0;\\n\\t\\t\\t\\tthis.line = line;\\n\\t\\t\\t\\tconst parts = splitToWords(line);\\n\\t\\t\\t\\tif (parts.length < 2) {\\n\\t\\t\\t\\t\\t\\tshader.failed = true;\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.name = parts[0];\\n\\t\\t\\t\\tthis.type = parts.slice(1).join(' ');\\n\\t\\t\\t\\tif (this.type.includes('array<')) {\\n\\t\\t\\t\\t\\t\\tconst match = UNIFORM_ARRAY_REGEX.exec(this.type);\\n\\t\\t\\t\\t\\t\\tthis.type = match[1].trim();\\n\\t\\t\\t\\t\\t\\tthis.arraySize = Number(match[2]);\\n\\t\\t\\t\\t\\t\\tif (isNaN(this.arraySize)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tshader.failed = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\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\\t\\tequals(other) {\\n\\t\\t\\t\\tif (this.name !== other.name) return false;\\n\\t\\t\\t\\tif (this.type !== other.type) return false;\\n\\t\\t\\t\\tif (this.isTexture !== other.isTexture) return false;\\n\\t\\t\\t\\tif (this.isSampler !== other.isSampler) return false;\\n\\t\\t\\t\\tif (this.isStorageTexture !== other.isStorageTexture) return false;\\n\\t\\t\\t\\tif (this.isStorageBuffer !== other.isStorageBuffer) return false;\\n\\t\\t\\t\\tif (this.isExternalTexture !== other.isExternalTexture) return false;\\n\\t\\t\\t\\tif (this.textureFormat !== other.textureFormat) return false;\\n\\t\\t\\t\\tif (this.textureDimension !== other.textureDimension) return false;\\n\\t\\t\\t\\tif (this.sampleType !== other.sampleType) return false;\\n\\t\\t\\t\\tif (this.textureType !== other.textureType) return false;\\n\\t\\t\\t\\tif (this.format !== other.format) return false;\\n\\t\\t\\t\\tif (this.access !== other.access) return false;\\n\\t\\t\\t\\tif (this.accessMode !== other.accessMode) return false;\\n\\t\\t\\t\\tif (this.samplerType !== other.samplerType) return false;\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tconstructor(line, shader){\\n\\t\\t\\t\\tthis.originalLine = line;\\n\\t\\t\\t\\tthis.line = line;\\n\\t\\t\\t\\tthis.isTexture = false;\\n\\t\\t\\t\\tthis.isSampler = false;\\n\\t\\t\\t\\tthis.isStorageTexture = false;\\n\\t\\t\\t\\tthis.isStorageBuffer = false;\\n\\t\\t\\t\\tthis.isExternalTexture = false;\\n\\t\\t\\t\\tthis.type = '';\\n\\t\\t\\t\\tthis.matchedElements = [];\\n\\t\\t\\t\\tconst textureMatch = this.line.match(TEXTURE_REGEX);\\n\\t\\t\\t\\tif (textureMatch) {\\n\\t\\t\\t\\t\\t\\tthis.name = textureMatch[1];\\n\\t\\t\\t\\t\\t\\tthis.type = textureMatch[2];\\n\\t\\t\\t\\t\\t\\tthis.textureFormat = textureMatch[3];\\n\\t\\t\\t\\t\\t\\tthis.isTexture = true;\\n\\t\\t\\t\\t\\t\\tthis.matchedElements.push(...textureMatch);\\n\\t\\t\\t\\t\\t\\tconst info = getTextureInfo(this.type, this.textureFormat);\\n\\t\\t\\t\\t\\t\\tthis.textureDimension = info.viewDimension;\\n\\t\\t\\t\\t\\t\\tthis.sampleType = info.sampleType;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst storageTextureMatch = this.line.match(STORAGE_TEXTURE_REGEX);\\n\\t\\t\\t\\tif (storageTextureMatch) {\\n\\t\\t\\t\\t\\t\\tthis.isStorageTexture = true;\\n\\t\\t\\t\\t\\t\\tthis.name = storageTextureMatch[1];\\n\\t\\t\\t\\t\\t\\tthis.textureType = storageTextureMatch[2];\\n\\t\\t\\t\\t\\t\\tthis.format = storageTextureMatch[3];\\n\\t\\t\\t\\t\\t\\tthis.access = storageTextureMatch[4];\\n\\t\\t\\t\\t\\t\\tthis.matchedElements.push(...storageTextureMatch);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst storageBufferMatch = this.line.match(STORAGE_BUFFER_REGEX);\\n\\t\\t\\t\\tif (storageBufferMatch) {\\n\\t\\t\\t\\t\\t\\tthis.isStorageBuffer = true;\\n\\t\\t\\t\\t\\t\\tthis.accessMode = storageBufferMatch[1] || 'none';\\n\\t\\t\\t\\t\\t\\tthis.name = storageBufferMatch[2];\\n\\t\\t\\t\\t\\t\\tthis.type = storageBufferMatch[3];\\n\\t\\t\\t\\t\\t\\tthis.matchedElements.push(...storageBufferMatch);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst externalTextureMatch = this.line.match(EXTERNAL_TEXTURE_REGEX);\\n\\t\\t\\t\\tif (externalTextureMatch) {\\n\\t\\t\\t\\t\\t\\tthis.name = externalTextureMatch[1];\\n\\t\\t\\t\\t\\t\\tthis.isExternalTexture = true;\\n\\t\\t\\t\\t\\t\\tthis.matchedElements.push(...storageBufferMatch);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst samplerMatch = this.line.match(SAMPLER_REGEX);\\n\\t\\t\\t\\tif (samplerMatch) {\\n\\t\\t\\t\\t\\t\\tthis.name = samplerMatch[1];\\n\\t\\t\\t\\t\\t\\tthis.samplerType = samplerMatch[2];\\n\\t\\t\\t\\t\\t\\tthis.isSampler = true;\\n\\t\\t\\t\\t\\t\\tthis.matchedElements.push(...samplerMatch);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.matchedElements.length === 0) {\\n\\t\\t\\t\\t\\t\\tshader.failed = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nclass WebgpuShaderProcessorWGSL {\\n\\t\\tstatic run(device, shaderDefinition, shader) {\\n\\t\\t\\t\\tconst varyingMap = new Map();\\n\\t\\t\\t\\tconst vertexExtracted = WebgpuShaderProcessorWGSL.extract(shaderDefinition.vshader);\\n\\t\\t\\t\\tconst fragmentExtracted = WebgpuShaderProcessorWGSL.extract(shaderDefinition.fshader);\\n\\t\\t\\t\\tconst attributesMap = new Map();\\n\\t\\t\\t\\tconst attributesBlock = WebgpuShaderProcessorWGSL.processAttributes(vertexExtracted.attributes, shaderDefinition.attributes, attributesMap, shaderDefinition.processingOptions, shader);\\n\\t\\t\\t\\tconst vertexVaryingsBlock = WebgpuShaderProcessorWGSL.processVaryings(vertexExtracted.varyings, varyingMap, true, device);\\n\\t\\t\\t\\tconst fragmentVaryingsBlock = WebgpuShaderProcessorWGSL.processVaryings(fragmentExtracted.varyings, varyingMap, false, device);\\n\\t\\t\\t\\tconst concatUniforms = vertexExtracted.uniforms.concat(fragmentExtracted.uniforms);\\n\\t\\t\\t\\tconst uniforms = Array.from(new Set(concatUniforms));\\n\\t\\t\\t\\tconst parsedUniforms = uniforms.map((line)=>new UniformLine(line, shader));\\n\\t\\t\\t\\tconst uniformsData = WebgpuShaderProcessorWGSL.processUniforms(device, parsedUniforms, shaderDefinition.processingOptions, shader);\\n\\t\\t\\t\\tvertexExtracted.src = WebgpuShaderProcessorWGSL.renameUniformAccess(vertexExtracted.src, parsedUniforms);\\n\\t\\t\\t\\tfragmentExtracted.src = WebgpuShaderProcessorWGSL.renameUniformAccess(fragmentExtracted.src, parsedUniforms);\\n\\t\\t\\t\\tconst parsedResources = WebgpuShaderProcessorWGSL.mergeResources(vertexExtracted.resources, fragmentExtracted.resources, shader);\\n\\t\\t\\t\\tconst resourcesData = WebgpuShaderProcessorWGSL.processResources(device, parsedResources, shaderDefinition.processingOptions, shader);\\n\\t\\t\\t\\tconst fOutput = WebgpuShaderProcessorWGSL.generateFragmentOutputStruct(fragmentExtracted.src, device.maxColorAttachments);\\n\\t\\t\\t\\tvertexExtracted.src = WebgpuShaderProcessorWGSL.copyInputs(vertexExtracted.src, shader);\\n\\t\\t\\t\\tfragmentExtracted.src = WebgpuShaderProcessorWGSL.copyInputs(fragmentExtracted.src, shader);\\n\\t\\t\\t\\tconst vBlock = `${attributesBlock}\\\\n${vertexVaryingsBlock}\\\\n${uniformsData.code}\\\\n${resourcesData.code}\\\\n`;\\n\\t\\t\\t\\tconst vshader = vertexExtracted.src.replace(MARKER, vBlock);\\n\\t\\t\\t\\tconst fBlock = `${fragmentVaryingsBlock}\\\\n${fOutput}\\\\n${uniformsData.code}\\\\n${resourcesData.code}\\\\n`;\\n\\t\\t\\t\\tconst fshader = fragmentExtracted.src.replace(MARKER, fBlock);\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tvshader: vshader,\\n\\t\\t\\t\\t\\t\\tfshader: fshader,\\n\\t\\t\\t\\t\\t\\tattributes: attributesMap,\\n\\t\\t\\t\\t\\t\\tmeshUniformBufferFormat: uniformsData.meshUniformBufferFormat,\\n\\t\\t\\t\\t\\t\\tmeshBindGroupFormat: resourcesData.meshBindGroupFormat\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tstatic extract(src) {\\n\\t\\t\\t\\tconst attributes = [];\\n\\t\\t\\t\\tconst varyings = [];\\n\\t\\t\\t\\tconst uniforms = [];\\n\\t\\t\\t\\tconst resources = [];\\n\\t\\t\\t\\tlet replacement = `${MARKER}\\\\n`;\\n\\t\\t\\t\\tlet match;\\n\\t\\t\\t\\twhile((match = KEYWORD$1.exec(src)) !== null){\\n\\t\\t\\t\\t\\t\\tconst keyword = match[1];\\n\\t\\t\\t\\t\\t\\tKEYWORD_LINE.lastIndex = match.index;\\n\\t\\t\\t\\t\\t\\tconst lineMatch = KEYWORD_LINE.exec(src);\\n\\t\\t\\t\\t\\t\\tif (keyword === 'attribute') {\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes.push(lineMatch[2]);\\n\\t\\t\\t\\t\\t\\t} else if (keyword === 'varying') {\\n\\t\\t\\t\\t\\t\\t\\t\\tvaryings.push(lineMatch[2]);\\n\\t\\t\\t\\t\\t\\t} else if (keyword === 'uniform') {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniforms.push(lineMatch[2]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tsrc = WebgpuShaderProcessorWGSL.cutOut(src, match.index, KEYWORD_LINE.lastIndex, replacement);\\n\\t\\t\\t\\t\\t\\tKEYWORD$1.lastIndex = match.index + replacement.length;\\n\\t\\t\\t\\t\\t\\treplacement = '';\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\twhile((match = KEYWORD_RESOURCE.exec(src)) !== null){\\n\\t\\t\\t\\t\\t\\tresources.push(match[0]);\\n\\t\\t\\t\\t\\t\\tsrc = WebgpuShaderProcessorWGSL.cutOut(src, match.index, KEYWORD_RESOURCE.lastIndex, replacement);\\n\\t\\t\\t\\t\\t\\tKEYWORD_RESOURCE.lastIndex = match.index + replacement.length;\\n\\t\\t\\t\\t\\t\\treplacement = '';\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tsrc,\\n\\t\\t\\t\\t\\t\\tattributes,\\n\\t\\t\\t\\t\\t\\tvaryings,\\n\\t\\t\\t\\t\\t\\tuniforms,\\n\\t\\t\\t\\t\\t\\tresources\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tstatic processUniforms(device, uniforms, processingOptions, shader) {\\n\\t\\t\\t\\tconst meshUniforms = [];\\n\\t\\t\\t\\tuniforms.forEach((uniform)=>{\\n\\t\\t\\t\\t\\t\\tif (!processingOptions.hasUniform(uniform.name)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniform.ubName = 'ub_mesh_ub';\\n\\t\\t\\t\\t\\t\\t\\t\\tconst uniformType = uniformTypeToNameMapWGSL.get(uniform.type);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst uniformFormat = new UniformFormat(uniform.name, uniformType, uniform.arraySize);\\n\\t\\t\\t\\t\\t\\t\\t\\tmeshUniforms.push(uniformFormat);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniform.ubName = 'ub_view';\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (meshUniforms.length === 0) {\\n\\t\\t\\t\\t\\t\\tmeshUniforms.push(new UniformFormat(UNUSED_UNIFORM_NAME, UNIFORMTYPE_FLOAT));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst meshUniformBufferFormat = new UniformBufferFormat(device, meshUniforms);\\n\\t\\t\\t\\tlet code = '';\\n\\t\\t\\t\\tprocessingOptions.uniformFormats.forEach((format, bindGroupIndex)=>{\\n\\t\\t\\t\\t\\t\\tif (format) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcode += WebgpuShaderProcessorWGSL.getUniformShaderDeclaration(format, bindGroupIndex, 0);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (meshUniformBufferFormat) {\\n\\t\\t\\t\\t\\t\\tcode += WebgpuShaderProcessorWGSL.getUniformShaderDeclaration(meshUniformBufferFormat, BINDGROUP_MESH_UB, 0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tcode,\\n\\t\\t\\t\\t\\t\\tmeshUniformBufferFormat\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tstatic renameUniformAccess(source, uniforms) {\\n\\t\\t\\t\\tuniforms.forEach((uniform)=>{\\n\\t\\t\\t\\t\\t\\tconst srcName = `uniform.${uniform.name}`;\\n\\t\\t\\t\\t\\t\\tconst dstName = `${uniform.ubName}.${uniform.name}`;\\n\\t\\t\\t\\t\\t\\tconst regex = new RegExp(`\\\\\\\\b${srcName}\\\\\\\\b`, 'g');\\n\\t\\t\\t\\t\\t\\tsource = source.replace(regex, dstName);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn source;\\n\\t\\t}\\n\\t\\tstatic mergeResources(vertex, fragment, shader) {\\n\\t\\t\\t\\tconst resources = vertex.map((line)=>new ResourceLine(line, shader));\\n\\t\\t\\t\\tconst fragmentResources = fragment.map((line)=>new ResourceLine(line, shader));\\n\\t\\t\\t\\tfragmentResources.forEach((fragmentResource)=>{\\n\\t\\t\\t\\t\\t\\tconst existing = resources.find((resource)=>resource.name === fragmentResource.name);\\n\\t\\t\\t\\t\\t\\tif (existing) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!existing.equals(fragmentResource)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshader.failed = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tresources.push(fragmentResource);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn resources;\\n\\t\\t}\\n\\t\\tstatic processResources(device, resources, processingOptions, shader) {\\n\\t\\t\\t\\tconst textureFormats = [];\\n\\t\\t\\t\\tfor(let i = 0; i < resources.length; i++){\\n\\t\\t\\t\\t\\t\\tconst resource = resources[i];\\n\\t\\t\\t\\t\\t\\tif (resource.isTexture) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst sampler = resources[i + 1];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst hasSampler = sampler?.isSampler;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst sampleType = resource.sampleType;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dimension = resource.textureDimension;\\n\\t\\t\\t\\t\\t\\t\\t\\ttextureFormats.push(new BindTextureFormat(resource.name, SHADERSTAGE_VERTEX | SHADERSTAGE_FRAGMENT, dimension, sampleType, hasSampler, hasSampler ? sampler.name : null));\\n\\t\\t\\t\\t\\t\\t\\t\\tif (hasSampler) i++;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (resource.isStorageBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst readOnly = resource.accessMode !== 'read_write';\\n\\t\\t\\t\\t\\t\\t\\t\\tconst bufferFormat = new BindStorageBufferFormat(resource.name, SHADERSTAGE_VERTEX | SHADERSTAGE_FRAGMENT, readOnly);\\n\\t\\t\\t\\t\\t\\t\\t\\tbufferFormat.format = resource.type;\\n\\t\\t\\t\\t\\t\\t\\t\\ttextureFormats.push(bufferFormat);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst meshBindGroupFormat = new BindGroupFormat(device, textureFormats);\\n\\t\\t\\t\\tlet code = '';\\n\\t\\t\\t\\tprocessingOptions.bindGroupFormats.forEach((format, bindGroupIndex)=>{\\n\\t\\t\\t\\t\\t\\tif (format) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcode += WebgpuShaderProcessorWGSL.getTextureShaderDeclaration(format, bindGroupIndex);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tcode += WebgpuShaderProcessorWGSL.getTextureShaderDeclaration(meshBindGroupFormat, BINDGROUP_MESH);\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tcode,\\n\\t\\t\\t\\t\\t\\tmeshBindGroupFormat\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tstatic getUniformShaderDeclaration(ubFormat, bindGroup, bindIndex) {\\n\\t\\t\\t\\tconst name = bindGroupNames[bindGroup];\\n\\t\\t\\t\\tconst structName = `struct_ub_${name}`;\\n\\t\\t\\t\\tlet code = `struct ${structName} {\\\\n`;\\n\\t\\t\\t\\tubFormat.uniforms.forEach((uniform)=>{\\n\\t\\t\\t\\t\\t\\tlet typeString = uniformTypeToNameWGSL[uniform.type][0];\\n\\t\\t\\t\\t\\t\\tif (uniform.count > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (wrappedArrayTypes.hasOwnProperty(typeString)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttypeString = wrappedArrayTypes[typeString];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tcode += `    ${uniform.shortName}: array<${typeString}, ${uniform.count}>,\\\\n`;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tcode += `    ${uniform.shortName}: ${typeString},\\\\n`;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tcode += '};\\\\n';\\n\\t\\t\\t\\tcode += `@group(${bindGroup}) @binding(${bindIndex}) var<uniform> ub_${name} : ${structName};\\\\n\\\\n`;\\n\\t\\t\\t\\treturn code;\\n\\t\\t}\\n\\t\\tstatic getTextureShaderDeclaration(format, bindGroup) {\\n\\t\\t\\t\\tlet code = '';\\n\\t\\t\\t\\tformat.textureFormats.forEach((format)=>{\\n\\t\\t\\t\\t\\t\\tconst textureTypeName = getTextureDeclarationType(format.textureDimension, format.sampleType);\\n\\t\\t\\t\\t\\t\\tcode += `@group(${bindGroup}) @binding(${format.slot}) var ${format.name}: ${textureTypeName};\\\\n`;\\n\\t\\t\\t\\t\\t\\tif (format.hasSampler) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst samplerName = format.sampleType === SAMPLETYPE_DEPTH ? 'sampler_comparison' : 'sampler';\\n\\t\\t\\t\\t\\t\\t\\t\\tcode += `@group(${bindGroup}) @binding(${format.slot + 1}) var ${format.samplerName}: ${samplerName};\\\\n`;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tformat.storageBufferFormats.forEach((format)=>{\\n\\t\\t\\t\\t\\t\\tconst access = format.readOnly ? 'read' : 'read_write';\\n\\t\\t\\t\\t\\t\\tcode += `@group(${bindGroup}) @binding(${format.slot}) var<storage, ${access}> ${format.name} : ${format.format};\\\\n`;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn code;\\n\\t\\t}\\n\\t\\tstatic processVaryings(varyingLines, varyingMap, isVertex, device) {\\n\\t\\t\\t\\tlet block = '';\\n\\t\\t\\t\\tlet blockPrivates = '';\\n\\t\\t\\t\\tlet blockCopy = '';\\n\\t\\t\\t\\tvaryingLines.forEach((line, index)=>{\\n\\t\\t\\t\\t\\t\\tconst match = line.match(VARYING);\\n\\t\\t\\t\\t\\t\\tif (match) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst name = match[1];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst type = match[2];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (isVertex) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvaryingMap.set(name, index);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindex = varyingMap.get(name);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tblock += `    @location(${index}) ${line},\\\\n`;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!isVertex) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tblockPrivates += `    var<private> ${name}: ${type};\\\\n`;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tblockCopy += `    ${name} = input.${name};\\\\n`;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (isVertex) {\\n\\t\\t\\t\\t\\t\\tblock += '    @builtin(position) position : vec4f,\\\\n';\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tblock += '    @builtin(position) position : vec4f,\\\\n';\\n\\t\\t\\t\\t\\t\\tblock += '    @builtin(front_facing) frontFacing : bool,\\\\n';\\n\\t\\t\\t\\t\\t\\tblock += '    @builtin(sample_index) sampleIndex : u32,\\\\n';\\n\\t\\t\\t\\t\\t\\tif (device.supportsPrimitiveIndex) {\\n\\t\\t\\t\\t\\t\\t\\t\\tblock += '    @builtin(primitive_index) primitiveIndex : u32,\\\\n';\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst primitiveIndexGlobals = device.supportsPrimitiveIndex ? `\\n\\t\\t\\t\\t\\t\\tvar<private> pcPrimitiveIndex: u32;\\n\\t\\t\\t\\t` : '';\\n\\t\\t\\t\\tconst primitiveIndexCopy = device.supportsPrimitiveIndex ? `\\n\\t\\t\\t\\t\\t\\t\\t\\tpcPrimitiveIndex = input.primitiveIndex;\\n\\t\\t\\t\\t` : '';\\n\\t\\t\\t\\tconst fragmentGlobals = isVertex ? '' : `\\n\\t\\t\\t\\t\\t\\tvar<private> pcPosition: vec4f;\\n\\t\\t\\t\\t\\t\\tvar<private> pcFrontFacing: bool;\\n\\t\\t\\t\\t\\t\\tvar<private> pcSampleIndex: u32;\\n\\t\\t\\t\\t\\t\\t${primitiveIndexGlobals}\\n\\t\\t\\t\\t\\t\\t${blockPrivates}\\n\\t\\t\\t\\t\\t\\t\\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\\tpcPosition = input.position;\\n\\t\\t\\t\\t\\t\\t\\t\\tpcFrontFacing = input.frontFacing;\\n\\t\\t\\t\\t\\t\\t\\t\\tpcSampleIndex = input.sampleIndex;\\n\\t\\t\\t\\t\\t\\t\\t\\t${primitiveIndexCopy}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t`;\\n\\t\\t\\t\\tconst structName = isVertex ? 'VertexOutput' : 'FragmentInput';\\n\\t\\t\\t\\treturn `\\n\\t\\t\\t\\t\\t\\tstruct ${structName} {\\n\\t\\t\\t\\t\\t\\t\\t\\t${block}\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t${fragmentGlobals}\\n\\t\\t\\t\\t`;\\n\\t\\t}\\n\\t\\tstatic generateFragmentOutputStruct(src, numRenderTargets) {\\n\\t\\t\\t\\tlet structCode = 'struct FragmentOutput {\\\\n';\\n\\t\\t\\t\\tconst colorName = (i)=>`color${i > 0 ? i : ''}`;\\n\\t\\t\\t\\tfor(let i = 0; i < numRenderTargets; i++){\\n\\t\\t\\t\\t\\t\\tconst name = colorName(i);\\n\\t\\t\\t\\t\\t\\tif (src.search(new RegExp(`\\\\\\\\.${name}\\\\\\\\s*=`)) !== -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tstructCode += `    @location(${i}) ${name} : pcOutType${i},\\\\n`;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst needsFragDepth = src.search(/\\\\.fragDepth\\\\s*=/) !== -1;\\n\\t\\t\\t\\tif (needsFragDepth) {\\n\\t\\t\\t\\t\\t\\tstructCode += '    @builtin(frag_depth) fragDepth : f32\\\\n';\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn `${structCode}};\\\\n`;\\n\\t\\t}\\n\\t\\tstatic floatAttributeToInt(type, signed) {\\n\\t\\t\\t\\tconst longToShortMap = {\\n\\t\\t\\t\\t\\t\\t'f32': 'f32',\\n\\t\\t\\t\\t\\t\\t'vec2<f32>': 'vec2f',\\n\\t\\t\\t\\t\\t\\t'vec3<f32>': 'vec3f',\\n\\t\\t\\t\\t\\t\\t'vec4<f32>': 'vec4f'\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst shortType = longToShortMap[type] || type;\\n\\t\\t\\t\\tconst floatToIntShort = {\\n\\t\\t\\t\\t\\t\\t'f32': signed ? 'i32' : 'u32',\\n\\t\\t\\t\\t\\t\\t'vec2f': signed ? 'vec2i' : 'vec2u',\\n\\t\\t\\t\\t\\t\\t'vec3f': signed ? 'vec3i' : 'vec3u',\\n\\t\\t\\t\\t\\t\\t'vec4f': signed ? 'vec4i' : 'vec4u'\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\treturn floatToIntShort[shortType] || null;\\n\\t\\t}\\n\\t\\tstatic processAttributes(attributeLines, shaderDefinitionAttributes = {}, attributesMap, processingOptions, shader) {\\n\\t\\t\\t\\tlet blockAttributes = '';\\n\\t\\t\\t\\tlet blockPrivates = '';\\n\\t\\t\\t\\tlet blockCopy = '';\\n\\t\\t\\t\\tattributeLines.forEach((line)=>{\\n\\t\\t\\t\\t\\t\\tconst words = splitToWords(line);\\n\\t\\t\\t\\t\\t\\tconst name = words[0];\\n\\t\\t\\t\\t\\t\\tlet type = words[1];\\n\\t\\t\\t\\t\\t\\tconst originalType = type;\\n\\t\\t\\t\\t\\t\\tif (shaderDefinitionAttributes.hasOwnProperty(name)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst semantic = shaderDefinitionAttributes[name];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst location = semanticToLocation[semantic];\\n\\t\\t\\t\\t\\t\\t\\t\\tattributesMap.set(location, name);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst element = processingOptions.getVertexElement(semantic);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (element) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst dataType = element.dataType;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (dataType !== TYPE_FLOAT32 && dataType !== TYPE_FLOAT16 && !element.normalize && !element.asInt) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst isSignedType = dataType === TYPE_INT8 || dataType === TYPE_INT16 || dataType === TYPE_INT32;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = WebgpuShaderProcessorWGSL.floatAttributeToInt(type, isSignedType);\\n\\t\\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\\tblockAttributes += `    @location(${location}) ${name}: ${type},\\\\n`;\\n\\t\\t\\t\\t\\t\\t\\t\\tblockPrivates += `    var<private> ${line};\\\\n`;\\n\\t\\t\\t\\t\\t\\t\\t\\tblockCopy += `    ${name} = ${originalType}(input.${name});\\\\n`;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\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@builtin(vertex_index) vertexIndex : u32,       // built-in vertex index\\n\\t\\t\\t\\t\\t\\t\\t\\t@builtin(instance_index) instanceIndex : u32    // built-in instance index\\n\\t\\t\\t\\t\\t\\t};\\n\\n\\t\\t\\t\\t\\t\\t${blockPrivates}\\n\\t\\t\\t\\t\\t\\tvar<private> pcVertexIndex: u32;\\n\\t\\t\\t\\t\\t\\tvar<private> pcInstanceIndex: u32;\\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\\tpcVertexIndex = input.vertexIndex;\\n\\t\\t\\t\\t\\t\\t\\t\\tpcInstanceIndex = input.instanceIndex;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t`;\\n\\t\\t}\\n\\t\\tstatic copyInputs(src, shader) {\\n\\t\\t\\t\\tconst match = src.match(ENTRY_FUNCTION);\\n\\t\\t\\t\\tif (!match || !match[2]) {\\n\\t\\t\\t\\t\\t\\treturn src;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst inputName = match[2];\\n\\t\\t\\t\\tconst braceIndex = match.index + match[0].length - 1;\\n\\t\\t\\t\\tconst beginning = src.slice(0, braceIndex + 1);\\n\\t\\t\\t\\tconst end = src.slice(braceIndex + 1);\\n\\t\\t\\t\\tconst lineToInject = `\\\\n    _pcCopyInputs(${inputName});`;\\n\\t\\t\\t\\treturn beginning + lineToInject + end;\\n\\t\\t}\\n\\t\\tstatic cutOut(src, start, end, replacement) {\\n\\t\\t\\t\\treturn src.substring(0, start) + replacement + src.substring(end);\\n\\t\\t}\\n}\\n\\nconst computeShaderIds = new StringIds();\\nclass WebgpuShader {\\n\\t\\tdestroy(shader) {\\n\\t\\t\\t\\tthis._vertexCode = null;\\n\\t\\t\\t\\tthis._fragmentCode = null;\\n\\t\\t}\\n\\t\\tcreateShaderModule(code, shaderType) {\\n\\t\\t\\t\\tconst device = this.shader.device;\\n\\t\\t\\t\\tconst wgpu = device.wgpu;\\n\\t\\t\\t\\tconst shaderModule = wgpu.createShaderModule({\\n\\t\\t\\t\\t\\t\\tcode: code\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn shaderModule;\\n\\t\\t}\\n\\t\\tgetVertexShaderModule() {\\n\\t\\t\\t\\treturn this.createShaderModule(this._vertexCode, 'Vertex');\\n\\t\\t}\\n\\t\\tgetFragmentShaderModule() {\\n\\t\\t\\t\\treturn this.createShaderModule(this._fragmentCode, 'Fragment');\\n\\t\\t}\\n\\t\\tgetComputeShaderModule() {\\n\\t\\t\\t\\treturn this.createShaderModule(this._computeCode, 'Compute');\\n\\t\\t}\\n\\t\\tprocessGLSL() {\\n\\t\\t\\t\\tconst shader = this.shader;\\n\\t\\t\\t\\tconst processed = ShaderProcessorGLSL.run(shader.device, shader.definition, shader);\\n\\t\\t\\t\\tthis._vertexCode = this.transpile(processed.vshader, 'vertex', shader.definition.vshader);\\n\\t\\t\\t\\tthis._fragmentCode = this.transpile(processed.fshader, 'fragment', shader.definition.fshader);\\n\\t\\t\\t\\tif (!(this._vertexCode && this._fragmentCode)) {\\n\\t\\t\\t\\t\\t\\tshader.failed = true;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tshader.ready = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tshader.meshUniformBufferFormat = processed.meshUniformBufferFormat;\\n\\t\\t\\t\\tshader.meshBindGroupFormat = processed.meshBindGroupFormat;\\n\\t\\t\\t\\tshader.attributes = processed.attributes;\\n\\t\\t}\\n\\t\\tprocessWGSL() {\\n\\t\\t\\t\\tconst shader = this.shader;\\n\\t\\t\\t\\tconst processed = WebgpuShaderProcessorWGSL.run(shader.device, shader.definition, shader);\\n\\t\\t\\t\\tthis._vertexCode = processed.vshader;\\n\\t\\t\\t\\tthis._fragmentCode = processed.fshader;\\n\\t\\t\\t\\tshader.meshUniformBufferFormat = processed.meshUniformBufferFormat;\\n\\t\\t\\t\\tshader.meshBindGroupFormat = processed.meshBindGroupFormat;\\n\\t\\t\\t\\tshader.attributes = processed.attributes;\\n\\t\\t}\\n\\t\\ttranspile(src, shaderType, originalSrc) {\\n\\t\\t\\t\\tconst device = this.shader.device;\\n\\t\\t\\t\\tif (!device.glslang || !device.twgsl) {\\n\\t\\t\\t\\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\\t\\t\\t\\t\\tshader: this.shader\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\tconst spirv = device.glslang.compileGLSL(src, shaderType);\\n\\t\\t\\t\\t\\t\\tconst wgsl = device.twgsl.convertSpirV2WGSL(spirv);\\n\\t\\t\\t\\t\\t\\treturn wgsl;\\n\\t\\t\\t\\t} catch (err) {\\n\\t\\t\\t\\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\\t\\t\\t\\t\\tprocessed: src,\\n\\t\\t\\t\\t\\t\\t\\t\\toriginal: originalSrc,\\n\\t\\t\\t\\t\\t\\t\\t\\tshader: this.shader,\\n\\t\\t\\t\\t\\t\\t\\t\\terror: err,\\n\\t\\t\\t\\t\\t\\t\\t\\tstack: err.stack\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget vertexCode() {\\n\\t\\t\\t\\treturn this._vertexCode;\\n\\t\\t}\\n\\t\\tget fragmentCode() {\\n\\t\\t\\t\\treturn this._fragmentCode;\\n\\t\\t}\\n\\t\\tget computeKey() {\\n\\t\\t\\t\\tif (this._computeKey === undefined) {\\n\\t\\t\\t\\t\\t\\tconst keyString = `${this._computeCode}|${this.computeEntryPoint}`;\\n\\t\\t\\t\\t\\t\\tthis._computeKey = computeShaderIds.get(keyString);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._computeKey;\\n\\t\\t}\\n\\t\\tloseContext() {}\\n\\t\\trestoreContext(device, shader) {}\\n\\t\\tconstructor(shader){\\n\\t\\t\\t\\tthis._vertexCode = null;\\n\\t\\t\\t\\tthis._fragmentCode = null;\\n\\t\\t\\t\\tthis._computeCode = null;\\n\\t\\t\\t\\tthis.vertexEntryPoint = 'main';\\n\\t\\t\\t\\tthis.fragmentEntryPoint = 'main';\\n\\t\\t\\t\\tthis.computeEntryPoint = 'main';\\n\\t\\t\\t\\tthis.shader = shader;\\n\\t\\t\\t\\tconst definition = shader.definition;\\n\\t\\t\\t\\tif (definition.shaderLanguage === SHADERLANGUAGE_WGSL) {\\n\\t\\t\\t\\t\\t\\tif (definition.cshader) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._computeCode = definition.cshader ?? null;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.computeUniformBufferFormats = definition.computeUniformBufferFormats;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.computeBindGroupFormat = definition.computeBindGroupFormat;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (definition.computeEntryPoint) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.computeEntryPoint = definition.computeEntryPoint;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.vertexEntryPoint = 'vertexMain';\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fragmentEntryPoint = 'fragmentMain';\\n\\t\\t\\t\\t\\t\\t\\t\\tif (definition.processingOptions) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.processWGSL();\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._vertexCode = definition.vshader ?? null;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._fragmentCode = definition.fshader ?? null;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshader.meshUniformBufferFormat = definition.meshUniformBufferFormat;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshader.meshBindGroupFormat = definition.meshBindGroupFormat;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tshader.ready = true;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (definition.processingOptions) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.processGLSL();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\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] = {\\n\\t\\tlevel: 'nearest',\\n\\t\\tmip: 'nearest'\\n};\\ngpuFilterModes[FILTER_LINEAR] = {\\n\\t\\tlevel: 'linear',\\n\\t\\tmip: 'nearest'\\n};\\ngpuFilterModes[FILTER_NEAREST_MIPMAP_NEAREST] = {\\n\\t\\tlevel: 'nearest',\\n\\t\\tmip: 'nearest'\\n};\\ngpuFilterModes[FILTER_NEAREST_MIPMAP_LINEAR] = {\\n\\t\\tlevel: 'nearest',\\n\\t\\tmip: 'linear'\\n};\\ngpuFilterModes[FILTER_LINEAR_MIPMAP_NEAREST] = {\\n\\t\\tlevel: 'linear',\\n\\t\\tmip: 'nearest'\\n};\\ngpuFilterModes[FILTER_LINEAR_MIPMAP_LINEAR] = {\\n\\t\\tlevel: 'linear',\\n\\t\\tmip: 'linear'\\n};\\nconst dummyUse = (thingOne)=>{};\\nclass WebgpuTexture {\\n\\t\\tcreate(device) {\\n\\t\\t\\t\\tconst texture = this.texture;\\n\\t\\t\\t\\tconst wgpu = device.wgpu;\\n\\t\\t\\t\\tconst numLevels = texture.numLevels;\\n\\t\\t\\t\\tthis.desc = {\\n\\t\\t\\t\\t\\t\\tsize: {\\n\\t\\t\\t\\t\\t\\t\\t\\twidth: texture.width,\\n\\t\\t\\t\\t\\t\\t\\t\\theight: texture.height,\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthOrArrayLayers: texture.cubemap ? 6 : texture.array ? texture.arrayLength : 1\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tformat: this.format,\\n\\t\\t\\t\\t\\t\\tmipLevelCount: numLevels,\\n\\t\\t\\t\\t\\t\\tsampleCount: 1,\\n\\t\\t\\t\\t\\t\\tdimension: texture.volume ? '3d' : '2d',\\n\\t\\t\\t\\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\\t\\t};\\n\\t\\t\\t\\tthis.gpuTexture = wgpu.createTexture(this.desc);\\n\\t\\t\\t\\tlet viewDescr;\\n\\t\\t\\t\\tif (this.texture.format === PIXELFORMAT_DEPTHSTENCIL) {\\n\\t\\t\\t\\t\\t\\tviewDescr = {\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: 'depth24plus',\\n\\t\\t\\t\\t\\t\\t\\t\\taspect: 'depth-only'\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.view = this.createView(viewDescr);\\n\\t\\t\\t\\tthis.viewCache.clear();\\n\\t\\t}\\n\\t\\tdestroy(device) {\\n\\t\\t\\t\\tdevice.deferDestroy(this.gpuTexture);\\n\\t\\t\\t\\tthis.gpuTexture = null;\\n\\t\\t\\t\\tthis.view = null;\\n\\t\\t\\t\\tthis.viewCache.clear();\\n\\t\\t\\t\\tthis.samplers.length = 0;\\n\\t\\t}\\n\\t\\tpropertyChanged(flag) {\\n\\t\\t\\t\\tthis.samplers.length = 0;\\n\\t\\t}\\n\\t\\tgetView(device, textureView) {\\n\\t\\t\\t\\tthis.uploadImmediate(device, this.texture);\\n\\t\\t\\t\\tif (textureView) {\\n\\t\\t\\t\\t\\t\\tlet view = this.viewCache.get(textureView.key);\\n\\t\\t\\t\\t\\t\\tif (!view) {\\n\\t\\t\\t\\t\\t\\t\\t\\tview = this.createView({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbaseMipLevel: textureView.baseMipLevel,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmipLevelCount: textureView.mipLevelCount,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbaseArrayLayer: textureView.baseArrayLayer,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tarrayLayerCount: textureView.arrayLayerCount\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.viewCache.set(textureView.key, view);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn view;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.view;\\n\\t\\t}\\n\\t\\tcreateView(viewDescr) {\\n\\t\\t\\t\\tconst options = viewDescr ?? {};\\n\\t\\t\\t\\tconst textureDescr = this.desc;\\n\\t\\t\\t\\tconst texture = this.texture;\\n\\t\\t\\t\\tconst defaultViewDimension = ()=>{\\n\\t\\t\\t\\t\\t\\tif (texture.cubemap) return 'cube';\\n\\t\\t\\t\\t\\t\\tif (texture.volume) return '3d';\\n\\t\\t\\t\\t\\t\\tif (texture.array) return '2d-array';\\n\\t\\t\\t\\t\\t\\treturn '2d';\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst desc = {\\n\\t\\t\\t\\t\\t\\tformat: options.format ?? textureDescr.format,\\n\\t\\t\\t\\t\\t\\tdimension: options.dimension ?? defaultViewDimension(),\\n\\t\\t\\t\\t\\t\\taspect: options.aspect ?? 'all',\\n\\t\\t\\t\\t\\t\\tbaseMipLevel: options.baseMipLevel ?? 0,\\n\\t\\t\\t\\t\\t\\tmipLevelCount: options.mipLevelCount ?? textureDescr.mipLevelCount,\\n\\t\\t\\t\\t\\t\\tbaseArrayLayer: options.baseArrayLayer ?? 0,\\n\\t\\t\\t\\t\\t\\tarrayLayerCount: options.arrayLayerCount ?? textureDescr.depthOrArrayLayers\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst view = this.gpuTexture.createView(desc);\\n\\t\\t\\t\\treturn view;\\n\\t\\t}\\n\\t\\tgetSampler(device, sampleType) {\\n\\t\\t\\t\\tlet sampler = this.samplers[sampleType];\\n\\t\\t\\t\\tif (!sampler) {\\n\\t\\t\\t\\t\\t\\tconst texture = this.texture;\\n\\t\\t\\t\\t\\t\\tconst desc = {\\n\\t\\t\\t\\t\\t\\t\\t\\taddressModeU: gpuAddressModes[texture.addressU],\\n\\t\\t\\t\\t\\t\\t\\t\\taddressModeV: gpuAddressModes[texture.addressV],\\n\\t\\t\\t\\t\\t\\t\\t\\taddressModeW: gpuAddressModes[texture.addressW]\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tif (!sampleType && texture.compareOnRead) {\\n\\t\\t\\t\\t\\t\\t\\t\\tsampleType = SAMPLETYPE_DEPTH;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (sampleType === SAMPLETYPE_DEPTH || sampleType === SAMPLETYPE_INT || sampleType === SAMPLETYPE_UINT) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdesc.compare = 'less';\\n\\t\\t\\t\\t\\t\\t\\t\\tdesc.magFilter = 'linear';\\n\\t\\t\\t\\t\\t\\t\\t\\tdesc.minFilter = 'linear';\\n\\t\\t\\t\\t\\t\\t} else if (sampleType === SAMPLETYPE_UNFILTERABLE_FLOAT) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdesc.magFilter = 'nearest';\\n\\t\\t\\t\\t\\t\\t\\t\\tdesc.minFilter = 'nearest';\\n\\t\\t\\t\\t\\t\\t\\t\\tdesc.mipmapFilter = 'nearest';\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst forceNearest = !device.textureFloatFilterable && (texture.format === PIXELFORMAT_RGBA32F || texture.format === PIXELFORMAT_RGBA16F);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (forceNearest || this.texture.format === PIXELFORMAT_DEPTHSTENCIL || isIntegerPixelFormat(this.texture.format)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdesc.magFilter = 'nearest';\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdesc.minFilter = 'nearest';\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdesc.mipmapFilter = 'nearest';\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdesc.magFilter = gpuFilterModes[texture.magFilter].level;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdesc.minFilter = gpuFilterModes[texture.minFilter].level;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdesc.mipmapFilter = gpuFilterModes[texture.minFilter].mip;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst allLinear = desc.minFilter === 'linear' && desc.magFilter === 'linear' && desc.mipmapFilter === 'linear';\\n\\t\\t\\t\\t\\t\\tdesc.maxAnisotropy = allLinear ? math.clamp(Math.round(texture._anisotropy), 1, device.maxTextureAnisotropy) : 1;\\n\\t\\t\\t\\t\\t\\tsampler = device.wgpu.createSampler(desc);\\n\\t\\t\\t\\t\\t\\tthis.samplers[sampleType] = sampler;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn sampler;\\n\\t\\t}\\n\\t\\tloseContext() {}\\n\\t\\tuploadImmediate(device, texture) {\\n\\t\\t\\t\\tif (texture._needsUpload || texture._needsMipmapsUpload) {\\n\\t\\t\\t\\t\\t\\tthis.uploadData(device);\\n\\t\\t\\t\\t\\t\\ttexture._needsUpload = false;\\n\\t\\t\\t\\t\\t\\ttexture._needsMipmapsUpload = false;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tuploadData(device) {\\n\\t\\t\\t\\tconst texture = this.texture;\\n\\t\\t\\t\\tif (this.desc && (this.desc.size.width !== texture.width || this.desc.size.height !== texture.height)) {\\n\\t\\t\\t\\t\\t\\tthis.gpuTexture.destroy();\\n\\t\\t\\t\\t\\t\\tthis.create(device);\\n\\t\\t\\t\\t\\t\\ttexture.renderVersionDirty = device.renderVersion;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (texture._levels) {\\n\\t\\t\\t\\t\\t\\tlet anyUploads = false;\\n\\t\\t\\t\\t\\t\\tlet anyLevelMissing = false;\\n\\t\\t\\t\\t\\t\\tconst requiredMipLevels = texture.numLevels;\\n\\t\\t\\t\\t\\t\\tfor(let mipLevel = 0; mipLevel < requiredMipLevels; mipLevel++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst mipObject = texture._levels[mipLevel];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (mipObject) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (texture.cubemap) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let face = 0; face < 6; face++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst faceSource = mipObject[face];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (faceSource) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this.isExternalImage(faceSource)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.uploadExternalImage(device, faceSource, mipLevel, face);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tanyUploads = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else if (ArrayBuffer.isView(faceSource)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.uploadTypedArrayData(device, faceSource, mipLevel, face);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tanyUploads = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else ;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tanyLevelMissing = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else if (texture._volume) ; else if (texture.array) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (texture.arrayLength === mipObject.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let index = 0; index < texture._arrayLength; index++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst arraySource = mipObject[index];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this.isExternalImage(arraySource)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.uploadExternalImage(device, arraySource, mipLevel, index);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tanyUploads = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else if (ArrayBuffer.isView(arraySource)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.uploadTypedArrayData(device, arraySource, mipLevel, index);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tanyUploads = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else ;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tanyLevelMissing = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this.isExternalImage(mipObject)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.uploadExternalImage(device, mipObject, mipLevel, 0);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tanyUploads = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else if (ArrayBuffer.isView(mipObject)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.uploadTypedArrayData(device, mipObject, mipLevel, 0);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tanyUploads = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else ;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tanyLevelMissing = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (anyUploads && anyLevelMissing && texture.mipmaps && !isCompressedPixelFormat(texture.format) && !isIntegerPixelFormat(texture.format)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.mipmapRenderer.generate(this);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (texture._gpuSize) {\\n\\t\\t\\t\\t\\t\\t\\t\\ttexture.adjustVramSizeTracking(device._vram, -texture._gpuSize);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\ttexture._gpuSize = texture.gpuSize;\\n\\t\\t\\t\\t\\t\\ttexture.adjustVramSizeTracking(device._vram, texture._gpuSize);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tisExternalImage(image) {\\n\\t\\t\\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\\t}\\n\\t\\tuploadExternalImage(device, image, mipLevel, index) {\\n\\t\\t\\t\\tconst src = {\\n\\t\\t\\t\\t\\t\\tsource: image,\\n\\t\\t\\t\\t\\t\\torigin: [\\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],\\n\\t\\t\\t\\t\\t\\tflipY: false\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst dst = {\\n\\t\\t\\t\\t\\t\\ttexture: this.gpuTexture,\\n\\t\\t\\t\\t\\t\\tmipLevel: mipLevel,\\n\\t\\t\\t\\t\\t\\torigin: [\\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],\\n\\t\\t\\t\\t\\t\\taspect: 'all',\\n\\t\\t\\t\\t\\t\\tpremultipliedAlpha: this.texture._premultiplyAlpha\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst copySize = {\\n\\t\\t\\t\\t\\t\\twidth: this.desc.size.width,\\n\\t\\t\\t\\t\\t\\theight: this.desc.size.height,\\n\\t\\t\\t\\t\\t\\tdepthOrArrayLayers: 1\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tdevice.submit();\\n\\t\\t\\t\\tdummyUse(image instanceof HTMLCanvasElement && image.getContext('2d'));\\n\\t\\t\\t\\tdevice.wgpu.queue.copyExternalImageToTexture(src, dst, copySize);\\n\\t\\t}\\n\\t\\tuploadTypedArrayData(device, data, mipLevel, index) {\\n\\t\\t\\t\\tconst texture = this.texture;\\n\\t\\t\\t\\tconst wgpu = device.wgpu;\\n\\t\\t\\t\\tconst dest = {\\n\\t\\t\\t\\t\\t\\ttexture: this.gpuTexture,\\n\\t\\t\\t\\t\\t\\torigin: [\\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],\\n\\t\\t\\t\\t\\t\\tmipLevel: mipLevel\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst width = TextureUtils.calcLevelDimension(texture.width, mipLevel);\\n\\t\\t\\t\\tconst height = TextureUtils.calcLevelDimension(texture.height, mipLevel);\\n\\t\\t\\t\\tTextureUtils.calcLevelGpuSize(width, height, 1, texture.format);\\n\\t\\t\\t\\tconst formatInfo = pixelFormatInfo.get(texture.format);\\n\\t\\t\\t\\tlet dataLayout;\\n\\t\\t\\t\\tlet size;\\n\\t\\t\\t\\tif (formatInfo.size) {\\n\\t\\t\\t\\t\\t\\tdataLayout = {\\n\\t\\t\\t\\t\\t\\t\\t\\toffset: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tbytesPerRow: formatInfo.size * width,\\n\\t\\t\\t\\t\\t\\t\\t\\trowsPerImage: height\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tsize = {\\n\\t\\t\\t\\t\\t\\t\\t\\twidth: width,\\n\\t\\t\\t\\t\\t\\t\\t\\theight: height\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t} else if (formatInfo.blockSize) {\\n\\t\\t\\t\\t\\t\\tconst blockDim = (size)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\treturn Math.floor((size + 3) / 4);\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tdataLayout = {\\n\\t\\t\\t\\t\\t\\t\\t\\toffset: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tbytesPerRow: formatInfo.blockSize * blockDim(width),\\n\\t\\t\\t\\t\\t\\t\\t\\trowsPerImage: blockDim(height)\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tsize = {\\n\\t\\t\\t\\t\\t\\t\\t\\twidth: Math.max(4, width),\\n\\t\\t\\t\\t\\t\\t\\t\\theight: Math.max(4, height)\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t} else ;\\n\\t\\t\\t\\tdevice.submit();\\n\\t\\t\\t\\twgpu.queue.writeTexture(dest, data, dataLayout, size);\\n\\t\\t}\\n\\t\\tread(x, y, width, height, options) {\\n\\t\\t\\t\\tconst mipLevel = options.mipLevel ?? 0;\\n\\t\\t\\t\\tconst face = options.face ?? 0;\\n\\t\\t\\t\\tconst data = options.data ?? null;\\n\\t\\t\\t\\tconst immediate = options.immediate ?? false;\\n\\t\\t\\t\\tconst texture = this.texture;\\n\\t\\t\\t\\tconst formatInfo = pixelFormatInfo.get(texture.format);\\n\\t\\t\\t\\tconst bytesPerRow = width * formatInfo.size;\\n\\t\\t\\t\\tconst paddedBytesPerRow = math.roundUp(bytesPerRow, 256);\\n\\t\\t\\t\\tconst size = paddedBytesPerRow * height;\\n\\t\\t\\t\\tconst device = texture.device;\\n\\t\\t\\t\\tconst stagingBuffer = device.createBufferImpl(BUFFERUSAGE_READ | BUFFERUSAGE_COPY_DST);\\n\\t\\t\\t\\tstagingBuffer.allocate(device, size);\\n\\t\\t\\t\\tconst src = {\\n\\t\\t\\t\\t\\t\\ttexture: this.gpuTexture,\\n\\t\\t\\t\\t\\t\\tmipLevel: mipLevel,\\n\\t\\t\\t\\t\\t\\torigin: [\\n\\t\\t\\t\\t\\t\\t\\t\\tx,\\n\\t\\t\\t\\t\\t\\t\\t\\ty,\\n\\t\\t\\t\\t\\t\\t\\t\\tface\\n\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst dst = {\\n\\t\\t\\t\\t\\t\\tbuffer: stagingBuffer.buffer,\\n\\t\\t\\t\\t\\t\\toffset: 0,\\n\\t\\t\\t\\t\\t\\tbytesPerRow: paddedBytesPerRow\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst copySize = {\\n\\t\\t\\t\\t\\t\\twidth,\\n\\t\\t\\t\\t\\t\\theight,\\n\\t\\t\\t\\t\\t\\tdepthOrArrayLayers: 1\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst commandEncoder = device.getCommandEncoder();\\n\\t\\t\\t\\tcommandEncoder.copyTextureToBuffer(src, dst, copySize);\\n\\t\\t\\t\\treturn device.readBuffer(stagingBuffer, size, null, immediate).then((temp)=>{\\n\\t\\t\\t\\t\\t\\tconst ArrayType = getPixelFormatArrayType(texture.format);\\n\\t\\t\\t\\t\\t\\tconst targetBuffer = data?.buffer ?? new ArrayBuffer(height * bytesPerRow);\\n\\t\\t\\t\\t\\t\\tconst target = new Uint8Array(targetBuffer, data?.byteOffset ?? 0, height * bytesPerRow);\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < height; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst srcOffset = i * paddedBytesPerRow;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dstOffset = i * bytesPerRow;\\n\\t\\t\\t\\t\\t\\t\\t\\ttarget.set(temp.subarray(srcOffset, srcOffset + bytesPerRow), dstOffset);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn data ?? new ArrayType(targetBuffer);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tconstructor(texture){\\n\\t\\t\\t\\tthis.samplers = [];\\n\\t\\t\\t\\tthis.viewCache = new Map();\\n\\t\\t\\t\\tthis.texture = texture;\\n\\t\\t\\t\\tthis.format = gpuTextureFormats[texture.format];\\n\\t\\t\\t\\tthis.create(texture.device);\\n\\t\\t}\\n}\\n\\nclass WebgpuUniformBuffer extends WebgpuBuffer {\\n\\t\\tunlock(uniformBuffer) {\\n\\t\\t\\t\\tconst device = uniformBuffer.device;\\n\\t\\t\\t\\tsuper.unlock(device, uniformBuffer.storageInt32.buffer);\\n\\t\\t}\\n\\t\\tconstructor(uniformBuffer){\\n\\t\\t\\t\\tsuper(BUFFERUSAGE_UNIFORM);\\n\\t\\t}\\n}\\n\\nclass WebgpuVertexBuffer extends WebgpuBuffer {\\n\\t\\tunlock(vertexBuffer) {\\n\\t\\t\\t\\tconst device = vertexBuffer.device;\\n\\t\\t\\t\\tsuper.unlock(device, vertexBuffer.storage);\\n\\t\\t}\\n\\t\\tconstructor(vertexBuffer, format, options){\\n\\t\\t\\t\\tsuper(BUFFERUSAGE_VERTEX | (options?.storage ? BUFFERUSAGE_STORAGE : 0));\\n\\t\\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\\t\\tstatic run(source, includes = new Map(), options = {}) {\\n\\t\\t\\t\\tPreprocessor.sourceName = options.sourceName;\\n\\t\\t\\t\\tsource = this.stripComments(source);\\n\\t\\t\\t\\tsource = source.split(/\\\\r?\\\\n/).map((line)=>line.trimEnd()).join('\\\\n');\\n\\t\\t\\t\\tconst defines = new Map();\\n\\t\\t\\t\\tconst injectDefines = new Map();\\n\\t\\t\\t\\tsource = this._preprocess(source, defines, injectDefines, includes, options.stripDefines);\\n\\t\\t\\t\\tif (source === null) return null;\\n\\t\\t\\t\\tconst intDefines = new Map();\\n\\t\\t\\t\\tdefines.forEach((value, key)=>{\\n\\t\\t\\t\\t\\t\\tif (Number.isInteger(parseFloat(value)) && !value.includes('.')) {\\n\\t\\t\\t\\t\\t\\t\\t\\tintDefines.set(key, value);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tsource = this.stripComments(source);\\n\\t\\t\\t\\tsource = this.stripUnusedColorAttachments(source, options);\\n\\t\\t\\t\\tsource = this.RemoveEmptyLines(source);\\n\\t\\t\\t\\tsource = this.processArraySize(source, intDefines);\\n\\t\\t\\t\\tsource = this.injectDefines(source, injectDefines);\\n\\t\\t\\t\\treturn source;\\n\\t\\t}\\n\\t\\tstatic stripUnusedColorAttachments(source, options) {\\n\\t\\t\\t\\tif (options.stripUnusedColorAttachments) {\\n\\t\\t\\t\\t\\t\\tconst counts = new Map();\\n\\t\\t\\t\\t\\t\\tconst matches = source.match(FRAGCOLOR);\\n\\t\\t\\t\\t\\t\\tmatches?.forEach((match)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst index = parseInt(match.charAt(match.length - 1), 10);\\n\\t\\t\\t\\t\\t\\t\\t\\tcounts.set(index, (counts.get(index) ?? 0) + 1);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tconst anySingleUse = Array.from(counts.values()).some((count)=>count === 1);\\n\\t\\t\\t\\t\\t\\tif (anySingleUse) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst lines = source.split('\\\\n');\\n\\t\\t\\t\\t\\t\\t\\t\\tconst keepLines = [];\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < lines.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst match = lines[i].match(FRAGCOLOR);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (match) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst index = parseInt(match[0].charAt(match[0].length - 1), 10);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (index > 0 && counts.get(index) === 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tkeepLines.push(lines[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tsource = keepLines.join('\\\\n');\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn source;\\n\\t\\t}\\n\\t\\tstatic stripComments(source) {\\n\\t\\t\\t\\treturn source.replace(/\\\\/\\\\*[\\\\s\\\\S]*?\\\\*\\\\/|([^\\\\\\\\:]|^)\\\\/\\\\/.*$/gm, '$1');\\n\\t\\t}\\n\\t\\tstatic processArraySize(source, intDefines) {\\n\\t\\t\\t\\tif (source !== null) {\\n\\t\\t\\t\\t\\t\\tintDefines.forEach((value, key)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tsource = source.replace(new RegExp(`\\\\\\\\[${key}\\\\\\\\]`, 'g'), `[${value}]`);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn source;\\n\\t\\t}\\n\\t\\tstatic injectDefines(source, injectDefines) {\\n\\t\\t\\t\\tif (source !== null && injectDefines.size > 0) {\\n\\t\\t\\t\\t\\t\\tconst lines = source.split('\\\\n');\\n\\t\\t\\t\\t\\t\\tinjectDefines.forEach((value, key)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst regex = new RegExp(key, 'g');\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < lines.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!lines[i].includes('#')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlines[i] = lines[i].replace(regex, value);\\n\\t\\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});\\n\\t\\t\\t\\t\\t\\tsource = lines.join('\\\\n');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn source;\\n\\t\\t}\\n\\t\\tstatic RemoveEmptyLines(source) {\\n\\t\\t\\t\\tif (source !== null) {\\n\\t\\t\\t\\t\\t\\tsource = source.split(/\\\\r?\\\\n/).map((line)=>line.trim() === '' ? '' : line).join('\\\\n');\\n\\t\\t\\t\\t\\t\\tsource = source.replace(/(\\\\n\\\\n){3,}/g, '\\\\n\\\\n');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn source;\\n\\t\\t}\\n\\t\\tstatic _preprocess(source, defines = new Map(), injectDefines, includes, stripDefines) {\\n\\t\\t\\t\\tconst originalSource = source;\\n\\t\\t\\t\\tconst stack = [];\\n\\t\\t\\t\\tlet error = false;\\n\\t\\t\\t\\tlet match;\\n\\t\\t\\t\\twhile((match = KEYWORD.exec(source)) !== null && !error){\\n\\t\\t\\t\\t\\t\\tconst keyword = match[1];\\n\\t\\t\\t\\t\\t\\tswitch(keyword){\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 'define':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tDEFINE.lastIndex = match.index;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst define = DEFINE.exec(source);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\terror || (error = define === null);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst expression = define[1];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tIDENTIFIER$1.lastIndex = define.index;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst identifierValue = IDENTIFIER$1.exec(expression);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst identifier = identifierValue[0];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet value = expression.substring(identifier.length).trim();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (value === '') value = 'true';\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst keep = Preprocessor._keep(stack);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet stripThisDefine = stripDefines;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (keep) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst replacementDefine = identifier.startsWith('{') && identifier.endsWith('}');\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (replacementDefine) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstripThisDefine = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (replacementDefine) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinjectDefines.set(identifier, value);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdefines.set(identifier, value);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (stripThisDefine) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsource = source.substring(0, define.index - 1) + source.substring(DEFINE.lastIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tKEYWORD.lastIndex = define.index - 1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!stripThisDefine) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tKEYWORD.lastIndex = define.index + define[0].length;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 'undef':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tUNDEF.lastIndex = match.index;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst undef = UNDEF.exec(source);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst identifier = undef[1].trim();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst keep = Preprocessor._keep(stack);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (keep) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdefines.delete(identifier);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (stripDefines) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsource = source.substring(0, undef.index - 1) + source.substring(UNDEF.lastIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tKEYWORD.lastIndex = undef.index - 1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!stripDefines) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tKEYWORD.lastIndex = undef.index + undef[0].length;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 'extension':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tEXTENSION.lastIndex = match.index;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst extension = EXTENSION.exec(source);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\terror || (error = extension === null);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (extension) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst identifier = extension[1];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst keep = Preprocessor._keep(stack);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (keep) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdefines.set(identifier, 'true');\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tKEYWORD.lastIndex = extension.index + extension[0].length;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 'ifdef':\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 'ifndef':\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 'if':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tIF.lastIndex = match.index;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst iff = IF.exec(source);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst expression = iff[2];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst evaluated = Preprocessor.evaluate(expression, defines);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\terror || (error = evaluated.error);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet result = evaluated.result;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (keyword === 'ifndef') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult = !result;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstack.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tanyKeep: result,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tkeep: result,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstart: match.index,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tend: IF.lastIndex\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tKEYWORD.lastIndex = iff.index + iff[0].length;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 'endif':\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 'else':\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 'elif':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tENDIF.lastIndex = match.index;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst endif = ENDIF.exec(source);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst blockInfo = stack.pop();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!blockInfo) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\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)}...`, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsource: originalSource\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\terror = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst blockCode = blockInfo.keep ? source.substring(blockInfo.end, match.index) : '';\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsource = source.substring(0, blockInfo.start) + blockCode + source.substring(ENDIF.lastIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tKEYWORD.lastIndex = blockInfo.start + blockCode.length;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst endifCommand = endif[1];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (endifCommand === 'else' || endifCommand === 'elif') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet result = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!blockInfo.anyKeep) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (endifCommand === 'else') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult = !blockInfo.keep;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst evaluated = Preprocessor.evaluate(endif[2], defines);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult = evaluated.result;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\terror || (error = evaluated.error);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstack.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tanyKeep: blockInfo.anyKeep || result,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tkeep: result,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstart: KEYWORD.lastIndex,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tend: KEYWORD.lastIndex\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 'include':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tINCLUDE.lastIndex = match.index;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst include = INCLUDE.exec(source);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\terror || (error = include === null);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!include) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\terror = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst identifier = include[1].trim();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst countIdentifier = include[2]?.trim();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst keep = Preprocessor._keep(stack);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (keep) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet includeSource = includes?.get(identifier);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (includeSource !== undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tincludeSource = this.stripComments(includeSource);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (countIdentifier) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst countString = defines.get(countIdentifier);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst count = parseFloat(countString);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (Number.isInteger(count)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet result = '';\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\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\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tincludeSource = result;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\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)}...`, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toriginalSource: originalSource,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsource: source\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\terror = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tKEYWORD.lastIndex = include.index - 1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconsole.error(`Include \\\"${identifier}\\\" not resolved while preprocessing ${Preprocessor.sourceName}`, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toriginalSource: originalSource,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsource: source\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\terror = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (stack.length > 0) {\\n\\t\\t\\t\\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\\t\\t\\t\\terror = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (error) {\\n\\t\\t\\t\\t\\t\\tconsole.error('Failed to preprocess shader: ', {\\n\\t\\t\\t\\t\\t\\t\\t\\tsource: originalSource\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn source;\\n\\t\\t}\\n\\t\\tstatic _keep(stack) {\\n\\t\\t\\t\\tfor(let i = 0; i < stack.length; i++){\\n\\t\\t\\t\\t\\t\\tif (!stack[i].keep) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tstatic evaluateAtomicExpression(expr, defines) {\\n\\t\\t\\t\\tlet error = false;\\n\\t\\t\\t\\texpr = expr.trim();\\n\\t\\t\\t\\tlet invert = false;\\n\\t\\t\\t\\tif (expr === 'true') {\\n\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult: true,\\n\\t\\t\\t\\t\\t\\t\\t\\terror\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (expr === 'false') {\\n\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult: false,\\n\\t\\t\\t\\t\\t\\t\\t\\terror\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (NUMERIC_LITERAL.test(expr)) {\\n\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult: parseFloat(expr) !== 0,\\n\\t\\t\\t\\t\\t\\t\\t\\terror\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst definedMatch = DEFINED.exec(expr);\\n\\t\\t\\t\\tif (definedMatch) {\\n\\t\\t\\t\\t\\t\\tinvert = definedMatch[1] === '!';\\n\\t\\t\\t\\t\\t\\texpr = definedMatch[2].trim();\\n\\t\\t\\t\\t\\t\\tconst exists = defines.has(expr);\\n\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult: invert ? !exists : exists,\\n\\t\\t\\t\\t\\t\\t\\t\\terror\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst comparisonMatch = COMPARISON.exec(expr);\\n\\t\\t\\t\\tif (comparisonMatch) {\\n\\t\\t\\t\\t\\t\\tconst left = defines.get(comparisonMatch[1].trim()) ?? comparisonMatch[1].trim();\\n\\t\\t\\t\\t\\t\\tconst right = defines.get(comparisonMatch[3].trim()) ?? comparisonMatch[3].trim();\\n\\t\\t\\t\\t\\t\\tconst operator = comparisonMatch[2].trim();\\n\\t\\t\\t\\t\\t\\tlet result = false;\\n\\t\\t\\t\\t\\t\\tswitch(operator){\\n\\t\\t\\t\\t\\t\\t\\t\\tcase '==':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult = left === right;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase '!=':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult = left !== right;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase '<':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult = left < right;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase '<=':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult = left <= right;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase '>':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult = left > right;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase '>=':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult = left >= right;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\terror = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult,\\n\\t\\t\\t\\t\\t\\t\\t\\terror\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst result = defines.has(expr);\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tresult,\\n\\t\\t\\t\\t\\t\\terror\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tstatic processParentheses(expression, defines) {\\n\\t\\t\\t\\tlet error = false;\\n\\t\\t\\t\\tlet processed = expression.trim();\\n\\t\\t\\t\\twhile(processed.startsWith('(') && processed.endsWith(')')){\\n\\t\\t\\t\\t\\t\\tlet depth = 0;\\n\\t\\t\\t\\t\\t\\tlet wrapsEntire = true;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < processed.length - 1; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (processed[i] === '(') depth++;\\n\\t\\t\\t\\t\\t\\t\\t\\telse if (processed[i] === ')') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdepth--;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (depth === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twrapsEntire = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tif (wrapsEntire) {\\n\\t\\t\\t\\t\\t\\t\\t\\tprocessed = processed.slice(1, -1).trim();\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\twhile(true){\\n\\t\\t\\t\\t\\t\\tlet foundParen = false;\\n\\t\\t\\t\\t\\t\\tlet depth = 0;\\n\\t\\t\\t\\t\\t\\tlet maxDepth = 0;\\n\\t\\t\\t\\t\\t\\tlet deepestStart = -1;\\n\\t\\t\\t\\t\\t\\tlet deepestEnd = -1;\\n\\t\\t\\t\\t\\t\\tlet inDefinedParen = 0;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < processed.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (processed[i] === '(') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst beforeParen = processed.substring(0, i);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (DEFINED_BEFORE_PAREN.test(beforeParen)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinDefinedParen++;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else if (inDefinedParen === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdepth++;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (depth > maxDepth) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmaxDepth = depth;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdeepestStart = i;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfoundParen = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else if (processed[i] === ')') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (inDefinedParen > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinDefinedParen--;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else if (depth > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (depth === maxDepth && deepestStart !== -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdeepestEnd = i;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdepth--;\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tif (!foundParen || deepestStart === -1 || deepestEnd === -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst subExpr = processed.substring(deepestStart + 1, deepestEnd);\\n\\t\\t\\t\\t\\t\\tconst { result, error: subError } = Preprocessor.evaluate(subExpr, defines);\\n\\t\\t\\t\\t\\t\\terror = error || subError;\\n\\t\\t\\t\\t\\t\\tprocessed = processed.substring(0, deepestStart) + (result ? 'true' : 'false') + processed.substring(deepestEnd + 1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\texpression: processed,\\n\\t\\t\\t\\t\\t\\terror\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tstatic evaluate(expression, defines) {\\n\\t\\t\\t\\tconst correct = INVALID.exec(expression) === null;\\n\\t\\t\\t\\tlet processedExpr = expression;\\n\\t\\t\\t\\tlet parenError = false;\\n\\t\\t\\t\\tconst withoutDefined = expression.replace(DEFINED_PARENS, '');\\n\\t\\t\\t\\tif (withoutDefined.indexOf('(') !== -1) {\\n\\t\\t\\t\\t\\t\\tconst processed = Preprocessor.processParentheses(expression, defines);\\n\\t\\t\\t\\t\\t\\tprocessedExpr = processed.expression;\\n\\t\\t\\t\\t\\t\\tparenError = processed.error;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (parenError) {\\n\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult: false,\\n\\t\\t\\t\\t\\t\\t\\t\\terror: true\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst orSegments = processedExpr.split('||');\\n\\t\\t\\t\\tfor (const orSegment of orSegments){\\n\\t\\t\\t\\t\\t\\tconst andSegments = orSegment.split('&&');\\n\\t\\t\\t\\t\\t\\tlet andResult = true;\\n\\t\\t\\t\\t\\t\\tfor (const andSegment of andSegments){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst { result, error } = Preprocessor.evaluateAtomicExpression(andSegment.trim(), defines);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!result || error) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tandResult = false;\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tif (andResult) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult: true,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\terror: !correct\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tresult: false,\\n\\t\\t\\t\\t\\t\\terror: !correct\\n\\t\\t\\t\\t};\\n\\t\\t}\\n}\\n\\nvar gles3PS = `\\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 gles3VS = `\\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 webgpuPS$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 webgpuVS$1 = `\\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 webgpuPS = `\\n`;\\n\\nvar webgpuVS = `\\n#define VERTEXSHADER\\n`;\\n\\nvar sharedGLSL = `\\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 sharedWGSL = `\\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\\nconst _attrib2Semantic = {\\n\\t\\tvertex_position: SEMANTIC_POSITION,\\n\\t\\tvertex_normal: SEMANTIC_NORMAL,\\n\\t\\tvertex_tangent: SEMANTIC_TANGENT,\\n\\t\\tvertex_texCoord0: SEMANTIC_TEXCOORD0,\\n\\t\\tvertex_texCoord1: SEMANTIC_TEXCOORD1,\\n\\t\\tvertex_texCoord2: SEMANTIC_TEXCOORD2,\\n\\t\\tvertex_texCoord3: SEMANTIC_TEXCOORD3,\\n\\t\\tvertex_texCoord4: SEMANTIC_TEXCOORD4,\\n\\t\\tvertex_texCoord5: SEMANTIC_TEXCOORD5,\\n\\t\\tvertex_texCoord6: SEMANTIC_TEXCOORD6,\\n\\t\\tvertex_texCoord7: SEMANTIC_TEXCOORD7,\\n\\t\\tvertex_color: SEMANTIC_COLOR,\\n\\t\\tvertex_boneIndices: SEMANTIC_BLENDINDICES,\\n\\t\\tvertex_boneWeights: SEMANTIC_BLENDWEIGHT\\n};\\nclass ShaderDefinitionUtils {\\n\\t\\tstatic createDefinition(device, options) {\\n\\t\\t\\t\\tconst normalizedOutputTypes = (options)=>{\\n\\t\\t\\t\\t\\t\\tlet fragmentOutputTypes = options.fragmentOutputTypes ?? 'vec4';\\n\\t\\t\\t\\t\\t\\tif (!Array.isArray(fragmentOutputTypes)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentOutputTypes = [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfragmentOutputTypes\\n\\t\\t\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn fragmentOutputTypes;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst getDefines = (gpu, gl2, isVertex, options)=>{\\n\\t\\t\\t\\t\\t\\tconst deviceIntro = device.isWebGPU ? gpu : gl2;\\n\\t\\t\\t\\t\\t\\tlet attachmentsDefine = '';\\n\\t\\t\\t\\t\\t\\tif (!isVertex) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst fragmentOutputTypes = normalizedOutputTypes(options);\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < device.maxColorAttachments; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tattachmentsDefine += `#define COLOR_ATTACHMENT_${i}\\\\n`;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst outType = fragmentOutputTypes[i] ?? 'vec4';\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tattachmentsDefine += `#define outType_${i} ${outType}\\\\n`;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn attachmentsDefine + deviceIntro;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst getDefinesWgsl = (isVertex, options)=>{\\n\\t\\t\\t\\t\\t\\tlet code = '';\\n\\t\\t\\t\\t\\t\\tif (!isVertex && device.supportsPrimitiveIndex) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcode += 'enable primitive_index;\\\\n';\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!isVertex) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst fragmentOutputTypes = normalizedOutputTypes(options);\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < device.maxColorAttachments; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst glslOutType = fragmentOutputTypes[i] ?? 'vec4';\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst wgslOutType = primitiveGlslToWgslTypeMap.get(glslOutType);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcode += `alias pcOutType${i} = ${wgslOutType};\\\\n`;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn code;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst name = options.name ?? 'Untitled';\\n\\t\\t\\t\\tlet vertCode;\\n\\t\\t\\t\\tlet fragCode;\\n\\t\\t\\t\\tconst vertexDefinesCode = ShaderDefinitionUtils.getDefinesCode(device, options.vertexDefines);\\n\\t\\t\\t\\tconst fragmentDefinesCode = ShaderDefinitionUtils.getDefinesCode(device, options.fragmentDefines);\\n\\t\\t\\t\\tconst wgsl = options.shaderLanguage === SHADERLANGUAGE_WGSL;\\n\\t\\t\\t\\tif (wgsl) {\\n\\t\\t\\t\\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${webgpuVS}\\n\\t\\t\\t\\t\\t\\t\\t\\t${sharedWGSL}\\n\\t\\t\\t\\t\\t\\t\\t\\t${options.vertexCode}\\n\\t\\t\\t\\t\\t\\t`;\\n\\t\\t\\t\\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${webgpuPS}\\n\\t\\t\\t\\t\\t\\t\\t\\t${sharedWGSL}\\n\\t\\t\\t\\t\\t\\t\\t\\t${options.fragmentCode}\\n\\t\\t\\t\\t\\t\\t`;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tvertCode = `${ShaderDefinitionUtils.versionCode(device) + getDefines(webgpuVS$1, gles3VS, true, options) + vertexDefinesCode + ShaderDefinitionUtils.precisionCode(device)}\\n\\t\\t\\t\\t\\t\\t\\t\\t${sharedGLSL}\\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\\t\\t\\t\\tfragCode = `${(options.fragmentPreamble || '') + ShaderDefinitionUtils.versionCode(device) + getDefines(webgpuPS$1, gles3PS, false, options) + fragmentDefinesCode + ShaderDefinitionUtils.precisionCode(device)}\\n\\t\\t\\t\\t\\t\\t\\t\\t${sharedGLSL}\\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\\t\\t}\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\t\\t\\tshaderLanguage: options.shaderLanguage ?? SHADERLANGUAGE_GLSL,\\n\\t\\t\\t\\t\\t\\tattributes: options.attributes,\\n\\t\\t\\t\\t\\t\\tvshader: vertCode,\\n\\t\\t\\t\\t\\t\\tvincludes: options.vertexIncludes,\\n\\t\\t\\t\\t\\t\\tfincludes: options.fragmentIncludes,\\n\\t\\t\\t\\t\\t\\tfshader: fragCode,\\n\\t\\t\\t\\t\\t\\tfeedbackVaryings: options.feedbackVaryings,\\n\\t\\t\\t\\t\\t\\tuseTransformFeedback: options.useTransformFeedback,\\n\\t\\t\\t\\t\\t\\tmeshUniformBufferFormat: options.meshUniformBufferFormat,\\n\\t\\t\\t\\t\\t\\tmeshBindGroupFormat: options.meshBindGroupFormat\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tstatic getDefinesCode(device, defines) {\\n\\t\\t\\t\\tlet code = '';\\n\\t\\t\\t\\tdevice.capsDefines.forEach((value, key)=>{\\n\\t\\t\\t\\t\\t\\tcode += `#define ${key} ${value}\\\\n`;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tcode += '\\\\n';\\n\\t\\t\\t\\tdefines?.forEach((value, key)=>{\\n\\t\\t\\t\\t\\t\\tcode += `#define ${key} ${value}\\\\n`;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tcode += '\\\\n';\\n\\t\\t\\t\\treturn code;\\n\\t\\t}\\n\\t\\tstatic getShaderNameCode(name) {\\n\\t\\t\\t\\treturn `#define SHADER_NAME ${name}\\\\n`;\\n\\t\\t}\\n\\t\\tstatic versionCode(device) {\\n\\t\\t\\t\\treturn device.isWebGPU ? '#version 450\\\\n' : '#version 300 es\\\\n';\\n\\t\\t}\\n\\t\\tstatic precisionCode(device, forcePrecision) {\\n\\t\\t\\t\\tif (forcePrecision && forcePrecision !== 'highp' && forcePrecision !== 'mediump' && forcePrecision !== 'lowp') {\\n\\t\\t\\t\\t\\t\\tforcePrecision = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (forcePrecision) {\\n\\t\\t\\t\\t\\t\\tif (forcePrecision === 'highp' && device.maxPrecision !== 'highp') {\\n\\t\\t\\t\\t\\t\\t\\t\\tforcePrecision = 'mediump';\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (forcePrecision === 'mediump' && device.maxPrecision === 'lowp') {\\n\\t\\t\\t\\t\\t\\t\\t\\tforcePrecision = 'lowp';\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst precision = forcePrecision ? forcePrecision : device.precision;\\n\\t\\t\\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\\t\\t\\treturn code;\\n\\t\\t}\\n\\t\\tstatic collectAttributes(vsCode) {\\n\\t\\t\\t\\tconst attribs = {};\\n\\t\\t\\t\\tlet attrs = 0;\\n\\t\\t\\t\\tlet found = vsCode.indexOf('attribute');\\n\\t\\t\\t\\twhile(found >= 0){\\n\\t\\t\\t\\t\\t\\tif (found > 0 && vsCode[found - 1] === '/') break;\\n\\t\\t\\t\\t\\t\\tlet ignore = false;\\n\\t\\t\\t\\t\\t\\tif (found > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlet startOfLine = vsCode.lastIndexOf('\\\\n', found);\\n\\t\\t\\t\\t\\t\\t\\t\\tstartOfLine = startOfLine !== -1 ? startOfLine + 1 : 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst lineStartString = vsCode.substring(startOfLine, found);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (lineStartString.includes('#')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tignore = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!ignore) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst endOfLine = vsCode.indexOf(';', found);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst startOfAttribName = vsCode.lastIndexOf(' ', endOfLine);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst attribName = vsCode.substring(startOfAttribName + 1, endOfLine);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (attribs[attribName]) ; else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst semantic = _attrib2Semantic[attribName];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (semantic !== undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tattribs[attribName] = semantic;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tattribs[attribName] = `ATTR${attrs}`;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tattrs++;\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tfound = vsCode.indexOf('attribute', found + 1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn attribs;\\n\\t\\t}\\n}\\n\\nlet id$7 = 0;\\nclass Shader {\\n\\t\\tinit() {\\n\\t\\t\\t\\tthis.ready = false;\\n\\t\\t\\t\\tthis.failed = false;\\n\\t\\t}\\n\\t\\tget label() {\\n\\t\\t\\t\\treturn `Shader Id ${this.id} (${this.definition.shaderLanguage === SHADERLANGUAGE_WGSL ? 'WGSL' : 'GLSL'}) ${this.name}`;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.device.onDestroyShader(this);\\n\\t\\t\\t\\tthis.impl.destroy(this);\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tthis.init();\\n\\t\\t\\t\\tthis.impl.loseContext();\\n\\t\\t}\\n\\t\\trestoreContext() {\\n\\t\\t\\t\\tthis.impl.restoreContext(this.device, this);\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice, definition){\\n\\t\\t\\t\\tthis.attributes = new Map();\\n\\t\\t\\t\\tthis.id = id$7++;\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t\\t\\tthis.definition = definition;\\n\\t\\t\\t\\tthis.name = definition.name || 'Untitled';\\n\\t\\t\\t\\tthis.init();\\n\\t\\t\\t\\tif (definition.cshader) {\\n\\t\\t\\t\\t\\t\\tconst definesCode = ShaderDefinitionUtils.getDefinesCode(graphicsDevice, definition.cdefines);\\n\\t\\t\\t\\t\\t\\tconst cshader = definesCode + definition.cshader;\\n\\t\\t\\t\\t\\t\\tdefinition.cshader = Preprocessor.run(cshader, definition.cincludes, {\\n\\t\\t\\t\\t\\t\\t\\t\\tsourceName: `compute shader for ${this.label}`,\\n\\t\\t\\t\\t\\t\\t\\t\\tstripDefines: true\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst wgsl = definition.shaderLanguage === SHADERLANGUAGE_WGSL;\\n\\t\\t\\t\\t\\t\\tdefinition.vshader = Preprocessor.run(definition.vshader, definition.vincludes, {\\n\\t\\t\\t\\t\\t\\t\\t\\tsourceName: `vertex shader for ${this.label}`,\\n\\t\\t\\t\\t\\t\\t\\t\\tstripDefines: wgsl\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tif (definition.shaderLanguage === SHADERLANGUAGE_GLSL) {\\n\\t\\t\\t\\t\\t\\t\\t\\tvar _definition;\\n\\t\\t\\t\\t\\t\\t\\t\\t(_definition = definition).attributes ?? (_definition.attributes = ShaderDefinitionUtils.collectAttributes(definition.vshader));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst stripUnusedColorAttachments = graphicsDevice.isWebGL2 && (platform.name === 'osx' || platform.name === 'ios');\\n\\t\\t\\t\\t\\t\\tdefinition.fshader = Preprocessor.run(definition.fshader, definition.fincludes, {\\n\\t\\t\\t\\t\\t\\t\\t\\tstripUnusedColorAttachments,\\n\\t\\t\\t\\t\\t\\t\\t\\tstripDefines: wgsl,\\n\\t\\t\\t\\t\\t\\t\\t\\tsourceName: `fragment shader for ${this.label}`\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tif (!definition.vshader || !definition.fshader) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.failed = true;\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.impl = graphicsDevice.createShaderImpl(this);\\n\\t\\t}\\n}\\n\\nclass UsedBuffer {\\n}\\nclass DynamicBufferAllocation {\\n}\\nclass DynamicBuffers {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.gpuBuffers.forEach((gpuBuffer)=>{\\n\\t\\t\\t\\t\\t\\tgpuBuffer.destroy(this.device);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.gpuBuffers = null;\\n\\t\\t\\t\\tthis.stagingBuffers.forEach((stagingBuffer)=>{\\n\\t\\t\\t\\t\\t\\tstagingBuffer.destroy(this.device);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.stagingBuffers = null;\\n\\t\\t\\t\\tthis.usedBuffers = null;\\n\\t\\t\\t\\tthis.activeBuffer = null;\\n\\t\\t}\\n\\t\\talloc(allocation, size) {\\n\\t\\t\\t\\tif (this.activeBuffer) {\\n\\t\\t\\t\\t\\t\\tconst alignedStart = math.roundUp(this.activeBuffer.size, this.bufferAlignment);\\n\\t\\t\\t\\t\\t\\tconst space = this.bufferSize - alignedStart;\\n\\t\\t\\t\\t\\t\\tif (space < size) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.scheduleSubmit();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this.activeBuffer) {\\n\\t\\t\\t\\t\\t\\tlet gpuBuffer = this.gpuBuffers.pop();\\n\\t\\t\\t\\t\\t\\tif (!gpuBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgpuBuffer = this.createBuffer(this.device, this.bufferSize, false);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlet stagingBuffer = this.stagingBuffers.pop();\\n\\t\\t\\t\\t\\t\\tif (!stagingBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tstagingBuffer = this.createBuffer(this.device, this.bufferSize, true);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.activeBuffer = new UsedBuffer();\\n\\t\\t\\t\\t\\t\\tthis.activeBuffer.stagingBuffer = stagingBuffer;\\n\\t\\t\\t\\t\\t\\tthis.activeBuffer.gpuBuffer = gpuBuffer;\\n\\t\\t\\t\\t\\t\\tthis.activeBuffer.offset = 0;\\n\\t\\t\\t\\t\\t\\tthis.activeBuffer.size = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst activeBuffer = this.activeBuffer;\\n\\t\\t\\t\\tconst alignedStart = math.roundUp(activeBuffer.size, this.bufferAlignment);\\n\\t\\t\\t\\tallocation.gpuBuffer = activeBuffer.gpuBuffer;\\n\\t\\t\\t\\tallocation.offset = alignedStart;\\n\\t\\t\\t\\tallocation.storage = activeBuffer.stagingBuffer.alloc(alignedStart, size);\\n\\t\\t\\t\\tactiveBuffer.size = alignedStart + size;\\n\\t\\t}\\n\\t\\tscheduleSubmit() {\\n\\t\\t\\t\\tif (this.activeBuffer) {\\n\\t\\t\\t\\t\\t\\tthis.usedBuffers.push(this.activeBuffer);\\n\\t\\t\\t\\t\\t\\tthis.activeBuffer = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsubmit() {\\n\\t\\t\\t\\tthis.scheduleSubmit();\\n\\t\\t}\\n\\t\\tconstructor(device, bufferSize, bufferAlignment){\\n\\t\\t\\t\\tthis.gpuBuffers = [];\\n\\t\\t\\t\\tthis.stagingBuffers = [];\\n\\t\\t\\t\\tthis.usedBuffers = [];\\n\\t\\t\\t\\tthis.activeBuffer = null;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.bufferSize = bufferSize;\\n\\t\\t\\t\\tthis.bufferAlignment = bufferAlignment;\\n\\t\\t}\\n}\\n\\nconst _updateFunctions = [];\\n_updateFunctions[UNIFORMTYPE_FLOAT] = function(uniformBuffer, value, offset) {\\n\\t\\tconst dst = uniformBuffer.storageFloat32;\\n\\t\\tdst[offset] = value;\\n};\\n_updateFunctions[UNIFORMTYPE_VEC2] = (uniformBuffer, value, offset)=>{\\n\\t\\tconst dst = uniformBuffer.storageFloat32;\\n\\t\\tdst[offset] = value[0];\\n\\t\\tdst[offset + 1] = value[1];\\n};\\n_updateFunctions[UNIFORMTYPE_VEC3] = (uniformBuffer, value, offset)=>{\\n\\t\\tconst dst = uniformBuffer.storageFloat32;\\n\\t\\tdst[offset] = value[0];\\n\\t\\tdst[offset + 1] = value[1];\\n\\t\\tdst[offset + 2] = value[2];\\n};\\n_updateFunctions[UNIFORMTYPE_VEC4] = (uniformBuffer, value, offset)=>{\\n\\t\\tconst dst = uniformBuffer.storageFloat32;\\n\\t\\tdst[offset] = value[0];\\n\\t\\tdst[offset + 1] = value[1];\\n\\t\\tdst[offset + 2] = value[2];\\n\\t\\tdst[offset + 3] = value[3];\\n};\\n_updateFunctions[UNIFORMTYPE_INT] = function(uniformBuffer, value, offset) {\\n\\t\\tconst dst = uniformBuffer.storageInt32;\\n\\t\\tdst[offset] = value;\\n};\\n_updateFunctions[UNIFORMTYPE_IVEC2] = function(uniformBuffer, value, offset) {\\n\\t\\tconst dst = uniformBuffer.storageInt32;\\n\\t\\tdst[offset] = value[0];\\n\\t\\tdst[offset + 1] = value[1];\\n};\\n_updateFunctions[UNIFORMTYPE_IVEC3] = function(uniformBuffer, value, offset) {\\n\\t\\tconst dst = uniformBuffer.storageInt32;\\n\\t\\tdst[offset] = value[0];\\n\\t\\tdst[offset + 1] = value[1];\\n\\t\\tdst[offset + 2] = value[2];\\n};\\n_updateFunctions[UNIFORMTYPE_IVEC4] = function(uniformBuffer, value, offset) {\\n\\t\\tconst dst = uniformBuffer.storageInt32;\\n\\t\\tdst[offset] = value[0];\\n\\t\\tdst[offset + 1] = value[1];\\n\\t\\tdst[offset + 2] = value[2];\\n\\t\\tdst[offset + 3] = value[3];\\n};\\n_updateFunctions[UNIFORMTYPE_MAT2] = (uniformBuffer, value, offset)=>{\\n\\t\\tconst dst = uniformBuffer.storageFloat32;\\n\\t\\tdst[offset] = value[0];\\n\\t\\tdst[offset + 1] = value[1];\\n\\t\\tdst[offset + 4] = value[2];\\n\\t\\tdst[offset + 5] = value[3];\\n\\t\\tdst[offset + 8] = value[4];\\n\\t\\tdst[offset + 9] = value[5];\\n};\\n_updateFunctions[UNIFORMTYPE_MAT3] = (uniformBuffer, value, offset)=>{\\n\\t\\tconst dst = uniformBuffer.storageFloat32;\\n\\t\\tdst[offset] = value[0];\\n\\t\\tdst[offset + 1] = value[1];\\n\\t\\tdst[offset + 2] = value[2];\\n\\t\\tdst[offset + 4] = value[3];\\n\\t\\tdst[offset + 5] = value[4];\\n\\t\\tdst[offset + 6] = value[5];\\n\\t\\tdst[offset + 8] = value[6];\\n\\t\\tdst[offset + 9] = value[7];\\n\\t\\tdst[offset + 10] = value[8];\\n};\\n_updateFunctions[UNIFORMTYPE_FLOATARRAY] = function(uniformBuffer, value, offset, count) {\\n\\t\\tconst dst = uniformBuffer.storageFloat32;\\n\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\tdst[offset + i * 4] = value[i];\\n\\t\\t}\\n};\\n_updateFunctions[UNIFORMTYPE_VEC2ARRAY] = (uniformBuffer, value, offset, count)=>{\\n\\t\\tconst dst = uniformBuffer.storageFloat32;\\n\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\tdst[offset + i * 4] = value[i * 2];\\n\\t\\t\\t\\tdst[offset + i * 4 + 1] = value[i * 2 + 1];\\n\\t\\t}\\n};\\n_updateFunctions[UNIFORMTYPE_VEC3ARRAY] = (uniformBuffer, value, offset, count)=>{\\n\\t\\tconst dst = uniformBuffer.storageFloat32;\\n\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\tdst[offset + i * 4] = value[i * 3];\\n\\t\\t\\t\\tdst[offset + i * 4 + 1] = value[i * 3 + 1];\\n\\t\\t\\t\\tdst[offset + i * 4 + 2] = value[i * 3 + 2];\\n\\t\\t}\\n};\\n_updateFunctions[UNIFORMTYPE_UINT] = (uniformBuffer, value, offset, count)=>{\\n\\t\\tconst dst = uniformBuffer.storageUint32;\\n\\t\\tdst[offset] = value;\\n};\\n_updateFunctions[UNIFORMTYPE_UVEC2] = (uniformBuffer, value, offset, count)=>{\\n\\t\\tconst dst = uniformBuffer.storageUint32;\\n\\t\\tdst[offset] = value[0];\\n\\t\\tdst[offset + 1] = value[1];\\n};\\n_updateFunctions[UNIFORMTYPE_UVEC3] = (uniformBuffer, value, offset, count)=>{\\n\\t\\tconst dst = uniformBuffer.storageUint32;\\n\\t\\tdst[offset] = value[0];\\n\\t\\tdst[offset + 1] = value[1];\\n\\t\\tdst[offset + 2] = value[2];\\n};\\n_updateFunctions[UNIFORMTYPE_UVEC4] = (uniformBuffer, value, offset, count)=>{\\n\\t\\tconst dst = uniformBuffer.storageUint32;\\n\\t\\tdst[offset] = value[0];\\n\\t\\tdst[offset + 1] = value[1];\\n\\t\\tdst[offset + 2] = value[2];\\n\\t\\tdst[offset + 3] = value[3];\\n};\\n_updateFunctions[UNIFORMTYPE_INTARRAY] = function(uniformBuffer, value, offset, count) {\\n\\t\\tconst dst = uniformBuffer.storageInt32;\\n\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\tdst[offset + i * 4] = value[i];\\n\\t\\t}\\n};\\n_updateFunctions[UNIFORMTYPE_BOOLARRAY] = _updateFunctions[UNIFORMTYPE_INTARRAY];\\n_updateFunctions[UNIFORMTYPE_UINTARRAY] = function(uniformBuffer, value, offset, count) {\\n\\t\\tconst dst = uniformBuffer.storageUint32;\\n\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\tdst[offset + i * 4] = value[i];\\n\\t\\t}\\n};\\n_updateFunctions[UNIFORMTYPE_IVEC2ARRAY] = (uniformBuffer, value, offset, count)=>{\\n\\t\\tconst dst = uniformBuffer.storageInt32;\\n\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\tdst[offset + i * 4] = value[i * 2];\\n\\t\\t\\t\\tdst[offset + i * 4 + 1] = value[i * 2 + 1];\\n\\t\\t}\\n};\\n_updateFunctions[UNIFORMTYPE_BVEC2ARRAY] = _updateFunctions[UNIFORMTYPE_IVEC2ARRAY];\\n_updateFunctions[UNIFORMTYPE_UVEC2ARRAY] = (uniformBuffer, value, offset, count)=>{\\n\\t\\tconst dst = uniformBuffer.storageUint32;\\n\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\tdst[offset + i * 4] = value[i * 2];\\n\\t\\t\\t\\tdst[offset + i * 4 + 1] = value[i * 2 + 1];\\n\\t\\t}\\n};\\n_updateFunctions[UNIFORMTYPE_IVEC3ARRAY] = (uniformBuffer, value, offset, count)=>{\\n\\t\\tconst dst = uniformBuffer.storageInt32;\\n\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\tdst[offset + i * 4] = value[i * 3];\\n\\t\\t\\t\\tdst[offset + i * 4 + 1] = value[i * 3 + 1];\\n\\t\\t\\t\\tdst[offset + i * 4 + 2] = value[i * 3 + 2];\\n\\t\\t}\\n};\\n_updateFunctions[UNIFORMTYPE_BVEC3ARRAY] = _updateFunctions[UNIFORMTYPE_IVEC3ARRAY];\\n_updateFunctions[UNIFORMTYPE_UVEC3ARRAY] = (uniformBuffer, value, offset, count)=>{\\n\\t\\tconst dst = uniformBuffer.storageUint32;\\n\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\tdst[offset + i * 4] = value[i * 3];\\n\\t\\t\\t\\tdst[offset + i * 4 + 1] = value[i * 3 + 1];\\n\\t\\t\\t\\tdst[offset + i * 4 + 2] = value[i * 3 + 2];\\n\\t\\t}\\n};\\nclass UniformBuffer {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tif (this.persistent) {\\n\\t\\t\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\t\\t\\tthis.impl.destroy(device);\\n\\t\\t\\t\\t\\t\\tdevice._vram.ub -= this.format.byteSize;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget offset() {\\n\\t\\t\\t\\treturn this.persistent ? 0 : this.allocation.offset;\\n\\t\\t}\\n\\t\\tassignStorage(storage) {\\n\\t\\t\\t\\tthis.storageInt32 = storage;\\n\\t\\t\\t\\tthis.storageUint32 = new Uint32Array(storage.buffer, storage.byteOffset, storage.byteLength / 4);\\n\\t\\t\\t\\tthis.storageFloat32 = new Float32Array(storage.buffer, storage.byteOffset, storage.byteLength / 4);\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tthis.impl?.loseContext();\\n\\t\\t}\\n\\t\\tsetUniform(uniformFormat, value) {\\n\\t\\t\\t\\tconst offset = uniformFormat.offset;\\n\\t\\t\\t\\tif (value !== null && value !== undefined) {\\n\\t\\t\\t\\t\\t\\tconst updateFunction = _updateFunctions[uniformFormat.updateType];\\n\\t\\t\\t\\t\\t\\tif (updateFunction) {\\n\\t\\t\\t\\t\\t\\t\\t\\tupdateFunction(this, value, offset, uniformFormat.count);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.storageFloat32.set(value, offset);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tset(name, value) {\\n\\t\\t\\t\\tconst uniformFormat = this.format.map.get(name);\\n\\t\\t\\t\\tif (uniformFormat) {\\n\\t\\t\\t\\t\\t\\tthis.setUniform(uniformFormat, value);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tstartUpdate(dynamicBindGroup) {\\n\\t\\t\\t\\tif (!this.persistent) {\\n\\t\\t\\t\\t\\t\\tconst allocation = this.allocation;\\n\\t\\t\\t\\t\\t\\tconst oldGpuBuffer = allocation.gpuBuffer;\\n\\t\\t\\t\\t\\t\\tthis.device.dynamicBuffers.alloc(allocation, this.format.byteSize);\\n\\t\\t\\t\\t\\t\\tthis.assignStorage(allocation.storage);\\n\\t\\t\\t\\t\\t\\tif (dynamicBindGroup) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdynamicBindGroup.bindGroup = allocation.gpuBuffer.getBindGroup(this);\\n\\t\\t\\t\\t\\t\\t\\t\\tdynamicBindGroup.offsets[0] = allocation.offset;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (oldGpuBuffer !== allocation.gpuBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.renderVersionDirty = this.device.renderVersion;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tendUpdate() {\\n\\t\\t\\t\\tif (this.persistent) {\\n\\t\\t\\t\\t\\t\\tthis.impl.unlock(this);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.storageFloat32 = null;\\n\\t\\t\\t\\t\\t\\tthis.storageInt32 = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdate(dynamicBindGroup) {\\n\\t\\t\\t\\tthis.startUpdate(dynamicBindGroup);\\n\\t\\t\\t\\tconst uniforms = this.format.uniforms;\\n\\t\\t\\t\\tfor(let i = 0; i < uniforms.length; i++){\\n\\t\\t\\t\\t\\t\\tconst value = uniforms[i].scopeId.value;\\n\\t\\t\\t\\t\\t\\tthis.setUniform(uniforms[i], value);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.endUpdate();\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice, format, persistent = true){\\n\\t\\t\\t\\tthis.renderVersionDirty = 0;\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t\\t\\tthis.format = format;\\n\\t\\t\\t\\tthis.persistent = persistent;\\n\\t\\t\\t\\tif (persistent) {\\n\\t\\t\\t\\t\\t\\tthis.impl = graphicsDevice.createUniformBufferImpl(this);\\n\\t\\t\\t\\t\\t\\tconst storage = new ArrayBuffer(format.byteSize);\\n\\t\\t\\t\\t\\t\\tthis.assignStorage(new Int32Array(storage));\\n\\t\\t\\t\\t\\t\\tgraphicsDevice._vram.ub += this.format.byteSize;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.allocation = new DynamicBufferAllocation();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nconst primitive = {\\n\\t\\ttype: PRIMITIVE_TRISTRIP,\\n\\t\\tbase: 0,\\n\\t\\tbaseVertex: 0,\\n\\t\\tcount: 4,\\n\\t\\tindexed: false\\n};\\nclass WebgpuClearRenderer {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.shader.destroy();\\n\\t\\t\\t\\tthis.shader = null;\\n\\t\\t\\t\\tthis.uniformBuffer.destroy();\\n\\t\\t\\t\\tthis.uniformBuffer = null;\\n\\t\\t}\\n\\t\\tclear(device, renderTarget, options, defaultOptions) {\\n\\t\\t\\t\\toptions = options || defaultOptions;\\n\\t\\t\\t\\tconst flags = options.flags ?? defaultOptions.flags;\\n\\t\\t\\t\\tif (flags !== 0) {\\n\\t\\t\\t\\t\\t\\tconst { uniformBuffer, dynamicBindGroup } = this;\\n\\t\\t\\t\\t\\t\\tuniformBuffer.startUpdate(dynamicBindGroup);\\n\\t\\t\\t\\t\\t\\tdevice.setBindGroup(BINDGROUP_MESH_UB, dynamicBindGroup.bindGroup, dynamicBindGroup.offsets);\\n\\t\\t\\t\\t\\t\\tdevice.setBindGroup(BINDGROUP_MESH, device.emptyBindGroup);\\n\\t\\t\\t\\t\\t\\tif (flags & CLEARFLAG_COLOR && (renderTarget.colorBuffer || renderTarget.impl.assignedColorTexture)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst color = options.color ?? defaultOptions.color;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.colorData.set(color);\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.setBlendState(BlendState.NOBLEND);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.setBlendState(BlendState.NOWRITE);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tuniformBuffer.set('color', this.colorData);\\n\\t\\t\\t\\t\\t\\tif (flags & CLEARFLAG_DEPTH && renderTarget.depth) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst depth = options.depth ?? defaultOptions.depth;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformBuffer.set('depth', depth);\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.setDepthState(DepthState.WRITEDEPTH);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformBuffer.set('depth', 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.setDepthState(DepthState.NODEPTH);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (flags & CLEARFLAG_STENCIL && renderTarget.stencil) ;\\n\\t\\t\\t\\t\\t\\tuniformBuffer.endUpdate();\\n\\t\\t\\t\\t\\t\\tdevice.setCullMode(CULLFACE_NONE);\\n\\t\\t\\t\\t\\t\\tdevice.setShader(this.shader);\\n\\t\\t\\t\\t\\t\\tdevice.draw(primitive);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\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\\t\\t\\tthis.shader = new Shader(device, {\\n\\t\\t\\t\\t\\t\\tname: 'WebGPUClearRendererShader',\\n\\t\\t\\t\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\t\\t\\t\\tvshader: code,\\n\\t\\t\\t\\t\\t\\tfshader: code\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.uniformBuffer = new UniformBuffer(device, new UniformBufferFormat(device, [\\n\\t\\t\\t\\t\\t\\tnew UniformFormat('color', UNIFORMTYPE_VEC4),\\n\\t\\t\\t\\t\\t\\tnew UniformFormat('depth', UNIFORMTYPE_FLOAT)\\n\\t\\t\\t\\t]), false);\\n\\t\\t\\t\\tthis.dynamicBindGroup = new DynamicBindGroup();\\n\\t\\t\\t\\tthis.colorData = new Float32Array(4);\\n\\t\\t}\\n}\\n\\nclass WebgpuMipmapRenderer {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.shader.destroy();\\n\\t\\t\\t\\tthis.shader = null;\\n\\t\\t\\t\\tthis.pipelineCache.clear();\\n\\t\\t}\\n\\t\\tgenerate(webgpuTexture) {\\n\\t\\t\\t\\tconst textureDescr = webgpuTexture.desc;\\n\\t\\t\\t\\tif (textureDescr.mipLevelCount <= 1) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (webgpuTexture.texture.volume) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tconst wgpu = device.wgpu;\\n\\t\\t\\t\\tconst format = textureDescr.format;\\n\\t\\t\\t\\tlet pipeline = this.pipelineCache.get(format);\\n\\t\\t\\t\\tif (!pipeline) {\\n\\t\\t\\t\\t\\t\\tconst webgpuShader = this.shader.impl;\\n\\t\\t\\t\\t\\t\\tpipeline = wgpu.createRenderPipeline({\\n\\t\\t\\t\\t\\t\\t\\t\\tlayout: 'auto',\\n\\t\\t\\t\\t\\t\\t\\t\\tvertex: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmodule: webgpuShader.getVertexShaderModule(),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tentryPoint: webgpuShader.vertexEntryPoint\\n\\t\\t\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t\\t\\tfragment: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmodule: webgpuShader.getFragmentShaderModule(),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tentryPoint: webgpuShader.fragmentEntryPoint,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttargets: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: format\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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\\tprimitive: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttopology: 'triangle-strip'\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tthis.pipelineCache.set(format, pipeline);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst texture = webgpuTexture.texture;\\n\\t\\t\\t\\tconst numFaces = texture.cubemap ? 6 : texture.array ? texture.arrayLength : 1;\\n\\t\\t\\t\\tconst srcViews = [];\\n\\t\\t\\t\\tfor(let face = 0; face < numFaces; face++){\\n\\t\\t\\t\\t\\t\\tsrcViews.push(webgpuTexture.createView({\\n\\t\\t\\t\\t\\t\\t\\t\\tdimension: '2d',\\n\\t\\t\\t\\t\\t\\t\\t\\tbaseMipLevel: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipLevelCount: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\tbaseArrayLayer: face\\n\\t\\t\\t\\t\\t\\t}));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst commandEncoder = device.getCommandEncoder();\\n\\t\\t\\t\\tfor(let i = 1; i < textureDescr.mipLevelCount; i++){\\n\\t\\t\\t\\t\\t\\tfor(let face = 0; face < numFaces; face++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dstView = webgpuTexture.createView({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdimension: '2d',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbaseMipLevel: i,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmipLevelCount: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbaseArrayLayer: face\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tconst passEncoder = commandEncoder.beginRenderPass({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcolorAttachments: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tview: dstView,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tloadOp: 'clear',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstoreOp: 'store'\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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 bindGroup = wgpu.createBindGroup({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayout: pipeline.getBindGroupLayout(0),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tentries: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbinding: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresource: this.minSampler\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbinding: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresource: srcViews[face]\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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\\tpassEncoder.setPipeline(pipeline);\\n\\t\\t\\t\\t\\t\\t\\t\\tpassEncoder.setBindGroup(0, bindGroup);\\n\\t\\t\\t\\t\\t\\t\\t\\tpassEncoder.draw(4);\\n\\t\\t\\t\\t\\t\\t\\t\\tpassEncoder.end();\\n\\t\\t\\t\\t\\t\\t\\t\\tsrcViews[face] = dstView;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdevice.pipeline = null;\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis.pipelineCache = new Map();\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\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\\t\\t\\tthis.shader = new Shader(device, {\\n\\t\\t\\t\\t\\t\\tname: 'WebGPUMipmapRendererShader',\\n\\t\\t\\t\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\t\\t\\t\\tvshader: code,\\n\\t\\t\\t\\t\\t\\tfshader: code\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.minSampler = device.wgpu.createSampler({\\n\\t\\t\\t\\t\\t\\tminFilter: 'linear'\\n\\t\\t\\t\\t});\\n\\t\\t}\\n}\\n\\nclass DynamicBuffer {\\n\\t\\tgetBindGroup(ub) {\\n\\t\\t\\t\\tconst ubSize = ub.format.byteSize;\\n\\t\\t\\t\\tlet bindGroup = this.bindGroupCache.get(ubSize);\\n\\t\\t\\t\\tif (!bindGroup) {\\n\\t\\t\\t\\t\\t\\tbindGroup = new BindGroup(this.device, this.bindGroupFormat, ub);\\n\\t\\t\\t\\t\\t\\tbindGroup.update();\\n\\t\\t\\t\\t\\t\\tthis.bindGroupCache.set(ubSize, bindGroup);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn bindGroup;\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis.bindGroupCache = new Map();\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.bindGroupFormat = new BindGroupFormat(this.device, [\\n\\t\\t\\t\\t\\t\\tnew BindUniformBufferFormat(UNIFORM_BUFFER_DEFAULT_SLOT_NAME, SHADERSTAGE_VERTEX | SHADERSTAGE_FRAGMENT)\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n}\\n\\nclass WebgpuDynamicBuffer extends DynamicBuffer {\\n\\t\\tdestroy(device) {\\n\\t\\t\\t\\tdevice._vram.ub -= this.buffer.size;\\n\\t\\t\\t\\tthis.buffer.destroy();\\n\\t\\t\\t\\tthis.buffer = null;\\n\\t\\t}\\n\\t\\tonAvailable() {\\n\\t\\t\\t\\tthis.mappedRange = this.buffer.getMappedRange();\\n\\t\\t}\\n\\t\\talloc(offset, size) {\\n\\t\\t\\t\\treturn new Int32Array(this.mappedRange, offset, size / 4);\\n\\t\\t}\\n\\t\\tconstructor(device, size, isStaging){\\n\\t\\t\\t\\tsuper(device), this.buffer = null, this.mappedRange = null;\\n\\t\\t\\t\\tthis.buffer = device.wgpu.createBuffer({\\n\\t\\t\\t\\t\\t\\tsize: size,\\n\\t\\t\\t\\t\\t\\tusage: isStaging ? GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC : GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\\n\\t\\t\\t\\t\\t\\tmappedAtCreation: isStaging\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (isStaging) {\\n\\t\\t\\t\\t\\t\\tthis.onAvailable();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdevice._vram.ub += size;\\n\\t\\t}\\n}\\n\\nclass WebgpuDynamicBuffers extends DynamicBuffers {\\n\\t\\tcreateBuffer(device, size, isStaging) {\\n\\t\\t\\t\\treturn new WebgpuDynamicBuffer(device, size, isStaging);\\n\\t\\t}\\n\\t\\tsubmit() {\\n\\t\\t\\t\\tsuper.submit();\\n\\t\\t\\t\\tconst count = this.usedBuffers.length;\\n\\t\\t\\t\\tif (count) {\\n\\t\\t\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\t\\t\\tconst gpuBuffers = this.gpuBuffers;\\n\\t\\t\\t\\t\\t\\tconst commandEncoder = device.wgpu.createCommandEncoder();\\n\\t\\t\\t\\t\\t\\tfor(let i = count - 1; i >= 0; i--){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst usedBuffer = this.usedBuffers[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst { stagingBuffer, gpuBuffer, offset, size } = usedBuffer;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst src = stagingBuffer.buffer;\\n\\t\\t\\t\\t\\t\\t\\t\\tsrc.unmap();\\n\\t\\t\\t\\t\\t\\t\\t\\tcommandEncoder.copyBufferToBuffer(src, offset, gpuBuffer.buffer, offset, size);\\n\\t\\t\\t\\t\\t\\t\\t\\tgpuBuffers.push(gpuBuffer);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst cb = commandEncoder.finish();\\n\\t\\t\\t\\t\\t\\tdevice.addCommandBuffer(cb, true);\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst stagingBuffer = this.usedBuffers[i].stagingBuffer;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.pendingStagingBuffers.push(stagingBuffer);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.usedBuffers.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonCommandBuffersSubmitted() {\\n\\t\\t\\t\\tconst count = this.pendingStagingBuffers.length;\\n\\t\\t\\t\\tif (count) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst stagingBuffer = this.pendingStagingBuffers[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tstagingBuffer.buffer.mapAsync(GPUMapMode.WRITE).then(()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this.stagingBuffers) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstagingBuffer.onAvailable();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.stagingBuffers.push(stagingBuffer);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tthis.pendingStagingBuffers.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(...args){\\n\\t\\t\\t\\tsuper(...args), this.pendingStagingBuffers = [];\\n\\t\\t}\\n}\\n\\nclass GpuProfiler {\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tthis.pastFrameAllocations.clear();\\n\\t\\t}\\n\\t\\tset enabled(value) {\\n\\t\\t\\t\\tthis._enableRequest = value;\\n\\t\\t}\\n\\t\\tget enabled() {\\n\\t\\t\\t\\treturn this._enableRequest;\\n\\t\\t}\\n\\t\\tget passTimings() {\\n\\t\\t\\t\\treturn this._passTimings;\\n\\t\\t}\\n\\t\\tprocessEnableRequest() {\\n\\t\\t\\t\\tif (this._enableRequest !== this._enabled) {\\n\\t\\t\\t\\t\\t\\tthis._enabled = this._enableRequest;\\n\\t\\t\\t\\t\\t\\tif (!this._enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._frameTime = 0;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\trequest(renderVersion) {\\n\\t\\t\\t\\tthis.pastFrameAllocations.set(renderVersion, this.frameAllocations);\\n\\t\\t\\t\\tthis.frameAllocations = [];\\n\\t\\t}\\n\\t\\t_parsePassName(name) {\\n\\t\\t\\t\\tlet parsedName = this._nameCache.get(name);\\n\\t\\t\\t\\tif (parsedName === undefined) {\\n\\t\\t\\t\\t\\t\\tif (name.startsWith('RenderPass')) {\\n\\t\\t\\t\\t\\t\\t\\t\\tparsedName = name.substring(10);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tparsedName = name;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._nameCache.set(name, parsedName);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn parsedName;\\n\\t\\t}\\n\\t\\treport(renderVersion, timings) {\\n\\t\\t\\t\\tif (timings) {\\n\\t\\t\\t\\t\\t\\tconst allocations = this.pastFrameAllocations.get(renderVersion);\\n\\t\\t\\t\\t\\t\\tif (!allocations) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (timings.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._frameTime = timings.reduce((sum, t)=>sum + t, 0);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._passTimings.clear();\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < allocations.length; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst name = allocations[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst timing = timings[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst parsedName = this._parsePassName(name);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._passTimings.set(parsedName, (this._passTimings.get(parsedName) || 0) + timing);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (Tracing.get(TRACEID_GPU_TIMINGS)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlet total = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < allocations.length; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tallocations[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttotal += timings[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.pastFrameAllocations.delete(renderVersion);\\n\\t\\t}\\n\\t\\tgetSlot(name) {\\n\\t\\t\\t\\tif (this.frameAllocations.length >= this.maxCount) {\\n\\t\\t\\t\\t\\t\\treturn -1;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst slot = this.frameAllocations.length;\\n\\t\\t\\t\\tthis.frameAllocations.push(name);\\n\\t\\t\\t\\treturn slot;\\n\\t\\t}\\n\\t\\tget slotCount() {\\n\\t\\t\\t\\treturn this.frameAllocations.length;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.frameAllocations = [];\\n\\t\\t\\t\\tthis.pastFrameAllocations = new Map();\\n\\t\\t\\t\\tthis._enabled = false;\\n\\t\\t\\t\\tthis._enableRequest = false;\\n\\t\\t\\t\\tthis._frameTime = 0;\\n\\t\\t\\t\\tthis._passTimings = new Map();\\n\\t\\t\\t\\tthis._nameCache = new Map();\\n\\t\\t\\t\\tthis.maxCount = 9999;\\n\\t\\t}\\n}\\n\\nclass WebgpuQuerySet {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.querySet?.destroy();\\n\\t\\t\\t\\tthis.querySet = null;\\n\\t\\t\\t\\tthis.queryBuffer?.destroy();\\n\\t\\t\\t\\tthis.queryBuffer = null;\\n\\t\\t\\t\\tthis.activeStagingBuffer = null;\\n\\t\\t\\t\\tthis.stagingBuffers.forEach((stagingBuffer)=>{\\n\\t\\t\\t\\t\\t\\tstagingBuffer.destroy();\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.stagingBuffers = null;\\n\\t\\t}\\n\\t\\tgetStagingBuffer() {\\n\\t\\t\\t\\tlet stagingBuffer = this.stagingBuffers.pop();\\n\\t\\t\\t\\tif (!stagingBuffer) {\\n\\t\\t\\t\\t\\t\\tstagingBuffer = this.device.wgpu.createBuffer({\\n\\t\\t\\t\\t\\t\\t\\t\\tsize: this.queryBuffer.size,\\n\\t\\t\\t\\t\\t\\t\\t\\tusage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn stagingBuffer;\\n\\t\\t}\\n\\t\\tresolve(count) {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tconst commandEncoder = device.getCommandEncoder();\\n\\t\\t\\t\\tcommandEncoder.resolveQuerySet(this.querySet, 0, count, this.queryBuffer, 0);\\n\\t\\t\\t\\tconst activeStagingBuffer = this.getStagingBuffer();\\n\\t\\t\\t\\tthis.activeStagingBuffer = activeStagingBuffer;\\n\\t\\t\\t\\tcommandEncoder.copyBufferToBuffer(this.queryBuffer, 0, activeStagingBuffer, 0, this.bytesPerSlot * count);\\n\\t\\t}\\n\\t\\trequest(count, renderVersion) {\\n\\t\\t\\t\\tconst stagingBuffer = this.activeStagingBuffer;\\n\\t\\t\\t\\tthis.activeStagingBuffer = null;\\n\\t\\t\\t\\treturn stagingBuffer.mapAsync(GPUMapMode.READ).then(()=>{\\n\\t\\t\\t\\t\\t\\tconst srcTimings = new BigInt64Array(stagingBuffer.getMappedRange());\\n\\t\\t\\t\\t\\t\\tconst timings = [];\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\ttimings.push(Number(srcTimings[i * 2 + 1] - srcTimings[i * 2]) * 0.000001);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tstagingBuffer.unmap();\\n\\t\\t\\t\\t\\t\\tthis.stagingBuffers?.push(stagingBuffer);\\n\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\trenderVersion,\\n\\t\\t\\t\\t\\t\\t\\t\\ttimings\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tconstructor(device, isTimestamp, capacity){\\n\\t\\t\\t\\tthis.stagingBuffers = [];\\n\\t\\t\\t\\tthis.activeStagingBuffer = null;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.capacity = capacity;\\n\\t\\t\\t\\tthis.bytesPerSlot = isTimestamp ? 8 : 4;\\n\\t\\t\\t\\tconst wgpu = device.wgpu;\\n\\t\\t\\t\\tthis.querySet = wgpu.createQuerySet({\\n\\t\\t\\t\\t\\t\\ttype: isTimestamp ? 'timestamp' : 'occlusion',\\n\\t\\t\\t\\t\\t\\tcount: capacity\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.queryBuffer = wgpu.createBuffer({\\n\\t\\t\\t\\t\\t\\tsize: this.bytesPerSlot * capacity,\\n\\t\\t\\t\\t\\t\\tusage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST\\n\\t\\t\\t\\t});\\n\\t\\t}\\n}\\n\\nclass WebgpuGpuProfiler extends GpuProfiler {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.timestampQueriesSet?.destroy();\\n\\t\\t\\t\\tthis.timestampQueriesSet = null;\\n\\t\\t}\\n\\t\\tframeStart() {\\n\\t\\t\\t\\tthis.processEnableRequest();\\n\\t\\t}\\n\\t\\tframeEnd() {\\n\\t\\t\\t\\tif (this._enabled) {\\n\\t\\t\\t\\t\\t\\tthis.timestampQueriesSet?.resolve(this.slotCount * 2);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\trequest() {\\n\\t\\t\\t\\tif (this._enabled) {\\n\\t\\t\\t\\t\\t\\tconst renderVersion = this.device.renderVersion;\\n\\t\\t\\t\\t\\t\\tthis.timestampQueriesSet?.request(this.slotCount, renderVersion).then((results)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.report(results.renderVersion, results.timings);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tsuper.request(renderVersion);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.maxCount = 1024;\\n\\t\\t\\t\\tthis.timestampQueriesSet = device.supportsTimestampQuery ? new WebgpuQuerySet(device, true, 2 * this.maxCount) : null;\\n\\t\\t}\\n}\\n\\nclass WebgpuResolver {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.shader.destroy();\\n\\t\\t\\t\\tthis.shader = null;\\n\\t\\t\\t\\tthis.pipelineCache = null;\\n\\t\\t}\\n\\t\\tgetPipeline(format) {\\n\\t\\t\\t\\tlet pipeline = this.pipelineCache.get(format);\\n\\t\\t\\t\\tif (!pipeline) {\\n\\t\\t\\t\\t\\t\\tpipeline = this.createPipeline(format);\\n\\t\\t\\t\\t\\t\\tthis.pipelineCache.set(format, pipeline);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn pipeline;\\n\\t\\t}\\n\\t\\tcreatePipeline(format) {\\n\\t\\t\\t\\tconst webgpuShader = this.shader.impl;\\n\\t\\t\\t\\tconst pipeline = this.device.wgpu.createRenderPipeline({\\n\\t\\t\\t\\t\\t\\tlayout: 'auto',\\n\\t\\t\\t\\t\\t\\tvertex: {\\n\\t\\t\\t\\t\\t\\t\\t\\tmodule: webgpuShader.getVertexShaderModule(),\\n\\t\\t\\t\\t\\t\\t\\t\\tentryPoint: webgpuShader.vertexEntryPoint\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tfragment: {\\n\\t\\t\\t\\t\\t\\t\\t\\tmodule: webgpuShader.getFragmentShaderModule(),\\n\\t\\t\\t\\t\\t\\t\\t\\tentryPoint: webgpuShader.fragmentEntryPoint,\\n\\t\\t\\t\\t\\t\\t\\t\\ttargets: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: format\\n\\t\\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},\\n\\t\\t\\t\\t\\t\\tprimitive: {\\n\\t\\t\\t\\t\\t\\t\\t\\ttopology: 'triangle-strip'\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn pipeline;\\n\\t\\t}\\n\\t\\tresolveDepth(commandEncoder, sourceTexture, destinationTexture) {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tconst wgpu = device.wgpu;\\n\\t\\t\\t\\tconst pipeline = this.getPipeline(destinationTexture.format);\\n\\t\\t\\t\\tconst numFaces = sourceTexture.depthOrArrayLayers;\\n\\t\\t\\t\\tfor(let face = 0; face < numFaces; face++){\\n\\t\\t\\t\\t\\t\\tconst srcView = sourceTexture.createView({\\n\\t\\t\\t\\t\\t\\t\\t\\tdimension: '2d',\\n\\t\\t\\t\\t\\t\\t\\t\\taspect: 'depth-only',\\n\\t\\t\\t\\t\\t\\t\\t\\tbaseMipLevel: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipLevelCount: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\tbaseArrayLayer: face\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tconst dstView = destinationTexture.createView({\\n\\t\\t\\t\\t\\t\\t\\t\\tdimension: '2d',\\n\\t\\t\\t\\t\\t\\t\\t\\tbaseMipLevel: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipLevelCount: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\tbaseArrayLayer: face\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tconst passEncoder = commandEncoder.beginRenderPass({\\n\\t\\t\\t\\t\\t\\t\\t\\tcolorAttachments: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tview: dstView,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tloadOp: 'clear',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstoreOp: 'store'\\n\\t\\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});\\n\\t\\t\\t\\t\\t\\tconst bindGroup = wgpu.createBindGroup({\\n\\t\\t\\t\\t\\t\\t\\t\\tlayout: pipeline.getBindGroupLayout(0),\\n\\t\\t\\t\\t\\t\\t\\t\\tentries: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbinding: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresource: srcView\\n\\t\\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});\\n\\t\\t\\t\\t\\t\\tpassEncoder.setPipeline(pipeline);\\n\\t\\t\\t\\t\\t\\tpassEncoder.setBindGroup(0, bindGroup);\\n\\t\\t\\t\\t\\t\\tpassEncoder.draw(4);\\n\\t\\t\\t\\t\\t\\tpassEncoder.end();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdevice.pipeline = null;\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis.pipelineCache = new Map();\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\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\\t\\t\\tthis.shader = new Shader(device, {\\n\\t\\t\\t\\t\\t\\tname: 'WebGPUResolverDepthShader',\\n\\t\\t\\t\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\t\\t\\t\\tvshader: code,\\n\\t\\t\\t\\t\\t\\tfshader: code\\n\\t\\t\\t\\t});\\n\\t\\t}\\n}\\n\\nconst _indirectDispatchEntryByteSize$1 = 3 * 4;\\nclass WebgpuCompute {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.uniformBuffers.forEach((ub)=>ub.destroy());\\n\\t\\t\\t\\tthis.uniformBuffers.length = 0;\\n\\t\\t\\t\\tthis.bindGroup.destroy();\\n\\t\\t\\t\\tthis.bindGroup = null;\\n\\t\\t}\\n\\t\\tupdateBindGroup() {\\n\\t\\t\\t\\tconst { bindGroup } = this;\\n\\t\\t\\t\\tbindGroup.updateUniformBuffers();\\n\\t\\t\\t\\tbindGroup.update();\\n\\t\\t}\\n\\t\\tdispatch(x, y, z) {\\n\\t\\t\\t\\tconst device = this.compute.device;\\n\\t\\t\\t\\tdevice.setBindGroup(0, this.bindGroup);\\n\\t\\t\\t\\tconst passEncoder = device.passEncoder;\\n\\t\\t\\t\\tpassEncoder.setPipeline(this.pipeline);\\n\\t\\t\\t\\tconst { indirectSlotIndex, indirectBuffer, indirectFrameStamp } = this.compute;\\n\\t\\t\\t\\tif (indirectSlotIndex >= 0) {\\n\\t\\t\\t\\t\\t\\tlet gpuBuffer;\\n\\t\\t\\t\\t\\t\\tif (indirectBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgpuBuffer = indirectBuffer.impl.buffer;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tgpuBuffer = device.indirectDispatchBuffer.impl.buffer;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst offset = indirectSlotIndex * _indirectDispatchEntryByteSize$1;\\n\\t\\t\\t\\t\\t\\tpassEncoder.dispatchWorkgroupsIndirect(gpuBuffer, offset);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tpassEncoder.dispatchWorkgroups(x, y, z);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(compute){\\n\\t\\t\\t\\tthis.uniformBuffers = [];\\n\\t\\t\\t\\tthis.bindGroup = null;\\n\\t\\t\\t\\tthis.compute = compute;\\n\\t\\t\\t\\tconst { device, shader } = compute;\\n\\t\\t\\t\\tconst { computeBindGroupFormat, computeUniformBufferFormats } = shader.impl;\\n\\t\\t\\t\\tthis.bindGroup = new BindGroup(device, computeBindGroupFormat);\\n\\t\\t\\t\\tif (computeUniformBufferFormats) {\\n\\t\\t\\t\\t\\t\\tfor(const name in computeUniformBufferFormats){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (computeUniformBufferFormats.hasOwnProperty(name)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst ub = new UniformBuffer(device, computeUniformBufferFormats[name], true);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.uniformBuffers.push(ub);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.bindGroup.setUniformBuffer(name, ub);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.pipeline = device.computePipeline.get(shader, computeBindGroupFormat);\\n\\t\\t}\\n}\\n\\nlet id$6 = 0;\\nclass StorageBuffer {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tdevice.buffers.delete(this);\\n\\t\\t\\t\\tthis.adjustVramSizeTracking(device._vram, -this.byteSize);\\n\\t\\t\\t\\tthis.impl.destroy(device);\\n\\t\\t}\\n\\t\\tadjustVramSizeTracking(vram, size) {\\n\\t\\t\\t\\tvram.sb += size;\\n\\t\\t}\\n\\t\\tread(offset = 0, size = this.byteSize, data = null, immediate = false) {\\n\\t\\t\\t\\treturn this.impl.read(this.device, offset, size, data, immediate);\\n\\t\\t}\\n\\t\\twrite(bufferOffset = 0, data, dataOffset = 0, size) {\\n\\t\\t\\t\\tthis.impl.write(this.device, bufferOffset, data, dataOffset, size);\\n\\t\\t}\\n\\t\\tclear(offset = 0, size = this.byteSize) {\\n\\t\\t\\t\\tthis.impl.clear(this.device, offset, size);\\n\\t\\t}\\n\\t\\tcopy(srcBuffer, srcOffset = 0, dstOffset = 0, size = srcBuffer.byteSize - srcOffset) {\\n\\t\\t\\t\\tconst commandEncoder = this.device.getCommandEncoder();\\n\\t\\t\\t\\tcommandEncoder.copyBufferToBuffer(srcBuffer.impl.buffer, srcOffset, this.impl.buffer, dstOffset, size);\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice, byteSize, bufferUsage = 0, addStorageUsage = true){\\n\\t\\t\\t\\tthis.id = id$6++;\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t\\t\\tthis.byteSize = byteSize;\\n\\t\\t\\t\\tthis.bufferUsage = bufferUsage;\\n\\t\\t\\t\\tconst usage = addStorageUsage ? BUFFERUSAGE_STORAGE | bufferUsage : bufferUsage;\\n\\t\\t\\t\\tthis.impl = graphicsDevice.createBufferImpl(usage);\\n\\t\\t\\t\\tthis.impl.allocate(graphicsDevice, byteSize);\\n\\t\\t\\t\\tthis.device.buffers.add(this);\\n\\t\\t\\t\\tthis.adjustVramSizeTracking(graphicsDevice._vram, this.byteSize);\\n\\t\\t}\\n}\\n\\nclass WebgpuDrawCommands {\\n\\t\\tallocate(maxCount) {\\n\\t\\t\\t\\tif (this.gpuIndirect && this.gpuIndirect.length === 5 * maxCount) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.storage?.destroy();\\n\\t\\t\\t\\tthis.gpuIndirect = new Uint32Array(5 * maxCount);\\n\\t\\t\\t\\tthis.gpuIndirectSigned = new Int32Array(this.gpuIndirect.buffer);\\n\\t\\t\\t\\tthis.storage = new StorageBuffer(this.device, this.gpuIndirect.byteLength, BUFFERUSAGE_INDIRECT | BUFFERUSAGE_COPY_DST);\\n\\t\\t}\\n\\t\\tadd(i, indexOrVertexCount, instanceCount, firstIndexOrVertex, baseVertex = 0, firstInstance = 0) {\\n\\t\\t\\t\\tconst o = i * 5;\\n\\t\\t\\t\\tthis.gpuIndirect[o + 0] = indexOrVertexCount;\\n\\t\\t\\t\\tthis.gpuIndirect[o + 1] = instanceCount;\\n\\t\\t\\t\\tthis.gpuIndirect[o + 2] = firstIndexOrVertex;\\n\\t\\t\\t\\tthis.gpuIndirectSigned[o + 3] = baseVertex;\\n\\t\\t\\t\\tthis.gpuIndirect[o + 4] = firstInstance;\\n\\t\\t}\\n\\t\\tupdate(count) {\\n\\t\\t\\t\\tif (this.storage && count > 0) {\\n\\t\\t\\t\\t\\t\\tconst used = count * 5;\\n\\t\\t\\t\\t\\t\\tthis.storage.write(0, this.gpuIndirect, 0, used);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet totalPrimitives = 0;\\n\\t\\t\\t\\treturn totalPrimitives;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.storage?.destroy();\\n\\t\\t\\t\\tthis.storage = null;\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis.gpuIndirect = null;\\n\\t\\t\\t\\tthis.gpuIndirectSigned = null;\\n\\t\\t\\t\\tthis.storage = null;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t}\\n}\\n\\nclass WebgpuUploadStream {\\n\\t\\t_onDeviceLost() {}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._destroyed = true;\\n\\t\\t\\t\\tthis.availableStagingBuffers.forEach((buffer)=>buffer.destroy());\\n\\t\\t\\t\\tthis.pendingStagingBuffers.forEach((buffer)=>buffer.destroy());\\n\\t\\t}\\n\\t\\tupdate(minByteSize) {\\n\\t\\t\\t\\tconst pending = this.pendingStagingBuffers;\\n\\t\\t\\t\\tfor(let i = 0; i < pending.length; i++){\\n\\t\\t\\t\\t\\t\\tconst buffer = pending[i];\\n\\t\\t\\t\\t\\t\\tbuffer.mapAsync(GPUMapMode.WRITE).then(()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this._destroyed) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.availableStagingBuffers.push(buffer);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbuffer.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tpending.length = 0;\\n\\t\\t\\t\\tconst available = this.availableStagingBuffers;\\n\\t\\t\\t\\tfor(let i = available.length - 1; i >= 0; i--){\\n\\t\\t\\t\\t\\t\\tif (available[i].size < minByteSize) {\\n\\t\\t\\t\\t\\t\\t\\t\\tavailable[i].destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\tavailable.splice(i, 1);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupload(data, target, offset, size) {\\n\\t\\t\\t\\tif (this.useSingleBuffer) {\\n\\t\\t\\t\\t\\t\\tthis.uploadDirect(data, target, offset, size);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.uploadStaging(data, target, offset, size);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tuploadDirect(data, target, offset, size) {\\n\\t\\t\\t\\tconst byteOffset = offset * data.BYTES_PER_ELEMENT;\\n\\t\\t\\t\\tsize * data.BYTES_PER_ELEMENT;\\n\\t\\t\\t\\ttarget.write(byteOffset, data, 0, size);\\n\\t\\t}\\n\\t\\tuploadStaging(data, target, offset, size) {\\n\\t\\t\\t\\tconst device = this.uploadStream.device;\\n\\t\\t\\t\\tconst byteOffset = offset * data.BYTES_PER_ELEMENT;\\n\\t\\t\\t\\tconst byteSize = size * data.BYTES_PER_ELEMENT;\\n\\t\\t\\t\\tthis.update(byteSize);\\n\\t\\t\\t\\tconst buffer = this.availableStagingBuffers.pop() ?? (()=>{\\n\\t\\t\\t\\t\\t\\tconst newBuffer = this.uploadStream.device.wgpu.createBuffer({\\n\\t\\t\\t\\t\\t\\t\\t\\tsize: byteSize,\\n\\t\\t\\t\\t\\t\\t\\t\\tusage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC,\\n\\t\\t\\t\\t\\t\\t\\t\\tmappedAtCreation: true\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\treturn newBuffer;\\n\\t\\t\\t\\t})();\\n\\t\\t\\t\\tconst mappedRange = buffer.getMappedRange();\\n\\t\\t\\t\\tnew Uint8Array(mappedRange).set(new Uint8Array(data.buffer, data.byteOffset, byteSize));\\n\\t\\t\\t\\tbuffer.unmap();\\n\\t\\t\\t\\tdevice.getCommandEncoder().copyBufferToBuffer(buffer, 0, target.impl.buffer, byteOffset, byteSize);\\n\\t\\t\\t\\tthis.pendingStagingBuffers.push(buffer);\\n\\t\\t}\\n\\t\\tconstructor(uploadStream){\\n\\t\\t\\t\\tthis.availableStagingBuffers = [];\\n\\t\\t\\t\\tthis.pendingStagingBuffers = [];\\n\\t\\t\\t\\tthis._destroyed = false;\\n\\t\\t\\t\\tthis.uploadStream = uploadStream;\\n\\t\\t\\t\\tthis.useSingleBuffer = uploadStream.useSingleBuffer;\\n\\t\\t}\\n}\\n\\nconst _uniqueLocations = new Map();\\nconst _indirectEntryByteSize = 5 * 4;\\nconst _indirectDispatchEntryByteSize = 3 * 4;\\nclass WebgpuGraphicsDevice extends GraphicsDevice {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.clearRenderer.destroy();\\n\\t\\t\\t\\tthis.clearRenderer = null;\\n\\t\\t\\t\\tthis.mipmapRenderer.destroy();\\n\\t\\t\\t\\tthis.mipmapRenderer = null;\\n\\t\\t\\t\\tthis.resolver.destroy();\\n\\t\\t\\t\\tthis.resolver = null;\\n\\t\\t\\t\\tsuper.destroy();\\n\\t\\t}\\n\\t\\tinitDeviceCaps() {\\n\\t\\t\\t\\tconst limits = this.wgpu?.limits;\\n\\t\\t\\t\\tthis.limits = limits;\\n\\t\\t\\t\\tthis.precision = 'highp';\\n\\t\\t\\t\\tthis.maxPrecision = 'highp';\\n\\t\\t\\t\\tthis.maxSamples = 4;\\n\\t\\t\\t\\tthis.maxTextures = 16;\\n\\t\\t\\t\\tthis.maxTextureSize = limits.maxTextureDimension2D;\\n\\t\\t\\t\\tthis.maxCubeMapSize = limits.maxTextureDimension2D;\\n\\t\\t\\t\\tthis.maxVolumeSize = limits.maxTextureDimension3D;\\n\\t\\t\\t\\tthis.maxColorAttachments = limits.maxColorAttachments;\\n\\t\\t\\t\\tthis.maxPixelRatio = 1;\\n\\t\\t\\t\\tthis.maxAnisotropy = 16;\\n\\t\\t\\t\\tthis.fragmentUniformsCount = limits.maxUniformBufferBindingSize / 16;\\n\\t\\t\\t\\tthis.vertexUniformsCount = limits.maxUniformBufferBindingSize / 16;\\n\\t\\t\\t\\tthis.supportsUniformBuffers = true;\\n\\t\\t\\t\\tthis.supportsAreaLights = true;\\n\\t\\t\\t\\tthis.supportsGpuParticles = true;\\n\\t\\t\\t\\tthis.supportsCompute = true;\\n\\t\\t\\t\\tthis.textureFloatRenderable = true;\\n\\t\\t\\t\\tthis.textureHalfFloatRenderable = true;\\n\\t\\t\\t\\tthis.supportsImageBitmap = true;\\n\\t\\t\\t\\tthis.samples = this.backBufferAntialias ? 4 : 1;\\n\\t\\t\\t\\tconst wgslFeatures = window.navigator.gpu.wgslLanguageFeatures;\\n\\t\\t\\t\\tthis.supportsStorageTextureRead = wgslFeatures?.has('readonly_and_readwrite_storage_textures');\\n\\t\\t\\t\\tthis.supportsSubgroupUniformity = wgslFeatures?.has('subgroup_uniformity');\\n\\t\\t\\t\\tthis.supportsSubgroupId = wgslFeatures?.has('subgroup_id');\\n\\t\\t\\t\\tthis.initCapsDefines();\\n\\t\\t}\\n\\t\\tasync initWebGpu(glslangUrl, twgslUrl) {\\n\\t\\t\\t\\tif (!window.navigator.gpu) {\\n\\t\\t\\t\\t\\t\\tthrow new Error('Unable to retrieve GPU. Ensure you are using a browser that supports WebGPU rendering.');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (glslangUrl && twgslUrl) {\\n\\t\\t\\t\\t\\t\\tconst buildUrl = (srcPath)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\treturn new URL(srcPath, window.location.href).toString();\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tconst results = await Promise.all([\\n\\t\\t\\t\\t\\t\\t\\t\\timport(/* @vite-ignore */ /* webpackIgnore: true */ `${buildUrl(twgslUrl)}`).then((module)=>twgsl(twgslUrl.replace('.js', '.wasm'))),\\n\\t\\t\\t\\t\\t\\t\\t\\timport(/* @vite-ignore */ /* webpackIgnore: true */ `${buildUrl(glslangUrl)}`).then((module)=>module.default())\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\tthis.twgsl = results[0];\\n\\t\\t\\t\\t\\t\\tthis.glslang = results[1];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.createDevice();\\n\\t\\t}\\n\\t\\tasync createDevice() {\\n\\t\\t\\t\\tconst adapterOptions = {\\n\\t\\t\\t\\t\\t\\tpowerPreference: this.initOptions.powerPreference !== 'default' ? this.initOptions.powerPreference : undefined,\\n\\t\\t\\t\\t\\t\\txrCompatible: this.initOptions.xrCompatible\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.gpuAdapter = await window.navigator.gpu.requestAdapter(adapterOptions);\\n\\t\\t\\t\\tconst requiredFeatures = [];\\n\\t\\t\\t\\tconst requireFeature = (feature)=>{\\n\\t\\t\\t\\t\\t\\tconst supported = this.gpuAdapter.features.has(feature);\\n\\t\\t\\t\\t\\t\\tif (supported) {\\n\\t\\t\\t\\t\\t\\t\\t\\trequiredFeatures.push(feature);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn supported;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.textureFloatFilterable = requireFeature('float32-filterable');\\n\\t\\t\\t\\tthis.textureFloatBlendable = requireFeature('float32-blendable');\\n\\t\\t\\t\\tthis.extCompressedTextureS3TC = requireFeature('texture-compression-bc');\\n\\t\\t\\t\\tthis.extCompressedTextureS3TCSliced3D = requireFeature('texture-compression-bc-sliced-3d');\\n\\t\\t\\t\\tthis.extCompressedTextureETC = requireFeature('texture-compression-etc2');\\n\\t\\t\\t\\tthis.extCompressedTextureASTC = requireFeature('texture-compression-astc');\\n\\t\\t\\t\\tthis.extCompressedTextureASTCSliced3D = requireFeature('texture-compression-astc-sliced-3d');\\n\\t\\t\\t\\tthis.supportsTimestampQuery = requireFeature('timestamp-query');\\n\\t\\t\\t\\tthis.supportsDepthClip = requireFeature('depth-clip-control');\\n\\t\\t\\t\\tthis.supportsDepth32Stencil = requireFeature('depth32float-stencil8');\\n\\t\\t\\t\\tthis.supportsIndirectFirstInstance = requireFeature('indirect-first-instance');\\n\\t\\t\\t\\tthis.supportsShaderF16 = requireFeature('shader-f16');\\n\\t\\t\\t\\tthis.supportsStorageRGBA8 = requireFeature('bgra8unorm-storage');\\n\\t\\t\\t\\tthis.textureRG11B10Renderable = requireFeature('rg11b10ufloat-renderable');\\n\\t\\t\\t\\tthis.supportsClipDistances = requireFeature('clip-distances');\\n\\t\\t\\t\\tthis.supportsTextureFormatTier1 = requireFeature('texture-format-tier1');\\n\\t\\t\\t\\tthis.supportsTextureFormatTier2 = requireFeature('texture-format-tier2');\\n\\t\\t\\t\\tthis.supportsPrimitiveIndex = requireFeature('primitive-index');\\n\\t\\t\\t\\tconst adapterLimits = this.gpuAdapter?.limits;\\n\\t\\t\\t\\tconst requiredLimits = {};\\n\\t\\t\\t\\tif (adapterLimits) {\\n\\t\\t\\t\\t\\t\\tfor(const limitName in adapterLimits){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (limitName === 'minSubgroupSize' || limitName === 'maxSubgroupSize') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\trequiredLimits[limitName] = adapterLimits[limitName];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst deviceDescr = {\\n\\t\\t\\t\\t\\t\\trequiredFeatures,\\n\\t\\t\\t\\t\\t\\trequiredLimits,\\n\\t\\t\\t\\t\\t\\tdefaultQueue: {\\n\\t\\t\\t\\t\\t\\t\\t\\tlabel: 'Default Queue'\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.wgpu = await this.gpuAdapter.requestDevice(deviceDescr);\\n\\t\\t\\t\\tthis.wgpu.lost?.then(this.handleDeviceLost.bind(this));\\n\\t\\t\\t\\tthis.initDeviceCaps();\\n\\t\\t\\t\\tthis.gpuContext = this.canvas.getContext('webgpu');\\n\\t\\t\\t\\tlet canvasToneMapping = 'standard';\\n\\t\\t\\t\\tlet preferredCanvasFormat = window.navigator.gpu.getPreferredCanvasFormat();\\n\\t\\t\\t\\tconst displayFormat = this.initOptions.displayFormat;\\n\\t\\t\\t\\tthis.backBufferFormat = preferredCanvasFormat === 'rgba8unorm' ? displayFormat === DISPLAYFORMAT_LDR_SRGB ? PIXELFORMAT_SRGBA8 : PIXELFORMAT_RGBA8 : displayFormat === DISPLAYFORMAT_LDR_SRGB ? PIXELFORMAT_SBGRA8 : PIXELFORMAT_BGRA8;\\n\\t\\t\\t\\tthis.backBufferViewFormat = displayFormat === DISPLAYFORMAT_LDR_SRGB ? `${preferredCanvasFormat}-srgb` : preferredCanvasFormat;\\n\\t\\t\\t\\tif (displayFormat === DISPLAYFORMAT_HDR && this.textureFloatFilterable) {\\n\\t\\t\\t\\t\\t\\tconst hdrMediaQuery = window.matchMedia('(dynamic-range: high)');\\n\\t\\t\\t\\t\\t\\tif (hdrMediaQuery?.matches) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.backBufferFormat = PIXELFORMAT_RGBA16F;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.backBufferViewFormat = 'rgba16float';\\n\\t\\t\\t\\t\\t\\t\\t\\tpreferredCanvasFormat = 'rgba16float';\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.isHdr = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tcanvasToneMapping = 'extended';\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.canvasConfig = {\\n\\t\\t\\t\\t\\t\\tdevice: this.wgpu,\\n\\t\\t\\t\\t\\t\\tcolorSpace: 'srgb',\\n\\t\\t\\t\\t\\t\\talphaMode: this.initOptions.alpha ? 'premultiplied' : 'opaque',\\n\\t\\t\\t\\t\\t\\tformat: preferredCanvasFormat,\\n\\t\\t\\t\\t\\t\\ttoneMapping: {\\n\\t\\t\\t\\t\\t\\t\\t\\tmode: canvasToneMapping\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tusage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,\\n\\t\\t\\t\\t\\t\\tviewFormats: displayFormat === DISPLAYFORMAT_LDR_SRGB ? [\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.backBufferViewFormat\\n\\t\\t\\t\\t\\t\\t] : []\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.gpuContext?.configure(this.canvasConfig);\\n\\t\\t\\t\\tthis.createBackbuffer();\\n\\t\\t\\t\\tthis.clearRenderer = new WebgpuClearRenderer(this);\\n\\t\\t\\t\\tthis.mipmapRenderer = new WebgpuMipmapRenderer(this);\\n\\t\\t\\t\\tthis.resolver = new WebgpuResolver(this);\\n\\t\\t\\t\\tthis.postInit();\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tasync handleDeviceLost(info) {\\n\\t\\t\\t\\tif (info.reason !== 'destroyed') {\\n\\t\\t\\t\\t\\t\\tsuper.loseContext();\\n\\t\\t\\t\\t\\t\\tawait this.createDevice();\\n\\t\\t\\t\\t\\t\\tsuper.restoreContext();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tpostInit() {\\n\\t\\t\\t\\tsuper.postInit();\\n\\t\\t\\t\\tthis.initializeRenderState();\\n\\t\\t\\t\\tthis.setupPassEncoderDefaults();\\n\\t\\t\\t\\tthis.gpuProfiler = new WebgpuGpuProfiler(this);\\n\\t\\t\\t\\tthis.dynamicBuffers = new WebgpuDynamicBuffers(this, 100 * 1024, this.limits.minUniformBufferOffsetAlignment);\\n\\t\\t\\t\\tthis.emptyBindGroup = new BindGroup(this, new BindGroupFormat(this, []));\\n\\t\\t\\t\\tthis.emptyBindGroup.update();\\n\\t\\t}\\n\\t\\tcreateBackbuffer() {\\n\\t\\t\\t\\tthis.supportsStencil = this.initOptions.stencil;\\n\\t\\t\\t\\tthis.backBuffer = new RenderTarget({\\n\\t\\t\\t\\t\\t\\tname: 'WebgpuFramebuffer',\\n\\t\\t\\t\\t\\t\\tgraphicsDevice: this,\\n\\t\\t\\t\\t\\t\\tdepth: this.initOptions.depth,\\n\\t\\t\\t\\t\\t\\tstencil: this.supportsStencil,\\n\\t\\t\\t\\t\\t\\tsamples: this.samples\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.backBuffer.impl.isBackbuffer = true;\\n\\t\\t}\\n\\t\\tframeStart() {\\n\\t\\t\\t\\tsuper.frameStart();\\n\\t\\t\\t\\tthis.gpuProfiler.frameStart();\\n\\t\\t\\t\\tthis.submit();\\n\\t\\t\\t\\tconst outColorBuffer = this.gpuContext?.getCurrentTexture?.() ?? this.externalBackbuffer?.impl.gpuTexture;\\n\\t\\t\\t\\tif (this.backBufferSize.x !== outColorBuffer.width || this.backBufferSize.y !== outColorBuffer.height) {\\n\\t\\t\\t\\t\\t\\tthis.backBufferSize.set(outColorBuffer.width, outColorBuffer.height);\\n\\t\\t\\t\\t\\t\\tthis.backBuffer.destroy();\\n\\t\\t\\t\\t\\t\\tthis.backBuffer = null;\\n\\t\\t\\t\\t\\t\\tthis.createBackbuffer();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst rt = this.backBuffer;\\n\\t\\t\\t\\tconst wrt = rt.impl;\\n\\t\\t\\t\\twrt.setColorAttachment(0, undefined, this.backBufferViewFormat);\\n\\t\\t\\t\\tthis.initRenderTarget(rt);\\n\\t\\t\\t\\twrt.assignColorTexture(this, outColorBuffer);\\n\\t\\t}\\n\\t\\tframeEnd() {\\n\\t\\t\\t\\tsuper.frameEnd();\\n\\t\\t\\t\\tthis.gpuProfiler.frameEnd();\\n\\t\\t\\t\\tthis.submit();\\n\\t\\t\\t\\tif (!this.contextLost) {\\n\\t\\t\\t\\t\\t\\tthis.gpuProfiler.request();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._indirectDrawNextIndex = 0;\\n\\t\\t\\t\\tthis._indirectDispatchNextIndex = 0;\\n\\t\\t}\\n\\t\\tcreateBufferImpl(usageFlags) {\\n\\t\\t\\t\\treturn new WebgpuBuffer(usageFlags);\\n\\t\\t}\\n\\t\\tcreateUniformBufferImpl(uniformBuffer) {\\n\\t\\t\\t\\treturn new WebgpuUniformBuffer(uniformBuffer);\\n\\t\\t}\\n\\t\\tcreateVertexBufferImpl(vertexBuffer, format, options) {\\n\\t\\t\\t\\treturn new WebgpuVertexBuffer(vertexBuffer, format, options);\\n\\t\\t}\\n\\t\\tcreateIndexBufferImpl(indexBuffer, options) {\\n\\t\\t\\t\\treturn new WebgpuIndexBuffer(indexBuffer, options);\\n\\t\\t}\\n\\t\\tcreateShaderImpl(shader) {\\n\\t\\t\\t\\treturn new WebgpuShader(shader);\\n\\t\\t}\\n\\t\\tcreateDrawCommandImpl(drawCommands) {\\n\\t\\t\\t\\treturn new WebgpuDrawCommands(this);\\n\\t\\t}\\n\\t\\tcreateTextureImpl(texture) {\\n\\t\\t\\t\\tthis.textures.add(texture);\\n\\t\\t\\t\\treturn new WebgpuTexture(texture);\\n\\t\\t}\\n\\t\\tcreateRenderTargetImpl(renderTarget) {\\n\\t\\t\\t\\treturn new WebgpuRenderTarget(renderTarget);\\n\\t\\t}\\n\\t\\tcreateUploadStreamImpl(uploadStream) {\\n\\t\\t\\t\\treturn new WebgpuUploadStream(uploadStream);\\n\\t\\t}\\n\\t\\tcreateBindGroupFormatImpl(bindGroupFormat) {\\n\\t\\t\\t\\treturn new WebgpuBindGroupFormat(bindGroupFormat);\\n\\t\\t}\\n\\t\\tcreateBindGroupImpl(bindGroup) {\\n\\t\\t\\t\\treturn new WebgpuBindGroup();\\n\\t\\t}\\n\\t\\tcreateComputeImpl(compute) {\\n\\t\\t\\t\\treturn new WebgpuCompute(compute);\\n\\t\\t}\\n\\t\\tget indirectDrawBuffer() {\\n\\t\\t\\t\\tthis.allocateIndirectDrawBuffer();\\n\\t\\t\\t\\treturn this._indirectDrawBuffer;\\n\\t\\t}\\n\\t\\tallocateIndirectDrawBuffer() {\\n\\t\\t\\t\\tif (this._indirectDrawNextIndex === 0 && this._indirectDrawBufferCount < this.maxIndirectDrawCount) {\\n\\t\\t\\t\\t\\t\\tthis._indirectDrawBuffer?.destroy();\\n\\t\\t\\t\\t\\t\\tthis._indirectDrawBuffer = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._indirectDrawBuffer === null) {\\n\\t\\t\\t\\t\\t\\tthis._indirectDrawBuffer = new StorageBuffer(this, this.maxIndirectDrawCount * _indirectEntryByteSize, BUFFERUSAGE_INDIRECT | BUFFERUSAGE_COPY_DST);\\n\\t\\t\\t\\t\\t\\tthis._indirectDrawBufferCount = this.maxIndirectDrawCount;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetIndirectDrawSlot(count = 1) {\\n\\t\\t\\t\\tthis.allocateIndirectDrawBuffer();\\n\\t\\t\\t\\tconst slot = this._indirectDrawNextIndex;\\n\\t\\t\\t\\tconst nextIndex = this._indirectDrawNextIndex + count;\\n\\t\\t\\t\\tthis._indirectDrawNextIndex = nextIndex;\\n\\t\\t\\t\\treturn slot;\\n\\t\\t}\\n\\t\\tget indirectDispatchBuffer() {\\n\\t\\t\\t\\tthis.allocateIndirectDispatchBuffer();\\n\\t\\t\\t\\treturn this._indirectDispatchBuffer;\\n\\t\\t}\\n\\t\\tallocateIndirectDispatchBuffer() {\\n\\t\\t\\t\\tif (this._indirectDispatchNextIndex === 0 && this._indirectDispatchBufferCount < this.maxIndirectDispatchCount) {\\n\\t\\t\\t\\t\\t\\tthis._indirectDispatchBuffer?.destroy();\\n\\t\\t\\t\\t\\t\\tthis._indirectDispatchBuffer = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._indirectDispatchBuffer === null) {\\n\\t\\t\\t\\t\\t\\tthis._indirectDispatchBuffer = new StorageBuffer(this, this.maxIndirectDispatchCount * _indirectDispatchEntryByteSize, BUFFERUSAGE_INDIRECT | BUFFERUSAGE_COPY_DST);\\n\\t\\t\\t\\t\\t\\tthis._indirectDispatchBufferCount = this.maxIndirectDispatchCount;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetIndirectDispatchSlot(count = 1) {\\n\\t\\t\\t\\tthis.allocateIndirectDispatchBuffer();\\n\\t\\t\\t\\tconst slot = this._indirectDispatchNextIndex;\\n\\t\\t\\t\\tconst nextIndex = this._indirectDispatchNextIndex + count;\\n\\t\\t\\t\\tthis._indirectDispatchNextIndex = nextIndex;\\n\\t\\t\\t\\treturn slot;\\n\\t\\t}\\n\\t\\tsetBindGroup(index, bindGroup, offsets) {\\n\\t\\t\\t\\tif (this.passEncoder) {\\n\\t\\t\\t\\t\\t\\tthis.passEncoder.setBindGroup(index, bindGroup.impl.bindGroup, offsets ?? bindGroup.uniformBufferOffsets);\\n\\t\\t\\t\\t\\t\\tthis.bindGroupFormats[index] = bindGroup.format.impl;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsubmitVertexBuffer(vertexBuffer, slot) {\\n\\t\\t\\t\\tconst format = vertexBuffer.format;\\n\\t\\t\\t\\tconst { interleaved, elements } = format;\\n\\t\\t\\t\\tconst elementCount = elements.length;\\n\\t\\t\\t\\tconst vbBuffer = vertexBuffer.impl.buffer;\\n\\t\\t\\t\\tif (interleaved) {\\n\\t\\t\\t\\t\\t\\tthis.passEncoder.setVertexBuffer(slot, vbBuffer);\\n\\t\\t\\t\\t\\t\\treturn 1;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < elementCount; i++){\\n\\t\\t\\t\\t\\t\\tthis.passEncoder.setVertexBuffer(slot + i, vbBuffer, elements[i].offset);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn elementCount;\\n\\t\\t}\\n\\t\\tvalidateVBLocations(vb0, vb1) {\\n\\t\\t\\t\\tconst validateVB = (vb)=>{\\n\\t\\t\\t\\t\\t\\tconst { elements } = vb.format;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < elements.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst name = elements[i].name;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst location = semanticToLocation[name];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (_uniqueLocations.has(location)) ;\\n\\t\\t\\t\\t\\t\\t\\t\\t_uniqueLocations.set(location, name);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tvalidateVB(vb0);\\n\\t\\t\\t\\tvalidateVB(vb1);\\n\\t\\t\\t\\t_uniqueLocations.clear();\\n\\t\\t}\\n\\t\\tdraw(primitive, indexBuffer, numInstances = 1, drawCommands, first = true, last = true) {\\n\\t\\t\\t\\tif (this.shader.ready && !this.shader.failed) {\\n\\t\\t\\t\\t\\t\\tconst passEncoder = this.passEncoder;\\n\\t\\t\\t\\t\\t\\tlet pipeline = this.pipeline;\\n\\t\\t\\t\\t\\t\\tconst vb0 = this.vertexBuffers[0];\\n\\t\\t\\t\\t\\t\\tconst vb1 = this.vertexBuffers[1];\\n\\t\\t\\t\\t\\t\\tif (first) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (vb0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst vbSlot = this.submitVertexBuffer(vb0, 0);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (vb1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.submitVertexBuffer(vb1, vbSlot);\\n\\t\\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\\tpipeline = this.renderPipeline.get(primitive, vb0?.format, vb1?.format, indexBuffer?.format, this.shader, this.renderTarget, this.bindGroupFormats, this.blendState, this.depthState, this.cullMode, this.stencilEnabled, this.stencilFront, this.stencilBack);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.pipeline !== pipeline) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.pipeline = pipeline;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpassEncoder.setPipeline(pipeline);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (indexBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tpassEncoder.setIndexBuffer(indexBuffer.impl.buffer, indexBuffer.impl.format);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (drawCommands) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst storage = drawCommands.impl?.storage ?? this.indirectDrawBuffer;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst indirectBuffer = storage.impl.buffer;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst drawsCount = drawCommands.count;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let d = 0; d < drawsCount; d++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst indirectOffset = (drawCommands.slotIndex + d) * _indirectEntryByteSize;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (indexBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpassEncoder.drawIndexedIndirect(indirectBuffer, indirectOffset);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpassEncoder.drawIndirect(indirectBuffer, indirectOffset);\\n\\t\\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} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (indexBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpassEncoder.drawIndexed(primitive.count, numInstances, primitive.base, primitive.baseVertex ?? 0, 0);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpassEncoder.draw(primitive.count, numInstances, primitive.base, 0);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._drawCallsPerFrame++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (last) {\\n\\t\\t\\t\\t\\t\\tthis.clearVertexBuffer();\\n\\t\\t\\t\\t\\t\\tthis.pipeline = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetShader(shader, asyncCompile = false) {\\n\\t\\t\\t\\tif (shader !== this.shader) {\\n\\t\\t\\t\\t\\t\\tthis.shader = shader;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetBlendState(blendState) {\\n\\t\\t\\t\\tthis.blendState.copy(blendState);\\n\\t\\t}\\n\\t\\tsetDepthState(depthState) {\\n\\t\\t\\t\\tthis.depthState.copy(depthState);\\n\\t\\t}\\n\\t\\tsetStencilState(stencilFront, stencilBack) {\\n\\t\\t\\t\\tif (stencilFront || stencilBack) {\\n\\t\\t\\t\\t\\t\\tthis.stencilEnabled = true;\\n\\t\\t\\t\\t\\t\\tthis.stencilFront.copy(stencilFront ?? StencilParameters.DEFAULT);\\n\\t\\t\\t\\t\\t\\tthis.stencilBack.copy(stencilBack ?? StencilParameters.DEFAULT);\\n\\t\\t\\t\\t\\t\\tconst ref = this.stencilFront.ref;\\n\\t\\t\\t\\t\\t\\tif (this.stencilRef !== ref) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.stencilRef = ref;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.passEncoder.setStencilReference(ref);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.stencilEnabled = false;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetBlendColor(r, g, b, a) {\\n\\t\\t\\t\\tconst c = this.blendColor;\\n\\t\\t\\t\\tif (r !== c.r || g !== c.g || b !== c.b || a !== c.a) {\\n\\t\\t\\t\\t\\t\\tc.set(r, g, b, a);\\n\\t\\t\\t\\t\\t\\tthis.passEncoder.setBlendConstant(c);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetCullMode(cullMode) {\\n\\t\\t\\t\\tthis.cullMode = cullMode;\\n\\t\\t}\\n\\t\\tsetAlphaToCoverage(state) {}\\n\\t\\tinitializeContextCaches() {\\n\\t\\t\\t\\tsuper.initializeContextCaches();\\n\\t\\t}\\n\\t\\tsetupPassEncoderDefaults() {\\n\\t\\t\\t\\tthis.pipeline = null;\\n\\t\\t\\t\\tthis.stencilRef = 0;\\n\\t\\t\\t\\tthis.blendColor.set(0, 0, 0, 0);\\n\\t\\t}\\n\\t\\t_uploadDirtyTextures() {\\n\\t\\t\\t\\tthis.texturesToUpload.forEach((texture)=>{\\n\\t\\t\\t\\t\\t\\tif (texture._needsUpload || texture._needsMipmapsUpload) {\\n\\t\\t\\t\\t\\t\\t\\t\\ttexture.upload();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.texturesToUpload.clear();\\n\\t\\t}\\n\\t\\tsetupTimeStampWrites(passDesc, name) {\\n\\t\\t\\t\\tif (this.gpuProfiler._enabled) {\\n\\t\\t\\t\\t\\t\\tif (this.gpuProfiler.timestampQueriesSet) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst slot = this.gpuProfiler.getSlot(name);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (slot === -1) ; else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpassDesc = passDesc ?? {};\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpassDesc.timestampWrites = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tquerySet: this.gpuProfiler.timestampQueriesSet.querySet,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbeginningOfPassWriteIndex: slot * 2,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tendOfPassWriteIndex: slot * 2 + 1\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn passDesc;\\n\\t\\t}\\n\\t\\tstartRenderPass(renderPass) {\\n\\t\\t\\t\\tthis._uploadDirtyTextures();\\n\\t\\t\\t\\tconst rt = renderPass.renderTarget || this.backBuffer;\\n\\t\\t\\t\\tthis.renderTarget = rt;\\n\\t\\t\\t\\tconst wrt = rt.impl;\\n\\t\\t\\t\\tif (rt !== this.backBuffer) {\\n\\t\\t\\t\\t\\t\\tthis.initRenderTarget(rt);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\twrt.setupForRenderPass(renderPass, rt);\\n\\t\\t\\t\\tconst renderPassDesc = wrt.renderPassDescriptor;\\n\\t\\t\\t\\tthis.setupTimeStampWrites(renderPassDesc, renderPass.name);\\n\\t\\t\\t\\tconst commandEncoder = this.getCommandEncoder();\\n\\t\\t\\t\\tthis.passEncoder = commandEncoder.beginRenderPass(renderPassDesc);\\n\\t\\t\\t\\tthis.passEncoder.label = `${renderPass.name}-PassEncoder RT:${rt.name}`;\\n\\t\\t\\t\\tthis.setupPassEncoderDefaults();\\n\\t\\t\\t\\tconst { width, height } = rt;\\n\\t\\t\\t\\tthis.setViewport(0, 0, width, height);\\n\\t\\t\\t\\tthis.setScissor(0, 0, width, height);\\n\\t\\t\\t\\tthis.insideRenderPass = true;\\n\\t\\t}\\n\\t\\tendRenderPass(renderPass) {\\n\\t\\t\\t\\tthis.passEncoder.end();\\n\\t\\t\\t\\tthis.passEncoder = null;\\n\\t\\t\\t\\tthis.insideRenderPass = false;\\n\\t\\t\\t\\tthis.bindGroupFormats.length = 0;\\n\\t\\t\\t\\tconst target = this.renderTarget;\\n\\t\\t\\t\\tif (target) {\\n\\t\\t\\t\\t\\t\\tif (target.depthBuffer && renderPass.depthStencilOps.resolveDepth) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (renderPass.samples > 1 && target.autoResolve) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst depthAttachment = target.impl.depthAttachment;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst destTexture = target.depthBuffer.impl.gpuTexture;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (depthAttachment && destTexture) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.resolver.resolveDepth(this.commandEncoder, depthAttachment.multisampledDepthBuffer, destTexture);\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < renderPass.colorArrayOps.length; i++){\\n\\t\\t\\t\\t\\t\\tconst colorOps = renderPass.colorArrayOps[i];\\n\\t\\t\\t\\t\\t\\tif (colorOps.genMipmaps) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.mipmapRenderer.generate(renderPass.renderTarget._colorBuffers[i].impl);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tstartComputePass(name) {\\n\\t\\t\\t\\tthis._uploadDirtyTextures();\\n\\t\\t\\t\\tthis.pipeline = null;\\n\\t\\t\\t\\tconst computePassDesc = this.setupTimeStampWrites(undefined, name);\\n\\t\\t\\t\\tconst commandEncoder = this.getCommandEncoder();\\n\\t\\t\\t\\tthis.passEncoder = commandEncoder.beginComputePass(computePassDesc);\\n\\t\\t\\t\\tthis.insideRenderPass = true;\\n\\t\\t}\\n\\t\\tendComputePass() {\\n\\t\\t\\t\\tthis.passEncoder.end();\\n\\t\\t\\t\\tthis.passEncoder = null;\\n\\t\\t\\t\\tthis.insideRenderPass = false;\\n\\t\\t\\t\\tthis.bindGroupFormats.length = 0;\\n\\t\\t}\\n\\t\\tcomputeDispatch(computes, name = 'Unnamed') {\\n\\t\\t\\t\\tthis.startComputePass(name);\\n\\t\\t\\t\\tfor(let i = 0; i < computes.length; i++){\\n\\t\\t\\t\\t\\t\\tconst compute = computes[i];\\n\\t\\t\\t\\t\\t\\tcompute.applyParameters();\\n\\t\\t\\t\\t\\t\\tcompute.impl.updateBindGroup();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < computes.length; i++){\\n\\t\\t\\t\\t\\t\\tconst compute = computes[i];\\n\\t\\t\\t\\t\\t\\tcompute.impl.dispatch(compute.countX, compute.countY, compute.countZ);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.endComputePass();\\n\\t\\t}\\n\\t\\tgetCommandEncoder() {\\n\\t\\t\\t\\tlet commandEncoder = this.commandEncoder;\\n\\t\\t\\t\\tif (!commandEncoder) {\\n\\t\\t\\t\\t\\t\\tcommandEncoder = this.wgpu.createCommandEncoder();\\n\\t\\t\\t\\t\\t\\tthis.commandEncoder = commandEncoder;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn commandEncoder;\\n\\t\\t}\\n\\t\\tendCommandEncoder() {\\n\\t\\t\\t\\tconst { commandEncoder } = this;\\n\\t\\t\\t\\tif (commandEncoder) {\\n\\t\\t\\t\\t\\t\\tconst cb = commandEncoder.finish();\\n\\t\\t\\t\\t\\t\\tthis.addCommandBuffer(cb);\\n\\t\\t\\t\\t\\t\\tthis.commandEncoder = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\taddCommandBuffer(commandBuffer, front = false) {\\n\\t\\t\\t\\tif (front) {\\n\\t\\t\\t\\t\\t\\tthis.commandBuffers.unshift(commandBuffer);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.commandBuffers.push(commandBuffer);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsubmit() {\\n\\t\\t\\t\\tthis.endCommandEncoder();\\n\\t\\t\\t\\tif (this.commandBuffers.length > 0) {\\n\\t\\t\\t\\t\\t\\tthis.dynamicBuffers.submit();\\n\\t\\t\\t\\t\\t\\tthis.wgpu.queue.submit(this.commandBuffers);\\n\\t\\t\\t\\t\\t\\tthis.commandBuffers.length = 0;\\n\\t\\t\\t\\t\\t\\tthis.dynamicBuffers.onCommandBuffersSubmitted();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst deferredDestroys = this._deferredDestroys;\\n\\t\\t\\t\\tif (deferredDestroys.length > 0) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < deferredDestroys.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tdeferredDestroys[i].destroy();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tdeferredDestroys.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdeferDestroy(gpuResource) {\\n\\t\\t\\t\\tif (gpuResource) {\\n\\t\\t\\t\\t\\t\\tthis._deferredDestroys.push(gpuResource);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tclear(options) {\\n\\t\\t\\t\\tif (options.flags) {\\n\\t\\t\\t\\t\\t\\tthis.clearRenderer.clear(this, this.renderTarget, options, this.defaultClearOptions);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetViewport(x, y, w, h) {\\n\\t\\t\\t\\tif (this.passEncoder) {\\n\\t\\t\\t\\t\\t\\tif (!this.renderTarget.flipY) {\\n\\t\\t\\t\\t\\t\\t\\t\\ty = this.renderTarget.height - y - h;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.vx = x;\\n\\t\\t\\t\\t\\t\\tthis.vy = y;\\n\\t\\t\\t\\t\\t\\tthis.vw = w;\\n\\t\\t\\t\\t\\t\\tthis.vh = h;\\n\\t\\t\\t\\t\\t\\tthis.passEncoder.setViewport(x, y, w, h, 0, 1);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetScissor(x, y, w, h) {\\n\\t\\t\\t\\tif (this.passEncoder) {\\n\\t\\t\\t\\t\\t\\tif (!this.renderTarget.flipY) {\\n\\t\\t\\t\\t\\t\\t\\t\\ty = this.renderTarget.height - y - h;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.sx = x;\\n\\t\\t\\t\\t\\t\\tthis.sy = y;\\n\\t\\t\\t\\t\\t\\tthis.sw = w;\\n\\t\\t\\t\\t\\t\\tthis.sh = h;\\n\\t\\t\\t\\t\\t\\tthis.passEncoder.setScissorRect(x, y, w, h);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tclearStorageBuffer(storageBuffer, offset = 0, size = storageBuffer.byteSize) {\\n\\t\\t\\t\\tconst commandEncoder = this.getCommandEncoder();\\n\\t\\t\\t\\tcommandEncoder.clearBuffer(storageBuffer.buffer, offset, size);\\n\\t\\t}\\n\\t\\treadStorageBuffer(storageBuffer, offset = 0, size = storageBuffer.byteSize - offset, data = null, immediate = false) {\\n\\t\\t\\t\\tconst stagingBuffer = this.createBufferImpl(BUFFERUSAGE_READ | BUFFERUSAGE_COPY_DST);\\n\\t\\t\\t\\tstagingBuffer.allocate(this, size);\\n\\t\\t\\t\\tconst destBuffer = stagingBuffer.buffer;\\n\\t\\t\\t\\tconst commandEncoder = this.getCommandEncoder();\\n\\t\\t\\t\\tcommandEncoder.copyBufferToBuffer(storageBuffer.buffer, offset, destBuffer, 0, size);\\n\\t\\t\\t\\treturn this.readBuffer(stagingBuffer, size, data, immediate);\\n\\t\\t}\\n\\t\\treadBuffer(stagingBuffer, size, data = null, immediate = false) {\\n\\t\\t\\t\\tconst destBuffer = stagingBuffer.buffer;\\n\\t\\t\\t\\treturn new Promise((resolve, reject)=>{\\n\\t\\t\\t\\t\\t\\tconst read = ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tdestBuffer?.mapAsync(GPUMapMode.READ).then(()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata ?? (data = new Uint8Array(size));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst copySrc = destBuffer.getMappedRange(0, size);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst srcType = data.constructor;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata.set(new srcType(copySrc));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdestBuffer.unmap();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstagingBuffer.destroy(this);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresolve(data);\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tif (immediate) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.submit();\\n\\t\\t\\t\\t\\t\\t\\t\\tread();\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tsetTimeout(()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tread();\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\twriteStorageBuffer(storageBuffer, bufferOffset = 0, data, dataOffset = 0, size) {\\n\\t\\t\\t\\tthis.wgpu.queue.writeBuffer(storageBuffer.buffer, bufferOffset, data, dataOffset, size);\\n\\t\\t}\\n\\t\\tcopyRenderTarget(source, dest, color, depth) {\\n\\t\\t\\t\\tconst copySize = {\\n\\t\\t\\t\\t\\t\\twidth: source ? source.width : dest.width,\\n\\t\\t\\t\\t\\t\\theight: source ? source.height : dest.height,\\n\\t\\t\\t\\t\\t\\tdepthOrArrayLayers: 1\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst commandEncoder = this.getCommandEncoder();\\n\\t\\t\\t\\tif (color) {\\n\\t\\t\\t\\t\\t\\tconst copySrc = {\\n\\t\\t\\t\\t\\t\\t\\t\\ttexture: source ? source.colorBuffer.impl.gpuTexture : this.backBuffer.impl.assignedColorTexture,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipLevel: source ? source.mipLevel : 0\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tconst copyDst = {\\n\\t\\t\\t\\t\\t\\t\\t\\ttexture: dest ? dest.colorBuffer.impl.gpuTexture : this.backBuffer.impl.assignedColorTexture,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipLevel: dest ? dest.mipLevel : 0\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tcommandEncoder.copyTextureToTexture(copySrc, copyDst, copySize);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (depth) {\\n\\t\\t\\t\\t\\t\\tconst sourceRT = source ? source : this.renderTarget;\\n\\t\\t\\t\\t\\t\\tconst sourceTexture = sourceRT.impl.depthAttachment.depthTexture;\\n\\t\\t\\t\\t\\t\\tconst sourceMipLevel = sourceRT.mipLevel;\\n\\t\\t\\t\\t\\t\\tif (source.samples > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst destTexture = dest.colorBuffer.impl.gpuTexture;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.resolver.resolveDepth(commandEncoder, sourceTexture, destTexture);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst destTexture = dest ? dest.depthBuffer.impl.gpuTexture : this.renderTarget.impl.depthAttachment.depthTexture;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst destMipLevel = dest ? dest.mipLevel : this.renderTarget.mipLevel;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst copySrc = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture: sourceTexture,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmipLevel: sourceMipLevel\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\tconst copyDst = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture: destTexture,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmipLevel: destMipLevel\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\tcommandEncoder.copyTextureToTexture(copySrc, copyDst, copySize);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tget hasTranspilers() {\\n\\t\\t\\t\\treturn this.glslang && this.twgsl;\\n\\t\\t}\\n\\t\\tconstructor(canvas, options = {}){\\n\\t\\t\\t\\tsuper(canvas, options), this._deferredDestroys = [], this.renderPipeline = new WebgpuRenderPipeline(this), this.computePipeline = new WebgpuComputePipeline(this), this._indirectDrawBuffer = null, this._indirectDrawBufferCount = 0, this._indirectDrawNextIndex = 0, this._indirectDispatchBuffer = null, this._indirectDispatchBufferCount = 0, this._indirectDispatchNextIndex = 0, this.pipeline = null, this.bindGroupFormats = [], this.commandEncoder = null, this.commandBuffers = [], this.glslang = null, this.twgsl = null;\\n\\t\\t\\t\\toptions = this.initOptions;\\n\\t\\t\\t\\toptions.alpha = options.alpha ?? true;\\n\\t\\t\\t\\tthis.backBufferAntialias = options.antialias ?? false;\\n\\t\\t\\t\\tthis.isWebGPU = true;\\n\\t\\t\\t\\tthis._deviceType = DEVICETYPE_WEBGPU;\\n\\t\\t\\t\\tthis.scope.resolve(UNUSED_UNIFORM_NAME).setValue(0);\\n\\t\\t}\\n}\\n\\nclass WebglBuffer {\\n\\t\\tdestroy(device) {\\n\\t\\t\\t\\tif (this.bufferId) {\\n\\t\\t\\t\\t\\t\\tdevice.gl.deleteBuffer(this.bufferId);\\n\\t\\t\\t\\t\\t\\tthis.bufferId = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget initialized() {\\n\\t\\t\\t\\treturn !!this.bufferId;\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tthis.bufferId = null;\\n\\t\\t}\\n\\t\\tunlock(device, usage, target, storage) {\\n\\t\\t\\t\\tconst gl = device.gl;\\n\\t\\t\\t\\tif (!this.bufferId) {\\n\\t\\t\\t\\t\\t\\tlet glUsage;\\n\\t\\t\\t\\t\\t\\tswitch(usage){\\n\\t\\t\\t\\t\\t\\t\\t\\tcase BUFFER_STATIC:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tglUsage = gl.STATIC_DRAW;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase BUFFER_DYNAMIC:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tglUsage = gl.DYNAMIC_DRAW;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase BUFFER_STREAM:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tglUsage = gl.STREAM_DRAW;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase BUFFER_GPUDYNAMIC:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tglUsage = gl.DYNAMIC_COPY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.bufferId = gl.createBuffer();\\n\\t\\t\\t\\t\\t\\tgl.bindBuffer(target, this.bufferId);\\n\\t\\t\\t\\t\\t\\tgl.bufferData(target, storage, glUsage);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tgl.bindBuffer(target, this.bufferId);\\n\\t\\t\\t\\t\\t\\tgl.bufferSubData(target, 0, storage);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.bufferId = null;\\n\\t\\t}\\n}\\n\\nclass WebglVertexBuffer extends WebglBuffer {\\n\\t\\tdestroy(device) {\\n\\t\\t\\t\\tsuper.destroy(device);\\n\\t\\t\\t\\tdevice.unbindVertexArray();\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tsuper.loseContext();\\n\\t\\t\\t\\tthis.vao = null;\\n\\t\\t}\\n\\t\\tunlock(vertexBuffer) {\\n\\t\\t\\t\\tconst device = vertexBuffer.device;\\n\\t\\t\\t\\tsuper.unlock(device, vertexBuffer.usage, device.gl.ARRAY_BUFFER, vertexBuffer.storage);\\n\\t\\t}\\n\\t\\tconstructor(...args){\\n\\t\\t\\t\\tsuper(...args), this.vao = null;\\n\\t\\t}\\n}\\n\\nclass WebglIndexBuffer extends WebglBuffer {\\n\\t\\tunlock(indexBuffer) {\\n\\t\\t\\t\\tconst device = indexBuffer.device;\\n\\t\\t\\t\\tsuper.unlock(device, indexBuffer.usage, device.gl.ELEMENT_ARRAY_BUFFER, indexBuffer.storage);\\n\\t\\t}\\n\\t\\tconstructor(indexBuffer){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tconst gl = indexBuffer.device.gl;\\n\\t\\t\\t\\tconst format = indexBuffer.format;\\n\\t\\t\\t\\tif (format === INDEXFORMAT_UINT8) {\\n\\t\\t\\t\\t\\t\\tthis.glFormat = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\t} else if (format === INDEXFORMAT_UINT16) {\\n\\t\\t\\t\\t\\t\\tthis.glFormat = gl.UNSIGNED_SHORT;\\n\\t\\t\\t\\t} else if (format === INDEXFORMAT_UINT32) {\\n\\t\\t\\t\\t\\t\\tthis.glFormat = gl.UNSIGNED_INT;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass WebglShaderInput {\\n\\t\\tconstructor(graphicsDevice, name, type, locationId){\\n\\t\\t\\t\\tthis.locationId = locationId;\\n\\t\\t\\t\\tthis.scopeId = graphicsDevice.scope.resolve(name);\\n\\t\\t\\t\\tthis.version = new Version();\\n\\t\\t\\t\\tif (name.substring(name.length - 3) === '[0]') {\\n\\t\\t\\t\\t\\t\\tswitch(type){\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_FLOAT:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = UNIFORMTYPE_FLOATARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_INT:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = UNIFORMTYPE_INTARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_UINT:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = UNIFORMTYPE_UINTARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_BOOL:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = UNIFORMTYPE_BOOLARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_VEC2:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = UNIFORMTYPE_VEC2ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_IVEC2:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = UNIFORMTYPE_IVEC2ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_UVEC2:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = UNIFORMTYPE_UVEC2ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_BVEC2:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = UNIFORMTYPE_BVEC2ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_VEC3:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = UNIFORMTYPE_VEC3ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_IVEC3:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = UNIFORMTYPE_IVEC3ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_UVEC3:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = UNIFORMTYPE_UVEC3ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_BVEC3:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = UNIFORMTYPE_BVEC3ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_VEC4:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = UNIFORMTYPE_VEC4ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_IVEC4:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = UNIFORMTYPE_IVEC4ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_UVEC4:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = UNIFORMTYPE_UVEC4ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase UNIFORMTYPE_BVEC4:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype = UNIFORMTYPE_BVEC4ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.dataType = type;\\n\\t\\t\\t\\tthis.value = [\\n\\t\\t\\t\\t\\t\\tnull,\\n\\t\\t\\t\\t\\t\\tnull,\\n\\t\\t\\t\\t\\t\\tnull,\\n\\t\\t\\t\\t\\t\\tnull\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.array = [];\\n\\t\\t}\\n}\\n\\nconst _vertexShaderBuiltins = new Set([\\n\\t\\t'gl_VertexID',\\n\\t\\t'gl_InstanceID',\\n\\t\\t'gl_DrawID',\\n\\t\\t'gl_BaseVertex',\\n\\t\\t'gl_BaseInstance'\\n]);\\nclass CompiledShaderCache {\\n\\t\\tdestroy(device) {\\n\\t\\t\\t\\tthis.map.forEach((shader)=>{\\n\\t\\t\\t\\t\\t\\tdevice.gl.deleteShader(shader);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tloseContext(device) {\\n\\t\\t\\t\\tthis.map.clear();\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.map = new Map();\\n\\t\\t}\\n}\\nconst _vertexShaderCache = new DeviceCache();\\nconst _fragmentShaderCache = new DeviceCache();\\nclass WebglShader {\\n\\t\\tdestroy(shader) {\\n\\t\\t\\t\\tif (this.glProgram) {\\n\\t\\t\\t\\t\\t\\tshader.device.gl.deleteProgram(this.glProgram);\\n\\t\\t\\t\\t\\t\\tthis.glProgram = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tinit() {\\n\\t\\t\\t\\tthis.uniforms = [];\\n\\t\\t\\t\\tthis.samplers = [];\\n\\t\\t\\t\\tthis.attributes = [];\\n\\t\\t\\t\\tthis.glProgram = null;\\n\\t\\t\\t\\tthis.glVertexShader = null;\\n\\t\\t\\t\\tthis.glFragmentShader = null;\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tthis.init();\\n\\t\\t}\\n\\t\\trestoreContext(device, shader) {\\n\\t\\t\\t\\tthis.compile(device, shader);\\n\\t\\t\\t\\tthis.link(device, shader);\\n\\t\\t}\\n\\t\\tcompile(device, shader) {\\n\\t\\t\\t\\tconst definition = shader.definition;\\n\\t\\t\\t\\tthis.glVertexShader = this._compileShaderSource(device, definition.vshader, true);\\n\\t\\t\\t\\tthis.glFragmentShader = this._compileShaderSource(device, definition.fshader, false);\\n\\t\\t}\\n\\t\\tlink(device, shader) {\\n\\t\\t\\t\\tif (this.glProgram) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst gl = device.gl;\\n\\t\\t\\t\\tif (gl.isContextLost()) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst glProgram = gl.createProgram();\\n\\t\\t\\t\\tthis.glProgram = glProgram;\\n\\t\\t\\t\\tgl.attachShader(glProgram, this.glVertexShader);\\n\\t\\t\\t\\tgl.attachShader(glProgram, this.glFragmentShader);\\n\\t\\t\\t\\tconst definition = shader.definition;\\n\\t\\t\\t\\tconst attrs = definition.attributes;\\n\\t\\t\\t\\tif (definition.useTransformFeedback) {\\n\\t\\t\\t\\t\\t\\tlet outNames = definition.feedbackVaryings;\\n\\t\\t\\t\\t\\t\\tif (!outNames) {\\n\\t\\t\\t\\t\\t\\t\\t\\toutNames = [];\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(const attr in attrs){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (attrs.hasOwnProperty(attr)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toutNames.push(`out_${attr}`);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tgl.transformFeedbackVaryings(glProgram, outNames, gl.INTERLEAVED_ATTRIBS);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(const attr in attrs){\\n\\t\\t\\t\\t\\t\\tif (attrs.hasOwnProperty(attr)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst semantic = attrs[attr];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst loc = semanticToLocation[semantic];\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.bindAttribLocation(glProgram, loc, attr);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tgl.linkProgram(glProgram);\\n\\t\\t}\\n\\t\\t_compileShaderSource(device, src, isVertexShader) {\\n\\t\\t\\t\\tconst gl = device.gl;\\n\\t\\t\\t\\tif (gl.isContextLost()) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst shaderDeviceCache = isVertexShader ? _vertexShaderCache : _fragmentShaderCache;\\n\\t\\t\\t\\tconst shaderCache = shaderDeviceCache.get(device, ()=>{\\n\\t\\t\\t\\t\\t\\treturn new CompiledShaderCache();\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tlet glShader = shaderCache.map.get(src);\\n\\t\\t\\t\\tif (!glShader) {\\n\\t\\t\\t\\t\\t\\tglShader = gl.createShader(isVertexShader ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER);\\n\\t\\t\\t\\t\\t\\tgl.shaderSource(glShader, src);\\n\\t\\t\\t\\t\\t\\tgl.compileShader(glShader);\\n\\t\\t\\t\\t\\t\\tshaderCache.map.set(src, glShader);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn glShader;\\n\\t\\t}\\n\\t\\tfinalize(device, shader) {\\n\\t\\t\\t\\tconst gl = device.gl;\\n\\t\\t\\t\\tif (gl.isContextLost()) {\\n\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst glProgram = this.glProgram;\\n\\t\\t\\t\\tconst definition = shader.definition;\\n\\t\\t\\t\\tconst linkStatus = gl.getProgramParameter(glProgram, gl.LINK_STATUS);\\n\\t\\t\\t\\tif (!linkStatus) {\\n\\t\\t\\t\\t\\t\\tif (!this._isCompiled(device, shader, this.glVertexShader, definition.vshader, 'vertex')) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!this._isCompiled(device, shader, this.glFragmentShader, definition.fshader, 'fragment')) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst message = `Failed to link shader program. Error: ${gl.getProgramInfoLog(glProgram)}`;\\n\\t\\t\\t\\t\\t\\tconsole.error(message);\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst numAttributes = gl.getProgramParameter(glProgram, gl.ACTIVE_ATTRIBUTES);\\n\\t\\t\\t\\tshader.attributes.clear();\\n\\t\\t\\t\\tfor(let i = 0; i < numAttributes; i++){\\n\\t\\t\\t\\t\\t\\tconst info = gl.getActiveAttrib(glProgram, i);\\n\\t\\t\\t\\t\\t\\tconst location = gl.getAttribLocation(glProgram, info.name);\\n\\t\\t\\t\\t\\t\\tif (_vertexShaderBuiltins.has(info.name)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (definition.attributes[info.name] === undefined) {\\n\\t\\t\\t\\t\\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\\t\\t\\t\\t\\tshader.failed = true;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tshader.attributes.set(location, info.name);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst samplerTypes = device._samplerTypes;\\n\\t\\t\\t\\tconst numUniforms = gl.getProgramParameter(glProgram, gl.ACTIVE_UNIFORMS);\\n\\t\\t\\t\\tfor(let i = 0; i < numUniforms; i++){\\n\\t\\t\\t\\t\\t\\tconst info = gl.getActiveUniform(glProgram, i);\\n\\t\\t\\t\\t\\t\\tconst location = gl.getUniformLocation(glProgram, info.name);\\n\\t\\t\\t\\t\\t\\tif (_vertexShaderBuiltins.has(info.name)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst shaderInput = new WebglShaderInput(device, info.name, device.pcUniformType[info.type], location);\\n\\t\\t\\t\\t\\t\\tif (samplerTypes.has(info.type)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.samplers.push(shaderInput);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.uniforms.push(shaderInput);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tshader.ready = true;\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\t_isCompiled(device, shader, glShader, source, shaderType) {\\n\\t\\t\\t\\tconst gl = device.gl;\\n\\t\\t\\t\\tif (!gl.getShaderParameter(glShader, gl.COMPILE_STATUS)) {\\n\\t\\t\\t\\t\\t\\tconst infoLog = gl.getShaderInfoLog(glShader);\\n\\t\\t\\t\\t\\t\\tconst [code, error] = this._processError(source, infoLog);\\n\\t\\t\\t\\t\\t\\tconst message = `Failed to compile ${shaderType} shader:\\\\n\\\\n${infoLog}\\\\n${code} while rendering ${ void 0}`;\\n\\t\\t\\t\\t\\t\\tconsole.error(message);\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tisLinked(device) {\\n\\t\\t\\t\\tconst { extParallelShaderCompile } = device;\\n\\t\\t\\t\\tif (extParallelShaderCompile) {\\n\\t\\t\\t\\t\\t\\treturn device.gl.getProgramParameter(this.glProgram, extParallelShaderCompile.COMPLETION_STATUS_KHR);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\t_processError(src, infoLog) {\\n\\t\\t\\t\\tconst error = {};\\n\\t\\t\\t\\tlet code = '';\\n\\t\\t\\t\\tif (src) {\\n\\t\\t\\t\\t\\t\\tconst lines = src.split('\\\\n');\\n\\t\\t\\t\\t\\t\\tlet from = 0;\\n\\t\\t\\t\\t\\t\\tlet to = lines.length;\\n\\t\\t\\t\\t\\t\\tif (infoLog && infoLog.startsWith('ERROR:')) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst match = infoLog.match(/^ERROR:\\\\s(\\\\d+):(\\\\d+):\\\\s*(.+)/);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (match) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\terror.message = match[3];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\terror.line = parseInt(match[2], 10);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfrom = Math.max(0, error.line - 6);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tto = Math.min(lines.length, error.line + 5);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor(let i = from; i < to; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst linePrefix = i + 1 === error.line ? '> ' : '  ';\\n\\t\\t\\t\\t\\t\\t\\t\\tcode += `${linePrefix}${i + 1}:\\\\t${lines[i]}\\\\n`;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\terror.source = src;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn [\\n\\t\\t\\t\\t\\t\\tcode,\\n\\t\\t\\t\\t\\t\\terror\\n\\t\\t\\t\\t];\\n\\t\\t}\\n\\t\\tconstructor(shader){\\n\\t\\t\\t\\tthis.compileDuration = 0;\\n\\t\\t\\t\\tthis.init();\\n\\t\\t\\t\\tthis.compile(shader.device, shader);\\n\\t\\t\\t\\tthis.link(shader.device, shader);\\n\\t\\t\\t\\tshader.device.shaders.push(shader);\\n\\t\\t}\\n}\\n\\nclass WebglDrawCommands {\\n\\t\\tallocate(maxCount) {\\n\\t\\t\\t\\tif (this.glCounts && this.glCounts.length === maxCount) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.glCounts = new Int32Array(maxCount);\\n\\t\\t\\t\\tthis.glOffsetsBytes = new Int32Array(maxCount);\\n\\t\\t\\t\\tthis.glInstanceCounts = new Int32Array(maxCount);\\n\\t\\t}\\n\\t\\tadd(i, indexOrVertexCount, instanceCount, firstIndexOrVertex) {\\n\\t\\t\\t\\tthis.glCounts[i] = indexOrVertexCount;\\n\\t\\t\\t\\tthis.glOffsetsBytes[i] = firstIndexOrVertex * this.indexSizeBytes;\\n\\t\\t\\t\\tthis.glInstanceCounts[i] = instanceCount;\\n\\t\\t}\\n\\t\\tupdate(count) {\\n\\t\\t\\t\\tlet totalPrimitives = 0;\\n\\t\\t\\t\\treturn totalPrimitives;\\n\\t\\t}\\n\\t\\tconstructor(indexSizeBytes){\\n\\t\\t\\t\\tthis.glCounts = null;\\n\\t\\t\\t\\tthis.glOffsetsBytes = null;\\n\\t\\t\\t\\tthis.glInstanceCounts = null;\\n\\t\\t\\t\\tthis.indexSizeBytes = indexSizeBytes;\\n\\t\\t}\\n}\\n\\nfunction downsampleImage(image, size) {\\n\\t\\tconst srcW = image.width;\\n\\t\\tconst srcH = image.height;\\n\\t\\tif (srcW > size || srcH > size) {\\n\\t\\t\\t\\tconst scale = size / Math.max(srcW, srcH);\\n\\t\\t\\t\\tconst dstW = Math.floor(srcW * scale);\\n\\t\\t\\t\\tconst dstH = Math.floor(srcH * scale);\\n\\t\\t\\t\\tconst canvas = document.createElement('canvas');\\n\\t\\t\\t\\tcanvas.width = dstW;\\n\\t\\t\\t\\tcanvas.height = dstH;\\n\\t\\t\\t\\tconst context = canvas.getContext('2d');\\n\\t\\t\\t\\tcontext.drawImage(image, 0, 0, srcW, srcH, 0, 0, dstW, dstH);\\n\\t\\t\\t\\treturn canvas;\\n\\t\\t}\\n\\t\\treturn image;\\n}\\nclass WebglTexture {\\n\\t\\tdestroy(device) {\\n\\t\\t\\t\\tif (this._glTexture) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < device.textureUnits.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst textureUnit = device.textureUnits[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < textureUnit.length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (textureUnit[j] === this._glTexture) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttextureUnit[j] = null;\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tdevice.gl.deleteTexture(this._glTexture);\\n\\t\\t\\t\\t\\t\\tthis._glTexture = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tthis._glTexture = null;\\n\\t\\t}\\n\\t\\tpropertyChanged(flag) {\\n\\t\\t\\t\\tthis.dirtyParameterFlags |= flag;\\n\\t\\t}\\n\\t\\tinitialize(device, texture) {\\n\\t\\t\\t\\tconst gl = device.gl;\\n\\t\\t\\t\\tthis._glTexture = gl.createTexture();\\n\\t\\t\\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\\t\\t\\tswitch(texture._format){\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_A8:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.ALPHA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.ALPHA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_L8:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.LUMINANCE;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.LUMINANCE;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_LA8:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.LUMINANCE_ALPHA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.LUMINANCE_ALPHA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_R8:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RED;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.R8;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RG8:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RG;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RG8;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGB565:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGB565;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_SHORT_5_6_5;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGBA5551:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGB5_A1;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_SHORT_5_5_5_1;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGBA4:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA4;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_SHORT_4_4_4_4;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGB8:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGB8;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGBA8:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA8;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_BGRA8:\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_SBGRA8:\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RG32F:\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGB9E5:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGB9_E5;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_INT_5_9_9_9_REV;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RG8S:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RG;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RG8_SNORM;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGBA8S:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA8_SNORM;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGB10A2:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGB10_A2;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_INT_2_10_10_10_REV;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGB10A2U:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGB10_A2UI;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_INT_2_10_10_10_REV;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_DXT1:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureS3TC.COMPRESSED_RGB_S3TC_DXT1_EXT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_DXT3:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT3_EXT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_DXT5:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT5_EXT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_ETC1:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureETC1.COMPRESSED_RGB_ETC1_WEBGL;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_PVRTC_2BPP_RGB_1:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTexturePVRTC.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_PVRTC_2BPP_RGBA_1:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTexturePVRTC.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_PVRTC_4BPP_RGB_1:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTexturePVRTC.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_PVRTC_4BPP_RGBA_1:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTexturePVRTC.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_ETC2_RGB:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureETC.COMPRESSED_RGB8_ETC2;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_ETC2_RGBA:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureETC.COMPRESSED_RGBA8_ETC2_EAC;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_ASTC_4x4:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureASTC.COMPRESSED_RGBA_ASTC_4x4_KHR;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_ATC_RGB:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureATC.COMPRESSED_RGB_ATC_WEBGL;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_ATC_RGBA:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureATC.COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_BC6F:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extTextureCompressionBPTC.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_BC6UF:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extTextureCompressionBPTC.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_BC7:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extTextureCompressionBPTC.COMPRESSED_RGBA_BPTC_UNORM_EXT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_DXT1_SRGB:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.SRGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureS3TC_SRGB.COMPRESSED_SRGB_S3TC_DXT1_EXT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_DXT3_SRGBA:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.SRGB_ALPHA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureS3TC_SRGB.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_DXT5_SRGBA:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.SRGB_ALPHA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureS3TC_SRGB.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_ETC2_SRGB:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.SRGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureETC.COMPRESSED_SRGB8_ETC2;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_ETC2_SRGBA:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.SRGB_ALPHA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureETC.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_ASTC_4x4_SRGB:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.SRGB_ALPHA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extCompressedTextureASTC.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_BC7_SRGBA:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = device.extTextureCompressionBPTC.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_R16F:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RED;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.R16F;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.HALF_FLOAT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RG16F:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RG;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RG16F;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.HALF_FLOAT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGB16F:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGB16F;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.HALF_FLOAT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGBA16F:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA16F;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.HALF_FLOAT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGB32F:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGB32F;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.FLOAT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGBA32F:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA32F;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.FLOAT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_R32F:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RED;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.R32F;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.FLOAT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_DEPTH:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.DEPTH_COMPONENT;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.DEPTH_COMPONENT32F;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.FLOAT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_DEPTH16:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.DEPTH_COMPONENT;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.DEPTH_COMPONENT16;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_SHORT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_DEPTHSTENCIL:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.DEPTH_STENCIL;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.DEPTH24_STENCIL8;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_INT_24_8;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_111110F:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.R11F_G11F_B10F;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_INT_10F_11F_11F_REV;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_SRGB8:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGB;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.SRGB8;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_SRGBA8:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.SRGB8_ALPHA8;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_R8I:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RED_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.R8I;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_R8U:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RED_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.R8UI;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_R16I:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RED_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.R16I;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.SHORT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_R16U:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RED_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.R16UI;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_SHORT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_R32I:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RED_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.R32I;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.INT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_R32U:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RED_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.R32UI;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_INT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RG8I:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RG_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RG8I;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RG8U:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RG_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RG8UI;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RG16I:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RG_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RG16I;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.SHORT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RG16U:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RG_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RG16UI;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_SHORT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RG32I:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RG_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RG32I;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.INT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RG32U:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RG_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RG32UI;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_INT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGBA8I:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA8I;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGBA8U:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA8UI;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGBA16I:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA16I;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.SHORT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGBA16U:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA16UI;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_SHORT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGBA32I:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA32I;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.INT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_RGBA32U:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glFormat = gl.RGBA_INTEGER;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glInternalFormat = gl.RGBA32UI;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glPixelType = gl.UNSIGNED_INT;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._glCreated = false;\\n\\t\\t}\\n\\t\\tupload(device, texture) {\\n\\t\\t\\t\\tconst gl = device.gl;\\n\\t\\t\\t\\tif (!texture._needsUpload && (texture._needsMipmapsUpload && texture._mipmapsUploaded || !texture.pot)) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet mipLevel = 0;\\n\\t\\t\\t\\tlet mipObject;\\n\\t\\t\\t\\tlet resMult;\\n\\t\\t\\t\\tconst requiredMipLevels = texture.numLevels;\\n\\t\\t\\t\\tif (texture.array && !this._glCreated) {\\n\\t\\t\\t\\t\\t\\tgl.texStorage3D(gl.TEXTURE_2D_ARRAY, requiredMipLevels, this._glInternalFormat, texture._width, texture._height, texture._arrayLength);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\twhile(texture._levels[mipLevel] || mipLevel === 0){\\n\\t\\t\\t\\t\\t\\tif (!texture._needsUpload && mipLevel === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmipLevel++;\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t} else if (mipLevel && (!texture._needsMipmapsUpload || !texture._mipmaps)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tmipObject = texture._levels[mipLevel];\\n\\t\\t\\t\\t\\t\\tresMult = 1 / Math.pow(2, mipLevel);\\n\\t\\t\\t\\t\\t\\tif (mipLevel === 1 && !texture._compressed && !texture._integerFormat && texture._levels.length < requiredMipLevels) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.generateMipmap(this._glTarget);\\n\\t\\t\\t\\t\\t\\t\\t\\ttexture._mipmapsUploaded = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (texture._cubemap) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlet face;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (device._isBrowserInterface(mipObject[0])) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(face = 0; face < 6; face++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!texture._levelsUpdated[0][face]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet src = mipObject[face];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (device._isImageBrowserInterface(src)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (src.width > device.maxCubeMapSize || src.height > device.maxCubeMapSize) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsrc = downsampleImage(src, device.maxCubeMapSize);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (mipLevel === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture._width = src.width;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture._height = src.height;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackFlipY(false);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackPremultiplyAlpha(texture._premultiplyAlpha);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this._glCreated) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + face, mipLevel, 0, 0, this._glFormat, this._glPixelType, src);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + face, mipLevel, this._glInternalFormat, this._glFormat, this._glPixelType, src);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresMult = 1 / Math.pow(2, mipLevel);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(face = 0; face < 6; face++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!texture._levelsUpdated[0][face]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst texData = mipObject[face];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (texture._compressed) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this._glCreated && texData) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.compressedTexSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + face, mipLevel, 0, 0, Math.max(texture._width * resMult, 1), Math.max(texture._height * resMult, 1), this._glInternalFormat, texData);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.compressedTexImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + face, mipLevel, this._glInternalFormat, Math.max(texture._width * resMult, 1), Math.max(texture._height * resMult, 1), 0, texData);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackFlipY(false);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackPremultiplyAlpha(texture._premultiplyAlpha);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackAlignment(1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this._glCreated && texData) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + face, mipLevel, 0, 0, Math.max(texture._width * resMult, 1), Math.max(texture._height * resMult, 1), this._glFormat, this._glPixelType, texData);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + face, mipLevel, this._glInternalFormat, Math.max(texture._width * resMult, 1), Math.max(texture._height * resMult, 1), 0, this._glFormat, this._glPixelType, texData);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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} else if (texture._volume) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (texture._compressed) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.compressedTexImage3D(gl.TEXTURE_3D, mipLevel, this._glInternalFormat, Math.max(texture._width * resMult, 1), Math.max(texture._height * resMult, 1), Math.max(texture._depth * resMult, 1), 0, mipObject);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackFlipY(false);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackPremultiplyAlpha(texture._premultiplyAlpha);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackAlignment(1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.texImage3D(gl.TEXTURE_3D, mipLevel, this._glInternalFormat, Math.max(texture._width * resMult, 1), Math.max(texture._height * resMult, 1), Math.max(texture._depth * resMult, 1), 0, this._glFormat, this._glPixelType, mipObject);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else if (texture.array) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (Array.isArray(mipObject) && texture._arrayLength === mipObject.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (texture._compressed) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let index = 0; index < texture._arrayLength; index++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.compressedTexSubImage3D(gl.TEXTURE_2D_ARRAY, mipLevel, 0, 0, index, Math.max(Math.floor(texture._width * resMult), 1), Math.max(Math.floor(texture._height * resMult), 1), 1, this._glInternalFormat, mipObject[index]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackAlignment(1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let index = 0; index < texture._arrayLength; index++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.texSubImage3D(gl.TEXTURE_2D_ARRAY, mipLevel, 0, 0, index, Math.max(Math.floor(texture._width * resMult), 1), Math.max(Math.floor(texture._height * resMult), 1), 1, this._glFormat, this._glPixelType, mipObject[index]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (device._isBrowserInterface(mipObject)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (device._isImageBrowserInterface(mipObject)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (mipObject.width > device.maxTextureSize || mipObject.height > device.maxTextureSize) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmipObject = downsampleImage(mipObject, device.maxTextureSize);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (mipLevel === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture._width = mipObject.width;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture._height = mipObject.height;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst w = mipObject.width || mipObject.videoWidth;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst h = mipObject.height || mipObject.videoHeight;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackFlipY(texture._flipY);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackPremultiplyAlpha(texture._premultiplyAlpha);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this._glCreated && texture._width === w && texture._height === h && !device._isImageVideoInterface(mipObject)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.texSubImage2D(gl.TEXTURE_2D, mipLevel, 0, 0, this._glFormat, this._glPixelType, mipObject);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.texImage2D(gl.TEXTURE_2D, mipLevel, this._glInternalFormat, this._glFormat, this._glPixelType, mipObject);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (mipLevel === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture._width = w;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture._height = h;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresMult = 1 / Math.pow(2, mipLevel);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (texture._compressed) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this._glCreated && mipObject) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.compressedTexSubImage2D(gl.TEXTURE_2D, mipLevel, 0, 0, Math.max(Math.floor(texture._width * resMult), 1), Math.max(Math.floor(texture._height * resMult), 1), this._glInternalFormat, mipObject);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.compressedTexImage2D(gl.TEXTURE_2D, mipLevel, this._glInternalFormat, Math.max(Math.floor(texture._width * resMult), 1), Math.max(Math.floor(texture._height * resMult), 1), 0, mipObject);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackFlipY(false);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackPremultiplyAlpha(texture._premultiplyAlpha);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setUnpackAlignment(1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this._glCreated && mipObject) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.texSubImage2D(gl.TEXTURE_2D, mipLevel, 0, 0, Math.max(texture._width * resMult, 1), Math.max(texture._height * resMult, 1), this._glFormat, this._glPixelType, mipObject);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.texImage2D(gl.TEXTURE_2D, mipLevel, this._glInternalFormat, Math.max(texture._width * resMult, 1), Math.max(texture._height * resMult, 1), 0, this._glFormat, this._glPixelType, mipObject);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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\\tif (mipLevel === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture._mipmapsUploaded = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture._mipmapsUploaded = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tmipLevel++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (texture._needsUpload) {\\n\\t\\t\\t\\t\\t\\tif (texture._cubemap) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < 6; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture._levelsUpdated[0][i] = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\ttexture._levelsUpdated[0] = false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!texture._compressed && !texture._integerFormat && texture._mipmaps && texture._needsMipmapsUpload && texture._levels.length === 1) {\\n\\t\\t\\t\\t\\t\\tgl.generateMipmap(this._glTarget);\\n\\t\\t\\t\\t\\t\\ttexture._mipmapsUploaded = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (texture._gpuSize) {\\n\\t\\t\\t\\t\\t\\ttexture.adjustVramSizeTracking(device._vram, -texture._gpuSize);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttexture._gpuSize = texture.gpuSize;\\n\\t\\t\\t\\ttexture.adjustVramSizeTracking(device._vram, texture._gpuSize);\\n\\t\\t\\t\\tthis._glCreated = true;\\n\\t\\t}\\n\\t\\tuploadImmediate(device, texture) {\\n\\t\\t\\t\\tif (texture._needsUpload || texture._needsMipmapsUpload) {\\n\\t\\t\\t\\t\\t\\tdevice.setTexture(texture, 0);\\n\\t\\t\\t\\t\\t\\ttexture._needsUpload = false;\\n\\t\\t\\t\\t\\t\\ttexture._needsMipmapsUpload = false;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tread(x, y, width, height, options) {\\n\\t\\t\\t\\tconst texture = this.texture;\\n\\t\\t\\t\\tconst device = texture.device;\\n\\t\\t\\t\\treturn device.readTextureAsync(texture, x, y, width, height, options);\\n\\t\\t}\\n\\t\\twrite(x, y, width, height, data) {\\n\\t\\t\\t\\tconst { texture } = this;\\n\\t\\t\\t\\tconst { device } = texture;\\n\\t\\t\\t\\tdevice.setTexture(texture, 0);\\n\\t\\t\\t\\treturn device.writeTextureAsync(texture, x, y, width, height, data);\\n\\t\\t}\\n\\t\\tconstructor(texture){\\n\\t\\t\\t\\tthis._glTexture = null;\\n\\t\\t\\t\\tthis.dirtyParameterFlags = 0;\\n\\t\\t\\t\\tthis.texture = texture;\\n\\t\\t}\\n}\\n\\nclass FramebufferPair {\\n\\t\\tdestroy(gl) {\\n\\t\\t\\t\\tif (this.msaaFB) {\\n\\t\\t\\t\\t\\t\\tgl.deleteRenderbuffer(this.msaaFB);\\n\\t\\t\\t\\t\\t\\tthis.msaaFB = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.resolveFB) {\\n\\t\\t\\t\\t\\t\\tgl.deleteRenderbuffer(this.resolveFB);\\n\\t\\t\\t\\t\\t\\tthis.resolveFB = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(msaaFB, resolveFB){\\n\\t\\t\\t\\tthis.msaaFB = msaaFB;\\n\\t\\t\\t\\tthis.resolveFB = resolveFB;\\n\\t\\t}\\n}\\nclass WebglRenderTarget {\\n\\t\\tdestroy(device) {\\n\\t\\t\\t\\tconst gl = device.gl;\\n\\t\\t\\t\\tthis._isInitialized = false;\\n\\t\\t\\t\\tif (this._glFrameBuffer) {\\n\\t\\t\\t\\t\\t\\tif (this._glFrameBuffer !== this.suppliedColorFramebuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.deleteFramebuffer(this._glFrameBuffer);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._glFrameBuffer = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._glDepthBuffer) {\\n\\t\\t\\t\\t\\t\\tgl.deleteRenderbuffer(this._glDepthBuffer);\\n\\t\\t\\t\\t\\t\\tthis._glDepthBuffer = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._glResolveFrameBuffer) {\\n\\t\\t\\t\\t\\t\\tif (this._glResolveFrameBuffer !== this.suppliedColorFramebuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.deleteFramebuffer(this._glResolveFrameBuffer);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._glResolveFrameBuffer = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._glMsaaColorBuffers.forEach((buffer)=>{\\n\\t\\t\\t\\t\\t\\tgl.deleteRenderbuffer(buffer);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis._glMsaaColorBuffers.length = 0;\\n\\t\\t\\t\\tthis.colorMrtFramebuffers?.forEach((framebuffer)=>{\\n\\t\\t\\t\\t\\t\\tframebuffer.destroy(gl);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.colorMrtFramebuffers = null;\\n\\t\\t\\t\\tif (this._glMsaaDepthBuffer) {\\n\\t\\t\\t\\t\\t\\tthis._glMsaaDepthBuffer = null;\\n\\t\\t\\t\\t\\t\\tif (this.msaaDepthBufferKey) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgetMultisampledTextureCache(device).release(this.msaaDepthBufferKey);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.suppliedColorFramebuffer = undefined;\\n\\t\\t}\\n\\t\\tget initialized() {\\n\\t\\t\\t\\treturn this._isInitialized;\\n\\t\\t}\\n\\t\\tinit(device, target) {\\n\\t\\t\\t\\tconst gl = device.gl;\\n\\t\\t\\t\\tthis._isInitialized = true;\\n\\t\\t\\t\\tconst buffers = [];\\n\\t\\t\\t\\tif (this.suppliedColorFramebuffer !== undefined) {\\n\\t\\t\\t\\t\\t\\tthis._glFrameBuffer = this.suppliedColorFramebuffer;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._glFrameBuffer = gl.createFramebuffer();\\n\\t\\t\\t\\t\\t\\tdevice.setFramebuffer(this._glFrameBuffer);\\n\\t\\t\\t\\t\\t\\tconst colorBufferCount = target._colorBuffers?.length ?? 0;\\n\\t\\t\\t\\t\\t\\tconst attachmentBaseConstant = gl.COLOR_ATTACHMENT0;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < colorBufferCount; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst colorBuffer = target.getColorBuffer(i);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (colorBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!colorBuffer.impl._glTexture) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcolorBuffer._width = Math.min(colorBuffer.width, device.maxRenderBufferSize);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcolorBuffer._height = Math.min(colorBuffer.height, device.maxRenderBufferSize);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setTexture(colorBuffer, 0);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentBaseConstant + i, colorBuffer._cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D, colorBuffer.impl._glTexture, target.mipLevel);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbuffers.push(attachmentBaseConstant + i);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tgl.drawBuffers(buffers);\\n\\t\\t\\t\\t\\t\\tconst depthBuffer = target._depthBuffer;\\n\\t\\t\\t\\t\\t\\tif (depthBuffer || target._depth) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst attachmentPoint = target._stencil ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (depthBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!depthBuffer.impl._glTexture) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdepthBuffer._width = Math.min(depthBuffer.width, device.maxRenderBufferSize);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdepthBuffer._height = Math.min(depthBuffer.height, device.maxRenderBufferSize);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setTexture(depthBuffer, 0);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, depthBuffer._cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D, target._depthBuffer.impl._glTexture, target.mipLevel);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst willRenderMsaa = target._samples > 1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!willRenderMsaa) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!this._glDepthBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._glDepthBuffer = gl.createRenderbuffer();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst internalFormat = target._stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT32F;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.bindRenderbuffer(gl.RENDERBUFFER, this._glDepthBuffer);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.renderbufferStorage(gl.RENDERBUFFER, internalFormat, target.width, target.height);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachmentPoint, gl.RENDERBUFFER, this._glDepthBuffer);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.bindRenderbuffer(gl.RENDERBUFFER, null);\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (target._samples > 1) {\\n\\t\\t\\t\\t\\t\\tthis._glResolveFrameBuffer = this._glFrameBuffer;\\n\\t\\t\\t\\t\\t\\tthis._glFrameBuffer = gl.createFramebuffer();\\n\\t\\t\\t\\t\\t\\tdevice.setFramebuffer(this._glFrameBuffer);\\n\\t\\t\\t\\t\\t\\tconst colorBufferCount = target._colorBuffers?.length ?? 0;\\n\\t\\t\\t\\t\\t\\tif (this.suppliedColorFramebuffer !== undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst buffer = gl.createRenderbuffer();\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._glMsaaColorBuffers.push(buffer);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst internalFormat = device.backBufferFormat === PIXELFORMAT_RGBA8 ? gl.RGBA8 : gl.RGB8;\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.bindRenderbuffer(gl.RENDERBUFFER, buffer);\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.renderbufferStorageMultisample(gl.RENDERBUFFER, target._samples, internalFormat, target.width, target.height);\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, buffer);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < colorBufferCount; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst colorBuffer = target.getColorBuffer(i);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (colorBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst buffer = gl.createRenderbuffer();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._glMsaaColorBuffers.push(buffer);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.bindRenderbuffer(gl.RENDERBUFFER, buffer);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.renderbufferStorageMultisample(gl.RENDERBUFFER, target._samples, colorBuffer.impl._glInternalFormat, target.width, target.height);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.RENDERBUFFER, buffer);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tif (target._depth) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst internalFormat = target._stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT32F;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst attachmentPoint = target._stencil ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;\\n\\t\\t\\t\\t\\t\\t\\t\\tlet key;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst depthBuffer = target._depthBuffer;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (depthBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tkey = `${depthBuffer.id}:${target.width}:${target.height}:${target._samples}:${internalFormat}:${attachmentPoint}`;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._glMsaaDepthBuffer = getMultisampledTextureCache(device).get(key);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this._glMsaaDepthBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._glMsaaDepthBuffer = gl.createRenderbuffer();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.bindRenderbuffer(gl.RENDERBUFFER, this._glMsaaDepthBuffer);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.renderbufferStorageMultisample(gl.RENDERBUFFER, target._samples, internalFormat, target.width, target.height);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._glMsaaDepthBuffer.destroy = function() {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.deleteRenderbuffer(this);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (depthBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgetMultisampledTextureCache(device).set(key, this._glMsaaDepthBuffer);\\n\\t\\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\\tthis.msaaDepthBufferKey = key;\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachmentPoint, gl.RENDERBUFFER, this._glMsaaDepthBuffer);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (colorBufferCount > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._createMsaaMrtFramebuffers(device, target, colorBufferCount);\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.setFramebuffer(this._glFrameBuffer);\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.drawBuffers(buffers);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_createMsaaMrtFramebuffers(device, target, colorBufferCount) {\\n\\t\\t\\t\\tconst gl = device.gl;\\n\\t\\t\\t\\tthis.colorMrtFramebuffers = [];\\n\\t\\t\\t\\tfor(let i = 0; i < colorBufferCount; ++i){\\n\\t\\t\\t\\t\\t\\tconst colorBuffer = target.getColorBuffer(i);\\n\\t\\t\\t\\t\\t\\tconst srcFramebuffer = gl.createFramebuffer();\\n\\t\\t\\t\\t\\t\\tdevice.setFramebuffer(srcFramebuffer);\\n\\t\\t\\t\\t\\t\\tconst buffer = this._glMsaaColorBuffers[i];\\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, gl.RENDERBUFFER, buffer);\\n\\t\\t\\t\\t\\t\\tgl.drawBuffers([\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.COLOR_ATTACHMENT0\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\tconst dstFramebuffer = gl.createFramebuffer();\\n\\t\\t\\t\\t\\t\\tdevice.setFramebuffer(dstFramebuffer);\\n\\t\\t\\t\\t\\t\\tgl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorBuffer._cubemap ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + target._face : gl.TEXTURE_2D, colorBuffer.impl._glTexture, 0);\\n\\t\\t\\t\\t\\t\\tthis.colorMrtFramebuffers[i] = new FramebufferPair(srcFramebuffer, dstFramebuffer);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_checkFbo(device, target, type = '') {\\n\\t\\t\\t\\tconst gl = device.gl;\\n\\t\\t\\t\\tconst status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\\n\\t\\t\\t\\tswitch(status){\\n\\t\\t\\t\\t\\t\\tcase gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase gl.FRAMEBUFFER_UNSUPPORTED:\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tthis._glFrameBuffer = null;\\n\\t\\t\\t\\tthis._glDepthBuffer = null;\\n\\t\\t\\t\\tthis._glResolveFrameBuffer = null;\\n\\t\\t\\t\\tthis._glMsaaColorBuffers.length = 0;\\n\\t\\t\\t\\tthis._glMsaaDepthBuffer = null;\\n\\t\\t\\t\\tthis.msaaDepthBufferKey = undefined;\\n\\t\\t\\t\\tthis.colorMrtFramebuffers = null;\\n\\t\\t\\t\\tthis.suppliedColorFramebuffer = undefined;\\n\\t\\t\\t\\tthis._isInitialized = false;\\n\\t\\t}\\n\\t\\tinternalResolve(device, src, dst, target, mask) {\\n\\t\\t\\t\\tdevice.setScissor(0, 0, target.width, target.height);\\n\\t\\t\\t\\tconst gl = device.gl;\\n\\t\\t\\t\\tgl.bindFramebuffer(gl.READ_FRAMEBUFFER, src);\\n\\t\\t\\t\\tgl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dst);\\n\\t\\t\\t\\tgl.blitFramebuffer(0, 0, target.width, target.height, 0, 0, target.width, target.height, mask, gl.NEAREST);\\n\\t\\t}\\n\\t\\tresolve(device, target, color, depth) {\\n\\t\\t\\t\\tconst gl = device.gl;\\n\\t\\t\\t\\tif (this.colorMrtFramebuffers) {\\n\\t\\t\\t\\t\\t\\tif (color) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this.colorMrtFramebuffers.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst fbPair = this.colorMrtFramebuffers[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.internalResolve(device, fbPair.msaaFB, fbPair.resolveFB, target, gl.COLOR_BUFFER_BIT);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (depth) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.internalResolve(device, this._glFrameBuffer, this._glResolveFrameBuffer, target, gl.DEPTH_BUFFER_BIT);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.internalResolve(device, this._glFrameBuffer, this._glResolveFrameBuffer, target, (color ? gl.COLOR_BUFFER_BIT : 0) | (depth ? gl.DEPTH_BUFFER_BIT : 0));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tgl.bindFramebuffer(gl.FRAMEBUFFER, this._glFrameBuffer);\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis._glFrameBuffer = null;\\n\\t\\t\\t\\tthis._glDepthBuffer = null;\\n\\t\\t\\t\\tthis._glResolveFrameBuffer = null;\\n\\t\\t\\t\\tthis.colorMrtFramebuffers = null;\\n\\t\\t\\t\\tthis._glMsaaColorBuffers = [];\\n\\t\\t\\t\\tthis._glMsaaDepthBuffer = null;\\n\\t\\t\\t\\tthis._isInitialized = false;\\n\\t\\t}\\n}\\n\\nclass WebglUploadStream {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tconst gl = this.uploadStream.device.gl;\\n\\t\\t\\t\\tthis.availablePBOs.forEach((info)=>gl.deleteBuffer(info.pbo));\\n\\t\\t\\t\\tthis.pendingPBOs.forEach((item)=>{\\n\\t\\t\\t\\t\\t\\tif (item.sync) gl.deleteSync(item.sync);\\n\\t\\t\\t\\t\\t\\tgl.deleteBuffer(item.pbo);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\t_onDeviceLost() {\\n\\t\\t\\t\\tthis.availablePBOs.length = 0;\\n\\t\\t\\t\\tthis.pendingPBOs.length = 0;\\n\\t\\t}\\n\\t\\tupdate(minByteSize) {\\n\\t\\t\\t\\tconst gl = this.uploadStream.device.gl;\\n\\t\\t\\t\\tconst pending = this.pendingPBOs;\\n\\t\\t\\t\\tfor(let i = pending.length - 1; i >= 0; i--){\\n\\t\\t\\t\\t\\t\\tconst item = pending[i];\\n\\t\\t\\t\\t\\t\\tconst result = gl.clientWaitSync(item.sync, 0, 0);\\n\\t\\t\\t\\t\\t\\tif (result === gl.CONDITION_SATISFIED || result === gl.ALREADY_SIGNALED) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.deleteSync(item.sync);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.availablePBOs.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpbo: item.pbo,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsize: item.size\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tpending.splice(i, 1);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst available = this.availablePBOs;\\n\\t\\t\\t\\tfor(let i = available.length - 1; i >= 0; i--){\\n\\t\\t\\t\\t\\t\\tif (available[i].size < minByteSize) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.deleteBuffer(available[i].pbo);\\n\\t\\t\\t\\t\\t\\t\\t\\tavailable.splice(i, 1);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupload(data, target, offset, size) {\\n\\t\\t\\t\\tif (this.useSingleBuffer) {\\n\\t\\t\\t\\t\\t\\tthis.uploadDirect(data, target, offset, size);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.uploadPBO(data, target, offset, size);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tuploadDirect(data, target, offset, size) {\\n\\t\\t\\t\\ttarget._levels[0] = data;\\n\\t\\t\\t\\ttarget.upload();\\n\\t\\t}\\n\\t\\tuploadPBO(data, target, offset, size) {\\n\\t\\t\\t\\tconst device = this.uploadStream.device;\\n\\t\\t\\t\\tconst gl = device.gl;\\n\\t\\t\\t\\tconst width = target.width;\\n\\t\\t\\t\\tconst byteSize = size * data.BYTES_PER_ELEMENT;\\n\\t\\t\\t\\tthis.update(byteSize);\\n\\t\\t\\t\\tconst startY = offset / width;\\n\\t\\t\\t\\tconst height = size / width;\\n\\t\\t\\t\\tconst pboInfo = this.availablePBOs.pop() ?? (()=>{\\n\\t\\t\\t\\t\\t\\tconst pbo = gl.createBuffer();\\n\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\tpbo,\\n\\t\\t\\t\\t\\t\\t\\t\\tsize: byteSize\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t})();\\n\\t\\t\\t\\tgl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, pboInfo.pbo);\\n\\t\\t\\t\\tgl.bufferData(gl.PIXEL_UNPACK_BUFFER, byteSize, gl.STREAM_DRAW);\\n\\t\\t\\t\\tgl.bufferSubData(gl.PIXEL_UNPACK_BUFFER, 0, new Uint8Array(data.buffer, data.byteOffset, byteSize));\\n\\t\\t\\t\\tgl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);\\n\\t\\t\\t\\tdevice.setTexture(target, 0);\\n\\t\\t\\t\\tdevice.activeTexture(0);\\n\\t\\t\\t\\tdevice.bindTexture(target);\\n\\t\\t\\t\\tgl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, pboInfo.pbo);\\n\\t\\t\\t\\tdevice.setUnpackFlipY(false);\\n\\t\\t\\t\\tdevice.setUnpackPremultiplyAlpha(false);\\n\\t\\t\\t\\tdevice.setUnpackAlignment(data.BYTES_PER_ELEMENT);\\n\\t\\t\\t\\tgl.pixelStorei(gl.UNPACK_ROW_LENGTH, 0);\\n\\t\\t\\t\\tgl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0);\\n\\t\\t\\t\\tgl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0);\\n\\t\\t\\t\\tconst impl = target.impl;\\n\\t\\t\\t\\tgl.texSubImage2D(gl.TEXTURE_2D, 0, 0, startY, width, height, impl._glFormat, impl._glPixelType, 0);\\n\\t\\t\\t\\tgl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);\\n\\t\\t\\t\\tconst sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);\\n\\t\\t\\t\\tthis.pendingPBOs.push({\\n\\t\\t\\t\\t\\t\\tpbo: pboInfo.pbo,\\n\\t\\t\\t\\t\\t\\tsize: byteSize,\\n\\t\\t\\t\\t\\t\\tsync\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tgl.flush();\\n\\t\\t}\\n\\t\\tconstructor(uploadStream){\\n\\t\\t\\t\\tthis.availablePBOs = [];\\n\\t\\t\\t\\tthis.pendingPBOs = [];\\n\\t\\t\\t\\tthis.uploadStream = uploadStream;\\n\\t\\t\\t\\tthis.useSingleBuffer = uploadStream.useSingleBuffer;\\n\\t\\t}\\n}\\n\\nclass FrameQueriesInfo {\\n\\t\\tdestroy(gl) {\\n\\t\\t\\t\\tthis.queries.forEach((query)=>gl.deleteQuery(query));\\n\\t\\t\\t\\tthis.queries = null;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.queries = [];\\n\\t\\t}\\n}\\nclass WebglGpuProfiler extends GpuProfiler {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.freeQueries.forEach((query)=>this.device.gl.deleteQuery(query));\\n\\t\\t\\t\\tthis.frameQueries.forEach((query)=>this.device.gl.deleteQuery(query));\\n\\t\\t\\t\\tthis.previousFrameQueries.forEach((frameQueriesInfo)=>frameQueriesInfo.destroy(this.device.gl));\\n\\t\\t\\t\\tthis.freeQueries = null;\\n\\t\\t\\t\\tthis.frameQueries = null;\\n\\t\\t\\t\\tthis.previousFrameQueries = null;\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tsuper.loseContext();\\n\\t\\t\\t\\tthis.freeQueries = [];\\n\\t\\t\\t\\tthis.frameQueries = [];\\n\\t\\t\\t\\tthis.previousFrameQueries = [];\\n\\t\\t}\\n\\t\\trestoreContext() {\\n\\t\\t\\t\\tthis.ext = this.device.extDisjointTimerQuery;\\n\\t\\t}\\n\\t\\tgetQuery() {\\n\\t\\t\\t\\treturn this.freeQueries.pop() ?? this.device.gl.createQuery();\\n\\t\\t}\\n\\t\\tstart(name) {\\n\\t\\t\\t\\tif (this.ext) {\\n\\t\\t\\t\\t\\t\\tconst slot = this.getSlot(name);\\n\\t\\t\\t\\t\\t\\tconst query = this.getQuery();\\n\\t\\t\\t\\t\\t\\tthis.frameQueries[slot] = query;\\n\\t\\t\\t\\t\\t\\tthis.device.gl.beginQuery(this.ext.TIME_ELAPSED_EXT, query);\\n\\t\\t\\t\\t\\t\\treturn slot;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn undefined;\\n\\t\\t}\\n\\t\\tend(slot) {\\n\\t\\t\\t\\tif (slot !== undefined) {\\n\\t\\t\\t\\t\\t\\tthis.device.gl.endQuery(this.ext.TIME_ELAPSED_EXT);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tframeStart() {\\n\\t\\t\\t\\tthis.processEnableRequest();\\n\\t\\t\\t\\tif (this._enabled) {\\n\\t\\t\\t\\t\\t\\tthis.frameGPUMarkerSlot = this.start('GpuFrame');\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tframeEnd() {\\n\\t\\t\\t\\tif (this._enabled) {\\n\\t\\t\\t\\t\\t\\tthis.end(this.frameGPUMarkerSlot);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\trequest() {\\n\\t\\t\\t\\tif (this._enabled) {\\n\\t\\t\\t\\t\\t\\tconst ext = this.ext;\\n\\t\\t\\t\\t\\t\\tconst gl = this.device.gl;\\n\\t\\t\\t\\t\\t\\tconst renderVersion = this.device.renderVersion;\\n\\t\\t\\t\\t\\t\\tconst frameQueries = this.frameQueries;\\n\\t\\t\\t\\t\\t\\tif (frameQueries.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.frameQueries = [];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst frameQueriesInfo = new FrameQueriesInfo();\\n\\t\\t\\t\\t\\t\\t\\t\\tframeQueriesInfo.queries = frameQueries;\\n\\t\\t\\t\\t\\t\\t\\t\\tframeQueriesInfo.renderVersion = renderVersion;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.previousFrameQueries.push(frameQueriesInfo);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.previousFrameQueries.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst previousQueriesInfo = this.previousFrameQueries[0];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst previousQueries = previousQueriesInfo.queries;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst lastQuery = previousQueries[previousQueries.length - 1];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst available = gl.getQueryParameter(lastQuery, gl.QUERY_RESULT_AVAILABLE);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst disjoint = gl.getParameter(ext.GPU_DISJOINT_EXT);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (available && !disjoint) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.previousFrameQueries.shift();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst timings = this.timings;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttimings.length = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < previousQueries.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst query = previousQueries[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst duration = gl.getQueryParameter(query, gl.QUERY_RESULT);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttimings[i] = duration * 0.000001;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.freeQueries.push(query);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.report(previousQueriesInfo.renderVersion, timings);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (disjoint) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.previousFrameQueries.forEach((frameQueriesInfo)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.report(frameQueriesInfo.renderVersion, null);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tframeQueriesInfo.destroy(gl);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.previousFrameQueries.length = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tsuper.request(renderVersion);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tsuper(), this.freeQueries = [], this.frameQueries = [], this.previousFrameQueries = [], this.timings = [];\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.ext = device.extDisjointTimerQuery;\\n\\t\\t}\\n}\\n\\nconst getPixelFormatChannelsForRgbaReadback = (format)=>{\\n\\t\\tswitch(format){\\n\\t\\t\\t\\tcase PIXELFORMAT_R8:\\n\\t\\t\\t\\t\\t\\treturn 1;\\n\\t\\t\\t\\tcase PIXELFORMAT_RG8:\\n\\t\\t\\t\\t\\t\\treturn 2;\\n\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\treturn 0;\\n\\t\\t}\\n};\\nconst invalidateAttachments = [];\\nclass WebglGraphicsDevice extends GraphicsDevice {\\n\\t\\tpostInit() {\\n\\t\\t\\t\\tsuper.postInit();\\n\\t\\t\\t\\tthis.gpuProfiler = new WebglGpuProfiler(this);\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tsuper.destroy();\\n\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\tif (this.feedback) {\\n\\t\\t\\t\\t\\t\\tgl.deleteTransformFeedback(this.feedback);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.clearVertexArrayObjectCache();\\n\\t\\t\\t\\tthis.canvas.removeEventListener('webglcontextlost', this._contextLostHandler, false);\\n\\t\\t\\t\\tthis.canvas.removeEventListener('webglcontextrestored', this._contextRestoredHandler, false);\\n\\t\\t\\t\\tthis._contextLostHandler = null;\\n\\t\\t\\t\\tthis._contextRestoredHandler = null;\\n\\t\\t\\t\\tthis.gl = null;\\n\\t\\t\\t\\tsuper.postDestroy();\\n\\t\\t}\\n\\t\\tcreateBackbuffer(frameBuffer) {\\n\\t\\t\\t\\tthis.supportsStencil = this.initOptions.stencil;\\n\\t\\t\\t\\tthis.backBuffer = new RenderTarget({\\n\\t\\t\\t\\t\\t\\tname: 'WebglFramebuffer',\\n\\t\\t\\t\\t\\t\\tgraphicsDevice: this,\\n\\t\\t\\t\\t\\t\\tdepth: this.initOptions.depth,\\n\\t\\t\\t\\t\\t\\tstencil: this.supportsStencil,\\n\\t\\t\\t\\t\\t\\tsamples: this.samples\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.backBuffer.impl.suppliedColorFramebuffer = frameBuffer;\\n\\t\\t}\\n\\t\\tupdateBackbufferFormat(framebuffer) {\\n\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\tgl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\\n\\t\\t\\t\\tconst alphaBits = this.gl.getParameter(this.gl.ALPHA_BITS);\\n\\t\\t\\t\\tthis.backBufferFormat = alphaBits ? PIXELFORMAT_RGBA8 : PIXELFORMAT_RGB8;\\n\\t\\t}\\n\\t\\tupdateBackbuffer() {\\n\\t\\t\\t\\tconst resolutionChanged = this.canvas.width !== this.backBufferSize.x || this.canvas.height !== this.backBufferSize.y;\\n\\t\\t\\t\\tif (this._defaultFramebufferChanged || resolutionChanged) {\\n\\t\\t\\t\\t\\t\\tif (this._defaultFramebufferChanged) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.updateBackbufferFormat(this._defaultFramebuffer);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._defaultFramebufferChanged = false;\\n\\t\\t\\t\\t\\t\\tthis.backBufferSize.set(this.canvas.width, this.canvas.height);\\n\\t\\t\\t\\t\\t\\tthis.backBuffer.destroy();\\n\\t\\t\\t\\t\\t\\tthis.createBackbuffer(this._defaultFramebuffer);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcreateVertexBufferImpl(vertexBuffer, format) {\\n\\t\\t\\t\\treturn new WebglVertexBuffer();\\n\\t\\t}\\n\\t\\tcreateIndexBufferImpl(indexBuffer) {\\n\\t\\t\\t\\treturn new WebglIndexBuffer(indexBuffer);\\n\\t\\t}\\n\\t\\tcreateShaderImpl(shader) {\\n\\t\\t\\t\\treturn new WebglShader(shader);\\n\\t\\t}\\n\\t\\tcreateDrawCommandImpl(drawCommands) {\\n\\t\\t\\t\\treturn new WebglDrawCommands(drawCommands.indexSizeBytes);\\n\\t\\t}\\n\\t\\tcreateTextureImpl(texture) {\\n\\t\\t\\t\\tthis.textures.add(texture);\\n\\t\\t\\t\\treturn new WebglTexture(texture);\\n\\t\\t}\\n\\t\\tcreateRenderTargetImpl(renderTarget) {\\n\\t\\t\\t\\treturn new WebglRenderTarget();\\n\\t\\t}\\n\\t\\tcreateUploadStreamImpl(uploadStream) {\\n\\t\\t\\t\\treturn new WebglUploadStream(uploadStream);\\n\\t\\t}\\n\\t\\tgetPrecision() {\\n\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\tlet precision = 'highp';\\n\\t\\t\\t\\tif (gl.getShaderPrecisionFormat) {\\n\\t\\t\\t\\t\\t\\tconst vertexShaderPrecisionHighpFloat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT);\\n\\t\\t\\t\\t\\t\\tconst vertexShaderPrecisionMediumpFloat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT);\\n\\t\\t\\t\\t\\t\\tconst fragmentShaderPrecisionHighpFloat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT);\\n\\t\\t\\t\\t\\t\\tconst fragmentShaderPrecisionMediumpFloat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT);\\n\\t\\t\\t\\t\\t\\tif (vertexShaderPrecisionHighpFloat && vertexShaderPrecisionMediumpFloat && fragmentShaderPrecisionHighpFloat && fragmentShaderPrecisionMediumpFloat) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst highpAvailable = vertexShaderPrecisionHighpFloat.precision > 0 && fragmentShaderPrecisionHighpFloat.precision > 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst mediumpAvailable = vertexShaderPrecisionMediumpFloat.precision > 0 && fragmentShaderPrecisionMediumpFloat.precision > 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!highpAvailable) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (mediumpAvailable) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tprecision = 'mediump';\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tprecision = 'lowp';\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn precision;\\n\\t\\t}\\n\\t\\tgetExtension() {\\n\\t\\t\\t\\tfor(let i = 0; i < arguments.length; i++){\\n\\t\\t\\t\\t\\t\\tif (this.supportedExtensions.indexOf(arguments[i]) !== -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn this.gl.getExtension(arguments[i]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tget extDisjointTimerQuery() {\\n\\t\\t\\t\\tif (!this._extDisjointTimerQuery) {\\n\\t\\t\\t\\t\\t\\tthis._extDisjointTimerQuery = this.getExtension('EXT_disjoint_timer_query_webgl2', 'EXT_disjoint_timer_query');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._extDisjointTimerQuery;\\n\\t\\t}\\n\\t\\tinitializeExtensions() {\\n\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\tthis.supportedExtensions = gl.getSupportedExtensions() ?? [];\\n\\t\\t\\t\\tthis._extDisjointTimerQuery = null;\\n\\t\\t\\t\\tthis.textureRG11B10Renderable = true;\\n\\t\\t\\t\\tthis.extColorBufferFloat = this.getExtension('EXT_color_buffer_float');\\n\\t\\t\\t\\tthis.textureFloatRenderable = !!this.extColorBufferFloat;\\n\\t\\t\\t\\tthis.extColorBufferHalfFloat = this.getExtension('EXT_color_buffer_half_float');\\n\\t\\t\\t\\tthis.textureHalfFloatRenderable = !!this.extColorBufferHalfFloat || !!this.extColorBufferFloat;\\n\\t\\t\\t\\tthis.extDebugRendererInfo = this.getExtension('WEBGL_debug_renderer_info');\\n\\t\\t\\t\\tthis.extTextureFloatLinear = this.getExtension('OES_texture_float_linear');\\n\\t\\t\\t\\tthis.textureFloatFilterable = !!this.extTextureFloatLinear;\\n\\t\\t\\t\\tthis.extFloatBlend = this.getExtension('EXT_float_blend');\\n\\t\\t\\t\\tthis.extTextureFilterAnisotropic = this.getExtension('EXT_texture_filter_anisotropic', 'WEBKIT_EXT_texture_filter_anisotropic');\\n\\t\\t\\t\\tthis.extParallelShaderCompile = this.getExtension('KHR_parallel_shader_compile');\\n\\t\\t\\t\\tthis.extMultiDraw = this.getExtension('WEBGL_multi_draw');\\n\\t\\t\\t\\tthis.supportsMultiDraw = !!this.extMultiDraw;\\n\\t\\t\\t\\tthis.extCompressedTextureETC1 = this.getExtension('WEBGL_compressed_texture_etc1');\\n\\t\\t\\t\\tthis.extCompressedTextureETC = this.getExtension('WEBGL_compressed_texture_etc');\\n\\t\\t\\t\\tthis.extCompressedTexturePVRTC = this.getExtension('WEBGL_compressed_texture_pvrtc', 'WEBKIT_WEBGL_compressed_texture_pvrtc');\\n\\t\\t\\t\\tthis.extCompressedTextureS3TC = this.getExtension('WEBGL_compressed_texture_s3tc', 'WEBKIT_WEBGL_compressed_texture_s3tc');\\n\\t\\t\\t\\tthis.extCompressedTextureS3TC_SRGB = this.getExtension('WEBGL_compressed_texture_s3tc_srgb');\\n\\t\\t\\t\\tthis.extCompressedTextureATC = this.getExtension('WEBGL_compressed_texture_atc');\\n\\t\\t\\t\\tthis.extCompressedTextureASTC = this.getExtension('WEBGL_compressed_texture_astc');\\n\\t\\t\\t\\tthis.extTextureCompressionBPTC = this.getExtension('EXT_texture_compression_bptc');\\n\\t\\t}\\n\\t\\tinitializeCapabilities() {\\n\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\tlet ext;\\n\\t\\t\\t\\tconst userAgent = typeof navigator !== 'undefined' ? navigator.userAgent : '';\\n\\t\\t\\t\\tthis.maxPrecision = this.precision = this.getPrecision();\\n\\t\\t\\t\\tconst contextAttribs = gl.getContextAttributes();\\n\\t\\t\\t\\tthis.supportsMsaa = contextAttribs?.antialias ?? false;\\n\\t\\t\\t\\tthis.supportsStencil = contextAttribs?.stencil ?? false;\\n\\t\\t\\t\\tthis.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);\\n\\t\\t\\t\\tthis.maxCubeMapSize = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE);\\n\\t\\t\\t\\tthis.maxRenderBufferSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE);\\n\\t\\t\\t\\tthis.maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);\\n\\t\\t\\t\\tthis.maxCombinedTextures = gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS);\\n\\t\\t\\t\\tthis.maxVertexTextures = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS);\\n\\t\\t\\t\\tthis.vertexUniformsCount = gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS);\\n\\t\\t\\t\\tthis.fragmentUniformsCount = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS);\\n\\t\\t\\t\\tthis.maxColorAttachments = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);\\n\\t\\t\\t\\tthis.maxVolumeSize = gl.getParameter(gl.MAX_3D_TEXTURE_SIZE);\\n\\t\\t\\t\\text = this.extDebugRendererInfo;\\n\\t\\t\\t\\tthis.unmaskedRenderer = ext ? gl.getParameter(ext.UNMASKED_RENDERER_WEBGL) : '';\\n\\t\\t\\t\\tthis.unmaskedVendor = ext ? gl.getParameter(ext.UNMASKED_VENDOR_WEBGL) : '';\\n\\t\\t\\t\\tconst maliRendererRegex = /\\\\bMali-G52+/;\\n\\t\\t\\t\\tconst samsungModelRegex = /SM-[a-zA-Z0-9]+/;\\n\\t\\t\\t\\tthis.supportsGpuParticles = !(this.unmaskedVendor === 'ARM' && userAgent.match(samsungModelRegex)) && !this.unmaskedRenderer.match(maliRendererRegex);\\n\\t\\t\\t\\text = this.extTextureFilterAnisotropic;\\n\\t\\t\\t\\tthis.maxAnisotropy = ext ? gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY_EXT) : 1;\\n\\t\\t\\t\\tconst antialiasSupported = !this.forceDisableMultisampling;\\n\\t\\t\\t\\tthis.maxSamples = antialiasSupported ? gl.getParameter(gl.MAX_SAMPLES) : 1;\\n\\t\\t\\t\\tthis.maxSamples = Math.min(this.maxSamples, 4);\\n\\t\\t\\t\\tthis.samples = antialiasSupported && this.backBufferAntialias ? this.maxSamples : 1;\\n\\t\\t\\t\\tthis.supportsAreaLights = !platform.android;\\n\\t\\t\\t\\tif (this.maxTextures <= 8) {\\n\\t\\t\\t\\t\\t\\tthis.supportsAreaLights = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.initCapsDefines();\\n\\t\\t}\\n\\t\\tinitializeRenderState() {\\n\\t\\t\\t\\tsuper.initializeRenderState();\\n\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\tgl.disable(gl.BLEND);\\n\\t\\t\\t\\tgl.blendFunc(gl.ONE, gl.ZERO);\\n\\t\\t\\t\\tgl.blendEquation(gl.FUNC_ADD);\\n\\t\\t\\t\\tgl.colorMask(true, true, true, true);\\n\\t\\t\\t\\tgl.blendColor(0, 0, 0, 0);\\n\\t\\t\\t\\tgl.enable(gl.CULL_FACE);\\n\\t\\t\\t\\tthis.cullFace = gl.BACK;\\n\\t\\t\\t\\tgl.cullFace(gl.BACK);\\n\\t\\t\\t\\tgl.enable(gl.DEPTH_TEST);\\n\\t\\t\\t\\tgl.depthFunc(gl.LEQUAL);\\n\\t\\t\\t\\tgl.depthMask(true);\\n\\t\\t\\t\\tthis.stencil = false;\\n\\t\\t\\t\\tgl.disable(gl.STENCIL_TEST);\\n\\t\\t\\t\\tthis.stencilFuncFront = this.stencilFuncBack = FUNC_ALWAYS;\\n\\t\\t\\t\\tthis.stencilRefFront = this.stencilRefBack = 0;\\n\\t\\t\\t\\tthis.stencilMaskFront = this.stencilMaskBack = 0xFF;\\n\\t\\t\\t\\tgl.stencilFunc(gl.ALWAYS, 0, 0xFF);\\n\\t\\t\\t\\tthis.stencilFailFront = this.stencilFailBack = STENCILOP_KEEP;\\n\\t\\t\\t\\tthis.stencilZfailFront = this.stencilZfailBack = STENCILOP_KEEP;\\n\\t\\t\\t\\tthis.stencilZpassFront = this.stencilZpassBack = STENCILOP_KEEP;\\n\\t\\t\\t\\tthis.stencilWriteMaskFront = 0xFF;\\n\\t\\t\\t\\tthis.stencilWriteMaskBack = 0xFF;\\n\\t\\t\\t\\tgl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);\\n\\t\\t\\t\\tgl.stencilMask(0xFF);\\n\\t\\t\\t\\tthis.alphaToCoverage = false;\\n\\t\\t\\t\\tthis.raster = true;\\n\\t\\t\\t\\tgl.disable(gl.SAMPLE_ALPHA_TO_COVERAGE);\\n\\t\\t\\t\\tgl.disable(gl.RASTERIZER_DISCARD);\\n\\t\\t\\t\\tthis.depthBiasEnabled = false;\\n\\t\\t\\t\\tgl.disable(gl.POLYGON_OFFSET_FILL);\\n\\t\\t\\t\\tthis.clearDepth = 1;\\n\\t\\t\\t\\tgl.clearDepth(1);\\n\\t\\t\\t\\tthis.clearColor = new Color(0, 0, 0, 0);\\n\\t\\t\\t\\tgl.clearColor(0, 0, 0, 0);\\n\\t\\t\\t\\tthis.clearStencil = 0;\\n\\t\\t\\t\\tgl.clearStencil(0);\\n\\t\\t\\t\\tgl.hint(gl.FRAGMENT_SHADER_DERIVATIVE_HINT, gl.NICEST);\\n\\t\\t\\t\\tgl.enable(gl.SCISSOR_TEST);\\n\\t\\t\\t\\tgl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);\\n\\t\\t\\t\\tthis.unpackFlipY = false;\\n\\t\\t\\t\\tgl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\\n\\t\\t\\t\\tthis.unpackPremultiplyAlpha = false;\\n\\t\\t\\t\\tgl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\\n\\t\\t\\t\\tthis.unpackAlignment = 1;\\n\\t\\t\\t\\tgl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);\\n\\t\\t}\\n\\t\\tinitTextureUnits(count = 16) {\\n\\t\\t\\t\\tthis.textureUnits = [];\\n\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\tthis.textureUnits.push([\\n\\t\\t\\t\\t\\t\\t\\t\\tnull,\\n\\t\\t\\t\\t\\t\\t\\t\\tnull,\\n\\t\\t\\t\\t\\t\\t\\t\\tnull\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tinitializeContextCaches() {\\n\\t\\t\\t\\tsuper.initializeContextCaches();\\n\\t\\t\\t\\tthis._vaoMap = new Map();\\n\\t\\t\\t\\tthis.boundVao = null;\\n\\t\\t\\t\\tthis.activeFramebuffer = null;\\n\\t\\t\\t\\tthis.feedback = null;\\n\\t\\t\\t\\tthis.transformFeedbackBuffer = null;\\n\\t\\t\\t\\tthis.textureUnit = 0;\\n\\t\\t\\t\\tthis.initTextureUnits(this.maxCombinedTextures);\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tsuper.loseContext();\\n\\t\\t\\t\\tfor (const shader of this.shaders){\\n\\t\\t\\t\\t\\t\\tshader.loseContext();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\trestoreContext() {\\n\\t\\t\\t\\tthis.initializeExtensions();\\n\\t\\t\\t\\tthis.initializeCapabilities();\\n\\t\\t\\t\\tsuper.restoreContext();\\n\\t\\t\\t\\tfor (const shader of this.shaders){\\n\\t\\t\\t\\t\\t\\tshader.restoreContext();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetViewport(x, y, w, h) {\\n\\t\\t\\t\\tif (this.vx !== x || this.vy !== y || this.vw !== w || this.vh !== h) {\\n\\t\\t\\t\\t\\t\\tthis.gl.viewport(x, y, w, h);\\n\\t\\t\\t\\t\\t\\tthis.vx = x;\\n\\t\\t\\t\\t\\t\\tthis.vy = y;\\n\\t\\t\\t\\t\\t\\tthis.vw = w;\\n\\t\\t\\t\\t\\t\\tthis.vh = h;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetScissor(x, y, w, h) {\\n\\t\\t\\t\\tif (this.sx !== x || this.sy !== y || this.sw !== w || this.sh !== h) {\\n\\t\\t\\t\\t\\t\\tthis.gl.scissor(x, y, w, h);\\n\\t\\t\\t\\t\\t\\tthis.sx = x;\\n\\t\\t\\t\\t\\t\\tthis.sy = y;\\n\\t\\t\\t\\t\\t\\tthis.sw = w;\\n\\t\\t\\t\\t\\t\\tthis.sh = h;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetFramebuffer(fb) {\\n\\t\\t\\t\\tif (this.activeFramebuffer !== fb) {\\n\\t\\t\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\t\\t\\tgl.bindFramebuffer(gl.FRAMEBUFFER, fb);\\n\\t\\t\\t\\t\\t\\tthis.activeFramebuffer = fb;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcopyRenderTarget(source, dest, color, depth) {\\n\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\tif (source === this.backBuffer) {\\n\\t\\t\\t\\t\\t\\tsource = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (color) {\\n\\t\\t\\t\\t\\t\\tif (!dest) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!source._colorBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else if (source) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!source._colorBuffer || !dest._colorBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (source._colorBuffer._format !== dest._colorBuffer._format) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (depth && source) {\\n\\t\\t\\t\\t\\t\\tif (!source._depth) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!source._depthBuffer || !dest._depthBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (source._depthBuffer._format !== dest._depthBuffer._format) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst prevRt = this.renderTarget;\\n\\t\\t\\t\\tthis.renderTarget = dest;\\n\\t\\t\\t\\tthis.updateBegin();\\n\\t\\t\\t\\tconst src = source ? source.impl._glFrameBuffer : this.backBuffer?.impl._glFrameBuffer;\\n\\t\\t\\t\\tconst dst = dest ? dest.impl._glFrameBuffer : this.backBuffer?.impl._glFrameBuffer;\\n\\t\\t\\t\\tgl.bindFramebuffer(gl.READ_FRAMEBUFFER, src);\\n\\t\\t\\t\\tgl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dst);\\n\\t\\t\\t\\tconst w = source ? source.width : dest ? dest.width : this.width;\\n\\t\\t\\t\\tconst h = source ? source.height : dest ? dest.height : this.height;\\n\\t\\t\\t\\tgl.blitFramebuffer(0, 0, w, h, 0, 0, w, h, (color ? gl.COLOR_BUFFER_BIT : 0) | (depth ? gl.DEPTH_BUFFER_BIT : 0), gl.NEAREST);\\n\\t\\t\\t\\tthis.renderTarget = prevRt;\\n\\t\\t\\t\\tgl.bindFramebuffer(gl.FRAMEBUFFER, prevRt ? prevRt.impl._glFrameBuffer : null);\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tframeStart() {\\n\\t\\t\\t\\tsuper.frameStart();\\n\\t\\t\\t\\tthis.updateBackbuffer();\\n\\t\\t\\t\\tthis.gpuProfiler.frameStart();\\n\\t\\t}\\n\\t\\tframeEnd() {\\n\\t\\t\\t\\tsuper.frameEnd();\\n\\t\\t\\t\\tthis.gpuProfiler.frameEnd();\\n\\t\\t\\t\\tthis.gpuProfiler.request();\\n\\t\\t}\\n\\t\\tstartRenderPass(renderPass) {\\n\\t\\t\\t\\tconst rt = renderPass.renderTarget ?? this.backBuffer;\\n\\t\\t\\t\\tthis.renderTarget = rt;\\n\\t\\t\\t\\tthis.updateBegin();\\n\\t\\t\\t\\tconst { width, height } = rt;\\n\\t\\t\\t\\tthis.setViewport(0, 0, width, height);\\n\\t\\t\\t\\tthis.setScissor(0, 0, width, height);\\n\\t\\t\\t\\tconst colorOps = renderPass.colorOps;\\n\\t\\t\\t\\tconst depthStencilOps = renderPass.depthStencilOps;\\n\\t\\t\\t\\tif (colorOps?.clear || depthStencilOps.clearDepth || depthStencilOps.clearStencil) {\\n\\t\\t\\t\\t\\t\\tlet clearFlags = 0;\\n\\t\\t\\t\\t\\t\\tconst clearOptions = {};\\n\\t\\t\\t\\t\\t\\tif (colorOps?.clear) {\\n\\t\\t\\t\\t\\t\\t\\t\\tclearFlags |= CLEARFLAG_COLOR;\\n\\t\\t\\t\\t\\t\\t\\t\\tclearOptions.color = [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcolorOps.clearValue.r,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcolorOps.clearValue.g,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcolorOps.clearValue.b,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcolorOps.clearValue.a\\n\\t\\t\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (depthStencilOps.clearDepth) {\\n\\t\\t\\t\\t\\t\\t\\t\\tclearFlags |= CLEARFLAG_DEPTH;\\n\\t\\t\\t\\t\\t\\t\\t\\tclearOptions.depth = depthStencilOps.clearDepthValue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (depthStencilOps.clearStencil) {\\n\\t\\t\\t\\t\\t\\t\\t\\tclearFlags |= CLEARFLAG_STENCIL;\\n\\t\\t\\t\\t\\t\\t\\t\\tclearOptions.stencil = depthStencilOps.clearStencilValue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tclearOptions.flags = clearFlags;\\n\\t\\t\\t\\t\\t\\tthis.clear(clearOptions);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.insideRenderPass = true;\\n\\t\\t}\\n\\t\\tendRenderPass(renderPass) {\\n\\t\\t\\t\\tthis.unbindVertexArray();\\n\\t\\t\\t\\tconst target = this.renderTarget;\\n\\t\\t\\t\\tconst colorBufferCount = renderPass.colorArrayOps.length;\\n\\t\\t\\t\\tif (target) {\\n\\t\\t\\t\\t\\t\\tinvalidateAttachments.length = 0;\\n\\t\\t\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < colorBufferCount; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst colorOps = renderPass.colorArrayOps[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!(colorOps.store || colorOps.resolve)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinvalidateAttachments.push(gl.COLOR_ATTACHMENT0 + i);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (target !== this.backBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!renderPass.depthStencilOps.storeDepth) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinvalidateAttachments.push(gl.DEPTH_ATTACHMENT);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!renderPass.depthStencilOps.storeStencil) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinvalidateAttachments.push(gl.STENCIL_ATTACHMENT);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (invalidateAttachments.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (renderPass.fullSizeClearRect) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.invalidateFramebuffer(gl.DRAW_FRAMEBUFFER, invalidateAttachments);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (colorBufferCount && renderPass.colorOps?.resolve) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (renderPass.samples > 1 && target.autoResolve) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttarget.resolve(true, false);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (target.depthBuffer && renderPass.depthStencilOps.resolveDepth) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (renderPass.samples > 1 && target.autoResolve) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttarget.resolve(false, true);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < colorBufferCount; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst colorOps = renderPass.colorArrayOps[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (colorOps.genMipmaps) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst colorBuffer = target._colorBuffers[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (colorBuffer && colorBuffer.impl._glTexture && colorBuffer.mipmaps) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.activeTexture(this.maxCombinedTextures - 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.bindTexture(colorBuffer);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.gl.generateMipmap(colorBuffer.impl._glTarget);\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.insideRenderPass = false;\\n\\t\\t}\\n\\t\\tset defaultFramebuffer(value) {\\n\\t\\t\\t\\tif (this._defaultFramebuffer !== value) {\\n\\t\\t\\t\\t\\t\\tthis._defaultFramebuffer = value;\\n\\t\\t\\t\\t\\t\\tthis._defaultFramebufferChanged = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget defaultFramebuffer() {\\n\\t\\t\\t\\treturn this._defaultFramebuffer;\\n\\t\\t}\\n\\t\\tupdateBegin() {\\n\\t\\t\\t\\tthis.boundVao = null;\\n\\t\\t\\t\\tif (this._tempEnableSafariTextureUnitWorkaround) {\\n\\t\\t\\t\\t\\t\\tfor(let unit = 0; unit < this.textureUnits.length; ++unit){\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let slot = 0; slot < 3; ++slot){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.textureUnits[unit][slot] = null;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst target = this.renderTarget ?? this.backBuffer;\\n\\t\\t\\t\\tconst targetImpl = target.impl;\\n\\t\\t\\t\\tif (!targetImpl.initialized) {\\n\\t\\t\\t\\t\\t\\tthis.initRenderTarget(target);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.setFramebuffer(targetImpl._glFrameBuffer);\\n\\t\\t}\\n\\t\\tupdateEnd() {\\n\\t\\t\\t\\tthis.unbindVertexArray();\\n\\t\\t\\t\\tconst target = this.renderTarget;\\n\\t\\t\\t\\tif (target && target !== this.backBuffer) {\\n\\t\\t\\t\\t\\t\\tif (target._samples > 1 && target.autoResolve) {\\n\\t\\t\\t\\t\\t\\t\\t\\ttarget.resolve();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst colorBuffer = target._colorBuffer;\\n\\t\\t\\t\\t\\t\\tif (colorBuffer && colorBuffer.impl._glTexture && colorBuffer.mipmaps) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.activeTexture(this.maxCombinedTextures - 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.bindTexture(colorBuffer);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gl.generateMipmap(colorBuffer.impl._glTarget);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetUnpackFlipY(flipY) {\\n\\t\\t\\t\\tif (this.unpackFlipY !== flipY) {\\n\\t\\t\\t\\t\\t\\tthis.unpackFlipY = flipY;\\n\\t\\t\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\t\\t\\tgl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetUnpackPremultiplyAlpha(premultiplyAlpha) {\\n\\t\\t\\t\\tif (this.unpackPremultiplyAlpha !== premultiplyAlpha) {\\n\\t\\t\\t\\t\\t\\tthis.unpackPremultiplyAlpha = premultiplyAlpha;\\n\\t\\t\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\t\\t\\tgl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetUnpackAlignment(alignment) {\\n\\t\\t\\t\\tif (this.unpackAlignment !== alignment) {\\n\\t\\t\\t\\t\\t\\tthis.unpackAlignment = alignment;\\n\\t\\t\\t\\t\\t\\tthis.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT, alignment);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tactiveTexture(textureUnit) {\\n\\t\\t\\t\\tif (this.textureUnit !== textureUnit) {\\n\\t\\t\\t\\t\\t\\tthis.gl.activeTexture(this.gl.TEXTURE0 + textureUnit);\\n\\t\\t\\t\\t\\t\\tthis.textureUnit = textureUnit;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tbindTexture(texture) {\\n\\t\\t\\t\\tconst impl = texture.impl;\\n\\t\\t\\t\\tconst textureTarget = impl._glTarget;\\n\\t\\t\\t\\tconst textureObject = impl._glTexture;\\n\\t\\t\\t\\tconst textureUnit = this.textureUnit;\\n\\t\\t\\t\\tconst slot = this.targetToSlot[textureTarget];\\n\\t\\t\\t\\tif (this.textureUnits[textureUnit][slot] !== textureObject) {\\n\\t\\t\\t\\t\\t\\tthis.gl.bindTexture(textureTarget, textureObject);\\n\\t\\t\\t\\t\\t\\tthis.textureUnits[textureUnit][slot] = textureObject;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tbindTextureOnUnit(texture, textureUnit) {\\n\\t\\t\\t\\tconst impl = texture.impl;\\n\\t\\t\\t\\tconst textureTarget = impl._glTarget;\\n\\t\\t\\t\\tconst textureObject = impl._glTexture;\\n\\t\\t\\t\\tconst slot = this.targetToSlot[textureTarget];\\n\\t\\t\\t\\tif (this.textureUnits[textureUnit][slot] !== textureObject) {\\n\\t\\t\\t\\t\\t\\tthis.activeTexture(textureUnit);\\n\\t\\t\\t\\t\\t\\tthis.gl.bindTexture(textureTarget, textureObject);\\n\\t\\t\\t\\t\\t\\tthis.textureUnits[textureUnit][slot] = textureObject;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetTextureParameters(texture) {\\n\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\tconst flags = texture.impl.dirtyParameterFlags;\\n\\t\\t\\t\\tconst target = texture.impl._glTarget;\\n\\t\\t\\t\\tif (flags & TEXPROPERTY_MIN_FILTER) {\\n\\t\\t\\t\\t\\t\\tlet filter = texture._minFilter;\\n\\t\\t\\t\\t\\t\\tif (!texture._mipmaps || texture._compressed && texture._levels.length === 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (filter === FILTER_NEAREST_MIPMAP_NEAREST || filter === FILTER_NEAREST_MIPMAP_LINEAR) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfilter = FILTER_NEAREST;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else if (filter === FILTER_LINEAR_MIPMAP_NEAREST || filter === FILTER_LINEAR_MIPMAP_LINEAR) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfilter = FILTER_LINEAR;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tgl.texParameteri(target, gl.TEXTURE_MIN_FILTER, this.glFilter[filter]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (flags & TEXPROPERTY_MAG_FILTER) {\\n\\t\\t\\t\\t\\t\\tgl.texParameteri(target, gl.TEXTURE_MAG_FILTER, this.glFilter[texture._magFilter]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (flags & TEXPROPERTY_ADDRESS_U) {\\n\\t\\t\\t\\t\\t\\tgl.texParameteri(target, gl.TEXTURE_WRAP_S, this.glAddress[texture._addressU]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (flags & TEXPROPERTY_ADDRESS_V) {\\n\\t\\t\\t\\t\\t\\tgl.texParameteri(target, gl.TEXTURE_WRAP_T, this.glAddress[texture._addressV]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (flags & TEXPROPERTY_ADDRESS_W) {\\n\\t\\t\\t\\t\\t\\tgl.texParameteri(target, gl.TEXTURE_WRAP_R, this.glAddress[texture._addressW]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (flags & TEXPROPERTY_COMPARE_ON_READ) {\\n\\t\\t\\t\\t\\t\\tgl.texParameteri(target, gl.TEXTURE_COMPARE_MODE, texture._compareOnRead ? gl.COMPARE_REF_TO_TEXTURE : gl.NONE);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (flags & TEXPROPERTY_COMPARE_FUNC) {\\n\\t\\t\\t\\t\\t\\tgl.texParameteri(target, gl.TEXTURE_COMPARE_FUNC, this.glComparison[texture._compareFunc]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (flags & TEXPROPERTY_ANISOTROPY) {\\n\\t\\t\\t\\t\\t\\tconst ext = this.extTextureFilterAnisotropic;\\n\\t\\t\\t\\t\\t\\tif (ext) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.texParameterf(target, ext.TEXTURE_MAX_ANISOTROPY_EXT, math.clamp(Math.round(texture._anisotropy), 1, this.maxAnisotropy));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetTexture(texture, textureUnit) {\\n\\t\\t\\t\\tconst impl = texture.impl;\\n\\t\\t\\t\\tif (!impl._glTexture) {\\n\\t\\t\\t\\t\\t\\timpl.initialize(this, texture);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (impl.dirtyParameterFlags > 0 || texture._needsUpload || texture._needsMipmapsUpload) {\\n\\t\\t\\t\\t\\t\\tthis.activeTexture(textureUnit);\\n\\t\\t\\t\\t\\t\\tthis.bindTexture(texture);\\n\\t\\t\\t\\t\\t\\tif (impl.dirtyParameterFlags) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setTextureParameters(texture);\\n\\t\\t\\t\\t\\t\\t\\t\\timpl.dirtyParameterFlags = 0;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (texture._needsUpload || texture._needsMipmapsUpload) {\\n\\t\\t\\t\\t\\t\\t\\t\\timpl.upload(this, texture);\\n\\t\\t\\t\\t\\t\\t\\t\\ttexture._needsUpload = false;\\n\\t\\t\\t\\t\\t\\t\\t\\ttexture._needsMipmapsUpload = false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.bindTextureOnUnit(texture, textureUnit);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcreateVertexArray(vertexBuffers) {\\n\\t\\t\\t\\tlet key, vao;\\n\\t\\t\\t\\tconst useCache = vertexBuffers.length > 1;\\n\\t\\t\\t\\tif (useCache) {\\n\\t\\t\\t\\t\\t\\tkey = '';\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < vertexBuffers.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst vertexBuffer = vertexBuffers[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tkey += vertexBuffer.id + vertexBuffer.format.renderingHash;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tvao = this._vaoMap.get(key);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!vao) {\\n\\t\\t\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\t\\t\\tvao = gl.createVertexArray();\\n\\t\\t\\t\\t\\t\\tgl.bindVertexArray(vao);\\n\\t\\t\\t\\t\\t\\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < vertexBuffers.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst vertexBuffer = vertexBuffers[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer.impl.bufferId);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst elements = vertexBuffer.format.elements;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < elements.length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst e = elements[j];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst loc = semanticToLocation[e.name];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (e.asInt) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.vertexAttribIPointer(loc, e.numComponents, this.glType[e.dataType], e.stride, e.offset);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.enableVertexAttribArray(loc);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (vertexBuffer.format.instancing) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.vertexAttribDivisor(loc, 1);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tgl.bindVertexArray(null);\\n\\t\\t\\t\\t\\t\\tgl.bindBuffer(gl.ARRAY_BUFFER, null);\\n\\t\\t\\t\\t\\t\\tif (useCache) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._vaoMap.set(key, vao);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn vao;\\n\\t\\t}\\n\\t\\tunbindVertexArray() {\\n\\t\\t\\t\\tif (this.boundVao) {\\n\\t\\t\\t\\t\\t\\tthis.boundVao = null;\\n\\t\\t\\t\\t\\t\\tthis.gl.bindVertexArray(null);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetBuffers(indexBuffer) {\\n\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\tlet vao;\\n\\t\\t\\t\\tif (this.vertexBuffers.length === 1) {\\n\\t\\t\\t\\t\\t\\tconst vertexBuffer = this.vertexBuffers[0];\\n\\t\\t\\t\\t\\t\\tif (!vertexBuffer.impl.vao) {\\n\\t\\t\\t\\t\\t\\t\\t\\tvertexBuffer.impl.vao = this.createVertexArray(this.vertexBuffers);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tvao = vertexBuffer.impl.vao;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tvao = this.createVertexArray(this.vertexBuffers);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.boundVao !== vao) {\\n\\t\\t\\t\\t\\t\\tthis.boundVao = vao;\\n\\t\\t\\t\\t\\t\\tgl.bindVertexArray(vao);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst bufferId = indexBuffer ? indexBuffer.impl.bufferId : null;\\n\\t\\t\\t\\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufferId);\\n\\t\\t}\\n\\t\\t_multiDrawLoopFallback(mode, primitive, indexBuffer, numInstances, drawCommands) {\\n\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\tif (primitive.indexed) {\\n\\t\\t\\t\\t\\t\\tconst format = indexBuffer.impl.glFormat;\\n\\t\\t\\t\\t\\t\\tconst { glCounts, glOffsetsBytes, glInstanceCounts, count } = drawCommands.impl;\\n\\t\\t\\t\\t\\t\\tif (numInstances > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.drawElementsInstanced(mode, glCounts[i], format, glOffsetsBytes[i], glInstanceCounts[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.drawElements(mode, glCounts[i], format, glOffsetsBytes[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst { glCounts, glOffsetsBytes, glInstanceCounts, count } = drawCommands.impl;\\n\\t\\t\\t\\t\\t\\tif (numInstances > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.drawArraysInstanced(mode, glOffsetsBytes[i], glCounts[i], glInstanceCounts[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.drawArrays(mode, glOffsetsBytes[i], glCounts[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdraw(primitive, indexBuffer, numInstances, drawCommands, first = true, last = true) {\\n\\t\\t\\t\\tconst shader = this.shader;\\n\\t\\t\\t\\tif (shader) {\\n\\t\\t\\t\\t\\t\\tthis.activateShader();\\n\\t\\t\\t\\t\\t\\tif (this.shaderValid) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (first) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.setBuffers(indexBuffer);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tlet textureUnit = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst samplers = shader.impl.samplers;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0, len = samplers.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst sampler = samplers[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet samplerValue = sampler.scopeId.value;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!samplerValue) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst samplerName = sampler.scopeId.name;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (samplerName === 'uSceneDepthMap') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsamplerValue = getBuiltInTexture(this, 'white');\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (samplerName === 'uSceneColorMap') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsamplerValue = getBuiltInTexture(this, 'pink');\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!samplerValue) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsamplerValue = getBuiltInTexture(this, 'pink');\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (samplerValue instanceof Texture) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst texture = samplerValue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.setTexture(texture, textureUnit);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (sampler.slot !== textureUnit) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.uniform1i(sampler.locationId, textureUnit);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsampler.slot = textureUnit;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttextureUnit++;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsampler.array.length = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst numTextures = samplerValue.length;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < numTextures; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst texture = samplerValue[j];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.setTexture(texture, textureUnit);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsampler.array[j] = textureUnit;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttextureUnit++;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.uniform1iv(sampler.locationId, sampler.array);\\n\\t\\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 uniforms = shader.impl.uniforms;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0, len = uniforms.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst uniform = uniforms[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst scopeId = uniform.scopeId;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst uniformVersion = uniform.version;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst programVersion = scopeId.versionObject.version;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (uniformVersion.globalId !== programVersion.globalId || uniformVersion.revision !== programVersion.revision) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuniformVersion.globalId = programVersion.globalId;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuniformVersion.revision = programVersion.revision;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst value = scopeId.value;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (value !== null && value !== undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.commitFunction[uniform.dataType](uniform, value);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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\\tif (this.transformFeedbackBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, this.transformFeedbackBuffer.impl.bufferId);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.beginTransformFeedback(gl.POINTS);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst mode = this.glPrimitive[primitive.type];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst count = primitive.count;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (drawCommands) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this.extMultiDraw) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst impl = drawCommands.impl;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (primitive.indexed) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst format = indexBuffer.impl.glFormat;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (numInstances > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (numInstances > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._multiDrawLoopFallback(mode, primitive, indexBuffer, numInstances, drawCommands);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (primitive.indexed) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst format = indexBuffer.impl.glFormat;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst offset = primitive.base * indexBuffer.bytesPerIndex;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (numInstances > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.drawElementsInstanced(mode, count, format, offset, numInstances);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.drawElements(mode, count, format, offset);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst first = primitive.base;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (numInstances > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.drawArraysInstanced(mode, first, count, numInstances);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.drawArrays(mode, first, count);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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\\tif (this.transformFeedbackBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.endTransformFeedback();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._drawCallsPerFrame++;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (last) {\\n\\t\\t\\t\\t\\t\\tthis.clearVertexBuffer();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tclear(options) {\\n\\t\\t\\t\\tconst defaultOptions = this.defaultClearOptions;\\n\\t\\t\\t\\toptions = options || defaultOptions;\\n\\t\\t\\t\\tconst flags = options.flags ?? defaultOptions.flags;\\n\\t\\t\\t\\tif (flags !== 0) {\\n\\t\\t\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\t\\t\\tif (flags & CLEARFLAG_COLOR) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst color = options.color ?? defaultOptions.color;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst r = color[0];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst g = color[1];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst b = color[2];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst a = color[3];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst c = this.clearColor;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (r !== c.r || g !== c.g || b !== c.b || a !== c.a) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.gl.clearColor(r, g, b, a);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.clearColor.set(r, g, b, a);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setBlendState(BlendState.NOBLEND);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (flags & CLEARFLAG_DEPTH) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst depth = options.depth ?? defaultOptions.depth;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (depth !== this.clearDepth) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.gl.clearDepth(depth);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.clearDepth = depth;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setDepthState(DepthState.WRITEDEPTH);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (flags & CLEARFLAG_STENCIL) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst stencil = options.stencil ?? defaultOptions.stencil;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (stencil !== this.clearStencil) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.gl.clearStencil(stencil);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.clearStencil = stencil;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.stencilMask(0xFF);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.stencilWriteMaskFront = 0xFF;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.stencilWriteMaskBack = 0xFF;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tgl.clear(this.glClearFlag[flags]);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsubmit() {\\n\\t\\t\\t\\tthis.gl.flush();\\n\\t\\t}\\n\\t\\treadPixels(x, y, w, h, pixels) {\\n\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\tgl.readPixels(x, y, w, h, gl.RGBA, gl.UNSIGNED_BYTE, pixels);\\n\\t\\t}\\n\\t\\tclientWaitAsync(flags, interval_ms) {\\n\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\tconst sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);\\n\\t\\t\\t\\tthis.submit();\\n\\t\\t\\t\\treturn new Promise((resolve, reject)=>{\\n\\t\\t\\t\\t\\t\\tfunction test() {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst res = gl.clientWaitSync(sync, flags, 0);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (res === gl.TIMEOUT_EXPIRED) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsetTimeout(test, interval_ms);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.deleteSync(sync);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (res === gl.WAIT_FAILED) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treject(new Error('webgl clientWaitSync sync failed'));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresolve();\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\ttest();\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tasync readPixelsAsync(x, y, w, h, pixels, forceRgba = false) {\\n\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\tlet format, pixelType;\\n\\t\\t\\t\\tif (forceRgba) {\\n\\t\\t\\t\\t\\t\\tformat = gl.RGBA;\\n\\t\\t\\t\\t\\t\\tpixelType = gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst impl = this.renderTarget.colorBuffer?.impl;\\n\\t\\t\\t\\t\\t\\tformat = impl?._glFormat ?? gl.RGBA;\\n\\t\\t\\t\\t\\t\\tpixelType = impl?._glPixelType ?? gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst buf = gl.createBuffer();\\n\\t\\t\\t\\tgl.bindBuffer(gl.PIXEL_PACK_BUFFER, buf);\\n\\t\\t\\t\\tgl.bufferData(gl.PIXEL_PACK_BUFFER, pixels.byteLength, gl.STREAM_READ);\\n\\t\\t\\t\\tgl.readPixels(x, y, w, h, format, pixelType, 0);\\n\\t\\t\\t\\tgl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);\\n\\t\\t\\t\\tawait this.clientWaitAsync(0, 16);\\n\\t\\t\\t\\tgl.bindBuffer(gl.PIXEL_PACK_BUFFER, buf);\\n\\t\\t\\t\\tgl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, pixels);\\n\\t\\t\\t\\tgl.bindBuffer(gl.PIXEL_PACK_BUFFER, null);\\n\\t\\t\\t\\tgl.deleteBuffer(buf);\\n\\t\\t\\t\\treturn pixels;\\n\\t\\t}\\n\\t\\treadTextureAsync(texture, x, y, width, height, options) {\\n\\t\\t\\t\\tconst face = options.face ?? 0;\\n\\t\\t\\t\\tconst mipLevel = options.mipLevel ?? 0;\\n\\t\\t\\t\\tconst renderTarget = options.renderTarget ?? new RenderTarget({\\n\\t\\t\\t\\t\\t\\tcolorBuffer: texture,\\n\\t\\t\\t\\t\\t\\tdepth: false,\\n\\t\\t\\t\\t\\t\\tface: face,\\n\\t\\t\\t\\t\\t\\tmipLevel: mipLevel\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst rgbaChannels = getPixelFormatChannelsForRgbaReadback(texture._format);\\n\\t\\t\\t\\tconst needsRgbaReadback = rgbaChannels > 0;\\n\\t\\t\\t\\tconst ArrayType = getPixelFormatArrayType(texture._format);\\n\\t\\t\\t\\tconst outputData = options.data ?? new ArrayType(TextureUtils.calcLevelGpuSize(width, height, 1, texture._format) / ArrayType.BYTES_PER_ELEMENT);\\n\\t\\t\\t\\tconst readBuffer = needsRgbaReadback ? new Uint8Array(width * height * 4) : outputData;\\n\\t\\t\\t\\tthis.setRenderTarget(renderTarget);\\n\\t\\t\\t\\tthis.initRenderTarget(renderTarget);\\n\\t\\t\\t\\tthis.setFramebuffer(renderTarget.impl._glFrameBuffer);\\n\\t\\t\\t\\tif (options.immediate) {\\n\\t\\t\\t\\t\\t\\tthis.gl.flush();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn new Promise((resolve, reject)=>{\\n\\t\\t\\t\\t\\t\\tconst readPromise = this.readPixelsAsync(x, y, width, height, readBuffer, needsRgbaReadback);\\n\\t\\t\\t\\t\\t\\treadPromise.then((data)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._destroyed) return;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!options.renderTarget) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trenderTarget.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (needsRgbaReadback) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst pixelCount = width * height;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < pixelCount; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let c = 0; c < rgbaChannels; c++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toutputData[i * rgbaChannels + c] = data[i * 4 + c];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresolve(outputData);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresolve(data);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}).catch(reject);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tasync writeTextureAsync(texture, x, y, width, height, data) {\\n\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\tconst impl = texture.impl;\\n\\t\\t\\t\\tconst format = impl?._glFormat ?? gl.RGBA;\\n\\t\\t\\t\\tconst pixelType = impl?._glPixelType ?? gl.UNSIGNED_BYTE;\\n\\t\\t\\t\\tconst buf = gl.createBuffer();\\n\\t\\t\\t\\tgl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buf);\\n\\t\\t\\t\\tgl.bufferData(gl.PIXEL_UNPACK_BUFFER, data, gl.STREAM_DRAW);\\n\\t\\t\\t\\tgl.bindTexture(gl.TEXTURE_2D, impl._glTexture);\\n\\t\\t\\t\\tgl.texSubImage2D(gl.TEXTURE_2D, 0, x, y, width, height, format, pixelType, 0);\\n\\t\\t\\t\\tgl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);\\n\\t\\t\\t\\ttexture._needsUpload = false;\\n\\t\\t\\t\\ttexture._mipmapsUploaded = false;\\n\\t\\t\\t\\tawait this.clientWaitAsync(0, 16);\\n\\t\\t}\\n\\t\\tsetAlphaToCoverage(state) {\\n\\t\\t\\t\\tif (this.alphaToCoverage !== state) {\\n\\t\\t\\t\\t\\t\\tthis.alphaToCoverage = state;\\n\\t\\t\\t\\t\\t\\tif (state) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gl.enable(this.gl.SAMPLE_ALPHA_TO_COVERAGE);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gl.disable(this.gl.SAMPLE_ALPHA_TO_COVERAGE);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetTransformFeedbackBuffer(tf) {\\n\\t\\t\\t\\tif (this.transformFeedbackBuffer !== tf) {\\n\\t\\t\\t\\t\\t\\tthis.transformFeedbackBuffer = tf;\\n\\t\\t\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\t\\t\\tif (tf) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this.feedback) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.feedback = gl.createTransformFeedback();\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, this.feedback);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetRaster(on) {\\n\\t\\t\\t\\tif (this.raster !== on) {\\n\\t\\t\\t\\t\\t\\tthis.raster = on;\\n\\t\\t\\t\\t\\t\\tif (on) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gl.disable(this.gl.RASTERIZER_DISCARD);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gl.enable(this.gl.RASTERIZER_DISCARD);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetStencilTest(enable) {\\n\\t\\t\\t\\tif (this.stencil !== enable) {\\n\\t\\t\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\t\\t\\tif (enable) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.enable(gl.STENCIL_TEST);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.disable(gl.STENCIL_TEST);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.stencil = enable;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetStencilFunc(func, ref, mask) {\\n\\t\\t\\t\\tif (this.stencilFuncFront !== func || this.stencilRefFront !== ref || this.stencilMaskFront !== mask || this.stencilFuncBack !== func || this.stencilRefBack !== ref || this.stencilMaskBack !== mask) {\\n\\t\\t\\t\\t\\t\\tthis.gl.stencilFunc(this.glComparison[func], ref, mask);\\n\\t\\t\\t\\t\\t\\tthis.stencilFuncFront = this.stencilFuncBack = func;\\n\\t\\t\\t\\t\\t\\tthis.stencilRefFront = this.stencilRefBack = ref;\\n\\t\\t\\t\\t\\t\\tthis.stencilMaskFront = this.stencilMaskBack = mask;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetStencilFuncFront(func, ref, mask) {\\n\\t\\t\\t\\tif (this.stencilFuncFront !== func || this.stencilRefFront !== ref || this.stencilMaskFront !== mask) {\\n\\t\\t\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\t\\t\\tgl.stencilFuncSeparate(gl.FRONT, this.glComparison[func], ref, mask);\\n\\t\\t\\t\\t\\t\\tthis.stencilFuncFront = func;\\n\\t\\t\\t\\t\\t\\tthis.stencilRefFront = ref;\\n\\t\\t\\t\\t\\t\\tthis.stencilMaskFront = mask;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetStencilFuncBack(func, ref, mask) {\\n\\t\\t\\t\\tif (this.stencilFuncBack !== func || this.stencilRefBack !== ref || this.stencilMaskBack !== mask) {\\n\\t\\t\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\t\\t\\tgl.stencilFuncSeparate(gl.BACK, this.glComparison[func], ref, mask);\\n\\t\\t\\t\\t\\t\\tthis.stencilFuncBack = func;\\n\\t\\t\\t\\t\\t\\tthis.stencilRefBack = ref;\\n\\t\\t\\t\\t\\t\\tthis.stencilMaskBack = mask;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetStencilOperation(fail, zfail, zpass, writeMask) {\\n\\t\\t\\t\\tif (this.stencilFailFront !== fail || this.stencilZfailFront !== zfail || this.stencilZpassFront !== zpass || this.stencilFailBack !== fail || this.stencilZfailBack !== zfail || this.stencilZpassBack !== zpass) {\\n\\t\\t\\t\\t\\t\\tthis.gl.stencilOp(this.glStencilOp[fail], this.glStencilOp[zfail], this.glStencilOp[zpass]);\\n\\t\\t\\t\\t\\t\\tthis.stencilFailFront = this.stencilFailBack = fail;\\n\\t\\t\\t\\t\\t\\tthis.stencilZfailFront = this.stencilZfailBack = zfail;\\n\\t\\t\\t\\t\\t\\tthis.stencilZpassFront = this.stencilZpassBack = zpass;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.stencilWriteMaskFront !== writeMask || this.stencilWriteMaskBack !== writeMask) {\\n\\t\\t\\t\\t\\t\\tthis.gl.stencilMask(writeMask);\\n\\t\\t\\t\\t\\t\\tthis.stencilWriteMaskFront = writeMask;\\n\\t\\t\\t\\t\\t\\tthis.stencilWriteMaskBack = writeMask;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetStencilOperationFront(fail, zfail, zpass, writeMask) {\\n\\t\\t\\t\\tif (this.stencilFailFront !== fail || this.stencilZfailFront !== zfail || this.stencilZpassFront !== zpass) {\\n\\t\\t\\t\\t\\t\\tthis.gl.stencilOpSeparate(this.gl.FRONT, this.glStencilOp[fail], this.glStencilOp[zfail], this.glStencilOp[zpass]);\\n\\t\\t\\t\\t\\t\\tthis.stencilFailFront = fail;\\n\\t\\t\\t\\t\\t\\tthis.stencilZfailFront = zfail;\\n\\t\\t\\t\\t\\t\\tthis.stencilZpassFront = zpass;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.stencilWriteMaskFront !== writeMask) {\\n\\t\\t\\t\\t\\t\\tthis.gl.stencilMaskSeparate(this.gl.FRONT, writeMask);\\n\\t\\t\\t\\t\\t\\tthis.stencilWriteMaskFront = writeMask;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetStencilOperationBack(fail, zfail, zpass, writeMask) {\\n\\t\\t\\t\\tif (this.stencilFailBack !== fail || this.stencilZfailBack !== zfail || this.stencilZpassBack !== zpass) {\\n\\t\\t\\t\\t\\t\\tthis.gl.stencilOpSeparate(this.gl.BACK, this.glStencilOp[fail], this.glStencilOp[zfail], this.glStencilOp[zpass]);\\n\\t\\t\\t\\t\\t\\tthis.stencilFailBack = fail;\\n\\t\\t\\t\\t\\t\\tthis.stencilZfailBack = zfail;\\n\\t\\t\\t\\t\\t\\tthis.stencilZpassBack = zpass;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.stencilWriteMaskBack !== writeMask) {\\n\\t\\t\\t\\t\\t\\tthis.gl.stencilMaskSeparate(this.gl.BACK, writeMask);\\n\\t\\t\\t\\t\\t\\tthis.stencilWriteMaskBack = writeMask;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetBlendState(blendState) {\\n\\t\\t\\t\\tconst currentBlendState = this.blendState;\\n\\t\\t\\t\\tif (!currentBlendState.equals(blendState)) {\\n\\t\\t\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\t\\t\\tconst { blend, colorOp, alphaOp, colorSrcFactor, colorDstFactor, alphaSrcFactor, alphaDstFactor } = blendState;\\n\\t\\t\\t\\t\\t\\tif (currentBlendState.blend !== blend) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (blend) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.enable(gl.BLEND);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.disable(gl.BLEND);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (currentBlendState.colorOp !== colorOp || currentBlendState.alphaOp !== alphaOp) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst glBlendEquation = this.glBlendEquation;\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.blendEquationSeparate(glBlendEquation[colorOp], glBlendEquation[alphaOp]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (currentBlendState.colorSrcFactor !== colorSrcFactor || currentBlendState.colorDstFactor !== colorDstFactor || currentBlendState.alphaSrcFactor !== alphaSrcFactor || currentBlendState.alphaDstFactor !== alphaDstFactor) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.blendFuncSeparate(this.glBlendFunctionColor[colorSrcFactor], this.glBlendFunctionColor[colorDstFactor], this.glBlendFunctionAlpha[alphaSrcFactor], this.glBlendFunctionAlpha[alphaDstFactor]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (currentBlendState.allWrite !== blendState.allWrite) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gl.colorMask(blendState.redWrite, blendState.greenWrite, blendState.blueWrite, blendState.alphaWrite);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcurrentBlendState.copy(blendState);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetBlendColor(r, g, b, a) {\\n\\t\\t\\t\\tconst c = this.blendColor;\\n\\t\\t\\t\\tif (r !== c.r || g !== c.g || b !== c.b || a !== c.a) {\\n\\t\\t\\t\\t\\t\\tthis.gl.blendColor(r, g, b, a);\\n\\t\\t\\t\\t\\t\\tc.set(r, g, b, a);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetStencilState(stencilFront, stencilBack) {\\n\\t\\t\\t\\tif (stencilFront || stencilBack) {\\n\\t\\t\\t\\t\\t\\tthis.setStencilTest(true);\\n\\t\\t\\t\\t\\t\\tif (stencilFront === stencilBack) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setStencilFunc(stencilFront.func, stencilFront.ref, stencilFront.readMask);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setStencilOperation(stencilFront.fail, stencilFront.zfail, stencilFront.zpass, stencilFront.writeMask);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tstencilFront ?? (stencilFront = StencilParameters.DEFAULT);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setStencilFuncFront(stencilFront.func, stencilFront.ref, stencilFront.readMask);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setStencilOperationFront(stencilFront.fail, stencilFront.zfail, stencilFront.zpass, stencilFront.writeMask);\\n\\t\\t\\t\\t\\t\\t\\t\\tstencilBack ?? (stencilBack = StencilParameters.DEFAULT);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setStencilFuncBack(stencilBack.func, stencilBack.ref, stencilBack.readMask);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setStencilOperationBack(stencilBack.fail, stencilBack.zfail, stencilBack.zpass, stencilBack.writeMask);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.setStencilTest(false);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetDepthState(depthState) {\\n\\t\\t\\t\\tconst currentDepthState = this.depthState;\\n\\t\\t\\t\\tif (!currentDepthState.equals(depthState)) {\\n\\t\\t\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\t\\t\\tconst write = depthState.write;\\n\\t\\t\\t\\t\\t\\tif (currentDepthState.write !== write) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.depthMask(write);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlet { func, test } = depthState;\\n\\t\\t\\t\\t\\t\\tif (!test && write) {\\n\\t\\t\\t\\t\\t\\t\\t\\ttest = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tfunc = FUNC_ALWAYS;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (currentDepthState.func !== func) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.depthFunc(this.glComparison[func]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (currentDepthState.test !== test) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (test) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.enable(gl.DEPTH_TEST);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgl.disable(gl.DEPTH_TEST);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst { depthBias, depthBiasSlope } = depthState;\\n\\t\\t\\t\\t\\t\\tif (depthBias || depthBiasSlope) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this.depthBiasEnabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.depthBiasEnabled = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.gl.enable(this.gl.POLYGON_OFFSET_FILL);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.polygonOffset(depthBiasSlope, depthBias);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.depthBiasEnabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.depthBiasEnabled = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.gl.disable(this.gl.POLYGON_OFFSET_FILL);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcurrentDepthState.copy(depthState);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetCullMode(cullMode) {\\n\\t\\t\\t\\tif (this.cullMode !== cullMode) {\\n\\t\\t\\t\\t\\t\\tif (cullMode === CULLFACE_NONE) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gl.disable(this.gl.CULL_FACE);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.cullMode === CULLFACE_NONE) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.gl.enable(this.gl.CULL_FACE);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst mode = this.glCull[cullMode];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.cullFace !== mode) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.gl.cullFace(mode);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.cullFace = mode;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.cullMode = cullMode;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetShader(shader, asyncCompile = false) {\\n\\t\\t\\t\\tif (shader !== this.shader) {\\n\\t\\t\\t\\t\\t\\tthis.shader = shader;\\n\\t\\t\\t\\t\\t\\tthis.shaderAsyncCompile = asyncCompile;\\n\\t\\t\\t\\t\\t\\tthis.shaderValid = undefined;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tactivateShader() {\\n\\t\\t\\t\\tconst { shader } = this;\\n\\t\\t\\t\\tconst { impl } = shader;\\n\\t\\t\\t\\tif (this.shaderValid === undefined) {\\n\\t\\t\\t\\t\\t\\tif (shader.failed) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.shaderValid = false;\\n\\t\\t\\t\\t\\t\\t} else if (!shader.ready) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.shaderAsyncCompile) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (impl.isLinked(this)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!impl.finalize(this, shader)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshader.failed = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.shaderValid = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.shaderValid = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!impl.finalize(this, shader)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshader.failed = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.shaderValid = false;\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.shaderValid === undefined) {\\n\\t\\t\\t\\t\\t\\tthis.gl.useProgram(impl.glProgram);\\n\\t\\t\\t\\t\\t\\tthis.shaderValid = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tclearVertexArrayObjectCache() {\\n\\t\\t\\t\\tconst gl = this.gl;\\n\\t\\t\\t\\tthis._vaoMap.forEach((item, key, mapObj)=>{\\n\\t\\t\\t\\t\\t\\tgl.deleteVertexArray(item);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis._vaoMap.clear();\\n\\t\\t}\\n\\t\\tset fullscreen(fullscreen) {\\n\\t\\t\\t\\tif (fullscreen) {\\n\\t\\t\\t\\t\\t\\tconst canvas = this.gl.canvas;\\n\\t\\t\\t\\t\\t\\tcanvas.requestFullscreen();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tdocument.exitFullscreen();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget fullscreen() {\\n\\t\\t\\t\\treturn !!document.fullscreenElement;\\n\\t\\t}\\n\\t\\tconstructor(canvas, options = {}){\\n\\t\\t\\t\\tsuper(canvas, options), this._defaultFramebuffer = null, this._defaultFramebufferChanged = false;\\n\\t\\t\\t\\toptions = this.initOptions;\\n\\t\\t\\t\\tthis.updateClientRect();\\n\\t\\t\\t\\tthis.initTextureUnits();\\n\\t\\t\\t\\tthis.contextLost = false;\\n\\t\\t\\t\\tthis._contextLostHandler = (event)=>{\\n\\t\\t\\t\\t\\t\\tevent.preventDefault();\\n\\t\\t\\t\\t\\t\\tthis.loseContext();\\n\\t\\t\\t\\t\\t\\tthis.fire('devicelost');\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis._contextRestoredHandler = ()=>{\\n\\t\\t\\t\\t\\t\\tthis.restoreContext();\\n\\t\\t\\t\\t\\t\\tthis.fire('devicerestored');\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst ua = typeof navigator !== 'undefined' && navigator.userAgent;\\n\\t\\t\\t\\tthis.forceDisableMultisampling = ua && ua.includes('AppleWebKit') && (ua.includes('15.4') || ua.includes('15_4'));\\n\\t\\t\\t\\tif (this.forceDisableMultisampling) {\\n\\t\\t\\t\\t\\t\\toptions.antialias = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (platform.browserName === 'firefox') {\\n\\t\\t\\t\\t\\t\\tconst ua = typeof navigator !== 'undefined' ? navigator.userAgent : '';\\n\\t\\t\\t\\t\\t\\tconst match = ua.match(/Firefox\\\\/(\\\\d+(\\\\.\\\\d+)*)/);\\n\\t\\t\\t\\t\\t\\tconst firefoxVersion = match ? match[1] : null;\\n\\t\\t\\t\\t\\t\\tif (firefoxVersion) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst version = parseFloat(firefoxVersion);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst disableAntialias = platform.name === 'windows' && (version >= 120 || version === 115) || platform.name === 'android' && version >= 132;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (disableAntialias) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions.antialias = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.backBufferAntialias = options.antialias ?? false;\\n\\t\\t\\t\\toptions.antialias = false;\\n\\t\\t\\t\\tconst gl = options.gl ?? canvas.getContext('webgl2', options);\\n\\t\\t\\t\\tif (!gl) {\\n\\t\\t\\t\\t\\t\\tthrow new Error('WebGL not supported');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.gl = gl;\\n\\t\\t\\t\\tthis.isWebGL2 = true;\\n\\t\\t\\t\\tthis._deviceType = DEVICETYPE_WEBGL2;\\n\\t\\t\\t\\tthis.updateBackbufferFormat(null);\\n\\t\\t\\t\\tconst isChrome = platform.browserName === 'chrome';\\n\\t\\t\\t\\tconst isSafari = platform.browserName === 'safari';\\n\\t\\t\\t\\tconst isMac = platform.browser && navigator.appVersion.indexOf('Mac') !== -1;\\n\\t\\t\\t\\tthis._tempEnableSafariTextureUnitWorkaround = isSafari;\\n\\t\\t\\t\\tthis._tempMacChromeBlitFramebufferWorkaround = isMac && isChrome && !options.alpha;\\n\\t\\t\\t\\tcanvas.addEventListener('webglcontextlost', this._contextLostHandler, false);\\n\\t\\t\\t\\tcanvas.addEventListener('webglcontextrestored', this._contextRestoredHandler, false);\\n\\t\\t\\t\\tthis.initializeExtensions();\\n\\t\\t\\t\\tthis.initializeCapabilities();\\n\\t\\t\\t\\tthis.initializeRenderState();\\n\\t\\t\\t\\tthis.initializeContextCaches();\\n\\t\\t\\t\\tthis.createBackbuffer(null);\\n\\t\\t\\t\\tthis.supportsImageBitmap = !isSafari && typeof ImageBitmap !== 'undefined';\\n\\t\\t\\t\\tthis._samplerTypes = new Set([\\n\\t\\t\\t\\t\\t\\tgl.SAMPLER_2D,\\n\\t\\t\\t\\t\\t\\tgl.SAMPLER_CUBE,\\n\\t\\t\\t\\t\\t\\tgl.UNSIGNED_INT_SAMPLER_2D,\\n\\t\\t\\t\\t\\t\\tgl.INT_SAMPLER_2D,\\n\\t\\t\\t\\t\\t\\tgl.SAMPLER_2D_SHADOW,\\n\\t\\t\\t\\t\\t\\tgl.SAMPLER_CUBE_SHADOW,\\n\\t\\t\\t\\t\\t\\tgl.SAMPLER_3D,\\n\\t\\t\\t\\t\\t\\tgl.INT_SAMPLER_3D,\\n\\t\\t\\t\\t\\t\\tgl.UNSIGNED_INT_SAMPLER_3D,\\n\\t\\t\\t\\t\\t\\tgl.SAMPLER_2D_ARRAY,\\n\\t\\t\\t\\t\\t\\tgl.INT_SAMPLER_2D_ARRAY,\\n\\t\\t\\t\\t\\t\\tgl.UNSIGNED_INT_SAMPLER_2D_ARRAY\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tthis.glAddress = [\\n\\t\\t\\t\\t\\t\\tgl.REPEAT,\\n\\t\\t\\t\\t\\t\\tgl.CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\tgl.MIRRORED_REPEAT\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.glBlendEquation = [\\n\\t\\t\\t\\t\\t\\tgl.FUNC_ADD,\\n\\t\\t\\t\\t\\t\\tgl.FUNC_SUBTRACT,\\n\\t\\t\\t\\t\\t\\tgl.FUNC_REVERSE_SUBTRACT,\\n\\t\\t\\t\\t\\t\\tgl.MIN,\\n\\t\\t\\t\\t\\t\\tgl.MAX\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.glBlendFunctionColor = [\\n\\t\\t\\t\\t\\t\\tgl.ZERO,\\n\\t\\t\\t\\t\\t\\tgl.ONE,\\n\\t\\t\\t\\t\\t\\tgl.SRC_COLOR,\\n\\t\\t\\t\\t\\t\\tgl.ONE_MINUS_SRC_COLOR,\\n\\t\\t\\t\\t\\t\\tgl.DST_COLOR,\\n\\t\\t\\t\\t\\t\\tgl.ONE_MINUS_DST_COLOR,\\n\\t\\t\\t\\t\\t\\tgl.SRC_ALPHA,\\n\\t\\t\\t\\t\\t\\tgl.SRC_ALPHA_SATURATE,\\n\\t\\t\\t\\t\\t\\tgl.ONE_MINUS_SRC_ALPHA,\\n\\t\\t\\t\\t\\t\\tgl.DST_ALPHA,\\n\\t\\t\\t\\t\\t\\tgl.ONE_MINUS_DST_ALPHA,\\n\\t\\t\\t\\t\\t\\tgl.CONSTANT_COLOR,\\n\\t\\t\\t\\t\\t\\tgl.ONE_MINUS_CONSTANT_COLOR\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.glBlendFunctionAlpha = [\\n\\t\\t\\t\\t\\t\\tgl.ZERO,\\n\\t\\t\\t\\t\\t\\tgl.ONE,\\n\\t\\t\\t\\t\\t\\tgl.SRC_COLOR,\\n\\t\\t\\t\\t\\t\\tgl.ONE_MINUS_SRC_COLOR,\\n\\t\\t\\t\\t\\t\\tgl.DST_COLOR,\\n\\t\\t\\t\\t\\t\\tgl.ONE_MINUS_DST_COLOR,\\n\\t\\t\\t\\t\\t\\tgl.SRC_ALPHA,\\n\\t\\t\\t\\t\\t\\tgl.SRC_ALPHA_SATURATE,\\n\\t\\t\\t\\t\\t\\tgl.ONE_MINUS_SRC_ALPHA,\\n\\t\\t\\t\\t\\t\\tgl.DST_ALPHA,\\n\\t\\t\\t\\t\\t\\tgl.ONE_MINUS_DST_ALPHA,\\n\\t\\t\\t\\t\\t\\tgl.CONSTANT_ALPHA,\\n\\t\\t\\t\\t\\t\\tgl.ONE_MINUS_CONSTANT_ALPHA\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.glComparison = [\\n\\t\\t\\t\\t\\t\\tgl.NEVER,\\n\\t\\t\\t\\t\\t\\tgl.LESS,\\n\\t\\t\\t\\t\\t\\tgl.EQUAL,\\n\\t\\t\\t\\t\\t\\tgl.LEQUAL,\\n\\t\\t\\t\\t\\t\\tgl.GREATER,\\n\\t\\t\\t\\t\\t\\tgl.NOTEQUAL,\\n\\t\\t\\t\\t\\t\\tgl.GEQUAL,\\n\\t\\t\\t\\t\\t\\tgl.ALWAYS\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.glStencilOp = [\\n\\t\\t\\t\\t\\t\\tgl.KEEP,\\n\\t\\t\\t\\t\\t\\tgl.ZERO,\\n\\t\\t\\t\\t\\t\\tgl.REPLACE,\\n\\t\\t\\t\\t\\t\\tgl.INCR,\\n\\t\\t\\t\\t\\t\\tgl.INCR_WRAP,\\n\\t\\t\\t\\t\\t\\tgl.DECR,\\n\\t\\t\\t\\t\\t\\tgl.DECR_WRAP,\\n\\t\\t\\t\\t\\t\\tgl.INVERT\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.glClearFlag = [\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\tgl.COLOR_BUFFER_BIT,\\n\\t\\t\\t\\t\\t\\tgl.DEPTH_BUFFER_BIT,\\n\\t\\t\\t\\t\\t\\tgl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT,\\n\\t\\t\\t\\t\\t\\tgl.STENCIL_BUFFER_BIT,\\n\\t\\t\\t\\t\\t\\tgl.STENCIL_BUFFER_BIT | gl.COLOR_BUFFER_BIT,\\n\\t\\t\\t\\t\\t\\tgl.STENCIL_BUFFER_BIT | gl.DEPTH_BUFFER_BIT,\\n\\t\\t\\t\\t\\t\\tgl.STENCIL_BUFFER_BIT | gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.glCull = [\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\tgl.BACK,\\n\\t\\t\\t\\t\\t\\tgl.FRONT,\\n\\t\\t\\t\\t\\t\\tgl.FRONT_AND_BACK\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.glFilter = [\\n\\t\\t\\t\\t\\t\\tgl.NEAREST,\\n\\t\\t\\t\\t\\t\\tgl.LINEAR,\\n\\t\\t\\t\\t\\t\\tgl.NEAREST_MIPMAP_NEAREST,\\n\\t\\t\\t\\t\\t\\tgl.NEAREST_MIPMAP_LINEAR,\\n\\t\\t\\t\\t\\t\\tgl.LINEAR_MIPMAP_NEAREST,\\n\\t\\t\\t\\t\\t\\tgl.LINEAR_MIPMAP_LINEAR\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.glPrimitive = [\\n\\t\\t\\t\\t\\t\\tgl.POINTS,\\n\\t\\t\\t\\t\\t\\tgl.LINES,\\n\\t\\t\\t\\t\\t\\tgl.LINE_LOOP,\\n\\t\\t\\t\\t\\t\\tgl.LINE_STRIP,\\n\\t\\t\\t\\t\\t\\tgl.TRIANGLES,\\n\\t\\t\\t\\t\\t\\tgl.TRIANGLE_STRIP,\\n\\t\\t\\t\\t\\t\\tgl.TRIANGLE_FAN\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.glType = [\\n\\t\\t\\t\\t\\t\\tgl.BYTE,\\n\\t\\t\\t\\t\\t\\tgl.UNSIGNED_BYTE,\\n\\t\\t\\t\\t\\t\\tgl.SHORT,\\n\\t\\t\\t\\t\\t\\tgl.UNSIGNED_SHORT,\\n\\t\\t\\t\\t\\t\\tgl.INT,\\n\\t\\t\\t\\t\\t\\tgl.UNSIGNED_INT,\\n\\t\\t\\t\\t\\t\\tgl.FLOAT,\\n\\t\\t\\t\\t\\t\\tgl.HALF_FLOAT\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.pcUniformType = {};\\n\\t\\t\\t\\tthis.pcUniformType[gl.BOOL] = UNIFORMTYPE_BOOL;\\n\\t\\t\\t\\tthis.pcUniformType[gl.INT] = UNIFORMTYPE_INT;\\n\\t\\t\\t\\tthis.pcUniformType[gl.FLOAT] = UNIFORMTYPE_FLOAT;\\n\\t\\t\\t\\tthis.pcUniformType[gl.FLOAT_VEC2] = UNIFORMTYPE_VEC2;\\n\\t\\t\\t\\tthis.pcUniformType[gl.FLOAT_VEC3] = UNIFORMTYPE_VEC3;\\n\\t\\t\\t\\tthis.pcUniformType[gl.FLOAT_VEC4] = UNIFORMTYPE_VEC4;\\n\\t\\t\\t\\tthis.pcUniformType[gl.INT_VEC2] = UNIFORMTYPE_IVEC2;\\n\\t\\t\\t\\tthis.pcUniformType[gl.INT_VEC3] = UNIFORMTYPE_IVEC3;\\n\\t\\t\\t\\tthis.pcUniformType[gl.INT_VEC4] = UNIFORMTYPE_IVEC4;\\n\\t\\t\\t\\tthis.pcUniformType[gl.BOOL_VEC2] = UNIFORMTYPE_BVEC2;\\n\\t\\t\\t\\tthis.pcUniformType[gl.BOOL_VEC3] = UNIFORMTYPE_BVEC3;\\n\\t\\t\\t\\tthis.pcUniformType[gl.BOOL_VEC4] = UNIFORMTYPE_BVEC4;\\n\\t\\t\\t\\tthis.pcUniformType[gl.FLOAT_MAT2] = UNIFORMTYPE_MAT2;\\n\\t\\t\\t\\tthis.pcUniformType[gl.FLOAT_MAT3] = UNIFORMTYPE_MAT3;\\n\\t\\t\\t\\tthis.pcUniformType[gl.FLOAT_MAT4] = UNIFORMTYPE_MAT4;\\n\\t\\t\\t\\tthis.pcUniformType[gl.SAMPLER_2D] = UNIFORMTYPE_TEXTURE2D;\\n\\t\\t\\t\\tthis.pcUniformType[gl.SAMPLER_CUBE] = UNIFORMTYPE_TEXTURECUBE;\\n\\t\\t\\t\\tthis.pcUniformType[gl.UNSIGNED_INT] = UNIFORMTYPE_UINT;\\n\\t\\t\\t\\tthis.pcUniformType[gl.UNSIGNED_INT_VEC2] = UNIFORMTYPE_UVEC2;\\n\\t\\t\\t\\tthis.pcUniformType[gl.UNSIGNED_INT_VEC3] = UNIFORMTYPE_UVEC3;\\n\\t\\t\\t\\tthis.pcUniformType[gl.UNSIGNED_INT_VEC4] = UNIFORMTYPE_UVEC4;\\n\\t\\t\\t\\tthis.pcUniformType[gl.SAMPLER_2D_SHADOW] = UNIFORMTYPE_TEXTURE2D_SHADOW;\\n\\t\\t\\t\\tthis.pcUniformType[gl.SAMPLER_CUBE_SHADOW] = UNIFORMTYPE_TEXTURECUBE_SHADOW;\\n\\t\\t\\t\\tthis.pcUniformType[gl.SAMPLER_2D_ARRAY] = UNIFORMTYPE_TEXTURE2D_ARRAY;\\n\\t\\t\\t\\tthis.pcUniformType[gl.SAMPLER_3D] = UNIFORMTYPE_TEXTURE3D;\\n\\t\\t\\t\\tthis.pcUniformType[gl.INT_SAMPLER_2D] = UNIFORMTYPE_ITEXTURE2D;\\n\\t\\t\\t\\tthis.pcUniformType[gl.UNSIGNED_INT_SAMPLER_2D] = UNIFORMTYPE_UTEXTURE2D;\\n\\t\\t\\t\\tthis.pcUniformType[gl.INT_SAMPLER_CUBE] = UNIFORMTYPE_ITEXTURECUBE;\\n\\t\\t\\t\\tthis.pcUniformType[gl.UNSIGNED_INT_SAMPLER_2D] = UNIFORMTYPE_UTEXTURECUBE;\\n\\t\\t\\t\\tthis.pcUniformType[gl.INT_SAMPLER_3D] = UNIFORMTYPE_ITEXTURE3D;\\n\\t\\t\\t\\tthis.pcUniformType[gl.UNSIGNED_INT_SAMPLER_3D] = UNIFORMTYPE_UTEXTURE3D;\\n\\t\\t\\t\\tthis.pcUniformType[gl.INT_SAMPLER_2D_ARRAY] = UNIFORMTYPE_ITEXTURE2D_ARRAY;\\n\\t\\t\\t\\tthis.pcUniformType[gl.UNSIGNED_INT_SAMPLER_2D_ARRAY] = UNIFORMTYPE_UTEXTURE2D_ARRAY;\\n\\t\\t\\t\\tthis.targetToSlot = {};\\n\\t\\t\\t\\tthis.targetToSlot[gl.TEXTURE_2D] = 0;\\n\\t\\t\\t\\tthis.targetToSlot[gl.TEXTURE_CUBE_MAP] = 1;\\n\\t\\t\\t\\tthis.targetToSlot[gl.TEXTURE_3D] = 2;\\n\\t\\t\\t\\tlet scopeX, scopeY, scopeZ, scopeW;\\n\\t\\t\\t\\tlet uniformValue;\\n\\t\\t\\t\\tthis.commitFunction = [];\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_BOOL] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tif (uniform.value !== value) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.uniform1i(uniform.locationId, value);\\n\\t\\t\\t\\t\\t\\t\\t\\tuniform.value = value;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_INT] = this.commitFunction[UNIFORMTYPE_BOOL];\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_FLOAT] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tif (uniform.value !== value) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.uniform1f(uniform.locationId, value);\\n\\t\\t\\t\\t\\t\\t\\t\\tuniform.value = value;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_VEC2] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\t\\t\\t\\tscopeX = value[0];\\n\\t\\t\\t\\t\\t\\tscopeY = value[1];\\n\\t\\t\\t\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.uniform2fv(uniform.locationId, value);\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_VEC3] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\t\\t\\t\\tscopeX = value[0];\\n\\t\\t\\t\\t\\t\\tscopeY = value[1];\\n\\t\\t\\t\\t\\t\\tscopeZ = value[2];\\n\\t\\t\\t\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY || uniformValue[2] !== scopeZ) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.uniform3fv(uniform.locationId, value);\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[2] = scopeZ;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_VEC4] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\t\\t\\t\\tscopeX = value[0];\\n\\t\\t\\t\\t\\t\\tscopeY = value[1];\\n\\t\\t\\t\\t\\t\\tscopeZ = value[2];\\n\\t\\t\\t\\t\\t\\tscopeW = value[3];\\n\\t\\t\\t\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY || uniformValue[2] !== scopeZ || uniformValue[3] !== scopeW) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.uniform4fv(uniform.locationId, value);\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[2] = scopeZ;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[3] = scopeW;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_IVEC2] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\t\\t\\t\\tscopeX = value[0];\\n\\t\\t\\t\\t\\t\\tscopeY = value[1];\\n\\t\\t\\t\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.uniform2iv(uniform.locationId, value);\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_BVEC2] = this.commitFunction[UNIFORMTYPE_IVEC2];\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_IVEC3] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\t\\t\\t\\tscopeX = value[0];\\n\\t\\t\\t\\t\\t\\tscopeY = value[1];\\n\\t\\t\\t\\t\\t\\tscopeZ = value[2];\\n\\t\\t\\t\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY || uniformValue[2] !== scopeZ) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.uniform3iv(uniform.locationId, value);\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[2] = scopeZ;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_BVEC3] = this.commitFunction[UNIFORMTYPE_IVEC3];\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_IVEC4] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\t\\t\\t\\tscopeX = value[0];\\n\\t\\t\\t\\t\\t\\tscopeY = value[1];\\n\\t\\t\\t\\t\\t\\tscopeZ = value[2];\\n\\t\\t\\t\\t\\t\\tscopeW = value[3];\\n\\t\\t\\t\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY || uniformValue[2] !== scopeZ || uniformValue[3] !== scopeW) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.uniform4iv(uniform.locationId, value);\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[2] = scopeZ;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[3] = scopeW;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_BVEC4] = this.commitFunction[UNIFORMTYPE_IVEC4];\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_MAT2] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tgl.uniformMatrix2fv(uniform.locationId, false, value);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_MAT3] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tgl.uniformMatrix3fv(uniform.locationId, false, value);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_MAT4] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tgl.uniformMatrix4fv(uniform.locationId, false, value);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_FLOATARRAY] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tgl.uniform1fv(uniform.locationId, value);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_VEC2ARRAY] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tgl.uniform2fv(uniform.locationId, value);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_VEC3ARRAY] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tgl.uniform3fv(uniform.locationId, value);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_VEC4ARRAY] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tgl.uniform4fv(uniform.locationId, value);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_UINT] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tif (uniform.value !== value) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.uniform1ui(uniform.locationId, value);\\n\\t\\t\\t\\t\\t\\t\\t\\tuniform.value = value;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_UVEC2] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\t\\t\\t\\tscopeX = value[0];\\n\\t\\t\\t\\t\\t\\tscopeY = value[1];\\n\\t\\t\\t\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.uniform2uiv(uniform.locationId, value);\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_UVEC3] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\t\\t\\t\\tscopeX = value[0];\\n\\t\\t\\t\\t\\t\\tscopeY = value[1];\\n\\t\\t\\t\\t\\t\\tscopeZ = value[2];\\n\\t\\t\\t\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY || uniformValue[2] !== scopeZ) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.uniform3uiv(uniform.locationId, value);\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[2] = scopeZ;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_UVEC4] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tuniformValue = uniform.value;\\n\\t\\t\\t\\t\\t\\tscopeX = value[0];\\n\\t\\t\\t\\t\\t\\tscopeY = value[1];\\n\\t\\t\\t\\t\\t\\tscopeZ = value[2];\\n\\t\\t\\t\\t\\t\\tscopeW = value[3];\\n\\t\\t\\t\\t\\t\\tif (uniformValue[0] !== scopeX || uniformValue[1] !== scopeY || uniformValue[2] !== scopeZ || uniformValue[3] !== scopeW) {\\n\\t\\t\\t\\t\\t\\t\\t\\tgl.uniform4uiv(uniform.locationId, value);\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[0] = scopeX;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[1] = scopeY;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[2] = scopeZ;\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformValue[3] = scopeW;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_INTARRAY] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tgl.uniform1iv(uniform.locationId, value);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_UINTARRAY] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tgl.uniform1uiv(uniform.locationId, value);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_BOOLARRAY] = this.commitFunction[UNIFORMTYPE_INTARRAY];\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_IVEC2ARRAY] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tgl.uniform2iv(uniform.locationId, value);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_UVEC2ARRAY] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tgl.uniform2uiv(uniform.locationId, value);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_BVEC2ARRAY] = this.commitFunction[UNIFORMTYPE_IVEC2ARRAY];\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_IVEC3ARRAY] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tgl.uniform3iv(uniform.locationId, value);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_UVEC3ARRAY] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tgl.uniform3uiv(uniform.locationId, value);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_BVEC3ARRAY] = this.commitFunction[UNIFORMTYPE_IVEC3ARRAY];\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_IVEC4ARRAY] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tgl.uniform4iv(uniform.locationId, value);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_UVEC4ARRAY] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tgl.uniform4uiv(uniform.locationId, value);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_BVEC4ARRAY] = this.commitFunction[UNIFORMTYPE_IVEC4ARRAY];\\n\\t\\t\\t\\tthis.commitFunction[UNIFORMTYPE_MAT4ARRAY] = function(uniform, value) {\\n\\t\\t\\t\\t\\t\\tgl.uniformMatrix4fv(uniform.locationId, false, value);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.constantTexSource = this.scope.resolve('source');\\n\\t\\t\\t\\tthis.postInit();\\n\\t\\t}\\n}\\n\\nclass NullIndexBuffer {\\n\\t\\tunlock(indexBuffer) {}\\n}\\n\\nclass NullRenderTarget {\\n\\t\\tdestroy(device) {}\\n\\t\\tinit(device, renderTarget) {}\\n\\t\\tloseContext() {}\\n\\t\\tresolve(device, target, color, depth) {}\\n}\\n\\nclass NullShader {\\n\\t\\tdestroy(shader) {}\\n\\t\\tloseContext() {}\\n\\t\\trestoreContext(device, shader) {}\\n}\\n\\nclass NullTexture {\\n\\t\\tdestroy(device) {}\\n\\t\\tpropertyChanged(flag) {}\\n\\t\\tloseContext() {}\\n}\\n\\nclass NullVertexBuffer {\\n\\t\\tdestroy(device) {}\\n\\t\\tunlock(vertexBuffer) {}\\n}\\n\\nclass NullDrawCommands {\\n\\t\\tadd(i, indexOrVertexCount, instanceCount, firstIndexOrVertex) {}\\n}\\n\\nclass NullGraphicsDevice extends GraphicsDevice {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tsuper.destroy();\\n\\t\\t}\\n\\t\\tinitDeviceCaps() {\\n\\t\\t\\t\\tthis.disableParticleSystem = true;\\n\\t\\t\\t\\tthis.precision = 'highp';\\n\\t\\t\\t\\tthis.maxPrecision = 'highp';\\n\\t\\t\\t\\tthis.maxSamples = 4;\\n\\t\\t\\t\\tthis.maxTextures = 16;\\n\\t\\t\\t\\tthis.maxTextureSize = 4096;\\n\\t\\t\\t\\tthis.maxCubeMapSize = 4096;\\n\\t\\t\\t\\tthis.maxVolumeSize = 4096;\\n\\t\\t\\t\\tthis.maxColorAttachments = 8;\\n\\t\\t\\t\\tthis.maxPixelRatio = 1;\\n\\t\\t\\t\\tthis.maxAnisotropy = 16;\\n\\t\\t\\t\\tthis.supportsUniformBuffers = false;\\n\\t\\t\\t\\tthis.supportsAreaLights = true;\\n\\t\\t\\t\\tthis.supportsGpuParticles = false;\\n\\t\\t\\t\\tthis.textureFloatRenderable = true;\\n\\t\\t\\t\\tthis.textureHalfFloatRenderable = true;\\n\\t\\t\\t\\tthis.supportsImageBitmap = false;\\n\\t\\t}\\n\\t\\tpostInit() {\\n\\t\\t\\t\\tsuper.postInit();\\n\\t\\t}\\n\\t\\tframeStart() {\\n\\t\\t\\t\\tsuper.frameStart();\\n\\t\\t}\\n\\t\\tframeEnd() {\\n\\t\\t\\t\\tsuper.frameEnd();\\n\\t\\t}\\n\\t\\tupdateBegin() {}\\n\\t\\tupdateEnd() {}\\n\\t\\treadPixels(x, y, w, h, pixels) {}\\n\\t\\tcreateVertexBufferImpl(vertexBuffer, format) {\\n\\t\\t\\t\\treturn new NullVertexBuffer(vertexBuffer, format);\\n\\t\\t}\\n\\t\\tcreateIndexBufferImpl(indexBuffer) {\\n\\t\\t\\t\\treturn new NullIndexBuffer(indexBuffer);\\n\\t\\t}\\n\\t\\tcreateShaderImpl(shader) {\\n\\t\\t\\t\\treturn new NullShader(shader);\\n\\t\\t}\\n\\t\\tcreateTextureImpl(texture) {\\n\\t\\t\\t\\treturn new NullTexture(texture);\\n\\t\\t}\\n\\t\\tcreateRenderTargetImpl(renderTarget) {\\n\\t\\t\\t\\treturn new NullRenderTarget(renderTarget);\\n\\t\\t}\\n\\t\\tcreateDrawCommandImpl(drawCommands) {\\n\\t\\t\\t\\treturn new NullDrawCommands();\\n\\t\\t}\\n\\t\\tcreateUploadStreamImpl(uploadStream) {\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tdraw(primitive, indexBuffer, numInstances, drawCommands, first = true, last = true) {}\\n\\t\\tsetShader(shader, asyncCompile = false) {}\\n\\t\\tsetBlendState(blendState) {}\\n\\t\\tsetDepthState(depthState) {}\\n\\t\\tsetStencilState(stencilFront, stencilBack) {}\\n\\t\\tsetBlendColor(r, g, b, a) {}\\n\\t\\tsetCullMode(cullMode) {}\\n\\t\\tsetAlphaToCoverage(state) {}\\n\\t\\tinitializeContextCaches() {\\n\\t\\t\\t\\tsuper.initializeContextCaches();\\n\\t\\t}\\n\\t\\tclear(options) {}\\n\\t\\tsetViewport(x, y, w, h) {}\\n\\t\\tsetScissor(x, y, w, h) {}\\n\\t\\tcopyRenderTarget(source, dest, color, depth) {\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tconstructor(canvas, options = {}){\\n\\t\\t\\t\\tsuper(canvas, options);\\n\\t\\t\\t\\toptions = this.initOptions;\\n\\t\\t\\t\\tthis.isNull = true;\\n\\t\\t\\t\\tthis._deviceType = DEVICETYPE_NULL;\\n\\t\\t\\t\\tthis.samples = 1;\\n\\t\\t\\t\\tthis.backBuffer = new RenderTarget({\\n\\t\\t\\t\\t\\t\\tname: 'Framebuffer',\\n\\t\\t\\t\\t\\t\\tgraphicsDevice: this,\\n\\t\\t\\t\\t\\t\\tdepth: this.initOptions.depth,\\n\\t\\t\\t\\t\\t\\tstencil: this.supportsStencil,\\n\\t\\t\\t\\t\\t\\tsamples: this.samples\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.initDeviceCaps();\\n\\t\\t}\\n}\\n\\nfunction createGraphicsDevice(canvas, options = {}) {\\n\\t\\tconst deviceTypes = options.deviceTypes ?? [];\\n\\t\\tif (!deviceTypes.includes(DEVICETYPE_WEBGL2)) {\\n\\t\\t\\t\\tdeviceTypes.push(DEVICETYPE_WEBGL2);\\n\\t\\t}\\n\\t\\tif (!deviceTypes.includes(DEVICETYPE_NULL)) {\\n\\t\\t\\t\\tdeviceTypes.push(DEVICETYPE_NULL);\\n\\t\\t}\\n\\t\\tif (platform.browser && !!navigator.xr) {\\n\\t\\t\\t\\tvar _options;\\n\\t\\t\\t\\t(_options = options).xrCompatible ?? (_options.xrCompatible = true);\\n\\t\\t}\\n\\t\\tconst deviceCreateFuncs = [];\\n\\t\\tfor(let i = 0; i < deviceTypes.length; i++){\\n\\t\\t\\t\\tconst deviceType = deviceTypes[i];\\n\\t\\t\\t\\tif (deviceType === DEVICETYPE_WEBGPU && window?.navigator?.gpu) {\\n\\t\\t\\t\\t\\t\\tdeviceCreateFuncs.push(()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst device = new WebgpuGraphicsDevice(canvas, options);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn device.initWebGpu(options.glslangUrl, options.twgslUrl);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (deviceType === DEVICETYPE_WEBGL2) {\\n\\t\\t\\t\\t\\t\\tdeviceCreateFuncs.push(()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\treturn new WebglGraphicsDevice(canvas, options);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (deviceType === DEVICETYPE_NULL) {\\n\\t\\t\\t\\t\\t\\tdeviceCreateFuncs.push(()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\treturn new NullGraphicsDevice(canvas, options);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn new Promise((resolve, reject)=>{\\n\\t\\t\\t\\tlet attempt = 0;\\n\\t\\t\\t\\tconst next = ()=>{\\n\\t\\t\\t\\t\\t\\tif (attempt >= deviceCreateFuncs.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\treject(new Error('Failed to create a graphics device'));\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tPromise.resolve(deviceCreateFuncs[attempt++]()).then((device)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (device) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresolve(device);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnext();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t}).catch((err)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconsole.log(err);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnext();\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tnext();\\n\\t\\t});\\n}\\n\\nclass ComputeParameter {\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.scopeId = null;\\n\\t\\t}\\n}\\nclass Compute {\\n\\t\\tsetParameter(name, value) {\\n\\t\\t\\t\\tlet param = this.parameters.get(name);\\n\\t\\t\\t\\tif (!param) {\\n\\t\\t\\t\\t\\t\\tparam = new ComputeParameter();\\n\\t\\t\\t\\t\\t\\tparam.scopeId = this.device.scope.resolve(name);\\n\\t\\t\\t\\t\\t\\tthis.parameters.set(name, param);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tparam.value = value;\\n\\t\\t}\\n\\t\\tgetParameter(name) {\\n\\t\\t\\t\\treturn this.parameters.get(name)?.value;\\n\\t\\t}\\n\\t\\tdeleteParameter(name) {\\n\\t\\t\\t\\tthis.parameters.delete(name);\\n\\t\\t}\\n\\t\\tapplyParameters() {\\n\\t\\t\\t\\tfor (const [, param] of this.parameters){\\n\\t\\t\\t\\t\\t\\tparam.scopeId.setValue(param.value);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetupDispatch(x, y, z) {\\n\\t\\t\\t\\tthis.countX = x;\\n\\t\\t\\t\\tthis.countY = y;\\n\\t\\t\\t\\tthis.countZ = z;\\n\\t\\t\\t\\tthis.indirectSlotIndex = -1;\\n\\t\\t\\t\\tthis.indirectBuffer = null;\\n\\t\\t}\\n\\t\\tsetupIndirectDispatch(slotIndex, buffer = null) {\\n\\t\\t\\t\\tthis.indirectSlotIndex = slotIndex;\\n\\t\\t\\t\\tthis.indirectBuffer = buffer;\\n\\t\\t\\t\\tthis.indirectFrameStamp = this.device.renderVersion;\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice, shader, name = 'Unnamed'){\\n\\t\\t\\t\\tthis.shader = null;\\n\\t\\t\\t\\tthis.parameters = new Map();\\n\\t\\t\\t\\tthis.countX = 1;\\n\\t\\t\\t\\tthis.indirectSlotIndex = -1;\\n\\t\\t\\t\\tthis.indirectBuffer = null;\\n\\t\\t\\t\\tthis.indirectFrameStamp = 0;\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t\\t\\tthis.shader = shader;\\n\\t\\t\\t\\tthis.name = name;\\n\\t\\t\\t\\tif (graphicsDevice.supportsCompute) {\\n\\t\\t\\t\\t\\t\\tthis.impl = graphicsDevice.createComputeImpl(this);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass DrawCommands {\\n\\t\\tget maxCount() {\\n\\t\\t\\t\\treturn this._maxCount;\\n\\t\\t}\\n\\t\\tget count() {\\n\\t\\t\\t\\treturn this._count;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.impl?.destroy?.();\\n\\t\\t\\t\\tthis.impl = null;\\n\\t\\t}\\n\\t\\tallocate(maxCount) {\\n\\t\\t\\t\\tthis._maxCount = maxCount;\\n\\t\\t\\t\\tthis.impl.allocate?.(maxCount);\\n\\t\\t}\\n\\t\\tadd(i, indexOrVertexCount, instanceCount, firstIndexOrVertex, baseVertex = 0, firstInstance = 0) {\\n\\t\\t\\t\\tthis.impl.add(i, indexOrVertexCount, instanceCount, firstIndexOrVertex, baseVertex, firstInstance);\\n\\t\\t}\\n\\t\\tupdate(count) {\\n\\t\\t\\t\\tthis._count = count;\\n\\t\\t\\t\\tthis.primitiveCount = this.impl.update?.(count) ?? 0;\\n\\t\\t}\\n\\t\\tconstructor(device, indexSizeBytes = 0){\\n\\t\\t\\t\\tthis._maxCount = 0;\\n\\t\\t\\t\\tthis.impl = null;\\n\\t\\t\\t\\tthis._count = 1;\\n\\t\\t\\t\\tthis.slotIndex = 0;\\n\\t\\t\\t\\tthis.primitiveCount = 0;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.indexSizeBytes = indexSizeBytes;\\n\\t\\t\\t\\tthis.impl = device.createDrawCommandImpl(this);\\n\\t\\t}\\n}\\n\\nlet id$5 = 0;\\nclass IndexBuffer {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tdevice.buffers.delete(this);\\n\\t\\t\\t\\tif (this.device.indexBuffer === this) {\\n\\t\\t\\t\\t\\t\\tthis.device.indexBuffer = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.impl.initialized) {\\n\\t\\t\\t\\t\\t\\tthis.impl.destroy(device);\\n\\t\\t\\t\\t\\t\\tthis.adjustVramSizeTracking(device._vram, -this.storage.byteLength);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tadjustVramSizeTracking(vram, size) {\\n\\t\\t\\t\\tvram.ib += size;\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tthis.impl.loseContext();\\n\\t\\t}\\n\\t\\tgetFormat() {\\n\\t\\t\\t\\treturn this.format;\\n\\t\\t}\\n\\t\\tgetNumIndices() {\\n\\t\\t\\t\\treturn this.numIndices;\\n\\t\\t}\\n\\t\\tlock() {\\n\\t\\t\\t\\treturn this.storage;\\n\\t\\t}\\n\\t\\tunlock() {\\n\\t\\t\\t\\tthis.impl.unlock(this);\\n\\t\\t}\\n\\t\\tsetData(data) {\\n\\t\\t\\t\\tif (data.byteLength !== this.numBytes) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.storage = data;\\n\\t\\t\\t\\tthis.unlock();\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\t_lockTypedArray() {\\n\\t\\t\\t\\tconst lock = this.lock();\\n\\t\\t\\t\\tconst indices = this.format === INDEXFORMAT_UINT32 ? new Uint32Array(lock) : this.format === INDEXFORMAT_UINT16 ? new Uint16Array(lock) : new Uint8Array(lock);\\n\\t\\t\\t\\treturn indices;\\n\\t\\t}\\n\\t\\twriteData(data, count) {\\n\\t\\t\\t\\tconst indices = this._lockTypedArray();\\n\\t\\t\\t\\tif (data.length > count) {\\n\\t\\t\\t\\t\\t\\tif (ArrayBuffer.isView(data)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdata = data.subarray(0, count);\\n\\t\\t\\t\\t\\t\\t\\t\\tindices.set(data);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices[i] = data[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tindices.set(data);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.unlock();\\n\\t\\t}\\n\\t\\treadData(data) {\\n\\t\\t\\t\\tconst indices = this._lockTypedArray();\\n\\t\\t\\t\\tconst count = this.numIndices;\\n\\t\\t\\t\\tif (ArrayBuffer.isView(data)) {\\n\\t\\t\\t\\t\\t\\tdata.set(indices);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tdata.length = 0;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tdata[i] = indices[i];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn count;\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice, format, numIndices, usage = BUFFER_STATIC, initialData, options){\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t\\t\\tthis.format = format;\\n\\t\\t\\t\\tthis.numIndices = numIndices;\\n\\t\\t\\t\\tthis.usage = usage;\\n\\t\\t\\t\\tthis.id = id$5++;\\n\\t\\t\\t\\tthis.impl = graphicsDevice.createIndexBufferImpl(this, options);\\n\\t\\t\\t\\tconst bytesPerIndex = typedArrayIndexFormatsByteSize[format];\\n\\t\\t\\t\\tthis.bytesPerIndex = bytesPerIndex;\\n\\t\\t\\t\\tthis.numBytes = this.numIndices * bytesPerIndex;\\n\\t\\t\\t\\tif (initialData) {\\n\\t\\t\\t\\t\\t\\tthis.setData(initialData);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.storage = new ArrayBuffer(this.numBytes);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.adjustVramSizeTracking(graphicsDevice._vram, this.numBytes);\\n\\t\\t\\t\\tthis.device.buffers.add(this);\\n\\t\\t}\\n}\\n\\nclass ColorAttachmentOps {\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.clearValue = new Color(0, 0, 0, 1);\\n\\t\\t\\t\\tthis.clearValueLinear = new Color(0, 0, 0, 1);\\n\\t\\t\\t\\tthis.clear = false;\\n\\t\\t\\t\\tthis.store = false;\\n\\t\\t\\t\\tthis.resolve = true;\\n\\t\\t\\t\\tthis.genMipmaps = false;\\n\\t\\t}\\n}\\nclass DepthStencilAttachmentOps {\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.clearDepthValue = 1;\\n\\t\\t\\t\\tthis.clearStencilValue = 0;\\n\\t\\t\\t\\tthis.clearDepth = false;\\n\\t\\t\\t\\tthis.clearStencil = false;\\n\\t\\t\\t\\tthis.storeDepth = false;\\n\\t\\t\\t\\tthis.resolveDepth = false;\\n\\t\\t\\t\\tthis.storeStencil = false;\\n\\t\\t}\\n}\\nclass RenderPass {\\n\\t\\tget colorOps() {\\n\\t\\t\\t\\treturn this.colorArrayOps[0];\\n\\t\\t}\\n\\t\\tset name(value) {\\n\\t\\t\\t\\tthis._name = value;\\n\\t\\t}\\n\\t\\tget name() {\\n\\t\\t\\t\\tif (!this._name) {\\n\\t\\t\\t\\t\\t\\tthis._name = this.constructor.name;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._name;\\n\\t\\t}\\n\\t\\tset scaleX(value) {\\n\\t\\t\\t\\tthis._options.scaleX = value;\\n\\t\\t}\\n\\t\\tget scaleX() {\\n\\t\\t\\t\\treturn this._options.scaleX;\\n\\t\\t}\\n\\t\\tset scaleY(value) {\\n\\t\\t\\t\\tthis._options.scaleY = value;\\n\\t\\t}\\n\\t\\tget scaleY() {\\n\\t\\t\\t\\treturn this._options.scaleY;\\n\\t\\t}\\n\\t\\tset options(value) {\\n\\t\\t\\t\\tthis._options = value;\\n\\t\\t\\t\\tif (value) {\\n\\t\\t\\t\\t\\t\\tthis.scaleX = this.scaleX ?? 1;\\n\\t\\t\\t\\t\\t\\tthis.scaleY = this.scaleY ?? 1;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget options() {\\n\\t\\t\\t\\treturn this._options;\\n\\t\\t}\\n\\t\\tinit(renderTarget = null, options) {\\n\\t\\t\\t\\tthis.options = options;\\n\\t\\t\\t\\tthis.renderTarget = renderTarget;\\n\\t\\t\\t\\tthis.samples = Math.max(this.renderTarget ? this.renderTarget.samples : this.device.samples, 1);\\n\\t\\t\\t\\tthis.allocateAttachments();\\n\\t\\t\\t\\tthis.postInit();\\n\\t\\t}\\n\\t\\tallocateAttachments() {\\n\\t\\t\\t\\tconst rt = this.renderTarget;\\n\\t\\t\\t\\tthis.depthStencilOps = new DepthStencilAttachmentOps();\\n\\t\\t\\t\\tif (rt?.depthBuffer) {\\n\\t\\t\\t\\t\\t\\tthis.depthStencilOps.storeDepth = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst numColorOps = rt ? rt._colorBuffers?.length ?? 0 : 1;\\n\\t\\t\\t\\tthis.colorArrayOps.length = 0;\\n\\t\\t\\t\\tfor(let i = 0; i < numColorOps; i++){\\n\\t\\t\\t\\t\\t\\tconst colorOps = new ColorAttachmentOps();\\n\\t\\t\\t\\t\\t\\tthis.colorArrayOps[i] = colorOps;\\n\\t\\t\\t\\t\\t\\tif (this.samples === 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcolorOps.store = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tcolorOps.resolve = false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst colorBuffer = this.renderTarget?._colorBuffers?.[i];\\n\\t\\t\\t\\t\\t\\tif (this.renderTarget?.mipmaps && colorBuffer?.mipmaps) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst intFormat = isIntegerPixelFormat(colorBuffer._format);\\n\\t\\t\\t\\t\\t\\t\\t\\tcolorOps.genMipmaps = !intFormat;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdestroy() {}\\n\\t\\tpostInit() {}\\n\\t\\tframeUpdate() {\\n\\t\\t\\t\\tif (this._options && this.renderTarget) {\\n\\t\\t\\t\\t\\t\\tconst resizeSource = this._options.resizeSource ?? this.device.backBuffer;\\n\\t\\t\\t\\t\\t\\tconst width = Math.floor(resizeSource.width * this.scaleX);\\n\\t\\t\\t\\t\\t\\tconst height = Math.floor(resizeSource.height * this.scaleY);\\n\\t\\t\\t\\t\\t\\tthis.renderTarget.resize(width, height);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tbefore() {}\\n\\t\\texecute() {}\\n\\t\\tafter() {}\\n\\t\\tonEnable() {}\\n\\t\\tonDisable() {}\\n\\t\\tset enabled(value) {\\n\\t\\t\\t\\tif (this._enabled !== value) {\\n\\t\\t\\t\\t\\t\\tthis._enabled = value;\\n\\t\\t\\t\\t\\t\\tif (value) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.onEnable();\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.onDisable();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget enabled() {\\n\\t\\t\\t\\treturn this._enabled;\\n\\t\\t}\\n\\t\\tsetClearColor(color) {\\n\\t\\t\\t\\tconst count = this.colorArrayOps.length;\\n\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\tconst colorOps = this.colorArrayOps[i];\\n\\t\\t\\t\\t\\t\\tif (color) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcolorOps.clearValue.copy(color);\\n\\t\\t\\t\\t\\t\\t\\t\\tcolorOps.clearValueLinear.linear(color);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcolorOps.clear = !!color;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetClearDepth(depthValue) {\\n\\t\\t\\t\\tif (depthValue !== undefined) {\\n\\t\\t\\t\\t\\t\\tthis.depthStencilOps.clearDepthValue = depthValue;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.depthStencilOps.clearDepth = depthValue !== undefined;\\n\\t\\t}\\n\\t\\tsetClearStencil(stencilValue) {\\n\\t\\t\\t\\tif (stencilValue !== undefined) {\\n\\t\\t\\t\\t\\t\\tthis.depthStencilOps.clearStencilValue = stencilValue;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.depthStencilOps.clearStencil = stencilValue !== undefined;\\n\\t\\t}\\n\\t\\trender() {\\n\\t\\t\\t\\tif (this.enabled) {\\n\\t\\t\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\t\\t\\tconst realPass = this.renderTarget !== undefined;\\n\\t\\t\\t\\t\\t\\tthis.before();\\n\\t\\t\\t\\t\\t\\tif (this.executeEnabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (realPass && !this._skipStart) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.startRenderPass(this);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.execute();\\n\\t\\t\\t\\t\\t\\t\\t\\tif (realPass && !this._skipEnd) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.endRenderPass(this);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.after();\\n\\t\\t\\t\\t\\t\\tdevice.renderPassIndex++;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice){\\n\\t\\t\\t\\tthis._enabled = true;\\n\\t\\t\\t\\tthis._skipStart = false;\\n\\t\\t\\t\\tthis._skipEnd = false;\\n\\t\\t\\t\\tthis.executeEnabled = true;\\n\\t\\t\\t\\tthis.samples = 0;\\n\\t\\t\\t\\tthis.colorArrayOps = [];\\n\\t\\t\\t\\tthis.requiresCubemaps = true;\\n\\t\\t\\t\\tthis.fullSizeClearRect = true;\\n\\t\\t\\t\\tthis.beforePasses = [];\\n\\t\\t\\t\\tthis.afterPasses = [];\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t}\\n}\\n\\nfunction set1(a) {\\n\\t\\tthis.array[this.index] = a;\\n}\\nfunction set2(a, b) {\\n\\t\\tthis.array[this.index] = a;\\n\\t\\tthis.array[this.index + 1] = b;\\n}\\nfunction set3(a, b, c) {\\n\\t\\tthis.array[this.index] = a;\\n\\t\\tthis.array[this.index + 1] = b;\\n\\t\\tthis.array[this.index + 2] = c;\\n}\\nfunction set4(a, b, c, d) {\\n\\t\\tthis.array[this.index] = a;\\n\\t\\tthis.array[this.index + 1] = b;\\n\\t\\tthis.array[this.index + 2] = c;\\n\\t\\tthis.array[this.index + 3] = d;\\n}\\nfunction arraySet1(index, inputArray, inputIndex) {\\n\\t\\tthis.array[index] = inputArray[inputIndex];\\n}\\nfunction arraySet2(index, inputArray, inputIndex) {\\n\\t\\tthis.array[index] = inputArray[inputIndex];\\n\\t\\tthis.array[index + 1] = inputArray[inputIndex + 1];\\n}\\nfunction arraySet3(index, inputArray, inputIndex) {\\n\\t\\tthis.array[index] = inputArray[inputIndex];\\n\\t\\tthis.array[index + 1] = inputArray[inputIndex + 1];\\n\\t\\tthis.array[index + 2] = inputArray[inputIndex + 2];\\n}\\nfunction arraySet4(index, inputArray, inputIndex) {\\n\\t\\tthis.array[index] = inputArray[inputIndex];\\n\\t\\tthis.array[index + 1] = inputArray[inputIndex + 1];\\n\\t\\tthis.array[index + 2] = inputArray[inputIndex + 2];\\n\\t\\tthis.array[index + 3] = inputArray[inputIndex + 3];\\n}\\nfunction arrayGet1(offset, outputArray, outputIndex) {\\n\\t\\toutputArray[outputIndex] = this.array[offset];\\n}\\nfunction arrayGet2(offset, outputArray, outputIndex) {\\n\\t\\toutputArray[outputIndex] = this.array[offset];\\n\\t\\toutputArray[outputIndex + 1] = this.array[offset + 1];\\n}\\nfunction arrayGet3(offset, outputArray, outputIndex) {\\n\\t\\toutputArray[outputIndex] = this.array[offset];\\n\\t\\toutputArray[outputIndex + 1] = this.array[offset + 1];\\n\\t\\toutputArray[outputIndex + 2] = this.array[offset + 2];\\n}\\nfunction arrayGet4(offset, outputArray, outputIndex) {\\n\\t\\toutputArray[outputIndex] = this.array[offset];\\n\\t\\toutputArray[outputIndex + 1] = this.array[offset + 1];\\n\\t\\toutputArray[outputIndex + 2] = this.array[offset + 2];\\n\\t\\toutputArray[outputIndex + 3] = this.array[offset + 3];\\n}\\nclass VertexIteratorAccessor {\\n\\t\\tget(offset) {\\n\\t\\t\\t\\treturn this.array[this.index + offset];\\n\\t\\t}\\n\\t\\tset(a, b, c, d) {}\\n\\t\\tgetToArray(offset, outputArray, outputIndex) {}\\n\\t\\tsetFromArray(index, inputArray, inputIndex) {}\\n\\t\\tconstructor(buffer, vertexElement, vertexFormat){\\n\\t\\t\\t\\tthis.index = 0;\\n\\t\\t\\t\\tthis.numComponents = vertexElement.numComponents;\\n\\t\\t\\t\\tif (vertexFormat.interleaved) {\\n\\t\\t\\t\\t\\t\\tthis.array = new typedArrayTypes[vertexElement.dataType](buffer, vertexElement.offset);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.array = new typedArrayTypes[vertexElement.dataType](buffer, vertexElement.offset, vertexFormat.vertexCount * vertexElement.numComponents);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.stride = vertexElement.stride / this.array.constructor.BYTES_PER_ELEMENT;\\n\\t\\t\\t\\tswitch(vertexElement.numComponents){\\n\\t\\t\\t\\t\\t\\tcase 1:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.set = set1;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.getToArray = arrayGet1;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setFromArray = arraySet1;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 2:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.set = set2;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.getToArray = arrayGet2;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setFromArray = arraySet2;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 3:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.set = set3;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.getToArray = arrayGet3;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setFromArray = arraySet3;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 4:\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.set = set4;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.getToArray = arrayGet4;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setFromArray = arraySet4;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nclass VertexIterator {\\n\\t\\tnext(count = 1) {\\n\\t\\t\\t\\tlet i = 0;\\n\\t\\t\\t\\tconst accessors = this.accessors;\\n\\t\\t\\t\\tconst numAccessors = this.accessors.length;\\n\\t\\t\\t\\twhile(i < numAccessors){\\n\\t\\t\\t\\t\\t\\tconst accessor = accessors[i++];\\n\\t\\t\\t\\t\\t\\taccessor.index += count * accessor.stride;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tend() {\\n\\t\\t\\t\\tthis.vertexBuffer.unlock();\\n\\t\\t}\\n\\t\\twriteData(semantic, data, numVertices) {\\n\\t\\t\\t\\tconst element = this.element[semantic];\\n\\t\\t\\t\\tif (element) {\\n\\t\\t\\t\\t\\t\\tif (numVertices > this.vertexBuffer.numVertices) {\\n\\t\\t\\t\\t\\t\\t\\t\\tnumVertices = this.vertexBuffer.numVertices;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst numComponents = element.numComponents;\\n\\t\\t\\t\\t\\t\\tif (this.vertexBuffer.getFormat().interleaved) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlet index = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < numVertices; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\telement.setFromArray(index, data, i * numComponents);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindex += element.stride;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (data.length > numVertices * numComponents) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst copyCount = numVertices * numComponents;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (ArrayBuffer.isView(data)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata = data.subarray(0, copyCount);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\telement.array.set(data);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < copyCount; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\telement.array[i] = data[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\telement.array.set(data);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treadData(semantic, data) {\\n\\t\\t\\t\\tconst element = this.element[semantic];\\n\\t\\t\\t\\tlet count = 0;\\n\\t\\t\\t\\tif (element) {\\n\\t\\t\\t\\t\\t\\tcount = this.vertexBuffer.numVertices;\\n\\t\\t\\t\\t\\t\\tlet i;\\n\\t\\t\\t\\t\\t\\tconst numComponents = element.numComponents;\\n\\t\\t\\t\\t\\t\\tif (this.vertexBuffer.getFormat().interleaved) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (Array.isArray(data)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata.length = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\telement.index = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tlet offset = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\telement.getToArray(offset, data, i * numComponents);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toffset += element.stride;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (ArrayBuffer.isView(data)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata.set(element.array);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata.length = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst copyCount = count * numComponents;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(i = 0; i < copyCount; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata[i] = element.array[i];\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn count;\\n\\t\\t}\\n\\t\\tconstructor(vertexBuffer){\\n\\t\\t\\t\\tthis.vertexBuffer = vertexBuffer;\\n\\t\\t\\t\\tthis.vertexFormatSize = vertexBuffer.getFormat().size;\\n\\t\\t\\t\\tthis.buffer = this.vertexBuffer.lock();\\n\\t\\t\\t\\tthis.accessors = [];\\n\\t\\t\\t\\tthis.element = {};\\n\\t\\t\\t\\tconst vertexFormat = this.vertexBuffer.getFormat();\\n\\t\\t\\t\\tfor(let i = 0; i < vertexFormat.elements.length; i++){\\n\\t\\t\\t\\t\\t\\tconst vertexElement = vertexFormat.elements[i];\\n\\t\\t\\t\\t\\t\\tthis.accessors[i] = new VertexIteratorAccessor(this.buffer, vertexElement, vertexFormat);\\n\\t\\t\\t\\t\\t\\tthis.element[vertexElement.name] = this.accessors[i];\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nconst MOUSEBUTTON_NONE = -1;\\n\\nclass KeyboardEvent {\\n\\t\\tconstructor(keyboard, event){\\n\\t\\t\\t\\tthis.key = null;\\n\\t\\t\\t\\tthis.element = null;\\n\\t\\t\\t\\tthis.event = null;\\n\\t\\t\\t\\tif (event) {\\n\\t\\t\\t\\t\\t\\tthis.key = event.keyCode;\\n\\t\\t\\t\\t\\t\\tthis.element = event.target;\\n\\t\\t\\t\\t\\t\\tthis.event = event;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nconst _keyboardEvent = new KeyboardEvent();\\nfunction makeKeyboardEvent(event) {\\n\\t\\t_keyboardEvent.key = event.keyCode;\\n\\t\\t_keyboardEvent.element = event.target;\\n\\t\\t_keyboardEvent.event = event;\\n\\t\\treturn _keyboardEvent;\\n}\\nfunction toKeyCode(s) {\\n\\t\\tif (typeof s === 'string') {\\n\\t\\t\\t\\treturn s.toUpperCase().charCodeAt(0);\\n\\t\\t}\\n\\t\\treturn s;\\n}\\nconst _keyCodeToKeyIdentifier = {\\n\\t\\t'9': 'Tab',\\n\\t\\t'13': 'Enter',\\n\\t\\t'16': 'Shift',\\n\\t\\t'17': 'Control',\\n\\t\\t'18': 'Alt',\\n\\t\\t'27': 'Escape',\\n\\t\\t'37': 'Left',\\n\\t\\t'38': 'Up',\\n\\t\\t'39': 'Right',\\n\\t\\t'40': 'Down',\\n\\t\\t'46': 'Delete',\\n\\t\\t'91': 'Win'\\n};\\nclass Keyboard extends EventHandler {\\n\\t\\tattach(element) {\\n\\t\\t\\t\\tif (this._element) {\\n\\t\\t\\t\\t\\t\\tthis.detach();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._element = element;\\n\\t\\t\\t\\tthis._element.addEventListener('keydown', this._keyDownHandler, false);\\n\\t\\t\\t\\tthis._element.addEventListener('keypress', this._keyPressHandler, false);\\n\\t\\t\\t\\tthis._element.addEventListener('keyup', this._keyUpHandler, false);\\n\\t\\t\\t\\tdocument.addEventListener('visibilitychange', this._visibilityChangeHandler, false);\\n\\t\\t\\t\\twindow.addEventListener('blur', this._windowBlurHandler, false);\\n\\t\\t}\\n\\t\\tdetach() {\\n\\t\\t\\t\\tif (!this._element) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._element.removeEventListener('keydown', this._keyDownHandler);\\n\\t\\t\\t\\tthis._element.removeEventListener('keypress', this._keyPressHandler);\\n\\t\\t\\t\\tthis._element.removeEventListener('keyup', this._keyUpHandler);\\n\\t\\t\\t\\tthis._element = null;\\n\\t\\t\\t\\tdocument.removeEventListener('visibilitychange', this._visibilityChangeHandler, false);\\n\\t\\t\\t\\twindow.removeEventListener('blur', this._windowBlurHandler, false);\\n\\t\\t}\\n\\t\\ttoKeyIdentifier(keyCode) {\\n\\t\\t\\t\\tkeyCode = toKeyCode(keyCode);\\n\\t\\t\\t\\tconst id = _keyCodeToKeyIdentifier[keyCode.toString()];\\n\\t\\t\\t\\tif (id) {\\n\\t\\t\\t\\t\\t\\treturn id;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet hex = keyCode.toString(16).toUpperCase();\\n\\t\\t\\t\\tconst length = hex.length;\\n\\t\\t\\t\\tfor(let count = 0; count < 4 - length; count++){\\n\\t\\t\\t\\t\\t\\thex = `0${hex}`;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn `U+${hex}`;\\n\\t\\t}\\n\\t\\t_handleKeyDown(event) {\\n\\t\\t\\t\\tconst code = event.keyCode || event.charCode;\\n\\t\\t\\t\\tif (code === undefined) return;\\n\\t\\t\\t\\tconst id = this.toKeyIdentifier(code);\\n\\t\\t\\t\\tthis._keymap[id] = true;\\n\\t\\t\\t\\tthis.fire('keydown', makeKeyboardEvent(event));\\n\\t\\t\\t\\tif (this.preventDefault) {\\n\\t\\t\\t\\t\\t\\tevent.preventDefault();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.stopPropagation) {\\n\\t\\t\\t\\t\\t\\tevent.stopPropagation();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_handleKeyUp(event) {\\n\\t\\t\\t\\tconst code = event.keyCode || event.charCode;\\n\\t\\t\\t\\tif (code === undefined) return;\\n\\t\\t\\t\\tconst id = this.toKeyIdentifier(code);\\n\\t\\t\\t\\tdelete this._keymap[id];\\n\\t\\t\\t\\tthis.fire('keyup', makeKeyboardEvent(event));\\n\\t\\t\\t\\tif (this.preventDefault) {\\n\\t\\t\\t\\t\\t\\tevent.preventDefault();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.stopPropagation) {\\n\\t\\t\\t\\t\\t\\tevent.stopPropagation();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_handleKeyPress(event) {\\n\\t\\t\\t\\tthis.fire('keypress', makeKeyboardEvent(event));\\n\\t\\t\\t\\tif (this.preventDefault) {\\n\\t\\t\\t\\t\\t\\tevent.preventDefault();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.stopPropagation) {\\n\\t\\t\\t\\t\\t\\tevent.stopPropagation();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_handleVisibilityChange() {\\n\\t\\t\\t\\tif (document.visibilityState === 'hidden') {\\n\\t\\t\\t\\t\\t\\tthis._handleWindowBlur();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_handleWindowBlur() {\\n\\t\\t\\t\\tthis._keymap = {};\\n\\t\\t\\t\\tthis._lastmap = {};\\n\\t\\t}\\n\\t\\tupdate() {\\n\\t\\t\\t\\tfor(const prop in this._lastmap){\\n\\t\\t\\t\\t\\t\\tdelete this._lastmap[prop];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(const prop in this._keymap){\\n\\t\\t\\t\\t\\t\\tif (this._keymap.hasOwnProperty(prop)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._lastmap[prop] = this._keymap[prop];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tisPressed(key) {\\n\\t\\t\\t\\tconst keyCode = toKeyCode(key);\\n\\t\\t\\t\\tconst id = this.toKeyIdentifier(keyCode);\\n\\t\\t\\t\\treturn !!this._keymap[id];\\n\\t\\t}\\n\\t\\twasPressed(key) {\\n\\t\\t\\t\\tconst keyCode = toKeyCode(key);\\n\\t\\t\\t\\tconst id = this.toKeyIdentifier(keyCode);\\n\\t\\t\\t\\treturn !!this._keymap[id] && !!!this._lastmap[id];\\n\\t\\t}\\n\\t\\twasReleased(key) {\\n\\t\\t\\t\\tconst keyCode = toKeyCode(key);\\n\\t\\t\\t\\tconst id = this.toKeyIdentifier(keyCode);\\n\\t\\t\\t\\treturn !!!this._keymap[id] && !!this._lastmap[id];\\n\\t\\t}\\n\\t\\tconstructor(element, options = {}){\\n\\t\\t\\t\\tsuper(), this._element = null, this._keymap = {}, this._lastmap = {};\\n\\t\\t\\t\\tthis._keyDownHandler = this._handleKeyDown.bind(this);\\n\\t\\t\\t\\tthis._keyUpHandler = this._handleKeyUp.bind(this);\\n\\t\\t\\t\\tthis._keyPressHandler = this._handleKeyPress.bind(this);\\n\\t\\t\\t\\tthis._visibilityChangeHandler = this._handleVisibilityChange.bind(this);\\n\\t\\t\\t\\tthis._windowBlurHandler = this._handleWindowBlur.bind(this);\\n\\t\\t\\t\\tif (element) {\\n\\t\\t\\t\\t\\t\\tthis.attach(element);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.preventDefault = options.preventDefault || false;\\n\\t\\t\\t\\tthis.stopPropagation = options.stopPropagation || false;\\n\\t\\t}\\n}\\nKeyboard.EVENT_KEYDOWN = 'keydown';\\nKeyboard.EVENT_KEYUP = 'keyup';\\n\\nfunction isMousePointerLocked() {\\n\\t\\treturn !!(document.pointerLockElement || document.mozPointerLockElement || document.webkitPointerLockElement);\\n}\\nclass MouseEvent {\\n\\t\\tconstructor(mouse, event){\\n\\t\\t\\t\\tthis.x = 0;\\n\\t\\t\\t\\tthis.y = 0;\\n\\t\\t\\t\\tthis.dx = 0;\\n\\t\\t\\t\\tthis.dy = 0;\\n\\t\\t\\t\\tthis.button = MOUSEBUTTON_NONE;\\n\\t\\t\\t\\tthis.wheelDelta = 0;\\n\\t\\t\\t\\tthis.ctrlKey = false;\\n\\t\\t\\t\\tthis.altKey = false;\\n\\t\\t\\t\\tthis.shiftKey = false;\\n\\t\\t\\t\\tthis.metaKey = false;\\n\\t\\t\\t\\tlet coords = {\\n\\t\\t\\t\\t\\t\\tx: 0,\\n\\t\\t\\t\\t\\t\\ty: 0\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (event) {\\n\\t\\t\\t\\t\\t\\tif (event instanceof MouseEvent) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthrow Error('Expected MouseEvent');\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcoords = mouse._getTargetCoords(event);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tevent = {};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (coords) {\\n\\t\\t\\t\\t\\t\\tthis.x = coords.x;\\n\\t\\t\\t\\t\\t\\tthis.y = coords.y;\\n\\t\\t\\t\\t} else if (isMousePointerLocked()) {\\n\\t\\t\\t\\t\\t\\tthis.x = 0;\\n\\t\\t\\t\\t\\t\\tthis.y = 0;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (event.type === 'wheel') {\\n\\t\\t\\t\\t\\t\\tif (event.deltaY > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.wheelDelta = 1;\\n\\t\\t\\t\\t\\t\\t} else if (event.deltaY < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.wheelDelta = -1;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (isMousePointerLocked()) {\\n\\t\\t\\t\\t\\t\\tthis.dx = event.movementX || event.webkitMovementX || event.mozMovementX || 0;\\n\\t\\t\\t\\t\\t\\tthis.dy = event.movementY || event.webkitMovementY || event.mozMovementY || 0;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.dx = this.x - mouse._lastX;\\n\\t\\t\\t\\t\\t\\tthis.dy = this.y - mouse._lastY;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (event.type === 'mousedown' || event.type === 'mouseup') {\\n\\t\\t\\t\\t\\t\\tthis.button = event.button;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.buttons = mouse._buttons.slice(0);\\n\\t\\t\\t\\tthis.element = event.target;\\n\\t\\t\\t\\tthis.ctrlKey = event.ctrlKey ?? false;\\n\\t\\t\\t\\tthis.altKey = event.altKey ?? false;\\n\\t\\t\\t\\tthis.shiftKey = event.shiftKey ?? false;\\n\\t\\t\\t\\tthis.metaKey = event.metaKey ?? false;\\n\\t\\t\\t\\tthis.event = event;\\n\\t\\t}\\n}\\n\\nclass Mouse extends EventHandler {\\n\\t\\tstatic isPointerLocked() {\\n\\t\\t\\t\\treturn isMousePointerLocked();\\n\\t\\t}\\n\\t\\tattach(element) {\\n\\t\\t\\t\\tthis._target = element;\\n\\t\\t\\t\\tif (this._attached) return;\\n\\t\\t\\t\\tthis._attached = true;\\n\\t\\t\\t\\tconst passiveOptions = {\\n\\t\\t\\t\\t\\t\\tpassive: false\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst options = platform.passiveEvents ? passiveOptions : false;\\n\\t\\t\\t\\twindow.addEventListener('mouseup', this._upHandler, options);\\n\\t\\t\\t\\twindow.addEventListener('mousedown', this._downHandler, options);\\n\\t\\t\\t\\twindow.addEventListener('mousemove', this._moveHandler, options);\\n\\t\\t\\t\\twindow.addEventListener('wheel', this._wheelHandler, options);\\n\\t\\t}\\n\\t\\tdetach() {\\n\\t\\t\\t\\tif (!this._attached) return;\\n\\t\\t\\t\\tthis._attached = false;\\n\\t\\t\\t\\tthis._target = null;\\n\\t\\t\\t\\tconst passiveOptions = {\\n\\t\\t\\t\\t\\t\\tpassive: false\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst options = platform.passiveEvents ? passiveOptions : false;\\n\\t\\t\\t\\twindow.removeEventListener('mouseup', this._upHandler, options);\\n\\t\\t\\t\\twindow.removeEventListener('mousedown', this._downHandler, options);\\n\\t\\t\\t\\twindow.removeEventListener('mousemove', this._moveHandler, options);\\n\\t\\t\\t\\twindow.removeEventListener('wheel', this._wheelHandler, options);\\n\\t\\t}\\n\\t\\tdisableContextMenu() {\\n\\t\\t\\t\\tif (!this._target) return;\\n\\t\\t\\t\\tthis._target.addEventListener('contextmenu', this._contextMenuHandler);\\n\\t\\t}\\n\\t\\tenableContextMenu() {\\n\\t\\t\\t\\tif (!this._target) return;\\n\\t\\t\\t\\tthis._target.removeEventListener('contextmenu', this._contextMenuHandler);\\n\\t\\t}\\n\\t\\tenablePointerLock(success, error) {\\n\\t\\t\\t\\tif (!document.body.requestPointerLock) {\\n\\t\\t\\t\\t\\t\\tif (error) {\\n\\t\\t\\t\\t\\t\\t\\t\\terror();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst s = ()=>{\\n\\t\\t\\t\\t\\t\\tsuccess();\\n\\t\\t\\t\\t\\t\\tdocument.removeEventListener('pointerlockchange', s);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst e = ()=>{\\n\\t\\t\\t\\t\\t\\terror();\\n\\t\\t\\t\\t\\t\\tdocument.removeEventListener('pointerlockerror', e);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (success) {\\n\\t\\t\\t\\t\\t\\tdocument.addEventListener('pointerlockchange', s, false);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (error) {\\n\\t\\t\\t\\t\\t\\tdocument.addEventListener('pointerlockerror', e, false);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdocument.body.requestPointerLock();\\n\\t\\t}\\n\\t\\tdisablePointerLock(success) {\\n\\t\\t\\t\\tif (!document.exitPointerLock) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst s = ()=>{\\n\\t\\t\\t\\t\\t\\tsuccess();\\n\\t\\t\\t\\t\\t\\tdocument.removeEventListener('pointerlockchange', s);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (success) {\\n\\t\\t\\t\\t\\t\\tdocument.addEventListener('pointerlockchange', s, false);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdocument.exitPointerLock();\\n\\t\\t}\\n\\t\\tupdate() {\\n\\t\\t\\t\\tthis._lastbuttons[0] = this._buttons[0];\\n\\t\\t\\t\\tthis._lastbuttons[1] = this._buttons[1];\\n\\t\\t\\t\\tthis._lastbuttons[2] = this._buttons[2];\\n\\t\\t}\\n\\t\\tisPressed(button) {\\n\\t\\t\\t\\treturn this._buttons[button];\\n\\t\\t}\\n\\t\\twasPressed(button) {\\n\\t\\t\\t\\treturn this._buttons[button] && !this._lastbuttons[button];\\n\\t\\t}\\n\\t\\twasReleased(button) {\\n\\t\\t\\t\\treturn !this._buttons[button] && this._lastbuttons[button];\\n\\t\\t}\\n\\t\\t_handleUp(event) {\\n\\t\\t\\t\\tthis._buttons[event.button] = false;\\n\\t\\t\\t\\tconst e = new MouseEvent(this, event);\\n\\t\\t\\t\\tif (!e.event) return;\\n\\t\\t\\t\\tthis.fire('mouseup', e);\\n\\t\\t}\\n\\t\\t_handleDown(event) {\\n\\t\\t\\t\\tthis._buttons[event.button] = true;\\n\\t\\t\\t\\tconst e = new MouseEvent(this, event);\\n\\t\\t\\t\\tif (!e.event) return;\\n\\t\\t\\t\\tthis.fire('mousedown', e);\\n\\t\\t}\\n\\t\\t_handleMove(event) {\\n\\t\\t\\t\\tconst e = new MouseEvent(this, event);\\n\\t\\t\\t\\tif (!e.event) return;\\n\\t\\t\\t\\tthis.fire('mousemove', e);\\n\\t\\t\\t\\tthis._lastX = e.x;\\n\\t\\t\\t\\tthis._lastY = e.y;\\n\\t\\t}\\n\\t\\t_handleWheel(event) {\\n\\t\\t\\t\\tconst e = new MouseEvent(this, event);\\n\\t\\t\\t\\tif (!e.event) return;\\n\\t\\t\\t\\tthis.fire('mousewheel', e);\\n\\t\\t}\\n\\t\\t_getTargetCoords(event) {\\n\\t\\t\\t\\tconst rect = this._target.getBoundingClientRect();\\n\\t\\t\\t\\tconst left = Math.floor(rect.left);\\n\\t\\t\\t\\tconst top = Math.floor(rect.top);\\n\\t\\t\\t\\tif (event.clientX < left || event.clientX >= left + this._target.clientWidth || event.clientY < top || event.clientY >= top + this._target.clientHeight) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tx: event.clientX - left,\\n\\t\\t\\t\\t\\t\\ty: event.clientY - top\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tconstructor(element){\\n\\t\\t\\t\\tsuper(), this._lastX = 0, this._lastY = 0, this._buttons = [\\n\\t\\t\\t\\t\\t\\tfalse,\\n\\t\\t\\t\\t\\t\\tfalse,\\n\\t\\t\\t\\t\\t\\tfalse\\n\\t\\t\\t\\t], this._lastbuttons = [\\n\\t\\t\\t\\t\\t\\tfalse,\\n\\t\\t\\t\\t\\t\\tfalse,\\n\\t\\t\\t\\t\\t\\tfalse\\n\\t\\t\\t\\t], this._target = null, this._attached = false;\\n\\t\\t\\t\\tthis._upHandler = this._handleUp.bind(this);\\n\\t\\t\\t\\tthis._downHandler = this._handleDown.bind(this);\\n\\t\\t\\t\\tthis._moveHandler = this._handleMove.bind(this);\\n\\t\\t\\t\\tthis._wheelHandler = this._handleWheel.bind(this);\\n\\t\\t\\t\\tthis._contextMenuHandler = (event)=>{\\n\\t\\t\\t\\t\\t\\tevent.preventDefault();\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.attach(element);\\n\\t\\t}\\n}\\nMouse.EVENT_MOUSEMOVE = 'mousemove';\\nMouse.EVENT_MOUSEDOWN = 'mousedown';\\nMouse.EVENT_MOUSEUP = 'mouseup';\\nMouse.EVENT_MOUSEWHEEL = 'mousewheel';\\n\\nfunction getTouchTargetCoords(touch) {\\n\\t\\tlet totalOffsetX = 0;\\n\\t\\tlet totalOffsetY = 0;\\n\\t\\tlet target = touch.target;\\n\\t\\twhile(!(target instanceof HTMLElement) && target){\\n\\t\\t\\t\\ttarget = target.parentNode;\\n\\t\\t}\\n\\t\\twhile(target){\\n\\t\\t\\t\\ttotalOffsetX += target.offsetLeft - target.scrollLeft;\\n\\t\\t\\t\\ttotalOffsetY += target.offsetTop - target.scrollTop;\\n\\t\\t\\t\\ttarget = target.offsetParent;\\n\\t\\t}\\n\\t\\treturn {\\n\\t\\t\\t\\tx: touch.pageX - totalOffsetX,\\n\\t\\t\\t\\ty: touch.pageY - totalOffsetY\\n\\t\\t};\\n}\\nclass Touch {\\n\\t\\tconstructor(touch){\\n\\t\\t\\t\\tconst coords = getTouchTargetCoords(touch);\\n\\t\\t\\t\\tthis.id = touch.identifier;\\n\\t\\t\\t\\tthis.x = coords.x;\\n\\t\\t\\t\\tthis.y = coords.y;\\n\\t\\t\\t\\tthis.target = touch.target;\\n\\t\\t\\t\\tthis.touch = touch;\\n\\t\\t}\\n}\\nclass TouchEvent {\\n\\t\\tgetTouchById(id, list) {\\n\\t\\t\\t\\treturn list.find((touch)=>touch.id === id) || null;\\n\\t\\t}\\n\\t\\tconstructor(device, event){\\n\\t\\t\\t\\tthis.touches = [];\\n\\t\\t\\t\\tthis.changedTouches = [];\\n\\t\\t\\t\\tthis.element = event.target;\\n\\t\\t\\t\\tthis.event = event;\\n\\t\\t\\t\\tthis.touches = Array.from(event.touches).map((touch)=>new Touch(touch));\\n\\t\\t\\t\\tthis.changedTouches = Array.from(event.changedTouches).map((touch)=>new Touch(touch));\\n\\t\\t}\\n}\\n\\nclass TouchDevice extends EventHandler {\\n\\t\\tattach(element) {\\n\\t\\t\\t\\tif (this._element) {\\n\\t\\t\\t\\t\\t\\tthis.detach();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._element = element;\\n\\t\\t\\t\\tthis._element.addEventListener('touchstart', this._startHandler, false);\\n\\t\\t\\t\\tthis._element.addEventListener('touchend', this._endHandler, false);\\n\\t\\t\\t\\tthis._element.addEventListener('touchmove', this._moveHandler, false);\\n\\t\\t\\t\\tthis._element.addEventListener('touchcancel', this._cancelHandler, false);\\n\\t\\t}\\n\\t\\tdetach() {\\n\\t\\t\\t\\tif (this._element) {\\n\\t\\t\\t\\t\\t\\tthis._element.removeEventListener('touchstart', this._startHandler, false);\\n\\t\\t\\t\\t\\t\\tthis._element.removeEventListener('touchend', this._endHandler, false);\\n\\t\\t\\t\\t\\t\\tthis._element.removeEventListener('touchmove', this._moveHandler, false);\\n\\t\\t\\t\\t\\t\\tthis._element.removeEventListener('touchcancel', this._cancelHandler, false);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._element = null;\\n\\t\\t}\\n\\t\\t_handleTouchStart(e) {\\n\\t\\t\\t\\tthis.fire('touchstart', new TouchEvent(this, e));\\n\\t\\t}\\n\\t\\t_handleTouchEnd(e) {\\n\\t\\t\\t\\tthis.fire('touchend', new TouchEvent(this, e));\\n\\t\\t}\\n\\t\\t_handleTouchMove(e) {\\n\\t\\t\\t\\te.preventDefault();\\n\\t\\t\\t\\tthis.fire('touchmove', new TouchEvent(this, e));\\n\\t\\t}\\n\\t\\t_handleTouchCancel(e) {\\n\\t\\t\\t\\tthis.fire('touchcancel', new TouchEvent(this, e));\\n\\t\\t}\\n\\t\\tconstructor(element){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis._element = null;\\n\\t\\t\\t\\tthis._startHandler = this._handleTouchStart.bind(this);\\n\\t\\t\\t\\tthis._endHandler = this._handleTouchEnd.bind(this);\\n\\t\\t\\t\\tthis._moveHandler = this._handleTouchMove.bind(this);\\n\\t\\t\\t\\tthis._cancelHandler = this._handleTouchCancel.bind(this);\\n\\t\\t\\t\\tthis.attach(element);\\n\\t\\t}\\n}\\nTouchDevice.EVENT_TOUCHSTART = 'touchstart';\\nTouchDevice.EVENT_TOUCHEND = 'touchend';\\nTouchDevice.EVENT_TOUCHMOVE = 'touchmove';\\nTouchDevice.EVENT_TOUCHCANCEL = 'touchcancel';\\n\\nclass Http {\\n\\t\\tget(url, options, callback) {\\n\\t\\t\\t\\tif (typeof options === 'function') {\\n\\t\\t\\t\\t\\t\\tcallback = options;\\n\\t\\t\\t\\t\\t\\toptions = {};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst result = this.request('GET', url, options, callback);\\n\\t\\t\\t\\tconst { progress } = options;\\n\\t\\t\\t\\tif (progress) {\\n\\t\\t\\t\\t\\t\\tconst handler = (event)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (event.lengthComputable) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tprogress.fire('progress', event.loaded, event.total);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tconst endHandler = (event)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\thandler(event);\\n\\t\\t\\t\\t\\t\\t\\t\\tresult.removeEventListener('loadstart', handler);\\n\\t\\t\\t\\t\\t\\t\\t\\tresult.removeEventListener('progress', handler);\\n\\t\\t\\t\\t\\t\\t\\t\\tresult.removeEventListener('loadend', endHandler);\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tresult.addEventListener('loadstart', handler);\\n\\t\\t\\t\\t\\t\\tresult.addEventListener('progress', handler);\\n\\t\\t\\t\\t\\t\\tresult.addEventListener('loadend', endHandler);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tpost(url, data, options, callback) {\\n\\t\\t\\t\\tif (typeof options === 'function') {\\n\\t\\t\\t\\t\\t\\tcallback = options;\\n\\t\\t\\t\\t\\t\\toptions = {};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\toptions.postdata = data;\\n\\t\\t\\t\\treturn this.request('POST', url, options, callback);\\n\\t\\t}\\n\\t\\tput(url, data, options, callback) {\\n\\t\\t\\t\\tif (typeof options === 'function') {\\n\\t\\t\\t\\t\\t\\tcallback = options;\\n\\t\\t\\t\\t\\t\\toptions = {};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\toptions.postdata = data;\\n\\t\\t\\t\\treturn this.request('PUT', url, options, callback);\\n\\t\\t}\\n\\t\\tdel(url, options, callback) {\\n\\t\\t\\t\\tif (typeof options === 'function') {\\n\\t\\t\\t\\t\\t\\tcallback = options;\\n\\t\\t\\t\\t\\t\\toptions = {};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.request('DELETE', url, options, callback);\\n\\t\\t}\\n\\t\\trequest(method, url, options, callback) {\\n\\t\\t\\t\\tlet uri, query, postdata;\\n\\t\\t\\t\\tlet errored = false;\\n\\t\\t\\t\\tif (typeof options === 'function') {\\n\\t\\t\\t\\t\\t\\tcallback = options;\\n\\t\\t\\t\\t\\t\\toptions = {};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.retry) {\\n\\t\\t\\t\\t\\t\\toptions = Object.assign({\\n\\t\\t\\t\\t\\t\\t\\t\\tretries: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tmaxRetries: 5\\n\\t\\t\\t\\t\\t\\t}, options);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\toptions.callback = callback;\\n\\t\\t\\t\\tif (options.async == null) {\\n\\t\\t\\t\\t\\t\\toptions.async = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.headers == null) {\\n\\t\\t\\t\\t\\t\\toptions.headers = {};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.postdata != null) {\\n\\t\\t\\t\\t\\t\\tif (options.postdata instanceof Document) {\\n\\t\\t\\t\\t\\t\\t\\t\\tpostdata = options.postdata;\\n\\t\\t\\t\\t\\t\\t} else if (options.postdata instanceof FormData) {\\n\\t\\t\\t\\t\\t\\t\\t\\tpostdata = options.postdata;\\n\\t\\t\\t\\t\\t\\t} else if (options.postdata instanceof Object) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlet contentType = options.headers['Content-Type'];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (contentType === undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions.headers['Content-Type'] = Http.ContentType.FORM_URLENCODED;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontentType = options.headers['Content-Type'];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tswitch(contentType){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase Http.ContentType.FORM_URLENCODED:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpostdata = '';\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet bFirstItem = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(const key in options.postdata){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (options.postdata.hasOwnProperty(key)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (bFirstItem) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbFirstItem = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpostdata += '&';\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst encodedKey = encodeURIComponent(key);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst encodedValue = encodeURIComponent(options.postdata[key]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpostdata += `${encodedKey}=${encodedValue}`;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase Http.ContentType.JSON:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (contentType == null) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions.headers['Content-Type'] = Http.ContentType.JSON;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpostdata = JSON.stringify(options.postdata);\\n\\t\\t\\t\\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} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tpostdata = options.postdata;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.cache === false) {\\n\\t\\t\\t\\t\\t\\tconst timestamp = now();\\n\\t\\t\\t\\t\\t\\turi = new URI(url);\\n\\t\\t\\t\\t\\t\\tif (!uri.query) {\\n\\t\\t\\t\\t\\t\\t\\t\\turi.query = `ts=${timestamp}`;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\turi.query = `${uri.query}&ts=${timestamp}`;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\turl = uri.toString();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.query) {\\n\\t\\t\\t\\t\\t\\turi = new URI(url);\\n\\t\\t\\t\\t\\t\\tquery = extend(uri.getQuery(), options.query);\\n\\t\\t\\t\\t\\t\\turi.setQuery(query);\\n\\t\\t\\t\\t\\t\\turl = uri.toString();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst xhr = new XMLHttpRequest();\\n\\t\\t\\t\\txhr.open(method, url, options.async);\\n\\t\\t\\t\\txhr.withCredentials = options.withCredentials !== undefined ? options.withCredentials : false;\\n\\t\\t\\t\\txhr.responseType = options.responseType || this._guessResponseType(url);\\n\\t\\t\\t\\tfor(const header in options.headers){\\n\\t\\t\\t\\t\\t\\tif (options.headers.hasOwnProperty(header)) {\\n\\t\\t\\t\\t\\t\\t\\t\\txhr.setRequestHeader(header, options.headers[header]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\txhr.onreadystatechange = ()=>{\\n\\t\\t\\t\\t\\t\\tthis._onReadyStateChange(method, url, options, xhr);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\txhr.onerror = ()=>{\\n\\t\\t\\t\\t\\t\\tthis._onError(method, url, options, xhr);\\n\\t\\t\\t\\t\\t\\terrored = true;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\txhr.send(postdata);\\n\\t\\t\\t\\t} catch (e) {\\n\\t\\t\\t\\t\\t\\tif (!errored) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.error(xhr.status, xhr, e);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn xhr;\\n\\t\\t}\\n\\t\\t_guessResponseType(url) {\\n\\t\\t\\t\\tconst uri = new URI(url);\\n\\t\\t\\t\\tconst ext = path.getExtension(uri.path).toLowerCase();\\n\\t\\t\\t\\tif (Http.binaryExtensions.indexOf(ext) >= 0) {\\n\\t\\t\\t\\t\\t\\treturn Http.ResponseType.ARRAY_BUFFER;\\n\\t\\t\\t\\t} else if (ext === '.json') {\\n\\t\\t\\t\\t\\t\\treturn Http.ResponseType.JSON;\\n\\t\\t\\t\\t} else if (ext === '.xml') {\\n\\t\\t\\t\\t\\t\\treturn Http.ResponseType.DOCUMENT;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn Http.ResponseType.TEXT;\\n\\t\\t}\\n\\t\\t_isBinaryContentType(contentType) {\\n\\t\\t\\t\\tconst binTypes = [\\n\\t\\t\\t\\t\\t\\tHttp.ContentType.BASIS,\\n\\t\\t\\t\\t\\t\\tHttp.ContentType.BIN,\\n\\t\\t\\t\\t\\t\\tHttp.ContentType.DDS,\\n\\t\\t\\t\\t\\t\\tHttp.ContentType.GLB,\\n\\t\\t\\t\\t\\t\\tHttp.ContentType.MP3,\\n\\t\\t\\t\\t\\t\\tHttp.ContentType.MP4,\\n\\t\\t\\t\\t\\t\\tHttp.ContentType.OGG,\\n\\t\\t\\t\\t\\t\\tHttp.ContentType.OPUS,\\n\\t\\t\\t\\t\\t\\tHttp.ContentType.WAV\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tif (binTypes.indexOf(contentType) >= 0) {\\n\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\t_isBinaryResponseType(responseType) {\\n\\t\\t\\t\\treturn responseType === Http.ResponseType.ARRAY_BUFFER || responseType === Http.ResponseType.BLOB || responseType === Http.ResponseType.JSON;\\n\\t\\t}\\n\\t\\t_onReadyStateChange(method, url, options, xhr) {\\n\\t\\t\\t\\tif (xhr.readyState === 4) {\\n\\t\\t\\t\\t\\t\\tswitch(xhr.status){\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 0:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (xhr.responseURL && xhr.responseURL.startsWith('file:///')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._onSuccess(method, url, options, xhr);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._onError(method, url, options, xhr);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 200:\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 201:\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 206:\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 304:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._onSuccess(method, url, options, xhr);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._onError(method, url, options, xhr);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onSuccess(method, url, options, xhr) {\\n\\t\\t\\t\\tlet response;\\n\\t\\t\\t\\tlet contentType;\\n\\t\\t\\t\\tconst header = xhr.getResponseHeader('Content-Type');\\n\\t\\t\\t\\tif (header) {\\n\\t\\t\\t\\t\\t\\tconst parts = header.split(';');\\n\\t\\t\\t\\t\\t\\tcontentType = parts[0].trim();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\tif (this._isBinaryContentType(contentType) || this._isBinaryResponseType(xhr.responseType)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tresponse = xhr.response;\\n\\t\\t\\t\\t\\t\\t} else if (contentType === Http.ContentType.JSON || url.split('?')[0].endsWith('.json')) {\\n\\t\\t\\t\\t\\t\\t\\t\\tresponse = JSON.parse(xhr.responseText);\\n\\t\\t\\t\\t\\t\\t} else if (xhr.responseType === Http.ResponseType.DOCUMENT || contentType === Http.ContentType.XML) {\\n\\t\\t\\t\\t\\t\\t\\t\\tresponse = xhr.responseXML;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tresponse = xhr.responseText;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\toptions.callback(null, response);\\n\\t\\t\\t\\t} catch (err) {\\n\\t\\t\\t\\t\\t\\toptions.callback(err);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onError(method, url, options, xhr) {\\n\\t\\t\\t\\tif (options.retrying) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.retry && options.retries < options.maxRetries) {\\n\\t\\t\\t\\t\\t\\toptions.retries++;\\n\\t\\t\\t\\t\\t\\toptions.retrying = true;\\n\\t\\t\\t\\t\\t\\tconst retryDelay = math.clamp(Math.pow(2, options.retries) * Http.retryDelay, 0, options.maxRetryDelay || 5000);\\n\\t\\t\\t\\t\\t\\tconsole.log(`${method}: ${url} - Error ${xhr.status}. Retrying in ${retryDelay} ms`);\\n\\t\\t\\t\\t\\t\\tsetTimeout(()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.retrying = false;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.request(method, url, options, options.callback);\\n\\t\\t\\t\\t\\t\\t}, retryDelay);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\toptions.callback(xhr.status === 0 ? 'Network error' : xhr.status, null);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nHttp.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};\\nHttp.ResponseType = {\\n\\t\\tTEXT: 'text',\\n\\t\\tARRAY_BUFFER: 'arraybuffer',\\n\\t\\tBLOB: 'blob',\\n\\t\\tDOCUMENT: 'document',\\n\\t\\tJSON: 'json'\\n};\\nHttp.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];\\nHttp.retryDelay = 100;\\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\\t[BLEND_SUBTRACTIVE]: 'SUBTRACTIVE',\\n\\t\\t[BLEND_ADDITIVE]: 'ADDITIVE',\\n\\t\\t[BLEND_NORMAL]: 'NORMAL',\\n\\t\\t[BLEND_NONE]: 'NONE',\\n\\t\\t[BLEND_PREMULTIPLIED]: 'PREMULTIPLIED',\\n\\t\\t[BLEND_MULTIPLICATIVE]: 'MULTIPLICATIVE',\\n\\t\\t[BLEND_ADDITIVEALPHA]: 'ADDITIVEALPHA',\\n\\t\\t[BLEND_MULTIPLICATIVE2X]: 'MULTIPLICATIVE2X',\\n\\t\\t[BLEND_SCREEN]: 'SCREEN',\\n\\t\\t[BLEND_MIN]: 'MIN',\\n\\t\\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\\t[FRESNEL_NONE]: 'NONE',\\n\\t\\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\\t[LIGHTTYPE_DIRECTIONAL]: 'DIRECTIONAL',\\n\\t\\t[LIGHTTYPE_OMNI]: 'OMNI',\\n\\t\\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\\t[LIGHTSHAPE_PUNCTUAL]: 'PUNCTUAL',\\n\\t\\t[LIGHTSHAPE_RECT]: 'RECT',\\n\\t\\t[LIGHTSHAPE_DISK]: 'DISK',\\n\\t\\t[LIGHTSHAPE_SPHERE]: 'SPHERE'\\n};\\nconst LIGHTFALLOFF_LINEAR = 0;\\nconst LIGHTFALLOFF_INVERSESQUARED = 1;\\nconst lightFalloffNames = {\\n\\t\\t[LIGHTFALLOFF_LINEAR]: 'LINEAR',\\n\\t\\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 = new Map([\\n\\t\\t[\\n\\t\\t\\t\\tSHADOW_PCF1_32F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'PCF1_32F',\\n\\t\\t\\t\\t\\t\\tkind: 'PCF1',\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_DEPTH,\\n\\t\\t\\t\\t\\t\\tpcf: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tSHADOW_PCF3_32F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'PCF3_32F',\\n\\t\\t\\t\\t\\t\\tkind: 'PCF3',\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_DEPTH,\\n\\t\\t\\t\\t\\t\\tpcf: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tSHADOW_PCF5_32F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'PCF5_32F',\\n\\t\\t\\t\\t\\t\\tkind: 'PCF5',\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_DEPTH,\\n\\t\\t\\t\\t\\t\\tpcf: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tSHADOW_PCF1_16F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'PCF1_16F',\\n\\t\\t\\t\\t\\t\\tkind: 'PCF1',\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_DEPTH16,\\n\\t\\t\\t\\t\\t\\tpcf: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tSHADOW_PCF3_16F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'PCF3_16F',\\n\\t\\t\\t\\t\\t\\tkind: 'PCF3',\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_DEPTH16,\\n\\t\\t\\t\\t\\t\\tpcf: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tSHADOW_PCF5_16F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'PCF5_16F',\\n\\t\\t\\t\\t\\t\\tkind: 'PCF5',\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_DEPTH16,\\n\\t\\t\\t\\t\\t\\tpcf: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tSHADOW_VSM_16F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'VSM_16F',\\n\\t\\t\\t\\t\\t\\tkind: 'VSM',\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA16F,\\n\\t\\t\\t\\t\\t\\tvsm: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tSHADOW_VSM_32F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'VSM_32F',\\n\\t\\t\\t\\t\\t\\tkind: 'VSM',\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32F,\\n\\t\\t\\t\\t\\t\\tvsm: true\\n\\t\\t\\t\\t}\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tSHADOW_PCSS_32F,\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tname: 'PCSS_32F',\\n\\t\\t\\t\\t\\t\\tkind: 'PCSS',\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_R32F,\\n\\t\\t\\t\\t\\t\\tpcss: true\\n\\t\\t\\t\\t}\\n\\t\\t]\\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\\t[CUBEPROJ_NONE]: 'NONE',\\n\\t\\t[CUBEPROJ_BOX]: 'BOX'\\n};\\nconst DETAILMODE_MUL = 'mul';\\nconst GAMMA_NONE = 0;\\nconst GAMMA_SRGB = 1;\\nconst gammaNames = {\\n\\t\\t[GAMMA_NONE]: 'NONE',\\n\\t\\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\\t'LINEAR',\\n\\t\\t'FILMIC',\\n\\t\\t'HEJL',\\n\\t\\t'ACES',\\n\\t\\t'ACES2',\\n\\t\\t'NEUTRAL',\\n\\t\\t'NONE'\\n];\\nconst SPECOCC_NONE = 0;\\nconst SPECOCC_AO = 1;\\nconst SPECOCC_GLOSSDEPENDENT = 2;\\nconst specularOcclusionNames = {\\n\\t\\t[SPECOCC_NONE]: 'NONE',\\n\\t\\t[SPECOCC_AO]: 'AO',\\n\\t\\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\\t[REFLECTIONSRC_NONE]: 'NONE',\\n\\t\\t[REFLECTIONSRC_ENVATLAS]: 'ENVATLAS',\\n\\t\\t[REFLECTIONSRC_ENVATLASHQ]: 'ENVATLASHQ',\\n\\t\\t[REFLECTIONSRC_CUBEMAP]: 'CUBEMAP',\\n\\t\\t[REFLECTIONSRC_SPHEREMAP]: 'SPHEREMAP'\\n};\\nconst AMBIENTSRC_AMBIENTSH = 'ambientSH';\\nconst AMBIENTSRC_ENVALATLAS = 'envAtlas';\\nconst AMBIENTSRC_CONSTANT = 'constant';\\nconst ambientSrcNames = {\\n\\t\\t[AMBIENTSRC_AMBIENTSH]: 'AMBIENTSH',\\n\\t\\t[AMBIENTSRC_ENVALATLAS]: 'ENVALATLAS',\\n\\t\\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\\t[SPRITE_RENDERMODE_SIMPLE]: 'SIMPLE',\\n\\t\\t[SPRITE_RENDERMODE_SLICED]: 'SLICED',\\n\\t\\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\\t[DITHER_NONE]: 'NONE',\\n\\t\\t[DITHER_BAYER8]: 'BAYER8',\\n\\t\\t[DITHER_BLUENOISE]: 'BLUENOISE',\\n\\t\\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;\\n\\nclass ShaderProcessorOptions {\\n\\t\\thasUniform(name) {\\n\\t\\t\\t\\tfor(let i = 0; i < this.uniformFormats.length; i++){\\n\\t\\t\\t\\t\\t\\tconst uniformFormat = this.uniformFormats[i];\\n\\t\\t\\t\\t\\t\\tif (uniformFormat?.get(name)) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\thasTexture(name) {\\n\\t\\t\\t\\tfor(let i = 0; i < this.bindGroupFormats.length; i++){\\n\\t\\t\\t\\t\\t\\tconst groupFormat = this.bindGroupFormats[i];\\n\\t\\t\\t\\t\\t\\tif (groupFormat?.getTexture(name)) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tgetVertexElement(semantic) {\\n\\t\\t\\t\\treturn this.vertexFormat?.elements.find((element)=>element.name === semantic);\\n\\t\\t}\\n\\t\\tgenerateKey(device) {\\n\\t\\t\\t\\tlet key = JSON.stringify(this.uniformFormats) + JSON.stringify(this.bindGroupFormats);\\n\\t\\t\\t\\tif (device.isWebGPU) {\\n\\t\\t\\t\\t\\t\\tkey += this.vertexFormat?.shaderProcessingHashString;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn key;\\n\\t\\t}\\n\\t\\tconstructor(viewUniformFormat, viewBindGroupFormat, vertexFormat){\\n\\t\\t\\t\\tthis.uniformFormats = [];\\n\\t\\t\\t\\tthis.bindGroupFormats = [];\\n\\t\\t\\t\\tthis.uniformFormats[BINDGROUP_VIEW] = viewUniformFormat;\\n\\t\\t\\t\\tthis.bindGroupFormats[BINDGROUP_VIEW] = viewBindGroupFormat;\\n\\t\\t\\t\\tthis.vertexFormat = vertexFormat;\\n\\t\\t}\\n}\\n\\nconst programLibraryDeviceCache = new DeviceCache();\\nfunction getProgramLibrary(device) {\\n\\t\\tconst library = programLibraryDeviceCache.get(device);\\n\\t\\treturn library;\\n}\\nfunction setProgramLibrary(device, library) {\\n\\t\\tprogramLibraryDeviceCache.get(device, ()=>{\\n\\t\\t\\t\\treturn library;\\n\\t\\t});\\n}\\n\\nclass ShaderGenerator {\\n\\t\\tstatic definesHash(defines) {\\n\\t\\t\\t\\tconst sortedArray = Array.from(defines).sort((a, b)=>a[0] > b[0] ? 1 : -1);\\n\\t\\t\\t\\treturn hashCode(JSON.stringify(sortedArray));\\n\\t\\t}\\n}\\n\\nconst shaderPassDeviceCache = new DeviceCache();\\nclass ShaderPassInfo {\\n\\t\\tbuildShaderDefines() {\\n\\t\\t\\t\\tlet keyword;\\n\\t\\t\\t\\tif (this.isShadow) {\\n\\t\\t\\t\\t\\t\\tkeyword = 'SHADOW';\\n\\t\\t\\t\\t} else if (this.isForward) {\\n\\t\\t\\t\\t\\t\\tkeyword = 'FORWARD';\\n\\t\\t\\t\\t} else if (this.index === SHADER_PICK) {\\n\\t\\t\\t\\t\\t\\tkeyword = 'PICK';\\n\\t\\t\\t\\t} else if (this.index === SHADER_DEPTH_PICK) {\\n\\t\\t\\t\\t\\t\\tkeyword = 'PICK';\\n\\t\\t\\t\\t\\t\\tthis.defines.set('DEPTH_PICK_PASS', '');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.defines.set(`${keyword}_PASS`, '');\\n\\t\\t\\t\\tthis.defines.set(`${this.name.toUpperCase()}_PASS`, '');\\n\\t\\t}\\n\\t\\tconstructor(name, index, options = {}){\\n\\t\\t\\t\\tthis.defines = new Map();\\n\\t\\t\\t\\tthis.name = name;\\n\\t\\t\\t\\tthis.index = index;\\n\\t\\t\\t\\tObject.assign(this, options);\\n\\t\\t\\t\\tthis.buildShaderDefines();\\n\\t\\t}\\n}\\nclass ShaderPass {\\n\\t\\tstatic get(device) {\\n\\t\\t\\t\\treturn shaderPassDeviceCache.get(device, ()=>{\\n\\t\\t\\t\\t\\t\\treturn new ShaderPass();\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tallocate(name, options) {\\n\\t\\t\\t\\tlet info = this.passesNamed.get(name);\\n\\t\\t\\t\\tif (info === undefined) {\\n\\t\\t\\t\\t\\t\\tinfo = new ShaderPassInfo(name, this.nextIndex, options);\\n\\t\\t\\t\\t\\t\\tthis.passesNamed.set(info.name, info);\\n\\t\\t\\t\\t\\t\\tthis.passesIndexed[info.index] = info;\\n\\t\\t\\t\\t\\t\\tthis.nextIndex++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn info;\\n\\t\\t}\\n\\t\\tgetByIndex(index) {\\n\\t\\t\\t\\tconst info = this.passesIndexed[index];\\n\\t\\t\\t\\treturn info;\\n\\t\\t}\\n\\t\\tgetByName(name) {\\n\\t\\t\\t\\treturn this.passesNamed.get(name);\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.passesNamed = new Map();\\n\\t\\t\\t\\tthis.passesIndexed = [];\\n\\t\\t\\t\\tthis.nextIndex = 0;\\n\\t\\t\\t\\tconst add = (name, index, options)=>{\\n\\t\\t\\t\\t\\t\\tthis.allocate(name, options);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tadd('forward', SHADER_FORWARD, {\\n\\t\\t\\t\\t\\t\\tisForward: true\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tadd('prepass');\\n\\t\\t\\t\\tadd('shadow');\\n\\t\\t\\t\\tadd('pick');\\n\\t\\t\\t\\tadd('depth_pick');\\n\\t\\t}\\n}\\n\\nclass ShaderChunkMap extends Map {\\n\\t\\tset(name, code) {\\n\\t\\t\\t\\tif (!this.has(name) || this.get(name) !== code) {\\n\\t\\t\\t\\t\\t\\tthis.markDirty();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn super.set(name, code);\\n\\t\\t}\\n\\t\\tadd(object, override = true) {\\n\\t\\t\\t\\tfor (const [key, value] of Object.entries(object)){\\n\\t\\t\\t\\t\\t\\tif (override || !this.has(key)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.set(key, value);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tdelete(name) {\\n\\t\\t\\t\\tconst existed = this.has(name);\\n\\t\\t\\t\\tconst result = super.delete(name);\\n\\t\\t\\t\\tif (existed && result) {\\n\\t\\t\\t\\t\\t\\tthis.markDirty();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tclear() {\\n\\t\\t\\t\\tif (this.size > 0) {\\n\\t\\t\\t\\t\\t\\tthis.markDirty();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tsuper.clear();\\n\\t\\t}\\n\\t\\tmarkDirty() {\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t\\t\\tthis._keyDirty = true;\\n\\t\\t}\\n\\t\\tisDirty() {\\n\\t\\t\\t\\treturn this._dirty;\\n\\t\\t}\\n\\t\\tresetDirty() {\\n\\t\\t\\t\\tthis._dirty = false;\\n\\t\\t}\\n\\t\\tget key() {\\n\\t\\t\\t\\tif (this._keyDirty) {\\n\\t\\t\\t\\t\\t\\tthis._keyDirty = false;\\n\\t\\t\\t\\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\\t\\t}\\n\\t\\t\\t\\treturn this._key;\\n\\t\\t}\\n\\t\\tcopy(source) {\\n\\t\\t\\t\\tthis.clear();\\n\\t\\t\\t\\tfor (const [key, value] of source){\\n\\t\\t\\t\\t\\t\\tthis.set(key, value);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tconstructor(validations){\\n\\t\\t\\t\\tsuper(), this._keyDirty = false, this._key = '';\\n\\t\\t\\t\\tthis._validations = validations;\\n\\t\\t}\\n}\\n\\nconst _chunksCache = new DeviceCache();\\nclass ShaderChunks {\\n\\t\\tstatic get(device, shaderLanguage = SHADERLANGUAGE_GLSL) {\\n\\t\\t\\t\\tconst cache = _chunksCache.get(device, ()=>{\\n\\t\\t\\t\\t\\t\\treturn new ShaderChunks();\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn shaderLanguage === SHADERLANGUAGE_GLSL ? cache.glsl : cache.wgsl;\\n\\t\\t}\\n\\t\\tstatic registerValidation(name, options) {}\\n\\t\\tget useWGSL() {\\n\\t\\t\\t\\treturn this.glsl.size === 0 || this.wgsl.size > 0;\\n\\t\\t}\\n\\t\\tget key() {\\n\\t\\t\\t\\treturn `GLSL:${this.glsl.key}|WGSL:${this.wgsl.key}|API:${this.version}`;\\n\\t\\t}\\n\\t\\tisDirty() {\\n\\t\\t\\t\\treturn this.glsl.isDirty() || this.wgsl.isDirty();\\n\\t\\t}\\n\\t\\tresetDirty() {\\n\\t\\t\\t\\tthis.glsl.resetDirty();\\n\\t\\t\\t\\tthis.wgsl.resetDirty();\\n\\t\\t}\\n\\t\\tcopy(source) {\\n\\t\\t\\t\\tthis.version = source.version;\\n\\t\\t\\t\\tthis.glsl.copy(source.glsl);\\n\\t\\t\\t\\tthis.wgsl.copy(source.wgsl);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.glsl = new ShaderChunkMap(ShaderChunks._validations);\\n\\t\\t\\t\\tthis.wgsl = new ShaderChunkMap(ShaderChunks._validations);\\n\\t\\t\\t\\tthis.version = '';\\n\\t\\t}\\n}\\nShaderChunks._validations = new Map();\\n\\nclass MapUtils {\\n\\t\\tstatic merge(...maps) {\\n\\t\\t\\t\\tconst result = new Map(maps[0] ?? []);\\n\\t\\t\\t\\tfor(let i = 1; i < maps.length; i++){\\n\\t\\t\\t\\t\\t\\tconst map = maps[i];\\n\\t\\t\\t\\t\\t\\tif (map) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor (const [key, value] of map){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult.set(key, value);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n}\\n\\nclass ShaderGeneratorPassThrough extends ShaderGenerator {\\n\\t\\tgenerateKey(options) {\\n\\t\\t\\t\\treturn this.key;\\n\\t\\t}\\n\\t\\tcreateShaderDefinition(device, options) {\\n\\t\\t\\t\\treturn this.shaderDefinition;\\n\\t\\t}\\n\\t\\tconstructor(key, shaderDefinition){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.key = key;\\n\\t\\t\\t\\tthis.shaderDefinition = shaderDefinition;\\n\\t\\t}\\n}\\nclass ShaderUtils {\\n\\t\\tstatic createShader(device, options) {\\n\\t\\t\\t\\tconst programLibrary = getProgramLibrary(device);\\n\\t\\t\\t\\tlet shader = programLibrary.getCachedShader(options.uniqueName);\\n\\t\\t\\t\\tif (!shader) {\\n\\t\\t\\t\\t\\t\\tconst wgsl = device.isWebGPU && (!!options.vertexWGSL || !!options.vertexChunk) && (!!options.fragmentWGSL || !!options.fragmentChunk);\\n\\t\\t\\t\\t\\t\\tconst chunksMap = ShaderChunks.get(device, wgsl ? SHADERLANGUAGE_WGSL : SHADERLANGUAGE_GLSL);\\n\\t\\t\\t\\t\\t\\tconst vertexCode = options.vertexChunk ? chunksMap.get(options.vertexChunk) : wgsl ? options.vertexWGSL : options.vertexGLSL;\\n\\t\\t\\t\\t\\t\\tconst fragmentCode = options.fragmentChunk ? chunksMap.get(options.fragmentChunk) : wgsl ? options.fragmentWGSL : options.fragmentGLSL;\\n\\t\\t\\t\\t\\t\\tconst fragmentIncludes = MapUtils.merge(chunksMap, options.fragmentIncludes);\\n\\t\\t\\t\\t\\t\\tconst vertexIncludes = MapUtils.merge(chunksMap, options.vertexIncludes);\\n\\t\\t\\t\\t\\t\\tshader = new Shader(device, ShaderDefinitionUtils.createDefinition(device, {\\n\\t\\t\\t\\t\\t\\t\\t\\tname: options.uniqueName,\\n\\t\\t\\t\\t\\t\\t\\t\\tshaderLanguage: wgsl ? SHADERLANGUAGE_WGSL : SHADERLANGUAGE_GLSL,\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes: options.attributes,\\n\\t\\t\\t\\t\\t\\t\\t\\tvertexCode: vertexCode,\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentCode: fragmentCode,\\n\\t\\t\\t\\t\\t\\t\\t\\tuseTransformFeedback: options.useTransformFeedback,\\n\\t\\t\\t\\t\\t\\t\\t\\tvertexIncludes: vertexIncludes,\\n\\t\\t\\t\\t\\t\\t\\t\\tvertexDefines: options.vertexDefines,\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentIncludes: fragmentIncludes,\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentDefines: options.fragmentDefines,\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentOutputTypes: options.fragmentOutputTypes\\n\\t\\t\\t\\t\\t\\t}));\\n\\t\\t\\t\\t\\t\\tprogramLibrary.setCachedShader(options.uniqueName, shader);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn shader;\\n\\t\\t}\\n\\t\\tstatic getCoreDefines(material, params) {\\n\\t\\t\\t\\tconst defines = new Map(material.defines);\\n\\t\\t\\t\\tparams.cameraShaderParams.defines.forEach((value, key)=>defines.set(key, value));\\n\\t\\t\\t\\tconst shaderPassInfo = ShaderPass.get(params.device).getByIndex(params.pass);\\n\\t\\t\\t\\tshaderPassInfo.defines.forEach((value, key)=>defines.set(key, value));\\n\\t\\t\\t\\treturn defines;\\n\\t\\t}\\n\\t\\tstatic processShader(shader, processingOptions) {\\n\\t\\t\\t\\tconst shaderDefinition = shader.definition;\\n\\t\\t\\t\\tconst name = shaderDefinition.name ?? 'shader';\\n\\t\\t\\t\\tconst key = `${name}-id-${shader.id}`;\\n\\t\\t\\t\\tconst materialGenerator = new ShaderGeneratorPassThrough(key, shaderDefinition);\\n\\t\\t\\t\\tconst libraryModuleName = 'shader';\\n\\t\\t\\t\\tconst library = getProgramLibrary(shader.device);\\n\\t\\t\\t\\tlibrary.register(libraryModuleName, materialGenerator);\\n\\t\\t\\t\\tconst variant = library.getProgram(libraryModuleName, {}, processingOptions);\\n\\t\\t\\t\\tlibrary.unregister(libraryModuleName);\\n\\t\\t\\t\\treturn variant;\\n\\t\\t}\\n\\t\\tstatic addScreenDepthChunkDefines(device, cameraShaderParams, defines) {\\n\\t\\t\\t\\tif (cameraShaderParams.sceneDepthMapLinear) {\\n\\t\\t\\t\\t\\t\\tdefines.set('SCENE_DEPTHMAP_LINEAR', '');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (device.textureFloatRenderable) {\\n\\t\\t\\t\\t\\t\\tdefines.set('SCENE_DEPTHMAP_FLOAT', '');\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nconst _quadPrimitive = {\\n\\t\\ttype: PRIMITIVE_TRISTRIP,\\n\\t\\tbase: 0,\\n\\t\\tbaseVertex: 0,\\n\\t\\tcount: 4,\\n\\t\\tindexed: false\\n};\\nconst _tempViewport = new Vec4();\\nconst _tempScissor = new Vec4();\\nconst _dynamicBindGroup$1 = new DynamicBindGroup();\\nclass QuadRender {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.uniformBuffer?.destroy();\\n\\t\\t\\t\\tthis.uniformBuffer = null;\\n\\t\\t\\t\\tthis.bindGroup?.destroy();\\n\\t\\t\\t\\tthis.bindGroup = null;\\n\\t\\t}\\n\\t\\trender(viewport, scissor) {\\n\\t\\t\\t\\tconst device = this.shader.device;\\n\\t\\t\\t\\tif (viewport) {\\n\\t\\t\\t\\t\\t\\t_tempViewport.set(device.vx, device.vy, device.vw, device.vh);\\n\\t\\t\\t\\t\\t\\t_tempScissor.set(device.sx, device.sy, device.sw, device.sh);\\n\\t\\t\\t\\t\\t\\tscissor = scissor ?? viewport;\\n\\t\\t\\t\\t\\t\\tdevice.setViewport(viewport.x, viewport.y, viewport.z, viewport.w);\\n\\t\\t\\t\\t\\t\\tdevice.setScissor(scissor.x, scissor.y, scissor.z, scissor.w);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdevice.setVertexBuffer(device.quadVertexBuffer);\\n\\t\\t\\t\\tconst shader = this.shader;\\n\\t\\t\\t\\tdevice.setShader(shader);\\n\\t\\t\\t\\tif (device.supportsUniformBuffers) {\\n\\t\\t\\t\\t\\t\\tdevice.setBindGroup(BINDGROUP_VIEW, device.emptyBindGroup);\\n\\t\\t\\t\\t\\t\\tconst bindGroup = this.bindGroup;\\n\\t\\t\\t\\t\\t\\tbindGroup.update();\\n\\t\\t\\t\\t\\t\\tdevice.setBindGroup(BINDGROUP_MESH, bindGroup);\\n\\t\\t\\t\\t\\t\\tconst uniformBuffer = this.uniformBuffer;\\n\\t\\t\\t\\t\\t\\tif (uniformBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniformBuffer.update(_dynamicBindGroup$1);\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.setBindGroup(BINDGROUP_MESH_UB, _dynamicBindGroup$1.bindGroup, _dynamicBindGroup$1.offsets);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.setBindGroup(BINDGROUP_MESH_UB, device.emptyBindGroup);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdevice.draw(_quadPrimitive);\\n\\t\\t\\t\\tif (viewport) {\\n\\t\\t\\t\\t\\t\\tdevice.setViewport(_tempViewport.x, _tempViewport.y, _tempViewport.z, _tempViewport.w);\\n\\t\\t\\t\\t\\t\\tdevice.setScissor(_tempScissor.x, _tempScissor.y, _tempScissor.z, _tempScissor.w);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(shader){\\n\\t\\t\\t\\tconst device = shader.device;\\n\\t\\t\\t\\tthis.shader = shader;\\n\\t\\t\\t\\tif (device.supportsUniformBuffers) {\\n\\t\\t\\t\\t\\t\\tconst processingOptions = new ShaderProcessorOptions();\\n\\t\\t\\t\\t\\t\\tthis.shader = ShaderUtils.processShader(shader, processingOptions);\\n\\t\\t\\t\\t\\t\\tconst ubFormat = this.shader.meshUniformBufferFormat;\\n\\t\\t\\t\\t\\t\\tif (ubFormat) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.uniformBuffer = new UniformBuffer(device, ubFormat, false);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst bindGroupFormat = this.shader.meshBindGroupFormat;\\n\\t\\t\\t\\t\\t\\tthis.bindGroup = new BindGroup(device, bindGroupFormat);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass RenderPassQuad extends RenderPass {\\n\\t\\texecute() {\\n\\t\\t\\t\\tconst { device } = this;\\n\\t\\t\\t\\tdevice.setCullMode(CULLFACE_NONE);\\n\\t\\t\\t\\tdevice.setDepthState(DepthState.NODEPTH);\\n\\t\\t\\t\\tdevice.setStencilState(null, null);\\n\\t\\t\\t\\tthis.quad.render(this.rect, this.scissorRect);\\n\\t\\t}\\n\\t\\tconstructor(device, quad, rect, scissorRect){\\n\\t\\t\\t\\tsuper(device);\\n\\t\\t\\t\\tthis.quad = quad;\\n\\t\\t\\t\\tthis.rect = rect;\\n\\t\\t\\t\\tthis.scissorRect = scissorRect;\\n\\t\\t}\\n}\\n\\nconst _tempRect = new Vec4();\\nfunction drawQuadWithShader(device, target, shader, rect, scissorRect) {\\n\\t\\tconst quad = new QuadRender(shader);\\n\\t\\tif (!rect) {\\n\\t\\t\\t\\trect = _tempRect;\\n\\t\\t\\t\\trect.x = 0;\\n\\t\\t\\t\\trect.y = 0;\\n\\t\\t\\t\\trect.z = target ? target.width : device.width;\\n\\t\\t\\t\\trect.w = target ? target.height : device.height;\\n\\t\\t}\\n\\t\\tconst renderPass = new RenderPassQuad(device, quad, rect, scissorRect);\\n\\t\\trenderPass.init(target);\\n\\t\\trenderPass.colorOps.clear = false;\\n\\t\\trenderPass.depthStencilOps.clearDepth = false;\\n\\t\\tif (device.isWebGPU && target === null && device.samples > 1) {\\n\\t\\t\\t\\trenderPass.colorOps.store = true;\\n\\t\\t}\\n\\t\\trenderPass.render();\\n\\t\\tquad.destroy();\\n}\\n\\nclass BatchGroup {\\n\\t\\tconstructor(id, name, dynamic, maxAabbSize, layers = [\\n\\t\\t\\t\\tLAYERID_WORLD\\n\\t\\t]){\\n\\t\\t\\t\\tthis._ui = false;\\n\\t\\t\\t\\tthis._sprite = false;\\n\\t\\t\\t\\tthis._obj = {\\n\\t\\t\\t\\t\\t\\tmodel: [],\\n\\t\\t\\t\\t\\t\\telement: [],\\n\\t\\t\\t\\t\\t\\tsprite: [],\\n\\t\\t\\t\\t\\t\\trender: []\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.id = id;\\n\\t\\t\\t\\tthis.name = name;\\n\\t\\t\\t\\tthis.dynamic = dynamic;\\n\\t\\t\\t\\tthis.maxAabbSize = maxAabbSize;\\n\\t\\t\\t\\tthis.layers = layers;\\n\\t\\t}\\n}\\nBatchGroup.MODEL = 'model';\\nBatchGroup.ELEMENT = 'element';\\nBatchGroup.SPRITE = 'sprite';\\nBatchGroup.RENDER = 'render';\\n\\nconst _invMatrix = new Mat4();\\nclass SkinInstance {\\n\\t\\tset rootBone(rootBone) {\\n\\t\\t\\t\\tthis._rootBone = rootBone;\\n\\t\\t}\\n\\t\\tget rootBone() {\\n\\t\\t\\t\\treturn this._rootBone;\\n\\t\\t}\\n\\t\\tinit(device, numBones) {\\n\\t\\t\\t\\tconst numPixels = numBones * 3;\\n\\t\\t\\t\\tlet width = Math.ceil(Math.sqrt(numPixels));\\n\\t\\t\\t\\twidth = math.roundUp(width, 3);\\n\\t\\t\\t\\tconst height = Math.ceil(numPixels / width);\\n\\t\\t\\t\\tthis.boneTexture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\twidth: width,\\n\\t\\t\\t\\t\\t\\theight: height,\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32F,\\n\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\tname: 'skin'\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.matrixPalette = this.boneTexture.lock({\\n\\t\\t\\t\\t\\t\\tmode: TEXTURELOCK_READ\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.boneTexture.unlock();\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tif (this.boneTexture) {\\n\\t\\t\\t\\t\\t\\tthis.boneTexture.destroy();\\n\\t\\t\\t\\t\\t\\tthis.boneTexture = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tresolve(rootBone, entity) {\\n\\t\\t\\t\\tthis.rootBone = rootBone;\\n\\t\\t\\t\\tconst skin = this.skin;\\n\\t\\t\\t\\tconst bones = [];\\n\\t\\t\\t\\tfor(let j = 0; j < skin.boneNames.length; j++){\\n\\t\\t\\t\\t\\t\\tconst boneName = skin.boneNames[j];\\n\\t\\t\\t\\t\\t\\tlet bone = rootBone.findByName(boneName);\\n\\t\\t\\t\\t\\t\\tif (!bone) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbone = entity;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tbones.push(bone);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.bones = bones;\\n\\t\\t}\\n\\t\\tinitSkin(skin) {\\n\\t\\t\\t\\tthis.skin = skin;\\n\\t\\t\\t\\tthis.bones = [];\\n\\t\\t\\t\\tconst numBones = skin.inverseBindPose.length;\\n\\t\\t\\t\\tthis.init(skin.device, numBones);\\n\\t\\t\\t\\tthis.matrices = [];\\n\\t\\t\\t\\tfor(let i = 0; i < numBones; i++){\\n\\t\\t\\t\\t\\t\\tthis.matrices[i] = new Mat4();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tuploadBones(device) {\\n\\t\\t\\t\\tthis.boneTexture.upload();\\n\\t\\t}\\n\\t\\t_updateMatrices(rootNode, skinUpdateIndex) {\\n\\t\\t\\t\\tif (this._skinUpdateIndex !== skinUpdateIndex) {\\n\\t\\t\\t\\t\\t\\tthis._skinUpdateIndex = skinUpdateIndex;\\n\\t\\t\\t\\t\\t\\t_invMatrix.copy(rootNode.getWorldTransform()).invert();\\n\\t\\t\\t\\t\\t\\tfor(let i = this.bones.length - 1; i >= 0; i--){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.matrices[i].mulAffine2(_invMatrix, this.bones[i].getWorldTransform());\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.matrices[i].mulAffine2(this.matrices[i], this.skin.inverseBindPose[i]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateMatrices(rootNode, skinUpdateIndex) {\\n\\t\\t\\t\\tif (this._updateBeforeCull) {\\n\\t\\t\\t\\t\\t\\tthis._updateMatrices(rootNode, skinUpdateIndex);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateMatrixPalette(rootNode, skinUpdateIndex) {\\n\\t\\t\\t\\tthis._updateMatrices(rootNode, skinUpdateIndex);\\n\\t\\t\\t\\tconst mp = this.matrixPalette;\\n\\t\\t\\t\\tconst count = this.bones.length;\\n\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\tconst pe = this.matrices[i].data;\\n\\t\\t\\t\\t\\t\\tconst base = i * 12;\\n\\t\\t\\t\\t\\t\\tmp[base] = pe[0];\\n\\t\\t\\t\\t\\t\\tmp[base + 1] = pe[4];\\n\\t\\t\\t\\t\\t\\tmp[base + 2] = pe[8];\\n\\t\\t\\t\\t\\t\\tmp[base + 3] = pe[12];\\n\\t\\t\\t\\t\\t\\tmp[base + 4] = pe[1];\\n\\t\\t\\t\\t\\t\\tmp[base + 5] = pe[5];\\n\\t\\t\\t\\t\\t\\tmp[base + 6] = pe[9];\\n\\t\\t\\t\\t\\t\\tmp[base + 7] = pe[13];\\n\\t\\t\\t\\t\\t\\tmp[base + 8] = pe[2];\\n\\t\\t\\t\\t\\t\\tmp[base + 9] = pe[6];\\n\\t\\t\\t\\t\\t\\tmp[base + 10] = pe[10];\\n\\t\\t\\t\\t\\t\\tmp[base + 11] = pe[14];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.uploadBones(this.skin.device);\\n\\t\\t}\\n\\t\\tconstructor(skin){\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t\\t\\tthis._rootBone = null;\\n\\t\\t\\t\\tthis._skinUpdateIndex = -1;\\n\\t\\t\\t\\tthis._updateBeforeCull = true;\\n\\t\\t\\t\\tif (skin) {\\n\\t\\t\\t\\t\\t\\tthis.initSkin(skin);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nlet id$4 = 0;\\nclass GeometryData {\\n\\t\\tinitDefaults() {\\n\\t\\t\\t\\tthis.recreate = false;\\n\\t\\t\\t\\tthis.verticesUsage = BUFFER_STATIC;\\n\\t\\t\\t\\tthis.indicesUsage = BUFFER_STATIC;\\n\\t\\t\\t\\tthis.maxVertices = 0;\\n\\t\\t\\t\\tthis.maxIndices = 0;\\n\\t\\t\\t\\tthis.vertexCount = 0;\\n\\t\\t\\t\\tthis.indexCount = 0;\\n\\t\\t\\t\\tthis.vertexStreamsUpdated = false;\\n\\t\\t\\t\\tthis.indexStreamUpdated = false;\\n\\t\\t\\t\\tthis.vertexStreamDictionary = {};\\n\\t\\t\\t\\tthis.indices = null;\\n\\t\\t}\\n\\t\\t_changeVertexCount(count, semantic) {\\n\\t\\t\\t\\tif (!this.vertexCount) {\\n\\t\\t\\t\\t\\t\\tthis.vertexCount = count;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.initDefaults();\\n\\t\\t}\\n}\\nGeometryData.DEFAULT_COMPONENTS_POSITION = 3;\\nGeometryData.DEFAULT_COMPONENTS_NORMAL = 3;\\nGeometryData.DEFAULT_COMPONENTS_UV = 2;\\nGeometryData.DEFAULT_COMPONENTS_COLORS = 4;\\nclass GeometryVertexStream {\\n\\t\\tconstructor(data, componentCount, dataType, dataTypeNormalize, asInt){\\n\\t\\t\\t\\tthis.data = data;\\n\\t\\t\\t\\tthis.componentCount = componentCount;\\n\\t\\t\\t\\tthis.dataType = dataType;\\n\\t\\t\\t\\tthis.dataTypeNormalize = dataTypeNormalize;\\n\\t\\t\\t\\tthis.asInt = asInt;\\n\\t\\t}\\n}\\nclass Mesh extends RefCountedObject {\\n\\t\\tstatic fromGeometry(graphicsDevice, geometry, options = {}) {\\n\\t\\t\\t\\tconst mesh = new Mesh(graphicsDevice, options);\\n\\t\\t\\t\\tconst { positions, normals, tangents, colors, uvs, uvs1, blendIndices, blendWeights, indices } = geometry;\\n\\t\\t\\t\\tif (positions) {\\n\\t\\t\\t\\t\\t\\tmesh.setPositions(positions);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (normals) {\\n\\t\\t\\t\\t\\t\\tmesh.setNormals(normals);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (tangents) {\\n\\t\\t\\t\\t\\t\\tmesh.setVertexStream(SEMANTIC_TANGENT, tangents, 4);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (colors) {\\n\\t\\t\\t\\t\\t\\tmesh.setColors32(colors);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (uvs) {\\n\\t\\t\\t\\t\\t\\tmesh.setUvs(0, uvs);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (uvs1) {\\n\\t\\t\\t\\t\\t\\tmesh.setUvs(1, uvs1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (blendIndices) {\\n\\t\\t\\t\\t\\t\\tmesh.setVertexStream(SEMANTIC_BLENDINDICES, blendIndices, 4, blendIndices.length / 4, TYPE_UINT8);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (blendWeights) {\\n\\t\\t\\t\\t\\t\\tmesh.setVertexStream(SEMANTIC_BLENDWEIGHT, blendWeights, 4);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (indices) {\\n\\t\\t\\t\\t\\t\\tmesh.setIndices(indices);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tmesh.update();\\n\\t\\t\\t\\treturn mesh;\\n\\t\\t}\\n\\t\\tset morph(morph) {\\n\\t\\t\\t\\tif (morph !== this._morph) {\\n\\t\\t\\t\\t\\t\\tif (this._morph) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._morph.decRefCount();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._morph = morph;\\n\\t\\t\\t\\t\\t\\tif (morph) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmorph.incRefCount();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget morph() {\\n\\t\\t\\t\\treturn this._morph;\\n\\t\\t}\\n\\t\\tset aabb(aabb) {\\n\\t\\t\\t\\tthis._aabb = aabb;\\n\\t\\t\\t\\tthis._aabbVer++;\\n\\t\\t}\\n\\t\\tget aabb() {\\n\\t\\t\\t\\treturn this._aabb;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tconst morph = this.morph;\\n\\t\\t\\t\\tif (morph) {\\n\\t\\t\\t\\t\\t\\tthis.morph = null;\\n\\t\\t\\t\\t\\t\\tif (morph.refCount < 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmorph.destroy();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.vertexBuffer) {\\n\\t\\t\\t\\t\\t\\tthis.vertexBuffer.destroy();\\n\\t\\t\\t\\t\\t\\tthis.vertexBuffer = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let j = 0; j < this.indexBuffer.length; j++){\\n\\t\\t\\t\\t\\t\\tthis._destroyIndexBuffer(j);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.indexBuffer.length = 0;\\n\\t\\t\\t\\tthis._geometryData = null;\\n\\t\\t}\\n\\t\\t_destroyIndexBuffer(index) {\\n\\t\\t\\t\\tif (this.indexBuffer[index]) {\\n\\t\\t\\t\\t\\t\\tthis.indexBuffer[index].destroy();\\n\\t\\t\\t\\t\\t\\tthis.indexBuffer[index] = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_initBoneAabbs(morphTargets) {\\n\\t\\t\\t\\tthis.boneAabb = [];\\n\\t\\t\\t\\tthis.boneUsed = [];\\n\\t\\t\\t\\tlet x, y, z;\\n\\t\\t\\t\\tlet bMax, bMin;\\n\\t\\t\\t\\tconst boneMin = [];\\n\\t\\t\\t\\tconst boneMax = [];\\n\\t\\t\\t\\tconst boneUsed = this.boneUsed;\\n\\t\\t\\t\\tconst numBones = this.skin.boneNames.length;\\n\\t\\t\\t\\tlet maxMorphX, maxMorphY, maxMorphZ;\\n\\t\\t\\t\\tfor(let i = 0; i < numBones; i++){\\n\\t\\t\\t\\t\\t\\tboneMin[i] = new Vec3(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);\\n\\t\\t\\t\\t\\t\\tboneMax[i] = new Vec3(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst iterator = new VertexIterator(this.vertexBuffer);\\n\\t\\t\\t\\tconst posElement = iterator.element[SEMANTIC_POSITION];\\n\\t\\t\\t\\tconst weightsElement = iterator.element[SEMANTIC_BLENDWEIGHT];\\n\\t\\t\\t\\tconst indicesElement = iterator.element[SEMANTIC_BLENDINDICES];\\n\\t\\t\\t\\tconst numVerts = this.vertexBuffer.numVertices;\\n\\t\\t\\t\\tfor(let j = 0; j < numVerts; j++){\\n\\t\\t\\t\\t\\t\\tfor(let k = 0; k < 4; k++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst boneWeight = weightsElement.array[weightsElement.index + k];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (boneWeight > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst boneIndex = indicesElement.array[indicesElement.index + k];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tboneUsed[boneIndex] = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tx = posElement.array[posElement.index];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ty = posElement.array[posElement.index + 1];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tz = posElement.array[posElement.index + 2];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbMax = boneMax[boneIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbMin = boneMin[boneIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (bMin.x > x) bMin.x = x;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (bMin.y > y) bMin.y = y;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (bMin.z > z) bMin.z = z;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (bMax.x < x) bMax.x = x;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (bMax.y < y) bMax.y = y;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (bMax.z < z) bMax.z = z;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (morphTargets) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet minMorphX = maxMorphX = x;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet minMorphY = maxMorphY = y;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet minMorphZ = maxMorphZ = z;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let l = 0; l < morphTargets.length; l++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst target = morphTargets[l];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst dx = target.deltaPositions[j * 3];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst dy = target.deltaPositions[j * 3 + 1];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst dz = target.deltaPositions[j * 3 + 2];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (dx < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tminMorphX += dx;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmaxMorphX += dx;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (dy < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tminMorphY += dy;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmaxMorphY += dy;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (dz < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tminMorphZ += dz;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmaxMorphZ += dz;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (bMin.x > minMorphX) bMin.x = minMorphX;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (bMin.y > minMorphY) bMin.y = minMorphY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (bMin.z > minMorphZ) bMin.z = minMorphZ;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (bMax.x < maxMorphX) bMax.x = maxMorphX;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (bMax.y < maxMorphY) bMax.y = maxMorphY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (bMax.z < maxMorphZ) bMax.z = maxMorphZ;\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\titerator.next();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst positionElement = this.vertexBuffer.getFormat().elements.find((e)=>e.name === SEMANTIC_POSITION);\\n\\t\\t\\t\\tif (positionElement && positionElement.normalize) {\\n\\t\\t\\t\\t\\t\\tconst func = (()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tswitch(positionElement.dataType){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase TYPE_INT8:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn (x)=>Math.max(x / 127.0, -1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase TYPE_UINT8:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn (x)=>x / 255.0;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase TYPE_INT16:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn (x)=>Math.max(x / 32767.0, -1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase TYPE_UINT16:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn (x)=>x / 65535.0;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn (x)=>x;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t})();\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < numBones; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (boneUsed[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst min = boneMin[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst max = boneMax[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmin.set(func(min.x), func(min.y), func(min.z));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmax.set(func(max.x), func(max.y), func(max.z));\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < numBones; i++){\\n\\t\\t\\t\\t\\t\\tconst aabb = new BoundingBox();\\n\\t\\t\\t\\t\\t\\taabb.setMinMax(boneMin[i], boneMax[i]);\\n\\t\\t\\t\\t\\t\\tthis.boneAabb.push(aabb);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_initGeometryData() {\\n\\t\\t\\t\\tif (!this._geometryData) {\\n\\t\\t\\t\\t\\t\\tthis._geometryData = new GeometryData();\\n\\t\\t\\t\\t\\t\\tif (this.vertexBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._geometryData.vertexCount = this.vertexBuffer.numVertices;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._geometryData.maxVertices = this.vertexBuffer.numVertices;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.indexBuffer.length > 0 && this.indexBuffer[0]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._geometryData.indexCount = this.indexBuffer[0].numIndices;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._geometryData.maxIndices = this.indexBuffer[0].numIndices;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tclear(verticesDynamic, indicesDynamic, maxVertices = 0, maxIndices = 0) {\\n\\t\\t\\t\\tthis._initGeometryData();\\n\\t\\t\\t\\tthis._geometryData.initDefaults();\\n\\t\\t\\t\\tthis._geometryData.recreate = true;\\n\\t\\t\\t\\tthis._geometryData.maxVertices = maxVertices;\\n\\t\\t\\t\\tthis._geometryData.maxIndices = maxIndices;\\n\\t\\t\\t\\tthis._geometryData.verticesUsage = verticesDynamic ? BUFFER_STATIC : BUFFER_DYNAMIC;\\n\\t\\t\\t\\tthis._geometryData.indicesUsage = indicesDynamic ? BUFFER_STATIC : BUFFER_DYNAMIC;\\n\\t\\t}\\n\\t\\tsetVertexStream(semantic, data, componentCount, numVertices, dataType = TYPE_FLOAT32, dataTypeNormalize = false, asInt = false) {\\n\\t\\t\\t\\tthis._initGeometryData();\\n\\t\\t\\t\\tconst vertexCount = numVertices || data.length / componentCount;\\n\\t\\t\\t\\tthis._geometryData._changeVertexCount(vertexCount, semantic);\\n\\t\\t\\t\\tthis._geometryData.vertexStreamsUpdated = true;\\n\\t\\t\\t\\tthis._geometryData.vertexStreamDictionary[semantic] = new GeometryVertexStream(data, componentCount, dataType, dataTypeNormalize, asInt);\\n\\t\\t}\\n\\t\\tgetVertexStream(semantic, data) {\\n\\t\\t\\t\\tlet count = 0;\\n\\t\\t\\t\\tlet done = false;\\n\\t\\t\\t\\tif (this._geometryData) {\\n\\t\\t\\t\\t\\t\\tconst stream = this._geometryData.vertexStreamDictionary[semantic];\\n\\t\\t\\t\\t\\t\\tif (stream) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdone = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tcount = this._geometryData.vertexCount;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (ArrayBuffer.isView(data)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata.set(stream.data);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata.length = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata.push(stream.data);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!done) {\\n\\t\\t\\t\\t\\t\\tif (this.vertexBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst iterator = new VertexIterator(this.vertexBuffer);\\n\\t\\t\\t\\t\\t\\t\\t\\tcount = iterator.readData(semantic, data);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn count;\\n\\t\\t}\\n\\t\\tsetPositions(positions, componentCount = GeometryData.DEFAULT_COMPONENTS_POSITION, numVertices) {\\n\\t\\t\\t\\tthis.setVertexStream(SEMANTIC_POSITION, positions, componentCount, numVertices, TYPE_FLOAT32, false);\\n\\t\\t}\\n\\t\\tsetNormals(normals, componentCount = GeometryData.DEFAULT_COMPONENTS_NORMAL, numVertices) {\\n\\t\\t\\t\\tthis.setVertexStream(SEMANTIC_NORMAL, normals, componentCount, numVertices, TYPE_FLOAT32, false);\\n\\t\\t}\\n\\t\\tsetUvs(channel, uvs, componentCount = GeometryData.DEFAULT_COMPONENTS_UV, numVertices) {\\n\\t\\t\\t\\tthis.setVertexStream(SEMANTIC_TEXCOORD + channel, uvs, componentCount, numVertices, TYPE_FLOAT32, false);\\n\\t\\t}\\n\\t\\tsetColors(colors, componentCount = GeometryData.DEFAULT_COMPONENTS_COLORS, numVertices) {\\n\\t\\t\\t\\tthis.setVertexStream(SEMANTIC_COLOR, colors, componentCount, numVertices, TYPE_FLOAT32, false);\\n\\t\\t}\\n\\t\\tsetColors32(colors, numVertices) {\\n\\t\\t\\t\\tthis.setVertexStream(SEMANTIC_COLOR, colors, GeometryData.DEFAULT_COMPONENTS_COLORS, numVertices, TYPE_UINT8, true);\\n\\t\\t}\\n\\t\\tsetIndices(indices, numIndices) {\\n\\t\\t\\t\\tthis._initGeometryData();\\n\\t\\t\\t\\tthis._geometryData.indexStreamUpdated = true;\\n\\t\\t\\t\\tthis._geometryData.indices = indices;\\n\\t\\t\\t\\tthis._geometryData.indexCount = numIndices || indices.length;\\n\\t\\t}\\n\\t\\tgetPositions(positions) {\\n\\t\\t\\t\\treturn this.getVertexStream(SEMANTIC_POSITION, positions);\\n\\t\\t}\\n\\t\\tgetNormals(normals) {\\n\\t\\t\\t\\treturn this.getVertexStream(SEMANTIC_NORMAL, normals);\\n\\t\\t}\\n\\t\\tgetUvs(channel, uvs) {\\n\\t\\t\\t\\treturn this.getVertexStream(SEMANTIC_TEXCOORD + channel, uvs);\\n\\t\\t}\\n\\t\\tgetColors(colors) {\\n\\t\\t\\t\\treturn this.getVertexStream(SEMANTIC_COLOR, colors);\\n\\t\\t}\\n\\t\\tgetIndices(indices) {\\n\\t\\t\\t\\tlet count = 0;\\n\\t\\t\\t\\tif (this._geometryData && this._geometryData.indices) {\\n\\t\\t\\t\\t\\t\\tconst streamIndices = this._geometryData.indices;\\n\\t\\t\\t\\t\\t\\tcount = this._geometryData.indexCount;\\n\\t\\t\\t\\t\\t\\tif (ArrayBuffer.isView(indices)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tindices.set(streamIndices);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tindices.length = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0, il = streamIndices.length; i < il; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices.push(streamIndices[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (this.indexBuffer.length > 0 && this.indexBuffer[0]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst indexBuffer = this.indexBuffer[0];\\n\\t\\t\\t\\t\\t\\t\\t\\tcount = indexBuffer.readData(indices);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn count;\\n\\t\\t}\\n\\t\\tupdate(primitiveType = PRIMITIVE_TRIANGLES, updateBoundingBox = true) {\\n\\t\\t\\t\\tif (this._geometryData) {\\n\\t\\t\\t\\t\\t\\tif (updateBoundingBox) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst stream = this._geometryData.vertexStreamDictionary[SEMANTIC_POSITION];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (stream) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (stream.componentCount === 3) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._aabb.compute(stream.data, this._geometryData.vertexCount);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._aabbVer++;\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tlet destroyVB = this._geometryData.recreate;\\n\\t\\t\\t\\t\\t\\tif (this._geometryData.vertexCount > this._geometryData.maxVertices) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdestroyVB = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._geometryData.maxVertices = this._geometryData.vertexCount;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (destroyVB) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.vertexBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.vertexBuffer.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.vertexBuffer = null;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlet destroyIB = this._geometryData.recreate;\\n\\t\\t\\t\\t\\t\\tif (this._geometryData.indexCount > this._geometryData.maxIndices) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdestroyIB = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._geometryData.maxIndices = this._geometryData.indexCount;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (destroyIB) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.indexBuffer.length > 0 && this.indexBuffer[0]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.indexBuffer[0].destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.indexBuffer[0] = null;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this._geometryData.vertexStreamsUpdated) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._updateVertexBuffer();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this._geometryData.indexStreamUpdated) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._updateIndexBuffer();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.primitive[0].type = primitiveType;\\n\\t\\t\\t\\t\\t\\tif (this.indexBuffer.length > 0 && this.indexBuffer[0]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._geometryData.indexStreamUpdated) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.primitive[0].count = this._geometryData.indexCount;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.primitive[0].indexed = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._geometryData.vertexStreamsUpdated) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.primitive[0].count = this._geometryData.vertexCount;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.primitive[0].indexed = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._geometryData.vertexCount = 0;\\n\\t\\t\\t\\t\\t\\tthis._geometryData.indexCount = 0;\\n\\t\\t\\t\\t\\t\\tthis._geometryData.vertexStreamsUpdated = false;\\n\\t\\t\\t\\t\\t\\tthis._geometryData.indexStreamUpdated = false;\\n\\t\\t\\t\\t\\t\\tthis._geometryData.recreate = false;\\n\\t\\t\\t\\t\\t\\tthis.updateRenderStates();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_buildVertexFormat(vertexCount) {\\n\\t\\t\\t\\tconst vertexDesc = [];\\n\\t\\t\\t\\tfor(const semantic in this._geometryData.vertexStreamDictionary){\\n\\t\\t\\t\\t\\t\\tconst stream = this._geometryData.vertexStreamDictionary[semantic];\\n\\t\\t\\t\\t\\t\\tvertexDesc.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tsemantic: semantic,\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponents: stream.componentCount,\\n\\t\\t\\t\\t\\t\\t\\t\\ttype: stream.dataType,\\n\\t\\t\\t\\t\\t\\t\\t\\tnormalize: stream.dataTypeNormalize,\\n\\t\\t\\t\\t\\t\\t\\t\\tasInt: stream.asInt\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn new VertexFormat(this.device, vertexDesc, vertexCount);\\n\\t\\t}\\n\\t\\t_updateVertexBuffer() {\\n\\t\\t\\t\\tif (!this.vertexBuffer) {\\n\\t\\t\\t\\t\\t\\tconst allocateVertexCount = this._geometryData.maxVertices;\\n\\t\\t\\t\\t\\t\\tconst format = this._buildVertexFormat(allocateVertexCount);\\n\\t\\t\\t\\t\\t\\tthis.vertexBuffer = new VertexBuffer(this.device, format, allocateVertexCount, {\\n\\t\\t\\t\\t\\t\\t\\t\\tusage: this._geometryData.verticesUsage,\\n\\t\\t\\t\\t\\t\\t\\t\\tstorage: this._storageVertex\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst iterator = new VertexIterator(this.vertexBuffer);\\n\\t\\t\\t\\tconst numVertices = this._geometryData.vertexCount;\\n\\t\\t\\t\\tfor(const semantic in this._geometryData.vertexStreamDictionary){\\n\\t\\t\\t\\t\\t\\tconst stream = this._geometryData.vertexStreamDictionary[semantic];\\n\\t\\t\\t\\t\\t\\titerator.writeData(semantic, stream.data, numVertices);\\n\\t\\t\\t\\t\\t\\tdelete this._geometryData.vertexStreamDictionary[semantic];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\titerator.end();\\n\\t\\t}\\n\\t\\t_updateIndexBuffer() {\\n\\t\\t\\t\\tif (this.indexBuffer.length <= 0 || !this.indexBuffer[0]) {\\n\\t\\t\\t\\t\\t\\tconst maxVertices = this._geometryData.maxVertices;\\n\\t\\t\\t\\t\\t\\tconst createFormat = maxVertices > 0xffff || maxVertices === 0 ? INDEXFORMAT_UINT32 : INDEXFORMAT_UINT16;\\n\\t\\t\\t\\t\\t\\tconst options = this._storageIndex ? {\\n\\t\\t\\t\\t\\t\\t\\t\\tstorage: true\\n\\t\\t\\t\\t\\t\\t} : undefined;\\n\\t\\t\\t\\t\\t\\tthis.indexBuffer[0] = new IndexBuffer(this.device, createFormat, this._geometryData.maxIndices, this._geometryData.indicesUsage, undefined, options);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst srcIndices = this._geometryData.indices;\\n\\t\\t\\t\\tif (srcIndices) {\\n\\t\\t\\t\\t\\t\\tconst indexBuffer = this.indexBuffer[0];\\n\\t\\t\\t\\t\\t\\tindexBuffer.writeData(srcIndices, this._geometryData.indexCount);\\n\\t\\t\\t\\t\\t\\tthis._geometryData.indices = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tprepareRenderState(renderStyle) {\\n\\t\\t\\t\\tif (renderStyle === RENDERSTYLE_WIREFRAME) {\\n\\t\\t\\t\\t\\t\\tthis.generateWireframe();\\n\\t\\t\\t\\t} else if (renderStyle === RENDERSTYLE_POINTS) {\\n\\t\\t\\t\\t\\t\\tthis.primitive[RENDERSTYLE_POINTS] = {\\n\\t\\t\\t\\t\\t\\t\\t\\ttype: PRIMITIVE_POINTS,\\n\\t\\t\\t\\t\\t\\t\\t\\tbase: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tbaseVertex: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tcount: this.vertexBuffer ? this.vertexBuffer.numVertices : 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tindexed: false\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateRenderStates() {\\n\\t\\t\\t\\tif (this.primitive[RENDERSTYLE_POINTS]) {\\n\\t\\t\\t\\t\\t\\tthis.prepareRenderState(RENDERSTYLE_POINTS);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.primitive[RENDERSTYLE_WIREFRAME]) {\\n\\t\\t\\t\\t\\t\\tthis.prepareRenderState(RENDERSTYLE_WIREFRAME);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgenerateWireframe() {\\n\\t\\t\\t\\tthis._destroyIndexBuffer(RENDERSTYLE_WIREFRAME);\\n\\t\\t\\t\\tconst numVertices = this.vertexBuffer.numVertices;\\n\\t\\t\\t\\tlet lines;\\n\\t\\t\\t\\tlet format;\\n\\t\\t\\t\\tif (this.indexBuffer.length > 0 && this.indexBuffer[0]) {\\n\\t\\t\\t\\t\\t\\tconst offsets = [\\n\\t\\t\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t1\\n\\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\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t2\\n\\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\\t\\t\\t2,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t\\t\\tconst base = this.primitive[RENDERSTYLE_SOLID].base;\\n\\t\\t\\t\\t\\t\\tconst count = this.primitive[RENDERSTYLE_SOLID].count;\\n\\t\\t\\t\\t\\t\\tconst baseVertex = this.primitive[RENDERSTYLE_SOLID].baseVertex || 0;\\n\\t\\t\\t\\t\\t\\tconst indexBuffer = this.indexBuffer[RENDERSTYLE_SOLID];\\n\\t\\t\\t\\t\\t\\tconst indicesArrayType = typedArrayIndexFormats[indexBuffer.format];\\n\\t\\t\\t\\t\\t\\tconst srcIndices = new indicesArrayType(indexBuffer.storage);\\n\\t\\t\\t\\t\\t\\tconst tmpIndices = new indicesArrayType(count * 2);\\n\\t\\t\\t\\t\\t\\tconst seen = new Set();\\n\\t\\t\\t\\t\\t\\tlet len = 0;\\n\\t\\t\\t\\t\\t\\tfor(let j = base; j < base + count; j += 3){\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let k = 0; k < 3; k++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst i1 = srcIndices[j + offsets[k][0]] + baseVertex;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst i2 = srcIndices[j + offsets[k][1]] + baseVertex;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst hash = i1 > i2 ? i2 * numVertices + i1 : i1 * numVertices + i2;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!seen.has(hash)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tseen.add(hash);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttmpIndices[len++] = i1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttmpIndices[len++] = i2;\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tseen.clear();\\n\\t\\t\\t\\t\\t\\tformat = indexBuffer.format;\\n\\t\\t\\t\\t\\t\\tlines = tmpIndices.slice(0, len);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst safeNumVertices = numVertices - numVertices % 3;\\n\\t\\t\\t\\t\\t\\tconst count = safeNumVertices / 3 * 6;\\n\\t\\t\\t\\t\\t\\tformat = count > 65535 ? INDEXFORMAT_UINT32 : INDEXFORMAT_UINT16;\\n\\t\\t\\t\\t\\t\\tlines = count > 65535 ? new Uint32Array(count) : new Uint16Array(count);\\n\\t\\t\\t\\t\\t\\tlet idx = 0;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < safeNumVertices; i += 3){\\n\\t\\t\\t\\t\\t\\t\\t\\tlines[idx++] = i;\\n\\t\\t\\t\\t\\t\\t\\t\\tlines[idx++] = i + 1;\\n\\t\\t\\t\\t\\t\\t\\t\\tlines[idx++] = i + 1;\\n\\t\\t\\t\\t\\t\\t\\t\\tlines[idx++] = i + 2;\\n\\t\\t\\t\\t\\t\\t\\t\\tlines[idx++] = i + 2;\\n\\t\\t\\t\\t\\t\\t\\t\\tlines[idx++] = i;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst wireBuffer = new IndexBuffer(this.vertexBuffer.device, format, lines.length, BUFFER_STATIC, lines.buffer);\\n\\t\\t\\t\\tthis.primitive[RENDERSTYLE_WIREFRAME] = {\\n\\t\\t\\t\\t\\t\\ttype: PRIMITIVE_LINES,\\n\\t\\t\\t\\t\\t\\tbase: 0,\\n\\t\\t\\t\\t\\t\\tbaseVertex: 0,\\n\\t\\t\\t\\t\\t\\tcount: lines.length,\\n\\t\\t\\t\\t\\t\\tindexed: true\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.indexBuffer[RENDERSTYLE_WIREFRAME] = wireBuffer;\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice, options){\\n\\t\\t\\t\\tsuper(), this.indexBuffer = [\\n\\t\\t\\t\\t\\t\\tnull\\n\\t\\t\\t\\t], this.vertexBuffer = null, this.primitive = [\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\ttype: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tbase: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tbaseVertex: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tcount: 0\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t], this.skin = null, this.boneAabb = null, this._aabbVer = 0, this._aabb = new BoundingBox(), this._geometryData = null, this._morph = null, this._storageIndex = false, this._storageVertex = false;\\n\\t\\t\\t\\tthis.id = id$4++;\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t\\t\\tthis._storageIndex = options?.storageIndex || false;\\n\\t\\t\\t\\tthis._storageVertex = options?.storageVertex || false;\\n\\t\\t}\\n}\\n\\nconst defaultMaterialDeviceCache = new DeviceCache();\\nfunction getDefaultMaterial(device) {\\n\\t\\tconst material = defaultMaterialDeviceCache.get(device);\\n\\t\\treturn material;\\n}\\nfunction setDefaultMaterial(device, material) {\\n\\t\\tdefaultMaterialDeviceCache.get(device, ()=>{\\n\\t\\t\\t\\treturn material;\\n\\t\\t});\\n}\\n\\nclass RefCountedCache {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.cache.forEach((refCount, object)=>{\\n\\t\\t\\t\\t\\t\\tobject.destroy();\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.cache.clear();\\n\\t\\t}\\n\\t\\tincRef(object) {\\n\\t\\t\\t\\tconst refCount = (this.cache.get(object) || 0) + 1;\\n\\t\\t\\t\\tthis.cache.set(object, refCount);\\n\\t\\t}\\n\\t\\tdecRef(object) {\\n\\t\\t\\t\\tif (object) {\\n\\t\\t\\t\\t\\t\\tlet refCount = this.cache.get(object);\\n\\t\\t\\t\\t\\t\\tif (refCount) {\\n\\t\\t\\t\\t\\t\\t\\t\\trefCount--;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (refCount === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.cache.delete(object);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tobject.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.cache.set(object, refCount);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.cache = new Map();\\n\\t\\t}\\n}\\n\\nclass LightmapCache {\\n\\t\\tstatic incRef(texture) {\\n\\t\\t\\t\\tthis.cache.incRef(texture);\\n\\t\\t}\\n\\t\\tstatic decRef(texture) {\\n\\t\\t\\t\\tthis.cache.decRef(texture);\\n\\t\\t}\\n\\t\\tstatic destroy() {\\n\\t\\t\\t\\tthis.cache.destroy();\\n\\t\\t}\\n}\\nLightmapCache.cache = new RefCountedCache();\\n\\nclass PickerId {\\n\\t\\tstatic get() {\\n\\t\\t\\t\\treturn this._counter++;\\n\\t\\t}\\n}\\nPickerId._counter = 0;\\n\\nconst _tmpAabb = new BoundingBox();\\nconst _tempBoneAabb = new BoundingBox();\\nconst _tempSphere = new BoundingSphere();\\nconst _meshSet = new Set();\\nconst lookupHashes = new Uint32Array(4);\\nclass InstancingData {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tif (this._destroyVertexBuffer) {\\n\\t\\t\\t\\t\\t\\tthis.vertexBuffer?.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.vertexBuffer = null;\\n\\t\\t}\\n\\t\\tconstructor(numObjects){\\n\\t\\t\\t\\tthis.vertexBuffer = null;\\n\\t\\t\\t\\tthis._destroyVertexBuffer = false;\\n\\t\\t\\t\\tthis.count = numObjects;\\n\\t\\t}\\n}\\nclass ShaderInstance {\\n\\t\\tgetBindGroup(device) {\\n\\t\\t\\t\\tif (!this.bindGroup) {\\n\\t\\t\\t\\t\\t\\tconst shader = this.shader;\\n\\t\\t\\t\\t\\t\\tconst bindGroupFormat = shader.meshBindGroupFormat;\\n\\t\\t\\t\\t\\t\\tthis.bindGroup = new BindGroup(device, bindGroupFormat);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.bindGroup;\\n\\t\\t}\\n\\t\\tgetUniformBuffer(device) {\\n\\t\\t\\t\\tif (!this.uniformBuffer) {\\n\\t\\t\\t\\t\\t\\tconst shader = this.shader;\\n\\t\\t\\t\\t\\t\\tconst ubFormat = shader.meshUniformBufferFormat;\\n\\t\\t\\t\\t\\t\\tthis.uniformBuffer = new UniformBuffer(device, ubFormat, false);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.uniformBuffer;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.bindGroup?.destroy();\\n\\t\\t\\t\\tthis.bindGroup = null;\\n\\t\\t\\t\\tthis.uniformBuffer?.destroy();\\n\\t\\t\\t\\tthis.uniformBuffer = null;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.bindGroup = null;\\n\\t\\t\\t\\tthis.uniformBuffer = null;\\n\\t\\t}\\n}\\nclass MeshInstance {\\n\\t\\tset drawBucket(bucket) {\\n\\t\\t\\t\\tthis._drawBucket = Math.floor(bucket) & 0xff;\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t\\tget drawBucket() {\\n\\t\\t\\t\\treturn this._drawBucket;\\n\\t\\t}\\n\\t\\tset renderStyle(renderStyle) {\\n\\t\\t\\t\\tthis._renderStyle = renderStyle;\\n\\t\\t\\t\\tthis.mesh.prepareRenderState(renderStyle);\\n\\t\\t}\\n\\t\\tget renderStyle() {\\n\\t\\t\\t\\treturn this._renderStyle;\\n\\t\\t}\\n\\t\\tset mesh(mesh) {\\n\\t\\t\\t\\tif (mesh === this._mesh) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._mesh) {\\n\\t\\t\\t\\t\\t\\tthis._mesh.decRefCount();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._mesh = mesh;\\n\\t\\t\\t\\tif (mesh) {\\n\\t\\t\\t\\t\\t\\tmesh.incRefCount();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget mesh() {\\n\\t\\t\\t\\treturn this._mesh;\\n\\t\\t}\\n\\t\\tset aabb(aabb) {\\n\\t\\t\\t\\tthis._aabb = aabb;\\n\\t\\t}\\n\\t\\tget aabb() {\\n\\t\\t\\t\\tif (!this._updateAabb) {\\n\\t\\t\\t\\t\\t\\treturn this._aabb;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._updateAabbFunc) {\\n\\t\\t\\t\\t\\t\\treturn this._updateAabbFunc(this._aabb);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet localAabb = this._customAabb;\\n\\t\\t\\t\\tlet toWorldSpace = !!localAabb;\\n\\t\\t\\t\\tif (!localAabb) {\\n\\t\\t\\t\\t\\t\\tlocalAabb = _tmpAabb;\\n\\t\\t\\t\\t\\t\\tif (this.skinInstance) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this.mesh.boneAabb) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst morphTargets = this._morphInstance ? this._morphInstance.morph._targets : null;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.mesh._initBoneAabbs(morphTargets);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst boneUsed = this.mesh.boneUsed;\\n\\t\\t\\t\\t\\t\\t\\t\\tlet first = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this.mesh.boneAabb.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (boneUsed[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_tempBoneAabb.setFromTransformedAabb(this.mesh.boneAabb[i], this.skinInstance.matrices[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (first) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfirst = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlocalAabb.center.copy(_tempBoneAabb.center);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlocalAabb.halfExtents.copy(_tempBoneAabb.halfExtents);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlocalAabb.add(_tempBoneAabb);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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\\ttoWorldSpace = true;\\n\\t\\t\\t\\t\\t\\t} else if (this.node._aabbVer !== this._aabbVer || this.mesh._aabbVer !== this._aabbMeshVer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.mesh) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlocalAabb.center.copy(this.mesh.aabb.center);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlocalAabb.halfExtents.copy(this.mesh.aabb.halfExtents);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlocalAabb.center.set(0, 0, 0);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlocalAabb.halfExtents.set(0, 0, 0);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.mesh && this.mesh.morph) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst morphAabb = this.mesh.morph.aabb;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlocalAabb._expand(morphAabb.getMin(), morphAabb.getMax());\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\ttoWorldSpace = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._aabbVer = this.node._aabbVer;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._aabbMeshVer = this.mesh._aabbVer;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (toWorldSpace) {\\n\\t\\t\\t\\t\\t\\tthis._aabb.setFromTransformedAabb(localAabb, this.node.getWorldTransform());\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._aabb;\\n\\t\\t}\\n\\t\\tclearShaders() {\\n\\t\\t\\t\\tthis._shaderCache.forEach((shaderInstance)=>{\\n\\t\\t\\t\\t\\t\\tshaderInstance.destroy();\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis._shaderCache.clear();\\n\\t\\t}\\n\\t\\tgetShaderInstance(shaderPass, lightHash, scene, cameraShaderParams, viewUniformFormat, viewBindGroupFormat, sortedLights) {\\n\\t\\t\\t\\tconst shaderDefs = this._shaderDefs;\\n\\t\\t\\t\\tlookupHashes[0] = shaderPass;\\n\\t\\t\\t\\tlookupHashes[1] = lightHash;\\n\\t\\t\\t\\tlookupHashes[2] = shaderDefs;\\n\\t\\t\\t\\tlookupHashes[3] = cameraShaderParams.hash;\\n\\t\\t\\t\\tconst hash = hash32Fnv1a(lookupHashes);\\n\\t\\t\\t\\tlet shaderInstance = this._shaderCache.get(hash);\\n\\t\\t\\t\\tif (!shaderInstance) {\\n\\t\\t\\t\\t\\t\\tconst mat = this._material;\\n\\t\\t\\t\\t\\t\\tshaderInstance = new ShaderInstance();\\n\\t\\t\\t\\t\\t\\tshaderInstance.shader = mat.variants.get(hash);\\n\\t\\t\\t\\t\\t\\tshaderInstance.hashes = new Uint32Array(lookupHashes);\\n\\t\\t\\t\\t\\t\\tif (!shaderInstance.shader) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst shader = mat.getShaderVariant({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice: this.mesh.device,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscene: scene,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tobjDefs: shaderDefs,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcameraShaderParams: cameraShaderParams,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpass: shaderPass,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsortedLights: sortedLights,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tviewUniformFormat: viewUniformFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tviewBindGroupFormat: viewBindGroupFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvertexFormat: this.mesh.vertexBuffer?.format\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tmat.variants.set(hash, shader);\\n\\t\\t\\t\\t\\t\\t\\t\\tshaderInstance.shader = shader;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._shaderCache.set(hash, shaderInstance);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn shaderInstance;\\n\\t\\t}\\n\\t\\tset material(material) {\\n\\t\\t\\t\\tthis.clearShaders();\\n\\t\\t\\t\\tconst prevMat = this._material;\\n\\t\\t\\t\\tif (prevMat) {\\n\\t\\t\\t\\t\\t\\tprevMat.removeMeshInstanceRef(this);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._material = material;\\n\\t\\t\\t\\tif (material) {\\n\\t\\t\\t\\t\\t\\tmaterial.addMeshInstanceRef(this);\\n\\t\\t\\t\\t\\t\\tthis.transparent = material.transparent;\\n\\t\\t\\t\\t\\t\\tthis.updateKey();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget material() {\\n\\t\\t\\t\\treturn this._material;\\n\\t\\t}\\n\\t\\t_updateShaderDefs(shaderDefs) {\\n\\t\\t\\t\\tif (shaderDefs !== this._shaderDefs) {\\n\\t\\t\\t\\t\\t\\tthis._shaderDefs = shaderDefs;\\n\\t\\t\\t\\t\\t\\tthis.clearShaders();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tset calculateSortDistance(calculateSortDistance) {\\n\\t\\t\\t\\tthis._calculateSortDistance = calculateSortDistance;\\n\\t\\t}\\n\\t\\tget calculateSortDistance() {\\n\\t\\t\\t\\treturn this._calculateSortDistance;\\n\\t\\t}\\n\\t\\tset receiveShadow(val) {\\n\\t\\t\\t\\tif (this._receiveShadow !== val) {\\n\\t\\t\\t\\t\\t\\tthis._receiveShadow = val;\\n\\t\\t\\t\\t\\t\\tthis._updateShaderDefs(val ? this._shaderDefs & ~SHADERDEF_NOSHADOW : this._shaderDefs | SHADERDEF_NOSHADOW);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget receiveShadow() {\\n\\t\\t\\t\\treturn this._receiveShadow;\\n\\t\\t}\\n\\t\\tset batching(val) {\\n\\t\\t\\t\\tthis._updateShaderDefs(val ? this._shaderDefs | SHADERDEF_BATCH : this._shaderDefs & ~SHADERDEF_BATCH);\\n\\t\\t}\\n\\t\\tget batching() {\\n\\t\\t\\t\\treturn (this._shaderDefs & SHADERDEF_BATCH) !== 0;\\n\\t\\t}\\n\\t\\tset skinInstance(val) {\\n\\t\\t\\t\\tthis._skinInstance = val;\\n\\t\\t\\t\\tthis._updateShaderDefs(val ? this._shaderDefs | SHADERDEF_SKIN : this._shaderDefs & ~SHADERDEF_SKIN);\\n\\t\\t\\t\\tthis._setupSkinUpdate();\\n\\t\\t}\\n\\t\\tget skinInstance() {\\n\\t\\t\\t\\treturn this._skinInstance;\\n\\t\\t}\\n\\t\\tset morphInstance(val) {\\n\\t\\t\\t\\tthis._morphInstance?.destroy();\\n\\t\\t\\t\\tthis._morphInstance = val;\\n\\t\\t\\t\\tlet shaderDefs = this._shaderDefs;\\n\\t\\t\\t\\tshaderDefs = val && val.morph.morphPositions ? shaderDefs | SHADERDEF_MORPH_POSITION : shaderDefs & ~SHADERDEF_MORPH_POSITION;\\n\\t\\t\\t\\tshaderDefs = val && val.morph.morphNormals ? shaderDefs | SHADERDEF_MORPH_NORMAL : shaderDefs & ~SHADERDEF_MORPH_NORMAL;\\n\\t\\t\\t\\tshaderDefs = val && val.morph.intRenderFormat ? shaderDefs | SHADERDEF_MORPH_TEXTURE_BASED_INT : shaderDefs & ~SHADERDEF_MORPH_TEXTURE_BASED_INT;\\n\\t\\t\\t\\tthis._updateShaderDefs(shaderDefs);\\n\\t\\t}\\n\\t\\tget morphInstance() {\\n\\t\\t\\t\\treturn this._morphInstance;\\n\\t\\t}\\n\\t\\tset screenSpace(val) {\\n\\t\\t\\t\\tif (this._screenSpace !== val) {\\n\\t\\t\\t\\t\\t\\tthis._screenSpace = val;\\n\\t\\t\\t\\t\\t\\tthis._updateShaderDefs(val ? this._shaderDefs | SHADERDEF_SCREENSPACE : this._shaderDefs & ~SHADERDEF_SCREENSPACE);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget screenSpace() {\\n\\t\\t\\t\\treturn this._screenSpace;\\n\\t\\t}\\n\\t\\tset key(val) {\\n\\t\\t\\t\\tthis._sortKeyForward = val;\\n\\t\\t}\\n\\t\\tget key() {\\n\\t\\t\\t\\treturn this._sortKeyForward;\\n\\t\\t}\\n\\t\\tset mask(val) {\\n\\t\\t\\t\\tconst toggles = this._shaderDefs & 0x0000FFFF;\\n\\t\\t\\t\\tthis._updateShaderDefs(toggles | val << 16);\\n\\t\\t}\\n\\t\\tget mask() {\\n\\t\\t\\t\\treturn this._shaderDefs >> 16;\\n\\t\\t}\\n\\t\\tset instancingCount(value) {\\n\\t\\t\\t\\tif (this.instancingData) {\\n\\t\\t\\t\\t\\t\\tthis.instancingData.count = value;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget instancingCount() {\\n\\t\\t\\t\\treturn this.instancingData ? this.instancingData.count : 0;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tconst mesh = this.mesh;\\n\\t\\t\\t\\tif (mesh) {\\n\\t\\t\\t\\t\\t\\tthis.mesh = null;\\n\\t\\t\\t\\t\\t\\tif (mesh.refCount < 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh.destroy();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.setRealtimeLightmap(MeshInstance.lightmapParamNames[0], null);\\n\\t\\t\\t\\tthis.setRealtimeLightmap(MeshInstance.lightmapParamNames[1], null);\\n\\t\\t\\t\\tthis._skinInstance?.destroy();\\n\\t\\t\\t\\tthis._skinInstance = null;\\n\\t\\t\\t\\tthis.morphInstance?.destroy();\\n\\t\\t\\t\\tthis.morphInstance = null;\\n\\t\\t\\t\\tthis.clearShaders();\\n\\t\\t\\t\\tthis.material = null;\\n\\t\\t\\t\\tthis.instancingData?.destroy();\\n\\t\\t\\t\\tthis.destroyDrawCommands();\\n\\t\\t}\\n\\t\\tdestroyDrawCommands() {\\n\\t\\t\\t\\tif (this.drawCommands) {\\n\\t\\t\\t\\t\\t\\tfor (const cmd of this.drawCommands.values()){\\n\\t\\t\\t\\t\\t\\t\\t\\tcmd?.destroy();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.drawCommands = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tstatic _prepareRenderStyleForArray(meshInstances, renderStyle) {\\n\\t\\t\\t\\tif (meshInstances) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tmeshInstances[i]._renderStyle = renderStyle;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst mesh = meshInstances[i].mesh;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!_meshSet.has(mesh)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_meshSet.add(mesh);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmesh.prepareRenderState(renderStyle);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t_meshSet.clear();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_isVisible(camera) {\\n\\t\\t\\t\\tif (this.visible) {\\n\\t\\t\\t\\t\\t\\tif (this.isVisibleFunc) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn this.isVisibleFunc(camera);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t_tempSphere.center = this.aabb.center;\\n\\t\\t\\t\\t\\t\\t_tempSphere.radius = this._aabb.halfExtents.length();\\n\\t\\t\\t\\t\\t\\treturn camera.frustum.containsSphere(_tempSphere) > 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tupdateKey() {\\n\\t\\t\\t\\tconst { material } = this;\\n\\t\\t\\t\\tthis._sortKeyForward = this._drawBucket << 23 | (material.alphaToCoverage || material.alphaTest ? 0x400000 : 0) | material.id & 0x3fffff;\\n\\t\\t}\\n\\t\\tsetInstancing(vertexBuffer, cull = false) {\\n\\t\\t\\t\\tif (vertexBuffer) {\\n\\t\\t\\t\\t\\t\\tthis.instancingData = new InstancingData(vertexBuffer.numVertices);\\n\\t\\t\\t\\t\\t\\tthis.instancingData.vertexBuffer = vertexBuffer;\\n\\t\\t\\t\\t\\t\\tvertexBuffer.format.instancing = true;\\n\\t\\t\\t\\t\\t\\tthis.cull = cull;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.instancingData = null;\\n\\t\\t\\t\\t\\t\\tthis.cull = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._updateShaderDefs(vertexBuffer ? this._shaderDefs | SHADERDEF_INSTANCING : this._shaderDefs & ~SHADERDEF_INSTANCING);\\n\\t\\t}\\n\\t\\tsetIndirect(camera, slot, count = 1) {\\n\\t\\t\\t\\tconst key = camera?.camera ?? null;\\n\\t\\t\\t\\tif (slot === -1) {\\n\\t\\t\\t\\t\\t\\tthis._deleteDrawCommandsKey(key);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.drawCommands ?? (this.drawCommands = new Map());\\n\\t\\t\\t\\t\\t\\tconst cmd = this.drawCommands.get(key) ?? new DrawCommands(this.mesh.device);\\n\\t\\t\\t\\t\\t\\tcmd.slotIndex = slot;\\n\\t\\t\\t\\t\\t\\tcmd.update(count);\\n\\t\\t\\t\\t\\t\\tthis.drawCommands.set(key, cmd);\\n\\t\\t\\t\\t\\t\\tconst device = this.mesh.device;\\n\\t\\t\\t\\t\\t\\tdevice.mapsToClear.add(this.drawCommands);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetMultiDraw(camera, maxCount = 1) {\\n\\t\\t\\t\\tconst key = camera?.camera ?? null;\\n\\t\\t\\t\\tlet cmd;\\n\\t\\t\\t\\tif (maxCount === 0) {\\n\\t\\t\\t\\t\\t\\tthis._deleteDrawCommandsKey(key);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.drawCommands ?? (this.drawCommands = new Map());\\n\\t\\t\\t\\t\\t\\tcmd = this.drawCommands.get(key);\\n\\t\\t\\t\\t\\t\\tif (!cmd) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst indexBuffer = this.mesh.indexBuffer?.[0];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst indexFormat = indexBuffer?.format;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst indexSizeBytes = indexFormat !== undefined ? indexFormatByteSize[indexFormat] : 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tcmd = new DrawCommands(this.mesh.device, indexSizeBytes);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.drawCommands.set(key, cmd);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcmd.allocate(maxCount);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn cmd;\\n\\t\\t}\\n\\t\\t_deleteDrawCommandsKey(key) {\\n\\t\\t\\t\\tconst cmds = this.drawCommands;\\n\\t\\t\\t\\tif (cmds) {\\n\\t\\t\\t\\t\\t\\tconst cmd = cmds.get(key);\\n\\t\\t\\t\\t\\t\\tcmd?.destroy();\\n\\t\\t\\t\\t\\t\\tcmds.delete(key);\\n\\t\\t\\t\\t\\t\\tif (cmds.size === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.destroyDrawCommands();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetDrawCommands(camera) {\\n\\t\\t\\t\\tconst cmds = this.drawCommands;\\n\\t\\t\\t\\tif (!cmds) return undefined;\\n\\t\\t\\t\\treturn cmds.get(camera) ?? cmds.get(null);\\n\\t\\t}\\n\\t\\tgetIndirectMetaData() {\\n\\t\\t\\t\\tconst prim = this.mesh?.primitive[this.renderStyle];\\n\\t\\t\\t\\tconst data = this.meshMetaData ?? (this.meshMetaData = new Int32Array(4));\\n\\t\\t\\t\\tdata[0] = prim.count;\\n\\t\\t\\t\\tdata[1] = prim.base;\\n\\t\\t\\t\\tdata[2] = prim.baseVertex;\\n\\t\\t\\t\\treturn data;\\n\\t\\t}\\n\\t\\tensureMaterial(device) {\\n\\t\\t\\t\\tif (!this.material) {\\n\\t\\t\\t\\t\\t\\tthis.material = getDefaultMaterial(device);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tclearParameters() {\\n\\t\\t\\t\\tthis.parameters = {};\\n\\t\\t}\\n\\t\\tgetParameters() {\\n\\t\\t\\t\\treturn this.parameters;\\n\\t\\t}\\n\\t\\tgetParameter(name) {\\n\\t\\t\\t\\treturn this.parameters[name];\\n\\t\\t}\\n\\t\\tsetParameter(name, data, passFlags = 0xFFFFFFFF) {\\n\\t\\t\\t\\tconst param = this.parameters[name];\\n\\t\\t\\t\\tif (param) {\\n\\t\\t\\t\\t\\t\\tparam.data = data;\\n\\t\\t\\t\\t\\t\\tparam.passFlags = passFlags;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.parameters[name] = {\\n\\t\\t\\t\\t\\t\\t\\t\\tscopeId: null,\\n\\t\\t\\t\\t\\t\\t\\t\\tdata: data,\\n\\t\\t\\t\\t\\t\\t\\t\\tpassFlags: passFlags\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetRealtimeLightmap(name, texture) {\\n\\t\\t\\t\\tconst old = this.getParameter(name);\\n\\t\\t\\t\\tif (old === texture) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (old) {\\n\\t\\t\\t\\t\\t\\tLightmapCache.decRef(old.data);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (texture) {\\n\\t\\t\\t\\t\\t\\tLightmapCache.incRef(texture);\\n\\t\\t\\t\\t\\t\\tthis.setParameter(name, texture);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.deleteParameter(name);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdeleteParameter(name) {\\n\\t\\t\\t\\tif (this.parameters[name]) {\\n\\t\\t\\t\\t\\t\\tdelete this.parameters[name];\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetParameters(device, passFlag) {\\n\\t\\t\\t\\tconst parameters = this.parameters;\\n\\t\\t\\t\\tfor(const paramName in parameters){\\n\\t\\t\\t\\t\\t\\tconst parameter = parameters[paramName];\\n\\t\\t\\t\\t\\t\\tif (parameter.passFlags & passFlag) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!parameter.scopeId) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tparameter.scopeId = device.scope.resolve(paramName);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tparameter.scopeId.setValue(parameter.data);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetLightmapped(value) {\\n\\t\\t\\t\\tif (value) {\\n\\t\\t\\t\\t\\t\\tthis.mask = (this.mask | MASK_AFFECT_LIGHTMAPPED) & -6;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.setRealtimeLightmap(MeshInstance.lightmapParamNames[0], null);\\n\\t\\t\\t\\t\\t\\tthis.setRealtimeLightmap(MeshInstance.lightmapParamNames[1], null);\\n\\t\\t\\t\\t\\t\\tthis._shaderDefs &= -4289;\\n\\t\\t\\t\\t\\t\\tthis.mask = (this.mask | MASK_AFFECT_DYNAMIC) & -7;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetCustomAabb(aabb) {\\n\\t\\t\\t\\tif (aabb) {\\n\\t\\t\\t\\t\\t\\tif (this._customAabb) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._customAabb.copy(aabb);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._customAabb = aabb.clone();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._customAabb = null;\\n\\t\\t\\t\\t\\t\\tthis._aabbVer = -1;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._setupSkinUpdate();\\n\\t\\t}\\n\\t\\t_setupSkinUpdate() {\\n\\t\\t\\t\\tif (this._skinInstance) {\\n\\t\\t\\t\\t\\t\\tthis._skinInstance._updateBeforeCull = !this._customAabb;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(mesh, material, node = null){\\n\\t\\t\\t\\tthis.castShadow = false;\\n\\t\\t\\t\\tthis.shadowCascadeMask = SHADOW_CASCADE_ALL;\\n\\t\\t\\t\\tthis.cull = true;\\n\\t\\t\\t\\tthis.drawOrder = 0;\\n\\t\\t\\t\\tthis._drawBucket = 127;\\n\\t\\t\\t\\tthis.visible = true;\\n\\t\\t\\t\\tthis.visibleThisFrame = false;\\n\\t\\t\\t\\tthis.flipFacesFactor = 1;\\n\\t\\t\\t\\tthis.gsplatInstance = null;\\n\\t\\t\\t\\tthis.id = PickerId.get();\\n\\t\\t\\t\\tthis.isVisibleFunc = null;\\n\\t\\t\\t\\tthis.instancingData = null;\\n\\t\\t\\t\\tthis.indirectData = null;\\n\\t\\t\\t\\tthis.drawCommands = null;\\n\\t\\t\\t\\tthis.meshMetaData = null;\\n\\t\\t\\t\\tthis.parameters = {};\\n\\t\\t\\t\\tthis.pick = true;\\n\\t\\t\\t\\tthis.stencilFront = null;\\n\\t\\t\\t\\tthis.stencilBack = null;\\n\\t\\t\\t\\tthis.transparent = false;\\n\\t\\t\\t\\tthis._aabb = new BoundingBox();\\n\\t\\t\\t\\tthis._aabbVer = -1;\\n\\t\\t\\t\\tthis._aabbMeshVer = -1;\\n\\t\\t\\t\\tthis._customAabb = null;\\n\\t\\t\\t\\tthis._updateAabb = true;\\n\\t\\t\\t\\tthis._updateAabbFunc = null;\\n\\t\\t\\t\\tthis._sortKeyShadow = 0;\\n\\t\\t\\t\\tthis._sortKeyForward = 0;\\n\\t\\t\\t\\tthis._sortKeyDynamic = 0;\\n\\t\\t\\t\\tthis._layer = LAYER_WORLD;\\n\\t\\t\\t\\tthis._material = null;\\n\\t\\t\\t\\tthis._skinInstance = null;\\n\\t\\t\\t\\tthis._morphInstance = null;\\n\\t\\t\\t\\tthis._receiveShadow = true;\\n\\t\\t\\t\\tthis._renderStyle = RENDERSTYLE_SOLID;\\n\\t\\t\\t\\tthis._screenSpace = false;\\n\\t\\t\\t\\tthis._shaderCache = new Map();\\n\\t\\t\\t\\tthis._shaderDefs = MASK_AFFECT_DYNAMIC << 16;\\n\\t\\t\\t\\tthis._calculateSortDistance = null;\\n\\t\\t\\t\\tthis.node = node;\\n\\t\\t\\t\\tthis._mesh = mesh;\\n\\t\\t\\t\\tmesh.incRefCount();\\n\\t\\t\\t\\tthis.material = material;\\n\\t\\t\\t\\tif (mesh.vertexBuffer) {\\n\\t\\t\\t\\t\\t\\tconst format = mesh.vertexBuffer.format;\\n\\t\\t\\t\\t\\t\\tthis._shaderDefs |= format.hasUv0 ? SHADERDEF_UV0 : 0;\\n\\t\\t\\t\\t\\t\\tthis._shaderDefs |= format.hasUv1 ? SHADERDEF_UV1 : 0;\\n\\t\\t\\t\\t\\t\\tthis._shaderDefs |= format.hasColor ? SHADERDEF_VCOLOR : 0;\\n\\t\\t\\t\\t\\t\\tthis._shaderDefs |= format.hasTangents ? SHADERDEF_TANGENTS : 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n}\\nMeshInstance.lightmapParamNames = [\\n\\t\\t'texture_lightMap',\\n\\t\\t'texture_dirLightMap'\\n];\\n\\nconst _colorUniformName = 'uSceneColorMap';\\nclass RenderPassColorGrab extends RenderPass {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tsuper.destroy();\\n\\t\\t\\t\\tthis.releaseRenderTarget(this.colorRenderTarget);\\n\\t\\t}\\n\\t\\tshouldReallocate(targetRT, sourceTexture, sourceFormat) {\\n\\t\\t\\t\\tconst targetFormat = targetRT?.colorBuffer.format;\\n\\t\\t\\t\\tif (targetFormat !== sourceFormat) {\\n\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst width = sourceTexture?.width || this.device.width;\\n\\t\\t\\t\\tconst height = sourceTexture?.height || this.device.height;\\n\\t\\t\\t\\treturn !targetRT || width !== targetRT.width || height !== targetRT.height;\\n\\t\\t}\\n\\t\\tallocateRenderTarget(renderTarget, sourceRenderTarget, device, format) {\\n\\t\\t\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: _colorUniformName,\\n\\t\\t\\t\\t\\t\\tformat,\\n\\t\\t\\t\\t\\t\\twidth: sourceRenderTarget ? sourceRenderTarget.colorBuffer.width : device.width,\\n\\t\\t\\t\\t\\t\\theight: sourceRenderTarget ? sourceRenderTarget.colorBuffer.height : device.height,\\n\\t\\t\\t\\t\\t\\tmipmaps: true,\\n\\t\\t\\t\\t\\t\\tminFilter: FILTER_LINEAR_MIPMAP_LINEAR,\\n\\t\\t\\t\\t\\t\\tmagFilter: FILTER_LINEAR,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (renderTarget) {\\n\\t\\t\\t\\t\\t\\trenderTarget.destroyFrameBuffers();\\n\\t\\t\\t\\t\\t\\trenderTarget._colorBuffer = texture;\\n\\t\\t\\t\\t\\t\\trenderTarget._colorBuffers = [\\n\\t\\t\\t\\t\\t\\t\\t\\ttexture\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t\\t\\trenderTarget.evaluateDimensions();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\trenderTarget = new RenderTarget({\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'ColorGrabRT',\\n\\t\\t\\t\\t\\t\\t\\t\\tcolorBuffer: texture,\\n\\t\\t\\t\\t\\t\\t\\t\\tdepth: false,\\n\\t\\t\\t\\t\\t\\t\\t\\tstencil: false,\\n\\t\\t\\t\\t\\t\\t\\t\\tautoResolve: false\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn renderTarget;\\n\\t\\t}\\n\\t\\treleaseRenderTarget(rt) {\\n\\t\\t\\t\\tif (rt) {\\n\\t\\t\\t\\t\\t\\trt.destroyTextureBuffers();\\n\\t\\t\\t\\t\\t\\trt.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tframeUpdate() {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tconst sourceRt = this.source;\\n\\t\\t\\t\\tconst sourceFormat = sourceRt?.colorBuffer.format ?? this.device.backBufferFormat;\\n\\t\\t\\t\\tif (this.shouldReallocate(this.colorRenderTarget, sourceRt?.colorBuffer, sourceFormat)) {\\n\\t\\t\\t\\t\\t\\tthis.releaseRenderTarget(this.colorRenderTarget);\\n\\t\\t\\t\\t\\t\\tthis.colorRenderTarget = this.allocateRenderTarget(this.colorRenderTarget, sourceRt, device, sourceFormat);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst colorBuffer = this.colorRenderTarget.colorBuffer;\\n\\t\\t\\t\\tdevice.scope.resolve(_colorUniformName).setValue(colorBuffer);\\n\\t\\t}\\n\\t\\texecute() {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tconst sourceRt = this.source;\\n\\t\\t\\t\\tconst colorBuffer = this.colorRenderTarget.colorBuffer;\\n\\t\\t\\t\\tif (device.isWebGPU) {\\n\\t\\t\\t\\t\\t\\tdevice.copyRenderTarget(sourceRt, this.colorRenderTarget, true, false);\\n\\t\\t\\t\\t\\t\\tdevice.mipmapRenderer.generate(this.colorRenderTarget.colorBuffer.impl);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tdevice.copyRenderTarget(sourceRt, this.colorRenderTarget, true, false);\\n\\t\\t\\t\\t\\t\\tdevice.activeTexture(device.maxCombinedTextures - 1);\\n\\t\\t\\t\\t\\t\\tdevice.bindTexture(colorBuffer);\\n\\t\\t\\t\\t\\t\\tdevice.gl.generateMipmap(colorBuffer.impl._glTarget);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(...args){\\n\\t\\t\\t\\tsuper(...args), this.colorRenderTarget = null, this.source = null;\\n\\t\\t}\\n}\\n\\nconst _depthUniformName = 'uSceneDepthMap';\\nclass RenderPassDepthGrab extends RenderPass {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tsuper.destroy();\\n\\t\\t\\t\\tthis.releaseRenderTarget(this.depthRenderTarget);\\n\\t\\t}\\n\\t\\tshouldReallocate(targetRT, sourceTexture) {\\n\\t\\t\\t\\tconst width = sourceTexture?.width || this.device.width;\\n\\t\\t\\t\\tconst height = sourceTexture?.height || this.device.height;\\n\\t\\t\\t\\treturn !targetRT || width !== targetRT.width || height !== targetRT.height;\\n\\t\\t}\\n\\t\\tallocateRenderTarget(renderTarget, sourceRenderTarget, device, format, isDepth) {\\n\\t\\t\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: _depthUniformName,\\n\\t\\t\\t\\t\\t\\tformat,\\n\\t\\t\\t\\t\\t\\twidth: sourceRenderTarget ? sourceRenderTarget.colorBuffer.width : device.width,\\n\\t\\t\\t\\t\\t\\theight: sourceRenderTarget ? sourceRenderTarget.colorBuffer.height : device.height,\\n\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (renderTarget) {\\n\\t\\t\\t\\t\\t\\trenderTarget.destroyFrameBuffers();\\n\\t\\t\\t\\t\\t\\tif (isDepth) {\\n\\t\\t\\t\\t\\t\\t\\t\\trenderTarget._depthBuffer = texture;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\trenderTarget._colorBuffer = texture;\\n\\t\\t\\t\\t\\t\\t\\t\\trenderTarget._colorBuffers = [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture\\n\\t\\t\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\trenderTarget.evaluateDimensions();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\trenderTarget = new RenderTarget({\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'DepthGrabRT',\\n\\t\\t\\t\\t\\t\\t\\t\\tcolorBuffer: isDepth ? null : texture,\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthBuffer: isDepth ? texture : null,\\n\\t\\t\\t\\t\\t\\t\\t\\tdepth: !isDepth,\\n\\t\\t\\t\\t\\t\\t\\t\\tstencil: device.supportsStencil,\\n\\t\\t\\t\\t\\t\\t\\t\\tautoResolve: false\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn renderTarget;\\n\\t\\t}\\n\\t\\treleaseRenderTarget(rt) {\\n\\t\\t\\t\\tif (rt) {\\n\\t\\t\\t\\t\\t\\trt.destroyTextureBuffers();\\n\\t\\t\\t\\t\\t\\trt.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tbefore() {\\n\\t\\t\\t\\tconst camera = this.camera;\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tconst destinationRt = camera?.renderTarget ?? device.backBuffer;\\n\\t\\t\\t\\tlet useDepthBuffer = true;\\n\\t\\t\\t\\tlet format = destinationRt.stencil ? PIXELFORMAT_DEPTHSTENCIL : PIXELFORMAT_DEPTH;\\n\\t\\t\\t\\tif (device.isWebGPU) {\\n\\t\\t\\t\\t\\t\\tconst numSamples = destinationRt.samples;\\n\\t\\t\\t\\t\\t\\tif (numSamples > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tformat = PIXELFORMAT_R32F;\\n\\t\\t\\t\\t\\t\\t\\t\\tuseDepthBuffer = false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst sourceTexture = camera.renderTarget?.depthBuffer ?? camera.renderTarget?.colorBuffer;\\n\\t\\t\\t\\tif (this.shouldReallocate(this.depthRenderTarget, sourceTexture)) {\\n\\t\\t\\t\\t\\t\\tthis.releaseRenderTarget(this.depthRenderTarget);\\n\\t\\t\\t\\t\\t\\tthis.depthRenderTarget = this.allocateRenderTarget(this.depthRenderTarget, camera.renderTarget, device, format, useDepthBuffer);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst colorBuffer = useDepthBuffer ? this.depthRenderTarget.depthBuffer : this.depthRenderTarget.colorBuffer;\\n\\t\\t\\t\\tdevice.scope.resolve(_depthUniformName).setValue(colorBuffer);\\n\\t\\t}\\n\\t\\texecute() {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tif (device.isWebGL2 && device.renderTarget.samples > 1) {\\n\\t\\t\\t\\t\\t\\tconst src = device.renderTarget.impl._glFrameBuffer;\\n\\t\\t\\t\\t\\t\\tconst dest = this.depthRenderTarget;\\n\\t\\t\\t\\t\\t\\tdevice.renderTarget = dest;\\n\\t\\t\\t\\t\\t\\tdevice.updateBegin();\\n\\t\\t\\t\\t\\t\\tthis.depthRenderTarget.impl.internalResolve(device, src, dest.impl._glFrameBuffer, this.depthRenderTarget, device.gl.DEPTH_BUFFER_BIT);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tdevice.copyRenderTarget(device.renderTarget, this.depthRenderTarget, false, true);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(device, camera){\\n\\t\\t\\t\\tsuper(device), this.depthRenderTarget = null, this.camera = null;\\n\\t\\t\\t\\tthis.camera = camera;\\n\\t\\t}\\n}\\n\\nclass CameraShaderParams {\\n\\t\\tget hash() {\\n\\t\\t\\t\\tif (this._hash === undefined) {\\n\\t\\t\\t\\t\\t\\tconst key = `${this.gammaCorrection}_${this.toneMapping}_${this.srgbRenderTarget}_${this.fog}_${this.ssaoEnabled}_${this.sceneDepthMapLinear}`;\\n\\t\\t\\t\\t\\t\\tthis._hash = hashCode(key);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._hash;\\n\\t\\t}\\n\\t\\tget defines() {\\n\\t\\t\\t\\tconst defines = this._defines;\\n\\t\\t\\t\\tif (this._definesDirty) {\\n\\t\\t\\t\\t\\t\\tthis._definesDirty = false;\\n\\t\\t\\t\\t\\t\\tdefines.clear();\\n\\t\\t\\t\\t\\t\\tif (this._sceneDepthMapLinear) defines.set('SCENE_DEPTHMAP_LINEAR', '');\\n\\t\\t\\t\\t\\t\\tif (this.shaderOutputGamma === GAMMA_SRGB) defines.set('SCENE_COLORMAP_GAMMA', '');\\n\\t\\t\\t\\t\\t\\tdefines.set('FOG', this._fog.toUpperCase());\\n\\t\\t\\t\\t\\t\\tdefines.set('TONEMAP', tonemapNames[this._toneMapping]);\\n\\t\\t\\t\\t\\t\\tdefines.set('GAMMA', gammaNames[this.shaderOutputGamma]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn defines;\\n\\t\\t}\\n\\t\\tmarkDirty() {\\n\\t\\t\\t\\tthis._hash = undefined;\\n\\t\\t\\t\\tthis._definesDirty = true;\\n\\t\\t}\\n\\t\\tset fog(type) {\\n\\t\\t\\t\\tif (this._fog !== type) {\\n\\t\\t\\t\\t\\t\\tthis._fog = type;\\n\\t\\t\\t\\t\\t\\tthis.markDirty();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget fog() {\\n\\t\\t\\t\\treturn this._fog;\\n\\t\\t}\\n\\t\\tset ssaoEnabled(value) {\\n\\t\\t\\t\\tif (this._ssaoEnabled !== value) {\\n\\t\\t\\t\\t\\t\\tthis._ssaoEnabled = value;\\n\\t\\t\\t\\t\\t\\tthis.markDirty();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget ssaoEnabled() {\\n\\t\\t\\t\\treturn this._ssaoEnabled;\\n\\t\\t}\\n\\t\\tset gammaCorrection(value) {\\n\\t\\t\\t\\tthis._gammaCorrectionAssigned = true;\\n\\t\\t\\t\\tif (this._gammaCorrection !== value) {\\n\\t\\t\\t\\t\\t\\tthis._gammaCorrection = value;\\n\\t\\t\\t\\t\\t\\tthis.markDirty();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget gammaCorrection() {\\n\\t\\t\\t\\treturn this._gammaCorrection;\\n\\t\\t}\\n\\t\\tset toneMapping(value) {\\n\\t\\t\\t\\tif (this._toneMapping !== value) {\\n\\t\\t\\t\\t\\t\\tthis._toneMapping = value;\\n\\t\\t\\t\\t\\t\\tthis.markDirty();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget toneMapping() {\\n\\t\\t\\t\\treturn this._toneMapping;\\n\\t\\t}\\n\\t\\tset srgbRenderTarget(value) {\\n\\t\\t\\t\\tif (this._srgbRenderTarget !== value) {\\n\\t\\t\\t\\t\\t\\tthis._srgbRenderTarget = value;\\n\\t\\t\\t\\t\\t\\tthis.markDirty();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget srgbRenderTarget() {\\n\\t\\t\\t\\treturn this._srgbRenderTarget;\\n\\t\\t}\\n\\t\\tset sceneDepthMapLinear(value) {\\n\\t\\t\\t\\tif (this._sceneDepthMapLinear !== value) {\\n\\t\\t\\t\\t\\t\\tthis._sceneDepthMapLinear = value;\\n\\t\\t\\t\\t\\t\\tthis.markDirty();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget sceneDepthMapLinear() {\\n\\t\\t\\t\\treturn this._sceneDepthMapLinear;\\n\\t\\t}\\n\\t\\tget shaderOutputGamma() {\\n\\t\\t\\t\\tconst gammaOutput = this._gammaCorrection === GAMMA_SRGB && !this._srgbRenderTarget;\\n\\t\\t\\t\\treturn gammaOutput ? GAMMA_SRGB : GAMMA_NONE;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis._gammaCorrection = GAMMA_SRGB;\\n\\t\\t\\t\\tthis._toneMapping = TONEMAP_LINEAR;\\n\\t\\t\\t\\tthis._srgbRenderTarget = false;\\n\\t\\t\\t\\tthis._ssaoEnabled = false;\\n\\t\\t\\t\\tthis._fog = FOG_NONE;\\n\\t\\t\\t\\tthis._sceneDepthMapLinear = false;\\n\\t\\t\\t\\tthis._defines = new Map();\\n\\t\\t\\t\\tthis._definesDirty = true;\\n\\t\\t}\\n}\\n\\nconst _deviceCoord = new Vec3();\\nconst _halfSize = new Vec3();\\nconst _point = new Vec3();\\nconst _invViewProjMat = new Mat4();\\nconst _frustumPoints = [\\n\\t\\tnew Vec3(),\\n\\t\\tnew Vec3(),\\n\\t\\tnew Vec3(),\\n\\t\\tnew Vec3(),\\n\\t\\tnew Vec3(),\\n\\t\\tnew Vec3(),\\n\\t\\tnew Vec3(),\\n\\t\\tnew Vec3()\\n];\\nlet Camera$1 = class Camera {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.renderPassColorGrab?.destroy();\\n\\t\\t\\t\\tthis.renderPassColorGrab = null;\\n\\t\\t\\t\\tthis.renderPassDepthGrab?.destroy();\\n\\t\\t\\t\\tthis.renderPassDepthGrab = null;\\n\\t\\t\\t\\tthis.renderPasses.length = 0;\\n\\t\\t}\\n\\t\\t_storeShaderMatrices(viewProjMat, jitterX, jitterY, renderVersion) {\\n\\t\\t\\t\\tif (this._shaderMatricesVersion !== renderVersion) {\\n\\t\\t\\t\\t\\t\\tthis._shaderMatricesVersion = renderVersion;\\n\\t\\t\\t\\t\\t\\tthis._viewProjPrevious.copy(this._viewProjCurrent ?? viewProjMat);\\n\\t\\t\\t\\t\\t\\tthis._viewProjCurrent ?? (this._viewProjCurrent = new Mat4());\\n\\t\\t\\t\\t\\t\\tthis._viewProjCurrent.copy(viewProjMat);\\n\\t\\t\\t\\t\\t\\tthis._viewProjInverse.invert(viewProjMat);\\n\\t\\t\\t\\t\\t\\tthis._jitters[2] = this._jitters[0];\\n\\t\\t\\t\\t\\t\\tthis._jitters[3] = this._jitters[1];\\n\\t\\t\\t\\t\\t\\tthis._jitters[0] = jitterX;\\n\\t\\t\\t\\t\\t\\tthis._jitters[1] = jitterY;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget fullSizeClearRect() {\\n\\t\\t\\t\\tconst rect = this._scissorRectClear ? this.scissorRect : this._rect;\\n\\t\\t\\t\\treturn rect.x === 0 && rect.y === 0 && rect.z === 1 && rect.w === 1;\\n\\t\\t}\\n\\t\\tset aspectRatio(newValue) {\\n\\t\\t\\t\\tif (this._aspectRatio !== newValue) {\\n\\t\\t\\t\\t\\t\\tthis._aspectRatio = newValue;\\n\\t\\t\\t\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget aspectRatio() {\\n\\t\\t\\t\\treturn this.xr?.active ? this._xrProperties.aspectRatio : this._aspectRatio;\\n\\t\\t}\\n\\t\\tset aspectRatioMode(newValue) {\\n\\t\\t\\t\\tif (this._aspectRatioMode !== newValue) {\\n\\t\\t\\t\\t\\t\\tthis._aspectRatioMode = newValue;\\n\\t\\t\\t\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget aspectRatioMode() {\\n\\t\\t\\t\\treturn this._aspectRatioMode;\\n\\t\\t}\\n\\t\\tset calculateProjection(newValue) {\\n\\t\\t\\t\\tthis._calculateProjection = newValue;\\n\\t\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t}\\n\\t\\tget calculateProjection() {\\n\\t\\t\\t\\treturn this._calculateProjection;\\n\\t\\t}\\n\\t\\tset calculateTransform(newValue) {\\n\\t\\t\\t\\tthis._calculateTransform = newValue;\\n\\t\\t}\\n\\t\\tget calculateTransform() {\\n\\t\\t\\t\\treturn this._calculateTransform;\\n\\t\\t}\\n\\t\\tset clearColor(newValue) {\\n\\t\\t\\t\\tthis._clearColor.copy(newValue);\\n\\t\\t}\\n\\t\\tget clearColor() {\\n\\t\\t\\t\\treturn this._clearColor;\\n\\t\\t}\\n\\t\\tset clearColorBuffer(newValue) {\\n\\t\\t\\t\\tthis._clearColorBuffer = newValue;\\n\\t\\t}\\n\\t\\tget clearColorBuffer() {\\n\\t\\t\\t\\treturn this._clearColorBuffer;\\n\\t\\t}\\n\\t\\tset clearDepth(newValue) {\\n\\t\\t\\t\\tthis._clearDepth = newValue;\\n\\t\\t}\\n\\t\\tget clearDepth() {\\n\\t\\t\\t\\treturn this._clearDepth;\\n\\t\\t}\\n\\t\\tset clearDepthBuffer(newValue) {\\n\\t\\t\\t\\tthis._clearDepthBuffer = newValue;\\n\\t\\t}\\n\\t\\tget clearDepthBuffer() {\\n\\t\\t\\t\\treturn this._clearDepthBuffer;\\n\\t\\t}\\n\\t\\tset clearStencil(newValue) {\\n\\t\\t\\t\\tthis._clearStencil = newValue;\\n\\t\\t}\\n\\t\\tget clearStencil() {\\n\\t\\t\\t\\treturn this._clearStencil;\\n\\t\\t}\\n\\t\\tset clearStencilBuffer(newValue) {\\n\\t\\t\\t\\tthis._clearStencilBuffer = newValue;\\n\\t\\t}\\n\\t\\tget clearStencilBuffer() {\\n\\t\\t\\t\\treturn this._clearStencilBuffer;\\n\\t\\t}\\n\\t\\tset cullFaces(newValue) {\\n\\t\\t\\t\\tthis._cullFaces = newValue;\\n\\t\\t}\\n\\t\\tget cullFaces() {\\n\\t\\t\\t\\treturn this._cullFaces;\\n\\t\\t}\\n\\t\\tset farClip(newValue) {\\n\\t\\t\\t\\tif (this._farClip !== newValue) {\\n\\t\\t\\t\\t\\t\\tthis._farClip = newValue;\\n\\t\\t\\t\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget farClip() {\\n\\t\\t\\t\\treturn this.xr?.active ? this._xrProperties.farClip : this._farClip;\\n\\t\\t}\\n\\t\\tset flipFaces(newValue) {\\n\\t\\t\\t\\tthis._flipFaces = newValue;\\n\\t\\t}\\n\\t\\tget flipFaces() {\\n\\t\\t\\t\\treturn this._flipFaces;\\n\\t\\t}\\n\\t\\tset fov(newValue) {\\n\\t\\t\\t\\tif (this._fov !== newValue) {\\n\\t\\t\\t\\t\\t\\tthis._fov = newValue;\\n\\t\\t\\t\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget fov() {\\n\\t\\t\\t\\treturn this.xr?.active ? this._xrProperties.fov : this._fov;\\n\\t\\t}\\n\\t\\tset frustumCulling(newValue) {\\n\\t\\t\\t\\tthis._frustumCulling = newValue;\\n\\t\\t}\\n\\t\\tget frustumCulling() {\\n\\t\\t\\t\\treturn this._frustumCulling;\\n\\t\\t}\\n\\t\\tset horizontalFov(newValue) {\\n\\t\\t\\t\\tif (this._horizontalFov !== newValue) {\\n\\t\\t\\t\\t\\t\\tthis._horizontalFov = newValue;\\n\\t\\t\\t\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget horizontalFov() {\\n\\t\\t\\t\\treturn this.xr?.active ? this._xrProperties.horizontalFov : this._horizontalFov;\\n\\t\\t}\\n\\t\\tset layers(newValue) {\\n\\t\\t\\t\\tthis._layers = newValue.slice(0);\\n\\t\\t\\t\\tthis._layersSet = new Set(this._layers);\\n\\t\\t}\\n\\t\\tget layers() {\\n\\t\\t\\t\\treturn this._layers;\\n\\t\\t}\\n\\t\\tget layersSet() {\\n\\t\\t\\t\\treturn this._layersSet;\\n\\t\\t}\\n\\t\\tset nearClip(newValue) {\\n\\t\\t\\t\\tif (this._nearClip !== newValue) {\\n\\t\\t\\t\\t\\t\\tthis._nearClip = newValue;\\n\\t\\t\\t\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget nearClip() {\\n\\t\\t\\t\\treturn this.xr?.active ? this._xrProperties.nearClip : this._nearClip;\\n\\t\\t}\\n\\t\\tset node(newValue) {\\n\\t\\t\\t\\tthis._node = newValue;\\n\\t\\t}\\n\\t\\tget node() {\\n\\t\\t\\t\\treturn this._node;\\n\\t\\t}\\n\\t\\tset orthoHeight(newValue) {\\n\\t\\t\\t\\tif (this._orthoHeight !== newValue) {\\n\\t\\t\\t\\t\\t\\tthis._orthoHeight = newValue;\\n\\t\\t\\t\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget orthoHeight() {\\n\\t\\t\\t\\treturn this._orthoHeight;\\n\\t\\t}\\n\\t\\tset projection(newValue) {\\n\\t\\t\\t\\tif (this._projection !== newValue) {\\n\\t\\t\\t\\t\\t\\tthis._projection = newValue;\\n\\t\\t\\t\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget projection() {\\n\\t\\t\\t\\treturn this._projection;\\n\\t\\t}\\n\\t\\tget projectionMatrix() {\\n\\t\\t\\t\\tthis._evaluateProjectionMatrix();\\n\\t\\t\\t\\treturn this._projMat;\\n\\t\\t}\\n\\t\\tset rect(newValue) {\\n\\t\\t\\t\\tthis._rect.copy(newValue);\\n\\t\\t}\\n\\t\\tget rect() {\\n\\t\\t\\t\\treturn this._rect;\\n\\t\\t}\\n\\t\\tset renderTarget(newValue) {\\n\\t\\t\\t\\tthis._renderTarget = newValue;\\n\\t\\t}\\n\\t\\tget renderTarget() {\\n\\t\\t\\t\\treturn this._renderTarget;\\n\\t\\t}\\n\\t\\tset scissorRect(newValue) {\\n\\t\\t\\t\\tthis._scissorRect.copy(newValue);\\n\\t\\t}\\n\\t\\tget scissorRect() {\\n\\t\\t\\t\\treturn this._scissorRect;\\n\\t\\t}\\n\\t\\tget viewMatrix() {\\n\\t\\t\\t\\tif (this._viewMatDirty) {\\n\\t\\t\\t\\t\\t\\tconst wtm = this._node.getWorldTransform();\\n\\t\\t\\t\\t\\t\\tthis._viewMat.copy(wtm).invert();\\n\\t\\t\\t\\t\\t\\tthis._viewMatDirty = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._viewMat;\\n\\t\\t}\\n\\t\\tset aperture(newValue) {\\n\\t\\t\\t\\tthis._aperture = newValue;\\n\\t\\t}\\n\\t\\tget aperture() {\\n\\t\\t\\t\\treturn this._aperture;\\n\\t\\t}\\n\\t\\tset sensitivity(newValue) {\\n\\t\\t\\t\\tthis._sensitivity = newValue;\\n\\t\\t}\\n\\t\\tget sensitivity() {\\n\\t\\t\\t\\treturn this._sensitivity;\\n\\t\\t}\\n\\t\\tset shutter(newValue) {\\n\\t\\t\\t\\tthis._shutter = newValue;\\n\\t\\t}\\n\\t\\tget shutter() {\\n\\t\\t\\t\\treturn this._shutter;\\n\\t\\t}\\n\\t\\tset xr(newValue) {\\n\\t\\t\\t\\tif (this._xr !== newValue) {\\n\\t\\t\\t\\t\\t\\tthis._xr = newValue;\\n\\t\\t\\t\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget xr() {\\n\\t\\t\\t\\treturn this._xr;\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\treturn new Camera().copy(this);\\n\\t\\t}\\n\\t\\tcopy(other) {\\n\\t\\t\\t\\tthis._aspectRatio = other._aspectRatio;\\n\\t\\t\\t\\tthis._farClip = other._farClip;\\n\\t\\t\\t\\tthis._fov = other._fov;\\n\\t\\t\\t\\tthis._horizontalFov = other._horizontalFov;\\n\\t\\t\\t\\tthis._nearClip = other._nearClip;\\n\\t\\t\\t\\tthis._xrProperties.aspectRatio = other._xrProperties.aspectRatio;\\n\\t\\t\\t\\tthis._xrProperties.farClip = other._xrProperties.farClip;\\n\\t\\t\\t\\tthis._xrProperties.fov = other._xrProperties.fov;\\n\\t\\t\\t\\tthis._xrProperties.horizontalFov = other._xrProperties.horizontalFov;\\n\\t\\t\\t\\tthis._xrProperties.nearClip = other._xrProperties.nearClip;\\n\\t\\t\\t\\tthis.aspectRatioMode = other.aspectRatioMode;\\n\\t\\t\\t\\tthis.calculateProjection = other.calculateProjection;\\n\\t\\t\\t\\tthis.calculateTransform = other.calculateTransform;\\n\\t\\t\\t\\tthis.clearColor = other.clearColor;\\n\\t\\t\\t\\tthis.clearColorBuffer = other.clearColorBuffer;\\n\\t\\t\\t\\tthis.clearDepth = other.clearDepth;\\n\\t\\t\\t\\tthis.clearDepthBuffer = other.clearDepthBuffer;\\n\\t\\t\\t\\tthis.clearStencil = other.clearStencil;\\n\\t\\t\\t\\tthis.clearStencilBuffer = other.clearStencilBuffer;\\n\\t\\t\\t\\tthis.cullFaces = other.cullFaces;\\n\\t\\t\\t\\tthis.flipFaces = other.flipFaces;\\n\\t\\t\\t\\tthis.frustumCulling = other.frustumCulling;\\n\\t\\t\\t\\tthis.layers = other.layers;\\n\\t\\t\\t\\tthis.orthoHeight = other.orthoHeight;\\n\\t\\t\\t\\tthis.projection = other.projection;\\n\\t\\t\\t\\tthis.rect = other.rect;\\n\\t\\t\\t\\tthis.renderTarget = other.renderTarget;\\n\\t\\t\\t\\tthis.scissorRect = other.scissorRect;\\n\\t\\t\\t\\tthis.aperture = other.aperture;\\n\\t\\t\\t\\tthis.shutter = other.shutter;\\n\\t\\t\\t\\tthis.sensitivity = other.sensitivity;\\n\\t\\t\\t\\tthis.shaderPassInfo = other.shaderPassInfo;\\n\\t\\t\\t\\tthis.jitter = other.jitter;\\n\\t\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\t_enableRenderPassColorGrab(device, enable) {\\n\\t\\t\\t\\tif (enable) {\\n\\t\\t\\t\\t\\t\\tif (!this.renderPassColorGrab) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.renderPassColorGrab = new RenderPassColorGrab(device);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.renderPassColorGrab?.destroy();\\n\\t\\t\\t\\t\\t\\tthis.renderPassColorGrab = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_enableRenderPassDepthGrab(device, renderer, enable) {\\n\\t\\t\\t\\tif (enable) {\\n\\t\\t\\t\\t\\t\\tif (!this.renderPassDepthGrab) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.renderPassDepthGrab = new RenderPassDepthGrab(device, this);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.renderPassDepthGrab?.destroy();\\n\\t\\t\\t\\t\\t\\tthis.renderPassDepthGrab = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_updateViewProjMat() {\\n\\t\\t\\t\\tif (this._projMatDirty || this._viewMatDirty || this._viewProjMatDirty) {\\n\\t\\t\\t\\t\\t\\tthis._viewProjMat.mul2(this.projectionMatrix, this.viewMatrix);\\n\\t\\t\\t\\t\\t\\tthis._viewProjMatDirty = false;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tworldToScreen(worldCoord, cw, ch, screenCoord = new Vec3()) {\\n\\t\\t\\t\\tthis._updateViewProjMat();\\n\\t\\t\\t\\tthis._viewProjMat.transformPoint(worldCoord, screenCoord);\\n\\t\\t\\t\\tconst vpm = this._viewProjMat.data;\\n\\t\\t\\t\\tconst w = worldCoord.x * vpm[3] + worldCoord.y * vpm[7] + worldCoord.z * vpm[11] + 1 * vpm[15];\\n\\t\\t\\t\\tscreenCoord.x = (screenCoord.x / w + 1) * 0.5;\\n\\t\\t\\t\\tscreenCoord.y = (1 - screenCoord.y / w) * 0.5;\\n\\t\\t\\t\\tconst { x: rx, y: ry, z: rw, w: rh } = this._rect;\\n\\t\\t\\t\\tscreenCoord.x = screenCoord.x * rw * cw + rx * cw;\\n\\t\\t\\t\\tscreenCoord.y = screenCoord.y * rh * ch + (1 - ry - rh) * ch;\\n\\t\\t\\t\\treturn screenCoord;\\n\\t\\t}\\n\\t\\tscreenToWorld(x, y, z, cw, ch, worldCoord = new Vec3()) {\\n\\t\\t\\t\\tconst { x: rx, y: ry, z: rw, w: rh } = this._rect;\\n\\t\\t\\t\\tconst range = this.farClip - this.nearClip;\\n\\t\\t\\t\\t_deviceCoord.set((x - rx * cw) / (rw * cw), 1 - (y - (1 - ry - rh) * ch) / (rh * ch), z / range);\\n\\t\\t\\t\\t_deviceCoord.mulScalar(2);\\n\\t\\t\\t\\t_deviceCoord.sub(Vec3.ONE);\\n\\t\\t\\t\\tif (this._projection === PROJECTION_PERSPECTIVE) {\\n\\t\\t\\t\\t\\t\\tMat4._getPerspectiveHalfSize(_halfSize, this.fov, this.aspectRatio, this.nearClip, this.horizontalFov);\\n\\t\\t\\t\\t\\t\\t_halfSize.x *= _deviceCoord.x;\\n\\t\\t\\t\\t\\t\\t_halfSize.y *= _deviceCoord.y;\\n\\t\\t\\t\\t\\t\\tconst invView = this._node.getWorldTransform();\\n\\t\\t\\t\\t\\t\\t_halfSize.z = -this.nearClip;\\n\\t\\t\\t\\t\\t\\tinvView.transformPoint(_halfSize, _point);\\n\\t\\t\\t\\t\\t\\tconst cameraPos = this._node.getPosition();\\n\\t\\t\\t\\t\\t\\tworldCoord.sub2(_point, cameraPos);\\n\\t\\t\\t\\t\\t\\tworldCoord.normalize();\\n\\t\\t\\t\\t\\t\\tworldCoord.mulScalar(z);\\n\\t\\t\\t\\t\\t\\tworldCoord.add(cameraPos);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._updateViewProjMat();\\n\\t\\t\\t\\t\\t\\t_invViewProjMat.copy(this._viewProjMat).invert();\\n\\t\\t\\t\\t\\t\\t_invViewProjMat.transformPoint(_deviceCoord, worldCoord);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn worldCoord;\\n\\t\\t}\\n\\t\\t_evaluateProjectionMatrix() {\\n\\t\\t\\t\\tif (this._projMatDirty) {\\n\\t\\t\\t\\t\\t\\tif (this._projection === PROJECTION_PERSPECTIVE) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._projMat.setPerspective(this.fov, this.aspectRatio, this.nearClip, this.farClip, this.horizontalFov);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._projMatSkybox.copy(this._projMat);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst y = this._orthoHeight;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst x = y * this.aspectRatio;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._projMat.setOrtho(-x, x, -y, y, this.nearClip, this.farClip);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._projMatSkybox.setPerspective(this.fov, this.aspectRatio, this.nearClip, this.farClip);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._projMatDirty = false;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetProjectionMatrixSkybox() {\\n\\t\\t\\t\\tthis._evaluateProjectionMatrix();\\n\\t\\t\\t\\treturn this._projMatSkybox;\\n\\t\\t}\\n\\t\\tgetExposure() {\\n\\t\\t\\t\\tconst ev100 = Math.log2(this._aperture * this._aperture / this._shutter * 100.0 / this._sensitivity);\\n\\t\\t\\t\\treturn 1.0 / (Math.pow(2.0, ev100) * 1.2);\\n\\t\\t}\\n\\t\\tgetScreenSize(sphere) {\\n\\t\\t\\t\\tif (this._projection === PROJECTION_PERSPECTIVE) {\\n\\t\\t\\t\\t\\t\\tconst distance = this._node.getPosition().distance(sphere.center);\\n\\t\\t\\t\\t\\t\\tif (distance < sphere.radius) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 1;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst viewAngle = Math.asin(sphere.radius / distance);\\n\\t\\t\\t\\t\\t\\tconst sphereViewHeight = Math.tan(viewAngle);\\n\\t\\t\\t\\t\\t\\tconst screenViewHeight = Math.tan(this.fov / 2 * math.DEG_TO_RAD);\\n\\t\\t\\t\\t\\t\\treturn Math.min(sphereViewHeight / screenViewHeight, 1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn math.clamp(sphere.radius / this._orthoHeight, 0, 1);\\n\\t\\t}\\n\\t\\tgetFrustumCorners(near = this.nearClip, far = this.farClip) {\\n\\t\\t\\t\\tconst fov = this.fov * math.DEG_TO_RAD;\\n\\t\\t\\t\\tlet x, y;\\n\\t\\t\\t\\tif (this.projection === PROJECTION_PERSPECTIVE) {\\n\\t\\t\\t\\t\\t\\tif (this.horizontalFov) {\\n\\t\\t\\t\\t\\t\\t\\t\\tx = near * Math.tan(fov / 2.0);\\n\\t\\t\\t\\t\\t\\t\\t\\ty = x / this.aspectRatio;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\ty = near * Math.tan(fov / 2.0);\\n\\t\\t\\t\\t\\t\\t\\t\\tx = y * this.aspectRatio;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\ty = this._orthoHeight;\\n\\t\\t\\t\\t\\t\\tx = y * this.aspectRatio;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst points = _frustumPoints;\\n\\t\\t\\t\\tpoints[0].x = x;\\n\\t\\t\\t\\tpoints[0].y = -y;\\n\\t\\t\\t\\tpoints[0].z = -near;\\n\\t\\t\\t\\tpoints[1].x = x;\\n\\t\\t\\t\\tpoints[1].y = y;\\n\\t\\t\\t\\tpoints[1].z = -near;\\n\\t\\t\\t\\tpoints[2].x = -x;\\n\\t\\t\\t\\tpoints[2].y = y;\\n\\t\\t\\t\\tpoints[2].z = -near;\\n\\t\\t\\t\\tpoints[3].x = -x;\\n\\t\\t\\t\\tpoints[3].y = -y;\\n\\t\\t\\t\\tpoints[3].z = -near;\\n\\t\\t\\t\\tif (this._projection === PROJECTION_PERSPECTIVE) {\\n\\t\\t\\t\\t\\t\\tif (this.horizontalFov) {\\n\\t\\t\\t\\t\\t\\t\\t\\tx = far * Math.tan(fov / 2.0);\\n\\t\\t\\t\\t\\t\\t\\t\\ty = x / this.aspectRatio;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\ty = far * Math.tan(fov / 2.0);\\n\\t\\t\\t\\t\\t\\t\\t\\tx = y * this.aspectRatio;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tpoints[4].x = x;\\n\\t\\t\\t\\tpoints[4].y = -y;\\n\\t\\t\\t\\tpoints[4].z = -far;\\n\\t\\t\\t\\tpoints[5].x = x;\\n\\t\\t\\t\\tpoints[5].y = y;\\n\\t\\t\\t\\tpoints[5].z = -far;\\n\\t\\t\\t\\tpoints[6].x = -x;\\n\\t\\t\\t\\tpoints[6].y = y;\\n\\t\\t\\t\\tpoints[6].z = -far;\\n\\t\\t\\t\\tpoints[7].x = -x;\\n\\t\\t\\t\\tpoints[7].y = -y;\\n\\t\\t\\t\\tpoints[7].z = -far;\\n\\t\\t\\t\\treturn points;\\n\\t\\t}\\n\\t\\tsetXrProperties(properties) {\\n\\t\\t\\t\\tObject.assign(this._xrProperties, properties);\\n\\t\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t}\\n\\t\\tfillShaderParams(output) {\\n\\t\\t\\t\\tconst f = this._farClip;\\n\\t\\t\\t\\toutput[0] = 1 / f;\\n\\t\\t\\t\\toutput[1] = f;\\n\\t\\t\\t\\toutput[2] = this._nearClip;\\n\\t\\t\\t\\toutput[3] = this._projection === PROJECTION_ORTHOGRAPHIC ? 1 : 0;\\n\\t\\t\\t\\treturn output;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.shaderPassInfo = null;\\n\\t\\t\\t\\tthis.renderPassColorGrab = null;\\n\\t\\t\\t\\tthis.renderPassDepthGrab = null;\\n\\t\\t\\t\\tthis.fogParams = null;\\n\\t\\t\\t\\tthis.shaderParams = new CameraShaderParams();\\n\\t\\t\\t\\tthis.renderPasses = [];\\n\\t\\t\\t\\tthis.jitter = 0;\\n\\t\\t\\t\\tthis._aspectRatio = 16 / 9;\\n\\t\\t\\t\\tthis._aspectRatioMode = ASPECT_AUTO;\\n\\t\\t\\t\\tthis._calculateProjection = null;\\n\\t\\t\\t\\tthis._calculateTransform = null;\\n\\t\\t\\t\\tthis._clearColor = new Color(0.75, 0.75, 0.75, 1);\\n\\t\\t\\t\\tthis._clearColorBuffer = true;\\n\\t\\t\\t\\tthis._clearDepth = 1;\\n\\t\\t\\t\\tthis._clearDepthBuffer = true;\\n\\t\\t\\t\\tthis._clearStencil = 0;\\n\\t\\t\\t\\tthis._clearStencilBuffer = true;\\n\\t\\t\\t\\tthis._cullFaces = true;\\n\\t\\t\\t\\tthis._farClip = 1000;\\n\\t\\t\\t\\tthis._flipFaces = false;\\n\\t\\t\\t\\tthis._fov = 45;\\n\\t\\t\\t\\tthis._frustumCulling = true;\\n\\t\\t\\t\\tthis._horizontalFov = false;\\n\\t\\t\\t\\tthis._layers = [\\n\\t\\t\\t\\t\\t\\tLAYERID_WORLD,\\n\\t\\t\\t\\t\\t\\tLAYERID_DEPTH,\\n\\t\\t\\t\\t\\t\\tLAYERID_SKYBOX,\\n\\t\\t\\t\\t\\t\\tLAYERID_UI,\\n\\t\\t\\t\\t\\t\\tLAYERID_IMMEDIATE\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis._layersSet = new Set(this._layers);\\n\\t\\t\\t\\tthis._nearClip = 0.1;\\n\\t\\t\\t\\tthis._node = null;\\n\\t\\t\\t\\tthis._orthoHeight = 10;\\n\\t\\t\\t\\tthis._projection = PROJECTION_PERSPECTIVE;\\n\\t\\t\\t\\tthis._rect = new Vec4(0, 0, 1, 1);\\n\\t\\t\\t\\tthis._renderTarget = null;\\n\\t\\t\\t\\tthis._scissorRect = new Vec4(0, 0, 1, 1);\\n\\t\\t\\t\\tthis._scissorRectClear = false;\\n\\t\\t\\t\\tthis._aperture = 16.0;\\n\\t\\t\\t\\tthis._shutter = 1.0 / 1000.0;\\n\\t\\t\\t\\tthis._sensitivity = 1000;\\n\\t\\t\\t\\tthis._projMat = new Mat4();\\n\\t\\t\\t\\tthis._projMatDirty = true;\\n\\t\\t\\t\\tthis._projMatSkybox = new Mat4();\\n\\t\\t\\t\\tthis._viewMat = new Mat4();\\n\\t\\t\\t\\tthis._viewMatDirty = true;\\n\\t\\t\\t\\tthis._viewProjMat = new Mat4();\\n\\t\\t\\t\\tthis._viewProjMatDirty = true;\\n\\t\\t\\t\\tthis._shaderMatricesVersion = 0;\\n\\t\\t\\t\\tthis._viewProjInverse = new Mat4();\\n\\t\\t\\t\\tthis._viewProjCurrent = null;\\n\\t\\t\\t\\tthis._viewProjPrevious = new Mat4();\\n\\t\\t\\t\\tthis._jitters = [\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.frustum = new Frustum();\\n\\t\\t\\t\\tthis._xr = null;\\n\\t\\t\\t\\tthis._xrProperties = {\\n\\t\\t\\t\\t\\t\\thorizontalFov: this._horizontalFov,\\n\\t\\t\\t\\t\\t\\tfov: this._fov,\\n\\t\\t\\t\\t\\t\\taspectRatio: this._aspectRatio,\\n\\t\\t\\t\\t\\t\\tfarClip: this._farClip,\\n\\t\\t\\t\\t\\t\\tnearClip: this._nearClip\\n\\t\\t\\t\\t};\\n\\t\\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$1 = new Vec3();\\nfunction createTest(attr, value) {\\n\\t\\tif (attr instanceof Function) {\\n\\t\\t\\t\\treturn attr;\\n\\t\\t}\\n\\t\\treturn (node)=>{\\n\\t\\t\\t\\tlet x = node[attr];\\n\\t\\t\\t\\tif (x instanceof Function) {\\n\\t\\t\\t\\t\\t\\tx = x();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn x === value;\\n\\t\\t};\\n}\\nfunction findNode(node, test) {\\n\\t\\tif (test(node)) {\\n\\t\\t\\t\\treturn node;\\n\\t\\t}\\n\\t\\tconst children = node._children;\\n\\t\\tconst len = children.length;\\n\\t\\tfor(let i = 0; i < len; ++i){\\n\\t\\t\\t\\tconst result = findNode(children[i], test);\\n\\t\\t\\t\\tif (result) {\\n\\t\\t\\t\\t\\t\\treturn result;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn null;\\n}\\nclass GraphNode extends EventHandler {\\n\\t\\tget right() {\\n\\t\\t\\t\\tif (!this._right) {\\n\\t\\t\\t\\t\\t\\tthis._right = new Vec3();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.getWorldTransform().getX(this._right).normalize();\\n\\t\\t}\\n\\t\\tget up() {\\n\\t\\t\\t\\tif (!this._up) {\\n\\t\\t\\t\\t\\t\\tthis._up = new Vec3();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.getWorldTransform().getY(this._up).normalize();\\n\\t\\t}\\n\\t\\tget forward() {\\n\\t\\t\\t\\tif (!this._forward) {\\n\\t\\t\\t\\t\\t\\tthis._forward = new Vec3();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.getWorldTransform().getZ(this._forward).normalize().mulScalar(-1);\\n\\t\\t}\\n\\t\\tget normalMatrix() {\\n\\t\\t\\t\\tconst normalMat = this._normalMatrix;\\n\\t\\t\\t\\tif (this._dirtyNormal) {\\n\\t\\t\\t\\t\\t\\tnormalMat.invertMat4(this.getWorldTransform()).transpose();\\n\\t\\t\\t\\t\\t\\tthis._dirtyNormal = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn normalMat;\\n\\t\\t}\\n\\t\\tset enabled(enabled) {\\n\\t\\t\\t\\tif (this._enabled !== enabled) {\\n\\t\\t\\t\\t\\t\\tthis._enabled = enabled;\\n\\t\\t\\t\\t\\t\\tif (enabled && this._parent?.enabled || !enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._notifyHierarchyStateChanged(this, enabled);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget enabled() {\\n\\t\\t\\t\\treturn this._enabled && this._enabledInHierarchy;\\n\\t\\t}\\n\\t\\tget parent() {\\n\\t\\t\\t\\treturn this._parent;\\n\\t\\t}\\n\\t\\tget path() {\\n\\t\\t\\t\\tlet node = this._parent;\\n\\t\\t\\t\\tif (!node) {\\n\\t\\t\\t\\t\\t\\treturn '';\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet result = this.name;\\n\\t\\t\\t\\twhile(node && node._parent){\\n\\t\\t\\t\\t\\t\\tresult = `${node.name}/${result}`;\\n\\t\\t\\t\\t\\t\\tnode = node._parent;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tget root() {\\n\\t\\t\\t\\tlet result = this;\\n\\t\\t\\t\\twhile(result._parent){\\n\\t\\t\\t\\t\\t\\tresult = result._parent;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tget children() {\\n\\t\\t\\t\\treturn this._children;\\n\\t\\t}\\n\\t\\tget graphDepth() {\\n\\t\\t\\t\\treturn this._graphDepth;\\n\\t\\t}\\n\\t\\t_notifyHierarchyStateChanged(node, enabled) {\\n\\t\\t\\t\\tnode._onHierarchyStateChanged(enabled);\\n\\t\\t\\t\\tconst c = node._children;\\n\\t\\t\\t\\tfor(let i = 0, len = c.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tif (c[i]._enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._notifyHierarchyStateChanged(c[i], enabled);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onHierarchyStateChanged(enabled) {\\n\\t\\t\\t\\tthis._enabledInHierarchy = enabled;\\n\\t\\t\\t\\tif (enabled && !this._frozen) {\\n\\t\\t\\t\\t\\t\\tthis._unfreezeParentToRoot();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_cloneInternal(clone) {\\n\\t\\t\\t\\tclone.name = this.name;\\n\\t\\t\\t\\tconst tags = this.tags._list;\\n\\t\\t\\t\\tclone.tags.clear();\\n\\t\\t\\t\\tfor(let i = 0; i < tags.length; i++){\\n\\t\\t\\t\\t\\t\\tclone.tags.add(tags[i]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tclone.localPosition.copy(this.localPosition);\\n\\t\\t\\t\\tclone.localRotation.copy(this.localRotation);\\n\\t\\t\\t\\tclone.localScale.copy(this.localScale);\\n\\t\\t\\t\\tclone.localEulerAngles.copy(this.localEulerAngles);\\n\\t\\t\\t\\tclone.position.copy(this.position);\\n\\t\\t\\t\\tclone.rotation.copy(this.rotation);\\n\\t\\t\\t\\tclone.eulerAngles.copy(this.eulerAngles);\\n\\t\\t\\t\\tclone.localTransform.copy(this.localTransform);\\n\\t\\t\\t\\tclone._dirtyLocal = this._dirtyLocal;\\n\\t\\t\\t\\tclone.worldTransform.copy(this.worldTransform);\\n\\t\\t\\t\\tclone._dirtyWorld = this._dirtyWorld;\\n\\t\\t\\t\\tclone._dirtyNormal = this._dirtyNormal;\\n\\t\\t\\t\\tclone._aabbVer = this._aabbVer + 1;\\n\\t\\t\\t\\tclone._enabled = this._enabled;\\n\\t\\t\\t\\tclone.scaleCompensation = this.scaleCompensation;\\n\\t\\t\\t\\tclone._enabledInHierarchy = false;\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst clone = new this.constructor();\\n\\t\\t\\t\\tthis._cloneInternal(clone);\\n\\t\\t\\t\\treturn clone;\\n\\t\\t}\\n\\t\\tcopy(source) {\\n\\t\\t\\t\\tsource._cloneInternal(this);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.remove();\\n\\t\\t\\t\\tconst children = this._children;\\n\\t\\t\\t\\twhile(children.length){\\n\\t\\t\\t\\t\\t\\tconst child = children.pop();\\n\\t\\t\\t\\t\\t\\tchild._parent = null;\\n\\t\\t\\t\\t\\t\\tchild.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.fire('destroy', this);\\n\\t\\t\\t\\tthis.off();\\n\\t\\t}\\n\\t\\tfind(attr, value) {\\n\\t\\t\\t\\tconst results = [];\\n\\t\\t\\t\\tconst test = createTest(attr, value);\\n\\t\\t\\t\\tthis.forEach((node)=>{\\n\\t\\t\\t\\t\\t\\tif (test(node)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tresults.push(node);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn results;\\n\\t\\t}\\n\\t\\tfindOne(attr, value) {\\n\\t\\t\\t\\tconst test = createTest(attr, value);\\n\\t\\t\\t\\treturn findNode(this, test);\\n\\t\\t}\\n\\t\\tfindByTag(...query) {\\n\\t\\t\\t\\tconst results = [];\\n\\t\\t\\t\\tconst queryNode = (node, checkNode)=>{\\n\\t\\t\\t\\t\\t\\tif (checkNode && node.tags.has(...query)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tresults.push(node);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < node._children.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tqueryNode(node._children[i], true);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tqueryNode(this, false);\\n\\t\\t\\t\\treturn results;\\n\\t\\t}\\n\\t\\tfindByName(name) {\\n\\t\\t\\t\\treturn this.findOne('name', name);\\n\\t\\t}\\n\\t\\tfindByPath(path) {\\n\\t\\t\\t\\tconst parts = Array.isArray(path) ? path : path.split('/');\\n\\t\\t\\t\\tlet result = this;\\n\\t\\t\\t\\tfor(let i = 0, imax = parts.length; i < imax; ++i){\\n\\t\\t\\t\\t\\t\\tresult = result.children.find((c)=>c.name === parts[i]);\\n\\t\\t\\t\\t\\t\\tif (!result) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tforEach(callback, thisArg) {\\n\\t\\t\\t\\tcallback.call(thisArg, this);\\n\\t\\t\\t\\tconst children = this._children;\\n\\t\\t\\t\\tconst len = children.length;\\n\\t\\t\\t\\tfor(let i = 0; i < len; ++i){\\n\\t\\t\\t\\t\\t\\tchildren[i].forEach(callback, thisArg);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tisDescendantOf(node) {\\n\\t\\t\\t\\tlet parent = this._parent;\\n\\t\\t\\t\\twhile(parent){\\n\\t\\t\\t\\t\\t\\tif (parent === node) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tparent = parent._parent;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tisAncestorOf(node) {\\n\\t\\t\\t\\treturn node.isDescendantOf(this);\\n\\t\\t}\\n\\t\\tgetEulerAngles() {\\n\\t\\t\\t\\tthis.getWorldTransform().getEulerAngles(this.eulerAngles);\\n\\t\\t\\t\\treturn this.eulerAngles;\\n\\t\\t}\\n\\t\\tgetLocalEulerAngles() {\\n\\t\\t\\t\\tthis.localRotation.getEulerAngles(this.localEulerAngles);\\n\\t\\t\\t\\treturn this.localEulerAngles;\\n\\t\\t}\\n\\t\\tgetLocalPosition() {\\n\\t\\t\\t\\treturn this.localPosition;\\n\\t\\t}\\n\\t\\tgetLocalRotation() {\\n\\t\\t\\t\\treturn this.localRotation;\\n\\t\\t}\\n\\t\\tgetLocalScale() {\\n\\t\\t\\t\\treturn this.localScale;\\n\\t\\t}\\n\\t\\tgetLocalTransform() {\\n\\t\\t\\t\\tif (this._dirtyLocal) {\\n\\t\\t\\t\\t\\t\\tthis.localTransform.setTRS(this.localPosition, this.localRotation, this.localScale);\\n\\t\\t\\t\\t\\t\\tthis._dirtyLocal = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.localTransform;\\n\\t\\t}\\n\\t\\tgetPosition() {\\n\\t\\t\\t\\tthis.getWorldTransform().getTranslation(this.position);\\n\\t\\t\\t\\treturn this.position;\\n\\t\\t}\\n\\t\\tgetRotation() {\\n\\t\\t\\t\\tthis.rotation.setFromMat4(this.getWorldTransform());\\n\\t\\t\\t\\treturn this.rotation;\\n\\t\\t}\\n\\t\\tgetScale() {\\n\\t\\t\\t\\tif (!this._scale) {\\n\\t\\t\\t\\t\\t\\tthis._scale = new Vec3();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.getWorldTransform().getScale(this._scale);\\n\\t\\t}\\n\\t\\tgetWorldTransform() {\\n\\t\\t\\t\\tif (!this._dirtyLocal && !this._dirtyWorld) {\\n\\t\\t\\t\\t\\t\\treturn this.worldTransform;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._parent) {\\n\\t\\t\\t\\t\\t\\tthis._parent.getWorldTransform();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._sync();\\n\\t\\t\\t\\treturn this.worldTransform;\\n\\t\\t}\\n\\t\\tget worldScaleSign() {\\n\\t\\t\\t\\tif (this._worldScaleSign === 0) {\\n\\t\\t\\t\\t\\t\\tthis._worldScaleSign = this.getWorldTransform().scaleSign;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._worldScaleSign;\\n\\t\\t}\\n\\t\\tremove() {\\n\\t\\t\\t\\tthis._parent?.removeChild(this);\\n\\t\\t}\\n\\t\\treparent(parent, index) {\\n\\t\\t\\t\\tthis.remove();\\n\\t\\t\\t\\tif (parent) {\\n\\t\\t\\t\\t\\t\\tif (index >= 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tparent.insertChild(this, index);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tparent.addChild(this);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetLocalEulerAngles(x, y, z) {\\n\\t\\t\\t\\tthis.localRotation.setFromEulerAngles(x, y, z);\\n\\t\\t\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\t\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetLocalPosition(x, y, z) {\\n\\t\\t\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\t\\t\\t\\tthis.localPosition.copy(x);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.localPosition.set(x, y, z);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\t\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetLocalRotation(x, y, z, w) {\\n\\t\\t\\t\\tif (x instanceof Quat) {\\n\\t\\t\\t\\t\\t\\tthis.localRotation.copy(x);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.localRotation.set(x, y, z, w);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\t\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetLocalScale(x, y, z) {\\n\\t\\t\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\t\\t\\t\\tthis.localScale.copy(x);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.localScale.set(x, y, z);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\t\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_dirtifyLocal() {\\n\\t\\t\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\t\\t\\t\\tthis._dirtyLocal = true;\\n\\t\\t\\t\\t\\t\\tif (!this._dirtyWorld) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._dirtifyWorld();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_unfreezeParentToRoot() {\\n\\t\\t\\t\\tlet p = this._parent;\\n\\t\\t\\t\\twhile(p){\\n\\t\\t\\t\\t\\t\\tp._frozen = false;\\n\\t\\t\\t\\t\\t\\tp = p._parent;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_dirtifyWorld() {\\n\\t\\t\\t\\tif (!this._dirtyWorld) {\\n\\t\\t\\t\\t\\t\\tthis._unfreezeParentToRoot();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._dirtifyWorldInternal();\\n\\t\\t}\\n\\t\\t_dirtifyWorldInternal() {\\n\\t\\t\\t\\tif (!this._dirtyWorld) {\\n\\t\\t\\t\\t\\t\\tthis._frozen = false;\\n\\t\\t\\t\\t\\t\\tthis._dirtyWorld = true;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._children.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this._children[i]._dirtyWorld) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._children[i]._dirtifyWorldInternal();\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._dirtyNormal = true;\\n\\t\\t\\t\\tthis._worldScaleSign = 0;\\n\\t\\t\\t\\tthis._aabbVer++;\\n\\t\\t}\\n\\t\\tsetPosition(x, y, z) {\\n\\t\\t\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\t\\t\\t\\tposition.copy(x);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tposition.set(x, y, z);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._parent === null) {\\n\\t\\t\\t\\t\\t\\tthis.localPosition.copy(position);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tinvParentWtm.copy(this._parent.getWorldTransform()).invert();\\n\\t\\t\\t\\t\\t\\tinvParentWtm.transformPoint(position, this.localPosition);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\t\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetRotation(x, y, z, w) {\\n\\t\\t\\t\\tif (x instanceof Quat) {\\n\\t\\t\\t\\t\\t\\trotation$4.copy(x);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\trotation$4.set(x, y, z, w);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._parent === null) {\\n\\t\\t\\t\\t\\t\\tthis.localRotation.copy(rotation$4);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst parentRot = this._parent.getRotation();\\n\\t\\t\\t\\t\\t\\tinvParentRot.copy(parentRot).invert();\\n\\t\\t\\t\\t\\t\\tthis.localRotation.copy(invParentRot).mul(rotation$4);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\t\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetPositionAndRotation(position, rotation) {\\n\\t\\t\\t\\tif (this._parent === null) {\\n\\t\\t\\t\\t\\t\\tthis.localPosition.copy(position);\\n\\t\\t\\t\\t\\t\\tthis.localRotation.copy(rotation);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst parentWtm = this._parent.getWorldTransform();\\n\\t\\t\\t\\t\\t\\tinvParentWtm.copy(parentWtm).invert();\\n\\t\\t\\t\\t\\t\\tinvParentWtm.transformPoint(position, this.localPosition);\\n\\t\\t\\t\\t\\t\\tthis.localRotation.setFromMat4(invParentWtm).mul(rotation);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\t\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetEulerAngles(x, y, z) {\\n\\t\\t\\t\\tthis.localRotation.setFromEulerAngles(x, y, z);\\n\\t\\t\\t\\tif (this._parent !== null) {\\n\\t\\t\\t\\t\\t\\tconst parentRot = this._parent.getRotation();\\n\\t\\t\\t\\t\\t\\tinvParentRot.copy(parentRot).invert();\\n\\t\\t\\t\\t\\t\\tthis.localRotation.mul2(invParentRot, this.localRotation);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\t\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\taddChild(node) {\\n\\t\\t\\t\\tthis._prepareInsertChild(node);\\n\\t\\t\\t\\tthis._children.push(node);\\n\\t\\t\\t\\tthis._onInsertChild(node);\\n\\t\\t}\\n\\t\\taddChildAndSaveTransform(node) {\\n\\t\\t\\t\\tconst wPos = node.getPosition();\\n\\t\\t\\t\\tconst wRot = node.getRotation();\\n\\t\\t\\t\\tthis._prepareInsertChild(node);\\n\\t\\t\\t\\tnode.setPosition(tmpMat4.copy(this.worldTransform).invert().transformPoint(wPos));\\n\\t\\t\\t\\tnode.setRotation(tmpQuat.copy(this.getRotation()).invert().mul(wRot));\\n\\t\\t\\t\\tthis._children.push(node);\\n\\t\\t\\t\\tthis._onInsertChild(node);\\n\\t\\t}\\n\\t\\tinsertChild(node, index) {\\n\\t\\t\\t\\tthis._prepareInsertChild(node);\\n\\t\\t\\t\\tthis._children.splice(index, 0, node);\\n\\t\\t\\t\\tthis._onInsertChild(node);\\n\\t\\t}\\n\\t\\t_prepareInsertChild(node) {\\n\\t\\t\\t\\tnode.remove();\\n\\t\\t}\\n\\t\\t_fireOnHierarchy(name, nameHierarchy, parent) {\\n\\t\\t\\t\\tthis.fire(name, parent);\\n\\t\\t\\t\\tfor(let i = 0; i < this._children.length; i++){\\n\\t\\t\\t\\t\\t\\tthis._children[i]._fireOnHierarchy(nameHierarchy, nameHierarchy, parent);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onInsertChild(node) {\\n\\t\\t\\t\\tnode._parent = this;\\n\\t\\t\\t\\tconst enabledInHierarchy = node._enabled && this.enabled;\\n\\t\\t\\t\\tif (node._enabledInHierarchy !== enabledInHierarchy) {\\n\\t\\t\\t\\t\\t\\tnode._enabledInHierarchy = enabledInHierarchy;\\n\\t\\t\\t\\t\\t\\tnode._notifyHierarchyStateChanged(node, enabledInHierarchy);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tnode._updateGraphDepth();\\n\\t\\t\\t\\tnode._dirtifyWorld();\\n\\t\\t\\t\\tif (this._frozen) {\\n\\t\\t\\t\\t\\t\\tnode._unfreezeParentToRoot();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tnode._fireOnHierarchy('insert', 'inserthierarchy', this);\\n\\t\\t\\t\\tif (this.fire) this.fire('childinsert', node);\\n\\t\\t}\\n\\t\\t_updateGraphDepth() {\\n\\t\\t\\t\\tthis._graphDepth = this._parent ? this._parent._graphDepth + 1 : 0;\\n\\t\\t\\t\\tfor(let i = 0, len = this._children.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tthis._children[i]._updateGraphDepth();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tremoveChild(child) {\\n\\t\\t\\t\\tconst index = this._children.indexOf(child);\\n\\t\\t\\t\\tif (index === -1) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._children.splice(index, 1);\\n\\t\\t\\t\\tchild._parent = null;\\n\\t\\t\\t\\tchild._fireOnHierarchy('remove', 'removehierarchy', this);\\n\\t\\t\\t\\tthis.fire('childremove', child);\\n\\t\\t}\\n\\t\\t_sync() {\\n\\t\\t\\t\\tif (this._dirtyLocal) {\\n\\t\\t\\t\\t\\t\\tthis.localTransform.setTRS(this.localPosition, this.localRotation, this.localScale);\\n\\t\\t\\t\\t\\t\\tthis._dirtyLocal = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._dirtyWorld) {\\n\\t\\t\\t\\t\\t\\tif (this._parent === null) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.worldTransform.copy(this.localTransform);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.scaleCompensation) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet parentWorldScale;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst parent = this._parent;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet scale = this.localScale;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet parentToUseScaleFrom = parent;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (parentToUseScaleFrom) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twhile(parentToUseScaleFrom && parentToUseScaleFrom.scaleCompensation){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tparentToUseScaleFrom = parentToUseScaleFrom._parent;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (parentToUseScaleFrom) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tparentToUseScaleFrom = parentToUseScaleFrom._parent;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (parentToUseScaleFrom) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tparentWorldScale = parentToUseScaleFrom.worldTransform.getScale();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscaleCompensateScale.mul2(parentWorldScale, this.localScale);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscale = scaleCompensateScale;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscaleCompensateRot2.setFromMat4(parent.worldTransform);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscaleCompensateRot.mul2(scaleCompensateRot2, this.localRotation);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet tmatrix = parent.worldTransform;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (parent.scaleCompensation) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscaleCompensateScaleForParent.mul2(parentWorldScale, parent.getLocalScale());\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscaleCompensatePosTransform.setTRS(parent.worldTransform.getTranslation(scaleCompensatePos), scaleCompensateRot2, scaleCompensateScaleForParent);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttmatrix = scaleCompensatePosTransform;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttmatrix.transformPoint(this.localPosition, scaleCompensatePos);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.worldTransform.setTRS(scaleCompensatePos, scaleCompensateRot, scale);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.worldTransform.mulAffine2(this._parent.worldTransform, this.localTransform);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._dirtyWorld = false;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsyncHierarchy() {\\n\\t\\t\\t\\tif (!this._enabled) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._frozen) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._frozen = true;\\n\\t\\t\\t\\tif (this._dirtyLocal || this._dirtyWorld) {\\n\\t\\t\\t\\t\\t\\tthis._sync();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst children = this._children;\\n\\t\\t\\t\\tfor(let i = 0, len = children.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tchildren[i].syncHierarchy();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tlookAt(x, y, z, ux = 0, uy = 1, uz = 0) {\\n\\t\\t\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\t\\t\\t\\ttarget.copy(x);\\n\\t\\t\\t\\t\\t\\tif (y instanceof Vec3) {\\n\\t\\t\\t\\t\\t\\t\\t\\tup$1.copy(y);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tup$1.copy(Vec3.UP);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else if (z === undefined) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\ttarget.set(x, y, z);\\n\\t\\t\\t\\t\\t\\tup$1.set(ux, uy, uz);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tmatrix.setLookAt(this.getPosition(), target, up$1);\\n\\t\\t\\t\\trotation$4.setFromMat4(matrix);\\n\\t\\t\\t\\tthis.setRotation(rotation$4);\\n\\t\\t}\\n\\t\\ttranslate(x, y, z) {\\n\\t\\t\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\t\\t\\t\\tposition.copy(x);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tposition.set(x, y, z);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tposition.add(this.getPosition());\\n\\t\\t\\t\\tthis.setPosition(position);\\n\\t\\t}\\n\\t\\ttranslateLocal(x, y, z) {\\n\\t\\t\\t\\tif (x instanceof Vec3) {\\n\\t\\t\\t\\t\\t\\tposition.copy(x);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tposition.set(x, y, z);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.localRotation.transformVector(position, position);\\n\\t\\t\\t\\tthis.localPosition.add(position);\\n\\t\\t\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\t\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\trotate(x, y, z) {\\n\\t\\t\\t\\trotation$4.setFromEulerAngles(x, y, z);\\n\\t\\t\\t\\tif (this._parent === null) {\\n\\t\\t\\t\\t\\t\\tthis.localRotation.mul2(rotation$4, this.localRotation);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst rot = this.getRotation();\\n\\t\\t\\t\\t\\t\\tconst parentRot = this._parent.getRotation();\\n\\t\\t\\t\\t\\t\\tinvParentRot.copy(parentRot).invert();\\n\\t\\t\\t\\t\\t\\trotation$4.mul2(invParentRot, rotation$4);\\n\\t\\t\\t\\t\\t\\tthis.localRotation.mul2(rotation$4, rot);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\t\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\trotateLocal(x, y, z) {\\n\\t\\t\\t\\trotation$4.setFromEulerAngles(x, y, z);\\n\\t\\t\\t\\tthis.localRotation.mul(rotation$4);\\n\\t\\t\\t\\tif (!this._dirtyLocal) {\\n\\t\\t\\t\\t\\t\\tthis._dirtifyLocal();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(name = 'Untitled'){\\n\\t\\t\\t\\tsuper(), this.tags = new Tags(this), this.localPosition = new Vec3(), this.localRotation = new Quat(), this.localScale = new Vec3(1, 1, 1), this.localEulerAngles = new Vec3(), this.position = new Vec3(), this.rotation = new Quat(), this.eulerAngles = new Vec3(), this._scale = null, this.localTransform = new Mat4(), this._dirtyLocal = false, this._aabbVer = 0, this._frozen = false, this.worldTransform = new Mat4(), this._dirtyWorld = false, this._worldScaleSign = 0, this._normalMatrix = new Mat3(), this._dirtyNormal = true, this._right = null, this._up = null, this._forward = null, this._parent = null, this._children = [], this._graphDepth = 0, this._enabled = true, this._enabledInHierarchy = false, this.scaleCompensation = false;\\n\\t\\t\\t\\tthis.name = name;\\n\\t\\t}\\n}\\n\\nconst _viewMat$1 = new Mat4();\\nconst _viewProjMat = new Mat4();\\nconst _viewportMatrix = new Mat4();\\nclass LightCamera {\\n\\t\\tstatic create(name, lightType, face) {\\n\\t\\t\\t\\tconst camera = new Camera$1();\\n\\t\\t\\t\\tcamera.node = new GraphNode(name);\\n\\t\\t\\t\\tcamera.aspectRatio = 1;\\n\\t\\t\\t\\tcamera.aspectRatioMode = ASPECT_MANUAL;\\n\\t\\t\\t\\tcamera._scissorRectClear = true;\\n\\t\\t\\t\\tswitch(lightType){\\n\\t\\t\\t\\t\\t\\tcase LIGHTTYPE_OMNI:\\n\\t\\t\\t\\t\\t\\t\\t\\tcamera.node.setRotation(LightCamera.pointLightRotations[face]);\\n\\t\\t\\t\\t\\t\\t\\t\\tcamera.fov = 90;\\n\\t\\t\\t\\t\\t\\t\\t\\tcamera.projection = PROJECTION_PERSPECTIVE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase LIGHTTYPE_SPOT:\\n\\t\\t\\t\\t\\t\\t\\t\\tcamera.projection = PROJECTION_PERSPECTIVE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase LIGHTTYPE_DIRECTIONAL:\\n\\t\\t\\t\\t\\t\\t\\t\\tcamera.projection = PROJECTION_ORTHOGRAPHIC;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn camera;\\n\\t\\t}\\n\\t\\tstatic evalSpotCookieMatrix(light) {\\n\\t\\t\\t\\tlet cookieCamera = LightCamera._spotCookieCamera;\\n\\t\\t\\t\\tif (!cookieCamera) {\\n\\t\\t\\t\\t\\t\\tcookieCamera = LightCamera.create('SpotCookieCamera', LIGHTTYPE_SPOT);\\n\\t\\t\\t\\t\\t\\tLightCamera._spotCookieCamera = cookieCamera;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcookieCamera.fov = light._outerConeAngle * 2;\\n\\t\\t\\t\\tconst cookieNode = cookieCamera._node;\\n\\t\\t\\t\\tcookieNode.setPosition(light._node.getPosition());\\n\\t\\t\\t\\tcookieNode.setRotation(light._node.getRotation());\\n\\t\\t\\t\\tcookieNode.rotateLocal(-90, 0, 0);\\n\\t\\t\\t\\t_viewMat$1.setTRS(cookieNode.getPosition(), cookieNode.getRotation(), Vec3.ONE).invert();\\n\\t\\t\\t\\t_viewProjMat.mul2(cookieCamera.projectionMatrix, _viewMat$1);\\n\\t\\t\\t\\tconst cookieMatrix = light.cookieMatrix;\\n\\t\\t\\t\\tconst rectViewport = light.atlasViewport;\\n\\t\\t\\t\\t_viewportMatrix.setViewport(rectViewport.x, rectViewport.y, rectViewport.z, rectViewport.w);\\n\\t\\t\\t\\tcookieMatrix.mul2(_viewportMatrix, _viewProjMat);\\n\\t\\t\\t\\treturn cookieMatrix;\\n\\t\\t}\\n}\\nLightCamera.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];\\nLightCamera._spotCookieCamera = null;\\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\\t\\tPOSITION_RANGE: 0,\\n\\t\\tDIRECTION_FLAGS: 1,\\n\\t\\tCOLOR_ANGLES_BIAS: 2,\\n\\t\\tPROJ_MAT_0: 3,\\n\\t\\tATLAS_VIEWPORT: 3,\\n\\t\\tPROJ_MAT_1: 4,\\n\\t\\tPROJ_MAT_2: 5,\\n\\t\\tPROJ_MAT_3: 6,\\n\\t\\tAREA_DATA_WIDTH: 7,\\n\\t\\tAREA_DATA_HEIGHT: 8,\\n\\t\\tCOUNT: 9\\n};\\nconst enums = {\\n\\t\\t'LIGHTSHAPE_PUNCTUAL': `${LIGHTSHAPE_PUNCTUAL}u`,\\n\\t\\t'LIGHTSHAPE_RECT': `${LIGHTSHAPE_RECT}u`,\\n\\t\\t'LIGHTSHAPE_DISK': `${LIGHTSHAPE_DISK}u`,\\n\\t\\t'LIGHTSHAPE_SPHERE': `${LIGHTSHAPE_SPHERE}u`,\\n\\t\\t'LIGHT_COLOR_DIVIDER': `${LIGHT_COLOR_DIVIDER}.0`\\n};\\nconst buildShaderDefines = (object, prefix)=>{\\n\\t\\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\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.lightsTexture?.destroy();\\n\\t\\t\\t\\tthis.lightsTexture = null;\\n\\t\\t}\\n\\t\\tcreateTexture(device, width, height, format, name) {\\n\\t\\t\\t\\tconst tex = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\t\\t\\twidth: width,\\n\\t\\t\\t\\t\\t\\theight: height,\\n\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\ttype: TEXTURETYPE_DEFAULT,\\n\\t\\t\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\tanisotropy: 1\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn tex;\\n\\t\\t}\\n\\t\\tsetBounds(min, delta) {\\n\\t\\t\\t\\tthis.boundsMin.copy(min);\\n\\t\\t\\t\\tthis.boundsDelta.copy(delta);\\n\\t\\t}\\n\\t\\tuploadTextures() {\\n\\t\\t\\t\\tthis.lightsTexture.lock().set(this.lightsFloat);\\n\\t\\t\\t\\tthis.lightsTexture.unlock();\\n\\t\\t}\\n\\t\\tupdateUniforms() {\\n\\t\\t\\t\\tthis._lightsTextureId.setValue(this.lightsTexture);\\n\\t\\t}\\n\\t\\tgetSpotDirection(direction, spot) {\\n\\t\\t\\t\\tconst mat = spot._node.getWorldTransform();\\n\\t\\t\\t\\tmat.getY(direction).mulScalar(-1);\\n\\t\\t\\t\\tdirection.normalize();\\n\\t\\t}\\n\\t\\tgetLightAreaSizes(light) {\\n\\t\\t\\t\\tconst mat = light._node.getWorldTransform();\\n\\t\\t\\t\\tmat.transformVector(areaHalfAxisWidth, tempVec3$1);\\n\\t\\t\\t\\ttempAreaLightSizes[0] = tempVec3$1.x;\\n\\t\\t\\t\\ttempAreaLightSizes[1] = tempVec3$1.y;\\n\\t\\t\\t\\ttempAreaLightSizes[2] = tempVec3$1.z;\\n\\t\\t\\t\\tmat.transformVector(areaHalfAxisHeight, tempVec3$1);\\n\\t\\t\\t\\ttempAreaLightSizes[3] = tempVec3$1.x;\\n\\t\\t\\t\\ttempAreaLightSizes[4] = tempVec3$1.y;\\n\\t\\t\\t\\ttempAreaLightSizes[5] = tempVec3$1.z;\\n\\t\\t\\t\\treturn tempAreaLightSizes;\\n\\t\\t}\\n\\t\\taddLightData(light, lightIndex) {\\n\\t\\t\\t\\tconst isSpot = light._type === LIGHTTYPE_SPOT;\\n\\t\\t\\t\\tconst hasAtlasViewport = light.atlasViewportAllocated;\\n\\t\\t\\t\\tconst isCookie = this.cookiesEnabled && !!light._cookie && hasAtlasViewport;\\n\\t\\t\\t\\tconst isArea = this.areaLightsEnabled && light.shape !== LIGHTSHAPE_PUNCTUAL;\\n\\t\\t\\t\\tconst castShadows = this.shadowsEnabled && light.castShadows && hasAtlasViewport;\\n\\t\\t\\t\\tconst pos = light._node.getPosition();\\n\\t\\t\\t\\tlet lightProjectionMatrix = null;\\n\\t\\t\\t\\tlet atlasViewport = null;\\n\\t\\t\\t\\tif (isSpot) {\\n\\t\\t\\t\\t\\t\\tif (castShadows) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst lightRenderData = light.getRenderData(null, 0);\\n\\t\\t\\t\\t\\t\\t\\t\\tlightProjectionMatrix = lightRenderData.shadowMatrix;\\n\\t\\t\\t\\t\\t\\t} else if (isCookie) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlightProjectionMatrix = LightCamera.evalSpotCookieMatrix(light);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (castShadows || isCookie) {\\n\\t\\t\\t\\t\\t\\t\\t\\tatlasViewport = light.atlasViewport;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst dataFloat = this.lightsFloat;\\n\\t\\t\\t\\tconst dataUint = this.lightsUint;\\n\\t\\t\\t\\tconst dataFloatStart = lightIndex * this.lightsTexture.width * 4;\\n\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.POSITION_RANGE + 0] = pos.x;\\n\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.POSITION_RANGE + 1] = pos.y;\\n\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.POSITION_RANGE + 2] = pos.z;\\n\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.POSITION_RANGE + 3] = light.attenuationEnd;\\n\\t\\t\\t\\tconst clusteredData = light.clusteredData;\\n\\t\\t\\t\\tdataUint[dataFloatStart + 4 * TextureIndexFloat.COLOR_ANGLES_BIAS + 0] = clusteredData[0];\\n\\t\\t\\t\\tdataUint[dataFloatStart + 4 * TextureIndexFloat.COLOR_ANGLES_BIAS + 1] = clusteredData[1];\\n\\t\\t\\t\\tdataUint[dataFloatStart + 4 * TextureIndexFloat.COLOR_ANGLES_BIAS + 2] = clusteredData[2];\\n\\t\\t\\t\\tif (light.castShadows) {\\n\\t\\t\\t\\t\\t\\tconst lightRenderData = light.getRenderData(null, 0);\\n\\t\\t\\t\\t\\t\\tconst biases = light._getUniformBiasValues(lightRenderData);\\n\\t\\t\\t\\t\\t\\tconst biasHalf = FloatPacking.float2Half(biases.bias);\\n\\t\\t\\t\\t\\t\\tconst normalBiasHalf = FloatPacking.float2Half(biases.normalBias);\\n\\t\\t\\t\\t\\t\\tdataUint[dataFloatStart + 4 * TextureIndexFloat.COLOR_ANGLES_BIAS + 3] = biasHalf | normalBiasHalf << 16;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (isSpot) {\\n\\t\\t\\t\\t\\t\\tthis.getSpotDirection(tempVec3$1, light);\\n\\t\\t\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.DIRECTION_FLAGS + 0] = tempVec3$1.x;\\n\\t\\t\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.DIRECTION_FLAGS + 1] = tempVec3$1.y;\\n\\t\\t\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.DIRECTION_FLAGS + 2] = tempVec3$1.z;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdataUint[dataFloatStart + 4 * TextureIndexFloat.DIRECTION_FLAGS + 3] = light.getClusteredFlags(castShadows, isCookie);\\n\\t\\t\\t\\tif (lightProjectionMatrix) {\\n\\t\\t\\t\\t\\t\\tconst matData = lightProjectionMatrix.data;\\n\\t\\t\\t\\t\\t\\tfor(let m = 0; m < 16; m++){\\n\\t\\t\\t\\t\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.PROJ_MAT_0 + m] = matData[m];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (atlasViewport) {\\n\\t\\t\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.ATLAS_VIEWPORT + 0] = atlasViewport.x;\\n\\t\\t\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.ATLAS_VIEWPORT + 1] = atlasViewport.y;\\n\\t\\t\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.ATLAS_VIEWPORT + 2] = atlasViewport.z / 3;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (isArea) {\\n\\t\\t\\t\\t\\t\\tconst areaSizes = this.getLightAreaSizes(light);\\n\\t\\t\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.AREA_DATA_WIDTH + 0] = areaSizes[0];\\n\\t\\t\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.AREA_DATA_WIDTH + 1] = areaSizes[1];\\n\\t\\t\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.AREA_DATA_WIDTH + 2] = areaSizes[2];\\n\\t\\t\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.AREA_DATA_HEIGHT + 0] = areaSizes[3];\\n\\t\\t\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.AREA_DATA_HEIGHT + 1] = areaSizes[4];\\n\\t\\t\\t\\t\\t\\tdataFloat[dataFloatStart + 4 * TextureIndexFloat.AREA_DATA_HEIGHT + 2] = areaSizes[5];\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis.areaLightsEnabled = false;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set('lightBufferDefinesPS', lightBufferDefines);\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set('lightBufferDefinesPS', lightBufferDefines);\\n\\t\\t\\t\\tthis.cookiesEnabled = false;\\n\\t\\t\\t\\tthis.shadowsEnabled = false;\\n\\t\\t\\t\\tthis.areaLightsEnabled = false;\\n\\t\\t\\t\\tthis.maxLights = 255;\\n\\t\\t\\t\\tconst pixelsPerLightFloat = TextureIndexFloat.COUNT;\\n\\t\\t\\t\\tthis.lightsFloat = new Float32Array(4 * pixelsPerLightFloat * this.maxLights);\\n\\t\\t\\t\\tthis.lightsUint = new Uint32Array(this.lightsFloat.buffer);\\n\\t\\t\\t\\tthis.lightsTexture = this.createTexture(this.device, pixelsPerLightFloat, this.maxLights, PIXELFORMAT_RGBA32F, 'LightsTexture');\\n\\t\\t\\t\\tthis._lightsTextureId = this.device.scope.resolve('lightsTexture');\\n\\t\\t\\t\\tthis.invMaxColorValue = 0;\\n\\t\\t\\t\\tthis.invMaxAttenuation = 0;\\n\\t\\t\\t\\tthis.boundsMin = new Vec3();\\n\\t\\t\\t\\tthis.boundsDelta = new Vec3();\\n\\t\\t}\\n}\\n\\nconst tempVec3 = new Vec3();\\nconst tempMin3 = new Vec3();\\nconst tempMax3 = new Vec3();\\nconst tempBox = new BoundingBox();\\nclass ClusterLight {\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.light = null;\\n\\t\\t\\t\\tthis.min = new Vec3();\\n\\t\\t\\t\\tthis.max = new Vec3();\\n\\t\\t}\\n}\\nclass WorldClusters {\\n\\t\\tset maxCellLightCount(count) {\\n\\t\\t\\t\\tif (count !== this._maxCellLightCount) {\\n\\t\\t\\t\\t\\t\\tthis._maxCellLightCount = count;\\n\\t\\t\\t\\t\\t\\tthis._cellsDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget maxCellLightCount() {\\n\\t\\t\\t\\treturn this._maxCellLightCount;\\n\\t\\t}\\n\\t\\tset cells(value) {\\n\\t\\t\\t\\ttempVec3.copy(value).floor();\\n\\t\\t\\t\\tif (!this._cells.equals(tempVec3)) {\\n\\t\\t\\t\\t\\t\\tthis._cells.copy(tempVec3);\\n\\t\\t\\t\\t\\t\\tthis._cellsLimit.copy(tempVec3).sub(Vec3.ONE);\\n\\t\\t\\t\\t\\t\\tthis._cellsDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget cells() {\\n\\t\\t\\t\\treturn this._cells;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.lightsBuffer.destroy();\\n\\t\\t\\t\\tthis.releaseClusterTexture();\\n\\t\\t}\\n\\t\\treleaseClusterTexture() {\\n\\t\\t\\t\\tif (this.clusterTexture) {\\n\\t\\t\\t\\t\\t\\tthis.clusterTexture.destroy();\\n\\t\\t\\t\\t\\t\\tthis.clusterTexture = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tregisterUniforms(device) {\\n\\t\\t\\t\\tthis._numClusteredLightsId = device.scope.resolve('numClusteredLights');\\n\\t\\t\\t\\tthis._clusterMaxCellsId = device.scope.resolve('clusterMaxCells');\\n\\t\\t\\t\\tthis._clusterWorldTextureId = device.scope.resolve('clusterWorldTexture');\\n\\t\\t\\t\\tthis._clusterBoundsMinId = device.scope.resolve('clusterBoundsMin');\\n\\t\\t\\t\\tthis._clusterBoundsMinData = new Float32Array(3);\\n\\t\\t\\t\\tthis._clusterBoundsDeltaId = device.scope.resolve('clusterBoundsDelta');\\n\\t\\t\\t\\tthis._clusterBoundsDeltaData = new Float32Array(3);\\n\\t\\t\\t\\tthis._clusterCellsCountByBoundsSizeId = device.scope.resolve('clusterCellsCountByBoundsSize');\\n\\t\\t\\t\\tthis._clusterCellsCountByBoundsSizeData = new Float32Array(3);\\n\\t\\t\\t\\tthis._clusterCellsDotId = device.scope.resolve('clusterCellsDot');\\n\\t\\t\\t\\tthis._clusterCellsDotData = new Int32Array(3);\\n\\t\\t\\t\\tthis._clusterCellsMaxId = device.scope.resolve('clusterCellsMax');\\n\\t\\t\\t\\tthis._clusterCellsMaxData = new Int32Array(3);\\n\\t\\t\\t\\tthis._clusterTextureWidthId = device.scope.resolve('clusterTextureWidth');\\n\\t\\t}\\n\\t\\tupdateParams(lightingParams) {\\n\\t\\t\\t\\tif (lightingParams) {\\n\\t\\t\\t\\t\\t\\tthis.cells = lightingParams.cells;\\n\\t\\t\\t\\t\\t\\tthis.maxCellLightCount = lightingParams.maxLightsPerCell;\\n\\t\\t\\t\\t\\t\\tthis.lightsBuffer.cookiesEnabled = lightingParams.cookiesEnabled;\\n\\t\\t\\t\\t\\t\\tthis.lightsBuffer.shadowsEnabled = lightingParams.shadowsEnabled;\\n\\t\\t\\t\\t\\t\\tthis.lightsBuffer.areaLightsEnabled = lightingParams.areaLightsEnabled;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateCells() {\\n\\t\\t\\t\\tif (this._cellsDirty) {\\n\\t\\t\\t\\t\\t\\tthis._cellsDirty = false;\\n\\t\\t\\t\\t\\t\\tconst cx = this._cells.x;\\n\\t\\t\\t\\t\\t\\tconst cy = this._cells.y;\\n\\t\\t\\t\\t\\t\\tconst cz = this._cells.z;\\n\\t\\t\\t\\t\\t\\tconst numCells = cx * cy * cz;\\n\\t\\t\\t\\t\\t\\tconst totalPixels = this.maxCellLightCount * numCells;\\n\\t\\t\\t\\t\\t\\tlet width = Math.ceil(Math.sqrt(totalPixels));\\n\\t\\t\\t\\t\\t\\twidth = math.roundUp(width, this.maxCellLightCount);\\n\\t\\t\\t\\t\\t\\tconst height = Math.ceil(totalPixels / width);\\n\\t\\t\\t\\t\\t\\tthis._clusterCellsMaxData[0] = cx;\\n\\t\\t\\t\\t\\t\\tthis._clusterCellsMaxData[1] = cy;\\n\\t\\t\\t\\t\\t\\tthis._clusterCellsMaxData[2] = cz;\\n\\t\\t\\t\\t\\t\\tthis._clusterCellsDotData[0] = this.maxCellLightCount;\\n\\t\\t\\t\\t\\t\\tthis._clusterCellsDotData[1] = cx * cz * this.maxCellLightCount;\\n\\t\\t\\t\\t\\t\\tthis._clusterCellsDotData[2] = cx * this.maxCellLightCount;\\n\\t\\t\\t\\t\\t\\tthis.clusters = new Uint8ClampedArray(totalPixels);\\n\\t\\t\\t\\t\\t\\tthis.counts = new Int32Array(numCells);\\n\\t\\t\\t\\t\\t\\tthis.releaseClusterTexture();\\n\\t\\t\\t\\t\\t\\tthis.clusterTexture = this.lightsBuffer.createTexture(this.device, width, height, PIXELFORMAT_R8U, 'ClusterTexture');\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tuploadTextures() {\\n\\t\\t\\t\\tthis.clusterTexture.lock().set(this.clusters);\\n\\t\\t\\t\\tthis.clusterTexture.unlock();\\n\\t\\t\\t\\tthis.lightsBuffer.uploadTextures();\\n\\t\\t}\\n\\t\\tupdateUniforms() {\\n\\t\\t\\t\\tthis._numClusteredLightsId.setValue(this._usedLights.length);\\n\\t\\t\\t\\tthis.lightsBuffer.updateUniforms();\\n\\t\\t\\t\\tthis._clusterWorldTextureId.setValue(this.clusterTexture);\\n\\t\\t\\t\\tthis._clusterMaxCellsId.setValue(this.maxCellLightCount);\\n\\t\\t\\t\\tconst boundsDelta = this.boundsDelta;\\n\\t\\t\\t\\tthis._clusterCellsCountByBoundsSizeData[0] = this._cells.x / boundsDelta.x;\\n\\t\\t\\t\\tthis._clusterCellsCountByBoundsSizeData[1] = this._cells.y / boundsDelta.y;\\n\\t\\t\\t\\tthis._clusterCellsCountByBoundsSizeData[2] = this._cells.z / boundsDelta.z;\\n\\t\\t\\t\\tthis._clusterCellsCountByBoundsSizeId.setValue(this._clusterCellsCountByBoundsSizeData);\\n\\t\\t\\t\\tthis._clusterBoundsMinData[0] = this.boundsMin.x;\\n\\t\\t\\t\\tthis._clusterBoundsMinData[1] = this.boundsMin.y;\\n\\t\\t\\t\\tthis._clusterBoundsMinData[2] = this.boundsMin.z;\\n\\t\\t\\t\\tthis._clusterBoundsDeltaData[0] = boundsDelta.x;\\n\\t\\t\\t\\tthis._clusterBoundsDeltaData[1] = boundsDelta.y;\\n\\t\\t\\t\\tthis._clusterBoundsDeltaData[2] = boundsDelta.z;\\n\\t\\t\\t\\tthis._clusterBoundsMinId.setValue(this._clusterBoundsMinData);\\n\\t\\t\\t\\tthis._clusterBoundsDeltaId.setValue(this._clusterBoundsDeltaData);\\n\\t\\t\\t\\tthis._clusterCellsDotId.setValue(this._clusterCellsDotData);\\n\\t\\t\\t\\tthis._clusterCellsMaxId.setValue(this._clusterCellsMaxData);\\n\\t\\t\\t\\tthis._clusterTextureWidthId.setValue(this.clusterTexture.width);\\n\\t\\t}\\n\\t\\tevalLightCellMinMax(clusteredLight, min, max) {\\n\\t\\t\\t\\tmin.copy(clusteredLight.min);\\n\\t\\t\\t\\tmin.sub(this.boundsMin);\\n\\t\\t\\t\\tmin.div(this.boundsDelta);\\n\\t\\t\\t\\tmin.mul2(min, this.cells);\\n\\t\\t\\t\\tmin.floor();\\n\\t\\t\\t\\tmax.copy(clusteredLight.max);\\n\\t\\t\\t\\tmax.sub(this.boundsMin);\\n\\t\\t\\t\\tmax.div(this.boundsDelta);\\n\\t\\t\\t\\tmax.mul2(max, this.cells);\\n\\t\\t\\t\\tmax.ceil();\\n\\t\\t\\t\\tmin.max(Vec3.ZERO);\\n\\t\\t\\t\\tmax.min(this._cellsLimit);\\n\\t\\t}\\n\\t\\tcollectLights(lights) {\\n\\t\\t\\t\\tconst maxLights = this.lightsBuffer.maxLights;\\n\\t\\t\\t\\tconst usedLights = this._usedLights;\\n\\t\\t\\t\\tlet lightIndex = 1;\\n\\t\\t\\t\\tlights.forEach((light)=>{\\n\\t\\t\\t\\t\\t\\tconst runtimeLight = !!(light.mask & (MASK_AFFECT_DYNAMIC | MASK_AFFECT_LIGHTMAPPED));\\n\\t\\t\\t\\t\\t\\tconst zeroAngleSpotlight = light.type === LIGHTTYPE_SPOT && light._outerConeAngle === 0;\\n\\t\\t\\t\\t\\t\\tif (light.enabled && light.type !== LIGHTTYPE_DIRECTIONAL && light.visibleThisFrame && light.intensity > 0 && runtimeLight && !zeroAngleSpotlight) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (lightIndex < maxLights) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet clusteredLight;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (lightIndex < usedLights.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tclusteredLight = usedLights[lightIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tclusteredLight = new ClusterLight();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tusedLights.push(clusteredLight);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tclusteredLight.light = light;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlight.getBoundingBox(tempBox);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tclusteredLight.min.copy(tempBox.getMin());\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tclusteredLight.max.copy(tempBox.getMax());\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlightIndex++;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tusedLights.length = lightIndex;\\n\\t\\t}\\n\\t\\tevaluateBounds() {\\n\\t\\t\\t\\tconst usedLights = this._usedLights;\\n\\t\\t\\t\\tconst min = this.boundsMin;\\n\\t\\t\\t\\tconst max = this.boundsMax;\\n\\t\\t\\t\\tif (usedLights.length > 1) {\\n\\t\\t\\t\\t\\t\\tmin.copy(usedLights[1].min);\\n\\t\\t\\t\\t\\t\\tmax.copy(usedLights[1].max);\\n\\t\\t\\t\\t\\t\\tfor(let i = 2; i < usedLights.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tmin.min(usedLights[i].min);\\n\\t\\t\\t\\t\\t\\t\\t\\tmax.max(usedLights[i].max);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tmin.set(0, 0, 0);\\n\\t\\t\\t\\t\\t\\tmax.set(1, 1, 1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.boundsDelta.sub2(max, min);\\n\\t\\t\\t\\tthis.lightsBuffer.setBounds(min, this.boundsDelta);\\n\\t\\t}\\n\\t\\tupdateClusters(lightingParams) {\\n\\t\\t\\t\\tthis.counts.fill(0);\\n\\t\\t\\t\\tthis.clusters.fill(0);\\n\\t\\t\\t\\tthis.lightsBuffer.areaLightsEnabled = lightingParams ? lightingParams.areaLightsEnabled : false;\\n\\t\\t\\t\\tconst divX = this._cells.x;\\n\\t\\t\\t\\tconst divZ = this._cells.z;\\n\\t\\t\\t\\tconst counts = this.counts;\\n\\t\\t\\t\\tconst limit = this._maxCellLightCount;\\n\\t\\t\\t\\tconst clusters = this.clusters;\\n\\t\\t\\t\\tconst pixelsPerCellCount = this.maxCellLightCount;\\n\\t\\t\\t\\tconst usedLights = this._usedLights;\\n\\t\\t\\t\\tfor(let i = 1; i < usedLights.length; i++){\\n\\t\\t\\t\\t\\t\\tconst clusteredLight = usedLights[i];\\n\\t\\t\\t\\t\\t\\tconst light = clusteredLight.light;\\n\\t\\t\\t\\t\\t\\tthis.lightsBuffer.addLightData(light, i);\\n\\t\\t\\t\\t\\t\\tthis.evalLightCellMinMax(clusteredLight, tempMin3, tempMax3);\\n\\t\\t\\t\\t\\t\\tconst xStart = tempMin3.x;\\n\\t\\t\\t\\t\\t\\tconst xEnd = tempMax3.x;\\n\\t\\t\\t\\t\\t\\tconst yStart = tempMin3.y;\\n\\t\\t\\t\\t\\t\\tconst yEnd = tempMax3.y;\\n\\t\\t\\t\\t\\t\\tconst zStart = tempMin3.z;\\n\\t\\t\\t\\t\\t\\tconst zEnd = tempMax3.z;\\n\\t\\t\\t\\t\\t\\tfor(let x = xStart; x <= xEnd; x++){\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let z = zStart; z <= zEnd; z++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let y = yStart; y <= yEnd; y++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst clusterIndex = x + divX * (z + y * divZ);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst count = counts[clusterIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (count < limit) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tclusters[pixelsPerCellCount * clusterIndex + count] = i;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcounts[clusterIndex] = count + 1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdate(lights, lightingParams = null) {\\n\\t\\t\\t\\tthis.updateParams(lightingParams);\\n\\t\\t\\t\\tthis.updateCells();\\n\\t\\t\\t\\tthis.collectLights(lights);\\n\\t\\t\\t\\tthis.evaluateBounds();\\n\\t\\t\\t\\tthis.updateClusters(lightingParams);\\n\\t\\t\\t\\tthis.uploadTextures();\\n\\t\\t}\\n\\t\\tactivate() {\\n\\t\\t\\t\\tthis.updateUniforms();\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.name = 'Untitled';\\n\\t\\t\\t\\tthis.reportCount = 0;\\n\\t\\t\\t\\tthis.boundsMin = new Vec3();\\n\\t\\t\\t\\tthis.boundsMax = new Vec3();\\n\\t\\t\\t\\tthis.boundsDelta = new Vec3();\\n\\t\\t\\t\\tthis._cells = new Vec3(1, 1, 1);\\n\\t\\t\\t\\tthis._cellsLimit = new Vec3();\\n\\t\\t\\t\\tthis.cells = this._cells;\\n\\t\\t\\t\\tthis.maxCellLightCount = 4;\\n\\t\\t\\t\\tthis._usedLights = [];\\n\\t\\t\\t\\tthis._usedLights.push(new ClusterLight());\\n\\t\\t\\t\\tthis.lightsBuffer = new LightsBuffer(device);\\n\\t\\t\\t\\tthis.registerUniforms(device);\\n\\t\\t}\\n}\\n\\nconst base64String = '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';\\nlet data = null;\\nconst initData = ()=>{\\n\\t\\tif (!data) {\\n\\t\\t\\t\\tconst binaryString = atob(base64String);\\n\\t\\t\\t\\tdata = Uint8Array.from(binaryString, (char)=>char.charCodeAt(0));\\n\\t\\t}\\n};\\nconst blueNoiseData = ()=>{\\n\\t\\tinitData();\\n\\t\\treturn data;\\n};\\nclass BlueNoise {\\n\\t\\t_next() {\\n\\t\\t\\t\\tthis.seed = (this.seed + 4) % data.length;\\n\\t\\t}\\n\\t\\tvalue() {\\n\\t\\t\\t\\tthis._next();\\n\\t\\t\\t\\treturn data[this.seed] / 255;\\n\\t\\t}\\n\\t\\tvec4(dest = new Vec4()) {\\n\\t\\t\\t\\tthis._next();\\n\\t\\t\\t\\treturn dest.set(data[this.seed], data[this.seed + 1], data[this.seed + 2], data[this.seed + 3]).mulScalar(1 / 255);\\n\\t\\t}\\n\\t\\tconstructor(seed = 0){\\n\\t\\t\\t\\tthis.seed = 0;\\n\\t\\t\\t\\tthis.seed = seed * 4;\\n\\t\\t\\t\\tinitData();\\n\\t\\t}\\n}\\n\\nconst lightCubeDir = [\\n\\t\\tnew Vec3(-1, 0, 0),\\n\\t\\tnew Vec3(1, 0, 0),\\n\\t\\tnew Vec3(0, -1, 0),\\n\\t\\tnew Vec3(0, 1, 0),\\n\\t\\tnew Vec3(0, 0, -1),\\n\\t\\tnew Vec3(0, 0, 1)\\n];\\nclass LightCube {\\n\\t\\tupdate(ambientLight, lights) {\\n\\t\\t\\t\\tconst colors = this.colors;\\n\\t\\t\\t\\tconst { r, g, b } = ambientLight;\\n\\t\\t\\t\\tfor(let j = 0; j < 6; j++){\\n\\t\\t\\t\\t\\t\\tcolors[j * 3] = r;\\n\\t\\t\\t\\t\\t\\tcolors[j * 3 + 1] = g;\\n\\t\\t\\t\\t\\t\\tcolors[j * 3 + 2] = b;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let j = 0; j < lights.length; j++){\\n\\t\\t\\t\\t\\t\\tconst light = lights[j];\\n\\t\\t\\t\\t\\t\\tif (light._type === LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let c = 0; c < 6; c++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst weight = Math.max(lightCubeDir[c].dot(light._direction), 0) * light._intensity;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst lightColor = light._color;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcolors[c * 3] += lightColor.r * weight;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcolors[c * 3 + 1] += lightColor.g * weight;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcolors[c * 3 + 2] += lightColor.b * weight;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.colors = new Float32Array(6 * 3);\\n\\t\\t}\\n}\\n\\nconst createTexture = (device, namePrefix, size, data)=>{\\n\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\t\\tname: `${namePrefix}${size}`,\\n\\t\\t\\t\\twidth: size,\\n\\t\\t\\t\\theight: size,\\n\\t\\t\\t\\tformat: PIXELFORMAT_RGBA8,\\n\\t\\t\\t\\taddressU: ADDRESS_REPEAT,\\n\\t\\t\\t\\taddressV: ADDRESS_REPEAT,\\n\\t\\t\\t\\ttype: TEXTURETYPE_DEFAULT,\\n\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\tanisotropy: 1,\\n\\t\\t\\t\\tmipmaps: false\\n\\t\\t});\\n\\t\\ttexture.lock().set(data);\\n\\t\\ttexture.unlock();\\n\\t\\treturn texture;\\n};\\nconst deviceCacheBlueNoise = new DeviceCache();\\nconst getBlueNoiseTexture = (device)=>{\\n\\t\\treturn deviceCacheBlueNoise.get(device, ()=>{\\n\\t\\t\\t\\tconst data = blueNoiseData();\\n\\t\\t\\t\\tconst size = Math.sqrt(data.length / 4);\\n\\t\\t\\t\\treturn createTexture(device, 'BlueNoise', size, data);\\n\\t\\t});\\n};\\n\\nclass ShadowMap {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tif (this.texture) {\\n\\t\\t\\t\\t\\t\\tthis.texture.destroy();\\n\\t\\t\\t\\t\\t\\tthis.texture = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst targets = this.renderTargets;\\n\\t\\t\\t\\tfor(let i = 0; i < targets.length; i++){\\n\\t\\t\\t\\t\\t\\ttargets[i].destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.renderTargets.length = 0;\\n\\t\\t}\\n\\t\\tstatic create(device, light) {\\n\\t\\t\\t\\tlet shadowMap = null;\\n\\t\\t\\t\\tif (light._type === LIGHTTYPE_OMNI) {\\n\\t\\t\\t\\t\\t\\tshadowMap = this.createCubemap(device, light._shadowResolution, light._shadowType);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tshadowMap = this.create2dMap(device, light._shadowResolution, light._shadowType);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn shadowMap;\\n\\t\\t}\\n\\t\\tstatic createAtlas(device, resolution, shadowType) {\\n\\t\\t\\t\\tconst shadowMap = this.create2dMap(device, resolution, shadowType);\\n\\t\\t\\t\\tconst targets = shadowMap.renderTargets;\\n\\t\\t\\t\\tconst rt = targets[0];\\n\\t\\t\\t\\tfor(let i = 0; i < 5; i++){\\n\\t\\t\\t\\t\\t\\ttargets.push(rt);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn shadowMap;\\n\\t\\t}\\n\\t\\tstatic create2dMap(device, size, shadowType) {\\n\\t\\t\\t\\tconst shadowInfo = shadowTypeInfo.get(shadowType);\\n\\t\\t\\t\\tlet format = shadowInfo.format;\\n\\t\\t\\t\\tif (format === PIXELFORMAT_R32F && !device.textureFloatRenderable && device.textureHalfFloatRenderable) {\\n\\t\\t\\t\\t\\t\\tformat = PIXELFORMAT_R16F;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst formatName = pixelFormatInfo.get(format)?.name;\\n\\t\\t\\t\\tlet filter = FILTER_LINEAR;\\n\\t\\t\\t\\tif (shadowType === SHADOW_VSM_32F) {\\n\\t\\t\\t\\t\\t\\tfilter = device.extTextureFloatLinear ? FILTER_LINEAR : FILTER_NEAREST;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (shadowType === SHADOW_PCSS_32F) {\\n\\t\\t\\t\\t\\t\\tfilter = FILTER_NEAREST;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\twidth: size,\\n\\t\\t\\t\\t\\t\\theight: size,\\n\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\tminFilter: filter,\\n\\t\\t\\t\\t\\t\\tmagFilter: filter,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\tname: `ShadowMap2D_${formatName}`\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tlet target = null;\\n\\t\\t\\t\\tif (shadowInfo?.pcf) {\\n\\t\\t\\t\\t\\t\\ttexture.compareOnRead = true;\\n\\t\\t\\t\\t\\t\\ttexture.compareFunc = FUNC_LESS;\\n\\t\\t\\t\\t\\t\\ttarget = new RenderTarget({\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthBuffer: texture\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\ttarget = new RenderTarget({\\n\\t\\t\\t\\t\\t\\t\\t\\tcolorBuffer: texture,\\n\\t\\t\\t\\t\\t\\t\\t\\tdepth: true\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (device.isWebGPU) {\\n\\t\\t\\t\\t\\t\\ttarget.flipY = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn new ShadowMap(texture, [\\n\\t\\t\\t\\t\\t\\ttarget\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tstatic createCubemap(device, size, shadowType) {\\n\\t\\t\\t\\tconst shadowInfo = shadowTypeInfo.get(shadowType);\\n\\t\\t\\t\\tconst formatName = pixelFormatInfo.get(shadowInfo.format)?.name;\\n\\t\\t\\t\\tconst isPcss = shadowType === SHADOW_PCSS_32F;\\n\\t\\t\\t\\tconst filter = isPcss ? FILTER_NEAREST : FILTER_LINEAR;\\n\\t\\t\\t\\tconst cubemap = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tformat: shadowInfo?.format,\\n\\t\\t\\t\\t\\t\\twidth: size,\\n\\t\\t\\t\\t\\t\\theight: size,\\n\\t\\t\\t\\t\\t\\tcubemap: true,\\n\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\tminFilter: filter,\\n\\t\\t\\t\\t\\t\\tmagFilter: filter,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\tname: `ShadowMapCube_${formatName}`\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (!isPcss) {\\n\\t\\t\\t\\t\\t\\tcubemap.compareOnRead = true;\\n\\t\\t\\t\\t\\t\\tcubemap.compareFunc = FUNC_LESS;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst targets = [];\\n\\t\\t\\t\\tfor(let i = 0; i < 6; i++){\\n\\t\\t\\t\\t\\t\\tif (isPcss) {\\n\\t\\t\\t\\t\\t\\t\\t\\ttargets.push(new RenderTarget({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcolorBuffer: cubemap,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tface: i,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdepth: true\\n\\t\\t\\t\\t\\t\\t\\t\\t}));\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\ttargets.push(new RenderTarget({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdepthBuffer: cubemap,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tface: i\\n\\t\\t\\t\\t\\t\\t\\t\\t}));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn new ShadowMap(cubemap, targets);\\n\\t\\t}\\n\\t\\tconstructor(texture, targets){\\n\\t\\t\\t\\tthis.texture = texture;\\n\\t\\t\\t\\tthis.cached = false;\\n\\t\\t\\t\\tthis.renderTargets = targets;\\n\\t\\t}\\n}\\n\\nconst _tempArray = [];\\nconst _tempArray2 = [];\\nconst _viewport$1 = new Vec4();\\nconst _scissor = new Vec4();\\nclass Slot {\\n\\t\\tconstructor(rect){\\n\\t\\t\\t\\tthis.size = Math.floor(rect.w * 1024);\\n\\t\\t\\t\\tthis.used = false;\\n\\t\\t\\t\\tthis.lightId = -1;\\n\\t\\t\\t\\tthis.rect = rect;\\n\\t\\t}\\n}\\nclass LightTextureAtlas {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.destroyShadowAtlas();\\n\\t\\t\\t\\tthis.destroyCookieAtlas();\\n\\t\\t}\\n\\t\\tdestroyShadowAtlas() {\\n\\t\\t\\t\\tthis.shadowAtlas?.destroy();\\n\\t\\t\\t\\tthis.shadowAtlas = null;\\n\\t\\t}\\n\\t\\tdestroyCookieAtlas() {\\n\\t\\t\\t\\tthis.cookieAtlas?.destroy();\\n\\t\\t\\t\\tthis.cookieAtlas = null;\\n\\t\\t\\t\\tthis.cookieRenderTarget?.destroy();\\n\\t\\t\\t\\tthis.cookieRenderTarget = null;\\n\\t\\t}\\n\\t\\tallocateShadowAtlas(resolution, shadowType = SHADOW_PCF3_32F) {\\n\\t\\t\\t\\tconst existingFormat = this.shadowAtlas?.texture.format;\\n\\t\\t\\t\\tconst requiredFormat = shadowTypeInfo.get(shadowType).format;\\n\\t\\t\\t\\tif (!this.shadowAtlas || this.shadowAtlas.texture.width !== resolution || existingFormat !== requiredFormat) {\\n\\t\\t\\t\\t\\t\\tthis.version++;\\n\\t\\t\\t\\t\\t\\tthis.destroyShadowAtlas();\\n\\t\\t\\t\\t\\t\\tthis.shadowAtlas = ShadowMap.createAtlas(this.device, resolution, shadowType);\\n\\t\\t\\t\\t\\t\\tthis.shadowAtlas.cached = true;\\n\\t\\t\\t\\t\\t\\tconst scissorOffset = 4 / this.shadowAtlasResolution;\\n\\t\\t\\t\\t\\t\\tthis.scissorVec.set(scissorOffset, scissorOffset, -2 * scissorOffset, -2 * scissorOffset);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tallocateCookieAtlas(resolution) {\\n\\t\\t\\t\\tif (this.cookieAtlas.width !== resolution) {\\n\\t\\t\\t\\t\\t\\tthis.cookieRenderTarget.resize(resolution, resolution);\\n\\t\\t\\t\\t\\t\\tthis.version++;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tallocateUniforms() {\\n\\t\\t\\t\\tthis._shadowAtlasTextureId = this.device.scope.resolve('shadowAtlasTexture');\\n\\t\\t\\t\\tthis._shadowAtlasParamsId = this.device.scope.resolve('shadowAtlasParams');\\n\\t\\t\\t\\tthis._shadowAtlasParams = new Float32Array(2);\\n\\t\\t\\t\\tthis._cookieAtlasTextureId = this.device.scope.resolve('cookieAtlasTexture');\\n\\t\\t}\\n\\t\\tupdateUniforms() {\\n\\t\\t\\t\\tconst rt = this.shadowAtlas.renderTargets[0];\\n\\t\\t\\t\\tconst shadowBuffer = rt.depthBuffer;\\n\\t\\t\\t\\tthis._shadowAtlasTextureId.setValue(shadowBuffer);\\n\\t\\t\\t\\tthis._shadowAtlasParams[0] = this.shadowAtlasResolution;\\n\\t\\t\\t\\tthis._shadowAtlasParams[1] = this.shadowEdgePixels;\\n\\t\\t\\t\\tthis._shadowAtlasParamsId.setValue(this._shadowAtlasParams);\\n\\t\\t\\t\\tthis._cookieAtlasTextureId.setValue(this.cookieAtlas);\\n\\t\\t}\\n\\t\\tsubdivide(numLights, lightingParams) {\\n\\t\\t\\t\\tlet atlasSplit = lightingParams.atlasSplit;\\n\\t\\t\\t\\tif (!atlasSplit) {\\n\\t\\t\\t\\t\\t\\tconst gridSize = Math.ceil(Math.sqrt(numLights));\\n\\t\\t\\t\\t\\t\\tatlasSplit = _tempArray2;\\n\\t\\t\\t\\t\\t\\tatlasSplit[0] = gridSize;\\n\\t\\t\\t\\t\\t\\tatlasSplit.length = 1;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst arraysEqual = (a, b)=>a.length === b.length && a.every((v, i)=>v === b[i]);\\n\\t\\t\\t\\tif (!arraysEqual(atlasSplit, this.atlasSplit)) {\\n\\t\\t\\t\\t\\t\\tthis.version++;\\n\\t\\t\\t\\t\\t\\tthis.slots.length = 0;\\n\\t\\t\\t\\t\\t\\tthis.atlasSplit.length = 0;\\n\\t\\t\\t\\t\\t\\tthis.atlasSplit.push(...atlasSplit);\\n\\t\\t\\t\\t\\t\\tconst splitCount = this.atlasSplit[0];\\n\\t\\t\\t\\t\\t\\tif (splitCount > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst invSize = 1 / splitCount;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < splitCount; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < splitCount; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst rect = new Vec4(i * invSize, j * invSize, invSize, invSize);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst nextLevelSplit = this.atlasSplit[1 + i * splitCount + j];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (nextLevelSplit > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let x = 0; x < nextLevelSplit; x++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let y = 0; y < nextLevelSplit; y++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst invSizeNext = invSize / nextLevelSplit;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.slots.push(new Slot(rectNext));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.slots.push(new Slot(rect));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.slots.push(new Slot(new Vec4(0, 0, 1, 1)));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.slots.sort((a, b)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\treturn b.size - a.size;\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcollectLights(localLights, lightingParams) {\\n\\t\\t\\t\\tconst cookiesEnabled = lightingParams.cookiesEnabled;\\n\\t\\t\\t\\tconst shadowsEnabled = lightingParams.shadowsEnabled;\\n\\t\\t\\t\\tlet needsShadowAtlas = false;\\n\\t\\t\\t\\tlet needsCookieAtlas = false;\\n\\t\\t\\t\\tconst lights = _tempArray;\\n\\t\\t\\t\\tlights.length = 0;\\n\\t\\t\\t\\tconst processLights = (list)=>{\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < list.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst light = list[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (light.visibleThisFrame) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst lightShadow = shadowsEnabled && light.castShadows;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst lightCookie = cookiesEnabled && !!light.cookie;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tneedsShadowAtlas || (needsShadowAtlas = lightShadow);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tneedsCookieAtlas || (needsCookieAtlas = lightCookie);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (lightShadow || lightCookie) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlights.push(light);\\n\\t\\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}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (cookiesEnabled || shadowsEnabled) {\\n\\t\\t\\t\\t\\t\\tprocessLights(localLights);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlights.sort((a, b)=>{\\n\\t\\t\\t\\t\\t\\treturn b.maxScreenSize - a.maxScreenSize;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (needsShadowAtlas) {\\n\\t\\t\\t\\t\\t\\tthis.allocateShadowAtlas(this.shadowAtlasResolution, lightingParams.shadowType);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (needsCookieAtlas) {\\n\\t\\t\\t\\t\\t\\tthis.allocateCookieAtlas(this.cookieAtlasResolution);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (needsShadowAtlas || needsCookieAtlas) {\\n\\t\\t\\t\\t\\t\\tthis.subdivide(lights.length, lightingParams);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn lights;\\n\\t\\t}\\n\\t\\tsetupSlot(light, rect) {\\n\\t\\t\\t\\tlight.atlasViewport.copy(rect);\\n\\t\\t\\t\\tconst faceCount = light.numShadowFaces;\\n\\t\\t\\t\\tfor(let face = 0; face < faceCount; face++){\\n\\t\\t\\t\\t\\t\\tif (light.castShadows || light._cookie) {\\n\\t\\t\\t\\t\\t\\t\\t\\t_viewport$1.copy(rect);\\n\\t\\t\\t\\t\\t\\t\\t\\t_scissor.copy(rect);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (light._type === LIGHTTYPE_SPOT) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_viewport$1.add(this.scissorVec);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (light._type === LIGHTTYPE_OMNI) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst smallSize = _viewport$1.z / 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst offset = this.cubeSlotsOffsets[face];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_viewport$1.x += smallSize * offset.x;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_viewport$1.y += smallSize * offset.y;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_viewport$1.z = smallSize;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_viewport$1.w = smallSize;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_scissor.copy(_viewport$1);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (light.castShadows) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst lightRenderData = light.getRenderData(null, face);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlightRenderData.shadowViewport.copy(_viewport$1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlightRenderData.shadowScissor.copy(_scissor);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tassignSlot(light, slotIndex, slotReassigned) {\\n\\t\\t\\t\\tlight.atlasViewportAllocated = true;\\n\\t\\t\\t\\tconst slot = this.slots[slotIndex];\\n\\t\\t\\t\\tslot.lightId = light.id;\\n\\t\\t\\t\\tslot.used = true;\\n\\t\\t\\t\\tif (slotReassigned) {\\n\\t\\t\\t\\t\\t\\tlight.atlasSlotUpdated = true;\\n\\t\\t\\t\\t\\t\\tlight.atlasVersion = this.version;\\n\\t\\t\\t\\t\\t\\tlight.atlasSlotIndex = slotIndex;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdate(localLights, lightingParams) {\\n\\t\\t\\t\\tthis.shadowAtlasResolution = lightingParams.shadowAtlasResolution;\\n\\t\\t\\t\\tthis.cookieAtlasResolution = lightingParams.cookieAtlasResolution;\\n\\t\\t\\t\\tconst lights = this.collectLights(localLights, lightingParams);\\n\\t\\t\\t\\tif (lights.length > 0) {\\n\\t\\t\\t\\t\\t\\tconst slots = this.slots;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < slots.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tslots[i].used = false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst assignCount = Math.min(lights.length, slots.length);\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < assignCount; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst light = lights[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (light.castShadows) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlight._shadowMap = this.shadowAtlas;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst previousSlot = slots[light.atlasSlotIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (light.atlasVersion === this.version && light.id === previousSlot?.lightId) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst previousSlot = slots[light.atlasSlotIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (previousSlot.size === slots[i].size && !previousSlot.used) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.assignSlot(light, light.atlasSlotIndex, false);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tlet usedCount = 0;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < assignCount; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\twhile(usedCount < slots.length && slots[usedCount].used){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tusedCount++;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst light = lights[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!light.atlasViewportAllocated) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.assignSlot(light, usedCount, true);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst slot = slots[light.atlasSlotIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setupSlot(light, slot.rect);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.updateUniforms();\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.version = 1;\\n\\t\\t\\t\\tthis.shadowAtlasResolution = 2048;\\n\\t\\t\\t\\tthis.shadowAtlas = null;\\n\\t\\t\\t\\tthis.shadowEdgePixels = 3;\\n\\t\\t\\t\\tthis.cookieAtlasResolution = 4;\\n\\t\\t\\t\\tthis.cookieAtlas = new Texture(this.device, {\\n\\t\\t\\t\\t\\t\\tname: 'CookieAtlas',\\n\\t\\t\\t\\t\\t\\twidth: this.cookieAtlasResolution,\\n\\t\\t\\t\\t\\t\\theight: this.cookieAtlasResolution,\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_SRGBA8,\\n\\t\\t\\t\\t\\t\\tcubemap: false,\\n\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.cookieRenderTarget = new RenderTarget({\\n\\t\\t\\t\\t\\t\\tcolorBuffer: this.cookieAtlas,\\n\\t\\t\\t\\t\\t\\tdepth: false,\\n\\t\\t\\t\\t\\t\\tflipY: true\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.slots = [];\\n\\t\\t\\t\\tthis.atlasSplit = [];\\n\\t\\t\\t\\tthis.cubeSlotsOffsets = [\\n\\t\\t\\t\\t\\t\\tnew Vec2(0, 0),\\n\\t\\t\\t\\t\\t\\tnew Vec2(0, 1),\\n\\t\\t\\t\\t\\t\\tnew Vec2(1, 0),\\n\\t\\t\\t\\t\\t\\tnew Vec2(1, 1),\\n\\t\\t\\t\\t\\t\\tnew Vec2(2, 0),\\n\\t\\t\\t\\t\\t\\tnew Vec2(2, 1)\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.scissorVec = new Vec4();\\n\\t\\t\\t\\tthis.allocateShadowAtlas(1);\\n\\t\\t\\t\\tthis.allocateCookieAtlas(1);\\n\\t\\t\\t\\tthis.allocateUniforms();\\n\\t\\t}\\n}\\n\\nconst blendModes = [];\\nblendModes[BLEND_SUBTRACTIVE] = {\\n\\t\\tsrc: BLENDMODE_ONE,\\n\\t\\tdst: BLENDMODE_ONE,\\n\\t\\top: BLENDEQUATION_REVERSE_SUBTRACT\\n};\\nblendModes[BLEND_NONE] = {\\n\\t\\tsrc: BLENDMODE_ONE,\\n\\t\\tdst: BLENDMODE_ZERO,\\n\\t\\top: BLENDEQUATION_ADD\\n};\\nblendModes[BLEND_NORMAL] = {\\n\\t\\tsrc: BLENDMODE_SRC_ALPHA,\\n\\t\\tdst: BLENDMODE_ONE_MINUS_SRC_ALPHA,\\n\\t\\top: BLENDEQUATION_ADD,\\n\\t\\talphaSrc: BLENDMODE_ONE\\n};\\nblendModes[BLEND_PREMULTIPLIED] = {\\n\\t\\tsrc: BLENDMODE_ONE,\\n\\t\\tdst: BLENDMODE_ONE_MINUS_SRC_ALPHA,\\n\\t\\top: BLENDEQUATION_ADD\\n};\\nblendModes[BLEND_ADDITIVE] = {\\n\\t\\tsrc: BLENDMODE_ONE,\\n\\t\\tdst: BLENDMODE_ONE,\\n\\t\\top: BLENDEQUATION_ADD\\n};\\nblendModes[BLEND_ADDITIVEALPHA] = {\\n\\t\\tsrc: BLENDMODE_SRC_ALPHA,\\n\\t\\tdst: BLENDMODE_ONE,\\n\\t\\top: BLENDEQUATION_ADD\\n};\\nblendModes[BLEND_MULTIPLICATIVE2X] = {\\n\\t\\tsrc: BLENDMODE_DST_COLOR,\\n\\t\\tdst: BLENDMODE_SRC_COLOR,\\n\\t\\top: BLENDEQUATION_ADD\\n};\\nblendModes[BLEND_SCREEN] = {\\n\\t\\tsrc: BLENDMODE_ONE_MINUS_DST_COLOR,\\n\\t\\tdst: BLENDMODE_ONE,\\n\\t\\top: BLENDEQUATION_ADD\\n};\\nblendModes[BLEND_MULTIPLICATIVE] = {\\n\\t\\tsrc: BLENDMODE_DST_COLOR,\\n\\t\\tdst: BLENDMODE_ZERO,\\n\\t\\top: BLENDEQUATION_ADD\\n};\\nblendModes[BLEND_MIN] = {\\n\\t\\tsrc: BLENDMODE_ONE,\\n\\t\\tdst: BLENDMODE_ONE,\\n\\t\\top: BLENDEQUATION_MIN\\n};\\nblendModes[BLEND_MAX] = {\\n\\t\\tsrc: BLENDMODE_ONE,\\n\\t\\tdst: BLENDMODE_ONE,\\n\\t\\top: BLENDEQUATION_MAX\\n};\\nlet id$3 = 0;\\nclass Material {\\n\\t\\tget hasShaderChunks() {\\n\\t\\t\\t\\treturn this._shaderChunks != null;\\n\\t\\t}\\n\\t\\tget shaderChunks() {\\n\\t\\t\\t\\tif (!this._shaderChunks) {\\n\\t\\t\\t\\t\\t\\tthis._shaderChunks = new ShaderChunks();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._shaderChunks;\\n\\t\\t}\\n\\t\\tgetShaderChunks(shaderLanguage = SHADERLANGUAGE_GLSL) {\\n\\t\\t\\t\\tconst chunks = this.shaderChunks;\\n\\t\\t\\t\\treturn shaderLanguage === SHADERLANGUAGE_GLSL ? chunks.glsl : chunks.wgsl;\\n\\t\\t}\\n\\t\\tset shaderChunksVersion(value) {\\n\\t\\t\\t\\tthis.shaderChunks.version = value;\\n\\t\\t}\\n\\t\\tget shaderChunksVersion() {\\n\\t\\t\\t\\treturn this.shaderChunks.version;\\n\\t\\t}\\n\\t\\tset chunks(value) {\\n\\t\\t\\t\\tthis._oldChunks = value;\\n\\t\\t}\\n\\t\\tget chunks() {\\n\\t\\t\\t\\tObject.assign(this._oldChunks, Object.fromEntries(this.shaderChunks.glsl));\\n\\t\\t\\t\\treturn this._oldChunks;\\n\\t\\t}\\n\\t\\tset depthBias(value) {\\n\\t\\t\\t\\tthis._depthState.depthBias = value;\\n\\t\\t}\\n\\t\\tget depthBias() {\\n\\t\\t\\t\\treturn this._depthState.depthBias;\\n\\t\\t}\\n\\t\\tset slopeDepthBias(value) {\\n\\t\\t\\t\\tthis._depthState.depthBiasSlope = value;\\n\\t\\t}\\n\\t\\tget slopeDepthBias() {\\n\\t\\t\\t\\treturn this._depthState.depthBiasSlope;\\n\\t\\t}\\n\\t\\tset redWrite(value) {\\n\\t\\t\\t\\tthis._blendState.redWrite = value;\\n\\t\\t}\\n\\t\\tget redWrite() {\\n\\t\\t\\t\\treturn this._blendState.redWrite;\\n\\t\\t}\\n\\t\\tset greenWrite(value) {\\n\\t\\t\\t\\tthis._blendState.greenWrite = value;\\n\\t\\t}\\n\\t\\tget greenWrite() {\\n\\t\\t\\t\\treturn this._blendState.greenWrite;\\n\\t\\t}\\n\\t\\tset blueWrite(value) {\\n\\t\\t\\t\\tthis._blendState.blueWrite = value;\\n\\t\\t}\\n\\t\\tget blueWrite() {\\n\\t\\t\\t\\treturn this._blendState.blueWrite;\\n\\t\\t}\\n\\t\\tset alphaWrite(value) {\\n\\t\\t\\t\\tthis._blendState.alphaWrite = value;\\n\\t\\t}\\n\\t\\tget alphaWrite() {\\n\\t\\t\\t\\treturn this._blendState.alphaWrite;\\n\\t\\t}\\n\\t\\tget transparent() {\\n\\t\\t\\t\\treturn this._blendState.blend;\\n\\t\\t}\\n\\t\\t_updateTransparency() {\\n\\t\\t\\t\\tconst transparent = this.transparent;\\n\\t\\t\\t\\tconst meshInstances = this.meshInstances;\\n\\t\\t\\t\\tfor(let i = 0; i < meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\tmeshInstances[i].transparent = transparent;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tset blendState(value) {\\n\\t\\t\\t\\tthis._blendState.copy(value);\\n\\t\\t\\t\\tthis._updateTransparency();\\n\\t\\t}\\n\\t\\tget blendState() {\\n\\t\\t\\t\\treturn this._blendState;\\n\\t\\t}\\n\\t\\tset blendType(type) {\\n\\t\\t\\t\\tconst blendMode = blendModes[type];\\n\\t\\t\\t\\tthis._blendState.setColorBlend(blendMode.op, blendMode.src, blendMode.dst);\\n\\t\\t\\t\\tthis._blendState.setAlphaBlend(blendMode.alphaOp ?? blendMode.op, blendMode.alphaSrc ?? blendMode.src, blendMode.alphaDst ?? blendMode.dst);\\n\\t\\t\\t\\tconst blend = type !== BLEND_NONE;\\n\\t\\t\\t\\tif (this._blendState.blend !== blend) {\\n\\t\\t\\t\\t\\t\\tthis._blendState.blend = blend;\\n\\t\\t\\t\\t\\t\\tthis._updateTransparency();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._updateMeshInstanceKeys();\\n\\t\\t}\\n\\t\\tget blendType() {\\n\\t\\t\\t\\tif (!this.transparent) {\\n\\t\\t\\t\\t\\t\\treturn BLEND_NONE;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst { colorOp, colorSrcFactor, colorDstFactor, alphaOp, alphaSrcFactor, alphaDstFactor } = this._blendState;\\n\\t\\t\\t\\tfor(let i = 0; i < blendModes.length; i++){\\n\\t\\t\\t\\t\\t\\tconst blendMode = blendModes[i];\\n\\t\\t\\t\\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\\t\\t\\t\\t\\treturn i;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn BLEND_NORMAL;\\n\\t\\t}\\n\\t\\tset depthState(value) {\\n\\t\\t\\t\\tthis._depthState.copy(value);\\n\\t\\t}\\n\\t\\tget depthState() {\\n\\t\\t\\t\\treturn this._depthState;\\n\\t\\t}\\n\\t\\tset depthTest(value) {\\n\\t\\t\\t\\tthis._depthState.test = value;\\n\\t\\t}\\n\\t\\tget depthTest() {\\n\\t\\t\\t\\treturn this._depthState.test;\\n\\t\\t}\\n\\t\\tset depthFunc(value) {\\n\\t\\t\\t\\tthis._depthState.func = value;\\n\\t\\t}\\n\\t\\tget depthFunc() {\\n\\t\\t\\t\\treturn this._depthState.func;\\n\\t\\t}\\n\\t\\tset depthWrite(value) {\\n\\t\\t\\t\\tthis._depthState.write = value;\\n\\t\\t}\\n\\t\\tget depthWrite() {\\n\\t\\t\\t\\treturn this._depthState.write;\\n\\t\\t}\\n\\t\\tcopy(source) {\\n\\t\\t\\t\\tthis.name = source.name;\\n\\t\\t\\t\\tthis.alphaTest = source.alphaTest;\\n\\t\\t\\t\\tthis.alphaToCoverage = source.alphaToCoverage;\\n\\t\\t\\t\\tthis._blendState.copy(source._blendState);\\n\\t\\t\\t\\tthis._depthState.copy(source._depthState);\\n\\t\\t\\t\\tthis.cull = source.cull;\\n\\t\\t\\t\\tthis.stencilFront = source.stencilFront?.clone();\\n\\t\\t\\t\\tif (source.stencilBack) {\\n\\t\\t\\t\\t\\t\\tthis.stencilBack = source.stencilFront === source.stencilBack ? this.stencilFront : source.stencilBack.clone();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.clearParameters();\\n\\t\\t\\t\\tfor(const name in source.parameters){\\n\\t\\t\\t\\t\\t\\tif (source.parameters.hasOwnProperty(name)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._setParameterSimple(name, source.parameters[name].data);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.defines.clear();\\n\\t\\t\\t\\tsource.defines.forEach((value, key)=>this.defines.set(key, value));\\n\\t\\t\\t\\tthis._shaderChunks = source.hasShaderChunks ? new ShaderChunks() : null;\\n\\t\\t\\t\\tthis._shaderChunks?.copy(source._shaderChunks);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst clone = new this.constructor();\\n\\t\\t\\t\\treturn clone.copy(this);\\n\\t\\t}\\n\\t\\t_updateMeshInstanceKeys() {\\n\\t\\t\\t\\tconst meshInstances = this.meshInstances;\\n\\t\\t\\t\\tfor(let i = 0; i < meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\tmeshInstances[i].updateKey();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateUniforms(device, scene) {\\n\\t\\t\\t\\tif (this._dirtyShader) {\\n\\t\\t\\t\\t\\t\\tthis.clearVariants();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetShaderVariant(params) {}\\n\\t\\tupdate() {\\n\\t\\t\\t\\tif (Object.keys(this._oldChunks).length > 0) {\\n\\t\\t\\t\\t\\t\\tfor (const [key, value] of Object.entries(this._oldChunks)){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.shaderChunks.glsl.set(key, value);\\n\\t\\t\\t\\t\\t\\t\\t\\tdelete this._oldChunks[key];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._definesDirty || this._shaderChunks?.isDirty()) {\\n\\t\\t\\t\\t\\t\\tthis._definesDirty = false;\\n\\t\\t\\t\\t\\t\\tthis._shaderChunks?.resetDirty();\\n\\t\\t\\t\\t\\t\\tthis.clearVariants();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t}\\n\\t\\tclearParameters() {\\n\\t\\t\\t\\tthis.parameters = {};\\n\\t\\t}\\n\\t\\tgetParameters() {\\n\\t\\t\\t\\treturn this.parameters;\\n\\t\\t}\\n\\t\\tclearVariants() {\\n\\t\\t\\t\\tthis.variants.clear();\\n\\t\\t\\t\\tconst meshInstances = this.meshInstances;\\n\\t\\t\\t\\tconst count = meshInstances.length;\\n\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\tmeshInstances[i].clearShaders();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetParameter(name) {\\n\\t\\t\\t\\treturn this.parameters[name];\\n\\t\\t}\\n\\t\\t_setParameterSimple(name, data) {\\n\\t\\t\\t\\tconst param = this.parameters[name];\\n\\t\\t\\t\\tif (param) {\\n\\t\\t\\t\\t\\t\\tparam.data = data;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.parameters[name] = {\\n\\t\\t\\t\\t\\t\\t\\t\\tscopeId: null,\\n\\t\\t\\t\\t\\t\\t\\t\\tdata: data\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetParameter(name, data) {\\n\\t\\t\\t\\tif (data === undefined && typeof name === 'object') {\\n\\t\\t\\t\\t\\t\\tconst uniformObject = name;\\n\\t\\t\\t\\t\\t\\tif (uniformObject.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < uniformObject.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.setParameter(uniformObject[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tname = uniformObject.name;\\n\\t\\t\\t\\t\\t\\tdata = uniformObject.value;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._setParameterSimple(name, data);\\n\\t\\t}\\n\\t\\tdeleteParameter(name) {\\n\\t\\t\\t\\tif (this.parameters[name]) {\\n\\t\\t\\t\\t\\t\\tdelete this.parameters[name];\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetParameters(device, names) {\\n\\t\\t\\t\\tconst parameters = this.parameters;\\n\\t\\t\\t\\tif (names === undefined) names = parameters;\\n\\t\\t\\t\\tfor(const paramName in names){\\n\\t\\t\\t\\t\\t\\tconst parameter = parameters[paramName];\\n\\t\\t\\t\\t\\t\\tif (parameter) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!parameter.scopeId) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tparameter.scopeId = device.scope.resolve(paramName);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tparameter.scopeId.setValue(parameter.data);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetDefine(name, value) {\\n\\t\\t\\t\\tlet modified = false;\\n\\t\\t\\t\\tconst { defines } = this;\\n\\t\\t\\t\\tif (value !== undefined && value !== false) {\\n\\t\\t\\t\\t\\t\\tmodified = !defines.has(name) || defines.get(name) !== value;\\n\\t\\t\\t\\t\\t\\tdefines.set(name, value);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tmodified = defines.has(name);\\n\\t\\t\\t\\t\\t\\tdefines.delete(name);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._definesDirty || (this._definesDirty = modified);\\n\\t\\t}\\n\\t\\tgetDefine(name) {\\n\\t\\t\\t\\treturn this.defines.has(name);\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.variants.clear();\\n\\t\\t\\t\\tfor(let i = 0; i < this.meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\tconst meshInstance = this.meshInstances[i];\\n\\t\\t\\t\\t\\t\\tmeshInstance.clearShaders();\\n\\t\\t\\t\\t\\t\\tmeshInstance._material = null;\\n\\t\\t\\t\\t\\t\\tif (meshInstance.mesh) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst defaultMaterial = getDefaultMaterial(meshInstance.mesh.device);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this !== defaultMaterial) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmeshInstance.material = defaultMaterial;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.meshInstances.length = 0;\\n\\t\\t}\\n\\t\\taddMeshInstanceRef(meshInstance) {\\n\\t\\t\\t\\tthis.meshInstances.push(meshInstance);\\n\\t\\t}\\n\\t\\tremoveMeshInstanceRef(meshInstance) {\\n\\t\\t\\t\\tconst meshInstances = this.meshInstances;\\n\\t\\t\\t\\tconst i = meshInstances.indexOf(meshInstance);\\n\\t\\t\\t\\tif (i !== -1) {\\n\\t\\t\\t\\t\\t\\tmeshInstances.splice(i, 1);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.meshInstances = [];\\n\\t\\t\\t\\tthis.name = 'Untitled';\\n\\t\\t\\t\\tthis.userId = '';\\n\\t\\t\\t\\tthis.id = id$3++;\\n\\t\\t\\t\\tthis.variants = new Map();\\n\\t\\t\\t\\tthis.defines = new Map();\\n\\t\\t\\t\\tthis._definesDirty = false;\\n\\t\\t\\t\\tthis.parameters = {};\\n\\t\\t\\t\\tthis.alphaTest = 0;\\n\\t\\t\\t\\tthis.alphaToCoverage = false;\\n\\t\\t\\t\\tthis._blendState = new BlendState();\\n\\t\\t\\t\\tthis._depthState = new DepthState();\\n\\t\\t\\t\\tthis.cull = CULLFACE_BACK;\\n\\t\\t\\t\\tthis.stencilFront = null;\\n\\t\\t\\t\\tthis.stencilBack = null;\\n\\t\\t\\t\\tthis._shaderChunks = null;\\n\\t\\t\\t\\tthis._oldChunks = {};\\n\\t\\t\\t\\tthis._dirtyShader = true;\\n\\t\\t\\t\\tthis._shaderVersion = 0;\\n\\t\\t\\t\\tthis._scene = null;\\n\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t}\\n}\\n\\nclass ShadowMapCache {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.clear();\\n\\t\\t\\t\\tthis.cache = null;\\n\\t\\t}\\n\\t\\tclear() {\\n\\t\\t\\t\\tthis.cache.forEach((shadowMaps)=>{\\n\\t\\t\\t\\t\\t\\tshadowMaps.forEach((shadowMap)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tshadowMap.destroy();\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.cache.clear();\\n\\t\\t}\\n\\t\\tgetKey(light) {\\n\\t\\t\\t\\tconst isCubeMap = light._type === LIGHTTYPE_OMNI;\\n\\t\\t\\t\\tconst shadowType = light._shadowType;\\n\\t\\t\\t\\tconst resolution = light._shadowResolution;\\n\\t\\t\\t\\treturn `${isCubeMap}-${shadowType}-${resolution}`;\\n\\t\\t}\\n\\t\\tget(device, light) {\\n\\t\\t\\t\\tconst key = this.getKey(light);\\n\\t\\t\\t\\tconst shadowMaps = this.cache.get(key);\\n\\t\\t\\t\\tif (shadowMaps && shadowMaps.length) {\\n\\t\\t\\t\\t\\t\\treturn shadowMaps.pop();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst shadowMap = ShadowMap.create(device, light);\\n\\t\\t\\t\\tshadowMap.cached = true;\\n\\t\\t\\t\\treturn shadowMap;\\n\\t\\t}\\n\\t\\tadd(light, shadowMap) {\\n\\t\\t\\t\\tconst key = this.getKey(light);\\n\\t\\t\\t\\tconst shadowMaps = this.cache.get(key);\\n\\t\\t\\t\\tif (shadowMaps) {\\n\\t\\t\\t\\t\\t\\tshadowMaps.push(shadowMap);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.cache.set(key, [\\n\\t\\t\\t\\t\\t\\t\\t\\tshadowMap\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.cache = new Map();\\n\\t\\t}\\n}\\n\\nclass RenderPassShadowLocalNonClustered extends RenderPass {\\n\\t\\texecute() {\\n\\t\\t\\t\\tthis.shadowRenderer.renderFace(this.light, null, this.face, false);\\n\\t\\t}\\n\\t\\tafter() {\\n\\t\\t\\t\\tif (this.applyVsm) {\\n\\t\\t\\t\\t\\t\\tthis.shadowRenderer.renderVsm(this.light, this.shadowCamera);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(device, shadowRenderer, light, face, applyVsm){\\n\\t\\t\\t\\tsuper(device);\\n\\t\\t\\t\\tthis.requiresCubemaps = false;\\n\\t\\t\\t\\tthis.shadowRenderer = shadowRenderer;\\n\\t\\t\\t\\tthis.light = light;\\n\\t\\t\\t\\tthis.face = face;\\n\\t\\t\\t\\tthis.applyVsm = applyVsm;\\n\\t\\t\\t\\tthis.shadowCamera = shadowRenderer.prepareFace(light, null, face);\\n\\t\\t\\t\\tshadowRenderer.setupRenderPass(this, this.shadowCamera, true);\\n\\t\\t}\\n}\\n\\nclass ShadowRendererLocal {\\n\\t\\tcull(light, comp, casters = null) {\\n\\t\\t\\t\\tconst isClustered = this.renderer.scene.clusteredLightingEnabled;\\n\\t\\t\\t\\tlight.visibleThisFrame = true;\\n\\t\\t\\t\\tif (!isClustered) {\\n\\t\\t\\t\\t\\t\\tif (!light._shadowMap) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlight._shadowMap = ShadowMap.create(this.device, light);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst type = light._type;\\n\\t\\t\\t\\tconst faceCount = type === LIGHTTYPE_SPOT ? 1 : 6;\\n\\t\\t\\t\\tfor(let face = 0; face < faceCount; face++){\\n\\t\\t\\t\\t\\t\\tconst lightRenderData = light.getRenderData(null, face);\\n\\t\\t\\t\\t\\t\\tconst shadowCam = lightRenderData.shadowCamera;\\n\\t\\t\\t\\t\\t\\tshadowCam.nearClip = light.attenuationEnd / 1000;\\n\\t\\t\\t\\t\\t\\tshadowCam.farClip = light.attenuationEnd;\\n\\t\\t\\t\\t\\t\\tconst shadowCamNode = shadowCam._node;\\n\\t\\t\\t\\t\\t\\tconst lightNode = light._node;\\n\\t\\t\\t\\t\\t\\tshadowCamNode.setPosition(lightNode.getPosition());\\n\\t\\t\\t\\t\\t\\tif (type === LIGHTTYPE_SPOT) {\\n\\t\\t\\t\\t\\t\\t\\t\\tshadowCam.fov = light._outerConeAngle * 2;\\n\\t\\t\\t\\t\\t\\t\\t\\tshadowCamNode.setRotation(lightNode.getRotation());\\n\\t\\t\\t\\t\\t\\t\\t\\tshadowCamNode.rotateLocal(-90, 0, 0);\\n\\t\\t\\t\\t\\t\\t} else if (type === LIGHTTYPE_OMNI) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (isClustered) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst tileSize = this.shadowRenderer.lightTextureAtlas.shadowAtlasResolution * light.atlasViewport.z / 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst texelSize = 2 / tileSize;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst filterSize = texelSize * this.shadowRenderer.lightTextureAtlas.shadowEdgePixels;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshadowCam.fov = Math.atan(1 + filterSize) * math.RAD_TO_DEG * 2;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshadowCam.fov = 90;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.renderer.updateCameraFrustum(shadowCam);\\n\\t\\t\\t\\t\\t\\tthis.shadowRenderer.cullShadowCasters(comp, light, lightRenderData.visibleCasters, shadowCam, casters);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tprepareLights(shadowLights, lights) {\\n\\t\\t\\t\\tlet shadowCamera;\\n\\t\\t\\t\\tfor(let i = 0; i < lights.length; i++){\\n\\t\\t\\t\\t\\t\\tconst light = lights[i];\\n\\t\\t\\t\\t\\t\\tif (this.shadowRenderer.needsShadowRendering(light) && light.atlasViewportAllocated) {\\n\\t\\t\\t\\t\\t\\t\\t\\tshadowLights.push(light);\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let face = 0; face < light.numShadowFaces; face++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshadowCamera = this.shadowRenderer.prepareFace(light, null, face);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn shadowCamera;\\n\\t\\t}\\n\\t\\tbuildNonClusteredRenderPasses(frameGraph, localLights) {\\n\\t\\t\\t\\tfor(let i = 0; i < localLights.length; i++){\\n\\t\\t\\t\\t\\t\\tconst light = localLights[i];\\n\\t\\t\\t\\t\\t\\tif (this.shadowRenderer.needsShadowRendering(light)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst applyVsm = light._type === LIGHTTYPE_SPOT;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst faceCount = light.numShadowFaces;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let face = 0; face < faceCount; face++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst renderPass = new RenderPassShadowLocalNonClustered(this.device, this.shadowRenderer, light, face, applyVsm);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tframeGraph.addRenderPass(renderPass);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(renderer, shadowRenderer){\\n\\t\\t\\t\\tthis.shadowLights = [];\\n\\t\\t\\t\\tthis.renderer = renderer;\\n\\t\\t\\t\\tthis.shadowRenderer = shadowRenderer;\\n\\t\\t\\t\\tthis.device = renderer.device;\\n\\t\\t}\\n}\\n\\nclass RenderPassShadowDirectional extends RenderPass {\\n\\t\\texecute() {\\n\\t\\t\\t\\tconst { light, camera, shadowRenderer, allCascadesRendering } = this;\\n\\t\\t\\t\\tconst faceCount = light.numShadowFaces;\\n\\t\\t\\t\\tconst shadowUpdateOverrides = light.shadowUpdateOverrides;\\n\\t\\t\\t\\tfor(let face = 0; face < faceCount; face++){\\n\\t\\t\\t\\t\\t\\tif (shadowUpdateOverrides?.[face] !== SHADOWUPDATE_NONE) {\\n\\t\\t\\t\\t\\t\\t\\t\\tshadowRenderer.renderFace(light, camera, face, !allCascadesRendering);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (shadowUpdateOverrides?.[face] === SHADOWUPDATE_THISFRAME) {\\n\\t\\t\\t\\t\\t\\t\\t\\tshadowUpdateOverrides[face] = SHADOWUPDATE_NONE;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tafter() {\\n\\t\\t\\t\\tthis.shadowRenderer.renderVsm(this.light, this.camera);\\n\\t\\t}\\n\\t\\tconstructor(device, shadowRenderer, light, camera, allCascadesRendering){\\n\\t\\t\\t\\tsuper(device);\\n\\t\\t\\t\\tthis.shadowRenderer = shadowRenderer;\\n\\t\\t\\t\\tthis.light = light;\\n\\t\\t\\t\\tthis.camera = camera;\\n\\t\\t\\t\\tthis.allCascadesRendering = allCascadesRendering;\\n\\t\\t}\\n}\\n\\nconst visibleSceneAabb = new BoundingBox();\\nconst center = new Vec3();\\nconst shadowCamView$1 = new Mat4();\\nconst aabbPoints = [\\n\\t\\tnew Vec3(),\\n\\t\\tnew Vec3(),\\n\\t\\tnew Vec3(),\\n\\t\\tnew Vec3(),\\n\\t\\tnew Vec3(),\\n\\t\\tnew Vec3(),\\n\\t\\tnew Vec3(),\\n\\t\\tnew Vec3()\\n];\\nconst _depthRange = {\\n\\t\\tmin: 0,\\n\\t\\tmax: 0\\n};\\nfunction getDepthRange(cameraViewMatrix, aabbMin, aabbMax) {\\n\\t\\taabbPoints[0].x = aabbPoints[1].x = aabbPoints[2].x = aabbPoints[3].x = aabbMin.x;\\n\\t\\taabbPoints[1].y = aabbPoints[3].y = aabbPoints[7].y = aabbPoints[5].y = aabbMin.y;\\n\\t\\taabbPoints[2].z = aabbPoints[3].z = aabbPoints[6].z = aabbPoints[7].z = aabbMin.z;\\n\\t\\taabbPoints[4].x = aabbPoints[5].x = aabbPoints[6].x = aabbPoints[7].x = aabbMax.x;\\n\\t\\taabbPoints[0].y = aabbPoints[2].y = aabbPoints[4].y = aabbPoints[6].y = aabbMax.y;\\n\\t\\taabbPoints[0].z = aabbPoints[1].z = aabbPoints[4].z = aabbPoints[5].z = aabbMax.z;\\n\\t\\tlet minz = 9999999999;\\n\\t\\tlet maxz = -9999999999;\\n\\t\\tfor(let i = 0; i < 8; ++i){\\n\\t\\t\\t\\tcameraViewMatrix.transformPoint(aabbPoints[i], aabbPoints[i]);\\n\\t\\t\\t\\tconst z = aabbPoints[i].z;\\n\\t\\t\\t\\tif (z < minz) minz = z;\\n\\t\\t\\t\\tif (z > maxz) maxz = z;\\n\\t\\t}\\n\\t\\t_depthRange.min = minz;\\n\\t\\t_depthRange.max = maxz;\\n\\t\\treturn _depthRange;\\n}\\nclass ShadowRendererDirectional {\\n\\t\\tcull(light, comp, camera, casters = null) {\\n\\t\\t\\t\\tlight.visibleThisFrame = true;\\n\\t\\t\\t\\tif (!light._shadowMap) {\\n\\t\\t\\t\\t\\t\\tlight._shadowMap = ShadowMap.create(this.device, light);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst nearDist = camera._nearClip;\\n\\t\\t\\t\\tthis.generateSplitDistances(light, nearDist, Math.min(camera._farClip, light.shadowDistance));\\n\\t\\t\\t\\tconst shadowUpdateOverrides = light.shadowUpdateOverrides;\\n\\t\\t\\t\\tfor(let cascade = 0; cascade < light.numCascades; cascade++){\\n\\t\\t\\t\\t\\t\\tif (shadowUpdateOverrides?.[cascade] === SHADOWUPDATE_NONE) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst lightRenderData = light.getRenderData(camera, cascade);\\n\\t\\t\\t\\t\\t\\tconst shadowCam = lightRenderData.shadowCamera;\\n\\t\\t\\t\\t\\t\\tshadowCam.renderTarget = light._shadowMap.renderTargets[0];\\n\\t\\t\\t\\t\\t\\tlightRenderData.shadowViewport.copy(light.cascades[cascade]);\\n\\t\\t\\t\\t\\t\\tlightRenderData.shadowScissor.copy(light.cascades[cascade]);\\n\\t\\t\\t\\t\\t\\tconst shadowCamNode = shadowCam._node;\\n\\t\\t\\t\\t\\t\\tconst lightNode = light._node;\\n\\t\\t\\t\\t\\t\\tshadowCamNode.setPosition(lightNode.getPosition());\\n\\t\\t\\t\\t\\t\\tshadowCamNode.setRotation(lightNode.getRotation());\\n\\t\\t\\t\\t\\t\\tshadowCamNode.rotateLocal(-90, 0, 0);\\n\\t\\t\\t\\t\\t\\tconst frustumNearDist = cascade === 0 ? nearDist : light._shadowCascadeDistances[cascade - 1];\\n\\t\\t\\t\\t\\t\\tconst frustumFarDist = light._shadowCascadeDistances[cascade];\\n\\t\\t\\t\\t\\t\\tconst frustumPoints = camera.getFrustumCorners(frustumNearDist, frustumFarDist);\\n\\t\\t\\t\\t\\t\\tcenter.set(0, 0, 0);\\n\\t\\t\\t\\t\\t\\tconst cameraWorldMat = camera.node.getWorldTransform();\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < 8; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tcameraWorldMat.transformPoint(frustumPoints[i], frustumPoints[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\tcenter.add(frustumPoints[i]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcenter.mulScalar(1 / 8);\\n\\t\\t\\t\\t\\t\\tlet radius = 0;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < 8; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dist = frustumPoints[i].sub(center).length();\\n\\t\\t\\t\\t\\t\\t\\t\\tif (dist > radius) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tradius = dist;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst right = shadowCamNode.right;\\n\\t\\t\\t\\t\\t\\tconst up = shadowCamNode.up;\\n\\t\\t\\t\\t\\t\\tconst lightDir = shadowCamNode.forward;\\n\\t\\t\\t\\t\\t\\tconst sizeRatio = 0.25 * light._shadowResolution / radius;\\n\\t\\t\\t\\t\\t\\tconst x = Math.ceil(center.dot(up) * sizeRatio) / sizeRatio;\\n\\t\\t\\t\\t\\t\\tconst y = Math.ceil(center.dot(right) * sizeRatio) / sizeRatio;\\n\\t\\t\\t\\t\\t\\tconst scaledUp = up.mulScalar(x);\\n\\t\\t\\t\\t\\t\\tconst scaledRight = right.mulScalar(y);\\n\\t\\t\\t\\t\\t\\tconst dot = center.dot(lightDir);\\n\\t\\t\\t\\t\\t\\tconst scaledDir = lightDir.mulScalar(dot);\\n\\t\\t\\t\\t\\t\\tcenter.add2(scaledUp, scaledRight).add(scaledDir);\\n\\t\\t\\t\\t\\t\\tshadowCamNode.setPosition(center);\\n\\t\\t\\t\\t\\t\\tshadowCamNode.translateLocal(0, 0, 1000000);\\n\\t\\t\\t\\t\\t\\tshadowCam.nearClip = 0.01;\\n\\t\\t\\t\\t\\t\\tshadowCam.farClip = 2000000;\\n\\t\\t\\t\\t\\t\\tshadowCam.orthoHeight = radius;\\n\\t\\t\\t\\t\\t\\tthis.renderer.updateCameraFrustum(shadowCam);\\n\\t\\t\\t\\t\\t\\tthis.shadowRenderer.cullShadowCasters(comp, light, lightRenderData.visibleCasters, shadowCam, casters);\\n\\t\\t\\t\\t\\t\\tconst cascadeFlag = 1 << cascade;\\n\\t\\t\\t\\t\\t\\tconst visibleCasters = lightRenderData.visibleCasters;\\n\\t\\t\\t\\t\\t\\tconst origNumVisibleCasters = visibleCasters.length;\\n\\t\\t\\t\\t\\t\\tlet numVisibleCasters = 0;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < origNumVisibleCasters; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst meshInstance = visibleCasters[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (meshInstance.shadowCascadeMask & cascadeFlag) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvisibleCasters[numVisibleCasters++] = meshInstance;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (numVisibleCasters === 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvisibleSceneAabb.copy(meshInstance.aabb);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvisibleSceneAabb.add(meshInstance.aabb);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tif (origNumVisibleCasters !== numVisibleCasters) {\\n\\t\\t\\t\\t\\t\\t\\t\\tvisibleCasters.length = numVisibleCasters;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tshadowCamView$1.copy(shadowCamNode.getWorldTransform()).invert();\\n\\t\\t\\t\\t\\t\\tconst depthRange = getDepthRange(shadowCamView$1, visibleSceneAabb.getMin(), visibleSceneAabb.getMax());\\n\\t\\t\\t\\t\\t\\tshadowCamNode.translateLocal(0, 0, depthRange.max + 0.1);\\n\\t\\t\\t\\t\\t\\tshadowCam.farClip = depthRange.max - depthRange.min + 0.2;\\n\\t\\t\\t\\t\\t\\tlightRenderData.projectionCompensation = radius;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgenerateSplitDistances(light, nearDist, farDist) {\\n\\t\\t\\t\\tlight._shadowCascadeDistances.fill(farDist);\\n\\t\\t\\t\\tfor(let i = 1; i < light.numCascades; i++){\\n\\t\\t\\t\\t\\t\\tconst fraction = i / light.numCascades;\\n\\t\\t\\t\\t\\t\\tconst linearDist = nearDist + (farDist - nearDist) * fraction;\\n\\t\\t\\t\\t\\t\\tconst logDist = nearDist * (farDist / nearDist) ** fraction;\\n\\t\\t\\t\\t\\t\\tconst dist = math.lerp(linearDist, logDist, light.cascadeDistribution);\\n\\t\\t\\t\\t\\t\\tlight._shadowCascadeDistances[i - 1] = dist;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetLightRenderPass(light, camera) {\\n\\t\\t\\t\\tlet renderPass = null;\\n\\t\\t\\t\\tif (this.shadowRenderer.needsShadowRendering(light)) {\\n\\t\\t\\t\\t\\t\\tconst faceCount = light.numShadowFaces;\\n\\t\\t\\t\\t\\t\\tconst shadowUpdateOverrides = light.shadowUpdateOverrides;\\n\\t\\t\\t\\t\\t\\tlet allCascadesRendering = true;\\n\\t\\t\\t\\t\\t\\tlet shadowCamera;\\n\\t\\t\\t\\t\\t\\tfor(let face = 0; face < faceCount; face++){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (shadowUpdateOverrides?.[face] === SHADOWUPDATE_NONE) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tallCascadesRendering = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tshadowCamera = this.shadowRenderer.prepareFace(light, camera, face);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\trenderPass = new RenderPassShadowDirectional(this.device, this.shadowRenderer, light, camera, allCascadesRendering);\\n\\t\\t\\t\\t\\t\\tthis.shadowRenderer.setupRenderPass(renderPass, shadowCamera, allCascadesRendering);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn renderPass;\\n\\t\\t}\\n\\t\\tconstructor(renderer, shadowRenderer){\\n\\t\\t\\t\\tthis.renderer = renderer;\\n\\t\\t\\t\\tthis.shadowRenderer = shadowRenderer;\\n\\t\\t\\t\\tthis.device = renderer.device;\\n\\t\\t}\\n}\\n\\nconst tempSet = 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\\t\\treturn Math.exp(-(x * x) / (2.0 * sigma * sigma));\\n}\\nfunction gaussWeights(kernelSize) {\\n\\t\\tconst sigma = (kernelSize - 1) / (2 * 3);\\n\\t\\tconst halfWidth = (kernelSize - 1) * 0.5;\\n\\t\\tconst values = new Array(kernelSize);\\n\\t\\tlet sum = 0.0;\\n\\t\\tfor(let i = 0; i < kernelSize; ++i){\\n\\t\\t\\t\\tvalues[i] = gauss(i - halfWidth, sigma);\\n\\t\\t\\t\\tsum += values[i];\\n\\t\\t}\\n\\t\\tfor(let i = 0; i < kernelSize; ++i){\\n\\t\\t\\t\\tvalues[i] /= sum;\\n\\t\\t}\\n\\t\\treturn values;\\n}\\nclass ShadowRenderer {\\n\\t\\tstatic createShadowCamera(shadowType, type, face) {\\n\\t\\t\\t\\tconst shadowCam = LightCamera.create(SHADOWCAMERA_NAME, type, face);\\n\\t\\t\\t\\tconst shadowInfo = shadowTypeInfo.get(shadowType);\\n\\t\\t\\t\\tconst isVsm = shadowInfo?.vsm ?? false;\\n\\t\\t\\t\\tconst isPcf = shadowInfo?.pcf ?? false;\\n\\t\\t\\t\\tif (isVsm) {\\n\\t\\t\\t\\t\\t\\tshadowCam.clearColor = new Color(0, 0, 0, 0);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tshadowCam.clearColor = new Color(1, 1, 1, 1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tshadowCam.clearDepthBuffer = true;\\n\\t\\t\\t\\tshadowCam.clearStencilBuffer = false;\\n\\t\\t\\t\\tshadowCam.clearColorBuffer = !isPcf;\\n\\t\\t\\t\\treturn shadowCam;\\n\\t\\t}\\n\\t\\t_cullShadowCastersInternal(meshInstances, visible, camera) {\\n\\t\\t\\t\\tconst numInstances = meshInstances.length;\\n\\t\\t\\t\\tfor(let i = 0; i < numInstances; i++){\\n\\t\\t\\t\\t\\t\\tconst meshInstance = meshInstances[i];\\n\\t\\t\\t\\t\\t\\tif (meshInstance.castShadow) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!meshInstance.cull || meshInstance._isVisible(camera)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmeshInstance.visibleThisFrame = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvisible.push(meshInstance);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcullShadowCasters(comp, light, visible, camera, casters) {\\n\\t\\t\\t\\tthis.renderer.scene?.fire(EVENT_PRECULL, camera);\\n\\t\\t\\t\\tvisible.length = 0;\\n\\t\\t\\t\\tif (casters) {\\n\\t\\t\\t\\t\\t\\tthis._cullShadowCastersInternal(casters, visible, camera);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst layers = comp.layerList;\\n\\t\\t\\t\\t\\t\\tconst len = layers.length;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < len; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst layer = layers[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (layer._lightsSet.has(light)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!tempSet.has(layer)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttempSet.add(layer);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._cullShadowCastersInternal(layer.shadowCasters, visible, camera);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\ttempSet.clear();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tvisible.sort(this.sortCompareShader);\\n\\t\\t\\t\\tthis.renderer.scene?.fire(EVENT_POSTCULL, camera);\\n\\t\\t}\\n\\t\\tsortCompareShader(drawCallA, drawCallB) {\\n\\t\\t\\t\\tconst keyA = drawCallA._sortKeyShadow;\\n\\t\\t\\t\\tconst keyB = drawCallB._sortKeyShadow;\\n\\t\\t\\t\\tif (keyA === keyB) {\\n\\t\\t\\t\\t\\t\\treturn drawCallB.mesh.id - drawCallA.mesh.id;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn keyB - keyA;\\n\\t\\t}\\n\\t\\tsetupRenderState(device, light) {\\n\\t\\t\\t\\tconst isClustered = this.renderer.scene.clusteredLightingEnabled;\\n\\t\\t\\t\\tconst useShadowSampler = isClustered ? light._isPcf : light._isPcf && light._type !== LIGHTTYPE_OMNI;\\n\\t\\t\\t\\tdevice.setBlendState(useShadowSampler ? this.blendStateNoWrite : this.blendStateWrite);\\n\\t\\t\\t\\tdevice.setDepthState(light.shadowDepthState);\\n\\t\\t\\t\\tdevice.setStencilState(null, null);\\n\\t\\t}\\n\\t\\tdispatchUniforms(light, shadowCam, lightRenderData, face) {\\n\\t\\t\\t\\tconst shadowCamNode = shadowCam._node;\\n\\t\\t\\t\\tif (light._type !== LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\t\\tthis.renderer.dispatchViewPos(shadowCamNode.getPosition());\\n\\t\\t\\t\\t\\t\\tthis.shadowMapLightRadiusId.setValue(light.attenuationEnd);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tshadowCamView.setTRS(shadowCamNode.getPosition(), shadowCamNode.getRotation(), Vec3.ONE).invert();\\n\\t\\t\\t\\tshadowCamViewProj.mul2(shadowCam.projectionMatrix, shadowCamView);\\n\\t\\t\\t\\tconst rectViewport = lightRenderData.shadowViewport;\\n\\t\\t\\t\\tshadowCam.rect = rectViewport;\\n\\t\\t\\t\\tshadowCam.scissorRect = lightRenderData.shadowScissor;\\n\\t\\t\\t\\tviewportMatrix.setViewport(rectViewport.x, rectViewport.y, rectViewport.z, rectViewport.w);\\n\\t\\t\\t\\tlightRenderData.shadowMatrix.mul2(viewportMatrix, shadowCamViewProj);\\n\\t\\t\\t\\tif (light._type === LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\t\\tlight._shadowMatrixPalette.set(lightRenderData.shadowMatrix.data, face * 16);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetShadowPass(light) {\\n\\t\\t\\t\\tconst lightType = light._type;\\n\\t\\t\\t\\tconst shadowType = light._shadowType;\\n\\t\\t\\t\\tlet shadowPassInfo = this.shadowPassCache[lightType]?.[shadowType];\\n\\t\\t\\t\\tif (!shadowPassInfo) {\\n\\t\\t\\t\\t\\t\\tconst shadowPassName = `ShadowPass_${lightType}_${shadowType}`;\\n\\t\\t\\t\\t\\t\\tshadowPassInfo = ShaderPass.get(this.device).allocate(shadowPassName, {\\n\\t\\t\\t\\t\\t\\t\\t\\tisShadow: true,\\n\\t\\t\\t\\t\\t\\t\\t\\tlightType: lightType,\\n\\t\\t\\t\\t\\t\\t\\t\\tshadowType: shadowType\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tif (!this.shadowPassCache[lightType]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.shadowPassCache[lightType] = [];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.shadowPassCache[lightType][shadowType] = shadowPassInfo;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn shadowPassInfo.index;\\n\\t\\t}\\n\\t\\tsubmitCasters(visibleCasters, light, camera) {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tconst renderer = this.renderer;\\n\\t\\t\\t\\tconst scene = renderer.scene;\\n\\t\\t\\t\\tconst passFlags = 1 << SHADER_SHADOW;\\n\\t\\t\\t\\tconst shadowPass = this.getShadowPass(light);\\n\\t\\t\\t\\tconst cameraShaderParams = camera.shaderParams;\\n\\t\\t\\t\\tconst flipFactor = camera.renderTarget.flipY ? -1 : 1;\\n\\t\\t\\t\\tconst count = visibleCasters.length;\\n\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\tconst meshInstance = visibleCasters[i];\\n\\t\\t\\t\\t\\t\\tconst mesh = meshInstance.mesh;\\n\\t\\t\\t\\t\\t\\tconst instancingData = meshInstance.instancingData;\\n\\t\\t\\t\\t\\t\\tif (instancingData && instancingData.count <= 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tmeshInstance.ensureMaterial(device);\\n\\t\\t\\t\\t\\t\\tconst material = meshInstance.material;\\n\\t\\t\\t\\t\\t\\trenderer.setBaseConstants(device, material);\\n\\t\\t\\t\\t\\t\\trenderer.setSkinning(device, meshInstance);\\n\\t\\t\\t\\t\\t\\tif (material.dirty) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmaterial.updateUniforms(device, scene);\\n\\t\\t\\t\\t\\t\\t\\t\\tmaterial.dirty = false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\trenderer.setupCullMode(true, flipFactor, meshInstance);\\n\\t\\t\\t\\t\\t\\tmaterial.setParameters(device);\\n\\t\\t\\t\\t\\t\\tmeshInstance.setParameters(device, passFlags);\\n\\t\\t\\t\\t\\t\\tconst shaderInstance = meshInstance.getShaderInstance(shadowPass, 0, scene, cameraShaderParams, this.viewUniformFormat, this.viewBindGroupFormat);\\n\\t\\t\\t\\t\\t\\tconst shadowShader = shaderInstance.shader;\\n\\t\\t\\t\\t\\t\\tif (shadowShader.failed) continue;\\n\\t\\t\\t\\t\\t\\tmeshInstance._sortKeyShadow = shadowShader.id;\\n\\t\\t\\t\\t\\t\\tdevice.setShader(shadowShader);\\n\\t\\t\\t\\t\\t\\trenderer.setVertexBuffers(device, mesh);\\n\\t\\t\\t\\t\\t\\trenderer.setMorphing(device, meshInstance.morphInstance);\\n\\t\\t\\t\\t\\t\\tif (instancingData) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.setVertexBuffer(instancingData.vertexBuffer);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\trenderer.setMeshInstanceMatrices(meshInstance);\\n\\t\\t\\t\\t\\t\\trenderer.setupMeshUniformBuffers(shaderInstance);\\n\\t\\t\\t\\t\\t\\tconst style = meshInstance.renderStyle;\\n\\t\\t\\t\\t\\t\\tconst indirectData = meshInstance.getDrawCommands(camera);\\n\\t\\t\\t\\t\\t\\tdevice.draw(mesh.primitive[style], mesh.indexBuffer[style], instancingData?.count, indirectData);\\n\\t\\t\\t\\t\\t\\trenderer._shadowDrawCalls++;\\n\\t\\t\\t\\t\\t\\tif (instancingData) {\\n\\t\\t\\t\\t\\t\\t\\t\\trenderer._instancedDrawCalls++;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tneedsShadowRendering(light) {\\n\\t\\t\\t\\tconst needs = light.enabled && light.castShadows && light.shadowUpdateMode !== SHADOWUPDATE_NONE && light.visibleThisFrame;\\n\\t\\t\\t\\tif (light.shadowUpdateMode === SHADOWUPDATE_THISFRAME) {\\n\\t\\t\\t\\t\\t\\tlight.shadowUpdateMode = SHADOWUPDATE_NONE;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (needs) {\\n\\t\\t\\t\\t\\t\\tthis.renderer._shadowMapUpdates += light.numShadowFaces;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn needs;\\n\\t\\t}\\n\\t\\tgetLightRenderData(light, camera, face) {\\n\\t\\t\\t\\treturn light.getRenderData(light._type === LIGHTTYPE_DIRECTIONAL ? camera : null, face);\\n\\t\\t}\\n\\t\\tsetupRenderPass(renderPass, shadowCamera, clearRenderTarget) {\\n\\t\\t\\t\\tconst rt = shadowCamera.renderTarget;\\n\\t\\t\\t\\trenderPass.init(rt);\\n\\t\\t\\t\\trenderPass.depthStencilOps.clearDepthValue = 1;\\n\\t\\t\\t\\trenderPass.depthStencilOps.clearDepth = clearRenderTarget;\\n\\t\\t\\t\\tif (rt.depthBuffer) {\\n\\t\\t\\t\\t\\t\\trenderPass.depthStencilOps.storeDepth = true;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\trenderPass.colorOps.clearValue.copy(shadowCamera.clearColor);\\n\\t\\t\\t\\t\\t\\trenderPass.colorOps.clear = clearRenderTarget;\\n\\t\\t\\t\\t\\t\\trenderPass.depthStencilOps.storeDepth = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\trenderPass.requiresCubemaps = false;\\n\\t\\t}\\n\\t\\tprepareFace(light, camera, face) {\\n\\t\\t\\t\\tconst type = light._type;\\n\\t\\t\\t\\tconst lightRenderData = this.getLightRenderData(light, camera, face);\\n\\t\\t\\t\\tconst shadowCam = lightRenderData.shadowCamera;\\n\\t\\t\\t\\tconst renderTargetIndex = type === LIGHTTYPE_DIRECTIONAL ? 0 : face;\\n\\t\\t\\t\\tshadowCam.renderTarget = light._shadowMap.renderTargets[renderTargetIndex];\\n\\t\\t\\t\\treturn shadowCam;\\n\\t\\t}\\n\\t\\trenderFace(light, camera, face, clear) {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tconst lightRenderData = this.getLightRenderData(light, camera, face);\\n\\t\\t\\t\\tconst shadowCam = lightRenderData.shadowCamera;\\n\\t\\t\\t\\tthis.dispatchUniforms(light, shadowCam, lightRenderData, face);\\n\\t\\t\\t\\tconst rt = shadowCam.renderTarget;\\n\\t\\t\\t\\tconst renderer = this.renderer;\\n\\t\\t\\t\\trenderer.setCameraUniforms(shadowCam, rt);\\n\\t\\t\\t\\tif (device.supportsUniformBuffers) {\\n\\t\\t\\t\\t\\t\\trenderer.setupViewUniformBuffers(lightRenderData.viewBindGroups, this.viewUniformFormat, this.viewBindGroupFormat, null);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\trenderer.setupViewport(shadowCam, rt);\\n\\t\\t\\t\\tif (clear) {\\n\\t\\t\\t\\t\\t\\trenderer.clear(shadowCam);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.setupRenderState(device, light);\\n\\t\\t\\t\\tthis.submitCasters(lightRenderData.visibleCasters, light, shadowCam);\\n\\t\\t}\\n\\t\\trenderVsm(light, camera) {\\n\\t\\t\\t\\tif (light._isVsm && light._vsmBlurSize > 1) {\\n\\t\\t\\t\\t\\t\\tconst isClustered = this.renderer.scene.clusteredLightingEnabled;\\n\\t\\t\\t\\t\\t\\tif (!isClustered || light._type === LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.applyVsmBlur(light, camera);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetVsmBlurShader(blurMode, filterSize) {\\n\\t\\t\\t\\tconst cache = this.blurVsmShader;\\n\\t\\t\\t\\tlet blurShader = cache[blurMode][filterSize];\\n\\t\\t\\t\\tif (!blurShader) {\\n\\t\\t\\t\\t\\t\\tthis.blurVsmWeights[filterSize] = gaussWeights(filterSize);\\n\\t\\t\\t\\t\\t\\tconst defines = new Map();\\n\\t\\t\\t\\t\\t\\tdefines.set('{SAMPLES}', filterSize);\\n\\t\\t\\t\\t\\t\\tif (blurMode === 1) defines.set('GAUSS', '');\\n\\t\\t\\t\\t\\t\\tblurShader = ShaderUtils.createShader(this.device, {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniqueName: `blurVsm${blurMode}${filterSize}`,\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t\\t\\tvertexChunk: 'fullscreenQuadVS',\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentChunk: 'blurVSMPS',\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentDefines: defines\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tcache[blurMode][filterSize] = blurShader;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn blurShader;\\n\\t\\t}\\n\\t\\tapplyVsmBlur(light, camera) {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tdevice.setBlendState(BlendState.NOBLEND);\\n\\t\\t\\t\\tconst lightRenderData = light.getRenderData(light._type === LIGHTTYPE_DIRECTIONAL ? camera : null, 0);\\n\\t\\t\\t\\tconst shadowCam = lightRenderData.shadowCamera;\\n\\t\\t\\t\\tconst origShadowMap = shadowCam.renderTarget;\\n\\t\\t\\t\\tconst tempShadowMap = this.renderer.shadowMapCache.get(device, light);\\n\\t\\t\\t\\tconst tempRt = tempShadowMap.renderTargets[0];\\n\\t\\t\\t\\tconst blurMode = light.vsmBlurMode;\\n\\t\\t\\t\\tconst filterSize = light._vsmBlurSize;\\n\\t\\t\\t\\tconst blurShader = this.getVsmBlurShader(blurMode, filterSize);\\n\\t\\t\\t\\tblurScissorRect.z = light._shadowResolution - 2;\\n\\t\\t\\t\\tblurScissorRect.w = blurScissorRect.z;\\n\\t\\t\\t\\tthis.sourceId.setValue(origShadowMap.colorBuffer);\\n\\t\\t\\t\\tpixelOffset[0] = 1 / light._shadowResolution;\\n\\t\\t\\t\\tpixelOffset[1] = 0;\\n\\t\\t\\t\\tthis.pixelOffsetId.setValue(pixelOffset);\\n\\t\\t\\t\\tif (blurMode === BLUR_GAUSSIAN) this.weightId.setValue(this.blurVsmWeights[filterSize]);\\n\\t\\t\\t\\tdrawQuadWithShader(device, tempRt, blurShader, null, blurScissorRect);\\n\\t\\t\\t\\tthis.sourceId.setValue(tempRt.colorBuffer);\\n\\t\\t\\t\\tpixelOffset[1] = pixelOffset[0];\\n\\t\\t\\t\\tpixelOffset[0] = 0;\\n\\t\\t\\t\\tthis.pixelOffsetId.setValue(pixelOffset);\\n\\t\\t\\t\\tdrawQuadWithShader(device, origShadowMap, blurShader, null, blurScissorRect);\\n\\t\\t\\t\\tthis.renderer.shadowMapCache.add(light, tempShadowMap);\\n\\t\\t}\\n\\t\\tinitViewBindGroupFormat() {\\n\\t\\t\\t\\tif (this.device.supportsUniformBuffers && !this.viewUniformFormat) {\\n\\t\\t\\t\\t\\t\\tthis.viewUniformFormat = new UniformBufferFormat(this.device, [\\n\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('matrix_viewProjection', UNIFORMTYPE_MAT4)\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\tthis.viewBindGroupFormat = new BindGroupFormat(this.device, [\\n\\t\\t\\t\\t\\t\\t\\t\\tnew BindUniformBufferFormat(UNIFORM_BUFFER_DEFAULT_SLOT_NAME, SHADERSTAGE_VERTEX | SHADERSTAGE_FRAGMENT)\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tframeUpdate() {\\n\\t\\t\\t\\tthis.initViewBindGroupFormat();\\n\\t\\t}\\n\\t\\tconstructor(renderer, lightTextureAtlas){\\n\\t\\t\\t\\tthis.shadowPassCache = [];\\n\\t\\t\\t\\tthis.device = renderer.device;\\n\\t\\t\\t\\tthis.renderer = renderer;\\n\\t\\t\\t\\tthis.lightTextureAtlas = lightTextureAtlas;\\n\\t\\t\\t\\tconst scope = this.device.scope;\\n\\t\\t\\t\\tthis.sourceId = scope.resolve('source');\\n\\t\\t\\t\\tthis.pixelOffsetId = scope.resolve('pixelOffset');\\n\\t\\t\\t\\tthis.weightId = scope.resolve('weight[0]');\\n\\t\\t\\t\\tthis.blurVsmShader = [\\n\\t\\t\\t\\t\\t\\t{},\\n\\t\\t\\t\\t\\t\\t{}\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.blurVsmWeights = {};\\n\\t\\t\\t\\tthis.shadowMapLightRadiusId = scope.resolve('light_radius');\\n\\t\\t\\t\\tthis.viewUniformFormat = null;\\n\\t\\t\\t\\tthis.viewBindGroupFormat = null;\\n\\t\\t\\t\\tthis.blendStateWrite = new BlendState();\\n\\t\\t\\t\\tthis.blendStateNoWrite = new BlendState();\\n\\t\\t\\t\\tthis.blendStateNoWrite.setColorWrite(false, false, false, false);\\n\\t\\t}\\n}\\n\\nconst tempClusterArray = [];\\nclass WorldClustersAllocator {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tif (this._empty) {\\n\\t\\t\\t\\t\\t\\tthis._empty.destroy();\\n\\t\\t\\t\\t\\t\\tthis._empty = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._allocated.forEach((cluster)=>{\\n\\t\\t\\t\\t\\t\\tcluster.destroy();\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis._allocated.length = 0;\\n\\t\\t}\\n\\t\\tget count() {\\n\\t\\t\\t\\treturn this._allocated.length;\\n\\t\\t}\\n\\t\\tget empty() {\\n\\t\\t\\t\\tif (!this._empty) {\\n\\t\\t\\t\\t\\t\\tconst empty = new WorldClusters(this.device);\\n\\t\\t\\t\\t\\t\\tempty.name = 'ClusterEmpty';\\n\\t\\t\\t\\t\\t\\tempty.update([]);\\n\\t\\t\\t\\t\\t\\tthis._empty = empty;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._empty;\\n\\t\\t}\\n\\t\\tassign(renderPasses) {\\n\\t\\t\\t\\ttempClusterArray.push(...this._allocated);\\n\\t\\t\\t\\tthis._allocated.length = 0;\\n\\t\\t\\t\\tthis._clusters.clear();\\n\\t\\t\\t\\tconst passCount = renderPasses.length;\\n\\t\\t\\t\\tfor(let p = 0; p < passCount; p++){\\n\\t\\t\\t\\t\\t\\tconst renderPass = renderPasses[p];\\n\\t\\t\\t\\t\\t\\tconst renderActions = renderPass.renderActions;\\n\\t\\t\\t\\t\\t\\tif (renderActions) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst count = renderActions.length;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst ra = renderActions[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tra.lightClusters = null;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst layer = ra.layer;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (layer.hasClusteredLights && layer.meshInstances.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst hash = layer.getLightIdHash();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst existingRenderAction = this._clusters.get(hash);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet clusters = existingRenderAction?.lightClusters;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!clusters) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tclusters = tempClusterArray.pop() ?? new WorldClusters(this.device);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._allocated.push(clusters);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._clusters.set(hash, ra);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tra.lightClusters = clusters;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!ra.lightClusters) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tra.lightClusters = this.empty;\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttempClusterArray.forEach((item)=>item.destroy());\\n\\t\\t\\t\\ttempClusterArray.length = 0;\\n\\t\\t}\\n\\t\\tupdate(renderPasses, lighting) {\\n\\t\\t\\t\\tthis.assign(renderPasses);\\n\\t\\t\\t\\tthis._clusters.forEach((renderAction)=>{\\n\\t\\t\\t\\t\\t\\tconst layer = renderAction.layer;\\n\\t\\t\\t\\t\\t\\tconst cluster = renderAction.lightClusters;\\n\\t\\t\\t\\t\\t\\tcluster.update(layer.clusteredLightsSet, lighting);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice){\\n\\t\\t\\t\\tthis._empty = null;\\n\\t\\t\\t\\tthis._allocated = [];\\n\\t\\t\\t\\tthis._clusters = new Map();\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t}\\n}\\n\\nconst _viewport = new Vec4();\\nconst _invViewProjMatrices = [];\\nclass RenderPassCookieRenderer extends RenderPass {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._quadRenderer2D?.destroy();\\n\\t\\t\\t\\tthis._quadRenderer2D = null;\\n\\t\\t\\t\\tthis._quadRendererCube?.destroy();\\n\\t\\t\\t\\tthis._quadRendererCube = null;\\n\\t\\t\\t\\tthis._evtDeviceRestored?.off();\\n\\t\\t\\t\\tthis._evtDeviceRestored = null;\\n\\t\\t}\\n\\t\\tstatic create(renderTarget, cubeSlotsOffsets) {\\n\\t\\t\\t\\tconst renderPass = new RenderPassCookieRenderer(renderTarget.device, cubeSlotsOffsets);\\n\\t\\t\\t\\trenderPass.init(renderTarget);\\n\\t\\t\\t\\trenderPass.colorOps.clear = false;\\n\\t\\t\\t\\trenderPass.depthStencilOps.clearDepth = false;\\n\\t\\t\\t\\treturn renderPass;\\n\\t\\t}\\n\\t\\tonDeviceRestored() {\\n\\t\\t\\t\\tthis._forceCopy = true;\\n\\t\\t}\\n\\t\\tupdate(lights) {\\n\\t\\t\\t\\tconst filteredLights = this._filteredLights;\\n\\t\\t\\t\\tthis.filter(lights, filteredLights);\\n\\t\\t\\t\\tthis.executeEnabled = filteredLights.length > 0;\\n\\t\\t}\\n\\t\\tfilter(lights, filteredLights) {\\n\\t\\t\\t\\tfor(let i = 0; i < lights.length; i++){\\n\\t\\t\\t\\t\\t\\tconst light = lights[i];\\n\\t\\t\\t\\t\\t\\tif (light._type === LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!light.atlasViewportAllocated) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!light.atlasSlotUpdated && !this._forceCopy) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (light.enabled && light.cookie && light.visibleThisFrame) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfilteredLights.push(light);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._forceCopy = false;\\n\\t\\t}\\n\\t\\tinitInvViewProjMatrices() {\\n\\t\\t\\t\\tif (!_invViewProjMatrices.length) {\\n\\t\\t\\t\\t\\t\\tfor(let face = 0; face < 6; face++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst camera = LightCamera.create(null, LIGHTTYPE_OMNI, face);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst projMat = camera.projectionMatrix;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst viewMat = camera.node.getLocalTransform().clone().invert();\\n\\t\\t\\t\\t\\t\\t\\t\\t_invViewProjMatrices[face] = new Mat4().mul2(projMat, viewMat).invert();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget quadRenderer2D() {\\n\\t\\t\\t\\tif (!this._quadRenderer2D) {\\n\\t\\t\\t\\t\\t\\tconst shader = ShaderUtils.createShader(this.device, {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniqueName: 'cookieRenderer2d',\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t\\t\\tvertexChunk: 'cookieBlitVS',\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentChunk: 'cookieBlit2DPS'\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tthis._quadRenderer2D = new QuadRender(shader);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._quadRenderer2D;\\n\\t\\t}\\n\\t\\tget quadRendererCube() {\\n\\t\\t\\t\\tif (!this._quadRendererCube) {\\n\\t\\t\\t\\t\\t\\tconst shader = ShaderUtils.createShader(this.device, {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniqueName: 'cookieRendererCube',\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t\\t\\tvertexChunk: 'cookieBlitVS',\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentChunk: 'cookieBlitCubePS'\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tthis._quadRendererCube = new QuadRender(shader);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._quadRendererCube;\\n\\t\\t}\\n\\t\\texecute() {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tdevice.setBlendState(BlendState.NOBLEND);\\n\\t\\t\\t\\tdevice.setCullMode(CULLFACE_NONE);\\n\\t\\t\\t\\tdevice.setDepthState(DepthState.NODEPTH);\\n\\t\\t\\t\\tdevice.setStencilState();\\n\\t\\t\\t\\tconst renderTargetWidth = this.renderTarget.colorBuffer.width;\\n\\t\\t\\t\\tconst cubeSlotsOffsets = this._cubeSlotsOffsets;\\n\\t\\t\\t\\tconst filteredLights = this._filteredLights;\\n\\t\\t\\t\\tfor(let i = 0; i < filteredLights.length; i++){\\n\\t\\t\\t\\t\\t\\tconst light = filteredLights[i];\\n\\t\\t\\t\\t\\t\\tconst faceCount = light.numShadowFaces;\\n\\t\\t\\t\\t\\t\\tconst quad = faceCount > 1 ? this.quadRendererCube : this.quadRenderer2D;\\n\\t\\t\\t\\t\\t\\tif (faceCount > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.initInvViewProjMatrices();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.blitTextureId.setValue(light.cookie);\\n\\t\\t\\t\\t\\t\\tfor(let face = 0; face < faceCount; face++){\\n\\t\\t\\t\\t\\t\\t\\t\\t_viewport.copy(light.atlasViewport);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (faceCount > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst smallSize = _viewport.z / 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst offset = cubeSlotsOffsets[face];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_viewport.x += smallSize * offset.x;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_viewport.y += smallSize * offset.y;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_viewport.z = smallSize;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_viewport.w = smallSize;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.invViewProjId.setValue(_invViewProjMatrices[face].data);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t_viewport.mulScalar(renderTargetWidth);\\n\\t\\t\\t\\t\\t\\t\\t\\tquad.render(_viewport);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfilteredLights.length = 0;\\n\\t\\t}\\n\\t\\tconstructor(device, cubeSlotsOffsets){\\n\\t\\t\\t\\tsuper(device), this._quadRenderer2D = null, this._quadRendererCube = null, this._filteredLights = [], this._forceCopy = false, this._evtDeviceRestored = null;\\n\\t\\t\\t\\tthis._cubeSlotsOffsets = cubeSlotsOffsets;\\n\\t\\t\\t\\tthis.requiresCubemaps = false;\\n\\t\\t\\t\\tthis.blitTextureId = device.scope.resolve('blitTexture');\\n\\t\\t\\t\\tthis.invViewProjId = device.scope.resolve('invViewProj');\\n\\t\\t\\t\\tthis._evtDeviceRestored = device.on('devicerestored', this.onDeviceRestored, this);\\n\\t\\t}\\n}\\n\\nclass RenderPassShadowLocalClustered extends RenderPass {\\n\\t\\tupdate(localLights) {\\n\\t\\t\\t\\tconst shadowLights = this.shadowRendererLocal.shadowLights;\\n\\t\\t\\t\\tconst shadowCamera = this.shadowRendererLocal.prepareLights(shadowLights, localLights);\\n\\t\\t\\t\\tconst count = shadowLights.length;\\n\\t\\t\\t\\tthis.enabled = count > 0;\\n\\t\\t\\t\\tif (count) {\\n\\t\\t\\t\\t\\t\\tthis.shadowRenderer.setupRenderPass(this, shadowCamera, false);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\texecute() {\\n\\t\\t\\t\\tconst shadowLights = this.shadowRendererLocal.shadowLights;\\n\\t\\t\\t\\tconst count = shadowLights.length;\\n\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\tconst light = shadowLights[i];\\n\\t\\t\\t\\t\\t\\tfor(let face = 0; face < light.numShadowFaces; face++){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.shadowRenderer.renderFace(light, null, face, true);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tshadowLights.length = 0;\\n\\t\\t}\\n\\t\\tconstructor(device, shadowRenderer, shadowRendererLocal){\\n\\t\\t\\t\\tsuper(device);\\n\\t\\t\\t\\tthis.requiresCubemaps = false;\\n\\t\\t\\t\\tthis.shadowRenderer = shadowRenderer;\\n\\t\\t\\t\\tthis.shadowRendererLocal = shadowRendererLocal;\\n\\t\\t}\\n}\\n\\nclass RenderPassUpdateClustered extends RenderPass {\\n\\t\\tupdate(frameGraph, shadowsEnabled, cookiesEnabled, lights, localLights) {\\n\\t\\t\\t\\tthis.frameGraph = frameGraph;\\n\\t\\t\\t\\tthis.cookiesRenderPass.enabled = cookiesEnabled;\\n\\t\\t\\t\\tif (cookiesEnabled) {\\n\\t\\t\\t\\t\\t\\tthis.cookiesRenderPass.update(lights);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.shadowRenderPass.enabled = shadowsEnabled;\\n\\t\\t\\t\\tif (shadowsEnabled) {\\n\\t\\t\\t\\t\\t\\tthis.shadowRenderPass.update(localLights);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.cookiesRenderPass.destroy();\\n\\t\\t\\t\\tthis.cookiesRenderPass = null;\\n\\t\\t}\\n\\t\\texecute() {\\n\\t\\t\\t\\tconst { renderer } = this;\\n\\t\\t\\t\\tconst { scene } = renderer;\\n\\t\\t\\t\\trenderer.worldClustersAllocator.update(this.frameGraph.renderPasses, scene.lighting);\\n\\t\\t}\\n\\t\\tconstructor(device, renderer, shadowRenderer, shadowRendererLocal, lightTextureAtlas){\\n\\t\\t\\t\\tsuper(device);\\n\\t\\t\\t\\tthis.renderer = renderer;\\n\\t\\t\\t\\tthis.frameGraph = null;\\n\\t\\t\\t\\tthis.cookiesRenderPass = RenderPassCookieRenderer.create(lightTextureAtlas.cookieRenderTarget, lightTextureAtlas.cubeSlotsOffsets);\\n\\t\\t\\t\\tthis.beforePasses.push(this.cookiesRenderPass);\\n\\t\\t\\t\\tthis.shadowRenderPass = new RenderPassShadowLocalClustered(device, shadowRenderer, shadowRendererLocal);\\n\\t\\t\\t\\tthis.beforePasses.push(this.shadowRenderPass);\\n\\t\\t}\\n}\\n\\nlet _skinUpdateIndex = 0;\\nconst viewProjMat = new Mat4();\\nconst viewInvMat = new Mat4();\\nconst viewMat = new Mat4();\\nconst viewMat3 = new Mat3();\\nconst tempSphere = new BoundingSphere();\\nconst tempFrustum = new Frustum();\\nconst _flipYMat = new Mat4().setScale(1, -1, 1);\\nconst _tempLightSet = new Set();\\nconst _tempLayerSet = new Set();\\nconst _dynamicBindGroup = new DynamicBindGroup();\\nconst _fixProjRangeMat = 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]);\\nconst _haltonSequence = [\\n\\t\\tnew Vec2(0.5, 0.333333),\\n\\t\\tnew Vec2(0.25, 0.666667),\\n\\t\\tnew Vec2(0.75, 0.111111),\\n\\t\\tnew Vec2(0.125, 0.444444),\\n\\t\\tnew Vec2(0.625, 0.777778),\\n\\t\\tnew Vec2(0.375, 0.222222),\\n\\t\\tnew Vec2(0.875, 0.555556),\\n\\t\\tnew Vec2(0.0625, 0.888889),\\n\\t\\tnew Vec2(0.5625, 0.037037),\\n\\t\\tnew Vec2(0.3125, 0.370370),\\n\\t\\tnew Vec2(0.8125, 0.703704),\\n\\t\\tnew Vec2(0.1875, 0.148148),\\n\\t\\tnew Vec2(0.6875, 0.481481),\\n\\t\\tnew Vec2(0.4375, 0.814815),\\n\\t\\tnew Vec2(0.9375, 0.259259),\\n\\t\\tnew Vec2(0.03125, 0.592593)\\n];\\nconst _tempProjMat0 = new Mat4();\\nconst _tempProjMat1 = new Mat4();\\nconst _tempProjMat2 = new Mat4();\\nconst _tempProjMat3 = new Mat4();\\nconst _tempProjMat4 = new Mat4();\\nconst _tempProjMat5 = new Mat4();\\nconst _tempSet = new Set();\\nconst _tempMeshInstances = [];\\nconst _tempMeshInstancesSkinned = [];\\nclass Renderer {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.shadowRenderer = null;\\n\\t\\t\\t\\tthis._shadowRendererLocal = null;\\n\\t\\t\\t\\tthis._shadowRendererDirectional = null;\\n\\t\\t\\t\\tthis.shadowMapCache.destroy();\\n\\t\\t\\t\\tthis.shadowMapCache = null;\\n\\t\\t\\t\\tthis._renderPassUpdateClustered?.destroy();\\n\\t\\t\\t\\tthis._renderPassUpdateClustered = null;\\n\\t\\t\\t\\tthis.lightTextureAtlas.destroy();\\n\\t\\t\\t\\tthis.lightTextureAtlas = null;\\n\\t\\t\\t\\tthis.gsplatDirector?.destroy();\\n\\t\\t\\t\\tthis.gsplatDirector = null;\\n\\t\\t}\\n\\t\\tsetupViewport(camera, renderTarget) {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tconst pixelWidth = renderTarget ? renderTarget.width : device.width;\\n\\t\\t\\t\\tconst pixelHeight = renderTarget ? renderTarget.height : device.height;\\n\\t\\t\\t\\tconst rect = camera.rect;\\n\\t\\t\\t\\tlet x = Math.floor(rect.x * pixelWidth);\\n\\t\\t\\t\\tlet y = Math.floor(rect.y * pixelHeight);\\n\\t\\t\\t\\tlet w = Math.floor(rect.z * pixelWidth);\\n\\t\\t\\t\\tlet h = Math.floor(rect.w * pixelHeight);\\n\\t\\t\\t\\tdevice.setViewport(x, y, w, h);\\n\\t\\t\\t\\tif (camera._scissorRectClear) {\\n\\t\\t\\t\\t\\t\\tconst scissorRect = camera.scissorRect;\\n\\t\\t\\t\\t\\t\\tx = Math.floor(scissorRect.x * pixelWidth);\\n\\t\\t\\t\\t\\t\\ty = Math.floor(scissorRect.y * pixelHeight);\\n\\t\\t\\t\\t\\t\\tw = Math.floor(scissorRect.z * pixelWidth);\\n\\t\\t\\t\\t\\t\\th = Math.floor(scissorRect.w * pixelHeight);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdevice.setScissor(x, y, w, h);\\n\\t\\t}\\n\\t\\tsetCameraUniforms(camera, target) {\\n\\t\\t\\t\\tconst flipY = target?.flipY;\\n\\t\\t\\t\\tlet viewList = null;\\n\\t\\t\\t\\tif (camera.xr && camera.xr.session) {\\n\\t\\t\\t\\t\\t\\tconst transform = camera._node?.parent?.getWorldTransform() || null;\\n\\t\\t\\t\\t\\t\\tconst views = camera.xr.views;\\n\\t\\t\\t\\t\\t\\tviewList = views.list;\\n\\t\\t\\t\\t\\t\\tfor(let v = 0; v < viewList.length; v++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst view = viewList[v];\\n\\t\\t\\t\\t\\t\\t\\t\\tview.updateTransforms(transform);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tlet projMat = camera.projectionMatrix;\\n\\t\\t\\t\\t\\t\\tif (camera.calculateProjection) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcamera.calculateProjection(projMat, VIEW_CENTER);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlet projMatSkybox = camera.getProjectionMatrixSkybox();\\n\\t\\t\\t\\t\\t\\tif (flipY) {\\n\\t\\t\\t\\t\\t\\t\\t\\tprojMat = _tempProjMat0.mul2(_flipYMat, projMat);\\n\\t\\t\\t\\t\\t\\t\\t\\tprojMatSkybox = _tempProjMat1.mul2(_flipYMat, projMatSkybox);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.device.isWebGPU) {\\n\\t\\t\\t\\t\\t\\t\\t\\tprojMat = _tempProjMat2.mul2(_fixProjRangeMat, projMat);\\n\\t\\t\\t\\t\\t\\t\\t\\tprojMatSkybox = _tempProjMat3.mul2(_fixProjRangeMat, projMatSkybox);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst { jitter } = camera;\\n\\t\\t\\t\\t\\t\\tlet jitterX = 0;\\n\\t\\t\\t\\t\\t\\tlet jitterY = 0;\\n\\t\\t\\t\\t\\t\\tif (jitter > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst targetWidth = target ? target.width : this.device.width;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst targetHeight = target ? target.height : this.device.height;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst offset = _haltonSequence[this.device.renderVersion % _haltonSequence.length];\\n\\t\\t\\t\\t\\t\\t\\t\\tjitterX = jitter * (offset.x * 2 - 1) / targetWidth;\\n\\t\\t\\t\\t\\t\\t\\t\\tjitterY = jitter * (offset.y * 2 - 1) / targetHeight;\\n\\t\\t\\t\\t\\t\\t\\t\\tprojMat = _tempProjMat4.copy(projMat);\\n\\t\\t\\t\\t\\t\\t\\t\\tprojMat.data[8] = jitterX;\\n\\t\\t\\t\\t\\t\\t\\t\\tprojMat.data[9] = jitterY;\\n\\t\\t\\t\\t\\t\\t\\t\\tprojMatSkybox = _tempProjMat5.copy(projMatSkybox);\\n\\t\\t\\t\\t\\t\\t\\t\\tprojMatSkybox.data[8] = jitterX;\\n\\t\\t\\t\\t\\t\\t\\t\\tprojMatSkybox.data[9] = jitterY;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.blueNoiseJitterVersion !== this.device.renderVersion) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.blueNoiseJitterVersion = this.device.renderVersion;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.blueNoise.vec4(this.blueNoiseJitterVec);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst jitterVec = jitter > 0 ? this.blueNoiseJitterVec : Vec4.ZERO;\\n\\t\\t\\t\\t\\t\\tthis.blueNoiseJitterData[0] = jitterVec.x;\\n\\t\\t\\t\\t\\t\\tthis.blueNoiseJitterData[1] = jitterVec.y;\\n\\t\\t\\t\\t\\t\\tthis.blueNoiseJitterData[2] = jitterVec.z;\\n\\t\\t\\t\\t\\t\\tthis.blueNoiseJitterData[3] = jitterVec.w;\\n\\t\\t\\t\\t\\t\\tthis.blueNoiseJitterId.setValue(this.blueNoiseJitterData);\\n\\t\\t\\t\\t\\t\\tthis.projId.setValue(projMat.data);\\n\\t\\t\\t\\t\\t\\tthis.projSkyboxId.setValue(projMatSkybox.data);\\n\\t\\t\\t\\t\\t\\tif (camera.calculateTransform) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcamera.calculateTransform(viewInvMat, VIEW_CENTER);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst pos = camera._node.getPosition();\\n\\t\\t\\t\\t\\t\\t\\t\\tconst rot = camera._node.getRotation();\\n\\t\\t\\t\\t\\t\\t\\t\\tviewInvMat.setTRS(pos, rot, Vec3.ONE);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.viewInvId.setValue(viewInvMat.data);\\n\\t\\t\\t\\t\\t\\tviewMat.copy(viewInvMat).invert();\\n\\t\\t\\t\\t\\t\\tthis.viewId.setValue(viewMat.data);\\n\\t\\t\\t\\t\\t\\tviewMat3.setFromMat4(viewMat);\\n\\t\\t\\t\\t\\t\\tthis.viewId3.setValue(viewMat3.data);\\n\\t\\t\\t\\t\\t\\tviewProjMat.mul2(projMat, viewMat);\\n\\t\\t\\t\\t\\t\\tthis.viewProjId.setValue(viewProjMat.data);\\n\\t\\t\\t\\t\\t\\tcamera._storeShaderMatrices(viewProjMat, jitterX, jitterY, this.device.renderVersion);\\n\\t\\t\\t\\t\\t\\tthis.flipYId.setValue(flipY ? -1 : 1);\\n\\t\\t\\t\\t\\t\\tthis.dispatchViewPos(camera._node.getPosition());\\n\\t\\t\\t\\t\\t\\tcamera.frustum.setFromMat4(viewProjMat);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.tbnBasis.setValue(flipY ? -1 : 1);\\n\\t\\t\\t\\tthis.cameraParamsId.setValue(camera.fillShaderParams(this.cameraParams));\\n\\t\\t\\t\\tlet viewportWidth = target ? target.width : this.device.width;\\n\\t\\t\\t\\tlet viewportHeight = target ? target.height : this.device.height;\\n\\t\\t\\t\\tviewportWidth *= camera.rect.z;\\n\\t\\t\\t\\tviewportHeight *= camera.rect.w;\\n\\t\\t\\t\\tif (camera.xr?.active && camera.xr.views.list.length === 2) {\\n\\t\\t\\t\\t\\t\\tviewportWidth *= 0.5;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.viewportSize[0] = viewportWidth;\\n\\t\\t\\t\\tthis.viewportSize[1] = viewportHeight;\\n\\t\\t\\t\\tthis.viewportSize[2] = 1 / viewportWidth;\\n\\t\\t\\t\\tthis.viewportSize[3] = 1 / viewportHeight;\\n\\t\\t\\t\\tthis.viewportSizeId.setValue(this.viewportSize);\\n\\t\\t\\t\\tthis.exposureId.setValue(this.scene.physicalUnits ? camera.getExposure() : this.scene.exposure);\\n\\t\\t\\t\\treturn viewList;\\n\\t\\t}\\n\\t\\tclear(camera, clearColor, clearDepth, clearStencil) {\\n\\t\\t\\t\\tconst flags = (clearColor ?? camera._clearColorBuffer ? CLEARFLAG_COLOR : 0) | (clearDepth ?? camera._clearDepthBuffer ? CLEARFLAG_DEPTH : 0) | (clearStencil ?? camera._clearStencilBuffer ? CLEARFLAG_STENCIL : 0);\\n\\t\\t\\t\\tif (flags) {\\n\\t\\t\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\t\\t\\tdevice.clear({\\n\\t\\t\\t\\t\\t\\t\\t\\tcolor: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcamera._clearColor.r,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcamera._clearColor.g,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcamera._clearColor.b,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcamera._clearColor.a\\n\\t\\t\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t\\t\\tdepth: camera._clearDepth,\\n\\t\\t\\t\\t\\t\\t\\t\\tstencil: camera._clearStencil,\\n\\t\\t\\t\\t\\t\\t\\t\\tflags: flags\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetupCullMode(cullFaces, flipFactor, drawCall) {\\n\\t\\t\\t\\tconst material = drawCall.material;\\n\\t\\t\\t\\tlet mode = CULLFACE_NONE;\\n\\t\\t\\t\\tif (cullFaces) {\\n\\t\\t\\t\\t\\t\\tlet flipFaces = 1;\\n\\t\\t\\t\\t\\t\\tif (material.cull === CULLFACE_FRONT || material.cull === CULLFACE_BACK) {\\n\\t\\t\\t\\t\\t\\t\\t\\tflipFaces = flipFactor * drawCall.flipFacesFactor * drawCall.node.worldScaleSign;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (flipFaces < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmode = material.cull === CULLFACE_FRONT ? CULLFACE_BACK : CULLFACE_FRONT;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tmode = material.cull;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.device.setCullMode(mode);\\n\\t\\t\\t\\tif (mode === CULLFACE_NONE && material.cull === CULLFACE_NONE) {\\n\\t\\t\\t\\t\\t\\tthis.twoSidedLightingNegScaleFactorId.setValue(drawCall.node.worldScaleSign);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateCameraFrustum(camera) {\\n\\t\\t\\t\\tif (camera.xr && camera.xr.views.list.length) {\\n\\t\\t\\t\\t\\t\\tconst views = camera.xr.views.list;\\n\\t\\t\\t\\t\\t\\tviewProjMat.mul2(views[0].projMat, views[0].viewOffMat);\\n\\t\\t\\t\\t\\t\\tcamera.frustum.setFromMat4(viewProjMat);\\n\\t\\t\\t\\t\\t\\tfor(let v = 1; v < views.length; v++){\\n\\t\\t\\t\\t\\t\\t\\t\\tviewProjMat.mul2(views[v].projMat, views[v].viewOffMat);\\n\\t\\t\\t\\t\\t\\t\\t\\ttempFrustum.setFromMat4(viewProjMat);\\n\\t\\t\\t\\t\\t\\t\\t\\tcamera.frustum.add(tempFrustum);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst projMat = camera.projectionMatrix;\\n\\t\\t\\t\\tif (camera.calculateProjection) {\\n\\t\\t\\t\\t\\t\\tcamera.calculateProjection(projMat, VIEW_CENTER);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (camera.calculateTransform) {\\n\\t\\t\\t\\t\\t\\tcamera.calculateTransform(viewInvMat, VIEW_CENTER);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst pos = camera._node.getPosition();\\n\\t\\t\\t\\t\\t\\tconst rot = camera._node.getRotation();\\n\\t\\t\\t\\t\\t\\tviewInvMat.setTRS(pos, rot, Vec3.ONE);\\n\\t\\t\\t\\t\\t\\tthis.viewInvId.setValue(viewInvMat.data);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tviewMat.copy(viewInvMat).invert();\\n\\t\\t\\t\\tviewProjMat.mul2(projMat, viewMat);\\n\\t\\t\\t\\tcamera.frustum.setFromMat4(viewProjMat);\\n\\t\\t}\\n\\t\\tsetBaseConstants(device, material) {\\n\\t\\t\\t\\tdevice.setCullMode(material.cull);\\n\\t\\t\\t\\tif (material.opacityMap) {\\n\\t\\t\\t\\t\\t\\tthis.opacityMapId.setValue(material.opacityMap);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (material.opacityMap || material.alphaTest > 0) {\\n\\t\\t\\t\\t\\t\\tthis.alphaTestId.setValue(material.alphaTest);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateCpuSkinMatrices(drawCalls) {\\n\\t\\t\\t\\t_skinUpdateIndex++;\\n\\t\\t\\t\\tconst drawCallsCount = drawCalls.length;\\n\\t\\t\\t\\tif (drawCallsCount === 0) return;\\n\\t\\t\\t\\tfor(let i = 0; i < drawCallsCount; i++){\\n\\t\\t\\t\\t\\t\\tconst si = drawCalls[i].skinInstance;\\n\\t\\t\\t\\t\\t\\tif (si) {\\n\\t\\t\\t\\t\\t\\t\\t\\tsi.updateMatrices(drawCalls[i].node, _skinUpdateIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\tsi._dirty = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateGpuSkinMatrices(drawCalls) {\\n\\t\\t\\t\\tfor (const drawCall of drawCalls){\\n\\t\\t\\t\\t\\t\\tconst skin = drawCall.skinInstance;\\n\\t\\t\\t\\t\\t\\tif (skin && skin._dirty) {\\n\\t\\t\\t\\t\\t\\t\\t\\tskin.updateMatrixPalette(drawCall.node, _skinUpdateIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\tskin._dirty = false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateMorphing(drawCalls) {\\n\\t\\t\\t\\tfor (const drawCall of drawCalls){\\n\\t\\t\\t\\t\\t\\tconst morphInst = drawCall.morphInstance;\\n\\t\\t\\t\\t\\t\\tif (morphInst && morphInst._dirty) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmorphInst.update();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateGSplats(drawCalls) {\\n\\t\\t\\t\\tfor (const drawCall of drawCalls){\\n\\t\\t\\t\\t\\t\\tdrawCall.gsplatInstance?.update();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgpuUpdate(drawCalls) {\\n\\t\\t\\t\\tthis.updateGpuSkinMatrices(drawCalls);\\n\\t\\t\\t\\tthis.updateMorphing(drawCalls);\\n\\t\\t\\t\\tthis.updateGSplats(drawCalls);\\n\\t\\t}\\n\\t\\tsetVertexBuffers(device, mesh) {\\n\\t\\t\\t\\tdevice.setVertexBuffer(mesh.vertexBuffer);\\n\\t\\t}\\n\\t\\tsetMorphing(device, morphInstance) {\\n\\t\\t\\t\\tif (morphInstance) {\\n\\t\\t\\t\\t\\t\\tmorphInstance.prepareRendering(device);\\n\\t\\t\\t\\t\\t\\tdevice.setVertexBuffer(morphInstance.morph.vertexBufferIds);\\n\\t\\t\\t\\t\\t\\tthis.morphPositionTex.setValue(morphInstance.texturePositions);\\n\\t\\t\\t\\t\\t\\tthis.morphNormalTex.setValue(morphInstance.textureNormals);\\n\\t\\t\\t\\t\\t\\tthis.morphTexParams.setValue(morphInstance._textureParams);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetSkinning(device, meshInstance) {\\n\\t\\t\\t\\tconst skinInstance = meshInstance.skinInstance;\\n\\t\\t\\t\\tif (skinInstance) {\\n\\t\\t\\t\\t\\t\\tthis._skinDrawCalls++;\\n\\t\\t\\t\\t\\t\\tconst boneTexture = skinInstance.boneTexture;\\n\\t\\t\\t\\t\\t\\tthis.boneTextureId.setValue(boneTexture);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdispatchViewPos(position) {\\n\\t\\t\\t\\tconst vp = this.viewPos;\\n\\t\\t\\t\\tvp[0] = position.x;\\n\\t\\t\\t\\tvp[1] = position.y;\\n\\t\\t\\t\\tvp[2] = position.z;\\n\\t\\t\\t\\tthis.viewPosId.setValue(vp);\\n\\t\\t}\\n\\t\\tinitViewBindGroupFormat(isClustered) {\\n\\t\\t\\t\\tif (this.device.supportsUniformBuffers && !this.viewUniformFormat) {\\n\\t\\t\\t\\t\\t\\tconst uniforms = [\\n\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('matrix_view', UNIFORMTYPE_MAT4),\\n\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('matrix_viewInverse', UNIFORMTYPE_MAT4),\\n\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('matrix_projection', UNIFORMTYPE_MAT4),\\n\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('matrix_projectionSkybox', UNIFORMTYPE_MAT4),\\n\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('matrix_viewProjection', UNIFORMTYPE_MAT4),\\n\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('matrix_view3', UNIFORMTYPE_MAT3),\\n\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('cubeMapRotationMatrix', UNIFORMTYPE_MAT3),\\n\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('view_position', UNIFORMTYPE_VEC3),\\n\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('viewport_size', UNIFORMTYPE_VEC4),\\n\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('skyboxIntensity', UNIFORMTYPE_FLOAT),\\n\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('exposure', UNIFORMTYPE_FLOAT),\\n\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('textureBias', UNIFORMTYPE_FLOAT),\\n\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('view_index', UNIFORMTYPE_FLOAT)\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t\\t\\tif (isClustered) {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniforms.push(...[\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('clusterCellsCountByBoundsSize', UNIFORMTYPE_VEC3),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('clusterBoundsMin', UNIFORMTYPE_VEC3),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('clusterBoundsDelta', UNIFORMTYPE_VEC3),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('clusterCellsDot', UNIFORMTYPE_IVEC3),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('clusterCellsMax', UNIFORMTYPE_IVEC3),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('shadowAtlasParams', UNIFORMTYPE_VEC2),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('clusterMaxCells', UNIFORMTYPE_INT),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('numClusteredLights', UNIFORMTYPE_INT),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnew UniformFormat('clusterTextureWidth', UNIFORMTYPE_INT)\\n\\t\\t\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.viewUniformFormat = new UniformBufferFormat(this.device, uniforms);\\n\\t\\t\\t\\t\\t\\tconst formats = [\\n\\t\\t\\t\\t\\t\\t\\t\\tnew BindUniformBufferFormat(UNIFORM_BUFFER_DEFAULT_SLOT_NAME, SHADERSTAGE_VERTEX | SHADERSTAGE_FRAGMENT)\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t\\t\\tthis.viewBindGroupFormat = new BindGroupFormat(this.device, formats);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetupViewUniforms(view, index) {\\n\\t\\t\\t\\tthis.projId.setValue(view.projMat.data);\\n\\t\\t\\t\\tthis.projSkyboxId.setValue(view.projMat.data);\\n\\t\\t\\t\\tthis.viewId.setValue(view.viewOffMat.data);\\n\\t\\t\\t\\tthis.viewInvId.setValue(view.viewInvOffMat.data);\\n\\t\\t\\t\\tthis.viewId3.setValue(view.viewMat3.data);\\n\\t\\t\\t\\tthis.viewProjId.setValue(view.projViewOffMat.data);\\n\\t\\t\\t\\tthis.viewPosId.setValue(view.positionData);\\n\\t\\t\\t\\tthis.viewIndexId.setValue(index);\\n\\t\\t}\\n\\t\\tsetupViewUniformBuffers(viewBindGroups, viewUniformFormat, viewBindGroupFormat, viewList) {\\n\\t\\t\\t\\tconst { device } = this;\\n\\t\\t\\t\\tconst viewCount = viewList?.length ?? 1;\\n\\t\\t\\t\\twhile(viewBindGroups.length < viewCount){\\n\\t\\t\\t\\t\\t\\tconst ub = new UniformBuffer(device, viewUniformFormat, false);\\n\\t\\t\\t\\t\\t\\tconst bg = new BindGroup(device, viewBindGroupFormat, ub);\\n\\t\\t\\t\\t\\t\\tviewBindGroups.push(bg);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (viewList) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < viewCount; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst view = viewList[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setupViewUniforms(view, i);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst viewBindGroup = viewBindGroups[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tviewBindGroup.defaultUniformBuffer.update();\\n\\t\\t\\t\\t\\t\\t\\t\\tviewBindGroup.update();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst viewBindGroup = viewBindGroups[0];\\n\\t\\t\\t\\t\\t\\tviewBindGroup.defaultUniformBuffer.update();\\n\\t\\t\\t\\t\\t\\tviewBindGroup.update();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!viewList) {\\n\\t\\t\\t\\t\\t\\tdevice.setBindGroup(BINDGROUP_VIEW, viewBindGroups[0]);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetupMeshUniformBuffers(shaderInstance) {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tif (device.supportsUniformBuffers) {\\n\\t\\t\\t\\t\\t\\tconst meshBindGroup = shaderInstance.getBindGroup(device);\\n\\t\\t\\t\\t\\t\\tmeshBindGroup.update();\\n\\t\\t\\t\\t\\t\\tdevice.setBindGroup(BINDGROUP_MESH, meshBindGroup);\\n\\t\\t\\t\\t\\t\\tconst meshUniformBuffer = shaderInstance.getUniformBuffer(device);\\n\\t\\t\\t\\t\\t\\tmeshUniformBuffer.update(_dynamicBindGroup);\\n\\t\\t\\t\\t\\t\\tdevice.setBindGroup(BINDGROUP_MESH_UB, _dynamicBindGroup.bindGroup, _dynamicBindGroup.offsets);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetMeshInstanceMatrices(meshInstance, setNormalMatrix = false) {\\n\\t\\t\\t\\tconst modelMatrix = meshInstance.node.worldTransform;\\n\\t\\t\\t\\tthis.modelMatrixId.setValue(modelMatrix.data);\\n\\t\\t\\t\\tif (setNormalMatrix) {\\n\\t\\t\\t\\t\\t\\tthis.normalMatrixId.setValue(meshInstance.node.normalMatrix.data);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcull(camera, drawCalls, culledInstances) {\\n\\t\\t\\t\\tconst opaque = culledInstances.opaque;\\n\\t\\t\\t\\topaque.length = 0;\\n\\t\\t\\t\\tconst transparent = culledInstances.transparent;\\n\\t\\t\\t\\ttransparent.length = 0;\\n\\t\\t\\t\\tconst doCull = camera.frustumCulling;\\n\\t\\t\\t\\tconst count = drawCalls.length;\\n\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\tconst drawCall = drawCalls[i];\\n\\t\\t\\t\\t\\t\\tif (drawCall.visible) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst visible = !doCull || !drawCall.cull || drawCall._isVisible(camera);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (visible) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdrawCall.visibleThisFrame = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst bucket = drawCall.transparent ? transparent : opaque;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbucket.push(drawCall);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (drawCall.skinInstance || drawCall.morphInstance || drawCall.gsplatInstance) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.processingMeshInstances.add(drawCall);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (drawCall.gsplatInstance) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdrawCall.gsplatInstance.cameras.push(camera);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcollectLights(comp) {\\n\\t\\t\\t\\tthis.lights.length = 0;\\n\\t\\t\\t\\tthis.localLights.length = 0;\\n\\t\\t\\t\\tconst stats = this.scene._stats;\\n\\t\\t\\t\\tconst count = comp.layerList.length;\\n\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\tconst layer = comp.layerList[i];\\n\\t\\t\\t\\t\\t\\tif (!_tempLayerSet.has(layer)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t_tempLayerSet.add(layer);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst lights = layer._lights;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < lights.length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst light = lights[j];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!_tempLightSet.has(light)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_tempLightSet.add(light);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.lights.push(light);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (light._type !== LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.localLights.push(light);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tstats.lights = this.lights.length;\\n\\t\\t\\t\\t_tempLightSet.clear();\\n\\t\\t\\t\\t_tempLayerSet.clear();\\n\\t\\t}\\n\\t\\tcullLights(camera, lights) {\\n\\t\\t\\t\\tconst clusteredLightingEnabled = this.scene.clusteredLightingEnabled;\\n\\t\\t\\t\\tconst physicalUnits = this.scene.physicalUnits;\\n\\t\\t\\t\\tfor(let i = 0; i < lights.length; i++){\\n\\t\\t\\t\\t\\t\\tconst light = lights[i];\\n\\t\\t\\t\\t\\t\\tif (light.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (light._type !== LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlight.getBoundingSphere(tempSphere);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (camera.frustum.containsSphere(tempSphere)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlight.visibleThisFrame = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlight.usePhysicalUnits = physicalUnits;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst screenSize = camera.getScreenSize(tempSphere);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlight.maxScreenSize = Math.max(light.maxScreenSize, screenSize);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (light.castShadows && !light.shadowMap) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlight.visibleThisFrame = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlight.usePhysicalUnits = this.scene.physicalUnits;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcullShadowmaps(comp) {\\n\\t\\t\\t\\tconst isClustered = this.scene.clusteredLightingEnabled;\\n\\t\\t\\t\\tfor(let i = 0; i < this.localLights.length; i++){\\n\\t\\t\\t\\t\\t\\tconst light = this.localLights[i];\\n\\t\\t\\t\\t\\t\\tif (light._type !== LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (isClustered) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (light.atlasSlotUpdated && light.shadowUpdateMode === SHADOWUPDATE_NONE) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlight.shadowUpdateMode = SHADOWUPDATE_THISFRAME;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (light.shadowUpdateMode === SHADOWUPDATE_NONE && light.castShadows) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!light.getRenderData(null, 0).shadowCamera.renderTarget) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlight.shadowUpdateMode = SHADOWUPDATE_THISFRAME;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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\\tif (light.visibleThisFrame && light.castShadows && light.shadowUpdateMode !== SHADOWUPDATE_NONE) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._shadowRendererLocal.cull(light, comp);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.cameraDirShadowLights.clear();\\n\\t\\t\\t\\tconst cameras = comp.cameras;\\n\\t\\t\\t\\tfor(let i = 0; i < cameras.length; i++){\\n\\t\\t\\t\\t\\t\\tconst cameraComponent = cameras[i];\\n\\t\\t\\t\\t\\t\\tif (cameraComponent.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst camera = cameraComponent.camera;\\n\\t\\t\\t\\t\\t\\t\\t\\tlet lightList;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst cameraLayers = camera.layers;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let l = 0; l < cameraLayers.length; l++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst cameraLayer = comp.getLayerById(cameraLayers[l]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (cameraLayer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst layerDirLights = cameraLayer.splitLights[LIGHTTYPE_DIRECTIONAL];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < layerDirLights.length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst light = layerDirLights[j];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (light.castShadows && !_tempSet.has(light)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_tempSet.add(light);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlightList = lightList ?? [];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlightList.push(light);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._shadowRendererDirectional.cull(light, comp, camera);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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\\tif (lightList) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.cameraDirShadowLights.set(camera, lightList);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t_tempSet.clear();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcullComposition(comp) {\\n\\t\\t\\t\\tconst { scene } = this;\\n\\t\\t\\t\\tthis.processingMeshInstances.clear();\\n\\t\\t\\t\\tconst numCameras = comp.cameras.length;\\n\\t\\t\\t\\tthis._camerasRendered += numCameras;\\n\\t\\t\\t\\tfor(let i = 0; i < numCameras; i++){\\n\\t\\t\\t\\t\\t\\tconst camera = comp.cameras[i];\\n\\t\\t\\t\\t\\t\\tscene?.fire(EVENT_PRECULL, camera);\\n\\t\\t\\t\\t\\t\\tconst renderTarget = camera.renderTarget;\\n\\t\\t\\t\\t\\t\\tcamera.frameUpdate(renderTarget);\\n\\t\\t\\t\\t\\t\\tthis.updateCameraFrustum(camera.camera);\\n\\t\\t\\t\\t\\t\\tconst layerIds = camera.layers;\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j < layerIds.length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst layer = comp.getLayerById(layerIds[j]);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (layer && layer.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.cullLights(camera.camera, layer._lights);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst culledInstances = layer.getCulledInstances(camera.camera);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.cull(camera.camera, layer.meshInstances, culledInstances);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tscene?.fire(EVENT_POSTCULL, camera);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (scene.clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\t\\tthis.updateLightTextureAtlas();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.cullShadowmaps(comp);\\n\\t\\t\\t\\tscene?.fire(EVENT_CULL_END);\\n\\t\\t}\\n\\t\\tupdateShaders(drawCalls, onlyLitShaders) {\\n\\t\\t\\t\\tconst count = drawCalls.length;\\n\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\tconst mat = drawCalls[i].material;\\n\\t\\t\\t\\t\\t\\tif (mat) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!_tempSet.has(mat)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_tempSet.add(mat);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (mat.getShaderVariant !== Material.prototype.getShaderVariant) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (onlyLitShaders) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!mat.useLighting || mat.emitter && !mat.emitter.lighting) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmat.clearVariants();\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\t_tempSet.clear();\\n\\t\\t}\\n\\t\\tupdateFrameUniforms() {\\n\\t\\t\\t\\tthis.blueNoiseTextureId.setValue(getBlueNoiseTexture(this.device));\\n\\t\\t}\\n\\t\\tbeginFrame(comp) {\\n\\t\\t\\t\\tconst scene = this.scene;\\n\\t\\t\\t\\tconst updateShaders = scene.updateShaders || this.device._shadersDirty;\\n\\t\\t\\t\\tconst layers = comp.layerList;\\n\\t\\t\\t\\tconst layerCount = layers.length;\\n\\t\\t\\t\\tfor(let i = 0; i < layerCount; i++){\\n\\t\\t\\t\\t\\t\\tconst layer = layers[i];\\n\\t\\t\\t\\t\\t\\tconst meshInstances = layer.meshInstances;\\n\\t\\t\\t\\t\\t\\tconst count = meshInstances.length;\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j < count; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst meshInst = meshInstances[j];\\n\\t\\t\\t\\t\\t\\t\\t\\tmeshInst.visibleThisFrame = false;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (updateShaders) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_tempMeshInstances.push(meshInst);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (meshInst.skinInstance) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_tempMeshInstancesSkinned.push(meshInst);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (updateShaders) {\\n\\t\\t\\t\\t\\t\\tconst onlyLitShaders = !scene.updateShaders || !this.device._shadersDirty;\\n\\t\\t\\t\\t\\t\\tthis.updateShaders(_tempMeshInstances, onlyLitShaders);\\n\\t\\t\\t\\t\\t\\tscene.updateShaders = false;\\n\\t\\t\\t\\t\\t\\tthis.device._shadersDirty = false;\\n\\t\\t\\t\\t\\t\\tscene._shaderVersion++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.updateFrameUniforms();\\n\\t\\t\\t\\tthis.updateCpuSkinMatrices(_tempMeshInstancesSkinned);\\n\\t\\t\\t\\t_tempMeshInstances.length = 0;\\n\\t\\t\\t\\t_tempMeshInstancesSkinned.length = 0;\\n\\t\\t\\t\\tconst lights = this.lights;\\n\\t\\t\\t\\tconst lightCount = lights.length;\\n\\t\\t\\t\\tfor(let i = 0; i < lightCount; i++){\\n\\t\\t\\t\\t\\t\\tlights[i].beginFrame();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateLightTextureAtlas() {\\n\\t\\t\\t\\tthis.lightTextureAtlas.update(this.localLights, this.scene.lighting);\\n\\t\\t}\\n\\t\\tupdateLayerComposition(comp) {\\n\\t\\t\\t\\tconst len = comp.layerList.length;\\n\\t\\t\\t\\tconst scene = this.scene;\\n\\t\\t\\t\\tconst shaderVersion = scene._shaderVersion;\\n\\t\\t\\t\\tfor(let i = 0; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst layer = comp.layerList[i];\\n\\t\\t\\t\\t\\t\\tlayer._shaderVersion = shaderVersion;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcomp._update();\\n\\t\\t}\\n\\t\\tframeUpdate() {\\n\\t\\t\\t\\tthis.clustersDebugRendered = false;\\n\\t\\t\\t\\tthis.initViewBindGroupFormat(this.scene.clusteredLightingEnabled);\\n\\t\\t\\t\\tthis.dirLightShadows.clear();\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice, scene){\\n\\t\\t\\t\\tthis.clustersDebugRendered = false;\\n\\t\\t\\t\\tthis.processingMeshInstances = new Set();\\n\\t\\t\\t\\tthis.lights = [];\\n\\t\\t\\t\\tthis.localLights = [];\\n\\t\\t\\t\\tthis.cameraDirShadowLights = new Map();\\n\\t\\t\\t\\tthis.dirLightShadows = new Map();\\n\\t\\t\\t\\tthis.blueNoise = new BlueNoise(123);\\n\\t\\t\\t\\tthis.gsplatDirector = null;\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t\\t\\tthis.scene = scene;\\n\\t\\t\\t\\tthis.worldClustersAllocator = new WorldClustersAllocator(graphicsDevice);\\n\\t\\t\\t\\tthis.lightTextureAtlas = new LightTextureAtlas(graphicsDevice);\\n\\t\\t\\t\\tthis.shadowMapCache = new ShadowMapCache();\\n\\t\\t\\t\\tthis.shadowRenderer = new ShadowRenderer(this, this.lightTextureAtlas);\\n\\t\\t\\t\\tthis._shadowRendererLocal = new ShadowRendererLocal(this, this.shadowRenderer);\\n\\t\\t\\t\\tthis._shadowRendererDirectional = new ShadowRendererDirectional(this, this.shadowRenderer);\\n\\t\\t\\t\\tif (this.scene.clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\t\\tthis._renderPassUpdateClustered = new RenderPassUpdateClustered(this.device, this, this.shadowRenderer, this._shadowRendererLocal, this.lightTextureAtlas);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.viewUniformFormat = null;\\n\\t\\t\\t\\tthis.viewBindGroupFormat = null;\\n\\t\\t\\t\\tthis._skinTime = 0;\\n\\t\\t\\t\\tthis._morphTime = 0;\\n\\t\\t\\t\\tthis._cullTime = 0;\\n\\t\\t\\t\\tthis._shadowMapTime = 0;\\n\\t\\t\\t\\tthis._lightClustersTime = 0;\\n\\t\\t\\t\\tthis._layerCompositionUpdateTime = 0;\\n\\t\\t\\t\\tthis._shadowDrawCalls = 0;\\n\\t\\t\\t\\tthis._skinDrawCalls = 0;\\n\\t\\t\\t\\tthis._instancedDrawCalls = 0;\\n\\t\\t\\t\\tthis._shadowMapUpdates = 0;\\n\\t\\t\\t\\tthis._numDrawCallsCulled = 0;\\n\\t\\t\\t\\tthis._camerasRendered = 0;\\n\\t\\t\\t\\tthis._lightClusters = 0;\\n\\t\\t\\t\\tthis._gsplatCount = 0;\\n\\t\\t\\t\\tconst scope = graphicsDevice.scope;\\n\\t\\t\\t\\tthis.boneTextureId = scope.resolve('texture_poseMap');\\n\\t\\t\\t\\tthis.modelMatrixId = scope.resolve('matrix_model');\\n\\t\\t\\t\\tthis.normalMatrixId = scope.resolve('matrix_normal');\\n\\t\\t\\t\\tthis.viewInvId = scope.resolve('matrix_viewInverse');\\n\\t\\t\\t\\tthis.viewPos = new Float32Array(3);\\n\\t\\t\\t\\tthis.viewPosId = scope.resolve('view_position');\\n\\t\\t\\t\\tthis.projId = scope.resolve('matrix_projection');\\n\\t\\t\\t\\tthis.projSkyboxId = scope.resolve('matrix_projectionSkybox');\\n\\t\\t\\t\\tthis.viewId = scope.resolve('matrix_view');\\n\\t\\t\\t\\tthis.viewId3 = scope.resolve('matrix_view3');\\n\\t\\t\\t\\tthis.viewProjId = scope.resolve('matrix_viewProjection');\\n\\t\\t\\t\\tthis.flipYId = scope.resolve('projectionFlipY');\\n\\t\\t\\t\\tthis.tbnBasis = scope.resolve('tbnBasis');\\n\\t\\t\\t\\tthis.cameraParams = new Float32Array(4);\\n\\t\\t\\t\\tthis.cameraParamsId = scope.resolve('camera_params');\\n\\t\\t\\t\\tthis.viewportSize = new Float32Array(4);\\n\\t\\t\\t\\tthis.viewportSizeId = scope.resolve('viewport_size');\\n\\t\\t\\t\\tthis.viewIndexId = scope.resolve('view_index');\\n\\t\\t\\t\\tthis.viewIndexId.setValue(0);\\n\\t\\t\\t\\tthis.blueNoiseJitterVersion = 0;\\n\\t\\t\\t\\tthis.blueNoiseJitterVec = new Vec4();\\n\\t\\t\\t\\tthis.blueNoiseJitterData = new Float32Array(4);\\n\\t\\t\\t\\tthis.blueNoiseJitterId = scope.resolve('blueNoiseJitter');\\n\\t\\t\\t\\tthis.blueNoiseTextureId = scope.resolve('blueNoiseTex32');\\n\\t\\t\\t\\tthis.alphaTestId = scope.resolve('alpha_ref');\\n\\t\\t\\t\\tthis.opacityMapId = scope.resolve('texture_opacityMap');\\n\\t\\t\\t\\tthis.exposureId = scope.resolve('exposure');\\n\\t\\t\\t\\tthis.twoSidedLightingNegScaleFactorId = scope.resolve('twoSidedLightingNegScaleFactor');\\n\\t\\t\\t\\tthis.twoSidedLightingNegScaleFactorId.setValue(0);\\n\\t\\t\\t\\tthis.morphPositionTex = scope.resolve('morphPositionTex');\\n\\t\\t\\t\\tthis.morphNormalTex = scope.resolve('morphNormalTex');\\n\\t\\t\\t\\tthis.morphTexParams = scope.resolve('morph_tex_params');\\n\\t\\t\\t\\tthis.lightCube = new LightCube();\\n\\t\\t\\t\\tthis.constantLightCube = scope.resolve('lightCube[0]');\\n\\t\\t}\\n}\\n\\nclass RenderAction {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.viewBindGroups.forEach((bg)=>{\\n\\t\\t\\t\\t\\t\\tbg.defaultUniformBuffer.destroy();\\n\\t\\t\\t\\t\\t\\tbg.destroy();\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.viewBindGroups.length = 0;\\n\\t\\t}\\n\\t\\tsetupClears(camera, layer) {\\n\\t\\t\\t\\tthis.clearColor = camera?.clearColorBuffer || layer.clearColorBuffer;\\n\\t\\t\\t\\tthis.clearDepth = camera?.clearDepthBuffer || layer.clearDepthBuffer;\\n\\t\\t\\t\\tthis.clearStencil = camera?.clearStencilBuffer || layer.clearStencilBuffer;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.camera = null;\\n\\t\\t\\t\\tthis.layer = null;\\n\\t\\t\\t\\tthis.transparent = false;\\n\\t\\t\\t\\tthis.renderTarget = null;\\n\\t\\t\\t\\tthis.lightClusters = null;\\n\\t\\t\\t\\tthis.clearColor = false;\\n\\t\\t\\t\\tthis.clearDepth = false;\\n\\t\\t\\t\\tthis.clearStencil = false;\\n\\t\\t\\t\\tthis.triggerPostprocess = false;\\n\\t\\t\\t\\tthis.firstCameraUse = false;\\n\\t\\t\\t\\tthis.lastCameraUse = false;\\n\\t\\t\\t\\tthis.viewBindGroups = [];\\n\\t\\t\\t\\tthis.useCameraPasses = false;\\n\\t\\t}\\n}\\n\\nclass RenderPassForward extends RenderPass {\\n\\t\\tget rendersAnything() {\\n\\t\\t\\t\\treturn this.renderActions.length > 0;\\n\\t\\t}\\n\\t\\taddRenderAction(renderAction) {\\n\\t\\t\\t\\tthis.renderActions.push(renderAction);\\n\\t\\t}\\n\\t\\taddLayer(cameraComponent, layer, transparent, autoClears = true) {\\n\\t\\t\\t\\tconst ra = new RenderAction();\\n\\t\\t\\t\\tra.renderTarget = this.renderTarget;\\n\\t\\t\\t\\tra.camera = cameraComponent;\\n\\t\\t\\t\\tra.layer = layer;\\n\\t\\t\\t\\tra.transparent = transparent;\\n\\t\\t\\t\\tif (autoClears) {\\n\\t\\t\\t\\t\\t\\tconst firstRa = this.renderActions.length === 0;\\n\\t\\t\\t\\t\\t\\tra.setupClears(firstRa ? cameraComponent : undefined, layer);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.addRenderAction(ra);\\n\\t\\t}\\n\\t\\taddLayers(composition, cameraComponent, startIndex, firstLayerClears, lastLayerId, lastLayerIsTransparent = true) {\\n\\t\\t\\t\\tconst { layerList, subLayerList } = composition;\\n\\t\\t\\t\\tlet clearRenderTarget = firstLayerClears;\\n\\t\\t\\t\\tlet index = startIndex;\\n\\t\\t\\t\\twhile(index < layerList.length){\\n\\t\\t\\t\\t\\t\\tconst layer = layerList[index];\\n\\t\\t\\t\\t\\t\\tconst isTransparent = subLayerList[index];\\n\\t\\t\\t\\t\\t\\tconst renderedByCamera = cameraComponent.camera.layersSet.has(layer.id);\\n\\t\\t\\t\\t\\t\\tif (renderedByCamera) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.addLayer(cameraComponent, layer, isTransparent, clearRenderTarget);\\n\\t\\t\\t\\t\\t\\t\\t\\tclearRenderTarget = false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tindex++;\\n\\t\\t\\t\\t\\t\\tif (layer.id === lastLayerId && isTransparent === lastLayerIsTransparent) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn index;\\n\\t\\t}\\n\\t\\tupdateDirectionalShadows() {\\n\\t\\t\\t\\tconst { renderer, renderActions } = this;\\n\\t\\t\\t\\tfor(let i = 0; i < renderActions.length; i++){\\n\\t\\t\\t\\t\\t\\tconst renderAction = renderActions[i];\\n\\t\\t\\t\\t\\t\\tconst cameraComp = renderAction.camera;\\n\\t\\t\\t\\t\\t\\tconst camera = cameraComp.camera;\\n\\t\\t\\t\\t\\t\\tconst shadowDirLights = this.renderer.cameraDirShadowLights.get(camera);\\n\\t\\t\\t\\t\\t\\tif (shadowDirLights) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let l = 0; l < shadowDirLights.length; l++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst light = shadowDirLights[l];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (renderer.dirLightShadows.get(light) !== camera) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trenderer.dirLightShadows.set(light, camera);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst shadowPass = renderer._shadowRendererDirectional.getLightRenderPass(light, camera);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (shadowPass) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.beforePasses.push(shadowPass);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateClears() {\\n\\t\\t\\t\\tconst renderAction = this.renderActions[0];\\n\\t\\t\\t\\tif (renderAction) {\\n\\t\\t\\t\\t\\t\\tconst cameraComponent = renderAction.camera;\\n\\t\\t\\t\\t\\t\\tconst camera = cameraComponent.camera;\\n\\t\\t\\t\\t\\t\\tconst fullSizeClearRect = camera.fullSizeClearRect;\\n\\t\\t\\t\\t\\t\\tthis.setClearColor(fullSizeClearRect && renderAction.clearColor ? camera.clearColor : undefined);\\n\\t\\t\\t\\t\\t\\tthis.setClearDepth(fullSizeClearRect && renderAction.clearDepth && !this.noDepthClear ? camera.clearDepth : undefined);\\n\\t\\t\\t\\t\\t\\tthis.setClearStencil(fullSizeClearRect && renderAction.clearStencil ? camera.clearStencil : undefined);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tframeUpdate() {\\n\\t\\t\\t\\tsuper.frameUpdate();\\n\\t\\t\\t\\tthis.updateDirectionalShadows();\\n\\t\\t\\t\\tthis.updateClears();\\n\\t\\t}\\n\\t\\tbefore() {\\n\\t\\t\\t\\tconst { renderActions } = this;\\n\\t\\t\\t\\tfor(let i = 0; i < renderActions.length; i++){\\n\\t\\t\\t\\t\\t\\tconst ra = renderActions[i];\\n\\t\\t\\t\\t\\t\\tif (ra.firstCameraUse) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.scene.fire(EVENT_PRERENDER, ra.camera);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\texecute() {\\n\\t\\t\\t\\tconst { layerComposition, renderActions } = this;\\n\\t\\t\\t\\tfor(let i = 0; i < renderActions.length; i++){\\n\\t\\t\\t\\t\\t\\tconst ra = renderActions[i];\\n\\t\\t\\t\\t\\t\\tconst layer = ra.layer;\\n\\t\\t\\t\\t\\t\\tif (layerComposition.isEnabled(layer, ra.transparent)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.renderRenderAction(ra, i === 0);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tafter() {\\n\\t\\t\\t\\tfor(let i = 0; i < this.renderActions.length; i++){\\n\\t\\t\\t\\t\\t\\tconst ra = this.renderActions[i];\\n\\t\\t\\t\\t\\t\\tif (ra.lastCameraUse) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.scene.fire(EVENT_POSTRENDER, ra.camera);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.beforePasses.length = 0;\\n\\t\\t}\\n\\t\\trenderRenderAction(renderAction, firstRenderAction) {\\n\\t\\t\\t\\tconst { renderer, scene } = this;\\n\\t\\t\\t\\tconst device = renderer.device;\\n\\t\\t\\t\\tconst { layer, transparent, camera } = renderAction;\\n\\t\\t\\t\\tif (camera) {\\n\\t\\t\\t\\t\\t\\tconst originalGammaCorrection = camera.gammaCorrection;\\n\\t\\t\\t\\t\\t\\tconst originalToneMapping = camera.toneMapping;\\n\\t\\t\\t\\t\\t\\tif (this.gammaCorrection !== undefined) camera.gammaCorrection = this.gammaCorrection;\\n\\t\\t\\t\\t\\t\\tif (this.toneMapping !== undefined) camera.toneMapping = this.toneMapping;\\n\\t\\t\\t\\t\\t\\tscene.fire(EVENT_PRERENDER_LAYER, camera, layer, transparent);\\n\\t\\t\\t\\t\\t\\tconst options = {\\n\\t\\t\\t\\t\\t\\t\\t\\tlightClusters: renderAction.lightClusters\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tconst shaderPass = camera.camera.shaderPassInfo?.index ?? SHADER_FORWARD;\\n\\t\\t\\t\\t\\t\\tif (!firstRenderAction || !camera.camera.fullSizeClearRect) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.clearColor = renderAction.clearColor;\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.clearDepth = renderAction.clearDepth;\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.clearStencil = renderAction.clearStencil;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst renderTarget = renderAction.renderTarget ?? device.backBuffer;\\n\\t\\t\\t\\t\\t\\trenderer.renderForwardLayer(camera.camera, renderTarget, layer, transparent, shaderPass, renderAction.viewBindGroups, options);\\n\\t\\t\\t\\t\\t\\tdevice.setBlendState(BlendState.NOBLEND);\\n\\t\\t\\t\\t\\t\\tdevice.setStencilState(null, null);\\n\\t\\t\\t\\t\\t\\tdevice.setAlphaToCoverage(false);\\n\\t\\t\\t\\t\\t\\tscene.fire(EVENT_POSTRENDER_LAYER, camera, layer, transparent);\\n\\t\\t\\t\\t\\t\\tif (this.gammaCorrection !== undefined) camera.gammaCorrection = originalGammaCorrection;\\n\\t\\t\\t\\t\\t\\tif (this.toneMapping !== undefined) camera.toneMapping = originalToneMapping;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(device, layerComposition, scene, renderer){\\n\\t\\t\\t\\tsuper(device), this.renderActions = [], this.noDepthClear = false;\\n\\t\\t\\t\\tthis.layerComposition = layerComposition;\\n\\t\\t\\t\\tthis.scene = scene;\\n\\t\\t\\t\\tthis.renderer = renderer;\\n\\t\\t}\\n}\\n\\nclass RenderPassPostprocessing extends RenderPass {\\n\\t\\texecute() {\\n\\t\\t\\t\\tconst renderAction = this.renderAction;\\n\\t\\t\\t\\tconst camera = renderAction.camera;\\n\\t\\t\\t\\tcamera.onPostprocessing();\\n\\t\\t}\\n\\t\\tconstructor(device, renderer, renderAction){\\n\\t\\t\\t\\tsuper(device);\\n\\t\\t\\t\\tthis.renderer = renderer;\\n\\t\\t\\t\\tthis.renderAction = renderAction;\\n\\t\\t\\t\\tthis.requiresCubemaps = false;\\n\\t\\t}\\n}\\n\\nconst _noLights = [\\n\\t\\t[],\\n\\t\\t[],\\n\\t\\t[]\\n];\\nconst tmpColor$1 = new Color();\\nconst _drawCallList = {\\n\\t\\tdrawCalls: [],\\n\\t\\tshaderInstances: [],\\n\\t\\tisNewMaterial: [],\\n\\t\\tlightMaskChanged: [],\\n\\t\\tclear: function() {\\n\\t\\t\\t\\tthis.drawCalls.length = 0;\\n\\t\\t\\t\\tthis.shaderInstances.length = 0;\\n\\t\\t\\t\\tthis.isNewMaterial.length = 0;\\n\\t\\t\\t\\tthis.lightMaskChanged.length = 0;\\n\\t\\t}\\n};\\nfunction vogelDiskPrecalculationSamples(numSamples) {\\n\\t\\tconst samples = [];\\n\\t\\tfor(let i = 0; i < numSamples; ++i){\\n\\t\\t\\t\\tconst r = Math.sqrt(i + 0.5) / Math.sqrt(numSamples);\\n\\t\\t\\t\\tsamples.push(r);\\n\\t\\t}\\n\\t\\treturn samples;\\n}\\nfunction vogelSpherePrecalculationSamples(numSamples) {\\n\\t\\tconst samples = [];\\n\\t\\tfor(let i = 0; i < numSamples; i++){\\n\\t\\t\\t\\tconst weight = i / numSamples;\\n\\t\\t\\t\\tconst radius = Math.sqrt(weight * weight);\\n\\t\\t\\t\\tsamples.push(radius);\\n\\t\\t}\\n\\t\\treturn samples;\\n}\\nclass ForwardRenderer extends Renderer {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tsuper.destroy();\\n\\t\\t}\\n\\t\\tdispatchGlobalLights(scene) {\\n\\t\\t\\t\\tconst ambientUniform = this.ambientColor;\\n\\t\\t\\t\\ttmpColor$1.linear(scene.ambientLight);\\n\\t\\t\\t\\tambientUniform[0] = tmpColor$1.r;\\n\\t\\t\\t\\tambientUniform[1] = tmpColor$1.g;\\n\\t\\t\\t\\tambientUniform[2] = tmpColor$1.b;\\n\\t\\t\\t\\tif (scene.physicalUnits) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < 3; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tambientUniform[i] *= scene.ambientLuminance;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.ambientId.setValue(ambientUniform);\\n\\t\\t\\t\\tthis.skyboxIntensityId.setValue(scene.physicalUnits ? scene.skyboxLuminance : scene.skyboxIntensity);\\n\\t\\t\\t\\tthis.cubeMapRotationMatrixId.setValue(scene._skyboxRotationMat3.data);\\n\\t\\t}\\n\\t\\t_resolveLight(scope, i) {\\n\\t\\t\\t\\tconst light = `light${i}`;\\n\\t\\t\\t\\tthis.lightColorId[i] = scope.resolve(`${light}_color`);\\n\\t\\t\\t\\tthis.lightDir[i] = new Float32Array(3);\\n\\t\\t\\t\\tthis.lightDirId[i] = scope.resolve(`${light}_direction`);\\n\\t\\t\\t\\tthis.lightShadowMapId[i] = scope.resolve(`${light}_shadowMap`);\\n\\t\\t\\t\\tthis.lightShadowMatrixId[i] = scope.resolve(`${light}_shadowMatrix`);\\n\\t\\t\\t\\tthis.lightShadowParamsId[i] = scope.resolve(`${light}_shadowParams`);\\n\\t\\t\\t\\tthis.lightShadowIntensity[i] = scope.resolve(`${light}_shadowIntensity`);\\n\\t\\t\\t\\tthis.lightShadowSearchAreaId[i] = scope.resolve(`${light}_shadowSearchArea`);\\n\\t\\t\\t\\tthis.lightRadiusId[i] = scope.resolve(`${light}_radius`);\\n\\t\\t\\t\\tthis.lightPos[i] = new Float32Array(3);\\n\\t\\t\\t\\tthis.lightPosId[i] = scope.resolve(`${light}_position`);\\n\\t\\t\\t\\tthis.lightWidth[i] = new Float32Array(3);\\n\\t\\t\\t\\tthis.lightWidthId[i] = scope.resolve(`${light}_halfWidth`);\\n\\t\\t\\t\\tthis.lightHeight[i] = new Float32Array(3);\\n\\t\\t\\t\\tthis.lightHeightId[i] = scope.resolve(`${light}_halfHeight`);\\n\\t\\t\\t\\tthis.lightInAngleId[i] = scope.resolve(`${light}_innerConeAngle`);\\n\\t\\t\\t\\tthis.lightOutAngleId[i] = scope.resolve(`${light}_outerConeAngle`);\\n\\t\\t\\t\\tthis.lightCookieId[i] = scope.resolve(`${light}_cookie`);\\n\\t\\t\\t\\tthis.lightCookieIntId[i] = scope.resolve(`${light}_cookieIntensity`);\\n\\t\\t\\t\\tthis.lightCookieMatrixId[i] = scope.resolve(`${light}_cookieMatrix`);\\n\\t\\t\\t\\tthis.lightCookieOffsetId[i] = scope.resolve(`${light}_cookieOffset`);\\n\\t\\t\\t\\tthis.lightCameraParamsId[i] = scope.resolve(`${light}_cameraParams`);\\n\\t\\t\\t\\tthis.lightSoftShadowParamsId[i] = scope.resolve(`${light}_softShadowParams`);\\n\\t\\t\\t\\tthis.shadowMatrixPaletteId[i] = scope.resolve(`${light}_shadowMatrixPalette[0]`);\\n\\t\\t\\t\\tthis.shadowCascadeDistancesId[i] = scope.resolve(`${light}_shadowCascadeDistances`);\\n\\t\\t\\t\\tthis.shadowCascadeCountId[i] = scope.resolve(`${light}_shadowCascadeCount`);\\n\\t\\t\\t\\tthis.shadowCascadeBlendId[i] = scope.resolve(`${light}_shadowCascadeBlend`);\\n\\t\\t}\\n\\t\\tsetLTCDirectionalLight(wtm, cnt, dir, campos, far) {\\n\\t\\t\\t\\tthis.lightPos[cnt][0] = campos.x - dir.x * far;\\n\\t\\t\\t\\tthis.lightPos[cnt][1] = campos.y - dir.y * far;\\n\\t\\t\\t\\tthis.lightPos[cnt][2] = campos.z - dir.z * far;\\n\\t\\t\\t\\tthis.lightPosId[cnt].setValue(this.lightPos[cnt]);\\n\\t\\t\\t\\tconst hWidth = wtm.transformVector(new Vec3(-0.5, 0, 0));\\n\\t\\t\\t\\tthis.lightWidth[cnt][0] = hWidth.x * far;\\n\\t\\t\\t\\tthis.lightWidth[cnt][1] = hWidth.y * far;\\n\\t\\t\\t\\tthis.lightWidth[cnt][2] = hWidth.z * far;\\n\\t\\t\\t\\tthis.lightWidthId[cnt].setValue(this.lightWidth[cnt]);\\n\\t\\t\\t\\tconst hHeight = wtm.transformVector(new Vec3(0, 0, 0.5));\\n\\t\\t\\t\\tthis.lightHeight[cnt][0] = hHeight.x * far;\\n\\t\\t\\t\\tthis.lightHeight[cnt][1] = hHeight.y * far;\\n\\t\\t\\t\\tthis.lightHeight[cnt][2] = hHeight.z * far;\\n\\t\\t\\t\\tthis.lightHeightId[cnt].setValue(this.lightHeight[cnt]);\\n\\t\\t}\\n\\t\\tdispatchDirectLights(dirs, mask, camera) {\\n\\t\\t\\t\\tlet cnt = 0;\\n\\t\\t\\t\\tconst scope = this.device.scope;\\n\\t\\t\\t\\tfor(let i = 0; i < dirs.length; i++){\\n\\t\\t\\t\\t\\t\\tif (!(dirs[i].mask & mask)) continue;\\n\\t\\t\\t\\t\\t\\tconst directional = dirs[i];\\n\\t\\t\\t\\t\\t\\tconst wtm = directional._node.getWorldTransform();\\n\\t\\t\\t\\t\\t\\tif (!this.lightColorId[cnt]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._resolveLight(scope, cnt);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.lightColorId[cnt].setValue(directional._colorLinear);\\n\\t\\t\\t\\t\\t\\twtm.getY(directional._direction).mulScalar(-1);\\n\\t\\t\\t\\t\\t\\tdirectional._direction.normalize();\\n\\t\\t\\t\\t\\t\\tthis.lightDir[cnt][0] = directional._direction.x;\\n\\t\\t\\t\\t\\t\\tthis.lightDir[cnt][1] = directional._direction.y;\\n\\t\\t\\t\\t\\t\\tthis.lightDir[cnt][2] = directional._direction.z;\\n\\t\\t\\t\\t\\t\\tthis.lightDirId[cnt].setValue(this.lightDir[cnt]);\\n\\t\\t\\t\\t\\t\\tif (directional.shape !== LIGHTSHAPE_PUNCTUAL) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setLTCDirectionalLight(wtm, cnt, directional._direction, camera._node.getPosition(), camera.farClip);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (directional.castShadows) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst lightRenderData = directional.getRenderData(camera, 0);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst biases = directional._getUniformBiasValues(lightRenderData);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.lightShadowMapId[cnt].setValue(lightRenderData.shadowBuffer);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.lightShadowMatrixId[cnt].setValue(lightRenderData.shadowMatrix.data);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.shadowMatrixPaletteId[cnt].setValue(directional._shadowMatrixPalette);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.shadowCascadeDistancesId[cnt].setValue(directional._shadowCascadeDistances);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.shadowCascadeCountId[cnt].setValue(directional.numCascades);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.shadowCascadeBlendId[cnt].setValue(1 - directional.cascadeBlend);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.lightShadowIntensity[cnt].setValue(directional.shadowIntensity);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.lightSoftShadowParamsId[cnt].setValue(directional._softShadowParams);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst shadowRT = lightRenderData.shadowCamera.renderTarget;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (shadowRT) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.lightShadowSearchAreaId[cnt].setValue(directional.penumbraSize / lightRenderData.shadowCamera.renderTarget.width * lightRenderData.projectionCompensation);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst cameraParams = directional._shadowCameraParams;\\n\\t\\t\\t\\t\\t\\t\\t\\tcameraParams.length = 4;\\n\\t\\t\\t\\t\\t\\t\\t\\tcameraParams[0] = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tcameraParams[1] = lightRenderData.shadowCamera._farClip;\\n\\t\\t\\t\\t\\t\\t\\t\\tcameraParams[2] = lightRenderData.shadowCamera._nearClip;\\n\\t\\t\\t\\t\\t\\t\\t\\tcameraParams[3] = 1;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.lightCameraParamsId[cnt].setValue(cameraParams);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst params = directional._shadowRenderParams;\\n\\t\\t\\t\\t\\t\\t\\t\\tparams.length = 4;\\n\\t\\t\\t\\t\\t\\t\\t\\tparams[0] = directional._shadowResolution;\\n\\t\\t\\t\\t\\t\\t\\t\\tparams[1] = biases.normalBias;\\n\\t\\t\\t\\t\\t\\t\\t\\tparams[2] = biases.bias;\\n\\t\\t\\t\\t\\t\\t\\t\\tparams[3] = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.lightShadowParamsId[cnt].setValue(params);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcnt++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn cnt;\\n\\t\\t}\\n\\t\\tsetLTCPositionalLight(wtm, cnt) {\\n\\t\\t\\t\\tconst hWidth = wtm.transformVector(new Vec3(-0.5, 0, 0));\\n\\t\\t\\t\\tthis.lightWidth[cnt][0] = hWidth.x;\\n\\t\\t\\t\\tthis.lightWidth[cnt][1] = hWidth.y;\\n\\t\\t\\t\\tthis.lightWidth[cnt][2] = hWidth.z;\\n\\t\\t\\t\\tthis.lightWidthId[cnt].setValue(this.lightWidth[cnt]);\\n\\t\\t\\t\\tconst hHeight = wtm.transformVector(new Vec3(0, 0, 0.5));\\n\\t\\t\\t\\tthis.lightHeight[cnt][0] = hHeight.x;\\n\\t\\t\\t\\tthis.lightHeight[cnt][1] = hHeight.y;\\n\\t\\t\\t\\tthis.lightHeight[cnt][2] = hHeight.z;\\n\\t\\t\\t\\tthis.lightHeightId[cnt].setValue(this.lightHeight[cnt]);\\n\\t\\t}\\n\\t\\tdispatchOmniLight(scope, omni, cnt) {\\n\\t\\t\\t\\tconst wtm = omni._node.getWorldTransform();\\n\\t\\t\\t\\tif (!this.lightColorId[cnt]) {\\n\\t\\t\\t\\t\\t\\tthis._resolveLight(scope, cnt);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.lightRadiusId[cnt].setValue(omni.attenuationEnd);\\n\\t\\t\\t\\tthis.lightColorId[cnt].setValue(omni._colorLinear);\\n\\t\\t\\t\\twtm.getTranslation(omni._position);\\n\\t\\t\\t\\tthis.lightPos[cnt][0] = omni._position.x;\\n\\t\\t\\t\\tthis.lightPos[cnt][1] = omni._position.y;\\n\\t\\t\\t\\tthis.lightPos[cnt][2] = omni._position.z;\\n\\t\\t\\t\\tthis.lightPosId[cnt].setValue(this.lightPos[cnt]);\\n\\t\\t\\t\\tif (omni.shape !== LIGHTSHAPE_PUNCTUAL) {\\n\\t\\t\\t\\t\\t\\tthis.setLTCPositionalLight(wtm, cnt);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (omni.castShadows) {\\n\\t\\t\\t\\t\\t\\tconst lightRenderData = omni.getRenderData(null, 0);\\n\\t\\t\\t\\t\\t\\tthis.lightShadowMapId[cnt].setValue(lightRenderData.shadowBuffer);\\n\\t\\t\\t\\t\\t\\tconst biases = omni._getUniformBiasValues(lightRenderData);\\n\\t\\t\\t\\t\\t\\tconst params = omni._shadowRenderParams;\\n\\t\\t\\t\\t\\t\\tparams.length = 4;\\n\\t\\t\\t\\t\\t\\tparams[0] = omni._shadowResolution;\\n\\t\\t\\t\\t\\t\\tparams[1] = biases.normalBias;\\n\\t\\t\\t\\t\\t\\tparams[2] = biases.bias;\\n\\t\\t\\t\\t\\t\\tparams[3] = 1.0 / omni.attenuationEnd;\\n\\t\\t\\t\\t\\t\\tthis.lightShadowParamsId[cnt].setValue(params);\\n\\t\\t\\t\\t\\t\\tthis.lightShadowIntensity[cnt].setValue(omni.shadowIntensity);\\n\\t\\t\\t\\t\\t\\tconst pixelsPerMeter = omni.penumbraSize / lightRenderData.shadowCamera.renderTarget.width;\\n\\t\\t\\t\\t\\t\\tthis.lightShadowSearchAreaId[cnt].setValue(pixelsPerMeter);\\n\\t\\t\\t\\t\\t\\tconst cameraParams = omni._shadowCameraParams;\\n\\t\\t\\t\\t\\t\\tcameraParams.length = 4;\\n\\t\\t\\t\\t\\t\\tcameraParams[0] = 0;\\n\\t\\t\\t\\t\\t\\tcameraParams[1] = lightRenderData.shadowCamera._farClip;\\n\\t\\t\\t\\t\\t\\tcameraParams[2] = lightRenderData.shadowCamera._nearClip;\\n\\t\\t\\t\\t\\t\\tcameraParams[3] = 0;\\n\\t\\t\\t\\t\\t\\tthis.lightCameraParamsId[cnt].setValue(cameraParams);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (omni._cookie) {\\n\\t\\t\\t\\t\\t\\tthis.lightCookieId[cnt].setValue(omni._cookie);\\n\\t\\t\\t\\t\\t\\tthis.lightShadowMatrixId[cnt].setValue(wtm.data);\\n\\t\\t\\t\\t\\t\\tthis.lightCookieIntId[cnt].setValue(omni.cookieIntensity);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdispatchSpotLight(scope, spot, cnt) {\\n\\t\\t\\t\\tconst wtm = spot._node.getWorldTransform();\\n\\t\\t\\t\\tif (!this.lightColorId[cnt]) {\\n\\t\\t\\t\\t\\t\\tthis._resolveLight(scope, cnt);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.lightInAngleId[cnt].setValue(spot._innerConeAngleCos);\\n\\t\\t\\t\\tthis.lightOutAngleId[cnt].setValue(spot._outerConeAngleCos);\\n\\t\\t\\t\\tthis.lightRadiusId[cnt].setValue(spot.attenuationEnd);\\n\\t\\t\\t\\tthis.lightColorId[cnt].setValue(spot._colorLinear);\\n\\t\\t\\t\\twtm.getTranslation(spot._position);\\n\\t\\t\\t\\tthis.lightPos[cnt][0] = spot._position.x;\\n\\t\\t\\t\\tthis.lightPos[cnt][1] = spot._position.y;\\n\\t\\t\\t\\tthis.lightPos[cnt][2] = spot._position.z;\\n\\t\\t\\t\\tthis.lightPosId[cnt].setValue(this.lightPos[cnt]);\\n\\t\\t\\t\\tif (spot.shape !== LIGHTSHAPE_PUNCTUAL) {\\n\\t\\t\\t\\t\\t\\tthis.setLTCPositionalLight(wtm, cnt);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\twtm.getY(spot._direction).mulScalar(-1);\\n\\t\\t\\t\\tspot._direction.normalize();\\n\\t\\t\\t\\tthis.lightDir[cnt][0] = spot._direction.x;\\n\\t\\t\\t\\tthis.lightDir[cnt][1] = spot._direction.y;\\n\\t\\t\\t\\tthis.lightDir[cnt][2] = spot._direction.z;\\n\\t\\t\\t\\tthis.lightDirId[cnt].setValue(this.lightDir[cnt]);\\n\\t\\t\\t\\tif (spot.castShadows) {\\n\\t\\t\\t\\t\\t\\tconst lightRenderData = spot.getRenderData(null, 0);\\n\\t\\t\\t\\t\\t\\tthis.lightShadowMapId[cnt].setValue(lightRenderData.shadowBuffer);\\n\\t\\t\\t\\t\\t\\tthis.lightShadowMatrixId[cnt].setValue(lightRenderData.shadowMatrix.data);\\n\\t\\t\\t\\t\\t\\tconst biases = spot._getUniformBiasValues(lightRenderData);\\n\\t\\t\\t\\t\\t\\tconst params = spot._shadowRenderParams;\\n\\t\\t\\t\\t\\t\\tparams.length = 4;\\n\\t\\t\\t\\t\\t\\tparams[0] = spot._shadowResolution;\\n\\t\\t\\t\\t\\t\\tparams[1] = biases.normalBias;\\n\\t\\t\\t\\t\\t\\tparams[2] = biases.bias;\\n\\t\\t\\t\\t\\t\\tparams[3] = 1.0 / spot.attenuationEnd;\\n\\t\\t\\t\\t\\t\\tthis.lightShadowParamsId[cnt].setValue(params);\\n\\t\\t\\t\\t\\t\\tthis.lightShadowIntensity[cnt].setValue(spot.shadowIntensity);\\n\\t\\t\\t\\t\\t\\tconst pixelsPerMeter = spot.penumbraSize / lightRenderData.shadowCamera.renderTarget.width;\\n\\t\\t\\t\\t\\t\\tconst fov = lightRenderData.shadowCamera._fov * math.DEG_TO_RAD;\\n\\t\\t\\t\\t\\t\\tconst fovRatio = 1.0 / Math.tan(fov / 2.0);\\n\\t\\t\\t\\t\\t\\tthis.lightShadowSearchAreaId[cnt].setValue(pixelsPerMeter * fovRatio);\\n\\t\\t\\t\\t\\t\\tconst cameraParams = spot._shadowCameraParams;\\n\\t\\t\\t\\t\\t\\tcameraParams.length = 4;\\n\\t\\t\\t\\t\\t\\tcameraParams[0] = 0;\\n\\t\\t\\t\\t\\t\\tcameraParams[1] = lightRenderData.shadowCamera._farClip;\\n\\t\\t\\t\\t\\t\\tcameraParams[2] = lightRenderData.shadowCamera._nearClip;\\n\\t\\t\\t\\t\\t\\tcameraParams[3] = 0;\\n\\t\\t\\t\\t\\t\\tthis.lightCameraParamsId[cnt].setValue(cameraParams);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (spot._cookie) {\\n\\t\\t\\t\\t\\t\\tif (!spot.castShadows) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst cookieMatrix = LightCamera.evalSpotCookieMatrix(spot);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.lightShadowMatrixId[cnt].setValue(cookieMatrix.data);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.lightCookieId[cnt].setValue(spot._cookie);\\n\\t\\t\\t\\t\\t\\tthis.lightCookieIntId[cnt].setValue(spot.cookieIntensity);\\n\\t\\t\\t\\t\\t\\tif (spot._cookieTransform) {\\n\\t\\t\\t\\t\\t\\t\\t\\tspot._cookieTransformUniform[0] = spot._cookieTransform.x;\\n\\t\\t\\t\\t\\t\\t\\t\\tspot._cookieTransformUniform[1] = spot._cookieTransform.y;\\n\\t\\t\\t\\t\\t\\t\\t\\tspot._cookieTransformUniform[2] = spot._cookieTransform.z;\\n\\t\\t\\t\\t\\t\\t\\t\\tspot._cookieTransformUniform[3] = spot._cookieTransform.w;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.lightCookieMatrixId[cnt].setValue(spot._cookieTransformUniform);\\n\\t\\t\\t\\t\\t\\t\\t\\tspot._cookieOffsetUniform[0] = spot._cookieOffset.x;\\n\\t\\t\\t\\t\\t\\t\\t\\tspot._cookieOffsetUniform[1] = spot._cookieOffset.y;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.lightCookieOffsetId[cnt].setValue(spot._cookieOffsetUniform);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdispatchLocalLights(sortedLights, mask, usedDirLights) {\\n\\t\\t\\t\\tlet cnt = usedDirLights;\\n\\t\\t\\t\\tconst scope = this.device.scope;\\n\\t\\t\\t\\tconst omnis = sortedLights[LIGHTTYPE_OMNI];\\n\\t\\t\\t\\tconst numOmnis = omnis.length;\\n\\t\\t\\t\\tfor(let i = 0; i < numOmnis; i++){\\n\\t\\t\\t\\t\\t\\tconst omni = omnis[i];\\n\\t\\t\\t\\t\\t\\tif (!(omni.mask & mask)) continue;\\n\\t\\t\\t\\t\\t\\tthis.dispatchOmniLight(scope, omni, cnt);\\n\\t\\t\\t\\t\\t\\tcnt++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst spts = sortedLights[LIGHTTYPE_SPOT];\\n\\t\\t\\t\\tconst numSpts = spts.length;\\n\\t\\t\\t\\tfor(let i = 0; i < numSpts; i++){\\n\\t\\t\\t\\t\\t\\tconst spot = spts[i];\\n\\t\\t\\t\\t\\t\\tif (!(spot.mask & mask)) continue;\\n\\t\\t\\t\\t\\t\\tthis.dispatchSpotLight(scope, spot, cnt);\\n\\t\\t\\t\\t\\t\\tcnt++;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\trenderForwardPrepareMaterials(camera, renderTarget, drawCalls, sortedLights, layer, pass) {\\n\\t\\t\\t\\tconst fogParams = camera.fogParams ?? this.scene.fog;\\n\\t\\t\\t\\tconst shaderParams = camera.shaderParams;\\n\\t\\t\\t\\tshaderParams.fog = fogParams.type;\\n\\t\\t\\t\\tshaderParams.srgbRenderTarget = renderTarget?.isColorBufferSrgb(0) ?? false;\\n\\t\\t\\t\\tconst addCall = (drawCall, shaderInstance, isNewMaterial, lightMaskChanged)=>{\\n\\t\\t\\t\\t\\t\\t_drawCallList.drawCalls.push(drawCall);\\n\\t\\t\\t\\t\\t\\t_drawCallList.shaderInstances.push(shaderInstance);\\n\\t\\t\\t\\t\\t\\t_drawCallList.isNewMaterial.push(isNewMaterial);\\n\\t\\t\\t\\t\\t\\t_drawCallList.lightMaskChanged.push(lightMaskChanged);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\t_drawCallList.clear();\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tconst scene = this.scene;\\n\\t\\t\\t\\tconst clusteredLightingEnabled = scene.clusteredLightingEnabled;\\n\\t\\t\\t\\tconst lightHash = layer?.getLightHash(clusteredLightingEnabled) ?? 0;\\n\\t\\t\\t\\tlet prevMaterial = null, prevObjDefs, prevLightMask;\\n\\t\\t\\t\\tconst drawCallsCount = drawCalls.length;\\n\\t\\t\\t\\tfor(let i = 0; i < drawCallsCount; i++){\\n\\t\\t\\t\\t\\t\\tconst drawCall = drawCalls[i];\\n\\t\\t\\t\\t\\t\\tconst instancingData = drawCall.instancingData;\\n\\t\\t\\t\\t\\t\\tif (instancingData && instancingData.count <= 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tdrawCall.ensureMaterial(device);\\n\\t\\t\\t\\t\\t\\tconst material = drawCall.material;\\n\\t\\t\\t\\t\\t\\tconst objDefs = drawCall._shaderDefs;\\n\\t\\t\\t\\t\\t\\tconst lightMask = drawCall.mask;\\n\\t\\t\\t\\t\\t\\tif (material && material === prevMaterial && objDefs !== prevObjDefs) {\\n\\t\\t\\t\\t\\t\\t\\t\\tprevMaterial = null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (material !== prevMaterial) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._materialSwitches++;\\n\\t\\t\\t\\t\\t\\t\\t\\tmaterial._scene = scene;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (material.dirty) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmaterial.updateUniforms(device, scene);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmaterial.dirty = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst shaderInstance = drawCall.getShaderInstance(pass, lightHash, scene, shaderParams, this.viewUniformFormat, this.viewBindGroupFormat, sortedLights);\\n\\t\\t\\t\\t\\t\\taddCall(drawCall, shaderInstance, material !== prevMaterial, !prevMaterial || lightMask !== prevLightMask);\\n\\t\\t\\t\\t\\t\\tprevMaterial = material;\\n\\t\\t\\t\\t\\t\\tprevObjDefs = objDefs;\\n\\t\\t\\t\\t\\t\\tprevLightMask = lightMask;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn _drawCallList;\\n\\t\\t}\\n\\t\\trenderForwardInternal(camera, preparedCalls, sortedLights, pass, drawCallback, flipFaces, viewBindGroups) {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tconst scene = this.scene;\\n\\t\\t\\t\\tconst passFlag = 1 << pass;\\n\\t\\t\\t\\tconst flipFactor = flipFaces ? -1 : 1;\\n\\t\\t\\t\\tconst clusteredLightingEnabled = scene.clusteredLightingEnabled;\\n\\t\\t\\t\\tconst viewList = camera.xr?.session && camera.xr.views.list.length ? camera.xr.views.list : null;\\n\\t\\t\\t\\tconst preparedCallsCount = preparedCalls.drawCalls.length;\\n\\t\\t\\t\\tfor(let i = 0; i < preparedCallsCount; i++){\\n\\t\\t\\t\\t\\t\\tconst drawCall = preparedCalls.drawCalls[i];\\n\\t\\t\\t\\t\\t\\tconst newMaterial = preparedCalls.isNewMaterial[i];\\n\\t\\t\\t\\t\\t\\tconst lightMaskChanged = preparedCalls.lightMaskChanged[i];\\n\\t\\t\\t\\t\\t\\tconst shaderInstance = preparedCalls.shaderInstances[i];\\n\\t\\t\\t\\t\\t\\tconst material = drawCall.material;\\n\\t\\t\\t\\t\\t\\tconst lightMask = drawCall.mask;\\n\\t\\t\\t\\t\\t\\tif (shaderInstance.shader.failed) continue;\\n\\t\\t\\t\\t\\t\\tif (newMaterial) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst asyncCompile = false;\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.setShader(shaderInstance.shader, asyncCompile);\\n\\t\\t\\t\\t\\t\\t\\t\\tmaterial.setParameters(device);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (lightMaskChanged) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst usedDirLights = this.dispatchDirectLights(sortedLights[LIGHTTYPE_DIRECTIONAL], lightMask, camera);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.dispatchLocalLights(sortedLights, lightMask, usedDirLights);\\n\\t\\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\\tthis.alphaTestId.setValue(material.alphaTest);\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.setBlendState(material.blendState);\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.setDepthState(material.depthState);\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.setAlphaToCoverage(material.alphaToCoverage);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.setupCullMode(camera._cullFaces, flipFactor, drawCall);\\n\\t\\t\\t\\t\\t\\tconst stencilFront = drawCall.stencilFront ?? material.stencilFront;\\n\\t\\t\\t\\t\\t\\tconst stencilBack = drawCall.stencilBack ?? material.stencilBack;\\n\\t\\t\\t\\t\\t\\tdevice.setStencilState(stencilFront, stencilBack);\\n\\t\\t\\t\\t\\t\\tdrawCall.setParameters(device, passFlag);\\n\\t\\t\\t\\t\\t\\tdevice.scope.resolve('meshInstanceId').setValue(drawCall.id);\\n\\t\\t\\t\\t\\t\\tconst mesh = drawCall.mesh;\\n\\t\\t\\t\\t\\t\\tthis.setVertexBuffers(device, mesh);\\n\\t\\t\\t\\t\\t\\tthis.setMorphing(device, drawCall.morphInstance);\\n\\t\\t\\t\\t\\t\\tthis.setSkinning(device, drawCall);\\n\\t\\t\\t\\t\\t\\tconst instancingData = drawCall.instancingData;\\n\\t\\t\\t\\t\\t\\tif (instancingData) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.setVertexBuffer(instancingData.vertexBuffer);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.setMeshInstanceMatrices(drawCall, true);\\n\\t\\t\\t\\t\\t\\tthis.setupMeshUniformBuffers(shaderInstance);\\n\\t\\t\\t\\t\\t\\tconst style = drawCall.renderStyle;\\n\\t\\t\\t\\t\\t\\tconst indexBuffer = mesh.indexBuffer[style];\\n\\t\\t\\t\\t\\t\\tdrawCallback?.(drawCall, i);\\n\\t\\t\\t\\t\\t\\tconst indirectData = drawCall.getDrawCommands(camera);\\n\\t\\t\\t\\t\\t\\tif (viewList) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let v = 0; v < viewList.length; v++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst view = viewList[v];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setViewport(view.viewport.x, view.viewport.y, view.viewport.z, view.viewport.w);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (device.supportsUniformBuffers) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst viewBindGroup = viewBindGroups[v];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setBindGroup(BINDGROUP_VIEW, viewBindGroup);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.setupViewUniforms(view, v);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst first = v === 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst last = v === viewList.length - 1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.draw(mesh.primitive[style], indexBuffer, instancingData?.count, indirectData, first, last);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._forwardDrawCalls++;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (drawCall.instancingData) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._instancedDrawCalls++;\\n\\t\\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} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.draw(mesh.primitive[style], indexBuffer, instancingData?.count, indirectData);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._forwardDrawCalls++;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (drawCall.instancingData) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._instancedDrawCalls++;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (i < preparedCallsCount - 1 && !preparedCalls.isNewMaterial[i + 1]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmaterial.setParameters(device, drawCall.parameters);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\trenderForward(camera, renderTarget, allDrawCalls, sortedLights, pass, drawCallback, layer, flipFaces, viewBindGroups) {\\n\\t\\t\\t\\tconst preparedCalls = this.renderForwardPrepareMaterials(camera, renderTarget, allDrawCalls, sortedLights, layer, pass);\\n\\t\\t\\t\\tthis.renderForwardInternal(camera, preparedCalls, sortedLights, pass, drawCallback, flipFaces, viewBindGroups);\\n\\t\\t\\t\\t_drawCallList.clear();\\n\\t\\t}\\n\\t\\trenderForwardLayer(camera, renderTarget, layer, transparent, shaderPass, viewBindGroups, options = {}) {\\n\\t\\t\\t\\tconst { scene, device } = this;\\n\\t\\t\\t\\tconst clusteredLightingEnabled = scene.clusteredLightingEnabled;\\n\\t\\t\\t\\tthis.setupViewport(camera, renderTarget);\\n\\t\\t\\t\\tlet visible, splitLights;\\n\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\tlayer.sortVisible(camera, transparent);\\n\\t\\t\\t\\t\\t\\tconst culledInstances = layer.getCulledInstances(camera);\\n\\t\\t\\t\\t\\t\\tvisible = transparent ? culledInstances.transparent : culledInstances.opaque;\\n\\t\\t\\t\\t\\t\\tscene.immediate.onPreRenderLayer(layer, visible, transparent);\\n\\t\\t\\t\\t\\t\\tif (layer.requiresLightCube) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.lightCube.update(scene.ambientLight, layer._lights);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.constantLightCube.setValue(this.lightCube.colors);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tsplitLights = layer.splitLights;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tvisible = options.meshInstances;\\n\\t\\t\\t\\t\\t\\tsplitLights = options.splitLights ?? _noLights;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\t\\tconst lightClusters = options.lightClusters ?? this.worldClustersAllocator.empty;\\n\\t\\t\\t\\t\\t\\tlightClusters.activate();\\n\\t\\t\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this.clustersDebugRendered && scene.lighting.debugLayer === layer.id) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.clustersDebugRendered = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tscene._activeCamera = camera;\\n\\t\\t\\t\\tconst fogParams = camera.fogParams ?? this.scene.fog;\\n\\t\\t\\t\\tthis.setFogConstants(fogParams);\\n\\t\\t\\t\\tconst viewList = this.setCameraUniforms(camera, renderTarget);\\n\\t\\t\\t\\tif (device.supportsUniformBuffers) {\\n\\t\\t\\t\\t\\t\\tthis.setupViewUniformBuffers(viewBindGroups, this.viewUniformFormat, this.viewBindGroupFormat, viewList);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst clearColor = options.clearColor ?? false;\\n\\t\\t\\t\\tconst clearDepth = options.clearDepth ?? false;\\n\\t\\t\\t\\tconst clearStencil = options.clearStencil ?? false;\\n\\t\\t\\t\\tif (clearColor || clearDepth || clearStencil) {\\n\\t\\t\\t\\t\\t\\tthis.clear(camera, clearColor, clearDepth, clearStencil);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst flipFaces = !!(camera._flipFaces ^ renderTarget?.flipY);\\n\\t\\t\\t\\tconst forwardDrawCalls = this._forwardDrawCalls;\\n\\t\\t\\t\\tthis.renderForward(camera, renderTarget, visible, splitLights, shaderPass, null, layer, flipFaces, viewBindGroups);\\n\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\tlayer._forwardDrawCalls += this._forwardDrawCalls - forwardDrawCalls;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetFogConstants(fogParams) {\\n\\t\\t\\t\\tif (fogParams.type !== FOG_NONE) {\\n\\t\\t\\t\\t\\t\\ttmpColor$1.linear(fogParams.color);\\n\\t\\t\\t\\t\\t\\tconst fogUniform = this.fogColor;\\n\\t\\t\\t\\t\\t\\tfogUniform[0] = tmpColor$1.r;\\n\\t\\t\\t\\t\\t\\tfogUniform[1] = tmpColor$1.g;\\n\\t\\t\\t\\t\\t\\tfogUniform[2] = tmpColor$1.b;\\n\\t\\t\\t\\t\\t\\tthis.fogColorId.setValue(fogUniform);\\n\\t\\t\\t\\t\\t\\tif (fogParams.type === FOG_LINEAR) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fogStartId.setValue(fogParams.start);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fogEndId.setValue(fogParams.end);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fogDensityId.setValue(fogParams.density);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetSceneConstants() {\\n\\t\\t\\t\\tconst scene = this.scene;\\n\\t\\t\\t\\tthis.dispatchGlobalLights(scene);\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tthis._screenSize[0] = device.width;\\n\\t\\t\\t\\tthis._screenSize[1] = device.height;\\n\\t\\t\\t\\tthis._screenSize[2] = 1 / device.width;\\n\\t\\t\\t\\tthis._screenSize[3] = 1 / device.height;\\n\\t\\t\\t\\tthis.screenSizeId.setValue(this._screenSize);\\n\\t\\t\\t\\tthis.pcssDiskSamplesId.setValue(this.pcssDiskSamples);\\n\\t\\t\\t\\tthis.pcssSphereSamplesId.setValue(this.pcssSphereSamples);\\n\\t\\t}\\n\\t\\tbuildFrameGraph(frameGraph, layerComposition) {\\n\\t\\t\\t\\tconst scene = this.scene;\\n\\t\\t\\t\\tframeGraph.reset();\\n\\t\\t\\t\\tif (scene.clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\t\\tconst { shadowsEnabled, cookiesEnabled } = scene.lighting;\\n\\t\\t\\t\\t\\t\\tthis._renderPassUpdateClustered.update(frameGraph, shadowsEnabled, cookiesEnabled, this.lights, this.localLights);\\n\\t\\t\\t\\t\\t\\tframeGraph.addRenderPass(this._renderPassUpdateClustered);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._shadowRendererLocal.buildNonClusteredRenderPasses(frameGraph, this.localLights);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet startIndex = 0;\\n\\t\\t\\t\\tlet newStart = true;\\n\\t\\t\\t\\tlet renderTarget = null;\\n\\t\\t\\t\\tconst renderActions = layerComposition._renderActions;\\n\\t\\t\\t\\tfor(let i = startIndex; i < renderActions.length; i++){\\n\\t\\t\\t\\t\\t\\tconst renderAction = renderActions[i];\\n\\t\\t\\t\\t\\t\\tconst { layer, camera } = renderAction;\\n\\t\\t\\t\\t\\t\\tif (renderAction.useCameraPasses) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcamera.camera.renderPasses.forEach((renderPass)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tframeGraph.addRenderPass(renderPass);\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst isDepthLayer = layer.id === LAYERID_DEPTH;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst isGrabPass = isDepthLayer && (camera.renderSceneColorMap || camera.renderSceneDepthMap);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (newStart) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnewStart = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstartIndex = i;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trenderTarget = renderAction.renderTarget;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst nextRenderAction = renderActions[i + 1];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst isNextLayerDepth = nextRenderAction ? !nextRenderAction.useCameraPasses && nextRenderAction.layer.id === LAYERID_DEPTH : false;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst isNextLayerGrabPass = isNextLayerDepth && (camera.renderSceneColorMap || camera.renderSceneDepthMap);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst nextNeedDirShadows = nextRenderAction ? nextRenderAction.firstCameraUse && this.cameraDirShadowLights.has(nextRenderAction.camera.camera) : false;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!nextRenderAction || nextRenderAction.renderTarget !== renderTarget || nextNeedDirShadows || isNextLayerGrabPass || isGrabPass) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst isDepthOnly = isDepthLayer && startIndex === i;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!isDepthOnly) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.addMainRenderPass(frameGraph, layerComposition, renderTarget, startIndex, i);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (isDepthLayer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (camera.renderSceneColorMap) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst colorGrabPass = camera.camera.renderPassColorGrab;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcolorGrabPass.source = camera.renderTarget;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tframeGraph.addRenderPass(colorGrabPass);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (camera.renderSceneDepthMap) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tframeGraph.addRenderPass(camera.camera.renderPassDepthGrab);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (renderAction.triggerPostprocess && camera?.onPostprocessing) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst renderPass = new RenderPassPostprocessing(this.device, this, renderAction);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tframeGraph.addRenderPass(renderPass);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnewStart = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\taddMainRenderPass(frameGraph, layerComposition, renderTarget, startIndex, endIndex) {\\n\\t\\t\\t\\tconst renderPass = new RenderPassForward(this.device, layerComposition, this.scene, this);\\n\\t\\t\\t\\trenderPass.init(renderTarget);\\n\\t\\t\\t\\tconst renderActions = layerComposition._renderActions;\\n\\t\\t\\t\\tfor(let i = startIndex; i <= endIndex; i++){\\n\\t\\t\\t\\t\\t\\trenderPass.addRenderAction(renderActions[i]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tframeGraph.addRenderPass(renderPass);\\n\\t\\t}\\n\\t\\tupdate(comp) {\\n\\t\\t\\t\\tthis.frameUpdate();\\n\\t\\t\\t\\tthis.shadowRenderer.frameUpdate();\\n\\t\\t\\t\\tthis.scene._updateSkyMesh();\\n\\t\\t\\t\\tthis.updateLayerComposition(comp);\\n\\t\\t\\t\\tthis.collectLights(comp);\\n\\t\\t\\t\\tthis.beginFrame(comp);\\n\\t\\t\\t\\tthis.setSceneConstants();\\n\\t\\t\\t\\tthis.gsplatDirector?.update(comp);\\n\\t\\t\\t\\tthis.cullComposition(comp);\\n\\t\\t\\t\\tthis.gpuUpdate(this.processingMeshInstances);\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice, scene){\\n\\t\\t\\t\\tsuper(graphicsDevice, scene);\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tthis._forwardDrawCalls = 0;\\n\\t\\t\\t\\tthis._materialSwitches = 0;\\n\\t\\t\\t\\tthis._depthMapTime = 0;\\n\\t\\t\\t\\tthis._forwardTime = 0;\\n\\t\\t\\t\\tthis._sortTime = 0;\\n\\t\\t\\t\\tconst scope = device.scope;\\n\\t\\t\\t\\tthis.fogColorId = scope.resolve('fog_color');\\n\\t\\t\\t\\tthis.fogStartId = scope.resolve('fog_start');\\n\\t\\t\\t\\tthis.fogEndId = scope.resolve('fog_end');\\n\\t\\t\\t\\tthis.fogDensityId = scope.resolve('fog_density');\\n\\t\\t\\t\\tthis.ambientId = scope.resolve('light_globalAmbient');\\n\\t\\t\\t\\tthis.skyboxIntensityId = scope.resolve('skyboxIntensity');\\n\\t\\t\\t\\tthis.cubeMapRotationMatrixId = scope.resolve('cubeMapRotationMatrix');\\n\\t\\t\\t\\tthis.pcssDiskSamplesId = scope.resolve('pcssDiskSamples[0]');\\n\\t\\t\\t\\tthis.pcssSphereSamplesId = scope.resolve('pcssSphereSamples[0]');\\n\\t\\t\\t\\tthis.lightColorId = [];\\n\\t\\t\\t\\tthis.lightDir = [];\\n\\t\\t\\t\\tthis.lightDirId = [];\\n\\t\\t\\t\\tthis.lightShadowMapId = [];\\n\\t\\t\\t\\tthis.lightShadowMatrixId = [];\\n\\t\\t\\t\\tthis.lightShadowParamsId = [];\\n\\t\\t\\t\\tthis.lightShadowIntensity = [];\\n\\t\\t\\t\\tthis.lightRadiusId = [];\\n\\t\\t\\t\\tthis.lightPos = [];\\n\\t\\t\\t\\tthis.lightPosId = [];\\n\\t\\t\\t\\tthis.lightWidth = [];\\n\\t\\t\\t\\tthis.lightWidthId = [];\\n\\t\\t\\t\\tthis.lightHeight = [];\\n\\t\\t\\t\\tthis.lightHeightId = [];\\n\\t\\t\\t\\tthis.lightInAngleId = [];\\n\\t\\t\\t\\tthis.lightOutAngleId = [];\\n\\t\\t\\t\\tthis.lightCookieId = [];\\n\\t\\t\\t\\tthis.lightCookieIntId = [];\\n\\t\\t\\t\\tthis.lightCookieMatrixId = [];\\n\\t\\t\\t\\tthis.lightCookieOffsetId = [];\\n\\t\\t\\t\\tthis.lightShadowSearchAreaId = [];\\n\\t\\t\\t\\tthis.lightCameraParamsId = [];\\n\\t\\t\\t\\tthis.lightSoftShadowParamsId = [];\\n\\t\\t\\t\\tthis.shadowMatrixPaletteId = [];\\n\\t\\t\\t\\tthis.shadowCascadeDistancesId = [];\\n\\t\\t\\t\\tthis.shadowCascadeCountId = [];\\n\\t\\t\\t\\tthis.shadowCascadeBlendId = [];\\n\\t\\t\\t\\tthis.screenSizeId = scope.resolve('uScreenSize');\\n\\t\\t\\t\\tthis._screenSize = new Float32Array(4);\\n\\t\\t\\t\\tthis.fogColor = new Float32Array(3);\\n\\t\\t\\t\\tthis.ambientColor = new Float32Array(3);\\n\\t\\t\\t\\tthis.pcssDiskSamples = vogelDiskPrecalculationSamples(16);\\n\\t\\t\\t\\tthis.pcssSphereSamples = vogelSpherePrecalculationSamples(16);\\n\\t\\t}\\n}\\n\\nlet layerCounter = 0;\\nconst lightKeys = [];\\nconst _tempMaterials = new Set();\\nfunction sortManual(drawCallA, drawCallB) {\\n\\t\\treturn drawCallA.drawOrder - drawCallB.drawOrder;\\n}\\nfunction sortMaterialMesh(drawCallA, drawCallB) {\\n\\t\\tconst keyA = drawCallA._sortKeyForward;\\n\\t\\tconst keyB = drawCallB._sortKeyForward;\\n\\t\\tif (keyA === keyB) {\\n\\t\\t\\t\\treturn drawCallB.mesh.id - drawCallA.mesh.id;\\n\\t\\t}\\n\\t\\treturn keyB - keyA;\\n}\\nfunction sortBackToFront(drawCallA, drawCallB) {\\n\\t\\treturn drawCallB._sortKeyDynamic - drawCallA._sortKeyDynamic;\\n}\\nfunction sortFrontToBack(drawCallA, drawCallB) {\\n\\t\\treturn drawCallA._sortKeyDynamic - drawCallB._sortKeyDynamic;\\n}\\nconst sortCallbacks = [\\n\\t\\tnull,\\n\\t\\tsortManual,\\n\\t\\tsortMaterialMesh,\\n\\t\\tsortBackToFront,\\n\\t\\tsortFrontToBack\\n];\\nclass CulledInstances {\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.opaque = [];\\n\\t\\t\\t\\tthis.transparent = [];\\n\\t\\t}\\n}\\nclass Layer {\\n\\t\\tset enabled(val) {\\n\\t\\t\\t\\tif (val !== this._enabled) {\\n\\t\\t\\t\\t\\t\\tthis._dirtyComposition = true;\\n\\t\\t\\t\\t\\t\\tthis.gsplatPlacementsDirty = true;\\n\\t\\t\\t\\t\\t\\tthis._enabled = val;\\n\\t\\t\\t\\t\\t\\tif (val) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.incrementCounter();\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.onEnable) this.onEnable();\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.decrementCounter();\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.onDisable) this.onDisable();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget enabled() {\\n\\t\\t\\t\\treturn this._enabled;\\n\\t\\t}\\n\\t\\tset clearColorBuffer(val) {\\n\\t\\t\\t\\tthis._clearColorBuffer = val;\\n\\t\\t\\t\\tthis._dirtyComposition = true;\\n\\t\\t}\\n\\t\\tget clearColorBuffer() {\\n\\t\\t\\t\\treturn this._clearColorBuffer;\\n\\t\\t}\\n\\t\\tset clearDepthBuffer(val) {\\n\\t\\t\\t\\tthis._clearDepthBuffer = val;\\n\\t\\t\\t\\tthis._dirtyComposition = true;\\n\\t\\t}\\n\\t\\tget clearDepthBuffer() {\\n\\t\\t\\t\\treturn this._clearDepthBuffer;\\n\\t\\t}\\n\\t\\tset clearStencilBuffer(val) {\\n\\t\\t\\t\\tthis._clearStencilBuffer = val;\\n\\t\\t\\t\\tthis._dirtyComposition = true;\\n\\t\\t}\\n\\t\\tget clearStencilBuffer() {\\n\\t\\t\\t\\treturn this._clearStencilBuffer;\\n\\t\\t}\\n\\t\\tget hasClusteredLights() {\\n\\t\\t\\t\\treturn this._clusteredLightsSet.size > 0;\\n\\t\\t}\\n\\t\\tget clusteredLightsSet() {\\n\\t\\t\\t\\treturn this._clusteredLightsSet;\\n\\t\\t}\\n\\t\\tincrementCounter() {\\n\\t\\t\\t\\tif (this._refCounter === 0) {\\n\\t\\t\\t\\t\\t\\tthis._enabled = true;\\n\\t\\t\\t\\t\\t\\tif (this.onEnable) this.onEnable();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._refCounter++;\\n\\t\\t}\\n\\t\\tdecrementCounter() {\\n\\t\\t\\t\\tif (this._refCounter === 1) {\\n\\t\\t\\t\\t\\t\\tthis._enabled = false;\\n\\t\\t\\t\\t\\t\\tif (this.onDisable) this.onDisable();\\n\\t\\t\\t\\t} else if (this._refCounter === 0) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._refCounter--;\\n\\t\\t}\\n\\t\\taddGSplatPlacement(placement) {\\n\\t\\t\\t\\tif (!this.gsplatPlacementsSet.has(placement)) {\\n\\t\\t\\t\\t\\t\\tthis.gsplatPlacements.push(placement);\\n\\t\\t\\t\\t\\t\\tthis.gsplatPlacementsSet.add(placement);\\n\\t\\t\\t\\t\\t\\tthis.gsplatPlacementsDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tremoveGSplatPlacement(placement) {\\n\\t\\t\\t\\tconst index = this.gsplatPlacements.indexOf(placement);\\n\\t\\t\\t\\tif (index >= 0) {\\n\\t\\t\\t\\t\\t\\tthis.gsplatPlacements.splice(index, 1);\\n\\t\\t\\t\\t\\t\\tthis.gsplatPlacementsSet.delete(placement);\\n\\t\\t\\t\\t\\t\\tthis.gsplatPlacementsDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\taddGSplatShadowCaster(placement) {\\n\\t\\t\\t\\tif (!this.gsplatShadowCastersSet.has(placement)) {\\n\\t\\t\\t\\t\\t\\tthis.gsplatShadowCasters.push(placement);\\n\\t\\t\\t\\t\\t\\tthis.gsplatShadowCastersSet.add(placement);\\n\\t\\t\\t\\t\\t\\tthis.gsplatPlacementsDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tremoveGSplatShadowCaster(placement) {\\n\\t\\t\\t\\tconst index = this.gsplatShadowCasters.indexOf(placement);\\n\\t\\t\\t\\tif (index >= 0) {\\n\\t\\t\\t\\t\\t\\tthis.gsplatShadowCasters.splice(index, 1);\\n\\t\\t\\t\\t\\t\\tthis.gsplatShadowCastersSet.delete(placement);\\n\\t\\t\\t\\t\\t\\tthis.gsplatPlacementsDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\taddMeshInstances(meshInstances, skipShadowCasters) {\\n\\t\\t\\t\\tconst destMeshInstances = this.meshInstances;\\n\\t\\t\\t\\tconst destMeshInstancesSet = this.meshInstancesSet;\\n\\t\\t\\t\\tfor(let i = 0; i < meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\tconst mi = meshInstances[i];\\n\\t\\t\\t\\t\\t\\tif (!destMeshInstancesSet.has(mi)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdestMeshInstances.push(mi);\\n\\t\\t\\t\\t\\t\\t\\t\\tdestMeshInstancesSet.add(mi);\\n\\t\\t\\t\\t\\t\\t\\t\\t_tempMaterials.add(mi.material);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!skipShadowCasters) {\\n\\t\\t\\t\\t\\t\\tthis.addShadowCasters(meshInstances);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (_tempMaterials.size > 0) {\\n\\t\\t\\t\\t\\t\\tconst sceneShaderVer = this._shaderVersion;\\n\\t\\t\\t\\t\\t\\t_tempMaterials.forEach((mat)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (sceneShaderVer >= 0 && mat._shaderVersion !== sceneShaderVer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (mat.getShaderVariant !== Material.prototype.getShaderVariant) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmat.clearVariants();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmat._shaderVersion = sceneShaderVer;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t_tempMaterials.clear();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tremoveMeshInstances(meshInstances, skipShadowCasters) {\\n\\t\\t\\t\\tconst destMeshInstances = this.meshInstances;\\n\\t\\t\\t\\tconst destMeshInstancesSet = this.meshInstancesSet;\\n\\t\\t\\t\\tfor(let i = 0; i < meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\tconst mi = meshInstances[i];\\n\\t\\t\\t\\t\\t\\tif (destMeshInstancesSet.has(mi)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdestMeshInstancesSet.delete(mi);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst j = destMeshInstances.indexOf(mi);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (j >= 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdestMeshInstances.splice(j, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!skipShadowCasters) {\\n\\t\\t\\t\\t\\t\\tthis.removeShadowCasters(meshInstances);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\taddShadowCasters(meshInstances) {\\n\\t\\t\\t\\tconst shadowCasters = this.shadowCasters;\\n\\t\\t\\t\\tconst shadowCastersSet = this.shadowCastersSet;\\n\\t\\t\\t\\tfor(let i = 0; i < meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\tconst mi = meshInstances[i];\\n\\t\\t\\t\\t\\t\\tif (mi.castShadow && !shadowCastersSet.has(mi)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tshadowCastersSet.add(mi);\\n\\t\\t\\t\\t\\t\\t\\t\\tshadowCasters.push(mi);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tremoveShadowCasters(meshInstances) {\\n\\t\\t\\t\\tconst shadowCasters = this.shadowCasters;\\n\\t\\t\\t\\tconst shadowCastersSet = this.shadowCastersSet;\\n\\t\\t\\t\\tfor(let i = 0; i < meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\tconst mi = meshInstances[i];\\n\\t\\t\\t\\t\\t\\tif (shadowCastersSet.has(mi)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tshadowCastersSet.delete(mi);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst j = shadowCasters.indexOf(mi);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (j >= 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshadowCasters.splice(j, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tclearMeshInstances(skipShadowCasters = false) {\\n\\t\\t\\t\\tthis.meshInstances.length = 0;\\n\\t\\t\\t\\tthis.meshInstancesSet.clear();\\n\\t\\t\\t\\tif (!skipShadowCasters) {\\n\\t\\t\\t\\t\\t\\tthis.shadowCasters.length = 0;\\n\\t\\t\\t\\t\\t\\tthis.shadowCastersSet.clear();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tmarkLightsDirty() {\\n\\t\\t\\t\\tthis._lightHashDirty = true;\\n\\t\\t\\t\\tthis._lightIdHashDirty = true;\\n\\t\\t\\t\\tthis._splitLightsDirty = true;\\n\\t\\t}\\n\\t\\thasLight(light) {\\n\\t\\t\\t\\treturn this._lightsSet.has(light);\\n\\t\\t}\\n\\t\\taddLight(light) {\\n\\t\\t\\t\\tconst l = light.light;\\n\\t\\t\\t\\tif (!this._lightsSet.has(l)) {\\n\\t\\t\\t\\t\\t\\tthis._lightsSet.add(l);\\n\\t\\t\\t\\t\\t\\tthis._lights.push(l);\\n\\t\\t\\t\\t\\t\\tthis.markLightsDirty();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (l.type !== LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\t\\tthis._clusteredLightsSet.add(l);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tremoveLight(light) {\\n\\t\\t\\t\\tconst l = light.light;\\n\\t\\t\\t\\tif (this._lightsSet.has(l)) {\\n\\t\\t\\t\\t\\t\\tthis._lightsSet.delete(l);\\n\\t\\t\\t\\t\\t\\tthis._lights.splice(this._lights.indexOf(l), 1);\\n\\t\\t\\t\\t\\t\\tthis.markLightsDirty();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (l.type !== LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\t\\tthis._clusteredLightsSet.delete(l);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tclearLights() {\\n\\t\\t\\t\\tthis._lightsSet.forEach((light)=>light.removeLayer(this));\\n\\t\\t\\t\\tthis._lightsSet.clear();\\n\\t\\t\\t\\tthis._clusteredLightsSet.clear();\\n\\t\\t\\t\\tthis._lights.length = 0;\\n\\t\\t\\t\\tthis.markLightsDirty();\\n\\t\\t}\\n\\t\\tget splitLights() {\\n\\t\\t\\t\\tif (this._splitLightsDirty) {\\n\\t\\t\\t\\t\\t\\tthis._splitLightsDirty = false;\\n\\t\\t\\t\\t\\t\\tconst splitLights = this._splitLights;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < splitLights.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tsplitLights[i].length = 0;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst lights = this._lights;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < lights.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst light = lights[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (light.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsplitLights[light._type].push(light);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < splitLights.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tsplitLights[i].sort((a, b)=>a.key - b.key);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._splitLights;\\n\\t\\t}\\n\\t\\tevaluateLightHash(localLights, directionalLights, useIds) {\\n\\t\\t\\t\\tlet hash = 0;\\n\\t\\t\\t\\tconst lights = this._lights;\\n\\t\\t\\t\\tfor(let i = 0; i < lights.length; i++){\\n\\t\\t\\t\\t\\t\\tconst isLocalLight = lights[i].type !== LIGHTTYPE_DIRECTIONAL;\\n\\t\\t\\t\\t\\t\\tif (localLights && isLocalLight || directionalLights && !isLocalLight) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlightKeys.push(useIds ? lights[i].id : lights[i].key);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (lightKeys.length > 0) {\\n\\t\\t\\t\\t\\t\\tlightKeys.sort();\\n\\t\\t\\t\\t\\t\\thash = hash32Fnv1a(lightKeys);\\n\\t\\t\\t\\t\\t\\tlightKeys.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn hash;\\n\\t\\t}\\n\\t\\tgetLightHash(isClustered) {\\n\\t\\t\\t\\tif (this._lightHashDirty) {\\n\\t\\t\\t\\t\\t\\tthis._lightHashDirty = false;\\n\\t\\t\\t\\t\\t\\tthis._lightHash = this.evaluateLightHash(!isClustered, true, false);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._lightHash;\\n\\t\\t}\\n\\t\\tgetLightIdHash() {\\n\\t\\t\\t\\tif (this._lightIdHashDirty) {\\n\\t\\t\\t\\t\\t\\tthis._lightIdHashDirty = false;\\n\\t\\t\\t\\t\\t\\tthis._lightIdHash = this.evaluateLightHash(true, false, true);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._lightIdHash;\\n\\t\\t}\\n\\t\\taddCamera(camera) {\\n\\t\\t\\t\\tif (!this.camerasSet.has(camera.camera)) {\\n\\t\\t\\t\\t\\t\\tthis.camerasSet.add(camera.camera);\\n\\t\\t\\t\\t\\t\\tthis.cameras.push(camera);\\n\\t\\t\\t\\t\\t\\tthis._dirtyComposition = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tremoveCamera(camera) {\\n\\t\\t\\t\\tif (this.camerasSet.has(camera.camera)) {\\n\\t\\t\\t\\t\\t\\tthis.camerasSet.delete(camera.camera);\\n\\t\\t\\t\\t\\t\\tconst index = this.cameras.indexOf(camera);\\n\\t\\t\\t\\t\\t\\tthis.cameras.splice(index, 1);\\n\\t\\t\\t\\t\\t\\tthis._dirtyComposition = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tclearCameras() {\\n\\t\\t\\t\\tthis.cameras.length = 0;\\n\\t\\t\\t\\tthis.camerasSet.clear();\\n\\t\\t\\t\\tthis._dirtyComposition = true;\\n\\t\\t}\\n\\t\\t_calculateSortDistances(drawCalls, camPos, camFwd) {\\n\\t\\t\\t\\tconst count = drawCalls.length;\\n\\t\\t\\t\\tconst { x: px, y: py, z: pz } = camPos;\\n\\t\\t\\t\\tconst { x: fx, y: fy, z: fz } = camFwd;\\n\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\tconst drawCall = drawCalls[i];\\n\\t\\t\\t\\t\\t\\tlet zDist;\\n\\t\\t\\t\\t\\t\\tif (drawCall.calculateSortDistance) {\\n\\t\\t\\t\\t\\t\\t\\t\\tzDist = drawCall.calculateSortDistance(drawCall, camPos, camFwd);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst meshPos = drawCall.aabb.center;\\n\\t\\t\\t\\t\\t\\t\\t\\tzDist = (meshPos.x - px) * fx + (meshPos.y - py) * fy + (meshPos.z - pz) * fz;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst bucket = drawCall._drawBucket * 1e9;\\n\\t\\t\\t\\t\\t\\tdrawCall._sortKeyDynamic = bucket + zDist;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetCulledInstances(camera) {\\n\\t\\t\\t\\tlet instances = this._visibleInstances.get(camera);\\n\\t\\t\\t\\tif (!instances) {\\n\\t\\t\\t\\t\\t\\tinstances = new CulledInstances();\\n\\t\\t\\t\\t\\t\\tthis._visibleInstances.set(camera, instances);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn instances;\\n\\t\\t}\\n\\t\\tsortVisible(camera, transparent) {\\n\\t\\t\\t\\tconst sortMode = transparent ? this.transparentSortMode : this.opaqueSortMode;\\n\\t\\t\\t\\tif (sortMode === SORTMODE_NONE) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst culledInstances = this.getCulledInstances(camera);\\n\\t\\t\\t\\tconst instances = transparent ? culledInstances.transparent : culledInstances.opaque;\\n\\t\\t\\t\\tconst cameraNode = camera.node;\\n\\t\\t\\t\\tif (sortMode === SORTMODE_CUSTOM) {\\n\\t\\t\\t\\t\\t\\tconst sortPos = cameraNode.getPosition();\\n\\t\\t\\t\\t\\t\\tconst sortDir = cameraNode.forward;\\n\\t\\t\\t\\t\\t\\tif (this.customCalculateSortValues) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.customCalculateSortValues(instances, instances.length, sortPos, sortDir);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.customSortCallback) {\\n\\t\\t\\t\\t\\t\\t\\t\\tinstances.sort(this.customSortCallback);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (sortMode === SORTMODE_BACK2FRONT || sortMode === SORTMODE_FRONT2BACK) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst sortPos = cameraNode.getPosition();\\n\\t\\t\\t\\t\\t\\t\\t\\tconst sortDir = cameraNode.forward;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._calculateSortDistances(instances, sortPos, sortDir);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tinstances.sort(sortCallbacks[sortMode]);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(options = {}){\\n\\t\\t\\t\\tthis.meshInstances = [];\\n\\t\\t\\t\\tthis.meshInstancesSet = new Set();\\n\\t\\t\\t\\tthis.shadowCasters = [];\\n\\t\\t\\t\\tthis.shadowCastersSet = new Set();\\n\\t\\t\\t\\tthis._visibleInstances = new WeakMap();\\n\\t\\t\\t\\tthis._lights = [];\\n\\t\\t\\t\\tthis._lightsSet = new Set();\\n\\t\\t\\t\\tthis._clusteredLightsSet = new Set();\\n\\t\\t\\t\\tthis._splitLights = [\\n\\t\\t\\t\\t\\t\\t[],\\n\\t\\t\\t\\t\\t\\t[],\\n\\t\\t\\t\\t\\t\\t[]\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis._splitLightsDirty = true;\\n\\t\\t\\t\\tthis.requiresLightCube = false;\\n\\t\\t\\t\\tthis.cameras = [];\\n\\t\\t\\t\\tthis.camerasSet = new Set();\\n\\t\\t\\t\\tthis.gsplatPlacements = [];\\n\\t\\t\\t\\tthis.gsplatPlacementsSet = new Set();\\n\\t\\t\\t\\tthis.gsplatShadowCasters = [];\\n\\t\\t\\t\\tthis.gsplatShadowCastersSet = new Set();\\n\\t\\t\\t\\tthis.gsplatPlacementsDirty = true;\\n\\t\\t\\t\\tthis._dirtyComposition = false;\\n\\t\\t\\t\\tif (options.id !== undefined) {\\n\\t\\t\\t\\t\\t\\tthis.id = options.id;\\n\\t\\t\\t\\t\\t\\tlayerCounter = Math.max(this.id + 1, layerCounter);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.id = layerCounter++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.name = options.name;\\n\\t\\t\\t\\tthis._enabled = options.enabled ?? true;\\n\\t\\t\\t\\tthis._refCounter = this._enabled ? 1 : 0;\\n\\t\\t\\t\\tthis.opaqueSortMode = options.opaqueSortMode ?? SORTMODE_MATERIALMESH;\\n\\t\\t\\t\\tthis.transparentSortMode = options.transparentSortMode ?? SORTMODE_BACK2FRONT;\\n\\t\\t\\t\\tif (options.renderTarget) {\\n\\t\\t\\t\\t\\t\\tthis.renderTarget = options.renderTarget;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._clearColorBuffer = !!options.clearColorBuffer;\\n\\t\\t\\t\\tthis._clearDepthBuffer = !!options.clearDepthBuffer;\\n\\t\\t\\t\\tthis._clearStencilBuffer = !!options.clearStencilBuffer;\\n\\t\\t\\t\\tthis.onEnable = options.onEnable;\\n\\t\\t\\t\\tthis.onDisable = options.onDisable;\\n\\t\\t\\t\\tif (this._enabled && this.onEnable) {\\n\\t\\t\\t\\t\\t\\tthis.onEnable();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.customSortCallback = null;\\n\\t\\t\\t\\tthis.customCalculateSortValues = null;\\n\\t\\t\\t\\tthis._lightHash = 0;\\n\\t\\t\\t\\tthis._lightHashDirty = false;\\n\\t\\t\\t\\tthis._lightIdHash = 0;\\n\\t\\t\\t\\tthis._lightIdHashDirty = false;\\n\\t\\t\\t\\tthis._shaderVersion = -1;\\n\\t\\t}\\n}\\n\\nconst cmpPriority = (a, b)=>a.priority - b.priority;\\nconst sortPriority = (arr)=>arr.sort(cmpPriority);\\n\\nclass LayerComposition extends EventHandler {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.destroyRenderActions();\\n\\t\\t}\\n\\t\\tdestroyRenderActions() {\\n\\t\\t\\t\\tthis._renderActions.forEach((ra)=>ra.destroy());\\n\\t\\t\\t\\tthis._renderActions.length = 0;\\n\\t\\t}\\n\\t\\tmarkDirty() {\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t}\\n\\t\\t_update() {\\n\\t\\t\\t\\tconst len = this.layerList.length;\\n\\t\\t\\t\\tif (!this._dirty) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < len; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.layerList[i]._dirtyComposition) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._dirty = true;\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._dirty) {\\n\\t\\t\\t\\t\\t\\tthis._dirty = false;\\n\\t\\t\\t\\t\\t\\tthis.cameras.length = 0;\\n\\t\\t\\t\\t\\t\\tthis.camerasSet.clear();\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < len; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst layer = this.layerList[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tlayer._dirtyComposition = false;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < layer.cameras.length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst cameraComponent = layer.cameras[j];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!this.camerasSet.has(cameraComponent.camera)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.camerasSet.add(cameraComponent.camera);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.cameras.push(cameraComponent);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tif (this.cameras.length > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tsortPriority(this.cameras);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlet renderActionCount = 0;\\n\\t\\t\\t\\t\\t\\tthis.destroyRenderActions();\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this.cameras.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst camera = this.cameras[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (camera.camera.renderPasses.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.addDummyRenderAction(renderActionCount, camera);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trenderActionCount++;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tlet cameraFirstRenderAction = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst cameraFirstRenderActionIndex = renderActionCount;\\n\\t\\t\\t\\t\\t\\t\\t\\tlet lastRenderAction = null;\\n\\t\\t\\t\\t\\t\\t\\t\\tlet postProcessMarked = false;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < len; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst layer = this.layerList[j];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst isLayerEnabled = layer.enabled && this.subLayerEnabled[j];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (isLayerEnabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (layer.cameras.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (camera.layers.indexOf(layer.id) >= 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!postProcessMarked && layer.id === camera.disablePostEffectsLayer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpostProcessMarked = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (lastRenderAction) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlastRenderAction.triggerPostprocess = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst isTransparent = this.subLayerList[j];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlastRenderAction = this.addRenderAction(renderActionCount, layer, isTransparent, camera, cameraFirstRenderAction, postProcessMarked);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trenderActionCount++;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcameraFirstRenderAction = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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\\tif (cameraFirstRenderActionIndex < renderActionCount) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlastRenderAction.lastCameraUse = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!postProcessMarked && lastRenderAction) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlastRenderAction.triggerPostprocess = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (camera.renderTarget && camera.postEffectsEnabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.propagateRenderTarget(cameraFirstRenderActionIndex - 1, camera);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._logRenderActions();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetNextRenderAction(renderActionIndex) {\\n\\t\\t\\t\\tconst renderAction = new RenderAction();\\n\\t\\t\\t\\tthis._renderActions.push(renderAction);\\n\\t\\t\\t\\treturn renderAction;\\n\\t\\t}\\n\\t\\taddDummyRenderAction(renderActionIndex, camera) {\\n\\t\\t\\t\\tconst renderAction = this.getNextRenderAction(renderActionIndex);\\n\\t\\t\\t\\trenderAction.camera = camera;\\n\\t\\t\\t\\trenderAction.useCameraPasses = true;\\n\\t\\t}\\n\\t\\taddRenderAction(renderActionIndex, layer, isTransparent, camera, cameraFirstRenderAction, postProcessMarked) {\\n\\t\\t\\t\\tlet rt = layer.id !== LAYERID_DEPTH ? camera.renderTarget : null;\\n\\t\\t\\t\\tlet used = false;\\n\\t\\t\\t\\tconst renderActions = this._renderActions;\\n\\t\\t\\t\\tfor(let i = renderActionIndex - 1; i >= 0; i--){\\n\\t\\t\\t\\t\\t\\tif (renderActions[i].camera === camera && renderActions[i].renderTarget === rt) {\\n\\t\\t\\t\\t\\t\\t\\t\\tused = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (postProcessMarked && camera.postEffectsEnabled) {\\n\\t\\t\\t\\t\\t\\trt = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst renderAction = this.getNextRenderAction(renderActionIndex);\\n\\t\\t\\t\\trenderAction.triggerPostprocess = false;\\n\\t\\t\\t\\trenderAction.layer = layer;\\n\\t\\t\\t\\trenderAction.transparent = isTransparent;\\n\\t\\t\\t\\trenderAction.camera = camera;\\n\\t\\t\\t\\trenderAction.renderTarget = rt;\\n\\t\\t\\t\\trenderAction.firstCameraUse = cameraFirstRenderAction;\\n\\t\\t\\t\\trenderAction.lastCameraUse = false;\\n\\t\\t\\t\\tconst needsCameraClear = cameraFirstRenderAction || !used;\\n\\t\\t\\t\\tconst needsLayerClear = layer.clearColorBuffer || layer.clearDepthBuffer || layer.clearStencilBuffer;\\n\\t\\t\\t\\tif (needsCameraClear || needsLayerClear) {\\n\\t\\t\\t\\t\\t\\trenderAction.setupClears(needsCameraClear ? camera : undefined, layer);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn renderAction;\\n\\t\\t}\\n\\t\\tpropagateRenderTarget(startIndex, fromCamera) {\\n\\t\\t\\t\\tfor(let a = startIndex; a >= 0; a--){\\n\\t\\t\\t\\t\\t\\tconst ra = this._renderActions[a];\\n\\t\\t\\t\\t\\t\\tconst layer = ra.layer;\\n\\t\\t\\t\\t\\t\\tif (ra.renderTarget && layer.id !== LAYERID_DEPTH) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (layer.id === LAYERID_DEPTH) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (ra.useCameraPasses) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst thisCamera = ra?.camera.camera;\\n\\t\\t\\t\\t\\t\\tif (thisCamera) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!fromCamera.camera.rect.equals(thisCamera.rect) || !fromCamera.camera.scissorRect.equals(thisCamera.scissorRect)) {\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tra.renderTarget = fromCamera.renderTarget;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_logRenderActions() {}\\n\\t\\t_isLayerAdded(layer) {\\n\\t\\t\\t\\tconst found = this.layerIdMap.get(layer.id) === layer;\\n\\t\\t\\t\\treturn found;\\n\\t\\t}\\n\\t\\t_isSublayerAdded(layer, transparent) {\\n\\t\\t\\t\\tconst map = transparent ? this.layerTransparentIndexMap : this.layerOpaqueIndexMap;\\n\\t\\t\\t\\tif (map.get(layer) !== undefined) {\\n\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tpush(layer) {\\n\\t\\t\\t\\tif (this._isLayerAdded(layer)) return;\\n\\t\\t\\t\\tthis.layerList.push(layer);\\n\\t\\t\\t\\tthis.layerList.push(layer);\\n\\t\\t\\t\\tthis._opaqueOrder[layer.id] = this.subLayerList.push(false) - 1;\\n\\t\\t\\t\\tthis._transparentOrder[layer.id] = this.subLayerList.push(true) - 1;\\n\\t\\t\\t\\tthis.subLayerEnabled.push(true);\\n\\t\\t\\t\\tthis.subLayerEnabled.push(true);\\n\\t\\t\\t\\tthis._updateLayerMaps();\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t\\t\\tthis.fire('add', layer);\\n\\t\\t}\\n\\t\\tinsert(layer, index) {\\n\\t\\t\\t\\tif (this._isLayerAdded(layer)) return;\\n\\t\\t\\t\\tthis.layerList.splice(index, 0, layer, layer);\\n\\t\\t\\t\\tthis.subLayerList.splice(index, 0, false, true);\\n\\t\\t\\t\\tconst count = this.layerList.length;\\n\\t\\t\\t\\tthis._updateOpaqueOrder(index, count - 1);\\n\\t\\t\\t\\tthis._updateTransparentOrder(index, count - 1);\\n\\t\\t\\t\\tthis.subLayerEnabled.splice(index, 0, true, true);\\n\\t\\t\\t\\tthis._updateLayerMaps();\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t\\t\\tthis.fire('add', layer);\\n\\t\\t}\\n\\t\\tremove(layer) {\\n\\t\\t\\t\\tlet id = this.layerList.indexOf(layer);\\n\\t\\t\\t\\tdelete this._opaqueOrder[id];\\n\\t\\t\\t\\tdelete this._transparentOrder[id];\\n\\t\\t\\t\\twhile(id >= 0){\\n\\t\\t\\t\\t\\t\\tthis.layerList.splice(id, 1);\\n\\t\\t\\t\\t\\t\\tthis.subLayerList.splice(id, 1);\\n\\t\\t\\t\\t\\t\\tthis.subLayerEnabled.splice(id, 1);\\n\\t\\t\\t\\t\\t\\tid = this.layerList.indexOf(layer);\\n\\t\\t\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t\\t\\t\\t\\tthis.fire('remove', layer);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst count = this.layerList.length;\\n\\t\\t\\t\\tthis._updateOpaqueOrder(0, count - 1);\\n\\t\\t\\t\\tthis._updateTransparentOrder(0, count - 1);\\n\\t\\t\\t\\tthis._updateLayerMaps();\\n\\t\\t}\\n\\t\\tpushOpaque(layer) {\\n\\t\\t\\t\\tif (this._isSublayerAdded(layer, false)) return;\\n\\t\\t\\t\\tthis.layerList.push(layer);\\n\\t\\t\\t\\tthis._opaqueOrder[layer.id] = this.subLayerList.push(false) - 1;\\n\\t\\t\\t\\tthis.subLayerEnabled.push(true);\\n\\t\\t\\t\\tthis._updateLayerMaps();\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t\\t\\tthis.fire('add', layer);\\n\\t\\t}\\n\\t\\tinsertOpaque(layer, index) {\\n\\t\\t\\t\\tif (this._isSublayerAdded(layer, false)) return;\\n\\t\\t\\t\\tthis.layerList.splice(index, 0, layer);\\n\\t\\t\\t\\tthis.subLayerList.splice(index, 0, false);\\n\\t\\t\\t\\tconst count = this.subLayerList.length;\\n\\t\\t\\t\\tthis._updateOpaqueOrder(index, count - 1);\\n\\t\\t\\t\\tthis.subLayerEnabled.splice(index, 0, true);\\n\\t\\t\\t\\tthis._updateLayerMaps();\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t\\t\\tthis.fire('add', layer);\\n\\t\\t}\\n\\t\\tremoveOpaque(layer) {\\n\\t\\t\\t\\tfor(let i = 0, len = this.layerList.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tif (this.layerList[i] === layer && !this.subLayerList[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.layerList.splice(i, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.subLayerList.splice(i, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tlen--;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._updateOpaqueOrder(i, len - 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.subLayerEnabled.splice(i, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.layerList.indexOf(layer) < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('remove', layer);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._updateLayerMaps();\\n\\t\\t}\\n\\t\\tpushTransparent(layer) {\\n\\t\\t\\t\\tif (this._isSublayerAdded(layer, true)) return;\\n\\t\\t\\t\\tthis.layerList.push(layer);\\n\\t\\t\\t\\tthis._transparentOrder[layer.id] = this.subLayerList.push(true) - 1;\\n\\t\\t\\t\\tthis.subLayerEnabled.push(true);\\n\\t\\t\\t\\tthis._updateLayerMaps();\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t\\t\\tthis.fire('add', layer);\\n\\t\\t}\\n\\t\\tinsertTransparent(layer, index) {\\n\\t\\t\\t\\tif (this._isSublayerAdded(layer, true)) return;\\n\\t\\t\\t\\tthis.layerList.splice(index, 0, layer);\\n\\t\\t\\t\\tthis.subLayerList.splice(index, 0, true);\\n\\t\\t\\t\\tconst count = this.subLayerList.length;\\n\\t\\t\\t\\tthis._updateTransparentOrder(index, count - 1);\\n\\t\\t\\t\\tthis.subLayerEnabled.splice(index, 0, true);\\n\\t\\t\\t\\tthis._updateLayerMaps();\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t\\t\\tthis.fire('add', layer);\\n\\t\\t}\\n\\t\\tremoveTransparent(layer) {\\n\\t\\t\\t\\tfor(let i = 0, len = this.layerList.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tif (this.layerList[i] === layer && this.subLayerList[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.layerList.splice(i, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.subLayerList.splice(i, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tlen--;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._updateTransparentOrder(i, len - 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.subLayerEnabled.splice(i, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.layerList.indexOf(layer) < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('remove', layer);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._updateLayerMaps();\\n\\t\\t}\\n\\t\\tgetOpaqueIndex(layer) {\\n\\t\\t\\t\\treturn this.layerOpaqueIndexMap.get(layer) ?? -1;\\n\\t\\t}\\n\\t\\tgetTransparentIndex(layer) {\\n\\t\\t\\t\\treturn this.layerTransparentIndexMap.get(layer) ?? -1;\\n\\t\\t}\\n\\t\\tisEnabled(layer, transparent) {\\n\\t\\t\\t\\tif (layer.enabled) {\\n\\t\\t\\t\\t\\t\\tconst index = transparent ? this.getTransparentIndex(layer) : this.getOpaqueIndex(layer);\\n\\t\\t\\t\\t\\t\\tif (index >= 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn this.subLayerEnabled[index];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\t_updateLayerMaps() {\\n\\t\\t\\t\\tthis.layerIdMap.clear();\\n\\t\\t\\t\\tthis.layerNameMap.clear();\\n\\t\\t\\t\\tthis.layerOpaqueIndexMap.clear();\\n\\t\\t\\t\\tthis.layerTransparentIndexMap.clear();\\n\\t\\t\\t\\tfor(let i = 0; i < this.layerList.length; i++){\\n\\t\\t\\t\\t\\t\\tconst layer = this.layerList[i];\\n\\t\\t\\t\\t\\t\\tthis.layerIdMap.set(layer.id, layer);\\n\\t\\t\\t\\t\\t\\tthis.layerNameMap.set(layer.name, layer);\\n\\t\\t\\t\\t\\t\\tconst subLayerIndexMap = this.subLayerList[i] ? this.layerTransparentIndexMap : this.layerOpaqueIndexMap;\\n\\t\\t\\t\\t\\t\\tsubLayerIndexMap.set(layer, i);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetLayerById(id) {\\n\\t\\t\\t\\treturn this.layerIdMap.get(id) ?? null;\\n\\t\\t}\\n\\t\\tgetLayerByName(name) {\\n\\t\\t\\t\\treturn this.layerNameMap.get(name) ?? null;\\n\\t\\t}\\n\\t\\t_updateOpaqueOrder(startIndex, endIndex) {\\n\\t\\t\\t\\tfor(let i = startIndex; i <= endIndex; i++){\\n\\t\\t\\t\\t\\t\\tif (this.subLayerList[i] === false) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._opaqueOrder[this.layerList[i].id] = i;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_updateTransparentOrder(startIndex, endIndex) {\\n\\t\\t\\t\\tfor(let i = startIndex; i <= endIndex; i++){\\n\\t\\t\\t\\t\\t\\tif (this.subLayerList[i] === true) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._transparentOrder[this.layerList[i].id] = i;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_sortLayersDescending(layersA, layersB, order) {\\n\\t\\t\\t\\tlet topLayerA = -1;\\n\\t\\t\\t\\tlet topLayerB = -1;\\n\\t\\t\\t\\tfor(let i = 0, len = layersA.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst id = layersA[i];\\n\\t\\t\\t\\t\\t\\tif (order.hasOwnProperty(id)) {\\n\\t\\t\\t\\t\\t\\t\\t\\ttopLayerA = Math.max(topLayerA, order[id]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0, len = layersB.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst id = layersB[i];\\n\\t\\t\\t\\t\\t\\tif (order.hasOwnProperty(id)) {\\n\\t\\t\\t\\t\\t\\t\\t\\ttopLayerB = Math.max(topLayerB, order[id]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (topLayerA === -1 && topLayerB !== -1) {\\n\\t\\t\\t\\t\\t\\treturn 1;\\n\\t\\t\\t\\t} else if (topLayerB === -1 && topLayerA !== -1) {\\n\\t\\t\\t\\t\\t\\treturn -1;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn topLayerB - topLayerA;\\n\\t\\t}\\n\\t\\tsortTransparentLayers(layersA, layersB) {\\n\\t\\t\\t\\treturn this._sortLayersDescending(layersA, layersB, this._transparentOrder);\\n\\t\\t}\\n\\t\\tsortOpaqueLayers(layersA, layersB) {\\n\\t\\t\\t\\treturn this._sortLayersDescending(layersA, layersB, this._opaqueOrder);\\n\\t\\t}\\n\\t\\tconstructor(name = 'Untitled'){\\n\\t\\t\\t\\tsuper(), this.layerList = [], this.layerIdMap = new Map(), this.layerNameMap = new Map(), this.layerOpaqueIndexMap = new Map(), this.layerTransparentIndexMap = new Map(), this.subLayerList = [], this.subLayerEnabled = [], this.cameras = [], this.camerasSet = new Set(), this._renderActions = [], this._dirty = false;\\n\\t\\t\\t\\tthis.name = name;\\n\\t\\t\\t\\tthis._opaqueOrder = {};\\n\\t\\t\\t\\tthis._transparentOrder = {};\\n\\t\\t}\\n}\\n\\nconst tmpVec = new Vec3();\\nconst tmpBiases = {\\n\\t\\tbias: 0,\\n\\t\\tnormalBias: 0\\n};\\nconst tmpColor = new Color();\\nconst chanId = {\\n\\t\\tr: 0,\\n\\t\\tg: 1,\\n\\t\\tb: 2,\\n\\t\\ta: 3\\n};\\nconst lightTypes = {\\n\\t\\t'directional': LIGHTTYPE_DIRECTIONAL,\\n\\t\\t'omni': LIGHTTYPE_OMNI,\\n\\t\\t'point': LIGHTTYPE_OMNI,\\n\\t\\t'spot': LIGHTTYPE_SPOT\\n};\\nconst directionalCascades = [\\n\\t\\t[\\n\\t\\t\\t\\tnew Vec4(0, 0, 1, 1)\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tnew Vec4(0, 0, 0.5, 0.5),\\n\\t\\t\\t\\tnew Vec4(0, 0.5, 0.5, 0.5)\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tnew Vec4(0, 0, 0.5, 0.5),\\n\\t\\t\\t\\tnew Vec4(0, 0.5, 0.5, 0.5),\\n\\t\\t\\t\\tnew Vec4(0.5, 0, 0.5, 0.5)\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\tnew Vec4(0, 0, 0.5, 0.5),\\n\\t\\t\\t\\tnew Vec4(0, 0.5, 0.5, 0.5),\\n\\t\\t\\t\\tnew Vec4(0.5, 0, 0.5, 0.5),\\n\\t\\t\\t\\tnew Vec4(0.5, 0.5, 0.5, 0.5)\\n\\t\\t]\\n];\\nconst channelMap = {\\n\\t\\t'rrr': 0b0001,\\n\\t\\t'ggg': 0b0010,\\n\\t\\t'bbb': 0b0100,\\n\\t\\t'aaa': 0b1000,\\n\\t\\t'rgb': 0b0111\\n};\\nlet id$2 = 0;\\nclass LightRenderData {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.viewBindGroups.forEach((bg)=>{\\n\\t\\t\\t\\t\\t\\tbg.defaultUniformBuffer.destroy();\\n\\t\\t\\t\\t\\t\\tbg.destroy();\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.viewBindGroups.length = 0;\\n\\t\\t}\\n\\t\\tget shadowBuffer() {\\n\\t\\t\\t\\tconst rt = this.shadowCamera.renderTarget;\\n\\t\\t\\t\\tif (rt) {\\n\\t\\t\\t\\t\\t\\treturn this.light._isPcf ? rt.depthBuffer : rt.colorBuffer;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tconstructor(camera, face, light){\\n\\t\\t\\t\\tthis.light = light;\\n\\t\\t\\t\\tthis.camera = camera;\\n\\t\\t\\t\\tthis.shadowCamera = ShadowRenderer.createShadowCamera(light._shadowType, light._type, face);\\n\\t\\t\\t\\tthis.shadowMatrix = new Mat4();\\n\\t\\t\\t\\tthis.shadowViewport = new Vec4(0, 0, 1, 1);\\n\\t\\t\\t\\tthis.shadowScissor = new Vec4(0, 0, 1, 1);\\n\\t\\t\\t\\tthis.projectionCompensation = 0;\\n\\t\\t\\t\\tthis.face = face;\\n\\t\\t\\t\\tthis.visibleCasters = [];\\n\\t\\t\\t\\tthis.viewBindGroups = [];\\n\\t\\t}\\n}\\nclass Light {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._evtDeviceRestored?.off();\\n\\t\\t\\t\\tthis._evtDeviceRestored = null;\\n\\t\\t\\t\\tthis._destroyShadowMap();\\n\\t\\t\\t\\tthis.releaseRenderData();\\n\\t\\t\\t\\tthis._renderData = null;\\n\\t\\t}\\n\\t\\tonDeviceRestored() {\\n\\t\\t\\t\\tif (this.shadowUpdateMode === SHADOWUPDATE_NONE) {\\n\\t\\t\\t\\t\\t\\tthis.shadowUpdateMode = SHADOWUPDATE_THISFRAME;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treleaseRenderData() {\\n\\t\\t\\t\\tif (this._renderData) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._renderData.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._renderData[i].destroy();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._renderData.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\taddLayer(layer) {\\n\\t\\t\\t\\tthis.layers.add(layer);\\n\\t\\t}\\n\\t\\tremoveLayer(layer) {\\n\\t\\t\\t\\tthis.layers.delete(layer);\\n\\t\\t}\\n\\t\\tset shadowSamples(value) {\\n\\t\\t\\t\\tthis._softShadowParams[0] = value;\\n\\t\\t}\\n\\t\\tget shadowSamples() {\\n\\t\\t\\t\\treturn this._softShadowParams[0];\\n\\t\\t}\\n\\t\\tset shadowBlockerSamples(value) {\\n\\t\\t\\t\\tthis._softShadowParams[1] = value;\\n\\t\\t}\\n\\t\\tget shadowBlockerSamples() {\\n\\t\\t\\t\\treturn this._softShadowParams[1];\\n\\t\\t}\\n\\t\\tset shadowBias(value) {\\n\\t\\t\\t\\tif (this._shadowBias !== value) {\\n\\t\\t\\t\\t\\t\\tthis._shadowBias = value;\\n\\t\\t\\t\\t\\t\\tthis._updateShadowBias();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget shadowBias() {\\n\\t\\t\\t\\treturn this._shadowBias;\\n\\t\\t}\\n\\t\\tset numCascades(value) {\\n\\t\\t\\t\\tif (!this.cascades || this.numCascades !== value) {\\n\\t\\t\\t\\t\\t\\tthis.cascades = directionalCascades[value - 1];\\n\\t\\t\\t\\t\\t\\tthis._shadowMatrixPalette = new Float32Array(4 * 16);\\n\\t\\t\\t\\t\\t\\tthis._shadowCascadeDistances = new Float32Array(4);\\n\\t\\t\\t\\t\\t\\tthis._destroyShadowMap();\\n\\t\\t\\t\\t\\t\\tthis.updateKey();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget numCascades() {\\n\\t\\t\\t\\treturn this.cascades.length;\\n\\t\\t}\\n\\t\\tset cascadeBlend(value) {\\n\\t\\t\\t\\tif (this._cascadeBlend !== value) {\\n\\t\\t\\t\\t\\t\\tthis._cascadeBlend = value;\\n\\t\\t\\t\\t\\t\\tthis.updateKey();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget cascadeBlend() {\\n\\t\\t\\t\\treturn this._cascadeBlend;\\n\\t\\t}\\n\\t\\tset shadowMap(shadowMap) {\\n\\t\\t\\t\\tif (this._shadowMap !== shadowMap) {\\n\\t\\t\\t\\t\\t\\tthis._destroyShadowMap();\\n\\t\\t\\t\\t\\t\\tthis._shadowMap = shadowMap;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget shadowMap() {\\n\\t\\t\\t\\treturn this._shadowMap;\\n\\t\\t}\\n\\t\\tset mask(value) {\\n\\t\\t\\t\\tif (this._mask !== value) {\\n\\t\\t\\t\\t\\t\\tthis._mask = value;\\n\\t\\t\\t\\t\\t\\tthis.updateKey();\\n\\t\\t\\t\\t\\t\\tthis.updateClusteredFlags();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget mask() {\\n\\t\\t\\t\\treturn this._mask;\\n\\t\\t}\\n\\t\\tget numShadowFaces() {\\n\\t\\t\\t\\tconst type = this._type;\\n\\t\\t\\t\\tif (type === LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\t\\treturn this.numCascades;\\n\\t\\t\\t\\t} else if (type === LIGHTTYPE_OMNI) {\\n\\t\\t\\t\\t\\t\\treturn 6;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn 1;\\n\\t\\t}\\n\\t\\tset type(value) {\\n\\t\\t\\t\\tif (this._type === value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._type = value;\\n\\t\\t\\t\\tthis._destroyShadowMap();\\n\\t\\t\\t\\tthis._updateShadowBias();\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t\\t\\tthis.updateClusteredFlags();\\n\\t\\t\\t\\tconst stype = this._shadowType;\\n\\t\\t\\t\\tthis._shadowType = null;\\n\\t\\t\\t\\tthis.shadowUpdateOverrides = null;\\n\\t\\t\\t\\tthis.shadowType = stype;\\n\\t\\t}\\n\\t\\tget type() {\\n\\t\\t\\t\\treturn this._type;\\n\\t\\t}\\n\\t\\tset shape(value) {\\n\\t\\t\\t\\tif (this._shape === value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._shape = value;\\n\\t\\t\\t\\tthis._destroyShadowMap();\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t\\t\\tthis.updateClusteredFlags();\\n\\t\\t\\t\\tconst stype = this._shadowType;\\n\\t\\t\\t\\tthis._shadowType = null;\\n\\t\\t\\t\\tthis.shadowType = stype;\\n\\t\\t}\\n\\t\\tget shape() {\\n\\t\\t\\t\\treturn this._shape;\\n\\t\\t}\\n\\t\\tset usePhysicalUnits(value) {\\n\\t\\t\\t\\tif (this._usePhysicalUnits !== value) {\\n\\t\\t\\t\\t\\t\\tthis._usePhysicalUnits = value;\\n\\t\\t\\t\\t\\t\\tthis._updateLinearColor();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget usePhysicalUnits() {\\n\\t\\t\\t\\treturn this._usePhysicalUnits;\\n\\t\\t}\\n\\t\\tset shadowType(value) {\\n\\t\\t\\t\\tif (this._shadowType === value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet shadowInfo = shadowTypeInfo.get(value);\\n\\t\\t\\t\\tif (!shadowInfo) {\\n\\t\\t\\t\\t\\t\\tvalue = SHADOW_PCF3_32F;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tif (value === SHADOW_PCSS_32F && (!device.textureFloatRenderable || !device.textureFloatFilterable)) {\\n\\t\\t\\t\\t\\t\\tvalue = SHADOW_PCF3_32F;\\n\\t\\t\\t\\t}\\n\\t\\t\\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\\t\\t\\t\\tvalue = SHADOW_PCF3_32F;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (value === SHADOW_VSM_32F && (!device.textureFloatRenderable || !device.textureFloatFilterable)) {\\n\\t\\t\\t\\t\\t\\tvalue = SHADOW_VSM_16F;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (value === SHADOW_VSM_16F && !device.textureHalfFloatRenderable) {\\n\\t\\t\\t\\t\\t\\tvalue = SHADOW_PCF3_32F;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tshadowInfo = shadowTypeInfo.get(value);\\n\\t\\t\\t\\tthis._isVsm = shadowInfo?.vsm ?? false;\\n\\t\\t\\t\\tthis._isPcf = shadowInfo?.pcf ?? false;\\n\\t\\t\\t\\tthis._shadowType = value;\\n\\t\\t\\t\\tthis._destroyShadowMap();\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t\\tget shadowType() {\\n\\t\\t\\t\\treturn this._shadowType;\\n\\t\\t}\\n\\t\\tset enabled(value) {\\n\\t\\t\\t\\tif (this._enabled !== value) {\\n\\t\\t\\t\\t\\t\\tthis._enabled = value;\\n\\t\\t\\t\\t\\t\\tthis.layersDirty();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget enabled() {\\n\\t\\t\\t\\treturn this._enabled;\\n\\t\\t}\\n\\t\\tset castShadows(value) {\\n\\t\\t\\t\\tif (this._castShadows !== value) {\\n\\t\\t\\t\\t\\t\\tthis._castShadows = value;\\n\\t\\t\\t\\t\\t\\tthis._destroyShadowMap();\\n\\t\\t\\t\\t\\t\\tthis.layersDirty();\\n\\t\\t\\t\\t\\t\\tthis.updateKey();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget castShadows() {\\n\\t\\t\\t\\treturn this._castShadows && this._mask !== MASK_BAKE && this._mask !== 0;\\n\\t\\t}\\n\\t\\tset shadowIntensity(value) {\\n\\t\\t\\t\\tif (this._shadowIntensity !== value) {\\n\\t\\t\\t\\t\\t\\tthis._shadowIntensity = value;\\n\\t\\t\\t\\t\\t\\tthis.updateKey();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget shadowIntensity() {\\n\\t\\t\\t\\treturn this._shadowIntensity;\\n\\t\\t}\\n\\t\\tget bakeShadows() {\\n\\t\\t\\t\\treturn this._castShadows && this._mask === MASK_BAKE;\\n\\t\\t}\\n\\t\\tset shadowResolution(value) {\\n\\t\\t\\t\\tif (this._shadowResolution !== value) {\\n\\t\\t\\t\\t\\t\\tif (this._type === LIGHTTYPE_OMNI) {\\n\\t\\t\\t\\t\\t\\t\\t\\tvalue = Math.min(value, this.device.maxCubeMapSize);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tvalue = Math.min(value, this.device.maxTextureSize);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._shadowResolution = value;\\n\\t\\t\\t\\t\\t\\tthis._destroyShadowMap();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget shadowResolution() {\\n\\t\\t\\t\\treturn this._shadowResolution;\\n\\t\\t}\\n\\t\\tset vsmBlurSize(value) {\\n\\t\\t\\t\\tif (this._vsmBlurSize === value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (value % 2 === 0) value++;\\n\\t\\t\\t\\tthis._vsmBlurSize = value;\\n\\t\\t}\\n\\t\\tget vsmBlurSize() {\\n\\t\\t\\t\\treturn this._vsmBlurSize;\\n\\t\\t}\\n\\t\\tset normalOffsetBias(value) {\\n\\t\\t\\t\\tif (this._normalOffsetBias !== value) {\\n\\t\\t\\t\\t\\t\\tconst dirty = !this._normalOffsetBias && value || this._normalOffsetBias && !value;\\n\\t\\t\\t\\t\\t\\tthis._normalOffsetBias = value;\\n\\t\\t\\t\\t\\t\\tif (dirty) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.updateKey();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget normalOffsetBias() {\\n\\t\\t\\t\\treturn this._normalOffsetBias;\\n\\t\\t}\\n\\t\\tset falloffMode(value) {\\n\\t\\t\\t\\tif (this._falloffMode === value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._falloffMode = value;\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t\\t\\tthis.updateClusteredFlags();\\n\\t\\t}\\n\\t\\tget falloffMode() {\\n\\t\\t\\t\\treturn this._falloffMode;\\n\\t\\t}\\n\\t\\tset innerConeAngle(value) {\\n\\t\\t\\t\\tif (this._innerConeAngle === value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._innerConeAngle = value;\\n\\t\\t\\t\\tthis._innerConeAngleCos = Math.cos(value * math.DEG_TO_RAD);\\n\\t\\t\\t\\tthis.updateClusterData(false, true);\\n\\t\\t\\t\\tif (this._usePhysicalUnits) {\\n\\t\\t\\t\\t\\t\\tthis._updateLinearColor();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget innerConeAngle() {\\n\\t\\t\\t\\treturn this._innerConeAngle;\\n\\t\\t}\\n\\t\\tset outerConeAngle(value) {\\n\\t\\t\\t\\tif (this._outerConeAngle === value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._outerConeAngle = value;\\n\\t\\t\\t\\tthis._updateOuterAngle(value);\\n\\t\\t\\t\\tif (this._usePhysicalUnits) {\\n\\t\\t\\t\\t\\t\\tthis._updateLinearColor();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget outerConeAngle() {\\n\\t\\t\\t\\treturn this._outerConeAngle;\\n\\t\\t}\\n\\t\\tset penumbraSize(value) {\\n\\t\\t\\t\\tthis._penumbraSize = value;\\n\\t\\t\\t\\tthis._softShadowParams[2] = value;\\n\\t\\t}\\n\\t\\tget penumbraSize() {\\n\\t\\t\\t\\treturn this._penumbraSize;\\n\\t\\t}\\n\\t\\tset penumbraFalloff(value) {\\n\\t\\t\\t\\tthis._softShadowParams[3] = value;\\n\\t\\t}\\n\\t\\tget penumbraFalloff() {\\n\\t\\t\\t\\treturn this._softShadowParams[3];\\n\\t\\t}\\n\\t\\t_updateOuterAngle(angle) {\\n\\t\\t\\t\\tconst radAngle = angle * math.DEG_TO_RAD;\\n\\t\\t\\t\\tthis._outerConeAngleCos = Math.cos(radAngle);\\n\\t\\t\\t\\tthis._outerConeAngleSin = Math.sin(radAngle);\\n\\t\\t\\t\\tthis.updateClusterData(false, true);\\n\\t\\t}\\n\\t\\tset intensity(value) {\\n\\t\\t\\t\\tif (this._intensity !== value) {\\n\\t\\t\\t\\t\\t\\tthis._intensity = value;\\n\\t\\t\\t\\t\\t\\tthis._updateLinearColor();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget intensity() {\\n\\t\\t\\t\\treturn this._intensity;\\n\\t\\t}\\n\\t\\tset affectSpecularity(value) {\\n\\t\\t\\t\\tif (this._type === LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\t\\tthis._affectSpecularity = value;\\n\\t\\t\\t\\t\\t\\tthis.updateKey();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget affectSpecularity() {\\n\\t\\t\\t\\treturn this._affectSpecularity;\\n\\t\\t}\\n\\t\\tset luminance(value) {\\n\\t\\t\\t\\tif (this._luminance !== value) {\\n\\t\\t\\t\\t\\t\\tthis._luminance = value;\\n\\t\\t\\t\\t\\t\\tthis._updateLinearColor();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget luminance() {\\n\\t\\t\\t\\treturn this._luminance;\\n\\t\\t}\\n\\t\\tget cookieMatrix() {\\n\\t\\t\\t\\tif (!this._cookieMatrix) {\\n\\t\\t\\t\\t\\t\\tthis._cookieMatrix = new Mat4();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._cookieMatrix;\\n\\t\\t}\\n\\t\\tget atlasViewport() {\\n\\t\\t\\t\\tif (!this._atlasViewport) {\\n\\t\\t\\t\\t\\t\\tthis._atlasViewport = new Vec4(0, 0, 1, 1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._atlasViewport;\\n\\t\\t}\\n\\t\\tset cookie(value) {\\n\\t\\t\\t\\tif (this._cookie === value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._cookie = value;\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t\\tget cookie() {\\n\\t\\t\\t\\treturn this._cookie;\\n\\t\\t}\\n\\t\\tset cookieFalloff(value) {\\n\\t\\t\\t\\tif (this._cookieFalloff === value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._cookieFalloff = value;\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t\\tget cookieFalloff() {\\n\\t\\t\\t\\treturn this._cookieFalloff;\\n\\t\\t}\\n\\t\\tset cookieChannel(value) {\\n\\t\\t\\t\\tif (this._cookieChannel === value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (value.length < 3) {\\n\\t\\t\\t\\t\\t\\tconst chr = value.charAt(value.length - 1);\\n\\t\\t\\t\\t\\t\\tconst addLen = 3 - value.length;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < addLen; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tvalue += chr;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._cookieChannel = value;\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t\\t\\tthis.updateClusteredFlags();\\n\\t\\t}\\n\\t\\tget cookieChannel() {\\n\\t\\t\\t\\treturn this._cookieChannel;\\n\\t\\t}\\n\\t\\tset cookieTransform(value) {\\n\\t\\t\\t\\tif (this._cookieTransform === value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._cookieTransform = value;\\n\\t\\t\\t\\tthis._cookieTransformSet = !!value;\\n\\t\\t\\t\\tif (value && !this._cookieOffset) {\\n\\t\\t\\t\\t\\t\\tthis.cookieOffset = new Vec2();\\n\\t\\t\\t\\t\\t\\tthis._cookieOffsetSet = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t\\tget cookieTransform() {\\n\\t\\t\\t\\treturn this._cookieTransform;\\n\\t\\t}\\n\\t\\tset cookieOffset(value) {\\n\\t\\t\\t\\tif (this._cookieOffset === value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst xformNew = !!(this._cookieTransformSet || value);\\n\\t\\t\\t\\tif (xformNew && !value && this._cookieOffset) {\\n\\t\\t\\t\\t\\t\\tthis._cookieOffset.set(0, 0);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._cookieOffset = value;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._cookieOffsetSet = !!value;\\n\\t\\t\\t\\tif (value && !this._cookieTransform) {\\n\\t\\t\\t\\t\\t\\tthis.cookieTransform = new Vec4(1, 1, 0, 0);\\n\\t\\t\\t\\t\\t\\tthis._cookieTransformSet = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.updateKey();\\n\\t\\t}\\n\\t\\tget cookieOffset() {\\n\\t\\t\\t\\treturn this._cookieOffset;\\n\\t\\t}\\n\\t\\tbeginFrame() {\\n\\t\\t\\t\\tthis.visibleThisFrame = this._type === LIGHTTYPE_DIRECTIONAL && this._enabled;\\n\\t\\t\\t\\tthis.maxScreenSize = 0;\\n\\t\\t\\t\\tthis.atlasViewportAllocated = false;\\n\\t\\t\\t\\tthis.atlasSlotUpdated = false;\\n\\t\\t}\\n\\t\\t_destroyShadowMap() {\\n\\t\\t\\t\\tthis.releaseRenderData();\\n\\t\\t\\t\\tif (this._shadowMap) {\\n\\t\\t\\t\\t\\t\\tif (!this._shadowMap.cached) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._shadowMap.destroy();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._shadowMap = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.shadowUpdateMode === SHADOWUPDATE_NONE) {\\n\\t\\t\\t\\t\\t\\tthis.shadowUpdateMode = SHADOWUPDATE_THISFRAME;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.shadowUpdateOverrides) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this.shadowUpdateOverrides.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.shadowUpdateOverrides[i] === SHADOWUPDATE_NONE) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.shadowUpdateOverrides[i] = SHADOWUPDATE_THISFRAME;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetRenderData(camera, face) {\\n\\t\\t\\t\\tfor(let i = 0; i < this._renderData.length; i++){\\n\\t\\t\\t\\t\\t\\tconst current = this._renderData[i];\\n\\t\\t\\t\\t\\t\\tif (current.camera === camera && current.face === face) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn current;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst rd = new LightRenderData(camera, face, this);\\n\\t\\t\\t\\tthis._renderData.push(rd);\\n\\t\\t\\t\\treturn rd;\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst clone = new Light(this.device, this.clusteredLighting);\\n\\t\\t\\t\\tclone.type = this._type;\\n\\t\\t\\t\\tclone.setColor(this._color);\\n\\t\\t\\t\\tclone.intensity = this._intensity;\\n\\t\\t\\t\\tclone.affectSpecularity = this._affectSpecularity;\\n\\t\\t\\t\\tclone.luminance = this._luminance;\\n\\t\\t\\t\\tclone.castShadows = this.castShadows;\\n\\t\\t\\t\\tclone._enabled = this._enabled;\\n\\t\\t\\t\\tclone.attenuationStart = this.attenuationStart;\\n\\t\\t\\t\\tclone.attenuationEnd = this.attenuationEnd;\\n\\t\\t\\t\\tclone.falloffMode = this._falloffMode;\\n\\t\\t\\t\\tclone.shadowType = this._shadowType;\\n\\t\\t\\t\\tclone.vsmBlurSize = this._vsmBlurSize;\\n\\t\\t\\t\\tclone.vsmBlurMode = this.vsmBlurMode;\\n\\t\\t\\t\\tclone.vsmBias = this.vsmBias;\\n\\t\\t\\t\\tclone.shadowUpdateMode = this.shadowUpdateMode;\\n\\t\\t\\t\\tclone.mask = this.mask;\\n\\t\\t\\t\\tif (this.shadowUpdateOverrides) {\\n\\t\\t\\t\\t\\t\\tclone.shadowUpdateOverrides = this.shadowUpdateOverrides.slice();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tclone.innerConeAngle = this._innerConeAngle;\\n\\t\\t\\t\\tclone.outerConeAngle = this._outerConeAngle;\\n\\t\\t\\t\\tclone.numCascades = this.numCascades;\\n\\t\\t\\t\\tclone.cascadeDistribution = this.cascadeDistribution;\\n\\t\\t\\t\\tclone.cascadeBlend = this._cascadeBlend;\\n\\t\\t\\t\\tclone.shape = this._shape;\\n\\t\\t\\t\\tclone.shadowDepthState.copy(this.shadowDepthState);\\n\\t\\t\\t\\tclone.shadowBias = this.shadowBias;\\n\\t\\t\\t\\tclone.normalOffsetBias = this._normalOffsetBias;\\n\\t\\t\\t\\tclone.shadowResolution = this._shadowResolution;\\n\\t\\t\\t\\tclone.shadowDistance = this.shadowDistance;\\n\\t\\t\\t\\tclone.shadowIntensity = this.shadowIntensity;\\n\\t\\t\\t\\tclone.shadowSamples = this.shadowSamples;\\n\\t\\t\\t\\tclone.shadowBlockerSamples = this.shadowBlockerSamples;\\n\\t\\t\\t\\tclone.penumbraSize = this.penumbraSize;\\n\\t\\t\\t\\tclone.penumbraFalloff = this.penumbraFalloff;\\n\\t\\t\\t\\treturn clone;\\n\\t\\t}\\n\\t\\tstatic getLightUnitConversion(type, outerAngle = Math.PI / 4, innerAngle = 0) {\\n\\t\\t\\t\\tswitch(type){\\n\\t\\t\\t\\t\\t\\tcase LIGHTTYPE_SPOT:\\n\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst falloffEnd = Math.cos(outerAngle);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst falloffStart = Math.cos(innerAngle);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn 2 * Math.PI * (1 - falloffStart + (falloffStart - falloffEnd) / 2.0);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcase LIGHTTYPE_OMNI:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 4 * Math.PI;\\n\\t\\t\\t\\t\\t\\tcase LIGHTTYPE_DIRECTIONAL:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 1;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_getUniformBiasValues(lightRenderData) {\\n\\t\\t\\t\\tconst farClip = lightRenderData.shadowCamera._farClip;\\n\\t\\t\\t\\tswitch(this._type){\\n\\t\\t\\t\\t\\t\\tcase LIGHTTYPE_OMNI:\\n\\t\\t\\t\\t\\t\\t\\t\\ttmpBiases.bias = this.shadowBias;\\n\\t\\t\\t\\t\\t\\t\\t\\ttmpBiases.normalBias = this._normalOffsetBias;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase LIGHTTYPE_SPOT:\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._isVsm) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttmpBiases.bias = -1e-5 * 20;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttmpBiases.bias = this.shadowBias * 20;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\ttmpBiases.normalBias = this._isVsm ? this.vsmBias / (this.attenuationEnd / 7.0) : this._normalOffsetBias;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase LIGHTTYPE_DIRECTIONAL:\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._isVsm) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttmpBiases.bias = -1e-5 * 20;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttmpBiases.bias = this.shadowBias / farClip * 100;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\ttmpBiases.normalBias = this._isVsm ? this.vsmBias / (farClip / 7.0) : this._normalOffsetBias;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn tmpBiases;\\n\\t\\t}\\n\\t\\tgetColor() {\\n\\t\\t\\t\\treturn this._color;\\n\\t\\t}\\n\\t\\tgetBoundingSphere(sphere) {\\n\\t\\t\\t\\tif (this._type === LIGHTTYPE_SPOT) {\\n\\t\\t\\t\\t\\t\\tconst size = this.attenuationEnd;\\n\\t\\t\\t\\t\\t\\tconst angle = this._outerConeAngle;\\n\\t\\t\\t\\t\\t\\tconst cosAngle = this._outerConeAngleCos;\\n\\t\\t\\t\\t\\t\\tconst node = this._node;\\n\\t\\t\\t\\t\\t\\ttmpVec.copy(node.up);\\n\\t\\t\\t\\t\\t\\tif (angle > 45) {\\n\\t\\t\\t\\t\\t\\t\\t\\tsphere.radius = size * this._outerConeAngleSin;\\n\\t\\t\\t\\t\\t\\t\\t\\ttmpVec.mulScalar(-size * cosAngle);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tsphere.radius = size / (2 * cosAngle);\\n\\t\\t\\t\\t\\t\\t\\t\\ttmpVec.mulScalar(-sphere.radius);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tsphere.center.add2(node.getPosition(), tmpVec);\\n\\t\\t\\t\\t} else if (this._type === LIGHTTYPE_OMNI) {\\n\\t\\t\\t\\t\\t\\tsphere.center = this._node.getPosition();\\n\\t\\t\\t\\t\\t\\tsphere.radius = this.attenuationEnd;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetBoundingBox(box) {\\n\\t\\t\\t\\tif (this._type === LIGHTTYPE_SPOT) {\\n\\t\\t\\t\\t\\t\\tconst range = this.attenuationEnd;\\n\\t\\t\\t\\t\\t\\tconst angle = this._outerConeAngle;\\n\\t\\t\\t\\t\\t\\tconst node = this._node;\\n\\t\\t\\t\\t\\t\\tconst scl = Math.abs(Math.sin(angle * math.DEG_TO_RAD) * range);\\n\\t\\t\\t\\t\\t\\tbox.center.set(0, -range * 0.5, 0);\\n\\t\\t\\t\\t\\t\\tbox.halfExtents.set(scl, range * 0.5, scl);\\n\\t\\t\\t\\t\\t\\tbox.setFromTransformedAabb(box, node.getWorldTransform(), true);\\n\\t\\t\\t\\t} else if (this._type === LIGHTTYPE_OMNI) {\\n\\t\\t\\t\\t\\t\\tbox.center.copy(this._node.getPosition());\\n\\t\\t\\t\\t\\t\\tbox.halfExtents.set(this.attenuationEnd, this.attenuationEnd, this.attenuationEnd);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_updateShadowBias() {\\n\\t\\t\\t\\tif (this._type === LIGHTTYPE_OMNI && !this.clusteredLighting) {\\n\\t\\t\\t\\t\\t\\tthis.shadowDepthState.depthBias = 0;\\n\\t\\t\\t\\t\\t\\tthis.shadowDepthState.depthBiasSlope = 0;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst bias = this.shadowBias * -1e3;\\n\\t\\t\\t\\t\\t\\tthis.shadowDepthState.depthBias = bias;\\n\\t\\t\\t\\t\\t\\tthis.shadowDepthState.depthBiasSlope = bias;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_updateLinearColor() {\\n\\t\\t\\t\\tlet intensity = this._intensity;\\n\\t\\t\\t\\tif (this._usePhysicalUnits) {\\n\\t\\t\\t\\t\\t\\tintensity = this._luminance / Light.getLightUnitConversion(this._type, this._outerConeAngle * math.DEG_TO_RAD, this._innerConeAngle * math.DEG_TO_RAD);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst color = this._color;\\n\\t\\t\\t\\tconst colorLinear = this._colorLinear;\\n\\t\\t\\t\\tif (intensity >= 1) {\\n\\t\\t\\t\\t\\t\\ttmpColor.linear(color).mulScalar(intensity);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\ttmpColor.copy(color).mulScalar(intensity).linear();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcolorLinear[0] = tmpColor.r;\\n\\t\\t\\t\\tcolorLinear[1] = tmpColor.g;\\n\\t\\t\\t\\tcolorLinear[2] = tmpColor.b;\\n\\t\\t\\t\\tthis.updateClusterData(true);\\n\\t\\t}\\n\\t\\tsetColor() {\\n\\t\\t\\t\\tif (arguments.length === 1) {\\n\\t\\t\\t\\t\\t\\tthis._color.set(arguments[0].r, arguments[0].g, arguments[0].b);\\n\\t\\t\\t\\t} else if (arguments.length === 3) {\\n\\t\\t\\t\\t\\t\\tthis._color.set(arguments[0], arguments[1], arguments[2]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._updateLinearColor();\\n\\t\\t}\\n\\t\\tlayersDirty() {\\n\\t\\t\\t\\tthis.layers.forEach((layer)=>{\\n\\t\\t\\t\\t\\t\\tif (layer.hasLight(this)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlayer.markLightsDirty();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tupdateKey() {\\n\\t\\t\\t\\tlet key = this._type << 29 | this._shadowType << 25 | this._falloffMode << 23 | (this._normalOffsetBias !== 0.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\\t\\t\\tif (this._cookieChannel.length === 3) {\\n\\t\\t\\t\\t\\t\\tkey |= chanId[this._cookieChannel.charAt(1)] << 16;\\n\\t\\t\\t\\t\\t\\tkey |= chanId[this._cookieChannel.charAt(2)] << 14;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (key !== this.key) {\\n\\t\\t\\t\\t\\t\\tthis.layersDirty();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.key = key;\\n\\t\\t}\\n\\t\\tupdateClusteredFlags() {\\n\\t\\t\\t\\tconst isDynamic = !!(this.mask & MASK_AFFECT_DYNAMIC);\\n\\t\\t\\t\\tconst isLightmapped = !!(this.mask & MASK_AFFECT_LIGHTMAPPED);\\n\\t\\t\\t\\tthis.clusteredFlags = (this.type === LIGHTTYPE_SPOT ? 1 : 0) << 30 | (this._shape & 0x3) << 28 | (this._falloffMode & 0x1) << 27 | (channelMap[this._cookieChannel] ?? 0) << 23 | (isDynamic ? 1 : 0) << 22 | (isLightmapped ? 1 : 0) << 21;\\n\\t\\t}\\n\\t\\tgetClusteredFlags(castShadows, useCookie) {\\n\\t\\t\\t\\treturn this.clusteredFlags | ((castShadows ? Math.floor(this.shadowIntensity * 255) : 0) & 0xFF) << 0 | ((useCookie ? Math.floor(this.cookieIntensity * 255) : 0) & 0xFF) << 8;\\n\\t\\t}\\n\\t\\tupdateClusterData(updateColor, updateAngles) {\\n\\t\\t\\t\\tconst { clusteredData16 } = this;\\n\\t\\t\\t\\tconst float2Half = FloatPacking.float2Half;\\n\\t\\t\\t\\tif (updateColor) {\\n\\t\\t\\t\\t\\t\\tclusteredData16[0] = float2Half(math.clamp(this._colorLinear[0] / LIGHT_COLOR_DIVIDER, 0, 65504));\\n\\t\\t\\t\\t\\t\\tclusteredData16[1] = float2Half(math.clamp(this._colorLinear[1] / LIGHT_COLOR_DIVIDER, 0, 65504));\\n\\t\\t\\t\\t\\t\\tclusteredData16[2] = float2Half(math.clamp(this._colorLinear[2] / LIGHT_COLOR_DIVIDER, 0, 65504));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (updateAngles) {\\n\\t\\t\\t\\t\\t\\tconst cosThreshold = 0.5;\\n\\t\\t\\t\\t\\t\\tlet flags = 0;\\n\\t\\t\\t\\t\\t\\tconst angleShrinkFactor = 0.99;\\n\\t\\t\\t\\t\\t\\tlet innerCos = Math.cos(this._innerConeAngle * angleShrinkFactor * math.DEG_TO_RAD);\\n\\t\\t\\t\\t\\t\\tif (innerCos > cosThreshold) {\\n\\t\\t\\t\\t\\t\\t\\t\\tinnerCos = 1.0 - innerCos;\\n\\t\\t\\t\\t\\t\\t\\t\\tflags |= 1;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlet outerCos = Math.cos(this._outerConeAngle * angleShrinkFactor * math.DEG_TO_RAD);\\n\\t\\t\\t\\t\\t\\tif (outerCos > cosThreshold) {\\n\\t\\t\\t\\t\\t\\t\\t\\touterCos = 1.0 - outerCos;\\n\\t\\t\\t\\t\\t\\t\\t\\tflags |= 2;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tclusteredData16[3] = flags;\\n\\t\\t\\t\\t\\t\\tclusteredData16[4] = float2Half(innerCos);\\n\\t\\t\\t\\t\\t\\tclusteredData16[5] = float2Half(outerCos);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice, clusteredLighting){\\n\\t\\t\\t\\tthis.layers = new Set();\\n\\t\\t\\t\\tthis.shadowDepthState = DepthState.DEFAULT.clone();\\n\\t\\t\\t\\tthis.clusteredFlags = 0;\\n\\t\\t\\t\\tthis.clusteredData = new Uint32Array(3);\\n\\t\\t\\t\\tthis.clusteredData16 = new Uint16Array(this.clusteredData.buffer);\\n\\t\\t\\t\\tthis._evtDeviceRestored = null;\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t\\t\\tthis.clusteredLighting = clusteredLighting;\\n\\t\\t\\t\\tthis.id = id$2++;\\n\\t\\t\\t\\tthis._evtDeviceRestored = graphicsDevice.on('devicerestored', this.onDeviceRestored, this);\\n\\t\\t\\t\\tthis._type = LIGHTTYPE_DIRECTIONAL;\\n\\t\\t\\t\\tthis._color = new Color(0.8, 0.8, 0.8);\\n\\t\\t\\t\\tthis._intensity = 1;\\n\\t\\t\\t\\tthis._affectSpecularity = true;\\n\\t\\t\\t\\tthis._luminance = 0;\\n\\t\\t\\t\\tthis._castShadows = false;\\n\\t\\t\\t\\tthis._enabled = false;\\n\\t\\t\\t\\tthis._mask = MASK_AFFECT_DYNAMIC;\\n\\t\\t\\t\\tthis.isStatic = false;\\n\\t\\t\\t\\tthis.key = 0;\\n\\t\\t\\t\\tthis.bakeDir = true;\\n\\t\\t\\t\\tthis.bakeNumSamples = 1;\\n\\t\\t\\t\\tthis.bakeArea = 0;\\n\\t\\t\\t\\tthis.attenuationStart = 10;\\n\\t\\t\\t\\tthis.attenuationEnd = 10;\\n\\t\\t\\t\\tthis._falloffMode = LIGHTFALLOFF_LINEAR;\\n\\t\\t\\t\\tthis._shadowType = SHADOW_PCF3_32F;\\n\\t\\t\\t\\tthis._vsmBlurSize = 11;\\n\\t\\t\\t\\tthis.vsmBlurMode = BLUR_GAUSSIAN;\\n\\t\\t\\t\\tthis.vsmBias = 0.01 * 0.25;\\n\\t\\t\\t\\tthis._cookie = null;\\n\\t\\t\\t\\tthis.cookieIntensity = 1;\\n\\t\\t\\t\\tthis._cookieFalloff = true;\\n\\t\\t\\t\\tthis._cookieChannel = 'rgb';\\n\\t\\t\\t\\tthis._cookieTransform = null;\\n\\t\\t\\t\\tthis._cookieTransformUniform = new Float32Array(4);\\n\\t\\t\\t\\tthis._cookieOffset = null;\\n\\t\\t\\t\\tthis._cookieOffsetUniform = new Float32Array(2);\\n\\t\\t\\t\\tthis._cookieTransformSet = false;\\n\\t\\t\\t\\tthis._cookieOffsetSet = false;\\n\\t\\t\\t\\tthis._innerConeAngle = 40;\\n\\t\\t\\t\\tthis._outerConeAngle = 45;\\n\\t\\t\\t\\tthis.cascades = null;\\n\\t\\t\\t\\tthis._shadowMatrixPalette = null;\\n\\t\\t\\t\\tthis._shadowCascadeDistances = null;\\n\\t\\t\\t\\tthis.numCascades = 1;\\n\\t\\t\\t\\tthis._cascadeBlend = 0;\\n\\t\\t\\t\\tthis.cascadeDistribution = 0.5;\\n\\t\\t\\t\\tthis._shape = LIGHTSHAPE_PUNCTUAL;\\n\\t\\t\\t\\tthis._colorLinear = new Float32Array(3);\\n\\t\\t\\t\\tthis._updateLinearColor();\\n\\t\\t\\t\\tthis._position = new Vec3(0, 0, 0);\\n\\t\\t\\t\\tthis._direction = new Vec3(0, 0, 0);\\n\\t\\t\\t\\tthis._innerConeAngleCos = Math.cos(this._innerConeAngle * math.DEG_TO_RAD);\\n\\t\\t\\t\\tthis._updateOuterAngle(this._outerConeAngle);\\n\\t\\t\\t\\tthis._usePhysicalUnits = undefined;\\n\\t\\t\\t\\tthis._shadowMap = null;\\n\\t\\t\\t\\tthis._shadowRenderParams = [];\\n\\t\\t\\t\\tthis._shadowCameraParams = [];\\n\\t\\t\\t\\tthis.shadowDistance = 40;\\n\\t\\t\\t\\tthis._shadowResolution = 1024;\\n\\t\\t\\t\\tthis._shadowBias = -5e-4;\\n\\t\\t\\t\\tthis._shadowIntensity = 1.0;\\n\\t\\t\\t\\tthis._normalOffsetBias = 0.0;\\n\\t\\t\\t\\tthis.shadowUpdateMode = SHADOWUPDATE_REALTIME;\\n\\t\\t\\t\\tthis.shadowUpdateOverrides = null;\\n\\t\\t\\t\\tthis._isVsm = false;\\n\\t\\t\\t\\tthis._isPcf = true;\\n\\t\\t\\t\\tthis._softShadowParams = new Float32Array(4);\\n\\t\\t\\t\\tthis.shadowSamples = 16;\\n\\t\\t\\t\\tthis.shadowBlockerSamples = 16;\\n\\t\\t\\t\\tthis.penumbraSize = 1.0;\\n\\t\\t\\t\\tthis.penumbraFalloff = 1.0;\\n\\t\\t\\t\\tthis._cookieMatrix = null;\\n\\t\\t\\t\\tthis._atlasViewport = null;\\n\\t\\t\\t\\tthis.atlasViewportAllocated = false;\\n\\t\\t\\t\\tthis.atlasVersion = 0;\\n\\t\\t\\t\\tthis.atlasSlotIndex = 0;\\n\\t\\t\\t\\tthis.atlasSlotUpdated = false;\\n\\t\\t\\t\\tthis._node = null;\\n\\t\\t\\t\\tthis._renderData = [];\\n\\t\\t\\t\\tthis.visibleThisFrame = false;\\n\\t\\t\\t\\tthis.maxScreenSize = 0;\\n\\t\\t\\t\\tthis._updateShadowBias();\\n\\t\\t}\\n}\\n\\nclass LightingParams {\\n\\t\\tapplySettings(render) {\\n\\t\\t\\t\\tthis.shadowsEnabled = render.lightingShadowsEnabled ?? this.shadowsEnabled;\\n\\t\\t\\t\\tthis.cookiesEnabled = render.lightingCookiesEnabled ?? this.cookiesEnabled;\\n\\t\\t\\t\\tthis.areaLightsEnabled = render.lightingAreaLightsEnabled ?? this.areaLightsEnabled;\\n\\t\\t\\t\\tthis.shadowAtlasResolution = render.lightingShadowAtlasResolution ?? this.shadowAtlasResolution;\\n\\t\\t\\t\\tthis.cookieAtlasResolution = render.lightingCookieAtlasResolution ?? this.cookieAtlasResolution;\\n\\t\\t\\t\\tthis.maxLightsPerCell = render.lightingMaxLightsPerCell ?? this.maxLightsPerCell;\\n\\t\\t\\t\\tthis.shadowType = render.lightingShadowType ?? this.shadowType;\\n\\t\\t\\t\\tif (render.lightingCells) {\\n\\t\\t\\t\\t\\t\\tthis.cells = new Vec3(render.lightingCells);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tset cells(value) {\\n\\t\\t\\t\\tthis._cells.copy(value);\\n\\t\\t}\\n\\t\\tget cells() {\\n\\t\\t\\t\\treturn this._cells;\\n\\t\\t}\\n\\t\\tset maxLightsPerCell(value) {\\n\\t\\t\\t\\tthis._maxLightsPerCell = math.clamp(value, 1, 255);\\n\\t\\t}\\n\\t\\tget maxLightsPerCell() {\\n\\t\\t\\t\\treturn this._maxLightsPerCell;\\n\\t\\t}\\n\\t\\tset cookieAtlasResolution(value) {\\n\\t\\t\\t\\tthis._cookieAtlasResolution = math.clamp(value, 32, this._maxTextureSize);\\n\\t\\t}\\n\\t\\tget cookieAtlasResolution() {\\n\\t\\t\\t\\treturn this._cookieAtlasResolution;\\n\\t\\t}\\n\\t\\tset shadowAtlasResolution(value) {\\n\\t\\t\\t\\tthis._shadowAtlasResolution = math.clamp(value, 32, this._maxTextureSize);\\n\\t\\t}\\n\\t\\tget shadowAtlasResolution() {\\n\\t\\t\\t\\treturn this._shadowAtlasResolution;\\n\\t\\t}\\n\\t\\tset shadowType(value) {\\n\\t\\t\\t\\tif (this._shadowType !== value) {\\n\\t\\t\\t\\t\\t\\tthis._shadowType = value;\\n\\t\\t\\t\\t\\t\\tthis._dirtyLightsFnc();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget shadowType() {\\n\\t\\t\\t\\treturn this._shadowType;\\n\\t\\t}\\n\\t\\tset cookiesEnabled(value) {\\n\\t\\t\\t\\tif (this._cookiesEnabled !== value) {\\n\\t\\t\\t\\t\\t\\tthis._cookiesEnabled = value;\\n\\t\\t\\t\\t\\t\\tthis._dirtyLightsFnc();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget cookiesEnabled() {\\n\\t\\t\\t\\treturn this._cookiesEnabled;\\n\\t\\t}\\n\\t\\tset areaLightsEnabled(value) {\\n\\t\\t\\t\\tif (this._supportsAreaLights) {\\n\\t\\t\\t\\t\\t\\tif (this._areaLightsEnabled !== value) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._areaLightsEnabled = value;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._dirtyLightsFnc();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget areaLightsEnabled() {\\n\\t\\t\\t\\treturn this._areaLightsEnabled;\\n\\t\\t}\\n\\t\\tset shadowsEnabled(value) {\\n\\t\\t\\t\\tif (this._shadowsEnabled !== value) {\\n\\t\\t\\t\\t\\t\\tthis._shadowsEnabled = value;\\n\\t\\t\\t\\t\\t\\tthis._dirtyLightsFnc();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget shadowsEnabled() {\\n\\t\\t\\t\\treturn this._shadowsEnabled;\\n\\t\\t}\\n\\t\\tconstructor(supportsAreaLights, maxTextureSize, dirtyLightsFnc){\\n\\t\\t\\t\\tthis._areaLightsEnabled = false;\\n\\t\\t\\t\\tthis._cells = new Vec3(10, 3, 10);\\n\\t\\t\\t\\tthis._maxLightsPerCell = 255;\\n\\t\\t\\t\\tthis._shadowsEnabled = true;\\n\\t\\t\\t\\tthis._shadowType = SHADOW_PCF3_32F;\\n\\t\\t\\t\\tthis._shadowAtlasResolution = 2048;\\n\\t\\t\\t\\tthis._cookiesEnabled = false;\\n\\t\\t\\t\\tthis._cookieAtlasResolution = 2048;\\n\\t\\t\\t\\tthis.atlasSplit = null;\\n\\t\\t\\t\\tthis._supportsAreaLights = supportsAreaLights;\\n\\t\\t\\t\\tthis._maxTextureSize = maxTextureSize;\\n\\t\\t\\t\\tthis._dirtyLightsFnc = dirtyLightsFnc;\\n\\t\\t}\\n}\\n\\nclass MorphInstance {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.shader = null;\\n\\t\\t\\t\\tconst morph = this.morph;\\n\\t\\t\\t\\tif (morph) {\\n\\t\\t\\t\\t\\t\\tthis.morph = null;\\n\\t\\t\\t\\t\\t\\tmorph.decRefCount();\\n\\t\\t\\t\\t\\t\\tif (morph.refCount < 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmorph.destroy();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.rtPositions?.destroy();\\n\\t\\t\\t\\tthis.rtPositions = null;\\n\\t\\t\\t\\tthis.texturePositions?.destroy();\\n\\t\\t\\t\\tthis.texturePositions = null;\\n\\t\\t\\t\\tthis.rtNormals?.destroy();\\n\\t\\t\\t\\tthis.rtNormals = null;\\n\\t\\t\\t\\tthis.textureNormals?.destroy();\\n\\t\\t\\t\\tthis.textureNormals = null;\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\treturn new MorphInstance(this.morph);\\n\\t\\t}\\n\\t\\t_getWeightIndex(key) {\\n\\t\\t\\t\\tif (typeof key === 'string') {\\n\\t\\t\\t\\t\\t\\tconst index = this._weightMap.get(key);\\n\\t\\t\\t\\t\\t\\treturn index;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn key;\\n\\t\\t}\\n\\t\\tgetWeight(key) {\\n\\t\\t\\t\\tconst index = this._getWeightIndex(key);\\n\\t\\t\\t\\treturn this._weights[index];\\n\\t\\t}\\n\\t\\tsetWeight(key, weight) {\\n\\t\\t\\t\\tconst index = this._getWeightIndex(key);\\n\\t\\t\\t\\tthis._weights[index] = weight;\\n\\t\\t\\t\\tthis._dirty = true;\\n\\t\\t}\\n\\t\\t_createShader(maxCount) {\\n\\t\\t\\t\\tconst defines = new Map();\\n\\t\\t\\t\\tdefines.set('{MORPH_TEXTURE_MAX_COUNT}', maxCount);\\n\\t\\t\\t\\tif (this.morph.intRenderFormat) defines.set('MORPH_INT', '');\\n\\t\\t\\t\\tconst outputType = this.morph.intRenderFormat ? 'uvec4' : 'vec4';\\n\\t\\t\\t\\treturn ShaderUtils.createShader(this.device, {\\n\\t\\t\\t\\t\\t\\tuniqueName: `TextureMorphShader_${maxCount}-${this.morph.intRenderFormat ? 'int' : 'float'}`,\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tvertexChunk: 'morphVS',\\n\\t\\t\\t\\t\\t\\tfragmentChunk: 'morphPS',\\n\\t\\t\\t\\t\\t\\tfragmentDefines: defines,\\n\\t\\t\\t\\t\\t\\tfragmentOutputTypes: [\\n\\t\\t\\t\\t\\t\\t\\t\\toutputType\\n\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\t_updateTextureRenderTarget(renderTarget, activeCount, isPos) {\\n\\t\\t\\t\\tconst { morph, device } = this;\\n\\t\\t\\t\\tthis.setAabbUniforms(isPos);\\n\\t\\t\\t\\tthis.morphTextureId.setValue(isPos ? morph.targetsTexturePositions : morph.targetsTextureNormals);\\n\\t\\t\\t\\tdevice.setBlendState(BlendState.NOBLEND);\\n\\t\\t\\t\\tthis.countId.setValue(activeCount);\\n\\t\\t\\t\\tthis.morphFactor.setValue(this._shaderMorphWeights);\\n\\t\\t\\t\\tthis.morphIndex.setValue(this._shaderMorphIndex);\\n\\t\\t\\t\\tdrawQuadWithShader(device, renderTarget, this.shader);\\n\\t\\t}\\n\\t\\t_updateTextureMorph(activeCount) {\\n\\t\\t\\t\\tthis.device;\\n\\t\\t\\t\\tif (activeCount > 0 || !this.zeroTextures) {\\n\\t\\t\\t\\t\\t\\tif (this.rtPositions) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._updateTextureRenderTarget(this.rtPositions, activeCount, true);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.rtNormals) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._updateTextureRenderTarget(this.rtNormals, activeCount, false);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.zeroTextures = activeCount === 0;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetAabbUniforms(isPos = true) {\\n\\t\\t\\t\\tthis.aabbSizeId.setValue(isPos ? this._aabbSize : this._aabbNrmSize);\\n\\t\\t\\t\\tthis.aabbMinId.setValue(isPos ? this._aabbMin : this._aabbNrmMin);\\n\\t\\t}\\n\\t\\tprepareRendering(device) {\\n\\t\\t\\t\\tthis.setAabbUniforms();\\n\\t\\t}\\n\\t\\tupdate() {\\n\\t\\t\\t\\tthis._dirty = false;\\n\\t\\t\\t\\tconst targets = this.morph._targets;\\n\\t\\t\\t\\tconst epsilon = 0.00001;\\n\\t\\t\\t\\tconst weights = this._shaderMorphWeights;\\n\\t\\t\\t\\tconst indices = this._shaderMorphIndex;\\n\\t\\t\\t\\tlet activeCount = 0;\\n\\t\\t\\t\\tfor(let i = 0; i < targets.length; i++){\\n\\t\\t\\t\\t\\t\\tif (Math.abs(this.getWeight(i)) > epsilon) {\\n\\t\\t\\t\\t\\t\\t\\t\\tweights[activeCount] = this.getWeight(i);\\n\\t\\t\\t\\t\\t\\t\\t\\tindices[activeCount] = i;\\n\\t\\t\\t\\t\\t\\t\\t\\tactiveCount++;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._updateTextureMorph(activeCount);\\n\\t\\t}\\n\\t\\tconstructor(morph){\\n\\t\\t\\t\\tthis.morph = morph;\\n\\t\\t\\t\\tmorph.incRefCount();\\n\\t\\t\\t\\tthis.device = morph.device;\\n\\t\\t\\t\\tconst maxNumTargets = morph._targets.length;\\n\\t\\t\\t\\tthis.shader = this._createShader(maxNumTargets);\\n\\t\\t\\t\\tthis._weights = [];\\n\\t\\t\\t\\tthis._weightMap = new Map();\\n\\t\\t\\t\\tfor(let v = 0; v < morph._targets.length; v++){\\n\\t\\t\\t\\t\\t\\tconst target = morph._targets[v];\\n\\t\\t\\t\\t\\t\\tif (target.name) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._weightMap.set(target.name, v);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.setWeight(v, target.defaultWeight);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._shaderMorphWeights = new Float32Array(maxNumTargets);\\n\\t\\t\\t\\tthis._shaderMorphIndex = new Uint32Array(maxNumTargets);\\n\\t\\t\\t\\tconst createRT = (name, textureVar)=>{\\n\\t\\t\\t\\t\\t\\tthis[textureVar] = morph._createTexture(name, morph._renderTextureFormat);\\n\\t\\t\\t\\t\\t\\treturn new RenderTarget({\\n\\t\\t\\t\\t\\t\\t\\t\\tcolorBuffer: this[textureVar],\\n\\t\\t\\t\\t\\t\\t\\t\\tdepth: false\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (morph.morphPositions) {\\n\\t\\t\\t\\t\\t\\tthis.rtPositions = createRT('MorphRTPos', 'texturePositions');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (morph.morphNormals) {\\n\\t\\t\\t\\t\\t\\tthis.rtNormals = createRT('MorphRTNrm', 'textureNormals');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._textureParams = new Float32Array([\\n\\t\\t\\t\\t\\t\\tmorph.morphTextureWidth,\\n\\t\\t\\t\\t\\t\\tmorph.morphTextureHeight\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tconst halfSize = morph.aabb.halfExtents;\\n\\t\\t\\t\\tthis._aabbSize = new Float32Array([\\n\\t\\t\\t\\t\\t\\thalfSize.x * 4,\\n\\t\\t\\t\\t\\t\\thalfSize.y * 4,\\n\\t\\t\\t\\t\\t\\thalfSize.z * 4\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tconst min = morph.aabb.getMin();\\n\\t\\t\\t\\tthis._aabbMin = new Float32Array([\\n\\t\\t\\t\\t\\t\\tmin.x * 2,\\n\\t\\t\\t\\t\\t\\tmin.y * 2,\\n\\t\\t\\t\\t\\t\\tmin.z * 2\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tthis._aabbNrmSize = new Float32Array([\\n\\t\\t\\t\\t\\t\\t2,\\n\\t\\t\\t\\t\\t\\t2,\\n\\t\\t\\t\\t\\t\\t2\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tthis._aabbNrmMin = new Float32Array([\\n\\t\\t\\t\\t\\t\\t-1,\\n\\t\\t\\t\\t\\t\\t-1,\\n\\t\\t\\t\\t\\t\\t-1\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tthis.aabbSizeId = this.device.scope.resolve('aabbSize');\\n\\t\\t\\t\\tthis.aabbMinId = this.device.scope.resolve('aabbMin');\\n\\t\\t\\t\\tthis.morphTextureId = this.device.scope.resolve('morphTexture');\\n\\t\\t\\t\\tthis.morphFactor = this.device.scope.resolve('morphFactor[0]');\\n\\t\\t\\t\\tthis.morphIndex = this.device.scope.resolve('morphIndex[0]');\\n\\t\\t\\t\\tthis.countId = this.device.scope.resolve('count');\\n\\t\\t\\t\\tthis.zeroTextures = false;\\n\\t\\t}\\n}\\n\\nclass Model {\\n\\t\\tgetGraph() {\\n\\t\\t\\t\\treturn this.graph;\\n\\t\\t}\\n\\t\\tsetGraph(graph) {\\n\\t\\t\\t\\tthis.graph = graph;\\n\\t\\t}\\n\\t\\tgetCameras() {\\n\\t\\t\\t\\treturn this.cameras;\\n\\t\\t}\\n\\t\\tsetCameras(cameras) {\\n\\t\\t\\t\\tthis.cameras = cameras;\\n\\t\\t}\\n\\t\\tgetLights() {\\n\\t\\t\\t\\treturn this.lights;\\n\\t\\t}\\n\\t\\tsetLights(lights) {\\n\\t\\t\\t\\tthis.lights = lights;\\n\\t\\t}\\n\\t\\tgetMaterials() {\\n\\t\\t\\t\\tconst materials = [];\\n\\t\\t\\t\\tfor(let i = 0; i < this.meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\tconst meshInstance = this.meshInstances[i];\\n\\t\\t\\t\\t\\t\\tif (materials.indexOf(meshInstance.material) === -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmaterials.push(meshInstance.material);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn materials;\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst srcNodes = [];\\n\\t\\t\\t\\tconst cloneNodes = [];\\n\\t\\t\\t\\tconst _duplicate = function(node) {\\n\\t\\t\\t\\t\\t\\tconst newNode = node.clone();\\n\\t\\t\\t\\t\\t\\tsrcNodes.push(node);\\n\\t\\t\\t\\t\\t\\tcloneNodes.push(newNode);\\n\\t\\t\\t\\t\\t\\tfor(let idx = 0; idx < node._children.length; idx++){\\n\\t\\t\\t\\t\\t\\t\\t\\tnewNode.addChild(_duplicate(node._children[idx]));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn newNode;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst cloneGraph = _duplicate(this.graph);\\n\\t\\t\\t\\tconst cloneMeshInstances = [];\\n\\t\\t\\t\\tconst cloneSkinInstances = [];\\n\\t\\t\\t\\tconst cloneMorphInstances = [];\\n\\t\\t\\t\\tfor(let i = 0; i < this.skinInstances.length; i++){\\n\\t\\t\\t\\t\\t\\tconst skin = this.skinInstances[i].skin;\\n\\t\\t\\t\\t\\t\\tconst cloneSkinInstance = new SkinInstance(skin);\\n\\t\\t\\t\\t\\t\\tconst bones = [];\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j < skin.boneNames.length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst boneName = skin.boneNames[j];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst bone = cloneGraph.findByName(boneName);\\n\\t\\t\\t\\t\\t\\t\\t\\tbones.push(bone);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcloneSkinInstance.bones = bones;\\n\\t\\t\\t\\t\\t\\tcloneSkinInstances.push(cloneSkinInstance);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < this.morphInstances.length; i++){\\n\\t\\t\\t\\t\\t\\tconst morph = this.morphInstances[i].morph;\\n\\t\\t\\t\\t\\t\\tconst cloneMorphInstance = new MorphInstance(morph);\\n\\t\\t\\t\\t\\t\\tcloneMorphInstances.push(cloneMorphInstance);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < this.meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\tconst meshInstance = this.meshInstances[i];\\n\\t\\t\\t\\t\\t\\tconst nodeIndex = srcNodes.indexOf(meshInstance.node);\\n\\t\\t\\t\\t\\t\\tconst cloneMeshInstance = new MeshInstance(meshInstance.mesh, meshInstance.material, cloneNodes[nodeIndex]);\\n\\t\\t\\t\\t\\t\\tif (meshInstance.skinInstance) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst skinInstanceIndex = this.skinInstances.indexOf(meshInstance.skinInstance);\\n\\t\\t\\t\\t\\t\\t\\t\\tcloneMeshInstance.skinInstance = cloneSkinInstances[skinInstanceIndex];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (meshInstance.morphInstance) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst morphInstanceIndex = this.morphInstances.indexOf(meshInstance.morphInstance);\\n\\t\\t\\t\\t\\t\\t\\t\\tcloneMeshInstance.morphInstance = cloneMorphInstances[morphInstanceIndex];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcloneMeshInstances.push(cloneMeshInstance);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst clone = new Model();\\n\\t\\t\\t\\tclone.graph = cloneGraph;\\n\\t\\t\\t\\tclone.meshInstances = cloneMeshInstances;\\n\\t\\t\\t\\tclone.skinInstances = cloneSkinInstances;\\n\\t\\t\\t\\tclone.morphInstances = cloneMorphInstances;\\n\\t\\t\\t\\tclone.getGraph().syncHierarchy();\\n\\t\\t\\t\\treturn clone;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tconst meshInstances = this.meshInstances;\\n\\t\\t\\t\\tfor(let i = 0; i < meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\tmeshInstances[i].destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.meshInstances.length = 0;\\n\\t\\t}\\n\\t\\tgenerateWireframe() {\\n\\t\\t\\t\\tMeshInstance._prepareRenderStyleForArray(this.meshInstances, RENDERSTYLE_WIREFRAME);\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.graph = null;\\n\\t\\t\\t\\tthis.meshInstances = [];\\n\\t\\t\\t\\tthis.skinInstances = [];\\n\\t\\t\\t\\tthis.morphInstances = [];\\n\\t\\t\\t\\tthis.cameras = [];\\n\\t\\t\\t\\tthis.lights = [];\\n\\t\\t\\t\\tthis._shadersVersion = 0;\\n\\t\\t\\t\\tthis._immutable = false;\\n\\t\\t}\\n}\\n\\nclass Morph extends RefCountedObject {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.vertexBufferIds?.destroy();\\n\\t\\t\\t\\tthis.vertexBufferIds = null;\\n\\t\\t\\t\\tthis.targetsTexturePositions?.destroy();\\n\\t\\t\\t\\tthis.targetsTexturePositions = null;\\n\\t\\t\\t\\tthis.targetsTextureNormals?.destroy();\\n\\t\\t\\t\\tthis.targetsTextureNormals = null;\\n\\t\\t}\\n\\t\\tget aabb() {\\n\\t\\t\\t\\tif (!this._aabb) {\\n\\t\\t\\t\\t\\t\\tconst min = new Vec3();\\n\\t\\t\\t\\t\\t\\tconst max = new Vec3();\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._targets.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst targetAabb = this._targets[i].aabb;\\n\\t\\t\\t\\t\\t\\t\\t\\tmin.min(targetAabb.getMin());\\n\\t\\t\\t\\t\\t\\t\\t\\tmax.max(targetAabb.getMax());\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._aabb = new BoundingBox();\\n\\t\\t\\t\\t\\t\\tthis._aabb.setMinMax(min, max);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._aabb;\\n\\t\\t}\\n\\t\\tget morphPositions() {\\n\\t\\t\\t\\treturn this._morphPositions;\\n\\t\\t}\\n\\t\\tget morphNormals() {\\n\\t\\t\\t\\treturn this._morphNormals;\\n\\t\\t}\\n\\t\\t_init() {\\n\\t\\t\\t\\tthis._initTextureBased();\\n\\t\\t\\t\\tfor(let i = 0; i < this._targets.length; i++){\\n\\t\\t\\t\\t\\t\\tthis._targets[i]._postInit();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_findSparseSet(deltaArrays, ids, usedDataIndices) {\\n\\t\\t\\t\\tlet freeIndex = 1;\\n\\t\\t\\t\\tconst dataCount = deltaArrays[0].length;\\n\\t\\t\\t\\tfor(let v = 0; v < dataCount; v += 3){\\n\\t\\t\\t\\t\\t\\tlet vertexUsed = false;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < deltaArrays.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst data = deltaArrays[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (data[v] !== 0 || data[v + 1] !== 0 || data[v + 2] !== 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvertexUsed = true;\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tif (vertexUsed) {\\n\\t\\t\\t\\t\\t\\t\\t\\tids.push(freeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\tusedDataIndices.push(v / 3);\\n\\t\\t\\t\\t\\t\\t\\t\\tfreeIndex++;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tids.push(0);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn freeIndex;\\n\\t\\t}\\n\\t\\t_initTextureBased() {\\n\\t\\t\\t\\tconst deltaArrays = [], deltaInfos = [];\\n\\t\\t\\t\\tconst targets = this._targets;\\n\\t\\t\\t\\tfor(let i = 0; i < targets.length; i++){\\n\\t\\t\\t\\t\\t\\tconst target = targets[i];\\n\\t\\t\\t\\t\\t\\tif (target.options.deltaPositions) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdeltaArrays.push(target.options.deltaPositions);\\n\\t\\t\\t\\t\\t\\t\\t\\tdeltaInfos.push(true);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (target.options.deltaNormals) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdeltaArrays.push(target.options.deltaNormals);\\n\\t\\t\\t\\t\\t\\t\\t\\tdeltaInfos.push(false);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst ids = [], usedDataIndices = [];\\n\\t\\t\\t\\tconst freeIndex = this._findSparseSet(deltaArrays, ids, usedDataIndices);\\n\\t\\t\\t\\tconst maxTextureSize = this.device.maxTextureSize;\\n\\t\\t\\t\\tlet morphTextureWidth = Math.ceil(Math.sqrt(freeIndex));\\n\\t\\t\\t\\tmorphTextureWidth = Math.min(morphTextureWidth, maxTextureSize);\\n\\t\\t\\t\\tconst morphTextureHeight = Math.ceil(freeIndex / morphTextureWidth);\\n\\t\\t\\t\\tif (morphTextureHeight > maxTextureSize) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.morphTextureWidth = morphTextureWidth;\\n\\t\\t\\t\\tthis.morphTextureHeight = morphTextureHeight;\\n\\t\\t\\t\\tlet halfFloat = false;\\n\\t\\t\\t\\tconst float2Half = FloatPacking.float2Half;\\n\\t\\t\\t\\tif (this._textureFormat === PIXELFORMAT_RGBA16F) {\\n\\t\\t\\t\\t\\t\\thalfFloat = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst texturesDataPositions = [];\\n\\t\\t\\t\\tconst texturesDataNormals = [];\\n\\t\\t\\t\\tconst textureDataSize = morphTextureWidth * morphTextureHeight * 4;\\n\\t\\t\\t\\tfor(let i = 0; i < deltaArrays.length; i++){\\n\\t\\t\\t\\t\\t\\tconst data = deltaArrays[i];\\n\\t\\t\\t\\t\\t\\tconst textureData = this._textureFormat === PIXELFORMAT_RGBA16F ? new Uint16Array(textureDataSize) : new Float32Array(textureDataSize);\\n\\t\\t\\t\\t\\t\\t(deltaInfos[i] ? texturesDataPositions : texturesDataNormals).push(textureData);\\n\\t\\t\\t\\t\\t\\tif (halfFloat) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let v = 0; v < usedDataIndices.length; v++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst index = usedDataIndices[v] * 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst dstIndex = v * 4 + 4;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttextureData[dstIndex] = float2Half(data[index]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttextureData[dstIndex + 1] = float2Half(data[index + 1]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttextureData[dstIndex + 2] = float2Half(data[index + 2]);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let v = 0; v < usedDataIndices.length; v++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst index = usedDataIndices[v] * 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst dstIndex = v * 4 + 4;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttextureData[dstIndex] = data[index];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttextureData[dstIndex + 1] = data[index + 1];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttextureData[dstIndex + 2] = data[index + 2];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (texturesDataPositions.length > 0) {\\n\\t\\t\\t\\t\\t\\tthis.targetsTexturePositions = this._createTexture('MorphPositionsTexture', this._textureFormat, targets.length, [\\n\\t\\t\\t\\t\\t\\t\\t\\ttexturesDataPositions\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (texturesDataNormals.length > 0) {\\n\\t\\t\\t\\t\\t\\tthis.targetsTextureNormals = this._createTexture('MorphNormalsTexture', this._textureFormat, targets.length, [\\n\\t\\t\\t\\t\\t\\t\\t\\ttexturesDataNormals\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst formatDesc = [\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tsemantic: SEMANTIC_ATTR15,\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponents: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\ttype: TYPE_UINT32,\\n\\t\\t\\t\\t\\t\\t\\t\\tasInt: true\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.vertexBufferIds = new VertexBuffer(this.device, new VertexFormat(this.device, formatDesc, ids.length), ids.length, {\\n\\t\\t\\t\\t\\t\\tdata: new Uint32Array(ids)\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tget targets() {\\n\\t\\t\\t\\treturn this._targets;\\n\\t\\t}\\n\\t\\t_updateMorphFlags() {\\n\\t\\t\\t\\tthis._morphPositions = false;\\n\\t\\t\\t\\tthis._morphNormals = false;\\n\\t\\t\\t\\tfor(let i = 0; i < this._targets.length; i++){\\n\\t\\t\\t\\t\\t\\tconst target = this._targets[i];\\n\\t\\t\\t\\t\\t\\tif (target.morphPositions) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._morphPositions = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (target.morphNormals) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._morphNormals = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_createTexture(name, format, arrayLength, levels) {\\n\\t\\t\\t\\treturn new Texture(this.device, {\\n\\t\\t\\t\\t\\t\\tlevels: levels,\\n\\t\\t\\t\\t\\t\\tarrayLength: arrayLength,\\n\\t\\t\\t\\t\\t\\twidth: this.morphTextureWidth,\\n\\t\\t\\t\\t\\t\\theight: this.morphTextureHeight,\\n\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\tcubemap: false,\\n\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\tname: name\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tconstructor(targets, graphicsDevice, { preferHighPrecision = false } = {}){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t\\t\\tconst device = graphicsDevice;\\n\\t\\t\\t\\tthis.preferHighPrecision = preferHighPrecision;\\n\\t\\t\\t\\tthis._targets = targets.slice();\\n\\t\\t\\t\\tconst renderableHalf = device.textureHalfFloatRenderable ? PIXELFORMAT_RGBA16F : undefined;\\n\\t\\t\\t\\tconst renderableFloat = device.textureFloatRenderable ? PIXELFORMAT_RGBA32F : undefined;\\n\\t\\t\\t\\tthis._renderTextureFormat = this.preferHighPrecision ? renderableFloat ?? renderableHalf : renderableHalf ?? renderableFloat;\\n\\t\\t\\t\\tthis._renderTextureFormat = this._renderTextureFormat ?? PIXELFORMAT_RGBA16U;\\n\\t\\t\\t\\tthis.intRenderFormat = isIntegerPixelFormat(this._renderTextureFormat);\\n\\t\\t\\t\\tthis._textureFormat = this.preferHighPrecision ? PIXELFORMAT_RGBA32F : PIXELFORMAT_RGBA16F;\\n\\t\\t\\t\\tthis._init();\\n\\t\\t\\t\\tthis._updateMorphFlags();\\n\\t\\t}\\n}\\n\\nclass MorphTarget {\\n\\t\\tget name() {\\n\\t\\t\\t\\treturn this._name;\\n\\t\\t}\\n\\t\\tget defaultWeight() {\\n\\t\\t\\t\\treturn this._defaultWeight;\\n\\t\\t}\\n\\t\\tget aabb() {\\n\\t\\t\\t\\tif (!this._aabb) {\\n\\t\\t\\t\\t\\t\\tthis._aabb = new BoundingBox();\\n\\t\\t\\t\\t\\t\\tif (this.deltaPositions) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._aabb.compute(this.deltaPositions);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._aabb;\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\treturn new MorphTarget(this.options);\\n\\t\\t}\\n\\t\\t_postInit() {\\n\\t\\t\\t\\tif (!this.options.preserveData) {\\n\\t\\t\\t\\t\\t\\tthis.options = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.used = true;\\n\\t\\t}\\n\\t\\tconstructor(options){\\n\\t\\t\\t\\tthis.used = false;\\n\\t\\t\\t\\tthis.options = options;\\n\\t\\t\\t\\tthis._name = options.name;\\n\\t\\t\\t\\tthis._defaultWeight = options.defaultWeight || 0;\\n\\t\\t\\t\\tthis._aabb = options.aabb;\\n\\t\\t\\t\\tthis.deltaPositions = options.deltaPositions;\\n\\t\\t\\t\\tthis.morphPositions = !!options.deltaPositions;\\n\\t\\t\\t\\tthis.morphNormals = !!options.deltaNormals;\\n\\t\\t}\\n}\\n\\nclass ShaderGeneratorShader extends ShaderGenerator {\\n\\t\\tgenerateKey(options) {\\n\\t\\t\\t\\tconst desc = options.shaderDesc;\\n\\t\\t\\t\\tconst vsHashGLSL = desc.vertexGLSL ? hashCode(desc.vertexGLSL) : 0;\\n\\t\\t\\t\\tconst fsHashGLSL = desc.fragmentGLSL ? hashCode(desc.fragmentGLSL) : 0;\\n\\t\\t\\t\\tconst vsHashWGSL = desc.vertexWGSL ? hashCode(desc.vertexWGSL) : 0;\\n\\t\\t\\t\\tconst fsHashWGSL = desc.fragmentWGSL ? hashCode(desc.fragmentWGSL) : 0;\\n\\t\\t\\t\\tconst definesHash = ShaderGenerator.definesHash(options.defines);\\n\\t\\t\\t\\tconst chunksKey = options.shaderChunks?.key ?? '';\\n\\t\\t\\t\\tlet key = `${desc.uniqueName}_${definesHash}_${vsHashGLSL}_${fsHashGLSL}_${vsHashWGSL}_${fsHashWGSL}_${chunksKey}`;\\n\\t\\t\\t\\tif (options.skin) key += '_skin';\\n\\t\\t\\t\\tif (options.useInstancing) key += '_inst';\\n\\t\\t\\t\\tif (options.useMorphPosition) key += '_morphp';\\n\\t\\t\\t\\tif (options.useMorphNormal) key += '_morphn';\\n\\t\\t\\t\\tif (options.useMorphTextureBasedInt) key += '_morphi';\\n\\t\\t\\t\\treturn key;\\n\\t\\t}\\n\\t\\tcreateAttributesDefinition(definitionOptions, options) {\\n\\t\\t\\t\\tconst srcAttributes = options.shaderDesc.attributes;\\n\\t\\t\\t\\tconst attributes = srcAttributes ? {\\n\\t\\t\\t\\t\\t\\t...srcAttributes\\n\\t\\t\\t\\t} : undefined;\\n\\t\\t\\t\\tif (options.skin) {\\n\\t\\t\\t\\t\\t\\tattributes.vertex_boneWeights = SEMANTIC_BLENDWEIGHT;\\n\\t\\t\\t\\t\\t\\tattributes.vertex_boneIndices = SEMANTIC_BLENDINDICES;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.useMorphPosition || options.useMorphNormal) {\\n\\t\\t\\t\\t\\t\\tattributes.morph_vertex_id = SEMANTIC_ATTR15;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdefinitionOptions.attributes = attributes;\\n\\t\\t}\\n\\t\\tcreateVertexDefinition(definitionOptions, options, sharedIncludes, wgsl) {\\n\\t\\t\\t\\tconst desc = options.shaderDesc;\\n\\t\\t\\t\\tconst includes = new Map(sharedIncludes);\\n\\t\\t\\t\\tincludes.set('transformInstancingVS', '');\\n\\t\\t\\t\\tconst defines = new Map(options.defines);\\n\\t\\t\\t\\tif (options.skin) defines.set('SKIN', true);\\n\\t\\t\\t\\tif (options.useInstancing) defines.set('INSTANCING', true);\\n\\t\\t\\t\\tif (options.useMorphPosition || options.useMorphNormal) {\\n\\t\\t\\t\\t\\t\\tdefines.set('MORPHING', true);\\n\\t\\t\\t\\t\\t\\tif (options.useMorphTextureBasedInt) defines.set('MORPHING_INT', true);\\n\\t\\t\\t\\t\\t\\tif (options.useMorphPosition) defines.set('MORPHING_POSITION', true);\\n\\t\\t\\t\\t\\t\\tif (options.useMorphNormal) defines.set('MORPHING_NORMAL', true);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdefinitionOptions.vertexCode = wgsl ? desc.vertexWGSL : desc.vertexGLSL;\\n\\t\\t\\t\\tdefinitionOptions.vertexIncludes = includes;\\n\\t\\t\\t\\tdefinitionOptions.vertexDefines = defines;\\n\\t\\t}\\n\\t\\tcreateFragmentDefinition(definitionOptions, options, sharedIncludes, wgsl) {\\n\\t\\t\\t\\tconst desc = options.shaderDesc;\\n\\t\\t\\t\\tconst includes = new Map(sharedIncludes);\\n\\t\\t\\t\\tconst defines = new Map(options.defines);\\n\\t\\t\\t\\tdefinitionOptions.fragmentCode = wgsl ? desc.fragmentWGSL : desc.fragmentGLSL;\\n\\t\\t\\t\\tdefinitionOptions.fragmentIncludes = includes;\\n\\t\\t\\t\\tdefinitionOptions.fragmentDefines = defines;\\n\\t\\t}\\n\\t\\tcreateShaderDefinition(device, options) {\\n\\t\\t\\t\\tconst desc = options.shaderDesc;\\n\\t\\t\\t\\tconst wgsl = device.isWebGPU && !!desc.vertexWGSL && !!desc.fragmentWGSL && (options.shaderChunks?.useWGSL ?? true);\\n\\t\\t\\t\\tconst definitionOptions = {\\n\\t\\t\\t\\t\\t\\tname: `ShaderMaterial-${desc.uniqueName}`,\\n\\t\\t\\t\\t\\t\\tshaderLanguage: wgsl ? SHADERLANGUAGE_WGSL : SHADERLANGUAGE_GLSL,\\n\\t\\t\\t\\t\\t\\tfragmentOutputTypes: desc.fragmentOutputTypes,\\n\\t\\t\\t\\t\\t\\tmeshUniformBufferFormat: desc.meshUniformBufferFormat,\\n\\t\\t\\t\\t\\t\\tmeshBindGroupFormat: desc.meshBindGroupFormat\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst shaderLanguage = wgsl ? SHADERLANGUAGE_WGSL : SHADERLANGUAGE_GLSL;\\n\\t\\t\\t\\tconst sharedIncludes = MapUtils.merge(ShaderChunks.get(device, shaderLanguage), options.shaderChunks[shaderLanguage]);\\n\\t\\t\\t\\tthis.createAttributesDefinition(definitionOptions, options);\\n\\t\\t\\t\\tthis.createVertexDefinition(definitionOptions, options, sharedIncludes, wgsl);\\n\\t\\t\\t\\tthis.createFragmentDefinition(definitionOptions, options, sharedIncludes, wgsl);\\n\\t\\t\\t\\treturn ShaderDefinitionUtils.createDefinition(device, definitionOptions);\\n\\t\\t}\\n}\\nconst shaderGeneratorShader = new ShaderGeneratorShader();\\n\\nclass ShaderMaterial extends Material {\\n\\t\\tset shaderDesc(value) {\\n\\t\\t\\t\\tthis._shaderDesc = undefined;\\n\\t\\t\\t\\tif (value) {\\n\\t\\t\\t\\t\\t\\tthis._shaderDesc = {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniqueName: value.uniqueName,\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes: value.attributes,\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentOutputTypes: value.fragmentOutputTypes,\\n\\t\\t\\t\\t\\t\\t\\t\\tvertexGLSL: value.vertexGLSL,\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentGLSL: value.fragmentGLSL,\\n\\t\\t\\t\\t\\t\\t\\t\\tvertexWGSL: value.vertexWGSL,\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentWGSL: value.fragmentWGSL\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tif (value.vertexCode || value.fragmentCode || value.shaderLanguage) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst language = value.shaderLanguage ?? SHADERLANGUAGE_GLSL;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (language === SHADERLANGUAGE_GLSL) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._shaderDesc.vertexGLSL = value.vertexCode;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._shaderDesc.fragmentGLSL = value.fragmentCode;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else if (language === SHADERLANGUAGE_WGSL) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._shaderDesc.vertexWGSL = value.vertexCode;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._shaderDesc.fragmentWGSL = value.fragmentCode;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.clearVariants();\\n\\t\\t}\\n\\t\\tget shaderDesc() {\\n\\t\\t\\t\\treturn this._shaderDesc;\\n\\t\\t}\\n\\t\\tcopy(source) {\\n\\t\\t\\t\\tsuper.copy(source);\\n\\t\\t\\t\\tthis.shaderDesc = source.shaderDesc;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tgetShaderVariant(params) {\\n\\t\\t\\t\\tconst { objDefs } = params;\\n\\t\\t\\t\\tconst options = {\\n\\t\\t\\t\\t\\t\\tdefines: ShaderUtils.getCoreDefines(this, params),\\n\\t\\t\\t\\t\\t\\tskin: (objDefs & SHADERDEF_SKIN) !== 0,\\n\\t\\t\\t\\t\\t\\tuseInstancing: (objDefs & SHADERDEF_INSTANCING) !== 0,\\n\\t\\t\\t\\t\\t\\tuseMorphPosition: (objDefs & SHADERDEF_MORPH_POSITION) !== 0,\\n\\t\\t\\t\\t\\t\\tuseMorphNormal: (objDefs & SHADERDEF_MORPH_NORMAL) !== 0,\\n\\t\\t\\t\\t\\t\\tuseMorphTextureBasedInt: (objDefs & SHADERDEF_MORPH_TEXTURE_BASED_INT) !== 0,\\n\\t\\t\\t\\t\\t\\tpass: params.pass,\\n\\t\\t\\t\\t\\t\\tgamma: params.cameraShaderParams.shaderOutputGamma,\\n\\t\\t\\t\\t\\t\\ttoneMapping: params.cameraShaderParams.toneMapping,\\n\\t\\t\\t\\t\\t\\tfog: params.cameraShaderParams.fog,\\n\\t\\t\\t\\t\\t\\tshaderDesc: this.shaderDesc,\\n\\t\\t\\t\\t\\t\\tshaderChunks: this.shaderChunks\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst processingOptions = new ShaderProcessorOptions(params.viewUniformFormat, params.viewBindGroupFormat, params.vertexFormat);\\n\\t\\t\\t\\tconst library = getProgramLibrary(params.device);\\n\\t\\t\\t\\tlibrary.register('shader-material', shaderGeneratorShader);\\n\\t\\t\\t\\treturn library.getProgram('shader-material', options, processingOptions, this.userId);\\n\\t\\t}\\n\\t\\tconstructor(shaderDesc){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.shaderDesc = shaderDesc;\\n\\t\\t}\\n}\\n\\nvar glslStreamDecl = `\\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 wgslStreamDecl = `\\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 glslStreamOutput = `\\nvoid write{funcName}({returnType} value) {\\n#if {defineGuard}\\n\\tpcFragColor{index} = value;\\n#endif\\n}\\n`;\\n\\nvar wgslStreamOutput = `\\nfn write{funcName}(value: {returnType}) {\\n#if {defineGuard}\\n\\tprocessOutput.{colorSlot} = value;\\n#endif\\n}\\n`;\\n\\nvar gsplatContainerFloatReadVS$1 = `\\nvec3 getCenter() { return loadDataCenter().xyz; }\\nvec4 getColor() { return loadDataColor(); }\\nvec3 getScale() { return loadDataScale().xyz; }\\nvec4 getRotation() { return loadDataRotation(); }\\n`;\\n\\nvar gsplatContainerFloatReadVS = `\\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 glslContainerSimpleRead = `\\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 wgslContainerSimpleRead = `\\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_INDEX = /\\\\{index\\\\}/g;\\nconst RE_COLOR_SLOT = /\\\\{colorSlot\\\\}/g;\\nconst RE_DEFINE_GUARD = /\\\\{defineGuard\\\\}/g;\\nclass GSplatFormat {\\n\\t\\tget hash() {\\n\\t\\t\\t\\tif (this._hash === undefined) {\\n\\t\\t\\t\\t\\t\\tconst streamsStr = serializeStreams(this.streams);\\n\\t\\t\\t\\t\\t\\tconst extraStr = serializeStreams(this._extraStreams);\\n\\t\\t\\t\\t\\t\\tthis._hash = hashCode(streamsStr + extraStr + this._read);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._hash;\\n\\t\\t}\\n\\t\\tget extraStreamsVersion() {\\n\\t\\t\\t\\treturn this._extraStreamsVersion;\\n\\t\\t}\\n\\t\\tget extraStreams() {\\n\\t\\t\\t\\treturn this._extraStreams;\\n\\t\\t}\\n\\t\\tget resourceStreams() {\\n\\t\\t\\t\\tif (this._resourceStreams === null) {\\n\\t\\t\\t\\t\\t\\tthis._resourceStreams = [\\n\\t\\t\\t\\t\\t\\t\\t\\t...this.streams.filter((s)=>s.storage !== GSPLAT_STREAM_INSTANCE),\\n\\t\\t\\t\\t\\t\\t\\t\\t...this._extraStreams.filter((s)=>s.storage !== GSPLAT_STREAM_INSTANCE)\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._resourceStreams;\\n\\t\\t}\\n\\t\\tget instanceStreams() {\\n\\t\\t\\t\\tif (this._instanceStreams === null) {\\n\\t\\t\\t\\t\\t\\tthis._instanceStreams = this._extraStreams.filter((s)=>s.storage === GSPLAT_STREAM_INSTANCE);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._instanceStreams;\\n\\t\\t}\\n\\t\\taddExtraStreams(streams) {\\n\\t\\t\\t\\tif (!streams || streams.length === 0) return;\\n\\t\\t\\t\\tlet added = false;\\n\\t\\t\\t\\tfor (const s of streams){\\n\\t\\t\\t\\t\\t\\tif (this._streamNames.has(s.name)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._extraStreams.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tname: s.name,\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: s.format,\\n\\t\\t\\t\\t\\t\\t\\t\\tstorage: s.storage ?? GSPLAT_STREAM_RESOURCE\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tthis._streamNames.add(s.name);\\n\\t\\t\\t\\t\\t\\tadded = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (added) {\\n\\t\\t\\t\\t\\t\\tthis._extraStreamsVersion++;\\n\\t\\t\\t\\t\\t\\tthis._invalidateCaches();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetInputDeclarations(streamNames) {\\n\\t\\t\\t\\tconst isWebGPU = this._device.isWebGPU;\\n\\t\\t\\t\\tconst template = isWebGPU ? wgslStreamDecl : glslStreamDecl;\\n\\t\\t\\t\\tconst getShaderType = isWebGPU ? getWgslShaderType : getGlslShaderType;\\n\\t\\t\\t\\tconst lines = [];\\n\\t\\t\\t\\tlet streams = [\\n\\t\\t\\t\\t\\t\\t...this.streams,\\n\\t\\t\\t\\t\\t\\t...this._extraStreams\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tif (streamNames) {\\n\\t\\t\\t\\t\\t\\tstreams = streams.filter((s)=>streamNames.includes(s.name));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const stream of streams){\\n\\t\\t\\t\\t\\t\\tconst info = getShaderType(stream.format);\\n\\t\\t\\t\\t\\t\\tconst funcName = stream.name.charAt(0).toUpperCase() + stream.name.slice(1);\\n\\t\\t\\t\\t\\t\\tconst decl = template.replace(RE_NAME, stream.name).replace(RE_SAMPLER, info.sampler ?? '').replace(RE_TEXTURE_TYPE, info.textureType ?? '').replace(RE_RETURN_TYPE, info.returnType).replace(RE_FUNC_NAME, funcName);\\n\\t\\t\\t\\t\\t\\tlines.push(decl);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn lines.join('\\\\n');\\n\\t\\t}\\n\\t\\tgetReadCode() {\\n\\t\\t\\t\\treturn this._read;\\n\\t\\t}\\n\\t\\tgetOutputDeclarations(outputStreams) {\\n\\t\\t\\t\\tconst isWebGPU = this._device.isWebGPU;\\n\\t\\t\\t\\tconst lines = [];\\n\\t\\t\\t\\tconst template = isWebGPU ? wgslStreamOutput : glslStreamOutput;\\n\\t\\t\\t\\tconst getShaderType = isWebGPU ? getWgslShaderType : getGlslShaderType;\\n\\t\\t\\t\\tfor(let i = 0; i < outputStreams.length; i++){\\n\\t\\t\\t\\t\\t\\tconst stream = outputStreams[i];\\n\\t\\t\\t\\t\\t\\tconst info = getShaderType(stream.format);\\n\\t\\t\\t\\t\\t\\tconst funcName = stream.name.charAt(0).toUpperCase() + stream.name.slice(1);\\n\\t\\t\\t\\t\\t\\tconst colorSlot = i === 0 ? 'color' : `color${i}`;\\n\\t\\t\\t\\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\\t\\t\\t\\tlines.push(decl);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn lines.join('\\\\n');\\n\\t\\t}\\n\\t\\tgetOutputStubs(streams) {\\n\\t\\t\\t\\tconst isWebGPU = this._device.isWebGPU;\\n\\t\\t\\t\\tconst lines = [];\\n\\t\\t\\t\\tconst template = isWebGPU ? wgslStreamOutput : glslStreamOutput;\\n\\t\\t\\t\\tconst getShaderType = isWebGPU ? getWgslShaderType : getGlslShaderType;\\n\\t\\t\\t\\tfor (const stream of streams){\\n\\t\\t\\t\\t\\t\\tconst info = getShaderType(stream.format);\\n\\t\\t\\t\\t\\t\\tconst funcName = stream.name.charAt(0).toUpperCase() + stream.name.slice(1);\\n\\t\\t\\t\\t\\t\\tconst stub = template.replace(RE_FUNC_NAME, funcName).replace(RE_RETURN_TYPE, info.returnType).replace(RE_DEFINE_GUARD, '0');\\n\\t\\t\\t\\t\\t\\tlines.push(stub);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn lines.join('\\\\n');\\n\\t\\t}\\n\\t\\tgetStream(name) {\\n\\t\\t\\t\\tlet stream = this.streams.find((s)=>s.name === name);\\n\\t\\t\\t\\tif (!stream) {\\n\\t\\t\\t\\t\\t\\tstream = this._extraStreams.find((s)=>s.name === name);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn stream;\\n\\t\\t}\\n\\t\\t_invalidateCaches() {\\n\\t\\t\\t\\tthis._hash = undefined;\\n\\t\\t\\t\\tthis._resourceStreams = null;\\n\\t\\t\\t\\tthis._instanceStreams = null;\\n\\t\\t}\\n\\t\\tstatic createDefaultFormat(device) {\\n\\t\\t\\t\\treturn new GSplatFormat(device, [\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'dataColor',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA16F\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'dataCenter',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32F\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'dataScale',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA16F\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'dataRotation',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA16F\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t], {\\n\\t\\t\\t\\t\\t\\treadGLSL: gsplatContainerFloatReadVS$1,\\n\\t\\t\\t\\t\\t\\treadWGSL: gsplatContainerFloatReadVS\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tstatic createSimpleFormat(device) {\\n\\t\\t\\t\\treturn new GSplatFormat(device, [\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'dataCenter',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32F\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'dataColor',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA16F\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t], {\\n\\t\\t\\t\\t\\t\\treadGLSL: glslContainerSimpleRead,\\n\\t\\t\\t\\t\\t\\treadWGSL: wgslContainerSimpleRead\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tconstructor(device, streams, options){\\n\\t\\t\\t\\tthis._extraStreams = [];\\n\\t\\t\\t\\tthis._streamNames = new Set();\\n\\t\\t\\t\\tthis._extraStreamsVersion = 0;\\n\\t\\t\\t\\tthis._resourceStreams = null;\\n\\t\\t\\t\\tthis._instanceStreams = null;\\n\\t\\t\\t\\tthis._device = device;\\n\\t\\t\\t\\tthis.streams = [\\n\\t\\t\\t\\t\\t\\t...streams\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis._streamNames = new Set(this.streams.map((s)=>s.name));\\n\\t\\t\\t\\tconst isWebGPU = device.isWebGPU;\\n\\t\\t\\t\\tthis._read = isWebGPU ? options.readWGSL : options.readGLSL;\\n\\t\\t}\\n}\\n\\nclass GSplatParams {\\n\\t\\tset colorizeLod(value) {\\n\\t\\t\\t\\tif (this._colorizeLod !== value) {\\n\\t\\t\\t\\t\\t\\tthis._colorizeLod = value;\\n\\t\\t\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget colorizeLod() {\\n\\t\\t\\t\\treturn this._colorizeLod;\\n\\t\\t}\\n\\t\\tset enableIds(value) {\\n\\t\\t\\t\\tif (value && !this._enableIds) {\\n\\t\\t\\t\\t\\t\\tthis._enableIds = true;\\n\\t\\t\\t\\t\\t\\tif (!this._format.getStream('pcId')) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._format.addExtraStreams([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tname: 'pcId',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_R32U\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget enableIds() {\\n\\t\\t\\t\\treturn this._enableIds;\\n\\t\\t}\\n\\t\\tset lodBehindPenalty(value) {\\n\\t\\t\\t\\tif (this._lodBehindPenalty !== value) {\\n\\t\\t\\t\\t\\t\\tthis._lodBehindPenalty = value;\\n\\t\\t\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget lodBehindPenalty() {\\n\\t\\t\\t\\treturn this._lodBehindPenalty;\\n\\t\\t}\\n\\t\\tset lodRangeMin(value) {\\n\\t\\t\\t\\tif (this._lodRangeMin !== value) {\\n\\t\\t\\t\\t\\t\\tthis._lodRangeMin = value;\\n\\t\\t\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget lodRangeMin() {\\n\\t\\t\\t\\treturn this._lodRangeMin;\\n\\t\\t}\\n\\t\\tset lodRangeMax(value) {\\n\\t\\t\\t\\tif (this._lodRangeMax !== value) {\\n\\t\\t\\t\\t\\t\\tthis._lodRangeMax = value;\\n\\t\\t\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget lodRangeMax() {\\n\\t\\t\\t\\treturn this._lodRangeMax;\\n\\t\\t}\\n\\t\\tset lodUnderfillLimit(value) {\\n\\t\\t\\t\\tif (this._lodUnderfillLimit !== value) {\\n\\t\\t\\t\\t\\t\\tthis._lodUnderfillLimit = value;\\n\\t\\t\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget lodUnderfillLimit() {\\n\\t\\t\\t\\treturn this._lodUnderfillLimit;\\n\\t\\t}\\n\\t\\tset splatBudget(value) {}\\n\\t\\tget splatBudget() {\\n\\t\\t\\t\\treturn 0;\\n\\t\\t}\\n\\t\\tset colorRamp(value) {\\n\\t\\t\\t\\tif (this._colorRamp !== value) {\\n\\t\\t\\t\\t\\t\\tthis._colorRamp = value;\\n\\t\\t\\t\\t\\t\\tthis.dirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget colorRamp() {\\n\\t\\t\\t\\treturn this._colorRamp;\\n\\t\\t}\\n\\t\\tget material() {\\n\\t\\t\\t\\treturn this._material;\\n\\t\\t}\\n\\t\\tget format() {\\n\\t\\t\\t\\treturn this._format;\\n\\t\\t}\\n\\t\\tframeEnd() {\\n\\t\\t\\t\\tthis._material.dirty = false;\\n\\t\\t\\t\\tthis.dirty = false;\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis._material = new ShaderMaterial();\\n\\t\\t\\t\\tthis.debugAabbs = false;\\n\\t\\t\\t\\tthis.radialSorting = false;\\n\\t\\t\\t\\tthis.gpuSorting = false;\\n\\t\\t\\t\\tthis.debugNodeAabbs = false;\\n\\t\\t\\t\\tthis.dirty = false;\\n\\t\\t\\t\\tthis._colorizeLod = false;\\n\\t\\t\\t\\tthis._enableIds = false;\\n\\t\\t\\t\\tthis.lodUpdateDistance = 1;\\n\\t\\t\\t\\tthis.lodUpdateAngle = 0;\\n\\t\\t\\t\\tthis._lodBehindPenalty = 1;\\n\\t\\t\\t\\tthis._lodRangeMin = 0;\\n\\t\\t\\t\\tthis._lodRangeMax = 10;\\n\\t\\t\\t\\tthis._lodUnderfillLimit = 0;\\n\\t\\t\\t\\tthis._colorRamp = null;\\n\\t\\t\\t\\tthis.colorRampIntensity = 1;\\n\\t\\t\\t\\tthis.colorizeColorUpdate = false;\\n\\t\\t\\t\\tthis.colorUpdateDistance = 0.2;\\n\\t\\t\\t\\tthis.colorUpdateAngle = 2;\\n\\t\\t\\t\\tthis.colorUpdateDistanceLodScale = 2;\\n\\t\\t\\t\\tthis.colorUpdateAngleLodScale = 2;\\n\\t\\t\\t\\tthis.cooldownTicks = 100;\\n\\t\\t\\t\\tconst colorFormat = device.getRenderableHdrFormat([\\n\\t\\t\\t\\t\\t\\tPIXELFORMAT_RGBA16F\\n\\t\\t\\t\\t]) || PIXELFORMAT_RGBA16U;\\n\\t\\t\\t\\tthis._format = new GSplatFormat(device, [\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'dataColor',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: colorFormat\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'dataTransformA',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32U\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'dataTransformB',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RG32U\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t], {\\n\\t\\t\\t\\t\\t\\treadGLSL: '#include \\\"gsplatContainerPackedReadVS\\\"',\\n\\t\\t\\t\\t\\t\\treadWGSL: '#include \\\"gsplatContainerPackedReadVS\\\"'\\n\\t\\t\\t\\t});\\n\\t\\t}\\n}\\n\\nconst decodeTable = {\\n\\t\\t'linear': 'decodeLinear',\\n\\t\\t'srgb': 'decodeGamma',\\n\\t\\t'rgbm': 'decodeRGBM',\\n\\t\\t'rgbe': 'decodeRGBE',\\n\\t\\t'rgbp': 'decodeRGBP',\\n\\t\\t'xy': 'unpackNormalXY',\\n\\t\\t'xyz': 'unpackNormalXYZ'\\n};\\nconst encodeTable = {\\n\\t\\t'linear': 'encodeLinear',\\n\\t\\t'srgb': 'encodeGamma',\\n\\t\\t'rgbm': 'encodeRGBM',\\n\\t\\t'rgbe': 'encodeRGBE',\\n\\t\\t'rgbp': 'encodeRGBP'\\n};\\nclass ChunkUtils {\\n\\t\\tstatic decodeFunc(encoding) {\\n\\t\\t\\t\\treturn decodeTable[encoding] ?? 'decodeGamma';\\n\\t\\t}\\n\\t\\tstatic encodeFunc(encoding) {\\n\\t\\t\\t\\treturn encodeTable[encoding] ?? 'encodeGamma';\\n\\t\\t}\\n}\\n\\nconst calculateNormals = (positions, indices)=>{\\n\\t\\tconst triangleCount = indices.length / 3;\\n\\t\\tconst vertexCount = positions.length / 3;\\n\\t\\tconst p1 = new Vec3();\\n\\t\\tconst p2 = new Vec3();\\n\\t\\tconst p3 = new Vec3();\\n\\t\\tconst p1p2 = new Vec3();\\n\\t\\tconst p1p3 = new Vec3();\\n\\t\\tconst faceNormal = new Vec3();\\n\\t\\tconst normals = [];\\n\\t\\tfor(let i = 0; i < positions.length; i++){\\n\\t\\t\\t\\tnormals[i] = 0;\\n\\t\\t}\\n\\t\\tfor(let i = 0; i < triangleCount; i++){\\n\\t\\t\\t\\tconst i1 = indices[i * 3];\\n\\t\\t\\t\\tconst i2 = indices[i * 3 + 1];\\n\\t\\t\\t\\tconst i3 = indices[i * 3 + 2];\\n\\t\\t\\t\\tp1.set(positions[i1 * 3], positions[i1 * 3 + 1], positions[i1 * 3 + 2]);\\n\\t\\t\\t\\tp2.set(positions[i2 * 3], positions[i2 * 3 + 1], positions[i2 * 3 + 2]);\\n\\t\\t\\t\\tp3.set(positions[i3 * 3], positions[i3 * 3 + 1], positions[i3 * 3 + 2]);\\n\\t\\t\\t\\tp1p2.sub2(p2, p1);\\n\\t\\t\\t\\tp1p3.sub2(p3, p1);\\n\\t\\t\\t\\tfaceNormal.cross(p1p2, p1p3).normalize();\\n\\t\\t\\t\\tnormals[i1 * 3] += faceNormal.x;\\n\\t\\t\\t\\tnormals[i1 * 3 + 1] += faceNormal.y;\\n\\t\\t\\t\\tnormals[i1 * 3 + 2] += faceNormal.z;\\n\\t\\t\\t\\tnormals[i2 * 3] += faceNormal.x;\\n\\t\\t\\t\\tnormals[i2 * 3 + 1] += faceNormal.y;\\n\\t\\t\\t\\tnormals[i2 * 3 + 2] += faceNormal.z;\\n\\t\\t\\t\\tnormals[i3 * 3] += faceNormal.x;\\n\\t\\t\\t\\tnormals[i3 * 3 + 1] += faceNormal.y;\\n\\t\\t\\t\\tnormals[i3 * 3 + 2] += faceNormal.z;\\n\\t\\t}\\n\\t\\tfor(let i = 0; i < vertexCount; i++){\\n\\t\\t\\t\\tconst nx = normals[i * 3];\\n\\t\\t\\t\\tconst ny = normals[i * 3 + 1];\\n\\t\\t\\t\\tconst nz = normals[i * 3 + 2];\\n\\t\\t\\t\\tconst invLen = 1 / Math.sqrt(nx * nx + ny * ny + nz * nz);\\n\\t\\t\\t\\tnormals[i * 3] *= invLen;\\n\\t\\t\\t\\tnormals[i * 3 + 1] *= invLen;\\n\\t\\t\\t\\tnormals[i * 3 + 2] *= invLen;\\n\\t\\t}\\n\\t\\treturn normals;\\n};\\nconst calculateTangents = (positions, normals, uvs, indices)=>{\\n\\t\\tconst triangleCount = indices.length / 3;\\n\\t\\tconst vertexCount = positions.length / 3;\\n\\t\\tconst v1 = new Vec3();\\n\\t\\tconst v2 = new Vec3();\\n\\t\\tconst v3 = new Vec3();\\n\\t\\tconst w1 = new Vec2();\\n\\t\\tconst w2 = new Vec2();\\n\\t\\tconst w3 = new Vec2();\\n\\t\\tconst sdir = new Vec3();\\n\\t\\tconst tdir = new Vec3();\\n\\t\\tconst tan1 = new Float32Array(vertexCount * 3);\\n\\t\\tconst tan2 = new Float32Array(vertexCount * 3);\\n\\t\\tconst tangents = [];\\n\\t\\tfor(let i = 0; i < triangleCount; i++){\\n\\t\\t\\t\\tconst i1 = indices[i * 3];\\n\\t\\t\\t\\tconst i2 = indices[i * 3 + 1];\\n\\t\\t\\t\\tconst i3 = indices[i * 3 + 2];\\n\\t\\t\\t\\tv1.set(positions[i1 * 3], positions[i1 * 3 + 1], positions[i1 * 3 + 2]);\\n\\t\\t\\t\\tv2.set(positions[i2 * 3], positions[i2 * 3 + 1], positions[i2 * 3 + 2]);\\n\\t\\t\\t\\tv3.set(positions[i3 * 3], positions[i3 * 3 + 1], positions[i3 * 3 + 2]);\\n\\t\\t\\t\\tw1.set(uvs[i1 * 2], uvs[i1 * 2 + 1]);\\n\\t\\t\\t\\tw2.set(uvs[i2 * 2], uvs[i2 * 2 + 1]);\\n\\t\\t\\t\\tw3.set(uvs[i3 * 2], uvs[i3 * 2 + 1]);\\n\\t\\t\\t\\tconst x1 = v2.x - v1.x;\\n\\t\\t\\t\\tconst x2 = v3.x - v1.x;\\n\\t\\t\\t\\tconst y1 = v2.y - v1.y;\\n\\t\\t\\t\\tconst y2 = v3.y - v1.y;\\n\\t\\t\\t\\tconst z1 = v2.z - v1.z;\\n\\t\\t\\t\\tconst z2 = v3.z - v1.z;\\n\\t\\t\\t\\tconst s1 = w2.x - w1.x;\\n\\t\\t\\t\\tconst s2 = w3.x - w1.x;\\n\\t\\t\\t\\tconst t1 = w2.y - w1.y;\\n\\t\\t\\t\\tconst t2 = w3.y - w1.y;\\n\\t\\t\\t\\tconst area = s1 * t2 - s2 * t1;\\n\\t\\t\\t\\tif (area === 0) {\\n\\t\\t\\t\\t\\t\\tsdir.set(0, 1, 0);\\n\\t\\t\\t\\t\\t\\ttdir.set(1, 0, 0);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst r = 1 / area;\\n\\t\\t\\t\\t\\t\\tsdir.set((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);\\n\\t\\t\\t\\t\\t\\ttdir.set((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttan1[i1 * 3 + 0] += sdir.x;\\n\\t\\t\\t\\ttan1[i1 * 3 + 1] += sdir.y;\\n\\t\\t\\t\\ttan1[i1 * 3 + 2] += sdir.z;\\n\\t\\t\\t\\ttan1[i2 * 3 + 0] += sdir.x;\\n\\t\\t\\t\\ttan1[i2 * 3 + 1] += sdir.y;\\n\\t\\t\\t\\ttan1[i2 * 3 + 2] += sdir.z;\\n\\t\\t\\t\\ttan1[i3 * 3 + 0] += sdir.x;\\n\\t\\t\\t\\ttan1[i3 * 3 + 1] += sdir.y;\\n\\t\\t\\t\\ttan1[i3 * 3 + 2] += sdir.z;\\n\\t\\t\\t\\ttan2[i1 * 3 + 0] += tdir.x;\\n\\t\\t\\t\\ttan2[i1 * 3 + 1] += tdir.y;\\n\\t\\t\\t\\ttan2[i1 * 3 + 2] += tdir.z;\\n\\t\\t\\t\\ttan2[i2 * 3 + 0] += tdir.x;\\n\\t\\t\\t\\ttan2[i2 * 3 + 1] += tdir.y;\\n\\t\\t\\t\\ttan2[i2 * 3 + 2] += tdir.z;\\n\\t\\t\\t\\ttan2[i3 * 3 + 0] += tdir.x;\\n\\t\\t\\t\\ttan2[i3 * 3 + 1] += tdir.y;\\n\\t\\t\\t\\ttan2[i3 * 3 + 2] += tdir.z;\\n\\t\\t}\\n\\t\\tconst t1 = new Vec3();\\n\\t\\tconst t2 = new Vec3();\\n\\t\\tconst n = new Vec3();\\n\\t\\tconst temp = new Vec3();\\n\\t\\tfor(let i = 0; i < vertexCount; i++){\\n\\t\\t\\t\\tn.set(normals[i * 3], normals[i * 3 + 1], normals[i * 3 + 2]);\\n\\t\\t\\t\\tt1.set(tan1[i * 3], tan1[i * 3 + 1], tan1[i * 3 + 2]);\\n\\t\\t\\t\\tt2.set(tan2[i * 3], tan2[i * 3 + 1], tan2[i * 3 + 2]);\\n\\t\\t\\t\\tconst ndott = n.dot(t1);\\n\\t\\t\\t\\ttemp.copy(n).mulScalar(ndott);\\n\\t\\t\\t\\ttemp.sub2(t1, temp).normalize();\\n\\t\\t\\t\\ttangents[i * 4] = temp.x;\\n\\t\\t\\t\\ttangents[i * 4 + 1] = temp.y;\\n\\t\\t\\t\\ttangents[i * 4 + 2] = temp.z;\\n\\t\\t\\t\\ttemp.cross(n, t1);\\n\\t\\t\\t\\ttangents[i * 4 + 3] = temp.dot(t2) < 0.0 ? -1 : 1.0;\\n\\t\\t}\\n\\t\\treturn tangents;\\n};\\n\\nclass Geometry {\\n\\t\\tcalculateNormals() {\\n\\t\\t\\t\\tthis.normals = calculateNormals(this.positions, this.indices);\\n\\t\\t}\\n\\t\\tcalculateTangents() {\\n\\t\\t\\t\\tthis.tangents = calculateTangents(this.positions, this.normals, this.uvs, this.indices);\\n\\t\\t}\\n}\\n\\nconst primitiveUv1Padding$1 = 8.0 / 64;\\nconst primitiveUv1PaddingScale$1 = 1.0 - primitiveUv1Padding$1 * 2;\\nclass BoxGeometry extends Geometry {\\n\\t\\tconstructor(opts = {}){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tconst he = opts.halfExtents ?? new Vec3(0.5, 0.5, 0.5);\\n\\t\\t\\t\\tconst ws = opts.widthSegments ?? 1;\\n\\t\\t\\t\\tconst ls = opts.lengthSegments ?? 1;\\n\\t\\t\\t\\tconst hs = opts.heightSegments ?? 1;\\n\\t\\t\\t\\tconst yOffset = opts.yOffset ?? 0;\\n\\t\\t\\t\\tconst minY = -he.y + yOffset;\\n\\t\\t\\t\\tconst maxY = he.y + yOffset;\\n\\t\\t\\t\\tconst corners = [\\n\\t\\t\\t\\t\\t\\tnew Vec3(-he.x, minY, he.z),\\n\\t\\t\\t\\t\\t\\tnew Vec3(he.x, minY, he.z),\\n\\t\\t\\t\\t\\t\\tnew Vec3(he.x, maxY, he.z),\\n\\t\\t\\t\\t\\t\\tnew Vec3(-he.x, maxY, he.z),\\n\\t\\t\\t\\t\\t\\tnew Vec3(he.x, minY, -he.z),\\n\\t\\t\\t\\t\\t\\tnew Vec3(-he.x, minY, -he.z),\\n\\t\\t\\t\\t\\t\\tnew Vec3(-he.x, maxY, -he.z),\\n\\t\\t\\t\\t\\t\\tnew Vec3(he.x, maxY, -he.z)\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tconst faceAxes = [\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t\\t\\t3\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t4,\\n\\t\\t\\t\\t\\t\\t\\t\\t5,\\n\\t\\t\\t\\t\\t\\t\\t\\t7\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t3,\\n\\t\\t\\t\\t\\t\\t\\t\\t2,\\n\\t\\t\\t\\t\\t\\t\\t\\t6\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t4\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t\\t\\t4,\\n\\t\\t\\t\\t\\t\\t\\t\\t2\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t5,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t6\\n\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tconst faceNormals = [\\n\\t\\t\\t\\t\\t\\t[\\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\\t1\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t[\\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\\t-1\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t-1,\\n\\t\\t\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t1,\\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],\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t-1,\\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]\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tconst sides = {\\n\\t\\t\\t\\t\\t\\tFRONT: 0,\\n\\t\\t\\t\\t\\t\\tBACK: 1,\\n\\t\\t\\t\\t\\t\\tTOP: 2,\\n\\t\\t\\t\\t\\t\\tBOTTOM: 3,\\n\\t\\t\\t\\t\\t\\tRIGHT: 4,\\n\\t\\t\\t\\t\\t\\tLEFT: 5\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst positions = [];\\n\\t\\t\\t\\tconst normals = [];\\n\\t\\t\\t\\tconst uvs = [];\\n\\t\\t\\t\\tconst uvs1 = [];\\n\\t\\t\\t\\tconst indices = [];\\n\\t\\t\\t\\tlet vcounter = 0;\\n\\t\\t\\t\\tconst generateFace = (side, uSegments, vSegments)=>{\\n\\t\\t\\t\\t\\t\\tconst temp1 = new Vec3();\\n\\t\\t\\t\\t\\t\\tconst temp2 = new Vec3();\\n\\t\\t\\t\\t\\t\\tconst temp3 = new Vec3();\\n\\t\\t\\t\\t\\t\\tconst r = new Vec3();\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i <= uSegments; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j <= vSegments; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttemp1.lerp(corners[faceAxes[side][0]], corners[faceAxes[side][1]], i / uSegments);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttemp2.lerp(corners[faceAxes[side][0]], corners[faceAxes[side][2]], j / vSegments);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttemp3.sub2(temp2, corners[faceAxes[side][0]]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tr.add2(temp1, temp3);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet u = i / uSegments;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet v = j / vSegments;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpositions.push(r.x, r.y, r.z);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnormals.push(faceNormals[side][0], faceNormals[side][1], faceNormals[side][2]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu = u * primitiveUv1PaddingScale$1 + primitiveUv1Padding$1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tv = v * primitiveUv1PaddingScale$1 + primitiveUv1Padding$1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu /= 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tv /= 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu += side % 3 / 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tv += Math.floor(side / 3) / 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuvs1.push(u, 1 - v);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (i < uSegments && j < vSegments) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices.push(vcounter + vSegments + 1, vcounter + 1, vcounter);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices.push(vcounter + vSegments + 1, vcounter + vSegments + 2, vcounter + 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvcounter++;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tgenerateFace(sides.FRONT, ws, hs);\\n\\t\\t\\t\\tgenerateFace(sides.BACK, ws, hs);\\n\\t\\t\\t\\tgenerateFace(sides.TOP, ws, ls);\\n\\t\\t\\t\\tgenerateFace(sides.BOTTOM, ws, ls);\\n\\t\\t\\t\\tgenerateFace(sides.RIGHT, ls, hs);\\n\\t\\t\\t\\tgenerateFace(sides.LEFT, ls, hs);\\n\\t\\t\\t\\tthis.positions = positions;\\n\\t\\t\\t\\tthis.normals = normals;\\n\\t\\t\\t\\tthis.uvs = uvs;\\n\\t\\t\\t\\tthis.uvs1 = uvs1;\\n\\t\\t\\t\\tthis.indices = indices;\\n\\t\\t\\t\\tif (opts.calculateTangents) {\\n\\t\\t\\t\\t\\t\\tthis.tangents = calculateTangents(positions, normals, uvs, indices);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass SphereGeometry extends Geometry {\\n\\t\\tconstructor(opts = {}){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tconst radius = opts.radius ?? 0.5;\\n\\t\\t\\t\\tconst latitudeBands = opts.latitudeBands ?? 16;\\n\\t\\t\\t\\tconst longitudeBands = opts.longitudeBands ?? 16;\\n\\t\\t\\t\\tconst positions = [];\\n\\t\\t\\t\\tconst normals = [];\\n\\t\\t\\t\\tconst uvs = [];\\n\\t\\t\\t\\tconst indices = [];\\n\\t\\t\\t\\tfor(let lat = 0; lat <= latitudeBands; lat++){\\n\\t\\t\\t\\t\\t\\tconst theta = lat * Math.PI / latitudeBands;\\n\\t\\t\\t\\t\\t\\tconst sinTheta = Math.sin(theta);\\n\\t\\t\\t\\t\\t\\tconst cosTheta = Math.cos(theta);\\n\\t\\t\\t\\t\\t\\tfor(let lon = 0; lon <= longitudeBands; lon++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst phi = lon * 2 * Math.PI / longitudeBands - Math.PI / 2;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst sinPhi = Math.sin(phi);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst cosPhi = Math.cos(phi);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst x = cosPhi * sinTheta;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst y = cosTheta;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst z = sinPhi * sinTheta;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst u = 1 - lon / longitudeBands;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst v = 1 - lat / latitudeBands;\\n\\t\\t\\t\\t\\t\\t\\t\\tpositions.push(x * radius, y * radius, z * radius);\\n\\t\\t\\t\\t\\t\\t\\t\\tnormals.push(x, y, z);\\n\\t\\t\\t\\t\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let lat = 0; lat < latitudeBands; ++lat){\\n\\t\\t\\t\\t\\t\\tfor(let lon = 0; lon < longitudeBands; ++lon){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst first = lat * (longitudeBands + 1) + lon;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst second = first + longitudeBands + 1;\\n\\t\\t\\t\\t\\t\\t\\t\\tindices.push(first + 1, second, first);\\n\\t\\t\\t\\t\\t\\t\\t\\tindices.push(first + 1, second + 1, second);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.positions = positions;\\n\\t\\t\\t\\tthis.normals = normals;\\n\\t\\t\\t\\tthis.uvs = uvs;\\n\\t\\t\\t\\tthis.uvs1 = uvs;\\n\\t\\t\\t\\tthis.indices = indices;\\n\\t\\t\\t\\tif (opts.calculateTangents) {\\n\\t\\t\\t\\t\\t\\tthis.tangents = calculateTangents(positions, normals, uvs, indices);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass DomeGeometry extends SphereGeometry {\\n\\t\\tconstructor(opts = {}){\\n\\t\\t\\t\\tconst radius = 0.5;\\n\\t\\t\\t\\tconst latitudeBands = opts.latitudeBands ?? 16;\\n\\t\\t\\t\\tconst longitudeBands = opts.longitudeBands ?? 16;\\n\\t\\t\\t\\tsuper({\\n\\t\\t\\t\\t\\t\\tradius,\\n\\t\\t\\t\\t\\t\\tlatitudeBands,\\n\\t\\t\\t\\t\\t\\tlongitudeBands\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst bottomLimit = 0.1;\\n\\t\\t\\t\\tconst curvatureRadius = 0.95;\\n\\t\\t\\t\\tconst curvatureRadiusSq = curvatureRadius * curvatureRadius;\\n\\t\\t\\t\\tconst positions = this.positions;\\n\\t\\t\\t\\tfor(let i = 0; i < positions.length; i += 3){\\n\\t\\t\\t\\t\\t\\tconst x = positions[i] / radius;\\n\\t\\t\\t\\t\\t\\tlet y = positions[i + 1] / radius;\\n\\t\\t\\t\\t\\t\\tconst z = positions[i + 2] / radius;\\n\\t\\t\\t\\t\\t\\tif (y < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\ty *= 0.3;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (x * x + z * z < curvatureRadiusSq) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ty = -bottomLimit;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\ty += bottomLimit;\\n\\t\\t\\t\\t\\t\\ty *= radius;\\n\\t\\t\\t\\t\\t\\tpositions[i + 1] = y;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass SkyGeometry {\\n\\t\\tstatic create(device, type) {\\n\\t\\t\\t\\tswitch(type){\\n\\t\\t\\t\\t\\t\\tcase SKYTYPE_BOX:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn SkyGeometry.box(device);\\n\\t\\t\\t\\t\\t\\tcase SKYTYPE_DOME:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn SkyGeometry.dome(device);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn SkyGeometry.infinite(device);\\n\\t\\t}\\n\\t\\tstatic infinite(device) {\\n\\t\\t\\t\\treturn Mesh.fromGeometry(device, new BoxGeometry(device));\\n\\t\\t}\\n\\t\\tstatic box(device) {\\n\\t\\t\\t\\treturn Mesh.fromGeometry(device, new BoxGeometry({\\n\\t\\t\\t\\t\\t\\tyOffset: 0.5\\n\\t\\t\\t\\t}));\\n\\t\\t}\\n\\t\\tstatic dome(device) {\\n\\t\\t\\t\\tconst geom = new DomeGeometry({\\n\\t\\t\\t\\t\\t\\tlatitudeBands: 50,\\n\\t\\t\\t\\t\\t\\tlongitudeBands: 50\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tgeom.normals = undefined;\\n\\t\\t\\t\\tgeom.uvs = undefined;\\n\\t\\t\\t\\treturn Mesh.fromGeometry(device, geom);\\n\\t\\t}\\n}\\n\\nclass SkyMesh {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tif (this.meshInstance) {\\n\\t\\t\\t\\t\\t\\tif (this.skyLayer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.skyLayer.removeMeshInstances([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.meshInstance\\n\\t\\t\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.meshInstance.destroy();\\n\\t\\t\\t\\t\\t\\tthis.meshInstance = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tset depthWrite(value) {\\n\\t\\t\\t\\tthis._depthWrite = value;\\n\\t\\t\\t\\tif (this.meshInstance) {\\n\\t\\t\\t\\t\\t\\tthis.meshInstance.material.depthWrite = value;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget depthWrite() {\\n\\t\\t\\t\\treturn this._depthWrite;\\n\\t\\t}\\n\\t\\tconstructor(device, scene, node, texture, type){\\n\\t\\t\\t\\tthis.meshInstance = null;\\n\\t\\t\\t\\tthis._depthWrite = false;\\n\\t\\t\\t\\tconst material = new ShaderMaterial({\\n\\t\\t\\t\\t\\t\\tuniqueName: 'SkyMaterial',\\n\\t\\t\\t\\t\\t\\tvertexGLSL: ShaderChunks.get(device, SHADERLANGUAGE_GLSL).get('skyboxVS'),\\n\\t\\t\\t\\t\\t\\tfragmentGLSL: ShaderChunks.get(device, SHADERLANGUAGE_GLSL).get('skyboxPS'),\\n\\t\\t\\t\\t\\t\\tvertexWGSL: ShaderChunks.get(device, SHADERLANGUAGE_WGSL).get('skyboxVS'),\\n\\t\\t\\t\\t\\t\\tfragmentWGSL: ShaderChunks.get(device, SHADERLANGUAGE_WGSL).get('skyboxPS'),\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\taPosition: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tmaterial.setDefine('{SKYBOX_DECODE_FNC}', ChunkUtils.decodeFunc(texture.encoding));\\n\\t\\t\\t\\tif (type !== SKYTYPE_INFINITE) material.setDefine('SKYMESH', '');\\n\\t\\t\\t\\tif (texture.cubemap) material.setDefine('SKY_CUBEMAP', '');\\n\\t\\t\\t\\tmaterial.setParameter('skyboxHighlightMultiplier', scene.skyboxHighlightMultiplier);\\n\\t\\t\\t\\tif (texture.cubemap) {\\n\\t\\t\\t\\t\\t\\tmaterial.setParameter('texture_cubeMap', texture);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tmaterial.setParameter('texture_envAtlas', texture);\\n\\t\\t\\t\\t\\t\\tmaterial.setParameter('mipLevel', scene.skyboxMip);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tmaterial.cull = CULLFACE_FRONT;\\n\\t\\t\\t\\tmaterial.depthWrite = this._depthWrite;\\n\\t\\t\\t\\tconst skyLayer = scene.layers.getLayerById(LAYERID_SKYBOX);\\n\\t\\t\\t\\tif (skyLayer) {\\n\\t\\t\\t\\t\\t\\tconst mesh = SkyGeometry.create(device, type);\\n\\t\\t\\t\\t\\t\\tconst meshInstance = new MeshInstance(mesh, material, node);\\n\\t\\t\\t\\t\\t\\tthis.meshInstance = meshInstance;\\n\\t\\t\\t\\t\\t\\tmeshInstance.cull = false;\\n\\t\\t\\t\\t\\t\\tmeshInstance.pick = false;\\n\\t\\t\\t\\t\\t\\tskyLayer.addMeshInstances([\\n\\t\\t\\t\\t\\t\\t\\t\\tmeshInstance\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\tthis.skyLayer = skyLayer;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass Sky {\\n\\t\\tapplySettings(render) {\\n\\t\\t\\t\\tthis.type = render.skyType ?? SKYTYPE_INFINITE;\\n\\t\\t\\t\\tthis.node.setLocalPosition(new Vec3(render.skyMeshPosition ?? [\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t]));\\n\\t\\t\\t\\tthis.node.setLocalEulerAngles(new Vec3(render.skyMeshRotation ?? [\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t]));\\n\\t\\t\\t\\tthis.node.setLocalScale(new Vec3(render.skyMeshScale ?? [\\n\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t1\\n\\t\\t\\t\\t]));\\n\\t\\t\\t\\tif (render.skyCenter) {\\n\\t\\t\\t\\t\\t\\tthis._center = new Vec3(render.skyCenter);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tset type(value) {\\n\\t\\t\\t\\tif (this._type !== value) {\\n\\t\\t\\t\\t\\t\\tthis._type = value;\\n\\t\\t\\t\\t\\t\\tthis.scene.updateShaders = true;\\n\\t\\t\\t\\t\\t\\tthis.updateSkyMesh();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget type() {\\n\\t\\t\\t\\treturn this._type;\\n\\t\\t}\\n\\t\\tset center(value) {\\n\\t\\t\\t\\tthis._center.copy(value);\\n\\t\\t}\\n\\t\\tget center() {\\n\\t\\t\\t\\treturn this._center;\\n\\t\\t}\\n\\t\\tset depthWrite(value) {\\n\\t\\t\\t\\tif (this._depthWrite !== value) {\\n\\t\\t\\t\\t\\t\\tthis._depthWrite = value;\\n\\t\\t\\t\\t\\t\\tif (this.skyMesh) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.skyMesh.depthWrite = value;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget depthWrite() {\\n\\t\\t\\t\\treturn this._depthWrite;\\n\\t\\t}\\n\\t\\tupdateSkyMesh() {\\n\\t\\t\\t\\tconst texture = this.scene._getSkyboxTex();\\n\\t\\t\\t\\tif (texture) {\\n\\t\\t\\t\\t\\t\\tthis.resetSkyMesh();\\n\\t\\t\\t\\t\\t\\tthis.skyMesh = new SkyMesh(this.device, this.scene, this.node, texture, this.type);\\n\\t\\t\\t\\t\\t\\tthis.skyMesh.depthWrite = this._depthWrite;\\n\\t\\t\\t\\t\\t\\tthis.scene.fire('set:skybox', texture);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tresetSkyMesh() {\\n\\t\\t\\t\\tthis.skyMesh?.destroy();\\n\\t\\t\\t\\tthis.skyMesh = null;\\n\\t\\t}\\n\\t\\tupdate() {\\n\\t\\t\\t\\tif (this.type !== SKYTYPE_INFINITE) {\\n\\t\\t\\t\\t\\t\\tconst { center, centerArray } = this;\\n\\t\\t\\t\\t\\t\\tconst temp = new Vec3();\\n\\t\\t\\t\\t\\t\\tthis.node.getWorldTransform().transformPoint(center, temp);\\n\\t\\t\\t\\t\\t\\tcenterArray[0] = temp.x;\\n\\t\\t\\t\\t\\t\\tcenterArray[1] = temp.y;\\n\\t\\t\\t\\t\\t\\tcenterArray[2] = temp.z;\\n\\t\\t\\t\\t\\t\\tthis.projectedSkydomeCenterId.setValue(centerArray);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(scene){\\n\\t\\t\\t\\tthis._type = SKYTYPE_INFINITE;\\n\\t\\t\\t\\tthis._center = new Vec3(0, 1, 0);\\n\\t\\t\\t\\tthis.skyMesh = null;\\n\\t\\t\\t\\tthis._depthWrite = false;\\n\\t\\t\\t\\tthis.node = new GraphNode('SkyMeshNode');\\n\\t\\t\\t\\tthis.device = scene.device;\\n\\t\\t\\t\\tthis.scene = scene;\\n\\t\\t\\t\\tthis.center = new Vec3(0, 1, 0);\\n\\t\\t\\t\\tthis.centerArray = new Float32Array(3);\\n\\t\\t\\t\\tthis.projectedSkydomeCenterId = this.device.scope.resolve('projectedSkydomeCenter');\\n\\t\\t}\\n}\\n\\nconst identityGraphNode = new GraphNode();\\nidentityGraphNode.worldTransform = Mat4.IDENTITY;\\nidentityGraphNode._dirtyWorld = identityGraphNode._dirtyNormal = false;\\nclass ImmediateBatch {\\n\\t\\taddLines(positions, color) {\\n\\t\\t\\t\\tconst destPos = this.positions;\\n\\t\\t\\t\\tconst count = positions.length;\\n\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\tconst pos = positions[i];\\n\\t\\t\\t\\t\\t\\tdestPos.push(pos.x, pos.y, pos.z);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst destCol = this.colors;\\n\\t\\t\\t\\tif (color.length) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst col = color[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tdestCol.push(col.r, col.g, col.b, col.a);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tdestCol.push(color.r, color.g, color.b, color.a);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\taddLinesArrays(positions, color) {\\n\\t\\t\\t\\tconst destPos = this.positions;\\n\\t\\t\\t\\tfor(let i = 0; i < positions.length; i += 3){\\n\\t\\t\\t\\t\\t\\tdestPos.push(positions[i], positions[i + 1], positions[i + 2]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst destCol = this.colors;\\n\\t\\t\\t\\tif (color.length) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < color.length; i += 4){\\n\\t\\t\\t\\t\\t\\t\\t\\tdestCol.push(color[i], color[i + 1], color[i + 2], color[i + 3]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst count = positions.length / 3;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tdestCol.push(color.r, color.g, color.b, color.a);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonPreRender(visibleList, transparent) {\\n\\t\\t\\t\\tif (this.positions.length > 0 && this.material.transparent === transparent) {\\n\\t\\t\\t\\t\\t\\tthis.mesh.setPositions(this.positions);\\n\\t\\t\\t\\t\\t\\tthis.mesh.setColors(this.colors);\\n\\t\\t\\t\\t\\t\\tthis.mesh.update(PRIMITIVE_LINES, false);\\n\\t\\t\\t\\t\\t\\tif (!this.meshInstance) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.meshInstance = new MeshInstance(this.mesh, this.material, identityGraphNode);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tvisibleList.push(this.meshInstance);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tclear() {\\n\\t\\t\\t\\tthis.positions.length = 0;\\n\\t\\t\\t\\tthis.colors.length = 0;\\n\\t\\t}\\n\\t\\tconstructor(device, material, layer){\\n\\t\\t\\t\\tthis.material = material;\\n\\t\\t\\t\\tthis.layer = layer;\\n\\t\\t\\t\\tthis.positions = [];\\n\\t\\t\\t\\tthis.colors = [];\\n\\t\\t\\t\\tthis.mesh = new Mesh(device);\\n\\t\\t\\t\\tthis.meshInstance = null;\\n\\t\\t}\\n}\\n\\nclass ImmediateBatches {\\n\\t\\tgetBatch(material, layer) {\\n\\t\\t\\t\\tlet batch = this.map.get(material);\\n\\t\\t\\t\\tif (!batch) {\\n\\t\\t\\t\\t\\t\\tbatch = new ImmediateBatch(this.device, material, layer);\\n\\t\\t\\t\\t\\t\\tthis.map.set(material, batch);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn batch;\\n\\t\\t}\\n\\t\\tonPreRender(visibleList, transparent) {\\n\\t\\t\\t\\tthis.map.forEach((batch)=>{\\n\\t\\t\\t\\t\\t\\tbatch.onPreRender(visibleList, transparent);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tclear() {\\n\\t\\t\\t\\tthis.map.forEach((batch)=>batch.clear());\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.map = new Map();\\n\\t\\t}\\n}\\n\\nconst tempPoints = [];\\nconst vec$3 = new Vec3();\\nclass Immediate {\\n\\t\\tcreateMaterial(depthTest) {\\n\\t\\t\\t\\tconst material = new ShaderMaterial({\\n\\t\\t\\t\\t\\t\\tuniqueName: 'ImmediateLine',\\n\\t\\t\\t\\t\\t\\tvertexGLSL: ShaderChunks.get(this.device, SHADERLANGUAGE_GLSL).get('immediateLineVS'),\\n\\t\\t\\t\\t\\t\\tfragmentGLSL: ShaderChunks.get(this.device, SHADERLANGUAGE_GLSL).get('immediateLinePS'),\\n\\t\\t\\t\\t\\t\\tvertexWGSL: ShaderChunks.get(this.device, SHADERLANGUAGE_WGSL).get('immediateLineVS'),\\n\\t\\t\\t\\t\\t\\tfragmentWGSL: ShaderChunks.get(this.device, SHADERLANGUAGE_WGSL).get('immediateLinePS'),\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION,\\n\\t\\t\\t\\t\\t\\t\\t\\tvertex_color: SEMANTIC_COLOR\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tmaterial.blendType = BLEND_NORMAL;\\n\\t\\t\\t\\tmaterial.depthTest = depthTest;\\n\\t\\t\\t\\tmaterial.update();\\n\\t\\t\\t\\treturn material;\\n\\t\\t}\\n\\t\\tget materialDepth() {\\n\\t\\t\\t\\tif (!this._materialDepth) {\\n\\t\\t\\t\\t\\t\\tthis._materialDepth = this.createMaterial(true);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._materialDepth;\\n\\t\\t}\\n\\t\\tget materialNoDepth() {\\n\\t\\t\\t\\tif (!this._materialNoDepth) {\\n\\t\\t\\t\\t\\t\\tthis._materialNoDepth = this.createMaterial(false);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._materialNoDepth;\\n\\t\\t}\\n\\t\\tgetBatch(layer, depthTest) {\\n\\t\\t\\t\\tlet batches = this.batchesMap.get(layer);\\n\\t\\t\\t\\tif (!batches) {\\n\\t\\t\\t\\t\\t\\tbatches = new ImmediateBatches(this.device);\\n\\t\\t\\t\\t\\t\\tthis.batchesMap.set(layer, batches);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.allBatches.add(batches);\\n\\t\\t\\t\\tconst material = depthTest ? this.materialDepth : this.materialNoDepth;\\n\\t\\t\\t\\treturn batches.getBatch(material, layer);\\n\\t\\t}\\n\\t\\tgetShaderDesc(id, fragmentGLSL, fragmentWGSL) {\\n\\t\\t\\t\\tif (!this.shaderDescs.has(id)) {\\n\\t\\t\\t\\t\\t\\tthis.shaderDescs.set(id, {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniqueName: `DebugShader:${id}`,\\n\\t\\t\\t\\t\\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\\t\\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\\t\\t\\t\\t\\tfragmentGLSL: fragmentGLSL,\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentWGSL: fragmentWGSL,\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.shaderDescs.get(id);\\n\\t\\t}\\n\\t\\tgetTextureShaderDesc(encoding) {\\n\\t\\t\\t\\tconst decodeFunc = ChunkUtils.decodeFunc(encoding);\\n\\t\\t\\t\\treturn this.getShaderDesc(`textureShader-${encoding}`, `\\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#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\\tgetUnfilterableTextureShaderDesc() {\\n\\t\\t\\t\\treturn this.getShaderDesc('textureShaderUnfilterable', `\\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\\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\\tgetDepthTextureShaderDesc() {\\n\\t\\t\\t\\treturn this.getShaderDesc('depthTextureShader', `\\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#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\\tgetQuadMesh() {\\n\\t\\t\\t\\tif (!this.quadMesh) {\\n\\t\\t\\t\\t\\t\\tthis.quadMesh = new Mesh(this.device);\\n\\t\\t\\t\\t\\t\\tthis.quadMesh.setPositions([\\n\\t\\t\\t\\t\\t\\t\\t\\t-0.5,\\n\\t\\t\\t\\t\\t\\t\\t\\t-0.5,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t0.5,\\n\\t\\t\\t\\t\\t\\t\\t\\t-0.5,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t-0.5,\\n\\t\\t\\t\\t\\t\\t\\t\\t0.5,\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t0.5,\\n\\t\\t\\t\\t\\t\\t\\t\\t0.5,\\n\\t\\t\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\tthis.quadMesh.update(PRIMITIVE_TRISTRIP);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.quadMesh;\\n\\t\\t}\\n\\t\\tdrawMesh(material, matrix, mesh, meshInstance, layer) {\\n\\t\\t\\t\\tif (!meshInstance) {\\n\\t\\t\\t\\t\\t\\tconst graphNode = this.getGraphNode(matrix);\\n\\t\\t\\t\\t\\t\\tmeshInstance = new MeshInstance(mesh, material, graphNode);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet layerMeshInstances = this.layerMeshInstances.get(layer);\\n\\t\\t\\t\\tif (!layerMeshInstances) {\\n\\t\\t\\t\\t\\t\\tlayerMeshInstances = [];\\n\\t\\t\\t\\t\\t\\tthis.layerMeshInstances.set(layer, layerMeshInstances);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlayerMeshInstances.push(meshInstance);\\n\\t\\t}\\n\\t\\tdrawWireAlignedBox(min, max, color, depthTest, layer, mat) {\\n\\t\\t\\t\\tif (mat) {\\n\\t\\t\\t\\t\\t\\tconst mulPoint = (x, y, z)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tvec$3.set(x, y, z);\\n\\t\\t\\t\\t\\t\\t\\t\\tmat.transformPoint(vec$3, vec$3);\\n\\t\\t\\t\\t\\t\\t\\t\\ttempPoints.push(vec$3.x, vec$3.y, vec$3.z);\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tmulPoint(min.x, min.y, min.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(min.x, max.y, min.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(min.x, max.y, min.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(max.x, max.y, min.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(max.x, max.y, min.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(max.x, min.y, min.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(max.x, min.y, min.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(min.x, min.y, min.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(min.x, min.y, max.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(min.x, max.y, max.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(min.x, max.y, max.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(max.x, max.y, max.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(max.x, max.y, max.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(max.x, min.y, max.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(max.x, min.y, max.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(min.x, min.y, max.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(min.x, min.y, min.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(min.x, min.y, max.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(min.x, max.y, min.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(min.x, max.y, max.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(max.x, max.y, min.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(max.x, max.y, max.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(max.x, min.y, min.z);\\n\\t\\t\\t\\t\\t\\tmulPoint(max.x, min.y, max.z);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\ttempPoints.push(min.x, min.y, min.z, min.x, max.y, min.z, min.x, max.y, min.z, max.x, max.y, min.z, max.x, max.y, min.z, max.x, min.y, min.z, max.x, min.y, min.z, min.x, min.y, min.z, min.x, min.y, max.z, min.x, max.y, max.z, min.x, max.y, max.z, max.x, max.y, max.z, max.x, max.y, max.z, max.x, min.y, max.z, max.x, min.y, max.z, min.x, min.y, max.z, min.x, min.y, min.z, min.x, min.y, max.z, min.x, max.y, min.z, min.x, max.y, max.z, max.x, max.y, min.z, max.x, max.y, max.z, max.x, min.y, min.z, max.x, min.y, max.z);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst batch = this.getBatch(layer, depthTest);\\n\\t\\t\\t\\tbatch.addLinesArrays(tempPoints, color);\\n\\t\\t\\t\\ttempPoints.length = 0;\\n\\t\\t}\\n\\t\\tdrawWireSphere(center, radius, color, numSegments, depthTest, layer) {\\n\\t\\t\\t\\tconst step = 2 * Math.PI / numSegments;\\n\\t\\t\\t\\tlet angle = 0;\\n\\t\\t\\t\\tfor(let i = 0; i < numSegments; i++){\\n\\t\\t\\t\\t\\t\\tconst sin0 = Math.sin(angle);\\n\\t\\t\\t\\t\\t\\tconst cos0 = Math.cos(angle);\\n\\t\\t\\t\\t\\t\\tangle += step;\\n\\t\\t\\t\\t\\t\\tconst sin1 = Math.sin(angle);\\n\\t\\t\\t\\t\\t\\tconst cos1 = Math.cos(angle);\\n\\t\\t\\t\\t\\t\\ttempPoints.push(center.x + radius * sin0, center.y, center.z + radius * cos0);\\n\\t\\t\\t\\t\\t\\ttempPoints.push(center.x + radius * sin1, center.y, center.z + radius * cos1);\\n\\t\\t\\t\\t\\t\\ttempPoints.push(center.x + radius * sin0, center.y + radius * cos0, center.z);\\n\\t\\t\\t\\t\\t\\ttempPoints.push(center.x + radius * sin1, center.y + radius * cos1, center.z);\\n\\t\\t\\t\\t\\t\\ttempPoints.push(center.x, center.y + radius * sin0, center.z + radius * cos0);\\n\\t\\t\\t\\t\\t\\ttempPoints.push(center.x, center.y + radius * sin1, center.z + radius * cos1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst batch = this.getBatch(layer, depthTest);\\n\\t\\t\\t\\tbatch.addLinesArrays(tempPoints, color);\\n\\t\\t\\t\\ttempPoints.length = 0;\\n\\t\\t}\\n\\t\\tgetGraphNode(matrix) {\\n\\t\\t\\t\\tconst graphNode = new GraphNode('ImmediateDebug');\\n\\t\\t\\t\\tgraphNode.worldTransform = matrix;\\n\\t\\t\\t\\tgraphNode._dirtyWorld = graphNode._dirtyNormal = false;\\n\\t\\t\\t\\treturn graphNode;\\n\\t\\t}\\n\\t\\tonPreRenderLayer(layer, visibleList, transparent) {\\n\\t\\t\\t\\tthis.batchesMap.forEach((batches, batchLayer)=>{\\n\\t\\t\\t\\t\\t\\tif (batchLayer === layer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbatches.onPreRender(visibleList, transparent);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (!this.updatedLayers.has(layer)) {\\n\\t\\t\\t\\t\\t\\tthis.updatedLayers.add(layer);\\n\\t\\t\\t\\t\\t\\tconst meshInstances = this.layerMeshInstances.get(layer);\\n\\t\\t\\t\\t\\t\\tif (meshInstances) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvisibleList.push(meshInstances[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tmeshInstances.length = 0;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonPostRender() {\\n\\t\\t\\t\\tthis.allBatches.forEach((batch)=>batch.clear());\\n\\t\\t\\t\\tthis.allBatches.clear();\\n\\t\\t\\t\\tthis.updatedLayers.clear();\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis.shaderDescs = new Map();\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.quadMesh = null;\\n\\t\\t\\t\\tthis.textureShader = null;\\n\\t\\t\\t\\tthis.depthTextureShader = null;\\n\\t\\t\\t\\tthis.cubeLocalPos = null;\\n\\t\\t\\t\\tthis.cubeWorldPos = null;\\n\\t\\t\\t\\tthis.batchesMap = new Map();\\n\\t\\t\\t\\tthis.allBatches = new Set();\\n\\t\\t\\t\\tthis.updatedLayers = new Set();\\n\\t\\t\\t\\tthis._materialDepth = null;\\n\\t\\t\\t\\tthis._materialNoDepth = null;\\n\\t\\t\\t\\tthis.layerMeshInstances = new Map();\\n\\t\\t}\\n}\\n\\nconst _goldenAngle = 2.399963229728653;\\nconst random = {\\n\\t\\tcirclePoint (point) {\\n\\t\\t\\t\\tconst r = Math.sqrt(Math.random());\\n\\t\\t\\t\\tconst theta = Math.random() * 2 * Math.PI;\\n\\t\\t\\t\\tpoint.x = r * Math.cos(theta);\\n\\t\\t\\t\\tpoint.y = r * Math.sin(theta);\\n\\t\\t},\\n\\t\\tcirclePointDeterministic (point, index, numPoints) {\\n\\t\\t\\t\\tconst theta = index * _goldenAngle;\\n\\t\\t\\t\\tconst r = Math.sqrt(index / numPoints);\\n\\t\\t\\t\\tpoint.x = r * Math.cos(theta);\\n\\t\\t\\t\\tpoint.y = r * Math.sin(theta);\\n\\t\\t},\\n\\t\\tspherePointDeterministic (point, index, numPoints, start = 0, end = 1) {\\n\\t\\t\\t\\tstart = 1 - 2 * start;\\n\\t\\t\\t\\tend = 1 - 2 * end;\\n\\t\\t\\t\\tconst y = math.lerp(start, end, index / numPoints);\\n\\t\\t\\t\\tconst radius = Math.sqrt(1 - y * y);\\n\\t\\t\\t\\tconst theta = _goldenAngle * index;\\n\\t\\t\\t\\tpoint.x = Math.cos(theta) * radius;\\n\\t\\t\\t\\tpoint.y = y;\\n\\t\\t\\t\\tpoint.z = Math.sin(theta) * radius;\\n\\t\\t},\\n\\t\\tradicalInverse (i) {\\n\\t\\t\\t\\tlet bits = (i << 16 | i >>> 16) >>> 0;\\n\\t\\t\\t\\tbits = ((bits & 0x55555555) << 1 | (bits & 0xAAAAAAAA) >>> 1) >>> 0;\\n\\t\\t\\t\\tbits = ((bits & 0x33333333) << 2 | (bits & 0xCCCCCCCC) >>> 2) >>> 0;\\n\\t\\t\\t\\tbits = ((bits & 0x0F0F0F0F) << 4 | (bits & 0xF0F0F0F0) >>> 4) >>> 0;\\n\\t\\t\\t\\tbits = ((bits & 0x00FF00FF) << 8 | (bits & 0xFF00FF00) >>> 8) >>> 0;\\n\\t\\t\\t\\treturn bits * 2.3283064365386963e-10;\\n\\t\\t}\\n};\\n\\nconst getProjectionName = (projection)=>{\\n\\t\\tswitch(projection){\\n\\t\\t\\t\\tcase TEXTUREPROJECTION_CUBE:\\n\\t\\t\\t\\t\\t\\treturn 'Cubemap';\\n\\t\\t\\t\\tcase TEXTUREPROJECTION_OCTAHEDRAL:\\n\\t\\t\\t\\t\\t\\treturn 'Octahedral';\\n\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\treturn 'Equirect';\\n\\t\\t}\\n};\\nconst packFloat32ToRGBA8 = (value, array, offset)=>{\\n\\t\\tif (value <= 0) {\\n\\t\\t\\t\\tarray[offset + 0] = 0;\\n\\t\\t\\t\\tarray[offset + 1] = 0;\\n\\t\\t\\t\\tarray[offset + 2] = 0;\\n\\t\\t\\t\\tarray[offset + 3] = 0;\\n\\t\\t} else if (value >= 1.0) {\\n\\t\\t\\t\\tarray[offset + 0] = 255;\\n\\t\\t\\t\\tarray[offset + 1] = 0;\\n\\t\\t\\t\\tarray[offset + 2] = 0;\\n\\t\\t\\t\\tarray[offset + 3] = 0;\\n\\t\\t} else {\\n\\t\\t\\t\\tlet encX = 1 * value % 1;\\n\\t\\t\\t\\tlet encY = 255 * value % 1;\\n\\t\\t\\t\\tlet encZ = 65025 * value % 1;\\n\\t\\t\\t\\tconst encW = 16581375.0 * value % 1;\\n\\t\\t\\t\\tencX -= encY / 255;\\n\\t\\t\\t\\tencY -= encZ / 255;\\n\\t\\t\\t\\tencZ -= encW / 255;\\n\\t\\t\\t\\tarray[offset + 0] = Math.min(255, Math.floor(encX * 256));\\n\\t\\t\\t\\tarray[offset + 1] = Math.min(255, Math.floor(encY * 256));\\n\\t\\t\\t\\tarray[offset + 2] = Math.min(255, Math.floor(encZ * 256));\\n\\t\\t\\t\\tarray[offset + 3] = Math.min(255, Math.floor(encW * 256));\\n\\t\\t}\\n};\\nconst packSamples = (samples)=>{\\n\\t\\tconst numSamples = samples.length;\\n\\t\\tconst w = Math.min(numSamples, 512);\\n\\t\\tconst h = Math.ceil(numSamples / w);\\n\\t\\tconst data = new Uint8Array(w * h * 4);\\n\\t\\tlet off = 0;\\n\\t\\tfor(let i = 0; i < numSamples; i += 4){\\n\\t\\t\\t\\tpackFloat32ToRGBA8(samples[i + 0] * 0.5 + 0.5, data, off + 0);\\n\\t\\t\\t\\tpackFloat32ToRGBA8(samples[i + 1] * 0.5 + 0.5, data, off + 4);\\n\\t\\t\\t\\tpackFloat32ToRGBA8(samples[i + 2] * 0.5 + 0.5, data, off + 8);\\n\\t\\t\\t\\tpackFloat32ToRGBA8(samples[i + 3] / 8, data, off + 12);\\n\\t\\t\\t\\toff += 16;\\n\\t\\t}\\n\\t\\treturn {\\n\\t\\t\\t\\twidth: w,\\n\\t\\t\\t\\theight: h,\\n\\t\\t\\t\\tdata: data\\n\\t\\t};\\n};\\nconst hemisphereSamplePhong = (dstVec, x, y, specularPower)=>{\\n\\t\\tconst phi = y * 2 * Math.PI;\\n\\t\\tconst cosTheta = Math.pow(1 - x, 1 / (specularPower + 1));\\n\\t\\tconst sinTheta = Math.sqrt(1 - cosTheta * cosTheta);\\n\\t\\tdstVec.set(Math.cos(phi) * sinTheta, Math.sin(phi) * sinTheta, cosTheta).normalize();\\n};\\nconst hemisphereSampleLambert = (dstVec, x, y)=>{\\n\\t\\tconst phi = y * 2 * Math.PI;\\n\\t\\tconst cosTheta = Math.sqrt(1 - x);\\n\\t\\tconst sinTheta = Math.sqrt(x);\\n\\t\\tdstVec.set(Math.cos(phi) * sinTheta, Math.sin(phi) * sinTheta, cosTheta).normalize();\\n};\\nconst hemisphereSampleGGX = (dstVec, x, y, a)=>{\\n\\t\\tconst phi = y * 2 * Math.PI;\\n\\t\\tconst cosTheta = Math.sqrt((1 - x) / (1 + (a * a - 1) * x));\\n\\t\\tconst sinTheta = Math.sqrt(1 - cosTheta * cosTheta);\\n\\t\\tdstVec.set(Math.cos(phi) * sinTheta, Math.sin(phi) * sinTheta, cosTheta).normalize();\\n};\\nconst D_GGX = (NoH, linearRoughness)=>{\\n\\t\\tconst a = NoH * linearRoughness;\\n\\t\\tconst k = linearRoughness / (1.0 - NoH * NoH + a * a);\\n\\t\\treturn k * k * (1 / Math.PI);\\n};\\nconst generatePhongSamples = (numSamples, specularPower)=>{\\n\\t\\tconst H = new Vec3();\\n\\t\\tconst result = [];\\n\\t\\tfor(let i = 0; i < numSamples; ++i){\\n\\t\\t\\t\\themisphereSamplePhong(H, i / numSamples, random.radicalInverse(i), specularPower);\\n\\t\\t\\t\\tresult.push(H.x, H.y, H.z, 0);\\n\\t\\t}\\n\\t\\treturn result;\\n};\\nconst generateLambertSamples = (numSamples, sourceTotalPixels)=>{\\n\\t\\tconst pixelsPerSample = sourceTotalPixels / numSamples;\\n\\t\\tconst H = new Vec3();\\n\\t\\tconst result = [];\\n\\t\\tfor(let i = 0; i < numSamples; ++i){\\n\\t\\t\\t\\themisphereSampleLambert(H, i / numSamples, random.radicalInverse(i));\\n\\t\\t\\t\\tconst pdf = H.z / Math.PI;\\n\\t\\t\\t\\tconst mipLevel = 0.5 * Math.log2(pixelsPerSample / pdf);\\n\\t\\t\\t\\tresult.push(H.x, H.y, H.z, mipLevel);\\n\\t\\t}\\n\\t\\treturn result;\\n};\\nconst requiredSamplesGGX = {\\n\\t\\t'16': {\\n\\t\\t\\t\\t'2': 26,\\n\\t\\t\\t\\t'8': 20,\\n\\t\\t\\t\\t'32': 17,\\n\\t\\t\\t\\t'128': 16,\\n\\t\\t\\t\\t'512': 16\\n\\t\\t},\\n\\t\\t'32': {\\n\\t\\t\\t\\t'2': 53,\\n\\t\\t\\t\\t'8': 40,\\n\\t\\t\\t\\t'32': 34,\\n\\t\\t\\t\\t'128': 32,\\n\\t\\t\\t\\t'512': 32\\n\\t\\t},\\n\\t\\t'128': {\\n\\t\\t\\t\\t'2': 214,\\n\\t\\t\\t\\t'8': 163,\\n\\t\\t\\t\\t'32': 139,\\n\\t\\t\\t\\t'128': 130,\\n\\t\\t\\t\\t'512': 128\\n\\t\\t},\\n\\t\\t'1024': {\\n\\t\\t\\t\\t'2': 1722,\\n\\t\\t\\t\\t'8': 1310,\\n\\t\\t\\t\\t'32': 1114,\\n\\t\\t\\t\\t'128': 1041,\\n\\t\\t\\t\\t'512': 1025\\n\\t\\t}\\n};\\nconst getRequiredSamplesGGX = (numSamples, specularPower)=>{\\n\\t\\tconst table = requiredSamplesGGX[numSamples];\\n\\t\\treturn table && table[specularPower] || numSamples;\\n};\\nconst generateGGXSamples = (numSamples, specularPower, sourceTotalPixels)=>{\\n\\t\\tconst pixelsPerSample = sourceTotalPixels / numSamples;\\n\\t\\tconst roughness = 1 - Math.log2(specularPower) / 11.0;\\n\\t\\tconst a = roughness * roughness;\\n\\t\\tconst H = new Vec3();\\n\\t\\tconst L = new Vec3();\\n\\t\\tconst N = new Vec3(0, 0, 1);\\n\\t\\tconst result = [];\\n\\t\\tconst requiredSamples = getRequiredSamplesGGX(numSamples, specularPower);\\n\\t\\tfor(let i = 0; i < requiredSamples; ++i){\\n\\t\\t\\t\\themisphereSampleGGX(H, i / requiredSamples, random.radicalInverse(i), a);\\n\\t\\t\\t\\tconst NoH = H.z;\\n\\t\\t\\t\\tL.set(H.x, H.y, H.z).mulScalar(2 * NoH).sub(N);\\n\\t\\t\\t\\tif (L.z > 0) {\\n\\t\\t\\t\\t\\t\\tconst pdf = D_GGX(Math.min(1, NoH), a) / 4 + 0.001;\\n\\t\\t\\t\\t\\t\\tconst mipLevel = 0.5 * Math.log2(pixelsPerSample / pdf);\\n\\t\\t\\t\\t\\t\\tresult.push(L.x, L.y, L.z, mipLevel);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\twhile(result.length < numSamples * 4){\\n\\t\\t\\t\\tresult.push(0, 0, 0, 0);\\n\\t\\t}\\n\\t\\treturn result;\\n};\\nconst createSamplesTex = (device, name, samples)=>{\\n\\t\\tconst packedSamples = packSamples(samples);\\n\\t\\treturn new Texture(device, {\\n\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\twidth: packedSamples.width,\\n\\t\\t\\t\\theight: packedSamples.height,\\n\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\tlevels: [\\n\\t\\t\\t\\t\\t\\tpackedSamples.data\\n\\t\\t\\t\\t]\\n\\t\\t});\\n};\\nclass SimpleCache {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tif (this.destroyContent) {\\n\\t\\t\\t\\t\\t\\tthis.map.forEach((value, key)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tvalue.destroy();\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget(key, missFunc) {\\n\\t\\t\\t\\tif (!this.map.has(key)) {\\n\\t\\t\\t\\t\\t\\tconst result = missFunc();\\n\\t\\t\\t\\t\\t\\tthis.map.set(key, result);\\n\\t\\t\\t\\t\\t\\treturn result;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.map.get(key);\\n\\t\\t}\\n\\t\\tconstructor(destroyContent = true){\\n\\t\\t\\t\\tthis.map = new Map();\\n\\t\\t\\t\\tthis.destroyContent = destroyContent;\\n\\t\\t}\\n}\\nconst samplesCache = new SimpleCache(false);\\nconst deviceCache$1 = new DeviceCache();\\nconst getCachedTexture = (device, key, getSamplesFnc)=>{\\n\\t\\tconst cache = deviceCache$1.get(device, ()=>{\\n\\t\\t\\t\\treturn new SimpleCache();\\n\\t\\t});\\n\\t\\treturn cache.get(key, ()=>{\\n\\t\\t\\t\\treturn createSamplesTex(device, key, samplesCache.get(key, getSamplesFnc));\\n\\t\\t});\\n};\\nconst generateLambertSamplesTex = (device, numSamples, sourceTotalPixels)=>{\\n\\t\\tconst key = `lambert-samples-${numSamples}-${sourceTotalPixels}`;\\n\\t\\treturn getCachedTexture(device, key, ()=>{\\n\\t\\t\\t\\treturn generateLambertSamples(numSamples, sourceTotalPixels);\\n\\t\\t});\\n};\\nconst generatePhongSamplesTex = (device, numSamples, specularPower)=>{\\n\\t\\tconst key = `phong-samples-${numSamples}-${specularPower}`;\\n\\t\\treturn getCachedTexture(device, key, ()=>{\\n\\t\\t\\t\\treturn generatePhongSamples(numSamples, specularPower);\\n\\t\\t});\\n};\\nconst generateGGXSamplesTex = (device, numSamples, specularPower, sourceTotalPixels)=>{\\n\\t\\tconst key = `ggx-samples-${numSamples}-${specularPower}-${sourceTotalPixels}`;\\n\\t\\treturn getCachedTexture(device, key, ()=>{\\n\\t\\t\\t\\treturn generateGGXSamples(numSamples, specularPower, sourceTotalPixels);\\n\\t\\t});\\n};\\nfunction reprojectTexture(source, target, options = {}) {\\n\\t\\tconst seamPixels = options.seamPixels ?? 0;\\n\\t\\tconst innerWidth = (options.rect?.z ?? target.width) - seamPixels * 2;\\n\\t\\tconst innerHeight = (options.rect?.w ?? target.height) - seamPixels * 2;\\n\\t\\tif (innerWidth < 1 || innerHeight < 1) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tconst funcNames = {\\n\\t\\t\\t\\t'none': 'reproject',\\n\\t\\t\\t\\t'lambert': 'prefilterSamplesUnweighted',\\n\\t\\t\\t\\t'phong': 'prefilterSamplesUnweighted',\\n\\t\\t\\t\\t'ggx': 'prefilterSamples'\\n\\t\\t};\\n\\t\\tconst specularPower = options.hasOwnProperty('specularPower') ? options.specularPower : 1;\\n\\t\\tconst face = options.hasOwnProperty('face') ? options.face : null;\\n\\t\\tconst distribution = options.hasOwnProperty('distribution') ? options.distribution : specularPower === 1 ? 'none' : 'phong';\\n\\t\\tconst processFunc = funcNames[distribution] || 'reproject';\\n\\t\\tconst prefilterSamples = processFunc.startsWith('prefilterSamples');\\n\\t\\tconst decodeFunc = ChunkUtils.decodeFunc(source.encoding);\\n\\t\\tconst encodeFunc = ChunkUtils.encodeFunc(target.encoding);\\n\\t\\tconst sourceFunc = `sample${getProjectionName(source.projection)}`;\\n\\t\\tconst targetFunc = `getDirection${getProjectionName(target.projection)}`;\\n\\t\\tconst numSamples = options.hasOwnProperty('numSamples') ? options.numSamples : 1024;\\n\\t\\tconst shaderKey = `ReprojectShader:${processFunc}_${decodeFunc}_${encodeFunc}_${sourceFunc}_${targetFunc}_${numSamples}`;\\n\\t\\tconst device = source.device;\\n\\t\\tlet shader = getProgramLibrary(device).getCachedShader(shaderKey);\\n\\t\\tif (!shader) {\\n\\t\\t\\t\\tconst defines = new Map();\\n\\t\\t\\t\\tif (prefilterSamples) defines.set('USE_SAMPLES_TEX', '');\\n\\t\\t\\t\\tif (source.cubemap) defines.set('CUBEMAP_SOURCE', '');\\n\\t\\t\\t\\tdefines.set('{PROCESS_FUNC}', processFunc);\\n\\t\\t\\t\\tdefines.set('{DECODE_FUNC}', decodeFunc);\\n\\t\\t\\t\\tdefines.set('{ENCODE_FUNC}', encodeFunc);\\n\\t\\t\\t\\tdefines.set('{SOURCE_FUNC}', sourceFunc);\\n\\t\\t\\t\\tdefines.set('{TARGET_FUNC}', targetFunc);\\n\\t\\t\\t\\tdefines.set('{NUM_SAMPLES}', numSamples);\\n\\t\\t\\t\\tdefines.set('{NUM_SAMPLES_SQRT}', Math.round(Math.sqrt(numSamples)).toFixed(1));\\n\\t\\t\\t\\tconst wgsl = device.isWebGPU;\\n\\t\\t\\t\\tconst chunks = ShaderChunks.get(device, wgsl ? SHADERLANGUAGE_WGSL : SHADERLANGUAGE_GLSL);\\n\\t\\t\\t\\tconst includes = new Map();\\n\\t\\t\\t\\tincludes.set('decodePS', chunks.get('decodePS'));\\n\\t\\t\\t\\tincludes.set('encodePS', chunks.get('encodePS'));\\n\\t\\t\\t\\tshader = ShaderUtils.createShader(device, {\\n\\t\\t\\t\\t\\t\\tuniqueName: shaderKey,\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tvertexChunk: 'reprojectVS',\\n\\t\\t\\t\\t\\t\\tfragmentChunk: 'reprojectPS',\\n\\t\\t\\t\\t\\t\\tfragmentIncludes: includes,\\n\\t\\t\\t\\t\\t\\tfragmentDefines: defines\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tdevice.setBlendState(BlendState.NOBLEND);\\n\\t\\tconst constantSource = device.scope.resolve(source.cubemap ? 'sourceCube' : 'sourceTex');\\n\\t\\tconstantSource.setValue(source);\\n\\t\\tconst constantParams = device.scope.resolve('params');\\n\\t\\tconst uvModParam = device.scope.resolve('uvMod');\\n\\t\\tif (seamPixels > 0) {\\n\\t\\t\\t\\tuvModParam.setValue([\\n\\t\\t\\t\\t\\t\\t(innerWidth + seamPixels * 2) / innerWidth,\\n\\t\\t\\t\\t\\t\\t(innerHeight + seamPixels * 2) / innerHeight,\\n\\t\\t\\t\\t\\t\\t-seamPixels / innerWidth,\\n\\t\\t\\t\\t\\t\\t-seamPixels / innerHeight\\n\\t\\t\\t\\t]);\\n\\t\\t} else {\\n\\t\\t\\t\\tuvModParam.setValue([\\n\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tconst params = [\\n\\t\\t\\t\\t0,\\n\\t\\t\\t\\ttarget.width * target.height * (target.cubemap ? 6 : 1),\\n\\t\\t\\t\\tsource.width * source.height * (source.cubemap ? 6 : 1)\\n\\t\\t];\\n\\t\\tif (prefilterSamples) {\\n\\t\\t\\t\\tconst sourceTotalPixels = source.width * source.height * (source.cubemap ? 6 : 1);\\n\\t\\t\\t\\tconst samplesTex = distribution === 'ggx' ? generateGGXSamplesTex(device, numSamples, specularPower, sourceTotalPixels) : distribution === 'lambert' ? generateLambertSamplesTex(device, numSamples, sourceTotalPixels) : generatePhongSamplesTex(device, numSamples, specularPower);\\n\\t\\t\\t\\tdevice.scope.resolve('samplesTex').setValue(samplesTex);\\n\\t\\t\\t\\tdevice.scope.resolve('samplesTexInverseSize').setValue([\\n\\t\\t\\t\\t\\t\\t1.0 / samplesTex.width,\\n\\t\\t\\t\\t\\t\\t1.0 / samplesTex.height\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tfor(let f = 0; f < (target.cubemap ? 6 : 1); f++){\\n\\t\\t\\t\\tif (face === null || f === face) {\\n\\t\\t\\t\\t\\t\\tconst renderTarget = new RenderTarget({\\n\\t\\t\\t\\t\\t\\t\\t\\tcolorBuffer: target,\\n\\t\\t\\t\\t\\t\\t\\t\\tface: f,\\n\\t\\t\\t\\t\\t\\t\\t\\tdepth: false,\\n\\t\\t\\t\\t\\t\\t\\t\\tflipY: device.isWebGPU\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tparams[0] = f;\\n\\t\\t\\t\\t\\t\\tconstantParams.setValue(params);\\n\\t\\t\\t\\t\\t\\tdrawQuadWithShader(device, renderTarget, shader, options?.rect);\\n\\t\\t\\t\\t\\t\\trenderTarget.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn true;\\n}\\n\\nconst calcLevels = (width, height = 0)=>{\\n\\t\\treturn 1 + Math.floor(Math.log2(Math.max(width, height)));\\n};\\nconst supportsFloat16 = (device)=>{\\n\\t\\treturn device.textureHalfFloatRenderable;\\n};\\nconst supportsFloat32 = (device)=>{\\n\\t\\treturn device.textureFloatRenderable;\\n};\\nconst lightingSourcePixelFormat = (device)=>{\\n\\t\\treturn supportsFloat16(device) ? PIXELFORMAT_RGBA16F : supportsFloat32(device) ? PIXELFORMAT_RGBA32F : PIXELFORMAT_RGBA8;\\n};\\nconst lightingPixelFormat = (device)=>{\\n\\t\\treturn PIXELFORMAT_RGBA8;\\n};\\nconst createCubemap = (device, size, format, mipmaps)=>{\\n\\t\\treturn new Texture(device, {\\n\\t\\t\\t\\tname: `lighting-${size}`,\\n\\t\\t\\t\\tcubemap: true,\\n\\t\\t\\t\\twidth: size,\\n\\t\\t\\t\\theight: size,\\n\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\ttype: TEXTURETYPE_RGBP ,\\n\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\tmipmaps: false\\n\\t\\t});\\n};\\nclass EnvLighting {\\n\\t\\tstatic generateSkyboxCubemap(source, size) {\\n\\t\\t\\t\\tconst device = source.device;\\n\\t\\t\\t\\tconst result = createCubemap(device, size || (source.cubemap ? source.width : source.width / 4), PIXELFORMAT_RGBA8);\\n\\t\\t\\t\\treprojectTexture(source, result, {\\n\\t\\t\\t\\t\\t\\tnumSamples: 1024\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tstatic generateLightingSource(source, options) {\\n\\t\\t\\t\\tconst device = source.device;\\n\\t\\t\\t\\tconst format = lightingSourcePixelFormat(device);\\n\\t\\t\\t\\tconst result = options?.target || new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: 'lighting-source',\\n\\t\\t\\t\\t\\t\\tcubemap: true,\\n\\t\\t\\t\\t\\t\\twidth: options?.size || 128,\\n\\t\\t\\t\\t\\t\\theight: options?.size || 128,\\n\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\ttype: format === PIXELFORMAT_RGBA8 ? TEXTURETYPE_RGBP : TEXTURETYPE_DEFAULT,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\tmipmaps: true\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treprojectTexture(source, result, {\\n\\t\\t\\t\\t\\t\\tnumSamples: source.mipmaps ? 1 : 1024\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tstatic generateAtlas(source, options) {\\n\\t\\t\\t\\tconst device = source.device;\\n\\t\\t\\t\\tconst format = lightingPixelFormat();\\n\\t\\t\\t\\tconst result = options?.target || new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: 'envAtlas',\\n\\t\\t\\t\\t\\t\\twidth: options?.size || 512,\\n\\t\\t\\t\\t\\t\\theight: options?.size || 512,\\n\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\ttype: TEXTURETYPE_RGBP ,\\n\\t\\t\\t\\t\\t\\tprojection: TEXTUREPROJECTION_EQUIRECT,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\tmipmaps: false\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst s = result.width / 512;\\n\\t\\t\\t\\tconst rect = new Vec4(0, 0, 512 * s, 256 * s);\\n\\t\\t\\t\\tconst levels = calcLevels(256) - calcLevels(4);\\n\\t\\t\\t\\tfor(let i = 0; i < levels; ++i){\\n\\t\\t\\t\\t\\t\\treprojectTexture(source, result, {\\n\\t\\t\\t\\t\\t\\t\\t\\tnumSamples: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\trect: rect,\\n\\t\\t\\t\\t\\t\\t\\t\\tseamPixels: s\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\trect.x += rect.w;\\n\\t\\t\\t\\t\\t\\trect.y += rect.w;\\n\\t\\t\\t\\t\\t\\trect.z = Math.max(1, Math.floor(rect.z * 0.5));\\n\\t\\t\\t\\t\\t\\trect.w = Math.max(1, Math.floor(rect.w * 0.5));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\trect.set(0, 256 * s, 256 * s, 128 * s);\\n\\t\\t\\t\\tfor(let i = 1; i < 7; ++i){\\n\\t\\t\\t\\t\\t\\treprojectTexture(source, result, {\\n\\t\\t\\t\\t\\t\\t\\t\\tnumSamples: options?.numReflectionSamples || 1024,\\n\\t\\t\\t\\t\\t\\t\\t\\tdistribution: options?.distribution || 'ggx',\\n\\t\\t\\t\\t\\t\\t\\t\\tspecularPower: Math.max(1, 2048 >> i * 2),\\n\\t\\t\\t\\t\\t\\t\\t\\trect: rect,\\n\\t\\t\\t\\t\\t\\t\\t\\tseamPixels: s\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\trect.y += rect.w;\\n\\t\\t\\t\\t\\t\\trect.z = Math.max(1, Math.floor(rect.z * 0.5));\\n\\t\\t\\t\\t\\t\\trect.w = Math.max(1, Math.floor(rect.w * 0.5));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\trect.set(128 * s, (256 + 128) * s, 64 * s, 32 * s);\\n\\t\\t\\t\\treprojectTexture(source, result, {\\n\\t\\t\\t\\t\\t\\tnumSamples: options?.numAmbientSamples || 2048,\\n\\t\\t\\t\\t\\t\\tdistribution: 'lambert',\\n\\t\\t\\t\\t\\t\\trect: rect,\\n\\t\\t\\t\\t\\t\\tseamPixels: s\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tstatic generatePrefilteredAtlas(sources, options) {\\n\\t\\t\\t\\tconst device = sources[0].device;\\n\\t\\t\\t\\tconst format = sources[0].format;\\n\\t\\t\\t\\tconst type = sources[0].type;\\n\\t\\t\\t\\tconst result = options?.target || new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: 'envPrefilteredAtlas',\\n\\t\\t\\t\\t\\t\\twidth: options?.size || 512,\\n\\t\\t\\t\\t\\t\\theight: options?.size || 512,\\n\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\ttype: type,\\n\\t\\t\\t\\t\\t\\tprojection: TEXTUREPROJECTION_EQUIRECT,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\tmipmaps: false\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst s = result.width / 512;\\n\\t\\t\\t\\tconst rect = new Vec4(0, 0, 512 * s, 256 * s);\\n\\t\\t\\t\\tconst levels = calcLevels(512);\\n\\t\\t\\t\\tfor(let i = 0; i < levels; ++i){\\n\\t\\t\\t\\t\\t\\treprojectTexture(sources[0], result, {\\n\\t\\t\\t\\t\\t\\t\\t\\tnumSamples: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\trect: rect,\\n\\t\\t\\t\\t\\t\\t\\t\\tseamPixels: s\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\trect.x += rect.w;\\n\\t\\t\\t\\t\\t\\trect.y += rect.w;\\n\\t\\t\\t\\t\\t\\trect.z = Math.max(1, Math.floor(rect.z * 0.5));\\n\\t\\t\\t\\t\\t\\trect.w = Math.max(1, Math.floor(rect.w * 0.5));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\trect.set(0, 256 * s, 256 * s, 128 * s);\\n\\t\\t\\t\\tfor(let i = 1; i < sources.length; ++i){\\n\\t\\t\\t\\t\\t\\treprojectTexture(sources[i], result, {\\n\\t\\t\\t\\t\\t\\t\\t\\tnumSamples: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\trect: rect,\\n\\t\\t\\t\\t\\t\\t\\t\\tseamPixels: s\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\trect.y += rect.w;\\n\\t\\t\\t\\t\\t\\trect.z = Math.max(1, Math.floor(rect.z * 0.5));\\n\\t\\t\\t\\t\\t\\trect.w = Math.max(1, Math.floor(rect.w * 0.5));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\trect.set(128 * s, (256 + 128) * s, 64 * s, 32 * s);\\n\\t\\t\\t\\tif (options?.legacyAmbient) {\\n\\t\\t\\t\\t\\t\\treprojectTexture(sources[5], result, {\\n\\t\\t\\t\\t\\t\\t\\t\\tnumSamples: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\trect: rect,\\n\\t\\t\\t\\t\\t\\t\\t\\tseamPixels: s\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\treprojectTexture(sources[0], result, {\\n\\t\\t\\t\\t\\t\\t\\t\\tnumSamples: options?.numSamples || 2048,\\n\\t\\t\\t\\t\\t\\t\\t\\tdistribution: 'lambert',\\n\\t\\t\\t\\t\\t\\t\\t\\trect: rect,\\n\\t\\t\\t\\t\\t\\t\\t\\tseamPixels: s\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n}\\n\\nclass FogParams {\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.type = FOG_NONE;\\n\\t\\t\\t\\tthis.color = new Color(0, 0, 0);\\n\\t\\t\\t\\tthis.density = 0;\\n\\t\\t\\t\\tthis.start = 1;\\n\\t\\t\\t\\tthis.end = 1000;\\n\\t\\t}\\n}\\n\\nclass Scene extends EventHandler {\\n\\t\\tget defaultDrawLayer() {\\n\\t\\t\\t\\treturn this.layers.getLayerById(LAYERID_IMMEDIATE);\\n\\t\\t}\\n\\t\\tset ambientBakeNumSamples(value) {\\n\\t\\t\\t\\tthis._ambientBakeNumSamples = math.clamp(Math.floor(value), 1, 255);\\n\\t\\t}\\n\\t\\tget ambientBakeNumSamples() {\\n\\t\\t\\t\\treturn this._ambientBakeNumSamples;\\n\\t\\t}\\n\\t\\tset ambientBakeSpherePart(value) {\\n\\t\\t\\t\\tthis._ambientBakeSpherePart = math.clamp(value, 0.001, 1);\\n\\t\\t}\\n\\t\\tget ambientBakeSpherePart() {\\n\\t\\t\\t\\treturn this._ambientBakeSpherePart;\\n\\t\\t}\\n\\t\\tset clusteredLightingEnabled(value) {\\n\\t\\t\\t\\tif (this.device.isWebGPU && !value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._clusteredLightingEnabled && value) {\\n\\t\\t\\t\\t\\t\\tconsole.error('Turning on disabled clustered lighting is not currently supported');\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._clusteredLightingEnabled = value;\\n\\t\\t}\\n\\t\\tget clusteredLightingEnabled() {\\n\\t\\t\\t\\treturn this._clusteredLightingEnabled;\\n\\t\\t}\\n\\t\\tset envAtlas(value) {\\n\\t\\t\\t\\tif (value !== this._envAtlas) {\\n\\t\\t\\t\\t\\t\\tthis._envAtlas = value;\\n\\t\\t\\t\\t\\t\\tif (value) {\\n\\t\\t\\t\\t\\t\\t\\t\\tvalue.addressU = ADDRESS_CLAMP_TO_EDGE;\\n\\t\\t\\t\\t\\t\\t\\t\\tvalue.addressV = ADDRESS_CLAMP_TO_EDGE;\\n\\t\\t\\t\\t\\t\\t\\t\\tvalue.minFilter = FILTER_LINEAR;\\n\\t\\t\\t\\t\\t\\t\\t\\tvalue.magFilter = FILTER_LINEAR;\\n\\t\\t\\t\\t\\t\\t\\t\\tvalue.mipmaps = false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._prefilteredCubemaps = [];\\n\\t\\t\\t\\t\\t\\tif (this._internalEnvAtlas) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._internalEnvAtlas.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._internalEnvAtlas = null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget envAtlas() {\\n\\t\\t\\t\\treturn this._envAtlas;\\n\\t\\t}\\n\\t\\tset layers(layers) {\\n\\t\\t\\t\\tconst prev = this._layers;\\n\\t\\t\\t\\tthis._layers = layers;\\n\\t\\t\\t\\tthis.fire('set:layers', prev, layers);\\n\\t\\t}\\n\\t\\tget layers() {\\n\\t\\t\\t\\treturn this._layers;\\n\\t\\t}\\n\\t\\tget sky() {\\n\\t\\t\\t\\treturn this._sky;\\n\\t\\t}\\n\\t\\tget lighting() {\\n\\t\\t\\t\\treturn this._lightingParams;\\n\\t\\t}\\n\\t\\tget gsplat() {\\n\\t\\t\\t\\treturn this._gsplatParams;\\n\\t\\t}\\n\\t\\tget fog() {\\n\\t\\t\\t\\treturn this._fogParams;\\n\\t\\t}\\n\\t\\tset lightmapFilterRange(value) {\\n\\t\\t\\t\\tthis._lightmapFilterRange = Math.max(value, 0.001);\\n\\t\\t}\\n\\t\\tget lightmapFilterRange() {\\n\\t\\t\\t\\treturn this._lightmapFilterRange;\\n\\t\\t}\\n\\t\\tset lightmapFilterSmoothness(value) {\\n\\t\\t\\t\\tthis._lightmapFilterSmoothness = Math.max(value, 0.001);\\n\\t\\t}\\n\\t\\tget lightmapFilterSmoothness() {\\n\\t\\t\\t\\treturn this._lightmapFilterSmoothness;\\n\\t\\t}\\n\\t\\tset prefilteredCubemaps(value) {\\n\\t\\t\\t\\tvalue = value || [];\\n\\t\\t\\t\\tconst cubemaps = this._prefilteredCubemaps;\\n\\t\\t\\t\\tconst changed = cubemaps.length !== value.length || cubemaps.some((c, i)=>c !== value[i]);\\n\\t\\t\\t\\tif (changed) {\\n\\t\\t\\t\\t\\t\\tconst complete = value.length === 6 && value.every((c)=>!!c);\\n\\t\\t\\t\\t\\t\\tif (complete) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._internalEnvAtlas = EnvLighting.generatePrefilteredAtlas(value, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttarget: this._internalEnvAtlas\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._envAtlas = this._internalEnvAtlas;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._internalEnvAtlas) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._internalEnvAtlas.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._internalEnvAtlas = null;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._envAtlas = null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._prefilteredCubemaps = value.slice();\\n\\t\\t\\t\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget prefilteredCubemaps() {\\n\\t\\t\\t\\treturn this._prefilteredCubemaps;\\n\\t\\t}\\n\\t\\tset skybox(value) {\\n\\t\\t\\t\\tif (value !== this._skyboxCubeMap) {\\n\\t\\t\\t\\t\\t\\tthis._skyboxCubeMap = value;\\n\\t\\t\\t\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget skybox() {\\n\\t\\t\\t\\treturn this._skyboxCubeMap;\\n\\t\\t}\\n\\t\\tset skyboxIntensity(value) {\\n\\t\\t\\t\\tif (value !== this._skyboxIntensity) {\\n\\t\\t\\t\\t\\t\\tthis._skyboxIntensity = value;\\n\\t\\t\\t\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget skyboxIntensity() {\\n\\t\\t\\t\\treturn this._skyboxIntensity;\\n\\t\\t}\\n\\t\\tset skyboxLuminance(value) {\\n\\t\\t\\t\\tif (value !== this._skyboxLuminance) {\\n\\t\\t\\t\\t\\t\\tthis._skyboxLuminance = value;\\n\\t\\t\\t\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget skyboxLuminance() {\\n\\t\\t\\t\\treturn this._skyboxLuminance;\\n\\t\\t}\\n\\t\\tset skyboxMip(value) {\\n\\t\\t\\t\\tif (value !== this._skyboxMip) {\\n\\t\\t\\t\\t\\t\\tthis._skyboxMip = value;\\n\\t\\t\\t\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget skyboxMip() {\\n\\t\\t\\t\\treturn this._skyboxMip;\\n\\t\\t}\\n\\t\\tset skyboxHighlightMultiplier(value) {\\n\\t\\t\\t\\tif (value !== this._skyboxHighlightMultiplier) {\\n\\t\\t\\t\\t\\t\\tthis._skyboxHighlightMultiplier = value;\\n\\t\\t\\t\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget skyboxHighlightMultiplier() {\\n\\t\\t\\t\\treturn this._skyboxHighlightMultiplier;\\n\\t\\t}\\n\\t\\tset skyboxRotation(value) {\\n\\t\\t\\t\\tif (!this._skyboxRotation.equals(value)) {\\n\\t\\t\\t\\t\\t\\tconst isIdentity = value.equals(Quat.IDENTITY);\\n\\t\\t\\t\\t\\t\\tthis._skyboxRotation.copy(value);\\n\\t\\t\\t\\t\\t\\tif (isIdentity) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._skyboxRotationMat3.setIdentity();\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._skyboxRotationMat4.setTRS(Vec3.ZERO, value, Vec3.ONE);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._skyboxRotationMat3.invertMat4(this._skyboxRotationMat4);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!this._skyboxRotationShaderInclude && !isIdentity) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._skyboxRotationShaderInclude = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget skyboxRotation() {\\n\\t\\t\\t\\treturn this._skyboxRotation;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t\\t\\tthis.root = null;\\n\\t\\t\\t\\tthis.off();\\n\\t\\t}\\n\\t\\tdrawLine(start, end, color = Color.WHITE, depthTest = true, layer = this.defaultDrawLayer) {\\n\\t\\t\\t\\tconst batch = this.immediate.getBatch(layer, depthTest);\\n\\t\\t\\t\\tbatch.addLines([\\n\\t\\t\\t\\t\\t\\tstart,\\n\\t\\t\\t\\t\\t\\tend\\n\\t\\t\\t\\t], [\\n\\t\\t\\t\\t\\t\\tcolor,\\n\\t\\t\\t\\t\\t\\tcolor\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tdrawLines(positions, colors, depthTest = true, layer = this.defaultDrawLayer) {\\n\\t\\t\\t\\tconst batch = this.immediate.getBatch(layer, depthTest);\\n\\t\\t\\t\\tbatch.addLines(positions, colors);\\n\\t\\t}\\n\\t\\tdrawLineArrays(positions, colors, depthTest = true, layer = this.defaultDrawLayer) {\\n\\t\\t\\t\\tconst batch = this.immediate.getBatch(layer, depthTest);\\n\\t\\t\\t\\tbatch.addLinesArrays(positions, colors);\\n\\t\\t}\\n\\t\\tapplySettings(settings) {\\n\\t\\t\\t\\tconst physics = settings.physics;\\n\\t\\t\\t\\tconst render = settings.render;\\n\\t\\t\\t\\tthis._gravity.set(physics.gravity[0], physics.gravity[1], physics.gravity[2]);\\n\\t\\t\\t\\tthis.ambientLight.set(render.global_ambient[0], render.global_ambient[1], render.global_ambient[2]);\\n\\t\\t\\t\\tthis.ambientLuminance = render.ambientLuminance;\\n\\t\\t\\t\\tthis.fog.type = render.fog;\\n\\t\\t\\t\\tthis.fog.color.set(render.fog_color[0], render.fog_color[1], render.fog_color[2]);\\n\\t\\t\\t\\tthis.fog.start = render.fog_start;\\n\\t\\t\\t\\tthis.fog.end = render.fog_end;\\n\\t\\t\\t\\tthis.fog.density = render.fog_density;\\n\\t\\t\\t\\tthis.lightmapSizeMultiplier = render.lightmapSizeMultiplier;\\n\\t\\t\\t\\tthis.lightmapMaxResolution = render.lightmapMaxResolution;\\n\\t\\t\\t\\tthis.lightmapMode = render.lightmapMode;\\n\\t\\t\\t\\tthis.exposure = render.exposure;\\n\\t\\t\\t\\tthis._skyboxIntensity = render.skyboxIntensity ?? 1;\\n\\t\\t\\t\\tthis._skyboxLuminance = render.skyboxLuminance ?? 20000;\\n\\t\\t\\t\\tthis._skyboxMip = render.skyboxMip ?? 0;\\n\\t\\t\\t\\tif (render.skyboxRotation) {\\n\\t\\t\\t\\t\\t\\tthis.skyboxRotation = new Quat().setFromEulerAngles(render.skyboxRotation[0], render.skyboxRotation[1], render.skyboxRotation[2]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.sky.applySettings(render);\\n\\t\\t\\t\\tthis.clusteredLightingEnabled = render.clusteredLightingEnabled ?? false;\\n\\t\\t\\t\\tthis.lighting.applySettings(render);\\n\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t'lightmapFilterEnabled',\\n\\t\\t\\t\\t\\t\\t'lightmapFilterRange',\\n\\t\\t\\t\\t\\t\\t'lightmapFilterSmoothness',\\n\\t\\t\\t\\t\\t\\t'ambientBake',\\n\\t\\t\\t\\t\\t\\t'ambientBakeNumSamples',\\n\\t\\t\\t\\t\\t\\t'ambientBakeSpherePart',\\n\\t\\t\\t\\t\\t\\t'ambientBakeOcclusionBrightness',\\n\\t\\t\\t\\t\\t\\t'ambientBakeOcclusionContrast'\\n\\t\\t\\t\\t].forEach((setting)=>{\\n\\t\\t\\t\\t\\t\\tif (render.hasOwnProperty(setting)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis[setting] = render[setting];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis._resetSkyMesh();\\n\\t\\t}\\n\\t\\t_getSkyboxTex() {\\n\\t\\t\\t\\tconst cubemaps = this._prefilteredCubemaps;\\n\\t\\t\\t\\tif (this._skyboxMip) {\\n\\t\\t\\t\\t\\t\\tconst skyboxMapping = [\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t\\t\\t3,\\n\\t\\t\\t\\t\\t\\t\\t\\t4,\\n\\t\\t\\t\\t\\t\\t\\t\\t5,\\n\\t\\t\\t\\t\\t\\t\\t\\t6\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t\\t\\treturn cubemaps[skyboxMapping[this._skyboxMip]] || this._envAtlas || cubemaps[0] || this._skyboxCubeMap;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._skyboxCubeMap || cubemaps[0] || this._envAtlas;\\n\\t\\t}\\n\\t\\t_updateSkyMesh() {\\n\\t\\t\\t\\tif (!this.sky.skyMesh) {\\n\\t\\t\\t\\t\\t\\tthis.sky.updateSkyMesh();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.sky.update();\\n\\t\\t}\\n\\t\\t_resetSkyMesh() {\\n\\t\\t\\t\\tthis.sky.resetSkyMesh();\\n\\t\\t\\t\\tthis.updateShaders = true;\\n\\t\\t}\\n\\t\\tsetSkybox(cubemaps) {\\n\\t\\t\\t\\tif (!cubemaps) {\\n\\t\\t\\t\\t\\t\\tthis.skybox = null;\\n\\t\\t\\t\\t\\t\\tthis.envAtlas = null;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.skybox = cubemaps[0] || null;\\n\\t\\t\\t\\t\\t\\tif (cubemaps[1] && !cubemaps[1].cubemap) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.envAtlas = cubemaps[1];\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.prefilteredCubemaps = cubemaps.slice(1);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget lightmapPixelFormat() {\\n\\t\\t\\t\\treturn this.lightmapHDR && this.device.getRenderableHdrFormat() || PIXELFORMAT_RGBA8;\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice){\\n\\t\\t\\t\\tsuper(), this.ambientBake = false, this.ambientBakeOcclusionBrightness = 0, this.ambientBakeOcclusionContrast = 0, this.ambientLight = new Color(0, 0, 0), this.ambientLuminance = 0, this.exposure = 1, this.lightmapSizeMultiplier = 1, this.lightmapMaxResolution = 2048, this.lightmapMode = BAKE_COLORDIR, this.lightmapFilterEnabled = false, this.lightmapHDR = false, this.root = null, this.physicalUnits = false, this._envAtlas = null, this._skyboxCubeMap = null, this._fogParams = new FogParams(), this.forcePassThroughSpecular = false;\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t\\t\\tthis._gravity = new Vec3(0, -9.8, 0);\\n\\t\\t\\t\\tthis._layers = null;\\n\\t\\t\\t\\tthis._prefilteredCubemaps = [];\\n\\t\\t\\t\\tthis._internalEnvAtlas = null;\\n\\t\\t\\t\\tthis._skyboxIntensity = 1;\\n\\t\\t\\t\\tthis._skyboxLuminance = 0;\\n\\t\\t\\t\\tthis._skyboxMip = 0;\\n\\t\\t\\t\\tthis._skyboxHighlightMultiplier = 1;\\n\\t\\t\\t\\tthis._skyboxRotationShaderInclude = false;\\n\\t\\t\\t\\tthis._skyboxRotation = new Quat();\\n\\t\\t\\t\\tthis._skyboxRotationMat3 = new Mat3();\\n\\t\\t\\t\\tthis._skyboxRotationMat4 = new Mat4();\\n\\t\\t\\t\\tthis._ambientBakeNumSamples = 1;\\n\\t\\t\\t\\tthis._ambientBakeSpherePart = 0.4;\\n\\t\\t\\t\\tthis._lightmapFilterRange = 10;\\n\\t\\t\\t\\tthis._lightmapFilterSmoothness = 0.2;\\n\\t\\t\\t\\tthis._clusteredLightingEnabled = true;\\n\\t\\t\\t\\tthis._lightingParams = new LightingParams(this.device.supportsAreaLights, this.device.maxTextureSize, ()=>{\\n\\t\\t\\t\\t\\t\\tthis.updateShaders = true;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis._gsplatParams = new GSplatParams(this.device);\\n\\t\\t\\t\\tthis._sky = new Sky(this);\\n\\t\\t\\t\\tthis._stats = {\\n\\t\\t\\t\\t\\t\\tmeshInstances: 0,\\n\\t\\t\\t\\t\\t\\tlights: 0,\\n\\t\\t\\t\\t\\t\\tdynamicLights: 0,\\n\\t\\t\\t\\t\\t\\tbakedLights: 0,\\n\\t\\t\\t\\t\\t\\tupdateShadersTime: 0\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.updateShaders = true;\\n\\t\\t\\t\\tthis._shaderVersion = 0;\\n\\t\\t\\t\\tthis.immediate = new Immediate(this.device);\\n\\t\\t}\\n}\\nScene.EVENT_SETLAYERS = 'set:layers';\\nScene.EVENT_SETSKYBOX = 'set:skybox';\\nScene.EVENT_PRERENDER = 'prerender';\\nScene.EVENT_POSTRENDER = 'postrender';\\nScene.EVENT_PRERENDER_LAYER = 'prerender:layer';\\nScene.EVENT_POSTRENDER_LAYER = 'postrender:layer';\\nScene.EVENT_PRECULL = 'precull';\\nScene.EVENT_POSTCULL = 'postcull';\\n\\nclass Skin {\\n\\t\\tconstructor(graphicsDevice, ibp, boneNames){\\n\\t\\t\\t\\tthis.device = graphicsDevice;\\n\\t\\t\\t\\tthis.inverseBindPose = ibp;\\n\\t\\t\\t\\tthis.boneNames = boneNames;\\n\\t\\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$2 = 16;\\nconst WORKGROUP_SIZE_Y$2 = 16;\\nconst THREADS_PER_WORKGROUP$2 = WORKGROUP_SIZE_X$2 * WORKGROUP_SIZE_Y$2;\\nconst ITEMS_PER_WORKGROUP = 2 * THREADS_PER_WORKGROUP$2;\\nclass PrefixSumKernel {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._destroyPasses();\\n\\t\\t\\t\\tthis._scanShader?.destroy();\\n\\t\\t\\t\\tthis._addBlockShader?.destroy();\\n\\t\\t\\t\\tthis._bindGroupFormat?.destroy();\\n\\t\\t\\t\\tthis._scanShader = null;\\n\\t\\t\\t\\tthis._addBlockShader = null;\\n\\t\\t\\t\\tthis._bindGroupFormat = null;\\n\\t\\t\\t\\tthis._uniformBufferFormat = null;\\n\\t\\t}\\n\\t\\t_createFormatsAndShaders() {\\n\\t\\t\\t\\tthis._uniformBufferFormat = new UniformBufferFormat(this.device, [\\n\\t\\t\\t\\t\\t\\tnew UniformFormat('elementCount', UNIFORMTYPE_UINT)\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tthis._bindGroupFormat = new BindGroupFormat(this.device, [\\n\\t\\t\\t\\t\\t\\tnew BindStorageBufferFormat('items', SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\t\\t\\t\\tnew BindStorageBufferFormat('blockSums', SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\t\\t\\t\\tnew BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE)\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tthis._scanShader = this._createShader('PrefixSumScan', 'reduce_downsweep');\\n\\t\\t\\t\\tthis._addBlockShader = this._createShader('PrefixSumAddBlock', 'add_block_sums');\\n\\t\\t}\\n\\t\\tcreatePassesRecursive(dataBuffer, count) {\\n\\t\\t\\t\\tconst workgroupCount = Math.ceil(count / ITEMS_PER_WORKGROUP);\\n\\t\\t\\t\\tconst { x: dispatchX, y: dispatchY } = this.findOptimalDispatchSize(workgroupCount);\\n\\t\\t\\t\\tconst blockSumBuffer = new StorageBuffer(this.device, workgroupCount * 4);\\n\\t\\t\\t\\tconst scanCompute = new Compute(this.device, this._scanShader, 'PrefixSumScan');\\n\\t\\t\\t\\tscanCompute.setParameter('items', dataBuffer);\\n\\t\\t\\t\\tscanCompute.setParameter('blockSums', blockSumBuffer);\\n\\t\\t\\t\\tconst pass = {\\n\\t\\t\\t\\t\\t\\tscanCompute,\\n\\t\\t\\t\\t\\t\\taddBlockCompute: null,\\n\\t\\t\\t\\t\\t\\tblockSumBuffer,\\n\\t\\t\\t\\t\\t\\tdispatchX,\\n\\t\\t\\t\\t\\t\\tdispatchY,\\n\\t\\t\\t\\t\\t\\tcount,\\n\\t\\t\\t\\t\\t\\tallocatedCount: count\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.passes.push(pass);\\n\\t\\t\\t\\tif (workgroupCount > 1) {\\n\\t\\t\\t\\t\\t\\tthis.createPassesRecursive(blockSumBuffer, workgroupCount);\\n\\t\\t\\t\\t\\t\\tconst addBlockCompute = new Compute(this.device, this._addBlockShader, 'PrefixSumAddBlock');\\n\\t\\t\\t\\t\\t\\taddBlockCompute.setParameter('items', dataBuffer);\\n\\t\\t\\t\\t\\t\\taddBlockCompute.setParameter('blockSums', blockSumBuffer);\\n\\t\\t\\t\\t\\t\\tpass.addBlockCompute = addBlockCompute;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_createShader(name, entryPoint) {\\n\\t\\t\\t\\tconst cdefines = new Map();\\n\\t\\t\\t\\tcdefines.set('{WORKGROUP_SIZE_X}', WORKGROUP_SIZE_X$2);\\n\\t\\t\\t\\tcdefines.set('{WORKGROUP_SIZE_Y}', WORKGROUP_SIZE_Y$2);\\n\\t\\t\\t\\tcdefines.set('{THREADS_PER_WORKGROUP}', THREADS_PER_WORKGROUP$2);\\n\\t\\t\\t\\tcdefines.set('{ITEMS_PER_WORKGROUP}', ITEMS_PER_WORKGROUP);\\n\\t\\t\\t\\treturn new Shader(this.device, {\\n\\t\\t\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\t\\t\\t\\tcshader: prefixSumSource,\\n\\t\\t\\t\\t\\t\\tcdefines: cdefines,\\n\\t\\t\\t\\t\\t\\tcomputeEntryPoint: entryPoint,\\n\\t\\t\\t\\t\\t\\tcomputeBindGroupFormat: this._bindGroupFormat,\\n\\t\\t\\t\\t\\t\\tcomputeUniformBufferFormats: {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniforms: this._uniformBufferFormat\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tfindOptimalDispatchSize(workgroupCount) {\\n\\t\\t\\t\\tconst maxDimension = this.device.limits.maxComputeWorkgroupsPerDimension || 65535;\\n\\t\\t\\t\\tif (workgroupCount <= maxDimension) {\\n\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\tx: workgroupCount,\\n\\t\\t\\t\\t\\t\\t\\t\\ty: 1\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst x = Math.floor(Math.sqrt(workgroupCount));\\n\\t\\t\\t\\tconst y = Math.ceil(workgroupCount / x);\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tx,\\n\\t\\t\\t\\t\\t\\ty\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tresize(dataBuffer, count) {\\n\\t\\t\\t\\tconst requiredPasses = this._countPassesNeeded(count);\\n\\t\\t\\t\\tconst currentPasses = this.passes.length;\\n\\t\\t\\t\\tif (requiredPasses > currentPasses) {\\n\\t\\t\\t\\t\\t\\tthis._destroyPasses();\\n\\t\\t\\t\\t\\t\\tthis.createPassesRecursive(dataBuffer, count);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet levelCount = count;\\n\\t\\t\\t\\tfor(let i = 0; i < this.passes.length; i++){\\n\\t\\t\\t\\t\\t\\tconst workgroupCount = Math.ceil(levelCount / ITEMS_PER_WORKGROUP);\\n\\t\\t\\t\\t\\t\\tconst { x: dispatchX, y: dispatchY } = this.findOptimalDispatchSize(workgroupCount);\\n\\t\\t\\t\\t\\t\\tthis.passes[i].count = levelCount;\\n\\t\\t\\t\\t\\t\\tthis.passes[i].dispatchX = dispatchX;\\n\\t\\t\\t\\t\\t\\tthis.passes[i].dispatchY = dispatchY;\\n\\t\\t\\t\\t\\t\\tlevelCount = workgroupCount;\\n\\t\\t\\t\\t\\t\\tif (workgroupCount <= 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_destroyPasses() {\\n\\t\\t\\t\\tfor (const pass of this.passes){\\n\\t\\t\\t\\t\\t\\tpass.blockSumBuffer?.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.passes.length = 0;\\n\\t\\t}\\n\\t\\t_countPassesNeeded(count) {\\n\\t\\t\\t\\tlet passes = 0;\\n\\t\\t\\t\\tlet levelCount = count;\\n\\t\\t\\t\\twhile(levelCount > 0){\\n\\t\\t\\t\\t\\t\\tpasses++;\\n\\t\\t\\t\\t\\t\\tconst workgroupCount = Math.ceil(levelCount / ITEMS_PER_WORKGROUP);\\n\\t\\t\\t\\t\\t\\tif (workgroupCount <= 1) break;\\n\\t\\t\\t\\t\\t\\tlevelCount = workgroupCount;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn passes;\\n\\t\\t}\\n\\t\\tdispatch(device) {\\n\\t\\t\\t\\tfor(let i = 0; i < this.passes.length; i++){\\n\\t\\t\\t\\t\\t\\tconst pass = this.passes[i];\\n\\t\\t\\t\\t\\t\\tpass.scanCompute.setParameter('elementCount', pass.count);\\n\\t\\t\\t\\t\\t\\tpass.scanCompute.setupDispatch(pass.dispatchX, pass.dispatchY, 1);\\n\\t\\t\\t\\t\\t\\tdevice.computeDispatch([\\n\\t\\t\\t\\t\\t\\t\\t\\tpass.scanCompute\\n\\t\\t\\t\\t\\t\\t], 'PrefixSumScan');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = this.passes.length - 1; i >= 0; i--){\\n\\t\\t\\t\\t\\t\\tconst pass = this.passes[i];\\n\\t\\t\\t\\t\\t\\tif (pass.addBlockCompute) {\\n\\t\\t\\t\\t\\t\\t\\t\\tpass.addBlockCompute.setParameter('elementCount', pass.count);\\n\\t\\t\\t\\t\\t\\t\\t\\tpass.addBlockCompute.setupDispatch(pass.dispatchX, pass.dispatchY, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tdevice.computeDispatch([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpass.addBlockCompute\\n\\t\\t\\t\\t\\t\\t\\t\\t], 'PrefixSumAddBlock');\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis.passes = [];\\n\\t\\t\\t\\tthis._uniformBufferFormat = null;\\n\\t\\t\\t\\tthis._bindGroupFormat = null;\\n\\t\\t\\t\\tthis._scanShader = null;\\n\\t\\t\\t\\tthis._addBlockShader = null;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis._createFormatsAndShaders();\\n\\t\\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> local_prefix_sums: array<u32>;\\n@group(0) @binding(2) var<storage, read_write> block_sums: array<u32>;\\nstruct RadixSortUniforms {\\n\\tworkgroupCount: u32,\\n\\telementCount: u32\\n};\\n@group(0) @binding(3) var<uniform> uniforms: RadixSortUniforms;\\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;\\nvar<workgroup> histogram: array<atomic<u32>, 16>;\\nvar<workgroup> thread_digits: array<u32, 256>;\\n@compute @workgroup_size(WORKGROUP_SIZE_X, WORKGROUP_SIZE_Y, 1)\\nfn radix_sort(\\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\\tif (TID < 16u) {\\n\\t\\tatomicStore(&histogram[TID], 0u);\\n\\t}\\n\\tworkgroupBarrier();\\n\\tlet is_valid = GID < uniforms.elementCount && WORKGROUP_ID < uniforms.workgroupCount;\\n\\tlet elm = select(0u, input[GID], is_valid);\\n\\tlet digit: u32 = select(16u, (elm >> CURRENT_BIT) & 0xFu, is_valid);\\n\\tthread_digits[TID] = digit;\\n\\tif (is_valid) {\\n\\t\\tatomicAdd(&histogram[digit], 1u);\\n\\t}\\n\\tworkgroupBarrier();\\n\\tvar local_prefix: u32 = 0u;\\n\\tif (is_valid) {\\n\\t\\tlet digit_vec = vec4<u32>(digit, digit, digit, digit);\\n\\t\\tlet ones = vec4<u32>(1u, 1u, 1u, 1u);\\n\\t\\tlet zeros = vec4<u32>(0u, 0u, 0u, 0u);\\n\\t\\t\\n\\t\\tvar i: u32 = 0u;\\n\\t\\tlet limit = TID & ~3u;\\n\\t\\tfor (; i < limit; i += 4u) {\\n\\t\\t\\tlet d = vec4<u32>(\\n\\t\\t\\t\\tthread_digits[i],\\n\\t\\t\\t\\tthread_digits[i + 1u],\\n\\t\\t\\t\\tthread_digits[i + 2u],\\n\\t\\t\\t\\tthread_digits[i + 3u]\\n\\t\\t\\t);\\n\\t\\t\\tlet matches = select(zeros, ones, d == digit_vec);\\n\\t\\t\\tlocal_prefix += matches.x + matches.y + matches.z + matches.w;\\n\\t\\t}\\n\\t\\t\\n\\t\\tfor (; i < TID; i++) {\\n\\t\\t\\tlocal_prefix += select(0u, 1u, thread_digits[i] == digit);\\n\\t\\t}\\n\\t}\\n\\tif (is_valid) {\\n\\t\\tlocal_prefix_sums[GID] = local_prefix;\\n\\t}\\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> local_prefix_sum: array<u32>;\\n@group(0) @binding(3) var<storage, read> prefix_block_sum: array<u32>;\\n@group(0) @binding(4) var<storage, read> inputValues: array<u32>;\\n@group(0) @binding(5) var<storage, read_write> outputValues: array<u32>;\\nstruct RadixSortUniforms {\\n\\tworkgroupCount: u32,\\n\\telementCount: u32\\n};\\n@group(0) @binding(6) var<uniform> uniforms: RadixSortUniforms;\\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;\\n@compute @workgroup_size(WORKGROUP_SIZE_X, WORKGROUP_SIZE_Y, 1)\\nfn radix_sort_reorder(\\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\\tif (GID >= uniforms.elementCount) {\\n\\t\\treturn;\\n\\t}\\n\\tlet k = inputKeys[GID];\\n\\tlet v = select(inputValues[GID], GID, IS_FIRST_PASS == 1u);\\n\\tlet local_prefix = local_prefix_sum[GID];\\n\\tlet extract_bits = (k >> CURRENT_BIT) & 0xFu;\\n\\t\\n\\tlet pid = extract_bits * uniforms.workgroupCount + WORKGROUP_ID;\\n\\tlet sorted_position = prefix_block_sum[pid] + local_prefix;\\n\\toutputKeys[sorted_position] = k;\\n\\toutputValues[sorted_position] = v;\\n}\\n`;\\n\\nconst BITS_PER_PASS = 4;\\nconst BUCKET_COUNT = 16;\\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;\\nclass ComputeRadixSort {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._destroyBuffers();\\n\\t\\t\\t\\tthis._destroyPasses();\\n\\t\\t\\t\\tthis._blockSumBindGroupFormat?.destroy();\\n\\t\\t\\t\\tthis._reorderBindGroupFormat?.destroy();\\n\\t\\t\\t\\tthis._blockSumBindGroupFormat = null;\\n\\t\\t\\t\\tthis._reorderBindGroupFormat = null;\\n\\t\\t\\t\\tthis._uniformBufferFormat = null;\\n\\t\\t}\\n\\t\\t_destroyPasses() {\\n\\t\\t\\t\\tfor (const pass of this._passes){\\n\\t\\t\\t\\t\\t\\tpass.blockSumCompute.shader?.destroy();\\n\\t\\t\\t\\t\\t\\tpass.reorderCompute.shader?.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._passes.length = 0;\\n\\t\\t\\t\\tthis._numBits = 0;\\n\\t\\t}\\n\\t\\t_destroyBuffers() {\\n\\t\\t\\t\\tthis._keys0?.destroy();\\n\\t\\t\\t\\tthis._keys1?.destroy();\\n\\t\\t\\t\\tthis._values0?.destroy();\\n\\t\\t\\t\\tthis._values1?.destroy();\\n\\t\\t\\t\\tthis._localPrefixSums?.destroy();\\n\\t\\t\\t\\tthis._blockSums?.destroy();\\n\\t\\t\\t\\tthis._sortedIndices?.destroy();\\n\\t\\t\\t\\tthis._prefixSumKernel?.destroy();\\n\\t\\t\\t\\tthis._keys0 = null;\\n\\t\\t\\t\\tthis._keys1 = null;\\n\\t\\t\\t\\tthis._values0 = null;\\n\\t\\t\\t\\tthis._values1 = null;\\n\\t\\t\\t\\tthis._localPrefixSums = null;\\n\\t\\t\\t\\tthis._blockSums = null;\\n\\t\\t\\t\\tthis._sortedIndices = null;\\n\\t\\t\\t\\tthis._prefixSumKernel = null;\\n\\t\\t\\t\\tthis._workgroupCount = 0;\\n\\t\\t\\t\\tthis._allocatedWorkgroupCount = 0;\\n\\t\\t}\\n\\t\\tget sortedIndices() {\\n\\t\\t\\t\\treturn this._sortedIndices;\\n\\t\\t}\\n\\t\\t_createBindGroupFormats() {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tthis._uniformBufferFormat = new UniformBufferFormat(device, [\\n\\t\\t\\t\\t\\t\\tnew UniformFormat('workgroupCount', UNIFORMTYPE_UINT),\\n\\t\\t\\t\\t\\t\\tnew UniformFormat('elementCount', UNIFORMTYPE_UINT)\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tthis._blockSumBindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\t\\t\\t\\tnew BindStorageBufferFormat('input', SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\t\\t\\tnew BindStorageBufferFormat('local_prefix_sums', SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\t\\t\\t\\tnew BindStorageBufferFormat('block_sums', SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\t\\t\\t\\tnew BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE)\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tthis._reorderBindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\t\\t\\t\\tnew BindStorageBufferFormat('inputKeys', SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\t\\t\\tnew BindStorageBufferFormat('outputKeys', SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\t\\t\\t\\tnew BindStorageBufferFormat('local_prefix_sum', SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\t\\t\\tnew BindStorageBufferFormat('prefix_block_sum', SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\t\\t\\tnew BindStorageBufferFormat('inputValues', SHADERSTAGE_COMPUTE, true),\\n\\t\\t\\t\\t\\t\\tnew BindStorageBufferFormat('outputValues', SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\t\\t\\t\\tnew BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE)\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\t_createPasses(numBits) {\\n\\t\\t\\t\\tthis._destroyPasses();\\n\\t\\t\\t\\tthis._numBits = numBits;\\n\\t\\t\\t\\tconst numPasses = numBits / BITS_PER_PASS;\\n\\t\\t\\t\\tfor(let pass = 0; pass < numPasses; pass++){\\n\\t\\t\\t\\t\\t\\tconst bitOffset = pass * BITS_PER_PASS;\\n\\t\\t\\t\\t\\t\\tconst isFirstPass = pass === 0;\\n\\t\\t\\t\\t\\t\\tconst blockSumShader = this._createShader(`RadixSort4bit-BlockSum-${bitOffset}`, radixSort4bitSource, 'radix_sort', bitOffset, false, this._blockSumBindGroupFormat);\\n\\t\\t\\t\\t\\t\\tconst reorderShader = this._createShader(`RadixSort4bit-Reorder-${bitOffset}`, radixSortReorderSource, 'radix_sort_reorder', bitOffset, isFirstPass, this._reorderBindGroupFormat);\\n\\t\\t\\t\\t\\t\\tconst blockSumCompute = new Compute(this.device, blockSumShader, `RadixSort4bit-BlockSum-${bitOffset}`);\\n\\t\\t\\t\\t\\t\\tconst reorderCompute = new Compute(this.device, reorderShader, `RadixSort4bit-Reorder-${bitOffset}`);\\n\\t\\t\\t\\t\\t\\tthis._passes.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tblockSumCompute,\\n\\t\\t\\t\\t\\t\\t\\t\\treorderCompute\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_allocateBuffers(elementCount, numBits) {\\n\\t\\t\\t\\tconst workgroupCount = Math.ceil(elementCount / THREADS_PER_WORKGROUP$1);\\n\\t\\t\\t\\tconst buffersNeedRealloc = workgroupCount > this._allocatedWorkgroupCount || !this._keys0;\\n\\t\\t\\t\\tconst passesNeedRecreate = numBits !== this._numBits;\\n\\t\\t\\t\\tthis._workgroupCount = workgroupCount;\\n\\t\\t\\t\\tthis._dispatchSize = this._findOptimalDispatchSize(workgroupCount);\\n\\t\\t\\t\\tif (buffersNeedRealloc) {\\n\\t\\t\\t\\t\\t\\tthis._destroyBuffers();\\n\\t\\t\\t\\t\\t\\tthis._allocatedWorkgroupCount = workgroupCount;\\n\\t\\t\\t\\t\\t\\tthis._workgroupCount = workgroupCount;\\n\\t\\t\\t\\t\\t\\tthis._dispatchSize = this._findOptimalDispatchSize(workgroupCount);\\n\\t\\t\\t\\t\\t\\tconst elementSize = elementCount * 4;\\n\\t\\t\\t\\t\\t\\tconst blockSumSize = BUCKET_COUNT * workgroupCount * 4;\\n\\t\\t\\t\\t\\t\\tthis._keys0 = new StorageBuffer(this.device, elementSize, BUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST);\\n\\t\\t\\t\\t\\t\\tthis._keys1 = new StorageBuffer(this.device, elementSize, BUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST);\\n\\t\\t\\t\\t\\t\\tthis._values0 = new StorageBuffer(this.device, elementSize, BUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST);\\n\\t\\t\\t\\t\\t\\tthis._values1 = new StorageBuffer(this.device, elementSize, BUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST);\\n\\t\\t\\t\\t\\t\\tthis._localPrefixSums = new StorageBuffer(this.device, elementSize, BUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST);\\n\\t\\t\\t\\t\\t\\tthis._blockSums = new StorageBuffer(this.device, blockSumSize, BUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST);\\n\\t\\t\\t\\t\\t\\tthis._sortedIndices = new StorageBuffer(this.device, elementSize, BUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST);\\n\\t\\t\\t\\t\\t\\tthis._prefixSumKernel = new PrefixSumKernel(this.device);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._prefixSumKernel.resize(this._blockSums, BUCKET_COUNT * workgroupCount);\\n\\t\\t\\t\\tif (passesNeedRecreate) {\\n\\t\\t\\t\\t\\t\\tthis._createPasses(numBits);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_findOptimalDispatchSize(workgroupCount) {\\n\\t\\t\\t\\tconst maxDimension = this.device.limits.maxComputeWorkgroupsPerDimension || 65535;\\n\\t\\t\\t\\tif (workgroupCount <= maxDimension) {\\n\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\tx: workgroupCount,\\n\\t\\t\\t\\t\\t\\t\\t\\ty: 1\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst x = Math.floor(Math.sqrt(workgroupCount));\\n\\t\\t\\t\\tconst y = Math.ceil(workgroupCount / x);\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tx,\\n\\t\\t\\t\\t\\t\\ty\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\t_createShader(name, source, entryPoint, currentBit, isFirstPass, bindGroupFormat) {\\n\\t\\t\\t\\tconst cdefines = new Map();\\n\\t\\t\\t\\tcdefines.set('{WORKGROUP_SIZE_X}', WORKGROUP_SIZE_X$1);\\n\\t\\t\\t\\tcdefines.set('{WORKGROUP_SIZE_Y}', WORKGROUP_SIZE_Y$1);\\n\\t\\t\\t\\tcdefines.set('{THREADS_PER_WORKGROUP}', THREADS_PER_WORKGROUP$1);\\n\\t\\t\\t\\tcdefines.set('{CURRENT_BIT}', currentBit);\\n\\t\\t\\t\\tcdefines.set('{IS_FIRST_PASS}', isFirstPass ? 1 : 0);\\n\\t\\t\\t\\treturn new Shader(this.device, {\\n\\t\\t\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\t\\t\\t\\tcshader: source,\\n\\t\\t\\t\\t\\t\\tcdefines: cdefines,\\n\\t\\t\\t\\t\\t\\tcomputeEntryPoint: entryPoint,\\n\\t\\t\\t\\t\\t\\tcomputeBindGroupFormat: bindGroupFormat,\\n\\t\\t\\t\\t\\t\\tcomputeUniformBufferFormats: {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniforms: this._uniformBufferFormat\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tsort(keysBuffer, elementCount, numBits = 16) {\\n\\t\\t\\t\\tthis._elementCount = elementCount;\\n\\t\\t\\t\\tthis._allocateBuffers(elementCount, numBits);\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tconst numPasses = numBits / BITS_PER_PASS;\\n\\t\\t\\t\\tlet currentKeys = keysBuffer;\\n\\t\\t\\t\\tlet currentValues = this._values0;\\n\\t\\t\\t\\tlet nextKeys = this._keys0;\\n\\t\\t\\t\\tlet nextValues = this._values1;\\n\\t\\t\\t\\tfor(let pass = 0; pass < numPasses; pass++){\\n\\t\\t\\t\\t\\t\\tconst { blockSumCompute, reorderCompute } = this._passes[pass];\\n\\t\\t\\t\\t\\t\\tconst isLastPass = pass === numPasses - 1;\\n\\t\\t\\t\\t\\t\\tblockSumCompute.setParameter('input', currentKeys);\\n\\t\\t\\t\\t\\t\\tblockSumCompute.setParameter('local_prefix_sums', this._localPrefixSums);\\n\\t\\t\\t\\t\\t\\tblockSumCompute.setParameter('block_sums', this._blockSums);\\n\\t\\t\\t\\t\\t\\tblockSumCompute.setParameter('workgroupCount', this._workgroupCount);\\n\\t\\t\\t\\t\\t\\tblockSumCompute.setParameter('elementCount', elementCount);\\n\\t\\t\\t\\t\\t\\tblockSumCompute.setupDispatch(this._dispatchSize.x, this._dispatchSize.y, 1);\\n\\t\\t\\t\\t\\t\\tdevice.computeDispatch([\\n\\t\\t\\t\\t\\t\\t\\t\\tblockSumCompute\\n\\t\\t\\t\\t\\t\\t], 'RadixSort-BlockSum');\\n\\t\\t\\t\\t\\t\\tthis._prefixSumKernel.dispatch(device);\\n\\t\\t\\t\\t\\t\\tconst outputValues = isLastPass ? this._sortedIndices : nextValues;\\n\\t\\t\\t\\t\\t\\treorderCompute.setParameter('inputKeys', currentKeys);\\n\\t\\t\\t\\t\\t\\treorderCompute.setParameter('outputKeys', nextKeys);\\n\\t\\t\\t\\t\\t\\treorderCompute.setParameter('local_prefix_sum', this._localPrefixSums);\\n\\t\\t\\t\\t\\t\\treorderCompute.setParameter('prefix_block_sum', this._blockSums);\\n\\t\\t\\t\\t\\t\\treorderCompute.setParameter('inputValues', currentValues);\\n\\t\\t\\t\\t\\t\\treorderCompute.setParameter('outputValues', outputValues);\\n\\t\\t\\t\\t\\t\\treorderCompute.setParameter('workgroupCount', this._workgroupCount);\\n\\t\\t\\t\\t\\t\\treorderCompute.setParameter('elementCount', elementCount);\\n\\t\\t\\t\\t\\t\\treorderCompute.setupDispatch(this._dispatchSize.x, this._dispatchSize.y, 1);\\n\\t\\t\\t\\t\\t\\tdevice.computeDispatch([\\n\\t\\t\\t\\t\\t\\t\\t\\treorderCompute\\n\\t\\t\\t\\t\\t\\t], 'RadixSort-Reorder');\\n\\t\\t\\t\\t\\t\\tif (!isLastPass) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcurrentKeys = nextKeys;\\n\\t\\t\\t\\t\\t\\t\\t\\tnextKeys = currentKeys === this._keys0 ? this._keys1 : this._keys0;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst tempValues = currentValues;\\n\\t\\t\\t\\t\\t\\t\\t\\tcurrentValues = nextValues;\\n\\t\\t\\t\\t\\t\\t\\t\\tnextValues = tempValues;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._sortedIndices;\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis._elementCount = 0;\\n\\t\\t\\t\\tthis._workgroupCount = 0;\\n\\t\\t\\t\\tthis._allocatedWorkgroupCount = 0;\\n\\t\\t\\t\\tthis._numBits = 0;\\n\\t\\t\\t\\tthis._keys0 = null;\\n\\t\\t\\t\\tthis._keys1 = null;\\n\\t\\t\\t\\tthis._values0 = null;\\n\\t\\t\\t\\tthis._values1 = null;\\n\\t\\t\\t\\tthis._localPrefixSums = null;\\n\\t\\t\\t\\tthis._blockSums = null;\\n\\t\\t\\t\\tthis._sortedIndices = null;\\n\\t\\t\\t\\tthis._prefixSumKernel = null;\\n\\t\\t\\t\\tthis._dispatchSize = {\\n\\t\\t\\t\\t\\t\\tx: 1,\\n\\t\\t\\t\\t\\t\\ty: 1\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis._blockSumBindGroupFormat = null;\\n\\t\\t\\t\\tthis._reorderBindGroupFormat = null;\\n\\t\\t\\t\\tthis._uniformBufferFormat = null;\\n\\t\\t\\t\\tthis._passes = [];\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis._createBindGroupFormats();\\n\\t\\t}\\n}\\n\\nclass RenderPassShaderQuad extends RenderPass {\\n\\t\\tset shader(shader) {\\n\\t\\t\\t\\tthis.quadRender?.destroy();\\n\\t\\t\\t\\tthis.quadRender = null;\\n\\t\\t\\t\\tthis._shader = shader;\\n\\t\\t\\t\\tif (shader) {\\n\\t\\t\\t\\t\\t\\tthis.quadRender = new QuadRender(shader);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget shader() {\\n\\t\\t\\t\\treturn this._shader;\\n\\t\\t}\\n\\t\\texecute() {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tdevice.setBlendState(this.blendState);\\n\\t\\t\\t\\tdevice.setCullMode(this.cullMode);\\n\\t\\t\\t\\tdevice.setDepthState(this.depthState);\\n\\t\\t\\t\\tdevice.setStencilState(this.stencilFront, this.stencilBack);\\n\\t\\t\\t\\tthis.quadRender?.render(this.viewport, this.scissor);\\n\\t\\t}\\n\\t\\tconstructor(...args){\\n\\t\\t\\t\\tsuper(...args), this._shader = null, this.quadRender = null, this.cullMode = CULLFACE_NONE, this.blendState = BlendState.NOBLEND, this.depthState = DepthState.NODEPTH, this.stencilFront = null, this.stencilBack = null;\\n\\t\\t}\\n}\\n\\nclass LitShaderOptions {\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.hasTangents = false;\\n\\t\\t\\t\\tthis.shaderChunks = null;\\n\\t\\t\\t\\tthis.pass = 0;\\n\\t\\t\\t\\tthis.alphaTest = false;\\n\\t\\t\\t\\tthis.blendType = BLEND_NONE;\\n\\t\\t\\t\\tthis.separateAmbient = false;\\n\\t\\t\\t\\tthis.screenSpace = false;\\n\\t\\t\\t\\tthis.skin = false;\\n\\t\\t\\t\\tthis.batch = false;\\n\\t\\t\\t\\tthis.useInstancing = false;\\n\\t\\t\\t\\tthis.useMorphPosition = false;\\n\\t\\t\\t\\tthis.useMorphNormal = false;\\n\\t\\t\\t\\tthis.useMorphTextureBasedInt = false;\\n\\t\\t\\t\\tthis.nineSlicedMode = 0;\\n\\t\\t\\t\\tthis.clusteredLightingEnabled = true;\\n\\t\\t\\t\\tthis.clusteredLightingCookiesEnabled = false;\\n\\t\\t\\t\\tthis.clusteredLightingShadowsEnabled = false;\\n\\t\\t\\t\\tthis.clusteredLightingShadowType = 0;\\n\\t\\t\\t\\tthis.clusteredLightingAreaLightsEnabled = false;\\n\\t\\t\\t\\tthis.vertexColors = false;\\n\\t\\t\\t\\tthis.useVertexColorGamma = false;\\n\\t\\t\\t\\tthis.lightMapEnabled = false;\\n\\t\\t\\t\\tthis.dirLightMapEnabled = false;\\n\\t\\t\\t\\tthis.useHeights = false;\\n\\t\\t\\t\\tthis.useNormals = false;\\n\\t\\t\\t\\tthis.useClearCoatNormals = false;\\n\\t\\t\\t\\tthis.useAo = false;\\n\\t\\t\\t\\tthis.diffuseMapEnabled = false;\\n\\t\\t\\t\\tthis.pixelSnap = false;\\n\\t\\t\\t\\tthis.ambientSH = false;\\n\\t\\t\\t\\tthis.ssao = false;\\n\\t\\t\\t\\tthis.twoSidedLighting = false;\\n\\t\\t\\t\\tthis.occludeDirect = false;\\n\\t\\t\\t\\tthis.occludeSpecular = 0;\\n\\t\\t\\t\\tthis.occludeSpecularFloat = false;\\n\\t\\t\\t\\tthis.useMsdf = false;\\n\\t\\t\\t\\tthis.msdfTextAttribute = false;\\n\\t\\t\\t\\tthis.alphaToCoverage = false;\\n\\t\\t\\t\\tthis.opacityFadesSpecular = false;\\n\\t\\t\\t\\tthis.opacityDither = DITHER_NONE;\\n\\t\\t\\t\\tthis.opacityShadowDither = DITHER_NONE;\\n\\t\\t\\t\\tthis.cubeMapProjection = 0;\\n\\t\\t\\t\\tthis.useSpecular = false;\\n\\t\\t\\t\\tthis.useSpecularityFactor = false;\\n\\t\\t\\t\\tthis.enableGGXSpecular = false;\\n\\t\\t\\t\\tthis.fresnelModel = 0;\\n\\t\\t\\t\\tthis.useRefraction = false;\\n\\t\\t\\t\\tthis.useClearCoat = false;\\n\\t\\t\\t\\tthis.useSheen = false;\\n\\t\\t\\t\\tthis.useIridescence = false;\\n\\t\\t\\t\\tthis.useMetalness = false;\\n\\t\\t\\t\\tthis.useDynamicRefraction = false;\\n\\t\\t\\t\\tthis.dispersion = false;\\n\\t\\t\\t\\tthis.fog = FOG_NONE;\\n\\t\\t\\t\\tthis.gamma = GAMMA_NONE;\\n\\t\\t\\t\\tthis.toneMap = -1;\\n\\t\\t\\t\\tthis.reflectionSource = REFLECTIONSRC_NONE;\\n\\t\\t\\t\\tthis.reflectionEncoding = null;\\n\\t\\t\\t\\tthis.reflectionCubemapEncoding = null;\\n\\t\\t\\t\\tthis.ambientSource = 'constant';\\n\\t\\t\\t\\tthis.ambientEncoding = null;\\n\\t\\t\\t\\tthis.skyboxIntensity = 1.0;\\n\\t\\t\\t\\tthis.useCubeMapRotation = false;\\n\\t\\t\\t\\tthis.lightMapWithoutAmbient = false;\\n\\t\\t\\t\\tthis.lights = [];\\n\\t\\t\\t\\tthis.noShadow = false;\\n\\t\\t\\t\\tthis.lightMaskDynamic = 0x0;\\n\\t\\t\\t\\tthis.userAttributes = {};\\n\\t\\t\\t\\tthis.linearDepth = false;\\n\\t\\t\\t\\tthis.shadowCatcher = false;\\n\\t\\t}\\n}\\n\\nclass LitMaterialOptionsBuilder {\\n\\t\\tstatic update(litOptions, material, scene, renderParams, objDefs, pass, sortedLights) {\\n\\t\\t\\t\\tLitMaterialOptionsBuilder.updateSharedOptions(litOptions, material, scene, objDefs, pass);\\n\\t\\t\\t\\tLitMaterialOptionsBuilder.updateMaterialOptions(litOptions, material);\\n\\t\\t\\t\\tLitMaterialOptionsBuilder.updateEnvOptions(litOptions, material, scene, renderParams);\\n\\t\\t\\t\\tLitMaterialOptionsBuilder.updateLightingOptions(litOptions, material, scene, objDefs, sortedLights);\\n\\t\\t}\\n\\t\\tstatic updateSharedOptions(litOptions, material, scene, objDefs, pass) {\\n\\t\\t\\t\\tlitOptions.shaderChunks = material.shaderChunks;\\n\\t\\t\\t\\tlitOptions.pass = pass;\\n\\t\\t\\t\\tlitOptions.alphaTest = material.alphaTest > 0;\\n\\t\\t\\t\\tlitOptions.blendType = material.blendType;\\n\\t\\t\\t\\tlitOptions.screenSpace = objDefs && (objDefs & SHADERDEF_SCREENSPACE) !== 0;\\n\\t\\t\\t\\tlitOptions.skin = objDefs && (objDefs & SHADERDEF_SKIN) !== 0;\\n\\t\\t\\t\\tlitOptions.useInstancing = objDefs && (objDefs & SHADERDEF_INSTANCING) !== 0;\\n\\t\\t\\t\\tlitOptions.useMorphPosition = objDefs && (objDefs & SHADERDEF_MORPH_POSITION) !== 0;\\n\\t\\t\\t\\tlitOptions.useMorphNormal = objDefs && (objDefs & SHADERDEF_MORPH_NORMAL) !== 0;\\n\\t\\t\\t\\tlitOptions.useMorphTextureBasedInt = objDefs && (objDefs & SHADERDEF_MORPH_TEXTURE_BASED_INT) !== 0;\\n\\t\\t\\t\\tlitOptions.hasTangents = objDefs && (objDefs & SHADERDEF_TANGENTS) !== 0;\\n\\t\\t\\t\\tlitOptions.nineSlicedMode = material.nineSlicedMode || SPRITE_RENDERMODE_SIMPLE;\\n\\t\\t\\t\\tif (material.useLighting && scene.clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\t\\tlitOptions.clusteredLightingEnabled = true;\\n\\t\\t\\t\\t\\t\\tlitOptions.clusteredLightingCookiesEnabled = scene.lighting.cookiesEnabled;\\n\\t\\t\\t\\t\\t\\tlitOptions.clusteredLightingShadowsEnabled = scene.lighting.shadowsEnabled;\\n\\t\\t\\t\\t\\t\\tlitOptions.clusteredLightingShadowType = scene.lighting.shadowType;\\n\\t\\t\\t\\t\\t\\tlitOptions.clusteredLightingAreaLightsEnabled = scene.lighting.areaLightsEnabled;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tlitOptions.clusteredLightingEnabled = false;\\n\\t\\t\\t\\t\\t\\tlitOptions.clusteredLightingCookiesEnabled = false;\\n\\t\\t\\t\\t\\t\\tlitOptions.clusteredLightingShadowsEnabled = false;\\n\\t\\t\\t\\t\\t\\tlitOptions.clusteredLightingAreaLightsEnabled = false;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tstatic updateMaterialOptions(litOptions, material) {\\n\\t\\t\\t\\tlitOptions.separateAmbient = false;\\n\\t\\t\\t\\tlitOptions.pixelSnap = material.pixelSnap;\\n\\t\\t\\t\\tlitOptions.ambientSH = material.ambientSH;\\n\\t\\t\\t\\tlitOptions.twoSidedLighting = material.twoSidedLighting;\\n\\t\\t\\t\\tlitOptions.occludeDirect = material.occludeDirect;\\n\\t\\t\\t\\tlitOptions.occludeSpecular = material.occludeSpecular;\\n\\t\\t\\t\\tlitOptions.occludeSpecularFloat = material.occludeSpecularIntensity !== 1.0;\\n\\t\\t\\t\\tlitOptions.useMsdf = false;\\n\\t\\t\\t\\tlitOptions.msdfTextAttribute = false;\\n\\t\\t\\t\\tlitOptions.alphaToCoverage = material.alphaToCoverage;\\n\\t\\t\\t\\tlitOptions.opacityFadesSpecular = material.opacityFadesSpecular;\\n\\t\\t\\t\\tlitOptions.opacityDither = material.opacityDither;\\n\\t\\t\\t\\tlitOptions.cubeMapProjection = CUBEPROJ_NONE;\\n\\t\\t\\t\\tlitOptions.useSpecular = material.hasSpecular;\\n\\t\\t\\t\\tlitOptions.useSpecularityFactor = material.hasSpecularityFactor;\\n\\t\\t\\t\\tlitOptions.enableGGXSpecular = material.ggxSpecular;\\n\\t\\t\\t\\tlitOptions.useAnisotropy = false;\\n\\t\\t\\t\\tlitOptions.fresnelModel = material.fresnelModel;\\n\\t\\t\\t\\tlitOptions.useRefraction = material.hasRefraction;\\n\\t\\t\\t\\tlitOptions.useClearCoat = material.hasClearCoat;\\n\\t\\t\\t\\tlitOptions.useSheen = material.hasSheen;\\n\\t\\t\\t\\tlitOptions.useIridescence = material.hasIrridescence;\\n\\t\\t\\t\\tlitOptions.useMetalness = material.hasMetalness;\\n\\t\\t\\t\\tlitOptions.useDynamicRefraction = material.dynamicRefraction;\\n\\t\\t\\t\\tlitOptions.dispersion = material.dispersion > 0;\\n\\t\\t\\t\\tlitOptions.vertexColors = false;\\n\\t\\t\\t\\tlitOptions.lightMapEnabled = material.hasLighting;\\n\\t\\t\\t\\tlitOptions.dirLightMapEnabled = material.dirLightMap;\\n\\t\\t\\t\\tlitOptions.useHeights = material.hasHeights;\\n\\t\\t\\t\\tlitOptions.useNormals = material.hasNormals;\\n\\t\\t\\t\\tlitOptions.useClearCoatNormals = material.hasClearCoatNormals;\\n\\t\\t\\t\\tlitOptions.useAo = material.hasAo;\\n\\t\\t\\t\\tlitOptions.diffuseMapEnabled = material.hasDiffuseMap;\\n\\t\\t}\\n\\t\\tstatic updateEnvOptions(litOptions, material, scene, renderParams) {\\n\\t\\t\\t\\tlitOptions.fog = material.useFog ? renderParams.fog : FOG_NONE;\\n\\t\\t\\t\\tlitOptions.gamma = renderParams.shaderOutputGamma;\\n\\t\\t\\t\\tlitOptions.toneMap = material.useTonemap ? renderParams.toneMapping : TONEMAP_NONE;\\n\\t\\t\\t\\tif (material.useSkybox && scene.envAtlas && scene.skybox) {\\n\\t\\t\\t\\t\\t\\tlitOptions.reflectionSource = REFLECTIONSRC_ENVATLASHQ;\\n\\t\\t\\t\\t\\t\\tlitOptions.reflectionEncoding = scene.envAtlas.encoding;\\n\\t\\t\\t\\t\\t\\tlitOptions.reflectionCubemapEncoding = scene.skybox.encoding;\\n\\t\\t\\t\\t} else if (material.useSkybox && scene.envAtlas) {\\n\\t\\t\\t\\t\\t\\tlitOptions.reflectionSource = REFLECTIONSRC_ENVATLAS;\\n\\t\\t\\t\\t\\t\\tlitOptions.reflectionEncoding = scene.envAtlas.encoding;\\n\\t\\t\\t\\t} else if (material.useSkybox && scene.skybox) {\\n\\t\\t\\t\\t\\t\\tlitOptions.reflectionSource = REFLECTIONSRC_CUBEMAP;\\n\\t\\t\\t\\t\\t\\tlitOptions.reflectionEncoding = scene.skybox.encoding;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tlitOptions.reflectionSource = REFLECTIONSRC_NONE;\\n\\t\\t\\t\\t\\t\\tlitOptions.reflectionEncoding = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (material.ambientSH) {\\n\\t\\t\\t\\t\\t\\tlitOptions.ambientSource = AMBIENTSRC_AMBIENTSH;\\n\\t\\t\\t\\t\\t\\tlitOptions.ambientEncoding = null;\\n\\t\\t\\t\\t} else if (litOptions.reflectionSource !== REFLECTIONSRC_NONE && scene.envAtlas) {\\n\\t\\t\\t\\t\\t\\tlitOptions.ambientSource = AMBIENTSRC_ENVALATLAS;\\n\\t\\t\\t\\t\\t\\tlitOptions.ambientEncoding = scene.envAtlas.encoding;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tlitOptions.ambientSource = AMBIENTSRC_CONSTANT;\\n\\t\\t\\t\\t\\t\\tlitOptions.ambientEncoding = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst hasSkybox = litOptions.reflectionSource !== REFLECTIONSRC_NONE;\\n\\t\\t\\t\\tlitOptions.skyboxIntensity = hasSkybox;\\n\\t\\t\\t\\tlitOptions.useCubeMapRotation = hasSkybox && scene._skyboxRotationShaderInclude;\\n\\t\\t}\\n\\t\\tstatic updateLightingOptions(litOptions, material, scene, objDefs, sortedLights) {\\n\\t\\t\\t\\tlitOptions.lightMapWithoutAmbient = false;\\n\\t\\t\\t\\tif (material.useLighting) {\\n\\t\\t\\t\\t\\t\\tconst lightsFiltered = [];\\n\\t\\t\\t\\t\\t\\tconst mask = objDefs ? objDefs >> 16 : MASK_AFFECT_DYNAMIC;\\n\\t\\t\\t\\t\\t\\tlitOptions.lightMaskDynamic = !!(mask & MASK_AFFECT_DYNAMIC);\\n\\t\\t\\t\\t\\t\\tlitOptions.lightMapWithoutAmbient = false;\\n\\t\\t\\t\\t\\t\\tif (sortedLights) {\\n\\t\\t\\t\\t\\t\\t\\t\\tLitMaterialOptionsBuilder.collectLights(LIGHTTYPE_DIRECTIONAL, sortedLights[LIGHTTYPE_DIRECTIONAL], lightsFiltered, mask);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!scene.clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tLitMaterialOptionsBuilder.collectLights(LIGHTTYPE_OMNI, sortedLights[LIGHTTYPE_OMNI], lightsFiltered, mask);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tLitMaterialOptionsBuilder.collectLights(LIGHTTYPE_SPOT, sortedLights[LIGHTTYPE_SPOT], lightsFiltered, mask);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlitOptions.lights = lightsFiltered;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tlitOptions.lights = [];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (litOptions.lights.length === 0 && !scene.clusteredLightingEnabled || (objDefs & SHADERDEF_NOSHADOW) !== 0) {\\n\\t\\t\\t\\t\\t\\tlitOptions.noShadow = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tstatic collectLights(lType, lights, lightsFiltered, mask) {\\n\\t\\t\\t\\tfor(let i = 0; i < lights.length; i++){\\n\\t\\t\\t\\t\\t\\tconst light = lights[i];\\n\\t\\t\\t\\t\\t\\tif (light.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (light.mask & mask) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlightsFiltered.push(light);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nconst builtinAttributes = {\\n\\t\\tvertex_normal: SEMANTIC_NORMAL,\\n\\t\\tvertex_tangent: SEMANTIC_TANGENT,\\n\\t\\tvertex_texCoord0: SEMANTIC_TEXCOORD0,\\n\\t\\tvertex_texCoord1: SEMANTIC_TEXCOORD1,\\n\\t\\tvertex_color: SEMANTIC_COLOR,\\n\\t\\tvertex_boneWeights: SEMANTIC_BLENDWEIGHT,\\n\\t\\tvertex_boneIndices: SEMANTIC_BLENDINDICES\\n};\\nclass LitShader {\\n\\t\\tfDefineSet(condition, name, value = '') {\\n\\t\\t\\t\\tif (condition) {\\n\\t\\t\\t\\t\\t\\tthis.fDefines.set(name, value);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgenerateVertexShader(useUv, useUnmodifiedUv, mapTransforms) {\\n\\t\\t\\t\\tconst { options, vDefines, attributes } = this;\\n\\t\\t\\t\\tconst varyings = new Map();\\n\\t\\t\\t\\tvaryings.set('vPositionW', 'vec3');\\n\\t\\t\\t\\tif (options.nineSlicedMode === SPRITE_RENDERMODE_SLICED || options.nineSlicedMode === SPRITE_RENDERMODE_TILED) {\\n\\t\\t\\t\\t\\t\\tvDefines.set('NINESLICED', true);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.options.linearDepth) {\\n\\t\\t\\t\\t\\t\\tvDefines.set('LINEAR_DEPTH', true);\\n\\t\\t\\t\\t\\t\\tvaryings.set('vLinearDepth', 'float');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.needsNormal) vDefines.set('NORMALS', true);\\n\\t\\t\\t\\tif (this.options.useInstancing) {\\n\\t\\t\\t\\t\\t\\tconst languageChunks = ShaderChunks.get(this.device, this.shaderLanguage);\\n\\t\\t\\t\\t\\t\\tif (this.chunks.get('transformInstancingVS') === languageChunks.get('transformInstancingVS')) {\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes.instance_line1 = SEMANTIC_ATTR11;\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes.instance_line2 = SEMANTIC_ATTR12;\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes.instance_line3 = SEMANTIC_ATTR14;\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes.instance_line4 = SEMANTIC_ATTR15;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.needsNormal) {\\n\\t\\t\\t\\t\\t\\tattributes.vertex_normal = SEMANTIC_NORMAL;\\n\\t\\t\\t\\t\\t\\tvaryings.set('vNormalW', 'vec3');\\n\\t\\t\\t\\t\\t\\tif (options.hasTangents && (options.useHeights || options.useNormals || options.useClearCoatNormals || options.enableGGXSpecular)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tvDefines.set('TANGENTS', true);\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes.vertex_tangent = SEMANTIC_TANGENT;\\n\\t\\t\\t\\t\\t\\t\\t\\tvaryings.set('vTangentW', 'vec3');\\n\\t\\t\\t\\t\\t\\t\\t\\tvaryings.set('vBinormalW', 'vec3');\\n\\t\\t\\t\\t\\t\\t} else if (options.enableGGXSpecular) {\\n\\t\\t\\t\\t\\t\\t\\t\\tvDefines.set('GGX_SPECULAR', true);\\n\\t\\t\\t\\t\\t\\t\\t\\tvaryings.set('vObjectSpaceUpW', 'vec3');\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst maxUvSets = 2;\\n\\t\\t\\t\\tfor(let i = 0; i < maxUvSets; i++){\\n\\t\\t\\t\\t\\t\\tif (useUv[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tvDefines.set(`UV${i}`, true);\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes[`vertex_texCoord${i}`] = `TEXCOORD${i}`;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (useUnmodifiedUv[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tvDefines.set(`UV${i}_UNMODIFIED`, true);\\n\\t\\t\\t\\t\\t\\t\\t\\tvaryings.set(`vUv${i}`, 'vec2');\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet numTransforms = 0;\\n\\t\\t\\t\\tconst transformDone = new Set();\\n\\t\\t\\t\\tmapTransforms.forEach((mapTransform)=>{\\n\\t\\t\\t\\t\\t\\tconst { id, uv, name } = mapTransform;\\n\\t\\t\\t\\t\\t\\tconst checkId = id + uv * 100;\\n\\t\\t\\t\\t\\t\\tif (!transformDone.has(checkId)) {\\n\\t\\t\\t\\t\\t\\t\\t\\ttransformDone.add(checkId);\\n\\t\\t\\t\\t\\t\\t\\t\\tvaryings.set(`vUV${uv}_${id}`, 'vec2');\\n\\t\\t\\t\\t\\t\\t\\t\\tconst varName = `texture_${name}MapTransform`;\\n\\t\\t\\t\\t\\t\\t\\t\\tvDefines.set(`{TRANSFORM_NAME_${numTransforms}}`, varName);\\n\\t\\t\\t\\t\\t\\t\\t\\tvDefines.set(`{TRANSFORM_UV_${numTransforms}}`, uv);\\n\\t\\t\\t\\t\\t\\t\\t\\tvDefines.set(`{TRANSFORM_ID_${numTransforms}}`, id);\\n\\t\\t\\t\\t\\t\\t\\t\\tnumTransforms++;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tvDefines.set('UV_TRANSFORMS_COUNT', numTransforms);\\n\\t\\t\\t\\tif (options.vertexColors) {\\n\\t\\t\\t\\t\\t\\tattributes.vertex_color = SEMANTIC_COLOR;\\n\\t\\t\\t\\t\\t\\tvDefines.set('VERTEX_COLOR', true);\\n\\t\\t\\t\\t\\t\\tvaryings.set('vVertexColor', 'vec4');\\n\\t\\t\\t\\t\\t\\tif (options.useVertexColorGamma) {\\n\\t\\t\\t\\t\\t\\t\\t\\tvDefines.set('STD_VERTEX_COLOR_GAMMA', '');\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.useMsdf && options.msdfTextAttribute) {\\n\\t\\t\\t\\t\\t\\tattributes.vertex_outlineParameters = SEMANTIC_ATTR8;\\n\\t\\t\\t\\t\\t\\tattributes.vertex_shadowParameters = SEMANTIC_ATTR9;\\n\\t\\t\\t\\t\\t\\tvDefines.set('MSDF', true);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.useMorphPosition || options.useMorphNormal) {\\n\\t\\t\\t\\t\\t\\tvDefines.set('MORPHING', true);\\n\\t\\t\\t\\t\\t\\tif (options.useMorphTextureBasedInt) vDefines.set('MORPHING_INT', true);\\n\\t\\t\\t\\t\\t\\tif (options.useMorphPosition) vDefines.set('MORPHING_POSITION', true);\\n\\t\\t\\t\\t\\t\\tif (options.useMorphNormal) vDefines.set('MORPHING_NORMAL', true);\\n\\t\\t\\t\\t\\t\\tattributes.morph_vertex_id = SEMANTIC_ATTR15;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.skin) {\\n\\t\\t\\t\\t\\t\\tattributes.vertex_boneIndices = SEMANTIC_BLENDINDICES;\\n\\t\\t\\t\\t\\t\\tif (options.batch) {\\n\\t\\t\\t\\t\\t\\t\\t\\tvDefines.set('BATCH', true);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes.vertex_boneWeights = SEMANTIC_BLENDWEIGHT;\\n\\t\\t\\t\\t\\t\\t\\t\\tvDefines.set('SKIN', true);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.useInstancing) vDefines.set('INSTANCING', true);\\n\\t\\t\\t\\tif (options.screenSpace) vDefines.set('SCREENSPACE', true);\\n\\t\\t\\t\\tif (options.pixelSnap) vDefines.set('PIXELSNAP', true);\\n\\t\\t\\t\\tvaryings.forEach((type, name)=>{\\n\\t\\t\\t\\t\\t\\tthis.varyingsCode += `#define VARYING_${name.toUpperCase()}\\\\n`;\\n\\t\\t\\t\\t\\t\\tthis.varyingsCode += this.shaderLanguage === SHADERLANGUAGE_WGSL ? `varying ${name}: ${primitiveGlslToWgslTypeMap.get(type)};\\\\n` : `varying ${type} ${name};\\\\n`;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.includes.set('varyingsVS', this.varyingsCode);\\n\\t\\t\\t\\tthis.includes.set('varyingsPS', this.varyingsCode);\\n\\t\\t\\t\\tthis.vshader = `\\n\\t\\t\\t\\t\\t\\t#include \\\"litMainVS\\\"\\n\\t\\t\\t\\t`;\\n\\t\\t}\\n\\t\\t_setupLightingDefines(hasAreaLights, clusteredLightingEnabled) {\\n\\t\\t\\t\\tconst fDefines = this.fDefines;\\n\\t\\t\\t\\tconst options = this.options;\\n\\t\\t\\t\\tthis.fDefines.set('LIGHT_COUNT', options.lights.length);\\n\\t\\t\\t\\tif (hasAreaLights) fDefines.set('AREA_LIGHTS', true);\\n\\t\\t\\t\\tif (clusteredLightingEnabled && this.lighting) {\\n\\t\\t\\t\\t\\t\\tfDefines.set('LIT_CLUSTERED_LIGHTS', true);\\n\\t\\t\\t\\t\\t\\tif (options.clusteredLightingCookiesEnabled) fDefines.set('CLUSTER_COOKIES', true);\\n\\t\\t\\t\\t\\t\\tif (options.clusteredLightingAreaLightsEnabled) fDefines.set('CLUSTER_AREALIGHTS', true);\\n\\t\\t\\t\\t\\t\\tif (options.lightMaskDynamic) fDefines.set('CLUSTER_MESH_DYNAMIC_LIGHTS', true);\\n\\t\\t\\t\\t\\t\\tif (options.clusteredLightingShadowsEnabled && !options.noShadow) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst clusteredShadowInfo = shadowTypeInfo.get(options.clusteredLightingShadowType);\\n\\t\\t\\t\\t\\t\\t\\t\\tfDefines.set('CLUSTER_SHADOWS', true);\\n\\t\\t\\t\\t\\t\\t\\t\\tfDefines.set(`SHADOW_KIND_${clusteredShadowInfo.kind}`, true);\\n\\t\\t\\t\\t\\t\\t\\t\\tfDefines.set(`CLUSTER_SHADOW_TYPE_${clusteredShadowInfo.kind}`, true);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < options.lights.length; i++){\\n\\t\\t\\t\\t\\t\\tconst light = options.lights[i];\\n\\t\\t\\t\\t\\t\\tconst lightType = light._type;\\n\\t\\t\\t\\t\\t\\tif (clusteredLightingEnabled && lightType !== LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst lightShape = hasAreaLights && light._shape ? light._shape : LIGHTSHAPE_PUNCTUAL;\\n\\t\\t\\t\\t\\t\\tconst shadowType = light._shadowType;\\n\\t\\t\\t\\t\\t\\tconst castShadow = light.castShadows && !options.noShadow;\\n\\t\\t\\t\\t\\t\\tconst shadowInfo = shadowTypeInfo.get(shadowType);\\n\\t\\t\\t\\t\\t\\tfDefines.set(`LIGHT${i}`, true);\\n\\t\\t\\t\\t\\t\\tfDefines.set(`LIGHT${i}TYPE`, `${lightTypeNames[lightType]}`);\\n\\t\\t\\t\\t\\t\\tfDefines.set(`LIGHT${i}SHADOWTYPE`, `${shadowInfo.name}`);\\n\\t\\t\\t\\t\\t\\tfDefines.set(`LIGHT${i}SHAPE`, `${lightShapeNames[lightShape]}`);\\n\\t\\t\\t\\t\\t\\tfDefines.set(`LIGHT${i}FALLOFF`, `${lightFalloffNames[light._falloffMode]}`);\\n\\t\\t\\t\\t\\t\\tif (light.affectSpecularity) fDefines.set(`LIGHT${i}AFFECT_SPECULARITY`, true);\\n\\t\\t\\t\\t\\t\\tif (light._cookie) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (lightType === LIGHTTYPE_SPOT && !light._cookie._cubemap || lightType === LIGHTTYPE_OMNI && light._cookie._cubemap) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfDefines.set(`LIGHT${i}COOKIE`, true);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfDefines.set(`{LIGHT${i}COOKIE_CHANNEL}`, light._cookieChannel);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (lightType === LIGHTTYPE_SPOT) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (light._cookieTransform) fDefines.set(`LIGHT${i}COOKIE_TRANSFORM`, true);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (light._cookieFalloff) fDefines.set(`LIGHT${i}COOKIE_FALLOFF`, true);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tif (castShadow) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfDefines.set(`LIGHT${i}CASTSHADOW`, true);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (shadowInfo.pcf) fDefines.set(`LIGHT${i}SHADOW_PCF`, true);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (light._normalOffsetBias && !light._isVsm) fDefines.set(`LIGHT${i}_SHADOW_SAMPLE_NORMAL_OFFSET`, true);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (lightType === LIGHTTYPE_DIRECTIONAL) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfDefines.set(`LIGHT${i}_SHADOW_SAMPLE_ORTHO`, true);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (light.cascadeBlend > 0) fDefines.set(`LIGHT${i}_SHADOW_CASCADE_BLEND`, true);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (light.numCascades > 1) fDefines.set(`LIGHT${i}_SHADOW_CASCADES`, true);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (shadowInfo.pcf || shadowInfo.pcss || this.device.isWebGPU) fDefines.set(`LIGHT${i}_SHADOW_SAMPLE_SOURCE_ZBUFFER`, true);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (lightType === LIGHTTYPE_OMNI) fDefines.set(`LIGHT${i}_SHADOW_SAMPLE_POINT`, true);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (castShadow) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfDefines.set(`SHADOW_KIND_${shadowInfo.kind}`, true);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (lightType === LIGHTTYPE_DIRECTIONAL) fDefines.set('SHADOW_DIRECTIONAL', true);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tprepareForwardPass(lightingUv) {\\n\\t\\t\\t\\tconst { options } = this;\\n\\t\\t\\t\\tconst clusteredAreaLights = options.clusteredLightingEnabled && options.clusteredLightingAreaLightsEnabled;\\n\\t\\t\\t\\tconst hasAreaLights = clusteredAreaLights || options.lights.some((light)=>{\\n\\t\\t\\t\\t\\t\\treturn light._shape && light._shape !== LIGHTSHAPE_PUNCTUAL;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst addAmbient = !options.lightMapEnabled || options.lightMapWithoutAmbient;\\n\\t\\t\\t\\tconst hasTBN = this.needsNormal && (options.useNormals || options.useClearCoatNormals || options.enableGGXSpecular && !options.useHeights);\\n\\t\\t\\t\\tif (options.useSpecular) {\\n\\t\\t\\t\\t\\t\\tthis.fDefineSet(true, 'LIT_SPECULAR');\\n\\t\\t\\t\\t\\t\\tthis.fDefineSet(this.reflections, 'LIT_REFLECTIONS');\\n\\t\\t\\t\\t\\t\\tthis.fDefineSet(options.useClearCoat, 'LIT_CLEARCOAT');\\n\\t\\t\\t\\t\\t\\tthis.fDefineSet(options.fresnelModel > 0, 'LIT_SPECULAR_FRESNEL');\\n\\t\\t\\t\\t\\t\\tthis.fDefineSet(options.useSheen, 'LIT_SHEEN');\\n\\t\\t\\t\\t\\t\\tthis.fDefineSet(options.useIridescence, 'LIT_IRIDESCENCE');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.fDefineSet(this.lighting && options.useSpecular || this.reflections, 'LIT_SPECULAR_OR_REFLECTION');\\n\\t\\t\\t\\tthis.fDefineSet(this.needsSceneColor, 'LIT_SCENE_COLOR');\\n\\t\\t\\t\\tthis.fDefineSet(this.needsScreenSize, 'LIT_SCREEN_SIZE');\\n\\t\\t\\t\\tthis.fDefineSet(this.needsTransforms, 'LIT_TRANSFORMS');\\n\\t\\t\\t\\tthis.fDefineSet(this.needsNormal, 'LIT_NEEDS_NORMAL');\\n\\t\\t\\t\\tthis.fDefineSet(this.lighting, 'LIT_LIGHTING');\\n\\t\\t\\t\\tthis.fDefineSet(options.useMetalness, 'LIT_METALNESS');\\n\\t\\t\\t\\tthis.fDefineSet(options.enableGGXSpecular, 'LIT_GGX_SPECULAR');\\n\\t\\t\\t\\tthis.fDefineSet(options.useAnisotropy, 'LIT_ANISOTROPY');\\n\\t\\t\\t\\tthis.fDefineSet(options.useSpecularityFactor, 'LIT_SPECULARITY_FACTOR');\\n\\t\\t\\t\\tthis.fDefineSet(options.useCubeMapRotation, 'CUBEMAP_ROTATION');\\n\\t\\t\\t\\tthis.fDefineSet(options.occludeSpecularFloat, 'LIT_OCCLUDE_SPECULAR_FLOAT');\\n\\t\\t\\t\\tthis.fDefineSet(options.separateAmbient, 'LIT_SEPARATE_AMBIENT');\\n\\t\\t\\t\\tthis.fDefineSet(options.twoSidedLighting, 'LIT_TWO_SIDED_LIGHTING');\\n\\t\\t\\t\\tthis.fDefineSet(options.lightMapEnabled, 'LIT_LIGHTMAP');\\n\\t\\t\\t\\tthis.fDefineSet(options.dirLightMapEnabled, 'LIT_DIR_LIGHTMAP');\\n\\t\\t\\t\\tthis.fDefineSet(options.skyboxIntensity > 0, 'LIT_SKYBOX_INTENSITY');\\n\\t\\t\\t\\tthis.fDefineSet(options.clusteredLightingShadowsEnabled, 'LIT_CLUSTERED_SHADOWS');\\n\\t\\t\\t\\tthis.fDefineSet(options.clusteredLightingAreaLightsEnabled, 'LIT_CLUSTERED_AREA_LIGHTS');\\n\\t\\t\\t\\tthis.fDefineSet(hasTBN, 'LIT_TBN');\\n\\t\\t\\t\\tthis.fDefineSet(addAmbient, 'LIT_ADD_AMBIENT');\\n\\t\\t\\t\\tthis.fDefineSet(options.hasTangents, 'LIT_TANGENTS');\\n\\t\\t\\t\\tthis.fDefineSet(options.useNormals, 'LIT_USE_NORMALS');\\n\\t\\t\\t\\tthis.fDefineSet(options.useClearCoatNormals, 'LIT_USE_CLEARCOAT_NORMALS');\\n\\t\\t\\t\\tthis.fDefineSet(options.useRefraction, 'LIT_REFRACTION');\\n\\t\\t\\t\\tthis.fDefineSet(options.useDynamicRefraction, 'LIT_DYNAMIC_REFRACTION');\\n\\t\\t\\t\\tthis.fDefineSet(options.dispersion, 'LIT_DISPERSION');\\n\\t\\t\\t\\tthis.fDefineSet(options.useHeights, 'LIT_HEIGHTS');\\n\\t\\t\\t\\tthis.fDefineSet(options.opacityFadesSpecular, 'LIT_OPACITY_FADES_SPECULAR');\\n\\t\\t\\t\\tthis.fDefineSet(options.alphaToCoverage, 'LIT_ALPHA_TO_COVERAGE');\\n\\t\\t\\t\\tthis.fDefineSet(options.alphaTest, 'LIT_ALPHA_TEST');\\n\\t\\t\\t\\tthis.fDefineSet(options.useMsdf, 'LIT_MSDF');\\n\\t\\t\\t\\tthis.fDefineSet(options.ssao, 'LIT_SSAO');\\n\\t\\t\\t\\tthis.fDefineSet(options.useAo, 'LIT_AO');\\n\\t\\t\\t\\tthis.fDefineSet(options.occludeDirect, 'LIT_OCCLUDE_DIRECT');\\n\\t\\t\\t\\tthis.fDefineSet(options.msdfTextAttribute, 'LIT_MSDF_TEXT_ATTRIBUTE');\\n\\t\\t\\t\\tthis.fDefineSet(options.diffuseMapEnabled, 'LIT_DIFFUSE_MAP');\\n\\t\\t\\t\\tthis.fDefineSet(options.shadowCatcher, 'LIT_SHADOW_CATCHER');\\n\\t\\t\\t\\tthis.fDefineSet(true, 'LIT_FRESNEL_MODEL', fresnelNames[options.fresnelModel]);\\n\\t\\t\\t\\tthis.fDefineSet(true, 'LIT_NONE_SLICE_MODE', spriteRenderModeNames[options.nineSlicedMode]);\\n\\t\\t\\t\\tthis.fDefineSet(true, 'LIT_BLEND_TYPE', blendNames[options.blendType]);\\n\\t\\t\\t\\tthis.fDefineSet(true, 'LIT_CUBEMAP_PROJECTION', cubemaProjectionNames[options.cubeMapProjection]);\\n\\t\\t\\t\\tthis.fDefineSet(true, 'LIT_OCCLUDE_SPECULAR', specularOcclusionNames[options.occludeSpecular]);\\n\\t\\t\\t\\tthis.fDefineSet(true, 'LIT_REFLECTION_SOURCE', reflectionSrcNames[options.reflectionSource]);\\n\\t\\t\\t\\tthis.fDefineSet(true, 'LIT_AMBIENT_SOURCE', ambientSrcNames[options.ambientSource]);\\n\\t\\t\\t\\tthis.fDefineSet(true, '{lightingUv}', lightingUv ?? '');\\n\\t\\t\\t\\tthis.fDefineSet(true, '{reflectionDecode}', ChunkUtils.decodeFunc(options.reflectionEncoding));\\n\\t\\t\\t\\tthis.fDefineSet(true, '{reflectionCubemapDecode}', ChunkUtils.decodeFunc(options.reflectionCubemapEncoding));\\n\\t\\t\\t\\tthis.fDefineSet(true, '{ambientDecode}', ChunkUtils.decodeFunc(options.ambientEncoding));\\n\\t\\t\\t\\tthis._setupLightingDefines(hasAreaLights, options.clusteredLightingEnabled);\\n\\t\\t}\\n\\t\\tprepareShadowPass() {\\n\\t\\t\\t\\tconst { options } = this;\\n\\t\\t\\t\\tconst lightType = this.shaderPassInfo.lightType;\\n\\t\\t\\t\\tconst shadowType = this.shaderPassInfo.shadowType;\\n\\t\\t\\t\\tconst shadowInfo = shadowTypeInfo.get(shadowType);\\n\\t\\t\\t\\tconst usePerspectiveDepth = lightType === LIGHTTYPE_DIRECTIONAL || !shadowInfo.vsm && lightType === LIGHTTYPE_SPOT;\\n\\t\\t\\t\\tthis.fDefineSet(usePerspectiveDepth, 'PERSPECTIVE_DEPTH');\\n\\t\\t\\t\\tthis.fDefineSet(true, 'LIGHT_TYPE', `${lightTypeNames[lightType]}`);\\n\\t\\t\\t\\tthis.fDefineSet(true, 'SHADOW_TYPE', `${shadowInfo.name}`);\\n\\t\\t\\t\\tthis.fDefineSet(options.alphaTest, 'LIT_ALPHA_TEST');\\n\\t\\t}\\n\\t\\tgenerateFragmentShader(frontendDecl, frontendCode, lightingUv) {\\n\\t\\t\\t\\tconst options = this.options;\\n\\t\\t\\t\\tthis.includes.set('frontendDeclPS', frontendDecl ?? '');\\n\\t\\t\\t\\tthis.includes.set('frontendCodePS', frontendCode ?? '');\\n\\t\\t\\t\\tif (options.pass === SHADER_PICK || options.pass === SHADER_PREPASS) ; else if (this.shadowPass) {\\n\\t\\t\\t\\t\\t\\tthis.prepareShadowPass();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.prepareForwardPass(lightingUv);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.fshader = `\\n\\t\\t\\t\\t\\t\\t#include \\\"litMainPS\\\"\\n\\t\\t\\t\\t`;\\n\\t\\t}\\n\\t\\tconstructor(device, options, allowWGSL = true){\\n\\t\\t\\t\\tthis.varyingsCode = '';\\n\\t\\t\\t\\tthis.vDefines = new Map();\\n\\t\\t\\t\\tthis.fDefines = new Map();\\n\\t\\t\\t\\tthis.includes = new Map();\\n\\t\\t\\t\\tthis.chunks = null;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.options = options;\\n\\t\\t\\t\\tconst userChunks = options.shaderChunks;\\n\\t\\t\\t\\tthis.shaderLanguage = device.isWebGPU && allowWGSL && (!userChunks || userChunks.useWGSL) ? SHADERLANGUAGE_WGSL : SHADERLANGUAGE_GLSL;\\n\\t\\t\\t\\tif (device.isWebGPU && this.shaderLanguage === SHADERLANGUAGE_GLSL) {\\n\\t\\t\\t\\t\\t\\tif (!device.hasTranspilers) ;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.attributes = {\\n\\t\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (options.userAttributes) {\\n\\t\\t\\t\\t\\t\\tfor (const [semantic, name] of Object.entries(options.userAttributes)){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.attributes[name] = semantic;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst engineChunks = ShaderChunks.get(device, this.shaderLanguage);\\n\\t\\t\\t\\tthis.chunks = new Map(engineChunks);\\n\\t\\t\\t\\tif (userChunks) {\\n\\t\\t\\t\\t\\t\\tconst userChunkMap = this.shaderLanguage === SHADERLANGUAGE_GLSL ? userChunks.glsl : userChunks.wgsl;\\n\\t\\t\\t\\t\\t\\tuserChunkMap.forEach((chunk, chunkName)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(const a in builtinAttributes){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (builtinAttributes.hasOwnProperty(a) && chunk.indexOf(a) >= 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.attributes[a] = builtinAttributes[a];\\n\\t\\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\\tthis.chunks.set(chunkName, chunk);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.shaderPassInfo = ShaderPass.get(this.device).getByIndex(options.pass);\\n\\t\\t\\t\\tthis.shadowPass = this.shaderPassInfo.isShadow;\\n\\t\\t\\t\\tthis.lighting = options.lights.length > 0 || options.dirLightMapEnabled || options.clusteredLightingEnabled;\\n\\t\\t\\t\\tthis.reflections = options.reflectionSource !== REFLECTIONSRC_NONE;\\n\\t\\t\\t\\tthis.needsNormal = this.lighting || this.reflections || options.useSpecular || options.ambientSH || options.useHeights || options.enableGGXSpecular || options.clusteredLightingEnabled && !this.shadowPass || options.useClearCoatNormals;\\n\\t\\t\\t\\tthis.needsNormal = this.needsNormal && !this.shadowPass;\\n\\t\\t\\t\\tthis.needsSceneColor = options.useDynamicRefraction;\\n\\t\\t\\t\\tthis.needsScreenSize = options.useDynamicRefraction;\\n\\t\\t\\t\\tthis.needsTransforms = options.useDynamicRefraction;\\n\\t\\t\\t\\tthis.vshader = null;\\n\\t\\t\\t\\tthis.fshader = null;\\n\\t\\t}\\n}\\n\\nconst LitOptionsUtils = {\\n\\t\\tgenerateKey (options) {\\n\\t\\t\\t\\treturn `lit${Object.keys(options).sort().map((key)=>{\\n\\t\\t\\t\\t\\t\\tif (key === 'shaderChunks') {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn options.shaderChunks?.key ?? '';\\n\\t\\t\\t\\t\\t\\t} else if (key === 'lights') {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn LitOptionsUtils.generateLightsKey(options);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn key + options[key];\\n\\t\\t\\t\\t}).join('\\\\n')}`;\\n\\t\\t},\\n\\t\\tgenerateLightsKey (options) {\\n\\t\\t\\t\\treturn `lights:${options.lights.map((light)=>{\\n\\t\\t\\t\\t\\t\\treturn !options.clusteredLightingEnabled || light._type === LIGHTTYPE_DIRECTIONAL ? `${light.key},` : '';\\n\\t\\t\\t\\t}).join('')}`;\\n\\t\\t}\\n};\\n\\nclass StandardMaterialOptions {\\n\\t\\tget pass() {\\n\\t\\t\\t\\treturn this.litOptions.pass;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.defines = new Map();\\n\\t\\t\\t\\tthis.forceUv1 = false;\\n\\t\\t\\t\\tthis.specularTint = false;\\n\\t\\t\\t\\tthis.metalnessTint = false;\\n\\t\\t\\t\\tthis.glossTint = false;\\n\\t\\t\\t\\tthis.emissiveEncoding = 'linear';\\n\\t\\t\\t\\tthis.lightMapEncoding = 'linear';\\n\\t\\t\\t\\tthis.vertexColorGamma = false;\\n\\t\\t\\t\\tthis.packedNormal = false;\\n\\t\\t\\t\\tthis.normalDetailPackedNormal = false;\\n\\t\\t\\t\\tthis.clearCoatPackedNormal = false;\\n\\t\\t\\t\\tthis.glossInvert = false;\\n\\t\\t\\t\\tthis.sheenGlossInvert = false;\\n\\t\\t\\t\\tthis.clearCoatGlossInvert = false;\\n\\t\\t\\t\\tthis.useAO = false;\\n\\t\\t\\t\\tthis.litOptions = new LitShaderOptions();\\n\\t\\t}\\n}\\n\\nconst _matTex2D = [];\\nconst buildPropertiesList = (options)=>{\\n\\t\\treturn Object.keys(options).filter((key)=>key !== 'litOptions').sort();\\n};\\nclass ShaderGeneratorStandard extends ShaderGenerator {\\n\\t\\tgenerateKey(options) {\\n\\t\\t\\t\\tlet props;\\n\\t\\t\\t\\tif (options === this.optionsContextMin) {\\n\\t\\t\\t\\t\\t\\tif (!this.propsMin) this.propsMin = buildPropertiesList(options);\\n\\t\\t\\t\\t\\t\\tprops = this.propsMin;\\n\\t\\t\\t\\t} else if (options === this.optionsContext) {\\n\\t\\t\\t\\t\\t\\tif (!this.props) this.props = buildPropertiesList(options);\\n\\t\\t\\t\\t\\t\\tprops = this.props;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tprops = buildPropertiesList(options);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst definesHash = ShaderGenerator.definesHash(options.defines);\\n\\t\\t\\t\\tconst key = `standard:\\\\n${definesHash}\\\\n${props.map((prop)=>prop + options[prop]).join('\\\\n')}${LitOptionsUtils.generateKey(options.litOptions)}`;\\n\\t\\t\\t\\treturn key;\\n\\t\\t}\\n\\t\\t_getUvSourceExpression(transformPropName, uVPropName, options) {\\n\\t\\t\\t\\tconst transformId = options[transformPropName];\\n\\t\\t\\t\\tconst uvChannel = options[uVPropName];\\n\\t\\t\\t\\tconst isMainPass = options.litOptions.pass === SHADER_FORWARD;\\n\\t\\t\\t\\tlet expression;\\n\\t\\t\\t\\tif (isMainPass && options.litOptions.nineSlicedMode === SPRITE_RENDERMODE_SLICED) {\\n\\t\\t\\t\\t\\t\\texpression = 'nineSlicedUv';\\n\\t\\t\\t\\t} else if (isMainPass && options.litOptions.nineSlicedMode === SPRITE_RENDERMODE_TILED) {\\n\\t\\t\\t\\t\\t\\texpression = 'nineSlicedUv';\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (transformId === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\texpression = `vUv${uvChannel}`;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\texpression = `vUV${uvChannel}_${transformId}`;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (options.heightMap && transformPropName !== 'heightMapTransform') {\\n\\t\\t\\t\\t\\t\\t\\t\\texpression += ' + dUvOffset';\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn expression;\\n\\t\\t}\\n\\t\\t_validateMapChunk(code, propName, chunkName, chunks) {}\\n\\t\\t_addMapDefines(fDefines, propName, chunkName, options, chunks, mapping, encoding = null) {\\n\\t\\t\\t\\tconst mapPropName = `${propName}Map`;\\n\\t\\t\\t\\tconst propNameCaps = propName.toUpperCase();\\n\\t\\t\\t\\tconst uVPropName = `${mapPropName}Uv`;\\n\\t\\t\\t\\tconst identifierPropName = `${mapPropName}Identifier`;\\n\\t\\t\\t\\tconst transformPropName = `${mapPropName}Transform`;\\n\\t\\t\\t\\tconst channelPropName = `${mapPropName}Channel`;\\n\\t\\t\\t\\tconst vertexColorChannelPropName = `${propName}VertexColorChannel`;\\n\\t\\t\\t\\tconst tintPropName = `${propName}Tint`;\\n\\t\\t\\t\\tconst vertexColorPropName = `${propName}VertexColor`;\\n\\t\\t\\t\\tconst detailModePropName = `${propName}Mode`;\\n\\t\\t\\t\\tconst invertName = `${propName}Invert`;\\n\\t\\t\\t\\tconst tintOption = options[tintPropName];\\n\\t\\t\\t\\tconst vertexColorOption = options[vertexColorPropName];\\n\\t\\t\\t\\tconst textureOption = options[mapPropName];\\n\\t\\t\\t\\tconst textureIdentifier = options[identifierPropName];\\n\\t\\t\\t\\tconst detailModeOption = options[detailModePropName];\\n\\t\\t\\t\\tconst chunkCode = chunks.get(chunkName);\\n\\t\\t\\t\\tif (textureOption) {\\n\\t\\t\\t\\t\\t\\tfDefines.set(`STD_${propNameCaps}_TEXTURE`, '');\\n\\t\\t\\t\\t\\t\\tconst uv = this._getUvSourceExpression(transformPropName, uVPropName, options);\\n\\t\\t\\t\\t\\t\\tfDefines.set(`{STD_${propNameCaps}_TEXTURE_UV}`, uv);\\n\\t\\t\\t\\t\\t\\tfDefines.set(`{STD_${propNameCaps}_TEXTURE_CHANNEL}`, options[channelPropName]);\\n\\t\\t\\t\\t\\t\\tconst textureId = `{STD_${propNameCaps}_TEXTURE_NAME}`;\\n\\t\\t\\t\\t\\t\\tif (chunkCode.includes(textureId)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlet samplerName = `texture_${mapPropName}`;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst alias = mapping[textureIdentifier];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (alias) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsamplerName = alias;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmapping[textureIdentifier] = samplerName;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfDefines.set(`STD_${propNameCaps}_TEXTURE_ALLOCATE`, '');\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tfDefines.set(textureId, samplerName);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (encoding) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst textureDecode = options[channelPropName] === 'aaa' ? 'passThrough' : ChunkUtils.decodeFunc(encoding);\\n\\t\\t\\t\\t\\t\\t\\t\\tfDefines.set(`{STD_${propNameCaps}_TEXTURE_DECODE}`, textureDecode);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (vertexColorOption) {\\n\\t\\t\\t\\t\\t\\tfDefines.set(`STD_${propNameCaps}_VERTEX`, '');\\n\\t\\t\\t\\t\\t\\tfDefines.set(`{STD_${propNameCaps}_VERTEX_CHANNEL}`, options[vertexColorChannelPropName]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (detailModeOption) {\\n\\t\\t\\t\\t\\t\\tfDefines.set(`{STD_${propNameCaps}_DETAILMODE}`, detailModeOption);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (tintOption) {\\n\\t\\t\\t\\t\\t\\tfDefines.set(`STD_${propNameCaps}_CONSTANT`, '');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!!options[invertName]) {\\n\\t\\t\\t\\t\\t\\tfDefines.set(`STD_${propNameCaps}_INVERT`, '');\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_correctChannel(p, chan, _matTex2D) {\\n\\t\\t\\t\\tif (_matTex2D[p] > 0) {\\n\\t\\t\\t\\t\\t\\tif (_matTex2D[p] < chan.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn chan.substring(0, _matTex2D[p]);\\n\\t\\t\\t\\t\\t\\t} else if (_matTex2D[p] > chan.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlet str = chan;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst chr = str.charAt(str.length - 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst addLen = _matTex2D[p] - str.length;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < addLen; i++)str += chr;\\n\\t\\t\\t\\t\\t\\t\\t\\treturn str;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn chan;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcreateVertexShader(litShader, options) {\\n\\t\\t\\t\\tconst useUv = [];\\n\\t\\t\\t\\tconst useUnmodifiedUv = [];\\n\\t\\t\\t\\tconst mapTransforms = [];\\n\\t\\t\\t\\tconst maxUvSets = 2;\\n\\t\\t\\t\\tfor(const p in _matTex2D){\\n\\t\\t\\t\\t\\t\\tconst mapName = `${p}Map`;\\n\\t\\t\\t\\t\\t\\tif (options[`${p}VertexColor`]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst colorChannelName = `${p}VertexColorChannel`;\\n\\t\\t\\t\\t\\t\\t\\t\\toptions[colorChannelName] = this._correctChannel(p, options[colorChannelName], _matTex2D);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (options[mapName]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst channelName = `${mapName}Channel`;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst transformName = `${mapName}Transform`;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst uvName = `${mapName}Uv`;\\n\\t\\t\\t\\t\\t\\t\\t\\toptions[uvName] = Math.min(options[uvName], maxUvSets - 1);\\n\\t\\t\\t\\t\\t\\t\\t\\toptions[channelName] = this._correctChannel(p, options[channelName], _matTex2D);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst uvSet = options[uvName];\\n\\t\\t\\t\\t\\t\\t\\t\\tuseUv[uvSet] = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tuseUnmodifiedUv[uvSet] = useUnmodifiedUv[uvSet] || options[mapName] && !options[transformName];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (options[transformName]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmapTransforms.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tname: p,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tid: options[transformName],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuv: options[uvName]\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.forceUv1) {\\n\\t\\t\\t\\t\\t\\tuseUv[1] = true;\\n\\t\\t\\t\\t\\t\\tuseUnmodifiedUv[1] = useUnmodifiedUv[1] !== undefined ? useUnmodifiedUv[1] : true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlitShader.generateVertexShader(useUv, useUnmodifiedUv, mapTransforms);\\n\\t\\t}\\n\\t\\tprepareFragmentDefines(options, fDefines, shaderPassInfo) {\\n\\t\\t\\t\\tconst fDefineSet = (condition, name, value = '')=>{\\n\\t\\t\\t\\t\\t\\tif (condition) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfDefines.set(name, value);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tfDefineSet(options.lightMap, 'STD_LIGHTMAP', '');\\n\\t\\t\\t\\tfDefineSet(options.lightVertexColor, 'STD_LIGHT_VERTEX_COLOR', '');\\n\\t\\t\\t\\tfDefineSet(options.dirLightMap && options.litOptions.useSpecular, 'STD_LIGHTMAP_DIR', '');\\n\\t\\t\\t\\tfDefineSet(options.heightMap, 'STD_HEIGHT_MAP', '');\\n\\t\\t\\t\\tfDefineSet(options.useSpecularColor, 'STD_SPECULAR_COLOR', '');\\n\\t\\t\\t\\tfDefineSet(options.aoMap || options.aoVertexColor || options.useAO, 'STD_AO', '');\\n\\t\\t\\t\\tfDefineSet(true, 'STD_OPACITY_DITHER', ditherNames[shaderPassInfo.isForward ? options.litOptions.opacityDither : options.litOptions.opacityShadowDither]);\\n\\t\\t}\\n\\t\\tcreateShaderDefinition(device, options) {\\n\\t\\t\\t\\tconst shaderPassInfo = ShaderPass.get(device).getByIndex(options.litOptions.pass);\\n\\t\\t\\t\\tconst isForwardPass = shaderPassInfo.isForward;\\n\\t\\t\\t\\tconst litShader = new LitShader(device, options.litOptions);\\n\\t\\t\\t\\tthis.createVertexShader(litShader, options);\\n\\t\\t\\t\\tconst textureMapping = {};\\n\\t\\t\\t\\toptions.litOptions.fresnelModel = options.litOptions.fresnelModel === 0 ? FRESNEL_SCHLICK : options.litOptions.fresnelModel;\\n\\t\\t\\t\\tconst fDefines = litShader.fDefines;\\n\\t\\t\\t\\tthis.prepareFragmentDefines(options, fDefines, shaderPassInfo);\\n\\t\\t\\t\\tlet lightingUv = '';\\n\\t\\t\\t\\tif (isForwardPass) {\\n\\t\\t\\t\\t\\t\\tif (options.heightMap) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'height', 'parallaxPS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (options.litOptions.blendType !== BLEND_NONE || options.litOptions.alphaTest || options.litOptions.alphaToCoverage || options.litOptions.opacityDither !== DITHER_NONE) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'opacity', 'opacityPS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (litShader.needsNormal) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (options.normalMap || options.clearCoatNormalMap) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!options.litOptions.hasTangents) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst baseName = options.normalMap ? 'normalMap' : 'clearCoatNormalMap';\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlightingUv = this._getUvSourceExpression(`${baseName}Transform`, `${baseName}Uv`, options);\\n\\t\\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\\tthis._addMapDefines(fDefines, 'normalDetail', 'normalMapPS', options, litShader.chunks, textureMapping, options.normalDetailPackedNormal ? 'xy' : 'xyz');\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'normal', 'normalMapPS', options, litShader.chunks, textureMapping, options.packedNormal ? 'xy' : 'xyz');\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (options.diffuseDetail) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'diffuseDetail', 'diffusePS', options, litShader.chunks, textureMapping, options.diffuseDetailEncoding);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'diffuse', 'diffusePS', options, litShader.chunks, textureMapping, options.diffuseEncoding);\\n\\t\\t\\t\\t\\t\\tif (options.litOptions.useRefraction) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'refraction', 'transmissionPS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'thickness', 'thicknessPS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (options.litOptions.useIridescence) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'iridescence', 'iridescencePS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'iridescenceThickness', 'iridescenceThicknessPS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (litShader.lighting && options.litOptions.useSpecular || litShader.reflections) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (options.litOptions.useSheen) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'sheen', 'sheenPS', options, litShader.chunks, textureMapping, options.sheenEncoding);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'sheenGloss', 'sheenGlossPS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (options.litOptions.useMetalness) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'metalness', 'metalnessPS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'ior', 'iorPS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (options.litOptions.useSpecularityFactor) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'specularityFactor', 'specularityFactorPS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (options.useSpecularColor) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'specular', 'specularPS', options, litShader.chunks, textureMapping, options.specularEncoding);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'gloss', 'glossPS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (options.aoDetail) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'aoDetail', 'aoPS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (options.aoMap || options.aoVertexColor || options.useAO) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'ao', 'aoPS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'emissive', 'emissivePS', options, litShader.chunks, textureMapping, options.emissiveEncoding);\\n\\t\\t\\t\\t\\t\\tif (options.litOptions.useClearCoat) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'clearCoat', 'clearCoatPS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'clearCoatGloss', 'clearCoatGlossPS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'clearCoatNormal', 'clearCoatNormalPS', options, litShader.chunks, textureMapping, options.clearCoatPackedNormal ? 'xy' : 'xyz');\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (options.litOptions.enableGGXSpecular) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'anisotropy', 'anisotropyPS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (options.lightMap || options.lightVertexColor) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'light', 'lightmapPS', options, litShader.chunks, textureMapping, options.lightMapEncoding);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst opacityShadowDither = options.litOptions.opacityShadowDither;\\n\\t\\t\\t\\t\\t\\tif (options.litOptions.alphaTest || opacityShadowDither) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._addMapDefines(fDefines, 'opacity', 'opacityPS', options, litShader.chunks, textureMapping);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlitShader.generateFragmentShader(litShader.chunks.get('stdDeclarationPS'), litShader.chunks.get('stdFrontEndPS'), lightingUv);\\n\\t\\t\\t\\tconst includes = MapUtils.merge(litShader.chunks, litShader.includes);\\n\\t\\t\\t\\tconst vDefines = litShader.vDefines;\\n\\t\\t\\t\\toptions.defines.forEach((value, key)=>vDefines.set(key, value));\\n\\t\\t\\t\\toptions.defines.forEach((value, key)=>fDefines.set(key, value));\\n\\t\\t\\t\\tconst definition = ShaderDefinitionUtils.createDefinition(device, {\\n\\t\\t\\t\\t\\t\\tname: 'StandardShader',\\n\\t\\t\\t\\t\\t\\tattributes: litShader.attributes,\\n\\t\\t\\t\\t\\t\\tshaderLanguage: litShader.shaderLanguage,\\n\\t\\t\\t\\t\\t\\tvertexCode: litShader.vshader,\\n\\t\\t\\t\\t\\t\\tfragmentCode: litShader.fshader,\\n\\t\\t\\t\\t\\t\\tvertexIncludes: includes,\\n\\t\\t\\t\\t\\t\\tfragmentIncludes: includes,\\n\\t\\t\\t\\t\\t\\tfragmentDefines: fDefines,\\n\\t\\t\\t\\t\\t\\tvertexDefines: vDefines\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (litShader.shaderPassInfo.isForward) {\\n\\t\\t\\t\\t\\t\\tdefinition.tag = SHADERTAG_MATERIAL;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn definition;\\n\\t\\t}\\n\\t\\tconstructor(...args){\\n\\t\\t\\t\\tsuper(...args), this.optionsContext = new StandardMaterialOptions(), this.optionsContextMin = new StandardMaterialOptions();\\n\\t\\t}\\n}\\nconst standard = new ShaderGeneratorStandard();\\n\\nconst arraysEqual = (a, b)=>{\\n\\t\\tif (a.length !== b.length) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tfor(let i = 0; i < a.length; ++i){\\n\\t\\t\\t\\tif (a[i] !== b[i]) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn true;\\n};\\nconst notWhite = (color)=>{\\n\\t\\treturn color.r !== 1 || color.g !== 1 || color.b !== 1;\\n};\\nconst notBlack = (color)=>{\\n\\t\\treturn color.r !== 0 || color.g !== 0 || color.b !== 0;\\n};\\nclass StandardMaterialOptionsBuilder {\\n\\t\\tupdateMinRef(options, scene, stdMat, objDefs, pass, sortedLights) {\\n\\t\\t\\t\\tthis._updateSharedOptions(options, scene, stdMat, objDefs, pass);\\n\\t\\t\\t\\tthis._updateMinOptions(options, stdMat, pass);\\n\\t\\t\\t\\tthis._updateUVOptions(options, stdMat, objDefs, true);\\n\\t\\t}\\n\\t\\tupdateRef(options, scene, cameraShaderParams, stdMat, objDefs, pass, sortedLights) {\\n\\t\\t\\t\\tthis._updateSharedOptions(options, scene, stdMat, objDefs, pass);\\n\\t\\t\\t\\tthis._updateEnvOptions(options, stdMat, scene, cameraShaderParams);\\n\\t\\t\\t\\tthis._updateMaterialOptions(options, stdMat, scene);\\n\\t\\t\\t\\toptions.litOptions.hasTangents = objDefs && (objDefs & SHADERDEF_TANGENTS) !== 0;\\n\\t\\t\\t\\tthis._updateLightOptions(options, scene, stdMat, objDefs, sortedLights);\\n\\t\\t\\t\\tthis._updateUVOptions(options, stdMat, objDefs, false, cameraShaderParams);\\n\\t\\t}\\n\\t\\t_updateSharedOptions(options, scene, stdMat, objDefs, pass) {\\n\\t\\t\\t\\toptions.forceUv1 = stdMat.forceUv1;\\n\\t\\t\\t\\tif (stdMat.userAttributes) {\\n\\t\\t\\t\\t\\t\\toptions.litOptions.userAttributes = Object.fromEntries(stdMat.userAttributes.entries());\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\toptions.litOptions.shaderChunks = stdMat.shaderChunks;\\n\\t\\t\\t\\toptions.litOptions.pass = pass;\\n\\t\\t\\t\\toptions.litOptions.alphaTest = stdMat.alphaTest > 0;\\n\\t\\t\\t\\toptions.litOptions.blendType = stdMat.blendType;\\n\\t\\t\\t\\toptions.litOptions.screenSpace = objDefs && (objDefs & SHADERDEF_SCREENSPACE) !== 0;\\n\\t\\t\\t\\toptions.litOptions.skin = objDefs && (objDefs & SHADERDEF_SKIN) !== 0;\\n\\t\\t\\t\\toptions.litOptions.batch = objDefs && (objDefs & SHADERDEF_BATCH) !== 0;\\n\\t\\t\\t\\toptions.litOptions.useInstancing = objDefs && (objDefs & SHADERDEF_INSTANCING) !== 0;\\n\\t\\t\\t\\toptions.litOptions.useMorphPosition = objDefs && (objDefs & SHADERDEF_MORPH_POSITION) !== 0;\\n\\t\\t\\t\\toptions.litOptions.useMorphNormal = objDefs && (objDefs & SHADERDEF_MORPH_NORMAL) !== 0;\\n\\t\\t\\t\\toptions.litOptions.useMorphTextureBasedInt = objDefs && (objDefs & SHADERDEF_MORPH_TEXTURE_BASED_INT) !== 0;\\n\\t\\t\\t\\toptions.litOptions.nineSlicedMode = stdMat.nineSlicedMode || 0;\\n\\t\\t\\t\\tif (scene.clusteredLightingEnabled && stdMat.useLighting) {\\n\\t\\t\\t\\t\\t\\toptions.litOptions.clusteredLightingEnabled = true;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.clusteredLightingCookiesEnabled = scene.lighting.cookiesEnabled;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.clusteredLightingShadowsEnabled = scene.lighting.shadowsEnabled;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.clusteredLightingShadowType = scene.lighting.shadowType;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.clusteredLightingAreaLightsEnabled = scene.lighting.areaLightsEnabled;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\toptions.litOptions.clusteredLightingEnabled = false;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.clusteredLightingCookiesEnabled = false;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.clusteredLightingShadowsEnabled = false;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.clusteredLightingAreaLightsEnabled = false;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_updateUVOptions(options, stdMat, objDefs, minimalOptions, cameraShaderParams) {\\n\\t\\t\\t\\tlet hasUv0 = false;\\n\\t\\t\\t\\tlet hasUv1 = false;\\n\\t\\t\\t\\tlet hasVcolor = false;\\n\\t\\t\\t\\tif (objDefs) {\\n\\t\\t\\t\\t\\t\\thasUv0 = (objDefs & SHADERDEF_UV0) !== 0;\\n\\t\\t\\t\\t\\t\\thasUv1 = (objDefs & SHADERDEF_UV1) !== 0;\\n\\t\\t\\t\\t\\t\\thasVcolor = (objDefs & SHADERDEF_VCOLOR) !== 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\toptions.litOptions.vertexColors = false;\\n\\t\\t\\t\\tthis._mapXForms = [];\\n\\t\\t\\t\\tconst uniqueTextureMap = {};\\n\\t\\t\\t\\tfor(const p in _matTex2D){\\n\\t\\t\\t\\t\\t\\tthis._updateTexOptions(options, stdMat, p, hasUv0, hasUv1, hasVcolor, minimalOptions, uniqueTextureMap);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._mapXForms = null;\\n\\t\\t\\t\\toptions.litOptions.ssao = cameraShaderParams?.ssaoEnabled;\\n\\t\\t\\t\\toptions.useAO = options.litOptions.ssao;\\n\\t\\t\\t\\toptions.litOptions.lightMapEnabled = options.lightMap;\\n\\t\\t\\t\\toptions.litOptions.dirLightMapEnabled = options.dirLightMap;\\n\\t\\t\\t\\toptions.litOptions.useHeights = options.heightMap;\\n\\t\\t\\t\\toptions.litOptions.useNormals = options.normalMap;\\n\\t\\t\\t\\toptions.litOptions.useClearCoatNormals = options.clearCoatNormalMap;\\n\\t\\t\\t\\toptions.litOptions.useAo = options.aoMap || options.aoVertexColor || options.litOptions.ssao;\\n\\t\\t\\t\\toptions.litOptions.diffuseMapEnabled = options.diffuseMap;\\n\\t\\t}\\n\\t\\t_updateTexOptions(options, stdMat, p, hasUv0, hasUv1, hasVcolor, minimalOptions, uniqueTextureMap) {\\n\\t\\t\\t\\tconst isOpacity = p === 'opacity';\\n\\t\\t\\t\\tif (!minimalOptions || isOpacity) {\\n\\t\\t\\t\\t\\t\\tconst mname = `${p}Map`;\\n\\t\\t\\t\\t\\t\\tconst vname = `${p}VertexColor`;\\n\\t\\t\\t\\t\\t\\tconst vcname = `${p}VertexColorChannel`;\\n\\t\\t\\t\\t\\t\\tconst cname = `${mname}Channel`;\\n\\t\\t\\t\\t\\t\\tconst tname = `${mname}Transform`;\\n\\t\\t\\t\\t\\t\\tconst uname = `${mname}Uv`;\\n\\t\\t\\t\\t\\t\\tconst iname = `${mname}Identifier`;\\n\\t\\t\\t\\t\\t\\tif (p !== 'light') {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions[mname] = false;\\n\\t\\t\\t\\t\\t\\t\\t\\toptions[iname] = undefined;\\n\\t\\t\\t\\t\\t\\t\\t\\toptions[cname] = '';\\n\\t\\t\\t\\t\\t\\t\\t\\toptions[tname] = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\toptions[uname] = 0;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\toptions[vname] = false;\\n\\t\\t\\t\\t\\t\\toptions[vcname] = '';\\n\\t\\t\\t\\t\\t\\tif (isOpacity && stdMat.blendType === BLEND_NONE && stdMat.alphaTest === 0.0 && !stdMat.alphaToCoverage && stdMat.opacityDither === DITHER_NONE) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (p !== 'height' && stdMat[vname]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (hasVcolor) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions[vname] = stdMat[vname];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions[vcname] = stdMat[vcname];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions.litOptions.vertexColors = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (stdMat[mname]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlet allow = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (stdMat[uname] === 0 && !hasUv0) allow = false;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (stdMat[uname] === 1 && !hasUv1) allow = false;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (allow) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst mapId = stdMat[mname].id;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet identifier = uniqueTextureMap[mapId];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (identifier === undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuniqueTextureMap[mapId] = p;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tidentifier = p;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions[mname] = !!stdMat[mname];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions[iname] = identifier;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions[tname] = this._getMapTransformID(stdMat.getUniform(tname), stdMat[uname]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions[cname] = stdMat[cname];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions[uname] = stdMat[uname];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_updateMinOptions(options, stdMat, pass) {\\n\\t\\t\\t\\tconst isPrepass = pass === SHADER_PREPASS;\\n\\t\\t\\t\\toptions.litOptions.opacityShadowDither = isPrepass ? stdMat.opacityDither : stdMat.opacityShadowDither;\\n\\t\\t\\t\\toptions.litOptions.linearDepth = isPrepass;\\n\\t\\t\\t\\toptions.litOptions.lights = [];\\n\\t\\t}\\n\\t\\t_updateMaterialOptions(options, stdMat, scene) {\\n\\t\\t\\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\\t\\t\\tconst useSpecularColor = !stdMat.useMetalness || stdMat.useMetalnessSpecularColor;\\n\\t\\t\\t\\tconst specularTint = useSpecular && (stdMat.specularTint || !stdMat.specularMap && !stdMat.specularVertexColor) && notWhite(stdMat.specular);\\n\\t\\t\\t\\tconst specularityFactorTint = useSpecular && stdMat.useMetalnessSpecularColor && (stdMat.specularityFactorTint || stdMat.specularityFactor < 1 && !stdMat.specularityFactorMap);\\n\\t\\t\\t\\tconst isPackedNormalMap = (texture)=>texture ? texture.format === PIXELFORMAT_DXT5 || texture.type === TEXTURETYPE_SWIZZLEGGGR : false;\\n\\t\\t\\t\\tconst equalish = (a, b)=>Math.abs(a - b) < 1e-4;\\n\\t\\t\\t\\toptions.specularTint = specularTint;\\n\\t\\t\\t\\toptions.specularityFactorTint = specularityFactorTint;\\n\\t\\t\\t\\toptions.metalnessTint = stdMat.useMetalness && stdMat.metalness < 1;\\n\\t\\t\\t\\toptions.glossTint = true;\\n\\t\\t\\t\\toptions.diffuseEncoding = stdMat.diffuseMap?.encoding;\\n\\t\\t\\t\\toptions.diffuseDetailEncoding = stdMat.diffuseDetailMap?.encoding;\\n\\t\\t\\t\\toptions.emissiveEncoding = stdMat.emissiveMap?.encoding;\\n\\t\\t\\t\\toptions.lightMapEncoding = stdMat.lightMap?.encoding;\\n\\t\\t\\t\\toptions.packedNormal = isPackedNormalMap(stdMat.normalMap);\\n\\t\\t\\t\\toptions.refractionTint = !equalish(stdMat.refraction, 1.0);\\n\\t\\t\\t\\toptions.refractionIndexTint = !equalish(stdMat.refractionIndex, 1.0 / 1.5);\\n\\t\\t\\t\\toptions.thicknessTint = stdMat.useDynamicRefraction && stdMat.thickness !== 1.0;\\n\\t\\t\\t\\toptions.specularEncoding = stdMat.specularMap?.encoding;\\n\\t\\t\\t\\toptions.sheenEncoding = stdMat.sheenMap?.encoding;\\n\\t\\t\\t\\toptions.aoMapUv = stdMat.aoUvSet;\\n\\t\\t\\t\\toptions.aoDetail = !!stdMat.aoDetailMap;\\n\\t\\t\\t\\toptions.diffuseDetail = !!stdMat.diffuseDetailMap;\\n\\t\\t\\t\\toptions.normalDetail = !!stdMat.normalMap;\\n\\t\\t\\t\\toptions.normalDetailPackedNormal = isPackedNormalMap(stdMat.normalDetailMap);\\n\\t\\t\\t\\toptions.diffuseDetailMode = stdMat.diffuseDetailMode;\\n\\t\\t\\t\\toptions.aoDetailMode = stdMat.aoDetailMode;\\n\\t\\t\\t\\toptions.clearCoatGloss = !!stdMat.clearCoatGloss;\\n\\t\\t\\t\\toptions.clearCoatPackedNormal = isPackedNormalMap(stdMat.clearCoatNormalMap);\\n\\t\\t\\t\\toptions.iorTint = !equalish(stdMat.refractionIndex, 1.0 / 1.5);\\n\\t\\t\\t\\tif (scene.forcePassThroughSpecular) {\\n\\t\\t\\t\\t\\t\\toptions.specularEncoding = 'linear';\\n\\t\\t\\t\\t\\t\\toptions.sheenEncoding = 'linear';\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\toptions.iridescenceTint = stdMat.iridescence !== 1.0;\\n\\t\\t\\t\\toptions.glossInvert = stdMat.glossInvert;\\n\\t\\t\\t\\toptions.sheenGlossInvert = stdMat.sheenGlossInvert;\\n\\t\\t\\t\\toptions.clearCoatGlossInvert = stdMat.clearCoatGlossInvert;\\n\\t\\t\\t\\toptions.useSpecularColor = useSpecularColor;\\n\\t\\t\\t\\toptions.litOptions.separateAmbient = false;\\n\\t\\t\\t\\toptions.litOptions.pixelSnap = stdMat.pixelSnap;\\n\\t\\t\\t\\toptions.litOptions.ambientSH = !!stdMat.ambientSH;\\n\\t\\t\\t\\toptions.litOptions.twoSidedLighting = stdMat.twoSidedLighting;\\n\\t\\t\\t\\toptions.litOptions.occludeSpecular = stdMat.occludeSpecular;\\n\\t\\t\\t\\toptions.litOptions.occludeSpecularFloat = stdMat.occludeSpecularIntensity !== 1.0;\\n\\t\\t\\t\\toptions.litOptions.useMsdf = !!stdMat.msdfMap;\\n\\t\\t\\t\\toptions.litOptions.msdfTextAttribute = !!stdMat.msdfTextAttribute;\\n\\t\\t\\t\\toptions.litOptions.alphaToCoverage = stdMat.alphaToCoverage;\\n\\t\\t\\t\\toptions.litOptions.opacityFadesSpecular = stdMat.opacityFadesSpecular;\\n\\t\\t\\t\\toptions.litOptions.opacityDither = stdMat.opacityDither;\\n\\t\\t\\t\\toptions.litOptions.cubeMapProjection = stdMat.cubeMapProjection;\\n\\t\\t\\t\\toptions.litOptions.occludeDirect = stdMat.occludeDirect;\\n\\t\\t\\t\\toptions.litOptions.useSpecular = useSpecular;\\n\\t\\t\\t\\toptions.litOptions.useSpecularityFactor = (specularityFactorTint || !!stdMat.specularityFactorMap) && stdMat.useMetalnessSpecularColor;\\n\\t\\t\\t\\toptions.litOptions.enableGGXSpecular = stdMat.enableGGXSpecular;\\n\\t\\t\\t\\toptions.litOptions.useAnisotropy = stdMat.enableGGXSpecular && (stdMat.anisotropyIntensity > 0 || !!stdMat.anisotropyMap);\\n\\t\\t\\t\\toptions.litOptions.fresnelModel = stdMat.fresnelModel;\\n\\t\\t\\t\\toptions.litOptions.useRefraction = (stdMat.refraction || !!stdMat.refractionMap) && (stdMat.useDynamicRefraction || options.litOptions.reflectionSource !== REFLECTIONSRC_NONE);\\n\\t\\t\\t\\toptions.litOptions.useClearCoat = !!stdMat.clearCoat;\\n\\t\\t\\t\\toptions.litOptions.useSheen = stdMat.useSheen;\\n\\t\\t\\t\\toptions.litOptions.useIridescence = stdMat.useIridescence && stdMat.iridescence !== 0.0;\\n\\t\\t\\t\\toptions.litOptions.useMetalness = stdMat.useMetalness;\\n\\t\\t\\t\\toptions.litOptions.useDynamicRefraction = stdMat.useDynamicRefraction;\\n\\t\\t\\t\\toptions.litOptions.dispersion = stdMat.dispersion > 0;\\n\\t\\t\\t\\toptions.litOptions.shadowCatcher = stdMat.shadowCatcher;\\n\\t\\t\\t\\toptions.litOptions.useVertexColorGamma = stdMat.vertexColorGamma;\\n\\t\\t}\\n\\t\\t_updateEnvOptions(options, stdMat, scene, cameraShaderParams) {\\n\\t\\t\\t\\toptions.litOptions.fog = stdMat.useFog ? cameraShaderParams.fog : FOG_NONE;\\n\\t\\t\\t\\toptions.litOptions.gamma = cameraShaderParams.shaderOutputGamma;\\n\\t\\t\\t\\toptions.litOptions.toneMap = stdMat.useTonemap ? cameraShaderParams.toneMapping : TONEMAP_NONE;\\n\\t\\t\\t\\tlet usingSceneEnv = false;\\n\\t\\t\\t\\tif (stdMat.envAtlas && stdMat.cubeMap) {\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionSource = REFLECTIONSRC_ENVATLASHQ;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionEncoding = stdMat.envAtlas.encoding;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionCubemapEncoding = stdMat.cubeMap.encoding;\\n\\t\\t\\t\\t} else if (stdMat.envAtlas) {\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionSource = REFLECTIONSRC_ENVATLAS;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionEncoding = stdMat.envAtlas.encoding;\\n\\t\\t\\t\\t} else if (stdMat.cubeMap) {\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionSource = REFLECTIONSRC_CUBEMAP;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionEncoding = stdMat.cubeMap.encoding;\\n\\t\\t\\t\\t} else if (stdMat.sphereMap) {\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionSource = REFLECTIONSRC_SPHEREMAP;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionEncoding = stdMat.sphereMap.encoding;\\n\\t\\t\\t\\t} else if (stdMat.useSkybox && scene.envAtlas && scene.skybox) {\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionSource = REFLECTIONSRC_ENVATLASHQ;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionEncoding = scene.envAtlas.encoding;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionCubemapEncoding = scene.skybox.encoding;\\n\\t\\t\\t\\t\\t\\tusingSceneEnv = true;\\n\\t\\t\\t\\t} else if (stdMat.useSkybox && scene.envAtlas) {\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionSource = REFLECTIONSRC_ENVATLAS;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionEncoding = scene.envAtlas.encoding;\\n\\t\\t\\t\\t\\t\\tusingSceneEnv = true;\\n\\t\\t\\t\\t} else if (stdMat.useSkybox && scene.skybox) {\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionSource = REFLECTIONSRC_CUBEMAP;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionEncoding = scene.skybox.encoding;\\n\\t\\t\\t\\t\\t\\tusingSceneEnv = true;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionSource = REFLECTIONSRC_NONE;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.reflectionEncoding = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (stdMat.ambientSH) {\\n\\t\\t\\t\\t\\t\\toptions.litOptions.ambientSource = AMBIENTSRC_AMBIENTSH;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.ambientEncoding = null;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst envAtlas = stdMat.envAtlas || (stdMat.useSkybox && scene.envAtlas ? scene.envAtlas : null);\\n\\t\\t\\t\\t\\t\\tif (envAtlas && !stdMat.sphereMap) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.litOptions.ambientSource = AMBIENTSRC_ENVALATLAS;\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.litOptions.ambientEncoding = envAtlas.encoding;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.litOptions.ambientSource = AMBIENTSRC_CONSTANT;\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.litOptions.ambientEncoding = null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\toptions.litOptions.skyboxIntensity = usingSceneEnv;\\n\\t\\t\\t\\toptions.litOptions.useCubeMapRotation = usingSceneEnv && scene._skyboxRotationShaderInclude;\\n\\t\\t}\\n\\t\\t_updateLightOptions(options, scene, stdMat, objDefs, sortedLights) {\\n\\t\\t\\t\\toptions.lightMap = false;\\n\\t\\t\\t\\toptions.lightMapChannel = '';\\n\\t\\t\\t\\toptions.lightMapUv = 0;\\n\\t\\t\\t\\toptions.lightMapTransform = 0;\\n\\t\\t\\t\\toptions.litOptions.lightMapWithoutAmbient = false;\\n\\t\\t\\t\\toptions.dirLightMap = false;\\n\\t\\t\\t\\tif (objDefs) {\\n\\t\\t\\t\\t\\t\\toptions.litOptions.noShadow = (objDefs & SHADERDEF_NOSHADOW) !== 0;\\n\\t\\t\\t\\t\\t\\tif ((objDefs & SHADERDEF_LM) !== 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.lightMapEncoding = scene.lightmapPixelFormat === PIXELFORMAT_RGBA8 ? 'rgbm' : 'linear';\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.lightMap = true;\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.lightMapChannel = 'rgb';\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.lightMapUv = 1;\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.lightMapTransform = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.litOptions.lightMapWithoutAmbient = !stdMat.lightMap;\\n\\t\\t\\t\\t\\t\\t\\t\\tif ((objDefs & SHADERDEF_DIRLM) !== 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions.dirLightMap = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif ((objDefs & SHADERDEF_LMAMBIENT) !== 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions.litOptions.lightMapWithoutAmbient = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (stdMat.useLighting) {\\n\\t\\t\\t\\t\\t\\tconst lightsFiltered = [];\\n\\t\\t\\t\\t\\t\\tconst mask = objDefs ? objDefs >> 16 : MASK_AFFECT_DYNAMIC;\\n\\t\\t\\t\\t\\t\\toptions.litOptions.lightMaskDynamic = !!(mask & MASK_AFFECT_DYNAMIC);\\n\\t\\t\\t\\t\\t\\tif (sortedLights) {\\n\\t\\t\\t\\t\\t\\t\\t\\tLitMaterialOptionsBuilder.collectLights(LIGHTTYPE_DIRECTIONAL, sortedLights[LIGHTTYPE_DIRECTIONAL], lightsFiltered, mask);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!scene.clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tLitMaterialOptionsBuilder.collectLights(LIGHTTYPE_OMNI, sortedLights[LIGHTTYPE_OMNI], lightsFiltered, mask);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tLitMaterialOptionsBuilder.collectLights(LIGHTTYPE_SPOT, sortedLights[LIGHTTYPE_SPOT], lightsFiltered, mask);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\toptions.litOptions.lights = lightsFiltered;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\toptions.litOptions.lights = [];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.litOptions.lights.length === 0 && !scene.clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\t\\toptions.litOptions.noShadow = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_getMapTransformID(xform, uv) {\\n\\t\\t\\t\\tif (!xform) return 0;\\n\\t\\t\\t\\tlet xforms = this._mapXForms[uv];\\n\\t\\t\\t\\tif (!xforms) {\\n\\t\\t\\t\\t\\t\\txforms = [];\\n\\t\\t\\t\\t\\t\\tthis._mapXForms[uv] = xforms;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < xforms.length; i++){\\n\\t\\t\\t\\t\\t\\tif (arraysEqual(xforms[i][0].value, xform[0].value) && arraysEqual(xforms[i][1].value, xform[1].value)) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn i + 1;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn xforms.push(xform);\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis._mapXForms = null;\\n\\t\\t}\\n}\\n\\nfunction _textureParameter(name, channel = true, vertexColor = true) {\\n\\t\\tconst result = {};\\n\\t\\tresult[`${name}Map`] = 'texture';\\n\\t\\tresult[`${name}MapTiling`] = 'vec2';\\n\\t\\tresult[`${name}MapOffset`] = 'vec2';\\n\\t\\tresult[`${name}MapRotation`] = 'number';\\n\\t\\tresult[`${name}MapUv`] = 'number';\\n\\t\\tif (channel) {\\n\\t\\t\\t\\tresult[`${name}MapChannel`] = 'string';\\n\\t\\t\\t\\tif (vertexColor) {\\n\\t\\t\\t\\t\\t\\tresult[`${name}VertexColor`] = 'boolean';\\n\\t\\t\\t\\t\\t\\tresult[`${name}VertexColorChannel`] = 'string';\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn result;\\n}\\nconst standardMaterialParameterTypes = {\\n\\t\\tname: 'string',\\n\\t\\tchunks: 'chunks',\\n\\t\\tmappingFormat: 'string',\\n\\t\\t_engine: 'boolean',\\n\\t\\tambient: 'rgb',\\n\\t\\t..._textureParameter('ao'),\\n\\t\\t..._textureParameter('aoDetail', true, false),\\n\\t\\taoDetailMode: 'string',\\n\\t\\taoIntensity: 'number',\\n\\t\\tdiffuse: 'rgb',\\n\\t\\t..._textureParameter('diffuse'),\\n\\t\\t..._textureParameter('diffuseDetail', true, false),\\n\\t\\tdiffuseDetailMode: 'string',\\n\\t\\tvertexColorGamma: 'boolean',\\n\\t\\tspecular: 'rgb',\\n\\t\\tspecularTint: 'boolean',\\n\\t\\t..._textureParameter('specular'),\\n\\t\\toccludeSpecular: 'enum:occludeSpecular',\\n\\t\\tspecularityFactor: 'number',\\n\\t\\tspecularityFactorTint: 'boolean',\\n\\t\\t..._textureParameter('specularityFactor'),\\n\\t\\tuseMetalness: 'boolean',\\n\\t\\tmetalness: 'number',\\n\\t\\tenableGGXSpecular: 'boolean',\\n\\t\\tmetalnessTint: 'boolean',\\n\\t\\t..._textureParameter('metalness'),\\n\\t\\tuseMetalnessSpecularColor: 'boolean',\\n\\t\\tanisotropyIntensity: 'number',\\n\\t\\tanisotropyRotation: 'number',\\n\\t\\t..._textureParameter('anisotropy'),\\n\\t\\tshininess: 'number',\\n\\t\\tgloss: 'number',\\n\\t\\tglossInvert: 'boolean',\\n\\t\\t..._textureParameter('gloss'),\\n\\t\\tclearCoat: 'number',\\n\\t\\t..._textureParameter('clearCoat'),\\n\\t\\tclearCoatGloss: 'number',\\n\\t\\tclearCoatGlossInvert: 'boolean',\\n\\t\\t..._textureParameter('clearCoatGloss'),\\n\\t\\tclearCoatBumpiness: 'number',\\n\\t\\t..._textureParameter('clearCoatNormal', false),\\n\\t\\tuseSheen: 'boolean',\\n\\t\\tsheen: 'rgb',\\n\\t\\t..._textureParameter('sheen'),\\n\\t\\tsheenGloss: 'number',\\n\\t\\tsheenGlossInvert: 'boolean',\\n\\t\\t..._textureParameter('sheenGloss'),\\n\\t\\tfresnelModel: 'number',\\n\\t\\temissive: 'rgb',\\n\\t\\t..._textureParameter('emissive'),\\n\\t\\temissiveIntensity: 'number',\\n\\t\\t..._textureParameter('normal', false),\\n\\t\\tbumpiness: 'number',\\n\\t\\t..._textureParameter('normalDetail', false),\\n\\t\\tnormalDetailMapBumpiness: 'number',\\n\\t\\t..._textureParameter('height', true, false),\\n\\t\\theightMapFactor: 'number',\\n\\t\\talphaToCoverage: 'boolean',\\n\\t\\talphaTest: 'number',\\n\\t\\talphaFade: 'number',\\n\\t\\topacity: 'number',\\n\\t\\t..._textureParameter('opacity'),\\n\\t\\topacityFadesSpecular: 'boolean',\\n\\t\\topacityDither: 'string',\\n\\t\\topacityShadowDither: 'string',\\n\\t\\treflectivity: 'number',\\n\\t\\trefraction: 'number',\\n\\t\\trefractionTint: 'boolean',\\n\\t\\t..._textureParameter('refraction'),\\n\\t\\trefractionIndex: 'number',\\n\\t\\tdispersion: 'number',\\n\\t\\tthickness: 'number',\\n\\t\\tthicknessTint: 'boolean',\\n\\t\\t..._textureParameter('thickness'),\\n\\t\\tattenuation: 'rgb',\\n\\t\\tattenuationDistance: 'number',\\n\\t\\tuseDynamicRefraction: 'boolean',\\n\\t\\tsphereMap: 'texture',\\n\\t\\tcubeMap: 'cubemap',\\n\\t\\tcubeMapProjection: 'number',\\n\\t\\tcubeMapProjectionBox: 'boundingbox',\\n\\t\\tuseIridescence: 'boolean',\\n\\t\\tiridescence: 'number',\\n\\t\\tiridescenceTint: 'boolean',\\n\\t\\t..._textureParameter('iridescence'),\\n\\t\\tiridescenceThicknessTint: 'boolean',\\n\\t\\tiridescenceThicknessMin: 'number',\\n\\t\\tiridescenceThicknessMax: 'number',\\n\\t\\tiridescenceRefractionIndex: 'number',\\n\\t\\t..._textureParameter('iridescenceThickness'),\\n\\t\\t..._textureParameter('light'),\\n\\t\\tdepthTest: 'boolean',\\n\\t\\tdepthFunc: 'enum:depthFunc',\\n\\t\\tdepthWrite: 'boolean',\\n\\t\\tdepthBias: 'number',\\n\\t\\tslopeDepthBias: 'number',\\n\\t\\tcull: 'enum:cull',\\n\\t\\tblendType: 'enum:blendType',\\n\\t\\tuseFog: 'boolean',\\n\\t\\tuseLighting: 'boolean',\\n\\t\\tuseSkybox: 'boolean',\\n\\t\\tuseTonemap: 'boolean',\\n\\t\\tenvAtlas: 'texture',\\n\\t\\ttwoSidedLighting: 'boolean',\\n\\t\\tshadowCatcher: 'boolean'\\n};\\nconst standardMaterialTextureParameters = [];\\nfor(const key in standardMaterialParameterTypes){\\n\\t\\tconst type = standardMaterialParameterTypes[key];\\n\\t\\tif (type === 'texture') {\\n\\t\\t\\t\\tstandardMaterialTextureParameters.push(key);\\n\\t\\t}\\n}\\nconst standardMaterialCubemapParameters = [];\\nfor(const key in standardMaterialParameterTypes){\\n\\t\\tconst type = standardMaterialParameterTypes[key];\\n\\t\\tif (type === 'cubemap') {\\n\\t\\t\\t\\tstandardMaterialCubemapParameters.push(key);\\n\\t\\t}\\n}\\n\\nconst _props = {};\\nconst _uniforms = {};\\nlet _params = new Set();\\nconst _tempColor = new Color();\\nclass StandardMaterial extends Material {\\n\\t\\treset() {\\n\\t\\t\\t\\tObject.keys(_props).forEach((name)=>{\\n\\t\\t\\t\\t\\t\\tthis[`_${name}`] = _props[name].value();\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis._uniformCache = {};\\n\\t\\t}\\n\\t\\tcopy(source) {\\n\\t\\t\\t\\tsuper.copy(source);\\n\\t\\t\\t\\tObject.keys(_props).forEach((k)=>{\\n\\t\\t\\t\\t\\t\\tthis[k] = source[k];\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.userAttributes = new Map(source.userAttributes);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tsetAttribute(name, semantic) {\\n\\t\\t\\t\\tthis.userAttributes.set(semantic, name);\\n\\t\\t}\\n\\t\\t_setParameter(name, value) {\\n\\t\\t\\t\\t_params.add(name);\\n\\t\\t\\t\\tthis.setParameter(name, value);\\n\\t\\t}\\n\\t\\t_setParameters(parameters) {\\n\\t\\t\\t\\tparameters.forEach((v)=>{\\n\\t\\t\\t\\t\\t\\tthis._setParameter(v.name, v.value);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\t_processParameters(paramsName) {\\n\\t\\t\\t\\tconst prevParams = this[paramsName];\\n\\t\\t\\t\\tprevParams.forEach((param)=>{\\n\\t\\t\\t\\t\\t\\tif (!_params.has(param)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdelete this.parameters[param];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis[paramsName] = _params;\\n\\t\\t\\t\\t_params = prevParams;\\n\\t\\t\\t\\t_params.clear();\\n\\t\\t}\\n\\t\\t_updateMap(p) {\\n\\t\\t\\t\\tconst mname = `${p}Map`;\\n\\t\\t\\t\\tconst map = this[mname];\\n\\t\\t\\t\\tif (map) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter(`texture_${mname}`, map);\\n\\t\\t\\t\\t\\t\\tconst tname = `${mname}Transform`;\\n\\t\\t\\t\\t\\t\\tconst uniform = this.getUniform(tname);\\n\\t\\t\\t\\t\\t\\tif (uniform) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._setParameters(uniform);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_allocUniform(name, allocFunc) {\\n\\t\\t\\t\\tlet uniform = this._uniformCache[name];\\n\\t\\t\\t\\tif (!uniform) {\\n\\t\\t\\t\\t\\t\\tuniform = allocFunc();\\n\\t\\t\\t\\t\\t\\tthis._uniformCache[name] = uniform;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn uniform;\\n\\t\\t}\\n\\t\\tgetUniform(name, device, scene) {\\n\\t\\t\\t\\treturn _uniforms[name](this, device, scene);\\n\\t\\t}\\n\\t\\tupdateUniforms(device, scene) {\\n\\t\\t\\t\\tconst getUniform = (name)=>{\\n\\t\\t\\t\\t\\t\\treturn this.getUniform(name, device, scene);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis._setParameter('material_ambient', getUniform('ambient'));\\n\\t\\t\\t\\tthis._setParameter('material_diffuse', getUniform('diffuse'));\\n\\t\\t\\t\\tthis._setParameter('material_aoIntensity', this.aoIntensity);\\n\\t\\t\\t\\tif (this.useMetalness) {\\n\\t\\t\\t\\t\\t\\tif (!this.metalnessMap || this.metalness < 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._setParameter('material_metalness', this.metalness);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!this.specularMap || this.specularTint) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._setParameter('material_specular', getUniform('specular'));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!this.specularityFactorMap || this.specularityFactorTint) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._setParameter('material_specularityFactor', this.specularityFactor);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_sheen', getUniform('sheen'));\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_sheenGloss', this.sheenGloss);\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_refractionIndex', this.refractionIndex);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (!this.specularMap || this.specularTint) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._setParameter('material_specular', getUniform('specular'));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.enableGGXSpecular) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_anisotropyIntensity', this.anisotropyIntensity);\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_anisotropyRotation', [\\n\\t\\t\\t\\t\\t\\t\\t\\tMath.cos(this.anisotropyRotation * math.DEG_TO_RAD),\\n\\t\\t\\t\\t\\t\\t\\t\\tMath.sin(this.anisotropyRotation * math.DEG_TO_RAD)\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.clearCoat > 0) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_clearCoat', this.clearCoat);\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_clearCoatGloss', this.clearCoatGloss);\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_clearCoatBumpiness', this.clearCoatBumpiness);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._setParameter('material_gloss', this.gloss);\\n\\t\\t\\t\\tthis._setParameter('material_emissive', getUniform('emissive'));\\n\\t\\t\\t\\tthis._setParameter('material_emissiveIntensity', this.emissiveIntensity);\\n\\t\\t\\t\\tif (this.refraction > 0) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_refraction', this.refraction);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.dispersion > 0) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_dispersion', this.dispersion);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.useDynamicRefraction) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_thickness', this.thickness);\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_attenuation', getUniform('attenuation'));\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_invAttenuationDistance', this.attenuationDistance === 0 ? 0 : 1.0 / this.attenuationDistance);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.useIridescence) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_iridescence', this.iridescence);\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_iridescenceRefractionIndex', this.iridescenceRefractionIndex);\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_iridescenceThicknessMin', this.iridescenceThicknessMin);\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_iridescenceThicknessMax', this.iridescenceThicknessMax);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._setParameter('material_opacity', this.opacity);\\n\\t\\t\\t\\tif (this.opacityFadesSpecular === false) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_alphaFade', this.alphaFade);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.occludeSpecular) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_occludeSpecularIntensity', this.occludeSpecularIntensity);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.cubeMapProjection === CUBEPROJ_BOX) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter(getUniform('cubeMapProjectionBox'));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(const p in _matTex2D){\\n\\t\\t\\t\\t\\t\\tthis._updateMap(p);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.ambientSH) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter('ambientSH[0]', this.ambientSH);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.normalMap) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_bumpiness', this.bumpiness);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.normalMap && this.normalDetailMap) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_normalDetailMapBumpiness', this.normalDetailMapBumpiness);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.heightMap) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter('material_heightMapFactor', getUniform('heightMapFactor'));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.envAtlas && this.cubeMap) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter('texture_envAtlas', this.envAtlas);\\n\\t\\t\\t\\t\\t\\tthis._setParameter('texture_cubeMap', this.cubeMap);\\n\\t\\t\\t\\t} else if (this.envAtlas) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter('texture_envAtlas', this.envAtlas);\\n\\t\\t\\t\\t} else if (this.cubeMap) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter('texture_cubeMap', this.cubeMap);\\n\\t\\t\\t\\t} else if (this.sphereMap) {\\n\\t\\t\\t\\t\\t\\tthis._setParameter('texture_sphereMap', this.sphereMap);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._setParameter('material_reflectivity', this.reflectivity);\\n\\t\\t\\t\\tthis._processParameters('_activeParams');\\n\\t\\t\\t\\tsuper.updateUniforms(device, scene);\\n\\t\\t}\\n\\t\\tupdateEnvUniforms(device, scene) {\\n\\t\\t\\t\\tconst hasLocalEnvOverride = this.envAtlas || this.cubeMap || this.sphereMap;\\n\\t\\t\\t\\tif (!hasLocalEnvOverride && this.useSkybox) {\\n\\t\\t\\t\\t\\t\\tif (scene.envAtlas && scene.skybox) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._setParameter('texture_envAtlas', scene.envAtlas);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._setParameter('texture_cubeMap', scene.skybox);\\n\\t\\t\\t\\t\\t\\t} else if (scene.envAtlas) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._setParameter('texture_envAtlas', scene.envAtlas);\\n\\t\\t\\t\\t\\t\\t} else if (scene.skybox) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._setParameter('texture_cubeMap', scene.skybox);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._processParameters('_activeLightingParams');\\n\\t\\t}\\n\\t\\tgetShaderVariant(params) {\\n\\t\\t\\t\\tconst { device, scene, pass, objDefs, sortedLights, cameraShaderParams } = params;\\n\\t\\t\\t\\tthis.updateEnvUniforms(device, scene);\\n\\t\\t\\t\\tconst shaderPassInfo = ShaderPass.get(device).getByIndex(pass);\\n\\t\\t\\t\\tconst minimalOptions = pass === SHADER_PICK || pass === SHADER_PREPASS || shaderPassInfo.isShadow;\\n\\t\\t\\t\\tlet options = minimalOptions ? standard.optionsContextMin : standard.optionsContext;\\n\\t\\t\\t\\toptions.defines = ShaderUtils.getCoreDefines(this, params);\\n\\t\\t\\t\\tif (minimalOptions) {\\n\\t\\t\\t\\t\\t\\tthis.shaderOptBuilder.updateMinRef(options, scene, this, objDefs, pass, sortedLights);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.shaderOptBuilder.updateRef(options, scene, cameraShaderParams, this, objDefs, pass, sortedLights);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this.useFog) options.defines.set('FOG', 'NONE');\\n\\t\\t\\t\\toptions.defines.set('TONEMAP', tonemapNames[options.litOptions.toneMap]);\\n\\t\\t\\t\\tif (this.onUpdateShader) {\\n\\t\\t\\t\\t\\t\\toptions = this.onUpdateShader(options);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst processingOptions = new ShaderProcessorOptions(params.viewUniformFormat, params.viewBindGroupFormat, params.vertexFormat);\\n\\t\\t\\t\\tconst library = getProgramLibrary(device);\\n\\t\\t\\t\\tlibrary.register('standard', standard);\\n\\t\\t\\t\\tconst shader = library.getProgram('standard', options, processingOptions, this.userId);\\n\\t\\t\\t\\tthis._dirtyShader = false;\\n\\t\\t\\t\\treturn shader;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tfor(const asset in this._assetReferences){\\n\\t\\t\\t\\t\\t\\tthis._assetReferences[asset]._unbind();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._assetReferences = null;\\n\\t\\t\\t\\tsuper.destroy();\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tsuper(), this.userAttributes = new Map();\\n\\t\\t\\t\\tthis._assetReferences = {};\\n\\t\\t\\t\\tthis._activeParams = new Set();\\n\\t\\t\\t\\tthis._activeLightingParams = new Set();\\n\\t\\t\\t\\tthis.shaderOptBuilder = new StandardMaterialOptionsBuilder();\\n\\t\\t\\t\\tthis.reset();\\n\\t\\t}\\n}\\nStandardMaterial.TEXTURE_PARAMETERS = standardMaterialTextureParameters;\\nStandardMaterial.CUBEMAP_PARAMETERS = standardMaterialCubemapParameters;\\nconst defineUniform = (name, getUniformFunc)=>{\\n\\t\\t_uniforms[name] = getUniformFunc;\\n};\\nconst definePropInternal = (name, constructorFunc, setterFunc, getterFunc)=>{\\n\\t\\tObject.defineProperty(StandardMaterial.prototype, name, {\\n\\t\\t\\t\\tget: getterFunc || function() {\\n\\t\\t\\t\\t\\t\\treturn this[`_${name}`];\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\tset: setterFunc\\n\\t\\t});\\n\\t\\t_props[name] = {\\n\\t\\t\\t\\tvalue: constructorFunc\\n\\t\\t};\\n};\\nconst defineValueProp = (prop)=>{\\n\\t\\tconst internalName = `_${prop.name}`;\\n\\t\\tconst dirtyShaderFunc = prop.dirtyShaderFunc || (()=>true);\\n\\t\\tconst setterFunc = function(value) {\\n\\t\\t\\t\\tconst oldValue = this[internalName];\\n\\t\\t\\t\\tif (oldValue !== value) {\\n\\t\\t\\t\\t\\t\\tthis._dirtyShader = this._dirtyShader || dirtyShaderFunc(oldValue, value);\\n\\t\\t\\t\\t\\t\\tthis[internalName] = value;\\n\\t\\t\\t\\t}\\n\\t\\t};\\n\\t\\tdefinePropInternal(prop.name, ()=>prop.defaultValue, setterFunc, prop.getterFunc);\\n};\\nconst defineAggProp = (prop)=>{\\n\\t\\tconst internalName = `_${prop.name}`;\\n\\t\\tconst dirtyShaderFunc = prop.dirtyShaderFunc || (()=>true);\\n\\t\\tconst setterFunc = function(value) {\\n\\t\\t\\t\\tconst oldValue = this[internalName];\\n\\t\\t\\t\\tif (!oldValue.equals(value)) {\\n\\t\\t\\t\\t\\t\\tthis._dirtyShader = this._dirtyShader || dirtyShaderFunc(oldValue, value);\\n\\t\\t\\t\\t\\t\\tthis[internalName] = oldValue.copy(value);\\n\\t\\t\\t\\t}\\n\\t\\t};\\n\\t\\tdefinePropInternal(prop.name, ()=>prop.defaultValue.clone(), setterFunc, prop.getterFunc);\\n};\\nconst defineProp = (prop)=>{\\n\\t\\treturn prop.defaultValue && prop.defaultValue.clone ? defineAggProp(prop) : defineValueProp(prop);\\n};\\nfunction _defineTex2D(name, channel = 'rgb', vertexColor = true, uv = 0) {\\n\\t\\t_matTex2D[name] = channel.length || -1;\\n\\t\\tdefineProp({\\n\\t\\t\\t\\tname: `${name}Map`,\\n\\t\\t\\t\\tdefaultValue: null,\\n\\t\\t\\t\\tdirtyShaderFunc: (oldValue, newValue)=>{\\n\\t\\t\\t\\t\\t\\treturn !!oldValue !== !!newValue || oldValue && (oldValue.type !== newValue.type || oldValue.format !== newValue.format);\\n\\t\\t\\t\\t}\\n\\t\\t});\\n\\t\\tdefineProp({\\n\\t\\t\\t\\tname: `${name}MapTiling`,\\n\\t\\t\\t\\tdefaultValue: new Vec2(1, 1)\\n\\t\\t});\\n\\t\\tdefineProp({\\n\\t\\t\\t\\tname: `${name}MapOffset`,\\n\\t\\t\\t\\tdefaultValue: new Vec2(0, 0)\\n\\t\\t});\\n\\t\\tdefineProp({\\n\\t\\t\\t\\tname: `${name}MapRotation`,\\n\\t\\t\\t\\tdefaultValue: 0\\n\\t\\t});\\n\\t\\tdefineProp({\\n\\t\\t\\t\\tname: `${name}MapUv`,\\n\\t\\t\\t\\tdefaultValue: uv\\n\\t\\t});\\n\\t\\tif (channel) {\\n\\t\\t\\t\\tdefineProp({\\n\\t\\t\\t\\t\\t\\tname: `${name}MapChannel`,\\n\\t\\t\\t\\t\\t\\tdefaultValue: channel\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (vertexColor) {\\n\\t\\t\\t\\t\\t\\tdefineProp({\\n\\t\\t\\t\\t\\t\\t\\t\\tname: `${name}VertexColor`,\\n\\t\\t\\t\\t\\t\\t\\t\\tdefaultValue: false\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tdefineProp({\\n\\t\\t\\t\\t\\t\\t\\t\\tname: `${name}VertexColorChannel`,\\n\\t\\t\\t\\t\\t\\t\\t\\tdefaultValue: channel\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst mapTiling = `${name}MapTiling`;\\n\\t\\tconst mapOffset = `${name}MapOffset`;\\n\\t\\tconst mapRotation = `${name}MapRotation`;\\n\\t\\tconst mapTransform = `${name}MapTransform`;\\n\\t\\tdefineUniform(mapTransform, (material, device, scene)=>{\\n\\t\\t\\t\\tconst tiling = material[mapTiling];\\n\\t\\t\\t\\tconst offset = material[mapOffset];\\n\\t\\t\\t\\tconst rotation = material[mapRotation];\\n\\t\\t\\t\\tif (tiling.x === 1 && tiling.y === 1 && offset.x === 0 && offset.y === 0 && rotation === 0) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst uniform = material._allocUniform(mapTransform, ()=>{\\n\\t\\t\\t\\t\\t\\treturn [\\n\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tname: `texture_${mapTransform}0`,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvalue: new Float32Array(3)\\n\\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\\t\\t\\tname: `texture_${mapTransform}1`,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvalue: new Float32Array(3)\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst cr = Math.cos(rotation * math.DEG_TO_RAD);\\n\\t\\t\\t\\tconst sr = Math.sin(rotation * math.DEG_TO_RAD);\\n\\t\\t\\t\\tconst uniform0 = uniform[0].value;\\n\\t\\t\\t\\tuniform0[0] = cr * tiling.x;\\n\\t\\t\\t\\tuniform0[1] = -sr * tiling.y;\\n\\t\\t\\t\\tuniform0[2] = offset.x;\\n\\t\\t\\t\\tconst uniform1 = uniform[1].value;\\n\\t\\t\\t\\tuniform1[0] = sr * tiling.x;\\n\\t\\t\\t\\tuniform1[1] = cr * tiling.y;\\n\\t\\t\\t\\tuniform1[2] = 1.0 - tiling.y - offset.y;\\n\\t\\t\\t\\treturn uniform;\\n\\t\\t});\\n}\\nfunction _defineColor(name, defaultValue) {\\n\\t\\tdefineProp({\\n\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\tdefaultValue: defaultValue,\\n\\t\\t\\t\\tgetterFunc: function() {\\n\\t\\t\\t\\t\\t\\tthis._dirtyShader = true;\\n\\t\\t\\t\\t\\t\\treturn this[`_${name}`];\\n\\t\\t\\t\\t}\\n\\t\\t});\\n\\t\\tdefineUniform(name, (material, device, scene)=>{\\n\\t\\t\\t\\tconst uniform = material._allocUniform(name, ()=>new Float32Array(3));\\n\\t\\t\\t\\tconst color = material[name];\\n\\t\\t\\t\\t_tempColor.linear(color);\\n\\t\\t\\t\\tuniform[0] = _tempColor.r;\\n\\t\\t\\t\\tuniform[1] = _tempColor.g;\\n\\t\\t\\t\\tuniform[2] = _tempColor.b;\\n\\t\\t\\t\\treturn uniform;\\n\\t\\t});\\n}\\nfunction _defineFloat(name, defaultValue, getUniformFunc) {\\n\\t\\tdefineProp({\\n\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\tdefaultValue: defaultValue,\\n\\t\\t\\t\\tdirtyShaderFunc: (oldValue, newValue)=>{\\n\\t\\t\\t\\t\\t\\treturn (oldValue === 0 || oldValue === 1) !== (newValue === 0 || newValue === 1);\\n\\t\\t\\t\\t}\\n\\t\\t});\\n\\t\\tdefineUniform(name, getUniformFunc);\\n}\\nfunction _defineObject(name, getUniformFunc) {\\n\\t\\tdefineProp({\\n\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\tdefaultValue: null,\\n\\t\\t\\t\\tdirtyShaderFunc: (oldValue, newValue)=>{\\n\\t\\t\\t\\t\\t\\treturn !!oldValue === !!newValue;\\n\\t\\t\\t\\t}\\n\\t\\t});\\n\\t\\tdefineUniform(name, getUniformFunc);\\n}\\nfunction _defineFlag(name, defaultValue) {\\n\\t\\tdefineProp({\\n\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\tdefaultValue: defaultValue\\n\\t\\t});\\n}\\nfunction _defineMaterialProps() {\\n\\t\\t_defineColor('ambient', new Color(1, 1, 1));\\n\\t\\t_defineColor('diffuse', new Color(1, 1, 1));\\n\\t\\t_defineColor('specular', new Color(0, 0, 0));\\n\\t\\t_defineColor('emissive', new Color(0, 0, 0));\\n\\t\\t_defineColor('sheen', new Color(1, 1, 1));\\n\\t\\t_defineColor('attenuation', new Color(1, 1, 1));\\n\\t\\t_defineFloat('emissiveIntensity', 1);\\n\\t\\t_defineFloat('specularityFactor', 1);\\n\\t\\t_defineFloat('sheenGloss', 0.0);\\n\\t\\t_defineFloat('gloss', 0.25);\\n\\t\\t_defineFloat('aoIntensity', 1);\\n\\t\\t_defineFloat('heightMapFactor', 1, (material, device, scene)=>{\\n\\t\\t\\t\\treturn material.heightMapFactor * 0.025;\\n\\t\\t});\\n\\t\\t_defineFloat('opacity', 1);\\n\\t\\t_defineFloat('alphaFade', 1);\\n\\t\\t_defineFloat('alphaTest', 0);\\n\\t\\t_defineFloat('bumpiness', 1);\\n\\t\\t_defineFloat('normalDetailMapBumpiness', 1);\\n\\t\\t_defineFloat('reflectivity', 1);\\n\\t\\t_defineFloat('occludeSpecularIntensity', 1);\\n\\t\\t_defineFloat('refraction', 0);\\n\\t\\t_defineFloat('refractionIndex', 1.0 / 1.5, (material, device, scene)=>{\\n\\t\\t\\t\\treturn Math.max(0.001, material.refractionIndex);\\n\\t\\t});\\n\\t\\t_defineFloat('dispersion', 0);\\n\\t\\t_defineFloat('thickness', 0);\\n\\t\\t_defineFloat('attenuationDistance', 0);\\n\\t\\t_defineFloat('metalness', 1);\\n\\t\\t_defineFloat('anisotropyIntensity', 0);\\n\\t\\t_defineFloat('anisotropyRotation', 0);\\n\\t\\t_defineFloat('clearCoat', 0);\\n\\t\\t_defineFloat('clearCoatGloss', 1);\\n\\t\\t_defineFloat('clearCoatBumpiness', 1);\\n\\t\\t_defineFloat('aoUvSet', 0, null);\\n\\t\\t_defineFloat('iridescence', 0);\\n\\t\\t_defineFloat('iridescenceRefractionIndex', 1.0 / 1.5);\\n\\t\\t_defineFloat('iridescenceThicknessMin', 0);\\n\\t\\t_defineFloat('iridescenceThicknessMax', 0);\\n\\t\\t_defineObject('ambientSH');\\n\\t\\t_defineObject('cubeMapProjectionBox', (material, device, scene)=>{\\n\\t\\t\\t\\tconst uniform = material._allocUniform('cubeMapProjectionBox', ()=>{\\n\\t\\t\\t\\t\\t\\treturn [\\n\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tname: 'envBoxMin',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvalue: new Float32Array(3)\\n\\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\\t\\t\\tname: 'envBoxMax',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvalue: new Float32Array(3)\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst bboxMin = material.cubeMapProjectionBox.getMin();\\n\\t\\t\\t\\tconst minUniform = uniform[0].value;\\n\\t\\t\\t\\tminUniform[0] = bboxMin.x;\\n\\t\\t\\t\\tminUniform[1] = bboxMin.y;\\n\\t\\t\\t\\tminUniform[2] = bboxMin.z;\\n\\t\\t\\t\\tconst bboxMax = material.cubeMapProjectionBox.getMax();\\n\\t\\t\\t\\tconst maxUniform = uniform[1].value;\\n\\t\\t\\t\\tmaxUniform[0] = bboxMax.x;\\n\\t\\t\\t\\tmaxUniform[1] = bboxMax.y;\\n\\t\\t\\t\\tmaxUniform[2] = bboxMax.z;\\n\\t\\t\\t\\treturn uniform;\\n\\t\\t});\\n\\t\\t_defineFlag('specularTint', false);\\n\\t\\t_defineFlag('specularityFactorTint', false);\\n\\t\\t_defineFlag('useMetalness', false);\\n\\t\\t_defineFlag('useMetalnessSpecularColor', false);\\n\\t\\t_defineFlag('useSheen', false);\\n\\t\\t_defineFlag('enableGGXSpecular', false);\\n\\t\\t_defineFlag('occludeDirect', false);\\n\\t\\t_defineFlag('opacityFadesSpecular', true);\\n\\t\\t_defineFlag('occludeSpecular', SPECOCC_AO);\\n\\t\\t_defineFlag('fresnelModel', FRESNEL_SCHLICK);\\n\\t\\t_defineFlag('useDynamicRefraction', false);\\n\\t\\t_defineFlag('cubeMapProjection', CUBEPROJ_NONE);\\n\\t\\t_defineFlag('useFog', true);\\n\\t\\t_defineFlag('useLighting', true);\\n\\t\\t_defineFlag('useTonemap', true);\\n\\t\\t_defineFlag('useSkybox', true);\\n\\t\\t_defineFlag('forceUv1', false);\\n\\t\\t_defineFlag('pixelSnap', false);\\n\\t\\t_defineFlag('twoSidedLighting', false);\\n\\t\\t_defineFlag('nineSlicedMode', undefined);\\n\\t\\t_defineFlag('msdfTextAttribute', false);\\n\\t\\t_defineFlag('useIridescence', false);\\n\\t\\t_defineFlag('glossInvert', false);\\n\\t\\t_defineFlag('sheenGlossInvert', false);\\n\\t\\t_defineFlag('clearCoatGlossInvert', false);\\n\\t\\t_defineFlag('opacityDither', DITHER_NONE);\\n\\t\\t_defineFlag('opacityShadowDither', DITHER_NONE);\\n\\t\\t_defineFlag('shadowCatcher', false);\\n\\t\\t_defineFlag('vertexColorGamma', false);\\n\\t\\t_defineTex2D('diffuse');\\n\\t\\t_defineTex2D('specular');\\n\\t\\t_defineTex2D('emissive');\\n\\t\\t_defineTex2D('thickness', 'g');\\n\\t\\t_defineTex2D('specularityFactor', 'g');\\n\\t\\t_defineTex2D('normal', '');\\n\\t\\t_defineTex2D('metalness', 'g');\\n\\t\\t_defineTex2D('gloss', 'g');\\n\\t\\t_defineTex2D('opacity', 'a');\\n\\t\\t_defineTex2D('refraction', 'g');\\n\\t\\t_defineTex2D('height', 'g', false);\\n\\t\\t_defineTex2D('ao', 'g');\\n\\t\\t_defineTex2D('light', 'rgb', true, 1);\\n\\t\\t_defineTex2D('msdf', '');\\n\\t\\t_defineTex2D('diffuseDetail', 'rgb', false);\\n\\t\\t_defineTex2D('normalDetail', '');\\n\\t\\t_defineTex2D('aoDetail', 'g', false);\\n\\t\\t_defineTex2D('clearCoat', 'g');\\n\\t\\t_defineTex2D('clearCoatGloss', 'g');\\n\\t\\t_defineTex2D('clearCoatNormal', '');\\n\\t\\t_defineTex2D('sheen', 'rgb');\\n\\t\\t_defineTex2D('sheenGloss', 'g');\\n\\t\\t_defineTex2D('iridescence', 'g');\\n\\t\\t_defineTex2D('iridescenceThickness', 'g');\\n\\t\\t_defineTex2D('anisotropy', '');\\n\\t\\t_defineFlag('diffuseDetailMode', DETAILMODE_MUL);\\n\\t\\t_defineFlag('aoDetailMode', DETAILMODE_MUL);\\n\\t\\t_defineObject('cubeMap');\\n\\t\\t_defineObject('sphereMap');\\n\\t\\t_defineObject('envAtlas');\\n\\t\\tconst getterFunc = function() {\\n\\t\\t\\t\\treturn this._prefilteredCubemaps;\\n\\t\\t};\\n\\t\\tconst setterFunc = function(value) {\\n\\t\\t\\t\\tconst cubemaps = this._prefilteredCubemaps;\\n\\t\\t\\t\\tvalue = value || [];\\n\\t\\t\\t\\tlet changed = false;\\n\\t\\t\\t\\tlet complete = true;\\n\\t\\t\\t\\tfor(let i = 0; i < 6; ++i){\\n\\t\\t\\t\\t\\t\\tconst v = value[i] || null;\\n\\t\\t\\t\\t\\t\\tif (cubemaps[i] !== v) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcubemaps[i] = v;\\n\\t\\t\\t\\t\\t\\t\\t\\tchanged = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcomplete = complete && !!cubemaps[i];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (changed) {\\n\\t\\t\\t\\t\\t\\tif (complete) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.envAtlas = EnvLighting.generatePrefilteredAtlas(cubemaps, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttarget: this.envAtlas\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.envAtlas) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.envAtlas.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.envAtlas = null;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._dirtyShader = true;\\n\\t\\t\\t\\t}\\n\\t\\t};\\n\\t\\tconst empty = [\\n\\t\\t\\t\\tnull,\\n\\t\\t\\t\\tnull,\\n\\t\\t\\t\\tnull,\\n\\t\\t\\t\\tnull,\\n\\t\\t\\t\\tnull,\\n\\t\\t\\t\\tnull\\n\\t\\t];\\n\\t\\tdefinePropInternal('prefilteredCubemaps', ()=>empty.slice(), setterFunc, getterFunc);\\n}\\n_defineMaterialProps();\\n\\nconst primitiveUv1Padding = 8.0 / 64;\\nconst primitiveUv1PaddingScale = 1.0 - primitiveUv1Padding * 2;\\nclass ConeBaseGeometry extends Geometry {\\n\\t\\tconstructor(baseRadius, peakRadius, height, heightSegments, capSegments, roundedCaps){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tconst pos = new Vec3();\\n\\t\\t\\t\\tconst bottomToTop = new Vec3();\\n\\t\\t\\t\\tconst norm = new Vec3();\\n\\t\\t\\t\\tconst top = new Vec3();\\n\\t\\t\\t\\tconst bottom = new Vec3();\\n\\t\\t\\t\\tconst tangent = new Vec3();\\n\\t\\t\\t\\tconst positions = [];\\n\\t\\t\\t\\tconst normals = [];\\n\\t\\t\\t\\tconst uvs = [];\\n\\t\\t\\t\\tconst uvs1 = [];\\n\\t\\t\\t\\tconst indices = [];\\n\\t\\t\\t\\tlet offset;\\n\\t\\t\\t\\tif (height > 0) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i <= heightSegments; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j <= capSegments; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst theta = j / capSegments * 2 * Math.PI - Math.PI;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst sinTheta = Math.sin(theta);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst cosTheta = Math.cos(theta);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbottom.set(sinTheta * baseRadius, -height / 2, cosTheta * baseRadius);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttop.set(sinTheta * peakRadius, height / 2, cosTheta * peakRadius);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpos.lerp(bottom, top, i / heightSegments);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbottomToTop.sub2(top, bottom).normalize();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttangent.set(cosTheta, 0, -sinTheta);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnorm.cross(tangent, bottomToTop).normalize();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpositions.push(pos.x, pos.y, pos.z);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnormals.push(norm.x, norm.y, norm.z);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet u = j / capSegments;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet v = i / heightSegments;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst _v = v;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tv = u;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu = _v;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu = u * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tv = v * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu /= 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuvs1.push(u, 1 - v);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (i < heightSegments && j < capSegments) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst first = i * (capSegments + 1) + j;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst second = i * (capSegments + 1) + (j + 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst third = (i + 1) * (capSegments + 1) + j;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst fourth = (i + 1) * (capSegments + 1) + (j + 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices.push(first, second, third);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices.push(second, fourth, third);\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (roundedCaps) {\\n\\t\\t\\t\\t\\t\\tconst latitudeBands = Math.floor(capSegments / 2);\\n\\t\\t\\t\\t\\t\\tconst longitudeBands = capSegments;\\n\\t\\t\\t\\t\\t\\tconst capOffset = height / 2;\\n\\t\\t\\t\\t\\t\\tfor(let lat = 0; lat <= latitudeBands; lat++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst theta = lat * Math.PI * 0.5 / latitudeBands;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst sinTheta = Math.sin(theta);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst cosTheta = Math.cos(theta);\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let lon = 0; lon <= longitudeBands; lon++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst phi = lon * 2 * Math.PI / longitudeBands - Math.PI / 2;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst sinPhi = Math.sin(phi);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst cosPhi = Math.cos(phi);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst x = cosPhi * sinTheta;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst y = cosTheta;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst z = sinPhi * sinTheta;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet u = 1 - lon / longitudeBands;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet v = 1 - lat / latitudeBands;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpositions.push(x * peakRadius, y * peakRadius + capOffset, z * peakRadius);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnormals.push(x, y, z);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu = u * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tv = v * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu /= 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tv /= 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu += 1.0 / 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuvs1.push(u, 1 - v);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\toffset = (heightSegments + 1) * (capSegments + 1);\\n\\t\\t\\t\\t\\t\\tfor(let lat = 0; lat < latitudeBands; ++lat){\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let lon = 0; lon < longitudeBands; ++lon){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst first = lat * (longitudeBands + 1) + lon;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst second = first + longitudeBands + 1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices.push(offset + first + 1, offset + second, offset + first);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices.push(offset + first + 1, offset + second + 1, offset + second);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor(let lat = 0; lat <= latitudeBands; lat++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst theta = Math.PI * 0.5 + lat * Math.PI * 0.5 / latitudeBands;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst sinTheta = Math.sin(theta);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst cosTheta = Math.cos(theta);\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let lon = 0; lon <= longitudeBands; lon++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst phi = lon * 2 * Math.PI / longitudeBands - Math.PI / 2;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst sinPhi = Math.sin(phi);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst cosPhi = Math.cos(phi);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst x = cosPhi * sinTheta;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst y = cosTheta;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst z = sinPhi * sinTheta;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet u = 1 - lon / longitudeBands;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet v = 1 - lat / latitudeBands;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpositions.push(x * peakRadius, y * peakRadius - capOffset, z * peakRadius);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnormals.push(x, y, z);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu = u * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tv = v * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu /= 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tv /= 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu += 2.0 / 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuvs1.push(u, 1 - v);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\toffset = (heightSegments + 1) * (capSegments + 1) + (longitudeBands + 1) * (latitudeBands + 1);\\n\\t\\t\\t\\t\\t\\tfor(let lat = 0; lat < latitudeBands; ++lat){\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let lon = 0; lon < longitudeBands; ++lon){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst first = lat * (longitudeBands + 1) + lon;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst second = first + longitudeBands + 1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices.push(offset + first + 1, offset + second, offset + first);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices.push(offset + first + 1, offset + second + 1, offset + second);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\toffset = (heightSegments + 1) * (capSegments + 1);\\n\\t\\t\\t\\t\\t\\tif (baseRadius > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < capSegments; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst theta = i / capSegments * 2 * Math.PI;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst x = Math.sin(theta);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst y = -height / 2;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst z = Math.cos(theta);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet u = 1 - (x + 1) / 2;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet v = (z + 1) / 2;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpositions.push(x * baseRadius, y, z * baseRadius);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnormals.push(0, -1, 0);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu = u * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tv = v * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu /= 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tv /= 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu += 1 / 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuvs1.push(u, 1 - v);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (i > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices.push(offset, offset + i, offset + i - 1);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\toffset += capSegments;\\n\\t\\t\\t\\t\\t\\tif (peakRadius > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < capSegments; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst theta = i / capSegments * 2 * Math.PI;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst x = Math.sin(theta);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst y = height / 2;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst z = Math.cos(theta);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet u = 1 - (x + 1) / 2;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet v = (z + 1) / 2;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpositions.push(x * peakRadius, y, z * peakRadius);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnormals.push(0, 1, 0);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu = u * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tv = v * primitiveUv1PaddingScale + primitiveUv1Padding;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu /= 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tv /= 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tu += 2 / 3;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuvs1.push(u, 1 - v);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (i > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices.push(offset, offset + i - 1, offset + i);\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.positions = positions;\\n\\t\\t\\t\\tthis.normals = normals;\\n\\t\\t\\t\\tthis.uvs = uvs;\\n\\t\\t\\t\\tthis.uvs1 = uvs1;\\n\\t\\t\\t\\tthis.indices = indices;\\n\\t\\t}\\n}\\n\\nclass CapsuleGeometry extends ConeBaseGeometry {\\n\\t\\tconstructor(opts = {}){\\n\\t\\t\\t\\tconst radius = opts.radius ?? 0.3;\\n\\t\\t\\t\\tconst height = opts.height ?? 1;\\n\\t\\t\\t\\tconst heightSegments = opts.heightSegments ?? 1;\\n\\t\\t\\t\\tconst sides = opts.sides ?? 20;\\n\\t\\t\\t\\tsuper(radius, radius, height - 2 * radius, heightSegments, sides, true);\\n\\t\\t\\t\\tif (opts.calculateTangents) {\\n\\t\\t\\t\\t\\t\\tthis.tangents = calculateTangents(this.positions, this.normals, this.uvs, this.indices);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass ConeGeometry extends ConeBaseGeometry {\\n\\t\\tconstructor(opts = {}){\\n\\t\\t\\t\\tconst baseRadius = opts.baseRadius ?? 0.5;\\n\\t\\t\\t\\tconst peakRadius = opts.peakRadius ?? 0;\\n\\t\\t\\t\\tconst height = opts.height ?? 1;\\n\\t\\t\\t\\tconst heightSegments = opts.heightSegments ?? 5;\\n\\t\\t\\t\\tconst capSegments = opts.capSegments ?? 18;\\n\\t\\t\\t\\tsuper(baseRadius, peakRadius, height, heightSegments, capSegments, false);\\n\\t\\t\\t\\tif (opts.calculateTangents) {\\n\\t\\t\\t\\t\\t\\tthis.tangents = calculateTangents(this.positions, this.normals, this.uvs, this.indices);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass CylinderGeometry extends ConeBaseGeometry {\\n\\t\\tconstructor(opts = {}){\\n\\t\\t\\t\\tconst radius = opts.radius ?? 0.5;\\n\\t\\t\\t\\tconst height = opts.height ?? 1;\\n\\t\\t\\t\\tconst heightSegments = opts.heightSegments ?? 5;\\n\\t\\t\\t\\tconst capSegments = opts.capSegments ?? 20;\\n\\t\\t\\t\\tsuper(radius, radius, height, heightSegments, capSegments, false);\\n\\t\\t\\t\\tif (opts.calculateTangents) {\\n\\t\\t\\t\\t\\t\\tthis.tangents = calculateTangents(this.positions, this.normals, this.uvs, this.indices);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass PlaneGeometry extends Geometry {\\n\\t\\tconstructor(opts = {}){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tconst he = opts.halfExtents ?? new Vec2(0.5, 0.5);\\n\\t\\t\\t\\tconst ws = opts.widthSegments ?? 5;\\n\\t\\t\\t\\tconst ls = opts.lengthSegments ?? 5;\\n\\t\\t\\t\\tconst positions = [];\\n\\t\\t\\t\\tconst normals = [];\\n\\t\\t\\t\\tconst uvs = [];\\n\\t\\t\\t\\tconst indices = [];\\n\\t\\t\\t\\tlet vcounter = 0;\\n\\t\\t\\t\\tfor(let i = 0; i <= ws; i++){\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j <= ls; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst x = -he.x + 2 * he.x * i / ws;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst y = 0.0;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst z = -(-he.y + 2 * he.y * j / ls);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst u = i / ws;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst v = j / ls;\\n\\t\\t\\t\\t\\t\\t\\t\\tpositions.push(x, y, z);\\n\\t\\t\\t\\t\\t\\t\\t\\tnormals.push(0, 1, 0);\\n\\t\\t\\t\\t\\t\\t\\t\\tuvs.push(u, 1 - v);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (i < ws && j < ls) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices.push(vcounter + ls + 1, vcounter + 1, vcounter);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices.push(vcounter + ls + 1, vcounter + ls + 2, vcounter + 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tvcounter++;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.positions = positions;\\n\\t\\t\\t\\tthis.normals = normals;\\n\\t\\t\\t\\tthis.uvs = uvs;\\n\\t\\t\\t\\tthis.uvs1 = uvs;\\n\\t\\t\\t\\tthis.indices = indices;\\n\\t\\t\\t\\tif (opts.calculateTangents) {\\n\\t\\t\\t\\t\\t\\tthis.tangents = calculateTangents(positions, normals, uvs, indices);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass TorusGeometry extends Geometry {\\n\\t\\tconstructor(opts = {}){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tconst rc = opts.tubeRadius ?? 0.2;\\n\\t\\t\\t\\tconst rt = opts.ringRadius ?? 0.3;\\n\\t\\t\\t\\tconst sectorAngle = (opts.sectorAngle ?? 360) * math.DEG_TO_RAD;\\n\\t\\t\\t\\tconst segments = opts.segments ?? 30;\\n\\t\\t\\t\\tconst sides = opts.sides ?? 20;\\n\\t\\t\\t\\tconst positions = [];\\n\\t\\t\\t\\tconst normals = [];\\n\\t\\t\\t\\tconst uvs = [];\\n\\t\\t\\t\\tconst indices = [];\\n\\t\\t\\t\\tfor(let i = 0; i <= sides; i++){\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j <= segments; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst x = Math.cos(sectorAngle * j / segments) * (rt + rc * Math.cos(2 * Math.PI * i / sides));\\n\\t\\t\\t\\t\\t\\t\\t\\tconst y = Math.sin(2 * Math.PI * i / sides) * rc;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst z = Math.sin(sectorAngle * j / segments) * (rt + rc * Math.cos(2 * Math.PI * i / sides));\\n\\t\\t\\t\\t\\t\\t\\t\\tconst nx = Math.cos(sectorAngle * j / segments) * Math.cos(2 * Math.PI * i / sides);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst ny = Math.sin(2 * Math.PI * i / sides);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst nz = Math.sin(sectorAngle * j / segments) * Math.cos(2 * Math.PI * i / sides);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst u = i / sides;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst v = 1 - j / segments;\\n\\t\\t\\t\\t\\t\\t\\t\\tpositions.push(x, y, z);\\n\\t\\t\\t\\t\\t\\t\\t\\tnormals.push(nx, ny, nz);\\n\\t\\t\\t\\t\\t\\t\\t\\tuvs.push(u, 1.0 - v);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (i < sides && j < segments) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst first = i * (segments + 1) + j;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst second = (i + 1) * (segments + 1) + j;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst third = i * (segments + 1) + (j + 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst fourth = (i + 1) * (segments + 1) + (j + 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices.push(first, second, third);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices.push(second, fourth, third);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.positions = positions;\\n\\t\\t\\t\\tthis.normals = normals;\\n\\t\\t\\t\\tthis.uvs = uvs;\\n\\t\\t\\t\\tthis.uvs1 = uvs;\\n\\t\\t\\t\\tthis.indices = indices;\\n\\t\\t\\t\\tif (opts.calculateTangents) {\\n\\t\\t\\t\\t\\t\\tthis.tangents = calculateTangents(positions, normals, uvs, indices);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass ProgramLibrary {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.clearCache();\\n\\t\\t}\\n\\t\\tregister(name, generator) {\\n\\t\\t\\t\\tif (!this._generators.has(name)) {\\n\\t\\t\\t\\t\\t\\tthis._generators.set(name, generator);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tunregister(name) {\\n\\t\\t\\t\\tif (this._generators.has(name)) {\\n\\t\\t\\t\\t\\t\\tthis._generators.delete(name);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tisRegistered(name) {\\n\\t\\t\\t\\treturn this._generators.has(name);\\n\\t\\t}\\n\\t\\tgenerateShaderDefinition(generator, name, key, options) {\\n\\t\\t\\t\\tlet def = this.definitionsCache.get(key);\\n\\t\\t\\t\\tif (!def) {\\n\\t\\t\\t\\t\\t\\tlet lights;\\n\\t\\t\\t\\t\\t\\tif (options.litOptions?.lights) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlights = options.litOptions.lights;\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.litOptions.lights = lights.map((l)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst lcopy = l.clone ? l.clone() : l;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlcopy.key = l.key;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn lcopy;\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.storeNewProgram(name, options);\\n\\t\\t\\t\\t\\t\\tif (options.litOptions?.lights) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.litOptions.lights = lights;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this._precached) ;\\n\\t\\t\\t\\t\\t\\tconst device = this._device;\\n\\t\\t\\t\\t\\t\\tdef = generator.createShaderDefinition(device, options);\\n\\t\\t\\t\\t\\t\\tdef.name = def.name ?? (options.pass ? `${name}-pass:${options.pass}` : name);\\n\\t\\t\\t\\t\\t\\tthis.definitionsCache.set(key, def);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn def;\\n\\t\\t}\\n\\t\\tgetCachedShader(key) {\\n\\t\\t\\t\\treturn this.processedCache.get(key);\\n\\t\\t}\\n\\t\\tsetCachedShader(key, shader) {\\n\\t\\t\\t\\tthis.processedCache.set(key, shader);\\n\\t\\t}\\n\\t\\tgetProgram(name, options, processingOptions, userMaterialId) {\\n\\t\\t\\t\\tconst generator = this._generators.get(name);\\n\\t\\t\\t\\tif (!generator) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst generationKeyString = generator.generateKey(options);\\n\\t\\t\\t\\tconst generationKey = hashCode(generationKeyString);\\n\\t\\t\\t\\tconst processingKeyString = processingOptions.generateKey(this._device);\\n\\t\\t\\t\\tconst processingKey = hashCode(processingKeyString);\\n\\t\\t\\t\\tconst totalKey = `${generationKey}#${processingKey}`;\\n\\t\\t\\t\\tlet processedShader = this.getCachedShader(totalKey);\\n\\t\\t\\t\\tif (!processedShader) {\\n\\t\\t\\t\\t\\t\\tconst generatedShaderDef = this.generateShaderDefinition(generator, name, generationKey, options);\\n\\t\\t\\t\\t\\t\\tlet passName = '';\\n\\t\\t\\t\\t\\t\\tlet shaderPassInfo;\\n\\t\\t\\t\\t\\t\\tif (options.pass !== undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\tshaderPassInfo = ShaderPass.get(this._device).getByIndex(options.pass);\\n\\t\\t\\t\\t\\t\\t\\t\\tpassName = `-${shaderPassInfo.name}`;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._device.fire('shader:generate', {\\n\\t\\t\\t\\t\\t\\t\\t\\tuserMaterialId,\\n\\t\\t\\t\\t\\t\\t\\t\\tshaderPassInfo,\\n\\t\\t\\t\\t\\t\\t\\t\\tdefinition: generatedShaderDef\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tconst shaderDefinition = {\\n\\t\\t\\t\\t\\t\\t\\t\\tname: `${generatedShaderDef.name}${passName}-proc`,\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes: generatedShaderDef.attributes,\\n\\t\\t\\t\\t\\t\\t\\t\\tvshader: generatedShaderDef.vshader,\\n\\t\\t\\t\\t\\t\\t\\t\\tvincludes: generatedShaderDef.vincludes,\\n\\t\\t\\t\\t\\t\\t\\t\\tfincludes: generatedShaderDef.fincludes,\\n\\t\\t\\t\\t\\t\\t\\t\\tfshader: generatedShaderDef.fshader,\\n\\t\\t\\t\\t\\t\\t\\t\\tprocessingOptions: processingOptions,\\n\\t\\t\\t\\t\\t\\t\\t\\tshaderLanguage: generatedShaderDef.shaderLanguage,\\n\\t\\t\\t\\t\\t\\t\\t\\tmeshUniformBufferFormat: generatedShaderDef.meshUniformBufferFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tmeshBindGroupFormat: generatedShaderDef.meshBindGroupFormat\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tprocessedShader = new Shader(this._device, shaderDefinition);\\n\\t\\t\\t\\t\\t\\tthis.setCachedShader(totalKey, processedShader);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn processedShader;\\n\\t\\t}\\n\\t\\tstoreNewProgram(name, options) {\\n\\t\\t\\t\\tlet opt = {};\\n\\t\\t\\t\\tif (name === 'standard') {\\n\\t\\t\\t\\t\\t\\tconst defaultMat = this._getDefaultStdMatOptions(options.pass);\\n\\t\\t\\t\\t\\t\\tfor(const p in options){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (options.hasOwnProperty(p) && defaultMat[p] !== options[p] || p === 'pass') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\topt[p] = options[p];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor(const p in options.litOptions){\\n\\t\\t\\t\\t\\t\\t\\t\\topt[p] = options.litOptions[p];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\topt = options;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._programsCollection.push(JSON.stringify({\\n\\t\\t\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\t\\t\\toptions: opt\\n\\t\\t\\t\\t}));\\n\\t\\t}\\n\\t\\tdumpPrograms() {\\n\\t\\t\\t\\tlet text = 'let device = pc.app ? pc.app.graphicsDevice : pc.Application.getApplication().graphicsDevice;\\\\n';\\n\\t\\t\\t\\ttext += 'let shaders = [';\\n\\t\\t\\t\\tif (this._programsCollection[0]) {\\n\\t\\t\\t\\t\\t\\ttext += `\\\\n\\\\t${this._programsCollection[0]}`;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 1; i < this._programsCollection.length; ++i){\\n\\t\\t\\t\\t\\t\\ttext += `,\\\\n\\\\t${this._programsCollection[i]}`;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttext += '\\\\n];\\\\n';\\n\\t\\t\\t\\ttext += 'pc.getProgramLibrary(device).precompile(shaders);\\\\n';\\n\\t\\t\\t\\ttext += `if (pc.version != \\\\\\\"${version$1}\\\\\\\" || pc.revision != \\\\\\\"${revision}\\\\\\\")\\\\n`;\\n\\t\\t\\t\\ttext += '\\\\tconsole.warn(\\\\\\\"precompile-shaders.js: engine version mismatch, rebuild shaders lib with current engine\\\\\\\");';\\n\\t\\t\\t\\tconst element = document.createElement('a');\\n\\t\\t\\t\\telement.setAttribute('href', `data:text/plain;charset=utf-8,${encodeURIComponent(text)}`);\\n\\t\\t\\t\\telement.setAttribute('download', 'precompile-shaders.js');\\n\\t\\t\\t\\telement.style.display = 'none';\\n\\t\\t\\t\\tdocument.body.appendChild(element);\\n\\t\\t\\t\\telement.click();\\n\\t\\t\\t\\tdocument.body.removeChild(element);\\n\\t\\t}\\n\\t\\tclearCache() {\\n\\t\\t\\t\\tthis._isClearingCache = true;\\n\\t\\t\\t\\tthis.processedCache.forEach((shader)=>{\\n\\t\\t\\t\\t\\t\\tshader.destroy();\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.processedCache.clear();\\n\\t\\t\\t\\tthis._isClearingCache = false;\\n\\t\\t}\\n\\t\\tremoveFromCache(shader) {\\n\\t\\t\\t\\tif (this._isClearingCache) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.processedCache.forEach((cachedShader, key)=>{\\n\\t\\t\\t\\t\\t\\tif (shader === cachedShader) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.processedCache.delete(key);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\t_getDefaultStdMatOptions(pass) {\\n\\t\\t\\t\\tconst shaderPassInfo = ShaderPass.get(this._device).getByIndex(pass);\\n\\t\\t\\t\\treturn pass === SHADER_PICK || pass === SHADER_PREPASS || shaderPassInfo.isShadow ? this._defaultStdMatOptionMin : this._defaultStdMatOption;\\n\\t\\t}\\n\\t\\tprecompile(cache) {\\n\\t\\t\\t\\tif (cache) {\\n\\t\\t\\t\\t\\t\\tconst shaders = new Array(cache.length);\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < cache.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (cache[i].name === 'standard') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst opt = cache[i].options;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst defaultMat = this._getDefaultStdMatOptions(opt.pass);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(const p in defaultMat){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (defaultMat.hasOwnProperty(p) && opt[p] === undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\topt[p] = defaultMat[p];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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\\tshaders[i] = this.getProgram(cache[i].name, cache[i].options);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._precached = true;\\n\\t\\t}\\n\\t\\tconstructor(device, standardMaterial){\\n\\t\\t\\t\\tthis.processedCache = new Map();\\n\\t\\t\\t\\tthis.definitionsCache = new Map();\\n\\t\\t\\t\\tthis._generators = new Map();\\n\\t\\t\\t\\tthis._device = device;\\n\\t\\t\\t\\tthis._isClearingCache = false;\\n\\t\\t\\t\\tthis._precached = false;\\n\\t\\t\\t\\tthis._programsCollection = [];\\n\\t\\t\\t\\tthis._defaultStdMatOption = new StandardMaterialOptions();\\n\\t\\t\\t\\tthis._defaultStdMatOptionMin = new StandardMaterialOptions();\\n\\t\\t\\t\\tconst defaultCameraShaderParams = new CameraShaderParams();\\n\\t\\t\\t\\tstandardMaterial.shaderOptBuilder.updateRef(this._defaultStdMatOption, {}, defaultCameraShaderParams, standardMaterial, null, [], SHADER_FORWARD, null);\\n\\t\\t\\t\\tstandardMaterial.shaderOptBuilder.updateMinRef(this._defaultStdMatOptionMin, {}, standardMaterial, null, SHADER_SHADOW, null);\\n\\t\\t\\t\\tdevice.on('destroy:shader', (shader)=>{\\n\\t\\t\\t\\t\\t\\tthis.removeFromCache(shader);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n}\\n\\nclass UploadStream {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._deviceLostEvent?.off();\\n\\t\\t\\t\\tthis._deviceLostEvent = null;\\n\\t\\t\\t\\tthis.impl?.destroy();\\n\\t\\t\\t\\tthis.impl = null;\\n\\t\\t}\\n\\t\\tupload(data, target, offset = 0, size = data.length) {\\n\\t\\t\\t\\tthis.impl?.upload(data, target, offset, size);\\n\\t\\t}\\n\\t\\t_onDeviceLost() {\\n\\t\\t\\t\\tthis.impl?._onDeviceLost?.();\\n\\t\\t}\\n\\t\\tconstructor(device, useSingleBuffer = false){\\n\\t\\t\\t\\tthis._deviceLostEvent = null;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.useSingleBuffer = useSingleBuffer;\\n\\t\\t\\t\\tthis.impl = device.createUploadStreamImpl(this);\\n\\t\\t\\t\\tthis._deviceLostEvent = this.device.on('devicelost', this._onDeviceLost, this);\\n\\t\\t}\\n}\\n\\nvar glslGsplatCopyToWorkBufferPS = `\\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 \\\"gsplatModifyVS\\\"\\nuniform int uStartLine;\\nuniform int uViewportWidth;\\n#ifdef GSPLAT_LOD\\n\\tuniform usampler2D uIntervalsTexture;\\n#endif\\nuniform vec3 uColorMultiply;\\nuniform int uActiveSplats;\\nuniform vec3 model_scale;\\nuniform vec4 model_rotation;\\n#ifdef GSPLAT_ID\\n\\tuniform uint uId;\\n#endif\\nvoid main(void) {\\n\\tivec2 localFragCoords = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y) - uStartLine);\\n\\tint targetIndex = localFragCoords.y * uViewportWidth + localFragCoords.x;\\n\\tif (targetIndex >= uActiveSplats) {\\n\\t\\t#ifdef GSPLAT_COLOR_UINT\\n\\t\\t\\twriteDataColor(uvec4(0u));\\n\\t\\t#else\\n\\t\\t\\twriteDataColor(vec4(0.0));\\n\\t\\t#endif\\n\\t\\t#ifndef GSPLAT_COLOR_ONLY\\n\\t\\t\\twriteDataTransformA(uvec4(0u));\\n\\t\\t\\twriteDataTransformB(uvec4(0u));\\n\\t\\t#endif\\n\\t} else {\\n\\t\\t#ifdef GSPLAT_LOD\\n\\t\\t\\tint intervalsSize = int(textureSize(uIntervalsTexture, 0).x);\\n\\t\\t\\tivec2 intervalUV = ivec2(targetIndex % intervalsSize, targetIndex / intervalsSize);\\n\\t\\t\\tuint originalIndex = texelFetch(uIntervalsTexture, intervalUV, 0).r;\\n\\t\\t#else\\n\\t\\t\\tuint originalIndex = uint(targetIndex);\\n\\t\\t#endif\\n\\t\\t\\n\\t\\tsetSplat(originalIndex);\\n\\t\\tvec3 modelCenter = getCenter();\\n\\t\\tvec3 worldCenter = (matrix_model * vec4(modelCenter, 1.0)).xyz;\\n\\t\\tSplatCenter center;\\n\\t\\tinitCenter(modelCenter, center);\\n\\t\\tvec4 srcRotation = getRotation().yzwx;\\n\\t\\tvec3 srcScale = getScale();\\n\\t\\tvec4 worldRotation = quatMul(model_rotation, srcRotation);\\n\\t\\tif (worldRotation.w < 0.0) {\\n\\t\\t\\tworldRotation = -worldRotation;\\n\\t\\t}\\n\\t\\tvec3 worldScale = model_scale * srcScale;\\n\\t\\tvec3 originalCenter = worldCenter;\\n\\t\\tmodifySplatCenter(worldCenter);\\n\\t\\tmodifySplatRotationScale(originalCenter, worldCenter, worldRotation, worldScale);\\n\\t\\tvec4 color = getColor();\\n\\t\\t#if SH_BANDS > 0\\n\\t\\t\\tvec3 dir = normalize(center.view * mat3(center.modelView));\\n\\t\\t\\tvec3 sh[SH_COEFFS];\\n\\t\\t\\tfloat scale;\\n\\t\\t\\treadSHData(sh, scale);\\n\\t\\t\\tcolor.xyz += evalSH(sh, dir) * scale;\\n\\t\\t#endif\\n\\t\\tmodifySplatColor(worldCenter, color);\\n\\t\\tcolor.xyz *= uColorMultiply;\\n\\t\\t#ifdef GSPLAT_COLOR_UINT\\n\\t\\t\\tuint packed_rg = packHalf2x16(color.rg);\\n\\t\\t\\tuint packed_ba = packHalf2x16(color.ba);\\n\\t\\t\\twriteDataColor(uvec4(\\n\\t\\t\\t\\tpacked_rg & 0xFFFFu,\\n\\t\\t\\t\\tpacked_rg >> 16u,\\n\\t\\t\\t\\tpacked_ba & 0xFFFFu,\\n\\t\\t\\t\\tpacked_ba >> 16u\\n\\t\\t\\t));\\n\\t\\t#else\\n\\t\\t\\twriteDataColor(color);\\n\\t\\t#endif\\n\\t\\t#ifndef GSPLAT_COLOR_ONLY\\n\\t\\t\\twriteDataTransformA(uvec4(floatBitsToUint(worldCenter.x), floatBitsToUint(worldCenter.y), floatBitsToUint(worldCenter.z), packHalf2x16(worldRotation.xy)));\\n\\t\\t\\twriteDataTransformB(uvec4(packHalf2x16(vec2(worldRotation.z, worldScale.x)), packHalf2x16(worldScale.yz), 0u, 0u));\\n\\t\\t#endif\\n\\t\\t#ifdef GSPLAT_ID\\n\\t\\t\\twritePcId(uvec4(uId, 0u, 0u, 0u));\\n\\t\\t#endif\\n\\t}\\n}\\n`;\\n\\nvar wgslGsplatCopyToWorkBufferPS = `\\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 \\\"gsplatModifyVS\\\"\\nuniform uStartLine: i32;\\nuniform uViewportWidth: i32;\\n#ifdef GSPLAT_LOD\\n\\tvar uIntervalsTexture: texture_2d<u32>;\\n#endif\\nuniform uColorMultiply: vec3f;\\nuniform uActiveSplats: i32;\\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 localFragCoords = vec2i(i32(input.position.x), i32(input.position.y) - uniform.uStartLine);\\n\\tlet targetIndex = localFragCoords.y * uniform.uViewportWidth + localFragCoords.x;\\n\\t\\n\\tif (targetIndex >= uniform.uActiveSplats) {\\n\\t\\twriteDataColor(vec4f(0.0));\\n\\t\\t#ifndef GSPLAT_COLOR_ONLY\\n\\t\\t\\twriteDataTransformA(vec4u(0u));\\n\\t\\t\\twriteDataTransformB(vec4u(0u));\\n\\t\\t#endif\\n\\t} else {\\n\\t\\t#ifdef GSPLAT_LOD\\n\\t\\t\\tlet intervalsSize = i32(textureDimensions(uIntervalsTexture, 0).x);\\n\\t\\t\\tlet intervalUV = vec2i(targetIndex % intervalsSize, targetIndex / intervalsSize);\\n\\t\\t\\tlet originalIndex = textureLoad(uIntervalsTexture, intervalUV, 0).r;\\n\\t\\t#else\\n\\t\\t\\tlet originalIndex = targetIndex;\\n\\t\\t#endif\\n\\t\\t\\n\\t\\tsetSplat(u32(originalIndex));\\n\\t\\tvar modelCenter = getCenter();\\n\\t\\tvar worldCenter = (uniform.matrix_model * vec4f(modelCenter, 1.0)).xyz;\\n\\t\\tvar center: SplatCenter;\\n\\t\\tinitCenter(modelCenter, &center);\\n\\t\\tlet srcRotation = getRotation().yzwx;\\n\\t\\tlet srcScale = getScale();\\n\\t\\tvar worldRotation = quatMul(uniform.model_rotation, srcRotation);\\n\\t\\tif (worldRotation.w < 0.0) {\\n\\t\\t\\tworldRotation = -worldRotation;\\n\\t\\t}\\n\\t\\tvar worldScale = uniform.model_scale * srcScale;\\n\\t\\tlet originalCenter = worldCenter;\\n\\t\\tmodifySplatCenter(&worldCenter);\\n\\t\\tmodifySplatRotationScale(originalCenter, worldCenter, &worldRotation, &worldScale);\\n\\t\\tvar color = getColor();\\n\\t\\t#if SH_BANDS > 0\\n\\t\\t\\tlet dir = normalize(center.view * mat3x3f(center.modelView[0].xyz, center.modelView[1].xyz, center.modelView[2].xyz));\\n\\t\\t\\tvar sh: array<vec3f, SH_COEFFS>;\\n\\t\\t\\tvar scale: f32;\\n\\t\\t\\treadSHData(&sh, &scale);\\n\\t\\t\\tcolor = vec4f(color.xyz + evalSH(&sh, dir) * scale, color.w);\\n\\t\\t#endif\\n\\t\\tmodifySplatColor(worldCenter, &color);\\n\\t\\tcolor = vec4f(color.xyz * uniform.uColorMultiply, color.w);\\n\\t\\twriteDataColor(color);\\n\\t\\t#ifndef GSPLAT_COLOR_ONLY\\n\\t\\t\\twriteDataTransformA(vec4u(bitcast<u32>(worldCenter.x), bitcast<u32>(worldCenter.y), bitcast<u32>(worldCenter.z), pack2x16float(worldRotation.xy)));\\n\\t\\t\\twriteDataTransformB(vec4u(pack2x16float(vec2f(worldRotation.z, worldScale.x)), pack2x16float(worldScale.yz), 0u, 0u));\\n\\t\\t#endif\\n\\t\\t#ifdef GSPLAT_ID\\n\\t\\t\\twritePcId(vec4u(uniform.uId, 0u, 0u, 0u));\\n\\t\\t#endif\\n\\t}\\n\\t\\n\\treturn processOutput;\\n}\\n`;\\n\\nconst _viewMat = new Mat4();\\nconst _modelScale = new Vec3();\\nconst _modelRotation = new Quat();\\nconst _whiteColor = [\\n\\t\\t1,\\n\\t\\t1,\\n\\t\\t1\\n];\\nclass GSplatWorkBufferRenderPass extends RenderPass {\\n\\t\\tinit(renderTarget) {\\n\\t\\t\\t\\tsuper.init(renderTarget);\\n\\t\\t\\t\\tthis.colorOps.clear = false;\\n\\t\\t\\t\\tthis.depthStencilOps.clearDepth = false;\\n\\t\\t}\\n\\t\\tupdate(splats, cameraNode, colorsByLod) {\\n\\t\\t\\t\\tthis.splats.length = 0;\\n\\t\\t\\t\\tthis.colorsByLod = colorsByLod;\\n\\t\\t\\t\\tfor(let i = 0; i < splats.length; i++){\\n\\t\\t\\t\\t\\t\\tconst splatInfo = splats[i];\\n\\t\\t\\t\\t\\t\\tif (splatInfo.activeSplats > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.splats.push(splatInfo);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.cameraNode = cameraNode;\\n\\t\\t\\t\\treturn this.splats.length > 0;\\n\\t\\t}\\n\\t\\texecute() {\\n\\t\\t\\t\\tconst { device, splats, cameraNode } = this;\\n\\t\\t\\t\\tdevice.setBlendState(BlendState.NOBLEND);\\n\\t\\t\\t\\tdevice.setCullMode(CULLFACE_NONE);\\n\\t\\t\\t\\tdevice.setDepthState(DepthState.NODEPTH);\\n\\t\\t\\t\\tdevice.setStencilState();\\n\\t\\t\\t\\tconst viewInvMat = cameraNode.getWorldTransform();\\n\\t\\t\\t\\tconst viewMat = _viewMat.copy(viewInvMat).invert();\\n\\t\\t\\t\\tdevice.scope.resolve('matrix_view').setValue(viewMat.data);\\n\\t\\t\\t\\tfor(let i = 0; i < splats.length; i++){\\n\\t\\t\\t\\t\\t\\tthis.renderSplat(splats[i]);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\trenderSplat(splatInfo) {\\n\\t\\t\\t\\tconst { device, resource } = splatInfo;\\n\\t\\t\\t\\tconst scope = device.scope;\\n\\t\\t\\t\\tconst { activeSplats, lineStart, viewport, intervalTexture } = splatInfo;\\n\\t\\t\\t\\tconst workBufferModifier = splatInfo.getWorkBufferModifier?.() ?? null;\\n\\t\\t\\t\\tconst formatHash = resource.format.hash;\\n\\t\\t\\t\\tconst formatDeclarations = resource.format.getInputDeclarations();\\n\\t\\t\\t\\tconst workBufferRenderInfo = resource.getWorkBufferRenderInfo(intervalTexture !== null, this.colorOnly, workBufferModifier, formatHash, formatDeclarations, this.workBuffer.format);\\n\\t\\t\\t\\tworkBufferRenderInfo.material.setParameters(device);\\n\\t\\t\\t\\tif (intervalTexture) {\\n\\t\\t\\t\\t\\t\\tscope.resolve('uIntervalsTexture').setValue(intervalTexture.texture);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tscope.resolve('uActiveSplats').setValue(activeSplats);\\n\\t\\t\\t\\tscope.resolve('uStartLine').setValue(lineStart);\\n\\t\\t\\t\\tscope.resolve('uViewportWidth').setValue(viewport.z);\\n\\t\\t\\t\\tconst color = this.colorsByLod?.[splatInfo.lodIndex] ?? this.colorsByLod?.[0] ?? _whiteColor;\\n\\t\\t\\t\\tscope.resolve('uColorMultiply').setValue(color);\\n\\t\\t\\t\\tconst worldTransform = splatInfo.node.getWorldTransform();\\n\\t\\t\\t\\tworldTransform.getScale(_modelScale);\\n\\t\\t\\t\\t_modelRotation.setFromMat4(worldTransform);\\n\\t\\t\\t\\tif (_modelRotation.w < 0) {\\n\\t\\t\\t\\t\\t\\t_modelRotation.mulScalar(-1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._modelScaleData[0] = _modelScale.x;\\n\\t\\t\\t\\tthis._modelScaleData[1] = _modelScale.y;\\n\\t\\t\\t\\tthis._modelScaleData[2] = _modelScale.z;\\n\\t\\t\\t\\tthis._modelRotationData[0] = _modelRotation.x;\\n\\t\\t\\t\\tthis._modelRotationData[1] = _modelRotation.y;\\n\\t\\t\\t\\tthis._modelRotationData[2] = _modelRotation.z;\\n\\t\\t\\t\\tthis._modelRotationData[3] = _modelRotation.w;\\n\\t\\t\\t\\tscope.resolve('matrix_model').setValue(worldTransform.data);\\n\\t\\t\\t\\tscope.resolve('model_scale').setValue(this._modelScaleData);\\n\\t\\t\\t\\tscope.resolve('model_rotation').setValue(this._modelRotationData);\\n\\t\\t\\t\\tscope.resolve('uId').setValue(splatInfo.placementId);\\n\\t\\t\\t\\tif (splatInfo.parameters) {\\n\\t\\t\\t\\t\\t\\tfor (const param of splatInfo.parameters.values()){\\n\\t\\t\\t\\t\\t\\t\\t\\tparam.scopeId.setValue(param.data);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst instanceStreams = splatInfo.getInstanceStreams?.();\\n\\t\\t\\t\\tif (instanceStreams) {\\n\\t\\t\\t\\t\\t\\tinstanceStreams.syncWithFormat(splatInfo.resource.format);\\n\\t\\t\\t\\t\\t\\tfor (const [name, texture] of instanceStreams.textures){\\n\\t\\t\\t\\t\\t\\t\\t\\tscope.resolve(name).setValue(texture);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tworkBufferRenderInfo.quadRender.render(viewport);\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.splats.length = 0;\\n\\t\\t\\t\\tsuper.destroy();\\n\\t\\t}\\n\\t\\tconstructor(device, workBuffer, colorOnly = false){\\n\\t\\t\\t\\tsuper(device), this.splats = [], this.colorsByLod = undefined, this.cameraNode = null, this._modelScaleData = new Float32Array(3), this._modelRotationData = new Float32Array(4);\\n\\t\\t\\t\\tthis.workBuffer = workBuffer;\\n\\t\\t\\t\\tthis.colorOnly = colorOnly;\\n\\t\\t}\\n}\\n\\nclass GSplatStreams {\\n\\t\\tget textureDimensions() {\\n\\t\\t\\t\\treturn this._textureDimensions;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tfor (const texture of this.textures.values()){\\n\\t\\t\\t\\t\\t\\ttexture.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.textures.clear();\\n\\t\\t}\\n\\t\\tinit(format, numElements) {\\n\\t\\t\\t\\tthis.format = format;\\n\\t\\t\\t\\tthis._textureDimensions = this.evalTextureSize(numElements);\\n\\t\\t\\t\\tconst streams = this._isInstance ? format.instanceStreams : format.resourceStreams;\\n\\t\\t\\t\\tfor (const stream of streams){\\n\\t\\t\\t\\t\\t\\tconst texture = this.createTexture(stream.name, stream.format, this._textureDimensions);\\n\\t\\t\\t\\t\\t\\tthis.textures.set(stream.name, texture);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._formatVersion = format.extraStreamsVersion;\\n\\t\\t}\\n\\t\\tgetTexture(name) {\\n\\t\\t\\t\\tthis.syncWithFormat(this.format);\\n\\t\\t\\t\\treturn this.textures.get(name);\\n\\t\\t}\\n\\t\\tgetTexturesInOrder() {\\n\\t\\t\\t\\tconst result = [];\\n\\t\\t\\t\\tif (this.format) {\\n\\t\\t\\t\\t\\t\\tconst allStreams = this._isInstance ? this.format.instanceStreams : this.format.resourceStreams;\\n\\t\\t\\t\\t\\t\\tfor (const stream of allStreams){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst texture = this.textures.get(stream.name);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (texture) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult.push(texture);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tsyncWithFormat(format) {\\n\\t\\t\\t\\tif (format) {\\n\\t\\t\\t\\t\\t\\tif (this.format === format && this._formatVersion === format.extraStreamsVersion) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.format = format;\\n\\t\\t\\t\\t\\t\\tconst streams = this._isInstance ? format.instanceStreams : format.resourceStreams;\\n\\t\\t\\t\\t\\t\\tfor (const stream of streams){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this.textures.has(stream.name)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst texture = this.createTexture(stream.name, stream.format, this._textureDimensions);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.textures.set(stream.name, texture);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._formatVersion = format.extraStreamsVersion;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tevalTextureSize(count) {\\n\\t\\t\\t\\tconst width = Math.ceil(Math.sqrt(count));\\n\\t\\t\\t\\treturn new Vec2(width, Math.ceil(count / width));\\n\\t\\t}\\n\\t\\tresize(width, height) {\\n\\t\\t\\t\\tthis._textureDimensions.set(width, height);\\n\\t\\t\\t\\tfor (const texture of this.textures.values()){\\n\\t\\t\\t\\t\\t\\ttexture.resize(width, height);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcreateTexture(name, format, size, data) {\\n\\t\\t\\t\\tconst options = {\\n\\t\\t\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\t\\t\\twidth: size.x,\\n\\t\\t\\t\\t\\t\\theight: size.y,\\n\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\tcubemap: false,\\n\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (data) {\\n\\t\\t\\t\\t\\t\\toptions.levels = [\\n\\t\\t\\t\\t\\t\\t\\t\\tdata\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn new Texture(this.device, options);\\n\\t\\t}\\n\\t\\tconstructor(device, isInstance = false){\\n\\t\\t\\t\\tthis.format = null;\\n\\t\\t\\t\\tthis.textures = new Map();\\n\\t\\t\\t\\tthis._textureDimensions = new Vec2();\\n\\t\\t\\t\\tthis._isInstance = false;\\n\\t\\t\\t\\tthis._formatVersion = -1;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis._isInstance = isInstance;\\n\\t\\t}\\n}\\n\\nlet id$1 = 0;\\nclass WorkBufferRenderInfo {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.material?.destroy();\\n\\t\\t\\t\\tthis.quadRender?.destroy();\\n\\t\\t}\\n\\t\\tconstructor(device, key, material, colorOnly, format){\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.material = material;\\n\\t\\t\\t\\tconst clonedDefines = new Map(material.defines);\\n\\t\\t\\t\\tconst colorStream = format.getStream('dataColor');\\n\\t\\t\\t\\tif (colorStream.format === PIXELFORMAT_RGBA16U) {\\n\\t\\t\\t\\t\\t\\tclonedDefines.set('GSPLAT_COLOR_UINT', '');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (colorOnly) {\\n\\t\\t\\t\\t\\t\\tclonedDefines.set('GSPLAT_COLOR_ONLY', '');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (format.getStream('pcId')) {\\n\\t\\t\\t\\t\\t\\tclonedDefines.set('GSPLAT_ID', '');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst fragmentIncludes = material.hasShaderChunks ? device.isWebGPU ? material.shaderChunks.wgsl : material.shaderChunks.glsl : undefined;\\n\\t\\t\\t\\tconst outputStreams = colorOnly ? [\\n\\t\\t\\t\\t\\t\\tcolorStream\\n\\t\\t\\t\\t] : [\\n\\t\\t\\t\\t\\t\\t...format.streams,\\n\\t\\t\\t\\t\\t\\t...format.extraStreams\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tconst fragmentOutputTypes = [];\\n\\t\\t\\t\\tfor (const stream of outputStreams){\\n\\t\\t\\t\\t\\t\\tconst info = getGlslShaderType(stream.format);\\n\\t\\t\\t\\t\\t\\tfragmentOutputTypes.push(info.returnType);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst shader = ShaderUtils.createShader(device, {\\n\\t\\t\\t\\t\\t\\tuniqueName: `SplatCopyToWorkBuffer:${key}`,\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tvertexDefines: clonedDefines,\\n\\t\\t\\t\\t\\t\\tfragmentDefines: clonedDefines,\\n\\t\\t\\t\\t\\t\\tvertexChunk: 'fullscreenQuadVS',\\n\\t\\t\\t\\t\\t\\tfragmentGLSL: glslGsplatCopyToWorkBufferPS,\\n\\t\\t\\t\\t\\t\\tfragmentWGSL: wgslGsplatCopyToWorkBufferPS,\\n\\t\\t\\t\\t\\t\\tfragmentIncludes: fragmentIncludes,\\n\\t\\t\\t\\t\\t\\tfragmentOutputTypes: fragmentOutputTypes\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.quadRender = new QuadRender(shader);\\n\\t\\t}\\n}\\nclass GSplatWorkBuffer {\\n\\t\\t_createRenderTargets() {\\n\\t\\t\\t\\tthis.renderTarget?.destroy();\\n\\t\\t\\t\\tthis.colorRenderTarget?.destroy();\\n\\t\\t\\t\\tconst colorBuffers = this.streams.getTexturesInOrder();\\n\\t\\t\\t\\tthis.renderTarget = new RenderTarget({\\n\\t\\t\\t\\t\\t\\tname: `GsplatWorkBuffer-MRT-${this.id}`,\\n\\t\\t\\t\\t\\t\\tcolorBuffers: colorBuffers,\\n\\t\\t\\t\\t\\t\\tdepth: false,\\n\\t\\t\\t\\t\\t\\tflipY: true\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst colorTexture = this.streams.getTexture('dataColor');\\n\\t\\t\\t\\tthis.colorRenderTarget = new RenderTarget({\\n\\t\\t\\t\\t\\t\\tname: `GsplatWorkBuffer-Color-${this.id}`,\\n\\t\\t\\t\\t\\t\\tcolorBuffer: colorTexture,\\n\\t\\t\\t\\t\\t\\tdepth: false,\\n\\t\\t\\t\\t\\t\\tflipY: true\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.renderPass?.init(this.renderTarget);\\n\\t\\t\\t\\tthis.colorRenderPass?.init(this.colorRenderTarget);\\n\\t\\t}\\n\\t\\tsyncWithFormat() {\\n\\t\\t\\t\\tconst prevVersion = this.streams._formatVersion;\\n\\t\\t\\t\\tthis.streams.syncWithFormat(this.format);\\n\\t\\t\\t\\tif (prevVersion !== this.streams._formatVersion) {\\n\\t\\t\\t\\t\\t\\tthis._createRenderTargets();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetTexture(name) {\\n\\t\\t\\t\\treturn this.streams.getTexture(name);\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.renderPass?.destroy();\\n\\t\\t\\t\\tthis.colorRenderPass?.destroy();\\n\\t\\t\\t\\tthis.streams.destroy();\\n\\t\\t\\t\\tthis.orderTexture?.destroy();\\n\\t\\t\\t\\tthis.orderBuffer?.destroy();\\n\\t\\t\\t\\tthis.renderTarget?.destroy();\\n\\t\\t\\t\\tthis.colorRenderTarget?.destroy();\\n\\t\\t\\t\\tthis.uploadStream.destroy();\\n\\t\\t}\\n\\t\\tget textureSize() {\\n\\t\\t\\t\\treturn this.streams.textureDimensions.x;\\n\\t\\t}\\n\\t\\tsetOrderData(data) {\\n\\t\\t\\t\\tthis.textureSize;\\n\\t\\t\\t\\tif (this.device.isWebGPU) {\\n\\t\\t\\t\\t\\t\\tthis.uploadStream.upload(data, this.orderBuffer, 0, data.length);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.uploadStream.upload(data, this.orderTexture, 0, data.length);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tresize(textureSize) {\\n\\t\\t\\t\\tthis.renderTarget.resize(textureSize, textureSize);\\n\\t\\t\\t\\tthis.colorRenderTarget.resize(textureSize, textureSize);\\n\\t\\t\\t\\tthis.streams.resize(textureSize, textureSize);\\n\\t\\t\\t\\tif (this.device.isWebGPU) {\\n\\t\\t\\t\\t\\t\\tconst newByteSize = textureSize * textureSize * 4;\\n\\t\\t\\t\\t\\t\\tif (this.orderBuffer.byteSize < newByteSize) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.orderBuffer.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.orderBuffer = new StorageBuffer(this.device, newByteSize, BUFFERUSAGE_COPY_DST);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.orderTexture.resize(textureSize, textureSize);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\trender(splats, cameraNode, colorsByLod) {\\n\\t\\t\\t\\tif (this.renderPass.update(splats, cameraNode, colorsByLod)) {\\n\\t\\t\\t\\t\\t\\tthis.renderPass.render();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\trenderColor(splats, cameraNode, colorsByLod) {\\n\\t\\t\\t\\tif (this.colorRenderPass.update(splats, cameraNode, colorsByLod)) {\\n\\t\\t\\t\\t\\t\\tthis.colorRenderPass.render();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(device, format){\\n\\t\\t\\t\\tthis.id = id$1++;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.format = format;\\n\\t\\t\\t\\tthis.streams = new GSplatStreams(device);\\n\\t\\t\\t\\tthis.streams.init(format, 1);\\n\\t\\t\\t\\tthis._createRenderTargets();\\n\\t\\t\\t\\tthis.uploadStream = new UploadStream(device);\\n\\t\\t\\t\\tif (device.isWebGPU) {\\n\\t\\t\\t\\t\\t\\tthis.orderBuffer = new StorageBuffer(device, 4, BUFFERUSAGE_COPY_DST);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.orderTexture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'SplatGlobalOrder',\\n\\t\\t\\t\\t\\t\\t\\t\\twidth: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\theight: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_R32U,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.renderPass = new GSplatWorkBufferRenderPass(device, this);\\n\\t\\t\\t\\tthis.renderPass.init(this.renderTarget);\\n\\t\\t\\t\\tthis.colorRenderPass = new GSplatWorkBufferRenderPass(device, this, true);\\n\\t\\t\\t\\tthis.colorRenderPass.init(this.colorRenderTarget);\\n\\t\\t}\\n}\\n\\nclass GSplatResourceCleanup {\\n\\t\\tstatic queueDestroy(device, resource) {\\n\\t\\t\\t\\tthis._cache.get(device, ()=>new GSplatResourceCleanup())._pendingDestroy.add(resource);\\n\\t\\t}\\n\\t\\tstatic process(device) {\\n\\t\\t\\t\\tconst pending = this._cache.get(device, ()=>new GSplatResourceCleanup())._pendingDestroy;\\n\\t\\t\\t\\tfor (const resource of pending){\\n\\t\\t\\t\\t\\t\\tif (resource.refCount === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tresource._actualDestroy();\\n\\t\\t\\t\\t\\t\\t\\t\\tpending.delete(resource);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._pendingDestroy.clear();\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis._pendingDestroy = new Set();\\n\\t\\t}\\n}\\nGSplatResourceCleanup._cache = new DeviceCache();\\n\\nlet id = 0;\\nconst tempMap = new Map();\\nclass GSplatResourceBase {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tif (this.refCount > 0) {\\n\\t\\t\\t\\t\\t\\tGSplatResourceCleanup.queueDestroy(this.device, this);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._actualDestroy();\\n\\t\\t}\\n\\t\\t_actualDestroy() {\\n\\t\\t\\t\\tthis.streams.destroy();\\n\\t\\t\\t\\tthis.mesh?.destroy();\\n\\t\\t\\t\\tthis.instanceIndices?.destroy();\\n\\t\\t\\t\\tthis.workBufferRenderInfos.forEach((info)=>info.destroy());\\n\\t\\t\\t\\tthis.workBufferRenderInfos.clear();\\n\\t\\t}\\n\\t\\tincRefCount() {\\n\\t\\t\\t\\tthis._refCount++;\\n\\t\\t}\\n\\t\\tdecRefCount() {\\n\\t\\t\\t\\tthis._refCount--;\\n\\t\\t}\\n\\t\\tget refCount() {\\n\\t\\t\\t\\treturn this._refCount;\\n\\t\\t}\\n\\t\\tensureMesh() {\\n\\t\\t\\t\\tif (!this.mesh) {\\n\\t\\t\\t\\t\\t\\tthis.mesh = GSplatResourceBase.createMesh(this.device);\\n\\t\\t\\t\\t\\t\\tthis.mesh.aabb.copy(this.aabb);\\n\\t\\t\\t\\t\\t\\tthis.instanceIndices = GSplatResourceBase.createInstanceIndices(this.device, this.gsplatData.numSplats);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._meshRefCount++;\\n\\t\\t}\\n\\t\\treleaseMesh() {\\n\\t\\t\\t\\tthis._meshRefCount--;\\n\\t\\t\\t\\tif (this._meshRefCount < 1) {\\n\\t\\t\\t\\t\\t\\tthis.mesh = null;\\n\\t\\t\\t\\t\\t\\tthis.instanceIndices?.destroy();\\n\\t\\t\\t\\t\\t\\tthis.instanceIndices = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetWorkBufferRenderInfo(useIntervals, colorOnly, workBufferModifier, formatHash, formatDeclarations, workBufferFormat) {\\n\\t\\t\\t\\tthis.configureMaterialDefines(tempMap);\\n\\t\\t\\t\\tif (useIntervals) tempMap.set('GSPLAT_LOD', '');\\n\\t\\t\\t\\tif (colorOnly) tempMap.set('GSPLAT_COLOR_ONLY', '');\\n\\t\\t\\t\\tlet definesKey = '';\\n\\t\\t\\t\\tfor (const [k, v] of tempMap){\\n\\t\\t\\t\\t\\t\\tif (definesKey) definesKey += ';';\\n\\t\\t\\t\\t\\t\\tdefinesKey += `${k}=${v}`;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst key = `${formatHash};${workBufferFormat.hash};${workBufferModifier?.hash ?? 0};${definesKey}`;\\n\\t\\t\\t\\tlet info = this.workBufferRenderInfos.get(key);\\n\\t\\t\\t\\tif (!info) {\\n\\t\\t\\t\\t\\t\\tconst material = new ShaderMaterial();\\n\\t\\t\\t\\t\\t\\tthis.configureMaterial(material, workBufferModifier, formatDeclarations);\\n\\t\\t\\t\\t\\t\\tconst chunks = this.device.isWebGPU ? material.shaderChunks.wgsl : material.shaderChunks.glsl;\\n\\t\\t\\t\\t\\t\\tconst outputStreams = colorOnly ? [\\n\\t\\t\\t\\t\\t\\t\\t\\tworkBufferFormat.getStream('dataColor')\\n\\t\\t\\t\\t\\t\\t] : [\\n\\t\\t\\t\\t\\t\\t\\t\\t...workBufferFormat.streams,\\n\\t\\t\\t\\t\\t\\t\\t\\t...workBufferFormat.extraStreams\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t\\t\\tlet outputCode = workBufferFormat.getOutputDeclarations(outputStreams);\\n\\t\\t\\t\\t\\t\\tif (colorOnly && workBufferFormat.extraStreams.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\toutputCode += `\\\\n${workBufferFormat.getOutputStubs(workBufferFormat.extraStreams)}`;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tchunks.set('gsplatWorkBufferOutputVS', outputCode);\\n\\t\\t\\t\\t\\t\\ttempMap.forEach((v, k)=>material.setDefine(k, v));\\n\\t\\t\\t\\t\\t\\tinfo = new WorkBufferRenderInfo(this.device, key, material, colorOnly, workBufferFormat);\\n\\t\\t\\t\\t\\t\\tthis.workBufferRenderInfos.set(key, info);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttempMap.clear();\\n\\t\\t\\t\\treturn info;\\n\\t\\t}\\n\\t\\tstatic createMesh(device) {\\n\\t\\t\\t\\tconst splatInstanceSize = GSplatResourceBase.instanceSize;\\n\\t\\t\\t\\tconst meshPositions = new Float32Array(12 * splatInstanceSize);\\n\\t\\t\\t\\tconst meshIndices = new Uint32Array(6 * splatInstanceSize);\\n\\t\\t\\t\\tfor(let i = 0; i < splatInstanceSize; ++i){\\n\\t\\t\\t\\t\\t\\tmeshPositions.set([\\n\\t\\t\\t\\t\\t\\t\\t\\t-1,\\n\\t\\t\\t\\t\\t\\t\\t\\t-1,\\n\\t\\t\\t\\t\\t\\t\\t\\ti,\\n\\t\\t\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t\\t\\t-1,\\n\\t\\t\\t\\t\\t\\t\\t\\ti,\\n\\t\\t\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t\\t\\ti,\\n\\t\\t\\t\\t\\t\\t\\t\\t-1,\\n\\t\\t\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t\\t\\ti\\n\\t\\t\\t\\t\\t\\t], i * 12);\\n\\t\\t\\t\\t\\t\\tconst b = i * 4;\\n\\t\\t\\t\\t\\t\\tmeshIndices.set([\\n\\t\\t\\t\\t\\t\\t\\t\\t0 + b,\\n\\t\\t\\t\\t\\t\\t\\t\\t1 + b,\\n\\t\\t\\t\\t\\t\\t\\t\\t2 + b,\\n\\t\\t\\t\\t\\t\\t\\t\\t0 + b,\\n\\t\\t\\t\\t\\t\\t\\t\\t2 + b,\\n\\t\\t\\t\\t\\t\\t\\t\\t3 + b\\n\\t\\t\\t\\t\\t\\t], i * 6);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst mesh = new Mesh(device);\\n\\t\\t\\t\\tmesh.setPositions(meshPositions, 3);\\n\\t\\t\\t\\tmesh.setIndices(meshIndices);\\n\\t\\t\\t\\tmesh.update();\\n\\t\\t\\t\\treturn mesh;\\n\\t\\t}\\n\\t\\tstatic createInstanceIndices(device, splatCount) {\\n\\t\\t\\t\\tconst splatInstanceSize = GSplatResourceBase.instanceSize;\\n\\t\\t\\t\\tconst numSplats = Math.ceil(splatCount / splatInstanceSize) * splatInstanceSize;\\n\\t\\t\\t\\tconst numSplatInstances = numSplats / splatInstanceSize;\\n\\t\\t\\t\\tconst indexData = new Uint32Array(numSplatInstances);\\n\\t\\t\\t\\tfor(let i = 0; i < numSplatInstances; ++i){\\n\\t\\t\\t\\t\\t\\tindexData[i] = i * splatInstanceSize;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst vertexFormat = new VertexFormat(device, [\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tsemantic: SEMANTIC_ATTR13,\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponents: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\ttype: TYPE_UINT32,\\n\\t\\t\\t\\t\\t\\t\\t\\tasInt: true\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tconst instanceIndices = new VertexBuffer(device, vertexFormat, numSplatInstances, {\\n\\t\\t\\t\\t\\t\\tusage: BUFFER_STATIC,\\n\\t\\t\\t\\t\\t\\tdata: indexData.buffer\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn instanceIndices;\\n\\t\\t}\\n\\t\\tstatic get instanceSize() {\\n\\t\\t\\t\\treturn 128;\\n\\t\\t}\\n\\t\\tget numSplats() {\\n\\t\\t\\t\\treturn this.gsplatData.numSplats;\\n\\t\\t}\\n\\t\\tget format() {\\n\\t\\t\\t\\treturn this._format;\\n\\t\\t}\\n\\t\\tgetTexture(name) {\\n\\t\\t\\t\\treturn this.streams.getTexture(name) ?? null;\\n\\t\\t}\\n\\t\\tget textureDimensions() {\\n\\t\\t\\t\\treturn this.streams.textureDimensions;\\n\\t\\t}\\n\\t\\tconfigureMaterial(material, workBufferModifier, formatDeclarations) {\\n\\t\\t\\t\\tthis.configureMaterialDefines(material.defines);\\n\\t\\t\\t\\tthis.streams.syncWithFormat(this.format);\\n\\t\\t\\t\\tconst chunks = this.device.isWebGPU ? material.shaderChunks.wgsl : material.shaderChunks.glsl;\\n\\t\\t\\t\\tchunks.set('gsplatDeclarationsVS', formatDeclarations);\\n\\t\\t\\t\\tchunks.set('gsplatReadVS', this.format.getReadCode());\\n\\t\\t\\t\\tif (workBufferModifier?.code) {\\n\\t\\t\\t\\t\\t\\tchunks.set('gsplatModifyVS', workBufferModifier.code);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const [name, texture] of this.streams.textures){\\n\\t\\t\\t\\t\\t\\tmaterial.setParameter(name, texture);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const [name, value] of this.parameters){\\n\\t\\t\\t\\t\\t\\tmaterial.setParameter(name, value);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.textureDimensions.x > 0) {\\n\\t\\t\\t\\t\\t\\tmaterial.setParameter('splatTextureSize', this.textureDimensions.x);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconfigureMaterialDefines(defines) {}\\n\\t\\tinstantiate() {}\\n\\t\\tconstructor(device, gsplatData){\\n\\t\\t\\t\\tthis.centersVersion = 0;\\n\\t\\t\\t\\tthis.mesh = null;\\n\\t\\t\\t\\tthis.instanceIndices = null;\\n\\t\\t\\t\\tthis.id = id++;\\n\\t\\t\\t\\tthis.workBufferRenderInfos = new Map();\\n\\t\\t\\t\\tthis._format = null;\\n\\t\\t\\t\\tthis.parameters = new Map();\\n\\t\\t\\t\\tthis._refCount = 0;\\n\\t\\t\\t\\tthis._meshRefCount = 0;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.gsplatData = gsplatData;\\n\\t\\t\\t\\tthis.streams = new GSplatStreams(device);\\n\\t\\t\\t\\tthis.centers = gsplatData.getCenters();\\n\\t\\t\\t\\tthis.aabb = new BoundingBox();\\n\\t\\t\\t\\tgsplatData.calcAabb(this.aabb);\\n\\t\\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\\t\\tconstructor(gsplatData, p, r, s, c){\\n\\t\\t\\t\\tconst x = gsplatData.getProp('x');\\n\\t\\t\\t\\tconst y = gsplatData.getProp('y');\\n\\t\\t\\t\\tconst z = gsplatData.getProp('z');\\n\\t\\t\\t\\tconst rx = gsplatData.getProp('rot_1');\\n\\t\\t\\t\\tconst ry = gsplatData.getProp('rot_2');\\n\\t\\t\\t\\tconst rz = gsplatData.getProp('rot_3');\\n\\t\\t\\t\\tconst rw = gsplatData.getProp('rot_0');\\n\\t\\t\\t\\tconst sx = gsplatData.getProp('scale_0');\\n\\t\\t\\t\\tconst sy = gsplatData.getProp('scale_1');\\n\\t\\t\\t\\tconst sz = gsplatData.getProp('scale_2');\\n\\t\\t\\t\\tconst cr = gsplatData.getProp('f_dc_0');\\n\\t\\t\\t\\tconst cg = gsplatData.getProp('f_dc_1');\\n\\t\\t\\t\\tconst cb = gsplatData.getProp('f_dc_2');\\n\\t\\t\\t\\tconst ca = gsplatData.getProp('opacity');\\n\\t\\t\\t\\tconst sigmoid = (v)=>{\\n\\t\\t\\t\\t\\t\\tif (v > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 1 / (1 + Math.exp(-v));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst t = Math.exp(v);\\n\\t\\t\\t\\t\\t\\treturn t / (1 + t);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.read = (i)=>{\\n\\t\\t\\t\\t\\t\\tif (p) {\\n\\t\\t\\t\\t\\t\\t\\t\\tp.x = x[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tp.y = y[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tp.z = z[i];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (r) {\\n\\t\\t\\t\\t\\t\\t\\t\\tr.set(rx[i], ry[i], rz[i], rw[i]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (s) {\\n\\t\\t\\t\\t\\t\\t\\t\\ts.set(Math.exp(sx[i]), Math.exp(sy[i]), Math.exp(sz[i]));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (c) {\\n\\t\\t\\t\\t\\t\\t\\t\\tc.set(0.5 + cr[i] * SH_C0$2, 0.5 + cg[i] * SH_C0$2, 0.5 + cb[i] * SH_C0$2, sigmoid(ca[i]));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t}\\n}\\nconst calcSplatMat = (result, p, r)=>{\\n\\t\\tquat$1.set(r.x, r.y, r.z, r.w).normalize();\\n\\t\\tresult.setTRS(p, quat$1, Vec3.ONE);\\n};\\nclass GSplatData {\\n\\t\\tstatic calcSplatAabb(result, p, r, s) {\\n\\t\\t\\t\\tcalcSplatMat(mat4, p, r);\\n\\t\\t\\t\\taabb.center.set(0, 0, 0);\\n\\t\\t\\t\\taabb.halfExtents.set(s.x * 2, s.y * 2, s.z * 2);\\n\\t\\t\\t\\tresult.setFromTransformedAabb(aabb, mat4);\\n\\t\\t}\\n\\t\\tgetProp(name, elementName = 'vertex') {\\n\\t\\t\\t\\treturn this.getElement(elementName)?.properties.find((p)=>p.name === name)?.storage;\\n\\t\\t}\\n\\t\\tgetElement(name) {\\n\\t\\t\\t\\treturn this.elements.find((e)=>e.name === name);\\n\\t\\t}\\n\\t\\taddProp(name, storage) {\\n\\t\\t\\t\\tthis.getElement('vertex').properties.push({\\n\\t\\t\\t\\t\\t\\ttype: 'float',\\n\\t\\t\\t\\t\\t\\tname,\\n\\t\\t\\t\\t\\t\\tstorage,\\n\\t\\t\\t\\t\\t\\tbyteSize: 4\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tcreateIter(p, r, s, c) {\\n\\t\\t\\t\\treturn new SplatIterator(this, p, r, s, c);\\n\\t\\t}\\n\\t\\tcalcAabb(result, pred) {\\n\\t\\t\\t\\tlet mx, my, mz, Mx, My, Mz;\\n\\t\\t\\t\\tlet first = true;\\n\\t\\t\\t\\tconst x = this.getProp('x');\\n\\t\\t\\t\\tconst y = this.getProp('y');\\n\\t\\t\\t\\tconst z = this.getProp('z');\\n\\t\\t\\t\\tconst sx = this.getProp('scale_0');\\n\\t\\t\\t\\tconst sy = this.getProp('scale_1');\\n\\t\\t\\t\\tconst sz = this.getProp('scale_2');\\n\\t\\t\\t\\tfor(let i = 0; i < this.numSplats; ++i){\\n\\t\\t\\t\\t\\t\\tif (pred && !pred(i)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst px = x[i];\\n\\t\\t\\t\\t\\t\\tconst py = y[i];\\n\\t\\t\\t\\t\\t\\tconst pz = z[i];\\n\\t\\t\\t\\t\\t\\tconst scale = Math.max(sx[i], sy[i], sz[i]);\\n\\t\\t\\t\\t\\t\\tif (!isFinite(px) || !isFinite(py) || !isFinite(pz) || !isFinite(scale)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst scaleVal = 2.0 * Math.exp(scale);\\n\\t\\t\\t\\t\\t\\tif (first) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfirst = false;\\n\\t\\t\\t\\t\\t\\t\\t\\tmx = px - scaleVal;\\n\\t\\t\\t\\t\\t\\t\\t\\tmy = py - scaleVal;\\n\\t\\t\\t\\t\\t\\t\\t\\tmz = pz - scaleVal;\\n\\t\\t\\t\\t\\t\\t\\t\\tMx = px + scaleVal;\\n\\t\\t\\t\\t\\t\\t\\t\\tMy = py + scaleVal;\\n\\t\\t\\t\\t\\t\\t\\t\\tMz = pz + scaleVal;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tmx = Math.min(mx, px - scaleVal);\\n\\t\\t\\t\\t\\t\\t\\t\\tmy = Math.min(my, py - scaleVal);\\n\\t\\t\\t\\t\\t\\t\\t\\tmz = Math.min(mz, pz - scaleVal);\\n\\t\\t\\t\\t\\t\\t\\t\\tMx = Math.max(Mx, px + scaleVal);\\n\\t\\t\\t\\t\\t\\t\\t\\tMy = Math.max(My, py + scaleVal);\\n\\t\\t\\t\\t\\t\\t\\t\\tMz = Math.max(Mz, pz + scaleVal);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!first) {\\n\\t\\t\\t\\t\\t\\tresult.center.set((mx + Mx) * 0.5, (my + My) * 0.5, (mz + Mz) * 0.5);\\n\\t\\t\\t\\t\\t\\tresult.halfExtents.set((Mx - mx) * 0.5, (My - my) * 0.5, (Mz - mz) * 0.5);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn !first;\\n\\t\\t}\\n\\t\\tcalcAabbExact(result, pred) {\\n\\t\\t\\t\\tconst p = new Vec3();\\n\\t\\t\\t\\tconst r = new Quat();\\n\\t\\t\\t\\tconst s = new Vec3();\\n\\t\\t\\t\\tconst iter = this.createIter(p, r, s);\\n\\t\\t\\t\\tlet first = true;\\n\\t\\t\\t\\tfor(let i = 0; i < this.numSplats; ++i){\\n\\t\\t\\t\\t\\t\\tif (pred && !pred(i)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\titer.read(i);\\n\\t\\t\\t\\t\\t\\tif (first) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfirst = false;\\n\\t\\t\\t\\t\\t\\t\\t\\tGSplatData.calcSplatAabb(result, p, r, s);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tGSplatData.calcSplatAabb(aabb2, p, r, s);\\n\\t\\t\\t\\t\\t\\t\\t\\tresult.add(aabb2);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn !first;\\n\\t\\t}\\n\\t\\tgetCenters() {\\n\\t\\t\\t\\tconst x = this.getProp('x');\\n\\t\\t\\t\\tconst y = this.getProp('y');\\n\\t\\t\\t\\tconst z = this.getProp('z');\\n\\t\\t\\t\\tconst result = new Float32Array(this.numSplats * 3);\\n\\t\\t\\t\\tfor(let i = 0; i < this.numSplats; ++i){\\n\\t\\t\\t\\t\\t\\tresult[i * 3 + 0] = x[i];\\n\\t\\t\\t\\t\\t\\tresult[i * 3 + 1] = y[i];\\n\\t\\t\\t\\t\\t\\tresult[i * 3 + 2] = z[i];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tcalcFocalPoint(result, pred) {\\n\\t\\t\\t\\tconst x = this.getProp('x');\\n\\t\\t\\t\\tconst y = this.getProp('y');\\n\\t\\t\\t\\tconst z = this.getProp('z');\\n\\t\\t\\t\\tconst sx = this.getProp('scale_0');\\n\\t\\t\\t\\tconst sy = this.getProp('scale_1');\\n\\t\\t\\t\\tconst sz = this.getProp('scale_2');\\n\\t\\t\\t\\tresult.x = 0;\\n\\t\\t\\t\\tresult.y = 0;\\n\\t\\t\\t\\tresult.z = 0;\\n\\t\\t\\t\\tlet sum = 0;\\n\\t\\t\\t\\tfor(let i = 0; i < this.numSplats; ++i){\\n\\t\\t\\t\\t\\t\\tif (pred && !pred(i)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst px = x[i];\\n\\t\\t\\t\\t\\t\\tconst py = y[i];\\n\\t\\t\\t\\t\\t\\tconst pz = z[i];\\n\\t\\t\\t\\t\\t\\tif (!isFinite(px) || !isFinite(py) || !isFinite(pz)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst weight = 1.0 / (1.0 + Math.exp(Math.max(sx[i], sy[i], sz[i])));\\n\\t\\t\\t\\t\\t\\tresult.x += px * weight;\\n\\t\\t\\t\\t\\t\\tresult.y += py * weight;\\n\\t\\t\\t\\t\\t\\tresult.z += pz * weight;\\n\\t\\t\\t\\t\\t\\tsum += weight;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tresult.mulScalar(1 / sum);\\n\\t\\t}\\n\\t\\trenderWireframeBounds(scene, worldMat) {\\n\\t\\t\\t\\tconst p = new Vec3();\\n\\t\\t\\t\\tconst r = new Quat();\\n\\t\\t\\t\\tconst s = new Vec3();\\n\\t\\t\\t\\tconst min = new Vec3();\\n\\t\\t\\t\\tconst max = new Vec3();\\n\\t\\t\\t\\tconst iter = this.createIter(p, r, s);\\n\\t\\t\\t\\tfor(let i = 0; i < this.numSplats; ++i){\\n\\t\\t\\t\\t\\t\\titer.read(i);\\n\\t\\t\\t\\t\\t\\tcalcSplatMat(mat4, p, r);\\n\\t\\t\\t\\t\\t\\tmat4.mul2(worldMat, mat4);\\n\\t\\t\\t\\t\\t\\tmin.set(s.x * -2, s.y * -2, s.z * -2);\\n\\t\\t\\t\\t\\t\\tmax.set(s.x * 2.0, s.y * 2.0, s.z * 2.0);\\n\\t\\t\\t\\t\\t\\tscene.immediate.drawWireAlignedBox(min, max, debugColor, true, scene.defaultDrawLayer, mat4);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget isCompressed() {\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tget shBands() {\\n\\t\\t\\t\\tconst numProps = ()=>{\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < 45; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this.getProp(`f_rest_${i}`)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn i;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn 45;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst sizes = {\\n\\t\\t\\t\\t\\t\\t9: 1,\\n\\t\\t\\t\\t\\t\\t24: 2,\\n\\t\\t\\t\\t\\t\\t45: 3\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\treturn sizes[numProps()] ?? 0;\\n\\t\\t}\\n\\t\\tcalcMortonOrder() {\\n\\t\\t\\t\\tconst calcMinMax = (arr)=>{\\n\\t\\t\\t\\t\\t\\tlet min = arr[0];\\n\\t\\t\\t\\t\\t\\tlet max = arr[0];\\n\\t\\t\\t\\t\\t\\tfor(let i = 1; i < arr.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (arr[i] < min) min = arr[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (arr[i] > max) max = arr[i];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\tmin,\\n\\t\\t\\t\\t\\t\\t\\t\\tmax\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst encodeMorton3 = (x, y, z)=>{\\n\\t\\t\\t\\t\\t\\tconst Part1By2 = (x)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tx &= 0x000003ff;\\n\\t\\t\\t\\t\\t\\t\\t\\tx = (x ^ x << 16) & 0xff0000ff;\\n\\t\\t\\t\\t\\t\\t\\t\\tx = (x ^ x << 8) & 0x0300f00f;\\n\\t\\t\\t\\t\\t\\t\\t\\tx = (x ^ x << 4) & 0x030c30c3;\\n\\t\\t\\t\\t\\t\\t\\t\\tx = (x ^ x << 2) & 0x09249249;\\n\\t\\t\\t\\t\\t\\t\\t\\treturn x;\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\treturn (Part1By2(z) << 2) + (Part1By2(y) << 1) + Part1By2(x);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst x = this.getProp('x');\\n\\t\\t\\t\\tconst y = this.getProp('y');\\n\\t\\t\\t\\tconst z = this.getProp('z');\\n\\t\\t\\t\\tconst { min: minX, max: maxX } = calcMinMax(x);\\n\\t\\t\\t\\tconst { min: minY, max: maxY } = calcMinMax(y);\\n\\t\\t\\t\\tconst { min: minZ, max: maxZ } = calcMinMax(z);\\n\\t\\t\\t\\tconst sizeX = minX === maxX ? 0 : 1024 / (maxX - minX);\\n\\t\\t\\t\\tconst sizeY = minY === maxY ? 0 : 1024 / (maxY - minY);\\n\\t\\t\\t\\tconst sizeZ = minZ === maxZ ? 0 : 1024 / (maxZ - minZ);\\n\\t\\t\\t\\tconst codes = new Map();\\n\\t\\t\\t\\tfor(let i = 0; i < this.numSplats; i++){\\n\\t\\t\\t\\t\\t\\tconst ix = Math.min(1023, Math.floor((x[i] - minX) * sizeX));\\n\\t\\t\\t\\t\\t\\tconst iy = Math.min(1023, Math.floor((y[i] - minY) * sizeY));\\n\\t\\t\\t\\t\\t\\tconst iz = Math.min(1023, Math.floor((z[i] - minZ) * sizeZ));\\n\\t\\t\\t\\t\\t\\tconst code = encodeMorton3(ix, iy, iz);\\n\\t\\t\\t\\t\\t\\tconst val = codes.get(code);\\n\\t\\t\\t\\t\\t\\tif (val) {\\n\\t\\t\\t\\t\\t\\t\\t\\tval.push(i);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tcodes.set(code, [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ti\\n\\t\\t\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst keys = Array.from(codes.keys()).sort((a, b)=>a - b);\\n\\t\\t\\t\\tconst indices = new Uint32Array(this.numSplats);\\n\\t\\t\\t\\tlet idx = 0;\\n\\t\\t\\t\\tfor(let i = 0; i < keys.length; ++i){\\n\\t\\t\\t\\t\\t\\tconst val = codes.get(keys[i]);\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j < val.length; ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\tindices[idx++] = val[j];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn indices;\\n\\t\\t}\\n\\t\\treorder(order) {\\n\\t\\t\\t\\tconst cache = new Map();\\n\\t\\t\\t\\tconst getStorage = (size)=>{\\n\\t\\t\\t\\t\\t\\tif (cache.has(size)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst buffer = cache.get(size);\\n\\t\\t\\t\\t\\t\\t\\t\\tcache.delete(size);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn buffer;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn new ArrayBuffer(size);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst returnStorage = (buffer)=>{\\n\\t\\t\\t\\t\\t\\tcache.set(buffer.byteLength, buffer);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst reorder = (data)=>{\\n\\t\\t\\t\\t\\t\\tconst result = new data.constructor(getStorage(data.byteLength));\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < order.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tresult[i] = data[order[i]];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturnStorage(data.buffer);\\n\\t\\t\\t\\t\\t\\treturn result;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.elements.forEach((element)=>{\\n\\t\\t\\t\\t\\t\\telement.properties.forEach((property)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (property.storage) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tproperty.storage = reorder(property.storage);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\treorderData() {\\n\\t\\t\\t\\tthis.reorder(this.calcMortonOrder());\\n\\t\\t}\\n\\t\\tconstructor(elements, comments = []){\\n\\t\\t\\t\\tthis.elements = elements;\\n\\t\\t\\t\\tthis.numSplats = this.getElement('vertex').count;\\n\\t\\t\\t\\tthis.comments = comments;\\n\\t\\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\\t\\tfor(const key in values){\\n\\t\\t\\t\\tscope.resolve(key).setValue(values[key]);\\n\\t\\t}\\n};\\nclass CustomRenderPass extends RenderPass {\\n\\t\\texecute() {\\n\\t\\t\\t\\tthis.executeCallback?.();\\n\\t\\t}\\n\\t\\tconstructor(...args){\\n\\t\\t\\t\\tsuper(...args), this.executeCallback = null;\\n\\t\\t}\\n}\\nconst invModelMat$1 = new Mat4();\\nconst dir$1 = new Vec3();\\nclass GSplatResolveSH {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tconst { gsplatInstance } = this;\\n\\t\\t\\t\\tconst { material } = gsplatInstance;\\n\\t\\t\\t\\tmaterial.setDefine('SH_BANDS', gsplatInstance.resource.gsplatData.shBands.toString());\\n\\t\\t\\t\\tconst { shaderChunks } = material;\\n\\t\\t\\t\\tshaderChunks.glsl.delete('gsplatSogColorVS');\\n\\t\\t\\t\\tshaderChunks.wgsl.delete('gsplatSogColorVS');\\n\\t\\t\\t\\tmaterial.update();\\n\\t\\t\\t\\tthis.quadRender.destroy();\\n\\t\\t\\t\\tthis.renderPass.destroy();\\n\\t\\t\\t\\tthis.renderTarget.destroy();\\n\\t\\t\\t\\tthis.texture.destroy();\\n\\t\\t\\t\\tthis.shader.destroy();\\n\\t\\t}\\n\\t\\trender(camera, modelMat) {\\n\\t\\t\\t\\tconst { prevDir, updateMode } = this;\\n\\t\\t\\t\\tif (updateMode === 'disable') {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tinvModelMat$1.invert(modelMat);\\n\\t\\t\\t\\tinvModelMat$1.transformVector(camera.forward, dir$1);\\n\\t\\t\\t\\tdir$1.normalize();\\n\\t\\t\\t\\tif (updateMode === 'enable' && dir$1.equalsApprox(prevDir, 1e-3)) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tprevDir.copy(dir$1);\\n\\t\\t\\t\\tconst execute = ()=>{\\n\\t\\t\\t\\t\\t\\tconst { device } = this;\\n\\t\\t\\t\\t\\t\\tconst { sh_centroids, meta } = this.gsplatInstance.resource.gsplatData;\\n\\t\\t\\t\\t\\t\\tresolve$1(device.scope, {\\n\\t\\t\\t\\t\\t\\t\\t\\tdir: dir$1.toArray(),\\n\\t\\t\\t\\t\\t\\t\\t\\tcentroids: sh_centroids,\\n\\t\\t\\t\\t\\t\\t\\t\\tshN_mins: meta.shN.mins,\\n\\t\\t\\t\\t\\t\\t\\t\\tshN_maxs: meta.shN.maxs\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tdevice.setCullMode(CULLFACE_NONE);\\n\\t\\t\\t\\t\\t\\tdevice.setDepthState(DepthState.NODEPTH);\\n\\t\\t\\t\\t\\t\\tdevice.setStencilState(null, null);\\n\\t\\t\\t\\t\\t\\tdevice.setBlendState(BlendState.NOBLEND);\\n\\t\\t\\t\\t\\t\\tthis.quadRender.render();\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.renderPass.executeCallback = execute;\\n\\t\\t\\t\\tthis.renderPass.render();\\n\\t\\t}\\n\\t\\tconstructor(device, gsplatInstance){\\n\\t\\t\\t\\tthis.prevDir = new Vec3();\\n\\t\\t\\t\\tthis.updateMode = 'enable';\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.gsplatInstance = gsplatInstance;\\n\\t\\t\\t\\tconst { resource } = gsplatInstance;\\n\\t\\t\\t\\tconst includes = new Map(ShaderChunks.get(device, device.isWebGPU ? 'wgsl' : 'glsl'));\\n\\t\\t\\t\\tthis.shader = ShaderUtils.createShader(device, {\\n\\t\\t\\t\\t\\t\\tuniqueName: 'gsplatResolveSH',\\n\\t\\t\\t\\t\\t\\tvertexGLSL,\\n\\t\\t\\t\\t\\t\\tfragmentGLSL,\\n\\t\\t\\t\\t\\t\\tvertexWGSL,\\n\\t\\t\\t\\t\\t\\tfragmentWGSL,\\n\\t\\t\\t\\t\\t\\tvertexIncludes: includes,\\n\\t\\t\\t\\t\\t\\tfragmentIncludes: includes,\\n\\t\\t\\t\\t\\t\\tfragmentDefines: new Map([\\n\\t\\t\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t'SH_BANDS',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresource.gsplatData.shBands.toString()\\n\\t\\t\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t\\t\\t]),\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.texture = resource.streams.createTexture('centroids', PIXELFORMAT_RGBA8, new Vec2(64, 1024));\\n\\t\\t\\t\\tthis.renderTarget = new RenderTarget({\\n\\t\\t\\t\\t\\t\\tcolorBuffer: this.texture,\\n\\t\\t\\t\\t\\t\\tdepth: false\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.renderPass = new CustomRenderPass(device);\\n\\t\\t\\t\\tthis.renderPass.init(this.renderTarget, {});\\n\\t\\t\\t\\tthis.renderPass.colorOps.clear = true;\\n\\t\\t\\t\\tthis.quadRender = new QuadRender(this.shader);\\n\\t\\t\\t\\tconst { material } = gsplatInstance;\\n\\t\\t\\t\\tmaterial.setDefine('SH_BANDS', '0');\\n\\t\\t\\t\\tconst { shaderChunks } = material;\\n\\t\\t\\t\\tshaderChunks.glsl.set('gsplatSogColorVS', gsplatSogColorGLSL);\\n\\t\\t\\t\\tshaderChunks.wgsl.set('gsplatSogColorVS', gsplatSogColorWGSL);\\n\\t\\t\\t\\tmaterial.update();\\n\\t\\t\\t\\tdevice.scope.resolve('sh_result').setValue(this.texture);\\n\\t\\t}\\n}\\n\\nfunction SortWorker() {\\n\\t\\tconst myself = typeof self !== 'undefined' && self || require('node:worker_threads').parentPort;\\n\\t\\tlet order;\\n\\t\\tlet centers;\\n\\t\\tlet chunks;\\n\\t\\tlet mapping;\\n\\t\\tlet cameraPosition;\\n\\t\\tlet cameraDirection;\\n\\t\\tlet forceUpdate = false;\\n\\t\\tconst lastCameraPosition = {\\n\\t\\t\\t\\tx: 0,\\n\\t\\t\\t\\ty: 0,\\n\\t\\t\\t\\tz: 0\\n\\t\\t};\\n\\t\\tconst lastCameraDirection = {\\n\\t\\t\\t\\tx: 0,\\n\\t\\t\\t\\ty: 0,\\n\\t\\t\\t\\tz: 0\\n\\t\\t};\\n\\t\\tconst boundMin = {\\n\\t\\t\\t\\tx: 0,\\n\\t\\t\\t\\ty: 0,\\n\\t\\t\\t\\tz: 0\\n\\t\\t};\\n\\t\\tconst boundMax = {\\n\\t\\t\\t\\tx: 0,\\n\\t\\t\\t\\ty: 0,\\n\\t\\t\\t\\tz: 0\\n\\t\\t};\\n\\t\\tlet distances;\\n\\t\\tlet countBuffer;\\n\\t\\tconst numBins = 32;\\n\\t\\tconst binCount = new Array(numBins).fill(0);\\n\\t\\tconst binBase = new Array(numBins).fill(0);\\n\\t\\tconst binDivider = new Array(numBins).fill(0);\\n\\t\\tconst binarySearch = (m, n, compare_fn)=>{\\n\\t\\t\\t\\twhile(m <= n){\\n\\t\\t\\t\\t\\t\\tconst k = n + m >> 1;\\n\\t\\t\\t\\t\\t\\tconst cmp = compare_fn(k);\\n\\t\\t\\t\\t\\t\\tif (cmp > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tm = k + 1;\\n\\t\\t\\t\\t\\t\\t} else if (cmp < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tn = k - 1;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn k;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn ~m;\\n\\t\\t};\\n\\t\\tconst update = ()=>{\\n\\t\\t\\t\\tif (!order || !centers || centers.length === 0 || !cameraPosition || !cameraDirection) return;\\n\\t\\t\\t\\tconst sortStartTime = performance.now();\\n\\t\\t\\t\\tconst px = cameraPosition.x;\\n\\t\\t\\t\\tconst py = cameraPosition.y;\\n\\t\\t\\t\\tconst pz = cameraPosition.z;\\n\\t\\t\\t\\tconst dx = cameraDirection.x;\\n\\t\\t\\t\\tconst dy = cameraDirection.y;\\n\\t\\t\\t\\tconst dz = cameraDirection.z;\\n\\t\\t\\t\\tconst epsilon = 0.001;\\n\\t\\t\\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\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tforceUpdate = false;\\n\\t\\t\\t\\tlastCameraPosition.x = px;\\n\\t\\t\\t\\tlastCameraPosition.y = py;\\n\\t\\t\\t\\tlastCameraPosition.z = pz;\\n\\t\\t\\t\\tlastCameraDirection.x = dx;\\n\\t\\t\\t\\tlastCameraDirection.y = dy;\\n\\t\\t\\t\\tlastCameraDirection.z = dz;\\n\\t\\t\\t\\tlet minDist;\\n\\t\\t\\t\\tlet maxDist;\\n\\t\\t\\t\\tfor(let i = 0; i < 8; ++i){\\n\\t\\t\\t\\t\\t\\tconst x = i & 1 ? boundMin.x : boundMax.x;\\n\\t\\t\\t\\t\\t\\tconst y = i & 2 ? boundMin.y : boundMax.y;\\n\\t\\t\\t\\t\\t\\tconst z = i & 4 ? boundMin.z : boundMax.z;\\n\\t\\t\\t\\t\\t\\tconst d = x * dx + y * dy + z * dz;\\n\\t\\t\\t\\t\\t\\tif (i === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tminDist = maxDist = d;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tminDist = Math.min(minDist, d);\\n\\t\\t\\t\\t\\t\\t\\t\\tmaxDist = Math.max(maxDist, d);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst numVertices = centers.length / 3;\\n\\t\\t\\t\\tconst compareBits = Math.max(10, Math.min(20, Math.round(Math.log2(numVertices / 4))));\\n\\t\\t\\t\\tconst bucketCount = 2 ** compareBits + 1;\\n\\t\\t\\t\\tif (distances?.length !== numVertices) {\\n\\t\\t\\t\\t\\t\\tdistances = new Uint32Array(numVertices);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!countBuffer || countBuffer.length !== bucketCount) {\\n\\t\\t\\t\\t\\t\\tcountBuffer = new Uint32Array(bucketCount);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tcountBuffer.fill(0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst range = maxDist - minDist;\\n\\t\\t\\t\\tif (range < 1e-6) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < numVertices; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tdistances[i] = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tcountBuffer[0]++;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst numChunks = chunks.length / 4;\\n\\t\\t\\t\\t\\t\\tbinCount.fill(0);\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < numChunks; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst x = chunks[i * 4 + 0];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst y = chunks[i * 4 + 1];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst z = chunks[i * 4 + 2];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst r = chunks[i * 4 + 3];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst d = x * dx + y * dy + z * dz - minDist;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst binMin = Math.max(0, Math.floor((d - r) * numBins / range));\\n\\t\\t\\t\\t\\t\\t\\t\\tconst binMax = Math.min(numBins, Math.ceil((d + r) * numBins / range));\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = binMin; j < binMax; ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbinCount[j]++;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst binTotal = binCount.reduce((a, b)=>a + b, 0);\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < numBins; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tbinDivider[i] = binCount[i] / binTotal * bucketCount >>> 0;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < numBins; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tbinBase[i] = i === 0 ? 0 : binBase[i - 1] + binDivider[i - 1];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst binRange = range / numBins;\\n\\t\\t\\t\\t\\t\\tlet ii = 0;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < numVertices; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst x = centers[ii++];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst y = centers[ii++];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst z = centers[ii++];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst d = (x * dx + y * dy + z * dz - minDist) / binRange;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst bin = d >>> 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst sortKey = binBase[bin] + binDivider[bin] * (d - bin) >>> 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tdistances[i] = sortKey;\\n\\t\\t\\t\\t\\t\\t\\t\\tcountBuffer[sortKey]++;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 1; i < bucketCount; i++){\\n\\t\\t\\t\\t\\t\\tcountBuffer[i] += countBuffer[i - 1];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < numVertices; i++){\\n\\t\\t\\t\\t\\t\\tconst distance = distances[i];\\n\\t\\t\\t\\t\\t\\tconst destIndex = --countBuffer[distance];\\n\\t\\t\\t\\t\\t\\torder[destIndex] = i;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst cameraDist = px * dx + py * dy + pz * dz;\\n\\t\\t\\t\\tconst dist = (i)=>{\\n\\t\\t\\t\\t\\t\\tlet o = order[i] * 3;\\n\\t\\t\\t\\t\\t\\treturn centers[o++] * dx + centers[o++] * dy + centers[o] * dz - cameraDist;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst findZero = ()=>{\\n\\t\\t\\t\\t\\t\\tconst result = binarySearch(0, numVertices - 1, (i)=>-dist(i));\\n\\t\\t\\t\\t\\t\\treturn Math.min(numVertices, Math.abs(result));\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst count = dist(numVertices - 1) >= 0 ? findZero() : numVertices;\\n\\t\\t\\t\\tif (mapping) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < numVertices; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\torder[i] = mapping[order[i]];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tmyself.postMessage({\\n\\t\\t\\t\\t\\t\\torder: order.buffer,\\n\\t\\t\\t\\t\\t\\tcount,\\n\\t\\t\\t\\t\\t\\tsortTime: performance.now() - sortStartTime\\n\\t\\t\\t\\t}, [\\n\\t\\t\\t\\t\\t\\torder.buffer\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\torder = null;\\n\\t\\t};\\n\\t\\tmyself.addEventListener('message', (message)=>{\\n\\t\\t\\t\\tconst msgData = message.data ?? message;\\n\\t\\t\\t\\tif (msgData.order) {\\n\\t\\t\\t\\t\\t\\torder = new Uint32Array(msgData.order);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (msgData.centers) {\\n\\t\\t\\t\\t\\t\\tcenters = new Float32Array(msgData.centers);\\n\\t\\t\\t\\t\\t\\tforceUpdate = true;\\n\\t\\t\\t\\t\\t\\tif (msgData.chunks) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst chunksSrc = new Float32Array(msgData.chunks);\\n\\t\\t\\t\\t\\t\\t\\t\\tchunks = new Float32Array(msgData.chunks, 0, chunksSrc.length * 4 / 6);\\n\\t\\t\\t\\t\\t\\t\\t\\tboundMin.x = chunksSrc[0];\\n\\t\\t\\t\\t\\t\\t\\t\\tboundMin.y = chunksSrc[1];\\n\\t\\t\\t\\t\\t\\t\\t\\tboundMin.z = chunksSrc[2];\\n\\t\\t\\t\\t\\t\\t\\t\\tboundMax.x = chunksSrc[3];\\n\\t\\t\\t\\t\\t\\t\\t\\tboundMax.y = chunksSrc[4];\\n\\t\\t\\t\\t\\t\\t\\t\\tboundMax.z = chunksSrc[5];\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < chunksSrc.length / 6; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst mx = chunksSrc[i * 6 + 0];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst my = chunksSrc[i * 6 + 1];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst mz = chunksSrc[i * 6 + 2];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst Mx = chunksSrc[i * 6 + 3];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst My = chunksSrc[i * 6 + 4];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst Mz = chunksSrc[i * 6 + 5];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tchunks[i * 4 + 0] = (mx + Mx) * 0.5;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tchunks[i * 4 + 1] = (my + My) * 0.5;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tchunks[i * 4 + 2] = (mz + Mz) * 0.5;\\n\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\tif (mx < boundMin.x) boundMin.x = mx;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (my < boundMin.y) boundMin.y = my;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (mz < boundMin.z) boundMin.z = mz;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (Mx > boundMax.x) boundMax.x = Mx;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (My > boundMax.y) boundMax.y = My;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (Mz > boundMax.z) boundMax.z = Mz;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst numVertices = centers.length / 3;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst numChunks = Math.ceil(numVertices / 256);\\n\\t\\t\\t\\t\\t\\t\\t\\tchunks = new Float32Array(numChunks * 4);\\n\\t\\t\\t\\t\\t\\t\\t\\tboundMin.x = boundMin.y = boundMin.z = Infinity;\\n\\t\\t\\t\\t\\t\\t\\t\\tboundMax.x = boundMax.y = boundMax.z = -Infinity;\\n\\t\\t\\t\\t\\t\\t\\t\\tlet mx, my, mz, Mx, My, Mz;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let c = 0; c < numChunks; ++c){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmx = my = mz = Infinity;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tMx = My = Mz = -Infinity;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst start = c * 256;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst end = Math.min(numVertices, (c + 1) * 256);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = start; i < end; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst x = centers[i * 3 + 0];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst y = centers[i * 3 + 1];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst z = centers[i * 3 + 2];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst validX = Number.isFinite(x);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst validY = Number.isFinite(y);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst validZ = Number.isFinite(z);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!validX) centers[i * 3 + 0] = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!validY) centers[i * 3 + 1] = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!validZ) centers[i * 3 + 2] = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!validX || !validY || !validZ) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (x < mx) mx = x;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\telse if (x > Mx) Mx = x;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (y < my) my = y;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\telse if (y > My) My = y;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (z < mz) mz = z;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\telse if (z > Mz) Mz = z;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (x < boundMin.x) boundMin.x = x;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\telse if (x > boundMax.x) boundMax.x = x;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (y < boundMin.y) boundMin.y = y;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\telse if (y > boundMax.y) boundMax.y = y;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (z < boundMin.z) boundMin.z = z;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\telse if (z > boundMax.z) boundMax.z = z;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tchunks[c * 4 + 0] = (mx + Mx) * 0.5;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tchunks[c * 4 + 1] = (my + My) * 0.5;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tchunks[c * 4 + 2] = (mz + Mz) * 0.5;\\n\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (msgData.hasOwnProperty('mapping')) {\\n\\t\\t\\t\\t\\t\\tmapping = msgData.mapping ? new Uint32Array(msgData.mapping) : null;\\n\\t\\t\\t\\t\\t\\tforceUpdate = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (msgData.cameraPosition) cameraPosition = msgData.cameraPosition;\\n\\t\\t\\t\\tif (msgData.cameraDirection) cameraDirection = msgData.cameraDirection;\\n\\t\\t\\t\\tupdate();\\n\\t\\t});\\n}\\n\\nclass GSplatSorter extends EventHandler {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.worker.terminate();\\n\\t\\t\\t\\tthis.worker = null;\\n\\t\\t}\\n\\t\\tinit(orderTexture, centers, chunks) {\\n\\t\\t\\t\\tthis.orderTexture = orderTexture;\\n\\t\\t\\t\\tthis.centers = centers.slice();\\n\\t\\t\\t\\tconst orderBuffer = this.orderTexture.lock({\\n\\t\\t\\t\\t\\t\\tmode: TEXTURELOCK_READ\\n\\t\\t\\t\\t}).slice();\\n\\t\\t\\t\\tthis.orderTexture.unlock();\\n\\t\\t\\t\\tfor(let i = 0; i < orderBuffer.length; ++i){\\n\\t\\t\\t\\t\\t\\torderBuffer[i] = i;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst obj = {\\n\\t\\t\\t\\t\\t\\torder: orderBuffer.buffer,\\n\\t\\t\\t\\t\\t\\tcenters: centers.buffer,\\n\\t\\t\\t\\t\\t\\tchunks: chunks?.buffer\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst transfer = [\\n\\t\\t\\t\\t\\t\\torderBuffer.buffer,\\n\\t\\t\\t\\t\\t\\tcenters.buffer\\n\\t\\t\\t\\t].concat(chunks ? [\\n\\t\\t\\t\\t\\t\\tchunks.buffer\\n\\t\\t\\t\\t] : []);\\n\\t\\t\\t\\tthis.worker.postMessage(obj, transfer);\\n\\t\\t}\\n\\t\\tsetMapping(mapping) {\\n\\t\\t\\t\\tif (mapping) {\\n\\t\\t\\t\\t\\t\\tconst centers = new Float32Array(mapping.length * 3);\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < mapping.length; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst src = mapping[i] * 3;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dst = i * 3;\\n\\t\\t\\t\\t\\t\\t\\t\\tcenters[dst + 0] = this.centers[src + 0];\\n\\t\\t\\t\\t\\t\\t\\t\\tcenters[dst + 1] = this.centers[src + 1];\\n\\t\\t\\t\\t\\t\\t\\t\\tcenters[dst + 2] = this.centers[src + 2];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.worker.postMessage({\\n\\t\\t\\t\\t\\t\\t\\t\\tcenters: centers.buffer,\\n\\t\\t\\t\\t\\t\\t\\t\\tmapping: mapping.buffer\\n\\t\\t\\t\\t\\t\\t}, [\\n\\t\\t\\t\\t\\t\\t\\t\\tcenters.buffer,\\n\\t\\t\\t\\t\\t\\t\\t\\tmapping.buffer\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst centers = this.centers.slice();\\n\\t\\t\\t\\t\\t\\tthis.worker.postMessage({\\n\\t\\t\\t\\t\\t\\t\\t\\tcenters: centers.buffer,\\n\\t\\t\\t\\t\\t\\t\\t\\tmapping: null\\n\\t\\t\\t\\t\\t\\t}, [\\n\\t\\t\\t\\t\\t\\t\\t\\tcenters.buffer\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetCamera(pos, dir) {\\n\\t\\t\\t\\tthis.worker.postMessage({\\n\\t\\t\\t\\t\\t\\tcameraPosition: {\\n\\t\\t\\t\\t\\t\\t\\t\\tx: pos.x,\\n\\t\\t\\t\\t\\t\\t\\t\\ty: pos.y,\\n\\t\\t\\t\\t\\t\\t\\t\\tz: pos.z\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tcameraDirection: {\\n\\t\\t\\t\\t\\t\\t\\t\\tx: dir.x,\\n\\t\\t\\t\\t\\t\\t\\t\\ty: dir.y,\\n\\t\\t\\t\\t\\t\\t\\t\\tz: dir.z\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tconstructor(scene){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.scene = scene ?? null;\\n\\t\\t\\t\\tconst messageHandler = (message)=>{\\n\\t\\t\\t\\t\\t\\tconst msgData = message.data ?? message;\\n\\t\\t\\t\\t\\t\\tif (this.scene && msgData.sortTime !== undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.scene.fire('gsplat:sorted', msgData.sortTime);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst newOrder = msgData.order;\\n\\t\\t\\t\\t\\t\\tconst oldOrder = this.orderTexture._levels[0].buffer;\\n\\t\\t\\t\\t\\t\\tthis.worker.postMessage({\\n\\t\\t\\t\\t\\t\\t\\t\\torder: oldOrder\\n\\t\\t\\t\\t\\t\\t}, [\\n\\t\\t\\t\\t\\t\\t\\t\\toldOrder\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\tthis.orderTexture._levels[0] = new Uint32Array(newOrder);\\n\\t\\t\\t\\t\\t\\tthis.orderTexture.upload();\\n\\t\\t\\t\\t\\t\\tthis.fire('updated', msgData.count);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst workerSource = `(${SortWorker.toString()})()`;\\n\\t\\t\\t\\tif (platform.environment === 'node') {\\n\\t\\t\\t\\t\\t\\tthis.worker = new Worker(workerSource, {\\n\\t\\t\\t\\t\\t\\t\\t\\teval: true\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tthis.worker.on('message', messageHandler);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.worker = new Worker(URL.createObjectURL(new Blob([\\n\\t\\t\\t\\t\\t\\t\\t\\tworkerSource\\n\\t\\t\\t\\t\\t\\t], {\\n\\t\\t\\t\\t\\t\\t\\t\\ttype: \\\"application/javascript\\\"\\n\\t\\t\\t\\t\\t\\t})));\\n\\t\\t\\t\\t\\t\\tthis.worker.addEventListener('message', messageHandler);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nvar glslGsplatSogReorderPS = `\\n#include \\\"gsplatPackingPS\\\"\\nuniform highp sampler2D means_l;\\nuniform highp sampler2D means_u;\\nuniform highp sampler2D quats;\\nuniform highp sampler2D scales;\\nuniform highp sampler2D sh0;\\nuniform highp sampler2D sh_labels;\\nuniform highp uint numSplats;\\n#ifdef REORDER_V1\\n\\tfloat sigmoid(float x) { return 1.0 / (1.0 + exp(-x)); }\\n\\tvec3 vmin(vec3 v) { return vec3(min(min(v.x, v.y), v.z)); }\\n\\tvec3 vmax(vec3 v) { return vec3(max(max(v.x, v.y), v.z)); }\\n\\tvec3 resolve(vec3 m, vec3 M, vec3 v) { return (mix(m, M, v) - vmin(m)) / (vmax(M) - vmin(m)); }\\n\\t\\n\\tuniform vec3 scalesMins;\\n\\tuniform vec3 scalesMaxs;\\n\\tuniform vec4 sh0Mins;\\n\\tuniform vec4 sh0Maxs;\\n#else\\n\\tuniform vec4 scales_codebook[64];\\n\\tuniform vec4 sh0_codebook[64];\\n#endif\\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 meansLSample   = texelFetch(means_l, uv, 0).xyz;\\n\\tvec3 meansUSample   = texelFetch(means_u, uv, 0).xyz;\\n\\tvec4 quatsSample\\t= texelFetch(quats, uv, 0);\\n\\tvec3 scalesSample   = texelFetch(scales, uv, 0).xyz;\\n\\tvec4 sh0Sample\\t  = texelFetch(sh0, uv, 0);\\n\\tvec2 shLabelsSample = texelFetch(sh_labels, uv, 0).xy;\\n\\t#ifdef REORDER_V1\\n\\t\\tuint scale = pack101010(resolve(scalesMins, scalesMaxs, scalesSample));\\n\\t\\tuint sh0 = pack111110(resolve(sh0Mins.xyz, sh0Maxs.xyz, sh0Sample.xyz));\\n\\t\\tfloat alpha = sigmoid(mix(sh0Mins.w, sh0Maxs.w, sh0Sample.w));\\n\\t#else\\n\\t\\tuint scale = pack101010(resolveCodebook(scalesSample, scales_codebook));\\n\\t\\tuint sh0 = pack111110(resolveCodebook(sh0Sample.xyz, sh0_codebook));\\n\\t\\tfloat alpha = sh0Sample.w;\\n\\t#endif\\n\\tuint qmode = uint(quatsSample.w * 255.0) - 252u;\\n\\tpcFragColor0 = uvec4(\\n\\t\\tpack8888(vec4(meansLSample, shLabelsSample.x)),\\n\\t\\tpack8888(vec4(meansUSample, shLabelsSample.y)),\\n\\t\\tpack8888(vec4(quatsSample.xyz, alpha)),\\n\\t\\t(scale << 2u) | qmode\\n\\t);\\n\\tpcFragColor1 = unpack8888(sh0);\\n}\\n`;\\n\\nvar wgslGsplatSogReorderPS = `\\n#include \\\"gsplatPackingPS\\\"\\nvar means_l: texture_2d<f32>;\\nvar means_u: texture_2d<f32>;\\nvar quats: texture_2d<f32>;\\nvar scales: texture_2d<f32>;\\nvar sh0: texture_2d<f32>;\\nvar sh_labels: texture_2d<f32>;\\nuniform numSplats: u32;\\n#ifdef REORDER_V1\\n\\tfn sigmoid(x: f32) -> f32 { return 1.0 / (1.0 + exp(-x)); }\\n\\tfn vmin(v: vec3f) -> vec3f { return vec3f(min(min(v.x, v.y), v.z)); }\\n\\tfn vmax(v: vec3f) -> vec3f { return vec3f(max(max(v.x, v.y), v.z)); }\\n\\tfn resolve(m: vec3f, M: vec3f, v: vec3f) -> vec3f { return (mix(m, M, v) - vmin(m)) / (vmax(M) - vmin(m)); }\\n\\tuniform scalesMins: vec3f;\\n\\tuniform scalesMaxs: vec3f;\\n\\tuniform sh0Mins: vec4f;\\n\\tuniform sh0Maxs: vec4f;\\n#else\\n\\tuniform scales_codebook: array<vec4f, 64>;\\n\\tuniform sh0_codebook: array<vec4f, 64>;\\n#endif\\n@fragment\\nfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\tvar output: FragmentOutput;\\n\\tlet w: u32 = textureDimensions(means_l, 0).x;\\n\\tlet uv: vec2<u32> = vec2<u32>(input.position.xy);\\n\\tif (uv.x + uv.y * w >= uniform.numSplats) {\\n\\t\\tdiscard;\\n\\t\\treturn output;\\n\\t}\\n\\tlet meansLSample: vec3<f32> = textureLoad(means_l, uv, 0).xyz;\\n\\tlet meansUSample: vec3<f32> = textureLoad(means_u, uv, 0).xyz;\\n\\tlet quatsSample: vec4<f32> = textureLoad(quats, uv, 0);\\n\\tlet scalesSample: vec3<f32> = textureLoad(scales, uv, 0).xyz;\\n\\tlet sh0Sample: vec4f = textureLoad(sh0, uv, 0);\\n\\tlet shLabelsSample: vec2<f32> = textureLoad(sh_labels, uv, 0).xy;\\n\\t#ifdef REORDER_V1\\n\\t\\tlet scale = pack101010(resolve(uniform.scalesMins, uniform.scalesMaxs, scalesSample));\\n\\t\\tlet sh0 = pack111110(resolve(uniform.sh0Mins.xyz, uniform.sh0Maxs.xyz, sh0Sample.xyz));\\n\\t\\tlet alpha = sigmoid(mix(uniform.sh0Mins.w, uniform.sh0Maxs.w, sh0Sample.w));\\n\\t#else\\n\\t\\tlet scalesIdx = vec3u(scalesSample * 255.0);\\n\\t\\tlet scalesV = vec3f(\\n\\t\\t\\tuniform.scales_codebook[scalesIdx.x >> 2u][scalesIdx.x & 3u],\\n\\t\\t\\tuniform.scales_codebook[scalesIdx.y >> 2u][scalesIdx.y & 3u],\\n\\t\\t\\tuniform.scales_codebook[scalesIdx.z >> 2u][scalesIdx.z & 3u]\\n\\t\\t);\\n\\t\\tlet scale = pack101010((scalesV - uniform.scales_codebook[0].x) / (uniform.scales_codebook[63].w - uniform.scales_codebook[0].x));\\n\\t\\tlet sh0Idx = vec3u(sh0Sample.xyz * 255.0);\\n\\t\\tlet sh0V = vec3f(\\n\\t\\t\\tuniform.sh0_codebook[sh0Idx.x >> 2u][sh0Idx.x & 3u],\\n\\t\\t\\tuniform.sh0_codebook[sh0Idx.y >> 2u][sh0Idx.y & 3u],\\n\\t\\t\\tuniform.sh0_codebook[sh0Idx.z >> 2u][sh0Idx.z & 3u]\\n\\t\\t);\\n\\t\\tlet sh0 = pack111110((sh0V - uniform.sh0_codebook[0].x) / (uniform.sh0_codebook[63].w - uniform.sh0_codebook[0].x));\\n\\t\\tlet alpha = sh0Sample.w;\\n\\t#endif\\n\\tlet qmode = u32(quatsSample.w * 255.0) - 252u;\\n\\toutput.color = vec4u(\\n\\t\\tpack8888(vec4f(meansLSample, shLabelsSample.x)),\\n\\t\\tpack8888(vec4f(meansUSample, shLabelsSample.y)),\\n\\t\\tpack8888(vec4f(quatsSample.xyz, alpha)),\\n\\t\\t(scale << 2u) | qmode\\n\\t);\\n\\toutput.color1 = unpack8888(sh0);\\n\\treturn output;\\n}\\n`;\\n\\nvar glslGsplatSogReorderSh = `\\n#include \\\"gsplatPackingPS\\\"\\nuniform highp sampler2D sh_centroids;\\nuniform vec4 shN_codebook[64];\\nvoid main(void) {\\n\\tivec2 uv = ivec2(gl_FragCoord.xy);\\n\\tvec3 shNSample = texelFetch(sh_centroids, uv, 0).xyz;\\n#ifdef REORDER_V1\\n\\tpcFragColor0 = unpack8888(pack111110(shNSample));\\n#else\\n\\tpcFragColor0 = unpack8888(pack111110(resolveCodebook(shNSample, shN_codebook)));\\n#endif\\n}\\n`;\\n\\nvar gsplatPackingPS$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 wgslGsplatSogReorderSH = `\\n#include \\\"gsplatPackingPS\\\"\\nvar sh_centroids: texture_2d<f32>;\\nuniform shN_codebook: array<vec4f, 64>;\\n@fragment\\nfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\tvar output: FragmentOutput;\\n\\tvar uv = vec2i(input.position.xy);\\n\\tvar shNSample = textureLoad(sh_centroids, uv, 0).xyz;\\n#ifdef REORDER_V1\\n\\toutput.color = unpack8888(pack111110(shNSample));\\n#else\\n\\tlet shNIdx = vec3u(shNSample * 255.0);\\n\\tlet shNV = vec3f(\\n\\t\\tuniform.shN_codebook[shNIdx.x >> 2u][shNIdx.x & 3u],\\n\\t\\tuniform.shN_codebook[shNIdx.y >> 2u][shNIdx.y & 3u],\\n\\t\\tuniform.shN_codebook[shNIdx.z >> 2u][shNIdx.z & 3u]\\n\\t);\\n\\toutput.color = unpack8888(pack111110((shNV - uniform.shN_codebook[0].x) / (uniform.shN_codebook[63].w - uniform.shN_codebook[0].x)));\\n#endif\\n\\treturn output;\\n}\\n`;\\n\\nvar gsplatPackingPS = `\\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 glslSogCentersPS = `\\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 wgslSogCentersPS = `\\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\\t\\tif (texture.device.isNull) {\\n\\t\\t\\t\\treturn new Promise((resolve)=>{\\n\\t\\t\\t\\t\\t\\tresolve(new Uint8Array(texture.width * texture.height * 4));\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\treturn texture.read(0, 0, texture.width, texture.height, {\\n\\t\\t\\t\\tmipLevel: 0,\\n\\t\\t\\t\\tface: 0,\\n\\t\\t\\t\\timmediate: true\\n\\t\\t});\\n};\\nconst resolve = (scope, values)=>{\\n\\t\\tfor(const key in values){\\n\\t\\t\\t\\tscope.resolve(key).setValue(values[key]);\\n\\t\\t}\\n};\\nclass GSplatSogIterator {\\n\\t\\tconstructor(data, p, r, s, c, sh){\\n\\t\\t\\t\\tconst lerp = (a, b, t)=>a * (1 - t) + b * t;\\n\\t\\t\\t\\tconst { meta, shBands } = data;\\n\\t\\t\\t\\tconst { means, scales, sh0, shN } = meta;\\n\\t\\t\\t\\tconst means_l_data = p && data.means_l._levels[0];\\n\\t\\t\\t\\tconst means_u_data = p && data.means_u._levels[0];\\n\\t\\t\\t\\tconst quats_data = r && data.quats._levels[0];\\n\\t\\t\\t\\tconst scales_data = s && data.scales._levels[0];\\n\\t\\t\\t\\tconst sh0_data = c && data.sh0._levels[0];\\n\\t\\t\\t\\tconst sh_labels_data = sh && data.sh_labels._levels[0];\\n\\t\\t\\t\\tconst sh_centroids_data = sh && data.sh_centroids._levels[0];\\n\\t\\t\\t\\tconst norm = Math.SQRT2;\\n\\t\\t\\t\\tconst coeffs = {\\n\\t\\t\\t\\t\\t\\t1: 3,\\n\\t\\t\\t\\t\\t\\t2: 8,\\n\\t\\t\\t\\t\\t\\t3: 15\\n\\t\\t\\t\\t}[shBands] ?? 0;\\n\\t\\t\\t\\tthis.read = (i)=>{\\n\\t\\t\\t\\t\\t\\tif (p) {\\n\\t\\t\\t\\t\\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\\t\\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\\t\\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\\t\\t\\t\\t\\tp.x = Math.sign(nx) * (Math.exp(Math.abs(nx)) - 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tp.y = Math.sign(ny) * (Math.exp(Math.abs(ny)) - 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tp.z = Math.sign(nz) * (Math.exp(Math.abs(nz)) - 1);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (r) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst a = (quats_data[i * 4 + 0] / 255 - 0.5) * norm;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst b = (quats_data[i * 4 + 1] / 255 - 0.5) * norm;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst c = (quats_data[i * 4 + 2] / 255 - 0.5) * norm;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst d = Math.sqrt(Math.max(0, 1 - (a * a + b * b + c * c)));\\n\\t\\t\\t\\t\\t\\t\\t\\tconst mode = quats_data[i * 4 + 3] - 252;\\n\\t\\t\\t\\t\\t\\t\\t\\tswitch(mode){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase 0:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tr.set(a, b, c, d);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase 1:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tr.set(d, b, c, a);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase 2:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tr.set(b, d, c, a);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase 3:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tr.set(b, c, d, a);\\n\\t\\t\\t\\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}\\n\\t\\t\\t\\t\\t\\tif (s) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (meta.version === 2) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst sx = scales.codebook[scales_data[i * 4 + 0]];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst sy = scales.codebook[scales_data[i * 4 + 1]];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst sz = scales.codebook[scales_data[i * 4 + 2]];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ts.set(sx, sy, sz);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst sx = lerp(scales.mins[0], scales.maxs[0], scales_data[i * 4 + 0] / 255);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst sy = lerp(scales.mins[1], scales.maxs[1], scales_data[i * 4 + 1] / 255);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst sz = lerp(scales.mins[2], scales.maxs[2], scales_data[i * 4 + 2] / 255);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ts.set(sx, sy, sz);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (c) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (meta.version === 2) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst r = sh0.codebook[sh0_data[i * 4 + 0]];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst g = sh0.codebook[sh0_data[i * 4 + 1]];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst b = sh0.codebook[sh0_data[i * 4 + 2]];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst a = sh0_data[i * 4 + 3] / 255;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tc.set(0.5 + r * SH_C0$1, 0.5 + g * SH_C0$1, 0.5 + b * SH_C0$1, a);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst r = lerp(sh0.mins[0], sh0.maxs[0], sh0_data[i * 4 + 0] / 255);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst g = lerp(sh0.mins[1], sh0.maxs[1], sh0_data[i * 4 + 1] / 255);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst b = lerp(sh0.mins[2], sh0.maxs[2], sh0_data[i * 4 + 2] / 255);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst a = lerp(sh0.mins[3], sh0.maxs[3], sh0_data[i * 4 + 3] / 255);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tc.set(0.5 + r * SH_C0$1, 0.5 + g * SH_C0$1, 0.5 + b * SH_C0$1, 1.0 / (1.0 + Math.exp(-a)));\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (sh) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst n = sh_labels_data[i * 4 + 0] + (sh_labels_data[i * 4 + 1] << 8);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst u = n % 64 * coeffs;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst v = Math.floor(n / 64);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (meta.version === 2) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < 3; ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let k = 0; k < coeffs; ++k){\\n\\t\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < 3; ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let k = 0; k < coeffs; ++k){\\n\\t\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t};\\n\\t\\t}\\n}\\nclass GSplatSogData {\\n\\t\\t_destroyGpuResources() {\\n\\t\\t\\t\\tthis.means_l?.destroy();\\n\\t\\t\\t\\tthis.means_u?.destroy();\\n\\t\\t\\t\\tthis.quats?.destroy();\\n\\t\\t\\t\\tthis.scales?.destroy();\\n\\t\\t\\t\\tthis.sh0?.destroy();\\n\\t\\t\\t\\tthis.sh_centroids?.destroy();\\n\\t\\t\\t\\tthis.sh_labels?.destroy();\\n\\t\\t\\t\\tthis.packedTexture?.destroy();\\n\\t\\t\\t\\tthis.packedSh0?.destroy();\\n\\t\\t\\t\\tthis.packedShN?.destroy();\\n\\t\\t}\\n\\t\\tstatic calcBands(centroidsWidth) {\\n\\t\\t\\t\\tconst shBandsWidths = {\\n\\t\\t\\t\\t\\t\\t192: 1,\\n\\t\\t\\t\\t\\t\\t512: 2,\\n\\t\\t\\t\\t\\t\\t960: 3\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\treturn shBandsWidths[centroidsWidth] ?? 0;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.deviceRestoredEvent?.off();\\n\\t\\t\\t\\tthis.deviceRestoredEvent = null;\\n\\t\\t\\t\\tthis.destroyed = true;\\n\\t\\t\\t\\tthis._destroyGpuResources();\\n\\t\\t}\\n\\t\\tcreateIter(p, r, s, c, sh) {\\n\\t\\t\\t\\treturn new GSplatSogIterator(this, p, r, s, c, sh);\\n\\t\\t}\\n\\t\\tcalcAabb(result) {\\n\\t\\t\\t\\tconst { mins, maxs } = this.meta.means;\\n\\t\\t\\t\\tconst map = (v)=>Math.sign(v) * (Math.exp(Math.abs(v)) - 1);\\n\\t\\t\\t\\tresult.center.set((map(mins[0]) + map(maxs[0])) * 0.5, (map(mins[1]) + map(maxs[1])) * 0.5, (map(mins[2]) + map(maxs[2])) * 0.5);\\n\\t\\t\\t\\tresult.halfExtents.set((map(maxs[0]) - map(mins[0])) * 0.5, (map(maxs[1]) - map(mins[1])) * 0.5, (map(maxs[2]) - map(mins[2])) * 0.5);\\n\\t\\t}\\n\\t\\tgetCenters() {\\n\\t\\t\\t\\tconst centers = this._centers;\\n\\t\\t\\t\\tthis._centers = null;\\n\\t\\t\\t\\treturn centers;\\n\\t\\t}\\n\\t\\tcalcFocalPoint(result, pred) {\\n\\t\\t\\t\\tconst { mins, maxs } = this.meta.means;\\n\\t\\t\\t\\tconst map = (v)=>Math.sign(v) * (Math.exp(Math.abs(v)) - 1);\\n\\t\\t\\t\\tresult.set((map(mins[0]) + map(maxs[0])) * 0.5, (map(mins[1]) + map(maxs[1])) * 0.5, (map(mins[2]) + map(maxs[2])) * 0.5);\\n\\t\\t}\\n\\t\\tget isSog() {\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tasync decompress() {\\n\\t\\t\\t\\tconst members = [\\n\\t\\t\\t\\t\\t\\t'x',\\n\\t\\t\\t\\t\\t\\t'y',\\n\\t\\t\\t\\t\\t\\t'z',\\n\\t\\t\\t\\t\\t\\t'f_dc_0',\\n\\t\\t\\t\\t\\t\\t'f_dc_1',\\n\\t\\t\\t\\t\\t\\t'f_dc_2',\\n\\t\\t\\t\\t\\t\\t'opacity',\\n\\t\\t\\t\\t\\t\\t'scale_0',\\n\\t\\t\\t\\t\\t\\t'scale_1',\\n\\t\\t\\t\\t\\t\\t'scale_2',\\n\\t\\t\\t\\t\\t\\t'rot_0',\\n\\t\\t\\t\\t\\t\\t'rot_1',\\n\\t\\t\\t\\t\\t\\t'rot_2',\\n\\t\\t\\t\\t\\t\\t'rot_3'\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tconst { shBands } = this;\\n\\t\\t\\t\\tconst { means_l, means_u, quats, scales, sh0, sh_labels, sh_centroids } = this;\\n\\t\\t\\t\\tmeans_l._levels[0] = await readImageDataAsync(means_l);\\n\\t\\t\\t\\tmeans_u._levels[0] = await readImageDataAsync(means_u);\\n\\t\\t\\t\\tquats._levels[0] = await readImageDataAsync(quats);\\n\\t\\t\\t\\tscales._levels[0] = await readImageDataAsync(scales);\\n\\t\\t\\t\\tsh0._levels[0] = await readImageDataAsync(sh0);\\n\\t\\t\\t\\tif (shBands > 0) {\\n\\t\\t\\t\\t\\t\\tsh_labels._levels[0] = await readImageDataAsync(sh_labels);\\n\\t\\t\\t\\t\\t\\tsh_centroids._levels[0] = await readImageDataAsync(sh_centroids);\\n\\t\\t\\t\\t\\t\\tconst shMembers = [];\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < 45; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tshMembers.push(`f_rest_${i}`);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tmembers.splice(members.indexOf('f_dc_0') + 1, 0, ...shMembers);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst data = {};\\n\\t\\t\\t\\tmembers.forEach((name)=>{\\n\\t\\t\\t\\t\\t\\tdata[name] = new Float32Array(this.numSplats);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst p = new Vec3();\\n\\t\\t\\t\\tconst r = new Quat();\\n\\t\\t\\t\\tconst s = new Vec3();\\n\\t\\t\\t\\tconst c = new Vec4();\\n\\t\\t\\t\\tconst sh = shBands > 0 ? new Float32Array(45) : null;\\n\\t\\t\\t\\tconst iter = this.createIter(p, r, s, c, sh);\\n\\t\\t\\t\\tfor(let i = 0; i < this.numSplats; ++i){\\n\\t\\t\\t\\t\\t\\titer.read(i);\\n\\t\\t\\t\\t\\t\\tdata.x[i] = p.x;\\n\\t\\t\\t\\t\\t\\tdata.y[i] = p.y;\\n\\t\\t\\t\\t\\t\\tdata.z[i] = p.z;\\n\\t\\t\\t\\t\\t\\tdata.rot_1[i] = r.x;\\n\\t\\t\\t\\t\\t\\tdata.rot_2[i] = r.y;\\n\\t\\t\\t\\t\\t\\tdata.rot_3[i] = r.z;\\n\\t\\t\\t\\t\\t\\tdata.rot_0[i] = r.w;\\n\\t\\t\\t\\t\\t\\tdata.scale_0[i] = s.x;\\n\\t\\t\\t\\t\\t\\tdata.scale_1[i] = s.y;\\n\\t\\t\\t\\t\\t\\tdata.scale_2[i] = s.z;\\n\\t\\t\\t\\t\\t\\tdata.f_dc_0[i] = (c.x - 0.5) / SH_C0$1;\\n\\t\\t\\t\\t\\t\\tdata.f_dc_1[i] = (c.y - 0.5) / SH_C0$1;\\n\\t\\t\\t\\t\\t\\tdata.f_dc_2[i] = (c.z - 0.5) / SH_C0$1;\\n\\t\\t\\t\\t\\t\\tdata.opacity[i] = c.w <= 0 ? -40 : c.w >= 1 ? 40 : -Math.log(1 / c.w - 1);\\n\\t\\t\\t\\t\\t\\tif (sh) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let c = 0; c < 45; ++c){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata[`f_rest_${c}`][i] = sh[c];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn new GSplatData([\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'vertex',\\n\\t\\t\\t\\t\\t\\t\\t\\tcount: this.numSplats,\\n\\t\\t\\t\\t\\t\\t\\t\\tproperties: members.map((name)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype: 'float',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbyteSize: 4,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstorage: data[name]\\n\\t\\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}\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tasync generateCenters() {\\n\\t\\t\\t\\tconst { device, width, height } = this.means_l;\\n\\t\\t\\t\\tconst { scope } = device;\\n\\t\\t\\t\\tconst centersTexture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: 'sogCentersTexture',\\n\\t\\t\\t\\t\\t\\twidth,\\n\\t\\t\\t\\t\\t\\theight,\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32U,\\n\\t\\t\\t\\t\\t\\tmipmaps: false\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst shader = ShaderUtils.createShader(device, {\\n\\t\\t\\t\\t\\t\\tuniqueName: 'GsplatSogCentersShader',\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tvertexChunk: 'fullscreenQuadVS',\\n\\t\\t\\t\\t\\t\\tfragmentGLSL: glslSogCentersPS,\\n\\t\\t\\t\\t\\t\\tfragmentWGSL: wgslSogCentersPS,\\n\\t\\t\\t\\t\\t\\tfragmentOutputTypes: [\\n\\t\\t\\t\\t\\t\\t\\t\\t'uvec4'\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\tfragmentIncludes: new Map([\\n\\t\\t\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t'gsplatPackingPS',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.isWebGPU ? gsplatPackingPS : gsplatPackingPS$1\\n\\t\\t\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t\\t\\t])\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst renderTarget = new RenderTarget({\\n\\t\\t\\t\\t\\t\\tcolorBuffer: centersTexture,\\n\\t\\t\\t\\t\\t\\tdepth: false,\\n\\t\\t\\t\\t\\t\\tmipLevel: 0\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tdevice.setCullMode(CULLFACE_NONE);\\n\\t\\t\\t\\tdevice.setBlendState(BlendState.NOBLEND);\\n\\t\\t\\t\\tdevice.setDepthState(DepthState.NODEPTH);\\n\\t\\t\\t\\tresolve(scope, {\\n\\t\\t\\t\\t\\t\\tmeans_l: this.means_l,\\n\\t\\t\\t\\t\\t\\tmeans_u: this.means_u,\\n\\t\\t\\t\\t\\t\\tnumSplats: this.numSplats,\\n\\t\\t\\t\\t\\t\\tmeans_mins: this.meta.means.mins,\\n\\t\\t\\t\\t\\t\\tmeans_maxs: this.meta.means.maxs\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tdrawQuadWithShader(device, renderTarget, shader);\\n\\t\\t\\t\\trenderTarget.destroy();\\n\\t\\t\\t\\tconst u32 = await readImageDataAsync(centersTexture);\\n\\t\\t\\t\\tif (this.destroyed || device._destroyed) {\\n\\t\\t\\t\\t\\t\\tcentersTexture.destroy();\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst asFloat = new Float32Array(u32.buffer);\\n\\t\\t\\t\\tconst result = new Float32Array(this.numSplats * 3);\\n\\t\\t\\t\\tfor(let i = 0; i < this.numSplats; i++){\\n\\t\\t\\t\\t\\t\\tconst base = i * 4;\\n\\t\\t\\t\\t\\t\\tresult[i * 3 + 0] = asFloat[base + 0];\\n\\t\\t\\t\\t\\t\\tresult[i * 3 + 1] = asFloat[base + 1];\\n\\t\\t\\t\\t\\t\\tresult[i * 3 + 2] = asFloat[base + 2];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._centers = result;\\n\\t\\t\\t\\tcentersTexture.destroy();\\n\\t\\t}\\n\\t\\tpackGpuMemory() {\\n\\t\\t\\t\\tconst { meta, means_l, means_u, quats, scales, sh0, sh_labels, numSplats } = this;\\n\\t\\t\\t\\tconst { device } = means_l;\\n\\t\\t\\t\\tconst { scope } = device;\\n\\t\\t\\t\\tconst shaderKey = meta.version === 2 ? 'v2' : 'v1';\\n\\t\\t\\t\\tconst shader = ShaderUtils.createShader(device, {\\n\\t\\t\\t\\t\\t\\tuniqueName: `GsplatSogReorderShader-${shaderKey}`,\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tvertexChunk: 'fullscreenQuadVS',\\n\\t\\t\\t\\t\\t\\tfragmentGLSL: glslGsplatSogReorderPS,\\n\\t\\t\\t\\t\\t\\tfragmentWGSL: wgslGsplatSogReorderPS,\\n\\t\\t\\t\\t\\t\\tfragmentOutputTypes: [\\n\\t\\t\\t\\t\\t\\t\\t\\t'uvec4',\\n\\t\\t\\t\\t\\t\\t\\t\\t'vec4'\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\tfragmentIncludes: new Map([\\n\\t\\t\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t'gsplatPackingPS',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.isWebGPU ? gsplatPackingPS : gsplatPackingPS$1\\n\\t\\t\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t\\t\\t]),\\n\\t\\t\\t\\t\\t\\tfragmentDefines: meta.version === 2 ? undefined : new Map([\\n\\t\\t\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t'REORDER_V1',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t'1'\\n\\t\\t\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t\\t\\t])\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst renderTarget = new RenderTarget({\\n\\t\\t\\t\\t\\t\\tcolorBuffers: [\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.packedTexture,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.packedSh0\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\tdepth: false,\\n\\t\\t\\t\\t\\t\\tmipLevel: 0\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tdevice.setCullMode(CULLFACE_NONE);\\n\\t\\t\\t\\tdevice.setBlendState(BlendState.NOBLEND);\\n\\t\\t\\t\\tdevice.setDepthState(DepthState.NODEPTH);\\n\\t\\t\\t\\tresolve(scope, {\\n\\t\\t\\t\\t\\t\\tmeans_l,\\n\\t\\t\\t\\t\\t\\tmeans_u,\\n\\t\\t\\t\\t\\t\\tquats,\\n\\t\\t\\t\\t\\t\\tscales,\\n\\t\\t\\t\\t\\t\\tsh0,\\n\\t\\t\\t\\t\\t\\tsh_labels: sh_labels ?? means_l,\\n\\t\\t\\t\\t\\t\\tnumSplats,\\n\\t\\t\\t\\t\\t\\t'scales_codebook[0]': this.meta.scales.codebook,\\n\\t\\t\\t\\t\\t\\t'sh0_codebook[0]': this.meta.sh0.codebook,\\n\\t\\t\\t\\t\\t\\tscalesMins: meta.scales.mins,\\n\\t\\t\\t\\t\\t\\tscalesMaxs: meta.scales.maxs,\\n\\t\\t\\t\\t\\t\\tsh0Mins: meta.sh0.mins,\\n\\t\\t\\t\\t\\t\\tsh0Maxs: meta.sh0.maxs\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tdrawQuadWithShader(device, renderTarget, shader);\\n\\t\\t\\t\\trenderTarget.destroy();\\n\\t\\t}\\n\\t\\tpackShMemory() {\\n\\t\\t\\t\\tconst { meta, sh_centroids } = this;\\n\\t\\t\\t\\tconst { device } = sh_centroids;\\n\\t\\t\\t\\tconst { scope } = device;\\n\\t\\t\\t\\tconst shaderKey = meta.version === 2 ? 'v2' : 'v1';\\n\\t\\t\\t\\tconst shader = ShaderUtils.createShader(device, {\\n\\t\\t\\t\\t\\t\\tuniqueName: `GsplatSogReorderShShader-${shaderKey}`,\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tvertexChunk: 'fullscreenQuadVS',\\n\\t\\t\\t\\t\\t\\tfragmentGLSL: glslGsplatSogReorderSh,\\n\\t\\t\\t\\t\\t\\tfragmentWGSL: wgslGsplatSogReorderSH,\\n\\t\\t\\t\\t\\t\\tfragmentIncludes: new Map([\\n\\t\\t\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t'gsplatPackingPS',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.isWebGPU ? gsplatPackingPS : gsplatPackingPS$1\\n\\t\\t\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t\\t\\t]),\\n\\t\\t\\t\\t\\t\\tfragmentDefines: meta.version === 2 ? undefined : new Map([\\n\\t\\t\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t'REORDER_V1',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t'1'\\n\\t\\t\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t\\t\\t])\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst renderTarget = new RenderTarget({\\n\\t\\t\\t\\t\\t\\tcolorBuffer: this.packedShN,\\n\\t\\t\\t\\t\\t\\tdepth: false,\\n\\t\\t\\t\\t\\t\\tmipLevel: 0\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tdevice.setCullMode(CULLFACE_NONE);\\n\\t\\t\\t\\tdevice.setBlendState(BlendState.NOBLEND);\\n\\t\\t\\t\\tdevice.setDepthState(DepthState.NODEPTH);\\n\\t\\t\\t\\tresolve(scope, {\\n\\t\\t\\t\\t\\t\\tsh_centroids,\\n\\t\\t\\t\\t\\t\\t'shN_codebook[0]': this.meta.shN.codebook\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tdrawQuadWithShader(device, renderTarget, shader);\\n\\t\\t\\t\\trenderTarget.destroy();\\n\\t\\t}\\n\\t\\tasync prepareGpuData() {\\n\\t\\t\\t\\tlet device = this.means_l.device;\\n\\t\\t\\t\\tconst { height, width } = this.means_l;\\n\\t\\t\\t\\tif (this.destroyed || !device || device._destroyed) return;\\n\\t\\t\\t\\tconst urlSuffix = this.url ? `_${this.url}` : '';\\n\\t\\t\\t\\tthis.packedTexture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: `sogPackedTexture${urlSuffix}`,\\n\\t\\t\\t\\t\\t\\twidth,\\n\\t\\t\\t\\t\\t\\theight,\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32U,\\n\\t\\t\\t\\t\\t\\tmipmaps: false\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.packedSh0 = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: `sogPackedSh0${urlSuffix}`,\\n\\t\\t\\t\\t\\t\\twidth,\\n\\t\\t\\t\\t\\t\\theight,\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA8,\\n\\t\\t\\t\\t\\t\\tmipmaps: false\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.packedShN = this.sh_centroids && new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: `sogPackedShN${urlSuffix}`,\\n\\t\\t\\t\\t\\t\\twidth: this.sh_centroids.width,\\n\\t\\t\\t\\t\\t\\theight: this.sh_centroids.height,\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA8,\\n\\t\\t\\t\\t\\t\\tmipmaps: false\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (!this.minimalMemory) {\\n\\t\\t\\t\\t\\t\\tthis.deviceRestoredEvent = device.on('devicerestored', ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.packGpuMemory();\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.packedShN) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.packShMemory();\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t'scales',\\n\\t\\t\\t\\t\\t\\t'sh0',\\n\\t\\t\\t\\t\\t\\t'shN'\\n\\t\\t\\t\\t].forEach((name)=>{\\n\\t\\t\\t\\t\\t\\tconst codebook = this.meta[name]?.codebook;\\n\\t\\t\\t\\t\\t\\tif (codebook?.[0] === null) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcodebook[0] = codebook[1] + (codebook[1] - codebook[255]) / 255;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tdevice = this.means_l?.device;\\n\\t\\t\\t\\tif (this.destroyed || !device || device._destroyed) return;\\n\\t\\t\\t\\tawait this.generateCenters();\\n\\t\\t\\t\\tdevice = this.means_l?.device;\\n\\t\\t\\t\\tif (this.destroyed || !device || device._destroyed) return;\\n\\t\\t\\t\\tthis.packGpuMemory();\\n\\t\\t\\t\\tif (this.packedShN) {\\n\\t\\t\\t\\t\\t\\tdevice = this.means_l?.device;\\n\\t\\t\\t\\t\\t\\tif (this.destroyed || !device || device._destroyed) return;\\n\\t\\t\\t\\t\\t\\tthis.packShMemory();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.minimalMemory) {\\n\\t\\t\\t\\t\\t\\tthis.means_l?.destroy();\\n\\t\\t\\t\\t\\t\\tthis.means_u?.destroy();\\n\\t\\t\\t\\t\\t\\tthis.quats?.destroy();\\n\\t\\t\\t\\t\\t\\tthis.scales?.destroy();\\n\\t\\t\\t\\t\\t\\tthis.sh0?.destroy();\\n\\t\\t\\t\\t\\t\\tthis.sh_centroids?.destroy();\\n\\t\\t\\t\\t\\t\\tthis.sh_labels?.destroy();\\n\\t\\t\\t\\t\\t\\tthis.means_l = null;\\n\\t\\t\\t\\t\\t\\tthis.means_u = null;\\n\\t\\t\\t\\t\\t\\tthis.quats = null;\\n\\t\\t\\t\\t\\t\\tthis.scales = null;\\n\\t\\t\\t\\t\\t\\tthis.sh0 = null;\\n\\t\\t\\t\\t\\t\\tthis.sh_centroids = null;\\n\\t\\t\\t\\t\\t\\tthis.sh_labels = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treorderData() {\\n\\t\\t\\t\\treturn this.prepareGpuData();\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.url = '';\\n\\t\\t\\t\\tthis.minimalMemory = false;\\n\\t\\t\\t\\tthis.deviceRestoredEvent = null;\\n\\t\\t\\t\\tthis._centers = null;\\n\\t\\t\\t\\tthis.destroyed = false;\\n\\t\\t\\t\\tthis.shBands = 0;\\n\\t\\t}\\n}\\n\\nconst mat = new Mat4();\\nconst cameraPosition$1 = new Vec3();\\nconst cameraDirection$1 = new Vec3();\\nclass GSplatInstance {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.resource?.releaseMesh();\\n\\t\\t\\t\\tthis.orderTexture?.destroy();\\n\\t\\t\\t\\tthis.resolveSH?.destroy();\\n\\t\\t\\t\\tthis.material?.destroy();\\n\\t\\t\\t\\tthis.meshInstance?.destroy();\\n\\t\\t\\t\\tthis.sorter?.destroy();\\n\\t\\t}\\n\\t\\tsetMaterialOrderTexture(material) {\\n\\t\\t\\t\\tmaterial.setParameter('splatOrder', this.orderTexture);\\n\\t\\t\\t\\tmaterial.setParameter('splatTextureSize', this.orderTexture.width);\\n\\t\\t}\\n\\t\\tset material(value) {\\n\\t\\t\\t\\tif (this._material !== value) {\\n\\t\\t\\t\\t\\t\\tthis._material = value;\\n\\t\\t\\t\\t\\t\\tthis.setMaterialOrderTexture(this._material);\\n\\t\\t\\t\\t\\t\\tif (this.meshInstance) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.meshInstance.material = value;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget material() {\\n\\t\\t\\t\\treturn this._material;\\n\\t\\t}\\n\\t\\tconfigureMaterial(material, options = {}) {\\n\\t\\t\\t\\tthis.resource.configureMaterial(material, null, this.resource.format.getInputDeclarations());\\n\\t\\t\\t\\tmaterial.setParameter('numSplats', 0);\\n\\t\\t\\t\\tthis.setMaterialOrderTexture(material);\\n\\t\\t\\t\\tmaterial.setParameter('alphaClip', 0.3);\\n\\t\\t\\t\\tmaterial.setDefine(`DITHER_${options.dither ? 'BLUENOISE' : 'NONE'}`, '');\\n\\t\\t\\t\\tmaterial.cull = CULLFACE_NONE;\\n\\t\\t\\t\\tmaterial.blendType = options.dither ? BLEND_NONE : BLEND_PREMULTIPLIED;\\n\\t\\t\\t\\tmaterial.depthWrite = !!options.dither;\\n\\t\\t}\\n\\t\\tsort(cameraNode) {\\n\\t\\t\\t\\tif (this.sorter) {\\n\\t\\t\\t\\t\\t\\tconst cameraMat = cameraNode.getWorldTransform();\\n\\t\\t\\t\\t\\t\\tcameraMat.getTranslation(cameraPosition$1);\\n\\t\\t\\t\\t\\t\\tcameraMat.getZ(cameraDirection$1);\\n\\t\\t\\t\\t\\t\\tconst modelMat = this.meshInstance.node.getWorldTransform();\\n\\t\\t\\t\\t\\t\\tconst invModelMat = mat.invert(modelMat);\\n\\t\\t\\t\\t\\t\\tinvModelMat.transformPoint(cameraPosition$1, cameraPosition$1);\\n\\t\\t\\t\\t\\t\\tinvModelMat.transformVector(cameraDirection$1, cameraDirection$1);\\n\\t\\t\\t\\t\\t\\tif (!cameraPosition$1.equalsApprox(this.lastCameraPosition) || !cameraDirection$1.equalsApprox(this.lastCameraDirection)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.lastCameraPosition.copy(cameraPosition$1);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.lastCameraDirection.copy(cameraDirection$1);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.sorter.setCamera(cameraPosition$1, cameraDirection$1);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdate() {\\n\\t\\t\\t\\tif (this.cameras.length > 0) {\\n\\t\\t\\t\\t\\t\\tconst camera = this.cameras[0];\\n\\t\\t\\t\\t\\t\\tthis.sort(camera._node);\\n\\t\\t\\t\\t\\t\\tthis.resolveSH?.render(camera._node, this.meshInstance.node.getWorldTransform());\\n\\t\\t\\t\\t\\t\\tthis.cameras.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetHighQualitySH(value) {\\n\\t\\t\\t\\tconst { resource } = this;\\n\\t\\t\\t\\tconst { gsplatData } = resource;\\n\\t\\t\\t\\tif (gsplatData instanceof GSplatSogData && gsplatData.shBands > 0 && value === !!this.resolveSH) {\\n\\t\\t\\t\\t\\t\\tif (this.resolveSH) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.resolveSH.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.resolveSH = null;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.resolveSH = new GSplatResolveSH(resource.device, this);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(resource, options = {}){\\n\\t\\t\\t\\tthis.options = {};\\n\\t\\t\\t\\tthis.sorter = null;\\n\\t\\t\\t\\tthis.lastCameraPosition = new Vec3();\\n\\t\\t\\t\\tthis.lastCameraDirection = new Vec3();\\n\\t\\t\\t\\tthis.resolveSH = null;\\n\\t\\t\\t\\tthis.cameras = [];\\n\\t\\t\\t\\tthis.resource = resource;\\n\\t\\t\\t\\tconst dims = resource.streams.textureDimensions;\\n\\t\\t\\t\\tthis.orderTexture = resource.streams.createTexture('splatOrder', PIXELFORMAT_R32U, dims);\\n\\t\\t\\t\\tif (options.material) {\\n\\t\\t\\t\\t\\t\\tthis._material = options.material;\\n\\t\\t\\t\\t\\t\\tthis.setMaterialOrderTexture(this._material);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._material = new ShaderMaterial({\\n\\t\\t\\t\\t\\t\\t\\t\\tuniqueName: 'SplatMaterial',\\n\\t\\t\\t\\t\\t\\t\\t\\tvertexGLSL: '#include \\\"gsplatVS\\\"',\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentGLSL: '#include \\\"gsplatPS\\\"',\\n\\t\\t\\t\\t\\t\\t\\t\\tvertexWGSL: '#include \\\"gsplatVS\\\"',\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentWGSL: '#include \\\"gsplatPS\\\"',\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvertex_id_attrib: SEMANTIC_ATTR13\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tthis.configureMaterial(this._material);\\n\\t\\t\\t\\t\\t\\tthis._material.update();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tresource.ensureMesh();\\n\\t\\t\\t\\tthis.meshInstance = new MeshInstance(resource.mesh, this._material);\\n\\t\\t\\t\\tthis.meshInstance.setInstancing(resource.instanceIndices, true);\\n\\t\\t\\t\\tthis.meshInstance.gsplatInstance = this;\\n\\t\\t\\t\\tthis.meshInstance.instancingCount = 0;\\n\\t\\t\\t\\tconst centers = resource.centers.slice();\\n\\t\\t\\t\\tconst chunks = resource.chunks?.slice();\\n\\t\\t\\t\\tthis.sorter = new GSplatSorter(options.scene);\\n\\t\\t\\t\\tthis.sorter.init(this.orderTexture, centers, chunks);\\n\\t\\t\\t\\tthis.sorter.on('updated', (count)=>{\\n\\t\\t\\t\\t\\t\\tthis.meshInstance.instancingCount = Math.ceil(count / GSplatResourceBase.instanceSize);\\n\\t\\t\\t\\t\\t\\tthis.material.setParameter('numSplats', count);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.setHighQualitySH(options.highQualitySH ?? false);\\n\\t\\t}\\n}\\n\\nconst getSHData = (gsplatData, numCoeffs)=>{\\n\\t\\tconst result = [];\\n\\t\\tfor(let i = 0; i < numCoeffs; ++i){\\n\\t\\t\\t\\tresult.push(gsplatData.getProp(`f_rest_${i}`));\\n\\t\\t}\\n\\t\\treturn result;\\n};\\nclass GSplatResource extends GSplatResourceBase {\\n\\t\\tconfigureMaterialDefines(defines) {\\n\\t\\t\\t\\tdefines.set('SH_BANDS', this.shBands);\\n\\t\\t}\\n\\t\\tupdateColorData(gsplatData) {\\n\\t\\t\\t\\tconst texture = this.streams.getTexture('splatColor');\\n\\t\\t\\t\\tif (!texture) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst float2Half = FloatPacking.float2Half;\\n\\t\\t\\t\\tconst data = texture.lock();\\n\\t\\t\\t\\tconst cr = gsplatData.getProp('f_dc_0');\\n\\t\\t\\t\\tconst cg = gsplatData.getProp('f_dc_1');\\n\\t\\t\\t\\tconst cb = gsplatData.getProp('f_dc_2');\\n\\t\\t\\t\\tconst ca = gsplatData.getProp('opacity');\\n\\t\\t\\t\\tconst SH_C0 = 0.28209479177387814;\\n\\t\\t\\t\\tfor(let i = 0; i < this.numSplats; ++i){\\n\\t\\t\\t\\t\\t\\tconst r = cr[i] * SH_C0 + 0.5;\\n\\t\\t\\t\\t\\t\\tconst g = cg[i] * SH_C0 + 0.5;\\n\\t\\t\\t\\t\\t\\tconst b = cb[i] * SH_C0 + 0.5;\\n\\t\\t\\t\\t\\t\\tconst a = 1 / (1 + Math.exp(-ca[i]));\\n\\t\\t\\t\\t\\t\\tdata[i * 4 + 0] = float2Half(r);\\n\\t\\t\\t\\t\\t\\tdata[i * 4 + 1] = float2Half(g);\\n\\t\\t\\t\\t\\t\\tdata[i * 4 + 2] = float2Half(b);\\n\\t\\t\\t\\t\\t\\tdata[i * 4 + 3] = float2Half(a);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttexture.unlock();\\n\\t\\t}\\n\\t\\tupdateTransformData(gsplatData) {\\n\\t\\t\\t\\tconst float2Half = FloatPacking.float2Half;\\n\\t\\t\\t\\tconst transformA = this.streams.getTexture('transformA');\\n\\t\\t\\t\\tconst transformB = this.streams.getTexture('transformB');\\n\\t\\t\\t\\tif (!transformA) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst dataA = transformA.lock();\\n\\t\\t\\t\\tconst dataAFloat32 = new Float32Array(dataA.buffer);\\n\\t\\t\\t\\tconst dataB = transformB.lock();\\n\\t\\t\\t\\tconst p = new Vec3();\\n\\t\\t\\t\\tconst r = new Quat();\\n\\t\\t\\t\\tconst s = new Vec3();\\n\\t\\t\\t\\tconst iter = gsplatData.createIter(p, r, s);\\n\\t\\t\\t\\tfor(let i = 0; i < this.numSplats; i++){\\n\\t\\t\\t\\t\\t\\titer.read(i);\\n\\t\\t\\t\\t\\t\\tr.normalize();\\n\\t\\t\\t\\t\\t\\tif (r.w < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tr.mulScalar(-1);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tdataAFloat32[i * 4 + 0] = p.x;\\n\\t\\t\\t\\t\\t\\tdataAFloat32[i * 4 + 1] = p.y;\\n\\t\\t\\t\\t\\t\\tdataAFloat32[i * 4 + 2] = p.z;\\n\\t\\t\\t\\t\\t\\tdataA[i * 4 + 3] = float2Half(r.x) | float2Half(r.y) << 16;\\n\\t\\t\\t\\t\\t\\tdataB[i * 4 + 0] = float2Half(s.x);\\n\\t\\t\\t\\t\\t\\tdataB[i * 4 + 1] = float2Half(s.y);\\n\\t\\t\\t\\t\\t\\tdataB[i * 4 + 2] = float2Half(s.z);\\n\\t\\t\\t\\t\\t\\tdataB[i * 4 + 3] = float2Half(r.z);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttransformA.unlock();\\n\\t\\t\\t\\ttransformB.unlock();\\n\\t\\t}\\n\\t\\tupdateSHData(gsplatData) {\\n\\t\\t\\t\\tconst sh1to3Texture = this.streams.getTexture('splatSH_1to3');\\n\\t\\t\\t\\tconst sh4to7Texture = this.streams.getTexture('splatSH_4to7');\\n\\t\\t\\t\\tconst sh8to11Texture = this.streams.getTexture('splatSH_8to11');\\n\\t\\t\\t\\tconst sh12to15Texture = this.streams.getTexture('splatSH_12to15');\\n\\t\\t\\t\\tconst sh1to3Data = sh1to3Texture.lock();\\n\\t\\t\\t\\tconst sh4to7Data = sh4to7Texture?.lock();\\n\\t\\t\\t\\tconst sh8to11Data = sh8to11Texture?.lock();\\n\\t\\t\\t\\tconst sh12to15Data = sh12to15Texture?.lock();\\n\\t\\t\\t\\tconst numCoeffs = {\\n\\t\\t\\t\\t\\t\\t1: 3,\\n\\t\\t\\t\\t\\t\\t2: 8,\\n\\t\\t\\t\\t\\t\\t3: 15\\n\\t\\t\\t\\t}[this.shBands];\\n\\t\\t\\t\\tconst src = getSHData(gsplatData, numCoeffs * 3);\\n\\t\\t\\t\\tconst t11 = (1 << 11) - 1;\\n\\t\\t\\t\\tconst t10 = (1 << 10) - 1;\\n\\t\\t\\t\\tconst float32 = new Float32Array(1);\\n\\t\\t\\t\\tconst uint32 = new Uint32Array(float32.buffer);\\n\\t\\t\\t\\tconst c = new Array(numCoeffs * 3).fill(0);\\n\\t\\t\\t\\tfor(let i = 0; i < gsplatData.numSplats; ++i){\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j < numCoeffs; ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\tc[j * 3] = src[j][i];\\n\\t\\t\\t\\t\\t\\t\\t\\tc[j * 3 + 1] = src[j + numCoeffs][i];\\n\\t\\t\\t\\t\\t\\t\\t\\tc[j * 3 + 2] = src[j + numCoeffs * 2][i];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlet max = c[0];\\n\\t\\t\\t\\t\\t\\tfor(let j = 1; j < numCoeffs * 3; ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\tmax = Math.max(max, Math.abs(c[j]));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (max === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j < numCoeffs; ++j){\\n\\t\\t\\t\\t\\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\\t\\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\\t\\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\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfloat32[0] = max;\\n\\t\\t\\t\\t\\t\\tsh1to3Data[i * 4 + 0] = uint32[0];\\n\\t\\t\\t\\t\\t\\tsh1to3Data[i * 4 + 1] = c[0] << 21 | c[1] << 11 | c[2];\\n\\t\\t\\t\\t\\t\\tsh1to3Data[i * 4 + 2] = c[3] << 21 | c[4] << 11 | c[5];\\n\\t\\t\\t\\t\\t\\tsh1to3Data[i * 4 + 3] = c[6] << 21 | c[7] << 11 | c[8];\\n\\t\\t\\t\\t\\t\\tif (this.shBands > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tsh4to7Data[i * 4 + 0] = c[9] << 21 | c[10] << 11 | c[11];\\n\\t\\t\\t\\t\\t\\t\\t\\tsh4to7Data[i * 4 + 1] = c[12] << 21 | c[13] << 11 | c[14];\\n\\t\\t\\t\\t\\t\\t\\t\\tsh4to7Data[i * 4 + 2] = c[15] << 21 | c[16] << 11 | c[17];\\n\\t\\t\\t\\t\\t\\t\\t\\tsh4to7Data[i * 4 + 3] = c[18] << 21 | c[19] << 11 | c[20];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.shBands > 2) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsh8to11Data[i * 4 + 0] = c[21] << 21 | c[22] << 11 | c[23];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsh8to11Data[i * 4 + 1] = c[24] << 21 | c[25] << 11 | c[26];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsh8to11Data[i * 4 + 2] = c[27] << 21 | c[28] << 11 | c[29];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsh8to11Data[i * 4 + 3] = c[30] << 21 | c[31] << 11 | c[32];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsh12to15Data[i * 4 + 0] = c[33] << 21 | c[34] << 11 | c[35];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsh12to15Data[i * 4 + 1] = c[36] << 21 | c[37] << 11 | c[38];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsh12to15Data[i * 4 + 2] = c[39] << 21 | c[40] << 11 | c[41];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsh12to15Data[i * 4 + 3] = c[42] << 21 | c[43] << 11 | c[44];\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsh8to11Data[i] = c[21] << 21 | c[22] << 11 | c[23];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tsh1to3Texture.unlock();\\n\\t\\t\\t\\tsh4to7Texture?.unlock();\\n\\t\\t\\t\\tsh8to11Texture?.unlock();\\n\\t\\t\\t\\tsh12to15Texture?.unlock();\\n\\t\\t}\\n\\t\\tconstructor(device, gsplatData){\\n\\t\\t\\t\\tsuper(device, gsplatData);\\n\\t\\t\\t\\tconst numSplats = gsplatData.numSplats;\\n\\t\\t\\t\\tthis.shBands = gsplatData.shBands;\\n\\t\\t\\t\\tconst streams = [\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'splatColor',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA16F\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'transformA',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32U\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'transformB',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA16F\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tif (this.shBands > 0) {\\n\\t\\t\\t\\t\\t\\tstreams.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'splatSH_1to3',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32U\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tif (this.shBands > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tstreams.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tname: 'splatSH_4to7',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32U\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.shBands > 2) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstreams.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tname: 'splatSH_8to11',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32U\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstreams.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tname: 'splatSH_12to15',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32U\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstreams.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tname: 'splatSH_8to11',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_R32U\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._format = new GSplatFormat(device, streams, {\\n\\t\\t\\t\\t\\t\\treadGLSL: '#include \\\"gsplatUncompressedVS\\\"',\\n\\t\\t\\t\\t\\t\\treadWGSL: '#include \\\"gsplatUncompressedVS\\\"'\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.streams.init(this.format, numSplats);\\n\\t\\t\\t\\tthis.updateColorData(gsplatData);\\n\\t\\t\\t\\tthis.updateTransformData(gsplatData);\\n\\t\\t\\t\\tif (this.shBands > 0) {\\n\\t\\t\\t\\t\\t\\tthis.updateSHData(gsplatData);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass GSplatSogResource extends GSplatResourceBase {\\n\\t\\t_actualDestroy() {\\n\\t\\t\\t\\tthis.streams.textures.delete('packedTexture');\\n\\t\\t\\t\\tthis.streams.textures.delete('packedSh0');\\n\\t\\t\\t\\tthis.streams.textures.delete('packedShN');\\n\\t\\t\\t\\tthis.gsplatData.destroy();\\n\\t\\t\\t\\tsuper._actualDestroy();\\n\\t\\t}\\n\\t\\t_populateParameters() {\\n\\t\\t\\t\\tconst { meta } = this.gsplatData;\\n\\t\\t\\t\\tif (meta.means) {\\n\\t\\t\\t\\t\\t\\tthis.parameters.set('means_mins', meta.means.mins);\\n\\t\\t\\t\\t\\t\\tthis.parameters.set('means_maxs', meta.means.maxs);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (meta.version === 2) {\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t'scales',\\n\\t\\t\\t\\t\\t\\t\\t\\t'sh0',\\n\\t\\t\\t\\t\\t\\t\\t\\t'shN'\\n\\t\\t\\t\\t\\t\\t].forEach((name)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst v = meta[name];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (v) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.parameters.set(`${name}_mins`, v.codebook[0]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.parameters.set(`${name}_maxs`, v.codebook[255]);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t'scales',\\n\\t\\t\\t\\t\\t\\t\\t\\t'sh0'\\n\\t\\t\\t\\t\\t\\t].forEach((name)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst v = meta[name];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (v) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.parameters.set(`${name}_mins`, Math.min(...v.mins.slice(0, 3)));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.parameters.set(`${name}_maxs`, Math.max(...v.maxs.slice(0, 3)));\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t'shN'\\n\\t\\t\\t\\t\\t\\t].forEach((name)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst v = meta[name];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (v) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.parameters.set(`${name}_mins`, v.mins);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.parameters.set(`${name}_maxs`, v.maxs);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconfigureMaterialDefines(defines) {\\n\\t\\t\\t\\tdefines.set('SH_BANDS', this.gsplatData.shBands);\\n\\t\\t}\\n\\t\\tconstructor(device, gsplatData){\\n\\t\\t\\t\\tsuper(device, gsplatData);\\n\\t\\t\\t\\tconst sizeTexture = gsplatData.means_l || gsplatData.packedTexture;\\n\\t\\t\\t\\tif (sizeTexture) {\\n\\t\\t\\t\\t\\t\\tthis.streams.textureDimensions.set(sizeTexture.width, sizeTexture.height);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (gsplatData.packedTexture) {\\n\\t\\t\\t\\t\\t\\tthis.streams.textures.set('packedTexture', gsplatData.packedTexture);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (gsplatData.packedSh0) {\\n\\t\\t\\t\\t\\t\\tthis.streams.textures.set('packedSh0', gsplatData.packedSh0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (gsplatData.packedShN) {\\n\\t\\t\\t\\t\\t\\tthis.streams.textures.set('packedShN', gsplatData.packedShN);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst streams = [\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'packedTexture',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32U\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis._format = new GSplatFormat(device, streams, {\\n\\t\\t\\t\\t\\t\\treadGLSL: '#include \\\"gsplatSogVS\\\"',\\n\\t\\t\\t\\t\\t\\treadWGSL: '#include \\\"gsplatSogVS\\\"'\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis._populateParameters();\\n\\t\\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\\t\\treturn currentApplication;\\n}\\nfunction setApplication(app) {\\n\\t\\tcurrentApplication = app;\\n}\\n\\nclass FrameGraph {\\n\\t\\taddRenderPass(renderPass) {\\n\\t\\t\\t\\trenderPass.frameUpdate();\\n\\t\\t\\t\\tconst beforePasses = renderPass.beforePasses;\\n\\t\\t\\t\\tfor(let i = 0; i < beforePasses.length; i++){\\n\\t\\t\\t\\t\\t\\tconst pass = beforePasses[i];\\n\\t\\t\\t\\t\\t\\tif (pass.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.addRenderPass(pass);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (renderPass.enabled) {\\n\\t\\t\\t\\t\\t\\tthis.renderPasses.push(renderPass);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst afterPasses = renderPass.afterPasses;\\n\\t\\t\\t\\tfor(let i = 0; i < afterPasses.length; i++){\\n\\t\\t\\t\\t\\t\\tconst pass = afterPasses[i];\\n\\t\\t\\t\\t\\t\\tif (pass.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.addRenderPass(pass);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treset() {\\n\\t\\t\\t\\tthis.renderPasses.length = 0;\\n\\t\\t}\\n\\t\\tcompile() {\\n\\t\\t\\t\\tconst renderTargetMap = this.renderTargetMap;\\n\\t\\t\\t\\tconst renderPasses = this.renderPasses;\\n\\t\\t\\t\\tfor(let i = 0; i < renderPasses.length; i++){\\n\\t\\t\\t\\t\\t\\tconst renderPass = renderPasses[i];\\n\\t\\t\\t\\t\\t\\tconst renderTarget = renderPass.renderTarget;\\n\\t\\t\\t\\t\\t\\tif (renderTarget !== undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst prevPass = renderTargetMap.get(renderTarget);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (prevPass) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst count = renderPass.colorArrayOps.length;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < count; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst colorOps = renderPass.colorArrayOps[j];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!colorOps.clear) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tprevPass.colorArrayOps[j].store = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!renderPass.depthStencilOps.clearDepth) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tprevPass.depthStencilOps.storeDepth = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!renderPass.depthStencilOps.clearStencil) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tprevPass.depthStencilOps.storeStencil = true;\\n\\t\\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\\trenderTargetMap.set(renderTarget, renderPass);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < renderPasses.length - 1; i++){\\n\\t\\t\\t\\t\\t\\tconst firstPass = renderPasses[i];\\n\\t\\t\\t\\t\\t\\tconst firstRT = firstPass.renderTarget;\\n\\t\\t\\t\\t\\t\\tconst secondPass = renderPasses[i + 1];\\n\\t\\t\\t\\t\\t\\tconst secondRT = secondPass.renderTarget;\\n\\t\\t\\t\\t\\t\\tif (firstRT !== secondRT || firstRT === undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (secondPass.depthStencilOps.clearDepth || secondPass.depthStencilOps.clearStencil || secondPass.colorArrayOps.some((colorOps)=>colorOps.clear)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (firstPass.afterPasses.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (secondPass.beforePasses.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfirstPass._skipEnd = true;\\n\\t\\t\\t\\t\\t\\tsecondPass._skipStart = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet lastCubeTexture = null;\\n\\t\\t\\t\\tlet lastCubeRenderPass = null;\\n\\t\\t\\t\\tfor(let i = 0; i < renderPasses.length; i++){\\n\\t\\t\\t\\t\\t\\tconst renderPass = renderPasses[i];\\n\\t\\t\\t\\t\\t\\tconst renderTarget = renderPass.renderTarget;\\n\\t\\t\\t\\t\\t\\tconst thisTexture = renderTarget?.colorBuffer;\\n\\t\\t\\t\\t\\t\\tif (thisTexture?.cubemap) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (lastCubeTexture === thisTexture) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst count = lastCubeRenderPass.colorArrayOps.length;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < count; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlastCubeRenderPass.colorArrayOps[j].mipmaps = false;\\n\\t\\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\\tlastCubeTexture = renderTarget.colorBuffer;\\n\\t\\t\\t\\t\\t\\t\\t\\tlastCubeRenderPass = renderPass;\\n\\t\\t\\t\\t\\t\\t} else if (renderPass.requiresCubemaps) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlastCubeTexture = null;\\n\\t\\t\\t\\t\\t\\t\\t\\tlastCubeRenderPass = null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\trenderTargetMap.clear();\\n\\t\\t}\\n\\t\\trender(device) {\\n\\t\\t\\t\\tthis.compile();\\n\\t\\t\\t\\tconst renderPasses = this.renderPasses;\\n\\t\\t\\t\\tfor(let i = 0; i < renderPasses.length; i++){\\n\\t\\t\\t\\t\\t\\trenderPasses[i].render();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.renderPasses = [];\\n\\t\\t\\t\\tthis.renderTargetMap = new Map();\\n\\t\\t}\\n}\\n\\nclass AreaLightCacheEntry {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.texture0?.destroy();\\n\\t\\t\\t\\tthis.texture1?.destroy();\\n\\t\\t}\\n\\t\\tconstructor(texture0, texture1){\\n\\t\\t\\t\\tthis.texture0 = texture0;\\n\\t\\t\\t\\tthis.texture1 = texture1;\\n\\t\\t}\\n}\\nconst deviceCache = new DeviceCache();\\nclass AreaLightLuts {\\n\\t\\tstatic createTexture(device, format, size, postfix = '') {\\n\\t\\t\\t\\tconst tex = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: `AreaLightLUT${postfix}`,\\n\\t\\t\\t\\t\\t\\twidth: size,\\n\\t\\t\\t\\t\\t\\theight: size,\\n\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\ttype: TEXTURETYPE_DEFAULT,\\n\\t\\t\\t\\t\\t\\tmagFilter: FILTER_LINEAR,\\n\\t\\t\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\tanisotropy: 1,\\n\\t\\t\\t\\t\\t\\tmipmaps: false\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn tex;\\n\\t\\t}\\n\\t\\tstatic applyTextures(device, texture1, texture2) {\\n\\t\\t\\t\\tdeviceCache.remove(device);\\n\\t\\t\\t\\tdeviceCache.get(device, ()=>{\\n\\t\\t\\t\\t\\t\\treturn new AreaLightCacheEntry(texture1, texture1 === texture2 ? null : texture2);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tdevice.scope.resolve('areaLightsLutTex1').setValue(texture1);\\n\\t\\t\\t\\tdevice.scope.resolve('areaLightsLutTex2').setValue(texture2);\\n\\t\\t}\\n\\t\\tstatic createPlaceholder(device) {\\n\\t\\t\\t\\tconst texture = AreaLightLuts.createTexture(device, PIXELFORMAT_RGBA16F, 2, 'placeholder');\\n\\t\\t\\t\\tconst pixels = texture.lock();\\n\\t\\t\\t\\tpixels.fill(0);\\n\\t\\t\\t\\ttexture.unlock();\\n\\t\\t\\t\\tAreaLightLuts.applyTextures(device, texture, texture);\\n\\t\\t}\\n\\t\\tstatic set(device, ltcMat1, ltcMat2) {\\n\\t\\t\\t\\tfunction buildTexture(device, data, format) {\\n\\t\\t\\t\\t\\t\\tconst texture = AreaLightLuts.createTexture(device, format, 64);\\n\\t\\t\\t\\t\\t\\ttexture.lock().set(data);\\n\\t\\t\\t\\t\\t\\ttexture.unlock();\\n\\t\\t\\t\\t\\t\\treturn texture;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfunction convertToHalfFloat(data) {\\n\\t\\t\\t\\t\\t\\tconst count = data.length;\\n\\t\\t\\t\\t\\t\\tconst ret = new Uint16Array(count);\\n\\t\\t\\t\\t\\t\\tconst float2Half = FloatPacking.float2Half;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tret[i] = float2Half(data[i]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn ret;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst srcData1 = ltcMat1;\\n\\t\\t\\t\\tconst srcData2 = ltcMat2;\\n\\t\\t\\t\\tconst data1 = convertToHalfFloat(srcData1);\\n\\t\\t\\t\\tconst data2 = convertToHalfFloat(srcData2);\\n\\t\\t\\t\\tconst tex1 = buildTexture(device, data1, PIXELFORMAT_RGBA16F);\\n\\t\\t\\t\\tconst tex2 = buildTexture(device, data2, PIXELFORMAT_RGBA16F);\\n\\t\\t\\t\\tAreaLightLuts.applyTextures(device, tex1, tex2);\\n\\t\\t}\\n}\\n\\nconst DEFAULT_LOCALE = 'en-US';\\nconst DEFAULT_LOCALE_FALLBACKS = {\\n\\t\\t'en': 'en-US',\\n\\t\\t'es': 'en-ES',\\n\\t\\t'zh': 'zh-CN',\\n\\t\\t'zh-HK': 'zh-TW',\\n\\t\\t'zh-TW': 'zh-HK',\\n\\t\\t'zh-MO': 'zh-HK',\\n\\t\\t'fr': 'fr-FR',\\n\\t\\t'de': 'de-DE',\\n\\t\\t'it': 'it-IT',\\n\\t\\t'ru': 'ru-RU',\\n\\t\\t'ja': 'ja-JP'\\n};\\n\\nconst PLURALS = {};\\nfunction definePluralFn(locales, fn) {\\n\\t\\tfor(let i = 0, len = locales.length; i < len; i++){\\n\\t\\t\\t\\tPLURALS[locales[i]] = fn;\\n\\t\\t}\\n}\\nfunction getLang(locale) {\\n\\t\\tconst idx = locale.indexOf('-');\\n\\t\\tif (idx !== -1) {\\n\\t\\t\\t\\treturn locale.substring(0, idx);\\n\\t\\t}\\n\\t\\treturn locale;\\n}\\nfunction replaceLang(locale, desiredLang) {\\n\\t\\tconst idx = locale.indexOf('-');\\n\\t\\tif (idx !== -1) {\\n\\t\\t\\t\\treturn desiredLang + locale.substring(idx);\\n\\t\\t}\\n\\t\\treturn desiredLang;\\n}\\nfunction findAvailableLocale(desiredLocale, availableLocales) {\\n\\t\\tif (availableLocales[desiredLocale]) {\\n\\t\\t\\t\\treturn desiredLocale;\\n\\t\\t}\\n\\t\\tlet fallback = DEFAULT_LOCALE_FALLBACKS[desiredLocale];\\n\\t\\tif (fallback && availableLocales[fallback]) {\\n\\t\\t\\t\\treturn fallback;\\n\\t\\t}\\n\\t\\tconst lang = getLang(desiredLocale);\\n\\t\\tfallback = DEFAULT_LOCALE_FALLBACKS[lang];\\n\\t\\tif (availableLocales[fallback]) {\\n\\t\\t\\t\\treturn fallback;\\n\\t\\t}\\n\\t\\tif (availableLocales[lang]) {\\n\\t\\t\\t\\treturn lang;\\n\\t\\t}\\n\\t\\treturn DEFAULT_LOCALE;\\n}\\ndefinePluralFn([\\n\\t\\t'ja',\\n\\t\\t'ko',\\n\\t\\t'th',\\n\\t\\t'vi',\\n\\t\\t'zh',\\n\\t\\t'id'\\n], (n)=>{\\n\\t\\treturn 0;\\n});\\ndefinePluralFn([\\n\\t\\t'fa',\\n\\t\\t'hi'\\n], (n)=>{\\n\\t\\tif (n >= 0 && n <= 1) {\\n\\t\\t\\t\\treturn 0;\\n\\t\\t}\\n\\t\\treturn 1;\\n});\\ndefinePluralFn([\\n\\t\\t'fr',\\n\\t\\t'pt'\\n], (n)=>{\\n\\t\\tif (n >= 0 && n < 2) {\\n\\t\\t\\t\\treturn 0;\\n\\t\\t}\\n\\t\\treturn 1;\\n});\\ndefinePluralFn([\\n\\t\\t'da'\\n], (n)=>{\\n\\t\\tif (n === 1 || !Number.isInteger(n) && n >= 0 && n <= 1) {\\n\\t\\t\\t\\treturn 0;\\n\\t\\t}\\n\\t\\treturn 1;\\n});\\ndefinePluralFn([\\n\\t\\t'de',\\n\\t\\t'en',\\n\\t\\t'it',\\n\\t\\t'el',\\n\\t\\t'es',\\n\\t\\t'tr',\\n\\t\\t'fi',\\n\\t\\t'sv',\\n\\t\\t'nb',\\n\\t\\t'no',\\n\\t\\t'ur'\\n], (n)=>{\\n\\t\\tif (n === 1) {\\n\\t\\t\\t\\treturn 0;\\n\\t\\t}\\n\\t\\treturn 1;\\n});\\ndefinePluralFn([\\n\\t\\t'ru',\\n\\t\\t'uk'\\n], (n)=>{\\n\\t\\tif (Number.isInteger(n)) {\\n\\t\\t\\t\\tconst mod10 = n % 10;\\n\\t\\t\\t\\tconst mod100 = n % 100;\\n\\t\\t\\t\\tif (mod10 === 1 && mod100 !== 11) {\\n\\t\\t\\t\\t\\t\\treturn 0;\\n\\t\\t\\t\\t} else if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) {\\n\\t\\t\\t\\t\\t\\treturn 1;\\n\\t\\t\\t\\t} else if (mod10 === 0 || mod10 >= 5 && mod10 <= 9 || mod100 >= 11 && mod100 <= 14) {\\n\\t\\t\\t\\t\\t\\treturn 2;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn 3;\\n});\\ndefinePluralFn([\\n\\t\\t'pl'\\n], (n)=>{\\n\\t\\tif (Number.isInteger(n)) {\\n\\t\\t\\t\\tif (n === 1) {\\n\\t\\t\\t\\t\\t\\treturn 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst mod10 = n % 10;\\n\\t\\t\\t\\tconst mod100 = n % 100;\\n\\t\\t\\t\\tif (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) {\\n\\t\\t\\t\\t\\t\\treturn 1;\\n\\t\\t\\t\\t} else if (mod10 >= 0 && mod10 <= 1 || mod10 >= 5 && mod10 <= 9 || mod100 >= 12 && mod100 <= 14) {\\n\\t\\t\\t\\t\\t\\treturn 2;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn 3;\\n});\\ndefinePluralFn([\\n\\t\\t'ar'\\n], (n)=>{\\n\\t\\tif (n === 0) {\\n\\t\\t\\t\\treturn 0;\\n\\t\\t} else if (n === 1) {\\n\\t\\t\\t\\treturn 1;\\n\\t\\t} else if (n === 2) {\\n\\t\\t\\t\\treturn 2;\\n\\t\\t}\\n\\t\\tif (Number.isInteger(n)) {\\n\\t\\t\\t\\tconst mod100 = n % 100;\\n\\t\\t\\t\\tif (mod100 >= 3 && mod100 <= 10) {\\n\\t\\t\\t\\t\\t\\treturn 3;\\n\\t\\t\\t\\t} else if (mod100 >= 11 && mod100 <= 99) {\\n\\t\\t\\t\\t\\t\\treturn 4;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn 5;\\n});\\nconst DEFAULT_PLURAL_FN = PLURALS[getLang(DEFAULT_LOCALE)];\\nfunction getPluralFn(lang) {\\n\\t\\treturn PLURALS[lang] || DEFAULT_PLURAL_FN;\\n}\\n\\nconst ABSOLUTE_URL = new RegExp('^' + '\\\\\\\\s*' + '(?:' + '(?:' + '[a-z]+[a-z0-9\\\\\\\\-+.]*' + ':' + ')?' + '//' + '|' + 'data:' + '|blob:' + ')', 'i');\\n\\nclass AssetFile {\\n\\t\\tequals(other) {\\n\\t\\t\\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\\t}\\n\\t\\tconstructor(url = '', filename = '', hash = null, size = null, opt = null, contents = null){\\n\\t\\t\\t\\tthis.url = url;\\n\\t\\t\\t\\tthis.filename = filename;\\n\\t\\t\\t\\tthis.hash = hash;\\n\\t\\t\\t\\tthis.size = size;\\n\\t\\t\\t\\tthis.opt = opt;\\n\\t\\t\\t\\tthis.contents = contents;\\n\\t\\t}\\n}\\n\\nlet assetIdCounter = -1;\\nconst VARIANT_SUPPORT = {\\n\\t\\tpvr: 'extCompressedTexturePVRTC',\\n\\t\\tdxt: 'extCompressedTextureS3TC',\\n\\t\\tetc2: 'extCompressedTextureETC',\\n\\t\\tetc1: 'extCompressedTextureETC1',\\n\\t\\tbasis: 'canvas'\\n};\\nconst VARIANT_DEFAULT_PRIORITY = [\\n\\t\\t'pvr',\\n\\t\\t'dxt',\\n\\t\\t'etc2',\\n\\t\\t'etc1',\\n\\t\\t'basis'\\n];\\nclass Asset extends EventHandler {\\n\\t\\tset name(value) {\\n\\t\\t\\t\\tif (this._name === value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst old = this._name;\\n\\t\\t\\t\\tthis._name = value;\\n\\t\\t\\t\\tthis.fire('name', this, this._name, old);\\n\\t\\t}\\n\\t\\tget name() {\\n\\t\\t\\t\\treturn this._name;\\n\\t\\t}\\n\\t\\tset file(value) {\\n\\t\\t\\t\\tif (value && value.variants && [\\n\\t\\t\\t\\t\\t\\t'texture',\\n\\t\\t\\t\\t\\t\\t'textureatlas',\\n\\t\\t\\t\\t\\t\\t'bundle'\\n\\t\\t\\t\\t].indexOf(this.type) !== -1) {\\n\\t\\t\\t\\t\\t\\tconst app = this.registry?._loader?._app || getApplication();\\n\\t\\t\\t\\t\\t\\tconst device = app?.graphicsDevice;\\n\\t\\t\\t\\t\\t\\tif (device) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0, len = VARIANT_DEFAULT_PRIORITY.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst variant = VARIANT_DEFAULT_PRIORITY[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (value.variants[variant] && device[VARIANT_SUPPORT[variant]]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvalue = value.variants[variant];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (app.enableBundles) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst bundles = app.bundles.listBundlesForAsset(this);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (bundles && bundles.find((b)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn b?.file?.variants[variant];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t})) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst oldFile = this._file;\\n\\t\\t\\t\\tconst newFile = value ? new AssetFile(value.url, value.filename, value.hash, value.size, value.opt, value.contents) : null;\\n\\t\\t\\t\\tif (!!newFile !== !!oldFile || newFile && !newFile.equals(oldFile)) {\\n\\t\\t\\t\\t\\t\\tthis._file = newFile;\\n\\t\\t\\t\\t\\t\\tthis.fire('change', this, 'file', newFile, oldFile);\\n\\t\\t\\t\\t\\t\\tthis.reload();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget file() {\\n\\t\\t\\t\\treturn this._file;\\n\\t\\t}\\n\\t\\tset data(value) {\\n\\t\\t\\t\\tconst old = this._data;\\n\\t\\t\\t\\tthis._data = value;\\n\\t\\t\\t\\tif (value !== old) {\\n\\t\\t\\t\\t\\t\\tthis.fire('change', this, 'data', value, old);\\n\\t\\t\\t\\t\\t\\tif (this.loaded) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.registry._loader.patch(this, this.registry);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget data() {\\n\\t\\t\\t\\treturn this._data;\\n\\t\\t}\\n\\t\\tset resource(value) {\\n\\t\\t\\t\\tconst _old = this._resources[0];\\n\\t\\t\\t\\tthis._resources[0] = value;\\n\\t\\t\\t\\tthis.fire('change', this, 'resource', value, _old);\\n\\t\\t}\\n\\t\\tget resource() {\\n\\t\\t\\t\\treturn this._resources[0];\\n\\t\\t}\\n\\t\\tset resources(value) {\\n\\t\\t\\t\\tconst _old = this._resources;\\n\\t\\t\\t\\tthis._resources = value;\\n\\t\\t\\t\\tthis.fire('change', this, 'resources', value, _old);\\n\\t\\t}\\n\\t\\tget resources() {\\n\\t\\t\\t\\treturn this._resources;\\n\\t\\t}\\n\\t\\tset preload(value) {\\n\\t\\t\\t\\tvalue = !!value;\\n\\t\\t\\t\\tif (this._preload === value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._preload = value;\\n\\t\\t\\t\\tif (this._preload && !this.loaded && !this.loading && this.registry) {\\n\\t\\t\\t\\t\\t\\tthis.registry.load(this);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget preload() {\\n\\t\\t\\t\\treturn this._preload;\\n\\t\\t}\\n\\t\\tset loadFaces(value) {\\n\\t\\t\\t\\tvalue = !!value;\\n\\t\\t\\t\\tif (!this.hasOwnProperty('_loadFaces') || value !== this._loadFaces) {\\n\\t\\t\\t\\t\\t\\tthis._loadFaces = value;\\n\\t\\t\\t\\t\\t\\tif (this.loaded) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.registry._loader.patch(this, this.registry);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget loadFaces() {\\n\\t\\t\\t\\treturn this._loadFaces;\\n\\t\\t}\\n\\t\\tgetFileUrl() {\\n\\t\\t\\t\\tconst file = this.file;\\n\\t\\t\\t\\tif (!file || !file.url) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet url = file.url;\\n\\t\\t\\t\\tif (this.registry && this.registry.prefix && !ABSOLUTE_URL.test(url)) {\\n\\t\\t\\t\\t\\t\\turl = this.registry.prefix + url;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.type !== \\\"script\\\" && file.hash) {\\n\\t\\t\\t\\t\\t\\tconst separator = url.indexOf('?') !== -1 ? '&' : '?';\\n\\t\\t\\t\\t\\t\\turl += `${separator}t=${file.hash}`;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn url;\\n\\t\\t}\\n\\t\\tgetAbsoluteUrl(relativePath) {\\n\\t\\t\\t\\tif (relativePath.startsWith('blob:') || relativePath.startsWith('data:')) {\\n\\t\\t\\t\\t\\t\\treturn relativePath;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst base = path.getDirectory(this.file.url);\\n\\t\\t\\t\\treturn path.join(base, relativePath);\\n\\t\\t}\\n\\t\\tgetLocalizedAssetId(locale) {\\n\\t\\t\\t\\tlocale = findAvailableLocale(locale, this._i18n);\\n\\t\\t\\t\\treturn this._i18n[locale] || null;\\n\\t\\t}\\n\\t\\taddLocalizedAssetId(locale, assetId) {\\n\\t\\t\\t\\tthis._i18n[locale] = assetId;\\n\\t\\t\\t\\tthis.fire('add:localized', locale, assetId);\\n\\t\\t}\\n\\t\\tremoveLocalizedAssetId(locale) {\\n\\t\\t\\t\\tconst assetId = this._i18n[locale];\\n\\t\\t\\t\\tif (assetId) {\\n\\t\\t\\t\\t\\t\\tdelete this._i18n[locale];\\n\\t\\t\\t\\t\\t\\tthis.fire('remove:localized', locale, assetId);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tready(callback, scope) {\\n\\t\\t\\t\\tscope = scope || this;\\n\\t\\t\\t\\tif (this.loaded) {\\n\\t\\t\\t\\t\\t\\tcallback.call(scope, this);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.once('load', (asset)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback.call(scope, asset);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treload() {\\n\\t\\t\\t\\tif (this.loaded) {\\n\\t\\t\\t\\t\\t\\tthis.loaded = false;\\n\\t\\t\\t\\t\\t\\tthis.registry.load(this);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tunload() {\\n\\t\\t\\t\\tif (!this.loaded && this._resources.length === 0) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.fire('unload', this);\\n\\t\\t\\t\\tthis.registry.fire(`unload:${this.id}`, this);\\n\\t\\t\\t\\tconst old = this._resources;\\n\\t\\t\\t\\tif (this.urlObject) {\\n\\t\\t\\t\\t\\t\\tURL.revokeObjectURL(this.urlObject);\\n\\t\\t\\t\\t\\t\\tthis.urlObject = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.resources = [];\\n\\t\\t\\t\\tthis.loaded = false;\\n\\t\\t\\t\\tif (this.file) {\\n\\t\\t\\t\\t\\t\\tthis.registry._loader.clearCache(this.getFileUrl(), this.type);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < old.length; ++i){\\n\\t\\t\\t\\t\\t\\told[i]?.destroy?.();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tstatic fetchArrayBuffer(loadUrl, callback, asset, maxRetries = 0) {\\n\\t\\t\\t\\tif (asset?.file?.contents) {\\n\\t\\t\\t\\t\\t\\tsetTimeout(()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(null, asset.file.contents);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\thttp.get(loadUrl, {\\n\\t\\t\\t\\t\\t\\t\\t\\tcache: true,\\n\\t\\t\\t\\t\\t\\t\\t\\tresponseType: 'arraybuffer',\\n\\t\\t\\t\\t\\t\\t\\t\\tretry: maxRetries > 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tmaxRetries: maxRetries,\\n\\t\\t\\t\\t\\t\\t\\t\\tprogress: asset\\n\\t\\t\\t\\t\\t\\t}, callback);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(name, type, file, data = {}, options = {}){\\n\\t\\t\\t\\tsuper(), this._file = null, this._i18n = {}, this._preload = false, this._resources = [], this.id = assetIdCounter--, this.loaded = false, this.loading = false, this.options = {}, this.registry = null, this.tags = new Tags(this), this.urlObject = null;\\n\\t\\t\\t\\tthis._name = name || '';\\n\\t\\t\\t\\tthis.type = type;\\n\\t\\t\\t\\tthis._data = data || {};\\n\\t\\t\\t\\tthis.options = options || {};\\n\\t\\t\\t\\tif (file) this.file = file;\\n\\t\\t}\\n}\\nAsset.EVENT_LOAD = 'load';\\nAsset.EVENT_UNLOAD = 'unload';\\nAsset.EVENT_REMOVE = 'remove';\\nAsset.EVENT_ERROR = 'error';\\nAsset.EVENT_CHANGE = 'change';\\nAsset.EVENT_PROGRESS = 'progress';\\nAsset.EVENT_ADDLOCALIZED = 'add:localized';\\nAsset.EVENT_REMOVELOCALIZED = 'remove:localized';\\n\\nclass TagsCache {\\n\\t\\taddItem(item) {\\n\\t\\t\\t\\tconst tags = item.tags._list;\\n\\t\\t\\t\\tfor (const tag of tags){\\n\\t\\t\\t\\t\\t\\tthis.add(tag, item);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tremoveItem(item) {\\n\\t\\t\\t\\tconst tags = item.tags._list;\\n\\t\\t\\t\\tfor (const tag of tags){\\n\\t\\t\\t\\t\\t\\tthis.remove(tag, item);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tadd(tag, item) {\\n\\t\\t\\t\\tif (this._index[tag] && this._index[tag].list.indexOf(item) !== -1) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._index[tag]) {\\n\\t\\t\\t\\t\\t\\tthis._index[tag] = {\\n\\t\\t\\t\\t\\t\\t\\t\\tlist: []\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tif (this._key) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._index[tag].keys = {};\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._index[tag].list.push(item);\\n\\t\\t\\t\\tif (this._key) {\\n\\t\\t\\t\\t\\t\\tthis._index[tag].keys[item[this._key]] = item;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tremove(tag, item) {\\n\\t\\t\\t\\tif (!this._index[tag]) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._key) {\\n\\t\\t\\t\\t\\t\\tif (!this._index[tag].keys[item[this._key]]) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst ind = this._index[tag].list.indexOf(item);\\n\\t\\t\\t\\tif (ind === -1) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._index[tag].list.splice(ind, 1);\\n\\t\\t\\t\\tif (this._key) {\\n\\t\\t\\t\\t\\t\\tdelete this._index[tag].keys[item[this._key]];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._index[tag].list.length === 0) {\\n\\t\\t\\t\\t\\t\\tdelete this._index[tag];\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tfind(args) {\\n\\t\\t\\t\\tconst index = {};\\n\\t\\t\\t\\tconst items = [];\\n\\t\\t\\t\\tlet item, tag, tags, tagsRest, missingIndex;\\n\\t\\t\\t\\tconst sort = (a, b)=>{\\n\\t\\t\\t\\t\\t\\treturn this._index[a].list.length - this._index[b].list.length;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tfor(let i = 0; i < args.length; i++){\\n\\t\\t\\t\\t\\t\\ttag = args[i];\\n\\t\\t\\t\\t\\t\\tif (tag instanceof Array) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (tag.length === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (tag.length === 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttag = tag[0];\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmissingIndex = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let t = 0; t < tag.length; t++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!this._index[tag[t]]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmissingIndex = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (missingIndex) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttags = tag.slice(0).sort(sort);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttagsRest = tags.slice(1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (tagsRest.length === 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttagsRest = tagsRest[0];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let n = 0; n < this._index[tags[0]].list.length; n++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\titem = this._index[tags[0]].list[n];\\n\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\t\\t\\tif (this._key) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindex[item[this._key]] = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\titems.push(item);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (tag && typeof tag === 'string' && this._index[tag]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let n = 0; n < this._index[tag].list.length; n++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\titem = this._index[tag].list[n];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this._key) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!index[item[this._key]]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindex[item[this._key]] = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\titems.push(item);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else if (items.indexOf(item) === -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\titems.push(item);\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn items;\\n\\t\\t}\\n\\t\\tconstructor(key = null){\\n\\t\\t\\t\\tthis._index = {};\\n\\t\\t\\t\\tthis._key = key;\\n\\t\\t}\\n}\\n\\nclass AssetRegistry extends EventHandler {\\n\\t\\tget loader() {\\n\\t\\t\\t\\treturn this._loader;\\n\\t\\t}\\n\\t\\tlist(filters = {}) {\\n\\t\\t\\t\\tconst assets = Array.from(this._assets);\\n\\t\\t\\t\\tif (filters.preload !== undefined) {\\n\\t\\t\\t\\t\\t\\treturn assets.filter((asset)=>asset.preload === filters.preload);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn assets;\\n\\t\\t}\\n\\t\\tadd(asset) {\\n\\t\\t\\t\\tif (this._assets.has(asset)) return;\\n\\t\\t\\t\\tthis._assets.add(asset);\\n\\t\\t\\t\\tthis._idToAsset.set(asset.id, asset);\\n\\t\\t\\t\\tif (asset.file?.url) {\\n\\t\\t\\t\\t\\t\\tthis._urlToAsset.set(asset.file.url, asset);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._nameToAsset.has(asset.name)) {\\n\\t\\t\\t\\t\\t\\tthis._nameToAsset.set(asset.name, new Set());\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._nameToAsset.get(asset.name).add(asset);\\n\\t\\t\\t\\tasset.on('name', this._onNameChange, this);\\n\\t\\t\\t\\tasset.registry = this;\\n\\t\\t\\t\\tthis._tags.addItem(asset);\\n\\t\\t\\t\\tasset.tags.on('add', this._onTagAdd, this);\\n\\t\\t\\t\\tasset.tags.on('remove', this._onTagRemove, this);\\n\\t\\t\\t\\tthis.fire('add', asset);\\n\\t\\t\\t\\tthis.fire(`add:${asset.id}`, asset);\\n\\t\\t\\t\\tif (asset.file?.url) {\\n\\t\\t\\t\\t\\t\\tthis.fire(`add:url:${asset.file.url}`, asset);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (asset.preload) {\\n\\t\\t\\t\\t\\t\\tthis.load(asset);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tremove(asset) {\\n\\t\\t\\t\\tif (!this._assets.has(asset)) return false;\\n\\t\\t\\t\\tthis._assets.delete(asset);\\n\\t\\t\\t\\tthis._idToAsset.delete(asset.id);\\n\\t\\t\\t\\tif (asset.file?.url) {\\n\\t\\t\\t\\t\\t\\tthis._urlToAsset.delete(asset.file.url);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tasset.off('name', this._onNameChange, this);\\n\\t\\t\\t\\tif (this._nameToAsset.has(asset.name)) {\\n\\t\\t\\t\\t\\t\\tconst items = this._nameToAsset.get(asset.name);\\n\\t\\t\\t\\t\\t\\titems.delete(asset);\\n\\t\\t\\t\\t\\t\\tif (items.size === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._nameToAsset.delete(asset.name);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._tags.removeItem(asset);\\n\\t\\t\\t\\tasset.tags.off('add', this._onTagAdd, this);\\n\\t\\t\\t\\tasset.tags.off('remove', this._onTagRemove, this);\\n\\t\\t\\t\\tasset.fire('remove', asset);\\n\\t\\t\\t\\tthis.fire('remove', asset);\\n\\t\\t\\t\\tthis.fire(`remove:${asset.id}`, asset);\\n\\t\\t\\t\\tif (asset.file?.url) {\\n\\t\\t\\t\\t\\t\\tthis.fire(`remove:url:${asset.file.url}`, asset);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tget(id) {\\n\\t\\t\\t\\treturn this._idToAsset.get(Number(id));\\n\\t\\t}\\n\\t\\tgetByUrl(url) {\\n\\t\\t\\t\\treturn this._urlToAsset.get(url);\\n\\t\\t}\\n\\t\\tload(asset, options) {\\n\\t\\t\\t\\tif ((asset.loading || asset.loaded) && !options?.force) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst file = asset.file;\\n\\t\\t\\t\\tconst _fireLoad = ()=>{\\n\\t\\t\\t\\t\\t\\tthis.fire('load', asset);\\n\\t\\t\\t\\t\\t\\tthis.fire(`load:${asset.id}`, asset);\\n\\t\\t\\t\\t\\t\\tif (file && file.url) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire(`load:url:${file.url}`, asset);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tasset.fire('load', asset);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst _opened = (resource)=>{\\n\\t\\t\\t\\t\\t\\tif (resource instanceof Array) {\\n\\t\\t\\t\\t\\t\\t\\t\\tasset.resources = resource;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tasset.resource = resource;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._loader.patch(asset, this);\\n\\t\\t\\t\\t\\t\\tif (asset.type === 'bundle') {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst assetIds = asset.data.assets;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < assetIds.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst assetInBundle = this._idToAsset.get(assetIds[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (assetInBundle && !assetInBundle.loaded) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.load(assetInBundle, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tforce: true\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\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\\tif (asset.resource.loaded) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_fireLoad();\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('load:start', asset);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fire(`load:start:${asset.id}`, asset);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (file && file.url) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fire(`load:start:url:${file.url}`, asset);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tasset.fire('load:start', asset);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tasset.resource.on('load', _fireLoad);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t_fireLoad();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst _loaded = (err, resource, extra)=>{\\n\\t\\t\\t\\t\\t\\tasset.loaded = true;\\n\\t\\t\\t\\t\\t\\tasset.loading = false;\\n\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('error', err, asset);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire(`error:${asset.id}`, err, asset);\\n\\t\\t\\t\\t\\t\\t\\t\\tasset.fire('error', err, asset);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (asset.type === \\\"script\\\") {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst handler = this._loader.getHandler(\\\"script\\\");\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (handler._cache[asset.id] && handler._cache[asset.id].parentNode === document.head) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdocument.head.removeChild(handler._cache[asset.id]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (extra) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\thandler._cache[asset.id] = extra;\\n\\t\\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\\t_opened(resource);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (file || asset.type === 'cubemap') {\\n\\t\\t\\t\\t\\t\\tthis.fire('load:start', asset);\\n\\t\\t\\t\\t\\t\\tthis.fire(`load:${asset.id}:start`, asset);\\n\\t\\t\\t\\t\\t\\tasset.loading = true;\\n\\t\\t\\t\\t\\t\\tconst fileUrl = asset.getFileUrl();\\n\\t\\t\\t\\t\\t\\tif (asset.type === 'bundle') {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst assetIds = asset.data.assets;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < assetIds.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst assetInBundle = this._idToAsset.get(assetIds[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!assetInBundle) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (assetInBundle.loaded || assetInBundle.resource || assetInBundle.loading) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tassetInBundle.loading = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._loader.load(fileUrl, asset.type, _loaded, asset, options);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst resource = this._loader.open(asset.type, asset.data);\\n\\t\\t\\t\\t\\t\\tasset.loaded = true;\\n\\t\\t\\t\\t\\t\\t_opened(resource);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tloadFromUrl(url, type, callback) {\\n\\t\\t\\t\\tthis.loadFromUrlAndFilename(url, null, type, callback);\\n\\t\\t}\\n\\t\\tloadFromUrlAndFilename(url, filename, type, callback) {\\n\\t\\t\\t\\tconst name = path.getBasename(filename || url);\\n\\t\\t\\t\\tconst file = {\\n\\t\\t\\t\\t\\t\\tfilename: filename || name,\\n\\t\\t\\t\\t\\t\\turl: url\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tlet asset = this.getByUrl(url);\\n\\t\\t\\t\\tif (!asset) {\\n\\t\\t\\t\\t\\t\\tasset = new Asset(name, type, file);\\n\\t\\t\\t\\t\\t\\tthis.add(asset);\\n\\t\\t\\t\\t} else if (asset.loaded) {\\n\\t\\t\\t\\t\\t\\tcallback(asset.loadFromUrlError || null, asset);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst startLoad = (asset)=>{\\n\\t\\t\\t\\t\\t\\tasset.once('load', (loadedAsset)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (type === 'material') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._loadTextures(loadedAsset, (err, textures)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(err, loadedAsset);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(null, loadedAsset);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tasset.once('error', (err)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.loadFromUrlError = err;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(err, asset);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tthis.load(asset);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (asset.resource) {\\n\\t\\t\\t\\t\\t\\tcallback(null, asset);\\n\\t\\t\\t\\t} else if (type === 'model') {\\n\\t\\t\\t\\t\\t\\tthis._loadModel(asset, startLoad);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tstartLoad(asset);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_loadModel(modelAsset, continuation) {\\n\\t\\t\\t\\tconst url = modelAsset.getFileUrl();\\n\\t\\t\\t\\tconst ext = path.getExtension(url);\\n\\t\\t\\t\\tif (ext === '.json' || ext === '.glb') {\\n\\t\\t\\t\\t\\t\\tconst dir = path.getDirectory(url);\\n\\t\\t\\t\\t\\t\\tconst basename = path.getBasename(url);\\n\\t\\t\\t\\t\\t\\tconst mappingUrl = path.join(dir, basename.replace(ext, '.mapping.json'));\\n\\t\\t\\t\\t\\t\\tthis._loader.load(mappingUrl, 'json', (err, data)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmodelAsset.data = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmapping: []\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinuation(modelAsset);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._loadMaterials(modelAsset, data, (e, materials)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmodelAsset.data = data;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinuation(modelAsset);\\n\\t\\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});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tcontinuation(modelAsset);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_loadMaterials(modelAsset, mapping, callback) {\\n\\t\\t\\t\\tconst materials = [];\\n\\t\\t\\t\\tlet count = 0;\\n\\t\\t\\t\\tconst onMaterialLoaded = (err, materialAsset)=>{\\n\\t\\t\\t\\t\\t\\tthis._loadTextures(materialAsset, (err, textures)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tmaterials.push(materialAsset);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (materials.length === count) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(null, materials);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tfor(let i = 0; i < mapping.mapping.length; i++){\\n\\t\\t\\t\\t\\t\\tconst path = mapping.mapping[i].path;\\n\\t\\t\\t\\t\\t\\tif (path) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcount++;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst url = modelAsset.getAbsoluteUrl(path);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.loadFromUrl(url, 'material', onMaterialLoaded);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (count === 0) {\\n\\t\\t\\t\\t\\t\\tcallback(null, materials);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_loadTextures(materialAsset, callback) {\\n\\t\\t\\t\\tconst textures = [];\\n\\t\\t\\t\\tlet count = 0;\\n\\t\\t\\t\\tconst data = materialAsset.data;\\n\\t\\t\\t\\tif (data.mappingFormat !== 'path') {\\n\\t\\t\\t\\t\\t\\tcallback(null, textures);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst onTextureLoaded = (err, texture)=>{\\n\\t\\t\\t\\t\\t\\tif (err) console.error(err);\\n\\t\\t\\t\\t\\t\\ttextures.push(texture);\\n\\t\\t\\t\\t\\t\\tif (textures.length === count) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(null, textures);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst texParams = standardMaterialTextureParameters;\\n\\t\\t\\t\\tfor(let i = 0; i < texParams.length; i++){\\n\\t\\t\\t\\t\\t\\tconst path = data[texParams[i]];\\n\\t\\t\\t\\t\\t\\tif (path && typeof path === 'string') {\\n\\t\\t\\t\\t\\t\\t\\t\\tcount++;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst url = materialAsset.getAbsoluteUrl(path);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.loadFromUrl(url, 'texture', onTextureLoaded);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (count === 0) {\\n\\t\\t\\t\\t\\t\\tcallback(null, textures);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onTagAdd(tag, asset) {\\n\\t\\t\\t\\tthis._tags.add(tag, asset);\\n\\t\\t}\\n\\t\\t_onTagRemove(tag, asset) {\\n\\t\\t\\t\\tthis._tags.remove(tag, asset);\\n\\t\\t}\\n\\t\\t_onNameChange(asset, name, nameOld) {\\n\\t\\t\\t\\tif (this._nameToAsset.has(nameOld)) {\\n\\t\\t\\t\\t\\t\\tconst items = this._nameToAsset.get(nameOld);\\n\\t\\t\\t\\t\\t\\titems.delete(asset);\\n\\t\\t\\t\\t\\t\\tif (items.size === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._nameToAsset.delete(nameOld);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._nameToAsset.has(asset.name)) {\\n\\t\\t\\t\\t\\t\\tthis._nameToAsset.set(asset.name, new Set());\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._nameToAsset.get(asset.name).add(asset);\\n\\t\\t}\\n\\t\\tfindByTag(...query) {\\n\\t\\t\\t\\treturn this._tags.find(query);\\n\\t\\t}\\n\\t\\tfilter(callback) {\\n\\t\\t\\t\\treturn Array.from(this._assets).filter((asset)=>callback(asset));\\n\\t\\t}\\n\\t\\tfind(name, type) {\\n\\t\\t\\t\\tconst items = this._nameToAsset.get(name);\\n\\t\\t\\t\\tif (!items) return null;\\n\\t\\t\\t\\tfor (const asset of items){\\n\\t\\t\\t\\t\\t\\tif (!type || asset.type === type) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn asset;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tfindAll(name, type) {\\n\\t\\t\\t\\tconst items = this._nameToAsset.get(name);\\n\\t\\t\\t\\tif (!items) return [];\\n\\t\\t\\t\\tconst results = Array.from(items);\\n\\t\\t\\t\\tif (!type) return results;\\n\\t\\t\\t\\treturn results.filter((asset)=>asset.type === type);\\n\\t\\t}\\n\\t\\tlog() {}\\n\\t\\tconstructor(loader){\\n\\t\\t\\t\\tsuper(), this._assets = new Set(), this._idToAsset = new Map(), this._urlToAsset = new Map(), this._nameToAsset = new Map(), this._tags = new TagsCache('id'), this.prefix = null, this.bundles = null;\\n\\t\\t\\t\\tthis._loader = loader;\\n\\t\\t}\\n}\\nAssetRegistry.EVENT_LOAD = 'load';\\nAssetRegistry.EVENT_ADD = 'add';\\nAssetRegistry.EVENT_REMOVE = 'remove';\\nAssetRegistry.EVENT_ERROR = 'error';\\n\\nclass BundleRegistry {\\n\\t\\t_onAssetAdd(asset) {\\n\\t\\t\\t\\tif (asset.type === 'bundle') {\\n\\t\\t\\t\\t\\t\\tthis._idToBundle.set(asset.id, asset);\\n\\t\\t\\t\\t\\t\\tthis._assets.on(`load:start:${asset.id}`, this._onBundleLoadStart, this);\\n\\t\\t\\t\\t\\t\\tthis._assets.on(`load:${asset.id}`, this._onBundleLoad, this);\\n\\t\\t\\t\\t\\t\\tthis._assets.on(`error:${asset.id}`, this._onBundleError, this);\\n\\t\\t\\t\\t\\t\\tconst assetIds = asset.data.assets;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < assetIds.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._indexAssetInBundle(assetIds[i], asset);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (this._assetToBundles.has(asset.id)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._indexAssetFileUrls(asset);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_unbindAssetEvents(id) {\\n\\t\\t\\t\\tthis._assets.off(`load:start:${id}`, this._onBundleLoadStart, this);\\n\\t\\t\\t\\tthis._assets.off(`load:${id}`, this._onBundleLoad, this);\\n\\t\\t\\t\\tthis._assets.off(`error:${id}`, this._onBundleError, this);\\n\\t\\t}\\n\\t\\t_indexAssetInBundle(id, bundle) {\\n\\t\\t\\t\\tlet bundles = this._assetToBundles.get(id);\\n\\t\\t\\t\\tif (!bundles) {\\n\\t\\t\\t\\t\\t\\tbundles = new Set();\\n\\t\\t\\t\\t\\t\\tthis._assetToBundles.set(id, bundles);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tbundles.add(bundle);\\n\\t\\t\\t\\tconst asset = this._assets.get(id);\\n\\t\\t\\t\\tif (asset) this._indexAssetFileUrls(asset);\\n\\t\\t}\\n\\t\\t_indexAssetFileUrls(asset) {\\n\\t\\t\\t\\tconst urls = this._getAssetFileUrls(asset);\\n\\t\\t\\t\\tif (!urls) return;\\n\\t\\t\\t\\tfor(let i = 0; i < urls.length; i++){\\n\\t\\t\\t\\t\\t\\tconst bundles = this._assetToBundles.get(asset.id);\\n\\t\\t\\t\\t\\t\\tif (!bundles) continue;\\n\\t\\t\\t\\t\\t\\tthis._urlsToBundles.set(urls[i], bundles);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_getAssetFileUrls(asset) {\\n\\t\\t\\t\\tlet url = asset.getFileUrl();\\n\\t\\t\\t\\tif (!url) return null;\\n\\t\\t\\t\\turl = url.split('?')[0];\\n\\t\\t\\t\\tconst urls = [\\n\\t\\t\\t\\t\\t\\turl\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tif (asset.type === 'font') {\\n\\t\\t\\t\\t\\t\\tconst numFiles = asset.data.info.maps.length;\\n\\t\\t\\t\\t\\t\\tfor(let i = 1; i < numFiles; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\turls.push(url.replace('.png', `${i}.png`));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn urls;\\n\\t\\t}\\n\\t\\t_onAssetRemove(asset) {\\n\\t\\t\\t\\tif (asset.type === 'bundle') {\\n\\t\\t\\t\\t\\t\\tthis._idToBundle.delete(asset.id);\\n\\t\\t\\t\\t\\t\\tthis._unbindAssetEvents(asset.id);\\n\\t\\t\\t\\t\\t\\tconst assetIds = asset.data.assets;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < assetIds.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst bundles = this._assetToBundles.get(assetIds[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!bundles) continue;\\n\\t\\t\\t\\t\\t\\t\\t\\tbundles.delete(asset);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (bundles.size === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._assetToBundles.delete(assetIds[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor (const [url, otherBundles] of this._urlsToBundles){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (otherBundles !== bundles) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._urlsToBundles.delete(url);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tthis._onBundleError(`Bundle ${asset.id} was removed`);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst bundles = this._assetToBundles.get(asset.id);\\n\\t\\t\\t\\t\\t\\tif (!bundles) return;\\n\\t\\t\\t\\t\\t\\tthis._assetToBundles.delete(asset.id);\\n\\t\\t\\t\\t\\t\\tconst urls = this._getAssetFileUrls(asset);\\n\\t\\t\\t\\t\\t\\tif (!urls) return;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < urls.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._urlsToBundles.delete(urls[i]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onBundleLoadStart(asset) {\\n\\t\\t\\t\\tasset.resource.on('add', (url, data)=>{\\n\\t\\t\\t\\t\\t\\tconst callbacks = this._fileRequests.get(url);\\n\\t\\t\\t\\t\\t\\tif (!callbacks) return;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < callbacks.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tcallbacks[i](null, data);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._fileRequests.delete(url);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\t_onBundleLoad(asset) {\\n\\t\\t\\t\\tif (!asset.resource) {\\n\\t\\t\\t\\t\\t\\tthis._onBundleError(`Bundle ${asset.id} failed to load`);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._fileRequests) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const [url, requests] of this._fileRequests){\\n\\t\\t\\t\\t\\t\\tconst bundles = this._urlsToBundles.get(url);\\n\\t\\t\\t\\t\\t\\tif (!bundles || !bundles.has(asset)) continue;\\n\\t\\t\\t\\t\\t\\tconst decodedUrl = decodeURIComponent(url);\\n\\t\\t\\t\\t\\t\\tlet err, data;\\n\\t\\t\\t\\t\\t\\tif (asset.resource.has(decodedUrl)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdata = asset.resource.get(decodedUrl);\\n\\t\\t\\t\\t\\t\\t} else if (asset.resource.loaded) {\\n\\t\\t\\t\\t\\t\\t\\t\\terr = `Bundle ${asset.id} does not contain URL ${url}`;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < requests.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\trequests[i](err, err || data);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._fileRequests.delete(url);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onBundleError(err) {\\n\\t\\t\\t\\tfor (const [url, requests] of this._fileRequests){\\n\\t\\t\\t\\t\\t\\tconst bundle = this._findLoadedOrLoadingBundleForUrl(url);\\n\\t\\t\\t\\t\\t\\tif (!bundle) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < requests.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trequests[i](err);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._fileRequests.delete(url);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_findLoadedOrLoadingBundleForUrl(url) {\\n\\t\\t\\t\\tconst bundles = this._urlsToBundles.get(url);\\n\\t\\t\\t\\tif (!bundles) return null;\\n\\t\\t\\t\\tlet candidate = null;\\n\\t\\t\\t\\tfor (const bundle of bundles){\\n\\t\\t\\t\\t\\t\\tif (bundle.loaded && bundle.resource) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn bundle;\\n\\t\\t\\t\\t\\t\\t} else if (bundle.loading) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcandidate = bundle;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn candidate;\\n\\t\\t}\\n\\t\\tlistBundlesForAsset(asset) {\\n\\t\\t\\t\\tconst bundles = this._assetToBundles.get(asset.id);\\n\\t\\t\\t\\tif (bundles) return Array.from(bundles);\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tlist() {\\n\\t\\t\\t\\treturn Array.from(this._idToBundle.values());\\n\\t\\t}\\n\\t\\thasUrl(url) {\\n\\t\\t\\t\\treturn this._urlsToBundles.has(url);\\n\\t\\t}\\n\\t\\turlIsLoadedOrLoading(url) {\\n\\t\\t\\t\\treturn !!this._findLoadedOrLoadingBundleForUrl(url);\\n\\t\\t}\\n\\t\\tloadUrl(url, callback) {\\n\\t\\t\\t\\tconst bundle = this._findLoadedOrLoadingBundleForUrl(url);\\n\\t\\t\\t\\tif (!bundle) {\\n\\t\\t\\t\\t\\t\\tcallback(`URL ${url} not found in any bundles`);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (bundle.loaded) {\\n\\t\\t\\t\\t\\t\\tconst decodedUrl = decodeURIComponent(url);\\n\\t\\t\\t\\t\\t\\tif (bundle.resource.has(decodedUrl)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(null, bundle.resource.get(decodedUrl));\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t} else if (bundle.resource.loaded) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(`Bundle ${bundle.id} does not contain URL ${url}`);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet callbacks = this._fileRequests.get(url);\\n\\t\\t\\t\\tif (!callbacks) {\\n\\t\\t\\t\\t\\t\\tcallbacks = [];\\n\\t\\t\\t\\t\\t\\tthis._fileRequests.set(url, callbacks);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcallbacks.push(callback);\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._assets.off('add', this._onAssetAdd, this);\\n\\t\\t\\t\\tthis._assets.off('remove', this._onAssetRemove, this);\\n\\t\\t\\t\\tfor (const id of this._idToBundle.keys()){\\n\\t\\t\\t\\t\\t\\tthis._unbindAssetEvents(id);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._assets = null;\\n\\t\\t\\t\\tthis._idToBundle.clear();\\n\\t\\t\\t\\tthis._idToBundle = null;\\n\\t\\t\\t\\tthis._assetToBundles.clear();\\n\\t\\t\\t\\tthis._assetToBundles = null;\\n\\t\\t\\t\\tthis._urlsToBundles.clear();\\n\\t\\t\\t\\tthis._urlsToBundles = null;\\n\\t\\t\\t\\tthis._fileRequests.clear();\\n\\t\\t\\t\\tthis._fileRequests = null;\\n\\t\\t}\\n\\t\\tconstructor(assets){\\n\\t\\t\\t\\tthis._idToBundle = new Map();\\n\\t\\t\\t\\tthis._assetToBundles = new Map();\\n\\t\\t\\t\\tthis._urlsToBundles = new Map();\\n\\t\\t\\t\\tthis._fileRequests = new Map();\\n\\t\\t\\t\\tthis._assets = assets;\\n\\t\\t\\t\\tthis._assets.bundles = this;\\n\\t\\t\\t\\tthis._assets.on('add', this._onAssetAdd, this);\\n\\t\\t\\t\\tthis._assets.on('remove', this._onAssetRemove, this);\\n\\t\\t}\\n}\\n\\nclass ComponentSystemRegistry extends EventHandler {\\n\\t\\tadd(system) {\\n\\t\\t\\t\\tconst id = system.id;\\n\\t\\t\\t\\tif (this[id]) {\\n\\t\\t\\t\\t\\t\\tthrow new Error(`ComponentSystem name '${id}' already registered or not allowed`);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis[id] = system;\\n\\t\\t\\t\\tthis.list.push(system);\\n\\t\\t}\\n\\t\\tremove(system) {\\n\\t\\t\\t\\tconst id = system.id;\\n\\t\\t\\t\\tif (!this[id]) {\\n\\t\\t\\t\\t\\t\\tthrow new Error(`No ComponentSystem named '${id}' registered`);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdelete this[id];\\n\\t\\t\\t\\tconst index = this.list.indexOf(this[id]);\\n\\t\\t\\t\\tif (index !== -1) {\\n\\t\\t\\t\\t\\t\\tthis.list.splice(index, 1);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.off();\\n\\t\\t\\t\\tfor(let i = 0; i < this.list.length; i++){\\n\\t\\t\\t\\t\\t\\tthis.list[i].destroy();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.list = [];\\n\\t\\t}\\n}\\n\\nclass Bundle extends EventHandler {\\n\\t\\taddFile(url, data) {\\n\\t\\t\\t\\tif (this._index.has(url)) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._index.set(url, data);\\n\\t\\t\\t\\tthis.fire('add', url, data);\\n\\t\\t}\\n\\t\\thas(url) {\\n\\t\\t\\t\\treturn this._index.has(url);\\n\\t\\t}\\n\\t\\tget(url) {\\n\\t\\t\\t\\treturn this._index.get(url) || null;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._index.clear();\\n\\t\\t}\\n\\t\\tset loaded(value) {\\n\\t\\t\\t\\tif (!value || this._loaded) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._loaded = true;\\n\\t\\t\\t\\tthis.fire('load');\\n\\t\\t}\\n\\t\\tget loaded() {\\n\\t\\t\\t\\treturn this._loaded;\\n\\t\\t}\\n\\t\\tconstructor(...args){\\n\\t\\t\\t\\tsuper(...args), this._index = new Map(), this._loaded = false;\\n\\t\\t}\\n}\\nBundle.EVENT_ADD = 'add';\\nBundle.EVENT_LOAD = 'load';\\n\\nclass Untar extends EventHandler {\\n\\t\\tpump(done, value) {\\n\\t\\t\\t\\tif (done) {\\n\\t\\t\\t\\t\\t\\tthis.fire('done');\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.bytesReceived += value.byteLength;\\n\\t\\t\\t\\tconst data = new Uint8Array(this.data.length + value.length);\\n\\t\\t\\t\\tdata.set(this.data);\\n\\t\\t\\t\\tdata.set(value, this.data.length);\\n\\t\\t\\t\\tthis.data = data;\\n\\t\\t\\t\\twhile(this.readFile());\\n\\t\\t\\t\\treturn this.reader.read().then((res)=>{\\n\\t\\t\\t\\t\\t\\tthis.pump(res.done, res.value);\\n\\t\\t\\t\\t}).catch((err)=>{\\n\\t\\t\\t\\t\\t\\tthis.fire('error', err);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\treadFile() {\\n\\t\\t\\t\\tif (!this.headerRead && this.bytesReceived > this.bytesRead + this.headerSize) {\\n\\t\\t\\t\\t\\t\\tthis.headerRead = true;\\n\\t\\t\\t\\t\\t\\tconst view = new DataView(this.data.buffer, this.bytesRead, this.headerSize);\\n\\t\\t\\t\\t\\t\\tthis.decoder ?? (this.decoder = new TextDecoder('windows-1252'));\\n\\t\\t\\t\\t\\t\\tconst headers = this.decoder.decode(view);\\n\\t\\t\\t\\t\\t\\tthis.fileName = headers.substring(0, 100).replace(/\\\\0/g, '');\\n\\t\\t\\t\\t\\t\\tthis.fileSize = parseInt(headers.substring(124, 136), 8);\\n\\t\\t\\t\\t\\t\\tthis.fileType = headers.substring(156, 157);\\n\\t\\t\\t\\t\\t\\tthis.ustarFormat = headers.substring(257, 263);\\n\\t\\t\\t\\t\\t\\tif (this.ustarFormat.indexOf('ustar') !== -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst prefix = headers.substring(345, 500).replace(/\\\\0/g, '');\\n\\t\\t\\t\\t\\t\\t\\t\\tif (prefix.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fileName = prefix.trim() + this.fileName.trim();\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.bytesRead += 512;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.headerRead) {\\n\\t\\t\\t\\t\\t\\tif (this.bytesReceived < this.bytesRead + this.fileSize) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.fileType === '' || this.fileType === '0') {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dataView = new DataView(this.data.buffer, this.bytesRead, this.fileSize);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst file = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tname: this.prefix + this.fileName,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsize: this.fileSize,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata: dataView\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('file', file);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.bytesRead += this.fileSize;\\n\\t\\t\\t\\t\\t\\tthis.headerRead = false;\\n\\t\\t\\t\\t\\t\\tconst bytesRemained = this.bytesRead % this.paddingSize;\\n\\t\\t\\t\\t\\t\\tif (bytesRemained !== 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.bytesRead += this.paddingSize - bytesRemained;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tconstructor(fetchPromise, assetsPrefix = ''){\\n\\t\\t\\t\\tsuper(), this.headerSize = 512, this.paddingSize = 512, this.bytesRead = 0, this.bytesReceived = 0, this.headerRead = false, this.reader = null, this.data = new Uint8Array(0), this.decoder = null, this.prefix = '', this.fileName = '', this.fileSize = 0, this.fileType = '', this.ustarFormat = '';\\n\\t\\t\\t\\tthis.prefix = assetsPrefix || '';\\n\\t\\t\\t\\tthis.reader = fetchPromise.body.getReader();\\n\\t\\t\\t\\tthis.reader.read().then((res)=>{\\n\\t\\t\\t\\t\\t\\tthis.pump(res.done, res.value);\\n\\t\\t\\t\\t}).catch((err)=>{\\n\\t\\t\\t\\t\\t\\tthis.fire('error', err);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n}\\n\\nclass ResourceHandler {\\n\\t\\tset maxRetries(value) {\\n\\t\\t\\t\\tthis._maxRetries = value;\\n\\t\\t}\\n\\t\\tget maxRetries() {\\n\\t\\t\\t\\treturn this._maxRetries;\\n\\t\\t}\\n\\t\\tload(url, callback, asset) {}\\n\\t\\topen(url, data, asset) {\\n\\t\\t\\t\\treturn data;\\n\\t\\t}\\n\\t\\tpatch(asset, assets) {}\\n\\t\\tconstructor(app, handlerType){\\n\\t\\t\\t\\tthis.handlerType = '';\\n\\t\\t\\t\\tthis._maxRetries = 0;\\n\\t\\t\\t\\tthis._app = app;\\n\\t\\t\\t\\tthis.handlerType = handlerType;\\n\\t\\t}\\n}\\n\\nclass BundleHandler extends ResourceHandler {\\n\\t\\t_fetchRetries(url, options, retries = 0) {\\n\\t\\t\\t\\treturn new Promise((resolve, reject)=>{\\n\\t\\t\\t\\t\\t\\tconst tryFetch = ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tfetch(url, options).then(resolve).catch((err)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tretries++;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (retries < this.maxRetries) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttryFetch();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treject(err);\\n\\t\\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};\\n\\t\\t\\t\\t\\t\\ttryFetch();\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tload(url, callback) {\\n\\t\\t\\t\\tif (typeof url === 'string') {\\n\\t\\t\\t\\t\\t\\turl = {\\n\\t\\t\\t\\t\\t\\t\\t\\tload: url,\\n\\t\\t\\t\\t\\t\\t\\t\\toriginal: url\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._fetchRetries(url.load, {\\n\\t\\t\\t\\t\\t\\tmode: 'cors'\\n\\t\\t\\t\\t}, this.maxRetries).then((res)=>{\\n\\t\\t\\t\\t\\t\\tconst bundle = new Bundle();\\n\\t\\t\\t\\t\\t\\tcallback(null, bundle);\\n\\t\\t\\t\\t\\t\\tconst untar = new Untar(res, this._assets.prefix);\\n\\t\\t\\t\\t\\t\\tuntar.on('file', (file)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tbundle.addFile(file.name, file.data);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tuntar.on('done', ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tbundle.loaded = true;\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tuntar.on('error', (err)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}).catch((err)=>{\\n\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\topen(url, bundle) {\\n\\t\\t\\t\\treturn bundle;\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tsuper(app, 'bundle');\\n\\t\\t\\t\\tthis._assets = app.assets;\\n\\t\\t}\\n}\\n\\nclass ResourceLoader {\\n\\t\\taddHandler(type, handler) {\\n\\t\\t\\t\\tthis._handlers[type] = handler;\\n\\t\\t\\t\\thandler._loader = this;\\n\\t\\t}\\n\\t\\tremoveHandler(type) {\\n\\t\\t\\t\\tdelete this._handlers[type];\\n\\t\\t}\\n\\t\\tgetHandler(type) {\\n\\t\\t\\t\\treturn this._handlers[type];\\n\\t\\t}\\n\\t\\tstatic makeKey(url, type) {\\n\\t\\t\\t\\treturn `${url}-${type}`;\\n\\t\\t}\\n\\t\\tload(url, type, callback, asset, options) {\\n\\t\\t\\t\\tconst handler = this._handlers[type];\\n\\t\\t\\t\\tif (!handler) {\\n\\t\\t\\t\\t\\t\\tconst err = `No resource handler for asset type: '${type}' when loading [${url}]`;\\n\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!url) {\\n\\t\\t\\t\\t\\t\\tthis._loadNull(handler, callback, asset);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst key = ResourceLoader.makeKey(url, type);\\n\\t\\t\\t\\tif (this._cache[key] !== undefined) {\\n\\t\\t\\t\\t\\t\\tcallback(null, this._cache[key]);\\n\\t\\t\\t\\t} else if (this._requests[key]) {\\n\\t\\t\\t\\t\\t\\tthis._requests[key].push(callback);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._requests[key] = [\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t\\t\\tconst self = this;\\n\\t\\t\\t\\t\\t\\tconst handleLoad = function(err, urlObj) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tself._onFailure(key, err);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (urlObj.load instanceof DataView) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (handler.openBinary) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!self._requests[key]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst data = handler.openBinary(urlObj.load);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tself._onSuccess(key, data);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} catch (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tself._onFailure(key, err);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\turlObj.load = URL.createObjectURL(new Blob([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\turlObj.load\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t]));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (asset) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (asset.urlObject) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tURL.revokeObjectURL(asset.urlObject);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tasset.urlObject = urlObj.load;\\n\\t\\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\\thandler.load(urlObj, (err, data, extra)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!self._requests[key]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tself._onFailure(key, err);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tself._onSuccess(key, handler.open(urlObj.original, data, asset), extra);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} catch (e) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tself._onFailure(key, e);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t}, asset);\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tconst normalizedUrl = url.split('?')[0];\\n\\t\\t\\t\\t\\t\\tif (this._app.enableBundles && this._app.bundles.hasUrl(normalizedUrl) && !(options && options.bundlesIgnore)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this._app.bundles.urlIsLoadedOrLoading(normalizedUrl)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst bundles = this._app.bundles.listBundlesForAsset(asset);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet bundle;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (options && options.bundlesFilter) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbundle = options.bundlesFilter(bundles);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!bundle) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbundles?.sort((a, b)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn a.file.size - b.file.size;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbundle = bundles?.[0];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (bundle) this._app.assets?.load(bundle);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._app.bundles.loadUrl(normalizedUrl, (err, fileUrlFromBundle)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\thandleLoad(err, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tload: fileUrlFromBundle,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toriginal: normalizedUrl\\n\\t\\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} else {\\n\\t\\t\\t\\t\\t\\t\\t\\thandleLoad(null, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tload: url,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toriginal: asset && asset.file.filename || url\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_loadNull(handler, callback, asset) {\\n\\t\\t\\t\\tconst onLoad = function(err, data, extra) {\\n\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(null, handler.open(null, data, asset), extra);\\n\\t\\t\\t\\t\\t\\t\\t\\t} catch (e) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(e);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\thandler.load(null, onLoad, asset);\\n\\t\\t}\\n\\t\\t_onSuccess(key, result, extra) {\\n\\t\\t\\t\\tif (result !== null) {\\n\\t\\t\\t\\t\\t\\tthis._cache[key] = result;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tdelete this._cache[key];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < this._requests[key].length; i++){\\n\\t\\t\\t\\t\\t\\tthis._requests[key][i](null, result, extra);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdelete this._requests[key];\\n\\t\\t}\\n\\t\\t_onFailure(key, err) {\\n\\t\\t\\t\\tconsole.error(err);\\n\\t\\t\\t\\tif (this._requests[key]) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._requests[key].length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._requests[key][i](err);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tdelete this._requests[key];\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\topen(type, data) {\\n\\t\\t\\t\\tconst handler = this._handlers[type];\\n\\t\\t\\t\\tif (!handler) {\\n\\t\\t\\t\\t\\t\\tconsole.warn(`No resource handler found for: ${type}`);\\n\\t\\t\\t\\t\\t\\treturn data;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn handler.open(null, data);\\n\\t\\t}\\n\\t\\tpatch(asset, assets) {\\n\\t\\t\\t\\tconst handler = this._handlers[asset.type];\\n\\t\\t\\t\\tif (!handler) {\\n\\t\\t\\t\\t\\t\\tconsole.warn(`No resource handler found for: ${asset.type}`);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (handler.patch) {\\n\\t\\t\\t\\t\\t\\thandler.patch(asset, assets);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tclearCache(url, type) {\\n\\t\\t\\t\\tconst key = ResourceLoader.makeKey(url, type);\\n\\t\\t\\t\\tdelete this._cache[key];\\n\\t\\t}\\n\\t\\tgetFromCache(url, type) {\\n\\t\\t\\t\\tconst key = ResourceLoader.makeKey(url, type);\\n\\t\\t\\t\\tif (this._cache[key]) {\\n\\t\\t\\t\\t\\t\\treturn this._cache[key];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn undefined;\\n\\t\\t}\\n\\t\\tenableRetry(maxRetries = 5) {\\n\\t\\t\\t\\tmaxRetries = Math.max(0, maxRetries) || 0;\\n\\t\\t\\t\\tfor(const key in this._handlers){\\n\\t\\t\\t\\t\\t\\tthis._handlers[key].maxRetries = maxRetries;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdisableRetry() {\\n\\t\\t\\t\\tfor(const key in this._handlers){\\n\\t\\t\\t\\t\\t\\tthis._handlers[key].maxRetries = 0;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._handlers = {};\\n\\t\\t\\t\\tthis._requests = {};\\n\\t\\t\\t\\tthis._cache = {};\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tthis._handlers = {};\\n\\t\\t\\t\\tthis._requests = {};\\n\\t\\t\\t\\tthis._cache = {};\\n\\t\\t\\t\\tthis._app = app;\\n\\t\\t}\\n}\\n\\nclass I18nParser {\\n\\t\\t_validate(data) {\\n\\t\\t\\t\\tif (!data.header) {\\n\\t\\t\\t\\t\\t\\tthrow new Error('pc.I18n#addData: Missing \\\"header\\\" field');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!data.header.version) {\\n\\t\\t\\t\\t\\t\\tthrow new Error('pc.I18n#addData: Missing \\\"header.version\\\" field');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (data.header.version !== 1) {\\n\\t\\t\\t\\t\\t\\tthrow new Error('pc.I18n#addData: Invalid \\\"header.version\\\" field');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!data.data) {\\n\\t\\t\\t\\t\\t\\tthrow new Error('pc.I18n#addData: Missing \\\"data\\\" field');\\n\\t\\t\\t\\t} else if (!Array.isArray(data.data)) {\\n\\t\\t\\t\\t\\t\\tthrow new Error('pc.I18n#addData: \\\"data\\\" field must be an array');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0, len = data.data.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst entry = data.data[i];\\n\\t\\t\\t\\t\\t\\tif (!entry.info) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthrow new Error(`pc.I18n#addData: missing \\\"data[${i}].info\\\" field`);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!entry.info.locale) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthrow new Error(`pc.I18n#addData: missing \\\"data[${i}].info.locale\\\" field`);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (typeof entry.info.locale !== 'string') {\\n\\t\\t\\t\\t\\t\\t\\t\\tthrow new Error(`pc.I18n#addData: \\\"data[${i}].info.locale\\\" must be a string`);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!entry.messages) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthrow new Error(`pc.I18n#addData: missing \\\"data[${i}].messages\\\" field`);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tparse(data) {\\n\\t\\t\\t\\treturn data.data;\\n\\t\\t}\\n}\\n\\nclass I18n extends EventHandler {\\n\\t\\tset assets(value) {\\n\\t\\t\\t\\tconst index = {};\\n\\t\\t\\t\\tfor(let i = 0, len = value.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst id = value[i] instanceof Asset ? value[i].id : value[i];\\n\\t\\t\\t\\t\\t\\tindex[id] = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet i = this._assets.length;\\n\\t\\t\\t\\twhile(i--){\\n\\t\\t\\t\\t\\t\\tconst id = this._assets[i];\\n\\t\\t\\t\\t\\t\\tif (!index[id]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._app.assets.off(`add:${id}`, this._onAssetAdd, this);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst asset = this._app.assets.get(id);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (asset) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._onAssetRemove(asset);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._assets.splice(i, 1);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(const id in index){\\n\\t\\t\\t\\t\\t\\tconst idNum = parseInt(id, 10);\\n\\t\\t\\t\\t\\t\\tif (this._assets.indexOf(idNum) !== -1) continue;\\n\\t\\t\\t\\t\\t\\tthis._assets.push(idNum);\\n\\t\\t\\t\\t\\t\\tconst asset = this._app.assets.get(idNum);\\n\\t\\t\\t\\t\\t\\tif (!asset) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._app.assets.once(`add:${idNum}`, this._onAssetAdd, this);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._onAssetAdd(asset);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget assets() {\\n\\t\\t\\t\\treturn this._assets;\\n\\t\\t}\\n\\t\\tset locale(value) {\\n\\t\\t\\t\\tif (this._locale === value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet lang = getLang(value);\\n\\t\\t\\t\\tif (lang === 'in') {\\n\\t\\t\\t\\t\\t\\tlang = 'id';\\n\\t\\t\\t\\t\\t\\tvalue = replaceLang(value, lang);\\n\\t\\t\\t\\t\\t\\tif (this._locale === value) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst old = this._locale;\\n\\t\\t\\t\\tthis._locale = value;\\n\\t\\t\\t\\tthis._lang = lang;\\n\\t\\t\\t\\tthis._pluralFn = getPluralFn(this._lang);\\n\\t\\t\\t\\tthis.fire(I18n.EVENT_CHANGE, value, old);\\n\\t\\t}\\n\\t\\tget locale() {\\n\\t\\t\\t\\treturn this._locale;\\n\\t\\t}\\n\\t\\tstatic findAvailableLocale(desiredLocale, availableLocales) {\\n\\t\\t\\t\\treturn findAvailableLocale(desiredLocale, availableLocales);\\n\\t\\t}\\n\\t\\tfindAvailableLocale(desiredLocale) {\\n\\t\\t\\t\\tif (this._translations[desiredLocale]) {\\n\\t\\t\\t\\t\\t\\treturn desiredLocale;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst lang = getLang(desiredLocale);\\n\\t\\t\\t\\treturn this._findFallbackLocale(desiredLocale, lang);\\n\\t\\t}\\n\\t\\tgetText(key, locale) {\\n\\t\\t\\t\\tlet result = key;\\n\\t\\t\\t\\tlet lang;\\n\\t\\t\\t\\tif (!locale) {\\n\\t\\t\\t\\t\\t\\tlocale = this._locale;\\n\\t\\t\\t\\t\\t\\tlang = this._lang;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet translations = this._translations[locale];\\n\\t\\t\\t\\tif (!translations) {\\n\\t\\t\\t\\t\\t\\tif (!lang) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlang = getLang(locale);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlocale = this._findFallbackLocale(locale, lang);\\n\\t\\t\\t\\t\\t\\ttranslations = this._translations[locale];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (translations && translations.hasOwnProperty(key)) {\\n\\t\\t\\t\\t\\t\\tresult = translations[key];\\n\\t\\t\\t\\t\\t\\tif (Array.isArray(result)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult = result[0];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (result === null || result === undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult = key;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tgetPluralText(key, n, locale) {\\n\\t\\t\\t\\tlet result = key;\\n\\t\\t\\t\\tlet lang;\\n\\t\\t\\t\\tlet pluralFn;\\n\\t\\t\\t\\tif (!locale) {\\n\\t\\t\\t\\t\\t\\tlocale = this._locale;\\n\\t\\t\\t\\t\\t\\tlang = this._lang;\\n\\t\\t\\t\\t\\t\\tpluralFn = this._pluralFn;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tlang = getLang(locale);\\n\\t\\t\\t\\t\\t\\tpluralFn = getPluralFn(lang);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet translations = this._translations[locale];\\n\\t\\t\\t\\tif (!translations) {\\n\\t\\t\\t\\t\\t\\tlocale = this._findFallbackLocale(locale, lang);\\n\\t\\t\\t\\t\\t\\tlang = getLang(locale);\\n\\t\\t\\t\\t\\t\\tpluralFn = getPluralFn(lang);\\n\\t\\t\\t\\t\\t\\ttranslations = this._translations[locale];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (translations && translations[key] && pluralFn) {\\n\\t\\t\\t\\t\\t\\tconst index = pluralFn(n);\\n\\t\\t\\t\\t\\t\\tresult = translations[key][index];\\n\\t\\t\\t\\t\\t\\tif (result === null || result === undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult = key;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\taddData(data) {\\n\\t\\t\\t\\tlet parsed;\\n\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\tparsed = this._parser.parse(data);\\n\\t\\t\\t\\t} catch (err) {\\n\\t\\t\\t\\t\\t\\tconsole.error(err);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0, len = parsed.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst entry = parsed[i];\\n\\t\\t\\t\\t\\t\\tconst locale = entry.info.locale;\\n\\t\\t\\t\\t\\t\\tconst messages = entry.messages;\\n\\t\\t\\t\\t\\t\\tif (!this._translations[locale]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._translations[locale] = {};\\n\\t\\t\\t\\t\\t\\t\\t\\tconst lang = getLang(locale);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this._availableLangs[lang]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._availableLangs[lang] = locale;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tObject.assign(this._translations[locale], messages);\\n\\t\\t\\t\\t\\t\\tthis.fire('data:add', locale, messages);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tremoveData(data) {\\n\\t\\t\\t\\tlet parsed;\\n\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\tparsed = this._parser.parse(data);\\n\\t\\t\\t\\t} catch (err) {\\n\\t\\t\\t\\t\\t\\tconsole.error(err);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0, len = parsed.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst entry = parsed[i];\\n\\t\\t\\t\\t\\t\\tconst locale = entry.info.locale;\\n\\t\\t\\t\\t\\t\\tconst translations = this._translations[locale];\\n\\t\\t\\t\\t\\t\\tif (!translations) continue;\\n\\t\\t\\t\\t\\t\\tconst messages = entry.messages;\\n\\t\\t\\t\\t\\t\\tfor(const key in messages){\\n\\t\\t\\t\\t\\t\\t\\t\\tdelete translations[key];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (Object.keys(translations).length === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdelete this._translations[locale];\\n\\t\\t\\t\\t\\t\\t\\t\\tdelete this._availableLangs[getLang(locale)];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.fire('data:remove', locale, messages);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._translations = null;\\n\\t\\t\\t\\tthis._availableLangs = null;\\n\\t\\t\\t\\tthis._assets = null;\\n\\t\\t\\t\\tthis._parser = null;\\n\\t\\t\\t\\tthis.off();\\n\\t\\t}\\n\\t\\t_findFallbackLocale(locale, lang) {\\n\\t\\t\\t\\tlet result = DEFAULT_LOCALE_FALLBACKS[locale];\\n\\t\\t\\t\\tif (result && this._translations[result]) {\\n\\t\\t\\t\\t\\t\\treturn result;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tresult = DEFAULT_LOCALE_FALLBACKS[lang];\\n\\t\\t\\t\\tif (result && this._translations[result]) {\\n\\t\\t\\t\\t\\t\\treturn result;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tresult = this._availableLangs[lang];\\n\\t\\t\\t\\tif (result && this._translations[result]) {\\n\\t\\t\\t\\t\\t\\treturn result;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn DEFAULT_LOCALE;\\n\\t\\t}\\n\\t\\t_onAssetAdd(asset) {\\n\\t\\t\\t\\tasset.on('load', this._onAssetLoad, this);\\n\\t\\t\\t\\tasset.on('change', this._onAssetChange, this);\\n\\t\\t\\t\\tasset.on('remove', this._onAssetRemove, this);\\n\\t\\t\\t\\tasset.on('unload', this._onAssetUnload, this);\\n\\t\\t\\t\\tif (asset.resource) {\\n\\t\\t\\t\\t\\t\\tthis._onAssetLoad(asset);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onAssetLoad(asset) {\\n\\t\\t\\t\\tthis.addData(asset.resource);\\n\\t\\t}\\n\\t\\t_onAssetChange(asset) {\\n\\t\\t\\t\\tif (asset.resource) {\\n\\t\\t\\t\\t\\t\\tthis.addData(asset.resource);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onAssetRemove(asset) {\\n\\t\\t\\t\\tasset.off('load', this._onAssetLoad, this);\\n\\t\\t\\t\\tasset.off('change', this._onAssetChange, this);\\n\\t\\t\\t\\tasset.off('remove', this._onAssetRemove, this);\\n\\t\\t\\t\\tasset.off('unload', this._onAssetUnload, this);\\n\\t\\t\\t\\tif (asset.resource) {\\n\\t\\t\\t\\t\\t\\tthis.removeData(asset.resource);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._app.assets.once(`add:${asset.id}`, this._onAssetAdd, this);\\n\\t\\t}\\n\\t\\t_onAssetUnload(asset) {\\n\\t\\t\\t\\tif (asset.resource) {\\n\\t\\t\\t\\t\\t\\tthis.removeData(asset.resource);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.locale = DEFAULT_LOCALE;\\n\\t\\t\\t\\tthis._translations = {};\\n\\t\\t\\t\\tthis._availableLangs = {};\\n\\t\\t\\t\\tthis._app = app;\\n\\t\\t\\t\\tthis._assets = [];\\n\\t\\t\\t\\tthis._parser = new I18nParser();\\n\\t\\t}\\n}\\nI18n.EVENT_CHANGE = 'change';\\n\\nclass ScriptRegistry extends EventHandler {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.app = null;\\n\\t\\t\\t\\tthis.off();\\n\\t\\t}\\n\\t\\taddSchema(id, schema) {\\n\\t\\t\\t\\tif (!schema) return;\\n\\t\\t\\t\\tthis._scriptSchemas.set(id, schema);\\n\\t\\t}\\n\\t\\tgetSchema(id) {\\n\\t\\t\\t\\treturn this._scriptSchemas.get(id);\\n\\t\\t}\\n\\t\\tadd(script) {\\n\\t\\t\\t\\tconst scriptName = script.__name;\\n\\t\\t\\t\\tif (this._scripts.hasOwnProperty(scriptName)) {\\n\\t\\t\\t\\t\\t\\tsetTimeout(()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (script.prototype.swap) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst old = this._scripts[scriptName];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst ind = this._list.indexOf(old);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._list[ind] = script;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._scripts[scriptName] = script;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('swap', scriptName, script);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fire(`swap:${scriptName}`, script);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._scripts[scriptName] = script;\\n\\t\\t\\t\\tthis._list.push(script);\\n\\t\\t\\t\\tthis.fire('add', scriptName, script);\\n\\t\\t\\t\\tthis.fire(`add:${scriptName}`, script);\\n\\t\\t\\t\\tsetTimeout(()=>{\\n\\t\\t\\t\\t\\t\\tif (!this._scripts.hasOwnProperty(scriptName)) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!this.app || !this.app.systems || !this.app.systems.script) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst components = this.app.systems.script._components;\\n\\t\\t\\t\\t\\t\\tlet attributes;\\n\\t\\t\\t\\t\\t\\tconst scriptInstances = [];\\n\\t\\t\\t\\t\\t\\tconst scriptInstancesInitialized = [];\\n\\t\\t\\t\\t\\t\\tfor(components.loopIndex = 0; components.loopIndex < components.length; components.loopIndex++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst component = components.items[components.loopIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (component._scriptsIndex[scriptName] && component._scriptsIndex[scriptName].awaiting) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (component._scriptsData && component._scriptsData[scriptName]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tattributes = component._scriptsData[scriptName].attributes;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst scriptInstance = component.create(scriptName, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpreloading: true,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tind: component._scriptsIndex[scriptName].ind,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tattributes: attributes\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (scriptInstance) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscriptInstances.push(scriptInstance);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor (const script of component.scripts){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcomponent.initializeAttributes(script);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < scriptInstances.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (scriptInstances[i].enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscriptInstances[i]._initialized = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscriptInstancesInitialized.push(scriptInstances[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (scriptInstances[i].initialize) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscriptInstances[i].initialize();\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < scriptInstancesInitialized.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!scriptInstancesInitialized[i].enabled || scriptInstancesInitialized[i]._postInitialized) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tscriptInstancesInitialized[i]._postInitialized = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (scriptInstancesInitialized[i].postInitialize) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscriptInstancesInitialized[i].postInitialize();\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tremove(nameOrType) {\\n\\t\\t\\t\\tlet scriptType = nameOrType;\\n\\t\\t\\t\\tlet scriptName = nameOrType;\\n\\t\\t\\t\\tif (typeof scriptName !== 'string') {\\n\\t\\t\\t\\t\\t\\tscriptName = scriptType.__name;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tscriptType = this.get(scriptName);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.get(scriptName) !== scriptType) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdelete this._scripts[scriptName];\\n\\t\\t\\t\\tconst ind = this._list.indexOf(scriptType);\\n\\t\\t\\t\\tthis._list.splice(ind, 1);\\n\\t\\t\\t\\tthis.fire('remove', scriptName, scriptType);\\n\\t\\t\\t\\tthis.fire(`remove:${scriptName}`, scriptType);\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tget(name) {\\n\\t\\t\\t\\treturn this._scripts[name] || null;\\n\\t\\t}\\n\\t\\thas(nameOrType) {\\n\\t\\t\\t\\tif (typeof nameOrType === 'string') {\\n\\t\\t\\t\\t\\t\\treturn this._scripts.hasOwnProperty(nameOrType);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!nameOrType) return false;\\n\\t\\t\\t\\tconst scriptName = nameOrType.__name;\\n\\t\\t\\t\\treturn this._scripts[scriptName] === nameOrType;\\n\\t\\t}\\n\\t\\tlist() {\\n\\t\\t\\t\\treturn this._list;\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tsuper(), this._scripts = {}, this._list = [], this._scriptSchemas = new Map();\\n\\t\\t\\t\\tthis.app = app;\\n\\t\\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\\t\\treturn tmpPool.pop() ?? [];\\n};\\nconst releaseTempArray = (a)=>{\\n\\t\\ta.length = 0;\\n\\t\\ttmpPool.push(a);\\n};\\nclass Entity extends GraphNode {\\n\\t\\taddComponent(type, data) {\\n\\t\\t\\t\\tconst system = this._app.systems[type];\\n\\t\\t\\t\\tif (!system) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.c[type]) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn system.addComponent(this, data);\\n\\t\\t}\\n\\t\\tremoveComponent(type) {\\n\\t\\t\\t\\tconst system = this._app.systems[type];\\n\\t\\t\\t\\tif (!system) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this.c[type]) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tsystem.removeComponent(this);\\n\\t\\t}\\n\\t\\tfindComponent(type) {\\n\\t\\t\\t\\tconst entity = this.findOne((entity)=>entity.c?.[type]);\\n\\t\\t\\t\\treturn entity && entity.c[type];\\n\\t\\t}\\n\\t\\tfindComponents(type) {\\n\\t\\t\\t\\treturn this.find((entity)=>entity.c?.[type]).map((entity)=>entity.c[type]);\\n\\t\\t}\\n\\t\\tfindScript(nameOrType) {\\n\\t\\t\\t\\tconst entity = this.findOne((node)=>node.c?.script?.has(nameOrType));\\n\\t\\t\\t\\treturn entity?.c.script.get(nameOrType);\\n\\t\\t}\\n\\t\\tfindScripts(nameOrType) {\\n\\t\\t\\t\\tconst entities = this.find((node)=>node.c?.script?.has(nameOrType));\\n\\t\\t\\t\\treturn entities.map((entity)=>entity.c.script.get(nameOrType));\\n\\t\\t}\\n\\t\\tgetGuid() {\\n\\t\\t\\t\\tif (!this._guid) {\\n\\t\\t\\t\\t\\t\\tthis.setGuid(guid.create());\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._guid;\\n\\t\\t}\\n\\t\\tsetGuid(guid) {\\n\\t\\t\\t\\tconst index = this._app._entityIndex;\\n\\t\\t\\t\\tif (this._guid) {\\n\\t\\t\\t\\t\\t\\tdelete index[this._guid];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._guid = guid;\\n\\t\\t\\t\\tindex[this._guid] = this;\\n\\t\\t}\\n\\t\\t_notifyHierarchyStateChanged(node, enabled) {\\n\\t\\t\\t\\tlet enableFirst = false;\\n\\t\\t\\t\\tif (node === this && _enableList.length === 0) {\\n\\t\\t\\t\\t\\t\\tenableFirst = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tnode._beingEnabled = true;\\n\\t\\t\\t\\tnode._onHierarchyStateChanged(enabled);\\n\\t\\t\\t\\tif (node._onHierarchyStatePostChanged) {\\n\\t\\t\\t\\t\\t\\t_enableList.push(node);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst c = node._children;\\n\\t\\t\\t\\tfor(let i = 0, len = c.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tif (c[i]._enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._notifyHierarchyStateChanged(c[i], enabled);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tnode._beingEnabled = false;\\n\\t\\t\\t\\tif (enableFirst) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < _enableList.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t_enableList[i]._onHierarchyStatePostChanged();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t_enableList.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onHierarchyStateChanged(enabled) {\\n\\t\\t\\t\\tsuper._onHierarchyStateChanged(enabled);\\n\\t\\t\\t\\tconst components = this._getSortedComponents();\\n\\t\\t\\t\\tfor(let i = 0; i < components.length; i++){\\n\\t\\t\\t\\t\\t\\tconst component = components[i];\\n\\t\\t\\t\\t\\t\\tif (component.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcomponent.onEnable();\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcomponent.onDisable();\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treleaseTempArray(components);\\n\\t\\t}\\n\\t\\t_onHierarchyStatePostChanged() {\\n\\t\\t\\t\\tconst components = this._getSortedComponents();\\n\\t\\t\\t\\tfor(let i = 0; i < components.length; i++){\\n\\t\\t\\t\\t\\t\\tcomponents[i].onPostStateChange();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treleaseTempArray(components);\\n\\t\\t}\\n\\t\\tfindByGuid(guid) {\\n\\t\\t\\t\\tif (this._guid === guid) return this;\\n\\t\\t\\t\\tconst e = this._app._entityIndex[guid];\\n\\t\\t\\t\\tif (e && (e === this || e.isDescendantOf(this))) {\\n\\t\\t\\t\\t\\t\\treturn e;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._destroying = true;\\n\\t\\t\\t\\tfor(const name in this.c){\\n\\t\\t\\t\\t\\t\\tthis.c[name].enabled = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(const name in this.c){\\n\\t\\t\\t\\t\\t\\tthis.c[name].system.removeComponent(this);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tsuper.destroy();\\n\\t\\t\\t\\tif (this._guid) {\\n\\t\\t\\t\\t\\t\\tdelete this._app._entityIndex[this._guid];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._destroying = false;\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\tconst duplicatedIdsMap = {};\\n\\t\\t\\t\\tconst clone = this._cloneRecursively(duplicatedIdsMap);\\n\\t\\t\\t\\tduplicatedIdsMap[this.getGuid()] = clone;\\n\\t\\t\\t\\tresolveDuplicatedEntityReferenceProperties(this, this, clone, duplicatedIdsMap);\\n\\t\\t\\t\\treturn clone;\\n\\t\\t}\\n\\t\\t_getSortedComponents() {\\n\\t\\t\\t\\tconst components = this.c;\\n\\t\\t\\t\\tconst sortedArray = getTempArray();\\n\\t\\t\\t\\tlet needSort = 0;\\n\\t\\t\\t\\tfor(const type in components){\\n\\t\\t\\t\\t\\t\\tif (components.hasOwnProperty(type)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst component = components[type];\\n\\t\\t\\t\\t\\t\\t\\t\\tneedSort |= component.constructor.order !== 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tsortedArray.push(component);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (needSort && sortedArray.length > 1) {\\n\\t\\t\\t\\t\\t\\tsortStaticOrder(sortedArray);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn sortedArray;\\n\\t\\t}\\n\\t\\t_cloneRecursively(duplicatedIdsMap) {\\n\\t\\t\\t\\tconst clone = new this.constructor(undefined, this._app);\\n\\t\\t\\t\\tsuper._cloneInternal(clone);\\n\\t\\t\\t\\tfor(const type in this.c){\\n\\t\\t\\t\\t\\t\\tconst component = this.c[type];\\n\\t\\t\\t\\t\\t\\tcomponent.system.cloneComponent(this, clone);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < this._children.length; i++){\\n\\t\\t\\t\\t\\t\\tconst oldChild = this._children[i];\\n\\t\\t\\t\\t\\t\\tif (oldChild instanceof Entity) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst newChild = oldChild._cloneRecursively(duplicatedIdsMap);\\n\\t\\t\\t\\t\\t\\t\\t\\tclone.addChild(newChild);\\n\\t\\t\\t\\t\\t\\t\\t\\tduplicatedIdsMap[oldChild.getGuid()] = newChild;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn clone;\\n\\t\\t}\\n\\t\\tconstructor(name, app = getApplication()){\\n\\t\\t\\t\\tsuper(name), this.c = {}, this._destroying = false, this._guid = null, this._template = false;\\n\\t\\t\\t\\tthis._app = app;\\n\\t\\t}\\n}\\nEntity.EVENT_DESTROY = 'destroy';\\nfunction resolveDuplicatedEntityReferenceProperties(oldSubtreeRoot, oldEntity, newEntity, duplicatedIdsMap) {\\n\\t\\tif (oldEntity instanceof Entity) {\\n\\t\\t\\t\\tconst components = oldEntity.c;\\n\\t\\t\\t\\tfor(const componentName in components){\\n\\t\\t\\t\\t\\t\\tconst component = components[componentName];\\n\\t\\t\\t\\t\\t\\tconst entityProperties = component.system.getPropertiesOfType('entity');\\n\\t\\t\\t\\t\\t\\tfor(let i = 0, len = entityProperties.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst propertyDescriptor = entityProperties[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst propertyName = propertyDescriptor.name;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst oldEntityReferenceId = component[propertyName];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst entityIsWithinOldSubtree = !!oldSubtreeRoot.findByGuid(oldEntityReferenceId);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (entityIsWithinOldSubtree) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst newEntityReferenceId = duplicatedIdsMap[oldEntityReferenceId].getGuid();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (newEntityReferenceId) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnewEntity.c[componentName][propertyName] = newEntityReferenceId;\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (components.script) {\\n\\t\\t\\t\\t\\t\\tnewEntity.script.resolveDuplicatedEntityReferenceProperties(components.script, duplicatedIdsMap);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (components.render) {\\n\\t\\t\\t\\t\\t\\tnewEntity.render.resolveDuplicatedEntityReferenceProperties(components.render, duplicatedIdsMap);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (components.button) {\\n\\t\\t\\t\\t\\t\\tnewEntity.button.resolveDuplicatedEntityReferenceProperties(components.button, duplicatedIdsMap);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (components.scrollview) {\\n\\t\\t\\t\\t\\t\\tnewEntity.scrollview.resolveDuplicatedEntityReferenceProperties(components.scrollview, duplicatedIdsMap);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (components.scrollbar) {\\n\\t\\t\\t\\t\\t\\tnewEntity.scrollbar.resolveDuplicatedEntityReferenceProperties(components.scrollbar, duplicatedIdsMap);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (components.anim) {\\n\\t\\t\\t\\t\\t\\tnewEntity.anim.resolveDuplicatedEntityReferenceProperties(components.anim, duplicatedIdsMap);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst _old = oldEntity.children.filter((e)=>e instanceof Entity);\\n\\t\\t\\t\\tconst _new = newEntity.children.filter((e)=>e instanceof Entity);\\n\\t\\t\\t\\tfor(let i = 0, len = _old.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tresolveDuplicatedEntityReferenceProperties(oldSubtreeRoot, _old[i], _new[i], duplicatedIdsMap);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass SceneRegistryItem {\\n\\t\\tget loaded() {\\n\\t\\t\\t\\treturn !!this.data;\\n\\t\\t}\\n\\t\\tget loading() {\\n\\t\\t\\t\\treturn this._loading;\\n\\t\\t}\\n\\t\\tconstructor(name, url){\\n\\t\\t\\t\\tthis.data = null;\\n\\t\\t\\t\\tthis._loading = false;\\n\\t\\t\\t\\tthis._onLoadedCallbacks = [];\\n\\t\\t\\t\\tthis.name = name;\\n\\t\\t\\t\\tthis.url = url;\\n\\t\\t}\\n}\\n\\nclass SceneRegistry {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._app = null;\\n\\t\\t}\\n\\t\\tlist() {\\n\\t\\t\\t\\treturn this._list;\\n\\t\\t}\\n\\t\\tadd(name, url) {\\n\\t\\t\\t\\tif (this._index.hasOwnProperty(name)) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst item = new SceneRegistryItem(name, url);\\n\\t\\t\\t\\tconst i = this._list.push(item);\\n\\t\\t\\t\\tthis._index[item.name] = i - 1;\\n\\t\\t\\t\\tthis._urlIndex[item.url] = i - 1;\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tfind(name) {\\n\\t\\t\\t\\tif (this._index.hasOwnProperty(name)) {\\n\\t\\t\\t\\t\\t\\treturn this._list[this._index[name]];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tfindByUrl(url) {\\n\\t\\t\\t\\tif (this._urlIndex.hasOwnProperty(url)) {\\n\\t\\t\\t\\t\\t\\treturn this._list[this._urlIndex[url]];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tremove(name) {\\n\\t\\t\\t\\tif (this._index.hasOwnProperty(name)) {\\n\\t\\t\\t\\t\\t\\tconst idx = this._index[name];\\n\\t\\t\\t\\t\\t\\tlet item = this._list[idx];\\n\\t\\t\\t\\t\\t\\tdelete this._urlIndex[item.url];\\n\\t\\t\\t\\t\\t\\tdelete this._index[name];\\n\\t\\t\\t\\t\\t\\tthis._list.splice(idx, 1);\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._list.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\titem = this._list[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._index[item.name] = i;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._urlIndex[item.url] = i;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_loadSceneData(sceneItem, storeInCache, callback) {\\n\\t\\t\\t\\tconst app = this._app;\\n\\t\\t\\t\\tlet url = sceneItem;\\n\\t\\t\\t\\tif (typeof sceneItem === 'string') {\\n\\t\\t\\t\\t\\t\\tsceneItem = this.findByUrl(url) || this.find(url) || new SceneRegistryItem('Untitled', url);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\turl = sceneItem.url;\\n\\t\\t\\t\\tif (!url) {\\n\\t\\t\\t\\t\\t\\tcallback('Cannot find scene to load');\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (sceneItem.loaded) {\\n\\t\\t\\t\\t\\t\\tcallback(null, sceneItem);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (app.assets && app.assets.prefix && !ABSOLUTE_URL.test(url)) {\\n\\t\\t\\t\\t\\t\\turl = path.join(app.assets.prefix, url);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tsceneItem._onLoadedCallbacks.push(callback);\\n\\t\\t\\t\\tif (!sceneItem._loading) {\\n\\t\\t\\t\\t\\t\\tconst handler = app.loader.getHandler('hierarchy');\\n\\t\\t\\t\\t\\t\\thandler.load(url, (err, data)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tsceneItem.data = data;\\n\\t\\t\\t\\t\\t\\t\\t\\tsceneItem._loading = false;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < sceneItem._onLoadedCallbacks.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsceneItem._onLoadedCallbacks[i](err, sceneItem);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!storeInCache) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsceneItem.data = null;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tsceneItem._onLoadedCallbacks.length = 0;\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tsceneItem._loading = true;\\n\\t\\t}\\n\\t\\tloadSceneData(sceneItem, callback) {\\n\\t\\t\\t\\tthis._loadSceneData(sceneItem, true, callback);\\n\\t\\t}\\n\\t\\tunloadSceneData(sceneItem) {\\n\\t\\t\\t\\tif (typeof sceneItem === 'string') {\\n\\t\\t\\t\\t\\t\\tsceneItem = this.findByUrl(sceneItem);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (sceneItem) {\\n\\t\\t\\t\\t\\t\\tsceneItem.data = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_loadSceneHierarchy(sceneItem, onBeforeAddHierarchy, callback) {\\n\\t\\t\\t\\tthis._loadSceneData(sceneItem, false, (err, sceneItem)=>{\\n\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (callback) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (onBeforeAddHierarchy) {\\n\\t\\t\\t\\t\\t\\t\\t\\tonBeforeAddHierarchy(sceneItem);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst app = this._app;\\n\\t\\t\\t\\t\\t\\tconst _loaded = ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst handler = app.loader.getHandler('hierarchy');\\n\\t\\t\\t\\t\\t\\t\\t\\tapp.systems.script.preloading = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst entity = handler.open(sceneItem.url, sceneItem.data);\\n\\t\\t\\t\\t\\t\\t\\t\\tapp.systems.script.preloading = false;\\n\\t\\t\\t\\t\\t\\t\\t\\tapp.loader.clearCache(sceneItem.url, 'hierarchy');\\n\\t\\t\\t\\t\\t\\t\\t\\tapp.root.addChild(entity);\\n\\t\\t\\t\\t\\t\\t\\t\\tapp.systems.fire('initialize', entity);\\n\\t\\t\\t\\t\\t\\t\\t\\tapp.systems.fire('postInitialize', entity);\\n\\t\\t\\t\\t\\t\\t\\t\\tapp.systems.fire('postPostInitialize', entity);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (callback) callback(null, entity);\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tapp._preloadScripts(sceneItem.data, _loaded);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tloadSceneHierarchy(sceneItem, callback) {\\n\\t\\t\\t\\tthis._loadSceneHierarchy(sceneItem, null, callback);\\n\\t\\t}\\n\\t\\tloadSceneSettings(sceneItem, callback) {\\n\\t\\t\\t\\tthis._loadSceneData(sceneItem, false, (err, sceneItem)=>{\\n\\t\\t\\t\\t\\t\\tif (!err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._app.applySceneSettings(sceneItem.data.settings);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (callback) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(null);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (callback) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tchangeScene(sceneItem, callback) {\\n\\t\\t\\t\\tconst app = this._app;\\n\\t\\t\\t\\tconst onBeforeAddHierarchy = (sceneItem)=>{\\n\\t\\t\\t\\t\\t\\tconst { children } = app.root;\\n\\t\\t\\t\\t\\t\\twhile(children.length){\\n\\t\\t\\t\\t\\t\\t\\t\\tchildren[0].destroy();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tapp.applySceneSettings(sceneItem.data.settings);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis._loadSceneHierarchy(sceneItem, onBeforeAddHierarchy, callback);\\n\\t\\t}\\n\\t\\tloadScene(url, callback) {\\n\\t\\t\\t\\tconst app = this._app;\\n\\t\\t\\t\\tconst handler = app.loader.getHandler('scene');\\n\\t\\t\\t\\tif (app.assets && app.assets.prefix && !ABSOLUTE_URL.test(url)) {\\n\\t\\t\\t\\t\\t\\turl = path.join(app.assets.prefix, url);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\thandler.load(url, (err, data)=>{\\n\\t\\t\\t\\t\\t\\tif (!err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst _loaded = ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tapp.systems.script.preloading = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst scene = handler.open(url, data);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst sceneItem = this.findByUrl(url);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (sceneItem && !sceneItem.loaded) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsceneItem.data = data;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tapp.systems.script.preloading = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tapp.loader.clearCache(url, 'scene');\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tapp.loader.patch({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresource: scene,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype: 'scene'\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}, app.assets);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tapp.root.addChild(scene.root);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (app.systems.rigidbody && typeof Ammo !== 'undefined') {\\n\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (callback) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(null, scene);\\n\\t\\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\\tapp._preloadScripts(data, _loaded);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (callback) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tthis._list = [];\\n\\t\\t\\t\\tthis._index = {};\\n\\t\\t\\t\\tthis._urlIndex = {};\\n\\t\\t\\t\\tthis._app = app;\\n\\t\\t}\\n}\\n\\nclass ApplicationStats {\\n\\t\\tget scene() {\\n\\t\\t\\t\\treturn getApplication().scene._stats;\\n\\t\\t}\\n\\t\\tget lightmapper() {\\n\\t\\t\\t\\treturn getApplication().lightmapper?.stats;\\n\\t\\t}\\n\\t\\tget batcher() {\\n\\t\\t\\t\\tconst batcher = getApplication()._batcher;\\n\\t\\t\\t\\treturn batcher ? batcher._stats : null;\\n\\t\\t}\\n\\t\\tframeEnd() {\\n\\t\\t\\t\\tthis.frame.gsplatSort = 0;\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis.frame = {\\n\\t\\t\\t\\t\\t\\tfps: 0,\\n\\t\\t\\t\\t\\t\\tms: 0,\\n\\t\\t\\t\\t\\t\\tdt: 0,\\n\\t\\t\\t\\t\\t\\tupdateStart: 0,\\n\\t\\t\\t\\t\\t\\tupdateTime: 0,\\n\\t\\t\\t\\t\\t\\trenderStart: 0,\\n\\t\\t\\t\\t\\t\\trenderTime: 0,\\n\\t\\t\\t\\t\\t\\tphysicsStart: 0,\\n\\t\\t\\t\\t\\t\\tphysicsTime: 0,\\n\\t\\t\\t\\t\\t\\tscriptUpdateStart: 0,\\n\\t\\t\\t\\t\\t\\tscriptUpdate: 0,\\n\\t\\t\\t\\t\\t\\tscriptPostUpdateStart: 0,\\n\\t\\t\\t\\t\\t\\tscriptPostUpdate: 0,\\n\\t\\t\\t\\t\\t\\tanimUpdateStart: 0,\\n\\t\\t\\t\\t\\t\\tanimUpdate: 0,\\n\\t\\t\\t\\t\\t\\tcullTime: 0,\\n\\t\\t\\t\\t\\t\\tsortTime: 0,\\n\\t\\t\\t\\t\\t\\tskinTime: 0,\\n\\t\\t\\t\\t\\t\\tmorphTime: 0,\\n\\t\\t\\t\\t\\t\\tinstancingTime: 0,\\n\\t\\t\\t\\t\\t\\ttriangles: 0,\\n\\t\\t\\t\\t\\t\\tgsplats: 0,\\n\\t\\t\\t\\t\\t\\tgsplatSort: 0,\\n\\t\\t\\t\\t\\t\\totherPrimitives: 0,\\n\\t\\t\\t\\t\\t\\tshaders: 0,\\n\\t\\t\\t\\t\\t\\tmaterials: 0,\\n\\t\\t\\t\\t\\t\\tcameras: 0,\\n\\t\\t\\t\\t\\t\\tshadowMapUpdates: 0,\\n\\t\\t\\t\\t\\t\\tshadowMapTime: 0,\\n\\t\\t\\t\\t\\t\\tdepthMapTime: 0,\\n\\t\\t\\t\\t\\t\\tforwardTime: 0,\\n\\t\\t\\t\\t\\t\\tlightClustersTime: 0,\\n\\t\\t\\t\\t\\t\\tlightClusters: 0,\\n\\t\\t\\t\\t\\t\\t_timeToCountFrames: 0,\\n\\t\\t\\t\\t\\t\\t_fpsAccum: 0\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.drawCalls = {\\n\\t\\t\\t\\t\\t\\tforward: 0,\\n\\t\\t\\t\\t\\t\\tdepth: 0,\\n\\t\\t\\t\\t\\t\\tshadow: 0,\\n\\t\\t\\t\\t\\t\\timmediate: 0,\\n\\t\\t\\t\\t\\t\\tmisc: 0,\\n\\t\\t\\t\\t\\t\\ttotal: 0,\\n\\t\\t\\t\\t\\t\\tskinned: 0,\\n\\t\\t\\t\\t\\t\\tinstanced: 0,\\n\\t\\t\\t\\t\\t\\tremovedByInstancing: 0\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.misc = {\\n\\t\\t\\t\\t\\t\\trenderTargetCreationTime: 0\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.particles = {\\n\\t\\t\\t\\t\\t\\tupdatesPerFrame: 0,\\n\\t\\t\\t\\t\\t\\t_updatesPerFrame: 0,\\n\\t\\t\\t\\t\\t\\tframeTime: 0,\\n\\t\\t\\t\\t\\t\\t_frameTime: 0\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.shaders = device._shaderStats;\\n\\t\\t\\t\\tthis.vram = device._vram;\\n\\t\\t\\t\\tthis.gpu = device.gpuProfiler?.passTimings ?? new Map();\\n\\t\\t\\t\\tObject.defineProperty(this.vram, 'totalUsed', {\\n\\t\\t\\t\\t\\t\\tget: function() {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn this.tex + this.vb + this.ib;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tObject.defineProperty(this.vram, 'geom', {\\n\\t\\t\\t\\t\\t\\tget: function() {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn this.vb + this.ib;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n}\\n\\nvar alphaTestPS$1 = `\\nuniform float alpha_ref;\\nvoid alphaTest(float a) {\\n\\tif (a < alpha_ref) discard;\\n}\\n`;\\n\\nvar ambientPS$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 anisotropyPS$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 aoPS$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 aoDiffuseOccPS$1 = `\\nvoid occludeDiffuse(float ao) {\\n\\tdDiffuseLight *= ao;\\n}\\n`;\\n\\nvar aoSpecOccPS$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 bakeDirLmEndPS$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 bakeLmEndPS$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 basePS$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 baseNineSlicedPS$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 baseNineSlicedTiledPS$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 bayerPS$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 blurVSMPS$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 clearCoatPS$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 clearCoatGlossPS$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 clearCoatNormalPS$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 clusteredLightUtilsPS$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 clusteredLightCookiesPS$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 clusteredLightShadowsPS$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 clusteredLightPS$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 halfWidth;\\n\\tbool isSpot;\\n\\tvec3 halfHeight;\\n\\tint lightIndex;\\n\\tvec3 position;\\n\\tuint shape;\\n\\tvec3 direction;\\n\\tbool falloffModeLinear;\\n\\tvec3 color;\\n\\tfloat shadowIntensity;\\n\\tvec3 omniAtlasViewport;\\n\\tfloat range;\\n\\tvec4 cookieChannelMask;\\n\\tfloat biasesData;\\n\\tfloat shadowBias;\\n\\tfloat shadowNormalBias;\\n\\tfloat innerConeAngleCos;\\n\\tfloat outerConeAngleCos;\\n\\tfloat cookieIntensity;\\n\\tbool isDynamic;\\n\\tbool isLightmapped;\\n};\\nmat4 lightProjectionMatrix;\\nuint clusterLightData_flags;\\nfloat clusterLightData_anglesData;\\nuint clusterLightData_colorBFlagsData;\\nvec4 sampleLightTextureF(const ClusterLightData clusterLightData, int index) {\\n\\treturn texelFetch(lightsTexture, ivec2(index, clusterLightData.lightIndex), 0);\\n}\\nvoid decodeClusterLightCore(inout ClusterLightData clusterLightData, int lightIndex) {\\n\\tclusterLightData.lightIndex = lightIndex;\\n\\tvec4 halfData = sampleLightTextureF(clusterLightData, {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(clusterLightData, {CLUSTER_TEXTURE_POSITION_RANGE});\\n\\tclusterLightData.position = lightPosRange.xyz;\\n\\tclusterLightData.range = lightPosRange.w;\\n\\tvec4 lightDir_Flags = sampleLightTextureF(clusterLightData, {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}\\nvoid decodeClusterLightSpot(inout ClusterLightData clusterLightData) {\\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\\tclusterLightData.innerConeAngleCos = mix(innerVal, 1.0 - innerVal, innerIsVersine);\\n\\tclusterLightData.outerConeAngleCos = mix(outerVal, 1.0 - outerVal, outerIsVersine);\\n}\\nvoid decodeClusterLightOmniAtlasViewport(inout ClusterLightData clusterLightData) {\\n\\tclusterLightData.omniAtlasViewport = sampleLightTextureF(clusterLightData, {CLUSTER_TEXTURE_PROJ_MAT_0}).xyz;\\n}\\nvoid decodeClusterLightAreaData(inout ClusterLightData clusterLightData) {\\n\\tclusterLightData.halfWidth = sampleLightTextureF(clusterLightData, {CLUSTER_TEXTURE_AREA_DATA_WIDTH}).xyz;\\n\\tclusterLightData.halfHeight = sampleLightTextureF(clusterLightData, {CLUSTER_TEXTURE_AREA_DATA_HEIGHT}).xyz;\\n}\\nvoid decodeClusterLightProjectionMatrixData(inout ClusterLightData clusterLightData) {\\n\\t\\n\\tvec4 m0 = sampleLightTextureF(clusterLightData, {CLUSTER_TEXTURE_PROJ_MAT_0});\\n\\tvec4 m1 = sampleLightTextureF(clusterLightData, {CLUSTER_TEXTURE_PROJ_MAT_1});\\n\\tvec4 m2 = sampleLightTextureF(clusterLightData, {CLUSTER_TEXTURE_PROJ_MAT_2});\\n\\tvec4 m3 = sampleLightTextureF(clusterLightData, {CLUSTER_TEXTURE_PROJ_MAT_3});\\n\\tlightProjectionMatrix = mat4(m0, m1, m2, m3);\\n}\\nvoid decodeClusterLightShadowData(inout ClusterLightData clusterLightData) {\\n\\t\\n\\tvec2 biases = unpackHalf2x16(floatBitsToUint(clusterLightData.biasesData));\\n\\tclusterLightData.shadowBias = biases.x;\\n\\tclusterLightData.shadowNormalBias = biases.y;\\n}\\nvoid decodeClusterLightCookieData(inout ClusterLightData clusterLightData) {\\n\\tuint cookieFlags = (clusterLightData_flags >> 23u) & 0x0Fu;\\n\\tclusterLightData.cookieChannelMask = vec4(uvec4(cookieFlags) & uvec4(1u, 2u, 4u, 8u));\\n\\tclusterLightData.cookieChannelMask = step(1.0, clusterLightData.cookieChannelMask);\\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\\tdecodeClusterLightAreaData(light);\\n\\t\\tif (light.shape == {LIGHTSHAPE_RECT}) {\\n\\t\\t\\tcalcRectLightValues(light.position, light.halfWidth, light.halfHeight);\\n\\t\\t} else if (light.shape == {LIGHTSHAPE_DISK}) {\\n\\t\\t\\tcalcDiskLightValues(light.position, light.halfWidth, light.halfHeight);\\n\\t\\t} else {\\n\\t\\t\\tcalcSphereLightValues(light.position, light.halfWidth, light.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\\tdecodeClusterLightSpot(light);\\n\\t\\t\\tfalloffAttenuation *= getSpotEffect(light.direction, light.innerConeAngleCos, light.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\\tif (light.isSpot) {\\n\\t\\t\\t\\t\\tdecodeClusterLightProjectionMatrixData(light);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tdecodeClusterLightOmniAtlasViewport(light);\\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\\tdecodeClusterLightCookieData(light);\\n\\t\\t\\t\\t\\tif (light.isSpot) {\\n\\t\\t\\t\\t\\t\\tcookieAttenuation = getCookie2DClustered(TEXTURE_PASS(cookieAtlasTexture), lightProjectionMatrix, vPositionW, light.cookieIntensity, light.cookieChannelMask);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tcookieAttenuation = getCookieCubeClustered(TEXTURE_PASS(cookieAtlasTexture), lightDirW, light.cookieIntensity, light.cookieChannelMask, shadowTextureResolution, shadowEdgePixels, light.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\\tdecodeClusterLightShadowData(light);\\n\\t\\t\\t\\t\\tvec4 shadowParams = vec4(shadowTextureResolution, light.shadowNormalBias, light.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, light.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, light.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, light.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;\\n\\tdecodeClusterLightCore(clusterLightData, 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 combinePS$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 cookieBlit2DPS$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 cookieBlitCubePS$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 cookieBlitVS$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 cookiePS = `\\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 cubeMapProjectPS$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 cubeMapRotatePS$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 debugOutputPS$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 debugProcessFrontendPS$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 decodePS$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 detailModesPS$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 diffusePS$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 emissivePS$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 encodePS$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 endPS$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 envAtlasPS$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 envProcPS$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 falloffInvSquaredPS$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 falloffLinearPS$1 = `\\nfloat getFalloffLinear(float lightRadius, vec3 lightDir) {\\n\\tfloat d = length(lightDir);\\n\\treturn max(((lightRadius - d) / lightRadius), 0.0);\\n}\\n`;\\n\\nvar floatAsUintPS$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 fogPS$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\\nfloat getFogFactor() {\\n\\tfloat depth = gl_FragCoord.z / gl_FragCoord.w;\\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}\\nvec3 addFog(vec3 color) {\\n\\t#if (FOG != NONE)\\n\\t\\treturn mix(fog_color * dBlendModeFogFactor, color, getFogFactor());\\n\\t#endif\\n\\treturn color;\\n}\\n`;\\n\\nvar fresnelSchlickPS$1 = `\\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 = pow(1.0 - saturate(cosTheta), 5.0);\\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 = pow(1.0 - saturate(cosTheta), 5.0);\\n\\treturn 0.04 + (1.0 - 0.04) * fresnel;\\n}\\n`;\\n\\nvar fullscreenQuadVS$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 gammaPS$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 glossPS$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 quadVS$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 immediateLinePS$1 = `\\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 immediateLineVS$1 = `\\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 iridescenceDiffractionPS$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 iridescencePS$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 iridescenceThicknessPS$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 iorPS$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 lightDeclarationPS$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 lightDiffuseLambertPS$1 = `\\nfloat getLightDiffuse(vec3 worldNormal, vec3 viewDir, vec3 lightDirNorm) {\\n\\treturn max(dot(worldNormal, -lightDirNorm), 0.0);\\n}\\n`;\\n\\nvar lightDirPointPS$1 = `\\nvec3 evalOmniLight(vec3 lightPosW) {\\n\\treturn vPositionW - lightPosW;\\n}\\n`;\\n\\nvar lightEvaluationPS$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 lightFunctionLightPS$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 lightFunctionShadowPS$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 lightingPS$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 lightmapAddPS$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 lightmapPS$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 lightSpecularAnisoGGXPS$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 lightSpecularGGXPS$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 lightSpecularBlinnPS$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 lightSheenPS$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 linearizeDepthPS$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 litForwardBackendPS$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 litForwardDeclarationPS$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 litForwardMainPS$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 litForwardPostCodePS$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#if LIT_FRESNEL_MODEL == SCHLICK\\n\\t\\t#include \\\"fresnelSchlickPS\\\"\\n\\t#endif\\n\\t#ifdef LIT_IRIDESCENCE\\n\\t\\t#include \\\"iridescenceDiffractionPS\\\"\\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 litForwardPreCodePS$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 litMainPS$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 litMainVS$1 = `\\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 litOtherMainPS$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 litShaderArgsPS$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 litShaderCorePS$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 litShadowMainPS$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 ltcPS$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 metalnessPS$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 msdfPS$1 = `\\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 metalnessModulatePS$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 morphPS$1 = `\\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 morphVS$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}\\n`;\\n\\nvar msdfVS$1 = `\\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 normalVS$1 = `\\nmat3 dNormalMatrix;\\nvec3 getNormal() {\\n\\tdNormalMatrix = getNormalMatrix(dModelMatrix);\\n\\tvec3 localNormal = getLocalNormal(vertex_normal);\\n\\treturn normalize(dNormalMatrix * localNormal);\\n}\\n`;\\n\\nvar normalCoreVS$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 normalMapPS$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 opacityPS$1 = `\\nuniform float material_opacity;\\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 opacityDitherPS$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\\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 outputPS$1 = `\\n`;\\n\\nvar outputAlphaPS$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 outputTex2DPS$1 = `\\nvarying vec2 vUv0;\\nuniform sampler2D source;\\nvoid main(void) {\\n\\tgl_FragColor = texture2D(source, vUv0);\\n}\\n`;\\n\\nvar sheenPS$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 sheenGlossPS$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 parallaxPS$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 pickPS$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\\tvec4 getPickDepth() {\\n\\t\\treturn float2uint(gl_FragCoord.z);\\n\\t}\\n#endif\\n`;\\n\\nvar reflDirPS$1 = `\\nvoid getReflDir(vec3 worldNormal, vec3 viewDir, float gloss, mat3 tbn) {\\n\\tdReflDirW = normalize(-reflect(viewDir, worldNormal));\\n}\\n`;\\n\\nvar reflDirAnisoPS$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 reflectionCCPS$1 = `\\n#ifdef LIT_CLEARCOAT\\nvoid addReflectionCC(vec3 reflDir, float gloss) {\\n\\tccReflection += calcReflection(reflDir, gloss);\\n}\\n#endif\\n`;\\n\\nvar reflectionCubePS$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 reflectionEnvHQPS$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 reflectionEnvPS$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 reflectionSpherePS$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 reflectionSheenPS$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 refractionCubePS$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 refractionDynamicPS$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 reprojectPS$1 = `\\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 reprojectVS$1 = `\\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 screenDepthPS$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 shadowCascadesPS$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 shadowEVSMPS$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 shadowPCF1PS$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 shadowPCF3PS$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 shadowPCF5PS$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 shadowPCSSPS = `\\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 shadowSoftPS$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 skinBatchVS$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 skinVS$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 skyboxPS$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 float vLinearDepth;\\n\\t\\t#include \\\"floatAsUintPS\\\"\\n\\t#endif\\n\\tvarying vec3 vViewDir;\\n\\tuniform float skyboxHighlightMultiplier;\\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#ifdef SKY_CUBEMAP\\n\\t\\t\\t\\t#ifdef SKYMESH\\n\\t\\t\\t\\t\\tvec3 envDir = normalize(vWorldPos - projectedSkydomeCenter);\\n\\t\\t\\t\\t\\tvec3 dir = envDir * cubeMapRotationMatrix;\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\tvec3 dir = vViewDir;\\n\\t\\t\\t\\t#endif\\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\\tvec3 dir = vViewDir * 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 skyboxVS$1 = `\\nattribute vec4 aPosition;\\nuniform mat4 matrix_view;\\nuniform mat4 matrix_projectionSkybox;\\nuniform mat3 cubeMapRotationMatrix;\\nvarying vec3 vViewDir;\\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\\tgl_Position = matrix_projectionSkybox * (view * aPosition);\\n\\t\\tvViewDir = aPosition.xyz * cubeMapRotationMatrix;\\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 specularPS$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 sphericalPS$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 specularityFactorPS$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 spotPS$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 startNineSlicedPS$1 = `\\n\\tnineSlicedUv = vec2(vUv0.x, 1.0 - vUv0.y);\\n`;\\n\\nvar startNineSlicedTiledPS$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 stdDeclarationPS$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 stdFrontEndPS$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, 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 TBNPS$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 thicknessPS$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 tonemappingPS$1 = `\\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 tonemappingAcesPS$1 = `\\nuniform float exposure;\\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 * exposure;\\n\\treturn (x*(tA*x+tB))/(x*(tC*x+tD)+tE);\\n}\\n`;\\n\\nvar tonemappingAces2PS$1 = `\\nuniform float exposure;\\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 *= exposure / 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 tonemappingFilmicPS$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;\\nuniform float exposure;\\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 * exposure);\\n\\tvec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W,W,W));\\n\\tcolor = color * whiteScale;\\n\\treturn color;\\n}\\n`;\\n\\nvar tonemappingHejlPS$1 = `\\nuniform float exposure;\\nvec3 toneMap(vec3 color) {\\n\\tcolor *= exposure;\\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 tonemappingLinearPS$1 = `\\nuniform float exposure;\\nvec3 toneMap(vec3 color) {\\n\\treturn color * exposure;\\n}\\n`;\\n\\nvar tonemappingNeutralPS$1 = `\\nuniform float exposure;\\nvec3 toneMap(vec3 color) {\\n\\tcolor *= exposure;\\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 tonemappingNonePS$1 = `\\nvec3 toneMap(vec3 color) {\\n\\treturn color;\\n}\\n`;\\n\\nvar transformVS$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 transformCoreVS$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 transformInstancingVS$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 transmissionPS$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 twoSidedLightingPS$1 = `\\nuniform float twoSidedLightingNegScaleFactor;\\nvoid handleTwoSidedLighting() {\\n\\tdTBN[2] *= gl_FrontFacing ? twoSidedLightingNegScaleFactor : -twoSidedLightingNegScaleFactor;\\n}\\n`;\\n\\nvar uv0VS$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 uv1VS$1 = `\\nvec2 getUv1() {\\n\\treturn vertex_texCoord1;\\n}\\n`;\\n\\nvar uvTransformVS$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 uvTransformUniformsPS$1 = `\\n\\tuniform vec3 {TRANSFORM_NAME_{i}}0;\\n\\tuniform vec3 {TRANSFORM_NAME_{i}}1;\\n`;\\n\\nvar viewDirPS$1 = `\\nvoid getViewDir() {\\n\\tdViewDirW = normalize(view_position - vPositionW);\\n}\\n`;\\n\\nconst shaderChunksGLSL = {\\n\\t\\talphaTestPS: alphaTestPS$1,\\n\\t\\tambientPS: ambientPS$1,\\n\\t\\tanisotropyPS: anisotropyPS$1,\\n\\t\\taoPS: aoPS$1,\\n\\t\\taoDiffuseOccPS: aoDiffuseOccPS$1,\\n\\t\\taoSpecOccPS: aoSpecOccPS$1,\\n\\t\\tbakeDirLmEndPS: bakeDirLmEndPS$1,\\n\\t\\tbakeLmEndPS: bakeLmEndPS$1,\\n\\t\\tbasePS: basePS$1,\\n\\t\\tbaseNineSlicedPS: baseNineSlicedPS$1,\\n\\t\\tbaseNineSlicedTiledPS: baseNineSlicedTiledPS$1,\\n\\t\\tbayerPS: bayerPS$1,\\n\\t\\tblurVSMPS: blurVSMPS$1,\\n\\t\\tclearCoatPS: clearCoatPS$1,\\n\\t\\tclearCoatGlossPS: clearCoatGlossPS$1,\\n\\t\\tclearCoatNormalPS: clearCoatNormalPS$1,\\n\\t\\tclusteredLightCookiesPS: clusteredLightCookiesPS$1,\\n\\t\\tclusteredLightShadowsPS: clusteredLightShadowsPS$1,\\n\\t\\tclusteredLightUtilsPS: clusteredLightUtilsPS$1,\\n\\t\\tclusteredLightPS: clusteredLightPS$1,\\n\\t\\tcombinePS: combinePS$1,\\n\\t\\tcookieBlit2DPS: cookieBlit2DPS$1,\\n\\t\\tcookieBlitCubePS: cookieBlitCubePS$1,\\n\\t\\tcookieBlitVS: cookieBlitVS$1,\\n\\t\\tcookiePS,\\n\\t\\tcubeMapProjectPS: cubeMapProjectPS$1,\\n\\t\\tcubeMapRotatePS: cubeMapRotatePS$1,\\n\\t\\tdebugOutputPS: debugOutputPS$1,\\n\\t\\tdebugProcessFrontendPS: debugProcessFrontendPS$1,\\n\\t\\tdetailModesPS: detailModesPS$1,\\n\\t\\tdiffusePS: diffusePS$1,\\n\\t\\tdecodePS: decodePS$1,\\n\\t\\temissivePS: emissivePS$1,\\n\\t\\tencodePS: encodePS$1,\\n\\t\\tendPS: endPS$1,\\n\\t\\tenvAtlasPS: envAtlasPS$1,\\n\\t\\tenvProcPS: envProcPS$1,\\n\\t\\tfalloffInvSquaredPS: falloffInvSquaredPS$1,\\n\\t\\tfalloffLinearPS: falloffLinearPS$1,\\n\\t\\tfloatAsUintPS: floatAsUintPS$1,\\n\\t\\tfogPS: fogPS$1,\\n\\t\\tfresnelSchlickPS: fresnelSchlickPS$1,\\n\\t\\tfrontendCodePS: '',\\n\\t\\tfrontendDeclPS: '',\\n\\t\\tfullscreenQuadVS: fullscreenQuadVS$1,\\n\\t\\tgammaPS: gammaPS$1,\\n\\t\\tgles3PS,\\n\\t\\tgles3VS,\\n\\t\\tglossPS: glossPS$1,\\n\\t\\tquadVS: quadVS$1,\\n\\t\\timmediateLinePS: immediateLinePS$1,\\n\\t\\timmediateLineVS: immediateLineVS$1,\\n\\t\\tiridescenceDiffractionPS: iridescenceDiffractionPS$1,\\n\\t\\tiridescencePS: iridescencePS$1,\\n\\t\\tiridescenceThicknessPS: iridescenceThicknessPS$1,\\n\\t\\tiorPS: iorPS$1,\\n\\t\\tlightDeclarationPS: lightDeclarationPS$1,\\n\\t\\tlightDiffuseLambertPS: lightDiffuseLambertPS$1,\\n\\t\\tlightDirPointPS: lightDirPointPS$1,\\n\\t\\tlightEvaluationPS: lightEvaluationPS$1,\\n\\t\\tlightFunctionLightPS: lightFunctionLightPS$1,\\n\\t\\tlightFunctionShadowPS: lightFunctionShadowPS$1,\\n\\t\\tlightingPS: lightingPS$1,\\n\\t\\tlightmapAddPS: lightmapAddPS$1,\\n\\t\\tlightmapPS: lightmapPS$1,\\n\\t\\tlightSpecularAnisoGGXPS: lightSpecularAnisoGGXPS$1,\\n\\t\\tlightSpecularGGXPS: lightSpecularGGXPS$1,\\n\\t\\tlightSpecularBlinnPS: lightSpecularBlinnPS$1,\\n\\t\\tlightSheenPS: lightSheenPS$1,\\n\\t\\tlinearizeDepthPS: linearizeDepthPS$1,\\n\\t\\tlitForwardBackendPS: litForwardBackendPS$1,\\n\\t\\tlitForwardDeclarationPS: litForwardDeclarationPS$1,\\n\\t\\tlitForwardMainPS: litForwardMainPS$1,\\n\\t\\tlitForwardPostCodePS: litForwardPostCodePS$1,\\n\\t\\tlitForwardPreCodePS: litForwardPreCodePS$1,\\n\\t\\tlitMainPS: litMainPS$1,\\n\\t\\tlitMainVS: litMainVS$1,\\n\\t\\tlitOtherMainPS: litOtherMainPS$1,\\n\\t\\tlitShaderArgsPS: litShaderArgsPS$1,\\n\\t\\tlitShaderCorePS: litShaderCorePS$1,\\n\\t\\tlitShadowMainPS: litShadowMainPS$1,\\n\\t\\tlitUserDeclarationPS: '',\\n\\t\\tlitUserDeclarationVS: '',\\n\\t\\tlitUserCodePS: '',\\n\\t\\tlitUserCodeVS: '',\\n\\t\\tlitUserMainStartPS: '',\\n\\t\\tlitUserMainStartVS: '',\\n\\t\\tlitUserMainEndPS: '',\\n\\t\\tlitUserMainEndVS: '',\\n\\t\\tltcPS: ltcPS$1,\\n\\t\\tmetalnessPS: metalnessPS$1,\\n\\t\\tmetalnessModulatePS: metalnessModulatePS$1,\\n\\t\\tmorphPS: morphPS$1,\\n\\t\\tmorphVS: morphVS$1,\\n\\t\\tmsdfPS: msdfPS$1,\\n\\t\\tmsdfVS: msdfVS$1,\\n\\t\\tnormalVS: normalVS$1,\\n\\t\\tnormalCoreVS: normalCoreVS$1,\\n\\t\\tnormalMapPS: normalMapPS$1,\\n\\t\\topacityPS: opacityPS$1,\\n\\t\\topacityDitherPS: opacityDitherPS$1,\\n\\t\\toutputPS: outputPS$1,\\n\\t\\toutputAlphaPS: outputAlphaPS$1,\\n\\t\\toutputTex2DPS: outputTex2DPS$1,\\n\\t\\tsheenPS: sheenPS$1,\\n\\t\\tsheenGlossPS: sheenGlossPS$1,\\n\\t\\tparallaxPS: parallaxPS$1,\\n\\t\\tpickPS: pickPS$1,\\n\\t\\treflDirPS: reflDirPS$1,\\n\\t\\treflDirAnisoPS: reflDirAnisoPS$1,\\n\\t\\treflectionCCPS: reflectionCCPS$1,\\n\\t\\treflectionCubePS: reflectionCubePS$1,\\n\\t\\treflectionEnvHQPS: reflectionEnvHQPS$1,\\n\\t\\treflectionEnvPS: reflectionEnvPS$1,\\n\\t\\treflectionSpherePS: reflectionSpherePS$1,\\n\\t\\treflectionSheenPS: reflectionSheenPS$1,\\n\\t\\trefractionCubePS: refractionCubePS$1,\\n\\t\\trefractionDynamicPS: refractionDynamicPS$1,\\n\\t\\treprojectPS: reprojectPS$1,\\n\\t\\treprojectVS: reprojectVS$1,\\n\\t\\tscreenDepthPS: screenDepthPS$1,\\n\\t\\tshadowCascadesPS: shadowCascadesPS$1,\\n\\t\\tshadowEVSMPS: shadowEVSMPS$1,\\n\\t\\tshadowPCF1PS: shadowPCF1PS$1,\\n\\t\\tshadowPCF3PS: shadowPCF3PS$1,\\n\\t\\tshadowPCF5PS: shadowPCF5PS$1,\\n\\t\\tshadowPCSSPS,\\n\\t\\tshadowSoftPS: shadowSoftPS$1,\\n\\t\\tskinBatchVS: skinBatchVS$1,\\n\\t\\tskinVS: skinVS$1,\\n\\t\\tskyboxPS: skyboxPS$1,\\n\\t\\tskyboxVS: skyboxVS$1,\\n\\t\\tspecularPS: specularPS$1,\\n\\t\\tsphericalPS: sphericalPS$1,\\n\\t\\tspecularityFactorPS: specularityFactorPS$1,\\n\\t\\tspotPS: spotPS$1,\\n\\t\\tstartNineSlicedPS: startNineSlicedPS$1,\\n\\t\\tstartNineSlicedTiledPS: startNineSlicedTiledPS$1,\\n\\t\\tstdDeclarationPS: stdDeclarationPS$1,\\n\\t\\tstdFrontEndPS: stdFrontEndPS$1,\\n\\t\\tTBNPS: TBNPS$1,\\n\\t\\tthicknessPS: thicknessPS$1,\\n\\t\\ttonemappingPS: tonemappingPS$1,\\n\\t\\ttonemappingAcesPS: tonemappingAcesPS$1,\\n\\t\\ttonemappingAces2PS: tonemappingAces2PS$1,\\n\\t\\ttonemappingFilmicPS: tonemappingFilmicPS$1,\\n\\t\\ttonemappingHejlPS: tonemappingHejlPS$1,\\n\\t\\ttonemappingLinearPS: tonemappingLinearPS$1,\\n\\t\\ttonemappingNeutralPS: tonemappingNeutralPS$1,\\n\\t\\ttonemappingNonePS: tonemappingNonePS$1,\\n\\t\\ttransformVS: transformVS$1,\\n\\t\\ttransformCoreVS: transformCoreVS$1,\\n\\t\\ttransformInstancingVS: transformInstancingVS$1,\\n\\t\\ttransmissionPS: transmissionPS$1,\\n\\t\\ttwoSidedLightingPS: twoSidedLightingPS$1,\\n\\t\\tuv0VS: uv0VS$1,\\n\\t\\tuv1VS: uv1VS$1,\\n\\t\\tuvTransformVS: uvTransformVS$1,\\n\\t\\tuvTransformUniformsPS: uvTransformUniformsPS$1,\\n\\t\\tviewDirPS: viewDirPS$1,\\n\\t\\twebgpuPS: webgpuPS$1,\\n\\t\\twebgpuVS: webgpuVS$1\\n};\\n\\nvar alphaTestPS = `\\nuniform alpha_ref: f32;\\nfn alphaTest(a: f32) {\\n\\tif (a < uniform.alpha_ref) {\\n\\t\\tdiscard;\\n\\t}\\n}\\n`;\\n\\nvar ambientPS = `\\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 anisotropyPS = `\\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 aoPS = `\\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 aoDiffuseOccPS = `\\nfn occludeDiffuse(ao: f32) {\\n\\tdDiffuseLight = dDiffuseLight * ao;\\n}\\n`;\\n\\nvar aoSpecOccPS = `\\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 bakeDirLmEndPS = `\\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 bakeLmEndPS = `\\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 basePS = `\\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 baseNineSlicedPS = `\\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 baseNineSlicedTiledPS = `\\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 bayerPS = `\\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 blurVSMPS = `\\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 clearCoatPS = `\\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 clearCoatGlossPS = `\\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 clearCoatNormalPS = `\\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 clusteredLightUtilsPS = `\\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 clusteredLightCookiesPS = `\\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 clusteredLightShadowsPS = `\\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 clusteredLightPS = `\\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\\tflags: u32,\\n\\thalfWidth: vec3f,\\n\\tisSpot: bool,\\n\\thalfHeight: vec3f,\\n\\tlightIndex: i32,\\n\\tposition: vec3f,\\n\\tshape: u32,\\n\\tdirection: vec3f,\\n\\tfalloffModeLinear: bool,\\n\\tcolor: vec3f,\\n\\tshadowIntensity: f32,\\n\\tomniAtlasViewport: vec3f,\\n\\trange: f32,\\n\\tcookieChannelMask: vec4f,\\n\\tbiasesData: f32,\\n\\tcolorBFlagsData: u32,\\n\\tshadowBias: f32,\\n\\tshadowNormalBias: f32,\\n\\tanglesData: f32,\\n\\tinnerConeAngleCos: f32,\\n\\touterConeAngleCos: f32,\\n\\tcookieIntensity: f32,\\n\\tisDynamic: bool,\\n\\tisLightmapped: bool\\n}\\nvar<private> lightProjectionMatrix: mat4x4f;\\nfn sampleLightTextureF(lightIndex: i32, index: i32) -> vec4f {\\n\\treturn textureLoad(lightsTexture, vec2<i32>(index, lightIndex), 0);\\n}\\nfn decodeClusterLightCore(clusterLightData: ptr<function, ClusterLightData>, lightIndex: i32) {\\n\\tclusterLightData.lightIndex = lightIndex;\\n\\tlet halfData: vec4f = sampleLightTextureF(clusterLightData.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(clusterLightData.lightIndex, {CLUSTER_TEXTURE_POSITION_RANGE});\\n\\tclusterLightData.position = lightPosRange.xyz;\\n\\tclusterLightData.range = lightPosRange.w;\\n\\tlet lightDir_Flags: vec4f = sampleLightTextureF(clusterLightData.lightIndex, {CLUSTER_TEXTURE_DIRECTION_FLAGS});\\n\\tclusterLightData.direction = lightDir_Flags.xyz;\\n\\tlet flags_uint: u32 = bitcast<u32>(lightDir_Flags.w);\\n\\tclusterLightData.flags = flags_uint;\\n\\tclusterLightData.isSpot = (flags_uint & (1u << 30u)) != 0u;\\n\\tclusterLightData.shape = (flags_uint >> 28u) & 0x3u;\\n\\tclusterLightData.falloffModeLinear = (flags_uint & (1u << 27u)) == 0u;\\n\\tclusterLightData.shadowIntensity = f32((flags_uint >> 0u) & 0xFFu) / 255.0;\\n\\tclusterLightData.cookieIntensity = f32((flags_uint >> 8u) & 0xFFu) / 255.0;\\n\\tclusterLightData.isDynamic = (flags_uint & (1u << 22u)) != 0u;\\n\\tclusterLightData.isLightmapped = (flags_uint & (1u << 21u)) != 0u;\\n}\\nfn decodeClusterLightSpot(clusterLightData: ptr<function, ClusterLightData>) {\\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\\tclusterLightData.innerConeAngleCos = select(innerVal, 1.0 - innerVal, innerIsVersine);\\n\\tclusterLightData.outerConeAngleCos = select(outerVal, 1.0 - outerVal, outerIsVersine);\\n}\\nfn decodeClusterLightOmniAtlasViewport(clusterLightData: ptr<function, ClusterLightData>) {\\n\\tclusterLightData.omniAtlasViewport = sampleLightTextureF(clusterLightData.lightIndex, {CLUSTER_TEXTURE_PROJ_MAT_0}).xyz;\\n}\\nfn decodeClusterLightAreaData(clusterLightData: ptr<function, ClusterLightData>) {\\n\\tclusterLightData.halfWidth = sampleLightTextureF(clusterLightData.lightIndex, {CLUSTER_TEXTURE_AREA_DATA_WIDTH}).xyz;\\n\\tclusterLightData.halfHeight = sampleLightTextureF(clusterLightData.lightIndex, {CLUSTER_TEXTURE_AREA_DATA_HEIGHT}).xyz;\\n}\\nfn decodeClusterLightProjectionMatrixData(clusterLightData: ptr<function, ClusterLightData>) {\\n\\tlet m0: vec4f = sampleLightTextureF(clusterLightData.lightIndex, {CLUSTER_TEXTURE_PROJ_MAT_0});\\n\\tlet m1: vec4f = sampleLightTextureF(clusterLightData.lightIndex, {CLUSTER_TEXTURE_PROJ_MAT_1});\\n\\tlet m2: vec4f = sampleLightTextureF(clusterLightData.lightIndex, {CLUSTER_TEXTURE_PROJ_MAT_2});\\n\\tlet m3: vec4f = sampleLightTextureF(clusterLightData.lightIndex, {CLUSTER_TEXTURE_PROJ_MAT_3});\\n\\tlightProjectionMatrix = mat4x4f(m0, m1, m2, m3);\\n}\\nfn decodeClusterLightShadowData(clusterLightData: ptr<function, ClusterLightData>) {\\n\\tlet biases: vec2f = unpack2x16float(bitcast<u32>(clusterLightData.biasesData));\\n\\tclusterLightData.shadowBias = biases.x;\\n\\tclusterLightData.shadowNormalBias = biases.y;\\n}\\nfn decodeClusterLightCookieData(clusterLightData: ptr<function, ClusterLightData>) {\\n\\tlet cookieFlags: u32 = (clusterLightData.flags >> 23u) & 0x0Fu;\\n\\tlet mask_uvec: vec4<u32> = vec4<u32>(cookieFlags) & vec4<u32>(1u, 2u, 4u, 8u);\\n\\tclusterLightData.cookieChannelMask = step(vec4f(1.0), vec4f(mask_uvec));\\n}\\nfn evaluateLight(\\n\\tlight: ptr<function, 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\\tdecodeClusterLightAreaData(light);\\n\\t\\tif (light.shape == {LIGHTSHAPE_RECT}) {\\n\\t\\t\\tcalcRectLightValues(light.position, light.halfWidth, light.halfHeight);\\n\\t\\t} else if (light.shape == {LIGHTSHAPE_DISK}) {\\n\\t\\t\\tcalcDiskLightValues(light.position, light.halfWidth, light.halfHeight);\\n\\t\\t} else {\\n\\t\\t\\tcalcSphereLightValues(light.position, light.halfWidth, light.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\\tdecodeClusterLightSpot(light);\\n\\t\\t\\tfalloffAttenuation = falloffAttenuation * getSpotEffect(light.direction, light.innerConeAngleCos, light.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\\tif (light.isSpot) {\\n\\t\\t\\t\\t\\tdecodeClusterLightProjectionMatrixData(light);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\tdecodeClusterLightOmniAtlasViewport(light);\\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\\tdecodeClusterLightCookieData(light);\\n\\t\\t\\t\\t\\tif (light.isSpot) {\\n\\t\\t\\t\\t\\t\\tcookieAttenuation = getCookie2DClustered(cookieAtlasTexture, cookieAtlasTextureSampler, lightProjectionMatrix, vPositionW, light.cookieIntensity, light.cookieChannelMask);\\n\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tcookieAttenuation = getCookieCubeClustered(cookieAtlasTexture, cookieAtlasTextureSampler, lightDirW, light.cookieIntensity, light.cookieChannelMask, shadowTextureResolution, shadowEdgePixels, light.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\\tdecodeClusterLightShadowData(light);\\n\\t\\t\\t\\t\\tlet shadowParams: vec4f = vec4f(shadowTextureResolution, light.shadowNormalBias, light.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, light.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, light.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, light.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\\tvar clusterLightData: ClusterLightData;\\n\\tdecodeClusterLightCore(&clusterLightData, 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\\t&clusterLightData,\\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 combinePS = `\\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 cookieBlit2DPS = `\\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 cookieBlitCubePS = `\\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 cookieBlitVS = `\\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 cubeMapProjectPS = `\\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 cubeMapRotatePS = `\\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 debugOutputPS = `\\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 debugProcessFrontendPS = `\\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 decodePS = `\\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 detailModesPS = `\\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 diffusePS = `\\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 emissivePS = `\\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 encodePS = `\\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 endPS = `\\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 envAtlasPS = `\\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 envProcPS = `\\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 falloffInvSquaredPS = `\\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 falloffLinearPS = `\\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 floatAsUintPS = `\\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 fogPS = `\\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\\nfn getFogFactor() -> f32 {\\n\\tlet depth = pcPosition.z / pcPosition.w;\\n\\tvar fogFactor : f32 = 0.0;\\n\\t#if (FOG == LINEAR)\\n\\t\\tfogFactor = (uniform.fog_end - depth) / (uniform.fog_end - uniform.fog_start);\\n\\t#elif (FOG == EXP)\\n\\t\\tfogFactor = exp(-depth * uniform.fog_density);\\n\\t#elif (FOG == EXP2)\\n\\t\\tfogFactor = exp(-depth * depth * uniform.fog_density * uniform.fog_density);\\n\\t#endif\\n\\treturn clamp(fogFactor, 0.0, 1.0);\\n}\\nfn addFog(color : vec3f) -> vec3f {\\n\\t#if (FOG != NONE)\\n\\t\\treturn mix(uniform.fog_color * dBlendModeFogFactor, color, getFogFactor());\\n\\t#else\\n\\t\\treturn color;\\n\\t#endif\\n}\\n`;\\n\\nvar fresnelSchlickPS = `\\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 = pow(1.0 - saturate(cosTheta), 5.0);\\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 = pow(1.0 - saturate(cosTheta), 5.0);\\n\\treturn 0.04 + (1.0 - 0.04) * fresnel;\\n}`;\\n\\nvar fullscreenQuadVS = `\\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 gammaPS = `\\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 glossPS = `\\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 quadVS = `\\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 indirectCoreCS = `\\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 immediateLinePS = `\\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 immediateLineVS = `\\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 iridescenceDiffractionPS = `\\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 iridescencePS = `\\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 iridescenceThicknessPS = `\\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 iorPS = `\\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 lightDeclarationPS = `\\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\\t\\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 lightDiffuseLambertPS = `\\nfn getLightDiffuse(worldNormal: vec3f, viewDir: vec3f, lightDirNorm: vec3f) -> f32 {\\n\\treturn max(dot(worldNormal, -lightDirNorm), 0.0);\\n}\\n`;\\n\\nvar lightDirPointPS = `\\nfn evalOmniLight(lightPosW: vec3f) -> vec3f {\\n\\treturn vPositionW - lightPosW;\\n}\\n`;\\n\\nvar lightEvaluationPS = `\\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 lightFunctionLightPS = `\\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 lightFunctionShadowPS = `\\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 lightingPS = `\\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 lightmapAddPS = `\\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 lightmapPS = `\\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 lightSpecularAnisoGGXPS = `\\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 lightSpecularGGXPS = `\\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 lightSpecularBlinnPS = `\\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 lightSheenPS = `\\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 linearizeDepthPS = `\\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 litForwardBackendPS = `\\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 litForwardDeclarationPS = `\\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 litForwardMainPS = `\\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 litForwardPostCodePS = `\\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#if LIT_FRESNEL_MODEL == SCHLICK\\n\\t\\t#include \\\"fresnelSchlickPS\\\"\\n\\t#endif\\n\\t#ifdef LIT_IRIDESCENCE\\n\\t\\t#include \\\"iridescenceDiffractionPS\\\"\\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 litForwardPreCodePS = `\\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 litMainPS = `\\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 litMainVS = `\\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 litOtherMainPS = `\\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 litShaderArgsPS = `\\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 litShaderCorePS = `\\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 litShadowMainPS = `\\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 ltcPS = `\\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 metalnessPS = `\\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 msdfPS = `\\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 metalnessModulatePS = `\\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 morphPS = `\\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 morphVS = `\\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 msdfVS = `\\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 normalVS = `\\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 normalCoreVS = `\\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 normalMapPS = `\\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 opacityPS = `\\nuniform material_opacity: 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 opacityDitherPS = `\\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\\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 outputPS = `\\n`;\\n\\nvar outputAlphaPS = `\\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 outputTex2DPS = `\\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 sheenPS = `\\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 sheenGlossPS = `\\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 parallaxPS = `\\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 pickPS = `\\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\\tfn getPickDepth() -> vec4f {\\n\\t\\treturn float2uint(pcPosition.z);\\n\\t}\\n#endif\\n`;\\n\\nvar reflDirPS = `\\nfn getReflDir(worldNormal: vec3f, viewDir: vec3f, gloss: f32, tbn: mat3x3f) {\\n\\tdReflDirW = normalize(-reflect(viewDir, worldNormal));\\n}\\n`;\\n\\nvar reflDirAnisoPS = `\\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 reflectionCCPS = `\\n#ifdef LIT_CLEARCOAT\\nfn addReflectionCC(reflDir: vec3f, gloss: f32) {\\n\\tccReflection = ccReflection + calcReflection(reflDir, gloss);\\n}\\n#endif\\n`;\\n\\nvar reflectionCubePS = `\\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 reflectionEnvHQPS = `\\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 reflectionEnvPS = `\\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 reflectionSpherePS = `\\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 reflectionSheenPS = `\\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 refractionCubePS = `\\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 refractionDynamicPS = `\\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 reprojectPS = `\\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 reprojectVS = `\\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 screenDepthPS = `\\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 shadowCascadesPS = `\\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 shadowEVSMPS = `\\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 shadowPCF1PS = `\\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 shadowPCF3PS = `\\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 shadowPCF5PS = `\\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 shadowSoftPS = `\\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 skinBatchVS = `\\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 skinVS = `\\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 skyboxPS = `\\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#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#ifdef SKY_CUBEMAP\\n\\t\\t\\t\\t#ifdef SKYMESH\\n\\t\\t\\t\\t\\tvar envDir : vec3f = normalize(input.vWorldPos - uniform.projectedSkydomeCenter);\\n\\t\\t\\t\\t\\tdir = envDir * uniform.cubeMapRotationMatrix;\\n\\t\\t\\t\\t#else\\n\\t\\t\\t\\t\\tdir = input.vViewDir;\\n\\t\\t\\t\\t#endif\\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 = input.vViewDir * 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 skyboxVS = `\\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 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.position = uniform.matrix_projectionSkybox * (view * input.aPosition);\\n\\t\\t\\toutput.vViewDir = input.aPosition.xyz * uniform.cubeMapRotationMatrix;\\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 specularPS = `\\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 sphericalPS = `\\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 specularityFactorPS = `\\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 spotPS = `\\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 startNineSlicedPS = `\\n\\tnineSlicedUv = vec2f(vUv0.x, 1.0 - vUv0.y);\\n`;\\n\\nvar startNineSlicedTiledPS = `\\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 stdDeclarationPS = `\\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 stdFrontEndPS = `\\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, 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 TBNPS = `\\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 thicknessPS = `\\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 tonemappingPS = `\\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 tonemappingAcesPS = `\\nuniform exposure: f32;\\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 * uniform.exposure;\\n\\treturn (x * (tA * x + tB)) / (x * (tC * x + tD) + tE);\\n}\\n`;\\n\\nvar tonemappingAces2PS = `\\nuniform exposure: f32;\\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 * (uniform.exposure / 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 tonemappingFilmicPS = `\\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;\\nuniform exposure: f32;\\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 * uniform.exposure);\\n\\tlet whiteScale: vec3f = vec3f(1.0) / uncharted2Tonemap(vec3f(W, W, W));\\n\\tc *= whiteScale;\\n\\treturn c;\\n}\\n`;\\n\\nvar tonemappingHejlPS = `\\nuniform exposure: f32;\\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 * uniform.exposure;\\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 tonemappingLinearPS = `\\nuniform exposure: f32;\\nfn toneMap(color: vec3f) -> vec3f {\\n\\treturn color * uniform.exposure;\\n}\\n`;\\n\\nvar tonemappingNeutralPS = `\\nuniform exposure: f32;\\nfn toneMap(col: vec3f) -> vec3f {\\n\\tvar color = col * uniform.exposure;\\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 tonemappingNonePS = `\\nfn toneMap(color: vec3f) -> vec3f {\\n\\treturn color;\\n}\\n`;\\n\\nvar transformVS = `\\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 transformCoreVS = `\\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 transformInstancingVS = `\\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 transmissionPS = `\\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 twoSidedLightingPS = `\\nuniform twoSidedLightingNegScaleFactor: f32;\\nfn handleTwoSidedLighting() {\\n\\tdTBN[2] = dTBN[2] * select(-uniform.twoSidedLightingNegScaleFactor, uniform.twoSidedLightingNegScaleFactor, pcFrontFacing);\\n}\\n`;\\n\\nvar uv0VS = `\\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 uv1VS = `\\nfn getUv1() -> vec2f {\\n\\treturn vertex_texCoord1;\\n}\\n`;\\n\\nvar uvTransformVS = `\\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 uvTransformUniformsPS = `\\n\\tuniform {TRANSFORM_NAME_{i}}0: vec3f;\\n\\tuniform {TRANSFORM_NAME_{i}}1: vec3f;\\n`;\\n\\nvar viewDirPS = `\\nfn getViewDir() {\\n\\tdViewDirW = normalize(uniform.view_position - vPositionW);\\n}\\n`;\\n\\nconst shaderChunksWGSL = {\\n\\t\\talphaTestPS,\\n\\t\\tambientPS,\\n\\t\\tanisotropyPS,\\n\\t\\taoPS,\\n\\t\\taoDiffuseOccPS,\\n\\t\\taoSpecOccPS,\\n\\t\\tbakeDirLmEndPS,\\n\\t\\tbakeLmEndPS,\\n\\t\\tbasePS,\\n\\t\\tbaseNineSlicedPS,\\n\\t\\tbaseNineSlicedTiledPS,\\n\\t\\tbayerPS,\\n\\t\\tblurVSMPS,\\n\\t\\tclearCoatPS,\\n\\t\\tclearCoatGlossPS,\\n\\t\\tclearCoatNormalPS,\\n\\t\\tclusteredLightCookiesPS,\\n\\t\\tclusteredLightShadowsPS,\\n\\t\\tclusteredLightUtilsPS,\\n\\t\\tclusteredLightPS,\\n\\t\\tcombinePS,\\n\\t\\tcookieBlit2DPS,\\n\\t\\tcookieBlitCubePS,\\n\\t\\tcookieBlitVS,\\n\\t\\tcubeMapProjectPS,\\n\\t\\tcubeMapRotatePS,\\n\\t\\tdebugOutputPS,\\n\\t\\tdebugProcessFrontendPS,\\n\\t\\tdetailModesPS,\\n\\t\\tdiffusePS,\\n\\t\\tdecodePS,\\n\\t\\temissivePS,\\n\\t\\tencodePS,\\n\\t\\tendPS,\\n\\t\\tenvAtlasPS,\\n\\t\\tenvProcPS,\\n\\t\\tfalloffInvSquaredPS,\\n\\t\\tfalloffLinearPS,\\n\\t\\tfloatAsUintPS,\\n\\t\\tfogPS,\\n\\t\\tfresnelSchlickPS,\\n\\t\\tfrontendCodePS: '',\\n\\t\\tfrontendDeclPS: '',\\n\\t\\tfullscreenQuadVS,\\n\\t\\tgammaPS,\\n\\t\\tglossPS,\\n\\t\\tquadVS,\\n\\t\\tindirectCoreCS,\\n\\t\\timmediateLinePS,\\n\\t\\timmediateLineVS,\\n\\t\\tiridescenceDiffractionPS,\\n\\t\\tiridescencePS,\\n\\t\\tiridescenceThicknessPS,\\n\\t\\tiorPS,\\n\\t\\tlightDeclarationPS,\\n\\t\\tlightDiffuseLambertPS,\\n\\t\\tlightDirPointPS,\\n\\t\\tlightEvaluationPS,\\n\\t\\tlightFunctionLightPS,\\n\\t\\tlightFunctionShadowPS,\\n\\t\\tlightingPS,\\n\\t\\tlightmapAddPS,\\n\\t\\tlightmapPS,\\n\\t\\tlightSpecularAnisoGGXPS,\\n\\t\\tlightSpecularGGXPS,\\n\\t\\tlightSpecularBlinnPS,\\n\\t\\tlightSheenPS,\\n\\t\\tlinearizeDepthPS,\\n\\t\\tlitForwardBackendPS,\\n\\t\\tlitForwardDeclarationPS,\\n\\t\\tlitForwardMainPS,\\n\\t\\tlitForwardPostCodePS,\\n\\t\\tlitForwardPreCodePS,\\n\\t\\tlitMainPS,\\n\\t\\tlitMainVS,\\n\\t\\tlitOtherMainPS,\\n\\t\\tlitShaderArgsPS,\\n\\t\\tlitShaderCorePS,\\n\\t\\tlitShadowMainPS,\\n\\t\\tlitUserDeclarationPS: '',\\n\\t\\tlitUserDeclarationVS: '',\\n\\t\\tlitUserCodePS: '',\\n\\t\\tlitUserCodeVS: '',\\n\\t\\tlitUserMainStartPS: '',\\n\\t\\tlitUserMainStartVS: '',\\n\\t\\tlitUserMainEndPS: '',\\n\\t\\tlitUserMainEndVS: '',\\n\\t\\tltcPS,\\n\\t\\tmetalnessPS,\\n\\t\\tmetalnessModulatePS,\\n\\t\\tmorphPS,\\n\\t\\tmorphVS,\\n\\t\\tmsdfPS,\\n\\t\\tmsdfVS,\\n\\t\\tnormalVS,\\n\\t\\tnormalCoreVS,\\n\\t\\tnormalMapPS,\\n\\t\\topacityPS,\\n\\t\\topacityDitherPS,\\n\\t\\toutputPS,\\n\\t\\toutputAlphaPS,\\n\\t\\toutputTex2DPS,\\n\\t\\tsheenPS,\\n\\t\\tsheenGlossPS,\\n\\t\\tparallaxPS,\\n\\t\\tpickPS,\\n\\t\\treflDirPS,\\n\\t\\treflDirAnisoPS,\\n\\t\\treflectionCCPS,\\n\\t\\treflectionCubePS,\\n\\t\\treflectionEnvHQPS,\\n\\t\\treflectionEnvPS,\\n\\t\\treflectionSpherePS,\\n\\t\\treflectionSheenPS,\\n\\t\\trefractionCubePS,\\n\\t\\trefractionDynamicPS,\\n\\t\\treprojectPS,\\n\\t\\treprojectVS,\\n\\t\\tscreenDepthPS,\\n\\t\\tshadowCascadesPS,\\n\\t\\tshadowEVSMPS,\\n\\t\\tshadowPCF1PS,\\n\\t\\tshadowPCF3PS,\\n\\t\\tshadowPCF5PS,\\n\\t\\tshadowSoftPS,\\n\\t\\tskinBatchVS,\\n\\t\\tskinVS,\\n\\t\\tskyboxPS,\\n\\t\\tskyboxVS,\\n\\t\\tspecularPS,\\n\\t\\tsphericalPS,\\n\\t\\tspecularityFactorPS,\\n\\t\\tspotPS,\\n\\t\\tstartNineSlicedPS,\\n\\t\\tstartNineSlicedTiledPS,\\n\\t\\tstdDeclarationPS,\\n\\t\\tstdFrontEndPS,\\n\\t\\tTBNPS,\\n\\t\\tthicknessPS,\\n\\t\\ttonemappingPS,\\n\\t\\ttonemappingAcesPS,\\n\\t\\ttonemappingAces2PS,\\n\\t\\ttonemappingFilmicPS,\\n\\t\\ttonemappingHejlPS,\\n\\t\\ttonemappingLinearPS,\\n\\t\\ttonemappingNeutralPS,\\n\\t\\ttonemappingNonePS,\\n\\t\\ttransformVS,\\n\\t\\ttransformCoreVS,\\n\\t\\ttransformInstancingVS,\\n\\t\\ttransmissionPS,\\n\\t\\ttwoSidedLightingPS,\\n\\t\\tuv0VS,\\n\\t\\tuv1VS,\\n\\t\\tuvTransformVS,\\n\\t\\tuvTransformUniformsPS,\\n\\t\\tviewDirPS,\\n\\t\\twebgpuPS,\\n\\t\\twebgpuVS\\n};\\n\\nclass AppBase extends EventHandler {\\n\\t\\tinit(appOptions) {\\n\\t\\t\\t\\tconst { assetPrefix, batchManager, componentSystems, elementInput, gamepads, graphicsDevice, keyboard, lightmapper, mouse, resourceHandlers, scriptsOrder, scriptPrefix, soundManager, touch, xr } = appOptions;\\n\\t\\t\\t\\tthis.graphicsDevice = graphicsDevice;\\n\\t\\t\\t\\tShaderChunks.get(graphicsDevice, SHADERLANGUAGE_GLSL).add(shaderChunksGLSL);\\n\\t\\t\\t\\tShaderChunks.get(graphicsDevice, SHADERLANGUAGE_WGSL).add(shaderChunksWGSL);\\n\\t\\t\\t\\tthis._initDefaultMaterial();\\n\\t\\t\\t\\tthis._initProgramLibrary();\\n\\t\\t\\t\\tthis.stats = new ApplicationStats(graphicsDevice);\\n\\t\\t\\t\\tthis._soundManager = soundManager;\\n\\t\\t\\t\\tthis.scene = new Scene(graphicsDevice);\\n\\t\\t\\t\\tthis._registerSceneImmediate(this.scene);\\n\\t\\t\\t\\tthis.assets = new AssetRegistry(this.loader);\\n\\t\\t\\t\\tif (assetPrefix) this.assets.prefix = assetPrefix;\\n\\t\\t\\t\\tthis.bundles = new BundleRegistry(this.assets);\\n\\t\\t\\t\\tthis.scriptsOrder = scriptsOrder || [];\\n\\t\\t\\t\\tthis.defaultLayerWorld = new Layer({\\n\\t\\t\\t\\t\\t\\tname: 'World',\\n\\t\\t\\t\\t\\t\\tid: LAYERID_WORLD\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.defaultLayerDepth = new Layer({\\n\\t\\t\\t\\t\\t\\tname: 'Depth',\\n\\t\\t\\t\\t\\t\\tid: LAYERID_DEPTH,\\n\\t\\t\\t\\t\\t\\tenabled: false,\\n\\t\\t\\t\\t\\t\\topaqueSortMode: SORTMODE_NONE\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.defaultLayerSkybox = new Layer({\\n\\t\\t\\t\\t\\t\\tname: 'Skybox',\\n\\t\\t\\t\\t\\t\\tid: LAYERID_SKYBOX,\\n\\t\\t\\t\\t\\t\\topaqueSortMode: SORTMODE_NONE\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.defaultLayerUi = new Layer({\\n\\t\\t\\t\\t\\t\\tname: 'UI',\\n\\t\\t\\t\\t\\t\\tid: LAYERID_UI,\\n\\t\\t\\t\\t\\t\\ttransparentSortMode: SORTMODE_MANUAL\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.defaultLayerImmediate = new Layer({\\n\\t\\t\\t\\t\\t\\tname: 'Immediate',\\n\\t\\t\\t\\t\\t\\tid: LAYERID_IMMEDIATE,\\n\\t\\t\\t\\t\\t\\topaqueSortMode: SORTMODE_NONE\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst defaultLayerComposition = new LayerComposition('default');\\n\\t\\t\\t\\tdefaultLayerComposition.pushOpaque(this.defaultLayerWorld);\\n\\t\\t\\t\\tdefaultLayerComposition.pushOpaque(this.defaultLayerDepth);\\n\\t\\t\\t\\tdefaultLayerComposition.pushOpaque(this.defaultLayerSkybox);\\n\\t\\t\\t\\tdefaultLayerComposition.pushTransparent(this.defaultLayerWorld);\\n\\t\\t\\t\\tdefaultLayerComposition.pushOpaque(this.defaultLayerImmediate);\\n\\t\\t\\t\\tdefaultLayerComposition.pushTransparent(this.defaultLayerImmediate);\\n\\t\\t\\t\\tdefaultLayerComposition.pushTransparent(this.defaultLayerUi);\\n\\t\\t\\t\\tthis.scene.layers = defaultLayerComposition;\\n\\t\\t\\t\\tAreaLightLuts.createPlaceholder(graphicsDevice);\\n\\t\\t\\t\\tthis.renderer = new ForwardRenderer(graphicsDevice, this.scene);\\n\\t\\t\\t\\tif (lightmapper) {\\n\\t\\t\\t\\t\\t\\tthis.lightmapper = new lightmapper(graphicsDevice, this.root, this.scene, this.renderer, this.assets);\\n\\t\\t\\t\\t\\t\\tthis.once('prerender', this._firstBake, this);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (batchManager) {\\n\\t\\t\\t\\t\\t\\tthis._batcher = new batchManager(graphicsDevice, this.root, this.scene);\\n\\t\\t\\t\\t\\t\\tthis.once('prerender', this._firstBatch, this);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.keyboard = keyboard || null;\\n\\t\\t\\t\\tthis.mouse = mouse || null;\\n\\t\\t\\t\\tthis.touch = touch || null;\\n\\t\\t\\t\\tthis.gamepads = gamepads || null;\\n\\t\\t\\t\\tif (elementInput) {\\n\\t\\t\\t\\t\\t\\tthis.elementInput = elementInput;\\n\\t\\t\\t\\t\\t\\tthis.elementInput.app = this;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.xr = xr ? new xr(this) : null;\\n\\t\\t\\t\\tif (this.elementInput) this.elementInput.attachSelectEvents();\\n\\t\\t\\t\\tthis._scriptPrefix = scriptPrefix || '';\\n\\t\\t\\t\\tif (this.enableBundles) {\\n\\t\\t\\t\\t\\t\\tthis.loader.addHandler('bundle', new BundleHandler(this));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tresourceHandlers.forEach((resourceHandler)=>{\\n\\t\\t\\t\\t\\t\\tconst handler = new resourceHandler(this);\\n\\t\\t\\t\\t\\t\\tthis.loader.addHandler(handler.handlerType, handler);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tcomponentSystems.forEach((componentSystem)=>{\\n\\t\\t\\t\\t\\t\\tthis.systems.add(new componentSystem(this));\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis._visibilityChangeHandler = this.onVisibilityChange.bind(this);\\n\\t\\t\\t\\tif (typeof document !== 'undefined') {\\n\\t\\t\\t\\t\\t\\tif (document.hidden !== undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._hiddenAttr = 'hidden';\\n\\t\\t\\t\\t\\t\\t\\t\\tdocument.addEventListener('visibilitychange', this._visibilityChangeHandler, false);\\n\\t\\t\\t\\t\\t\\t} else if (document.mozHidden !== undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._hiddenAttr = 'mozHidden';\\n\\t\\t\\t\\t\\t\\t\\t\\tdocument.addEventListener('mozvisibilitychange', this._visibilityChangeHandler, false);\\n\\t\\t\\t\\t\\t\\t} else if (document.msHidden !== undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._hiddenAttr = 'msHidden';\\n\\t\\t\\t\\t\\t\\t\\t\\tdocument.addEventListener('msvisibilitychange', this._visibilityChangeHandler, false);\\n\\t\\t\\t\\t\\t\\t} else if (document.webkitHidden !== undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._hiddenAttr = 'webkitHidden';\\n\\t\\t\\t\\t\\t\\t\\t\\tdocument.addEventListener('webkitvisibilitychange', this._visibilityChangeHandler, false);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.tick = makeTick(this);\\n\\t\\t}\\n\\t\\tstatic getApplication(id) {\\n\\t\\t\\t\\treturn id ? AppBase._applications[id] : getApplication();\\n\\t\\t}\\n\\t\\t_initDefaultMaterial() {\\n\\t\\t\\t\\tconst material = new StandardMaterial();\\n\\t\\t\\t\\tmaterial.name = 'Default Material';\\n\\t\\t\\t\\tsetDefaultMaterial(this.graphicsDevice, material);\\n\\t\\t}\\n\\t\\t_initProgramLibrary() {\\n\\t\\t\\t\\tconst library = new ProgramLibrary(this.graphicsDevice, new StandardMaterial());\\n\\t\\t\\t\\tsetProgramLibrary(this.graphicsDevice, library);\\n\\t\\t}\\n\\t\\tget soundManager() {\\n\\t\\t\\t\\treturn this._soundManager;\\n\\t\\t}\\n\\t\\tget batcher() {\\n\\t\\t\\t\\treturn this._batcher;\\n\\t\\t}\\n\\t\\tget fillMode() {\\n\\t\\t\\t\\treturn this._fillMode;\\n\\t\\t}\\n\\t\\tget resolutionMode() {\\n\\t\\t\\t\\treturn this._resolutionMode;\\n\\t\\t}\\n\\t\\tconfigure(url, callback) {\\n\\t\\t\\t\\thttp.get(url, (err, response)=>{\\n\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst props = response.application_properties;\\n\\t\\t\\t\\t\\t\\tconst scenes = response.scenes;\\n\\t\\t\\t\\t\\t\\tconst assets = response.assets;\\n\\t\\t\\t\\t\\t\\tthis._parseApplicationProperties(props, (err)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._parseScenes(scenes);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._parseAssets(assets);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(null);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tpreload(callback) {\\n\\t\\t\\t\\tthis.fire('preload:start');\\n\\t\\t\\t\\tconst assets = this.assets.list({\\n\\t\\t\\t\\t\\t\\tpreload: true\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (assets.length === 0) {\\n\\t\\t\\t\\t\\t\\tthis.fire('preload:end');\\n\\t\\t\\t\\t\\t\\tcallback();\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet loadedCount = 0;\\n\\t\\t\\t\\tconst onAssetLoadOrError = ()=>{\\n\\t\\t\\t\\t\\t\\tloadedCount++;\\n\\t\\t\\t\\t\\t\\tthis.fire('preload:progress', loadedCount / assets.length);\\n\\t\\t\\t\\t\\t\\tif (loadedCount === assets.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('preload:end');\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tassets.forEach((asset)=>{\\n\\t\\t\\t\\t\\t\\tif (!asset.loaded) {\\n\\t\\t\\t\\t\\t\\t\\t\\tasset.once('load', onAssetLoadOrError);\\n\\t\\t\\t\\t\\t\\t\\t\\tasset.once('error', onAssetLoadOrError);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.assets.load(asset);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tonAssetLoadOrError();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\t_preloadScripts(sceneData, callback) {\\n\\t\\t\\t\\tcallback();\\n\\t\\t}\\n\\t\\t_parseApplicationProperties(props, callback) {\\n\\t\\t\\t\\tif (typeof props.maxAssetRetries === 'number' && props.maxAssetRetries > 0) {\\n\\t\\t\\t\\t\\t\\tthis.loader.enableRetry(props.maxAssetRetries);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!props.useDevicePixelRatio) {\\n\\t\\t\\t\\t\\t\\tprops.useDevicePixelRatio = props.use_device_pixel_ratio;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!props.resolutionMode) {\\n\\t\\t\\t\\t\\t\\tprops.resolutionMode = props.resolution_mode;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!props.fillMode) {\\n\\t\\t\\t\\t\\t\\tprops.fillMode = props.fill_mode;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._width = props.width;\\n\\t\\t\\t\\tthis._height = props.height;\\n\\t\\t\\t\\tif (props.useDevicePixelRatio) {\\n\\t\\t\\t\\t\\t\\tthis.graphicsDevice.maxPixelRatio = window.devicePixelRatio;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.setCanvasResolution(props.resolutionMode, this._width, this._height);\\n\\t\\t\\t\\tthis.setCanvasFillMode(props.fillMode, this._width, this._height);\\n\\t\\t\\t\\tif (props.layers && props.layerOrder) {\\n\\t\\t\\t\\t\\t\\tconst composition = new LayerComposition('application');\\n\\t\\t\\t\\t\\t\\tconst layers = {};\\n\\t\\t\\t\\t\\t\\tfor(const key in props.layers){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst data = props.layers[key];\\n\\t\\t\\t\\t\\t\\t\\t\\tdata.id = parseInt(key, 10);\\n\\t\\t\\t\\t\\t\\t\\t\\tdata.enabled = data.id !== LAYERID_DEPTH;\\n\\t\\t\\t\\t\\t\\t\\t\\tlayers[key] = new Layer(data);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor(let i = 0, len = props.layerOrder.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst sublayer = props.layerOrder[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst layer = layers[sublayer.layer];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!layer) continue;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (sublayer.transparent) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcomposition.pushTransparent(layer);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcomposition.pushOpaque(layer);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tcomposition.subLayerEnabled[i] = sublayer.enabled;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.scene.layers = composition;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (props.batchGroups) {\\n\\t\\t\\t\\t\\t\\tconst batcher = this.batcher;\\n\\t\\t\\t\\t\\t\\tif (batcher) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0, len = props.batchGroups.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst grp = props.batchGroups[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbatcher.addGroup(grp.name, grp.dynamic, grp.maxAabbSize, grp.id, grp.layers);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (props.i18nAssets) {\\n\\t\\t\\t\\t\\t\\tthis.i18n.assets = props.i18nAssets;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._loadLibraries(props.libraries, callback);\\n\\t\\t}\\n\\t\\t_loadLibraries(urls, callback) {\\n\\t\\t\\t\\tconst len = urls.length;\\n\\t\\t\\t\\tlet count = len;\\n\\t\\t\\t\\tconst regex = /^https?:\\\\/\\\\//;\\n\\t\\t\\t\\tif (len) {\\n\\t\\t\\t\\t\\t\\tconst onLoad = (err, script)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tcount--;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else if (count === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.onLibrariesLoaded();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(null);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < len; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tlet url = urls[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!regex.test(url.toLowerCase()) && this._scriptPrefix) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\turl = path.join(this._scriptPrefix, url);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.loader.load(url, \\\"script\\\", onLoad);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.onLibrariesLoaded();\\n\\t\\t\\t\\t\\t\\tcallback(null);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_parseScenes(scenes) {\\n\\t\\t\\t\\tif (!scenes) return;\\n\\t\\t\\t\\tfor(let i = 0; i < scenes.length; i++){\\n\\t\\t\\t\\t\\t\\tthis.scenes.add(scenes[i].name, scenes[i].url);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_parseAssets(assets) {\\n\\t\\t\\t\\tconst list = [];\\n\\t\\t\\t\\tconst scriptsIndex = {};\\n\\t\\t\\t\\tconst bundlesIndex = {};\\n\\t\\t\\t\\tfor(let i = 0; i < this.scriptsOrder.length; i++){\\n\\t\\t\\t\\t\\t\\tconst id = this.scriptsOrder[i];\\n\\t\\t\\t\\t\\t\\tif (!assets[id]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tscriptsIndex[id] = true;\\n\\t\\t\\t\\t\\t\\tlist.push(assets[id]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.enableBundles) {\\n\\t\\t\\t\\t\\t\\tfor(const id in assets){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (assets[id].type === 'bundle') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbundlesIndex[id] = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlist.push(assets[id]);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(const id in assets){\\n\\t\\t\\t\\t\\t\\tif (scriptsIndex[id] || bundlesIndex[id]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlist.push(assets[id]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < list.length; i++){\\n\\t\\t\\t\\t\\t\\tconst data = list[i];\\n\\t\\t\\t\\t\\t\\tconst asset = new Asset(data.name, data.type, data.file, data.data);\\n\\t\\t\\t\\t\\t\\tasset.id = parseInt(data.id, 10);\\n\\t\\t\\t\\t\\t\\tasset.preload = data.preload ? data.preload : false;\\n\\t\\t\\t\\t\\t\\tasset.loaded = data.type === \\\"script\\\" && data.data && data.data.loadingType > 0;\\n\\t\\t\\t\\t\\t\\tasset.tags.add(data.tags);\\n\\t\\t\\t\\t\\t\\tif (data.i18n) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(const locale in data.i18n){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tasset.addLocalizedAssetId(locale, data.i18n[locale]);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.assets.add(asset);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tstart() {\\n\\t\\t\\t\\tthis.frame = 0;\\n\\t\\t\\t\\tthis.fire('start', {\\n\\t\\t\\t\\t\\t\\ttimestamp: now(),\\n\\t\\t\\t\\t\\t\\ttarget: this\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (!this._librariesLoaded) {\\n\\t\\t\\t\\t\\t\\tthis.onLibrariesLoaded();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.systems.fire('initialize', this.root);\\n\\t\\t\\t\\tthis.fire('initialize');\\n\\t\\t\\t\\tthis.systems.fire('postInitialize', this.root);\\n\\t\\t\\t\\tthis.systems.fire('postPostInitialize', this.root);\\n\\t\\t\\t\\tthis.fire('postinitialize');\\n\\t\\t\\t\\tthis.requestAnimationFrame();\\n\\t\\t}\\n\\t\\trequestAnimationFrame() {\\n\\t\\t\\t\\tif (this.xr?.session) {\\n\\t\\t\\t\\t\\t\\tthis.frameRequestId = this.xr.session.requestAnimationFrame(this.tick);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.frameRequestId = platform.browser || platform.worker ? requestAnimationFrame(this.tick) : null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tinputUpdate(dt) {\\n\\t\\t\\t\\tif (this.controller) {\\n\\t\\t\\t\\t\\t\\tthis.controller.update(dt);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.mouse) {\\n\\t\\t\\t\\t\\t\\tthis.mouse.update();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.keyboard) {\\n\\t\\t\\t\\t\\t\\tthis.keyboard.update();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.gamepads) {\\n\\t\\t\\t\\t\\t\\tthis.gamepads.update();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdate(dt) {\\n\\t\\t\\t\\tthis.frame++;\\n\\t\\t\\t\\tthis.graphicsDevice.update();\\n\\t\\t\\t\\tthis.stats.frame.scriptUpdateStart = now();\\n\\t\\t\\t\\tthis.systems.fire(this._inTools ? 'toolsUpdate' : 'update', dt);\\n\\t\\t\\t\\tthis.stats.frame.scriptUpdate = now() - this.stats.frame.scriptUpdateStart;\\n\\t\\t\\t\\tthis.stats.frame.animUpdateStart = now();\\n\\t\\t\\t\\tthis.systems.fire('animationUpdate', dt);\\n\\t\\t\\t\\tthis.stats.frame.animUpdate = now() - this.stats.frame.animUpdateStart;\\n\\t\\t\\t\\tthis.stats.frame.scriptPostUpdateStart = now();\\n\\t\\t\\t\\tthis.systems.fire('postUpdate', dt);\\n\\t\\t\\t\\tthis.stats.frame.scriptPostUpdate = now() - this.stats.frame.scriptPostUpdateStart;\\n\\t\\t\\t\\tthis.fire('update', dt);\\n\\t\\t\\t\\tthis.inputUpdate(dt);\\n\\t\\t}\\n\\t\\trender() {\\n\\t\\t\\t\\tthis.updateCanvasSize();\\n\\t\\t\\t\\tthis.graphicsDevice.frameStart();\\n\\t\\t\\t\\tthis.fire('prerender');\\n\\t\\t\\t\\tthis.root.syncHierarchy();\\n\\t\\t\\t\\tif (this._batcher) {\\n\\t\\t\\t\\t\\t\\tthis._batcher.updateAll();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.renderComposition(this.scene.layers);\\n\\t\\t\\t\\tthis.fire('postrender');\\n\\t\\t\\t\\tthis.stats.frame.renderTime = now() - this.stats.frame.renderStart;\\n\\t\\t\\t\\tthis.graphicsDevice.frameEnd();\\n\\t\\t}\\n\\t\\trenderComposition(layerComposition) {\\n\\t\\t\\t\\tthis.renderer.update(layerComposition);\\n\\t\\t\\t\\tthis.renderer.buildFrameGraph(this.frameGraph, layerComposition);\\n\\t\\t\\t\\tthis.frameGraph.render(this.graphicsDevice);\\n\\t\\t}\\n\\t\\t_fillFrameStatsBasic(now, dt, ms) {\\n\\t\\t\\t\\tconst stats = this.stats.frame;\\n\\t\\t\\t\\tstats.dt = dt;\\n\\t\\t\\t\\tstats.ms = ms;\\n\\t\\t\\t\\tif (now > stats._timeToCountFrames) {\\n\\t\\t\\t\\t\\t\\tstats.fps = stats._fpsAccum;\\n\\t\\t\\t\\t\\t\\tstats._fpsAccum = 0;\\n\\t\\t\\t\\t\\t\\tstats._timeToCountFrames = now + 1000;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tstats._fpsAccum++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.stats.drawCalls.total = this.graphicsDevice._drawCallsPerFrame;\\n\\t\\t\\t\\tthis.graphicsDevice._drawCallsPerFrame = 0;\\n\\t\\t\\t\\tstats.gsplats = this.renderer._gsplatCount;\\n\\t\\t}\\n\\t\\t_fillFrameStats() {\\n\\t\\t\\t\\tlet stats = this.stats.frame;\\n\\t\\t\\t\\tstats.cameras = this.renderer._camerasRendered;\\n\\t\\t\\t\\tstats.materials = this.renderer._materialSwitches;\\n\\t\\t\\t\\tstats.shaders = this.graphicsDevice._shaderSwitchesPerFrame;\\n\\t\\t\\t\\tstats.shadowMapUpdates = this.renderer._shadowMapUpdates;\\n\\t\\t\\t\\tstats.shadowMapTime = this.renderer._shadowMapTime;\\n\\t\\t\\t\\tstats.depthMapTime = this.renderer._depthMapTime;\\n\\t\\t\\t\\tstats.forwardTime = this.renderer._forwardTime;\\n\\t\\t\\t\\tconst prims = this.graphicsDevice._primsPerFrame;\\n\\t\\t\\t\\tstats.triangles = prims[PRIMITIVE_TRIANGLES] / 3 + Math.max(prims[PRIMITIVE_TRISTRIP] - 2, 0) + Math.max(prims[PRIMITIVE_TRIFAN] - 2, 0);\\n\\t\\t\\t\\tstats.cullTime = this.renderer._cullTime;\\n\\t\\t\\t\\tstats.sortTime = this.renderer._sortTime;\\n\\t\\t\\t\\tstats.skinTime = this.renderer._skinTime;\\n\\t\\t\\t\\tstats.morphTime = this.renderer._morphTime;\\n\\t\\t\\t\\tstats.lightClusters = this.renderer._lightClusters;\\n\\t\\t\\t\\tstats.lightClustersTime = this.renderer._lightClustersTime;\\n\\t\\t\\t\\tstats.otherPrimitives = 0;\\n\\t\\t\\t\\tfor(let i = 0; i < prims.length; i++){\\n\\t\\t\\t\\t\\t\\tif (i < PRIMITIVE_TRIANGLES) {\\n\\t\\t\\t\\t\\t\\t\\t\\tstats.otherPrimitives += prims[i];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tprims[i] = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.renderer._camerasRendered = 0;\\n\\t\\t\\t\\tthis.renderer._materialSwitches = 0;\\n\\t\\t\\t\\tthis.renderer._shadowMapUpdates = 0;\\n\\t\\t\\t\\tthis.graphicsDevice._shaderSwitchesPerFrame = 0;\\n\\t\\t\\t\\tthis.renderer._cullTime = 0;\\n\\t\\t\\t\\tthis.renderer._layerCompositionUpdateTime = 0;\\n\\t\\t\\t\\tthis.renderer._lightClustersTime = 0;\\n\\t\\t\\t\\tthis.renderer._sortTime = 0;\\n\\t\\t\\t\\tthis.renderer._skinTime = 0;\\n\\t\\t\\t\\tthis.renderer._morphTime = 0;\\n\\t\\t\\t\\tthis.renderer._shadowMapTime = 0;\\n\\t\\t\\t\\tthis.renderer._depthMapTime = 0;\\n\\t\\t\\t\\tthis.renderer._forwardTime = 0;\\n\\t\\t\\t\\tstats = this.stats.drawCalls;\\n\\t\\t\\t\\tstats.forward = this.renderer._forwardDrawCalls;\\n\\t\\t\\t\\tstats.culled = this.renderer._numDrawCallsCulled;\\n\\t\\t\\t\\tstats.depth = 0;\\n\\t\\t\\t\\tstats.shadow = this.renderer._shadowDrawCalls;\\n\\t\\t\\t\\tstats.skinned = this.renderer._skinDrawCalls;\\n\\t\\t\\t\\tstats.immediate = 0;\\n\\t\\t\\t\\tstats.instanced = 0;\\n\\t\\t\\t\\tstats.removedByInstancing = 0;\\n\\t\\t\\t\\tstats.misc = stats.total - (stats.forward + stats.shadow);\\n\\t\\t\\t\\tthis.renderer._depthDrawCalls = 0;\\n\\t\\t\\t\\tthis.renderer._shadowDrawCalls = 0;\\n\\t\\t\\t\\tthis.renderer._forwardDrawCalls = 0;\\n\\t\\t\\t\\tthis.renderer._numDrawCallsCulled = 0;\\n\\t\\t\\t\\tthis.renderer._skinDrawCalls = 0;\\n\\t\\t\\t\\tthis.renderer._immediateRendered = 0;\\n\\t\\t\\t\\tthis.renderer._instancedDrawCalls = 0;\\n\\t\\t\\t\\tthis.stats.misc.renderTargetCreationTime = this.graphicsDevice.renderTargetCreationTime;\\n\\t\\t\\t\\tstats = this.stats.particles;\\n\\t\\t\\t\\tstats.updatesPerFrame = stats._updatesPerFrame;\\n\\t\\t\\t\\tstats.frameTime = stats._frameTime;\\n\\t\\t\\t\\tstats._updatesPerFrame = 0;\\n\\t\\t\\t\\tstats._frameTime = 0;\\n\\t\\t}\\n\\t\\tsetCanvasFillMode(mode, width, height) {\\n\\t\\t\\t\\tthis._fillMode = mode;\\n\\t\\t\\t\\tthis.resizeCanvas(width, height);\\n\\t\\t}\\n\\t\\tsetCanvasResolution(mode, width, height) {\\n\\t\\t\\t\\tthis._resolutionMode = mode;\\n\\t\\t\\t\\tif (mode === RESOLUTION_AUTO && width === undefined) {\\n\\t\\t\\t\\t\\t\\twidth = this.graphicsDevice.canvas.clientWidth;\\n\\t\\t\\t\\t\\t\\theight = this.graphicsDevice.canvas.clientHeight;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.graphicsDevice.resizeCanvas(width, height);\\n\\t\\t}\\n\\t\\tisHidden() {\\n\\t\\t\\t\\treturn document[this._hiddenAttr];\\n\\t\\t}\\n\\t\\tonVisibilityChange() {\\n\\t\\t\\t\\tif (this.isHidden()) {\\n\\t\\t\\t\\t\\t\\tif (this._soundManager) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._soundManager.suspend();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (this._soundManager) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._soundManager.resume();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tresizeCanvas(width, height) {\\n\\t\\t\\t\\tif (!this._allowResize) return undefined;\\n\\t\\t\\t\\tif (this.xr && this.xr.session) {\\n\\t\\t\\t\\t\\t\\treturn undefined;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst windowWidth = window.innerWidth;\\n\\t\\t\\t\\tconst windowHeight = window.innerHeight;\\n\\t\\t\\t\\tif (this._fillMode === FILLMODE_KEEP_ASPECT) {\\n\\t\\t\\t\\t\\t\\tconst r = this.graphicsDevice.canvas.width / this.graphicsDevice.canvas.height;\\n\\t\\t\\t\\t\\t\\tconst winR = windowWidth / windowHeight;\\n\\t\\t\\t\\t\\t\\tif (r > winR) {\\n\\t\\t\\t\\t\\t\\t\\t\\twidth = windowWidth;\\n\\t\\t\\t\\t\\t\\t\\t\\theight = width / r;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\theight = windowHeight;\\n\\t\\t\\t\\t\\t\\t\\t\\twidth = height * r;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else if (this._fillMode === FILLMODE_FILL_WINDOW) {\\n\\t\\t\\t\\t\\t\\twidth = windowWidth;\\n\\t\\t\\t\\t\\t\\theight = windowHeight;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.graphicsDevice.canvas.style.width = `${width}px`;\\n\\t\\t\\t\\tthis.graphicsDevice.canvas.style.height = `${height}px`;\\n\\t\\t\\t\\tthis.updateCanvasSize();\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\twidth: width,\\n\\t\\t\\t\\t\\t\\theight: height\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tupdateCanvasSize() {\\n\\t\\t\\t\\tif (!this._allowResize || this.xr?.active) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._resolutionMode === RESOLUTION_AUTO) {\\n\\t\\t\\t\\t\\t\\tconst canvas = this.graphicsDevice.canvas;\\n\\t\\t\\t\\t\\t\\tthis.graphicsDevice.resizeCanvas(canvas.clientWidth, canvas.clientHeight);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonLibrariesLoaded() {\\n\\t\\t\\t\\tthis._librariesLoaded = true;\\n\\t\\t\\t\\tif (this.systems.rigidbody) {\\n\\t\\t\\t\\t\\t\\tthis.systems.rigidbody.onLibraryLoaded();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tapplySceneSettings(settings) {\\n\\t\\t\\t\\tlet asset;\\n\\t\\t\\t\\tif (this.systems.rigidbody && typeof Ammo !== 'undefined') {\\n\\t\\t\\t\\t\\t\\tconst [x, y, z] = settings.physics.gravity;\\n\\t\\t\\t\\t\\t\\tthis.systems.rigidbody.gravity.set(x, y, z);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.scene.applySettings(settings);\\n\\t\\t\\t\\tif (settings.render.hasOwnProperty('skybox')) {\\n\\t\\t\\t\\t\\t\\tif (settings.render.skybox) {\\n\\t\\t\\t\\t\\t\\t\\t\\tasset = this.assets.get(settings.render.skybox);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (asset) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.setSkybox(asset);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.assets.once(`add:${settings.render.skybox}`, this.setSkybox, this);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setSkybox(null);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetAreaLightLuts(ltcMat1, ltcMat2) {\\n\\t\\t\\t\\tif (ltcMat1 && ltcMat2) {\\n\\t\\t\\t\\t\\t\\tAreaLightLuts.set(this.graphicsDevice, ltcMat1, ltcMat2);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetSkybox(asset) {\\n\\t\\t\\t\\tif (asset !== this._skyboxAsset) {\\n\\t\\t\\t\\t\\t\\tconst onSkyboxRemoved = ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setSkybox(null);\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tconst onSkyboxChanged = ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.scene.setSkybox(this._skyboxAsset ? this._skyboxAsset.resources : null);\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tif (this._skyboxAsset) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.assets.off(`load:${this._skyboxAsset.id}`, onSkyboxChanged, this);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.assets.off(`remove:${this._skyboxAsset.id}`, onSkyboxRemoved, this);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._skyboxAsset.off('change', onSkyboxChanged, this);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._skyboxAsset = asset;\\n\\t\\t\\t\\t\\t\\tif (this._skyboxAsset) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.assets.on(`load:${this._skyboxAsset.id}`, onSkyboxChanged, this);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.assets.once(`remove:${this._skyboxAsset.id}`, onSkyboxRemoved, this);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._skyboxAsset.on('change', onSkyboxChanged, this);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.scene.skyboxMip === 0 && !this._skyboxAsset.loadFaces) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._skyboxAsset.loadFaces = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.assets.load(this._skyboxAsset);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tonSkyboxChanged();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_firstBake() {\\n\\t\\t\\t\\tthis.lightmapper?.bake(null, this.scene.lightmapMode);\\n\\t\\t}\\n\\t\\t_firstBatch() {\\n\\t\\t\\t\\tthis.batcher?.generate();\\n\\t\\t}\\n\\t\\t_processTimestamp(timestamp) {\\n\\t\\t\\t\\treturn timestamp;\\n\\t\\t}\\n\\t\\tdrawLine(start, end, color, depthTest, layer) {\\n\\t\\t\\t\\tthis.scene.drawLine(start, end, color, depthTest, layer);\\n\\t\\t}\\n\\t\\tdrawLines(positions, colors, depthTest = true, layer = this.scene.defaultDrawLayer) {\\n\\t\\t\\t\\tthis.scene.drawLines(positions, colors, depthTest, layer);\\n\\t\\t}\\n\\t\\tdrawLineArrays(positions, colors, depthTest = true, layer = this.scene.defaultDrawLayer) {\\n\\t\\t\\t\\tthis.scene.drawLineArrays(positions, colors, depthTest, layer);\\n\\t\\t}\\n\\t\\tdrawWireSphere(center, radius, color = Color.WHITE, segments = 20, depthTest = true, layer = this.scene.defaultDrawLayer) {\\n\\t\\t\\t\\tthis.scene.immediate.drawWireSphere(center, radius, color, segments, depthTest, layer);\\n\\t\\t}\\n\\t\\tdrawWireAlignedBox(minPoint, maxPoint, color = Color.WHITE, depthTest = true, layer = this.scene.defaultDrawLayer, mat) {\\n\\t\\t\\t\\tthis.scene.immediate.drawWireAlignedBox(minPoint, maxPoint, color, depthTest, layer, mat);\\n\\t\\t}\\n\\t\\tdrawMeshInstance(meshInstance, layer = this.scene.defaultDrawLayer) {\\n\\t\\t\\t\\tthis.scene.immediate.drawMesh(null, null, null, meshInstance, layer);\\n\\t\\t}\\n\\t\\tdrawMesh(mesh, material, matrix, layer = this.scene.defaultDrawLayer) {\\n\\t\\t\\t\\tthis.scene.immediate.drawMesh(material, matrix, mesh, null, layer);\\n\\t\\t}\\n\\t\\tdrawQuad(matrix, material, layer = this.scene.defaultDrawLayer) {\\n\\t\\t\\t\\tthis.scene.immediate.drawMesh(material, matrix, this.scene.immediate.getQuadMesh(), null, layer);\\n\\t\\t}\\n\\t\\tdrawTexture(x, y, width, height, texture, material, layer = this.scene.defaultDrawLayer, filterable = true) {\\n\\t\\t\\t\\tif (filterable === false && !this.graphicsDevice.isWebGPU) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst matrix = new Mat4();\\n\\t\\t\\t\\tmatrix.setTRS(new Vec3(x, y, 0.0), Quat.IDENTITY, new Vec3(width, -height, 0.0));\\n\\t\\t\\t\\tif (!material) {\\n\\t\\t\\t\\t\\t\\tmaterial = new ShaderMaterial();\\n\\t\\t\\t\\t\\t\\tmaterial.cull = CULLFACE_NONE;\\n\\t\\t\\t\\t\\t\\tmaterial.setParameter('colorMap', texture);\\n\\t\\t\\t\\t\\t\\tmaterial.shaderDesc = filterable ? this.scene.immediate.getTextureShaderDesc(texture.encoding) : this.scene.immediate.getUnfilterableTextureShaderDesc();\\n\\t\\t\\t\\t\\t\\tmaterial.update();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.drawQuad(matrix, material, layer);\\n\\t\\t}\\n\\t\\tdrawDepthTexture(x, y, width, height, layer = this.scene.defaultDrawLayer) {\\n\\t\\t\\t\\tconst material = new ShaderMaterial();\\n\\t\\t\\t\\tmaterial.cull = CULLFACE_NONE;\\n\\t\\t\\t\\tmaterial.shaderDesc = this.scene.immediate.getDepthTextureShaderDesc();\\n\\t\\t\\t\\tmaterial.update();\\n\\t\\t\\t\\tthis.drawTexture(x, y, width, height, null, material, layer);\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tif (this._inFrameUpdate) {\\n\\t\\t\\t\\t\\t\\tthis._destroyRequested = true;\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst canvasId = this.graphicsDevice.canvas.id;\\n\\t\\t\\t\\tthis.fire('destroy', this);\\n\\t\\t\\t\\tthis.off('librariesloaded');\\n\\t\\t\\t\\tthis._gsplatSortedEvt?.off();\\n\\t\\t\\t\\tthis._gsplatSortedEvt = null;\\n\\t\\t\\t\\tif (typeof document !== 'undefined') {\\n\\t\\t\\t\\t\\t\\tdocument.removeEventListener('visibilitychange', this._visibilityChangeHandler, false);\\n\\t\\t\\t\\t\\t\\tdocument.removeEventListener('mozvisibilitychange', this._visibilityChangeHandler, false);\\n\\t\\t\\t\\t\\t\\tdocument.removeEventListener('msvisibilitychange', this._visibilityChangeHandler, false);\\n\\t\\t\\t\\t\\t\\tdocument.removeEventListener('webkitvisibilitychange', this._visibilityChangeHandler, false);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._visibilityChangeHandler = null;\\n\\t\\t\\t\\tthis.root.destroy();\\n\\t\\t\\t\\tthis.root = null;\\n\\t\\t\\t\\tif (this.mouse) {\\n\\t\\t\\t\\t\\t\\tthis.mouse.off();\\n\\t\\t\\t\\t\\t\\tthis.mouse.detach();\\n\\t\\t\\t\\t\\t\\tthis.mouse = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.keyboard) {\\n\\t\\t\\t\\t\\t\\tthis.keyboard.off();\\n\\t\\t\\t\\t\\t\\tthis.keyboard.detach();\\n\\t\\t\\t\\t\\t\\tthis.keyboard = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.touch) {\\n\\t\\t\\t\\t\\t\\tthis.touch.off();\\n\\t\\t\\t\\t\\t\\tthis.touch.detach();\\n\\t\\t\\t\\t\\t\\tthis.touch = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.elementInput) {\\n\\t\\t\\t\\t\\t\\tthis.elementInput.detach();\\n\\t\\t\\t\\t\\t\\tthis.elementInput = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.gamepads) {\\n\\t\\t\\t\\t\\t\\tthis.gamepads.destroy();\\n\\t\\t\\t\\t\\t\\tthis.gamepads = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.controller) {\\n\\t\\t\\t\\t\\t\\tthis.controller = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.systems.destroy();\\n\\t\\t\\t\\tif (this.scene.layers) {\\n\\t\\t\\t\\t\\t\\tthis.scene.layers.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.bundles.destroy();\\n\\t\\t\\t\\tthis.bundles = null;\\n\\t\\t\\t\\tthis.i18n.destroy();\\n\\t\\t\\t\\tthis.i18n = null;\\n\\t\\t\\t\\tconst scriptHandler = this.loader.getHandler(\\\"script\\\");\\n\\t\\t\\t\\tscriptHandler?.clearCache();\\n\\t\\t\\t\\tthis.loader.destroy();\\n\\t\\t\\t\\tthis.loader = null;\\n\\t\\t\\t\\tthis.systems = null;\\n\\t\\t\\t\\tthis.context = null;\\n\\t\\t\\t\\tthis.scripts.destroy();\\n\\t\\t\\t\\tthis.scripts = null;\\n\\t\\t\\t\\tthis.scenes.destroy();\\n\\t\\t\\t\\tthis.scenes = null;\\n\\t\\t\\t\\tthis.lightmapper?.destroy();\\n\\t\\t\\t\\tthis.lightmapper = null;\\n\\t\\t\\t\\tif (this._batcher) {\\n\\t\\t\\t\\t\\t\\tthis._batcher.destroy();\\n\\t\\t\\t\\t\\t\\tthis._batcher = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._entityIndex = {};\\n\\t\\t\\t\\tthis.defaultLayerDepth.onDisable = null;\\n\\t\\t\\t\\tthis.defaultLayerDepth.onEnable = null;\\n\\t\\t\\t\\tthis.defaultLayerDepth = null;\\n\\t\\t\\t\\tthis.defaultLayerWorld = null;\\n\\t\\t\\t\\tthis.xr?.end();\\n\\t\\t\\t\\tthis.xr?.destroy();\\n\\t\\t\\t\\tthis.renderer.destroy();\\n\\t\\t\\t\\tthis.renderer = null;\\n\\t\\t\\t\\tconst assets = this.assets.list();\\n\\t\\t\\t\\tfor(let i = 0; i < assets.length; i++){\\n\\t\\t\\t\\t\\t\\tassets[i].unload();\\n\\t\\t\\t\\t\\t\\tassets[i].off();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.assets.off();\\n\\t\\t\\t\\tthis.scene.destroy();\\n\\t\\t\\t\\tthis.scene = null;\\n\\t\\t\\t\\tthis.graphicsDevice.destroy();\\n\\t\\t\\t\\tthis.graphicsDevice = null;\\n\\t\\t\\t\\tthis.tick = null;\\n\\t\\t\\t\\tthis.off();\\n\\t\\t\\t\\tthis._soundManager?.destroy();\\n\\t\\t\\t\\tthis._soundManager = null;\\n\\t\\t\\t\\tAppBase._applications[canvasId] = null;\\n\\t\\t\\t\\tif (getApplication() === this) {\\n\\t\\t\\t\\t\\t\\tsetApplication(null);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tAppBase.cancelTick(this);\\n\\t\\t}\\n\\t\\tstatic cancelTick(app) {\\n\\t\\t\\t\\tif (app.frameRequestId) {\\n\\t\\t\\t\\t\\t\\tcancelAnimationFrame(app.frameRequestId);\\n\\t\\t\\t\\t\\t\\tapp.frameRequestId = undefined;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetEntityFromIndex(guid) {\\n\\t\\t\\t\\treturn this._entityIndex[guid];\\n\\t\\t}\\n\\t\\t_registerSceneImmediate(scene) {\\n\\t\\t\\t\\tthis.on('postrender', scene.immediate.onPostRender, scene.immediate);\\n\\t\\t\\t\\tthis._gsplatSortedEvt = scene.on('gsplat:sorted', (sortTime)=>{\\n\\t\\t\\t\\t\\t\\tthis.stats.frame.gsplatSort += sortTime;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tconstructor(canvas){\\n\\t\\t\\t\\tsuper(), this._batcher = null, this._destroyRequested = false, this._inFrameUpdate = false, this._librariesLoaded = false, this._fillMode = FILLMODE_KEEP_ASPECT, this._resolutionMode = RESOLUTION_FIXED, this._allowResize = true, this._skyboxAsset = null, this._entityIndex = {}, this._inTools = false, this._scriptPrefix = '', this._time = 0, this.enableBundles = typeof TextDecoder !== 'undefined', this.timeScale = 1, this.maxDeltaTime = 0.1, this.frame = 0, this.frameGraph = new FrameGraph(), this.scriptsOrder = [], this.autoRender = true, this.renderNextFrame = false, this.lightmapper = null, this.loader = new ResourceLoader(this), this.scenes = new SceneRegistry(this), this.scripts = new ScriptRegistry(this), this.systems = new ComponentSystemRegistry(), this.i18n = new I18n(this), this.keyboard = null, this.mouse = null, this.touch = null, this.gamepads = null, this.elementInput = null, this.xr = null;\\n\\t\\t\\t\\tAppBase._applications[canvas.id] = this;\\n\\t\\t\\t\\tsetApplication(this);\\n\\t\\t\\t\\tthis.root = new Entity();\\n\\t\\t\\t\\tthis.root._enabledInHierarchy = true;\\n\\t\\t}\\n}\\nAppBase._applications = {};\\nconst makeTick = function(_app) {\\n\\t\\tconst application = _app;\\n\\t\\treturn function(timestamp, xrFrame) {\\n\\t\\t\\t\\tif (!application.graphicsDevice) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (application.frameRequestId) {\\n\\t\\t\\t\\t\\t\\tapplication.xr?.session?.cancelAnimationFrame(application.frameRequestId);\\n\\t\\t\\t\\t\\t\\tcancelAnimationFrame(application.frameRequestId);\\n\\t\\t\\t\\t\\t\\tapplication.frameRequestId = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tapplication._inFrameUpdate = true;\\n\\t\\t\\t\\tsetApplication(application);\\n\\t\\t\\t\\tconst currentTime = application._processTimestamp(timestamp) || now();\\n\\t\\t\\t\\tconst ms = currentTime - (application._time || currentTime);\\n\\t\\t\\t\\tlet dt = ms / 1000.0;\\n\\t\\t\\t\\tdt = math.clamp(dt, 0, application.maxDeltaTime);\\n\\t\\t\\t\\tdt *= application.timeScale;\\n\\t\\t\\t\\tapplication._time = currentTime;\\n\\t\\t\\t\\tapplication.requestAnimationFrame();\\n\\t\\t\\t\\tif (application.graphicsDevice.contextLost) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tapplication._fillFrameStatsBasic(currentTime, dt, ms);\\n\\t\\t\\t\\tapplication.fire('frameupdate', ms);\\n\\t\\t\\t\\tlet skipUpdate = false;\\n\\t\\t\\t\\tif (xrFrame) {\\n\\t\\t\\t\\t\\t\\tskipUpdate = !application.xr?.update(xrFrame);\\n\\t\\t\\t\\t\\t\\tapplication.graphicsDevice.defaultFramebuffer = xrFrame.session.renderState.baseLayer.framebuffer;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tapplication.graphicsDevice.defaultFramebuffer = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!skipUpdate) {\\n\\t\\t\\t\\t\\t\\tapplication.update(dt);\\n\\t\\t\\t\\t\\t\\tapplication.fire('framerender');\\n\\t\\t\\t\\t\\t\\tif (application.autoRender || application.renderNextFrame) {\\n\\t\\t\\t\\t\\t\\t\\t\\tapplication.render();\\n\\t\\t\\t\\t\\t\\t\\t\\tapplication.renderNextFrame = false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tapplication.fire('frameend');\\n\\t\\t\\t\\t\\t\\tapplication.stats.frameEnd();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tapplication._inFrameUpdate = false;\\n\\t\\t\\t\\tif (application._destroyRequested) {\\n\\t\\t\\t\\t\\t\\tapplication.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t};\\n};\\n\\nclass AppOptions {\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.componentSystems = [];\\n\\t\\t\\t\\tthis.resourceHandlers = [];\\n\\t\\t}\\n}\\n\\nclass Component extends EventHandler {\\n\\t\\tstatic _buildAccessors(obj, schema) {\\n\\t\\t\\t\\tschema.forEach((descriptor)=>{\\n\\t\\t\\t\\t\\t\\tconst name = typeof descriptor === 'object' ? descriptor.name : descriptor;\\n\\t\\t\\t\\t\\t\\tObject.defineProperty(obj, name, {\\n\\t\\t\\t\\t\\t\\t\\t\\tget: function() {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn this.data[name];\\n\\t\\t\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t\\t\\tset: function(value) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst data = this.data;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst oldValue = data[name];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata[name] = value;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('set', name, oldValue, value);\\n\\t\\t\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t\\t\\tconfigurable: true\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tobj._accessorsBuilt = true;\\n\\t\\t}\\n\\t\\tbuildAccessors(schema) {\\n\\t\\t\\t\\tComponent._buildAccessors(this, schema);\\n\\t\\t}\\n\\t\\tonSetEnabled(name, oldValue, newValue) {\\n\\t\\t\\t\\tif (oldValue !== newValue) {\\n\\t\\t\\t\\t\\t\\tif (this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (newValue) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.onEnable();\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.onDisable();\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonEnable() {}\\n\\t\\tonDisable() {}\\n\\t\\tonPostStateChange() {}\\n\\t\\tget data() {\\n\\t\\t\\t\\tconst record = this.system.store[this.entity.getGuid()];\\n\\t\\t\\t\\treturn record ? record.data : null;\\n\\t\\t}\\n\\t\\tset enabled(arg) {}\\n\\t\\tget enabled() {\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tconstructor(system, entity){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.system = system;\\n\\t\\t\\t\\tthis.entity = entity;\\n\\t\\t\\t\\tif (this.system.schema && !this._accessorsBuilt) {\\n\\t\\t\\t\\t\\t\\tthis.buildAccessors(this.system.schema);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.on('set', function(name, oldValue, newValue) {\\n\\t\\t\\t\\t\\t\\tthis.fire(`set_${name}`, name, oldValue, newValue);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.on('set_enabled', this.onSetEnabled, this);\\n\\t\\t}\\n}\\nComponent.order = 0;\\n\\nclass ComponentSystem extends EventHandler {\\n\\t\\taddComponent(entity, data = {}) {\\n\\t\\t\\t\\tconst component = new this.ComponentType(this, entity);\\n\\t\\t\\t\\tconst componentData = new this.DataType();\\n\\t\\t\\t\\tthis.store[entity.getGuid()] = {\\n\\t\\t\\t\\t\\t\\tentity: entity,\\n\\t\\t\\t\\t\\t\\tdata: componentData\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tentity[this.id] = component;\\n\\t\\t\\t\\tentity.c[this.id] = component;\\n\\t\\t\\t\\tthis.initializeComponentData(component, data, []);\\n\\t\\t\\t\\tthis.fire('add', entity, component);\\n\\t\\t\\t\\treturn component;\\n\\t\\t}\\n\\t\\tremoveComponent(entity) {\\n\\t\\t\\t\\tconst id = this.id;\\n\\t\\t\\t\\tconst record = this.store[entity.getGuid()];\\n\\t\\t\\t\\tconst component = entity.c[id];\\n\\t\\t\\t\\tcomponent.fire('beforeremove');\\n\\t\\t\\t\\tthis.fire('beforeremove', entity, component);\\n\\t\\t\\t\\tdelete this.store[entity.getGuid()];\\n\\t\\t\\t\\tentity[id] = undefined;\\n\\t\\t\\t\\tdelete entity.c[id];\\n\\t\\t\\t\\tthis.fire('remove', entity, record.data);\\n\\t\\t}\\n\\t\\tcloneComponent(entity, clone) {\\n\\t\\t\\t\\tconst src = this.store[entity.getGuid()];\\n\\t\\t\\t\\treturn this.addComponent(clone, src.data);\\n\\t\\t}\\n\\t\\tinitializeComponentData(component, data = {}, properties) {\\n\\t\\t\\t\\tfor(let i = 0, len = properties.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst descriptor = properties[i];\\n\\t\\t\\t\\t\\t\\tlet name, type;\\n\\t\\t\\t\\t\\t\\tif (typeof descriptor === 'object') {\\n\\t\\t\\t\\t\\t\\t\\t\\tname = descriptor.name;\\n\\t\\t\\t\\t\\t\\t\\t\\ttype = descriptor.type;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tname = descriptor;\\n\\t\\t\\t\\t\\t\\t\\t\\ttype = undefined;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlet value = data[name];\\n\\t\\t\\t\\t\\t\\tif (value !== undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (type !== undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvalue = convertValue(value, type);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponent[name] = value;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponent[name] = component.data[name];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (component.enabled && component.entity.enabled) {\\n\\t\\t\\t\\t\\t\\tcomponent.onEnable();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetPropertiesOfType(type) {\\n\\t\\t\\t\\tconst matchingProperties = [];\\n\\t\\t\\t\\tconst schema = this.schema || [];\\n\\t\\t\\t\\tschema.forEach((descriptor)=>{\\n\\t\\t\\t\\t\\t\\tif (descriptor && typeof descriptor === 'object' && descriptor.type === type) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmatchingProperties.push(descriptor);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn matchingProperties;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.off();\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.app = app;\\n\\t\\t\\t\\tthis.store = {};\\n\\t\\t\\t\\tthis.schema = [];\\n\\t\\t}\\n}\\nfunction convertValue(value, type) {\\n\\t\\tif (!value) {\\n\\t\\t\\t\\treturn value;\\n\\t\\t}\\n\\t\\tswitch(type){\\n\\t\\t\\t\\tcase 'rgb':\\n\\t\\t\\t\\t\\t\\tif (value instanceof Color) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn value.clone();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn new Color(value[0], value[1], value[2]);\\n\\t\\t\\t\\tcase 'rgba':\\n\\t\\t\\t\\t\\t\\tif (value instanceof Color) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn value.clone();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn new Color(value[0], value[1], value[2], value[3]);\\n\\t\\t\\t\\tcase 'vec2':\\n\\t\\t\\t\\t\\t\\tif (value instanceof Vec2) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn value.clone();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn new Vec2(value[0], value[1]);\\n\\t\\t\\t\\tcase 'vec3':\\n\\t\\t\\t\\t\\t\\tif (value instanceof Vec3) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn value.clone();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn new Vec3(value[0], value[1], value[2]);\\n\\t\\t\\t\\tcase 'vec4':\\n\\t\\t\\t\\t\\t\\tif (value instanceof Vec4) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn value.clone();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn new Vec4(value[0], value[1], value[2], value[3]);\\n\\t\\t\\t\\tcase 'boolean':\\n\\t\\t\\t\\tcase 'number':\\n\\t\\t\\t\\tcase 'string':\\n\\t\\t\\t\\t\\t\\treturn value;\\n\\t\\t\\t\\tcase 'entity':\\n\\t\\t\\t\\t\\t\\treturn value;\\n\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\tthrow new Error(`Could not convert unhandled type: ${type}`);\\n\\t\\t}\\n}\\n\\nconst INTERPOLATION_STEP = 0;\\nconst INTERPOLATION_LINEAR = 1;\\nconst INTERPOLATION_CUBIC = 2;\\n\\nclass AnimEvents {\\n\\t\\tget events() {\\n\\t\\t\\t\\treturn this._events;\\n\\t\\t}\\n\\t\\tconstructor(events){\\n\\t\\t\\t\\tthis._events = [\\n\\t\\t\\t\\t\\t\\t...events\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis._events.sort((a, b)=>a.time - b.time);\\n\\t\\t}\\n}\\n\\nclass AnimTrack {\\n\\t\\tget name() {\\n\\t\\t\\t\\treturn this._name;\\n\\t\\t}\\n\\t\\tget duration() {\\n\\t\\t\\t\\treturn this._duration;\\n\\t\\t}\\n\\t\\tget inputs() {\\n\\t\\t\\t\\treturn this._inputs;\\n\\t\\t}\\n\\t\\tget outputs() {\\n\\t\\t\\t\\treturn this._outputs;\\n\\t\\t}\\n\\t\\tget curves() {\\n\\t\\t\\t\\treturn this._curves;\\n\\t\\t}\\n\\t\\tset events(animEvents) {\\n\\t\\t\\t\\tthis._animEvents = animEvents;\\n\\t\\t}\\n\\t\\tget events() {\\n\\t\\t\\t\\treturn this._animEvents.events;\\n\\t\\t}\\n\\t\\teval(time, snapshot) {\\n\\t\\t\\t\\tsnapshot._time = time;\\n\\t\\t\\t\\tconst inputs = this._inputs;\\n\\t\\t\\t\\tconst outputs = this._outputs;\\n\\t\\t\\t\\tconst curves = this._curves;\\n\\t\\t\\t\\tconst cache = snapshot._cache;\\n\\t\\t\\t\\tconst results = snapshot._results;\\n\\t\\t\\t\\tfor(let i = 0; i < inputs.length; ++i){\\n\\t\\t\\t\\t\\t\\tcache[i].update(time, inputs[i]._data);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < curves.length; ++i){\\n\\t\\t\\t\\t\\t\\tconst curve = curves[i];\\n\\t\\t\\t\\t\\t\\tconst output = outputs[curve._output];\\n\\t\\t\\t\\t\\t\\tconst result = results[i];\\n\\t\\t\\t\\t\\t\\tcache[curve._input].eval(result, curve._interpolation, output);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(name, duration, inputs, outputs, curves, animEvents = new AnimEvents([])){\\n\\t\\t\\t\\tthis._name = name;\\n\\t\\t\\t\\tthis._duration = duration;\\n\\t\\t\\t\\tthis._inputs = inputs;\\n\\t\\t\\t\\tthis._outputs = outputs;\\n\\t\\t\\t\\tthis._curves = curves;\\n\\t\\t\\t\\tthis._animEvents = animEvents;\\n\\t\\t}\\n}\\nAnimTrack.EMPTY = Object.freeze(new AnimTrack('empty', Number.MAX_VALUE, [], [], []));\\n\\nclass PrimitivesCache {\\n\\t\\tdestroy(device) {\\n\\t\\t\\t\\tthis.map.forEach((primData)=>primData.mesh.destroy());\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.map = new Map();\\n\\t\\t}\\n}\\nconst _primitivesCache = new DeviceCache();\\nconst getShapePrimitive = (device, type)=>{\\n\\t\\tconst cache = _primitivesCache.get(device, ()=>{\\n\\t\\t\\t\\treturn new PrimitivesCache();\\n\\t\\t});\\n\\t\\tlet primData = cache.map.get(type);\\n\\t\\tif (!primData) {\\n\\t\\t\\t\\tlet mesh, area;\\n\\t\\t\\t\\tswitch(type){\\n\\t\\t\\t\\t\\t\\tcase 'box':\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh = Mesh.fromGeometry(device, new BoxGeometry());\\n\\t\\t\\t\\t\\t\\t\\t\\tarea = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tx: 2,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ty: 2,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tz: 2,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuv: 2.0 / 3\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 'capsule':\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh = Mesh.fromGeometry(device, new CapsuleGeometry({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tradius: 0.5,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\theight: 2\\n\\t\\t\\t\\t\\t\\t\\t\\t}));\\n\\t\\t\\t\\t\\t\\t\\t\\tarea = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tx: Math.PI * 2,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ty: Math.PI,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tz: Math.PI * 2,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuv: 1.0 / 3 + 1.0 / 3 / 3 * 2\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 'cone':\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh = Mesh.fromGeometry(device, new ConeGeometry({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbaseRadius: 0.5,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpeakRadius: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\theight: 1\\n\\t\\t\\t\\t\\t\\t\\t\\t}));\\n\\t\\t\\t\\t\\t\\t\\t\\tarea = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tx: 2.54,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ty: 2.54,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tz: 2.54,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuv: 1.0 / 3 + 1.0 / 3 / 3\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 'cylinder':\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh = Mesh.fromGeometry(device, new CylinderGeometry({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tradius: 0.5,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\theight: 1\\n\\t\\t\\t\\t\\t\\t\\t\\t}));\\n\\t\\t\\t\\t\\t\\t\\t\\tarea = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tx: Math.PI,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ty: 0.79 * 2,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tz: Math.PI,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuv: 1.0 / 3 + 1.0 / 3 / 3 * 2\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 'plane':\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh = Mesh.fromGeometry(device, new PlaneGeometry({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\thalfExtents: new Vec2(0.5, 0.5),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twidthSegments: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlengthSegments: 1\\n\\t\\t\\t\\t\\t\\t\\t\\t}));\\n\\t\\t\\t\\t\\t\\t\\t\\tarea = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tx: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ty: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tz: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuv: 1\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 'sphere':\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh = Mesh.fromGeometry(device, new SphereGeometry({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tradius: 0.5\\n\\t\\t\\t\\t\\t\\t\\t\\t}));\\n\\t\\t\\t\\t\\t\\t\\t\\tarea = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tx: Math.PI,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ty: Math.PI,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tz: Math.PI,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuv: 1\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 'torus':\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh = Mesh.fromGeometry(device, new TorusGeometry({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttubeRadius: 0.2,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tringRadius: 0.3\\n\\t\\t\\t\\t\\t\\t\\t\\t}));\\n\\t\\t\\t\\t\\t\\t\\t\\tarea = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tx: Math.PI * 0.5 * 0.5 - Math.PI * 0.1 * 0.1,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ty: 0.4,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tz: 0.4,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuv: 1\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\t\\t\\tthrow new Error(`Invalid primitive type: ${type}`);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tmesh.incRefCount();\\n\\t\\t\\t\\tprimData = {\\n\\t\\t\\t\\t\\t\\tmesh: mesh,\\n\\t\\t\\t\\t\\t\\tarea: area\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tcache.map.set(type, primData);\\n\\t\\t}\\n\\t\\treturn primData;\\n};\\n\\nclass SkinInstanceCachedObject extends RefCountedObject {\\n\\t\\tconstructor(skin, skinInstance){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.skin = skin;\\n\\t\\t\\t\\tthis.skinInstance = skinInstance;\\n\\t\\t}\\n}\\nclass SkinInstanceCache {\\n\\t\\tstatic createCachedSkinInstance(skin, rootBone, entity) {\\n\\t\\t\\t\\tlet skinInst = SkinInstanceCache.getCachedSkinInstance(skin, rootBone);\\n\\t\\t\\t\\tif (!skinInst) {\\n\\t\\t\\t\\t\\t\\tskinInst = new SkinInstance(skin);\\n\\t\\t\\t\\t\\t\\tskinInst.resolve(rootBone, entity);\\n\\t\\t\\t\\t\\t\\tSkinInstanceCache.addCachedSkinInstance(skin, rootBone, skinInst);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn skinInst;\\n\\t\\t}\\n\\t\\tstatic getCachedSkinInstance(skin, rootBone) {\\n\\t\\t\\t\\tlet skinInstance = null;\\n\\t\\t\\t\\tconst cachedObjArray = SkinInstanceCache._skinInstanceCache.get(rootBone);\\n\\t\\t\\t\\tif (cachedObjArray) {\\n\\t\\t\\t\\t\\t\\tconst cachedObj = cachedObjArray.find((element)=>element.skin === skin);\\n\\t\\t\\t\\t\\t\\tif (cachedObj) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcachedObj.incRefCount();\\n\\t\\t\\t\\t\\t\\t\\t\\tskinInstance = cachedObj.skinInstance;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn skinInstance;\\n\\t\\t}\\n\\t\\tstatic addCachedSkinInstance(skin, rootBone, skinInstance) {\\n\\t\\t\\t\\tlet cachedObjArray = SkinInstanceCache._skinInstanceCache.get(rootBone);\\n\\t\\t\\t\\tif (!cachedObjArray) {\\n\\t\\t\\t\\t\\t\\tcachedObjArray = [];\\n\\t\\t\\t\\t\\t\\tSkinInstanceCache._skinInstanceCache.set(rootBone, cachedObjArray);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet cachedObj = cachedObjArray.find((element)=>element.skin === skin);\\n\\t\\t\\t\\tif (!cachedObj) {\\n\\t\\t\\t\\t\\t\\tcachedObj = new SkinInstanceCachedObject(skin, skinInstance);\\n\\t\\t\\t\\t\\t\\tcachedObjArray.push(cachedObj);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcachedObj.incRefCount();\\n\\t\\t}\\n\\t\\tstatic removeCachedSkinInstance(skinInstance) {\\n\\t\\t\\t\\tif (skinInstance) {\\n\\t\\t\\t\\t\\t\\tconst rootBone = skinInstance.rootBone;\\n\\t\\t\\t\\t\\t\\tif (rootBone) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst cachedObjArray = SkinInstanceCache._skinInstanceCache.get(rootBone);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (cachedObjArray) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst cachedObjIndex = cachedObjArray.findIndex((element)=>element.skinInstance === skinInstance);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (cachedObjIndex >= 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst cachedObj = cachedObjArray[cachedObjIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcachedObj.decRefCount();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (cachedObj.refCount === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcachedObjArray.splice(cachedObjIndex, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!cachedObjArray.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tSkinInstanceCache._skinInstanceCache.delete(rootBone);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (skinInstance) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tskinInstance.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcachedObj.skinInstance = null;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nSkinInstanceCache._skinInstanceCache = new Map();\\n\\nclass AssetReference {\\n\\t\\tset id(value) {\\n\\t\\t\\t\\tif (this.url) throw Error('Can\\\\'t set id and url');\\n\\t\\t\\t\\tthis._unbind();\\n\\t\\t\\t\\tthis._id = value;\\n\\t\\t\\t\\tthis.asset = this._registry.get(this._id);\\n\\t\\t\\t\\tthis._bind();\\n\\t\\t}\\n\\t\\tget id() {\\n\\t\\t\\t\\treturn this._id;\\n\\t\\t}\\n\\t\\tset url(value) {\\n\\t\\t\\t\\tif (this.id) throw Error('Can\\\\'t set id and url');\\n\\t\\t\\t\\tthis._unbind();\\n\\t\\t\\t\\tthis._url = value;\\n\\t\\t\\t\\tthis.asset = this._registry.getByUrl(this._url);\\n\\t\\t\\t\\tthis._bind();\\n\\t\\t}\\n\\t\\tget url() {\\n\\t\\t\\t\\treturn this._url;\\n\\t\\t}\\n\\t\\t_bind() {\\n\\t\\t\\t\\tif (this.id) {\\n\\t\\t\\t\\t\\t\\tif (this._onAssetLoad) this._evtLoadById = this._registry.on(`load:${this.id}`, this._onLoad, this);\\n\\t\\t\\t\\t\\t\\tif (this._onAssetAdd) this._evtAddById = this._registry.once(`add:${this.id}`, this._onAdd, this);\\n\\t\\t\\t\\t\\t\\tif (this._onAssetRemove) this._evtRemoveById = this._registry.on(`remove:${this.id}`, this._onRemove, this);\\n\\t\\t\\t\\t\\t\\tif (this._onAssetUnload) this._evtUnloadById = this._registry.on(`unload:${this.id}`, this._onUnload, this);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.url) {\\n\\t\\t\\t\\t\\t\\tif (this._onAssetLoad) this._evtLoadByUrl = this._registry.on(`load:url:${this.url}`, this._onLoad, this);\\n\\t\\t\\t\\t\\t\\tif (this._onAssetAdd) this._evtAddByUrl = this._registry.once(`add:url:${this.url}`, this._onAdd, this);\\n\\t\\t\\t\\t\\t\\tif (this._onAssetRemove) this._evtRemoveByUrl = this._registry.on(`remove:url:${this.url}`, this._onRemove, this);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_unbind() {\\n\\t\\t\\t\\tif (this.id) {\\n\\t\\t\\t\\t\\t\\tthis._evtLoadById?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtLoadById = null;\\n\\t\\t\\t\\t\\t\\tthis._evtAddById?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtAddById = null;\\n\\t\\t\\t\\t\\t\\tthis._evtRemoveById?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtRemoveById = null;\\n\\t\\t\\t\\t\\t\\tthis._evtUnloadById?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtUnloadById = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.url) {\\n\\t\\t\\t\\t\\t\\tthis._evtLoadByUrl?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtLoadByUrl = null;\\n\\t\\t\\t\\t\\t\\tthis._evtAddByUrl?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtAddByUrl = null;\\n\\t\\t\\t\\t\\t\\tthis._evtRemoveByUrl?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtRemoveByUrl = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onLoad(asset) {\\n\\t\\t\\t\\tthis._onAssetLoad.call(this._scope, this.propertyName, this.parent, asset);\\n\\t\\t}\\n\\t\\t_onAdd(asset) {\\n\\t\\t\\t\\tthis.asset = asset;\\n\\t\\t\\t\\tthis._onAssetAdd.call(this._scope, this.propertyName, this.parent, asset);\\n\\t\\t}\\n\\t\\t_onRemove(asset) {\\n\\t\\t\\t\\tthis._onAssetRemove.call(this._scope, this.propertyName, this.parent, asset);\\n\\t\\t\\t\\tthis.asset = null;\\n\\t\\t}\\n\\t\\t_onUnload(asset) {\\n\\t\\t\\t\\tthis._onAssetUnload.call(this._scope, this.propertyName, this.parent, asset);\\n\\t\\t}\\n\\t\\tconstructor(propertyName, parent, registry, callbacks, scope){\\n\\t\\t\\t\\tthis._evtLoadById = null;\\n\\t\\t\\t\\tthis._evtUnloadById = null;\\n\\t\\t\\t\\tthis._evtAddById = null;\\n\\t\\t\\t\\tthis._evtRemoveById = null;\\n\\t\\t\\t\\tthis._evtLoadByUrl = null;\\n\\t\\t\\t\\tthis._evtAddByUrl = null;\\n\\t\\t\\t\\tthis._evtRemoveByUrl = null;\\n\\t\\t\\t\\tthis.propertyName = propertyName;\\n\\t\\t\\t\\tthis.parent = parent;\\n\\t\\t\\t\\tthis._scope = scope;\\n\\t\\t\\t\\tthis._registry = registry;\\n\\t\\t\\t\\tthis.id = null;\\n\\t\\t\\t\\tthis.url = null;\\n\\t\\t\\t\\tthis.asset = null;\\n\\t\\t\\t\\tthis._onAssetLoad = callbacks.load;\\n\\t\\t\\t\\tthis._onAssetAdd = callbacks.add;\\n\\t\\t\\t\\tthis._onAssetRemove = callbacks.remove;\\n\\t\\t\\t\\tthis._onAssetUnload = callbacks.unload;\\n\\t\\t}\\n}\\n\\nclass RenderComponent extends Component {\\n\\t\\tset renderStyle(renderStyle) {\\n\\t\\t\\t\\tif (this._renderStyle !== renderStyle) {\\n\\t\\t\\t\\t\\t\\tthis._renderStyle = renderStyle;\\n\\t\\t\\t\\t\\t\\tMeshInstance._prepareRenderStyleForArray(this._meshInstances, renderStyle);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget renderStyle() {\\n\\t\\t\\t\\treturn this._renderStyle;\\n\\t\\t}\\n\\t\\tset customAabb(value) {\\n\\t\\t\\t\\tthis._customAabb = value;\\n\\t\\t\\t\\tconst mi = this._meshInstances;\\n\\t\\t\\t\\tif (mi) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < mi.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tmi[i].setCustomAabb(this._customAabb);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget customAabb() {\\n\\t\\t\\t\\treturn this._customAabb;\\n\\t\\t}\\n\\t\\tset type(value) {\\n\\t\\t\\t\\tif (this._type !== value) {\\n\\t\\t\\t\\t\\t\\tthis._area = null;\\n\\t\\t\\t\\t\\t\\tthis._type = value;\\n\\t\\t\\t\\t\\t\\tthis.destroyMeshInstances();\\n\\t\\t\\t\\t\\t\\tif (value !== 'asset') {\\n\\t\\t\\t\\t\\t\\t\\t\\tlet material = this._material;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!material || material === this.system.defaultMaterial) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmaterial = this._materialReferences[0] && this._materialReferences[0].asset && this._materialReferences[0].asset.resource;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst primData = getShapePrimitive(this.system.app.graphicsDevice, value);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._area = primData.area;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.meshInstances = [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnew MeshInstance(primData.mesh, material || this.system.defaultMaterial, this.entity)\\n\\t\\t\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget type() {\\n\\t\\t\\t\\treturn this._type;\\n\\t\\t}\\n\\t\\tset meshInstances(value) {\\n\\t\\t\\t\\tthis.destroyMeshInstances();\\n\\t\\t\\t\\tthis._meshInstances = value;\\n\\t\\t\\t\\tif (this._meshInstances) {\\n\\t\\t\\t\\t\\t\\tconst mi = this._meshInstances;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < mi.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!mi[i].node) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmi[i].node = this.entity;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tmi[i].castShadow = this._castShadows;\\n\\t\\t\\t\\t\\t\\t\\t\\tmi[i].receiveShadow = this._receiveShadows;\\n\\t\\t\\t\\t\\t\\t\\t\\tmi[i].renderStyle = this._renderStyle;\\n\\t\\t\\t\\t\\t\\t\\t\\tmi[i].setLightmapped(this._lightmapped);\\n\\t\\t\\t\\t\\t\\t\\t\\tmi[i].setCustomAabb(this._customAabb);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.addToLayers();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget meshInstances() {\\n\\t\\t\\t\\treturn this._meshInstances;\\n\\t\\t}\\n\\t\\tset lightmapped(value) {\\n\\t\\t\\t\\tif (value !== this._lightmapped) {\\n\\t\\t\\t\\t\\t\\tthis._lightmapped = value;\\n\\t\\t\\t\\t\\t\\tconst mi = this._meshInstances;\\n\\t\\t\\t\\t\\t\\tif (mi) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < mi.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmi[i].setLightmapped(value);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget lightmapped() {\\n\\t\\t\\t\\treturn this._lightmapped;\\n\\t\\t}\\n\\t\\tset castShadows(value) {\\n\\t\\t\\t\\tif (this._castShadows !== value) {\\n\\t\\t\\t\\t\\t\\tconst mi = this._meshInstances;\\n\\t\\t\\t\\t\\t\\tif (mi) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst layers = this.layers;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst scene = this.system.app.scene;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._castShadows && !value) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < layers.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst layer = scene.layers.getLayerById(this.layers[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayer.removeShadowCasters(mi);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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\\tfor(let i = 0; i < mi.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmi[i].castShadow = value;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this._castShadows && value) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < layers.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst layer = scene.layers.getLayerById(layers[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayer.addShadowCasters(mi);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tthis._castShadows = value;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget castShadows() {\\n\\t\\t\\t\\treturn this._castShadows;\\n\\t\\t}\\n\\t\\tset receiveShadows(value) {\\n\\t\\t\\t\\tif (this._receiveShadows !== value) {\\n\\t\\t\\t\\t\\t\\tthis._receiveShadows = value;\\n\\t\\t\\t\\t\\t\\tconst mi = this._meshInstances;\\n\\t\\t\\t\\t\\t\\tif (mi) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < mi.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmi[i].receiveShadow = value;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget receiveShadows() {\\n\\t\\t\\t\\treturn this._receiveShadows;\\n\\t\\t}\\n\\t\\tset castShadowsLightmap(value) {\\n\\t\\t\\t\\tthis._castShadowsLightmap = value;\\n\\t\\t}\\n\\t\\tget castShadowsLightmap() {\\n\\t\\t\\t\\treturn this._castShadowsLightmap;\\n\\t\\t}\\n\\t\\tset lightmapSizeMultiplier(value) {\\n\\t\\t\\t\\tthis._lightmapSizeMultiplier = value;\\n\\t\\t}\\n\\t\\tget lightmapSizeMultiplier() {\\n\\t\\t\\t\\treturn this._lightmapSizeMultiplier;\\n\\t\\t}\\n\\t\\tset layers(value) {\\n\\t\\t\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\t\\t\\tlet layer;\\n\\t\\t\\t\\tif (this._meshInstances) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._layers.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tlayer = layers.getLayerById(this._layers[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayer.removeMeshInstances(this._meshInstances);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._layers.length = 0;\\n\\t\\t\\t\\tfor(let i = 0; i < value.length; i++){\\n\\t\\t\\t\\t\\t\\tthis._layers[i] = value[i];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this.enabled || !this.entity.enabled || !this._meshInstances) return;\\n\\t\\t\\t\\tfor(let i = 0; i < this._layers.length; i++){\\n\\t\\t\\t\\t\\t\\tlayer = layers.getLayerById(this._layers[i]);\\n\\t\\t\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlayer.addMeshInstances(this._meshInstances);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget layers() {\\n\\t\\t\\t\\treturn this._layers;\\n\\t\\t}\\n\\t\\tset batchGroupId(value) {\\n\\t\\t\\t\\tif (this._batchGroupId !== value) {\\n\\t\\t\\t\\t\\t\\tif (this.entity.enabled && this._batchGroupId >= 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.system.app.batcher?.remove(BatchGroup.RENDER, this.batchGroupId, this.entity);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.entity.enabled && value >= 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.system.app.batcher?.insert(BatchGroup.RENDER, value, this.entity);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (value < 0 && this._batchGroupId >= 0 && this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.addToLayers();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._batchGroupId = value;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget batchGroupId() {\\n\\t\\t\\t\\treturn this._batchGroupId;\\n\\t\\t}\\n\\t\\tset material(value) {\\n\\t\\t\\t\\tif (this._material !== value) {\\n\\t\\t\\t\\t\\t\\tthis._material = value;\\n\\t\\t\\t\\t\\t\\tif (this._meshInstances && this._type !== 'asset') {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._meshInstances[i].material = value;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget material() {\\n\\t\\t\\t\\treturn this._material;\\n\\t\\t}\\n\\t\\tset materialAssets(value = []) {\\n\\t\\t\\t\\tif (this._materialReferences.length > value.length) {\\n\\t\\t\\t\\t\\t\\tfor(let i = value.length; i < this._materialReferences.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._materialReferences[i].id = null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._materialReferences.length = value.length;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < value.length; i++){\\n\\t\\t\\t\\t\\t\\tif (!this._materialReferences[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._materialReferences.push(new AssetReference(i, this, this.system.app.assets, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tadd: this._onMaterialAdded,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tload: this._onMaterialLoad,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tremove: this._onMaterialRemove,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tunload: this._onMaterialUnload\\n\\t\\t\\t\\t\\t\\t\\t\\t}, this));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (value[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst id = value[i] instanceof Asset ? value[i].id : value[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._materialReferences[i].id !== id) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._materialReferences[i].id = id;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._materialReferences[i].asset) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._onMaterialAdded(i, this, this._materialReferences[i].asset);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._materialReferences[i].id = null;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._meshInstances[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._meshInstances[i].material = this.system.defaultMaterial;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget materialAssets() {\\n\\t\\t\\t\\treturn this._materialReferences.map((ref)=>{\\n\\t\\t\\t\\t\\t\\treturn ref.id;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tset asset(value) {\\n\\t\\t\\t\\tconst id = value instanceof Asset ? value.id : value;\\n\\t\\t\\t\\tif (this._assetReference.id === id) return;\\n\\t\\t\\t\\tif (this._assetReference.asset && this._assetReference.asset.resource) {\\n\\t\\t\\t\\t\\t\\tthis._onRenderAssetRemove();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._assetReference.id = id;\\n\\t\\t\\t\\tif (this._assetReference.asset) {\\n\\t\\t\\t\\t\\t\\tthis._onRenderAssetAdded();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget asset() {\\n\\t\\t\\t\\treturn this._assetReference.id;\\n\\t\\t}\\n\\t\\tassignAsset(asset) {\\n\\t\\t\\t\\tconst id = asset instanceof Asset ? asset.id : asset;\\n\\t\\t\\t\\tthis._assetReference.id = id;\\n\\t\\t}\\n\\t\\tset rootBone(value) {\\n\\t\\t\\t\\tif (this._rootBone !== value) {\\n\\t\\t\\t\\t\\t\\tconst isString = typeof value === 'string';\\n\\t\\t\\t\\t\\t\\tif (this._rootBone && isString && this._rootBone.getGuid() === value) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this._rootBone) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._clearSkinInstances();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (value instanceof GraphNode) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._rootBone = value;\\n\\t\\t\\t\\t\\t\\t} else if (isString) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._rootBone = this.system.app.getEntityFromIndex(value) || null;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this._rootBone) ;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._rootBone = null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this._rootBone) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._cloneSkinInstances();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget rootBone() {\\n\\t\\t\\t\\treturn this._rootBone;\\n\\t\\t}\\n\\t\\tdestroyMeshInstances() {\\n\\t\\t\\t\\tconst meshInstances = this._meshInstances;\\n\\t\\t\\t\\tif (meshInstances) {\\n\\t\\t\\t\\t\\t\\tthis.removeFromLayers();\\n\\t\\t\\t\\t\\t\\tthis._clearSkinInstances();\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tmeshInstances[i].destroy();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._meshInstances.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\taddToLayers() {\\n\\t\\t\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\t\\t\\tfor(let i = 0; i < this._layers.length; i++){\\n\\t\\t\\t\\t\\t\\tconst layer = layers.getLayerById(this._layers[i]);\\n\\t\\t\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlayer.addMeshInstances(this._meshInstances);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tremoveFromLayers() {\\n\\t\\t\\t\\tif (this._meshInstances && this._meshInstances.length) {\\n\\t\\t\\t\\t\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._layers.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst layer = layers.getLayerById(this._layers[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayer.removeMeshInstances(this._meshInstances);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonRemoveChild() {\\n\\t\\t\\t\\tthis.removeFromLayers();\\n\\t\\t}\\n\\t\\tonInsertChild() {\\n\\t\\t\\t\\tif (this._meshInstances && this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\tthis.addToLayers();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonRemove() {\\n\\t\\t\\t\\tthis.destroyMeshInstances();\\n\\t\\t\\t\\tthis.asset = null;\\n\\t\\t\\t\\tthis.materialAsset = null;\\n\\t\\t\\t\\tthis._assetReference.id = null;\\n\\t\\t\\t\\tfor(let i = 0; i < this._materialReferences.length; i++){\\n\\t\\t\\t\\t\\t\\tthis._materialReferences[i].id = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.entity.off('remove', this.onRemoveChild, this);\\n\\t\\t\\t\\tthis.entity.off('insert', this.onInsertChild, this);\\n\\t\\t}\\n\\t\\tonLayersChanged(oldComp, newComp) {\\n\\t\\t\\t\\tthis.addToLayers();\\n\\t\\t\\t\\toldComp.off('add', this.onLayerAdded, this);\\n\\t\\t\\t\\toldComp.off('remove', this.onLayerRemoved, this);\\n\\t\\t\\t\\tnewComp.on('add', this.onLayerAdded, this);\\n\\t\\t\\t\\tnewComp.on('remove', this.onLayerRemoved, this);\\n\\t\\t}\\n\\t\\tonLayerAdded(layer) {\\n\\t\\t\\t\\tconst index = this.layers.indexOf(layer.id);\\n\\t\\t\\t\\tif (index < 0) return;\\n\\t\\t\\t\\tlayer.addMeshInstances(this._meshInstances);\\n\\t\\t}\\n\\t\\tonLayerRemoved(layer) {\\n\\t\\t\\t\\tconst index = this.layers.indexOf(layer.id);\\n\\t\\t\\t\\tif (index < 0) return;\\n\\t\\t\\t\\tlayer.removeMeshInstances(this._meshInstances);\\n\\t\\t}\\n\\t\\tonEnable() {\\n\\t\\t\\t\\tconst app = this.system.app;\\n\\t\\t\\t\\tconst scene = app.scene;\\n\\t\\t\\t\\tconst layers = scene.layers;\\n\\t\\t\\t\\tif (this._rootBone) {\\n\\t\\t\\t\\t\\t\\tthis._cloneSkinInstances();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._evtLayersChanged = scene.on('set:layers', this.onLayersChanged, this);\\n\\t\\t\\t\\tif (layers) {\\n\\t\\t\\t\\t\\t\\tthis._evtLayerAdded = layers.on('add', this.onLayerAdded, this);\\n\\t\\t\\t\\t\\t\\tthis._evtLayerRemoved = layers.on('remove', this.onLayerRemoved, this);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst isAsset = this._type === 'asset';\\n\\t\\t\\t\\tif (this._meshInstances && this._meshInstances.length) {\\n\\t\\t\\t\\t\\t\\tthis.addToLayers();\\n\\t\\t\\t\\t} else if (isAsset && this.asset) {\\n\\t\\t\\t\\t\\t\\tthis._onRenderAssetAdded();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < this._materialReferences.length; i++){\\n\\t\\t\\t\\t\\t\\tif (this._materialReferences[i].asset) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.system.app.assets.load(this._materialReferences[i].asset);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._batchGroupId >= 0) {\\n\\t\\t\\t\\t\\t\\tapp.batcher?.insert(BatchGroup.RENDER, this.batchGroupId, this.entity);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonDisable() {\\n\\t\\t\\t\\tconst app = this.system.app;\\n\\t\\t\\t\\tconst scene = app.scene;\\n\\t\\t\\t\\tconst layers = scene.layers;\\n\\t\\t\\t\\tthis._evtLayersChanged?.off();\\n\\t\\t\\t\\tthis._evtLayersChanged = null;\\n\\t\\t\\t\\tif (this._rootBone) {\\n\\t\\t\\t\\t\\t\\tthis._clearSkinInstances();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (layers) {\\n\\t\\t\\t\\t\\t\\tthis._evtLayerAdded?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtLayerAdded = null;\\n\\t\\t\\t\\t\\t\\tthis._evtLayerRemoved?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtLayerRemoved = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._batchGroupId >= 0) {\\n\\t\\t\\t\\t\\t\\tapp.batcher?.remove(BatchGroup.RENDER, this.batchGroupId, this.entity);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.removeFromLayers();\\n\\t\\t}\\n\\t\\thide() {\\n\\t\\t\\t\\tif (this._meshInstances) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._meshInstances[i].visible = false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tshow() {\\n\\t\\t\\t\\tif (this._meshInstances) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._meshInstances[i].visible = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onRenderAssetAdded() {\\n\\t\\t\\t\\tif (!this._assetReference.asset) return;\\n\\t\\t\\t\\tif (this._assetReference.asset.resource) {\\n\\t\\t\\t\\t\\t\\tthis._onRenderAssetLoad();\\n\\t\\t\\t\\t} else if (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\tthis.system.app.assets.load(this._assetReference.asset);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onRenderAssetLoad() {\\n\\t\\t\\t\\tthis.destroyMeshInstances();\\n\\t\\t\\t\\tif (this._assetReference.asset) {\\n\\t\\t\\t\\t\\t\\tconst render = this._assetReference.asset.resource;\\n\\t\\t\\t\\t\\t\\tthis._evtSetMeshes?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtSetMeshes = render.on('set:meshes', this._onSetMeshes, this);\\n\\t\\t\\t\\t\\t\\tif (render.meshes) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._onSetMeshes(render.meshes);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onSetMeshes(meshes) {\\n\\t\\t\\t\\tthis._cloneMeshes(meshes);\\n\\t\\t}\\n\\t\\t_clearSkinInstances() {\\n\\t\\t\\t\\tfor(let i = 0; i < this._meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\tconst meshInstance = this._meshInstances[i];\\n\\t\\t\\t\\t\\t\\tSkinInstanceCache.removeCachedSkinInstance(meshInstance.skinInstance);\\n\\t\\t\\t\\t\\t\\tmeshInstance.skinInstance = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_cloneSkinInstances() {\\n\\t\\t\\t\\tif (this._meshInstances.length && this._rootBone instanceof GraphNode) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._meshInstances.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst meshInstance = this._meshInstances[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst mesh = meshInstance.mesh;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (mesh.skin && !meshInstance.skinInstance) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmeshInstance.skinInstance = SkinInstanceCache.createCachedSkinInstance(mesh.skin, this._rootBone, this.entity);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_cloneMeshes(meshes) {\\n\\t\\t\\t\\tif (meshes && meshes.length) {\\n\\t\\t\\t\\t\\t\\tconst meshInstances = [];\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < meshes.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst mesh = meshes[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst material = this._materialReferences[i] && this._materialReferences[i].asset && this._materialReferences[i].asset.resource;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst meshInst = new MeshInstance(mesh, material || this.system.defaultMaterial, this.entity);\\n\\t\\t\\t\\t\\t\\t\\t\\tmeshInstances.push(meshInst);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (mesh.morph) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmeshInst.morphInstance = new MorphInstance(mesh.morph);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.meshInstances = meshInstances;\\n\\t\\t\\t\\t\\t\\tthis._cloneSkinInstances();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onRenderAssetUnload() {\\n\\t\\t\\t\\tif (this._type === 'asset') {\\n\\t\\t\\t\\t\\t\\tthis.destroyMeshInstances();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onRenderAssetRemove() {\\n\\t\\t\\t\\tthis._evtSetMeshes?.off();\\n\\t\\t\\t\\tthis._evtSetMeshes = null;\\n\\t\\t\\t\\tthis._onRenderAssetUnload();\\n\\t\\t}\\n\\t\\t_onMaterialAdded(index, component, asset) {\\n\\t\\t\\t\\tif (asset.resource) {\\n\\t\\t\\t\\t\\t\\tthis._onMaterialLoad(index, component, asset);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.system.app.assets.load(asset);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_updateMainMaterial(index, material) {\\n\\t\\t\\t\\tif (index === 0) {\\n\\t\\t\\t\\t\\t\\tthis.material = material;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onMaterialLoad(index, component, asset) {\\n\\t\\t\\t\\tif (this._meshInstances[index]) {\\n\\t\\t\\t\\t\\t\\tthis._meshInstances[index].material = asset.resource;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._updateMainMaterial(index, asset.resource);\\n\\t\\t}\\n\\t\\t_onMaterialRemove(index, component, asset) {\\n\\t\\t\\t\\tif (this._meshInstances[index]) {\\n\\t\\t\\t\\t\\t\\tthis._meshInstances[index].material = this.system.defaultMaterial;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._updateMainMaterial(index, this.system.defaultMaterial);\\n\\t\\t}\\n\\t\\t_onMaterialUnload(index, component, asset) {\\n\\t\\t\\t\\tif (this._meshInstances[index]) {\\n\\t\\t\\t\\t\\t\\tthis._meshInstances[index].material = this.system.defaultMaterial;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._updateMainMaterial(index, this.system.defaultMaterial);\\n\\t\\t}\\n\\t\\tresolveDuplicatedEntityReferenceProperties(oldRender, duplicatedIdsMap) {\\n\\t\\t\\t\\tif (oldRender.rootBone) {\\n\\t\\t\\t\\t\\t\\tthis.rootBone = duplicatedIdsMap[oldRender.rootBone.getGuid()];\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(system, entity){\\n\\t\\t\\t\\tsuper(system, entity), this._type = 'asset', this._castShadows = true, this._receiveShadows = true, this._castShadowsLightmap = true, this._lightmapped = false, this._lightmapSizeMultiplier = 1, this.isStatic = false, this._batchGroupId = -1, this._layers = [\\n\\t\\t\\t\\t\\t\\tLAYERID_WORLD\\n\\t\\t\\t\\t], this._renderStyle = RENDERSTYLE_SOLID, this._meshInstances = [], this._customAabb = null, this._area = null, this._materialReferences = [], this._rootBone = null, this._evtLayersChanged = null, this._evtLayerAdded = null, this._evtLayerRemoved = null, this._evtSetMeshes = null;\\n\\t\\t\\t\\tthis._assetReference = new AssetReference('asset', this, system.app.assets, {\\n\\t\\t\\t\\t\\t\\tadd: this._onRenderAssetAdded,\\n\\t\\t\\t\\t\\t\\tload: this._onRenderAssetLoad,\\n\\t\\t\\t\\t\\t\\tremove: this._onRenderAssetRemove,\\n\\t\\t\\t\\t\\t\\tunload: this._onRenderAssetUnload\\n\\t\\t\\t\\t}, this);\\n\\t\\t\\t\\tthis._material = system.defaultMaterial;\\n\\t\\t\\t\\tentity.on('remove', this.onRemoveChild, this);\\n\\t\\t\\t\\tentity.on('removehierarchy', this.onRemoveChild, this);\\n\\t\\t\\t\\tentity.on('insert', this.onInsertChild, this);\\n\\t\\t\\t\\tentity.on('inserthierarchy', this.onInsertChild, this);\\n\\t\\t}\\n}\\n\\nclass RenderComponentData {\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.enabled = true;\\n\\t\\t}\\n}\\n\\nconst _schema$2 = [\\n\\t\\t'enabled'\\n];\\nconst _properties$1 = [\\n\\t\\t'material',\\n\\t\\t'meshInstances',\\n\\t\\t'asset',\\n\\t\\t'materialAssets',\\n\\t\\t'castShadows',\\n\\t\\t'receiveShadows',\\n\\t\\t'castShadowsLightmap',\\n\\t\\t'lightmapped',\\n\\t\\t'lightmapSizeMultiplier',\\n\\t\\t'renderStyle',\\n\\t\\t'type',\\n\\t\\t'layers',\\n\\t\\t'isStatic',\\n\\t\\t'batchGroupId',\\n\\t\\t'rootBone'\\n];\\nclass RenderComponentSystem extends ComponentSystem {\\n\\t\\tinitializeComponentData(component, _data, properties) {\\n\\t\\t\\t\\tif (_data.batchGroupId === null || _data.batchGroupId === undefined) {\\n\\t\\t\\t\\t\\t\\t_data.batchGroupId = -1;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (_data.layers && _data.layers.length) {\\n\\t\\t\\t\\t\\t\\t_data.layers = _data.layers.slice(0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < _properties$1.length; i++){\\n\\t\\t\\t\\t\\t\\tif (_data.hasOwnProperty(_properties$1[i])) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponent[_properties$1[i]] = _data[_properties$1[i]];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (_data.aabbCenter && _data.aabbHalfExtents) {\\n\\t\\t\\t\\t\\t\\tcomponent.customAabb = new BoundingBox(new Vec3(_data.aabbCenter), new Vec3(_data.aabbHalfExtents));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tsuper.initializeComponentData(component, _data, _schema$2);\\n\\t\\t}\\n\\t\\tcloneComponent(entity, clone) {\\n\\t\\t\\t\\tconst data = {};\\n\\t\\t\\t\\tfor(let i = 0; i < _properties$1.length; i++){\\n\\t\\t\\t\\t\\t\\tdata[_properties$1[i]] = entity.render[_properties$1[i]];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdata.enabled = entity.render.enabled;\\n\\t\\t\\t\\tdelete data.meshInstances;\\n\\t\\t\\t\\tconst component = this.addComponent(clone, data);\\n\\t\\t\\t\\tconst srcMeshInstances = entity.render.meshInstances;\\n\\t\\t\\t\\tconst meshes = srcMeshInstances.map((mi)=>mi.mesh);\\n\\t\\t\\t\\tcomponent._onSetMeshes(meshes);\\n\\t\\t\\t\\tfor(let m = 0; m < srcMeshInstances.length; m++){\\n\\t\\t\\t\\t\\t\\tcomponent.meshInstances[m].material = srcMeshInstances[m].material;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (entity.render.customAabb) {\\n\\t\\t\\t\\t\\t\\tcomponent.customAabb = entity.render.customAabb.clone();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn component;\\n\\t\\t}\\n\\t\\tonRemove(entity, component) {\\n\\t\\t\\t\\tcomponent.onRemove();\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tsuper(app);\\n\\t\\t\\t\\tthis.id = 'render';\\n\\t\\t\\t\\tthis.ComponentType = RenderComponent;\\n\\t\\t\\t\\tthis.DataType = RenderComponentData;\\n\\t\\t\\t\\tthis.schema = _schema$2;\\n\\t\\t\\t\\tthis.defaultMaterial = getDefaultMaterial(app.graphicsDevice);\\n\\t\\t\\t\\tthis.on('beforeremove', this.onRemove, this);\\n\\t\\t}\\n}\\nComponent._buildAccessors(RenderComponent.prototype, _schema$2);\\n\\nclass PostEffectEntry {\\n\\t\\tconstructor(effect, inputTarget){\\n\\t\\t\\t\\tthis.effect = effect;\\n\\t\\t\\t\\tthis.inputTarget = inputTarget;\\n\\t\\t\\t\\tthis.outputTarget = null;\\n\\t\\t\\t\\tthis.name = effect.constructor.name;\\n\\t\\t}\\n}\\nclass PostEffectQueue {\\n\\t\\t_allocateColorBuffer(format, name) {\\n\\t\\t\\t\\tconst rect = this.camera.rect;\\n\\t\\t\\t\\tconst renderTarget = this.destinationRenderTarget;\\n\\t\\t\\t\\tconst device = this.app.graphicsDevice;\\n\\t\\t\\t\\tconst width = Math.floor(rect.z * (renderTarget?.width ?? device.width));\\n\\t\\t\\t\\tconst height = Math.floor(rect.w * (renderTarget?.height ?? device.height));\\n\\t\\t\\t\\tconst colorBuffer = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\twidth: width,\\n\\t\\t\\t\\t\\t\\theight: height,\\n\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn colorBuffer;\\n\\t\\t}\\n\\t\\t_createOffscreenTarget(useDepth, hdr) {\\n\\t\\t\\t\\tconst device = this.app.graphicsDevice;\\n\\t\\t\\t\\tconst outputRt = this.destinationRenderTarget ?? device.backBuffer;\\n\\t\\t\\t\\tconst srgb = outputRt.isColorBufferSrgb(0);\\n\\t\\t\\t\\tconst format = (hdr && device.getRenderableHdrFormat([\\n\\t\\t\\t\\t\\t\\tPIXELFORMAT_RGBA16F,\\n\\t\\t\\t\\t\\t\\tPIXELFORMAT_RGBA32F\\n\\t\\t\\t\\t], true)) ?? (srgb ? PIXELFORMAT_SRGBA8 : PIXELFORMAT_RGBA8);\\n\\t\\t\\t\\tconst name = `${this.camera.entity.name}-posteffect-${this.effects.length}`;\\n\\t\\t\\t\\tconst colorBuffer = this._allocateColorBuffer(format, name);\\n\\t\\t\\t\\treturn new RenderTarget({\\n\\t\\t\\t\\t\\t\\tcolorBuffer: colorBuffer,\\n\\t\\t\\t\\t\\t\\tdepth: useDepth,\\n\\t\\t\\t\\t\\t\\tstencil: useDepth && this.app.graphicsDevice.supportsStencil,\\n\\t\\t\\t\\t\\t\\tsamples: useDepth ? device.samples : 1\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\t_resizeOffscreenTarget(rt) {\\n\\t\\t\\t\\tconst format = rt.colorBuffer.format;\\n\\t\\t\\t\\tconst name = rt.colorBuffer.name;\\n\\t\\t\\t\\trt.destroyFrameBuffers();\\n\\t\\t\\t\\trt.destroyTextureBuffers();\\n\\t\\t\\t\\trt._colorBuffer = this._allocateColorBuffer(format, name);\\n\\t\\t\\t\\trt._colorBuffers = [\\n\\t\\t\\t\\t\\t\\trt._colorBuffer\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\trt.evaluateDimensions();\\n\\t\\t}\\n\\t\\t_destroyOffscreenTarget(rt) {\\n\\t\\t\\t\\trt.destroyTextureBuffers();\\n\\t\\t\\t\\trt.destroy();\\n\\t\\t}\\n\\t\\taddEffect(effect) {\\n\\t\\t\\t\\tconst effects = this.effects;\\n\\t\\t\\t\\tconst isFirstEffect = effects.length === 0;\\n\\t\\t\\t\\tconst inputTarget = this._createOffscreenTarget(isFirstEffect, effect.hdr);\\n\\t\\t\\t\\tconst newEntry = new PostEffectEntry(effect, inputTarget);\\n\\t\\t\\t\\teffects.push(newEntry);\\n\\t\\t\\t\\tthis._sourceTarget = newEntry.inputTarget;\\n\\t\\t\\t\\tif (effects.length > 1) {\\n\\t\\t\\t\\t\\t\\teffects[effects.length - 2].outputTarget = newEntry.inputTarget;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._newPostEffect = effect;\\n\\t\\t\\t\\tif (effect.needsDepthBuffer) {\\n\\t\\t\\t\\t\\t\\tthis._requestDepthMap();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.enable();\\n\\t\\t\\t\\tthis._newPostEffect = undefined;\\n\\t\\t}\\n\\t\\tremoveEffect(effect) {\\n\\t\\t\\t\\tlet index = -1;\\n\\t\\t\\t\\tfor(let i = 0, len = this.effects.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tif (this.effects[i].effect === effect) {\\n\\t\\t\\t\\t\\t\\t\\t\\tindex = i;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (index >= 0) {\\n\\t\\t\\t\\t\\t\\tif (index > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.effects[index - 1].outputTarget = index + 1 < this.effects.length ? this.effects[index + 1].inputTarget : null;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.effects.length > 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!this.effects[1].inputTarget._depth) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._destroyOffscreenTarget(this.effects[1].inputTarget);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.effects[1].inputTarget = this._createOffscreenTarget(true, this.effects[1].hdr);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._sourceTarget = this.effects[1].inputTarget;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.camera.renderTarget = this.effects[1].inputTarget;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._destroyOffscreenTarget(this.effects[index].inputTarget);\\n\\t\\t\\t\\t\\t\\tthis.effects.splice(index, 1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.enabled) {\\n\\t\\t\\t\\t\\t\\tif (effect.needsDepthBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._releaseDepthMap();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.effects.length === 0) {\\n\\t\\t\\t\\t\\t\\tthis.disable();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_requestDepthMaps() {\\n\\t\\t\\t\\tfor(let i = 0, len = this.effects.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst effect = this.effects[i].effect;\\n\\t\\t\\t\\t\\t\\tif (this._newPostEffect === effect) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (effect.needsDepthBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._requestDepthMap();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_releaseDepthMaps() {\\n\\t\\t\\t\\tfor(let i = 0, len = this.effects.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst effect = this.effects[i].effect;\\n\\t\\t\\t\\t\\t\\tif (effect.needsDepthBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._releaseDepthMap();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_requestDepthMap() {\\n\\t\\t\\t\\tconst depthLayer = this.app.scene.layers.getLayerById(LAYERID_DEPTH);\\n\\t\\t\\t\\tif (depthLayer) {\\n\\t\\t\\t\\t\\t\\tdepthLayer.incrementCounter();\\n\\t\\t\\t\\t\\t\\tthis.camera.requestSceneDepthMap(true);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_releaseDepthMap() {\\n\\t\\t\\t\\tconst depthLayer = this.app.scene.layers.getLayerById(LAYERID_DEPTH);\\n\\t\\t\\t\\tif (depthLayer) {\\n\\t\\t\\t\\t\\t\\tdepthLayer.decrementCounter();\\n\\t\\t\\t\\t\\t\\tthis.camera.requestSceneDepthMap(false);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tfor(let i = 0, len = this.effects.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tthis.effects[i].inputTarget.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.effects.length = 0;\\n\\t\\t\\t\\tthis.disable();\\n\\t\\t}\\n\\t\\tenable() {\\n\\t\\t\\t\\tif (!this.enabled && this.effects.length) {\\n\\t\\t\\t\\t\\t\\tthis.enabled = true;\\n\\t\\t\\t\\t\\t\\tthis._requestDepthMaps();\\n\\t\\t\\t\\t\\t\\tthis.app.graphicsDevice.on('resizecanvas', this._onCanvasResized, this);\\n\\t\\t\\t\\t\\t\\tthis.destinationRenderTarget = this.camera.renderTarget;\\n\\t\\t\\t\\t\\t\\tthis.camera.renderTarget = this.effects[0].inputTarget;\\n\\t\\t\\t\\t\\t\\tthis.camera.onPostprocessing = ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet rect = null;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst len = this.effects.length;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (len) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < len; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst fx = this.effects[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet destTarget = fx.outputTarget;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (i === len - 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trect = this.camera.rect;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this.destinationRenderTarget) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdestTarget = this.destinationRenderTarget;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfx.effect.render(fx.inputTarget, destTarget, rect);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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};\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdisable() {\\n\\t\\t\\t\\tif (this.enabled) {\\n\\t\\t\\t\\t\\t\\tthis.enabled = false;\\n\\t\\t\\t\\t\\t\\tthis.app.graphicsDevice.off('resizecanvas', this._onCanvasResized, this);\\n\\t\\t\\t\\t\\t\\tthis._releaseDepthMaps();\\n\\t\\t\\t\\t\\t\\tthis._destroyOffscreenTarget(this._sourceTarget);\\n\\t\\t\\t\\t\\t\\tthis.camera.renderTarget = this.destinationRenderTarget;\\n\\t\\t\\t\\t\\t\\tthis.camera.onPostprocessing = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onCanvasResized(width, height) {\\n\\t\\t\\t\\tconst rect = this.camera.rect;\\n\\t\\t\\t\\tconst renderTarget = this.destinationRenderTarget;\\n\\t\\t\\t\\twidth = renderTarget?.width ?? width;\\n\\t\\t\\t\\theight = renderTarget?.height ?? height;\\n\\t\\t\\t\\tthis.camera.camera.aspectRatio = width * rect.z / (height * rect.w);\\n\\t\\t\\t\\tthis.resizeRenderTargets();\\n\\t\\t}\\n\\t\\tresizeRenderTargets() {\\n\\t\\t\\t\\tconst device = this.app.graphicsDevice;\\n\\t\\t\\t\\tconst renderTarget = this.destinationRenderTarget;\\n\\t\\t\\t\\tconst width = renderTarget?.width ?? device.width;\\n\\t\\t\\t\\tconst height = renderTarget?.height ?? device.height;\\n\\t\\t\\t\\tconst rect = this.camera.rect;\\n\\t\\t\\t\\tconst desiredWidth = Math.floor(rect.z * width);\\n\\t\\t\\t\\tconst desiredHeight = Math.floor(rect.w * height);\\n\\t\\t\\t\\tconst effects = this.effects;\\n\\t\\t\\t\\tfor(let i = 0, len = effects.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst fx = effects[i];\\n\\t\\t\\t\\t\\t\\tif (fx.inputTarget.width !== desiredWidth || fx.inputTarget.height !== desiredHeight) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._resizeOffscreenTarget(fx.inputTarget);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonCameraRectChanged(name, oldValue, newValue) {\\n\\t\\t\\t\\tif (this.enabled) {\\n\\t\\t\\t\\t\\t\\tthis.resizeRenderTargets();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(app, camera){\\n\\t\\t\\t\\tthis.app = app;\\n\\t\\t\\t\\tthis.camera = camera;\\n\\t\\t\\t\\tthis.destinationRenderTarget = null;\\n\\t\\t\\t\\tthis.effects = [];\\n\\t\\t\\t\\tthis.enabled = false;\\n\\t\\t\\t\\tthis.depthTarget = null;\\n\\t\\t\\t\\tcamera.on('set:rect', this.onCameraRectChanged, this);\\n\\t\\t}\\n}\\n\\nclass CameraComponent extends Component {\\n\\t\\tsetShaderPass(name) {\\n\\t\\t\\t\\tconst shaderPass = ShaderPass.get(this.system.app.graphicsDevice);\\n\\t\\t\\t\\tconst shaderPassInfo = name ? shaderPass.allocate(name, {\\n\\t\\t\\t\\t\\t\\tisForward: true\\n\\t\\t\\t\\t}) : null;\\n\\t\\t\\t\\tthis._camera.shaderPassInfo = shaderPassInfo;\\n\\t\\t\\t\\treturn shaderPassInfo.index;\\n\\t\\t}\\n\\t\\tgetShaderPass() {\\n\\t\\t\\t\\treturn this._camera.shaderPassInfo?.name;\\n\\t\\t}\\n\\t\\tset renderPasses(passes) {\\n\\t\\t\\t\\tthis._camera.renderPasses = passes || [];\\n\\t\\t\\t\\tthis.dirtyLayerCompositionCameras();\\n\\t\\t\\t\\tthis.system.app.scene.updateShaders = true;\\n\\t\\t}\\n\\t\\tget renderPasses() {\\n\\t\\t\\t\\treturn this._camera.renderPasses;\\n\\t\\t}\\n\\t\\tget shaderParams() {\\n\\t\\t\\t\\treturn this._camera.shaderParams;\\n\\t\\t}\\n\\t\\tset gammaCorrection(value) {\\n\\t\\t\\t\\tthis.camera.shaderParams.gammaCorrection = value;\\n\\t\\t}\\n\\t\\tget gammaCorrection() {\\n\\t\\t\\t\\treturn this.camera.shaderParams.gammaCorrection;\\n\\t\\t}\\n\\t\\tset toneMapping(value) {\\n\\t\\t\\t\\tthis.camera.shaderParams.toneMapping = value;\\n\\t\\t}\\n\\t\\tget toneMapping() {\\n\\t\\t\\t\\treturn this.camera.shaderParams.toneMapping;\\n\\t\\t}\\n\\t\\tset fog(value) {\\n\\t\\t\\t\\tthis._camera.fogParams = value;\\n\\t\\t}\\n\\t\\tget fog() {\\n\\t\\t\\t\\treturn this._camera.fogParams;\\n\\t\\t}\\n\\t\\tset aperture(value) {\\n\\t\\t\\t\\tthis._camera.aperture = value;\\n\\t\\t}\\n\\t\\tget aperture() {\\n\\t\\t\\t\\treturn this._camera.aperture;\\n\\t\\t}\\n\\t\\tset aspectRatio(value) {\\n\\t\\t\\t\\tthis._camera.aspectRatio = value;\\n\\t\\t}\\n\\t\\tget aspectRatio() {\\n\\t\\t\\t\\treturn this._camera.aspectRatio;\\n\\t\\t}\\n\\t\\tset aspectRatioMode(value) {\\n\\t\\t\\t\\tthis._camera.aspectRatioMode = value;\\n\\t\\t}\\n\\t\\tget aspectRatioMode() {\\n\\t\\t\\t\\treturn this._camera.aspectRatioMode;\\n\\t\\t}\\n\\t\\tset calculateProjection(value) {\\n\\t\\t\\t\\tthis._camera.calculateProjection = value;\\n\\t\\t}\\n\\t\\tget calculateProjection() {\\n\\t\\t\\t\\treturn this._camera.calculateProjection;\\n\\t\\t}\\n\\t\\tset calculateTransform(value) {\\n\\t\\t\\t\\tthis._camera.calculateTransform = value;\\n\\t\\t}\\n\\t\\tget calculateTransform() {\\n\\t\\t\\t\\treturn this._camera.calculateTransform;\\n\\t\\t}\\n\\t\\tget camera() {\\n\\t\\t\\t\\treturn this._camera;\\n\\t\\t}\\n\\t\\tset clearColor(value) {\\n\\t\\t\\t\\tthis._camera.clearColor = value;\\n\\t\\t}\\n\\t\\tget clearColor() {\\n\\t\\t\\t\\treturn this._camera.clearColor;\\n\\t\\t}\\n\\t\\tset clearColorBuffer(value) {\\n\\t\\t\\t\\tthis._camera.clearColorBuffer = value;\\n\\t\\t\\t\\tthis.dirtyLayerCompositionCameras();\\n\\t\\t}\\n\\t\\tget clearColorBuffer() {\\n\\t\\t\\t\\treturn this._camera.clearColorBuffer;\\n\\t\\t}\\n\\t\\tset clearDepth(value) {\\n\\t\\t\\t\\tthis._camera.clearDepth = value;\\n\\t\\t}\\n\\t\\tget clearDepth() {\\n\\t\\t\\t\\treturn this._camera.clearDepth;\\n\\t\\t}\\n\\t\\tset clearDepthBuffer(value) {\\n\\t\\t\\t\\tthis._camera.clearDepthBuffer = value;\\n\\t\\t\\t\\tthis.dirtyLayerCompositionCameras();\\n\\t\\t}\\n\\t\\tget clearDepthBuffer() {\\n\\t\\t\\t\\treturn this._camera.clearDepthBuffer;\\n\\t\\t}\\n\\t\\tset clearStencilBuffer(value) {\\n\\t\\t\\t\\tthis._camera.clearStencilBuffer = value;\\n\\t\\t\\t\\tthis.dirtyLayerCompositionCameras();\\n\\t\\t}\\n\\t\\tget clearStencilBuffer() {\\n\\t\\t\\t\\treturn this._camera.clearStencilBuffer;\\n\\t\\t}\\n\\t\\tset cullFaces(value) {\\n\\t\\t\\t\\tthis._camera.cullFaces = value;\\n\\t\\t}\\n\\t\\tget cullFaces() {\\n\\t\\t\\t\\treturn this._camera.cullFaces;\\n\\t\\t}\\n\\t\\tset disablePostEffectsLayer(layer) {\\n\\t\\t\\t\\tthis._disablePostEffectsLayer = layer;\\n\\t\\t\\t\\tthis.dirtyLayerCompositionCameras();\\n\\t\\t}\\n\\t\\tget disablePostEffectsLayer() {\\n\\t\\t\\t\\treturn this._disablePostEffectsLayer;\\n\\t\\t}\\n\\t\\tset farClip(value) {\\n\\t\\t\\t\\tthis._camera.farClip = value;\\n\\t\\t}\\n\\t\\tget farClip() {\\n\\t\\t\\t\\treturn this._camera.farClip;\\n\\t\\t}\\n\\t\\tset flipFaces(value) {\\n\\t\\t\\t\\tthis._camera.flipFaces = value;\\n\\t\\t}\\n\\t\\tget flipFaces() {\\n\\t\\t\\t\\treturn this._camera.flipFaces;\\n\\t\\t}\\n\\t\\tset fov(value) {\\n\\t\\t\\t\\tthis._camera.fov = value;\\n\\t\\t}\\n\\t\\tget fov() {\\n\\t\\t\\t\\treturn this._camera.fov;\\n\\t\\t}\\n\\t\\tget frustum() {\\n\\t\\t\\t\\treturn this._camera.frustum;\\n\\t\\t}\\n\\t\\tset frustumCulling(value) {\\n\\t\\t\\t\\tthis._camera.frustumCulling = value;\\n\\t\\t}\\n\\t\\tget frustumCulling() {\\n\\t\\t\\t\\treturn this._camera.frustumCulling;\\n\\t\\t}\\n\\t\\tset horizontalFov(value) {\\n\\t\\t\\t\\tthis._camera.horizontalFov = value;\\n\\t\\t}\\n\\t\\tget horizontalFov() {\\n\\t\\t\\t\\treturn this._camera.horizontalFov;\\n\\t\\t}\\n\\t\\tset layers(newValue) {\\n\\t\\t\\t\\tconst oldLayers = this._camera.layers;\\n\\t\\t\\t\\tconst scene = this.system.app.scene;\\n\\t\\t\\t\\toldLayers.forEach((layerId)=>{\\n\\t\\t\\t\\t\\t\\tconst layer = scene.layers.getLayerById(layerId);\\n\\t\\t\\t\\t\\t\\tlayer?.removeCamera(this);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis._camera.layers = newValue;\\n\\t\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\tnewValue.forEach((layerId)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst layer = scene.layers.getLayerById(layerId);\\n\\t\\t\\t\\t\\t\\t\\t\\tlayer?.addCamera(this);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.fire('set:layers');\\n\\t\\t}\\n\\t\\tget layers() {\\n\\t\\t\\t\\treturn this._camera.layers;\\n\\t\\t}\\n\\t\\tget layersSet() {\\n\\t\\t\\t\\treturn this._camera.layersSet;\\n\\t\\t}\\n\\t\\tset jitter(value) {\\n\\t\\t\\t\\tthis._camera.jitter = value;\\n\\t\\t}\\n\\t\\tget jitter() {\\n\\t\\t\\t\\treturn this._camera.jitter;\\n\\t\\t}\\n\\t\\tset nearClip(value) {\\n\\t\\t\\t\\tthis._camera.nearClip = value;\\n\\t\\t}\\n\\t\\tget nearClip() {\\n\\t\\t\\t\\treturn this._camera.nearClip;\\n\\t\\t}\\n\\t\\tset orthoHeight(value) {\\n\\t\\t\\t\\tthis._camera.orthoHeight = value;\\n\\t\\t}\\n\\t\\tget orthoHeight() {\\n\\t\\t\\t\\treturn this._camera.orthoHeight;\\n\\t\\t}\\n\\t\\tget postEffects() {\\n\\t\\t\\t\\treturn this._postEffects;\\n\\t\\t}\\n\\t\\tget postEffectsEnabled() {\\n\\t\\t\\t\\treturn this._postEffects.enabled;\\n\\t\\t}\\n\\t\\tset priority(newValue) {\\n\\t\\t\\t\\tthis._priority = newValue;\\n\\t\\t\\t\\tthis.dirtyLayerCompositionCameras();\\n\\t\\t}\\n\\t\\tget priority() {\\n\\t\\t\\t\\treturn this._priority;\\n\\t\\t}\\n\\t\\tset projection(value) {\\n\\t\\t\\t\\tthis._camera.projection = value;\\n\\t\\t}\\n\\t\\tget projection() {\\n\\t\\t\\t\\treturn this._camera.projection;\\n\\t\\t}\\n\\t\\tget projectionMatrix() {\\n\\t\\t\\t\\treturn this._camera.projectionMatrix;\\n\\t\\t}\\n\\t\\tset rect(value) {\\n\\t\\t\\t\\tthis._camera.rect = value;\\n\\t\\t\\t\\tthis.fire('set:rect', this._camera.rect);\\n\\t\\t}\\n\\t\\tget rect() {\\n\\t\\t\\t\\treturn this._camera.rect;\\n\\t\\t}\\n\\t\\tset renderSceneColorMap(value) {\\n\\t\\t\\t\\tif (value && !this._sceneColorMapRequested) {\\n\\t\\t\\t\\t\\t\\tthis.requestSceneColorMap(true);\\n\\t\\t\\t\\t\\t\\tthis._sceneColorMapRequested = true;\\n\\t\\t\\t\\t} else if (this._sceneColorMapRequested) {\\n\\t\\t\\t\\t\\t\\tthis.requestSceneColorMap(false);\\n\\t\\t\\t\\t\\t\\tthis._sceneColorMapRequested = false;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget renderSceneColorMap() {\\n\\t\\t\\t\\treturn this._renderSceneColorMap > 0;\\n\\t\\t}\\n\\t\\tset renderSceneDepthMap(value) {\\n\\t\\t\\t\\tif (value && !this._sceneDepthMapRequested) {\\n\\t\\t\\t\\t\\t\\tthis.requestSceneDepthMap(true);\\n\\t\\t\\t\\t\\t\\tthis._sceneDepthMapRequested = true;\\n\\t\\t\\t\\t} else if (this._sceneDepthMapRequested) {\\n\\t\\t\\t\\t\\t\\tthis.requestSceneDepthMap(false);\\n\\t\\t\\t\\t\\t\\tthis._sceneDepthMapRequested = false;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget renderSceneDepthMap() {\\n\\t\\t\\t\\treturn this._renderSceneDepthMap > 0;\\n\\t\\t}\\n\\t\\tset renderTarget(value) {\\n\\t\\t\\t\\tthis._camera.renderTarget = value;\\n\\t\\t\\t\\tthis.dirtyLayerCompositionCameras();\\n\\t\\t}\\n\\t\\tget renderTarget() {\\n\\t\\t\\t\\treturn this._camera.renderTarget;\\n\\t\\t}\\n\\t\\tset scissorRect(value) {\\n\\t\\t\\t\\tthis._camera.scissorRect = value;\\n\\t\\t}\\n\\t\\tget scissorRect() {\\n\\t\\t\\t\\treturn this._camera.scissorRect;\\n\\t\\t}\\n\\t\\tset sensitivity(value) {\\n\\t\\t\\t\\tthis._camera.sensitivity = value;\\n\\t\\t}\\n\\t\\tget sensitivity() {\\n\\t\\t\\t\\treturn this._camera.sensitivity;\\n\\t\\t}\\n\\t\\tset shutter(value) {\\n\\t\\t\\t\\tthis._camera.shutter = value;\\n\\t\\t}\\n\\t\\tget shutter() {\\n\\t\\t\\t\\treturn this._camera.shutter;\\n\\t\\t}\\n\\t\\tget viewMatrix() {\\n\\t\\t\\t\\treturn this._camera.viewMatrix;\\n\\t\\t}\\n\\t\\t_enableDepthLayer(value) {\\n\\t\\t\\t\\tconst hasDepthLayer = this.layers.find((layerId)=>layerId === LAYERID_DEPTH);\\n\\t\\t\\t\\tif (hasDepthLayer) {\\n\\t\\t\\t\\t\\t\\tconst depthLayer = this.system.app.scene.layers.getLayerById(LAYERID_DEPTH);\\n\\t\\t\\t\\t\\t\\tif (value) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthLayer?.incrementCounter();\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tdepthLayer?.decrementCounter();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else if (value) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\trequestSceneColorMap(enabled) {\\n\\t\\t\\t\\tthis._renderSceneColorMap += enabled ? 1 : -1;\\n\\t\\t\\t\\tthis._enableDepthLayer(enabled);\\n\\t\\t\\t\\tthis.camera._enableRenderPassColorGrab(this.system.app.graphicsDevice, this.renderSceneColorMap);\\n\\t\\t\\t\\tthis.system.app.scene.layers.markDirty();\\n\\t\\t}\\n\\t\\trequestSceneDepthMap(enabled) {\\n\\t\\t\\t\\tthis._renderSceneDepthMap += enabled ? 1 : -1;\\n\\t\\t\\t\\tthis._enableDepthLayer(enabled);\\n\\t\\t\\t\\tthis.camera._enableRenderPassDepthGrab(this.system.app.graphicsDevice, this.system.app.renderer, this.renderSceneDepthMap);\\n\\t\\t\\t\\tthis.system.app.scene.layers.markDirty();\\n\\t\\t}\\n\\t\\tdirtyLayerCompositionCameras() {\\n\\t\\t\\t\\tconst layerComp = this.system.app.scene.layers;\\n\\t\\t\\t\\tlayerComp._dirty = true;\\n\\t\\t}\\n\\t\\tscreenToWorld(screenx, screeny, cameraz, worldCoord) {\\n\\t\\t\\t\\tconst device = this.system.app.graphicsDevice;\\n\\t\\t\\t\\tconst { width, height } = device.clientRect;\\n\\t\\t\\t\\treturn this._camera.screenToWorld(screenx, screeny, cameraz, width, height, worldCoord);\\n\\t\\t}\\n\\t\\tworldToScreen(worldCoord, screenCoord) {\\n\\t\\t\\t\\tconst device = this.system.app.graphicsDevice;\\n\\t\\t\\t\\tconst { width, height } = device.clientRect;\\n\\t\\t\\t\\treturn this._camera.worldToScreen(worldCoord, width, height, screenCoord);\\n\\t\\t}\\n\\t\\tonAppPrerender() {\\n\\t\\t\\t\\tthis._camera._viewMatDirty = true;\\n\\t\\t\\t\\tthis._camera._viewProjMatDirty = true;\\n\\t\\t}\\n\\t\\taddCameraToLayers() {\\n\\t\\t\\t\\tconst layers = this.layers;\\n\\t\\t\\t\\tfor(let i = 0; i < layers.length; i++){\\n\\t\\t\\t\\t\\t\\tconst layer = this.system.app.scene.layers.getLayerById(layers[i]);\\n\\t\\t\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlayer.addCamera(this);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tremoveCameraFromLayers() {\\n\\t\\t\\t\\tconst layers = this.layers;\\n\\t\\t\\t\\tfor(let i = 0; i < layers.length; i++){\\n\\t\\t\\t\\t\\t\\tconst layer = this.system.app.scene.layers.getLayerById(layers[i]);\\n\\t\\t\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlayer.removeCamera(this);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonLayersChanged(oldComp, newComp) {\\n\\t\\t\\t\\tthis.addCameraToLayers();\\n\\t\\t\\t\\toldComp.off('add', this.onLayerAdded, this);\\n\\t\\t\\t\\toldComp.off('remove', this.onLayerRemoved, this);\\n\\t\\t\\t\\tnewComp.on('add', this.onLayerAdded, this);\\n\\t\\t\\t\\tnewComp.on('remove', this.onLayerRemoved, this);\\n\\t\\t}\\n\\t\\tonLayerAdded(layer) {\\n\\t\\t\\t\\tconst index = this.layers.indexOf(layer.id);\\n\\t\\t\\t\\tif (index < 0) return;\\n\\t\\t\\t\\tlayer.addCamera(this);\\n\\t\\t}\\n\\t\\tonLayerRemoved(layer) {\\n\\t\\t\\t\\tconst index = this.layers.indexOf(layer.id);\\n\\t\\t\\t\\tif (index < 0) return;\\n\\t\\t\\t\\tlayer.removeCamera(this);\\n\\t\\t}\\n\\t\\tonEnable() {\\n\\t\\t\\t\\tconst scene = this.system.app.scene;\\n\\t\\t\\t\\tconst layers = scene.layers;\\n\\t\\t\\t\\tthis.system.addCamera(this);\\n\\t\\t\\t\\tthis._evtLayersChanged?.off();\\n\\t\\t\\t\\tthis._evtLayersChanged = scene.on('set:layers', this.onLayersChanged, this);\\n\\t\\t\\t\\tif (layers) {\\n\\t\\t\\t\\t\\t\\tthis._evtLayerAdded?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtLayerAdded = layers.on('add', this.onLayerAdded, this);\\n\\t\\t\\t\\t\\t\\tthis._evtLayerRemoved?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtLayerRemoved = layers.on('remove', this.onLayerRemoved, this);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\tthis.addCameraToLayers();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.postEffects.enable();\\n\\t\\t}\\n\\t\\tonDisable() {\\n\\t\\t\\t\\tconst scene = this.system.app.scene;\\n\\t\\t\\t\\tconst layers = scene.layers;\\n\\t\\t\\t\\tthis.postEffects.disable();\\n\\t\\t\\t\\tthis.removeCameraFromLayers();\\n\\t\\t\\t\\tthis._evtLayersChanged?.off();\\n\\t\\t\\t\\tthis._evtLayersChanged = null;\\n\\t\\t\\t\\tif (layers) {\\n\\t\\t\\t\\t\\t\\tthis._evtLayerAdded?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtLayerAdded = null;\\n\\t\\t\\t\\t\\t\\tthis._evtLayerRemoved?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtLayerRemoved = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.system.removeCamera(this);\\n\\t\\t}\\n\\t\\tonRemove() {\\n\\t\\t\\t\\tthis.onDisable();\\n\\t\\t\\t\\tthis.off();\\n\\t\\t\\t\\tthis.camera.destroy();\\n\\t\\t}\\n\\t\\tcalculateAspectRatio(rt) {\\n\\t\\t\\t\\tconst device = this.system.app.graphicsDevice;\\n\\t\\t\\t\\tconst width = rt ? rt.width : device.width;\\n\\t\\t\\t\\tconst height = rt ? rt.height : device.height;\\n\\t\\t\\t\\treturn width * this.rect.z / (height * this.rect.w);\\n\\t\\t}\\n\\t\\tframeUpdate(rt) {\\n\\t\\t\\t\\tif (this.aspectRatioMode === ASPECT_AUTO) {\\n\\t\\t\\t\\t\\t\\tthis.aspectRatio = this.calculateAspectRatio(rt);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tstartXr(type, spaceType, options) {\\n\\t\\t\\t\\tthis.system.app.xr.start(this, type, spaceType, options);\\n\\t\\t}\\n\\t\\tendXr(callback) {\\n\\t\\t\\t\\tif (!this._camera.xr) {\\n\\t\\t\\t\\t\\t\\tif (callback) callback(new Error('Camera is not in XR'));\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._camera.xr.end(callback);\\n\\t\\t}\\n\\t\\tcopy(source) {\\n\\t\\t\\t\\tthis.aperture = source.aperture;\\n\\t\\t\\t\\tthis.aspectRatio = source.aspectRatio;\\n\\t\\t\\t\\tthis.aspectRatioMode = source.aspectRatioMode;\\n\\t\\t\\t\\tthis.calculateProjection = source.calculateProjection;\\n\\t\\t\\t\\tthis.calculateTransform = source.calculateTransform;\\n\\t\\t\\t\\tthis.clearColor = source.clearColor;\\n\\t\\t\\t\\tthis.clearColorBuffer = source.clearColorBuffer;\\n\\t\\t\\t\\tthis.clearDepthBuffer = source.clearDepthBuffer;\\n\\t\\t\\t\\tthis.clearStencilBuffer = source.clearStencilBuffer;\\n\\t\\t\\t\\tthis.cullFaces = source.cullFaces;\\n\\t\\t\\t\\tthis.disablePostEffectsLayer = source.disablePostEffectsLayer;\\n\\t\\t\\t\\tthis.farClip = source.farClip;\\n\\t\\t\\t\\tthis.flipFaces = source.flipFaces;\\n\\t\\t\\t\\tthis.fov = source.fov;\\n\\t\\t\\t\\tthis.frustumCulling = source.frustumCulling;\\n\\t\\t\\t\\tthis.horizontalFov = source.horizontalFov;\\n\\t\\t\\t\\tthis.layers = source.layers;\\n\\t\\t\\t\\tthis.nearClip = source.nearClip;\\n\\t\\t\\t\\tthis.orthoHeight = source.orthoHeight;\\n\\t\\t\\t\\tthis.priority = source.priority;\\n\\t\\t\\t\\tthis.projection = source.projection;\\n\\t\\t\\t\\tthis.rect = source.rect;\\n\\t\\t\\t\\tthis.renderTarget = source.renderTarget;\\n\\t\\t\\t\\tthis.scissorRect = source.scissorRect;\\n\\t\\t\\t\\tthis.sensitivity = source.sensitivity;\\n\\t\\t\\t\\tthis.shutter = source.shutter;\\n\\t\\t}\\n\\t\\tconstructor(system, entity){\\n\\t\\t\\t\\tsuper(system, entity), this.onPostprocessing = null, this._renderSceneDepthMap = 0, this._renderSceneColorMap = 0, this._sceneDepthMapRequested = false, this._sceneColorMapRequested = false, this._priority = 0, this._disablePostEffectsLayer = LAYERID_UI, this._camera = new Camera$1(), this._evtLayersChanged = null, this._evtLayerAdded = null, this._evtLayerRemoved = null;\\n\\t\\t\\t\\tthis._camera.node = entity;\\n\\t\\t\\t\\tthis._postEffects = new PostEffectQueue(system.app, this);\\n\\t\\t}\\n}\\n\\nclass CameraComponentData {\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.enabled = true;\\n\\t\\t}\\n}\\n\\nconst _schema$1 = [\\n\\t\\t'enabled'\\n];\\nclass CameraComponentSystem extends ComponentSystem {\\n\\t\\tinitializeComponentData(component, data, properties) {\\n\\t\\t\\t\\tproperties = [\\n\\t\\t\\t\\t\\t\\t'aspectRatio',\\n\\t\\t\\t\\t\\t\\t'aspectRatioMode',\\n\\t\\t\\t\\t\\t\\t'calculateProjection',\\n\\t\\t\\t\\t\\t\\t'calculateTransform',\\n\\t\\t\\t\\t\\t\\t'clearColor',\\n\\t\\t\\t\\t\\t\\t'clearColorBuffer',\\n\\t\\t\\t\\t\\t\\t'clearDepth',\\n\\t\\t\\t\\t\\t\\t'clearDepthBuffer',\\n\\t\\t\\t\\t\\t\\t'clearStencilBuffer',\\n\\t\\t\\t\\t\\t\\t'renderSceneColorMap',\\n\\t\\t\\t\\t\\t\\t'renderSceneDepthMap',\\n\\t\\t\\t\\t\\t\\t'cullFaces',\\n\\t\\t\\t\\t\\t\\t'farClip',\\n\\t\\t\\t\\t\\t\\t'flipFaces',\\n\\t\\t\\t\\t\\t\\t'fog',\\n\\t\\t\\t\\t\\t\\t'fov',\\n\\t\\t\\t\\t\\t\\t'frustumCulling',\\n\\t\\t\\t\\t\\t\\t'horizontalFov',\\n\\t\\t\\t\\t\\t\\t'layers',\\n\\t\\t\\t\\t\\t\\t'renderTarget',\\n\\t\\t\\t\\t\\t\\t'nearClip',\\n\\t\\t\\t\\t\\t\\t'orthoHeight',\\n\\t\\t\\t\\t\\t\\t'projection',\\n\\t\\t\\t\\t\\t\\t'priority',\\n\\t\\t\\t\\t\\t\\t'rect',\\n\\t\\t\\t\\t\\t\\t'scissorRect',\\n\\t\\t\\t\\t\\t\\t'aperture',\\n\\t\\t\\t\\t\\t\\t'shutter',\\n\\t\\t\\t\\t\\t\\t'sensitivity',\\n\\t\\t\\t\\t\\t\\t'gammaCorrection',\\n\\t\\t\\t\\t\\t\\t'toneMapping'\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tfor(let i = 0; i < properties.length; i++){\\n\\t\\t\\t\\t\\t\\tconst property = properties[i];\\n\\t\\t\\t\\t\\t\\tif (data.hasOwnProperty(property)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst value = data[property];\\n\\t\\t\\t\\t\\t\\t\\t\\tswitch(property){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase 'rect':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase 'scissorRect':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (Array.isArray(value)) {\\n\\t\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcomponent[property] = value;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase 'clearColor':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (Array.isArray(value)) {\\n\\t\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcomponent[property] = value;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcomponent[property] = value;\\n\\t\\t\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tsuper.initializeComponentData(component, data, [\\n\\t\\t\\t\\t\\t\\t'enabled'\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tcloneComponent(entity, clone) {\\n\\t\\t\\t\\tconst c = entity.camera;\\n\\t\\t\\t\\treturn this.addComponent(clone, {\\n\\t\\t\\t\\t\\t\\taspectRatio: c.aspectRatio,\\n\\t\\t\\t\\t\\t\\taspectRatioMode: c.aspectRatioMode,\\n\\t\\t\\t\\t\\t\\tcalculateProjection: c.calculateProjection,\\n\\t\\t\\t\\t\\t\\tcalculateTransform: c.calculateTransform,\\n\\t\\t\\t\\t\\t\\tclearColor: c.clearColor,\\n\\t\\t\\t\\t\\t\\tclearColorBuffer: c.clearColorBuffer,\\n\\t\\t\\t\\t\\t\\tclearDepthBuffer: c.clearDepthBuffer,\\n\\t\\t\\t\\t\\t\\tclearStencilBuffer: c.clearStencilBuffer,\\n\\t\\t\\t\\t\\t\\trenderSceneDepthMap: c.renderSceneDepthMap,\\n\\t\\t\\t\\t\\t\\trenderSceneColorMap: c.renderSceneColorMap,\\n\\t\\t\\t\\t\\t\\tcullFaces: c.cullFaces,\\n\\t\\t\\t\\t\\t\\tenabled: c.enabled,\\n\\t\\t\\t\\t\\t\\tfarClip: c.farClip,\\n\\t\\t\\t\\t\\t\\tflipFaces: c.flipFaces,\\n\\t\\t\\t\\t\\t\\tfov: c.fov,\\n\\t\\t\\t\\t\\t\\tfrustumCulling: c.frustumCulling,\\n\\t\\t\\t\\t\\t\\thorizontalFov: c.horizontalFov,\\n\\t\\t\\t\\t\\t\\tlayers: c.layers,\\n\\t\\t\\t\\t\\t\\trenderTarget: c.renderTarget,\\n\\t\\t\\t\\t\\t\\tnearClip: c.nearClip,\\n\\t\\t\\t\\t\\t\\torthoHeight: c.orthoHeight,\\n\\t\\t\\t\\t\\t\\tprojection: c.projection,\\n\\t\\t\\t\\t\\t\\tpriority: c.priority,\\n\\t\\t\\t\\t\\t\\trect: c.rect,\\n\\t\\t\\t\\t\\t\\tscissorRect: c.scissorRect,\\n\\t\\t\\t\\t\\t\\taperture: c.aperture,\\n\\t\\t\\t\\t\\t\\tsensitivity: c.sensitivity,\\n\\t\\t\\t\\t\\t\\tshutter: c.shutter,\\n\\t\\t\\t\\t\\t\\tgammaCorrection: c.gammaCorrection,\\n\\t\\t\\t\\t\\t\\ttoneMapping: c.toneMapping\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tonBeforeRemove(entity, component) {\\n\\t\\t\\t\\tthis.removeCamera(component);\\n\\t\\t\\t\\tcomponent.onRemove();\\n\\t\\t}\\n\\t\\tonAppPrerender() {\\n\\t\\t\\t\\tfor(let i = 0, len = this.cameras.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tthis.cameras[i].onAppPrerender();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\taddCamera(camera) {\\n\\t\\t\\t\\tthis.cameras.push(camera);\\n\\t\\t\\t\\tsortPriority(this.cameras);\\n\\t\\t}\\n\\t\\tremoveCamera(camera) {\\n\\t\\t\\t\\tconst index = this.cameras.indexOf(camera);\\n\\t\\t\\t\\tif (index >= 0) {\\n\\t\\t\\t\\t\\t\\tthis.cameras.splice(index, 1);\\n\\t\\t\\t\\t\\t\\tsortPriority(this.cameras);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.app.off('prerender', this.onAppPrerender, this);\\n\\t\\t\\t\\tsuper.destroy();\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tsuper(app), this.cameras = [];\\n\\t\\t\\t\\tthis.id = 'camera';\\n\\t\\t\\t\\tthis.ComponentType = CameraComponent;\\n\\t\\t\\t\\tthis.DataType = CameraComponentData;\\n\\t\\t\\t\\tthis.schema = _schema$1;\\n\\t\\t\\t\\tthis.on('beforeremove', this.onBeforeRemove, this);\\n\\t\\t\\t\\tthis.app.on('prerender', this.onAppPrerender, this);\\n\\t\\t}\\n}\\nComponent._buildAccessors(CameraComponent.prototype, _schema$1);\\n\\nclass LightComponentData {\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.enabled = true;\\n\\t\\t\\t\\tthis.type = 'directional';\\n\\t\\t\\t\\tthis.color = new Color(1, 1, 1);\\n\\t\\t\\t\\tthis.intensity = 1;\\n\\t\\t\\t\\tthis.luminance = 0;\\n\\t\\t\\t\\tthis.shape = LIGHTSHAPE_PUNCTUAL;\\n\\t\\t\\t\\tthis.affectSpecularity = true;\\n\\t\\t\\t\\tthis.castShadows = false;\\n\\t\\t\\t\\tthis.shadowDistance = 40;\\n\\t\\t\\t\\tthis.shadowIntensity = 1;\\n\\t\\t\\t\\tthis.shadowResolution = 1024;\\n\\t\\t\\t\\tthis.shadowBias = 0.05;\\n\\t\\t\\t\\tthis.numCascades = 1;\\n\\t\\t\\t\\tthis.cascadeBlend = 0;\\n\\t\\t\\t\\tthis.bakeNumSamples = 1;\\n\\t\\t\\t\\tthis.bakeArea = 0;\\n\\t\\t\\t\\tthis.cascadeDistribution = 0.5;\\n\\t\\t\\t\\tthis.normalOffsetBias = 0;\\n\\t\\t\\t\\tthis.range = 10;\\n\\t\\t\\t\\tthis.innerConeAngle = 40;\\n\\t\\t\\t\\tthis.outerConeAngle = 45;\\n\\t\\t\\t\\tthis.falloffMode = LIGHTFALLOFF_LINEAR;\\n\\t\\t\\t\\tthis.shadowType = SHADOW_PCF3_32F;\\n\\t\\t\\t\\tthis.vsmBlurSize = 11;\\n\\t\\t\\t\\tthis.vsmBlurMode = BLUR_GAUSSIAN;\\n\\t\\t\\t\\tthis.vsmBias = 0.01 * 0.25;\\n\\t\\t\\t\\tthis.cookieAsset = null;\\n\\t\\t\\t\\tthis.cookie = null;\\n\\t\\t\\t\\tthis.cookieIntensity = 1;\\n\\t\\t\\t\\tthis.cookieFalloff = true;\\n\\t\\t\\t\\tthis.cookieChannel = 'rgb';\\n\\t\\t\\t\\tthis.cookieAngle = 0;\\n\\t\\t\\t\\tthis.cookieScale = null;\\n\\t\\t\\t\\tthis.cookieOffset = null;\\n\\t\\t\\t\\tthis.shadowUpdateMode = SHADOWUPDATE_REALTIME;\\n\\t\\t\\t\\tthis.mask = 1;\\n\\t\\t\\t\\tthis.affectDynamic = true;\\n\\t\\t\\t\\tthis.affectLightmapped = false;\\n\\t\\t\\t\\tthis.bake = false;\\n\\t\\t\\t\\tthis.bakeDir = true;\\n\\t\\t\\t\\tthis.isStatic = false;\\n\\t\\t\\t\\tthis.layers = [\\n\\t\\t\\t\\t\\t\\tLAYERID_WORLD\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.penumbraSize = 1;\\n\\t\\t\\t\\tthis.penumbraFalloff = 1;\\n\\t\\t\\t\\tthis.shadowSamples = 16;\\n\\t\\t\\t\\tthis.shadowBlockerSamples = 16;\\n\\t\\t}\\n}\\nconst properties = Object.keys(new LightComponentData());\\n\\nclass LightComponent extends Component {\\n\\t\\tget data() {\\n\\t\\t\\t\\tconst record = this.system.store[this.entity.getGuid()];\\n\\t\\t\\t\\treturn record ? record.data : null;\\n\\t\\t}\\n\\t\\tset enabled(arg) {\\n\\t\\t\\t\\tthis._setValue('enabled', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.onSetEnabled(null, oldValue, newValue);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget enabled() {\\n\\t\\t\\t\\treturn this.data.enabled;\\n\\t\\t}\\n\\t\\tset light(arg) {\\n\\t\\t\\t\\tthis._setValue('light', arg);\\n\\t\\t}\\n\\t\\tget light() {\\n\\t\\t\\t\\treturn this.data.light;\\n\\t\\t}\\n\\t\\tset type(arg) {\\n\\t\\t\\t\\tthis._setValue('type', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.system.changeType(this, oldValue, newValue);\\n\\t\\t\\t\\t\\t\\tthis.refreshProperties();\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget type() {\\n\\t\\t\\t\\treturn this.data.type;\\n\\t\\t}\\n\\t\\tset color(arg) {\\n\\t\\t\\t\\tthis._setValue('color', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.setColor(newValue);\\n\\t\\t\\t\\t}, true);\\n\\t\\t}\\n\\t\\tget color() {\\n\\t\\t\\t\\treturn this.data.color;\\n\\t\\t}\\n\\t\\tset intensity(arg) {\\n\\t\\t\\t\\tthis._setValue('intensity', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.intensity = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget intensity() {\\n\\t\\t\\t\\treturn this.data.intensity;\\n\\t\\t}\\n\\t\\tset luminance(arg) {\\n\\t\\t\\t\\tthis._setValue('luminance', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.luminance = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget luminance() {\\n\\t\\t\\t\\treturn this.data.luminance;\\n\\t\\t}\\n\\t\\tset shape(arg) {\\n\\t\\t\\t\\tthis._setValue('shape', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.shape = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget shape() {\\n\\t\\t\\t\\treturn this.data.shape;\\n\\t\\t}\\n\\t\\tset affectSpecularity(arg) {\\n\\t\\t\\t\\tthis._setValue('affectSpecularity', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.affectSpecularity = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget affectSpecularity() {\\n\\t\\t\\t\\treturn this.data.affectSpecularity;\\n\\t\\t}\\n\\t\\tset castShadows(arg) {\\n\\t\\t\\t\\tthis._setValue('castShadows', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.castShadows = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget castShadows() {\\n\\t\\t\\t\\treturn this.data.castShadows;\\n\\t\\t}\\n\\t\\tset shadowDistance(arg) {\\n\\t\\t\\t\\tthis._setValue('shadowDistance', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.shadowDistance = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget shadowDistance() {\\n\\t\\t\\t\\treturn this.data.shadowDistance;\\n\\t\\t}\\n\\t\\tset shadowIntensity(arg) {\\n\\t\\t\\t\\tthis._setValue('shadowIntensity', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.shadowIntensity = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget shadowIntensity() {\\n\\t\\t\\t\\treturn this.data.shadowIntensity;\\n\\t\\t}\\n\\t\\tset shadowResolution(arg) {\\n\\t\\t\\t\\tthis._setValue('shadowResolution', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.shadowResolution = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget shadowResolution() {\\n\\t\\t\\t\\treturn this.data.shadowResolution;\\n\\t\\t}\\n\\t\\tset shadowBias(arg) {\\n\\t\\t\\t\\tthis._setValue('shadowBias', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.shadowBias = -0.01 * math.clamp(newValue, 0, 1);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget shadowBias() {\\n\\t\\t\\t\\treturn this.data.shadowBias;\\n\\t\\t}\\n\\t\\tset numCascades(arg) {\\n\\t\\t\\t\\tthis._setValue('numCascades', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.numCascades = math.clamp(Math.floor(newValue), 1, 4);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget numCascades() {\\n\\t\\t\\t\\treturn this.data.numCascades;\\n\\t\\t}\\n\\t\\tset cascadeBlend(value) {\\n\\t\\t\\t\\tthis._setValue('cascadeBlend', value, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.cascadeBlend = math.clamp(newValue, 0, 1);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget cascadeBlend() {\\n\\t\\t\\t\\treturn this.data.cascadeBlend;\\n\\t\\t}\\n\\t\\tset bakeNumSamples(arg) {\\n\\t\\t\\t\\tthis._setValue('bakeNumSamples', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.bakeNumSamples = math.clamp(Math.floor(newValue), 1, 255);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget bakeNumSamples() {\\n\\t\\t\\t\\treturn this.data.bakeNumSamples;\\n\\t\\t}\\n\\t\\tset bakeArea(arg) {\\n\\t\\t\\t\\tthis._setValue('bakeArea', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.bakeArea = math.clamp(newValue, 0, 180);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget bakeArea() {\\n\\t\\t\\t\\treturn this.data.bakeArea;\\n\\t\\t}\\n\\t\\tset cascadeDistribution(arg) {\\n\\t\\t\\t\\tthis._setValue('cascadeDistribution', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.cascadeDistribution = math.clamp(newValue, 0, 1);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget cascadeDistribution() {\\n\\t\\t\\t\\treturn this.data.cascadeDistribution;\\n\\t\\t}\\n\\t\\tset normalOffsetBias(arg) {\\n\\t\\t\\t\\tthis._setValue('normalOffsetBias', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.normalOffsetBias = math.clamp(newValue, 0, 1);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget normalOffsetBias() {\\n\\t\\t\\t\\treturn this.data.normalOffsetBias;\\n\\t\\t}\\n\\t\\tset range(arg) {\\n\\t\\t\\t\\tthis._setValue('range', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.attenuationEnd = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget range() {\\n\\t\\t\\t\\treturn this.data.range;\\n\\t\\t}\\n\\t\\tset innerConeAngle(arg) {\\n\\t\\t\\t\\tthis._setValue('innerConeAngle', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.innerConeAngle = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget innerConeAngle() {\\n\\t\\t\\t\\treturn this.data.innerConeAngle;\\n\\t\\t}\\n\\t\\tset outerConeAngle(arg) {\\n\\t\\t\\t\\tthis._setValue('outerConeAngle', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.outerConeAngle = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget outerConeAngle() {\\n\\t\\t\\t\\treturn this.data.outerConeAngle;\\n\\t\\t}\\n\\t\\tset falloffMode(arg) {\\n\\t\\t\\t\\tthis._setValue('falloffMode', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.falloffMode = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget falloffMode() {\\n\\t\\t\\t\\treturn this.data.falloffMode;\\n\\t\\t}\\n\\t\\tset shadowType(arg) {\\n\\t\\t\\t\\tthis._setValue('shadowType', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.shadowType = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget shadowType() {\\n\\t\\t\\t\\treturn this.data.shadowType;\\n\\t\\t}\\n\\t\\tset vsmBlurSize(arg) {\\n\\t\\t\\t\\tthis._setValue('vsmBlurSize', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.vsmBlurSize = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget vsmBlurSize() {\\n\\t\\t\\t\\treturn this.data.vsmBlurSize;\\n\\t\\t}\\n\\t\\tset vsmBlurMode(arg) {\\n\\t\\t\\t\\tthis._setValue('vsmBlurMode', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.vsmBlurMode = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget vsmBlurMode() {\\n\\t\\t\\t\\treturn this.data.vsmBlurMode;\\n\\t\\t}\\n\\t\\tset vsmBias(arg) {\\n\\t\\t\\t\\tthis._setValue('vsmBias', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.vsmBias = math.clamp(newValue, 0, 1);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget vsmBias() {\\n\\t\\t\\t\\treturn this.data.vsmBias;\\n\\t\\t}\\n\\t\\tset cookieAsset(arg) {\\n\\t\\t\\t\\tthis._setValue('cookieAsset', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tif (this._cookieAssetId && (newValue instanceof Asset && newValue.id === this._cookieAssetId || newValue === this._cookieAssetId)) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.onCookieAssetRemove();\\n\\t\\t\\t\\t\\t\\tthis._cookieAssetId = null;\\n\\t\\t\\t\\t\\t\\tif (newValue instanceof Asset) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.data.cookieAsset = newValue.id;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._cookieAssetId = newValue.id;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.onCookieAssetAdd(newValue);\\n\\t\\t\\t\\t\\t\\t} else if (typeof newValue === 'number') {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._cookieAssetId = newValue;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst asset = this.system.app.assets.get(newValue);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (asset) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.onCookieAssetAdd(asset);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._cookieAssetAdd = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.system.app.assets.on(`add:${this._cookieAssetId}`, this.onCookieAssetAdd, this);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget cookieAsset() {\\n\\t\\t\\t\\treturn this.data.cookieAsset;\\n\\t\\t}\\n\\t\\tset cookie(arg) {\\n\\t\\t\\t\\tthis._setValue('cookie', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.cookie = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget cookie() {\\n\\t\\t\\t\\treturn this.data.cookie;\\n\\t\\t}\\n\\t\\tset cookieIntensity(arg) {\\n\\t\\t\\t\\tthis._setValue('cookieIntensity', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.cookieIntensity = math.clamp(newValue, 0, 1);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget cookieIntensity() {\\n\\t\\t\\t\\treturn this.data.cookieIntensity;\\n\\t\\t}\\n\\t\\tset cookieFalloff(arg) {\\n\\t\\t\\t\\tthis._setValue('cookieFalloff', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.cookieFalloff = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget cookieFalloff() {\\n\\t\\t\\t\\treturn this.data.cookieFalloff;\\n\\t\\t}\\n\\t\\tset cookieChannel(arg) {\\n\\t\\t\\t\\tthis._setValue('cookieChannel', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.cookieChannel = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget cookieChannel() {\\n\\t\\t\\t\\treturn this.data.cookieChannel;\\n\\t\\t}\\n\\t\\tset cookieAngle(arg) {\\n\\t\\t\\t\\tthis._setValue('cookieAngle', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tif (newValue !== 0 || this.cookieScale !== null) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this._cookieMatrix) this._cookieMatrix = new Vec4();\\n\\t\\t\\t\\t\\t\\t\\t\\tlet scx = 1;\\n\\t\\t\\t\\t\\t\\t\\t\\tlet scy = 1;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.cookieScale) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscx = this.cookieScale.x;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscy = this.cookieScale.y;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst c = Math.cos(newValue * math.DEG_TO_RAD);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst s = Math.sin(newValue * math.DEG_TO_RAD);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._cookieMatrix.set(c / scx, -s / scx, s / scy, c / scy);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.light.cookieTransform = this._cookieMatrix;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.light.cookieTransform = null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget cookieAngle() {\\n\\t\\t\\t\\treturn this.data.cookieAngle;\\n\\t\\t}\\n\\t\\tset cookieScale(arg) {\\n\\t\\t\\t\\tthis._setValue('cookieScale', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tif (newValue !== null || this.cookieAngle !== 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this._cookieMatrix) this._cookieMatrix = new Vec4();\\n\\t\\t\\t\\t\\t\\t\\t\\tconst scx = newValue.x;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst scy = newValue.y;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst c = Math.cos(this.cookieAngle * math.DEG_TO_RAD);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst s = Math.sin(this.cookieAngle * math.DEG_TO_RAD);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._cookieMatrix.set(c / scx, -s / scx, s / scy, c / scy);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.light.cookieTransform = this._cookieMatrix;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.light.cookieTransform = null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}, true);\\n\\t\\t}\\n\\t\\tget cookieScale() {\\n\\t\\t\\t\\treturn this.data.cookieScale;\\n\\t\\t}\\n\\t\\tset cookieOffset(arg) {\\n\\t\\t\\t\\tthis._setValue('cookieOffset', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.cookieOffset = newValue;\\n\\t\\t\\t\\t}, true);\\n\\t\\t}\\n\\t\\tget cookieOffset() {\\n\\t\\t\\t\\treturn this.data.cookieOffset;\\n\\t\\t}\\n\\t\\tset shadowUpdateMode(arg) {\\n\\t\\t\\t\\tthis._setValue('shadowUpdateMode', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.shadowUpdateMode = newValue;\\n\\t\\t\\t\\t}, true);\\n\\t\\t}\\n\\t\\tget shadowUpdateMode() {\\n\\t\\t\\t\\treturn this.data.shadowUpdateMode;\\n\\t\\t}\\n\\t\\tset mask(arg) {\\n\\t\\t\\t\\tthis._setValue('mask', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.mask = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget mask() {\\n\\t\\t\\t\\treturn this.data.mask;\\n\\t\\t}\\n\\t\\tset affectDynamic(arg) {\\n\\t\\t\\t\\tthis._setValue('affectDynamic', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tif (newValue) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.light.mask |= MASK_AFFECT_DYNAMIC;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.light.mask &= ~MASK_AFFECT_DYNAMIC;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.light.layersDirty();\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget affectDynamic() {\\n\\t\\t\\t\\treturn this.data.affectDynamic;\\n\\t\\t}\\n\\t\\tset affectLightmapped(arg) {\\n\\t\\t\\t\\tthis._setValue('affectLightmapped', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tif (newValue) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.light.mask |= MASK_AFFECT_LIGHTMAPPED;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.bake) this.light.mask &= ~MASK_BAKE;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.light.mask &= ~MASK_AFFECT_LIGHTMAPPED;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.bake) this.light.mask |= MASK_BAKE;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget affectLightmapped() {\\n\\t\\t\\t\\treturn this.data.affectLightmapped;\\n\\t\\t}\\n\\t\\tset bake(arg) {\\n\\t\\t\\t\\tthis._setValue('bake', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tif (newValue) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.light.mask |= MASK_BAKE;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.affectLightmapped) this.light.mask &= ~MASK_AFFECT_LIGHTMAPPED;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.light.mask &= ~MASK_BAKE;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.affectLightmapped) this.light.mask |= MASK_AFFECT_LIGHTMAPPED;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.light.layersDirty();\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget bake() {\\n\\t\\t\\t\\treturn this.data.bake;\\n\\t\\t}\\n\\t\\tset bakeDir(arg) {\\n\\t\\t\\t\\tthis._setValue('bakeDir', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.bakeDir = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget bakeDir() {\\n\\t\\t\\t\\treturn this.data.bakeDir;\\n\\t\\t}\\n\\t\\tset isStatic(arg) {\\n\\t\\t\\t\\tthis._setValue('isStatic', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tthis.light.isStatic = newValue;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget isStatic() {\\n\\t\\t\\t\\treturn this.data.isStatic;\\n\\t\\t}\\n\\t\\tset layers(arg) {\\n\\t\\t\\t\\tthis._setValue('layers', arg, function(newValue, oldValue) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < oldValue.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst layer = this.system.app.scene.layers.getLayerById(oldValue[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!layer) continue;\\n\\t\\t\\t\\t\\t\\t\\t\\tlayer.removeLight(this);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.light.removeLayer(layer);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < newValue.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst layer = this.system.app.scene.layers.getLayerById(newValue[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!layer) continue;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayer.addLight(this);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.light.addLayer(layer);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget layers() {\\n\\t\\t\\t\\treturn this.data.layers;\\n\\t\\t}\\n\\t\\tset shadowUpdateOverrides(values) {\\n\\t\\t\\t\\tthis.light.shadowUpdateOverrides = values;\\n\\t\\t}\\n\\t\\tget shadowUpdateOverrides() {\\n\\t\\t\\t\\treturn this.light.shadowUpdateOverrides;\\n\\t\\t}\\n\\t\\tset shadowSamples(value) {\\n\\t\\t\\t\\tthis.light.shadowSamples = value;\\n\\t\\t}\\n\\t\\tget shadowSamples() {\\n\\t\\t\\t\\treturn this.light.shadowSamples;\\n\\t\\t}\\n\\t\\tset shadowBlockerSamples(value) {\\n\\t\\t\\t\\tthis.light.shadowBlockerSamples = value;\\n\\t\\t}\\n\\t\\tget shadowBlockerSamples() {\\n\\t\\t\\t\\treturn this.light.shadowBlockerSamples;\\n\\t\\t}\\n\\t\\tset penumbraSize(value) {\\n\\t\\t\\t\\tthis.light.penumbraSize = value;\\n\\t\\t}\\n\\t\\tget penumbraSize() {\\n\\t\\t\\t\\treturn this.light.penumbraSize;\\n\\t\\t}\\n\\t\\tset penumbraFalloff(value) {\\n\\t\\t\\t\\tthis.light.penumbraFalloff = value;\\n\\t\\t}\\n\\t\\tget penumbraFalloff() {\\n\\t\\t\\t\\treturn this.light.penumbraFalloff;\\n\\t\\t}\\n\\t\\t_setValue(name, value, setFunc, skipEqualsCheck) {\\n\\t\\t\\t\\tconst data = this.data;\\n\\t\\t\\t\\tconst oldValue = data[name];\\n\\t\\t\\t\\tif (!skipEqualsCheck && oldValue === value) return;\\n\\t\\t\\t\\tdata[name] = value;\\n\\t\\t\\t\\tif (setFunc) setFunc.call(this, value, oldValue);\\n\\t\\t}\\n\\t\\taddLightToLayers() {\\n\\t\\t\\t\\tfor(let i = 0; i < this.layers.length; i++){\\n\\t\\t\\t\\t\\t\\tconst layer = this.system.app.scene.layers.getLayerById(this.layers[i]);\\n\\t\\t\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlayer.addLight(this);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.light.addLayer(layer);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tremoveLightFromLayers() {\\n\\t\\t\\t\\tfor(let i = 0; i < this.layers.length; i++){\\n\\t\\t\\t\\t\\t\\tconst layer = this.system.app.scene.layers.getLayerById(this.layers[i]);\\n\\t\\t\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlayer.removeLight(this);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.light.removeLayer(layer);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonLayersChanged(oldComp, newComp) {\\n\\t\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\tthis.addLightToLayers();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\toldComp.off('add', this.onLayerAdded, this);\\n\\t\\t\\t\\toldComp.off('remove', this.onLayerRemoved, this);\\n\\t\\t\\t\\tnewComp.on('add', this.onLayerAdded, this);\\n\\t\\t\\t\\tnewComp.on('remove', this.onLayerRemoved, this);\\n\\t\\t}\\n\\t\\tonLayerAdded(layer) {\\n\\t\\t\\t\\tconst index = this.layers.indexOf(layer.id);\\n\\t\\t\\t\\tif (index >= 0 && this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\tlayer.addLight(this);\\n\\t\\t\\t\\t\\t\\tthis.light.addLayer(layer);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonLayerRemoved(layer) {\\n\\t\\t\\t\\tconst index = this.layers.indexOf(layer.id);\\n\\t\\t\\t\\tif (index >= 0) {\\n\\t\\t\\t\\t\\t\\tlayer.removeLight(this);\\n\\t\\t\\t\\t\\t\\tthis.light.removeLayer(layer);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\trefreshProperties() {\\n\\t\\t\\t\\tfor(let i = 0; i < properties.length; i++){\\n\\t\\t\\t\\t\\t\\tconst name = properties[i];\\n\\t\\t\\t\\t\\t\\tthis[name] = this[name];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\tthis.onEnable();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonCookieAssetSet() {\\n\\t\\t\\t\\tlet forceLoad = false;\\n\\t\\t\\t\\tif (this._cookieAsset.type === 'cubemap' && !this._cookieAsset.loadFaces) {\\n\\t\\t\\t\\t\\t\\tthis._cookieAsset.loadFaces = true;\\n\\t\\t\\t\\t\\t\\tforceLoad = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._cookieAsset.resource || forceLoad) this.system.app.assets.load(this._cookieAsset);\\n\\t\\t\\t\\tif (this._cookieAsset.resource) {\\n\\t\\t\\t\\t\\t\\tthis.onCookieAssetLoad();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonCookieAssetAdd(asset) {\\n\\t\\t\\t\\tif (this._cookieAssetId !== asset.id) return;\\n\\t\\t\\t\\tthis._cookieAsset = asset;\\n\\t\\t\\t\\tif (this.light.enabled) {\\n\\t\\t\\t\\t\\t\\tthis.onCookieAssetSet();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._cookieAsset.on('load', this.onCookieAssetLoad, this);\\n\\t\\t\\t\\tthis._cookieAsset.on('remove', this.onCookieAssetRemove, this);\\n\\t\\t}\\n\\t\\tonCookieAssetLoad() {\\n\\t\\t\\t\\tif (!this._cookieAsset || !this._cookieAsset.resource) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.cookie = this._cookieAsset.resource;\\n\\t\\t}\\n\\t\\tonCookieAssetRemove() {\\n\\t\\t\\t\\tif (!this._cookieAssetId) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._cookieAssetAdd) {\\n\\t\\t\\t\\t\\t\\tthis.system.app.assets.off(`add:${this._cookieAssetId}`, this.onCookieAssetAdd, this);\\n\\t\\t\\t\\t\\t\\tthis._cookieAssetAdd = false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._cookieAsset) {\\n\\t\\t\\t\\t\\t\\tthis._cookieAsset.off('load', this.onCookieAssetLoad, this);\\n\\t\\t\\t\\t\\t\\tthis._cookieAsset.off('remove', this.onCookieAssetRemove, this);\\n\\t\\t\\t\\t\\t\\tthis._cookieAsset = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.cookie = null;\\n\\t\\t}\\n\\t\\tonEnable() {\\n\\t\\t\\t\\tconst scene = this.system.app.scene;\\n\\t\\t\\t\\tconst layers = scene.layers;\\n\\t\\t\\t\\tthis.light.enabled = true;\\n\\t\\t\\t\\tthis._evtLayersChanged = scene.on('set:layers', this.onLayersChanged, this);\\n\\t\\t\\t\\tif (layers) {\\n\\t\\t\\t\\t\\t\\tthis._evtLayerAdded = layers.on('add', this.onLayerAdded, this);\\n\\t\\t\\t\\t\\t\\tthis._evtLayerRemoved = layers.on('remove', this.onLayerRemoved, this);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\tthis.addLightToLayers();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._cookieAsset && !this.cookie) {\\n\\t\\t\\t\\t\\t\\tthis.onCookieAssetSet();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonDisable() {\\n\\t\\t\\t\\tconst scene = this.system.app.scene;\\n\\t\\t\\t\\tconst layers = scene.layers;\\n\\t\\t\\t\\tthis.light.enabled = false;\\n\\t\\t\\t\\tthis._evtLayersChanged?.off();\\n\\t\\t\\t\\tthis._evtLayersChanged = null;\\n\\t\\t\\t\\tif (layers) {\\n\\t\\t\\t\\t\\t\\tthis._evtLayerAdded?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtLayerAdded = null;\\n\\t\\t\\t\\t\\t\\tthis._evtLayerRemoved?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtLayerRemoved = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.removeLightFromLayers();\\n\\t\\t}\\n\\t\\tonRemove() {\\n\\t\\t\\t\\tthis.onDisable();\\n\\t\\t\\t\\tthis.light.destroy();\\n\\t\\t\\t\\tthis.cookieAsset = null;\\n\\t\\t}\\n\\t\\tconstructor(...args){\\n\\t\\t\\t\\tsuper(...args), this._evtLayersChanged = null, this._evtLayerAdded = null, this._evtLayerRemoved = null, this._cookieAsset = null, this._cookieAssetId = null, this._cookieAssetAdd = false, this._cookieMatrix = null;\\n\\t\\t}\\n}\\n\\nclass LightComponentSystem extends ComponentSystem {\\n\\t\\tinitializeComponentData(component, _data) {\\n\\t\\t\\t\\tconst data = {\\n\\t\\t\\t\\t\\t\\t..._data\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (!data.type) {\\n\\t\\t\\t\\t\\t\\tdata.type = component.data.type;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcomponent.data.type = data.type;\\n\\t\\t\\t\\tif (data.layers && Array.isArray(data.layers)) {\\n\\t\\t\\t\\t\\t\\tdata.layers = data.layers.slice(0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (data.color && Array.isArray(data.color)) {\\n\\t\\t\\t\\t\\t\\tdata.color = new Color(data.color[0], data.color[1], data.color[2]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (data.cookieOffset && data.cookieOffset instanceof Array) {\\n\\t\\t\\t\\t\\t\\tdata.cookieOffset = new Vec2(data.cookieOffset[0], data.cookieOffset[1]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (data.cookieScale && data.cookieScale instanceof Array) {\\n\\t\\t\\t\\t\\t\\tdata.cookieScale = new Vec2(data.cookieScale[0], data.cookieScale[1]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (data.enable) {\\n\\t\\t\\t\\t\\t\\tconsole.warn('WARNING: enable: Property is deprecated. Set enabled property instead.');\\n\\t\\t\\t\\t\\t\\tdata.enabled = data.enable;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!data.shape) {\\n\\t\\t\\t\\t\\t\\tdata.shape = LIGHTSHAPE_PUNCTUAL;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst light = new Light(this.app.graphicsDevice, this.app.scene.clusteredLightingEnabled);\\n\\t\\t\\t\\tlight.type = lightTypes[data.type];\\n\\t\\t\\t\\tlight._node = component.entity;\\n\\t\\t\\t\\tcomponent.data.light = light;\\n\\t\\t\\t\\tsuper.initializeComponentData(component, data, properties);\\n\\t\\t}\\n\\t\\t_onRemoveComponent(entity, component) {\\n\\t\\t\\t\\tcomponent.onRemove();\\n\\t\\t}\\n\\t\\tcloneComponent(entity, clone) {\\n\\t\\t\\t\\tconst light = entity.light;\\n\\t\\t\\t\\tconst data = [];\\n\\t\\t\\t\\tlet name;\\n\\t\\t\\t\\tfor(let i = 0; i < properties.length; i++){\\n\\t\\t\\t\\t\\t\\tname = properties[i];\\n\\t\\t\\t\\t\\t\\tif (name === 'light') {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (light[name] && light[name].clone) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdata[name] = light[name].clone();\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tdata[name] = light[name];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.addComponent(clone, data);\\n\\t\\t}\\n\\t\\tchangeType(component, oldValue, newValue) {\\n\\t\\t\\t\\tif (oldValue !== newValue) {\\n\\t\\t\\t\\t\\t\\tcomponent.light.type = lightTypes[newValue];\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tsuper(app);\\n\\t\\t\\t\\tthis.id = 'light';\\n\\t\\t\\t\\tthis.ComponentType = LightComponent;\\n\\t\\t\\t\\tthis.DataType = LightComponentData;\\n\\t\\t\\t\\tthis.on('beforeremove', this._onRemoveComponent, this);\\n\\t\\t}\\n}\\n\\nconst components = [\\n\\t\\t'x',\\n\\t\\t'y',\\n\\t\\t'z',\\n\\t\\t'w'\\n];\\nconst vecLookup = [\\n\\t\\tundefined,\\n\\t\\tundefined,\\n\\t\\tVec2,\\n\\t\\tVec3,\\n\\t\\tVec4\\n];\\nfunction rawToValue(app, args, value, old) {\\n\\t\\tswitch(args.type){\\n\\t\\t\\t\\tcase 'boolean':\\n\\t\\t\\t\\t\\t\\treturn !!value;\\n\\t\\t\\t\\tcase 'number':\\n\\t\\t\\t\\t\\t\\tif (typeof value === 'number') {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn value;\\n\\t\\t\\t\\t\\t\\t} else if (typeof value === 'string') {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst v = parseInt(value, 10);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (isNaN(v)) return null;\\n\\t\\t\\t\\t\\t\\t\\t\\treturn v;\\n\\t\\t\\t\\t\\t\\t} else if (typeof value === 'boolean') {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 0 + value;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\tcase 'json':\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst result = {};\\n\\t\\t\\t\\t\\t\\t\\t\\tif (Array.isArray(args.schema)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!value || typeof value !== 'object') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvalue = {};\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < args.schema.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst field = args.schema[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!field.name) continue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (field.array) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult[field.name] = [];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst arr = Array.isArray(value[field.name]) ? value[field.name] : [];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < arr.length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult[field.name].push(rawToValue(app, field, arr[j]));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst val = value.hasOwnProperty(field.name) ? value[field.name] : field.default;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult[field.name] = rawToValue(app, field, val);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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\\treturn result;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\tcase 'asset':\\n\\t\\t\\t\\t\\t\\tif (value instanceof Asset) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn value;\\n\\t\\t\\t\\t\\t\\t} else if (typeof value === 'number') {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn app.assets.get(value) || null;\\n\\t\\t\\t\\t\\t\\t} else if (typeof value === 'string') {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn app.assets.get(parseInt(value, 10)) || null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\tcase 'entity':\\n\\t\\t\\t\\t\\t\\tif (value instanceof GraphNode) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn value;\\n\\t\\t\\t\\t\\t\\t} else if (typeof value === 'string') {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn app.getEntityFromIndex(value);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\tcase 'rgb':\\n\\t\\t\\t\\tcase 'rgba':\\n\\t\\t\\t\\t\\t\\tif (value instanceof Color) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (old instanceof Color) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\told.copy(value);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn old;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\treturn value.clone();\\n\\t\\t\\t\\t\\t\\t} else if (value instanceof Array && value.length >= 3 && value.length <= 4) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < value.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (typeof value[i] !== 'number') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\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\\tif (!old) old = new Color();\\n\\t\\t\\t\\t\\t\\t\\t\\told.r = value[0];\\n\\t\\t\\t\\t\\t\\t\\t\\told.g = value[1];\\n\\t\\t\\t\\t\\t\\t\\t\\told.b = value[2];\\n\\t\\t\\t\\t\\t\\t\\t\\told.a = value.length === 3 ? 1 : value[3];\\n\\t\\t\\t\\t\\t\\t\\t\\treturn old;\\n\\t\\t\\t\\t\\t\\t} else if (typeof value === 'string' && /#(?:[0-9a-f]{2}){3,4}/i.test(value)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!old) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\told = new Color();\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\told.fromString(value);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn old;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\tcase 'vec2':\\n\\t\\t\\t\\tcase 'vec3':\\n\\t\\t\\t\\tcase 'vec4':\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst len = parseInt(args.type.slice(3), 10);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst vecType = vecLookup[len];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (value instanceof vecType) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (old instanceof vecType) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\told.copy(value);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn old;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn value.clone();\\n\\t\\t\\t\\t\\t\\t\\t\\t} else if (value instanceof Array && value.length === len) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < value.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (typeof value[i] !== 'number') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!old) old = new vecType();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < len; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\told[components[i]] = value[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn old;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\tcase 'curve':\\n\\t\\t\\t\\t\\t\\tif (value) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlet curve;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (value instanceof Curve || value instanceof CurveSet) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcurve = value.clone();\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst CurveType = value.keys[0] instanceof Array ? CurveSet : Curve;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcurve = new CurveType(value.keys);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcurve.type = value.type;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\treturn curve;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t}\\n\\t\\treturn value;\\n}\\nfunction attributeToValue(app, schema, value, current) {\\n\\t\\tif (schema.array) {\\n\\t\\t\\t\\treturn value.map((item, index)=>rawToValue(app, schema, item, current ? current[index] : null));\\n\\t\\t}\\n\\t\\treturn rawToValue(app, schema, value, current);\\n}\\nfunction assignAttributesToScript(app, attributeSchemaMap, data, script) {\\n\\t\\tif (!data) return;\\n\\t\\tfor(const attributeName in attributeSchemaMap){\\n\\t\\t\\t\\tconst attributeSchema = attributeSchemaMap[attributeName];\\n\\t\\t\\t\\tconst dataToAssign = data[attributeName];\\n\\t\\t\\t\\tif (dataToAssign === undefined) continue;\\n\\t\\t\\t\\tscript[attributeName] = attributeToValue(app, attributeSchema, dataToAssign, script[attributeName]);\\n\\t\\t}\\n}\\nclass ScriptAttributes {\\n\\t\\tadd(name, args) {\\n\\t\\t\\t\\tif (!args) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!args.type) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.index[name]) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t} else if (ScriptAttributes.reservedNames.has(name)) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.index[name] = args;\\n\\t\\t\\t\\tObject.defineProperty(this.scriptType.prototype, name, {\\n\\t\\t\\t\\t\\t\\tget: function() {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn this.__attributes[name];\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tset: function(raw) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst evt = 'attr';\\n\\t\\t\\t\\t\\t\\t\\t\\tconst evtName = `attr:${name}`;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst old = this.__attributes[name];\\n\\t\\t\\t\\t\\t\\t\\t\\tlet oldCopy = old;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (old && args.type !== 'json' && args.type !== 'entity' && old.clone) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this.hasEvent(evt) || this.hasEvent(evtName)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toldCopy = old.clone();\\n\\t\\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\\tif (args.array) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.__attributes[name] = [];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (raw) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0, len = raw.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.__attributes[name] = rawToValue(this.app, args, raw, old);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire(evt, name, this.__attributes[name], oldCopy);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire(evtName, this.__attributes[name], oldCopy);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tremove(name) {\\n\\t\\t\\t\\tif (!this.index[name]) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdelete this.index[name];\\n\\t\\t\\t\\tdelete this.scriptType.prototype[name];\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\thas(name) {\\n\\t\\t\\t\\treturn !!this.index[name];\\n\\t\\t}\\n\\t\\tget(name) {\\n\\t\\t\\t\\treturn this.index[name] || null;\\n\\t\\t}\\n\\t\\tconstructor(scriptType){\\n\\t\\t\\t\\tthis.scriptType = scriptType;\\n\\t\\t\\t\\tthis.index = {};\\n\\t\\t}\\n}\\nScriptAttributes.assignAttributesToScript = assignAttributesToScript;\\nScriptAttributes.attributeToValue = attributeToValue;\\nScriptAttributes.reservedNames = 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]);\\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\\t\\tset enabled(value) {\\n\\t\\t\\t\\tthis._enabled = !!value;\\n\\t\\t\\t\\tif (this.enabled === this._enabledOld) return;\\n\\t\\t\\t\\tthis._enabledOld = this.enabled;\\n\\t\\t\\t\\tthis.fire(this.enabled ? 'enable' : 'disable');\\n\\t\\t\\t\\tthis.fire('state', this.enabled);\\n\\t\\t\\t\\tif (!this._initialized && this.enabled) {\\n\\t\\t\\t\\t\\t\\tthis._initialized = true;\\n\\t\\t\\t\\t\\t\\tthis.fire('preInitialize');\\n\\t\\t\\t\\t\\t\\tif (this.initialize) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.entity.script._scriptMethod(this, SCRIPT_INITIALIZE);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._initialized && !this._postInitialized && this.enabled && !this.entity.script._beingEnabled) {\\n\\t\\t\\t\\t\\t\\tthis._postInitialized = true;\\n\\t\\t\\t\\t\\t\\tif (this.postInitialize) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.entity.script._scriptMethod(this, SCRIPT_POST_INITIALIZE);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget enabled() {\\n\\t\\t\\t\\treturn this._enabled && !this._destroyed && this.entity.script.enabled && this.entity.enabled;\\n\\t\\t}\\n\\t\\tinitScript(args) {\\n\\t\\t\\t\\tconst script = this.constructor;\\n\\t\\t\\t\\tthis.app = args.app;\\n\\t\\t\\t\\tthis.entity = args.entity;\\n\\t\\t\\t\\tthis._enabled = typeof args.enabled === 'boolean' ? args.enabled : true;\\n\\t\\t\\t\\tthis._enabledOld = this.enabled;\\n\\t\\t\\t\\tthis.__destroyed = false;\\n\\t\\t\\t\\tthis.__scriptType = script;\\n\\t\\t\\t\\tthis.__executionOrder = -1;\\n\\t\\t}\\n\\t\\tstatic set scriptName(value) {\\n\\t\\t\\t\\tthis.__name = value;\\n\\t\\t}\\n\\t\\tstatic get scriptName() {\\n\\t\\t\\t\\treturn this.__name;\\n\\t\\t}\\n\\t\\tconstructor(args){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.initScript(args);\\n\\t\\t}\\n}\\nScript.EVENT_ENABLE = 'enable';\\nScript.EVENT_DISABLE = 'disable';\\nScript.EVENT_STATE = 'state';\\nScript.EVENT_DESTROY = 'destroy';\\nScript.EVENT_ATTR = 'attr';\\nScript.EVENT_ERROR = 'error';\\nScript.__name = null;\\nScript.__getScriptName = getScriptName;\\nconst funcNameRegex = /^\\\\s*function(?:\\\\s|\\\\s*\\\\/\\\\*.*\\\\*\\\\/\\\\s*)+([^(\\\\s\\\\/]*)\\\\s*/;\\nfunction getScriptName(constructorFn) {\\n\\t\\tif (typeof constructorFn !== 'function') return undefined;\\n\\t\\tif (constructorFn.scriptName) return constructorFn.scriptName;\\n\\t\\tif ('name' in Function.prototype) return constructorFn.name;\\n\\t\\tif (constructorFn === Function || constructorFn === Function.prototype.constructor) return 'Function';\\n\\t\\tconst match = `${constructorFn}`.match(funcNameRegex);\\n\\t\\treturn match ? match[1] : undefined;\\n}\\n\\nclass ScriptType extends Script {\\n\\t\\tstatic get attributes() {\\n\\t\\t\\t\\tif (!this.hasOwnProperty('__attributes')) this.__attributes = new ScriptAttributes(this);\\n\\t\\t\\t\\treturn this.__attributes;\\n\\t\\t}\\n\\t\\tinitScript(args) {\\n\\t\\t\\t\\tScript.prototype.initScript.call(this, args);\\n\\t\\t\\t\\tthis.__attributes = {};\\n\\t\\t\\t\\tthis.__attributesRaw = args.attributes || {};\\n\\t\\t}\\n\\t\\tinitScriptType(args) {\\n\\t\\t\\t\\tthis.initScript(args);\\n\\t\\t}\\n\\t\\t__initializeAttributes(force) {\\n\\t\\t\\t\\tif (!force && !this.__attributesRaw) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(const key in this.__scriptType.attributes.index){\\n\\t\\t\\t\\t\\t\\tif (this.__attributesRaw && this.__attributesRaw.hasOwnProperty(key)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis[key] = this.__attributesRaw[key];\\n\\t\\t\\t\\t\\t\\t} else if (!this.__attributes.hasOwnProperty(key)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.__scriptType.attributes.index[key].hasOwnProperty('default')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis[key] = this.__scriptType.attributes.index[key].default;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis[key] = null;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.__attributesRaw = null;\\n\\t\\t}\\n\\t\\tstatic extend(methods) {\\n\\t\\t\\t\\tfor(const key in methods){\\n\\t\\t\\t\\t\\t\\tif (!methods.hasOwnProperty(key)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.prototype[key] = methods[key];\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(args){\\n\\t\\t\\t\\tsuper(args);\\n\\t\\t\\t\\tthis.initScriptType(args);\\n\\t\\t}\\n}\\n\\nconst toLowerCamelCase = (str)=>str[0].toLowerCase() + str.substring(1);\\nclass ScriptComponent extends Component {\\n\\t\\tset scripts(value) {\\n\\t\\t\\t\\tthis._scriptsData = value;\\n\\t\\t\\t\\tfor(const key in value){\\n\\t\\t\\t\\t\\t\\tif (!value.hasOwnProperty(key)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst script = this._scriptsIndex[key];\\n\\t\\t\\t\\t\\t\\tif (script) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (typeof value[key].enabled === 'boolean') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscript.once('preInitialize', ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.initializeAttributes(script);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscript.enabled = !!value[key].enabled;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (typeof value[key].attributes === 'object') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(const attr in value[key].attributes){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (ScriptAttributes.reservedNames.has(attr)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!script.__attributes.hasOwnProperty(attr)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst scriptType = this.system.app.scripts.get(key);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (scriptType) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscriptType.attributes.add(attr, {});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscript[attr] = value[key].attributes[attr];\\n\\t\\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} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconsole.log(this.order);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget scripts() {\\n\\t\\t\\t\\treturn this._scripts;\\n\\t\\t}\\n\\t\\tset enabled(value) {\\n\\t\\t\\t\\tconst oldValue = this._enabled;\\n\\t\\t\\t\\tthis._enabled = value;\\n\\t\\t\\t\\tthis.fire('set', 'enabled', oldValue, value);\\n\\t\\t}\\n\\t\\tget enabled() {\\n\\t\\t\\t\\treturn this._enabled;\\n\\t\\t}\\n\\t\\tonEnable() {\\n\\t\\t\\t\\tthis._beingEnabled = true;\\n\\t\\t\\t\\tthis._checkState();\\n\\t\\t\\t\\tif (!this.entity._beingEnabled) {\\n\\t\\t\\t\\t\\t\\tthis.onPostStateChange();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._beingEnabled = false;\\n\\t\\t}\\n\\t\\tonDisable() {\\n\\t\\t\\t\\tthis._checkState();\\n\\t\\t}\\n\\t\\tonPostStateChange() {\\n\\t\\t\\t\\tconst wasLooping = this._beginLooping();\\n\\t\\t\\t\\tfor(let i = 0, len = this.scripts.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst script = this.scripts[i];\\n\\t\\t\\t\\t\\t\\tif (script._initialized && !script._postInitialized && script.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tscript._postInitialized = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (script.postInitialize) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._scriptMethod(script, SCRIPT_POST_INITIALIZE);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._endLooping(wasLooping);\\n\\t\\t}\\n\\t\\t_beginLooping() {\\n\\t\\t\\t\\tconst looping = this._isLoopingThroughScripts;\\n\\t\\t\\t\\tthis._isLoopingThroughScripts = true;\\n\\t\\t\\t\\treturn looping;\\n\\t\\t}\\n\\t\\t_endLooping(wasLoopingBefore) {\\n\\t\\t\\t\\tthis._isLoopingThroughScripts = wasLoopingBefore;\\n\\t\\t\\t\\tif (!this._isLoopingThroughScripts) {\\n\\t\\t\\t\\t\\t\\tthis._removeDestroyedScripts();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onSetEnabled(prop, old, value) {\\n\\t\\t\\t\\tthis._beingEnabled = true;\\n\\t\\t\\t\\tthis._checkState();\\n\\t\\t\\t\\tthis._beingEnabled = false;\\n\\t\\t}\\n\\t\\t_checkState() {\\n\\t\\t\\t\\tconst state = this.enabled && this.entity.enabled;\\n\\t\\t\\t\\tif (state === this._oldState) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._oldState = state;\\n\\t\\t\\t\\tthis.fire(state ? 'enable' : 'disable');\\n\\t\\t\\t\\tthis.fire('state', state);\\n\\t\\t\\t\\tif (state) {\\n\\t\\t\\t\\t\\t\\tthis.system._addComponentToEnabled(this);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.system._removeComponentFromEnabled(this);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst wasLooping = this._beginLooping();\\n\\t\\t\\t\\tfor(let i = 0, len = this.scripts.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst script = this.scripts[i];\\n\\t\\t\\t\\t\\t\\tscript.once('preInitialize', ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.initializeAttributes(script);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tscript.enabled = script._enabled;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._endLooping(wasLooping);\\n\\t\\t}\\n\\t\\t_onBeforeRemove() {\\n\\t\\t\\t\\tthis.fire('remove');\\n\\t\\t\\t\\tconst wasLooping = this._beginLooping();\\n\\t\\t\\t\\tfor(let i = 0; i < this.scripts.length; i++){\\n\\t\\t\\t\\t\\t\\tconst script = this.scripts[i];\\n\\t\\t\\t\\t\\t\\tif (!script) continue;\\n\\t\\t\\t\\t\\t\\tthis.destroy(script.__scriptType.__name);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._endLooping(wasLooping);\\n\\t\\t}\\n\\t\\t_removeDestroyedScripts() {\\n\\t\\t\\t\\tconst len = this._destroyedScripts.length;\\n\\t\\t\\t\\tif (!len) return;\\n\\t\\t\\t\\tfor(let i = 0; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst script = this._destroyedScripts[i];\\n\\t\\t\\t\\t\\t\\tthis._removeScriptInstance(script);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._destroyedScripts.length = 0;\\n\\t\\t\\t\\tthis._resetExecutionOrder(0, this._scripts.length);\\n\\t\\t}\\n\\t\\t_onInitializeAttributes() {\\n\\t\\t\\t\\tfor(let i = 0, len = this.scripts.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst script = this.scripts[i];\\n\\t\\t\\t\\t\\t\\tthis.initializeAttributes(script);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tinitializeAttributes(script) {\\n\\t\\t\\t\\tif (script instanceof ScriptType) {\\n\\t\\t\\t\\t\\t\\tscript.__initializeAttributes();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst name = script.__scriptType.__name;\\n\\t\\t\\t\\t\\t\\tconst data = this._attributeDataMap.get(name);\\n\\t\\t\\t\\t\\t\\tif (!data) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst schema = this.system.app.scripts?.getSchema(name);\\n\\t\\t\\t\\t\\t\\tassignAttributesToScript(this.system.app, schema.attributes, data, script);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_scriptMethod(script, method, arg) {\\n\\t\\t\\t\\tscript[method](arg);\\n\\t\\t}\\n\\t\\t_onInitialize() {\\n\\t\\t\\t\\tconst scripts = this._scripts;\\n\\t\\t\\t\\tconst wasLooping = this._beginLooping();\\n\\t\\t\\t\\tfor(let i = 0, len = scripts.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tconst script = scripts[i];\\n\\t\\t\\t\\t\\t\\tif (!script._initialized && script.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tscript._initialized = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (script.initialize) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._scriptMethod(script, SCRIPT_INITIALIZE);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._endLooping(wasLooping);\\n\\t\\t}\\n\\t\\t_onPostInitialize() {\\n\\t\\t\\t\\tthis.onPostStateChange();\\n\\t\\t}\\n\\t\\t_onUpdate(dt) {\\n\\t\\t\\t\\tconst list = this._updateList;\\n\\t\\t\\t\\tif (!list.length) return;\\n\\t\\t\\t\\tconst wasLooping = this._beginLooping();\\n\\t\\t\\t\\tfor(list.loopIndex = 0; list.loopIndex < list.length; list.loopIndex++){\\n\\t\\t\\t\\t\\t\\tconst script = list.items[list.loopIndex];\\n\\t\\t\\t\\t\\t\\tif (script.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._scriptMethod(script, SCRIPT_UPDATE, dt);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._endLooping(wasLooping);\\n\\t\\t}\\n\\t\\t_onPostUpdate(dt) {\\n\\t\\t\\t\\tconst list = this._postUpdateList;\\n\\t\\t\\t\\tif (!list.length) return;\\n\\t\\t\\t\\tconst wasLooping = this._beginLooping();\\n\\t\\t\\t\\tfor(list.loopIndex = 0; list.loopIndex < list.length; list.loopIndex++){\\n\\t\\t\\t\\t\\t\\tconst script = list.items[list.loopIndex];\\n\\t\\t\\t\\t\\t\\tif (script.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._scriptMethod(script, SCRIPT_POST_UPDATE, dt);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._endLooping(wasLooping);\\n\\t\\t}\\n\\t\\t_insertScriptInstance(scriptInstance, index, scriptsLength) {\\n\\t\\t\\t\\tif (index === -1) {\\n\\t\\t\\t\\t\\t\\tthis._scripts.push(scriptInstance);\\n\\t\\t\\t\\t\\t\\tscriptInstance.__executionOrder = scriptsLength;\\n\\t\\t\\t\\t\\t\\tif (scriptInstance.update) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._updateList.append(scriptInstance);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (scriptInstance.postUpdate) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._postUpdateList.append(scriptInstance);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._scripts.splice(index, 0, scriptInstance);\\n\\t\\t\\t\\t\\t\\tscriptInstance.__executionOrder = index;\\n\\t\\t\\t\\t\\t\\tthis._resetExecutionOrder(index + 1, scriptsLength + 1);\\n\\t\\t\\t\\t\\t\\tif (scriptInstance.update) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._updateList.insert(scriptInstance);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (scriptInstance.postUpdate) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._postUpdateList.insert(scriptInstance);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_removeScriptInstance(scriptInstance) {\\n\\t\\t\\t\\tconst idx = this._scripts.indexOf(scriptInstance);\\n\\t\\t\\t\\tif (idx === -1) return idx;\\n\\t\\t\\t\\tthis._scripts.splice(idx, 1);\\n\\t\\t\\t\\tif (scriptInstance.update) {\\n\\t\\t\\t\\t\\t\\tthis._updateList.remove(scriptInstance);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (scriptInstance.postUpdate) {\\n\\t\\t\\t\\t\\t\\tthis._postUpdateList.remove(scriptInstance);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn idx;\\n\\t\\t}\\n\\t\\t_resetExecutionOrder(startIndex, scriptsLength) {\\n\\t\\t\\t\\tfor(let i = startIndex; i < scriptsLength; i++){\\n\\t\\t\\t\\t\\t\\tthis._scripts[i].__executionOrder = i;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_resolveEntityScriptAttribute(attribute, attributeName, oldValue, useGuid, newAttributes, duplicatedIdsMap) {\\n\\t\\t\\t\\tif (attribute.array) {\\n\\t\\t\\t\\t\\t\\tconst len = oldValue.length;\\n\\t\\t\\t\\t\\t\\tif (!len) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst newGuidArray = oldValue.slice();\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < len; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst guid = newGuidArray[i] instanceof Entity ? newGuidArray[i].getGuid() : newGuidArray[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (duplicatedIdsMap[guid]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnewGuidArray[i] = useGuid ? duplicatedIdsMap[guid].getGuid() : duplicatedIdsMap[guid];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tnewAttributes[attributeName] = newGuidArray;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (oldValue instanceof Entity) {\\n\\t\\t\\t\\t\\t\\t\\t\\toldValue = oldValue.getGuid();\\n\\t\\t\\t\\t\\t\\t} else if (typeof oldValue !== 'string') {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (duplicatedIdsMap[oldValue]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tnewAttributes[attributeName] = duplicatedIdsMap[oldValue];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\thas(nameOrType) {\\n\\t\\t\\t\\tif (typeof nameOrType === 'string') {\\n\\t\\t\\t\\t\\t\\treturn !!this._scriptsIndex[nameOrType];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!nameOrType) return false;\\n\\t\\t\\t\\tconst scriptType = nameOrType;\\n\\t\\t\\t\\tconst scriptName = scriptType.__name;\\n\\t\\t\\t\\tconst scriptData = this._scriptsIndex[scriptName];\\n\\t\\t\\t\\tconst scriptInstance = scriptData && scriptData.instance;\\n\\t\\t\\t\\treturn scriptInstance instanceof scriptType;\\n\\t\\t}\\n\\t\\tget(nameOrType) {\\n\\t\\t\\t\\tif (typeof nameOrType === 'string') {\\n\\t\\t\\t\\t\\t\\tconst data = this._scriptsIndex[nameOrType];\\n\\t\\t\\t\\t\\t\\treturn data ? data.instance : null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!nameOrType) return null;\\n\\t\\t\\t\\tconst scriptType = nameOrType;\\n\\t\\t\\t\\tconst scriptName = scriptType.__name;\\n\\t\\t\\t\\tconst scriptData = this._scriptsIndex[scriptName];\\n\\t\\t\\t\\tconst scriptInstance = scriptData && scriptData.instance;\\n\\t\\t\\t\\treturn scriptInstance instanceof scriptType ? scriptInstance : null;\\n\\t\\t}\\n\\t\\tcreate(nameOrType, args = {}) {\\n\\t\\t\\t\\tconst self = this;\\n\\t\\t\\t\\tlet scriptType = nameOrType;\\n\\t\\t\\t\\tlet scriptName = nameOrType;\\n\\t\\t\\t\\tif (typeof scriptType === 'string') {\\n\\t\\t\\t\\t\\t\\tscriptType = this.system.app.scripts.get(scriptType);\\n\\t\\t\\t\\t} else if (scriptType) {\\n\\t\\t\\t\\t\\t\\tvar _scriptType;\\n\\t\\t\\t\\t\\t\\tconst inferredScriptName = getScriptName(scriptType);\\n\\t\\t\\t\\t\\t\\tconst lowerInferredScriptName = toLowerCamelCase(inferredScriptName);\\n\\t\\t\\t\\t\\t\\tif (!(scriptType.prototype instanceof ScriptType) && !scriptType.scriptName) ;\\n\\t\\t\\t\\t\\t\\t(_scriptType = scriptType).__name ?? (_scriptType.__name = scriptType.scriptName ?? lowerInferredScriptName);\\n\\t\\t\\t\\t\\t\\tscriptName = scriptType.__name;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (scriptType) {\\n\\t\\t\\t\\t\\t\\tif (!this._scriptsIndex[scriptName] || !this._scriptsIndex[scriptName].instance) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst scriptInstance = new scriptType({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tapp: this.system.app,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tentity: this.entity,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tenabled: args.hasOwnProperty('enabled') ? args.enabled : true,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tattributes: args.attributes || {}\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tif (args.properties && typeof args.properties === 'object') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tObject.assign(scriptInstance, args.properties);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!(scriptInstance instanceof ScriptType) && args.attributes) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._attributeDataMap.set(scriptName, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t...args.attributes\\n\\t\\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 len = this._scripts.length;\\n\\t\\t\\t\\t\\t\\t\\t\\tlet ind = -1;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (typeof args.ind === 'number' && args.ind !== -1 && len > args.ind) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tind = args.ind;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._insertScriptInstance(scriptInstance, ind, len);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._scriptsIndex[scriptName] = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinstance: scriptInstance,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tonSwap: function() {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tself.swap(scriptName);\\n\\t\\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\\tthis[scriptName] = scriptInstance;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!args.preloading) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.initializeAttributes(scriptInstance);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('create', scriptName, scriptInstance);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire(`create:${scriptName}`, scriptInstance);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.system.app.scripts.on(`swap:${scriptName}`, this._scriptsIndex[scriptName].onSwap);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!args.preloading) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (scriptInstance.enabled && !scriptInstance._initialized) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscriptInstance._initialized = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (scriptInstance.initialize) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._scriptMethod(scriptInstance, SCRIPT_INITIALIZE);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (scriptInstance.enabled && !scriptInstance._postInitialized) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscriptInstance._postInitialized = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (scriptInstance.postInitialize) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._scriptMethod(scriptInstance, SCRIPT_POST_INITIALIZE);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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\\treturn scriptInstance;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._scriptsIndex[scriptName] = {\\n\\t\\t\\t\\t\\t\\t\\t\\tawaiting: true,\\n\\t\\t\\t\\t\\t\\t\\t\\tind: this._scripts.length\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tdestroy(nameOrType) {\\n\\t\\t\\t\\tlet scriptName = nameOrType;\\n\\t\\t\\t\\tlet scriptType = nameOrType;\\n\\t\\t\\t\\tif (typeof scriptType === 'string') {\\n\\t\\t\\t\\t\\t\\tscriptType = this.system.app.scripts.get(scriptType);\\n\\t\\t\\t\\t} else if (scriptType) {\\n\\t\\t\\t\\t\\t\\tscriptName = scriptType.__name;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst scriptData = this._scriptsIndex[scriptName];\\n\\t\\t\\t\\tdelete this._scriptsIndex[scriptName];\\n\\t\\t\\t\\tif (!scriptData) return false;\\n\\t\\t\\t\\tthis._attributeDataMap.delete(scriptName);\\n\\t\\t\\t\\tconst scriptInstance = scriptData.instance;\\n\\t\\t\\t\\tif (scriptInstance && !scriptInstance._destroyed) {\\n\\t\\t\\t\\t\\t\\tscriptInstance.enabled = false;\\n\\t\\t\\t\\t\\t\\tscriptInstance._destroyed = true;\\n\\t\\t\\t\\t\\t\\tif (!this._isLoopingThroughScripts) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst ind = this._removeScriptInstance(scriptInstance);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (ind >= 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._resetExecutionOrder(ind, this._scripts.length);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._destroyedScripts.push(scriptInstance);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.system.app.scripts.off(`swap:${scriptName}`, scriptData.onSwap);\\n\\t\\t\\t\\tdelete this[scriptName];\\n\\t\\t\\t\\tthis.fire('destroy', scriptName, scriptInstance || null);\\n\\t\\t\\t\\tthis.fire(`destroy:${scriptName}`, scriptInstance || null);\\n\\t\\t\\t\\tif (scriptInstance) {\\n\\t\\t\\t\\t\\t\\tscriptInstance.fire('destroy');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tswap(nameOrType) {\\n\\t\\t\\t\\tlet scriptName = nameOrType;\\n\\t\\t\\t\\tlet scriptType = nameOrType;\\n\\t\\t\\t\\tif (typeof scriptType === 'string') {\\n\\t\\t\\t\\t\\t\\tscriptType = this.system.app.scripts.get(scriptType);\\n\\t\\t\\t\\t} else if (scriptType) {\\n\\t\\t\\t\\t\\t\\tscriptName = scriptType.__name;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst old = this._scriptsIndex[scriptName];\\n\\t\\t\\t\\tif (!old || !old.instance) return false;\\n\\t\\t\\t\\tconst scriptInstanceOld = old.instance;\\n\\t\\t\\t\\tconst ind = this._scripts.indexOf(scriptInstanceOld);\\n\\t\\t\\t\\tconst scriptInstance = new scriptType({\\n\\t\\t\\t\\t\\t\\tapp: this.system.app,\\n\\t\\t\\t\\t\\t\\tentity: this.entity,\\n\\t\\t\\t\\t\\t\\tenabled: scriptInstanceOld.enabled,\\n\\t\\t\\t\\t\\t\\tattributes: scriptInstanceOld.__attributes\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (!scriptInstance.swap) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.initializeAttributes(scriptInstance);\\n\\t\\t\\t\\tthis._scripts[ind] = scriptInstance;\\n\\t\\t\\t\\tthis._scriptsIndex[scriptName].instance = scriptInstance;\\n\\t\\t\\t\\tthis[scriptName] = scriptInstance;\\n\\t\\t\\t\\tscriptInstance.__executionOrder = ind;\\n\\t\\t\\t\\tif (scriptInstanceOld.update) {\\n\\t\\t\\t\\t\\t\\tthis._updateList.remove(scriptInstanceOld);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (scriptInstanceOld.postUpdate) {\\n\\t\\t\\t\\t\\t\\tthis._postUpdateList.remove(scriptInstanceOld);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (scriptInstance.update) {\\n\\t\\t\\t\\t\\t\\tthis._updateList.insert(scriptInstance);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (scriptInstance.postUpdate) {\\n\\t\\t\\t\\t\\t\\tthis._postUpdateList.insert(scriptInstance);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._scriptMethod(scriptInstance, SCRIPT_SWAP, scriptInstanceOld);\\n\\t\\t\\t\\tthis.fire('swap', scriptName, scriptInstance);\\n\\t\\t\\t\\tthis.fire(`swap:${scriptName}`, scriptInstance);\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tresolveDuplicatedEntityReferenceProperties(oldScriptComponent, duplicatedIdsMap) {\\n\\t\\t\\t\\tconst newScriptComponent = this.entity.script;\\n\\t\\t\\t\\tfor(const scriptName in oldScriptComponent._scriptsIndex){\\n\\t\\t\\t\\t\\t\\tconst scriptType = this.system.app.scripts.get(scriptName);\\n\\t\\t\\t\\t\\t\\tif (!scriptType) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst script = oldScriptComponent._scriptsIndex[scriptName];\\n\\t\\t\\t\\t\\t\\tif (!script || !script.instance) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst newAttributesRaw = newScriptComponent[scriptName].__attributesRaw ?? newScriptComponent._attributeDataMap.get(scriptName);\\n\\t\\t\\t\\t\\t\\tconst newAttributes = newScriptComponent[scriptName].__attributes;\\n\\t\\t\\t\\t\\t\\tif (!newAttributesRaw && !newAttributes) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst useGuid = !!newAttributesRaw;\\n\\t\\t\\t\\t\\t\\tconst oldAttributes = script.instance.__attributes ?? newScriptComponent._attributeDataMap.get(scriptName);\\n\\t\\t\\t\\t\\t\\tfor(const attributeName in oldAttributes){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!oldAttributes[attributeName]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst attribute = scriptType.attributes?.get(attributeName) ?? this.system.app.scripts.getSchema(scriptName)?.attributes?.[attributeName];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!attribute) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (attribute.type === 'entity') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._resolveEntityScriptAttribute(attribute, attributeName, oldAttributes[attributeName], useGuid, newAttributesRaw || newAttributes, duplicatedIdsMap);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else if (attribute.type === 'json' && Array.isArray(attribute.schema)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst oldValue = oldAttributes[attributeName];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst newJsonValue = newAttributesRaw ? newAttributesRaw[attributeName] : newAttributes[attributeName];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < attribute.schema.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst field = attribute.schema[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (field.type !== 'entity') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (attribute.array) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < oldValue.length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._resolveEntityScriptAttribute(field, field.name, oldValue[j][field.name], useGuid, newJsonValue[j], duplicatedIdsMap);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._resolveEntityScriptAttribute(field, field.name, oldValue[field.name], useGuid, newJsonValue, duplicatedIdsMap);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tmove(nameOrType, ind) {\\n\\t\\t\\t\\tconst len = this._scripts.length;\\n\\t\\t\\t\\tif (ind >= len || ind < 0) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet scriptType = nameOrType;\\n\\t\\t\\t\\tlet scriptName = nameOrType;\\n\\t\\t\\t\\tif (typeof scriptName !== 'string') {\\n\\t\\t\\t\\t\\t\\tscriptName = nameOrType.__name;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tscriptType = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst scriptData = this._scriptsIndex[scriptName];\\n\\t\\t\\t\\tif (!scriptData || !scriptData.instance) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst scriptInstance = scriptData.instance;\\n\\t\\t\\t\\tif (scriptType && !(scriptInstance instanceof scriptType)) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst indOld = this._scripts.indexOf(scriptInstance);\\n\\t\\t\\t\\tif (indOld === -1 || indOld === ind) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._scripts.splice(ind, 0, this._scripts.splice(indOld, 1)[0]);\\n\\t\\t\\t\\tthis._resetExecutionOrder(0, len);\\n\\t\\t\\t\\tthis._updateList.sort();\\n\\t\\t\\t\\tthis._postUpdateList.sort();\\n\\t\\t\\t\\tthis.fire('move', scriptName, scriptInstance, ind, indOld);\\n\\t\\t\\t\\tthis.fire(`move:${scriptName}`, scriptInstance, ind, indOld);\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tconstructor(system, entity){\\n\\t\\t\\t\\tsuper(system, entity), this._attributeDataMap = new Map();\\n\\t\\t\\t\\tthis._scripts = [];\\n\\t\\t\\t\\tthis._updateList = new SortedLoopArray({\\n\\t\\t\\t\\t\\t\\tsortBy: '__executionOrder'\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis._postUpdateList = new SortedLoopArray({\\n\\t\\t\\t\\t\\t\\tsortBy: '__executionOrder'\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis._scriptsIndex = {};\\n\\t\\t\\t\\tthis._destroyedScripts = [];\\n\\t\\t\\t\\tthis._destroyed = false;\\n\\t\\t\\t\\tthis._scriptsData = null;\\n\\t\\t\\t\\tthis._oldState = true;\\n\\t\\t\\t\\tthis._enabled = true;\\n\\t\\t\\t\\tthis._beingEnabled = false;\\n\\t\\t\\t\\tthis._isLoopingThroughScripts = false;\\n\\t\\t\\t\\tthis._executionOrder = -1;\\n\\t\\t\\t\\tthis.on('set_enabled', this._onSetEnabled, this);\\n\\t\\t}\\n}\\nScriptComponent.EVENT_CREATE = 'create';\\nScriptComponent.EVENT_DESTROY = 'destroy';\\nScriptComponent.EVENT_ENABLE = 'enable';\\nScriptComponent.EVENT_DISABLE = 'disable';\\nScriptComponent.EVENT_REMOVE = 'remove';\\nScriptComponent.EVENT_STATE = 'state';\\nScriptComponent.EVENT_MOVE = 'move';\\nScriptComponent.EVENT_ERROR = 'error';\\n\\nclass ScriptComponentData {\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.enabled = true;\\n\\t\\t}\\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\\t\\tinitializeComponentData(component, data) {\\n\\t\\t\\t\\tcomponent._executionOrder = executionOrderCounter++;\\n\\t\\t\\t\\tthis._components.append(component);\\n\\t\\t\\t\\tif (executionOrderCounter > Number.MAX_SAFE_INTEGER) {\\n\\t\\t\\t\\t\\t\\tthis._resetExecutionOrder();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcomponent.enabled = data.hasOwnProperty('enabled') ? !!data.enabled : true;\\n\\t\\t\\t\\tif (component.enabled && component.entity.enabled) {\\n\\t\\t\\t\\t\\t\\tthis._enabledComponents.append(component);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (data.hasOwnProperty('order') && data.hasOwnProperty(\\\"scripts\\\")) {\\n\\t\\t\\t\\t\\t\\tcomponent._scriptsData = data.scripts;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < data.order.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponent.create(data.order[i], {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tenabled: data.scripts[data.order[i]].enabled,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tattributes: data.scripts[data.order[i]].attributes,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpreloading: this.preloading\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcloneComponent(entity, clone) {\\n\\t\\t\\t\\tconst order = [];\\n\\t\\t\\t\\tconst scripts = {};\\n\\t\\t\\t\\tfor(let i = 0; i < entity.script._scripts.length; i++){\\n\\t\\t\\t\\t\\t\\tconst scriptInstance = entity.script._scripts[i];\\n\\t\\t\\t\\t\\t\\tconst scriptName = scriptInstance.__scriptType.__name;\\n\\t\\t\\t\\t\\t\\torder.push(scriptName);\\n\\t\\t\\t\\t\\t\\tconst attributes = entity.script._attributeDataMap?.get(scriptName) || {};\\n\\t\\t\\t\\t\\t\\tfor(const key in scriptInstance.__attributes){\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes[key] = scriptInstance.__attributes[key];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tscripts[scriptName] = {\\n\\t\\t\\t\\t\\t\\t\\t\\tenabled: scriptInstance._enabled,\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes: attributes\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(const key in entity.script._scriptsIndex){\\n\\t\\t\\t\\t\\t\\tif (key.awaiting) {\\n\\t\\t\\t\\t\\t\\t\\t\\torder.splice(key.ind, 0, key);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst data = {\\n\\t\\t\\t\\t\\t\\tenabled: entity.script.enabled,\\n\\t\\t\\t\\t\\t\\torder: order,\\n\\t\\t\\t\\t\\t\\tscripts: scripts\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\treturn this.addComponent(clone, data);\\n\\t\\t}\\n\\t\\t_resetExecutionOrder() {\\n\\t\\t\\t\\texecutionOrderCounter = 0;\\n\\t\\t\\t\\tfor(let i = 0, len = this._components.length; i < len; i++){\\n\\t\\t\\t\\t\\t\\tthis._components.items[i]._executionOrder = executionOrderCounter++;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_callComponentMethod(components, name, dt) {\\n\\t\\t\\t\\tfor(components.loopIndex = 0; components.loopIndex < components.length; components.loopIndex++){\\n\\t\\t\\t\\t\\t\\tcomponents.items[components.loopIndex][name](dt);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onInitialize() {\\n\\t\\t\\t\\tthis.preloading = false;\\n\\t\\t\\t\\tthis._callComponentMethod(this._components, METHOD_INITIALIZE_ATTRIBUTES);\\n\\t\\t\\t\\tthis._callComponentMethod(this._enabledComponents, METHOD_INITIALIZE);\\n\\t\\t}\\n\\t\\t_onPostInitialize() {\\n\\t\\t\\t\\tthis._callComponentMethod(this._enabledComponents, METHOD_POST_INITIALIZE);\\n\\t\\t}\\n\\t\\t_onUpdate(dt) {\\n\\t\\t\\t\\tthis._callComponentMethod(this._enabledComponents, METHOD_UPDATE, dt);\\n\\t\\t}\\n\\t\\t_onPostUpdate(dt) {\\n\\t\\t\\t\\tthis._callComponentMethod(this._enabledComponents, METHOD_POST_UPDATE, dt);\\n\\t\\t}\\n\\t\\t_addComponentToEnabled(component) {\\n\\t\\t\\t\\tthis._enabledComponents.insert(component);\\n\\t\\t}\\n\\t\\t_removeComponentFromEnabled(component) {\\n\\t\\t\\t\\tthis._enabledComponents.remove(component);\\n\\t\\t}\\n\\t\\t_onBeforeRemove(entity, component) {\\n\\t\\t\\t\\tconst ind = this._components.items.indexOf(component);\\n\\t\\t\\t\\tif (ind >= 0) {\\n\\t\\t\\t\\t\\t\\tcomponent._onBeforeRemove();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._removeComponentFromEnabled(component);\\n\\t\\t\\t\\tthis._components.remove(component);\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tsuper.destroy();\\n\\t\\t\\t\\tthis.app.systems.off('initialize', this._onInitialize, this);\\n\\t\\t\\t\\tthis.app.systems.off('postInitialize', this._onPostInitialize, this);\\n\\t\\t\\t\\tthis.app.systems.off('update', this._onUpdate, this);\\n\\t\\t\\t\\tthis.app.systems.off('postUpdate', this._onPostUpdate, this);\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tsuper(app);\\n\\t\\t\\t\\tthis.id = \\\"script\\\";\\n\\t\\t\\t\\tthis.ComponentType = ScriptComponent;\\n\\t\\t\\t\\tthis.DataType = ScriptComponentData;\\n\\t\\t\\t\\tthis._components = new SortedLoopArray({\\n\\t\\t\\t\\t\\t\\tsortBy: '_executionOrder'\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis._enabledComponents = new SortedLoopArray({\\n\\t\\t\\t\\t\\t\\tsortBy: '_executionOrder'\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.preloading = true;\\n\\t\\t\\t\\tthis.on('beforeremove', this._onBeforeRemove, this);\\n\\t\\t\\t\\tthis.app.systems.on('initialize', this._onInitialize, this);\\n\\t\\t\\t\\tthis.app.systems.on('postInitialize', this._onPostInitialize, this);\\n\\t\\t\\t\\tthis.app.systems.on('update', this._onUpdate, this);\\n\\t\\t\\t\\tthis.app.systems.on('postUpdate', this._onPostUpdate, this);\\n\\t\\t}\\n}\\n\\nvar gsplatIntervalTextureGLSL = `\\nprecision highp usampler2D;\\nuniform usampler2D uIntervalsTexture;\\nuniform int uNumIntervals;\\nuniform int uTextureWidth;\\nuniform int uActiveSplats;\\nivec2 getCoordFromIndex(int index, int textureWidth) {\\n\\treturn ivec2(index % textureWidth, index / textureWidth);\\n}\\nvoid main() {\\n\\tivec2 coord = ivec2(gl_FragCoord.xy);\\n\\tint targetIndex = coord.y * uTextureWidth + coord.x;\\n\\t\\n\\tif (targetIndex >= uActiveSplats) {\\n\\t\\tgl_FragColor = 0u;\\n\\t\\treturn;\\n\\t}\\n\\t\\n\\tint left = 0;\\n\\tint right = uNumIntervals - 1;\\n\\tint intervalIndex = 0;\\n\\t\\n\\twhile (left <= right) {\\n\\t\\tint mid = (left + right) / 2;\\n\\t\\t\\n\\t\\tint textureWidth = textureSize(uIntervalsTexture, 0).x;\\n\\t\\tivec2 intervalCoord = getCoordFromIndex(mid, textureWidth);\\n\\t\\tuvec2 intervalData = texelFetch(uIntervalsTexture, intervalCoord, 0).rg;\\n\\t\\t\\n\\t\\tuint accumulatedSum = intervalData.g;\\n\\t\\t\\n\\t\\tif (uint(targetIndex) < accumulatedSum) {\\n\\t\\t\\tintervalIndex = mid;\\n\\t\\t\\tright = mid - 1;\\n\\t\\t} else {\\n\\t\\t\\tleft = mid + 1;\\n\\t\\t}\\n\\t}\\n\\t\\n\\tint textureWidth = textureSize(uIntervalsTexture, 0).x;\\n\\tivec2 intervalCoord = getCoordFromIndex(intervalIndex, textureWidth);\\n\\tuvec2 intervalData = texelFetch(uIntervalsTexture, intervalCoord, 0).rg;\\n\\t\\n\\tuint intervalStart = intervalData.r;\\n\\tuint currentAccSum = intervalData.g;\\n\\t\\n\\tuint prevAccSum = 0u;\\n\\tif (intervalIndex > 0) {\\n\\t\\tivec2 prevCoord = getCoordFromIndex(intervalIndex - 1, textureWidth);\\n\\t\\tprevAccSum = texelFetch(uIntervalsTexture, prevCoord, 0).g;\\n\\t}\\n\\t\\n\\tuint offsetInInterval = uint(targetIndex) - prevAccSum;\\n\\tuint originalIndex = intervalStart + offsetInInterval;\\n\\t\\n\\tgl_FragColor = originalIndex;\\n}\\n`;\\n\\nvar gsplatIntervalTextureWGSL = `\\nvar uIntervalsTexture: texture_2d<u32>;\\nuniform uNumIntervals: i32;\\nuniform uTextureWidth: i32;\\nuniform uActiveSplats: i32;\\nfn getCoordFromIndex(index: i32, textureWidth: i32) -> vec2i {\\n\\treturn vec2i(index % textureWidth, index / textureWidth);\\n}\\n@fragment\\nfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\tvar output: FragmentOutput;\\n\\t\\n\\tlet coord = vec2i(i32(input.position.x), i32(input.position.y));\\n\\tlet targetIndex = coord.y * uniform.uTextureWidth + coord.x;\\n\\t\\n\\tif (targetIndex >= uniform.uActiveSplats) {\\n\\t\\toutput.color = 0u;\\n\\t\\treturn output;\\n\\t}\\n\\t\\n\\tvar left = 0i;\\n\\tvar right = uniform.uNumIntervals - 1;\\n\\tvar intervalIndex = 0i;\\n\\t\\n\\twhile (left <= right) {\\n\\t\\tlet mid = (left + right) / 2;\\n\\t\\t\\n\\t\\tlet textureWidth = i32(textureDimensions(uIntervalsTexture, 0).x);\\n\\t\\tlet intervalCoord = getCoordFromIndex(mid, textureWidth);\\n\\t\\tlet intervalData = textureLoad(uIntervalsTexture, intervalCoord, 0).rg;\\n\\t\\t\\n\\t\\tlet accumulatedSum = intervalData.g;\\n\\t\\t\\n\\t\\tif (u32(targetIndex) < accumulatedSum) {\\n\\t\\t\\tintervalIndex = mid;\\n\\t\\t\\tright = mid - 1;\\n\\t\\t} else {\\n\\t\\t\\tleft = mid + 1;\\n\\t\\t}\\n\\t}\\n\\t\\n\\tlet textureWidth = i32(textureDimensions(uIntervalsTexture, 0).x);\\n\\tlet intervalCoord = getCoordFromIndex(intervalIndex, textureWidth);\\n\\tlet intervalData = textureLoad(uIntervalsTexture, intervalCoord, 0).rg;\\n\\t\\n\\tlet intervalStart = intervalData.r;\\n\\tlet currentAccSum = intervalData.g;\\n\\t\\n\\tvar prevAccSum = 0u;\\n\\tif (intervalIndex > 0) {\\n\\t\\tlet prevCoord = getCoordFromIndex(intervalIndex - 1, textureWidth);\\n\\t\\tprevAccSum = textureLoad(uIntervalsTexture, prevCoord, 0).g;\\n\\t}\\n\\t\\n\\tlet offsetInInterval = u32(targetIndex) - prevAccSum;\\n\\tlet originalIndex = intervalStart + offsetInInterval;\\n\\t\\n\\toutput.color = originalIndex;\\n\\treturn output;\\n}\\n`;\\n\\nclass GSplatIntervalTexture {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.texture?.destroy();\\n\\t\\t\\t\\tthis.texture = null;\\n\\t\\t\\t\\tthis.rt?.destroy();\\n\\t\\t\\t\\tthis.rt = null;\\n\\t\\t\\t\\tthis.intervalsDataTexture?.destroy();\\n\\t\\t\\t\\tthis.intervalsDataTexture = null;\\n\\t\\t\\t\\tthis.shader = null;\\n\\t\\t}\\n\\t\\tgetShader() {\\n\\t\\t\\t\\tif (!this.shader) {\\n\\t\\t\\t\\t\\t\\tthis.shader = ShaderUtils.createShader(this.device, {\\n\\t\\t\\t\\t\\t\\t\\t\\tuniqueName: 'GSplatIntervalsShader',\\n\\t\\t\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taPosition: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t\\t\\tvertexChunk: 'quadVS',\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentGLSL: gsplatIntervalTextureGLSL,\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentWGSL: gsplatIntervalTextureWGSL,\\n\\t\\t\\t\\t\\t\\t\\t\\tfragmentOutputTypes: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t'uint'\\n\\t\\t\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.shader;\\n\\t\\t}\\n\\t\\tcreateTexture(name, format, width, height) {\\n\\t\\t\\t\\treturn new Texture(this.device, {\\n\\t\\t\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\t\\t\\twidth: width,\\n\\t\\t\\t\\t\\t\\theight: height,\\n\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\tcubemap: false,\\n\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tupdate(intervals, totalIntervalSplats) {\\n\\t\\t\\t\\tconst maxTextureSize = this.device.maxTextureSize;\\n\\t\\t\\t\\tlet textureWidth = Math.ceil(Math.sqrt(totalIntervalSplats));\\n\\t\\t\\t\\ttextureWidth = Math.min(textureWidth, maxTextureSize);\\n\\t\\t\\t\\tconst textureHeight = Math.ceil(totalIntervalSplats / textureWidth);\\n\\t\\t\\t\\tthis.texture = this.createTexture('intervalsTexture', PIXELFORMAT_R32U, textureWidth, textureHeight);\\n\\t\\t\\t\\tthis.rt = new RenderTarget({\\n\\t\\t\\t\\t\\t\\tcolorBuffer: this.texture,\\n\\t\\t\\t\\t\\t\\tdepth: false\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst numIntervals = intervals.length / 2;\\n\\t\\t\\t\\tconst dataTextureSize = Math.ceil(Math.sqrt(numIntervals));\\n\\t\\t\\t\\tthis.intervalsDataTexture = this.createTexture('intervalsData', PIXELFORMAT_RG32U, dataTextureSize, dataTextureSize);\\n\\t\\t\\t\\tconst intervalsData = this.intervalsDataTexture.lock();\\n\\t\\t\\t\\tlet runningSum = 0;\\n\\t\\t\\t\\tfor(let i = 0; i < numIntervals; i++){\\n\\t\\t\\t\\t\\t\\tconst start = intervals[i * 2];\\n\\t\\t\\t\\t\\t\\tconst end = intervals[i * 2 + 1];\\n\\t\\t\\t\\t\\t\\tconst intervalSize = end - start;\\n\\t\\t\\t\\t\\t\\trunningSum += intervalSize;\\n\\t\\t\\t\\t\\t\\tintervalsData[i * 2] = start;\\n\\t\\t\\t\\t\\t\\tintervalsData[i * 2 + 1] = runningSum;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.intervalsDataTexture.unlock();\\n\\t\\t\\t\\tconst scope = this.device.scope;\\n\\t\\t\\t\\tscope.resolve('uIntervalsTexture').setValue(this.intervalsDataTexture);\\n\\t\\t\\t\\tscope.resolve('uNumIntervals').setValue(numIntervals);\\n\\t\\t\\t\\tscope.resolve('uTextureWidth').setValue(textureWidth);\\n\\t\\t\\t\\tscope.resolve('uActiveSplats').setValue(totalIntervalSplats);\\n\\t\\t\\t\\tthis.device.setCullMode(CULLFACE_NONE);\\n\\t\\t\\t\\tthis.device.setBlendState(BlendState.NOBLEND);\\n\\t\\t\\t\\tthis.device.setDepthState(DepthState.NODEPTH);\\n\\t\\t\\t\\tdrawQuadWithShader(this.device, this.rt, this.getShader());\\n\\t\\t\\t\\treturn totalIntervalSplats;\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis.texture = null;\\n\\t\\t\\t\\tthis.rt = null;\\n\\t\\t\\t\\tthis.intervalsDataTexture = null;\\n\\t\\t\\t\\tthis.shader = null;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t}\\n}\\n\\nconst vecs = [];\\nclass GSplatInfo {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.intervals.length = 0;\\n\\t\\t\\t\\tthis.intervalTexture?.destroy();\\n\\t\\t}\\n\\t\\tsetLines(start, count, textureSize, activeSplats) {\\n\\t\\t\\t\\tthis.lineStart = start;\\n\\t\\t\\t\\tthis.lineCount = count;\\n\\t\\t\\t\\tthis.padding = textureSize * count - activeSplats;\\n\\t\\t\\t\\tthis.viewport.set(0, start, textureSize, count);\\n\\t\\t}\\n\\t\\tupdateIntervals(intervals) {\\n\\t\\t\\t\\tconst resource = this.resource;\\n\\t\\t\\t\\tthis.intervals.length = 0;\\n\\t\\t\\t\\tthis.activeSplats = resource.numSplats;\\n\\t\\t\\t\\tif (intervals.size > 0) {\\n\\t\\t\\t\\t\\t\\tlet totalCount = 0;\\n\\t\\t\\t\\t\\t\\tlet used = 0;\\n\\t\\t\\t\\t\\t\\tfor (const interval of intervals.values()){\\n\\t\\t\\t\\t\\t\\t\\t\\ttotalCount += interval.y - interval.x + 1;\\n\\t\\t\\t\\t\\t\\t\\t\\tvecs[used++] = interval;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (totalCount !== this.numSplats) {\\n\\t\\t\\t\\t\\t\\t\\t\\tvecs.length = used;\\n\\t\\t\\t\\t\\t\\t\\t\\tvecs.sort((a, b)=>a.x - b.x);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.intervals.length = used * 2;\\n\\t\\t\\t\\t\\t\\t\\t\\tlet k = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tlet currentStart = vecs[0].x;\\n\\t\\t\\t\\t\\t\\t\\t\\tlet currentEnd = vecs[0].y;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 1; i < used; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst p = vecs[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (p.x === currentEnd + 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcurrentEnd = p.y;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.intervals[k++] = currentStart;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.intervals[k++] = currentEnd + 1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcurrentStart = p.x;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcurrentEnd = p.y;\\n\\t\\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\\tthis.intervals[k++] = currentStart;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.intervals[k++] = currentEnd + 1;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.intervals.length = k;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.intervalTexture = new GSplatIntervalTexture(this.device);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.activeSplats = this.intervalTexture.update(this.intervals, totalCount);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tvecs.length = 0;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst totalCenters = resource.centers?.length / 3;\\n\\t\\t\\t\\t\\t\\tif (totalCenters && this.activeSplats < totalCenters) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.intervals[0] = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.intervals[1] = this.activeSplats;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdate() {\\n\\t\\t\\t\\tconst worldMatrix = this.node.getWorldTransform();\\n\\t\\t\\t\\tconst worldMatrixChanged = !this.previousWorldTransform.equals(worldMatrix);\\n\\t\\t\\t\\tif (worldMatrixChanged) {\\n\\t\\t\\t\\t\\t\\tthis.previousWorldTransform.copy(worldMatrix);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst renderDirty = this._consumeRenderDirty ? this._consumeRenderDirty() : false;\\n\\t\\t\\t\\treturn worldMatrixChanged || renderDirty;\\n\\t\\t}\\n\\t\\tresetColorAccumulators(colorUpdateAngle, colorUpdateDistance) {\\n\\t\\t\\t\\tconst randomFactor = Math.random();\\n\\t\\t\\t\\tthis.colorAccumulatedRotation = randomFactor * colorUpdateAngle;\\n\\t\\t\\t\\tthis.colorAccumulatedTranslation = randomFactor * colorUpdateDistance;\\n\\t\\t}\\n\\t\\tget hasSphericalHarmonics() {\\n\\t\\t\\t\\treturn this.resource.gsplatData?.shBands > 0;\\n\\t\\t}\\n\\t\\tconstructor(device, resource, placement, consumeRenderDirty = null){\\n\\t\\t\\t\\tthis.activeSplats = 0;\\n\\t\\t\\t\\tthis.intervals = [];\\n\\t\\t\\t\\tthis.lineStart = 0;\\n\\t\\t\\t\\tthis.lineCount = 0;\\n\\t\\t\\t\\tthis.padding = 0;\\n\\t\\t\\t\\tthis.viewport = new Vec4();\\n\\t\\t\\t\\tthis.previousWorldTransform = new Mat4();\\n\\t\\t\\t\\tthis.aabb = new BoundingBox();\\n\\t\\t\\t\\tthis.intervalTexture = null;\\n\\t\\t\\t\\tthis.colorAccumulatedRotation = 0;\\n\\t\\t\\t\\tthis.colorAccumulatedTranslation = 0;\\n\\t\\t\\t\\tthis.parameters = null;\\n\\t\\t\\t\\tthis.getWorkBufferModifier = null;\\n\\t\\t\\t\\tthis.getInstanceStreams = null;\\n\\t\\t\\t\\tthis._consumeRenderDirty = null;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.resource = resource;\\n\\t\\t\\t\\tthis.node = placement.node;\\n\\t\\t\\t\\tthis.lodIndex = placement.lodIndex;\\n\\t\\t\\t\\tthis.placementId = placement.id;\\n\\t\\t\\t\\tthis.numSplats = resource.numSplats;\\n\\t\\t\\t\\tthis.aabb.copy(placement.aabb);\\n\\t\\t\\t\\tthis.parameters = placement.parameters;\\n\\t\\t\\t\\tthis.getWorkBufferModifier = ()=>placement.workBufferModifier;\\n\\t\\t\\t\\tthis.getInstanceStreams = ()=>placement.streams;\\n\\t\\t\\t\\tthis._consumeRenderDirty = consumeRenderDirty;\\n\\t\\t\\t\\tthis.updateIntervals(placement.intervals);\\n\\t\\t}\\n}\\n\\nfunction UnifiedSortWorker() {\\n\\t\\tconst myself = typeof self !== 'undefined' && self || require('node:worker_threads').parentPort;\\n\\t\\tconst centersMap = new Map();\\n\\t\\tlet centersData;\\n\\t\\tlet distances;\\n\\t\\tlet countBuffer;\\n\\t\\tlet _radialSort = false;\\n\\t\\tlet _warnedSortKeyOverflow = false;\\n\\t\\tconst numBins = 32;\\n\\t\\tconst binBase = new Float32Array(numBins + 1);\\n\\t\\tconst binDivider = new Float32Array(numBins + 1);\\n\\t\\tconst binWeightsUtil = new GSplatSortBinWeights();\\n\\t\\tconst unpackBinWeights = (binWeights)=>{\\n\\t\\t\\t\\tfor(let i = 0; i < numBins; i++){\\n\\t\\t\\t\\t\\t\\tbinBase[i] = binWeights[i * 2];\\n\\t\\t\\t\\t\\t\\tbinDivider[i] = binWeights[i * 2 + 1];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tbinBase[numBins] = binBase[numBins - 1] + binDivider[numBins - 1];\\n\\t\\t\\t\\tbinDivider[numBins] = 0;\\n\\t\\t};\\n\\t\\tconst evaluateSortKeysCommon = (sortParams, minDist, range, distances, countBuffer, centersData, processSplatFn)=>{\\n\\t\\t\\t\\tconst { ids, lineStarts, padding, intervals, textureSize } = centersData;\\n\\t\\t\\t\\tconst invBinRange = numBins / range;\\n\\t\\t\\t\\tfor(let paramIdx = 0; paramIdx < sortParams.length; paramIdx++){\\n\\t\\t\\t\\t\\t\\tconst params = sortParams[paramIdx];\\n\\t\\t\\t\\t\\t\\tconst id = ids[paramIdx];\\n\\t\\t\\t\\t\\t\\tconst centers = centersMap.get(id);\\n\\t\\t\\t\\t\\t\\tif (!centers) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconsole.error('UnifiedSortWorker: No centers found for id', id);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlet targetIndex = lineStarts[paramIdx] * textureSize;\\n\\t\\t\\t\\t\\t\\tconst intervalsArray = intervals[paramIdx].length > 0 ? intervals[paramIdx] : [\\n\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\tcenters.length / 3\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < intervalsArray.length; i += 2){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst intervalStart = intervalsArray[i] * 3;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst intervalEnd = intervalsArray[i + 1] * 3;\\n\\t\\t\\t\\t\\t\\t\\t\\ttargetIndex = processSplatFn(centers, params, intervalStart, intervalEnd, targetIndex, invBinRange, minDist, range, distances, countBuffer);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst pad = padding[paramIdx];\\n\\t\\t\\t\\t\\t\\tcountBuffer[0] += pad;\\n\\t\\t\\t\\t\\t\\tdistances.fill(0, targetIndex, targetIndex + pad);\\n\\t\\t\\t\\t\\t\\ttargetIndex += pad;\\n\\t\\t\\t\\t}\\n\\t\\t};\\n\\t\\tconst evaluateSortKeysLinear = (sortParams, minDist, range, distances, countBuffer, centersData)=>{\\n\\t\\t\\t\\tevaluateSortKeysCommon(sortParams, minDist, range, distances, countBuffer, centersData, (centers, params, intervalStart, intervalEnd, targetIndex, invBinRange, minDist, range, distances, countBuffer)=>{\\n\\t\\t\\t\\t\\t\\tconst { transformedDirection, offset, scale } = params;\\n\\t\\t\\t\\t\\t\\tconst dx = transformedDirection.x;\\n\\t\\t\\t\\t\\t\\tconst dy = transformedDirection.y;\\n\\t\\t\\t\\t\\t\\tconst dz = transformedDirection.z;\\n\\t\\t\\t\\t\\t\\tconst sdx = dx * scale;\\n\\t\\t\\t\\t\\t\\tconst sdy = dy * scale;\\n\\t\\t\\t\\t\\t\\tconst sdz = dz * scale;\\n\\t\\t\\t\\t\\t\\tconst add = offset - minDist;\\n\\t\\t\\t\\t\\t\\tfor(let srcIndex = intervalStart; srcIndex < intervalEnd; srcIndex += 3){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst x = centers[srcIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst y = centers[srcIndex + 1];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst z = centers[srcIndex + 2];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dist = x * sdx + y * sdy + z * sdz + add;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst d = dist * invBinRange;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst bin = d >>> 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst sortKey = binBase[bin] + binDivider[bin] * (d - bin) >>> 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tdistances[targetIndex++] = sortKey;\\n\\t\\t\\t\\t\\t\\t\\t\\tcountBuffer[sortKey]++;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn targetIndex;\\n\\t\\t\\t\\t});\\n\\t\\t};\\n\\t\\tconst evaluateSortKeysRadial = (sortParams, minDist, range, distances, countBuffer, centersData)=>{\\n\\t\\t\\t\\tevaluateSortKeysCommon(sortParams, minDist, range, distances, countBuffer, centersData, (centers, params, intervalStart, intervalEnd, targetIndex, invBinRange, minDist, range, distances, countBuffer)=>{\\n\\t\\t\\t\\t\\t\\tconst { transformedPosition, scale } = params;\\n\\t\\t\\t\\t\\t\\tconst cx = transformedPosition.x;\\n\\t\\t\\t\\t\\t\\tconst cy = transformedPosition.y;\\n\\t\\t\\t\\t\\t\\tconst cz = transformedPosition.z;\\n\\t\\t\\t\\t\\t\\tfor(let srcIndex = intervalStart; srcIndex < intervalEnd; srcIndex += 3){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dx = centers[srcIndex] - cx;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dy = centers[srcIndex + 1] - cy;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dz = centers[srcIndex + 2] - cz;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst distSq = dx * dx + dy * dy + dz * dz;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dist = Math.sqrt(distSq) * scale;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst invertedDist = range - dist;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst d = invertedDist * invBinRange;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst bin = d >>> 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst sortKey = binBase[bin] + binDivider[bin] * (d - bin) >>> 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tdistances[targetIndex++] = sortKey;\\n\\t\\t\\t\\t\\t\\t\\t\\tcountBuffer[sortKey]++;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn targetIndex;\\n\\t\\t\\t\\t});\\n\\t\\t};\\n\\t\\tconst countingSort = (bucketCount, countBuffer, numVertices, distances, order)=>{\\n\\t\\t\\t\\tfor(let i = 1; i < bucketCount; i++){\\n\\t\\t\\t\\t\\t\\tcountBuffer[i] += countBuffer[i - 1];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst validCount = countBuffer[bucketCount - 1];\\n\\t\\t\\t\\tif (validCount !== numVertices && !_warnedSortKeyOverflow) {\\n\\t\\t\\t\\t\\t\\t_warnedSortKeyOverflow = true;\\n\\t\\t\\t\\t\\t\\tconsole.warn(`[SortWorker] ${numVertices - validCount} splats lost due to sortKey overflow. Check resource AABB bounds contain all the splats.`);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < numVertices; i++){\\n\\t\\t\\t\\t\\t\\tconst distance = distances[i];\\n\\t\\t\\t\\t\\t\\tconst destIndex = --countBuffer[distance];\\n\\t\\t\\t\\t\\t\\torder[destIndex] = i;\\n\\t\\t\\t\\t}\\n\\t\\t};\\n\\t\\tconst computeEffectiveDistanceRangeLinear = (sortParams)=>{\\n\\t\\t\\t\\tlet minDist = Infinity;\\n\\t\\t\\t\\tlet maxDist = -Infinity;\\n\\t\\t\\t\\tfor(let paramIdx = 0; paramIdx < sortParams.length; paramIdx++){\\n\\t\\t\\t\\t\\t\\tconst params = sortParams[paramIdx];\\n\\t\\t\\t\\t\\t\\tconst { transformedDirection, offset, scale, aabbMin, aabbMax } = params;\\n\\t\\t\\t\\t\\t\\tconst dx = transformedDirection.x;\\n\\t\\t\\t\\t\\t\\tconst dy = transformedDirection.y;\\n\\t\\t\\t\\t\\t\\tconst dz = transformedDirection.z;\\n\\t\\t\\t\\t\\t\\tconst pxMin = dx >= 0 ? aabbMin[0] : aabbMax[0];\\n\\t\\t\\t\\t\\t\\tconst pyMin = dy >= 0 ? aabbMin[1] : aabbMax[1];\\n\\t\\t\\t\\t\\t\\tconst pzMin = dz >= 0 ? aabbMin[2] : aabbMax[2];\\n\\t\\t\\t\\t\\t\\tconst pxMax = dx >= 0 ? aabbMax[0] : aabbMin[0];\\n\\t\\t\\t\\t\\t\\tconst pyMax = dy >= 0 ? aabbMax[1] : aabbMin[1];\\n\\t\\t\\t\\t\\t\\tconst pzMax = dz >= 0 ? aabbMax[2] : aabbMin[2];\\n\\t\\t\\t\\t\\t\\tconst dMin = pxMin * dx + pyMin * dy + pzMin * dz;\\n\\t\\t\\t\\t\\t\\tconst dMax = pxMax * dx + pyMax * dy + pzMax * dz;\\n\\t\\t\\t\\t\\t\\tconst eMin = dMin * scale + offset;\\n\\t\\t\\t\\t\\t\\tconst eMax = dMax * scale + offset;\\n\\t\\t\\t\\t\\t\\tconst localMin = Math.min(eMin, eMax);\\n\\t\\t\\t\\t\\t\\tconst localMax = Math.max(eMin, eMax);\\n\\t\\t\\t\\t\\t\\tif (localMin < minDist) minDist = localMin;\\n\\t\\t\\t\\t\\t\\tif (localMax > maxDist) maxDist = localMax;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (minDist === Infinity) {\\n\\t\\t\\t\\t\\t\\tminDist = 0;\\n\\t\\t\\t\\t\\t\\tmaxDist = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tminDist,\\n\\t\\t\\t\\t\\t\\tmaxDist\\n\\t\\t\\t\\t};\\n\\t\\t};\\n\\t\\tconst computeEffectiveDistanceRangeRadial = (sortParams)=>{\\n\\t\\t\\t\\tlet maxDist = -Infinity;\\n\\t\\t\\t\\tfor(let paramIdx = 0; paramIdx < sortParams.length; paramIdx++){\\n\\t\\t\\t\\t\\t\\tconst params = sortParams[paramIdx];\\n\\t\\t\\t\\t\\t\\tconst { transformedPosition, scale, aabbMin, aabbMax } = params;\\n\\t\\t\\t\\t\\t\\tconst cx = transformedPosition.x;\\n\\t\\t\\t\\t\\t\\tconst cy = transformedPosition.y;\\n\\t\\t\\t\\t\\t\\tconst cz = transformedPosition.z;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < 8; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst px = i & 1 ? aabbMax[0] : aabbMin[0];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst py = i & 2 ? aabbMax[1] : aabbMin[1];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst pz = i & 4 ? aabbMax[2] : aabbMin[2];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dx = px - cx;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dy = py - cy;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dz = pz - cz;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst distSq = dx * dx + dy * dy + dz * dz;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dist = Math.sqrt(distSq) * scale;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (dist > maxDist) maxDist = dist;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst minDist = 0;\\n\\t\\t\\t\\tif (maxDist < 0) {\\n\\t\\t\\t\\t\\t\\tmaxDist = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tminDist,\\n\\t\\t\\t\\t\\t\\tmaxDist\\n\\t\\t\\t\\t};\\n\\t\\t};\\n\\t\\tconst sort = (sortParams, order, centersData)=>{\\n\\t\\t\\t\\tconst sortStartTime = performance.now();\\n\\t\\t\\t\\tconst { minDist, maxDist } = _radialSort ? computeEffectiveDistanceRangeRadial(sortParams) : computeEffectiveDistanceRangeLinear(sortParams);\\n\\t\\t\\t\\tconst numVertices = centersData.totalUsedPixels;\\n\\t\\t\\t\\tconst compareBits = Math.max(10, Math.min(20, Math.round(Math.log2(numVertices / 4))));\\n\\t\\t\\t\\tconst bucketCount = 2 ** compareBits + 1;\\n\\t\\t\\t\\tif (distances?.length !== numVertices) {\\n\\t\\t\\t\\t\\t\\tdistances = new Uint32Array(numVertices);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!countBuffer || countBuffer.length !== bucketCount) {\\n\\t\\t\\t\\t\\t\\tcountBuffer = new Uint32Array(bucketCount);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tcountBuffer.fill(0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst range = maxDist - minDist;\\n\\t\\t\\t\\tconst cameraBin = GSplatSortBinWeights.computeCameraBin(_radialSort, minDist, range);\\n\\t\\t\\t\\tconst binWeights = binWeightsUtil.compute(cameraBin, bucketCount);\\n\\t\\t\\t\\tunpackBinWeights(binWeights);\\n\\t\\t\\t\\tif (_radialSort) {\\n\\t\\t\\t\\t\\t\\tevaluateSortKeysRadial(sortParams, minDist, range, distances, countBuffer, centersData);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tevaluateSortKeysLinear(sortParams, minDist, range, distances, countBuffer, centersData);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcountingSort(bucketCount, countBuffer, numVertices, distances, order);\\n\\t\\t\\t\\tconst count = numVertices;\\n\\t\\t\\t\\tconst sortTime = performance.now() - sortStartTime;\\n\\t\\t\\t\\tconst transferList = [\\n\\t\\t\\t\\t\\t\\torder.buffer\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tconst response = {\\n\\t\\t\\t\\t\\t\\torder: order.buffer,\\n\\t\\t\\t\\t\\t\\tcount,\\n\\t\\t\\t\\t\\t\\tversion: centersData.version,\\n\\t\\t\\t\\t\\t\\tsortTime: sortTime\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tmyself.postMessage(response, transferList);\\n\\t\\t};\\n\\t\\tmyself.addEventListener('message', (message)=>{\\n\\t\\t\\t\\tconst msgData = message.data ?? message;\\n\\t\\t\\t\\tswitch(msgData.command){\\n\\t\\t\\t\\t\\t\\tcase 'addCenters':\\n\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcentersMap.set(msgData.id, new Float32Array(msgData.centers));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcase 'removeCenters':\\n\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcentersMap.delete(msgData.id);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcase 'sort':\\n\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_radialSort = msgData.radialSorting || false;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst order = new Uint32Array(msgData.order);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsort(msgData.sortParams, order, centersData);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcase 'intervals':\\n\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcentersData = msgData;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t});\\n}\\n\\nlet GSplatSortBinWeights$1 = class GSplatSortBinWeights {\\n\\t\\tstatic get NUM_BINS() {\\n\\t\\t\\t\\treturn 32;\\n\\t\\t}\\n\\t\\tstatic get WEIGHT_TIERS() {\\n\\t\\t\\t\\treturn [\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tmaxDistance: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tweight: 40.0\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tmaxDistance: 2,\\n\\t\\t\\t\\t\\t\\t\\t\\tweight: 20.0\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tmaxDistance: 5,\\n\\t\\t\\t\\t\\t\\t\\t\\tweight: 8.0\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tmaxDistance: 10,\\n\\t\\t\\t\\t\\t\\t\\t\\tweight: 3.0\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tmaxDistance: Infinity,\\n\\t\\t\\t\\t\\t\\t\\t\\tweight: 1.0\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t];\\n\\t\\t}\\n\\t\\tstatic computeCameraBin(radialSort, minDist, range) {\\n\\t\\t\\t\\tconst numBins = GSplatSortBinWeights.NUM_BINS;\\n\\t\\t\\t\\tif (radialSort) {\\n\\t\\t\\t\\t\\t\\treturn numBins - 1;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst cameraOffsetFromRangeStart = -minDist;\\n\\t\\t\\t\\tconst cameraBinFloat = cameraOffsetFromRangeStart / range * numBins;\\n\\t\\t\\t\\treturn Math.max(0, Math.min(numBins - 1, Math.floor(cameraBinFloat)));\\n\\t\\t}\\n\\t\\tcompute(cameraBin, bucketCount) {\\n\\t\\t\\t\\tif (cameraBin === this.lastCameraBin && bucketCount === this.lastBucketCount) {\\n\\t\\t\\t\\t\\t\\treturn this.binWeights;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.lastCameraBin = cameraBin;\\n\\t\\t\\t\\tthis.lastBucketCount = bucketCount;\\n\\t\\t\\t\\tconst numBins = GSplatSortBinWeights.NUM_BINS;\\n\\t\\t\\t\\tconst bitsPerBin = this.bitsPerBin;\\n\\t\\t\\t\\tfor(let i = 0; i < numBins; i++){\\n\\t\\t\\t\\t\\t\\tconst distFromCamera = Math.abs(i - cameraBin);\\n\\t\\t\\t\\t\\t\\tbitsPerBin[i] = this.weightByDistance[distFromCamera];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet totalWeight = 0;\\n\\t\\t\\t\\tfor(let i = 0; i < numBins; i++){\\n\\t\\t\\t\\t\\t\\ttotalWeight += bitsPerBin[i];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet accumulated = 0;\\n\\t\\t\\t\\tfor(let i = 0; i < numBins; i++){\\n\\t\\t\\t\\t\\t\\tconst divider = Math.max(1, Math.floor(bitsPerBin[i] / totalWeight * bucketCount));\\n\\t\\t\\t\\t\\t\\tthis.binWeights[i * 2] = accumulated;\\n\\t\\t\\t\\t\\t\\tthis.binWeights[i * 2 + 1] = divider;\\n\\t\\t\\t\\t\\t\\taccumulated += divider;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (accumulated > bucketCount) {\\n\\t\\t\\t\\t\\t\\tconst excess = accumulated - bucketCount;\\n\\t\\t\\t\\t\\t\\tconst lastDividerIdx = (numBins - 1) * 2 + 1;\\n\\t\\t\\t\\t\\t\\tthis.binWeights[lastDividerIdx] = Math.max(1, this.binWeights[lastDividerIdx] - excess);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.binWeights;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.binWeights = new Float32Array(GSplatSortBinWeights.NUM_BINS * 2);\\n\\t\\t\\t\\tthis.lastCameraBin = -1;\\n\\t\\t\\t\\tthis.lastBucketCount = -1;\\n\\t\\t\\t\\tconst numBins = GSplatSortBinWeights.NUM_BINS;\\n\\t\\t\\t\\tconst weightTiers = GSplatSortBinWeights.WEIGHT_TIERS;\\n\\t\\t\\t\\tthis.bitsPerBin = new Float32Array(numBins);\\n\\t\\t\\t\\tthis.weightByDistance = new Float32Array(numBins);\\n\\t\\t\\t\\tfor(let dist = 0; dist < numBins; dist++){\\n\\t\\t\\t\\t\\t\\tlet weight = 1.0;\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j < weightTiers.length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (dist <= weightTiers[j].maxDistance) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tweight = weightTiers[j].weight;\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tthis.weightByDistance[dist] = weight;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n};\\n\\nconst _neededIds = new Set();\\nclass GSplatUnifiedSorter extends EventHandler {\\n\\t\\tonSorted(message) {\\n\\t\\t\\t\\tif (this._destroyed) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst msgData = message.data ?? message;\\n\\t\\t\\t\\tif (this.scene && msgData.sortTime !== undefined) {\\n\\t\\t\\t\\t\\t\\tthis.scene.fire('gsplat:sorted', msgData.sortTime);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst orderData = new Uint32Array(msgData.order);\\n\\t\\t\\t\\tthis.jobsInFlight--;\\n\\t\\t\\t\\tif (this.pendingSorted) {\\n\\t\\t\\t\\t\\t\\tthis.releaseOrderData(this.pendingSorted.orderData);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.pendingSorted = {\\n\\t\\t\\t\\t\\t\\tcount: msgData.count,\\n\\t\\t\\t\\t\\t\\tversion: msgData.version,\\n\\t\\t\\t\\t\\t\\torderData: orderData\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tapplyPendingSorted() {\\n\\t\\t\\t\\tif (this.pendingSorted) {\\n\\t\\t\\t\\t\\t\\tconst { count, version, orderData } = this.pendingSorted;\\n\\t\\t\\t\\t\\t\\tthis.pendingSorted = null;\\n\\t\\t\\t\\t\\t\\tthis.fire('sorted', count, version, orderData);\\n\\t\\t\\t\\t\\t\\tthis.releaseOrderData(orderData);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treleaseOrderData(orderData) {\\n\\t\\t\\t\\tif (orderData.length === this.bufferLength) {\\n\\t\\t\\t\\t\\t\\tthis.availableOrderData.push(orderData);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._destroyed = true;\\n\\t\\t\\t\\tthis.pendingSorted = null;\\n\\t\\t\\t\\tthis.worker.terminate();\\n\\t\\t\\t\\tthis.worker = null;\\n\\t\\t}\\n\\t\\tsetCenters(id, centers) {\\n\\t\\t\\t\\tif (centers) {\\n\\t\\t\\t\\t\\t\\tif (!this.centersSet.has(id)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.centersSet.add(id);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst centersBuffer = centers.buffer.slice();\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.worker.postMessage({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcommand: 'addCenters',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tid: id,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcenters: centersBuffer\\n\\t\\t\\t\\t\\t\\t\\t\\t}, [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcentersBuffer\\n\\t\\t\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (this.centersSet.has(id)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.centersSet.delete(id);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.worker.postMessage({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcommand: 'removeCenters',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tid: id\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateCentersForSplats(splats) {\\n\\t\\t\\t\\tfor (const splat of splats){\\n\\t\\t\\t\\t\\t\\tconst id = splat.resource.id;\\n\\t\\t\\t\\t\\t\\t_neededIds.add(id);\\n\\t\\t\\t\\t\\t\\tif (!this.centersSet.has(id)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setCenters(id, splat.resource.centers);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const id of this.centersSet){\\n\\t\\t\\t\\t\\t\\tif (!_neededIds.has(id)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.setCenters(id, null);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\t_neededIds.clear();\\n\\t\\t}\\n\\t\\tsetSortParameters(payload) {\\n\\t\\t\\t\\tthis.hasNewVersion = true;\\n\\t\\t\\t\\tconst { textureSize } = payload;\\n\\t\\t\\t\\tconst newLength = textureSize * textureSize;\\n\\t\\t\\t\\tif (newLength !== this.bufferLength) {\\n\\t\\t\\t\\t\\t\\tthis.bufferLength = newLength;\\n\\t\\t\\t\\t\\t\\tthis.availableOrderData.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.worker.postMessage(payload);\\n\\t\\t}\\n\\t\\tsetSortParams(params, radialSorting) {\\n\\t\\t\\t\\tif (this.hasNewVersion || this.jobsInFlight === 0) {\\n\\t\\t\\t\\t\\t\\tlet orderData = this.availableOrderData.pop();\\n\\t\\t\\t\\t\\t\\tif (!orderData) {\\n\\t\\t\\t\\t\\t\\t\\t\\torderData = new Uint32Array(this.bufferLength);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.jobsInFlight++;\\n\\t\\t\\t\\t\\t\\tthis.hasNewVersion = false;\\n\\t\\t\\t\\t\\t\\tthis.worker.postMessage({\\n\\t\\t\\t\\t\\t\\t\\t\\tcommand: 'sort',\\n\\t\\t\\t\\t\\t\\t\\t\\tsortParams: params,\\n\\t\\t\\t\\t\\t\\t\\t\\tradialSorting: radialSorting,\\n\\t\\t\\t\\t\\t\\t\\t\\torder: orderData.buffer\\n\\t\\t\\t\\t\\t\\t}, [\\n\\t\\t\\t\\t\\t\\t\\t\\torderData.buffer\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(scene){\\n\\t\\t\\t\\tsuper(), this.bufferLength = 0, this.availableOrderData = [], this.jobsInFlight = 0, this.hasNewVersion = false, this.pendingSorted = null, this.centersSet = new Set(), this._destroyed = false, this.scene = null;\\n\\t\\t\\t\\tthis.scene = scene ?? null;\\n\\t\\t\\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\\t\\t\\tif (platform.environment === 'node') {\\n\\t\\t\\t\\t\\t\\tthis.worker = new Worker(workerSource, {\\n\\t\\t\\t\\t\\t\\t\\t\\teval: true\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tthis.worker.on('message', this.onSorted.bind(this));\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.worker = new Worker(URL.createObjectURL(new Blob([\\n\\t\\t\\t\\t\\t\\t\\t\\tworkerSource\\n\\t\\t\\t\\t\\t\\t], {\\n\\t\\t\\t\\t\\t\\t\\t\\ttype: \\\"application/javascript\\\"\\n\\t\\t\\t\\t\\t\\t})));\\n\\t\\t\\t\\t\\t\\tthis.worker.addEventListener('message', this.onSorted.bind(this));\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass GSplatRenderer {\\n\\t\\tsetRenderMode(renderMode) {\\n\\t\\t\\t\\tconst oldRenderMode = this.renderMode ?? 0;\\n\\t\\t\\t\\tconst wasForward = (oldRenderMode & GSPLAT_FORWARD) !== 0;\\n\\t\\t\\t\\tconst wasShadow = (oldRenderMode & GSPLAT_SHADOW) !== 0;\\n\\t\\t\\t\\tconst isForward = (renderMode & GSPLAT_FORWARD) !== 0;\\n\\t\\t\\t\\tconst isShadow = (renderMode & GSPLAT_SHADOW) !== 0;\\n\\t\\t\\t\\tthis.meshInstance.castShadow = isShadow;\\n\\t\\t\\t\\tif (wasForward && !isForward) {\\n\\t\\t\\t\\t\\t\\tthis.layer.removeMeshInstances([\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.meshInstance\\n\\t\\t\\t\\t\\t\\t], true);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (wasShadow && !isShadow) {\\n\\t\\t\\t\\t\\t\\tthis.layer.removeShadowCasters([\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.meshInstance\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!wasForward && isForward) {\\n\\t\\t\\t\\t\\t\\tthis.layer.addMeshInstances([\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.meshInstance\\n\\t\\t\\t\\t\\t\\t], true);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!wasShadow && isShadow) {\\n\\t\\t\\t\\t\\t\\tthis.layer.addShadowCasters([\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.meshInstance\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.renderMode = renderMode;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tif (this.renderMode) {\\n\\t\\t\\t\\t\\t\\tif (this.renderMode & GSPLAT_FORWARD) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.layer.removeMeshInstances([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.meshInstance\\n\\t\\t\\t\\t\\t\\t\\t\\t], true);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.renderMode & GSPLAT_SHADOW) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.layer.removeShadowCasters([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.meshInstance\\n\\t\\t\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._material.destroy();\\n\\t\\t\\t\\tthis.meshInstance.destroy();\\n\\t\\t}\\n\\t\\tget material() {\\n\\t\\t\\t\\treturn this._material;\\n\\t\\t}\\n\\t\\tconfigureMaterial() {\\n\\t\\t\\t\\tconst { device, workBuffer } = this;\\n\\t\\t\\t\\tthis._injectFormatChunks();\\n\\t\\t\\t\\tthis._material.setDefine('STORAGE_ORDER', device.isWebGPU);\\n\\t\\t\\t\\tthis._material.setDefine('SH_BANDS', '0');\\n\\t\\t\\t\\tconst colorStream = workBuffer.format.getStream('dataColor');\\n\\t\\t\\t\\tif (colorStream && colorStream.format !== PIXELFORMAT_RGBA16U) {\\n\\t\\t\\t\\t\\t\\tthis._material.setDefine('GSPLAT_COLOR_FLOAT', '');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._updateIdDefines();\\n\\t\\t\\t\\tthis._bindWorkBufferTextures();\\n\\t\\t\\t\\tthis._material.setParameter('numSplats', 0);\\n\\t\\t\\t\\tif (workBuffer.orderTexture) {\\n\\t\\t\\t\\t\\t\\tthis._material.setParameter('splatOrder', workBuffer.orderTexture);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._material.setParameter('alphaClip', 0.3);\\n\\t\\t\\t\\tthis._material.setDefine(`DITHER_${'NONE'}`, '');\\n\\t\\t\\t\\tthis._material.cull = CULLFACE_NONE;\\n\\t\\t\\t\\tthis._material.blendType = BLEND_PREMULTIPLIED;\\n\\t\\t\\t\\tthis._material.depthWrite = false;\\n\\t\\t\\t\\tthis._material.update();\\n\\t\\t}\\n\\t\\t_bindWorkBufferTextures() {\\n\\t\\t\\t\\tconst { workBuffer } = this;\\n\\t\\t\\t\\tfor (const stream of workBuffer.format.resourceStreams){\\n\\t\\t\\t\\t\\t\\tconst texture = workBuffer.getTexture(stream.name);\\n\\t\\t\\t\\t\\t\\tif (texture) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._material.setParameter(stream.name, texture);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_injectFormatChunks() {\\n\\t\\t\\t\\tconst chunks = this.device.isWebGPU ? this._material.shaderChunks.wgsl : this._material.shaderChunks.glsl;\\n\\t\\t\\t\\tconst wbFormat = this.workBuffer.format;\\n\\t\\t\\t\\tchunks.set('gsplatDeclarationsVS', wbFormat.getInputDeclarations());\\n\\t\\t\\t\\tchunks.set('gsplatReadVS', wbFormat.getReadCode());\\n\\t\\t}\\n\\t\\tupdate(count, textureSize) {\\n\\t\\t\\t\\tthis.meshInstance.instancingCount = Math.ceil(count / GSplatResourceBase.instanceSize);\\n\\t\\t\\t\\tthis._material.setParameter('numSplats', count);\\n\\t\\t\\t\\tthis._material.setParameter('splatTextureSize', textureSize);\\n\\t\\t\\t\\tthis.meshInstance.visible = count > 0;\\n\\t\\t}\\n\\t\\tsetOrderData() {\\n\\t\\t\\t\\tif (this.device.isWebGPU) {\\n\\t\\t\\t\\t\\t\\tthis._material.setParameter('splatOrder', this.workBuffer.orderBuffer);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._material.setParameter('splatOrder', this.workBuffer.orderTexture);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetOrderBuffer(buffer) {\\n\\t\\t\\t\\tthis._material.setParameter('splatOrder', buffer);\\n\\t\\t}\\n\\t\\tframeUpdate(params) {\\n\\t\\t\\t\\tif (params.colorRamp) {\\n\\t\\t\\t\\t\\t\\tthis._material.setParameter('colorRampIntensity', params.colorRampIntensity);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._syncWithWorkBufferFormat();\\n\\t\\t\\t\\tif (this.forceCopyMaterial || params.material.dirty) {\\n\\t\\t\\t\\t\\t\\tthis.copyMaterialSettings(params.material);\\n\\t\\t\\t\\t\\t\\tthis.forceCopyMaterial = false;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_updateIdDefines() {\\n\\t\\t\\t\\tconst hasPcId = !!this.workBuffer.format.getStream('pcId');\\n\\t\\t\\t\\tthis._material.setDefine('GSPLAT_UNIFIED_ID', hasPcId);\\n\\t\\t\\t\\tthis._material.setDefine('PICK_CUSTOM_ID', hasPcId);\\n\\t\\t}\\n\\t\\t_syncWithWorkBufferFormat() {\\n\\t\\t\\t\\tconst wbFormat = this.workBuffer.format;\\n\\t\\t\\t\\tif (this._workBufferFormatVersion !== wbFormat.extraStreamsVersion) {\\n\\t\\t\\t\\t\\t\\tthis._workBufferFormatVersion = wbFormat.extraStreamsVersion;\\n\\t\\t\\t\\t\\t\\tthis.workBuffer.syncWithFormat();\\n\\t\\t\\t\\t\\t\\tthis._injectFormatChunks();\\n\\t\\t\\t\\t\\t\\tthis._bindWorkBufferTextures();\\n\\t\\t\\t\\t\\t\\tthis._updateIdDefines();\\n\\t\\t\\t\\t\\t\\tthis._material.update();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcopyMaterialSettings(sourceMaterial) {\\n\\t\\t\\t\\tconst keysToDelete = [];\\n\\t\\t\\t\\tthis._material.defines.forEach((value, key)=>{\\n\\t\\t\\t\\t\\t\\tif (!this._internalDefines.has(key)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tkeysToDelete.push(key);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tkeysToDelete.forEach((key)=>this._material.defines.delete(key));\\n\\t\\t\\t\\tsourceMaterial.defines.forEach((value, key)=>{\\n\\t\\t\\t\\t\\t\\tthis._material.defines.set(key, value);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst srcParams = sourceMaterial.parameters;\\n\\t\\t\\t\\tfor(const paramName in srcParams){\\n\\t\\t\\t\\t\\t\\tif (srcParams.hasOwnProperty(paramName)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._material.setParameter(paramName, srcParams[paramName].data);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (sourceMaterial.hasShaderChunks) {\\n\\t\\t\\t\\t\\t\\tthis._material.shaderChunks.copy(sourceMaterial.shaderChunks);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._injectFormatChunks();\\n\\t\\t\\t\\tthis._material.update();\\n\\t\\t}\\n\\t\\tupdateOverdrawMode(params) {\\n\\t\\t\\t\\tconst overdrawEnabled = !!params.colorRamp;\\n\\t\\t\\t\\tconst wasOverdrawEnabled = this._material.getDefine('GSPLAT_OVERDRAW');\\n\\t\\t\\t\\tif (overdrawEnabled) {\\n\\t\\t\\t\\t\\t\\tthis._material.setParameter('colorRamp', params.colorRamp);\\n\\t\\t\\t\\t\\t\\tthis._material.setParameter('colorRampIntensity', params.colorRampIntensity);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (overdrawEnabled !== wasOverdrawEnabled) {\\n\\t\\t\\t\\t\\t\\tthis._material.setDefine('GSPLAT_OVERDRAW', overdrawEnabled);\\n\\t\\t\\t\\t\\t\\tif (overdrawEnabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.originalBlendType = this._material.blendType;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._material.blendType = BLEND_ADDITIVE;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._material.blendType = this.originalBlendType;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._material.update();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetMaxNumSplats(numSplats) {\\n\\t\\t\\t\\tconst roundedNumSplats = math.roundUp(numSplats, GSplatResourceBase.instanceSize);\\n\\t\\t\\t\\tif (this.instanceIndicesCount < roundedNumSplats) {\\n\\t\\t\\t\\t\\t\\tthis.instanceIndicesCount = roundedNumSplats;\\n\\t\\t\\t\\t\\t\\tthis.instanceIndices?.destroy();\\n\\t\\t\\t\\t\\t\\tthis.instanceIndices = GSplatResourceBase.createInstanceIndices(this.device, numSplats);\\n\\t\\t\\t\\t\\t\\tthis.meshInstance.setInstancing(this.instanceIndices, true);\\n\\t\\t\\t\\t\\t\\tthis._material.setParameter('splatTextureSize', this.workBuffer.textureSize);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcreateMeshInstance() {\\n\\t\\t\\t\\tconst mesh = GSplatResourceBase.createMesh(this.device);\\n\\t\\t\\t\\tconst textureSize = this.workBuffer.textureSize;\\n\\t\\t\\t\\tconst instanceIndices = GSplatResourceBase.createInstanceIndices(this.device, textureSize * textureSize);\\n\\t\\t\\t\\tconst meshInstance = new MeshInstance(mesh, this._material);\\n\\t\\t\\t\\tmeshInstance.node = this.node;\\n\\t\\t\\t\\tmeshInstance.setInstancing(instanceIndices, true);\\n\\t\\t\\t\\tmeshInstance.instancingCount = 0;\\n\\t\\t\\t\\tconst thisCamera = this.cameraNode.camera;\\n\\t\\t\\t\\tmeshInstance.isVisibleFunc = (camera)=>{\\n\\t\\t\\t\\t\\t\\tconst renderMode = this.renderMode ?? 0;\\n\\t\\t\\t\\t\\t\\tif (thisCamera.camera === camera && renderMode & GSPLAT_FORWARD) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (renderMode & GSPLAT_SHADOW) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn camera.node?.name === SHADOWCAMERA_NAME;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\treturn meshInstance;\\n\\t\\t}\\n\\t\\tconstructor(device, node, cameraNode, layer, workBuffer){\\n\\t\\t\\t\\tthis.instanceIndices = null;\\n\\t\\t\\t\\tthis.instanceIndicesCount = 0;\\n\\t\\t\\t\\tthis.originalBlendType = BLEND_ADDITIVE;\\n\\t\\t\\t\\tthis._internalDefines = new Set();\\n\\t\\t\\t\\tthis.forceCopyMaterial = true;\\n\\t\\t\\t\\tthis._workBufferFormatVersion = -1;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.node = node;\\n\\t\\t\\t\\tthis.cameraNode = cameraNode;\\n\\t\\t\\t\\tthis.layer = layer;\\n\\t\\t\\t\\tthis.workBuffer = workBuffer;\\n\\t\\t\\t\\tthis._workBufferFormatVersion = workBuffer.format.extraStreamsVersion;\\n\\t\\t\\t\\tthis._material = new ShaderMaterial({\\n\\t\\t\\t\\t\\t\\tuniqueName: 'UnifiedSplatMaterial',\\n\\t\\t\\t\\t\\t\\tvertexGLSL: '#include \\\"gsplatVS\\\"',\\n\\t\\t\\t\\t\\t\\tfragmentGLSL: '#include \\\"gsplatPS\\\"',\\n\\t\\t\\t\\t\\t\\tvertexWGSL: '#include \\\"gsplatVS\\\"',\\n\\t\\t\\t\\t\\t\\tfragmentWGSL: '#include \\\"gsplatPS\\\"',\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION,\\n\\t\\t\\t\\t\\t\\t\\t\\tvertex_id_attrib: SEMANTIC_ATTR13\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.configureMaterial();\\n\\t\\t\\t\\tthis._material.defines.forEach((value, key)=>{\\n\\t\\t\\t\\t\\t\\tthis._internalDefines.add(key);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis._internalDefines.add('GSPLAT_UNIFIED_ID');\\n\\t\\t\\t\\tthis._internalDefines.add('PICK_CUSTOM_ID');\\n\\t\\t\\t\\tthis.meshInstance = this.createMeshInstance();\\n\\t\\t}\\n}\\n\\nclass GSplatPlacement {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._streams?.destroy();\\n\\t\\t\\t\\tthis._streams = null;\\n\\t\\t\\t\\tthis.intervals.clear();\\n\\t\\t\\t\\tthis.resource = null;\\n\\t\\t}\\n\\t\\tset workBufferModifier(value) {\\n\\t\\t\\t\\tthis._workBufferModifier = value;\\n\\t\\t\\t\\tthis.renderDirty = true;\\n\\t\\t}\\n\\t\\tget workBufferModifier() {\\n\\t\\t\\t\\treturn this._parentPlacement?.workBufferModifier ?? this._workBufferModifier;\\n\\t\\t}\\n\\t\\tconsumeRenderDirty() {\\n\\t\\t\\t\\tconst format = this.resource?.format;\\n\\t\\t\\t\\tif (format && this._lastFormatVersion !== format.extraStreamsVersion) {\\n\\t\\t\\t\\t\\t\\tthis._lastFormatVersion = format.extraStreamsVersion;\\n\\t\\t\\t\\t\\t\\tthis.renderDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.workBufferUpdate === WORKBUFFER_UPDATE_ALWAYS) {\\n\\t\\t\\t\\t\\t\\tthis.renderDirty = true;\\n\\t\\t\\t\\t} else if (this.workBufferUpdate === WORKBUFFER_UPDATE_ONCE) {\\n\\t\\t\\t\\t\\t\\tthis.renderDirty = true;\\n\\t\\t\\t\\t\\t\\tthis.workBufferUpdate = WORKBUFFER_UPDATE_AUTO;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst dirty = this.renderDirty;\\n\\t\\t\\t\\tthis.renderDirty = false;\\n\\t\\t\\t\\treturn dirty;\\n\\t\\t}\\n\\t\\tset aabb(aabb) {\\n\\t\\t\\t\\tthis._aabb = aabb?.clone() ?? null;\\n\\t\\t}\\n\\t\\tget aabb() {\\n\\t\\t\\t\\tconst aabb = this._aabb ?? this.resource?.aabb;\\n\\t\\t\\t\\treturn aabb;\\n\\t\\t}\\n\\t\\tset lodDistances(distances) {\\n\\t\\t\\t\\tconst isOctree = !!(this.resource && this.resource.octree);\\n\\t\\t\\t\\tif (isOctree) {\\n\\t\\t\\t\\t\\t\\tif (distances) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.resource.octree?.lodLevels ?? 1;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._lodDistances = distances.slice();\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._lodDistances = null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget lodDistances() {\\n\\t\\t\\t\\treturn this._lodDistances ? this._lodDistances.slice() : null;\\n\\t\\t}\\n\\t\\tgetInstanceTexture(name, device) {\\n\\t\\t\\t\\tconst resource = this.resource;\\n\\t\\t\\t\\tif (!resource?.format) {\\n\\t\\t\\t\\t\\t\\treturn undefined;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._streams && resource.format.instanceStreams.length > 0) {\\n\\t\\t\\t\\t\\t\\tthis._streams = new GSplatStreams(device, true);\\n\\t\\t\\t\\t\\t\\tthis._streams.textureDimensions.copy(resource.streams.textureDimensions);\\n\\t\\t\\t\\t\\t\\tthis._streams.syncWithFormat(resource.format);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._streams?.getTexture(name);\\n\\t\\t}\\n\\t\\tget streams() {\\n\\t\\t\\t\\treturn this._parentPlacement?.streams ?? this._streams;\\n\\t\\t}\\n\\t\\tensureInstanceStreams(device) {\\n\\t\\t\\t\\tconst resource = this.resource;\\n\\t\\t\\t\\tif (!resource?.format) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._streams && resource.format.instanceStreams.length > 0) {\\n\\t\\t\\t\\t\\t\\tthis._streams = new GSplatStreams(device, true);\\n\\t\\t\\t\\t\\t\\tthis._streams.textureDimensions.copy(resource.streams.textureDimensions);\\n\\t\\t\\t\\t\\t\\tthis._streams.syncWithFormat(resource.format);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(resource, node, lodIndex = 0, parameters = null, parentPlacement = null, id = null){\\n\\t\\t\\t\\tthis.intervals = new Map();\\n\\t\\t\\t\\tthis.id = 0;\\n\\t\\t\\t\\tthis.lodIndex = 0;\\n\\t\\t\\t\\tthis._lodDistances = null;\\n\\t\\t\\t\\tthis.splatBudget = 0;\\n\\t\\t\\t\\tthis._aabb = null;\\n\\t\\t\\t\\tthis.parameters = null;\\n\\t\\t\\t\\tthis._streams = null;\\n\\t\\t\\t\\tthis.renderDirty = false;\\n\\t\\t\\t\\tthis.workBufferUpdate = WORKBUFFER_UPDATE_AUTO;\\n\\t\\t\\t\\tthis._lastFormatVersion = -1;\\n\\t\\t\\t\\tthis._workBufferModifier = null;\\n\\t\\t\\t\\tthis._parentPlacement = null;\\n\\t\\t\\t\\tthis.id = id ?? parentPlacement?.id ?? 0;\\n\\t\\t\\t\\tthis.resource = resource;\\n\\t\\t\\t\\tthis.node = node;\\n\\t\\t\\t\\tthis.lodIndex = lodIndex;\\n\\t\\t\\t\\tthis.parameters = parameters ?? parentPlacement?.parameters ?? null;\\n\\t\\t\\t\\tthis._parentPlacement = parentPlacement;\\n\\t\\t}\\n}\\n\\nconst _invWorldMat = new Mat4();\\nconst _localCameraPos = new Vec3();\\nconst _localCameraFwd = new Vec3();\\nconst _dirToNode = new Vec3();\\nconst _tempCompletedUrls = [];\\nnew BoundingBox();\\n[\\n\\t\\tnew Color(1, 0, 0),\\n\\t\\tnew Color(0, 1, 0),\\n\\t\\tnew Color(0, 0, 1),\\n\\t\\tnew Color(1, 1, 0),\\n\\t\\tnew Color(1, 0, 1)\\n];\\nclass NodeInfo {\\n\\t\\treset() {\\n\\t\\t\\t\\tthis.currentLod = -1;\\n\\t\\t\\t\\tthis.optimalLod = -1;\\n\\t\\t\\t\\tthis.importance = 0;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.currentLod = -1;\\n\\t\\t\\t\\tthis.optimalLod = -1;\\n\\t\\t\\t\\tthis.importance = 0;\\n\\t\\t}\\n}\\nclass GSplatOctreeInstance {\\n\\t\\tget pendingLoadCount() {\\n\\t\\t\\t\\tlet count = this.pending.size + this.prefetchPending.size;\\n\\t\\t\\t\\tif (this.octree.environmentUrl && !this.environmentPlacement) {\\n\\t\\t\\t\\t\\t\\tcount++;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn count;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tif (this.octree && !this.octree.destroyed) {\\n\\t\\t\\t\\t\\t\\tconst filesToDecRef = this.getFileDecrements();\\n\\t\\t\\t\\t\\t\\tfor (const fileIndex of filesToDecRef){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.octree.decRefCount(fileIndex, 0);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor (const fileIndex of this.pending){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this.filePlacements[fileIndex]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.octree.unloadResource(fileIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor (const fileIndex of this.prefetchPending){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this.filePlacements[fileIndex]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.octree.unloadResource(fileIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.environmentPlacement) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.octree.decEnvironmentRefCount();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.pending.clear();\\n\\t\\t\\t\\tthis.pendingDecrements.clear();\\n\\t\\t\\t\\tthis.filePlacements.length = 0;\\n\\t\\t\\t\\tif (this.environmentPlacement) {\\n\\t\\t\\t\\t\\t\\tthis.activePlacements.delete(this.environmentPlacement);\\n\\t\\t\\t\\t\\t\\tthis.environmentPlacement = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._deviceLostEvent?.off();\\n\\t\\t\\t\\tthis._deviceLostEvent = null;\\n\\t\\t}\\n\\t\\t_onDeviceLost() {\\n\\t\\t\\t\\tfor(let i = 0; i < this.filePlacements.length; i++){\\n\\t\\t\\t\\t\\t\\tif (this.filePlacements[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.octree.decRefCount(i, 0);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.filePlacements.fill(null);\\n\\t\\t\\t\\tthis.activePlacements.clear();\\n\\t\\t\\t\\tthis.pending.clear();\\n\\t\\t\\t\\tthis.pendingDecrements.clear();\\n\\t\\t\\t\\tthis.removedCandidates.clear();\\n\\t\\t\\t\\tthis.prefetchPending.clear();\\n\\t\\t\\t\\tthis.pendingVisibleAdds.clear();\\n\\t\\t\\t\\tfor (const nodeInfo of this.nodeInfos){\\n\\t\\t\\t\\t\\t\\tnodeInfo.reset();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.environmentPlacement) {\\n\\t\\t\\t\\t\\t\\tthis.activePlacements.delete(this.environmentPlacement);\\n\\t\\t\\t\\t\\t\\tthis.environmentPlacement = null;\\n\\t\\t\\t\\t\\t\\tthis.octree.unloadEnvironmentResource();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.dirtyModifiedPlacements = true;\\n\\t\\t\\t\\tthis.needsLodUpdate = true;\\n\\t\\t}\\n\\t\\tgetFileDecrements() {\\n\\t\\t\\t\\tconst toRelease = [];\\n\\t\\t\\t\\tfor(let i = 0; i < this.filePlacements.length; i++){\\n\\t\\t\\t\\t\\t\\tif (this.filePlacements[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\ttoRelease.push(i);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn toRelease;\\n\\t\\t}\\n\\t\\tcalculateNodeLod(localCameraPosition, localCameraForward, nodeIndex, maxLod, lodDistances, lodBehindPenalty) {\\n\\t\\t\\t\\tconst node = this.octree.nodes[nodeIndex];\\n\\t\\t\\t\\tnode.bounds.closestPoint(localCameraPosition, _dirToNode);\\n\\t\\t\\t\\t_dirToNode.sub(localCameraPosition);\\n\\t\\t\\t\\tlet distance = _dirToNode.length();\\n\\t\\t\\t\\tif (lodBehindPenalty > 1 && distance > 0.01) {\\n\\t\\t\\t\\t\\t\\tconst dotOverDistance = localCameraForward.dot(_dirToNode) / distance;\\n\\t\\t\\t\\t\\t\\tif (dotOverDistance < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst t = -dotOverDistance;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst factor = 1 + t * (lodBehindPenalty - 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tdistance *= factor;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let lod = 0; lod < maxLod; lod++){\\n\\t\\t\\t\\t\\t\\tif (distance < lodDistances[lod]) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn lod;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn maxLod;\\n\\t\\t}\\n\\t\\tselectDesiredLodIndex(node, optimalLodIndex, maxLod, lodUnderfillLimit) {\\n\\t\\t\\t\\tif (lodUnderfillLimit > 0) {\\n\\t\\t\\t\\t\\t\\tconst allowedMaxCoarseLod = Math.min(maxLod, optimalLodIndex + lodUnderfillLimit);\\n\\t\\t\\t\\t\\t\\tfor(let lod = optimalLodIndex; lod <= allowedMaxCoarseLod; lod++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst fi = node.lods[lod].fileIndex;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (fi !== -1 && this.octree.getFileResource(fi)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn lod;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor(let lod = allowedMaxCoarseLod; lod >= optimalLodIndex; lod--){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst fi = node.lods[lod].fileIndex;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (fi !== -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn lod;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn optimalLodIndex;\\n\\t\\t}\\n\\t\\tprefetchNextLod(node, desiredLodIndex, optimalLodIndex) {\\n\\t\\t\\t\\tif (desiredLodIndex === -1 || optimalLodIndex === -1) return;\\n\\t\\t\\t\\tif (desiredLodIndex === optimalLodIndex) {\\n\\t\\t\\t\\t\\t\\tconst fi = node.lods[optimalLodIndex].fileIndex;\\n\\t\\t\\t\\t\\t\\tif (fi !== -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.octree.ensureFileResource(fi);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this.octree.getFileResource(fi)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.prefetchPending.add(fi);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst targetLod = Math.max(optimalLodIndex, desiredLodIndex - 1);\\n\\t\\t\\t\\tfor(let lod = targetLod; lod >= optimalLodIndex; lod--){\\n\\t\\t\\t\\t\\t\\tconst fi = node.lods[lod].fileIndex;\\n\\t\\t\\t\\t\\t\\tif (fi !== -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.octree.ensureFileResource(fi);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this.octree.getFileResource(fi)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.prefetchPending.add(fi);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateLod(cameraNode, params) {\\n\\t\\t\\t\\tconst maxLod = this.octree.lodLevels - 1;\\n\\t\\t\\t\\tconst lodDistances = this.placement.lodDistances || [\\n\\t\\t\\t\\t\\t\\t5,\\n\\t\\t\\t\\t\\t\\t10,\\n\\t\\t\\t\\t\\t\\t15,\\n\\t\\t\\t\\t\\t\\t20,\\n\\t\\t\\t\\t\\t\\t25,\\n\\t\\t\\t\\t\\t\\t30,\\n\\t\\t\\t\\t\\t\\t35,\\n\\t\\t\\t\\t\\t\\t40,\\n\\t\\t\\t\\t\\t\\t45,\\n\\t\\t\\t\\t\\t\\t50,\\n\\t\\t\\t\\t\\t\\t55,\\n\\t\\t\\t\\t\\t\\t60\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tconst { lodRangeMin, lodRangeMax } = params;\\n\\t\\t\\t\\tconst rangeMin = Math.max(0, Math.min(lodRangeMin ?? 0, maxLod));\\n\\t\\t\\t\\tconst rangeMax = Math.max(rangeMin, Math.min(lodRangeMax ?? maxLod, maxLod));\\n\\t\\t\\t\\tconst totalOptimalSplats = this.evaluateNodeLods(cameraNode, maxLod, lodDistances, rangeMin, rangeMax, params);\\n\\t\\t\\t\\tif (this.splatBudget > 0) {\\n\\t\\t\\t\\t\\t\\tthis.enforceSplatBudget(totalOptimalSplats, this.splatBudget, rangeMin, rangeMax);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.applyLodChanges(maxLod, params);\\n\\t\\t}\\n\\t\\tevaluateNodeLods(cameraNode, maxLod, lodDistances, rangeMin, rangeMax, params) {\\n\\t\\t\\t\\tconst { lodBehindPenalty } = params;\\n\\t\\t\\t\\tconst worldCameraPosition = cameraNode.getPosition();\\n\\t\\t\\t\\tconst octreeWorldTransform = this.placement.node.getWorldTransform();\\n\\t\\t\\t\\t_invWorldMat.copy(octreeWorldTransform).invert();\\n\\t\\t\\t\\tconst localCameraPosition = _invWorldMat.transformPoint(worldCameraPosition, _localCameraPos);\\n\\t\\t\\t\\tconst worldCameraForward = cameraNode.forward;\\n\\t\\t\\t\\tconst localCameraForward = _invWorldMat.transformVector(worldCameraForward, _localCameraFwd).normalize();\\n\\t\\t\\t\\tconst nodes = this.octree.nodes;\\n\\t\\t\\t\\tconst nodeInfos = this.nodeInfos;\\n\\t\\t\\t\\tlet totalSplats = 0;\\n\\t\\t\\t\\tconst maxDistance = lodDistances[rangeMax] || 100;\\n\\t\\t\\t\\tfor(let nodeIndex = 0; nodeIndex < nodes.length; nodeIndex++){\\n\\t\\t\\t\\t\\t\\tconst node = nodes[nodeIndex];\\n\\t\\t\\t\\t\\t\\tnode.bounds.closestPoint(localCameraPosition, _dirToNode);\\n\\t\\t\\t\\t\\t\\t_dirToNode.sub(localCameraPosition);\\n\\t\\t\\t\\t\\t\\tconst actualDistance = _dirToNode.length();\\n\\t\\t\\t\\t\\t\\tlet penalizedDistance = actualDistance;\\n\\t\\t\\t\\t\\t\\tlet importanceMultiplier = 1.0;\\n\\t\\t\\t\\t\\t\\tif (lodBehindPenalty > 1 && actualDistance > 0.01) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dotOverDistance = localCameraForward.dot(_dirToNode) / actualDistance;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (dotOverDistance < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst t = -dotOverDistance;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst factor = 1 + t * (lodBehindPenalty - 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpenalizedDistance = actualDistance * factor;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\timportanceMultiplier = 1.0 / factor;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlet optimalLodIndex = maxLod;\\n\\t\\t\\t\\t\\t\\tfor(let lod = 0; lod < maxLod; lod++){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (penalizedDistance < lodDistances[lod]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptimalLodIndex = lod;\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tif (optimalLodIndex < rangeMin) optimalLodIndex = rangeMin;\\n\\t\\t\\t\\t\\t\\tif (optimalLodIndex > rangeMax) optimalLodIndex = rangeMax;\\n\\t\\t\\t\\t\\t\\tconst normalizedDistance = Math.min(actualDistance / maxDistance, 1.0);\\n\\t\\t\\t\\t\\t\\tconst importance = (1.0 - normalizedDistance) * importanceMultiplier;\\n\\t\\t\\t\\t\\t\\tnodeInfos[nodeIndex].optimalLod = optimalLodIndex;\\n\\t\\t\\t\\t\\t\\tnodeInfos[nodeIndex].importance = importance;\\n\\t\\t\\t\\t\\t\\tconst lod = nodes[nodeIndex].lods[optimalLodIndex];\\n\\t\\t\\t\\t\\t\\tif (lod && lod.count) {\\n\\t\\t\\t\\t\\t\\t\\t\\ttotalSplats += lod.count;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn totalSplats;\\n\\t\\t}\\n\\t\\tenforceSplatBudget(totalSplats, splatBudget, rangeMin, rangeMax) {\\n\\t\\t\\t\\tconst nodes = this.octree.nodes;\\n\\t\\t\\t\\tconst nodeInfos = this.nodeInfos;\\n\\t\\t\\t\\tif (!this._nodeIndices) {\\n\\t\\t\\t\\t\\t\\tthis._nodeIndices = new Uint32Array(nodes.length);\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < nodes.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._nodeIndices[i] = i;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst nodeIndices = this._nodeIndices;\\n\\t\\t\\t\\tnodeIndices.sort((a, b)=>nodeInfos[a].importance - nodeInfos[b].importance);\\n\\t\\t\\t\\tlet currentSplats = totalSplats;\\n\\t\\t\\t\\tif (currentSplats === splatBudget) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst isOverBudget = currentSplats > splatBudget;\\n\\t\\t\\t\\tconst lodDelta = isOverBudget ? 1 : -1;\\n\\t\\t\\t\\twhile(isOverBudget ? currentSplats > splatBudget : currentSplats < splatBudget){\\n\\t\\t\\t\\t\\t\\tlet modified = false;\\n\\t\\t\\t\\t\\t\\tif (isOverBudget) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < nodeIndices.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst nodeIndex = nodeIndices[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst nodeInfo = nodeInfos[nodeIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst node = nodes[nodeIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst currentOptimalLod = nodeInfo.optimalLod;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (currentOptimalLod < rangeMax) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst currentLod = node.lods[currentOptimalLod];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst nextLod = node.lods[currentOptimalLod + 1];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst splatsSaved = currentLod.count - nextLod.count;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnodeInfo.optimalLod += lodDelta;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcurrentSplats -= splatsSaved;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmodified = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (currentSplats <= splatBudget) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = nodeIndices.length - 1; i >= 0; i--){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst nodeIndex = nodeIndices[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst nodeInfo = nodeInfos[nodeIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst node = nodes[nodeIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst currentOptimalLod = nodeInfo.optimalLod;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (currentOptimalLod > rangeMin) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst currentLod = node.lods[currentOptimalLod];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst nextLod = node.lods[currentOptimalLod - 1];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst splatsAdded = nextLod.count - currentLod.count;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (currentSplats + splatsAdded <= splatBudget) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnodeInfo.optimalLod += lodDelta;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcurrentSplats += splatsAdded;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmodified = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (currentSplats >= splatBudget) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tif (!modified) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tapplyLodChanges(maxLod, params) {\\n\\t\\t\\t\\tconst nodes = this.octree.nodes;\\n\\t\\t\\t\\tconst { lodUnderfillLimit = 0 } = params;\\n\\t\\t\\t\\tfor(let nodeIndex = 0; nodeIndex < nodes.length; nodeIndex++){\\n\\t\\t\\t\\t\\t\\tconst node = nodes[nodeIndex];\\n\\t\\t\\t\\t\\t\\tconst nodeInfo = this.nodeInfos[nodeIndex];\\n\\t\\t\\t\\t\\t\\tconst optimalLodIndex = nodeInfo.optimalLod;\\n\\t\\t\\t\\t\\t\\tconst currentLodIndex = nodeInfo.currentLod;\\n\\t\\t\\t\\t\\t\\tconst desiredLodIndex = this.selectDesiredLodIndex(node, optimalLodIndex, maxLod, lodUnderfillLimit);\\n\\t\\t\\t\\t\\t\\tif (desiredLodIndex !== currentLodIndex) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst currentFileIndex = currentLodIndex >= 0 ? node.lods[currentLodIndex].fileIndex : -1;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst desiredFileIndex = desiredLodIndex >= 0 ? node.lods[desiredLodIndex].fileIndex : -1;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst wasVisible = currentFileIndex !== -1;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst willBeVisible = desiredFileIndex !== -1;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst pendingEntry = this.pendingDecrements.get(nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (pendingEntry) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (pendingEntry.newFileIndex !== desiredFileIndex) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst prevPendingPlacement = this.filePlacements[pendingEntry.newFileIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (prevPendingPlacement) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.decrementFileRef(pendingEntry.newFileIndex, nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (wasVisible && willBeVisible) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.pendingDecrements.set(nodeIndex, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toldFileIndex: pendingEntry.oldFileIndex,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnewFileIndex: desiredFileIndex\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.pendingDecrements.delete(nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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\\tif (!wasVisible && willBeVisible) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst prevPendingFi = this.pendingVisibleAdds.get(nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (prevPendingFi !== undefined && prevPendingFi !== desiredFileIndex) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.decrementFileRef(prevPendingFi, nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.pendingVisibleAdds.delete(nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.incrementFileRef(desiredFileIndex, nodeIndex, desiredLodIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst newPlacement = this.filePlacements[desiredFileIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (newPlacement?.resource) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnodeInfo.currentLod = desiredLodIndex;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.pendingVisibleAdds.delete(nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.pendingVisibleAdds.set(nodeIndex, desiredFileIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else if (wasVisible && !willBeVisible) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst pendingEntry2 = this.pendingDecrements.get(nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (pendingEntry2) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.decrementFileRef(pendingEntry2.newFileIndex, nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.pendingDecrements.delete(nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.decrementFileRef(currentFileIndex, nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnodeInfo.currentLod = -1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.pendingVisibleAdds.delete(nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else if (wasVisible && willBeVisible) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.incrementFileRef(desiredFileIndex, nodeIndex, desiredLodIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst newPlacement = this.filePlacements[desiredFileIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (newPlacement?.resource) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.decrementFileRef(currentFileIndex, nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.pendingDecrements.delete(nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnodeInfo.currentLod = desiredLodIndex;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.pendingVisibleAdds.delete(nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.pendingDecrements.set(nodeIndex, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toldFileIndex: currentFileIndex,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnewFileIndex: desiredFileIndex\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.pendingVisibleAdds.delete(nodeIndex);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tthis.prefetchNextLod(node, desiredLodIndex, optimalLodIndex);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tincrementFileRef(fileIndex, nodeIndex, lodIndex) {\\n\\t\\t\\t\\tif (fileIndex === -1) return;\\n\\t\\t\\t\\tlet placement = this.filePlacements[fileIndex];\\n\\t\\t\\t\\tif (!placement) {\\n\\t\\t\\t\\t\\t\\tplacement = new GSplatPlacement(null, this.placement.node, lodIndex, null, this.placement);\\n\\t\\t\\t\\t\\t\\tthis.filePlacements[fileIndex] = placement;\\n\\t\\t\\t\\t\\t\\tconst removeScheduled = this.removedCandidates.delete(fileIndex);\\n\\t\\t\\t\\t\\t\\tif (!removeScheduled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.octree.incRefCount(fileIndex);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!this.addFilePlacement(fileIndex)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.octree.ensureFileResource(fileIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.pending.add(fileIndex);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst nodes = this.octree.nodes;\\n\\t\\t\\t\\tconst node = nodes[nodeIndex];\\n\\t\\t\\t\\tconst lod = node.lods[lodIndex];\\n\\t\\t\\t\\tconst interval = new Vec2(lod.offset, lod.offset + lod.count - 1);\\n\\t\\t\\t\\tplacement.intervals.set(nodeIndex, interval);\\n\\t\\t\\t\\tthis.dirtyModifiedPlacements = true;\\n\\t\\t}\\n\\t\\tdecrementFileRef(fileIndex, nodeIndex) {\\n\\t\\t\\t\\tif (fileIndex === -1) return;\\n\\t\\t\\t\\tconst placement = this.filePlacements[fileIndex];\\n\\t\\t\\t\\tif (!placement) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (placement) {\\n\\t\\t\\t\\t\\t\\tplacement.intervals.delete(nodeIndex);\\n\\t\\t\\t\\t\\t\\tthis.dirtyModifiedPlacements = true;\\n\\t\\t\\t\\t\\t\\tif (placement.intervals.size === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (placement.resource) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.activePlacements.delete(placement);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.removedCandidates.add(fileIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.filePlacements[fileIndex] = null;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.pending.delete(fileIndex);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\taddFilePlacement(fileIndex) {\\n\\t\\t\\t\\tconst res = this.octree.getFileResource(fileIndex);\\n\\t\\t\\t\\tif (res) {\\n\\t\\t\\t\\t\\t\\tconst placement = this.filePlacements[fileIndex];\\n\\t\\t\\t\\t\\t\\tif (placement) {\\n\\t\\t\\t\\t\\t\\t\\t\\tplacement.resource = res;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.activePlacements.add(placement);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.dirtyModifiedPlacements = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.removedCandidates.delete(fileIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\ttestMoved(threshold) {\\n\\t\\t\\t\\tconst position = this.placement.node.getPosition();\\n\\t\\t\\t\\tconst length = position.distance(this.previousPosition);\\n\\t\\t\\t\\tif (length > threshold) {\\n\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tupdateMoved() {\\n\\t\\t\\t\\tthis.previousPosition.copy(this.placement.node.getPosition());\\n\\t\\t}\\n\\t\\tupdate(scene) {\\n\\t\\t\\t\\tconst currentBudget = this.placement.splatBudget;\\n\\t\\t\\t\\tif (currentBudget !== this.splatBudget) {\\n\\t\\t\\t\\t\\t\\tthis.splatBudget = currentBudget;\\n\\t\\t\\t\\t\\t\\tthis.needsLodUpdate = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.pending.size) {\\n\\t\\t\\t\\t\\t\\tfor (const fileIndex of this.pending){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.octree.ensureFileResource(fileIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.addFilePlacement(fileIndex)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_tempCompletedUrls.push(fileIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor (const [nodeIndex, { oldFileIndex, newFileIndex }] of this.pendingDecrements){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (newFileIndex === fileIndex) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.decrementFileRef(oldFileIndex, nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.pendingDecrements.delete(nodeIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet newLodIndex = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst nodeLods = this.octree.nodes[nodeIndex].lods;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let li = 0; li < nodeLods.length; li++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (nodeLods[li].fileIndex === newFileIndex) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnewLodIndex = li;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.nodeInfos[nodeIndex].currentLod = newLodIndex;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tif (_tempCompletedUrls.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.needsLodUpdate = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor (const fileIndex of _tempCompletedUrls){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.pending.delete(fileIndex);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t_tempCompletedUrls.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.pollPrefetchCompletions();\\n\\t\\t\\t\\tif (this.octree.environmentUrl && !this.environmentPlacement) {\\n\\t\\t\\t\\t\\t\\tthis.octree.ensureEnvironmentResource();\\n\\t\\t\\t\\t\\t\\tconst envResource = this.octree.environmentResource;\\n\\t\\t\\t\\t\\t\\tif (envResource) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.environmentPlacement = new GSplatPlacement(envResource, this.placement.node, 0, null, this.placement);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.environmentPlacement.aabb.copy(envResource.aabb);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.activePlacements.add(this.environmentPlacement);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.dirtyModifiedPlacements = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst dirty = this.dirtyModifiedPlacements;\\n\\t\\t\\t\\tthis.dirtyModifiedPlacements = false;\\n\\t\\t\\t\\treturn dirty;\\n\\t\\t}\\n\\t\\tdebugRender(scene) {}\\n\\t\\tconsumeNeedsLodUpdate() {\\n\\t\\t\\t\\tconst v = this.needsLodUpdate;\\n\\t\\t\\t\\tthis.needsLodUpdate = false;\\n\\t\\t\\t\\treturn v;\\n\\t\\t}\\n\\t\\tpollPrefetchCompletions() {\\n\\t\\t\\t\\tif (this.prefetchPending.size) {\\n\\t\\t\\t\\t\\t\\tfor (const fileIndex of this.prefetchPending){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.octree.ensureFileResource(fileIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.octree.getFileResource(fileIndex)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_tempCompletedUrls.push(fileIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (_tempCompletedUrls.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.needsLodUpdate = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor (const fileIndex of _tempCompletedUrls){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.prefetchPending.delete(fileIndex);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t_tempCompletedUrls.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(device, octree, placement){\\n\\t\\t\\t\\tthis.activePlacements = new Set();\\n\\t\\t\\t\\tthis.dirtyModifiedPlacements = false;\\n\\t\\t\\t\\tthis.pending = new Set();\\n\\t\\t\\t\\tthis.pendingDecrements = new Map();\\n\\t\\t\\t\\tthis.removedCandidates = new Set();\\n\\t\\t\\t\\tthis.previousPosition = new Vec3();\\n\\t\\t\\t\\tthis.needsLodUpdate = false;\\n\\t\\t\\t\\tthis.prefetchPending = new Set();\\n\\t\\t\\t\\tthis.pendingVisibleAdds = new Map();\\n\\t\\t\\t\\tthis.splatBudget = 0;\\n\\t\\t\\t\\tthis._nodeIndices = null;\\n\\t\\t\\t\\tthis.environmentPlacement = null;\\n\\t\\t\\t\\tthis._deviceLostEvent = null;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.octree = octree;\\n\\t\\t\\t\\tthis.placement = placement;\\n\\t\\t\\t\\tthis.nodeInfos = new Array(octree.nodes.length);\\n\\t\\t\\t\\tfor(let i = 0; i < octree.nodes.length; i++){\\n\\t\\t\\t\\t\\t\\tthis.nodeInfos[i] = new NodeInfo();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst numFiles = octree.files.length;\\n\\t\\t\\t\\tthis.filePlacements = new Array(numFiles).fill(null);\\n\\t\\t\\t\\tif (octree.environmentUrl) {\\n\\t\\t\\t\\t\\t\\toctree.incEnvironmentRefCount();\\n\\t\\t\\t\\t\\t\\toctree.ensureEnvironmentResource();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._deviceLostEvent = device.on('devicelost', this._onDeviceLost, this);\\n\\t\\t}\\n}\\n\\nconst tmpMin = new Vec3();\\nconst tmpMax = new Vec3();\\nclass GSplatOctreeNode {\\n\\t\\tconstructor(lods, boundData){\\n\\t\\t\\t\\tthis.bounds = new BoundingBox();\\n\\t\\t\\t\\tthis.lods = lods;\\n\\t\\t\\t\\ttmpMin.set(boundData.min[0], boundData.min[1], boundData.min[2]);\\n\\t\\t\\t\\ttmpMax.set(boundData.max[0], boundData.max[1], boundData.max[2]);\\n\\t\\t\\t\\tthis.bounds.setMinMax(tmpMin, tmpMax);\\n\\t\\t}\\n}\\n\\nconst _toDelete = [];\\nclass GSplatOctree {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.destroyed = true;\\n\\t\\t\\t\\tthis.fileResources.clear();\\n\\t\\t\\t\\tthis.cooldowns.clear();\\n\\t\\t\\t\\tthis.assetLoader?.destroy();\\n\\t\\t\\t\\tthis.assetLoader = null;\\n\\t\\t\\t\\tthis.environmentResource = null;\\n\\t\\t}\\n\\t\\t_traceLodCounts() {}\\n\\t\\t_extractLeafNodes(node, leafNodes) {\\n\\t\\t\\t\\tif (node.lods) {\\n\\t\\t\\t\\t\\t\\tleafNodes.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tlods: node.lods,\\n\\t\\t\\t\\t\\t\\t\\t\\tbound: node.bound\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t} else if (node.children) {\\n\\t\\t\\t\\t\\t\\tfor (const child of node.children){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._extractLeafNodes(child, leafNodes);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetFileResource(fileIndex) {\\n\\t\\t\\t\\treturn this.fileResources.get(fileIndex);\\n\\t\\t}\\n\\t\\tincRefCount(fileIndex) {\\n\\t\\t\\t\\tconst count = this.fileRefCounts[fileIndex] + 1;\\n\\t\\t\\t\\tthis.fileRefCounts[fileIndex] = count;\\n\\t\\t\\t\\tthis.cooldowns.delete(fileIndex);\\n\\t\\t}\\n\\t\\tdecRefCount(fileIndex, cooldownTicks) {\\n\\t\\t\\t\\tconst count = this.fileRefCounts[fileIndex] - 1;\\n\\t\\t\\t\\tthis.fileRefCounts[fileIndex] = count;\\n\\t\\t\\t\\tif (count === 0) {\\n\\t\\t\\t\\t\\t\\tif (cooldownTicks === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.unloadResource(fileIndex);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.cooldowns.set(fileIndex, cooldownTicks);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tunloadResource(fileIndex) {\\n\\t\\t\\t\\tif (!this.assetLoader) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst fullUrl = this.files[fileIndex].url;\\n\\t\\t\\t\\tthis.assetLoader.unload(fullUrl);\\n\\t\\t\\t\\tif (this.fileResources.has(fileIndex)) {\\n\\t\\t\\t\\t\\t\\tthis.fileResources.delete(fileIndex);\\n\\t\\t\\t\\t\\t\\tthis._traceLodCounts();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateCooldownTick(cooldownTicks) {\\n\\t\\t\\t\\tthis.cooldownTicks = cooldownTicks;\\n\\t\\t\\t\\tif (this.cooldowns.size > 0) {\\n\\t\\t\\t\\t\\t\\tthis.cooldowns.forEach((remaining, fileIndex)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (remaining <= 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this.fileRefCounts[fileIndex] === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.unloadResource(fileIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_toDelete.push(fileIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.cooldowns.set(fileIndex, remaining - 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t_toDelete.forEach((idx)=>this.cooldowns.delete(idx));\\n\\t\\t\\t\\t\\t\\t_toDelete.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tensureFileResource(fileIndex) {\\n\\t\\t\\t\\tif (this.fileResources.has(fileIndex)) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst fullUrl = this.files[fileIndex].url;\\n\\t\\t\\t\\tconst res = this.assetLoader?.getResource(fullUrl);\\n\\t\\t\\t\\tif (res) {\\n\\t\\t\\t\\t\\t\\tthis.fileResources.set(fileIndex, res);\\n\\t\\t\\t\\t\\t\\tif (this.fileRefCounts[fileIndex] === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.cooldowns.set(fileIndex, this.cooldownTicks);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._traceLodCounts();\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.assetLoader?.load(fullUrl);\\n\\t\\t}\\n\\t\\tincEnvironmentRefCount() {\\n\\t\\t\\t\\tthis.environmentRefCount++;\\n\\t\\t}\\n\\t\\tdecEnvironmentRefCount() {\\n\\t\\t\\t\\tthis.environmentRefCount--;\\n\\t\\t\\t\\tif (this.environmentRefCount === 0) {\\n\\t\\t\\t\\t\\t\\tthis.unloadEnvironmentResource();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tensureEnvironmentResource() {\\n\\t\\t\\t\\tif (!this.assetLoader) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this.environmentUrl) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.environmentResource) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst res = this.assetLoader.getResource(this.environmentUrl);\\n\\t\\t\\t\\tif (res) {\\n\\t\\t\\t\\t\\t\\tthis.environmentResource = res;\\n\\t\\t\\t\\t\\t\\tif (this.environmentRefCount === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.unloadEnvironmentResource();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.assetLoader.load(this.environmentUrl);\\n\\t\\t}\\n\\t\\tunloadEnvironmentResource() {\\n\\t\\t\\t\\tif (!this.assetLoader) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.environmentResource && this.environmentUrl) {\\n\\t\\t\\t\\t\\t\\tthis.assetLoader.unload(this.environmentUrl);\\n\\t\\t\\t\\t\\t\\tthis.environmentResource = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(assetFileUrl, data){\\n\\t\\t\\t\\tthis.fileResources = new Map();\\n\\t\\t\\t\\tthis.cooldowns = new Map();\\n\\t\\t\\t\\tthis.environmentUrl = null;\\n\\t\\t\\t\\tthis.environmentResource = null;\\n\\t\\t\\t\\tthis.environmentRefCount = 0;\\n\\t\\t\\t\\tthis.assetLoader = null;\\n\\t\\t\\t\\tthis.destroyed = false;\\n\\t\\t\\t\\tthis.cooldownTicks = 100;\\n\\t\\t\\t\\tthis.lodLevels = data.lodLevels;\\n\\t\\t\\t\\tthis.assetFileUrl = assetFileUrl;\\n\\t\\t\\t\\tconst baseDir = path.getDirectory(assetFileUrl);\\n\\t\\t\\t\\tthis.files = data.filenames.map((url)=>({\\n\\t\\t\\t\\t\\t\\t\\t\\turl: path.isRelativePath(url) ? path.join(baseDir, url) : url,\\n\\t\\t\\t\\t\\t\\t\\t\\tlodLevel: -1\\n\\t\\t\\t\\t\\t\\t}));\\n\\t\\t\\t\\tthis.fileRefCounts = new Int32Array(this.files.length);\\n\\t\\t\\t\\tif (data.environment) {\\n\\t\\t\\t\\t\\t\\tthis.environmentUrl = path.isRelativePath(data.environment) ? path.join(baseDir, data.environment) : data.environment;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst leafNodes = [];\\n\\t\\t\\t\\tthis._extractLeafNodes(data.tree, leafNodes);\\n\\t\\t\\t\\tthis.nodes = leafNodes.map((nodeData)=>{\\n\\t\\t\\t\\t\\t\\tconst lods = [];\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this.lodLevels; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst lodData = nodeData.lods[i.toString()];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (lodData) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlods.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfile: this.files[lodData.file].url || '',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfileIndex: lodData.file,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toffset: lodData.offset || 0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcount: lodData.count || 0\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.files[lodData.file].lodLevel = i;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlods.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfile: '',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfileIndex: -1,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toffset: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcount: 0\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\treturn new GSplatOctreeNode(lods, nodeData.bound);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n}\\n\\nclass GSplatOctreeResource {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.octree?.destroy();\\n\\t\\t\\t\\tthis.octree = null;\\n\\t\\t}\\n\\t\\tconstructor(assetFileUrl, data, assetLoader){\\n\\t\\t\\t\\tthis.aabb = new BoundingBox();\\n\\t\\t\\t\\tthis.centersVersion = 0;\\n\\t\\t\\t\\tthis.octree = new GSplatOctree(assetFileUrl, data);\\n\\t\\t\\t\\tthis.octree.assetLoader = assetLoader;\\n\\t\\t\\t\\tthis.aabb.setMinMax(new Vec3(data.tree.bound.min), new Vec3(data.tree.bound.max));\\n\\t\\t}\\n}\\n\\nclass GSplatWorldState {\\n\\t\\testimateTextureSize(splats, maxSize) {\\n\\t\\t\\t\\tconst fits = (size)=>{\\n\\t\\t\\t\\t\\t\\tlet rows = 0;\\n\\t\\t\\t\\t\\t\\tfor (const splat of splats){\\n\\t\\t\\t\\t\\t\\t\\t\\trows += Math.ceil(splat.activeSplats / size);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (rows > size) return false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tlet low = 1;\\n\\t\\t\\t\\tlet high = maxSize;\\n\\t\\t\\t\\tlet bestSize = null;\\n\\t\\t\\t\\twhile(low <= high){\\n\\t\\t\\t\\t\\t\\tconst mid = Math.floor((low + high) / 2);\\n\\t\\t\\t\\t\\t\\tif (fits(mid)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbestSize = mid;\\n\\t\\t\\t\\t\\t\\t\\t\\thigh = mid - 1;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tlow = mid + 1;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (bestSize === null) {\\n\\t\\t\\t\\t\\t\\tthis.textureSize = 0;\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.textureSize = bestSize;\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.splats.forEach((splat)=>splat.destroy());\\n\\t\\t\\t\\tthis.splats.length = 0;\\n\\t\\t}\\n\\t\\tassignLines(splats, size) {\\n\\t\\t\\t\\tif (splats.length === 0) {\\n\\t\\t\\t\\t\\t\\tthis.totalUsedPixels = 0;\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet start = 0;\\n\\t\\t\\t\\tfor (const splat of splats){\\n\\t\\t\\t\\t\\t\\tconst activeSplats = splat.activeSplats;\\n\\t\\t\\t\\t\\t\\tconst numLines = Math.ceil(activeSplats / size);\\n\\t\\t\\t\\t\\t\\tsplat.setLines(start, numLines, size, activeSplats);\\n\\t\\t\\t\\t\\t\\tstart += numLines;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.totalUsedPixels = start * size;\\n\\t\\t}\\n\\t\\tconstructor(device, version, splats){\\n\\t\\t\\t\\tthis.version = 0;\\n\\t\\t\\t\\tthis.sortParametersSet = false;\\n\\t\\t\\t\\tthis.sortedBefore = false;\\n\\t\\t\\t\\tthis.splats = [];\\n\\t\\t\\t\\tthis.textureSize = 0;\\n\\t\\t\\t\\tthis.totalUsedPixels = 0;\\n\\t\\t\\t\\tthis.pendingReleases = [];\\n\\t\\t\\t\\tthis.version = version;\\n\\t\\t\\t\\tthis.splats = splats;\\n\\t\\t\\t\\tthis.estimateTextureSize(this.splats, device.maxTextureSize);\\n\\t\\t\\t\\tthis.assignLines(this.splats, this.textureSize);\\n\\t\\t}\\n}\\n\\nclass GSplatPlacementStateTracker {\\n\\t\\thasChanges(placements) {\\n\\t\\t\\t\\tlet changed = false;\\n\\t\\t\\t\\tfor (const p of placements){\\n\\t\\t\\t\\t\\t\\tif (!p.resource) continue;\\n\\t\\t\\t\\t\\t\\tconst formatVersion = p.resource.format?.extraStreamsVersion ?? 0;\\n\\t\\t\\t\\t\\t\\tconst modifierHash = p.workBufferModifier?.hash ?? 0;\\n\\t\\t\\t\\t\\t\\tconst numSplats = p.resource.numSplats ?? 0;\\n\\t\\t\\t\\t\\t\\tconst centersVersion = p.resource.centersVersion;\\n\\t\\t\\t\\t\\t\\tconst state = this._states.get(p);\\n\\t\\t\\t\\t\\t\\tif (!state) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._states.set(p, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformatVersion,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmodifierHash,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnumSplats,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcentersVersion\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tchanged = true;\\n\\t\\t\\t\\t\\t\\t} else if (state.formatVersion !== formatVersion || state.modifierHash !== modifierHash || state.numSplats !== numSplats || state.centersVersion !== centersVersion) {\\n\\t\\t\\t\\t\\t\\t\\t\\tstate.formatVersion = formatVersion;\\n\\t\\t\\t\\t\\t\\t\\t\\tstate.modifierHash = modifierHash;\\n\\t\\t\\t\\t\\t\\t\\t\\tstate.numSplats = numSplats;\\n\\t\\t\\t\\t\\t\\t\\t\\tstate.centersVersion = centersVersion;\\n\\t\\t\\t\\t\\t\\t\\t\\tchanged = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn changed;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis._states = new WeakMap();\\n\\t\\t}\\n}\\n\\nconst computeGsplatSortKeySource = `\\n@group(0) @binding(0) var dataTransformA: texture_2d<u32>;\\n@group(0) @binding(1) var<storage, read_write> sortKeys: array<u32>;\\nstruct SortKeyUniforms {\\n\\tcameraPosition: vec3f,\\n\\telementCount: u32,\\n\\tcameraDirection: vec3f,\\n\\tnumBits: u32,\\n\\ttextureSize: u32,\\n\\tminDist: f32,\\n\\tinvRange: f32,\\n\\tnumWorkgroupsX: u32,\\n\\tnumBins: u32\\n};\\n@group(0) @binding(2) var<uniform> uniforms: SortKeyUniforms;\\nstruct BinWeight {\\n\\tbase: f32,\\n\\tdivider: f32\\n};\\n@group(0) @binding(3) var<storage, read> binWeights: array<BinWeight>;\\n@compute @workgroup_size({WORKGROUP_SIZE_X}, {WORKGROUP_SIZE_Y}, 1)\\nfn computeSortKey(@builtin(global_invocation_id) global_id: vec3u) {\\n\\tlet gid = global_id.x + global_id.y * ({WORKGROUP_SIZE_X} * uniforms.numWorkgroupsX);\\n\\t\\n\\tif (gid >= uniforms.elementCount) {\\n\\t\\treturn;\\n\\t}\\n\\t\\n\\tlet textureSize = uniforms.textureSize;\\n\\tlet uv = vec2i(i32(gid % textureSize), i32(gid / textureSize));\\n\\t\\n\\tlet packed = textureLoad(dataTransformA, uv, 0);\\n\\tlet worldCenter = vec3f(\\n\\t\\tbitcast<f32>(packed.r),\\n\\t\\tbitcast<f32>(packed.g),\\n\\t\\tbitcast<f32>(packed.b)\\n\\t);\\n\\t\\n\\tvar dist: f32;\\n\\t\\n\\t#ifdef RADIAL_SORT\\n\\t\\tlet delta = worldCenter - uniforms.cameraPosition;\\n\\t\\tlet radialDist = length(delta);\\n\\t\\tdist = (1.0 / uniforms.invRange) - radialDist - uniforms.minDist;\\n\\t#else\\n\\t\\tlet toSplat = worldCenter - uniforms.cameraPosition;\\n\\t\\tdist = dot(toSplat, uniforms.cameraDirection) - uniforms.minDist;\\n\\t#endif\\n\\t\\n\\tlet numBins = uniforms.numBins;\\n\\tlet d = dist * uniforms.invRange * f32(numBins);\\n\\tlet binFloat = clamp(d, 0.0, f32(numBins) - 0.001);\\n\\tlet bin = u32(binFloat);\\n\\tlet binFrac = binFloat - f32(bin);\\n\\t\\n\\tlet sortKey = u32(binWeights[bin].base + binWeights[bin].divider * binFrac);\\n\\t\\n\\tsortKeys[gid] = sortKey;\\n}\\n`;\\n\\nconst WORKGROUP_SIZE_X = 16;\\nconst WORKGROUP_SIZE_Y = 16;\\nconst THREADS_PER_WORKGROUP = WORKGROUP_SIZE_X * WORKGROUP_SIZE_Y;\\nconst _cameraDir = new Vec3();\\nclass GSplatSortKeyCompute {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.keysBuffer?.destroy();\\n\\t\\t\\t\\tthis.binWeightsBuffer?.destroy();\\n\\t\\t\\t\\tthis.compute?.shader?.destroy();\\n\\t\\t\\t\\tthis.bindGroupFormat?.destroy();\\n\\t\\t\\t\\tthis.keysBuffer = null;\\n\\t\\t\\t\\tthis.binWeightsBuffer = null;\\n\\t\\t\\t\\tthis.compute = null;\\n\\t\\t\\t\\tthis.bindGroupFormat = null;\\n\\t\\t\\t\\tthis.uniformBufferFormat = null;\\n\\t\\t}\\n\\t\\t_getCompute(radialSort) {\\n\\t\\t\\t\\tif (!this.compute || this.computeRadialSort !== radialSort) {\\n\\t\\t\\t\\t\\t\\tthis.compute?.shader?.destroy();\\n\\t\\t\\t\\t\\t\\tconst name = radialSort ? 'GSplatSortKeyCompute-Radial' : 'GSplatSortKeyCompute-Linear';\\n\\t\\t\\t\\t\\t\\tconst cdefines = new Map([\\n\\t\\t\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t'{WORKGROUP_SIZE_X}',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t`${WORKGROUP_SIZE_X}`\\n\\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\\t\\t\\t'{WORKGROUP_SIZE_Y}',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t`${WORKGROUP_SIZE_Y}`\\n\\t\\t\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\tif (radialSort) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcdefines.set('RADIAL_SORT', '');\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst shader = new Shader(this.device, {\\n\\t\\t\\t\\t\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\t\\t\\t\\t\\tshaderLanguage: SHADERLANGUAGE_WGSL,\\n\\t\\t\\t\\t\\t\\t\\t\\tcshader: computeGsplatSortKeySource,\\n\\t\\t\\t\\t\\t\\t\\t\\tcdefines: cdefines,\\n\\t\\t\\t\\t\\t\\t\\t\\tcomputeEntryPoint: 'computeSortKey',\\n\\t\\t\\t\\t\\t\\t\\t\\tcomputeBindGroupFormat: this.bindGroupFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tcomputeUniformBufferFormats: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuniforms: this.uniformBufferFormat\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tthis.compute = new Compute(this.device, shader, name);\\n\\t\\t\\t\\t\\t\\tthis.computeRadialSort = radialSort;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.compute;\\n\\t\\t}\\n\\t\\t_createBindGroupFormat() {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tthis.uniformBufferFormat = new UniformBufferFormat(device, [\\n\\t\\t\\t\\t\\t\\tnew UniformFormat('cameraPosition', UNIFORMTYPE_VEC3),\\n\\t\\t\\t\\t\\t\\tnew UniformFormat('elementCount', UNIFORMTYPE_UINT),\\n\\t\\t\\t\\t\\t\\tnew UniformFormat('cameraDirection', UNIFORMTYPE_VEC3),\\n\\t\\t\\t\\t\\t\\tnew UniformFormat('numBits', UNIFORMTYPE_UINT),\\n\\t\\t\\t\\t\\t\\tnew UniformFormat('textureSize', UNIFORMTYPE_UINT),\\n\\t\\t\\t\\t\\t\\tnew UniformFormat('minDist', UNIFORMTYPE_FLOAT),\\n\\t\\t\\t\\t\\t\\tnew UniformFormat('invRange', UNIFORMTYPE_FLOAT),\\n\\t\\t\\t\\t\\t\\tnew UniformFormat('numWorkgroupsX', UNIFORMTYPE_UINT),\\n\\t\\t\\t\\t\\t\\tnew UniformFormat('numBins', UNIFORMTYPE_UINT)\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tthis.bindGroupFormat = new BindGroupFormat(device, [\\n\\t\\t\\t\\t\\t\\tnew BindTextureFormat('dataTransformA', SHADERSTAGE_COMPUTE, undefined, SAMPLETYPE_UINT, false),\\n\\t\\t\\t\\t\\t\\tnew BindStorageBufferFormat('sortKeys', SHADERSTAGE_COMPUTE, false),\\n\\t\\t\\t\\t\\t\\tnew BindUniformBufferFormat('uniforms', SHADERSTAGE_COMPUTE),\\n\\t\\t\\t\\t\\t\\tnew BindStorageBufferFormat('binWeights', SHADERSTAGE_COMPUTE, true)\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\t_ensureCapacity(elementCount) {\\n\\t\\t\\t\\tif (elementCount > this.allocatedCount) {\\n\\t\\t\\t\\t\\t\\tthis.keysBuffer?.destroy();\\n\\t\\t\\t\\t\\t\\tthis.allocatedCount = elementCount;\\n\\t\\t\\t\\t\\t\\tthis.keysBuffer = new StorageBuffer(this.device, elementCount * 4, BUFFERUSAGE_COPY_SRC);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgenerate(workBuffer, cameraNode, radialSort, elementCount, numBits, minDist, maxDist) {\\n\\t\\t\\t\\tthis._ensureCapacity(elementCount);\\n\\t\\t\\t\\tconst workgroupCount = Math.ceil(elementCount / THREADS_PER_WORKGROUP);\\n\\t\\t\\t\\tconst numWorkgroupsX = Math.min(workgroupCount, this.device.limits.maxComputeWorkgroupsPerDimension || 65535);\\n\\t\\t\\t\\tconst numWorkgroupsY = Math.ceil(workgroupCount / numWorkgroupsX);\\n\\t\\t\\t\\tconst compute = this._getCompute(radialSort);\\n\\t\\t\\t\\tconst cameraPos = cameraNode.getPosition();\\n\\t\\t\\t\\tconst cameraMat = cameraNode.getWorldTransform();\\n\\t\\t\\t\\tconst cameraDir = cameraMat.getZ(_cameraDir).normalize();\\n\\t\\t\\t\\tconst range = maxDist - minDist;\\n\\t\\t\\t\\tconst invRange = range > 0 ? 1.0 / range : 1.0;\\n\\t\\t\\t\\tconst bucketCount = 1 << numBits;\\n\\t\\t\\t\\tconst cameraBin = GSplatSortBinWeights$1.computeCameraBin(radialSort, minDist, range);\\n\\t\\t\\t\\tconst binWeights = this.binWeightsUtil.compute(cameraBin, bucketCount);\\n\\t\\t\\t\\tthis.binWeightsBuffer.write(0, binWeights);\\n\\t\\t\\t\\tcompute.setParameter('dataTransformA', workBuffer.getTexture('dataTransformA'));\\n\\t\\t\\t\\tcompute.setParameter('sortKeys', this.keysBuffer);\\n\\t\\t\\t\\tcompute.setParameter('binWeights', this.binWeightsBuffer);\\n\\t\\t\\t\\tthis.cameraPositionData[0] = cameraPos.x;\\n\\t\\t\\t\\tthis.cameraPositionData[1] = cameraPos.y;\\n\\t\\t\\t\\tthis.cameraPositionData[2] = cameraPos.z;\\n\\t\\t\\t\\tcompute.setParameter('cameraPosition', this.cameraPositionData);\\n\\t\\t\\t\\tthis.cameraDirectionData[0] = cameraDir.x;\\n\\t\\t\\t\\tthis.cameraDirectionData[1] = cameraDir.y;\\n\\t\\t\\t\\tthis.cameraDirectionData[2] = cameraDir.z;\\n\\t\\t\\t\\tcompute.setParameter('cameraDirection', this.cameraDirectionData);\\n\\t\\t\\t\\tcompute.setParameter('elementCount', elementCount);\\n\\t\\t\\t\\tcompute.setParameter('numBits', numBits);\\n\\t\\t\\t\\tcompute.setParameter('textureSize', workBuffer.textureSize);\\n\\t\\t\\t\\tcompute.setParameter('minDist', minDist);\\n\\t\\t\\t\\tcompute.setParameter('invRange', invRange);\\n\\t\\t\\t\\tcompute.setParameter('numWorkgroupsX', numWorkgroupsX);\\n\\t\\t\\t\\tcompute.setParameter('numBins', GSplatSortBinWeights$1.NUM_BINS);\\n\\t\\t\\t\\tcompute.setupDispatch(numWorkgroupsX, numWorkgroupsY, 1);\\n\\t\\t\\t\\tthis.device.computeDispatch([\\n\\t\\t\\t\\t\\t\\tcompute\\n\\t\\t\\t\\t], 'GSplatSortKeyCompute');\\n\\t\\t\\t\\treturn this.keysBuffer;\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis.allocatedCount = 0;\\n\\t\\t\\t\\tthis.keysBuffer = null;\\n\\t\\t\\t\\tthis.binWeightsBuffer = null;\\n\\t\\t\\t\\tthis.compute = null;\\n\\t\\t\\t\\tthis.computeRadialSort = false;\\n\\t\\t\\t\\tthis.bindGroupFormat = null;\\n\\t\\t\\t\\tthis.uniformBufferFormat = null;\\n\\t\\t\\t\\tthis.cameraPositionData = new Float32Array(3);\\n\\t\\t\\t\\tthis.cameraDirectionData = new Float32Array(3);\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.binWeightsUtil = new GSplatSortBinWeights$1();\\n\\t\\t\\t\\tthis.binWeightsBuffer = new StorageBuffer(device, GSplatSortBinWeights$1.NUM_BINS * 2 * 4, BUFFERUSAGE_COPY_SRC | BUFFERUSAGE_COPY_DST);\\n\\t\\t\\t\\tthis._createBindGroupFormat();\\n\\t\\t}\\n}\\n\\nconst cameraPosition = new Vec3();\\nconst cameraDirection = new Vec3();\\nconst translation = new Vec3();\\nconst _cornerPoint = new Vec3();\\nconst invModelMat = new Mat4();\\nconst tempNonOctreePlacements = new Set();\\nconst tempOctreePlacements = new Set();\\nconst _updatedSplats = [];\\nconst _splatsNeedingColorUpdate = [];\\nconst _cameraDeltas = {\\n\\t\\trotationDelta: 0,\\n\\t\\ttranslationDelta: 0\\n};\\nconst tempOctreesTicked = new Set();\\nconst _lodColorsRaw = [\\n\\t\\t[\\n\\t\\t\\t\\t1,\\n\\t\\t\\t\\t0,\\n\\t\\t\\t\\t0\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t0,\\n\\t\\t\\t\\t1,\\n\\t\\t\\t\\t0\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t0,\\n\\t\\t\\t\\t0,\\n\\t\\t\\t\\t1\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t1,\\n\\t\\t\\t\\t1,\\n\\t\\t\\t\\t0\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t1,\\n\\t\\t\\t\\t0,\\n\\t\\t\\t\\t1\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t0,\\n\\t\\t\\t\\t1,\\n\\t\\t\\t\\t1\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t1,\\n\\t\\t\\t\\t0.5,\\n\\t\\t\\t\\t0\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t0.5,\\n\\t\\t\\t\\t0,\\n\\t\\t\\t\\t1\\n\\t\\t]\\n];\\n[\\n\\t\\tnew Color(1, 0, 0),\\n\\t\\tnew Color(0, 1, 0),\\n\\t\\tnew Color(0, 0, 1),\\n\\t\\tnew Color(1, 1, 0),\\n\\t\\tnew Color(1, 0, 1),\\n\\t\\tnew Color(0, 1, 1),\\n\\t\\tnew Color(1, 0.5, 0),\\n\\t\\tnew Color(0.5, 0, 1)\\n];\\nlet _randomColorRaw = null;\\nclass GSplatManager {\\n\\t\\tsetRenderMode(renderMode) {\\n\\t\\t\\t\\tthis.renderMode = renderMode;\\n\\t\\t\\t\\tthis.renderer.setRenderMode(renderMode);\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._destroyed = true;\\n\\t\\t\\t\\tfor (const [, worldState] of this.worldStates){\\n\\t\\t\\t\\t\\t\\tfor (const splat of worldState.splats){\\n\\t\\t\\t\\t\\t\\t\\t\\tsplat.resource.decRefCount();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tworldState.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.worldStates.clear();\\n\\t\\t\\t\\tfor (const [, instance] of this.octreeInstances){\\n\\t\\t\\t\\t\\t\\tinstance.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.octreeInstances.clear();\\n\\t\\t\\t\\tfor (const instance of this.octreeInstancesToDestroy){\\n\\t\\t\\t\\t\\t\\tinstance.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.octreeInstancesToDestroy.length = 0;\\n\\t\\t\\t\\tthis.workBuffer.destroy();\\n\\t\\t\\t\\tthis.renderer.destroy();\\n\\t\\t\\t\\tthis.keyGenerator?.destroy();\\n\\t\\t\\t\\tthis.gpuSorter?.destroy();\\n\\t\\t\\t\\tthis.cpuSorter?.destroy();\\n\\t\\t}\\n\\t\\tget material() {\\n\\t\\t\\t\\treturn this.renderer.material;\\n\\t\\t}\\n\\t\\tcreateSorter() {\\n\\t\\t\\t\\tconst sorter = new GSplatUnifiedSorter(this.scene);\\n\\t\\t\\t\\tsorter.on('sorted', (count, version, orderData)=>{\\n\\t\\t\\t\\t\\t\\tthis.onSorted(count, version, orderData);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn sorter;\\n\\t\\t}\\n\\t\\treconcile(placements) {\\n\\t\\t\\t\\ttempNonOctreePlacements.clear();\\n\\t\\t\\t\\tfor (const p of placements){\\n\\t\\t\\t\\t\\t\\tif (p.resource instanceof GSplatOctreeResource) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this.octreeInstances.has(p)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.octreeInstances.set(p, new GSplatOctreeInstance(this.device, p.resource.octree, p));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.hasNewOctreeInstances = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\ttempOctreePlacements.add(p);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\ttempNonOctreePlacements.add(p);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const [placement, inst] of this.octreeInstances){\\n\\t\\t\\t\\t\\t\\tif (!tempOctreePlacements.has(placement)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.octreeInstances.delete(placement);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.layerPlacementsDirty = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.octreeInstancesToDestroy.push(inst);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.layerPlacementsDirty = this.layerPlacements.length !== tempNonOctreePlacements.size;\\n\\t\\t\\t\\tif (!this.layerPlacementsDirty) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this.layerPlacements.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst existing = this.layerPlacements[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!tempNonOctreePlacements.has(existing)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.layerPlacementsDirty = true;\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.layerPlacements.length = 0;\\n\\t\\t\\t\\tfor (const p of tempNonOctreePlacements){\\n\\t\\t\\t\\t\\t\\tthis.layerPlacements.push(p);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttempNonOctreePlacements.clear();\\n\\t\\t\\t\\ttempOctreePlacements.clear();\\n\\t\\t}\\n\\t\\tupdateWorldState() {\\n\\t\\t\\t\\tlet stateChanged = this._stateTracker.hasChanges(this.layerPlacements);\\n\\t\\t\\t\\tfor (const [, inst] of this.octreeInstances){\\n\\t\\t\\t\\t\\t\\tif (this._stateTracker.hasChanges(inst.activePlacements)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tstateChanged = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst worldChanged = this.layerPlacementsDirty || stateChanged || this.worldStates.size === 0;\\n\\t\\t\\t\\tif (worldChanged) {\\n\\t\\t\\t\\t\\t\\tthis.lastWorldStateVersion++;\\n\\t\\t\\t\\t\\t\\tconst splats = [];\\n\\t\\t\\t\\t\\t\\tconst { colorUpdateAngle, colorUpdateDistance } = this.scene.gsplat;\\n\\t\\t\\t\\t\\t\\tfor (const p of this.layerPlacements){\\n\\t\\t\\t\\t\\t\\t\\t\\tp.ensureInstanceStreams(this.device);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst splatInfo = new GSplatInfo(this.device, p.resource, p, p.consumeRenderDirty.bind(p));\\n\\t\\t\\t\\t\\t\\t\\t\\tsplatInfo.resetColorAccumulators(colorUpdateAngle, colorUpdateDistance);\\n\\t\\t\\t\\t\\t\\t\\t\\tsplats.push(splatInfo);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor (const [, inst] of this.octreeInstances){\\n\\t\\t\\t\\t\\t\\t\\t\\tinst.activePlacements.forEach((p)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (p.resource) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tp.ensureInstanceStreams(this.device);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst splatInfo = new GSplatInfo(this.device, p.resource, p, p.consumeRenderDirty.bind(p));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsplatInfo.resetColorAccumulators(colorUpdateAngle, colorUpdateDistance);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsplats.push(splatInfo);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tif (this.cpuSorter) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor (const splat of splats){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst resource = splat.resource;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst lastVersion = this._centersVersions.get(resource.id);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (lastVersion !== resource.centersVersion) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._centersVersions.set(resource.id, resource.centersVersion);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.cpuSorter.setCenters(resource.id, null);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.cpuSorter.setCenters(resource.id, resource.centers);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tthis.cpuSorter?.updateCentersForSplats(splats);\\n\\t\\t\\t\\t\\t\\tconst newState = new GSplatWorldState(this.device, this.lastWorldStateVersion, splats);\\n\\t\\t\\t\\t\\t\\tfor (const splat of newState.splats){\\n\\t\\t\\t\\t\\t\\t\\t\\tsplat.resource.incRefCount();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor (const [, inst] of this.octreeInstances){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (inst.removedCandidates && inst.removedCandidates.size) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor (const fileIndex of inst.removedCandidates){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnewState.pendingReleases.push([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinst.octree,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfileIndex\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinst.removedCandidates.clear();\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.octreeInstancesToDestroy.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor (const inst of this.octreeInstancesToDestroy){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst toRelease = inst.getFileDecrements();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor (const fileIndex of toRelease){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnewState.pendingReleases.push([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinst.octree,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfileIndex\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinst.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.octreeInstancesToDestroy.length = 0;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.worldStates.set(this.lastWorldStateVersion, newState);\\n\\t\\t\\t\\t\\t\\tthis.layerPlacementsDirty = false;\\n\\t\\t\\t\\t\\t\\tthis.sortNeeded = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonSorted(count, version, orderData) {\\n\\t\\t\\t\\tthis.cleanupOldWorldStates(version);\\n\\t\\t\\t\\tthis.sortedVersion = version;\\n\\t\\t\\t\\tconst worldState = this.worldStates.get(version);\\n\\t\\t\\t\\tif (worldState) {\\n\\t\\t\\t\\t\\t\\tif (!worldState.sortedBefore) {\\n\\t\\t\\t\\t\\t\\t\\t\\tworldState.sortedBefore = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.rebuildWorkBuffer(worldState, count);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.workBuffer.setOrderData(orderData);\\n\\t\\t\\t\\t\\t\\tthis.renderer.setOrderData();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\trebuildWorkBuffer(worldState, count) {\\n\\t\\t\\t\\tconst textureSize = worldState.textureSize;\\n\\t\\t\\t\\tif (textureSize !== this.workBuffer.textureSize) {\\n\\t\\t\\t\\t\\t\\tthis.workBuffer.resize(textureSize);\\n\\t\\t\\t\\t\\t\\tthis.renderer.setMaxNumSplats(textureSize * textureSize);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.workBuffer.render(worldState.splats, this.cameraNode, this.getDebugColors());\\n\\t\\t\\t\\tconst { colorUpdateAngle, colorUpdateDistance } = this.scene.gsplat;\\n\\t\\t\\t\\tworldState.splats.forEach((splat)=>{\\n\\t\\t\\t\\t\\t\\tsplat.update();\\n\\t\\t\\t\\t\\t\\tsplat.resetColorAccumulators(colorUpdateAngle, colorUpdateDistance);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.updateColorCameraTracking();\\n\\t\\t\\t\\tif (worldState.pendingReleases && worldState.pendingReleases.length) {\\n\\t\\t\\t\\t\\t\\tconst cooldownTicks = this.scene.gsplat.cooldownTicks;\\n\\t\\t\\t\\t\\t\\tfor (const [octree, fileIndex] of worldState.pendingReleases){\\n\\t\\t\\t\\t\\t\\t\\t\\toctree.decRefCount(fileIndex, cooldownTicks);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tworldState.pendingReleases.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.renderer.update(count, textureSize);\\n\\t\\t}\\n\\t\\tcleanupOldWorldStates(newVersion) {\\n\\t\\t\\t\\tfor(let v = this.sortedVersion; v < newVersion; v++){\\n\\t\\t\\t\\t\\t\\tconst oldState = this.worldStates.get(v);\\n\\t\\t\\t\\t\\t\\tif (oldState) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor (const splat of oldState.splats){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsplat.resource.decRefCount();\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.worldStates.delete(v);\\n\\t\\t\\t\\t\\t\\t\\t\\toldState.destroy();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tapplyWorkBufferUpdates(state) {\\n\\t\\t\\t\\tconst { colorUpdateAngle, colorUpdateDistance, colorUpdateDistanceLodScale, colorUpdateAngleLodScale } = this.scene.gsplat;\\n\\t\\t\\t\\tconst { rotationDelta, translationDelta } = this.calculateColorCameraDeltas();\\n\\t\\t\\t\\tstate.splats.forEach((splat)=>{\\n\\t\\t\\t\\t\\t\\tif (splat.update()) {\\n\\t\\t\\t\\t\\t\\t\\t\\t_updatedSplats.push(splat);\\n\\t\\t\\t\\t\\t\\t\\t\\tsplat.resetColorAccumulators(colorUpdateAngle, colorUpdateDistance);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.sortNeeded = true;\\n\\t\\t\\t\\t\\t\\t} else if (splat.hasSphericalHarmonics) {\\n\\t\\t\\t\\t\\t\\t\\t\\tsplat.colorAccumulatedRotation += rotationDelta;\\n\\t\\t\\t\\t\\t\\t\\t\\tsplat.colorAccumulatedTranslation += translationDelta;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst lodIndex = splat.lodIndex ?? 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst distThreshold = colorUpdateDistance * Math.pow(colorUpdateDistanceLodScale, lodIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst angleThreshold = colorUpdateAngle * Math.pow(colorUpdateAngleLodScale, lodIndex);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (splat.colorAccumulatedRotation >= angleThreshold || splat.colorAccumulatedTranslation >= distThreshold) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t_splatsNeedingColorUpdate.push(splat);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsplat.resetColorAccumulators(angleThreshold, distThreshold);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (_updatedSplats.length > 0) {\\n\\t\\t\\t\\t\\t\\tthis.workBuffer.render(_updatedSplats, this.cameraNode, this.getDebugColors());\\n\\t\\t\\t\\t\\t\\t_updatedSplats.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (_splatsNeedingColorUpdate.length > 0) {\\n\\t\\t\\t\\t\\t\\tthis.workBuffer.renderColor(_splatsNeedingColorUpdate, this.cameraNode, this.getDebugColors());\\n\\t\\t\\t\\t\\t\\t_splatsNeedingColorUpdate.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\ttestCameraMovedForLod() {\\n\\t\\t\\t\\tconst distanceThreshold = this.scene.gsplat.lodUpdateDistance;\\n\\t\\t\\t\\tconst currentCameraPos = this.cameraNode.getPosition();\\n\\t\\t\\t\\tconst cameraMoved = this.lastLodCameraPos.distance(currentCameraPos) > distanceThreshold;\\n\\t\\t\\t\\tif (cameraMoved) {\\n\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet cameraRotated = false;\\n\\t\\t\\t\\tconst lodUpdateAngleDeg = this.scene.gsplat.lodUpdateAngle;\\n\\t\\t\\t\\tif (lodUpdateAngleDeg > 0) {\\n\\t\\t\\t\\t\\t\\tif (Number.isFinite(this.lastLodCameraFwd.x)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst currentCameraFwd = this.cameraNode.forward;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dot = Math.min(1, Math.max(-1, this.lastLodCameraFwd.dot(currentCameraFwd)));\\n\\t\\t\\t\\t\\t\\t\\t\\tconst angle = Math.acos(dot);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst rotThreshold = lodUpdateAngleDeg * math.DEG_TO_RAD;\\n\\t\\t\\t\\t\\t\\t\\t\\tcameraRotated = angle > rotThreshold;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tcameraRotated = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn cameraMoved || cameraRotated;\\n\\t\\t}\\n\\t\\ttestCameraMovedForSort() {\\n\\t\\t\\t\\tconst epsilon = 0.001;\\n\\t\\t\\t\\tif (this.scene.gsplat.radialSorting) {\\n\\t\\t\\t\\t\\t\\tconst currentCameraPos = this.cameraNode.getPosition();\\n\\t\\t\\t\\t\\t\\tconst distance = this.lastSortCameraPos.distance(currentCameraPos);\\n\\t\\t\\t\\t\\t\\treturn distance > epsilon;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (Number.isFinite(this.lastSortCameraFwd.x)) {\\n\\t\\t\\t\\t\\t\\tconst currentCameraFwd = this.cameraNode.forward;\\n\\t\\t\\t\\t\\t\\tconst dot = Math.min(1, Math.max(-1, this.lastSortCameraFwd.dot(currentCameraFwd)));\\n\\t\\t\\t\\t\\t\\tconst angle = Math.acos(dot);\\n\\t\\t\\t\\t\\t\\treturn angle > epsilon;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tupdateColorCameraTracking() {\\n\\t\\t\\t\\tthis.lastColorUpdateCameraPos.copy(this.cameraNode.getPosition());\\n\\t\\t\\t\\tthis.lastColorUpdateCameraFwd.copy(this.cameraNode.forward);\\n\\t\\t}\\n\\t\\tgetDebugColors() {\\n\\t\\t\\t\\tif (this.scene.gsplat.colorizeColorUpdate) {\\n\\t\\t\\t\\t\\t\\t_randomColorRaw ?? (_randomColorRaw = []);\\n\\t\\t\\t\\t\\t\\tconst r = Math.random();\\n\\t\\t\\t\\t\\t\\tconst g = Math.random();\\n\\t\\t\\t\\t\\t\\tconst b = Math.random();\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < _lodColorsRaw.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tvar _randomColorRaw1, _i;\\n\\t\\t\\t\\t\\t\\t\\t\\t(_randomColorRaw1 = _randomColorRaw)[_i = i] ?? (_randomColorRaw1[_i] = [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\t\\t\\t_randomColorRaw[i][0] = r;\\n\\t\\t\\t\\t\\t\\t\\t\\t_randomColorRaw[i][1] = g;\\n\\t\\t\\t\\t\\t\\t\\t\\t_randomColorRaw[i][2] = b;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn _randomColorRaw;\\n\\t\\t\\t\\t} else if (this.scene.gsplat.colorizeLod) {\\n\\t\\t\\t\\t\\t\\treturn _lodColorsRaw;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn undefined;\\n\\t\\t}\\n\\t\\tcalculateColorCameraDeltas() {\\n\\t\\t\\t\\t_cameraDeltas.rotationDelta = 0;\\n\\t\\t\\t\\t_cameraDeltas.translationDelta = 0;\\n\\t\\t\\t\\tif (isFinite(this.lastColorUpdateCameraPos.x)) {\\n\\t\\t\\t\\t\\t\\tconst currentCameraFwd = this.cameraNode.forward;\\n\\t\\t\\t\\t\\t\\tconst dot = Math.min(1, Math.max(-1, this.lastColorUpdateCameraFwd.dot(currentCameraFwd)));\\n\\t\\t\\t\\t\\t\\t_cameraDeltas.rotationDelta = Math.acos(dot) * math.RAD_TO_DEG;\\n\\t\\t\\t\\t\\t\\tconst currentCameraPos = this.cameraNode.getPosition();\\n\\t\\t\\t\\t\\t\\t_cameraDeltas.translationDelta = this.lastColorUpdateCameraPos.distance(currentCameraPos);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn _cameraDeltas;\\n\\t\\t}\\n\\t\\tfireFrameReadyEvent() {\\n\\t\\t\\t\\tconst ready = this.sortedVersion === this.lastWorldStateVersion;\\n\\t\\t\\t\\tlet loadingCount = 0;\\n\\t\\t\\t\\tfor (const [, inst] of this.octreeInstances){\\n\\t\\t\\t\\t\\t\\tloadingCount += inst.pendingLoadCount;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.director.eventHandler.fire('frame:ready', this.cameraNode.camera, this.renderer.layer, ready, loadingCount);\\n\\t\\t}\\n\\t\\tupdate() {\\n\\t\\t\\t\\tconst wbFormatVersion = this.workBuffer.format.extraStreamsVersion;\\n\\t\\t\\t\\tif (this._workBufferFormatVersion !== wbFormatVersion) {\\n\\t\\t\\t\\t\\t\\tthis._workBufferFormatVersion = wbFormatVersion;\\n\\t\\t\\t\\t\\t\\tthis.workBuffer.syncWithFormat();\\n\\t\\t\\t\\t\\t\\tthis._workBufferRebuildRequired = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.cpuSorter) {\\n\\t\\t\\t\\t\\t\\tthis.cpuSorter.applyPendingSorted();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst sorterAvailable = this.useGpuSorting || this.cpuSorter && this.cpuSorter.jobsInFlight < 3;\\n\\t\\t\\t\\tlet fullUpdate = false;\\n\\t\\t\\t\\tthis.framesTillFullUpdate--;\\n\\t\\t\\t\\tif (this.framesTillFullUpdate <= 0) {\\n\\t\\t\\t\\t\\t\\tthis.framesTillFullUpdate = 10;\\n\\t\\t\\t\\t\\t\\tif (sorterAvailable) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfullUpdate = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst hasNewInstances = this.hasNewOctreeInstances && sorterAvailable;\\n\\t\\t\\t\\tif (hasNewInstances) this.hasNewOctreeInstances = false;\\n\\t\\t\\t\\tlet anyInstanceNeedsLodUpdate = false;\\n\\t\\t\\t\\tlet anyOctreeMoved = false;\\n\\t\\t\\t\\tlet cameraMovedOrRotatedForLod = false;\\n\\t\\t\\t\\tif (fullUpdate) {\\n\\t\\t\\t\\t\\t\\tfor (const [, inst] of this.octreeInstances){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst isDirty = inst.update(this.scene);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.layerPlacementsDirty || (this.layerPlacementsDirty = isDirty);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst instNeeds = inst.consumeNeedsLodUpdate();\\n\\t\\t\\t\\t\\t\\t\\t\\tanyInstanceNeedsLodUpdate || (anyInstanceNeedsLodUpdate = instNeeds);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst threshold = this.scene.gsplat.lodUpdateDistance;\\n\\t\\t\\t\\t\\t\\tfor (const [, inst] of this.octreeInstances){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst moved = inst.testMoved(threshold);\\n\\t\\t\\t\\t\\t\\t\\t\\tanyOctreeMoved || (anyOctreeMoved = moved);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcameraMovedOrRotatedForLod = this.testCameraMovedForLod();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.testCameraMovedForSort()) {\\n\\t\\t\\t\\t\\t\\tthis.sortNeeded = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.scene.gsplat.dirty) {\\n\\t\\t\\t\\t\\t\\tthis.layerPlacementsDirty = true;\\n\\t\\t\\t\\t\\t\\tthis.renderer.updateOverdrawMode(this.scene.gsplat);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (cameraMovedOrRotatedForLod || anyOctreeMoved || this.scene.gsplat.dirty || anyInstanceNeedsLodUpdate || hasNewInstances) {\\n\\t\\t\\t\\t\\t\\tfor (const [, inst] of this.octreeInstances){\\n\\t\\t\\t\\t\\t\\t\\t\\tinst.updateMoved();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.lastLodCameraPos.copy(this.cameraNode.getPosition());\\n\\t\\t\\t\\t\\t\\tthis.lastLodCameraFwd.copy(this.cameraNode.forward);\\n\\t\\t\\t\\t\\t\\tfor (const [, inst] of this.octreeInstances){\\n\\t\\t\\t\\t\\t\\t\\t\\tinst.updateLod(this.cameraNode, this.scene.gsplat);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.updateWorldState();\\n\\t\\t\\t\\tconst lastState = this.worldStates.get(this.lastWorldStateVersion);\\n\\t\\t\\t\\tif (lastState) {\\n\\t\\t\\t\\t\\t\\tif (this.cpuSorter && !lastState.sortParametersSet) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlastState.sortParametersSet = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst payload = this.prepareSortParameters(lastState);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.cpuSorter.setSortParameters(payload);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst sortedState = this.worldStates.get(this.sortedVersion);\\n\\t\\t\\t\\tif (sortedState) {\\n\\t\\t\\t\\t\\t\\tif (this._workBufferRebuildRequired) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.rebuildWorkBuffer(sortedState, sortedState.totalUsedPixels);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._workBufferRebuildRequired = false;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.applyWorkBufferUpdates(sortedState);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.sortNeeded && lastState) {\\n\\t\\t\\t\\t\\t\\tif (this.useGpuSorting) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.sortGpu(lastState);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.sortCpu(lastState);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.sortNeeded = false;\\n\\t\\t\\t\\t\\t\\tthis.lastSortCameraPos.copy(this.cameraNode.getPosition());\\n\\t\\t\\t\\t\\t\\tthis.lastSortCameraFwd.copy(this.cameraNode.forward);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (sortedState) {\\n\\t\\t\\t\\t\\t\\tthis.renderer.frameUpdate(this.scene.gsplat);\\n\\t\\t\\t\\t\\t\\tthis.updateColorCameraTracking();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.octreeInstances.size) {\\n\\t\\t\\t\\t\\t\\tconst cooldownTicks = this.scene.gsplat.cooldownTicks;\\n\\t\\t\\t\\t\\t\\tfor (const [, inst] of this.octreeInstances){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst octree = inst.octree;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!tempOctreesTicked.has(octree)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttempOctreesTicked.add(octree);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toctree.updateCooldownTick(cooldownTicks);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\ttempOctreesTicked.clear();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.fireFrameReadyEvent();\\n\\t\\t\\t\\tconst { textureSize } = this.workBuffer;\\n\\t\\t\\t\\treturn textureSize * textureSize;\\n\\t\\t}\\n\\t\\tsortGpu(worldState) {\\n\\t\\t\\t\\tconst keyGenerator = this.keyGenerator;\\n\\t\\t\\t\\tconst gpuSorter = this.gpuSorter;\\n\\t\\t\\t\\tif (!keyGenerator || !gpuSorter) return;\\n\\t\\t\\t\\tconst elementCount = worldState.totalUsedPixels;\\n\\t\\t\\t\\tif (elementCount === 0) return;\\n\\t\\t\\t\\tif (!worldState.sortedBefore) {\\n\\t\\t\\t\\t\\t\\tworldState.sortedBefore = true;\\n\\t\\t\\t\\t\\t\\tthis.rebuildWorkBuffer(worldState, elementCount);\\n\\t\\t\\t\\t\\t\\tthis.cleanupOldWorldStates(worldState.version);\\n\\t\\t\\t\\t\\t\\tthis.sortedVersion = worldState.version;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst numBits = Math.max(10, Math.min(20, Math.round(Math.log2(elementCount / 4))));\\n\\t\\t\\t\\tconst roundedNumBits = Math.ceil(numBits / 4) * 4;\\n\\t\\t\\t\\tconst { minDist, maxDist } = this.computeDistanceRange(worldState);\\n\\t\\t\\t\\tconst keysBuffer = keyGenerator.generate(this.workBuffer, this.cameraNode, this.scene.gsplat.radialSorting, elementCount, roundedNumBits, minDist, maxDist);\\n\\t\\t\\t\\tconst sortedIndices = gpuSorter.sort(keysBuffer, elementCount, roundedNumBits);\\n\\t\\t\\t\\tthis.renderer.setOrderBuffer(sortedIndices);\\n\\t\\t\\t\\tthis.renderer.update(elementCount, worldState.textureSize);\\n\\t\\t}\\n\\t\\tcomputeDistanceRange(worldState) {\\n\\t\\t\\t\\tconst cameraNode = this.cameraNode;\\n\\t\\t\\t\\tconst cameraMat = cameraNode.getWorldTransform();\\n\\t\\t\\t\\tcameraMat.getTranslation(cameraPosition);\\n\\t\\t\\t\\tcameraMat.getZ(cameraDirection).normalize();\\n\\t\\t\\t\\tconst radialSort = this.scene.gsplat.radialSorting;\\n\\t\\t\\t\\tlet minDist = radialSort ? 0 : Infinity;\\n\\t\\t\\t\\tlet maxDist = radialSort ? 0 : -Infinity;\\n\\t\\t\\t\\tfor (const splat of worldState.splats){\\n\\t\\t\\t\\t\\t\\tconst modelMat = splat.node.getWorldTransform();\\n\\t\\t\\t\\t\\t\\tconst aabbMin = splat.aabb.getMin();\\n\\t\\t\\t\\t\\t\\tconst aabbMax = splat.aabb.getMax();\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < 8; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t_cornerPoint.x = i & 1 ? aabbMax.x : aabbMin.x;\\n\\t\\t\\t\\t\\t\\t\\t\\t_cornerPoint.y = i & 2 ? aabbMax.y : aabbMin.y;\\n\\t\\t\\t\\t\\t\\t\\t\\t_cornerPoint.z = i & 4 ? aabbMax.z : aabbMin.z;\\n\\t\\t\\t\\t\\t\\t\\t\\tmodelMat.transformPoint(_cornerPoint, _cornerPoint);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (radialSort) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst dist = _cornerPoint.distance(cameraPosition);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (dist > maxDist) maxDist = dist;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst dist = _cornerPoint.sub(cameraPosition).dot(cameraDirection);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (dist < minDist) minDist = dist;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (dist > maxDist) maxDist = dist;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (maxDist === 0 || maxDist === -Infinity) {\\n\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\tminDist: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tmaxDist: 1\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tminDist,\\n\\t\\t\\t\\t\\t\\tmaxDist\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tsortCpu(lastState) {\\n\\t\\t\\t\\tif (!this.cpuSorter) return;\\n\\t\\t\\t\\tconst cameraNode = this.cameraNode;\\n\\t\\t\\t\\tconst cameraMat = cameraNode.getWorldTransform();\\n\\t\\t\\t\\tcameraMat.getTranslation(cameraPosition);\\n\\t\\t\\t\\tcameraMat.getZ(cameraDirection).normalize();\\n\\t\\t\\t\\tconst sorterRequest = [];\\n\\t\\t\\t\\tlastState.splats.forEach((splat)=>{\\n\\t\\t\\t\\t\\t\\tconst modelMat = splat.node.getWorldTransform();\\n\\t\\t\\t\\t\\t\\tinvModelMat.copy(modelMat).invert();\\n\\t\\t\\t\\t\\t\\tconst uniformScale = modelMat.getScale().x;\\n\\t\\t\\t\\t\\t\\tconst transformedDirection = invModelMat.transformVector(cameraDirection).normalize();\\n\\t\\t\\t\\t\\t\\tconst transformedPosition = invModelMat.transformPoint(cameraPosition);\\n\\t\\t\\t\\t\\t\\tmodelMat.getTranslation(translation);\\n\\t\\t\\t\\t\\t\\tconst offset = translation.sub(cameraPosition).dot(cameraDirection);\\n\\t\\t\\t\\t\\t\\tconst aabbMin = splat.aabb.getMin();\\n\\t\\t\\t\\t\\t\\tconst aabbMax = splat.aabb.getMax();\\n\\t\\t\\t\\t\\t\\tsorterRequest.push({\\n\\t\\t\\t\\t\\t\\t\\t\\ttransformedDirection,\\n\\t\\t\\t\\t\\t\\t\\t\\ttransformedPosition,\\n\\t\\t\\t\\t\\t\\t\\t\\toffset,\\n\\t\\t\\t\\t\\t\\t\\t\\tscale: uniformScale,\\n\\t\\t\\t\\t\\t\\t\\t\\tmodelMat: modelMat.data.slice(),\\n\\t\\t\\t\\t\\t\\t\\t\\taabbMin: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taabbMin.x,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taabbMin.y,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taabbMin.z\\n\\t\\t\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t\\t\\taabbMax: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taabbMax.x,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taabbMax.y,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taabbMax.z\\n\\t\\t\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.cpuSorter.setSortParams(sorterRequest, this.scene.gsplat.radialSorting);\\n\\t\\t}\\n\\t\\tprepareSortParameters(worldState) {\\n\\t\\t\\t\\tconst params = {\\n\\t\\t\\t\\t\\t\\tcommand: 'intervals',\\n\\t\\t\\t\\t\\t\\ttextureSize: worldState.textureSize,\\n\\t\\t\\t\\t\\t\\ttotalUsedPixels: worldState.totalUsedPixels,\\n\\t\\t\\t\\t\\t\\tversion: worldState.version,\\n\\t\\t\\t\\t\\t\\tids: worldState.splats.map((splat)=>splat.resource.id),\\n\\t\\t\\t\\t\\t\\tlineStarts: worldState.splats.map((splat)=>splat.lineStart),\\n\\t\\t\\t\\t\\t\\tpadding: worldState.splats.map((splat)=>splat.padding),\\n\\t\\t\\t\\t\\t\\tintervals: worldState.splats.map((splat)=>splat.intervals)\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\treturn params;\\n\\t\\t}\\n\\t\\tconstructor(device, director, layer, cameraNode){\\n\\t\\t\\t\\tthis.node = new GraphNode('GSplatManager');\\n\\t\\t\\t\\tthis.worldStates = new Map();\\n\\t\\t\\t\\tthis.lastWorldStateVersion = 0;\\n\\t\\t\\t\\tthis.useGpuSorting = false;\\n\\t\\t\\t\\tthis.cpuSorter = null;\\n\\t\\t\\t\\tthis.keyGenerator = null;\\n\\t\\t\\t\\tthis.gpuSorter = null;\\n\\t\\t\\t\\tthis.sortedVersion = 0;\\n\\t\\t\\t\\tthis._workBufferFormatVersion = -1;\\n\\t\\t\\t\\tthis._workBufferRebuildRequired = false;\\n\\t\\t\\t\\tthis._stateTracker = new GSplatPlacementStateTracker();\\n\\t\\t\\t\\tthis._centersVersions = new Map();\\n\\t\\t\\t\\tthis.framesTillFullUpdate = 0;\\n\\t\\t\\t\\tthis.lastLodCameraPos = new Vec3(Infinity, Infinity, Infinity);\\n\\t\\t\\t\\tthis.lastLodCameraFwd = new Vec3(Infinity, Infinity, Infinity);\\n\\t\\t\\t\\tthis.lastSortCameraPos = new Vec3(Infinity, Infinity, Infinity);\\n\\t\\t\\t\\tthis.lastSortCameraFwd = new Vec3(Infinity, Infinity, Infinity);\\n\\t\\t\\t\\tthis.sortNeeded = true;\\n\\t\\t\\t\\tthis.lastColorUpdateCameraPos = new Vec3(Infinity, Infinity, Infinity);\\n\\t\\t\\t\\tthis.lastColorUpdateCameraFwd = new Vec3(Infinity, Infinity, Infinity);\\n\\t\\t\\t\\tthis.layerPlacements = [];\\n\\t\\t\\t\\tthis.layerPlacementsDirty = false;\\n\\t\\t\\t\\tthis.octreeInstances = new Map();\\n\\t\\t\\t\\tthis.octreeInstancesToDestroy = [];\\n\\t\\t\\t\\tthis.hasNewOctreeInstances = false;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.scene = director.scene;\\n\\t\\t\\t\\tthis.director = director;\\n\\t\\t\\t\\tthis.cameraNode = cameraNode;\\n\\t\\t\\t\\tthis.workBuffer = new GSplatWorkBuffer(device, this.scene.gsplat.format);\\n\\t\\t\\t\\tthis.renderer = new GSplatRenderer(device, this.node, this.cameraNode, layer, this.workBuffer);\\n\\t\\t\\t\\tthis._workBufferFormatVersion = this.workBuffer.format.extraStreamsVersion;\\n\\t\\t\\t\\tthis.useGpuSorting = device.isWebGPU && director.scene.gsplat.gpuSorting;\\n\\t\\t\\t\\tif (this.useGpuSorting) {\\n\\t\\t\\t\\t\\t\\tthis.keyGenerator = new GSplatSortKeyCompute(device);\\n\\t\\t\\t\\t\\t\\tthis.gpuSorter = new ComputeRadixSort(device);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.cpuSorter = this.createSorter();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\n\\nclass SetUtils {\\n\\t\\tstatic equals(setA, setB) {\\n\\t\\t\\t\\tif (setA.size !== setB.size) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const elem of setA){\\n\\t\\t\\t\\t\\t\\tif (!setB.has(elem)) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n}\\n\\nconst tempLayersToRemove = [];\\nclass GSplatLayerData {\\n\\t\\tcreateManager(device, director, layer, cameraNode, camera, renderMode) {\\n\\t\\t\\t\\tconst manager = new GSplatManager(device, director, layer, cameraNode);\\n\\t\\t\\t\\tmanager.setRenderMode(renderMode);\\n\\t\\t\\t\\tif (director.eventHandler) {\\n\\t\\t\\t\\t\\t\\tdirector.eventHandler.fire('material:created', manager.material, camera, layer);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn manager;\\n\\t\\t}\\n\\t\\tupdateConfiguration(device, director, layer, camera) {\\n\\t\\t\\t\\tconst cameraNode = camera.node;\\n\\t\\t\\t\\tconst hasNormalPlacements = layer.gsplatPlacements.length > 0;\\n\\t\\t\\t\\tconst hasShadowCasters = layer.gsplatShadowCasters.length > 0;\\n\\t\\t\\t\\tconst setsEqual = SetUtils.equals(layer.gsplatPlacementsSet, layer.gsplatShadowCastersSet);\\n\\t\\t\\t\\tconst useSharedManager = setsEqual && hasNormalPlacements;\\n\\t\\t\\t\\tconst desiredMainMode = useSharedManager ? GSPLAT_FORWARD | GSPLAT_SHADOW : hasNormalPlacements ? GSPLAT_FORWARD : 0;\\n\\t\\t\\t\\tconst desiredShadowMode = useSharedManager ? 0 : hasShadowCasters ? GSPLAT_SHADOW : 0;\\n\\t\\t\\t\\tif (desiredMainMode) {\\n\\t\\t\\t\\t\\t\\tif (this.gsplatManager) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gsplatManager.setRenderMode(desiredMainMode);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gsplatManager = this.createManager(device, director, layer, cameraNode, camera, desiredMainMode);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else if (this.gsplatManager) {\\n\\t\\t\\t\\t\\t\\tthis.gsplatManager.destroy();\\n\\t\\t\\t\\t\\t\\tthis.gsplatManager = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (desiredShadowMode) {\\n\\t\\t\\t\\t\\t\\tif (this.gsplatManagerShadow) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gsplatManagerShadow.setRenderMode(desiredShadowMode);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gsplatManagerShadow = this.createManager(device, director, layer, cameraNode, camera, desiredShadowMode);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else if (this.gsplatManagerShadow) {\\n\\t\\t\\t\\t\\t\\tthis.gsplatManagerShadow.destroy();\\n\\t\\t\\t\\t\\t\\tthis.gsplatManagerShadow = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.gsplatManager?.destroy();\\n\\t\\t\\t\\tthis.gsplatManager = null;\\n\\t\\t\\t\\tthis.gsplatManagerShadow?.destroy();\\n\\t\\t\\t\\tthis.gsplatManagerShadow = null;\\n\\t\\t}\\n\\t\\tconstructor(device, director, layer, camera){\\n\\t\\t\\t\\tthis.gsplatManager = null;\\n\\t\\t\\t\\tthis.gsplatManagerShadow = null;\\n\\t\\t\\t\\tthis.updateConfiguration(device, director, layer, camera);\\n\\t\\t}\\n}\\nclass GSplatCameraData {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.layersMap.forEach((layerData)=>layerData.destroy());\\n\\t\\t\\t\\tthis.layersMap.clear();\\n\\t\\t}\\n\\t\\tremoveLayerData(layer) {\\n\\t\\t\\t\\tconst layerData = this.layersMap.get(layer);\\n\\t\\t\\t\\tif (layerData) {\\n\\t\\t\\t\\t\\t\\tlayerData.destroy();\\n\\t\\t\\t\\t\\t\\tthis.layersMap.delete(layer);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetLayerData(device, director, layer, camera) {\\n\\t\\t\\t\\tlet layerData = this.layersMap.get(layer);\\n\\t\\t\\t\\tif (!layerData) {\\n\\t\\t\\t\\t\\t\\tlayerData = new GSplatLayerData(device, director, layer, camera);\\n\\t\\t\\t\\t\\t\\tthis.layersMap.set(layer, layerData);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn layerData;\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.layersMap = new Map();\\n\\t\\t}\\n}\\nclass GSplatDirector {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.camerasMap.forEach((cameraData)=>cameraData.destroy());\\n\\t\\t\\t\\tthis.camerasMap.clear();\\n\\t\\t}\\n\\t\\tgetCameraData(camera) {\\n\\t\\t\\t\\tlet cameraData = this.camerasMap.get(camera);\\n\\t\\t\\t\\tif (!cameraData) {\\n\\t\\t\\t\\t\\t\\tcameraData = new GSplatCameraData();\\n\\t\\t\\t\\t\\t\\tthis.camerasMap.set(camera, cameraData);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn cameraData;\\n\\t\\t}\\n\\t\\tupdate(comp) {\\n\\t\\t\\t\\tGSplatResourceCleanup.process(this.device);\\n\\t\\t\\t\\tthis.camerasMap.forEach((cameraData, camera)=>{\\n\\t\\t\\t\\t\\t\\tif (!comp.camerasSet.has(camera)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcameraData.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.camerasMap.delete(camera);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tcameraData.layersMap.forEach((layerData, layer)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!camera.layersSet.has(layer.id) || !layer.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttempLayersToRemove.push(layer);\\n\\t\\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\\tfor(let i = 0; i < tempLayersToRemove.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst layer = tempLayersToRemove[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst layerData = cameraData.layersMap.get(layer);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (layerData) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayerData.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcameraData.layersMap.delete(layer);\\n\\t\\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\\ttempLayersToRemove.length = 0;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tlet gsplatCount = 0;\\n\\t\\t\\t\\tconst camerasComponents = comp.cameras;\\n\\t\\t\\t\\tfor(let i = 0; i < camerasComponents.length; i++){\\n\\t\\t\\t\\t\\t\\tconst camera = camerasComponents[i].camera;\\n\\t\\t\\t\\t\\t\\tlet cameraData = this.camerasMap.get(camera);\\n\\t\\t\\t\\t\\t\\tconst layerIds = camera.layers;\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j < layerIds.length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst layer = comp.getLayerById(layerIds[j]);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (layer?.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (layer.gsplatPlacementsDirty || !cameraData) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst hasNormalPlacements = layer.gsplatPlacements.length > 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst hasShadowCasters = layer.gsplatShadowCasters.length > 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!hasNormalPlacements && !hasShadowCasters) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (cameraData) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcameraData.removeLayerData(layer);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcameraData ?? (cameraData = this.getCameraData(camera));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst layerData = cameraData.getLayerData(this.device, this, layer, camera);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayerData.updateConfiguration(this.device, this, layer, camera);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (layerData.gsplatManager) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayerData.gsplatManager.reconcile(layer.gsplatPlacements);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (layerData.gsplatManagerShadow) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayerData.gsplatManagerShadow.reconcile(layer.gsplatShadowCasters);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tif (cameraData) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor (const layerData of cameraData.layersMap.values()){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (layerData.gsplatManager) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgsplatCount += layerData.gsplatManager.update();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (layerData.gsplatManagerShadow) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgsplatCount += layerData.gsplatManagerShadow.update();\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.renderer._gsplatCount = gsplatCount;\\n\\t\\t\\t\\tthis.scene.gsplat.frameEnd();\\n\\t\\t\\t\\tfor(let i = 0; i < comp.layerList.length; i++){\\n\\t\\t\\t\\t\\t\\tcomp.layerList[i].gsplatPlacementsDirty = false;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(device, renderer, scene, eventHandler){\\n\\t\\t\\t\\tthis.camerasMap = new Map();\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.renderer = renderer;\\n\\t\\t\\t\\tthis.scene = scene;\\n\\t\\t\\t\\tthis.eventHandler = eventHandler;\\n\\t\\t}\\n}\\n\\nclass GSplatComponent extends Component {\\n\\t\\tset customAabb(value) {\\n\\t\\t\\t\\tthis._customAabb = value;\\n\\t\\t\\t\\tthis._instance?.meshInstance?.setCustomAabb(this._customAabb);\\n\\t\\t\\t\\tif (this._placement) {\\n\\t\\t\\t\\t\\t\\tthis._placement.aabb = this._customAabb;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget customAabb() {\\n\\t\\t\\t\\treturn this._customAabb ?? this._placement?.aabb ?? this.resource?.aabb ?? null;\\n\\t\\t}\\n\\t\\tset instance(value) {\\n\\t\\t\\t\\tif (this.unified) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.destroyInstance();\\n\\t\\t\\t\\tthis._instance = value;\\n\\t\\t\\t\\tif (this._instance) {\\n\\t\\t\\t\\t\\t\\tconst mi = this._instance.meshInstance;\\n\\t\\t\\t\\t\\t\\tif (!mi.node) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmi.node = this.entity;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tmi.castShadow = this._castShadows;\\n\\t\\t\\t\\t\\t\\tmi.setCustomAabb(this._customAabb);\\n\\t\\t\\t\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.addToLayers();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget instance() {\\n\\t\\t\\t\\treturn this._instance;\\n\\t\\t}\\n\\t\\tset material(value) {\\n\\t\\t\\t\\tif (this.unified) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._instance) {\\n\\t\\t\\t\\t\\t\\tthis._instance.material = value;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._materialTmp = value;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget material() {\\n\\t\\t\\t\\tif (this.unified) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._instance?.material ?? this._materialTmp ?? null;\\n\\t\\t}\\n\\t\\tset highQualitySH(value) {\\n\\t\\t\\t\\tif (value !== this._highQualitySH) {\\n\\t\\t\\t\\t\\t\\tthis._highQualitySH = value;\\n\\t\\t\\t\\t\\t\\tthis._instance?.setHighQualitySH(value);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget highQualitySH() {\\n\\t\\t\\t\\treturn this._highQualitySH;\\n\\t\\t}\\n\\t\\tset castShadows(value) {\\n\\t\\t\\t\\tif (this._castShadows !== value) {\\n\\t\\t\\t\\t\\t\\tconst layers = this.layers;\\n\\t\\t\\t\\t\\t\\tconst scene = this.system.app.scene;\\n\\t\\t\\t\\t\\t\\tif (this._placement) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (value) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < layers.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst layer = scene.layers.getLayerById(layers[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayer?.addGSplatShadowCaster(this._placement);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < layers.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst layer = scene.layers.getLayerById(layers[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayer?.removeGSplatShadowCaster(this._placement);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tconst mi = this.instance?.meshInstance;\\n\\t\\t\\t\\t\\t\\tif (mi) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._castShadows && !value) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < layers.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst layer = scene.layers.getLayerById(this.layers[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayer?.removeShadowCasters([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmi\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t]);\\n\\t\\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\\tmi.castShadow = value;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this._castShadows && value) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < layers.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst layer = scene.layers.getLayerById(layers[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayer?.addShadowCasters([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmi\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t]);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tthis._castShadows = value;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget castShadows() {\\n\\t\\t\\t\\treturn this._castShadows;\\n\\t\\t}\\n\\t\\tset lodDistances(value) {\\n\\t\\t\\t\\tthis._lodDistances = Array.isArray(value) ? value.slice() : null;\\n\\t\\t\\t\\tif (this._placement) {\\n\\t\\t\\t\\t\\t\\tthis._placement.lodDistances = this._lodDistances;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget lodDistances() {\\n\\t\\t\\t\\treturn this._lodDistances ? this._lodDistances.slice() : null;\\n\\t\\t}\\n\\t\\tset splatBudget(value) {\\n\\t\\t\\t\\tthis._splatBudget = value;\\n\\t\\t\\t\\tif (this._placement) {\\n\\t\\t\\t\\t\\t\\tthis._placement.splatBudget = this._splatBudget;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget splatBudget() {\\n\\t\\t\\t\\treturn this._splatBudget;\\n\\t\\t}\\n\\t\\tset unified(value) {\\n\\t\\t\\t\\tif (this._unified !== value) {\\n\\t\\t\\t\\t\\t\\tthis._unified = value;\\n\\t\\t\\t\\t\\t\\tthis._onGSplatAssetAdded();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget unified() {\\n\\t\\t\\t\\treturn this._unified;\\n\\t\\t}\\n\\t\\tget id() {\\n\\t\\t\\t\\treturn this._id;\\n\\t\\t}\\n\\t\\tset workBufferUpdate(value) {\\n\\t\\t\\t\\tthis._workBufferUpdate = value;\\n\\t\\t\\t\\tif (this._placement) {\\n\\t\\t\\t\\t\\t\\tthis._placement.workBufferUpdate = value;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget workBufferUpdate() {\\n\\t\\t\\t\\treturn this._workBufferUpdate;\\n\\t\\t}\\n\\t\\tsetWorkBufferModifier(value) {\\n\\t\\t\\t\\tif (value) {\\n\\t\\t\\t\\t\\t\\tconst device = this.system.app.graphicsDevice;\\n\\t\\t\\t\\t\\t\\tconst code = (device.isWebGPU ? value.wgsl : value.glsl) ?? null;\\n\\t\\t\\t\\t\\t\\tthis._workBufferModifier = code ? {\\n\\t\\t\\t\\t\\t\\t\\t\\tcode,\\n\\t\\t\\t\\t\\t\\t\\t\\thash: hashCode(code)\\n\\t\\t\\t\\t\\t\\t} : null;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._workBufferModifier = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._placement) {\\n\\t\\t\\t\\t\\t\\tthis._placement.workBufferModifier = this._workBufferModifier;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tset layers(value) {\\n\\t\\t\\t\\tthis.removeFromLayers();\\n\\t\\t\\t\\tthis._layers.length = 0;\\n\\t\\t\\t\\tfor(let i = 0; i < value.length; i++){\\n\\t\\t\\t\\t\\t\\tthis._layers[i] = value[i];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this.enabled || !this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.addToLayers();\\n\\t\\t}\\n\\t\\tget layers() {\\n\\t\\t\\t\\treturn this._layers;\\n\\t\\t}\\n\\t\\tset asset(value) {\\n\\t\\t\\t\\tconst id = value instanceof Asset ? value.id : value;\\n\\t\\t\\t\\tif (this._assetReference.id === id) return;\\n\\t\\t\\t\\tif (this._assetReference.asset && this._assetReference.asset.resource) {\\n\\t\\t\\t\\t\\t\\tthis._onGSplatAssetRemove();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._assetReference.id = id;\\n\\t\\t\\t\\tif (this._assetReference.asset) {\\n\\t\\t\\t\\t\\t\\tthis._onGSplatAssetAdded();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget asset() {\\n\\t\\t\\t\\treturn this._assetReference.id;\\n\\t\\t}\\n\\t\\tset resource(value) {\\n\\t\\t\\t\\tif (this._resource === value) return;\\n\\t\\t\\t\\tif (this._resource || this._assetReference.asset?.resource) {\\n\\t\\t\\t\\t\\t\\tthis._onGSplatAssetRemove();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (value && this._assetReference.id) {\\n\\t\\t\\t\\t\\t\\tthis._assetReference.id = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._resource = value;\\n\\t\\t\\t\\tif (this._resource && this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\tthis._onGSplatAssetLoad();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget resource() {\\n\\t\\t\\t\\treturn this._resource ?? this._assetReference.asset?.resource ?? null;\\n\\t\\t}\\n\\t\\tdestroyInstance() {\\n\\t\\t\\t\\tif (this._placement) {\\n\\t\\t\\t\\t\\t\\tthis.removeFromLayers();\\n\\t\\t\\t\\t\\t\\tthis._placement.destroy();\\n\\t\\t\\t\\t\\t\\tthis._placement = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._instance) {\\n\\t\\t\\t\\t\\t\\tthis.removeFromLayers();\\n\\t\\t\\t\\t\\t\\tthis._instance?.destroy();\\n\\t\\t\\t\\t\\t\\tthis._instance = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\taddToLayers() {\\n\\t\\t\\t\\tif (this._placement) {\\n\\t\\t\\t\\t\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._layers.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst layer = layers.getLayerById(this._layers[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayer.addGSplatPlacement(this._placement);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this._castShadows) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayer.addGSplatShadowCaster(this._placement);\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst meshInstance = this.instance?.meshInstance;\\n\\t\\t\\t\\tif (meshInstance) {\\n\\t\\t\\t\\t\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._layers.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tlayers.getLayerById(this._layers[i])?.addMeshInstances([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmeshInstance\\n\\t\\t\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tremoveFromLayers() {\\n\\t\\t\\t\\tif (this._placement) {\\n\\t\\t\\t\\t\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._layers.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst layer = layers.getLayerById(this._layers[i]);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (layer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayer.removeGSplatPlacement(this._placement);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlayer.removeGSplatShadowCaster(this._placement);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst meshInstance = this.instance?.meshInstance;\\n\\t\\t\\t\\tif (meshInstance) {\\n\\t\\t\\t\\t\\t\\tconst layers = this.system.app.scene.layers;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._layers.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tlayers.getLayerById(this._layers[i])?.removeMeshInstances([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmeshInstance\\n\\t\\t\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonRemoveChild() {\\n\\t\\t\\t\\tthis.removeFromLayers();\\n\\t\\t}\\n\\t\\tonInsertChild() {\\n\\t\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\tif (this._instance || this._placement) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.addToLayers();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonRemove() {\\n\\t\\t\\t\\tthis.destroyInstance();\\n\\t\\t\\t\\tthis.asset = null;\\n\\t\\t\\t\\tthis._assetReference.id = null;\\n\\t\\t\\t\\tthis.entity.off('remove', this.onRemoveChild, this);\\n\\t\\t\\t\\tthis.entity.off('insert', this.onInsertChild, this);\\n\\t\\t}\\n\\t\\tonLayersChanged(oldComp, newComp) {\\n\\t\\t\\t\\tthis.addToLayers();\\n\\t\\t\\t\\toldComp.off('add', this.onLayerAdded, this);\\n\\t\\t\\t\\toldComp.off('remove', this.onLayerRemoved, this);\\n\\t\\t\\t\\tnewComp.on('add', this.onLayerAdded, this);\\n\\t\\t\\t\\tnewComp.on('remove', this.onLayerRemoved, this);\\n\\t\\t}\\n\\t\\tonLayerAdded(layer) {\\n\\t\\t\\t\\tconst index = this.layers.indexOf(layer.id);\\n\\t\\t\\t\\tif (index < 0) return;\\n\\t\\t\\t\\tif (this.unified) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._instance) {\\n\\t\\t\\t\\t\\t\\tlayer.addMeshInstances(this._instance.meshInstance);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonLayerRemoved(layer) {\\n\\t\\t\\t\\tconst index = this.layers.indexOf(layer.id);\\n\\t\\t\\t\\tif (index < 0) return;\\n\\t\\t\\t\\tif (this.unified) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._instance) {\\n\\t\\t\\t\\t\\t\\tlayer.removeMeshInstances(this._instance.meshInstance);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonEnable() {\\n\\t\\t\\t\\tconst scene = this.system.app.scene;\\n\\t\\t\\t\\tconst layers = scene.layers;\\n\\t\\t\\t\\tthis._evtLayersChanged = scene.on('set:layers', this.onLayersChanged, this);\\n\\t\\t\\t\\tif (layers) {\\n\\t\\t\\t\\t\\t\\tthis._evtLayerAdded = layers.on('add', this.onLayerAdded, this);\\n\\t\\t\\t\\t\\t\\tthis._evtLayerRemoved = layers.on('remove', this.onLayerRemoved, this);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._instance || this._placement) {\\n\\t\\t\\t\\t\\t\\tthis.addToLayers();\\n\\t\\t\\t\\t} else if (this.asset) {\\n\\t\\t\\t\\t\\t\\tthis._onGSplatAssetAdded();\\n\\t\\t\\t\\t} else if (this._resource) {\\n\\t\\t\\t\\t\\t\\tthis._onGSplatAssetLoad();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonDisable() {\\n\\t\\t\\t\\tconst scene = this.system.app.scene;\\n\\t\\t\\t\\tconst layers = scene.layers;\\n\\t\\t\\t\\tthis._evtLayersChanged?.off();\\n\\t\\t\\t\\tthis._evtLayersChanged = null;\\n\\t\\t\\t\\tif (layers) {\\n\\t\\t\\t\\t\\t\\tthis._evtLayerAdded?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtLayerAdded = null;\\n\\t\\t\\t\\t\\t\\tthis._evtLayerRemoved?.off();\\n\\t\\t\\t\\t\\t\\tthis._evtLayerRemoved = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.removeFromLayers();\\n\\t\\t}\\n\\t\\thide() {\\n\\t\\t\\t\\tif (this._instance) {\\n\\t\\t\\t\\t\\t\\tthis._instance.meshInstance.visible = false;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tshow() {\\n\\t\\t\\t\\tif (this._instance) {\\n\\t\\t\\t\\t\\t\\tthis._instance.meshInstance.visible = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetParameter(name, data) {\\n\\t\\t\\t\\tconst scopeId = this.system.app.graphicsDevice.scope.resolve(name);\\n\\t\\t\\t\\tthis._parameters.set(name, {\\n\\t\\t\\t\\t\\t\\tscopeId,\\n\\t\\t\\t\\t\\t\\tdata\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (this._placement) this._placement.renderDirty = true;\\n\\t\\t}\\n\\t\\tgetParameter(name) {\\n\\t\\t\\t\\treturn this._parameters.get(name)?.data;\\n\\t\\t}\\n\\t\\tdeleteParameter(name) {\\n\\t\\t\\t\\tthis._parameters.delete(name);\\n\\t\\t\\t\\tif (this._placement) this._placement.renderDirty = true;\\n\\t\\t}\\n\\t\\tgetInstanceTexture(name) {\\n\\t\\t\\t\\tif (!this._placement) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._placement.getInstanceTexture(name, this.system.app.graphicsDevice) ?? null;\\n\\t\\t}\\n\\t\\t_onGSplatAssetAdded() {\\n\\t\\t\\t\\tif (!this._assetReference.asset) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._assetReference.asset.resource) {\\n\\t\\t\\t\\t\\t\\tthis._onGSplatAssetLoad();\\n\\t\\t\\t\\t} else if (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\tthis.system.app.assets.load(this._assetReference.asset);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onGSplatAssetLoad() {\\n\\t\\t\\t\\tthis.destroyInstance();\\n\\t\\t\\t\\tconst resource = this._resource ?? this._assetReference.asset?.resource;\\n\\t\\t\\t\\tif (!resource) return;\\n\\t\\t\\t\\tif (this.unified) {\\n\\t\\t\\t\\t\\t\\tthis._placement = null;\\n\\t\\t\\t\\t\\t\\tthis._placement = new GSplatPlacement(resource, this.entity, 0, this._parameters, null, this._id);\\n\\t\\t\\t\\t\\t\\tthis._placement.lodDistances = this._lodDistances;\\n\\t\\t\\t\\t\\t\\tthis._placement.splatBudget = this._splatBudget;\\n\\t\\t\\t\\t\\t\\tthis._placement.workBufferUpdate = this._workBufferUpdate;\\n\\t\\t\\t\\t\\t\\tthis._placement.workBufferModifier = this._workBufferModifier;\\n\\t\\t\\t\\t\\t\\tif (this.enabled && this.entity.enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.addToLayers();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.instance = new GSplatInstance(resource, {\\n\\t\\t\\t\\t\\t\\t\\t\\tmaterial: this._materialTmp,\\n\\t\\t\\t\\t\\t\\t\\t\\thighQualitySH: this._highQualitySH,\\n\\t\\t\\t\\t\\t\\t\\t\\tscene: this.system.app.scene\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tthis._materialTmp = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onGSplatAssetUnload() {\\n\\t\\t\\t\\tthis.destroyInstance();\\n\\t\\t}\\n\\t\\t_onGSplatAssetRemove() {\\n\\t\\t\\t\\tthis._onGSplatAssetUnload();\\n\\t\\t}\\n\\t\\tconstructor(system, entity){\\n\\t\\t\\t\\tsuper(system, entity), this._layers = [\\n\\t\\t\\t\\t\\t\\tLAYERID_WORLD\\n\\t\\t\\t\\t], this._instance = null, this._placement = null, this._id = PickerId.get(), this._materialTmp = null, this._highQualitySH = true, this._lodDistances = [\\n\\t\\t\\t\\t\\t\\t5,\\n\\t\\t\\t\\t\\t\\t10,\\n\\t\\t\\t\\t\\t\\t15,\\n\\t\\t\\t\\t\\t\\t20,\\n\\t\\t\\t\\t\\t\\t25,\\n\\t\\t\\t\\t\\t\\t30,\\n\\t\\t\\t\\t\\t\\t35,\\n\\t\\t\\t\\t\\t\\t40,\\n\\t\\t\\t\\t\\t\\t45,\\n\\t\\t\\t\\t\\t\\t50,\\n\\t\\t\\t\\t\\t\\t55,\\n\\t\\t\\t\\t\\t\\t60\\n\\t\\t\\t\\t], this._splatBudget = 0, this._customAabb = null, this._resource = null, this._evtLayersChanged = null, this._evtLayerAdded = null, this._evtLayerRemoved = null, this._castShadows = false, this._unified = false, this._parameters = new Map(), this._workBufferUpdate = WORKBUFFER_UPDATE_AUTO, this._workBufferModifier = null;\\n\\t\\t\\t\\tthis._assetReference = new AssetReference('asset', this, system.app.assets, {\\n\\t\\t\\t\\t\\t\\tadd: this._onGSplatAssetAdded,\\n\\t\\t\\t\\t\\t\\tload: this._onGSplatAssetLoad,\\n\\t\\t\\t\\t\\t\\tremove: this._onGSplatAssetRemove,\\n\\t\\t\\t\\t\\t\\tunload: this._onGSplatAssetUnload\\n\\t\\t\\t\\t}, this);\\n\\t\\t\\t\\tentity.on('remove', this.onRemoveChild, this);\\n\\t\\t\\t\\tentity.on('removehierarchy', this.onRemoveChild, this);\\n\\t\\t\\t\\tentity.on('insert', this.onInsertChild, this);\\n\\t\\t\\t\\tentity.on('inserthierarchy', this.onInsertChild, this);\\n\\t\\t}\\n}\\n\\nclass GSplatComponentData {\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.enabled = true;\\n\\t\\t}\\n}\\n\\nvar gsplatCenterVS$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#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\\tif (camera_params.w != 1.0 && centerView.z > 0.0) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tvec4 centerProj = matrix_projection * centerView;\\n\\t\\t#if WEBGPU\\n\\t\\t\\tcenterProj.z = clamp(centerProj.z, 0, abs(centerProj.w));\\n\\t\\t#else\\n\\t\\t\\tcenterProj.z = clamp(centerProj.z, -abs(centerProj.w), abs(centerProj.w));\\n\\t\\t#endif\\n\\t\\tcenter.proj = centerProj;\\n\\t\\tcenter.projMat00 = matrix_projection[0][0];\\n\\t#endif\\n\\tcenter.view = centerView.xyz / centerView.w;\\n\\tcenter.modelView = modelView;\\n\\treturn true;\\n}\\n`;\\n\\nvar gsplatCommonVS$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\\\"\\nvoid clipCorner(inout SplatCorner corner, float alpha) {\\n\\tfloat clip = min(1.0, sqrt(-log(1.0 / (255.0 * alpha))) / 2.0);\\n\\tcorner.offset *= clip;\\n\\tcorner.uv *= clip;\\n}\\n`;\\n\\nvar gsplatSplatVS$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 gsplatEvalSHVS$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 gsplatHelpersVS$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 gsplatModifyVS$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 gsplatQuatToMat3VS$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 gsplatStructsVS$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};\\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 gsplatCornerVS$1 = `\\nuniform vec4 viewport_size;\\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 = camera_params.w == 1.0 ? vec3(0.0, 0.0, 1.0) : center.view.xyz;\\n\\tfloat J1 = focal / v.z;\\n\\tvec2 J2 = -J1 / v.z * v.xy;\\n\\tmat3 J = mat3(\\n\\t\\tJ1, 0.0, J2.x, \\n\\t\\t0.0, J1, J2.y, \\n\\t\\t0.0, 0.0, 0.0\\n\\t);\\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 (l1 < 2.0 && l2 < 2.0) {\\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 gsplatOutputVS$1 = `\\n#include \\\"tonemappingPS\\\"\\n#include \\\"decodePS\\\"\\n#include \\\"gammaPS\\\"\\nvec3 prepareOutputFromGamma(vec3 gammaColor) {\\n\\t#if TONEMAP == NONE\\n\\t\\t#if GAMMA == NONE\\n\\t\\t\\treturn decodeGamma(gammaColor);\\n\\t\\t#else\\n\\t\\t\\treturn gammaColor;\\n\\t\\t#endif\\n\\t#else\\n\\t\\treturn gammaCorrectOutput(toneMap(decodeGamma(gammaColor)));\\n\\t#endif\\n}\\n`;\\n\\nvar gsplatPS$1 = `\\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\\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 < 1.0 / 255.0) {\\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 gsplatSourceVS$1 = `\\nattribute vec3 vertex_position;\\nattribute uint vertex_id_attrib;\\nuniform uint numSplats;\\nuniform highp usampler2D splatOrder;\\nbool initSource(out SplatSource source) {\\n\\tsource.order = vertex_id_attrib + 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 gsplatVS$1 = `\\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\\tvec4 clr = getColor();\\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\\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)), 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 gsplatFormatVS$1 = `\\nuniform uint splatTextureSize;\\n`;\\n\\nvar gsplatUncompressedVS$1 = `\\nuint tAw;\\nvec4 tBcached;\\nvec4 unpackRotation(vec3 packed) {\\n\\treturn vec4(packed.xyz, sqrt(max(0.0, 1.0 - dot(packed, packed))));\\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 gsplatUncompressedSHVS$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 gsplatCompressedVS$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 gsplatCompressedSHVS$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 gsplatSogVS$1 = `\\n#include \\\"gsplatPackingPS\\\"\\nuniform vec3 means_mins;\\nuniform vec3 means_maxs;\\nuniform float scales_mins;\\nuniform float scales_maxs;\\nuniform float sh0_mins;\\nuniform float sh0_maxs;\\nuniform highp sampler2D packedSh0;\\nconst float SH_C0 = 0.28209479177387814;\\nuvec4 packedSample;\\nconst float norm = sqrt(2.0);\\nvec3 getCenter() {\\n\\tpackedSample = loadPackedTexture();\\n\\tvec3 l = unpack8888(packedSample.x).xyz;\\n\\tvec3 u = unpack8888(packedSample.y).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 getColor() {\\n\\tvec3 clr = mix(vec3(sh0_mins), vec3(sh0_maxs), unpack111110(pack8888(texelFetch(packedSh0, splat.uv, 0))));\\n\\tfloat alpha = float(packedSample.z & 0xffu) / 255.0;\\n\\treturn vec4(vec3(0.5) + clr * SH_C0, alpha);\\n}\\nvec4 getRotation() {\\n\\tvec3 qdata = unpack8888(packedSample.z).xyz;\\n\\tuint qmode = packedSample.w & 0x3u;\\n\\tvec3 abc = (qdata - 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 sdata = unpack101010(packedSample.w >> 2u);\\n\\treturn exp(mix(vec3(scales_mins), vec3(scales_maxs), sdata));\\n}\\n#include \\\"gsplatSogSHVS\\\"\\n`;\\n\\nvar gsplatSogSHVS$1 = `\\n#if SH_BANDS > 0\\nuniform highp sampler2D packedShN;\\nuniform float shN_mins;\\nuniform float shN_maxs;\\nvoid readSHData(out vec3 sh[SH_COEFFS], out float scale) {\\n\\tivec2 t = ivec2(packedSample.xy & 255u);\\n\\tint n = t.x + t.y * 256;\\n\\tint u = (n % 64) * SH_COEFFS;\\n\\tint v = n / 64;\\n\\tfor (int i = 0; i < SH_COEFFS; i++) {\\n\\t\\tsh[i] = mix(vec3(shN_mins), vec3(shN_maxs), unpack111110(pack8888(texelFetch(packedShN, ivec2(u + i, v), 0))));\\n\\t}\\n\\tscale = 1.0;\\n}\\n#endif\\n`;\\n\\nvar gsplatContainerDeclVS$1 = `\\n#include \\\"gsplatContainerDeclarationsVS\\\"\\nvec3 splatCenter;\\nvec4 splatColor;\\nvec3 splatScale;\\nvec4 splatRotation;\\n`;\\n\\nvar gsplatContainerReadVS$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\\nvar gsplatContainerPackedReadVS$1 = `\\nuvec4 cachedTransformA;\\nuvec2 cachedTransformB;\\nvec3 getCenter() {\\n\\tcachedTransformA = loadDataTransformA();\\n\\tcachedTransformB = loadDataTransformB().xy;\\n\\treturn vec3(uintBitsToFloat(cachedTransformA.r), uintBitsToFloat(cachedTransformA.g), uintBitsToFloat(cachedTransformA.b));\\n}\\nvec4 getColor() {\\n\\t#ifdef GSPLAT_COLOR_FLOAT\\n\\t\\treturn 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\\treturn vec4(unpackHalf2x16(packed_rg), unpackHalf2x16(packed_ba));\\n\\t#endif\\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\\nconst gsplatChunksGLSL = {\\n\\t\\tgsplatCenterVS: gsplatCenterVS$1,\\n\\t\\tgsplatCornerVS: gsplatCornerVS$1,\\n\\t\\tgsplatCommonVS: gsplatCommonVS$1,\\n\\t\\tgsplatSplatVS: gsplatSplatVS$1,\\n\\t\\tgsplatEvalSHVS: gsplatEvalSHVS$1,\\n\\t\\tgsplatHelpersVS: gsplatHelpersVS$1,\\n\\t\\tgsplatModifyVS: gsplatModifyVS$1,\\n\\t\\tgsplatQuatToMat3VS: gsplatQuatToMat3VS$1,\\n\\t\\tgsplatStructsVS: gsplatStructsVS$1,\\n\\t\\tgsplatOutputVS: gsplatOutputVS$1,\\n\\t\\tgsplatPS: gsplatPS$1,\\n\\t\\tgsplatSourceVS: gsplatSourceVS$1,\\n\\t\\tgsplatVS: gsplatVS$1,\\n\\t\\tgsplatPackingPS: gsplatPackingPS$1,\\n\\t\\tgsplatFormatVS: gsplatFormatVS$1,\\n\\t\\tgsplatUncompressedVS: gsplatUncompressedVS$1,\\n\\t\\tgsplatUncompressedSHVS: gsplatUncompressedSHVS$1,\\n\\t\\tgsplatCompressedVS: gsplatCompressedVS$1,\\n\\t\\tgsplatCompressedSHVS: gsplatCompressedSHVS$1,\\n\\t\\tgsplatSogVS: gsplatSogVS$1,\\n\\t\\tgsplatSogSHVS: gsplatSogSHVS$1,\\n\\t\\tgsplatContainerDeclVS: gsplatContainerDeclVS$1,\\n\\t\\tgsplatContainerReadVS: gsplatContainerReadVS$1,\\n\\t\\tgsplatContainerPackedReadVS: gsplatContainerPackedReadVS$1,\\n\\t\\tgsplatContainerFloatReadVS: gsplatContainerFloatReadVS$1\\n};\\n\\nvar gsplatCenterVS = `\\nuniform matrix_model: mat4x4f;\\nuniform matrix_view: mat4x4f;\\n#ifndef GSPLAT_CENTER_NOPROJ\\n\\tuniform camera_params: vec4f;\\n\\tuniform matrix_projection: mat4x4f;\\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\\tif (uniform.camera_params.w != 1.0 && centerView.z > 0.0) {\\n\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tvar centerProj: vec4f = uniform.matrix_projection * centerView;\\n\\t\\tcenterProj.z = clamp(centerProj.z, 0.0, abs(centerProj.w));\\n\\t\\tcenter.proj = centerProj;\\n\\t\\tcenter.projMat00 = uniform.matrix_projection[0][0];\\n\\t#endif\\n\\tcenter.view = centerView.xyz / centerView.w;\\n\\tcenter.modelView = modelView;\\n\\treturn true;\\n}\\n`;\\n\\nvar gsplatCommonVS = `\\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\\\"\\nfn clipCorner(corner: ptr<function, SplatCorner>, alpha: f32) {\\n\\tlet clip: f32 = min(1.0, sqrt(-log(1.0 / (255.0 * alpha))) / 2.0);\\n\\tcorner.offset = corner.offset * clip;\\n\\tcorner.uv = corner.uv * clip;\\n}\\n`;\\n\\nvar gsplatSplatVS = `\\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 gsplatEvalSHVS = `\\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: f32 = 0.4886025119029199;\\n\\t#if SH_BANDS > 1\\n\\t\\tconst SH_C2_0: f32 = 1.0925484305920792;\\n\\t\\tconst SH_C2_1: f32 = -1.0925484305920792;\\n\\t\\tconst SH_C2_2: f32 = 0.31539156525252005;\\n\\t\\tconst SH_C2_3: f32 = -1.0925484305920792;\\n\\t\\tconst SH_C2_4: f32 = 0.5462742152960396;\\n\\t#endif\\n\\t#if SH_BANDS > 2\\n\\t\\tconst SH_C3_0: f32 = -0.5900435899266435;\\n\\t\\tconst SH_C3_1: f32 = 2.890611442640554;\\n\\t\\tconst SH_C3_2: f32 = -0.4570457994644658;\\n\\t\\tconst SH_C3_3: f32 = 0.3731763325901154;\\n\\t\\tconst SH_C3_4: f32 = -0.4570457994644658;\\n\\t\\tconst SH_C3_5: f32 = 1.445305721320277;\\n\\t\\tconst SH_C3_6: f32 = -0.5900435899266435;\\n\\t#endif\\n\\tfn evalSH(sh: ptr<function, array<vec3f, SH_COEFFS>>, dir: vec3f) -> vec3f {\\n\\t\\tlet x = dir.x;\\n\\t\\tlet y = dir.y;\\n\\t\\tlet z = dir.z;\\n\\t\\tvar result = SH_C1 * (-sh[0] * y + sh[1] * z - sh[2] * x);\\n\\t\\t#if SH_BANDS > 1\\n\\t\\t\\tlet xx = x * x;\\n\\t\\t\\tlet yy = y * y;\\n\\t\\t\\tlet zz = z * z;\\n\\t\\t\\tlet xy = x * y;\\n\\t\\t\\tlet yz = y * z;\\n\\t\\t\\tlet xz = x * 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 * (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 * 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\\t);\\n\\t\\t#endif\\n\\t\\treturn result;\\n\\t}\\n\\t#endif\\n`;\\n\\nvar gsplatHelpersVS = `\\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 gsplatModifyVS = `\\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 gsplatQuatToMat3VS = `\\nfn quatToMat3(R: vec4<f32>) -> mat3x3<f32> {\\n\\tlet R2: vec4<f32> = R + R;\\n\\tlet X: f32\\t   = R2.x * R.w;\\n\\tlet Y: vec4<f32> = R2.y * R;\\n\\tlet Z: vec4<f32> = R2.z * R;\\n\\tlet W: f32\\t   = R2.w * R.w;\\n\\treturn mat3x3<f32>(\\n\\t\\t1.0 - Z.z - W,  Y.z + X,\\t  Y.w - Z.x,\\n\\t\\tY.z - X,\\t\\t1.0 - Y.y - W, Z.w + Y.x,\\n\\t\\tY.w + Z.x,\\t  Z.w - Y.x,\\t 1.0 - Y.y - Z.z\\n\\t);\\n}\\nfn quatMul(a: vec4<f32>, b: vec4<f32>) -> vec4<f32> {\\n\\treturn vec4<f32>(\\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 gsplatStructsVS = `\\n#include \\\"gsplatSplatVS\\\"\\nstruct SplatSource {\\n\\torder: u32,\\n\\tcornerUV: vec2f\\n}\\nstruct SplatCenter {\\n\\tview: vec3f,\\n\\tproj: vec4f,\\n\\tmodelView: mat4x4f,\\n\\tprojMat00: f32,\\n\\tmodelCenterOriginal: vec3f,\\n\\tmodelCenterModified: vec3f,\\n}\\nstruct SplatCorner {\\n\\toffset: vec3f,\\n\\tuv: vec2f,\\n\\t#if GSPLAT_AA\\n\\t\\taaFactor: f32,\\n\\t#endif\\n}\\n`;\\n\\nvar gsplatCornerVS = `\\nuniform viewport_size: vec4f;\\nfn computeCovariance(rotation: vec4f, scale: vec3f, covA_ptr: ptr<function, vec3f>, covB_ptr: ptr<function, vec3f>) {\\n\\tlet rot = quatToMat3(rotation);\\n\\tlet M = transpose(mat3x3f(\\n\\t\\tscale.x * rot[0],\\n\\t\\tscale.y * rot[1],\\n\\t\\tscale.z * 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 = select(center.view.xyz, vec3f(0.0, 0.0, 1.0), uniform.camera_params.w == 1.0);\\n\\tlet J1 = focal / v.z;\\n\\tlet J2 = -J1 / v.z * v.xy;\\n\\tlet J = mat3x3f(\\n\\t\\tvec3f(J1, 0.0, J2.x),\\n\\t\\tvec3f(0.0, J1, J2.y),\\n\\t\\tvec3f(0.0, 0.0, 0.0)\\n\\t);\\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 = sqrt(detOrig / detBlur);\\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 (l1 < 2.0 && l2 < 2.0) {\\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((source.cornerUV.x * v1 + 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 = 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(rotation.wxyz, scale, &covA, &covB);\\n\\t\\treturn initCornerCov(source, center, corner, covA, covB);\\n\\t#endif\\n}\\n`;\\n\\nvar gsplatOutputVS = `\\n#include \\\"tonemappingPS\\\"\\n#include \\\"decodePS\\\"\\n#include \\\"gammaPS\\\"\\nfn prepareOutputFromGamma(gammaColor: vec3f) -> vec3f {\\n\\t#if TONEMAP == NONE\\n\\t\\t#if GAMMA == NONE\\n\\t\\t\\treturn decodeGamma3(gammaColor);\\n\\t\\t#else \\n\\t\\t\\treturn gammaColor;\\n\\t\\t#endif\\n\\t#else\\n\\t\\treturn gammaCorrectOutput(toneMap(decodeGamma3(gammaColor)));\\n\\t#endif\\n}\\n`;\\n\\nvar gsplatPS = `\\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\\nconst EXP4\\t  = exp(-4.0);\\nconst INV_EXP4  = 1.0 / (1.0 - EXP4);\\nfn normExp(x: f32) -> f32 {\\n\\treturn (exp(x * -4.0) - EXP4) * INV_EXP4;\\n}\\nvarying gaussianUV: vec2f;\\nvarying gaussianColor: vec4f;\\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: f32 = dot(gaussianUV, gaussianUV);\\n\\tif (A > 1.0) {\\n\\t\\tdiscard;\\n\\t\\treturn output;\\n\\t}\\n\\tvar alpha = normExp(A) * gaussianColor.a;\\n\\t#if defined(SHADOW_PASS) || defined(PICK_PASS) || defined(PREPASS_PASS)\\n\\t\\tif (alpha < 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 < (1.0 / 255.0)) {\\n\\t\\t\\tdiscard;\\n\\t\\t\\treturn output;\\n\\t\\t}\\n\\t\\t#ifndef DITHER_NONE\\n\\t\\t\\topacityDither(&alpha, id * 0.013);\\n\\t\\t#endif\\n\\t\\toutput.color = vec4f(input.gaussianColor.xyz * alpha, alpha);\\n\\t#endif\\n\\treturn output;\\n}`;\\n\\nvar gsplatSourceVS = `\\nattribute vertex_position: vec3f;\\nattribute vertex_id_attrib: u32;\\nuniform numSplats: u32;\\n#ifdef STORAGE_ORDER\\n\\tvar<storage, read> splatOrder: array<u32>;\\n#else\\n\\tvar splatOrder: texture_2d<u32>;\\n#endif\\nfn initSource(source: ptr<function, SplatSource>) -> bool {\\n\\t(*source).order = vertex_id_attrib + u32(vertex_position.z);\\n\\tif ((*source).order >= uniform.numSplats) {\\n\\t\\treturn false;\\n\\t}\\n\\tvar splatId: u32;\\n\\t#ifdef STORAGE_ORDER\\n\\t\\tsplatId = splatOrder[(*source).order];\\n\\t#else\\n\\t\\tlet uv = vec2u((*source).order % uniform.splatTextureSize, (*source).order / uniform.splatTextureSize);\\n\\t\\tsplatId = textureLoad(splatOrder, vec2i(uv), 0).r;\\n\\t#endif\\n\\tsetSplat(splatId);\\n\\t(*source).cornerUV = vertex_position.xy;\\n\\treturn true;\\n}\\n`;\\n\\nvar gsplatVS = `\\n#include \\\"gsplatCommonVS\\\"\\nvarying gaussianUV: vec2f;\\nvarying gaussianColor: vec4f;\\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\\tvar clr: vec4f = getColor();\\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<vec3f, SH_COEFFS>;\\n\\t\\tvar scale: f32;\\n\\t\\treadSHData(&sh, &scale);\\n\\t\\tclr = vec4f(clr.xyz + evalSH(&sh, dir) * scale, clr.a);\\n\\t#endif\\n\\tmodifySplatColor(modelCenter, &clr);\\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(originalCenter.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 * (1.0 / 32.0) * uniform.colorRampIntensity;\\n\\t\\toutput.gaussianColor = vec4f(rampColor, clr.a);\\n\\t#else\\n\\t\\toutput.gaussianColor = vec4f(prepareOutputFromGamma(max(clr.xyz, vec3f(0.0))), 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 gsplatFormatVS = `\\nuniform splatTextureSize: u32;\\n`;\\n\\nvar gsplatUncompressedVS = `\\nvar<private> tAw: u32;\\nvar<private> tBcached: vec4f;\\nfn unpackRotation(packed: vec3f) -> vec4f {\\n\\treturn vec4f(packed.xyz, sqrt(max(0.0, 1.0 - dot(packed, packed))));\\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 gsplatUncompressedSHVS = `\\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<vec3f, 3>>, scale: ptr<function, f32>) {\\n\\t\\tlet result = fetchScale(loadSplatSH_1to3());\\n\\t\\t*scale = result.scale;\\n\\t\\tsh[0] = result.a;\\n\\t\\tsh[1] = result.b;\\n\\t\\tsh[2] = result.c;\\n\\t}\\n#elif SH_BANDS == 2\\n\\tfn readSHData(sh: ptr<function, array<vec3f, 8>>, scale: ptr<function, f32>) {\\n\\t\\tlet first: ScaleAndSH = fetchScale(loadSplatSH_1to3());\\n\\t\\t*scale = first.scale;\\n\\t\\tsh[0] = first.a;\\n\\t\\tsh[1] = first.b;\\n\\t\\tsh[2] = first.c;\\n\\t\\tlet second: SH = fetch4(loadSplatSH_4to7());\\n\\t\\tsh[3] = second.a;\\n\\t\\tsh[4] = second.b;\\n\\t\\tsh[5] = second.c;\\n\\t\\tsh[6] = second.d;\\n\\t\\tsh[7] = fetch1(loadSplatSH_8to11().x);\\n\\t}\\n#else\\n\\tfn readSHData(sh: ptr<function, array<vec3f, 15>>, scale: ptr<function, f32>) {\\n\\t\\tlet first: ScaleAndSH = fetchScale(loadSplatSH_1to3());\\n\\t\\t*scale = first.scale;\\n\\t\\tsh[0] = first.a;\\n\\t\\tsh[1] = first.b;\\n\\t\\tsh[2] = first.c;\\n\\t\\tlet second: SH = fetch4(loadSplatSH_4to7());\\n\\t\\tsh[3] = second.a;\\n\\t\\tsh[4] = second.b;\\n\\t\\tsh[5] = second.c;\\n\\t\\tsh[6] = second.d;\\n\\t\\tlet third: SH = fetch4(loadSplatSH_8to11());\\n\\t\\tsh[7] = third.a;\\n\\t\\tsh[8] = third.b;\\n\\t\\tsh[9] = third.c;\\n\\t\\tsh[10] = third.d;\\n\\t\\tlet fourth: SH = fetch4(loadSplatSH_12to15());\\n\\t\\tsh[11] = fourth.a;\\n\\t\\tsh[12] = fourth.b;\\n\\t\\tsh[13] = fourth.c;\\n\\t\\tsh[14] = fourth.d;\\n\\t}\\n#endif\\n#endif\\n`;\\n\\nvar gsplatCompressedVS = `\\n#include \\\"gsplatPackingPS\\\"\\nvar chunkTexture: texture_2d<f32>;\\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 gsplatCompressedSHVS = `\\n#if SH_BANDS > 0\\nfn unpack8888s(bits: u32) -> vec4f {\\n\\tlet unpacked_u = (vec4<u32>(bits) >> vec4<u32>(0u, 8u, 16u, 24u)) & vec4<u32>(0xffu);\\n\\treturn vec4f(unpacked_u) * (8.0 / 255.0) - 4.0;\\n}\\nfn readSHData(sh: ptr<function, array<vec3f, 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 = unpack8888s(shData0.x);\\n\\tlet r1 = unpack8888s(shData0.y);\\n\\tlet r2 = unpack8888s(shData0.z);\\n\\tlet r3 = unpack8888s(shData0.w);\\n\\tlet g0 = unpack8888s(shData1.x);\\n\\tlet g1 = unpack8888s(shData1.y);\\n\\tlet g2 = unpack8888s(shData1.z);\\n\\tlet g3 = unpack8888s(shData1.w);\\n\\tlet b0 = unpack8888s(shData2.x);\\n\\tlet b1 = unpack8888s(shData2.y);\\n\\tlet b2 = unpack8888s(shData2.z);\\n\\tlet b3 = unpack8888s(shData2.w);\\n\\tsh[0] =  vec3f(r0.x, g0.x, b0.x);\\n\\tsh[1] =  vec3f(r0.y, g0.y, b0.y);\\n\\tsh[2] =  vec3f(r0.z, g0.z, b0.z);\\n\\tsh[3] =  vec3f(r0.w, g0.w, b0.w);\\n\\tsh[4] =  vec3f(r1.x, g1.x, b1.x);\\n\\tsh[5] =  vec3f(r1.y, g1.y, b1.y);\\n\\tsh[6] =  vec3f(r1.z, g1.z, b1.z);\\n\\tsh[7] =  vec3f(r1.w, g1.w, b1.w);\\n\\tsh[8] =  vec3f(r2.x, g2.x, b2.x);\\n\\tsh[9] =  vec3f(r2.y, g2.y, b2.y);\\n\\tsh[10] = vec3f(r2.z, g2.z, b2.z);\\n\\tsh[11] = vec3f(r2.w, g2.w, b2.w);\\n\\tsh[12] = vec3f(r3.x, g3.x, b3.x);\\n\\tsh[13] = vec3f(r3.y, g3.y, b3.y);\\n\\tsh[14] = vec3f(r3.z, g3.z, b3.z);\\n\\t*scale = 1.0;\\n}\\n#endif\\n`;\\n\\nvar gsplatSogVS = `\\n#include \\\"gsplatPackingPS\\\"\\nuniform means_mins: vec3f;\\nuniform means_maxs: vec3f;\\nuniform scales_mins: f32;\\nuniform scales_maxs: f32;\\nuniform sh0_mins: f32;\\nuniform sh0_maxs: f32;\\nvar packedSh0: texture_2d<f32>;\\nconst SH_C0: f32 = 0.28209479177387814;\\nvar<private> packedSample: vec4<u32>;\\nconst norm: f32 = sqrt(2.0);\\nfn getCenter() -> vec3f {\\n\\tpackedSample = loadPackedTexture();\\n\\tlet l = unpack8888(packedSample.x).xyz;\\n\\tlet u = unpack8888(packedSample.y).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 getColor() -> vec4f {\\n\\tlet clr = mix(vec3f(uniform.sh0_mins), vec3f(uniform.sh0_maxs), unpack111110(pack8888(textureLoad(packedSh0, splat.uv, 0))));\\n\\tlet alpha = f32(packedSample.z & 0xffu) / 255.0;\\n\\treturn vec4f(vec3f(0.5) + clr * SH_C0, alpha);\\n}\\nfn getRotation() -> vec4f {\\n\\tlet qdata = unpack8888(packedSample.z).xyz;\\n\\tlet qmode = packedSample.w & 0x3u;\\n\\tlet abc = (qdata - 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 sdata = unpack101010(packedSample.w >> 2u);\\n\\treturn exp(mix(vec3f(uniform.scales_mins), vec3f(uniform.scales_maxs), sdata));\\n}\\n#include \\\"gsplatSogSHVS\\\"\\n`;\\n\\nvar gsplatSogSHVS = `\\n#if SH_BANDS > 0\\nvar packedShN: texture_2d<f32>;\\nuniform shN_mins: f32;\\nuniform shN_maxs: f32;\\nfn readSHData(sh: ptr<function, array<vec3f, SH_COEFFS>>, scale: ptr<function, f32>) {\\n\\tlet t = vec2i(packedSample.xy & vec2u(255u));\\n\\tlet n = t.x + t.y * 256;\\n\\tlet u = (n % 64) * SH_COEFFS;\\n\\tlet v = n / 64;\\n\\tfor (var i: i32 = 0; i < SH_COEFFS; i = i + 1) {\\n\\t\\tsh[i] = mix(vec3f(uniform.shN_mins), vec3f(uniform.shN_maxs), unpack111110(pack8888(textureLoad(packedShN, vec2i(u + i, v), 0))));\\n\\t}\\n\\t*scale = 1.0;\\n}\\n#endif\\n`;\\n\\nvar gsplatContainerDeclVS = `\\n#include \\\"gsplatContainerDeclarationsVS\\\"\\nvar<private> splatCenter: vec3f;\\nvar<private> splatColor: vec4f;\\nvar<private> splatScale: vec3f;\\nvar<private> splatRotation: vec4f;\\n`;\\n\\nvar gsplatContainerReadVS = `\\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\\nvar gsplatContainerPackedReadVS = `\\nvar<private> cachedTransformA: vec4u;\\nvar<private> cachedTransformB: vec2u;\\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 getColor() -> vec4f {\\n\\t#ifdef GSPLAT_COLOR_FLOAT\\n\\t\\treturn 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\\treturn vec4f(unpack2x16float(packed_rg), unpack2x16float(packed_ba));\\n\\t#endif\\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\\nconst gsplatChunksWGSL = {\\n\\t\\tgsplatCenterVS,\\n\\t\\tgsplatCornerVS,\\n\\t\\tgsplatCommonVS,\\n\\t\\tgsplatSplatVS,\\n\\t\\tgsplatEvalSHVS,\\n\\t\\tgsplatHelpersVS,\\n\\t\\tgsplatModifyVS,\\n\\t\\tgsplatStructsVS,\\n\\t\\tgsplatQuatToMat3VS,\\n\\t\\tgsplatOutputVS,\\n\\t\\tgsplatPS,\\n\\t\\tgsplatSourceVS,\\n\\t\\tgsplatVS,\\n\\t\\tgsplatPackingPS,\\n\\t\\tgsplatFormatVS,\\n\\t\\tgsplatUncompressedVS,\\n\\t\\tgsplatUncompressedSHVS,\\n\\t\\tgsplatCompressedVS,\\n\\t\\tgsplatCompressedSHVS,\\n\\t\\tgsplatSogVS,\\n\\t\\tgsplatSogSHVS,\\n\\t\\tgsplatContainerDeclVS,\\n\\t\\tgsplatContainerReadVS,\\n\\t\\tgsplatContainerPackedReadVS,\\n\\t\\tgsplatContainerFloatReadVS\\n};\\n\\nconst _schema = [\\n\\t\\t'enabled'\\n];\\nconst _properties = [\\n\\t\\t'unified',\\n\\t\\t'lodDistances',\\n\\t\\t'castShadows',\\n\\t\\t'material',\\n\\t\\t'highQualitySH',\\n\\t\\t'asset',\\n\\t\\t'resource',\\n\\t\\t'layers'\\n];\\nclass GSplatComponentSystem extends ComponentSystem {\\n\\t\\tinitializeComponentData(component, _data, properties) {\\n\\t\\t\\t\\tif (_data.layers && _data.layers.length) {\\n\\t\\t\\t\\t\\t\\t_data.layers = _data.layers.slice(0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < _properties.length; i++){\\n\\t\\t\\t\\t\\t\\tif (_data.hasOwnProperty(_properties[i])) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponent[_properties[i]] = _data[_properties[i]];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (_data.aabbCenter && _data.aabbHalfExtents) {\\n\\t\\t\\t\\t\\t\\tcomponent.customAabb = new BoundingBox(new Vec3(_data.aabbCenter), new Vec3(_data.aabbHalfExtents));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tsuper.initializeComponentData(component, _data, _schema);\\n\\t\\t}\\n\\t\\tcloneComponent(entity, clone) {\\n\\t\\t\\t\\tconst gSplatComponent = entity.gsplat;\\n\\t\\t\\t\\tconst data = {};\\n\\t\\t\\t\\t_properties.forEach((prop)=>{\\n\\t\\t\\t\\t\\t\\tif (prop === 'material') {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!gSplatComponent.unified) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst srcMaterial = gSplatComponent[prop];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (srcMaterial) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata[prop] = srcMaterial.clone();\\n\\t\\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} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tdata[prop] = gSplatComponent[prop];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tdata.enabled = gSplatComponent.enabled;\\n\\t\\t\\t\\tconst component = this.addComponent(clone, data);\\n\\t\\t\\t\\tcomponent.customAabb = gSplatComponent.customAabb?.clone() ?? null;\\n\\t\\t\\t\\treturn component;\\n\\t\\t}\\n\\t\\tonRemove(entity, component) {\\n\\t\\t\\t\\tcomponent.onRemove();\\n\\t\\t}\\n\\t\\tgetMaterial(camera, layer) {\\n\\t\\t\\t\\tconst director = this.app.renderer.gsplatDirector;\\n\\t\\t\\t\\tif (!director) return null;\\n\\t\\t\\t\\tconst cameraData = director.camerasMap.get(camera);\\n\\t\\t\\t\\tif (!cameraData) return null;\\n\\t\\t\\t\\tconst layerData = cameraData.layersMap.get(layer);\\n\\t\\t\\t\\treturn layerData?.gsplatManager?.material ?? null;\\n\\t\\t}\\n\\t\\tgetGSplatMaterial(camera, layer) {\\n\\t\\t\\t\\treturn this.getMaterial(camera, layer);\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tsuper(app);\\n\\t\\t\\t\\tthis.id = 'gsplat';\\n\\t\\t\\t\\tthis.ComponentType = GSplatComponent;\\n\\t\\t\\t\\tthis.DataType = GSplatComponentData;\\n\\t\\t\\t\\tthis.schema = _schema;\\n\\t\\t\\t\\tapp.renderer.gsplatDirector = new GSplatDirector(app.graphicsDevice, app.renderer, app.scene, this);\\n\\t\\t\\t\\tShaderChunks.get(app.graphicsDevice, SHADERLANGUAGE_GLSL).add(gsplatChunksGLSL);\\n\\t\\t\\t\\tShaderChunks.get(app.graphicsDevice, SHADERLANGUAGE_WGSL).add(gsplatChunksWGSL);\\n\\t\\t\\t\\tthis.on('beforeremove', this.onRemove, this);\\n\\t\\t}\\n}\\nGSplatComponentSystem.EVENT_MATERIALCREATED = 'material:created';\\nGSplatComponentSystem.EVENT_FRAMEREADY = 'frame:ready';\\nComponent._buildAccessors(GSplatComponent.prototype, _schema);\\n\\nclass Render extends EventHandler {\\n\\t\\tset meshes(value) {\\n\\t\\t\\t\\tthis.decRefMeshes();\\n\\t\\t\\t\\tthis._meshes = value;\\n\\t\\t\\t\\tthis.incRefMeshes();\\n\\t\\t\\t\\tthis.fire('set:meshes', value);\\n\\t\\t}\\n\\t\\tget meshes() {\\n\\t\\t\\t\\treturn this._meshes;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.meshes = null;\\n\\t\\t}\\n\\t\\tdecRefMeshes() {\\n\\t\\t\\t\\tthis._meshes?.forEach((mesh, index)=>{\\n\\t\\t\\t\\t\\t\\tif (mesh) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh.decRefCount();\\n\\t\\t\\t\\t\\t\\t\\t\\tif (mesh.refCount < 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmesh.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._meshes[index] = null;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tincRefMeshes() {\\n\\t\\t\\t\\tthis._meshes?.forEach((mesh)=>{\\n\\t\\t\\t\\t\\t\\tmesh?.incRefCount();\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tconstructor(...args){\\n\\t\\t\\t\\tsuper(...args), this._meshes = null;\\n\\t\\t}\\n}\\nRender.EVENT_SETMESHES = 'set:meshes';\\n\\nclass AnimCurve {\\n\\t\\tget paths() {\\n\\t\\t\\t\\treturn this._paths;\\n\\t\\t}\\n\\t\\tget input() {\\n\\t\\t\\t\\treturn this._input;\\n\\t\\t}\\n\\t\\tget output() {\\n\\t\\t\\t\\treturn this._output;\\n\\t\\t}\\n\\t\\tget interpolation() {\\n\\t\\t\\t\\treturn this._interpolation;\\n\\t\\t}\\n\\t\\tconstructor(paths, input, output, interpolation){\\n\\t\\t\\t\\tthis._paths = paths;\\n\\t\\t\\t\\tthis._input = input;\\n\\t\\t\\t\\tthis._output = output;\\n\\t\\t\\t\\tthis._interpolation = interpolation;\\n\\t\\t}\\n}\\n\\nclass AnimData {\\n\\t\\tget components() {\\n\\t\\t\\t\\treturn this._components;\\n\\t\\t}\\n\\t\\tget data() {\\n\\t\\t\\t\\treturn this._data;\\n\\t\\t}\\n\\t\\tconstructor(components, data){\\n\\t\\t\\t\\tthis._components = components;\\n\\t\\t\\t\\tthis._data = data;\\n\\t\\t}\\n}\\n\\nfunction DracoWorker(jsUrl, wasmUrl) {\\n\\t\\tlet draco;\\n\\t\\tconst POSITION_ATTRIBUTE = 0;\\n\\t\\tconst NORMAL_ATTRIBUTE = 1;\\n\\t\\tconst wrap = (typedArray, dataType)=>{\\n\\t\\t\\t\\tswitch(dataType){\\n\\t\\t\\t\\t\\t\\tcase draco.DT_INT8:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn new Int8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);\\n\\t\\t\\t\\t\\t\\tcase draco.DT_INT16:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn new Int16Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength / 2);\\n\\t\\t\\t\\t\\t\\tcase draco.DT_INT32:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn new Int32Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength / 4);\\n\\t\\t\\t\\t\\t\\tcase draco.DT_UINT8:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);\\n\\t\\t\\t\\t\\t\\tcase draco.DT_UINT16:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn new Uint16Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength / 2);\\n\\t\\t\\t\\t\\t\\tcase draco.DT_UINT32:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn new Uint32Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength / 4);\\n\\t\\t\\t\\t\\t\\tcase draco.DT_FLOAT32:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn new Float32Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength / 4);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn null;\\n\\t\\t};\\n\\t\\tconst componentSizeInBytes = (dataType)=>{\\n\\t\\t\\t\\tswitch(dataType){\\n\\t\\t\\t\\t\\t\\tcase draco.DT_INT8:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 1;\\n\\t\\t\\t\\t\\t\\tcase draco.DT_INT16:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 2;\\n\\t\\t\\t\\t\\t\\tcase draco.DT_INT32:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 4;\\n\\t\\t\\t\\t\\t\\tcase draco.DT_UINT8:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 1;\\n\\t\\t\\t\\t\\t\\tcase draco.DT_UINT16:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 2;\\n\\t\\t\\t\\t\\t\\tcase draco.DT_UINT32:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 4;\\n\\t\\t\\t\\t\\t\\tcase draco.DT_FLOAT32:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 4;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn 1;\\n\\t\\t};\\n\\t\\tconst toEngineDataType = (dataType)=>{\\n\\t\\t\\t\\tswitch(dataType){\\n\\t\\t\\t\\t\\t\\tcase draco.DT_INT8:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 0;\\n\\t\\t\\t\\t\\t\\tcase draco.DT_UINT8:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 1;\\n\\t\\t\\t\\t\\t\\tcase draco.DT_INT16:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 2;\\n\\t\\t\\t\\t\\t\\tcase draco.DT_UINT16:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 3;\\n\\t\\t\\t\\t\\t\\tcase draco.DT_INT32:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 4;\\n\\t\\t\\t\\t\\t\\tcase draco.DT_UINT32:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 5;\\n\\t\\t\\t\\t\\t\\tcase draco.DT_FLOAT32:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 6;\\n\\t\\t\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 6;\\n\\t\\t\\t\\t}\\n\\t\\t};\\n\\t\\tconst attributeSizeInBytes = (attribute)=>{\\n\\t\\t\\t\\treturn attribute.num_components() * componentSizeInBytes(attribute.data_type());\\n\\t\\t};\\n\\t\\tconst attributeOrder = {\\n\\t\\t\\t\\t0: 0,\\n\\t\\t\\t\\t1: 1,\\n\\t\\t\\t\\t5: 2,\\n\\t\\t\\t\\t2: 3,\\n\\t\\t\\t\\t7: 4,\\n\\t\\t\\t\\t8: 5,\\n\\t\\t\\t\\t4: 6,\\n\\t\\t\\t\\t3: 7\\n\\t\\t};\\n\\t\\tconst generateNormals = (vertices, indices)=>{\\n\\t\\t\\t\\tconst subtract = (dst, a, b)=>{\\n\\t\\t\\t\\t\\t\\tdst[0] = a[0] - b[0];\\n\\t\\t\\t\\t\\t\\tdst[1] = a[1] - b[1];\\n\\t\\t\\t\\t\\t\\tdst[2] = a[2] - b[2];\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst cross = (dst, a, b)=>{\\n\\t\\t\\t\\t\\t\\tdst[0] = a[1] * b[2] - b[1] * a[2];\\n\\t\\t\\t\\t\\t\\tdst[1] = a[2] * b[0] - b[2] * a[0];\\n\\t\\t\\t\\t\\t\\tdst[2] = a[0] * b[1] - b[0] * a[1];\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst normalize = (dst, offset)=>{\\n\\t\\t\\t\\t\\t\\tconst a = dst[offset + 0];\\n\\t\\t\\t\\t\\t\\tconst b = dst[offset + 1];\\n\\t\\t\\t\\t\\t\\tconst c = dst[offset + 2];\\n\\t\\t\\t\\t\\t\\tconst l = 1.0 / Math.sqrt(a * a + b * b + c * c);\\n\\t\\t\\t\\t\\t\\tdst[offset + 0] *= l;\\n\\t\\t\\t\\t\\t\\tdst[offset + 1] *= l;\\n\\t\\t\\t\\t\\t\\tdst[offset + 2] *= l;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst copy = (dst, src, srcOffset)=>{\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < 3; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tdst[i] = src[srcOffset + i];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst numTriangles = indices.length / 3;\\n\\t\\t\\t\\tconst numVertices = vertices.length / 3;\\n\\t\\t\\t\\tconst result = new Float32Array(vertices.length);\\n\\t\\t\\t\\tconst a = [\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t], b = [\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t], c = [\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t], t1 = [\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t], t2 = [\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t], n = [\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tfor(let i = 0; i < numTriangles; ++i){\\n\\t\\t\\t\\t\\t\\tconst v0 = indices[i * 3 + 0] * 3;\\n\\t\\t\\t\\t\\t\\tconst v1 = indices[i * 3 + 1] * 3;\\n\\t\\t\\t\\t\\t\\tconst v2 = indices[i * 3 + 2] * 3;\\n\\t\\t\\t\\t\\t\\tcopy(a, vertices, v0);\\n\\t\\t\\t\\t\\t\\tcopy(b, vertices, v1);\\n\\t\\t\\t\\t\\t\\tcopy(c, vertices, v2);\\n\\t\\t\\t\\t\\t\\tsubtract(t1, b, a);\\n\\t\\t\\t\\t\\t\\tsubtract(t2, c, a);\\n\\t\\t\\t\\t\\t\\tcross(n, t1, t2);\\n\\t\\t\\t\\t\\t\\tnormalize(n, 0);\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j < 3; ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\tresult[v0 + j] += n[j];\\n\\t\\t\\t\\t\\t\\t\\t\\tresult[v1 + j] += n[j];\\n\\t\\t\\t\\t\\t\\t\\t\\tresult[v2 + j] += n[j];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < numVertices; ++i){\\n\\t\\t\\t\\t\\t\\tnormalize(result, i * 3);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn new Uint8Array(result.buffer);\\n\\t\\t};\\n\\t\\tconst decodeMesh = (inputBuffer)=>{\\n\\t\\t\\t\\tconst result = {};\\n\\t\\t\\t\\tconst buffer = new draco.DecoderBuffer();\\n\\t\\t\\t\\tbuffer.Init(inputBuffer, inputBuffer.length);\\n\\t\\t\\t\\tconst decoder = new draco.Decoder();\\n\\t\\t\\t\\tif (decoder.GetEncodedGeometryType(buffer) !== draco.TRIANGULAR_MESH) {\\n\\t\\t\\t\\t\\t\\tresult.error = 'Failed to decode draco mesh: not a mesh';\\n\\t\\t\\t\\t\\t\\treturn result;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst mesh = new draco.Mesh();\\n\\t\\t\\t\\tconst status = decoder.DecodeBufferToMesh(buffer, mesh);\\n\\t\\t\\t\\tif (!status || !status.ok() || draco.getPointer(mesh) === 0) {\\n\\t\\t\\t\\t\\t\\tresult.error = 'Failed to decode draco asset';\\n\\t\\t\\t\\t\\t\\treturn result;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst numIndices = mesh.num_faces() * 3;\\n\\t\\t\\t\\tconst shortIndices = mesh.num_points() <= 65535;\\n\\t\\t\\t\\tconst indicesSize = numIndices * (shortIndices ? 2 : 4);\\n\\t\\t\\t\\tconst indicesPtr = draco._malloc(indicesSize);\\n\\t\\t\\t\\tif (shortIndices) {\\n\\t\\t\\t\\t\\t\\tdecoder.GetTrianglesUInt16Array(mesh, indicesSize, indicesPtr);\\n\\t\\t\\t\\t\\t\\tresult.indices = new Uint16Array(draco.HEAPU16.buffer, indicesPtr, numIndices).slice().buffer;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tdecoder.GetTrianglesUInt32Array(mesh, indicesSize, indicesPtr);\\n\\t\\t\\t\\t\\t\\tresult.indices = new Uint32Array(draco.HEAPU32.buffer, indicesPtr, numIndices).slice().buffer;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdraco._free(indicesPtr);\\n\\t\\t\\t\\tconst attributes = [];\\n\\t\\t\\t\\tfor(let i = 0; i < mesh.num_attributes(); ++i){\\n\\t\\t\\t\\t\\t\\tattributes.push(decoder.GetAttribute(mesh, i));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tattributes.sort((a, b)=>{\\n\\t\\t\\t\\t\\t\\treturn (attributeOrder[a.attribute_type()] ?? attributeOrder.length) - (attributeOrder[b.attribute_type()] ?? attributeOrder.length);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tlet totalVertexSize = 0;\\n\\t\\t\\t\\tconst offsets = attributes.map((a)=>{\\n\\t\\t\\t\\t\\t\\tconst offset = totalVertexSize;\\n\\t\\t\\t\\t\\t\\ttotalVertexSize += Math.ceil(attributeSizeInBytes(a) / 4) * 4;\\n\\t\\t\\t\\t\\t\\treturn offset;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst hasNormals = attributes.some((a)=>a.attribute_type() === NORMAL_ATTRIBUTE);\\n\\t\\t\\t\\tlet normalOffset = offsets[1] ?? 0;\\n\\t\\t\\t\\tif (!hasNormals) {\\n\\t\\t\\t\\t\\t\\tnormalOffset = offsets[0] + Math.ceil(attributeSizeInBytes(attributes[0]) / 4) * 4;\\n\\t\\t\\t\\t\\t\\tfor(let i = 1; i < offsets.length; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\toffsets[i] += 12;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\ttotalVertexSize += 12;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tresult.attributes = attributes.map((a, i)=>({\\n\\t\\t\\t\\t\\t\\t\\t\\tid: a.unique_id(),\\n\\t\\t\\t\\t\\t\\t\\t\\tdataType: toEngineDataType(a.data_type()),\\n\\t\\t\\t\\t\\t\\t\\t\\tnumComponents: a.num_components(),\\n\\t\\t\\t\\t\\t\\t\\t\\toffset: offsets[i]\\n\\t\\t\\t\\t\\t\\t}));\\n\\t\\t\\t\\tif (!hasNormals) {\\n\\t\\t\\t\\t\\t\\tresult.attributes.splice(1, 0, {\\n\\t\\t\\t\\t\\t\\t\\t\\tid: -1,\\n\\t\\t\\t\\t\\t\\t\\t\\tdataType: 6,\\n\\t\\t\\t\\t\\t\\t\\t\\tnumComponents: 3,\\n\\t\\t\\t\\t\\t\\t\\t\\toffset: normalOffset\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tresult.stride = totalVertexSize;\\n\\t\\t\\t\\tresult.vertices = new ArrayBuffer(mesh.num_points() * totalVertexSize);\\n\\t\\t\\t\\tconst dst = new Uint8Array(result.vertices);\\n\\t\\t\\t\\tfor(let i = 0; i < mesh.num_attributes(); ++i){\\n\\t\\t\\t\\t\\t\\tconst attribute = attributes[i];\\n\\t\\t\\t\\t\\t\\tconst sizeInBytes = attributeSizeInBytes(attribute);\\n\\t\\t\\t\\t\\t\\tconst ptrSize = mesh.num_points() * sizeInBytes;\\n\\t\\t\\t\\t\\t\\tconst ptr = draco._malloc(ptrSize);\\n\\t\\t\\t\\t\\t\\tdecoder.GetAttributeDataArrayForAllPoints(mesh, attribute, attribute.data_type(), ptrSize, ptr);\\n\\t\\t\\t\\t\\t\\tconst src = new Uint8Array(draco.HEAPU8.buffer, ptr, ptrSize);\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j < mesh.num_points(); ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let c = 0; c < sizeInBytes; ++c){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdst[j * totalVertexSize + offsets[i] + c] = src[j * sizeInBytes + c];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!hasNormals && attribute.attribute_type() === POSITION_ATTRIBUTE) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst normals = generateNormals(wrap(src, attribute.data_type()), shortIndices ? new Uint16Array(result.indices) : new Uint32Array(result.indices));\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < mesh.num_points(); ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let c = 0; c < 12; ++c){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdst[j * totalVertexSize + normalOffset + c] = normals[j * 12 + c];\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tdraco._free(ptr);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdraco.destroy(mesh);\\n\\t\\t\\t\\tdraco.destroy(decoder);\\n\\t\\t\\t\\tdraco.destroy(buffer);\\n\\t\\t\\t\\treturn result;\\n\\t\\t};\\n\\t\\tconst decode = (data)=>{\\n\\t\\t\\t\\tconst result = decodeMesh(new Uint8Array(data.buffer));\\n\\t\\t\\t\\tself.postMessage({\\n\\t\\t\\t\\t\\t\\tjobId: data.jobId,\\n\\t\\t\\t\\t\\t\\terror: result.error,\\n\\t\\t\\t\\t\\t\\tindices: result.indices,\\n\\t\\t\\t\\t\\t\\tvertices: result.vertices,\\n\\t\\t\\t\\t\\t\\tattributes: result.attributes,\\n\\t\\t\\t\\t\\t\\tstride: result.stride\\n\\t\\t\\t\\t}, [\\n\\t\\t\\t\\t\\t\\tresult.indices,\\n\\t\\t\\t\\t\\t\\tresult.vertices\\n\\t\\t\\t\\t].filter((t)=>t != null));\\n\\t\\t};\\n\\t\\tconst workQueue = [];\\n\\t\\tself.onmessage = (message)=>{\\n\\t\\t\\t\\tconst data = message.data;\\n\\t\\t\\t\\tswitch(data.type){\\n\\t\\t\\t\\t\\t\\tcase 'init':\\n\\t\\t\\t\\t\\t\\t\\t\\tself.DracoDecoderModule({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinstantiateWasm: (imports, successCallback)=>{\\n\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\t\\treturn {};\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t}).then((instance)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdraco = instance;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tworkQueue.forEach((data)=>decode(data));\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 'decodeMesh':\\n\\t\\t\\t\\t\\t\\t\\t\\tif (draco) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdecode(data);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tworkQueue.push(data);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t};\\n}\\n\\nconst downloadMaxRetries = 3;\\nclass JobQueue {\\n\\t\\tinit(workers) {\\n\\t\\t\\t\\tworkers.forEach((worker)=>{\\n\\t\\t\\t\\t\\t\\tworker.addEventListener('message', (message)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst data = message.data;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst callback = this.jobCallbacks.get(data.jobId);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (callback) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(data.error, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices: data.indices,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvertices: data.vertices,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tattributes: data.attributes,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstride: data.stride\\n\\t\\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\\tthis.jobCallbacks.delete(data.jobId);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.jobQueue.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst job = this.jobQueue.shift();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.run(worker, job);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst index2 = this.workers[2].indexOf(worker);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (index2 !== -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.workers[2].splice(index2, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.workers[1].push(worker);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst index1 = this.workers[1].indexOf(worker);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (index1 !== -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.workers[1].splice(index1, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.workers[0].push(worker);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.workers[0] = workers;\\n\\t\\t\\t\\twhile(this.jobQueue.length && (this.workers[0].length || this.workers[1].length)){\\n\\t\\t\\t\\t\\t\\tconst job = this.jobQueue.shift();\\n\\t\\t\\t\\t\\t\\tif (this.workers[0].length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst worker = this.workers[0].shift();\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.workers[1].push(worker);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.run(worker, job);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst worker = this.workers[1].shift();\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.workers[2].push(worker);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.run(worker, job);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tenqueueJob(buffer, callback) {\\n\\t\\t\\t\\tconst job = {\\n\\t\\t\\t\\t\\t\\tjobId: this.jobId++,\\n\\t\\t\\t\\t\\t\\tbuffer: buffer\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.jobCallbacks.set(job.jobId, callback);\\n\\t\\t\\t\\tif (this.workers[0].length > 0) {\\n\\t\\t\\t\\t\\t\\tconst worker = this.workers[0].shift();\\n\\t\\t\\t\\t\\t\\tthis.workers[1].push(worker);\\n\\t\\t\\t\\t\\t\\tthis.run(worker, job);\\n\\t\\t\\t\\t} else if (this.workers[1].length > 0) {\\n\\t\\t\\t\\t\\t\\tconst worker = this.workers[1].shift();\\n\\t\\t\\t\\t\\t\\tthis.workers[2].push(worker);\\n\\t\\t\\t\\t\\t\\tthis.run(worker, job);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.jobQueue.push(job);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.workers = [\\n\\t\\t\\t\\t\\t\\t[],\\n\\t\\t\\t\\t\\t\\t[],\\n\\t\\t\\t\\t\\t\\t[]\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis.jobId = 0;\\n\\t\\t\\t\\tthis.jobQueue = [];\\n\\t\\t\\t\\tthis.jobCallbacks = new Map();\\n\\t\\t\\t\\tthis.run = (worker, job)=>{\\n\\t\\t\\t\\t\\t\\tworker.postMessage({\\n\\t\\t\\t\\t\\t\\t\\t\\ttype: 'decodeMesh',\\n\\t\\t\\t\\t\\t\\t\\t\\tjobId: job.jobId,\\n\\t\\t\\t\\t\\t\\t\\t\\tbuffer: job.buffer\\n\\t\\t\\t\\t\\t\\t}, [\\n\\t\\t\\t\\t\\t\\t\\t\\tjob.buffer\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t};\\n\\t\\t}\\n}\\nconst downloadScript = (url)=>{\\n\\t\\treturn new Promise((resolve, reject)=>{\\n\\t\\t\\t\\tconst options = {\\n\\t\\t\\t\\t\\t\\tcache: true,\\n\\t\\t\\t\\t\\t\\tresponseType: 'text',\\n\\t\\t\\t\\t\\t\\tretry: downloadMaxRetries > 0,\\n\\t\\t\\t\\t\\t\\tmaxRetries: downloadMaxRetries\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\thttp.get(url, options, (err, response)=>{\\n\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\treject(err);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tresolve(response);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t});\\n};\\nconst compileModule = (url)=>{\\n\\t\\tconst compileManual = ()=>{\\n\\t\\t\\t\\treturn fetch(url).then((result)=>result.arrayBuffer()).then((buffer)=>WebAssembly.compile(buffer));\\n\\t\\t};\\n\\t\\tconst compileStreaming = ()=>{\\n\\t\\t\\t\\treturn WebAssembly.compileStreaming(fetch(url)).catch((err)=>{\\n\\t\\t\\t\\t\\t\\treturn compileManual();\\n\\t\\t\\t\\t});\\n\\t\\t};\\n\\t\\treturn WebAssembly.compileStreaming ? compileStreaming() : compileManual();\\n};\\nconst defaultNumWorkers$1 = 1;\\nlet jobQueue;\\nconst initializeWorkers = (config)=>{\\n\\t\\tif (jobQueue) {\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tif (!config) {\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\tconst moduleConfig = WasmModule.getConfig('DracoDecoderModule');\\n\\t\\t\\t\\t\\t\\tif (moduleConfig) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconfig = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tjsUrl: moduleConfig.glueUrl,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twasmUrl: moduleConfig.wasmUrl,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnumWorkers: moduleConfig.numWorkers\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconfig = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tjsUrl: 'draco.wasm.js',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twasmUrl: 'draco.wasm.wasm',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnumWorkers: defaultNumWorkers$1\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (!config.jsUrl || !config.wasmUrl) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tjobQueue = new JobQueue();\\n\\t\\tPromise.all([\\n\\t\\t\\t\\tdownloadScript(config.jsUrl),\\n\\t\\t\\t\\tcompileModule(config.wasmUrl)\\n\\t\\t]).then(([dracoSource, dracoModule])=>{\\n\\t\\t\\t\\tconst code = [\\n\\t\\t\\t\\t\\t\\t'/* draco */',\\n\\t\\t\\t\\t\\t\\tdracoSource,\\n\\t\\t\\t\\t\\t\\t'/* worker */',\\n\\t\\t\\t\\t\\t\\t`(\\\\n${DracoWorker.toString()}\\\\n)()\\\\n\\\\n`\\n\\t\\t\\t\\t].join('\\\\n');\\n\\t\\t\\t\\tconst blob = new Blob([\\n\\t\\t\\t\\t\\t\\tcode\\n\\t\\t\\t\\t], {\\n\\t\\t\\t\\t\\t\\ttype: \\\"application/javascript\\\"\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst workerUrl = URL.createObjectURL(blob);\\n\\t\\t\\t\\tconst numWorkers = Math.max(1, Math.min(16, config.numWorkers || defaultNumWorkers$1));\\n\\t\\t\\t\\tconst workers = [];\\n\\t\\t\\t\\tfor(let i = 0; i < numWorkers; ++i){\\n\\t\\t\\t\\t\\t\\tconst worker = new Worker(workerUrl);\\n\\t\\t\\t\\t\\t\\tworker.postMessage({\\n\\t\\t\\t\\t\\t\\t\\t\\ttype: 'init',\\n\\t\\t\\t\\t\\t\\t\\t\\tmodule: dracoModule\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tworkers.push(worker);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tjobQueue.init(workers);\\n\\t\\t});\\n\\t\\treturn true;\\n};\\nconst dracoDecode = (buffer, callback)=>{\\n\\t\\tif (!initializeWorkers()) {\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tjobQueue.enqueueJob(buffer, callback);\\n\\t\\treturn true;\\n};\\n\\nclass GlbResources {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tif (this.renders) {\\n\\t\\t\\t\\t\\t\\tthis.renders.forEach((render)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\trender.meshes = null;\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nconst isDataURI = (uri)=>{\\n\\t\\treturn /^data:[^\\\\n\\\\r,\\\\u2028\\\\u2029]*,.*$/i.test(uri);\\n};\\nconst getDataURIMimeType = (uri)=>{\\n\\t\\treturn uri.substring(uri.indexOf(':') + 1, uri.indexOf(';'));\\n};\\nconst getNumComponents = (accessorType)=>{\\n\\t\\tswitch(accessorType){\\n\\t\\t\\t\\tcase 'SCALAR':\\n\\t\\t\\t\\t\\t\\treturn 1;\\n\\t\\t\\t\\tcase 'VEC2':\\n\\t\\t\\t\\t\\t\\treturn 2;\\n\\t\\t\\t\\tcase 'VEC3':\\n\\t\\t\\t\\t\\t\\treturn 3;\\n\\t\\t\\t\\tcase 'VEC4':\\n\\t\\t\\t\\t\\t\\treturn 4;\\n\\t\\t\\t\\tcase 'MAT2':\\n\\t\\t\\t\\t\\t\\treturn 4;\\n\\t\\t\\t\\tcase 'MAT3':\\n\\t\\t\\t\\t\\t\\treturn 9;\\n\\t\\t\\t\\tcase 'MAT4':\\n\\t\\t\\t\\t\\t\\treturn 16;\\n\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\treturn 3;\\n\\t\\t}\\n};\\nconst getComponentType = (componentType)=>{\\n\\t\\tswitch(componentType){\\n\\t\\t\\t\\tcase 5120:\\n\\t\\t\\t\\t\\t\\treturn TYPE_INT8;\\n\\t\\t\\t\\tcase 5121:\\n\\t\\t\\t\\t\\t\\treturn TYPE_UINT8;\\n\\t\\t\\t\\tcase 5122:\\n\\t\\t\\t\\t\\t\\treturn TYPE_INT16;\\n\\t\\t\\t\\tcase 5123:\\n\\t\\t\\t\\t\\t\\treturn TYPE_UINT16;\\n\\t\\t\\t\\tcase 5124:\\n\\t\\t\\t\\t\\t\\treturn TYPE_INT32;\\n\\t\\t\\t\\tcase 5125:\\n\\t\\t\\t\\t\\t\\treturn TYPE_UINT32;\\n\\t\\t\\t\\tcase 5126:\\n\\t\\t\\t\\t\\t\\treturn TYPE_FLOAT32;\\n\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\treturn 0;\\n\\t\\t}\\n};\\nconst getComponentSizeInBytes = (componentType)=>{\\n\\t\\tswitch(componentType){\\n\\t\\t\\t\\tcase 5120:\\n\\t\\t\\t\\t\\t\\treturn 1;\\n\\t\\t\\t\\tcase 5121:\\n\\t\\t\\t\\t\\t\\treturn 1;\\n\\t\\t\\t\\tcase 5122:\\n\\t\\t\\t\\t\\t\\treturn 2;\\n\\t\\t\\t\\tcase 5123:\\n\\t\\t\\t\\t\\t\\treturn 2;\\n\\t\\t\\t\\tcase 5124:\\n\\t\\t\\t\\t\\t\\treturn 4;\\n\\t\\t\\t\\tcase 5125:\\n\\t\\t\\t\\t\\t\\treturn 4;\\n\\t\\t\\t\\tcase 5126:\\n\\t\\t\\t\\t\\t\\treturn 4;\\n\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\treturn 0;\\n\\t\\t}\\n};\\nconst getComponentDataType = (componentType)=>{\\n\\t\\tswitch(componentType){\\n\\t\\t\\t\\tcase 5120:\\n\\t\\t\\t\\t\\t\\treturn Int8Array;\\n\\t\\t\\t\\tcase 5121:\\n\\t\\t\\t\\t\\t\\treturn Uint8Array;\\n\\t\\t\\t\\tcase 5122:\\n\\t\\t\\t\\t\\t\\treturn Int16Array;\\n\\t\\t\\t\\tcase 5123:\\n\\t\\t\\t\\t\\t\\treturn Uint16Array;\\n\\t\\t\\t\\tcase 5124:\\n\\t\\t\\t\\t\\t\\treturn Int32Array;\\n\\t\\t\\t\\tcase 5125:\\n\\t\\t\\t\\t\\t\\treturn Uint32Array;\\n\\t\\t\\t\\tcase 5126:\\n\\t\\t\\t\\t\\t\\treturn Float32Array;\\n\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t}\\n};\\nconst gltfToEngineSemanticMap = {\\n\\t\\t'POSITION': SEMANTIC_POSITION,\\n\\t\\t'NORMAL': SEMANTIC_NORMAL,\\n\\t\\t'TANGENT': SEMANTIC_TANGENT,\\n\\t\\t'COLOR_0': SEMANTIC_COLOR,\\n\\t\\t'JOINTS_0': SEMANTIC_BLENDINDICES,\\n\\t\\t'WEIGHTS_0': SEMANTIC_BLENDWEIGHT,\\n\\t\\t'TEXCOORD_0': SEMANTIC_TEXCOORD0,\\n\\t\\t'TEXCOORD_1': SEMANTIC_TEXCOORD1,\\n\\t\\t'TEXCOORD_2': SEMANTIC_TEXCOORD2,\\n\\t\\t'TEXCOORD_3': SEMANTIC_TEXCOORD3,\\n\\t\\t'TEXCOORD_4': SEMANTIC_TEXCOORD4,\\n\\t\\t'TEXCOORD_5': SEMANTIC_TEXCOORD5,\\n\\t\\t'TEXCOORD_6': SEMANTIC_TEXCOORD6,\\n\\t\\t'TEXCOORD_7': SEMANTIC_TEXCOORD7\\n};\\nconst attributeOrder = {\\n\\t\\t[SEMANTIC_POSITION]: 0,\\n\\t\\t[SEMANTIC_NORMAL]: 1,\\n\\t\\t[SEMANTIC_TANGENT]: 2,\\n\\t\\t[SEMANTIC_COLOR]: 3,\\n\\t\\t[SEMANTIC_BLENDINDICES]: 4,\\n\\t\\t[SEMANTIC_BLENDWEIGHT]: 5,\\n\\t\\t[SEMANTIC_TEXCOORD0]: 6,\\n\\t\\t[SEMANTIC_TEXCOORD1]: 7,\\n\\t\\t[SEMANTIC_TEXCOORD2]: 8,\\n\\t\\t[SEMANTIC_TEXCOORD3]: 9,\\n\\t\\t[SEMANTIC_TEXCOORD4]: 10,\\n\\t\\t[SEMANTIC_TEXCOORD5]: 11,\\n\\t\\t[SEMANTIC_TEXCOORD6]: 12,\\n\\t\\t[SEMANTIC_TEXCOORD7]: 13\\n};\\nconst getDequantizeFunc = (srcType)=>{\\n\\t\\tswitch(srcType){\\n\\t\\t\\t\\tcase TYPE_INT8:\\n\\t\\t\\t\\t\\t\\treturn (x)=>Math.max(x / 127.0, -1);\\n\\t\\t\\t\\tcase TYPE_UINT8:\\n\\t\\t\\t\\t\\t\\treturn (x)=>x / 255.0;\\n\\t\\t\\t\\tcase TYPE_INT16:\\n\\t\\t\\t\\t\\t\\treturn (x)=>Math.max(x / 32767.0, -1);\\n\\t\\t\\t\\tcase TYPE_UINT16:\\n\\t\\t\\t\\t\\t\\treturn (x)=>x / 65535.0;\\n\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\treturn (x)=>x;\\n\\t\\t}\\n};\\nconst dequantizeArray = (dstArray, srcArray, srcType)=>{\\n\\t\\tconst convFunc = getDequantizeFunc(srcType);\\n\\t\\tconst len = srcArray.length;\\n\\t\\tfor(let i = 0; i < len; ++i){\\n\\t\\t\\t\\tdstArray[i] = convFunc(srcArray[i]);\\n\\t\\t}\\n\\t\\treturn dstArray;\\n};\\nconst getAccessorData = (gltfAccessor, bufferViews, flatten = false)=>{\\n\\t\\tconst numComponents = getNumComponents(gltfAccessor.type);\\n\\t\\tconst dataType = getComponentDataType(gltfAccessor.componentType);\\n\\t\\tif (!dataType) {\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tlet result;\\n\\t\\tif (gltfAccessor.sparse) {\\n\\t\\t\\t\\tconst sparse = gltfAccessor.sparse;\\n\\t\\t\\t\\tconst indicesAccessor = {\\n\\t\\t\\t\\t\\t\\tcount: sparse.count,\\n\\t\\t\\t\\t\\t\\ttype: 'SCALAR'\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst indices = getAccessorData(Object.assign(indicesAccessor, sparse.indices), bufferViews, true);\\n\\t\\t\\t\\tconst valuesAccessor = {\\n\\t\\t\\t\\t\\t\\tcount: sparse.count,\\n\\t\\t\\t\\t\\t\\ttype: gltfAccessor.type,\\n\\t\\t\\t\\t\\t\\tcomponentType: gltfAccessor.componentType\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst values = getAccessorData(Object.assign(valuesAccessor, sparse.values), bufferViews, true);\\n\\t\\t\\t\\tif (gltfAccessor.hasOwnProperty('bufferView')) {\\n\\t\\t\\t\\t\\t\\tconst baseAccessor = {\\n\\t\\t\\t\\t\\t\\t\\t\\tbufferView: gltfAccessor.bufferView,\\n\\t\\t\\t\\t\\t\\t\\t\\tbyteOffset: gltfAccessor.byteOffset,\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponentType: gltfAccessor.componentType,\\n\\t\\t\\t\\t\\t\\t\\t\\tcount: gltfAccessor.count,\\n\\t\\t\\t\\t\\t\\t\\t\\ttype: gltfAccessor.type\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tresult = getAccessorData(baseAccessor, bufferViews, true).slice();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tresult = new dataType(gltfAccessor.count * numComponents);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < sparse.count; ++i){\\n\\t\\t\\t\\t\\t\\tconst targetIndex = indices[i];\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j < numComponents; ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\tresult[targetIndex * numComponents + j] = values[i * numComponents + j];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\t\\tif (gltfAccessor.hasOwnProperty('bufferView')) {\\n\\t\\t\\t\\t\\t\\tconst bufferView = bufferViews[gltfAccessor.bufferView];\\n\\t\\t\\t\\t\\t\\tif (flatten && bufferView.hasOwnProperty('byteStride')) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst bytesPerElement = numComponents * dataType.BYTES_PER_ELEMENT;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst storage = new ArrayBuffer(gltfAccessor.count * bytesPerElement);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst tmpArray = new Uint8Array(storage);\\n\\t\\t\\t\\t\\t\\t\\t\\tlet dstOffset = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < gltfAccessor.count; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet srcOffset = (gltfAccessor.byteOffset || 0) + i * bufferView.byteStride;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let b = 0; b < bytesPerElement; ++b){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttmpArray[dstOffset++] = bufferView[srcOffset++];\\n\\t\\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\\tresult = new dataType(storage);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tresult = new dataType(bufferView.buffer, bufferView.byteOffset + (gltfAccessor.byteOffset || 0), gltfAccessor.count * numComponents);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tresult = new dataType(gltfAccessor.count * numComponents);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn result;\\n};\\nconst getAccessorDataFloat32 = (gltfAccessor, bufferViews)=>{\\n\\t\\tconst data = getAccessorData(gltfAccessor, bufferViews, true);\\n\\t\\tif (data instanceof Float32Array || !gltfAccessor.normalized) {\\n\\t\\t\\t\\treturn data;\\n\\t\\t}\\n\\t\\tconst float32Data = new Float32Array(data.length);\\n\\t\\tdequantizeArray(float32Data, data, getComponentType(gltfAccessor.componentType));\\n\\t\\treturn float32Data;\\n};\\nconst getAccessorBoundingBox = (gltfAccessor)=>{\\n\\t\\tlet min = gltfAccessor.min;\\n\\t\\tlet max = gltfAccessor.max;\\n\\t\\tif (!min || !max) {\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tif (gltfAccessor.normalized) {\\n\\t\\t\\t\\tconst ctype = getComponentType(gltfAccessor.componentType);\\n\\t\\t\\t\\tmin = dequantizeArray([], min, ctype);\\n\\t\\t\\t\\tmax = dequantizeArray([], max, ctype);\\n\\t\\t}\\n\\t\\treturn new BoundingBox(new Vec3((max[0] + min[0]) * 0.5, (max[1] + min[1]) * 0.5, (max[2] + min[2]) * 0.5), new Vec3((max[0] - min[0]) * 0.5, (max[1] - min[1]) * 0.5, (max[2] - min[2]) * 0.5));\\n};\\nconst getPrimitiveType = (primitive)=>{\\n\\t\\tif (!primitive.hasOwnProperty('mode')) {\\n\\t\\t\\t\\treturn PRIMITIVE_TRIANGLES;\\n\\t\\t}\\n\\t\\tswitch(primitive.mode){\\n\\t\\t\\t\\tcase 0:\\n\\t\\t\\t\\t\\t\\treturn PRIMITIVE_POINTS;\\n\\t\\t\\t\\tcase 1:\\n\\t\\t\\t\\t\\t\\treturn PRIMITIVE_LINES;\\n\\t\\t\\t\\tcase 2:\\n\\t\\t\\t\\t\\t\\treturn PRIMITIVE_LINELOOP;\\n\\t\\t\\t\\tcase 3:\\n\\t\\t\\t\\t\\t\\treturn PRIMITIVE_LINESTRIP;\\n\\t\\t\\t\\tcase 4:\\n\\t\\t\\t\\t\\t\\treturn PRIMITIVE_TRIANGLES;\\n\\t\\t\\t\\tcase 5:\\n\\t\\t\\t\\t\\t\\treturn PRIMITIVE_TRISTRIP;\\n\\t\\t\\t\\tcase 6:\\n\\t\\t\\t\\t\\t\\treturn PRIMITIVE_TRIFAN;\\n\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\treturn PRIMITIVE_TRIANGLES;\\n\\t\\t}\\n};\\nconst generateIndices = (numVertices)=>{\\n\\t\\tconst dummyIndices = new Uint16Array(numVertices);\\n\\t\\tfor(let i = 0; i < numVertices; i++){\\n\\t\\t\\t\\tdummyIndices[i] = i;\\n\\t\\t}\\n\\t\\treturn dummyIndices;\\n};\\nconst generateNormals = (sourceDesc, indices)=>{\\n\\t\\tconst p = sourceDesc[SEMANTIC_POSITION];\\n\\t\\tif (!p || p.components !== 3) {\\n\\t\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tlet positions;\\n\\t\\tif (p.size !== p.stride) {\\n\\t\\t\\t\\tconst srcStride = p.stride / typedArrayTypesByteSize[p.type];\\n\\t\\t\\t\\tconst src = new typedArrayTypes[p.type](p.buffer, p.offset, p.count * srcStride);\\n\\t\\t\\t\\tpositions = new typedArrayTypes[p.type](p.count * 3);\\n\\t\\t\\t\\tfor(let i = 0; i < p.count; ++i){\\n\\t\\t\\t\\t\\t\\tpositions[i * 3 + 0] = src[i * srcStride + 0];\\n\\t\\t\\t\\t\\t\\tpositions[i * 3 + 1] = src[i * srcStride + 1];\\n\\t\\t\\t\\t\\t\\tpositions[i * 3 + 2] = src[i * srcStride + 2];\\n\\t\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\t\\tpositions = new typedArrayTypes[p.type](p.buffer, p.offset, p.count * 3);\\n\\t\\t}\\n\\t\\tconst numVertices = p.count;\\n\\t\\tif (!indices) {\\n\\t\\t\\t\\tindices = generateIndices(numVertices);\\n\\t\\t}\\n\\t\\tconst normalsTemp = calculateNormals(positions, indices);\\n\\t\\tconst normals = new Float32Array(normalsTemp.length);\\n\\t\\tnormals.set(normalsTemp);\\n\\t\\tsourceDesc[SEMANTIC_NORMAL] = {\\n\\t\\t\\t\\tbuffer: normals.buffer,\\n\\t\\t\\t\\tsize: 12,\\n\\t\\t\\t\\toffset: 0,\\n\\t\\t\\t\\tstride: 12,\\n\\t\\t\\t\\tcount: numVertices,\\n\\t\\t\\t\\tcomponents: 3,\\n\\t\\t\\t\\ttype: TYPE_FLOAT32\\n\\t\\t};\\n};\\nconst cloneTexture = (texture)=>{\\n\\t\\tconst shallowCopyLevels = (texture)=>{\\n\\t\\t\\t\\tconst result = [];\\n\\t\\t\\t\\tfor(let mip = 0; mip < texture._levels.length; ++mip){\\n\\t\\t\\t\\t\\t\\tlet level = [];\\n\\t\\t\\t\\t\\t\\tif (texture.cubemap) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let face = 0; face < 6; ++face){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlevel.push(texture._levels[mip][face]);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tlevel = texture._levels[mip];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tresult.push(level);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t};\\n\\t\\tconst result = new Texture(texture.device, texture);\\n\\t\\tresult._levels = shallowCopyLevels(texture);\\n\\t\\treturn result;\\n};\\nconst cloneTextureAsset = (src)=>{\\n\\t\\tconst result = new Asset(`${src.name}_clone`, src.type, src.file, src.data, src.options);\\n\\t\\tresult.loaded = true;\\n\\t\\tresult.resource = cloneTexture(src.resource);\\n\\t\\tsrc.registry.add(result);\\n\\t\\treturn result;\\n};\\nconst createVertexBufferInternal = (device, sourceDesc)=>{\\n\\t\\tconst positionDesc = sourceDesc[SEMANTIC_POSITION];\\n\\t\\tif (!positionDesc) {\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tconst numVertices = positionDesc.count;\\n\\t\\tconst vertexDesc = [];\\n\\t\\tfor(const semantic in sourceDesc){\\n\\t\\t\\t\\tif (sourceDesc.hasOwnProperty(semantic)) {\\n\\t\\t\\t\\t\\t\\tconst element = {\\n\\t\\t\\t\\t\\t\\t\\t\\tsemantic: semantic,\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponents: sourceDesc[semantic].components,\\n\\t\\t\\t\\t\\t\\t\\t\\ttype: sourceDesc[semantic].type,\\n\\t\\t\\t\\t\\t\\t\\t\\tnormalize: !!sourceDesc[semantic].normalize\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tif (!VertexFormat.isElementValid(device, element)) {\\n\\t\\t\\t\\t\\t\\t\\t\\telement.components++;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tvertexDesc.push(element);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tvertexDesc.sort((lhs, rhs)=>{\\n\\t\\t\\t\\treturn attributeOrder[lhs.semantic] - attributeOrder[rhs.semantic];\\n\\t\\t});\\n\\t\\tlet i, j, k;\\n\\t\\tlet source, target, sourceOffset;\\n\\t\\tconst vertexFormat = new VertexFormat(device, vertexDesc);\\n\\t\\tlet isCorrectlyInterleaved = true;\\n\\t\\tfor(i = 0; i < vertexFormat.elements.length; ++i){\\n\\t\\t\\t\\ttarget = vertexFormat.elements[i];\\n\\t\\t\\t\\tsource = sourceDesc[target.name];\\n\\t\\t\\t\\tsourceOffset = source.offset - positionDesc.offset;\\n\\t\\t\\t\\tif (source.buffer !== positionDesc.buffer || source.stride !== target.stride || source.size !== target.size || sourceOffset !== target.offset) {\\n\\t\\t\\t\\t\\t\\tisCorrectlyInterleaved = false;\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst vertexBuffer = new VertexBuffer(device, vertexFormat, numVertices);\\n\\t\\tconst vertexData = vertexBuffer.lock();\\n\\t\\tconst targetArray = new Uint32Array(vertexData);\\n\\t\\tlet sourceArray;\\n\\t\\tif (isCorrectlyInterleaved) {\\n\\t\\t\\t\\tsourceArray = new Uint32Array(positionDesc.buffer, positionDesc.offset, numVertices * vertexBuffer.format.size / 4);\\n\\t\\t\\t\\ttargetArray.set(sourceArray);\\n\\t\\t} else {\\n\\t\\t\\t\\tlet targetStride, sourceStride;\\n\\t\\t\\t\\tfor(i = 0; i < vertexBuffer.format.elements.length; ++i){\\n\\t\\t\\t\\t\\t\\ttarget = vertexBuffer.format.elements[i];\\n\\t\\t\\t\\t\\t\\ttargetStride = target.stride / 4;\\n\\t\\t\\t\\t\\t\\tsource = sourceDesc[target.name];\\n\\t\\t\\t\\t\\t\\tsourceStride = source.stride / 4;\\n\\t\\t\\t\\t\\t\\tsourceArray = new Uint32Array(source.buffer, source.offset, (source.count - 1) * sourceStride + (source.size + 3) / 4);\\n\\t\\t\\t\\t\\t\\tlet src = 0;\\n\\t\\t\\t\\t\\t\\tlet dst = target.offset / 4;\\n\\t\\t\\t\\t\\t\\tconst kend = Math.floor((source.size + 3) / 4);\\n\\t\\t\\t\\t\\t\\tfor(j = 0; j < numVertices; ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(k = 0; k < kend; ++k){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttargetArray[dst + k] = sourceArray[src + k];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tsrc += sourceStride;\\n\\t\\t\\t\\t\\t\\t\\t\\tdst += targetStride;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tvertexBuffer.unlock();\\n\\t\\treturn vertexBuffer;\\n};\\nconst createVertexBuffer = (device, attributes, indices, accessors, bufferViews, vertexBufferDict)=>{\\n\\t\\tconst useAttributes = {};\\n\\t\\tconst attribIds = [];\\n\\t\\tfor(const attrib in attributes){\\n\\t\\t\\t\\tif (attributes.hasOwnProperty(attrib) && gltfToEngineSemanticMap.hasOwnProperty(attrib)) {\\n\\t\\t\\t\\t\\t\\tuseAttributes[attrib] = attributes[attrib];\\n\\t\\t\\t\\t\\t\\tattribIds.push(`${attrib}:${attributes[attrib]}`);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tattribIds.sort();\\n\\t\\tconst vbKey = attribIds.join();\\n\\t\\tlet vb = vertexBufferDict[vbKey];\\n\\t\\tif (!vb) {\\n\\t\\t\\t\\tconst sourceDesc = {};\\n\\t\\t\\t\\tfor(const attrib in useAttributes){\\n\\t\\t\\t\\t\\t\\tconst accessor = accessors[attributes[attrib]];\\n\\t\\t\\t\\t\\t\\tconst accessorData = getAccessorData(accessor, bufferViews);\\n\\t\\t\\t\\t\\t\\tconst bufferView = bufferViews[accessor.bufferView];\\n\\t\\t\\t\\t\\t\\tconst semantic = gltfToEngineSemanticMap[attrib];\\n\\t\\t\\t\\t\\t\\tconst size = getNumComponents(accessor.type) * getComponentSizeInBytes(accessor.componentType);\\n\\t\\t\\t\\t\\t\\tconst stride = bufferView && bufferView.hasOwnProperty('byteStride') ? bufferView.byteStride : size;\\n\\t\\t\\t\\t\\t\\tsourceDesc[semantic] = {\\n\\t\\t\\t\\t\\t\\t\\t\\tbuffer: accessorData.buffer,\\n\\t\\t\\t\\t\\t\\t\\t\\tsize: size,\\n\\t\\t\\t\\t\\t\\t\\t\\toffset: accessorData.byteOffset,\\n\\t\\t\\t\\t\\t\\t\\t\\tstride: stride,\\n\\t\\t\\t\\t\\t\\t\\t\\tcount: accessor.count,\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponents: getNumComponents(accessor.type),\\n\\t\\t\\t\\t\\t\\t\\t\\ttype: getComponentType(accessor.componentType),\\n\\t\\t\\t\\t\\t\\t\\t\\tnormalize: accessor.normalized\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!sourceDesc.hasOwnProperty(SEMANTIC_NORMAL)) {\\n\\t\\t\\t\\t\\t\\tgenerateNormals(sourceDesc, indices);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tvb = createVertexBufferInternal(device, sourceDesc);\\n\\t\\t\\t\\tvertexBufferDict[vbKey] = vb;\\n\\t\\t}\\n\\t\\treturn vb;\\n};\\nconst createSkin = (device, gltfSkin, accessors, bufferViews, nodes, glbSkins)=>{\\n\\t\\tlet i, j, bindMatrix;\\n\\t\\tconst joints = gltfSkin.joints;\\n\\t\\tconst numJoints = joints.length;\\n\\t\\tconst ibp = [];\\n\\t\\tif (gltfSkin.hasOwnProperty('inverseBindMatrices')) {\\n\\t\\t\\t\\tconst inverseBindMatrices = gltfSkin.inverseBindMatrices;\\n\\t\\t\\t\\tconst ibmData = getAccessorData(accessors[inverseBindMatrices], bufferViews, true);\\n\\t\\t\\t\\tconst ibmValues = [];\\n\\t\\t\\t\\tfor(i = 0; i < numJoints; i++){\\n\\t\\t\\t\\t\\t\\tfor(j = 0; j < 16; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\tibmValues[j] = ibmData[i * 16 + j];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tbindMatrix = new Mat4();\\n\\t\\t\\t\\t\\t\\tbindMatrix.set(ibmValues);\\n\\t\\t\\t\\t\\t\\tibp.push(bindMatrix);\\n\\t\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\t\\tfor(i = 0; i < numJoints; i++){\\n\\t\\t\\t\\t\\t\\tbindMatrix = new Mat4();\\n\\t\\t\\t\\t\\t\\tibp.push(bindMatrix);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst boneNames = [];\\n\\t\\tfor(i = 0; i < numJoints; i++){\\n\\t\\t\\t\\tboneNames[i] = nodes[joints[i]].name;\\n\\t\\t}\\n\\t\\tconst key = boneNames.join('#');\\n\\t\\tlet skin = glbSkins.get(key);\\n\\t\\tif (!skin) {\\n\\t\\t\\t\\tskin = new Skin(device, ibp, boneNames);\\n\\t\\t\\t\\tglbSkins.set(key, skin);\\n\\t\\t}\\n\\t\\treturn skin;\\n};\\nconst createDracoMesh = (device, primitive, accessors, bufferViews, meshVariants, meshDefaultMaterials, promises)=>{\\n\\t\\tconst result = new Mesh(device);\\n\\t\\tresult.aabb = getAccessorBoundingBox(accessors[primitive.attributes.POSITION]);\\n\\t\\tpromises.push(new Promise((resolve, reject)=>{\\n\\t\\t\\t\\tconst dracoExt = primitive.extensions.KHR_draco_mesh_compression;\\n\\t\\t\\t\\tdracoDecode(bufferViews[dracoExt.bufferView].slice().buffer, (err, decompressedData)=>{\\n\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconsole.log(err);\\n\\t\\t\\t\\t\\t\\t\\t\\treject(err);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst idToSemantic = {};\\n\\t\\t\\t\\t\\t\\t\\t\\tfor (const [name, id] of Object.entries(dracoExt.attributes)){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tidToSemantic[id] = gltfToEngineSemanticMap[name];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tidToSemantic[-1] = SEMANTIC_NORMAL;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst vertexDesc = [];\\n\\t\\t\\t\\t\\t\\t\\t\\tfor (const attr of decompressedData.attributes){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst semantic = idToSemantic[attr.id];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (semantic !== undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet normalize = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (attr.id !== -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor (const [name, id] of Object.entries(dracoExt.attributes)){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (id === attr.id && primitive.attributes[name] !== undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst accessor = accessors[primitive.attributes[name]];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvertexDesc.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsemantic: semantic,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcomponents: attr.numComponents,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype: attr.dataType,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnormalize: normalize,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toffset: attr.offset,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstride: decompressedData.stride\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\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 vertexFormat = new VertexFormat(device, vertexDesc);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst numVertices = decompressedData.vertices.byteLength / decompressedData.stride;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst indexFormat = numVertices <= 65535 ? INDEXFORMAT_UINT16 : INDEXFORMAT_UINT32;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst numIndices = decompressedData.indices.byteLength / (numVertices <= 65535 ? 2 : 4);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst vertexBuffer = new VertexBuffer(device, vertexFormat, numVertices, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata: decompressedData.vertices\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tconst indexBuffer = new IndexBuffer(device, indexFormat, numIndices, BUFFER_STATIC, decompressedData.indices);\\n\\t\\t\\t\\t\\t\\t\\t\\tresult.vertexBuffer = vertexBuffer;\\n\\t\\t\\t\\t\\t\\t\\t\\tresult.indexBuffer[0] = indexBuffer;\\n\\t\\t\\t\\t\\t\\t\\t\\tresult.primitive[0].type = getPrimitiveType(primitive);\\n\\t\\t\\t\\t\\t\\t\\t\\tresult.primitive[0].base = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tresult.primitive[0].count = indexBuffer ? numIndices : numVertices;\\n\\t\\t\\t\\t\\t\\t\\t\\tresult.primitive[0].indexed = !!indexBuffer;\\n\\t\\t\\t\\t\\t\\t\\t\\tresolve();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}));\\n\\t\\tif (primitive?.extensions?.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\\t\\tmapping.variants.forEach((variant)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\ttempMapping[variant] = mapping.material;\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tmeshVariants[result.id] = tempMapping;\\n\\t\\t}\\n\\t\\tmeshDefaultMaterials[result.id] = primitive.material;\\n\\t\\treturn result;\\n};\\nconst createMesh = (device, gltfMesh, accessors, bufferViews, vertexBufferDict, meshVariants, meshDefaultMaterials, assetOptions, promises)=>{\\n\\t\\tconst meshes = [];\\n\\t\\tgltfMesh.primitives.forEach((primitive)=>{\\n\\t\\t\\t\\tif (primitive.extensions?.KHR_draco_mesh_compression) {\\n\\t\\t\\t\\t\\t\\tmeshes.push(createDracoMesh(device, primitive, accessors, bufferViews, meshVariants, meshDefaultMaterials, promises));\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tlet indices = primitive.hasOwnProperty('indices') ? getAccessorData(accessors[primitive.indices], bufferViews, true) : null;\\n\\t\\t\\t\\t\\t\\tconst vertexBuffer = createVertexBuffer(device, primitive.attributes, indices, accessors, bufferViews, vertexBufferDict);\\n\\t\\t\\t\\t\\t\\tconst primitiveType = getPrimitiveType(primitive);\\n\\t\\t\\t\\t\\t\\tconst mesh = new Mesh(device);\\n\\t\\t\\t\\t\\t\\tmesh.vertexBuffer = vertexBuffer;\\n\\t\\t\\t\\t\\t\\tmesh.primitive[0].type = primitiveType;\\n\\t\\t\\t\\t\\t\\tmesh.primitive[0].base = 0;\\n\\t\\t\\t\\t\\t\\tmesh.primitive[0].indexed = indices !== null;\\n\\t\\t\\t\\t\\t\\tif (indices !== null) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlet indexFormat;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (indices instanceof Uint8Array) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindexFormat = INDEXFORMAT_UINT8;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else if (indices instanceof Uint16Array) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindexFormat = INDEXFORMAT_UINT16;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindexFormat = INDEXFORMAT_UINT32;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (indexFormat === INDEXFORMAT_UINT8 && device.isWebGPU) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindexFormat = INDEXFORMAT_UINT16;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tindices = new Uint16Array(indices);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst indexBuffer = new IndexBuffer(device, indexFormat, indices.length, BUFFER_STATIC, indices);\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh.indexBuffer[0] = indexBuffer;\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh.primitive[0].count = indices.length;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh.primitive[0].count = vertexBuffer.numVertices;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (primitive.hasOwnProperty('extensions') && primitive.extensions.hasOwnProperty('KHR_materials_variants')) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst variants = primitive.extensions.KHR_materials_variants;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst tempMapping = {};\\n\\t\\t\\t\\t\\t\\t\\t\\tvariants.mappings.forEach((mapping)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmapping.variants.forEach((variant)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttempMapping[variant] = mapping.material;\\n\\t\\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\\tmeshVariants[mesh.id] = tempMapping;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tmeshDefaultMaterials[mesh.id] = primitive.material;\\n\\t\\t\\t\\t\\t\\tlet accessor = accessors[primitive.attributes.POSITION];\\n\\t\\t\\t\\t\\t\\tmesh.aabb = getAccessorBoundingBox(accessor);\\n\\t\\t\\t\\t\\t\\tif (primitive.hasOwnProperty('targets')) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst targets = [];\\n\\t\\t\\t\\t\\t\\t\\t\\tprimitive.targets.forEach((target, index)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst options = {};\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (target.hasOwnProperty('POSITION')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taccessor = accessors[target.POSITION];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions.deltaPositions = getAccessorDataFloat32(accessor, bufferViews);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions.aabb = getAccessorBoundingBox(accessor);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (target.hasOwnProperty('NORMAL')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taccessor = accessors[target.NORMAL];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions.deltaNormals = getAccessorDataFloat32(accessor, bufferViews);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (gltfMesh.hasOwnProperty('extras') && gltfMesh.extras.hasOwnProperty('targetNames')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions.name = gltfMesh.extras.targetNames[index];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions.name = index.toString(10);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (gltfMesh.hasOwnProperty('weights')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions.defaultWeight = gltfMesh.weights[index];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toptions.preserveData = assetOptions.morphPreserveData;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttargets.push(new MorphTarget(options));\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh.morph = new Morph(targets, device, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpreferHighPrecision: assetOptions.morphPreferHighPrecision\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tmeshes.push(mesh);\\n\\t\\t\\t\\t}\\n\\t\\t});\\n\\t\\treturn meshes;\\n};\\nconst extractTextureTransform = (source, material, maps)=>{\\n\\t\\tlet map;\\n\\t\\tconst texCoord = source.texCoord;\\n\\t\\tif (texCoord) {\\n\\t\\t\\t\\tfor(map = 0; map < maps.length; ++map){\\n\\t\\t\\t\\t\\t\\tmaterial[`${maps[map]}MapUv`] = texCoord;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst zeros = [\\n\\t\\t\\t\\t0,\\n\\t\\t\\t\\t0\\n\\t\\t];\\n\\t\\tconst ones = [\\n\\t\\t\\t\\t1,\\n\\t\\t\\t\\t1\\n\\t\\t];\\n\\t\\tconst textureTransform = source.extensions?.KHR_texture_transform;\\n\\t\\tif (textureTransform) {\\n\\t\\t\\t\\tconst offset = textureTransform.offset || zeros;\\n\\t\\t\\t\\tconst scale = textureTransform.scale || ones;\\n\\t\\t\\t\\tconst rotation = textureTransform.rotation ? -textureTransform.rotation * math.RAD_TO_DEG : 0;\\n\\t\\t\\t\\tconst tilingVec = new Vec2(scale[0], scale[1]);\\n\\t\\t\\t\\tconst offsetVec = new Vec2(offset[0], 1.0 - scale[1] - offset[1]);\\n\\t\\t\\t\\tfor(map = 0; map < maps.length; ++map){\\n\\t\\t\\t\\t\\t\\tmaterial[`${maps[map]}MapTiling`] = tilingVec;\\n\\t\\t\\t\\t\\t\\tmaterial[`${maps[map]}MapOffset`] = offsetVec;\\n\\t\\t\\t\\t\\t\\tmaterial[`${maps[map]}MapRotation`] = rotation;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n};\\nconst extensionPbrSpecGlossiness = (data, material, textures)=>{\\n\\t\\tlet texture;\\n\\t\\tif (data.hasOwnProperty('diffuseFactor')) {\\n\\t\\t\\t\\tconst [r, g, b, a] = data.diffuseFactor;\\n\\t\\t\\t\\tmaterial.diffuse.set(r, g, b).gamma();\\n\\t\\t\\t\\tmaterial.opacity = a;\\n\\t\\t} else {\\n\\t\\t\\t\\tmaterial.diffuse.set(1, 1, 1);\\n\\t\\t\\t\\tmaterial.opacity = 1;\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('diffuseTexture')) {\\n\\t\\t\\t\\tconst diffuseTexture = data.diffuseTexture;\\n\\t\\t\\t\\ttexture = textures[diffuseTexture.index];\\n\\t\\t\\t\\tmaterial.diffuseMap = texture;\\n\\t\\t\\t\\tmaterial.diffuseMapChannel = 'rgb';\\n\\t\\t\\t\\tmaterial.opacityMap = texture;\\n\\t\\t\\t\\tmaterial.opacityMapChannel = 'a';\\n\\t\\t\\t\\textractTextureTransform(diffuseTexture, material, [\\n\\t\\t\\t\\t\\t\\t'diffuse',\\n\\t\\t\\t\\t\\t\\t'opacity'\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tmaterial.useMetalness = false;\\n\\t\\tif (data.hasOwnProperty('specularFactor')) {\\n\\t\\t\\t\\tconst [r, g, b] = data.specularFactor;\\n\\t\\t\\t\\tmaterial.specular.set(r, g, b).gamma();\\n\\t\\t} else {\\n\\t\\t\\t\\tmaterial.specular.set(1, 1, 1);\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('glossinessFactor')) {\\n\\t\\t\\t\\tmaterial.gloss = data.glossinessFactor;\\n\\t\\t} else {\\n\\t\\t\\t\\tmaterial.gloss = 1.0;\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('specularGlossinessTexture')) {\\n\\t\\t\\t\\tconst specularGlossinessTexture = data.specularGlossinessTexture;\\n\\t\\t\\t\\tmaterial.specularMap = material.glossMap = textures[specularGlossinessTexture.index];\\n\\t\\t\\t\\tmaterial.specularMapChannel = 'rgb';\\n\\t\\t\\t\\tmaterial.glossMapChannel = 'a';\\n\\t\\t\\t\\textractTextureTransform(specularGlossinessTexture, material, [\\n\\t\\t\\t\\t\\t\\t'gloss',\\n\\t\\t\\t\\t\\t\\t'metalness'\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n};\\nconst extensionClearCoat = (data, material, textures)=>{\\n\\t\\tif (data.hasOwnProperty('clearcoatFactor')) {\\n\\t\\t\\t\\tmaterial.clearCoat = data.clearcoatFactor * 0.25;\\n\\t\\t} else {\\n\\t\\t\\t\\tmaterial.clearCoat = 0;\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('clearcoatTexture')) {\\n\\t\\t\\t\\tconst clearcoatTexture = data.clearcoatTexture;\\n\\t\\t\\t\\tmaterial.clearCoatMap = textures[clearcoatTexture.index];\\n\\t\\t\\t\\tmaterial.clearCoatMapChannel = 'r';\\n\\t\\t\\t\\textractTextureTransform(clearcoatTexture, material, [\\n\\t\\t\\t\\t\\t\\t'clearCoat'\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('clearcoatRoughnessFactor')) {\\n\\t\\t\\t\\tmaterial.clearCoatGloss = data.clearcoatRoughnessFactor;\\n\\t\\t} else {\\n\\t\\t\\t\\tmaterial.clearCoatGloss = 0;\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('clearcoatRoughnessTexture')) {\\n\\t\\t\\t\\tconst clearcoatRoughnessTexture = data.clearcoatRoughnessTexture;\\n\\t\\t\\t\\tmaterial.clearCoatGlossMap = textures[clearcoatRoughnessTexture.index];\\n\\t\\t\\t\\tmaterial.clearCoatGlossMapChannel = 'g';\\n\\t\\t\\t\\textractTextureTransform(clearcoatRoughnessTexture, material, [\\n\\t\\t\\t\\t\\t\\t'clearCoatGloss'\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('clearcoatNormalTexture')) {\\n\\t\\t\\t\\tconst clearcoatNormalTexture = data.clearcoatNormalTexture;\\n\\t\\t\\t\\tmaterial.clearCoatNormalMap = textures[clearcoatNormalTexture.index];\\n\\t\\t\\t\\textractTextureTransform(clearcoatNormalTexture, material, [\\n\\t\\t\\t\\t\\t\\t'clearCoatNormal'\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tif (clearcoatNormalTexture.hasOwnProperty('scale')) {\\n\\t\\t\\t\\t\\t\\tmaterial.clearCoatBumpiness = clearcoatNormalTexture.scale;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tmaterial.clearCoatBumpiness = 1;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tmaterial.clearCoatGlossInvert = true;\\n};\\nconst extensionUnlit = (data, material, textures)=>{\\n\\t\\tmaterial.useLighting = false;\\n\\t\\tmaterial.emissive.copy(material.diffuse);\\n\\t\\tmaterial.emissiveMap = material.diffuseMap;\\n\\t\\tmaterial.emissiveMapUv = material.diffuseMapUv;\\n\\t\\tmaterial.emissiveMapTiling.copy(material.diffuseMapTiling);\\n\\t\\tmaterial.emissiveMapOffset.copy(material.diffuseMapOffset);\\n\\t\\tmaterial.emissiveMapRotation = material.diffuseMapRotation;\\n\\t\\tmaterial.emissiveMapChannel = material.diffuseMapChannel;\\n\\t\\tmaterial.emissiveVertexColor = material.diffuseVertexColor;\\n\\t\\tmaterial.emissiveVertexColorChannel = material.diffuseVertexColorChannel;\\n\\t\\tmaterial.useLighting = false;\\n\\t\\tmaterial.useSkybox = false;\\n\\t\\tmaterial.diffuse.set(1, 1, 1);\\n\\t\\tmaterial.diffuseMap = null;\\n\\t\\tmaterial.diffuseVertexColor = false;\\n};\\nconst extensionSpecular = (data, material, textures)=>{\\n\\t\\tmaterial.useMetalnessSpecularColor = true;\\n\\t\\tif (data.hasOwnProperty('specularColorTexture')) {\\n\\t\\t\\t\\tmaterial.specularMap = textures[data.specularColorTexture.index];\\n\\t\\t\\t\\tmaterial.specularMapChannel = 'rgb';\\n\\t\\t\\t\\textractTextureTransform(data.specularColorTexture, material, [\\n\\t\\t\\t\\t\\t\\t'specular'\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('specularColorFactor')) {\\n\\t\\t\\t\\tconst [r, g, b] = data.specularColorFactor;\\n\\t\\t\\t\\tmaterial.specular.set(r, g, b).gamma();\\n\\t\\t} else {\\n\\t\\t\\t\\tmaterial.specular.set(1, 1, 1);\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('specularFactor')) {\\n\\t\\t\\t\\tmaterial.specularityFactor = data.specularFactor;\\n\\t\\t} else {\\n\\t\\t\\t\\tmaterial.specularityFactor = 1;\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('specularTexture')) {\\n\\t\\t\\t\\tmaterial.specularityFactorMapChannel = 'a';\\n\\t\\t\\t\\tmaterial.specularityFactorMap = textures[data.specularTexture.index];\\n\\t\\t\\t\\textractTextureTransform(data.specularTexture, material, [\\n\\t\\t\\t\\t\\t\\t'specularityFactor'\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n};\\nconst extensionIor = (data, material, textures)=>{\\n\\t\\tif (data.hasOwnProperty('ior')) {\\n\\t\\t\\t\\tmaterial.refractionIndex = 1.0 / data.ior;\\n\\t\\t}\\n};\\nconst extensionDispersion = (data, material, textures)=>{\\n\\t\\tif (data.hasOwnProperty('dispersion')) {\\n\\t\\t\\t\\tmaterial.dispersion = data.dispersion;\\n\\t\\t}\\n};\\nconst extensionTransmission = (data, material, textures)=>{\\n\\t\\tmaterial.blendType = BLEND_NORMAL;\\n\\t\\tmaterial.useDynamicRefraction = true;\\n\\t\\tif (data.hasOwnProperty('transmissionFactor')) {\\n\\t\\t\\t\\tmaterial.refraction = data.transmissionFactor;\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('transmissionTexture')) {\\n\\t\\t\\t\\tmaterial.refractionMapChannel = 'r';\\n\\t\\t\\t\\tmaterial.refractionMap = textures[data.transmissionTexture.index];\\n\\t\\t\\t\\textractTextureTransform(data.transmissionTexture, material, [\\n\\t\\t\\t\\t\\t\\t'refraction'\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n};\\nconst extensionSheen = (data, material, textures)=>{\\n\\t\\tmaterial.useSheen = true;\\n\\t\\tif (data.hasOwnProperty('sheenColorFactor')) {\\n\\t\\t\\t\\tconst [r, g, b] = data.sheenColorFactor;\\n\\t\\t\\t\\tmaterial.sheen.set(r, g, b).gamma();\\n\\t\\t} else {\\n\\t\\t\\t\\tmaterial.sheen.set(1, 1, 1);\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('sheenColorTexture')) {\\n\\t\\t\\t\\tmaterial.sheenMap = textures[data.sheenColorTexture.index];\\n\\t\\t\\t\\textractTextureTransform(data.sheenColorTexture, material, [\\n\\t\\t\\t\\t\\t\\t'sheen'\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tmaterial.sheenGloss = data.hasOwnProperty('sheenRoughnessFactor') ? data.sheenRoughnessFactor : 0.0;\\n\\t\\tif (data.hasOwnProperty('sheenRoughnessTexture')) {\\n\\t\\t\\t\\tmaterial.sheenGlossMap = textures[data.sheenRoughnessTexture.index];\\n\\t\\t\\t\\tmaterial.sheenGlossMapChannel = 'a';\\n\\t\\t\\t\\textractTextureTransform(data.sheenRoughnessTexture, material, [\\n\\t\\t\\t\\t\\t\\t'sheenGloss'\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tmaterial.sheenGlossInvert = true;\\n};\\nconst extensionVolume = (data, material, textures)=>{\\n\\t\\tmaterial.blendType = BLEND_NORMAL;\\n\\t\\tmaterial.useDynamicRefraction = true;\\n\\t\\tif (data.hasOwnProperty('thicknessFactor')) {\\n\\t\\t\\t\\tmaterial.thickness = data.thicknessFactor;\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('thicknessTexture')) {\\n\\t\\t\\t\\tmaterial.thicknessMap = textures[data.thicknessTexture.index];\\n\\t\\t\\t\\tmaterial.thicknessMapChannel = 'g';\\n\\t\\t\\t\\textractTextureTransform(data.thicknessTexture, material, [\\n\\t\\t\\t\\t\\t\\t'thickness'\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('attenuationDistance')) {\\n\\t\\t\\t\\tmaterial.attenuationDistance = data.attenuationDistance;\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('attenuationColor')) {\\n\\t\\t\\t\\tconst [r, g, b] = data.attenuationColor;\\n\\t\\t\\t\\tmaterial.attenuation.set(r, g, b).gamma();\\n\\t\\t}\\n};\\nconst extensionEmissiveStrength = (data, material, textures)=>{\\n\\t\\tif (data.hasOwnProperty('emissiveStrength')) {\\n\\t\\t\\t\\tmaterial.emissiveIntensity = data.emissiveStrength;\\n\\t\\t}\\n};\\nconst extensionIridescence = (data, material, textures)=>{\\n\\t\\tmaterial.useIridescence = true;\\n\\t\\tif (data.hasOwnProperty('iridescenceFactor')) {\\n\\t\\t\\t\\tmaterial.iridescence = data.iridescenceFactor;\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('iridescenceTexture')) {\\n\\t\\t\\t\\tmaterial.iridescenceMapChannel = 'r';\\n\\t\\t\\t\\tmaterial.iridescenceMap = textures[data.iridescenceTexture.index];\\n\\t\\t\\t\\textractTextureTransform(data.iridescenceTexture, material, [\\n\\t\\t\\t\\t\\t\\t'iridescence'\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('iridescenceIor')) {\\n\\t\\t\\t\\tmaterial.iridescenceRefractionIndex = data.iridescenceIor;\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('iridescenceThicknessMinimum')) {\\n\\t\\t\\t\\tmaterial.iridescenceThicknessMin = data.iridescenceThicknessMinimum;\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('iridescenceThicknessMaximum')) {\\n\\t\\t\\t\\tmaterial.iridescenceThicknessMax = data.iridescenceThicknessMaximum;\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('iridescenceThicknessTexture')) {\\n\\t\\t\\t\\tmaterial.iridescenceThicknessMapChannel = 'g';\\n\\t\\t\\t\\tmaterial.iridescenceThicknessMap = textures[data.iridescenceThicknessTexture.index];\\n\\t\\t\\t\\textractTextureTransform(data.iridescenceThicknessTexture, material, [\\n\\t\\t\\t\\t\\t\\t'iridescenceThickness'\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n};\\nconst extensionAnisotropy = (data, material, textures)=>{\\n\\t\\tmaterial.enableGGXSpecular = true;\\n\\t\\tif (data.hasOwnProperty('anisotropyStrength')) {\\n\\t\\t\\t\\tmaterial.anisotropyIntensity = data.anisotropyStrength;\\n\\t\\t} else {\\n\\t\\t\\t\\tmaterial.anisotropyIntensity = 0;\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('anisotropyTexture')) {\\n\\t\\t\\t\\tconst anisotropyTexture = data.anisotropyTexture;\\n\\t\\t\\t\\tmaterial.anisotropyMap = textures[anisotropyTexture.index];\\n\\t\\t\\t\\textractTextureTransform(anisotropyTexture, material, [\\n\\t\\t\\t\\t\\t\\t'anisotropy'\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tif (data.hasOwnProperty('anisotropyRotation')) {\\n\\t\\t\\t\\tmaterial.anisotropyRotation = data.anisotropyRotation * math.RAD_TO_DEG;\\n\\t\\t} else {\\n\\t\\t\\t\\tmaterial.anisotropyRotation = 0;\\n\\t\\t}\\n};\\nconst createMaterial = (gltfMaterial, textures)=>{\\n\\t\\tconst material = new StandardMaterial();\\n\\t\\tif (gltfMaterial.hasOwnProperty('name')) {\\n\\t\\t\\t\\tmaterial.name = gltfMaterial.name;\\n\\t\\t}\\n\\t\\tmaterial.occludeSpecular = SPECOCC_AO;\\n\\t\\tmaterial.diffuseVertexColor = true;\\n\\t\\tmaterial.specularTint = true;\\n\\t\\tmaterial.specularVertexColor = true;\\n\\t\\tmaterial.specular.set(1, 1, 1);\\n\\t\\tmaterial.gloss = 1;\\n\\t\\tmaterial.glossInvert = true;\\n\\t\\tmaterial.useMetalness = true;\\n\\t\\tlet texture;\\n\\t\\tif (gltfMaterial.hasOwnProperty('pbrMetallicRoughness')) {\\n\\t\\t\\t\\tconst pbrData = gltfMaterial.pbrMetallicRoughness;\\n\\t\\t\\t\\tif (pbrData.hasOwnProperty('baseColorFactor')) {\\n\\t\\t\\t\\t\\t\\tconst [r, g, b, a] = pbrData.baseColorFactor;\\n\\t\\t\\t\\t\\t\\tmaterial.diffuse.set(r, g, b).gamma();\\n\\t\\t\\t\\t\\t\\tmaterial.opacity = a;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (pbrData.hasOwnProperty('baseColorTexture')) {\\n\\t\\t\\t\\t\\t\\tconst baseColorTexture = pbrData.baseColorTexture;\\n\\t\\t\\t\\t\\t\\ttexture = textures[baseColorTexture.index];\\n\\t\\t\\t\\t\\t\\tmaterial.diffuseMap = texture;\\n\\t\\t\\t\\t\\t\\tmaterial.diffuseMapChannel = 'rgb';\\n\\t\\t\\t\\t\\t\\tmaterial.opacityMap = texture;\\n\\t\\t\\t\\t\\t\\tmaterial.opacityMapChannel = 'a';\\n\\t\\t\\t\\t\\t\\textractTextureTransform(baseColorTexture, material, [\\n\\t\\t\\t\\t\\t\\t\\t\\t'diffuse',\\n\\t\\t\\t\\t\\t\\t\\t\\t'opacity'\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (pbrData.hasOwnProperty('metallicFactor')) {\\n\\t\\t\\t\\t\\t\\tmaterial.metalness = pbrData.metallicFactor;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (pbrData.hasOwnProperty('roughnessFactor')) {\\n\\t\\t\\t\\t\\t\\tmaterial.gloss = pbrData.roughnessFactor;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (pbrData.hasOwnProperty('metallicRoughnessTexture')) {\\n\\t\\t\\t\\t\\t\\tconst metallicRoughnessTexture = pbrData.metallicRoughnessTexture;\\n\\t\\t\\t\\t\\t\\tmaterial.metalnessMap = material.glossMap = textures[metallicRoughnessTexture.index];\\n\\t\\t\\t\\t\\t\\tmaterial.metalnessMapChannel = 'b';\\n\\t\\t\\t\\t\\t\\tmaterial.glossMapChannel = 'g';\\n\\t\\t\\t\\t\\t\\textractTextureTransform(metallicRoughnessTexture, material, [\\n\\t\\t\\t\\t\\t\\t\\t\\t'gloss',\\n\\t\\t\\t\\t\\t\\t\\t\\t'metalness'\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (gltfMaterial.hasOwnProperty('normalTexture')) {\\n\\t\\t\\t\\tconst normalTexture = gltfMaterial.normalTexture;\\n\\t\\t\\t\\tmaterial.normalMap = textures[normalTexture.index];\\n\\t\\t\\t\\textractTextureTransform(normalTexture, material, [\\n\\t\\t\\t\\t\\t\\t'normal'\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tif (normalTexture.hasOwnProperty('scale')) {\\n\\t\\t\\t\\t\\t\\tmaterial.bumpiness = normalTexture.scale;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (gltfMaterial.hasOwnProperty('occlusionTexture')) {\\n\\t\\t\\t\\tconst occlusionTexture = gltfMaterial.occlusionTexture;\\n\\t\\t\\t\\tmaterial.aoMap = textures[occlusionTexture.index];\\n\\t\\t\\t\\tmaterial.aoMapChannel = 'r';\\n\\t\\t\\t\\textractTextureTransform(occlusionTexture, material, [\\n\\t\\t\\t\\t\\t\\t'ao'\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tif (gltfMaterial.hasOwnProperty('emissiveFactor')) {\\n\\t\\t\\t\\tconst [r, g, b] = gltfMaterial.emissiveFactor;\\n\\t\\t\\t\\tmaterial.emissive.set(r, g, b).gamma();\\n\\t\\t}\\n\\t\\tif (gltfMaterial.hasOwnProperty('emissiveTexture')) {\\n\\t\\t\\t\\tconst emissiveTexture = gltfMaterial.emissiveTexture;\\n\\t\\t\\t\\tmaterial.emissiveMap = textures[emissiveTexture.index];\\n\\t\\t\\t\\textractTextureTransform(emissiveTexture, material, [\\n\\t\\t\\t\\t\\t\\t'emissive'\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tif (gltfMaterial.hasOwnProperty('alphaMode')) {\\n\\t\\t\\t\\tswitch(gltfMaterial.alphaMode){\\n\\t\\t\\t\\t\\t\\tcase 'MASK':\\n\\t\\t\\t\\t\\t\\t\\t\\tmaterial.blendType = BLEND_NONE;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (gltfMaterial.hasOwnProperty('alphaCutoff')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmaterial.alphaTest = gltfMaterial.alphaCutoff;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmaterial.alphaTest = 0.5;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 'BLEND':\\n\\t\\t\\t\\t\\t\\t\\t\\tmaterial.blendType = BLEND_NORMAL;\\n\\t\\t\\t\\t\\t\\t\\t\\tmaterial.depthWrite = false;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\tcase 'OPAQUE':\\n\\t\\t\\t\\t\\t\\t\\t\\tmaterial.blendType = BLEND_NONE;\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\t\\tmaterial.blendType = BLEND_NONE;\\n\\t\\t}\\n\\t\\tif (gltfMaterial.hasOwnProperty('doubleSided')) {\\n\\t\\t\\t\\tmaterial.twoSidedLighting = gltfMaterial.doubleSided;\\n\\t\\t\\t\\tmaterial.cull = gltfMaterial.doubleSided ? CULLFACE_NONE : CULLFACE_BACK;\\n\\t\\t} else {\\n\\t\\t\\t\\tmaterial.twoSidedLighting = false;\\n\\t\\t\\t\\tmaterial.cull = CULLFACE_BACK;\\n\\t\\t}\\n\\t\\tconst extensions = {\\n\\t\\t\\t\\t'KHR_materials_clearcoat': extensionClearCoat,\\n\\t\\t\\t\\t'KHR_materials_emissive_strength': extensionEmissiveStrength,\\n\\t\\t\\t\\t'KHR_materials_ior': extensionIor,\\n\\t\\t\\t\\t'KHR_materials_dispersion': extensionDispersion,\\n\\t\\t\\t\\t'KHR_materials_iridescence': extensionIridescence,\\n\\t\\t\\t\\t'KHR_materials_pbrSpecularGlossiness': extensionPbrSpecGlossiness,\\n\\t\\t\\t\\t'KHR_materials_sheen': extensionSheen,\\n\\t\\t\\t\\t'KHR_materials_specular': extensionSpecular,\\n\\t\\t\\t\\t'KHR_materials_transmission': extensionTransmission,\\n\\t\\t\\t\\t'KHR_materials_unlit': extensionUnlit,\\n\\t\\t\\t\\t'KHR_materials_volume': extensionVolume,\\n\\t\\t\\t\\t'KHR_materials_anisotropy': extensionAnisotropy\\n\\t\\t};\\n\\t\\tif (gltfMaterial.hasOwnProperty('extensions')) {\\n\\t\\t\\t\\tfor(const key in gltfMaterial.extensions){\\n\\t\\t\\t\\t\\t\\tconst extensionFunc = extensions[key];\\n\\t\\t\\t\\t\\t\\tif (extensionFunc !== undefined) {\\n\\t\\t\\t\\t\\t\\t\\t\\textensionFunc(gltfMaterial.extensions[key], material, textures);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tmaterial.update();\\n\\t\\treturn material;\\n};\\nconst createAnimation = (gltfAnimation, animationIndex, gltfAccessors, bufferViews, nodes, meshes, gltfNodes)=>{\\n\\t\\tconst createAnimData = (gltfAccessor)=>{\\n\\t\\t\\t\\treturn new AnimData(getNumComponents(gltfAccessor.type), getAccessorDataFloat32(gltfAccessor, bufferViews));\\n\\t\\t};\\n\\t\\tconst interpMap = {\\n\\t\\t\\t\\t'STEP': INTERPOLATION_STEP,\\n\\t\\t\\t\\t'LINEAR': INTERPOLATION_LINEAR,\\n\\t\\t\\t\\t'CUBICSPLINE': INTERPOLATION_CUBIC\\n\\t\\t};\\n\\t\\tconst inputMap = {};\\n\\t\\tconst outputMap = {};\\n\\t\\tconst curveMap = {};\\n\\t\\tlet outputCounter = 1;\\n\\t\\tlet i;\\n\\t\\tfor(i = 0; i < gltfAnimation.samplers.length; ++i){\\n\\t\\t\\t\\tconst sampler = gltfAnimation.samplers[i];\\n\\t\\t\\t\\tif (!inputMap.hasOwnProperty(sampler.input)) {\\n\\t\\t\\t\\t\\t\\tinputMap[sampler.input] = createAnimData(gltfAccessors[sampler.input]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!outputMap.hasOwnProperty(sampler.output)) {\\n\\t\\t\\t\\t\\t\\toutputMap[sampler.output] = createAnimData(gltfAccessors[sampler.output]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst interpolation = sampler.hasOwnProperty('interpolation') && interpMap.hasOwnProperty(sampler.interpolation) ? interpMap[sampler.interpolation] : INTERPOLATION_LINEAR;\\n\\t\\t\\t\\tconst curve = {\\n\\t\\t\\t\\t\\t\\tpaths: [],\\n\\t\\t\\t\\t\\t\\tinput: sampler.input,\\n\\t\\t\\t\\t\\t\\toutput: sampler.output,\\n\\t\\t\\t\\t\\t\\tinterpolation: interpolation\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tcurveMap[i] = curve;\\n\\t\\t}\\n\\t\\tconst quatArrays = [];\\n\\t\\tconst transformSchema = {\\n\\t\\t\\t\\t'translation': 'localPosition',\\n\\t\\t\\t\\t'rotation': 'localRotation',\\n\\t\\t\\t\\t'scale': 'localScale'\\n\\t\\t};\\n\\t\\tconst constructNodePath = (node)=>{\\n\\t\\t\\t\\tconst path = [];\\n\\t\\t\\t\\twhile(node){\\n\\t\\t\\t\\t\\t\\tpath.unshift(node.name);\\n\\t\\t\\t\\t\\t\\tnode = node.parent;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn path;\\n\\t\\t};\\n\\t\\tconst createMorphTargetCurves = (curve, gltfNode, entityPath)=>{\\n\\t\\t\\t\\tconst out = outputMap[curve.output];\\n\\t\\t\\t\\tif (!out) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet targetNames;\\n\\t\\t\\t\\tif (meshes && meshes[gltfNode.mesh]) {\\n\\t\\t\\t\\t\\t\\tconst mesh = meshes[gltfNode.mesh];\\n\\t\\t\\t\\t\\t\\tif (mesh.hasOwnProperty('extras') && mesh.extras.hasOwnProperty('targetNames')) {\\n\\t\\t\\t\\t\\t\\t\\t\\ttargetNames = mesh.extras.targetNames;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst outData = out.data;\\n\\t\\t\\t\\tconst morphTargetCount = outData.length / inputMap[curve.input].data.length;\\n\\t\\t\\t\\tconst keyframeCount = outData.length / morphTargetCount;\\n\\t\\t\\t\\tconst singleBufferSize = keyframeCount * 4;\\n\\t\\t\\t\\tconst buffer = new ArrayBuffer(singleBufferSize * morphTargetCount);\\n\\t\\t\\t\\tfor(let j = 0; j < morphTargetCount; j++){\\n\\t\\t\\t\\t\\t\\tconst morphTargetOutput = new Float32Array(buffer, singleBufferSize * j, keyframeCount);\\n\\t\\t\\t\\t\\t\\tfor(let k = 0; k < keyframeCount; k++){\\n\\t\\t\\t\\t\\t\\t\\t\\tmorphTargetOutput[k] = outData[k * morphTargetCount + j];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst output = new AnimData(1, morphTargetOutput);\\n\\t\\t\\t\\t\\t\\tconst weightName = targetNames?.[j] ? `name.${targetNames[j]}` : j;\\n\\t\\t\\t\\t\\t\\toutputMap[-outputCounter] = output;\\n\\t\\t\\t\\t\\t\\tconst morphCurve = {\\n\\t\\t\\t\\t\\t\\t\\t\\tpaths: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tentityPath: entityPath,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcomponent: 'graph',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpropertyPath: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t`weight.${weightName}`\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t]\\n\\t\\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\\tinput: curve.input,\\n\\t\\t\\t\\t\\t\\t\\t\\toutput: -outputCounter,\\n\\t\\t\\t\\t\\t\\t\\t\\tinterpolation: curve.interpolation\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\toutputCounter++;\\n\\t\\t\\t\\t\\t\\tcurveMap[`morphCurve-${i}-${j}`] = morphCurve;\\n\\t\\t\\t\\t}\\n\\t\\t};\\n\\t\\tfor(i = 0; i < gltfAnimation.channels.length; ++i){\\n\\t\\t\\t\\tconst channel = gltfAnimation.channels[i];\\n\\t\\t\\t\\tconst target = channel.target;\\n\\t\\t\\t\\tconst curve = curveMap[channel.sampler];\\n\\t\\t\\t\\tconst node = nodes[target.node];\\n\\t\\t\\t\\tconst gltfNode = gltfNodes[target.node];\\n\\t\\t\\t\\tconst entityPath = constructNodePath(node);\\n\\t\\t\\t\\tif (target.path.startsWith('weights')) {\\n\\t\\t\\t\\t\\t\\tcreateMorphTargetCurves(curve, gltfNode, entityPath);\\n\\t\\t\\t\\t\\t\\tcurveMap[channel.sampler].morphCurve = true;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tcurve.paths.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tentityPath: entityPath,\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponent: 'graph',\\n\\t\\t\\t\\t\\t\\t\\t\\tpropertyPath: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttransformSchema[target.path]\\n\\t\\t\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst inputs = [];\\n\\t\\tconst outputs = [];\\n\\t\\tconst curves = [];\\n\\t\\tfor(const inputKey in inputMap){\\n\\t\\t\\t\\tinputs.push(inputMap[inputKey]);\\n\\t\\t\\t\\tinputMap[inputKey] = inputs.length - 1;\\n\\t\\t}\\n\\t\\tfor(const outputKey in outputMap){\\n\\t\\t\\t\\toutputs.push(outputMap[outputKey]);\\n\\t\\t\\t\\toutputMap[outputKey] = outputs.length - 1;\\n\\t\\t}\\n\\t\\tfor(const curveKey in curveMap){\\n\\t\\t\\t\\tconst curveData = curveMap[curveKey];\\n\\t\\t\\t\\tif (curveData.morphCurve) {\\n\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcurves.push(new AnimCurve(curveData.paths, inputMap[curveData.input], outputMap[curveData.output], curveData.interpolation));\\n\\t\\t\\t\\tif (curveData.paths.length > 0 && curveData.paths[0].propertyPath[0] === 'localRotation' && curveData.interpolation !== INTERPOLATION_CUBIC) {\\n\\t\\t\\t\\t\\t\\tquatArrays.push(curves[curves.length - 1].output);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tquatArrays.sort();\\n\\t\\tlet prevIndex = null;\\n\\t\\tlet data;\\n\\t\\tfor(i = 0; i < quatArrays.length; ++i){\\n\\t\\t\\t\\tconst index = quatArrays[i];\\n\\t\\t\\t\\tif (i === 0 || index !== prevIndex) {\\n\\t\\t\\t\\t\\t\\tdata = outputs[index];\\n\\t\\t\\t\\t\\t\\tif (data.components === 4) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst d = data.data;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst len = d.length - 4;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < len; j += 4){\\n\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\tif (dp < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\td[j + 4] *= -1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\td[j + 5] *= -1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\td[j + 6] *= -1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\td[j + 7] *= -1;\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tprevIndex = index;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tlet duration = 0;\\n\\t\\tfor(i = 0; i < inputs.length; i++){\\n\\t\\t\\t\\tdata = inputs[i]._data;\\n\\t\\t\\t\\tduration = Math.max(duration, data.length === 0 ? 0 : data[data.length - 1]);\\n\\t\\t}\\n\\t\\treturn new AnimTrack(gltfAnimation.hasOwnProperty('name') ? gltfAnimation.name : `animation_${animationIndex}`, duration, inputs, outputs, curves);\\n};\\nconst tempMat = new Mat4();\\nconst tempVec = new Vec3();\\nconst tempQuat = new Quat();\\nconst createNode = (gltfNode, nodeIndex, nodeInstancingMap)=>{\\n\\t\\tconst entity = new GraphNode();\\n\\t\\tif (gltfNode.hasOwnProperty('name') && gltfNode.name.length > 0) {\\n\\t\\t\\t\\tentity.name = gltfNode.name;\\n\\t\\t} else {\\n\\t\\t\\t\\tentity.name = `node_${nodeIndex}`;\\n\\t\\t}\\n\\t\\tif (gltfNode.hasOwnProperty('matrix')) {\\n\\t\\t\\t\\ttempMat.data.set(gltfNode.matrix);\\n\\t\\t\\t\\ttempMat.getTranslation(tempVec);\\n\\t\\t\\t\\tentity.setLocalPosition(tempVec);\\n\\t\\t\\t\\ttempQuat.setFromMat4(tempMat);\\n\\t\\t\\t\\tentity.setLocalRotation(tempQuat);\\n\\t\\t\\t\\ttempMat.getScale(tempVec);\\n\\t\\t\\t\\ttempVec.x *= tempMat.scaleSign;\\n\\t\\t\\t\\tentity.setLocalScale(tempVec);\\n\\t\\t}\\n\\t\\tif (gltfNode.hasOwnProperty('rotation')) {\\n\\t\\t\\t\\tconst r = gltfNode.rotation;\\n\\t\\t\\t\\tentity.setLocalRotation(r[0], r[1], r[2], r[3]);\\n\\t\\t}\\n\\t\\tif (gltfNode.hasOwnProperty('translation')) {\\n\\t\\t\\t\\tconst t = gltfNode.translation;\\n\\t\\t\\t\\tentity.setLocalPosition(t[0], t[1], t[2]);\\n\\t\\t}\\n\\t\\tif (gltfNode.hasOwnProperty('scale')) {\\n\\t\\t\\t\\tconst s = gltfNode.scale;\\n\\t\\t\\t\\tentity.setLocalScale(s[0], s[1], s[2]);\\n\\t\\t}\\n\\t\\tif (gltfNode.hasOwnProperty('extensions') && gltfNode.extensions.EXT_mesh_gpu_instancing) {\\n\\t\\t\\t\\tnodeInstancingMap.set(gltfNode, {\\n\\t\\t\\t\\t\\t\\text: gltfNode.extensions.EXT_mesh_gpu_instancing\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\treturn entity;\\n};\\nconst createCamera$1 = (gltfCamera, node)=>{\\n\\t\\tconst isOrthographic = gltfCamera.type === 'orthographic';\\n\\t\\tconst gltfProperties = isOrthographic ? gltfCamera.orthographic : gltfCamera.perspective;\\n\\t\\tconst componentData = {\\n\\t\\t\\t\\tenabled: false,\\n\\t\\t\\t\\tprojection: isOrthographic ? PROJECTION_ORTHOGRAPHIC : PROJECTION_PERSPECTIVE,\\n\\t\\t\\t\\tnearClip: gltfProperties.znear,\\n\\t\\t\\t\\taspectRatioMode: ASPECT_AUTO\\n\\t\\t};\\n\\t\\tif (gltfProperties.zfar) {\\n\\t\\t\\t\\tcomponentData.farClip = gltfProperties.zfar;\\n\\t\\t}\\n\\t\\tif (isOrthographic) {\\n\\t\\t\\t\\tcomponentData.orthoHeight = gltfProperties.ymag;\\n\\t\\t\\t\\tif (gltfProperties.xmag && gltfProperties.ymag) {\\n\\t\\t\\t\\t\\t\\tcomponentData.aspectRatioMode = ASPECT_MANUAL;\\n\\t\\t\\t\\t\\t\\tcomponentData.aspectRatio = gltfProperties.xmag / gltfProperties.ymag;\\n\\t\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\t\\tcomponentData.fov = gltfProperties.yfov * math.RAD_TO_DEG;\\n\\t\\t\\t\\tif (gltfProperties.aspectRatio) {\\n\\t\\t\\t\\t\\t\\tcomponentData.aspectRatioMode = ASPECT_MANUAL;\\n\\t\\t\\t\\t\\t\\tcomponentData.aspectRatio = gltfProperties.aspectRatio;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst cameraEntity = new Entity(gltfCamera.name);\\n\\t\\tcameraEntity.addComponent('camera', componentData);\\n\\t\\treturn cameraEntity;\\n};\\nconst createLight = (gltfLight, node)=>{\\n\\t\\tconst lightProps = {\\n\\t\\t\\t\\tenabled: false,\\n\\t\\t\\t\\ttype: gltfLight.type === 'point' ? 'omni' : gltfLight.type,\\n\\t\\t\\t\\tcolor: gltfLight.hasOwnProperty('color') ? new Color(gltfLight.color) : Color.WHITE,\\n\\t\\t\\t\\trange: gltfLight.hasOwnProperty('range') ? gltfLight.range : 9999,\\n\\t\\t\\t\\tfalloffMode: LIGHTFALLOFF_INVERSESQUARED,\\n\\t\\t\\t\\tintensity: gltfLight.hasOwnProperty('intensity') ? math.clamp(gltfLight.intensity, 0, 2) : 1\\n\\t\\t};\\n\\t\\tif (gltfLight.hasOwnProperty('spot')) {\\n\\t\\t\\t\\tlightProps.innerConeAngle = gltfLight.spot.hasOwnProperty('innerConeAngle') ? gltfLight.spot.innerConeAngle * math.RAD_TO_DEG : 0;\\n\\t\\t\\t\\tlightProps.outerConeAngle = gltfLight.spot.hasOwnProperty('outerConeAngle') ? gltfLight.spot.outerConeAngle * math.RAD_TO_DEG : 45;\\n\\t\\t}\\n\\t\\tif (gltfLight.hasOwnProperty('intensity')) {\\n\\t\\t\\t\\tconst outerAngleRad = gltfLight.spot?.outerConeAngle ?? Math.PI / 4;\\n\\t\\t\\t\\tconst innerAngleRad = gltfLight.spot?.innerConeAngle ?? 0;\\n\\t\\t\\t\\tlightProps.luminance = gltfLight.intensity * Light.getLightUnitConversion(lightTypes[lightProps.type], outerAngleRad, innerAngleRad);\\n\\t\\t}\\n\\t\\tconst lightEntity = new Entity(node.name);\\n\\t\\tlightEntity.rotateLocal(90, 0, 0);\\n\\t\\tlightEntity.addComponent('light', lightProps);\\n\\t\\treturn lightEntity;\\n};\\nconst createSkins = (device, gltf, nodes, bufferViews)=>{\\n\\t\\tif (!gltf.hasOwnProperty('skins') || gltf.skins.length === 0) {\\n\\t\\t\\t\\treturn [];\\n\\t\\t}\\n\\t\\tconst glbSkins = new Map();\\n\\t\\treturn gltf.skins.map((gltfSkin)=>{\\n\\t\\t\\t\\treturn createSkin(device, gltfSkin, gltf.accessors, bufferViews, nodes, glbSkins);\\n\\t\\t});\\n};\\nconst createMeshes = (device, gltf, bufferViews, options)=>{\\n\\t\\tconst vertexBufferDict = {};\\n\\t\\tconst meshVariants = {};\\n\\t\\tconst meshDefaultMaterials = {};\\n\\t\\tconst promises = [];\\n\\t\\tconst valid = !options.skipMeshes && gltf?.meshes?.length && gltf?.accessors?.length && gltf?.bufferViews?.length;\\n\\t\\tconst meshes = valid ? gltf.meshes.map((gltfMesh)=>{\\n\\t\\t\\t\\treturn createMesh(device, gltfMesh, gltf.accessors, bufferViews, vertexBufferDict, meshVariants, meshDefaultMaterials, options, promises);\\n\\t\\t}) : [];\\n\\t\\treturn {\\n\\t\\t\\t\\tmeshes,\\n\\t\\t\\t\\tmeshVariants,\\n\\t\\t\\t\\tmeshDefaultMaterials,\\n\\t\\t\\t\\tpromises\\n\\t\\t};\\n};\\nconst createMaterials = (gltf, textures, options)=>{\\n\\t\\tif (!gltf.hasOwnProperty('materials') || gltf.materials.length === 0) {\\n\\t\\t\\t\\treturn [];\\n\\t\\t}\\n\\t\\tconst preprocess = options?.material?.preprocess;\\n\\t\\tconst process = options?.material?.process ?? createMaterial;\\n\\t\\tconst postprocess = options?.material?.postprocess;\\n\\t\\treturn gltf.materials.map((gltfMaterial)=>{\\n\\t\\t\\t\\tif (preprocess) {\\n\\t\\t\\t\\t\\t\\tpreprocess(gltfMaterial);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst material = process(gltfMaterial, textures);\\n\\t\\t\\t\\tif (postprocess) {\\n\\t\\t\\t\\t\\t\\tpostprocess(gltfMaterial, material);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn material;\\n\\t\\t});\\n};\\nconst createVariants = (gltf)=>{\\n\\t\\tif (!gltf.hasOwnProperty('extensions') || !gltf.extensions.hasOwnProperty('KHR_materials_variants')) {\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\tconst data = gltf.extensions.KHR_materials_variants.variants;\\n\\t\\tconst variants = {};\\n\\t\\tfor(let i = 0; i < data.length; i++){\\n\\t\\t\\t\\tvariants[data[i].name] = i;\\n\\t\\t}\\n\\t\\treturn variants;\\n};\\nconst createAnimations = (gltf, nodes, bufferViews, options)=>{\\n\\t\\tif (!gltf.hasOwnProperty('animations') || gltf.animations.length === 0) {\\n\\t\\t\\t\\treturn [];\\n\\t\\t}\\n\\t\\tconst preprocess = options?.animation?.preprocess;\\n\\t\\tconst postprocess = options?.animation?.postprocess;\\n\\t\\treturn gltf.animations.map((gltfAnimation, index)=>{\\n\\t\\t\\t\\tif (preprocess) {\\n\\t\\t\\t\\t\\t\\tpreprocess(gltfAnimation);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst animation = createAnimation(gltfAnimation, index, gltf.accessors, bufferViews, nodes, gltf.meshes, gltf.nodes);\\n\\t\\t\\t\\tif (postprocess) {\\n\\t\\t\\t\\t\\t\\tpostprocess(gltfAnimation, animation);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn animation;\\n\\t\\t});\\n};\\nconst createInstancing = (device, gltf, nodeInstancingMap, bufferViews)=>{\\n\\t\\tconst accessors = gltf.accessors;\\n\\t\\tnodeInstancingMap.forEach((data, entity)=>{\\n\\t\\t\\t\\tconst attributes = data.ext.attributes;\\n\\t\\t\\t\\tlet translations;\\n\\t\\t\\t\\tif (attributes.hasOwnProperty('TRANSLATION')) {\\n\\t\\t\\t\\t\\t\\tconst accessor = accessors[attributes.TRANSLATION];\\n\\t\\t\\t\\t\\t\\ttranslations = getAccessorDataFloat32(accessor, bufferViews);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet rotations;\\n\\t\\t\\t\\tif (attributes.hasOwnProperty('ROTATION')) {\\n\\t\\t\\t\\t\\t\\tconst accessor = accessors[attributes.ROTATION];\\n\\t\\t\\t\\t\\t\\trotations = getAccessorDataFloat32(accessor, bufferViews);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet scales;\\n\\t\\t\\t\\tif (attributes.hasOwnProperty('SCALE')) {\\n\\t\\t\\t\\t\\t\\tconst accessor = accessors[attributes.SCALE];\\n\\t\\t\\t\\t\\t\\tscales = getAccessorDataFloat32(accessor, bufferViews);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst instanceCount = (translations ? translations.length / 3 : 0) || (rotations ? rotations.length / 4 : 0) || (scales ? scales.length / 3 : 0);\\n\\t\\t\\t\\tif (instanceCount) {\\n\\t\\t\\t\\t\\t\\tconst matrices = new Float32Array(instanceCount * 16);\\n\\t\\t\\t\\t\\t\\tconst pos = new Vec3();\\n\\t\\t\\t\\t\\t\\tconst rot = new Quat();\\n\\t\\t\\t\\t\\t\\tconst scl = new Vec3(1, 1, 1);\\n\\t\\t\\t\\t\\t\\tconst matrix = new Mat4();\\n\\t\\t\\t\\t\\t\\tlet matrixIndex = 0;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < instanceCount; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst i3 = i * 3;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (translations) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpos.set(translations[i3], translations[i3 + 1], translations[i3 + 2]);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (rotations) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst i4 = i * 4;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trot.set(rotations[i4], rotations[i4 + 1], rotations[i4 + 2], rotations[i4 + 3]);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (scales) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscl.set(scales[i3], scales[i3 + 1], scales[i3 + 2]);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tmatrix.setTRS(pos, rot, scl);\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let m = 0; m < 16; m++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmatrices[matrixIndex++] = matrix.data[m];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tdata.matrices = matrices;\\n\\t\\t\\t\\t}\\n\\t\\t});\\n};\\nconst createNodes = (gltf, options, nodeInstancingMap)=>{\\n\\t\\tif (!gltf.hasOwnProperty('nodes') || gltf.nodes.length === 0) {\\n\\t\\t\\t\\treturn [];\\n\\t\\t}\\n\\t\\tconst preprocess = options?.node?.preprocess;\\n\\t\\tconst process = options?.node?.process ?? createNode;\\n\\t\\tconst postprocess = options?.node?.postprocess;\\n\\t\\tconst nodes = gltf.nodes.map((gltfNode, index)=>{\\n\\t\\t\\t\\tif (preprocess) {\\n\\t\\t\\t\\t\\t\\tpreprocess(gltfNode);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst node = process(gltfNode, index, nodeInstancingMap);\\n\\t\\t\\t\\tif (postprocess) {\\n\\t\\t\\t\\t\\t\\tpostprocess(gltfNode, node);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn node;\\n\\t\\t});\\n\\t\\tfor(let i = 0; i < gltf.nodes.length; ++i){\\n\\t\\t\\t\\tconst gltfNode = gltf.nodes[i];\\n\\t\\t\\t\\tif (gltfNode.hasOwnProperty('children')) {\\n\\t\\t\\t\\t\\t\\tconst parent = nodes[i];\\n\\t\\t\\t\\t\\t\\tconst uniqueNames = {};\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j < gltfNode.children.length; ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst child = nodes[gltfNode.children[j]];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!child.parent) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (uniqueNames.hasOwnProperty(child.name)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tchild.name += uniqueNames[child.name]++;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuniqueNames[child.name] = 1;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tparent.addChild(child);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn nodes;\\n};\\nconst createScenes = (gltf, nodes)=>{\\n\\t\\tconst scenes = [];\\n\\t\\tconst count = gltf.scenes.length;\\n\\t\\tif (count === 1 && gltf.scenes[0].nodes?.length === 1) {\\n\\t\\t\\t\\tconst nodeIndex = gltf.scenes[0].nodes[0];\\n\\t\\t\\t\\tscenes.push(nodes[nodeIndex]);\\n\\t\\t} else {\\n\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\tconst scene = gltf.scenes[i];\\n\\t\\t\\t\\t\\t\\tif (scene.nodes) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst sceneRoot = new GraphNode(scene.name);\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let n = 0; n < scene.nodes.length; n++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst childNode = nodes[scene.nodes[n]];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsceneRoot.addChild(childNode);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tscenes.push(sceneRoot);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn scenes;\\n};\\nconst createCameras = (gltf, nodes, options)=>{\\n\\t\\tlet cameras = null;\\n\\t\\tif (gltf.hasOwnProperty('nodes') && gltf.hasOwnProperty('cameras') && gltf.cameras.length > 0) {\\n\\t\\t\\t\\tconst preprocess = options?.camera?.preprocess;\\n\\t\\t\\t\\tconst process = options?.camera?.process ?? createCamera$1;\\n\\t\\t\\t\\tconst postprocess = options?.camera?.postprocess;\\n\\t\\t\\t\\tgltf.nodes.forEach((gltfNode, nodeIndex)=>{\\n\\t\\t\\t\\t\\t\\tif (gltfNode.hasOwnProperty('camera')) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst gltfCamera = gltf.cameras[gltfNode.camera];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (gltfCamera) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (preprocess) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpreprocess(gltfCamera);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst camera = process(gltfCamera, nodes[nodeIndex]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (postprocess) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpostprocess(gltfCamera, camera);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (camera) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!cameras) cameras = new Map();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcameras.set(gltfNode, camera);\\n\\t\\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}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\treturn cameras;\\n};\\nconst createLights = (gltf, nodes, options)=>{\\n\\t\\tlet lights = null;\\n\\t\\tif (gltf.hasOwnProperty('nodes') && gltf.hasOwnProperty('extensions') && gltf.extensions.hasOwnProperty('KHR_lights_punctual') && gltf.extensions.KHR_lights_punctual.hasOwnProperty('lights')) {\\n\\t\\t\\t\\tconst gltfLights = gltf.extensions.KHR_lights_punctual.lights;\\n\\t\\t\\t\\tif (gltfLights.length) {\\n\\t\\t\\t\\t\\t\\tconst preprocess = options?.light?.preprocess;\\n\\t\\t\\t\\t\\t\\tconst process = options?.light?.process ?? createLight;\\n\\t\\t\\t\\t\\t\\tconst postprocess = options?.light?.postprocess;\\n\\t\\t\\t\\t\\t\\tgltf.nodes.forEach((gltfNode, nodeIndex)=>{\\n\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\tconst lightIndex = gltfNode.extensions.KHR_lights_punctual.light;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst gltfLight = gltfLights[lightIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (gltfLight) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (preprocess) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpreprocess(gltfLight);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst light = process(gltfLight, nodes[nodeIndex]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (postprocess) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpostprocess(gltfLight, light);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (light) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!lights) lights = new Map();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlights.set(gltfNode, light);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn lights;\\n};\\nconst linkSkins = (gltf, renders, skins)=>{\\n\\t\\tgltf.nodes.forEach((gltfNode)=>{\\n\\t\\t\\t\\tif (gltfNode.hasOwnProperty('mesh') && gltfNode.hasOwnProperty('skin')) {\\n\\t\\t\\t\\t\\t\\tconst meshGroup = renders[gltfNode.mesh].meshes;\\n\\t\\t\\t\\t\\t\\tmeshGroup.forEach((mesh)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh.skin = skins[gltfNode.skin];\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t});\\n};\\nconst createResources = async (device, gltf, bufferViews, textures, options)=>{\\n\\t\\tconst preprocess = options?.global?.preprocess;\\n\\t\\tconst postprocess = options?.global?.postprocess;\\n\\t\\tif (preprocess) {\\n\\t\\t\\t\\tpreprocess(gltf);\\n\\t\\t}\\n\\t\\tif (gltf.asset && gltf.asset.generator === 'PlayCanvas') ;\\n\\t\\tconst nodeInstancingMap = new Map();\\n\\t\\tconst nodes = createNodes(gltf, options, nodeInstancingMap);\\n\\t\\tconst scenes = createScenes(gltf, nodes);\\n\\t\\tconst lights = createLights(gltf, nodes, options);\\n\\t\\tconst cameras = createCameras(gltf, nodes, options);\\n\\t\\tconst variants = createVariants(gltf);\\n\\t\\tconst bufferViewData = await Promise.all(bufferViews);\\n\\t\\tconst { meshes, meshVariants, meshDefaultMaterials, promises } = createMeshes(device, gltf, bufferViewData, options);\\n\\t\\tconst animations = createAnimations(gltf, nodes, bufferViewData, options);\\n\\t\\tcreateInstancing(device, gltf, nodeInstancingMap, bufferViewData);\\n\\t\\tconst textureAssets = await Promise.all(textures);\\n\\t\\tconst textureInstances = textureAssets.map((t)=>t.resource);\\n\\t\\tconst materials = createMaterials(gltf, textureInstances, options);\\n\\t\\tconst skins = createSkins(device, gltf, nodes, bufferViewData);\\n\\t\\tconst renders = [];\\n\\t\\tfor(let i = 0; i < meshes.length; i++){\\n\\t\\t\\t\\trenders[i] = new Render();\\n\\t\\t\\t\\trenders[i].meshes = meshes[i];\\n\\t\\t}\\n\\t\\tlinkSkins(gltf, renders, skins);\\n\\t\\tconst result = new GlbResources();\\n\\t\\tresult.gltf = gltf;\\n\\t\\tresult.nodes = nodes;\\n\\t\\tresult.scenes = scenes;\\n\\t\\tresult.animations = animations;\\n\\t\\tresult.textures = textureAssets;\\n\\t\\tresult.materials = materials;\\n\\t\\tresult.variants = variants;\\n\\t\\tresult.meshVariants = meshVariants;\\n\\t\\tresult.meshDefaultMaterials = meshDefaultMaterials;\\n\\t\\tresult.renders = renders;\\n\\t\\tresult.skins = skins;\\n\\t\\tresult.lights = lights;\\n\\t\\tresult.cameras = cameras;\\n\\t\\tresult.nodeInstancingMap = nodeInstancingMap;\\n\\t\\tif (postprocess) {\\n\\t\\t\\t\\tpostprocess(gltf, result);\\n\\t\\t}\\n\\t\\tawait Promise.all(promises);\\n\\t\\treturn result;\\n};\\nconst applySampler = (texture, gltfSampler)=>{\\n\\t\\tconst getFilter = (filter, defaultValue)=>{\\n\\t\\t\\t\\tswitch(filter){\\n\\t\\t\\t\\t\\t\\tcase 9728:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn FILTER_NEAREST;\\n\\t\\t\\t\\t\\t\\tcase 9729:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn FILTER_LINEAR;\\n\\t\\t\\t\\t\\t\\tcase 9984:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn FILTER_NEAREST_MIPMAP_NEAREST;\\n\\t\\t\\t\\t\\t\\tcase 9985:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn FILTER_LINEAR_MIPMAP_NEAREST;\\n\\t\\t\\t\\t\\t\\tcase 9986:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn FILTER_NEAREST_MIPMAP_LINEAR;\\n\\t\\t\\t\\t\\t\\tcase 9987:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn FILTER_LINEAR_MIPMAP_LINEAR;\\n\\t\\t\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn defaultValue;\\n\\t\\t\\t\\t}\\n\\t\\t};\\n\\t\\tconst getWrap = (wrap, defaultValue)=>{\\n\\t\\t\\t\\tswitch(wrap){\\n\\t\\t\\t\\t\\t\\tcase 33071:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn ADDRESS_CLAMP_TO_EDGE;\\n\\t\\t\\t\\t\\t\\tcase 33648:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn ADDRESS_MIRRORED_REPEAT;\\n\\t\\t\\t\\t\\t\\tcase 10497:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn ADDRESS_REPEAT;\\n\\t\\t\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn defaultValue;\\n\\t\\t\\t\\t}\\n\\t\\t};\\n\\t\\tif (texture) {\\n\\t\\t\\t\\tgltfSampler = gltfSampler ?? {};\\n\\t\\t\\t\\ttexture.minFilter = getFilter(gltfSampler.minFilter, FILTER_LINEAR_MIPMAP_LINEAR);\\n\\t\\t\\t\\ttexture.magFilter = getFilter(gltfSampler.magFilter, FILTER_LINEAR);\\n\\t\\t\\t\\ttexture.addressU = getWrap(gltfSampler.wrapS, ADDRESS_REPEAT);\\n\\t\\t\\t\\ttexture.addressV = getWrap(gltfSampler.wrapT, ADDRESS_REPEAT);\\n\\t\\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\\t\\tif (!gltf.images || gltf.images.length === 0) {\\n\\t\\t\\t\\treturn [];\\n\\t\\t}\\n\\t\\tconst preprocess = options?.image?.preprocess;\\n\\t\\tconst processAsync = options?.image?.processAsync;\\n\\t\\tconst postprocess = options?.image?.postprocess;\\n\\t\\tconst mimeTypeFileExtensions = {\\n\\t\\t\\t\\t'image/png': 'png',\\n\\t\\t\\t\\t'image/jpeg': 'jpg',\\n\\t\\t\\t\\t'image/basis': 'basis',\\n\\t\\t\\t\\t'image/ktx': 'ktx',\\n\\t\\t\\t\\t'image/ktx2': 'ktx2',\\n\\t\\t\\t\\t'image/vnd-ms.dds': 'dds'\\n\\t\\t};\\n\\t\\tconst getGammaTextures = (gltf)=>{\\n\\t\\t\\t\\tconst set = new Set();\\n\\t\\t\\t\\tif (gltf.hasOwnProperty('materials')) {\\n\\t\\t\\t\\t\\t\\tgltf.materials.forEach((gltfMaterial)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (gltfMaterial.hasOwnProperty('pbrMetallicRoughness')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst pbrData = gltfMaterial.pbrMetallicRoughness;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (pbrData.hasOwnProperty('baseColorTexture')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst gltfTexture = gltf.textures[pbrData.baseColorTexture.index];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tset.add(getTextureSource(gltfTexture));\\n\\t\\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\\tif (gltfMaterial.hasOwnProperty('emissiveTexture')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst gltfTexture = gltf.textures[gltfMaterial.emissiveTexture.index];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tset.add(getTextureSource(gltfTexture));\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (gltfMaterial.hasOwnProperty('extensions')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst sheen = gltfMaterial.extensions.KHR_materials_sheen;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (sheen) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (sheen.hasOwnProperty('sheenColorTexture')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst gltfTexture = gltf.textures[sheen.sheenColorTexture.index];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tset.add(getTextureSource(gltfTexture));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst specularGlossiness = gltfMaterial.extensions.KHR_materials_pbrSpecularGlossiness;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (specularGlossiness) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (specularGlossiness.hasOwnProperty('specularGlossinessTexture')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst gltfTexture = gltf.textures[specularGlossiness.specularGlossinessTexture.index];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tset.add(getTextureSource(gltfTexture));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst specular = gltfMaterial.extensions.KHR_materials_specular;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (specular) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (specular.hasOwnProperty('specularColorTexture')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst gltfTexture = gltf.textures[specular.specularColorTexture.index];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tset.add(getTextureSource(gltfTexture));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn set;\\n\\t\\t};\\n\\t\\tconst loadTexture = (gltfImage, url, bufferView, mimeType, options, srgb)=>{\\n\\t\\t\\t\\treturn new Promise((resolve, reject)=>{\\n\\t\\t\\t\\t\\t\\tconst continuation = (bufferViewData)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst name = `${gltfImage.name || 'gltf-texture'}-${gltfTextureUniqueId++}`;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst file = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\turl: url || name\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\tif (bufferViewData) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfile.contents = bufferViewData.slice(0).buffer;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (mimeType) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst extension = mimeTypeFileExtensions[mimeType];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (extension) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfile.filename = `${file.url}.${extension}`;\\n\\t\\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 data = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsrgb\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\tconst asset = new Asset(name, 'texture', file, data, options);\\n\\t\\t\\t\\t\\t\\t\\t\\tasset.on('load', (asset)=>resolve(asset));\\n\\t\\t\\t\\t\\t\\t\\t\\tasset.on('error', (err)=>reject(err));\\n\\t\\t\\t\\t\\t\\t\\t\\tregistry.add(asset);\\n\\t\\t\\t\\t\\t\\t\\t\\tregistry.load(asset);\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tif (bufferView) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbufferView.then((bufferViewData)=>continuation(bufferViewData));\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinuation(null);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t};\\n\\t\\tconst gammaTextures = getGammaTextures(gltf);\\n\\t\\treturn gltf.images.map((gltfImage, i)=>{\\n\\t\\t\\t\\tif (preprocess) {\\n\\t\\t\\t\\t\\t\\tpreprocess(gltfImage);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet promise;\\n\\t\\t\\t\\tif (processAsync) {\\n\\t\\t\\t\\t\\t\\tpromise = new Promise((resolve, reject)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tprocessAsync(gltfImage, (err, textureAsset)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treject(err);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresolve(textureAsset);\\n\\t\\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});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tpromise = new Promise((resolve)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tresolve(null);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tpromise = promise.then((textureAsset)=>{\\n\\t\\t\\t\\t\\t\\tconst srgb = gammaTextures.has(i);\\n\\t\\t\\t\\t\\t\\tif (textureAsset) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn textureAsset;\\n\\t\\t\\t\\t\\t\\t} else if (gltfImage.hasOwnProperty('uri')) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (isDataURI(gltfImage.uri)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn loadTexture(gltfImage, gltfImage.uri, null, getDataURIMimeType(gltfImage.uri), null, srgb);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\treturn loadTexture(gltfImage, ABSOLUTE_URL.test(gltfImage.uri) ? gltfImage.uri : path.join(urlBase, gltfImage.uri), null, null, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcrossOrigin: 'anonymous'\\n\\t\\t\\t\\t\\t\\t\\t\\t}, srgb);\\n\\t\\t\\t\\t\\t\\t} else if (gltfImage.hasOwnProperty('bufferView') && gltfImage.hasOwnProperty('mimeType')) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn loadTexture(gltfImage, null, bufferViews[gltfImage.bufferView], gltfImage.mimeType, null, srgb);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn Promise.reject(new Error(`Invalid image found in gltf (neither uri or bufferView found). index=${i}`));\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (postprocess) {\\n\\t\\t\\t\\t\\t\\tpromise = promise.then((textureAsset)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tpostprocess(gltfImage, textureAsset);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn textureAsset;\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn promise;\\n\\t\\t});\\n};\\nconst createTextures = (gltf, images, options)=>{\\n\\t\\tif (!gltf?.images?.length || !gltf?.textures?.length) {\\n\\t\\t\\t\\treturn [];\\n\\t\\t}\\n\\t\\tconst preprocess = options?.texture?.preprocess;\\n\\t\\tconst processAsync = options?.texture?.processAsync;\\n\\t\\tconst postprocess = options?.texture?.postprocess;\\n\\t\\tconst seenImages = new Set();\\n\\t\\treturn gltf.textures.map((gltfTexture)=>{\\n\\t\\t\\t\\tif (preprocess) {\\n\\t\\t\\t\\t\\t\\tpreprocess(gltfTexture);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet promise;\\n\\t\\t\\t\\tif (processAsync) {\\n\\t\\t\\t\\t\\t\\tpromise = new Promise((resolve, reject)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tprocessAsync(gltfTexture, gltf.images, (err, gltfImageIndex)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treject(err);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresolve(gltfImageIndex);\\n\\t\\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});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tpromise = new Promise((resolve)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tresolve(null);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tpromise = promise.then((gltfImageIndex)=>{\\n\\t\\t\\t\\t\\t\\tgltfImageIndex = gltfImageIndex ?? getTextureSource(gltfTexture);\\n\\t\\t\\t\\t\\t\\tconst cloneAsset = seenImages.has(gltfImageIndex);\\n\\t\\t\\t\\t\\t\\tseenImages.add(gltfImageIndex);\\n\\t\\t\\t\\t\\t\\treturn images[gltfImageIndex].then((imageAsset)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst asset = cloneAsset ? cloneTextureAsset(imageAsset) : imageAsset;\\n\\t\\t\\t\\t\\t\\t\\t\\tapplySampler(asset.resource, (gltf.samplers ?? [])[gltfTexture.sampler]);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn asset;\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (postprocess) {\\n\\t\\t\\t\\t\\t\\tpromise = promise.then((textureAsset)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tpostprocess(gltfTexture, textureAsset);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn textureAsset;\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn promise;\\n\\t\\t});\\n};\\nconst loadBuffers = (gltf, binaryChunk, urlBase, options)=>{\\n\\t\\tif (!gltf.buffers || gltf.buffers.length === 0) {\\n\\t\\t\\t\\treturn [];\\n\\t\\t}\\n\\t\\tconst preprocess = options?.buffer?.preprocess;\\n\\t\\tconst processAsync = options?.buffer?.processAsync;\\n\\t\\tconst postprocess = options?.buffer?.postprocess;\\n\\t\\treturn gltf.buffers.map((gltfBuffer, i)=>{\\n\\t\\t\\t\\tif (preprocess) {\\n\\t\\t\\t\\t\\t\\tpreprocess(gltfBuffer);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet promise;\\n\\t\\t\\t\\tif (processAsync) {\\n\\t\\t\\t\\t\\t\\tpromise = new Promise((resolve, reject)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tprocessAsync(gltfBuffer, (err, arrayBuffer)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treject(err);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresolve(arrayBuffer);\\n\\t\\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});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tpromise = new Promise((resolve)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tresolve(null);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tpromise = promise.then((arrayBuffer)=>{\\n\\t\\t\\t\\t\\t\\tif (arrayBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn arrayBuffer;\\n\\t\\t\\t\\t\\t\\t} else if (gltfBuffer.hasOwnProperty('uri')) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (isDataURI(gltfBuffer.uri)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst byteString = atob(gltfBuffer.uri.split(',')[1]);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst binaryArray = new Uint8Array(byteString.length);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < byteString.length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbinaryArray[j] = byteString.charCodeAt(j);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn binaryArray;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\treturn new Promise((resolve, reject)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\thttp.get(ABSOLUTE_URL.test(gltfBuffer.uri) ? gltfBuffer.uri : path.join(urlBase, gltfBuffer.uri), {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcache: true,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresponseType: 'arraybuffer',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tretry: false\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}, (err, result)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treject(err);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresolve(new Uint8Array(result));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\treturn binaryChunk;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (postprocess) {\\n\\t\\t\\t\\t\\t\\tpromise = promise.then((buffer)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tpostprocess(gltf.buffers[i], buffer);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn buffer;\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn promise;\\n\\t\\t});\\n};\\nconst parseGltf = (gltfChunk, callback)=>{\\n\\t\\tconst decodeBinaryUtf8 = (array)=>{\\n\\t\\t\\t\\tif (typeof TextDecoder !== 'undefined') {\\n\\t\\t\\t\\t\\t\\treturn new TextDecoder().decode(array);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet str = '';\\n\\t\\t\\t\\tfor(let i = 0; i < array.length; i++){\\n\\t\\t\\t\\t\\t\\tstr += String.fromCharCode(array[i]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn decodeURIComponent(escape(str));\\n\\t\\t};\\n\\t\\tconst gltf = JSON.parse(decodeBinaryUtf8(gltfChunk));\\n\\t\\tif (gltf.asset && gltf.asset.version && parseFloat(gltf.asset.version) < 2) {\\n\\t\\t\\t\\tcallback(`Invalid gltf version. Expected version 2.0 or above but found version '${gltf.asset.version}'.`);\\n\\t\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tcallback(null, gltf);\\n};\\nconst parseGlb = (glbData, callback)=>{\\n\\t\\tconst data = glbData instanceof ArrayBuffer ? new DataView(glbData) : new DataView(glbData.buffer, glbData.byteOffset, glbData.byteLength);\\n\\t\\tconst magic = data.getUint32(0, true);\\n\\t\\tconst version = data.getUint32(4, true);\\n\\t\\tconst length = data.getUint32(8, true);\\n\\t\\tif (magic !== 0x46546C67) {\\n\\t\\t\\t\\tcallback(`Invalid magic number found in glb header. Expected 0x46546C67, found 0x${magic.toString(16)}`);\\n\\t\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (version !== 2) {\\n\\t\\t\\t\\tcallback(`Invalid version number found in glb header. Expected 2, found ${version}`);\\n\\t\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (length <= 0 || length > data.byteLength) {\\n\\t\\t\\t\\tcallback(`Invalid length found in glb header. Found ${length}`);\\n\\t\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst chunks = [];\\n\\t\\tlet offset = 12;\\n\\t\\twhile(offset < length){\\n\\t\\t\\t\\tconst chunkLength = data.getUint32(offset, true);\\n\\t\\t\\t\\tif (offset + chunkLength + 8 > data.byteLength) {\\n\\t\\t\\t\\t\\t\\tcallback(`Invalid chunk length found in glb. Found ${chunkLength}`);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst chunkType = data.getUint32(offset + 4, true);\\n\\t\\t\\t\\tconst chunkData = new Uint8Array(data.buffer, data.byteOffset + offset + 8, chunkLength);\\n\\t\\t\\t\\tchunks.push({\\n\\t\\t\\t\\t\\t\\tlength: chunkLength,\\n\\t\\t\\t\\t\\t\\ttype: chunkType,\\n\\t\\t\\t\\t\\t\\tdata: chunkData\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\toffset += chunkLength + 8;\\n\\t\\t}\\n\\t\\tif (chunks.length !== 1 && chunks.length !== 2) {\\n\\t\\t\\t\\tcallback('Invalid number of chunks found in glb file.');\\n\\t\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (chunks[0].type !== 0x4E4F534A) {\\n\\t\\t\\t\\tcallback(`Invalid chunk type found in glb file. Expected 0x4E4F534A, found 0x${chunks[0].type.toString(16)}`);\\n\\t\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (chunks.length > 1 && chunks[1].type !== 0x004E4942) {\\n\\t\\t\\t\\tcallback(`Invalid chunk type found in glb file. Expected 0x004E4942, found 0x${chunks[1].type.toString(16)}`);\\n\\t\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tcallback(null, {\\n\\t\\t\\t\\tgltfChunk: chunks[0].data,\\n\\t\\t\\t\\tbinaryChunk: chunks.length === 2 ? chunks[1].data : null\\n\\t\\t});\\n};\\nconst parseChunk = (filename, data, callback)=>{\\n\\t\\tconst hasGlbHeader = ()=>{\\n\\t\\t\\t\\tconst u8 = new Uint8Array(data);\\n\\t\\t\\t\\treturn u8[0] === 103 && u8[1] === 108 && u8[2] === 84 && u8[3] === 70;\\n\\t\\t};\\n\\t\\tif (filename && filename.toLowerCase().endsWith('.glb') || hasGlbHeader()) {\\n\\t\\t\\t\\tparseGlb(data, callback);\\n\\t\\t} else {\\n\\t\\t\\t\\tcallback(null, {\\n\\t\\t\\t\\t\\t\\tgltfChunk: data,\\n\\t\\t\\t\\t\\t\\tbinaryChunk: null\\n\\t\\t\\t\\t});\\n\\t\\t}\\n};\\nconst createBufferViews = (gltf, buffers, options)=>{\\n\\t\\tconst result = [];\\n\\t\\tconst preprocess = options?.bufferView?.preprocess;\\n\\t\\tconst processAsync = options?.bufferView?.processAsync;\\n\\t\\tconst postprocess = options?.bufferView?.postprocess;\\n\\t\\tif (!gltf.bufferViews?.length) {\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tfor(let i = 0; i < gltf.bufferViews.length; ++i){\\n\\t\\t\\t\\tconst gltfBufferView = gltf.bufferViews[i];\\n\\t\\t\\t\\tif (preprocess) {\\n\\t\\t\\t\\t\\t\\tpreprocess(gltfBufferView);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet promise;\\n\\t\\t\\t\\tif (processAsync) {\\n\\t\\t\\t\\t\\t\\tpromise = new Promise((resolve, reject)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tprocessAsync(gltfBufferView, buffers, (err, result)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treject(err);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresolve(result);\\n\\t\\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});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tpromise = new Promise((resolve)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tresolve(null);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tpromise = promise.then((buffer)=>{\\n\\t\\t\\t\\t\\t\\tif (buffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn buffer;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn buffers[gltfBufferView.buffer].then((buffer)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\treturn new Uint8Array(buffer.buffer, buffer.byteOffset + (gltfBufferView.byteOffset || 0), gltfBufferView.byteLength);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (gltfBufferView.hasOwnProperty('byteStride')) {\\n\\t\\t\\t\\t\\t\\tpromise = promise.then((typedArray)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\ttypedArray.byteStride = gltfBufferView.byteStride;\\n\\t\\t\\t\\t\\t\\t\\t\\treturn typedArray;\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (postprocess) {\\n\\t\\t\\t\\t\\t\\tpromise = promise.then((typedArray)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tpostprocess(gltfBufferView, typedArray);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn typedArray;\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tresult.push(promise);\\n\\t\\t}\\n\\t\\treturn result;\\n};\\nclass GlbParser {\\n\\t\\tstatic parse(filename, urlBase, data, device, registry, options, callback) {\\n\\t\\t\\t\\tparseChunk(filename, data, (err, chunks)=>{\\n\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tparseGltf(chunks.gltfChunk, (err, gltf)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst buffers = loadBuffers(gltf, chunks.binaryChunk, urlBase, options);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst bufferViews = createBufferViews(gltf, buffers, options);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst images = createImages(gltf, bufferViews, urlBase, registry, options);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst textures = createTextures(gltf, images, options);\\n\\t\\t\\t\\t\\t\\t\\t\\tcreateResources(device, gltf, bufferViews, textures, options).then((result)=>callback(null, result)).catch((err)=>callback(err));\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tstatic createDefaultMaterial() {\\n\\t\\t\\t\\treturn createMaterial({\\n\\t\\t\\t\\t\\t\\tname: 'defaultGlbMaterial'\\n\\t\\t\\t\\t}, []);\\n\\t\\t}\\n}\\n\\nclass BinaryHandler extends ResourceHandler {\\n\\t\\tload(url, callback) {\\n\\t\\t\\t\\tif (typeof url === 'string') {\\n\\t\\t\\t\\t\\t\\turl = {\\n\\t\\t\\t\\t\\t\\t\\t\\tload: url,\\n\\t\\t\\t\\t\\t\\t\\t\\toriginal: url\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\thttp.get(url.load, {\\n\\t\\t\\t\\t\\t\\tresponseType: Http.ResponseType.ARRAY_BUFFER,\\n\\t\\t\\t\\t\\t\\tretry: this.maxRetries > 0,\\n\\t\\t\\t\\t\\t\\tmaxRetries: this.maxRetries\\n\\t\\t\\t\\t}, (err, response)=>{\\n\\t\\t\\t\\t\\t\\tif (!err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(null, response);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(`Error loading binary resource: ${url.original} [${err}]`);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\topenBinary(data) {\\n\\t\\t\\t\\treturn data.buffer;\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tsuper(app, 'binary');\\n\\t\\t}\\n}\\n\\nclass GlbContainerResource {\\n\\t\\tget model() {\\n\\t\\t\\t\\tif (!this._model) {\\n\\t\\t\\t\\t\\t\\tconst model = GlbContainerResource.createModel(this.data, this._defaultMaterial);\\n\\t\\t\\t\\t\\t\\tconst modelAsset = GlbContainerResource.createAsset(this._assetName, 'model', model, 0);\\n\\t\\t\\t\\t\\t\\tthis._assets.add(modelAsset);\\n\\t\\t\\t\\t\\t\\tthis._model = modelAsset;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._model;\\n\\t\\t}\\n\\t\\tstatic createAsset(assetName, type, resource, index) {\\n\\t\\t\\t\\tconst subAsset = new Asset(`${assetName}/${type}/${index}`, type, {\\n\\t\\t\\t\\t\\t\\turl: ''\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tsubAsset.resource = resource;\\n\\t\\t\\t\\tsubAsset.loaded = true;\\n\\t\\t\\t\\treturn subAsset;\\n\\t\\t}\\n\\t\\tinstantiateModelEntity(options) {\\n\\t\\t\\t\\tconst entity = new Entity(undefined, this._assets._loader._app);\\n\\t\\t\\t\\tentity.addComponent('model', Object.assign({\\n\\t\\t\\t\\t\\t\\ttype: 'asset',\\n\\t\\t\\t\\t\\t\\tasset: this.model\\n\\t\\t\\t\\t}, options));\\n\\t\\t\\t\\treturn entity;\\n\\t\\t}\\n\\t\\tinstantiateRenderEntity(options) {\\n\\t\\t\\t\\tconst defaultMaterial = this._defaultMaterial;\\n\\t\\t\\t\\tconst skinnedMeshInstances = [];\\n\\t\\t\\t\\tconst createMeshInstance = function(root, entity, mesh, materials, meshDefaultMaterials, skins, gltfNode, nodeInstancingMap) {\\n\\t\\t\\t\\t\\t\\tconst materialIndex = meshDefaultMaterials[mesh.id];\\n\\t\\t\\t\\t\\t\\tconst material = materialIndex === undefined ? defaultMaterial : materials[materialIndex];\\n\\t\\t\\t\\t\\t\\tconst meshInstance = new MeshInstance(mesh, material);\\n\\t\\t\\t\\t\\t\\tif (mesh.morph) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmeshInstance.morphInstance = new MorphInstance(mesh.morph);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (gltfNode.hasOwnProperty('skin')) {\\n\\t\\t\\t\\t\\t\\t\\t\\tskinnedMeshInstances.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmeshInstance: meshInstance,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trootBone: root,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tentity: entity\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst instData = nodeInstancingMap.get(gltfNode);\\n\\t\\t\\t\\t\\t\\tif (instData) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst matrices = instData.matrices;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst vbFormat = VertexFormat.getDefaultInstancingFormat(mesh.device);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst vb = new VertexBuffer(mesh.device, vbFormat, matrices.length / 16, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata: matrices\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tmeshInstance.setInstancing(vb);\\n\\t\\t\\t\\t\\t\\t\\t\\tmeshInstance.instancingData._destroyVertexBuffer = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn meshInstance;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst cloneHierarchy = (root, node, glb)=>{\\n\\t\\t\\t\\t\\t\\tconst entity = new Entity(undefined, this._assets._loader._app);\\n\\t\\t\\t\\t\\t\\tnode._cloneInternal(entity);\\n\\t\\t\\t\\t\\t\\tif (!root) root = entity;\\n\\t\\t\\t\\t\\t\\tlet attachedMi = null;\\n\\t\\t\\t\\t\\t\\tlet renderAsset = null;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < glb.nodes.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst glbNode = glb.nodes[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (glbNode === node) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst gltfNode = glb.gltf.nodes[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (gltfNode.hasOwnProperty('mesh')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst meshGroup = glb.renders[gltfNode.mesh].meshes;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trenderAsset = this.renders[gltfNode.mesh];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let mi = 0; mi < meshGroup.length; mi++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst mesh = meshGroup[mi];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (mesh) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!attachedMi) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tattachedMi = [];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tattachedMi.push(cloneMi);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (glb.lights) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst lightEntity = glb.lights.get(gltfNode);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (lightEntity) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tentity.addChild(lightEntity.clone());\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (glb.cameras) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst cameraEntity = glb.cameras.get(gltfNode);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (cameraEntity) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcameraEntity.camera.system.cloneComponent(cameraEntity, entity);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tif (attachedMi) {\\n\\t\\t\\t\\t\\t\\t\\t\\tentity.addComponent('render', Object.assign({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype: 'asset',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmeshInstances: attachedMi\\n\\t\\t\\t\\t\\t\\t\\t\\t}, options));\\n\\t\\t\\t\\t\\t\\t\\t\\tentity.render.assignAsset(renderAsset);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst children = node.children;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < children.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst childClone = cloneHierarchy(root, children[i], glb);\\n\\t\\t\\t\\t\\t\\t\\t\\tentity.addChild(childClone);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn entity;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst sceneClones = [];\\n\\t\\t\\t\\tfor (const scene of this.data.scenes){\\n\\t\\t\\t\\t\\t\\tsceneClones.push(cloneHierarchy(null, scene, this.data));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tskinnedMeshInstances.forEach((data)=>{\\n\\t\\t\\t\\t\\t\\tdata.meshInstance.skinInstance = SkinInstanceCache.createCachedSkinInstance(data.meshInstance.mesh.skin, data.rootBone, data.entity);\\n\\t\\t\\t\\t\\t\\tdata.meshInstance.node.render.rootBone = data.rootBone;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn GlbContainerResource.createSceneHierarchy(sceneClones, Entity);\\n\\t\\t}\\n\\t\\tgetMaterialVariants() {\\n\\t\\t\\t\\treturn this.data.variants ? Object.keys(this.data.variants) : [];\\n\\t\\t}\\n\\t\\tapplyMaterialVariant(entity, name) {\\n\\t\\t\\t\\tconst variant = name ? this.data.variants[name] : null;\\n\\t\\t\\t\\tif (variant === undefined) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst renders = entity.findComponents('render');\\n\\t\\t\\t\\tfor(let i = 0; i < renders.length; i++){\\n\\t\\t\\t\\t\\t\\tconst renderComponent = renders[i];\\n\\t\\t\\t\\t\\t\\tthis._applyMaterialVariant(variant, renderComponent.meshInstances);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tapplyMaterialVariantInstances(instances, name) {\\n\\t\\t\\t\\tconst variant = name ? this.data.variants[name] : null;\\n\\t\\t\\t\\tif (variant === undefined) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._applyMaterialVariant(variant, instances);\\n\\t\\t}\\n\\t\\t_applyMaterialVariant(variant, instances) {\\n\\t\\t\\t\\tinstances.forEach((instance)=>{\\n\\t\\t\\t\\t\\t\\tif (variant === null) {\\n\\t\\t\\t\\t\\t\\t\\t\\tinstance.material = this._defaultMaterial;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst meshVariants = this.data.meshVariants[instance.mesh.id];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (meshVariants) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinstance.material = this.data.materials[meshVariants[variant]];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tstatic createSceneHierarchy(sceneNodes, nodeType) {\\n\\t\\t\\t\\tlet root = null;\\n\\t\\t\\t\\tif (sceneNodes.length === 1) {\\n\\t\\t\\t\\t\\t\\troot = sceneNodes[0];\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\troot = new nodeType('SceneGroup');\\n\\t\\t\\t\\t\\t\\tfor (const scene of sceneNodes){\\n\\t\\t\\t\\t\\t\\t\\t\\troot.addChild(scene);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn root;\\n\\t\\t}\\n\\t\\tstatic createModel(glb, defaultMaterial) {\\n\\t\\t\\t\\tconst createMeshInstance = function(model, mesh, skins, skinInstances, materials, node, gltfNode) {\\n\\t\\t\\t\\t\\t\\tconst materialIndex = glb.meshDefaultMaterials[mesh.id];\\n\\t\\t\\t\\t\\t\\tconst material = materialIndex === undefined ? defaultMaterial : materials[materialIndex];\\n\\t\\t\\t\\t\\t\\tconst meshInstance = new MeshInstance(mesh, material, node);\\n\\t\\t\\t\\t\\t\\tif (mesh.morph) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst morphInstance = new MorphInstance(mesh.morph);\\n\\t\\t\\t\\t\\t\\t\\t\\tmeshInstance.morphInstance = morphInstance;\\n\\t\\t\\t\\t\\t\\t\\t\\tmodel.morphInstances.push(morphInstance);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (gltfNode.hasOwnProperty('skin')) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst skinIndex = gltfNode.skin;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst skin = skins[skinIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh.skin = skin;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst skinInstance = skinInstances[skinIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\tmeshInstance.skinInstance = skinInstance;\\n\\t\\t\\t\\t\\t\\t\\t\\tmodel.skinInstances.push(skinInstance);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tmodel.meshInstances.push(meshInstance);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst model = new Model();\\n\\t\\t\\t\\tconst skinInstances = [];\\n\\t\\t\\t\\tfor (const skin of glb.skins){\\n\\t\\t\\t\\t\\t\\tconst skinInstance = new SkinInstance(skin);\\n\\t\\t\\t\\t\\t\\tskinInstance.bones = skin.bones;\\n\\t\\t\\t\\t\\t\\tskinInstances.push(skinInstance);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tmodel.graph = GlbContainerResource.createSceneHierarchy(glb.scenes, GraphNode);\\n\\t\\t\\t\\tfor(let i = 0; i < glb.nodes.length; i++){\\n\\t\\t\\t\\t\\t\\tconst node = glb.nodes[i];\\n\\t\\t\\t\\t\\t\\tif (node.root === model.graph) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst gltfNode = glb.gltf.nodes[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (gltfNode.hasOwnProperty('mesh')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst meshGroup = glb.renders[gltfNode.mesh].meshes;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let mi = 0; mi < meshGroup.length; mi++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst mesh = meshGroup[mi];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (mesh) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcreateMeshInstance(model, mesh, glb.skins, skinInstances, glb.materials, node, gltfNode);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn model;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tconst registry = this._assets;\\n\\t\\t\\t\\tconst destroyAsset = function(asset) {\\n\\t\\t\\t\\t\\t\\tregistry.remove(asset);\\n\\t\\t\\t\\t\\t\\tasset.unload();\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst destroyAssets = function(assets) {\\n\\t\\t\\t\\t\\t\\tassets.forEach((asset)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tdestroyAsset(asset);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (this.animations) {\\n\\t\\t\\t\\t\\t\\tdestroyAssets(this.animations);\\n\\t\\t\\t\\t\\t\\tthis.animations = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.textures) {\\n\\t\\t\\t\\t\\t\\tdestroyAssets(this.textures);\\n\\t\\t\\t\\t\\t\\tthis.textures = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.materials) {\\n\\t\\t\\t\\t\\t\\tdestroyAssets(this.materials);\\n\\t\\t\\t\\t\\t\\tthis.materials = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.renders) {\\n\\t\\t\\t\\t\\t\\tdestroyAssets(this.renders);\\n\\t\\t\\t\\t\\t\\tthis.renders = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._model) {\\n\\t\\t\\t\\t\\t\\tdestroyAsset(this._model);\\n\\t\\t\\t\\t\\t\\tthis._model = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.data = null;\\n\\t\\t\\t\\tthis.assets = null;\\n\\t\\t}\\n\\t\\tconstructor(data, asset, assets, defaultMaterial){\\n\\t\\t\\t\\tconst createAsset = function(type, resource, index) {\\n\\t\\t\\t\\t\\t\\tconst subAsset = GlbContainerResource.createAsset(asset.name, type, resource, index);\\n\\t\\t\\t\\t\\t\\tassets.add(subAsset);\\n\\t\\t\\t\\t\\t\\treturn subAsset;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst renders = [];\\n\\t\\t\\t\\tfor(let i = 0; i < data.renders.length; ++i){\\n\\t\\t\\t\\t\\t\\trenders.push(createAsset('render', data.renders[i], i));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst materials = [];\\n\\t\\t\\t\\tfor(let i = 0; i < data.materials.length; ++i){\\n\\t\\t\\t\\t\\t\\tmaterials.push(createAsset('material', data.materials[i], i));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst animations = [];\\n\\t\\t\\t\\tfor(let i = 0; i < data.animations.length; ++i){\\n\\t\\t\\t\\t\\t\\tanimations.push(createAsset('animation', data.animations[i], i));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.data = data;\\n\\t\\t\\t\\tthis._model = null;\\n\\t\\t\\t\\tthis._assetName = asset.name;\\n\\t\\t\\t\\tthis._assets = assets;\\n\\t\\t\\t\\tthis._defaultMaterial = defaultMaterial;\\n\\t\\t\\t\\tthis.renders = renders;\\n\\t\\t\\t\\tthis.materials = materials;\\n\\t\\t\\t\\tthis.textures = data.textures;\\n\\t\\t\\t\\tthis.animations = animations;\\n\\t\\t}\\n}\\n\\nclass GlbContainerParser {\\n\\t\\t_getUrlWithoutParams(url) {\\n\\t\\t\\t\\treturn url.indexOf('?') >= 0 ? url.split('?')[0] : url;\\n\\t\\t}\\n\\t\\tload(url, callback, asset) {\\n\\t\\t\\t\\tAsset.fetchArrayBuffer(url.load, (err, result)=>{\\n\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tGlbParser.parse(this._getUrlWithoutParams(url.original), path.extractPath(url.load), result, this._device, asset.registry, asset.options, (err, result)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(null, new GlbContainerResource(result, asset, this._assets, this._defaultMaterial));\\n\\t\\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}\\n\\t\\t\\t\\t}, asset, this.maxRetries);\\n\\t\\t}\\n\\t\\topen(url, data, asset) {\\n\\t\\t\\t\\treturn data;\\n\\t\\t}\\n\\t\\tpatch(asset, assets) {}\\n\\t\\tconstructor(device, assets, maxRetries){\\n\\t\\t\\t\\tthis._device = device;\\n\\t\\t\\t\\tthis._assets = assets;\\n\\t\\t\\t\\tthis._defaultMaterial = GlbParser.createDefaultMaterial();\\n\\t\\t\\t\\tthis.maxRetries = maxRetries;\\n\\t\\t}\\n}\\n\\nclass ContainerHandler extends ResourceHandler {\\n\\t\\tset maxRetries(value) {\\n\\t\\t\\t\\tthis.glbContainerParser.maxRetries = value;\\n\\t\\t\\t\\tfor(const parser in this.parsers){\\n\\t\\t\\t\\t\\t\\tif (this.parsers.hasOwnProperty(parser)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.parsers[parser].maxRetries = value;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget maxRetries() {\\n\\t\\t\\t\\treturn this.glbContainerParser.maxRetries;\\n\\t\\t}\\n\\t\\t_getUrlWithoutParams(url) {\\n\\t\\t\\t\\treturn url.indexOf('?') >= 0 ? url.split('?')[0] : url;\\n\\t\\t}\\n\\t\\t_getParser(url) {\\n\\t\\t\\t\\tconst ext = url ? path.getExtension(this._getUrlWithoutParams(url)).toLowerCase().replace('.', '') : null;\\n\\t\\t\\t\\treturn this.parsers[ext] || this.glbContainerParser;\\n\\t\\t}\\n\\t\\tload(url, callback, asset) {\\n\\t\\t\\t\\tif (typeof url === 'string') {\\n\\t\\t\\t\\t\\t\\turl = {\\n\\t\\t\\t\\t\\t\\t\\t\\tload: url,\\n\\t\\t\\t\\t\\t\\t\\t\\toriginal: url\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._getParser(url.original).load(url, callback, asset);\\n\\t\\t}\\n\\t\\topen(url, data, asset) {\\n\\t\\t\\t\\treturn this._getParser(url).open(url, data, asset);\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tsuper(app, 'container');\\n\\t\\t\\t\\tthis.glbContainerParser = new GlbContainerParser(app.graphicsDevice, app.assets, 0);\\n\\t\\t\\t\\tthis.parsers = {};\\n\\t\\t}\\n}\\n\\nconst SH_C0 = 0.28209479177387814;\\nclass SplatCompressedIterator {\\n\\t\\tconstructor(gsplatData, p, r, s, c, sh){\\n\\t\\t\\t\\tconst unpackUnorm = (value, bits)=>{\\n\\t\\t\\t\\t\\t\\tconst t = (1 << bits) - 1;\\n\\t\\t\\t\\t\\t\\treturn (value & t) / t;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst unpack111011 = (result, value)=>{\\n\\t\\t\\t\\t\\t\\tresult.x = unpackUnorm(value >>> 21, 11);\\n\\t\\t\\t\\t\\t\\tresult.y = unpackUnorm(value >>> 11, 10);\\n\\t\\t\\t\\t\\t\\tresult.z = unpackUnorm(value, 11);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst unpack8888 = (result, value)=>{\\n\\t\\t\\t\\t\\t\\tresult.x = unpackUnorm(value >>> 24, 8);\\n\\t\\t\\t\\t\\t\\tresult.y = unpackUnorm(value >>> 16, 8);\\n\\t\\t\\t\\t\\t\\tresult.z = unpackUnorm(value >>> 8, 8);\\n\\t\\t\\t\\t\\t\\tresult.w = unpackUnorm(value, 8);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst unpackRot = (result, value)=>{\\n\\t\\t\\t\\t\\t\\tconst norm = Math.SQRT2;\\n\\t\\t\\t\\t\\t\\tconst a = (unpackUnorm(value >>> 20, 10) - 0.5) * norm;\\n\\t\\t\\t\\t\\t\\tconst b = (unpackUnorm(value >>> 10, 10) - 0.5) * norm;\\n\\t\\t\\t\\t\\t\\tconst c = (unpackUnorm(value, 10) - 0.5) * norm;\\n\\t\\t\\t\\t\\t\\tconst m = Math.sqrt(1.0 - (a * a + b * b + c * c));\\n\\t\\t\\t\\t\\t\\tswitch(value >>> 30){\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 0:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult.set(a, b, c, m);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 1:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult.set(m, b, c, a);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 2:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult.set(b, m, c, a);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\tcase 3:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tresult.set(b, c, m, a);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst lerp = (a, b, t)=>a * (1 - t) + b * t;\\n\\t\\t\\t\\tconst { chunkData, chunkSize, vertexData, shData0, shData1, shData2, shBands } = gsplatData;\\n\\t\\t\\t\\tconst shCoeffs = [\\n\\t\\t\\t\\t\\t\\t3,\\n\\t\\t\\t\\t\\t\\t8,\\n\\t\\t\\t\\t\\t\\t15\\n\\t\\t\\t\\t][shBands - 1];\\n\\t\\t\\t\\tthis.read = (i)=>{\\n\\t\\t\\t\\t\\t\\tconst ci = Math.floor(i / 256) * chunkSize;\\n\\t\\t\\t\\t\\t\\tif (p) {\\n\\t\\t\\t\\t\\t\\t\\t\\tunpack111011(p, vertexData[i * 4 + 0]);\\n\\t\\t\\t\\t\\t\\t\\t\\tp.x = lerp(chunkData[ci + 0], chunkData[ci + 3], p.x);\\n\\t\\t\\t\\t\\t\\t\\t\\tp.y = lerp(chunkData[ci + 1], chunkData[ci + 4], p.y);\\n\\t\\t\\t\\t\\t\\t\\t\\tp.z = lerp(chunkData[ci + 2], chunkData[ci + 5], p.z);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (r) {\\n\\t\\t\\t\\t\\t\\t\\t\\tunpackRot(r, vertexData[i * 4 + 1]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (s) {\\n\\t\\t\\t\\t\\t\\t\\t\\tunpack111011(s, vertexData[i * 4 + 2]);\\n\\t\\t\\t\\t\\t\\t\\t\\ts.x = lerp(chunkData[ci + 6], chunkData[ci + 9], s.x);\\n\\t\\t\\t\\t\\t\\t\\t\\ts.y = lerp(chunkData[ci + 7], chunkData[ci + 10], s.y);\\n\\t\\t\\t\\t\\t\\t\\t\\ts.z = lerp(chunkData[ci + 8], chunkData[ci + 11], s.z);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (c) {\\n\\t\\t\\t\\t\\t\\t\\t\\tunpack8888(c, vertexData[i * 4 + 3]);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (chunkSize > 12) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tc.x = lerp(chunkData[ci + 12], chunkData[ci + 15], c.x);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tc.y = lerp(chunkData[ci + 13], chunkData[ci + 16], c.y);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tc.z = lerp(chunkData[ci + 14], chunkData[ci + 17], c.z);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (sh && shBands > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst shData = [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshData0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshData1,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshData2\\n\\t\\t\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < 3; ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let k = 0; k < 15; ++k){\\n\\t\\t\\t\\t\\t\\t\\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\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t}\\n}\\nclass GSplatCompressedData {\\n\\t\\tcreateIter(p, r, s, c, sh) {\\n\\t\\t\\t\\treturn new SplatCompressedIterator(this, p, r, s, c, sh);\\n\\t\\t}\\n\\t\\tcalcAabb(result) {\\n\\t\\t\\t\\tconst { chunkData, numChunks, chunkSize } = this;\\n\\t\\t\\t\\tlet s = Math.exp(Math.max(chunkData[9], chunkData[10], chunkData[11]));\\n\\t\\t\\t\\tlet mx = chunkData[0] - s;\\n\\t\\t\\t\\tlet my = chunkData[1] - s;\\n\\t\\t\\t\\tlet mz = chunkData[2] - s;\\n\\t\\t\\t\\tlet Mx = chunkData[3] + s;\\n\\t\\t\\t\\tlet My = chunkData[4] + s;\\n\\t\\t\\t\\tlet Mz = chunkData[5] + s;\\n\\t\\t\\t\\tfor(let i = 1; i < numChunks; ++i){\\n\\t\\t\\t\\t\\t\\tconst off = i * chunkSize;\\n\\t\\t\\t\\t\\t\\ts = Math.exp(Math.max(chunkData[off + 9], chunkData[off + 10], chunkData[off + 11]));\\n\\t\\t\\t\\t\\t\\tmx = Math.min(mx, chunkData[off + 0] - s);\\n\\t\\t\\t\\t\\t\\tmy = Math.min(my, chunkData[off + 1] - s);\\n\\t\\t\\t\\t\\t\\tmz = Math.min(mz, chunkData[off + 2] - s);\\n\\t\\t\\t\\t\\t\\tMx = Math.max(Mx, chunkData[off + 3] + s);\\n\\t\\t\\t\\t\\t\\tMy = Math.max(My, chunkData[off + 4] + s);\\n\\t\\t\\t\\t\\t\\tMz = Math.max(Mz, chunkData[off + 5] + s);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tresult.center.set((mx + Mx) * 0.5, (my + My) * 0.5, (mz + Mz) * 0.5);\\n\\t\\t\\t\\tresult.halfExtents.set((Mx - mx) * 0.5, (My - my) * 0.5, (Mz - mz) * 0.5);\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tgetCenters() {\\n\\t\\t\\t\\tconst { vertexData, chunkData, numChunks, chunkSize } = this;\\n\\t\\t\\t\\tconst result = new Float32Array(this.numSplats * 3);\\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\\t\\tconst off = c * chunkSize;\\n\\t\\t\\t\\t\\t\\tmx = chunkData[off + 0];\\n\\t\\t\\t\\t\\t\\tmy = chunkData[off + 1];\\n\\t\\t\\t\\t\\t\\tmz = chunkData[off + 2];\\n\\t\\t\\t\\t\\t\\tMx = chunkData[off + 3];\\n\\t\\t\\t\\t\\t\\tMy = chunkData[off + 4];\\n\\t\\t\\t\\t\\t\\tMz = chunkData[off + 5];\\n\\t\\t\\t\\t\\t\\tconst end = Math.min(this.numSplats, (c + 1) * 256);\\n\\t\\t\\t\\t\\t\\tfor(let i = c * 256; i < end; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst p = vertexData[i * 4];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst px = (p >>> 21) / 2047;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst py = (p >>> 11 & 0x3ff) / 1023;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst pz = (p & 0x7ff) / 2047;\\n\\t\\t\\t\\t\\t\\t\\t\\tresult[i * 3 + 0] = (1 - px) * mx + px * Mx;\\n\\t\\t\\t\\t\\t\\t\\t\\tresult[i * 3 + 1] = (1 - py) * my + py * My;\\n\\t\\t\\t\\t\\t\\t\\t\\tresult[i * 3 + 2] = (1 - pz) * mz + pz * Mz;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tgetChunks(result) {\\n\\t\\t\\t\\tconst { chunkData, numChunks, chunkSize } = this;\\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\\t\\tconst off = c * chunkSize;\\n\\t\\t\\t\\t\\t\\tmx = chunkData[off + 0];\\n\\t\\t\\t\\t\\t\\tmy = chunkData[off + 1];\\n\\t\\t\\t\\t\\t\\tmz = chunkData[off + 2];\\n\\t\\t\\t\\t\\t\\tMx = chunkData[off + 3];\\n\\t\\t\\t\\t\\t\\tMy = chunkData[off + 4];\\n\\t\\t\\t\\t\\t\\tMz = chunkData[off + 5];\\n\\t\\t\\t\\t\\t\\tresult[c * 6 + 0] = mx;\\n\\t\\t\\t\\t\\t\\tresult[c * 6 + 1] = my;\\n\\t\\t\\t\\t\\t\\tresult[c * 6 + 2] = mz;\\n\\t\\t\\t\\t\\t\\tresult[c * 6 + 3] = Mx;\\n\\t\\t\\t\\t\\t\\tresult[c * 6 + 4] = My;\\n\\t\\t\\t\\t\\t\\tresult[c * 6 + 5] = Mz;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcalcFocalPoint(result) {\\n\\t\\t\\t\\tconst { chunkData, numChunks, chunkSize } = this;\\n\\t\\t\\t\\tresult.x = 0;\\n\\t\\t\\t\\tresult.y = 0;\\n\\t\\t\\t\\tresult.z = 0;\\n\\t\\t\\t\\tfor(let i = 0; i < numChunks; ++i){\\n\\t\\t\\t\\t\\t\\tconst off = i * chunkSize;\\n\\t\\t\\t\\t\\t\\tresult.x += chunkData[off + 0] + chunkData[off + 3];\\n\\t\\t\\t\\t\\t\\tresult.y += chunkData[off + 1] + chunkData[off + 4];\\n\\t\\t\\t\\t\\t\\tresult.z += chunkData[off + 2] + chunkData[off + 5];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tresult.mulScalar(0.5 / numChunks);\\n\\t\\t}\\n\\t\\tget isCompressed() {\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tget numChunks() {\\n\\t\\t\\t\\treturn Math.ceil(this.numSplats / 256);\\n\\t\\t}\\n\\t\\tget chunkSize() {\\n\\t\\t\\t\\treturn this.chunkData.length / this.numChunks;\\n\\t\\t}\\n\\t\\tdecompress() {\\n\\t\\t\\t\\tconst members = [\\n\\t\\t\\t\\t\\t\\t'x',\\n\\t\\t\\t\\t\\t\\t'y',\\n\\t\\t\\t\\t\\t\\t'z',\\n\\t\\t\\t\\t\\t\\t'f_dc_0',\\n\\t\\t\\t\\t\\t\\t'f_dc_1',\\n\\t\\t\\t\\t\\t\\t'f_dc_2',\\n\\t\\t\\t\\t\\t\\t'opacity',\\n\\t\\t\\t\\t\\t\\t'scale_0',\\n\\t\\t\\t\\t\\t\\t'scale_1',\\n\\t\\t\\t\\t\\t\\t'scale_2',\\n\\t\\t\\t\\t\\t\\t'rot_0',\\n\\t\\t\\t\\t\\t\\t'rot_1',\\n\\t\\t\\t\\t\\t\\t'rot_2',\\n\\t\\t\\t\\t\\t\\t'rot_3'\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tconst { shBands } = this;\\n\\t\\t\\t\\tif (shBands > 0) {\\n\\t\\t\\t\\t\\t\\tconst shMembers = [];\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < 45; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tshMembers.push(`f_rest_${i}`);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst location = Math.max(...[\\n\\t\\t\\t\\t\\t\\t\\t\\t'f_dc_0',\\n\\t\\t\\t\\t\\t\\t\\t\\t'f_dc_1',\\n\\t\\t\\t\\t\\t\\t\\t\\t'f_dc_2'\\n\\t\\t\\t\\t\\t\\t].map((name)=>members.indexOf(name)));\\n\\t\\t\\t\\t\\t\\tmembers.splice(location + 1, 0, ...shMembers);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst data = {};\\n\\t\\t\\t\\tmembers.forEach((name)=>{\\n\\t\\t\\t\\t\\t\\tdata[name] = new Float32Array(this.numSplats);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst p = new Vec3();\\n\\t\\t\\t\\tconst r = new Quat();\\n\\t\\t\\t\\tconst s = new Vec3();\\n\\t\\t\\t\\tconst c = new Vec4();\\n\\t\\t\\t\\tconst sh = shBands > 0 ? new Float32Array(45) : null;\\n\\t\\t\\t\\tconst iter = this.createIter(p, r, s, c, sh);\\n\\t\\t\\t\\tfor(let i = 0; i < this.numSplats; ++i){\\n\\t\\t\\t\\t\\t\\titer.read(i);\\n\\t\\t\\t\\t\\t\\tdata.x[i] = p.x;\\n\\t\\t\\t\\t\\t\\tdata.y[i] = p.y;\\n\\t\\t\\t\\t\\t\\tdata.z[i] = p.z;\\n\\t\\t\\t\\t\\t\\tdata.rot_1[i] = r.x;\\n\\t\\t\\t\\t\\t\\tdata.rot_2[i] = r.y;\\n\\t\\t\\t\\t\\t\\tdata.rot_3[i] = r.z;\\n\\t\\t\\t\\t\\t\\tdata.rot_0[i] = r.w;\\n\\t\\t\\t\\t\\t\\tdata.scale_0[i] = s.x;\\n\\t\\t\\t\\t\\t\\tdata.scale_1[i] = s.y;\\n\\t\\t\\t\\t\\t\\tdata.scale_2[i] = s.z;\\n\\t\\t\\t\\t\\t\\tdata.f_dc_0[i] = (c.x - 0.5) / SH_C0;\\n\\t\\t\\t\\t\\t\\tdata.f_dc_1[i] = (c.y - 0.5) / SH_C0;\\n\\t\\t\\t\\t\\t\\tdata.f_dc_2[i] = (c.z - 0.5) / SH_C0;\\n\\t\\t\\t\\t\\t\\tdata.opacity[i] = c.w <= 0 ? -40 : c.w >= 1 ? 40 : -Math.log(1 / c.w - 1);\\n\\t\\t\\t\\t\\t\\tif (sh) {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let c = 0; c < 45; ++c){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata[`f_rest_${c}`][i] = sh[c];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn new GSplatData([\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'vertex',\\n\\t\\t\\t\\t\\t\\t\\t\\tcount: this.numSplats,\\n\\t\\t\\t\\t\\t\\t\\t\\tproperties: members.map((name)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype: 'float',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbyteSize: 4,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstorage: data[name]\\n\\t\\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}\\n\\t\\t\\t\\t], this.comments);\\n\\t\\t}\\n}\\n\\nconst strideCopy = (target, targetStride, src, srcStride, numEntries)=>{\\n\\t\\tfor(let i = 0; i < numEntries; ++i){\\n\\t\\t\\t\\tfor(let j = 0; j < srcStride; ++j){\\n\\t\\t\\t\\t\\t\\ttarget[i * targetStride + j] = src[i * srcStride + j];\\n\\t\\t\\t\\t}\\n\\t\\t}\\n};\\nclass GSplatCompressedResource extends GSplatResourceBase {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tsuper.destroy();\\n\\t\\t}\\n\\t\\tconfigureMaterialDefines(defines) {\\n\\t\\t\\t\\tdefines.set('SH_BANDS', this.streams.textures.has('shTexture0') ? 3 : 0);\\n\\t\\t}\\n\\t\\tevalChunkTextureSize(numChunks) {\\n\\t\\t\\t\\tconst width = Math.ceil(Math.sqrt(numChunks));\\n\\t\\t\\t\\tconst height = Math.ceil(numChunks / width);\\n\\t\\t\\t\\treturn new Vec2(width * 5, height);\\n\\t\\t}\\n\\t\\tconstructor(device, gsplatData){\\n\\t\\t\\t\\tsuper(device, gsplatData);\\n\\t\\t\\t\\tconst { chunkData, chunkSize, numChunks, numSplats, vertexData, shBands } = gsplatData;\\n\\t\\t\\t\\tthis.chunks = new Float32Array(numChunks * 6);\\n\\t\\t\\t\\tgsplatData.getChunks(this.chunks);\\n\\t\\t\\t\\tconst formatStreams = [\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'packedTexture',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32U\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tif (shBands > 0) {\\n\\t\\t\\t\\t\\t\\tformatStreams.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'shTexture0',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32U\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tformatStreams.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'shTexture1',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32U\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tformatStreams.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'shTexture2',\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA32U\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._format = new GSplatFormat(device, formatStreams, {\\n\\t\\t\\t\\t\\t\\treadGLSL: '#include \\\"gsplatCompressedVS\\\"',\\n\\t\\t\\t\\t\\t\\treadWGSL: '#include \\\"gsplatCompressedVS\\\"'\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.streams.init(this.format, numSplats);\\n\\t\\t\\t\\tconst packedTexture = this.streams.getTexture('packedTexture');\\n\\t\\t\\t\\tconst packedData = packedTexture.lock();\\n\\t\\t\\t\\tpackedData.set(vertexData);\\n\\t\\t\\t\\tpackedTexture.unlock();\\n\\t\\t\\t\\tif (shBands > 0) {\\n\\t\\t\\t\\t\\t\\tconst shTexture0 = this.streams.getTexture('shTexture0');\\n\\t\\t\\t\\t\\t\\tconst shTexture1 = this.streams.getTexture('shTexture1');\\n\\t\\t\\t\\t\\t\\tconst shTexture2 = this.streams.getTexture('shTexture2');\\n\\t\\t\\t\\t\\t\\tconst sh0Data = shTexture0.lock();\\n\\t\\t\\t\\t\\t\\tsh0Data.set(new Uint32Array(gsplatData.shData0.buffer));\\n\\t\\t\\t\\t\\t\\tshTexture0.unlock();\\n\\t\\t\\t\\t\\t\\tconst sh1Data = shTexture1.lock();\\n\\t\\t\\t\\t\\t\\tsh1Data.set(new Uint32Array(gsplatData.shData1.buffer));\\n\\t\\t\\t\\t\\t\\tshTexture1.unlock();\\n\\t\\t\\t\\t\\t\\tconst sh2Data = shTexture2.lock();\\n\\t\\t\\t\\t\\t\\tsh2Data.set(new Uint32Array(gsplatData.shData2.buffer));\\n\\t\\t\\t\\t\\t\\tshTexture2.unlock();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst chunkTextureSize = this.evalChunkTextureSize(numChunks);\\n\\t\\t\\t\\tconst chunkTexture = this.streams.createTexture('chunkTexture', PIXELFORMAT_RGBA32F, chunkTextureSize);\\n\\t\\t\\t\\tthis.streams.textures.set('chunkTexture', chunkTexture);\\n\\t\\t\\t\\tconst chunkTextureData = chunkTexture.lock();\\n\\t\\t\\t\\tstrideCopy(chunkTextureData, 20, chunkData, chunkSize, numChunks);\\n\\t\\t\\t\\tif (chunkSize === 12) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < numChunks; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tchunkTextureData[i * 20 + 15] = 1;\\n\\t\\t\\t\\t\\t\\t\\t\\tchunkTextureData[i * 20 + 16] = 1;\\n\\t\\t\\t\\t\\t\\t\\t\\tchunkTextureData[i * 20 + 17] = 1;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tchunkTexture.unlock();\\n\\t\\t}\\n}\\n\\nconst magicBytes = new Uint8Array([\\n\\t\\t112,\\n\\t\\t108,\\n\\t\\t121,\\n\\t\\t10\\n]);\\nconst endHeaderBytes = new Uint8Array([\\n\\t\\t10,\\n\\t\\t101,\\n\\t\\t110,\\n\\t\\t100,\\n\\t\\t95,\\n\\t\\t104,\\n\\t\\t101,\\n\\t\\t97,\\n\\t\\t100,\\n\\t\\t101,\\n\\t\\t114,\\n\\t\\t10\\n]);\\nconst dataTypeMap = new Map([\\n\\t\\t[\\n\\t\\t\\t\\t'char',\\n\\t\\t\\t\\tInt8Array\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'uchar',\\n\\t\\t\\t\\tUint8Array\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'short',\\n\\t\\t\\t\\tInt16Array\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'ushort',\\n\\t\\t\\t\\tUint16Array\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'int',\\n\\t\\t\\t\\tInt32Array\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'uint',\\n\\t\\t\\t\\tUint32Array\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'float',\\n\\t\\t\\t\\tFloat32Array\\n\\t\\t],\\n\\t\\t[\\n\\t\\t\\t\\t'double',\\n\\t\\t\\t\\tFloat64Array\\n\\t\\t]\\n]);\\nclass StreamBuf {\\n\\t\\tasync read() {\\n\\t\\t\\t\\tconst { value, done } = await this.reader.read();\\n\\t\\t\\t\\tif (done) {\\n\\t\\t\\t\\t\\t\\tthrow new Error('Stream finished before end of header');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.push(value);\\n\\t\\t\\t\\tthis.progressFunc?.(value.byteLength);\\n\\t\\t}\\n\\t\\tpush(data) {\\n\\t\\t\\t\\tif (!this.data) {\\n\\t\\t\\t\\t\\t\\tthis.data = data;\\n\\t\\t\\t\\t\\t\\tthis.view = new DataView(this.data.buffer);\\n\\t\\t\\t\\t\\t\\tthis.tail = data.length;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst remaining = this.tail - this.head;\\n\\t\\t\\t\\t\\t\\tconst newSize = remaining + data.length;\\n\\t\\t\\t\\t\\t\\tif (this.data.length >= newSize) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.head > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.data.copyWithin(0, this.head, this.tail);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.data.set(data, remaining);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.head = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.tail = newSize;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.data.set(data, this.tail);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.tail += data.length;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst tmp = new Uint8Array(newSize);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.head > 0 || this.tail < this.data.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttmp.set(this.data.subarray(this.head, this.tail), 0);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttmp.set(this.data, 0);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\ttmp.set(data, remaining);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.data = tmp;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.view = new DataView(this.data.buffer);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.head = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.tail = newSize;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcompact() {\\n\\t\\t\\t\\tif (this.head > 0) {\\n\\t\\t\\t\\t\\t\\tthis.data.copyWithin(0, this.head, this.tail);\\n\\t\\t\\t\\t\\t\\tthis.tail -= this.head;\\n\\t\\t\\t\\t\\t\\tthis.head = 0;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget remaining() {\\n\\t\\t\\t\\treturn this.tail - this.head;\\n\\t\\t}\\n\\t\\tgetInt8() {\\n\\t\\t\\t\\tconst result = this.view.getInt8(this.head);\\n\\t\\t\\t\\tthis.head++;\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tgetUint8() {\\n\\t\\t\\t\\tconst result = this.view.getUint8(this.head);\\n\\t\\t\\t\\tthis.head++;\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tgetInt16() {\\n\\t\\t\\t\\tconst result = this.view.getInt16(this.head, true);\\n\\t\\t\\t\\tthis.head += 2;\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tgetUint16() {\\n\\t\\t\\t\\tconst result = this.view.getUint16(this.head, true);\\n\\t\\t\\t\\tthis.head += 2;\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tgetInt32() {\\n\\t\\t\\t\\tconst result = this.view.getInt32(this.head, true);\\n\\t\\t\\t\\tthis.head += 4;\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tgetUint32() {\\n\\t\\t\\t\\tconst result = this.view.getUint32(this.head, true);\\n\\t\\t\\t\\tthis.head += 4;\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tgetFloat32() {\\n\\t\\t\\t\\tconst result = this.view.getFloat32(this.head, true);\\n\\t\\t\\t\\tthis.head += 4;\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tgetFloat64() {\\n\\t\\t\\t\\tconst result = this.view.getFloat64(this.head, true);\\n\\t\\t\\t\\tthis.head += 8;\\n\\t\\t\\t\\treturn result;\\n\\t\\t}\\n\\t\\tconstructor(reader, progressFunc){\\n\\t\\t\\t\\tthis.head = 0;\\n\\t\\t\\t\\tthis.tail = 0;\\n\\t\\t\\t\\tthis.reader = reader;\\n\\t\\t\\t\\tthis.progressFunc = progressFunc;\\n\\t\\t}\\n}\\nconst parseHeader = (lines)=>{\\n\\t\\tconst elements = [];\\n\\t\\tconst comments = [];\\n\\t\\tlet format;\\n\\t\\tfor(let i = 1; i < lines.length; ++i){\\n\\t\\t\\t\\tconst words = lines[i].split(' ');\\n\\t\\t\\t\\tswitch(words[0]){\\n\\t\\t\\t\\t\\t\\tcase 'comment':\\n\\t\\t\\t\\t\\t\\t\\t\\tcomments.push(words.slice(1).join(' '));\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 'format':\\n\\t\\t\\t\\t\\t\\t\\t\\tformat = words[1];\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 'element':\\n\\t\\t\\t\\t\\t\\t\\t\\telements.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tname: words[1],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcount: parseInt(words[2], 10),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tproperties: []\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 'property':\\n\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!dataTypeMap.has(words[1])) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthrow new Error(`Unrecognized property data type '${words[1]}' in ply header`);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst element = elements[elements.length - 1];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\telement.properties.push({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttype: words[1],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tname: words[2],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstorage: null,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbyteSize: dataTypeMap.get(words[1]).BYTES_PER_ELEMENT\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\t\\t\\tthrow new Error(`Unrecognized header value '${words[0]}' in ply header`);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn {\\n\\t\\t\\t\\telements,\\n\\t\\t\\t\\tformat,\\n\\t\\t\\t\\tcomments\\n\\t\\t};\\n};\\nconst isCompressedPly = (elements)=>{\\n\\t\\tconst chunkProperties = [\\n\\t\\t\\t\\t'min_x',\\n\\t\\t\\t\\t'min_y',\\n\\t\\t\\t\\t'min_z',\\n\\t\\t\\t\\t'max_x',\\n\\t\\t\\t\\t'max_y',\\n\\t\\t\\t\\t'max_z',\\n\\t\\t\\t\\t'min_scale_x',\\n\\t\\t\\t\\t'min_scale_y',\\n\\t\\t\\t\\t'min_scale_z',\\n\\t\\t\\t\\t'max_scale_x',\\n\\t\\t\\t\\t'max_scale_y',\\n\\t\\t\\t\\t'max_scale_z',\\n\\t\\t\\t\\t'min_r',\\n\\t\\t\\t\\t'min_g',\\n\\t\\t\\t\\t'min_b',\\n\\t\\t\\t\\t'max_r',\\n\\t\\t\\t\\t'max_g',\\n\\t\\t\\t\\t'max_b'\\n\\t\\t];\\n\\t\\tconst vertexProperties = [\\n\\t\\t\\t\\t'packed_position',\\n\\t\\t\\t\\t'packed_rotation',\\n\\t\\t\\t\\t'packed_scale',\\n\\t\\t\\t\\t'packed_color'\\n\\t\\t];\\n\\t\\tconst shProperties = new Array(45).fill('').map((_, i)=>`f_rest_${i}`);\\n\\t\\tconst hasBaseElements = ()=>{\\n\\t\\t\\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\\t};\\n\\t\\tconst hasSHElements = ()=>{\\n\\t\\t\\t\\treturn elements[2].name === 'sh' && [\\n\\t\\t\\t\\t\\t\\t9,\\n\\t\\t\\t\\t\\t\\t24,\\n\\t\\t\\t\\t\\t\\t45\\n\\t\\t\\t\\t].indexOf(elements[2].properties.length) !== -1 && elements[2].properties.every((p, i)=>p.name === shProperties[i] && p.type === 'uchar');\\n\\t\\t};\\n\\t\\treturn elements.length === 2 && hasBaseElements() || elements.length === 3 && hasBaseElements() && hasSHElements();\\n};\\nconst isFloatPly = (elements)=>{\\n\\t\\treturn elements.length === 1 && elements[0].name === 'vertex' && elements[0].properties.every((p)=>p.type === 'float');\\n};\\nconst readCompressedPly = async (streamBuf, elements, comments)=>{\\n\\t\\tconst result = new GSplatCompressedData();\\n\\t\\tresult.comments = comments;\\n\\t\\tconst numChunks = elements[0].count;\\n\\t\\tconst numChunkProperties = elements[0].properties.length;\\n\\t\\tconst numVertices = elements[1].count;\\n\\t\\tconst evalStorageSize = (count)=>{\\n\\t\\t\\t\\tconst width = Math.ceil(Math.sqrt(count));\\n\\t\\t\\t\\tconst height = Math.ceil(count / width);\\n\\t\\t\\t\\treturn width * height;\\n\\t\\t};\\n\\t\\tconst storageSize = evalStorageSize(numVertices);\\n\\t\\tresult.numSplats = numVertices;\\n\\t\\tresult.chunkData = new Float32Array(numChunks * numChunkProperties);\\n\\t\\tresult.vertexData = new Uint32Array(storageSize * 4);\\n\\t\\tconst read = async (buffer, length)=>{\\n\\t\\t\\t\\tconst target = new Uint8Array(buffer);\\n\\t\\t\\t\\tlet cursor = 0;\\n\\t\\t\\t\\twhile(cursor < length){\\n\\t\\t\\t\\t\\t\\twhile(streamBuf.remaining === 0){\\n\\t\\t\\t\\t\\t\\t\\t\\tawait streamBuf.read();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst toCopy = Math.min(length - cursor, streamBuf.remaining);\\n\\t\\t\\t\\t\\t\\tconst src = streamBuf.data;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < toCopy; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\ttarget[cursor++] = src[streamBuf.head++];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t};\\n\\t\\tawait read(result.chunkData.buffer, numChunks * numChunkProperties * 4);\\n\\t\\tawait read(result.vertexData.buffer, numVertices * 4 * 4);\\n\\t\\tif (elements.length === 3) {\\n\\t\\t\\t\\tconst texStorageSize = storageSize * 16;\\n\\t\\t\\t\\tconst shData0 = new Uint8Array(texStorageSize);\\n\\t\\t\\t\\tconst shData1 = new Uint8Array(texStorageSize);\\n\\t\\t\\t\\tconst shData2 = new Uint8Array(texStorageSize);\\n\\t\\t\\t\\tconst chunkSize = 1024;\\n\\t\\t\\t\\tconst srcCoeffs = elements[2].properties.length / 3;\\n\\t\\t\\t\\tconst tmpBuf = new Uint8Array(chunkSize * srcCoeffs * 3);\\n\\t\\t\\t\\tfor(let i = 0; i < result.numSplats; i += chunkSize){\\n\\t\\t\\t\\t\\t\\tconst toRead = Math.min(chunkSize, result.numSplats - i);\\n\\t\\t\\t\\t\\t\\tawait read(tmpBuf.buffer, toRead * srcCoeffs * 3);\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j < toRead; ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let k = 0; k < 15; ++k){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst tidx = (i + j) * 16 + k;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (k < srcCoeffs) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshData0[tidx] = tmpBuf[(j * 3 + 0) * srcCoeffs + k];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshData1[tidx] = tmpBuf[(j * 3 + 1) * srcCoeffs + k];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshData2[tidx] = tmpBuf[(j * 3 + 2) * srcCoeffs + k];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshData0[tidx] = 127;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshData1[tidx] = 127;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tshData2[tidx] = 127;\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tresult.shData0 = shData0;\\n\\t\\t\\t\\tresult.shData1 = shData1;\\n\\t\\t\\t\\tresult.shData2 = shData2;\\n\\t\\t\\t\\tresult.shBands = ({\\n\\t\\t\\t\\t\\t\\t3: 1,\\n\\t\\t\\t\\t\\t\\t8: 2,\\n\\t\\t\\t\\t\\t\\t15: 3\\n\\t\\t\\t\\t})[srcCoeffs];\\n\\t\\t} else {\\n\\t\\t\\t\\tresult.shBands = 0;\\n\\t\\t}\\n\\t\\treturn result;\\n};\\nconst readFloatPly = async (streamBuf, elements, comments)=>{\\n\\t\\tconst element = elements[0];\\n\\t\\tconst properties = element.properties;\\n\\t\\tconst numProperties = properties.length;\\n\\t\\tconst storage = properties.map((p)=>p.storage);\\n\\t\\tconst inputSize = properties.reduce((a, p)=>a + p.byteSize, 0);\\n\\t\\tlet vertexIdx = 0;\\n\\t\\tlet floatData;\\n\\t\\tconst checkFloatData = ()=>{\\n\\t\\t\\t\\tconst buffer = streamBuf.data.buffer;\\n\\t\\t\\t\\tif (floatData?.buffer !== buffer) {\\n\\t\\t\\t\\t\\t\\tfloatData = new Float32Array(buffer, 0, buffer.byteLength / 4);\\n\\t\\t\\t\\t}\\n\\t\\t};\\n\\t\\tcheckFloatData();\\n\\t\\twhile(vertexIdx < element.count){\\n\\t\\t\\t\\twhile(streamBuf.remaining < inputSize){\\n\\t\\t\\t\\t\\t\\tawait streamBuf.read();\\n\\t\\t\\t\\t\\t\\tcheckFloatData();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst toRead = Math.min(element.count - vertexIdx, Math.floor(streamBuf.remaining / inputSize));\\n\\t\\t\\t\\tfor(let j = 0; j < numProperties; ++j){\\n\\t\\t\\t\\t\\t\\tconst s = storage[j];\\n\\t\\t\\t\\t\\t\\tfor(let n = 0; n < toRead; ++n){\\n\\t\\t\\t\\t\\t\\t\\t\\ts[n + vertexIdx] = floatData[n * numProperties + j];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tvertexIdx += toRead;\\n\\t\\t\\t\\tstreamBuf.head += toRead * inputSize;\\n\\t\\t}\\n\\t\\treturn new GSplatData(elements, comments);\\n};\\nconst readGeneralPly = async (streamBuf, elements, comments)=>{\\n\\t\\tfor(let i = 0; i < elements.length; ++i){\\n\\t\\t\\t\\tconst element = elements[i];\\n\\t\\t\\t\\tconst inputSize = element.properties.reduce((a, p)=>a + p.byteSize, 0);\\n\\t\\t\\t\\tconst propertyParsingFunctions = element.properties.map((p)=>{\\n\\t\\t\\t\\t\\t\\tif (p.storage) {\\n\\t\\t\\t\\t\\t\\t\\t\\tswitch(p.type){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase 'char':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn (streamBuf, c)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tp.storage[c] = streamBuf.getInt8();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase 'uchar':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn (streamBuf, c)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tp.storage[c] = streamBuf.getUint8();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase 'short':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn (streamBuf, c)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tp.storage[c] = streamBuf.getInt16();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase 'ushort':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn (streamBuf, c)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tp.storage[c] = streamBuf.getUint16();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase 'int':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn (streamBuf, c)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tp.storage[c] = streamBuf.getInt32();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase 'uint':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn (streamBuf, c)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tp.storage[c] = streamBuf.getUint32();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase 'float':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn (streamBuf, c)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tp.storage[c] = streamBuf.getFloat32();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase 'double':\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn (streamBuf, c)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tp.storage[c] = streamBuf.getFloat64();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdefault:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthrow new Error(`Unsupported property data type '${p.type}' in ply header`);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn (streamBuf)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstreamBuf.head += p.byteSize;\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tlet c = 0;\\n\\t\\t\\t\\twhile(c < element.count){\\n\\t\\t\\t\\t\\t\\twhile(streamBuf.remaining < inputSize){\\n\\t\\t\\t\\t\\t\\t\\t\\tawait streamBuf.read();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst toRead = Math.min(element.count - c, Math.floor(streamBuf.remaining / inputSize));\\n\\t\\t\\t\\t\\t\\tfor(let n = 0; n < toRead; ++n){\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < element.properties.length; ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpropertyParsingFunctions[j](streamBuf, c);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tc++;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\treturn new GSplatData(elements, comments);\\n};\\nconst readPly = async (reader, propertyFilter = null, progressFunc = null)=>{\\n\\t\\tconst find = (buf, search)=>{\\n\\t\\t\\t\\tconst endIndex = buf.length - search.length;\\n\\t\\t\\t\\tlet i, j;\\n\\t\\t\\t\\tfor(i = 0; i <= endIndex; ++i){\\n\\t\\t\\t\\t\\t\\tfor(j = 0; j < search.length; ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (buf[i + j] !== search[j]) {\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tif (j === search.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn i;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn -1;\\n\\t\\t};\\n\\t\\tconst startsWith = (a, b)=>{\\n\\t\\t\\t\\tif (a.length < b.length) {\\n\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < b.length; ++i){\\n\\t\\t\\t\\t\\t\\tif (a[i] !== b[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn true;\\n\\t\\t};\\n\\t\\tconst streamBuf = new StreamBuf(reader, progressFunc);\\n\\t\\tlet headerLength;\\n\\t\\twhile(true){\\n\\t\\t\\t\\tawait streamBuf.read();\\n\\t\\t\\t\\tif (streamBuf.tail >= magicBytes.length && !startsWith(streamBuf.data, magicBytes)) {\\n\\t\\t\\t\\t\\t\\tthrow new Error('Invalid ply header');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\theaderLength = find(streamBuf.data, endHeaderBytes);\\n\\t\\t\\t\\tif (headerLength !== -1) {\\n\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconst lines = new TextDecoder('ascii').decode(streamBuf.data.subarray(0, headerLength)).split('\\\\n');\\n\\t\\tconst { elements, format, comments } = parseHeader(lines);\\n\\t\\tif (format !== 'binary_little_endian') {\\n\\t\\t\\t\\tthrow new Error('Unsupported ply format');\\n\\t\\t}\\n\\t\\tstreamBuf.head = headerLength + endHeaderBytes.length;\\n\\t\\tstreamBuf.compact();\\n\\t\\tconst readData = async ()=>{\\n\\t\\t\\t\\tif (isCompressedPly(elements)) {\\n\\t\\t\\t\\t\\t\\treturn await readCompressedPly(streamBuf, elements, comments);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\telements.forEach((e)=>{\\n\\t\\t\\t\\t\\t\\te.properties.forEach((p)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst storageType = dataTypeMap.get(p.type);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (storageType) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst storage = !propertyFilter || propertyFilter(p.name) ? new storageType(e.count) : null;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tp.storage = storage;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (isFloatPly(elements)) {\\n\\t\\t\\t\\t\\t\\treturn await readFloatPly(streamBuf, elements, comments);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn await readGeneralPly(streamBuf, elements, comments);\\n\\t\\t};\\n\\t\\treturn await readData();\\n};\\nconst defaultElementFilter = (val)=>true;\\nclass PlyParser {\\n\\t\\tasync load(url, callback, asset) {\\n\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\tconst response = await (asset.file?.contents ?? fetch(url.load));\\n\\t\\t\\t\\t\\t\\tif (!response || !response.body) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback('Error loading resource', null);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst totalLength = parseInt(response.headers.get('content-length') ?? '0', 10);\\n\\t\\t\\t\\t\\t\\t\\t\\tlet totalReceived = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst data = await readPly(response.body.getReader(), asset.data.elementFilter ?? defaultElementFilter, (bytes)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttotalReceived += bytes;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (asset) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tasset.fire('progress', totalReceived, totalLength);\\n\\t\\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\\tasset.fire('load:data', data);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!data.isCompressed) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (asset.data.reorder ?? true) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdata.reorderData();\\n\\t\\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 resource = data.isCompressed && !asset.data.decompress ? new GSplatCompressedResource(this.app.graphicsDevice, data) : new GSplatResource(this.app.graphicsDevice, data.isCompressed ? data.decompress() : data);\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(null, resource);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} catch (err) {\\n\\t\\t\\t\\t\\t\\tcallback(err, null);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\topen(url, data) {\\n\\t\\t\\t\\treturn data;\\n\\t\\t}\\n\\t\\tconstructor(app, maxRetries){\\n\\t\\t\\t\\tthis.app = app;\\n\\t\\t\\t\\tthis.maxRetries = maxRetries;\\n\\t\\t}\\n}\\n\\nconst combineProgress = (target, assets)=>{\\n\\t\\tconst map = new Map();\\n\\t\\tconst fire = ()=>{\\n\\t\\t\\t\\tlet loaded = 0;\\n\\t\\t\\t\\tlet total = 0;\\n\\t\\t\\t\\tmap.forEach((value)=>{\\n\\t\\t\\t\\t\\t\\tloaded += value.loaded;\\n\\t\\t\\t\\t\\t\\ttotal += value.total;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\ttarget.fire('progress', loaded, total);\\n\\t\\t};\\n\\t\\tassets.forEach((asset)=>{\\n\\t\\t\\t\\tconst progress = (loaded, total)=>{\\n\\t\\t\\t\\t\\t\\tmap.set(asset, {\\n\\t\\t\\t\\t\\t\\t\\t\\tloaded,\\n\\t\\t\\t\\t\\t\\t\\t\\ttotal\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tfire();\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst done = ()=>{\\n\\t\\t\\t\\t\\t\\tasset.off('progress', progress);\\n\\t\\t\\t\\t\\t\\tasset.off('load', done);\\n\\t\\t\\t\\t\\t\\tasset.off('error', done);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tasset.on('progress', progress);\\n\\t\\t\\t\\tasset.on('load', done);\\n\\t\\t\\t\\tasset.on('error', done);\\n\\t\\t});\\n};\\nconst upgradeMeta = (meta)=>{\\n\\t\\tconst result = {\\n\\t\\t\\t\\tversion: 1,\\n\\t\\t\\t\\tcount: meta.means.shape[0],\\n\\t\\t\\t\\tmeans: {\\n\\t\\t\\t\\t\\t\\tmins: meta.means.mins,\\n\\t\\t\\t\\t\\t\\tmaxs: meta.means.maxs,\\n\\t\\t\\t\\t\\t\\tfiles: meta.means.files\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\tscales: {\\n\\t\\t\\t\\t\\t\\tmins: meta.scales.mins,\\n\\t\\t\\t\\t\\t\\tmaxs: meta.scales.maxs,\\n\\t\\t\\t\\t\\t\\tfiles: meta.scales.files\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\tquats: {\\n\\t\\t\\t\\t\\t\\tfiles: meta.quats.files\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\tsh0: {\\n\\t\\t\\t\\t\\t\\tmins: meta.sh0.mins,\\n\\t\\t\\t\\t\\t\\tmaxs: meta.sh0.maxs,\\n\\t\\t\\t\\t\\t\\tfiles: meta.sh0.files\\n\\t\\t\\t\\t}\\n\\t\\t};\\n\\t\\tif (meta.shN) {\\n\\t\\t\\t\\tresult.shN = {\\n\\t\\t\\t\\t\\t\\tmins: meta.shN.mins,\\n\\t\\t\\t\\t\\t\\tmaxs: meta.shN.maxs,\\n\\t\\t\\t\\t\\t\\tfiles: meta.shN.files\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\treturn result;\\n};\\nclass SogParser {\\n\\t\\t_shouldAbort(asset, unloaded) {\\n\\t\\t\\t\\tif (unloaded || !this.app.assets.get(asset.id)) return true;\\n\\t\\t\\t\\tif (!this.app?.graphicsDevice || this.app.graphicsDevice._destroyed) return true;\\n\\t\\t\\t\\treturn false;\\n\\t\\t}\\n\\t\\tasync loadTextures(url, callback, asset, meta) {\\n\\t\\t\\t\\tif (meta.version !== 2) {\\n\\t\\t\\t\\t\\t\\tmeta = upgradeMeta(meta);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst { assets } = this.app;\\n\\t\\t\\t\\tconst subs = [\\n\\t\\t\\t\\t\\t\\t'means',\\n\\t\\t\\t\\t\\t\\t'quats',\\n\\t\\t\\t\\t\\t\\t'scales',\\n\\t\\t\\t\\t\\t\\t'sh0',\\n\\t\\t\\t\\t\\t\\t'shN'\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tconst textures = {};\\n\\t\\t\\t\\tconst promises = [];\\n\\t\\t\\t\\tsubs.forEach((sub)=>{\\n\\t\\t\\t\\t\\t\\tconst files = meta[sub]?.files ?? [];\\n\\t\\t\\t\\t\\t\\ttextures[sub] = files.map((filename)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst texture = new Asset(filename, 'texture', {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\turl: asset.options?.mapUrl?.(filename) ?? new URL(filename, new URL(url.load, window.location.href).toString()).toString(),\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfilename\\n\\t\\t\\t\\t\\t\\t\\t\\t}, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmipmaps: false\\n\\t\\t\\t\\t\\t\\t\\t\\t}, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcrossOrigin: 'anonymous'\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tconst promise = new Promise((resolve, reject)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture.on('load', ()=>resolve(null));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture.on('error', (err)=>reject(err));\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tassets.add(texture);\\n\\t\\t\\t\\t\\t\\t\\t\\tpromises.push(promise);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn texture;\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst textureAssets = subs.map((sub)=>textures[sub]).flat();\\n\\t\\t\\t\\tlet unloaded = false;\\n\\t\\t\\t\\tasset.once('unload', ()=>{\\n\\t\\t\\t\\t\\t\\tunloaded = true;\\n\\t\\t\\t\\t\\t\\ttextureAssets.forEach((t)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tassets.remove(t);\\n\\t\\t\\t\\t\\t\\t\\t\\tt.unload();\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tcombineProgress(asset, textureAssets);\\n\\t\\t\\t\\ttextureAssets.forEach((t)=>assets.load(t));\\n\\t\\t\\t\\tawait Promise.allSettled(promises);\\n\\t\\t\\t\\tif (this._shouldAbort(asset, unloaded)) {\\n\\t\\t\\t\\t\\t\\ttextureAssets.forEach((t)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tassets.remove(t);\\n\\t\\t\\t\\t\\t\\t\\t\\tt.unload();\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tcallback(null, null);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst data = new GSplatSogData();\\n\\t\\t\\t\\tdata.url = url.original;\\n\\t\\t\\t\\tdata.meta = meta;\\n\\t\\t\\t\\tdata.numSplats = meta.count;\\n\\t\\t\\t\\tdata.means_l = textures.means[0].resource;\\n\\t\\t\\t\\tdata.means_u = textures.means[1].resource;\\n\\t\\t\\t\\tdata.quats = textures.quats[0].resource;\\n\\t\\t\\t\\tdata.scales = textures.scales[0].resource;\\n\\t\\t\\t\\tdata.sh0 = textures.sh0[0].resource;\\n\\t\\t\\t\\tdata.sh_centroids = textures.shN?.[0]?.resource;\\n\\t\\t\\t\\tdata.sh_labels = textures.shN?.[1]?.resource;\\n\\t\\t\\t\\tdata.shBands = GSplatSogData.calcBands(data.sh_centroids?.width);\\n\\t\\t\\t\\tconst decompress = asset.data?.decompress;\\n\\t\\t\\t\\tconst minimalMemory = asset.options?.minimalMemory ?? false;\\n\\t\\t\\t\\tdata.minimalMemory = minimalMemory;\\n\\t\\t\\t\\tif (!decompress) {\\n\\t\\t\\t\\t\\t\\tif (this._shouldAbort(asset, unloaded)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdata.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(null, null);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tawait data.prepareGpuData();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._shouldAbort(asset, unloaded)) {\\n\\t\\t\\t\\t\\t\\tdata.destroy();\\n\\t\\t\\t\\t\\t\\tcallback(null, null);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst resource = decompress ? new GSplatResource(this.app.graphicsDevice, await data.decompress()) : new GSplatSogResource(this.app.graphicsDevice, data);\\n\\t\\t\\t\\tif (this._shouldAbort(asset, unloaded)) {\\n\\t\\t\\t\\t\\t\\tresource.destroy();\\n\\t\\t\\t\\t\\t\\tcallback(null, null);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcallback(null, resource);\\n\\t\\t}\\n\\t\\tload(url, callback, asset) {\\n\\t\\t\\t\\tif (asset.data?.means) {\\n\\t\\t\\t\\t\\t\\tthis.loadTextures(url, callback, asset, asset.data);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (typeof url === 'string') {\\n\\t\\t\\t\\t\\t\\t\\t\\turl = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tload: url,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toriginal: url\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst options = {\\n\\t\\t\\t\\t\\t\\t\\t\\tretry: this.maxRetries > 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tmaxRetries: this.maxRetries,\\n\\t\\t\\t\\t\\t\\t\\t\\tresponseType: Http.ResponseType.JSON\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\thttp.get(url.load, options, (err, meta)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._shouldAbort(asset, false)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(null, null);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.loadTextures(url, callback, asset, meta);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcallback(`Error loading gsplat meta: ${url.original} [${err}]`);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(app, maxRetries){\\n\\t\\t\\t\\tthis.app = app;\\n\\t\\t\\t\\tthis.maxRetries = maxRetries;\\n\\t\\t}\\n}\\n\\nconst parseZipArchive = (data)=>{\\n\\t\\tconst dataView = new DataView(data);\\n\\t\\tconst u16 = (offset)=>dataView.getUint16(offset, true);\\n\\t\\tconst u32 = (offset)=>dataView.getUint32(offset, true);\\n\\t\\tconst extractEocd = (offset)=>{\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tmagic: u32(offset),\\n\\t\\t\\t\\t\\t\\tnumFiles: u16(offset + 8),\\n\\t\\t\\t\\t\\t\\tcdSizeBytes: u32(offset + 12),\\n\\t\\t\\t\\t\\t\\tcdOffsetBytes: u32(offset + 16)\\n\\t\\t\\t\\t};\\n\\t\\t};\\n\\t\\tconst extractCdr = (offset)=>{\\n\\t\\t\\t\\tconst filenameLength = u16(offset + 28);\\n\\t\\t\\t\\tconst extraFieldLength = u16(offset + 30);\\n\\t\\t\\t\\tconst fileCommentLength = u16(offset + 32);\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tmagic: u32(offset),\\n\\t\\t\\t\\t\\t\\tcompressionMethod: u16(offset + 10),\\n\\t\\t\\t\\t\\t\\tcompressedSizeBytes: u32(offset + 20),\\n\\t\\t\\t\\t\\t\\tuncompressedSizeBytes: u32(offset + 24),\\n\\t\\t\\t\\t\\t\\tlfhOffsetBytes: u32(offset + 42),\\n\\t\\t\\t\\t\\t\\tfilename: new TextDecoder().decode(new Uint8Array(data, offset + 46, filenameLength)),\\n\\t\\t\\t\\t\\t\\trecordSizeBytes: 46 + filenameLength + extraFieldLength + fileCommentLength\\n\\t\\t\\t\\t};\\n\\t\\t};\\n\\t\\tconst extractLfh = (offset)=>{\\n\\t\\t\\t\\tconst filenameLength = u16(offset + 26);\\n\\t\\t\\t\\tconst extraLength = u16(offset + 28);\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tmagic: u32(offset),\\n\\t\\t\\t\\t\\t\\toffsetBytes: offset + 30 + filenameLength + extraLength\\n\\t\\t\\t\\t};\\n\\t\\t};\\n\\t\\tconst eocd = extractEocd(dataView.byteLength - 22);\\n\\t\\tif (eocd.magic !== 0x06054b50) {\\n\\t\\t\\t\\tthrow new Error('Invalid zip file: EOCDR not found');\\n\\t\\t}\\n\\t\\tif (eocd.cdOffsetBytes === 0xffffffff || eocd.cdSizeBytes === 0xffffffff) {\\n\\t\\t\\t\\tthrow new Error('Invalid zip file: Zip64 not supported');\\n\\t\\t}\\n\\t\\tconst result = [];\\n\\t\\tlet offset = eocd.cdOffsetBytes;\\n\\t\\tfor(let i = 0; i < eocd.numFiles; i++){\\n\\t\\t\\t\\tconst cdr = extractCdr(offset);\\n\\t\\t\\t\\tif (cdr.magic !== 0x02014b50) {\\n\\t\\t\\t\\t\\t\\tthrow new Error('Invalid zip file: CDR not found');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst lfh = extractLfh(cdr.lfhOffsetBytes);\\n\\t\\t\\t\\tif (lfh.magic !== 0x04034b50) {\\n\\t\\t\\t\\t\\t\\tthrow new Error('Invalid zip file: LFH not found');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tresult.push({\\n\\t\\t\\t\\t\\t\\tfilename: cdr.filename,\\n\\t\\t\\t\\t\\t\\tcompression: {\\n\\t\\t\\t\\t\\t\\t\\t\\t0: 'none',\\n\\t\\t\\t\\t\\t\\t\\t\\t8: 'deflate'\\n\\t\\t\\t\\t\\t\\t}[cdr.compressionMethod] ?? 'unknown',\\n\\t\\t\\t\\t\\t\\tdata: new Uint8Array(data, lfh.offsetBytes, cdr.compressedSizeBytes)\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\toffset += cdr.recordSizeBytes;\\n\\t\\t}\\n\\t\\treturn result;\\n};\\nconst inflate = async (compressed)=>{\\n\\t\\tconst ds = new DecompressionStream('deflate-raw');\\n\\t\\tconst out = new Blob([\\n\\t\\t\\t\\tcompressed\\n\\t\\t]).stream().pipeThrough(ds);\\n\\t\\tconst ab = await new Response(out).arrayBuffer();\\n\\t\\treturn new Uint8Array(ab);\\n};\\nconst downloadArrayBuffer = async (url, asset)=>{\\n\\t\\tconst response = await (asset.file?.contents ?? fetch(url.load));\\n\\t\\tif (!response) {\\n\\t\\t\\t\\tthrow new Error('Error loading resource');\\n\\t\\t}\\n\\t\\tif (response instanceof Response) {\\n\\t\\t\\t\\tif (!response.ok) {\\n\\t\\t\\t\\t\\t\\tthrow new Error(`Error loading resource: ${response.status} ${response.statusText}`);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst totalLength = parseInt(response.headers.get('content-length') ?? '0', 10);\\n\\t\\t\\t\\tif (!response.body || !response.body.getReader) {\\n\\t\\t\\t\\t\\t\\tconst buf = await response.arrayBuffer();\\n\\t\\t\\t\\t\\t\\tasset.fire('progress', buf.byteLength, totalLength);\\n\\t\\t\\t\\t\\t\\treturn buf;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst reader = response.body.getReader();\\n\\t\\t\\t\\tconst chunks = [];\\n\\t\\t\\t\\tlet totalReceived = 0;\\n\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\twhile(true){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst { done, value } = await reader.read();\\n\\t\\t\\t\\t\\t\\t\\t\\tif (done) {\\n\\t\\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\\tchunks.push(value);\\n\\t\\t\\t\\t\\t\\t\\t\\ttotalReceived += value.byteLength;\\n\\t\\t\\t\\t\\t\\t\\t\\tasset.fire('progress', totalReceived, totalLength);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} finally{\\n\\t\\t\\t\\t\\t\\treader.releaseLock();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn new Blob(chunks).arrayBuffer();\\n\\t\\t}\\n\\t\\treturn response;\\n};\\nclass SogBundleParser {\\n\\t\\tasync load(url, callback, asset) {\\n\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\tconst arrayBuffer = await downloadArrayBuffer(url, asset);\\n\\t\\t\\t\\t\\t\\tconst files = parseZipArchive(arrayBuffer);\\n\\t\\t\\t\\t\\t\\tfor (const file of files){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (file.compression === 'deflate') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfile.data = await inflate(file.data);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst metaFile = files.find((f)=>f.filename === 'meta.json');\\n\\t\\t\\t\\t\\t\\tif (!metaFile) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback('Error: meta.json not found');\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tlet meta;\\n\\t\\t\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\t\\t\\tmeta = JSON.parse(new TextDecoder().decode(metaFile.data));\\n\\t\\t\\t\\t\\t\\t} catch (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(`Error parsing meta.json: ${err}`);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst filenames = [\\n\\t\\t\\t\\t\\t\\t\\t\\t'means',\\n\\t\\t\\t\\t\\t\\t\\t\\t'scales',\\n\\t\\t\\t\\t\\t\\t\\t\\t'quats',\\n\\t\\t\\t\\t\\t\\t\\t\\t'sh0',\\n\\t\\t\\t\\t\\t\\t\\t\\t'shN'\\n\\t\\t\\t\\t\\t\\t].map((key)=>meta[key]?.files ?? []).flat();\\n\\t\\t\\t\\t\\t\\tconst textures = {};\\n\\t\\t\\t\\t\\t\\tconst promises = [];\\n\\t\\t\\t\\t\\t\\tfor (const filename of filenames){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst file = files.find((f)=>f.filename === filename);\\n\\t\\t\\t\\t\\t\\t\\t\\tlet texture;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (file) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture = new Asset(filename, 'texture', {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\turl: `${url.load}/${filename}`,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfilename,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontents: file.data\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmipmaps: false\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcrossOrigin: 'anonymous'\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst url = new URL(filename, new URL(filename, window.location.href).toString()).toString();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture = new Asset(filename, 'texture', {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\turl,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfilename\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmipmaps: false\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcrossOrigin: 'anonymous'\\n\\t\\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 promise = new Promise((resolve, reject)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture.on('load', ()=>resolve(null));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture.on('error', (err)=>reject(err));\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.app.assets.add(texture);\\n\\t\\t\\t\\t\\t\\t\\t\\ttextures[filename] = texture;\\n\\t\\t\\t\\t\\t\\t\\t\\tpromises.push(promise);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tObject.values(textures).forEach((t)=>this.app.assets.load(t));\\n\\t\\t\\t\\t\\t\\tawait Promise.allSettled(promises);\\n\\t\\t\\t\\t\\t\\tconst { assets } = this.app;\\n\\t\\t\\t\\t\\t\\tasset.once('unload', ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tObject.values(textures).forEach((t)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tassets.remove(t);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tt.unload();\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tconst decompress = asset.data?.decompress;\\n\\t\\t\\t\\t\\t\\tconst minimalMemory = asset.options?.minimalMemory ?? false;\\n\\t\\t\\t\\t\\t\\tconst data = new GSplatSogData();\\n\\t\\t\\t\\t\\t\\tdata.url = url.original;\\n\\t\\t\\t\\t\\t\\tdata.minimalMemory = minimalMemory;\\n\\t\\t\\t\\t\\t\\tdata.meta = meta;\\n\\t\\t\\t\\t\\t\\tdata.numSplats = meta.count;\\n\\t\\t\\t\\t\\t\\tdata.means_l = textures[meta.means.files[0]].resource;\\n\\t\\t\\t\\t\\t\\tdata.means_u = textures[meta.means.files[1]].resource;\\n\\t\\t\\t\\t\\t\\tdata.quats = textures[meta.quats.files[0]].resource;\\n\\t\\t\\t\\t\\t\\tdata.scales = textures[meta.scales.files[0]].resource;\\n\\t\\t\\t\\t\\t\\tdata.sh0 = textures[meta.sh0.files[0]].resource;\\n\\t\\t\\t\\t\\t\\tdata.sh_centroids = textures[meta.shN?.files[0]]?.resource;\\n\\t\\t\\t\\t\\t\\tdata.sh_labels = textures[meta.shN?.files[1]]?.resource;\\n\\t\\t\\t\\t\\t\\tdata.shBands = GSplatSogData.calcBands(data.sh_centroids?.width);\\n\\t\\t\\t\\t\\t\\tif (!decompress) {\\n\\t\\t\\t\\t\\t\\t\\t\\tawait data.prepareGpuData();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst resource = decompress ? new GSplatResource(this.app.graphicsDevice, await data.decompress()) : new GSplatSogResource(this.app.graphicsDevice, data);\\n\\t\\t\\t\\t\\t\\tcallback(null, resource);\\n\\t\\t\\t\\t} catch (err) {\\n\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(app, maxRetries = 3){\\n\\t\\t\\t\\tthis.app = app;\\n\\t\\t\\t\\tthis.maxRetries = maxRetries;\\n\\t\\t}\\n}\\n\\nclass GSplatAssetLoaderBase {\\n\\t\\tload(url) {}\\n\\t\\tunload(url) {}\\n\\t\\tgetResource(url) {}\\n\\t\\tdestroy() {}\\n}\\n\\nclass GSplatAssetLoader extends GSplatAssetLoaderBase {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._destroyed = true;\\n\\t\\t\\t\\tfor (const asset of this._urlToAsset.values()){\\n\\t\\t\\t\\t\\t\\tasset.fire('unload', asset);\\n\\t\\t\\t\\t\\t\\tasset.off('load');\\n\\t\\t\\t\\t\\t\\tasset.off('error');\\n\\t\\t\\t\\t\\t\\tthis._registry.remove(asset);\\n\\t\\t\\t\\t\\t\\tasset.unload();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._urlToAsset.clear();\\n\\t\\t\\t\\tthis._loadQueue.length = 0;\\n\\t\\t\\t\\tthis._currentlyLoading.clear();\\n\\t\\t\\t\\tthis._retryCount.clear();\\n\\t\\t}\\n\\t\\t_canLoad() {\\n\\t\\t\\t\\treturn !!this._registry.loader?.getHandler('gsplat');\\n\\t\\t}\\n\\t\\tload(url) {\\n\\t\\t\\t\\tconst asset = this._urlToAsset.get(url);\\n\\t\\t\\t\\tif (asset?.loaded || this._currentlyLoading.has(url)) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._loadQueue.includes(url)) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._currentlyLoading.size < this.maxConcurrentLoads) {\\n\\t\\t\\t\\t\\t\\tthis._startLoading(url);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._loadQueue.push(url);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_startLoading(url) {\\n\\t\\t\\t\\tthis._currentlyLoading.add(url);\\n\\t\\t\\t\\tlet asset = this._urlToAsset.get(url);\\n\\t\\t\\t\\tif (!asset) {\\n\\t\\t\\t\\t\\t\\tasset = new Asset(url, 'gsplat', {\\n\\t\\t\\t\\t\\t\\t\\t\\turl\\n\\t\\t\\t\\t\\t\\t}, {}, {\\n\\t\\t\\t\\t\\t\\t\\t\\tminimalMemory: true\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tthis._registry.add(asset);\\n\\t\\t\\t\\t\\t\\tthis._urlToAsset.set(url, asset);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tasset.once('load', ()=>this._onAssetLoadSuccess(url, asset));\\n\\t\\t\\t\\tasset.once('error', (err)=>this._onAssetLoadError(url, asset, err));\\n\\t\\t\\t\\tif (!asset.loaded && !asset.loading) {\\n\\t\\t\\t\\t\\t\\tthis._registry.load(asset);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onAssetLoadSuccess(url, asset) {\\n\\t\\t\\t\\tif (this._destroyed || !this._urlToAsset.has(url)) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._currentlyLoading.delete(url);\\n\\t\\t\\t\\tthis._retryCount.delete(url);\\n\\t\\t\\t\\tthis._processQueue();\\n\\t\\t}\\n\\t\\t_onAssetLoadError(url, asset, err) {\\n\\t\\t\\t\\tif (this._destroyed || !this._canLoad() || !this._urlToAsset.has(url)) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst retryCount = this._retryCount.get(url) || 0;\\n\\t\\t\\t\\tif (retryCount < this.maxRetries) {\\n\\t\\t\\t\\t\\t\\tthis._retryCount.set(url, retryCount + 1);\\n\\t\\t\\t\\t\\t\\tasset.loaded = false;\\n\\t\\t\\t\\t\\t\\tasset.loading = false;\\n\\t\\t\\t\\t\\t\\tthis._registry.load(asset);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._currentlyLoading.delete(url);\\n\\t\\t\\t\\t\\t\\tthis._retryCount.delete(url);\\n\\t\\t\\t\\t\\t\\tthis._processQueue();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_processQueue() {\\n\\t\\t\\t\\tif (this._destroyed || !this._canLoad()) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\twhile(this._currentlyLoading.size < this.maxConcurrentLoads && this._loadQueue.length > 0){\\n\\t\\t\\t\\t\\t\\tconst url = this._loadQueue.shift();\\n\\t\\t\\t\\t\\t\\tif (url) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._startLoading(url);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tunload(url) {\\n\\t\\t\\t\\tthis._currentlyLoading.delete(url);\\n\\t\\t\\t\\tconst queueIndex = this._loadQueue.indexOf(url);\\n\\t\\t\\t\\tif (queueIndex !== -1) {\\n\\t\\t\\t\\t\\t\\tthis._loadQueue.splice(queueIndex, 1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._retryCount.delete(url);\\n\\t\\t\\t\\tconst asset = this._urlToAsset.get(url);\\n\\t\\t\\t\\tif (asset) {\\n\\t\\t\\t\\t\\t\\tasset.fire('unload', asset);\\n\\t\\t\\t\\t\\t\\tasset.off('load');\\n\\t\\t\\t\\t\\t\\tasset.off('error');\\n\\t\\t\\t\\t\\t\\tthis._registry.remove(asset);\\n\\t\\t\\t\\t\\t\\tasset.unload();\\n\\t\\t\\t\\t\\t\\tthis._urlToAsset.delete(url);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._processQueue();\\n\\t\\t}\\n\\t\\tgetResource(url) {\\n\\t\\t\\t\\tconst asset = this._urlToAsset.get(url);\\n\\t\\t\\t\\treturn asset?.resource;\\n\\t\\t}\\n\\t\\tconstructor(registry){\\n\\t\\t\\t\\tsuper(), this._urlToAsset = new Map(), this.maxConcurrentLoads = 2, this.maxRetries = 2, this._currentlyLoading = new Set(), this._loadQueue = [], this._retryCount = new Map(), this._destroyed = false;\\n\\t\\t\\t\\tthis._registry = registry;\\n\\t\\t}\\n}\\n\\nclass GSplatOctreeParser {\\n\\t\\tload(url, callback, asset) {\\n\\t\\t\\t\\tif (typeof url === 'string') {\\n\\t\\t\\t\\t\\t\\turl = {\\n\\t\\t\\t\\t\\t\\t\\t\\tload: url,\\n\\t\\t\\t\\t\\t\\t\\t\\toriginal: url\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst options = {\\n\\t\\t\\t\\t\\t\\tretry: this.maxRetries > 0,\\n\\t\\t\\t\\t\\t\\tmaxRetries: this.maxRetries,\\n\\t\\t\\t\\t\\t\\tresponseType: Http.ResponseType.JSON\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\thttp.get(url.load, options, (err, data)=>{\\n\\t\\t\\t\\t\\t\\tif (!err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst assetLoader = new GSplatAssetLoader(this.app.assets);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst resource = new GSplatOctreeResource(asset.file.url, data, assetLoader);\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(null, resource);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(`Error loading gsplat octree: ${url.original} [${err}]`);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tconstructor(app, maxRetries){\\n\\t\\t\\t\\tthis.app = app;\\n\\t\\t\\t\\tthis.maxRetries = maxRetries;\\n\\t\\t}\\n}\\n\\nclass GSplatHandler extends ResourceHandler {\\n\\t\\t_getUrlWithoutParams(url) {\\n\\t\\t\\t\\treturn url.indexOf('?') >= 0 ? url.split('?')[0] : url;\\n\\t\\t}\\n\\t\\t_getParser(url) {\\n\\t\\t\\t\\tconst basename = path.getBasename(this._getUrlWithoutParams(url)).toLowerCase();\\n\\t\\t\\t\\tif (basename === 'lod-meta.json') {\\n\\t\\t\\t\\t\\t\\treturn this.parsers.octree;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst ext = path.getExtension(basename).replace('.', '');\\n\\t\\t\\t\\treturn this.parsers[ext] || this.parsers.ply;\\n\\t\\t}\\n\\t\\tload(url, callback, asset) {\\n\\t\\t\\t\\tif (typeof url === 'string') {\\n\\t\\t\\t\\t\\t\\turl = {\\n\\t\\t\\t\\t\\t\\t\\t\\tload: url,\\n\\t\\t\\t\\t\\t\\t\\t\\toriginal: url\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._getParser(url.original).load(url, callback, asset);\\n\\t\\t}\\n\\t\\topen(url, data, asset) {\\n\\t\\t\\t\\treturn data;\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tsuper(app, 'gsplat');\\n\\t\\t\\t\\tthis.parsers = {\\n\\t\\t\\t\\t\\t\\tply: new PlyParser(app, 3),\\n\\t\\t\\t\\t\\t\\tsog: new SogBundleParser(app),\\n\\t\\t\\t\\t\\t\\tjson: new SogParser(app, 3),\\n\\t\\t\\t\\t\\t\\toctree: new GSplatOctreeParser(app, 3)\\n\\t\\t\\t\\t};\\n\\t\\t}\\n}\\n\\nfunction BasisWorker() {\\n\\t\\tconst BASIS_FORMAT = {\\n\\t\\t\\t\\tcTFETC1: 0,\\n\\t\\t\\t\\tcTFETC2: 1,\\n\\t\\t\\t\\tcTFBC1: 2,\\n\\t\\t\\t\\tcTFBC3: 3,\\n\\t\\t\\t\\tcTFPVRTC1_4_RGB: 8,\\n\\t\\t\\t\\tcTFPVRTC1_4_RGBA: 9,\\n\\t\\t\\t\\tcTFASTC_4x4: 10,\\n\\t\\t\\t\\tcTFATC_RGB: 11,\\n\\t\\t\\t\\tcTFATC_RGBA_INTERPOLATED_ALPHA: 12,\\n\\t\\t\\t\\tcTFRGBA32: 13,\\n\\t\\t\\t\\tcTFRGB565: 14,\\n\\t\\t\\t\\tcTFRGBA4444: 16\\n\\t\\t};\\n\\t\\tconst opaqueMapping = {\\n\\t\\t\\t\\tastc: BASIS_FORMAT.cTFASTC_4x4,\\n\\t\\t\\t\\tdxt: BASIS_FORMAT.cTFBC1,\\n\\t\\t\\t\\tetc1: BASIS_FORMAT.cTFETC1,\\n\\t\\t\\t\\tetc2: BASIS_FORMAT.cTFETC1,\\n\\t\\t\\t\\tpvr: BASIS_FORMAT.cTFPVRTC1_4_RGB,\\n\\t\\t\\t\\tatc: BASIS_FORMAT.cTFATC_RGB,\\n\\t\\t\\t\\tnone: BASIS_FORMAT.cTFRGB565\\n\\t\\t};\\n\\t\\tconst alphaMapping = {\\n\\t\\t\\t\\tastc: BASIS_FORMAT.cTFASTC_4x4,\\n\\t\\t\\t\\tdxt: BASIS_FORMAT.cTFBC3,\\n\\t\\t\\t\\tetc1: BASIS_FORMAT.cTFRGBA4444,\\n\\t\\t\\t\\tetc2: BASIS_FORMAT.cTFETC2,\\n\\t\\t\\t\\tpvr: BASIS_FORMAT.cTFPVRTC1_4_RGBA,\\n\\t\\t\\t\\tatc: BASIS_FORMAT.cTFATC_RGBA_INTERPOLATED_ALPHA,\\n\\t\\t\\t\\tnone: BASIS_FORMAT.cTFRGBA4444\\n\\t\\t};\\n\\t\\tconst PIXEL_FORMAT = {\\n\\t\\t\\t\\tETC1: 21,\\n\\t\\t\\t\\tETC2_RGB: 22,\\n\\t\\t\\t\\tETC2_RGBA: 23,\\n\\t\\t\\t\\tDXT1: 8,\\n\\t\\t\\t\\tDXT5: 10,\\n\\t\\t\\t\\tPVRTC_4BPP_RGB_1: 26,\\n\\t\\t\\t\\tPVRTC_4BPP_RGBA_1: 27,\\n\\t\\t\\t\\tASTC_4x4: 28,\\n\\t\\t\\t\\tATC_RGB: 29,\\n\\t\\t\\t\\tATC_RGBA: 30,\\n\\t\\t\\t\\tR8_G8_B8_A8: 7,\\n\\t\\t\\t\\tR5_G6_B5: 3,\\n\\t\\t\\t\\tR4_G4_B4_A4: 5\\n\\t\\t};\\n\\t\\tconst basisToEngineMapping = (basisFormat, deviceDetails)=>{\\n\\t\\t\\t\\tswitch(basisFormat){\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFETC1:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn deviceDetails.formats.etc2 ? PIXEL_FORMAT.ETC2_RGB : PIXEL_FORMAT.ETC1;\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFETC2:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn PIXEL_FORMAT.ETC2_RGBA;\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFBC1:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn PIXEL_FORMAT.DXT1;\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFBC3:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn PIXEL_FORMAT.DXT5;\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFPVRTC1_4_RGB:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn PIXEL_FORMAT.PVRTC_4BPP_RGB_1;\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFPVRTC1_4_RGBA:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn PIXEL_FORMAT.PVRTC_4BPP_RGBA_1;\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFASTC_4x4:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn PIXEL_FORMAT.ASTC_4x4;\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFATC_RGB:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn PIXEL_FORMAT.ATC_RGB;\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFATC_RGBA_INTERPOLATED_ALPHA:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn PIXEL_FORMAT.ATC_RGBA;\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFRGBA32:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn PIXEL_FORMAT.R8_G8_B8_A8;\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFRGB565:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn PIXEL_FORMAT.R5_G6_B5;\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFRGBA4444:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn PIXEL_FORMAT.R4_G4_B4_A4;\\n\\t\\t\\t\\t}\\n\\t\\t};\\n\\t\\tconst unswizzleGGGR = (data)=>{\\n\\t\\t\\t\\tconst genB = function(R, G) {\\n\\t\\t\\t\\t\\t\\tconst r = R * (2.0 / 255.0) - 1.0;\\n\\t\\t\\t\\t\\t\\tconst g = G * (2.0 / 255.0) - 1.0;\\n\\t\\t\\t\\t\\t\\tconst b = Math.sqrt(1.0 - Math.min(1.0, r * r + g * g));\\n\\t\\t\\t\\t\\t\\treturn Math.max(0, Math.min(255, Math.floor((b + 1.0) * 0.5 * 255.0)));\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tfor(let offset = 0; offset < data.length; offset += 4){\\n\\t\\t\\t\\t\\t\\tconst R = data[offset + 3];\\n\\t\\t\\t\\t\\t\\tconst G = data[offset + 1];\\n\\t\\t\\t\\t\\t\\tdata[offset + 0] = R;\\n\\t\\t\\t\\t\\t\\tdata[offset + 2] = genB(R, G);\\n\\t\\t\\t\\t\\t\\tdata[offset + 3] = 255;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn data;\\n\\t\\t};\\n\\t\\tconst pack565 = (data)=>{\\n\\t\\t\\t\\tconst result = new Uint16Array(data.length / 4);\\n\\t\\t\\t\\tfor(let offset = 0; offset < data.length; offset += 4){\\n\\t\\t\\t\\t\\t\\tconst R = data[offset + 0];\\n\\t\\t\\t\\t\\t\\tconst G = data[offset + 1];\\n\\t\\t\\t\\t\\t\\tconst B = data[offset + 2];\\n\\t\\t\\t\\t\\t\\tresult[offset / 4] = (R & 0xf8) << 8 | (G & 0xfc) << 3 | B >> 3;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn result;\\n\\t\\t};\\n\\t\\tconst isPOT = (width, height)=>{\\n\\t\\t\\t\\treturn (width & width - 1) === 0 && (height & height - 1) === 0;\\n\\t\\t};\\n\\t\\tconst performanceNow = ()=>{\\n\\t\\t\\t\\treturn typeof performance !== 'undefined' ? performance.now() : 0;\\n\\t\\t};\\n\\t\\tlet basis;\\n\\t\\tlet rgbPriority;\\n\\t\\tlet rgbaPriority;\\n\\t\\tconst chooseTargetFormat = (deviceDetails, hasAlpha, isUASTC)=>{\\n\\t\\t\\t\\tif (isUASTC) {\\n\\t\\t\\t\\t\\t\\tif (deviceDetails.formats.astc) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn 'astc';\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (hasAlpha) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (deviceDetails.formats.etc2) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn 'etc2';\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (deviceDetails.formats.etc2) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn 'etc2';\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (deviceDetails.formats.etc1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn 'etc1';\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst testInOrder = (priority)=>{\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < priority.length; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst format = priority[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (deviceDetails.formats[format]) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn format;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn 'none';\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\treturn testInOrder(hasAlpha ? rgbaPriority : rgbPriority);\\n\\t\\t};\\n\\t\\tconst dimensionsValid = (width, height, format)=>{\\n\\t\\t\\t\\tswitch(format){\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFETC1:\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFETC2:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFBC1:\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFBC3:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn (width & 0x3) === 0 && (height & 0x3) === 0;\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFPVRTC1_4_RGB:\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFPVRTC1_4_RGBA:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn isPOT(width, height);\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFASTC_4x4:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFATC_RGB:\\n\\t\\t\\t\\t\\t\\tcase BASIS_FORMAT.cTFATC_RGBA_INTERPOLATED_ALPHA:\\n\\t\\t\\t\\t\\t\\t\\t\\treturn true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn false;\\n\\t\\t};\\n\\t\\tconst transcodeKTX2 = (url, data, options)=>{\\n\\t\\t\\t\\tif (!basis.KTX2File) {\\n\\t\\t\\t\\t\\t\\tthrow new Error('Basis transcoder module does not include support for KTX2.');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst funcStart = performanceNow();\\n\\t\\t\\t\\tconst basisFile = new basis.KTX2File(new Uint8Array(data));\\n\\t\\t\\t\\tconst width = basisFile.getWidth();\\n\\t\\t\\t\\tconst height = basisFile.getHeight();\\n\\t\\t\\t\\tconst levels = basisFile.getLevels();\\n\\t\\t\\t\\tconst hasAlpha = !!basisFile.getHasAlpha();\\n\\t\\t\\t\\tconst isUASTC = basisFile.isUASTC && basisFile.isUASTC();\\n\\t\\t\\t\\tif (!width || !height || !levels) {\\n\\t\\t\\t\\t\\t\\tbasisFile.close();\\n\\t\\t\\t\\t\\t\\tbasisFile.delete();\\n\\t\\t\\t\\t\\t\\tthrow new Error(`Invalid image dimensions url=${url} width=${width} height=${height} levels=${levels}`);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst format = chooseTargetFormat(options.deviceDetails, hasAlpha, isUASTC);\\n\\t\\t\\t\\tconst unswizzle = !!options.isGGGR && format === 'pvr';\\n\\t\\t\\t\\tlet basisFormat;\\n\\t\\t\\t\\tif (unswizzle) {\\n\\t\\t\\t\\t\\t\\tbasisFormat = BASIS_FORMAT.cTFRGBA32;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tbasisFormat = hasAlpha ? alphaMapping[format] : opaqueMapping[format];\\n\\t\\t\\t\\t\\t\\tif (!dimensionsValid(width, height, basisFormat)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbasisFormat = hasAlpha ? BASIS_FORMAT.cTFRGBA32 : BASIS_FORMAT.cTFRGB565;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!basisFile.startTranscoding()) {\\n\\t\\t\\t\\t\\t\\tbasisFile.close();\\n\\t\\t\\t\\t\\t\\tbasisFile.delete();\\n\\t\\t\\t\\t\\t\\tthrow new Error(`Failed to start transcoding url=${url}`);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet i;\\n\\t\\t\\t\\tconst levelData = [];\\n\\t\\t\\t\\tfor(let mip = 0; mip < levels; ++mip){\\n\\t\\t\\t\\t\\t\\tconst dstSize = basisFile.getImageTranscodedSizeInBytes(mip, 0, 0, basisFormat);\\n\\t\\t\\t\\t\\t\\tconst dst = new Uint8Array(dstSize);\\n\\t\\t\\t\\t\\t\\tif (!basisFile.transcodeImage(dst, mip, 0, 0, basisFormat, 0, -1, -1)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbasisFile.close();\\n\\t\\t\\t\\t\\t\\t\\t\\tbasisFile.delete();\\n\\t\\t\\t\\t\\t\\t\\t\\tthrow new Error(`Failed to transcode image url=${url}`);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst is16BitFormat = basisFormat === BASIS_FORMAT.cTFRGB565 || basisFormat === BASIS_FORMAT.cTFRGBA4444;\\n\\t\\t\\t\\t\\t\\tlevelData.push(is16BitFormat ? new Uint16Array(dst.buffer) : dst);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tbasisFile.close();\\n\\t\\t\\t\\tbasisFile.delete();\\n\\t\\t\\t\\tif (unswizzle) {\\n\\t\\t\\t\\t\\t\\tbasisFormat = BASIS_FORMAT.cTFRGB565;\\n\\t\\t\\t\\t\\t\\tfor(i = 0; i < levelData.length; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tlevelData[i] = pack565(unswizzleGGGR(levelData[i]));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tformat: basisToEngineMapping(basisFormat, options.deviceDetails),\\n\\t\\t\\t\\t\\t\\twidth: width,\\n\\t\\t\\t\\t\\t\\theight: height,\\n\\t\\t\\t\\t\\t\\tlevels: levelData,\\n\\t\\t\\t\\t\\t\\tcubemap: false,\\n\\t\\t\\t\\t\\t\\ttranscodeTime: performanceNow() - funcStart,\\n\\t\\t\\t\\t\\t\\turl: url,\\n\\t\\t\\t\\t\\t\\tunswizzledGGGR: unswizzle\\n\\t\\t\\t\\t};\\n\\t\\t};\\n\\t\\tconst transcodeBasis = (url, data, options)=>{\\n\\t\\t\\t\\tconst funcStart = performanceNow();\\n\\t\\t\\t\\tconst basisFile = new basis.BasisFile(new Uint8Array(data));\\n\\t\\t\\t\\tconst width = basisFile.getImageWidth(0, 0);\\n\\t\\t\\t\\tconst height = basisFile.getImageHeight(0, 0);\\n\\t\\t\\t\\tconst images = basisFile.getNumImages();\\n\\t\\t\\t\\tconst levels = basisFile.getNumLevels(0);\\n\\t\\t\\t\\tconst hasAlpha = !!basisFile.getHasAlpha();\\n\\t\\t\\t\\tconst isUASTC = basisFile.isUASTC && basisFile.isUASTC();\\n\\t\\t\\t\\tif (!width || !height || !images || !levels) {\\n\\t\\t\\t\\t\\t\\tbasisFile.close();\\n\\t\\t\\t\\t\\t\\tbasisFile.delete();\\n\\t\\t\\t\\t\\t\\tthrow new Error(`Invalid image dimensions url=${url} width=${width} height=${height} images=${images} levels=${levels}`);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst format = chooseTargetFormat(options.deviceDetails, hasAlpha, isUASTC);\\n\\t\\t\\t\\tconst unswizzle = !!options.isGGGR && format === 'pvr';\\n\\t\\t\\t\\tlet basisFormat;\\n\\t\\t\\t\\tif (unswizzle) {\\n\\t\\t\\t\\t\\t\\tbasisFormat = BASIS_FORMAT.cTFRGBA32;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tbasisFormat = hasAlpha ? alphaMapping[format] : opaqueMapping[format];\\n\\t\\t\\t\\t\\t\\tif (!dimensionsValid(width, height, basisFormat)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbasisFormat = hasAlpha ? BASIS_FORMAT.cTFRGBA32 : BASIS_FORMAT.cTFRGB565;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!basisFile.startTranscoding()) {\\n\\t\\t\\t\\t\\t\\tbasisFile.close();\\n\\t\\t\\t\\t\\t\\tbasisFile.delete();\\n\\t\\t\\t\\t\\t\\tthrow new Error(`Failed to start transcoding url=${url}`);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet i;\\n\\t\\t\\t\\tconst levelData = [];\\n\\t\\t\\t\\tfor(let mip = 0; mip < levels; ++mip){\\n\\t\\t\\t\\t\\t\\tconst dstSize = basisFile.getImageTranscodedSizeInBytes(0, mip, basisFormat);\\n\\t\\t\\t\\t\\t\\tconst dst = new Uint8Array(dstSize);\\n\\t\\t\\t\\t\\t\\tif (!basisFile.transcodeImage(dst, 0, mip, basisFormat, 0, 0)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (mip === levels - 1 && dstSize === levelData[mip - 1].buffer.byteLength) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdst.set(new Uint8Array(levelData[mip - 1].buffer));\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconsole.warn(`Failed to transcode last mipmap level, using previous level instead url=${url}`);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbasisFile.close();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbasisFile.delete();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthrow new Error(`Failed to transcode image url=${url}`);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst is16BitFormat = basisFormat === BASIS_FORMAT.cTFRGB565 || basisFormat === BASIS_FORMAT.cTFRGBA4444;\\n\\t\\t\\t\\t\\t\\tlevelData.push(is16BitFormat ? new Uint16Array(dst.buffer) : dst);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tbasisFile.close();\\n\\t\\t\\t\\tbasisFile.delete();\\n\\t\\t\\t\\tif (unswizzle) {\\n\\t\\t\\t\\t\\t\\tbasisFormat = BASIS_FORMAT.cTFRGB565;\\n\\t\\t\\t\\t\\t\\tfor(i = 0; i < levelData.length; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tlevelData[i] = pack565(unswizzleGGGR(levelData[i]));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tformat: basisToEngineMapping(basisFormat, options.deviceDetails),\\n\\t\\t\\t\\t\\t\\twidth: width,\\n\\t\\t\\t\\t\\t\\theight: height,\\n\\t\\t\\t\\t\\t\\tlevels: levelData,\\n\\t\\t\\t\\t\\t\\tcubemap: false,\\n\\t\\t\\t\\t\\t\\ttranscodeTime: performanceNow() - funcStart,\\n\\t\\t\\t\\t\\t\\turl: url,\\n\\t\\t\\t\\t\\t\\tunswizzledGGGR: unswizzle\\n\\t\\t\\t\\t};\\n\\t\\t};\\n\\t\\tconst transcode = (url, data, options)=>{\\n\\t\\t\\t\\treturn options.isKTX2 ? transcodeKTX2(url, data, options) : transcodeBasis(url, data, options);\\n\\t\\t};\\n\\t\\tconst workerTranscode = (url, data, options)=>{\\n\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\tconst result = transcode(url, data, options);\\n\\t\\t\\t\\t\\t\\tresult.levels = result.levels.map((v)=>v.buffer);\\n\\t\\t\\t\\t\\t\\tself.postMessage({\\n\\t\\t\\t\\t\\t\\t\\t\\turl: url,\\n\\t\\t\\t\\t\\t\\t\\t\\tdata: result\\n\\t\\t\\t\\t\\t\\t}, result.levels);\\n\\t\\t\\t\\t} catch (err) {\\n\\t\\t\\t\\t\\t\\tself.postMessage({\\n\\t\\t\\t\\t\\t\\t\\t\\turl: url,\\n\\t\\t\\t\\t\\t\\t\\t\\terr: err\\n\\t\\t\\t\\t\\t\\t}, null);\\n\\t\\t\\t\\t}\\n\\t\\t};\\n\\t\\tconst workerInit = (config, callback)=>{\\n\\t\\t\\t\\tconst instantiateWasmFunc = (imports, successCallback)=>{\\n\\t\\t\\t\\t\\t\\tWebAssembly.instantiate(config.module, imports).then((result)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tsuccessCallback(result);\\n\\t\\t\\t\\t\\t\\t}).catch((reason)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tconsole.error(`instantiate failed + ${reason}`);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\treturn {};\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tself.BASIS(config.module ? {\\n\\t\\t\\t\\t\\t\\tinstantiateWasm: instantiateWasmFunc\\n\\t\\t\\t\\t} : null).then((instance)=>{\\n\\t\\t\\t\\t\\t\\tinstance.initializeBasis();\\n\\t\\t\\t\\t\\t\\tbasis = instance;\\n\\t\\t\\t\\t\\t\\trgbPriority = config.rgbPriority;\\n\\t\\t\\t\\t\\t\\trgbaPriority = config.rgbaPriority;\\n\\t\\t\\t\\t\\t\\tcallback(null);\\n\\t\\t\\t\\t});\\n\\t\\t};\\n\\t\\tconst queue = [];\\n\\t\\tself.onmessage = (message)=>{\\n\\t\\t\\t\\tconst data = message.data;\\n\\t\\t\\t\\tswitch(data.type){\\n\\t\\t\\t\\t\\t\\tcase 'init':\\n\\t\\t\\t\\t\\t\\t\\t\\tworkerInit(data.config, ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < queue.length; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tworkerTranscode(queue[i].url, queue[i].data, queue[i].options);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tqueue.length = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\tcase 'transcode':\\n\\t\\t\\t\\t\\t\\t\\t\\tif (basis) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tworkerTranscode(data.url, data.data, data.options);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tqueue.push(data);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t}\\n\\t\\t};\\n}\\n\\nconst getCompressionFormats = (device)=>{\\n\\t\\treturn {\\n\\t\\t\\t\\tastc: !!device.extCompressedTextureASTC,\\n\\t\\t\\t\\tatc: !!device.extCompressedTextureATC,\\n\\t\\t\\t\\tdxt: !!device.extCompressedTextureS3TC,\\n\\t\\t\\t\\tetc1: !!device.extCompressedTextureETC1,\\n\\t\\t\\t\\tetc2: !!device.extCompressedTextureETC,\\n\\t\\t\\t\\tpvr: !!device.extCompressedTexturePVRTC\\n\\t\\t};\\n};\\nconst prepareWorkerModules = (config, callback)=>{\\n\\t\\tconst getWorkerBlob = (basisCode)=>{\\n\\t\\t\\t\\tconst code = [\\n\\t\\t\\t\\t\\t\\t'/* basis */',\\n\\t\\t\\t\\t\\t\\tbasisCode,\\n\\t\\t\\t\\t\\t\\t'',\\n\\t\\t\\t\\t\\t\\t`(${BasisWorker.toString()})()\\\\n\\\\n`\\n\\t\\t\\t\\t].join('\\\\n');\\n\\t\\t\\t\\treturn new Blob([\\n\\t\\t\\t\\t\\t\\tcode\\n\\t\\t\\t\\t], {\\n\\t\\t\\t\\t\\t\\ttype: \\\"application/javascript\\\"\\n\\t\\t\\t\\t});\\n\\t\\t};\\n\\t\\tconst wasmSupported = ()=>{\\n\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\tif (typeof WebAssembly === 'object' && typeof WebAssembly.instantiate === 'function') {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));\\n\\t\\t\\t\\t\\t\\t\\t\\tif (module instanceof WebAssembly.Module) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn new WebAssembly.Instance(module) instanceof WebAssembly.Instance;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} catch (e) {}\\n\\t\\t\\t\\treturn false;\\n\\t\\t};\\n\\t\\tconst sendResponse = (basisCode, module)=>{\\n\\t\\t\\t\\tcallback(null, {\\n\\t\\t\\t\\t\\t\\tworkerUrl: URL.createObjectURL(getWorkerBlob(basisCode)),\\n\\t\\t\\t\\t\\t\\tmodule: module,\\n\\t\\t\\t\\t\\t\\trgbPriority: config.rgbPriority,\\n\\t\\t\\t\\t\\t\\trgbaPriority: config.rgbaPriority\\n\\t\\t\\t\\t});\\n\\t\\t};\\n\\t\\tconst options = {\\n\\t\\t\\t\\tcache: true,\\n\\t\\t\\t\\tresponseType: 'text',\\n\\t\\t\\t\\tretry: config.maxRetries > 0,\\n\\t\\t\\t\\tmaxRetries: config.maxRetries\\n\\t\\t};\\n\\t\\tif (config.glueUrl && config.wasmUrl && wasmSupported()) {\\n\\t\\t\\t\\tlet basisCode = null;\\n\\t\\t\\t\\tlet module = null;\\n\\t\\t\\t\\thttp.get(config.glueUrl, options, (err, response)=>{\\n\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (module) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsendResponse(response, module);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbasisCode = response;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst fetchPromise = fetch(config.wasmUrl);\\n\\t\\t\\t\\tconst compileManual = ()=>{\\n\\t\\t\\t\\t\\t\\tfetchPromise.then((result)=>result.arrayBuffer()).then((buffer)=>WebAssembly.compile(buffer)).then((module_)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (basisCode) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsendResponse(basisCode, module_);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmodule = module_;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}).catch((err)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(err, null);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (WebAssembly.compileStreaming) {\\n\\t\\t\\t\\t\\t\\tWebAssembly.compileStreaming(fetchPromise).then((module_)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (basisCode) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsendResponse(basisCode, module_);\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmodule = module_;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}).catch((err)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tcompileManual();\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tcompileManual();\\n\\t\\t\\t\\t}\\n\\t\\t} else {\\n\\t\\t\\t\\thttp.get(config.fallbackUrl, options, (err, response)=>{\\n\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(err, null);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tsendResponse(response, null);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n};\\nclass BasisQueue {\\n\\t\\tenqueueJob(url, data, callback, options) {\\n\\t\\t\\t\\tif (this.callbacks.hasOwnProperty(url)) {\\n\\t\\t\\t\\t\\t\\tthis.callbacks[url].push(callback);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.callbacks[url] = [\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t\\t\\tconst job = {\\n\\t\\t\\t\\t\\t\\t\\t\\turl: url,\\n\\t\\t\\t\\t\\t\\t\\t\\tdata: data,\\n\\t\\t\\t\\t\\t\\t\\t\\toptions: options\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\tif (this.clients.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.clients.shift().run(job);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.queue.push(job);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tenqueueClient(client) {\\n\\t\\t\\t\\tif (this.queue.length > 0) {\\n\\t\\t\\t\\t\\t\\tclient.run(this.queue.shift());\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.clients.push(client);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\thandleResponse(url, err, data) {\\n\\t\\t\\t\\tconst callback = this.callbacks[url];\\n\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < callback.length; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback[i](err);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (data.format === PIXELFORMAT_RGB565 || data.format === PIXELFORMAT_RGBA4) {\\n\\t\\t\\t\\t\\t\\t\\t\\tdata.levels = data.levels.map((v)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn new Uint16Array(v);\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tdata.levels = data.levels.map((v)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn new Uint8Array(v);\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < callback.length; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback[i](null, data);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tdelete this.callbacks[url];\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.callbacks = {};\\n\\t\\t\\t\\tthis.queue = [];\\n\\t\\t\\t\\tthis.clients = [];\\n\\t\\t}\\n}\\nclass BasisClient {\\n\\t\\trun(job) {\\n\\t\\t\\t\\tconst transfer = [];\\n\\t\\t\\t\\tif (job.data instanceof ArrayBuffer) {\\n\\t\\t\\t\\t\\t\\ttransfer.push(job.data);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.worker.postMessage({\\n\\t\\t\\t\\t\\t\\ttype: 'transcode',\\n\\t\\t\\t\\t\\t\\turl: job.url,\\n\\t\\t\\t\\t\\t\\tformat: job.format,\\n\\t\\t\\t\\t\\t\\tdata: job.data,\\n\\t\\t\\t\\t\\t\\toptions: job.options\\n\\t\\t\\t\\t}, transfer);\\n\\t\\t\\t\\tif (this.eager) {\\n\\t\\t\\t\\t\\t\\tthis.queue.enqueueClient(this);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(queue, config, eager){\\n\\t\\t\\t\\tthis.queue = queue;\\n\\t\\t\\t\\tthis.worker = new Worker(config.workerUrl);\\n\\t\\t\\t\\tthis.worker.addEventListener('message', (message)=>{\\n\\t\\t\\t\\t\\t\\tconst data = message.data;\\n\\t\\t\\t\\t\\t\\tthis.queue.handleResponse(data.url, data.err, data.data);\\n\\t\\t\\t\\t\\t\\tif (!this.eager) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.queue.enqueueClient(this);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.worker.postMessage({\\n\\t\\t\\t\\t\\t\\ttype: 'init',\\n\\t\\t\\t\\t\\t\\tconfig: config\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.eager = eager;\\n\\t\\t}\\n}\\nconst defaultNumWorkers = 1;\\nconst defaultRgbPriority = [\\n\\t\\t'etc2',\\n\\t\\t'etc1',\\n\\t\\t'astc',\\n\\t\\t'dxt',\\n\\t\\t'pvr',\\n\\t\\t'atc'\\n];\\nconst defaultRgbaPriority = [\\n\\t\\t'astc',\\n\\t\\t'dxt',\\n\\t\\t'etc2',\\n\\t\\t'pvr',\\n\\t\\t'atc'\\n];\\nconst defaultMaxRetries = 5;\\nconst queue = new BasisQueue();\\nlet lazyConfig = null;\\nlet initializing = false;\\nfunction basisInitialize(config) {\\n\\t\\tif (initializing) {\\n\\t\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!config) {\\n\\t\\t\\t\\tconfig = lazyConfig || {};\\n\\t\\t} else if (config.lazyInit) {\\n\\t\\t\\t\\tlazyConfig = config;\\n\\t\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tif (!config.glueUrl || !config.wasmUrl || !config.fallbackUrl) {\\n\\t\\t\\t\\tconst moduleConfig = WasmModule.getConfig('BASIS');\\n\\t\\t\\t\\tif (moduleConfig) {\\n\\t\\t\\t\\t\\t\\tconfig = {\\n\\t\\t\\t\\t\\t\\t\\t\\tglueUrl: moduleConfig.glueUrl,\\n\\t\\t\\t\\t\\t\\t\\t\\twasmUrl: moduleConfig.wasmUrl,\\n\\t\\t\\t\\t\\t\\t\\t\\tfallbackUrl: moduleConfig.fallbackUrl,\\n\\t\\t\\t\\t\\t\\t\\t\\tnumWorkers: moduleConfig.numWorkers\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tif (config.glueUrl || config.wasmUrl || config.fallbackUrl) {\\n\\t\\t\\t\\tinitializing = true;\\n\\t\\t\\t\\tconst numWorkers = Math.max(1, Math.min(16, config.numWorkers || defaultNumWorkers));\\n\\t\\t\\t\\tconst eagerWorkers = config.numWorkers === 1 || (config.hasOwnProperty('eagerWorkers') ? config.eagerWorkers : true);\\n\\t\\t\\t\\tconfig.rgbPriority = config.rgbPriority || defaultRgbPriority;\\n\\t\\t\\t\\tconfig.rgbaPriority = config.rgbaPriority || defaultRgbaPriority;\\n\\t\\t\\t\\tconfig.maxRetries = config.hasOwnProperty('maxRetries') ? config.maxRetries : defaultMaxRetries;\\n\\t\\t\\t\\tprepareWorkerModules(config, (err, clientConfig)=>{\\n\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconsole.error(`failed to initialize basis worker: ${err}`);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = 0; i < numWorkers; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tqueue.enqueueClient(new BasisClient(queue, clientConfig, eagerWorkers));\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n}\\nlet deviceDetails = null;\\nfunction basisTranscode(device, url, data, callback, options) {\\n\\t\\tbasisInitialize();\\n\\t\\tif (!deviceDetails) {\\n\\t\\t\\t\\tdeviceDetails = {\\n\\t\\t\\t\\t\\t\\tformats: getCompressionFormats(device)\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tqueue.enqueueJob(url, data, callback, {\\n\\t\\t\\t\\tdeviceDetails: deviceDetails,\\n\\t\\t\\t\\tisGGGR: !!options?.isGGGR,\\n\\t\\t\\t\\tisKTX2: !!options?.isKTX2\\n\\t\\t});\\n\\t\\treturn initializing;\\n}\\n\\nclass TextureParser {\\n\\t\\tload(url, callback, asset) {\\n\\t\\t\\t\\tthrow new Error('not implemented');\\n\\t\\t}\\n\\t\\topen(url, data, device) {\\n\\t\\t\\t\\tthrow new Error('not implemented');\\n\\t\\t}\\n}\\n\\nclass BasisParser extends TextureParser {\\n\\t\\tload(url, callback, asset) {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tconst transcode = (data)=>{\\n\\t\\t\\t\\t\\t\\tconst basisModuleFound = basisTranscode(device, url.load, data, callback, {\\n\\t\\t\\t\\t\\t\\t\\t\\tisGGGR: (asset?.file?.variants?.basis?.opt & 8) !== 0\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tif (!basisModuleFound) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(`Basis module not found. Asset [${asset.name}](${asset.getFileUrl()}) basis texture variant will not be loaded.`);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tAsset.fetchArrayBuffer(url.load, (err, result)=>{\\n\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\ttranscode(result);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}, asset, this.maxRetries);\\n\\t\\t}\\n\\t\\topen(url, data, device, textureOptions = {}) {\\n\\t\\t\\t\\tconst format = textureOptions.srgb ? pixelFormatLinearToGamma(data.format) : data.format;\\n\\t\\t\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: url,\\n\\t\\t\\t\\t\\t\\taddressU: data.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,\\n\\t\\t\\t\\t\\t\\taddressV: data.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,\\n\\t\\t\\t\\t\\t\\twidth: data.width,\\n\\t\\t\\t\\t\\t\\theight: data.height,\\n\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\tcubemap: data.cubemap,\\n\\t\\t\\t\\t\\t\\tlevels: data.levels,\\n\\t\\t\\t\\t\\t\\t...textureOptions\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\ttexture.upload();\\n\\t\\t\\t\\treturn texture;\\n\\t\\t}\\n\\t\\tconstructor(registry, device){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.maxRetries = 0;\\n\\t\\t}\\n}\\n\\nclass ImgParser extends TextureParser {\\n\\t\\tload(url, callback, asset) {\\n\\t\\t\\t\\tconst hasContents = !!asset?.file?.contents;\\n\\t\\t\\t\\tif (hasContents) {\\n\\t\\t\\t\\t\\t\\tif (this.device.supportsImageBitmap) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._loadImageBitmapFromBlob(new Blob([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tasset.file.contents\\n\\t\\t\\t\\t\\t\\t\\t\\t]), callback);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\turl = {\\n\\t\\t\\t\\t\\t\\t\\t\\tload: URL.createObjectURL(new Blob([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tasset.file.contents\\n\\t\\t\\t\\t\\t\\t\\t\\t])),\\n\\t\\t\\t\\t\\t\\t\\t\\toriginal: url.original\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst handler = (err, result)=>{\\n\\t\\t\\t\\t\\t\\tif (hasContents) {\\n\\t\\t\\t\\t\\t\\t\\t\\tURL.revokeObjectURL(url.load);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcallback(err, result);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tlet crossOrigin;\\n\\t\\t\\t\\tif (asset && asset.options && asset.options.hasOwnProperty('crossOrigin')) {\\n\\t\\t\\t\\t\\t\\tcrossOrigin = asset.options.crossOrigin;\\n\\t\\t\\t\\t} else if (ABSOLUTE_URL.test(url.load)) {\\n\\t\\t\\t\\t\\t\\tcrossOrigin = this.crossOrigin;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.device.supportsImageBitmap) {\\n\\t\\t\\t\\t\\t\\tthis._loadImageBitmap(url.load, url.original, crossOrigin, handler, asset);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._loadImage(url.load, url.original, crossOrigin, handler, asset);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\topen(url, data, device, textureOptions = {}) {\\n\\t\\t\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: url,\\n\\t\\t\\t\\t\\t\\twidth: data.width,\\n\\t\\t\\t\\t\\t\\theight: data.height,\\n\\t\\t\\t\\t\\t\\tformat: textureOptions.srgb ? PIXELFORMAT_SRGBA8 : PIXELFORMAT_RGBA8,\\n\\t\\t\\t\\t\\t\\t...textureOptions\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\ttexture.setSource(data);\\n\\t\\t\\t\\treturn texture;\\n\\t\\t}\\n\\t\\t_loadImage(url, originalUrl, crossOrigin, callback, asset) {\\n\\t\\t\\t\\tconst image = new Image();\\n\\t\\t\\t\\tif (crossOrigin) {\\n\\t\\t\\t\\t\\t\\timage.crossOrigin = crossOrigin;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet retries = 0;\\n\\t\\t\\t\\tconst maxRetries = this.maxRetries;\\n\\t\\t\\t\\tlet retryTimeout;\\n\\t\\t\\t\\tconst dummySize = 1024 * 1024;\\n\\t\\t\\t\\tasset?.fire('progress', 0, dummySize);\\n\\t\\t\\t\\timage.onload = function() {\\n\\t\\t\\t\\t\\t\\tasset?.fire('progress', dummySize, dummySize);\\n\\t\\t\\t\\t\\t\\tcallback(null, image);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\timage.onerror = function() {\\n\\t\\t\\t\\t\\t\\tif (retryTimeout) return;\\n\\t\\t\\t\\t\\t\\tif (maxRetries > 0 && ++retries <= maxRetries) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst retryDelay = Math.pow(2, retries) * 100;\\n\\t\\t\\t\\t\\t\\t\\t\\tconsole.log(`Error loading Texture from: '${originalUrl}' - Retrying in ${retryDelay}ms...`);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst idx = url.indexOf('?');\\n\\t\\t\\t\\t\\t\\t\\t\\tconst separator = idx >= 0 ? '&' : '?';\\n\\t\\t\\t\\t\\t\\t\\t\\tretryTimeout = setTimeout(()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\timage.src = `${url + separator}retry=${Date.now()}`;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tretryTimeout = null;\\n\\t\\t\\t\\t\\t\\t\\t\\t}, retryDelay);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(`Error loading Texture from: '${originalUrl}'`);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\timage.src = url;\\n\\t\\t}\\n\\t\\t_loadImageBitmap(url, originalUrl, crossOrigin, callback, asset) {\\n\\t\\t\\t\\tconst options = {\\n\\t\\t\\t\\t\\t\\tcache: true,\\n\\t\\t\\t\\t\\t\\tresponseType: 'blob',\\n\\t\\t\\t\\t\\t\\tretry: this.maxRetries > 0,\\n\\t\\t\\t\\t\\t\\tmaxRetries: this.maxRetries,\\n\\t\\t\\t\\t\\t\\tprogress: asset\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\thttp.get(url, options, (err, blob)=>{\\n\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(err);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._loadImageBitmapFromBlob(blob, callback);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\t_loadImageBitmapFromBlob(blob, callback) {\\n\\t\\t\\t\\tcreateImageBitmap(blob, {\\n\\t\\t\\t\\t\\t\\tpremultiplyAlpha: 'none',\\n\\t\\t\\t\\t\\t\\tcolorSpaceConversion: 'none'\\n\\t\\t\\t\\t}).then((imageBitmap)=>callback(null, imageBitmap)).catch((e)=>callback(e));\\n\\t\\t}\\n\\t\\tconstructor(registry, device){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.crossOrigin = registry.prefix ? 'anonymous' : null;\\n\\t\\t\\t\\tthis.maxRetries = 0;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t}\\n}\\n\\nconst IDENTIFIER = [\\n\\t\\t0x58544BAB,\\n\\t\\t0xBB313120,\\n\\t\\t0x0A1A0A0D\\n];\\nconst KNOWN_FORMATS = {\\n\\t\\t0x83F0: PIXELFORMAT_DXT1,\\n\\t\\t0x83F2: PIXELFORMAT_DXT3,\\n\\t\\t0x83F3: PIXELFORMAT_DXT5,\\n\\t\\t0x8D64: PIXELFORMAT_ETC1,\\n\\t\\t0x9274: PIXELFORMAT_ETC2_RGB,\\n\\t\\t0x9278: PIXELFORMAT_ETC2_RGBA,\\n\\t\\t0x8C00: PIXELFORMAT_PVRTC_4BPP_RGB_1,\\n\\t\\t0x8C01: PIXELFORMAT_PVRTC_2BPP_RGB_1,\\n\\t\\t0x8C02: PIXELFORMAT_PVRTC_4BPP_RGBA_1,\\n\\t\\t0x8C03: PIXELFORMAT_PVRTC_2BPP_RGBA_1,\\n\\t\\t0x8051: PIXELFORMAT_RGB8,\\n\\t\\t0x8058: PIXELFORMAT_RGBA8,\\n\\t\\t0x8C41: PIXELFORMAT_SRGB8,\\n\\t\\t0x8C43: PIXELFORMAT_SRGBA8,\\n\\t\\t0x8C3A: PIXELFORMAT_111110F,\\n\\t\\t0x881B: PIXELFORMAT_RGB16F,\\n\\t\\t0x881A: PIXELFORMAT_RGBA16F\\n};\\nfunction createContainer(pixelFormat, buffer, byteOffset, byteSize) {\\n\\t\\treturn pixelFormat === PIXELFORMAT_111110F ? new Uint32Array(buffer, byteOffset, byteSize / 4) : new Uint8Array(buffer, byteOffset, byteSize);\\n}\\nclass KtxParser extends TextureParser {\\n\\t\\tload(url, callback, asset) {\\n\\t\\t\\t\\tAsset.fetchArrayBuffer(url.load, callback, asset, this.maxRetries);\\n\\t\\t}\\n\\t\\topen(url, data, device, textureOptions = {}) {\\n\\t\\t\\t\\tconst textureData = this.parse(data);\\n\\t\\t\\t\\tif (!textureData) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst format = textureOptions.srgb ? pixelFormatLinearToGamma(textureData.format) : textureData.format;\\n\\t\\t\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: url,\\n\\t\\t\\t\\t\\t\\taddressU: textureData.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,\\n\\t\\t\\t\\t\\t\\taddressV: textureData.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,\\n\\t\\t\\t\\t\\t\\twidth: textureData.width,\\n\\t\\t\\t\\t\\t\\theight: textureData.height,\\n\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\tcubemap: textureData.cubemap,\\n\\t\\t\\t\\t\\t\\tlevels: textureData.levels,\\n\\t\\t\\t\\t\\t\\t...textureOptions\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\ttexture.upload();\\n\\t\\t\\t\\treturn texture;\\n\\t\\t}\\n\\t\\tparse(data) {\\n\\t\\t\\t\\tconst dataU32 = new Uint32Array(data);\\n\\t\\t\\t\\tif (IDENTIFIER[0] !== dataU32[0] || IDENTIFIER[1] !== dataU32[1] || IDENTIFIER[2] !== dataU32[2]) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst header = {\\n\\t\\t\\t\\t\\t\\tendianness: dataU32[3],\\n\\t\\t\\t\\t\\t\\tglType: dataU32[4],\\n\\t\\t\\t\\t\\t\\tglTypeSize: dataU32[5],\\n\\t\\t\\t\\t\\t\\tglFormat: dataU32[6],\\n\\t\\t\\t\\t\\t\\tglInternalFormat: dataU32[7],\\n\\t\\t\\t\\t\\t\\tglBaseInternalFormat: dataU32[8],\\n\\t\\t\\t\\t\\t\\tpixelWidth: dataU32[9],\\n\\t\\t\\t\\t\\t\\tpixelHeight: dataU32[10],\\n\\t\\t\\t\\t\\t\\tpixelDepth: dataU32[11],\\n\\t\\t\\t\\t\\t\\tnumberOfArrayElements: dataU32[12],\\n\\t\\t\\t\\t\\t\\tnumberOfFaces: dataU32[13],\\n\\t\\t\\t\\t\\t\\tnumberOfMipmapLevels: dataU32[14],\\n\\t\\t\\t\\t\\t\\tbytesOfKeyValueData: dataU32[15]\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tif (header.pixelDepth > 1) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (header.numberOfArrayElements !== 0) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst format = KNOWN_FORMATS[header.glInternalFormat];\\n\\t\\t\\t\\tif (format === undefined) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet offset = 16 + header.bytesOfKeyValueData / 4;\\n\\t\\t\\t\\tconst isCubemap = header.numberOfFaces > 1;\\n\\t\\t\\t\\tconst levels = [];\\n\\t\\t\\t\\tfor(let mipmapLevel = 0; mipmapLevel < (header.numberOfMipmapLevels || 1); mipmapLevel++){\\n\\t\\t\\t\\t\\t\\tconst imageSizeInBytes = dataU32[offset++];\\n\\t\\t\\t\\t\\t\\tif (isCubemap) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlevels.push([]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst target = isCubemap ? levels[mipmapLevel] : levels;\\n\\t\\t\\t\\t\\t\\tfor(let face = 0; face < (isCubemap ? 6 : 1); ++face){\\n\\t\\t\\t\\t\\t\\t\\t\\ttarget.push(createContainer(format, data, offset * 4, imageSizeInBytes));\\n\\t\\t\\t\\t\\t\\t\\t\\toffset += imageSizeInBytes + 3 >> 2;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\twidth: header.pixelWidth,\\n\\t\\t\\t\\t\\t\\theight: header.pixelHeight,\\n\\t\\t\\t\\t\\t\\tlevels: levels,\\n\\t\\t\\t\\t\\t\\tcubemap: isCubemap\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tconstructor(registry){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.maxRetries = 0;\\n\\t\\t}\\n}\\n\\nconst KHRConstants = {\\n\\t\\tKHR_DF_MODEL_UASTC: 166\\n};\\nclass Ktx2Parser extends TextureParser {\\n\\t\\tload(url, callback, asset) {\\n\\t\\t\\t\\tAsset.fetchArrayBuffer(url.load, (err, result)=>{\\n\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(err, result);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.parse(result, url, callback, asset);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}, asset, this.maxRetries);\\n\\t\\t}\\n\\t\\topen(url, data, device, textureOptions = {}) {\\n\\t\\t\\t\\tconst format = textureOptions.srgb ? pixelFormatLinearToGamma(data.format) : data.format;\\n\\t\\t\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: url,\\n\\t\\t\\t\\t\\t\\taddressU: data.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,\\n\\t\\t\\t\\t\\t\\taddressV: data.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,\\n\\t\\t\\t\\t\\t\\twidth: data.width,\\n\\t\\t\\t\\t\\t\\theight: data.height,\\n\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\tcubemap: data.cubemap,\\n\\t\\t\\t\\t\\t\\tlevels: data.levels,\\n\\t\\t\\t\\t\\t\\t...textureOptions\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\ttexture.upload();\\n\\t\\t\\t\\treturn texture;\\n\\t\\t}\\n\\t\\tparse(arraybuffer, url, callback, asset) {\\n\\t\\t\\t\\tconst rs = new ReadStream(arraybuffer);\\n\\t\\t\\t\\tconst magic = [\\n\\t\\t\\t\\t\\t\\trs.readU32be(),\\n\\t\\t\\t\\t\\t\\trs.readU32be(),\\n\\t\\t\\t\\t\\t\\trs.readU32be()\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tif (magic[0] !== 0xAB4B5458 || magic[1] !== 0x203230BB || magic[2] !== 0x0D0A1A0A) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst header = {\\n\\t\\t\\t\\t\\t\\tvkFormat: rs.readU32(),\\n\\t\\t\\t\\t\\t\\ttypeSize: rs.readU32(),\\n\\t\\t\\t\\t\\t\\tpixelWidth: rs.readU32(),\\n\\t\\t\\t\\t\\t\\tpixelHeight: rs.readU32(),\\n\\t\\t\\t\\t\\t\\tpixelDepth: rs.readU32(),\\n\\t\\t\\t\\t\\t\\tlayerCount: rs.readU32(),\\n\\t\\t\\t\\t\\t\\tfaceCount: rs.readU32(),\\n\\t\\t\\t\\t\\t\\tlevelCount: rs.readU32(),\\n\\t\\t\\t\\t\\t\\tsupercompressionScheme: rs.readU32()\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst index = {\\n\\t\\t\\t\\t\\t\\tdfdByteOffset: rs.readU32(),\\n\\t\\t\\t\\t\\t\\tdfdByteLength: rs.readU32(),\\n\\t\\t\\t\\t\\t\\tkvdByteOffset: rs.readU32(),\\n\\t\\t\\t\\t\\t\\tkvdByteLength: rs.readU32(),\\n\\t\\t\\t\\t\\t\\tsgdByteOffset: rs.readU64(),\\n\\t\\t\\t\\t\\t\\tsgdByteLength: rs.readU64()\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst levels = [];\\n\\t\\t\\t\\tfor(let i = 0; i < Math.max(1, header.levelCount); ++i){\\n\\t\\t\\t\\t\\t\\tlevels.push({\\n\\t\\t\\t\\t\\t\\t\\t\\tbyteOffset: rs.readU64(),\\n\\t\\t\\t\\t\\t\\t\\t\\tbyteLength: rs.readU64(),\\n\\t\\t\\t\\t\\t\\t\\t\\tuncompressedByteLength: rs.readU64()\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst dfdTotalSize = rs.readU32();\\n\\t\\t\\t\\tif (dfdTotalSize !== index.kvdByteOffset - index.dfdByteOffset) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\trs.skip(8);\\n\\t\\t\\t\\tconst colorModel = rs.readU8();\\n\\t\\t\\t\\trs.skip(index.dfdByteLength - 9);\\n\\t\\t\\t\\trs.skip(index.kvdByteLength);\\n\\t\\t\\t\\tif (header.supercompressionScheme === 1 || colorModel === KHRConstants.KHR_DF_MODEL_UASTC) {\\n\\t\\t\\t\\t\\t\\tconst basisModuleFound = basisTranscode(this.device, url.load, arraybuffer, callback, {\\n\\t\\t\\t\\t\\t\\t\\t\\tisGGGR: (asset?.file?.variants?.basis?.opt & 8) !== 0,\\n\\t\\t\\t\\t\\t\\t\\t\\tisKTX2: true\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tif (!basisModuleFound) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(`Basis module not found. Asset [${asset.name}](${asset.getFileUrl()}) basis texture variant will not be loaded.`);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tcallback('unsupported KTX2 pixel format');\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(registry, device){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.maxRetries = 0;\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t}\\n}\\n\\nclass DdsParser extends TextureParser {\\n\\t\\tload(url, callback, asset) {\\n\\t\\t\\t\\tAsset.fetchArrayBuffer(url.load, callback, asset, this.maxRetries);\\n\\t\\t}\\n\\t\\topen(url, data, device, textureOptions = {}) {\\n\\t\\t\\t\\tconst header = new Uint32Array(data, 0, 128 / 4);\\n\\t\\t\\t\\tconst width = header[4];\\n\\t\\t\\t\\tconst height = header[3];\\n\\t\\t\\t\\tconst mips = Math.max(header[7], 1);\\n\\t\\t\\t\\tconst isFourCc = header[20] === 4;\\n\\t\\t\\t\\tconst fcc = header[21];\\n\\t\\t\\t\\tconst bpp = header[22];\\n\\t\\t\\t\\tconst isCubemap = header[28] === 65024;\\n\\t\\t\\t\\tconst FCC_DXT1 = 827611204;\\n\\t\\t\\t\\tconst FCC_DXT5 = 894720068;\\n\\t\\t\\t\\tconst FCC_FP16 = 113;\\n\\t\\t\\t\\tconst FCC_FP32 = 116;\\n\\t\\t\\t\\tconst FCC_ETC1 = 826496069;\\n\\t\\t\\t\\tconst FCC_PVRTC_2BPP_RGB_1 = 825438800;\\n\\t\\t\\t\\tconst FCC_PVRTC_2BPP_RGBA_1 = 825504336;\\n\\t\\t\\t\\tconst FCC_PVRTC_4BPP_RGB_1 = 825439312;\\n\\t\\t\\t\\tconst FCC_PVRTC_4BPP_RGBA_1 = 825504848;\\n\\t\\t\\t\\tlet compressed = false;\\n\\t\\t\\t\\tlet etc1 = false;\\n\\t\\t\\t\\tlet pvrtc2 = false;\\n\\t\\t\\t\\tlet pvrtc4 = false;\\n\\t\\t\\t\\tlet format = null;\\n\\t\\t\\t\\tlet componentSize = 1;\\n\\t\\t\\t\\tlet texture;\\n\\t\\t\\t\\tif (isFourCc) {\\n\\t\\t\\t\\t\\t\\tif (fcc === FCC_DXT1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tformat = PIXELFORMAT_DXT1;\\n\\t\\t\\t\\t\\t\\t\\t\\tcompressed = true;\\n\\t\\t\\t\\t\\t\\t} else if (fcc === FCC_DXT5) {\\n\\t\\t\\t\\t\\t\\t\\t\\tformat = PIXELFORMAT_DXT5;\\n\\t\\t\\t\\t\\t\\t\\t\\tcompressed = true;\\n\\t\\t\\t\\t\\t\\t} else if (fcc === FCC_FP16) {\\n\\t\\t\\t\\t\\t\\t\\t\\tformat = PIXELFORMAT_RGBA16F;\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponentSize = 2;\\n\\t\\t\\t\\t\\t\\t} else if (fcc === FCC_FP32) {\\n\\t\\t\\t\\t\\t\\t\\t\\tformat = PIXELFORMAT_RGBA32F;\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponentSize = 4;\\n\\t\\t\\t\\t\\t\\t} else if (fcc === FCC_ETC1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tformat = PIXELFORMAT_ETC1;\\n\\t\\t\\t\\t\\t\\t\\t\\tcompressed = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tetc1 = true;\\n\\t\\t\\t\\t\\t\\t} else if (fcc === FCC_PVRTC_2BPP_RGB_1 || fcc === FCC_PVRTC_2BPP_RGBA_1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tformat = fcc === FCC_PVRTC_2BPP_RGB_1 ? PIXELFORMAT_PVRTC_2BPP_RGB_1 : PIXELFORMAT_PVRTC_2BPP_RGBA_1;\\n\\t\\t\\t\\t\\t\\t\\t\\tcompressed = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tpvrtc2 = true;\\n\\t\\t\\t\\t\\t\\t} else if (fcc === FCC_PVRTC_4BPP_RGB_1 || fcc === FCC_PVRTC_4BPP_RGBA_1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tformat = fcc === FCC_PVRTC_4BPP_RGB_1 ? PIXELFORMAT_PVRTC_4BPP_RGB_1 : PIXELFORMAT_PVRTC_4BPP_RGBA_1;\\n\\t\\t\\t\\t\\t\\t\\t\\tcompressed = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tpvrtc4 = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (bpp === 32) {\\n\\t\\t\\t\\t\\t\\t\\t\\tformat = PIXELFORMAT_RGBA8;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!format) {\\n\\t\\t\\t\\t\\t\\ttexture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\t\\t\\twidth: 4,\\n\\t\\t\\t\\t\\t\\t\\t\\theight: 4,\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGB8,\\n\\t\\t\\t\\t\\t\\t\\t\\tname: 'dds-legacy-empty'\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\treturn texture;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttexture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: url,\\n\\t\\t\\t\\t\\t\\taddressU: isCubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,\\n\\t\\t\\t\\t\\t\\taddressV: isCubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,\\n\\t\\t\\t\\t\\t\\twidth: width,\\n\\t\\t\\t\\t\\t\\theight: height,\\n\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\tcubemap: isCubemap,\\n\\t\\t\\t\\t\\t\\tmipmaps: mips > 1,\\n\\t\\t\\t\\t\\t\\t...textureOptions\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tlet offset = 128;\\n\\t\\t\\t\\tconst faces = isCubemap ? 6 : 1;\\n\\t\\t\\t\\tlet mipSize;\\n\\t\\t\\t\\tconst DXT_BLOCK_WIDTH = 4;\\n\\t\\t\\t\\tconst DXT_BLOCK_HEIGHT = 4;\\n\\t\\t\\t\\tconst blockSize = fcc === FCC_DXT1 ? 8 : 16;\\n\\t\\t\\t\\tlet numBlocksAcross, numBlocksDown, numBlocks;\\n\\t\\t\\t\\tfor(let face = 0; face < faces; face++){\\n\\t\\t\\t\\t\\t\\tlet mipWidth = width;\\n\\t\\t\\t\\t\\t\\tlet mipHeight = height;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < mips; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tif (compressed) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (etc1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmipSize = Math.floor((mipWidth + 3) / 4) * Math.floor((mipHeight + 3) / 4) * 8;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else if (pvrtc2) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmipSize = Math.max(mipWidth, 16) * Math.max(mipHeight, 8) / 4;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else if (pvrtc4) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmipSize = Math.max(mipWidth, 8) * Math.max(mipHeight, 8) / 2;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnumBlocksAcross = Math.floor((mipWidth + DXT_BLOCK_WIDTH - 1) / DXT_BLOCK_WIDTH);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnumBlocksDown = Math.floor((mipHeight + DXT_BLOCK_HEIGHT - 1) / DXT_BLOCK_HEIGHT);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tnumBlocks = numBlocksAcross * numBlocksDown;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmipSize = numBlocks * blockSize;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmipSize = mipWidth * mipHeight * 4;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\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\\t\\t\\t\\t\\tif (!isCubemap) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture._levels[i] = mipBuff;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!texture._levels[i]) texture._levels[i] = [];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttexture._levels[i][face] = mipBuff;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\toffset += mipSize * componentSize;\\n\\t\\t\\t\\t\\t\\t\\t\\tmipWidth = Math.max(mipWidth * 0.5, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tmipHeight = Math.max(mipHeight * 0.5, 1);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\ttexture.upload();\\n\\t\\t\\t\\treturn texture;\\n\\t\\t}\\n\\t\\tconstructor(registry){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.maxRetries = 0;\\n\\t\\t}\\n}\\n\\nclass HdrParser extends TextureParser {\\n\\t\\tload(url, callback, asset) {\\n\\t\\t\\t\\tAsset.fetchArrayBuffer(url.load, callback, asset, this.maxRetries);\\n\\t\\t\\t\\tif (asset.data && !asset.data.type) {\\n\\t\\t\\t\\t\\t\\tasset.data.type = TEXTURETYPE_RGBE;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\topen(url, data, device, textureOptions = {}) {\\n\\t\\t\\t\\tconst textureData = this.parse(data);\\n\\t\\t\\t\\tif (!textureData) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst texture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: url,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_REPEAT,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\twidth: textureData.width,\\n\\t\\t\\t\\t\\t\\theight: textureData.height,\\n\\t\\t\\t\\t\\t\\tlevels: textureData.levels,\\n\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGBA8,\\n\\t\\t\\t\\t\\t\\ttype: TEXTURETYPE_RGBE,\\n\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\t...textureOptions\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\ttexture.upload();\\n\\t\\t\\t\\treturn texture;\\n\\t\\t}\\n\\t\\tparse(data) {\\n\\t\\t\\t\\tconst readStream = new ReadStream(data);\\n\\t\\t\\t\\tconst magic = readStream.readLine();\\n\\t\\t\\t\\tif (!magic.startsWith('#?RADIANCE')) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst variables = {};\\n\\t\\t\\t\\twhile(true){\\n\\t\\t\\t\\t\\t\\tconst line = readStream.readLine();\\n\\t\\t\\t\\t\\t\\tif (line.length === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst parts = line.split('=');\\n\\t\\t\\t\\t\\t\\t\\t\\tif (parts.length === 2) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvariables[parts[0]] = parts[1];\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!variables.hasOwnProperty('FORMAT')) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst resolution = readStream.readLine().split(' ');\\n\\t\\t\\t\\tif (resolution.length !== 4) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst height = parseInt(resolution[1], 10);\\n\\t\\t\\t\\tconst width = parseInt(resolution[3], 10);\\n\\t\\t\\t\\tconst pixels = this._readPixels(readStream, width, height, resolution[0] === '-Y');\\n\\t\\t\\t\\tif (!pixels) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\twidth: width,\\n\\t\\t\\t\\t\\t\\theight: height,\\n\\t\\t\\t\\t\\t\\tlevels: [\\n\\t\\t\\t\\t\\t\\t\\t\\tpixels\\n\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\t_readPixels(readStream, width, height, flipY) {\\n\\t\\t\\t\\tif (width < 8 || width > 0x7fff) {\\n\\t\\t\\t\\t\\t\\treturn this._readPixelsFlat(readStream, width, height);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst rgbe = [\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\treadStream.readArray(rgbe);\\n\\t\\t\\t\\tif (rgbe[0] !== 2 || rgbe[1] !== 2 || (rgbe[2] & 0x80) !== 0) {\\n\\t\\t\\t\\t\\t\\treadStream.skip(-4);\\n\\t\\t\\t\\t\\t\\treturn this._readPixelsFlat(readStream, width, height);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst buffer = new ArrayBuffer(width * height * 4);\\n\\t\\t\\t\\tconst view = new Uint8Array(buffer);\\n\\t\\t\\t\\tlet scanstart = flipY ? 0 : width * 4 * (height - 1);\\n\\t\\t\\t\\tlet x, y, i, channel, count, value;\\n\\t\\t\\t\\tfor(y = 0; y < height; ++y){\\n\\t\\t\\t\\t\\t\\tif (y) {\\n\\t\\t\\t\\t\\t\\t\\t\\treadStream.readArray(rgbe);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif ((rgbe[2] << 8) + rgbe[3] !== width) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tfor(channel = 0; channel < 4; ++channel){\\n\\t\\t\\t\\t\\t\\t\\t\\tx = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\twhile(x < width){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcount = readStream.readU8();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (count > 128) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcount -= 128;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (x + count > width) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvalue = readStream.readU8();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(i = 0; i < count; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tview[scanstart + channel + 4 * x++] = value;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (count === 0 || x + count > width) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(i = 0; i < count; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tview[scanstart + channel + 4 * x++] = readStream.readU8();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t\\t\\tscanstart += width * 4 * (flipY ? 1 : -1);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn view;\\n\\t\\t}\\n\\t\\t_readPixelsFlat(readStream, width, height) {\\n\\t\\t\\t\\treturn readStream.remainingBytes === width * height * 4 ? new Uint8Array(readStream.arraybuffer, readStream.offset) : null;\\n\\t\\t}\\n\\t\\tconstructor(registry){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.maxRetries = 0;\\n\\t\\t}\\n}\\n\\nconst JSON_ADDRESS_MODE = {\\n\\t\\t'repeat': ADDRESS_REPEAT,\\n\\t\\t'clamp': ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t'mirror': ADDRESS_MIRRORED_REPEAT\\n};\\nconst JSON_FILTER_MODE = {\\n\\t\\t'nearest': FILTER_NEAREST,\\n\\t\\t'linear': FILTER_LINEAR,\\n\\t\\t'nearest_mip_nearest': FILTER_NEAREST_MIPMAP_NEAREST,\\n\\t\\t'linear_mip_nearest': FILTER_LINEAR_MIPMAP_NEAREST,\\n\\t\\t'nearest_mip_linear': FILTER_NEAREST_MIPMAP_LINEAR,\\n\\t\\t'linear_mip_linear': FILTER_LINEAR_MIPMAP_LINEAR\\n};\\nconst JSON_TEXTURE_TYPE = {\\n\\t\\t'default': TEXTURETYPE_DEFAULT,\\n\\t\\t'rgbm': TEXTURETYPE_RGBM,\\n\\t\\t'rgbe': TEXTURETYPE_RGBE,\\n\\t\\t'rgbp': TEXTURETYPE_RGBP,\\n\\t\\t'swizzleGGGR': TEXTURETYPE_SWIZZLEGGGR\\n};\\nconst _completePartialMipmapChain = function(texture) {\\n\\t\\tconst requiredMipLevels = TextureUtils.calcMipLevelsCount(texture._width, texture._height);\\n\\t\\tconst isHtmlElement = function(object) {\\n\\t\\t\\t\\treturn object instanceof HTMLCanvasElement || object instanceof HTMLImageElement || object instanceof HTMLVideoElement;\\n\\t\\t};\\n\\t\\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\\t\\t\\treturn;\\n\\t\\t}\\n\\t\\tconst downsample = function(width, height, data) {\\n\\t\\t\\t\\tconst sampledWidth = Math.max(1, width >> 1);\\n\\t\\t\\t\\tconst sampledHeight = Math.max(1, height >> 1);\\n\\t\\t\\t\\tconst sampledData = new data.constructor(sampledWidth * sampledHeight * 4);\\n\\t\\t\\t\\tconst xs = Math.floor(width / sampledWidth);\\n\\t\\t\\t\\tconst ys = Math.floor(height / sampledHeight);\\n\\t\\t\\t\\tconst xsys = xs * ys;\\n\\t\\t\\t\\tfor(let y = 0; y < sampledHeight; ++y){\\n\\t\\t\\t\\t\\t\\tfor(let x = 0; x < sampledWidth; ++x){\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let e = 0; e < 4; ++e){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlet sum = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let sy = 0; sy < ys; ++sy){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let sx = 0; sx < xs; ++sx){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsum += data[(x * xs + sx + (y * ys + sy) * width) * 4 + e];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tsampledData[(x + y * sampledWidth) * 4 + e] = sum / xsys;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn sampledData;\\n\\t\\t};\\n\\t\\tfor(let level = texture._levels.length; level < requiredMipLevels; ++level){\\n\\t\\t\\t\\tconst width = Math.max(1, texture._width >> level - 1);\\n\\t\\t\\t\\tconst height = Math.max(1, texture._height >> level - 1);\\n\\t\\t\\t\\tif (texture._cubemap) {\\n\\t\\t\\t\\t\\t\\tconst mips = [];\\n\\t\\t\\t\\t\\t\\tfor(let face = 0; face < 6; ++face){\\n\\t\\t\\t\\t\\t\\t\\t\\tmips.push(downsample(width, height, texture._levels[level - 1][face]));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\ttexture._levels.push(mips);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\ttexture._levels.push(downsample(width, height, texture._levels[level - 1]));\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\ttexture._levelsUpdated = texture._cubemap ? [\\n\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\ttrue,\\n\\t\\t\\t\\t\\t\\ttrue,\\n\\t\\t\\t\\t\\t\\ttrue,\\n\\t\\t\\t\\t\\t\\ttrue,\\n\\t\\t\\t\\t\\t\\ttrue,\\n\\t\\t\\t\\t\\t\\ttrue\\n\\t\\t\\t\\t]\\n\\t\\t] : [\\n\\t\\t\\t\\ttrue\\n\\t\\t];\\n};\\nclass TextureHandler extends ResourceHandler {\\n\\t\\tset crossOrigin(value) {\\n\\t\\t\\t\\tthis.imgParser.crossOrigin = value;\\n\\t\\t}\\n\\t\\tget crossOrigin() {\\n\\t\\t\\t\\treturn this.imgParser.crossOrigin;\\n\\t\\t}\\n\\t\\tset maxRetries(value) {\\n\\t\\t\\t\\tthis.imgParser.maxRetries = value;\\n\\t\\t\\t\\tfor(const parser in this.parsers){\\n\\t\\t\\t\\t\\t\\tif (this.parsers.hasOwnProperty(parser)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.parsers[parser].maxRetries = value;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget maxRetries() {\\n\\t\\t\\t\\treturn this.imgParser.maxRetries;\\n\\t\\t}\\n\\t\\t_getUrlWithoutParams(url) {\\n\\t\\t\\t\\treturn url.indexOf('?') >= 0 ? url.split('?')[0] : url;\\n\\t\\t}\\n\\t\\t_getParser(url) {\\n\\t\\t\\t\\tconst ext = path.getExtension(this._getUrlWithoutParams(url)).toLowerCase().replace('.', '');\\n\\t\\t\\t\\treturn this.parsers[ext] || this.imgParser;\\n\\t\\t}\\n\\t\\t_getTextureOptions(asset) {\\n\\t\\t\\t\\tconst options = {};\\n\\t\\t\\t\\tif (asset) {\\n\\t\\t\\t\\t\\t\\tif (asset.name?.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.name = asset.name;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst assetData = asset.data;\\n\\t\\t\\t\\t\\t\\tif (assetData.hasOwnProperty('minfilter')) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.minFilter = JSON_FILTER_MODE[assetData.minfilter];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (assetData.hasOwnProperty('magfilter')) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.magFilter = JSON_FILTER_MODE[assetData.magfilter];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (assetData.hasOwnProperty('addressu')) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.addressU = JSON_ADDRESS_MODE[assetData.addressu];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (assetData.hasOwnProperty('addressv')) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.addressV = JSON_ADDRESS_MODE[assetData.addressv];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (assetData.hasOwnProperty('mipmaps')) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.mipmaps = assetData.mipmaps;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (assetData.hasOwnProperty('anisotropy')) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.anisotropy = assetData.anisotropy;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (assetData.hasOwnProperty('flipY')) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.flipY = !!assetData.flipY;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (assetData.hasOwnProperty('srgb')) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.srgb = !!assetData.srgb;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\toptions.type = TEXTURETYPE_DEFAULT;\\n\\t\\t\\t\\t\\t\\tif (assetData.hasOwnProperty('type')) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.type = JSON_TEXTURE_TYPE[assetData.type];\\n\\t\\t\\t\\t\\t\\t} else if (assetData.hasOwnProperty('rgbm') && assetData.rgbm) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.type = TEXTURETYPE_RGBM;\\n\\t\\t\\t\\t\\t\\t} else if (asset.file && (asset.file.opt & 8) !== 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\toptions.type = TEXTURETYPE_SWIZZLEGGGR;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn options;\\n\\t\\t}\\n\\t\\tload(url, callback, asset) {\\n\\t\\t\\t\\tif (typeof url === 'string') {\\n\\t\\t\\t\\t\\t\\turl = {\\n\\t\\t\\t\\t\\t\\t\\t\\tload: url,\\n\\t\\t\\t\\t\\t\\t\\t\\toriginal: url\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._getParser(url.original).load(url, callback, asset);\\n\\t\\t}\\n\\t\\topen(url, data, asset) {\\n\\t\\t\\t\\tif (!url) {\\n\\t\\t\\t\\t\\t\\treturn undefined;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst textureOptions = this._getTextureOptions(asset);\\n\\t\\t\\t\\tlet texture = this._getParser(url).open(url, data, this._device, textureOptions);\\n\\t\\t\\t\\tif (texture === null) {\\n\\t\\t\\t\\t\\t\\ttexture = new Texture(this._device, {\\n\\t\\t\\t\\t\\t\\t\\t\\twidth: 4,\\n\\t\\t\\t\\t\\t\\t\\t\\theight: 4,\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGB8\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t_completePartialMipmapChain(texture);\\n\\t\\t\\t\\t\\t\\tif (data.unswizzledGGGR) {\\n\\t\\t\\t\\t\\t\\t\\t\\tasset.file.variants.basis.opt &= -9;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn texture;\\n\\t\\t}\\n\\t\\tpatch(asset, assets) {\\n\\t\\t\\t\\tconst texture = asset.resource;\\n\\t\\t\\t\\tif (!texture) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst options = this._getTextureOptions(asset);\\n\\t\\t\\t\\tfor (const key of Object.keys(options)){\\n\\t\\t\\t\\t\\t\\ttexture[key] = options[key];\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tsuper(app, 'texture');\\n\\t\\t\\t\\tconst assets = app.assets;\\n\\t\\t\\t\\tconst device = app.graphicsDevice;\\n\\t\\t\\t\\tthis._device = device;\\n\\t\\t\\t\\tthis._assets = assets;\\n\\t\\t\\t\\tthis.imgParser = new ImgParser(assets, device);\\n\\t\\t\\t\\tthis.parsers = {\\n\\t\\t\\t\\t\\t\\tdds: new DdsParser(assets),\\n\\t\\t\\t\\t\\t\\tktx: new KtxParser(assets),\\n\\t\\t\\t\\t\\t\\tktx2: new Ktx2Parser(assets, device),\\n\\t\\t\\t\\t\\t\\tbasis: new BasisParser(assets, device),\\n\\t\\t\\t\\t\\t\\thdr: new HdrParser(assets)\\n\\t\\t\\t\\t};\\n\\t\\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\\tget supported() {\\n\\t\\t\\t\\treturn this._supported;\\n\\t\\t}\\n\\t\\tget available() {\\n\\t\\t\\t\\treturn this._supported && this._manager.active && this._manager._session.domOverlayState !== null;\\n\\t\\t}\\n\\t\\tget state() {\\n\\t\\t\\t\\tif (!this._supported || !this._manager.active || !this._manager._session.domOverlayState) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._manager._session.domOverlayState.type;\\n\\t\\t}\\n\\t\\tset root(value) {\\n\\t\\t\\t\\tif (!this._supported || this._manager.active) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._root = value;\\n\\t\\t}\\n\\t\\tget root() {\\n\\t\\t\\t\\treturn this._root;\\n\\t\\t}\\n\\t\\tconstructor(manager){\\n\\t\\t\\t\\tthis._supported = platform.browser && !!window.XRDOMOverlayState;\\n\\t\\t\\t\\tthis._root = null;\\n\\t\\t\\t\\tthis._manager = manager;\\n\\t\\t}\\n}\\n\\nconst poolVec3 = [];\\nconst poolQuat = [];\\nclass XrHitTestSource extends EventHandler {\\n\\t\\tremove() {\\n\\t\\t\\t\\tif (!this._xrHitTestSource) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst sources = this.manager.hitTest.sources;\\n\\t\\t\\t\\tconst ind = sources.indexOf(this);\\n\\t\\t\\t\\tif (ind !== -1) sources.splice(ind, 1);\\n\\t\\t\\t\\tthis.onStop();\\n\\t\\t}\\n\\t\\tonStop() {\\n\\t\\t\\t\\tthis._xrHitTestSource.cancel();\\n\\t\\t\\t\\tthis._xrHitTestSource = null;\\n\\t\\t\\t\\tthis.fire('remove');\\n\\t\\t\\t\\tthis.manager.hitTest.fire('remove', this);\\n\\t\\t}\\n\\t\\tupdate(frame) {\\n\\t\\t\\t\\tif (this._transient) {\\n\\t\\t\\t\\t\\t\\tconst transientResults = frame.getHitTestResultsForTransientInput(this._xrHitTestSource);\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < transientResults.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst transientResult = transientResults[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!transientResult.results.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tlet inputSource;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (transientResult.inputSource) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinputSource = this.manager.input._getByInputSource(transientResult.inputSource);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.updateHitResults(transientResult.results, inputSource);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst results = frame.getHitTestResults(this._xrHitTestSource);\\n\\t\\t\\t\\t\\t\\tif (!results.length) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.updateHitResults(results);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdateHitResults(results, inputSource) {\\n\\t\\t\\t\\tif (this._inputSource && this._inputSource !== inputSource) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst origin = poolVec3.pop() ?? new Vec3();\\n\\t\\t\\t\\tif (inputSource) {\\n\\t\\t\\t\\t\\t\\torigin.copy(inputSource.getOrigin());\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\torigin.copy(this.manager.camera.getPosition());\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet candidateDistance = Infinity;\\n\\t\\t\\t\\tlet candidateHitTestResult = null;\\n\\t\\t\\t\\tconst position = poolVec3.pop() ?? new Vec3();\\n\\t\\t\\t\\tconst rotation = poolQuat.pop() ?? new Quat();\\n\\t\\t\\t\\tfor(let i = 0; i < results.length; i++){\\n\\t\\t\\t\\t\\t\\tconst pose = results[i].getPose(this.manager._referenceSpace);\\n\\t\\t\\t\\t\\t\\tconst distance = origin.distance(pose.transform.position);\\n\\t\\t\\t\\t\\t\\tif (distance >= candidateDistance) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tcandidateDistance = distance;\\n\\t\\t\\t\\t\\t\\tcandidateHitTestResult = results[i];\\n\\t\\t\\t\\t\\t\\tposition.copy(pose.transform.position);\\n\\t\\t\\t\\t\\t\\trotation.copy(pose.transform.orientation);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.fire('result', position, rotation, inputSource || this._inputSource, candidateHitTestResult);\\n\\t\\t\\t\\tthis.manager.hitTest.fire('result', this, position, rotation, inputSource || this._inputSource, candidateHitTestResult);\\n\\t\\t\\t\\tpoolVec3.push(origin);\\n\\t\\t\\t\\tpoolVec3.push(position);\\n\\t\\t\\t\\tpoolQuat.push(rotation);\\n\\t\\t}\\n\\t\\tconstructor(manager, xrHitTestSource, transient, inputSource = null){\\n\\t\\t\\t\\tsuper();\\n\\t\\t\\t\\tthis.manager = manager;\\n\\t\\t\\t\\tthis._xrHitTestSource = xrHitTestSource;\\n\\t\\t\\t\\tthis._transient = transient;\\n\\t\\t\\t\\tthis._inputSource = inputSource;\\n\\t\\t}\\n}\\nXrHitTestSource.EVENT_REMOVE = 'remove';\\nXrHitTestSource.EVENT_RESULT = 'result';\\n\\nclass XrHitTest extends EventHandler {\\n\\t\\t_onSessionStart() {\\n\\t\\t\\t\\tif (this.manager.session.enabledFeatures) {\\n\\t\\t\\t\\t\\t\\tconst available = this.manager.session.enabledFeatures.indexOf('hit-test') !== -1;\\n\\t\\t\\t\\t\\t\\tif (!available) return;\\n\\t\\t\\t\\t\\t\\tthis._available = available;\\n\\t\\t\\t\\t\\t\\tthis.fire('available');\\n\\t\\t\\t\\t} else if (!this._checkingAvailability) {\\n\\t\\t\\t\\t\\t\\tthis._checkingAvailability = true;\\n\\t\\t\\t\\t\\t\\tthis.manager.session.requestReferenceSpace(XRSPACE_VIEWER).then((referenceSpace)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.manager.session.requestHitTestSource({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tspace: referenceSpace\\n\\t\\t\\t\\t\\t\\t\\t\\t}).then((hitTestSource)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\thitTestSource.cancel();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this.manager.active) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._available = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('available');\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t}).catch(()=>{});\\n\\t\\t\\t\\t\\t\\t}).catch(()=>{});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onSessionEnd() {\\n\\t\\t\\t\\tif (!this._available) return;\\n\\t\\t\\t\\tthis._available = false;\\n\\t\\t\\t\\tfor(let i = 0; i < this.sources.length; i++){\\n\\t\\t\\t\\t\\t\\tthis.sources[i].onStop();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.sources = [];\\n\\t\\t\\t\\tthis.fire('unavailable');\\n\\t\\t}\\n\\t\\tstart(options = {}) {\\n\\t\\t\\t\\tif (!this._supported) {\\n\\t\\t\\t\\t\\t\\toptions.callback?.(new Error('XR HitTest is not supported'), null);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._available) {\\n\\t\\t\\t\\t\\t\\toptions.callback?.(new Error('XR HitTest is not available'), null);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!options.profile && !options.spaceType) {\\n\\t\\t\\t\\t\\t\\toptions.spaceType = XRSPACE_VIEWER;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet xrRay;\\n\\t\\t\\t\\tconst offsetRay = options.offsetRay;\\n\\t\\t\\t\\tif (offsetRay) {\\n\\t\\t\\t\\t\\t\\tconst origin = new DOMPoint(offsetRay.origin.x, offsetRay.origin.y, offsetRay.origin.z, 1.0);\\n\\t\\t\\t\\t\\t\\tconst direction = new DOMPoint(offsetRay.direction.x, offsetRay.direction.y, offsetRay.direction.z, 0.0);\\n\\t\\t\\t\\t\\t\\txrRay = new XRRay(origin, direction);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst callback = options.callback;\\n\\t\\t\\t\\tif (options.spaceType) {\\n\\t\\t\\t\\t\\t\\tthis.manager.session.requestReferenceSpace(options.spaceType).then((referenceSpace)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!this.manager.session) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst err = new Error('XR Session is not started (2)');\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (callback) callback(err);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('error', err);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.manager.session.requestHitTestSource({\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tspace: referenceSpace,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tentityTypes: options.entityTypes || undefined,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\toffsetRay: xrRay\\n\\t\\t\\t\\t\\t\\t\\t\\t}).then((xrHitTestSource)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._onHitTestSource(xrHitTestSource, false, options.inputSource, callback);\\n\\t\\t\\t\\t\\t\\t\\t\\t}).catch((ex)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (callback) callback(ex);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('error', ex);\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t}).catch((ex)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (callback) callback(ex);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('error', ex);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.manager.session.requestHitTestSourceForTransientInput({\\n\\t\\t\\t\\t\\t\\t\\t\\tprofile: options.profile,\\n\\t\\t\\t\\t\\t\\t\\t\\tentityTypes: options.entityTypes || undefined,\\n\\t\\t\\t\\t\\t\\t\\t\\toffsetRay: xrRay\\n\\t\\t\\t\\t\\t\\t}).then((xrHitTestSource)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._onHitTestSource(xrHitTestSource, true, options.inputSource, callback);\\n\\t\\t\\t\\t\\t\\t}).catch((ex)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (callback) callback(ex);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('error', ex);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onHitTestSource(xrHitTestSource, transient, inputSource, callback) {\\n\\t\\t\\t\\tif (!this.manager.session) {\\n\\t\\t\\t\\t\\t\\txrHitTestSource.cancel();\\n\\t\\t\\t\\t\\t\\tconst err = new Error('XR Session is not started (3)');\\n\\t\\t\\t\\t\\t\\tif (callback) callback(err);\\n\\t\\t\\t\\t\\t\\tthis.fire('error', err);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst hitTestSource = new XrHitTestSource(this.manager, xrHitTestSource, transient, inputSource ?? null);\\n\\t\\t\\t\\tthis.sources.push(hitTestSource);\\n\\t\\t\\t\\tif (callback) callback(null, hitTestSource);\\n\\t\\t\\t\\tthis.fire('add', hitTestSource);\\n\\t\\t}\\n\\t\\tupdate(frame) {\\n\\t\\t\\t\\tif (!this._available) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < this.sources.length; i++){\\n\\t\\t\\t\\t\\t\\tthis.sources[i].update(frame);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget supported() {\\n\\t\\t\\t\\treturn this._supported;\\n\\t\\t}\\n\\t\\tget available() {\\n\\t\\t\\t\\treturn this._available;\\n\\t\\t}\\n\\t\\tconstructor(manager){\\n\\t\\t\\t\\tsuper(), this._supported = platform.browser && !!(window.XRSession && window.XRSession.prototype.requestHitTestSource), this._available = false, this._checkingAvailability = false, this.sources = [];\\n\\t\\t\\t\\tthis.manager = manager;\\n\\t\\t\\t\\tif (this._supported) {\\n\\t\\t\\t\\t\\t\\tthis.manager.on('start', this._onSessionStart, this);\\n\\t\\t\\t\\t\\t\\tthis.manager.on('end', this._onSessionEnd, this);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nXrHitTest.EVENT_AVAILABLE = 'available';\\nXrHitTest.EVENT_UNAVAILABLE = 'unavailable';\\nXrHitTest.EVENT_ADD = 'add';\\nXrHitTest.EVENT_REMOVE = 'remove';\\nXrHitTest.EVENT_RESULT = 'result';\\nXrHitTest.EVENT_ERROR = 'error';\\n\\nclass XrTrackedImage extends EventHandler {\\n\\t\\tget image() {\\n\\t\\t\\t\\treturn this._image;\\n\\t\\t}\\n\\t\\tset width(value) {\\n\\t\\t\\t\\tthis._width = value;\\n\\t\\t}\\n\\t\\tget width() {\\n\\t\\t\\t\\treturn this._width;\\n\\t\\t}\\n\\t\\tget trackable() {\\n\\t\\t\\t\\treturn this._trackable;\\n\\t\\t}\\n\\t\\tget tracking() {\\n\\t\\t\\t\\treturn this._tracking;\\n\\t\\t}\\n\\t\\tget emulated() {\\n\\t\\t\\t\\treturn this._emulated;\\n\\t\\t}\\n\\t\\tprepare() {\\n\\t\\t\\t\\tif (this._bitmap) {\\n\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\timage: this._bitmap,\\n\\t\\t\\t\\t\\t\\t\\t\\twidthInMeters: this._width\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn createImageBitmap(this._image).then((bitmap)=>{\\n\\t\\t\\t\\t\\t\\tthis._bitmap = bitmap;\\n\\t\\t\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\t\\t\\timage: this._bitmap,\\n\\t\\t\\t\\t\\t\\t\\t\\twidthInMeters: this._width\\n\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._image = null;\\n\\t\\t\\t\\tthis._pose = null;\\n\\t\\t\\t\\tif (this._bitmap) {\\n\\t\\t\\t\\t\\t\\tthis._bitmap.close();\\n\\t\\t\\t\\t\\t\\tthis._bitmap = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetPosition() {\\n\\t\\t\\t\\tif (this._pose) this._position.copy(this._pose.transform.position);\\n\\t\\t\\t\\treturn this._position;\\n\\t\\t}\\n\\t\\tgetRotation() {\\n\\t\\t\\t\\tif (this._pose) this._rotation.copy(this._pose.transform.orientation);\\n\\t\\t\\t\\treturn this._rotation;\\n\\t\\t}\\n\\t\\tconstructor(image, width){\\n\\t\\t\\t\\tsuper(), this._bitmap = null, this._measuredWidth = 0, this._trackable = false, this._tracking = false, this._emulated = false, this._pose = null, this._position = new Vec3(), this._rotation = new Quat();\\n\\t\\t\\t\\tthis._image = image;\\n\\t\\t\\t\\tthis._width = width;\\n\\t\\t}\\n}\\nXrTrackedImage.EVENT_TRACKED = 'tracked';\\nXrTrackedImage.EVENT_UNTRACKED = 'untracked';\\n\\nclass XrImageTracking extends EventHandler {\\n\\t\\tadd(image, width) {\\n\\t\\t\\t\\tif (!this._supported || this._manager.active) return null;\\n\\t\\t\\t\\tconst trackedImage = new XrTrackedImage(image, width);\\n\\t\\t\\t\\tthis._images.push(trackedImage);\\n\\t\\t\\t\\treturn trackedImage;\\n\\t\\t}\\n\\t\\tremove(trackedImage) {\\n\\t\\t\\t\\tif (this._manager.active) return;\\n\\t\\t\\t\\tconst ind = this._images.indexOf(trackedImage);\\n\\t\\t\\t\\tif (ind !== -1) {\\n\\t\\t\\t\\t\\t\\ttrackedImage.destroy();\\n\\t\\t\\t\\t\\t\\tthis._images.splice(ind, 1);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onSessionStart() {\\n\\t\\t\\t\\tthis._manager.session.getTrackedImageScores().then((images)=>{\\n\\t\\t\\t\\t\\t\\tthis._available = true;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < images.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._images[i]._trackable = images[i] === 'trackable';\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}).catch((err)=>{\\n\\t\\t\\t\\t\\t\\tthis._available = false;\\n\\t\\t\\t\\t\\t\\tthis.fire('error', err);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\t_onSessionEnd() {\\n\\t\\t\\t\\tthis._available = false;\\n\\t\\t\\t\\tfor(let i = 0; i < this._images.length; i++){\\n\\t\\t\\t\\t\\t\\tconst image = this._images[i];\\n\\t\\t\\t\\t\\t\\timage._pose = null;\\n\\t\\t\\t\\t\\t\\timage._measuredWidth = 0;\\n\\t\\t\\t\\t\\t\\tif (image._tracking) {\\n\\t\\t\\t\\t\\t\\t\\t\\timage._tracking = false;\\n\\t\\t\\t\\t\\t\\t\\t\\timage.fire('untracked');\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tprepareImages(callback) {\\n\\t\\t\\t\\tif (this._images.length) {\\n\\t\\t\\t\\t\\t\\tPromise.all(this._images.map((trackedImage)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\treturn trackedImage.prepare();\\n\\t\\t\\t\\t\\t\\t})).then((bitmaps)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(null, bitmaps);\\n\\t\\t\\t\\t\\t\\t}).catch((err)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(err, null);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tcallback(null, null);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdate(frame) {\\n\\t\\t\\t\\tif (!this._available) return;\\n\\t\\t\\t\\tconst results = frame.getImageTrackingResults();\\n\\t\\t\\t\\tconst index = {};\\n\\t\\t\\t\\tfor(let i = 0; i < results.length; i++){\\n\\t\\t\\t\\t\\t\\tindex[results[i].index] = results[i];\\n\\t\\t\\t\\t\\t\\tconst trackedImage = this._images[results[i].index];\\n\\t\\t\\t\\t\\t\\ttrackedImage._emulated = results[i].trackingState === 'emulated';\\n\\t\\t\\t\\t\\t\\ttrackedImage._measuredWidth = results[i].measuredWidthInMeters;\\n\\t\\t\\t\\t\\t\\ttrackedImage._pose = frame.getPose(results[i].imageSpace, this._manager._referenceSpace);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < this._images.length; i++){\\n\\t\\t\\t\\t\\t\\tif (this._images[i]._tracking && !index[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._images[i]._tracking = false;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._images[i].fire('untracked');\\n\\t\\t\\t\\t\\t\\t} else if (!this._images[i]._tracking && index[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._images[i]._tracking = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._images[i].fire('tracked');\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget supported() {\\n\\t\\t\\t\\treturn this._supported;\\n\\t\\t}\\n\\t\\tget available() {\\n\\t\\t\\t\\treturn this._available;\\n\\t\\t}\\n\\t\\tget images() {\\n\\t\\t\\t\\treturn this._images;\\n\\t\\t}\\n\\t\\tconstructor(manager){\\n\\t\\t\\t\\tsuper(), this._supported = platform.browser && !!window.XRImageTrackingResult, this._available = false, this._images = [];\\n\\t\\t\\t\\tthis._manager = manager;\\n\\t\\t\\t\\tif (this._supported) {\\n\\t\\t\\t\\t\\t\\tthis._manager.on('start', this._onSessionStart, this);\\n\\t\\t\\t\\t\\t\\tthis._manager.on('end', this._onSessionEnd, this);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nXrImageTracking.EVENT_ERROR = 'error';\\n\\nclass XrFinger {\\n\\t\\tget index() {\\n\\t\\t\\t\\treturn this._index;\\n\\t\\t}\\n\\t\\tget hand() {\\n\\t\\t\\t\\treturn this._hand;\\n\\t\\t}\\n\\t\\tget joints() {\\n\\t\\t\\t\\treturn this._joints;\\n\\t\\t}\\n\\t\\tget tip() {\\n\\t\\t\\t\\treturn this._tip;\\n\\t\\t}\\n\\t\\tconstructor(index, hand){\\n\\t\\t\\t\\tthis._joints = [];\\n\\t\\t\\t\\tthis._tip = null;\\n\\t\\t\\t\\tthis._index = index;\\n\\t\\t\\t\\tthis._hand = hand;\\n\\t\\t\\t\\tthis._hand._fingers.push(this);\\n\\t\\t}\\n}\\n\\nconst tipJointIds = platform.browser && window.XRHand ? [\\n\\t\\t'thumb-tip',\\n\\t\\t'index-finger-tip',\\n\\t\\t'middle-finger-tip',\\n\\t\\t'ring-finger-tip',\\n\\t\\t'pinky-finger-tip'\\n] : [];\\nconst tipJointIdsIndex = {};\\nfor(let i = 0; i < tipJointIds.length; i++){\\n\\t\\ttipJointIdsIndex[tipJointIds[i]] = true;\\n}\\nclass XrJoint {\\n\\t\\tupdate(pose) {\\n\\t\\t\\t\\tthis._dirtyLocal = true;\\n\\t\\t\\t\\tthis._radius = pose.radius;\\n\\t\\t\\t\\tthis._localPosition.copy(pose.transform.position);\\n\\t\\t\\t\\tthis._localRotation.copy(pose.transform.orientation);\\n\\t\\t}\\n\\t\\t_updateTransforms() {\\n\\t\\t\\t\\tif (this._dirtyLocal) {\\n\\t\\t\\t\\t\\t\\tthis._dirtyLocal = false;\\n\\t\\t\\t\\t\\t\\tthis._localTransform.setTRS(this._localPosition, this._localRotation, Vec3.ONE);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst manager = this._hand._manager;\\n\\t\\t\\t\\tconst parent = manager.camera.parent;\\n\\t\\t\\t\\tif (parent) {\\n\\t\\t\\t\\t\\t\\tthis._worldTransform.mul2(parent.getWorldTransform(), this._localTransform);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._worldTransform.copy(this._localTransform);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetPosition() {\\n\\t\\t\\t\\tthis._updateTransforms();\\n\\t\\t\\t\\tthis._worldTransform.getTranslation(this._position);\\n\\t\\t\\t\\treturn this._position;\\n\\t\\t}\\n\\t\\tgetRotation() {\\n\\t\\t\\t\\tthis._updateTransforms();\\n\\t\\t\\t\\tthis._rotation.setFromMat4(this._worldTransform);\\n\\t\\t\\t\\treturn this._rotation;\\n\\t\\t}\\n\\t\\tget id() {\\n\\t\\t\\t\\treturn this._id;\\n\\t\\t}\\n\\t\\tget index() {\\n\\t\\t\\t\\treturn this._index;\\n\\t\\t}\\n\\t\\tget hand() {\\n\\t\\t\\t\\treturn this._hand;\\n\\t\\t}\\n\\t\\tget finger() {\\n\\t\\t\\t\\treturn this._finger;\\n\\t\\t}\\n\\t\\tget wrist() {\\n\\t\\t\\t\\treturn this._wrist;\\n\\t\\t}\\n\\t\\tget tip() {\\n\\t\\t\\t\\treturn this._tip;\\n\\t\\t}\\n\\t\\tget radius() {\\n\\t\\t\\t\\treturn this._radius || 0.005;\\n\\t\\t}\\n\\t\\tconstructor(index, id, hand, finger = null){\\n\\t\\t\\t\\tthis._radius = null;\\n\\t\\t\\t\\tthis._localTransform = new Mat4();\\n\\t\\t\\t\\tthis._worldTransform = new Mat4();\\n\\t\\t\\t\\tthis._localPosition = new Vec3();\\n\\t\\t\\t\\tthis._localRotation = new Quat();\\n\\t\\t\\t\\tthis._position = new Vec3();\\n\\t\\t\\t\\tthis._rotation = new Quat();\\n\\t\\t\\t\\tthis._dirtyLocal = true;\\n\\t\\t\\t\\tthis._index = index;\\n\\t\\t\\t\\tthis._id = id;\\n\\t\\t\\t\\tthis._hand = hand;\\n\\t\\t\\t\\tthis._finger = finger;\\n\\t\\t\\t\\tthis._wrist = id === 'wrist';\\n\\t\\t\\t\\tthis._tip = this._finger && !!tipJointIdsIndex[id];\\n\\t\\t}\\n}\\n\\nlet fingerJointIds = [];\\nconst vecA = new Vec3();\\nconst vecB = new Vec3();\\nconst vecC = new Vec3();\\nif (platform.browser && window.XRHand) {\\n\\t\\tfingerJointIds = [\\n\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t'thumb-metacarpal',\\n\\t\\t\\t\\t\\t\\t'thumb-phalanx-proximal',\\n\\t\\t\\t\\t\\t\\t'thumb-phalanx-distal',\\n\\t\\t\\t\\t\\t\\t'thumb-tip'\\n\\t\\t\\t\\t],\\n\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t'index-finger-metacarpal',\\n\\t\\t\\t\\t\\t\\t'index-finger-phalanx-proximal',\\n\\t\\t\\t\\t\\t\\t'index-finger-phalanx-intermediate',\\n\\t\\t\\t\\t\\t\\t'index-finger-phalanx-distal',\\n\\t\\t\\t\\t\\t\\t'index-finger-tip'\\n\\t\\t\\t\\t],\\n\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t'middle-finger-metacarpal',\\n\\t\\t\\t\\t\\t\\t'middle-finger-phalanx-proximal',\\n\\t\\t\\t\\t\\t\\t'middle-finger-phalanx-intermediate',\\n\\t\\t\\t\\t\\t\\t'middle-finger-phalanx-distal',\\n\\t\\t\\t\\t\\t\\t'middle-finger-tip'\\n\\t\\t\\t\\t],\\n\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t'ring-finger-metacarpal',\\n\\t\\t\\t\\t\\t\\t'ring-finger-phalanx-proximal',\\n\\t\\t\\t\\t\\t\\t'ring-finger-phalanx-intermediate',\\n\\t\\t\\t\\t\\t\\t'ring-finger-phalanx-distal',\\n\\t\\t\\t\\t\\t\\t'ring-finger-tip'\\n\\t\\t\\t\\t],\\n\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t'pinky-finger-metacarpal',\\n\\t\\t\\t\\t\\t\\t'pinky-finger-phalanx-proximal',\\n\\t\\t\\t\\t\\t\\t'pinky-finger-phalanx-intermediate',\\n\\t\\t\\t\\t\\t\\t'pinky-finger-phalanx-distal',\\n\\t\\t\\t\\t\\t\\t'pinky-finger-tip'\\n\\t\\t\\t\\t]\\n\\t\\t];\\n}\\nclass XrHand extends EventHandler {\\n\\t\\tupdate(frame) {\\n\\t\\t\\t\\tconst xrInputSource = this._inputSource._xrInputSource;\\n\\t\\t\\t\\tfor(let j = 0; j < this._joints.length; j++){\\n\\t\\t\\t\\t\\t\\tconst joint = this._joints[j];\\n\\t\\t\\t\\t\\t\\tconst jointSpace = xrInputSource.hand.get(joint._id);\\n\\t\\t\\t\\t\\t\\tif (jointSpace) {\\n\\t\\t\\t\\t\\t\\t\\t\\tlet pose;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (frame.session.visibilityState !== 'hidden') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpose = frame.getJointPose(jointSpace, this._manager._referenceSpace);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (pose) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tjoint.update(pose);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (joint.wrist && !this._tracking) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._tracking = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('tracking');\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else if (joint.wrist) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this._tracking) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._tracking = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('trackinglost');\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst j1 = this._jointsById['thumb-metacarpal'];\\n\\t\\t\\t\\tconst j4 = this._jointsById['thumb-tip'];\\n\\t\\t\\t\\tconst j6 = this._jointsById['index-finger-phalanx-proximal'];\\n\\t\\t\\t\\tconst j9 = this._jointsById['index-finger-tip'];\\n\\t\\t\\t\\tconst j16 = this._jointsById['ring-finger-phalanx-proximal'];\\n\\t\\t\\t\\tconst j21 = this._jointsById['pinky-finger-phalanx-proximal'];\\n\\t\\t\\t\\tif (j1 && j4 && j6 && j9 && j16 && j21) {\\n\\t\\t\\t\\t\\t\\tthis._inputSource._dirtyRay = true;\\n\\t\\t\\t\\t\\t\\tthis._inputSource._rayLocal.origin.lerp(j4._localPosition, j9._localPosition, 0.5);\\n\\t\\t\\t\\t\\t\\tlet jointL = j1;\\n\\t\\t\\t\\t\\t\\tlet jointR = j21;\\n\\t\\t\\t\\t\\t\\tif (this._inputSource.handedness === XRHAND_LEFT) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst t = jointL;\\n\\t\\t\\t\\t\\t\\t\\t\\tjointL = jointR;\\n\\t\\t\\t\\t\\t\\t\\t\\tjointR = t;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tvecA.sub2(jointL._localPosition, this._wrist._localPosition);\\n\\t\\t\\t\\t\\t\\tvecB.sub2(jointR._localPosition, this._wrist._localPosition);\\n\\t\\t\\t\\t\\t\\tvecC.cross(vecA, vecB).normalize();\\n\\t\\t\\t\\t\\t\\tvecA.lerp(j6._localPosition, j16._localPosition, 0.5);\\n\\t\\t\\t\\t\\t\\tvecA.sub(this._wrist._localPosition).normalize();\\n\\t\\t\\t\\t\\t\\tthis._inputSource._rayLocal.direction.lerp(vecC, vecA, 0.5).normalize();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst squeezing = this._fingerIsClosed(1) && this._fingerIsClosed(2) && this._fingerIsClosed(3) && this._fingerIsClosed(4);\\n\\t\\t\\t\\tif (squeezing) {\\n\\t\\t\\t\\t\\t\\tif (!this._inputSource._squeezing) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._inputSource._squeezing = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._inputSource.fire('squeezestart');\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._manager.input.fire('squeezestart', this._inputSource);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (this._inputSource._squeezing) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._inputSource._squeezing = false;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._inputSource.fire('squeeze');\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._manager.input.fire('squeeze', this._inputSource);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._inputSource.fire('squeezeend');\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._manager.input.fire('squeezeend', this._inputSource);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_fingerIsClosed(index) {\\n\\t\\t\\t\\tconst finger = this._fingers[index];\\n\\t\\t\\t\\tvecA.sub2(finger.joints[0]._localPosition, finger.joints[1]._localPosition).normalize();\\n\\t\\t\\t\\tvecB.sub2(finger.joints[2]._localPosition, finger.joints[3]._localPosition).normalize();\\n\\t\\t\\t\\treturn vecA.dot(vecB) < -0.8;\\n\\t\\t}\\n\\t\\tgetJointById(id) {\\n\\t\\t\\t\\treturn this._jointsById[id] || null;\\n\\t\\t}\\n\\t\\tget fingers() {\\n\\t\\t\\t\\treturn this._fingers;\\n\\t\\t}\\n\\t\\tget joints() {\\n\\t\\t\\t\\treturn this._joints;\\n\\t\\t}\\n\\t\\tget tips() {\\n\\t\\t\\t\\treturn this._tips;\\n\\t\\t}\\n\\t\\tget wrist() {\\n\\t\\t\\t\\treturn this._wrist;\\n\\t\\t}\\n\\t\\tget tracking() {\\n\\t\\t\\t\\treturn this._tracking;\\n\\t\\t}\\n\\t\\tconstructor(inputSource){\\n\\t\\t\\t\\tsuper(), this._tracking = false, this._fingers = [], this._joints = [], this._jointsById = {}, this._tips = [], this._wrist = null;\\n\\t\\t\\t\\tconst xrHand = inputSource._xrInputSource.hand;\\n\\t\\t\\t\\tthis._manager = inputSource._manager;\\n\\t\\t\\t\\tthis._inputSource = inputSource;\\n\\t\\t\\t\\tif (xrHand.get('wrist')) {\\n\\t\\t\\t\\t\\t\\tconst joint = new XrJoint(0, 'wrist', this, null);\\n\\t\\t\\t\\t\\t\\tthis._wrist = joint;\\n\\t\\t\\t\\t\\t\\tthis._joints.push(joint);\\n\\t\\t\\t\\t\\t\\tthis._jointsById.wrist = joint;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let f = 0; f < fingerJointIds.length; f++){\\n\\t\\t\\t\\t\\t\\tconst finger = new XrFinger(f, this);\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j < fingerJointIds[f].length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst jointId = fingerJointIds[f][j];\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!xrHand.get(jointId)) continue;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst joint = new XrJoint(j, jointId, this, finger);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._joints.push(joint);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._jointsById[jointId] = joint;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (joint.tip) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._tips.push(joint);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfinger._tip = joint;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tfinger._joints.push(joint);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nXrHand.EVENT_TRACKING = 'tracking';\\nXrHand.EVENT_TRACKINGLOST = 'trackinglost';\\n\\nconst vec3A$1 = new Vec3();\\nconst quat = new Quat();\\nlet ids$1 = 0;\\nclass XrInputSource extends EventHandler {\\n\\t\\tget id() {\\n\\t\\t\\t\\treturn this._id;\\n\\t\\t}\\n\\t\\tget inputSource() {\\n\\t\\t\\t\\treturn this._xrInputSource;\\n\\t\\t}\\n\\t\\tget targetRayMode() {\\n\\t\\t\\t\\treturn this._xrInputSource.targetRayMode;\\n\\t\\t}\\n\\t\\tget handedness() {\\n\\t\\t\\t\\treturn this._xrInputSource.handedness;\\n\\t\\t}\\n\\t\\tget profiles() {\\n\\t\\t\\t\\treturn this._xrInputSource.profiles;\\n\\t\\t}\\n\\t\\tget grip() {\\n\\t\\t\\t\\treturn this._grip;\\n\\t\\t}\\n\\t\\tget hand() {\\n\\t\\t\\t\\treturn this._hand;\\n\\t\\t}\\n\\t\\tget gamepad() {\\n\\t\\t\\t\\treturn this._xrInputSource.gamepad || null;\\n\\t\\t}\\n\\t\\tget selecting() {\\n\\t\\t\\t\\treturn this._selecting;\\n\\t\\t}\\n\\t\\tget squeezing() {\\n\\t\\t\\t\\treturn this._squeezing;\\n\\t\\t}\\n\\t\\tset elementInput(value) {\\n\\t\\t\\t\\tif (this._elementInput === value) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._elementInput = value;\\n\\t\\t\\t\\tif (!this._elementInput) {\\n\\t\\t\\t\\t\\t\\tthis._elementEntity = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget elementInput() {\\n\\t\\t\\t\\treturn this._elementInput;\\n\\t\\t}\\n\\t\\tget elementEntity() {\\n\\t\\t\\t\\treturn this._elementEntity;\\n\\t\\t}\\n\\t\\tget hitTestSources() {\\n\\t\\t\\t\\treturn this._hitTestSources;\\n\\t\\t}\\n\\t\\tupdate(frame) {\\n\\t\\t\\t\\tif (this._hand) {\\n\\t\\t\\t\\t\\t\\tthis._hand.update(frame);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst gripSpace = this._xrInputSource.gripSpace;\\n\\t\\t\\t\\t\\t\\tif (gripSpace) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst gripPose = frame.getPose(gripSpace, this._manager._referenceSpace);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (gripPose) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (!this._grip) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._grip = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._localTransform = new Mat4();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._worldTransform = new Mat4();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._localPositionLast = new Vec3();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._localPosition = new Vec3();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._localRotation = new Quat();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._linearVelocity = new Vec3();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst timestamp = now();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst dt = (timestamp - this._velocitiesTimestamp) / 1000;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._velocitiesTimestamp = timestamp;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._dirtyLocal = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._localPositionLast.copy(this._localPosition);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._localPosition.copy(gripPose.transform.position);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._localRotation.copy(gripPose.transform.orientation);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._velocitiesAvailable = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this._manager.input.velocitiesSupported && gripPose.linearVelocity) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._linearVelocity.copy(gripPose.linearVelocity);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else if (dt > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvec3A$1.sub2(this._localPosition, this._localPositionLast).divScalar(dt);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._linearVelocity.lerp(this._linearVelocity, vec3A$1, 0.15);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._velocitiesAvailable = false;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst targetRayPose = frame.getPose(this._xrInputSource.targetRaySpace, this._manager._referenceSpace);\\n\\t\\t\\t\\t\\t\\tif (targetRayPose) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._dirtyRay = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._rayLocal.origin.copy(targetRayPose.transform.position);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._rayLocal.direction.set(0, 0, -1);\\n\\t\\t\\t\\t\\t\\t\\t\\tquat.copy(targetRayPose.transform.orientation);\\n\\t\\t\\t\\t\\t\\t\\t\\tquat.transformVector(this._rayLocal.direction, this._rayLocal.direction);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_updateTransforms() {\\n\\t\\t\\t\\tif (this._dirtyLocal) {\\n\\t\\t\\t\\t\\t\\tthis._dirtyLocal = false;\\n\\t\\t\\t\\t\\t\\tthis._localTransform.setTRS(this._localPosition, this._localRotation, Vec3.ONE);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst parent = this._manager.camera.parent;\\n\\t\\t\\t\\tif (parent) {\\n\\t\\t\\t\\t\\t\\tthis._worldTransform.mul2(parent.getWorldTransform(), this._localTransform);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._worldTransform.copy(this._localTransform);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_updateRayTransforms() {\\n\\t\\t\\t\\tconst dirty = this._dirtyRay;\\n\\t\\t\\t\\tthis._dirtyRay = false;\\n\\t\\t\\t\\tconst parent = this._manager.camera.parent;\\n\\t\\t\\t\\tif (parent) {\\n\\t\\t\\t\\t\\t\\tconst parentTransform = parent.getWorldTransform();\\n\\t\\t\\t\\t\\t\\tparentTransform.getTranslation(this._position);\\n\\t\\t\\t\\t\\t\\tthis._rotation.setFromMat4(parentTransform);\\n\\t\\t\\t\\t\\t\\tthis._rotation.transformVector(this._rayLocal.origin, this._ray.origin);\\n\\t\\t\\t\\t\\t\\tthis._ray.origin.add(this._position);\\n\\t\\t\\t\\t\\t\\tthis._rotation.transformVector(this._rayLocal.direction, this._ray.direction);\\n\\t\\t\\t\\t} else if (dirty) {\\n\\t\\t\\t\\t\\t\\tthis._ray.origin.copy(this._rayLocal.origin);\\n\\t\\t\\t\\t\\t\\tthis._ray.direction.copy(this._rayLocal.direction);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetPosition() {\\n\\t\\t\\t\\tif (!this._grip) return null;\\n\\t\\t\\t\\tthis._updateTransforms();\\n\\t\\t\\t\\tthis._worldTransform.getTranslation(this._position);\\n\\t\\t\\t\\treturn this._position;\\n\\t\\t}\\n\\t\\tgetLocalPosition() {\\n\\t\\t\\t\\treturn this._localPosition;\\n\\t\\t}\\n\\t\\tgetRotation() {\\n\\t\\t\\t\\tif (!this._grip) return null;\\n\\t\\t\\t\\tthis._updateTransforms();\\n\\t\\t\\t\\tthis._rotation.setFromMat4(this._worldTransform);\\n\\t\\t\\t\\treturn this._rotation;\\n\\t\\t}\\n\\t\\tgetLocalRotation() {\\n\\t\\t\\t\\treturn this._localRotation;\\n\\t\\t}\\n\\t\\tgetLinearVelocity() {\\n\\t\\t\\t\\tif (!this._velocitiesAvailable) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._linearVelocity;\\n\\t\\t}\\n\\t\\tgetOrigin() {\\n\\t\\t\\t\\tthis._updateRayTransforms();\\n\\t\\t\\t\\treturn this._ray.origin;\\n\\t\\t}\\n\\t\\tgetDirection() {\\n\\t\\t\\t\\tthis._updateRayTransforms();\\n\\t\\t\\t\\treturn this._ray.direction;\\n\\t\\t}\\n\\t\\thitTestStart(options = {}) {\\n\\t\\t\\t\\toptions.inputSource = this;\\n\\t\\t\\t\\toptions.profile = this._xrInputSource.profiles[0];\\n\\t\\t\\t\\tconst callback = options.callback;\\n\\t\\t\\t\\toptions.callback = (err, hitTestSource)=>{\\n\\t\\t\\t\\t\\t\\tif (hitTestSource) this.onHitTestSourceAdd(hitTestSource);\\n\\t\\t\\t\\t\\t\\tif (callback) callback(err, hitTestSource);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis._manager.hitTest.start(options);\\n\\t\\t}\\n\\t\\tonHitTestSourceAdd(hitTestSource) {\\n\\t\\t\\t\\tthis._hitTestSources.push(hitTestSource);\\n\\t\\t\\t\\tthis.fire('hittest:add', hitTestSource);\\n\\t\\t\\t\\thitTestSource.on('result', (position, rotation, inputSource, hitTestResult)=>{\\n\\t\\t\\t\\t\\t\\tif (inputSource !== this) return;\\n\\t\\t\\t\\t\\t\\tthis.fire('hittest:result', hitTestSource, position, rotation, hitTestResult);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\thitTestSource.once('remove', ()=>{\\n\\t\\t\\t\\t\\t\\tthis.onHitTestSourceRemove(hitTestSource);\\n\\t\\t\\t\\t\\t\\tthis.fire('hittest:remove', hitTestSource);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tonHitTestSourceRemove(hitTestSource) {\\n\\t\\t\\t\\tconst ind = this._hitTestSources.indexOf(hitTestSource);\\n\\t\\t\\t\\tif (ind !== -1) this._hitTestSources.splice(ind, 1);\\n\\t\\t}\\n\\t\\tconstructor(manager, xrInputSource){\\n\\t\\t\\t\\tsuper(), this._ray = new Ray(), this._rayLocal = new Ray(), this._grip = false, this._hand = null, this._velocitiesAvailable = false, this._velocitiesTimestamp = now(), this._localTransform = null, this._worldTransform = null, this._position = new Vec3(), this._rotation = new Quat(), this._localPosition = null, this._localPositionLast = null, this._localRotation = null, this._linearVelocity = null, this._dirtyLocal = true, this._dirtyRay = false, this._selecting = false, this._squeezing = false, this._elementInput = true, this._elementEntity = null, this._hitTestSources = [];\\n\\t\\t\\t\\tthis._id = ++ids$1;\\n\\t\\t\\t\\tthis._manager = manager;\\n\\t\\t\\t\\tthis._xrInputSource = xrInputSource;\\n\\t\\t\\t\\tif (xrInputSource.hand) {\\n\\t\\t\\t\\t\\t\\tthis._hand = new XrHand(this);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nXrInputSource.EVENT_REMOVE = 'remove';\\nXrInputSource.EVENT_SELECT = 'select';\\nXrInputSource.EVENT_SELECTSTART = 'selectstart';\\nXrInputSource.EVENT_SELECTEND = 'selectend';\\nXrInputSource.EVENT_SQUEEZE = 'squeeze';\\nXrInputSource.EVENT_SQUEEZESTART = 'squeezestart';\\nXrInputSource.EVENT_SQUEEZEEND = 'squeezeend';\\nXrInputSource.EVENT_HITTESTADD = 'hittest:add';\\nXrInputSource.EVENT_HITTESTREMOVE = 'hittest:remove';\\nXrInputSource.EVENT_HITTESTRESULT = 'hittest:result';\\n\\nclass XrInput extends EventHandler {\\n\\t\\t_onSessionStart() {\\n\\t\\t\\t\\tconst session = this.manager.session;\\n\\t\\t\\t\\tsession.addEventListener('inputsourceschange', this._onInputSourcesChangeEvt);\\n\\t\\t\\t\\tsession.addEventListener('select', (evt)=>{\\n\\t\\t\\t\\t\\t\\tconst inputSource = this._getByInputSource(evt.inputSource);\\n\\t\\t\\t\\t\\t\\tinputSource.update(evt.frame);\\n\\t\\t\\t\\t\\t\\tinputSource.fire('select', evt);\\n\\t\\t\\t\\t\\t\\tthis.fire('select', inputSource, evt);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tsession.addEventListener('selectstart', (evt)=>{\\n\\t\\t\\t\\t\\t\\tconst inputSource = this._getByInputSource(evt.inputSource);\\n\\t\\t\\t\\t\\t\\tinputSource.update(evt.frame);\\n\\t\\t\\t\\t\\t\\tinputSource._selecting = true;\\n\\t\\t\\t\\t\\t\\tinputSource.fire('selectstart', evt);\\n\\t\\t\\t\\t\\t\\tthis.fire('selectstart', inputSource, evt);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tsession.addEventListener('selectend', (evt)=>{\\n\\t\\t\\t\\t\\t\\tconst inputSource = this._getByInputSource(evt.inputSource);\\n\\t\\t\\t\\t\\t\\tinputSource.update(evt.frame);\\n\\t\\t\\t\\t\\t\\tinputSource._selecting = false;\\n\\t\\t\\t\\t\\t\\tinputSource.fire('selectend', evt);\\n\\t\\t\\t\\t\\t\\tthis.fire('selectend', inputSource, evt);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tsession.addEventListener('squeeze', (evt)=>{\\n\\t\\t\\t\\t\\t\\tconst inputSource = this._getByInputSource(evt.inputSource);\\n\\t\\t\\t\\t\\t\\tinputSource.update(evt.frame);\\n\\t\\t\\t\\t\\t\\tinputSource.fire('squeeze', evt);\\n\\t\\t\\t\\t\\t\\tthis.fire('squeeze', inputSource, evt);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tsession.addEventListener('squeezestart', (evt)=>{\\n\\t\\t\\t\\t\\t\\tconst inputSource = this._getByInputSource(evt.inputSource);\\n\\t\\t\\t\\t\\t\\tinputSource.update(evt.frame);\\n\\t\\t\\t\\t\\t\\tinputSource._squeezing = true;\\n\\t\\t\\t\\t\\t\\tinputSource.fire('squeezestart', evt);\\n\\t\\t\\t\\t\\t\\tthis.fire('squeezestart', inputSource, evt);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tsession.addEventListener('squeezeend', (evt)=>{\\n\\t\\t\\t\\t\\t\\tconst inputSource = this._getByInputSource(evt.inputSource);\\n\\t\\t\\t\\t\\t\\tinputSource.update(evt.frame);\\n\\t\\t\\t\\t\\t\\tinputSource._squeezing = false;\\n\\t\\t\\t\\t\\t\\tinputSource.fire('squeezeend', evt);\\n\\t\\t\\t\\t\\t\\tthis.fire('squeezeend', inputSource, evt);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst inputSources = session.inputSources;\\n\\t\\t\\t\\tfor(let i = 0; i < inputSources.length; i++){\\n\\t\\t\\t\\t\\t\\tthis._addInputSource(inputSources[i]);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onSessionEnd() {\\n\\t\\t\\t\\tlet i = this._inputSources.length;\\n\\t\\t\\t\\twhile(i--){\\n\\t\\t\\t\\t\\t\\tconst inputSource = this._inputSources[i];\\n\\t\\t\\t\\t\\t\\tthis._inputSources.splice(i, 1);\\n\\t\\t\\t\\t\\t\\tinputSource.fire('remove');\\n\\t\\t\\t\\t\\t\\tthis.fire('remove', inputSource);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst session = this.manager.session;\\n\\t\\t\\t\\tsession.removeEventListener('inputsourceschange', this._onInputSourcesChangeEvt);\\n\\t\\t}\\n\\t\\t_onInputSourcesChange(evt) {\\n\\t\\t\\t\\tfor(let i = 0; i < evt.removed.length; i++){\\n\\t\\t\\t\\t\\t\\tthis._removeInputSource(evt.removed[i]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < evt.added.length; i++){\\n\\t\\t\\t\\t\\t\\tthis._addInputSource(evt.added[i]);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_getByInputSource(xrInputSource) {\\n\\t\\t\\t\\tfor(let i = 0; i < this._inputSources.length; i++){\\n\\t\\t\\t\\t\\t\\tif (this._inputSources[i].inputSource === xrInputSource) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn this._inputSources[i];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn null;\\n\\t\\t}\\n\\t\\t_addInputSource(xrInputSource) {\\n\\t\\t\\t\\tif (this._getByInputSource(xrInputSource)) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst inputSource = new XrInputSource(this.manager, xrInputSource);\\n\\t\\t\\t\\tthis._inputSources.push(inputSource);\\n\\t\\t\\t\\tthis.fire('add', inputSource);\\n\\t\\t}\\n\\t\\t_removeInputSource(xrInputSource) {\\n\\t\\t\\t\\tfor(let i = 0; i < this._inputSources.length; i++){\\n\\t\\t\\t\\t\\t\\tif (this._inputSources[i].inputSource !== xrInputSource) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst inputSource = this._inputSources[i];\\n\\t\\t\\t\\t\\t\\tthis._inputSources.splice(i, 1);\\n\\t\\t\\t\\t\\t\\tlet h = inputSource.hitTestSources.length;\\n\\t\\t\\t\\t\\t\\twhile(h--){\\n\\t\\t\\t\\t\\t\\t\\t\\tinputSource.hitTestSources[h].remove();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tinputSource.fire('remove');\\n\\t\\t\\t\\t\\t\\tthis.fire('remove', inputSource);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdate(frame) {\\n\\t\\t\\t\\tfor(let i = 0; i < this._inputSources.length; i++){\\n\\t\\t\\t\\t\\t\\tthis._inputSources[i].update(frame);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget inputSources() {\\n\\t\\t\\t\\treturn this._inputSources;\\n\\t\\t}\\n\\t\\tconstructor(manager){\\n\\t\\t\\t\\tsuper(), this._inputSources = [], this.velocitiesSupported = false;\\n\\t\\t\\t\\tthis.manager = manager;\\n\\t\\t\\t\\tthis.velocitiesSupported = !!(platform.browser && window.XRPose?.prototype?.hasOwnProperty('linearVelocity'));\\n\\t\\t\\t\\tthis._onInputSourcesChangeEvt = (evt)=>{\\n\\t\\t\\t\\t\\t\\tthis._onInputSourcesChange(evt);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.manager.on('start', this._onSessionStart, this);\\n\\t\\t\\t\\tthis.manager.on('end', this._onSessionEnd, this);\\n\\t\\t}\\n}\\nXrInput.EVENT_ADD = 'add';\\nXrInput.EVENT_REMOVE = 'remove';\\nXrInput.EVENT_SELECT = 'select';\\nXrInput.EVENT_SELECTSTART = 'selectstart';\\nXrInput.EVENT_SELECTEND = 'selectend';\\nXrInput.EVENT_SQUEEZE = 'squeeze';\\nXrInput.EVENT_SQUEEZESTART = 'squeezestart';\\nXrInput.EVENT_SQUEEZEEND = 'squeezeend';\\n\\nconst vec3A = new Vec3();\\nconst vec3B = new Vec3();\\nconst mat4A = new Mat4();\\nconst mat4B = new Mat4();\\nclass XrLightEstimation extends EventHandler {\\n\\t\\t_onSessionStart() {\\n\\t\\t\\t\\tconst supported = !!this._manager.session.requestLightProbe;\\n\\t\\t\\t\\tif (!supported) return;\\n\\t\\t\\t\\tthis._supported = true;\\n\\t\\t}\\n\\t\\t_onSessionEnd() {\\n\\t\\t\\t\\tthis._supported = false;\\n\\t\\t\\t\\tthis._available = false;\\n\\t\\t\\t\\tthis._lightProbeRequested = false;\\n\\t\\t\\t\\tthis._lightProbe = null;\\n\\t\\t}\\n\\t\\tstart() {\\n\\t\\t\\t\\tlet err;\\n\\t\\t\\t\\tif (!this._manager.session) {\\n\\t\\t\\t\\t\\t\\terr = new Error('XR session is not running');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!err && this._manager.type !== XRTYPE_AR) {\\n\\t\\t\\t\\t\\t\\terr = new Error('XR session type is not AR');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!err && !this._supported) {\\n\\t\\t\\t\\t\\t\\terr = new Error('light-estimation is not supported');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!err && this._lightProbe || this._lightProbeRequested) {\\n\\t\\t\\t\\t\\t\\terr = new Error('light estimation is already requested');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\tthis.fire('error', err);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._lightProbeRequested = true;\\n\\t\\t\\t\\tthis._manager.session.requestLightProbe().then((lightProbe)=>{\\n\\t\\t\\t\\t\\t\\tconst wasRequested = this._lightProbeRequested;\\n\\t\\t\\t\\t\\t\\tthis._lightProbeRequested = false;\\n\\t\\t\\t\\t\\t\\tif (this._manager.active) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (wasRequested) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._lightProbe = lightProbe;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('error', new Error('XR session is not active'));\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}).catch((ex)=>{\\n\\t\\t\\t\\t\\t\\tthis._lightProbeRequested = false;\\n\\t\\t\\t\\t\\t\\tthis.fire('error', ex);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tend() {\\n\\t\\t\\t\\tthis._lightProbeRequested = false;\\n\\t\\t\\t\\tthis._lightProbe = null;\\n\\t\\t\\t\\tthis._available = false;\\n\\t\\t}\\n\\t\\tupdate(frame) {\\n\\t\\t\\t\\tif (!this._lightProbe) return;\\n\\t\\t\\t\\tconst lightEstimate = frame.getLightEstimate(this._lightProbe);\\n\\t\\t\\t\\tif (!lightEstimate) return;\\n\\t\\t\\t\\tif (!this._available) {\\n\\t\\t\\t\\t\\t\\tthis._available = true;\\n\\t\\t\\t\\t\\t\\tthis.fire('available');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst pli = lightEstimate.primaryLightIntensity;\\n\\t\\t\\t\\tthis._intensity = Math.max(1.0, Math.max(pli.x, Math.max(pli.y, pli.z)));\\n\\t\\t\\t\\tvec3A.copy(pli).mulScalar(1 / this._intensity);\\n\\t\\t\\t\\tthis._color.set(vec3A.x, vec3A.y, vec3A.z);\\n\\t\\t\\t\\tvec3A.set(0, 0, 0);\\n\\t\\t\\t\\tvec3B.copy(lightEstimate.primaryLightDirection);\\n\\t\\t\\t\\tmat4A.setLookAt(vec3B, vec3A, Vec3.UP);\\n\\t\\t\\t\\tmat4B.setFromAxisAngle(Vec3.RIGHT, 90);\\n\\t\\t\\t\\tmat4A.mul(mat4B);\\n\\t\\t\\t\\tthis._rotation.setFromMat4(mat4A);\\n\\t\\t\\t\\tthis._sphericalHarmonics.set(lightEstimate.sphericalHarmonicsCoefficients);\\n\\t\\t}\\n\\t\\tget supported() {\\n\\t\\t\\t\\treturn this._supported;\\n\\t\\t}\\n\\t\\tget available() {\\n\\t\\t\\t\\treturn this._available;\\n\\t\\t}\\n\\t\\tget intensity() {\\n\\t\\t\\t\\treturn this._available ? this._intensity : null;\\n\\t\\t}\\n\\t\\tget color() {\\n\\t\\t\\t\\treturn this._available ? this._color : null;\\n\\t\\t}\\n\\t\\tget rotation() {\\n\\t\\t\\t\\treturn this._available ? this._rotation : null;\\n\\t\\t}\\n\\t\\tget sphericalHarmonics() {\\n\\t\\t\\t\\treturn this._available ? this._sphericalHarmonics : null;\\n\\t\\t}\\n\\t\\tconstructor(manager){\\n\\t\\t\\t\\tsuper(), this._supported = false, this._available = false, this._lightProbeRequested = false, this._lightProbe = null, this._intensity = 0, this._rotation = new Quat(), this._color = new Color(), this._sphericalHarmonics = new Float32Array(27);\\n\\t\\t\\t\\tthis._manager = manager;\\n\\t\\t\\t\\tthis._manager.on('start', this._onSessionStart, this);\\n\\t\\t\\t\\tthis._manager.on('end', this._onSessionEnd, this);\\n\\t\\t}\\n}\\nXrLightEstimation.EVENT_AVAILABLE = 'available';\\nXrLightEstimation.EVENT_ERROR = 'error';\\n\\nlet ids = 0;\\nclass XrPlane extends EventHandler {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tif (!this._xrPlane) return;\\n\\t\\t\\t\\tthis._xrPlane = null;\\n\\t\\t\\t\\tthis.fire('remove');\\n\\t\\t}\\n\\t\\tupdate(frame) {\\n\\t\\t\\t\\tconst manager = this._planeDetection._manager;\\n\\t\\t\\t\\tconst pose = frame.getPose(this._xrPlane.planeSpace, manager._referenceSpace);\\n\\t\\t\\t\\tif (pose) {\\n\\t\\t\\t\\t\\t\\tthis._position.copy(pose.transform.position);\\n\\t\\t\\t\\t\\t\\tthis._rotation.copy(pose.transform.orientation);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._lastChangedTime !== this._xrPlane.lastChangedTime) {\\n\\t\\t\\t\\t\\t\\tthis._lastChangedTime = this._xrPlane.lastChangedTime;\\n\\t\\t\\t\\t\\t\\tthis.fire('change');\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetPosition() {\\n\\t\\t\\t\\treturn this._position;\\n\\t\\t}\\n\\t\\tgetRotation() {\\n\\t\\t\\t\\treturn this._rotation;\\n\\t\\t}\\n\\t\\tget id() {\\n\\t\\t\\t\\treturn this._id;\\n\\t\\t}\\n\\t\\tget orientation() {\\n\\t\\t\\t\\treturn this._orientation;\\n\\t\\t}\\n\\t\\tget points() {\\n\\t\\t\\t\\treturn this._xrPlane.polygon;\\n\\t\\t}\\n\\t\\tget label() {\\n\\t\\t\\t\\treturn this._xrPlane.semanticLabel || '';\\n\\t\\t}\\n\\t\\tconstructor(planeDetection, xrPlane){\\n\\t\\t\\t\\tsuper(), this._position = new Vec3(), this._rotation = new Quat();\\n\\t\\t\\t\\tthis._id = ++ids;\\n\\t\\t\\t\\tthis._planeDetection = planeDetection;\\n\\t\\t\\t\\tthis._xrPlane = xrPlane;\\n\\t\\t\\t\\tthis._lastChangedTime = xrPlane.lastChangedTime;\\n\\t\\t\\t\\tthis._orientation = xrPlane.orientation;\\n\\t\\t}\\n}\\nXrPlane.EVENT_REMOVE = 'remove';\\nXrPlane.EVENT_CHANGE = 'change';\\n\\nclass XrPlaneDetection extends EventHandler {\\n\\t\\t_onSessionStart() {\\n\\t\\t\\t\\tif (this._manager.session.enabledFeatures) {\\n\\t\\t\\t\\t\\t\\tconst available = this._manager.session.enabledFeatures.indexOf('plane-detection') !== -1;\\n\\t\\t\\t\\t\\t\\tif (available) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._available = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('available');\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onSessionEnd() {\\n\\t\\t\\t\\tfor(let i = 0; i < this._planes.length; i++){\\n\\t\\t\\t\\t\\t\\tthis._planes[i].destroy();\\n\\t\\t\\t\\t\\t\\tthis.fire('remove', this._planes[i]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._planesIndex.clear();\\n\\t\\t\\t\\tthis._planes.length = 0;\\n\\t\\t\\t\\tif (this._available) {\\n\\t\\t\\t\\t\\t\\tthis._available = false;\\n\\t\\t\\t\\t\\t\\tthis.fire('unavailable');\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdate(frame) {\\n\\t\\t\\t\\tif (!this._available) {\\n\\t\\t\\t\\t\\t\\tif (!this._manager.session.enabledFeatures && frame.detectedPlanes.size) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._available = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('available');\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst detectedPlanes = frame.detectedPlanes;\\n\\t\\t\\t\\tfor (const [xrPlane, plane] of this._planesIndex){\\n\\t\\t\\t\\t\\t\\tif (detectedPlanes.has(xrPlane)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._planesIndex.delete(xrPlane);\\n\\t\\t\\t\\t\\t\\tthis._planes.splice(this._planes.indexOf(plane), 1);\\n\\t\\t\\t\\t\\t\\tplane.destroy();\\n\\t\\t\\t\\t\\t\\tthis.fire('remove', plane);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const xrPlane of detectedPlanes){\\n\\t\\t\\t\\t\\t\\tlet plane = this._planesIndex.get(xrPlane);\\n\\t\\t\\t\\t\\t\\tif (!plane) {\\n\\t\\t\\t\\t\\t\\t\\t\\tplane = new XrPlane(this, xrPlane);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._planesIndex.set(xrPlane, plane);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._planes.push(plane);\\n\\t\\t\\t\\t\\t\\t\\t\\tplane.update(frame);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('add', plane);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tplane.update(frame);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget supported() {\\n\\t\\t\\t\\treturn this._supported;\\n\\t\\t}\\n\\t\\tget available() {\\n\\t\\t\\t\\treturn this._available;\\n\\t\\t}\\n\\t\\tget planes() {\\n\\t\\t\\t\\treturn this._planes;\\n\\t\\t}\\n\\t\\tconstructor(manager){\\n\\t\\t\\t\\tsuper(), this._supported = platform.browser && !!window.XRPlane, this._available = false, this._planesIndex = new Map(), this._planes = [];\\n\\t\\t\\t\\tthis._manager = manager;\\n\\t\\t\\t\\tif (this._supported) {\\n\\t\\t\\t\\t\\t\\tthis._manager.on('start', this._onSessionStart, this);\\n\\t\\t\\t\\t\\t\\tthis._manager.on('end', this._onSessionEnd, this);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nXrPlaneDetection.EVENT_AVAILABLE = 'available';\\nXrPlaneDetection.EVENT_UNAVAILABLE = 'unavailable';\\nXrPlaneDetection.EVENT_ADD = 'add';\\nXrPlaneDetection.EVENT_REMOVE = 'remove';\\n\\nclass XrAnchor extends EventHandler {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tif (!this._xrAnchor) return;\\n\\t\\t\\t\\tconst xrAnchor = this._xrAnchor;\\n\\t\\t\\t\\tthis._xrAnchor.delete();\\n\\t\\t\\t\\tthis._xrAnchor = null;\\n\\t\\t\\t\\tthis.fire('destroy', xrAnchor, this);\\n\\t\\t}\\n\\t\\tupdate(frame) {\\n\\t\\t\\t\\tif (!this._xrAnchor) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst pose = frame.getPose(this._xrAnchor.anchorSpace, this._anchors.manager._referenceSpace);\\n\\t\\t\\t\\tif (pose) {\\n\\t\\t\\t\\t\\t\\tif (this._position.equals(pose.transform.position) && this._rotation.equals(pose.transform.orientation)) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._position.copy(pose.transform.position);\\n\\t\\t\\t\\t\\t\\tthis._rotation.copy(pose.transform.orientation);\\n\\t\\t\\t\\t\\t\\tthis.fire('change');\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetPosition() {\\n\\t\\t\\t\\treturn this._position;\\n\\t\\t}\\n\\t\\tgetRotation() {\\n\\t\\t\\t\\treturn this._rotation;\\n\\t\\t}\\n\\t\\tpersist(callback) {\\n\\t\\t\\t\\tif (!this._anchors.persistence) {\\n\\t\\t\\t\\t\\t\\tcallback?.(new Error('Persistent Anchors are not supported'), null);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._uuid) {\\n\\t\\t\\t\\t\\t\\tcallback?.(null, this._uuid);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._uuidRequests) {\\n\\t\\t\\t\\t\\t\\tif (callback) this._uuidRequests.push(callback);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._uuidRequests = [];\\n\\t\\t\\t\\tthis._xrAnchor.requestPersistentHandle().then((uuid)=>{\\n\\t\\t\\t\\t\\t\\tthis._uuid = uuid;\\n\\t\\t\\t\\t\\t\\tthis._anchors._indexByUuid.set(this._uuid, this);\\n\\t\\t\\t\\t\\t\\tcallback?.(null, uuid);\\n\\t\\t\\t\\t\\t\\tfor (const uuidRequest of this._uuidRequests){\\n\\t\\t\\t\\t\\t\\t\\t\\tuuidRequest(null, uuid);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._uuidRequests = null;\\n\\t\\t\\t\\t\\t\\tthis.fire('persist', uuid);\\n\\t\\t\\t\\t}).catch((ex)=>{\\n\\t\\t\\t\\t\\t\\tcallback?.(ex, null);\\n\\t\\t\\t\\t\\t\\tfor (const uuidRequest of this._uuidRequests){\\n\\t\\t\\t\\t\\t\\t\\t\\tuuidRequest(ex, null);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._uuidRequests = null;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tforget(callback) {\\n\\t\\t\\t\\tif (!this._uuid) {\\n\\t\\t\\t\\t\\t\\tcallback?.(new Error('Anchor is not persistent'));\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._anchors.forget(this._uuid, (ex)=>{\\n\\t\\t\\t\\t\\t\\tthis._uuid = null;\\n\\t\\t\\t\\t\\t\\tcallback?.(ex);\\n\\t\\t\\t\\t\\t\\tthis.fire('forget');\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tget uuid() {\\n\\t\\t\\t\\treturn this._uuid;\\n\\t\\t}\\n\\t\\tget persistent() {\\n\\t\\t\\t\\treturn !!this._uuid;\\n\\t\\t}\\n\\t\\tconstructor(anchors, xrAnchor, uuid = null){\\n\\t\\t\\t\\tsuper(), this._position = new Vec3(), this._rotation = new Quat(), this._uuid = null, this._uuidRequests = null;\\n\\t\\t\\t\\tthis._anchors = anchors;\\n\\t\\t\\t\\tthis._xrAnchor = xrAnchor;\\n\\t\\t\\t\\tthis._uuid = uuid;\\n\\t\\t}\\n}\\nXrAnchor.EVENT_DESTROY = 'destroy';\\nXrAnchor.EVENT_CHANGE = 'change';\\nXrAnchor.EVENT_PERSIST = 'persist';\\nXrAnchor.EVENT_FORGET = 'forget';\\n\\nclass XrAnchors extends EventHandler {\\n\\t\\t_onSessionStart() {\\n\\t\\t\\t\\tconst available = this.manager.session.enabledFeatures?.indexOf('anchors') >= 0;\\n\\t\\t\\t\\tif (!available) return;\\n\\t\\t\\t\\tthis._available = available;\\n\\t\\t\\t\\tthis.fire('available');\\n\\t\\t}\\n\\t\\t_onSessionEnd() {\\n\\t\\t\\t\\tif (!this._available) return;\\n\\t\\t\\t\\tthis._available = false;\\n\\t\\t\\t\\tfor(let i = 0; i < this._creationQueue.length; i++){\\n\\t\\t\\t\\t\\t\\tif (!this._creationQueue[i].callback) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._creationQueue[i].callback(new Error('session ended'), null);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._creationQueue.length = 0;\\n\\t\\t\\t\\tthis._index.clear();\\n\\t\\t\\t\\tthis._indexByUuid.clear();\\n\\t\\t\\t\\tlet i = this._list.length;\\n\\t\\t\\t\\twhile(i--){\\n\\t\\t\\t\\t\\t\\tthis._list[i].destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._list.length = 0;\\n\\t\\t\\t\\tthis.fire('unavailable');\\n\\t\\t}\\n\\t\\t_createAnchor(xrAnchor, uuid = null) {\\n\\t\\t\\t\\tconst anchor = new XrAnchor(this, xrAnchor, uuid);\\n\\t\\t\\t\\tthis._index.set(xrAnchor, anchor);\\n\\t\\t\\t\\tif (uuid) this._indexByUuid.set(uuid, anchor);\\n\\t\\t\\t\\tthis._list.push(anchor);\\n\\t\\t\\t\\tanchor.once('destroy', this._onAnchorDestroy, this);\\n\\t\\t\\t\\treturn anchor;\\n\\t\\t}\\n\\t\\t_onAnchorDestroy(xrAnchor, anchor) {\\n\\t\\t\\t\\tthis._index.delete(xrAnchor);\\n\\t\\t\\t\\tif (anchor.uuid) this._indexByUuid.delete(anchor.uuid);\\n\\t\\t\\t\\tconst ind = this._list.indexOf(anchor);\\n\\t\\t\\t\\tif (ind !== -1) this._list.splice(ind, 1);\\n\\t\\t\\t\\tthis.fire('destroy', anchor);\\n\\t\\t}\\n\\t\\tcreate(position, rotation, callback) {\\n\\t\\t\\t\\tif (!this._available) {\\n\\t\\t\\t\\t\\t\\tcallback?.(new Error('Anchors API is not available'), null);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (window.XRHitTestResult && position instanceof XRHitTestResult) {\\n\\t\\t\\t\\t\\t\\tconst hitResult = position;\\n\\t\\t\\t\\t\\t\\tcallback = rotation;\\n\\t\\t\\t\\t\\t\\tif (!this._supported) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback?.(new Error('Anchors API is not supported'), null);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (!hitResult.createAnchor) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback?.(new Error('Creating Anchor from Hit Test is not supported'), null);\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\thitResult.createAnchor().then((xrAnchor)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst anchor = this._createAnchor(xrAnchor);\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback?.(null, anchor);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('add', anchor);\\n\\t\\t\\t\\t\\t\\t}).catch((ex)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback?.(ex, null);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('error', ex);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._creationQueue.push({\\n\\t\\t\\t\\t\\t\\t\\t\\ttransform: new XRRigidTransform(position, rotation),\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback: callback\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\trestore(uuid, callback) {\\n\\t\\t\\t\\tif (!this._available) {\\n\\t\\t\\t\\t\\t\\tcallback?.(new Error('Anchors API is not available'), null);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._persistence) {\\n\\t\\t\\t\\t\\t\\tcallback?.(new Error('Anchor Persistence is not supported'), null);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this.manager.active) {\\n\\t\\t\\t\\t\\t\\tcallback?.(new Error('WebXR session is not active'), null);\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.manager.session.restorePersistentAnchor(uuid).then((xrAnchor)=>{\\n\\t\\t\\t\\t\\t\\tconst anchor = this._createAnchor(xrAnchor, uuid);\\n\\t\\t\\t\\t\\t\\tcallback?.(null, anchor);\\n\\t\\t\\t\\t\\t\\tthis.fire('add', anchor);\\n\\t\\t\\t\\t}).catch((ex)=>{\\n\\t\\t\\t\\t\\t\\tcallback?.(ex, null);\\n\\t\\t\\t\\t\\t\\tthis.fire('error', ex);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tforget(uuid, callback) {\\n\\t\\t\\t\\tif (!this._available) {\\n\\t\\t\\t\\t\\t\\tcallback?.(new Error('Anchors API is not available'));\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._persistence) {\\n\\t\\t\\t\\t\\t\\tcallback?.(new Error('Anchor Persistence is not supported'));\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this.manager.active) {\\n\\t\\t\\t\\t\\t\\tcallback?.(new Error('WebXR session is not active'));\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.manager.session.deletePersistentAnchor(uuid).then(()=>{\\n\\t\\t\\t\\t\\t\\tcallback?.(null);\\n\\t\\t\\t\\t}).catch((ex)=>{\\n\\t\\t\\t\\t\\t\\tcallback?.(ex);\\n\\t\\t\\t\\t\\t\\tthis.fire('error', ex);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tupdate(frame) {\\n\\t\\t\\t\\tif (!this._available) {\\n\\t\\t\\t\\t\\t\\tif (!this.manager.session.enabledFeatures && !this._checkingAvailability) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._checkingAvailability = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tframe.createAnchor(new XRRigidTransform(), this.manager._referenceSpace).then((xrAnchor)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\txrAnchor.delete();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this.manager.active) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._available = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('available');\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t}).catch(()=>{});\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._creationQueue.length) {\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._creationQueue.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst request = this._creationQueue[i];\\n\\t\\t\\t\\t\\t\\t\\t\\tframe.createAnchor(request.transform, this.manager._referenceSpace).then((xrAnchor)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (request.callback) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._callbacksAnchors.set(xrAnchor, request.callback);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t}).catch((ex)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (request.callback) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trequest.callback(ex, null);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('error', ex);\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._creationQueue.length = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const [xrAnchor, anchor] of this._index){\\n\\t\\t\\t\\t\\t\\tif (frame.trackedAnchors.has(xrAnchor)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._index.delete(xrAnchor);\\n\\t\\t\\t\\t\\t\\tanchor.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < this._list.length; i++){\\n\\t\\t\\t\\t\\t\\tthis._list[i].update(frame);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const xrAnchor of frame.trackedAnchors){\\n\\t\\t\\t\\t\\t\\tif (this._index.has(xrAnchor)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst tmp = xrAnchor.anchorSpace;\\n\\t\\t\\t\\t\\t\\t} catch (ex) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst anchor = this._createAnchor(xrAnchor);\\n\\t\\t\\t\\t\\t\\tanchor.update(frame);\\n\\t\\t\\t\\t\\t\\tconst callback = this._callbacksAnchors.get(xrAnchor);\\n\\t\\t\\t\\t\\t\\tif (callback) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._callbacksAnchors.delete(xrAnchor);\\n\\t\\t\\t\\t\\t\\t\\t\\tcallback(null, anchor);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.fire('add', anchor);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget supported() {\\n\\t\\t\\t\\treturn this._supported;\\n\\t\\t}\\n\\t\\tget available() {\\n\\t\\t\\t\\treturn this._available;\\n\\t\\t}\\n\\t\\tget persistence() {\\n\\t\\t\\t\\treturn this._persistence;\\n\\t\\t}\\n\\t\\tget uuids() {\\n\\t\\t\\t\\tif (!this._available) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._persistence) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this.manager.active) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this.manager.session.persistentAnchors;\\n\\t\\t}\\n\\t\\tget list() {\\n\\t\\t\\t\\treturn this._list;\\n\\t\\t}\\n\\t\\tconstructor(manager){\\n\\t\\t\\t\\tsuper(), this._supported = platform.browser && !!window.XRAnchor, this._available = false, this._checkingAvailability = false, this._persistence = platform.browser && !!window?.XRSession?.prototype.restorePersistentAnchor, this._creationQueue = [], this._index = new Map(), this._indexByUuid = new Map(), this._list = [], this._callbacksAnchors = new Map();\\n\\t\\t\\t\\tthis.manager = manager;\\n\\t\\t\\t\\tif (this._supported) {\\n\\t\\t\\t\\t\\t\\tthis.manager.on('start', this._onSessionStart, this);\\n\\t\\t\\t\\t\\t\\tthis.manager.on('end', this._onSessionEnd, this);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nXrAnchors.EVENT_AVAILABLE = 'available';\\nXrAnchors.EVENT_UNAVAILABLE = 'unavailable';\\nXrAnchors.EVENT_ERROR = 'error';\\nXrAnchors.EVENT_ADD = 'add';\\nXrAnchors.EVENT_DESTROY = 'destroy';\\n\\nclass XrMesh extends EventHandler {\\n\\t\\tget xrMesh() {\\n\\t\\t\\t\\treturn this._xrMesh;\\n\\t\\t}\\n\\t\\tget label() {\\n\\t\\t\\t\\treturn this._xrMesh.semanticLabel || '';\\n\\t\\t}\\n\\t\\tget vertices() {\\n\\t\\t\\t\\treturn this._xrMesh.vertices;\\n\\t\\t}\\n\\t\\tget indices() {\\n\\t\\t\\t\\treturn this._xrMesh.indices;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tif (!this._xrMesh) return;\\n\\t\\t\\t\\tthis._xrMesh = null;\\n\\t\\t\\t\\tthis.fire('remove');\\n\\t\\t}\\n\\t\\tupdate(frame) {\\n\\t\\t\\t\\tconst manager = this._meshDetection._manager;\\n\\t\\t\\t\\tconst pose = frame.getPose(this._xrMesh.meshSpace, manager._referenceSpace);\\n\\t\\t\\t\\tif (pose) {\\n\\t\\t\\t\\t\\t\\tthis._position.copy(pose.transform.position);\\n\\t\\t\\t\\t\\t\\tthis._rotation.copy(pose.transform.orientation);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._lastChanged !== this._xrMesh.lastChangedTime) {\\n\\t\\t\\t\\t\\t\\tthis._lastChanged = this._xrMesh.lastChangedTime;\\n\\t\\t\\t\\t\\t\\tthis.fire('change');\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tgetPosition() {\\n\\t\\t\\t\\treturn this._position;\\n\\t\\t}\\n\\t\\tgetRotation() {\\n\\t\\t\\t\\treturn this._rotation;\\n\\t\\t}\\n\\t\\tconstructor(meshDetection, xrMesh){\\n\\t\\t\\t\\tsuper(), this._lastChanged = 0, this._position = new Vec3(), this._rotation = new Quat();\\n\\t\\t\\t\\tthis._meshDetection = meshDetection;\\n\\t\\t\\t\\tthis._xrMesh = xrMesh;\\n\\t\\t\\t\\tthis._lastChanged = this._xrMesh.lastChangedTime;\\n\\t\\t}\\n}\\nXrMesh.EVENT_REMOVE = 'remove';\\nXrMesh.EVENT_CHANGE = 'change';\\n\\nclass XrMeshDetection extends EventHandler {\\n\\t\\tupdate(frame) {\\n\\t\\t\\t\\tif (!this._available) {\\n\\t\\t\\t\\t\\t\\tif (!this._manager.session.enabledFeatures && frame.detectedMeshes.size) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._available = true;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('available');\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const xrMesh of frame.detectedMeshes){\\n\\t\\t\\t\\t\\t\\tlet mesh = this._index.get(xrMesh);\\n\\t\\t\\t\\t\\t\\tif (!mesh) {\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh = new XrMesh(this, xrMesh);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._index.set(xrMesh, mesh);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._list.push(mesh);\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh.update(frame);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('add', mesh);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tmesh.update(frame);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const mesh of this._index.values()){\\n\\t\\t\\t\\t\\t\\tif (frame.detectedMeshes.has(mesh.xrMesh)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._removeMesh(mesh);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_removeMesh(mesh) {\\n\\t\\t\\t\\tthis._index.delete(mesh.xrMesh);\\n\\t\\t\\t\\tthis._list.splice(this._list.indexOf(mesh), 1);\\n\\t\\t\\t\\tmesh.destroy();\\n\\t\\t\\t\\tthis.fire('remove', mesh);\\n\\t\\t}\\n\\t\\t_onSessionStart() {\\n\\t\\t\\t\\tif (this._manager.session.enabledFeatures) {\\n\\t\\t\\t\\t\\t\\tconst available = this._manager.session.enabledFeatures.indexOf('mesh-detection') !== -1;\\n\\t\\t\\t\\t\\t\\tif (!available) return;\\n\\t\\t\\t\\t\\t\\tthis._available = available;\\n\\t\\t\\t\\t\\t\\tthis.fire('available');\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onSessionEnd() {\\n\\t\\t\\t\\tif (!this._available) return;\\n\\t\\t\\t\\tthis._available = false;\\n\\t\\t\\t\\tfor (const mesh of this._index.values()){\\n\\t\\t\\t\\t\\t\\tthis._removeMesh(mesh);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.fire('unavailable');\\n\\t\\t}\\n\\t\\tget supported() {\\n\\t\\t\\t\\treturn this._supported;\\n\\t\\t}\\n\\t\\tget available() {\\n\\t\\t\\t\\treturn this._available;\\n\\t\\t}\\n\\t\\tget meshes() {\\n\\t\\t\\t\\treturn this._list;\\n\\t\\t}\\n\\t\\tconstructor(manager){\\n\\t\\t\\t\\tsuper(), this._supported = platform.browser && !!window.XRMesh, this._available = false, this._index = new Map(), this._list = [];\\n\\t\\t\\t\\tthis._manager = manager;\\n\\t\\t\\t\\tif (this._supported) {\\n\\t\\t\\t\\t\\t\\tthis._manager.on('start', this._onSessionStart, this);\\n\\t\\t\\t\\t\\t\\tthis._manager.on('end', this._onSessionEnd, this);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nXrMeshDetection.EVENT_AVAILABLE = 'available';\\nXrMeshDetection.EVENT_UNAVAILABLE = 'unavailable';\\nXrMeshDetection.EVENT_ADD = 'add';\\nXrMeshDetection.EVENT_REMOVE = 'remove';\\n\\nclass XrView extends EventHandler {\\n\\t\\tget textureColor() {\\n\\t\\t\\t\\treturn this._textureColor;\\n\\t\\t}\\n\\t\\tget textureDepth() {\\n\\t\\t\\t\\treturn this._textureDepth;\\n\\t\\t}\\n\\t\\tget depthUvMatrix() {\\n\\t\\t\\t\\treturn this._depthMatrix;\\n\\t\\t}\\n\\t\\tget depthValueToMeters() {\\n\\t\\t\\t\\treturn this._depthInfo?.rawValueToMeters || 0;\\n\\t\\t}\\n\\t\\tget eye() {\\n\\t\\t\\t\\treturn this._xrView.eye;\\n\\t\\t}\\n\\t\\tget viewport() {\\n\\t\\t\\t\\treturn this._viewport;\\n\\t\\t}\\n\\t\\tget projMat() {\\n\\t\\t\\t\\treturn this._projMat;\\n\\t\\t}\\n\\t\\tget projViewOffMat() {\\n\\t\\t\\t\\treturn this._projViewOffMat;\\n\\t\\t}\\n\\t\\tget viewOffMat() {\\n\\t\\t\\t\\treturn this._viewOffMat;\\n\\t\\t}\\n\\t\\tget viewInvOffMat() {\\n\\t\\t\\t\\treturn this._viewInvOffMat;\\n\\t\\t}\\n\\t\\tget viewMat3() {\\n\\t\\t\\t\\treturn this._viewMat3;\\n\\t\\t}\\n\\t\\tget positionData() {\\n\\t\\t\\t\\treturn this._positionData;\\n\\t\\t}\\n\\t\\tupdate(frame, xrView) {\\n\\t\\t\\t\\tthis._xrView = xrView;\\n\\t\\t\\t\\tif (this._manager.views.availableColor) {\\n\\t\\t\\t\\t\\t\\tthis._xrCamera = this._xrView.camera;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst layer = frame.session.renderState.baseLayer;\\n\\t\\t\\t\\tconst viewport = layer.getViewport(this._xrView);\\n\\t\\t\\t\\tthis._viewport.x = viewport.x;\\n\\t\\t\\t\\tthis._viewport.y = viewport.y;\\n\\t\\t\\t\\tthis._viewport.z = viewport.width;\\n\\t\\t\\t\\tthis._viewport.w = viewport.height;\\n\\t\\t\\t\\tthis._projMat.set(this._xrView.projectionMatrix);\\n\\t\\t\\t\\tthis._viewMat.set(this._xrView.transform.inverse.matrix);\\n\\t\\t\\t\\tthis._viewInvMat.set(this._xrView.transform.matrix);\\n\\t\\t\\t\\tthis._updateTextureColor();\\n\\t\\t\\t\\tthis._updateDepth(frame);\\n\\t\\t}\\n\\t\\t_updateTextureColor() {\\n\\t\\t\\t\\tif (!this._manager.views.availableColor || !this._xrCamera || !this._textureColor) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst binding = this._manager.webglBinding;\\n\\t\\t\\t\\tif (!binding) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst texture = binding.getCameraImage(this._xrCamera);\\n\\t\\t\\t\\tif (!texture) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst device = this._manager.app.graphicsDevice;\\n\\t\\t\\t\\tconst gl = device.gl;\\n\\t\\t\\t\\tif (!this._frameBufferSource) {\\n\\t\\t\\t\\t\\t\\tthis._frameBufferSource = gl.createFramebuffer();\\n\\t\\t\\t\\t\\t\\tthis._frameBuffer = gl.createFramebuffer();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst attachmentBaseConstant = gl.COLOR_ATTACHMENT0;\\n\\t\\t\\t\\t\\t\\tconst width = this._xrCamera.width;\\n\\t\\t\\t\\t\\t\\tconst height = this._xrCamera.height;\\n\\t\\t\\t\\t\\t\\tdevice.setFramebuffer(this._frameBufferSource);\\n\\t\\t\\t\\t\\t\\tgl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentBaseConstant, gl.TEXTURE_2D, texture, 0);\\n\\t\\t\\t\\t\\t\\tdevice.setFramebuffer(this._frameBuffer);\\n\\t\\t\\t\\t\\t\\tgl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentBaseConstant, gl.TEXTURE_2D, this._textureColor.impl._glTexture, 0);\\n\\t\\t\\t\\t\\t\\tgl.bindFramebuffer(gl.READ_FRAMEBUFFER, this._frameBufferSource);\\n\\t\\t\\t\\t\\t\\tgl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, this._frameBuffer);\\n\\t\\t\\t\\t\\t\\tgl.blitFramebuffer(0, height, width, 0, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_updateDepth(frame) {\\n\\t\\t\\t\\tif (!this._manager.views.availableDepth || !this._textureDepth) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst gpu = this._manager.views.depthGpuOptimized;\\n\\t\\t\\t\\tconst infoSource = gpu ? this._manager.webglBinding : frame;\\n\\t\\t\\t\\tif (!infoSource) {\\n\\t\\t\\t\\t\\t\\tthis._depthInfo = null;\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst depthInfo = infoSource.getDepthInformation(this._xrView);\\n\\t\\t\\t\\tif (!depthInfo) {\\n\\t\\t\\t\\t\\t\\tthis._depthInfo = null;\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet matrixDirty = !this._depthInfo !== !depthInfo;\\n\\t\\t\\t\\tthis._depthInfo = depthInfo;\\n\\t\\t\\t\\tconst width = this._depthInfo?.width || 4;\\n\\t\\t\\t\\tconst height = this._depthInfo?.height || 4;\\n\\t\\t\\t\\tlet resized = false;\\n\\t\\t\\t\\tif (this._textureDepth.width !== width || this._textureDepth.height !== height) {\\n\\t\\t\\t\\t\\t\\tthis._textureDepth._width = width;\\n\\t\\t\\t\\t\\t\\tthis._textureDepth._height = height;\\n\\t\\t\\t\\t\\t\\tmatrixDirty = true;\\n\\t\\t\\t\\t\\t\\tresized = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (matrixDirty) {\\n\\t\\t\\t\\t\\t\\tif (this._depthInfo) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._depthMatrix.data.set(this._depthInfo.normDepthBufferFromNormView.matrix);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._depthMatrix.setIdentity();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._depthInfo) {\\n\\t\\t\\t\\t\\t\\tif (gpu) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._depthInfo.texture) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst gl = this._manager.app.graphicsDevice.gl;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._textureDepth.impl._glTexture = this._depthInfo.texture;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this._depthInfo.textureType === 'texture-array') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._textureDepth.impl._glTarget = gl.TEXTURE_2D_ARRAY;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._textureDepth.impl._glTarget = gl.TEXTURE_2D;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tswitch(this._manager.views.depthPixelFormat){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_R32F:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._textureDepth.impl._glInternalFormat = gl.R32F;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._textureDepth.impl._glPixelType = gl.FLOAT;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._textureDepth.impl._glFormat = gl.RED;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcase PIXELFORMAT_DEPTH:\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._textureDepth.impl._glInternalFormat = gl.DEPTH_COMPONENT16;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._textureDepth.impl._glPixelType = gl.UNSIGNED_SHORT;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._textureDepth.impl._glFormat = gl.DEPTH_COMPONENT;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._textureDepth.impl._glCreated = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._textureDepth._levels[0] = new Uint8Array(this._depthInfo.data);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._textureDepth.upload();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._textureDepth._levels[0] = this._emptyDepthBuffer;\\n\\t\\t\\t\\t\\t\\tthis._textureDepth.upload();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (resized) this.fire('depth:resize', width, height);\\n\\t\\t}\\n\\t\\tupdateTransforms(transform) {\\n\\t\\t\\t\\tif (transform) {\\n\\t\\t\\t\\t\\t\\tthis._viewInvOffMat.mul2(transform, this._viewInvMat);\\n\\t\\t\\t\\t\\t\\tthis.viewOffMat.copy(this._viewInvOffMat).invert();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._viewInvOffMat.copy(this._viewInvMat);\\n\\t\\t\\t\\t\\t\\tthis.viewOffMat.copy(this._viewMat);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._viewMat3.setFromMat4(this._viewOffMat);\\n\\t\\t\\t\\tthis._projViewOffMat.mul2(this._projMat, this._viewOffMat);\\n\\t\\t\\t\\tthis._positionData[0] = this._viewInvOffMat.data[12];\\n\\t\\t\\t\\tthis._positionData[1] = this._viewInvOffMat.data[13];\\n\\t\\t\\t\\tthis._positionData[2] = this._viewInvOffMat.data[14];\\n\\t\\t}\\n\\t\\t_onDeviceLost() {\\n\\t\\t\\t\\tthis._frameBufferSource = null;\\n\\t\\t\\t\\tthis._frameBuffer = null;\\n\\t\\t\\t\\tthis._depthInfo = null;\\n\\t\\t}\\n\\t\\tgetDepth(u, v) {\\n\\t\\t\\t\\tif (this._manager.views.depthGpuOptimized) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._depthInfo?.getDepthInMeters(u, v) ?? null;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis._depthInfo = null;\\n\\t\\t\\t\\tif (this._textureColor) {\\n\\t\\t\\t\\t\\t\\tthis._textureColor.destroy();\\n\\t\\t\\t\\t\\t\\tthis._textureColor = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._textureDepth) {\\n\\t\\t\\t\\t\\t\\tthis._textureDepth.destroy();\\n\\t\\t\\t\\t\\t\\tthis._textureDepth = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._frameBufferSource) {\\n\\t\\t\\t\\t\\t\\tconst gl = this._manager.app.graphicsDevice.gl;\\n\\t\\t\\t\\t\\t\\tgl.deleteFramebuffer(this._frameBufferSource);\\n\\t\\t\\t\\t\\t\\tthis._frameBufferSource = null;\\n\\t\\t\\t\\t\\t\\tgl.deleteFramebuffer(this._frameBuffer);\\n\\t\\t\\t\\t\\t\\tthis._frameBuffer = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(manager, xrView, viewsCount){\\n\\t\\t\\t\\tsuper(), this._positionData = new Float32Array(3), this._viewport = new Vec4(), this._projMat = new Mat4(), this._projViewOffMat = new Mat4(), this._viewMat = new Mat4(), this._viewOffMat = new Mat4(), this._viewMat3 = new Mat3(), this._viewInvMat = new Mat4(), this._viewInvOffMat = new Mat4(), this._xrCamera = null, this._textureColor = null, this._textureDepth = null, this._depthInfo = null, this._emptyDepthBuffer = new Uint8Array(32), this._depthMatrix = new Mat4();\\n\\t\\t\\t\\tthis._manager = manager;\\n\\t\\t\\t\\tthis._xrView = xrView;\\n\\t\\t\\t\\tconst device = this._manager.app.graphicsDevice;\\n\\t\\t\\t\\tif (this._manager.views.supportedColor) {\\n\\t\\t\\t\\t\\t\\tthis._xrCamera = this._xrView.camera;\\n\\t\\t\\t\\t\\t\\tif (this._manager.views.availableColor && this._xrCamera) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._textureColor = new Texture(device, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_RGB8,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tminFilter: FILTER_LINEAR,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmagFilter: FILTER_LINEAR,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twidth: this._xrCamera.width,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\theight: this._xrCamera.height,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tname: `XrView-${this._xrView.eye}-Color`\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._manager.views.supportedDepth && this._manager.views.availableDepth) {\\n\\t\\t\\t\\t\\t\\tconst filtering = this._manager.views.depthGpuOptimized ? FILTER_NEAREST : FILTER_LINEAR;\\n\\t\\t\\t\\t\\t\\tthis._textureDepth = new Texture(device, {\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: this._manager.views.depthPixelFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tarrayLength: viewsCount === 1 ? 0 : viewsCount,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\t\\t\\tminFilter: filtering,\\n\\t\\t\\t\\t\\t\\t\\t\\tmagFilter: filtering,\\n\\t\\t\\t\\t\\t\\t\\t\\twidth: 4,\\n\\t\\t\\t\\t\\t\\t\\t\\theight: 4,\\n\\t\\t\\t\\t\\t\\t\\t\\tname: `XrView-${this._xrView.eye}-Depth`\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this._textureDepth._levels.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._textureDepth._levels[i] = this._emptyDepthBuffer;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._textureDepth.upload();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._textureColor || this._textureDepth) {\\n\\t\\t\\t\\t\\t\\tdevice.on('devicelost', this._onDeviceLost, this);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nXrView.EVENT_DEPTHRESIZE = 'depth:resize';\\n\\nclass XrViews extends EventHandler {\\n\\t\\tget list() {\\n\\t\\t\\t\\treturn this._list;\\n\\t\\t}\\n\\t\\tget supportedColor() {\\n\\t\\t\\t\\treturn this._supportedColor;\\n\\t\\t}\\n\\t\\tget supportedDepth() {\\n\\t\\t\\t\\treturn this._supportedDepth;\\n\\t\\t}\\n\\t\\tget availableColor() {\\n\\t\\t\\t\\treturn this._availableColor;\\n\\t\\t}\\n\\t\\tget availableDepth() {\\n\\t\\t\\t\\treturn this._availableDepth;\\n\\t\\t}\\n\\t\\tget depthUsage() {\\n\\t\\t\\t\\treturn this._depthUsage;\\n\\t\\t}\\n\\t\\tget depthGpuOptimized() {\\n\\t\\t\\t\\treturn this._depthUsage === XRDEPTHSENSINGUSAGE_GPU;\\n\\t\\t}\\n\\t\\tget depthFormat() {\\n\\t\\t\\t\\treturn this._depthFormat;\\n\\t\\t}\\n\\t\\tget depthPixelFormat() {\\n\\t\\t\\t\\treturn this._depthFormats[this._depthFormat] ?? null;\\n\\t\\t}\\n\\t\\tupdate(frame, xrViews) {\\n\\t\\t\\t\\tfor(let i = 0; i < xrViews.length; i++){\\n\\t\\t\\t\\t\\t\\tthis._indexTmp.set(xrViews[i].eye, xrViews[i]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const [eye, xrView] of this._indexTmp){\\n\\t\\t\\t\\t\\t\\tlet view = this._index.get(eye);\\n\\t\\t\\t\\t\\t\\tif (!view) {\\n\\t\\t\\t\\t\\t\\t\\t\\tview = new XrView(this._manager, xrView, xrViews.length);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._index.set(eye, view);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._list.push(view);\\n\\t\\t\\t\\t\\t\\t\\t\\tview.update(frame, xrView);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('add', view);\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tview.update(frame, xrView);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const [eye, view] of this._index){\\n\\t\\t\\t\\t\\t\\tif (this._indexTmp.has(eye)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tview.destroy();\\n\\t\\t\\t\\t\\t\\tthis._index.delete(eye);\\n\\t\\t\\t\\t\\t\\tconst ind = this._list.indexOf(view);\\n\\t\\t\\t\\t\\t\\tif (ind !== -1) this._list.splice(ind, 1);\\n\\t\\t\\t\\t\\t\\tthis.fire('remove', view);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._indexTmp.clear();\\n\\t\\t}\\n\\t\\tget(eye) {\\n\\t\\t\\t\\treturn this._index.get(eye) || null;\\n\\t\\t}\\n\\t\\t_onSessionStart() {\\n\\t\\t\\t\\tif (this._manager.type !== XRTYPE_AR) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._manager.session.enabledFeatures) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._availableColor = this._manager.session.enabledFeatures.indexOf('camera-access') !== -1;\\n\\t\\t\\t\\tthis._availableDepth = this._manager.session.enabledFeatures.indexOf('depth-sensing') !== -1;\\n\\t\\t\\t\\tif (this._availableDepth) {\\n\\t\\t\\t\\t\\t\\tconst session = this._manager.session;\\n\\t\\t\\t\\t\\t\\tthis._depthUsage = session.depthUsage;\\n\\t\\t\\t\\t\\t\\tthis._depthFormat = session.depthDataFormat;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onSessionEnd() {\\n\\t\\t\\t\\tfor (const view of this._index.values()){\\n\\t\\t\\t\\t\\t\\tview.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._index.clear();\\n\\t\\t\\t\\tthis._availableColor = false;\\n\\t\\t\\t\\tthis._availableDepth = false;\\n\\t\\t\\t\\tthis._depthUsage = '';\\n\\t\\t\\t\\tthis._depthFormat = '';\\n\\t\\t\\t\\tthis._list.length = 0;\\n\\t\\t}\\n\\t\\tconstructor(manager){\\n\\t\\t\\t\\tsuper(), this._index = new Map(), this._indexTmp = new Map(), this._list = [], this._supportedColor = platform.browser && !!window.XRCamera && !!window.XRWebGLBinding, this._supportedDepth = platform.browser && !!window.XRDepthInformation, this._availableColor = false, this._availableDepth = false, this._depthUsage = '', this._depthFormat = '', this._depthFormats = {\\n\\t\\t\\t\\t\\t\\t[XRDEPTHSENSINGFORMAT_L8A8]: PIXELFORMAT_LA8,\\n\\t\\t\\t\\t\\t\\t[XRDEPTHSENSINGFORMAT_R16U]: PIXELFORMAT_DEPTH,\\n\\t\\t\\t\\t\\t\\t[XRDEPTHSENSINGFORMAT_F32]: PIXELFORMAT_R32F\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis._manager = manager;\\n\\t\\t\\t\\tthis._manager.on('start', this._onSessionStart, this);\\n\\t\\t\\t\\tthis._manager.on('end', this._onSessionEnd, this);\\n\\t\\t}\\n}\\nXrViews.EVENT_ADD = 'add';\\nXrViews.EVENT_REMOVE = 'remove';\\n\\nclass XrManager extends EventHandler {\\n\\t\\tdestroy() {}\\n\\t\\tstart(camera, type, spaceType, options) {\\n\\t\\t\\t\\tlet callback = options;\\n\\t\\t\\t\\tif (typeof options === 'object') {\\n\\t\\t\\t\\t\\t\\tcallback = options.callback;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._available[type]) {\\n\\t\\t\\t\\t\\t\\tif (callback) callback(new Error('XR is not available'));\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._session) {\\n\\t\\t\\t\\t\\t\\tif (callback) callback(new Error('XR session is already started'));\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._camera = camera;\\n\\t\\t\\t\\tthis._camera.camera.xr = this;\\n\\t\\t\\t\\tthis._type = type;\\n\\t\\t\\t\\tthis._spaceType = spaceType;\\n\\t\\t\\t\\tthis._framebufferScaleFactor = options?.framebufferScaleFactor ?? 1.0;\\n\\t\\t\\t\\tthis._setClipPlanes(camera.nearClip, camera.farClip);\\n\\t\\t\\t\\tconst opts = {\\n\\t\\t\\t\\t\\t\\trequiredFeatures: [\\n\\t\\t\\t\\t\\t\\t\\t\\tspaceType\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\toptionalFeatures: []\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst device = this.app.graphicsDevice;\\n\\t\\t\\t\\tif (device?.isWebGPU) {\\n\\t\\t\\t\\t\\t\\topts.requiredFeatures.push('webgpu');\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst webgl = device?.isWebGL2;\\n\\t\\t\\t\\tif (type === XRTYPE_AR) {\\n\\t\\t\\t\\t\\t\\topts.optionalFeatures.push('light-estimation');\\n\\t\\t\\t\\t\\t\\topts.optionalFeatures.push('hit-test');\\n\\t\\t\\t\\t\\t\\tif (options) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (options.imageTracking && this.imageTracking.supported) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\topts.optionalFeatures.push('image-tracking');\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (options.planeDetection) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\topts.optionalFeatures.push('plane-detection');\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (options.meshDetection) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\topts.optionalFeatures.push('mesh-detection');\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.domOverlay.supported && this.domOverlay.root) {\\n\\t\\t\\t\\t\\t\\t\\t\\topts.optionalFeatures.push('dom-overlay');\\n\\t\\t\\t\\t\\t\\t\\t\\topts.domOverlay = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\troot: this.domOverlay.root\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (options && options.anchors && this.anchors.supported) {\\n\\t\\t\\t\\t\\t\\t\\t\\topts.optionalFeatures.push('anchors');\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (options && options.depthSensing && this.views.supportedDepth) {\\n\\t\\t\\t\\t\\t\\t\\t\\topts.optionalFeatures.push('depth-sensing');\\n\\t\\t\\t\\t\\t\\t\\t\\tconst usagePreference = [];\\n\\t\\t\\t\\t\\t\\t\\t\\tconst dataFormatPreference = [];\\n\\t\\t\\t\\t\\t\\t\\t\\tusagePreference.push(XRDEPTHSENSINGUSAGE_GPU, XRDEPTHSENSINGUSAGE_CPU);\\n\\t\\t\\t\\t\\t\\t\\t\\tdataFormatPreference.push(XRDEPTHSENSINGFORMAT_F32, XRDEPTHSENSINGFORMAT_L8A8, XRDEPTHSENSINGFORMAT_R16U);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (options.depthSensing.usagePreference) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst ind = usagePreference.indexOf(options.depthSensing.usagePreference);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (ind !== -1) usagePreference.splice(ind, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tusagePreference.unshift(options.depthSensing.usagePreference);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (options.depthSensing.dataFormatPreference) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst ind = dataFormatPreference.indexOf(options.depthSensing.dataFormatPreference);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (ind !== -1) dataFormatPreference.splice(ind, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdataFormatPreference.unshift(options.depthSensing.dataFormatPreference);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\topts.depthSensing = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tusagePreference: usagePreference,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdataFormatPreference: dataFormatPreference\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (webgl && options && options.cameraColor && this.views.supportedColor) {\\n\\t\\t\\t\\t\\t\\t\\t\\topts.optionalFeatures.push('camera-access');\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\topts.optionalFeatures.push('hand-tracking');\\n\\t\\t\\t\\tif (options && options.optionalFeatures) {\\n\\t\\t\\t\\t\\t\\topts.optionalFeatures = opts.optionalFeatures.concat(options.optionalFeatures);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.imageTracking.supported && this.imageTracking.images.length) {\\n\\t\\t\\t\\t\\t\\tthis.imageTracking.prepareImages((err, trackedImages)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (err) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (callback) callback(err);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('error', err);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tif (trackedImages !== null) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\topts.trackedImages = trackedImages;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._onStartOptionsReady(type, spaceType, opts, callback);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._onStartOptionsReady(type, spaceType, opts, callback);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onStartOptionsReady(type, spaceType, options, callback) {\\n\\t\\t\\t\\tnavigator.xr.requestSession(type, options).then((session)=>{\\n\\t\\t\\t\\t\\t\\tthis._onSessionStart(session, spaceType, callback);\\n\\t\\t\\t\\t}).catch((ex)=>{\\n\\t\\t\\t\\t\\t\\tthis._camera.camera.xr = null;\\n\\t\\t\\t\\t\\t\\tthis._camera = null;\\n\\t\\t\\t\\t\\t\\tthis._type = null;\\n\\t\\t\\t\\t\\t\\tthis._spaceType = null;\\n\\t\\t\\t\\t\\t\\tif (callback) callback(ex);\\n\\t\\t\\t\\t\\t\\tthis.fire('error', ex);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tend(callback) {\\n\\t\\t\\t\\tif (!this._session) {\\n\\t\\t\\t\\t\\t\\tif (callback) callback(new Error('XR Session is not initialized'));\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.webglBinding = null;\\n\\t\\t\\t\\tif (callback) this.once('end', callback);\\n\\t\\t\\t\\tthis._session.end();\\n\\t\\t}\\n\\t\\tisAvailable(type) {\\n\\t\\t\\t\\treturn this._available[type];\\n\\t\\t}\\n\\t\\t_deviceAvailabilityCheck() {\\n\\t\\t\\t\\tfor(const key in this._available){\\n\\t\\t\\t\\t\\t\\tthis._sessionSupportCheck(key);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tinitiateRoomCapture(callback) {\\n\\t\\t\\t\\tif (!this._session) {\\n\\t\\t\\t\\t\\t\\tcallback(new Error('Session is not active'));\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._session.initiateRoomCapture) {\\n\\t\\t\\t\\t\\t\\tcallback(new Error('Session does not support manual room capture'));\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._session.initiateRoomCapture().then(()=>{\\n\\t\\t\\t\\t\\t\\tif (callback) callback(null);\\n\\t\\t\\t\\t}).catch((err)=>{\\n\\t\\t\\t\\t\\t\\tif (callback) callback(err);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tupdateTargetFrameRate(frameRate, callback) {\\n\\t\\t\\t\\tif (!this._session?.updateTargetFrameRate) {\\n\\t\\t\\t\\t\\t\\tcallback?.(new Error('unable to update frameRate'));\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._session.updateTargetFrameRate(frameRate).then(()=>{\\n\\t\\t\\t\\t\\t\\tcallback?.();\\n\\t\\t\\t\\t}).catch((err)=>{\\n\\t\\t\\t\\t\\t\\tcallback?.(err);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\t_sessionSupportCheck(type) {\\n\\t\\t\\t\\tnavigator.xr.isSessionSupported(type).then((available)=>{\\n\\t\\t\\t\\t\\t\\tif (this._available[type] === available) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._available[type] = available;\\n\\t\\t\\t\\t\\t\\tthis.fire('available', type, available);\\n\\t\\t\\t\\t\\t\\tthis.fire(`available:${type}`, available);\\n\\t\\t\\t\\t}).catch((ex)=>{\\n\\t\\t\\t\\t\\t\\tthis.fire('error', ex);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\t_onSessionStart(session, spaceType, callback) {\\n\\t\\t\\t\\tlet failed = false;\\n\\t\\t\\t\\tthis._session = session;\\n\\t\\t\\t\\tconst onVisibilityChange = ()=>{\\n\\t\\t\\t\\t\\t\\tthis.fire('visibility:change', session.visibilityState);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst onClipPlanesChange = ()=>{\\n\\t\\t\\t\\t\\t\\tthis._setClipPlanes(this._camera.nearClip, this._camera.farClip);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst onFrameRateChange = ()=>{\\n\\t\\t\\t\\t\\t\\tthis.fire('frameratechange', this._session?.frameRate);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst onEnd = ()=>{\\n\\t\\t\\t\\t\\t\\tif (this._camera) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._camera.off('set_nearClip', onClipPlanesChange);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._camera.off('set_farClip', onClipPlanesChange);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._camera.camera.xr = null;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._camera = null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tsession.removeEventListener('end', onEnd);\\n\\t\\t\\t\\t\\t\\tsession.removeEventListener('visibilitychange', onVisibilityChange);\\n\\t\\t\\t\\t\\t\\tsession.removeEventListener('frameratechange', onFrameRateChange);\\n\\t\\t\\t\\t\\t\\tif (!failed) this.fire('end');\\n\\t\\t\\t\\t\\t\\tthis._session = null;\\n\\t\\t\\t\\t\\t\\tthis._referenceSpace = null;\\n\\t\\t\\t\\t\\t\\tthis._width = 0;\\n\\t\\t\\t\\t\\t\\tthis._height = 0;\\n\\t\\t\\t\\t\\t\\tthis._type = null;\\n\\t\\t\\t\\t\\t\\tthis._spaceType = null;\\n\\t\\t\\t\\t\\t\\tif (this.app.systems) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.app.requestAnimationFrame();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tsession.addEventListener('end', onEnd);\\n\\t\\t\\t\\tsession.addEventListener('visibilitychange', onVisibilityChange);\\n\\t\\t\\t\\tthis._camera.on('set_nearClip', onClipPlanesChange);\\n\\t\\t\\t\\tthis._camera.on('set_farClip', onClipPlanesChange);\\n\\t\\t\\t\\tthis._createBaseLayer();\\n\\t\\t\\t\\tif (this.session.supportedFrameRates) {\\n\\t\\t\\t\\t\\t\\tthis._supportedFrameRates = Array.from(this.session.supportedFrameRates);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._supportedFrameRates = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._session.addEventListener('frameratechange', onFrameRateChange);\\n\\t\\t\\t\\tsession.requestReferenceSpace(spaceType).then((referenceSpace)=>{\\n\\t\\t\\t\\t\\t\\tthis._referenceSpace = referenceSpace;\\n\\t\\t\\t\\t\\t\\tthis.app.requestAnimationFrame();\\n\\t\\t\\t\\t\\t\\tif (callback) callback(null);\\n\\t\\t\\t\\t\\t\\tthis.fire('start');\\n\\t\\t\\t\\t}).catch((ex)=>{\\n\\t\\t\\t\\t\\t\\tfailed = true;\\n\\t\\t\\t\\t\\t\\tsession.end();\\n\\t\\t\\t\\t\\t\\tif (callback) callback(ex);\\n\\t\\t\\t\\t\\t\\tthis.fire('error', ex);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\t_setClipPlanes(near, far) {\\n\\t\\t\\t\\tif (this._depthNear === near && this._depthFar === far) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._depthNear = near;\\n\\t\\t\\t\\tthis._depthFar = far;\\n\\t\\t\\t\\tif (!this._session) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._session.updateRenderState({\\n\\t\\t\\t\\t\\t\\tdepthNear: this._depthNear,\\n\\t\\t\\t\\t\\t\\tdepthFar: this._depthFar\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\t_createBaseLayer() {\\n\\t\\t\\t\\tconst device = this.app.graphicsDevice;\\n\\t\\t\\t\\tconst framebufferScaleFactor = device.maxPixelRatio / window.devicePixelRatio * this._framebufferScaleFactor;\\n\\t\\t\\t\\tthis._baseLayer = new XRWebGLLayer(this._session, device.gl, {\\n\\t\\t\\t\\t\\t\\talpha: true,\\n\\t\\t\\t\\t\\t\\tdepth: true,\\n\\t\\t\\t\\t\\t\\tstencil: true,\\n\\t\\t\\t\\t\\t\\tframebufferScaleFactor: framebufferScaleFactor,\\n\\t\\t\\t\\t\\t\\tantialias: false\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tif (device?.isWebGL2 && window.XRWebGLBinding) {\\n\\t\\t\\t\\t\\t\\ttry {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.webglBinding = new XRWebGLBinding(this._session, device.gl);\\n\\t\\t\\t\\t\\t\\t} catch (ex) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('error', ex);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._session.updateRenderState({\\n\\t\\t\\t\\t\\t\\tbaseLayer: this._baseLayer,\\n\\t\\t\\t\\t\\t\\tdepthNear: this._depthNear,\\n\\t\\t\\t\\t\\t\\tdepthFar: this._depthFar\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\t_onDeviceLost() {\\n\\t\\t\\t\\tif (!this._session) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.webglBinding) {\\n\\t\\t\\t\\t\\t\\tthis.webglBinding = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._baseLayer = null;\\n\\t\\t\\t\\tthis._session.updateRenderState({\\n\\t\\t\\t\\t\\t\\tbaseLayer: this._baseLayer,\\n\\t\\t\\t\\t\\t\\tdepthNear: this._depthNear,\\n\\t\\t\\t\\t\\t\\tdepthFar: this._depthFar\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\t_onDeviceRestored() {\\n\\t\\t\\t\\tif (!this._session) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tsetTimeout(()=>{\\n\\t\\t\\t\\t\\t\\tthis.app.graphicsDevice.gl.makeXRCompatible().then(()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._createBaseLayer();\\n\\t\\t\\t\\t\\t\\t}).catch((ex)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.fire('error', ex);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}, 0);\\n\\t\\t}\\n\\t\\tupdate(frame) {\\n\\t\\t\\t\\tif (!this._session) return false;\\n\\t\\t\\t\\tconst width = frame.session.renderState.baseLayer.framebufferWidth;\\n\\t\\t\\t\\tconst height = frame.session.renderState.baseLayer.framebufferHeight;\\n\\t\\t\\t\\tif (this._width !== width || this._height !== height) {\\n\\t\\t\\t\\t\\t\\tthis._width = width;\\n\\t\\t\\t\\t\\t\\tthis._height = height;\\n\\t\\t\\t\\t\\t\\tthis.app.graphicsDevice.setResolution(width, height);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst pose = frame.getViewerPose(this._referenceSpace);\\n\\t\\t\\t\\tif (!pose) return false;\\n\\t\\t\\t\\tconst lengthOld = this.views.list.length;\\n\\t\\t\\t\\tthis.views.update(frame, pose.views);\\n\\t\\t\\t\\tconst posePosition = pose.transform.position;\\n\\t\\t\\t\\tconst poseOrientation = pose.transform.orientation;\\n\\t\\t\\t\\tthis._localPosition.set(posePosition.x, posePosition.y, posePosition.z);\\n\\t\\t\\t\\tthis._localRotation.set(poseOrientation.x, poseOrientation.y, poseOrientation.z, poseOrientation.w);\\n\\t\\t\\t\\tif (lengthOld === 0 && this.views.list.length > 0) {\\n\\t\\t\\t\\t\\t\\tconst viewProjMat = new Mat4();\\n\\t\\t\\t\\t\\t\\tconst view = this.views.list[0];\\n\\t\\t\\t\\t\\t\\tviewProjMat.copy(view.projMat);\\n\\t\\t\\t\\t\\t\\tconst data = viewProjMat.data;\\n\\t\\t\\t\\t\\t\\tconst fov = 2.0 * Math.atan(1.0 / data[5]) * 180.0 / Math.PI;\\n\\t\\t\\t\\t\\t\\tconst aspectRatio = data[5] / data[0];\\n\\t\\t\\t\\t\\t\\tconst farClip = data[14] / (data[10] + 1);\\n\\t\\t\\t\\t\\t\\tconst nearClip = data[14] / (data[10] - 1);\\n\\t\\t\\t\\t\\t\\tconst horizontalFov = false;\\n\\t\\t\\t\\t\\t\\tconst camera = this._camera.camera;\\n\\t\\t\\t\\t\\t\\tcamera.setXrProperties({\\n\\t\\t\\t\\t\\t\\t\\t\\taspectRatio,\\n\\t\\t\\t\\t\\t\\t\\t\\tfarClip,\\n\\t\\t\\t\\t\\t\\t\\t\\tfov,\\n\\t\\t\\t\\t\\t\\t\\t\\thorizontalFov,\\n\\t\\t\\t\\t\\t\\t\\t\\tnearClip\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._camera.camera._node.setLocalPosition(this._localPosition);\\n\\t\\t\\t\\tthis._camera.camera._node.setLocalRotation(this._localRotation);\\n\\t\\t\\t\\tthis.input.update(frame);\\n\\t\\t\\t\\tif (this._type === XRTYPE_AR) {\\n\\t\\t\\t\\t\\t\\tif (this.hitTest.supported) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.hitTest.update(frame);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.lightEstimation.supported) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.lightEstimation.update(frame);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.imageTracking.supported) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.imageTracking.update(frame);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.anchors.supported) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.anchors.update(frame);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.planeDetection.supported) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.planeDetection.update(frame);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.meshDetection.supported) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.meshDetection.update(frame);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.fire('update', frame);\\n\\t\\t\\t\\treturn true;\\n\\t\\t}\\n\\t\\tget supported() {\\n\\t\\t\\t\\treturn this._supported;\\n\\t\\t}\\n\\t\\tget active() {\\n\\t\\t\\t\\treturn !!this._session;\\n\\t\\t}\\n\\t\\tget type() {\\n\\t\\t\\t\\treturn this._type;\\n\\t\\t}\\n\\t\\tget spaceType() {\\n\\t\\t\\t\\treturn this._spaceType;\\n\\t\\t}\\n\\t\\tget session() {\\n\\t\\t\\t\\treturn this._session;\\n\\t\\t}\\n\\t\\tget frameRate() {\\n\\t\\t\\t\\treturn this._session?.frameRate ?? null;\\n\\t\\t}\\n\\t\\tget supportedFrameRates() {\\n\\t\\t\\t\\treturn this._supportedFrameRates;\\n\\t\\t}\\n\\t\\tget framebufferScaleFactor() {\\n\\t\\t\\t\\treturn this._framebufferScaleFactor;\\n\\t\\t}\\n\\t\\tset fixedFoveation(value) {\\n\\t\\t\\t\\tif ((this._baseLayer?.fixedFoveation ?? null) !== null) {\\n\\t\\t\\t\\t\\t\\tif (this.app.graphicsDevice.samples > 1) ;\\n\\t\\t\\t\\t\\t\\tthis._baseLayer.fixedFoveation = value;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget fixedFoveation() {\\n\\t\\t\\t\\treturn this._baseLayer?.fixedFoveation ?? null;\\n\\t\\t}\\n\\t\\tget camera() {\\n\\t\\t\\t\\treturn this._camera ? this._camera.entity : null;\\n\\t\\t}\\n\\t\\tget visibilityState() {\\n\\t\\t\\t\\tif (!this._session) {\\n\\t\\t\\t\\t\\t\\treturn null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this._session.visibilityState;\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tsuper(), this._supported = platform.browser && !!navigator.xr, this._available = {}, this._type = null, this._spaceType = null, this._session = null, this._baseLayer = null, this.webglBinding = null, this._referenceSpace = null, this._camera = null, this._localPosition = new Vec3(), this._localRotation = new Quat(), this._depthNear = 0.1, this._depthFar = 1000, this._supportedFrameRates = null, this._width = 0, this._height = 0, this._framebufferScaleFactor = 1.0;\\n\\t\\t\\t\\tthis.app = app;\\n\\t\\t\\t\\tthis._available[XRTYPE_INLINE] = false;\\n\\t\\t\\t\\tthis._available[XRTYPE_VR] = false;\\n\\t\\t\\t\\tthis._available[XRTYPE_AR] = false;\\n\\t\\t\\t\\tthis.domOverlay = new XrDomOverlay(this);\\n\\t\\t\\t\\tthis.hitTest = new XrHitTest(this);\\n\\t\\t\\t\\tthis.imageTracking = new XrImageTracking(this);\\n\\t\\t\\t\\tthis.planeDetection = new XrPlaneDetection(this);\\n\\t\\t\\t\\tthis.meshDetection = new XrMeshDetection(this);\\n\\t\\t\\t\\tthis.input = new XrInput(this);\\n\\t\\t\\t\\tthis.lightEstimation = new XrLightEstimation(this);\\n\\t\\t\\t\\tthis.anchors = new XrAnchors(this);\\n\\t\\t\\t\\tthis.views = new XrViews(this);\\n\\t\\t\\t\\tif (this._supported) {\\n\\t\\t\\t\\t\\t\\tnavigator.xr.addEventListener('devicechange', ()=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._deviceAvailabilityCheck();\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tthis._deviceAvailabilityCheck();\\n\\t\\t\\t\\t\\t\\tthis.app.graphicsDevice.on('devicelost', this._onDeviceLost, this);\\n\\t\\t\\t\\t\\t\\tthis.app.graphicsDevice.on('devicerestored', this._onDeviceRestored, this);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nXrManager.EVENT_AVAILABLE = 'available';\\nXrManager.EVENT_START = 'start';\\nXrManager.EVENT_END = 'end';\\nXrManager.EVENT_UPDATE = 'update';\\nXrManager.EVENT_ERROR = 'error';\\n\\nconst tempMeshInstances$1 = [];\\nconst lights = [\\n\\t\\t[],\\n\\t\\t[],\\n\\t\\t[]\\n];\\nconst defaultShadowAtlasParams = new Float32Array(2);\\nclass RenderPassPicker extends RenderPass {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.viewBindGroups.forEach((bg)=>{\\n\\t\\t\\t\\t\\t\\tbg.defaultUniformBuffer.destroy();\\n\\t\\t\\t\\t\\t\\tbg.destroy();\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.viewBindGroups.length = 0;\\n\\t\\t}\\n\\t\\tupdate(camera, scene, layers, mapping, depth) {\\n\\t\\t\\t\\tthis.camera = camera;\\n\\t\\t\\t\\tthis.scene = scene;\\n\\t\\t\\t\\tthis.layers = layers;\\n\\t\\t\\t\\tthis.mapping = mapping;\\n\\t\\t\\t\\tthis.depth = depth;\\n\\t\\t\\t\\tif (scene.clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\t\\tthis.emptyWorldClusters = this.renderer.worldClustersAllocator.empty;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\texecute() {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tconst { renderer, camera, scene, layers, mapping, renderTarget } = this;\\n\\t\\t\\t\\tconst srcLayers = scene.layers.layerList;\\n\\t\\t\\t\\tconst subLayerEnabled = scene.layers.subLayerEnabled;\\n\\t\\t\\t\\tconst isTransparent = scene.layers.subLayerList;\\n\\t\\t\\t\\tfor(let i = 0; i < srcLayers.length; i++){\\n\\t\\t\\t\\t\\t\\tconst srcLayer = srcLayers[i];\\n\\t\\t\\t\\t\\t\\tif (layers && layers.indexOf(srcLayer) < 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (srcLayer.enabled && subLayerEnabled[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (srcLayer.camerasSet.has(camera.camera)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst transparent = isTransparent[i];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (srcLayer._clearDepthBuffer) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trenderer.clear(camera.camera, false, true, false);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst meshInstances = srcLayer.meshInstances;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < meshInstances.length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst meshInstance = meshInstances[j];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (meshInstance.pick && meshInstance.transparent === transparent) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttempMeshInstances$1.push(meshInstance);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmapping.set(meshInstance.id, meshInstance);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (scene.gsplat.enableIds) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst placements = srcLayer.gsplatPlacements;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < placements.length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst placement = placements[j];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst component = placement.node?.gsplat;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (component) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmapping.set(placement.id, component);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (tempMeshInstances$1.length > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst clusteredLightingEnabled = scene.clusteredLightingEnabled;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (clusteredLightingEnabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst lightClusters = this.emptyWorldClusters;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlightClusters.activate();\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trenderer.setCameraUniforms(camera.camera, renderTarget);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trenderer.dispatchGlobalLights(scene);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.scope.resolve('shadowAtlasParams').setValue(defaultShadowAtlasParams);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (device.supportsUniformBuffers) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trenderer.initViewBindGroupFormat(clusteredLightingEnabled);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trenderer.setupViewUniformBuffers(this.viewBindGroups, renderer.viewUniformFormat, renderer.viewBindGroupFormat, null);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst shaderPass = this.depth ? SHADER_DEPTH_PICK : SHADER_PICK;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trenderer.renderForward(camera.camera, renderTarget, tempMeshInstances$1, lights, shaderPass, (meshInstance)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdevice.setBlendState(this.blendState);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttempMeshInstances$1.length = 0;\\n\\t\\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}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(device, renderer){\\n\\t\\t\\t\\tsuper(device), this.viewBindGroups = [], this.blendState = BlendState.NOBLEND;\\n\\t\\t\\t\\tthis.renderer = renderer;\\n\\t\\t}\\n}\\n\\nclass CpuTimer {\\n\\t\\tbegin(name) {\\n\\t\\t\\t\\tif (!this.enabled) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._frameIndex < this._frameTimings.length) {\\n\\t\\t\\t\\t\\t\\tthis._frameTimings.splice(this._frameIndex);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst tmp = this._prevTimings;\\n\\t\\t\\t\\tthis._prevTimings = this._timings;\\n\\t\\t\\t\\tthis._timings = this._frameTimings;\\n\\t\\t\\t\\tthis._frameTimings = tmp;\\n\\t\\t\\t\\tthis._frameIndex = 0;\\n\\t\\t\\t\\tthis.mark(name);\\n\\t\\t}\\n\\t\\tmark(name) {\\n\\t\\t\\t\\tif (!this.enabled) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst timestamp = now();\\n\\t\\t\\t\\tif (this._frameIndex > 0) {\\n\\t\\t\\t\\t\\t\\tconst prev = this._frameTimings[this._frameIndex - 1];\\n\\t\\t\\t\\t\\t\\tprev[1] = timestamp - prev[1];\\n\\t\\t\\t\\t} else if (this._timings.length > 0) {\\n\\t\\t\\t\\t\\t\\tconst prev = this._timings[this._timings.length - 1];\\n\\t\\t\\t\\t\\t\\tprev[1] = timestamp - prev[1];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._frameIndex >= this._frameTimings.length) {\\n\\t\\t\\t\\t\\t\\tthis._frameTimings.push([\\n\\t\\t\\t\\t\\t\\t\\t\\tname,\\n\\t\\t\\t\\t\\t\\t\\t\\ttimestamp\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tconst timing = this._frameTimings[this._frameIndex];\\n\\t\\t\\t\\t\\t\\ttiming[0] = name;\\n\\t\\t\\t\\t\\t\\ttiming[1] = timestamp;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._frameIndex++;\\n\\t\\t}\\n\\t\\tget timings() {\\n\\t\\t\\t\\treturn this._timings.slice(0, -1).map((v)=>v[1]);\\n\\t\\t}\\n\\t\\tconstructor(app){\\n\\t\\t\\t\\tthis._frameIndex = 0;\\n\\t\\t\\t\\tthis._frameTimings = [];\\n\\t\\t\\t\\tthis._timings = [];\\n\\t\\t\\t\\tthis._prevTimings = [];\\n\\t\\t\\t\\tthis.unitsName = 'ms';\\n\\t\\t\\t\\tthis.decimalPlaces = 1;\\n\\t\\t\\t\\tthis.enabled = true;\\n\\t\\t\\t\\tapp.on('frameupdate', this.begin.bind(this, 'update'));\\n\\t\\t\\t\\tapp.on('framerender', this.mark.bind(this, 'render'));\\n\\t\\t\\t\\tapp.on('frameend', this.mark.bind(this, 'other'));\\n\\t\\t}\\n}\\n\\nclass GpuTimer {\\n\\t\\tget timings() {\\n\\t\\t\\t\\tthis._timings[0] = this.device.gpuProfiler?._frameTime ?? 0;\\n\\t\\t\\t\\treturn this._timings;\\n\\t\\t}\\n\\t\\tconstructor(device){\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tif (device.gpuProfiler) {\\n\\t\\t\\t\\t\\t\\tdevice.gpuProfiler.enabled = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.enabled = true;\\n\\t\\t\\t\\tthis.unitsName = 'ms';\\n\\t\\t\\t\\tthis.decimalPlaces = 1;\\n\\t\\t\\t\\tthis._timings = [];\\n\\t\\t}\\n}\\n\\nclass StatsTimer {\\n\\t\\tget timings() {\\n\\t\\t\\t\\treturn this.values;\\n\\t\\t}\\n\\t\\tconstructor(app, statNames, decimalPlaces, unitsName, multiplier){\\n\\t\\t\\t\\tthis.app = app;\\n\\t\\t\\t\\tthis.values = [];\\n\\t\\t\\t\\tthis.statNames = statNames;\\n\\t\\t\\t\\tif (this.statNames.length > 3) {\\n\\t\\t\\t\\t\\t\\tthis.statNames.length = 3;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.unitsName = unitsName;\\n\\t\\t\\t\\tthis.decimalPlaces = decimalPlaces;\\n\\t\\t\\t\\tthis.multiplier = multiplier || 1;\\n\\t\\t\\t\\tconst resolve = (path, obj)=>{\\n\\t\\t\\t\\t\\t\\treturn path.split('.').reduce((prev, curr)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tif (!prev) return null;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (prev instanceof Map) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\treturn prev.get(curr);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\treturn prev[curr];\\n\\t\\t\\t\\t\\t\\t}, obj || this);\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tapp.on('frameupdate', (ms)=>{\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this.statNames.length; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst value = resolve(this.statNames[i], this.app.stats);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.values[i] = (value ?? 0) * this.multiplier;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t}\\n}\\n\\nclass Graph {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.app.off('frameupdate', this.update, this);\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tif (this.timer && typeof this.timer.loseContext === 'function') {\\n\\t\\t\\t\\t\\t\\tthis.timer.loseContext();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tupdate(ms) {\\n\\t\\t\\t\\tconst timings = this.timer.timings;\\n\\t\\t\\t\\tconst total = timings.reduce((a, v)=>a + v, 0);\\n\\t\\t\\t\\tthis.avgTotal += total;\\n\\t\\t\\t\\tthis.avgTimer += ms;\\n\\t\\t\\t\\tthis.avgCount++;\\n\\t\\t\\t\\tthis.maxValue = Math.max(this.maxValue, total);\\n\\t\\t\\t\\tif (this.avgTimer > this.textRefreshRate) {\\n\\t\\t\\t\\t\\t\\tthis.timingText = (this.avgTotal / this.avgCount).toFixed(this.timer.decimalPlaces);\\n\\t\\t\\t\\t\\t\\tthis.maxText = this.maxValue.toFixed(this.timer.decimalPlaces);\\n\\t\\t\\t\\t\\t\\tthis.avgTimer = 0;\\n\\t\\t\\t\\t\\t\\tthis.avgTotal = 0;\\n\\t\\t\\t\\t\\t\\tthis.avgCount = 0;\\n\\t\\t\\t\\t\\t\\tthis.maxValue = 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.enabled) {\\n\\t\\t\\t\\t\\t\\tlet value = 0;\\n\\t\\t\\t\\t\\t\\tconst range = 1.5 * this.watermark;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < timings.length; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tvalue += Math.floor(timings[i] / range * 255);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.sample[i] = value;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.sample[3] = this.watermark / range * 255;\\n\\t\\t\\t\\t\\t\\tif (this.yOffset >= this.texture.height) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst data = this.texture.lock();\\n\\t\\t\\t\\t\\t\\tif (this.needsClear) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst rowOffset = this.yOffset * this.texture.width * 4;\\n\\t\\t\\t\\t\\t\\t\\t\\tdata.fill(0, rowOffset, rowOffset + this.texture.width * 4);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.needsClear = false;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tdata.set(this.sample, (this.cursor + this.yOffset * this.texture.width) * 4);\\n\\t\\t\\t\\t\\t\\tthis.texture.unlock();\\n\\t\\t\\t\\t\\t\\tthis.cursor++;\\n\\t\\t\\t\\t\\t\\tif (this.cursor === this.texture.width) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.cursor = 0;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\trender(render2d, x, y, w, h) {\\n\\t\\t\\t\\trender2d.quad(x + w, y, -w, h, this.enabled ? this.cursor : 0, this.enabled ? 0.5 + this.yOffset : this.texture.height - 1, -w, 0, this.texture, this.graphType);\\n\\t\\t}\\n\\t\\tconstructor(name, app, watermark, textRefreshRate, timer){\\n\\t\\t\\t\\tthis.app = app;\\n\\t\\t\\t\\tthis.name = name;\\n\\t\\t\\t\\tthis.device = app.graphicsDevice;\\n\\t\\t\\t\\tthis.timer = timer;\\n\\t\\t\\t\\tthis.watermark = watermark;\\n\\t\\t\\t\\tthis.enabled = false;\\n\\t\\t\\t\\tthis.textRefreshRate = textRefreshRate;\\n\\t\\t\\t\\tthis.avgTotal = 0;\\n\\t\\t\\t\\tthis.avgTimer = 0;\\n\\t\\t\\t\\tthis.avgCount = 0;\\n\\t\\t\\t\\tthis.maxValue = 0;\\n\\t\\t\\t\\tthis.timingText = '';\\n\\t\\t\\t\\tthis.maxText = '';\\n\\t\\t\\t\\tthis.texture = null;\\n\\t\\t\\t\\tthis.yOffset = 0;\\n\\t\\t\\t\\tthis.graphType = 0.0;\\n\\t\\t\\t\\tthis.cursor = 0;\\n\\t\\t\\t\\tthis.sample = new Uint8ClampedArray(4);\\n\\t\\t\\t\\tthis.sample.set([\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t255\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tthis.needsClear = false;\\n\\t\\t\\t\\tthis.counter = 0;\\n\\t\\t\\t\\tthis.app.on('frameupdate', this.update, this);\\n\\t\\t}\\n}\\n\\nclass WordAtlas {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.texture.destroy();\\n\\t\\t\\t\\tthis.texture = null;\\n\\t\\t}\\n\\t\\trender(render2d, word, x, y) {\\n\\t\\t\\t\\tconst p = this.placements.get(word);\\n\\t\\t\\t\\tif (p) {\\n\\t\\t\\t\\t\\t\\tconst padding = 1;\\n\\t\\t\\t\\t\\t\\trender2d.quad(x + p.l - padding, y - p.d + padding, p.w + padding * 2, p.h + padding * 2, p.x - padding, this.texture.height - p.y - p.h - padding, undefined, undefined, this.texture, 1);\\n\\t\\t\\t\\t\\t\\treturn p.w;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tlet totalWidth = 0;\\n\\t\\t\\t\\tfor(let i = 0; i < word.length; i++){\\n\\t\\t\\t\\t\\t\\tconst char = word[i];\\n\\t\\t\\t\\t\\t\\tif (char === ' ') {\\n\\t\\t\\t\\t\\t\\t\\t\\ttotalWidth += 5;\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst charPlacement = this.placements.get(char);\\n\\t\\t\\t\\t\\t\\tif (charPlacement) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst padding = 1;\\n\\t\\t\\t\\t\\t\\t\\t\\trender2d.quad(x + totalWidth + charPlacement.l - padding, y - charPlacement.d + padding, charPlacement.w + padding * 2, charPlacement.h + padding * 2, charPlacement.x - padding, this.texture.height - charPlacement.y - charPlacement.h - padding, undefined, undefined, this.texture, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\ttotalWidth += charPlacement.w;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn totalWidth;\\n\\t\\t}\\n\\t\\tconstructor(device, words){\\n\\t\\t\\t\\tconst initContext = (context)=>{\\n\\t\\t\\t\\t\\t\\tcontext.font = '10px \\\"Lucida Console\\\", Monaco, monospace';\\n\\t\\t\\t\\t\\t\\tcontext.textAlign = 'left';\\n\\t\\t\\t\\t\\t\\tcontext.textBaseline = 'alphabetic';\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst isNumber = (word)=>{\\n\\t\\t\\t\\t\\t\\treturn word === '.' || word.length === 1 && word.charCodeAt(0) >= 48 && word.charCodeAt(0) <= 57;\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tconst canvas = document.createElement('canvas');\\n\\t\\t\\t\\tconst context = canvas.getContext('2d', {\\n\\t\\t\\t\\t\\t\\talpha: true\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tinitContext(context);\\n\\t\\t\\t\\tconst placements = new Map();\\n\\t\\t\\t\\tconst padding = 5;\\n\\t\\t\\t\\tconst width = 512;\\n\\t\\t\\t\\tlet x = padding;\\n\\t\\t\\t\\tlet y = padding;\\n\\t\\t\\t\\twords.forEach((word)=>{\\n\\t\\t\\t\\t\\t\\tconst measurement = context.measureText(word);\\n\\t\\t\\t\\t\\t\\tconst l = Math.ceil(-measurement.actualBoundingBoxLeft);\\n\\t\\t\\t\\t\\t\\tconst r = Math.ceil(measurement.actualBoundingBoxRight);\\n\\t\\t\\t\\t\\t\\tconst a = Math.ceil(measurement.actualBoundingBoxAscent);\\n\\t\\t\\t\\t\\t\\tconst d = Math.ceil(measurement.actualBoundingBoxDescent);\\n\\t\\t\\t\\t\\t\\tconst w = l + r;\\n\\t\\t\\t\\t\\t\\tconst h = a + d;\\n\\t\\t\\t\\t\\t\\tif (x + w + padding >= width) {\\n\\t\\t\\t\\t\\t\\t\\t\\tx = padding;\\n\\t\\t\\t\\t\\t\\t\\t\\ty += 16;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tplacements.set(word, {\\n\\t\\t\\t\\t\\t\\t\\t\\tl,\\n\\t\\t\\t\\t\\t\\t\\t\\tr,\\n\\t\\t\\t\\t\\t\\t\\t\\ta,\\n\\t\\t\\t\\t\\t\\t\\t\\td,\\n\\t\\t\\t\\t\\t\\t\\t\\tw,\\n\\t\\t\\t\\t\\t\\t\\t\\th,\\n\\t\\t\\t\\t\\t\\t\\t\\tx: x,\\n\\t\\t\\t\\t\\t\\t\\t\\ty: y\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tx += w + padding;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tcanvas.width = 512;\\n\\t\\t\\t\\tcanvas.height = math.nextPowerOfTwo(y + 16 + padding);\\n\\t\\t\\t\\tinitContext(context);\\n\\t\\t\\t\\tcontext.fillStyle = 'rgb(0, 0, 0)';\\n\\t\\t\\t\\tcontext.fillRect(0, 0, canvas.width, canvas.height);\\n\\t\\t\\t\\tplacements.forEach((m, word)=>{\\n\\t\\t\\t\\t\\t\\tcontext.fillStyle = isNumber(word) ? 'rgb(255, 240, 100)' : 'rgb(150, 220, 230)';\\n\\t\\t\\t\\t\\t\\tcontext.fillText(word, m.x - m.l, m.y + m.a);\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.placements = placements;\\n\\t\\t\\t\\tconst data = context.getImageData(0, 0, canvas.width, canvas.height).data;\\n\\t\\t\\t\\tfor(let i = 0; i < data.length; i += 4){\\n\\t\\t\\t\\t\\t\\tconst maxChannel = Math.max(data[i + 0], data[i + 1], data[i + 2]);\\n\\t\\t\\t\\t\\t\\tdata[i + 3] = Math.min(maxChannel * 2, 255);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.texture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: 'mini-stats-word-atlas',\\n\\t\\t\\t\\t\\t\\twidth: canvas.width,\\n\\t\\t\\t\\t\\t\\theight: canvas.height,\\n\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\tlevels: [\\n\\t\\t\\t\\t\\t\\t\\t\\tdata\\n\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t});\\n\\t\\t}\\n}\\n\\nconst graphColorRed = '1.0, 0.412, 0.380';\\nconst graphColorGreen = '0.467, 0.867, 0.467';\\nconst graphColorBlue = '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\\tvec4 graphSample = texture2D(graphTex, uv0.xy);\\n\\t\\tvec4 graph;\\n\\t\\tif (uv0.w < graphSample.r)\\n\\t\\t\\tgraph = vec4(${graphColorRed}, 1.0);\\n\\t\\telse if (uv0.w < graphSample.g)\\n\\t\\t\\tgraph = vec4(${graphColorGreen}, 1.0);\\n\\t\\telse if (uv0.w < graphSample.b)\\n\\t\\t\\tgraph = vec4(${graphColorBlue}, 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 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(${graphColorRed}, 1.0);\\n\\t\\t} else if (uv0.w < graphSample.g) {\\n\\t\\t\\tgraph = vec4f(${graphColorGreen}, 1.0);\\n\\t\\t} else if (uv0.w < graphSample.b) {\\n\\t\\t\\tgraph = vec4f(${graphColorBlue}, 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\\t\\tquad(x, y, w, h, u, v, uw, uh, texture, wordFlag = 0) {\\n\\t\\t\\t\\tif (this.quads >= this.maxQuads) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst rw = this.targetSize.width;\\n\\t\\t\\t\\tconst rh = this.targetSize.height;\\n\\t\\t\\t\\tconst x0 = x / rw;\\n\\t\\t\\t\\tconst y0 = y / rh;\\n\\t\\t\\t\\tconst x1 = (x + w) / rw;\\n\\t\\t\\t\\tconst y1 = (y + h) / rh;\\n\\t\\t\\t\\tconst tw = texture.width;\\n\\t\\t\\t\\tconst th = texture.height;\\n\\t\\t\\t\\tconst u0 = u / tw;\\n\\t\\t\\t\\tconst v0 = v / th;\\n\\t\\t\\t\\tconst u1 = (u + (uw ?? w)) / tw;\\n\\t\\t\\t\\tconst v1 = (v + (uh ?? h)) / th;\\n\\t\\t\\t\\tthis.data.set([\\n\\t\\t\\t\\t\\t\\tx0,\\n\\t\\t\\t\\t\\t\\ty0,\\n\\t\\t\\t\\t\\t\\twordFlag,\\n\\t\\t\\t\\t\\t\\tu0,\\n\\t\\t\\t\\t\\t\\tv0,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\tx1,\\n\\t\\t\\t\\t\\t\\ty0,\\n\\t\\t\\t\\t\\t\\twordFlag,\\n\\t\\t\\t\\t\\t\\tu1,\\n\\t\\t\\t\\t\\t\\tv0,\\n\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\tx1,\\n\\t\\t\\t\\t\\t\\ty1,\\n\\t\\t\\t\\t\\t\\twordFlag,\\n\\t\\t\\t\\t\\t\\tu1,\\n\\t\\t\\t\\t\\t\\tv1,\\n\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\tx0,\\n\\t\\t\\t\\t\\t\\ty1,\\n\\t\\t\\t\\t\\t\\twordFlag,\\n\\t\\t\\t\\t\\t\\tu0,\\n\\t\\t\\t\\t\\t\\tv1,\\n\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t1\\n\\t\\t\\t\\t], 4 * 7 * this.quads);\\n\\t\\t\\t\\tthis.quads++;\\n\\t\\t\\t\\tthis.prim.count += 6;\\n\\t\\t}\\n\\t\\tstartFrame() {\\n\\t\\t\\t\\tthis.quads = 0;\\n\\t\\t\\t\\tthis.prim.count = 0;\\n\\t\\t\\t\\tthis.targetSize.width = this.device.canvas.scrollWidth;\\n\\t\\t\\t\\tthis.targetSize.height = this.device.canvas.scrollHeight;\\n\\t\\t}\\n\\t\\trender(app, layer, graphTexture, wordsTexture, clr, height) {\\n\\t\\t\\t\\tthis.buffer.setData(this.data.buffer);\\n\\t\\t\\t\\tthis.uniforms.clr.set(clr, 0);\\n\\t\\t\\t\\tthis.material.setParameter('clr', this.uniforms.clr);\\n\\t\\t\\t\\tthis.material.setParameter('graphTex', graphTexture);\\n\\t\\t\\t\\tthis.material.setParameter('wordsTex', wordsTexture);\\n\\t\\t\\t\\tapp.drawMeshInstance(this.meshInstance, layer);\\n\\t\\t}\\n\\t\\tconstructor(device, maxQuads = 2048){\\n\\t\\t\\t\\tconst format = new VertexFormat(device, [\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tsemantic: SEMANTIC_POSITION,\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponents: 3,\\n\\t\\t\\t\\t\\t\\t\\t\\ttype: TYPE_FLOAT32\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\tsemantic: SEMANTIC_TEXCOORD0,\\n\\t\\t\\t\\t\\t\\t\\t\\tcomponents: 4,\\n\\t\\t\\t\\t\\t\\t\\t\\ttype: TYPE_FLOAT32\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tconst indices = new Uint16Array(maxQuads * 6);\\n\\t\\t\\t\\tfor(let i = 0; i < maxQuads; ++i){\\n\\t\\t\\t\\t\\t\\tindices[i * 6 + 0] = i * 4;\\n\\t\\t\\t\\t\\t\\tindices[i * 6 + 1] = i * 4 + 1;\\n\\t\\t\\t\\t\\t\\tindices[i * 6 + 2] = i * 4 + 2;\\n\\t\\t\\t\\t\\t\\tindices[i * 6 + 3] = i * 4;\\n\\t\\t\\t\\t\\t\\tindices[i * 6 + 4] = i * 4 + 2;\\n\\t\\t\\t\\t\\t\\tindices[i * 6 + 5] = i * 4 + 3;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.maxQuads = maxQuads;\\n\\t\\t\\t\\tthis.buffer = new VertexBuffer(device, format, maxQuads * 4, {\\n\\t\\t\\t\\t\\t\\tusage: BUFFER_STREAM\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.data = new Float32Array(this.buffer.numBytes / 4);\\n\\t\\t\\t\\tthis.indexBuffer = new IndexBuffer(device, INDEXFORMAT_UINT16, maxQuads * 6, BUFFER_STATIC, indices);\\n\\t\\t\\t\\tthis.prim = {\\n\\t\\t\\t\\t\\t\\ttype: PRIMITIVE_TRIANGLES,\\n\\t\\t\\t\\t\\t\\tindexed: true,\\n\\t\\t\\t\\t\\t\\tbase: 0,\\n\\t\\t\\t\\t\\t\\tbaseVertex: 0,\\n\\t\\t\\t\\t\\t\\tcount: 0\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.quads = 0;\\n\\t\\t\\t\\tthis.mesh = new Mesh(device);\\n\\t\\t\\t\\tthis.mesh.vertexBuffer = this.buffer;\\n\\t\\t\\t\\tthis.mesh.indexBuffer[0] = this.indexBuffer;\\n\\t\\t\\t\\tthis.mesh.primitive = [\\n\\t\\t\\t\\t\\t\\tthis.prim\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tconst material = new ShaderMaterial({\\n\\t\\t\\t\\t\\t\\tuniqueName: 'MiniStats',\\n\\t\\t\\t\\t\\t\\tvertexGLSL: vertexShaderGLSL,\\n\\t\\t\\t\\t\\t\\tfragmentGLSL: fragmentShaderGLSL,\\n\\t\\t\\t\\t\\t\\tvertexWGSL: vertexShaderWGSL,\\n\\t\\t\\t\\t\\t\\tfragmentWGSL: fragmentShaderWGSL,\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\tvertex_position: SEMANTIC_POSITION,\\n\\t\\t\\t\\t\\t\\t\\t\\tvertex_texCoord0: SEMANTIC_TEXCOORD0\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.material = material;\\n\\t\\t\\t\\tmaterial.cull = CULLFACE_NONE;\\n\\t\\t\\t\\tmaterial.depthState = DepthState.NODEPTH;\\n\\t\\t\\t\\tmaterial.blendState = new BlendState(true, BLENDEQUATION_ADD, BLENDMODE_SRC_ALPHA, BLENDMODE_ONE_MINUS_SRC_ALPHA, BLENDEQUATION_ADD, BLENDMODE_ONE, BLENDMODE_ONE);\\n\\t\\t\\t\\tmaterial.update();\\n\\t\\t\\t\\tthis.meshInstance = new MeshInstance(this.mesh, material, new GraphNode('MiniStatsMesh'));\\n\\t\\t\\t\\tthis.uniforms = {\\n\\t\\t\\t\\t\\t\\tclr: new Float32Array(4)\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.targetSize = {\\n\\t\\t\\t\\t\\t\\twidth: device.width,\\n\\t\\t\\t\\t\\t\\theight: device.height\\n\\t\\t\\t\\t};\\n\\t\\t}\\n}\\n\\nconst cpuStatDisplayNames = {\\n\\t\\tanimUpdate: 'anim',\\n\\t\\tphysicsTime: 'physics',\\n\\t\\trenderTime: 'render',\\n\\t\\tgsplatSort: 'gsplatSort'\\n};\\nconst delayedStartStats = new Set([\\n\\t\\t'physicsTime',\\n\\t\\t'animUpdate',\\n\\t\\t'gsplatSort'\\n]);\\nclass MiniStats {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.device.off('resizecanvas', this.updateDiv, this);\\n\\t\\t\\t\\tthis.device.off('losecontext', this.loseContext, this);\\n\\t\\t\\t\\tthis.app.off('postrender', this.postRender, this);\\n\\t\\t\\t\\tthis.graphs.forEach((graph)=>graph.destroy());\\n\\t\\t\\t\\tthis.gpuPassGraphs.clear();\\n\\t\\t\\t\\tthis.wordAtlas.destroy();\\n\\t\\t\\t\\tthis.texture.destroy();\\n\\t\\t\\t\\tthis.div.remove();\\n\\t\\t}\\n\\t\\tstatic getDefaultOptions() {\\n\\t\\t\\t\\treturn {\\n\\t\\t\\t\\t\\t\\tsizes: [\\n\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twidth: 100,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\theight: 16,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tspacing: 0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgraphs: false\\n\\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\\t\\t\\twidth: 128,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\theight: 32,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tspacing: 2,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgraphs: true\\n\\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\\t\\t\\twidth: 256,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\theight: 64,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tspacing: 2,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgraphs: true\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\tstartSizeIndex: 0,\\n\\t\\t\\t\\t\\t\\ttextRefreshRate: 500,\\n\\t\\t\\t\\t\\t\\tcpu: {\\n\\t\\t\\t\\t\\t\\t\\t\\tenabled: true,\\n\\t\\t\\t\\t\\t\\t\\t\\twatermark: 33\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tgpu: {\\n\\t\\t\\t\\t\\t\\t\\t\\tenabled: true,\\n\\t\\t\\t\\t\\t\\t\\t\\twatermark: 33\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tstats: [\\n\\t\\t\\t\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tname: 'Frame',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstats: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t'frame.ms'\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdecimalPlaces: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tunitsName: 'ms',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twatermark: 33\\n\\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\\t\\t\\tname: 'DrawCalls',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstats: [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t'drawCalls.total'\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\twatermark: 1000\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\tgpuTimingMinSize: 1,\\n\\t\\t\\t\\t\\t\\tcpuTimingMinSize: 1\\n\\t\\t\\t\\t};\\n\\t\\t}\\n\\t\\tset activeSizeIndex(value) {\\n\\t\\t\\t\\tthis._activeSizeIndex = value;\\n\\t\\t\\t\\tthis.gspacing = this.sizes[value].spacing;\\n\\t\\t\\t\\tthis.resize(this.sizes[value].width, this.sizes[value].height, this.sizes[value].graphs);\\n\\t\\t\\t\\tthis.opacity = value > 0 ? 0.85 : 0.7;\\n\\t\\t\\t\\tif (value < this.gpuTimingMinSize && this.gpuPassGraphs) {\\n\\t\\t\\t\\t\\t\\tfor (const passData of this.gpuPassGraphs.values()){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst index = this.graphs.indexOf(passData.graph);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (index !== -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.graphs.splice(index, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.freeRow(passData.graph);\\n\\t\\t\\t\\t\\t\\t\\t\\tpassData.graph.destroy();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.gpuPassGraphs.clear();\\n\\t\\t\\t\\t\\t\\tconst gpuGraph = this.graphs.find((g)=>g.name === 'GPU');\\n\\t\\t\\t\\t\\t\\tif (gpuGraph) gpuGraph.graphType = 0.0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (value < this.cpuTimingMinSize && this.cpuGraphs) {\\n\\t\\t\\t\\t\\t\\tfor (const statData of this.cpuGraphs.values()){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst index = this.graphs.indexOf(statData.graph);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (index !== -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.graphs.splice(index, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.freeRow(statData.graph);\\n\\t\\t\\t\\t\\t\\t\\t\\tstatData.graph.destroy();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.cpuGraphs.clear();\\n\\t\\t\\t\\t\\t\\tconst cpuGraph = this.graphs.find((g)=>g.name === 'CPU');\\n\\t\\t\\t\\t\\t\\tif (cpuGraph) cpuGraph.graphType = 0.0;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget activeSizeIndex() {\\n\\t\\t\\t\\treturn this._activeSizeIndex;\\n\\t\\t}\\n\\t\\tset opacity(value) {\\n\\t\\t\\t\\tthis.clr[3] = value;\\n\\t\\t}\\n\\t\\tget opacity() {\\n\\t\\t\\t\\treturn this.clr[3];\\n\\t\\t}\\n\\t\\tget overallHeight() {\\n\\t\\t\\t\\tconst graphs = this.graphs;\\n\\t\\t\\t\\tconst spacing = this.gspacing;\\n\\t\\t\\t\\treturn this.height * graphs.length + spacing * (graphs.length - 1);\\n\\t\\t}\\n\\t\\tset enabled(value) {\\n\\t\\t\\t\\tif (value !== this._enabled) {\\n\\t\\t\\t\\t\\t\\tthis._enabled = value;\\n\\t\\t\\t\\t\\t\\tfor(let i = 0; i < this.graphs.length; ++i){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.graphs[i].enabled = value;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.graphs[i].timer.enabled = value;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget enabled() {\\n\\t\\t\\t\\treturn this._enabled;\\n\\t\\t}\\n\\t\\tinitGraphs(app, device, options) {\\n\\t\\t\\t\\tthis.graphs = [];\\n\\t\\t\\t\\tif (options.cpu.enabled) {\\n\\t\\t\\t\\t\\t\\tconst timer = new CpuTimer(app);\\n\\t\\t\\t\\t\\t\\tconst graph = new Graph('CPU', app, options.cpu.watermark, options.textRefreshRate, timer);\\n\\t\\t\\t\\t\\t\\tthis.graphs.push(graph);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.gpu.enabled) {\\n\\t\\t\\t\\t\\t\\tconst timer = new GpuTimer(device);\\n\\t\\t\\t\\t\\t\\tconst graph = new Graph('GPU', app, options.gpu.watermark, options.textRefreshRate, timer);\\n\\t\\t\\t\\t\\t\\tthis.graphs.push(graph);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.stats) {\\n\\t\\t\\t\\t\\t\\toptions.stats.forEach((entry)=>{\\n\\t\\t\\t\\t\\t\\t\\t\\tconst timer = new StatsTimer(app, entry.stats, entry.decimalPlaces, entry.unitsName, entry.multiplier);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst graph = new Graph(entry.name, app, entry.watermark, options.textRefreshRate, timer);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.graphs.push(graph);\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.texture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: 'mini-stats-graph-texture',\\n\\t\\t\\t\\t\\t\\twidth: 1,\\n\\t\\t\\t\\t\\t\\theight: 1,\\n\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_REPEAT,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_REPEAT\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.graphs.forEach((graph)=>{\\n\\t\\t\\t\\t\\t\\tgraph.texture = this.texture;\\n\\t\\t\\t\\t\\t\\tthis.allocateRow(graph);\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\trender() {\\n\\t\\t\\t\\tconst graphs = this.graphs;\\n\\t\\t\\t\\tconst wordAtlas = this.wordAtlas;\\n\\t\\t\\t\\tconst render2d = this.render2d;\\n\\t\\t\\t\\tconst width = this.width;\\n\\t\\t\\t\\tconst height = this.height;\\n\\t\\t\\t\\tconst gspacing = this.gspacing;\\n\\t\\t\\t\\trender2d.startFrame();\\n\\t\\t\\t\\tfor(let i = 0; i < graphs.length; ++i){\\n\\t\\t\\t\\t\\t\\tconst graph = graphs[i];\\n\\t\\t\\t\\t\\t\\tlet y = i * (height + gspacing);\\n\\t\\t\\t\\t\\t\\tgraph.render(render2d, 0, y, width, height);\\n\\t\\t\\t\\t\\t\\tlet x = 1;\\n\\t\\t\\t\\t\\t\\ty += height - 13;\\n\\t\\t\\t\\t\\t\\tx += wordAtlas.render(render2d, graph.name, x, y) + 10;\\n\\t\\t\\t\\t\\t\\tconst timingText = graph.timingText;\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j < timingText.length; ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\tx += wordAtlas.render(render2d, timingText[j], x, y);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (graph.maxText && this._activeSizeIndex > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tx += 5;\\n\\t\\t\\t\\t\\t\\t\\t\\tx += wordAtlas.render(render2d, 'max', x, y);\\n\\t\\t\\t\\t\\t\\t\\t\\tx += 5;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst maxText = graph.maxText;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < maxText.length; ++j){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tx += wordAtlas.render(render2d, maxText[j], x, y);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (graph.timer.unitsName) {\\n\\t\\t\\t\\t\\t\\t\\t\\tx += wordAtlas.render(render2d, graph.timer.unitsName, x, y);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\trender2d.render(this.app, this.drawLayer, this.texture, this.wordAtlas.texture, this.clr, height);\\n\\t\\t}\\n\\t\\tresize(width, height, showGraphs) {\\n\\t\\t\\t\\tconst graphs = this.graphs;\\n\\t\\t\\t\\tfor(let i = 0; i < graphs.length; ++i){\\n\\t\\t\\t\\t\\t\\tgraphs[i].enabled = showGraphs;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.width = width;\\n\\t\\t\\t\\tthis.height = height;\\n\\t\\t\\t\\tthis.updateDiv();\\n\\t\\t}\\n\\t\\tupdateDiv() {\\n\\t\\t\\t\\tconst rect = this.device.canvas.getBoundingClientRect();\\n\\t\\t\\t\\tthis.div.style.left = `${rect.left}px`;\\n\\t\\t\\t\\tthis.div.style.bottom = `${window.innerHeight - rect.bottom}px`;\\n\\t\\t\\t\\tthis.div.style.width = `${this.width}px`;\\n\\t\\t\\t\\tthis.div.style.height = `${this.overallHeight}px`;\\n\\t\\t}\\n\\t\\tloseContext() {\\n\\t\\t\\t\\tthis.graphs.forEach((graph)=>graph.loseContext());\\n\\t\\t}\\n\\t\\tupdateSubStats(subGraphs, mainGraphName, stats, statPathPrefix, removeAfterFrames) {\\n\\t\\t\\t\\tconst passesToRemove = [];\\n\\t\\t\\t\\tfor (const [statName, statData] of subGraphs){\\n\\t\\t\\t\\t\\t\\tconst timing = stats instanceof Map ? stats.get(statName) || 0 : stats[statName] || 0;\\n\\t\\t\\t\\t\\t\\tif (timing > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tstatData.lastNonZeroFrame = this.frameIndex;\\n\\t\\t\\t\\t\\t\\t} else if (removeAfterFrames > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst shouldAutoHide = statPathPrefix === 'gpu';\\n\\t\\t\\t\\t\\t\\t\\t\\tif (shouldAutoHide && this.frameIndex - statData.lastNonZeroFrame > removeAfterFrames) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tpassesToRemove.push(statName);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor (const statName of passesToRemove){\\n\\t\\t\\t\\t\\t\\tconst statData = subGraphs.get(statName);\\n\\t\\t\\t\\t\\t\\tif (statData) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst index = this.graphs.indexOf(statData.graph);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (index !== -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.graphs.splice(index, 1);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.freeRow(statData.graph);\\n\\t\\t\\t\\t\\t\\t\\t\\tstatData.graph.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\tsubGraphs.delete(statName);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst statsEntries = stats instanceof Map ? stats : Object.entries(stats);\\n\\t\\t\\t\\tfor (const [statName, timing] of statsEntries){\\n\\t\\t\\t\\t\\t\\tif (!subGraphs.has(statName)) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst isDelayedStart = statPathPrefix === 'gpu' || delayedStartStats.has(statName);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (isDelayedStart && timing === 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tlet displayName = statName;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (statPathPrefix === 'frame') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tdisplayName = cpuStatDisplayNames[statName] || statName;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tconst graphName = `  ${displayName}`;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst watermark = 10.0;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst statPath = `${statPathPrefix}.${statName}`;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst timer = new StatsTimer(this.app, [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tstatPath\\n\\t\\t\\t\\t\\t\\t\\t\\t], 1, 'ms', 1);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst graph = new Graph(graphName, this.app, watermark, this.textRefreshRate, timer);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (statPathPrefix === 'gpu') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgraph.graphType = 0.33;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else if (statPathPrefix === 'frame') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgraph.graphType = 0.66;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tgraph.texture = this.texture;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.allocateRow(graph);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst currentSize = this.sizes[this._activeSizeIndex];\\n\\t\\t\\t\\t\\t\\t\\t\\tgraph.enabled = currentSize.graphs;\\n\\t\\t\\t\\t\\t\\t\\t\\tlet mainGraphIndex = this.graphs.findIndex((g)=>g.name === mainGraphName);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (mainGraphIndex === -1) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmainGraphIndex = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\tlet insertIndex = mainGraphIndex;\\n\\t\\t\\t\\t\\t\\t\\t\\tfor(let i = mainGraphIndex - 1; i >= 0; i--){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (this.graphs[i].name.startsWith(' ')) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tinsertIndex = i;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\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\\tthis.graphs.splice(insertIndex, 0, graph);\\n\\t\\t\\t\\t\\t\\t\\t\\tsubGraphs.set(statName, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgraph: graph,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tlastNonZeroFrame: timing > 0 ? this.frameIndex : this.frameIndex - removeAfterFrames - 1\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst mainGraph = this.graphs.find((g)=>g.name === mainGraphName);\\n\\t\\t\\t\\tif (mainGraph) {\\n\\t\\t\\t\\t\\t\\tfor (const statData of subGraphs.values()){\\n\\t\\t\\t\\t\\t\\t\\t\\tstatData.graph.watermark = mainGraph.watermark;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (subGraphs.size > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (statPathPrefix === 'gpu') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmainGraph.graphType = 0.33;\\n\\t\\t\\t\\t\\t\\t\\t\\t} else if (statPathPrefix === 'frame') {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmainGraph.graphType = 0.66;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tmainGraph.graphType = 0.0;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tallocateRow(graph) {\\n\\t\\t\\t\\tlet row;\\n\\t\\t\\t\\tif (this.freeRows.length > 0) {\\n\\t\\t\\t\\t\\t\\trow = this.freeRows.pop();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\trow = this.nextRowIndex++;\\n\\t\\t\\t\\t\\t\\tthis.ensureTextureHeight(this.nextRowIndex);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.graphRows.set(graph, row);\\n\\t\\t\\t\\tgraph.yOffset = row;\\n\\t\\t\\t\\tgraph.needsClear = true;\\n\\t\\t\\t\\treturn row;\\n\\t\\t}\\n\\t\\tfreeRow(graph) {\\n\\t\\t\\t\\tconst row = this.graphRows.get(graph);\\n\\t\\t\\t\\tif (row !== undefined) {\\n\\t\\t\\t\\t\\t\\tthis.freeRows.push(row);\\n\\t\\t\\t\\t\\t\\tthis.graphRows.delete(graph);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tensureTextureHeight(requiredRows) {\\n\\t\\t\\t\\tconst maxWidth = this.sizes[this.sizes.length - 1].width;\\n\\t\\t\\t\\tconst requiredWidth = math.nextPowerOfTwo(maxWidth);\\n\\t\\t\\t\\tconst requiredHeight = math.nextPowerOfTwo(requiredRows);\\n\\t\\t\\t\\tif (requiredHeight > this.texture.height) {\\n\\t\\t\\t\\t\\t\\tthis.texture.resize(requiredWidth, requiredHeight);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tpostRender() {\\n\\t\\t\\t\\tif (this._enabled) {\\n\\t\\t\\t\\t\\t\\tthis.render();\\n\\t\\t\\t\\t\\t\\tif (this._activeSizeIndex >= this.gpuTimingMinSize) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst gpuStats = this.app.stats.gpu;\\n\\t\\t\\t\\t\\t\\t\\t\\tif (gpuStats) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.updateSubStats(this.gpuPassGraphs, 'GPU', gpuStats, 'gpu', 240);\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this._activeSizeIndex >= this.cpuTimingMinSize) {\\n\\t\\t\\t\\t\\t\\t\\t\\tconst cpuStats = {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscriptUpdate: this.app.stats.frame.scriptUpdate,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tscriptPostUpdate: this.app.stats.frame.scriptPostUpdate,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tanimUpdate: this.app.stats.frame.animUpdate,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tphysicsTime: this.app.stats.frame.physicsTime,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trenderTime: this.app.stats.frame.renderTime,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tgsplatSort: this.app.stats.frame.gsplatSort\\n\\t\\t\\t\\t\\t\\t\\t\\t};\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.updateSubStats(this.cpuGraphs, 'CPU', cpuStats, 'frame', 240);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.frameIndex++;\\n\\t\\t}\\n\\t\\tconstructor(app, options = MiniStats.getDefaultOptions()){\\n\\t\\t\\t\\tconst device = app.graphicsDevice;\\n\\t\\t\\t\\tthis.graphRows = new Map();\\n\\t\\t\\t\\tthis.freeRows = [];\\n\\t\\t\\t\\tthis.nextRowIndex = 0;\\n\\t\\t\\t\\tthis.sizes = options.sizes;\\n\\t\\t\\t\\tthis.initGraphs(app, device, options);\\n\\t\\t\\t\\tconst words = new Set([\\n\\t\\t\\t\\t\\t\\t'',\\n\\t\\t\\t\\t\\t\\t'ms',\\n\\t\\t\\t\\t\\t\\t'0',\\n\\t\\t\\t\\t\\t\\t'1',\\n\\t\\t\\t\\t\\t\\t'2',\\n\\t\\t\\t\\t\\t\\t'3',\\n\\t\\t\\t\\t\\t\\t'4',\\n\\t\\t\\t\\t\\t\\t'5',\\n\\t\\t\\t\\t\\t\\t'6',\\n\\t\\t\\t\\t\\t\\t'7',\\n\\t\\t\\t\\t\\t\\t'8',\\n\\t\\t\\t\\t\\t\\t'9',\\n\\t\\t\\t\\t\\t\\t'.',\\n\\t\\t\\t\\t\\t\\t'-',\\n\\t\\t\\t\\t\\t\\t' '\\n\\t\\t\\t\\t].concat(this.graphs.map((graph)=>graph.name)).concat(options.stats ? options.stats.map((stat)=>stat.unitsName) : []).filter((item)=>!!item));\\n\\t\\t\\t\\tfor(let i = 97; i <= 122; i++){\\n\\t\\t\\t\\t\\t\\twords.add(String.fromCharCode(i));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 65; i <= 90; i++){\\n\\t\\t\\t\\t\\t\\twords.add(String.fromCharCode(i));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.wordAtlas = new WordAtlas(device, words);\\n\\t\\t\\t\\tthis._activeSizeIndex = options.startSizeIndex;\\n\\t\\t\\t\\tconst gpuTimingMinSize = options.gpuTimingMinSize ?? 1;\\n\\t\\t\\t\\tconst cpuTimingMinSize = options.cpuTimingMinSize ?? 1;\\n\\t\\t\\t\\tif (gpuTimingMinSize < this.sizes.length || cpuTimingMinSize < this.sizes.length) {\\n\\t\\t\\t\\t\\t\\tconst lastWidth = this.sizes[this.sizes.length - 1].width;\\n\\t\\t\\t\\t\\t\\tfor(let i = 1; i < this.sizes.length - 1; i++){\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.sizes[i].width = lastWidth;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst div = document.createElement('div');\\n\\t\\t\\t\\tdiv.setAttribute('id', 'mini-stats');\\n\\t\\t\\t\\tdiv.style.cssText = 'position:fixed;bottom:0;left:0;background:transparent;';\\n\\t\\t\\t\\tdocument.body.appendChild(div);\\n\\t\\t\\t\\tdiv.addEventListener('mouseenter', (event)=>{\\n\\t\\t\\t\\t\\t\\tthis.opacity = 1.0;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tdiv.addEventListener('mouseleave', (event)=>{\\n\\t\\t\\t\\t\\t\\tthis.opacity = this._activeSizeIndex > 0 ? 0.85 : 0.7;\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tdiv.addEventListener('click', (event)=>{\\n\\t\\t\\t\\t\\t\\tevent.preventDefault();\\n\\t\\t\\t\\t\\t\\tif (this._enabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.activeSizeIndex = (this.activeSizeIndex + 1) % this.sizes.length;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.resize(this.sizes[this.activeSizeIndex].width, this.sizes[this.activeSizeIndex].height, this.sizes[this.activeSizeIndex].graphs);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tdevice.on('resizecanvas', this.updateDiv, this);\\n\\t\\t\\t\\tdevice.on('losecontext', this.loseContext, this);\\n\\t\\t\\t\\tapp.on('postrender', this.postRender, this);\\n\\t\\t\\t\\tthis.app = app;\\n\\t\\t\\t\\tthis.drawLayer = app.scene.layers.getLayerById(LAYERID_UI);\\n\\t\\t\\t\\tthis.device = device;\\n\\t\\t\\t\\tthis.render2d = new Render2d(device);\\n\\t\\t\\t\\tthis.div = div;\\n\\t\\t\\t\\tthis.width = 0;\\n\\t\\t\\t\\tthis.height = 0;\\n\\t\\t\\t\\tthis.gspacing = 2;\\n\\t\\t\\t\\tthis.clr = [\\n\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\t1,\\n\\t\\t\\t\\t\\t\\toptions.startSizeIndex > 0 ? 0.85 : 0.7\\n\\t\\t\\t\\t];\\n\\t\\t\\t\\tthis._enabled = true;\\n\\t\\t\\t\\tthis.gpuTimingMinSize = gpuTimingMinSize;\\n\\t\\t\\t\\tthis.gpuPassGraphs = new Map();\\n\\t\\t\\t\\tthis.cpuTimingMinSize = cpuTimingMinSize;\\n\\t\\t\\t\\tthis.cpuGraphs = new Map();\\n\\t\\t\\t\\tthis.frameIndex = 0;\\n\\t\\t\\t\\tthis.textRefreshRate = options.textRefreshRate;\\n\\t\\t\\t\\tthis.activeSizeIndex = this._activeSizeIndex;\\n\\t\\t}\\n}\\n\\nconst SSAOTYPE_NONE = 'none';\\nconst SSAOTYPE_LIGHTING = 'lighting';\\nconst SSAOTYPE_COMBINE = 'combine';\\n\\nvar glslDownsamplePS = `\\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 wgslDownsamplePS = `\\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: vec3f = textureSample(sourceTexture, sourceTextureSampler, input.uv0).rgb;\\n\\t#ifdef BOXFILTER\\n\\t\\tvar value: vec3f = e;\\n\\t\\t#ifdef PREMULTIPLY\\n\\t\\t\\tlet premultiply: f32 = textureSample(premultiplyTexture, premultiplyTextureSampler, input.uv0).{PREMULTIPLY_SRC_CHANNEL};\\n\\t\\t\\tvalue = value * vec3f(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: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x - 2.0 * x, input.uv0.y + 2.0 * y)).rgb;\\n\\t\\tlet b: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x,\\t\\t   input.uv0.y + 2.0 * y)).rgb;\\n\\t\\tlet c: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x + 2.0 * x, input.uv0.y + 2.0 * y)).rgb;\\n\\t\\tlet d: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x - 2.0 * x, input.uv0.y)).rgb;\\n\\t\\tlet f: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x + 2.0 * x, input.uv0.y)).rgb;\\n\\t\\tlet g: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x - 2.0 * x, input.uv0.y - 2.0 * y)).rgb;\\n\\t\\tlet h: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x,\\t\\t   input.uv0.y - 2.0 * y)).rgb;\\n\\t\\tlet i: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x + 2.0 * x, input.uv0.y - 2.0 * y)).rgb;\\n\\t\\tlet j: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x - x, input.uv0.y + y)).rgb;\\n\\t\\tlet k: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x + x, input.uv0.y + y)).rgb;\\n\\t\\tlet l: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x - x, input.uv0.y - y)).rgb;\\n\\t\\tlet m: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x + x, input.uv0.y - y)).rgb;\\n\\t\\tvar value: vec3f = e * 0.125;\\n\\t\\tvalue = value + (a + c + g + i) * 0.03125;\\n\\t\\tvalue = value + (b + d + f + h) * 0.0625;\\n\\t\\tvalue = value + (j + k + l + m) * 0.125;\\n\\t#endif\\n\\t#ifdef REMOVE_INVALID\\n\\t\\tvalue = max(value, vec3f(0.0));\\n\\t#endif\\n\\toutput.color = vec4f(value, 1.0);\\n\\treturn output;\\n}\\n`;\\n\\nclass RenderPassDownsample extends RenderPassShaderQuad {\\n\\t\\tsetSourceTexture(value) {\\n\\t\\t\\t\\tthis._sourceTexture = value;\\n\\t\\t\\t\\tthis.options.resizeSource = value;\\n\\t\\t}\\n\\t\\texecute() {\\n\\t\\t\\t\\tthis.sourceTextureId.setValue(this.sourceTexture);\\n\\t\\t\\t\\tif (this.premultiplyTexture) {\\n\\t\\t\\t\\t\\t\\tthis.premultiplyTextureId.setValue(this.premultiplyTexture);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.sourceInvResolutionValue[0] = 1.0 / this.sourceTexture.width;\\n\\t\\t\\t\\tthis.sourceInvResolutionValue[1] = 1.0 / this.sourceTexture.height;\\n\\t\\t\\t\\tthis.sourceInvResolutionId.setValue(this.sourceInvResolutionValue);\\n\\t\\t\\t\\tsuper.execute();\\n\\t\\t}\\n\\t\\tconstructor(device, sourceTexture, options = {}){\\n\\t\\t\\t\\tsuper(device);\\n\\t\\t\\t\\tthis.sourceTexture = sourceTexture;\\n\\t\\t\\t\\tthis.premultiplyTexture = options.premultiplyTexture;\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set('downsamplePS', glslDownsamplePS);\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set('downsamplePS', wgslDownsamplePS);\\n\\t\\t\\t\\tconst boxFilter = options.boxFilter ?? false;\\n\\t\\t\\t\\tconst key = `${boxFilter ? 'Box' : ''}-${options.premultiplyTexture ? 'Premultiply' : ''}-${options.premultiplySrcChannel ?? ''}-${options.removeInvalid ? 'RemoveInvalid' : ''}`;\\n\\t\\t\\t\\tconst defines = new Map();\\n\\t\\t\\t\\tif (boxFilter) defines.set('BOXFILTER', '');\\n\\t\\t\\t\\tif (options.premultiplyTexture) defines.set('PREMULTIPLY', '');\\n\\t\\t\\t\\tif (options.removeInvalid) defines.set('REMOVE_INVALID', '');\\n\\t\\t\\t\\tdefines.set('{PREMULTIPLY_SRC_CHANNEL}', options.premultiplySrcChannel ?? 'x');\\n\\t\\t\\t\\tthis.shader = ShaderUtils.createShader(device, {\\n\\t\\t\\t\\t\\t\\tuniqueName: `DownSampleShader:${key}`,\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\taPosition: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tvertexChunk: 'quadVS',\\n\\t\\t\\t\\t\\t\\tfragmentChunk: 'downsamplePS',\\n\\t\\t\\t\\t\\t\\tfragmentDefines: defines\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.sourceTextureId = device.scope.resolve('sourceTexture');\\n\\t\\t\\t\\tthis.premultiplyTextureId = device.scope.resolve('premultiplyTexture');\\n\\t\\t\\t\\tthis.sourceInvResolutionId = device.scope.resolve('sourceInvResolution');\\n\\t\\t\\t\\tthis.sourceInvResolutionValue = new Float32Array(2);\\n\\t\\t}\\n}\\n\\nvar glslUpsamplePS = `\\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 * 4.0;\\n\\t\\tvalue += (b + d + f + h) * 2.0;\\n\\t\\tvalue += (a + c + g + i);\\n\\t\\tvalue *= 1.0 / 16.0;\\n\\t\\tgl_FragColor = vec4(value, 1.0);\\n\\t}\\n`;\\n\\nvar wgslUpsamplePS = `\\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: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x - x, input.uv0.y + y)).rgb;\\n\\t\\tlet b: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x,\\t input.uv0.y + y)).rgb;\\n\\t\\tlet c: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x + x, input.uv0.y + y)).rgb;\\n\\t\\tlet d: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x - x, input.uv0.y)).rgb;\\n\\t\\tlet e: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x,\\t input.uv0.y)).rgb;\\n\\t\\tlet f: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x + x, input.uv0.y)).rgb;\\n\\t\\tlet g: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x - x, input.uv0.y - y)).rgb;\\n\\t\\tlet h: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x,\\t input.uv0.y - y)).rgb;\\n\\t\\tlet i: vec3f = textureSample(sourceTexture, sourceTextureSampler, vec2f(input.uv0.x + x, input.uv0.y - y)).rgb;\\n\\t\\tvar value: vec3f = e * 4.0;\\n\\t\\tvalue = value + (b + d + f + h) * 2.0;\\n\\t\\tvalue = value + (a + c + g + i);\\n\\t\\tvalue = value * (1.0 / 16.0);\\n\\t\\toutput.color = vec4f(value, 1.0);\\n\\t\\treturn output;\\n\\t}\\n`;\\n\\nclass RenderPassUpsample extends RenderPassShaderQuad {\\n\\t\\texecute() {\\n\\t\\t\\t\\tthis.sourceTextureId.setValue(this.sourceTexture);\\n\\t\\t\\t\\tthis.sourceInvResolutionValue[0] = 1.0 / this.sourceTexture.width;\\n\\t\\t\\t\\tthis.sourceInvResolutionValue[1] = 1.0 / this.sourceTexture.height;\\n\\t\\t\\t\\tthis.sourceInvResolutionId.setValue(this.sourceInvResolutionValue);\\n\\t\\t\\t\\tsuper.execute();\\n\\t\\t}\\n\\t\\tconstructor(device, sourceTexture){\\n\\t\\t\\t\\tsuper(device);\\n\\t\\t\\t\\tthis.sourceTexture = sourceTexture;\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set('upsamplePS', glslUpsamplePS);\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set('upsamplePS', wgslUpsamplePS);\\n\\t\\t\\t\\tthis.shader = ShaderUtils.createShader(device, {\\n\\t\\t\\t\\t\\t\\tuniqueName: 'UpSampleShader',\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\taPosition: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tvertexChunk: 'quadVS',\\n\\t\\t\\t\\t\\t\\tfragmentChunk: 'upsamplePS'\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.sourceTextureId = device.scope.resolve('sourceTexture');\\n\\t\\t\\t\\tthis.sourceInvResolutionId = device.scope.resolve('sourceInvResolution');\\n\\t\\t\\t\\tthis.sourceInvResolutionValue = new Float32Array(2);\\n\\t\\t}\\n}\\n\\nclass RenderPassBloom extends RenderPass {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.destroyRenderPasses();\\n\\t\\t\\t\\tthis.destroyRenderTargets();\\n\\t\\t}\\n\\t\\tdestroyRenderTargets(startIndex = 0) {\\n\\t\\t\\t\\tfor(let i = startIndex; i < this.renderTargets.length; i++){\\n\\t\\t\\t\\t\\t\\tconst rt = this.renderTargets[i];\\n\\t\\t\\t\\t\\t\\trt.destroyTextureBuffers();\\n\\t\\t\\t\\t\\t\\trt.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.renderTargets.length = 0;\\n\\t\\t}\\n\\t\\tdestroyRenderPasses() {\\n\\t\\t\\t\\tfor(let i = 0; i < this.beforePasses.length; i++){\\n\\t\\t\\t\\t\\t\\tthis.beforePasses[i].destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.beforePasses.length = 0;\\n\\t\\t}\\n\\t\\tcreateRenderTarget(index) {\\n\\t\\t\\t\\treturn new RenderTarget({\\n\\t\\t\\t\\t\\t\\tdepth: false,\\n\\t\\t\\t\\t\\t\\tcolorBuffer: new Texture(this.device, {\\n\\t\\t\\t\\t\\t\\t\\t\\tname: `BloomTexture${index}`,\\n\\t\\t\\t\\t\\t\\t\\t\\twidth: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\theight: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: this.textureFormat,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\t\\t\\tminFilter: FILTER_LINEAR,\\n\\t\\t\\t\\t\\t\\t\\t\\tmagFilter: FILTER_LINEAR,\\n\\t\\t\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t\\t\\t\\t\\t})\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tcreateRenderTargets(count) {\\n\\t\\t\\t\\tfor(let i = 0; i < count; i++){\\n\\t\\t\\t\\t\\t\\tconst rt = i === 0 ? this.bloomRenderTarget : this.createRenderTarget(i);\\n\\t\\t\\t\\t\\t\\tthis.renderTargets.push(rt);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcalcMipLevels(width, height, minSize) {\\n\\t\\t\\t\\tconst min = Math.min(width, height);\\n\\t\\t\\t\\treturn Math.floor(Math.log2(min) - Math.log2(minSize));\\n\\t\\t}\\n\\t\\tcreateRenderPasses(numPasses) {\\n\\t\\t\\t\\tconst device = this.device;\\n\\t\\t\\t\\tlet passSourceTexture = this._sourceTexture;\\n\\t\\t\\t\\tfor(let i = 0; i < numPasses; i++){\\n\\t\\t\\t\\t\\t\\tconst pass = new RenderPassDownsample(device, passSourceTexture);\\n\\t\\t\\t\\t\\t\\tconst rt = this.renderTargets[i];\\n\\t\\t\\t\\t\\t\\tpass.init(rt, {\\n\\t\\t\\t\\t\\t\\t\\t\\tresizeSource: passSourceTexture,\\n\\t\\t\\t\\t\\t\\t\\t\\tscaleX: 0.5,\\n\\t\\t\\t\\t\\t\\t\\t\\tscaleY: 0.5\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tpass.setClearColor(Color.BLACK);\\n\\t\\t\\t\\t\\t\\tthis.beforePasses.push(pass);\\n\\t\\t\\t\\t\\t\\tpassSourceTexture = rt.colorBuffer;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tpassSourceTexture = this.renderTargets[numPasses - 1].colorBuffer;\\n\\t\\t\\t\\tfor(let i = numPasses - 2; i >= 0; i--){\\n\\t\\t\\t\\t\\t\\tconst pass = new RenderPassUpsample(device, passSourceTexture);\\n\\t\\t\\t\\t\\t\\tconst rt = this.renderTargets[i];\\n\\t\\t\\t\\t\\t\\tpass.init(rt);\\n\\t\\t\\t\\t\\t\\tpass.blendState = BlendState.ADDBLEND;\\n\\t\\t\\t\\t\\t\\tthis.beforePasses.push(pass);\\n\\t\\t\\t\\t\\t\\tpassSourceTexture = rt.colorBuffer;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tonDisable() {\\n\\t\\t\\t\\tthis.renderTargets[0]?.resize(1, 1);\\n\\t\\t\\t\\tthis.destroyRenderPasses();\\n\\t\\t\\t\\tthis.destroyRenderTargets(1);\\n\\t\\t}\\n\\t\\tframeUpdate() {\\n\\t\\t\\t\\tsuper.frameUpdate();\\n\\t\\t\\t\\tconst maxNumPasses = this.calcMipLevels(this._sourceTexture.width, this._sourceTexture.height, 1);\\n\\t\\t\\t\\tconst numPasses = math.clamp(maxNumPasses, 1, this.blurLevel);\\n\\t\\t\\t\\tif (this.renderTargets.length !== numPasses) {\\n\\t\\t\\t\\t\\t\\tthis.destroyRenderPasses();\\n\\t\\t\\t\\t\\t\\tthis.destroyRenderTargets(1);\\n\\t\\t\\t\\t\\t\\tthis.createRenderTargets(numPasses);\\n\\t\\t\\t\\t\\t\\tthis.createRenderPasses(numPasses);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tconstructor(device, sourceTexture, format){\\n\\t\\t\\t\\tsuper(device), this.blurLevel = 16, this.renderTargets = [];\\n\\t\\t\\t\\tthis._sourceTexture = sourceTexture;\\n\\t\\t\\t\\tthis.textureFormat = format;\\n\\t\\t\\t\\tthis.bloomRenderTarget = this.createRenderTarget(0);\\n\\t\\t\\t\\tthis.bloomTexture = this.bloomRenderTarget.colorBuffer;\\n\\t\\t}\\n}\\n\\nvar composePS$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 \\\"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\\t#ifdef TAA\\n\\t\\t#ifdef WEBGPU\\n\\t\\t\\tuv.y = 1.0 - uv.y;\\n\\t\\t#endif\\n\\t\\t#endif\\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 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 composeBloomPS$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 composeDofPS$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 composeSsaoPS$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 composeGradingPS$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 composeVignettePS$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 composeFringingPS$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 composeCasPS$1 = `\\n\\t#ifdef CAS\\n\\t\\tuniform float sharpness;\\n\\t\\tfloat maxComponent(float x, float y, float z) { return max(x, max(y, z)); }\\n\\t\\tvec3 toSDR(vec3 c) { return c / (1.0 + maxComponent(c.r, c.g, c.b)); }\\n\\t\\tvec3 toHDR(vec3 c) { return c / (1.0 - maxComponent(c.r, c.g, c.b)); }\\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_g);\\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 composeColorLutPS$1 = `\\n\\t#ifdef COLOR_LUT\\n\\t\\tuniform sampler2D colorLUT;\\n\\t\\tuniform vec4 colorLUTParams;\\n\\t\\tvec3 applyColorLUT(vec3 color) {\\n\\t\\t\\tvec3 c = clamp(color, 0.0, 1.0);\\n\\t\\t\\tfloat width = colorLUTParams.x;\\n\\t\\t\\tfloat height = colorLUTParams.y;\\n\\t\\t\\tfloat maxColor = colorLUTParams.z;\\n\\t\\t\\tfloat cell = c.b * maxColor;\\n\\t\\t\\tfloat cell_l = floor(cell);\\n\\t\\t\\tfloat cell_h = ceil(cell);\\n\\t\\t\\tfloat half_px_x = 0.5 / width;\\n\\t\\t\\tfloat half_px_y = 0.5 / height;\\n\\t\\t\\tfloat r_offset = half_px_x + c.r / height * (maxColor / height);\\n\\t\\t\\tfloat g_offset = half_px_y + c.g * (maxColor / height);\\n\\t\\t\\tvec2 uv_l = vec2(cell_l / height + r_offset, g_offset);\\n\\t\\t\\tvec2 uv_h = vec2(cell_h / height + r_offset, g_offset);\\n\\t\\t\\tvec3 color_l = texture2DLod(colorLUT, uv_l, 0.0).rgb;\\n\\t\\t\\tvec3 color_h = texture2DLod(colorLUT, uv_h, 0.0).rgb;\\n\\t\\t\\tvec3 lutColor = mix(color_l, color_h, fract(cell));\\n\\t\\t\\treturn mix(color, lutColor, colorLUTParams.w);\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nconst composeChunksGLSL = {\\n\\t\\tcomposePS: composePS$1,\\n\\t\\tcomposeBloomPS: composeBloomPS$1,\\n\\t\\tcomposeDofPS: composeDofPS$1,\\n\\t\\tcomposeSsaoPS: composeSsaoPS$1,\\n\\t\\tcomposeGradingPS: composeGradingPS$1,\\n\\t\\tcomposeVignettePS: composeVignettePS$1,\\n\\t\\tcomposeFringingPS: composeFringingPS$1,\\n\\t\\tcomposeCasPS: composeCasPS$1,\\n\\t\\tcomposeColorLutPS: composeColorLutPS$1,\\n\\t\\tcomposeDeclarationsPS: '',\\n\\t\\tcomposeMainStartPS: '',\\n\\t\\tcomposeMainEndPS: ''\\n};\\n\\nvar composePS = `\\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 \\\"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\\t#ifdef TAA\\n\\t\\t\\tuv.y = 1.0 - uv.y;\\n\\t\\t#endif\\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 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 composeBloomPS = `\\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 composeDofPS = `\\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 composeSsaoPS = `\\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 composeGradingPS = `\\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 composeVignettePS = `\\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 composeFringingPS = `\\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 composeCasPS = `\\n\\t#ifdef CAS\\n\\t\\tuniform sharpness: f32;\\n\\t\\tfn maxComponent(x: f32, y: f32, z: f32) -> f32 { return max(x, max(y, z)); }\\n\\t\\tfn toSDR(c: vec3f) -> vec3f { return c / (1.0 + maxComponent(c.r, c.g, c.b)); }\\n\\t\\tfn toHDR(c: vec3f) -> vec3f { return c / (1.0 - maxComponent(c.r, c.g, c.b)); }\\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 = toSDR(textureSampleLevel(sceneTexture, sceneTextureSampler, uv + vec2f(0.0, -y), 0.0).rgb);\\n\\t\\t\\tlet b = toSDR(textureSampleLevel(sceneTexture, sceneTextureSampler, uv + vec2f(-x, 0.0), 0.0).rgb);\\n\\t\\t\\tlet c = toSDR(color.rgb);\\n\\t\\t\\tlet d = toSDR(textureSampleLevel(sceneTexture, sceneTextureSampler, uv + vec2f(x, 0.0), 0.0).rgb);\\n\\t\\t\\tlet e = 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(1.0 - max_g, min_g) / max_g);\\n\\t\\t\\tlet w = sharpening_amount * uniform.sharpness;\\n\\t\\t\\tvar res = (w * (a + b + d + e) + c) / (4.0 * w + 1.0);\\n\\t\\t\\tres = max(res, vec3f(0.0));\\n\\t\\t\\treturn toHDR(res);\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nvar composeColorLutPS = `\\n\\t#ifdef COLOR_LUT\\n\\t\\tvar colorLUT: texture_2d<f32>;\\n\\t\\tvar colorLUTSampler: sampler;\\n\\t\\tuniform colorLUTParams: vec4f;\\n\\t\\tfn applyColorLUT(color: vec3f) -> vec3f {\\n\\t\\t\\tvar c: vec3f = clamp(color, vec3f(0.0), vec3f(1.0));\\n\\t\\t\\tlet width: f32 = uniform.colorLUTParams.x;\\n\\t\\t\\tlet height: f32 = uniform.colorLUTParams.y;\\n\\t\\t\\tlet maxColor: f32 = uniform.colorLUTParams.z;\\n\\t\\t\\tlet cell: f32 = c.b * maxColor;\\n\\t\\t\\tlet cell_l: f32 = floor(cell);\\n\\t\\t\\tlet cell_h: f32 = ceil(cell);\\n\\t\\t\\tlet half_px_x: f32 = 0.5 / width;\\n\\t\\t\\tlet half_px_y: f32 = 0.5 / height;\\n\\t\\t\\tlet r_offset: f32 = half_px_x + c.r / height * (maxColor / height);\\n\\t\\t\\tlet g_offset: f32 = half_px_y + c.g * (maxColor / height);\\n\\t\\t\\tlet uv_l: vec2f = vec2f(cell_l / height + r_offset, g_offset);\\n\\t\\t\\tlet uv_h: vec2f = vec2f(cell_h / height + r_offset, g_offset);\\n\\t\\t\\tlet color_l: vec3f = textureSampleLevel(colorLUT, colorLUTSampler, uv_l, 0.0).rgb;\\n\\t\\t\\tlet color_h: vec3f = textureSampleLevel(colorLUT, colorLUTSampler, uv_h, 0.0).rgb;\\n\\t\\t\\tlet lutColor: vec3f = mix(color_l, color_h, fract(cell));\\n\\t\\t\\treturn mix(color, lutColor, uniform.colorLUTParams.w);\\n\\t\\t}\\n\\t#endif\\n`;\\n\\nconst composeChunksWGSL = {\\n\\t\\tcomposePS,\\n\\t\\tcomposeBloomPS,\\n\\t\\tcomposeDofPS,\\n\\t\\tcomposeSsaoPS,\\n\\t\\tcomposeGradingPS,\\n\\t\\tcomposeVignettePS,\\n\\t\\tcomposeFringingPS,\\n\\t\\tcomposeCasPS,\\n\\t\\tcomposeColorLutPS,\\n\\t\\tcomposeDeclarationsPS: '',\\n\\t\\tcomposeMainStartPS: '',\\n\\t\\tcomposeMainEndPS: ''\\n};\\n\\nclass RenderPassCompose extends RenderPassShaderQuad {\\n\\t\\tset debug(value) {\\n\\t\\t\\t\\tif (this._debug !== value) {\\n\\t\\t\\t\\t\\t\\tthis._debug = value;\\n\\t\\t\\t\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget debug() {\\n\\t\\t\\t\\treturn this._debug;\\n\\t\\t}\\n\\t\\tset colorLUT(value) {\\n\\t\\t\\t\\tif (this._colorLUT !== value) {\\n\\t\\t\\t\\t\\t\\tthis._colorLUT = value;\\n\\t\\t\\t\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget colorLUT() {\\n\\t\\t\\t\\treturn this._colorLUT;\\n\\t\\t}\\n\\t\\tset bloomTexture(value) {\\n\\t\\t\\t\\tif (this._bloomTexture !== value) {\\n\\t\\t\\t\\t\\t\\tthis._bloomTexture = value;\\n\\t\\t\\t\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget bloomTexture() {\\n\\t\\t\\t\\treturn this._bloomTexture;\\n\\t\\t}\\n\\t\\tset cocTexture(value) {\\n\\t\\t\\t\\tif (this._cocTexture !== value) {\\n\\t\\t\\t\\t\\t\\tthis._cocTexture = value;\\n\\t\\t\\t\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget cocTexture() {\\n\\t\\t\\t\\treturn this._cocTexture;\\n\\t\\t}\\n\\t\\tset ssaoTexture(value) {\\n\\t\\t\\t\\tif (this._ssaoTexture !== value) {\\n\\t\\t\\t\\t\\t\\tthis._ssaoTexture = value;\\n\\t\\t\\t\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget ssaoTexture() {\\n\\t\\t\\t\\treturn this._ssaoTexture;\\n\\t\\t}\\n\\t\\tset taaEnabled(value) {\\n\\t\\t\\t\\tif (this._taaEnabled !== value) {\\n\\t\\t\\t\\t\\t\\tthis._taaEnabled = value;\\n\\t\\t\\t\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget taaEnabled() {\\n\\t\\t\\t\\treturn this._taaEnabled;\\n\\t\\t}\\n\\t\\tset gradingEnabled(value) {\\n\\t\\t\\t\\tif (this._gradingEnabled !== value) {\\n\\t\\t\\t\\t\\t\\tthis._gradingEnabled = value;\\n\\t\\t\\t\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget gradingEnabled() {\\n\\t\\t\\t\\treturn this._gradingEnabled;\\n\\t\\t}\\n\\t\\tset vignetteEnabled(value) {\\n\\t\\t\\t\\tif (this._vignetteEnabled !== value) {\\n\\t\\t\\t\\t\\t\\tthis._vignetteEnabled = value;\\n\\t\\t\\t\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget vignetteEnabled() {\\n\\t\\t\\t\\treturn this._vignetteEnabled;\\n\\t\\t}\\n\\t\\tset fringingEnabled(value) {\\n\\t\\t\\t\\tif (this._fringingEnabled !== value) {\\n\\t\\t\\t\\t\\t\\tthis._fringingEnabled = value;\\n\\t\\t\\t\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget fringingEnabled() {\\n\\t\\t\\t\\treturn this._fringingEnabled;\\n\\t\\t}\\n\\t\\tset toneMapping(value) {\\n\\t\\t\\t\\tif (this._toneMapping !== value) {\\n\\t\\t\\t\\t\\t\\tthis._toneMapping = value;\\n\\t\\t\\t\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget toneMapping() {\\n\\t\\t\\t\\treturn this._toneMapping;\\n\\t\\t}\\n\\t\\tset sharpness(value) {\\n\\t\\t\\t\\tif (this._sharpness !== value) {\\n\\t\\t\\t\\t\\t\\tthis._sharpness = value;\\n\\t\\t\\t\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget sharpness() {\\n\\t\\t\\t\\treturn this._sharpness;\\n\\t\\t}\\n\\t\\tget isSharpnessEnabled() {\\n\\t\\t\\t\\treturn this._sharpness > 0;\\n\\t\\t}\\n\\t\\tpostInit() {\\n\\t\\t\\t\\tthis.setClearColor(Color.BLACK);\\n\\t\\t\\t\\tthis.setClearDepth(1.0);\\n\\t\\t\\t\\tthis.setClearStencil(0);\\n\\t\\t}\\n\\t\\tframeUpdate() {\\n\\t\\t\\t\\tconst rt = this.renderTarget ?? this.device.backBuffer;\\n\\t\\t\\t\\tconst srgb = rt.isColorBufferSrgb(0);\\n\\t\\t\\t\\tconst neededGammaCorrection = srgb ? GAMMA_NONE : GAMMA_SRGB;\\n\\t\\t\\t\\tif (this._gammaCorrection !== neededGammaCorrection) {\\n\\t\\t\\t\\t\\t\\tthis._gammaCorrection = neededGammaCorrection;\\n\\t\\t\\t\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst shaderChunks = ShaderChunks.get(this.device, this.device.isWebGPU ? SHADERLANGUAGE_WGSL : SHADERLANGUAGE_GLSL);\\n\\t\\t\\t\\tfor (const [name, prevValue] of this._customComposeChunks.entries()){\\n\\t\\t\\t\\t\\t\\tconst currentValue = shaderChunks.get(name);\\n\\t\\t\\t\\t\\t\\tif (currentValue !== prevValue) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._customComposeChunks.set(name, currentValue);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._shaderDirty = true;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._shaderDirty) {\\n\\t\\t\\t\\t\\t\\tthis._shaderDirty = false;\\n\\t\\t\\t\\t\\t\\tconst gammaCorrectionName = gammaNames[this._gammaCorrection];\\n\\t\\t\\t\\t\\t\\tconst customChunks = this._customComposeChunks;\\n\\t\\t\\t\\t\\t\\tconst declHash = hashCode(customChunks.get('composeDeclarationsPS') ?? '');\\n\\t\\t\\t\\t\\t\\tconst startHash = hashCode(customChunks.get('composeMainStartPS') ?? '');\\n\\t\\t\\t\\t\\t\\tconst endHash = hashCode(customChunks.get('composeMainEndPS') ?? '');\\n\\t\\t\\t\\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.colorLUT ? 'colorlut' : 'nocolorlut'}` + `-${this.vignetteEnabled ? 'vignette' : 'novignette'}` + `-${this.fringingEnabled ? 'fringing' : 'nofringing'}` + `-${this.taaEnabled ? 'taa' : 'notaa'}` + `-${this.isSharpnessEnabled ? 'cas' : 'nocas'}` + `-${this._debug ?? ''}` + `-decl${declHash}-start${startHash}-end${endHash}`;\\n\\t\\t\\t\\t\\t\\tif (this._key !== key) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._key = key;\\n\\t\\t\\t\\t\\t\\t\\t\\tconst defines = new Map();\\n\\t\\t\\t\\t\\t\\t\\t\\tdefines.set('TONEMAP', tonemapNames[this.toneMapping]);\\n\\t\\t\\t\\t\\t\\t\\t\\tdefines.set('GAMMA', gammaCorrectionName);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.bloomTexture) defines.set('BLOOM', true);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.cocTexture) defines.set('DOF', true);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.blurTextureUpscale) defines.set('DOF_UPSCALE', true);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.ssaoTexture) defines.set('SSAO', true);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.gradingEnabled) defines.set('GRADING', true);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.colorLUT) defines.set('COLOR_LUT', true);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.vignetteEnabled) defines.set('VIGNETTE', true);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.fringingEnabled) defines.set('FRINGING', true);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.taaEnabled) defines.set('TAA', true);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this.isSharpnessEnabled) defines.set('CAS', true);\\n\\t\\t\\t\\t\\t\\t\\t\\tif (this._debug) defines.set('DEBUG_COMPOSE', this._debug);\\n\\t\\t\\t\\t\\t\\t\\t\\tconst includes = new Map(shaderChunks);\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.shader = ShaderUtils.createShader(this.device, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tuniqueName: `ComposeShader-${key}`,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\taPosition: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tvertexChunk: 'quadVS',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfragmentChunk: 'composePS',\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfragmentDefines: defines,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfragmentIncludes: includes\\n\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\texecute() {\\n\\t\\t\\t\\tconst sceneTex = this.sceneTexture;\\n\\t\\t\\t\\tthis.sceneTextureId.setValue(sceneTex);\\n\\t\\t\\t\\tthis.sceneTextureInvResValue[0] = 1.0 / sceneTex.width;\\n\\t\\t\\t\\tthis.sceneTextureInvResValue[1] = 1.0 / sceneTex.height;\\n\\t\\t\\t\\tthis.sceneTextureInvResId.setValue(this.sceneTextureInvResValue);\\n\\t\\t\\t\\tif (this._bloomTexture) {\\n\\t\\t\\t\\t\\t\\tthis.bloomTextureId.setValue(this._bloomTexture);\\n\\t\\t\\t\\t\\t\\tthis.bloomIntensityId.setValue(this.bloomIntensity);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._cocTexture) {\\n\\t\\t\\t\\t\\t\\tthis.cocTextureId.setValue(this._cocTexture);\\n\\t\\t\\t\\t\\t\\tthis.blurTextureId.setValue(this.blurTexture);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._ssaoTexture) {\\n\\t\\t\\t\\t\\t\\tthis.ssaoTextureId.setValue(this._ssaoTexture);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._gradingEnabled) {\\n\\t\\t\\t\\t\\t\\tthis.bcsId.setValue([\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gradingBrightness,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gradingContrast,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gradingSaturation\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\tthis.tintId.setValue([\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gradingTint.r,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gradingTint.g,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.gradingTint.b\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst lutTexture = this._colorLUT;\\n\\t\\t\\t\\tif (lutTexture) {\\n\\t\\t\\t\\t\\t\\tthis.colorLUTParams[0] = lutTexture.width;\\n\\t\\t\\t\\t\\t\\tthis.colorLUTParams[1] = lutTexture.height;\\n\\t\\t\\t\\t\\t\\tthis.colorLUTParams[2] = lutTexture.height - 1.0;\\n\\t\\t\\t\\t\\t\\tthis.colorLUTParams[3] = this.colorLUTIntensity;\\n\\t\\t\\t\\t\\t\\tthis.colorLUTParamsId.setValue(this.colorLUTParams);\\n\\t\\t\\t\\t\\t\\tthis.colorLUTId.setValue(lutTexture);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._vignetteEnabled) {\\n\\t\\t\\t\\t\\t\\tthis.vignetterParamsId.setValue([\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.vignetteInner,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.vignetteOuter,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.vignetteCurvature,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.vignetteIntensity\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\tthis.vignetteColorId.setValue([\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.vignetteColor.r,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.vignetteColor.g,\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.vignetteColor.b\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._fringingEnabled) {\\n\\t\\t\\t\\t\\t\\tthis.fringingIntensityId.setValue(this.fringingIntensity / 1024);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.isSharpnessEnabled) {\\n\\t\\t\\t\\t\\t\\tthis.sharpnessId.setValue(math.lerp(-0.125, -0.2, this.sharpness));\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tsuper.execute();\\n\\t\\t}\\n\\t\\tconstructor(graphicsDevice){\\n\\t\\t\\t\\tsuper(graphicsDevice), this.sceneTexture = null, this.bloomIntensity = 0.01, this._bloomTexture = null, this._cocTexture = null, this.blurTexture = null, this.blurTextureUpscale = false, this._ssaoTexture = null, this._toneMapping = TONEMAP_LINEAR, this._gradingEnabled = false, this.gradingSaturation = 1, this.gradingContrast = 1, this.gradingBrightness = 1, this.gradingTint = new Color(1, 1, 1, 1), this._shaderDirty = true, this._vignetteEnabled = false, this.vignetteInner = 0.5, this.vignetteOuter = 1.0, this.vignetteCurvature = 0.5, this.vignetteIntensity = 0.3, this.vignetteColor = new Color(0, 0, 0), this._fringingEnabled = false, this.fringingIntensity = 10, this._taaEnabled = false, this._sharpness = 0.5, this._gammaCorrection = GAMMA_SRGB, this._colorLUT = null, this.colorLUTIntensity = 1, this._key = '', this._debug = null, this._customComposeChunks = new Map([\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t'composeDeclarationsPS',\\n\\t\\t\\t\\t\\t\\t\\t\\t''\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t'composeMainStartPS',\\n\\t\\t\\t\\t\\t\\t\\t\\t''\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\t[\\n\\t\\t\\t\\t\\t\\t\\t\\t'composeMainEndPS',\\n\\t\\t\\t\\t\\t\\t\\t\\t''\\n\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tShaderChunks.get(graphicsDevice, SHADERLANGUAGE_GLSL).add(composeChunksGLSL, false);\\n\\t\\t\\t\\tShaderChunks.get(graphicsDevice, SHADERLANGUAGE_WGSL).add(composeChunksWGSL, false);\\n\\t\\t\\t\\tconst { scope } = graphicsDevice;\\n\\t\\t\\t\\tthis.sceneTextureId = scope.resolve('sceneTexture');\\n\\t\\t\\t\\tthis.bloomTextureId = scope.resolve('bloomTexture');\\n\\t\\t\\t\\tthis.cocTextureId = scope.resolve('cocTexture');\\n\\t\\t\\t\\tthis.ssaoTextureId = scope.resolve('ssaoTexture');\\n\\t\\t\\t\\tthis.blurTextureId = scope.resolve('blurTexture');\\n\\t\\t\\t\\tthis.bloomIntensityId = scope.resolve('bloomIntensity');\\n\\t\\t\\t\\tthis.bcsId = scope.resolve('brightnessContrastSaturation');\\n\\t\\t\\t\\tthis.tintId = scope.resolve('tint');\\n\\t\\t\\t\\tthis.vignetterParamsId = scope.resolve('vignetterParams');\\n\\t\\t\\t\\tthis.vignetteColorId = scope.resolve('vignetteColor');\\n\\t\\t\\t\\tthis.fringingIntensityId = scope.resolve('fringingIntensity');\\n\\t\\t\\t\\tthis.sceneTextureInvResId = scope.resolve('sceneTextureInvRes');\\n\\t\\t\\t\\tthis.sceneTextureInvResValue = new Float32Array(2);\\n\\t\\t\\t\\tthis.sharpnessId = scope.resolve('sharpness');\\n\\t\\t\\t\\tthis.colorLUTId = scope.resolve('colorLUT');\\n\\t\\t\\t\\tthis.colorLUTParams = new Float32Array(4);\\n\\t\\t\\t\\tthis.colorLUTParamsId = scope.resolve('colorLUTParams');\\n\\t\\t}\\n}\\n\\nvar glslSampleCatmullRomPS = `\\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 wgslSampleCatmullRomPS = `\\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 glsltaaResolvePS = `\\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\\t#ifndef WEBGPU\\n\\t\\t\\tdepth = depth * 2.0 - 1.0;\\n\\t\\t#endif\\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\\tvec4 colorClamp(vec2 uv, vec4 historyColor) {\\n\\t\\tvec3 minColor = vec3(9999.0);\\n\\t\\tvec3 maxColor = 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\\tvec3 color = texture2D(sourceTexture, uv + vec2(x, y) / textureSize).rgb;\\n\\t\\t\\t\\tminColor = min(minColor, color);\\n\\t\\t\\t\\tmaxColor = max(maxColor, color);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tvec3 clamped = clamp(historyColor.rgb, minColor, maxColor);\\n\\t\\treturn vec4(clamped, historyColor.a);\\n\\t}\\n\\tvoid main()\\n\\t{\\n\\t\\tvec2 uv = uv0;\\n\\t\\t#ifdef WEBGPU\\n\\t\\t\\tuv.y = 1.0 - uv.y;\\n\\t\\t#endif\\n\\t\\tvec4 srcColor = texture2D(sourceTexture, uv);\\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 historyColor = SampleTextureCatmullRom(TEXTURE_PASS(historyTexture), historyUv, textureSize);\\n\\t\\t#else\\n\\t\\t\\tvec4 historyColor = texture2D(historyTexture, historyUv);\\n\\t\\t#endif\\n\\t\\tvec4 historyColorClamped = colorClamp(uv, historyColor);\\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\\tgl_FragColor = mix(historyColorClamped, srcColor, mixFactor);\\n\\t}\\n`;\\n\\nvar wgsltaaResolvePS = `\\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: vec2f, depth: f32) -> vec2f {\\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\\treturn (screenPrevious.xy / screenPrevious.w) * 0.5 + 0.5;\\n\\t}\\n\\tfn colorClamp(uv: vec2f, historyColor: vec4f) -> vec4f {\\n\\t\\tvar minColor = vec3f(9999.0);\\n\\t\\tvar maxColor = 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 color_sample = textureSample(sourceTexture, sourceTextureSampler, uv + vec2f(f32(ix), f32(iy)) / uniform.textureSize).rgb;\\n\\t\\t\\t\\tminColor = min(minColor, color_sample);\\n\\t\\t\\t\\tmaxColor = max(maxColor, color_sample);\\n\\t\\t\\t}\\n\\t\\t}\\n\\t\\tlet clamped = clamp(historyColor.rgb, minColor, maxColor);\\n\\t\\treturn vec4f(clamped, historyColor.a);\\n\\t}\\n\\t@fragment\\n\\tfn fragmentMain(input: FragmentInput) -> FragmentOutput {\\n\\t\\tvar output: FragmentOutput;\\n\\t\\tvar uv = input.uv0;\\n\\t\\tuv.y = 1.0 - uv.y;\\n\\t\\tlet srcColor = textureSample(sourceTexture, sourceTextureSampler, uv);\\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 historyColor: vec4f = SampleTextureCatmullRom(historyTexture, historyTextureSampler, historyUv, uniform.textureSize);\\n\\t\\t#else\\n\\t\\t\\tvar historyColor: vec4f = textureSample(historyTexture, historyTextureSampler, historyUv);\\n\\t\\t#endif\\n\\t\\tlet historyColorClamped = colorClamp(uv, historyColor);\\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\\toutput.color = mix(historyColorClamped, srcColor, mixFactor);\\n\\t\\treturn output;\\n\\t}\\n`;\\n\\nclass RenderPassTAA extends RenderPassShaderQuad {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tif (this.renderTarget) {\\n\\t\\t\\t\\t\\t\\tthis.renderTarget.destroyTextureBuffers();\\n\\t\\t\\t\\t\\t\\tthis.renderTarget.destroy();\\n\\t\\t\\t\\t\\t\\tthis.renderTarget = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetup() {\\n\\t\\t\\t\\tfor(let i = 0; i < 2; ++i){\\n\\t\\t\\t\\t\\t\\tthis.historyTextures[i] = new Texture(this.device, {\\n\\t\\t\\t\\t\\t\\t\\t\\tname: `TAA-History-${i}`,\\n\\t\\t\\t\\t\\t\\t\\t\\twidth: 4,\\n\\t\\t\\t\\t\\t\\t\\t\\theight: 4,\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: this.sourceTexture.format,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\t\\t\\tminFilter: FILTER_LINEAR,\\n\\t\\t\\t\\t\\t\\t\\t\\tmagFilter: FILTER_LINEAR,\\n\\t\\t\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tthis.historyRenderTargets[i] = new RenderTarget({\\n\\t\\t\\t\\t\\t\\t\\t\\tcolorBuffer: this.historyTextures[i],\\n\\t\\t\\t\\t\\t\\t\\t\\tdepth: false\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.historyTexture = this.historyTextures[0];\\n\\t\\t\\t\\tthis.init(this.historyRenderTargets[0], {\\n\\t\\t\\t\\t\\t\\tresizeSource: this.sourceTexture\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tbefore() {\\n\\t\\t\\t\\tthis.sourceTextureId.setValue(this.sourceTexture);\\n\\t\\t\\t\\tthis.historyTextureId.setValue(this.historyTextures[1 - this.historyIndex]);\\n\\t\\t\\t\\tthis.textureSize[0] = this.sourceTexture.width;\\n\\t\\t\\t\\tthis.textureSize[1] = this.sourceTexture.height;\\n\\t\\t\\t\\tthis.textureSizeId.setValue(this.textureSize);\\n\\t\\t\\t\\tconst camera = this.cameraComponent.camera;\\n\\t\\t\\t\\tthis.viewProjPrevId.setValue(camera._viewProjPrevious.data);\\n\\t\\t\\t\\tthis.viewProjInvId.setValue(camera._viewProjInverse.data);\\n\\t\\t\\t\\tthis.jittersId.setValue(camera._jitters);\\n\\t\\t\\t\\tthis.cameraParamsId.setValue(camera.fillShaderParams(this.cameraParams));\\n\\t\\t}\\n\\t\\tupdate() {\\n\\t\\t\\t\\tthis.historyIndex = 1 - this.historyIndex;\\n\\t\\t\\t\\tthis.historyTexture = this.historyTextures[this.historyIndex];\\n\\t\\t\\t\\tthis.renderTarget = this.historyRenderTargets[this.historyIndex];\\n\\t\\t\\t\\treturn this.historyTexture;\\n\\t\\t}\\n\\t\\tconstructor(device, sourceTexture, cameraComponent){\\n\\t\\t\\t\\tsuper(device), this.historyIndex = 0, this.historyTexture = null, this.historyTextures = [], this.historyRenderTargets = [];\\n\\t\\t\\t\\tthis.sourceTexture = sourceTexture;\\n\\t\\t\\t\\tthis.cameraComponent = cameraComponent;\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set('sampleCatmullRomPS', glslSampleCatmullRomPS);\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set('sampleCatmullRomPS', wgslSampleCatmullRomPS);\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set('taaResolvePS', glsltaaResolvePS);\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set('taaResolvePS', wgsltaaResolvePS);\\n\\t\\t\\t\\tconst defines = new Map();\\n\\t\\t\\t\\tdefines.set('QUALITY_HIGH', true);\\n\\t\\t\\t\\tShaderUtils.addScreenDepthChunkDefines(device, cameraComponent.shaderParams, defines);\\n\\t\\t\\t\\tthis.shader = ShaderUtils.createShader(device, {\\n\\t\\t\\t\\t\\t\\tuniqueName: 'TaaResolveShader',\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\taPosition: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tvertexChunk: 'quadVS',\\n\\t\\t\\t\\t\\t\\tfragmentChunk: 'taaResolvePS',\\n\\t\\t\\t\\t\\t\\tfragmentDefines: defines\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst { scope } = device;\\n\\t\\t\\t\\tthis.sourceTextureId = scope.resolve('sourceTexture');\\n\\t\\t\\t\\tthis.textureSizeId = scope.resolve('textureSize');\\n\\t\\t\\t\\tthis.textureSize = new Float32Array(2);\\n\\t\\t\\t\\tthis.historyTextureId = scope.resolve('historyTexture');\\n\\t\\t\\t\\tthis.viewProjPrevId = scope.resolve('matrix_viewProjectionPrevious');\\n\\t\\t\\t\\tthis.viewProjInvId = scope.resolve('matrix_viewProjectionInverse');\\n\\t\\t\\t\\tthis.jittersId = scope.resolve('jitters');\\n\\t\\t\\t\\tthis.cameraParams = new Float32Array(4);\\n\\t\\t\\t\\tthis.cameraParamsId = scope.resolve('camera_params');\\n\\t\\t\\t\\tthis.setup();\\n\\t\\t}\\n}\\n\\nvar glslCocPS = `\\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 wgslCocPS = `\\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\\t\\texecute() {\\n\\t\\t\\t\\tconst { paramsValue, focusRange } = this;\\n\\t\\t\\t\\tparamsValue[0] = this.focusDistance + 0.001;\\n\\t\\t\\t\\tparamsValue[1] = focusRange;\\n\\t\\t\\t\\tparamsValue[2] = 1 / focusRange;\\n\\t\\t\\t\\tthis.paramsId.setValue(paramsValue);\\n\\t\\t\\t\\tconst camera = this.cameraComponent.camera;\\n\\t\\t\\t\\tthis.cameraParamsId.setValue(camera.fillShaderParams(this.cameraParams));\\n\\t\\t\\t\\tsuper.execute();\\n\\t\\t}\\n\\t\\tconstructor(device, cameraComponent, nearBlur){\\n\\t\\t\\t\\tsuper(device);\\n\\t\\t\\t\\tthis.cameraComponent = cameraComponent;\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set('cocPS', glslCocPS);\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set('cocPS', wgslCocPS);\\n\\t\\t\\t\\tconst defines = new Map();\\n\\t\\t\\t\\tif (nearBlur) defines.set('NEAR_BLUR', '');\\n\\t\\t\\t\\tShaderUtils.addScreenDepthChunkDefines(device, cameraComponent.shaderParams, defines);\\n\\t\\t\\t\\tthis.shader = ShaderUtils.createShader(device, {\\n\\t\\t\\t\\t\\t\\tuniqueName: `CocShader-${nearBlur}`,\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\taPosition: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tvertexChunk: 'quadVS',\\n\\t\\t\\t\\t\\t\\tfragmentChunk: 'cocPS',\\n\\t\\t\\t\\t\\t\\tfragmentDefines: defines\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.paramsId = device.scope.resolve('params');\\n\\t\\t\\t\\tthis.paramsValue = new Float32Array(3);\\n\\t\\t\\t\\tthis.cameraParams = new Float32Array(4);\\n\\t\\t\\t\\tthis.cameraParamsId = device.scope.resolve('camera_params');\\n\\t\\t}\\n}\\n\\nvar glsldofBlurPS = `\\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 wgsldofBlurPS = `\\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\\t\\tset blurRings(value) {\\n\\t\\t\\t\\tif (this._blurRings !== value) {\\n\\t\\t\\t\\t\\t\\tthis._blurRings = value;\\n\\t\\t\\t\\t\\t\\tthis.shader = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget blurRings() {\\n\\t\\t\\t\\treturn this._blurRings;\\n\\t\\t}\\n\\t\\tset blurRingPoints(value) {\\n\\t\\t\\t\\tif (this._blurRingPoints !== value) {\\n\\t\\t\\t\\t\\t\\tthis._blurRingPoints = value;\\n\\t\\t\\t\\t\\t\\tthis.shader = null;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget blurRingPoints() {\\n\\t\\t\\t\\treturn this._blurRingPoints;\\n\\t\\t}\\n\\t\\tcreateShader() {\\n\\t\\t\\t\\tthis.kernel = new Float32Array(Kernel.concentric(this.blurRings, this.blurRingPoints));\\n\\t\\t\\t\\tconst kernelCount = this.kernel.length >> 1;\\n\\t\\t\\t\\tconst nearBlur = this.nearTexture !== null;\\n\\t\\t\\t\\tconst defines = new Map();\\n\\t\\t\\t\\tdefines.set('{KERNEL_COUNT}', kernelCount);\\n\\t\\t\\t\\tdefines.set('{INV_KERNEL_COUNT}', 1.0 / kernelCount);\\n\\t\\t\\t\\tif (nearBlur) defines.set('NEAR_BLUR', '');\\n\\t\\t\\t\\tthis.shader = ShaderUtils.createShader(this.device, {\\n\\t\\t\\t\\t\\t\\tuniqueName: `DofBlurShader-${kernelCount}-${nearBlur ? 'nearBlur' : 'noNearBlur'}`,\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\taPosition: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tvertexChunk: 'quadVS',\\n\\t\\t\\t\\t\\t\\tfragmentChunk: 'dofBlurPS',\\n\\t\\t\\t\\t\\t\\tfragmentDefines: defines\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\texecute() {\\n\\t\\t\\t\\tif (!this.shader) {\\n\\t\\t\\t\\t\\t\\tthis.createShader();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.nearTextureId.setValue(this.nearTexture);\\n\\t\\t\\t\\tthis.farTextureId.setValue(this.farTexture);\\n\\t\\t\\t\\tthis.cocTextureId.setValue(this.cocTexture);\\n\\t\\t\\t\\tthis.kernelId.setValue(this.kernel);\\n\\t\\t\\t\\tthis.kernelCountId.setValue(this.kernel.length >> 1);\\n\\t\\t\\t\\tthis.blurRadiusNearId.setValue(this.blurRadiusNear);\\n\\t\\t\\t\\tthis.blurRadiusFarId.setValue(this.blurRadiusFar);\\n\\t\\t\\t\\tsuper.execute();\\n\\t\\t}\\n\\t\\tconstructor(device, nearTexture, farTexture, cocTexture){\\n\\t\\t\\t\\tsuper(device), this.blurRadiusNear = 1, this.blurRadiusFar = 1, this._blurRings = 3, this._blurRingPoints = 3;\\n\\t\\t\\t\\tthis.nearTexture = nearTexture;\\n\\t\\t\\t\\tthis.farTexture = farTexture;\\n\\t\\t\\t\\tthis.cocTexture = cocTexture;\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set('dofBlurPS', glsldofBlurPS);\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set('dofBlurPS', wgsldofBlurPS);\\n\\t\\t\\t\\tconst { scope } = device;\\n\\t\\t\\t\\tthis.kernelId = scope.resolve('kernel[0]');\\n\\t\\t\\t\\tthis.kernelCountId = scope.resolve('kernelCount');\\n\\t\\t\\t\\tthis.blurRadiusNearId = scope.resolve('blurRadiusNear');\\n\\t\\t\\t\\tthis.blurRadiusFarId = scope.resolve('blurRadiusFar');\\n\\t\\t\\t\\tthis.nearTextureId = scope.resolve('nearTexture');\\n\\t\\t\\t\\tthis.farTextureId = scope.resolve('farTexture');\\n\\t\\t\\t\\tthis.cocTextureId = scope.resolve('cocTexture');\\n\\t\\t}\\n}\\n\\nclass RenderPassDof extends RenderPass {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.destroyRenderPasses();\\n\\t\\t\\t\\tthis.cocPass = null;\\n\\t\\t\\t\\tthis.farPass = null;\\n\\t\\t\\t\\tthis.blurPass = null;\\n\\t\\t\\t\\tthis.destroyRT(this.cocRT);\\n\\t\\t\\t\\tthis.destroyRT(this.farRt);\\n\\t\\t\\t\\tthis.destroyRT(this.blurRt);\\n\\t\\t\\t\\tthis.cocRT = null;\\n\\t\\t\\t\\tthis.farRt = null;\\n\\t\\t\\t\\tthis.blurRt = null;\\n\\t\\t}\\n\\t\\tdestroyRenderPasses() {\\n\\t\\t\\t\\tfor(let i = 0; i < this.beforePasses.length; i++){\\n\\t\\t\\t\\t\\t\\tthis.beforePasses[i].destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.beforePasses.length = 0;\\n\\t\\t}\\n\\t\\tdestroyRT(rt) {\\n\\t\\t\\t\\tif (rt) {\\n\\t\\t\\t\\t\\t\\trt.destroyTextureBuffers();\\n\\t\\t\\t\\t\\t\\trt.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetupCocPass(device, cameraComponent, sourceTexture, nearBlur) {\\n\\t\\t\\t\\tconst format = nearBlur ? PIXELFORMAT_RG8 : PIXELFORMAT_R8;\\n\\t\\t\\t\\tthis.cocRT = this.createRenderTarget('CoCTexture', format);\\n\\t\\t\\t\\tthis.cocTexture = this.cocRT.colorBuffer;\\n\\t\\t\\t\\tconst cocPass = new RenderPassCoC(device, cameraComponent, nearBlur);\\n\\t\\t\\t\\tcocPass.init(this.cocRT, {\\n\\t\\t\\t\\t\\t\\tresizeSource: sourceTexture\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tcocPass.setClearColor(Color.BLACK);\\n\\t\\t\\t\\treturn cocPass;\\n\\t\\t}\\n\\t\\tsetupFarPass(device, sourceTexture, scale) {\\n\\t\\t\\t\\tthis.farRt = this.createRenderTarget('FarDofTexture', sourceTexture.format);\\n\\t\\t\\t\\tconst farPass = new RenderPassDownsample(device, sourceTexture, {\\n\\t\\t\\t\\t\\t\\tboxFilter: true,\\n\\t\\t\\t\\t\\t\\tpremultiplyTexture: this.cocTexture,\\n\\t\\t\\t\\t\\t\\tpremultiplySrcChannel: 'r'\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tfarPass.init(this.farRt, {\\n\\t\\t\\t\\t\\t\\tresizeSource: sourceTexture,\\n\\t\\t\\t\\t\\t\\tscaleX: scale,\\n\\t\\t\\t\\t\\t\\tscaleY: scale\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tfarPass.setClearColor(Color.BLACK);\\n\\t\\t\\t\\treturn farPass;\\n\\t\\t}\\n\\t\\tsetupBlurPass(device, nearTexture, nearBlur, scale) {\\n\\t\\t\\t\\tconst farTexture = this.farRt?.colorBuffer;\\n\\t\\t\\t\\tthis.blurRt = this.createRenderTarget('DofBlurTexture', nearTexture.format);\\n\\t\\t\\t\\tthis.blurTexture = this.blurRt.colorBuffer;\\n\\t\\t\\t\\tconst blurPass = new RenderPassDofBlur(device, nearBlur ? nearTexture : null, farTexture, this.cocTexture);\\n\\t\\t\\t\\tblurPass.init(this.blurRt, {\\n\\t\\t\\t\\t\\t\\tresizeSource: nearTexture,\\n\\t\\t\\t\\t\\t\\tscaleX: scale,\\n\\t\\t\\t\\t\\t\\tscaleY: scale\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tblurPass.setClearColor(Color.BLACK);\\n\\t\\t\\t\\treturn blurPass;\\n\\t\\t}\\n\\t\\tcreateTexture(name, format) {\\n\\t\\t\\t\\treturn new Texture(this.device, {\\n\\t\\t\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\t\\t\\twidth: 1,\\n\\t\\t\\t\\t\\t\\theight: 1,\\n\\t\\t\\t\\t\\t\\tformat: format,\\n\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\tminFilter: FILTER_LINEAR,\\n\\t\\t\\t\\t\\t\\tmagFilter: FILTER_LINEAR,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tcreateRenderTarget(name, format) {\\n\\t\\t\\t\\treturn new RenderTarget({\\n\\t\\t\\t\\t\\t\\tcolorBuffer: this.createTexture(name, format),\\n\\t\\t\\t\\t\\t\\tdepth: false,\\n\\t\\t\\t\\t\\t\\tstencil: false\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tframeUpdate() {\\n\\t\\t\\t\\tsuper.frameUpdate();\\n\\t\\t\\t\\tthis.cocPass.focusDistance = this.focusDistance;\\n\\t\\t\\t\\tthis.cocPass.focusRange = this.focusRange;\\n\\t\\t\\t\\tthis.blurPass.blurRadiusNear = this.blurRadius;\\n\\t\\t\\t\\tthis.blurPass.blurRadiusFar = this.blurRadius * (this.highQuality ? 1 : 0.5);\\n\\t\\t\\t\\tthis.blurPass.blurRings = this.blurRings;\\n\\t\\t\\t\\tthis.blurPass.blurRingPoints = this.blurRingPoints;\\n\\t\\t}\\n\\t\\tconstructor(device, cameraComponent, sceneTexture, sceneTextureHalf, highQuality, nearBlur){\\n\\t\\t\\t\\tsuper(device), this.focusDistance = 100, this.focusRange = 50, this.blurRadius = 1, this.blurRings = 3, this.blurRingPoints = 3, this.highQuality = true, this.cocTexture = null, this.blurTexture = null, this.cocPass = null, this.farPass = null, this.blurPass = null;\\n\\t\\t\\t\\tthis.highQuality = highQuality;\\n\\t\\t\\t\\tthis.cocPass = this.setupCocPass(device, cameraComponent, sceneTexture, nearBlur);\\n\\t\\t\\t\\tthis.beforePasses.push(this.cocPass);\\n\\t\\t\\t\\tconst sourceTexture = highQuality ? sceneTexture : sceneTextureHalf;\\n\\t\\t\\t\\tthis.farPass = this.setupFarPass(device, sourceTexture, 0.5);\\n\\t\\t\\t\\tthis.beforePasses.push(this.farPass);\\n\\t\\t\\t\\tthis.blurPass = this.setupBlurPass(device, sceneTextureHalf, nearBlur, highQuality ? 2 : 0.5);\\n\\t\\t\\t\\tthis.beforePasses.push(this.blurPass);\\n\\t\\t}\\n}\\n\\nconst tempMeshInstances = [];\\nconst DEPTH_UNIFORM_NAME = 'uSceneDepthMap';\\nclass RenderPassPrepass extends RenderPass {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tsuper.destroy();\\n\\t\\t\\t\\tthis.renderTarget?.destroy();\\n\\t\\t\\t\\tthis.renderTarget = null;\\n\\t\\t\\t\\tthis.linearDepthTexture?.destroy();\\n\\t\\t\\t\\tthis.linearDepthTexture = null;\\n\\t\\t\\t\\tthis.viewBindGroups.forEach((bg)=>{\\n\\t\\t\\t\\t\\t\\tbg.defaultUniformBuffer.destroy();\\n\\t\\t\\t\\t\\t\\tbg.destroy();\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.viewBindGroups.length = 0;\\n\\t\\t}\\n\\t\\tsetupRenderTarget(options) {\\n\\t\\t\\t\\tconst { device } = this;\\n\\t\\t\\t\\tthis.linearDepthFormat = device.textureFloatRenderable ? PIXELFORMAT_R32F : PIXELFORMAT_RGBA8;\\n\\t\\t\\t\\tthis.linearDepthTexture = new Texture(device, {\\n\\t\\t\\t\\t\\t\\tname: 'SceneLinearDepthTexture',\\n\\t\\t\\t\\t\\t\\twidth: 1,\\n\\t\\t\\t\\t\\t\\theight: 1,\\n\\t\\t\\t\\t\\t\\tformat: this.linearDepthFormat,\\n\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst renderTarget = new RenderTarget({\\n\\t\\t\\t\\t\\t\\tname: 'PrepassRT',\\n\\t\\t\\t\\t\\t\\tcolorBuffer: this.linearDepthTexture,\\n\\t\\t\\t\\t\\t\\tdepth: true,\\n\\t\\t\\t\\t\\t\\tsamples: 1\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tthis.camera.shaderParams.sceneDepthMapLinear = true;\\n\\t\\t\\t\\tthis.init(renderTarget, options);\\n\\t\\t}\\n\\t\\tafter() {\\n\\t\\t\\t\\tthis.device.scope.resolve(DEPTH_UNIFORM_NAME).setValue(this.linearDepthTexture);\\n\\t\\t}\\n\\t\\texecute() {\\n\\t\\t\\t\\tconst { renderer, scene, renderTarget } = this;\\n\\t\\t\\t\\tconst camera = this.camera.camera;\\n\\t\\t\\t\\tconst layers = scene.layers.layerList;\\n\\t\\t\\t\\tconst subLayerEnabled = scene.layers.subLayerEnabled;\\n\\t\\t\\t\\tconst isTransparent = scene.layers.subLayerList;\\n\\t\\t\\t\\tfor(let i = 0; i < layers.length; i++){\\n\\t\\t\\t\\t\\t\\tconst layer = layers[i];\\n\\t\\t\\t\\t\\t\\tif (layer.id === LAYERID_DEPTH) {\\n\\t\\t\\t\\t\\t\\t\\t\\tbreak;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (layer.enabled && subLayerEnabled[i]) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (layer.camerasSet.has(camera)) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst culledInstances = layer.getCulledInstances(camera);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst meshInstances = isTransparent[i] ? culledInstances.transparent : culledInstances.opaque;\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tfor(let j = 0; j < meshInstances.length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tconst meshInstance = meshInstances[j];\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tif (meshInstance.material?.depthWrite) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttempMeshInstances.push(meshInstance);\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\trenderer.renderForwardLayer(camera, renderTarget, null, undefined, SHADER_PREPASS, this.viewBindGroups, {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tmeshInstances: tempMeshInstances\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\ttempMeshInstances.length = 0;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tframeUpdate() {\\n\\t\\t\\t\\tsuper.frameUpdate();\\n\\t\\t\\t\\tconst { camera } = this;\\n\\t\\t\\t\\tthis.setClearDepth(camera.clearDepthBuffer ? 1 : undefined);\\n\\t\\t\\t\\tlet clearValue;\\n\\t\\t\\t\\tif (camera.clearDepthBuffer) {\\n\\t\\t\\t\\t\\t\\tconst farClip = camera.farClip - Number.MIN_VALUE;\\n\\t\\t\\t\\t\\t\\tclearValue = this.linearDepthClearValue;\\n\\t\\t\\t\\t\\t\\tif (this.linearDepthFormat === PIXELFORMAT_R32F) {\\n\\t\\t\\t\\t\\t\\t\\t\\tclearValue.r = farClip;\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tFloatPacking.float2RGBA8(farClip, clearValue);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.setClearColor(clearValue);\\n\\t\\t}\\n\\t\\tconstructor(device, scene, renderer, camera, options){\\n\\t\\t\\t\\tsuper(device), this.viewBindGroups = [], this.linearDepthClearValue = new Color(0, 0, 0, 0);\\n\\t\\t\\t\\tthis.scene = scene;\\n\\t\\t\\t\\tthis.renderer = renderer;\\n\\t\\t\\t\\tthis.camera = camera;\\n\\t\\t\\t\\tthis.setupRenderTarget(options);\\n\\t\\t}\\n}\\n\\nvar glslDepthAwareBlurPS = `\\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 wgslDepthAwareBlurPS = `\\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\\t\\texecute() {\\n\\t\\t\\t\\tthis.filterSizeId.setValue(4);\\n\\t\\t\\t\\tthis.sourceTextureId.setValue(this.sourceTexture);\\n\\t\\t\\t\\tconst { width, height } = this.sourceTexture;\\n\\t\\t\\t\\tthis.sourceInvResolutionValue[0] = 1.0 / width;\\n\\t\\t\\t\\tthis.sourceInvResolutionValue[1] = 1.0 / height;\\n\\t\\t\\t\\tthis.sourceInvResolutionId.setValue(this.sourceInvResolutionValue);\\n\\t\\t\\t\\tsuper.execute();\\n\\t\\t}\\n\\t\\tconstructor(device, sourceTexture, cameraComponent, horizontal){\\n\\t\\t\\t\\tsuper(device);\\n\\t\\t\\t\\tthis.sourceTexture = sourceTexture;\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set('depthAwareBlurPS', glslDepthAwareBlurPS);\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set('depthAwareBlurPS', wgslDepthAwareBlurPS);\\n\\t\\t\\t\\tconst defines = new Map();\\n\\t\\t\\t\\tif (horizontal) defines.set('HORIZONTAL', '');\\n\\t\\t\\t\\tShaderUtils.addScreenDepthChunkDefines(device, cameraComponent.shaderParams, defines);\\n\\t\\t\\t\\tthis.shader = ShaderUtils.createShader(device, {\\n\\t\\t\\t\\t\\t\\tuniqueName: `DepthAware${horizontal ? 'Horizontal' : 'Vertical'}BlurShader`,\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\taPosition: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tvertexChunk: 'quadVS',\\n\\t\\t\\t\\t\\t\\tfragmentChunk: 'depthAwareBlurPS',\\n\\t\\t\\t\\t\\t\\tfragmentDefines: defines\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst scope = this.device.scope;\\n\\t\\t\\t\\tthis.sourceTextureId = scope.resolve('sourceTexture');\\n\\t\\t\\t\\tthis.sourceInvResolutionId = scope.resolve('sourceInvResolution');\\n\\t\\t\\t\\tthis.sourceInvResolutionValue = new Float32Array(2);\\n\\t\\t\\t\\tthis.filterSizeId = scope.resolve('filterSize');\\n\\t\\t}\\n}\\n\\nvar glslSsaoPS = `\\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 wgslSsaoPS = `\\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\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.renderTarget?.destroyTextureBuffers();\\n\\t\\t\\t\\tthis.renderTarget?.destroy();\\n\\t\\t\\t\\tthis.renderTarget = null;\\n\\t\\t\\t\\tif (this.afterPasses.length > 0) {\\n\\t\\t\\t\\t\\t\\tconst blurRt = this.afterPasses[0].renderTarget;\\n\\t\\t\\t\\t\\t\\tblurRt?.destroyTextureBuffers();\\n\\t\\t\\t\\t\\t\\tblurRt?.destroy();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.afterPasses.forEach((pass)=>pass.destroy());\\n\\t\\t\\t\\tthis.afterPasses.length = 0;\\n\\t\\t\\t\\tsuper.destroy();\\n\\t\\t}\\n\\t\\tset scale(value) {\\n\\t\\t\\t\\tthis._scale = value;\\n\\t\\t\\t\\tthis.scaleX = value;\\n\\t\\t\\t\\tthis.scaleY = value;\\n\\t\\t}\\n\\t\\tget scale() {\\n\\t\\t\\t\\treturn this._scale;\\n\\t\\t}\\n\\t\\tcreateRenderTarget(name) {\\n\\t\\t\\t\\treturn new RenderTarget({\\n\\t\\t\\t\\t\\t\\tdepth: false,\\n\\t\\t\\t\\t\\t\\tcolorBuffer: new Texture(this.device, {\\n\\t\\t\\t\\t\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\t\\t\\t\\t\\twidth: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\theight: 1,\\n\\t\\t\\t\\t\\t\\t\\t\\tformat: PIXELFORMAT_R8,\\n\\t\\t\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\t\\t\\tminFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\t\\t\\tmagFilter: FILTER_NEAREST,\\n\\t\\t\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t\\t\\t\\t\\t})\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\texecute() {\\n\\t\\t\\t\\tconst { device, sourceTexture, sampleCount, minAngle, scale } = this;\\n\\t\\t\\t\\tconst { width, height } = this.renderTarget.colorBuffer;\\n\\t\\t\\t\\tconst scope = device.scope;\\n\\t\\t\\t\\tscope.resolve('uAspect').setValue(width / height);\\n\\t\\t\\t\\tscope.resolve('uInvResolution').setValue([\\n\\t\\t\\t\\t\\t\\t1.0 / width,\\n\\t\\t\\t\\t\\t\\t1.0 / height\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tscope.resolve('uSampleCount').setValue([\\n\\t\\t\\t\\t\\t\\tsampleCount,\\n\\t\\t\\t\\t\\t\\t1.0 / sampleCount\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tconst minAngleSin = Math.sin(minAngle * math.DEG_TO_RAD);\\n\\t\\t\\t\\tscope.resolve('uMinHorizonAngleSineSquared').setValue(minAngleSin * minAngleSin);\\n\\t\\t\\t\\tconst spiralTurns = 10.0;\\n\\t\\t\\t\\tconst step = 1.0 / (sampleCount - 0.5) * spiralTurns * 2.0 * 3.141;\\n\\t\\t\\t\\tconst radius = this.radius / scale;\\n\\t\\t\\t\\tconst bias = 0.001;\\n\\t\\t\\t\\tconst peak = 0.1 * radius;\\n\\t\\t\\t\\tconst intensity = 2 * (peak * 2.0 * 3.141) * this.intensity / sampleCount;\\n\\t\\t\\t\\tconst projectionScale = 0.5 * sourceTexture.height;\\n\\t\\t\\t\\tscope.resolve('uSpiralTurns').setValue(spiralTurns);\\n\\t\\t\\t\\tscope.resolve('uAngleIncCosSin').setValue([\\n\\t\\t\\t\\t\\t\\tMath.cos(step),\\n\\t\\t\\t\\t\\t\\tMath.sin(step)\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tscope.resolve('uMaxLevel').setValue(0.0);\\n\\t\\t\\t\\tscope.resolve('uInvRadiusSquared').setValue(1.0 / (radius * radius));\\n\\t\\t\\t\\tscope.resolve('uBias').setValue(bias);\\n\\t\\t\\t\\tscope.resolve('uPeak2').setValue(peak * peak);\\n\\t\\t\\t\\tscope.resolve('uIntensity').setValue(intensity);\\n\\t\\t\\t\\tscope.resolve('uPower').setValue(this.power);\\n\\t\\t\\t\\tscope.resolve('uProjectionScaleRadius').setValue(projectionScale * radius);\\n\\t\\t\\t\\tscope.resolve('uRandomize').setValue(this.randomize ? this._blueNoise.value() : 0);\\n\\t\\t\\t\\tsuper.execute();\\n\\t\\t}\\n\\t\\tafter() {\\n\\t\\t\\t\\tthis.ssaoTextureId.setValue(this.ssaoTexture);\\n\\t\\t\\t\\tconst srcTexture = this.sourceTexture;\\n\\t\\t\\t\\tthis.ssaoTextureSizeInvId.setValue([\\n\\t\\t\\t\\t\\t\\t1.0 / srcTexture.width,\\n\\t\\t\\t\\t\\t\\t1.0 / srcTexture.height\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\tconstructor(device, sourceTexture, cameraComponent, blurEnabled){\\n\\t\\t\\t\\tsuper(device), this.radius = 5, this.intensity = 1, this.power = 1, this.sampleCount = 10, this.minAngle = 5, this.randomize = false, this._scale = 1, this._blueNoise = new BlueNoise(19);\\n\\t\\t\\t\\tthis.sourceTexture = sourceTexture;\\n\\t\\t\\t\\tthis.cameraComponent = cameraComponent;\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_GLSL).set('ssaoPS', glslSsaoPS);\\n\\t\\t\\t\\tShaderChunks.get(device, SHADERLANGUAGE_WGSL).set('ssaoPS', wgslSsaoPS);\\n\\t\\t\\t\\tconst defines = new Map();\\n\\t\\t\\t\\tShaderUtils.addScreenDepthChunkDefines(device, cameraComponent.shaderParams, defines);\\n\\t\\t\\t\\tthis.shader = ShaderUtils.createShader(device, {\\n\\t\\t\\t\\t\\t\\tuniqueName: 'SsaoShader',\\n\\t\\t\\t\\t\\t\\tattributes: {\\n\\t\\t\\t\\t\\t\\t\\t\\taPosition: SEMANTIC_POSITION\\n\\t\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t\\tvertexChunk: 'quadVS',\\n\\t\\t\\t\\t\\t\\tfragmentChunk: 'ssaoPS',\\n\\t\\t\\t\\t\\t\\tfragmentDefines: defines\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst rt = this.createRenderTarget('SsaoFinalTexture');\\n\\t\\t\\t\\tthis.ssaoTexture = rt.colorBuffer;\\n\\t\\t\\t\\tthis.init(rt, {\\n\\t\\t\\t\\t\\t\\tresizeSource: this.sourceTexture\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tconst clearColor = new Color(0, 0, 0, 0);\\n\\t\\t\\t\\tthis.setClearColor(clearColor);\\n\\t\\t\\t\\tif (blurEnabled) {\\n\\t\\t\\t\\t\\t\\tconst blurRT = this.createRenderTarget('SsaoTempTexture');\\n\\t\\t\\t\\t\\t\\tconst blurPassHorizontal = new RenderPassDepthAwareBlur(device, rt.colorBuffer, cameraComponent, true);\\n\\t\\t\\t\\t\\t\\tblurPassHorizontal.init(blurRT, {\\n\\t\\t\\t\\t\\t\\t\\t\\tresizeSource: rt.colorBuffer\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tblurPassHorizontal.setClearColor(clearColor);\\n\\t\\t\\t\\t\\t\\tconst blurPassVertical = new RenderPassDepthAwareBlur(device, blurRT.colorBuffer, cameraComponent, false);\\n\\t\\t\\t\\t\\t\\tblurPassVertical.init(rt, {\\n\\t\\t\\t\\t\\t\\t\\t\\tresizeSource: rt.colorBuffer\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tblurPassVertical.setClearColor(clearColor);\\n\\t\\t\\t\\t\\t\\tthis.afterPasses.push(blurPassHorizontal);\\n\\t\\t\\t\\t\\t\\tthis.afterPasses.push(blurPassVertical);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.ssaoTextureId = device.scope.resolve('ssaoTexture');\\n\\t\\t\\t\\tthis.ssaoTextureSizeInvId = device.scope.resolve('ssaoTextureSizeInv');\\n\\t\\t}\\n}\\n\\nclass CameraFrameOptions {\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tthis.stencil = false;\\n\\t\\t\\t\\tthis.samples = 1;\\n\\t\\t\\t\\tthis.sceneColorMap = false;\\n\\t\\t\\t\\tthis.lastGrabLayerId = LAYERID_SKYBOX;\\n\\t\\t\\t\\tthis.lastGrabLayerIsTransparent = false;\\n\\t\\t\\t\\tthis.lastSceneLayerId = LAYERID_IMMEDIATE;\\n\\t\\t\\t\\tthis.lastSceneLayerIsTransparent = true;\\n\\t\\t\\t\\tthis.taaEnabled = false;\\n\\t\\t\\t\\tthis.bloomEnabled = false;\\n\\t\\t\\t\\tthis.ssaoType = SSAOTYPE_NONE;\\n\\t\\t\\t\\tthis.ssaoBlurEnabled = true;\\n\\t\\t\\t\\tthis.prepassEnabled = false;\\n\\t\\t\\t\\tthis.dofEnabled = false;\\n\\t\\t\\t\\tthis.dofNearBlur = false;\\n\\t\\t\\t\\tthis.dofHighQuality = true;\\n\\t\\t}\\n}\\nconst _defaultOptions = new CameraFrameOptions();\\nclass RenderPassCameraFrame extends RenderPass {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.reset();\\n\\t\\t}\\n\\t\\treset() {\\n\\t\\t\\t\\tthis.sceneTexture = null;\\n\\t\\t\\t\\tthis.sceneTextureHalf = null;\\n\\t\\t\\t\\tif (this.rt) {\\n\\t\\t\\t\\t\\t\\tthis.rt.destroyTextureBuffers();\\n\\t\\t\\t\\t\\t\\tthis.rt.destroy();\\n\\t\\t\\t\\t\\t\\tthis.rt = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this.rtHalf) {\\n\\t\\t\\t\\t\\t\\tthis.rtHalf.destroyTextureBuffers();\\n\\t\\t\\t\\t\\t\\tthis.rtHalf.destroy();\\n\\t\\t\\t\\t\\t\\tthis.rtHalf = null;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.beforePasses.forEach((pass)=>pass.destroy());\\n\\t\\t\\t\\tthis.beforePasses.length = 0;\\n\\t\\t\\t\\tthis.prePass = null;\\n\\t\\t\\t\\tthis.scenePass = null;\\n\\t\\t\\t\\tthis.scenePassTransparent = null;\\n\\t\\t\\t\\tthis.colorGrabPass = null;\\n\\t\\t\\t\\tthis.composePass = null;\\n\\t\\t\\t\\tthis.bloomPass = null;\\n\\t\\t\\t\\tthis.ssaoPass = null;\\n\\t\\t\\t\\tthis.taaPass = null;\\n\\t\\t\\t\\tthis.afterPass = null;\\n\\t\\t\\t\\tthis.scenePassHalf = null;\\n\\t\\t\\t\\tthis.dofPass = null;\\n\\t\\t}\\n\\t\\tsanitizeOptions(options) {\\n\\t\\t\\t\\toptions = Object.assign({}, _defaultOptions, options);\\n\\t\\t\\t\\tif (options.taaEnabled || options.ssaoType !== SSAOTYPE_NONE || options.dofEnabled) {\\n\\t\\t\\t\\t\\t\\toptions.prepassEnabled = true;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn options;\\n\\t\\t}\\n\\t\\tset renderTargetScale(value) {\\n\\t\\t\\t\\tthis._renderTargetScale = value;\\n\\t\\t\\t\\tif (this.scenePass) {\\n\\t\\t\\t\\t\\t\\tthis.scenePass.scaleX = value;\\n\\t\\t\\t\\t\\t\\tthis.scenePass.scaleY = value;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget renderTargetScale() {\\n\\t\\t\\t\\treturn this._renderTargetScale;\\n\\t\\t}\\n\\t\\tneedsReset(options) {\\n\\t\\t\\t\\tconst currentOptions = this.options;\\n\\t\\t\\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\\t\\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\\t}\\n\\t\\tupdate(options) {\\n\\t\\t\\t\\toptions = this.sanitizeOptions(options);\\n\\t\\t\\t\\tif (this.needsReset(options) || this.layersDirty) {\\n\\t\\t\\t\\t\\t\\tthis.layersDirty = false;\\n\\t\\t\\t\\t\\t\\tthis.reset();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.options = options;\\n\\t\\t\\t\\tif (!this.sceneTexture) {\\n\\t\\t\\t\\t\\t\\tthis.setupRenderPasses(this.options);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tcreateRenderTarget(name, depth, stencil, samples, flipY) {\\n\\t\\t\\t\\tconst texture = new Texture(this.device, {\\n\\t\\t\\t\\t\\t\\tname: name,\\n\\t\\t\\t\\t\\t\\twidth: 4,\\n\\t\\t\\t\\t\\t\\theight: 4,\\n\\t\\t\\t\\t\\t\\tformat: this.hdrFormat,\\n\\t\\t\\t\\t\\t\\tmipmaps: false,\\n\\t\\t\\t\\t\\t\\tminFilter: FILTER_LINEAR,\\n\\t\\t\\t\\t\\t\\tmagFilter: FILTER_LINEAR,\\n\\t\\t\\t\\t\\t\\taddressU: ADDRESS_CLAMP_TO_EDGE,\\n\\t\\t\\t\\t\\t\\taddressV: ADDRESS_CLAMP_TO_EDGE\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\treturn new RenderTarget({\\n\\t\\t\\t\\t\\t\\tcolorBuffer: texture,\\n\\t\\t\\t\\t\\t\\tdepth: depth,\\n\\t\\t\\t\\t\\t\\tstencil: stencil,\\n\\t\\t\\t\\t\\t\\tsamples: samples,\\n\\t\\t\\t\\t\\t\\tflipY: flipY\\n\\t\\t\\t\\t});\\n\\t\\t}\\n\\t\\tsetupRenderPasses(options) {\\n\\t\\t\\t\\tconst { device } = this;\\n\\t\\t\\t\\tconst cameraComponent = this.cameraComponent;\\n\\t\\t\\t\\tconst targetRenderTarget = cameraComponent.renderTarget;\\n\\t\\t\\t\\tthis.hdrFormat = device.getRenderableHdrFormat(options.formats, true, options.samples) || PIXELFORMAT_RGBA8;\\n\\t\\t\\t\\tthis._bloomEnabled = options.bloomEnabled && this.hdrFormat !== PIXELFORMAT_RGBA8;\\n\\t\\t\\t\\tthis._sceneHalfEnabled = this._bloomEnabled || options.dofEnabled;\\n\\t\\t\\t\\tcameraComponent.shaderParams.ssaoEnabled = options.ssaoType === SSAOTYPE_LIGHTING;\\n\\t\\t\\t\\tconst flipY = !!targetRenderTarget?.flipY;\\n\\t\\t\\t\\tthis.rt = this.createRenderTarget('SceneColor', true, options.stencil, options.samples, flipY);\\n\\t\\t\\t\\tthis.sceneTexture = this.rt.colorBuffer;\\n\\t\\t\\t\\tif (this._sceneHalfEnabled) {\\n\\t\\t\\t\\t\\t\\tthis.rtHalf = this.createRenderTarget('SceneColorHalf', false, false, 1, flipY);\\n\\t\\t\\t\\t\\t\\tthis.sceneTextureHalf = this.rtHalf.colorBuffer;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.sceneOptions = {\\n\\t\\t\\t\\t\\t\\tresizeSource: targetRenderTarget,\\n\\t\\t\\t\\t\\t\\tscaleX: this.renderTargetScale,\\n\\t\\t\\t\\t\\t\\tscaleY: this.renderTargetScale\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.createPasses(options);\\n\\t\\t\\t\\tconst allPasses = this.collectPasses();\\n\\t\\t\\t\\tthis.beforePasses = allPasses.filter((element)=>element !== undefined && element !== null);\\n\\t\\t}\\n\\t\\tcollectPasses() {\\n\\t\\t\\t\\treturn [\\n\\t\\t\\t\\t\\t\\tthis.prePass,\\n\\t\\t\\t\\t\\t\\tthis.ssaoPass,\\n\\t\\t\\t\\t\\t\\tthis.scenePass,\\n\\t\\t\\t\\t\\t\\tthis.colorGrabPass,\\n\\t\\t\\t\\t\\t\\tthis.scenePassTransparent,\\n\\t\\t\\t\\t\\t\\tthis.taaPass,\\n\\t\\t\\t\\t\\t\\tthis.scenePassHalf,\\n\\t\\t\\t\\t\\t\\tthis.bloomPass,\\n\\t\\t\\t\\t\\t\\tthis.dofPass,\\n\\t\\t\\t\\t\\t\\tthis.composePass,\\n\\t\\t\\t\\t\\t\\tthis.afterPass\\n\\t\\t\\t\\t];\\n\\t\\t}\\n\\t\\tcreatePasses(options) {\\n\\t\\t\\t\\tthis.setupScenePrepass(options);\\n\\t\\t\\t\\tthis.setupSsaoPass(options);\\n\\t\\t\\t\\tconst scenePassesInfo = this.setupScenePass(options);\\n\\t\\t\\t\\tconst sceneTextureWithTaa = this.setupTaaPass(options);\\n\\t\\t\\t\\tthis.setupSceneHalfPass(options, sceneTextureWithTaa);\\n\\t\\t\\t\\tthis.setupBloomPass(options, this.sceneTextureHalf);\\n\\t\\t\\t\\tthis.setupDofPass(options, this.sceneTexture, this.sceneTextureHalf);\\n\\t\\t\\t\\tthis.setupComposePass(options);\\n\\t\\t\\t\\tthis.setupAfterPass(options, scenePassesInfo);\\n\\t\\t}\\n\\t\\tsetupScenePrepass(options) {\\n\\t\\t\\t\\tif (options.prepassEnabled) {\\n\\t\\t\\t\\t\\t\\tconst { app, device, cameraComponent } = this;\\n\\t\\t\\t\\t\\t\\tconst { scene, renderer } = app;\\n\\t\\t\\t\\t\\t\\tthis.prePass = new RenderPassPrepass(device, scene, renderer, cameraComponent, this.sceneOptions);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetupScenePassSettings(pass) {\\n\\t\\t\\t\\tpass.gammaCorrection = GAMMA_NONE;\\n\\t\\t\\t\\tpass.toneMapping = TONEMAP_NONE;\\n\\t\\t}\\n\\t\\tsetupScenePass(options) {\\n\\t\\t\\t\\tconst { app, device, cameraComponent } = this;\\n\\t\\t\\t\\tconst { scene, renderer } = app;\\n\\t\\t\\t\\tconst composition = scene.layers;\\n\\t\\t\\t\\tthis.scenePass = new RenderPassForward(device, composition, scene, renderer);\\n\\t\\t\\t\\tthis.setupScenePassSettings(this.scenePass);\\n\\t\\t\\t\\tthis.scenePass.init(this.rt, this.sceneOptions);\\n\\t\\t\\t\\tconst lastLayerId = options.sceneColorMap ? options.lastGrabLayerId : options.lastSceneLayerId;\\n\\t\\t\\t\\tconst lastLayerIsTransparent = options.sceneColorMap ? options.lastGrabLayerIsTransparent : options.lastSceneLayerIsTransparent;\\n\\t\\t\\t\\tconst ret = {\\n\\t\\t\\t\\t\\t\\tlastAddedIndex: 0,\\n\\t\\t\\t\\t\\t\\tclearRenderTarget: true\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tret.lastAddedIndex = this.scenePass.addLayers(composition, cameraComponent, ret.lastAddedIndex, ret.clearRenderTarget, lastLayerId, lastLayerIsTransparent);\\n\\t\\t\\t\\tret.clearRenderTarget = false;\\n\\t\\t\\t\\tif (options.sceneColorMap) {\\n\\t\\t\\t\\t\\t\\tthis.colorGrabPass = new RenderPassColorGrab(device);\\n\\t\\t\\t\\t\\t\\tthis.colorGrabPass.source = this.rt;\\n\\t\\t\\t\\t\\t\\tthis.scenePassTransparent = new RenderPassForward(device, composition, scene, renderer);\\n\\t\\t\\t\\t\\t\\tthis.setupScenePassSettings(this.scenePassTransparent);\\n\\t\\t\\t\\t\\t\\tthis.scenePassTransparent.init(this.rt);\\n\\t\\t\\t\\t\\t\\tret.lastAddedIndex = this.scenePassTransparent.addLayers(composition, cameraComponent, ret.lastAddedIndex, ret.clearRenderTarget, options.lastSceneLayerId, options.lastSceneLayerIsTransparent);\\n\\t\\t\\t\\t\\t\\tif (!this.scenePassTransparent.rendersAnything) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.scenePassTransparent.destroy();\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.scenePassTransparent = null;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (this.scenePassTransparent) {\\n\\t\\t\\t\\t\\t\\t\\t\\tif (options.prepassEnabled) {\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis.scenePassTransparent.depthStencilOps.storeDepth = true;\\n\\t\\t\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn ret;\\n\\t\\t}\\n\\t\\tsetupSsaoPass(options) {\\n\\t\\t\\t\\tconst { ssaoBlurEnabled, ssaoType } = options;\\n\\t\\t\\t\\tconst { device, cameraComponent } = this;\\n\\t\\t\\t\\tif (ssaoType !== SSAOTYPE_NONE) {\\n\\t\\t\\t\\t\\t\\tthis.ssaoPass = new RenderPassSsao(device, this.sceneTexture, cameraComponent, ssaoBlurEnabled);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetupSceneHalfPass(options, sourceTexture) {\\n\\t\\t\\t\\tif (this._sceneHalfEnabled) {\\n\\t\\t\\t\\t\\t\\tthis.scenePassHalf = new RenderPassDownsample(this.device, this.sceneTexture, {\\n\\t\\t\\t\\t\\t\\t\\t\\tboxFilter: true,\\n\\t\\t\\t\\t\\t\\t\\t\\tremoveInvalid: true\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tthis.scenePassHalf.name = 'RenderPassSceneHalf';\\n\\t\\t\\t\\t\\t\\tthis.scenePassHalf.init(this.rtHalf, {\\n\\t\\t\\t\\t\\t\\t\\t\\tresizeSource: sourceTexture,\\n\\t\\t\\t\\t\\t\\t\\t\\tscaleX: 0.5,\\n\\t\\t\\t\\t\\t\\t\\t\\tscaleY: 0.5\\n\\t\\t\\t\\t\\t\\t});\\n\\t\\t\\t\\t\\t\\tthis.scenePassHalf.setClearColor(Color.BLACK);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetupBloomPass(options, inputTexture) {\\n\\t\\t\\t\\tif (this._bloomEnabled) {\\n\\t\\t\\t\\t\\t\\tthis.bloomPass = new RenderPassBloom(this.device, inputTexture, this.hdrFormat);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetupDofPass(options, inputTexture, inputTextureHalf) {\\n\\t\\t\\t\\tif (options.dofEnabled) {\\n\\t\\t\\t\\t\\t\\tthis.dofPass = new RenderPassDof(this.device, this.cameraComponent, inputTexture, inputTextureHalf, options.dofHighQuality, options.dofNearBlur);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tsetupTaaPass(options) {\\n\\t\\t\\t\\tlet textureWithTaa = this.sceneTexture;\\n\\t\\t\\t\\tif (options.taaEnabled) {\\n\\t\\t\\t\\t\\t\\tthis.taaPass = new RenderPassTAA(this.device, this.sceneTexture, this.cameraComponent);\\n\\t\\t\\t\\t\\t\\ttextureWithTaa = this.taaPass.historyTexture;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn textureWithTaa;\\n\\t\\t}\\n\\t\\tsetupComposePass(options) {\\n\\t\\t\\t\\tthis.composePass = new RenderPassCompose(this.device);\\n\\t\\t\\t\\tthis.composePass.bloomTexture = this.bloomPass?.bloomTexture;\\n\\t\\t\\t\\tthis.composePass.taaEnabled = options.taaEnabled;\\n\\t\\t\\t\\tthis.composePass.cocTexture = this.dofPass?.cocTexture;\\n\\t\\t\\t\\tthis.composePass.blurTexture = this.dofPass?.blurTexture;\\n\\t\\t\\t\\tthis.composePass.blurTextureUpscale = !this.dofPass?.highQuality;\\n\\t\\t\\t\\tconst cameraComponent = this.cameraComponent;\\n\\t\\t\\t\\tconst targetRenderTarget = cameraComponent.renderTarget;\\n\\t\\t\\t\\tthis.composePass.init(targetRenderTarget);\\n\\t\\t\\t\\tthis.composePass.ssaoTexture = options.ssaoType === SSAOTYPE_COMBINE ? this.ssaoPass.ssaoTexture : null;\\n\\t\\t}\\n\\t\\tsetupAfterPass(options, scenePassesInfo) {\\n\\t\\t\\t\\tconst { app, cameraComponent } = this;\\n\\t\\t\\t\\tconst { scene, renderer } = app;\\n\\t\\t\\t\\tconst composition = scene.layers;\\n\\t\\t\\t\\tconst targetRenderTarget = cameraComponent.renderTarget;\\n\\t\\t\\t\\tthis.afterPass = new RenderPassForward(this.device, composition, scene, renderer);\\n\\t\\t\\t\\tthis.afterPass.init(targetRenderTarget);\\n\\t\\t\\t\\tthis.afterPass.addLayers(composition, cameraComponent, scenePassesInfo.lastAddedIndex, scenePassesInfo.clearRenderTarget);\\n\\t\\t}\\n\\t\\tframeUpdate() {\\n\\t\\t\\t\\tif (this.layersDirty) {\\n\\t\\t\\t\\t\\t\\tthis.cameraFrame.update();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tsuper.frameUpdate();\\n\\t\\t\\t\\tconst sceneTexture = this.taaPass?.update() ?? this.rt.colorBuffer;\\n\\t\\t\\t\\tthis.composePass.sceneTexture = sceneTexture;\\n\\t\\t\\t\\tthis.scenePassHalf?.setSourceTexture(sceneTexture);\\n\\t\\t}\\n\\t\\tconstructor(app, cameraFrame, cameraComponent, options = {}){\\n\\t\\t\\t\\tsuper(app.graphicsDevice), this._renderTargetScale = 1, this.layersDirty = false, this.rt = null;\\n\\t\\t\\t\\tthis.app = app;\\n\\t\\t\\t\\tthis.cameraComponent = cameraComponent;\\n\\t\\t\\t\\tthis.cameraFrame = cameraFrame;\\n\\t\\t\\t\\tthis.options = this.sanitizeOptions(options);\\n\\t\\t\\t\\tthis.setupRenderPasses(this.options);\\n\\t\\t}\\n}\\n\\nclass CameraFrame {\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.disable();\\n\\t\\t\\t\\tthis.cameraLayersChanged.off();\\n\\t\\t}\\n\\t\\tenable() {\\n\\t\\t\\t\\tthis.renderPassCamera = this.createRenderPass();\\n\\t\\t\\t\\tthis.cameraComponent.renderPasses = [\\n\\t\\t\\t\\t\\t\\tthis.renderPassCamera\\n\\t\\t\\t\\t];\\n\\t\\t}\\n\\t\\tdisable() {\\n\\t\\t\\t\\tconst cameraComponent = this.cameraComponent;\\n\\t\\t\\t\\tcameraComponent.renderPasses?.forEach((renderPass)=>{\\n\\t\\t\\t\\t\\t\\trenderPass.destroy();\\n\\t\\t\\t\\t});\\n\\t\\t\\t\\tcameraComponent.renderPasses = [];\\n\\t\\t\\t\\tcameraComponent.rendering = null;\\n\\t\\t\\t\\tcameraComponent.jitter = 0;\\n\\t\\t\\t\\tcameraComponent.shaderParams.ssaoEnabled = false;\\n\\t\\t\\t\\tthis.renderPassCamera = null;\\n\\t\\t}\\n\\t\\tcreateRenderPass() {\\n\\t\\t\\t\\treturn new RenderPassCameraFrame(this.app, this, this.cameraComponent, this.options);\\n\\t\\t}\\n\\t\\tset enabled(value) {\\n\\t\\t\\t\\tif (this._enabled !== value) {\\n\\t\\t\\t\\t\\t\\tif (value) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.enable();\\n\\t\\t\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.disable();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._enabled = value;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tget enabled() {\\n\\t\\t\\t\\treturn this._enabled;\\n\\t\\t}\\n\\t\\tupdateOptions() {\\n\\t\\t\\t\\tconst { options, rendering, bloom, taa, ssao } = this;\\n\\t\\t\\t\\toptions.stencil = rendering.stencil;\\n\\t\\t\\t\\toptions.samples = rendering.samples;\\n\\t\\t\\t\\toptions.sceneColorMap = rendering.sceneColorMap;\\n\\t\\t\\t\\toptions.prepassEnabled = rendering.sceneDepthMap;\\n\\t\\t\\t\\toptions.bloomEnabled = bloom.intensity > 0;\\n\\t\\t\\t\\toptions.taaEnabled = taa.enabled;\\n\\t\\t\\t\\toptions.ssaoType = ssao.type;\\n\\t\\t\\t\\toptions.ssaoBlurEnabled = ssao.blurEnabled;\\n\\t\\t\\t\\toptions.formats = rendering.renderFormats.slice();\\n\\t\\t\\t\\toptions.dofEnabled = this.dof.enabled;\\n\\t\\t\\t\\toptions.dofNearBlur = this.dof.nearBlur;\\n\\t\\t\\t\\toptions.dofHighQuality = this.dof.highQuality;\\n\\t\\t}\\n\\t\\tupdate() {\\n\\t\\t\\t\\tif (!this._enabled) return;\\n\\t\\t\\t\\tconst cameraComponent = this.cameraComponent;\\n\\t\\t\\t\\tconst { options, renderPassCamera, rendering, bloom, grading, vignette, fringing, taa, ssao } = this;\\n\\t\\t\\t\\tthis.updateOptions();\\n\\t\\t\\t\\trenderPassCamera.update(options);\\n\\t\\t\\t\\tconst { composePass, bloomPass, ssaoPass, dofPass } = renderPassCamera;\\n\\t\\t\\t\\trenderPassCamera.renderTargetScale = math.clamp(rendering.renderTargetScale, 0.1, 1);\\n\\t\\t\\t\\tcomposePass.toneMapping = rendering.toneMapping;\\n\\t\\t\\t\\tcomposePass.sharpness = rendering.sharpness;\\n\\t\\t\\t\\tif (options.bloomEnabled && bloomPass) {\\n\\t\\t\\t\\t\\t\\tcomposePass.bloomIntensity = bloom.intensity;\\n\\t\\t\\t\\t\\t\\tbloomPass.blurLevel = bloom.blurLevel;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.dofEnabled) {\\n\\t\\t\\t\\t\\t\\tdofPass.focusDistance = this.dof.focusDistance;\\n\\t\\t\\t\\t\\t\\tdofPass.focusRange = this.dof.focusRange;\\n\\t\\t\\t\\t\\t\\tdofPass.blurRadius = this.dof.blurRadius;\\n\\t\\t\\t\\t\\t\\tdofPass.blurRings = this.dof.blurRings;\\n\\t\\t\\t\\t\\t\\tdofPass.blurRingPoints = this.dof.blurRingPoints;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (options.ssaoType !== SSAOTYPE_NONE) {\\n\\t\\t\\t\\t\\t\\tssaoPass.intensity = ssao.intensity;\\n\\t\\t\\t\\t\\t\\tssaoPass.power = ssao.power;\\n\\t\\t\\t\\t\\t\\tssaoPass.radius = ssao.radius;\\n\\t\\t\\t\\t\\t\\tssaoPass.sampleCount = ssao.samples;\\n\\t\\t\\t\\t\\t\\tssaoPass.minAngle = ssao.minAngle;\\n\\t\\t\\t\\t\\t\\tssaoPass.scale = ssao.scale;\\n\\t\\t\\t\\t\\t\\tssaoPass.randomize = ssao.randomize;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcomposePass.gradingEnabled = grading.enabled;\\n\\t\\t\\t\\tif (grading.enabled) {\\n\\t\\t\\t\\t\\t\\tcomposePass.gradingSaturation = grading.saturation;\\n\\t\\t\\t\\t\\t\\tcomposePass.gradingBrightness = grading.brightness;\\n\\t\\t\\t\\t\\t\\tcomposePass.gradingContrast = grading.contrast;\\n\\t\\t\\t\\t\\t\\tcomposePass.gradingTint = grading.tint;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcomposePass.colorLUT = this.colorLUT.texture;\\n\\t\\t\\t\\tcomposePass.colorLUTIntensity = this.colorLUT.intensity;\\n\\t\\t\\t\\tcomposePass.vignetteEnabled = vignette.intensity > 0;\\n\\t\\t\\t\\tif (composePass.vignetteEnabled) {\\n\\t\\t\\t\\t\\t\\tcomposePass.vignetteInner = vignette.inner;\\n\\t\\t\\t\\t\\t\\tcomposePass.vignetteOuter = vignette.outer;\\n\\t\\t\\t\\t\\t\\tcomposePass.vignetteCurvature = vignette.curvature;\\n\\t\\t\\t\\t\\t\\tcomposePass.vignetteIntensity = vignette.intensity;\\n\\t\\t\\t\\t\\t\\tcomposePass.vignetteColor.copy(vignette.color);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcomposePass.fringingEnabled = fringing.intensity > 0;\\n\\t\\t\\t\\tif (composePass.fringingEnabled) {\\n\\t\\t\\t\\t\\t\\tcomposePass.fringingIntensity = fringing.intensity;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tcameraComponent.jitter = taa.enabled ? taa.jitter : 0;\\n\\t\\t\\t\\tcomposePass.debug = this.debug;\\n\\t\\t\\t\\tif (composePass.debug === 'ssao' && options.ssaoType === SSAOTYPE_NONE) composePass.debug = null;\\n\\t\\t\\t\\tif (composePass.debug === 'vignette' && !composePass.vignetteEnabled) composePass.debug = null;\\n\\t\\t}\\n\\t\\tconstructor(app, cameraComponent){\\n\\t\\t\\t\\tthis._enabled = true;\\n\\t\\t\\t\\tthis.rendering = {\\n\\t\\t\\t\\t\\t\\trenderFormats: [\\n\\t\\t\\t\\t\\t\\t\\t\\tPIXELFORMAT_111110F,\\n\\t\\t\\t\\t\\t\\t\\t\\tPIXELFORMAT_RGBA16F,\\n\\t\\t\\t\\t\\t\\t\\t\\tPIXELFORMAT_RGBA32F\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\tstencil: false,\\n\\t\\t\\t\\t\\t\\trenderTargetScale: 1.0,\\n\\t\\t\\t\\t\\t\\tsamples: 1,\\n\\t\\t\\t\\t\\t\\tsceneColorMap: false,\\n\\t\\t\\t\\t\\t\\tsceneDepthMap: false,\\n\\t\\t\\t\\t\\t\\ttoneMapping: 0,\\n\\t\\t\\t\\t\\t\\tsharpness: 0.0\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.ssao = {\\n\\t\\t\\t\\t\\t\\ttype: SSAOTYPE_NONE,\\n\\t\\t\\t\\t\\t\\tblurEnabled: true,\\n\\t\\t\\t\\t\\t\\trandomize: false,\\n\\t\\t\\t\\t\\t\\tintensity: 0.5,\\n\\t\\t\\t\\t\\t\\tradius: 30,\\n\\t\\t\\t\\t\\t\\tsamples: 12,\\n\\t\\t\\t\\t\\t\\tpower: 6,\\n\\t\\t\\t\\t\\t\\tminAngle: 10,\\n\\t\\t\\t\\t\\t\\tscale: 1\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.bloom = {\\n\\t\\t\\t\\t\\t\\tintensity: 0,\\n\\t\\t\\t\\t\\t\\tblurLevel: 16\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.grading = {\\n\\t\\t\\t\\t\\t\\tenabled: false,\\n\\t\\t\\t\\t\\t\\tbrightness: 1,\\n\\t\\t\\t\\t\\t\\tcontrast: 1,\\n\\t\\t\\t\\t\\t\\tsaturation: 1,\\n\\t\\t\\t\\t\\t\\ttint: new Color(1, 1, 1, 1)\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.colorLUT = {\\n\\t\\t\\t\\t\\t\\ttexture: null,\\n\\t\\t\\t\\t\\t\\tintensity: 1\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.vignette = {\\n\\t\\t\\t\\t\\t\\tintensity: 0,\\n\\t\\t\\t\\t\\t\\tinner: 0.5,\\n\\t\\t\\t\\t\\t\\touter: 1,\\n\\t\\t\\t\\t\\t\\tcurvature: 0.5,\\n\\t\\t\\t\\t\\t\\tcolor: new Color(0, 0, 0)\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.taa = {\\n\\t\\t\\t\\t\\t\\tenabled: false,\\n\\t\\t\\t\\t\\t\\tjitter: 1\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.fringing = {\\n\\t\\t\\t\\t\\t\\tintensity: 0\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.dof = {\\n\\t\\t\\t\\t\\t\\tenabled: false,\\n\\t\\t\\t\\t\\t\\tnearBlur: false,\\n\\t\\t\\t\\t\\t\\tfocusDistance: 100,\\n\\t\\t\\t\\t\\t\\tfocusRange: 10,\\n\\t\\t\\t\\t\\t\\tblurRadius: 3,\\n\\t\\t\\t\\t\\t\\tblurRings: 4,\\n\\t\\t\\t\\t\\t\\tblurRingPoints: 5,\\n\\t\\t\\t\\t\\t\\thighQuality: true\\n\\t\\t\\t\\t};\\n\\t\\t\\t\\tthis.debug = null;\\n\\t\\t\\t\\tthis.options = new CameraFrameOptions();\\n\\t\\t\\t\\tthis.renderPassCamera = null;\\n\\t\\t\\t\\tthis.app = app;\\n\\t\\t\\t\\tthis.cameraComponent = cameraComponent;\\n\\t\\t\\t\\tthis.updateOptions();\\n\\t\\t\\t\\tthis.enable();\\n\\t\\t\\t\\tthis.cameraLayersChanged = cameraComponent.on('set:layers', ()=>{\\n\\t\\t\\t\\t\\t\\tif (this.renderPassCamera) this.renderPassCamera.layersDirty = true;\\n\\t\\t\\t\\t});\\n\\t\\t}\\n}\\n\\nconst tmpV1$1 = new Vec3();\\nconst rotation$3 = new Quat();\\nclass Pose {\\n\\t\\tcopy(other) {\\n\\t\\t\\t\\treturn this.set(other.position, other.angles, other.distance);\\n\\t\\t}\\n\\t\\tclone() {\\n\\t\\t\\t\\treturn new Pose(this.position.clone(), this.angles.clone(), this.distance);\\n\\t\\t}\\n\\t\\tequalsApprox(other, epsilon = 1e-6) {\\n\\t\\t\\t\\treturn this.position.equalsApprox(other.position, epsilon) && this.angles.equalsApprox(other.angles, epsilon) && Math.abs(this.distance - other.distance) < epsilon;\\n\\t\\t}\\n\\t\\tlerp(lhs, rhs, alpha1, alpha2 = alpha1, alpha3 = alpha1) {\\n\\t\\t\\t\\tthis.position.lerp(lhs.position, rhs.position, alpha1);\\n\\t\\t\\t\\tthis.angles.x = math.lerpAngle(lhs.angles.x, rhs.angles.x, alpha2) % 360;\\n\\t\\t\\t\\tthis.angles.y = math.lerpAngle(lhs.angles.y, rhs.angles.y, alpha2) % 360;\\n\\t\\t\\t\\tthis.angles.z = math.lerpAngle(lhs.angles.z, rhs.angles.z, alpha2) % 360;\\n\\t\\t\\t\\tthis.distance = math.lerp(lhs.distance, rhs.distance, alpha3);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tmove(offset) {\\n\\t\\t\\t\\tthis.position.add(offset);\\n\\t\\t\\t\\tthis.position.x = math.clamp(this.position.x, this.xRange.x, this.xRange.y);\\n\\t\\t\\t\\tthis.position.y = math.clamp(this.position.y, this.yRange.x, this.yRange.y);\\n\\t\\t\\t\\tthis.position.z = math.clamp(this.position.z, this.zRange.x, this.zRange.y);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\trotate(euler) {\\n\\t\\t\\t\\tthis.angles.add(euler);\\n\\t\\t\\t\\tthis.angles.x %= 360;\\n\\t\\t\\t\\tthis.angles.y %= 360;\\n\\t\\t\\t\\tthis.angles.z %= 360;\\n\\t\\t\\t\\tthis.angles.x = math.clamp(this.angles.x, this.pitchRange.x, this.pitchRange.y);\\n\\t\\t\\t\\tthis.angles.y = math.clamp(this.angles.y, this.yawRange.x, this.yawRange.y);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tset(position, angles, distance) {\\n\\t\\t\\t\\tthis.position.copy(position);\\n\\t\\t\\t\\tthis.angles.copy(angles);\\n\\t\\t\\t\\tthis.distance = distance;\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tlook(from, to) {\\n\\t\\t\\t\\tthis.position.copy(from);\\n\\t\\t\\t\\tthis.distance = from.distance(to);\\n\\t\\t\\t\\tconst dir = tmpV1$1.sub2(to, from).normalize();\\n\\t\\t\\t\\tconst elev = Math.atan2(-dir.y, Math.sqrt(dir.x * dir.x + dir.z * dir.z)) * math.RAD_TO_DEG;\\n\\t\\t\\t\\tconst azim = Math.atan2(-dir.x, -dir.z) * math.RAD_TO_DEG;\\n\\t\\t\\t\\tthis.angles.set(-elev, azim, 0);\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tgetFocus(out) {\\n\\t\\t\\t\\treturn rotation$3.setFromEulerAngles(this.angles).transformVector(Vec3.FORWARD, out).mulScalar(this.distance).add(this.position);\\n\\t\\t}\\n\\t\\tconstructor(position = Vec3.ZERO, angles = Vec3.ZERO, distance = 0){\\n\\t\\t\\t\\tthis.position = new Vec3();\\n\\t\\t\\t\\tthis.angles = new Vec3();\\n\\t\\t\\t\\tthis.distance = 0;\\n\\t\\t\\t\\tthis.pitchRange = new Vec2(-Infinity, Infinity);\\n\\t\\t\\t\\tthis.yawRange = new Vec2(-Infinity, Infinity);\\n\\t\\t\\t\\tthis.xRange = new Vec2(-Infinity, Infinity);\\n\\t\\t\\t\\tthis.yRange = new Vec2(-Infinity, Infinity);\\n\\t\\t\\t\\tthis.zRange = new Vec2(-Infinity, Infinity);\\n\\t\\t\\t\\tthis.set(position, angles, distance);\\n\\t\\t}\\n}\\n\\nclass InputDelta {\\n\\t\\tadd(other) {\\n\\t\\t\\t\\tfor(let i = 0; i < this._value.length; i++){\\n\\t\\t\\t\\t\\t\\tthis._value[i] += other._value[i] || 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tappend(offsets) {\\n\\t\\t\\t\\tfor(let i = 0; i < this._value.length; i++){\\n\\t\\t\\t\\t\\t\\tthis._value[i] += offsets[i] || 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tcopy(other) {\\n\\t\\t\\t\\tfor(let i = 0; i < this._value.length; i++){\\n\\t\\t\\t\\t\\t\\tthis._value[i] = other._value[i] || 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn this;\\n\\t\\t}\\n\\t\\tlength() {\\n\\t\\t\\t\\tlet sum = 0;\\n\\t\\t\\t\\tfor (const value of this._value){\\n\\t\\t\\t\\t\\t\\tsum += value * value;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn Math.sqrt(sum);\\n\\t\\t}\\n\\t\\tread() {\\n\\t\\t\\t\\tconst value = this._value.slice();\\n\\t\\t\\t\\tthis._value.fill(0);\\n\\t\\t\\t\\treturn value;\\n\\t\\t}\\n\\t\\tconstructor(arg){\\n\\t\\t\\t\\tif (Array.isArray(arg)) {\\n\\t\\t\\t\\t\\t\\tthis._value = arg.slice();\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._value = new Array(+arg).fill(0);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nclass InputFrame {\\n\\t\\tread() {\\n\\t\\t\\t\\tconst frame = {};\\n\\t\\t\\t\\tfor(const name in this.deltas){\\n\\t\\t\\t\\t\\t\\tframe[name] = this.deltas[name].read();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn frame;\\n\\t\\t}\\n\\t\\tconstructor(data){\\n\\t\\t\\t\\tthis.deltas = {};\\n\\t\\t\\t\\tfor(const name in data){\\n\\t\\t\\t\\t\\t\\tthis.deltas[name] = new InputDelta(data[name]);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n}\\nclass InputSource extends InputFrame {\\n\\t\\ton(event, callback) {\\n\\t\\t\\t\\tthis._events.on(event, callback);\\n\\t\\t}\\n\\t\\toff(event, callback) {\\n\\t\\t\\t\\tthis._events.off(event, callback);\\n\\t\\t}\\n\\t\\tfire(event, ...args) {\\n\\t\\t\\t\\tthis._events.fire(event, ...args);\\n\\t\\t}\\n\\t\\tattach(element) {\\n\\t\\t\\t\\tif (this._element) {\\n\\t\\t\\t\\t\\t\\tthis.detach();\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._element = element;\\n\\t\\t}\\n\\t\\tdetach() {\\n\\t\\t\\t\\tif (!this._element) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._element = null;\\n\\t\\t\\t\\tthis.read();\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.detach();\\n\\t\\t\\t\\tthis._events.off();\\n\\t\\t}\\n\\t\\tconstructor(...args){\\n\\t\\t\\t\\tsuper(...args), this._element = null, this._events = new EventHandler();\\n\\t\\t}\\n}\\nclass InputConsumer {\\n\\t\\tupdate(frame, dt) {\\n\\t\\t\\t\\tframe.read();\\n\\t\\t}\\n}\\nlet InputController$1 = class InputController extends InputConsumer {\\n\\t\\tattach(pose, smooth = true) {}\\n\\t\\tdetach() {}\\n\\t\\tupdate(frame, dt) {\\n\\t\\t\\t\\tsuper.update(frame, dt);\\n\\t\\t\\t\\treturn this._pose;\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.detach();\\n\\t\\t}\\n\\t\\tconstructor(...args){\\n\\t\\t\\t\\tsuper(...args), this._pose = new Pose();\\n\\t\\t}\\n};\\n\\nconst movementState = ()=>{\\n\\t\\tconst state = new Map();\\n\\t\\treturn {\\n\\t\\t\\t\\tdown: (event)=>{\\n\\t\\t\\t\\t\\t\\tstate.set(event.pointerId, [\\n\\t\\t\\t\\t\\t\\t\\t\\tevent.screenX,\\n\\t\\t\\t\\t\\t\\t\\t\\tevent.screenY\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\tmove: (event)=>{\\n\\t\\t\\t\\t\\t\\tif (!state.has(event.pointerId)) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn [\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t0,\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst prev = state.get(event.pointerId);\\n\\t\\t\\t\\t\\t\\tconst mvX = event.screenX - prev[0];\\n\\t\\t\\t\\t\\t\\tconst mvY = event.screenY - prev[1];\\n\\t\\t\\t\\t\\t\\tprev[0] = event.screenX;\\n\\t\\t\\t\\t\\t\\tprev[1] = event.screenY;\\n\\t\\t\\t\\t\\t\\treturn [\\n\\t\\t\\t\\t\\t\\t\\t\\tmvX,\\n\\t\\t\\t\\t\\t\\t\\t\\tmvY\\n\\t\\t\\t\\t\\t\\t];\\n\\t\\t\\t\\t},\\n\\t\\t\\t\\tup: (event)=>{\\n\\t\\t\\t\\t\\t\\tstate.delete(event.pointerId);\\n\\t\\t\\t\\t}\\n\\t\\t};\\n};\\n\\nconst tmpVa = new Vec2();\\nclass MultiTouchSource extends InputSource {\\n\\t\\t_onPointerDown(event) {\\n\\t\\t\\t\\tconst { pointerId, pointerType } = event;\\n\\t\\t\\t\\tthis._movementState.down(event);\\n\\t\\t\\t\\tif (pointerType !== 'touch') {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._element?.setPointerCapture(pointerId);\\n\\t\\t\\t\\tthis._pointerEvents.set(pointerId, event);\\n\\t\\t\\t\\tthis.deltas.count.append([\\n\\t\\t\\t\\t\\t\\t1\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tif (this._pointerEvents.size > 1) {\\n\\t\\t\\t\\t\\t\\tthis._getMidPoint(this._pointerPos);\\n\\t\\t\\t\\t\\t\\tthis._pinchDist = this._getPinchDist();\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onPointerMove(event) {\\n\\t\\t\\t\\tconst { pointerType, target, pointerId } = event;\\n\\t\\t\\t\\tconst [movementX, movementY] = this._movementState.move(event);\\n\\t\\t\\t\\tif (pointerType !== 'touch') {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (target !== this._element) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._pointerEvents.size === 0) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._pointerEvents.set(pointerId, event);\\n\\t\\t\\t\\tif (this._pointerEvents.size > 1) {\\n\\t\\t\\t\\t\\t\\tconst mid = this._getMidPoint(tmpVa);\\n\\t\\t\\t\\t\\t\\tthis.deltas.touch.append([\\n\\t\\t\\t\\t\\t\\t\\t\\tmid.x - this._pointerPos.x,\\n\\t\\t\\t\\t\\t\\t\\t\\tmid.y - this._pointerPos.y\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\tthis._pointerPos.copy(mid);\\n\\t\\t\\t\\t\\t\\tconst pinchDist = this._getPinchDist();\\n\\t\\t\\t\\t\\t\\tif (this._pinchDist > 0) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.deltas.pinch.append([\\n\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tthis._pinchDist - pinchDist\\n\\t\\t\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._pinchDist = pinchDist;\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis.deltas.touch.append([\\n\\t\\t\\t\\t\\t\\t\\t\\tmovementX,\\n\\t\\t\\t\\t\\t\\t\\t\\tmovementY\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_onPointerUp(event) {\\n\\t\\t\\t\\tconst { pointerType, pointerId } = event;\\n\\t\\t\\t\\tthis._movementState.up(event);\\n\\t\\t\\t\\tif (pointerType !== 'touch') {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._element?.releasePointerCapture(pointerId);\\n\\t\\t\\t\\tthis._pointerEvents.delete(pointerId);\\n\\t\\t\\t\\tthis.deltas.count.append([\\n\\t\\t\\t\\t\\t\\t-1\\n\\t\\t\\t\\t]);\\n\\t\\t\\t\\tif (this._pointerEvents.size < 2) {\\n\\t\\t\\t\\t\\t\\tthis._pinchDist = -1;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._pointerPos.set(0, 0);\\n\\t\\t}\\n\\t\\t_onContextMenu(event) {\\n\\t\\t\\t\\tevent.preventDefault();\\n\\t\\t}\\n\\t\\t_getMidPoint(out) {\\n\\t\\t\\t\\tif (this._pointerEvents.size < 2) {\\n\\t\\t\\t\\t\\t\\treturn out.set(0, 0);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst [a, b] = this._pointerEvents.values();\\n\\t\\t\\t\\tconst dx = a.clientX - b.clientX;\\n\\t\\t\\t\\tconst dy = a.clientY - b.clientY;\\n\\t\\t\\t\\treturn out.set(b.clientX + dx * 0.5, b.clientY + dy * 0.5);\\n\\t\\t}\\n\\t\\t_getPinchDist() {\\n\\t\\t\\t\\tif (this._pointerEvents.size < 2) {\\n\\t\\t\\t\\t\\t\\treturn 0;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tconst [a, b] = this._pointerEvents.values();\\n\\t\\t\\t\\tconst dx = a.clientX - b.clientX;\\n\\t\\t\\t\\tconst dy = a.clientY - b.clientY;\\n\\t\\t\\t\\treturn Math.sqrt(dx * dx + dy * dy);\\n\\t\\t}\\n\\t\\tattach(element) {\\n\\t\\t\\t\\tsuper.attach(element);\\n\\t\\t\\t\\tthis._element = element;\\n\\t\\t\\t\\tthis._element.addEventListener('pointerdown', this._onPointerDown);\\n\\t\\t\\t\\tthis._element.addEventListener('pointermove', this._onPointerMove);\\n\\t\\t\\t\\tthis._element.addEventListener('pointerup', this._onPointerUp);\\n\\t\\t\\t\\tthis._element.addEventListener('pointercancel', this._onPointerUp);\\n\\t\\t\\t\\tthis._element.addEventListener('contextmenu', this._onContextMenu);\\n\\t\\t}\\n\\t\\tdetach() {\\n\\t\\t\\t\\tif (!this._element) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._element.removeEventListener('pointerdown', this._onPointerDown);\\n\\t\\t\\t\\tthis._element.removeEventListener('pointermove', this._onPointerMove);\\n\\t\\t\\t\\tthis._element.removeEventListener('pointerup', this._onPointerUp);\\n\\t\\t\\t\\tthis._element.removeEventListener('pointercancel', this._onPointerUp);\\n\\t\\t\\t\\tthis._element.removeEventListener('contextmenu', this._onContextMenu);\\n\\t\\t\\t\\tthis._pointerEvents.clear();\\n\\t\\t\\t\\tsuper.detach();\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tsuper({\\n\\t\\t\\t\\t\\t\\ttouch: [\\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],\\n\\t\\t\\t\\t\\t\\tcount: [\\n\\t\\t\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\tpinch: [\\n\\t\\t\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t}), this._movementState = movementState(), this._pointerEvents = new Map(), this._pointerPos = new Vec2(), this._pinchDist = -1;\\n\\t\\t\\t\\tthis._onPointerDown = this._onPointerDown.bind(this);\\n\\t\\t\\t\\tthis._onPointerMove = this._onPointerMove.bind(this);\\n\\t\\t\\t\\tthis._onPointerUp = this._onPointerUp.bind(this);\\n\\t\\t\\t\\tthis._onContextMenu = this._onContextMenu.bind(this);\\n\\t\\t}\\n}\\n\\nconst PASSIVE = {\\n\\t\\tpassive: false\\n};\\nconst KEY_CODES = {\\n\\t\\tA: 0,\\n\\t\\tB: 1,\\n\\t\\tC: 2,\\n\\t\\tD: 3,\\n\\t\\tE: 4,\\n\\t\\tF: 5,\\n\\t\\tG: 6,\\n\\t\\tH: 7,\\n\\t\\tI: 8,\\n\\t\\tJ: 9,\\n\\t\\tK: 10,\\n\\t\\tL: 11,\\n\\t\\tM: 12,\\n\\t\\tN: 13,\\n\\t\\tO: 14,\\n\\t\\tP: 15,\\n\\t\\tQ: 16,\\n\\t\\tR: 17,\\n\\t\\tS: 18,\\n\\t\\tT: 19,\\n\\t\\tU: 20,\\n\\t\\tV: 21,\\n\\t\\tW: 22,\\n\\t\\tX: 23,\\n\\t\\tY: 24,\\n\\t\\tZ: 25,\\n\\t\\t'0': 26,\\n\\t\\t'1': 27,\\n\\t\\t'2': 28,\\n\\t\\t'3': 29,\\n\\t\\t'4': 30,\\n\\t\\t'5': 31,\\n\\t\\t'6': 32,\\n\\t\\t'7': 33,\\n\\t\\t'8': 34,\\n\\t\\t'9': 35,\\n\\t\\tUP: 36,\\n\\t\\tDOWN: 37,\\n\\t\\tLEFT: 38,\\n\\t\\tRIGHT: 39,\\n\\t\\tSPACE: 40,\\n\\t\\tSHIFT: 41,\\n\\t\\tCTRL: 42\\n};\\nconst KEY_COUNT = Object.keys(KEY_CODES).length;\\nconst array = Array(KEY_COUNT).fill(0);\\nclass KeyboardMouseSource extends InputSource {\\n\\t\\t_onWheel(event) {\\n\\t\\t\\t\\tevent.preventDefault();\\n\\t\\t\\t\\tthis.deltas.wheel.append([\\n\\t\\t\\t\\t\\t\\tevent.deltaY\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\t_onPointerDown(event) {\\n\\t\\t\\t\\tthis._movementState.down(event);\\n\\t\\t\\t\\tif (event.pointerType !== 'mouse') {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._pointerLock) {\\n\\t\\t\\t\\t\\t\\tif (document.pointerLockElement !== this._element) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._element?.requestPointerLock();\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tthis._element?.setPointerCapture(event.pointerId);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._clearButtons();\\n\\t\\t\\t\\tthis._button[event.button] = 1;\\n\\t\\t\\t\\tthis.deltas.button.append(this._button);\\n\\t\\t\\t\\tif (this._pointerId !== -1) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._pointerId = event.pointerId;\\n\\t\\t}\\n\\t\\t_onPointerMove(event) {\\n\\t\\t\\t\\tconst [movementX, movementY] = this._pointerLock && document.pointerLockElement === this._element ? [\\n\\t\\t\\t\\t\\t\\tevent.movementX,\\n\\t\\t\\t\\t\\t\\tevent.movementY\\n\\t\\t\\t\\t] : this._movementState.move(event);\\n\\t\\t\\t\\tif (event.pointerType !== 'mouse') {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (event.target !== this._element) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (this._pointerLock) {\\n\\t\\t\\t\\t\\t\\tif (document.pointerLockElement !== this._element) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t} else {\\n\\t\\t\\t\\t\\t\\tif (this._pointerId !== event.pointerId) {\\n\\t\\t\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.deltas.mouse.append([\\n\\t\\t\\t\\t\\t\\tmovementX,\\n\\t\\t\\t\\t\\t\\tmovementY\\n\\t\\t\\t\\t]);\\n\\t\\t}\\n\\t\\t_onPointerUp(event) {\\n\\t\\t\\t\\tthis._movementState.up(event);\\n\\t\\t\\t\\tif (event.pointerType !== 'mouse') {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tif (!this._pointerLock) {\\n\\t\\t\\t\\t\\t\\tthis._element?.releasePointerCapture(event.pointerId);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._clearButtons();\\n\\t\\t\\t\\tthis.deltas.button.append(this._button);\\n\\t\\t\\t\\tif (this._pointerId !== event.pointerId) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._pointerId = -1;\\n\\t\\t}\\n\\t\\t_onContextMenu(event) {\\n\\t\\t\\t\\tevent.preventDefault();\\n\\t\\t}\\n\\t\\t_onKeyDown(event) {\\n\\t\\t\\t\\tif (this._pointerLock && document.pointerLockElement !== this._element) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tevent.stopPropagation();\\n\\t\\t\\t\\tthis._setKey(event.code, 1);\\n\\t\\t}\\n\\t\\t_onKeyUp(event) {\\n\\t\\t\\t\\tevent.stopPropagation();\\n\\t\\t\\t\\tthis._setKey(event.code, 0);\\n\\t\\t}\\n\\t\\t_clearButtons() {\\n\\t\\t\\t\\tfor(let i = 0; i < this._button.length; i++){\\n\\t\\t\\t\\t\\t\\tif (this._button[i] === 1) {\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._button[i] = -1;\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis._button[i] = 0;\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\t_setKey(code, value) {\\n\\t\\t\\t\\tif (!this._keyMap.has(code)) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._keyNow[this._keyMap.get(code) ?? 0] = value;\\n\\t\\t}\\n\\t\\tattach(element) {\\n\\t\\t\\t\\tsuper.attach(element);\\n\\t\\t\\t\\tthis._element = element;\\n\\t\\t\\t\\tthis._element.addEventListener('wheel', this._onWheel, PASSIVE);\\n\\t\\t\\t\\tthis._element.addEventListener('pointerdown', this._onPointerDown);\\n\\t\\t\\t\\tthis._element.addEventListener('pointermove', this._onPointerMove);\\n\\t\\t\\t\\tthis._element.addEventListener('pointerup', this._onPointerUp);\\n\\t\\t\\t\\tthis._element.addEventListener('pointercancel', this._onPointerUp);\\n\\t\\t\\t\\tthis._element.addEventListener('pointerleave', this._onPointerUp);\\n\\t\\t\\t\\tthis._element.addEventListener('contextmenu', this._onContextMenu);\\n\\t\\t\\t\\twindow.addEventListener('keydown', this._onKeyDown, false);\\n\\t\\t\\t\\twindow.addEventListener('keyup', this._onKeyUp, false);\\n\\t\\t}\\n\\t\\tdetach() {\\n\\t\\t\\t\\tif (!this._element) {\\n\\t\\t\\t\\t\\t\\treturn;\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._element.removeEventListener('wheel', this._onWheel, PASSIVE);\\n\\t\\t\\t\\tthis._element.removeEventListener('pointerdown', this._onPointerDown);\\n\\t\\t\\t\\tthis._element.removeEventListener('pointermove', this._onPointerMove);\\n\\t\\t\\t\\tthis._element.removeEventListener('pointerup', this._onPointerUp);\\n\\t\\t\\t\\tthis._element.removeEventListener('pointercancel', this._onPointerUp);\\n\\t\\t\\t\\tthis._element.removeEventListener('pointerleave', this._onPointerUp);\\n\\t\\t\\t\\tthis._element.removeEventListener('contextmenu', this._onContextMenu);\\n\\t\\t\\t\\twindow.removeEventListener('keydown', this._onKeyDown, false);\\n\\t\\t\\t\\twindow.removeEventListener('keyup', this._onKeyUp, false);\\n\\t\\t\\t\\tthis._keyNow.fill(0);\\n\\t\\t\\t\\tthis._keyPrev.fill(0);\\n\\t\\t\\t\\tsuper.detach();\\n\\t\\t}\\n\\t\\tread() {\\n\\t\\t\\t\\tfor(let i = 0; i < array.length; i++){\\n\\t\\t\\t\\t\\t\\tarray[i] = this._keyNow[i] - this._keyPrev[i];\\n\\t\\t\\t\\t\\t\\tthis._keyPrev[i] = this._keyNow[i];\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis.deltas.key.append(array);\\n\\t\\t\\t\\treturn super.read();\\n\\t\\t}\\n\\t\\tconstructor({ pointerLock = false } = {}){\\n\\t\\t\\t\\tsuper({\\n\\t\\t\\t\\t\\t\\tkey: Array(KEY_COUNT).fill(0),\\n\\t\\t\\t\\t\\t\\tbutton: [\\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\\t0\\n\\t\\t\\t\\t\\t\\t],\\n\\t\\t\\t\\t\\t\\tmouse: [\\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],\\n\\t\\t\\t\\t\\t\\twheel: [\\n\\t\\t\\t\\t\\t\\t\\t\\t0\\n\\t\\t\\t\\t\\t\\t]\\n\\t\\t\\t\\t}), this._movementState = movementState(), this._pointerId = -1, this._keyMap = new Map(), this._keyPrev = Array(KEY_COUNT).fill(0), this._keyNow = Array(KEY_COUNT).fill(0), this._button = Array(3).fill(0);\\n\\t\\t\\t\\tthis._pointerLock = pointerLock ?? false;\\n\\t\\t\\t\\tconst { keyCode } = KeyboardMouseSource;\\n\\t\\t\\t\\tfor(let i = 0; i < 26; i++){\\n\\t\\t\\t\\t\\t\\tconst code = `Key${String.fromCharCode('A'.charCodeAt(0) + i)}`;\\n\\t\\t\\t\\t\\t\\tthis._keyMap.set(code, keyCode.A + i);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tfor(let i = 0; i < 10; i++){\\n\\t\\t\\t\\t\\t\\tconst code = `Digit${i}`;\\n\\t\\t\\t\\t\\t\\tthis._keyMap.set(code, keyCode['0'] + i);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\tthis._keyMap.set('ArrowUp', keyCode.UP);\\n\\t\\t\\t\\tthis._keyMap.set('ArrowDown', keyCode.DOWN);\\n\\t\\t\\t\\tthis._keyMap.set('ArrowLeft', keyCode.LEFT);\\n\\t\\t\\t\\tthis._keyMap.set('ArrowRight', keyCode.RIGHT);\\n\\t\\t\\t\\tthis._keyMap.set('Space', keyCode.SPACE);\\n\\t\\t\\t\\tthis._keyMap.set('ShiftLeft', keyCode.SHIFT);\\n\\t\\t\\t\\tthis._keyMap.set('ShiftRight', keyCode.SHIFT);\\n\\t\\t\\t\\tthis._keyMap.set('ControlLeft', keyCode.CTRL);\\n\\t\\t\\t\\tthis._keyMap.set('ControlRight', keyCode.CTRL);\\n\\t\\t\\t\\tthis._onWheel = this._onWheel.bind(this);\\n\\t\\t\\t\\tthis._onPointerDown = this._onPointerDown.bind(this);\\n\\t\\t\\t\\tthis._onPointerMove = this._onPointerMove.bind(this);\\n\\t\\t\\t\\tthis._onPointerUp = this._onPointerUp.bind(this);\\n\\t\\t\\t\\tthis._onContextMenu = this._onContextMenu.bind(this);\\n\\t\\t\\t\\tthis._onKeyDown = this._onKeyDown.bind(this);\\n\\t\\t\\t\\tthis._onKeyUp = this._onKeyUp.bind(this);\\n\\t\\t}\\n}\\nKeyboardMouseSource.keyCode = KEY_CODES;\\n\\nconst BUTTON_CODES = {\\n\\t\\tA: 0,\\n\\t\\tB: 1,\\n\\t\\tX: 2,\\n\\t\\tY: 3,\\n\\t\\tLB: 4,\\n\\t\\tRB: 5,\\n\\t\\tLT: 6,\\n\\t\\tRT: 7,\\n\\t\\tSELECT: 8,\\n\\t\\tSTART: 9,\\n\\t\\tLEFT_STICK: 10,\\n\\t\\tRIGHT_STICK: 11\\n};\\nconst BUTTON_COUNT = Object.keys(BUTTON_CODES).length;\\nclass GamepadSource extends InputSource {\\n\\t\\tread() {\\n\\t\\t\\t\\tconst gamepads = navigator.getGamepads();\\n\\t\\t\\t\\tfor(let i = 0; i < gamepads.length; i++){\\n\\t\\t\\t\\t\\t\\tconst gp = gamepads[i];\\n\\t\\t\\t\\t\\t\\tif (!gp) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (gp.mapping !== 'standard') {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (gp.axes.length < 4) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tif (gp.buttons.length < BUTTON_COUNT) {\\n\\t\\t\\t\\t\\t\\t\\t\\tcontinue;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tconst { buttons, axes } = gp;\\n\\t\\t\\t\\t\\t\\tfor(let j = 0; j < this._buttonPrev.length; j++){\\n\\t\\t\\t\\t\\t\\t\\t\\tconst state = +buttons[j].pressed;\\n\\t\\t\\t\\t\\t\\t\\t\\tthis.deltas.buttons[j] = state - this._buttonPrev[j];\\n\\t\\t\\t\\t\\t\\t\\t\\tthis._buttonPrev[j] = state;\\n\\t\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t\\t\\tthis.deltas.leftStick.append([\\n\\t\\t\\t\\t\\t\\t\\t\\taxes[0],\\n\\t\\t\\t\\t\\t\\t\\t\\taxes[1]\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t\\t\\tthis.deltas.rightStick.append([\\n\\t\\t\\t\\t\\t\\t\\t\\taxes[2],\\n\\t\\t\\t\\t\\t\\t\\t\\taxes[3]\\n\\t\\t\\t\\t\\t\\t]);\\n\\t\\t\\t\\t}\\n\\t\\t\\t\\treturn super.read();\\n\\t\\t}\\n\\t\\tconstructor(){\\n\\t\\t\\t\\tsuper({\\n\\t\\t\\t\\t\\t\\tbuttons: Array(BUTTON_COUNT).fill(0),\\n\\t\\t\\t\\t\\t\\tleftStick: [\\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],\\n\\t\\t\\t\\t\\t\\trightStick: [\\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]\\n\\t\\t\\t\\t}), this._buttonPrev = Array(BUTTON_COUNT).fill(0);\\n\\t\\t}\\n}\\nGamepadSource.buttonCode = BUTTON_CODES;\\n\\nconst damp$1 = (damping, dt)=>1 - Math.pow(damping, dt * 1000);\\n\\nconst offset$1 = new Vec3();\\nconst angles$1 = new Vec3();\\nconst forward = new Vec3();\\nconst right = new Vec3();\\nconst up = new Vec3();\\nconst rotation$2 = new Quat();\\nlet FlyController$1 = class FlyController extends InputController$1 {\\n\\t\\tset pitchRange(value) {\\n\\t\\t\\t\\tthis._targetPose.pitchRange.copy(value);\\n\\t\\t\\t\\tthis._pose.copy(this._targetPose.rotate(Vec3.ZERO));\\n\\t\\t}\\n\\t\\tget pitchRange() {\\n\\t\\t\\t\\treturn this._targetPose.pitchRange;\\n\\t\\t}\\n\\t\\tset yawRange(value) {\\n\\t\\t\\t\\tthis._targetPose.yawRange.copy(value);\\n\\t\\t\\t\\tthis._pose.copy(this._targetPose.rotate(Vec3.ZERO));\\n\\t\\t}\\n\\t\\tget yawRange() {\\n\\t\\t\\t\\treturn this._targetPose.yawRange;\\n\\t\\t}\\n\\t\\tattach(pose, smooth = true) {\\n\\t\\t\\t\\tthis._targetPose.copy(pose);\\n\\t\\t\\t\\tif (!smooth) {\\n\\t\\t\\t\\t\\t\\tthis._pose.copy(this._targetPose);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdetach() {\\n\\t\\t\\t\\tthis._targetPose.copy(this._pose);\\n\\t\\t}\\n\\t\\tupdate(frame, dt) {\\n\\t\\t\\t\\tconst { move, rotate } = frame.read();\\n\\t\\t\\t\\tthis._targetPose.rotate(angles$1.set(-rotate[1], -rotate[0], 0));\\n\\t\\t\\t\\trotation$2.setFromEulerAngles(this._pose.angles);\\n\\t\\t\\t\\trotation$2.transformVector(Vec3.FORWARD, forward);\\n\\t\\t\\t\\trotation$2.transformVector(Vec3.RIGHT, right);\\n\\t\\t\\t\\trotation$2.transformVector(Vec3.UP, up);\\n\\t\\t\\t\\toffset$1.set(0, 0, 0);\\n\\t\\t\\t\\toffset$1.add(forward.mulScalar(move[2]));\\n\\t\\t\\t\\toffset$1.add(right.mulScalar(move[0]));\\n\\t\\t\\t\\toffset$1.add(up.mulScalar(move[1]));\\n\\t\\t\\t\\tthis._targetPose.move(offset$1);\\n\\t\\t\\t\\treturn this._pose.lerp(this._pose, this._targetPose, damp$1(this.moveDamping, dt), damp$1(this.rotateDamping, dt));\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.detach();\\n\\t\\t}\\n\\t\\tconstructor(...args){\\n\\t\\t\\t\\tsuper(...args), this._targetPose = new Pose(), this.rotateDamping = 0.98, this.moveDamping = 0.98;\\n\\t\\t}\\n};\\n\\nconst dir = new Vec3();\\nconst offset = new Vec3();\\nconst angles = new Vec3();\\nconst rotation$1 = new Quat();\\nlet OrbitController$1 = class OrbitController extends InputController$1 {\\n\\t\\tset pitchRange(range) {\\n\\t\\t\\t\\tthis._targetRootPose.pitchRange.copy(range);\\n\\t\\t\\t\\tthis._rootPose.copy(this._targetRootPose.rotate(Vec3.ZERO));\\n\\t\\t}\\n\\t\\tget pitchRange() {\\n\\t\\t\\t\\treturn this._targetRootPose.pitchRange;\\n\\t\\t}\\n\\t\\tset yawRange(range) {\\n\\t\\t\\t\\tthis._targetRootPose.yawRange.copy(range);\\n\\t\\t\\t\\tthis._rootPose.copy(this._targetRootPose.rotate(Vec3.ZERO));\\n\\t\\t}\\n\\t\\tget yawRange() {\\n\\t\\t\\t\\treturn this._targetRootPose.yawRange;\\n\\t\\t}\\n\\t\\tset zoomRange(range) {\\n\\t\\t\\t\\tthis._targetChildPose.zRange.copy(range);\\n\\t\\t\\t\\tthis._childPose.copy(this._targetChildPose.move(Vec3.ZERO));\\n\\t\\t}\\n\\t\\tget zoomRange() {\\n\\t\\t\\t\\treturn this._targetRootPose.zRange;\\n\\t\\t}\\n\\t\\tattach(pose, smooth = true) {\\n\\t\\t\\t\\tthis._targetRootPose.set(pose.getFocus(dir), pose.angles, 0);\\n\\t\\t\\t\\tthis._targetChildPose.position.set(0, 0, pose.distance);\\n\\t\\t\\t\\tif (!smooth) {\\n\\t\\t\\t\\t\\t\\tthis._rootPose.copy(this._targetRootPose);\\n\\t\\t\\t\\t\\t\\tthis._childPose.copy(this._targetChildPose);\\n\\t\\t\\t\\t}\\n\\t\\t}\\n\\t\\tdetach() {\\n\\t\\t\\t\\tthis._targetRootPose.copy(this._rootPose);\\n\\t\\t\\t\\tthis._targetChildPose.copy(this._childPose);\\n\\t\\t}\\n\\t\\tupdate(frame, dt) {\\n\\t\\t\\t\\tconst { move, rotate } = frame.read();\\n\\t\\t\\t\\toffset.set(move[0], move[1], 0);\\n\\t\\t\\t\\trotation$1.setFromEulerAngles(this._rootPose.angles).transformVector(offset, offset);\\n\\t\\t\\t\\tthis._targetRootPose.move(offset);\\n\\t\\t\\t\\tconst { z: dist } = this._targetChildPose.position;\\n\\t\\t\\t\\tthis._targetChildPose.move(offset.set(0, 0, dist * (1 + move[2]) - dist));\\n\\t\\t\\t\\tthis._targetRootPose.rotate(angles.set(-rotate[1], -rotate[0], 0));\\n\\t\\t\\t\\tthis._rootPose.lerp(this._rootPose, this._targetRootPose, damp$1(this.moveDamping, dt), damp$1(this.rotateDamping, dt), 1);\\n\\t\\t\\t\\tthis._childPose.lerp(this._childPose, this._targetChildPose, damp$1(this.zoomDamping, dt), 1, 1);\\n\\t\\t\\t\\trotation$1.setFromEulerAngles(this._rootPose.angles).transformVector(this._childPose.position, offset).add(this._rootPose.position);\\n\\t\\t\\t\\treturn this._pose.set(offset, this._rootPose.angles, this._childPose.position.z);\\n\\t\\t}\\n\\t\\tdestroy() {\\n\\t\\t\\t\\tthis.detach();\\n\\t\\t}\\n\\t\\tconstructor(...args){\\n\\t\\t\\t\\tsuper(...args), this._targetRootPose = new Pose(), this._rootPose = new Pose(), this._targetChildPose = new Pose(), this._childPose = new Pose(), this.rotateDamping = 0.98, this.moveDamping = 0.98, this.zoomDamping = 0.98;\\n\\t\\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// 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\\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: [{\\n                initial: {\\n                    position: (v1.camera.position || [0, 0, 5]),\\n                    target: (v1.camera.target || [0, 0, 0]),\\n                    fov: v1.camera.fov || 75\\n                }\\n            }],\\n        annotations: [],\\n        startMode: v1.camera.startAnim === 'animTrack' ? 'animTrack' : 'default',\\n        hasStartPose: !!(v1.camera.position && v1.camera.target)\\n    };\\n};\\n// import a json object to conform to the latest settings schema. settings is assumed to be one of the well-formed schemas\\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\\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=120, stick size=48)\\n    const joystickHeight = 120;\\n    const stickSize = 48;\\n    const stickCenterY = (joystickHeight - stickSize) / 2; // 36px - top position when centered\\n    const stickCenterX = (joystickHeight - stickSize) / 2; // 36px - left position when centered (for 2D mode)\\n    const maxStickTravel = stickCenterY; // can travel 36px 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 === 'fps') && state.inputMode === 'touch') {\\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    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        'hqCheck', 'hqOption', 'lqCheck', 'lqOption',\\n        'reset', 'frame',\\n        'loadingText', 'loadingBar',\\n        'joystickBase', 'joystick',\\n        'showVoxels',\\n        'tooltip',\\n        'annotationNav', 'annotationPrev', 'annotationNext', 'annotationInfo', 'annotationNavTitle',\\n        'supersplatBranding'\\n    ].reduce((acc, id) => {\\n        acc[id] = document.getElementById(id);\\n        return acc;\\n    }, {});\\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    const canvas = global.app.graphicsDevice.canvas;\\n    dom.ui.addEventListener('wheel', (event) => {\\n        event.preventDefault();\\n        canvas.dispatchEvent(new WheelEvent(event.type, event));\\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    // HQ mode\\n    dom.hqOption.addEventListener('click', () => {\\n        state.hqMode = true;\\n    });\\n    dom.lqOption.addEventListener('click', () => {\\n        state.hqMode = false;\\n    });\\n    const updateHQ = () => {\\n        dom.hqCheck.classList[state.hqMode ? 'add' : 'remove']('active');\\n        dom.lqCheck.classList[state.hqMode ? 'remove' : 'add']('active');\\n    };\\n    events.on('hqMode:changed', (value) => {\\n        updateHQ();\\n    });\\n    updateHQ();\\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    dom.arMode.addEventListener('click', () => events.fire('startAR'));\\n    dom.vrMode.addEventListener('click', () => events.fire('startVR'));\\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    dom.info.addEventListener('click', () => {\\n        updateInfoTab(state.inputMode);\\n        dom.infoPanel.classList.toggle('hidden');\\n    });\\n    dom.infoPanel.addEventListener('pointerdown', () => {\\n        dom.infoPanel.classList.add('hidden');\\n    });\\n    events.on('inputEvent', (event) => {\\n        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 showUI = () => {\\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    // 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 === 'fps');\\n    };\\n    events.on('cameraMode:changed', updateCameraModeUI);\\n    // show/hide the FPS button based on voxel data availability\\n    events.on('hasCollision: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    // Voxel overlay toggle (only visible when overlay is available)\\n    events.on('hasVoxelOverlay:changed', (value) => {\\n        dom.showVoxels.classList.toggle('hidden', !value);\\n    });\\n    dom.showVoxels.addEventListener('click', () => {\\n        state.voxelOverlayEnabled = !state.voxelOverlayEnabled;\\n    });\\n    events.on('voxelOverlayEnabled:changed', (value) => {\\n        dom.showVoxels.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', 'toggleFps');\\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, 'Play', 'top');\\n    tooltip.register(dom.pause, 'Pause', 'top');\\n    tooltip.register(dom.orbitCamera, 'Orbit Camera', 'top');\\n    tooltip.register(dom.flyCamera, 'Fly Camera', 'top');\\n    tooltip.register(dom.fpsCamera, 'Walk Mode', 'top');\\n    tooltip.register(dom.reset, 'Reset Camera', 'bottom');\\n    tooltip.register(dom.frame, 'Frame Scene', 'bottom');\\n    tooltip.register(dom.showVoxels, 'Show Voxels', 'top');\\n    tooltip.register(dom.settings, 'Settings', 'top');\\n    tooltip.register(dom.info, 'Help', 'top');\\n    tooltip.register(dom.arMode, 'Enter AR', 'top');\\n    tooltip.register(dom.vrMode, 'Enter VR', 'top');\\n    tooltip.register(dom.enterFullscreen, 'Fullscreen', 'top');\\n    tooltip.register(dom.exitFullscreen, '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.supersplatBranding.href = viewUrl.toString();\\n        dom.supersplatBranding.classList.remove('hidden');\\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$2 = 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$2);\\n        if (vec$2.z >= 0) {\\n            this._hideElements();\\n            return;\\n        }\\n        this._updatePositions(screenPos);\\n        this._updateRotationAndScale(-vec$2.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        global.events.on('controlsHidden:changed', (value) => {\\n            parentDom.style.display = value ? 'none' : 'block';\\n            Annotation.opacity = value ? 0.0 : 1.0;\\n            if (this.annotations.length > 0) {\\n                global.app.renderNextFrame = true;\\n            }\\n        });\\n        this.annotations = global.settings.annotations;\\n        this.parentDom = parentDom;\\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 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 mat = new Mat4();\\n    const vec = new Vec3();\\n    const dif = new Vec3(position.x - target.x, position.y - target.y, position.z - target.z);\\n    for (let i = 0; i < keys; ++i) {\\n        mat.setFromEulerAngles(0, -i / keys * 360, 0);\\n        mat.transformPoint(dif, vec);\\n        positions.push(target.x + vec.x);\\n        positions.push(target.y + vec.y);\\n        positions.push(target.z + vec.z);\\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\\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/**\\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    result.x = Math.asin(vec.y) * radToDeg;\\n    result.y = Math.atan2(-vec.x, -vec.z) * radToDeg;\\n    result.z = 0;\\n    return result;\\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 ? 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    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        }\\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 } = values;\\n        // construct the points array containing position and target\\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        }\\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        // snap camera to start position\\n        camera.look(this.animState.position, this.animState.target);\\n    }\\n    update(deltaTime, inputFrame, camera) {\\n        this.animState.update(deltaTime);\\n        // update camera pose\\n        camera.look(this.animState.position, this.animState.target);\\n        // ignore input\\n        inputFrame.read();\\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/** Radius of the camera collision sphere (meters) */\\nconst CAMERA_RADIUS = 0.2;\\nconst p$1 = new Pose();\\n/** Pre-allocated push-out vector for sphere collision */\\nconst pushOut$1 = { x: 0, y: 0, z: 0 };\\nclass FlyController {\\n    controller;\\n    /** Optional voxel collider for sphere collision with sliding */\\n    collider = null;\\n    constructor() {\\n        this.controller = new FlyController$1();\\n        this.controller.pitchRange = new Vec2(-90, 90);\\n        this.controller.rotateDamping = 0.97;\\n        this.controller.moveDamping = 0.97;\\n    }\\n    onEnter(camera) {\\n        p$1.position.copy(camera.position);\\n        p$1.angles.copy(camera.angles);\\n        p$1.distance = camera.distance;\\n        this.controller.attach(p$1, false);\\n    }\\n    update(deltaTime, inputFrame, camera) {\\n        const pose = this.controller.update(inputFrame, deltaTime);\\n        camera.angles.copy(pose.angles);\\n        camera.distance = pose.distance;\\n        if (this.collider) {\\n            // Resolve collision on _targetPose first. The engine's update() already\\n            // applied input to _targetPose and lerped _pose toward it. By correcting\\n            // _targetPose now, we ensure next frame's lerp interpolates toward a safe\\n            // position, preventing the camera from overshooting into the wall.\\n            const target = this.controller._targetPose;\\n            const tvx = -target.position.x;\\n            const tvy = -target.position.y;\\n            const tvz = target.position.z;\\n            if (this.collider.querySphere(tvx, tvy, tvz, CAMERA_RADIUS, pushOut$1)) {\\n                target.position.x += -pushOut$1.x;\\n                target.position.y += -pushOut$1.y;\\n                target.position.z += pushOut$1.z;\\n            }\\n            // Now resolve collision on the interpolated pose (_pose).\\n            const vx = -pose.position.x;\\n            const vy = -pose.position.y;\\n            const vz = pose.position.z;\\n            if (this.collider.querySphere(vx, vy, vz, CAMERA_RADIUS, pushOut$1)) {\\n                pose.position.x += -pushOut$1.x;\\n                pose.position.y += -pushOut$1.y;\\n                pose.position.z += pushOut$1.z;\\n            }\\n        }\\n        camera.position.copy(pose.position);\\n    }\\n    onExit(camera) {\\n    }\\n    goto(pose) {\\n        this.controller.attach(pose, true);\\n    }\\n}\\n\\n/** Pre-allocated push-out vector for capsule collision */\\nconst pushOut = { x: 0, y: 0, z: 0 };\\n/**\\n * First-person shooter style camera controller with gravity and capsule collision.\\n *\\n * Movement is constrained to the horizontal plane (XZ) relative to the camera yaw.\\n * Vertical motion is driven by gravity and resolved by capsule collision with the\\n * voxel grid. The camera is positioned at eye height within the capsule.\\n */\\nclass FpsController {\\n    /** Optional voxel collider for capsule collision with sliding */\\n    collider = null;\\n    /** Total capsule height in meters (default: human proportion) */\\n    capsuleHeight = 1.8;\\n    /** Capsule radius in meters */\\n    capsuleRadius = 0.3;\\n    /** Camera height from the bottom of the capsule in meters */\\n    eyeHeight = 1.6;\\n    /** Gravity acceleration in m/s^2 */\\n    gravity = 9.8;\\n    /** Jump velocity in m/s */\\n    jumpSpeed = 5;\\n    /** Movement damping factor (0 = no damping, 1 = full damping) */\\n    moveDamping = 0.97;\\n    /** Rotation damping factor (0 = no damping, 1 = full damping) */\\n    rotateDamping = 0.97;\\n    // Target state (where input drives)\\n    _targetPosition = new Vec3();\\n    _targetYaw = 0;\\n    _targetPitch = 0;\\n    // Smoothed state (lerps toward target)\\n    _position = new Vec3();\\n    _yaw = 0;\\n    _pitch = 0;\\n    // Vertical velocity for gravity\\n    _velocityY = 0;\\n    // Whether the capsule is resting on the ground\\n    _onGround = false;\\n    onEnter(camera) {\\n        this._position.copy(camera.position);\\n        this._targetPosition.copy(camera.position);\\n        // angles.x = pitch, angles.y = yaw\\n        this._pitch = camera.angles.x;\\n        this._targetPitch = camera.angles.x;\\n        this._yaw = camera.angles.y;\\n        this._targetYaw = camera.angles.y;\\n        this._velocityY = 0;\\n        this._onGround = false;\\n    }\\n    update(deltaTime, inputFrame, camera) {\\n        const { move, rotate } = inputFrame.read();\\n        // --- Rotation ---\\n        this._targetYaw -= rotate[0];\\n        this._targetPitch = math.clamp(this._targetPitch - rotate[1], -90, 90);\\n        const rotateLerp = damp(this.rotateDamping, deltaTime);\\n        this._yaw = math.lerpAngle(this._yaw, this._targetYaw, rotateLerp);\\n        this._pitch = math.lerp(this._pitch, this._targetPitch, rotateLerp);\\n        // Normalize yaw to prevent floating-point drift over long sessions.\\n        // Shift both values by the same multiple of 360 to preserve their delta.\\n        const yawOffset = Math.round(this._yaw / 360) * 360;\\n        if (yawOffset !== 0) {\\n            this._yaw -= yawOffset;\\n            this._targetYaw -= yawOffset;\\n        }\\n        // --- Horizontal movement ---\\n        // Compute forward/right from yaw only (ignore pitch for movement)\\n        const yawRad = this._targetYaw * math.DEG_TO_RAD;\\n        const sinYaw = Math.sin(yawRad);\\n        const cosYaw = Math.cos(yawRad);\\n        // PlayCanvas convention: forward = -Z, right = +X\\n        const forwardX = -sinYaw;\\n        const forwardZ = -cosYaw;\\n        const rightX = cosYaw;\\n        const rightZ = -sinYaw;\\n        const moveLerp = damp(this.moveDamping, deltaTime);\\n        this._targetPosition.x += rightX * move[0] + forwardX * move[2];\\n        this._targetPosition.z += rightZ * move[0] + forwardZ * move[2];\\n        // --- Jump ---\\n        if (move[1] > 0 && this._onGround) {\\n            this._velocityY = this.jumpSpeed;\\n            this._onGround = false;\\n        }\\n        // --- Gravity ---\\n        this._velocityY -= this.gravity * deltaTime;\\n        this._targetPosition.y += this._velocityY * deltaTime;\\n        // --- Capsule collision on target position ---\\n        if (this.collider) {\\n            this._resolveCapsuleCollision(this._targetPosition, true);\\n        }\\n        // --- Smooth horizontal position toward target ---\\n        this._position.x = math.lerp(this._position.x, this._targetPosition.x, moveLerp);\\n        this._position.z = math.lerp(this._position.z, this._targetPosition.z, moveLerp);\\n        // No smoothing on Y for crisp ground contact\\n        this._position.y = this._targetPosition.y;\\n        // --- Capsule collision on smoothed position ---\\n        if (this.collider) {\\n            this._resolveCapsuleCollision(this._position, false);\\n        }\\n        // --- Output to camera ---\\n        camera.position.copy(this._position);\\n        camera.angles.set(this._pitch, this._yaw, 0);\\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        this._position.copy(camera.position);\\n        this._targetPosition.copy(camera.position);\\n        this._pitch = camera.angles.x;\\n        this._targetPitch = camera.angles.x;\\n        this._yaw = camera.angles.y;\\n        this._targetYaw = camera.angles.y;\\n        this._velocityY = 0;\\n        this._onGround = false;\\n    }\\n    /**\\n     * Resolve capsule collision for a given eye position, modifying it in place.\\n     * Converts from PlayCanvas space to voxel space, queries the capsule, and\\n     * applies the push-out vector back to PlayCanvas space.\\n     *\\n     * @param eyePos - Eye position to resolve (modified in place).\\n     * @param isTarget - Whether this is the target position (updates velocity on ground contact).\\n     */\\n    _resolveCapsuleCollision(eyePos, isTarget) {\\n        // Derive capsule center from eye position in PlayCanvas space:\\n        // bottom of capsule = eyePos.y - eyeHeight\\n        // capsule center    = eyePos.y - eyeHeight + capsuleHeight / 2\\n        const capsuleCenterPCY = eyePos.y - this.eyeHeight + this.capsuleHeight * 0.5;\\n        const halfHeight = this.capsuleHeight * 0.5 - this.capsuleRadius;\\n        // Convert to voxel space (negate X, negate Y, keep Z)\\n        const vx = -eyePos.x;\\n        const vy = -capsuleCenterPCY;\\n        const vz = eyePos.z;\\n        if (this.collider.queryCapsule(vx, vy, vz, halfHeight, this.capsuleRadius, pushOut)) {\\n            // Convert push-out back to PlayCanvas space\\n            const pushPCX = -pushOut.x;\\n            const pushPCY = -pushOut.y;\\n            const pushPCZ = pushOut.z;\\n            eyePos.x += pushPCX;\\n            // Push-out applies to capsule center; eye moves by the same amount\\n            eyePos.y += pushPCY;\\n            eyePos.z += pushPCZ;\\n            // Ground detection: if pushed upward and falling, cancel downward velocity\\n            if (isTarget) {\\n                if (pushPCY > 0 && this._velocityY < 0) {\\n                    this._velocityY = 0;\\n                    this._onGround = true;\\n                }\\n                // Ceiling detection: if pushed downward and rising, cancel upward velocity\\n                if (pushPCY < 0 && this._velocityY > 0) {\\n                    this._velocityY = 0;\\n                }\\n            }\\n        }\\n    }\\n}\\n\\nconst p = new Pose();\\nclass OrbitController {\\n    controller;\\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 = 0.97;\\n        this.controller.moveDamping = 0.97;\\n        this.controller.zoomDamping = 0.97;\\n    }\\n    onEnter(camera) {\\n        p.position.copy(camera.position);\\n        p.angles.copy(camera.angles);\\n        p.distance = camera.distance;\\n        this.controller.attach(p, false);\\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    }\\n    onExit(camera) {\\n    }\\n    goto(camera) {\\n        p.position.copy(camera.position);\\n        p.angles.copy(camera.angles);\\n        p.distance = camera.distance;\\n        this.controller.attach(p, false);\\n    }\\n}\\n\\nconst tmpCamera = new Camera();\\nconst tmpv = new Vec3();\\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    // holds the camera state\\n    camera = new Camera();\\n    constructor(global, bbox, collider = null) {\\n        const { events, settings, state } = global;\\n        const camera0 = settings.cameras[0].initial;\\n        const frameCamera = createFrameCamera(bbox, camera0.fov);\\n        const resetCamera = createCamera(new Vec3(camera0.position), new Vec3(camera0.target), camera0.fov);\\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            return null;\\n        };\\n        // object experience starts outside the bounding box\\n        const isObjectExperience = !bbox.containsPoint(resetCamera.position);\\n        const animTrack = getAnimTrack(settings.hasStartPose ? resetCamera : frameCamera, isObjectExperience);\\n        const controllers = {\\n            orbit: new OrbitController(),\\n            fly: new FlyController(),\\n            fps: new FpsController(),\\n            anim: animTrack ? new AnimController(animTrack) : null\\n        };\\n        controllers.fly.collider = collider;\\n        controllers.fps.collider = collider;\\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' : '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        let fromMode = isObjectExperience ? 'orbit' : 'fly';\\n        // tracks the mode to restore when exiting FPS\\n        let preFpsMode = '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        // start a new camera transition from the current pose\\n        const startTransition = () => {\\n            from.copy(this.camera);\\n            transitionTimer = 0;\\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            transitionTimer = Math.min(1, transitionTimer + deltaTime * transitionSpeed);\\n            const controller = getController(state.cameraMode);\\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        };\\n        // handle input events\\n        events.on('inputEvent', (eventName, event) => {\\n            switch (eventName) {\\n                case 'frame':\\n                    state.cameraMode = 'orbit';\\n                    controllers.orbit.goto(frameCamera);\\n                    startTransition();\\n                    break;\\n                case 'reset':\\n                    state.cameraMode = 'orbit';\\n                    controllers.orbit.goto(resetCamera);\\n                    startTransition();\\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 'toggleFps':\\n                    if (collider) {\\n                        if (state.cameraMode === 'fps') {\\n                            state.cameraMode = preFpsMode;\\n                        }\\n                        else {\\n                            preFpsMode = state.cameraMode;\\n                            state.cameraMode = 'fps';\\n                        }\\n                    }\\n                    break;\\n                case 'cancel':\\n                    if (state.cameraMode === 'anim') {\\n                        state.cameraMode = fromMode;\\n                    }\\n                    else if (state.cameraMode === 'fps') {\\n                        state.cameraMode = preFpsMode;\\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            // 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        });\\n        events.on('annotation.activate', (annotation) => {\\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            target.fov = tmpCamera.fov;\\n            startTransition();\\n        });\\n    }\\n}\\n\\n// override global pick to pack depth instead of meshInstance id\\nconst pickDepthGlsl = /* glsl */ `\\nuniform vec4 camera_params;     // 1/far, far, near, isOrtho\\nvec4 getPickOutput() {\\n    float linearDepth = 1.0 / gl_FragCoord.w;\\n    float normalizedDepth = (linearDepth - camera_params.z) / (camera_params.y - camera_params.z);\\n    return vec4(gaussianColor.a * normalizedDepth, 0.0, 0.0, gaussianColor.a);\\n}\\n`;\\nconst pickDepthWgsl = /* wgsl */ `\\n    uniform camera_params: vec4f;       // 1/far, far, near, isOrtho\\n    fn getPickOutput() -> vec4f {\\n        let linearDepth = 1.0 / pcPosition.w;\\n        let normalizedDepth = (linearDepth - uniform.camera_params.z) / (uniform.camera_params.y - uniform.camera_params.z);\\n        return vec4f(gaussianColor.a * normalizedDepth, 0.0, 0.0, gaussianColor.a);\\n    }\\n`;\\nconst vec$1 = new Vec3();\\nconst vecb = new Vec3();\\nconst ray = new Ray();\\nconst clearColor = new Color(0, 0, 0, 1);\\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; // Move sign to bit 31\\n    const exponent = (h & 0x7C00) >> 10; // Extract 5-bit exponent\\n    const mantissa = h & 0x03FF; // Extract 10-bit mantissa\\n    if (exponent === 0) {\\n        if (mantissa === 0) {\\n            // Zero\\n            uint32[0] = sign;\\n        }\\n        else {\\n            // Denormalized: convert to normalized float32\\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        // Infinity or NaN\\n        uint32[0] = sign | 0x7F800000 | (mantissa << 13);\\n    }\\n    else {\\n        // Normalized: adjust exponent bias from 15 to 127\\n        uint32[0] = sign | ((exponent + 127 - 15) << 23) | (mantissa << 13);\\n    }\\n    return float32[0];\\n};\\n// get the normalized world-space ray starting at the camera position\\n// facing the supplied screen position\\n// works for both perspective and orthographic cameras\\nconst getRay = (camera, screenX, screenY, ray) => {\\n    const cameraPos = camera.getPosition();\\n    // create the pick ray in world space\\n    if (camera.camera.projection === PROJECTION_ORTHOGRAPHIC) {\\n        camera.camera.screenToWorld(screenX, screenY, -1, vec$1);\\n        camera.camera.screenToWorld(screenX, screenY, 1.0, vecb);\\n        vecb.sub(vec$1).normalize();\\n        ray.set(vec$1, vecb);\\n    }\\n    else {\\n        camera.camera.screenToWorld(screenX, screenY, 1.0, vec$1);\\n        vec$1.sub(cameraPos).normalize();\\n        ray.set(cameraPos, vec$1);\\n    }\\n};\\nclass Picker {\\n    pick;\\n    release;\\n    constructor(app, camera) {\\n        const { graphicsDevice } = app;\\n        // register pick depth shader chunks\\n        ShaderChunks.get(graphicsDevice, 'glsl').set('pickPS', pickDepthGlsl);\\n        ShaderChunks.get(graphicsDevice, 'wgsl').set('pickPS', pickDepthWgsl);\\n        let colorBuffer;\\n        let renderTarget;\\n        let renderPass;\\n        const emptyMap = new Map();\\n        const init = (width, height) => {\\n            colorBuffer = new Texture(graphicsDevice, {\\n                format: PIXELFORMAT_RGBA16F,\\n                width: width,\\n                height: 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'\\n            });\\n            renderTarget = new RenderTarget({\\n                colorBuffer,\\n                depth: false // not needed - gaussians are rendered back to front\\n            });\\n            renderPass = new RenderPassPicker(graphicsDevice, app.renderer);\\n            // RGB: additive depth accumulation (ONE, ONE_MINUS_SRC_ALPHA)\\n            // Alpha: multiplicative transmittance (ZERO, ONE_MINUS_SRC_ALPHA) -> T = T * (1 - alpha)\\n            renderPass.blendState = new BlendState(true, BLENDEQUATION_ADD, BLENDMODE_ONE, BLENDMODE_ONE_MINUS_SRC_ALPHA, // RGB blend\\n            BLENDEQUATION_ADD, BLENDMODE_ZERO, BLENDMODE_ONE_MINUS_SRC_ALPHA // Alpha blend (transmittance)\\n            );\\n        };\\n        this.pick = async (x, y) => {\\n            const width = Math.floor(graphicsDevice.width);\\n            const height = Math.floor(graphicsDevice.height);\\n            // convert from [0,1] to pixel coordinates\\n            const screenX = Math.floor(x * graphicsDevice.width);\\n            const screenY = Math.floor(y * graphicsDevice.height);\\n            // flip Y for texture read on WebGL (texture origin is bottom-left)\\n            const texX = screenX;\\n            const texY = graphicsDevice.isWebGL2 ? height - screenY - 1 : screenY;\\n            // construct picker on demand\\n            if (!renderPass) {\\n                init(width, height);\\n            }\\n            else {\\n                renderTarget.resize(width, height);\\n            }\\n            // render scene\\n            renderPass.init(renderTarget);\\n            renderPass.setClearColor(clearColor);\\n            renderPass.update(camera.camera, app.scene, [app.scene.layers.getLayerByName('World')], emptyMap, false);\\n            renderPass.render();\\n            // read pixel using texture coordinates\\n            const pixels = await colorBuffer.read(texX, texY, 1, 1, { renderTarget, immediate: true });\\n            // convert half-float values to floats\\n            // R channel: accumulated depth * alpha\\n            // A channel: transmittance (1 - alpha), values near 0 have better half-float precision\\n            const r = half2Float(pixels[0]);\\n            const transmittance = half2Float(pixels[3]);\\n            const alpha = 1 - transmittance;\\n            // check alpha first (transmittance close to 1 means nothing visible)\\n            if (alpha < 1e-6) {\\n                return null;\\n            }\\n            // get camera near/far for denormalization\\n            const near = camera.camera.nearClip;\\n            const far = camera.camera.farClip;\\n            // divide by alpha to get normalized depth, then denormalize to linear depth\\n            const normalizedDepth = r / alpha;\\n            const depth = normalizedDepth * (far - near) + near;\\n            // get the ray from camera through the screen point (using pixel coords)\\n            getRay(camera, Math.floor(x * graphicsDevice.canvas.offsetWidth), Math.floor(y * graphicsDevice.canvas.offsetHeight), ray);\\n            // convert linear depth (view-space z distance) to ray distance\\n            const forward = camera.forward;\\n            const t = depth / ray.direction.dot(forward);\\n            // world position = ray origin + ray direction * t\\n            return ray.origin.clone().add(ray.direction.clone().mulScalar(t));\\n        };\\n        this.release = () => {\\n            renderPass?.destroy();\\n            renderTarget?.destroy();\\n            colorBuffer?.destroy();\\n        };\\n    }\\n}\\n\\n/* Vec initialisation to avoid recurrent memory allocation */\\nconst tmpV1 = new Vec3();\\nconst tmpV2 = new Vec3();\\nconst mouseRotate = new Vec3();\\nconst flyMove = new Vec3();\\nconst pinchMove = new Vec3();\\nconst orbitRotate = new Vec3();\\nconst flyRotate = new Vec3();\\nconst stickMove = new Vec3();\\nconst stickRotate = new Vec3();\\n/**\\n * Converts screen space mouse deltas to world space pan vector.\\n *\\n * @param camera - The camera component.\\n * @param dx - The mouse delta x value.\\n * @param dy - The mouse delta y value.\\n * @param dz - The world space zoom delta value.\\n * @param out - The output vector to store the pan result.\\n * @returns - The pan vector in world space.\\n * @private\\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    // normalize deltas to device coord space\\n    out.set(-(dx / width) * 2, (dy / height) * 2, 0);\\n    // calculate half size of the view frustum at the current distance\\n    const halfSize = tmpV2.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    // scale by device coord space\\n    out.mul(halfSize);\\n    return out;\\n};\\n// patch keydown and keyup to ignore events with meta key otherwise\\n// keys can get stuck on macOS.\\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 InputController {\\n    _state = {\\n        axis: new Vec3(),\\n        mouse: [0, 0, 0],\\n        shift: 0,\\n        ctrl: 0,\\n        jump: 0,\\n        touches: 0\\n    };\\n    _desktopInput = new KeyboardMouseSource();\\n    _orbitInput = new MultiTouchSource();\\n    _gamepadInput = new GamepadSource();\\n    global;\\n    frame = new InputFrame({\\n        move: [0, 0, 0],\\n        rotate: [0, 0, 0]\\n    });\\n    // Touch joystick input values (-1 to 1)\\n    _touchJoystickX = 0; // negative = left, positive = right\\n    _touchJoystickY = 0; // negative = forward, positive = backward\\n    // this gets overridden by the viewer based on scene size\\n    moveSpeed = 4;\\n    orbitSpeed = 18;\\n    pinchSpeed = 0.4;\\n    wheelSpeed = 0.06;\\n    constructor(global) {\\n        const { app, camera, events, state } = global;\\n        const canvas = app.graphicsDevice.canvas;\\n        patchKeyboardMeta(this._desktopInput);\\n        this._desktopInput.attach(canvas);\\n        this._orbitInput.attach(canvas);\\n        // Listen for joystick input from the UI (touch joystick element)\\n        events.on('joystickInput', (value) => {\\n            this._touchJoystickX = value.x;\\n            this._touchJoystickY = value.y;\\n        });\\n        this.global = global;\\n        // Generate input events\\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        // Detect double taps manually because iOS doesn't send dblclick events\\n        const lastTap = { time: 0, x: 0, y: 0 };\\n        canvas.addEventListener('pointerdown', (event) => {\\n            const now = Date.now();\\n            const delay = Math.max(0, now - lastTap.time);\\n            if (delay < 300 &&\\n                Math.abs(event.clientX - lastTap.x) < 8 &&\\n                Math.abs(event.clientY - lastTap.y) < 8) {\\n                events.fire('inputEvent', 'dblclick', event);\\n                lastTap.time = 0;\\n            }\\n            else {\\n                lastTap.time = now;\\n                lastTap.x = event.clientX;\\n                lastTap.y = event.clientY;\\n            }\\n        });\\n        // Calculate pick location on double click\\n        let picker = null;\\n        events.on('inputEvent', async (eventName, event) => {\\n            switch (eventName) {\\n                case 'dblclick': {\\n                    if (!picker) {\\n                        picker = new Picker(app, camera);\\n                    }\\n                    const result = await picker.pick(event.offsetX / canvas.clientWidth, event.offsetY / canvas.clientHeight);\\n                    if (result) {\\n                        events.fire('pick', result);\\n                    }\\n                    break;\\n                }\\n            }\\n        });\\n        // update input mode based on pointer event\\n        ['pointerdown', 'pointermove'].forEach((eventName) => {\\n            window.addEventListener(eventName, (event) => {\\n                state.inputMode = event.pointerType === 'touch' ? 'touch' : 'desktop';\\n            });\\n        });\\n        // handle keyboard events\\n        window.addEventListener('keydown', (event) => {\\n            if (event.key === 'Escape') {\\n                events.fire('inputEvent', 'cancel', event);\\n            }\\n            else if (state.cameraMode !== 'fps' && !event.ctrlKey && !event.altKey && !event.metaKey) {\\n                switch (event.key) {\\n                    case 'f':\\n                        events.fire('inputEvent', 'frame', event);\\n                        break;\\n                    case 'r':\\n                        events.fire('inputEvent', 'reset', event);\\n                        break;\\n                    case ' ':\\n                        events.fire('inputEvent', 'playPause', event);\\n                        break;\\n                }\\n            }\\n        });\\n        // Pointer lock management for FPS mode on desktop\\n        events.on('cameraMode:changed', (value, prev) => {\\n            if (value === 'fps' && state.inputMode === 'desktop') {\\n                this._desktopInput._pointerLock = true;\\n                canvas.requestPointerLock();\\n            }\\n            else if (prev === 'fps') {\\n                this._desktopInput._pointerLock = false;\\n                if (document.pointerLockElement === canvas) {\\n                    document.exitPointerLock();\\n                }\\n            }\\n        });\\n        document.addEventListener('pointerlockchange', () => {\\n            if (!document.pointerLockElement && state.cameraMode === 'fps') {\\n                events.fire('inputEvent', 'cancel');\\n            }\\n        });\\n        // Pointer lock request rejected (e.g., no user gesture, document hidden).\\n        // Revert to avoid being stuck in FPS mode without mouse capture.\\n        document.addEventListener('pointerlockerror', () => {\\n            this._desktopInput._pointerLock = false;\\n            events.fire('inputEvent', 'cancel');\\n        });\\n    }\\n    /**\\n     * @param dt - delta time in seconds\\n     * @param state - the current state of the app\\n     * @param state.cameraMode - the current camera mode\\n     * @param distance - the distance to the camera target\\n     */\\n    update(dt, distance) {\\n        const { keyCode } = KeyboardMouseSource;\\n        const { key, button, mouse, wheel } = this._desktopInput.read();\\n        const { touch, pinch, count } = this._orbitInput.read();\\n        const { leftStick, rightStick } = this._gamepadInput.read();\\n        const { state, events } = this.global;\\n        const { camera } = this.global.camera;\\n        // update state\\n        this._state.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._state.jump += key[keyCode.SPACE];\\n        this._state.touches += count[0];\\n        for (let i = 0; i < button.length; i++) {\\n            this._state.mouse[i] += button[i];\\n        }\\n        this._state.shift += key[keyCode.SHIFT];\\n        this._state.ctrl += key[keyCode.CTRL];\\n        const isFps = state.cameraMode === 'fps';\\n        const isFirstPerson = state.cameraMode === 'fly' || isFps;\\n        if (!isFirstPerson && this._state.axis.length() > 0) {\\n            events.fire('inputEvent', 'requestFirstPerson');\\n        }\\n        const orbit = +(state.cameraMode === 'orbit');\\n        const fly = +isFirstPerson;\\n        const double = +(this._state.touches > 1);\\n        const pan = this._state.mouse[2] || +(button[2] === -1) || double;\\n        const orbitFactor = fly ? camera.fov / 120 : 1;\\n        const { deltas } = this.frame;\\n        // desktop move\\n        const v = tmpV1.set(0, 0, 0);\\n        const keyMove = this._state.axis.clone();\\n        if (isFps) {\\n            // In FPS mode, normalize only horizontal axes so jump doesn't reduce speed\\n            keyMove.y = 0;\\n        }\\n        keyMove.normalize();\\n        v.add(keyMove.mulScalar(fly * this.moveSpeed * (this._state.shift ? 4 : this._state.ctrl ? 0.25 : 1) * dt));\\n        if (isFps) {\\n            // Pass jump signal as raw Y; FPS controller uses move[1] > 0 as boolean trigger\\n            v.y = this._state.jump > 0 ? 1 : 0;\\n        }\\n        const panMove = screenToWorld(camera, mouse[0], mouse[1], distance);\\n        v.add(panMove.mulScalar(pan));\\n        const wheelMove = new Vec3(0, 0, -wheel[0]);\\n        v.add(wheelMove.mulScalar(this.wheelSpeed * dt));\\n        // FIXME: need to flip z axis for orbit camera\\n        deltas.move.append([v.x, v.y, orbit ? -v.z : v.z]);\\n        // desktop rotate\\n        v.set(0, 0, 0);\\n        mouseRotate.set(mouse[0], mouse[1], 0);\\n        v.add(mouseRotate.mulScalar((1 - pan) * this.orbitSpeed * orbitFactor * dt));\\n        deltas.rotate.append([v.x, v.y, v.z]);\\n        // mobile move\\n        v.set(0, 0, 0);\\n        const orbitMove = screenToWorld(camera, touch[0], touch[1], distance);\\n        v.add(orbitMove.mulScalar(orbit * pan));\\n        // Use touch joystick values for fly movement (X = strafe, Y = forward/backward)\\n        flyMove.set(this._touchJoystickX, 0, -this._touchJoystickY);\\n        v.add(flyMove.mulScalar(fly * this.moveSpeed * dt));\\n        pinchMove.set(0, 0, pinch[0]);\\n        v.add(pinchMove.mulScalar(orbit * double * this.pinchSpeed * dt));\\n        deltas.move.append([v.x, v.y, v.z]);\\n        // mobile rotate\\n        v.set(0, 0, 0);\\n        orbitRotate.set(touch[0], touch[1], 0);\\n        v.add(orbitRotate.mulScalar(orbit * (1 - pan) * this.orbitSpeed * dt));\\n        // In fly mode, use any touch for look-around (joystick captures its own touches)\\n        // Exclude multi-touch (double) to avoid interference with pinch gestures\\n        // 1.25x sensitivity for touch look-around\\n        flyRotate.set(touch[0], touch[1], 0);\\n        v.add(flyRotate.mulScalar(fly * (1 - double) * this.orbitSpeed * orbitFactor * 1.25 * dt));\\n        deltas.rotate.append([v.x, v.y, v.z]);\\n        // gamepad move\\n        v.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        // gamepad rotate\\n        v.set(0, 0, 0);\\n        stickRotate.set(rightStick[0], rightStick[1], 0);\\n        v.add(stickRotate.mulScalar(this.orbitSpeed * orbitFactor * dt));\\n        deltas.rotate.append([v.x, v.y, v.z]);\\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\\nconst EDGE_ALPHA: f32 = 0.85;\\n\\n// Interior fill alpha (subtle orientation tint)\\nconst FILL_ALPHA: f32 = 0.12;\\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    pad2: 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, emptyLevel):\\n//   result: 0 = empty, 1 = solid, 2+ = mixed leaf (2 + leafDataIndex)\\n//   emptyLevel: octree level at which emptiness was detected (only meaningful when result == 0)\\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\\n        if (node == SOLID_LEAF_MARKER) {\\n            return vec2u(1u, 0u);\\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\\nfn shadeVoxelHit(hitPos: vec3f, voxMin: vec3f, voxelRes: f32, ro: vec3f, isSolid: bool) -> 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    let distFade = clamp(1.0 - dist * 0.01, 0.2, 1.0);\\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 (isSolid) {\\n        if (faceAxis == 0u) { baseColor = vec3f(1.0, 0.25, 0.2); }\\n        else if (faceAxis == 1u) { baseColor = vec3f(0.8, 0.15, 0.1); }\\n        else { baseColor = vec3f(0.55, 0.08, 0.05); }\\n    } else {\\n        if (faceAxis == 0u) { baseColor = vec3f(0.7, 0.7, 0.72); }\\n        else if (faceAxis == 1u) { baseColor = vec3f(0.5, 0.5, 0.52); }\\n        else { baseColor = vec3f(0.33, 0.33, 0.35); }\\n    }\\n\\n    let alpha = mix(FILL_ALPHA, EDGE_ALPHA, ef) * distFade;\\n\\n    return vec4f(mix(baseColor, vec3f(0.0), alpha) * 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    // Convert from PlayCanvas world space to voxel space (negate X and Y)\\n    let ro = vec3f(-worldNear.x, -worldNear.y, worldNear.z);\\n    let rd = normalize(vec3f(-(worldFar.x - worldNear.x), -(worldFar.y - worldNear.y), worldFar.z - worldNear.z));\\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    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 emptyLevel = qResult.y;\\n\\n        if (blockResult == 0u && emptyLevel >= 1u) {\\n            // Large empty region: advance the block DDA past the empty cell\\n            let cellBlocks = i32(1u << emptyLevel);\\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            if (blockResult != 0u) {\\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                    if (isSolid) {\\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, blockResult == 1u);\\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    if (uniforms.displayMode == 0u) {\\n        textureStore(outputTexture, vec2i(px, py), vec4f(0.0));\\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}\\n`;\\n// ---------------------------------------------------------------------------\\n// VoxelDebugOverlay class\\n// ---------------------------------------------------------------------------\\nclass VoxelDebugOverlay {\\n    app;\\n    camera;\\n    compute;\\n    storageTexture;\\n    overlayMaterial;\\n    nodesBuffer;\\n    leafDataBuffer;\\n    collider;\\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, collider, camera) {\\n        this.app = app;\\n        this.camera = camera;\\n        this.collider = collider;\\n        const device = app.graphicsDevice;\\n        // Upload SVO node array as a read-only storage buffer\\n        const nodesData = collider.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 = collider.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('pad2', 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, collider } = 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        // Set compute uniforms\\n        compute.setParameter('invVP', this.invVP.data);\\n        compute.setParameter('screenWidth', width);\\n        compute.setParameter('screenHeight', height);\\n        compute.setParameter('gridMinX', collider.gridMinX);\\n        compute.setParameter('gridMinY', collider.gridMinY);\\n        compute.setParameter('gridMinZ', collider.gridMinZ);\\n        compute.setParameter('voxelRes', collider.voxelResolution);\\n        compute.setParameter('numVoxelsX', collider.numVoxelsX);\\n        compute.setParameter('numVoxelsY', collider.numVoxelsY);\\n        compute.setParameter('numVoxelsZ', collider.numVoxelsZ);\\n        compute.setParameter('leafSize', collider.leafSize);\\n        compute.setParameter('treeDepth', collider.treeDepth);\\n        compute.setParameter('projScaleY', cam.projectionMatrix.data[5]);\\n        compute.setParameter('displayMode', this.mode === 'heatmap' ? 1 : 0);\\n        compute.setParameter('pad2', 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\\nconst gammaChunkGlsl = `\\nvec3 prepareOutputFromGamma(vec3 gammaColor) {\\n    return gammaColor;\\n}\\n`;\\nconst gammaChunkWgsl = `\\nfn prepareOutputFromGamma(gammaColor: vec3f) -> vec3f {\\n    return gammaColor;\\n}\\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    annotations;\\n    forceRenderNextFrame = false;\\n    voxelOverlay = null;\\n    origChunks;\\n    constructor(global, gsplatLoad, skyboxLoad, voxelLoad) {\\n        this.global = global;\\n        const { app, settings, config, events, state, camera } = global;\\n        const { graphicsDevice } = app;\\n        // enable anonymous CORS for image loading in safari\\n        app.loader.getHandler('texture').imgParser.crossOrigin = 'anonymous';\\n        this.origChunks = {\\n            glsl: {\\n                gsplatOutputVS: ShaderChunks.get(graphicsDevice, 'glsl').get('gsplatOutputVS')\\n            },\\n            wgsl: {\\n                gsplatOutputVS: ShaderChunks.get(graphicsDevice, 'wgsl').get('gsplatOutputVS')\\n            }\\n        };\\n        // render skybox as plain equirect\\n        const glsl = ShaderChunks.get(graphicsDevice, 'glsl');\\n        glsl.set('skyboxPS', glsl.get('skyboxPS').replace('mapRoughnessUv(uv, mipLevel)', 'uv'));\\n        const wgsl = ShaderChunks.get(graphicsDevice, 'wgsl');\\n        wgsl.set('skyboxPS', wgsl.get('skyboxPS').replace('mapRoughnessUv(uv, uniform.mipLevel)', 'uv'));\\n        // disable auto render, we'll render only when camera changes\\n        app.autoRender = false;\\n        // apply camera animation settings\\n        camera.camera.aspectRatio = graphicsDevice.width / graphicsDevice.height;\\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        // handle horizontal fov on canvas resize\\n        const updateHorizontalFov = () => {\\n            camera.camera.horizontalFov = graphicsDevice.width > graphicsDevice.height;\\n            app.renderNextFrame = true;\\n        };\\n        graphicsDevice.on('resizecanvas', updateHorizontalFov);\\n        updateHorizontalFov();\\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            // 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        });\\n        // wait for the model to load\\n        Promise.all([gsplatLoad, skyboxLoad, voxelLoad]).then((results) => {\\n            const gsplat = results[0].gsplat;\\n            const collider = results[2];\\n            // get scene bounding box\\n            const gsplatBbox = gsplat.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.inputController = new InputController(global);\\n            state.hasCollision = !!collider;\\n            // Create voxel debug overlay in WebGPU only\\n            if (collider && config.webgpu) {\\n                this.voxelOverlay = new VoxelDebugOverlay(app, collider, camera);\\n                this.voxelOverlay.mode = config.heatmap ? 'heatmap' : 'overlay';\\n                state.hasVoxelOverlay = true;\\n                events.on('voxelOverlayEnabled:changed', (value) => {\\n                    this.voxelOverlay.enabled = value;\\n                    app.renderNextFrame = true;\\n                });\\n            }\\n            this.cameraManager = new CameraManager(global, sceneBound, collider);\\n            applyCamera(this.cameraManager.camera);\\n            const { instance } = gsplat;\\n            if (instance) {\\n                // kick off gsplat sorting immediately now that camera is in position\\n                instance.sort(camera);\\n                // listen for sorting updates to trigger first frame events\\n                instance.sorter?.on('updated', () => {\\n                    // request frame render when sorting changes\\n                    app.renderNextFrame = true;\\n                    if (!state.readyToRender) {\\n                        // we're ready to render once the first sort has completed\\n                        state.readyToRender = true;\\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                });\\n            }\\n            else {\\n                const { gsplat } = app.scene;\\n                // quality ranges\\n                const ranges = {\\n                    mobile: {\\n                        low: 1,\\n                        high: 2\\n                    },\\n                    desktop: {\\n                        low: 2,\\n                        high: 4\\n                    }\\n                };\\n                const quality = platform.mobile ? ranges.mobile : ranges.desktop;\\n                // start in low quality mode so we can get user interacting asap\\n                results[0].gsplat.splatBudget = quality.low * 1000000;\\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                // we must force continuous rendering with streaming & lod system\\n                this.forceRenderNextFrame = true;\\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                        const updateLod = () => {\\n                            const settings = state.hqMode ? quality.high : quality.low;\\n                            results[0].gsplat.splatBudget = settings * 1000000;\\n                        };\\n                        events.on('hqMode:changed', updateLod);\\n                        updateLod();\\n                        // debug colorize lods\\n                        gsplat.colorizeLod = config.colorize;\\n                        gsplat.gpuSorting = config.gpusort;\\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    }\\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 enableCameraFrame = !app.xr.active && !config.nofx && (anyPostEffectEnabled(postEffectSettings) || highPrecisionRendering);\\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            // 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 gsplat output 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            // 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    }\\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/** Minimum penetration depth to report a collision (avoids floating-point noise at corners) */\\nconst PENETRATION_EPSILON = 1e-4;\\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 VoxelCollider {\\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 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     * Load a VoxelCollider from a .voxel.json URL.\\n     * The corresponding .voxel.bin is inferred by replacing the extension.\\n     *\\n     * @param jsonUrl - URL to the .voxel.json metadata file.\\n     * @returns A promise resolving to a VoxelCollider instance.\\n     */\\n    static async load(jsonUrl) {\\n        // Fetch metadata\\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        // Fetch binary data\\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        return new VoxelCollider(metadata, nodes, leafData);\\n    }\\n    /**\\n     * Query whether a world-space point lies inside a solid voxel.\\n     *\\n     * @param x - World X coordinate.\\n     * @param y - World Y coordinate.\\n     * @param z - World Z coordinate.\\n     * @returns True if the point is inside a solid voxel.\\n     */\\n    queryPoint(x, y, z) {\\n        const ix = Math.floor((x - this.gridMinX) / this.voxelResolution);\\n        const iy = Math.floor((y - this.gridMinY) / this.voxelResolution);\\n        const iz = Math.floor((z - this.gridMinZ) / this.voxelResolution);\\n        return this.isVoxelSolid(ix, iy, iz);\\n    }\\n    /**\\n     * Query a sphere against the voxel grid and write a push-out vector to resolve penetration.\\n     * Uses iterative single-voxel resolution: each iteration finds the deepest penetrating voxel,\\n     * resolves it, then re-checks. This avoids over-push from summing multiple voxels and\\n     * naturally handles corners (2 iterations) and flat walls (1 iteration).\\n     *\\n     * @param cx - Sphere center X in world units.\\n     * @param cy - Sphere center Y in world units.\\n     * @param cz - Sphere center Z in world units.\\n     * @param radius - Sphere radius in world units.\\n     * @param out - Object to receive the push-out vector.\\n     * @returns True if a collision was detected and out was written.\\n     */\\n    querySphere(cx, cy, cz, radius, out) {\\n        if (this.nodes.length === 0) {\\n            return false;\\n        }\\n        const maxIterations = 4;\\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        const push = this._push;\\n        // Constraint normals from previous iterations - prevents oscillation at corners\\n        // by ensuring subsequent pushes don't undo previous ones\\n        const normals = this._constraintNormals;\\n        let numNormals = 0;\\n        for (let iter = 0; iter < maxIterations; iter++) {\\n            if (!this.resolveDeepestPenetration(resolvedX, resolvedY, resolvedZ, radius)) {\\n                break;\\n            }\\n            hadCollision = true;\\n            let px = push.x;\\n            let py = push.y;\\n            let pz = push.z;\\n            // Project out components that contradict previous constraint normals\\n            for (let i = 0; i < numNormals; i++) {\\n                const n = normals[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            // Record this push direction as a constraint normal\\n            const len = Math.sqrt(push.x * push.x + push.y * push.y + push.z * push.z);\\n            if (len > PENETRATION_EPSILON && numNormals < 3) {\\n                const invLen = 1.0 / len;\\n                const n = normals[numNormals];\\n                n.x = push.x * invLen;\\n                n.y = push.y * invLen;\\n                n.z = push.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        // Only report collision if the total push is meaningful\\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     * Query a vertical capsule against the voxel grid and write a push-out vector to resolve\\n     * penetration. The capsule is a line segment from (cx, cy - halfHeight, cz) to\\n     * (cx, cy + halfHeight, cz) swept by radius. Uses the same iterative deepest-penetration\\n     * approach as querySphere.\\n     *\\n     * @param cx - Capsule center X in world units.\\n     * @param cy - Capsule center Y in world units.\\n     * @param cz - Capsule center Z in world units.\\n     * @param halfHeight - Half-height of the capsule's inner line segment in world units.\\n     * @param radius - Capsule radius in world units.\\n     * @param out - Object to receive the push-out vector.\\n     * @returns True if a collision was detected and out was written.\\n     */\\n    queryCapsule(cx, cy, cz, halfHeight, radius, out) {\\n        if (this.nodes.length === 0) {\\n            return false;\\n        }\\n        const maxIterations = 4;\\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        const push = this._push;\\n        // Constraint normals from previous iterations - prevents oscillation at corners\\n        // by ensuring subsequent pushes don't undo previous ones\\n        const normals = this._constraintNormals;\\n        let numNormals = 0;\\n        for (let iter = 0; iter < maxIterations; iter++) {\\n            if (!this.resolveDeepestPenetrationCapsule(resolvedX, resolvedY, resolvedZ, halfHeight, radius)) {\\n                break;\\n            }\\n            hadCollision = true;\\n            let px = push.x;\\n            let py = push.y;\\n            let pz = push.z;\\n            // Project out components that contradict previous constraint normals\\n            for (let i = 0; i < numNormals; i++) {\\n                const n = normals[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            // Record this push direction as a constraint normal\\n            const len = Math.sqrt(push.x * push.x + push.y * push.y + push.z * push.z);\\n            if (len > PENETRATION_EPSILON && numNormals < 3) {\\n                const invLen = 1.0 / len;\\n                const n = normals[numNormals];\\n                n.x = push.x * invLen;\\n                n.y = push.y * invLen;\\n                n.z = push.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        // Only report collision if the total push is meaningful\\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     * Find the single deepest penetrating voxel for the given sphere.\\n     * Writes the push-out vector into this._push.\\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     * @returns True if a penetrating voxel was found.\\n     */\\n    resolveDeepestPenetration(cx, cy, cz, radius) {\\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            this._push.x = bestPushX;\\n            this._push.y = bestPushY;\\n            this._push.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     * Writes the push-out vector into this._push.\\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     * @returns True if a penetrating voxel was found.\\n     */\\n    resolveDeepestPenetrationCapsule(cx, cy, cz, halfHeight, radius) {\\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            this._push.x = bestPushX;\\n            this._push.y = bestPushY;\\n            this._push.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/** @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, and snap vertical movement.\\n * All methods can be enabled simultaneously, allowing users to choose their preferred\\n * 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 * Snap Turn: Use right thumbstick X-axis for snap turning\\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     * Angle in degrees for each snap turn.\\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     * 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 - snap turning\\n                this.handleSnapTurning(inputSource);\\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     * 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 } = 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    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\\nvar version = \\\"1.15.1\\\";\\n\\nconst loadGsplat = async (app, config, progressCallback) => {\\n    const { contents, contentUrl, unified, aa } = 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: unified || filename.toLowerCase().endsWith('lod-meta.json'),\\n                asset\\n            });\\n            const material = entity.gsplat.unified ? app.scene.gsplat.material : entity.gsplat.material;\\n            material.setDefine('GSPLAT_AA', aa);\\n            material.setParameter('alphaClip', 1 / 255);\\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    // Create the graphics device\\n    const device = await createGraphicsDevice(canvas, {\\n        deviceTypes: config.webgpu ? ['webgpu'] : [],\\n        antialias: false,\\n        depth: true,\\n        stencil: false,\\n        xrCompatible: !config.webgpu,\\n        powerPreference: 'high-performance'\\n    });\\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(canvas),\\n        keyboard: new Keyboard(window)\\n    });\\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 };\\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.hqMode ? 1.0 : 0.5;\\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('hqMode: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 } = await createApp(canvas, config);\\n    // create events\\n    const events = new EventHandler();\\n    const state = observe(events, {\\n        loaded: false,\\n        readyToRender: false,\\n        hqMode: true,\\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        hasVoxelOverlay: false,\\n        voxelOverlayEnabled: false,\\n        isFullscreen: false,\\n        controlsHidden: false\\n    });\\n    const global = {\\n        app,\\n        settings: importSettings(settingsJson),\\n        config,\\n        state,\\n        events,\\n        camera\\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\\n    if (!config.webgpu) {\\n        initXr(global);\\n    }\\n    // Initialize user interface\\n    initUI(global);\\n    // Load model\\n    const gsplatLoad = loadGsplat(app, config, (progress) => {\\n        state.progress = progress;\\n    });\\n    // Load skybox\\n    const skyboxLoad = config.skyboxUrl &&\\n        loadSkybox(app, config.skyboxUrl).then((asset) => {\\n            app.scene.envAtlas = asset.resource;\\n        });\\n    // Load voxel collision data\\n    const voxelLoad = config.voxelUrl &&\\n        VoxelCollider.load(config.voxelUrl).catch((err) => {\\n            console.warn('Failed to load voxel data:', err);\\n            return null;\\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, voxelLoad);\\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    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\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\n    constructor(outputWriter: Writer, entry: ZipEntry) {\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/data-table';\n\ninterface KdTreeNode {\n    index: number;\n    count: number;          // self + children indices\n    left?: KdTreeNode;\n    right?: KdTreeNode;\n}\n\nclass KdTree {\n    centroids: DataTable;\n    root: KdTreeNode;\n\n    constructor(centroids: DataTable) {\n        const build = (indices: Uint32Array, depth: number): KdTreeNode => {\n            const { centroids } = this;\n            const values = centroids.columns[depth % centroids.numColumns].data;\n            indices.sort((a, b) => values[a] - values[b]);\n\n            if (indices.length === 1) {\n                return {\n                    index: indices[0],\n                    count: 1\n                };\n            } else if (indices.length === 2) {\n                return {\n                    index: indices[0],\n                    count: 2,\n                    right: {\n                        index: indices[1],\n                        count: 1\n                    }\n                };\n            }\n\n            const mid = indices.length >> 1;\n            const left = build(indices.subarray(0, mid), depth + 1);\n            const right = build(indices.subarray(mid + 1), depth + 1);\n\n            return {\n                index: indices[mid],\n                count: 1 + left.count + right.count,\n                left,\n                right\n            };\n        };\n\n        const indices = new Uint32Array(centroids.numRows);\n        for (let i = 0; i < indices.length; ++i) {\n            indices[i] = i;\n        }\n\n        this.centroids = centroids;\n        this.root = build(indices, 0);\n    }\n\n    findNearest(point: Float32Array, filterFunc?: (index: number) => boolean) {\n        const { centroids } = this;\n        const { numColumns } = centroids;\n\n        const calcDistance = (index: number) => {\n            let l = 0;\n            for (let i = 0; i < numColumns; ++i) {\n                const v = centroids.columns[i].data[index] - point[i];\n                l += v * v;\n            }\n            return l;\n        };\n\n        let mind = Infinity;\n        let mini = -1;\n        let cnt = 0;\n\n        const recurse = (node: KdTreeNode, depth: number) => {\n            const axis = depth % numColumns;\n            const distance = point[axis] - centroids.columns[axis].data[node.index];\n            const next = (distance > 0) ? node.right : node.left;\n\n            cnt++;\n\n            if (next) {\n                recurse(next, depth + 1);\n            }\n\n            // check index\n            if (!filterFunc || filterFunc(node.index)) {\n                const thisd = calcDistance(node.index);\n                if (thisd < mind) {\n                    mind = thisd;\n                    mini = node.index;\n                }\n            }\n\n            // check the other side\n            if (distance * distance < mind) {\n                const other = next === node.right ? node.left : node.right;\n                if (other) {\n                    recurse(other, depth + 1);\n                }\n            }\n        };\n\n        recurse(this.root, 0);\n\n        return { index: mini, distanceSqr: mind, cnt };\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    FloatPacking,\n    Shader,\n    StorageBuffer,\n    UniformBufferFormat,\n    UniformFormat,\n    GraphicsDevice\n} from 'playcanvas';\n\nimport { DataTable } from '../data-table/data-table.js';\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","import { GraphicsDevice } from 'playcanvas';\n\nimport { KdTree } from './kd-tree';\nimport { Column, DataTable } from '../data-table/data-table';\nimport { GpuClustering } from '../gpu/gpu-clustering';\nimport { logger } from '../utils/logger';\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\n// cpu cluster\nconst clusterCpu = (points: DataTable, centroids: DataTable, labels: Uint32Array) => {\n    const numColumns = points.numColumns;\n\n    const pData = points.columns.map(c => c.data);\n    const cData = centroids.columns.map(c => c.data);\n\n    const point = new Float32Array(numColumns);\n\n    const distance = (centroidIndex: number) => {\n        let result = 0;\n        for (let i = 0; i < numColumns; ++i) {\n            const v = point[i] - cData[i][centroidIndex];\n            result += v * v;\n        }\n        return result;\n    };\n\n    for (let i = 0; i < points.numRows; ++i) {\n        let mind = Infinity;\n        let mini = -1;\n\n        for (let c = 0; c < numColumns; ++c) {\n            point[c] = pData[c][i];\n        }\n\n        for (let j = 0; j < centroids.numRows; ++j) {\n            const d = distance(j);\n            if (d < mind) {\n                mind = d;\n                mini = j;\n            }\n        }\n\n        labels[i] = mini;\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    // Report iterations as anonymous nested steps\n    logger.progress.begin(iterations);\n\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        // Report iteration as anonymous step\n        logger.progress.step();\n    }\n\n    if (gpuClustering) {\n        gpuClustering.destroy();\n    }\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 * bins values into a histogram, then uses DP to find k centroids that\n * minimize weighted sum-of-squared-errors (SSE).\n *\n * Bin weights use sub-linear density weighting: weight = count^alpha.\n * With alpha < 1, sparse tail regions of the distribution earn\n * meaningful influence on centroid placement, preventing the\n * catastrophic clipping of extreme values that standard k-means\n * (alpha = 1) exhibits on heavy-tailed distributions.\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    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    // find global min/max\n    let dataMin = Infinity;\n    let dataMax = -Infinity;\n    for (let i = 0; i < N; ++i) {\n        const v = data[i];\n        if (v < dataMin) dataMin = v;\n        if (v > dataMax) dataMax = v;\n    }\n\n    // handle degenerate case where all values are identical\n    if (dataMax - dataMin < 1e-20) {\n        const centroids = new DataTable([new Column('data', new Float32Array(k))]);\n        centroids.getColumn(0).data.fill(dataMin);\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\n    const H = 1024;\n    const binWidth = (dataMax - dataMin) / H;\n    const counts = new Float64Array(H);\n    const sums = new Float64Array(H);\n\n    for (let i = 0; i < N; ++i) {\n        const bin = Math.min(H - 1, Math.floor((data[i] - dataMin) / binWidth));\n        counts[bin]++;\n        sums[bin] += data[i];\n    }\n\n    // compute bin centers (mean of values in each bin, or geometric center if empty)\n    const centers = new Float64Array(H);\n    for (let i = 0; i < H; ++i) {\n        centers[i] = counts[i] > 0 ? sums[i] / counts[i] : dataMin + (i + 0.5) * binWidth;\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    // clamp k to number of non-empty bins\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    // build output in the same format as cluster1d\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 { dirname, resolve } from 'pathe';\nimport { GraphicsDevice } from 'playcanvas';\n\nimport { version } from '../../../package.json';\nimport { Column, DataTable } from '../data-table/data-table';\nimport { sortMortonOrder } from '../data-table/morton-order';\nimport { type FileSystem, writeFile, ZipFileSystem } from '../io/write';\nimport { kmeans } from '../spatial/k-means';\nimport { quantize1d } from '../spatial/quantize-1d';\nimport { logger } from '../utils/logger';\nimport { sigmoid } from '../utils/math';\nimport { WebPCodec } from '../utils/webp-codec';\n\n/**\n * A function that creates a PlayCanvas GraphicsDevice on demand.\n *\n * Used for GPU-accelerated k-means clustering during SOG compression.\n * The application is responsible for caching if needed.\n *\n * @returns Promise resolving to a GraphicsDevice instance.\n */\ntype DeviceCreator = () => Promise<GraphicsDevice>;\n\nconst shNames = new Array(45).fill('').map((_, i) => `f_rest_${i}`);\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, width: 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};\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, dataTable, iterations, createDevice } = options;\n\n    // initialize output stream - use ZipFileSystem for bundled output\n    const zipFs = bundle ? new ZipFileSystem(await fs.createWriter(outputFilename)) : 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    // the layout function determines how the data is packed into the output texture.\n    const layout = identity; // rectChunks;\n\n    const writeWebp = async (filename: string, data: Uint8Array, w = width, h = height) => {\n        const pathname = zipFs ? filename : resolve(dirname(outputFilename), filename);\n        logger.log(`writing '${pathname}'...`);\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\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, width);\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, width);\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, width);\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 = shNames.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        logger.progress.step('Compressing spherical harmonics');\n        const { centroids, labels } = await kmeans(shDataTable, paletteSize, iterations, gpuDevice);\n\n        logger.progress.step('Quantizing spherical harmonics');\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, width);\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 = { '9': 1, '24': 2, '-1': 3 }[shNames.findIndex(v => !dataTable.hasColumn(v))] ?? 0;\n    const totalSteps = shBands > 0 ? 8 : 6;\n\n    // convert and write attributes\n    logger.progress.begin(totalSteps);\n\n    logger.progress.step('Generating morton order');\n    // indices already generated above\n\n    logger.progress.step('Writing positions');\n    const meansMinMax = await writeMeans();\n\n    logger.progress.step('Writing quaternions');\n    await writeQuaternions();\n\n    logger.progress.step('Compressing scales');\n    const scalesCodebook = await writeScales();\n\n    logger.progress.step('Compressing colors');\n    const colorsCodebook = await writeColors();\n\n    let shN = null;\n    if (shBands > 0) {\n        shN = await writeSH(shBands);\n    }\n\n    logger.progress.step('Finalizing');\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    await writeFile(outputFs, metaFilename, metaJson);\n\n    // Close zip archive if bundling\n    if (zipFs) {\n        await zipFs.close();\n    }\n};\n\nexport { writeSog, type DeviceCreator };\n","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","import { html, css, js } from '@playcanvas/supersplat-viewer';\nimport { basename, dirname, join } from 'pathe';\n\nimport { writeSog, type DeviceCreator } from './write-sog';\nimport { DataTable } from '../data-table/data-table';\nimport { type FileSystem, MemoryFileSystem, writeFile } from '../io/write';\nimport { toBase64 } from '../utils/base64';\n\ntype ViewerSettings = {\n    camera?: {\n        fov?: number;\n        position?: [number, number, number];\n        target?: [number, number, number];\n        startAnim?: string;\n        animTrack?: string;\n    };\n    background?: {\n        color?: [number, number, number];\n    };\n    animTracks?: unknown[];\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    // Load viewer settings from file if provided\n    const viewerSettings = (viewerSettingsJson ?? {})as ViewerSettings;\n\n    // Merge provided settings with defaults\n    const mergedSettings = {\n        camera: {\n            fov: 50,\n            position: [2, 2, -2] as [number, number, number],\n            target: [0, 0, 0] as [number, number, number],\n            startAnim: 'none',\n            animTrack: undefined as string | undefined,\n            ...viewerSettings.camera\n        },\n        background: {\n            color: [0.4, 0.4, 0.4] as [number, number, number],\n            ...viewerSettings.background\n        },\n        animTracks: viewerSettings.animTracks ?? []\n    };\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        }, 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(mergedSettings)}`)\n        .replace(content, `fetch(\"data:application/octet-stream;base64,${sogData}\")`)\n        .replace('.compressed.ply', '.sog');\n\n        await writeFile(fs, filename, resultHtml);\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        // Write .sog file\n        await writeSog({\n            filename: sogPath,\n            dataTable,\n            bundle: true,\n            iterations,\n            createDevice\n        }, fs);\n\n        // Write CSS file\n        const cssPath = join(outputDir, 'index.css');\n        await writeFile(fs, cssPath, css);\n\n        // Write JS file\n        const jsPath = join(outputDir, 'index.js');\n        await writeFile(fs, jsPath, js);\n\n        // Generate HTML with external references\n        const settings = 'settings: fetch(settingsUrl).then(response => response.json())';\n        const content = 'fetch(contentUrl)';\n\n        const resultHtml = html\n        .replace(settings, `settings: ${JSON.stringify(mergedSettings)}`)\n        .replace(content, `fetch(\"${sogFilename}\")`)\n        .replace('.compressed.ply', '.sog');\n\n        await writeFile(fs, filename, resultHtml);\n    }\n};\n\nexport { writeHtml };\n","import { DataTable, TypedArray } from '../data-table/data-table';\n\n// partition idx indices around the k-th largest element\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        // Median-of-three pivot selection (using values via idx)\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        // Partition around pivot\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        // Place pivot in its final position\n        idx[l + 1] = idx[j];\n        idx[j] = pivotIdx;\n\n        // Narrow to the side containing k\n        if (j >= k) r = j - 1;\n        if (j <= k) l = i;\n    }\n};\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 { dirname, resolve } from 'pathe';\nimport { BoundingBox, Mat4, Quat, Vec3 } from 'playcanvas';\n\nimport { writeSog, type DeviceCreator } from './write-sog.js';\nimport { TypedArray, DataTable } from '../data-table/data-table';\nimport { sortMortonOrder } from '../data-table/morton-order';\nimport { type FileSystem } from '../io/write';\nimport { BTreeNode, BTree } from '../spatial/b-tree';\nimport { logger } from '../utils/logger';\n\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:', { m, M, index });\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, dataTable, envDataTable, iterations, createDevice, chunkCount, chunkExtent } = options;\n\n    const outputDir = dirname(filename);\n\n    // ensure top-level output folder exists\n    await fs.mkdir(outputDir);\n\n    // write the environment sog\n    if (envDataTable?.numRows > 0) {\n        const pathname = resolve(outputDir, 'env/meta.json');\n\n        // ensure output folder exists before any files are written\n        await fs.mkdir(dirname(pathname));\n\n        logger.log(`writing ${pathname}...`);\n\n        await writeSog({\n            filename: pathname,\n            dataTable: envDataTable,\n            bundle: false,\n            iterations,\n            createDevice\n        }, fs);\n    }\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    // write lod-meta.json\n    const writer = await fs.createWriter(filename);\n    writer.write((new TextEncoder()).encode(JSON.stringify(meta, replacer)));\n    await writer.close();\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            // 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.permuteRows(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            logger.log(`writing ${pathname}...`);\n\n            await writeSog({\n                filename: pathname,\n                dataTable: unitDataTable,\n                indices,\n                bundle: false,\n                iterations,\n                createDevice\n            }, fs);\n        }\n    }\n};\n\nexport { writeLod };\n","import { type FileSystem } from '../io/write';\nimport { PlyData } from '../readers/read-ply';\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, plyData } = options;\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    // 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\nexport { writePly };\n","import { BoundingBox, Mat4, Quat, Vec3 } from 'playcanvas';\n\nimport type { Bounds } from './sparse-octree.js';\nimport { Column, DataTable } from '../data-table/data-table.js';\nimport { logger } from '../utils/logger.js';\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 3-sigma (Gaussians render out to 3-sigma)\n        localBox.halfExtents.set(scale.x * 3, scale.y * 3, scale.z * 3);\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 ${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\n/**\n * Get the AABB for a specific Gaussian.\n *\n * @param extents - DataTable with extent_x, extent_y, extent_z columns\n * @param dataTable - DataTable containing position data (x, y, z)\n * @param index - Gaussian index\n * @param outMin - Output Vec3 for minimum corner\n * @param outMax - Output Vec3 for maximum corner\n */\nconst getGaussianAABB = (\n    extents: DataTable,\n    dataTable: DataTable,\n    index: number,\n    outMin: Vec3,\n    outMax: Vec3\n): void => {\n    const x = dataTable.getColumnByName('x').data;\n    const y = dataTable.getColumnByName('y').data;\n    const z = dataTable.getColumnByName('z').data;\n\n    const ex = extents.getColumnByName('extent_x').data;\n    const ey = extents.getColumnByName('extent_y').data;\n    const ez = extents.getColumnByName('extent_z').data;\n\n    outMin.set(x[index] - ex[index], y[index] - ey[index], z[index] - ez[index]);\n    outMax.set(x[index] + ex[index], y[index] + ey[index], z[index] + ez[index]);\n};\n\n/**\n * Check if a Gaussian's AABB overlaps with a given box.\n *\n * @param extents - DataTable with extent_x, extent_y, extent_z columns\n * @param dataTable - DataTable containing position data (x, y, z)\n * @param index - Gaussian index\n * @param boxMin - Minimum corner of query box\n * @param boxMax - Maximum corner of query box\n * @returns true if AABBs overlap\n */\nconst gaussianOverlapsBox = (\n    extents: DataTable,\n    dataTable: DataTable,\n    index: number,\n    boxMin: Vec3,\n    boxMax: Vec3\n): boolean => {\n    const x = dataTable.getColumnByName('x').data;\n    const y = dataTable.getColumnByName('y').data;\n    const z = dataTable.getColumnByName('z').data;\n\n    const ex = extents.getColumnByName('extent_x').data;\n    const ey = extents.getColumnByName('extent_y').data;\n    const ez = extents.getColumnByName('extent_z').data;\n\n    const gMinX = x[index] - ex[index];\n    const gMinY = y[index] - ey[index];\n    const gMinZ = z[index] - ez[index];\n    const gMaxX = x[index] + ex[index];\n    const gMaxY = y[index] + ey[index];\n    const gMaxZ = z[index] + ez[index];\n\n    // AABB overlap test\n    return !(gMaxX < boxMin.x || gMinX > boxMax.x ||\n             gMaxY < boxMin.y || gMinY > boxMax.y ||\n             gMaxZ < boxMin.z || gMinZ > boxMax.z);\n};\n\nexport {\n    computeGaussianExtents,\n    getGaussianAABB,\n    gaussianOverlapsBox\n};\n\nexport type { GaussianExtentsResult };\n","import { Vec3 } from 'playcanvas';\n\nimport { DataTable, TypedArray } from '../data-table/data-table.js';\n\n/**\n * Partition indices around the k-th largest element using quickselect.\n * This is a copy from b-tree.ts to avoid cross-module dependencies.\n *\n * @param data - The data array to use for comparison values\n * @param idx - The index array to partition\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\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     * 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     * 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_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/data-table.js';\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<atomic<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>;\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    // 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    // Write result bit to output using linear indexing (z*16 + y*4 + x)\n    // Each batch's results are at batchIdx * maxBlocksPerBatch * 2 in the results array\n    let linearIdx = localPos.z * 16u + localPos.y * 4u + localPos.x;\n    let resultBase = batchIdx * uniforms.maxBlocksPerBatch * 2u;\n    let wordIndex = resultBase + flatBlockId * 2u + (linearIdx >> 5u);\n    let bitIndex = linearIdx & 31u;\n    \n    if (isSolid) {\n        atomicOr(&results[wordIndex], 1u << bitIndex);\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    // Reusable zero buffer for clearing results (grown as needed)\n    private zeroBuffer: Uint32Array;\n\n    /** Floats per Gaussian in the interleaved buffer (16 for alignment) */\n    private static readonly FLOATS_PER_GAUSSIAN = 16;\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            // 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 | BUFFERUSAGE_COPY_DST);\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        // Pre-allocate zero buffer for clearing results\n        const initialResultsU32 = 64 * GpuVoxelization.MAX_BLOCKS_PER_BATCH * 2;\n        this.zeroBuffer = new Uint32Array(initialResultsU32);\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        // Interleave and upload all Gaussian data\n        const interleavedData = new Float32Array(numGaussians * GpuVoxelization.FLOATS_PER_GAUSSIAN);\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        for (let i = 0; i < numGaussians; i++) {\n            const offset = i * GpuVoxelization.FLOATS_PER_GAUSSIAN;\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(0, interleavedData, 0, interleavedData.length);\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 | BUFFERUSAGE_COPY_DST, '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        // Ensure zero buffer is large enough for clearing results\n        if (this.zeroBuffer.length < resultsU32Count) {\n            this.zeroBuffer = new Uint32Array(resultsU32Count);\n        }\n\n        // Clear results buffer\n        slot.resultsBuffer.write(0, this.zeroBuffer, 0, resultsU32Count);\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 {\n    BlockAccumulator,\n    xyzToMorton,\n    mortonToXYZ,\n    popcount\n} from './sparse-octree';\nimport { logger } from '../utils/logger';\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 accumulator - BlockAccumulator with voxelization results\n * @returns New BlockAccumulator with filtered/filled data\n */\nfunction filterAndFillBlocks(accumulator: BlockAccumulator): BlockAccumulator {\n    const mixed = accumulator.getMixedBlocks();\n    const solid = accumulator.getSolidBlocks();\n    const masks = mixed.masks;\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.morton.length; i++) {\n        mixedMap.set(mixed.morton[i], i);\n    }\n\n    // New masks array (snapshot: cross-block lookups always read the original masks)\n    const newMasks = new Array<number>(masks.length);\n    let voxelsRemoved = 0;\n    let voxelsFilled = 0;\n\n    for (let i = 0; i < mixed.morton.length; i++) {\n        const morton = mixed.morton[i];\n        const origLo = masks[i * 2];\n        const origHi = masks[i * 2 + 1];\n\n        const [bx, by, bz] = mortonToXYZ(morton);\n\n        // --- In-block per-direction occupancy masks ---\n        // Each gives: bit p = 1 iff position p's neighbor in that direction is occupied\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        // For each face direction: look up the adjacent block, extract opposite-face\n        // bits, shift to align with our face positions, OR into the direction mask.\n\n        // +X: our lx=3 face <- adjacent's lx=0 face (shifted left by 3)\n        addCrossFace(bx + 1, by, bz, 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, 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, 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, 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, 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, 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 accumulator with state transitions (mixed->empty, mixed->solid)\n    const result = new BlockAccumulator();\n\n    for (let i = 0; i < mixed.morton.length; i++) {\n        const lo = newMasks[i * 2];\n        const hi = newMasks[i * 2 + 1];\n        // addBlock handles empty (discarded) and solid (stored without mask)\n        result.addBlock(mixed.morton[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.log(\n        `voxel filter: ${voxelsRemoved} voxels removed, ${voxelsFilled} voxels filled`\n    );\n\n    return result;\n}\n\n// ============================================================================\n// Cross-block face helpers\n// ============================================================================\n\n/**\n * Add cross-block face contribution for X/Y directions (shift stays within lo/hi words).\n *\n * @param nx - Adjacent block X coordinate.\n * @param ny - Adjacent block Y coordinate.\n * @param nz - Adjacent block Z coordinate.\n * @param solidSet - Set of Morton codes for solid blocks.\n * @param mixedMap - Map from Morton code to index in the mixed masks array.\n * @param masks - Interleaved voxel masks for mixed blocks [lo0, hi0, lo1, hi1, ...].\n * @param ourFaceMask - Bit mask selecting our block's face positions.\n * @param adjFaceMask - Bit mask selecting the adjacent block's opposite face positions.\n * @param shiftAmount - Number of bits to shift the adjacent face into our face positions.\n * @param shiftLeft - True to shift left, false to shift right.\n * @param curLo - Current low 32 bits of the direction mask.\n * @param curHi - Current high 32 bits of the direction mask.\n * @param write - Callback to write the updated (lo, hi) direction mask.\n */\nfunction addCrossFace(\n    nx: number, ny: number, nz: number,\n    solidSet: Set<number>,\n    mixedMap: Map<number, number>,\n    masks: number[],\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    const adjMorton = xyzToMorton(nx, ny, nz);\n\n    if (solidSet.has(adjMorton)) {\n        write(curLo | ourFaceMask, curHi | ourFaceMask);\n        return;\n    }\n\n    const adjIdx = mixedMap.get(adjMorton);\n    if (adjIdx === undefined) {\n        write(curLo, curHi);\n        return;\n    }\n\n    const adjLo = masks[adjIdx * 2];\n    const adjHi = masks[adjIdx * 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\n/**\n * Add cross-block face contribution for Z direction (crosses lo/hi boundary).\n *\n * +Z: our lz=3 (hi bits 16-31) <- adjacent's lz=0 (lo bits 0-15), shift left by 16\n * -Z: our lz=0 (lo bits 0-15) <- adjacent's lz=3 (hi bits 16-31), shift right by 16\n *\n * @param nx - Adjacent block X coordinate.\n * @param ny - Adjacent block Y coordinate.\n * @param nz - Adjacent block Z coordinate.\n * @param solidSet - Set of Morton codes for solid blocks.\n * @param mixedMap - Map from Morton code to index in the mixed masks array.\n * @param masks - Interleaved voxel masks for mixed blocks [lo0, hi0, lo1, hi1, ...].\n * @param plusZ - True for +Z direction, false for -Z.\n * @param curLo - Current low 32 bits of the direction mask.\n * @param curHi - Current high 32 bits of the direction mask.\n * @param write - Callback to write the updated (lo, hi) direction mask.\n */\nfunction addCrossFaceZ(\n    nx: number, ny: number, nz: number,\n    solidSet: Set<number>,\n    mixedMap: Map<number, number>,\n    masks: number[],\n    plusZ: boolean,\n    curLo: number, curHi: number,\n    write: (lo: number, hi: number) => void\n): void {\n    const adjMorton = xyzToMorton(nx, ny, nz);\n\n    if (solidSet.has(adjMorton)) {\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 adjIdx = mixedMap.get(adjMorton);\n    if (adjIdx === undefined) {\n        write(curLo, curHi);\n        return;\n    }\n\n    const adjLo = masks[adjIdx * 2];\n    const adjHi = masks[adjIdx * 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 type { DeviceCreator } from './write-sog';\nimport { DataTable } from '../data-table/data-table';\nimport { type FileSystem, writeFile } from '../io/write';\nimport { logger } from '../utils/logger';\nimport {\n    computeGaussianExtents,\n    GaussianBVH,\n    GpuVoxelization,\n    buildSparseOctree,\n    alignGridBounds,\n    type BatchSpec,\n    type MultiBatchResult\n} from '../voxel/index';\nimport {\n    BlockAccumulator,\n    xyzToMorton,\n    type SparseOctree\n} from '../voxel/sparse-octree';\nimport { filterAndFillBlocks } from '../voxel/voxel-filter';\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.5 */\n    opacityCutoff?: number;\n\n    /** Optional function to create a GPU device for voxelization */\n    createDevice?: DeviceCreator;\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    /** Original Gaussian scene bounds */\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 * 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.0',\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    // Write JSON metadata\n    logger.log(`writing '${jsonFilename}'...`);\n    await writeFile(fs, jsonFilename, JSON.stringify(metadata, null, 2));\n\n    // Write binary data (nodes + leafData concatenated)\n    const binFilename = jsonFilename.replace('.voxel.json', '.voxel.bin');\n    logger.log(`writing '${binFilename}'...`);\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};\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 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 *\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.5,\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.5,\n        createDevice\n    } = options;\n\n    if (!createDevice) {\n        throw new Error('writeVoxel requires a createDevice function for GPU voxelization');\n    }\n\n    logger.log(`voxelizing scene (resolution: ${voxelResolution}, opacity cutoff: ${opacityCutoff})...`);\n\n    logger.progress.begin(7);\n\n    // Phase 1: Compute Gaussian extents\n    logger.progress.step('Computing Gaussian extents');\n    const extentsResult = computeGaussianExtents(dataTable);\n    const bounds = extentsResult.sceneBounds;\n\n    // Phase 2: Build BVH\n    logger.progress.step('Building BVH');\n    const bvh = new GaussianBVH(dataTable, extentsResult.extents);\n\n    // Phase 3: Create GPU device and voxelization\n    logger.progress.step('Creating GPU device');\n    const device = await createDevice();\n\n    const gpuVoxelization = new GpuVoxelization(device);\n    gpuVoxelization.uploadAllGaussians(dataTable, extentsResult.extents);\n\n    // Align grid bounds to block boundaries BEFORE voxelization so the\n    // block coordinates used during voxelization match what the reader expects.\n    const blockSize = 4 * voxelResolution;  // Each block is 4x4x4 voxels\n    const gridBounds = alignGridBounds(\n        bounds.min.x, bounds.min.y, bounds.min.z,\n        bounds.max.x, bounds.max.y, bounds.max.z,\n        voxelResolution\n    );\n\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    logger.log(`grid: ${numBlocksX} x ${numBlocksY} x ${numBlocksZ} blocks`);\n\n    // Phase 4: Double-buffered pipelined voxelization\n    // Uses two GPU dispatch slots so the CPU can prepare the next mega-dispatch\n    // (BVH queries + index copying) while the GPU executes the current one.\n    let accumulator = new BlockAccumulator();\n    const batchSize = 16;  // 16x16x16 = 4096 blocks max per batch\n\n    logger.progress.step('Voxelizing');\n\n    // Mega-dispatch thresholds: flush when either limit is reached\n    const MEGA_MAX_BATCHES = 512;\n    const MEGA_MAX_INDICES = 4 * 1024 * 1024;  // 4M indices\n\n    const maxBlocks = GpuVoxelization.MAX_BLOCKS_PER_BATCH;\n    const numSlots = GpuVoxelization.NUM_SLOTS;\n\n    // Batch collection state — per-slot for double buffering\n    interface PendingBatch extends BatchSpec {\n        bx: number;  // absolute block start X (for Morton codes)\n        by: number;\n        bz: number;\n        numBlocksX: number;\n        numBlocksY: number;\n        numBlocksZ: number;\n    }\n\n    // Per-slot CPU-side index arrays\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    let megaDispatchCount = 0;\n    let skippedEmpty = 0;\n\n    // Inflight dispatch from previous flush (for pipelining)\n    let inflight: {\n        resultPromise: Promise<MultiBatchResult>;\n        batches: PendingBatch[];\n    } | null = null;\n\n    /**\n     * Process GPU results back into the block accumulator.\n     *\n     * @param masks - Raw Uint32 voxel masks from the GPU readback.\n     * @param batches - Batch metadata used to decode block positions.\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                // Skip empty blocks — vast majority are empty\n                if (maskLo === 0 && maskHi === 0) continue;\n\n                // Compute block coordinates directly from flat index\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 morton = xyzToMorton(absBlockX, absBlockY, absBlockZ);\n                accumulator.addBlock(morton, maskLo, maskHi);\n            }\n        }\n    };\n\n    /**\n     * Submit pending batches as a GPU mega-dispatch and set up pipelining.\n     * The GPU dispatch is fire-and-forget — the result promise is stored\n     * in `inflight` and awaited on the NEXT flush, allowing the CPU to\n     * prepare more batches while the GPU is busy.\n     */\n    const flushPendingBatches = async (): Promise<void> => {\n        if (pendingBatches.length === 0) return;\n\n        // Capture current batch state before clearing\n        const batchesToSubmit = pendingBatches.slice();\n        const submitSlot = currentSlot;\n        const submitIndexArray = slotIndexArrays[submitSlot];\n        const submitIndexCount = indexOffset;\n\n        // Switch to the other slot for collecting the next round\n        currentSlot = (currentSlot + 1) % numSlots;\n        pendingBatches.length = 0;\n        indexOffset = 0;\n\n        // Submit new dispatch FIRST so GPU starts working immediately\n        const resultPromise = gpuVoxelization.submitMultiBatch(\n            submitSlot,\n            submitIndexArray,\n            submitIndexCount,\n            batchesToSubmit,\n            voxelResolution,\n            opacityCutoff\n        );\n\n        // THEN await and process the previous inflight dispatch\n        // (the GPU was computing it while the CPU prepared this batch)\n        if (inflight) {\n            const result = await inflight.resultPromise;\n            processResults(result.masks, inflight.batches);\n            megaDispatchCount++;\n        }\n\n        inflight = { resultPromise, batches: batchesToSubmit };\n    };\n\n    // Inner progress for voxelization batches\n    const numZBatches = Math.max(1, Math.ceil(numBlocksZ / batchSize));\n    logger.progress.begin(10);\n    let lastVoxelStep = 0;\n    let totalBatches = 0;\n\n    // Process the entire scene, collecting batches for multi-dispatch\n    for (let bz = 0; bz < numBlocksZ; bz += batchSize) {\n        // Report inner progress scaled to 10 steps\n        const currentVoxelStep = Math.min(10, Math.floor(((bz / batchSize) + 1) / numZBatches * 10));\n        while (lastVoxelStep < currentVoxelStep) {\n            logger.progress.step();\n            lastVoxelStep++;\n        }\n\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                // Query BVH for overlapping Gaussians\n                const overlapping = bvh.queryOverlappingRaw(\n                    blockMinX, blockMinY, blockMinZ,\n                    blockMaxX, blockMaxY, blockMaxZ\n                );\n\n                if (overlapping.length === 0) {\n                    skippedEmpty++;\n                    continue;\n                }\n\n                // Ensure current slot's index array has enough capacity\n                const needed = indexOffset + overlapping.length;\n                if (needed > slotCapacities[currentSlot]) {\n                    slotCapacities[currentSlot] = Math.max(slotCapacities[currentSlot] * 2, needed);\n                    const newArray = new Uint32Array(slotCapacities[currentSlot]);\n                    newArray.set(slotIndexArrays[currentSlot].subarray(0, indexOffset));\n                    slotIndexArrays[currentSlot] = newArray;\n                }\n\n                // Copy overlapping Gaussian indices into current slot's array\n                slotIndexArrays[currentSlot].set(overlapping, indexOffset);\n\n                // Record batch metadata\n                pendingBatches.push({\n                    indexOffset,\n                    indexCount: overlapping.length,\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 += overlapping.length;\n                totalBatches++;\n\n                // Flush when mega-dispatch thresholds are reached\n                if (pendingBatches.length >= MEGA_MAX_BATCHES || indexOffset >= MEGA_MAX_INDICES) {\n                    await flushPendingBatches();\n                }\n            }\n        }\n    }\n\n    // Flush remaining pending batches\n    await flushPendingBatches();\n\n    // Await and process the final inflight dispatch\n    if (inflight) {\n        const result = await inflight.resultPromise;\n        processResults(result.masks, inflight.batches);\n        megaDispatchCount++;\n        inflight = null;\n    }\n\n    // Flush remaining inner voxelization progress steps\n    while (lastVoxelStep < 10) {\n        logger.progress.step();\n        lastVoxelStep++;\n    }\n\n    // Cleanup GPU resources (device lifecycle managed by caller)\n    gpuVoxelization.destroy();\n\n    logger.log(`voxelization complete: ${accumulator.count} non-empty blocks`);\n    logger.log(`pipelined: ${totalBatches} batches in ${megaDispatchCount} mega-dispatches, ${skippedEmpty} empty skips`);\n\n    // Phase 5: Filter floaters and fill holes\n    logger.progress.step('Filtering voxels');\n    accumulator = filterAndFillBlocks(accumulator);\n\n    // Phase 6: Build sparse octree\n    logger.progress.step('Building sparse octree');\n\n    // Build the sparse octree (gridBounds already computed before voxelization)\n    const octree = buildSparseOctree(\n        accumulator,\n        gridBounds,\n        bounds,  // Original scene bounds\n        voxelResolution\n    );\n\n    logger.log(`octree: depth=${octree.treeDepth}, interior=${octree.numInteriorNodes}, mixed=${octree.numMixedLeaves}`);\n\n    // Phase 7: Write output files\n    logger.progress.step('Writing output');\n    await writeOctreeFiles(fs, filename, octree);\n\n    const totalBytes = (octree.nodes.length + octree.leafData.length) * 4;\n    logger.log(`total size: ${(totalBytes / 1024).toFixed(1)} KB`);\n};\n\nexport { writeVoxel, type WriteVoxelOptions, type VoxelMetadata };\n","import { DataTable } from './data-table/data-table';\nimport { type FileSystem } from './io/write';\nimport { Options } from './types';\nimport { logger } from './utils/logger';\nimport { writeCompressedPly } from './writers/write-compressed-ply';\nimport { writeCsv } from './writers/write-csv';\nimport { writeHtml } from './writers/write-html';\nimport { writeLod } from './writers/write-lod';\nimport { writePly } from './writers/write-ply';\nimport { writeSog, type DeviceCreator } from './writers/write-sog';\nimport { writeVoxel } from './writers/write-voxel';\n\n/**\n * Supported output file formats for Gaussian splat data.\n *\n * - `ply` - Standard PLY format\n * - `compressed-ply` - Compressed PLY format\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 */\ntype OutputFormat = 'csv' | 'sog' | 'sog-bundle' | 'lod' | 'compressed-ply' | 'ply' | 'html' | 'html-bundle' | 'voxel';\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('.html')) {\n        return options.unbundled ? 'html' : 'html-bundle';\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    logger.log(`writing '${filename}'...`);\n\n    // write the file data\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: dataTable\n                    }]\n                }\n            }, 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                createDevice\n            }, fs);\n            break;\n    }\n};\n\nexport { getOutputFormat, writeFile, type OutputFormat, type WriteOptions };\n","import { Quat, Vec3 } from 'playcanvas';\n\nimport { Column, DataTable } from './data-table/data-table';\nimport { sortByVisibility } from './data-table/filter-visibility';\nimport { sortMortonOrder } from './data-table/morton-order';\nimport { computeSummary, type SummaryData } from './data-table/summary';\nimport { transform } from './data-table/transform';\nimport { logger } from './utils/logger';\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, use the `_raw` suffix\n * (e.g. `opacity_raw`, `scale_0_raw`, `f_dc_0_raw`).\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 * Filter splats by visibility score, keeping only the most visible ones.\n *\n * Visibility is computed as: linear_opacity * volume\n * where opacity is converted from logit and scales from log space.\n */\ntype FilterVisibility = {\n    /** Action type identifier. */\n    kind: 'filterVisibility';\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 * 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 * - `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 * - `filterVisibility` - Keep only the most visible splats by opacity * volume\n */\ntype ProcessAction = Translate | Rotate | Scale | FilterNaN | FilterByValue | FilterBands | FilterBox | FilterSphere | Param | Lod | Summary | MortonOrder | FilterVisibility;\n\nconst shNames = new Array(45).fill('').map((_, i) => `f_rest_${i}`);\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 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.permuteRows(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 * @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 = 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 = (dataTable: DataTable, processActions: ProcessAction[]) => {\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                transform(result, processAction.value, Quat.IDENTITY, 1);\n                break;\n            case 'rotate':\n                transform(result, Vec3.ZERO, new Quat().setFromEulerAngles(\n                    processAction.value.x,\n                    processAction.value.y,\n                    processAction.value.z\n                ), 1);\n                break;\n            case 'scale':\n                transform(result, Vec3.ZERO, Quat.IDENTITY, processAction.value);\n                break;\n            case 'filterNaN': {\n                const infOk = new Set(['opacity']);\n                const negInfOk = new Set(['scale_0', 'scale_1', 'scale_2']);\n                const columnNames = dataTable.columnNames;\n\n                const predicate = (row: any, rowIndex: number) => {\n                    for (const key of columnNames) {\n                        const value = row[key];\n                        if (!isFinite(value)) {\n                            if (value === -Infinity && (infOk.has(key) || 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                break;\n            }\n            case 'filterByValue': {\n                const { comparator } = processAction;\n                let { columnName, value } = processAction;\n\n                if (rawColumnMap[columnName]) {\n                    columnName = rawColumnMap[columnName];\n                } else if (inverseTransforms[columnName]) {\n                    value = inverseTransforms[columnName](value);\n                }\n\n                const Predicates = {\n                    'lt': (row: any, rowIndex: number) => row[columnName] < value,\n                    'lte': (row: any, rowIndex: number) => row[columnName] <= value,\n                    'gt': (row: any, rowIndex: number) => row[columnName] > value,\n                    'gte': (row: any, rowIndex: number) => row[columnName] >= value,\n                    'eq': (row: any, rowIndex: number) => row[columnName] === value,\n                    'neq': (row: any, rowIndex: number) => row[columnName] !== value\n                };\n                const predicate = Predicates[comparator] ?? ((row: any, rowIndex: number) => true);\n                result = filter(result, predicate);\n                break;\n            }\n            case 'filterBands': {\n                const inputBands = { '9': 1, '24': 2, '-1': 3 }[shNames.findIndex(v => !dataTable.hasColumn(v))] ?? 0;\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));\n                }\n                break;\n            }\n            case 'filterBox': {\n                const { min, max } = processAction;\n                const predicate = (row: any, rowIndex: number) => {\n                    const { x, y, z } = row;\n                    return x >= min.x && x <= max.x && y >= min.y && y <= max.y && z >= min.z && z <= max.z;\n                };\n                result = filter(result, predicate);\n                break;\n            }\n            case 'filterSphere': {\n                const { center, radius } = processAction;\n                const radiusSq = radius * radius;\n                const predicate = (row: any, rowIndex: number) => {\n                    const { x, y, z } = row;\n                    return (x - center.x) ** 2 + (y - center.y) ** 2 + (z - center.z) ** 2 < radiusSq;\n                };\n                result = filter(result, predicate);\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 'filterVisibility': {\n                const indices = new Uint32Array(result.numRows);\n                for (let i = 0; i < indices.length; i++) {\n                    indices[i] = i;\n                }\n                sortByVisibility(result, indices);\n\n                // Determine how many to keep\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                result = result.permuteRows(indices.subarray(0, keepCount));\n                break;\n            }\n        }\n    }\n\n    return result;\n};\n\nexport {\n    processDataTable,\n    type ProcessAction,\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 Param,\n    type Lod,\n    type Summary,\n    type MortonOrder,\n    type FilterVisibility\n};\n"],"names":["shNames","q","readFile","HARMONICS_COMPONENT_COUNT","CHUNK_SIZE","exports","createModule","SOLID_MASK","writeFile","html","css","js","quickselect"],"mappings":"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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,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,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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,IA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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;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,CAA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AU,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,C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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;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,UAA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","x_google_ignoreList":[12,31]}