@zephyr3d/scene 0.9.20 → 0.9.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/camera/camera.js +208 -208
  2. package/dist/camera/camera.js.map +1 -1
  3. package/dist/index.d.ts +9 -0
  4. package/dist/posteffect/posteffect.js +16 -0
  5. package/dist/posteffect/posteffect.js.map +1 -1
  6. package/dist/posteffect/ssgi.js +644 -0
  7. package/dist/posteffect/ssgi.js.map +1 -0
  8. package/dist/posteffect/sss.js +129 -44
  9. package/dist/posteffect/sss.js.map +1 -1
  10. package/dist/render/lightpass.js +5 -1
  11. package/dist/render/lightpass.js.map +1 -1
  12. package/dist/render/rendergraph/forward_plus_builder.js +21 -6
  13. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  14. package/dist/render/rendergraph/frame_graph_context.js +41 -0
  15. package/dist/render/rendergraph/frame_graph_context.js.map +1 -0
  16. package/dist/render/shadow_mask_pass.js +42 -39
  17. package/dist/render/shadow_mask_pass.js.map +1 -1
  18. package/dist/shaders/ssgi.js +63 -0
  19. package/dist/shaders/ssgi.js.map +1 -0
  20. package/dist/shadow/esm.js +3 -1
  21. package/dist/shadow/esm.js.map +1 -1
  22. package/dist/shadow/pcf_opt.js +4 -1
  23. package/dist/shadow/pcf_opt.js.map +1 -1
  24. package/dist/shadow/pcf_pd.js +4 -1
  25. package/dist/shadow/pcf_pd.js.map +1 -1
  26. package/dist/shadow/pcss.js +2 -0
  27. package/dist/shadow/pcss.js.map +1 -1
  28. package/dist/shadow/shadow_impl.js.map +1 -1
  29. package/dist/shadow/shadowmapper.js +5 -1
  30. package/dist/shadow/shadowmapper.js.map +1 -1
  31. package/dist/shadow/ssm.js +4 -1
  32. package/dist/shadow/ssm.js.map +1 -1
  33. package/dist/shadow/vsm.js +3 -1
  34. package/dist/shadow/vsm.js.map +1 -1
  35. package/dist/utility/serialization/scene/camera.js.map +1 -1
  36. package/package.json +1 -1
  37. package/dist/animation/joint_dynamics/convex_collider.js +0 -320
  38. package/dist/animation/joint_dynamics/convex_collider.js.map +0 -1
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Ordering helper that encapsulates the side-effect "order token" chain.
3
+ *
4
+ * Side-effect passes (SkyUpdate, ClusterLights, ...) carry no data product, so
5
+ * they are ordered relative to one another through logical tokens rather than
6
+ * texture reads/writes. This scope tracks the most recently emitted token so a
7
+ * pass can chain after the previous one and (optionally) emit its own, without
8
+ * the builder threading a mutable `orderToken` local between blocks.
9
+ *
10
+ * @internal
11
+ */ class OrderingScope {
12
+ /** @internal */ _last = null;
13
+ /**
14
+ * Declare a read on the most recently emitted ordering token, if any, to
15
+ * order the current pass after the previous side-effect pass.
16
+ *
17
+ * @param builder - The pass builder of the current pass.
18
+ */ chainInto(builder) {
19
+ if (this._last) {
20
+ builder.read(this._last);
21
+ }
22
+ }
23
+ /**
24
+ * Emit a new ordering token from the current pass and record it as the latest
25
+ * link in the chain.
26
+ *
27
+ * @param builder - The pass builder of the current pass.
28
+ * @param name - Debug label for the token.
29
+ * @returns The newly created token handle.
30
+ */ emit(builder, name) {
31
+ const token = builder.createToken(name);
32
+ this._last = token;
33
+ return token;
34
+ }
35
+ /** The most recently emitted ordering token, or null. */ get last() {
36
+ return this._last;
37
+ }
38
+ }
39
+
40
+ export { OrderingScope };
41
+ //# sourceMappingURL=frame_graph_context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame_graph_context.js","sources":["../../../src/render/rendergraph/frame_graph_context.ts"],"sourcesContent":["import type { Nullable } from '@zephyr3d/base';\nimport type { RGHandle, RGPassBuilder } from './types';\nimport type { RenderGraph } from './rendergraph';\nimport type { RGBlackboard } from './blackboard';\nimport type { HistoryResourceManager } from './history_resource_manager';\nimport type { DrawContext } from '../drawable';\nimport type { RenderQueue } from '../render_queue';\nimport type { Texture2D, FrameBuffer } from '@zephyr3d/device';\nimport type { ForwardPlusOptions, FrameState, ForwardPlusBuildState } from './forward_plus_builder';\n\n/**\n * Ordering helper that encapsulates the side-effect \"order token\" chain.\n *\n * Side-effect passes (SkyUpdate, ClusterLights, ...) carry no data product, so\n * they are ordered relative to one another through logical tokens rather than\n * texture reads/writes. This scope tracks the most recently emitted token so a\n * pass can chain after the previous one and (optionally) emit its own, without\n * the builder threading a mutable `orderToken` local between blocks.\n *\n * @internal\n */\nexport class OrderingScope {\n /** @internal */\n private _last: Nullable<RGHandle> = null;\n\n /**\n * Declare a read on the most recently emitted ordering token, if any, to\n * order the current pass after the previous side-effect pass.\n *\n * @param builder - The pass builder of the current pass.\n */\n chainInto(builder: RGPassBuilder): void {\n if (this._last) {\n builder.read(this._last);\n }\n }\n\n /**\n * Emit a new ordering token from the current pass and record it as the latest\n * link in the chain.\n *\n * @param builder - The pass builder of the current pass.\n * @param name - Debug label for the token.\n * @returns The newly created token handle.\n */\n emit(builder: RGPassBuilder, name: string): RGHandle {\n const token = builder.createToken(name);\n this._last = token;\n return token;\n }\n\n /** The most recently emitted ordering token, or null. */\n get last(): Nullable<RGHandle> {\n return this._last;\n }\n}\n\n/**\n * Build-time context threaded through the Forward+ graph assembly.\n *\n * This aggregates everything the individual pass-build blocks previously reached\n * through enclosing function locals (`orderToken`, the mutable `depthHandle`,\n * result bundles, ...). Collecting them here is the seam that lets each pass be\n * expressed as an independent unit reading its inputs from a shared context\n * rather than from closure-captured variables.\n *\n * Handles for well-known frame resources (linear depth, scene color, ...) flow\n * through {@link FrameGraphContext.blackboard} keyed by\n * {@link ./blackboard#FrameResources}; the mutable execute-time state that is\n * not a render-graph resource stays on {@link FrameGraphContext.frame}.\n *\n * @internal\n */\nexport interface FrameGraphContext {\n /** The render graph being populated for this frame. */\n readonly graph: RenderGraph;\n /** Frame draw context. */\n readonly ctx: DrawContext;\n /** The culled render queue for this frame. */\n readonly renderQueue: RenderQueue;\n /** Named registry of shared frame-resource handles. */\n readonly blackboard: RGBlackboard;\n /** Mutable execute-time state shared between pass callbacks. */\n readonly frame: FrameState;\n /** Cross-frame history resource manager, or null when unavailable. */\n readonly history: Nullable<HistoryResourceManager<Texture2D>>;\n /** Pipeline feature toggles derived from scene/camera state. */\n readonly options: ForwardPlusOptions;\n /** Ordering-token chain for side-effect passes. */\n readonly ordering: OrderingScope;\n /** The imported backbuffer handle (graph sink). */\n readonly backbuffer: RGHandle;\n /** Mutable build-state shared between modules for non-resource intermediates. */\n readonly state: ForwardPlusBuildState;\n}\n\n/** Backend framebuffer type used by the Forward+ allocator. */\nexport type ForwardPlusFramebuffer = FrameBuffer;\n"],"names":["OrderingScope","_last","chainInto","builder","read","emit","name","token","createToken","last"],"mappings":"AAUA;;;;;;;;;;AAUC,IACM,MAAMA,aAAAA,CAAAA;qBAEX,KAAQC,GAA4B,IAAK;AAEzC;;;;;MAMAC,SAAAA,CAAUC,OAAsB,EAAQ;QACtC,IAAI,IAAI,CAACF,KAAK,EAAE;AACdE,YAAAA,OAAAA,CAAQC,IAAI,CAAC,IAAI,CAACH,KAAK,CAAA;AACzB;AACF;AAEA;;;;;;;AAOC,MACDI,IAAKF,CAAAA,OAAsB,EAAEG,IAAY,EAAY;QACnD,MAAMC,KAAAA,GAAQJ,OAAQK,CAAAA,WAAW,CAACF,IAAAA,CAAAA;QAClC,IAAI,CAACL,KAAK,GAAGM,KAAAA;QACb,OAAOA,KAAAA;AACT;8DAGA,IAAIE,IAA2B,GAAA;QAC7B,OAAO,IAAI,CAACR,KAAK;AACnB;AACF;;;;"}
@@ -4,29 +4,29 @@ import { drawFullscreenQuad } from './fullscreenquad.js';
4
4
  import { MAX_SHADOW_MASK_LIGHTS } from '../values.js';
