@babylonjs/lite 1.11.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/dist/index.js +444 -368
- package/dist/index.js.map +1 -1
- package/index.d.ts +208 -6
- package/lib/asset-container.js.map +1 -1
- package/lib/audio/index.js +1 -0
- package/lib/audio/index.js.map +1 -1
- package/lib/audio/media-stream-output.js +44 -0
- package/lib/audio/media-stream-output.js.map +1 -0
- package/lib/engine/engine.js +1 -1
- package/lib/frame-graph/render-task.js +1 -1
- package/lib/frame-graph/render-task.js.map +1 -1
- package/lib/frame-graph/shadow-inputs.js +10 -1
- package/lib/frame-graph/shadow-inputs.js.map +1 -1
- package/lib/frame-graph/transmission.js +1 -16
- package/lib/frame-graph/transmission.js.map +1 -1
- package/lib/index.js +6 -3
- package/lib/index.js.map +1 -1
- package/lib/loader-gltf/gltf-json-asset.js +1 -1
- package/lib/loader-gltf/gltf-json-asset.js.map +1 -1
- package/lib/loader-gltf/gltf-multi-buffer.js +2 -10
- package/lib/loader-gltf/gltf-multi-buffer.js.map +1 -1
- package/lib/loader-gltf/gltf-pbr-builder-ext.js +4 -18
- package/lib/loader-gltf/gltf-pbr-builder-ext.js.map +1 -1
- package/lib/loader-gltf/gltf-pbr-builder.js +17 -14
- package/lib/loader-gltf/gltf-pbr-builder.js.map +1 -1
- package/lib/loader-gltf/gltf-sampler-desc.js +3 -16
- package/lib/loader-gltf/gltf-sampler-desc.js.map +1 -1
- package/lib/material/node/blocks/ambient-occlusion-block.js +1 -4
- package/lib/material/node/blocks/ambient-occlusion-block.js.map +1 -1
- package/lib/material/node/blocks/biplanar-block.js +3 -6
- package/lib/material/node/blocks/biplanar-block.js.map +1 -1
- package/lib/material/node/blocks/image-source.js +2 -5
- package/lib/material/node/blocks/image-source.js.map +1 -1
- package/lib/material/node/blocks/input-block.js +5 -26
- package/lib/material/node/blocks/input-block.js.map +1 -1
- package/lib/material/node/blocks/pbr-mr-helper-full.js +5 -8
- package/lib/material/node/blocks/pbr-mr-helper-full.js.map +1 -1
- package/lib/material/node/blocks/reflection-texture-block.js +1 -4
- package/lib/material/node/blocks/reflection-texture-block.js.map +1 -1
- package/lib/material/node/blocks/texture-block.js +2 -5
- package/lib/material/node/blocks/texture-block.js.map +1 -1
- package/lib/material/node/blocks/triplanar-block.js +3 -6
- package/lib/material/node/blocks/triplanar-block.js.map +1 -1
- package/lib/material/node/node-emitter.js +24 -1
- package/lib/material/node/node-emitter.js.map +1 -1
- package/lib/material/node/node-geometry-renderable.js +2 -2
- package/lib/material/node/node-material.js +1 -22
- package/lib/material/node/node-material.js.map +1 -1
- package/lib/material/node/node-types.js.map +1 -1
- package/lib/material/pbr/fragments/shadow-only-fragment.js +68 -0
- package/lib/material/pbr/fragments/shadow-only-fragment.js.map +1 -0
- package/lib/material/pbr/pbr-flag-bits.js.map +1 -1
- package/lib/material/pbr/pbr-material.js.map +1 -1
- package/lib/material/pbr/pbr-primitive-resolver.js +2 -2
- package/lib/material/pbr/pbr-primitive-resolver.js.map +1 -1
- package/lib/material/pbr/pbr-renderable.js +3 -0
- package/lib/material/pbr/pbr-renderable.js.map +1 -1
- package/lib/material/pbr/pbr-template.js +1 -0
- package/lib/material/pbr/pbr-template.js.map +1 -1
- package/lib/mesh/GaussianSplatting/gaussian-splatting-mesh.js +2 -8
- package/lib/mesh/GaussianSplatting/gaussian-splatting-mesh.js.map +1 -1
- package/lib/mesh/get-mesh-geometry.js +24 -0
- package/lib/mesh/get-mesh-geometry.js.map +1 -0
- package/lib/mesh/mesh-dispose.js +2 -0
- package/lib/mesh/mesh-dispose.js.map +1 -1
- package/lib/mesh/mesh.js +2 -8
- package/lib/mesh/mesh.js.map +1 -1
- package/lib/mesh/thin-instance-cull-binding.js +54 -3
- package/lib/mesh/thin-instance-cull-binding.js.map +1 -1
- package/lib/mesh/thin-instance-gpu-culling.js +241 -24
- package/lib/mesh/thin-instance-gpu-culling.js.map +1 -1
- package/lib/mesh/thin-instance.js +112 -1
- package/lib/mesh/thin-instance.js.map +1 -1
- package/lib/picking/gpu-picker.js +4 -2
- package/lib/picking/gpu-picker.js.map +1 -1
- package/lib/picking/picking-pipeline.js +1 -1
- package/lib/picking/picking-pipeline.js.map +1 -1
- package/lib/picking/picking-shader.js +38 -16
- package/lib/picking/picking-shader.js.map +1 -1
- package/lib/scene/scene-core.js +7 -2
- package/lib/scene/scene-core.js.map +1 -1
- package/lib/scene/scene-node.js +2 -6
- package/lib/scene/scene-node.js.map +1 -1
- package/lib/scene/scene-remove.js +70 -1
- package/lib/scene/scene-remove.js.map +1 -1
- package/lib/scene/transform-node.js +3 -0
- package/lib/scene/transform-node.js.map +1 -1
- package/lib/scene/world-matrix-state.js +7 -1
- package/lib/scene/world-matrix-state.js.map +1 -1
- package/lib/shadow/csm-directional-shadow-generator.js +22 -1
- package/lib/shadow/csm-directional-shadow-generator.js.map +1 -1
- package/lib/shadow/csm-shadow-task-hooks.js +19 -11
- package/lib/shadow/csm-shadow-task-hooks.js.map +1 -1
- package/lib/shadow/esm-directional-shadow-generator.js +2 -51
- package/lib/shadow/esm-directional-shadow-generator.js.map +1 -1
- package/lib/shadow/pcf-directional-shadow-generator.js +2 -48
- package/lib/shadow/pcf-directional-shadow-generator.js.map +1 -1
- package/lib/shadow/shadow-base.js +48 -1
- package/lib/shadow/shadow-base.js.map +1 -1
- package/lib/text/text-renderable.js +2 -10
- package/lib/text/text-renderable.js.map +1 -1
- package/lib/texture/texture-array.js +96 -0
- package/lib/texture/texture-array.js.map +1 -0
- package/package.json +3 -3
|
@@ -3,7 +3,7 @@ import { TU, SS } from '../engine/gpu-flags.js';
|
|
|
3
3
|
import { createUniformBuffer } from '../resource/gpu-buffers.js';
|
|
4
4
|
import { getBilinearSampler } from '../resource/samplers.js';
|
|
5
5
|
import { createRenderTask } from '../frame-graph/render-task.js';
|
|
6
|
-
import { createShadowParamsUBO, createSharedShadowUBO, createShadowCamera, createShadowRenderTarget, casterVersionSum,
|
|
6
|
+
import { createShadowParamsUBO, createSharedShadowUBO, createShadowCamera, createShadowRenderTarget, casterVersionSum, computeDirectionalLightMatrix, writeShadowUboFields, updateShadowCameraBase } from './shadow-base.js';
|
|
7
7
|
import { packMat4IntoF32 } from '../math/pack-mat4-into-f32.js';
|
|
8
8
|
|
|
9
9
|
const blurVertSrc = "struct c{@builtin(position) clipPos:vec4<f32>,@location(0) sampleCenter:vec2<f32>}@vertex fn main(@builtin(vertex_index) d:u32)->c{var e=array<vec2<f32>,3>(vec2<f32>(-1.0,-1.0),vec2<f32>(3.0,-1.0),vec2<f32>(-1.0,3.0));var a:c;let b=e[d];a.clipPos=vec4<f32>(b,0.0,1.0);a.sampleCenter=b*vec2<f32>(0.5,-0.5)+0.5;return a;}";
|
|
@@ -56,55 +56,6 @@ async function preloadEsmShadowTaskState(casterMeshes) {
|
|
|
56
56
|
}
|
|
57
57
|
await Promise.all(loads);
|
|
58
58
|
}
|
|
59
|
-
function _computeDirectionalLightMatrix(light, casterMeshes, orthoMinZ, orthoMaxZ, offX = 0, offY = 0, offZ = 0) {
|
|
60
|
-
const view = buildLightViewMatrix(light.direction.x, light.direction.y, light.direction.z, light.position.x - offX, light.position.y - offY, light.position.z - offZ);
|
|
61
|
-
let lMinX = Infinity;
|
|
62
|
-
let lMaxX = -Infinity;
|
|
63
|
-
let lMinY = Infinity;
|
|
64
|
-
let lMaxY = -Infinity;
|
|
65
|
-
for (const mesh of casterMeshes) {
|
|
66
|
-
const world = mesh.worldMatrix;
|
|
67
|
-
const bmin = mesh.boundMin ?? [-0.5, -0.5, -0.5];
|
|
68
|
-
const bmax = mesh.boundMax ?? [0.5, 0.5, 0.5];
|
|
69
|
-
for (let ci = 0; ci < 8; ci++) {
|
|
70
|
-
const lx = ci & 1 ? bmax[0] : bmin[0];
|
|
71
|
-
const ly = ci & 2 ? bmax[1] : bmin[1];
|
|
72
|
-
const lz = ci & 4 ? bmax[2] : bmin[2];
|
|
73
|
-
const wx = world[0] * lx + world[4] * ly + world[8] * lz + world[12] - offX;
|
|
74
|
-
const wy = world[1] * lx + world[5] * ly + world[9] * lz + world[13] - offY;
|
|
75
|
-
const wz = world[2] * lx + world[6] * ly + world[10] * lz + world[14] - offZ;
|
|
76
|
-
const vx = view[0] * wx + view[4] * wy + view[8] * wz + view[12];
|
|
77
|
-
const vy = view[1] * wx + view[5] * wy + view[9] * wz + view[13];
|
|
78
|
-
lMinX = Math.min(lMinX, vx);
|
|
79
|
-
lMaxX = Math.max(lMaxX, vx);
|
|
80
|
-
lMinY = Math.min(lMinY, vy);
|
|
81
|
-
lMaxY = Math.max(lMaxY, vy);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
if (!Number.isFinite(lMinX)) {
|
|
85
|
-
lMinX = -1;
|
|
86
|
-
lMaxX = 1;
|
|
87
|
-
lMinY = -1;
|
|
88
|
-
lMaxY = 1;
|
|
89
|
-
}
|
|
90
|
-
const sx = (lMaxX - lMinX) * 0.1;
|
|
91
|
-
const sy = (lMaxY - lMinY) * 0.1;
|
|
92
|
-
lMinX -= sx;
|
|
93
|
-
lMaxX += sx;
|
|
94
|
-
lMinY -= sy;
|
|
95
|
-
lMaxY += sy;
|
|
96
|
-
const near = orthoMinZ;
|
|
97
|
-
const far = orthoMaxZ;
|
|
98
|
-
const proj = new F32(16);
|
|
99
|
-
proj[0] = 2 / (lMaxX - lMinX);
|
|
100
|
-
proj[5] = 2 / (lMaxY - lMinY);
|
|
101
|
-
proj[10] = 1 / (far - near);
|
|
102
|
-
proj[12] = -(lMaxX + lMinX) / (lMaxX - lMinX);
|
|
103
|
-
proj[13] = -(lMaxY + lMinY) / (lMaxY - lMinY);
|
|
104
|
-
proj[14] = -near / (far - near);
|
|
105
|
-
proj[15] = 1;
|
|
106
|
-
return { _view: view, _viewProj: multiply4x4(proj, view), _near: near, _far: far };
|
|
107
|
-
}
|
|
108
59
|
function nearestBestKernel(idealKernel) {
|
|
109
60
|
const v = Math.round(Math.max(idealKernel, 1));
|
|
110
61
|
for (const k of [v, v - 1, v + 1, v - 2, v + 2]) {
|
|
@@ -228,7 +179,7 @@ function renderEsmShadowMap(engine, sg, state) {
|
|
|
228
179
|
if (!sg._config._forceRefreshEveryFrame && casterVersion === state._lastCasterVersion && lightVersion === state._lastLightVersion && foVersion === state._lastFoVersion) {
|
|
229
180
|
return 0;
|
|
230
181
|
}
|
|
231
|
-
const matrix =
|
|
182
|
+
const matrix = computeDirectionalLightMatrix(sg._light, casterMeshes, sg._config._orthoMinZ, sg._config._orthoMaxZ, offX, offY, offZ);
|
|
232
183
|
if (shadowMatrixChanged(sg._lightMatrix, matrix._viewProj)) {
|
|
233
184
|
packMat4IntoF32(sg._lightMatrix, matrix._viewProj, 0);
|
|
234
185
|
sg._version++;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"esm-directional-shadow-generator.js","sources":["../../../shaders/shadow-blur.vertex.wgsl?raw","../../../src/shadow/esm-directional-shadow-generator.ts"],"sourcesContent":["export default \"// Shadow Blur Vertex Shader — fullscreen quad with pre-computed sample coordinates\\n// Uses Babylon's kernel blur approach with bilinear tap offsets\\n\\nstruct BlurParams {\\n delta: vec2<f32>, // (1/texWidth, 0) for H pass, (0, 1/texHeight) for V pass\\n _pad: vec2<f32>,\\n};\\n@group(0) @binding(0) var<uniform> params: BlurParams;\\n\\nstruct VertexOutput {\\n @builtin(position) clipPos: vec4<f32>,\\n @location(0) sampleCenter: vec2<f32>,\\n};\\n\\n@vertex\\nfn main(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {\\n // Fullscreen triangle (3 vertices cover the screen)\\n var pos = array<vec2<f32>, 3>(\\n vec2<f32>(-1.0, -1.0),\\n vec2<f32>(3.0, -1.0),\\n vec2<f32>(-1.0, 3.0),\\n );\\n\\n var out: VertexOutput;\\n let p = pos[vertexIndex];\\n out.clipPos = vec4<f32>(p, 0.0, 1.0);\\n out.sampleCenter = p * vec2<f32>(0.5, -0.5) + 0.5;\\n return out;\\n}\\n\"","/**\n * Exponential Shadow Map (ESM) generator resource setup.\n *\n * This module creates the directional shadow resources and owns the internal\n * task hooks used by frame-graph/shadow-task.ts.\n */\n\nimport { F32 } from \"../engine/typed-arrays.js\";\nimport { TU, SS } from \"../engine/gpu-flags.js\";\nimport type { Camera } from \"../camera/camera.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { DirectionalLight } from \"../light/directional-light.js\";\nimport type { Material, MaterialView } from \"../material/material.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport { createUniformBuffer } from \"../resource/gpu-buffers.js\";\nimport { getBilinearSampler } from \"../resource/samplers.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport { createRenderTask, type RenderTask } from \"../frame-graph/render-task.js\";\nimport {\n buildLightViewMatrix,\n casterVersionSum,\n createSharedShadowUBO,\n createShadowCamera,\n createShadowParamsUBO,\n createShadowRenderTarget,\n multiply4x4,\n updateShadowCameraBase,\n writeShadowUboFields,\n} from \"./shadow-base.js\";\nimport type { ShadowGenerator, ShadowTaskInternalState } from \"./shadow-generator.js\";\nimport blurVertSrc from \"../../shaders/shadow-blur.vertex.wgsl?raw\";\nimport { packMat4IntoF32 } from \"../math/pack-mat4-into-f32.js\";\n\nexport interface EsmLightMatrix {\n /** @internal */\n _view: Float32Array;\n /** @internal */\n _viewProj: Float32Array;\n /** @internal */\n _near: number;\n /** @internal */\n _far: number;\n}\n\nexport interface EsmShadowTaskResources {\n /** @internal */\n _esmTexture: GPUTexture;\n /** @internal */\n _depthBuffer: GPUTexture;\n /** @internal */\n _blurTexH: GPUTexture;\n /** @internal */\n _blurPipeline: GPURenderPipeline;\n /** @internal */\n _blurHBG: GPUBindGroup;\n /** @internal */\n _blurVBG: GPUBindGroup;\n /** @internal */\n _shadowUboData: Float32Array;\n}\n\n/** Configuration for a directional-light ESM shadow generator: map size, depth scale, blur kernel, darkness, and ortho projection bounds. */\nexport interface EsmDirectionalShadowGeneratorConfig {\n mapSize?: number;\n depthScale?: number;\n bias?: number;\n /** Kernel blur sample region in pixels. Matches Babylon.js ShadowGenerator.blurKernel. Default 1. */\n blurKernel?: number;\n blurScale?: number;\n darkness?: number;\n frustumEdgeFalloff?: number;\n /** Ortho projection min Z — typically camera.nearPlane. Default 1. */\n orthoMinZ?: number;\n /** Ortho projection max Z — typically camera.farPlane. Default 10000. */\n orthoMaxZ?: number;\n /** Force the shadow map to be regenerated every frame. Default false. */\n forceRefreshEveryFrame?: boolean;\n}\n\ninterface EsmTaskState extends ShadowTaskInternalState {\n _task: RenderTask;\n _camera: Camera;\n _cameraVersion: number;\n _lastCasterVersion: number;\n _lastLightVersion: number;\n /** @internal Floating-origin offset version (active camera worldMatrixVersion) at last shadow-map render; -1 when never rendered. */\n _lastFoVersion: number;\n _casterMeshes: readonly Mesh[];\n /** @internal Owning scene — used to read the live floating-origin offset (camera world position). */\n _scene: SceneContext;\n}\n\ntype StandardEsmFactory = typeof import(\"../material/standard/esm-shadow-view.js\").createStandardEsmShadowMaterialView;\ntype PbrEsmFactory = typeof import(\"../material/pbr/esm-shadow-view.js\").createPbrEsmShadowMaterialView;\ntype NodeEsmFactory = typeof import(\"../material/node/esm-shadow-view.js\").createNodeEsmShadowMaterialView;\n\nlet esmShadowTaskResources: WeakMap<ShadowGenerator, EsmShadowTaskResources> | null = null;\nlet createStandardEsmShadowMaterialView: StandardEsmFactory;\nlet createPbrEsmShadowMaterialView: PbrEsmFactory;\nlet createNodeEsmShadowMaterialView: NodeEsmFactory;\n\nfunction getEsmShadowTaskResourceMap(): WeakMap<ShadowGenerator, EsmShadowTaskResources> {\n esmShadowTaskResources ??= new WeakMap<ShadowGenerator, EsmShadowTaskResources>();\n return esmShadowTaskResources;\n}\n\nfunction setEsmShadowTaskResources(sg: ShadowGenerator, resources: EsmShadowTaskResources): void {\n getEsmShadowTaskResourceMap().set(sg, resources);\n}\n\nfunction getEsmShadowTaskResources(sg: ShadowGenerator): EsmShadowTaskResources | null {\n return esmShadowTaskResources?.get(sg) ?? null;\n}\n\nasync function preloadEsmShadowTaskState(casterMeshes: readonly Mesh[]): Promise<void> {\n const loads: Promise<void>[] = [];\n let needsStandard = false;\n let needsPbr = false;\n let needsNode = false;\n for (const mesh of casterMeshes) {\n const family = mesh.material?._buildGroup._materialFamily;\n needsStandard ||= family === \"standard\";\n needsPbr ||= family === \"pbr\";\n needsNode ||= family === \"node\";\n }\n if (needsStandard && !createStandardEsmShadowMaterialView) {\n loads.push(\n import(\"../material/standard/esm-shadow-view.js\").then((module) => {\n createStandardEsmShadowMaterialView = module.createStandardEsmShadowMaterialView;\n })\n );\n }\n if (needsPbr && !createPbrEsmShadowMaterialView) {\n loads.push(\n import(\"../material/pbr/esm-shadow-view.js\").then((module) => {\n createPbrEsmShadowMaterialView = module.createPbrEsmShadowMaterialView;\n })\n );\n }\n if (needsNode && !createNodeEsmShadowMaterialView) {\n loads.push(\n import(\"../material/node/esm-shadow-view.js\").then((module) => {\n createNodeEsmShadowMaterialView = module.createNodeEsmShadowMaterialView;\n })\n );\n }\n await Promise.all(loads);\n}\n\n/** @internal Compute the ESM directional light view/projection matrix for ShadowTask. */\nfunction _computeDirectionalLightMatrix(\n light: DirectionalLight,\n casterMeshes: readonly Mesh[],\n orthoMinZ: number,\n orthoMaxZ: number,\n offX = 0,\n offY = 0,\n offZ = 0\n): EsmLightMatrix {\n const view = buildLightViewMatrix(light.direction.x, light.direction.y, light.direction.z, light.position.x - offX, light.position.y - offY, light.position.z - offZ);\n let lMinX = Infinity;\n let lMaxX = -Infinity;\n let lMinY = Infinity;\n let lMaxY = -Infinity;\n for (const mesh of casterMeshes) {\n const world = mesh.worldMatrix;\n const bmin = mesh.boundMin ?? [-0.5, -0.5, -0.5];\n const bmax = mesh.boundMax ?? [0.5, 0.5, 0.5];\n for (let ci = 0; ci < 8; ci++) {\n const lx = ci & 1 ? bmax[0]! : bmin[0]!;\n const ly = ci & 2 ? bmax[1]! : bmin[1]!;\n const lz = ci & 4 ? bmax[2]! : bmin[2]!;\n const wx = world[0]! * lx + world[4]! * ly + world[8]! * lz + world[12]! - offX;\n const wy = world[1]! * lx + world[5]! * ly + world[9]! * lz + world[13]! - offY;\n const wz = world[2]! * lx + world[6]! * ly + world[10]! * lz + world[14]! - offZ;\n const vx = view[0]! * wx + view[4]! * wy + view[8]! * wz + view[12]!;\n const vy = view[1]! * wx + view[5]! * wy + view[9]! * wz + view[13]!;\n lMinX = Math.min(lMinX, vx);\n lMaxX = Math.max(lMaxX, vx);\n lMinY = Math.min(lMinY, vy);\n lMaxY = Math.max(lMaxY, vy);\n }\n }\n if (!Number.isFinite(lMinX)) {\n lMinX = -1;\n lMaxX = 1;\n lMinY = -1;\n lMaxY = 1;\n }\n const sx = (lMaxX - lMinX) * 0.1;\n const sy = (lMaxY - lMinY) * 0.1;\n lMinX -= sx;\n lMaxX += sx;\n lMinY -= sy;\n lMaxY += sy;\n\n const near = orthoMinZ;\n const far = orthoMaxZ;\n const proj = new F32(16);\n proj[0] = 2 / (lMaxX - lMinX);\n proj[5] = 2 / (lMaxY - lMinY);\n proj[10] = 1 / (far - near);\n proj[12] = -(lMaxX + lMinX) / (lMaxX - lMinX);\n proj[13] = -(lMaxY + lMinY) / (lMaxY - lMinY);\n proj[14] = -near / (far - near);\n proj[15] = 1;\n return { _view: view, _viewProj: multiply4x4(proj, view), _near: near, _far: far };\n}\n\nfunction nearestBestKernel(idealKernel: number): number {\n const v = Math.round(Math.max(idealKernel, 1));\n for (const k of [v, v - 1, v + 1, v - 2, v + 2]) {\n if (k % 2 !== 0 && Math.floor(k / 2) % 2 === 0 && k > 0) {\n return Math.max(k, 3);\n }\n }\n return Math.max(v, 3);\n}\n\nfunction gaussianWeight(x: number): number {\n const sigma = 1 / 3;\n return Math.exp(-((x * x) / (2 * sigma * sigma))) / (Math.sqrt(2 * Math.PI) * sigma);\n}\n\nfunction createKernelBlurSamples(idealKernel: number): { offsets: number[]; weights: number[] } {\n const n = nearestBestKernel(idealKernel);\n const centerIndex = (n - 1) / 2;\n const offsets: number[] = [];\n const weights: number[] = [];\n let totalWeight = 0;\n\n for (let i = 0; i < n; i++) {\n const u = i / (n - 1);\n const weight = gaussianWeight(u * 2.0 - 1);\n offsets[i] = i - centerIndex;\n weights[i] = weight;\n totalWeight += weight;\n }\n\n for (let i = 0; i < weights.length; i++) {\n weights[i] = weights[i]! / totalWeight;\n }\n\n const linearOffsets: number[] = [];\n const linearWeights: number[] = [];\n for (let i = 0; i <= centerIndex; i += 2) {\n const j = Math.min(i + 1, Math.floor(centerIndex));\n if (i === j) {\n linearOffsets.push(offsets[i]!);\n linearWeights.push(weights[i]!);\n continue;\n }\n\n const sharedCell = j === centerIndex;\n const weightLinear = weights[i]! + weights[j]! * (sharedCell ? 0.5 : 1);\n const offsetLinear = offsets[i]! + 1 / (1 + weights[i]! / weights[j]!);\n if (offsetLinear === 0) {\n linearOffsets.push(offsets[i]!, offsets[i + 1]!);\n linearWeights.push(weights[i]!, weights[i + 1]!);\n } else {\n linearOffsets.push(offsetLinear, -offsetLinear);\n linearWeights.push(weightLinear, weightLinear);\n }\n }\n\n return { offsets: linearOffsets, weights: linearWeights };\n}\n\nfunction wgslFloat(value: number): string {\n const n = Object.is(value, -0) ? 0 : value;\n let s = n.toPrecision(10);\n if (!/[.eE]/.test(s)) {\n s += \".0\";\n }\n return s;\n}\n\nfunction createShadowBlurFragmentWGSL(blurKernel: number): string {\n const { offsets, weights } = createKernelBlurSamples(blurKernel);\n const count = offsets.length;\n return `struct BlurParams{delta:vec2<f32>,_pad:vec2<f32>,};@group(0) @binding(0) var<uniform> params:BlurParams;@group(0) @binding(1) var srcTex:texture_2d<f32>;@group(0) @binding(2) var srcSampler:sampler;const OFFSETS=array<f32,${count}>(${offsets.map(wgslFloat).join(\",\")});const WEIGHTS=array<f32,${count}>(${weights.map(wgslFloat).join(\",\")});@fragment fn main(@location(0) sampleCenter:vec2<f32>)->@location(0) vec4<f32>{var blend=vec4<f32>(0.0);for(var i=0u;i<${count}u;i=i+1u){blend+=textureSample(srcTex,srcSampler,sampleCenter+params.delta*OFFSETS[i])*WEIGHTS[i];}return blend;}`;\n}\n\nfunction ensureEsmShadowTaskState(\n engine: EngineContext,\n scene: SceneContext,\n sg: ShadowGenerator,\n casterMeshes: readonly Mesh[],\n existingState: ShadowTaskInternalState | null\n): EsmTaskState {\n const existing = existingState as EsmTaskState | null;\n if (existing) {\n if (existing._casterMeshes === casterMeshes) {\n return existing;\n }\n existing._task.dispose();\n }\n const resources = getEsmShadowTaskResources(sg);\n if (!resources) {\n throw new Error(\"ShadowTask: missing ESM metadata.\");\n }\n const materialViews = new Map<Material, MaterialView>();\n const camera = createShadowCamera(sg);\n const taskState: EsmTaskState = {\n _task: createRenderTask(\n {\n name: \"esm\",\n rt: createShadowRenderTarget(sg, resources._esmTexture, resources._depthBuffer),\n clr: true,\n clrColor: { r: 0, g: 0, b: 0, a: 0 },\n cam: camera,\n _skipClusteredLights: true,\n },\n engine,\n scene\n ),\n _camera: camera,\n _cameraVersion: 0,\n _lastCasterVersion: -1,\n _lastLightVersion: -1,\n _lastFoVersion: -1,\n _casterMeshes: casterMeshes,\n _scene: scene,\n };\n\n for (const mesh of casterMeshes) {\n const material = mesh.material;\n if (material) {\n taskState._task.addMesh(mesh, { material: getEsmShadowView(material, materialViews, sg._shadowParamsUBO) });\n }\n }\n\n return taskState;\n}\n\nfunction renderEsmShadowMap(engine: EngineContext, sg: ShadowGenerator, state: EsmTaskState): number {\n const resources = getEsmShadowTaskResources(sg);\n if (!resources) {\n return 0;\n }\n const casterMeshes = state._casterMeshes;\n const casterVersion = casterVersionSum(casterMeshes);\n const lightVersion = sg._light.worldMatrixVersion;\n const foCam = engine.useFloatingOrigin ? state._scene.camera : null;\n const foVersion = foCam ? foCam.worldMatrixVersion : 0;\n const offX = foCam ? foCam.worldMatrix[12]! : 0;\n const offY = foCam ? foCam.worldMatrix[13]! : 0;\n const offZ = foCam ? foCam.worldMatrix[14]! : 0;\n if (!sg._config._forceRefreshEveryFrame && casterVersion === state._lastCasterVersion && lightVersion === state._lastLightVersion && foVersion === state._lastFoVersion) {\n return 0;\n }\n\n const matrix = _computeDirectionalLightMatrix(sg._light as DirectionalLight, casterMeshes, sg._config._orthoMinZ!, sg._config._orthoMaxZ!, offX, offY, offZ);\n if (shadowMatrixChanged(sg._lightMatrix, matrix._viewProj)) {\n packMat4IntoF32(sg._lightMatrix, matrix._viewProj, 0);\n sg._version++;\n writeShadowUboFields(resources._shadowUboData, sg);\n engine._device.queue.writeBuffer(sg._shadowUBO, 0, resources._shadowUboData as Float32Array<ArrayBuffer>);\n }\n updateShadowCamera(state, matrix);\n state._lastCasterVersion = casterVersion;\n state._lastLightVersion = lightVersion;\n state._lastFoVersion = foVersion;\n\n let draws = state._task.execute?.() ?? 0;\n const encoder = engine._currentEncoder;\n const bh = encoder.beginRenderPass({\n colorAttachments: [\n {\n view: resources._blurTexH.createView(),\n loadOp: \"clear\",\n storeOp: \"store\",\n clearValue: { r: 0, g: 0, b: 0, a: 0 },\n },\n ],\n });\n bh.setPipeline(resources._blurPipeline);\n bh.setBindGroup(0, resources._blurHBG);\n bh.draw(3);\n bh.end();\n\n const bv = encoder.beginRenderPass({\n colorAttachments: [\n {\n view: sg._depthTexture.createView(),\n loadOp: \"clear\",\n storeOp: \"store\",\n clearValue: { r: 0, g: 0, b: 0, a: 0 },\n },\n ],\n });\n bv.setPipeline(resources._blurPipeline);\n bv.setBindGroup(0, resources._blurVBG);\n bv.draw(3);\n bv.end();\n draws += 2;\n return draws;\n}\n\nfunction updateShadowCamera(state: EsmTaskState, matrix: EsmLightMatrix): void {\n state._cameraVersion++;\n updateShadowCameraBase(state._camera, state._cameraVersion, matrix._near, matrix._far, matrix._view, matrix._viewProj);\n}\n\nfunction getEsmShadowView(material: Material, cache: Map<Material, MaterialView>, shadowParamsUBO: GPUBuffer): MaterialView {\n const cached = cache.get(material);\n if (cached) {\n return cached;\n }\n const family = material._buildGroup._materialFamily;\n let view: MaterialView;\n if (family === \"standard\") {\n view = createStandardEsmShadowMaterialView(material as Parameters<StandardEsmFactory>[0], shadowParamsUBO);\n } else if (family === \"pbr\") {\n view = createPbrEsmShadowMaterialView(material as Parameters<PbrEsmFactory>[0], shadowParamsUBO);\n } else if (family === \"node\") {\n view = createNodeEsmShadowMaterialView(material as Parameters<NodeEsmFactory>[0], shadowParamsUBO);\n }\n cache.set(material, view!);\n return view!;\n}\n\nfunction shadowMatrixChanged(a: Float32Array, b: Float32Array): boolean {\n for (let i = 0; i < 16; i++) {\n if (a[i] !== b[i]) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Creates an exponential shadow map (ESM) shadow generator for a directional light,\n * including the depth, blur, and final ESM textures plus the per-frame render task hooks.\n * @param engine - The engine providing the GPU device.\n * @param _light - The directional light that casts the shadows.\n * @param cfg - Optional shadow-map, blur, and projection configuration.\n * @returns A `ShadowGenerator` wired to the directional ESM render path.\n */\nexport function createEsmDirectionalShadowGenerator(engine: EngineContext, _light: DirectionalLight, cfg: EsmDirectionalShadowGeneratorConfig = {}): ShadowGenerator {\n const device = engine._device;\n const mapSize = cfg.mapSize ?? 1024;\n const depthScale = cfg.depthScale ?? 50;\n const bias = cfg.bias ?? 0.00005;\n const blurKernel = cfg.blurKernel ?? 1;\n const blurScale = cfg.blurScale ?? 2;\n const darkness = cfg.darkness ?? 0;\n const frustumEdgeFalloff = cfg.frustumEdgeFalloff ?? 0;\n const orthoMinZ = cfg.orthoMinZ ?? 1;\n const orthoMaxZ = cfg.orthoMaxZ ?? 10000;\n const forceRefreshEveryFrame = cfg.forceRefreshEveryFrame ?? false;\n const blurSize = mapSize / blurScale;\n\n const _config: ShadowGenerator[\"_config\"] = {\n _mapSize: mapSize,\n _bias: bias,\n _orthoMinZ: orthoMinZ,\n _orthoMaxZ: orthoMaxZ,\n _forceRefreshEveryFrame: forceRefreshEveryFrame,\n };\n\n const _shadowParamsUBO = createShadowParamsUBO(engine, bias, depthScale);\n\n const esmTexture = device.createTexture({\n size: { width: mapSize, height: mapSize },\n format: \"rgba16float\",\n usage: TU.RENDER_ATTACHMENT | TU.TEXTURE_BINDING,\n });\n const depthBuf = device.createTexture({\n size: { width: mapSize, height: mapSize },\n format: \"depth32float\",\n usage: TU.RENDER_ATTACHMENT,\n });\n const blurTexH = device.createTexture({\n size: { width: blurSize, height: blurSize },\n format: \"rgba16float\",\n usage: TU.RENDER_ATTACHMENT | TU.TEXTURE_BINDING,\n });\n const blurTexV = device.createTexture({\n size: { width: blurSize, height: blurSize },\n format: \"rgba16float\",\n usage: TU.RENDER_ATTACHMENT | TU.TEXTURE_BINDING,\n });\n\n const blurVert = device.createShaderModule({ code: blurVertSrc });\n const blurFrag = device.createShaderModule({ code: createShadowBlurFragmentWGSL(blurKernel) });\n const blurBGL = device.createBindGroupLayout({\n entries: [\n { binding: 0, visibility: SS.VERTEX | SS.FRAGMENT, buffer: { type: \"uniform\" } },\n { binding: 1, visibility: SS.FRAGMENT, texture: { sampleType: \"float\" } },\n { binding: 2, visibility: SS.FRAGMENT, sampler: { type: \"filtering\" } },\n ],\n });\n const blurPipeline = device.createRenderPipeline({\n layout: device.createPipelineLayout({ bindGroupLayouts: [blurBGL] }),\n vertex: { module: blurVert, entryPoint: \"main\" },\n fragment: { module: blurFrag, entryPoint: \"main\", targets: [{ format: \"rgba16float\" }] },\n primitive: { topology: \"triangle-list\", cullMode: \"none\" },\n });\n\n const blurSampler = getBilinearSampler(engine);\n const blurHData = new F32([1.0 / blurSize, 0, 0, 0]);\n const blurHUBO = createUniformBuffer(engine, blurHData);\n const blurHBG = device.createBindGroup({\n layout: blurBGL,\n entries: [\n { binding: 0, resource: { buffer: blurHUBO } },\n { binding: 1, resource: esmTexture.createView() },\n { binding: 2, resource: blurSampler },\n ],\n });\n const blurVData = new F32([0, 1.0 / blurSize, 0, 0]);\n const blurVUBO = createUniformBuffer(engine, blurVData);\n const blurVBG = device.createBindGroup({\n layout: blurBGL,\n entries: [\n { binding: 0, resource: { buffer: blurVUBO } },\n { binding: 1, resource: blurTexH.createView() },\n { binding: 2, resource: blurSampler },\n ],\n });\n\n const _lightMatrix = new F32(16);\n const _shadowsInfo = new F32([darkness, 0, depthScale, frustumEdgeFalloff]);\n const _depthValues = new F32([0, 1]);\n const { ubo: _shadowUBO, data: shadowUboData } = createSharedShadowUBO(engine, _lightMatrix, _depthValues, _shadowsInfo);\n const _depthTexture = blurTexV;\n const _depthSampler = blurSampler;\n\n const sg: ShadowGenerator = {\n _shadowType: \"esm\",\n _light,\n _depthTexture,\n _depthSampler,\n _lightMatrix,\n _shadowsInfo,\n _depthValues,\n _shadowParamsUBO,\n _shadowUBO,\n _config,\n _version: 0,\n };\n sg._preloadShadowTask = preloadEsmShadowTaskState;\n sg._ensureShadowTaskState = (engine, scene, casterMeshes) => {\n const state = ensureEsmShadowTaskState(engine, scene, sg, casterMeshes, sg._shadowTaskState ?? null);\n sg._shadowTaskState = state;\n return state;\n };\n sg._renderShadowMap = (engine, state) => {\n return renderEsmShadowMap(engine, sg, state as EsmTaskState);\n };\n setEsmShadowTaskResources(sg, {\n _esmTexture: esmTexture,\n _depthBuffer: depthBuf,\n _blurTexH: blurTexH,\n _blurPipeline: blurPipeline,\n _blurHBG: blurHBG,\n _blurVBG: blurVBG,\n _shadowUboData: shadowUboData,\n });\n return sg;\n}\n"],"names":["engine"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"esm-directional-shadow-generator.js","sources":["../../../shaders/shadow-blur.vertex.wgsl?raw","../../../src/shadow/esm-directional-shadow-generator.ts"],"sourcesContent":["export default \"// Shadow Blur Vertex Shader — fullscreen quad with pre-computed sample coordinates\\n// Uses Babylon's kernel blur approach with bilinear tap offsets\\n\\nstruct BlurParams {\\n delta: vec2<f32>, // (1/texWidth, 0) for H pass, (0, 1/texHeight) for V pass\\n _pad: vec2<f32>,\\n};\\n@group(0) @binding(0) var<uniform> params: BlurParams;\\n\\nstruct VertexOutput {\\n @builtin(position) clipPos: vec4<f32>,\\n @location(0) sampleCenter: vec2<f32>,\\n};\\n\\n@vertex\\nfn main(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {\\n // Fullscreen triangle (3 vertices cover the screen)\\n var pos = array<vec2<f32>, 3>(\\n vec2<f32>(-1.0, -1.0),\\n vec2<f32>(3.0, -1.0),\\n vec2<f32>(-1.0, 3.0),\\n );\\n\\n var out: VertexOutput;\\n let p = pos[vertexIndex];\\n out.clipPos = vec4<f32>(p, 0.0, 1.0);\\n out.sampleCenter = p * vec2<f32>(0.5, -0.5) + 0.5;\\n return out;\\n}\\n\"","/**\n * Exponential Shadow Map (ESM) generator resource setup.\n *\n * This module creates the directional shadow resources and owns the internal\n * task hooks used by frame-graph/shadow-task.ts.\n */\n\nimport { F32 } from \"../engine/typed-arrays.js\";\nimport { TU, SS } from \"../engine/gpu-flags.js\";\nimport type { Camera } from \"../camera/camera.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { DirectionalLight } from \"../light/directional-light.js\";\nimport type { Material, MaterialView } from \"../material/material.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport { createUniformBuffer } from \"../resource/gpu-buffers.js\";\nimport { getBilinearSampler } from \"../resource/samplers.js\";\nimport type { SceneContext } from \"../scene/scene-core.js\";\nimport { createRenderTask, type RenderTask } from \"../frame-graph/render-task.js\";\nimport {\n casterVersionSum,\n computeDirectionalLightMatrix,\n createSharedShadowUBO,\n createShadowCamera,\n createShadowParamsUBO,\n createShadowRenderTarget,\n updateShadowCameraBase,\n writeShadowUboFields,\n} from \"./shadow-base.js\";\nimport type { ShadowGenerator, ShadowTaskInternalState } from \"./shadow-generator.js\";\nimport blurVertSrc from \"../../shaders/shadow-blur.vertex.wgsl?raw\";\nimport { packMat4IntoF32 } from \"../math/pack-mat4-into-f32.js\";\n\nexport interface EsmLightMatrix {\n /** @internal */\n _view: Float32Array;\n /** @internal */\n _viewProj: Float32Array;\n /** @internal */\n _near: number;\n /** @internal */\n _far: number;\n}\n\nexport interface EsmShadowTaskResources {\n /** @internal */\n _esmTexture: GPUTexture;\n /** @internal */\n _depthBuffer: GPUTexture;\n /** @internal */\n _blurTexH: GPUTexture;\n /** @internal */\n _blurPipeline: GPURenderPipeline;\n /** @internal */\n _blurHBG: GPUBindGroup;\n /** @internal */\n _blurVBG: GPUBindGroup;\n /** @internal */\n _shadowUboData: Float32Array;\n}\n\n/** Configuration for a directional-light ESM shadow generator: map size, depth scale, blur kernel, darkness, and ortho projection bounds. */\nexport interface EsmDirectionalShadowGeneratorConfig {\n mapSize?: number;\n depthScale?: number;\n bias?: number;\n /** Kernel blur sample region in pixels. Matches Babylon.js ShadowGenerator.blurKernel. Default 1. */\n blurKernel?: number;\n blurScale?: number;\n darkness?: number;\n frustumEdgeFalloff?: number;\n /** Ortho projection min Z — typically camera.nearPlane. Default 1. */\n orthoMinZ?: number;\n /** Ortho projection max Z — typically camera.farPlane. Default 10000. */\n orthoMaxZ?: number;\n /** Force the shadow map to be regenerated every frame. Default false. */\n forceRefreshEveryFrame?: boolean;\n}\n\ninterface EsmTaskState extends ShadowTaskInternalState {\n _task: RenderTask;\n _camera: Camera;\n _cameraVersion: number;\n _lastCasterVersion: number;\n _lastLightVersion: number;\n /** @internal Floating-origin offset version (active camera worldMatrixVersion) at last shadow-map render; -1 when never rendered. */\n _lastFoVersion: number;\n _casterMeshes: readonly Mesh[];\n /** @internal Owning scene — used to read the live floating-origin offset (camera world position). */\n _scene: SceneContext;\n}\n\ntype StandardEsmFactory = typeof import(\"../material/standard/esm-shadow-view.js\").createStandardEsmShadowMaterialView;\ntype PbrEsmFactory = typeof import(\"../material/pbr/esm-shadow-view.js\").createPbrEsmShadowMaterialView;\ntype NodeEsmFactory = typeof import(\"../material/node/esm-shadow-view.js\").createNodeEsmShadowMaterialView;\n\nlet esmShadowTaskResources: WeakMap<ShadowGenerator, EsmShadowTaskResources> | null = null;\nlet createStandardEsmShadowMaterialView: StandardEsmFactory;\nlet createPbrEsmShadowMaterialView: PbrEsmFactory;\nlet createNodeEsmShadowMaterialView: NodeEsmFactory;\n\nfunction getEsmShadowTaskResourceMap(): WeakMap<ShadowGenerator, EsmShadowTaskResources> {\n esmShadowTaskResources ??= new WeakMap<ShadowGenerator, EsmShadowTaskResources>();\n return esmShadowTaskResources;\n}\n\nfunction setEsmShadowTaskResources(sg: ShadowGenerator, resources: EsmShadowTaskResources): void {\n getEsmShadowTaskResourceMap().set(sg, resources);\n}\n\nfunction getEsmShadowTaskResources(sg: ShadowGenerator): EsmShadowTaskResources | null {\n return esmShadowTaskResources?.get(sg) ?? null;\n}\n\nasync function preloadEsmShadowTaskState(casterMeshes: readonly Mesh[]): Promise<void> {\n const loads: Promise<void>[] = [];\n let needsStandard = false;\n let needsPbr = false;\n let needsNode = false;\n for (const mesh of casterMeshes) {\n const family = mesh.material?._buildGroup._materialFamily;\n needsStandard ||= family === \"standard\";\n needsPbr ||= family === \"pbr\";\n needsNode ||= family === \"node\";\n }\n if (needsStandard && !createStandardEsmShadowMaterialView) {\n loads.push(\n import(\"../material/standard/esm-shadow-view.js\").then((module) => {\n createStandardEsmShadowMaterialView = module.createStandardEsmShadowMaterialView;\n })\n );\n }\n if (needsPbr && !createPbrEsmShadowMaterialView) {\n loads.push(\n import(\"../material/pbr/esm-shadow-view.js\").then((module) => {\n createPbrEsmShadowMaterialView = module.createPbrEsmShadowMaterialView;\n })\n );\n }\n if (needsNode && !createNodeEsmShadowMaterialView) {\n loads.push(\n import(\"../material/node/esm-shadow-view.js\").then((module) => {\n createNodeEsmShadowMaterialView = module.createNodeEsmShadowMaterialView;\n })\n );\n }\n await Promise.all(loads);\n}\n\nfunction nearestBestKernel(idealKernel: number): number {\n const v = Math.round(Math.max(idealKernel, 1));\n for (const k of [v, v - 1, v + 1, v - 2, v + 2]) {\n if (k % 2 !== 0 && Math.floor(k / 2) % 2 === 0 && k > 0) {\n return Math.max(k, 3);\n }\n }\n return Math.max(v, 3);\n}\n\nfunction gaussianWeight(x: number): number {\n const sigma = 1 / 3;\n return Math.exp(-((x * x) / (2 * sigma * sigma))) / (Math.sqrt(2 * Math.PI) * sigma);\n}\n\nfunction createKernelBlurSamples(idealKernel: number): { offsets: number[]; weights: number[] } {\n const n = nearestBestKernel(idealKernel);\n const centerIndex = (n - 1) / 2;\n const offsets: number[] = [];\n const weights: number[] = [];\n let totalWeight = 0;\n\n for (let i = 0; i < n; i++) {\n const u = i / (n - 1);\n const weight = gaussianWeight(u * 2.0 - 1);\n offsets[i] = i - centerIndex;\n weights[i] = weight;\n totalWeight += weight;\n }\n\n for (let i = 0; i < weights.length; i++) {\n weights[i] = weights[i]! / totalWeight;\n }\n\n const linearOffsets: number[] = [];\n const linearWeights: number[] = [];\n for (let i = 0; i <= centerIndex; i += 2) {\n const j = Math.min(i + 1, Math.floor(centerIndex));\n if (i === j) {\n linearOffsets.push(offsets[i]!);\n linearWeights.push(weights[i]!);\n continue;\n }\n\n const sharedCell = j === centerIndex;\n const weightLinear = weights[i]! + weights[j]! * (sharedCell ? 0.5 : 1);\n const offsetLinear = offsets[i]! + 1 / (1 + weights[i]! / weights[j]!);\n if (offsetLinear === 0) {\n linearOffsets.push(offsets[i]!, offsets[i + 1]!);\n linearWeights.push(weights[i]!, weights[i + 1]!);\n } else {\n linearOffsets.push(offsetLinear, -offsetLinear);\n linearWeights.push(weightLinear, weightLinear);\n }\n }\n\n return { offsets: linearOffsets, weights: linearWeights };\n}\n\nfunction wgslFloat(value: number): string {\n const n = Object.is(value, -0) ? 0 : value;\n let s = n.toPrecision(10);\n if (!/[.eE]/.test(s)) {\n s += \".0\";\n }\n return s;\n}\n\nfunction createShadowBlurFragmentWGSL(blurKernel: number): string {\n const { offsets, weights } = createKernelBlurSamples(blurKernel);\n const count = offsets.length;\n return `struct BlurParams{delta:vec2<f32>,_pad:vec2<f32>,};@group(0) @binding(0) var<uniform> params:BlurParams;@group(0) @binding(1) var srcTex:texture_2d<f32>;@group(0) @binding(2) var srcSampler:sampler;const OFFSETS=array<f32,${count}>(${offsets.map(wgslFloat).join(\",\")});const WEIGHTS=array<f32,${count}>(${weights.map(wgslFloat).join(\",\")});@fragment fn main(@location(0) sampleCenter:vec2<f32>)->@location(0) vec4<f32>{var blend=vec4<f32>(0.0);for(var i=0u;i<${count}u;i=i+1u){blend+=textureSample(srcTex,srcSampler,sampleCenter+params.delta*OFFSETS[i])*WEIGHTS[i];}return blend;}`;\n}\n\nfunction ensureEsmShadowTaskState(\n engine: EngineContext,\n scene: SceneContext,\n sg: ShadowGenerator,\n casterMeshes: readonly Mesh[],\n existingState: ShadowTaskInternalState | null\n): EsmTaskState {\n const existing = existingState as EsmTaskState | null;\n if (existing) {\n if (existing._casterMeshes === casterMeshes) {\n return existing;\n }\n existing._task.dispose();\n }\n const resources = getEsmShadowTaskResources(sg);\n if (!resources) {\n throw new Error(\"ShadowTask: missing ESM metadata.\");\n }\n const materialViews = new Map<Material, MaterialView>();\n const camera = createShadowCamera(sg);\n const taskState: EsmTaskState = {\n _task: createRenderTask(\n {\n name: \"esm\",\n rt: createShadowRenderTarget(sg, resources._esmTexture, resources._depthBuffer),\n clr: true,\n clrColor: { r: 0, g: 0, b: 0, a: 0 },\n cam: camera,\n _skipClusteredLights: true,\n },\n engine,\n scene\n ),\n _camera: camera,\n _cameraVersion: 0,\n _lastCasterVersion: -1,\n _lastLightVersion: -1,\n _lastFoVersion: -1,\n _casterMeshes: casterMeshes,\n _scene: scene,\n };\n\n for (const mesh of casterMeshes) {\n const material = mesh.material;\n if (material) {\n taskState._task.addMesh(mesh, { material: getEsmShadowView(material, materialViews, sg._shadowParamsUBO) });\n }\n }\n\n return taskState;\n}\n\nfunction renderEsmShadowMap(engine: EngineContext, sg: ShadowGenerator, state: EsmTaskState): number {\n const resources = getEsmShadowTaskResources(sg);\n if (!resources) {\n return 0;\n }\n const casterMeshes = state._casterMeshes;\n const casterVersion = casterVersionSum(casterMeshes);\n const lightVersion = sg._light.worldMatrixVersion;\n const foCam = engine.useFloatingOrigin ? state._scene.camera : null;\n const foVersion = foCam ? foCam.worldMatrixVersion : 0;\n const offX = foCam ? foCam.worldMatrix[12]! : 0;\n const offY = foCam ? foCam.worldMatrix[13]! : 0;\n const offZ = foCam ? foCam.worldMatrix[14]! : 0;\n if (!sg._config._forceRefreshEveryFrame && casterVersion === state._lastCasterVersion && lightVersion === state._lastLightVersion && foVersion === state._lastFoVersion) {\n return 0;\n }\n\n const matrix = computeDirectionalLightMatrix(sg._light as DirectionalLight, casterMeshes, sg._config._orthoMinZ!, sg._config._orthoMaxZ!, offX, offY, offZ);\n if (shadowMatrixChanged(sg._lightMatrix, matrix._viewProj)) {\n packMat4IntoF32(sg._lightMatrix, matrix._viewProj, 0);\n sg._version++;\n writeShadowUboFields(resources._shadowUboData, sg);\n engine._device.queue.writeBuffer(sg._shadowUBO, 0, resources._shadowUboData as Float32Array<ArrayBuffer>);\n }\n updateShadowCamera(state, matrix);\n state._lastCasterVersion = casterVersion;\n state._lastLightVersion = lightVersion;\n state._lastFoVersion = foVersion;\n\n let draws = state._task.execute?.() ?? 0;\n const encoder = engine._currentEncoder;\n const bh = encoder.beginRenderPass({\n colorAttachments: [\n {\n view: resources._blurTexH.createView(),\n loadOp: \"clear\",\n storeOp: \"store\",\n clearValue: { r: 0, g: 0, b: 0, a: 0 },\n },\n ],\n });\n bh.setPipeline(resources._blurPipeline);\n bh.setBindGroup(0, resources._blurHBG);\n bh.draw(3);\n bh.end();\n\n const bv = encoder.beginRenderPass({\n colorAttachments: [\n {\n view: sg._depthTexture.createView(),\n loadOp: \"clear\",\n storeOp: \"store\",\n clearValue: { r: 0, g: 0, b: 0, a: 0 },\n },\n ],\n });\n bv.setPipeline(resources._blurPipeline);\n bv.setBindGroup(0, resources._blurVBG);\n bv.draw(3);\n bv.end();\n draws += 2;\n return draws;\n}\n\nfunction updateShadowCamera(state: EsmTaskState, matrix: EsmLightMatrix): void {\n state._cameraVersion++;\n updateShadowCameraBase(state._camera, state._cameraVersion, matrix._near, matrix._far, matrix._view, matrix._viewProj);\n}\n\nfunction getEsmShadowView(material: Material, cache: Map<Material, MaterialView>, shadowParamsUBO: GPUBuffer): MaterialView {\n const cached = cache.get(material);\n if (cached) {\n return cached;\n }\n const family = material._buildGroup._materialFamily;\n let view: MaterialView;\n if (family === \"standard\") {\n view = createStandardEsmShadowMaterialView(material as Parameters<StandardEsmFactory>[0], shadowParamsUBO);\n } else if (family === \"pbr\") {\n view = createPbrEsmShadowMaterialView(material as Parameters<PbrEsmFactory>[0], shadowParamsUBO);\n } else if (family === \"node\") {\n view = createNodeEsmShadowMaterialView(material as Parameters<NodeEsmFactory>[0], shadowParamsUBO);\n }\n cache.set(material, view!);\n return view!;\n}\n\nfunction shadowMatrixChanged(a: Float32Array, b: Float32Array): boolean {\n for (let i = 0; i < 16; i++) {\n if (a[i] !== b[i]) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Creates an exponential shadow map (ESM) shadow generator for a directional light,\n * including the depth, blur, and final ESM textures plus the per-frame render task hooks.\n * @param engine - The engine providing the GPU device.\n * @param _light - The directional light that casts the shadows.\n * @param cfg - Optional shadow-map, blur, and projection configuration.\n * @returns A `ShadowGenerator` wired to the directional ESM render path.\n */\nexport function createEsmDirectionalShadowGenerator(engine: EngineContext, _light: DirectionalLight, cfg: EsmDirectionalShadowGeneratorConfig = {}): ShadowGenerator {\n const device = engine._device;\n const mapSize = cfg.mapSize ?? 1024;\n const depthScale = cfg.depthScale ?? 50;\n const bias = cfg.bias ?? 0.00005;\n const blurKernel = cfg.blurKernel ?? 1;\n const blurScale = cfg.blurScale ?? 2;\n const darkness = cfg.darkness ?? 0;\n const frustumEdgeFalloff = cfg.frustumEdgeFalloff ?? 0;\n const orthoMinZ = cfg.orthoMinZ ?? 1;\n const orthoMaxZ = cfg.orthoMaxZ ?? 10000;\n const forceRefreshEveryFrame = cfg.forceRefreshEveryFrame ?? false;\n const blurSize = mapSize / blurScale;\n\n const _config: ShadowGenerator[\"_config\"] = {\n _mapSize: mapSize,\n _bias: bias,\n _orthoMinZ: orthoMinZ,\n _orthoMaxZ: orthoMaxZ,\n _forceRefreshEveryFrame: forceRefreshEveryFrame,\n };\n\n const _shadowParamsUBO = createShadowParamsUBO(engine, bias, depthScale);\n\n const esmTexture = device.createTexture({\n size: { width: mapSize, height: mapSize },\n format: \"rgba16float\",\n usage: TU.RENDER_ATTACHMENT | TU.TEXTURE_BINDING,\n });\n const depthBuf = device.createTexture({\n size: { width: mapSize, height: mapSize },\n format: \"depth32float\",\n usage: TU.RENDER_ATTACHMENT,\n });\n const blurTexH = device.createTexture({\n size: { width: blurSize, height: blurSize },\n format: \"rgba16float\",\n usage: TU.RENDER_ATTACHMENT | TU.TEXTURE_BINDING,\n });\n const blurTexV = device.createTexture({\n size: { width: blurSize, height: blurSize },\n format: \"rgba16float\",\n usage: TU.RENDER_ATTACHMENT | TU.TEXTURE_BINDING,\n });\n\n const blurVert = device.createShaderModule({ code: blurVertSrc });\n const blurFrag = device.createShaderModule({ code: createShadowBlurFragmentWGSL(blurKernel) });\n const blurBGL = device.createBindGroupLayout({\n entries: [\n { binding: 0, visibility: SS.VERTEX | SS.FRAGMENT, buffer: { type: \"uniform\" } },\n { binding: 1, visibility: SS.FRAGMENT, texture: { sampleType: \"float\" } },\n { binding: 2, visibility: SS.FRAGMENT, sampler: { type: \"filtering\" } },\n ],\n });\n const blurPipeline = device.createRenderPipeline({\n layout: device.createPipelineLayout({ bindGroupLayouts: [blurBGL] }),\n vertex: { module: blurVert, entryPoint: \"main\" },\n fragment: { module: blurFrag, entryPoint: \"main\", targets: [{ format: \"rgba16float\" }] },\n primitive: { topology: \"triangle-list\", cullMode: \"none\" },\n });\n\n const blurSampler = getBilinearSampler(engine);\n const blurHData = new F32([1.0 / blurSize, 0, 0, 0]);\n const blurHUBO = createUniformBuffer(engine, blurHData);\n const blurHBG = device.createBindGroup({\n layout: blurBGL,\n entries: [\n { binding: 0, resource: { buffer: blurHUBO } },\n { binding: 1, resource: esmTexture.createView() },\n { binding: 2, resource: blurSampler },\n ],\n });\n const blurVData = new F32([0, 1.0 / blurSize, 0, 0]);\n const blurVUBO = createUniformBuffer(engine, blurVData);\n const blurVBG = device.createBindGroup({\n layout: blurBGL,\n entries: [\n { binding: 0, resource: { buffer: blurVUBO } },\n { binding: 1, resource: blurTexH.createView() },\n { binding: 2, resource: blurSampler },\n ],\n });\n\n const _lightMatrix = new F32(16);\n const _shadowsInfo = new F32([darkness, 0, depthScale, frustumEdgeFalloff]);\n const _depthValues = new F32([0, 1]);\n const { ubo: _shadowUBO, data: shadowUboData } = createSharedShadowUBO(engine, _lightMatrix, _depthValues, _shadowsInfo);\n const _depthTexture = blurTexV;\n const _depthSampler = blurSampler;\n\n const sg: ShadowGenerator = {\n _shadowType: \"esm\",\n _light,\n _depthTexture,\n _depthSampler,\n _lightMatrix,\n _shadowsInfo,\n _depthValues,\n _shadowParamsUBO,\n _shadowUBO,\n _config,\n _version: 0,\n };\n sg._preloadShadowTask = preloadEsmShadowTaskState;\n sg._ensureShadowTaskState = (engine, scene, casterMeshes) => {\n const state = ensureEsmShadowTaskState(engine, scene, sg, casterMeshes, sg._shadowTaskState ?? null);\n sg._shadowTaskState = state;\n return state;\n };\n sg._renderShadowMap = (engine, state) => {\n return renderEsmShadowMap(engine, sg, state as EsmTaskState);\n };\n setEsmShadowTaskResources(sg, {\n _esmTexture: esmTexture,\n _depthBuffer: depthBuf,\n _blurTexH: blurTexH,\n _blurPipeline: blurPipeline,\n _blurHBG: blurHBG,\n _blurVBG: blurVBG,\n _shadowUboData: shadowUboData,\n });\n return sg;\n}\n"],"names":["engine"],"mappings":"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"}
|
|
@@ -1,54 +1,8 @@
|
|
|
1
1
|
import { F32 } from '../engine/typed-arrays.js';
|
|
2
2
|
import { TU } from '../engine/gpu-flags.js';
|
|
3
|
-
import { createSharedShadowUBO, createShadowParamsUBO,
|
|
3
|
+
import { createSharedShadowUBO, createShadowParamsUBO, computeDirectionalLightMatrix } from './shadow-base.js';
|
|
4
4
|
import { preloadPcfShadowTaskState, ensurePcfShadowTaskState, renderPcfShadowMap } from './pcf-shadow-task-hooks.js';
|
|
5
5
|
|
|
6
|
-
function _computeDirectionalLightMatrix(light, casterMeshes, orthoMinZ, orthoMaxZ, offX = 0, offY = 0, offZ = 0) {
|
|
7
|
-
const view = buildLightViewMatrix(light.direction.x, light.direction.y, light.direction.z, light.position.x - offX, light.position.y - offY, light.position.z - offZ);
|
|
8
|
-
let lMinX = Infinity, lMaxX = -Infinity, lMinY = Infinity, lMaxY = -Infinity;
|
|
9
|
-
for (const mesh of casterMeshes) {
|
|
10
|
-
const world = mesh.worldMatrix;
|
|
11
|
-
const bmin = mesh.boundMin ?? [-0.5, -0.5, -0.5];
|
|
12
|
-
const bmax = mesh.boundMax ?? [0.5, 0.5, 0.5];
|
|
13
|
-
for (let ci = 0; ci < 8; ci++) {
|
|
14
|
-
const lx = ci & 1 ? bmax[0] : bmin[0];
|
|
15
|
-
const ly = ci & 2 ? bmax[1] : bmin[1];
|
|
16
|
-
const lz = ci & 4 ? bmax[2] : bmin[2];
|
|
17
|
-
const wx = world[0] * lx + world[4] * ly + world[8] * lz + world[12] - offX;
|
|
18
|
-
const wy = world[1] * lx + world[5] * ly + world[9] * lz + world[13] - offY;
|
|
19
|
-
const wz = world[2] * lx + world[6] * ly + world[10] * lz + world[14] - offZ;
|
|
20
|
-
const vx = view[0] * wx + view[4] * wy + view[8] * wz + view[12];
|
|
21
|
-
const vy = view[1] * wx + view[5] * wy + view[9] * wz + view[13];
|
|
22
|
-
lMinX = Math.min(lMinX, vx);
|
|
23
|
-
lMaxX = Math.max(lMaxX, vx);
|
|
24
|
-
lMinY = Math.min(lMinY, vy);
|
|
25
|
-
lMaxY = Math.max(lMaxY, vy);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
if (!Number.isFinite(lMinX)) {
|
|
29
|
-
lMinX = -1;
|
|
30
|
-
lMaxX = 1;
|
|
31
|
-
lMinY = -1;
|
|
32
|
-
lMaxY = 1;
|
|
33
|
-
}
|
|
34
|
-
const sx = (lMaxX - lMinX) * 0.1;
|
|
35
|
-
const sy = (lMaxY - lMinY) * 0.1;
|
|
36
|
-
lMinX -= sx;
|
|
37
|
-
lMaxX += sx;
|
|
38
|
-
lMinY -= sy;
|
|
39
|
-
lMaxY += sy;
|
|
40
|
-
const near = orthoMinZ;
|
|
41
|
-
const far = orthoMaxZ;
|
|
42
|
-
const proj = new F32(16);
|
|
43
|
-
proj[0] = 2 / (lMaxX - lMinX);
|
|
44
|
-
proj[5] = 2 / (lMaxY - lMinY);
|
|
45
|
-
proj[10] = 1 / (far - near);
|
|
46
|
-
proj[12] = -(lMaxX + lMinX) / (lMaxX - lMinX);
|
|
47
|
-
proj[13] = -(lMaxY + lMinY) / (lMaxY - lMinY);
|
|
48
|
-
proj[14] = -near / (far - near);
|
|
49
|
-
proj[15] = 1;
|
|
50
|
-
return { _view: view, _viewProj: multiply4x4(proj, view), _near: near, _far: far };
|
|
51
|
-
}
|
|
52
6
|
function createPcfDirectionalShadowGenerator(engine, _light, cfg = {}) {
|
|
53
7
|
const device = engine._device;
|
|
54
8
|
const mapSize = cfg.mapSize ?? 1024;
|
|
@@ -100,7 +54,7 @@ function createPcfDirectionalShadowGenerator(engine, _light, cfg = {}) {
|
|
|
100
54
|
engine2,
|
|
101
55
|
sg,
|
|
102
56
|
state,
|
|
103
|
-
(casterMeshes, offX, offY, offZ) =>
|
|
57
|
+
(casterMeshes, offX, offY, offZ) => computeDirectionalLightMatrix(_light, casterMeshes, orthoMinZ, orthoMaxZ, offX, offY, offZ)
|
|
104
58
|
);
|
|
105
59
|
};
|
|
106
60
|
return sg;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pcf-directional-shadow-generator.js","sources":["../../../src/shadow/pcf-directional-shadow-generator.ts"],"sourcesContent":["/** PCF Shadow Generator for Directional Lights.\n *\n * Same on-shader PCF5 sampling as `pcf-spotlight-shadow-generator.ts`, but with an\n * orthographic light projection fit to the caster AABBs — matching Babylon's\n * DirectionalLight + `usePercentageCloserFiltering=true` configuration.\n *\n * Everything downstream of the projection (depth-only pipeline, comparison\n * sampler, shared UBOs, dirty tracking) is identical to the spot-light PCF\n * path. The only differences are:\n * 1. The projection matrix (ortho vs perspective).\n * 2. The projection bounds auto-fit based on casters' world AABBs.\n *\n * Exported separately so scenes that only use spot-PCF don't pull in the\n * directional AABB-fit code path, and so the API parallels the ESM split\n * (`createEsmDirectionalShadowGenerator` → directional ESM, `createPcfSpotlightShadowGenerator` → spot PCF).\n */\n\nimport { F32 } from \"../engine/typed-arrays.js\";\nimport { TU } from \"../engine/gpu-flags.js\";\nimport type { DirectionalLight } from \"../light/directional-light.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { ShadowGenerator } from \"./shadow-generator.js\";\nimport { buildLightViewMatrix, createSharedShadowUBO, createShadowParamsUBO, multiply4x4 } from \"./shadow-base.js\";\nimport { ensurePcfShadowTaskState, preloadPcfShadowTaskState, renderPcfShadowMap, type PcfLightMatrix, type PcfTaskState } from \"./pcf-shadow-task-hooks.js\";\n\n// ─── Internal helpers ───────────────────────────────────────────────\n\n/** @internal Compute the PCF directional light view/projection matrix for ShadowTask.\n * Under floating-origin (`offX/offY/offZ` ≠ 0) the light view is built eye-relative\n * (offset subtracted from the light position) and the caster AABB corners are made\n * eye-relative too, so the returned view/viewProj match the eye-relative mesh world\n * matrices used by both the caster pass and the receiver shader. The projection bounds\n * are invariant under the offset (both light pos and corners shift by the same amount). */\nfunction _computeDirectionalLightMatrix(\n light: DirectionalLight,\n casterMeshes: readonly Mesh[],\n orthoMinZ: number,\n orthoMaxZ: number,\n offX = 0,\n offY = 0,\n offZ = 0\n): PcfLightMatrix {\n const view = buildLightViewMatrix(light.direction.x, light.direction.y, light.direction.z, light.position.x - offX, light.position.y - offY, light.position.z - offZ);\n let lMinX = Infinity,\n lMaxX = -Infinity,\n lMinY = Infinity,\n lMaxY = -Infinity;\n for (const mesh of casterMeshes) {\n const world = mesh.worldMatrix;\n const bmin = mesh.boundMin ?? [-0.5, -0.5, -0.5];\n const bmax = mesh.boundMax ?? [0.5, 0.5, 0.5];\n for (let ci = 0; ci < 8; ci++) {\n const lx = ci & 1 ? bmax[0] : bmin[0];\n const ly = ci & 2 ? bmax[1] : bmin[1];\n const lz = ci & 4 ? bmax[2] : bmin[2];\n const wx = world[0]! * lx + world[4]! * ly + world[8]! * lz + world[12]! - offX;\n const wy = world[1]! * lx + world[5]! * ly + world[9]! * lz + world[13]! - offY;\n const wz = world[2]! * lx + world[6]! * ly + world[10]! * lz + world[14]! - offZ;\n const vx = view[0]! * wx + view[4]! * wy + view[8]! * wz + view[12]!;\n const vy = view[1]! * wx + view[5]! * wy + view[9]! * wz + view[13]!;\n lMinX = Math.min(lMinX, vx);\n lMaxX = Math.max(lMaxX, vx);\n lMinY = Math.min(lMinY, vy);\n lMaxY = Math.max(lMaxY, vy);\n }\n }\n if (!Number.isFinite(lMinX)) {\n lMinX = -1;\n lMaxX = 1;\n lMinY = -1;\n lMaxY = 1;\n }\n const sx = (lMaxX - lMinX) * 0.1;\n const sy = (lMaxY - lMinY) * 0.1;\n lMinX -= sx;\n lMaxX += sx;\n lMinY -= sy;\n lMaxY += sy;\n\n const near = orthoMinZ;\n const far = orthoMaxZ;\n const proj = new F32(16);\n proj[0] = 2 / (lMaxX - lMinX);\n proj[5] = 2 / (lMaxY - lMinY);\n proj[10] = 1 / (far - near);\n proj[12] = -(lMaxX + lMinX) / (lMaxX - lMinX);\n proj[13] = -(lMaxY + lMinY) / (lMaxY - lMinY);\n proj[14] = -near / (far - near);\n proj[15] = 1;\n return { _view: view, _viewProj: multiply4x4(proj, view), _near: near, _far: far };\n}\n\n/** Configuration for a directional-light PCF shadow generator: map size, depth bias, darkness, and ortho projection bounds. */\nexport interface PcfDirectionalShadowGeneratorConfig {\n mapSize?: number;\n bias?: number;\n darkness?: number;\n normalBias?: number;\n /** Ortho near plane. Default 1. */\n orthoMinZ?: number;\n /** Ortho far plane. Default 10000. */\n orthoMaxZ?: number;\n /** Force the shadow map to be regenerated every frame. Default false. */\n forceRefreshEveryFrame?: boolean;\n}\n\n/**\n * Creates a PCF (percentage-closer filtering) shadow generator for a directional light,\n * using an orthographic projection auto-fit to the caster meshes' world AABBs.\n * @param engine - The engine providing the GPU device.\n * @param _light - The directional light that casts the shadows.\n * @param cfg - Optional shadow-map and projection configuration.\n * @returns A `ShadowGenerator` wired to the directional PCF render path.\n */\nexport function createPcfDirectionalShadowGenerator(engine: EngineContext, _light: DirectionalLight, cfg: PcfDirectionalShadowGeneratorConfig = {}): ShadowGenerator {\n const device = engine._device;\n const mapSize = cfg.mapSize ?? 1024;\n const bias = cfg.bias ?? 0.00005;\n const darkness = cfg.darkness ?? 0;\n const orthoMinZ = cfg.orthoMinZ ?? 1;\n const orthoMaxZ = cfg.orthoMaxZ ?? 10000;\n const forceRefreshEveryFrame = cfg.forceRefreshEveryFrame ?? false;\n\n const _lightMatrix = new F32(16);\n const _shadowsInfo = new F32([darkness, mapSize, 1.0 / mapSize, 0]);\n const _depthValues = new F32([0, 1]);\n const { ubo: _shadowUBO } = createSharedShadowUBO(engine, _lightMatrix, _depthValues, _shadowsInfo);\n const _config: ShadowGenerator[\"_config\"] = {\n _mapSize: mapSize,\n _bias: bias,\n _forceRefreshEveryFrame: forceRefreshEveryFrame,\n _orthoMinZ: orthoMinZ,\n _orthoMaxZ: orthoMaxZ,\n };\n\n const sg: ShadowGenerator = {\n _shadowType: \"pcf\" as const,\n _light,\n _depthTexture: device.createTexture({\n size: { width: mapSize, height: mapSize },\n format: \"depth32float\",\n usage: TU.RENDER_ATTACHMENT | TU.TEXTURE_BINDING,\n }),\n _depthSampler: device.createSampler({\n compare: \"less\",\n magFilter: \"linear\",\n minFilter: \"linear\",\n }),\n _lightMatrix,\n _shadowsInfo,\n _depthValues,\n _shadowParamsUBO: createShadowParamsUBO(engine, bias, 1.0 / mapSize),\n _shadowUBO,\n _config,\n _version: 0,\n };\n sg._preloadShadowTask = preloadPcfShadowTaskState;\n sg._ensureShadowTaskState = (engine, scene, casterMeshes) => {\n const state = ensurePcfShadowTaskState(engine, scene, sg, casterMeshes, sg._shadowTaskState ?? null);\n sg._shadowTaskState = state;\n return state;\n };\n sg._renderShadowMap = (engine, state) => {\n return renderPcfShadowMap(engine, sg, state as PcfTaskState, (casterMeshes, offX, offY, offZ) =>\n _computeDirectionalLightMatrix(_light, casterMeshes, orthoMinZ, orthoMaxZ, offX, offY, offZ)\n );\n };\n return sg;\n}\n"],"names":["engine"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pcf-directional-shadow-generator.js","sources":["../../../src/shadow/pcf-directional-shadow-generator.ts"],"sourcesContent":["/** PCF Shadow Generator for Directional Lights.\n *\n * Same on-shader PCF5 sampling as `pcf-spotlight-shadow-generator.ts`, but with an\n * orthographic light projection fit to the caster AABBs — matching Babylon's\n * DirectionalLight + `usePercentageCloserFiltering=true` configuration.\n *\n * Everything downstream of the projection (depth-only pipeline, comparison\n * sampler, shared UBOs, dirty tracking) is identical to the spot-light PCF\n * path. The only differences are:\n * 1. The projection matrix (ortho vs perspective).\n * 2. The projection bounds auto-fit based on casters' world AABBs.\n *\n * Exported separately so scenes that only use spot-PCF don't pull in the\n * directional AABB-fit code path, and so the API parallels the ESM split\n * (`createEsmDirectionalShadowGenerator` → directional ESM, `createPcfSpotlightShadowGenerator` → spot PCF).\n */\n\nimport { F32 } from \"../engine/typed-arrays.js\";\nimport { TU } from \"../engine/gpu-flags.js\";\nimport type { DirectionalLight } from \"../light/directional-light.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { ShadowGenerator } from \"./shadow-generator.js\";\nimport { computeDirectionalLightMatrix, createSharedShadowUBO, createShadowParamsUBO } from \"./shadow-base.js\";\nimport { ensurePcfShadowTaskState, preloadPcfShadowTaskState, renderPcfShadowMap, type PcfTaskState } from \"./pcf-shadow-task-hooks.js\";\n\n/** Configuration for a directional-light PCF shadow generator: map size, depth bias, darkness, and ortho projection bounds. */\nexport interface PcfDirectionalShadowGeneratorConfig {\n mapSize?: number;\n bias?: number;\n darkness?: number;\n normalBias?: number;\n /** Ortho near plane. Default 1. */\n orthoMinZ?: number;\n /** Ortho far plane. Default 10000. */\n orthoMaxZ?: number;\n /** Force the shadow map to be regenerated every frame. Default false. */\n forceRefreshEveryFrame?: boolean;\n}\n\n/**\n * Creates a PCF (percentage-closer filtering) shadow generator for a directional light,\n * using an orthographic projection auto-fit to the caster meshes' world AABBs.\n * @param engine - The engine providing the GPU device.\n * @param _light - The directional light that casts the shadows.\n * @param cfg - Optional shadow-map and projection configuration.\n * @returns A `ShadowGenerator` wired to the directional PCF render path.\n */\nexport function createPcfDirectionalShadowGenerator(engine: EngineContext, _light: DirectionalLight, cfg: PcfDirectionalShadowGeneratorConfig = {}): ShadowGenerator {\n const device = engine._device;\n const mapSize = cfg.mapSize ?? 1024;\n const bias = cfg.bias ?? 0.00005;\n const darkness = cfg.darkness ?? 0;\n const orthoMinZ = cfg.orthoMinZ ?? 1;\n const orthoMaxZ = cfg.orthoMaxZ ?? 10000;\n const forceRefreshEveryFrame = cfg.forceRefreshEveryFrame ?? false;\n\n const _lightMatrix = new F32(16);\n const _shadowsInfo = new F32([darkness, mapSize, 1.0 / mapSize, 0]);\n const _depthValues = new F32([0, 1]);\n const { ubo: _shadowUBO } = createSharedShadowUBO(engine, _lightMatrix, _depthValues, _shadowsInfo);\n const _config: ShadowGenerator[\"_config\"] = {\n _mapSize: mapSize,\n _bias: bias,\n _forceRefreshEveryFrame: forceRefreshEveryFrame,\n _orthoMinZ: orthoMinZ,\n _orthoMaxZ: orthoMaxZ,\n };\n\n const sg: ShadowGenerator = {\n _shadowType: \"pcf\" as const,\n _light,\n _depthTexture: device.createTexture({\n size: { width: mapSize, height: mapSize },\n format: \"depth32float\",\n usage: TU.RENDER_ATTACHMENT | TU.TEXTURE_BINDING,\n }),\n _depthSampler: device.createSampler({\n compare: \"less\",\n magFilter: \"linear\",\n minFilter: \"linear\",\n }),\n _lightMatrix,\n _shadowsInfo,\n _depthValues,\n _shadowParamsUBO: createShadowParamsUBO(engine, bias, 1.0 / mapSize),\n _shadowUBO,\n _config,\n _version: 0,\n };\n sg._preloadShadowTask = preloadPcfShadowTaskState;\n sg._ensureShadowTaskState = (engine, scene, casterMeshes) => {\n const state = ensurePcfShadowTaskState(engine, scene, sg, casterMeshes, sg._shadowTaskState ?? null);\n sg._shadowTaskState = state;\n return state;\n };\n sg._renderShadowMap = (engine, state) => {\n return renderPcfShadowMap(engine, sg, state as PcfTaskState, (casterMeshes, offX, offY, offZ) =>\n computeDirectionalLightMatrix(_light, casterMeshes, orthoMinZ, orthoMaxZ, offX, offY, offZ)\n );\n };\n return sg;\n}\n"],"names":["engine"],"mappings":";;;;;AA+CO,SAAS,mCAAA,CAAoC,MAAA,EAAuB,MAAA,EAA0B,GAAA,GAA2C,EAAC,EAAoB;AACjK,EAAA,MAAM,SAAS,MAAA,CAAO,OAAA;AACtB,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,IAAW,IAAA;AAC/B,EAAA,MAAM,IAAA,GAAO,IAAI,IAAA,IAAQ,IAAA;AACzB,EAAA,MAAM,QAAA,GAAW,IAAI,QAAA,IAAY,CAAA;AACjC,EAAA,MAAM,SAAA,GAAY,IAAI,SAAA,IAAa,CAAA;AACnC,EAAA,MAAM,SAAA,GAAY,IAAI,SAAA,IAAa,GAAA;AACnC,EAAA,MAAM,sBAAA,GAAyB,IAAI,sBAAA,IAA0B,KAAA;AAE7D,EAAA,MAAM,YAAA,GAAe,IAAI,GAAA,CAAI,EAAE,CAAA;AAC/B,EAAA,MAAM,YAAA,GAAe,IAAI,GAAA,CAAI,CAAC,UAAU,OAAA,EAAS,CAAA,GAAM,OAAA,EAAS,CAAC,CAAC,CAAA;AAClE,EAAA,MAAM,eAAe,IAAI,GAAA,CAAI,CAAC,CAAA,EAAG,CAAC,CAAC,CAAA;AACnC,EAAA,MAAM,EAAE,KAAK,UAAA,EAAW,GAAI,sBAAsB,MAAA,EAAQ,YAAA,EAAc,cAAc,YAAY,CAAA;AAClG,EAAA,MAAM,OAAA,GAAsC;AAAA,IACxC,QAAA,EAAU,OAAA;AAAA,IACV,KAAA,EAAO,IAAA;AAAA,IACP,uBAAA,EAAyB,sBAAA;AAAA,IACzB,UAAA,EAAY,SAAA;AAAA,IACZ,UAAA,EAAY;AAAA,GAChB;AAEA,EAAA,MAAM,EAAA,GAAsB;AAAA,IACxB,WAAA,EAAa,KAAA;AAAA,IACb,MAAA;AAAA,IACA,aAAA,EAAe,OAAO,aAAA,CAAc;AAAA,MAChC,IAAA,EAAM,EAAE,KAAA,EAAO,OAAA,EAAS,QAAQ,OAAA,EAAQ;AAAA,MACxC,MAAA,EAAQ,cAAA;AAAA,MACR,KAAA,EAAO,EAAA,CAAG,iBAAA,GAAoB,EAAA,CAAG;AAAA,KACpC,CAAA;AAAA,IACD,aAAA,EAAe,OAAO,aAAA,CAAc;AAAA,MAChC,OAAA,EAAS,MAAA;AAAA,MACT,SAAA,EAAW,QAAA;AAAA,MACX,SAAA,EAAW;AAAA,KACd,CAAA;AAAA,IACD,YAAA;AAAA,IACA,YAAA;AAAA,IACA,YAAA;AAAA,IACA,gBAAA,EAAkB,qBAAA,CAAsB,MAAA,EAAQ,IAAA,EAAM,IAAM,OAAO,CAAA;AAAA,IACnE,UAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA,EAAU;AAAA,GACd;AACA,EAAA,EAAA,CAAG,kBAAA,GAAqB,yBAAA;AACxB,EAAA,EAAA,CAAG,sBAAA,GAAyB,CAACA,OAAAA,EAAQ,KAAA,EAAO,YAAA,KAAiB;AACzD,IAAA,MAAM,KAAA,GAAQ,yBAAyBA,OAAAA,EAAQ,KAAA,EAAO,IAAI,YAAA,EAAc,EAAA,CAAG,oBAAoB,IAAI,CAAA;AACnG,IAAA,EAAA,CAAG,gBAAA,GAAmB,KAAA;AACtB,IAAA,OAAO,KAAA;AAAA,EACX,CAAA;AACA,EAAA,EAAA,CAAG,gBAAA,GAAmB,CAACA,OAAAA,EAAQ,KAAA,KAAU;AACrC,IAAA,OAAO,kBAAA;AAAA,MAAmBA,OAAAA;AAAA,MAAQ,EAAA;AAAA,MAAI,KAAA;AAAA,MAAuB,CAAC,YAAA,EAAc,IAAA,EAAM,IAAA,EAAM,IAAA,KACpF,6BAAA,CAA8B,MAAA,EAAQ,YAAA,EAAc,SAAA,EAAW,SAAA,EAAW,IAAA,EAAM,IAAA,EAAM,IAAI;AAAA,KAC9F;AAAA,EACJ,CAAA;AACA,EAAA,OAAO,EAAA;AACX;;;;"}
|
|
@@ -50,6 +50,53 @@ function multiply4x4(a, b) {
|
|
|
50
50
|
}
|
|
51
51
|
return out;
|
|
52
52
|
}
|
|
53
|
+
function computeDirectionalLightMatrix(light, casterMeshes, orthoMinZ, orthoMaxZ, offX = 0, offY = 0, offZ = 0) {
|
|
54
|
+
const view = buildLightViewMatrix(light.direction.x, light.direction.y, light.direction.z, light.position.x - offX, light.position.y - offY, light.position.z - offZ);
|
|
55
|
+
let minX = Infinity;
|
|
56
|
+
let maxX = -Infinity;
|
|
57
|
+
let minY = Infinity;
|
|
58
|
+
let maxY = -Infinity;
|
|
59
|
+
for (const mesh of casterMeshes) {
|
|
60
|
+
const world = mesh.worldMatrix;
|
|
61
|
+
const boundMin = mesh.boundMin ?? [-0.5, -0.5, -0.5];
|
|
62
|
+
const boundMax = mesh.boundMax ?? [0.5, 0.5, 0.5];
|
|
63
|
+
for (let corner = 0; corner < 8; corner++) {
|
|
64
|
+
const localX = corner & 1 ? boundMax[0] : boundMin[0];
|
|
65
|
+
const localY = corner & 2 ? boundMax[1] : boundMin[1];
|
|
66
|
+
const localZ = corner & 4 ? boundMax[2] : boundMin[2];
|
|
67
|
+
const worldX = world[0] * localX + world[4] * localY + world[8] * localZ + world[12] - offX;
|
|
68
|
+
const worldY = world[1] * localX + world[5] * localY + world[9] * localZ + world[13] - offY;
|
|
69
|
+
const worldZ = world[2] * localX + world[6] * localY + world[10] * localZ + world[14] - offZ;
|
|
70
|
+
const viewX = view[0] * worldX + view[4] * worldY + view[8] * worldZ + view[12];
|
|
71
|
+
const viewY = view[1] * worldX + view[5] * worldY + view[9] * worldZ + view[13];
|
|
72
|
+
minX = Math.min(minX, viewX);
|
|
73
|
+
maxX = Math.max(maxX, viewX);
|
|
74
|
+
minY = Math.min(minY, viewY);
|
|
75
|
+
maxY = Math.max(maxY, viewY);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (!Number.isFinite(minX)) {
|
|
79
|
+
minX = -1;
|
|
80
|
+
maxX = 1;
|
|
81
|
+
minY = -1;
|
|
82
|
+
maxY = 1;
|
|
83
|
+
}
|
|
84
|
+
const padX = (maxX - minX) * 0.1;
|
|
85
|
+
const padY = (maxY - minY) * 0.1;
|
|
86
|
+
minX -= padX;
|
|
87
|
+
maxX += padX;
|
|
88
|
+
minY -= padY;
|
|
89
|
+
maxY += padY;
|
|
90
|
+
const projection = new F32(16);
|
|
91
|
+
projection[0] = 2 / (maxX - minX);
|
|
92
|
+
projection[5] = 2 / (maxY - minY);
|
|
93
|
+
projection[10] = 1 / (orthoMaxZ - orthoMinZ);
|
|
94
|
+
projection[12] = -(maxX + minX) / (maxX - minX);
|
|
95
|
+
projection[13] = -(maxY + minY) / (maxY - minY);
|
|
96
|
+
projection[14] = -orthoMinZ / (orthoMaxZ - orthoMinZ);
|
|
97
|
+
projection[15] = 1;
|
|
98
|
+
return { _view: view, _viewProj: multiply4x4(projection, view), _near: orthoMinZ, _far: orthoMaxZ };
|
|
99
|
+
}
|
|
53
100
|
function createShadowParamsUBO(engine, bias, depthScale) {
|
|
54
101
|
const data = new F32(8);
|
|
55
102
|
data[0] = bias;
|
|
@@ -123,5 +170,5 @@ function updateShadowCameraBase(camera, cameraVersion, near, far, view, viewProj
|
|
|
123
170
|
camera._shadowCameraVersion = cameraVersion;
|
|
124
171
|
}
|
|
125
172
|
|
|
126
|
-
export { buildLightViewMatrix, casterVersionSum, createShadowCamera, createShadowParamsUBO, createShadowRenderTarget, createSharedShadowUBO, multiply4x4, updateShadowCameraBase, writeShadowUboFields };
|
|
173
|
+
export { buildLightViewMatrix, casterVersionSum, computeDirectionalLightMatrix, createShadowCamera, createShadowParamsUBO, createShadowRenderTarget, createSharedShadowUBO, multiply4x4, updateShadowCameraBase, writeShadowUboFields };
|
|
127
174
|
//# sourceMappingURL=shadow-base.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shadow-base.js","sources":["../../../src/shadow/shadow-base.ts"],"sourcesContent":["/**\n * Shared shadow helpers used by ESM and PCF shadow generators/tasks.\n */\n\nimport { F32 } from \"../engine/typed-arrays.js\";\nimport type { Camera } from \"../camera/camera.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Mat4Storage } from \"../math/types.js\";\nimport type { RenderTarget } from \"../engine/render-target.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport { createUniformBuffer } from \"../resource/gpu-buffers.js\";\nimport type { ShadowGenerator } from \"./shadow-generator.js\";\nimport { packMat4IntoF32 } from \"../math/pack-mat4-into-f32.js\";\nimport { allocateMat4 } from \"../math/_matrix-allocator.js\";\n\n/** Write shadow generator state into a Float32Array(24) for UBO upload.\n * Layout: [lightMatrix(16), depthValues.x, depthValues.y, 0, 0, shadowsInfo(4)] */\nexport function writeShadowUboFields(out: Float32Array, sg: { _lightMatrix: Float32Array; _depthValues: Float32Array; _shadowsInfo: Float32Array }): void {\n packMat4IntoF32(out, sg._lightMatrix, 0);\n out[16] = sg._depthValues[0]!;\n out[17] = sg._depthValues[1]!;\n out[18] = 0;\n out[19] = 0;\n out[20] = sg._shadowsInfo[0]!;\n out[21] = sg._shadowsInfo[1]!;\n out[22] = sg._shadowsInfo[2]!;\n out[23] = sg._shadowsInfo[3]!;\n}\n\n/** Build a light-space view matrix (column-major 4x4) from direction + position.\n * Shared between directional and spot shadow generators. */\nexport function buildLightViewMatrix(dirX: number, dirY: number, dirZ: number, px: number, py: number, pz: number): Float32Array {\n const len = Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ) || 1;\n const fx = dirX / len;\n const fy = dirY / len;\n const fz = dirZ / len;\n\n let upX = 0,\n upY = 1,\n upZ = 0;\n if (Math.abs(fy) > 0.99) {\n upX = 0;\n upY = 0;\n upZ = 1;\n }\n // right = cross(up, forward)\n let rx = upY * fz - upZ * fy;\n let ry = upZ * fx - upX * fz;\n let rz = upX * fy - upY * fx;\n const rLen = Math.sqrt(rx * rx + ry * ry + rz * rz) || 1;\n rx /= rLen;\n ry /= rLen;\n rz /= rLen;\n\n // up = cross(forward, right)\n const ux = fy * rz - fz * ry;\n const uy = fz * rx - fx * rz;\n const uz = fx * ry - fy * rx;\n\n // Column-major view matrix (stores basis as rows of rotation, plus translation column)\n return new F32([rx, ux, fx, 0, ry, uy, fy, 0, rz, uz, fz, 0, -(rx * px + ry * py + rz * pz), -(ux * px + uy * py + uz * pz), -(fx * px + fy * py + fz * pz), 1]);\n}\n\n/** Multiply two column-major 4x4 matrices: out = a * b. */\nexport function multiply4x4(a: Float32Array, b: Float32Array): Float32Array {\n const out = new F32(16);\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n let sum = 0;\n for (let k = 0; k < 4; k++) {\n sum += a[row + k * 4]! * b[k + col * 4]!;\n }\n out[row + col * 4] = sum;\n }\n }\n return out;\n}\n\n/** Create the shared shadow-params UBO (32 bytes) holding bias/depthScale/depth-range fields. */\nexport function createShadowParamsUBO(engine: EngineContext, bias: number, depthScale: number): GPUBuffer {\n const data = new F32(8);\n data[0] = bias;\n data[2] = depthScale;\n data[4] = 0; // depthMinZ (WebGPU)\n data[5] = 1; // depthMinZ + depthMaxZ\n return createUniformBuffer(engine, data);\n}\n\n/** Create the eager shadow-map render target used by frame-graph shadow tasks. */\nexport function createShadowRenderTarget(sg: ShadowGenerator, colorTexture: GPUTexture | null = null, depthTexture: GPUTexture = sg._depthTexture): RenderTarget {\n const mapSize = sg._config._mapSize;\n return {\n _descriptor: {\n size: { width: mapSize, height: mapSize },\n format: colorTexture ? \"rgba16float\" : undefined,\n dFormat: \"depth32float\",\n _depthClearValue: 1,\n _depthCompare: \"less-equal\",\n samples: 1,\n },\n _colorTexture: colorTexture,\n _colorView: colorTexture?.createView() ?? null,\n _depthTexture: depthTexture,\n _depthView: depthTexture.createView(),\n _width: mapSize,\n _height: mapSize,\n _eager: true,\n // Borrowed: the depth map is the generator's shared shadow map (persists for the generator's\n // lifetime); per-task render-target disposal must NOT destroy it (it's reused after rebuilds).\n _ownsDepthTexture: false,\n };\n}\n\n/** Create the shared receiver-side shadow UBO (96 bytes), initialised from state. */\nexport function createSharedShadowUBO(\n engine: EngineContext,\n _lightMatrix: Float32Array,\n _depthValues: Float32Array,\n _shadowsInfo: Float32Array\n): { ubo: GPUBuffer; data: Float32Array } {\n const data = new F32(24);\n writeShadowUboFields(data, { _lightMatrix, _depthValues, _shadowsInfo });\n const ubo = createUniformBuffer(engine, data);\n return { ubo, data };\n}\n\n/** Sum caster transform versions plus non-transform geometry/count mutations. */\nexport function casterVersionSum(casterMeshes: readonly Mesh[]): number {\n let sum = 0;\n for (const mesh of casterMeshes) {\n // Bitwise coercion maps the absent optional version to zero without another branch.\n sum += mesh.worldMatrixVersion + ~~(mesh.thinInstances?._version as number);\n }\n return sum;\n}\n\n/** Create the light-owned camera facade used by shadow render tasks.\n * Caches are pre-allocated from the process-global allocator. */\nexport function createShadowCamera(sg: Pick<ShadowGenerator, \"_light\">): Camera {\n return {\n fov: 1,\n nearPlane: 1,\n farPlane: 1,\n children: [],\n _viewCache: allocateMat4() as unknown as Mat4Storage,\n _projCache: allocateMat4() as unknown as Mat4Storage,\n _vpCache: allocateMat4() as unknown as Mat4Storage,\n get worldMatrix() {\n return sg._light.worldMatrix;\n },\n get worldMatrixVersion() {\n const state = (this as Camera & { _shadowCameraVersion?: number })._shadowCameraVersion;\n return state ?? sg._light.worldMatrixVersion;\n },\n } as Camera;\n}\n\n/** Update the camera facade caches shared by all shadow task variants. */\nexport function updateShadowCameraBase(camera: Camera, cameraVersion: number, near: number, far: number, view: Float32Array, viewProj: Float32Array): void {\n camera.nearPlane = near;\n camera.farPlane = far;\n camera._viewCache = view;\n camera._viewVer = cameraVersion;\n camera._vpCache = viewProj;\n camera._vpVer = cameraVersion;\n camera._vpAspect = 1;\n (camera as Camera & { _shadowCameraVersion?: number })._shadowCameraVersion = cameraVersion;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shadow-base.js","sources":["../../../src/shadow/shadow-base.ts"],"sourcesContent":["/**\n * Shared shadow helpers used by ESM and PCF shadow generators/tasks.\n */\n\nimport { F32 } from \"../engine/typed-arrays.js\";\nimport type { Camera } from \"../camera/camera.js\";\nimport type { EngineContext } from \"../engine/engine.js\";\nimport type { Mat4Storage } from \"../math/types.js\";\nimport type { RenderTarget } from \"../engine/render-target.js\";\nimport type { DirectionalLight } from \"../light/directional-light.js\";\nimport type { Mesh } from \"../mesh/mesh.js\";\nimport { createUniformBuffer } from \"../resource/gpu-buffers.js\";\nimport type { ShadowGenerator } from \"./shadow-generator.js\";\nimport { packMat4IntoF32 } from \"../math/pack-mat4-into-f32.js\";\nimport { allocateMat4 } from \"../math/_matrix-allocator.js\";\n\n/** Write shadow generator state into a Float32Array(24) for UBO upload.\n * Layout: [lightMatrix(16), depthValues.x, depthValues.y, 0, 0, shadowsInfo(4)] */\nexport function writeShadowUboFields(out: Float32Array, sg: { _lightMatrix: Float32Array; _depthValues: Float32Array; _shadowsInfo: Float32Array }): void {\n packMat4IntoF32(out, sg._lightMatrix, 0);\n out[16] = sg._depthValues[0]!;\n out[17] = sg._depthValues[1]!;\n out[18] = 0;\n out[19] = 0;\n out[20] = sg._shadowsInfo[0]!;\n out[21] = sg._shadowsInfo[1]!;\n out[22] = sg._shadowsInfo[2]!;\n out[23] = sg._shadowsInfo[3]!;\n}\n\n/** Build a light-space view matrix (column-major 4x4) from direction + position.\n * Shared between directional and spot shadow generators. */\nexport function buildLightViewMatrix(dirX: number, dirY: number, dirZ: number, px: number, py: number, pz: number): Float32Array {\n const len = Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ) || 1;\n const fx = dirX / len;\n const fy = dirY / len;\n const fz = dirZ / len;\n\n let upX = 0,\n upY = 1,\n upZ = 0;\n if (Math.abs(fy) > 0.99) {\n upX = 0;\n upY = 0;\n upZ = 1;\n }\n // right = cross(up, forward)\n let rx = upY * fz - upZ * fy;\n let ry = upZ * fx - upX * fz;\n let rz = upX * fy - upY * fx;\n const rLen = Math.sqrt(rx * rx + ry * ry + rz * rz) || 1;\n rx /= rLen;\n ry /= rLen;\n rz /= rLen;\n\n // up = cross(forward, right)\n const ux = fy * rz - fz * ry;\n const uy = fz * rx - fx * rz;\n const uz = fx * ry - fy * rx;\n\n // Column-major view matrix (stores basis as rows of rotation, plus translation column)\n return new F32([rx, ux, fx, 0, ry, uy, fy, 0, rz, uz, fz, 0, -(rx * px + ry * py + rz * pz), -(ux * px + uy * py + uz * pz), -(fx * px + fy * py + fz * pz), 1]);\n}\n\n/** Multiply two column-major 4x4 matrices: out = a * b. */\nexport function multiply4x4(a: Float32Array, b: Float32Array): Float32Array {\n const out = new F32(16);\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n let sum = 0;\n for (let k = 0; k < 4; k++) {\n sum += a[row + k * 4]! * b[k + col * 4]!;\n }\n out[row + col * 4] = sum;\n }\n }\n return out;\n}\n\n/** Fit an orthographic directional-light projection to caster world-space bounds. */\nexport function computeDirectionalLightMatrix(\n light: DirectionalLight,\n casterMeshes: readonly Mesh[],\n orthoMinZ: number,\n orthoMaxZ: number,\n offX = 0,\n offY = 0,\n offZ = 0\n): { _view: Float32Array; _viewProj: Float32Array; _near: number; _far: number } {\n const view = buildLightViewMatrix(light.direction.x, light.direction.y, light.direction.z, light.position.x - offX, light.position.y - offY, light.position.z - offZ);\n let minX = Infinity;\n let maxX = -Infinity;\n let minY = Infinity;\n let maxY = -Infinity;\n for (const mesh of casterMeshes) {\n const world = mesh.worldMatrix;\n const boundMin = mesh.boundMin ?? [-0.5, -0.5, -0.5];\n const boundMax = mesh.boundMax ?? [0.5, 0.5, 0.5];\n for (let corner = 0; corner < 8; corner++) {\n const localX = corner & 1 ? boundMax[0] : boundMin[0];\n const localY = corner & 2 ? boundMax[1] : boundMin[1];\n const localZ = corner & 4 ? boundMax[2] : boundMin[2];\n const worldX = world[0]! * localX + world[4]! * localY + world[8]! * localZ + world[12]! - offX;\n const worldY = world[1]! * localX + world[5]! * localY + world[9]! * localZ + world[13]! - offY;\n const worldZ = world[2]! * localX + world[6]! * localY + world[10]! * localZ + world[14]! - offZ;\n const viewX = view[0]! * worldX + view[4]! * worldY + view[8]! * worldZ + view[12]!;\n const viewY = view[1]! * worldX + view[5]! * worldY + view[9]! * worldZ + view[13]!;\n minX = Math.min(minX, viewX);\n maxX = Math.max(maxX, viewX);\n minY = Math.min(minY, viewY);\n maxY = Math.max(maxY, viewY);\n }\n }\n if (!Number.isFinite(minX)) {\n minX = -1;\n maxX = 1;\n minY = -1;\n maxY = 1;\n }\n const padX = (maxX - minX) * 0.1;\n const padY = (maxY - minY) * 0.1;\n minX -= padX;\n maxX += padX;\n minY -= padY;\n maxY += padY;\n\n const projection = new F32(16);\n projection[0] = 2 / (maxX - minX);\n projection[5] = 2 / (maxY - minY);\n projection[10] = 1 / (orthoMaxZ - orthoMinZ);\n projection[12] = -(maxX + minX) / (maxX - minX);\n projection[13] = -(maxY + minY) / (maxY - minY);\n projection[14] = -orthoMinZ / (orthoMaxZ - orthoMinZ);\n projection[15] = 1;\n return { _view: view, _viewProj: multiply4x4(projection, view), _near: orthoMinZ, _far: orthoMaxZ };\n}\n\n/** Create the shared shadow-params UBO (32 bytes) holding bias/depthScale/depth-range fields. */\nexport function createShadowParamsUBO(engine: EngineContext, bias: number, depthScale: number): GPUBuffer {\n const data = new F32(8);\n data[0] = bias;\n data[2] = depthScale;\n data[4] = 0; // depthMinZ (WebGPU)\n data[5] = 1; // depthMinZ + depthMaxZ\n return createUniformBuffer(engine, data);\n}\n\n/** Create the eager shadow-map render target used by frame-graph shadow tasks. */\nexport function createShadowRenderTarget(sg: ShadowGenerator, colorTexture: GPUTexture | null = null, depthTexture: GPUTexture = sg._depthTexture): RenderTarget {\n const mapSize = sg._config._mapSize;\n return {\n _descriptor: {\n size: { width: mapSize, height: mapSize },\n format: colorTexture ? \"rgba16float\" : undefined,\n dFormat: \"depth32float\",\n _depthClearValue: 1,\n _depthCompare: \"less-equal\",\n samples: 1,\n },\n _colorTexture: colorTexture,\n _colorView: colorTexture?.createView() ?? null,\n _depthTexture: depthTexture,\n _depthView: depthTexture.createView(),\n _width: mapSize,\n _height: mapSize,\n _eager: true,\n // Borrowed: the depth map is the generator's shared shadow map (persists for the generator's\n // lifetime); per-task render-target disposal must NOT destroy it (it's reused after rebuilds).\n _ownsDepthTexture: false,\n };\n}\n\n/** Create the shared receiver-side shadow UBO (96 bytes), initialised from state. */\nexport function createSharedShadowUBO(\n engine: EngineContext,\n _lightMatrix: Float32Array,\n _depthValues: Float32Array,\n _shadowsInfo: Float32Array\n): { ubo: GPUBuffer; data: Float32Array } {\n const data = new F32(24);\n writeShadowUboFields(data, { _lightMatrix, _depthValues, _shadowsInfo });\n const ubo = createUniformBuffer(engine, data);\n return { ubo, data };\n}\n\n/** Sum caster transform versions plus non-transform geometry/count mutations. */\nexport function casterVersionSum(casterMeshes: readonly Mesh[]): number {\n let sum = 0;\n for (const mesh of casterMeshes) {\n // Bitwise coercion maps the absent optional version to zero without another branch.\n sum += mesh.worldMatrixVersion + ~~(mesh.thinInstances?._version as number);\n }\n return sum;\n}\n\n/** Create the light-owned camera facade used by shadow render tasks.\n * Caches are pre-allocated from the process-global allocator. */\nexport function createShadowCamera(sg: Pick<ShadowGenerator, \"_light\">): Camera {\n return {\n fov: 1,\n nearPlane: 1,\n farPlane: 1,\n children: [],\n _viewCache: allocateMat4() as unknown as Mat4Storage,\n _projCache: allocateMat4() as unknown as Mat4Storage,\n _vpCache: allocateMat4() as unknown as Mat4Storage,\n get worldMatrix() {\n return sg._light.worldMatrix;\n },\n get worldMatrixVersion() {\n const state = (this as Camera & { _shadowCameraVersion?: number })._shadowCameraVersion;\n return state ?? sg._light.worldMatrixVersion;\n },\n } as Camera;\n}\n\n/** Update the camera facade caches shared by all shadow task variants. */\nexport function updateShadowCameraBase(camera: Camera, cameraVersion: number, near: number, far: number, view: Float32Array, viewProj: Float32Array): void {\n camera.nearPlane = near;\n camera.farPlane = far;\n camera._viewCache = view;\n camera._viewVer = cameraVersion;\n camera._vpCache = viewProj;\n camera._vpVer = cameraVersion;\n camera._vpAspect = 1;\n (camera as Camera & { _shadowCameraVersion?: number })._shadowCameraVersion = cameraVersion;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { ObservableVec3 } from '../math/observable-vec3.js';
|
|
2
2
|
import { ObservableQuat } from '../math/observable-quat.js';
|
|
3
|
-
import { createWorldMatrixState } from '../scene/world-matrix-state.js';
|
|
3
|
+
import { createWorldMatrixState, composeTrsLocalMatrix } from '../scene/world-matrix-state.js';
|
|
4
4
|
import { createEulerProxy } from '../scene/scene-node.js';
|
|
5
|
-
import { mat4Compose } from '../math/mat4-compose.js';
|
|
6
|
-
import { mat4Identity } from '../math/mat4-identity.js';
|
|
7
5
|
import { createEmptyUniformBuffer } from '../resource/gpu-buffers.js';
|
|
8
6
|
import { addDeferredSceneRenderables } from '../scene/scene-core.js';
|
|
9
7
|
import { mat4MultiplyInto } from '../math/mat4-multiply-into.js';
|
|
@@ -22,13 +20,7 @@ function createTextRenderable(data, options) {
|
|
|
22
20
|
const rq = options?.rotationQuaternion;
|
|
23
21
|
const sc = options?.scaling;
|
|
24
22
|
const initRq = rq ?? { x: 0, y: 0, z: 0, w: 1 };
|
|
25
|
-
const wm = createWorldMatrixState(() =>
|
|
26
|
-
const p = r.position;
|
|
27
|
-
const q = r.rotationQuaternion;
|
|
28
|
-
const s = r.scaling;
|
|
29
|
-
const isIdentity = p.x === 0 && p.y === 0 && p.z === 0 && q.x === 0 && q.y === 0 && q.z === 0 && q.w === 1 && s.x === 1 && s.y === 1 && s.z === 1;
|
|
30
|
-
return isIdentity ? mat4Identity() : mat4Compose(p.x, p.y, p.z, q.x, q.y, q.z, q.w, s.x, s.y, s.z);
|
|
31
|
-
});
|
|
23
|
+
const wm = createWorldMatrixState(() => composeTrsLocalMatrix(r.position, r.rotationQuaternion, r.scaling));
|
|
32
24
|
const markDirty = () => {
|
|
33
25
|
r._wmDirty = true;
|
|
34
26
|
wm.markLocalDirty();
|