@aura3d/rendering 4.6.1 → 4.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/dist/ClusteredForwardLighting.d.ts.map +1 -1
  2. package/dist/ClusteredForwardLighting.js +3 -1
  3. package/dist/ClusteredForwardLighting.js.map +1 -1
  4. package/dist/DepthPass.d.ts +25 -0
  5. package/dist/DepthPass.d.ts.map +1 -1
  6. package/dist/DepthPass.js +149 -1
  7. package/dist/DepthPass.js.map +1 -1
  8. package/dist/ForwardPass.d.ts +84 -0
  9. package/dist/ForwardPass.d.ts.map +1 -1
  10. package/dist/ForwardPass.js +236 -12
  11. package/dist/ForwardPass.js.map +1 -1
  12. package/dist/LightUniforms.d.ts +12 -0
  13. package/dist/LightUniforms.d.ts.map +1 -1
  14. package/dist/LightUniforms.js +9 -1
  15. package/dist/LightUniforms.js.map +1 -1
  16. package/dist/atmosphere/CloudLayer.d.ts +15 -0
  17. package/dist/atmosphere/CloudLayer.d.ts.map +1 -1
  18. package/dist/atmosphere/CloudLayer.js +27 -5
  19. package/dist/atmosphere/CloudLayer.js.map +1 -1
  20. package/dist/atmosphere/GradientSky.d.ts +3 -3
  21. package/dist/atmosphere/GradientSky.d.ts.map +1 -1
  22. package/dist/atmosphere/GradientSky.js +20 -9
  23. package/dist/atmosphere/GradientSky.js.map +1 -1
  24. package/dist/atmosphere/HeightFog.d.ts.map +1 -1
  25. package/dist/atmosphere/HeightFog.js +9 -0
  26. package/dist/atmosphere/HeightFog.js.map +1 -1
  27. package/dist/atmosphere/SkyBackgroundPass.d.ts +11 -0
  28. package/dist/atmosphere/SkyBackgroundPass.d.ts.map +1 -1
  29. package/dist/atmosphere/SkyBackgroundPass.js +40 -7
  30. package/dist/atmosphere/SkyBackgroundPass.js.map +1 -1
  31. package/dist/atmosphere/StarField.d.ts +21 -0
  32. package/dist/atmosphere/StarField.d.ts.map +1 -1
  33. package/dist/atmosphere/StarField.js +24 -1
  34. package/dist/atmosphere/StarField.js.map +1 -1
  35. package/dist/atmosphere/sky.glsl.d.ts.map +1 -1
  36. package/dist/atmosphere/sky.glsl.js +8 -0
  37. package/dist/atmosphere/sky.glsl.js.map +1 -1
  38. package/dist/contracts/flags.state.d.ts.map +1 -1
  39. package/dist/contracts/flags.state.js +19 -0
  40. package/dist/contracts/flags.state.js.map +1 -1
  41. package/dist/forward/Lighting.d.ts +7 -1
  42. package/dist/forward/Lighting.d.ts.map +1 -1
  43. package/dist/forward/Lighting.js +24 -1
  44. package/dist/forward/Lighting.js.map +1 -1
  45. package/dist/forward/Velocity.d.ts +8 -0
  46. package/dist/forward/Velocity.d.ts.map +1 -1
  47. package/dist/forward/Velocity.js +10 -0
  48. package/dist/forward/Velocity.js.map +1 -1
  49. package/dist/lanes/prd03.d.ts +1 -1
  50. package/dist/lanes/prd03.d.ts.map +1 -1
  51. package/dist/lanes/prd03.js +6 -1
  52. package/dist/lanes/prd03.js.map +1 -1
  53. package/dist/lanes/prd07.d.ts.map +1 -1
  54. package/dist/lanes/prd07.js +5 -2
  55. package/dist/lanes/prd07.js.map +1 -1
  56. package/dist/post/DisplayLutCache.d.ts +10 -2
  57. package/dist/post/DisplayLutCache.d.ts.map +1 -1
  58. package/dist/post/DisplayLutCache.js +15 -3
  59. package/dist/post/DisplayLutCache.js.map +1 -1
  60. package/dist/post/PostGraph.d.ts +23 -0
  61. package/dist/post/PostGraph.d.ts.map +1 -1
  62. package/dist/post/PostGraph.js.map +1 -1
  63. package/dist/post/PostQualityTiers.d.ts +36 -0
  64. package/dist/post/PostQualityTiers.d.ts.map +1 -1
  65. package/dist/post/PostQualityTiers.js +75 -0
  66. package/dist/post/PostQualityTiers.js.map +1 -1
  67. package/dist/post/chunks/velocity.glsl.d.ts +7 -0
  68. package/dist/post/chunks/velocity.glsl.d.ts.map +1 -1
  69. package/dist/post/chunks/velocity.glsl.js +12 -1
  70. package/dist/post/chunks/velocity.glsl.js.map +1 -1
  71. package/dist/post/shaders/displayGrade.glsl.d.ts +15 -1
  72. package/dist/post/shaders/displayGrade.glsl.d.ts.map +1 -1
  73. package/dist/post/shaders/displayGrade.glsl.js +26 -2
  74. package/dist/post/shaders/displayGrade.glsl.js.map +1 -1
  75. package/dist/post/shaders/dof.glsl.d.ts +11 -1
  76. package/dist/post/shaders/dof.glsl.d.ts.map +1 -1
  77. package/dist/post/shaders/dof.glsl.js +22 -0
  78. package/dist/post/shaders/dof.glsl.js.map +1 -1
  79. package/dist/post/shaders/finalize.glsl.d.ts +1 -1
  80. package/dist/post/shaders/finalize.glsl.d.ts.map +1 -1
  81. package/dist/post/shaders/finalize.glsl.js +3 -2
  82. package/dist/post/shaders/finalize.glsl.js.map +1 -1
  83. package/dist/post/shaders/godrays.glsl.d.ts +24 -1
  84. package/dist/post/shaders/godrays.glsl.d.ts.map +1 -1
  85. package/dist/post/shaders/godrays.glsl.js +45 -5
  86. package/dist/post/shaders/godrays.glsl.js.map +1 -1
  87. package/dist/post/shaders/hdrGrade.glsl.d.ts +66 -0
  88. package/dist/post/shaders/hdrGrade.glsl.d.ts.map +1 -0
  89. package/dist/post/shaders/hdrGrade.glsl.js +159 -0
  90. package/dist/post/shaders/hdrGrade.glsl.js.map +1 -0
  91. package/dist/post/shaders/ssr.glsl.d.ts +39 -0
  92. package/dist/post/shaders/ssr.glsl.d.ts.map +1 -0
  93. package/dist/post/shaders/ssr.glsl.js +163 -0
  94. package/dist/post/shaders/ssr.glsl.js.map +1 -0
  95. package/dist/post/v2Stages.d.ts +53 -0
  96. package/dist/post/v2Stages.d.ts.map +1 -1
  97. package/dist/post/v2Stages.js +314 -23
  98. package/dist/post/v2Stages.js.map +1 -1
  99. package/dist/postprocess/NativeBloomPyramid.d.ts +19 -0
  100. package/dist/postprocess/NativeBloomPyramid.d.ts.map +1 -1
  101. package/dist/postprocess/NativeBloomPyramid.js +37 -0
  102. package/dist/postprocess/NativeBloomPyramid.js.map +1 -1
  103. package/dist/program/ProgramGenerator.d.ts.map +1 -1
  104. package/dist/program/ProgramGenerator.js +12 -1
  105. package/dist/program/ProgramGenerator.js.map +1 -1
  106. package/dist/program/chunks/shadow_forward.glsl.d.ts +12 -0
  107. package/dist/program/chunks/shadow_forward.glsl.d.ts.map +1 -1
  108. package/dist/program/chunks/shadow_forward.glsl.js +57 -0
  109. package/dist/program/chunks/shadow_forward.glsl.js.map +1 -1
  110. package/dist/renderer/Background.d.ts.map +1 -1
  111. package/dist/renderer/Background.js +26 -2
  112. package/dist/renderer/Background.js.map +1 -1
  113. package/dist/renderer/FrameGraph.d.ts +8 -0
  114. package/dist/renderer/FrameGraph.d.ts.map +1 -1
  115. package/dist/renderer/FrameGraph.js +46 -7
  116. package/dist/renderer/FrameGraph.js.map +1 -1
  117. package/dist/renderer/OutlineTargets.d.ts +99 -0
  118. package/dist/renderer/OutlineTargets.d.ts.map +1 -0
  119. package/dist/renderer/OutlineTargets.js +286 -0
  120. package/dist/renderer/OutlineTargets.js.map +1 -0
  121. package/dist/renderer/PostprocessExecution.d.ts +5 -0
  122. package/dist/renderer/PostprocessExecution.d.ts.map +1 -1
  123. package/dist/renderer/PostprocessExecution.js +70 -4
  124. package/dist/renderer/PostprocessExecution.js.map +1 -1
  125. package/dist/renderer/postSkipped.d.ts +6 -0
  126. package/dist/renderer/postSkipped.d.ts.map +1 -1
  127. package/dist/renderer/postSkipped.js +8 -0
  128. package/dist/renderer/postSkipped.js.map +1 -1
  129. package/dist/shaders/chunks/author/ibl.glsl.d.ts +20 -0
  130. package/dist/shaders/chunks/author/ibl.glsl.d.ts.map +1 -0
  131. package/dist/shaders/chunks/author/ibl.glsl.js +84 -0
  132. package/dist/shaders/chunks/author/ibl.glsl.js.map +1 -0
  133. package/dist/shaders/chunks/author/index.d.ts +3 -1
  134. package/dist/shaders/chunks/author/index.d.ts.map +1 -1
  135. package/dist/shaders/chunks/author/index.js +38 -3
  136. package/dist/shaders/chunks/author/index.js.map +1 -1
  137. package/dist/shaders/chunks/author/lights.glsl.d.ts +16 -0
  138. package/dist/shaders/chunks/author/lights.glsl.d.ts.map +1 -0
  139. package/dist/shaders/chunks/author/lights.glsl.js +112 -0
  140. package/dist/shaders/chunks/author/lights.glsl.js.map +1 -0
  141. package/dist/shaders/chunks/author/shadow.glsl.d.ts +16 -2
  142. package/dist/shaders/chunks/author/shadow.glsl.d.ts.map +1 -1
  143. package/dist/shaders/chunks/author/shadow.glsl.js +46 -2
  144. package/dist/shaders/chunks/author/shadow.glsl.js.map +1 -1
  145. package/dist/shaders/chunks/instance_color_target.glsl.d.ts +34 -0
  146. package/dist/shaders/chunks/instance_color_target.glsl.d.ts.map +1 -0
  147. package/dist/shaders/chunks/instance_color_target.glsl.js +101 -0
  148. package/dist/shaders/chunks/instance_color_target.glsl.js.map +1 -0
  149. package/dist/shaders/chunks/rim.glsl.d.ts +37 -0
  150. package/dist/shaders/chunks/rim.glsl.d.ts.map +1 -0
  151. package/dist/shaders/chunks/rim.glsl.js +50 -0
  152. package/dist/shaders/chunks/rim.glsl.js.map +1 -0
  153. package/dist/shadows/Prd02ShadowBridge.d.ts +26 -3
  154. package/dist/shadows/Prd02ShadowBridge.d.ts.map +1 -1
  155. package/dist/shadows/Prd02ShadowBridge.js +134 -8
  156. package/dist/shadows/Prd02ShadowBridge.js.map +1 -1
  157. package/dist/shadows/Prd02ShadowsContributor.d.ts.map +1 -1
  158. package/dist/shadows/Prd02ShadowsContributor.js +4 -16
  159. package/dist/shadows/Prd02ShadowsContributor.js.map +1 -1
  160. package/dist/vfx/VfxAtlas.d.ts +10 -0
  161. package/dist/vfx/VfxAtlas.d.ts.map +1 -1
  162. package/dist/vfx/VfxAtlas.js +18 -3
  163. package/dist/vfx/VfxAtlas.js.map +1 -1
  164. package/dist/webgl2/LegacyPost.d.ts +9 -1
  165. package/dist/webgl2/LegacyPost.d.ts.map +1 -1
  166. package/dist/webgl2/LegacyPost.js +23 -7
  167. package/dist/webgl2/LegacyPost.js.map +1 -1
  168. package/dist/webgl2/MultiDraw.d.ts.map +1 -1
  169. package/dist/webgl2/MultiDraw.js +51 -1
  170. package/dist/webgl2/MultiDraw.js.map +1 -1
  171. package/dist/world/vegetation/WindField.d.ts.map +1 -1
  172. package/dist/world/vegetation/WindField.js +4 -1
  173. package/dist/world/vegetation/WindField.js.map +1 -1
  174. package/dist/world/water/ReflectionViewPass.d.ts.map +1 -1
  175. package/dist/world/water/ReflectionViewPass.js +12 -2
  176. package/dist/world/water/ReflectionViewPass.js.map +1 -1
  177. package/dist/world/water/SceneCopyFallback.d.ts.map +1 -1
  178. package/dist/world/water/SceneCopyFallback.js +9 -2
  179. package/dist/world/water/SceneCopyFallback.js.map +1 -1
  180. package/dist/world/water/WaterMaterial.d.ts.map +1 -1
  181. package/dist/world/water/WaterMaterial.js +8 -2
  182. package/dist/world/water/WaterMaterial.js.map +1 -1
  183. package/package.json +3 -3