5
5
 
6
6
  const UNIFORM_NAME_SHADOW_MAP = 'Z_UniformShadowMap';
7
- /**
8
- * Number of shadow-casting lights packed into a single RGBA8 mask array layer.
9
- * One light per color channel.
7
+ /**
8
+ * Number of shadow-casting lights packed into a single RGBA8 mask array layer.
9
+ * One light per color channel.
10
10
  */ const SHADOW_MASK_LIGHTS_PER_LAYER = 4;
11
- /**
12
- * Maximum number of shadow mask array layers, derived from the per-light cap.
11
+ /**
12
+ * Maximum number of shadow mask array layers, derived from the per-light cap.
13
13
  */ const MAX_SHADOW_MASK_LAYERS = MAX_SHADOW_MASK_LIGHTS / SHADOW_MASK_LIGHTS_PER_LAYER;
14
- /**
15
- * Renders the screen-space shadow mask for the Forward+ pipeline.
16
- *
17
- * For each shadow-casting light, the light's visibility factor `[0,1]` (1 = lit,
18
- * 0 = fully shadowed) is reconstructed from the linear depth prepass and written
19
- * into one channel of one layer of an `rgba8unorm` texture array. Four lights are
20
- * packed per layer (one per RGBA channel).
21
- *
22
- * The layer/channel assignment must stay in lockstep with
23
- * {@link ClusteredLight.getVisibleLights}: shadow-casting lights occupy clustered
24
- * buffer indices `1..N` in the order of `renderQueue.shadowedLights`. The zero-based
25
- * light ordinal `s = index - 1` maps to `layer = s >> 2`, `channel = s & 3`. The
26
- * clustered shading pass recovers the same mapping from a light's buffer index, so
27
- * no per-light mask index is stored.
28
- *
29
- * @internal
14
+ /**
15
+ * Renders the screen-space shadow mask for the Forward+ pipeline.
16
+ *
17
+ * For each shadow-casting light, the light's visibility factor `[0,1]` (1 = lit,
18
+ * 0 = fully shadowed) is reconstructed from the linear depth prepass and written
19
+ * into one channel of one layer of an `rgba8unorm` texture array. Four lights are
20
+ * packed per layer (one per RGBA channel).
21
+ *
22
+ * The layer/channel assignment must stay in lockstep with
23
+ * {@link ClusteredLight.getVisibleLights}: shadow-casting lights occupy clustered
24
+ * buffer indices `1..N` in the order of `renderQueue.shadowedLights`. The zero-based
25
+ * light ordinal `s = index - 1` maps to `layer = s >> 2`, `channel = s & 3`. The
26
+ * clustered shading pass recovers the same mapping from a light's buffer index, so
27
+ * no per-light mask index is stored.
28
+ *
29
+ * @internal
30
30
  */ class ShadowMaskRenderer {
31
31
  /** Fullscreen mask programs keyed by a per-light shader signature. */ _programs;
32
32
  /** Bind groups paired with each cached program. */ _bindGroups;
@@ -42,21 +42,21 @@ const UNIFORM_NAME_SHADOW_MAP = 'Z_UniformShadowMap';
42
42
  this._cameraPosition = new Vector4();
43
43
  this._cameraParams = new Vector4();
44
44
  }
45
- /**
46
- * Number of array layers required to hold `numLights` shadow lights.
47
- * @param numLights - Number of shadow-casting lights.
48
- * @returns Layer count, clamped to {@link MAX_SHADOW_MASK_LAYERS}.
45
+ /**
46
+ * Number of array layers required to hold `numLights` shadow lights.
47
+ * @param numLights - Number of shadow-casting lights.
48
+ * @returns Layer count, clamped to {@link MAX_SHADOW_MASK_LAYERS}.
49
49
  */ static getLayerCount(numLights) {
50
50
  const n = Math.min(numLights, MAX_SHADOW_MASK_LIGHTS);
51
51
  return Math.min(Math.ceil(n / SHADOW_MASK_LIGHTS_PER_LAYER), MAX_SHADOW_MASK_LAYERS);
52
52
  }
53
- /**
54
- * Render the shadow mask for the given shadow-casting lights.
55
- *
56
- * @param ctx - Draw context (must carry shadowMapInfo for the lights).
57
- * @param depthTexture - Linear depth texture from the depth prepass.
58
- * @param lights - Shadow-casting lights, in clustered-buffer order (index 1..N).
59
- * @param getLayerFramebuffer - Resolves the framebuffer bound to mask array layer `k`.
53
+ /**
54
+ * Render the shadow mask for the given shadow-casting lights.
55
+ *
56
+ * @param ctx - Draw context (must carry shadowMapInfo for the lights).
57
+ * @param depthTexture - Linear depth texture from the depth prepass.
58
+ * @param lights - Shadow-casting lights, in clustered-buffer order (index 1..N).
59
+ * @param getLayerFramebuffer - Resolves the framebuffer bound to mask array layer `k`.
60
60
  */ render(ctx, depthTexture, lights, getLayerFramebuffer) {
61
61
  const device = ctx.device;
62
62
  const numLights = Math.min(lights.length, MAX_SHADOW_MASK_LIGHTS);
@@ -84,6 +84,9 @@ const UNIFORM_NAME_SHADOW_MAP = 'Z_UniformShadowMap';
84
84
  if (!shadowMapParams || !shadowMapParams.shadowMap) {
85
85
  continue;
86
86
  }
87
+ // Record where this light lives in the mask so downstream samplers (e.g.
88
+ // the SSS combine pass) can read its channel without recomputing shadows.
89
+ shadowMapParams.maskOrdinal = ordinal;
87
90
  ctx.currentShadowLight = light;
88
91
  this.renderLightChannel(ctx, depthTexture, light, shadowMapParams, channelStates[channel]);
89
92
  }
@@ -108,9 +111,9 @@ const UNIFORM_NAME_SHADOW_MAP = 'Z_UniformShadowMap';
108
111
  device.setBindGroup(0, bindGroup);
109
112
  drawFullscreenQuad(renderState);
110
113
  }
111
- /**
112
- * The program signature: distinct shadow implementations, cascade counts and
113
- * shadow map types must not share a compiled program.
114
+ /**
115
+ * The program signature: distinct shadow implementations, cascade counts and
116
+ * shadow map types must not share a compiled program.
114
117
  */ getProgramKey(ctx, shadowMapParams) {
115
118
  return `${ctx.device.type}|${shadowMapParams.shaderHash}`;
116
119
  }
@@ -168,10 +171,10 @@ const UNIFORM_NAME_SHADOW_MAP = 'Z_UniformShadowMap';
168
171
  bindGroup.setTexture('depthTex', depthTexture);
169
172
  bindGroup.setTexture(UNIFORM_NAME_SHADOW_MAP, shadowMapParams.shadowMap, shadowMapParams.shadowMapSampler);
170
173
  }
171
- /**
172
- * Whether the fullscreen output needs a vertical flip. Mask array layers are
173
- * offscreen render targets, so the convention matches other offscreen passes
174
- * (no flip); WebGPU still flips clip-space Y in the vertex shader.
174
+ /**
175
+ * Whether the fullscreen output needs a vertical flip. Mask array layers are
176
+ * offscreen render targets, so the convention matches other offscreen passes
177
+ * (no flip); WebGPU still flips clip-space Y in the vertex shader.
175
178
  */ needFlip(_device) {
176
179
  return false;
177
180
  }
