@forgeax/engine-render 0.1.30 → 0.1.32

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 (118) hide show
  1. package/README.md +68 -1
  2. package/dist/assembly/webgpu-ready.d.ts +2 -1
  3. package/dist/assembly/webgpu-ready.d.ts.map +1 -1
  4. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  5. package/dist/{chunk-C3DDSXYK.mjs → chunk-4NNZQCL3.mjs} +110 -35
  6. package/dist/chunk-4NNZQCL3.mjs.map +1 -0
  7. package/dist/{chunk-JRBDO2KB.mjs → chunk-6TFBXLRJ.mjs} +19 -7
  8. package/dist/chunk-6TFBXLRJ.mjs.map +1 -0
  9. package/dist/{chunk-FUUO4UND.mjs → chunk-DRR7D3KX.mjs} +3 -3
  10. package/dist/chunk-DRR7D3KX.mjs.map +1 -0
  11. package/dist/{chunk-S5UE2T5P.mjs → chunk-GWCEMDVR.mjs} +380 -4
  12. package/dist/chunk-GWCEMDVR.mjs.map +1 -0
  13. package/dist/{chunk-MDQJPY3T.mjs → chunk-JCIRYQ4V.mjs} +3 -3
  14. package/dist/{chunk-MDQJPY3T.mjs.map → chunk-JCIRYQ4V.mjs.map} +1 -1
  15. package/dist/{chunk-PSEQ6QPH.mjs → chunk-JRIPCMYC.mjs} +17 -10
  16. package/dist/chunk-JRIPCMYC.mjs.map +1 -0
  17. package/dist/{chunk-7MQ3XBSP.mjs → chunk-LULCA3OF.mjs} +4 -4
  18. package/dist/{chunk-7MQ3XBSP.mjs.map → chunk-LULCA3OF.mjs.map} +1 -1
  19. package/dist/{chunk-NO4WZCAH.mjs → chunk-S665NJNF.mjs} +3 -3
  20. package/dist/{chunk-NO4WZCAH.mjs.map → chunk-S665NJNF.mjs.map} +1 -1
  21. package/dist/components/depth-of-field.d.ts +28 -0
  22. package/dist/components/depth-of-field.d.ts.map +1 -0
  23. package/dist/components/directional-light.d.ts +2 -1
  24. package/dist/components/directional-light.d.ts.map +1 -1
  25. package/dist/components/index.d.ts +1 -0
  26. package/dist/components/index.d.ts.map +1 -1
  27. package/dist/construct-renderer.mjs +898 -328
  28. package/dist/construct-renderer.mjs.map +1 -1
  29. package/dist/extract/camera.d.ts.map +1 -1
  30. package/dist/features/depth-of-field/depth-of-field-assembly.d.ts +19 -0
  31. package/dist/features/depth-of-field/depth-of-field-assembly.d.ts.map +1 -0
  32. package/dist/features/depth-of-field/depth-of-field-feature.d.ts +43 -0
  33. package/dist/features/depth-of-field/depth-of-field-feature.d.ts.map +1 -0
  34. package/dist/features/depth-of-field/depth-of-field-inspection.d.ts +34 -0
  35. package/dist/features/depth-of-field/depth-of-field-inspection.d.ts.map +1 -0
  36. package/dist/features/depth-of-field/depth-of-field-params.d.ts +83 -0
  37. package/dist/features/depth-of-field/depth-of-field-params.d.ts.map +1 -0
  38. package/dist/features/types.d.ts +19 -1
  39. package/dist/features/types.d.ts.map +1 -1
  40. package/dist/index.d.ts +4 -2
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.mjs +6 -5
  43. package/dist/index.mjs.map +1 -1
  44. package/dist/inspection-types.d.ts +35 -0
  45. package/dist/inspection-types.d.ts.map +1 -1
  46. package/dist/instances.d.ts +7 -0
  47. package/dist/instances.d.ts.map +1 -1
  48. package/dist/internal.mjs +6 -6
  49. package/dist/mesh-material-bindings.d.ts +3 -0
  50. package/dist/mesh-material-bindings.d.ts.map +1 -1
  51. package/dist/pipeline/standard-output/graph.d.ts.map +1 -1
  52. package/dist/pipeline/standard-output/types.d.ts +4 -2
  53. package/dist/pipeline/standard-output/types.d.ts.map +1 -1
  54. package/dist/pipeline/standard-post.d.ts.map +1 -1
  55. package/dist/plugin.d.ts.map +1 -1
  56. package/dist/record/frame-snapshot.d.ts +21 -1
  57. package/dist/record/frame-snapshot.d.ts.map +1 -1
  58. package/dist/record/frame.d.ts.map +1 -1
  59. package/dist/record/main-pass.d.ts.map +1 -1
  60. package/dist/record/typed-frame-graph.d.ts +7 -0
  61. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  62. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  63. package/dist/render-contract.d.ts +8 -1
  64. package/dist/render-contract.d.ts.map +1 -1
  65. package/dist/render-graph-primitives.d.ts +2 -0
  66. package/dist/render-graph-primitives.d.ts.map +1 -1
  67. package/dist/render-pipeline.d.ts +13 -1
  68. package/dist/render-pipeline.d.ts.map +1 -1
  69. package/dist/render-system-extract-tail.d.ts.map +1 -1
  70. package/dist/render-system-extract.d.ts +18 -4
  71. package/dist/render-system-extract.d.ts.map +1 -1
  72. package/dist/render-system.d.ts +2 -1
  73. package/dist/render-system.d.ts.map +1 -1
  74. package/dist/temporal/index.mjs +5 -5
  75. package/dist/typed-render-graph-primitives.d.ts.map +1 -1
  76. package/package.json +21 -21
  77. package/src/__tests__/gpu-driven-baseline.characterization.test.ts +12 -0
  78. package/src/__tests__/gpu-driven-production.integration.test.ts +27 -1
  79. package/src/__tests__/instances-store.unit.test.ts +15 -0
  80. package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +28 -0
  81. package/src/assembly/webgpu-ready.ts +5 -5
  82. package/src/assembly/webgpu-renderer.ts +14 -14
  83. package/src/components/depth-of-field.ts +45 -0
  84. package/src/components/directional-light.ts +2 -1
  85. package/src/components/index.ts +1 -0
  86. package/src/extract/camera.ts +22 -2
  87. package/src/features/depth-of-field/__tests__/depth-of-field-params.unit.test.ts +943 -0
  88. package/src/features/depth-of-field/depth-of-field-assembly.ts +100 -0
  89. package/src/features/depth-of-field/depth-of-field-feature.ts +295 -0
  90. package/src/features/depth-of-field/depth-of-field-inspection.ts +237 -0
  91. package/src/features/depth-of-field/depth-of-field-params.ts +556 -0
  92. package/src/features/host.ts +1 -1
  93. package/src/features/types.ts +18 -1
  94. package/src/index.ts +32 -0
  95. package/src/inspection-types.ts +38 -0
  96. package/src/instances.ts +19 -5
  97. package/src/mesh-material-bindings.ts +4 -0
  98. package/src/pipeline/standard-output/graph.ts +3 -0
  99. package/src/pipeline/standard-output/types.ts +4 -1
  100. package/src/pipeline/standard-post.ts +21 -2
  101. package/src/plugin.ts +2 -0
  102. package/src/record/frame-snapshot.ts +26 -1
  103. package/src/record/frame.ts +39 -6
  104. package/src/record/main-pass.ts +1 -5
  105. package/src/record/typed-frame-graph.ts +106 -6
  106. package/src/recovery/render-system-candidate.ts +6 -0
  107. package/src/render-contract.ts +11 -0
  108. package/src/render-graph-primitives.ts +8 -1
  109. package/src/render-pipeline.ts +17 -1
  110. package/src/render-system-extract-tail.ts +87 -13
  111. package/src/render-system-extract.ts +103 -25
  112. package/src/render-system.ts +78 -0
  113. package/src/typed-render-graph-primitives.ts +3 -0
  114. package/dist/chunk-C3DDSXYK.mjs.map +0 -1
  115. package/dist/chunk-FUUO4UND.mjs.map +0 -1
  116. package/dist/chunk-JRBDO2KB.mjs.map +0 -1
  117. package/dist/chunk-PSEQ6QPH.mjs.map +0 -1
  118. package/dist/chunk-S5UE2T5P.mjs.map +0 -1