@@ -1,3 +1,37 @@
1
+ /**
2
+ * GU47 E-D (PRD §3.1) `a3d_scene`: the scene built-ins a `material.custom` shader may read, each bound by the forward pass
3
+ * only when the program declares it (`ForwardPass.ts` `applyCustomShaderFrameUniforms` / `applyCustomShaderLightingUniforms`):
4
+ * - `u_a3dSunDirection`: unit direction from the surface toward the sun (the shadow-casting directional light, else the
5
+ * first directional light; straight up when the scene has none).
6
+ * - `u_a3dSunColor` (linear rgb) and `u_a3dSunIntensity`: that light's colour and intensity (0 when there is none).
7
+ * - `u_a3dHemiSky` / `u_a3dHemiGround`: the authored hemisphere light pair (linear rgb, premultiplied by intensity; 0 when none).
8
+ * - `u_a3dFogColor` / `u_a3dFogDensity`: the scene fog colour and an exp2 density (a linear fog gets the density that
9
+ * reaches 98% at `far`; 0 when the scene has no fog or the material opts out).
10
+ * `#include <a3d_shadow>`, `<a3d_lights>` and `<a3d_ibl>` include it; the adapter expands each author chunk once per stage.
11
+ */
12
+ export const A3D_SCENE_GLSL = /* glsl */ `
13
+ uniform vec3 u_a3dSunDirection;
14
+ uniform vec3 u_a3dSunColor;
15
+ uniform float u_a3dSunIntensity;
16
+ uniform vec3 u_a3dHemiSky;
17
+ uniform vec3 u_a3dHemiGround;
18
+ uniform vec3 u_a3dFogColor;
19
+ uniform float u_a3dFogDensity;
20
+
21
+ vec3 a3dSunRadiance() {
22
+ return u_a3dSunColor * max(u_a3dSunIntensity, 0.0);
23
+ }
24
+
25
+ vec3 a3dHemiLight(vec3 n) {
26
+ float up = clamp(n.y / max(length(n), 1e-4) * 0.5 + 0.5, 0.0, 1.0);
27
+ return mix(u_a3dHemiGround, u_a3dHemiSky, up);
28
+ }
29
+
30
+ vec3 a3dSceneFog(vec3 color, float viewDistance) {
31
+ float x = max(u_a3dFogDensity, 0.0) * max(viewDistance, 0.0);
32
+ return mix(color, u_a3dFogColor, 1.0 - exp(-x * x));
33
+ }
34
+ `;
1
35
  /**
2
36
  * `a3d_shadow`: sun-shadow receive for `material.custom` fragment shaders.
3
37
  *
@@ -5,9 +39,13 @@
5
39
  * from the light's `shadow` options) to any program that declares the `u_shadowMap*` uniforms below. This chunk declares them
6
40
  * and wraps the same lookup the built-in lit programs use, so a custom surface is darkened by exactly the same shadow.
7
41
  * `a3dSunShadow` returns 1 in light and `1 - strength * occlusion` in shadow; it returns 1 when the scene has no shadow map.
8
- * `u_a3dSunDirection` is bound to the direction from the surface toward the shadow-casting directional light.
42
+ * `u_a3dSunDirection` (from `a3d_scene`) is bound to the direction from the surface toward the shadow-casting directional light.
43
+ * GU47 E-D: `a3dFragWorldPosition()` reconstructs this fragment's world position from `gl_FragCoord` and the bound
44
+ * `u_a3dInverseViewProjection` (exact for any author vertex displacement; no varying needed).
9
45
  */