@@ -1 +1 @@
1
- {"version":3,"file":"shadow_mask_pass.js","sources":["../../src/render/shadow_mask_pass.ts"],"sourcesContent":["import { Vector2, Vector4 } from '@zephyr3d/base';\nimport type { Nullable } from '@zephyr3d/base';\nimport type {\n AbstractDevice,\n BindGroup,\n FrameBuffer,\n GPUProgram,\n PBShaderExp,\n RenderStateSet,\n Texture2D\n} from '@zephyr3d/device';\nimport type { DrawContext } from './drawable';\nimport type { PunctualLight } from '../scene/light';\nimport type { ShadowMapParams } from '../shadow/shadowmapper';\nimport { ShaderHelper } from '../material/shader/helper';\nimport { drawFullscreenQuad } from './fullscreenquad';\nimport { MAX_SHADOW_MASK_LIGHTS } from '../values';\n\nconst UNIFORM_NAME_SHADOW_MAP = 'Z_UniformShadowMap';\n\n/**\n * Number of shadow-casting lights packed into a single RGBA8 mask array layer.\n * One light per color channel.\n */\nexport const SHADOW_MASK_LIGHTS_PER_LAYER = 4;\n\n/**\n * Maximum number of shadow mask array layers, derived from the per-light cap.\n */\nexport const MAX_SHADOW_MASK_LAYERS = MAX_SHADOW_MASK_LIGHTS / SHADOW_MASK_LIGHTS_PER_LAYER;\n\n/**\n * Renders the screen-space shadow mask for the Forward+ pipeline.\n *\n * For each shadow-casting light, the light's visibility factor `[0,1]` (1 = lit,\n * 0 = fully shadowed) is reconstructed from the linear depth prepass and written\n * into one channel of one layer of an `rgba8unorm` texture array. Four lights are\n * packed per layer (one per RGBA channel).\n *\n * The layer/channel assignment must stay in lockstep with\n * {@link ClusteredLight.getVisibleLights}: shadow-casting lights occupy clustered\n * buffer indices `1..N` in the order of `renderQueue.shadowedLights`. The zero-based\n * light ordinal `s = index - 1` maps to `layer = s >> 2`, `channel = s & 3`. The\n * clustered shading pass recovers the same mapping from a light's buffer index, so\n * no per-light mask index is stored.\n *\n * @internal\n */\nexport class ShadowMaskRenderer {\n /** Fullscreen mask programs keyed by a per-light shader signature. */\n private _programs: Map<string, GPUProgram>;\n /** Bind groups paired with each cached program. */\n private _bindGroups: Map<string, BindGroup>;\n /** One render state per RGBA channel (color mask selects the target channel). */\n private _channelStates: Nullable<RenderStateSet[]>;\n private readonly _nearFar: Vector2;\n private readonly _cameraPosition: Vector4;\n private readonly _cameraParams: Vector4;\n\n constructor() {\n this._programs = new Map();\n this._bindGroups = new Map();\n this._channelStates = null;\n this._nearFar = new Vector2();\n this._cameraPosition = new Vector4();\n this._cameraParams = new Vector4();\n }\n\n /**\n * Number of array layers required to hold `numLights` shadow lights.\n * @param numLights - Number of shadow-casting lights.\n * @returns Layer count, clamped to {@link MAX_SHADOW_MASK_LAYERS}.\n */\n static getLayerCount(numLights: number): number {\n const n = Math.min(numLights, MAX_SHADOW_MASK_LIGHTS);\n return Math.min(Math.ceil(n / SHADOW_MASK_LIGHTS_PER_LAYER), MAX_SHADOW_MASK_LAYERS);\n }\n\n /**\n * Render the shadow mask for the given shadow-casting lights.\n *\n * @param ctx - Draw context (must carry shadowMapInfo for the lights).\n * @param depthTexture - Linear depth texture from the depth prepass.\n * @param lights - Shadow-casting lights, in clustered-buffer order (index 1..N).\n * @param getLayerFramebuffer - Resolves the framebuffer bound to mask array layer `k`.\n */\n render(\n ctx: DrawContext,\n depthTexture: Texture2D,\n lights: PunctualLight[],\n getLayerFramebuffer: (layer: number) => FrameBuffer\n ): void {\n const device = ctx.device;\n const numLights = Math.min(lights.length, MAX_SHADOW_MASK_LIGHTS);\n if (numLights === 0 || !ctx.shadowMapInfo) {\n return;\n }\n const numLayers = ShadowMaskRenderer.getLayerCount(numLights);\n const channelStates = this.getChannelStates(device);\n const savedShadowLight = ctx.currentShadowLight;\n\n device.pushDeviceStates();\n for (let layer = 0; layer < numLayers; layer++) {\n const framebuffer = getLayerFramebuffer(layer);\n device.setFramebuffer(framebuffer);\n // Clear to \"fully lit\" (1 = no shadow) so channels without an assigned\n // light, and pixels outside any shadow, read as unshadowed. The mask array\n // has no depth attachment, so depth/stencil clear args are null.\n device.clearFrameBuffer(new Vector4(1, 1, 1, 1), null, null);\n for (let channel = 0; channel < SHADOW_MASK_LIGHTS_PER_LAYER; channel++) {\n const ordinal = layer * SHADOW_MASK_LIGHTS_PER_LAYER + channel;\n if (ordinal >= numLights) {\n break;\n }\n const light = lights[ordinal];\n const shadowMapParams = ctx.shadowMapInfo.get(light);\n if (!shadowMapParams || !shadowMapParams.shadowMap) {\n continue;\n }\n ctx.currentShadowLight = light;\n this.renderLightChannel(ctx, depthTexture, light, shadowMapParams, channelStates[channel]);\n }\n }\n device.popDeviceStates();\n ctx.currentShadowLight = savedShadowLight;\n }\n\n /** Render one shadow light into one color channel of the current framebuffer. */\n private renderLightChannel(\n ctx: DrawContext,\n depthTexture: Texture2D,\n light: PunctualLight,\n shadowMapParams: ShadowMapParams,\n renderState: RenderStateSet\n ): void {\n const device = ctx.device;\n const key = this.getProgramKey(ctx, shadowMapParams);\n let program = this._programs.get(key) ?? null;\n let bindGroup = this._bindGroups.get(key) ?? null;\n if (!program) {\n program = this.createProgram(ctx, shadowMapParams);\n bindGroup = device.createBindGroup(program.bindGroupLayouts[0]);\n this._programs.set(key, program);\n this._bindGroups.set(key, bindGroup);\n }\n bindGroup = this._bindGroups.get(key)!;\n this.setUniforms(bindGroup, ctx, depthTexture, light, shadowMapParams);\n device.setProgram(program);\n device.setBindGroup(0, bindGroup);\n drawFullscreenQuad(renderState);\n }\n\n /**\n * The program signature: distinct shadow implementations, cascade counts and\n * shadow map types must not share a compiled program.\n */\n private getProgramKey(ctx: DrawContext, shadowMapParams: ShadowMapParams): string {\n return `${ctx.device.type}|${shadowMapParams.shaderHash}`;\n }\n\n private getChannelStates(device: AbstractDevice): RenderStateSet[] {\n if (!this._channelStates) {\n this._channelStates = [];\n for (let c = 0; c < SHADOW_MASK_LIGHTS_PER_LAYER; c++) {\n const rs = device.createRenderStateSet();\n rs.useDepthState().enableTest(false).enableWrite(false);\n rs.useRasterizerState().setCullMode('none');\n rs.useColorState().setColorMask(c === 0, c === 1, c === 2, c === 3);\n this._channelStates.push(rs);\n }\n }\n return this._channelStates;\n }\n\n private setUniforms(\n bindGroup: BindGroup,\n ctx: DrawContext,\n depthTexture: Texture2D,\n light: PunctualLight,\n shadowMapParams: ShadowMapParams\n ): void {\n const camera = ctx.camera;\n const near = camera.getNearPlane();\n const far = camera.getFarPlane();\n const cameraPos = camera.getWorldPosition();\n this._cameraPosition.setXYZW(cameraPos.x, cameraPos.y, cameraPos.z, 0);\n this._cameraParams.setXYZW(near, far, 1, 1);\n this._nearFar.setXY(near, far);\n bindGroup.setValue('camera', {\n position: this._cameraPosition,\n params: this._cameraParams,\n shadowDebugCascades: camera.shadowDebugCascades ? 1 : 0,\n framestamp: ctx.device.frameInfo.frameCounter\n });\n // Full shadow light struct (matches helper.ts currentShadowLight lightStruct,\n // including implParams which PCSS/VSM impls read via getShadowImplParams).\n const implParams = new Vector4();\n shadowMapParams.impl!.getParams(implParams);\n bindGroup.setValue('light', {\n sunDir: ctx.sunLight\n ? ctx.sunLight.directionAndCutoff.xyz().scaleBy(-1)\n : new Vector4(0, 1, 0, 0).xyz(),\n shadowCascades: shadowMapParams.numShadowCascades,\n positionAndRange: light.positionAndRange,\n directionAndCutoff: light.directionAndCutoff,\n diffuseAndIntensity: light.diffuseAndIntensity,\n extraParams: light.extraParams,\n cascadeDistances: shadowMapParams.cascadeDistances,\n depthBiasValues: shadowMapParams.depthBiasValues[0],\n shadowCameraParams: shadowMapParams.cameraParams,\n depthBiasScales: shadowMapParams.depthBiasScales,\n implParams: implParams,\n shadowMatrices: new Float32Array(shadowMapParams.shadowMatrices),\n shadowStrength: light.shadow.shadowStrength,\n envLightStrength: ctx.env?.light.strength ?? 0,\n envLightSpecularStrength: ctx.env?.light.specularStrength ?? 1\n });\n bindGroup.setValue('invViewProjMatrix', camera.invViewProjectionMatrix);\n bindGroup.setValue('cameraNearFar', this._nearFar);\n bindGroup.setValue('flip', this.needFlip(ctx.device) ? 1 : 0);\n bindGroup.setTexture('depthTex', depthTexture);\n bindGroup.setTexture(\n UNIFORM_NAME_SHADOW_MAP,\n shadowMapParams.shadowMap!,\n shadowMapParams.shadowMapSampler\n );\n }\n\n /**\n * Whether the fullscreen output needs a vertical flip. Mask array layers are\n * offscreen render targets, so the convention matches other offscreen passes\n * (no flip); WebGPU still flips clip-space Y in the vertex shader.\n */\n private needFlip(_device: AbstractDevice): boolean {\n return false;\n }\n\n private createProgram(ctx: DrawContext, shadowMapParams: ShadowMapParams): GPUProgram {\n const device = ctx.device;\n const numCascades = shadowMapParams.numShadowCascades;\n const shadowMap = shadowMapParams.shadowMap!;\n const program = device.buildRenderProgram({\n label: 'ShadowMask',\n vertex(pb) {\n this.flip = pb.int().uniform(0);\n this.$inputs.pos = pb.vec2().attrib('position');\n this.$outputs.uv = pb.vec2();\n pb.main(function () {\n this.$builtins.position = pb.vec4(this.$inputs.pos, 1, 1);\n this.$outputs.uv = pb.add(pb.mul(this.$inputs.pos.xy, 0.5), pb.vec2(0.5));\n this.$if(pb.notEqual(this.flip, 0), function () {\n this.$builtins.position.y = pb.neg(this.$builtins.position.y);\n });\n if (device.type === 'webgpu') {\n this.$builtins.position.y = pb.neg(this.$builtins.position.y);\n }\n });\n },\n fragment(pb) {\n const cameraStruct = pb.defineStruct([\n pb.vec4('position'),\n pb.vec4('params'),\n pb.float('shadowDebugCascades'),\n // Required by PCSS temporal jitter (ShaderHelper.getFramestamp).\n pb.int('framestamp')\n ]);\n // Must match helper.ts currentShadowLight lightStruct field-for-field.\n const lightStruct = pb.defineStruct([\n pb.vec3('sunDir'),\n pb.int('shadowCascades'),\n pb.vec4('positionAndRange'),\n pb.vec4('directionAndCutoff'),\n pb.vec4('diffuseAndIntensity'),\n pb.vec4('extraParams'),\n pb.vec4('cascadeDistances'),\n pb.vec4('depthBiasValues'),\n pb.vec4('shadowCameraParams'),\n pb.vec4('depthBiasScales'),\n pb.vec4('implParams'),\n pb.vec4[16]('shadowMatrices'),\n pb.float('shadowStrength'),\n pb.float('envLightStrength'),\n pb.float('envLightSpecularStrength')\n ]);\n this.camera = cameraStruct().uniform(0);\n this.light = lightStruct().uniform(0);\n const shadowTex = shadowMap.isTextureCube()\n ? shadowMap.isDepth()\n ? pb.texCubeShadow()\n : pb.texCube()\n : shadowMap.isTexture2D()\n ? shadowMap.isDepth()\n ? pb.tex2DShadow()\n : pb.tex2D()\n : shadowMap.isDepth()\n ? pb.tex2DArrayShadow()\n : pb.tex2DArray();\n if (\n !shadowMap.isDepth() &&\n !device.getDeviceCaps().textureCaps.getTextureFormatInfo(shadowMap.format).filterable\n ) {\n shadowTex.sampleType('unfilterable-float');\n }\n this[UNIFORM_NAME_SHADOW_MAP] = shadowTex.uniform(0);\n this.depthTex = pb.tex2D().uniform(0);\n this.invViewProjMatrix = pb.mat4().uniform(0);\n this.cameraNearFar = pb.vec2().uniform(0);\n this.$outputs.color = pb.vec4();\n // Explicit-depth cascade selection (fragCoord.z is invalid in a fullscreen\n // pass). Mirrors posteffect/sss.ts calculateTransmissionShadow.\n pb.func(\n 'zShadowMaskFactor',\n [pb.vec3('worldPos'), pb.float('depth01'), pb.float('NoL')],\n function () {\n if (numCascades > 1) {\n this.$l.linearDepth = pb.mul(this.depth01, this.camera.params.y);\n this.$l.splitDistances = this.light.cascadeDistances;\n this.$l.comparison = pb.vec4(pb.greaterThan(pb.vec4(this.linearDepth), this.splitDistances));\n this.$l.cascadeFlags = pb.vec4(\n pb.float(pb.greaterThan(this.light.shadowCascades, 0)),\n pb.float(pb.greaterThan(this.light.shadowCascades, 1)),\n pb.float(pb.greaterThan(this.light.shadowCascades, 2)),\n pb.float(pb.greaterThan(this.light.shadowCascades, 3))\n );\n this.$l.split = pb.int(pb.dot(this.comparison, this.cascadeFlags));\n if (device.type === 'webgl') {\n this.$l.shadowVertex = pb.vec4();\n this.$for(pb.int('cascade'), 0, 4, function () {\n this.$if(pb.equal(this.cascade, this.split), function () {\n this.shadowVertex = ShaderHelper.calculateShadowSpaceVertex(\n this,\n pb.vec4(this.worldPos, 1),\n this.cascade\n );\n this.$break();\n });\n });\n } else {\n this.$l.shadowVertex = ShaderHelper.calculateShadowSpaceVertex(\n this,\n pb.vec4(this.worldPos, 1),\n this.split\n );\n }\n this.$l.shadow = shadowMapParams.impl!.computeShadowCSM(\n shadowMapParams,\n this,\n this.shadowVertex,\n this.NoL,\n this.split\n );\n this.$l.shadowDistance = this.light.shadowCameraParams.w;\n this.shadow = pb.mix(\n this.shadow,\n 1,\n pb.smoothStep(\n pb.mul(this.shadowDistance, 0.8),\n this.shadowDistance,\n pb.distance(this.camera.position.xyz, this.worldPos)\n )\n );\n this.shadow = pb.mix(1, this.shadow, this.light.shadowStrength);\n this.$return(pb.clamp(this.shadow, 0, 1));\n } else {\n this.$l.shadowVertex = ShaderHelper.calculateShadowSpaceVertex(this, pb.vec4(this.worldPos, 1));\n this.$l.shadow = shadowMapParams.impl!.computeShadow(\n shadowMapParams,\n this,\n this.shadowVertex,\n this.NoL\n );\n this.$l.shadowDistance = this.light.shadowCameraParams.w;\n this.shadow = pb.mix(\n this.shadow,\n 1,\n pb.smoothStep(\n pb.mul(this.shadowDistance, 0.8),\n this.shadowDistance,\n pb.distance(this.camera.position.xyz, this.worldPos)\n )\n );\n this.shadow = pb.mix(1, this.shadow, this.light.shadowStrength);\n this.$return(pb.clamp(this.shadow, 0, 1));\n }\n }\n );\n pb.main(function () {\n this.$l.pos = ShaderHelper.samplePositionFromDepth(\n this,\n this.depthTex,\n this.$inputs.uv,\n this.invViewProjMatrix,\n this.cameraNearFar\n );\n // NoL is unavailable in a fullscreen pass (no geometric normal); it only\n // feeds normal-offset bias, so a conservative 1.0 is used.\n this.$l.factor = this.zShadowMaskFactor(this.pos.xyz, this.pos.w, pb.float(1));\n this.$outputs.color = pb.vec4(this.factor);\n });\n }\n })!;\n program.name = '@ShadowMask';\n return program;\n }\n\n /** Release cached GPU resources. */\n dispose(): void {\n for (const program of this._programs.values()) {\n program.dispose();\n }\n this._programs.clear();\n this._bindGroups.clear();\n this._channelStates = null;\n }\n}\n\n/** Shared type alias to keep the mask factor accessor discoverable. */\nexport type ShadowMaskFactorExp = PBShaderExp;\n"],"names":["UNIFORM_NAME_SHADOW_MAP","SHADOW_MASK_LIGHTS_PER_LAYER","MAX_SHADOW_MASK_LAYERS","MAX_SHADOW_MASK_LIGHTS","ShadowMaskRenderer","_nearFar","_cameraPosition","_cameraParams","_programs","Map","_bindGroups","_channelStates","Vector2","Vector4","getLayerCount","numLights","n","Math","min","ceil","render","ctx","depthTexture","lights","getLayerFramebuffer","device","length","shadowMapInfo","numLayers","channelStates","getChannelStates","savedShadowLight","currentShadowLight","pushDeviceStates","layer","framebuffer","setFramebuffer","clearFrameBuffer","channel","ordinal","light","shadowMapParams","get","shadowMap","renderLightChannel","popDeviceStates","renderState","key","getProgramKey","program","bindGroup","createProgram","createBindGroup","bindGroupLayouts","set","setUniforms","setProgram","setBindGroup","drawFullscreenQuad","type","shaderHash","c","rs","createRenderStateSet","useDepthState","enableTest","enableWrite","useRasterizerState","setCullMode","useColorState","setColorMask","push","camera","near","getNearPlane","far","getFarPlane","cameraPos","getWorldPosition","setXYZW","x","y","z","setXY","setValue","position","params","shadowDebugCascades","framestamp","frameInfo","frameCounter","implParams","impl","getParams","sunDir","sunLight","directionAndCutoff","xyz","scaleBy","shadowCascades","numShadowCascades","positionAndRange","diffuseAndIntensity","extraParams","cascadeDistances","depthBiasValues","shadowCameraParams","cameraParams","depthBiasScales","shadowMatrices","Float32Array","shadowStrength","shadow","envLightStrength","env","strength","envLightSpecularStrength","specularStrength","invViewProjectionMatrix","needFlip","setTexture","shadowMapSampler","_device","numCascades","buildRenderProgram","label","vertex","pb","flip","int","uniform","$inputs","pos","vec2","attrib","$outputs","uv","main","$builtins","vec4","add","mul","xy","$if","notEqual","neg","fragment","cameraStruct","defineStruct","float","lightStruct","vec3","shadowTex","isTextureCube","isDepth","texCubeShadow","texCube","isTexture2D","tex2DShadow","tex2D","tex2DArrayShadow","tex2DArray","getDeviceCaps","textureCaps","getTextureFormatInfo","format","filterable","sampleType","depthTex","invViewProjMatrix","mat4","cameraNearFar","color","func","$l","linearDepth","depth01","splitDistances","comparison","greaterThan","cascadeFlags","split","dot","shadowVertex","$for","equal","cascade","ShaderHelper","calculateShadowSpaceVertex","worldPos","$break","computeShadowCSM","NoL","shadowDistance","w","mix","smoothStep","distance","$return","clamp","computeShadow","samplePositionFromDepth","factor","zShadowMaskFactor","name","dispose","values","clear"],"mappings":"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"}
1
+ {"version":3,"file":"shadow_mask_pass.js","sources":["../../src/render/shadow_mask_pass.ts"],"sourcesContent":["import { Vector2, Vector4 } from '@zephyr3d/base';\r\nimport type { Nullable } from '@zephyr3d/base';\r\nimport type {\r\n AbstractDevice,\r\n BindGroup,\r\n FrameBuffer,\r\n GPUProgram,\r\n PBShaderExp,\r\n RenderStateSet,\r\n Texture2D\r\n} from '@zephyr3d/device';\r\nimport type { DrawContext } from './drawable';\r\nimport type { PunctualLight } from '../scene/light';\r\nimport type { ShadowMapParams } from '../shadow/shadowmapper';\r\nimport { ShaderHelper } from '../material/shader/helper';\r\nimport { drawFullscreenQuad } from './fullscreenquad';\r\nimport { MAX_SHADOW_MASK_LIGHTS } from '../values';\r\n\r\nconst UNIFORM_NAME_SHADOW_MAP = 'Z_UniformShadowMap';\r\n\r\n/**\r\n * Number of shadow-casting lights packed into a single RGBA8 mask array layer.\r\n * One light per color channel.\r\n */\r\nexport const SHADOW_MASK_LIGHTS_PER_LAYER = 4;\r\n\r\n/**\r\n * Maximum number of shadow mask array layers, derived from the per-light cap.\r\n */\r\nexport const MAX_SHADOW_MASK_LAYERS = MAX_SHADOW_MASK_LIGHTS / SHADOW_MASK_LIGHTS_PER_LAYER;\r\n\r\n/**\r\n * Renders the screen-space shadow mask for the Forward+ pipeline.\r\n *\r\n * For each shadow-casting light, the light's visibility factor `[0,1]` (1 = lit,\r\n * 0 = fully shadowed) is reconstructed from the linear depth prepass and written\r\n * into one channel of one layer of an `rgba8unorm` texture array. Four lights are\r\n * packed per layer (one per RGBA channel).\r\n *\r\n * The layer/channel assignment must stay in lockstep with\r\n * {@link ClusteredLight.getVisibleLights}: shadow-casting lights occupy clustered\r\n * buffer indices `1..N` in the order of `renderQueue.shadowedLights`. The zero-based\r\n * light ordinal `s = index - 1` maps to `layer = s >> 2`, `channel = s & 3`. The\r\n * clustered shading pass recovers the same mapping from a light's buffer index, so\r\n * no per-light mask index is stored.\r\n *\r\n * @internal\r\n */\r\nexport class ShadowMaskRenderer {\r\n /** Fullscreen mask programs keyed by a per-light shader signature. */\r\n private _programs: Map<string, GPUProgram>;\r\n /** Bind groups paired with each cached program. */\r\n private _bindGroups: Map<string, BindGroup>;\r\n /** One render state per RGBA channel (color mask selects the target channel). */\r\n private _channelStates: Nullable<RenderStateSet[]>;\r\n private readonly _nearFar: Vector2;\r\n private readonly _cameraPosition: Vector4;\r\n private readonly _cameraParams: Vector4;\r\n\r\n constructor() {\r\n this._programs = new Map();\r\n this._bindGroups = new Map();\r\n this._channelStates = null;\r\n this._nearFar = new Vector2();\r\n this._cameraPosition = new Vector4();\r\n this._cameraParams = new Vector4();\r\n }\r\n\r\n /**\r\n * Number of array layers required to hold `numLights` shadow lights.\r\n * @param numLights - Number of shadow-casting lights.\r\n * @returns Layer count, clamped to {@link MAX_SHADOW_MASK_LAYERS}.\r\n */\r\n static getLayerCount(numLights: number): number {\r\n const n = Math.min(numLights, MAX_SHADOW_MASK_LIGHTS);\r\n return Math.min(Math.ceil(n / SHADOW_MASK_LIGHTS_PER_LAYER), MAX_SHADOW_MASK_LAYERS);\r\n }\r\n\r\n /**\r\n * Render the shadow mask for the given shadow-casting lights.\r\n *\r\n * @param ctx - Draw context (must carry shadowMapInfo for the lights).\r\n * @param depthTexture - Linear depth texture from the depth prepass.\r\n * @param lights - Shadow-casting lights, in clustered-buffer order (index 1..N).\r\n * @param getLayerFramebuffer - Resolves the framebuffer bound to mask array layer `k`.\r\n */\r\n render(\r\n ctx: DrawContext,\r\n depthTexture: Texture2D,\r\n lights: PunctualLight[],\r\n getLayerFramebuffer: (layer: number) => FrameBuffer\r\n ): void {\r\n const device = ctx.device;\r\n const numLights = Math.min(lights.length, MAX_SHADOW_MASK_LIGHTS);\r\n if (numLights === 0 || !ctx.shadowMapInfo) {\r\n return;\r\n }\r\n const numLayers = ShadowMaskRenderer.getLayerCount(numLights);\r\n const channelStates = this.getChannelStates(device);\r\n const savedShadowLight = ctx.currentShadowLight;\r\n\r\n device.pushDeviceStates();\r\n for (let layer = 0; layer < numLayers; layer++) {\r\n const framebuffer = getLayerFramebuffer(layer);\r\n device.setFramebuffer(framebuffer);\r\n // Clear to \"fully lit\" (1 = no shadow) so channels without an assigned\r\n // light, and pixels outside any shadow, read as unshadowed. The mask array\r\n // has no depth attachment, so depth/stencil clear args are null.\r\n device.clearFrameBuffer(new Vector4(1, 1, 1, 1), null, null);\r\n for (let channel = 0; channel < SHADOW_MASK_LIGHTS_PER_LAYER; channel++) {\r\n const ordinal = layer * SHADOW_MASK_LIGHTS_PER_LAYER + channel;\r\n if (ordinal >= numLights) {\r\n break;\r\n }\r\n const light = lights[ordinal];\r\n const shadowMapParams = ctx.shadowMapInfo.get(light);\r\n if (!shadowMapParams || !shadowMapParams.shadowMap) {\r\n continue;\r\n }\r\n // Record where this light lives in the mask so downstream samplers (e.g.\r\n // the SSS combine pass) can read its channel without recomputing shadows.\r\n shadowMapParams.maskOrdinal = ordinal;\r\n ctx.currentShadowLight = light;\r\n this.renderLightChannel(ctx, depthTexture, light, shadowMapParams, channelStates[channel]);\r\n }\r\n }\r\n device.popDeviceStates();\r\n ctx.currentShadowLight = savedShadowLight;\r\n }\r\n\r\n /** Render one shadow light into one color channel of the current framebuffer. */\r\n private renderLightChannel(\r\n ctx: DrawContext,\r\n depthTexture: Texture2D,\r\n light: PunctualLight,\r\n shadowMapParams: ShadowMapParams,\r\n renderState: RenderStateSet\r\n ): void {\r\n const device = ctx.device;\r\n const key = this.getProgramKey(ctx, shadowMapParams);\r\n let program = this._programs.get(key) ?? null;\r\n let bindGroup = this._bindGroups.get(key) ?? null;\r\n if (!program) {\r\n program = this.createProgram(ctx, shadowMapParams);\r\n bindGroup = device.createBindGroup(program.bindGroupLayouts[0]);\r\n this._programs.set(key, program);\r\n this._bindGroups.set(key, bindGroup);\r\n }\r\n bindGroup = this._bindGroups.get(key)!;\r\n this.setUniforms(bindGroup, ctx, depthTexture, light, shadowMapParams);\r\n device.setProgram(program);\r\n device.setBindGroup(0, bindGroup);\r\n drawFullscreenQuad(renderState);\r\n }\r\n\r\n /**\r\n * The program signature: distinct shadow implementations, cascade counts and\r\n * shadow map types must not share a compiled program.\r\n */\r\n private getProgramKey(ctx: DrawContext, shadowMapParams: ShadowMapParams): string {\r\n return `${ctx.device.type}|${shadowMapParams.shaderHash}`;\r\n }\r\n\r\n private getChannelStates(device: AbstractDevice): RenderStateSet[] {\r\n if (!this._channelStates) {\r\n this._channelStates = [];\r\n for (let c = 0; c < SHADOW_MASK_LIGHTS_PER_LAYER; c++) {\r\n const rs = device.createRenderStateSet();\r\n rs.useDepthState().enableTest(false).enableWrite(false);\r\n rs.useRasterizerState().setCullMode('none');\r\n rs.useColorState().setColorMask(c === 0, c === 1, c === 2, c === 3);\r\n this._channelStates.push(rs);\r\n }\r\n }\r\n return this._channelStates;\r\n }\r\n\r\n private setUniforms(\r\n bindGroup: BindGroup,\r\n ctx: DrawContext,\r\n depthTexture: Texture2D,\r\n light: PunctualLight,\r\n shadowMapParams: ShadowMapParams\r\n ): void {\r\n const camera = ctx.camera;\r\n const near = camera.getNearPlane();\r\n const far = camera.getFarPlane();\r\n const cameraPos = camera.getWorldPosition();\r\n this._cameraPosition.setXYZW(cameraPos.x, cameraPos.y, cameraPos.z, 0);\r\n this._cameraParams.setXYZW(near, far, 1, 1);\r\n this._nearFar.setXY(near, far);\r\n bindGroup.setValue('camera', {\r\n position: this._cameraPosition,\r\n params: this._cameraParams,\r\n shadowDebugCascades: camera.shadowDebugCascades ? 1 : 0,\r\n framestamp: ctx.device.frameInfo.frameCounter\r\n });\r\n // Full shadow light struct (matches helper.ts currentShadowLight lightStruct,\r\n // including implParams which PCSS/VSM impls read via getShadowImplParams).\r\n const implParams = new Vector4();\r\n shadowMapParams.impl!.getParams(implParams);\r\n bindGroup.setValue('light', {\r\n sunDir: ctx.sunLight\r\n ? ctx.sunLight.directionAndCutoff.xyz().scaleBy(-1)\r\n : new Vector4(0, 1, 0, 0).xyz(),\r\n shadowCascades: shadowMapParams.numShadowCascades,\r\n positionAndRange: light.positionAndRange,\r\n directionAndCutoff: light.directionAndCutoff,\r\n diffuseAndIntensity: light.diffuseAndIntensity,\r\n extraParams: light.extraParams,\r\n cascadeDistances: shadowMapParams.cascadeDistances,\r\n depthBiasValues: shadowMapParams.depthBiasValues[0],\r\n shadowCameraParams: shadowMapParams.cameraParams,\r\n depthBiasScales: shadowMapParams.depthBiasScales,\r\n implParams: implParams,\r\n shadowMatrices: new Float32Array(shadowMapParams.shadowMatrices),\r\n shadowStrength: light.shadow.shadowStrength,\r\n envLightStrength: ctx.env?.light.strength ?? 0,\r\n envLightSpecularStrength: ctx.env?.light.specularStrength ?? 1\r\n });\r\n bindGroup.setValue('invViewProjMatrix', camera.invViewProjectionMatrix);\r\n bindGroup.setValue('cameraNearFar', this._nearFar);\r\n bindGroup.setValue('flip', this.needFlip(ctx.device) ? 1 : 0);\r\n bindGroup.setTexture('depthTex', depthTexture);\r\n bindGroup.setTexture(\r\n UNIFORM_NAME_SHADOW_MAP,\r\n shadowMapParams.shadowMap!,\r\n shadowMapParams.shadowMapSampler\r\n );\r\n }\r\n\r\n /**\r\n * Whether the fullscreen output needs a vertical flip. Mask array layers are\r\n * offscreen render targets, so the convention matches other offscreen passes\r\n * (no flip); WebGPU still flips clip-space Y in the vertex shader.\r\n */\r\n private needFlip(_device: AbstractDevice): boolean {\r\n return false;\r\n }\r\n\r\n private createProgram(ctx: DrawContext, shadowMapParams: ShadowMapParams): GPUProgram {\r\n const device = ctx.device;\r\n const numCascades = shadowMapParams.numShadowCascades;\r\n const shadowMap = shadowMapParams.shadowMap!;\r\n const program = device.buildRenderProgram({\r\n label: 'ShadowMask',\r\n vertex(pb) {\r\n this.flip = pb.int().uniform(0);\r\n this.$inputs.pos = pb.vec2().attrib('position');\r\n this.$outputs.uv = pb.vec2();\r\n pb.main(function () {\r\n this.$builtins.position = pb.vec4(this.$inputs.pos, 1, 1);\r\n this.$outputs.uv = pb.add(pb.mul(this.$inputs.pos.xy, 0.5), pb.vec2(0.5));\r\n this.$if(pb.notEqual(this.flip, 0), function () {\r\n this.$builtins.position.y = pb.neg(this.$builtins.position.y);\r\n });\r\n if (device.type === 'webgpu') {\r\n this.$builtins.position.y = pb.neg(this.$builtins.position.y);\r\n }\r\n });\r\n },\r\n fragment(pb) {\r\n const cameraStruct = pb.defineStruct([\r\n pb.vec4('position'),\r\n pb.vec4('params'),\r\n pb.float('shadowDebugCascades'),\r\n // Required by PCSS temporal jitter (ShaderHelper.getFramestamp).\r\n pb.int('framestamp')\r\n ]);\r\n // Must match helper.ts currentShadowLight lightStruct field-for-field.\r\n const lightStruct = pb.defineStruct([\r\n pb.vec3('sunDir'),\r\n pb.int('shadowCascades'),\r\n pb.vec4('positionAndRange'),\r\n pb.vec4('directionAndCutoff'),\r\n pb.vec4('diffuseAndIntensity'),\r\n pb.vec4('extraParams'),\r\n pb.vec4('cascadeDistances'),\r\n pb.vec4('depthBiasValues'),\r\n pb.vec4('shadowCameraParams'),\r\n pb.vec4('depthBiasScales'),\r\n pb.vec4('implParams'),\r\n pb.vec4[16]('shadowMatrices'),\r\n pb.float('shadowStrength'),\r\n pb.float('envLightStrength'),\r\n pb.float('envLightSpecularStrength')\r\n ]);\r\n this.camera = cameraStruct().uniform(0);\r\n this.light = lightStruct().uniform(0);\r\n const shadowTex = shadowMap.isTextureCube()\r\n ? shadowMap.isDepth()\r\n ? pb.texCubeShadow()\r\n : pb.texCube()\r\n : shadowMap.isTexture2D()\r\n ? shadowMap.isDepth()\r\n ? pb.tex2DShadow()\r\n : pb.tex2D()\r\n : shadowMap.isDepth()\r\n ? pb.tex2DArrayShadow()\r\n : pb.tex2DArray();\r\n if (\r\n !shadowMap.isDepth() &&\r\n !device.getDeviceCaps().textureCaps.getTextureFormatInfo(shadowMap.format).filterable\r\n ) {\r\n shadowTex.sampleType('unfilterable-float');\r\n }\r\n this[UNIFORM_NAME_SHADOW_MAP] = shadowTex.uniform(0);\r\n this.depthTex = pb.tex2D().uniform(0);\r\n this.invViewProjMatrix = pb.mat4().uniform(0);\r\n this.cameraNearFar = pb.vec2().uniform(0);\r\n this.$outputs.color = pb.vec4();\r\n // Explicit-depth cascade selection (fragCoord.z is invalid in a fullscreen\r\n // pass). Mirrors posteffect/sss.ts calculateTransmissionShadow.\r\n pb.func(\r\n 'zShadowMaskFactor',\r\n [pb.vec3('worldPos'), pb.float('depth01'), pb.float('NoL')],\r\n function () {\r\n if (numCascades > 1) {\r\n this.$l.linearDepth = pb.mul(this.depth01, this.camera.params.y);\r\n this.$l.splitDistances = this.light.cascadeDistances;\r\n this.$l.comparison = pb.vec4(pb.greaterThan(pb.vec4(this.linearDepth), this.splitDistances));\r\n this.$l.cascadeFlags = pb.vec4(\r\n pb.float(pb.greaterThan(this.light.shadowCascades, 0)),\r\n pb.float(pb.greaterThan(this.light.shadowCascades, 1)),\r\n pb.float(pb.greaterThan(this.light.shadowCascades, 2)),\r\n pb.float(pb.greaterThan(this.light.shadowCascades, 3))\r\n );\r\n this.$l.split = pb.int(pb.dot(this.comparison, this.cascadeFlags));\r\n if (device.type === 'webgl') {\r\n this.$l.shadowVertex = pb.vec4();\r\n this.$for(pb.int('cascade'), 0, 4, function () {\r\n this.$if(pb.equal(this.cascade, this.split), function () {\r\n this.shadowVertex = ShaderHelper.calculateShadowSpaceVertex(\r\n this,\r\n pb.vec4(this.worldPos, 1),\r\n this.cascade\r\n );\r\n this.$break();\r\n });\r\n });\r\n } else {\r\n this.$l.shadowVertex = ShaderHelper.calculateShadowSpaceVertex(\r\n this,\r\n pb.vec4(this.worldPos, 1),\r\n this.split\r\n );\r\n }\r\n this.$l.shadow = shadowMapParams.impl!.computeShadowCSM(\r\n shadowMapParams,\r\n this,\r\n this.shadowVertex,\r\n this.NoL,\r\n this.split\r\n );\r\n this.$l.shadowDistance = this.light.shadowCameraParams.w;\r\n this.shadow = pb.mix(\r\n this.shadow,\r\n 1,\r\n pb.smoothStep(\r\n pb.mul(this.shadowDistance, 0.8),\r\n this.shadowDistance,\r\n pb.distance(this.camera.position.xyz, this.worldPos)\r\n )\r\n );\r\n this.shadow = pb.mix(1, this.shadow, this.light.shadowStrength);\r\n this.$return(pb.clamp(this.shadow, 0, 1));\r\n } else {\r\n this.$l.shadowVertex = ShaderHelper.calculateShadowSpaceVertex(this, pb.vec4(this.worldPos, 1));\r\n this.$l.shadow = shadowMapParams.impl!.computeShadow(\r\n shadowMapParams,\r\n this,\r\n this.shadowVertex,\r\n this.NoL\r\n );\r\n this.$l.shadowDistance = this.light.shadowCameraParams.w;\r\n this.shadow = pb.mix(\r\n this.shadow,\r\n 1,\r\n pb.smoothStep(\r\n pb.mul(this.shadowDistance, 0.8),\r\n this.shadowDistance,\r\n pb.distance(this.camera.position.xyz, this.worldPos)\r\n )\r\n );\r\n this.shadow = pb.mix(1, this.shadow, this.light.shadowStrength);\r\n this.$return(pb.clamp(this.shadow, 0, 1));\r\n }\r\n }\r\n );\r\n pb.main(function () {\r\n this.$l.pos = ShaderHelper.samplePositionFromDepth(\r\n this,\r\n this.depthTex,\r\n this.$inputs.uv,\r\n this.invViewProjMatrix,\r\n this.cameraNearFar\r\n );\r\n // NoL is unavailable in a fullscreen pass (no geometric normal); it only\r\n // feeds normal-offset bias, so a conservative 1.0 is used.\r\n this.$l.factor = this.zShadowMaskFactor(this.pos.xyz, this.pos.w, pb.float(1));\r\n this.$outputs.color = pb.vec4(this.factor);\r\n });\r\n }\r\n })!;\r\n program.name = '@ShadowMask';\r\n return program;\r\n }\r\n\r\n /** Release cached GPU resources. */\r\n dispose(): void {\r\n for (const program of this._programs.values()) {\r\n program.dispose();\r\n }\r\n this._programs.clear();\r\n this._bindGroups.clear();\r\n this._channelStates = null;\r\n }\r\n}\r\n\r\n/** Shared type alias to keep the mask factor accessor discoverable. */\r\nexport type ShadowMaskFactorExp = PBShaderExp;\r\n"],"names":["UNIFORM_NAME_SHADOW_MAP","SHADOW_MASK_LIGHTS_PER_LAYER","MAX_SHADOW_MASK_LAYERS","MAX_SHADOW_MASK_LIGHTS","ShadowMaskRenderer","_nearFar","_cameraPosition","_cameraParams","_programs","Map","_bindGroups","_channelStates","Vector2","Vector4","getLayerCount","numLights","n","Math","min","ceil","render","ctx","depthTexture","lights","getLayerFramebuffer","device","length","shadowMapInfo","numLayers","channelStates","getChannelStates","savedShadowLight","currentShadowLight","pushDeviceStates","layer","framebuffer","setFramebuffer","clearFrameBuffer","channel","ordinal","light","shadowMapParams","get","shadowMap","maskOrdinal","renderLightChannel","popDeviceStates","renderState","key","getProgramKey","program","bindGroup","createProgram","createBindGroup","bindGroupLayouts","set","setUniforms","setProgram","setBindGroup","drawFullscreenQuad","type","shaderHash","c","rs","createRenderStateSet","useDepthState","enableTest","enableWrite","useRasterizerState","setCullMode","useColorState","setColorMask","push","camera","near","getNearPlane","far","getFarPlane","cameraPos","getWorldPosition","setXYZW","x","y","z","setXY","setValue","position","params","shadowDebugCascades","framestamp","frameInfo","frameCounter","implParams","impl","getParams","sunDir","sunLight","directionAndCutoff","xyz","scaleBy","shadowCascades","numShadowCascades","positionAndRange","diffuseAndIntensity","extraParams","cascadeDistances","depthBiasValues","shadowCameraParams","cameraParams","depthBiasScales","shadowMatrices","Float32Array","shadowStrength","shadow","envLightStrength","env","strength","envLightSpecularStrength","specularStrength","invViewProjectionMatrix","needFlip","setTexture","shadowMapSampler","_device","numCascades","buildRenderProgram","label","vertex","pb","flip","int","uniform","$inputs","pos","vec2","attrib","$outputs","uv","main","$builtins","vec4","add","mul","xy","$if","notEqual","neg","fragment","cameraStruct","defineStruct","float","lightStruct","vec3","shadowTex","isTextureCube","isDepth","texCubeShadow","texCube","isTexture2D","tex2DShadow","tex2D","tex2DArrayShadow","tex2DArray","getDeviceCaps","textureCaps","getTextureFormatInfo","format","filterable","sampleType","depthTex","invViewProjMatrix","mat4","cameraNearFar","color","func","$l","linearDepth","depth01","splitDistances","comparison","greaterThan","cascadeFlags","split","dot","shadowVertex","$for","equal","cascade","ShaderHelper","calculateShadowSpaceVertex","worldPos","$break","computeShadowCSM","NoL","shadowDistance","w","mix","smoothStep","distance","$return","clamp","computeShadow","samplePositionFromDepth","factor","zShadowMaskFactor","name","dispose","values","clear"],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Animated interleaved-gradient-noise pair used to decorrelate SSGI rays.
3
+ *
4
+ * Produces two low-discrepancy random numbers in [0, 1) for a given fragment,
5
+ * advanced per sample/frame through golden-ratio sequences so the temporal
6
+ * resolve pass converges the Monte-Carlo estimate.
7
+ *
8
+ * @param scope - The shader scope
9
+ * @param fragCoord - Fragment coordinate in pixels
10
+ * @param seed - Sequence index (frameIndex * sampleCount + sampleIndex)
11
+ * @returns A vec2 of pseudo random numbers in [0, 1)
12
+ *
13
+ * @internal
14
+ */ function SSGI_rand2(scope, fragCoord, seed) {
15
+ const pb = scope.$builder;
16
+ pb.func('SSGI_ign', [
17
+ pb.vec2('p')
18
+ ], function() {
19
+ this.$return(pb.fract(pb.mul(52.9829189, pb.fract(pb.add(pb.mul(0.06711056, this.p.x), pb.mul(0.00583715, this.p.y))))));
20
+ });
21
+ pb.func('SSGI_rand2', [
22
+ pb.vec2('fragCoord'),
23
+ pb.float('seed')
24
+ ], function() {
25
+ this.$l.n1 = this.SSGI_ign(this.fragCoord);
26
+ this.$l.n2 = this.SSGI_ign(pb.add(this.fragCoord, pb.vec2(5.588238, 5.588238)));
27
+ // Golden-ratio (and its square) sequences advance the pair every sample
28
+ this.$return(pb.fract(pb.add(pb.vec2(this.n1, this.n2), pb.mul(pb.vec2(0.61803398875, 0.38196601125), this.seed))));
29
+ });
30
+ return scope.SSGI_rand2(fragCoord, seed);
31
+ }
32
+ /**
33
+ * Cosine-weighted hemisphere sampling around a normal.
34
+ *
35
+ * With cosine-weighted sampling the Monte-Carlo estimator of the rendering
36
+ * equation's diffuse term reduces to the plain average of the sampled
37
+ * radiances, so the SSGI trace pass can simply accumulate hit colors.
38
+ *
39
+ * @param scope - The shader scope
40
+ * @param normal - Unit normal the hemisphere is oriented around
41
+ * @param rand - Two random numbers in [0, 1)
42
+ * @returns A unit direction inside the hemisphere
43
+ *
44
+ * @internal
45
+ */ function SSGI_cosineSampleHemisphere(scope, normal, rand) {
46
+ const pb = scope.$builder;
47
+ pb.func('SSGI_cosineSampleHemisphere', [
48
+ pb.vec3('n'),
49
+ pb.vec2('u')
50
+ ], function() {
51
+ this.$l.up = this.$choice(pb.lessThan(pb.abs(this.n.z), 0.999), pb.vec3(0, 0, 1), pb.vec3(1, 0, 0));
52
+ this.$l.tangent = pb.normalize(pb.cross(this.up, this.n));
53
+ this.$l.bitangent = pb.cross(this.n, this.tangent);
54
+ this.$l.r = pb.sqrt(this.u.x);
55
+ this.$l.phi = pb.mul(this.u.y, Math.PI * 2);
56
+ this.$l.dir = pb.add(pb.mul(this.tangent, pb.mul(this.r, pb.cos(this.phi))), pb.mul(this.bitangent, pb.mul(this.r, pb.sin(this.phi))), pb.mul(this.n, pb.sqrt(pb.max(0, pb.sub(1, this.u.x)))));
57
+ this.$return(pb.normalize(this.dir));
58
+ });
59
+ return scope.SSGI_cosineSampleHemisphere(normal, rand);
60
+ }
61
+
62
+ export { SSGI_cosineSampleHemisphere, SSGI_rand2 };
63
+ //# sourceMappingURL=ssgi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssgi.js","sources":["../../src/shaders/ssgi.ts"],"sourcesContent":["import type { PBInsideFunctionScope, PBShaderExp } from '@zephyr3d/device';\n\n/**\n * Animated interleaved-gradient-noise pair used to decorrelate SSGI rays.\n *\n * Produces two low-discrepancy random numbers in [0, 1) for a given fragment,\n * advanced per sample/frame through golden-ratio sequences so the temporal\n * resolve pass converges the Monte-Carlo estimate.\n *\n * @param scope - The shader scope\n * @param fragCoord - Fragment coordinate in pixels\n * @param seed - Sequence index (frameIndex * sampleCount + sampleIndex)\n * @returns A vec2 of pseudo random numbers in [0, 1)\n *\n * @internal\n */\nexport function SSGI_rand2(scope: PBInsideFunctionScope, fragCoord: PBShaderExp, seed: PBShaderExp) {\n const pb = scope.$builder;\n pb.func('SSGI_ign', [pb.vec2('p')], function () {\n this.$return(\n pb.fract(\n pb.mul(52.9829189, pb.fract(pb.add(pb.mul(0.06711056, this.p.x), pb.mul(0.00583715, this.p.y))))\n )\n );\n });\n pb.func('SSGI_rand2', [pb.vec2('fragCoord'), pb.float('seed')], function () {\n this.$l.n1 = this.SSGI_ign(this.fragCoord);\n this.$l.n2 = this.SSGI_ign(pb.add(this.fragCoord, pb.vec2(5.588238, 5.588238)));\n // Golden-ratio (and its square) sequences advance the pair every sample\n this.$return(\n pb.fract(pb.add(pb.vec2(this.n1, this.n2), pb.mul(pb.vec2(0.61803398875, 0.38196601125), this.seed)))\n );\n });\n return scope.SSGI_rand2(fragCoord, seed);\n}\n\n/**\n * Cosine-weighted hemisphere sampling around a normal.\n *\n * With cosine-weighted sampling the Monte-Carlo estimator of the rendering\n * equation's diffuse term reduces to the plain average of the sampled\n * radiances, so the SSGI trace pass can simply accumulate hit colors.\n *\n * @param scope - The shader scope\n * @param normal - Unit normal the hemisphere is oriented around\n * @param rand - Two random numbers in [0, 1)\n * @returns A unit direction inside the hemisphere\n *\n * @internal\n */\nexport function SSGI_cosineSampleHemisphere(\n scope: PBInsideFunctionScope,\n normal: PBShaderExp,\n rand: PBShaderExp\n) {\n const pb = scope.$builder;\n pb.func('SSGI_cosineSampleHemisphere', [pb.vec3('n'), pb.vec2('u')], function () {\n this.$l.up = this.$choice(pb.lessThan(pb.abs(this.n.z), 0.999), pb.vec3(0, 0, 1), pb.vec3(1, 0, 0));\n this.$l.tangent = pb.normalize(pb.cross(this.up, this.n));\n this.$l.bitangent = pb.cross(this.n, this.tangent);\n this.$l.r = pb.sqrt(this.u.x);\n this.$l.phi = pb.mul(this.u.y, Math.PI * 2);\n this.$l.dir = pb.add(\n pb.mul(this.tangent, pb.mul(this.r, pb.cos(this.phi))),\n pb.mul(this.bitangent, pb.mul(this.r, pb.sin(this.phi))),\n pb.mul(this.n, pb.sqrt(pb.max(0, pb.sub(1, this.u.x))))\n );\n this.$return(pb.normalize(this.dir));\n });\n return scope.SSGI_cosineSampleHemisphere(normal, rand);\n}\n"],"names":["SSGI_rand2","scope","fragCoord","seed","pb","$builder","func","vec2","$return","fract","mul","add","p","x","y","float","$l","n1","SSGI_ign","n2","SSGI_cosineSampleHemisphere","normal","rand","vec3","up","$choice","lessThan","abs","n","z","tangent","normalize","cross","bitangent","r","sqrt","u","phi","Math","PI","dir","cos","sin","max","sub"],"mappings":"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"}
@@ -268,7 +268,9 @@ class BlurBlitter extends GaussianBlurBlitter {
268
268
  getShaderHash() {
269
269
  return `${this._blur ? 1 : 0}${this._logSpace ? 1 : 0}`;
270
270
  }
271
- getParams() {}
271
+ getParams(out) {
272
+ return out ?? Vector4.zero();
273
+ }
272
274
  getShadowMapColorFormat(_shadowMapParams) {
273
275
  const device = getDevice();
274
276
  return device.getDeviceCaps().textureCaps.supportFloatColorBuffer && device.getDeviceCaps().textureCaps.supportLinearFloatTexture ? device.type === 'webgl' ? 'rgba32f' : 'rg32f' : device.getDeviceCaps().textureCaps.supportHalfFloatColorBuffer && device.getDeviceCaps().textureCaps.supportLinearHalfFloatTexture ? device.type === 'webgl' ? 'rgba16f' : 'rg16f' : 'rgba8unorm';