package/README.md CHANGED
@@ -101,6 +101,14 @@ plan. Register it at construction with
101
101
  `createRenderer(canvas, { features: [feature] })`. A feature never receives a
102
102
  device, queue, encoder, staging builder, or submit callback.
103
103
 
104
+ After a frame reaches queue submission, the optional `onFrameSubmitted` callback
105
+ receives a bounded `RenderFeatureSubmission` projection. Its `passes` contain
106
+ only work admitted after prepared-resource resolution, so producer diagnostics
107
+ can distinguish submitted compute dispatches and graphics draws from a plan
108
+ that was still pending. This is a receipt of admitted commands, not a GPU
109
+ readback or proof that an indirect draw produced non-zero instances; producers
110
+ that need those facts must use their existing readback or tape evidence.
111
+
104
112
  ## RenderFeature: the producer seam (first-read index)
105
113
 
106
114
  The public route is one `RenderFeature<FrameData>` through the active RenderGraph
@@ -157,6 +165,13 @@ surface receiver position along its world-space normal before projection (defaul
157
165
  Normal offset and depth bias are independent: increasing the CSM depth span must
158
166
  not magnify the world-space normal offset. Both PCF and PCSS project the offset
159
167
  receiver; volumetric samples have no surface normal and use only depth bias.
168
+ Surface receivers also get a per-cascade depth correction derived from the
169
+ world size of a shadow texel, the filter footprint, and the receiver's depth
170
+ slope along the light's two image axes. The existing normal offset counts
171
+ toward this coverage; only the missing amount is added to `depthBias`, after
172
+ conversion through that cascade's light-space depth span. PCSS derives its
173
+ blocker-search and comparison coverage separately from their actual radii.
174
+ This does not change either author field's units or add shadow texture taps.
160
175
  Cascade projections include their incoming blend band, and PCSS depth spans
161
176
  match the actual projection, including toward-light caster reach. The normal
162
177
  position offset follows the approach in
@@ -1093,6 +1108,8 @@ renderer.instances.update(collection.collectionId, {
1093
1108
  renderer.instances.replace(collection.collectionId, identityMatrices(instanceCount + 1));
1094
1109
  const current = renderer.instances.inspect(collection.collectionId).unwrap();
1095
1110
  const detached = renderer.instances.snapshot(collection.collectionId).unwrap();
1111
+ // A read-only observation does not advance the renderer upload cursor.
1112
+ const observed = renderer.instances.peek(collection.collectionId).unwrap();
1096
1113
  renderer.instances.release(collection.collectionId);
1097
1114
  ```
1098
1115
 
@@ -1101,7 +1118,9 @@ storage, `replace` publishes a complete new revision (and grows capacity when
1101
1118
  needed), `update` validates a bounded matrix interval and records its dirty
1102
1119
  range, `inspect` returns identity/count/capacity/revision, `snapshot` returns a
1103
1120
  detached matrix copy plus dirty ranges for extraction, and `release` makes the
1104
- collection id terminal. A caller never provides a GPU buffer or maintains
1121
+ collection id terminal. `peek` returns the same detached matrices without
1122
+ advancing the renderer upload cursor, so read-only inspection cannot hide a
1123
+ later dirty range. A caller never provides a GPU buffer or maintains
1105
1124
  backend-specific chunks. `detached.transforms` is an observation, not mutable
1106
1125
  renderer state.
1107
1126
 
@@ -2303,3 +2322,51 @@ froxel depth, including the clipped final segment. It does not rotate density
2303
2322
  samples with frame number: static authored air must not create temporal noise.
2304
2323
  Shadow visibility uses matching froxel centers without per-frame XY jitter or
2305
2324
  stochastic byte dithering. Shared PCF shadow filtering remains in effect.
2325
+
2326
+ ## Camera Depth of Field
2327
+
2328
+ `DepthOfField` is the built-in Standard camera effect for ordinary meshes. Add it
2329
+ only to the active perspective camera; component removal or
2330
+ `maxRadiusPixels: 0` declares the exact zero-work path. The side and quality
2331
+ fields use the closed numeric values exported by this package:
2332
+
2333
+ ```ts
2334
+ import {
2335
+ DepthOfField,
2336
+ DepthOfFieldQualityValue,
2337
+ DepthOfFieldSideValue,
2338
+ } from '@forgeax/engine-render';
2339
+
2340
+ world.addComponent(camera, {
2341
+ component: DepthOfField,
2342
+ data: {
2343
+ focusDistance: 8,
2344
+ fStop: 1.4,
2345
+ sensorHeight: 0.024,
2346
+ maxRadiusPixels: 16,
2347
+ quality: DepthOfFieldQualityValue.medium,
2348
+ blurSide: DepthOfFieldSideValue.both,
2349
+ },
2350
+ });
2351
+ ```
2352
+
2353
+ The near, far and both presets share one signed thin-lens CoC. `quality` changes
2354
+ sampling density only, so it does not change the optical radius. The graph uses
2355
+ the Standard `RenderExtent`: full-resolution CoC/composite targets follow the
2356
+ current internal or output domain, and half-resolution targets use
2357
+ `max(1, ceil(axis / 2))`. Current temporal-v1 depth validity and the resolved
2358
+ multisampled depth binding remain the source of truth.
2359
+
2360
+ After a real `draw()` submission, read `renderer.inspect().depthOfField` for the
2361
+ requested component values, effective submitted values, graph/device
2362
+ generations, extents, pass count and descriptor-derived bytes. `lastKnownGood`
2363
+ and `effective` stay bound to the accepted submission; a failed candidate keeps
2364
+ the prior accepted projection and reports its failure reason for recovery.
2365
+ When the active camera has no `DepthOfField` component, the inspection remains
2366
+ available with `status: 'off'` and zero DoF graph facts. Invalid fields and an
2367
+ orthographic camera stay on the normal camera snapshot path with structured
2368
+ `error.code`, `error.expected`, `error.hint`, and `error.detail`; they report
2369
+ `status: 'invalid'` or `status: 'unsupported'` without admitting a DoF graph.
2370
+ The Engine Preview/game capability lab uses this same component on its ordinary
2371
+ mesh camera, and its settings control toggles component presence through the
2372
+ normal World path.
@@ -1,6 +1,7 @@
1
1
  import type { RenderPipeline, Result, RhiDevice, ShaderModule } from '@forgeax/engine-rhi';
2
2
  import { RhiError } from '@forgeax/engine-rhi';
3
3
  import { type ShaderCatalog } from '@forgeax/engine-shader';
4
+ import { prewarmDepthOfField } from '../features/depth-of-field/depth-of-field-assembly';
4
5
  export type { MaterialShaderManifestEntry } from '@forgeax/engine-shader';
5
6
  import type { GpuResidencyCache } from '../device/gpu-residency';
6
7
  import type { DeviceScope, RhiErrorListenerRegistry } from '../lifecycle';
@@ -49,7 +50,7 @@ requiredFullscreenPostProcesses: readonly {
49
50
  registerBuiltinFxaa: (source: string) => void, registerBuiltinTemporalPostProcesses: (entries: {
50
51
  readonly motionBlur?: string;
51
52
  readonly taaResolve?: string;
52
- }) => void,
53
+ }) => void, registerBuiltinDepthOfField: Parameters<typeof prewarmDepthOfField>[2],
53
54
  /** Install manifest-owned volume utility sources only after all four modules compile. */
54
55
  setVolumetricFogShaderSources: (sources: VolumetricFogShaderSources) => void,
55
56
  /** Install manifest-owned SSR utility sources only after all five modules compile. */
@@ -1 +1 @@
1
- {"version":3,"file":"webgpu-ready.d.ts","sourceRoot":"","sources":["../../src/assembly/webgpu-ready.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAKV,cAAc,EACd,MAAM,EACN,SAAS,EAET,YAAY,EACb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAM,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAM9E,YAAY,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAE1E,OAAO,KAAK,EAAE,iBAAiB,EAAkB,MAAM,yBAAyB,CAAC;AAwBjF,OAAO,KAAK,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAE1E,OAAO,EAGL,KAAK,sBAAsB,EAG5B,MAAM,iBAAiB,CAAC;AAmBzB,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,gBAAgB,EAErB,KAAK,0BAA0B,EAChC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,aAAa,EAEnB,MAAM,kBAAkB,CAAC;AAQ1B,OAAO,EAIL,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAEnB,MAAM,kBAAkB,CAAC;AAmB1B;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,WAAW,EAC1B,SAAS,EAAE,MAAM,aAAa,EAC9B,QAAQ,EAAE,iBAAiB,EAC3B,uBAAuB,EACnB,CAAC,CACC,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,KAC/C,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,GAC7C,SAAS,EACb,aAAa,EAAE,wBAAwB;AACvC;;;;GAIG;AACH,uBAAuB,EAAE,SAAS,MAAM,EAAE,EAC1C,2BAA2B,EAAE,MAAM;AACnC,8EAA8E;AAC9E,+BAA+B,EAAE,SAAS;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,EAAE,EAUH,mBAAmB,EAAE,CACnB,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,kBAAkB,EACjD,KAAK,EAAE,aAAa,KACjB,IAAI,EAQT,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,KAAK,IAAI,EAQ/D,+BAA+B,EAAE,CAC/B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,cAAc,EACnB,cAAc,EAAE,sBAAsB,KACnC,IAAI,EAST,sBAAsB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI;AAChD,sEAAsE;AACtE,mBAAmB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,EAC7C,oCAAoC,EAAE,CAAC,OAAO,EAAE;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B,KAAK,IAAI;AACV,yFAAyF;AACzF,6BAA6B,EAAE,CAAC,OAAO,EAAE,0BAA0B,KAAK,IAAI;AAC5E,sFAAsF;AACtF,mBAAmB,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI;AACxD,wFAAwF;AACxF,0BAA0B,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,IAAI,GACrE,OAAO,CAAC,aAAa,CAAC,CAyxHxB"}
1
+ {"version":3,"file":"webgpu-ready.d.ts","sourceRoot":"","sources":["../../src/assembly/webgpu-ready.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAKV,cAAc,EACd,MAAM,EACN,SAAS,EAET,YAAY,EACb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAM,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,oDAAoD,CAAC;AAIzF,YAAY,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAE1E,OAAO,KAAK,EAAE,iBAAiB,EAAkB,MAAM,yBAAyB,CAAC;AAwBjF,OAAO,KAAK,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAE1E,OAAO,EAGL,KAAK,sBAAsB,EAG5B,MAAM,iBAAiB,CAAC;AAmBzB,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,gBAAgB,EAErB,KAAK,0BAA0B,EAChC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAEL,KAAK,aAAa,EAEnB,MAAM,kBAAkB,CAAC;AAQ1B,OAAO,EAIL,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAEnB,MAAM,kBAAkB,CAAC;AAmB1B;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,WAAW,EAC1B,SAAS,EAAE,MAAM,aAAa,EAC9B,QAAQ,EAAE,iBAAiB,EAC3B,uBAAuB,EACnB,CAAC,CACC,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,KAC/C,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,GAC7C,SAAS,EACb,aAAa,EAAE,wBAAwB;AACvC;;;;GAIG;AACH,uBAAuB,EAAE,SAAS,MAAM,EAAE,EAC1C,2BAA2B,EAAE,MAAM;AACnC,8EAA8E;AAC9E,+BAA+B,EAAE,SAAS;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,EAAE,EAUH,mBAAmB,EAAE,CACnB,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,kBAAkB,EACjD,KAAK,EAAE,aAAa,KACjB,IAAI,EAQT,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,KAAK,IAAI,EAQ/D,+BAA+B,EAAE,CAC/B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,cAAc,EACnB,cAAc,EAAE,sBAAsB,KACnC,IAAI,EAST,sBAAsB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI;AAChD,sEAAsE;AACtE,mBAAmB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,EAC7C,oCAAoC,EAAE,CAAC,OAAO,EAAE;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B,KAAK,IAAI,EACV,2BAA2B,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAC;AACtE,yFAAyF;AACzF,6BAA6B,EAAE,CAAC,OAAO,EAAE,0BAA0B,KAAK,IAAI;AAC5E,sFAAsF;AACtF,mBAAmB,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI;AACxD,wFAAwF;AACxF,0BAA0B,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,IAAI,GACrE,OAAO,CAAC,aAAa,CAAC,CAuxHxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"webgpu-renderer.d.ts","sourceRoot":"","sources":["../../src/assembly/webgpu-renderer.ts"],"names":[],"mappings":"AAyCA,YAAY,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAqE1E,OAAO,KAAK,EAUV,eAAe,EAQhB,MAAM,oBAAoB,CAAC;AAgB5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAkEzD,YAAY,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAUlF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAUhE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,YAAY,EACV,UAAU,EACV,6BAA6B,EAC7B,iCAAiC,GAClC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,2BAA2B,EAC3B,oCAAoC,EACpC,iCAAiC,EACjC,uCAAuC,EACvC,oCAAoC,EACpC,+BAA+B,EAC/B,+BAA+B,EAC/B,wCAAwC,EACxC,uBAAuB,EACvB,8BAA8B,EAC9B,wCAAwC,GACzC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,EAC1B,4BAA4B,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAC/B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EACL,gCAAgC,EAChC,4BAA4B,EAC5B,0BAA0B,EAC1B,yBAAyB,EACzB,4CAA4C,GAC7C,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACzF,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAI7E,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,iBAAiB,GAAG,eAAe,EAC3C,OAAO,EAAE,eAAe,GAAG,SAAS,EACpC,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,cAAc,GAAG,SAAS,GAClC,OAAO,CAAC,aAAa,CAAC,CAExB"}
1
+ {"version":3,"file":"webgpu-renderer.d.ts","sourceRoot":"","sources":["../../src/assembly/webgpu-renderer.ts"],"names":[],"mappings":"AAyCA,YAAY,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAyE1E,OAAO,KAAK,EAUV,eAAe,EAQhB,MAAM,oBAAoB,CAAC;AAgB5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAkEzD,YAAY,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAUlF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAUhE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,YAAY,EACV,UAAU,EACV,6BAA6B,EAC7B,iCAAiC,GAClC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,2BAA2B,EAC3B,oCAAoC,EACpC,iCAAiC,EACjC,uCAAuC,EACvC,oCAAoC,EACpC,+BAA+B,EAC/B,+BAA+B,EAC/B,wCAAwC,EACxC,uBAAuB,EACvB,8BAA8B,EAC9B,wCAAwC,GACzC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,EAC1B,4BAA4B,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAC/B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EACL,gCAAgC,EAChC,4BAA4B,EAC5B,0BAA0B,EAC1B,yBAAyB,EACzB,4CAA4C,GAC7C,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACzF,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAI7E,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,iBAAiB,GAAG,eAAe,EAC3C,OAAO,EAAE,eAAe,GAAG,SAAS,EACpC,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,cAAc,GAAG,SAAS,GAClC,OAAO,CAAC,aAAa,CAAC,CAExB"}
@@ -1,8 +1,8 @@
1
1
  import { GlyphText } from './chunk-ILQ5MEZF.mjs';
2
- import { MeshRenderer, MeshFilter, DirectionalLight, validateDirectionalLightData, PointLight, computeInvRangeSquared, SpotLight, degToCos, RectAreaLight, validateRectAreaLightData, directionalShadowQualityFromF32, PointLightShadow, Skylight, LightProbe, validateLightProbeData, SkyboxBackground, Atmosphere, Instances, Layer, Points, Lines, SortKey, resolveMeshMaterialBindings, pointShapeFromU32, PostProcessParams, buildCubeCameraFaceViews, CubeCamera, cubeCameraUpdateIntentFromF32, ReflectionProbe, reflectionProbeUpdateIntentFromF32, tonemapToU32, resolveVisibility, Fog, VolumetricFog, resolveSelectedVolumetricLight, extractVolumetricFog, MotionBlur, DynamicResolution, ScreenSpaceReflection, Camera, CAMERA_EXPOSURE_MODE_MANUAL, cameraExposureFromColumns, antialiasFromF32, validateDynamicResolutionCamera, bloomEnabledFromF32, tonemapFromF32, cameraProjectionFromF32 } from './chunk-S5UE2T5P.mjs';
2
+ import { MeshRenderer, MeshFilter, DirectionalLight, validateDirectionalLightData, PointLight, computeInvRangeSquared, SpotLight, degToCos, RectAreaLight, validateRectAreaLightData, directionalShadowQualityFromF32, PointLightShadow, Skylight, LightProbe, validateLightProbeData, SkyboxBackground, Atmosphere, Instances, Layer, Points, Lines, SortKey, resolveMeshMaterialBindings, pointShapeFromU32, PostProcessParams, buildCubeCameraFaceViews, CubeCamera, cubeCameraUpdateIntentFromF32, ReflectionProbe, reflectionProbeUpdateIntentFromF32, tonemapToU32, resolveVisibility, Fog, VolumetricFog, resolveSelectedVolumetricLight, extractVolumetricFog, MotionBlur, DynamicResolution, ScreenSpaceReflection, DepthOfField, Camera, cameraProjectionFromF32, resolveDepthOfFieldParams, depthOfFieldRequestFailure, CAMERA_EXPOSURE_MODE_MANUAL, cameraExposureFromColumns, antialiasFromF32, validateDynamicResolutionCamera, bloomEnabledFromF32, tonemapFromF32 } from './chunk-GWCEMDVR.mjs';
3
3
  import { SpriteRegionOverride, SpriteInstances, selectActiveCameraIndex, getActiveCamera } from './chunk-PA5DRJNI.mjs';
4
- import { PROBE_BLEND_RECORD_CAPACITY, GPU_BUFFER_USAGE_MAP_READ, GPU_BUFFER_USAGE_VERTEX, GPU_BUFFER_USAGE_COPY_DST, gpuDrivenShadowDrawKey, IES_SLICE_CAPACITY, COOKIE_SLICE_CAPACITY, isStandardPbrSkinMaterialShader, buildGpuDrivenDraws, worldEntityKey, gpuDrivenSourceDrawItemIndex, selectPasses, resolveRenderTargetMaterialSource, isCanonicalStandardPbrMaterialShader, PROBE_BLEND_RECORD_BYTE_SIZE, GPU_BUFFER_USAGE_UNIFORM, GPU_BUFFER_USAGE_QUERY_RESOLVE, GPU_BUFFER_USAGE_COPY_SRC, COOKIE_SLICE_SIZE, isStandardPbrMaterialShader } from './chunk-FUUO4UND.mjs';
5
- import { STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, SHADOW_ATLAS_DEFAULT_LAYERS, SkinMaterialMismatchError, MaterialSkinAttrMissingError, InstanceCollectionError, ShadowInvalidConfigError, EnvironmentSourceConflictError, FogCardinalityError, GPU_TEXTURE_USAGE_COPY_SRC, GPU_TEXTURE_USAGE_COPY_DST, GPU_TEXTURE_USAGE_TEXTURE_BINDING, GPU_TEXTURE_USAGE_STORAGE_BINDING, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT, AtmosphereInvalidParameterError } from './chunk-JRBDO2KB.mjs';
4
+ import { PROBE_BLEND_RECORD_CAPACITY, GPU_BUFFER_USAGE_MAP_READ, GPU_BUFFER_USAGE_VERTEX, GPU_BUFFER_USAGE_COPY_DST, gpuDrivenShadowDrawKey, IES_SLICE_CAPACITY, COOKIE_SLICE_CAPACITY, isStandardPbrSkinMaterialShader, buildGpuDrivenDraws, worldEntityKey, gpuDrivenSourceDrawItemIndex, selectPasses, resolveRenderTargetMaterialSource, isCanonicalStandardPbrMaterialShader, PROBE_BLEND_RECORD_BYTE_SIZE, GPU_BUFFER_USAGE_UNIFORM, GPU_BUFFER_USAGE_QUERY_RESOLVE, GPU_BUFFER_USAGE_COPY_SRC, COOKIE_SLICE_SIZE, isStandardPbrMaterialShader } from './chunk-DRR7D3KX.mjs';
5
+ import { STANDARD_OUTPUT_TRANSFORM_FEATURE_ID, SHADOW_ATLAS_DEFAULT_LAYERS, MaterialSkinAttrMissingError, SkinMaterialMismatchError, InstanceCollectionError, ShadowInvalidConfigError, EnvironmentSourceConflictError, FogCardinalityError, GPU_TEXTURE_USAGE_COPY_SRC, GPU_TEXTURE_USAGE_COPY_DST, GPU_TEXTURE_USAGE_TEXTURE_BINDING, GPU_TEXTURE_USAGE_STORAGE_BINDING, GPU_TEXTURE_USAGE_RENDER_ATTACHMENT, AtmosphereInvalidParameterError } from './chunk-6TFBXLRJ.mjs';
6
6
  import { R_MIN, ok, err, TextError, toShared, handleSlot, AssetError, ASSET_ERROR_HINTS, materialValuesToLinearRuntime, derive, unpackSlot, materialGuidText } from '@forgeax/engine-types';
7
7
  import { err as err$1, ok as ok$1, RhiError } from '@forgeax/engine-rhi';
8
8
  import { resolveAssetHandle, walkMaterialPassesOverSharedRefs, selectMaterialPassProgram, materialParametersToParamSchema as materialParametersToParamSchema$1 } from '@forgeax/engine-assets-runtime';
@@ -1984,6 +1984,14 @@ function buildShadowFrusta(lights) {
1984
1984
  function skinPaletteIdentity(world, entity) {
1985
1985
  return `skin:${world.identity}:${entity}`;
1986
1986
  }
1987
+ function materialProgramSelectionRequiresSkin(selection) {
1988
+ if (selection.abi?.skinPaletteAddress !== void 0) return true;
1989
+ const semantics = new Set((selection.abi?.vertexInputs ?? []).map((input) => input.semantic));
1990
+ return semantics.has("skinIndex") && semantics.has("skinWeight");
1991
+ }
1992
+ function isMissingMaterialProgram(error) {
1993
+ return error !== null && typeof error === "object" && error.code === "material-specialization-not-cooked";
1994
+ }
1987
1995
  function extractFrames(worlds, owner, assets, pipelineState, materialSnapshotCachesByWorld, options = {}) {
1988
1996
  const cameraOwner = typeof owner === "number" ? owner : owner.cameraOwner;
1989
1997
  const resourceOwner = typeof owner === "number" ? owner : owner.resourceOwner;
@@ -3198,6 +3206,7 @@ function extractFrame(world, context) {
3198
3206
  const handleRaw = materialHandles[0] ?? 0;
3199
3207
  const cachedMaterial = handleRaw !== 0 && !hasSpriteRegionOverride && !hasSkin ? materialSnapshotCache.get(handleRaw) : void 0;
3200
3208
  let materialSnap;
3209
+ let materialProgramSelections;
3201
3210
  if (cachedMaterial !== void 0) {
3202
3211
  materialSnap = cachedMaterial.snapshot;
3203
3212
  if (isRenderable) {
@@ -3293,10 +3302,41 @@ function extractFrame(world, context) {
3293
3302
  ...context.materialContext,
3294
3303
  geometry: hasSkin ? "skinned" : context.materialContext.geometry
3295
3304
  };
3296
- const materialProgramKeys = materialProgramKeysForMaterial(
3297
- asset,
3298
- assets,
3299
- materialContext
3305
+ try {
3306
+ materialProgramSelections = materialProgramSelectionsForMaterial(
3307
+ asset,
3308
+ assets,
3309
+ materialContext
3310
+ );
3311
+ } catch (error) {
3312
+ if (isMissingMaterialProgram(error) && materialContext?.geometry === "mesh") {
3313
+ try {
3314
+ const skinnedSelections = materialProgramSelectionsForMaterial(asset, assets, {
3315
+ ...materialContext,
3316
+ geometry: "skinned"
3317
+ });
3318
+ if (skinnedSelections?.some(materialProgramSelectionRequiresSkin) === true && gpuDrivenMesh !== void 0) {
3319
+ const hasSkinIndex = gpuDrivenMesh.attributes.skinIndex !== void 0;
3320
+ const hasSkinWeight = gpuDrivenMesh.attributes.skinWeight !== void 0;
3321
+ if (!hasSkinIndex || !hasSkinWeight) {
3322
+ const missing = !hasSkinIndex && !hasSkinWeight ? "both" : !hasSkinIndex ? "skinIndex" : "skinWeight";
3323
+ worldInternal._routeError(new MaterialSkinAttrMissingError(entity, missing), {
3324
+ severity: Severity.Error,
3325
+ systemName: "RenderSystem.extract (material-skin-attr-missing)"
3326
+ });
3327
+ continue;
3328
+ }
3329
+ }
3330
+ } catch {
3331
+ }
3332
+ }
3333
+ throw error;
3334
+ }
3335
+ const materialProgramKeys = materialProgramSelections === void 0 ? void 0 : Object.fromEntries(
3336
+ materialProgramSelections.map(({ pass, specializationKey }) => [
3337
+ pass,
3338
+ specializationKey
3339
+ ])
3300
3340
  );
3301
3341
  const materialSceneIndexProgramKeys = materialSceneIndexProgramKeysForMaterial(
3302
3342
  asset,
@@ -3341,7 +3381,7 @@ function extractFrame(world, context) {
3341
3381
  );
3342
3382
  {
3343
3383
  const hasSkinSkel = hasSkin && skinSkeletonView !== void 0 && skinSkeletonView !== void 0 && skinSkeletonView !== 0;
3344
- const isPbrSkinMaterial = isStandardPbrSkinMaterialShader(firstPassShader);
3384
+ const isPbrSkinMaterial = materialProgramSelections?.some(materialProgramSelectionRequiresSkin) === true || isStandardPbrSkinMaterialShader(firstPassShader);
3345
3385
  if (hasSkinSkel && !isPbrSkinMaterial) {
3346
3386
  worldInternal._routeError(new SkinMaterialMismatchError(entity, firstPassShader), {
3347
3387
  severity: Severity.Error,
@@ -3707,7 +3747,7 @@ function extractFrame(world, context) {
3707
3747
  }
3708
3748
  if (skinSlice === void 0 && hasSkin) {
3709
3749
  releaseSkinIdentity();
3710
- if (materialSnap.materialShaderId === "forgeax::pbr-skin") {
3750
+ if (materialSnap.materialShaderId === "forgeax::pbr-skin" || materialProgramSelections?.some(materialProgramSelectionRequiresSkin) === true) {
3711
3751
  pendingDispatch.length = 0;
3712
3752
  continue;
3713
3753
  }
@@ -4310,6 +4350,30 @@ function runtimeMaterialShaderId(module, passName) {
4310
4350
  function materialProgramKeysForMaterial(material, assets, context) {
4311
4351
  return materialProgramKeysForAddress(material, assets, context, "direct");
4312
4352
  }
4353
+ function materialProgramSelectionsForMaterial(material, assets, context, address = "direct") {
4354
+ const projection = assets.getMaterialProjectionForPayload(material);
4355
+ if (projection === void 0) return void 0;
4356
+ if (context === void 0)
4357
+ throw new Error("Published material selection requires renderer-owned compiler context");
4358
+ return projection.passes.map((pass) => {
4359
+ const mode = String(
4360
+ pass.renderState?.tags?.LightMode ?? pass.name
4361
+ );
4362
+ const passKind = /shadow/i.test(mode) ? "shadow" : /depth/i.test(mode) ? "depth" : "forward";
4363
+ const selectedContext = {
4364
+ ...context,
4365
+ pass: passKind,
4366
+ pipeline: /deferred|gbuffer/i.test(mode) ? "deferred" : context.pipeline
4367
+ };
4368
+ const selected = selectMaterialPassProgram(projection, pass.name, selectedContext, address);
4369
+ return {
4370
+ pass: pass.name,
4371
+ context: selectedContext,
4372
+ specializationKey: selected.specializationKey,
4373
+ ...selected.abi === void 0 ? {} : { abi: selected.abi }
4374
+ };
4375
+ });
4376
+ }
4313
4377
  function materialSceneIndexProgramKeysForMaterial(material, assets, context) {
4314
4378
  const projection = assets.getMaterialProjectionForPayload(material);
4315
4379
  if (projection === void 0) return void 0;
@@ -4335,35 +4399,19 @@ function materialSceneIndexProgramKeysForMaterial(material, assets, context) {
4335
4399
  );
4336
4400
  entries[pass.name] = { specializationKey: selected.specializationKey, pass: passKind };
4337
4401
  } catch (error) {
4338
- if (!isMissingMaterialProgram(error)) throw error;
4402
+ if (!isMissingMaterialProgram2(error)) throw error;
4339
4403
  }
4340
4404
  }
4341
4405
  return Object.keys(entries).length === 0 ? void 0 : entries;
4342
4406
  }
4343
- function isMissingMaterialProgram(error) {
4407
+ function isMissingMaterialProgram2(error) {
4344
4408
  return error !== null && typeof error === "object" && error.code === "material-specialization-not-cooked";
4345
4409
  }
4346
4410
  function materialProgramKeysForAddress(material, assets, context, address) {
4347
- const projection = assets.getMaterialProjectionForPayload(material);
4348
- if (projection === void 0) return void 0;
4349
- if (context === void 0)
4350
- throw new Error("Published material selection requires renderer-owned compiler context");
4351
- const entries = [];
4352
- for (const pass of projection.passes) {
4353
- const mode = String(
4354
- pass.renderState?.tags?.LightMode ?? pass.name
4355
- );
4356
- const selectedContext = {
4357
- ...context,
4358
- pass: /shadow/i.test(mode) ? "shadow" : /depth/i.test(mode) ? "depth" : "forward",
4359
- pipeline: /deferred|gbuffer/i.test(mode) ? "deferred" : context.pipeline
4360
- };
4361
- entries.push([
4362
- pass.name,
4363
- selectMaterialPassProgram(projection, pass.name, selectedContext, address).specializationKey
4364
- ]);
4365
- }
4366
- return entries.length === 0 ? void 0 : Object.fromEntries(entries);
4411
+ const selections = materialProgramSelectionsForMaterial(material, assets, context, address);
4412
+ return selections === void 0 ? void 0 : Object.fromEntries(
4413
+ selections.map(({ pass, specializationKey }) => [pass, specializationKey])
4414
+ );
4367
4415
  }
4368
4416
  function runtimeMaterialShaderIdForMaterial(passes, programs) {
4369
4417
  const pass = passes.find(
@@ -4965,6 +5013,22 @@ function computeDirectionalCsm(direction, config, cameraData) {
4965
5013
  if ((ls[2] ?? 0) < minZ) minZ = ls[2] ?? 0;
4966
5014
  if ((ls[2] ?? 0) > maxZ) maxZ = ls[2] ?? 0;
4967
5015
  }
5016
+ const texelX = (maxX - minX) / config.mapSize;
5017
+ const texelY = (maxY - minY) / config.mapSize;
5018
+ if (Number.isFinite(texelX) && texelX > 0) {
5019
+ const centerX = (minX + maxX) * 0.5;
5020
+ const snappedCenterX = Math.round(centerX / texelX) * texelX;
5021
+ const halfWidth = (maxX - minX) * 0.5 + texelX * 0.5;
5022
+ minX = snappedCenterX - halfWidth;
5023
+ maxX = snappedCenterX + halfWidth;
5024
+ }
5025
+ if (Number.isFinite(texelY) && texelY > 0) {
5026
+ const centerY = (minY + maxY) * 0.5;
5027
+ const snappedCenterY = Math.round(centerY / texelY) * texelY;
5028
+ const halfHeight = (maxY - minY) * 0.5 + texelY * 0.5;
5029
+ minY = snappedCenterY - halfHeight;
5030
+ maxY = snappedCenterY + halfHeight;
5031
+ }
4968
5032
  const nearZ = Math.max(maxZ, lightSpaceMaxZFull);
4969
5033
  const orthoProj = mat4.create();
4970
5034
  mat4.orthographic(orthoProj, minX, maxX, maxY, minY, -nearZ, -minZ);
@@ -5008,14 +5072,23 @@ function collectCameraSnapshots(world) {
5008
5072
  const cameras = [];
5009
5073
  const cameraQuery = world.query({
5010
5074
  read: [Camera],
5011
- optional: [MotionBlur, DynamicResolution, ScreenSpaceReflection],
5075
+ optional: [MotionBlur, DynamicResolution, ScreenSpaceReflection, DepthOfField],
5012
5076
  with: [Transform, GlobalTransform]
5013
5077
  }).unwrap();
5014
5078
  for (const row of cameraQuery) {
5015
5079
  const cam = row.get(Camera);
5016
5080
  const motionBlur = row.get(MotionBlur);
5081
+ const depthOfField = row.get(DepthOfField);
5017
5082
  const dynamicResolution = row.get(DynamicResolution);
5018
5083
  const screenSpaceReflection = row.get(ScreenSpaceReflection);
5084
+ const projection = cameraProjectionFromF32(cam.projection);
5085
+ const depthOfFieldResult = resolveDepthOfFieldParams(depthOfField, {
5086
+ projection,
5087
+ fov: cam.fov,
5088
+ near: cam.near,
5089
+ far: cam.far
5090
+ });
5091
+ const depthOfFieldError = depthOfFieldResult.ok ? void 0 : depthOfFieldRequestFailure(depthOfFieldResult.error);
5019
5092
  const entity = row.entity;
5020
5093
  const view = worldInternal._getArrayView(entity, GlobalTransform, "world");
5021
5094
  if (view === void 0) continue;
@@ -5042,7 +5115,7 @@ function collectCameraSnapshots(world) {
5042
5115
  aspect: cam.aspect,
5043
5116
  near: cam.near,
5044
5117
  far: cam.far,
5045
- projection: cameraProjectionFromF32(cam.projection),
5118
+ projection,
5046
5119
  orthoLeft: cam.left,
5047
5120
  orthoRight: cam.right,
5048
5121
  orthoBottom: cam.bottom,
@@ -5063,6 +5136,8 @@ function collectCameraSnapshots(world) {
5063
5136
  cam.clearColor[2] ?? 0,
5064
5137
  cam.clearColor[3] ?? 1
5065
5138
  ],
5139
+ ...depthOfFieldResult.ok && depthOfFieldResult.value !== void 0 ? { depthOfField: depthOfFieldResult.value } : {},
5140
+ ...depthOfFieldError === void 0 ? {} : { depthOfFieldError },
5066
5141
  ...motionBlur === void 0 ? {} : {
5067
5142
  motionBlur: {
5068
5143
  shutterAngle: motionBlur.shutterAngle,
@@ -5904,5 +5979,5 @@ var ProbeBlendSceneProjection = class {
5904
5979
  };
5905
5980
 
5906
5981
  export { InstanceBoundsCache, OcclusionRenderRuntime, PROBE_MAX_CONTRIBUTORS, ProbeBlendSceneProjection, SKYLIGHT_RECOVERY_FALLBACK, SSR_HISTORY_FORMAT, SsrHistoryOwner, admitProbeContributors, blendLightProbes, buildRectAreaWorldFrame, buildShadowFrusta, createCookieProjectionMatrixData, createExtendedLightingState, createSsrHistoryOwner, createSsrSpatialResources, estimateSsrSpatialMemory, extractFrames, fingerprintNumericArray, glyphTextLayoutSystem, primitiveKey, primitiveKeyId, projectExtendedLightingInspection, promoteExtendedLightingCandidate, recordExtendedLightingFailure, rectAreaFacesPoint, scaledProbeWeight, setOcclusionRuntimeTestHooks, viewKey, viewKeyId };
5907
- //# sourceMappingURL=chunk-C3DDSXYK.mjs.map
5908
- //# sourceMappingURL=chunk-C3DDSXYK.mjs.map
5982
+ //# sourceMappingURL=chunk-4NNZQCL3.mjs.map
5983
+ //# sourceMappingURL=chunk-4NNZQCL3.mjs.map