10
46
  export const A3D_SHADOW_GLSL = /* glsl */ `
47
+ #include <a3d_scene>
48
+ uniform mat4 u_a3dInverseViewProjection;
11
49
  uniform sampler2D u_shadowMapTexture;
12
50
  uniform float u_shadowMapEnabled;
13
51
  uniform mat4 u_shadowMapMatrix;
@@ -18,7 +56,6 @@ uniform vec2 u_shadowMapTexelSize;
18
56
  uniform float u_shadowPcfSampleCount;
19
57
  uniform vec4 u_shadowPcfSamples[32];
20
58
  uniform float u_shadowMapNormalBias;
21
- uniform vec3 u_a3dSunDirection;
22
59
 
23
60
  float a3dSunShadow(vec3 worldPosition, vec3 normal, vec3 toLight) {
24
61
  if (u_shadowMapEnabled < 0.5) return 1.0;
@@ -53,5 +90,12 @@ float a3dSunShadow(vec3 worldPosition, vec3 normal, vec3 toLight) {
53
90
  float a3dSunShadowAuto(vec3 worldPosition, vec3 normal) {
54
91
  return a3dSunShadow(worldPosition, normal, u_a3dSunDirection);
55
92
  }
93
+
94
+ vec3 a3dFragWorldPosition() {
95
+ vec2 ndc = gl_FragCoord.xy / max(u_resolution, vec2(1.0)) * 2.0 - 1.0;
96
+ vec4 world = u_a3dInverseViewProjection * vec4(ndc, gl_FragCoord.z * 2.0 - 1.0, 1.0);
97
+ float w = abs(world.w) > 1e-8 ? world.w : 1e-8;
98
+ return world.xyz / w;
99
+ }
56
100
  `;
57
101
  //# sourceMappingURL=shadow.glsl.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shadow.glsl.js","sourceRoot":"","sources":["../../../../../../../packages/rendering/src/shaders/chunks/author/shadow.glsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8CzC,CAAC"}
