@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.
- package/dist/index.js +457 -458
- package/dist/index.js.map +1 -1
- package/index.d.ts +107 -48
- package/lib/camera/geospatial-camera-controls.js +22 -0
- package/lib/camera/geospatial-camera-controls.js.map +1 -1
- package/lib/camera/geospatial-camera-fly.js +2 -1
- package/lib/camera/geospatial-camera-fly.js.map +1 -1
- package/lib/effect/effect-renderer.js +1 -1
- package/lib/effect/effect-renderer.js.map +1 -1
- package/lib/engine/engine.js +1 -1
- package/lib/frame-graph/depth-resolve-task.js +117 -0
- package/lib/frame-graph/depth-resolve-task.js.map +1 -0
- package/lib/frame-graph/transmission.js +4 -3
- package/lib/frame-graph/transmission.js.map +1 -1
- package/lib/index.js +5 -1
- package/lib/index.js.map +1 -1
- package/lib/material/shader/shader-material.js +4 -2
- package/lib/material/shader/shader-material.js.map +1 -1
- package/lib/material/shader/shader-pipeline.js +10 -0
- package/lib/material/shader/shader-pipeline.js.map +1 -1
- package/lib/material/shader/shader-renderable.js +19 -6
- package/lib/material/shader/shader-renderable.js.map +1 -1
- package/lib/material/shader/shader-thin-instance.js +1 -1
- package/lib/material/shader/shader-thin-instance.js.map +1 -1
- package/lib/post-process/taa.js +193 -0
- package/lib/post-process/taa.js.map +1 -0
- package/lib/scene/scene-core.js +5 -2
- package/lib/scene/scene-core.js.map +1 -1
- package/lib/shadow/csm-shadow-task-hooks.js +14 -6
- package/lib/shadow/csm-shadow-task-hooks.js.map +1 -1
- package/lib/shadow/pcf-shadow-task-hooks.js +6 -0
- package/lib/shadow/pcf-shadow-task-hooks.js.map +1 -1
- package/lib/sprite/billboard-custom-shader.js +32 -32
- package/lib/sprite/billboard-custom-shader.js.map +1 -1
- package/lib/sprite/billboard-pipeline.js +54 -56
- package/lib/sprite/billboard-pipeline.js.map +1 -1
- package/lib/sprite/custom-shader-core.js +1 -1
- package/lib/sprite/custom-shader-core.js.map +1 -1
- package/lib/sprite/shared/sprite-atlas.js +2 -2
- package/lib/sprite/shared/sprite-atlas.js.map +1 -1
- package/lib/sprite/sprite-2d-coverage-gamma.js +58 -0
- package/lib/sprite/sprite-2d-coverage-gamma.js.map +1 -0
- package/lib/sprite/sprite-2d-uvscroll.js +39 -0
- package/lib/sprite/sprite-2d-uvscroll.js.map +1 -0
- package/lib/sprite/sprite-2d.js +6 -40
- package/lib/sprite/sprite-2d.js.map +1 -1
- package/lib/sprite/sprite-coverage-gamma-hook.js +10 -0
- package/lib/sprite/sprite-coverage-gamma-hook.js.map +1 -0
- package/lib/sprite/sprite-custom-shader.js +2 -2
- package/lib/sprite/sprite-custom-shader.js.map +1 -1
- package/lib/sprite/sprite-pipeline.js +56 -71
- package/lib/sprite/sprite-pipeline.js.map +1 -1
- package/lib/sprite/sprite-renderable.js +5 -5
- package/lib/sprite/sprite-renderable.js.map +1 -1
- package/lib/sprite/sprite-renderer.js +4 -4
- package/lib/sprite/sprite-renderer.js.map +1 -1
- package/lib/sprite/sprite-scene.js +1 -1
- package/lib/sprite/sprite-scene.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transmission.js","sources":["../../../src/frame-graph/transmission.ts"],"sourcesContent":["import { TU, SS } from \"../engine/gpu-flags.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { _vis } from \"../engine/engine.js\";\nimport { createRenderTarget } from \"../engine/render-target.js\";\nimport { getBilinearSampler } from \"../resource/samplers.js\";\nimport { getTrilinearAnisotropicSampler } from \"../resource/trilinear-anisotropic-sampler.js\";\nimport type { Texture2D } from \"../texture/texture-2d.js\";\nimport { recordMipmaps } from \"../texture/generate-mipmaps.js\";\nimport { biasedMipLevelCount } from \"../texture/mip-count.js\";\nimport type { DrawBinding } from \"../render/renderable.js\";\nimport type { RenderTask } from \"./render-task.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport { createImageProcessingTask } from \"./image-processing-task.js\";\n\nexport interface RenderTaskTransmissionState {\n readonly texture: Texture2D;\n /** @internal */\n readonly _baseView: GPUTextureView;\n /** @internal */\n _sourceWidth: number;\n /** @internal */\n _sourceHeight: number;\n /** @internal */\n _sourceTexture: GPUTexture | null;\n /** @internal */\n _blit: TransmissionBlitState | null;\n /** @internal */\n readonly _copyCount: number;\n /** @internal */\n readonly _generateMipmaps: boolean;\n /** @internal */\n _copies: number;\n}\n\ninterface TransmissionBlitState {\n readonly _pipeline: GPURenderPipeline;\n readonly _bindGroup: GPUBindGroup;\n}\n\nconst BLIT_SHADER = `@group(0)@binding(0)var t:texture_2d<f32>;@group(0)@binding(1)var s:sampler;struct V{@builtin(position)p:vec4f,@location(0)u:vec2f};@vertex fn vs(@builtin(vertex_index)i:u32)->V{var p=array<vec2f,3>(vec2f(-1,-1),vec2f(3,-1),vec2f(-1,3));var u=array<vec2f,3>(vec2f(0,1),vec2f(2,1),vec2f(0,-1));return V(vec4f(p[i],0,1),u[i]);}@fragment fn fs(v:V)->@location(0)vec4f{return textureSample(t,s,v.u);}`;\nconst BLIT_MSAA_SHADER = `@group(0)@binding(0)var t:texture_multisampled_2d<f32>;struct V{@builtin(position)p:vec4f,@location(0)u:vec2f};@vertex fn vs(@builtin(vertex_index)i:u32)->V{var p=array<vec2f,3>(vec2f(-1,-1),vec2f(3,-1),vec2f(-1,3));var u=array<vec2f,3>(vec2f(0,1),vec2f(2,1),vec2f(0,-1));return V(vec4f(p[i],0,1),u[i]);}fn l(p:vec2i)->vec4f{let n=textureNumSamples(t);var c=vec4f(0);for(var i=0u;i<n;i++){c+=textureLoad(t,p,i);}return c/f32(n);}@fragment fn fs(v:V)->@location(0)vec4f{let d=vec2i(textureDimensions(t));let q=clamp(v.u*vec2f(d)-.5,vec2f(0),vec2f(d-vec2i(1)));let p=vec2i(floor(q));let f=fract(q);let p1=min(p+vec2i(1),d-vec2i(1));return mix(mix(l(p),l(vec2i(p1.x,p.y)),f.x),mix(l(vec2i(p.x,p1.y)),l(p1),f.x),f.y);}`;\nconst REFRACTION_LOD_BIAS = 4;\nlet blitPipelines: Map<string, GPURenderPipeline> | null = null;\nlet blitShader: GPUShaderModule | null = null;\nlet blitMsaaShader: GPUShaderModule | null = null;\nlet blitBgl: GPUBindGroupLayout | null = null;\nlet blitMsaaBgl: GPUBindGroupLayout | null = null;\nlet blitDevice: GPUDevice | null = null;\n\n/** Enable scene-color transmission for every render task currently registered in a scene. PBR materials are marked for linear transmission, and a trailing image-processing task is appended when needed. */\nexport function enableSceneTransmission(scene: SceneContext, engine: EngineContext): void {\n markPbrMaterialsLinear(scene);\n let lastRenderTask: RenderTask | null = null;\n for (const task of scene._frameGraph._tasks) {\n if (\"_renderables\" in task) {\n const renderTask = task as RenderTask;\n enableRenderTaskTransmission(renderTask, engine);\n lastRenderTask = renderTask;\n }\n }\n if (lastRenderTask && !scene._frameGraph._tasks.some((task) => task.name === \"transmission-image-processing\")) {\n scene._frameGraph._tasks.push(createImageProcessingTask({ name: \"transmission-image-processing\", source: lastRenderTask._config.rt }, engine, scene));\n }\n}\n\n/** Options controlling how a render task exposes opaque scene color to transmissive materials. Use these to opt out of the linear offscreen path, control refresh frequency, and limit mipmap generation cost. */\nexport interface TransmissionOptions {\n /** When true (the default), retarget the task's color buffer to a linear `rgba16float`\n * offscreen and tone-map it in a trailing image-processing pass — the model PBR\n * transmission uses so refractive materials read scene color in *linear* space.\n *\n * Set false to perform ONLY the mid-pass scene-color grab: the task's render target\n * format / sample count / clear are left untouched and no tone-map pass is added. Use\n * this for consumers that own their tone mapping / post (e.g. a custom depth-of-field\n * stack) and just need the opaque scene color exposed to a custom transmissive\n * `ShaderMaterial`. */\n linear?: boolean;\n /** Override how many times the scene-colour grab is refreshed per frame. `0` means before every\n * transmissive draw; the default is once before the first transmissive draw. */\n copyCount?: number;\n /** Set false when the transmissive material never samples the scene-colour grab above mip 0. */\n generateMipmaps?: boolean;\n /** Cap the scene-colour grab mip chain. Use this when the material samples explicit low LODs only, so\n * unused tiny mips are not regenerated every frame. Ignored when `generateMipmaps` is false. */\n mipLevelCount?: number;\n}\n\n/** Handle to a render task's scene-color grab, returned by `enableRenderTaskTransmission`. */\nexport interface SceneColorGrab {\n /** The live opaque-scene-color texture sampled by transmissive surfaces, or null before the\n * frame graph has built the task at least once. Its identity changes when the task rebuilds\n * (e.g. on resize), so consumers that bind it to a custom material should re-bind when it\n * changes. */\n readonly texture: Texture2D | null;\n}\n\n/** Enable mid-pass scene-color grabs for a single render task and return the live texture handle. The task is wrapped so transmissive draw calls can sample the opaque color rendered earlier in the same pass. */\nexport function enableRenderTaskTransmission(task: RenderTask, engine: EngineContext, options?: TransmissionOptions): SceneColorGrab {\n const linear = options?.linear !== false;\n applyTransmissionOptions(task, options);\n const grab: SceneColorGrab = {\n get texture(): Texture2D | null {\n return (task._targetSignature as { _transmissionTexture?: Texture2D })._transmissionTexture ?? null;\n },\n };\n if (task._executeWithTransmission) {\n return grab;\n }\n if (linear) {\n retargetRenderTaskToLinearOffscreen(task);\n }\n let state: RenderTaskTransmissionState | null = null;\n const record = task.record.bind(task);\n const execute = task.execute?.bind(task);\n const dispose = task.dispose?.bind(task);\n task.record = () => {\n disposeRenderTaskTransmission(state);\n state = createRenderTaskTransmission(task, engine);\n (task._targetSignature as { _transmissionTexture?: Texture2D })._transmissionTexture = state.texture;\n record();\n configureTransmissionSource(state, task, engine);\n };\n if (linear && execute) {\n task.execute = () => executeRenderTaskLinear(task.scene, execute);\n }\n task.dispose = () => {\n disposeRenderTaskTransmission(state);\n state = null;\n dispose?.();\n };\n task._executeWithTransmission = (sampleCount) => executePassWithTransmission(task, engine, state!, sampleCount);\n return grab;\n}\n\nfunction retargetRenderTaskToLinearOffscreen(task: RenderTask): void {\n const cfg = task._config;\n const oldDesc = cfg.rt._descriptor;\n const surface = task.scene.surface;\n const sampleCount = surface.msaaSamples;\n // The scene render task may target the shared engine scRT (single-sample,\n // colour-only — single-sample default path) or an MSAA colour RT that resolves into it\n // via `rst` (MSAA default path). Never mutate the shared scRT descriptor —\n // instead point the task at a fresh offscreen HDR target and stop resolving to swap.\n // Transmission samples this linear HDR result in its own final image-processing pass\n // that writes the tonemapped result to the swapchain.\n //\n // Depth ownership: when the task already carries an external depth (`cfg.depth`, the\n // single-sample default path), keep it; otherwise the new target owns depth (matching\n // the MSAA colour RT it replaces).\n const ownsDepth = !cfg.depth;\n const newRt = createRenderTarget({\n lbl: \"transmission-linear\",\n format: \"rgba16float\",\n dFormat: ownsDepth ? (oldDesc.dFormat ?? \"depth24plus-stencil8\") : undefined,\n _depthClearValue: oldDesc._depthClearValue,\n _depthCompare: oldDesc._depthCompare,\n samples: sampleCount,\n size: surface,\n });\n cfg.rt = newRt;\n cfg.rst = undefined;\n const sig = task._targetSignature as {\n _colorFormat?: GPUTextureFormat;\n _depthStencilFormat?: GPUTextureFormat;\n _depthCompare?: GPUCompareFunction;\n _sampleCount: number;\n };\n sig._colorFormat = \"rgba16float\";\n sig._depthStencilFormat = cfg.depth?._descriptor.dFormat ?? newRt._descriptor.dFormat;\n sig._depthCompare = newRt._descriptor._depthCompare;\n sig._sampleCount = sampleCount;\n task._opaqueBundles.length = 0;\n task._lastVersion = -1;\n}\n\nfunction executeRenderTaskLinear(scene: SceneContext, execute: () => number): number {\n const imageProcessing = scene.imageProcessing as { exposure: number; contrast: number; toneMappingEnabled: boolean | number };\n const toneMappingEnabled = imageProcessing.toneMappingEnabled;\n const clearColor = scene.clearColor;\n const linearClearColor = inverseImageProcessedColor(clearColor, imageProcessing.exposure, imageProcessing.contrast, toneMappingEnabled === true);\n imageProcessing.toneMappingEnabled = -1;\n scene.clearColor = linearClearColor;\n try {\n return execute();\n } finally {\n scene.clearColor = clearColor;\n imageProcessing.toneMappingEnabled = toneMappingEnabled;\n }\n}\n\nfunction inverseImageProcessedColor(color: GPUColorDict, exposure: number, contrast: number, toneMapping: boolean): GPUColorDict {\n return {\n r: inverseImageProcessedChannel(color.r, exposure, contrast, toneMapping),\n g: inverseImageProcessedChannel(color.g, exposure, contrast, toneMapping),\n b: inverseImageProcessedChannel(color.b, exposure, contrast, toneMapping),\n a: color.a,\n };\n}\n\nfunction inverseImageProcessedChannel(value: number, exposure: number, contrast: number, toneMapping: boolean): number {\n let c = clamp01(value);\n if (contrast < 1) {\n c = contrast > 0 ? clamp01((c - 0.5 * (1 - contrast)) / contrast) : 0.5;\n } else if (contrast > 1) {\n const mixAmount = contrast - 1;\n let lo = 0;\n let hi = 1;\n for (let i = 0; i < 16; i++) {\n const mid = (lo + hi) * 0.5;\n const high = mid * mid * (3 - 2 * mid);\n const out = mid + (high - mid) * mixAmount;\n if (out < c) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n c = (lo + hi) * 0.5;\n }\n c = c ** 2.2;\n if (toneMapping) {\n c = -Math.log2(Math.max(1 - c, 1e-6)) / 1.5905790328979492;\n }\n return exposure > 0 ? c / exposure : c;\n}\n\nfunction clamp01(v: number): number {\n return Math.min(Math.max(v, 0), 1);\n}\n\nfunction markPbrMaterialsLinear(scene: SceneContext): void {\n for (const mesh of scene.meshes) {\n const mat = mesh.material as { _linearImageProcessing?: boolean; _renderFeatures?: unknown } | undefined;\n if (mat) {\n mat._linearImageProcessing = true;\n mat._renderFeatures = undefined;\n }\n }\n}\n\nfunction createRenderTaskTransmission(task: RenderTask, engine: EngineContext): RenderTaskTransmissionState {\n const rt = task._config.rt;\n const width = 1024;\n const height = 1024;\n const format: GPUTextureFormat = \"rgba16float\";\n const mipLevelCount = transmissionMipLevelCount(task._config.transmission, width, height);\n const generateMipmaps = mipLevelCount > 1;\n const texture = engine._device.createTexture({\n label: task.name,\n size: { width, height },\n format,\n mipLevelCount,\n usage: TU.RENDER_ATTACHMENT | TU.TEXTURE_BINDING | TU.COPY_DST,\n });\n const tex: Texture2D = {\n texture,\n view: texture.createView(),\n sampler: getTrilinearAnisotropicSampler(engine),\n width,\n height,\n invertY: false,\n };\n return {\n texture: tex,\n _baseView: texture.createView({ baseMipLevel: 0, mipLevelCount: 1 }),\n _sourceWidth: rt._width,\n _sourceHeight: rt._height,\n _sourceTexture: null,\n _blit: null,\n _copyCount: normalizeCopyCount(task._config.transmission),\n _generateMipmaps: generateMipmaps,\n _copies: 0,\n };\n}\n\nfunction configureTransmissionSource(state: RenderTaskTransmissionState, task: RenderTask, engine: EngineContext): void {\n const rt = task._config.rt;\n state._sourceWidth = rt._width;\n state._sourceHeight = rt._height;\n state._sourceTexture = rt._colorTexture;\n const sampleCount = task._targetSignature._sampleCount;\n if (!state._sourceTexture) {\n return;\n }\n state._blit = shouldBlitTransmission(state, sampleCount) ? createTransmissionBlit(state, engine, state._sourceTexture, sampleCount > 1) : null;\n}\n\nfunction disposeRenderTaskTransmission(state: RenderTaskTransmissionState | null | undefined): void {\n state?.texture.texture.destroy();\n}\n\nexport function executePassWithTransmission(task: RenderTask, engine: EngineContext, state: RenderTaskTransmissionState, sampleCount: number): number {\n state._copies = 0;\n const transparent = task._transparentBindings;\n let pass = beginTaskPass(task, null, sampleCount, false);\n let draws = drawBaseTask(task, pass);\n let lastPipeline: GPURenderPipeline | null = null;\n let overlay: DrawBinding[] | null = null;\n for (let i = 0; i < transparent.length; i++) {\n const binding = transparent[i]!;\n // `Mesh.renderOnTop` surfaces draw last — after the scene-colour grab — so they sit on top of the\n // transmissive surface and are excluded from what it refracts (e.g. lily pads on water).\n if (binding.renderable.mesh?.renderOnTop === true) {\n (overlay ??= []).push(binding);\n continue;\n }\n const transmissive = binding.renderable._transmissive === true;\n if (transmissive && canUpdateTransmission(state)) {\n pass.end();\n updateTransmissionTexture(state, engine);\n pass = beginTaskPass(task, null, sampleCount, true);\n setPassState(task, pass);\n lastPipeline = null;\n }\n const mesh = binding.renderable.mesh;\n if (mesh && mesh.visible === false) {\n continue;\n }\n if (binding.pipeline !== lastPipeline) {\n pass.setPipeline(binding.pipeline);\n lastPipeline = binding.pipeline;\n }\n draws += binding.draw(pass, engine);\n }\n if (overlay) {\n draws += drawList(pass, overlay, engine);\n }\n pass.end();\n return draws;\n}\n\nfunction updateTransmissionTexture(state: RenderTaskTransmissionState, engine: EngineContext): void {\n if (!state._sourceTexture) {\n throw new Error(\"No transmission source\");\n }\n if (state._blit) {\n blitToTransmission(state, engine);\n } else {\n engine._currentEncoder.copyTextureToTexture(\n { texture: state._sourceTexture },\n { texture: state.texture.texture },\n { width: state.texture.width, height: state.texture.height }\n );\n }\n if (state._generateMipmaps) {\n recordMipmaps(engine, state.texture.texture, engine._currentEncoder);\n }\n state._copies++;\n}\n\nfunction getBlitPipeline(engine: EngineContext, format: GPUTextureFormat, multisampled: boolean): GPURenderPipeline {\n const device = engine._device;\n if (device !== blitDevice) {\n blitPipelines?.clear();\n blitPipelines = null;\n blitShader = null;\n blitMsaaShader = null;\n blitBgl = null;\n blitMsaaBgl = null;\n blitDevice = device;\n }\n if (multisampled) {\n blitMsaaShader ??= device.createShaderModule({ code: BLIT_MSAA_SHADER });\n blitMsaaBgl ??= device.createBindGroupLayout({\n entries: [{ binding: 0, visibility: SS.FRAGMENT, texture: { sampleType: \"unfilterable-float\", multisampled: true } }],\n });\n } else {\n blitShader ??= device.createShaderModule({ code: BLIT_SHADER });\n blitBgl ??= device.createBindGroupLayout({\n entries: [\n { binding: 0, visibility: SS.FRAGMENT, texture: { sampleType: \"float\" } },\n { binding: 1, visibility: SS.FRAGMENT, sampler: {} },\n ],\n });\n }\n blitPipelines ??= new Map();\n const key = `${format}:${multisampled ? \"msaa\" : \"\"}`;\n let pipeline = blitPipelines.get(key);\n if (!pipeline) {\n const bgl = multisampled ? blitMsaaBgl! : blitBgl!;\n pipeline = device.createRenderPipeline({\n label: \"transmission-copy\",\n layout: device.createPipelineLayout({ bindGroupLayouts: [bgl] }),\n vertex: { module: multisampled ? blitMsaaShader! : blitShader!, entryPoint: \"vs\" },\n fragment: { module: multisampled ? blitMsaaShader! : blitShader!, entryPoint: \"fs\", targets: [{ format }] },\n primitive: { topology: \"triangle-list\" },\n });\n blitPipelines.set(key, pipeline);\n }\n return pipeline;\n}\n\nfunction shouldBlitTransmission(state: RenderTaskTransmissionState, sampleCount: number): boolean {\n return sampleCount > 1 || state._sourceWidth !== state.texture.width || state._sourceHeight !== state.texture.height;\n}\n\nfunction createTransmissionBlit(state: RenderTaskTransmissionState, engine: EngineContext, source: GPUTexture, multisampled: boolean): TransmissionBlitState {\n const device = engine._device;\n const pipeline = getBlitPipeline(engine, state.texture.texture.format, multisampled);\n const bindGroup = device.createBindGroup({\n layout: multisampled ? blitMsaaBgl! : blitBgl!,\n entries: multisampled\n ? [{ binding: 0, resource: source.createView() }]\n : [\n { binding: 0, resource: source.createView() },\n { binding: 1, resource: getBilinearSampler(engine) },\n ],\n });\n return { _pipeline: pipeline, _bindGroup: bindGroup };\n}\n\nfunction blitToTransmission(state: RenderTaskTransmissionState, engine: EngineContext): void {\n const blit = state._blit!;\n const pass = engine._currentEncoder.beginRenderPass({\n colorAttachments: [{ view: state._baseView, loadOp: \"clear\", storeOp: \"store\", clearValue: { r: 0, g: 0, b: 0, a: 0 } }],\n });\n pass.setPipeline(blit._pipeline);\n pass.setBindGroup(0, blit._bindGroup);\n pass.draw(3);\n pass.end();\n}\n\nfunction canUpdateTransmission(state: RenderTaskTransmissionState): boolean {\n return state._copyCount === 0 || state._copies < state._copyCount;\n}\n\nfunction beginTaskPass(task: RenderTask, resolveTarget: GPUTextureView | null, sampleCount: number, load: boolean): GPURenderPassEncoder {\n const att = task._colorAttachment;\n const depthLoadOp = load || !task._config.clr ? \"load\" : \"clear\";\n if (load) {\n att.loadOp = \"load\";\n }\n const depthAttachment = task._renderPassDescriptor.depthStencilAttachment;\n if (depthAttachment) {\n depthAttachment.depthLoadOp = depthLoadOp;\n if (depthAttachment.stencilLoadOp) {\n depthAttachment.stencilLoadOp = depthLoadOp;\n }\n }\n if (sampleCount > 1) {\n att.resolveTarget = resolveTarget ?? undefined;\n } else {\n att.resolveTarget = undefined;\n }\n return task.engine._currentEncoder.beginRenderPass(task._renderPassDescriptor);\n}\n\nfunction setPassState(task: RenderTask, pass: GPURenderPassEncoder): void {\n const cfg = task._config;\n const rt = cfg.rt;\n const scene = task.scene;\n const camera = cfg.cam ?? scene.camera;\n const v = camera?.viewport;\n if (v) {\n const rw = rt._width;\n const rh = rt._height;\n const x = Math.floor(v.x * rw);\n const y = Math.floor((1 - v.y - v.height) * rh);\n const w = Math.ceil((v.x + v.width) * rw) - x;\n const h = Math.ceil((1 - v.y) * rh) - y;\n pass.setViewport(x, y, w, h, 0, 1);\n pass.setScissorRect(x, y, w, h);\n }\n pass.setBindGroup(0, task._sceneBG);\n}\n\nfunction drawBaseTask(task: RenderTask, pass: GPURenderPassEncoder): number {\n const eng = task.engine;\n const rt = task._config.rt;\n const scene = task.scene;\n const opaqueBindings = task._opaqueBindings;\n const opaqueBundles = task._opaqueBundles;\n\n setPassState(task, pass);\n\n if (task._lastVersion !== scene._renderableVersion || task._lastVis !== _vis || opaqueBundles.length === 0) {\n const desc = rt._descriptor;\n const be = eng._device.createRenderBundleEncoder({\n colorFormats: desc.format ? [desc.format] : [],\n depthStencilFormat: desc.dFormat,\n sampleCount: desc.samples ?? 1,\n });\n be.setBindGroup(0, task._sceneBG);\n drawList(be, opaqueBindings, eng);\n opaqueBundles[0] = be.finish();\n task._lastVersion = scene._renderableVersion;\n task._lastVis = _vis;\n }\n let draws = opaqueBindings.length;\n pass.executeBundles(opaqueBundles);\n pass.setBindGroup(0, task._sceneBG);\n draws += drawList(pass, task._directBindings, eng);\n return draws;\n}\n\nfunction drawList(enc: GPURenderPassEncoder | GPURenderBundleEncoder, list: readonly DrawBinding[], engine: EngineContext): number {\n let lp: GPURenderPipeline | null = null;\n let draws = 0;\n for (const b of list) {\n const mesh = b.renderable.mesh;\n if (mesh && mesh.visible === false) {\n continue;\n }\n if (b.pipeline !== lp) {\n enc.setPipeline(b.pipeline);\n lp = b.pipeline;\n }\n draws += b.draw(enc, engine);\n }\n return draws;\n}\n\nfunction normalizeCopyCount(cfg: RenderTask[\"_config\"][\"transmission\"]): number {\n const count = cfg?.copyCount ?? 1;\n return count === Infinity ? 0 : Math.max(0, count | 0);\n}\n\nfunction applyTransmissionOptions(task: RenderTask, options: TransmissionOptions | undefined): void {\n if (!options) {\n return;\n }\n let next = task._config.transmission;\n let changed = false;\n const set = <K extends keyof NonNullable<RenderTask[\"_config\"][\"transmission\"]>>(key: K, value: NonNullable<RenderTask[\"_config\"][\"transmission\"]>[K] | undefined): void => {\n if (value === undefined) {\n return;\n }\n next = { ...next, [key]: value };\n changed = true;\n };\n set(\"copyCount\", options.copyCount);\n set(\"generateMipmaps\", options.generateMipmaps);\n set(\"mipLevelCount\", options.mipLevelCount);\n if (changed) {\n task._config.transmission = next;\n }\n}\n\nfunction transmissionMipLevelCount(cfg: RenderTask[\"_config\"][\"transmission\"], width: number, height: number): number {\n if (cfg?.generateMipmaps === false) {\n return 1;\n }\n const full = Math.floor(Math.log2(Math.max(width, height))) + 1;\n const defaultCount = biasedMipLevelCount(width, height, REFRACTION_LOD_BIAS);\n const requested = cfg?.mipLevelCount;\n if (requested === undefined) {\n return Math.min(full, defaultCount);\n }\n return Math.min(full, Math.max(1, requested | 0));\n}\n"],"names":[],"mappings":";;;;;;;;;AAuCA,MAAM,WAAA,GAAc,CAAA,4YAAA,CAAA;AACpB,MAAM,gBAAA,GAAmB,CAAA,0sBAAA,CAAA;AACzB,MAAM,mBAAA,GAAsB,CAAA;AAC5B,IAAI,aAAA,GAAuD,IAAA;AAC3D,IAAI,UAAA,GAAqC,IAAA;AACzC,IAAI,cAAA,GAAyC,IAAA;AAC7C,IAAI,OAAA,GAAqC,IAAA;AACzC,IAAI,WAAA,GAAyC,IAAA;AAC7C,IAAI,UAAA,GAA+B,IAAA;AAG5B,SAAS,uBAAA,CAAwB,OAAqB,MAAA,EAA6B;AACtF,EAAA,sBAAA,CAAuB,KAAK,CAAA;AAC5B,EAAA,IAAI,cAAA,GAAoC,IAAA;AACxC,EAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,CAAM,WAAA,CAAY,MAAA,EAAQ;AACzC,IAAA,IAAI,kBAAkB,IAAA,EAAM;AACxB,MAAA,MAAM,UAAA,GAAa,IAAA;AACnB,MAAA,4BAAA,CAA6B,YAAY,MAAM,CAAA;AAC/C,MAAA,cAAA,GAAiB,UAAA;AAAA,IACrB;AAAA,EACJ;AACA,EAAA,IAAI,cAAA,IAAkB,CAAC,KAAA,CAAM,WAAA,CAAY,MAAA,CAAO,IAAA,CAAK,CAAC,IAAA,KAAS,IAAA,CAAK,IAAA,KAAS,+BAA+B,CAAA,EAAG;AAC3G,IAAA,KAAA,CAAM,WAAA,CAAY,MAAA,CAAO,IAAA,CAAK,yBAAA,CAA0B,EAAE,IAAA,EAAM,+BAAA,EAAiC,MAAA,EAAQ,cAAA,CAAe,OAAA,CAAQ,EAAA,EAAG,EAAG,MAAA,EAAQ,KAAK,CAAC,CAAA;AAAA,EACxJ;AACJ;AAkCO,SAAS,4BAAA,CAA6B,IAAA,EAAkB,MAAA,EAAuB,OAAA,EAA+C;AACjI,EAAA,MAAM,MAAA,GAAS,SAAS,MAAA,KAAW,KAAA;AACnC,EAAA,wBAAA,CAAyB,MAAM,OAAO,CAAA;AACtC,EAAA,MAAM,IAAA,GAAuB;AAAA,IACzB,IAAI,OAAA,GAA4B;AAC5B,MAAA,OAAQ,IAAA,CAAK,iBAA0D,oBAAA,IAAwB,IAAA;AAAA,IACnG;AAAA,GACJ;AACA,EAAA,IAAI,KAAK,wBAAA,EAA0B;AAC/B,IAAA,OAAO,IAAA;AAAA,EACX;AACA,EAAA,IAAI,MAAA,EAAQ;AACR,IAAA,mCAAA,CAAoC,IAAI,CAAA;AAAA,EAC5C;AACA,EAAA,IAAI,KAAA,GAA4C,IAAA;AAChD,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA;AACpC,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,EAAS,IAAA,CAAK,IAAI,CAAA;AACvC,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,EAAS,IAAA,CAAK,IAAI,CAAA;AACvC,EAAA,IAAA,CAAK,SAAS,MAAM;AAChB,IAAA,6BAAA,CAA8B,KAAK,CAAA;AACnC,IAAA,KAAA,GAAQ,4BAAA,CAA6B,MAAM,MAAM,CAAA;AACjD,IAAC,IAAA,CAAK,gBAAA,CAA0D,oBAAA,GAAuB,KAAA,CAAM,OAAA;AAC7F,IAAA,MAAA,EAAO;AACP,IAAA,2BAAA,CAA4B,KAAA,EAAO,MAAM,MAAM,CAAA;AAAA,EACnD,CAAA;AACA,EAAA,IAAI,UAAU,OAAA,EAAS;AACnB,IAAA,IAAA,CAAK,OAAA,GAAU,MAAM,uBAAA,CAAwB,IAAA,CAAK,OAAO,OAAO,CAAA;AAAA,EACpE;AACA,EAAA,IAAA,CAAK,UAAU,MAAM;AACjB,IAAA,6BAAA,CAA8B,KAAK,CAAA;AACnC,IAAA,KAAA,GAAQ,IAAA;AACR,IAAA,OAAA,IAAU;AAAA,EACd,CAAA;AACA,EAAA,IAAA,CAAK,2BAA2B,CAAC,WAAA,KAAgB,4BAA4B,IAAA,EAAM,MAAA,EAAQ,OAAQ,WAAW,CAAA;AAC9G,EAAA,OAAO,IAAA;AACX;AAEA,SAAS,oCAAoC,IAAA,EAAwB;AACjE,EAAA,MAAM,MAAM,IAAA,CAAK,OAAA;AACjB,EAAA,MAAM,OAAA,GAAU,IAAI,EAAA,CAAG,WAAA;AACvB,EAAA,MAAM,OAAA,GAAU,KAAK,KAAA,CAAM,OAAA;AAC3B,EAAA,MAAM,cAAc,OAAA,CAAQ,WAAA;AAW5B,EAAA,MAAM,SAAA,GAAY,CAAC,GAAA,CAAI,KAAA;AACvB,EAAA,MAAM,QAAQ,kBAAA,CAAmB;AAAA,IAC7B,GAAA,EAAK,qBAAA;AAAA,IACL,MAAA,EAAQ,aAAA;AAAA,IACR,OAAA,EAAS,SAAA,GAAa,OAAA,CAAQ,OAAA,IAAW,sBAAA,GAA0B,MAAA;AAAA,IACnE,kBAAkB,OAAA,CAAQ,gBAAA;AAAA,IAC1B,eAAe,OAAA,CAAQ,aAAA;AAAA,IACvB,OAAA,EAAS,WAAA;AAAA,IACT,IAAA,EAAM;AAAA,GACT,CAAA;AACD,EAAA,GAAA,CAAI,EAAA,GAAK,KAAA;AACT,EAAA,GAAA,CAAI,GAAA,GAAM,MAAA;AACV,EAAA,MAAM,MAAM,IAAA,CAAK,gBAAA;AAMjB,EAAA,GAAA,CAAI,YAAA,GAAe,aAAA;AACnB,EAAA,GAAA,CAAI,sBAAsB,GAAA,CAAI,KAAA,EAAO,WAAA,CAAY,OAAA,IAAW,MAAM,WAAA,CAAY,OAAA;AAC9E,EAAA,GAAA,CAAI,aAAA,GAAgB,MAAM,WAAA,CAAY,aAAA;AACtC,EAAA,GAAA,CAAI,YAAA,GAAe,WAAA;AACnB,EAAA,IAAA,CAAK,eAAe,MAAA,GAAS,CAAA;AAC7B,EAAA,IAAA,CAAK,YAAA,GAAe,EAAA;AACxB;AAEA,SAAS,uBAAA,CAAwB,OAAqB,OAAA,EAA+B;AACjF,EAAA,MAAM,kBAAkB,KAAA,CAAM,eAAA;AAC9B,EAAA,MAAM,qBAAqB,eAAA,CAAgB,kBAAA;AAC3C,EAAA,MAAM,aAAa,KAAA,CAAM,UAAA;AACzB,EAAA,MAAM,gBAAA,GAAmB,2BAA2B,UAAA,EAAY,eAAA,CAAgB,UAAU,eAAA,CAAgB,QAAA,EAAU,uBAAuB,IAAI,CAAA;AAC/I,EAAA,eAAA,CAAgB,kBAAA,GAAqB,EAAA;AACrC,EAAA,KAAA,CAAM,UAAA,GAAa,gBAAA;AACnB,EAAA,IAAI;AACA,IAAA,OAAO,OAAA,EAAQ;AAAA,EACnB,CAAA,SAAE;AACE,IAAA,KAAA,CAAM,UAAA,GAAa,UAAA;AACnB,IAAA,eAAA,CAAgB,kBAAA,GAAqB,kBAAA;AAAA,EACzC;AACJ;AAEA,SAAS,0BAAA,CAA2B,KAAA,EAAqB,QAAA,EAAkB,QAAA,EAAkB,WAAA,EAAoC;AAC7H,EAAA,OAAO;AAAA,IACH,GAAG,4BAAA,CAA6B,KAAA,CAAM,CAAA,EAAG,QAAA,EAAU,UAAU,WAAW,CAAA;AAAA,IACxE,GAAG,4BAAA,CAA6B,KAAA,CAAM,CAAA,EAAG,QAAA,EAAU,UAAU,WAAW,CAAA;AAAA,IACxE,GAAG,4BAAA,CAA6B,KAAA,CAAM,CAAA,EAAG,QAAA,EAAU,UAAU,WAAW,CAAA;AAAA,IACxE,GAAG,KAAA,CAAM;AAAA,GACb;AACJ;AAEA,SAAS,4BAAA,CAA6B,KAAA,EAAe,QAAA,EAAkB,QAAA,EAAkB,WAAA,EAA8B;AACnH,EAAA,IAAI,CAAA,GAAI,QAAQ,KAAK,CAAA;AACrB,EAAA,IAAI,WAAW,CAAA,EAAG;AACd,IAAA,CAAA,GAAI,QAAA,GAAW,IAAI,OAAA,CAAA,CAAS,CAAA,GAAI,OAAO,CAAA,GAAI,QAAA,CAAA,IAAa,QAAQ,CAAA,GAAI,GAAA;AAAA,EACxE,CAAA,MAAA,IAAW,WAAW,CAAA,EAAG;AACrB,IAAA,MAAM,YAAY,QAAA,GAAW,CAAA;AAC7B,IAAA,IAAI,EAAA,GAAK,CAAA;AACT,IAAA,IAAI,EAAA,GAAK,CAAA;AACT,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,EAAA,EAAI,CAAA,EAAA,EAAK;AACzB,MAAA,MAAM,GAAA,GAAA,CAAO,KAAK,EAAA,IAAM,GAAA;AACxB,MAAA,MAAM,IAAA,GAAO,GAAA,GAAM,GAAA,IAAO,CAAA,GAAI,CAAA,GAAI,GAAA,CAAA;AAClC,MAAA,MAAM,GAAA,GAAM,GAAA,GAAA,CAAO,IAAA,GAAO,GAAA,IAAO,SAAA;AACjC,MAAA,IAAI,MAAM,CAAA,EAAG;AACT,QAAA,EAAA,GAAK,GAAA;AAAA,MACT,CAAA,MAAO;AACH,QAAA,EAAA,GAAK,GAAA;AAAA,MACT;AAAA,IACJ;AACA,IAAA,CAAA,GAAA,CAAK,KAAK,EAAA,IAAM,GAAA;AAAA,EACpB;AACA,EAAA,CAAA,GAAI,CAAA,IAAK,GAAA;AACT,EAAA,IAAI,WAAA,EAAa;AACb,IAAA,CAAA,GAAI,CAAC,KAAK,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA,GAAI,CAAA,EAAG,IAAI,CAAC,CAAA,GAAI,kBAAA;AAAA,EAC5C;AACA,EAAA,OAAO,QAAA,GAAW,CAAA,GAAI,CAAA,GAAI,QAAA,GAAW,CAAA;AACzC;AAEA,SAAS,QAAQ,CAAA,EAAmB;AAChC,EAAA,OAAO,KAAK,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AACrC;AAEA,SAAS,uBAAuB,KAAA,EAA2B;AACvD,EAAA,KAAA,MAAW,IAAA,IAAQ,MAAM,MAAA,EAAQ;AAC7B,IAAA,MAAM,MAAM,IAAA,CAAK,QAAA;AACjB,IAAA,IAAI,GAAA,EAAK;AACL,MAAA,GAAA,CAAI,sBAAA,GAAyB,IAAA;AAC7B,MAAA,GAAA,CAAI,eAAA,GAAkB,MAAA;AAAA,IAC1B;AAAA,EACJ;AACJ;AAEA,SAAS,4BAAA,CAA6B,MAAkB,MAAA,EAAoD;AACxG,EAAA,MAAM,EAAA,GAAK,KAAK,OAAA,CAAQ,EAAA;AACxB,EAAA,MAAM,KAAA,GAAQ,IAAA;AACd,EAAA,MAAM,MAAA,GAAS,IAAA;AACf,EAAA,MAAM,MAAA,GAA2B,aAAA;AACjC,EAAA,MAAM,gBAAgB,yBAAA,CAA0B,IAAA,CAAK,OAAA,CAAQ,YAAA,EAAc,OAAO,MAAM,CAAA;AACxF,EAAA,MAAM,kBAAkB,aAAA,GAAgB,CAAA;AACxC,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,aAAA,CAAc;AAAA,IACzC,OAAO,IAAA,CAAK,IAAA;AAAA,IACZ,IAAA,EAAM,EAAE,KAAA,EAAO,MAAA,EAAO;AAAA,IACtB,MAAA;AAAA,IACA,aAAA;AAAA,IACA,KAAA,EAAO,EAAA,CAAG,iBAAA,GAAoB,EAAA,CAAG,kBAAkB,EAAA,CAAG;AAAA,GACzD,CAAA;AACD,EAAA,MAAM,GAAA,GAAiB;AAAA,IACnB,OAAA;AAAA,IACA,IAAA,EAAM,QAAQ,UAAA,EAAW;AAAA,IACzB,OAAA,EAAS,+BAA+B,MAAM,CAAA;AAAA,IAC9C,KAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAA,EAAS;AAAA,GACb;AACA,EAAA,OAAO;AAAA,IACH,OAAA,EAAS,GAAA;AAAA,IACT,SAAA,EAAW,QAAQ,UAAA,CAAW,EAAE,cAAc,CAAA,EAAG,aAAA,EAAe,GAAG,CAAA;AAAA,IACnE,cAAc,EAAA,CAAG,MAAA;AAAA,IACjB,eAAe,EAAA,CAAG,OAAA;AAAA,IAClB,cAAA,EAAgB,IAAA;AAAA,IAChB,KAAA,EAAO,IAAA;AAAA,IACP,UAAA,EAAY,kBAAA,CAAmB,IAAA,CAAK,OAAA,CAAQ,YAAY,CAAA;AAAA,IACxD,gBAAA,EAAkB,eAAA;AAAA,IAClB,OAAA,EAAS;AAAA,GACb;AACJ;AAEA,SAAS,2BAAA,CAA4B,KAAA,EAAoC,IAAA,EAAkB,MAAA,EAA6B;AACpH,EAAA,MAAM,EAAA,GAAK,KAAK,OAAA,CAAQ,EAAA;AACxB,EAAA,KAAA,CAAM,eAAe,EAAA,CAAG,MAAA;AACxB,EAAA,KAAA,CAAM,gBAAgB,EAAA,CAAG,OAAA;AACzB,EAAA,KAAA,CAAM,iBAAiB,EAAA,CAAG,aAAA;AAC1B,EAAA,MAAM,WAAA,GAAc,KAAK,gBAAA,CAAiB,YAAA;AAC1C,EAAA,IAAI,CAAC,MAAM,cAAA,EAAgB;AACvB,IAAA;AAAA,EACJ;AACA,EAAA,KAAA,CAAM,KAAA,GAAQ,sBAAA,CAAuB,KAAA,EAAO,WAAW,CAAA,GAAI,sBAAA,CAAuB,KAAA,EAAO,MAAA,EAAQ,KAAA,CAAM,cAAA,EAAgB,WAAA,GAAc,CAAC,CAAA,GAAI,IAAA;AAC9I;AAEA,SAAS,8BAA8B,KAAA,EAA6D;AAChG,EAAA,KAAA,EAAO,OAAA,CAAQ,QAAQ,OAAA,EAAQ;AACnC;AAEO,SAAS,2BAAA,CAA4B,IAAA,EAAkB,MAAA,EAAuB,KAAA,EAAoC,WAAA,EAA6B;AAClJ,EAAA,KAAA,CAAM,OAAA,GAAU,CAAA;AAChB,EAAA,MAAM,cAAc,IAAA,CAAK,oBAAA;AACzB,EAAA,IAAI,IAAA,GAAO,aAAA,CAAc,IAAA,EAAM,IAAA,EAAM,aAAa,KAAK,CAAA;AACvD,EAAA,IAAI,KAAA,GAAQ,YAAA,CAAa,IAAA,EAAM,IAAI,CAAA;AACnC,EAAA,IAAI,YAAA,GAAyC,IAAA;AAC7C,EAAA,IAAI,OAAA,GAAgC,IAAA;AACpC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,WAAA,CAAY,QAAQ,CAAA,EAAA,EAAK;AACzC,IAAA,MAAM,OAAA,GAAU,YAAY,CAAC,CAAA;AAG7B,IAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,IAAA,EAAM,WAAA,KAAgB,IAAA,EAAM;AAC/C,MAAA,CAAC,OAAA,KAAY,EAAC,EAAG,IAAA,CAAK,OAAO,CAAA;AAC7B,MAAA;AAAA,IACJ;AACA,IAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,UAAA,CAAW,aAAA,KAAkB,IAAA;AAC1D,IAAA,IAAI,YAAA,IAAgB,qBAAA,CAAsB,KAAK,CAAA,EAAG;AAC9C,MAAA,IAAA,CAAK,GAAA,EAAI;AACT,MAAA,yBAAA,CAA0B,OAAO,MAAM,CAAA;AACvC,MAAA,IAAA,GAAO,aAAA,CAAc,IAAA,EAAM,IAAA,EAAM,WAAA,EAAa,IAAI,CAAA;AAClD,MAAA,YAAA,CAAa,MAAM,IAAI,CAAA;AACvB,MAAA,YAAA,GAAe,IAAA;AAAA,IACnB;AACA,IAAA,MAAM,IAAA,GAAO,QAAQ,UAAA,CAAW,IAAA;AAChC,IAAA,IAAI,IAAA,IAAQ,IAAA,CAAK,OAAA,KAAY,KAAA,EAAO;AAChC,MAAA;AAAA,IACJ;AACA,IAAA,IAAI,OAAA,CAAQ,aAAa,YAAA,EAAc;AACnC,MAAA,IAAA,CAAK,WAAA,CAAY,QAAQ,QAAQ,CAAA;AACjC,MAAA,YAAA,GAAe,OAAA,CAAQ,QAAA;AAAA,IAC3B;AACA,IAAA,KAAA,IAAS,OAAA,CAAQ,IAAA,CAAK,IAAA,EAAM,MAAM,CAAA;AAAA,EACtC;AACA,EAAA,IAAI,OAAA,EAAS;AACT,IAAA,KAAA,IAAS,QAAA,CAAS,IAAA,EAAM,OAAA,EAAS,MAAM,CAAA;AAAA,EAC3C;AACA,EAAA,IAAA,CAAK,GAAA,EAAI;AACT,EAAA,OAAO,KAAA;AACX;AAEA,SAAS,yBAAA,CAA0B,OAAoC,MAAA,EAA6B;AAChG,EAAA,IAAI,CAAC,MAAM,cAAA,EAAgB;AACvB,IAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,EAC5C;AACA,EAAA,IAAI,MAAM,KAAA,EAAO;AACb,IAAA,kBAAA,CAAmB,OAAO,MAAM,CAAA;AAAA,EACpC,CAAA,MAAO;AACH,IAAA,MAAA,CAAO,eAAA,CAAgB,oBAAA;AAAA,MACnB,EAAE,OAAA,EAAS,KAAA,CAAM,cAAA,EAAe;AAAA,MAChC,EAAE,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,OAAA,EAAQ;AAAA,MACjC,EAAE,OAAO,KAAA,CAAM,OAAA,CAAQ,OAAO,MAAA,EAAQ,KAAA,CAAM,QAAQ,MAAA;AAAO,KAC/D;AAAA,EACJ;AACA,EAAA,IAAI,MAAM,gBAAA,EAAkB;AACxB,IAAA,aAAA,CAAc,MAAA,EAAQ,KAAA,CAAM,OAAA,CAAQ,OAAA,EAAS,OAAO,eAAe,CAAA;AAAA,EACvE;AACA,EAAA,KAAA,CAAM,OAAA,EAAA;AACV;AAEA,SAAS,eAAA,CAAgB,MAAA,EAAuB,MAAA,EAA0B,YAAA,EAA0C;AAChH,EAAA,MAAM,SAAS,MAAA,CAAO,OAAA;AACtB,EAAA,IAAI,WAAW,UAAA,EAAY;AACvB,IAAA,aAAA,EAAe,KAAA,EAAM;AACrB,IAAA,aAAA,GAAgB,IAAA;AAChB,IAAA,UAAA,GAAa,IAAA;AACb,IAAA,cAAA,GAAiB,IAAA;AACjB,IAAA,OAAA,GAAU,IAAA;AACV,IAAA,WAAA,GAAc,IAAA;AACd,IAAA,UAAA,GAAa,MAAA;AAAA,EACjB;AACA,EAAA,IAAI,YAAA,EAAc;AACd,IAAA,cAAA,KAAmB,MAAA,CAAO,kBAAA,CAAmB,EAAE,IAAA,EAAM,kBAAkB,CAAA;AACvE,IAAA,WAAA,KAAgB,OAAO,qBAAA,CAAsB;AAAA,MACzC,OAAA,EAAS,CAAC,EAAE,OAAA,EAAS,GAAG,UAAA,EAAY,EAAA,CAAG,QAAA,EAAU,OAAA,EAAS,EAAE,UAAA,EAAY,oBAAA,EAAsB,YAAA,EAAc,IAAA,IAAQ;AAAA,KACvH,CAAA;AAAA,EACL,CAAA,MAAO;AACH,IAAA,UAAA,KAAe,MAAA,CAAO,kBAAA,CAAmB,EAAE,IAAA,EAAM,aAAa,CAAA;AAC9D,IAAA,OAAA,KAAY,OAAO,qBAAA,CAAsB;AAAA,MACrC,OAAA,EAAS;AAAA,QACL,EAAE,OAAA,EAAS,CAAA,EAAG,UAAA,EAAY,EAAA,CAAG,UAAU,OAAA,EAAS,EAAE,UAAA,EAAY,OAAA,EAAQ,EAAE;AAAA,QACxE,EAAE,SAAS,CAAA,EAAG,UAAA,EAAY,GAAG,QAAA,EAAU,OAAA,EAAS,EAAC;AAAE;AACvD,KACH,CAAA;AAAA,EACL;AACA,EAAA,aAAA,yBAAsB,GAAA,EAAI;AAC1B,EAAA,MAAM,MAAM,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,YAAA,GAAe,SAAS,EAAE,CAAA,CAAA;AACnD,EAAA,IAAI,QAAA,GAAW,aAAA,CAAc,GAAA,CAAI,GAAG,CAAA;AACpC,EAAA,IAAI,CAAC,QAAA,EAAU;AACX,IAAA,MAAM,GAAA,GAAM,eAAe,WAAA,GAAe,OAAA;AAC1C,IAAA,QAAA,GAAW,OAAO,oBAAA,CAAqB;AAAA,MACnC,KAAA,EAAO,mBAAA;AAAA,MACP,MAAA,EAAQ,OAAO,oBAAA,CAAqB,EAAE,kBAAkB,CAAC,GAAG,GAAG,CAAA;AAAA,MAC/D,QAAQ,EAAE,MAAA,EAAQ,eAAe,cAAA,GAAkB,UAAA,EAAa,YAAY,IAAA,EAAK;AAAA,MACjF,QAAA,EAAU,EAAE,MAAA,EAAQ,YAAA,GAAe,cAAA,GAAkB,UAAA,EAAa,UAAA,EAAY,IAAA,EAAM,OAAA,EAAS,CAAC,EAAE,MAAA,EAAQ,CAAA,EAAE;AAAA,MAC1G,SAAA,EAAW,EAAE,QAAA,EAAU,eAAA;AAAgB,KAC1C,CAAA;AACD,IAAA,aAAA,CAAc,GAAA,CAAI,KAAK,QAAQ,CAAA;AAAA,EACnC;AACA,EAAA,OAAO,QAAA;AACX;AAEA,SAAS,sBAAA,CAAuB,OAAoC,WAAA,EAA8B;AAC9F,EAAA,OAAO,WAAA,GAAc,CAAA,IAAK,KAAA,CAAM,YAAA,KAAiB,KAAA,CAAM,QAAQ,KAAA,IAAS,KAAA,CAAM,aAAA,KAAkB,KAAA,CAAM,OAAA,CAAQ,MAAA;AAClH;AAEA,SAAS,sBAAA,CAAuB,KAAA,EAAoC,MAAA,EAAuB,MAAA,EAAoB,YAAA,EAA8C;AACzJ,EAAA,MAAM,SAAS,MAAA,CAAO,OAAA;AACtB,EAAA,MAAM,WAAW,eAAA,CAAgB,MAAA,EAAQ,MAAM,OAAA,CAAQ,OAAA,CAAQ,QAAQ,YAAY,CAAA;AACnF,EAAA,MAAM,SAAA,GAAY,OAAO,eAAA,CAAgB;AAAA,IACrC,MAAA,EAAQ,eAAe,WAAA,GAAe,OAAA;AAAA,IACtC,OAAA,EAAS,YAAA,GACH,CAAC,EAAE,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,MAAA,CAAO,UAAA,EAAW,EAAG,CAAA,GAC9C;AAAA,MACI,EAAE,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,MAAA,CAAO,YAAW,EAAE;AAAA,MAC5C,EAAE,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,kBAAA,CAAmB,MAAM,CAAA;AAAE;AACvD,GACT,CAAA;AACD,EAAA,OAAO,EAAE,SAAA,EAAW,QAAA,EAAU,UAAA,EAAY,SAAA,EAAU;AACxD;AAEA,SAAS,kBAAA,CAAmB,OAAoC,MAAA,EAA6B;AACzF,EAAA,MAAM,OAAO,KAAA,CAAM,KAAA;AACnB,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,eAAA,CAAgB,eAAA,CAAgB;AAAA,IAChD,gBAAA,EAAkB,CAAC,EAAE,IAAA,EAAM,MAAM,SAAA,EAAW,MAAA,EAAQ,SAAS,OAAA,EAAS,OAAA,EAAS,YAAY,EAAE,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAE,EAAG;AAAA,GAC1H,CAAA;AACD,EAAA,IAAA,CAAK,WAAA,CAAY,KAAK,SAAS,CAAA;AAC/B,EAAA,IAAA,CAAK,YAAA,CAAa,CAAA,EAAG,IAAA,CAAK,UAAU,CAAA;AACpC,EAAA,IAAA,CAAK,KAAK,CAAC,CAAA;AACX,EAAA,IAAA,CAAK,GAAA,EAAI;AACb;AAEA,SAAS,sBAAsB,KAAA,EAA6C;AACxE,EAAA,OAAO,KAAA,CAAM,UAAA,KAAe,CAAA,IAAK,KAAA,CAAM,UAAU,KAAA,CAAM,UAAA;AAC3D;AAEA,SAAS,aAAA,CAAc,IAAA,EAAkB,aAAA,EAAsC,WAAA,EAAqB,IAAA,EAAqC;AACrI,EAAA,MAAM,MAAM,IAAA,CAAK,gBAAA;AACjB,EAAA,MAAM,cAAc,IAAA,IAAQ,CAAC,IAAA,CAAK,OAAA,CAAQ,MAAM,MAAA,GAAS,OAAA;AACzD,EAAA,IAAI,IAAA,EAAM;AACN,IAAA,GAAA,CAAI,MAAA,GAAS,MAAA;AAAA,EACjB;AACA,EAAA,MAAM,eAAA,GAAkB,KAAK,qBAAA,CAAsB,sBAAA;AACnD,EAAA,IAAI,eAAA,EAAiB;AACjB,IAAA,eAAA,CAAgB,WAAA,GAAc,WAAA;AAC9B,IAAA,IAAI,gBAAgB,aAAA,EAAe;AAC/B,MAAA,eAAA,CAAgB,aAAA,GAAgB,WAAA;AAAA,IACpC;AAAA,EACJ;AACA,EAAA,IAAI,cAAc,CAAA,EAAG;AACjB,IAAA,GAAA,CAAI,gBAAiC,MAAA;AAAA,EACzC,CAAA,MAAO;AACH,IAAA,GAAA,CAAI,aAAA,GAAgB,MAAA;AAAA,EACxB;AACA,EAAA,OAAO,IAAA,CAAK,MAAA,CAAO,eAAA,CAAgB,eAAA,CAAgB,KAAK,qBAAqB,CAAA;AACjF;AAEA,SAAS,YAAA,CAAa,MAAkB,IAAA,EAAkC;AACtE,EAAA,MAAM,MAAM,IAAA,CAAK,OAAA;AACjB,EAAA,MAAM,KAAK,GAAA,CAAI,EAAA;AACf,EAAA,MAAM,QAAQ,IAAA,CAAK,KAAA;AACnB,EAAA,MAAM,MAAA,GAAS,GAAA,CAAI,GAAA,IAAO,KAAA,CAAM,MAAA;AAChC,EAAA,MAAM,IAAI,MAAA,EAAQ,QAAA;AAClB,EAAA,IAAI,CAAA,EAAG;AACH,IAAA,MAAM,KAAK,EAAA,CAAG,MAAA;AACd,IAAA,MAAM,KAAK,EAAA,CAAG,OAAA;AACd,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,IAAI,EAAE,CAAA;AAC7B,IAAA,MAAM,CAAA,GAAI,KAAK,KAAA,CAAA,CAAO,CAAA,GAAI,EAAE,CAAA,GAAI,CAAA,CAAE,UAAU,EAAE,CAAA;AAC9C,IAAA,MAAM,CAAA,GAAI,KAAK,IAAA,CAAA,CAAM,CAAA,CAAE,IAAI,CAAA,CAAE,KAAA,IAAS,EAAE,CAAA,GAAI,CAAA;AAC5C,IAAA,MAAM,IAAI,IAAA,CAAK,IAAA,CAAA,CAAM,IAAI,CAAA,CAAE,CAAA,IAAK,EAAE,CAAA,GAAI,CAAA;AACtC,IAAA,IAAA,CAAK,YAAY,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAC,CAAA;AACjC,IAAA,IAAA,CAAK,cAAA,CAAe,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA;AAAA,EAClC;AACA,EAAA,IAAA,CAAK,YAAA,CAAa,CAAA,EAAG,IAAA,CAAK,QAAQ,CAAA;AACtC;AAEA,SAAS,YAAA,CAAa,MAAkB,IAAA,EAAoC;AACxE,EAAA,MAAM,MAAM,IAAA,CAAK,MAAA;AACjB,EAAA,MAAM,EAAA,GAAK,KAAK,OAAA,CAAQ,EAAA;AACxB,EAAA,MAAM,QAAQ,IAAA,CAAK,KAAA;AACnB,EAAA,MAAM,iBAAiB,IAAA,CAAK,eAAA;AAC5B,EAAA,MAAM,gBAAgB,IAAA,CAAK,cAAA;AAE3B,EAAA,YAAA,CAAa,MAAM,IAAI,CAAA;AAEvB,EAAA,IAAI,IAAA,CAAK,iBAAiB,KAAA,CAAM,kBAAA,IAAsB,KAAK,QAAA,KAAa,IAAA,IAAQ,aAAA,CAAc,MAAA,KAAW,CAAA,EAAG;AACxG,IAAA,MAAM,OAAO,EAAA,CAAG,WAAA;AAChB,IAAA,MAAM,EAAA,GAAK,GAAA,CAAI,OAAA,CAAQ,yBAAA,CAA0B;AAAA,MAC7C,cAAc,IAAA,CAAK,MAAA,GAAS,CAAC,IAAA,CAAK,MAAM,IAAI,EAAC;AAAA,MAC7C,oBAAoB,IAAA,CAAK,OAAA;AAAA,MACzB,WAAA,EAAa,KAAK,OAAA,IAAW;AAAA,KAChC,CAAA;AACD,IAAA,EAAA,CAAG,YAAA,CAAa,CAAA,EAAG,IAAA,CAAK,QAAQ,CAAA;AAChC,IAAA,QAAA,CAAS,EAAA,EAAI,gBAAgB,GAAG,CAAA;AAChC,IAAA,aAAA,CAAc,CAAC,CAAA,GAAI,EAAA,CAAG,MAAA,EAAO;AAC7B,IAAA,IAAA,CAAK,eAAe,KAAA,CAAM,kBAAA;AAC1B,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAAA,EACpB;AACA,EAAA,IAAI,QAAQ,cAAA,CAAe,MAAA;AAC3B,EAAA,IAAA,CAAK,eAAe,aAAa,CAAA;AACjC,EAAA,IAAA,CAAK,YAAA,CAAa,CAAA,EAAG,IAAA,CAAK,QAAQ,CAAA;AAClC,EAAA,KAAA,IAAS,QAAA,CAAS,IAAA,EAAM,IAAA,CAAK,eAAA,EAAiB,GAAG,CAAA;AACjD,EAAA,OAAO,KAAA;AACX;AAEA,SAAS,QAAA,CAAS,GAAA,EAAoD,IAAA,EAA8B,MAAA,EAA+B;AAC/H,EAAA,IAAI,EAAA,GAA+B,IAAA;AACnC,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,KAAA,MAAW,KAAK,IAAA,EAAM;AAClB,IAAA,MAAM,IAAA,GAAO,EAAE,UAAA,CAAW,IAAA;AAC1B,IAAA,IAAI,IAAA,IAAQ,IAAA,CAAK,OAAA,KAAY,KAAA,EAAO;AAChC,MAAA;AAAA,IACJ;AACA,IAAA,IAAI,CAAA,CAAE,aAAa,EAAA,EAAI;AACnB,MAAA,GAAA,CAAI,WAAA,CAAY,EAAE,QAAQ,CAAA;AAC1B,MAAA,EAAA,GAAK,CAAA,CAAE,QAAA;AAAA,IACX;AACA,IAAA,KAAA,IAAS,CAAA,CAAE,IAAA,CAAK,GAAA,EAAK,MAAM,CAAA;AAAA,EAC/B;AACA,EAAA,OAAO,KAAA;AACX;AAEA,SAAS,mBAAmB,GAAA,EAAoD;AAC5E,EAAA,MAAM,KAAA,GAAQ,KAAK,SAAA,IAAa,CAAA;AAChC,EAAA,OAAO,UAAU,QAAA,GAAW,CAAA,GAAI,KAAK,GAAA,CAAI,CAAA,EAAG,QAAQ,CAAC,CAAA;AACzD;AAEA,SAAS,wBAAA,CAAyB,MAAkB,OAAA,EAAgD;AAChG,EAAA,IAAI,CAAC,OAAA,EAAS;AACV,IAAA;AAAA,EACJ;AACA,EAAA,IAAI,IAAA,GAAO,KAAK,OAAA,CAAQ,YAAA;AACxB,EAAA,IAAI,OAAA,GAAU,KAAA;AACd,EAAA,MAAM,GAAA,GAAM,CAAqE,GAAA,EAAQ,KAAA,KAAmF;AACxK,IAAA,IAAI,UAAU,MAAA,EAAW;AACrB,MAAA;AAAA,IACJ;AACA,IAAA,IAAA,GAAO,EAAE,GAAG,IAAA,EAAM,CAAC,GAAG,GAAG,KAAA,EAAM;AAC/B,IAAA,OAAA,GAAU,IAAA;AAAA,EACd,CAAA;AACA,EAAA,GAAA,CAAI,WAAA,EAAa,QAAQ,SAAS,CAAA;AAClC,EAAA,GAAA,CAAI,iBAAA,EAAmB,QAAQ,eAAe,CAAA;AAC9C,EAAA,GAAA,CAAI,eAAA,EAAiB,QAAQ,aAAa,CAAA;AAC1C,EAAA,IAAI,OAAA,EAAS;AACT,IAAA,IAAA,CAAK,QAAQ,YAAA,GAAe,IAAA;AAAA,EAChC;AACJ;AAEA,SAAS,yBAAA,CAA0B,GAAA,EAA4C,KAAA,EAAe,MAAA,EAAwB;AAClH,EAAA,IAAI,GAAA,EAAK,oBAAoB,KAAA,EAAO;AAChC,IAAA,OAAO,CAAA;AAAA,EACX;AACA,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,MAAM,CAAC,CAAC,CAAA,GAAI,CAAA;AAC9D,EAAA,MAAM,YAAA,GAAe,mBAAA,CAAoB,KAAA,EAAO,MAAA,EAAQ,mBAAmB,CAAA;AAC3E,EAAA,MAAM,YAAY,GAAA,EAAK,aAAA;AACvB,EAAA,IAAI,cAAc,MAAA,EAAW;AACzB,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,YAAY,CAAA;AAAA,EACtC;AACA,EAAA,OAAO,IAAA,CAAK,IAAI,IAAA,EAAM,IAAA,CAAK,IAAI,CAAA,EAAG,SAAA,GAAY,CAAC,CAAC,CAAA;AACpD;;;;"}
|
|
1
|
+
{"version":3,"file":"transmission.js","sources":["../../../src/frame-graph/transmission.ts"],"sourcesContent":["import { TU, SS } from \"../engine/gpu-flags.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport { _vis } from \"../engine/engine.js\";\nimport { createRenderTarget } from \"../engine/render-target.js\";\nimport { getBilinearSampler } from \"../resource/samplers.js\";\nimport { getTrilinearAnisotropicSampler } from \"../resource/trilinear-anisotropic-sampler.js\";\nimport type { Texture2D } from \"../texture/texture-2d.js\";\nimport { recordMipmaps } from \"../texture/generate-mipmaps.js\";\nimport { biasedMipLevelCount } from \"../texture/mip-count.js\";\nimport type { DrawBinding } from \"../render/renderable.js\";\nimport type { RenderTask } from \"./render-task.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport { createImageProcessingTask } from \"./image-processing-task.js\";\n\nexport interface RenderTaskTransmissionState {\n readonly texture: Texture2D;\n /** @internal */\n readonly _baseView: GPUTextureView;\n /** @internal */\n _sourceWidth: number;\n /** @internal */\n _sourceHeight: number;\n /** @internal */\n _sourceTexture: GPUTexture | null;\n /** @internal */\n _blit: TransmissionBlitState | null;\n /** @internal */\n readonly _copyCount: number;\n /** @internal */\n readonly _generateMipmaps: boolean;\n /** @internal */\n _copies: number;\n}\n\ninterface TransmissionBlitState {\n readonly _pipeline: GPURenderPipeline;\n readonly _bindGroup: GPUBindGroup;\n}\n\nconst BLIT_SHADER = `@group(0)@binding(0)var t:texture_2d<f32>;@group(0)@binding(1)var s:sampler;struct V{@builtin(position)p:vec4f,@location(0)u:vec2f};@vertex fn vs(@builtin(vertex_index)i:u32)->V{var p=array<vec2f,3>(vec2f(-1,-1),vec2f(3,-1),vec2f(-1,3));var u=array<vec2f,3>(vec2f(0,1),vec2f(2,1),vec2f(0,-1));return V(vec4f(p[i],0,1),u[i]);}@fragment fn fs(v:V)->@location(0)vec4f{return textureSample(t,s,v.u);}`;\nconst BLIT_MSAA_SHADER = `@group(0)@binding(0)var t:texture_multisampled_2d<f32>;struct V{@builtin(position)p:vec4f,@location(0)u:vec2f};@vertex fn vs(@builtin(vertex_index)i:u32)->V{var p=array<vec2f,3>(vec2f(-1,-1),vec2f(3,-1),vec2f(-1,3));var u=array<vec2f,3>(vec2f(0,1),vec2f(2,1),vec2f(0,-1));return V(vec4f(p[i],0,1),u[i]);}fn l(p:vec2i)->vec4f{let n=textureNumSamples(t);var c=vec4f(0);for(var i=0u;i<n;i++){c+=textureLoad(t,p,i);}return c/f32(n);}@fragment fn fs(v:V)->@location(0)vec4f{let d=vec2i(textureDimensions(t));let q=clamp(v.u*vec2f(d)-.5,vec2f(0),vec2f(d-vec2i(1)));let p=vec2i(floor(q));let f=fract(q);let p1=min(p+vec2i(1),d-vec2i(1));return mix(mix(l(p),l(vec2i(p1.x,p.y)),f.x),mix(l(vec2i(p.x,p1.y)),l(p1),f.x),f.y);}`;\nconst REFRACTION_LOD_BIAS = 4;\nlet blitPipelines: Map<string, GPURenderPipeline> | null = null;\nlet blitShader: GPUShaderModule | null = null;\nlet blitMsaaShader: GPUShaderModule | null = null;\nlet blitBgl: GPUBindGroupLayout | null = null;\nlet blitMsaaBgl: GPUBindGroupLayout | null = null;\nlet blitDevice: GPUDevice | null = null;\n\n/** Enable scene-color transmission for every render task currently registered in a scene. PBR materials are marked for linear transmission, and a trailing image-processing task is appended when needed. */\nexport function enableSceneTransmission(scene: SceneContext, engine: EngineContext): void {\n markPbrMaterialsLinear(scene);\n let lastRenderTask: RenderTask | null = null;\n for (const task of scene._frameGraph._tasks) {\n if (\"_renderables\" in task) {\n const renderTask = task as RenderTask;\n enableRenderTaskTransmission(renderTask, engine);\n lastRenderTask = renderTask;\n }\n }\n if (lastRenderTask && !scene._frameGraph._tasks.some((task) => task.name === \"transmission-image-processing\")) {\n scene._frameGraph._tasks.push(createImageProcessingTask({ name: \"transmission-image-processing\", source: lastRenderTask._config.rt }, engine, scene));\n }\n}\n\n/** Options controlling how a render task exposes opaque scene color to transmissive materials. Use these to opt out of the linear offscreen path, control refresh frequency, and limit mipmap generation cost. */\nexport interface TransmissionOptions {\n /** When true (the default), retarget the task's color buffer to a linear `rgba16float`\n * offscreen and tone-map it in a trailing image-processing pass — the model PBR\n * transmission uses so refractive materials read scene color in *linear* space.\n *\n * Set false to perform ONLY the mid-pass scene-color grab: the task's render target\n * format / sample count / clear are left untouched and no tone-map pass is added. Use\n * this for consumers that own their tone mapping / post (e.g. a custom depth-of-field\n * stack) and just need the opaque scene color exposed to a custom transmissive\n * `ShaderMaterial`. */\n linear?: boolean;\n /** Override how many times the scene-colour grab is refreshed per frame. `0` means before every\n * transmissive draw; the default is once before the first transmissive draw. */\n copyCount?: number;\n /** Set false when the transmissive material never samples the scene-colour grab above mip 0. */\n generateMipmaps?: boolean;\n /** Cap the scene-colour grab mip chain. Use this when the material samples explicit low LODs only, so\n * unused tiny mips are not regenerated every frame. Ignored when `generateMipmaps` is false. */\n mipLevelCount?: number;\n}\n\n/** Handle to a render task's scene-color grab, returned by `enableRenderTaskTransmission`. */\nexport interface SceneColorGrab {\n /** The live opaque-scene-color texture sampled by transmissive surfaces, or null before the\n * frame graph has built the task at least once. Its identity changes when the task rebuilds\n * (e.g. on resize), so consumers that bind it to a custom material should re-bind when it\n * changes. */\n readonly texture: Texture2D | null;\n}\n\n/** Enable mid-pass scene-color grabs for a single render task and return the live texture handle. The task is wrapped so transmissive draw calls can sample the opaque color rendered earlier in the same pass. */\nexport function enableRenderTaskTransmission(task: RenderTask, engine: EngineContext, options?: TransmissionOptions): SceneColorGrab {\n const linear = options?.linear !== false;\n applyTransmissionOptions(task, options);\n const grab: SceneColorGrab = {\n get texture(): Texture2D | null {\n return (task._targetSignature as { _transmissionTexture?: Texture2D })._transmissionTexture ?? null;\n },\n };\n if (task._executeWithTransmission) {\n return grab;\n }\n if (linear) {\n retargetRenderTaskToLinearOffscreen(task);\n }\n let state: RenderTaskTransmissionState | null = null;\n const record = task.record.bind(task);\n const execute = task.execute?.bind(task);\n const dispose = task.dispose?.bind(task);\n task.record = () => {\n disposeRenderTaskTransmission(state);\n state = createRenderTaskTransmission(task, engine);\n (task._targetSignature as { _transmissionTexture?: Texture2D })._transmissionTexture = state.texture;\n record();\n configureTransmissionSource(state, task, engine);\n };\n if (linear && execute) {\n task.execute = () => executeRenderTaskLinear(task.scene, execute);\n }\n task.dispose = () => {\n disposeRenderTaskTransmission(state);\n state = null;\n dispose?.();\n };\n task._executeWithTransmission = (sampleCount) => executePassWithTransmission(task, engine, state!, sampleCount);\n return grab;\n}\n\nfunction retargetRenderTaskToLinearOffscreen(task: RenderTask): void {\n const cfg = task._config;\n const oldDesc = cfg.rt._descriptor;\n const surface = task.scene.surface;\n const sampleCount = surface.msaaSamples;\n // The scene render task may target the shared engine scRT (single-sample,\n // colour-only — single-sample default path) or an MSAA colour RT that resolves into it\n // via `rst` (MSAA default path). Never mutate the shared scRT descriptor —\n // instead point the task at a fresh offscreen HDR target and stop resolving to swap.\n // Transmission samples this linear HDR result in its own final image-processing pass\n // that writes the tonemapped result to the swapchain.\n //\n // Depth ownership: when the task already carries an external depth (`cfg.depth`, the\n // single-sample default path), keep it; otherwise the new target owns depth (matching\n // the MSAA colour RT it replaces).\n const ownsDepth = !cfg.depth;\n const newRt = createRenderTarget({\n lbl: \"transmission-linear\",\n format: \"rgba16float\",\n dFormat: ownsDepth ? (oldDesc.dFormat ?? \"depth24plus-stencil8\") : undefined,\n _depthClearValue: oldDesc._depthClearValue,\n _depthCompare: oldDesc._depthCompare,\n samples: sampleCount,\n size: surface,\n });\n cfg.rt = newRt;\n cfg.rst = undefined;\n const sig = task._targetSignature as {\n _colorFormat?: GPUTextureFormat;\n _depthStencilFormat?: GPUTextureFormat;\n _depthCompare?: GPUCompareFunction;\n _sampleCount: number;\n };\n sig._colorFormat = \"rgba16float\";\n sig._depthStencilFormat = cfg.depth?._descriptor.dFormat ?? newRt._descriptor.dFormat;\n sig._depthCompare = newRt._descriptor._depthCompare;\n sig._sampleCount = sampleCount;\n task._opaqueBundles.length = 0;\n task._lastVersion = -1;\n}\n\nfunction executeRenderTaskLinear(scene: SceneContext, execute: () => number): number {\n const imageProcessing = scene.imageProcessing as { exposure: number; contrast: number; toneMappingEnabled: boolean | number };\n const toneMappingEnabled = imageProcessing.toneMappingEnabled;\n const clearColor = scene.clearColor;\n const linearClearColor = inverseImageProcessedColor(clearColor, imageProcessing.exposure, imageProcessing.contrast, toneMappingEnabled === true);\n imageProcessing.toneMappingEnabled = -1;\n scene.clearColor = linearClearColor;\n try {\n return execute();\n } finally {\n scene.clearColor = clearColor;\n imageProcessing.toneMappingEnabled = toneMappingEnabled;\n }\n}\n\nfunction inverseImageProcessedColor(color: GPUColorDict, exposure: number, contrast: number, toneMapping: boolean): GPUColorDict {\n return {\n r: inverseImageProcessedChannel(color.r, exposure, contrast, toneMapping),\n g: inverseImageProcessedChannel(color.g, exposure, contrast, toneMapping),\n b: inverseImageProcessedChannel(color.b, exposure, contrast, toneMapping),\n a: color.a,\n };\n}\n\nfunction inverseImageProcessedChannel(value: number, exposure: number, contrast: number, toneMapping: boolean): number {\n let c = clamp01(value);\n if (contrast < 1) {\n c = contrast > 0 ? clamp01((c - 0.5 * (1 - contrast)) / contrast) : 0.5;\n } else if (contrast > 1) {\n const mixAmount = contrast - 1;\n let lo = 0;\n let hi = 1;\n for (let i = 0; i < 16; i++) {\n const mid = (lo + hi) * 0.5;\n const high = mid * mid * (3 - 2 * mid);\n const out = mid + (high - mid) * mixAmount;\n if (out < c) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n c = (lo + hi) * 0.5;\n }\n c = c ** 2.2;\n if (toneMapping) {\n c = -Math.log2(Math.max(1 - c, 1e-6)) / 1.5905790328979492;\n }\n return exposure > 0 ? c / exposure : c;\n}\n\nfunction clamp01(v: number): number {\n return Math.min(Math.max(v, 0), 1);\n}\n\nfunction markPbrMaterialsLinear(scene: SceneContext): void {\n for (const mesh of scene.meshes) {\n const mat = mesh.material as { _linearImageProcessing?: boolean; _renderFeatures?: unknown } | undefined;\n if (mat) {\n mat._linearImageProcessing = true;\n mat._renderFeatures = undefined;\n }\n }\n}\n\nfunction createRenderTaskTransmission(task: RenderTask, engine: EngineContext): RenderTaskTransmissionState {\n const rt = task._config.rt;\n const width = 1024;\n const height = 1024;\n const format: GPUTextureFormat = \"rgba16float\";\n const mipLevelCount = transmissionMipLevelCount(task._config.transmission, width, height);\n const generateMipmaps = mipLevelCount > 1;\n const texture = engine._device.createTexture({\n label: task.name,\n size: { width, height },\n format,\n mipLevelCount,\n usage: TU.RENDER_ATTACHMENT | TU.TEXTURE_BINDING | TU.COPY_DST,\n });\n const tex: Texture2D = {\n texture,\n view: texture.createView(),\n sampler: getTrilinearAnisotropicSampler(engine),\n width,\n height,\n invertY: false,\n };\n return {\n texture: tex,\n _baseView: texture.createView({ baseMipLevel: 0, mipLevelCount: 1 }),\n _sourceWidth: rt._width,\n _sourceHeight: rt._height,\n _sourceTexture: null,\n _blit: null,\n _copyCount: normalizeCopyCount(task._config.transmission),\n _generateMipmaps: generateMipmaps,\n _copies: 0,\n };\n}\n\nfunction configureTransmissionSource(state: RenderTaskTransmissionState, task: RenderTask, engine: EngineContext): void {\n const rt = task._config.rt;\n state._sourceWidth = rt._width;\n state._sourceHeight = rt._height;\n state._sourceTexture = rt._colorTexture;\n const sampleCount = task._targetSignature._sampleCount;\n if (!state._sourceTexture) {\n return;\n }\n state._blit = shouldBlitTransmission(state, sampleCount) ? createTransmissionBlit(state, engine, state._sourceTexture, sampleCount > 1) : null;\n}\n\nfunction disposeRenderTaskTransmission(state: RenderTaskTransmissionState | null | undefined): void {\n state?.texture.texture.destroy();\n}\n\nexport function executePassWithTransmission(task: RenderTask, engine: EngineContext, state: RenderTaskTransmissionState, sampleCount: number): number {\n state._copies = 0;\n const transparent = task._transparentBindings;\n // MSAA: resolve the FINAL scene colour into the task's single-sample resolve target (`rst`) so downstream\n // passes that SAMPLE the scene RTT (e.g. a custom DoF/present stack) get a resolved image. The multisampled\n // colour is preserved across the split segments (store/load), so resolving on every segment leaves the LAST\n // (complete) resolve in `rst`. No-op when single-sample (resolveView stays null) — existing scenes unchanged.\n const resolveView = sampleCount > 1 ? (task._config.rst?._colorView ?? null) : null;\n let pass = beginTaskPass(task, resolveView, sampleCount, false);\n let draws = drawBaseTask(task, pass);\n let lastPipeline: GPURenderPipeline | null = null;\n let overlay: DrawBinding[] | null = null;\n for (let i = 0; i < transparent.length; i++) {\n const binding = transparent[i]!;\n // `Mesh.renderOnTop` surfaces draw last — after the scene-colour grab — so they sit on top of the\n // transmissive surface and are excluded from what it refracts (e.g. lily pads on water).\n if (binding.renderable.mesh?.renderOnTop === true) {\n (overlay ??= []).push(binding);\n continue;\n }\n const transmissive = binding.renderable._transmissive === true;\n if (transmissive && canUpdateTransmission(state)) {\n pass.end();\n updateTransmissionTexture(state, engine);\n pass = beginTaskPass(task, resolveView, sampleCount, true);\n setPassState(task, pass);\n lastPipeline = null;\n }\n const mesh = binding.renderable.mesh;\n if (mesh && mesh.visible === false) {\n continue;\n }\n if (binding.pipeline !== lastPipeline) {\n pass.setPipeline(binding.pipeline);\n lastPipeline = binding.pipeline;\n }\n draws += binding.draw(pass, engine);\n }\n if (overlay) {\n draws += drawList(pass, overlay, engine);\n }\n pass.end();\n return draws;\n}\n\nfunction updateTransmissionTexture(state: RenderTaskTransmissionState, engine: EngineContext): void {\n if (!state._sourceTexture) {\n throw new Error(\"No transmission source\");\n }\n if (state._blit) {\n blitToTransmission(state, engine);\n } else {\n engine._currentEncoder.copyTextureToTexture(\n { texture: state._sourceTexture },\n { texture: state.texture.texture },\n { width: state.texture.width, height: state.texture.height }\n );\n }\n if (state._generateMipmaps) {\n recordMipmaps(engine, state.texture.texture, engine._currentEncoder);\n }\n state._copies++;\n}\n\nfunction getBlitPipeline(engine: EngineContext, format: GPUTextureFormat, multisampled: boolean): GPURenderPipeline {\n const device = engine._device;\n if (device !== blitDevice) {\n blitPipelines?.clear();\n blitPipelines = null;\n blitShader = null;\n blitMsaaShader = null;\n blitBgl = null;\n blitMsaaBgl = null;\n blitDevice = device;\n }\n if (multisampled) {\n blitMsaaShader ??= device.createShaderModule({ code: BLIT_MSAA_SHADER });\n blitMsaaBgl ??= device.createBindGroupLayout({\n entries: [{ binding: 0, visibility: SS.FRAGMENT, texture: { sampleType: \"unfilterable-float\", multisampled: true } }],\n });\n } else {\n blitShader ??= device.createShaderModule({ code: BLIT_SHADER });\n blitBgl ??= device.createBindGroupLayout({\n entries: [\n { binding: 0, visibility: SS.FRAGMENT, texture: { sampleType: \"float\" } },\n { binding: 1, visibility: SS.FRAGMENT, sampler: {} },\n ],\n });\n }\n blitPipelines ??= new Map();\n const key = `${format}:${multisampled ? \"msaa\" : \"\"}`;\n let pipeline = blitPipelines.get(key);\n if (!pipeline) {\n const bgl = multisampled ? blitMsaaBgl! : blitBgl!;\n pipeline = device.createRenderPipeline({\n label: \"transmission-copy\",\n layout: device.createPipelineLayout({ bindGroupLayouts: [bgl] }),\n vertex: { module: multisampled ? blitMsaaShader! : blitShader!, entryPoint: \"vs\" },\n fragment: { module: multisampled ? blitMsaaShader! : blitShader!, entryPoint: \"fs\", targets: [{ format }] },\n primitive: { topology: \"triangle-list\" },\n });\n blitPipelines.set(key, pipeline);\n }\n return pipeline;\n}\n\nfunction shouldBlitTransmission(state: RenderTaskTransmissionState, sampleCount: number): boolean {\n return sampleCount > 1 || state._sourceWidth !== state.texture.width || state._sourceHeight !== state.texture.height;\n}\n\nfunction createTransmissionBlit(state: RenderTaskTransmissionState, engine: EngineContext, source: GPUTexture, multisampled: boolean): TransmissionBlitState {\n const device = engine._device;\n const pipeline = getBlitPipeline(engine, state.texture.texture.format, multisampled);\n const bindGroup = device.createBindGroup({\n layout: multisampled ? blitMsaaBgl! : blitBgl!,\n entries: multisampled\n ? [{ binding: 0, resource: source.createView() }]\n : [\n { binding: 0, resource: source.createView() },\n { binding: 1, resource: getBilinearSampler(engine) },\n ],\n });\n return { _pipeline: pipeline, _bindGroup: bindGroup };\n}\n\nfunction blitToTransmission(state: RenderTaskTransmissionState, engine: EngineContext): void {\n const blit = state._blit!;\n const pass = engine._currentEncoder.beginRenderPass({\n colorAttachments: [{ view: state._baseView, loadOp: \"clear\", storeOp: \"store\", clearValue: { r: 0, g: 0, b: 0, a: 0 } }],\n });\n pass.setPipeline(blit._pipeline);\n pass.setBindGroup(0, blit._bindGroup);\n pass.draw(3);\n pass.end();\n}\n\nfunction canUpdateTransmission(state: RenderTaskTransmissionState): boolean {\n return state._copyCount === 0 || state._copies < state._copyCount;\n}\n\nfunction beginTaskPass(task: RenderTask, resolveTarget: GPUTextureView | null, sampleCount: number, load: boolean): GPURenderPassEncoder {\n const att = task._colorAttachment;\n const depthLoadOp = load || !task._config.clr ? \"load\" : \"clear\";\n if (load) {\n att.loadOp = \"load\";\n }\n const depthAttachment = task._renderPassDescriptor.depthStencilAttachment;\n if (depthAttachment) {\n depthAttachment.depthLoadOp = depthLoadOp;\n if (depthAttachment.stencilLoadOp) {\n depthAttachment.stencilLoadOp = depthLoadOp;\n }\n }\n if (sampleCount > 1) {\n att.resolveTarget = resolveTarget ?? undefined;\n } else {\n att.resolveTarget = undefined;\n }\n return task.engine._currentEncoder.beginRenderPass(task._renderPassDescriptor);\n}\n\nfunction setPassState(task: RenderTask, pass: GPURenderPassEncoder): void {\n const cfg = task._config;\n const rt = cfg.rt;\n const scene = task.scene;\n const camera = cfg.cam ?? scene.camera;\n const v = camera?.viewport;\n if (v) {\n const rw = rt._width;\n const rh = rt._height;\n const x = Math.floor(v.x * rw);\n const y = Math.floor((1 - v.y - v.height) * rh);\n const w = Math.ceil((v.x + v.width) * rw) - x;\n const h = Math.ceil((1 - v.y) * rh) - y;\n pass.setViewport(x, y, w, h, 0, 1);\n pass.setScissorRect(x, y, w, h);\n }\n pass.setBindGroup(0, task._sceneBG);\n}\n\nfunction drawBaseTask(task: RenderTask, pass: GPURenderPassEncoder): number {\n const eng = task.engine;\n const rt = task._config.rt;\n const scene = task.scene;\n const opaqueBindings = task._opaqueBindings;\n const opaqueBundles = task._opaqueBundles;\n\n setPassState(task, pass);\n\n if (task._lastVersion !== scene._renderableVersion || task._lastVis !== _vis || opaqueBundles.length === 0) {\n const desc = rt._descriptor;\n const be = eng._device.createRenderBundleEncoder({\n colorFormats: desc.format ? [desc.format] : [],\n depthStencilFormat: desc.dFormat,\n sampleCount: desc.samples ?? 1,\n });\n be.setBindGroup(0, task._sceneBG);\n drawList(be, opaqueBindings, eng);\n opaqueBundles[0] = be.finish();\n task._lastVersion = scene._renderableVersion;\n task._lastVis = _vis;\n }\n let draws = opaqueBindings.length;\n pass.executeBundles(opaqueBundles);\n pass.setBindGroup(0, task._sceneBG);\n draws += drawList(pass, task._directBindings, eng);\n return draws;\n}\n\nfunction drawList(enc: GPURenderPassEncoder | GPURenderBundleEncoder, list: readonly DrawBinding[], engine: EngineContext): number {\n let lp: GPURenderPipeline | null = null;\n let draws = 0;\n for (const b of list) {\n const mesh = b.renderable.mesh;\n if (mesh && mesh.visible === false) {\n continue;\n }\n if (b.pipeline !== lp) {\n enc.setPipeline(b.pipeline);\n lp = b.pipeline;\n }\n draws += b.draw(enc, engine);\n }\n return draws;\n}\n\nfunction normalizeCopyCount(cfg: RenderTask[\"_config\"][\"transmission\"]): number {\n const count = cfg?.copyCount ?? 1;\n return count === Infinity ? 0 : Math.max(0, count | 0);\n}\n\nfunction applyTransmissionOptions(task: RenderTask, options: TransmissionOptions | undefined): void {\n if (!options) {\n return;\n }\n let next = task._config.transmission;\n let changed = false;\n const set = <K extends keyof NonNullable<RenderTask[\"_config\"][\"transmission\"]>>(key: K, value: NonNullable<RenderTask[\"_config\"][\"transmission\"]>[K] | undefined): void => {\n if (value === undefined) {\n return;\n }\n next = { ...next, [key]: value };\n changed = true;\n };\n set(\"copyCount\", options.copyCount);\n set(\"generateMipmaps\", options.generateMipmaps);\n set(\"mipLevelCount\", options.mipLevelCount);\n if (changed) {\n task._config.transmission = next;\n }\n}\n\nfunction transmissionMipLevelCount(cfg: RenderTask[\"_config\"][\"transmission\"], width: number, height: number): number {\n if (cfg?.generateMipmaps === false) {\n return 1;\n }\n const full = Math.floor(Math.log2(Math.max(width, height))) + 1;\n const defaultCount = biasedMipLevelCount(width, height, REFRACTION_LOD_BIAS);\n const requested = cfg?.mipLevelCount;\n if (requested === undefined) {\n return Math.min(full, defaultCount);\n }\n return Math.min(full, Math.max(1, requested | 0));\n}\n"],"names":[],"mappings":"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"}
|
package/lib/index.js
CHANGED
|
@@ -14,6 +14,7 @@ export { addPassDependencies } from './frame-graph/pass.js';
|
|
|
14
14
|
export { createRenderTask, removeMeshFromTask } from './frame-graph/render-task.js';
|
|
15
15
|
export { createImageProcessingTask } from './frame-graph/image-processing-task.js';
|
|
16
16
|
export { createCopyToTextureTask } from './frame-graph/copy-to-texture-task.js';
|
|
17
|
+
export { createDepthResolveTask } from './frame-graph/depth-resolve-task.js';
|
|
17
18
|
export { createGeometryRendererTask } from './frame-graph/geometry-renderer-task.js';
|
|
18
19
|
export { GeometryTextureType } from './frame-graph/geometry-types.js';
|
|
19
20
|
export { createRenderTarget } from './engine/render-target.js';
|
|
@@ -30,6 +31,7 @@ export { createChromaticAberrationPostProcessTask } from './post-process/chromat
|
|
|
30
31
|
export { createCircleOfConfusionPostProcessTask } from './post-process/circle-of-confusion.js';
|
|
31
32
|
export { createBloomPostProcessTask } from './post-process/bloom.js';
|
|
32
33
|
export { DepthOfFieldBlurLevel, createDepthOfFieldPostProcessTask } from './post-process/depth-of-field.js';
|
|
34
|
+
export { createTaaPostProcessTask } from './post-process/taa.js';
|
|
33
35
|
export { createArcRotateCamera } from './camera/arc-rotate.js';
|
|
34
36
|
export { attachControl, setCameraLimits } from './camera/arc-rotate-controls.js';
|
|
35
37
|
export { createFreeCamera } from './camera/free-camera.js';
|
|
@@ -163,7 +165,9 @@ export { attachBoundingBoxGizmoToNode, createBoundingBoxGizmo, disposeBoundingBo
|
|
|
163
165
|
export { createGridSpriteAtlas, loadSpriteAtlas } from './sprite/shared/sprite-atlas.js';
|
|
164
166
|
export { appendSpriteAtlasFrames, createSpriteAtlasFromFrames } from './sprite/shared/sprite-atlas-packer.js';
|
|
165
167
|
export { spriteBlendAdditive, spriteBlendAlpha, spriteBlendMultiply, spriteBlendPremultiplied } from './sprite/sprite-blend.js';
|
|
166
|
-
export { addSprite2DIndex, clearSprite2DLayer, createSprite2DLayer, removeSprite2DIndex, setSprite2DFrameIndex, setSprite2DShaderParams,
|
|
168
|
+
export { addSprite2DIndex, clearSprite2DLayer, createSprite2DLayer, removeSprite2DIndex, setSprite2DFrameIndex, setSprite2DShaderParams, updateSprite2DIndex } from './sprite/sprite-2d.js';
|
|
169
|
+
export { setSprite2DCoverageGamma } from './sprite/sprite-2d-coverage-gamma.js';
|
|
170
|
+
export { setSprite2DUvOffset } from './sprite/sprite-2d-uvscroll.js';
|
|
167
171
|
export { createSprite2DCustomShader } from './sprite/sprite-custom-shader.js';
|
|
168
172
|
export { addSprite2D, getSprite2DHandleIndex, isSprite2DHandleAlive, removeSprite2D, setSprite2DFrame, updateSprite2D } from './sprite/sprite-2d-handle.js';
|
|
169
173
|
export { addDepthHostedSpriteLayer } from './sprite/sprite-scene.js';
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -10,7 +10,7 @@ function assertIdentifier(kind, name) {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
function isSupportedAttribute(name) {
|
|
13
|
-
return name === "position" || name === "normal" || name === "uv" || name === "uv2" || name === "tangent" || name === "color";
|
|
13
|
+
return name === "position" || name === "normal" || name === "uv" || name === "uv2" || name === "tangent" || name === "color" || name === "joints" || name === "weights" || name === "joints1" || name === "weights1";
|
|
14
14
|
}
|
|
15
15
|
function isSystemUniform(name) {
|
|
16
16
|
return name === "world" || name === "view" || name === "projection" || name === "viewProjection" || name === "worldView" || name === "worldViewProjection" || name === "cameraPosition" || name === "screenSize" || name === "alphaCutoff";
|
|
@@ -38,7 +38,9 @@ function createShaderMaterial(options) {
|
|
|
38
38
|
const seenAttributes = /* @__PURE__ */ new Set();
|
|
39
39
|
for (const attr of options.attributes) {
|
|
40
40
|
if (!isSupportedAttribute(attr)) {
|
|
41
|
-
throw new Error(
|
|
41
|
+
throw new Error(
|
|
42
|
+
`ShaderMaterial: unsupported attribute "${String(attr)}". Supported attributes: position, normal, uv, uv2, tangent, color, joints, weights, joints1, weights1.`
|
|
43
|
+
);
|
|
42
44
|
}
|
|
43
45
|
if (seenAttributes.has(attr)) {
|
|
44
46
|
throw new Error(`ShaderMaterial: duplicate attribute "${attr}".`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shader-material.js","sources":["../../../../src/material/shader/shader-material.ts"],"sourcesContent":["import { F32 } from \"../../engine/typed-arrays.js\";\nimport type { Material, StencilState } from \"../material.js\";\nimport type { Texture2D } from \"../../texture/texture-2d.js\";\nimport type { Mat4 } from \"../../math/types.js\";\nimport { getShaderGroupBuilder } from \"./shader-group-builder.js\";\n\n/** Vertex attribute names a ShaderMaterial can bind. */\nexport type ShaderAttributeName = \"position\" | \"normal\" | \"uv\" | \"uv2\" | \"tangent\" | \"color\";\n/** WGSL scalar/vector/matrix types supported for ShaderMaterial uniforms. */\nexport type ShaderUniformType = \"f32\" | \"u32\" | \"i32\" | \"vec2<f32>\" | \"vec3<f32>\" | \"vec4<f32>\" | \"mat4x4<f32>\";\n/** Built-in uniform names automatically populated by the renderer each frame\n * (transforms, camera position, screen size, alpha cutoff). */\nexport type ShaderSystemUniformName = \"world\" | \"view\" | \"projection\" | \"viewProjection\" | \"worldView\" | \"worldViewProjection\" | \"cameraPosition\" | \"screenSize\" | \"alphaCutoff\";\n/** A uniform entry: either a system uniform name or an explicit custom declaration. */\nexport type ShaderUniformOption = ShaderSystemUniformName | ShaderUniformDecl;\n/** Accepted value shape when setting a ShaderMaterial uniform. */\nexport type ShaderUniformValue = number | readonly number[] | Float32Array;\n/** A sampler entry: either a bare sampler name or an explicit declaration. */\nexport type ShaderSamplerOption = string | ShaderSamplerDecl;\n/** A storage-buffer entry: a read-only WGSL storage binding declaration. */\nexport type ShaderStorageBufferOption = ShaderStorageBufferDecl;\n/** Value of a WGSL preprocessor define — boolean toggle or numeric constant. */\nexport type ShaderDefineValue = boolean | number;\n/** Map of WGSL preprocessor define names to their values. */\nexport type ShaderDefineMap = Readonly<Record<string, ShaderDefineValue>>;\n\n/** Options describing a ShaderMaterial: WGSL sources, attributes, uniforms,\n * samplers, defines, and blend/depth state. Passed to `createShaderMaterial()`. */\nexport interface ShaderMaterialOptions {\n readonly name?: string;\n readonly vertexSource: string;\n readonly fragmentSource: string;\n readonly attributes: readonly ShaderAttributeName[];\n readonly uniforms?: readonly ShaderUniformOption[];\n readonly samplers?: readonly ShaderSamplerOption[];\n readonly storageBuffers?: readonly ShaderStorageBufferOption[];\n readonly defines?: ShaderDefineMap;\n readonly needAlphaBlending?: boolean;\n /** Blend equation used when `needAlphaBlending` is set. \"alpha\" (default) is\n * standard src-over; \"additive\" adds the fragment's premultiplied-by-alpha\n * color to the framebuffer, which is the right choice for glows/light FX. */\n readonly blendMode?: \"alpha\" | \"additive\";\n /** Mark this surface as transmissive/refractive: the renderer grabs the opaque scene color\n * behind it just before it draws, so the fragment can sample what is *through* it (water,\n * glass). Requires `needAlphaBlending` (the surface composites over the grabbed scene\n * color). Enable the scene-color grab on the surface's render task with\n * `enableRenderTaskTransmission`, then bind the resulting texture via `setShaderTexture`.\n * Default false. */\n readonly transmissive?: boolean;\n readonly needAlphaTesting?: boolean;\n readonly backFaceCulling?: boolean;\n readonly depthWrite?: boolean;\n readonly depthCompare?: GPUCompareFunction;\n /** Compile/run the fragment stage even for depth-only render targets (no colour attachments).\n * Use for depth-only casters that need `discard` (alpha/clip masks). The fragment shader must not\n * declare colour outputs when drawn into a depth-only target. Default false. */\n readonly depthOnlyFragment?: boolean;\n /** Constant depth-bias added in the pipeline's depth-stencil state (units of the depth format's minimum\n * representable value). Lets a surface that hugs another (e.g. tiles overlapping a cone, decals) win the\n * depth test consistently and avoid z-fighting. Default 0 (no bias). */\n readonly depthBias?: number;\n /** Slope-scaled depth bias — extra bias proportional to the depth gradient, so steeply-angled (grazing)\n * surfaces get more bias. Pairs with `depthBias` to kill z-fighting at oblique angles. Default 0. */\n readonly depthBiasSlopeScale?: number;\n}\n\n/** A custom uniform declaration: WGSL identifier, type, and optional default. */\nexport interface ShaderUniformDecl {\n readonly name: string;\n readonly type: ShaderUniformType;\n readonly defaultValue?: number | readonly number[];\n}\n\n/** A sampler declaration: WGSL identifier and the bound texture's sample type. */\nexport interface ShaderSamplerDecl {\n readonly name: string;\n readonly sampleType?: \"float\" | \"unfilterable-float\" | \"depth\";\n /** Texture view dimension. Default \"2d\". Use \"2d-array\" for layered maps such as\n * cascaded-shadow (CSM) depth arrays. */\n readonly viewDimension?: \"2d\" | \"2d-array\";\n /** Bind a hardware comparison sampler (`sampler_comparison`) for depth compare / PCF\n * filtering. Implies a depth texture. Default false. */\n readonly comparison?: boolean;\n}\n\n/** A storage buffer declaration. `type` is the WGSL variable type, e.g. `array<vec4<f32>>`. */\nexport interface ShaderStorageBufferDecl {\n readonly name: string;\n readonly type: string;\n}\n\n/** A resolved WGSL preprocessor define (name + value). */\nexport interface ShaderDefine {\n readonly name: string;\n readonly value: ShaderDefineValue;\n}\n\nexport interface ShaderUniformSlot {\n readonly decl: ShaderUniformDecl;\n readonly value: Float32Array;\n}\n\nexport interface ShaderTextureSlot {\n readonly decl: ShaderSamplerDecl;\n current: Texture2D | null;\n}\n\nexport interface ShaderStorageBufferSlot {\n readonly decl: ShaderStorageBufferDecl;\n current: GPUBuffer | null;\n}\n\n/** A custom WGSL material: compiled from user-supplied vertex/fragment sources\n * with declared attributes, uniforms, samplers, and defines. Update its values\n * via `setShaderUniform()` / `setShaderTexture()` and friends. */\nexport interface ShaderMaterial extends Material {\n readonly name?: string;\n readonly vertexSource: string;\n readonly fragmentSource: string;\n readonly attributes: readonly ShaderAttributeName[];\n readonly uniformDecls: readonly ShaderUniformDecl[];\n readonly samplerDecls: readonly ShaderSamplerDecl[];\n readonly storageBufferDecls: readonly ShaderStorageBufferDecl[];\n readonly defines: readonly ShaderDefine[];\n readonly needAlphaBlending: boolean;\n readonly blendMode: \"alpha\" | \"additive\";\n /** True for transmissive/refractive surfaces (see `ShaderMaterialOptions.transmissive`). */\n readonly transmissive: boolean;\n readonly needAlphaTesting: boolean;\n readonly backFaceCulling: boolean;\n readonly depthWrite: boolean;\n readonly depthCompare: GPUCompareFunction;\n readonly depthOnlyFragment: boolean;\n readonly depthBias: number;\n readonly depthBiasSlopeScale: number;\n /** Optional stencil-test state baked into the main-pass pipeline (mask write / discard). Set after\n * creation (`mat.stencil = { ... }`) and call `enableMaterialStencil()` before `registerScene`. Default\n * none. See `StencilState`. */\n stencil?: StencilState;\n /** @internal */\n _uniformValues: Map<string, ShaderUniformSlot>;\n /** @internal */\n _textureSlots: Map<string, ShaderTextureSlot>;\n /** @internal */\n _storageBufferSlots: Map<string, ShaderStorageBufferSlot>;\n /** @internal */\n _uniformVersion: number;\n /** @internal */\n _resourceVersion: number;\n}\n\nfunction isIdentifier(name: string): boolean {\n return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name);\n}\n\nfunction assertIdentifier(kind: string, name: string): void {\n if (!isIdentifier(name)) {\n throw new Error(`ShaderMaterial: ${kind} name \"${name}\" is not a valid WGSL identifier.`);\n }\n}\n\nfunction isSupportedAttribute(name: string): name is ShaderAttributeName {\n return name === \"position\" || name === \"normal\" || name === \"uv\" || name === \"uv2\" || name === \"tangent\" || name === \"color\";\n}\n\nfunction isSystemUniform(name: string): name is ShaderSystemUniformName {\n return (\n name === \"world\" ||\n name === \"view\" ||\n name === \"projection\" ||\n name === \"viewProjection\" ||\n name === \"worldView\" ||\n name === \"worldViewProjection\" ||\n name === \"cameraPosition\" ||\n name === \"screenSize\" ||\n name === \"alphaCutoff\"\n );\n}\n\nfunction systemUniformType(name: ShaderSystemUniformName): ShaderUniformType {\n if (name === \"cameraPosition\") {\n return \"vec3<f32>\";\n }\n if (name === \"screenSize\") {\n return \"vec2<f32>\";\n }\n if (name === \"alphaCutoff\") {\n return \"f32\";\n }\n return \"mat4x4<f32>\";\n}\n\nexport function _isShaderSystemUniform(name: string): name is ShaderSystemUniformName {\n return isSystemUniform(name);\n}\n\n/** Create a ShaderMaterial from WGSL sources and declarations, validating\n * attributes, uniforms, samplers, and defines.\n * @param options - Sources, attributes, uniforms, samplers, defines, and render state.\n * @returns The constructed `ShaderMaterial`. */\nexport function createShaderMaterial(options: ShaderMaterialOptions): ShaderMaterial {\n if (!options.vertexSource || !options.fragmentSource) {\n throw new Error(\"ShaderMaterial: vertexSource and fragmentSource must be non-empty WGSL strings.\");\n }\n const attributes: ShaderAttributeName[] = [];\n const seenAttributes = new Set<string>();\n for (const attr of options.attributes) {\n if (!isSupportedAttribute(attr)) {\n throw new Error(`ShaderMaterial: unsupported attribute \"${String(attr)}\". Supported attributes: position, normal, uv, uv2, tangent, color.`);\n }\n if (seenAttributes.has(attr)) {\n throw new Error(`ShaderMaterial: duplicate attribute \"${attr}\".`);\n }\n seenAttributes.add(attr);\n attributes.push(attr);\n }\n if (!seenAttributes.has(\"position\")) {\n throw new Error('ShaderMaterial: \"position\" attribute is required for mesh rendering.');\n }\n\n const uniformDecls: ShaderUniformDecl[] = [];\n const uniformValues = new Map<string, ShaderUniformSlot>();\n const usedNames = new Set<string>();\n for (const opt of options.uniforms ?? []) {\n const decl = typeof opt === \"string\" ? normalizeSystemUniform(opt) : normalizeCustomUniform(opt);\n assertUniqueName(usedNames, \"uniform\", decl.name);\n uniformDecls.push(decl);\n uniformValues.set(decl.name, { decl, value: normalizeUniformValue(decl, decl.defaultValue ?? defaultUniformValue(decl)) });\n }\n\n const samplerDecls: ShaderSamplerDecl[] = [];\n const textureSlots = new Map<string, ShaderTextureSlot>();\n for (const opt of options.samplers ?? []) {\n const decl: ShaderSamplerDecl =\n typeof opt === \"string\"\n ? { name: opt, sampleType: \"float\" }\n : {\n name: opt.name,\n sampleType: opt.sampleType ?? (opt.comparison ? \"depth\" : \"float\"),\n viewDimension: opt.viewDimension ?? \"2d\",\n comparison: opt.comparison ?? false,\n };\n assertIdentifier(\"sampler\", decl.name);\n assertUniqueName(usedNames, \"sampler\", decl.name);\n assertUniqueName(usedNames, \"sampler\", `${decl.name}Sampler`);\n samplerDecls.push(decl);\n textureSlots.set(decl.name, { decl, current: null });\n }\n\n const storageBufferDecls: ShaderStorageBufferDecl[] = [];\n const storageBufferSlots = new Map<string, ShaderStorageBufferSlot>();\n for (const opt of options.storageBuffers ?? []) {\n assertIdentifier(\"storage buffer\", opt.name);\n assertUniqueName(usedNames, \"storage buffer\", opt.name);\n storageBufferDecls.push(opt);\n storageBufferSlots.set(opt.name, { decl: opt, current: null });\n }\n\n const defines: ShaderDefine[] = [];\n for (const [name, value] of Object.entries(options.defines ?? {})) {\n assertIdentifier(\"define\", name);\n assertUniqueName(usedNames, \"define\", name);\n if (typeof value !== \"boolean\" && typeof value !== \"number\") {\n throw new Error(`ShaderMaterial: define \"${name}\" must be a boolean or number.`);\n }\n defines.push({ name, value });\n }\n defines.sort((a, b) => a.name.localeCompare(b.name));\n\n if (options.transmissive && !(options.needAlphaBlending ?? false)) {\n throw new Error(\"ShaderMaterial: `transmissive` requires `needAlphaBlending` (the surface composites over the grabbed opaque scene color).\");\n }\n\n return {\n name: options.name,\n vertexSource: options.vertexSource,\n fragmentSource: options.fragmentSource,\n attributes,\n uniformDecls,\n samplerDecls,\n storageBufferDecls,\n defines,\n needAlphaBlending: options.needAlphaBlending ?? false,\n blendMode: options.blendMode ?? \"alpha\",\n transmissive: options.transmissive ?? false,\n needAlphaTesting: options.needAlphaTesting ?? false,\n backFaceCulling: options.backFaceCulling ?? true,\n depthWrite: options.depthWrite ?? true,\n depthCompare: options.depthCompare ?? \"greater-equal\",\n depthOnlyFragment: options.depthOnlyFragment ?? false,\n depthBias: options.depthBias ?? 0,\n depthBiasSlopeScale: options.depthBiasSlopeScale ?? 0,\n _buildGroup: getShaderGroupBuilder(),\n _uboVersion: 0,\n _uniformValues: uniformValues,\n _textureSlots: textureSlots,\n _storageBufferSlots: storageBufferSlots,\n _uniformVersion: 0,\n _resourceVersion: 0,\n };\n}\n\nfunction normalizeSystemUniform(name: string): ShaderUniformDecl {\n if (!isSystemUniform(name)) {\n throw new Error(`ShaderMaterial: custom uniform \"${name}\" must use an explicit typed declaration.`);\n }\n return { name, type: systemUniformType(name) };\n}\n\nfunction normalizeCustomUniform(decl: ShaderUniformDecl): ShaderUniformDecl {\n assertIdentifier(\"uniform\", decl.name);\n if (!isUniformType(decl.type)) {\n throw new Error(`ShaderMaterial: unsupported uniform type \"${String(decl.type)}\" for \"${decl.name}\".`);\n }\n return decl;\n}\n\nfunction isUniformType(type: string): type is ShaderUniformType {\n return type === \"f32\" || type === \"u32\" || type === \"i32\" || type === \"vec2<f32>\" || type === \"vec3<f32>\" || type === \"vec4<f32>\" || type === \"mat4x4<f32>\";\n}\n\nfunction assertUniqueName(usedNames: Set<string>, kind: string, name: string): void {\n if (usedNames.has(name)) {\n throw new Error(`ShaderMaterial: duplicate generated identifier \"${name}\" while adding ${kind}.`);\n }\n usedNames.add(name);\n}\n\nfunction elementCount(type: ShaderUniformType): number {\n switch (type) {\n case \"f32\":\n case \"u32\":\n case \"i32\":\n return 1;\n case \"vec2<f32>\":\n return 2;\n case \"vec3<f32>\":\n return 3;\n case \"vec4<f32>\":\n return 4;\n case \"mat4x4<f32>\":\n return 16;\n }\n}\n\nfunction defaultUniformValue(decl: ShaderUniformDecl): ShaderUniformValue {\n if (decl.name === \"alphaCutoff\") {\n return 0.4;\n }\n const count = elementCount(decl.type);\n return count === 1 ? 0 : new Array(count).fill(0);\n}\n\nfunction normalizeUniformValue(decl: ShaderUniformDecl, value: ShaderUniformValue): Float32Array {\n const count = elementCount(decl.type);\n const arr = typeof value === \"number\" ? new F32([value]) : value instanceof F32 ? new F32(value) : new F32(value);\n if (arr.length !== count) {\n throw new Error(`ShaderMaterial: uniform \"${decl.name}\" of type ${decl.type} expects ${count} value(s), got ${arr.length}.`);\n }\n return arr;\n}\n\n/** Set a declared uniform's value, validating its element count against the\n * declared type and bumping the material's UBO version.\n * @param material - Target material.\n * @param name - Declared uniform name.\n * @param value - New value (scalar, array, or `Float32Array`). */\nexport function setShaderUniform(material: ShaderMaterial, name: string, value: ShaderUniformValue): void {\n const slot = material._uniformValues.get(name);\n if (!slot) {\n throw new Error(`ShaderMaterial: uniform \"${name}\" was not declared.`);\n }\n slot.value.set(normalizeUniformValue(slot.decl, value));\n material._uniformVersion++;\n material._uboVersion = material._uniformVersion;\n}\n\n/** Bind (or clear) the texture for a declared sampler, enforcing that depth and\n * non-depth samplers receive a matching `Texture2D`.\n * @param material - Target material.\n * @param name - Declared sampler name.\n * @param texture - Texture to bind, or `null` to clear. */\nexport function setShaderTexture(material: ShaderMaterial, name: string, texture: Texture2D | null): void {\n const slot = material._textureSlots.get(name);\n if (!slot) {\n throw new Error(`ShaderMaterial: sampler \"${name}\" was not declared.`);\n }\n if (texture) {\n const expectsDepth = slot.decl.comparison || slot.decl.sampleType === \"depth\";\n const isDepthTexture = texture._sampleType === \"depth\";\n if (expectsDepth && !isDepthTexture) {\n throw new Error(`ShaderMaterial: sampler \"${name}\" expects a depth Texture2D.`);\n }\n if (!expectsDepth && isDepthTexture) {\n throw new Error(`ShaderMaterial: sampler \"${name}\" cannot use a depth Texture2D.`);\n }\n }\n // Only invalidate the cached bind groups when the bound texture HANDLE actually changes. The bind group\n // references the texture's view + sampler (see createShaderBindGroup), so re-binding the SAME Texture2D (the\n // common \"keep my shadow map / scene-depth bound every frame\" pattern) leaves those identical. Bumping the\n // resource version unconditionally therefore forced a BRAND-NEW bind group every frame (per material, for every\n // packet using it), churning the D3D12 descriptor heap until it OOMed on content-heavy scenes (e.g. reloading\n // a big save). A texture's CONTENTS can change freely without a new bind group (the bound view is live), so\n // identity comparison is correct.\n if (slot.current !== texture) {\n slot.current = texture;\n material._resourceVersion++;\n }\n}\n\n/** Bind (or clear) a declared read-only storage buffer. */\nexport function setShaderStorageBuffer(material: ShaderMaterial, name: string, buffer: GPUBuffer | null): void {\n const slot = material._storageBufferSlots.get(name);\n if (!slot) {\n throw new Error(`ShaderMaterial: storage buffer \"${name}\" was not declared.`);\n }\n // See setShaderTexture: only invalidate the bind groups when the bound buffer HANDLE changes; re-binding the\n // same GPUBuffer is a no-op (contents update live), so an unconditional bump churned the descriptor heap.\n if (slot.current !== buffer) {\n slot.current = buffer;\n material._resourceVersion++;\n }\n}\n\n/** Set a declared `f32` uniform. Convenience wrapper over `setShaderUniform()`. */\nexport function setShaderFloat(material: ShaderMaterial, name: string, value: number): void {\n setShaderUniform(material, name, value);\n}\n\n/** Set a declared `vec3<f32>` uniform. Convenience wrapper over `setShaderUniform()`. */\nexport function setShaderVector3(material: ShaderMaterial, name: string, value: readonly [number, number, number]): void {\n setShaderUniform(material, name, value);\n}\n\n/** Set a declared `mat4x4<f32>` uniform. Convenience wrapper over `setShaderUniform()`.\n * Accepts a raw `Float32Array` or the engine's branded `Mat4` (e.g. the result of\n * `getViewProjectionMatrix()` / `mat4Invert()`), so camera/math matrices can be fed\n * straight into a matrix uniform without laundering through a typed array. */\nexport function setShaderMatrix(material: ShaderMaterial, name: string, value: Float32Array | Mat4): void {\n setShaderUniform(material, name, value instanceof Float32Array ? value : Array.from(value));\n}\n"],"names":[],"mappings":";;;AAuJA,SAAS,aAAa,IAAA,EAAuB;AACzC,EAAA,OAAO,0BAAA,CAA2B,KAAK,IAAI,CAAA;AAC/C;AAEA,SAAS,gBAAA,CAAiB,MAAc,IAAA,EAAoB;AACxD,EAAA,IAAI,CAAC,YAAA,CAAa,IAAI,CAAA,EAAG;AACrB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gBAAA,EAAmB,IAAI,CAAA,OAAA,EAAU,IAAI,CAAA,iCAAA,CAAmC,CAAA;AAAA,EAC5F;AACJ;AAEA,SAAS,qBAAqB,IAAA,EAA2C;AACrE,EAAA,OAAO,IAAA,KAAS,UAAA,IAAc,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,QAAQ,IAAA,KAAS,KAAA,IAAS,IAAA,KAAS,SAAA,IAAa,IAAA,KAAS,OAAA;AACzH;AAEA,SAAS,gBAAgB,IAAA,EAA+C;AACpE,EAAA,OACI,SAAS,OAAA,IACT,IAAA,KAAS,MAAA,IACT,IAAA,KAAS,gBACT,IAAA,KAAS,gBAAA,IACT,IAAA,KAAS,WAAA,IACT,SAAS,qBAAA,IACT,IAAA,KAAS,gBAAA,IACT,IAAA,KAAS,gBACT,IAAA,KAAS,aAAA;AAEjB;AAEA,SAAS,kBAAkB,IAAA,EAAkD;AACzE,EAAA,IAAI,SAAS,gBAAA,EAAkB;AAC3B,IAAA,OAAO,WAAA;AAAA,EACX;AACA,EAAA,IAAI,SAAS,YAAA,EAAc;AACvB,IAAA,OAAO,WAAA;AAAA,EACX;AACA,EAAA,IAAI,SAAS,aAAA,EAAe;AACxB,IAAA,OAAO,KAAA;AAAA,EACX;AACA,EAAA,OAAO,aAAA;AACX;AAEO,SAAS,uBAAuB,IAAA,EAA+C;AAClF,EAAA,OAAO,gBAAgB,IAAI,CAAA;AAC/B;AAMO,SAAS,qBAAqB,OAAA,EAAgD;AACjF,EAAA,IAAI,CAAC,OAAA,CAAQ,YAAA,IAAgB,CAAC,QAAQ,cAAA,EAAgB;AAClD,IAAA,MAAM,IAAI,MAAM,iFAAiF,CAAA;AAAA,EACrG;AACA,EAAA,MAAM,aAAoC,EAAC;AAC3C,EAAA,MAAM,cAAA,uBAAqB,GAAA,EAAY;AACvC,EAAA,KAAA,MAAW,IAAA,IAAQ,QAAQ,UAAA,EAAY;AACnC,IAAA,IAAI,CAAC,oBAAA,CAAqB,IAAI,CAAA,EAAG;AAC7B,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uCAAA,EAA0C,MAAA,CAAO,IAAI,CAAC,CAAA,mEAAA,CAAqE,CAAA;AAAA,IAC/I;AACA,IAAA,IAAI,cAAA,CAAe,GAAA,CAAI,IAAI,CAAA,EAAG;AAC1B,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qCAAA,EAAwC,IAAI,CAAA,EAAA,CAAI,CAAA;AAAA,IACpE;AACA,IAAA,cAAA,CAAe,IAAI,IAAI,CAAA;AACvB,IAAA,UAAA,CAAW,KAAK,IAAI,CAAA;AAAA,EACxB;AACA,EAAA,IAAI,CAAC,cAAA,CAAe,GAAA,CAAI,UAAU,CAAA,EAAG;AACjC,IAAA,MAAM,IAAI,MAAM,sEAAsE,CAAA;AAAA,EAC1F;AAEA,EAAA,MAAM,eAAoC,EAAC;AAC3C,EAAA,MAAM,aAAA,uBAAoB,GAAA,EAA+B;AACzD,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAY;AAClC,EAAA,KAAA,MAAW,GAAA,IAAO,OAAA,CAAQ,QAAA,IAAY,EAAC,EAAG;AACtC,IAAA,MAAM,IAAA,GAAO,OAAO,GAAA,KAAQ,QAAA,GAAW,uBAAuB,GAAG,CAAA,GAAI,uBAAuB,GAAG,CAAA;AAC/F,IAAA,gBAAA,CAAiB,SAAA,EAAW,SAAA,EAAW,IAAA,CAAK,IAAI,CAAA;AAChD,IAAA,YAAA,CAAa,KAAK,IAAI,CAAA;AACtB,IAAA,aAAA,CAAc,GAAA,CAAI,IAAA,CAAK,IAAA,EAAM,EAAE,MAAM,KAAA,EAAO,qBAAA,CAAsB,IAAA,EAAM,IAAA,CAAK,YAAA,IAAgB,mBAAA,CAAoB,IAAI,CAAC,GAAG,CAAA;AAAA,EAC7H;AAEA,EAAA,MAAM,eAAoC,EAAC;AAC3C,EAAA,MAAM,YAAA,uBAAmB,GAAA,EAA+B;AACxD,EAAA,KAAA,MAAW,GAAA,IAAO,OAAA,CAAQ,QAAA,IAAY,EAAC,EAAG;AACtC,IAAA,MAAM,IAAA,GACF,OAAO,GAAA,KAAQ,QAAA,GACT,EAAE,IAAA,EAAM,GAAA,EAAK,UAAA,EAAY,OAAA,EAAQ,GACjC;AAAA,MACI,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,UAAA,EAAY,GAAA,CAAI,UAAA,KAAe,GAAA,CAAI,aAAa,OAAA,GAAU,OAAA,CAAA;AAAA,MAC1D,aAAA,EAAe,IAAI,aAAA,IAAiB,IAAA;AAAA,MACpC,UAAA,EAAY,IAAI,UAAA,IAAc;AAAA,KAClC;AACV,IAAA,gBAAA,CAAiB,SAAA,EAAW,KAAK,IAAI,CAAA;AACrC,IAAA,gBAAA,CAAiB,SAAA,EAAW,SAAA,EAAW,IAAA,CAAK,IAAI,CAAA;AAChD,IAAA,gBAAA,CAAiB,SAAA,EAAW,SAAA,EAAW,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,OAAA,CAAS,CAAA;AAC5D,IAAA,YAAA,CAAa,KAAK,IAAI,CAAA;AACtB,IAAA,YAAA,CAAa,IAAI,IAAA,CAAK,IAAA,EAAM,EAAE,IAAA,EAAM,OAAA,EAAS,MAAM,CAAA;AAAA,EACvD;AAEA,EAAA,MAAM,qBAAgD,EAAC;AACvD,EAAA,MAAM,kBAAA,uBAAyB,GAAA,EAAqC;AACpE,EAAA,KAAA,MAAW,GAAA,IAAO,OAAA,CAAQ,cAAA,IAAkB,EAAC,EAAG;AAC5C,IAAA,gBAAA,CAAiB,gBAAA,EAAkB,IAAI,IAAI,CAAA;AAC3C,IAAA,gBAAA,CAAiB,SAAA,EAAW,gBAAA,EAAkB,GAAA,CAAI,IAAI,CAAA;AACtD,IAAA,kBAAA,CAAmB,KAAK,GAAG,CAAA;AAC3B,IAAA,kBAAA,CAAmB,GAAA,CAAI,IAAI,IAAA,EAAM,EAAE,MAAM,GAAA,EAAK,OAAA,EAAS,MAAM,CAAA;AAAA,EACjE;AAEA,EAAA,MAAM,UAA0B,EAAC;AACjC,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,CAAA,IAAK,MAAA,CAAO,QAAQ,OAAA,CAAQ,OAAA,IAAW,EAAE,CAAA,EAAG;AAC/D,IAAA,gBAAA,CAAiB,UAAU,IAAI,CAAA;AAC/B,IAAA,gBAAA,CAAiB,SAAA,EAAW,UAAU,IAAI,CAAA;AAC1C,IAAA,IAAI,OAAO,KAAA,KAAU,SAAA,IAAa,OAAO,UAAU,QAAA,EAAU;AACzD,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,IAAI,CAAA,8BAAA,CAAgC,CAAA;AAAA,IACnF;AACA,IAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,IAAA,EAAM,KAAA,EAAO,CAAA;AAAA,EAChC;AACA,EAAA,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,IAAA,CAAK,aAAA,CAAc,CAAA,CAAE,IAAI,CAAC,CAAA;AAEnD,EAAA,IAAI,OAAA,CAAQ,YAAA,IAAgB,EAAE,OAAA,CAAQ,qBAAqB,KAAA,CAAA,EAAQ;AAC/D,IAAA,MAAM,IAAI,MAAM,2HAA2H,CAAA;AAAA,EAC/I;AAEA,EAAA,OAAO;AAAA,IACH,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,cAAc,OAAA,CAAQ,YAAA;AAAA,IACtB,gBAAgB,OAAA,CAAQ,cAAA;AAAA,IACxB,UAAA;AAAA,IACA,YAAA;AAAA,IACA,YAAA;AAAA,IACA,kBAAA;AAAA,IACA,OAAA;AAAA,IACA,iBAAA,EAAmB,QAAQ,iBAAA,IAAqB,KAAA;AAAA,IAChD,SAAA,EAAW,QAAQ,SAAA,IAAa,OAAA;AAAA,IAChC,YAAA,EAAc,QAAQ,YAAA,IAAgB,KAAA;AAAA,IACtC,gBAAA,EAAkB,QAAQ,gBAAA,IAAoB,KAAA;AAAA,IAC9C,eAAA,EAAiB,QAAQ,eAAA,IAAmB,IAAA;AAAA,IAC5C,UAAA,EAAY,QAAQ,UAAA,IAAc,IAAA;AAAA,IAClC,YAAA,EAAc,QAAQ,YAAA,IAAgB,eAAA;AAAA,IACtC,iBAAA,EAAmB,QAAQ,iBAAA,IAAqB,KAAA;AAAA,IAChD,SAAA,EAAW,QAAQ,SAAA,IAAa,CAAA;AAAA,IAChC,mBAAA,EAAqB,QAAQ,mBAAA,IAAuB,CAAA;AAAA,IACpD,aAAa,qBAAA,EAAsB;AAAA,IACnC,WAAA,EAAa,CAAA;AAAA,IACb,cAAA,EAAgB,aAAA;AAAA,IAChB,aAAA,EAAe,YAAA;AAAA,IACf,mBAAA,EAAqB,kBAAA;AAAA,IACrB,eAAA,EAAiB,CAAA;AAAA,IACjB,gBAAA,EAAkB;AAAA,GACtB;AACJ;AAEA,SAAS,uBAAuB,IAAA,EAAiC;AAC7D,EAAA,IAAI,CAAC,eAAA,CAAgB,IAAI,CAAA,EAAG;AACxB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gCAAA,EAAmC,IAAI,CAAA,yCAAA,CAA2C,CAAA;AAAA,EACtG;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,iBAAA,CAAkB,IAAI,CAAA,EAAE;AACjD;AAEA,SAAS,uBAAuB,IAAA,EAA4C;AACxE,EAAA,gBAAA,CAAiB,SAAA,EAAW,KAAK,IAAI,CAAA;AACrC,EAAA,IAAI,CAAC,aAAA,CAAc,IAAA,CAAK,IAAI,CAAA,EAAG;AAC3B,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0CAAA,EAA6C,MAAA,CAAO,IAAA,CAAK,IAAI,CAAC,CAAA,OAAA,EAAU,IAAA,CAAK,IAAI,CAAA,EAAA,CAAI,CAAA;AAAA,EACzG;AACA,EAAA,OAAO,IAAA;AACX;AAEA,SAAS,cAAc,IAAA,EAAyC;AAC5D,EAAA,OAAO,IAAA,KAAS,KAAA,IAAS,IAAA,KAAS,KAAA,IAAS,IAAA,KAAS,KAAA,IAAS,IAAA,KAAS,WAAA,IAAe,IAAA,KAAS,WAAA,IAAe,IAAA,KAAS,WAAA,IAAe,IAAA,KAAS,aAAA;AAClJ;AAEA,SAAS,gBAAA,CAAiB,SAAA,EAAwB,IAAA,EAAc,IAAA,EAAoB;AAChF,EAAA,IAAI,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA,EAAG;AACrB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gDAAA,EAAmD,IAAI,CAAA,eAAA,EAAkB,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,EACpG;AACA,EAAA,SAAA,CAAU,IAAI,IAAI,CAAA;AACtB;AAEA,SAAS,aAAa,IAAA,EAAiC;AACnD,EAAA,QAAQ,IAAA;AAAM,IACV,KAAK,KAAA;AAAA,IACL,KAAK,KAAA;AAAA,IACL,KAAK,KAAA;AACD,MAAA,OAAO,CAAA;AAAA,IACX,KAAK,WAAA;AACD,MAAA,OAAO,CAAA;AAAA,IACX,KAAK,WAAA;AACD,MAAA,OAAO,CAAA;AAAA,IACX,KAAK,WAAA;AACD,MAAA,OAAO,CAAA;AAAA,IACX,KAAK,aAAA;AACD,MAAA,OAAO,EAAA;AAAA;AAEnB;AAEA,SAAS,oBAAoB,IAAA,EAA6C;AACtE,EAAA,IAAI,IAAA,CAAK,SAAS,aAAA,EAAe;AAC7B,IAAA,OAAO,GAAA;AAAA,EACX;AACA,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,IAAA,CAAK,IAAI,CAAA;AACpC,EAAA,OAAO,KAAA,KAAU,IAAI,CAAA,GAAI,IAAI,MAAM,KAAK,CAAA,CAAE,KAAK,CAAC,CAAA;AACpD;AAEA,SAAS,qBAAA,CAAsB,MAAyB,KAAA,EAAyC;AAC7F,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,IAAA,CAAK,IAAI,CAAA;AACpC,EAAA,MAAM,MAAM,OAAO,KAAA,KAAU,WAAW,IAAI,GAAA,CAAI,CAAC,KAAK,CAAC,CAAA,GAAI,KAAA,YAAiB,MAAM,IAAI,GAAA,CAAI,KAAK,CAAA,GAAI,IAAI,IAAI,KAAK,CAAA;AAChH,EAAA,IAAI,GAAA,CAAI,WAAW,KAAA,EAAO;AACtB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,IAAA,CAAK,IAAI,CAAA,UAAA,EAAa,IAAA,CAAK,IAAI,CAAA,SAAA,EAAY,KAAK,CAAA,eAAA,EAAkB,GAAA,CAAI,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,EAC/H;AACA,EAAA,OAAO,GAAA;AACX;AAOO,SAAS,gBAAA,CAAiB,QAAA,EAA0B,IAAA,EAAc,KAAA,EAAiC;AACtG,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,cAAA,CAAe,GAAA,CAAI,IAAI,CAAA;AAC7C,EAAA,IAAI,CAAC,IAAA,EAAM;AACP,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,IAAI,CAAA,mBAAA,CAAqB,CAAA;AAAA,EACzE;AACA,EAAA,IAAA,CAAK,MAAM,GAAA,CAAI,qBAAA,CAAsB,IAAA,CAAK,IAAA,EAAM,KAAK,CAAC,CAAA;AACtD,EAAA,QAAA,CAAS,eAAA,EAAA;AACT,EAAA,QAAA,CAAS,cAAc,QAAA,CAAS,eAAA;AACpC;AAOO,SAAS,gBAAA,CAAiB,QAAA,EAA0B,IAAA,EAAc,OAAA,EAAiC;AACtG,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,aAAA,CAAc,GAAA,CAAI,IAAI,CAAA;AAC5C,EAAA,IAAI,CAAC,IAAA,EAAM;AACP,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,IAAI,CAAA,mBAAA,CAAqB,CAAA;AAAA,EACzE;AACA,EAAA,IAAI,OAAA,EAAS;AACT,IAAA,MAAM,eAAe,IAAA,CAAK,IAAA,CAAK,UAAA,IAAc,IAAA,CAAK,KAAK,UAAA,KAAe,OAAA;AACtE,IAAA,MAAM,cAAA,GAAiB,QAAQ,WAAA,KAAgB,OAAA;AAC/C,IAAA,IAAI,YAAA,IAAgB,CAAC,cAAA,EAAgB;AACjC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,IAAI,CAAA,4BAAA,CAA8B,CAAA;AAAA,IAClF;AACA,IAAA,IAAI,CAAC,gBAAgB,cAAA,EAAgB;AACjC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,IAAI,CAAA,+BAAA,CAAiC,CAAA;AAAA,IACrF;AAAA,EACJ;AAQA,EAAA,IAAI,IAAA,CAAK,YAAY,OAAA,EAAS;AAC1B,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,QAAA,CAAS,gBAAA,EAAA;AAAA,EACb;AACJ;AAGO,SAAS,sBAAA,CAAuB,QAAA,EAA0B,IAAA,EAAc,MAAA,EAAgC;AAC3G,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,mBAAA,CAAoB,GAAA,CAAI,IAAI,CAAA;AAClD,EAAA,IAAI,CAAC,IAAA,EAAM;AACP,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gCAAA,EAAmC,IAAI,CAAA,mBAAA,CAAqB,CAAA;AAAA,EAChF;AAGA,EAAA,IAAI,IAAA,CAAK,YAAY,MAAA,EAAQ;AACzB,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AACf,IAAA,QAAA,CAAS,gBAAA,EAAA;AAAA,EACb;AACJ;AAGO,SAAS,cAAA,CAAe,QAAA,EAA0B,IAAA,EAAc,KAAA,EAAqB;AACxF,EAAA,gBAAA,CAAiB,QAAA,EAAU,MAAM,KAAK,CAAA;AAC1C;AAGO,SAAS,gBAAA,CAAiB,QAAA,EAA0B,IAAA,EAAc,KAAA,EAAgD;AACrH,EAAA,gBAAA,CAAiB,QAAA,EAAU,MAAM,KAAK,CAAA;AAC1C;AAMO,SAAS,eAAA,CAAgB,QAAA,EAA0B,IAAA,EAAc,KAAA,EAAkC;AACtG,EAAA,gBAAA,CAAiB,QAAA,EAAU,MAAM,KAAA,YAAiB,YAAA,GAAe,QAAQ,KAAA,CAAM,IAAA,CAAK,KAAK,CAAC,CAAA;AAC9F;;;;"}
|
|
1
|
+
{"version":3,"file":"shader-material.js","sources":["../../../../src/material/shader/shader-material.ts"],"sourcesContent":["import { F32 } from \"../../engine/typed-arrays.js\";\nimport type { Material, StencilState } from \"../material.js\";\nimport type { Texture2D } from \"../../texture/texture-2d.js\";\nimport type { Mat4 } from \"../../math/types.js\";\nimport { getShaderGroupBuilder } from \"./shader-group-builder.js\";\n\n/** Vertex attribute names a ShaderMaterial can bind. `joints`/`weights` (and `joints1`/`weights1`\n * for \\>4 bones/vertex) are the skinning attributes — bound from the mesh's skeleton/VAT buffers,\n * letting a custom material do vertex skinning (e.g. baked vertex-animation). */\nexport type ShaderAttributeName = \"position\" | \"normal\" | \"uv\" | \"uv2\" | \"tangent\" | \"color\" | \"joints\" | \"weights\" | \"joints1\" | \"weights1\";\n/** WGSL scalar/vector/matrix types supported for ShaderMaterial uniforms. */\nexport type ShaderUniformType = \"f32\" | \"u32\" | \"i32\" | \"vec2<f32>\" | \"vec3<f32>\" | \"vec4<f32>\" | \"mat4x4<f32>\";\n/** Built-in uniform names automatically populated by the renderer each frame\n * (transforms, camera position, screen size, alpha cutoff). */\nexport type ShaderSystemUniformName = \"world\" | \"view\" | \"projection\" | \"viewProjection\" | \"worldView\" | \"worldViewProjection\" | \"cameraPosition\" | \"screenSize\" | \"alphaCutoff\";\n/** A uniform entry: either a system uniform name or an explicit custom declaration. */\nexport type ShaderUniformOption = ShaderSystemUniformName | ShaderUniformDecl;\n/** Accepted value shape when setting a ShaderMaterial uniform. */\nexport type ShaderUniformValue = number | readonly number[] | Float32Array;\n/** A sampler entry: either a bare sampler name or an explicit declaration. */\nexport type ShaderSamplerOption = string | ShaderSamplerDecl;\n/** A storage-buffer entry: a read-only WGSL storage binding declaration. */\nexport type ShaderStorageBufferOption = ShaderStorageBufferDecl;\n/** Value of a WGSL preprocessor define — boolean toggle or numeric constant. */\nexport type ShaderDefineValue = boolean | number;\n/** Map of WGSL preprocessor define names to their values. */\nexport type ShaderDefineMap = Readonly<Record<string, ShaderDefineValue>>;\n\n/** Options describing a ShaderMaterial: WGSL sources, attributes, uniforms,\n * samplers, defines, and blend/depth state. Passed to `createShaderMaterial()`. */\nexport interface ShaderMaterialOptions {\n readonly name?: string;\n readonly vertexSource: string;\n readonly fragmentSource: string;\n readonly attributes: readonly ShaderAttributeName[];\n readonly uniforms?: readonly ShaderUniformOption[];\n readonly samplers?: readonly ShaderSamplerOption[];\n readonly storageBuffers?: readonly ShaderStorageBufferOption[];\n readonly defines?: ShaderDefineMap;\n readonly needAlphaBlending?: boolean;\n /** Blend equation used when `needAlphaBlending` is set. \"alpha\" (default) is\n * standard src-over; \"additive\" adds the fragment's premultiplied-by-alpha\n * color to the framebuffer, which is the right choice for glows/light FX. */\n readonly blendMode?: \"alpha\" | \"additive\";\n /** Mark this surface as transmissive/refractive: the renderer grabs the opaque scene color\n * behind it just before it draws, so the fragment can sample what is *through* it (water,\n * glass). Requires `needAlphaBlending` (the surface composites over the grabbed scene\n * color). Enable the scene-color grab on the surface's render task with\n * `enableRenderTaskTransmission`, then bind the resulting texture via `setShaderTexture`.\n * Default false. */\n readonly transmissive?: boolean;\n readonly needAlphaTesting?: boolean;\n readonly backFaceCulling?: boolean;\n readonly depthWrite?: boolean;\n readonly depthCompare?: GPUCompareFunction;\n /** Compile/run the fragment stage even for depth-only render targets (no colour attachments).\n * Use for depth-only casters that need `discard` (alpha/clip masks). The fragment shader must not\n * declare colour outputs when drawn into a depth-only target. Default false. */\n readonly depthOnlyFragment?: boolean;\n /** Constant depth-bias added in the pipeline's depth-stencil state (units of the depth format's minimum\n * representable value). Lets a surface that hugs another (e.g. tiles overlapping a cone, decals) win the\n * depth test consistently and avoid z-fighting. Default 0 (no bias). */\n readonly depthBias?: number;\n /** Slope-scaled depth bias — extra bias proportional to the depth gradient, so steeply-angled (grazing)\n * surfaces get more bias. Pairs with `depthBias` to kill z-fighting at oblique angles. Default 0. */\n readonly depthBiasSlopeScale?: number;\n}\n\n/** A custom uniform declaration: WGSL identifier, type, and optional default. */\nexport interface ShaderUniformDecl {\n readonly name: string;\n readonly type: ShaderUniformType;\n readonly defaultValue?: number | readonly number[];\n}\n\n/** A sampler declaration: WGSL identifier and the bound texture's sample type. */\nexport interface ShaderSamplerDecl {\n readonly name: string;\n readonly sampleType?: \"float\" | \"unfilterable-float\" | \"depth\";\n /** Texture view dimension. Default \"2d\". Use \"2d-array\" for layered maps such as\n * cascaded-shadow (CSM) depth arrays. */\n readonly viewDimension?: \"2d\" | \"2d-array\";\n /** Bind a hardware comparison sampler (`sampler_comparison`) for depth compare / PCF\n * filtering. Implies a depth texture. Default false. */\n readonly comparison?: boolean;\n}\n\n/** A storage buffer declaration. `type` is the WGSL variable type, e.g. `array<vec4<f32>>`. */\nexport interface ShaderStorageBufferDecl {\n readonly name: string;\n readonly type: string;\n}\n\n/** A resolved WGSL preprocessor define (name + value). */\nexport interface ShaderDefine {\n readonly name: string;\n readonly value: ShaderDefineValue;\n}\n\nexport interface ShaderUniformSlot {\n readonly decl: ShaderUniformDecl;\n readonly value: Float32Array;\n}\n\nexport interface ShaderTextureSlot {\n readonly decl: ShaderSamplerDecl;\n current: Texture2D | null;\n}\n\nexport interface ShaderStorageBufferSlot {\n readonly decl: ShaderStorageBufferDecl;\n current: GPUBuffer | null;\n}\n\n/** A custom WGSL material: compiled from user-supplied vertex/fragment sources\n * with declared attributes, uniforms, samplers, and defines. Update its values\n * via `setShaderUniform()` / `setShaderTexture()` and friends. */\nexport interface ShaderMaterial extends Material {\n readonly name?: string;\n readonly vertexSource: string;\n readonly fragmentSource: string;\n readonly attributes: readonly ShaderAttributeName[];\n readonly uniformDecls: readonly ShaderUniformDecl[];\n readonly samplerDecls: readonly ShaderSamplerDecl[];\n readonly storageBufferDecls: readonly ShaderStorageBufferDecl[];\n readonly defines: readonly ShaderDefine[];\n readonly needAlphaBlending: boolean;\n readonly blendMode: \"alpha\" | \"additive\";\n /** True for transmissive/refractive surfaces (see `ShaderMaterialOptions.transmissive`). */\n readonly transmissive: boolean;\n readonly needAlphaTesting: boolean;\n readonly backFaceCulling: boolean;\n readonly depthWrite: boolean;\n readonly depthCompare: GPUCompareFunction;\n readonly depthOnlyFragment: boolean;\n readonly depthBias: number;\n readonly depthBiasSlopeScale: number;\n /** Optional stencil-test state baked into the main-pass pipeline (mask write / discard). Set after\n * creation (`mat.stencil = { ... }`) and call `enableMaterialStencil()` before `registerScene`. Default\n * none. See `StencilState`. */\n stencil?: StencilState;\n /** @internal */\n _uniformValues: Map<string, ShaderUniformSlot>;\n /** @internal */\n _textureSlots: Map<string, ShaderTextureSlot>;\n /** @internal */\n _storageBufferSlots: Map<string, ShaderStorageBufferSlot>;\n /** @internal */\n _uniformVersion: number;\n /** @internal */\n _resourceVersion: number;\n}\n\nfunction isIdentifier(name: string): boolean {\n return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name);\n}\n\nfunction assertIdentifier(kind: string, name: string): void {\n if (!isIdentifier(name)) {\n throw new Error(`ShaderMaterial: ${kind} name \"${name}\" is not a valid WGSL identifier.`);\n }\n}\n\nfunction isSupportedAttribute(name: string): name is ShaderAttributeName {\n return (\n name === \"position\" ||\n name === \"normal\" ||\n name === \"uv\" ||\n name === \"uv2\" ||\n name === \"tangent\" ||\n name === \"color\" ||\n name === \"joints\" ||\n name === \"weights\" ||\n name === \"joints1\" ||\n name === \"weights1\"\n );\n}\n\nfunction isSystemUniform(name: string): name is ShaderSystemUniformName {\n return (\n name === \"world\" ||\n name === \"view\" ||\n name === \"projection\" ||\n name === \"viewProjection\" ||\n name === \"worldView\" ||\n name === \"worldViewProjection\" ||\n name === \"cameraPosition\" ||\n name === \"screenSize\" ||\n name === \"alphaCutoff\"\n );\n}\n\nfunction systemUniformType(name: ShaderSystemUniformName): ShaderUniformType {\n if (name === \"cameraPosition\") {\n return \"vec3<f32>\";\n }\n if (name === \"screenSize\") {\n return \"vec2<f32>\";\n }\n if (name === \"alphaCutoff\") {\n return \"f32\";\n }\n return \"mat4x4<f32>\";\n}\n\nexport function _isShaderSystemUniform(name: string): name is ShaderSystemUniformName {\n return isSystemUniform(name);\n}\n\n/** Create a ShaderMaterial from WGSL sources and declarations, validating\n * attributes, uniforms, samplers, and defines.\n * @param options - Sources, attributes, uniforms, samplers, defines, and render state.\n * @returns The constructed `ShaderMaterial`. */\nexport function createShaderMaterial(options: ShaderMaterialOptions): ShaderMaterial {\n if (!options.vertexSource || !options.fragmentSource) {\n throw new Error(\"ShaderMaterial: vertexSource and fragmentSource must be non-empty WGSL strings.\");\n }\n const attributes: ShaderAttributeName[] = [];\n const seenAttributes = new Set<string>();\n for (const attr of options.attributes) {\n if (!isSupportedAttribute(attr)) {\n throw new Error(\n `ShaderMaterial: unsupported attribute \"${String(attr)}\". Supported attributes: position, normal, uv, uv2, tangent, color, joints, weights, joints1, weights1.`\n );\n }\n if (seenAttributes.has(attr)) {\n throw new Error(`ShaderMaterial: duplicate attribute \"${attr}\".`);\n }\n seenAttributes.add(attr);\n attributes.push(attr);\n }\n if (!seenAttributes.has(\"position\")) {\n throw new Error('ShaderMaterial: \"position\" attribute is required for mesh rendering.');\n }\n\n const uniformDecls: ShaderUniformDecl[] = [];\n const uniformValues = new Map<string, ShaderUniformSlot>();\n const usedNames = new Set<string>();\n for (const opt of options.uniforms ?? []) {\n const decl = typeof opt === \"string\" ? normalizeSystemUniform(opt) : normalizeCustomUniform(opt);\n assertUniqueName(usedNames, \"uniform\", decl.name);\n uniformDecls.push(decl);\n uniformValues.set(decl.name, { decl, value: normalizeUniformValue(decl, decl.defaultValue ?? defaultUniformValue(decl)) });\n }\n\n const samplerDecls: ShaderSamplerDecl[] = [];\n const textureSlots = new Map<string, ShaderTextureSlot>();\n for (const opt of options.samplers ?? []) {\n const decl: ShaderSamplerDecl =\n typeof opt === \"string\"\n ? { name: opt, sampleType: \"float\" }\n : {\n name: opt.name,\n sampleType: opt.sampleType ?? (opt.comparison ? \"depth\" : \"float\"),\n viewDimension: opt.viewDimension ?? \"2d\",\n comparison: opt.comparison ?? false,\n };\n assertIdentifier(\"sampler\", decl.name);\n assertUniqueName(usedNames, \"sampler\", decl.name);\n assertUniqueName(usedNames, \"sampler\", `${decl.name}Sampler`);\n samplerDecls.push(decl);\n textureSlots.set(decl.name, { decl, current: null });\n }\n\n const storageBufferDecls: ShaderStorageBufferDecl[] = [];\n const storageBufferSlots = new Map<string, ShaderStorageBufferSlot>();\n for (const opt of options.storageBuffers ?? []) {\n assertIdentifier(\"storage buffer\", opt.name);\n assertUniqueName(usedNames, \"storage buffer\", opt.name);\n storageBufferDecls.push(opt);\n storageBufferSlots.set(opt.name, { decl: opt, current: null });\n }\n\n const defines: ShaderDefine[] = [];\n for (const [name, value] of Object.entries(options.defines ?? {})) {\n assertIdentifier(\"define\", name);\n assertUniqueName(usedNames, \"define\", name);\n if (typeof value !== \"boolean\" && typeof value !== \"number\") {\n throw new Error(`ShaderMaterial: define \"${name}\" must be a boolean or number.`);\n }\n defines.push({ name, value });\n }\n defines.sort((a, b) => a.name.localeCompare(b.name));\n\n if (options.transmissive && !(options.needAlphaBlending ?? false)) {\n throw new Error(\"ShaderMaterial: `transmissive` requires `needAlphaBlending` (the surface composites over the grabbed opaque scene color).\");\n }\n\n return {\n name: options.name,\n vertexSource: options.vertexSource,\n fragmentSource: options.fragmentSource,\n attributes,\n uniformDecls,\n samplerDecls,\n storageBufferDecls,\n defines,\n needAlphaBlending: options.needAlphaBlending ?? false,\n blendMode: options.blendMode ?? \"alpha\",\n transmissive: options.transmissive ?? false,\n needAlphaTesting: options.needAlphaTesting ?? false,\n backFaceCulling: options.backFaceCulling ?? true,\n depthWrite: options.depthWrite ?? true,\n depthCompare: options.depthCompare ?? \"greater-equal\",\n depthOnlyFragment: options.depthOnlyFragment ?? false,\n depthBias: options.depthBias ?? 0,\n depthBiasSlopeScale: options.depthBiasSlopeScale ?? 0,\n _buildGroup: getShaderGroupBuilder(),\n _uboVersion: 0,\n _uniformValues: uniformValues,\n _textureSlots: textureSlots,\n _storageBufferSlots: storageBufferSlots,\n _uniformVersion: 0,\n _resourceVersion: 0,\n };\n}\n\nfunction normalizeSystemUniform(name: string): ShaderUniformDecl {\n if (!isSystemUniform(name)) {\n throw new Error(`ShaderMaterial: custom uniform \"${name}\" must use an explicit typed declaration.`);\n }\n return { name, type: systemUniformType(name) };\n}\n\nfunction normalizeCustomUniform(decl: ShaderUniformDecl): ShaderUniformDecl {\n assertIdentifier(\"uniform\", decl.name);\n if (!isUniformType(decl.type)) {\n throw new Error(`ShaderMaterial: unsupported uniform type \"${String(decl.type)}\" for \"${decl.name}\".`);\n }\n return decl;\n}\n\nfunction isUniformType(type: string): type is ShaderUniformType {\n return type === \"f32\" || type === \"u32\" || type === \"i32\" || type === \"vec2<f32>\" || type === \"vec3<f32>\" || type === \"vec4<f32>\" || type === \"mat4x4<f32>\";\n}\n\nfunction assertUniqueName(usedNames: Set<string>, kind: string, name: string): void {\n if (usedNames.has(name)) {\n throw new Error(`ShaderMaterial: duplicate generated identifier \"${name}\" while adding ${kind}.`);\n }\n usedNames.add(name);\n}\n\nfunction elementCount(type: ShaderUniformType): number {\n switch (type) {\n case \"f32\":\n case \"u32\":\n case \"i32\":\n return 1;\n case \"vec2<f32>\":\n return 2;\n case \"vec3<f32>\":\n return 3;\n case \"vec4<f32>\":\n return 4;\n case \"mat4x4<f32>\":\n return 16;\n }\n}\n\nfunction defaultUniformValue(decl: ShaderUniformDecl): ShaderUniformValue {\n if (decl.name === \"alphaCutoff\") {\n return 0.4;\n }\n const count = elementCount(decl.type);\n return count === 1 ? 0 : new Array(count).fill(0);\n}\n\nfunction normalizeUniformValue(decl: ShaderUniformDecl, value: ShaderUniformValue): Float32Array {\n const count = elementCount(decl.type);\n const arr = typeof value === \"number\" ? new F32([value]) : value instanceof F32 ? new F32(value) : new F32(value);\n if (arr.length !== count) {\n throw new Error(`ShaderMaterial: uniform \"${decl.name}\" of type ${decl.type} expects ${count} value(s), got ${arr.length}.`);\n }\n return arr;\n}\n\n/** Set a declared uniform's value, validating its element count against the\n * declared type and bumping the material's UBO version.\n * @param material - Target material.\n * @param name - Declared uniform name.\n * @param value - New value (scalar, array, or `Float32Array`). */\nexport function setShaderUniform(material: ShaderMaterial, name: string, value: ShaderUniformValue): void {\n const slot = material._uniformValues.get(name);\n if (!slot) {\n throw new Error(`ShaderMaterial: uniform \"${name}\" was not declared.`);\n }\n slot.value.set(normalizeUniformValue(slot.decl, value));\n material._uniformVersion++;\n material._uboVersion = material._uniformVersion;\n}\n\n/** Bind (or clear) the texture for a declared sampler, enforcing that depth and\n * non-depth samplers receive a matching `Texture2D`.\n * @param material - Target material.\n * @param name - Declared sampler name.\n * @param texture - Texture to bind, or `null` to clear. */\nexport function setShaderTexture(material: ShaderMaterial, name: string, texture: Texture2D | null): void {\n const slot = material._textureSlots.get(name);\n if (!slot) {\n throw new Error(`ShaderMaterial: sampler \"${name}\" was not declared.`);\n }\n if (texture) {\n const expectsDepth = slot.decl.comparison || slot.decl.sampleType === \"depth\";\n const isDepthTexture = texture._sampleType === \"depth\";\n if (expectsDepth && !isDepthTexture) {\n throw new Error(`ShaderMaterial: sampler \"${name}\" expects a depth Texture2D.`);\n }\n if (!expectsDepth && isDepthTexture) {\n throw new Error(`ShaderMaterial: sampler \"${name}\" cannot use a depth Texture2D.`);\n }\n }\n // Only invalidate the cached bind groups when the bound texture HANDLE actually changes. The bind group\n // references the texture's view + sampler (see createShaderBindGroup), so re-binding the SAME Texture2D (the\n // common \"keep my shadow map / scene-depth bound every frame\" pattern) leaves those identical. Bumping the\n // resource version unconditionally therefore forced a BRAND-NEW bind group every frame (per material, for every\n // packet using it), churning the D3D12 descriptor heap until it OOMed on content-heavy scenes (e.g. reloading\n // a big save). A texture's CONTENTS can change freely without a new bind group (the bound view is live), so\n // identity comparison is correct.\n if (slot.current !== texture) {\n slot.current = texture;\n material._resourceVersion++;\n }\n}\n\n/** Bind (or clear) a declared read-only storage buffer. */\nexport function setShaderStorageBuffer(material: ShaderMaterial, name: string, buffer: GPUBuffer | null): void {\n const slot = material._storageBufferSlots.get(name);\n if (!slot) {\n throw new Error(`ShaderMaterial: storage buffer \"${name}\" was not declared.`);\n }\n // See setShaderTexture: only invalidate the bind groups when the bound buffer HANDLE changes; re-binding the\n // same GPUBuffer is a no-op (contents update live), so an unconditional bump churned the descriptor heap.\n if (slot.current !== buffer) {\n slot.current = buffer;\n material._resourceVersion++;\n }\n}\n\n/** Set a declared `f32` uniform. Convenience wrapper over `setShaderUniform()`. */\nexport function setShaderFloat(material: ShaderMaterial, name: string, value: number): void {\n setShaderUniform(material, name, value);\n}\n\n/** Set a declared `vec3<f32>` uniform. Convenience wrapper over `setShaderUniform()`. */\nexport function setShaderVector3(material: ShaderMaterial, name: string, value: readonly [number, number, number]): void {\n setShaderUniform(material, name, value);\n}\n\n/** Set a declared `mat4x4<f32>` uniform. Convenience wrapper over `setShaderUniform()`.\n * Accepts a raw `Float32Array` or the engine's branded `Mat4` (e.g. the result of\n * `getViewProjectionMatrix()` / `mat4Invert()`), so camera/math matrices can be fed\n * straight into a matrix uniform without laundering through a typed array. */\nexport function setShaderMatrix(material: ShaderMaterial, name: string, value: Float32Array | Mat4): void {\n setShaderUniform(material, name, value instanceof Float32Array ? value : Array.from(value));\n}\n"],"names":[],"mappings":";;;AAyJA,SAAS,aAAa,IAAA,EAAuB;AACzC,EAAA,OAAO,0BAAA,CAA2B,KAAK,IAAI,CAAA;AAC/C;AAEA,SAAS,gBAAA,CAAiB,MAAc,IAAA,EAAoB;AACxD,EAAA,IAAI,CAAC,YAAA,CAAa,IAAI,CAAA,EAAG;AACrB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gBAAA,EAAmB,IAAI,CAAA,OAAA,EAAU,IAAI,CAAA,iCAAA,CAAmC,CAAA;AAAA,EAC5F;AACJ;AAEA,SAAS,qBAAqB,IAAA,EAA2C;AACrE,EAAA,OACI,SAAS,UAAA,IACT,IAAA,KAAS,YACT,IAAA,KAAS,IAAA,IACT,SAAS,KAAA,IACT,IAAA,KAAS,SAAA,IACT,IAAA,KAAS,WACT,IAAA,KAAS,QAAA,IACT,SAAS,SAAA,IACT,IAAA,KAAS,aACT,IAAA,KAAS,UAAA;AAEjB;AAEA,SAAS,gBAAgB,IAAA,EAA+C;AACpE,EAAA,OACI,SAAS,OAAA,IACT,IAAA,KAAS,MAAA,IACT,IAAA,KAAS,gBACT,IAAA,KAAS,gBAAA,IACT,IAAA,KAAS,WAAA,IACT,SAAS,qBAAA,IACT,IAAA,KAAS,gBAAA,IACT,IAAA,KAAS,gBACT,IAAA,KAAS,aAAA;AAEjB;AAEA,SAAS,kBAAkB,IAAA,EAAkD;AACzE,EAAA,IAAI,SAAS,gBAAA,EAAkB;AAC3B,IAAA,OAAO,WAAA;AAAA,EACX;AACA,EAAA,IAAI,SAAS,YAAA,EAAc;AACvB,IAAA,OAAO,WAAA;AAAA,EACX;AACA,EAAA,IAAI,SAAS,aAAA,EAAe;AACxB,IAAA,OAAO,KAAA;AAAA,EACX;AACA,EAAA,OAAO,aAAA;AACX;AAEO,SAAS,uBAAuB,IAAA,EAA+C;AAClF,EAAA,OAAO,gBAAgB,IAAI,CAAA;AAC/B;AAMO,SAAS,qBAAqB,OAAA,EAAgD;AACjF,EAAA,IAAI,CAAC,OAAA,CAAQ,YAAA,IAAgB,CAAC,QAAQ,cAAA,EAAgB;AAClD,IAAA,MAAM,IAAI,MAAM,iFAAiF,CAAA;AAAA,EACrG;AACA,EAAA,MAAM,aAAoC,EAAC;AAC3C,EAAA,MAAM,cAAA,uBAAqB,GAAA,EAAY;AACvC,EAAA,KAAA,MAAW,IAAA,IAAQ,QAAQ,UAAA,EAAY;AACnC,IAAA,IAAI,CAAC,oBAAA,CAAqB,IAAI,CAAA,EAAG;AAC7B,MAAA,MAAM,IAAI,KAAA;AAAA,QACN,CAAA,uCAAA,EAA0C,MAAA,CAAO,IAAI,CAAC,CAAA,uGAAA;AAAA,OAC1D;AAAA,IACJ;AACA,IAAA,IAAI,cAAA,CAAe,GAAA,CAAI,IAAI,CAAA,EAAG;AAC1B,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qCAAA,EAAwC,IAAI,CAAA,EAAA,CAAI,CAAA;AAAA,IACpE;AACA,IAAA,cAAA,CAAe,IAAI,IAAI,CAAA;AACvB,IAAA,UAAA,CAAW,KAAK,IAAI,CAAA;AAAA,EACxB;AACA,EAAA,IAAI,CAAC,cAAA,CAAe,GAAA,CAAI,UAAU,CAAA,EAAG;AACjC,IAAA,MAAM,IAAI,MAAM,sEAAsE,CAAA;AAAA,EAC1F;AAEA,EAAA,MAAM,eAAoC,EAAC;AAC3C,EAAA,MAAM,aAAA,uBAAoB,GAAA,EAA+B;AACzD,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAY;AAClC,EAAA,KAAA,MAAW,GAAA,IAAO,OAAA,CAAQ,QAAA,IAAY,EAAC,EAAG;AACtC,IAAA,MAAM,IAAA,GAAO,OAAO,GAAA,KAAQ,QAAA,GAAW,uBAAuB,GAAG,CAAA,GAAI,uBAAuB,GAAG,CAAA;AAC/F,IAAA,gBAAA,CAAiB,SAAA,EAAW,SAAA,EAAW,IAAA,CAAK,IAAI,CAAA;AAChD,IAAA,YAAA,CAAa,KAAK,IAAI,CAAA;AACtB,IAAA,aAAA,CAAc,GAAA,CAAI,IAAA,CAAK,IAAA,EAAM,EAAE,MAAM,KAAA,EAAO,qBAAA,CAAsB,IAAA,EAAM,IAAA,CAAK,YAAA,IAAgB,mBAAA,CAAoB,IAAI,CAAC,GAAG,CAAA;AAAA,EAC7H;AAEA,EAAA,MAAM,eAAoC,EAAC;AAC3C,EAAA,MAAM,YAAA,uBAAmB,GAAA,EAA+B;AACxD,EAAA,KAAA,MAAW,GAAA,IAAO,OAAA,CAAQ,QAAA,IAAY,EAAC,EAAG;AACtC,IAAA,MAAM,IAAA,GACF,OAAO,GAAA,KAAQ,QAAA,GACT,EAAE,IAAA,EAAM,GAAA,EAAK,UAAA,EAAY,OAAA,EAAQ,GACjC;AAAA,MACI,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,UAAA,EAAY,GAAA,CAAI,UAAA,KAAe,GAAA,CAAI,aAAa,OAAA,GAAU,OAAA,CAAA;AAAA,MAC1D,aAAA,EAAe,IAAI,aAAA,IAAiB,IAAA;AAAA,MACpC,UAAA,EAAY,IAAI,UAAA,IAAc;AAAA,KAClC;AACV,IAAA,gBAAA,CAAiB,SAAA,EAAW,KAAK,IAAI,CAAA;AACrC,IAAA,gBAAA,CAAiB,SAAA,EAAW,SAAA,EAAW,IAAA,CAAK,IAAI,CAAA;AAChD,IAAA,gBAAA,CAAiB,SAAA,EAAW,SAAA,EAAW,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,OAAA,CAAS,CAAA;AAC5D,IAAA,YAAA,CAAa,KAAK,IAAI,CAAA;AACtB,IAAA,YAAA,CAAa,IAAI,IAAA,CAAK,IAAA,EAAM,EAAE,IAAA,EAAM,OAAA,EAAS,MAAM,CAAA;AAAA,EACvD;AAEA,EAAA,MAAM,qBAAgD,EAAC;AACvD,EAAA,MAAM,kBAAA,uBAAyB,GAAA,EAAqC;AACpE,EAAA,KAAA,MAAW,GAAA,IAAO,OAAA,CAAQ,cAAA,IAAkB,EAAC,EAAG;AAC5C,IAAA,gBAAA,CAAiB,gBAAA,EAAkB,IAAI,IAAI,CAAA;AAC3C,IAAA,gBAAA,CAAiB,SAAA,EAAW,gBAAA,EAAkB,GAAA,CAAI,IAAI,CAAA;AACtD,IAAA,kBAAA,CAAmB,KAAK,GAAG,CAAA;AAC3B,IAAA,kBAAA,CAAmB,GAAA,CAAI,IAAI,IAAA,EAAM,EAAE,MAAM,GAAA,EAAK,OAAA,EAAS,MAAM,CAAA;AAAA,EACjE;AAEA,EAAA,MAAM,UAA0B,EAAC;AACjC,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,CAAA,IAAK,MAAA,CAAO,QAAQ,OAAA,CAAQ,OAAA,IAAW,EAAE,CAAA,EAAG;AAC/D,IAAA,gBAAA,CAAiB,UAAU,IAAI,CAAA;AAC/B,IAAA,gBAAA,CAAiB,SAAA,EAAW,UAAU,IAAI,CAAA;AAC1C,IAAA,IAAI,OAAO,KAAA,KAAU,SAAA,IAAa,OAAO,UAAU,QAAA,EAAU;AACzD,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,IAAI,CAAA,8BAAA,CAAgC,CAAA;AAAA,IACnF;AACA,IAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,IAAA,EAAM,KAAA,EAAO,CAAA;AAAA,EAChC;AACA,EAAA,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,IAAA,CAAK,aAAA,CAAc,CAAA,CAAE,IAAI,CAAC,CAAA;AAEnD,EAAA,IAAI,OAAA,CAAQ,YAAA,IAAgB,EAAE,OAAA,CAAQ,qBAAqB,KAAA,CAAA,EAAQ;AAC/D,IAAA,MAAM,IAAI,MAAM,2HAA2H,CAAA;AAAA,EAC/I;AAEA,EAAA,OAAO;AAAA,IACH,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,cAAc,OAAA,CAAQ,YAAA;AAAA,IACtB,gBAAgB,OAAA,CAAQ,cAAA;AAAA,IACxB,UAAA;AAAA,IACA,YAAA;AAAA,IACA,YAAA;AAAA,IACA,kBAAA;AAAA,IACA,OAAA;AAAA,IACA,iBAAA,EAAmB,QAAQ,iBAAA,IAAqB,KAAA;AAAA,IAChD,SAAA,EAAW,QAAQ,SAAA,IAAa,OAAA;AAAA,IAChC,YAAA,EAAc,QAAQ,YAAA,IAAgB,KAAA;AAAA,IACtC,gBAAA,EAAkB,QAAQ,gBAAA,IAAoB,KAAA;AAAA,IAC9C,eAAA,EAAiB,QAAQ,eAAA,IAAmB,IAAA;AAAA,IAC5C,UAAA,EAAY,QAAQ,UAAA,IAAc,IAAA;AAAA,IAClC,YAAA,EAAc,QAAQ,YAAA,IAAgB,eAAA;AAAA,IACtC,iBAAA,EAAmB,QAAQ,iBAAA,IAAqB,KAAA;AAAA,IAChD,SAAA,EAAW,QAAQ,SAAA,IAAa,CAAA;AAAA,IAChC,mBAAA,EAAqB,QAAQ,mBAAA,IAAuB,CAAA;AAAA,IACpD,aAAa,qBAAA,EAAsB;AAAA,IACnC,WAAA,EAAa,CAAA;AAAA,IACb,cAAA,EAAgB,aAAA;AAAA,IAChB,aAAA,EAAe,YAAA;AAAA,IACf,mBAAA,EAAqB,kBAAA;AAAA,IACrB,eAAA,EAAiB,CAAA;AAAA,IACjB,gBAAA,EAAkB;AAAA,GACtB;AACJ;AAEA,SAAS,uBAAuB,IAAA,EAAiC;AAC7D,EAAA,IAAI,CAAC,eAAA,CAAgB,IAAI,CAAA,EAAG;AACxB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gCAAA,EAAmC,IAAI,CAAA,yCAAA,CAA2C,CAAA;AAAA,EACtG;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,iBAAA,CAAkB,IAAI,CAAA,EAAE;AACjD;AAEA,SAAS,uBAAuB,IAAA,EAA4C;AACxE,EAAA,gBAAA,CAAiB,SAAA,EAAW,KAAK,IAAI,CAAA;AACrC,EAAA,IAAI,CAAC,aAAA,CAAc,IAAA,CAAK,IAAI,CAAA,EAAG;AAC3B,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0CAAA,EAA6C,MAAA,CAAO,IAAA,CAAK,IAAI,CAAC,CAAA,OAAA,EAAU,IAAA,CAAK,IAAI,CAAA,EAAA,CAAI,CAAA;AAAA,EACzG;AACA,EAAA,OAAO,IAAA;AACX;AAEA,SAAS,cAAc,IAAA,EAAyC;AAC5D,EAAA,OAAO,IAAA,KAAS,KAAA,IAAS,IAAA,KAAS,KAAA,IAAS,IAAA,KAAS,KAAA,IAAS,IAAA,KAAS,WAAA,IAAe,IAAA,KAAS,WAAA,IAAe,IAAA,KAAS,WAAA,IAAe,IAAA,KAAS,aAAA;AAClJ;AAEA,SAAS,gBAAA,CAAiB,SAAA,EAAwB,IAAA,EAAc,IAAA,EAAoB;AAChF,EAAA,IAAI,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA,EAAG;AACrB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gDAAA,EAAmD,IAAI,CAAA,eAAA,EAAkB,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,EACpG;AACA,EAAA,SAAA,CAAU,IAAI,IAAI,CAAA;AACtB;AAEA,SAAS,aAAa,IAAA,EAAiC;AACnD,EAAA,QAAQ,IAAA;AAAM,IACV,KAAK,KAAA;AAAA,IACL,KAAK,KAAA;AAAA,IACL,KAAK,KAAA;AACD,MAAA,OAAO,CAAA;AAAA,IACX,KAAK,WAAA;AACD,MAAA,OAAO,CAAA;AAAA,IACX,KAAK,WAAA;AACD,MAAA,OAAO,CAAA;AAAA,IACX,KAAK,WAAA;AACD,MAAA,OAAO,CAAA;AAAA,IACX,KAAK,aAAA;AACD,MAAA,OAAO,EAAA;AAAA;AAEnB;AAEA,SAAS,oBAAoB,IAAA,EAA6C;AACtE,EAAA,IAAI,IAAA,CAAK,SAAS,aAAA,EAAe;AAC7B,IAAA,OAAO,GAAA;AAAA,EACX;AACA,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,IAAA,CAAK,IAAI,CAAA;AACpC,EAAA,OAAO,KAAA,KAAU,IAAI,CAAA,GAAI,IAAI,MAAM,KAAK,CAAA,CAAE,KAAK,CAAC,CAAA;AACpD;AAEA,SAAS,qBAAA,CAAsB,MAAyB,KAAA,EAAyC;AAC7F,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,IAAA,CAAK,IAAI,CAAA;AACpC,EAAA,MAAM,MAAM,OAAO,KAAA,KAAU,WAAW,IAAI,GAAA,CAAI,CAAC,KAAK,CAAC,CAAA,GAAI,KAAA,YAAiB,MAAM,IAAI,GAAA,CAAI,KAAK,CAAA,GAAI,IAAI,IAAI,KAAK,CAAA;AAChH,EAAA,IAAI,GAAA,CAAI,WAAW,KAAA,EAAO;AACtB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,IAAA,CAAK,IAAI,CAAA,UAAA,EAAa,IAAA,CAAK,IAAI,CAAA,SAAA,EAAY,KAAK,CAAA,eAAA,EAAkB,GAAA,CAAI,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,EAC/H;AACA,EAAA,OAAO,GAAA;AACX;AAOO,SAAS,gBAAA,CAAiB,QAAA,EAA0B,IAAA,EAAc,KAAA,EAAiC;AACtG,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,cAAA,CAAe,GAAA,CAAI,IAAI,CAAA;AAC7C,EAAA,IAAI,CAAC,IAAA,EAAM;AACP,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,IAAI,CAAA,mBAAA,CAAqB,CAAA;AAAA,EACzE;AACA,EAAA,IAAA,CAAK,MAAM,GAAA,CAAI,qBAAA,CAAsB,IAAA,CAAK,IAAA,EAAM,KAAK,CAAC,CAAA;AACtD,EAAA,QAAA,CAAS,eAAA,EAAA;AACT,EAAA,QAAA,CAAS,cAAc,QAAA,CAAS,eAAA;AACpC;AAOO,SAAS,gBAAA,CAAiB,QAAA,EAA0B,IAAA,EAAc,OAAA,EAAiC;AACtG,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,aAAA,CAAc,GAAA,CAAI,IAAI,CAAA;AAC5C,EAAA,IAAI,CAAC,IAAA,EAAM;AACP,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,IAAI,CAAA,mBAAA,CAAqB,CAAA;AAAA,EACzE;AACA,EAAA,IAAI,OAAA,EAAS;AACT,IAAA,MAAM,eAAe,IAAA,CAAK,IAAA,CAAK,UAAA,IAAc,IAAA,CAAK,KAAK,UAAA,KAAe,OAAA;AACtE,IAAA,MAAM,cAAA,GAAiB,QAAQ,WAAA,KAAgB,OAAA;AAC/C,IAAA,IAAI,YAAA,IAAgB,CAAC,cAAA,EAAgB;AACjC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,IAAI,CAAA,4BAAA,CAA8B,CAAA;AAAA,IAClF;AACA,IAAA,IAAI,CAAC,gBAAgB,cAAA,EAAgB;AACjC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,IAAI,CAAA,+BAAA,CAAiC,CAAA;AAAA,IACrF;AAAA,EACJ;AAQA,EAAA,IAAI,IAAA,CAAK,YAAY,OAAA,EAAS;AAC1B,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,QAAA,CAAS,gBAAA,EAAA;AAAA,EACb;AACJ;AAGO,SAAS,sBAAA,CAAuB,QAAA,EAA0B,IAAA,EAAc,MAAA,EAAgC;AAC3G,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,mBAAA,CAAoB,GAAA,CAAI,IAAI,CAAA;AAClD,EAAA,IAAI,CAAC,IAAA,EAAM;AACP,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gCAAA,EAAmC,IAAI,CAAA,mBAAA,CAAqB,CAAA;AAAA,EAChF;AAGA,EAAA,IAAI,IAAA,CAAK,YAAY,MAAA,EAAQ;AACzB,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AACf,IAAA,QAAA,CAAS,gBAAA,EAAA;AAAA,EACb;AACJ;AAGO,SAAS,cAAA,CAAe,QAAA,EAA0B,IAAA,EAAc,KAAA,EAAqB;AACxF,EAAA,gBAAA,CAAiB,QAAA,EAAU,MAAM,KAAK,CAAA;AAC1C;AAGO,SAAS,gBAAA,CAAiB,QAAA,EAA0B,IAAA,EAAc,KAAA,EAAgD;AACrH,EAAA,gBAAA,CAAiB,QAAA,EAAU,MAAM,KAAK,CAAA;AAC1C;AAMO,SAAS,eAAA,CAAgB,QAAA,EAA0B,IAAA,EAAc,KAAA,EAAkC;AACtG,EAAA,gBAAA,CAAiB,QAAA,EAAU,MAAM,KAAA,YAAiB,YAAA,GAAe,QAAQ,KAAA,CAAM,IAAA,CAAK,KAAK,CAAC,CAAA;AAC9F;;;;"}
|
|
@@ -138,7 +138,12 @@ function attributeLayout(name, shaderLocation) {
|
|
|
138
138
|
return { arrayStride: 8, attributes: [{ shaderLocation, offset: 0, format: "float32x2" }] };
|
|
139
139
|
case "tangent":
|
|
140
140
|
case "color":
|
|
141
|
+
case "weights":
|
|
142
|
+
case "weights1":
|
|
141
143
|
return { arrayStride: 16, attributes: [{ shaderLocation, offset: 0, format: "float32x4" }] };
|
|
144
|
+
case "joints":
|
|
145
|
+
case "joints1":
|
|
146
|
+
return { arrayStride: 16, attributes: [{ shaderLocation, offset: 0, format: "uint32x4" }] };
|
|
142
147
|
}
|
|
143
148
|
}
|
|
144
149
|
function buildShaderPrelude(material, systemSpec, customSpec, instanceAttrs = "") {
|
|
@@ -204,7 +209,12 @@ function attributeWgslType(name) {
|
|
|
204
209
|
return "vec2<f32>";
|
|
205
210
|
case "tangent":
|
|
206
211
|
case "color":
|
|
212
|
+
case "weights":
|
|
213
|
+
case "weights1":
|
|
207
214
|
return "vec4<f32>";
|
|
215
|
+
case "joints":
|
|
216
|
+
case "joints1":
|
|
217
|
+
return "vec4<u32>";
|
|
208
218
|
}
|
|
209
219
|
}
|
|
210
220
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shader-pipeline.js","sources":["../../../../src/material/shader/shader-pipeline.ts"],"sourcesContent":["import { SS } from \"../../engine/gpu-flags.js\";\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport type { RenderTargetSignature } from \"../../engine/render-target.js\";\nimport { targetSignatureKey } from \"../../engine/render-target.js\";\nimport { getSceneBindGroupLayout } from \"../../render/scene-helpers.js\";\nimport { SCENE_UBO_WGSL } from \"../../shader/scene-uniforms.js\";\nimport { computeUboLayout } from \"../../shader/ubo-layout.js\";\nimport type { UboField, UboSpec } from \"../../shader/fragment-types.js\";\nimport type { ShaderAttributeName, ShaderMaterial, ShaderSamplerDecl, ShaderUniformDecl } from \"./shader-material.js\";\nimport { _isShaderSystemUniform } from \"./shader-material.js\";\nimport type { ResolvedStencil } from \"../stencil-state.js\";\nimport type { StencilState } from \"../material.js\";\n\n/** Stencil resolver, installed only by `enableMaterialStencil`. Module-local with a single exported setter:\n * when `enableMaterialStencil` is absent from the bundle the setter tree-shakes, the bundler proves this is\n * always null, and every stencil branch below folds away — stencil-free Shader scenes stay byte-identical. */\nlet _stencilResolver: ((stencil: StencilState) => ResolvedStencil) | null = null;\n/** @internal Install the stencil resolver into the Shader pipeline (called by `enableMaterialStencil`). */\nexport function _installShaderStencilResolver(resolve: (stencil: StencilState) => ResolvedStencil): void {\n _stencilResolver = resolve;\n}\n\nexport interface ShaderPipelineBindings {\n readonly group1BGL: GPUBindGroupLayout;\n readonly systemSpec: UboSpec;\n readonly customSpec: UboSpec | null;\n readonly vertexBuffers: readonly GPUVertexBufferLayout[];\n readonly pipelines: Map<string, GPURenderPipeline>;\n}\n\ninterface ShaderMaterialPipelineState extends ShaderMaterial {\n _shaderDevice?: GPUDevice;\n _shaderBindings?: ShaderPipelineBindings;\n _shaderCustomUbo?: GPUBuffer | null;\n _shaderCustomSpec?: UboSpec | null;\n _shaderCustomData?: ArrayBuffer | null;\n _shaderCustomVersion?: number;\n}\n\nconst SHADER_STAGE_ALL = SS.VERTEX | SS.FRAGMENT;\n\nexport function getOrCreateShaderPipelineBindings(engine: EngineContext, material: ShaderMaterial): ShaderPipelineBindings {\n const state = material as ShaderMaterialPipelineState;\n if (state._shaderBindings && state._shaderDevice === engine._device) {\n return state._shaderBindings;\n }\n\n state._shaderDevice = engine._device;\n const systemFields = material.uniformDecls.filter((u) => _isShaderSystemUniform(u.name)).map(toUboField);\n const customFields = material.uniformDecls.filter((u) => !_isShaderSystemUniform(u.name)).map(toUboField);\n const systemSpec = computeUboLayout(systemFields.length > 0 ? systemFields : [{ _name: \"_pad\", _type: \"vec4<f32>\" }]);\n const customSpec = customFields.length > 0 ? computeUboLayout(customFields) : null;\n const group1BGL = engine._device.createBindGroupLayout({\n label: \"shader-material-group1\",\n entries: buildBindGroupLayoutEntries(material.samplerDecls, material.storageBufferDecls, customSpec !== null),\n });\n const bindings: ShaderPipelineBindings = {\n group1BGL,\n systemSpec,\n customSpec,\n vertexBuffers: material.attributes.map(attributeLayout),\n pipelines: new Map(),\n };\n state._shaderBindings = bindings;\n state._shaderCustomSpec = customSpec;\n state._shaderCustomUbo = null;\n state._shaderCustomData = null;\n state._shaderCustomVersion = -1;\n return bindings;\n}\n\nexport function getOrCreateShaderPipeline(\n engine: EngineContext,\n sig: RenderTargetSignature,\n material: ShaderMaterial,\n bindings: ShaderPipelineBindings,\n variantKey = \"\",\n vertexBuffers: readonly GPUVertexBufferLayout[] = bindings.vertexBuffers,\n instanceAttrs = \"\"\n): GPURenderPipeline {\n // `variantKey`, `vertexBuffers` and `instanceAttrs` default to the\n // non-instanced pipeline — byte-for-byte identical behaviour to before\n // instancing existed. The dynamically-imported thin-instance module is the\n // only caller that passes non-default values, so no instancing logic runs\n // for non-instanced scenes.\n const key = `${targetSignatureKey(sig)}${variantKey}`;\n const cached = bindings.pipelines.get(key);\n if (cached) {\n return cached;\n }\n const stencil = material.stencil && _stencilResolver ? _stencilResolver(material.stencil) : null;\n const device = engine._device;\n const prelude = buildShaderPrelude(material, bindings.systemSpec, bindings.customSpec, instanceAttrs);\n const vertModule = device.createShaderModule({ label: `${material.name ?? \"shader\"}-vertex`, code: `${prelude}\\n${material.vertexSource}` });\n const wantsFragment = !!sig._colorFormat || material.depthOnlyFragment;\n const fragModule = wantsFragment ? device.createShaderModule({ label: `${material.name ?? \"shader\"}-fragment`, code: `${prelude}\\n${material.fragmentSource}` }) : null;\n const colorTarget: GPUColorTargetState | null = sig._colorFormat\n ? {\n format: sig._colorFormat,\n ...(material.needAlphaBlending\n ? {\n blend:\n material.blendMode === \"additive\"\n ? ({\n color: { srcFactor: \"src-alpha\", dstFactor: \"one\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one\", operation: \"add\" },\n } satisfies GPUBlendState)\n : ({\n color: { srcFactor: \"src-alpha\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n } satisfies GPUBlendState),\n }\n : {}),\n }\n : null;\n\n const pipeline = device.createRenderPipeline({\n label: `${material.name ?? \"shader\"}-pipeline`,\n layout: device.createPipelineLayout({ bindGroupLayouts: [getSceneBindGroupLayout(engine), bindings.group1BGL] }),\n vertex: { module: vertModule, entryPoint: \"mainVertex\", buffers: vertexBuffers as GPUVertexBufferLayout[] },\n ...(fragModule ? { fragment: { module: fragModule, entryPoint: \"mainFragment\", targets: colorTarget ? [colorTarget] : [] } } : {}),\n ...(sig._depthStencilFormat\n ? {\n depthStencil: {\n format: sig._depthStencilFormat,\n // The target's declared depth convention wins over the material default: a depth-only\n // caster authored for the forward-Z shadow map (\"less-equal\") must still depth-test\n // correctly when drawn into a reverse-Z camera depth prepass that declares\n // \"greater-equal\" — otherwise every fragment fails against the 0-cleared buffer.\n depthCompare: sig._depthCompare ?? material.depthCompare,\n depthWriteEnabled: material.needAlphaBlending ? false : material.depthWrite,\n ...(material.depthBias ? { depthBias: material.depthBias } : {}),\n ...(material.depthBiasSlopeScale ? { depthBiasSlopeScale: material.depthBiasSlopeScale } : {}),\n // Pre-baked stencil sub-fields, resolved through the opt-in `_stencilResolver` hook above;\n // applied only on a stencil-capable target — a material reused in the depth32float\n // shadow/depth pass keeps plain depth state (no stencil → no format mismatch). `stencil`\n // is a local const that folds to null in stencil-free bundles, so this branch disappears.\n ...(stencil && sig._depthStencilFormat.includes(\"stencil\") ? stencil._desc : {}),\n },\n }\n : {}),\n multisample: { count: sig._sampleCount },\n primitive: { topology: \"triangle-list\", cullMode: material.backFaceCulling ? \"back\" : \"none\", frontFace: \"ccw\" },\n });\n bindings.pipelines.set(key, pipeline);\n return pipeline;\n}\n\nfunction toUboField(decl: ShaderUniformDecl): UboField {\n return { _name: decl.name, _type: decl.type };\n}\n\nfunction buildBindGroupLayoutEntries(\n samplers: readonly ShaderSamplerDecl[],\n storageBuffers: readonly { name: string; type: string }[],\n hasCustomUbo: boolean\n): GPUBindGroupLayoutEntry[] {\n const entries: GPUBindGroupLayoutEntry[] = [{ binding: 0, visibility: SHADER_STAGE_ALL, buffer: { type: \"uniform\" } }];\n let nextBinding = 1;\n if (hasCustomUbo) {\n entries.push({ binding: nextBinding++, visibility: SHADER_STAGE_ALL, buffer: { type: \"uniform\" } });\n }\n for (const sampler of samplers) {\n const isArray = sampler.viewDimension === \"2d-array\";\n const sampleType = sampler.comparison === true ? \"depth\" : (sampler.sampleType ?? \"float\");\n entries.push({\n binding: nextBinding++,\n visibility: SHADER_STAGE_ALL,\n texture: {\n sampleType,\n viewDimension: isArray ? \"2d-array\" : \"2d\",\n },\n });\n entries.push({\n binding: nextBinding++,\n visibility: SHADER_STAGE_ALL,\n sampler: { type: sampler.comparison === true ? \"comparison\" : sampleType === \"float\" ? \"filtering\" : \"non-filtering\" },\n });\n }\n for (const _storage of storageBuffers) {\n entries.push({\n binding: nextBinding++,\n visibility: SHADER_STAGE_ALL,\n buffer: { type: \"read-only-storage\" },\n });\n }\n return entries;\n}\n\nfunction attributeLayout(name: ShaderAttributeName, shaderLocation: number): GPUVertexBufferLayout {\n switch (name) {\n case \"position\":\n case \"normal\":\n return { arrayStride: 12, attributes: [{ shaderLocation, offset: 0, format: \"float32x3\" }] };\n case \"uv\":\n case \"uv2\":\n return { arrayStride: 8, attributes: [{ shaderLocation, offset: 0, format: \"float32x2\" }] };\n case \"tangent\":\n case \"color\":\n return { arrayStride: 16, attributes: [{ shaderLocation, offset: 0, format: \"float32x4\" }] };\n }\n}\n\nfunction buildShaderPrelude(material: ShaderMaterial, systemSpec: UboSpec, customSpec: UboSpec | null, instanceAttrs = \"\"): string {\n let wgsl = `${SCENE_UBO_WGSL}\nstruct ShaderSystemUniforms {\n${systemSpec._structBody}\n}\n@group(1) @binding(0) var<uniform> shaderSystem: ShaderSystemUniforms;\n`;\n if (customSpec) {\n wgsl += `struct ShaderUniforms {\n${customSpec._structBody}\n}\n@group(1) @binding(1) var<uniform> shaderUniforms: ShaderUniforms;\n`;\n }\n let nextBinding = customSpec ? 2 : 1;\n for (const sampler of material.samplerDecls) {\n const isArray = sampler.viewDimension === \"2d-array\";\n const isDepth = sampler.comparison === true || sampler.sampleType === \"depth\";\n const texType = isDepth ? (isArray ? \"texture_depth_2d_array\" : \"texture_depth_2d\") : isArray ? \"texture_2d_array<f32>\" : \"texture_2d<f32>\";\n const samplerType = sampler.comparison === true ? \"sampler_comparison\" : \"sampler\";\n wgsl += `@group(1) @binding(${nextBinding++}) var ${sampler.name}: ${texType};\n@group(1) @binding(${nextBinding++}) var ${sampler.name}Sampler: ${samplerType};\n`;\n }\n for (const storage of material.storageBufferDecls) {\n wgsl += `@group(1) @binding(${nextBinding++}) var<storage, read> ${storage.name}: ${storage.type};\n`;\n }\n for (const define of material.defines) {\n wgsl += `const ${define.name}: ${typeof define.value === \"boolean\" ? \"bool\" : \"f32\"} = ${formatDefineValue(define.value)};\n`;\n }\n wgsl += `struct VertexInput {\n`;\n for (let i = 0; i < material.attributes.length; i++) {\n const attr = material.attributes[i]!;\n wgsl += `@location(${i}) ${attr}: ${attributeWgslType(attr)},\n`;\n }\n wgsl += instanceAttrs;\n wgsl += `};\n`;\n return wgsl;\n}\n\nfunction formatDefineValue(value: boolean | number): string {\n if (typeof value === \"boolean\") {\n return value ? \"true\" : \"false\";\n }\n if (Number.isInteger(value)) {\n return `${value}.0`;\n }\n return String(value);\n}\n\nfunction attributeWgslType(name: ShaderAttributeName): string {\n switch (name) {\n case \"position\":\n case \"normal\":\n return \"vec3<f32>\";\n case \"uv\":\n case \"uv2\":\n return \"vec2<f32>\";\n case \"tangent\":\n case \"color\":\n return \"vec4<f32>\";\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shader-pipeline.js","sources":["../../../../src/material/shader/shader-pipeline.ts"],"sourcesContent":["import { SS } from \"../../engine/gpu-flags.js\";\nimport type { EngineContext } from \"../../engine/engine.js\";\nimport type { RenderTargetSignature } from \"../../engine/render-target.js\";\nimport { targetSignatureKey } from \"../../engine/render-target.js\";\nimport { getSceneBindGroupLayout } from \"../../render/scene-helpers.js\";\nimport { SCENE_UBO_WGSL } from \"../../shader/scene-uniforms.js\";\nimport { computeUboLayout } from \"../../shader/ubo-layout.js\";\nimport type { UboField, UboSpec } from \"../../shader/fragment-types.js\";\nimport type { ShaderAttributeName, ShaderMaterial, ShaderSamplerDecl, ShaderUniformDecl } from \"./shader-material.js\";\nimport { _isShaderSystemUniform } from \"./shader-material.js\";\nimport type { ResolvedStencil } from \"../stencil-state.js\";\nimport type { StencilState } from \"../material.js\";\n\n/** Stencil resolver, installed only by `enableMaterialStencil`. Module-local with a single exported setter:\n * when `enableMaterialStencil` is absent from the bundle the setter tree-shakes, the bundler proves this is\n * always null, and every stencil branch below folds away — stencil-free Shader scenes stay byte-identical. */\nlet _stencilResolver: ((stencil: StencilState) => ResolvedStencil) | null = null;\n/** @internal Install the stencil resolver into the Shader pipeline (called by `enableMaterialStencil`). */\nexport function _installShaderStencilResolver(resolve: (stencil: StencilState) => ResolvedStencil): void {\n _stencilResolver = resolve;\n}\n\nexport interface ShaderPipelineBindings {\n readonly group1BGL: GPUBindGroupLayout;\n readonly systemSpec: UboSpec;\n readonly customSpec: UboSpec | null;\n readonly vertexBuffers: readonly GPUVertexBufferLayout[];\n readonly pipelines: Map<string, GPURenderPipeline>;\n}\n\ninterface ShaderMaterialPipelineState extends ShaderMaterial {\n _shaderDevice?: GPUDevice;\n _shaderBindings?: ShaderPipelineBindings;\n _shaderCustomUbo?: GPUBuffer | null;\n _shaderCustomSpec?: UboSpec | null;\n _shaderCustomData?: ArrayBuffer | null;\n _shaderCustomVersion?: number;\n}\n\nconst SHADER_STAGE_ALL = SS.VERTEX | SS.FRAGMENT;\n\nexport function getOrCreateShaderPipelineBindings(engine: EngineContext, material: ShaderMaterial): ShaderPipelineBindings {\n const state = material as ShaderMaterialPipelineState;\n if (state._shaderBindings && state._shaderDevice === engine._device) {\n return state._shaderBindings;\n }\n\n state._shaderDevice = engine._device;\n const systemFields = material.uniformDecls.filter((u) => _isShaderSystemUniform(u.name)).map(toUboField);\n const customFields = material.uniformDecls.filter((u) => !_isShaderSystemUniform(u.name)).map(toUboField);\n const systemSpec = computeUboLayout(systemFields.length > 0 ? systemFields : [{ _name: \"_pad\", _type: \"vec4<f32>\" }]);\n const customSpec = customFields.length > 0 ? computeUboLayout(customFields) : null;\n const group1BGL = engine._device.createBindGroupLayout({\n label: \"shader-material-group1\",\n entries: buildBindGroupLayoutEntries(material.samplerDecls, material.storageBufferDecls, customSpec !== null),\n });\n const bindings: ShaderPipelineBindings = {\n group1BGL,\n systemSpec,\n customSpec,\n vertexBuffers: material.attributes.map(attributeLayout),\n pipelines: new Map(),\n };\n state._shaderBindings = bindings;\n state._shaderCustomSpec = customSpec;\n state._shaderCustomUbo = null;\n state._shaderCustomData = null;\n state._shaderCustomVersion = -1;\n return bindings;\n}\n\nexport function getOrCreateShaderPipeline(\n engine: EngineContext,\n sig: RenderTargetSignature,\n material: ShaderMaterial,\n bindings: ShaderPipelineBindings,\n variantKey = \"\",\n vertexBuffers: readonly GPUVertexBufferLayout[] = bindings.vertexBuffers,\n instanceAttrs = \"\"\n): GPURenderPipeline {\n // `variantKey`, `vertexBuffers` and `instanceAttrs` default to the\n // non-instanced pipeline — byte-for-byte identical behaviour to before\n // instancing existed. The dynamically-imported thin-instance module is the\n // only caller that passes non-default values, so no instancing logic runs\n // for non-instanced scenes.\n const key = `${targetSignatureKey(sig)}${variantKey}`;\n const cached = bindings.pipelines.get(key);\n if (cached) {\n return cached;\n }\n const stencil = material.stencil && _stencilResolver ? _stencilResolver(material.stencil) : null;\n const device = engine._device;\n const prelude = buildShaderPrelude(material, bindings.systemSpec, bindings.customSpec, instanceAttrs);\n const vertModule = device.createShaderModule({ label: `${material.name ?? \"shader\"}-vertex`, code: `${prelude}\\n${material.vertexSource}` });\n const wantsFragment = !!sig._colorFormat || material.depthOnlyFragment;\n const fragModule = wantsFragment ? device.createShaderModule({ label: `${material.name ?? \"shader\"}-fragment`, code: `${prelude}\\n${material.fragmentSource}` }) : null;\n const colorTarget: GPUColorTargetState | null = sig._colorFormat\n ? {\n format: sig._colorFormat,\n ...(material.needAlphaBlending\n ? {\n blend:\n material.blendMode === \"additive\"\n ? ({\n color: { srcFactor: \"src-alpha\", dstFactor: \"one\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one\", operation: \"add\" },\n } satisfies GPUBlendState)\n : ({\n color: { srcFactor: \"src-alpha\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n } satisfies GPUBlendState),\n }\n : {}),\n }\n : null;\n\n const pipeline = device.createRenderPipeline({\n label: `${material.name ?? \"shader\"}-pipeline`,\n layout: device.createPipelineLayout({ bindGroupLayouts: [getSceneBindGroupLayout(engine), bindings.group1BGL] }),\n vertex: { module: vertModule, entryPoint: \"mainVertex\", buffers: vertexBuffers as GPUVertexBufferLayout[] },\n ...(fragModule ? { fragment: { module: fragModule, entryPoint: \"mainFragment\", targets: colorTarget ? [colorTarget] : [] } } : {}),\n ...(sig._depthStencilFormat\n ? {\n depthStencil: {\n format: sig._depthStencilFormat,\n // The target's declared depth convention wins over the material default: a depth-only\n // caster authored for the forward-Z shadow map (\"less-equal\") must still depth-test\n // correctly when drawn into a reverse-Z camera depth prepass that declares\n // \"greater-equal\" — otherwise every fragment fails against the 0-cleared buffer.\n depthCompare: sig._depthCompare ?? material.depthCompare,\n depthWriteEnabled: material.needAlphaBlending ? false : material.depthWrite,\n ...(material.depthBias ? { depthBias: material.depthBias } : {}),\n ...(material.depthBiasSlopeScale ? { depthBiasSlopeScale: material.depthBiasSlopeScale } : {}),\n // Pre-baked stencil sub-fields, resolved through the opt-in `_stencilResolver` hook above;\n // applied only on a stencil-capable target — a material reused in the depth32float\n // shadow/depth pass keeps plain depth state (no stencil → no format mismatch). `stencil`\n // is a local const that folds to null in stencil-free bundles, so this branch disappears.\n ...(stencil && sig._depthStencilFormat.includes(\"stencil\") ? stencil._desc : {}),\n },\n }\n : {}),\n multisample: { count: sig._sampleCount },\n primitive: { topology: \"triangle-list\", cullMode: material.backFaceCulling ? \"back\" : \"none\", frontFace: \"ccw\" },\n });\n bindings.pipelines.set(key, pipeline);\n return pipeline;\n}\n\nfunction toUboField(decl: ShaderUniformDecl): UboField {\n return { _name: decl.name, _type: decl.type };\n}\n\nfunction buildBindGroupLayoutEntries(\n samplers: readonly ShaderSamplerDecl[],\n storageBuffers: readonly { name: string; type: string }[],\n hasCustomUbo: boolean\n): GPUBindGroupLayoutEntry[] {\n const entries: GPUBindGroupLayoutEntry[] = [{ binding: 0, visibility: SHADER_STAGE_ALL, buffer: { type: \"uniform\" } }];\n let nextBinding = 1;\n if (hasCustomUbo) {\n entries.push({ binding: nextBinding++, visibility: SHADER_STAGE_ALL, buffer: { type: \"uniform\" } });\n }\n for (const sampler of samplers) {\n const isArray = sampler.viewDimension === \"2d-array\";\n const sampleType = sampler.comparison === true ? \"depth\" : (sampler.sampleType ?? \"float\");\n entries.push({\n binding: nextBinding++,\n visibility: SHADER_STAGE_ALL,\n texture: {\n sampleType,\n viewDimension: isArray ? \"2d-array\" : \"2d\",\n },\n });\n entries.push({\n binding: nextBinding++,\n visibility: SHADER_STAGE_ALL,\n sampler: { type: sampler.comparison === true ? \"comparison\" : sampleType === \"float\" ? \"filtering\" : \"non-filtering\" },\n });\n }\n for (const _storage of storageBuffers) {\n entries.push({\n binding: nextBinding++,\n visibility: SHADER_STAGE_ALL,\n buffer: { type: \"read-only-storage\" },\n });\n }\n return entries;\n}\n\nfunction attributeLayout(name: ShaderAttributeName, shaderLocation: number): GPUVertexBufferLayout {\n switch (name) {\n case \"position\":\n case \"normal\":\n return { arrayStride: 12, attributes: [{ shaderLocation, offset: 0, format: \"float32x3\" }] };\n case \"uv\":\n case \"uv2\":\n return { arrayStride: 8, attributes: [{ shaderLocation, offset: 0, format: \"float32x2\" }] };\n case \"tangent\":\n case \"color\":\n case \"weights\":\n case \"weights1\":\n return { arrayStride: 16, attributes: [{ shaderLocation, offset: 0, format: \"float32x4\" }] };\n case \"joints\":\n case \"joints1\":\n return { arrayStride: 16, attributes: [{ shaderLocation, offset: 0, format: \"uint32x4\" }] };\n }\n}\n\nfunction buildShaderPrelude(material: ShaderMaterial, systemSpec: UboSpec, customSpec: UboSpec | null, instanceAttrs = \"\"): string {\n let wgsl = `${SCENE_UBO_WGSL}\nstruct ShaderSystemUniforms {\n${systemSpec._structBody}\n}\n@group(1) @binding(0) var<uniform> shaderSystem: ShaderSystemUniforms;\n`;\n if (customSpec) {\n wgsl += `struct ShaderUniforms {\n${customSpec._structBody}\n}\n@group(1) @binding(1) var<uniform> shaderUniforms: ShaderUniforms;\n`;\n }\n let nextBinding = customSpec ? 2 : 1;\n for (const sampler of material.samplerDecls) {\n const isArray = sampler.viewDimension === \"2d-array\";\n const isDepth = sampler.comparison === true || sampler.sampleType === \"depth\";\n const texType = isDepth ? (isArray ? \"texture_depth_2d_array\" : \"texture_depth_2d\") : isArray ? \"texture_2d_array<f32>\" : \"texture_2d<f32>\";\n const samplerType = sampler.comparison === true ? \"sampler_comparison\" : \"sampler\";\n wgsl += `@group(1) @binding(${nextBinding++}) var ${sampler.name}: ${texType};\n@group(1) @binding(${nextBinding++}) var ${sampler.name}Sampler: ${samplerType};\n`;\n }\n for (const storage of material.storageBufferDecls) {\n wgsl += `@group(1) @binding(${nextBinding++}) var<storage, read> ${storage.name}: ${storage.type};\n`;\n }\n for (const define of material.defines) {\n wgsl += `const ${define.name}: ${typeof define.value === \"boolean\" ? \"bool\" : \"f32\"} = ${formatDefineValue(define.value)};\n`;\n }\n wgsl += `struct VertexInput {\n`;\n for (let i = 0; i < material.attributes.length; i++) {\n const attr = material.attributes[i]!;\n wgsl += `@location(${i}) ${attr}: ${attributeWgslType(attr)},\n`;\n }\n wgsl += instanceAttrs;\n wgsl += `};\n`;\n return wgsl;\n}\n\nfunction formatDefineValue(value: boolean | number): string {\n if (typeof value === \"boolean\") {\n return value ? \"true\" : \"false\";\n }\n if (Number.isInteger(value)) {\n return `${value}.0`;\n }\n return String(value);\n}\n\nfunction attributeWgslType(name: ShaderAttributeName): string {\n switch (name) {\n case \"position\":\n case \"normal\":\n return \"vec3<f32>\";\n case \"uv\":\n case \"uv2\":\n return \"vec2<f32>\";\n case \"tangent\":\n case \"color\":\n case \"weights\":\n case \"weights1\":\n return \"vec4<f32>\";\n case \"joints\":\n case \"joints1\":\n return \"vec4<u32>\";\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -169,22 +169,23 @@ function updatePacket(scene, material, packet, context) {
|
|
|
169
169
|
writeSystemUniforms(packet.systemData, state._shaderBindings.systemSpec, material, packet.mesh, context._camera ?? scene.camera, context.targetWidth, context.targetHeight);
|
|
170
170
|
engine._device.queue.writeBuffer(packet.systemUBO, 0, packet.systemData);
|
|
171
171
|
if (packet._lastResourceVersion !== material._resourceVersion) {
|
|
172
|
+
const newTextures = collectShaderTextures(material);
|
|
173
|
+
for (const tex of newTextures) {
|
|
174
|
+
acquireTexture(tex);
|
|
175
|
+
}
|
|
172
176
|
for (const tex of packet._boundTextures) {
|
|
173
177
|
releaseTexture(tex);
|
|
174
178
|
}
|
|
175
179
|
packet._bindGroup = createShaderBindGroup(engine, material, packet.systemUBO);
|
|
176
|
-
packet._boundTextures =
|
|
180
|
+
packet._boundTextures = newTextures;
|
|
177
181
|
packet._boundStorageBuffers = collectShaderStorageBuffers(material);
|
|
178
|
-
for (const tex of packet._boundTextures) {
|
|
179
|
-
acquireTexture(tex);
|
|
180
|
-
}
|
|
181
182
|
packet._lastResourceVersion = material._resourceVersion;
|
|
182
183
|
}
|
|
183
184
|
}
|
|
184
185
|
function drawPacket(pass, engine, material, packet) {
|
|
185
186
|
const gpu = packet.mesh._gpu;
|
|
186
187
|
for (let i = 0; i < material.attributes.length; i++) {
|
|
187
|
-
pass.setVertexBuffer(i, getAttrBuffer(engine,
|
|
188
|
+
pass.setVertexBuffer(i, getAttrBuffer(engine, packet.mesh, material.attributes[i]));
|
|
188
189
|
}
|
|
189
190
|
pass.setIndexBuffer(gpu.indexBuffer, gpu.indexFormat);
|
|
190
191
|
pass.setBindGroup(1, packet._bindGroup);
|
|
@@ -387,7 +388,11 @@ function getZeroAttrBuffer(engine, gpu, name) {
|
|
|
387
388
|
cache.set(name, buffer);
|
|
388
389
|
return buffer;
|
|
389
390
|
}
|
|
390
|
-
function
|
|
391
|
+
function getSkinBuffer(mesh, field) {
|
|
392
|
+
return mesh.vat?.[field] ?? mesh.skeleton?.[field] ?? null;
|
|
393
|
+
}
|
|
394
|
+
function getAttrBuffer(engine, mesh, name) {
|
|
395
|
+
const gpu = mesh._gpu;
|
|
391
396
|
switch (name) {
|
|
392
397
|
case "position":
|
|
393
398
|
return gpu.positionBuffer;
|
|
@@ -401,6 +406,14 @@ function getAttrBuffer(engine, gpu, name) {
|
|
|
401
406
|
return gpu.tangentBuffer ?? getZeroAttrBuffer(engine, gpu, "tangent");
|
|
402
407
|
case "color":
|
|
403
408
|
return gpu.colorBuffer ?? getZeroAttrBuffer(engine, gpu, "color");
|
|
409
|
+
case "joints":
|
|
410
|
+
return getSkinBuffer(mesh, "jointsBuffer") ?? getZeroAttrBuffer(engine, gpu, "joints");
|
|
411
|
+
case "weights":
|
|
412
|
+
return getSkinBuffer(mesh, "weightsBuffer") ?? getZeroAttrBuffer(engine, gpu, "weights");
|
|
413
|
+
case "joints1":
|
|
414
|
+
return getSkinBuffer(mesh, "joints1Buffer") ?? getZeroAttrBuffer(engine, gpu, "joints1");
|
|
415
|
+
case "weights1":
|
|
416
|
+
return getSkinBuffer(mesh, "weights1Buffer") ?? getZeroAttrBuffer(engine, gpu, "weights1");
|
|
404
417
|
}
|
|
405
418
|
}
|
|
406
419
|
|