@babylonjs/lite 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/index.js +457 -458
  2. package/dist/index.js.map +1 -1
  3. package/index.d.ts +107 -48
  4. package/lib/camera/geospatial-camera-controls.js +22 -0
  5. package/lib/camera/geospatial-camera-controls.js.map +1 -1
  6. package/lib/camera/geospatial-camera-fly.js +2 -1
  7. package/lib/camera/geospatial-camera-fly.js.map +1 -1
  8. package/lib/effect/effect-renderer.js +1 -1
  9. package/lib/effect/effect-renderer.js.map +1 -1
  10. package/lib/engine/engine.js +1 -1
  11. package/lib/frame-graph/depth-resolve-task.js +117 -0
  12. package/lib/frame-graph/depth-resolve-task.js.map +1 -0
  13. package/lib/frame-graph/transmission.js +4 -3
  14. package/lib/frame-graph/transmission.js.map +1 -1
  15. package/lib/index.js +5 -1
  16. package/lib/index.js.map +1 -1
  17. package/lib/material/shader/shader-material.js +4 -2
  18. package/lib/material/shader/shader-material.js.map +1 -1
  19. package/lib/material/shader/shader-pipeline.js +10 -0
  20. package/lib/material/shader/shader-pipeline.js.map +1 -1
  21. package/lib/material/shader/shader-renderable.js +19 -6
  22. package/lib/material/shader/shader-renderable.js.map +1 -1
  23. package/lib/material/shader/shader-thin-instance.js +1 -1
  24. package/lib/material/shader/shader-thin-instance.js.map +1 -1
  25. package/lib/post-process/taa.js +193 -0
  26. package/lib/post-process/taa.js.map +1 -0
  27. package/lib/scene/scene-core.js +5 -2
  28. package/lib/scene/scene-core.js.map +1 -1
  29. package/lib/shadow/csm-shadow-task-hooks.js +14 -6
  30. package/lib/shadow/csm-shadow-task-hooks.js.map +1 -1
  31. package/lib/shadow/pcf-shadow-task-hooks.js +6 -0
  32. package/lib/shadow/pcf-shadow-task-hooks.js.map +1 -1
  33. package/lib/sprite/billboard-custom-shader.js +32 -32
  34. package/lib/sprite/billboard-custom-shader.js.map +1 -1
  35. package/lib/sprite/billboard-pipeline.js +54 -56
  36. package/lib/sprite/billboard-pipeline.js.map +1 -1
  37. package/lib/sprite/custom-shader-core.js +1 -1
  38. package/lib/sprite/custom-shader-core.js.map +1 -1
  39. package/lib/sprite/shared/sprite-atlas.js +2 -2
  40. package/lib/sprite/shared/sprite-atlas.js.map +1 -1
  41. package/lib/sprite/sprite-2d-coverage-gamma.js +58 -0
  42. package/lib/sprite/sprite-2d-coverage-gamma.js.map +1 -0
  43. package/lib/sprite/sprite-2d-uvscroll.js +39 -0
  44. package/lib/sprite/sprite-2d-uvscroll.js.map +1 -0
  45. package/lib/sprite/sprite-2d.js +6 -40
  46. package/lib/sprite/sprite-2d.js.map +1 -1
  47. package/lib/sprite/sprite-coverage-gamma-hook.js +10 -0
  48. package/lib/sprite/sprite-coverage-gamma-hook.js.map +1 -0
  49. package/lib/sprite/sprite-custom-shader.js +2 -2
  50. package/lib/sprite/sprite-custom-shader.js.map +1 -1
  51. package/lib/sprite/sprite-pipeline.js +56 -71
  52. package/lib/sprite/sprite-pipeline.js.map +1 -1
  53. package/lib/sprite/sprite-renderable.js +5 -5
  54. package/lib/sprite/sprite-renderable.js.map +1 -1
  55. package/lib/sprite/sprite-renderer.js +4 -4
  56. package/lib/sprite/sprite-renderer.js.map +1 -1
  57. package/lib/sprite/sprite-scene.js +1 -1
  58. package/lib/sprite/sprite-scene.js.map +1 -1
  59. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"shader-renderable.js","sources":["../../../../src/material/shader/shader-renderable.ts"],"sourcesContent":["import { F32, U32, I32, U8 } from \"../../engine/typed-arrays.js\";\nimport { BU } from \"../../engine/gpu-flags.js\";\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport type { SceneContext } from \"../../scene/scene.js\";\nimport type { Mesh, MeshGPU } from \"../../mesh/mesh.js\";\nimport type { MeshGroupBuildResult, Renderable, DrawUpdateContext } from \"../../render/renderable.js\";\nimport type { Material } from \"../material.js\";\nimport type { Texture2D } from \"../../texture/texture-2d.js\";\nimport { createEmptyUniformBuffer } from \"../../resource/gpu-buffers.js\";\nimport { acquireTexture, releaseTexture } from \"../../resource/gpu-pool.js\";\nimport { getEffectiveAspectRatio, getProjectionMatrix, getViewMatrix, getViewProjectionMatrix } from \"../../camera/camera.js\";\nimport type { Camera } from \"../../camera/camera.js\";\nimport { mat4MultiplyInto } from \"../../math/mat4-multiply-into.js\";\nimport type { UboSpec } from \"../../shader/fragment-types.js\";\nimport type { ShaderAttributeName, ShaderMaterial, ShaderUniformType } from \"./shader-material.js\";\nimport type { ShaderPipelineBindings } from \"./shader-pipeline.js\";\nimport { _isShaderSystemUniform } from \"./shader-material.js\";\nimport { getOrCreateShaderPipeline, getOrCreateShaderPipelineBindings } from \"./shader-pipeline.js\";\n\n/** @internal Exported as a type only (zero runtime bytes) for the dynamically-imported\n * thin-instance builder. */\nexport interface ShaderPacket {\n readonly mesh: Mesh;\n readonly systemUBO: GPUBuffer;\n readonly systemData: Float32Array;\n /** @internal */\n _bindGroup: GPUBindGroup;\n /** @internal */\n _lastResourceVersion: number;\n /** @internal */\n _boundTextures: Texture2D[];\n /** @internal */\n _boundStorageBuffers: GPUBuffer[];\n /** @internal Set when the owning mesh is removed and this packet's GPU resources are\n * destroyed. A combined (multi-mesh) renderable keeps every packet in its\n * closure, so update()/draw() must skip disposed packets to avoid writing to\n * or submitting an already-destroyed systemUBO / vertex buffer. */\n _disposed?: boolean;\n /** @internal Back-reference to the combined renderable's packet array, so disposal can\n * splice this packet out and stop retaining/iterating dead chunk state every\n * frame (set only for merged opaque renderables). */\n _owner?: ShaderPacket[];\n}\n\ninterface ShaderMaterialRenderState extends ShaderMaterial {\n _shaderBindings?: ShaderPipelineBindings;\n _shaderCustomUbo?: GPUBuffer | null;\n _shaderCustomSpec?: UboSpec | null;\n _shaderCustomData?: ArrayBuffer | null;\n _shaderCustomVersion?: number;\n}\n\n/** @internal */\nexport type ShaderRenderPass = GPURenderPassEncoder | GPURenderBundleEncoder;\n\nexport function buildShaderMaterialRenderables(scene: SceneContext, meshes: Mesh[]): MeshGroupBuildResult {\n const renderables: Renderable[] = [];\n\n const rebuildSingle = (s: SceneContext, mesh: Mesh, materialOverride?: Material): Renderable =>\n buildSingleShaderRenderable(s, mesh, (materialOverride ?? mesh.material) as ShaderMaterial, materialOverride != null);\n\n const byMaterial = new Map<ShaderMaterial, Mesh[]>();\n for (const mesh of meshes) {\n const material = mesh.material as ShaderMaterial;\n let list = byMaterial.get(material);\n if (!list) {\n list = [];\n byMaterial.set(material, list);\n }\n list.push(mesh);\n }\n\n for (const [material, matMeshes] of byMaterial) {\n const built = buildMaterialRenderables(scene, material, matMeshes);\n renderables.push(...built);\n }\n\n return { renderables, rebuildSingle };\n}\n\n/** Async group entry point. Non-instanced ShaderMaterial scenes (the common case)\n * take the synchronous fast path and pull in zero instancing code. When at least\n * one mesh uses thin instances, the instancing module is dynamically imported and\n * the renderable helpers it needs are handed to it as positional arguments — NOT\n * module exports — so those helpers keep their mangled names in this chunk (an\n * export would de-mangle them, growing every ShaderMaterial scene's bundle). */\nexport async function buildShaderGroup(scene: SceneContext, meshes: Mesh[]): Promise<MeshGroupBuildResult> {\n if (!meshes.some((m) => !!m.thinInstances)) {\n return buildShaderMaterialRenderables(scene, meshes);\n }\n const mod = await import(\"./shader-thin-instance.js\");\n const cull = meshes.some((m) => !!m.thinInstances?._gpuCullingEnabled) ? await import(\"../../mesh/thin-instance-cull-binding.js\") : undefined;\n return mod.buildShaderRenderablesWithInstancing(\n scene,\n meshes,\n buildShaderMaterialRenderables,\n createPacket,\n updatePacket,\n updateCustomUbo,\n getAttrBuffer,\n getOrCreateShaderPipeline,\n getOrCreateShaderPipelineBindings,\n cull\n );\n}\n\nfunction buildSingleShaderRenderable(scene: SceneContext, mesh: Mesh, material: ShaderMaterial, isOverride: boolean): Renderable {\n return buildMaterialRenderables(scene, material, [mesh], isOverride)[0]!;\n}\n\nfunction buildMaterialRenderables(scene: SceneContext, material: ShaderMaterial, meshes: readonly Mesh[], isOverride = false): Renderable[] {\n const engine = scene.surface.engine;\n const bindings = getOrCreateShaderPipelineBindings(engine, material);\n ensureCustomUbo(engine, material, bindings.customSpec);\n const packets = meshes.map((mesh) => createPacket(scene, material, bindings.systemSpec, mesh));\n const isTransparent = material.needAlphaBlending;\n if (isTransparent) {\n return packets.map((packet) => createTransparentRenderable(scene, material, packet, isOverride));\n }\n return [createOpaqueRenderable(scene, material, packets, isOverride)];\n}\n\nfunction createPacket(scene: SceneContext, material: ShaderMaterial, systemSpec: UboSpec, mesh: Mesh): ShaderPacket {\n const engine = scene.surface.engine;\n const systemUBO = createEmptyUniformBuffer(engine, systemSpec._totalBytes, \"shader-system-ubo\");\n const systemData = new F32(systemSpec._totalBytes / 4);\n writeSystemUniforms(systemData, systemSpec, material, mesh, scene.camera, engine.canvas.width || 1, engine.canvas.height || 1);\n engine._device.queue.writeBuffer(systemUBO, 0, systemData);\n const packet: ShaderPacket = {\n mesh,\n systemUBO,\n systemData,\n _bindGroup: createShaderBindGroup(engine, material, systemUBO),\n _lastResourceVersion: material._resourceVersion,\n _boundTextures: collectShaderTextures(material),\n _boundStorageBuffers: collectShaderStorageBuffers(material),\n };\n for (const tex of packet._boundTextures) {\n acquireTexture(tex);\n }\n registerMeshTextureDisposer(scene, mesh, packet);\n return packet;\n}\n\nfunction createOpaqueRenderable(scene: SceneContext, material: ShaderMaterial, packets: readonly ShaderPacket[], isOverride: boolean): Renderable {\n // Only merged renderables (>1 mesh) can outlive an individual packet's mesh,\n // so give those packets a back-reference enabling disposal-time compaction.\n if (packets.length > 1) {\n for (const packet of packets) {\n packet._owner = packets as ShaderPacket[];\n }\n }\n const update = (context: DrawUpdateContext): void => {\n updateCustomUbo(scene.surface.engine, material);\n for (const packet of packets) {\n if (packet._disposed) {\n continue;\n }\n if (!isOverride && packet.mesh.material !== material) {\n continue;\n }\n updatePacket(scene, material, packet, context);\n }\n };\n const draw = (pass: ShaderRenderPass, engine: EngineContext): number => {\n let draws = 0;\n for (const packet of packets) {\n if (packet._disposed) {\n continue;\n }\n if (!isOverride && packet.mesh.material !== material) {\n continue;\n }\n drawPacket(pass, engine, material, packet);\n draws++;\n }\n return draws;\n };\n const r: Renderable = {\n order: packets.length === 1 ? (packets[0]!.mesh.renderOrder ?? 100) : Math.min(...packets.map((p) => p.mesh.renderOrder ?? 100)),\n isTransparent: false,\n mesh: packets.length === 1 ? packets[0]!.mesh : undefined,\n bind(eng, sig) {\n const bindings = getOrCreateShaderPipelineBindings(eng, material);\n return { renderable: r, pipeline: getOrCreateShaderPipeline(eng, sig, material, bindings), update, draw: (pass) => draw(pass, eng) };\n },\n };\n return r;\n}\n\nfunction createTransparentRenderable(scene: SceneContext, material: ShaderMaterial, packet: ShaderPacket, isOverride: boolean): Renderable {\n const wm = packet.mesh.worldMatrix as unknown as ArrayLike<number>;\n const sortCenter: [number, number, number] = [wm[12]!, wm[13]!, wm[14]!];\n const update = (context: DrawUpdateContext): void => {\n if (packet._disposed) {\n return;\n }\n if (!isOverride && packet.mesh.material !== material) {\n return;\n }\n updateCustomUbo(scene.surface.engine, material);\n updatePacket(scene, material, packet, context);\n const m = packet.mesh.worldMatrix as unknown as ArrayLike<number>;\n sortCenter[0] = m[12]!;\n sortCenter[1] = m[13]!;\n sortCenter[2] = m[14]!;\n };\n const draw = (pass: ShaderRenderPass, engine: EngineContext): number => {\n if (packet._disposed) {\n return 0;\n }\n if (!isOverride && packet.mesh.material !== material) {\n return 0;\n }\n drawPacket(pass, engine, material, packet);\n return 1;\n };\n const r: Renderable = {\n order: packet.mesh.renderOrder ?? 200,\n isTransparent: true,\n _transmissive: material.transmissive,\n mesh: packet.mesh,\n _worldCenter: sortCenter,\n bind(eng, sig) {\n const bindings = getOrCreateShaderPipelineBindings(eng, material);\n return { renderable: r, pipeline: getOrCreateShaderPipeline(eng, sig, material, bindings), update, draw: (pass) => draw(pass, eng) };\n },\n };\n return r;\n}\n\nfunction updatePacket(scene: SceneContext, material: ShaderMaterial, packet: ShaderPacket, context: DrawUpdateContext): void {\n const engine = scene.surface.engine;\n const state = material as ShaderMaterialRenderState;\n writeSystemUniforms(packet.systemData, state._shaderBindings!.systemSpec, material, packet.mesh, context._camera ?? scene.camera, context.targetWidth, context.targetHeight);\n engine._device.queue.writeBuffer(packet.systemUBO, 0, packet.systemData as Float32Array<ArrayBuffer>);\n if (packet._lastResourceVersion !== material._resourceVersion) {\n for (const tex of packet._boundTextures) {\n releaseTexture(tex);\n }\n packet._bindGroup = createShaderBindGroup(engine, material, packet.systemUBO);\n packet._boundTextures = collectShaderTextures(material);\n packet._boundStorageBuffers = collectShaderStorageBuffers(material);\n for (const tex of packet._boundTextures) {\n acquireTexture(tex);\n }\n packet._lastResourceVersion = material._resourceVersion;\n }\n}\n\nfunction drawPacket(pass: ShaderRenderPass, engine: EngineContext, material: ShaderMaterial, packet: ShaderPacket): void {\n const gpu = packet.mesh._gpu;\n for (let i = 0; i < material.attributes.length; i++) {\n pass.setVertexBuffer(i, getAttrBuffer(engine, gpu, material.attributes[i]!));\n }\n pass.setIndexBuffer(gpu.indexBuffer, gpu.indexFormat);\n pass.setBindGroup(1, packet._bindGroup);\n pass.drawIndexed(gpu.indexCount);\n}\n\nfunction ensureCustomUbo(engine: EngineContext, material: ShaderMaterial, customSpec: UboSpec | null): void {\n const state = material as ShaderMaterialRenderState;\n if (!customSpec) {\n state._shaderCustomUbo = null;\n state._shaderCustomData = null;\n state._shaderCustomVersion = material._uniformVersion;\n return;\n }\n if (state._shaderCustomUbo && state._shaderCustomData) {\n updateCustomUbo(engine, material);\n return;\n }\n state._shaderCustomUbo = createEmptyUniformBuffer(engine, customSpec._totalBytes, \"shader-custom-ubo\");\n state._shaderCustomData = new ArrayBuffer(customSpec._totalBytes);\n state._shaderCustomVersion = -1;\n updateCustomUbo(engine, material);\n}\n\nfunction updateCustomUbo(engine: EngineContext, material: ShaderMaterial): void {\n const state = material as ShaderMaterialRenderState;\n const customSpec = state._shaderCustomSpec;\n const customUbo = state._shaderCustomUbo;\n const customData = state._shaderCustomData;\n if (!customSpec || !customUbo || !customData || state._shaderCustomVersion === material._uniformVersion) {\n return;\n }\n const bytes = new U8(customData);\n bytes.fill(0);\n for (const [name, slot] of material._uniformValues) {\n if (_isShaderSystemUniform(name)) {\n continue;\n }\n const offset = customSpec._offsets.get(name);\n if (offset !== undefined) {\n writeTypedValue(customData, offset, slot.decl.type, slot.value);\n }\n }\n engine._device.queue.writeBuffer(customUbo, 0, bytes);\n state._shaderCustomVersion = material._uniformVersion;\n}\n\nfunction writeTypedValue(data: ArrayBuffer, offset: number, type: ShaderUniformType, value: Float32Array): void {\n if (type === \"u32\") {\n new U32(data, offset, 1)[0] = value[0]!;\n return;\n }\n if (type === \"i32\") {\n new I32(data, offset, 1)[0] = value[0]!;\n return;\n }\n new F32(data, offset, value.length).set(value);\n}\n\nfunction createShaderBindGroup(engine: EngineContext, material: ShaderMaterial, systemUBO: GPUBuffer): GPUBindGroup {\n const bindings = getOrCreateShaderPipelineBindings(engine, material);\n const entries: GPUBindGroupEntry[] = [{ binding: 0, resource: { buffer: systemUBO } }];\n let nextBinding = 1;\n if (bindings.customSpec) {\n ensureCustomUbo(engine, material, bindings.customSpec);\n entries.push({ binding: nextBinding++, resource: { buffer: (material as ShaderMaterialRenderState)._shaderCustomUbo! } });\n }\n for (const sampler of material.samplerDecls) {\n const slot = material._textureSlots.get(sampler.name);\n const tex = slot?.current;\n if (!tex) {\n throw new Error(`ShaderMaterial: sampler \"${sampler.name}\" has no Texture2D. Call setShaderTexture() before rendering.`);\n }\n entries.push({ binding: nextBinding++, resource: tex.view }, { binding: nextBinding++, resource: tex.sampler });\n }\n for (const storage of material.storageBufferDecls) {\n const slot = material._storageBufferSlots.get(storage.name);\n const buffer = slot?.current;\n if (!buffer) {\n throw new Error(`ShaderMaterial: storage buffer \"${storage.name}\" has no GPUBuffer. Call setShaderStorageBuffer() before rendering.`);\n }\n entries.push({ binding: nextBinding++, resource: { buffer } });\n }\n return engine._device.createBindGroup({ label: \"shader-material-bg\", layout: bindings.group1BGL, entries });\n}\n\nfunction collectShaderTextures(material: ShaderMaterial): Texture2D[] {\n const textures: Texture2D[] = [];\n for (const slot of material._textureSlots.values()) {\n if (slot.current) {\n textures.push(slot.current);\n }\n }\n return textures;\n}\n\nfunction collectShaderStorageBuffers(material: ShaderMaterial): GPUBuffer[] {\n const buffers: GPUBuffer[] = [];\n for (const slot of material._storageBufferSlots.values()) {\n if (slot.current) {\n buffers.push(slot.current);\n }\n }\n return buffers;\n}\n\nfunction registerMeshTextureDisposer(scene: SceneContext, mesh: Mesh, packet: ShaderPacket): void {\n const list = scene._meshDisposables.get(mesh) ?? [];\n list.push(() => {\n packet._disposed = true;\n if (packet._owner) {\n const oi = packet._owner.indexOf(packet);\n if (oi >= 0) {\n packet._owner.splice(oi, 1);\n }\n packet._owner = undefined;\n }\n packet.systemUBO.destroy();\n for (const tex of packet._boundTextures) {\n releaseTexture(tex);\n }\n packet._boundTextures = [];\n packet._boundStorageBuffers = [];\n });\n scene._meshDisposables.set(mesh, list);\n}\n\nfunction writeSystemUniforms(data: Float32Array, spec: UboSpec, material: ShaderMaterial, mesh: Mesh, camera: Camera | null, targetWidth: number, targetHeight: number): void {\n data.fill(0);\n const world = mesh.worldMatrix as unknown as Float32Array;\n const aspect = camera ? getEffectiveAspectRatio(camera, targetWidth, targetHeight) : 1;\n const view = camera ? (getViewMatrix(camera) as unknown as Float32Array) : null;\n const projection = camera ? (getProjectionMatrix(camera, aspect) as unknown as Float32Array) : null;\n const viewProjection = camera ? (getViewProjectionMatrix(camera, aspect) as unknown as Float32Array) : null;\n for (const uniform of material.uniformDecls) {\n if (!_isShaderSystemUniform(uniform.name)) {\n continue;\n }\n const offset = spec._offsets.get(uniform.name);\n if (offset === undefined) {\n continue;\n }\n const f = offset / 4;\n switch (uniform.name) {\n case \"world\":\n data.set(world, f);\n break;\n case \"view\":\n if (view) {\n data.set(view, f);\n }\n break;\n case \"projection\":\n if (projection) {\n data.set(projection, f);\n }\n break;\n case \"viewProjection\":\n if (viewProjection) {\n data.set(viewProjection, f);\n }\n break;\n case \"worldView\":\n if (view) {\n mat4MultiplyInto(data, f, view, 0, world, 0);\n }\n break;\n case \"worldViewProjection\":\n if (viewProjection) {\n mat4MultiplyInto(data, f, viewProjection, 0, world, 0);\n }\n break;\n case \"cameraPosition\":\n if (camera) {\n const wm = camera.worldMatrix as unknown as ArrayLike<number>;\n data[f] = wm[12]!;\n data[f + 1] = wm[13]!;\n data[f + 2] = wm[14]!;\n }\n break;\n case \"screenSize\":\n data[f] = targetWidth;\n data[f + 1] = targetHeight;\n break;\n case \"alphaCutoff\":\n data[f] = material._uniformValues.get(\"alphaCutoff\")?.value[0] ?? 0.4;\n break;\n }\n }\n}\n\nlet zeroAttrCache: WeakMap<object, Map<string, GPUBuffer>> | null = null;\n\nfunction getZeroAttrBuffer(engine: EngineContext, gpu: MeshGPU, name: string): GPUBuffer {\n if (!zeroAttrCache) {\n zeroAttrCache = new WeakMap();\n }\n let cache = zeroAttrCache.get(gpu as unknown as object);\n if (!cache) {\n cache = new Map();\n zeroAttrCache.set(gpu as unknown as object, cache);\n }\n const existing = cache.get(name);\n if (existing) {\n return existing;\n }\n const vertexCount = gpu.positionBuffer.size / 12;\n const stride = name === \"uv\" || name === \"uv2\" ? 8 : name === \"normal\" ? 12 : 16;\n const buffer = engine._device.createBuffer({ label: `shader-zero-${name}`, size: vertexCount * stride, usage: BU.VERTEX | BU.COPY_DST });\n cache.set(name, buffer);\n return buffer;\n}\n\nfunction getAttrBuffer(engine: EngineContext, gpu: MeshGPU, name: ShaderAttributeName): GPUBuffer {\n switch (name) {\n case \"position\":\n return gpu.positionBuffer;\n case \"normal\":\n return gpu.normalBuffer ?? getZeroAttrBuffer(engine, gpu, \"normal\");\n case \"uv\":\n return gpu.uvBuffer ?? getZeroAttrBuffer(engine, gpu, \"uv\");\n case \"uv2\":\n return gpu.uv2Buffer ?? getZeroAttrBuffer(engine, gpu, \"uv2\");\n case \"tangent\":\n return gpu.tangentBuffer ?? getZeroAttrBuffer(engine, gpu, \"tangent\");\n case \"color\":\n return gpu.colorBuffer ?? getZeroAttrBuffer(engine, gpu, \"color\");\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shader-renderable.js","sources":["../../../../src/material/shader/shader-renderable.ts"],"sourcesContent":["import { F32, U32, I32, U8 } from \"../../engine/typed-arrays.js\";\nimport { BU } from \"../../engine/gpu-flags.js\";\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport type { SceneContext } from \"../../scene/scene.js\";\nimport type { Mesh, MeshGPU } from \"../../mesh/mesh.js\";\nimport type { MeshGroupBuildResult, Renderable, DrawUpdateContext } from \"../../render/renderable.js\";\nimport type { Material } from \"../material.js\";\nimport type { Texture2D } from \"../../texture/texture-2d.js\";\nimport { createEmptyUniformBuffer } from \"../../resource/gpu-buffers.js\";\nimport { acquireTexture, releaseTexture } from \"../../resource/gpu-pool.js\";\nimport { getEffectiveAspectRatio, getProjectionMatrix, getViewMatrix, getViewProjectionMatrix } from \"../../camera/camera.js\";\nimport type { Camera } from \"../../camera/camera.js\";\nimport { mat4MultiplyInto } from \"../../math/mat4-multiply-into.js\";\nimport type { UboSpec } from \"../../shader/fragment-types.js\";\nimport type { ShaderAttributeName, ShaderMaterial, ShaderUniformType } from \"./shader-material.js\";\nimport type { ShaderPipelineBindings } from \"./shader-pipeline.js\";\nimport { _isShaderSystemUniform } from \"./shader-material.js\";\nimport { getOrCreateShaderPipeline, getOrCreateShaderPipelineBindings } from \"./shader-pipeline.js\";\n\n/** @internal Exported as a type only (zero runtime bytes) for the dynamically-imported\n * thin-instance builder. */\nexport interface ShaderPacket {\n readonly mesh: Mesh;\n readonly systemUBO: GPUBuffer;\n readonly systemData: Float32Array;\n /** @internal */\n _bindGroup: GPUBindGroup;\n /** @internal */\n _lastResourceVersion: number;\n /** @internal */\n _boundTextures: Texture2D[];\n /** @internal */\n _boundStorageBuffers: GPUBuffer[];\n /** @internal Set when the owning mesh is removed and this packet's GPU resources are\n * destroyed. A combined (multi-mesh) renderable keeps every packet in its\n * closure, so update()/draw() must skip disposed packets to avoid writing to\n * or submitting an already-destroyed systemUBO / vertex buffer. */\n _disposed?: boolean;\n /** @internal Back-reference to the combined renderable's packet array, so disposal can\n * splice this packet out and stop retaining/iterating dead chunk state every\n * frame (set only for merged opaque renderables). */\n _owner?: ShaderPacket[];\n}\n\ninterface ShaderMaterialRenderState extends ShaderMaterial {\n _shaderBindings?: ShaderPipelineBindings;\n _shaderCustomUbo?: GPUBuffer | null;\n _shaderCustomSpec?: UboSpec | null;\n _shaderCustomData?: ArrayBuffer | null;\n _shaderCustomVersion?: number;\n}\n\n/** @internal */\nexport type ShaderRenderPass = GPURenderPassEncoder | GPURenderBundleEncoder;\n\nexport function buildShaderMaterialRenderables(scene: SceneContext, meshes: Mesh[]): MeshGroupBuildResult {\n const renderables: Renderable[] = [];\n\n const rebuildSingle = (s: SceneContext, mesh: Mesh, materialOverride?: Material): Renderable =>\n buildSingleShaderRenderable(s, mesh, (materialOverride ?? mesh.material) as ShaderMaterial, materialOverride != null);\n\n const byMaterial = new Map<ShaderMaterial, Mesh[]>();\n for (const mesh of meshes) {\n const material = mesh.material as ShaderMaterial;\n let list = byMaterial.get(material);\n if (!list) {\n list = [];\n byMaterial.set(material, list);\n }\n list.push(mesh);\n }\n\n for (const [material, matMeshes] of byMaterial) {\n const built = buildMaterialRenderables(scene, material, matMeshes);\n renderables.push(...built);\n }\n\n return { renderables, rebuildSingle };\n}\n\n/** Async group entry point. Non-instanced ShaderMaterial scenes (the common case)\n * take the synchronous fast path and pull in zero instancing code. When at least\n * one mesh uses thin instances, the instancing module is dynamically imported and\n * the renderable helpers it needs are handed to it as positional arguments — NOT\n * module exports — so those helpers keep their mangled names in this chunk (an\n * export would de-mangle them, growing every ShaderMaterial scene's bundle). */\nexport async function buildShaderGroup(scene: SceneContext, meshes: Mesh[]): Promise<MeshGroupBuildResult> {\n if (!meshes.some((m) => !!m.thinInstances)) {\n return buildShaderMaterialRenderables(scene, meshes);\n }\n const mod = await import(\"./shader-thin-instance.js\");\n const cull = meshes.some((m) => !!m.thinInstances?._gpuCullingEnabled) ? await import(\"../../mesh/thin-instance-cull-binding.js\") : undefined;\n return mod.buildShaderRenderablesWithInstancing(\n scene,\n meshes,\n buildShaderMaterialRenderables,\n createPacket,\n updatePacket,\n updateCustomUbo,\n getAttrBuffer,\n getOrCreateShaderPipeline,\n getOrCreateShaderPipelineBindings,\n cull\n );\n}\n\nfunction buildSingleShaderRenderable(scene: SceneContext, mesh: Mesh, material: ShaderMaterial, isOverride: boolean): Renderable {\n return buildMaterialRenderables(scene, material, [mesh], isOverride)[0]!;\n}\n\nfunction buildMaterialRenderables(scene: SceneContext, material: ShaderMaterial, meshes: readonly Mesh[], isOverride = false): Renderable[] {\n const engine = scene.surface.engine;\n const bindings = getOrCreateShaderPipelineBindings(engine, material);\n ensureCustomUbo(engine, material, bindings.customSpec);\n const packets = meshes.map((mesh) => createPacket(scene, material, bindings.systemSpec, mesh));\n const isTransparent = material.needAlphaBlending;\n if (isTransparent) {\n return packets.map((packet) => createTransparentRenderable(scene, material, packet, isOverride));\n }\n return [createOpaqueRenderable(scene, material, packets, isOverride)];\n}\n\nfunction createPacket(scene: SceneContext, material: ShaderMaterial, systemSpec: UboSpec, mesh: Mesh): ShaderPacket {\n const engine = scene.surface.engine;\n const systemUBO = createEmptyUniformBuffer(engine, systemSpec._totalBytes, \"shader-system-ubo\");\n const systemData = new F32(systemSpec._totalBytes / 4);\n writeSystemUniforms(systemData, systemSpec, material, mesh, scene.camera, engine.canvas.width || 1, engine.canvas.height || 1);\n engine._device.queue.writeBuffer(systemUBO, 0, systemData);\n const packet: ShaderPacket = {\n mesh,\n systemUBO,\n systemData,\n _bindGroup: createShaderBindGroup(engine, material, systemUBO),\n _lastResourceVersion: material._resourceVersion,\n _boundTextures: collectShaderTextures(material),\n _boundStorageBuffers: collectShaderStorageBuffers(material),\n };\n for (const tex of packet._boundTextures) {\n acquireTexture(tex);\n }\n registerMeshTextureDisposer(scene, mesh, packet);\n return packet;\n}\n\nfunction createOpaqueRenderable(scene: SceneContext, material: ShaderMaterial, packets: readonly ShaderPacket[], isOverride: boolean): Renderable {\n // Only merged renderables (>1 mesh) can outlive an individual packet's mesh,\n // so give those packets a back-reference enabling disposal-time compaction.\n if (packets.length > 1) {\n for (const packet of packets) {\n packet._owner = packets as ShaderPacket[];\n }\n }\n const update = (context: DrawUpdateContext): void => {\n updateCustomUbo(scene.surface.engine, material);\n for (const packet of packets) {\n if (packet._disposed) {\n continue;\n }\n if (!isOverride && packet.mesh.material !== material) {\n continue;\n }\n updatePacket(scene, material, packet, context);\n }\n };\n const draw = (pass: ShaderRenderPass, engine: EngineContext): number => {\n let draws = 0;\n for (const packet of packets) {\n if (packet._disposed) {\n continue;\n }\n if (!isOverride && packet.mesh.material !== material) {\n continue;\n }\n drawPacket(pass, engine, material, packet);\n draws++;\n }\n return draws;\n };\n const r: Renderable = {\n order: packets.length === 1 ? (packets[0]!.mesh.renderOrder ?? 100) : Math.min(...packets.map((p) => p.mesh.renderOrder ?? 100)),\n isTransparent: false,\n mesh: packets.length === 1 ? packets[0]!.mesh : undefined,\n bind(eng, sig) {\n const bindings = getOrCreateShaderPipelineBindings(eng, material);\n return { renderable: r, pipeline: getOrCreateShaderPipeline(eng, sig, material, bindings), update, draw: (pass) => draw(pass, eng) };\n },\n };\n return r;\n}\n\nfunction createTransparentRenderable(scene: SceneContext, material: ShaderMaterial, packet: ShaderPacket, isOverride: boolean): Renderable {\n const wm = packet.mesh.worldMatrix as unknown as ArrayLike<number>;\n const sortCenter: [number, number, number] = [wm[12]!, wm[13]!, wm[14]!];\n const update = (context: DrawUpdateContext): void => {\n if (packet._disposed) {\n return;\n }\n if (!isOverride && packet.mesh.material !== material) {\n return;\n }\n updateCustomUbo(scene.surface.engine, material);\n updatePacket(scene, material, packet, context);\n const m = packet.mesh.worldMatrix as unknown as ArrayLike<number>;\n sortCenter[0] = m[12]!;\n sortCenter[1] = m[13]!;\n sortCenter[2] = m[14]!;\n };\n const draw = (pass: ShaderRenderPass, engine: EngineContext): number => {\n if (packet._disposed) {\n return 0;\n }\n if (!isOverride && packet.mesh.material !== material) {\n return 0;\n }\n drawPacket(pass, engine, material, packet);\n return 1;\n };\n const r: Renderable = {\n order: packet.mesh.renderOrder ?? 200,\n isTransparent: true,\n _transmissive: material.transmissive,\n mesh: packet.mesh,\n _worldCenter: sortCenter,\n bind(eng, sig) {\n const bindings = getOrCreateShaderPipelineBindings(eng, material);\n return { renderable: r, pipeline: getOrCreateShaderPipeline(eng, sig, material, bindings), update, draw: (pass) => draw(pass, eng) };\n },\n };\n return r;\n}\n\nfunction updatePacket(scene: SceneContext, material: ShaderMaterial, packet: ShaderPacket, context: DrawUpdateContext): void {\n const engine = scene.surface.engine;\n const state = material as ShaderMaterialRenderState;\n writeSystemUniforms(packet.systemData, state._shaderBindings!.systemSpec, material, packet.mesh, context._camera ?? scene.camera, context.targetWidth, context.targetHeight);\n engine._device.queue.writeBuffer(packet.systemUBO, 0, packet.systemData as Float32Array<ArrayBuffer>);\n if (packet._lastResourceVersion !== material._resourceVersion) {\n // Acquire the NEW bound textures BEFORE releasing the old set: a texture present in both (e.g. a material\n // that only swapped ONE of its textures) must never transiently drop to ref-count 0, or releaseTexture\n // would destroy a GPUTexture that the new bind group still uses. (Releasing first destroys a unique\n // ref-count-1 texture — exposed by a custom material binding a per-material texture nothing else shares.)\n const newTextures = collectShaderTextures(material);\n for (const tex of newTextures) {\n acquireTexture(tex);\n }\n for (const tex of packet._boundTextures) {\n releaseTexture(tex);\n }\n packet._bindGroup = createShaderBindGroup(engine, material, packet.systemUBO);\n packet._boundTextures = newTextures;\n packet._boundStorageBuffers = collectShaderStorageBuffers(material);\n packet._lastResourceVersion = material._resourceVersion;\n }\n}\n\nfunction drawPacket(pass: ShaderRenderPass, engine: EngineContext, material: ShaderMaterial, packet: ShaderPacket): void {\n const gpu = packet.mesh._gpu;\n for (let i = 0; i < material.attributes.length; i++) {\n pass.setVertexBuffer(i, getAttrBuffer(engine, packet.mesh, material.attributes[i]!));\n }\n pass.setIndexBuffer(gpu.indexBuffer, gpu.indexFormat);\n pass.setBindGroup(1, packet._bindGroup);\n pass.drawIndexed(gpu.indexCount);\n}\n\nfunction ensureCustomUbo(engine: EngineContext, material: ShaderMaterial, customSpec: UboSpec | null): void {\n const state = material as ShaderMaterialRenderState;\n if (!customSpec) {\n state._shaderCustomUbo = null;\n state._shaderCustomData = null;\n state._shaderCustomVersion = material._uniformVersion;\n return;\n }\n if (state._shaderCustomUbo && state._shaderCustomData) {\n updateCustomUbo(engine, material);\n return;\n }\n state._shaderCustomUbo = createEmptyUniformBuffer(engine, customSpec._totalBytes, \"shader-custom-ubo\");\n state._shaderCustomData = new ArrayBuffer(customSpec._totalBytes);\n state._shaderCustomVersion = -1;\n updateCustomUbo(engine, material);\n}\n\nfunction updateCustomUbo(engine: EngineContext, material: ShaderMaterial): void {\n const state = material as ShaderMaterialRenderState;\n const customSpec = state._shaderCustomSpec;\n const customUbo = state._shaderCustomUbo;\n const customData = state._shaderCustomData;\n if (!customSpec || !customUbo || !customData || state._shaderCustomVersion === material._uniformVersion) {\n return;\n }\n const bytes = new U8(customData);\n bytes.fill(0);\n for (const [name, slot] of material._uniformValues) {\n if (_isShaderSystemUniform(name)) {\n continue;\n }\n const offset = customSpec._offsets.get(name);\n if (offset !== undefined) {\n writeTypedValue(customData, offset, slot.decl.type, slot.value);\n }\n }\n engine._device.queue.writeBuffer(customUbo, 0, bytes);\n state._shaderCustomVersion = material._uniformVersion;\n}\n\nfunction writeTypedValue(data: ArrayBuffer, offset: number, type: ShaderUniformType, value: Float32Array): void {\n if (type === \"u32\") {\n new U32(data, offset, 1)[0] = value[0]!;\n return;\n }\n if (type === \"i32\") {\n new I32(data, offset, 1)[0] = value[0]!;\n return;\n }\n new F32(data, offset, value.length).set(value);\n}\n\nfunction createShaderBindGroup(engine: EngineContext, material: ShaderMaterial, systemUBO: GPUBuffer): GPUBindGroup {\n const bindings = getOrCreateShaderPipelineBindings(engine, material);\n const entries: GPUBindGroupEntry[] = [{ binding: 0, resource: { buffer: systemUBO } }];\n let nextBinding = 1;\n if (bindings.customSpec) {\n ensureCustomUbo(engine, material, bindings.customSpec);\n entries.push({ binding: nextBinding++, resource: { buffer: (material as ShaderMaterialRenderState)._shaderCustomUbo! } });\n }\n for (const sampler of material.samplerDecls) {\n const slot = material._textureSlots.get(sampler.name);\n const tex = slot?.current;\n if (!tex) {\n throw new Error(`ShaderMaterial: sampler \"${sampler.name}\" has no Texture2D. Call setShaderTexture() before rendering.`);\n }\n entries.push({ binding: nextBinding++, resource: tex.view }, { binding: nextBinding++, resource: tex.sampler });\n }\n for (const storage of material.storageBufferDecls) {\n const slot = material._storageBufferSlots.get(storage.name);\n const buffer = slot?.current;\n if (!buffer) {\n throw new Error(`ShaderMaterial: storage buffer \"${storage.name}\" has no GPUBuffer. Call setShaderStorageBuffer() before rendering.`);\n }\n entries.push({ binding: nextBinding++, resource: { buffer } });\n }\n return engine._device.createBindGroup({ label: \"shader-material-bg\", layout: bindings.group1BGL, entries });\n}\n\nfunction collectShaderTextures(material: ShaderMaterial): Texture2D[] {\n const textures: Texture2D[] = [];\n for (const slot of material._textureSlots.values()) {\n if (slot.current) {\n textures.push(slot.current);\n }\n }\n return textures;\n}\n\nfunction collectShaderStorageBuffers(material: ShaderMaterial): GPUBuffer[] {\n const buffers: GPUBuffer[] = [];\n for (const slot of material._storageBufferSlots.values()) {\n if (slot.current) {\n buffers.push(slot.current);\n }\n }\n return buffers;\n}\n\nfunction registerMeshTextureDisposer(scene: SceneContext, mesh: Mesh, packet: ShaderPacket): void {\n const list = scene._meshDisposables.get(mesh) ?? [];\n list.push(() => {\n packet._disposed = true;\n if (packet._owner) {\n const oi = packet._owner.indexOf(packet);\n if (oi >= 0) {\n packet._owner.splice(oi, 1);\n }\n packet._owner = undefined;\n }\n packet.systemUBO.destroy();\n for (const tex of packet._boundTextures) {\n releaseTexture(tex);\n }\n packet._boundTextures = [];\n packet._boundStorageBuffers = [];\n });\n scene._meshDisposables.set(mesh, list);\n}\n\nfunction writeSystemUniforms(data: Float32Array, spec: UboSpec, material: ShaderMaterial, mesh: Mesh, camera: Camera | null, targetWidth: number, targetHeight: number): void {\n data.fill(0);\n const world = mesh.worldMatrix as unknown as Float32Array;\n const aspect = camera ? getEffectiveAspectRatio(camera, targetWidth, targetHeight) : 1;\n const view = camera ? (getViewMatrix(camera) as unknown as Float32Array) : null;\n const projection = camera ? (getProjectionMatrix(camera, aspect) as unknown as Float32Array) : null;\n const viewProjection = camera ? (getViewProjectionMatrix(camera, aspect) as unknown as Float32Array) : null;\n for (const uniform of material.uniformDecls) {\n if (!_isShaderSystemUniform(uniform.name)) {\n continue;\n }\n const offset = spec._offsets.get(uniform.name);\n if (offset === undefined) {\n continue;\n }\n const f = offset / 4;\n switch (uniform.name) {\n case \"world\":\n data.set(world, f);\n break;\n case \"view\":\n if (view) {\n data.set(view, f);\n }\n break;\n case \"projection\":\n if (projection) {\n data.set(projection, f);\n }\n break;\n case \"viewProjection\":\n if (viewProjection) {\n data.set(viewProjection, f);\n }\n break;\n case \"worldView\":\n if (view) {\n mat4MultiplyInto(data, f, view, 0, world, 0);\n }\n break;\n case \"worldViewProjection\":\n if (viewProjection) {\n mat4MultiplyInto(data, f, viewProjection, 0, world, 0);\n }\n break;\n case \"cameraPosition\":\n if (camera) {\n const wm = camera.worldMatrix as unknown as ArrayLike<number>;\n data[f] = wm[12]!;\n data[f + 1] = wm[13]!;\n data[f + 2] = wm[14]!;\n }\n break;\n case \"screenSize\":\n data[f] = targetWidth;\n data[f + 1] = targetHeight;\n break;\n case \"alphaCutoff\":\n data[f] = material._uniformValues.get(\"alphaCutoff\")?.value[0] ?? 0.4;\n break;\n }\n }\n}\n\nlet zeroAttrCache: WeakMap<object, Map<string, GPUBuffer>> | null = null;\n\nfunction getZeroAttrBuffer(engine: EngineContext, gpu: MeshGPU, name: string): GPUBuffer {\n if (!zeroAttrCache) {\n zeroAttrCache = new WeakMap();\n }\n let cache = zeroAttrCache.get(gpu as unknown as object);\n if (!cache) {\n cache = new Map();\n zeroAttrCache.set(gpu as unknown as object, cache);\n }\n const existing = cache.get(name);\n if (existing) {\n return existing;\n }\n const vertexCount = gpu.positionBuffer.size / 12;\n const stride = name === \"uv\" || name === \"uv2\" ? 8 : name === \"normal\" ? 12 : 16;\n const buffer = engine._device.createBuffer({ label: `shader-zero-${name}`, size: vertexCount * stride, usage: BU.VERTEX | BU.COPY_DST });\n cache.set(name, buffer);\n return buffer;\n}\n\n/** Skinning vertex buffers live on the mesh's `skeleton` (live skinning) or `vat` (baked vertex\n * animation, which moves them off the dropped skeleton) — not on `MeshGPU`. */\nfunction getSkinBuffer(mesh: Mesh, field: \"jointsBuffer\" | \"weightsBuffer\" | \"joints1Buffer\" | \"weights1Buffer\"): GPUBuffer | null {\n return mesh.vat?.[field] ?? mesh.skeleton?.[field] ?? null;\n}\n\nfunction getAttrBuffer(engine: EngineContext, mesh: Mesh, name: ShaderAttributeName): GPUBuffer {\n const gpu = mesh._gpu;\n switch (name) {\n case \"position\":\n return gpu.positionBuffer;\n case \"normal\":\n return gpu.normalBuffer ?? getZeroAttrBuffer(engine, gpu, \"normal\");\n case \"uv\":\n return gpu.uvBuffer ?? getZeroAttrBuffer(engine, gpu, \"uv\");\n case \"uv2\":\n return gpu.uv2Buffer ?? getZeroAttrBuffer(engine, gpu, \"uv2\");\n case \"tangent\":\n return gpu.tangentBuffer ?? getZeroAttrBuffer(engine, gpu, \"tangent\");\n case \"color\":\n return gpu.colorBuffer ?? getZeroAttrBuffer(engine, gpu, \"color\");\n case \"joints\":\n return getSkinBuffer(mesh, \"jointsBuffer\") ?? getZeroAttrBuffer(engine, gpu, \"joints\");\n case \"weights\":\n return getSkinBuffer(mesh, \"weightsBuffer\") ?? getZeroAttrBuffer(engine, gpu, \"weights\");\n case \"joints1\":\n return getSkinBuffer(mesh, \"joints1Buffer\") ?? getZeroAttrBuffer(engine, gpu, \"joints1\");\n case \"weights1\":\n return getSkinBuffer(mesh, \"weights1Buffer\") ?? getZeroAttrBuffer(engine, gpu, \"weights1\");\n }\n}\n"],"names":[],"mappings":";;;;;;;;;AAuDO,SAAS,8BAAA,CAA+B,OAAqB,MAAA,EAAsC;AACtG,EAAA,MAAM,cAA4B,EAAC;AAEnC,EAAA,MAAM,aAAA,GAAgB,CAAC,CAAA,EAAiB,IAAA,EAAY,gBAAA,KAChD,2BAAA,CAA4B,CAAA,EAAG,IAAA,EAAO,gBAAA,IAAoB,IAAA,CAAK,QAAA,EAA6B,gBAAA,IAAoB,IAAI,CAAA;AAExH,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAA4B;AACnD,EAAA,KAAA,MAAW,QAAQ,MAAA,EAAQ;AACvB,IAAA,MAAM,WAAW,IAAA,CAAK,QAAA;AACtB,IAAA,IAAI,IAAA,GAAO,UAAA,CAAW,GAAA,CAAI,QAAQ,CAAA;AAClC,IAAA,IAAI,CAAC,IAAA,EAAM;AACP,MAAA,IAAA,GAAO,EAAC;AACR,MAAA,UAAA,CAAW,GAAA,CAAI,UAAU,IAAI,CAAA;AAAA,IACjC;AACA,IAAA,IAAA,CAAK,KAAK,IAAI,CAAA;AAAA,EAClB;AAEA,EAAA,KAAA,MAAW,CAAC,QAAA,EAAU,SAAS,CAAA,IAAK,UAAA,EAAY;AAC5C,IAAA,MAAM,KAAA,GAAQ,wBAAA,CAAyB,KAAA,EAAO,QAAA,EAAU,SAAS,CAAA;AACjE,IAAA,WAAA,CAAY,IAAA,CAAK,GAAG,KAAK,CAAA;AAAA,EAC7B;AAEA,EAAA,OAAO,EAAE,aAAa,aAAA,EAAc;AACxC;AAQA,eAAsB,gBAAA,CAAiB,OAAqB,MAAA,EAA+C;AACvG,EAAA,IAAI,CAAC,OAAO,IAAA,CAAK,CAAC,MAAM,CAAC,CAAC,CAAA,CAAE,aAAa,CAAA,EAAG;AACxC,IAAA,OAAO,8BAAA,CAA+B,OAAO,MAAM,CAAA;AAAA,EACvD;AACA,EAAA,MAAM,GAAA,GAAM,MAAM,OAAO,2BAA2B,CAAA;AACpD,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,CAAC,MAAM,CAAC,CAAC,CAAA,CAAE,aAAA,EAAe,kBAAkB,CAAA,GAAI,MAAM,OAAO,0CAA0C,CAAA,GAAI,MAAA;AACpI,EAAA,OAAO,GAAA,CAAI,oCAAA;AAAA,IACP,KAAA;AAAA,IACA,MAAA;AAAA,IACA,8BAAA;AAAA,IACA,YAAA;AAAA,IACA,YAAA;AAAA,IACA,eAAA;AAAA,IACA,aAAA;AAAA,IACA,yBAAA;AAAA,IACA,iCAAA;AAAA,IACA;AAAA,GACJ;AACJ;AAEA,SAAS,2BAAA,CAA4B,KAAA,EAAqB,IAAA,EAAY,QAAA,EAA0B,UAAA,EAAiC;AAC7H,EAAA,OAAO,wBAAA,CAAyB,OAAO,QAAA,EAAU,CAAC,IAAI,CAAA,EAAG,UAAU,EAAE,CAAC,CAAA;AAC1E;AAEA,SAAS,wBAAA,CAAyB,KAAA,EAAqB,QAAA,EAA0B,MAAA,EAAyB,aAAa,KAAA,EAAqB;AACxI,EAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,MAAA;AAC7B,EAAA,MAAM,QAAA,GAAW,iCAAA,CAAkC,MAAA,EAAQ,QAAQ,CAAA;AACnE,EAAA,eAAA,CAAgB,MAAA,EAAQ,QAAA,EAAU,QAAA,CAAS,UAAU,CAAA;AACrD,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,GAAA,CAAI,CAAC,IAAA,KAAS,YAAA,CAAa,KAAA,EAAO,QAAA,EAAU,QAAA,CAAS,UAAA,EAAY,IAAI,CAAC,CAAA;AAC7F,EAAA,MAAM,gBAAgB,QAAA,CAAS,iBAAA;AAC/B,EAAA,IAAI,aAAA,EAAe;AACf,IAAA,OAAO,OAAA,CAAQ,IAAI,CAAC,MAAA,KAAW,4BAA4B,KAAA,EAAO,QAAA,EAAU,MAAA,EAAQ,UAAU,CAAC,CAAA;AAAA,EACnG;AACA,EAAA,OAAO,CAAC,sBAAA,CAAuB,KAAA,EAAO,QAAA,EAAU,OAAA,EAAS,UAAU,CAAC,CAAA;AACxE;AAEA,SAAS,YAAA,CAAa,KAAA,EAAqB,QAAA,EAA0B,UAAA,EAAqB,IAAA,EAA0B;AAChH,EAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,MAAA;AAC7B,EAAA,MAAM,SAAA,GAAY,wBAAA,CAAyB,MAAA,EAAQ,UAAA,CAAW,aAAa,mBAAmB,CAAA;AAC9F,EAAA,MAAM,UAAA,GAAa,IAAI,GAAA,CAAI,UAAA,CAAW,cAAc,CAAC,CAAA;AACrD,EAAA,mBAAA,CAAoB,UAAA,EAAY,UAAA,EAAY,QAAA,EAAU,IAAA,EAAM,KAAA,CAAM,MAAA,EAAQ,MAAA,CAAO,MAAA,CAAO,KAAA,IAAS,CAAA,EAAG,MAAA,CAAO,MAAA,CAAO,UAAU,CAAC,CAAA;AAC7H,EAAA,MAAA,CAAO,OAAA,CAAQ,KAAA,CAAM,WAAA,CAAY,SAAA,EAAW,GAAG,UAAU,CAAA;AACzD,EAAA,MAAM,MAAA,GAAuB;AAAA,IACzB,IAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,IACA,UAAA,EAAY,qBAAA,CAAsB,MAAA,EAAQ,QAAA,EAAU,SAAS,CAAA;AAAA,IAC7D,sBAAsB,QAAA,CAAS,gBAAA;AAAA,IAC/B,cAAA,EAAgB,sBAAsB,QAAQ,CAAA;AAAA,IAC9C,oBAAA,EAAsB,4BAA4B,QAAQ;AAAA,GAC9D;AACA,EAAA,KAAA,MAAW,GAAA,IAAO,OAAO,cAAA,EAAgB;AACrC,IAAA,cAAA,CAAe,GAAG,CAAA;AAAA,EACtB;AACA,EAAA,2BAAA,CAA4B,KAAA,EAAO,MAAM,MAAM,CAAA;AAC/C,EAAA,OAAO,MAAA;AACX;AAEA,SAAS,sBAAA,CAAuB,KAAA,EAAqB,QAAA,EAA0B,OAAA,EAAkC,UAAA,EAAiC;AAG9I,EAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACpB,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC1B,MAAA,MAAA,CAAO,MAAA,GAAS,OAAA;AAAA,IACpB;AAAA,EACJ;AACA,EAAA,MAAM,MAAA,GAAS,CAAC,OAAA,KAAqC;AACjD,IAAA,eAAA,CAAgB,KAAA,CAAM,OAAA,CAAQ,MAAA,EAAQ,QAAQ,CAAA;AAC9C,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC1B,MAAA,IAAI,OAAO,SAAA,EAAW;AAClB,QAAA;AAAA,MACJ;AACA,MAAA,IAAI,CAAC,UAAA,IAAc,MAAA,CAAO,IAAA,CAAK,aAAa,QAAA,EAAU;AAClD,QAAA;AAAA,MACJ;AACA,MAAA,YAAA,CAAa,KAAA,EAAO,QAAA,EAAU,MAAA,EAAQ,OAAO,CAAA;AAAA,IACjD;AAAA,EACJ,CAAA;AACA,EAAA,MAAM,IAAA,GAAO,CAAC,IAAA,EAAwB,MAAA,KAAkC;AACpE,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC1B,MAAA,IAAI,OAAO,SAAA,EAAW;AAClB,QAAA;AAAA,MACJ;AACA,MAAA,IAAI,CAAC,UAAA,IAAc,MAAA,CAAO,IAAA,CAAK,aAAa,QAAA,EAAU;AAClD,QAAA;AAAA,MACJ;AACA,MAAA,UAAA,CAAW,IAAA,EAAM,MAAA,EAAQ,QAAA,EAAU,MAAM,CAAA;AACzC,MAAA,KAAA,EAAA;AAAA,IACJ;AACA,IAAA,OAAO,KAAA;AAAA,EACX,CAAA;AACA,EAAA,MAAM,CAAA,GAAgB;AAAA,IAClB,KAAA,EAAO,QAAQ,MAAA,KAAW,CAAA,GAAK,QAAQ,CAAC,CAAA,CAAG,KAAK,WAAA,IAAe,GAAA,GAAO,KAAK,GAAA,CAAI,GAAG,QAAQ,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,IAAA,CAAK,WAAA,IAAe,GAAG,CAAC,CAAA;AAAA,IAC/H,aAAA,EAAe,KAAA;AAAA,IACf,MAAM,OAAA,CAAQ,MAAA,KAAW,IAAI,OAAA,CAAQ,CAAC,EAAG,IAAA,GAAO,MAAA;AAAA,IAChD,IAAA,CAAK,KAAK,GAAA,EAAK;AACX,MAAA,MAAM,QAAA,GAAW,iCAAA,CAAkC,GAAA,EAAK,QAAQ,CAAA;AAChE,MAAA,OAAO,EAAE,UAAA,EAAY,CAAA,EAAG,QAAA,EAAU,yBAAA,CAA0B,KAAK,GAAA,EAAK,QAAA,EAAU,QAAQ,CAAA,EAAG,QAAQ,IAAA,EAAM,CAAC,SAAS,IAAA,CAAK,IAAA,EAAM,GAAG,CAAA,EAAE;AAAA,IACvI;AAAA,GACJ;AACA,EAAA,OAAO,CAAA;AACX;AAEA,SAAS,2BAAA,CAA4B,KAAA,EAAqB,QAAA,EAA0B,MAAA,EAAsB,UAAA,EAAiC;AACvI,EAAA,MAAM,EAAA,GAAK,OAAO,IAAA,CAAK,WAAA;AACvB,EAAA,MAAM,UAAA,GAAuC,CAAC,EAAA,CAAG,EAAE,CAAA,EAAI,GAAG,EAAE,CAAA,EAAI,EAAA,CAAG,EAAE,CAAE,CAAA;AACvE,EAAA,MAAM,MAAA,GAAS,CAAC,OAAA,KAAqC;AACjD,IAAA,IAAI,OAAO,SAAA,EAAW;AAClB,MAAA;AAAA,IACJ;AACA,IAAA,IAAI,CAAC,UAAA,IAAc,MAAA,CAAO,IAAA,CAAK,aAAa,QAAA,EAAU;AAClD,MAAA;AAAA,IACJ;AACA,IAAA,eAAA,CAAgB,KAAA,CAAM,OAAA,CAAQ,MAAA,EAAQ,QAAQ,CAAA;AAC9C,IAAA,YAAA,CAAa,KAAA,EAAO,QAAA,EAAU,MAAA,EAAQ,OAAO,CAAA;AAC7C,IAAA,MAAM,CAAA,GAAI,OAAO,IAAA,CAAK,WAAA;AACtB,IAAA,UAAA,CAAW,CAAC,CAAA,GAAI,CAAA,CAAE,EAAE,CAAA;AACpB,IAAA,UAAA,CAAW,CAAC,CAAA,GAAI,CAAA,CAAE,EAAE,CAAA;AACpB,IAAA,UAAA,CAAW,CAAC,CAAA,GAAI,CAAA,CAAE,EAAE,CAAA;AAAA,EACxB,CAAA;AACA,EAAA,MAAM,IAAA,GAAO,CAAC,IAAA,EAAwB,MAAA,KAAkC;AACpE,IAAA,IAAI,OAAO,SAAA,EAAW;AAClB,MAAA,OAAO,CAAA;AAAA,IACX;AACA,IAAA,IAAI,CAAC,UAAA,IAAc,MAAA,CAAO,IAAA,CAAK,aAAa,QAAA,EAAU;AAClD,MAAA,OAAO,CAAA;AAAA,IACX;AACA,IAAA,UAAA,CAAW,IAAA,EAAM,MAAA,EAAQ,QAAA,EAAU,MAAM,CAAA;AACzC,IAAA,OAAO,CAAA;AAAA,EACX,CAAA;AACA,EAAA,MAAM,CAAA,GAAgB;AAAA,IAClB,KAAA,EAAO,MAAA,CAAO,IAAA,CAAK,WAAA,IAAe,GAAA;AAAA,IAClC,aAAA,EAAe,IAAA;AAAA,IACf,eAAe,QAAA,CAAS,YAAA;AAAA,IACxB,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,YAAA,EAAc,UAAA;AAAA,IACd,IAAA,CAAK,KAAK,GAAA,EAAK;AACX,MAAA,MAAM,QAAA,GAAW,iCAAA,CAAkC,GAAA,EAAK,QAAQ,CAAA;AAChE,MAAA,OAAO,EAAE,UAAA,EAAY,CAAA,EAAG,QAAA,EAAU,yBAAA,CAA0B,KAAK,GAAA,EAAK,QAAA,EAAU,QAAQ,CAAA,EAAG,QAAQ,IAAA,EAAM,CAAC,SAAS,IAAA,CAAK,IAAA,EAAM,GAAG,CAAA,EAAE;AAAA,IACvI;AAAA,GACJ;AACA,EAAA,OAAO,CAAA;AACX;AAEA,SAAS,YAAA,CAAa,KAAA,EAAqB,QAAA,EAA0B,MAAA,EAAsB,OAAA,EAAkC;AACzH,EAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,MAAA;AAC7B,EAAA,MAAM,KAAA,GAAQ,QAAA;AACd,EAAA,mBAAA,CAAoB,MAAA,CAAO,UAAA,EAAY,KAAA,CAAM,eAAA,CAAiB,YAAY,QAAA,EAAU,MAAA,CAAO,IAAA,EAAM,OAAA,CAAQ,WAAW,KAAA,CAAM,MAAA,EAAQ,OAAA,CAAQ,WAAA,EAAa,QAAQ,YAAY,CAAA;AAC3K,EAAA,MAAA,CAAO,QAAQ,KAAA,CAAM,WAAA,CAAY,OAAO,SAAA,EAAW,CAAA,EAAG,OAAO,UAAuC,CAAA;AACpG,EAAA,IAAI,MAAA,CAAO,oBAAA,KAAyB,QAAA,CAAS,gBAAA,EAAkB;AAK3D,IAAA,MAAM,WAAA,GAAc,sBAAsB,QAAQ,CAAA;AAClD,IAAA,KAAA,MAAW,OAAO,WAAA,EAAa;AAC3B,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACtB;AACA,IAAA,KAAA,MAAW,GAAA,IAAO,OAAO,cAAA,EAAgB;AACrC,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACtB;AACA,IAAA,MAAA,CAAO,UAAA,GAAa,qBAAA,CAAsB,MAAA,EAAQ,QAAA,EAAU,OAAO,SAAS,CAAA;AAC5E,IAAA,MAAA,CAAO,cAAA,GAAiB,WAAA;AACxB,IAAA,MAAA,CAAO,oBAAA,GAAuB,4BAA4B,QAAQ,CAAA;AAClE,IAAA,MAAA,CAAO,uBAAuB,QAAA,CAAS,gBAAA;AAAA,EAC3C;AACJ;AAEA,SAAS,UAAA,CAAW,IAAA,EAAwB,MAAA,EAAuB,QAAA,EAA0B,MAAA,EAA4B;AACrH,EAAA,MAAM,GAAA,GAAM,OAAO,IAAA,CAAK,IAAA;AACxB,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,UAAA,CAAW,QAAQ,CAAA,EAAA,EAAK;AACjD,IAAA,IAAA,CAAK,eAAA,CAAgB,CAAA,EAAG,aAAA,CAAc,MAAA,EAAQ,MAAA,CAAO,MAAM,QAAA,CAAS,UAAA,CAAW,CAAC,CAAE,CAAC,CAAA;AAAA,EACvF;AACA,EAAA,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,WAAA,EAAa,GAAA,CAAI,WAAW,CAAA;AACpD,EAAA,IAAA,CAAK,YAAA,CAAa,CAAA,EAAG,MAAA,CAAO,UAAU,CAAA;AACtC,EAAA,IAAA,CAAK,WAAA,CAAY,IAAI,UAAU,CAAA;AACnC;AAEA,SAAS,eAAA,CAAgB,MAAA,EAAuB,QAAA,EAA0B,UAAA,EAAkC;AACxG,EAAA,MAAM,KAAA,GAAQ,QAAA;AACd,EAAA,IAAI,CAAC,UAAA,EAAY;AACb,IAAA,KAAA,CAAM,gBAAA,GAAmB,IAAA;AACzB,IAAA,KAAA,CAAM,iBAAA,GAAoB,IAAA;AAC1B,IAAA,KAAA,CAAM,uBAAuB,QAAA,CAAS,eAAA;AACtC,IAAA;AAAA,EACJ;AACA,EAAA,IAAI,KAAA,CAAM,gBAAA,IAAoB,KAAA,CAAM,iBAAA,EAAmB;AACnD,IAAA,eAAA,CAAgB,QAAQ,QAAQ,CAAA;AAChC,IAAA;AAAA,EACJ;AACA,EAAA,KAAA,CAAM,gBAAA,GAAmB,wBAAA,CAAyB,MAAA,EAAQ,UAAA,CAAW,aAAa,mBAAmB,CAAA;AACrG,EAAA,KAAA,CAAM,iBAAA,GAAoB,IAAI,WAAA,CAAY,UAAA,CAAW,WAAW,CAAA;AAChE,EAAA,KAAA,CAAM,oBAAA,GAAuB,EAAA;AAC7B,EAAA,eAAA,CAAgB,QAAQ,QAAQ,CAAA;AACpC;AAEA,SAAS,eAAA,CAAgB,QAAuB,QAAA,EAAgC;AAC5E,EAAA,MAAM,KAAA,GAAQ,QAAA;AACd,EAAA,MAAM,aAAa,KAAA,CAAM,iBAAA;AACzB,EAAA,MAAM,YAAY,KAAA,CAAM,gBAAA;AACxB,EAAA,MAAM,aAAa,KAAA,CAAM,iBAAA;AACzB,EAAA,IAAI,CAAC,cAAc,CAAC,SAAA,IAAa,CAAC,UAAA,IAAc,KAAA,CAAM,oBAAA,KAAyB,QAAA,CAAS,eAAA,EAAiB;AACrG,IAAA;AAAA,EACJ;AACA,EAAA,MAAM,KAAA,GAAQ,IAAI,EAAA,CAAG,UAAU,CAAA;AAC/B,EAAA,KAAA,CAAM,KAAK,CAAC,CAAA;AACZ,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,IAAI,CAAA,IAAK,SAAS,cAAA,EAAgB;AAChD,IAAA,IAAI,sBAAA,CAAuB,IAAI,CAAA,EAAG;AAC9B,MAAA;AAAA,IACJ;AACA,IAAA,MAAM,MAAA,GAAS,UAAA,CAAW,QAAA,CAAS,GAAA,CAAI,IAAI,CAAA;AAC3C,IAAA,IAAI,WAAW,MAAA,EAAW;AACtB,MAAA,eAAA,CAAgB,YAAY,MAAA,EAAQ,IAAA,CAAK,IAAA,CAAK,IAAA,EAAM,KAAK,KAAK,CAAA;AAAA,IAClE;AAAA,EACJ;AACA,EAAA,MAAA,CAAO,OAAA,CAAQ,KAAA,CAAM,WAAA,CAAY,SAAA,EAAW,GAAG,KAAK,CAAA;AACpD,EAAA,KAAA,CAAM,uBAAuB,QAAA,CAAS,eAAA;AAC1C;AAEA,SAAS,eAAA,CAAgB,IAAA,EAAmB,MAAA,EAAgB,IAAA,EAAyB,KAAA,EAA2B;AAC5G,EAAA,IAAI,SAAS,KAAA,EAAO;AAChB,IAAA,IAAI,GAAA,CAAI,MAAM,MAAA,EAAQ,CAAC,EAAE,CAAC,CAAA,GAAI,MAAM,CAAC,CAAA;AACrC,IAAA;AAAA,EACJ;AACA,EAAA,IAAI,SAAS,KAAA,EAAO;AAChB,IAAA,IAAI,GAAA,CAAI,MAAM,MAAA,EAAQ,CAAC,EAAE,CAAC,CAAA,GAAI,MAAM,CAAC,CAAA;AACrC,IAAA;AAAA,EACJ;AACA,EAAA,IAAI,IAAI,IAAA,EAAM,MAAA,EAAQ,MAAM,MAAM,CAAA,CAAE,IAAI,KAAK,CAAA;AACjD;AAEA,SAAS,qBAAA,CAAsB,MAAA,EAAuB,QAAA,EAA0B,SAAA,EAAoC;AAChH,EAAA,MAAM,QAAA,GAAW,iCAAA,CAAkC,MAAA,EAAQ,QAAQ,CAAA;AACnE,EAAA,MAAM,OAAA,GAA+B,CAAC,EAAE,OAAA,EAAS,CAAA,EAAG,UAAU,EAAE,MAAA,EAAQ,SAAA,EAAU,EAAG,CAAA;AACrF,EAAA,IAAI,WAAA,GAAc,CAAA;AAClB,EAAA,IAAI,SAAS,UAAA,EAAY;AACrB,IAAA,eAAA,CAAgB,MAAA,EAAQ,QAAA,EAAU,QAAA,CAAS,UAAU,CAAA;AACrD,IAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,OAAA,EAAS,WAAA,EAAA,EAAe,QAAA,EAAU,EAAE,MAAA,EAAS,QAAA,CAAuC,gBAAA,EAAkB,EAAG,CAAA;AAAA,EAC5H;AACA,EAAA,KAAA,MAAW,OAAA,IAAW,SAAS,YAAA,EAAc;AACzC,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,aAAA,CAAc,GAAA,CAAI,QAAQ,IAAI,CAAA;AACpD,IAAA,MAAM,MAAM,IAAA,EAAM,OAAA;AAClB,IAAA,IAAI,CAAC,GAAA,EAAK;AACN,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,OAAA,CAAQ,IAAI,CAAA,6DAAA,CAA+D,CAAA;AAAA,IAC3H;AACA,IAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,OAAA,EAAS,WAAA,EAAA,EAAe,UAAU,GAAA,CAAI,IAAA,EAAK,EAAG,EAAE,OAAA,EAAS,WAAA,EAAA,EAAe,QAAA,EAAU,GAAA,CAAI,SAAS,CAAA;AAAA,EAClH;AACA,EAAA,KAAA,MAAW,OAAA,IAAW,SAAS,kBAAA,EAAoB;AAC/C,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,mBAAA,CAAoB,GAAA,CAAI,QAAQ,IAAI,CAAA;AAC1D,IAAA,MAAM,SAAS,IAAA,EAAM,OAAA;AACrB,IAAA,IAAI,CAAC,MAAA,EAAQ;AACT,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gCAAA,EAAmC,OAAA,CAAQ,IAAI,CAAA,mEAAA,CAAqE,CAAA;AAAA,IACxI;AACA,IAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,OAAA,EAAS,WAAA,EAAA,EAAe,UAAU,EAAE,MAAA,IAAU,CAAA;AAAA,EACjE;AACA,EAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,eAAA,CAAgB,EAAE,KAAA,EAAO,sBAAsB,MAAA,EAAQ,QAAA,CAAS,SAAA,EAAW,OAAA,EAAS,CAAA;AAC9G;AAEA,SAAS,sBAAsB,QAAA,EAAuC;AAClE,EAAA,MAAM,WAAwB,EAAC;AAC/B,EAAA,KAAA,MAAW,IAAA,IAAQ,QAAA,CAAS,aAAA,CAAc,MAAA,EAAO,EAAG;AAChD,IAAA,IAAI,KAAK,OAAA,EAAS;AACd,MAAA,QAAA,CAAS,IAAA,CAAK,KAAK,OAAO,CAAA;AAAA,IAC9B;AAAA,EACJ;AACA,EAAA,OAAO,QAAA;AACX;AAEA,SAAS,4BAA4B,QAAA,EAAuC;AACxE,EAAA,MAAM,UAAuB,EAAC;AAC9B,EAAA,KAAA,MAAW,IAAA,IAAQ,QAAA,CAAS,mBAAA,CAAoB,MAAA,EAAO,EAAG;AACtD,IAAA,IAAI,KAAK,OAAA,EAAS;AACd,MAAA,OAAA,CAAQ,IAAA,CAAK,KAAK,OAAO,CAAA;AAAA,IAC7B;AAAA,EACJ;AACA,EAAA,OAAO,OAAA;AACX;AAEA,SAAS,2BAAA,CAA4B,KAAA,EAAqB,IAAA,EAAY,MAAA,EAA4B;AAC9F,EAAA,MAAM,OAAO,KAAA,CAAM,gBAAA,CAAiB,GAAA,CAAI,IAAI,KAAK,EAAC;AAClD,EAAA,IAAA,CAAK,KAAK,MAAM;AACZ,IAAA,MAAA,CAAO,SAAA,GAAY,IAAA;AACnB,IAAA,IAAI,OAAO,MAAA,EAAQ;AACf,MAAA,MAAM,EAAA,GAAK,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA;AACvC,MAAA,IAAI,MAAM,CAAA,EAAG;AACT,QAAA,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,EAAA,EAAI,CAAC,CAAA;AAAA,MAC9B;AACA,MAAA,MAAA,CAAO,MAAA,GAAS,MAAA;AAAA,IACpB;AACA,IAAA,MAAA,CAAO,UAAU,OAAA,EAAQ;AACzB,IAAA,KAAA,MAAW,GAAA,IAAO,OAAO,cAAA,EAAgB;AACrC,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACtB;AACA,IAAA,MAAA,CAAO,iBAAiB,EAAC;AACzB,IAAA,MAAA,CAAO,uBAAuB,EAAC;AAAA,EACnC,CAAC,CAAA;AACD,EAAA,KAAA,CAAM,gBAAA,CAAiB,GAAA,CAAI,IAAA,EAAM,IAAI,CAAA;AACzC;AAEA,SAAS,oBAAoB,IAAA,EAAoB,IAAA,EAAe,UAA0B,IAAA,EAAY,MAAA,EAAuB,aAAqB,YAAA,EAA4B;AAC1K,EAAA,IAAA,CAAK,KAAK,CAAC,CAAA;AACX,EAAA,MAAM,QAAQ,IAAA,CAAK,WAAA;AACnB,EAAA,MAAM,SAAS,MAAA,GAAS,uBAAA,CAAwB,MAAA,EAAQ,WAAA,EAAa,YAAY,CAAA,GAAI,CAAA;AACrF,EAAA,MAAM,IAAA,GAAO,MAAA,GAAU,aAAA,CAAc,MAAM,CAAA,GAAgC,IAAA;AAC3E,EAAA,MAAM,UAAA,GAAa,MAAA,GAAU,mBAAA,CAAoB,MAAA,EAAQ,MAAM,CAAA,GAAgC,IAAA;AAC/F,EAAA,MAAM,cAAA,GAAiB,MAAA,GAAU,uBAAA,CAAwB,MAAA,EAAQ,MAAM,CAAA,GAAgC,IAAA;AACvG,EAAA,KAAA,MAAW,OAAA,IAAW,SAAS,YAAA,EAAc;AACzC,IAAA,IAAI,CAAC,sBAAA,CAAuB,OAAA,CAAQ,IAAI,CAAA,EAAG;AACvC,MAAA;AAAA,IACJ;AACA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,QAAQ,IAAI,CAAA;AAC7C,IAAA,IAAI,WAAW,MAAA,EAAW;AACtB,MAAA;AAAA,IACJ;AACA,IAAA,MAAM,IAAI,MAAA,GAAS,CAAA;AACnB,IAAA,QAAQ,QAAQ,IAAA;AAAM,MAClB,KAAK,OAAA;AACD,QAAA,IAAA,CAAK,GAAA,CAAI,OAAO,CAAC,CAAA;AACjB,QAAA;AAAA,MACJ,KAAK,MAAA;AACD,QAAA,IAAI,IAAA,EAAM;AACN,UAAA,IAAA,CAAK,GAAA,CAAI,MAAM,CAAC,CAAA;AAAA,QACpB;AACA,QAAA;AAAA,MACJ,KAAK,YAAA;AACD,QAAA,IAAI,UAAA,EAAY;AACZ,UAAA,IAAA,CAAK,GAAA,CAAI,YAAY,CAAC,CAAA;AAAA,QAC1B;AACA,QAAA;AAAA,MACJ,KAAK,gBAAA;AACD,QAAA,IAAI,cAAA,EAAgB;AAChB,UAAA,IAAA,CAAK,GAAA,CAAI,gBAAgB,CAAC,CAAA;AAAA,QAC9B;AACA,QAAA;AAAA,MACJ,KAAK,WAAA;AACD,QAAA,IAAI,IAAA,EAAM;AACN,UAAA,gBAAA,CAAiB,IAAA,EAAM,CAAA,EAAG,IAAA,EAAM,CAAA,EAAG,OAAO,CAAC,CAAA;AAAA,QAC/C;AACA,QAAA;AAAA,MACJ,KAAK,qBAAA;AACD,QAAA,IAAI,cAAA,EAAgB;AAChB,UAAA,gBAAA,CAAiB,IAAA,EAAM,CAAA,EAAG,cAAA,EAAgB,CAAA,EAAG,OAAO,CAAC,CAAA;AAAA,QACzD;AACA,QAAA;AAAA,MACJ,KAAK,gBAAA;AACD,QAAA,IAAI,MAAA,EAAQ;AACR,UAAA,MAAM,KAAK,MAAA,CAAO,WAAA;AAClB,UAAA,IAAA,CAAK,CAAC,CAAA,GAAI,EAAA,CAAG,EAAE,CAAA;AACf,UAAA,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,GAAI,EAAA,CAAG,EAAE,CAAA;AACnB,UAAA,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,GAAI,EAAA,CAAG,EAAE,CAAA;AAAA,QACvB;AACA,QAAA;AAAA,MACJ,KAAK,YAAA;AACD,QAAA,IAAA,CAAK,CAAC,CAAA,GAAI,WAAA;AACV,QAAA,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,GAAI,YAAA;AACd,QAAA;AAAA,MACJ,KAAK,aAAA;AACD,QAAA,IAAA,CAAK,CAAC,IAAI,QAAA,CAAS,cAAA,CAAe,IAAI,aAAa,CAAA,EAAG,KAAA,CAAM,CAAC,CAAA,IAAK,GAAA;AAClE,QAAA;AAAA;AACR,EACJ;AACJ;AAEA,IAAI,aAAA,GAAgE,IAAA;AAEpE,SAAS,iBAAA,CAAkB,MAAA,EAAuB,GAAA,EAAc,IAAA,EAAyB;AACrF,EAAA,IAAI,CAAC,aAAA,EAAe;AAChB,IAAA,aAAA,uBAAoB,OAAA,EAAQ;AAAA,EAChC;AACA,EAAA,IAAI,KAAA,GAAQ,aAAA,CAAc,GAAA,CAAI,GAAwB,CAAA;AACtD,EAAA,IAAI,CAAC,KAAA,EAAO;AACR,IAAA,KAAA,uBAAY,GAAA,EAAI;AAChB,IAAA,aAAA,CAAc,GAAA,CAAI,KAA0B,KAAK,CAAA;AAAA,EACrD;AACA,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA;AAC/B,EAAA,IAAI,QAAA,EAAU;AACV,IAAA,OAAO,QAAA;AAAA,EACX;AACA,EAAA,MAAM,WAAA,GAAc,GAAA,CAAI,cAAA,CAAe,IAAA,GAAO,EAAA;AAC9C,EAAA,MAAM,MAAA,GAAS,SAAS,IAAA,IAAQ,IAAA,KAAS,QAAQ,CAAA,GAAI,IAAA,KAAS,WAAW,EAAA,GAAK,EAAA;AAC9E,EAAA,MAAM,SAAS,MAAA,CAAO,OAAA,CAAQ,YAAA,CAAa,EAAE,OAAO,CAAA,YAAA,EAAe,IAAI,CAAA,CAAA,EAAI,IAAA,EAAM,cAAc,MAAA,EAAQ,KAAA,EAAO,GAAG,MAAA,GAAS,EAAA,CAAG,UAAU,CAAA;AACvI,EAAA,KAAA,CAAM,GAAA,CAAI,MAAM,MAAM,CAAA;AACtB,EAAA,OAAO,MAAA;AACX;AAIA,SAAS,aAAA,CAAc,MAAY,KAAA,EAAgG;AAC/H,EAAA,OAAO,KAAK,GAAA,GAAM,KAAK,KAAK,IAAA,CAAK,QAAA,GAAW,KAAK,CAAA,IAAK,IAAA;AAC1D;AAEA,SAAS,aAAA,CAAc,MAAA,EAAuB,IAAA,EAAY,IAAA,EAAsC;AAC5F,EAAA,MAAM,MAAM,IAAA,CAAK,IAAA;AACjB,EAAA,QAAQ,IAAA;AAAM,IACV,KAAK,UAAA;AACD,MAAA,OAAO,GAAA,CAAI,cAAA;AAAA,IACf,KAAK,QAAA;AACD,MAAA,OAAO,GAAA,CAAI,YAAA,IAAgB,iBAAA,CAAkB,MAAA,EAAQ,KAAK,QAAQ,CAAA;AAAA,IACtE,KAAK,IAAA;AACD,MAAA,OAAO,GAAA,CAAI,QAAA,IAAY,iBAAA,CAAkB,MAAA,EAAQ,KAAK,IAAI,CAAA;AAAA,IAC9D,KAAK,KAAA;AACD,MAAA,OAAO,GAAA,CAAI,SAAA,IAAa,iBAAA,CAAkB,MAAA,EAAQ,KAAK,KAAK,CAAA;AAAA,IAChE,KAAK,SAAA;AACD,MAAA,OAAO,GAAA,CAAI,aAAA,IAAiB,iBAAA,CAAkB,MAAA,EAAQ,KAAK,SAAS,CAAA;AAAA,IACxE,KAAK,OAAA;AACD,MAAA,OAAO,GAAA,CAAI,WAAA,IAAe,iBAAA,CAAkB,MAAA,EAAQ,KAAK,OAAO,CAAA;AAAA,IACpE,KAAK,QAAA;AACD,MAAA,OAAO,cAAc,IAAA,EAAM,cAAc,KAAK,iBAAA,CAAkB,MAAA,EAAQ,KAAK,QAAQ,CAAA;AAAA,IACzF,KAAK,SAAA;AACD,MAAA,OAAO,cAAc,IAAA,EAAM,eAAe,KAAK,iBAAA,CAAkB,MAAA,EAAQ,KAAK,SAAS,CAAA;AAAA,IAC3F,KAAK,SAAA;AACD,MAAA,OAAO,cAAc,IAAA,EAAM,eAAe,KAAK,iBAAA,CAAkB,MAAA,EAAQ,KAAK,SAAS,CAAA;AAAA,IAC3F,KAAK,UAAA;AACD,MAAA,OAAO,cAAc,IAAA,EAAM,gBAAgB,KAAK,iBAAA,CAAkB,MAAA,EAAQ,KAAK,UAAU,CAAA;AAAA;AAErG;;;;"}