1
+ {"version":3,"file":"shadow.glsl.js","sourceRoot":"","sources":["../../../../../../../packages/rendering/src/shaders/chunks/author/shadow.glsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;CAsBxC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsDzC,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * GU47 E-D (PRD §3.1): what a per-instance colour multiplies (`instanceColorTarget`).
3
+ *
4
+ * Today the generated program multiplies the base colour by `a_instanceColor` (`USE_INSTANCING_COLOR`). The engine
5
+ * stamps `u_a3dInstanceColorTarget` on the node's material (0 = "base", 1 = "emissive", 2 = "both"; written through the
6
+ * public `Material.setParameter` API) and ForwardPass routes the colours per draw:
7
+ * - "base" (or no parameter): unchanged; this feature never selects, so the program is byte-identical.
8
+ * - "both": `a_instanceColor` still multiplies the base, and this feature also multiplies the emissive term by it.
9
+ * - "emissive": ForwardPass drops `instancing.color` from the program record (no base multiply) and binds the same
10
+ * colour buffer as `a_a3dInstanceEmissive`; this feature declares it and multiplies the emissive term only.
11
+ * Multiply semantics match "base": give the material an emissive colour (white is the usual choice) and an
12
+ * `emissiveIntensity`, and each instance glows its own colour. Generated programs only.
13
+ */
14
+ import type { RenderItem } from "../../contracts/renderItem.js";
15
+ import type { Material } from "../../Material.js";
16
+ import { MaterialInstance } from "../../MaterialInstance.js";
17
+ export type InstanceColorTarget = "base" | "emissive" | "both";
18
+ export declare const A3D_INSTANCE_COLOR_TARGET_FEATURE = "prd04.instanceColorTarget";
19
+ export declare const A3D_INSTANCE_COLOR_TARGET_PARAM = "u_a3dInstanceColorTarget";
20
+ /** Per-instance attribute that carries the colours when the target is "emissive" (no base multiply). */
21
+ export declare const A3D_INSTANCE_EMISSIVE_ATTRIBUTE = "a_a3dInstanceEmissive";
22
+ export declare const A3D_INSTANCE_EMISSIVE_VTX_PARS_CHUNK = "a3d_prd04_instance_emissive_vtx_pars";
23
+ export declare const A3D_INSTANCE_EMISSIVE_VTX_END_CHUNK = "a3d_prd04_instance_emissive_vtx_end";
24
+ export declare const A3D_INSTANCE_EMISSIVE_FRAG_PARS_CHUNK = "a3d_prd04_instance_emissive_frag_pars";
25
+ export declare const A3D_INSTANCE_EMISSIVE_FRAG_CALL_CHUNK = "a3d_prd04_instance_emissive_frag_call";
26
+ /** Material parameter value for a target. */
27
+ export declare function instanceColorTargetCode(target: InstanceColorTarget | undefined): number;
28
+ /** The target a material carries ("base" when it has none). */
29
+ export declare function materialInstanceColorTarget(material: Material | MaterialInstance | undefined): InstanceColorTarget;
30
+ /** `select`: forward draws with per-instance colours whose material targets the emissive term. Pure. */
31
+ export declare function selectInstanceColorTargetFeature(item: RenderItem, pass: string): "emissive" | "both" | undefined;
32
+ /** Registers the chunks and the `prd04.instanceColorTarget` ShaderFeature once per process (ForwardPass calls this at load). */
33
+ export declare function registerInstanceColorTargetFeature(): void;
34
+ //# sourceMappingURL=instance_color_target.glsl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instance_color_target.glsl.d.ts","sourceRoot":"","sources":["../../../../../../packages/rendering/src/shaders/chunks/instance_color_target.glsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;AAE/D,eAAO,MAAM,iCAAiC,8BAA8B,CAAC;AAC7E,eAAO,MAAM,+BAA+B,6BAA6B,CAAC;AAC1E,wGAAwG;AACxG,eAAO,MAAM,+BAA+B,0BAA0B,CAAC;AAEvE,eAAO,MAAM,oCAAoC,yCAAyC,CAAC;AAC3F,eAAO,MAAM,mCAAmC,wCAAwC,CAAC;AACzF,eAAO,MAAM,qCAAqC,0CAA0C,CAAC;AAC7F,eAAO,MAAM,qCAAqC,0CAA0C,CAAC;AAiC7F,6CAA6C;AAC7C,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,mBAAmB,GAAG,SAAS,GAAG,MAAM,CAEvF;AAED,+DAA+D;AAC/D,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,QAAQ,GAAG,gBAAgB,GAAG,SAAS,GAAG,mBAAmB,CAMlH;AAED,wGAAwG;AACxG,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CAIhH;AAiBD,gIAAgI;AAChI,wBAAgB,kCAAkC,IAAI,IAAI,CAazD"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * GU47 E-D (PRD §3.1): what a per-instance colour multiplies (`instanceColorTarget`).
3
+ *
4
+ * Today the generated program multiplies the base colour by `a_instanceColor` (`USE_INSTANCING_COLOR`). The engine
5
+ * stamps `u_a3dInstanceColorTarget` on the node's material (0 = "base", 1 = "emissive", 2 = "both"; written through the
6
+ * public `Material.setParameter` API) and ForwardPass routes the colours per draw:
7
+ * - "base" (or no parameter): unchanged; this feature never selects, so the program is byte-identical.
8
+ * - "both": `a_instanceColor` still multiplies the base, and this feature also multiplies the emissive term by it.
9
+ * - "emissive": ForwardPass drops `instancing.color` from the program record (no base multiply) and binds the same
10
+ * colour buffer as `a_a3dInstanceEmissive`; this feature declares it and multiplies the emissive term only.
11
+ * Multiply semantics match "base": give the material an emissive colour (white is the usual choice) and an
12
+ * `emissiveIntensity`, and each instance glows its own colour. Generated programs only.
13
+ */
14
+ import { registerShaderChunk, registerShaderFeature, shaderChunk } from "../../contracts/program.js";
15
+ import { MaterialInstance } from "../../MaterialInstance.js";
16
+ export const A3D_INSTANCE_COLOR_TARGET_FEATURE = "prd04.instanceColorTarget";
17
+ export const A3D_INSTANCE_COLOR_TARGET_PARAM = "u_a3dInstanceColorTarget";
18
+ /** Per-instance attribute that carries the colours when the target is "emissive" (no base multiply). */
19
+ export const A3D_INSTANCE_EMISSIVE_ATTRIBUTE = "a_a3dInstanceEmissive";
20
+ export const A3D_INSTANCE_EMISSIVE_VTX_PARS_CHUNK = "a3d_prd04_instance_emissive_vtx_pars";
21
+ export const A3D_INSTANCE_EMISSIVE_VTX_END_CHUNK = "a3d_prd04_instance_emissive_vtx_end";
22
+ export const A3D_INSTANCE_EMISSIVE_FRAG_PARS_CHUNK = "a3d_prd04_instance_emissive_frag_pars";
23
+ export const A3D_INSTANCE_EMISSIVE_FRAG_CALL_CHUNK = "a3d_prd04_instance_emissive_frag_call";
24
+ // Varying named apart from PRD-11's `v_a3dInstanceEmissive` (`batching/shaders/instanceEmissive.glsl.ts`), so both
25
+ // features may select in one program.
26
+ const VTX_PARS_GLSL = /* glsl */ `
27
+ #ifdef A3D_INSTANCE_EMISSIVE_ATTRIBUTE
28
+ in vec4 a_a3dInstanceEmissive;
29
+ out vec4 v_a3dInstanceEmissiveTint;
30
+ #endif
31
+ `;
32
+ const VTX_END_GLSL = /* glsl */ `
33
+ #ifdef A3D_INSTANCE_EMISSIVE_ATTRIBUTE
34
+ v_a3dInstanceEmissiveTint = a_a3dInstanceEmissive;
35
+ #endif
36
+ `;
37
+ const FRAG_PARS_GLSL = /* glsl */ `
38
+ #ifdef A3D_INSTANCE_EMISSIVE_ATTRIBUTE
39
+ in vec4 v_a3dInstanceEmissiveTint;
40
+ #endif
41
+ `;
42
+ const FRAG_CALL_GLSL = /* glsl */ `
43
+ #if defined(A3D_INSTANCE_EMISSIVE_ATTRIBUTE)
44
+ a3dEmissive *= v_a3dInstanceEmissiveTint.rgb;
45
+ #elif defined(USE_INSTANCING_COLOR)
46
+ a3dEmissive *= v_instanceColor.rgb;
47
+ #endif
48
+ `;
49
+ const TARGET_CODES = { base: 0, emissive: 1, both: 2 };
50
+ /** Material parameter value for a target. */
51
+ export function instanceColorTargetCode(target) {
52
+ return TARGET_CODES[target ?? "base"] ?? 0;
53
+ }
54
+ /** The target a material carries ("base" when it has none). */
55
+ export function materialInstanceColorTarget(material) {
56
+ if (!material)
57
+ return "base";
58
+ const base = material instanceof MaterialInstance ? material.baseMaterial : material;
59
+ if (base.disposed)
60
+ return "base";
61
+ const value = base.getParameter(A3D_INSTANCE_COLOR_TARGET_PARAM);
62
+ return value === 1 ? "emissive" : value === 2 ? "both" : "base";
63
+ }
64
+ /** `select`: forward draws with per-instance colours whose material targets the emissive term. Pure. */
65
+ export function selectInstanceColorTargetFeature(item, pass) {
66
+ if (pass !== "forward" || item.instanceTransforms === undefined || item.instanceColors === undefined)
67
+ return undefined;
68
+ const target = materialInstanceColorTarget(item.material);
69
+ return target === "base" ? undefined : target;
70
+ }
71
+ const FEATURE = {
72
+ id: A3D_INSTANCE_COLOR_TARGET_FEATURE,
73
+ owner: "prd04",
74
+ flag: "A3D_QR_MATERIALS",
75
+ order: 10,
76
+ select: (input) => selectInstanceColorTargetFeature(input.item, input.pass),
77
+ defines: (value) => value === "emissive"
78
+ ? { A3D_INSTANCE_COLOR_EMISSIVE: true, A3D_INSTANCE_EMISSIVE_ATTRIBUTE: true }
79
+ : { A3D_INSTANCE_COLOR_EMISSIVE: true },
80
+ chunks: [A3D_INSTANCE_EMISSIVE_VTX_PARS_CHUNK, A3D_INSTANCE_EMISSIVE_VTX_END_CHUNK, A3D_INSTANCE_EMISSIVE_FRAG_PARS_CHUNK, A3D_INSTANCE_EMISSIVE_FRAG_CALL_CHUNK],
81
+ hooks: ["vertex:pars", "vertex:end", "fragment:pars", "fragment:emissive"]
82
+ };
83
+ let registered = false;
84
+ /** Registers the chunks and the `prd04.instanceColorTarget` ShaderFeature once per process (ForwardPass calls this at load). */
85
+ export function registerInstanceColorTargetFeature() {
86
+ if (registered)
87
+ return;
88
+ const chunks = [
89
+ [A3D_INSTANCE_EMISSIVE_VTX_PARS_CHUNK, VTX_PARS_GLSL, "vertex"],
90
+ [A3D_INSTANCE_EMISSIVE_VTX_END_CHUNK, VTX_END_GLSL, "vertex"],
91
+ [A3D_INSTANCE_EMISSIVE_FRAG_PARS_CHUNK, FRAG_PARS_GLSL, "fragment"],
92
+ [A3D_INSTANCE_EMISSIVE_FRAG_CALL_CHUNK, FRAG_CALL_GLSL, "fragment"]
93
+ ];
94
+ for (const [name, glsl, stage] of chunks) {
95
+ if (!shaderChunk(name))
96
+ registerShaderChunk({ name, owner: "prd04", glsl, stage });
97
+ }
98
+ registerShaderFeature(FEATURE);
99
+ registered = true;
100
+ }
101
+ //# sourceMappingURL=instance_color_target.glsl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instance_color_target.glsl.js","sourceRoot":"","sources":["../../../../../../packages/rendering/src/shaders/chunks/instance_color_target.glsl.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * GU47 E-D (PRD §3.1): `rim: { color, power, intensity }` on the forward PBR program.
3
+ *
4
+ * The forward term is the PRD-04 `prd04.rim` ShaderFeature (#88: `materials/features.ts`, chunks `a3d_prd04_rim_pars`
5
+ * and `a3d_prd04_rim_call` in `shaders/physical/lobe_calls.glsl.ts`, registered by `lanes/prd04.ts`). It adds
6
+ * `u_prd04RimColor * u_prd04RimStrength * (1 - N·V)^u_prd04RimPower` to the emitted light of lit generated programs and
7
+ * selects only when the draw's material carries `u_prd04RimStrength > 0`, so a material without rim (or with intensity
8
+ * 0) gets no feature bit, no define and no chunk: its program is byte-identical to the one it compiled to before.
9
+ *
10
+ * GU47 reuses that feature instead of registering a second one (a second `prd04.rim` id throws REGISTRY_DUPLICATE when
11
+ * the rendering barrel loads, and two rim terms could stack). This module is the single source of the parameter names
12
+ * and defaults the engine lowers `rim` onto (`production-runtime/ModelMaterialOverrides.ts` mirrors them, it cannot
13
+ * import this file), and of the `a3dRim()` GLSL the toon material and the author chunk `a3d_rim` share. Generated
14
+ * programs only (the default `A3D_QR_CORE` path); the frozen legacy shaderKey library (`?a3d-qr=-core`) has no rim.
15
+ */
16
+ import type { Material } from "../../Material.js";
17
+ import { MaterialInstance } from "../../MaterialInstance.js";
18
+ /** The forward ShaderFeature that draws the rim (`materials/features.ts` `rimFeature`). */
19
+ export declare const A3D_RIM_FEATURE = "prd04.rim";
20
+ /** Material parameter names (also the GLSL uniform names of `a3d_prd04_rim_pars`). */
21
+ export declare const A3D_RIM_COLOR_PARAM = "u_prd04RimColor";
22
+ export declare const A3D_RIM_POWER_PARAM = "u_prd04RimPower";
23
+ export declare const A3D_RIM_INTENSITY_PARAM = "u_prd04RimStrength";
24
+ export declare const A3D_RIM_DEFAULT_POWER = 3;
25
+ export declare const A3D_RIM_DEFAULT_INTENSITY = 1;
26
+ /** Clamp ranges the engine lowering applies (`power` 0.1..16, `intensity` 0..16). */
27
+ export declare const A3D_RIM_POWER_RANGE: readonly [number, number];
28
+ export declare const A3D_RIM_INTENSITY_RANGE: readonly [number, number];
29
+ /**
30
+ * `vec3 a3dRim(n, v, color, power, intensity)`: the same term as `a3d_prd04_rim_call`, written with `exp2/log2` instead
31
+ * of `pow` so it is defined for every input on every GPU and composes with the custom-material safe-`pow` define. Used by
32
+ * `material.toon` and published to `material.custom` authors as `#include <a3d_rim>`.
33
+ */
34
+ export declare const A3D_RIM_FUNCTION_GLSL = "\nvec3 a3dRim(vec3 n, vec3 v, vec3 color, float power, float intensity) {\n float facing = clamp(dot(n / max(length(n), 1e-4), v / max(length(v), 1e-4)), 0.0, 1.0);\n float edge = exp2(clamp(power, 0.1, 16.0) * log2(max(1.0 - facing, 1e-4)));\n return color * (clamp(intensity, 0.0, 16.0) * edge);\n}\n";
35
+ /** The rim intensity a material carries (0 when it has no rim, so `prd04.rim` does not select). */
36
+ export declare function materialRimIntensity(material: Material | MaterialInstance | undefined): number;
37
+ //# sourceMappingURL=rim.glsl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rim.glsl.d.ts","sourceRoot":"","sources":["../../../../../../packages/rendering/src/shaders/chunks/rim.glsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,2FAA2F;AAC3F,eAAO,MAAM,eAAe,cAAc,CAAC;AAE3C,sFAAsF;AACtF,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AACrD,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AACrD,eAAO,MAAM,uBAAuB,uBAAuB,CAAC;AAE5D,eAAO,MAAM,qBAAqB,IAAI,CAAC;AACvC,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAC3C,qFAAqF;AACrF,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAa,CAAC;AACxE,eAAO,MAAM,uBAAuB,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAW,CAAC;AAE1E;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,sTAMjC,CAAC;AAEF,mGAAmG;AACnG,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,GAAG,gBAAgB,GAAG,SAAS,GAAG,MAAM,CAM9F"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * GU47 E-D (PRD §3.1): `rim: { color, power, intensity }` on the forward PBR program.
3
+ *
4
+ * The forward term is the PRD-04 `prd04.rim` ShaderFeature (#88: `materials/features.ts`, chunks `a3d_prd04_rim_pars`
5
+ * and `a3d_prd04_rim_call` in `shaders/physical/lobe_calls.glsl.ts`, registered by `lanes/prd04.ts`). It adds
6
+ * `u_prd04RimColor * u_prd04RimStrength * (1 - N·V)^u_prd04RimPower` to the emitted light of lit generated programs and
7
+ * selects only when the draw's material carries `u_prd04RimStrength > 0`, so a material without rim (or with intensity
8
+ * 0) gets no feature bit, no define and no chunk: its program is byte-identical to the one it compiled to before.
9
+ *
10
+ * GU47 reuses that feature instead of registering a second one (a second `prd04.rim` id throws REGISTRY_DUPLICATE when
11
+ * the rendering barrel loads, and two rim terms could stack). This module is the single source of the parameter names
12
+ * and defaults the engine lowers `rim` onto (`production-runtime/ModelMaterialOverrides.ts` mirrors them, it cannot
13
+ * import this file), and of the `a3dRim()` GLSL the toon material and the author chunk `a3d_rim` share. Generated
14
+ * programs only (the default `A3D_QR_CORE` path); the frozen legacy shaderKey library (`?a3d-qr=-core`) has no rim.
15
+ */
16
+ import { MaterialInstance } from "../../MaterialInstance.js";
17
+ /** The forward ShaderFeature that draws the rim (`materials/features.ts` `rimFeature`). */
18
+ export const A3D_RIM_FEATURE = "prd04.rim";
19
+ /** Material parameter names (also the GLSL uniform names of `a3d_prd04_rim_pars`). */
20
+ export const A3D_RIM_COLOR_PARAM = "u_prd04RimColor";
21
+ export const A3D_RIM_POWER_PARAM = "u_prd04RimPower";
22
+ export const A3D_RIM_INTENSITY_PARAM = "u_prd04RimStrength";
23
+ export const A3D_RIM_DEFAULT_POWER = 3;
24
+ export const A3D_RIM_DEFAULT_INTENSITY = 1;
25
+ /** Clamp ranges the engine lowering applies (`power` 0.1..16, `intensity` 0..16). */
26
+ export const A3D_RIM_POWER_RANGE = [0.1, 16];
27
+ export const A3D_RIM_INTENSITY_RANGE = [0, 16];
28
+ /**
29
+ * `vec3 a3dRim(n, v, color, power, intensity)`: the same term as `a3d_prd04_rim_call`, written with `exp2/log2` instead
30
+ * of `pow` so it is defined for every input on every GPU and composes with the custom-material safe-`pow` define. Used by
31
+ * `material.toon` and published to `material.custom` authors as `#include <a3d_rim>`.
32
+ */
33
+ export const A3D_RIM_FUNCTION_GLSL = /* glsl */ `
34
+ vec3 a3dRim(vec3 n, vec3 v, vec3 color, float power, float intensity) {
35
+ float facing = clamp(dot(n / max(length(n), 1e-4), v / max(length(v), 1e-4)), 0.0, 1.0);
36
+ float edge = exp2(clamp(power, 0.1, 16.0) * log2(max(1.0 - facing, 1e-4)));
37
+ return color * (clamp(intensity, 0.0, 16.0) * edge);
38
+ }
39
+ `;
40
+ /** The rim intensity a material carries (0 when it has no rim, so `prd04.rim` does not select). */
41
+ export function materialRimIntensity(material) {
42
+ if (!material)
43
+ return 0;
44
+ const base = material instanceof MaterialInstance ? material.baseMaterial : material;
45
+ if (base.disposed)
46
+ return 0;
47
+ const value = base.getParameter(A3D_RIM_INTENSITY_PARAM);
48
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
49
+ }
50
+ //# sourceMappingURL=rim.glsl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rim.glsl.js","sourceRoot":"","sources":["../../../../../../packages/rendering/src/shaders/chunks/rim.glsl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,2FAA2F;AAC3F,MAAM,CAAC,MAAM,eAAe,GAAG,WAAW,CAAC;AAE3C,sFAAsF;AACtF,MAAM,CAAC,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AACrD,MAAM,CAAC,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AACrD,MAAM,CAAC,MAAM,uBAAuB,GAAG,oBAAoB,CAAC;AAE5D,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AACvC,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAC3C,qFAAqF;AACrF,MAAM,CAAC,MAAM,mBAAmB,GAA8B,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACxE,MAAM,CAAC,MAAM,uBAAuB,GAA8B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAE1E;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,UAAU,CAAC;;;;;;CAM/C,CAAC;AAEF,mGAAmG;AACnG,MAAM,UAAU,oBAAoB,CAAC,QAAiD;IACpF,IAAI,CAAC,QAAQ;QAAE,OAAO,CAAC,CAAC;IACxB,MAAM,IAAI,GAAG,QAAQ,YAAY,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC;IACrF,IAAI,IAAI,CAAC,QAAQ;QAAE,OAAO,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,uBAAuB,CAAC,CAAC;IACzD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACtF,CAAC"}
@@ -16,15 +16,22 @@
16
16
  * (compiler/shadows.ts) for the config and `source.collectedLights` for the
17
17
  * sun, falling back to the scene graph only when the source carries neither.
18
18
  * Flag off never reaches this module (ShadowOrchestration legacy path).
19
+ *
20
+ * GU47 eint (E-B handoff EB-3): the shadowed spot / point lights of
21
+ * `source.collectedLights` (E-B's multi-caster selection) render into the
22
+ * PRD-02 local atlas in the same update and reach the forward pass as
23
+ * `ForwardShadowMapOptions.localShadows`, which the generated forward program
24
+ * samples per light (`program/chunks/shadow_forward.glsl.ts` `shadow_local`).
19
25
  */
20
26
  import type { Camera } from "@aura3d/scene";
21
27
  import type { ForwardShadowMapOptions } from "../ForwardPass.js";
28
+ import type { CollectedLight } from "../LightCollector.js";
22
29
  import type { RenderDevice } from "../RenderDevice.js";
23
30
  import type { QrFlags } from "../contracts/core.js";
24
31
  import type { AuraQualityTierSettings } from "../contracts/quality.js";
25
32
  import type { RenderItem } from "../contracts/renderItem.js";
26
33
  import type { RenderSource } from "../contracts/renderSource.js";
27
- import { Prd02ShadowSystem, type Prd02ShadowFrameUniforms, type ShadowSystemConfigInput } from "./ShadowSystem.js";
34
+ import { Prd02ShadowSystem, type Prd02ShadowFrameUniforms, type ShadowSystemConfigInput, type ShadowSystemLocalLight } from "./ShadowSystem.js";
28
35
  /** Uniform the `a3d_prd02_shadow_lookup` chunk declares (C-11); marks a lookup consumer. */
29
36
  export declare const PRD02_SHADOW_LOOKUP_UNIFORM = "u_prd02CascadeCompare0";
30
37
  type SourceLike = RenderSource | Iterable<RenderItem> | unknown;
@@ -33,6 +40,17 @@ type SourceLike = RenderSource | Iterable<RenderItem> | unknown;
33
40
  * else the legacy RendererShadowOptions mapped onto the tier defaults.
34
41
  */
35
42
  export declare function prd02ShadowConfig(source: SourceLike, flags: QrFlags, tier: AuraQualityTierSettings, cameraFar: number | undefined): ShadowSystemConfigInput;
43
+ /** A shadow-casting spot / point light of the compiled source and its PRD-02 shadow-system input. */
44
+ export interface Prd02LocalShadowLight {
45
+ readonly input: ShadowSystemLocalLight;
46
+ readonly light: CollectedLight;
47
+ }
48
+ /**
49
+ * Visible shadow-casting spot / point lights of `source.collectedLights`, in collected order (`shadowIndex` 0, 1, ...).
50
+ * Engine scenes mark them with E-B's multi-caster selection (`resolveProductionShadowCasterIndices`, capped by the
51
+ * tier's `localShadowLights`). Empty for sources without collected lights and with `?a3dLighting=atlas=off`.
52
+ */
53
+ export declare function prd02LocalShadowLights(source: SourceLike): readonly Prd02LocalShadowLight[];
36
54
  /** Normalized direction of the first visible shadow-casting sun. */
37
55
  export declare function prd02SunDirection(source: SourceLike): readonly [number, number, number] | null;
38
56
  /** True when a forward program samples the prd02 lookup chunk (C-02 generator path). */
@@ -114,8 +132,13 @@ export declare function shadowFrameCamera(viewProjection: Float32Array | readonl
114
132
  * Renders the prd02 sun cascades now and returns them as legacy
115
133
  * `ForwardShadowMapOptions` (T0-26 bridge). Returns undefined — and allocates
116
134
  * nothing — when shadows are off/killed, a lookup-chunk consumer exists (the
117
- * contributor owns that path), or there is no sun, caster, camera or depth
118
- * texture support.
135
+ * contributor owns that path), or there is no sun or local caster, no caster
136
+ * item, camera or depth texture support.
137
+ *
138
+ * GU47 eint (E-B handoff EB-3): the explicitly shadowed spot / point lights of
139
+ * the compiled source (`prd02LocalShadowLights`) get PRD-02 atlas tiles in the
140
+ * same update, handed to the forward pass as `localShadows`; a scene whose only
141
+ * casters are local lights binds a strength-0 sun map plus its tiles.
119
142
  */
120
143
  export declare function executePrd02BridgedShadowMap(input: Prd02BridgeInput): ForwardShadowMapOptions | undefined;
121
144
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"Prd02ShadowBridge.d.ts","sourceRoot":"","sources":["../../../../../packages/rendering/src/shadows/Prd02ShadowBridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Prd02ShadowBridge.d.ts","sourceRoot":"","sources":["../../../../../packages/rendering/src/shadows/Prd02ShadowBridge.ts"],"names":[],"mappings":"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"}
@@ -16,6 +16,12 @@
16
16
  * (compiler/shadows.ts) for the config and `source.collectedLights` for the
17
17
  * sun, falling back to the scene graph only when the source carries neither.
18
18
  * Flag off never reaches this module (ShadowOrchestration legacy path).
19
+ *
20
+ * GU47 eint (E-B handoff EB-3): the shadowed spot / point lights of
21
+ * `source.collectedLights` (E-B's multi-caster selection) render into the
22
+ * PRD-02 local atlas in the same update and reach the forward pass as
23
+ * `ForwardShadowMapOptions.localShadows`, which the generated forward program
24
+ * samples per light (`program/chunks/shadow_forward.glsl.ts` `shadow_local`).
19
25
  */
20
26
  import { Sampler } from "../Sampler.js";
21
27
  import { createShadowFilterKernel } from "../ShadowMap.js";
@@ -75,6 +81,37 @@ export function prd02ShadowConfig(source, flags, tier, cameraFar) {
75
81
  ...(isShadowPcfTapTier(compiled?.pcfTapTier) ? { pcfTapTier: compiled.pcfTapTier } : {})
76
82
  };
77
83
  }
84
+ /**
85
+ * Visible shadow-casting spot / point lights of `source.collectedLights`, in collected order (`shadowIndex` 0, 1, ...).
86
+ * Engine scenes mark them with E-B's multi-caster selection (`resolveProductionShadowCasterIndices`, capped by the
87
+ * tier's `localShadowLights`). Empty for sources without collected lights and with `?a3dLighting=atlas=off`.
88
+ */
89
+ export function prd02LocalShadowLights(source) {
90
+ if (!source || typeof source !== "object" || Symbol.iterator in source)
91
+ return [];
92
+ const collected = source.collectedLights;
93
+ if (collected === undefined || !readPrd02KillSwitches(source).atlas)
94
+ return [];
95
+ const out = [];
96
+ for (const light of collected) {
97
+ if (!light.castsShadow || light.source?.visible === false)
98
+ continue;
99
+ if (light.kind !== "spot" && light.kind !== "point")
100
+ continue;
101
+ out.push({
102
+ light,
103
+ input: {
104
+ shadowIndex: out.length,
105
+ kind: light.kind,
106
+ position: light.position,
107
+ direction: light.kind === "spot" ? light.direction : [0, -1, 0],
108
+ range: light.range,
109
+ ...(light.kind === "spot" ? { outerAngleRadians: light.spotAngle } : {})
110
+ }
111
+ });
112
+ }
113
+ return out;
114
+ }
78
115
  /** Normalized direction of the first visible shadow-casting sun. */
79
116
  export function prd02SunDirection(source) {
80
117
  const collected = source && typeof source === "object" && !(Symbol.iterator in source)
@@ -183,8 +220,13 @@ export function shadowFrameCamera(viewProjection, eye, viewMatrix) {
183
220
  * Renders the prd02 sun cascades now and returns them as legacy
184
221
  * `ForwardShadowMapOptions` (T0-26 bridge). Returns undefined — and allocates
185
222
  * nothing — when shadows are off/killed, a lookup-chunk consumer exists (the
186
- * contributor owns that path), or there is no sun, caster, camera or depth
187
- * texture support.
223
+ * contributor owns that path), or there is no sun or local caster, no caster
224
+ * item, camera or depth texture support.
225
+ *
226
+ * GU47 eint (E-B handoff EB-3): the explicitly shadowed spot / point lights of
227
+ * the compiled source (`prd02LocalShadowLights`) get PRD-02 atlas tiles in the
228
+ * same update, handed to the forward pass as `localShadows`; a scene whose only
229
+ * casters are local lights binds a strength-0 sun map plus its tiles.
188
230
  */
189
231
  export function executePrd02BridgedShadowMap(input) {
190
232
  bridgedFrames.delete(input.device);
@@ -208,7 +250,8 @@ export function executePrd02BridgedShadowMap(input) {
208
250
  if (!camera?.viewProjectionMatrix)
209
251
  return bail("no-camera");
210
252
  const sun = prd02SunDirection(input.source);
211
- if (!sun)
253
+ const localLights = prd02LocalShadowLights(input.source);
254
+ if (!sun && localLights.length === 0)
212
255
  return bail("no-sun");
213
256
  const tier = input.tier ?? QUALITY_TIERS.high;
214
257
  const config = prd02ShadowConfig(input.source, input.flags, tier, camera.far);
@@ -228,14 +271,21 @@ export function executePrd02BridgedShadowMap(input) {
228
271
  // camera's real clip range; `config.maxDistance` caps the cascade splits.
229
272
  const uniforms = system.update({
230
273
  camera: { viewProjectionMatrix: camera.viewProjectionMatrix, near, far: camera.far ?? 200 },
231
- sun: { direction: sun },
274
+ sun: sun ? { direction: sun } : null,
232
275
  casters: input.items,
233
- // Local (spot/point) prd02 tiles need the lookup chunk; the bridge is sun-only.
234
- localLights: [],
276
+ // GU47 eint (EB-3): local (spot / point) tiles render here too; the forward pass samples them.
277
+ localLights: localLights.map((light) => light.input),
235
278
  flags: input.flags,
236
279
  tier,
237
280
  ...(cascadeUse ? { cascadeUse } : {})
238
281
  });
282
+ const localShadows = bridgeLocalShadows(uniforms, localLights, config);
283
+ if (!sun) {
284
+ if (!localShadows.texture)
285
+ return bail("no-local-tiles");
286
+ bridgedFrames.set(input.device, { uniforms, config, system });
287
+ return localOnlyShadowMap(localShadows);
288
+ }
239
289
  const fits = system.cascadeFits();
240
290
  const maps = fits.map((fit) => {
241
291
  const texture = uniforms.cascadeTextures[fit.index] ?? null;
@@ -247,7 +297,7 @@ export function executePrd02BridgedShadowMap(input) {
247
297
  const resolved = maps;
248
298
  const first = resolved[0].map;
249
299
  if (resolved.length === 1)
250
- return first;
300
+ return { ...first, localShadows };
251
301
  let previousFar = 0;
252
302
  return {
253
303
  ...first,
@@ -255,7 +305,83 @@ export function executePrd02BridgedShadowMap(input) {
255
305
  const cascade = { index: fit.index, near: previousFar, far: fit.splitFar, shadowMap: map };
256
306
  previousFar = fit.splitFar;
257
307
  return cascade;
258
- })
308
+ }),
309
+ localShadows
310
+ };
311
+ }
312
+ /** Local-tile receiver biases in tile texels (GU47 eint EB-3; tuned by the phase-2 local-shadow frames). */
313
+ const LOCAL_DEPTH_BIAS_TEXELS = 1;
314
+ const LOCAL_NORMAL_BIAS_TEXELS = 1;
315
+ /** `shadows/ShadowSystem.ts` ATLAS_SIZE, for a mock atlas texture without a width. */
316
+ const LOCAL_ATLAS_FALLBACK_SIZE = 1024;
317
+ const LOCAL_COMPARE = new Sampler({
318
+ minFilter: "linear",
319
+ magFilter: "linear",
320
+ addressU: "clamp-to-edge",
321
+ addressV: "clamp-to-edge",
322
+ compare: "less-equal"
323
+ });
324
+ const IDENTITY = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
325
+ /** The spot tile's field of view (`ShadowAtlas.spotClip`). */
326
+ function spotTileFov(outerAngleRadians) {
327
+ return Math.min(Math.PI - 1e-3, Math.max(1e-3, (outerAngleRadians ?? Math.PI / 4) * 2));
328
+ }
329
+ /**
330
+ * GU47 eint (EB-3): this frame's atlas tiles as `ForwardShadowMapOptions.localShadows`. A light gets a slot only when
331
+ * all its tiles were kept, in face order (a spot 1, a point 6 consecutive); `slots` is empty (and `texture` unset)
332
+ * when no light did, which still tells the forward pass the bridged map is the sun's.
333
+ */
334
+ function bridgeLocalShadows(uniforms, lights, config) {
335
+ const tilesByLight = new Map();
336
+ const pairs = uniforms.perLightShadowIndex;
337
+ for (let i = 0; i + 1 < pairs.length; i += 2) {
338
+ const tiles = tilesByLight.get(pairs[i]) ?? [];
339
+ tiles.push(pairs[i + 1]);
340
+ tilesByLight.set(pairs[i], tiles);
341
+ }
342
+ const atlas = uniforms.atlasTexture;
343
+ const atlasSize = atlas && atlas.width > 0 ? atlas.width : LOCAL_ATLAS_FALLBACK_SIZE;
344
+ const texelScale = new Float32Array(8);
345
+ const slots = new Map();
346
+ for (const { input, light } of atlas ? lights : []) {
347
+ const tiles = tilesByLight.get(input.shadowIndex) ?? [];
348
+ if (tiles.length !== (input.kind === "point" ? 6 : 1) || tiles.some((tile, face) => tile !== tiles[0] + face))
349
+ continue;
350
+ const tanHalfFov = input.kind === "point" ? 1 : Math.tan(spotTileFov(input.outerAngleRadians) / 2);
351
+ for (const tile of tiles) {
352
+ texelScale[tile] = (2 * tanHalfFov) / Math.max(1, (uniforms.localShadowData[tile * 4 + 2] ?? 0) * atlasSize);
353
+ }
354
+ slots.set(light, tiles[0]);
355
+ }
356
+ return {
357
+ slots,
358
+ ...(atlas && slots.size > 0 ? { texture: new TextureBinding({ name: "u_localShadowAtlas", texture: atlas, sampler: LOCAL_COMPARE, required: true }) } : {}),
359
+ atlasSize,
360
+ matrices: uniforms.localShadowMatrices,
361
+ rects: uniforms.localShadowData,
362
+ texelScale,
363
+ strength: config.strength,
364
+ biasTexels: LOCAL_DEPTH_BIAS_TEXELS,
365
+ slopeBiasTexels: BRIDGE_SLOPE_BIAS,
366
+ normalBiasTexels: LOCAL_NORMAL_BIAS_TEXELS
367
+ };
368
+ }
369
+ /**
370
+ * A frame whose only casters are local lights: the forward programs still declare the sun map, so it is bound to the
371
+ * atlas at strength 0 (no light is gated onto it: `forwardShadedLights` clears every local caster's gate).
372
+ */
373
+ function localOnlyShadowMap(localShadows) {
374
+ const texel = 1 / localShadows.atlasSize;
375
+ return {
376
+ texture: new TextureBinding({ name: "u_shadowMapTexture", texture: localShadows.texture.texture, sampler: NEAREST_CLAMP, required: true }),
377
+ lightMatrix: IDENTITY,
378
+ strength: 0,
379
+ bias: BRIDGE_AUTO_DEPTH_BIAS,
380
+ slopeBias: BRIDGE_SLOPE_BIAS,
381
+ normalBias: 0,
382
+ texelSize: [texel, texel],
383
+ filterKernel: createShadowFilterKernel({ filter: "none" }),
384
+ localShadows
259
385
  };
260
386
  }
261
387
  function bridgeShadowMap(texture, lightMatrix, config, texelWorld) {