@@ -74,7 +74,7 @@ function createShaderInstancedRenderable(scene, material, packet, isOverride, h,
74
74
  const gpu = mesh._gpu;
75
75
  let slot = 0;
76
76
  for (let i = 0; i < material.attributes.length; i++) {
77
- pass.setVertexBuffer(slot++, h.getAttrBuffer(engine, gpu, material.attributes[i]));
77
+ pass.setVertexBuffer(slot++, h.getAttrBuffer(engine, mesh, material.attributes[i]));
78
78
  }
79
79
  slot = syncThinInstanceBuffers(engine, ti, pass, slot, hasColor, cullBinding?.cullDrawBufs);
80
80
  pass.setIndexBuffer(gpu.indexBuffer, gpu.indexFormat);
@@ -1 +1 @@
1
- {"version":3,"file":"shader-thin-instance.js","sources":["../../../../src/material/shader/shader-thin-instance.ts"],"sourcesContent":["/** ShaderMaterial thin-instance support — dynamically imported ONLY when a\n * ShaderMaterial scene actually uses thin instances, so non-instanced scenes pull\n * in zero extra bytes and the shared `shader-renderable.ts` / `shader-pipeline.ts`\n * chunks stay identical to their non-instanced form.\n *\n * The renderable helpers this module needs (packet create/update, attribute\n * buffers, pipeline builders, the plain-mesh builder) are passed in as positional\n * arguments by `buildShaderGroup`, NOT imported. Importing them would force the\n * shared chunk to export them, which de-mangles their names and grows every\n * ShaderMaterial scene's bundle. As parameters they keep their mangled identity in\n * the shared chunk and are only named here, in this culling/instancing-only chunk.\n *\n * The instance buffer layout MUST match the buffers produced by\n * `thin-instance-gpu.ts` (matrix buffer arrayStride 64, 4x float32x4 at offsets\n * 0/16/32/48; color buffer arrayStride 16, float32x4 at offset 0). */\n\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport type { SceneContext } from \"../../scene/scene.js\";\nimport type { Material } from \"../material.js\";\nimport type { Mesh, MeshGPU } from \"../../mesh/mesh.js\";\nimport type { RenderTargetSignature } from \"../../engine/render-target.js\";\nimport type { UboSpec } from \"../../shader/fragment-types.js\";\nimport type { DrawUpdateContext, MeshGroupBuildResult, Renderable } from \"../../render/renderable.js\";\nimport type { ShaderAttributeName, ShaderMaterial } from \"./shader-material.js\";\nimport type { ShaderPipelineBindings } from \"./shader-pipeline.js\";\nimport type { ShaderPacket, ShaderRenderPass } from \"./shader-renderable.js\";\nimport { syncThinInstanceBuffers } from \"../../mesh/thin-instance-gpu.js\";\n\ntype CullModule = typeof import(\"../../mesh/thin-instance-cull-binding.js\");\n\n/** The shader-renderable helpers handed in positionally by `buildShaderGroup`. */\ninterface ShaderHelpers {\n buildPlain: (scene: SceneContext, meshes: Mesh[]) => MeshGroupBuildResult;\n createPacket: (scene: SceneContext, material: ShaderMaterial, systemSpec: UboSpec, mesh: Mesh) => ShaderPacket;\n updatePacket: (scene: SceneContext, material: ShaderMaterial, packet: ShaderPacket, context: DrawUpdateContext) => void;\n updateCustomUbo: (engine: EngineContext, material: ShaderMaterial) => void;\n getAttrBuffer: (engine: EngineContext, gpu: MeshGPU, name: ShaderAttributeName) => GPUBuffer;\n getOrCreateShaderPipeline: (\n engine: EngineContext,\n sig: RenderTargetSignature,\n material: ShaderMaterial,\n bindings: ShaderPipelineBindings,\n variantKey?: string,\n vertexBuffers?: readonly GPUVertexBufferLayout[],\n instanceAttrs?: string\n ) => GPURenderPipeline;\n getOrCreateShaderPipelineBindings: (engine: EngineContext, material: ShaderMaterial) => ShaderPipelineBindings;\n}\n\n/** Instance vertex buffer layouts. `baseLocation` is the first free shader\n * location after the material's own attributes. */\nfunction instanceVertexLayouts(baseLocation: number, hasColor: boolean): GPUVertexBufferLayout[] {\n const layouts: GPUVertexBufferLayout[] = [\n {\n arrayStride: 64,\n stepMode: \"instance\",\n attributes: [\n { shaderLocation: baseLocation, offset: 0, format: \"float32x4\" },\n { shaderLocation: baseLocation + 1, offset: 16, format: \"float32x4\" },\n { shaderLocation: baseLocation + 2, offset: 32, format: \"float32x4\" },\n { shaderLocation: baseLocation + 3, offset: 48, format: \"float32x4\" },\n ],\n },\n ];\n if (hasColor) {\n layouts.push({\n arrayStride: 16,\n stepMode: \"instance\",\n attributes: [{ shaderLocation: baseLocation + 4, offset: 0, format: \"float32x4\" }],\n });\n }\n return layouts;\n}\n\n/** WGSL lines appended inside `VertexInput` for instanced variants. */\nfunction instancePreludeAttributes(baseLocation: number, hasColor: boolean): string {\n let wgsl = `@location(${baseLocation}) world0: vec4<f32>,\n@location(${baseLocation + 1}) world1: vec4<f32>,\n@location(${baseLocation + 2}) world2: vec4<f32>,\n@location(${baseLocation + 3}) world3: vec4<f32>,\n`;\n if (hasColor) {\n wgsl += `@location(${baseLocation + 4}) instanceColor: vec4<f32>,\n`;\n }\n return wgsl;\n}\n\n/** Build ONE thin-instance renderable for a ShaderMaterial mesh (opaque or\n * transparent). Marked `_direct` so instance buffers are re-bound fresh each\n * frame; this also prepares the renderable for opaque-only GPU culling. */\nfunction createShaderInstancedRenderable(\n scene: SceneContext,\n material: ShaderMaterial,\n packet: ShaderPacket,\n isOverride: boolean,\n h: ShaderHelpers,\n cull?: CullModule\n): Renderable {\n const isTransparent = material.needAlphaBlending;\n const mesh = packet.mesh;\n const ti = mesh.thinInstances!;\n const hasColor = !!ti.colors;\n const baseLocation = material.attributes.length;\n const instanceLayouts = instanceVertexLayouts(baseLocation, hasColor);\n const instanceAttrs = instancePreludeAttributes(baseLocation, hasColor);\n const variantKey = `|ti1c${hasColor ? 1 : 0}`;\n const wm = mesh.worldMatrix as unknown as ArrayLike<number>;\n const sortCenter: [number, number, number] = [wm[12]!, wm[13]!, wm[14]!];\n const update = (context: DrawUpdateContext): void => {\n if (packet._disposed) {\n return;\n }\n if (!isOverride && mesh.material !== material) {\n return;\n }\n h.updateCustomUbo(scene.surface.engine, material);\n h.updatePacket(scene, material, packet, context);\n if (isTransparent) {\n const m = mesh.worldMatrix as unknown as ArrayLike<number>;\n sortCenter[0] = m[12]!;\n sortCenter[1] = m[13]!;\n sortCenter[2] = m[14]!;\n }\n };\n const draw = (pass: ShaderRenderPass, engine: EngineContext, cullBinding?: import(\"../../mesh/thin-instance-cull-binding.js\").TiCullBinding): number => {\n if (packet._disposed) {\n return 0;\n }\n if (!isOverride && mesh.material !== material) {\n return 0;\n }\n if (ti.count <= 0) {\n return 0;\n }\n const gpu = mesh._gpu;\n let slot = 0;\n for (let i = 0; i < material.attributes.length; i++) {\n pass.setVertexBuffer(slot++, h.getAttrBuffer(engine, gpu, material.attributes[i]!));\n }\n slot = syncThinInstanceBuffers(engine, ti, pass, slot, hasColor, cullBinding?.cullDrawBufs);\n pass.setIndexBuffer(gpu.indexBuffer, gpu.indexFormat);\n pass.setBindGroup(1, packet._bindGroup);\n if (cullBinding) {\n cullBinding.draw(pass, gpu.indexCount, ti.count);\n } else {\n pass.drawIndexed(gpu.indexCount, ti.count);\n }\n return 1;\n };\n const r: Renderable = {\n order: mesh.renderOrder ?? (isTransparent ? 200 : 100),\n isTransparent,\n mesh,\n _worldCenter: sortCenter,\n bind(eng, sig) {\n const bindings = h.getOrCreateShaderPipelineBindings(eng, material);\n const vertexBuffers = [...bindings.vertexBuffers, ...instanceLayouts];\n const pipeline = h.getOrCreateShaderPipeline(eng, sig, material, bindings, variantKey, vertexBuffers, instanceAttrs);\n const cb = cull?.tryBind(r, scene, mesh, eng, hasColor, isTransparent, update, sig);\n return {\n renderable: r,\n pipeline,\n update: cb ? cb.update : update,\n draw: (pass) => draw(pass, eng, cb),\n };\n },\n };\n (r as { _direct?: boolean })._direct = true;\n return r;\n}\n\n/** Build one instanced renderable for `mesh` (used by the combined `rebuildSingle`). */\nfunction buildInstancedSingle(scene: SceneContext, mesh: Mesh, material: ShaderMaterial, isOverride: boolean, h: ShaderHelpers, cull?: CullModule): Renderable {\n const bindings = h.getOrCreateShaderPipelineBindings(scene.surface.engine, material);\n const packet = h.createPacket(scene, material, bindings.systemSpec, mesh);\n return createShaderInstancedRenderable(scene, material, packet, isOverride, h, cull);\n}\n\n/** Group entry point used whenever a ShaderMaterial scene has at least one\n * thin-instanced mesh. Plain meshes flow through the passed-in `buildPlain`\n * (`buildShaderMaterialRenderables`); instanced meshes get a dedicated renderable. */\nexport function buildShaderRenderablesWithInstancing(\n scene: SceneContext,\n meshes: Mesh[],\n buildPlain: ShaderHelpers[\"buildPlain\"],\n createPacket: ShaderHelpers[\"createPacket\"],\n updatePacket: ShaderHelpers[\"updatePacket\"],\n updateCustomUbo: ShaderHelpers[\"updateCustomUbo\"],\n getAttrBuffer: ShaderHelpers[\"getAttrBuffer\"],\n getOrCreateShaderPipeline: ShaderHelpers[\"getOrCreateShaderPipeline\"],\n getOrCreateShaderPipelineBindings: ShaderHelpers[\"getOrCreateShaderPipelineBindings\"],\n cull?: CullModule\n): MeshGroupBuildResult {\n const h: ShaderHelpers = { buildPlain, createPacket, updatePacket, updateCustomUbo, getAttrBuffer, getOrCreateShaderPipeline, getOrCreateShaderPipelineBindings };\n const instanced: Mesh[] = [];\n const plain: Mesh[] = [];\n for (const mesh of meshes) {\n if (mesh.thinInstances) {\n instanced.push(mesh);\n } else {\n plain.push(mesh);\n }\n }\n\n const renderables: Renderable[] = [];\n let plainRebuild: MeshGroupBuildResult[\"rebuildSingle\"] | undefined;\n if (plain.length > 0) {\n const plainResult = buildPlain(scene, plain);\n renderables.push(...plainResult.renderables);\n plainRebuild = plainResult.rebuildSingle;\n }\n for (const mesh of instanced) {\n renderables.push(buildInstancedSingle(scene, mesh, mesh.material as ShaderMaterial, false, h, cull));\n }\n\n const rebuildSingle = (s: SceneContext, mesh: Mesh, materialOverride?: Material): Renderable => {\n const material = (materialOverride ?? mesh.material) as ShaderMaterial;\n if (mesh.thinInstances) {\n return buildInstancedSingle(s, mesh, material, materialOverride != null, h, cull);\n }\n if (plainRebuild) {\n return plainRebuild(s, mesh, materialOverride);\n }\n return buildPlain(s, [mesh]).rebuildSingle(s, mesh, materialOverride);\n };\n\n return { renderables, rebuildSingle };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shader-thin-instance.js","sources":["../../../../src/material/shader/shader-thin-instance.ts"],"sourcesContent":["/** ShaderMaterial thin-instance support — dynamically imported ONLY when a\n * ShaderMaterial scene actually uses thin instances, so non-instanced scenes pull\n * in zero extra bytes and the shared `shader-renderable.ts` / `shader-pipeline.ts`\n * chunks stay identical to their non-instanced form.\n *\n * The renderable helpers this module needs (packet create/update, attribute\n * buffers, pipeline builders, the plain-mesh builder) are passed in as positional\n * arguments by `buildShaderGroup`, NOT imported. Importing them would force the\n * shared chunk to export them, which de-mangles their names and grows every\n * ShaderMaterial scene's bundle. As parameters they keep their mangled identity in\n * the shared chunk and are only named here, in this culling/instancing-only chunk.\n *\n * The instance buffer layout MUST match the buffers produced by\n * `thin-instance-gpu.ts` (matrix buffer arrayStride 64, 4x float32x4 at offsets\n * 0/16/32/48; color buffer arrayStride 16, float32x4 at offset 0). */\n\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport type { SceneContext } from \"../../scene/scene.js\";\nimport type { Material } from \"../material.js\";\nimport type { Mesh } from \"../../mesh/mesh.js\";\nimport type { RenderTargetSignature } from \"../../engine/render-target.js\";\nimport type { UboSpec } from \"../../shader/fragment-types.js\";\nimport type { DrawUpdateContext, MeshGroupBuildResult, Renderable } from \"../../render/renderable.js\";\nimport type { ShaderAttributeName, ShaderMaterial } from \"./shader-material.js\";\nimport type { ShaderPipelineBindings } from \"./shader-pipeline.js\";\nimport type { ShaderPacket, ShaderRenderPass } from \"./shader-renderable.js\";\nimport { syncThinInstanceBuffers } from \"../../mesh/thin-instance-gpu.js\";\n\ntype CullModule = typeof import(\"../../mesh/thin-instance-cull-binding.js\");\n\n/** The shader-renderable helpers handed in positionally by `buildShaderGroup`. */\ninterface ShaderHelpers {\n buildPlain: (scene: SceneContext, meshes: Mesh[]) => MeshGroupBuildResult;\n createPacket: (scene: SceneContext, material: ShaderMaterial, systemSpec: UboSpec, mesh: Mesh) => ShaderPacket;\n updatePacket: (scene: SceneContext, material: ShaderMaterial, packet: ShaderPacket, context: DrawUpdateContext) => void;\n updateCustomUbo: (engine: EngineContext, material: ShaderMaterial) => void;\n getAttrBuffer: (engine: EngineContext, mesh: Mesh, name: ShaderAttributeName) => GPUBuffer;\n getOrCreateShaderPipeline: (\n engine: EngineContext,\n sig: RenderTargetSignature,\n material: ShaderMaterial,\n bindings: ShaderPipelineBindings,\n variantKey?: string,\n vertexBuffers?: readonly GPUVertexBufferLayout[],\n instanceAttrs?: string\n ) => GPURenderPipeline;\n getOrCreateShaderPipelineBindings: (engine: EngineContext, material: ShaderMaterial) => ShaderPipelineBindings;\n}\n\n/** Instance vertex buffer layouts. `baseLocation` is the first free shader\n * location after the material's own attributes. */\nfunction instanceVertexLayouts(baseLocation: number, hasColor: boolean): GPUVertexBufferLayout[] {\n const layouts: GPUVertexBufferLayout[] = [\n {\n arrayStride: 64,\n stepMode: \"instance\",\n attributes: [\n { shaderLocation: baseLocation, offset: 0, format: \"float32x4\" },\n { shaderLocation: baseLocation + 1, offset: 16, format: \"float32x4\" },\n { shaderLocation: baseLocation + 2, offset: 32, format: \"float32x4\" },\n { shaderLocation: baseLocation + 3, offset: 48, format: \"float32x4\" },\n ],\n },\n ];\n if (hasColor) {\n layouts.push({\n arrayStride: 16,\n stepMode: \"instance\",\n attributes: [{ shaderLocation: baseLocation + 4, offset: 0, format: \"float32x4\" }],\n });\n }\n return layouts;\n}\n\n/** WGSL lines appended inside `VertexInput` for instanced variants. */\nfunction instancePreludeAttributes(baseLocation: number, hasColor: boolean): string {\n let wgsl = `@location(${baseLocation}) world0: vec4<f32>,\n@location(${baseLocation + 1}) world1: vec4<f32>,\n@location(${baseLocation + 2}) world2: vec4<f32>,\n@location(${baseLocation + 3}) world3: vec4<f32>,\n`;\n if (hasColor) {\n wgsl += `@location(${baseLocation + 4}) instanceColor: vec4<f32>,\n`;\n }\n return wgsl;\n}\n\n/** Build ONE thin-instance renderable for a ShaderMaterial mesh (opaque or\n * transparent). Marked `_direct` so instance buffers are re-bound fresh each\n * frame; this also prepares the renderable for opaque-only GPU culling. */\nfunction createShaderInstancedRenderable(\n scene: SceneContext,\n material: ShaderMaterial,\n packet: ShaderPacket,\n isOverride: boolean,\n h: ShaderHelpers,\n cull?: CullModule\n): Renderable {\n const isTransparent = material.needAlphaBlending;\n const mesh = packet.mesh;\n const ti = mesh.thinInstances!;\n const hasColor = !!ti.colors;\n const baseLocation = material.attributes.length;\n const instanceLayouts = instanceVertexLayouts(baseLocation, hasColor);\n const instanceAttrs = instancePreludeAttributes(baseLocation, hasColor);\n const variantKey = `|ti1c${hasColor ? 1 : 0}`;\n const wm = mesh.worldMatrix as unknown as ArrayLike<number>;\n const sortCenter: [number, number, number] = [wm[12]!, wm[13]!, wm[14]!];\n const update = (context: DrawUpdateContext): void => {\n if (packet._disposed) {\n return;\n }\n if (!isOverride && mesh.material !== material) {\n return;\n }\n h.updateCustomUbo(scene.surface.engine, material);\n h.updatePacket(scene, material, packet, context);\n if (isTransparent) {\n const m = mesh.worldMatrix as unknown as ArrayLike<number>;\n sortCenter[0] = m[12]!;\n sortCenter[1] = m[13]!;\n sortCenter[2] = m[14]!;\n }\n };\n const draw = (pass: ShaderRenderPass, engine: EngineContext, cullBinding?: import(\"../../mesh/thin-instance-cull-binding.js\").TiCullBinding): number => {\n if (packet._disposed) {\n return 0;\n }\n if (!isOverride && mesh.material !== material) {\n return 0;\n }\n if (ti.count <= 0) {\n return 0;\n }\n const gpu = mesh._gpu;\n let slot = 0;\n for (let i = 0; i < material.attributes.length; i++) {\n pass.setVertexBuffer(slot++, h.getAttrBuffer(engine, mesh, material.attributes[i]!));\n }\n slot = syncThinInstanceBuffers(engine, ti, pass, slot, hasColor, cullBinding?.cullDrawBufs);\n pass.setIndexBuffer(gpu.indexBuffer, gpu.indexFormat);\n pass.setBindGroup(1, packet._bindGroup);\n if (cullBinding) {\n cullBinding.draw(pass, gpu.indexCount, ti.count);\n } else {\n pass.drawIndexed(gpu.indexCount, ti.count);\n }\n return 1;\n };\n const r: Renderable = {\n order: mesh.renderOrder ?? (isTransparent ? 200 : 100),\n isTransparent,\n mesh,\n _worldCenter: sortCenter,\n bind(eng, sig) {\n const bindings = h.getOrCreateShaderPipelineBindings(eng, material);\n const vertexBuffers = [...bindings.vertexBuffers, ...instanceLayouts];\n const pipeline = h.getOrCreateShaderPipeline(eng, sig, material, bindings, variantKey, vertexBuffers, instanceAttrs);\n const cb = cull?.tryBind(r, scene, mesh, eng, hasColor, isTransparent, update, sig);\n return {\n renderable: r,\n pipeline,\n update: cb ? cb.update : update,\n draw: (pass) => draw(pass, eng, cb),\n };\n },\n };\n (r as { _direct?: boolean })._direct = true;\n return r;\n}\n\n/** Build one instanced renderable for `mesh` (used by the combined `rebuildSingle`). */\nfunction buildInstancedSingle(scene: SceneContext, mesh: Mesh, material: ShaderMaterial, isOverride: boolean, h: ShaderHelpers, cull?: CullModule): Renderable {\n const bindings = h.getOrCreateShaderPipelineBindings(scene.surface.engine, material);\n const packet = h.createPacket(scene, material, bindings.systemSpec, mesh);\n return createShaderInstancedRenderable(scene, material, packet, isOverride, h, cull);\n}\n\n/** Group entry point used whenever a ShaderMaterial scene has at least one\n * thin-instanced mesh. Plain meshes flow through the passed-in `buildPlain`\n * (`buildShaderMaterialRenderables`); instanced meshes get a dedicated renderable. */\nexport function buildShaderRenderablesWithInstancing(\n scene: SceneContext,\n meshes: Mesh[],\n buildPlain: ShaderHelpers[\"buildPlain\"],\n createPacket: ShaderHelpers[\"createPacket\"],\n updatePacket: ShaderHelpers[\"updatePacket\"],\n updateCustomUbo: ShaderHelpers[\"updateCustomUbo\"],\n getAttrBuffer: ShaderHelpers[\"getAttrBuffer\"],\n getOrCreateShaderPipeline: ShaderHelpers[\"getOrCreateShaderPipeline\"],\n getOrCreateShaderPipelineBindings: ShaderHelpers[\"getOrCreateShaderPipelineBindings\"],\n cull?: CullModule\n): MeshGroupBuildResult {\n const h: ShaderHelpers = { buildPlain, createPacket, updatePacket, updateCustomUbo, getAttrBuffer, getOrCreateShaderPipeline, getOrCreateShaderPipelineBindings };\n const instanced: Mesh[] = [];\n const plain: Mesh[] = [];\n for (const mesh of meshes) {\n if (mesh.thinInstances) {\n instanced.push(mesh);\n } else {\n plain.push(mesh);\n }\n }\n\n const renderables: Renderable[] = [];\n let plainRebuild: MeshGroupBuildResult[\"rebuildSingle\"] | undefined;\n if (plain.length > 0) {\n const plainResult = buildPlain(scene, plain);\n renderables.push(...plainResult.renderables);\n plainRebuild = plainResult.rebuildSingle;\n }\n for (const mesh of instanced) {\n renderables.push(buildInstancedSingle(scene, mesh, mesh.material as ShaderMaterial, false, h, cull));\n }\n\n const rebuildSingle = (s: SceneContext, mesh: Mesh, materialOverride?: Material): Renderable => {\n const material = (materialOverride ?? mesh.material) as ShaderMaterial;\n if (mesh.thinInstances) {\n return buildInstancedSingle(s, mesh, material, materialOverride != null, h, cull);\n }\n if (plainRebuild) {\n return plainRebuild(s, mesh, materialOverride);\n }\n return buildPlain(s, [mesh]).rebuildSingle(s, mesh, materialOverride);\n };\n\n return { renderables, rebuildSingle };\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,193 @@
1
+ import { F32 } from '../engine/typed-arrays.js';
2
+ import { createRenderTarget, disposeRenderTarget, buildRenderTarget } from '../engine/render-target.js';
3
+ import { createPostProcessTask } from '../frame-graph/post-process-task.js';
4
+
5
+ const TAA_HISTORY_TEXTURE_WGSL = `@group(0) @binding(2) var taaHistory:texture_2d<f32>;`;
6
+ const TAA_UNIFORM_WGSL = `struct TaaParams{factor:f32,p0:f32,p1:f32,p2:f32}
7
+ @group(0) @binding(3) var<uniform> taaParams:TaaParams;`;
8
+ const TAA_FRAGMENT_WGSL = `fn applyPostProcess(color:vec4f, uv:vec2f)->vec4f{let h=textureSample(taaHistory,sourceSampler,uv);return mix(h,color,taaParams.factor);}`;
9
+ const TAA_COPY_FRAGMENT_WGSL = `fn applyPostProcess(color:vec4f, uv:vec2f)->vec4f{return color;}`;
10
+ function createTaaPostProcessTask(config, engine, scene) {
11
+ const name = config.name ?? "taa";
12
+ const source = config.sourceTexture;
13
+ const target = config.targetTexture ?? null;
14
+ const samples = Math.max(1, Math.floor(config.samples ?? 8));
15
+ const sizeRef = source._descriptor.size;
16
+ const history = createRenderTarget({ lbl: `${name}-history`, format: "rgba16float", samples: 1, size: sizeRef });
17
+ const temp = createRenderTarget({ lbl: `${name}-temp`, format: "rgba16float", samples: 1, size: sizeRef });
18
+ const blend = createPostProcessTask(
19
+ {
20
+ name: `${name}-blend`,
21
+ sourceTexture: source,
22
+ // Nearest sampling reads the exact co-located texel of both the current
23
+ // frame and the history (all three targets share a resolution).
24
+ sourceSamplingMode: "nearest",
25
+ targetTexture: temp,
26
+ _shader: {
27
+ extraTextureWGSL: TAA_HISTORY_TEXTURE_WGSL,
28
+ extraTextures: [history],
29
+ uniformWGSL: TAA_UNIFORM_WGSL,
30
+ uniformBinding: 3,
31
+ uniformByteLength: 16,
32
+ writeUniforms(data) {
33
+ data[0] = task._factor;
34
+ },
35
+ fragmentWGSL: TAA_FRAGMENT_WGSL
36
+ }
37
+ },
38
+ engine,
39
+ scene
40
+ );
41
+ const present = createPostProcessTask(
42
+ {
43
+ name: `${name}-present`,
44
+ sourceTexture: temp,
45
+ sourceSamplingMode: "nearest",
46
+ targetTexture: target ?? engine.scRT,
47
+ _shader: { fragmentWGSL: TAA_COPY_FRAGMENT_WGSL }
48
+ },
49
+ engine,
50
+ scene
51
+ );
52
+ const historyUpdate = createPostProcessTask(
53
+ {
54
+ name: `${name}-history-update`,
55
+ sourceTexture: temp,
56
+ sourceSamplingMode: "nearest",
57
+ targetTexture: history,
58
+ _shader: { fragmentWGSL: TAA_COPY_FRAGMENT_WGSL }
59
+ },
60
+ engine,
61
+ scene
62
+ );
63
+ const task = {
64
+ name,
65
+ engine,
66
+ scene,
67
+ _passes: [],
68
+ sourceTexture: source,
69
+ targetTexture: target,
70
+ outputTexture: target ?? engine.scRT,
71
+ factor: config.factor ?? 0.05,
72
+ samples,
73
+ disableOnCameraMove: config.disableOnCameraMove ?? true,
74
+ _blend: blend,
75
+ _present: present,
76
+ _historyUpdate: historyUpdate,
77
+ _history: history,
78
+ _temp: temp,
79
+ _sourceRenderTask: config.sourceRenderTask,
80
+ _halton: generateHalton(samples),
81
+ _haltonIndex: 0,
82
+ _jitterScratch: new F32(16),
83
+ _firstUpdate: true,
84
+ _lastCamVer: -1,
85
+ _factor: 1,
86
+ record() {
87
+ const { width: w, height: h } = resolveSourceSize(task.sourceTexture);
88
+ ensurePersistentTarget(history, engine, w, h);
89
+ ensurePersistentTarget(temp, engine, w, h);
90
+ blend.record();
91
+ present.record();
92
+ historyUpdate.record();
93
+ task._firstUpdate = true;
94
+ task._haltonIndex = 0;
95
+ task._lastCamVer = -1;
96
+ },
97
+ execute() {
98
+ const cam = task._sourceRenderTask.scene.camera;
99
+ const camVer = cam ? cam.worldMatrixVersion : 0;
100
+ const moved = camVer !== task._lastCamVer;
101
+ task._lastCamVer = camVer;
102
+ const reset = task._firstUpdate || moved && task.disableOnCameraMove;
103
+ task._factor = reset ? 1 : task.factor;
104
+ blend.updateUniforms();
105
+ let draws = blend.execute?.() ?? 0;
106
+ draws += present.execute?.() ?? 0;
107
+ draws += historyUpdate.execute?.() ?? 0;
108
+ task._firstUpdate = false;
109
+ advanceJitter(task);
110
+ return draws;
111
+ },
112
+ updateUniforms() {
113
+ blend.updateUniforms();
114
+ },
115
+ dispose() {
116
+ task._passes.length = 0;
117
+ blend.dispose();
118
+ present.dispose();
119
+ historyUpdate.dispose();
120
+ history._eager = false;
121
+ temp._eager = false;
122
+ disposeRenderTarget(history);
123
+ disposeRenderTarget(temp);
124
+ }
125
+ };
126
+ return task;
127
+ }
128
+ function ensurePersistentTarget(rt, engine, width, height) {
129
+ if (rt._eager && rt._width === width && rt._height === height) {
130
+ return;
131
+ }
132
+ rt._eager = false;
133
+ disposeRenderTarget(rt);
134
+ rt._descriptor.size = { width, height };
135
+ buildRenderTarget(rt, engine);
136
+ rt._eager = true;
137
+ }
138
+ function resolveSourceSize(source) {
139
+ if (source._width > 0 && source._height > 0) {
140
+ return { width: source._width, height: source._height };
141
+ }
142
+ const size = source._descriptor.size;
143
+ if ("canvas" in size) {
144
+ return { width: size.canvas.width, height: size.canvas.height };
145
+ }
146
+ return { width: size.width, height: size.height };
147
+ }
148
+ function generateHalton(samples) {
149
+ const seq = new F32(samples * 2);
150
+ for (let i = 1; i <= samples; i++) {
151
+ seq[(i - 1) * 2] = halton(i, 2) - 0.5;
152
+ seq[(i - 1) * 2 + 1] = halton(i, 3) - 0.5;
153
+ }
154
+ return seq;
155
+ }
156
+ function halton(index, base) {
157
+ let fraction = 1;
158
+ let result = 0;
159
+ while (index > 0) {
160
+ fraction /= base;
161
+ result += fraction * (index % base);
162
+ index = Math.floor(index / base);
163
+ }
164
+ return result;
165
+ }
166
+ function advanceJitter(task) {
167
+ const src = task._sourceRenderTask;
168
+ const clean = src._suData;
169
+ const w = task.sourceTexture._width;
170
+ const h = task.sourceTexture._height;
171
+ if (w <= 0 || h <= 0) {
172
+ return;
173
+ }
174
+ const jx = task._halton[task._haltonIndex] / (w / 2);
175
+ const jy = task._halton[task._haltonIndex + 1] / (h / 2);
176
+ task._haltonIndex += 2;
177
+ if (task._haltonIndex >= task._halton.length) {
178
+ task._haltonIndex = 0;
179
+ }
180
+ const out = task._jitterScratch;
181
+ for (let c = 0; c < 4; c++) {
182
+ const b = c * 4;
183
+ const w3 = clean[b + 3];
184
+ out[b] = clean[b] + jx * w3;
185
+ out[b + 1] = clean[b + 1] + jy * w3;
186
+ out[b + 2] = clean[b + 2];
187
+ out[b + 3] = w3;
188
+ }
189
+ task.engine._device.queue.writeBuffer(src._sceneUBO, 0, out);
190
+ }
191
+
192
+ export { createTaaPostProcessTask };
193
+ //# sourceMappingURL=taa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taa.js","sources":["../../../src/post-process/taa.ts"],"sourcesContent":["// Temporal Anti-Aliasing (TAA) — a frame-graph post-process task.\n//\n// TAA jitters the camera projection by a sub-pixel Halton offset every frame and\n// accumulates a moving average of consecutive (jittered) frames. Spreading the\n// supersampling over time yields high-quality edge anti-aliasing without rendering\n// the scene multiple times per frame. The accumulated history converges to a\n// supersampled image after a few dozen frames.\n//\n// This task is a pure frame-graph node: add it at the END of a chain whose source\n// render task draws the scene into `sourceTexture`. Each frame it:\n// 1. blend : temp = mix(history, current, factor) (history bound as extra)\n// 2. present : temp -> targetTexture (e.g. the swapchain)\n// 3. historyUpd : temp -> history (becomes next frame's history)\n// 4. advances the Halton sequence and writes the jittered viewProjection into the\n// *source render task's* scene UBO so the NEXT frame renders sub-pixel shifted.\n//\n// `factor` is the blend weight of the current frame (BJS default 0.05). On the first\n// frame and on a camera-move reset it is forced to 1 (output == current) so no stale\n// history bleeds in.\n//\n// The jitter is injected by overwriting only the viewProjection slice (bytes 0..63)\n// of the source task's already-packed scene UBO. The source task's UBO write is\n// cached on the camera's worldMatrixVersion, so with a static camera our jittered\n// matrix survives each frame; when the camera moves the source re-packs a clean\n// matrix (a natural reset) and we set factor=1 for that frame. This needs zero\n// changes to the shared camera / scene-uniform hot path — so scenes that do not use\n// TAA pay nothing.\n\nimport { F32 } from \"../engine/typed-arrays.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { RenderTarget } from \"../engine/render-target.js\";\nimport { buildRenderTarget, createRenderTarget, disposeRenderTarget } from \"../engine/render-target.js\";\nimport { createPostProcessTask, type PostProcessTask, type PostProcessTaskSettings } from \"../frame-graph/post-process-task.js\";\nimport type { RenderTask } from \"../frame-graph/render-task.js\";\nimport type { Task } from \"../frame-graph/task.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\n\n/** Configuration for `createTaaPostProcessTask`. */\nexport interface TaaPostProcessTaskConfig extends PostProcessTaskSettings {\n /** The render task that draws the scene into `sourceTexture`. TAA jitters this\n * task's camera projection each frame (mirrors BJS `FrameGraphTAATask.objectRendererTask`). */\n sourceRenderTask: RenderTask;\n /** Blend weight of the current frame against the accumulated history (default: 0.05). */\n factor?: number;\n /** Number of jitter samples in the Halton sequence (default: 8). */\n samples?: number;\n /** Force a one-frame reset (output == current) whenever the camera moves (default: true).\n * Avoids ghosting while the view changes. */\n disableOnCameraMove?: boolean;\n}\n\n/** A Temporal Anti-Aliasing post-process task: accumulates jittered frames into an\n * anti-aliased image. Inject at the end of a frame-graph chain. */\nexport interface TaaPostProcessTask extends Task, PostProcessTaskSettings {\n readonly name: string;\n sourceTexture: RenderTarget;\n targetTexture: RenderTarget | null;\n outputTexture: RenderTarget;\n /** Blend weight of the current frame (smaller = smoother / slower convergence). */\n factor: number;\n /** Number of Halton jitter samples. */\n readonly samples: number;\n /** Reset to the current frame whenever the camera moves. */\n disableOnCameraMove: boolean;\n /** Recompute and upload the blend pass uniforms from current settings. */\n updateUniforms(): void;\n}\n\ninterface TaaTaskInternal extends TaaPostProcessTask {\n _blend: PostProcessTask;\n _present: PostProcessTask;\n _historyUpdate: PostProcessTask;\n _history: RenderTarget;\n _temp: RenderTarget;\n _sourceRenderTask: RenderTask;\n /** Raw Halton offsets in [-0.5, 0.5): [x0,y0, x1,y1, ...]. Scaled per-frame by source size. */\n _halton: Float32Array;\n _haltonIndex: number;\n _jitterScratch: Float32Array;\n _firstUpdate: boolean;\n _lastCamVer: number;\n _factor: number;\n}\n\nconst TAA_HISTORY_TEXTURE_WGSL = `@group(0) @binding(2) var taaHistory:texture_2d<f32>;`;\n\nconst TAA_UNIFORM_WGSL = `struct TaaParams{factor:f32,p0:f32,p1:f32,p2:f32}\n@group(0) @binding(3) var<uniform> taaParams:TaaParams;`;\n\n// mix(history, current, factor): factor=1 -> current only (first frame / reset).\nconst TAA_FRAGMENT_WGSL = `fn applyPostProcess(color:vec4f, uv:vec2f)->vec4f{let h=textureSample(taaHistory,sourceSampler,uv);return mix(h,color,taaParams.factor);}`;\n\n// Identity passthrough used by the present + history-update copies.\nconst TAA_COPY_FRAGMENT_WGSL = `fn applyPostProcess(color:vec4f, uv:vec2f)->vec4f{return color;}`;\n\n/**\n * Create a Temporal Anti-Aliasing post-process task.\n * @param config - Source texture + source render task, blend factor, sample count.\n * @param engine - The owning engine.\n * @param scene - Optional owning scene.\n * @returns The TAA post-process task. Add it at the end of the frame-graph chain.\n */\nexport function createTaaPostProcessTask(config: TaaPostProcessTaskConfig, engine: EngineContext, scene?: SceneContext): TaaPostProcessTask {\n const name = config.name ?? \"taa\";\n const source = config.sourceTexture;\n const target = config.targetTexture ?? null;\n // Clamp to >= 1: a zero/negative sample count would make `generateHalton` return an\n // empty sequence and `advanceJitter` write NaN jitter offsets into the source UBO.\n const samples = Math.max(1, Math.floor(config.samples ?? 8));\n const sizeRef = source._descriptor.size;\n\n // History accumulates at RGBA16F so the 0.05 moving average does not band on\n // an 8-bit buffer (matches BJS half-float history).\n const history = createRenderTarget({ lbl: `${name}-history`, format: \"rgba16float\", samples: 1, size: sizeRef });\n const temp = createRenderTarget({ lbl: `${name}-temp`, format: \"rgba16float\", samples: 1, size: sizeRef });\n\n const blend = createPostProcessTask(\n {\n name: `${name}-blend`,\n sourceTexture: source,\n // Nearest sampling reads the exact co-located texel of both the current\n // frame and the history (all three targets share a resolution).\n sourceSamplingMode: \"nearest\",\n targetTexture: temp,\n _shader: {\n extraTextureWGSL: TAA_HISTORY_TEXTURE_WGSL,\n extraTextures: [history],\n uniformWGSL: TAA_UNIFORM_WGSL,\n uniformBinding: 3,\n uniformByteLength: 16,\n writeUniforms(data) {\n data[0] = task._factor;\n },\n fragmentWGSL: TAA_FRAGMENT_WGSL,\n },\n },\n engine,\n scene\n );\n const present = createPostProcessTask(\n {\n name: `${name}-present`,\n sourceTexture: temp,\n sourceSamplingMode: \"nearest\",\n targetTexture: target ?? engine.scRT,\n _shader: { fragmentWGSL: TAA_COPY_FRAGMENT_WGSL },\n },\n engine,\n scene\n );\n const historyUpdate = createPostProcessTask(\n {\n name: `${name}-history-update`,\n sourceTexture: temp,\n sourceSamplingMode: \"nearest\",\n targetTexture: history,\n _shader: { fragmentWGSL: TAA_COPY_FRAGMENT_WGSL },\n },\n engine,\n scene\n );\n\n const task: TaaTaskInternal = {\n name,\n engine,\n scene,\n _passes: [],\n sourceTexture: source,\n targetTexture: target,\n outputTexture: target ?? engine.scRT,\n factor: config.factor ?? 0.05,\n samples,\n disableOnCameraMove: config.disableOnCameraMove ?? true,\n _blend: blend,\n _present: present,\n _historyUpdate: historyUpdate,\n _history: history,\n _temp: temp,\n _sourceRenderTask: config.sourceRenderTask,\n _halton: generateHalton(samples),\n _haltonIndex: 0,\n _jitterScratch: new F32(16),\n _firstUpdate: true,\n _lastCamVer: -1,\n _factor: 1,\n record(): void {\n // History + temp are persistent ping-pong buffers: allocate them once\n // (eager), sized to the source, and only reallocate on a real size change.\n // Marking them eager makes the sub-tasks' internal `buildRenderTarget`\n // no-op on them — critical because `historyUpdate` targets `history`, and a\n // rebuild there would destroy the texture `blend`'s bind group references.\n const { width: w, height: h } = resolveSourceSize(task.sourceTexture);\n ensurePersistentTarget(history, engine, w, h);\n ensurePersistentTarget(temp, engine, w, h);\n blend.record();\n present.record();\n historyUpdate.record();\n task._firstUpdate = true;\n task._haltonIndex = 0;\n task._lastCamVer = -1;\n },\n execute(): number {\n const cam = task._sourceRenderTask.scene.camera;\n const camVer = cam ? cam.worldMatrixVersion : 0;\n const moved = camVer !== task._lastCamVer;\n task._lastCamVer = camVer;\n\n // factor=1 on the first frame and on camera-move reset: take the current\n // (un-jittered) frame verbatim, discarding stale history.\n const reset = task._firstUpdate || (moved && task.disableOnCameraMove);\n task._factor = reset ? 1 : task.factor;\n blend.updateUniforms();\n\n let draws = blend.execute?.() ?? 0;\n draws += present.execute?.() ?? 0;\n draws += historyUpdate.execute?.() ?? 0;\n\n task._firstUpdate = false;\n\n // Prepare the NEXT frame's jitter: advance the Halton sequence and write the\n // jittered viewProjection into the source task's UBO. Always done — even on a\n // reset frame — so accumulation starts immediately on the following frame.\n // The blend `factor` reset already prevents stale-history bleed, and a still-\n // moving camera re-packs a clean matrix next frame anyway (overwriting this).\n advanceJitter(task);\n return draws;\n },\n updateUniforms(): void {\n blend.updateUniforms();\n },\n dispose(): void {\n task._passes.length = 0;\n blend.dispose();\n present.dispose();\n historyUpdate.dispose();\n // Clear the eager flag so the persistent buffers are actually freed.\n history._eager = false;\n temp._eager = false;\n disposeRenderTarget(history);\n disposeRenderTarget(temp);\n },\n };\n return task;\n}\n\n/** Allocate (or, on a size change, reallocate) a persistent ping-pong target sized\n * `width`×`height`. The target is marked `_eager` so the post-process sub-tasks'\n * internal `buildRenderTarget` no-ops on it, keeping accumulated history alive across\n * frames and preventing a rebuild from destroying a texture still bound elsewhere. */\nfunction ensurePersistentTarget(rt: RenderTarget, engine: EngineContext, width: number, height: number): void {\n if (rt._eager && rt._width === width && rt._height === height) {\n return;\n }\n rt._eager = false;\n disposeRenderTarget(rt);\n rt._descriptor.size = { width, height };\n buildRenderTarget(rt, engine);\n rt._eager = true;\n}\n\n/** Resolve a render target's pixel size: prefer its allocated dimensions, falling back\n * to the descriptor's surface (multi-surface safe — does not assume the engine canvas)\n * or explicit pixel size before the target has been built. */\nfunction resolveSourceSize(source: RenderTarget): { width: number; height: number } {\n if (source._width > 0 && source._height > 0) {\n return { width: source._width, height: source._height };\n }\n const size = source._descriptor.size;\n if (\"canvas\" in size) {\n return { width: size.canvas.width, height: size.canvas.height };\n }\n return { width: size.width, height: size.height };\n}\n\n/** Generate `samples` 2D Halton offsets (base 2 / base 3) centered on [-0.5, 0.5). */\nfunction generateHalton(samples: number): Float32Array {\n const seq = new F32(samples * 2);\n for (let i = 1; i <= samples; i++) {\n seq[(i - 1) * 2] = halton(i, 2) - 0.5;\n seq[(i - 1) * 2 + 1] = halton(i, 3) - 0.5;\n }\n return seq;\n}\n\nfunction halton(index: number, base: number): number {\n let fraction = 1;\n let result = 0;\n while (index > 0) {\n fraction /= base;\n result += fraction * (index % base);\n index = Math.floor(index / base);\n }\n return result;\n}\n\n/** Advance the Halton sequence and overwrite the source task's viewProjection\n * (column-major bytes 0..63 of its scene UBO) with a sub-pixel jittered matrix. */\nfunction advanceJitter(task: TaaTaskInternal): void {\n const src = task._sourceRenderTask;\n const clean = src._suData;\n const w = task.sourceTexture._width;\n const h = task.sourceTexture._height;\n if (w <= 0 || h <= 0) {\n return;\n }\n\n // NDC sub-pixel offset: one pixel spans 2/size in NDC, so size/2 is the denominator.\n const jx = task._halton[task._haltonIndex]! / (w / 2);\n const jy = task._halton[task._haltonIndex + 1]! / (h / 2);\n task._haltonIndex += 2;\n if (task._haltonIndex >= task._halton.length) {\n task._haltonIndex = 0;\n }\n\n // Translate the projected image by (jx, jy) in NDC: clip.xy += (jx,jy)*clip.w.\n // Column-major: row r, col c lives at c*4+r. Add j*row3 to row0 / row1.\n const out = task._jitterScratch;\n for (let c = 0; c < 4; c++) {\n const b = c * 4;\n const w3 = clean[b + 3]!;\n out[b] = clean[b]! + jx * w3;\n out[b + 1] = clean[b + 1]! + jy * w3;\n out[b + 2] = clean[b + 2]!;\n out[b + 3] = w3;\n }\n task.engine._device.queue.writeBuffer(src._sceneUBO, 0, out as Float32Array<ArrayBuffer>);\n}\n"],"names":[],"mappings":"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"}
@@ -33,6 +33,7 @@ function createSceneContext(surface, options) {
33
33
  _renderableVersion: 0,
34
34
  _materialEpoch: 0,
35
35
  _built: false,
36
+ _builtGroups: /* @__PURE__ */ new Set(),
36
37
  _drawCallsPre: 0,
37
38
  _update() {
38
39
  if (eng.useFloatingOrigin && ctx.camera && !ctx.camera._useFloatingOrigin) {
@@ -138,10 +139,11 @@ function addToScene(scene, entity) {
138
139
  if (result.updater) {
139
140
  ctx._uniformUpdaters.push(result.updater);
140
141
  }
142
+ ctx._builtGroups.add(build);
141
143
  });
142
144
  }
143
145
  group.push(mesh);
144
- if (ctx._built) {
146
+ if (ctx._built || ctx._builtGroups.has(build)) {
145
147
  enqueueMaterialSwap(ctx, mesh);
146
148
  }
147
149
  }
@@ -189,12 +191,13 @@ function disposeScene(scene) {
189
191
  }
190
192
  async function buildScene(scene) {
191
193
  const ctx = scene;
194
+ ctx._materialSwapQueue.length = 0;
192
195
  while (ctx._deferredBuilders.length > 0) {
193
196
  const builders = [...ctx._deferredBuilders];
194
197
  ctx._deferredBuilders = [];
195
198
  await Promise.all(builders.map(async (b) => b()));
196
199
  }
197
- ctx._materialSwapQueue.length = 0;
200
+ processMaterialSwaps(ctx);
198
201
  ctx._renderableVersion++;
199
202
  ctx._built = true;
200
203
  }